3

I'll get straight to the point:

I have created a structure for my vertices:

struct Vertex3D
{
    Vector3D position;
    Vector2D textureCoordinate;
    Vector3D normal;
}

I then import a particular *.dae file and bind it to a OpenGL Vertex Buffer, which is constructed out of a list of Vertex3D structured vertices. All goes well, the mesh imports and is displayed, I can manipulate it with shaders, but I have a problem.

What I also do is load up and assign a texture to it. Aftewards I'm trying to display it in this manner:

glEnableVertexAttribArray(0);
glEnableVertexAttribArray(8);
glEnableVertexAttribArray(2);

glBindBuffer(GL_ARRAY_BUFFER, this->_entries[i].VB);
glVertexAttribPointer(0,3, GL_FLOAT, GL_FALSE, sizeof(RomCommon::Vertex3D), 0); // Vertices
glVertexAttribPointer(8,2, GL_FLOAT, GL_FALSE, sizeof(RomCommon::Vertex3D), (const GLvoid*)sizeof(RomCommon::Vector3D)); // Supposed texture position
glVertexAttribPointer(2,3, GL_FLOAT, GL_FALSE, sizeof(RomCommon::Vertex3D),  (const GLvoid*)(sizeof(RomCommon::Vector2D) + sizeof(RomCommon::Vector3D))); // Supposed normal position
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->_entries[i].IB);
glBindTexture(GL_TEXTURE_2D, 3);
glDrawElements(GL_TRIANGLES, this->_entries[i]._indexCount, GL_UNSIGNED_INT, 0);

glDisableVertexAttribArray(0);
glDisableVertexAttribArray(8);
glDisableVertexAttribArray(2);

My problem is that the texture is not displayed. Only the color from the texture's first pixel is assigned (in my case it's blue). I've used gDEBugger to debug the whole process, and I can tell that the VertexBuffer seems to be set up correctly, the image of the texture is loaded up correctly, yet it won't be displayed.

I have tried searching and trying out different aspects of debugging, this includes:

  • making sure glEnable(GL_TEXTURE_2D) is set up;
  • adding glEnable(GL_LIGHTING) and glDisable(GL_LIGHTING);
  • using glDisable(GL_DEPTH_TEST); glDisable(GL_BLEND); and glDisable(GL_SCISSOR_TEST); before binding the texture
  • fetching for errors
  • searching for strange messages
  • double checking the vertex buffer in the memory (literaly going through the elemnts and cross comparing what's in the *.dae file)

EDIT

I am using CG Shaders with this. Here is the Vertex Program:

struct vsOutput {


 float4 position : POSITION;
  float2 texCoord : TEXCOORD0;
  float3 color    : COLOR;
};

vsOutput VS_Main(      float4 position : POSITION,
                           float2 texCoord : TEXCOORD0,
                           float3 color    : COLOR,
                           uniform float4x4 ModelViewProj
                           )
{
  vsOutput OUT;

  OUT.position = mul(ModelViewProj, position);
  OUT.texCoord = texCoord;
  OUT.color = color;

  return OUT;   
}

And the Fragment Program:

struct fsOutput {
  float4 color : COLOR;
};

fsOutput FS_Main(
    float2 texCoord : TEXCOORD0,
    uniform sampler2D decal : TEX0
)
{ 
    fsOutput OUT;
    OUT.color = tex2D(decal,texCoord);
    return OUT;
}

I could add more details about my project if necessary, though from what I've traced, the problem seems to be somewhere in the rendering of the vertex buffers.

EDIT

I've also found that because I'm using CG, the vertexAttribPointers should be different (8 is for TEXCOORD0) so I changed the general description based on that.

SOLUTION EDIT

Many thanks to the few chaps in the comments who opened my mind to look at the problem from a different perspective and actually do some more reading. Here is the solution:

    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(8);
    glEnableVertexAttribArray(2);

    glBindBuffer(GL_ARRAY_BUFFER, this->_entries[i].VB);
    glVertexAttribPointer(0,3, GL_FLOAT, GL_FALSE, sizeof(RomCommon::Vertex3D), 0); // Vertices
    glVertexAttribPointer(8,2, GL_FLOAT, GL_FALSE, sizeof(RomCommon::Vertex3D), (const GLvoid*)sizeof(RomCommon::Vector3D)); // Supposed texture position
    glVertexAttribPointer(2,3, GL_FLOAT, GL_FALSE, sizeof(RomCommon::Vertex3D),  (const GLvoid*)(sizeof(RomCommon::Vector2D) + sizeof(RomCommon::Vector3D))); // Supposed normal position
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->_entries[i].IB);


