0
\$\begingroup\$

So I'm trying to render 2D text in my Game Engine using programmable pipeline.

Normally I'm using perspective projection matrix but for UI elements I'm trying to create orthographic projection matrix with near plane -1 and far plane 1.

I was using deprecated solution before with gluOrtho2D and it was something like this:

        SDL_Color color = { (U8)textsToRender.at(i)->color->r, (U8)textsToRender.at(i)->color->g, (U8)textsToRender.at(i)->color->b };

        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();

        gluOrtho2D(0, Window::getWidth(), Window::getHeight(), 0);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();

        glDisable(GL_DEPTH_TEST);
        glEnable(GL_TEXTURE_2D);
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

        GLuint texture;
        glGenTextures(1, &texture);
        glBindTexture(GL_TEXTURE_2D, texture);

        TTF_Font *m_font = TTF_OpenFont(textsToRender.at(i)->file->getPath().c_str(), textsToRender.at(i)->size);

        if(!m_font && isGameRunning() == true) Error::throwError((char*) "Cannot load font file!");

            SDL_Surface *sFont = TTF_RenderText_Blended(m_font, textsToRender.at(i)->msg.c_str(), color);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, sFont->w, sFont->h, 0, GL_BGRA, GL_UNSIGNED_BYTE, sFont->pixels);


 glBegin(GL_QUADS);
                {
                    glTexCoord2f(0.0f, 0.0f); glVertex2f(textsToRender.at(i)->pos->x, textsToRender.at(i)->pos->y);
                    glTexCoord2f(1.0f, 0.0f); glVertex2f(textsToRender.at(i)->pos->x + sFont->w, textsToRender.at(i)->pos->y);
                    glTexCoord2f(1.0f, 1.0f); glVertex2f(textsToRender.at(i)->pos->x + sFont->w, textsToRender.at(i)->pos->y + sFont->h);
                    glTexCoord2f(0.0f, 1.0f); glVertex2f(textsToRender.at(i)->pos->x, textsToRender.at(i)->pos->y + sFont->h);
            }
            glEnd();

        glDisable(GL_BLEND);
        glDisable(GL_TEXTURE_2D);
        glEnable(GL_DEPTH_TEST);

        glMatrixMode(GL_PROJECTION);

        glDeleteTextures(1, &texture);
        TTF_CloseFont(m_font);
        SDL_FreeSurface(sFont);

And with this code everything is OK. I received really nice text, I could change size, even text color.

But because I'm creating my engine with programmable pipeline (GLSL shaders) solutions only I decided to create new shader program, 2 shader files and my own orthographic projection matrix "recipe".

Here is my code after changes:

        SDL_Color color = { (U8)textsToRender.at(i)->color->r, (U8)textsToRender.at(i)->color->g, (U8)textsToRender.at(i)->color->b };
        glDisable(GL_DEPTH_TEST);
        glEnable(GL_TEXTURE_2D);
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

        GLuint texture;
        glGenTextures(1, &texture);
        glBindTexture(GL_TEXTURE_2D, texture);

        TTF_Font *m_font = TTF_OpenFont(textsToRender.at(i)->file->getPath().c_str(), textsToRender.at(i)->size);

        if(!m_font && isGameRunning() == true) Error::throwError((char*) "Cannot load font file!");

        SDL_Surface *sFont = TTF_RenderText_Blended(m_font, textsToRender.at(i)->msg.c_str(), color);

        std::vector<F32> positions;

        positions.push_back(textsToRender.at(i)->pos->x);
        positions.push_back(textsToRender.at(i)->pos->y);
        positions.push_back(textsToRender.at(i)->pos->x + sFont->w);
        positions.push_back(textsToRender.at(i)->pos->y);
        positions.push_back(textsToRender.at(i)->pos->x + sFont->w);
        positions.push_back(textsToRender.at(i)->pos->y + sFont->h);
        positions.push_back(textsToRender.at(i)->pos->x);
        positions.push_back(textsToRender.at(i)->pos->y + sFont->h);

        std::vector<F32> textureVectors;

        textureVectors.push_back(0.0f);
        textureVectors.push_back(0.0f);
        textureVectors.push_back(1.0f);
        textureVectors.push_back(0.0f);
        textureVectors.push_back(1.0f);
        textureVectors.push_back(1.0f);
        textureVectors.push_back(0.0f);
        textureVectors.push_back(1.0f);

        U32 vaoID = VertexArrayObject::loadToVAO(positions, textureVectors);

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, sFont->w, sFont->h, 0, GL_BGRA, GL_UNSIGNED_BYTE, sFont->pixels);

        uiShader->start(); //

        uiShader->loadProjectionMatrix(projectionMatrixOrtho); //LOADS projection matrix to my shader program

        glBindVertexArray(vaoID);
        glEnableVertexAttribArray(0);
        glEnableVertexAttribArray(1);

        glActiveTexture(GL_TEXTURE0);

        glDrawArrays(GL_TRIANGLES, 0, 4);

        glDisableVertexAttribArray(0);
        glDisableVertexAttribArray(1);
        glBindVertexArray(0);

        uiShader->stop();

        glDisable(GL_BLEND);
        glDisable(GL_TEXTURE_2D);
        glEnable(GL_DEPTH_TEST);

        glMatrixMode(GL_PROJECTION);

        glDeleteTextures(1, &texture);
        TTF_CloseFont(m_font);
        SDL_FreeSurface(sFont);

