Problem on displaying fonts in p5.js on some devices - mobile

Is have a strange issue thats driving me insane and cant figure out the problem
Im kinda new to p5js and have a little experience with processing java.
I’ve made a lyrics visualizer sketch for a friends song, with some syncro lyrics, in glitch.me.
The problem is that on certain mobile devices, I cant see the fonts.
I have no problem on desktop and on some devices the fonts are displayed correctly. But, on my phone (Samsung Galaxy A51) I cant see the text of the lyrics.
Im using Webgl (later on I use it to achieve some sort of feedback effect) and tried some ttf and otf without success.
What may I be missing?
I’ve made a Minimal, Reproducible Example of my error, just to see if it stills persists… but no luck yet…
Hope someone could find it clearer this way:
https://editor.p5js.org/lisandroperalta/sketches/CbwrpflKU
EDIT: Here´s the code
let buffer1, buffer2;
let miFuente;
function preload() {
miFuente = loadFont('./assets/qanoar.personal-use.otf');
}
function setup() {
createCanvas(windowWidth, windowHeight);
buffer1 = createGraphics(windowWidth, windowHeight, WEBGL);
buffer2 = createGraphics(windowWidth, windowHeight, WEBGL);
background(0);
}
function draw() {
buffer1.push();
buffer1.noStroke(0);
buffer1.translate(0, 0, 0);
buffer1.texture(buffer2); // meto la textura de salida en la entrada
buffer1.plane(windowWidth, windowHeight,100,100); // dibujo la textura de salida en la entrada
//buffer1.box(100);
buffer1.pop();
dibujarTextoPrueba();
//meto lo que hice en la imagen de salida para reusarla despues
buffer2.push();
buffer2.scale(1.005, 1.005); //hago transformaciones
buffer2.texture(buffer1); //meto la textura de salida
buffer2.plane(windowWidth, windowHeight,100,100); //dibujo la textura de salida
buffer2.pop();
image(buffer2, 0, 0, windowWidth, windowHeight);
}
function dibujarTextoPrueba() {
buffer1.push();
buffer1.textFont(miFuente);
buffer1.textSize(100);
buffer1.fill(255, 0, 0);
buffer1.noStroke();
buffer1.ellipse(0, 0, 200, 200);
buffer1.fill(255, 255, 255);
buffer1.textAlign(CENTER);
buffer1.text("Testing", 0, 0);
buffer1.pop();
}

Related

How to use FT_RENDER_MODE_SDF in freetype?

I'm quite new to font rendering and I'm trying to generate signed distance field with freetype so that it can be used in fragment shader in OpenGL. Here is the code that I tried:
error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
if (error)
{
// Handle error
}
error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_SDF);
if (error)
{
// Handle error
}
Maybe I completly misunderstand the idea of SDF, but my thought was that I could give freetype a ttf file and with FT_RENDER_MODE_SDF it should produce a buffer with signed distances. But FT_Render_Glyph returns an error (19) which happens to be "cannot render this glyph format".
SDF support was added at the end of 2020, with a new module in the second half of 2021, so make sure you have a more recent version than that. For example, 2.6 is older than 2.12.0 (the newest at the time of writing).
With that out of the way, let's get started.
I'm assuming you've completed the font rendering tutorial from LearnOpenGL and you can successfully render text on the screen. You should have something like this (notice the new additions):
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // Disable byte-alignment restriction
FT_GlyphSlot slot = face->glyph; // <-- This is new
for (unsigned char c = 0; c < 128; c++)
{
// Load character glyph
if (FT_Load_Char(face, c, FT_LOAD_RENDER))
{
// error message
continue;
}
FT_Render_Glyph(slot, FT_RENDER_MODE_SDF); // <-- And this is new
// Generate texture
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D( ... );
...
}
When rendering the text, you have to tell OpenGL not to write the fragments of the quads to the depth buffer, otherwise adjacent glyphs will overlap and start to flicker:
glDepthMask(GL_FALSE); // Don't write into the depth buffer
RenderText(pTextShader, text, 25.0f, 25.0f, 1.0f, glm::vec3(0.5, 0.8f, 0.2f));
glDepthMask(GL_TRUE); // Re-enable writing to the depth buffer
If you want to place the text as an object in your scene, in world-space, then in the vertex shader you can use:
gl_Position = uVp * uModel * vec4(vertex.xy, 0.0, 1.0); // uVp is "projection * view" on the CPU side
However, this is a bit outside the scope of your question. It just makes it easier to inspect the text from all angles by circling the camera around it. Make sure you run glDisable(GL_CULL_FACE) before drawing the glyphs, to disable backface culling, so they're visible from both sides.
As for the fragment shader I suggest you watch this video.
The bare minimum would be:
void main()
{
float glyphShape = texture(uGlyphTexture, TexCoords).r;
if (glyphShape < 0.5)
discard;
oFragColor = vec4(uTextColor, 1.0);
}
Result:
I think there's a pretty stark difference between them, wouldn't you say?
Have fun!

