Текст не отображается при использовании egl (opengl) и freetype2 для отображения текста на экране - PullRequest
0 голосов
/ 17 октября 2018

Я написал приложение, которое запускается на встроенном устройстве, но все, что я вижу на дисплее, это область поверхности, заполненная цветом, как указано мной в glViewPort.

Текст не отображается.

У меня есть распечатки glError, чтобы увидеть, не произошел ли какой-то вызов API gl, но ничего не происходит.

У меня также нет ошибки библиотеки FT.

Хотя мои распечатки показывают face-> glyph-> bitmap.width face-> glyph-> bitmap_left как ноль для любого символа, который я загружаю.

// ******** CODE BELOW ******//

   int OpenGlInit()
{

    /* Here is the Init code for embedded graphics
       This works fine.*/

    glViewport(0, 0, 800, 600);
    PrintGlError();

    char vShaderStr[] =
    "attribute vec4 vertex;\n"
    "varying vec2 TexCoords;\n"
    "uniform vec4 projection;\n"
    "void main()\n"
    "{\n"
    "gl_Position = projection * vec4(vertex.xy, 0, 1);\n"
    "TexCoords = vertex.zw;\n"
    "}\n";

    char fShaderStr[]=
    "varying vec2 TexCoords;\n"
    "uniform sampler2D text;\n"
    "uniform vec4 color;\n"
    "void main(void) {\n"
    "gl_FragColor = vec4(1, 1, 1, texture2D(text, TexCoords).r) * color;\n"
    "}\n";

    GLuint vertexShader;
    GLuint fragmentShader;
    GLint linked;
    vertexShader = LoadShader(GL_VERTEX_SHADER, vShaderStr);
    fragmentShader = LoadShader(GL_FRAGMENT_SHADER, fShaderStr);

    ProgramObject = glCreateProgram();
    PrintGlError();

    if (ProgramObject == 0) {
       printf("DEBUG- glCreateProgram() returned 0\n");
       return 0;
    }
    glAttachShader( ProgramObject, vertexShader );
    PrintGlError();
    glAttachShader( ProgramObject, fragmentShader );
    PrintGlError();
    glLinkProgram( ProgramObject );
    PrintGlError();
    glGetProgramiv( ProgramObject, GL_LINK_STATUS, &linked );
    PrintGlError();

    if (!linked)
    {
        printf("failed to link program\n");
        GLint infoLen = 0;
        glGetProgramiv( ProgramObject, GL_INFO_LOG_LENGTH, &infoLen);
        PrintGlError();
        if (infoLen > 1)
        {
            char infoLog[infoLen];
            glGetProgramInfoLog( ProgramObject, infoLen, NULL, infoLog );
            PrintGlError();
            printf("Error linking program:\n%s\n", infoLog);
        }

        glDeleteProgram( ProgramObject );
        PrintGlError();
        return GL_FALSE;
    }
    printf("\nAfter Linked ProgramObject and compiled shaders");

     printf("\nBefore Gen Buffers");
     glGenBuffers(1, &VBO);
     PrintGlError();
     printf("\nAfter Gen Buffers");

    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    PrintGlError();
    glClear(GL_COLOR_BUFFER_BIT);
    PrintGlError();
    glEnable(GL_BLEND);
    PrintGlError();
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    PrintGlError();


    if(glGetUniformLocation(ProgramObject, "color") == -1)
      printf("\n ERROR uniform color is -1"); 
    GLfloat black[4] = {1, 0, 0, 1};
    glUniform4fv(glGetUniformLocation(ProgramObject, "color"), 1, black);
    PrintGlError();
    printf("\nAfter Matrix4fv");

    float sx = 2.0 / 800;
    float sy = 2.0 / 600;
    RenderText("This is sample text", -1 + 8 * sx,   1 - 50 * sy, sx, sy);
    printf("DEBUG\n\n\n\n\n\n\n\n\n\n\n");
    RenderText("(C) LearnOpenGL.com", -1 + 8.5 * sx, 1 - 100.5 * sy, sx, sy);
    eglSwapBuffers(egldisplay, eglsurface);
    PrintGlError();
    sleep(30);
    glDeleteProgram(ProgramObject);
}

