2013-08-01 4 views
2

Краткое описание: когда я применяю к одному фрагменту шейдеру две текстуры с двумя разными координатами текстуры, я вижу только первую текстуру. Но когда я использую одну координату текстуры для двух текстур, она отлично работает, и я могу видеть обе текстуры.Две текстуры с различными координатами текстуры в OpenGL ES 2.0

Работаю с фотофильтрами и использую 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); 
} 

метод:

@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 и надеюсь на вашу помощь.

+0

Почему вы включили смешивание? С таким необычным blendFunc? – rotoglup

+0

Я нашел это как решение другой проблемы, и я подумал, что это может помочь мне с моей проблемой. Но сейчас это бесполезно. –

ответ

2

Вы не можете использовать GLUtils.texImage2D() для загрузки альфа-текстур на Android. Это распространенная проблема, которую Google действительно должен документировать лучше. Проблема заключается в том, что класс Bitmap преобразует все изображения в предварительно умноженный формат, но это не работает с OpenGL ES, если изображения полностью непрозрачны. Лучшее решение - использовать собственный код. Эта статья дает более подробную информацию по этому вопросу:

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

+0

Я использую полностью непрозрачные изображения и устанавливаю альфа-канал в фрагмент-шейдере. –

Смежные вопросы