2
votes

I am working on an application using OpenGL ES 2.0 for an embedded device.

This is my fragment shader:

varying vec2 v_texCoord;
uniform sampler2D s_texture;
void main() {
  gl_FragColor = texture2D(s_texture, v_texCoord);
}

I set up the textures properly. For some reason, calling glTexImage2D is not producing the result I'm looking for. The texture is entirely black, rather than being filled with the data I provide it.

This is how I create the texture:

   GLuint textureId;

   // 2x2 Image, 3 bytes per pixel (R, G, B)
   GLubyte pixels[6 * 3] =
   {  
      255,   0,   0, // Red
        0, 255,   0, // Green
        0,   0, 255, // Blue
      255, 255,   0,  // Yellow
        0, 255, 255,
        255, 0, 255
   };

   // Use tightly packed data
   glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 );

   // Generate a texture object
   glGenTextures ( 1, &textureId );

   // Bind the texture object
   glBindTexture ( GL_TEXTURE_2D, textureId );

   // Load the texture
   glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, 3, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels );


   // Set the filtering mode
   glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
   glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );

Afterward, I bind the texture like so:

samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" );
glActiveTexture ( GL_TEXTURE0 );
glBindTexture ( GL_TEXTURE_2D, textureId );

// Set the sampler texture unit to 0
glUniform1i ( samplerLoc, 0 );

I confirmed that the vertex and texture coordinates are bound and passed to the shaders when debugging. So, it has to be an issue with s_texture or the glTexImage2D function itself.

2
Did you check for errors using GetError? You may also be calling TexImage and TexParameter in the wrong order (TexParameter typically comes before TexImage), though I'm not sure if that affects anything. That said, it's very unlikely to be an issue with TexImage, and is almost definitely a mistake on your part.user457812
Yea I did. No error was recorded. I know it cant be vertex shader, coz when i debugged i saw that vertex coordinates and texture coordinates are passed correctly. Its pretty much a straight forward example from textbook. I dont know what I missed. :(Nick
May also be because your texture either isn't square or its dimensions are not a power of two.user457812

2 Answers

8
votes

You need to set the clamp modes to CLAMP_TO_EDGE for both U and V dimensions, otherwise the texture is incomplete and will sample as black.

3
votes

Perhaps I'm missing something obvious but if you are storing only 2 x 2 pixels with 3 bytes per color (= 4 x 3 bytes = 12 bytes) as a texture; then where does the 6 in "GLubyte pixels[6 * 3]" come from?

6*3 equals 18 and != power of 2

// Load the texture glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, 3, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels );

From the spec: glTexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid * data);

Bolded vars are best a ^2...

So, try this:

// Load the texture glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels );

Delete the last 2 rows from your pixels array, then change all values to "255"; if you get a white texture, that means it's working.

Another example:

GLubyte pixels[4 * 3] = {

255, 0, 0, //Red //Green //Blue // pixel 0

255, 0, 0, //Red //Green //Blue // pixel 1

255, 0, 0, //Red //Green //Blue // pixel 2

255, 0, 0 //Red //Green //Blue // pixel 3

};

And everything shows up red.

If that doesnt do it, perhaps my code will help :

void CMesh::renderMesh(GLuint program, glm::mat4 *mvp){

glUseProgram(program);

int mvpLocation = glGetUniformLocation(program, "matViewProjection");
int texLocation = glGetUniformLocation(program, "baseMap");
glUniformMatrix4fv( mvpLocation, 1, GL_FALSE, glm::value_ptr(*mvp));

int vertexAttribLocation = glGetAttribLocation(program, "vertex");
int uvAttribLocation = glGetAttribLocation(program, "texturecoordinate");

// Bind our texture in Texture Unit 0
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureIndex);
glUniform1i(texLocation, 0);

glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexAttribPointer(
   vertexAttribLocation,            
   3,                               // size
   GL_FLOAT,                        // type
   GL_FALSE,                        // normalized?
   0,                               // stride
   (void*)0                         // array buffer offset
);

glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, uvBuffer);
glVertexAttribPointer(
   uvAttribLocation,                  
   2,                  // size
   GL_FLOAT,           // type
   GL_FALSE,           // normalized?
   0,                  // stride
   (void*)0            // array buffer offset
);

// Draw the triangles !
glDrawArrays(GL_TRIANGLES, 0, vertices.size() );

glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
};