简体   繁体   中英

How do I have to set up Textures that I can use them in an Android OpenGL-ES 2.0 fragment shader?

I try to access 2 textures in 1 fragment shader.

For this I have 2 textures that I set up with following code:

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

glVertexPointer(2, GL_FLOAT, 0, vbuff);
glTexCoordPointer(2, GL_FLOAT, 0, tbuff);

glActiveTextureARB(GL_TEXTURE0_ARB);
glBindTexture(GL_TEXTURE_2D, texture0);
glEnable(GL_TEXTURE_2D);

glActiveTextureARB(GL_TEXTURE1_ARB);
glBindTexture(GL_TEXTURE_2D, texture1); 
glEnable(GL_TEXTURE_2D);

And I try to combine them with following fragment shader:

uniform sampler2D tex0;
uniform sampler2D tex1;
void main()
{
    vec4 texval1 = texture2D(tex0, TextureCoordOut);
    vec4 texval2 = texture2D(tex1, TextureCoordOut);
    gl_FragColor = 0.5*(texval1 + texval2)
}

Somehow this doesn't work and it only displays the second texture.

PS: I am developing the shaders on Windows7 but want to use the C++ code and the shaders with the Android NDK on an Android Device.

EDIT: I got it working and I post the code here, so that others might benefit from it:

vertex shader

varying vec2 TextureCoordOut;
void main()
{
    gl_Position = ftransform();
    TextureCoordOut = vec2(gl_MultiTexCoord0);
}

fragment shader

varying mediump vec2 TextureCoordOut;
uniform sampler2D tex0;
uniform sampler2D tex1;
void main()
{
    gl_FragColor = texture2D(tex0, TextureCoordOut) * texture2D(tex1, TextureCoordOut);
}

render

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

glVertexPointer(2, GL_FLOAT, 0, vbuff);  //2 dimensional vertex buffer
glTexCoordPointer(2, GL_FLOAT, 0, tbuff); // 2 dimensional textures
glColor4f(1, 1, 1, 1);

glActiveTexture(GL_TEXTURE0);       glBindTexture(GL_TEXTURE_2D, mapid1);
glActiveTexture(GL_TEXTURE1);       glBindTexture(GL_TEXTURE_2D, mapid2);

glUseProgram(shader);

glUniform1i(glGetUniformLocation(gfx.prog, "tex0"), 0);   //GL_TEXTURE0
glUniform1i(glGetUniformLocation(gfx.prog, "tex1"), 1);   //GL_TEXTURE1

render....

glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);

Just binding these textures to the respective units is not enough. You also need to tell the shaders where to take the textures for it's sampler2D uniforms from. This is done by setting the corresponding integer uniform value to the texture unit you want to use:

//get uniform locations (either init code or render code)
int locTex0 = glGetUniformLocation(program, "tex0");
int locTex1 = glGetUniformLocation(program, "tex1");

...    

//bind textures to texture units
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture1);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture0);

//bind program and specify texture units for each sampler2D uniform
glUseProgram(program);
glUniform1i(locTex0, 0);   //use texture bound to GL_TEXTURE0
glUniform1i(locTex1, 1);   //use texture bound to GL_TEXTURE1

...
draw

Of course this assumes that you know how to use shaders and specify uniform values.

Some additional remarks:

  • When using a fragment shader you don't need to call glEnable(GL_TEXTURE_2D) , since the shader decides itself if it uses a texture or not.
  • Don't use those ARB versions of functions and constants, at least not for such old and established things like multitexturing, which is core since GL 1.2 or 1.3 (~15 years).
  • Don't expect your code to be 1-to-1 portable to OpenGL ES 2.0, which doesn't know about the old builtin attributes (like glVertexPointer or glTexCoordPointer ), but that is a different question.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM