NDC goes crazy

Hey,

I’m having 3 graphics (.png), representing Glyphs (0, 1, 2). They are rendered in the upper left corner among each other and it does work.
(In the code I can write any text with these 3 glyphs and it will be displayed on the screen. That works as well. I can specify any text position as well in Pixel or NDC (doesn’t matter). That works.)

But for some reason the text position randomly changes a bit, so that the displayed text moves a bit to the top. See the two images please. One shows 0, 1, 2 at the right position. The other shows that the 0 disappears. Text length in any direction doesn’t matter. When ever the bug appears, it’ll change the position and the text is moved more to the top.

Normal
Bug

It made me think of a classic typecast error during calculation, but everything seems fine. As you can see in the console output:

set: -1.000000 , 1.000000

calc: -1.000000 , 0.979492

position: -0.992188 , 0.979492

Mat: 1.000000 0.000000 0.000000 0.000000
0.000000 1.000000 0.000000 0.000000
0.000000 0.000000 1.000000 0.000000
-0.992188 0.979492 0.000000 1.000000

position: -0.992188 , 0.938477

Mat: 1.000000 0.000000 0.000000 0.000000
0.000000 1.000000 0.000000 0.000000
0.000000 0.000000 1.000000 0.000000
-0.992188 0.938477 0.000000 1.000000

position: -0.991406 , 0.897461

Mat: 1.000000 0.000000 0.000000 0.000000
0.000000 1.000000 0.000000 0.000000
0.000000 0.000000 1.000000 0.000000
-0.991406 0.897461 0.000000 1.000000

set: that’s the users’ NDC position of the text
calc: that’s the internal NDC position of the text
position: the current position of the glyph, based on the text
Mat: the matrix of that current glyph for rendering

All these values stay the same for each frame (I checked that). And they also stay the same, wether the bug does appear or not, which doesn’t make any sense at all. Any ideas?

The important code beneath (in ordner of function call):

Setting text position once:


int CApp::text_set_pos(int Obj_ID, float x, float y)
{
  int exit_code = ERR_EN_NO_ERROR;
  Text_Obj * pObj = this->text_get_obj(Obj_ID);

  if(pObj != NULL)
  {
    pObj->pos_x = math_convert_x_to_ndc(x, this->dycon_get_screen_width());
    pObj->pos_y = math_convert_y_to_ndc(y, this->dycon_get_screen_height());
  }
  else
    {exit_code = ERR_EN_TEXT_NOEXIST;}

  return exit_code;
}

Drawing the text:


