2

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.

Nick
  • 1,692
  • 3
  • 21
  • 35
  • 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. –  Jan 27 '12 at 22:15
  • 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 Jan 27 '12 at 22:16
  • May also be because your texture either isn't square or its dimensions are not a power of two. –  Jan 27 '12 at 22:19

2 Answers2

9

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.

Frogblast
  • 1,671
  • 10
  • 9
  • OMG!!! It worked thanks!! But I cant seem to explain why I need to set up clamping because all my texture coordinates were within the range. But thanks anyway!! – Nick Jan 28 '12 at 22:08
  • Non power of two textures need clamp_to_edge to work(among others), that's why. http://stackoverflow.com/questions/11069441/non-power-of-two-textures-in-ios – OMH Mar 12 '14 at 09:23
3

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);
};
Community
  • 1
  • 1
Erik
  • 804
  • 1
  • 8
  • 18