void RenderText(std::string message, GLfloat x, GLfloat y, GLfloat sx, GLfloat sy)
{
    FT_Library ft;
    FT_Face face;

    if(FT_Init_FreeType(&ft))
        std::cout << "ERROR::FREETYPE: Could not init FreeType Library" << std::endl;
    if(FT_New_Face(ft, "/usr/share/fonts/tt7268mi_.ttf", 0, &face))
        std::cout << "ERROR::FREETYPE: Failed to load calibri display" << std::endl;
    if(FT_Set_Char_Size(face, 0, 16*64, 300, 300))
       std::cout << "ERROR::FREETYPE: Failed to set char size" << std::endl;
    printf("\nDEBUG after freetype\n");
    if(FT_Set_Pixel_Sizes(face, 0, 48))
       std::cout << "ERROR::FREETYPE: Failed to set pixel size" << std::endl;
    printf("DEBUG after pixel sizes\n");

    glActiveTexture(GL_TEXTURE0);
    PrintGlError(); 
    GLuint text;
    glGenTextures(1, &text);
    PrintGlError();
    glBindTexture(GL_TEXTURE_2D, text);
    PrintGlError();
    if (glGetUniformLocation(ProgramObject, "text") == -1)
      printf("\n ERROR uniform text is -1");
    glUniform1i(glGetUniformLocation(ProgramObject, "text"), 0);
    PrintGlError();

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    PrintGlError();

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    PrintGlError();
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    PrintGlError();
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    PrintGlError();
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    PrintGlError();

    int vPosition = glGetAttribLocation(ProgramObject, "vertex");
    if (vPosition == -1)
      printf("\nERROR vPosition is -1");
    PrintGlError();
    glEnableVertexAttribArray(vPosition);
    PrintGlError();
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    PrintGlError();
    //glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 6 * 4, NULL, GL_DYNAMIC_DRAW);
    glVertexAttribPointer(vPosition, 4, GL_FLOAT, GL_FALSE, 0, 0);
    PrintGlError();

    std::string::const_iterator ch;
    for (ch = message.begin(); ch != message.end(); ch++) 
    {
        const char c = *ch;
    if (FT_Load_Char(face, c, FT_LOAD_RENDER))
        {
            std::cout << "ERROR::FREETYTPE: Failed to load Glyph" << std::endl;
            continue;
        }
    FT_UInt glyph_index = FT_Get_Char_Index(face, c);
    printf("\nglyphindex is: %u",glyph_index);
    FT_Load_Glyph(face, glyph_index, FT_LOAD_RENDER);

        printf("\nChar: %c, facewidth:%f, faceheight:%f", c, (face->glyph->bitmap.width), (face->glyph->bitmap.rows));
        printf("\nfaceleft:%f, facetop:%f ", (face->glyph->bitmap_left), (face->glyph->bitmap_top));
        glTexImage2D(
            GL_TEXTURE_2D,
            0,
            GL_RGBA,
            face->glyph->bitmap.width,
            face->glyph->bitmap.rows,
            0,
            GL_RGBA,
            GL_UNSIGNED_BYTE,
            face->glyph->bitmap.buffer
        );
        PrintGlError();

        GLfloat xpos = x + (face->glyph->bitmap_left) * sx;
        GLfloat ypos = -y - (face->glyph->bitmap_top) * sy;
        GLfloat w = (face->glyph->bitmap.width) * sx;
        GLfloat h = (face->glyph->bitmap.rows) * sy;

        printf("\n xpos:%f ypos:%f w:%f h:%f", xpos, ypos, w, h);
        /*GLfloat vertices[6][4] = {
            { xpos,     ypos + h,   0.0, 0.0 },            
            { xpos,     ypos,       0.0, 1.0 },
            { xpos + w, ypos,       1.0, 1.0 },

            { xpos,     ypos + h,   0.0, 0.0 },
            { xpos + w, ypos,       1.0, 1.0 },
            { xpos + w, ypos + h,   1.0, 0.0 }           
        };*/
        point vertices[4] = {
        {xpos,     -ypos    , 0, 0},
        {xpos + w, -ypos    , 1, 0},
        {xpos,     -ypos - h, 0, 1},
        {xpos + w, -ypos - h, 1, 1},
        };

        glBufferData(GL_ARRAY_BUFFER, sizeof vertices, vertices, GL_DYNAMIC_DRAW);
        PrintGlError();
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
        PrintGlError();
        x += (face->glyph->advance.x/64) * sx;
        y += (face->glyph->advance.y/64) * sy;
    }
    glDeleteTextures(1, &text);
    glDisableVertexAttribArray(vPosition);
    FT_Done_Face(face);
    FT_Done_FreeType(ft);
}