int CApp::mdl2d_draw_text(int Obj_ID, int Text_ID)
{
  int exit_code = ERR_EN_NO_ERROR;
  Obj_2D * pObj = this->mdl2d_get_obj(Obj_ID);
  Elem_2D * pGlyph = NULL;
  Text_Obj * pText_Obj = this->text_get_obj(Text_ID);
  Text_Elem * pCurrent = NULL;
  float x = 0.0f;
  float y = 0.0f;

  if(pObj != NULL)
  {
    if(pText_Obj != NULL)
    {
      x = pText_Obj->pos_x;
      y = pText_Obj->pos_y;
      y -= (pText_Obj->row_h / 2.0f);
      pCurrent = pText_Obj->pElem_Head->pRight;

      while(pCurrent != pText_Obj->pElem_Head)
      {
        if(pCurrent->letter == '
')
        {
          y -= pText_Obj->row_h;
          x = pText_Obj->pos_x;
          pCurrent = pCurrent->pRight;
        }
        else
        {
          pGlyph = this->mdl2d_get_elem(pObj, pCurrent->letter);
          x += pGlyph->x_half;
          pGlyph->pModel->set_position(x, y);
          pGlyph->pModel->draw(this->pShader_Loc);
          x += pGlyph->x_half;
          pCurrent = pCurrent->pRight;
        }
      }
    }
    else
      {exit_code = ERR_EN_TEXT_NOEXIST;}
  }
  else
    {exit_code = ERR_EN_OBJ2D_NOEXIST;}

  return exit_code;
}

set_position:


void CModel_2D::set_position(float x, float y)
{
  this->mdl_mat = glm::translate(glm::mat4(1.0f), glm::vec3(x, y, 0.0f));
}

draw:


int CModel_2D::draw(int * pShader_Loc)
{
  int exit_code = ERR_EN_NO_ERROR;

  // VAO aufrufen

  glBindVertexArray(this->VAO);

  if(glGetError() != GL_NO_ERROR)
    {exit_code = ERR_EN_MDL_BIND_VAO;}

  // Model Matrix aktualisieren

  if(exit_code == ERR_EN_NO_ERROR)
  {		
    glUniformMatrix4fv(pShader_Loc[SHADER_LOC_MDL2D_MODEL], 1, GL_FALSE, &(this->mdl_mat[0][0]));

    if(glGetError() != GL_NO_ERROR)
      {exit_code = ERR_EN_MAT4F;}
  }

  // Alphakanal aktualisieren

  if(exit_code == ERR_EN_NO_ERROR)
  {		
    glUniform1f(pShader_Loc[SHADER_LOC_MDL2D_A_VAL], this->alpha);

    if(glGetError() != GL_NO_ERROR)
      {exit_code = ERR_EN_1F;}
  }

  // Mixfarbe aktualisieren

  if(exit_code == ERR_EN_NO_ERROR)
  {		
    glUniform4fv(pShader_Loc[SHADER_LOC_MDL2D_MIX_COLOR], 1, glm::value_ptr(this->mix_color));

    if(glGetError() != GL_NO_ERROR)
      {exit_code = ERR_EN_1F;}
  }

  // Textur binden

  if(exit_code == ERR_EN_NO_ERROR)
  {
    glActiveTexture(GL_TEXTURE0);
		
    if(glGetError() == GL_NO_ERROR)
    {
      glBindTexture(GL_TEXTURE_2D, this->current_texture);

      if(glGetError() != GL_NO_ERROR)
        {exit_code = ERR_EN_BIND_TEXTURE;}
    }
    else
      {exit_code = ERR_EN_ACTIVE_TEX;}
  }

  // Model zeichnen

  if(exit_code == ERR_EN_NO_ERROR)
  {
    glDrawArrays(this->draw_mode, 0, this->number_vertexes);

    if(glGetError() != GL_NO_ERROR)
      {exit_code = ERR_EN_DRAW_ARR;}
  }

  // VAO entbinden

  if(exit_code == ERR_EN_NO_ERROR)
  {
    glBindVertexArray(0);

    if(glGetError() != GL_NO_ERROR)
      {exit_code = ERR_EN_MDL_BIND_VAO;}
  }

  // Textur entbinden

  if(exit_code == ERR_EN_NO_ERROR)
  {
    glBindTexture(GL_TEXTURE_2D, 0);

    if(glGetError() != GL_NO_ERROR)
      {exit_code = ERR_EN_BIND_TEXTURE;}
  }

  return exit_code;
}

Any idea? Tryin’ to solve this for weeks now, while coding the other stuff.

i had also some problems with text rendering using a texture atlas a while ago …
in my case i’ve figured out that uploading the text position in NDC floating-point numbers (x, y) did cause precision errors
so i decided to use pixel coordinates for text position (as described here: Tutorial 11 : 2D text)
but only “internally”, that means i’m still submitting text entries in NDC, but before rendering, i convert them into pixel coords, and write those in the vertex buffer object, and in the vertex shader i convert them back into NDC:


#version 450


// vertex attributes
layout (location = 0) in vec2 VertexPosition;
layout (location = 1) in vec2 VertexTextureCoords;


// constant: through the whole draw call
uniform vec2 DisplaySize = vec2(1200, 900);
uniform vec2 TextureSize = vec2(2048, 2048);


// output: passed to fragment shader
out vec2 TextureCoords;


void main(void)
{
	// vertex position
	gl_Position = vec4(-1 + 2 * VertexPosition.x / DisplaySize.x, -1 + 2 * VertexPosition.y / DisplaySize.y, 0.0, 1.0);

	// pass variables to fragment shader
    TextureCoords = vec2(VertexTextureCoords.x / TextureSize.x, VertexTextureCoords.y / TextureSize.y);
}


Thanks.
I will try that. 'though I didn’t recognize any precision errors in datatype operations.