0
\$\begingroup\$

I want to use two png pictures as textures. Then I want to set textureId as attribute to each vertex. My vertex shader:

uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform mat4 transformMatrix;
attribute vec2 aPosition;
attribute vec2 aTexPos;
attribute float aTexIdPos;
varying vec2 vTexPos;
varying float vTexIdPos;
void main() {
    vTexPos = aTexPos;
    vTexIdPos = aTexIdPos;
    gl_Position = projectionMatrix * viewMatrix * transformMatrix * 
    vec4(aPosition.xy, 0.0, 1.0);
}

Then this is the way, I load textures:

public void addTextures(Resources resources, int... resIds){
    GLES20.glGenTextures(resIds.length, textureIds, 0);
    numTextures = resIds.length;

    for(int i = 0 ; i < resIds.length ; i++){
        if (textureIds[i] == GLES20.GL_FALSE)
            throw new RuntimeException("Error loading texture");

        // bind the texture and set parameters
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + i);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureIds[i]);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);

        // Load a bitmap from resources folder and pass it to OpenGL
        // in the end, we recycle it to free unneeded resources
        Bitmap b = BitmapFactory.decodeResource(resources, resIds[i]);
        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, b, 0);
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);

        b.recycle();
    }

    int uTexture = GLES20.glGetUniformLocation(programHandle, "uTexture");
    GLES20.glUniform1iv(uTexture, numTextures, textureIds, 0);
}

When I use this fragment shader, it renders texture that was last baund with glBindTexture:

precision mediump float;
uniform sampler2D uTexture[16];
varying vec2 vTexPos;
varying float vTexIdPos;
void main(){
    gl_FragColor = texture2D(uTexture[0] , vTexPos);
}

But if I change it to:

precision mediump float;
uniform sampler2D uTexture[16];
varying vec2 vTexPos;
varying float vTexIdPos;
void main(){
    gl_FragColor = texture2D(uTexture[1] , vTexPos);
}

It renders black rectangles. I dont understand why binding texture changes what uTexture[0] contains. It should contain my first picture and uTexture[1] should contain the second one.

\$\endgroup\$

1 Answer 1

0
\$\begingroup\$

I think that the problem is the data provided in glUniform1iv call

int uTexture = GLES20.glGetUniformLocation(programHandle, "uTexture");
GLES20.glUniform1iv(uTexture, numTextures, **textureIds**, 0);

You are assigning to the uniform "uTexture" location, and the following numTextures locations, the values of the textureIds generated by

GLES20.glGenTextures(resIds.length, textureIds, 0);

But sampler2D uniforms expect the values of the "GLES20.GL_TEXTURE0 + i", basically [0, 1, 2, 3, 4, ...]

int[] textureOffset = new int[]{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }; 
int uTexture = GLES20.glGetUniformLocation(programHandle, "uTexture");
GLES20.glUniform1iv(uTexture, numTextures, **textureOffset** , 0);

Note: A black texture is shown when you provide a textureOffset not activated. And if there is no active texture, the tests that I have run shown that texture 0 points to the last bound texture.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .