多个纹理单元GLES 2.0 Android

时间:2015-03-05 15:00:49

标签: android opengl-es opengl-es-2.0

尝试让2个纹理单元正常工作。

@Override
public void onDrawFrame(GL10 gl) {
    //Clear the Rendering Surface
    glClear(GL_COLOR_BUFFER_BIT);

    multiplyMM(viewProjectionMatrix, 0, projectionMatrix, 0, viewMatrix, 0);

    positionTableInScene();
    textureProgram.useProgram();
    textureProgram.setUniforms(modelViewProjectionMatrix, texture_b, texture_r);
    table.bindData(textureProgram);
    table.draw();
    ...
}

纹理程序:

public class TextureShaderProgram extends ShaderProgram {
//Uniform locations
private final int uMatrixLocation;
private final int uTextureUnit0Location;
private final int uTextureUnit1Location;

//Attribute locations
private final int aPositionLocation;
private final int aTextureCoordinatesLocation;

public TextureShaderProgram(Context context){
    super(context, R.raw.texture_vertex_shader, R.raw.texture_fragment_shader);

    //Retrieve uniform locations for the shader program.
    uMatrixLocation = glGetUniformLocation(program, U_MATRIX);
    uTextureUnit0Location = glGetUniformLocation(program, U_TEXTURE_UNIT_0);
    uTextureUnit1Location = glGetUniformLocation(program, U_TEXTURE_UNIT_1);

    //Retrieve attribute locations for the shader program.
    aPositionLocation = glGetAttribLocation(program, A_POSITION);
    aTextureCoordinatesLocation = glGetAttribLocation(program, A_TEXTURE_COORDINATES);
}
public void setUniforms(float[] matrix, int textureId, int textureId2){
    //Pass the matrix into the shader program
    glUniformMatrix4fv(uMatrixLocation, 1, false, matrix, 0);

    //Set the active texture unit to texture unit 0.
    glActiveTexture(GL_TEXTURE0);
    //Bind the texture to this unit.
    glBindTexture(GL_TEXTURE_2D, textureId);
    //Tell the texture uniform sample to use this texture in the shader by
    //telling it to read from texture unit 0.
    glUniform1f(uTextureUnit0Location, 0);

    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, textureId2);
    glUniform1f(uTextureUnit1Location, 0);


}


public int getPositionAttributeLocation(){
    return aPositionLocation;
}

public int getTextureCoordinatesAttributeLocation(){
    return aTextureCoordinatesLocation;
}
}

Fragment Shader:

precision mediump float;

uniform sampler2D u_TextureUnit0;
uniform sampler2D u_TextureUnit1;
varying vec2 v_TextureCoordinates;

void main()
{

   //gl_FragColor = texture2D(u_TextureUnit0, v_TextureCoordinates);

   gl_FragColor = (v_TextureCoordinates.y > 0.5)
   ?texture2D(u_TextureUnit1, v_TextureCoordinates)
   :texture2D(u_TextureUnit0, v_TextureCoordinates);

}

这并没有为我提供一半纹理和另一半纹理的预期结果。我发现这是因为我的纹理单位保持相同的图像。始终将图像加载到纹理单元0.更改首先加载哪个纹理会更改纹理,因此我知道两个纹理都有效。

我认为它是通知opengl我的纹理单位在哪里的方式。但我不知道如何改变它。

1 个答案:

答案 0 :(得分:4)

两个问题。首先,您将两个统一变量设置为相同的值:

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureId);
glUniform1f(uTextureUnit0Location, 0);

glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, textureId2);
glUniform1f(uTextureUnit1Location, 0);

您为均匀变量设置的值必须与相应纹理绑定的纹理单元的索引相匹配。由于第二个纹理绑定到GL_TEXTURE1,因此第二个统一值必须为1,而不是0。

此外,必须使用glUniform1i()设置采样器的统一值,而不是glUniform1f()

所以正确的代码如下所示:

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureId);
glUniform1i(uTextureUnit0Location, 0);

glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, textureId2);
glUniform1i(uTextureUnit1Location, 1);