I want to display an image as texture on a quad with OpenGL ES 2.0 using the Android NDK.
I have the following simple vertex and fragment shader:
#define DISP_SHADER_V_SRC "\
attribute vec4 aPos;\
attribute vec2 aTexCoord;\
varying vec2 vTexCoord;\
void main() {\
gl_Position = aPos;\
vTexCoord = aTexCoord;\
}"
#define DISP_SHADER_F_SRC "\
precision mediump float;\n\
varying vec2 vTexCoord;\n\
uniform sampler2D sTexture;\n\
void main() {\n\
gl_FragColor = texture2D(sTexture, vTexCoord);\n\
}"
At first, a native "create" method is called when the GLSurfaceView is created. It sets the clear color, builds the shader and gets me a texture id using glGenTextures
. A "resize" method sets the current view size. Another method sets the texture data like this:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
I don't believe that there's something wrong there. The important thing should be the "draw" method. After glClear, glViewport and glUseProgram I do the following:
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texId);
glEnableVertexAttribArray(shAPos);
glVertexAttribPointer(shAPos, 3, GL_FLOAT, false, 0, quadVertices);
glVertexAttribPointer(shATexCoord, 2, GL_FLOAT, false, 0, quadTexCoordsStd);
glEnableVertexAttribArray(shATexCoord);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// now glDisableVertex...
I can confirm that the shader basically works, since gl_FragColor=vec4(1.0);
results in a white screen. It just does not work when I load a texture. I tried out setting the pixel data to "all white" using memset
just to confirm that the issue is not related with my image data, but still the screen stays black. What am I missing?
glBindTexture(GL_TEXTURE_2D, texId)
before theglTexImage2D
call? Is the texture using power-of-two sizes?glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texId);
, then I setGL_CLAMP_TO_EDGE
and generate mipmaps. I also checked thatvTexCoord
has valid values by settinggl_FragColor = vec4(vTexCoord.s, vTexCoord.t, 1.0, 1.0)
. It all does what it should, besides drawing the damn texture :(onSurfaceCreated
. However, I wanted that the texture changes when I touch the view. I guessed it had something to do with the calling thread. So I moved the code to call the texture loading function from anOnClickListener
directly to the class that implements theGLSurfaceView.Renderer
. Now it works. Tricky thing though, since no errors were thrown :(sTexture
to 0.