How do i get the actual position of vertices in OpenGL ES 2.0

After Applying a rotation or a translation matrix on the vertex array, the vertex buffer is not updated
So how can i get the position of vertices after applying the matrix?
here's the onDrawFrame() function
public void onDrawFrame(GL10 gl) {
PositionHandle = GLES20.glGetAttribLocation(Program,"vPosition");
MatrixHandle = GLES20.glGetUniformLocation(Program,"uMVPMatrix");
ColorHandle = GLES20.glGetUniformLocation(Program,"vColor");
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT|GLES20.GL_DEPTH_BUFFER_BIT );
Matrix.rotateM(RotationMatrix,0,-90f,1,0,0);
Matrix.multiplyMM(vPMatrix,0,projectionMatrix,0,viewMatrix,0);
Matrix.multiplyMM(vPMatrix,0,vPMatrix,0,RotationMatrix,0);
GLES20.glUniformMatrix4fv(MatrixHandle, 1, false, vPMatrix, 0);
GLES20.glUseProgram(Program);
GLES20.glEnableVertexAttribArray(PositionHandle);
GLES20.glVertexAttribPointer(PositionHandle,3,GLES20.GL_FLOAT,false,0,vertexbuffer);
GLES20.glUniform4fv(ColorHandle,1,color,1);
GLES20.glDrawArrays(GLES20.GL_TRIANGLES,0,6);
GLES20.glDisableVertexAttribArray(PositionHandle);
}
The GPU doesn't normally write back transformed results anywhere the application can use them. It's possible in ES 3.0 with transform feedback, BUT it's very expensive.
For touch event "hit" testing, you generally don't want to use the raw geometry. Generally use some simple proxy geometry, which can be transformed in software on the CPU.
Maybe you should try this:
private float[] modelViewMatrix = new float[16];
...
Matrix.rotateM(RotationMatrix, 0, -90f, 1, 0, 0);
Matrix.multiplyMM(modelViewMatrix, 0, viewMatrix, 0, RotationMatrix, 0);
Matrix.multiplyMM(vpMatrix, 0, projectionMatrix, 0, modelViewMatrix, 0);
You can use the vertex movement calculations in the CPU, and then use the GLU.gluProject() function to convert the coordinates of the vertex of the object in pixels of the screen. This data can be used when working with touch events.
private var view: IntArray = intArrayOf(0, 0, widthScreen, heightScreen)
...
GLU.gluProject(modelX, modelY, modelZ, mvMatrix, 0,
projectionMatrix, 0, view, 0,
coordinatesWindow, 0)
...
// coordinates in pixels of the screen
val x = coordinatesWindow[0]
val y = coordinatesWindow[1]

C programming ncurses colors on multiple windows not working

I'm working with ncurses on Linux, I have created two windows (winReception and winTransmission) basically winTransmission is for writing stuff to print in winReception. So, I'd like to print the text in winReception in certain color but it's not working it prints normally, no colors.
Any thoughts on why it's not working? I tried changing the colors of the window instead but it changes the color of all the text in the window, which is not what I want.
Edit: Forgot to mention that winTransmission do not need to change colors. Only winReception needs to change colors.
Here is the code you need to understand what I'm doing:
initscr();
/* WINDOW RECEPTION */
winReception = newwin(27, 0, 0, 0);
/* WINDOW TRANSMISSION */
winTransmission = newwin(8, 0, 27, 0);
if (!has_colors()) {
endwin();
fprintf(stderr, "Error - no color support on this terminal\n");
exit(1);
}
if (start_color() != OK) {
endwin();
fprintf(stderr, "Error - could not initialize colors\n");
exit(2);
}
init_pair(1, COLOR_RED, COLOR_BLACK);
init_pair(2, COLOR_RED, COLOR_GREEN);
attrset(COLOR_PAIR(1));
/* WINDOW RECEPTION */
mvwprintw(winReception, 1, 2, "%s", textinwindow);
wrefresh(winReception);
/* WINDOW TRANSMISSION */
touchwin(winTransmission);
wclear(winTransmission);
wrefresh(winTransmission);
The only place you are setting a color attribute is
attrset(COLOR_PAIR(1));
but that is applied only to stdscr
Perhaps you meant
wattrset(winReception, COLOR_PAIR(1));

X11 Why I can't draw any text?

