2

简介:当我将具有两个不同纹理坐标的两个纹理应用于一个片段着色器时,我只看到第一个纹理。但是当我对两个纹理使用一个纹理坐标时,它工作得很好,我可以看到两个纹理。

我使用照片滤镜并使用 OpenGL ES 2.0 制作滤镜。一些过滤器具有高级纹理。第一个纹理是照片,第二个是窗饰。

这是我的顶点着色器

attribute vec4 position;

attribute vec4 inputTextureCoordinate;
attribute vec4 inputTextureCoordinate2;

varying vec2 textureCoordinate;
varying vec2 textureCoordinate2;

void main() {
    gl_Position = position;
    textureCoordinate = inputTextureCoordinate.xy;
    textureCoordinate2 = inputTextureCoordinate2.xy;
} 

这是我的片段着色器

precision mediump float;

uniform sampler2D inputImageTexture1;
uniform sampler2D inputImageTexture2;

varying vec2 textureCoordinate;
varying vec2 textureCoordinate2;

void main() {
    mediump vec4 color1 = texture2D(inputImageTexture1, textureCoordinate);
    mediump vec4 color2 = texture2D(inputImageTexture2, textureCoordinate2);
    mediump vec3 colorResult = mix(color1.rgb, color2.rgb, 0.5);
    gl_FragColor = vec4(colorResult, 1.0);
}

在我的代码中,我使用 GLSurfaceView.Render 实现。

坐标初始化:

static final float CUBE[] = {-1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f,};
public static final float COORDINATES1[] = {0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,};
public static final float COORDINATES2[] = {0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,};

...

mGLCubeBuffer = ByteBuffer.allocateDirect(CUBE.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
mGLCubeBuffer.put(CUBE).position(0);

mGLTextureCoordinates1 = ByteBuffer.allocateDirect(COORDINATES1.length * 4).order(ByteOrder.nativeOrder())
                .asFloatBuffer();
mGLTextureCoordinates1.clear();
mGLTextureCoordinates1.put(COORDINATES1).position(0);

mGLTextureCoordinates2 = ByteBuffer.allocateDirect(COORDINATES2.length * 4).order(ByteOrder.nativeOrder())
                .asFloatBuffer();
mGLTextureCoordinates2.clear();
mGLTextureCoordinates1.put(COORDINATES2).position(0);

onSurfaceCreate方法:

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    GLES20.glClearColor(0, 0, 0, 1);
    GLES20.glDisable(GLES20.GL_DEPTH_TEST);
    GLES20.glDisable(GLES20.GL_DEPTH_BITS);

    String vertexShader = RawResourceReader.readTextFileFromRawResource(mContext, R.raw.test_vertex);
    String fragmentShader = RawResourceReader.readTextFileFromRawResource(mContext, R.raw.test_fragment);
    mGLProgId = loadProgram(vertexShader, fragmentShader);
    mGLAttribPosition = GLES20.glGetAttribLocation(mGLProgId, "position");
    mGLAttribTextureCoordinate = GLES20.glGetAttribLocation(mGLProgId, "inputTextureCoordinate");
    mGLAttribTextureCoordinate2 = GLES20.glGetAttribLocation(mGLProgId, "inputTextureCoordinate2");
    mGLUniformTexture1 = GLES20.glGetUniformLocation(mGLProgId, "inputImageTexture1");
    mGLUniformTexture2 = GLES20.glGetUniformLocation(mGLProgId, "inputImageTexture2");

    mTexture1 = loadTexture(mContext, R.drawable.photo);
    mTexture2 = loadTexture(mContext, R.drawable.formula1);
}

onDrawFrame方法:

    @Override
public void onDrawFrame(GL10 gl) {
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);

    GLES20.glUseProgram(mGLProgId);

    mGLCubeBuffer.position(0);
    GLES20.glVertexAttribPointer(mGLAttribPosition, 2, GLES20.GL_FLOAT, false, 0, mGLCubeBuffer);
    GLES20.glEnableVertexAttribArray(mGLAttribPosition);

    //set first coordinates
    mGLTextureCoordinates1.position(0);
    GLES20.glVertexAttribPointer(mGLAttribTextureCoordinate, 2, GLES20.GL_FLOAT, false, 0, mGLTextureCoordinates1);
    GLES20.glEnableVertexAttribArray(mGLAttribTextureCoordinate);

    //set second coordinates
    mGLTextureCoordinates2.position(0);
    GLES20.glVertexAttribPointer(mGLAttribTextureCoordinate2, 2, GLES20.GL_FLOAT, false, 0, mGLTextureCoordinates2);
    GLES20.glEnableVertexAttribArray(mGLAttribTextureCoordinate2);

    GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTexture1);
    GLES20.glUniform1i(mGLUniformTexture1, 0);

    GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTexture2);
    GLES20.glUniform1i(mGLUniformTexture2, 1);

    GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);

    GLES20.glDisableVertexAttribArray(mGLAttribPosition);
    GLES20.glDisableVertexAttribArray(mGLAttribTextureCoordinate);
    GLES20.glDisableVertexAttribArray(mGLAttribTextureCoordinate2);
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
}

方法的重要部分loadTexture

        GLES20.glGenTextures(1, textureHandle, 0);
        // Bind to the texture in OpenGL
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);

        // Set filtering
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
        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);

        GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_CONSTANT_ALPHA);
        GLES20.glEnable(GLES20.GL_BLEND);

        // Load the bitmap into the bound texture.
        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);

        // Recycle the bitmap, since its data has been loaded into OpenGL.
        bitmap.recycle();

请注意,在 iOs 上它工作正常,但使用了一些库。我尝试使用库 jp.co.cyberagent.android.gpuimage 但它有一些错误并且无法正常解决这个问题。

我想知道如何解决这个问题。它可能是一些我不知道的财产或其他东西。我是 OpenGL 新手,希望对您有所帮助。

4

1 回答 1

2

您不能使用 GLUtils.texImage2D() 在 Android 上加载 alpha 纹理。这是谷歌真正应该更好地记录的常见问题。问题是 Bitmap 类将所有图像转换为预乘格式,但这不适用于 OpenGL ES,除非图像完全不透明。最好的解决方案是使用本机代码。本文提供了更多详细信息:

http://software.intel.com/en-us/articles/porting-opengl-games-to-android-on-intel-atom-processors-part-1

于 2013-08-02T17:50:46.207 回答