Recipe for my orthographic matrix:

Matrix4 *projectionMatrix = new Matrix4();

F32 left = 0.0f;
F32 right = (F32) Window::getWidth();
F32 bottom = (F32) Window::getHeight();
F32 top = 0.0f;
F32 near = -1.0f;
F32 far = 1.0f;

F32 xO = 2.0f / (right - left);
F32 yO = 2.0f / (top - bottom);
F32 zO = -2.0f / (far - near);

F32 tx = -(right + left) / (right - left);
F32 ty = -(top + bottom) / (top - bottom);
F32 tz = -(far + near) / (far - near);

projectionMatrix->m00 = xO;
projectionMatrix->m10 = 0.0f;
projectionMatrix->m20 = 0.0f;
projectionMatrix->m30 = 0.0f;
projectionMatrix->m01 = 0.0f;
projectionMatrix->m11 = yO;
projectionMatrix->m21 = 0.0f;
projectionMatrix->m31 = 0.0f;
projectionMatrix->m02 = 0.0f;
projectionMatrix->m12 = 0.0f;
projectionMatrix->m22 = zO;
projectionMatrix->m32 = 0.0f;
projectionMatrix->m03 = tx;
projectionMatrix->m13 = ty;
projectionMatrix->m23 = tz;
projectionMatrix->m33 = 1.0f;

Vertex Shader:

#version 400 core

in vec2 position;
in vec2 textureVector;

out vec2 textureCoords;

uniform mat4 projectionMatrix;

void main(void)
{
  textureCoords = textureVector;
  gl_Position = projectionMatrix * vec4(position, 0.0, 1.0);
} 

And Fragment Shader:

#version 400 core

in vec2 textureCoords;

out vec4 out_Color;

uniform sampler2D sampler;

void main(void)
{
  out_Color = texture(sampler,textureCoords);
}

And what I receive on my screen instead of nice font like before is something like this:

enter image description here

I'm using GLEW, SDL2 with SDL2_image and SDL2_ttf.

Everything is OK with my VAO, shader program. I guess here is something wrong with my orthographic projection matrix, I checked my code 100 times and didn't found any mistake. Maybe wrong recipe?

\$\endgroup\$
  • 1
    \$\begingroup\$ Opengl has column major orderibg system, so when you put the tx to the m03 position, you put it in the first column's last row. Transpose it. \$\endgroup\$ – Bálint Feb 10 '16 at 7:52
  • 1
    \$\begingroup\$ @Bálint, don't forget to add this as an answer. :) \$\endgroup\$ – DMGregory Feb 10 '16 at 12:44
  • \$\begingroup\$ @DMGregory done. Good idea BTW. \$\endgroup\$ – Bálint Feb 10 '16 at 13:06
2
\$\begingroup\$

Opengl has column major orderibg system, so when you put the tx to the m03 position, you put it in the first column's last row. Transpose it.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.