void PrintGlError()
{
    GLenum ErrorCheckValue = glGetError();
    if (ErrorCheckValue != GL_NO_ERROR)
    {
       fprintf(stderr,"\nGL ERROR:%d", ErrorCheckValue);
    }
}

GLuint LoadShader(GLenum type, const char *shaderSrc)
{
    GLuint shader;
    GLint compiled;
    shader = glCreateShader( type );
    if (shader == 0) {
        return 0;
    }
    glShaderSource( shader, 1, &shaderSrc, NULL);
    PrintGlError();
    glCompileShader(shader);
    PrintGlError();
    glGetShaderiv( shader, GL_COMPILE_STATUS, &compiled);
    PrintGlError();
    if (!compiled)
    {
        printf("failed to compile shader\n");
        GLint infoLen = 0;
        glGetShaderiv(shader,GL_INFO_LOG_LENGTH, &infoLen);
        PrintGlError();
        if (infoLen > 1) {
            char infoLog[infoLen];
            glGetProgramInfoLog( ProgramObject, infoLen, NULL, infoLog );
            PrintGlError();
            printf("Error compiling shader:\n%s\n", infoLog);
        }
        glDeleteShader(shader);
        PrintGlError();
        return 0;
    }
    return shader;
}

1 Ответ

0 голосов
/ 17 октября 2018

В вашей программе есть некоторые проблемы.

Растровое изображение, генерируемое FT_Load_Glyph, имеет только один цветной канал.Это означает, что седьмой параметр glTexImage2D должен быть GL_RED, когда вы определяете текстуру изображения:

glTexImage2D(
    GL_TEXTURE_2D,
    0,
    GL_RGBA,
    face->glyph->bitmap.width,
    face->glyph->bitmap.rows,
    0,
    GL_RED, // <--------------- GL_RED instead of GL_RGBA
    GL_UNSIGNED_BYTE,
    face->glyph->bitmap.buffer
);

Вы пропустили установку программного объекта шейдера как частитекущего состояния рендеринга на glUseProgram.Это необходимо сделать после связывания программы ([glLinkProgram]) (https://www.khronos.org/registry/OpenGL-Refpages/es3.0/html/glLinkProgram.xhtml) и до указания любого значения униформы (glUniform*):

glLinkProgram( ProgramObject );

GLint color_location = glGetUniformLocation(ProgramObject, "color");

....

glUseProgram( ProgramObject );

GLfloat black[4] = {1, 0, 0, 1};
glUniform4fv(color_location, 1, black);

тип данных GLSL матрицы проекции должен быть mat4. Обратите внимание, умножение 2 переменных типа vec4 приведет к умножению по компонентам на все компоненты вектора. См. GLSL Программирование / Векторные и Матричные Операции .
Но так как вы инициализировали координаты вершины в нормализованном пространстве устройства, вам не нужна проекция:

attribute vec4 vertex;

varying vec2 TexCoords;

void main()
{
    gl_Position = vec4(vertex.xy, 0, 1);
    TexCoords   = vertex.zw;
}

Предварительный просмотр:


Но я использую библиотеку gl2 и (gl2.h) не определил GL_RED.

Так как GL_REDне поддерживается в OpenGL ES 2.0, вы должны сделать обходной путь. GL_ALPHA поддерживается в OpneGL ES 2.0, см. glTexImage2D.

Используйте спецификатор формата GL_ALPHA:

glTexImage2D(
    GL_TEXTURE_2D, 0, GL_RGBA,
    face->glyph->bitmap.width, face->glyph->bitmap.rows, 0,
    GL_ALPHA,
    GL_UNSIGNED_BYTE,
    face->glyph->bitmap.buffer
);

И читать альфа-канал из компонента a при поиске текстуры во фрагменте shader:

float alpha = texture2D(text, TexCoords).a;
gl_FragColor = vec4(1.0, 1.0, 1.0, alpha) * color; 
...