2

概要: 2 つの異なるテクスチャ座標を持つ 2 つのテクスチャを 1 つのフラグメント シェーダに適用すると、最初のテクスチャしか表示されません。しかし、2 つのテクスチャに対して 1 つのテクスチャ座標を使用すると、問題なく動作し、両方のテクスチャを見ることができます。

私は写真フィルターを扱っており、OpenGL ES 2.0 を使用してフィルターを作成しています。一部のフィルタには高度なテクスチャがあります。最初のテクスチャは写真で、2 番目はトレーサリーです。

ここに私の頂点シェーダーがあります

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

Android では、GLUtils.texImage2D() を使用してアルファ テクスチャをロードすることはできません。これはよくある問題であり、Google はより適切に文書化する必要があります。問題は、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 に答える