Nick
Nick

Reputation: 1758

OpenGL ES 2.0 texture appears black

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.

Upvotes: 2

Views: 5158

Answers (2)

Frogblast
Frogblast

Reputation: 1681

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.

Upvotes: 9

Erik
Erik

Reputation: 812

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);
};

Upvotes: 3

Related Questions