Android OpenGL ES - 在某些设备上无法绑定超过9个纹理

时间:2016-07-01 06:10:01

标签: java android opengl-es

首先,抱歉我的英语不好。

我正在为我的应用程序制作2D场景。我的场景中有13个纹理,所以我通过以下代码绑定这些纹理。 (我硬编码因为我正在测试它)

    //Prepare texture bitmap
            BitmapFactory.Options bfo = new BitmapFactory.Options();
            Bitmap bmp = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.scene02_bg, bfo);
            //Bind Texture
            int[] texturenames = new int[13];
            GLES20.glGenTextures(13, texturenames, 0);

            GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texturenames[0]);

            // Set filtering
            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 Texture
            GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bmp, 0);

            //Recycle bitmap
            bmp.recycle();

    //for second texture
            bmp = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.scene02_campfire, bfo);
            GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texturenames[1]);
            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);
            GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bmp, 0);
            bmp.recycle();

    //............
    //............
    //............

     bmp = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.scene02_tree09, bfo);
            GLES20.glActiveTexture(GLES20.GL_TEXTURE12);
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texturenames[12]);
            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);
            GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bmp, 0);
            bmp.recycle();

然后,我在三个设备上测试了它,三星Galaxy S3,Note 4和S5。

注4和S5正确渲染,全部13个。但是Galaxy S3只渲染了9个纹理,在第10个纹理之后,渲染了纹理名称[0]的纹理。

由于Note 4和S5完美运行,我认为我的代码没有问题。我用Google搜索了几个小时,但我甚至无法确定这有什么问题。

任何帮助将不胜感激。谢谢你的阅读。

- 有关更多详细信息,请附上我的着色器和渲染代码。

    public static final String VERTEXSHADER_TEXTURE =
            "uniform mat4 uMVPMatrix;" +
                    "attribute vec4 vPosition;" +
                    "attribute vec2 a_texCoord;" +
                    "varying vec2 v_texCoord;" +
                    "void main() {" +
                    "  gl_Position = uMVPMatrix * vPosition;" +
                    "  v_texCoord = a_texCoord;" +
                    "}";

    public static final String FRAGMENTSHADER_TEXTURE =
                    "precision mediump float;" +
                    "varying vec2 v_texCoord;" +
                    "uniform sampler2D s_texture;" +
                    "void main() {" +
                    "  gl_FragColor = texture2D( s_texture, v_texCoord );" +
                    "}";


   public void Draw(float[] mvpMatrix){
        int mPositionHandle, mMVPMatrixHandle;

        float[] mvp;
        mvp = mvpMatrix.clone();

        Matrix.setIdentityM(mModelMatrix, 0);
        Matrix.scaleM(mModelMatrix, 0, mScale, mScale, 1);

        Matrix.translateM(mModelMatrix, 0, mPositionX, mPositionY, mPositionZ);
        Matrix.setRotateM(mRotationMatrix, 0, mAngle, 0, 0, -1f);

        mTempMatrix = mModelMatrix.clone();
        Matrix.multiplyMM(mModelMatrix, 0, mTempMatrix, 0, mRotationMatrix, 0);

        mTempMatrix = mvp.clone();
        Matrix.multiplyMM(mvp, 0, mTempMatrix, 0, mModelMatrix, 0);

        GLES20.glUseProgram(mTextureShaderProgram);

        /*Setup vertex*/
        mPositionHandle = GLES20.glGetAttribLocation(mTextureShaderProgram, "vPosition");
        GLES20.glEnableVertexAttribArray(mPositionHandle);
        GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false,
            vertexStride, vertexBuffer);

        /*Setup camera view*/
        mMVPMatrixHandle = GLES20.glGetUniformLocation(mTextureShaderProgram, "uMVPMatrix");
        GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvp, 0);

        //Setup Texture
        int texCoordHandle = GLES20.glGetAttribLocation(mTextureShaderProgram, "a_texCoord");
        GLES20.glEnableVertexAttribArray(texCoordHandle);
        GLES20.glVertexAttribPointer(texCoordHandle, 2, GLES20.GL_FLOAT, false, 0, uvBuffer);
        int samplerHandle = GLES20.glGetUniformLocation(mTextureShaderProgram, "s_texture");
        GLES20.glUniform1i(samplerHandle, textureIndex);

        /*Draw*/
        GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length, GLES20.GL_UNSIGNED_SHORT, indexBuffer);
        GLES20.glDisableVertexAttribArray(mPositionHandle);
}

1 个答案:

答案 0 :(得分:0)

从渲染代码中,我假设你将每个纹理绑定到它自己的纹理单元:

最有可能的是,你超过了可以同时使用的允许纹理数量。在OpenGL ES小于或等于2.0时,只保证可以同时使用8个纹理单元,尽管可以有更多。您可以使用glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, ...);查询限制。

你可以在你的应用程序中做什么(并且因为你一次只使用一个纹理),就是将每个纹理重新绑定到例如TEXTURE_UNIT0,而不是将每个纹理分配给它自己的单元。然后,绘图代码如下所示:

int samplerHandle = GLES20.glGetUniformLocation(mTextureShaderProgram, "s_texture");
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texturenames[textureIndex]);
GLES20.glUniform1i(samplerHandle, 0);

GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length,
                      GLES20.GL_UNSIGNED_SHORT, indexBuffer);