首页 > 解决方案 > 如何一次使用 openGL ES 渲染多纹理?

问题描述

我目前正在为 android 编写一个视频播放器应用程序。这个想法是我可以在同一个视图中绘制多个纹理。现在我有四个纹理,我需要连接四个纹理。每个纹理在同一视图中的不同区域呈现。
我的顶点着色器显示如下:

private static final String VERTEX_SHADER =
        "uniform mat4 uMVPMatrix;\n" +
        "uniform mat4 uTexMatrix;\n" +
        "attribute vec4 aPosition;\n" +
        "attribute vec4 aTextureCoord;\n" +
        "varying vec2 vTextureCoord;\n" +
        "void main() {\n" +
        "    gl_Position = uMVPMatrix * aPosition;\n" +
        "    vTextureCoord = (uTexMatrix * aTextureCoord).xy;\n" +
        "}\n";

private static final String FRAGMENT_SHADER_2D =
        "precision highp float;\n" +
        "varying vec2 vTextureCoord;\n" +
        "uniform sampler2D sTexture;\n" +
        "void main() {\n" +
        "    gl_FragColor = texture2D(sTexture, vTextureCoord);\n" +
        "}\n";

我的绘制代码如下:

public void draw(float[] mvpMatrix, FloatBuffer vertexBuffer, int firstVertex,
                 int vertexCount, int coordsPerVertex, int vertexStride,
                 float[] texMatrix, FloatBuffer texBuffer, int textureId,
                 int texStride, int waterMarkTextureId) {
    GlUtil.checkGlError("draw start");

    // Select the program.
    GLES20.glUseProgram(mProgramHandle);
    GlUtil.checkGlError("glUseProgram");

    // Set the texture.
    GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
    GLES20.glBindTexture(mTextureTarget, textureId);

    if (mWaterEnabledLoc >= 0) {
        if (waterMarkTextureId != -1) {
            GLES20.glUniform1i(mWaterEnabledLoc, 1);
            GLES20.glActiveTexture(GLES20.GL_TEXTURE2);
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, waterMarkTextureId);
            GLES20.glUniform1i(mWaterTextureLoc, 2);
        } else {
            GLES20.glUniform1i(mWaterEnabledLoc, 0);
            GLES20.glUniform1i(mWaterTextureLoc, 0);
        }
    }

    // Copy the model / view / projection matrix over.
    GLES20.glUniformMatrix4fv(muMVPMatrixLoc, 1, false, mvpMatrix, 0);
    GlUtil.checkGlError("glUniformMatrix4fv");

    // Copy the texture transformation matrix over.
    GLES20.glUniformMatrix4fv(muTexMatrixLoc, 1, false, texMatrix, 0);
    GlUtil.checkGlError("glUniformMatrix4fv");

    // Enable the "aPosition" vertex attribute.
    GLES20.glEnableVertexAttribArray(maPositionLoc);
    GlUtil.checkGlError("glEnableVertexAttribArray");

    // Connect vertexBuffer to "aPosition".
    GLES20.glVertexAttribPointer(maPositionLoc, coordsPerVertex,
            GLES20.GL_FLOAT, false, vertexStride, vertexBuffer);
    GlUtil.checkGlError("glVertexAttribPointer");

    // Enable the "aTextureCoord" vertex attribute.
    GLES20.glEnableVertexAttribArray(maTextureCoordLoc);
    GlUtil.checkGlError("glEnableVertexAttribArray");

    // Connect texBuffer to "aTextureCoord".
    GLES20.glVertexAttribPointer(maTextureCoordLoc, 2,
            GLES20.GL_FLOAT, false, texStride, texBuffer);
    GlUtil.checkGlError("glVertexAttribPointer");

    // Draw the rect.
    GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, firstVertex, vertexCount);
    GlUtil.checkGlError("glDrawArrays");

    // Done -- disable vertex array, texture, and program.
    GLES20.glDisableVertexAttribArray(maPositionLoc);
    GLES20.glDisableVertexAttribArray(maTextureCoordLoc);
    GLES20.glBindTexture(mTextureTarget, 0);
    GLES20.glUseProgram(0);
}

理想情况下,结果如下:

___________________
|Texture1|Texture2|
|Texture3|Texture4|
___________________

我尝试四次绘制四个纹理,但没有成功。我使用与 GlUtil.IDENTITY_MATRIX 不同的 texMatrix 和相同的 mvpMatrix 来绘制每个纹理。但结果显示视图中只渲染了最后一个纹理。结果如下:

___________________
|********|********|
|********|Texture4|
___________________

* 表示为 Texture4 的 GLES20.GL_CLAMP_TO_EDGE。

我也试过变换mvpMatrix,会出现四个纹理,但是顺序错误如下:

___________________
|Texture4|Texture3|
|Texture2|Texture1|
___________________

至于其余区域是每个纹理的 GLES20.GL_CLAMP_TO_EDGE,它对再次转换 mvpMatrix 不起作用。

有没有更好的方法让我在一个视图中绘制多个纹理?真诚期待您的答复。

标签: javaandroidopengl-es

解决方案


推荐阅读