/* Solution start */
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glTexCoordPointer(2, GL_FLOAT, sizeof(RomCommon::Vertex3D), (const GLvoid*)12);
        glBindTexture(GL_TEXTURE_2D, 3);
        glDrawElements(GL_TRIANGLES, this->_entries[i]._indexCount, GL_UNSIGNED_INT, 0);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
/* Solution end */


    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(8);
    glDisableVertexAttribArray(2);

My problem was that I was only passing texture coordinates to the shader, but did not push it to the OpenGL state machine (if that's a good expression). I think this has something to do with the fact that I am using CG shaders and not GLSL shaders, though I could be wrong. The code is loosely based on a few examples and explanations that I read, but they were all based on GLSL shaders and they were working, hence the dediction. Anyway, it is now resolved.

VoltairePunk
  • 275
  • 4
  • 13
  • 2
    I see no shaders. *That* might be the problem with rendering of vertex buffers. You specified vertex attributes (0, 1 and 2) but gave no meaning to them. And oh, you don't bind textures to VBOs; you bind them to texture units and access as `uniform sampler*` variables in GLSL. – Bartek Banachewicz Jan 29 '13 at 13:21
  • I have shaders, but did not specify them in the description (I can add both vertex and fragment shader functions if necessary). They are enabled before glEnableVertexAttribArray(0); and disabled after glDisableVertexAttribArray(2); I am also using CG Shaders, but they work in a similar way I presume. – VoltairePunk Jan 29 '13 at 13:28
  • Did you try to render UVs as color? – Bartek Banachewicz Jan 29 '13 at 13:43
  • Please forgive my ignorance, I am not that good at these things. How do you render UVs as color again? – VoltairePunk Jan 29 '13 at 13:46
  • 3
    @karmalis: Just assign the texture coordinate as output color. I'm also a bit unsure about how Cg does assign vertex attribute location so to VS_Main parameters. with GLSL you either have to use glGetAttributeLocation to retrieve the location index based on its name, or assign it explicitly in the layout. – datenwolf Jan 29 '13 at 13:49
  • Many thanks, I will try that. I will also probably try to use GLSL shaders just for testing as well and see the output. Then I will update the question with my findings. Thanks guys. – VoltairePunk Jan 29 '13 at 13:52
  • If I do try to output textcoord directly to color, what should I be seeing? – VoltairePunk Jan 29 '13 at 15:56
  • Depends on the actual code used to output them. – Bartek Banachewicz Jan 30 '13 at 10:21
  • I have found the solution for the problem. Many thanks for the good push to where I had to be. – VoltairePunk Jan 30 '13 at 10:31
  • I'm having a similar issue (only first pixel shown on map) with Cg shaders but it happens only if I'm not using frament programs. This issue happens only on Macs with Radeon video cards. If I enable a simple fragment program like the one you showed, it displays the texture fine. – user642252 Apr 19 '13 at 16:10
  • @user642252 What I do is that the above code is surrounded with data that enables both Vertex and Fragment shaders and then disables them using cgGLEnableProfile() and then cgGLBindProgram(). There's also a useful function in CG cgGetLastErrorString which I always run after each CG function call, just to check for errors. Now after all is rendered I disable those parameters. There is also another thing. As far as I know, not everything from CG is supported with ATI radeon cards. Try the examples, you'll see. Don't know if that helps at all, but would be good to know the problem more. – VoltairePunk Apr 24 '13 at 16:05

1 Answers1

1
glBindTexture(GL_TEXTURE_2D, 3);

I'd be wary of forcing texture object IDs on OpenGL. Technically it ought to work but using glGenTextures() to acquire texture IDs is a better idea.

genpfault
  • 51,148
  • 11
  • 85
  • 139
  • It's written like that just to show that I'm actually trying to bind a texture. The actual code looks like this: texture->Bind(GL_TEXTURE0); where texture is a pointer to the object's that is being rendered texture. When it's loaded, it uses glGenTextures as well as glTexture2D to actually create the texture in the memory. I'm basically debugging and trying to make it to work. If I use glBegin() ... glEnd() I can see the texture appear, but not with the VBOs in this case. – VoltairePunk Jan 29 '13 at 15:51