在OpenGL ES 2中切换纹理

时间:2012-10-13 20:30:06

标签: opengl-es-2.0 textures

我正在试图弄清楚如何将不同的纹理放入不同的纹理单元并选择要绘制的纹理。我的onDrawFrame()方法

中有以下代码
    int[] texture = new int[7];
    texture[0] =TextureHelper.loadTexture(mActivityContext,R.drawable.texture1);
    texture[1] =TextureHelper.loadTexture(mActivityContext,R.drawable.texture2);
    texture[2] =TextureHelper.loadTexture(mActivityContext,R.drawable.texture3);
    texture[3] =TextureHelper.loadTexture(mActivityContext,R.drawable.texture4);
    texture[4] =TextureHelper.loadTexture(mActivityContext,R.drawable.texture5);
    texture[5] =TextureHelper.loadTexture(mActivityContext,R.drawable.texture6);
    texture[6] =TextureHelper.loadTexture(mActivityContext,R.drawable.texture7);

    for (int i = 0; i < 7; i ++) {
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + i);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture[i]);
        GLES20.glUniform1i(mTextureUniformHandle, i);
        Matrix.setIdentityM(mModelMatrix, 0);
        Matrix.translateM(mModelMatrix, 0, -0.60f + 0.2f * i, 0.0f, 0.0f);
        draw();
    }

这应该做的是将七种不同的纹理加载到单独的纹理单元中并绘制立方体,每个立方体具有不同的纹理。然而,最终发生的事情是所有立方体最终都是用第一个纹理绘制的。

如果我将GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + i)更改为GLES20.glActiveTexture(GLES20.GL_TEXTURE0)并将GLES20.glUniform1i(mTextureUniformHandle, i)更改为GLES20.glUniform1i(mTextureUniformHandle, 0),它可以正常工作,但这只是使用单个纹理单元并且每次都替换该单元中的纹理,这不是我想做的事。

我做错了什么? 提前谢谢。

编辑:

顶点着色器:

            "uniform mat4 u_MVPMatrix;" + // A constant representing the
                                            // combined
                                            // model/view/projection matrix.
            "uniform mat4 u_MVMatrix;" + // A constant representing the
                                            // combined model/view matrix.

            "attribute vec4 a_Position;" + // Per-vertex position
                                            // information we will pass in.
            "attribute vec4 a_Color;" + // Per-vertex color information we
                                        // will pass in.
            "attribute vec2 a_TexCoordinate;" + // Per-vertex texture
                                                // coordinate information we
                                                // will pass in.

            "varying vec3 v_Position;" + // This will be passed into the
                                            // fragment shader.
            "varying vec4 v_Color;" + // This will be passed into the
                                        // fragment shader.
            "varying vec2 v_TexCoordinate;" + // This will be passed into
                                                // the fragment shader.

            // The entry point for our vertex shader.
            "void main()" + "{" +
            // Transform the vertex into eye space.
            "v_Position = vec3(u_MVMatrix * a_Position);" +

            // Pass through the color.
            "v_Color = a_Color;" +

            // Pass through the texture coordinate.
            "v_TexCoordinate = a_TexCoordinate;" +

            // gl_Position is a special variable used to store the final
            // position.
            // Multiply the vertex by the matrix to get the final point in
            // normalized screen coordinates.
            "gl_Position = u_MVPMatrix * a_Position;" + "} ";

片段着色器:

            "precision mediump float;" + // Set the default precision to medium. We don't need as high of a
            // precision in the fragment shader.
            "uniform sampler2D u_Texture;" + // The input texture.

            "varying vec3 v_Position;" + // Interpolated position for this fragment.
            "varying vec4 v_Color;" + // This is the color from the vertex shader interpolated across the
            // triangle per fragment.
            "varying vec2 v_TexCoordinate;" + // Interpolated texture coordinate per fragment.

            // The entry point for our fragment shader.
            "void main()" +
            "{" +
                // Multiply the color by the diffuse illumination level and texture value to get final output color.
                "gl_FragColor = (v_Color * texture2D(u_Texture, v_TexCoordinate));" +
            "}";

draw()方法:

public void draw() {
// Pass in the position information
    mCubePositions.position(0);
    GLES20.glVertexAttribPointer(mPositionHandle, mPositionDataSize, GLES20.GL_FLOAT, false, 0, mCubePositions);
    GLES20.glEnableVertexAttribArray(mPositionHandle);

    // Pass in the color information
    mCubeColors.position(0);
    GLES20.glVertexAttribPointer(mColorHandle, mColorDataSize, GLES20.GL_FLOAT, false, 0, mCubeColors);
    GLES20.glEnableVertexAttribArray(mColorHandle);

    // Pass in the texture coordinate information
    mCubeTextureCoordinates.position(0);
    GLES20.glVertexAttribPointer(mTextureCoordinateHandle, mTextureCoordinateDataSize, GLES20.GL_FLOAT, false, 0, mCubeTextureCoordinates);
    GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle);

    // This multiplies the view matrix by the model matrix, and stores the
    // result in the MVP matrix
    // (which currently contains model * view).
    Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);

    // Pass in the modelview matrix.
    GLES20.glUniformMatrix4fv(mMVMatrixHandle, 1, false, mMVPMatrix, 0);

    // This multiplies the modelview matrix by the projection matrix, and
    // stores the result in the MVP matrix
    // (which now contains model * view * projection).
    Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);

    // Pass in the combined matrix.
    GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);

    // Draw the cube.
    GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
}

分配mTextureUniformHandle:

mTextureUniformHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_Texture");

1 个答案:

答案 0 :(得分:0)

最近我一直在片段着色器中搜索多个纹理并遇到了这个Binding textures to samplers

我从中得到以下工作:

onSurfaceCreatedonSurfaceChanged

  • 加载着色器(附加和链接)并获取sampler2D(和其他变量)的统一位置:

normalMapLoc = GLES20.glGetUniformLocation(shaderProgram, "normalMap"); shadowMapLoc = GLES20.glGetUniformLocation(shaderProgram, "shadowMap");

  • 加载纹理:

GLES20.glGenTextures(2, textures, 0); GLES20.glActiveTexture(GLES20.GL_TEXTURE0); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0); bitmap.recycle(); GLES20.glActiveTexture(GLES20.GL_TEXTURE1); GLES20.glBindTexture(GL10.GL_TEXTURE_COORD_ARRAY, textures[1]); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, mColorBuffer); GLES20.glUniform1i(normalMapLoc, 0); // Texture unit 0 is for normal images. GLES20.glUniform1i(shadowMapLoc, 1); // Texture unit 1 is for shadow maps.

onDrawFrame

GLES20.glClearColor(0f, 0f, 0f, 0f); GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); // pass variables to the fragment shader ... // get handle to vertex shader's Position member, etcetera int mPositionHandle = GLES20.glGetAttribLocation(shaderProgram, "vPosition"); GLES20.glEnableVertexAttribArray(mPositionHandle); GLES20.glVertexAttribPointer(mPositionHandle, 3, GLES20.GL_FLOAT, false, 0, mVertexBuffer); GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP, 4, GLES20.GL_UNSIGNED_SHORT, mIndexBuffer);

最后片段着色器看起来像这样(只是代码的相关部分):

    uniform sampler2D normalMap, shadowMap;
    varying vec2 pos;

    void main() {
      vec4 color = texture2D(normalMap, pos);
      vec4 shadow = texture2D(shadowMap, pos);
      // do stuff with the colors
      ...
      gl_FragColor = ...;
    }

这样我终于可以访问这两种纹理了!

希望这有帮助。