I'm trying to learn X11. It's very hard to me, because I don't have experience with window applications on Linux.
I wrote some simple code and I can't resolve this not visible text problem.
Everything is working good probably, when I was trying to draw rectangle with DrawRectangle function it was working.
Here is the code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <X11/Xlib.h>
int main()
{
Display* myDisplay;
Window myWindow;
int myScreen;
GC myGC;
XEvent myEvent;
unsigned long black, white;
char* hello = "Hello world!";
XFontStruct* myFont;
if((myDisplay = XOpenDisplay(NULL)) == NULL)
{
puts("Error in conneting to X Server!");
return -1;
}
myScreen = DefaultScreen(myDisplay);
black = BlackPixel(myDisplay, myScreen);
white = WhitePixel(myDisplay, myScreen);
myWindow = XCreateSimpleWindow(myDisplay, RootWindow(myDisplay, myScreen), 0, 0, 640, 320, 5, black, white);
XSelectInput(myDisplay, myWindow, ExposureMask);
XClearWindow(myDisplay, myWindow);
XMapWindow(myDisplay, myWindow);
myGC = XCreateGC(myDisplay, myWindow, 0, 0);
XSetForeground(myDisplay, myGC, black);
XSetBackground(myDisplay, myGC, white);
myFont = XLoadQueryFont(myDisplay, "-Misc-Fixed-Medium-R-Normal--7-70-75-75-C-50-ISO10646-1");
XSetFont(myDisplay, myGC, myFont->fid);
while(1)
{
XNextEvent(myDisplay, &myEvent);
if(myEvent.type == Expose)
{
XClearWindow(myDisplay, myWindow);
// HERE I DONT KNOW WHY IT DOESNT WORK!
XDrawString(myDisplay, myWindow, myGC, 0, 0, hello, strlen(hello));
}
}
XFreeGC(myDisplay, myGC);
XDestroyWindow(myDisplay, myWindow);
XCloseDisplay(myDisplay);
return 0;
}
Thank you for help!
Your font path argument to XLoadQueryFont is wrong (on my Linux/Debian desktop). Check with the xlsfonts command the right ones (they are all lowercases).
With
myFont = XLoadQueryFont
(myDisplay,
"-misc-fixed-medium-r-normal--9-90-75-75-c-60-iso10646-1");
it could work better. Try also with "lucidasanstypewriter-bold-14"
And most importantly the coordinates passed to XDrawString are wrong. Remember that they are the coordinates of the baseline of your text. And x=0, y=0 is the top left corner of the window, and y is growing downwards and x is growing to the right. Hence your text is drawn off-window, above its top. So y should be positive and more than the font height.
Try
XDrawString (myDisplay, myWindow, myGC, 15, 20, hello,
strlen (hello));
As I commented, you need to handle a lot more events.
I don't have experience with window applications on Linux.
And to learn about GUI programming, I strongly recommend first using some toolkit like GTK or Qt or perhaps SDL.
Raw X11 programming is too hard (and by the time you'll learn it is will be obsolete, e.g. by Wayland), in particular because an X11 application needs to be ICCCM & EWMH compliant. Notice that the entire X11 documentation requires nearly ten thousand pages.
See also https://tronche.com/gui/x/xlib/
BTW, most Linux GUI applications are drawing pixmap client side and sending it to the X11 server. Read about compositing window managers. Drawing requests like XDrawString are no more used anymore in practice. Recent font related libraries like libfontconfig, libXft, etc are working on the client side.

SDL2 converting SDL1.2 code in C, how to scroll a Window, previously SDL_BlitSurface

I'm converting SDL 1.2 code to SDL 2 in C and I have encountered code that scrolls a Window (SDL 1.2 SDL_Surface named nanoglk_surface) of text to allow empty space for new lines at the bottom:
// Copy (scroll down).
SDL_Rect r1 = { win->area.x, win->area.y + d,
win->area.w, win->area.h - d };
SDL_Rect r2 = { win->area.x, win->area.y, win->area.w, win->area.h - d };
SDL_BlitSurface(nanoglk_surface, &r1, nanoglk_surface, &r2);
// Clear new, free area.
SDL_Rect r = { win->area.x, win->area.y + win->area.h - d,
win->area.w, d };
SDL_FillRect(nanoglk_surface, &r,
SDL_MapRGB(nanoglk_surface->format,
win->bg[win->cur_styl].r,
win->bg[win->cur_styl].g,
win->bg[win->cur_styl].b));
This is part of an open source C app, here: https://github.com/BroadcastGames/nanoglk/blob/master/nanoglk/wintextbuffer.c - the whole app compiles and runs fine on Ubuntu 16.04 or 16.10. But I'm attempting to update it to SDL 2.0 conventions.
The app has only a single window with associated renderer and texture. What would be the SDL 2.0 way of doing the SDL_BlitSurface? Thank you.
As for what #genpfault linked to in the comments:
/* ... */
SDL_BlitSurface(src, &src_rect, dst, &dst_rect);
/* ... */
Is the same as (SDL2):
/* ... */
// Create texture as late as possible to save resources:
SDL_Texture *src_texture = SDL_CreateTextureFromSurface(renderer_dst, src);
SDL_RenderCopy(renderer_dst, src_texture, &src_rect, &dst_rect);
// Destroy texture as soon as possible to save resources:
SDL_DestroyTexture(src_texture);
/* ... */
SDL_RenderPresent(render_dst);
Your blit will be hardware-accelerated.

Resources