Java 将图像及其遮罩与Android着色器相结合?

Java 将图像及其遮罩与Android着色器相结合?,java,android,opengl-es,shader,Java,Android,Opengl Es,Shader,我正在为android开发一个应用程序,我使用GL处理一些行为,我遇到了一个具体案例的问题 我有一个环境图像(例如,一个房间),还有一个全白色的遮罩,用黑色标记墙的位置 我想把这两幅图像混合在一起,得到结果(例如,把墙涂成红色) 但首先我需要向着色器指出这两个图像是谁,这里我遇到了麻烦 这是我的片段着色器: public static final String fs_Image_mix = "precision mediump float;" +

我正在为android开发一个应用程序,我使用GL处理一些行为,我遇到了一个具体案例的问题

我有一个环境图像(例如,一个房间),还有一个全白色的遮罩,用黑色标记墙的位置

我想把这两幅图像混合在一起,得到结果(例如,把墙涂成红色)

但首先我需要向着色器指出这两个图像是谁,这里我遇到了麻烦

这是我的片段着色器:

public static final String fs_Image_mix =
        "precision mediump float;" +

                "arying LOWP vec4 v_color;" +
                "varying vec2 v_texCoord;" +

                "uniform sampler2D s_texture;" +
                "uniform sampler2D s_mask;" +

                "void main() {" +
                //"  gl_FragColor = texture2D( s_texture, v_texCoord );" +

                "   vec4 color0 = texture2D(s_texture, v_texCoords);" +
                "   vec4 color1 = texture2D(s_mask, v_texCoords);" +

                "   float mask = texture2D(s_mask, v_texCoords).a;" +
                "   mask = step(1.0, mask);" +

                "   gl_FragColor = v_color * mix(color0, color1, mask);" +
                "}";
这是我通过背景纹理时的绘图功能:

public void Draw(float[] mvpMatrix, int[] textureHandle, int textureIndex){

    GLES20.glActiveTexture(GLES20.GL_TEXTURE0);

    // Apply transparency to the texture
    GLES20.glEnable(GLES20.GL_BLEND);
    GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);

    // Ensure that uses the correct texture
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[textureIndex]);

    // get handle to vertex shader's vPosition member
    int mPositionHandle = GLES20.glGetAttribLocation(GraphicTools.sp_Image_mix, "vPosition");

    // Enable generic vertex attribute array
    GLES20.glEnableVertexAttribArray(mPositionHandle);

    // Prepare the triangle coordinate data
    GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
            GLES20.GL_FLOAT, false,
            vertexStride, vertexBuffer);

    // Get handle to texture coordinates location
    int mTexCoordLoc = GLES20.glGetAttribLocation(GraphicTools.sp_Image_mix, "a_texCoord" );

    // Enable generic vertex attribute array
    GLES20.glEnableVertexAttribArray ( mTexCoordLoc );

    // Prepare the texturecoordinates
    GLES20.glVertexAttribPointer ( mTexCoordLoc, 2, GLES20.GL_FLOAT,
            false,
            0, uvBuffer);

    // Get handle to shape's transformation matrix
    int mtrxhandle = GLES20.glGetUniformLocation(GraphicTools.sp_Image_mix, "uMVPMatrix");

    // Apply the projection and view transformation
    GLES20.glUniformMatrix4fv(mtrxhandle, 1, false, mvpMatrix, 0);

    // Get handle to textures locations
    int mSamplerLoc = GLES20.glGetUniformLocation (GraphicTools.sp_Image_mix, "s_texture" );

    // Set the sampler texture unit to 0, where we have saved the texture.
    GLES20.glUniform1i ( mSamplerLoc, 0);

    // Draw the triangle
    GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.length,
            GLES20.GL_UNSIGNED_SHORT, drawListBuffer);

    // Disable vertex array
    GLES20.glDisableVertexAttribArray(mPositionHandle);
    GLES20.glDisableVertexAttribArray(mTexCoordLoc);

}
如何用所需的掩码填充“s_mask”变量?记住,textureHandle[textureIndex]是背景图像。

访问纹理和遮罩纹理 传递给“纹理采样器均匀”的值是纹理所指向的纹理单元的索引 你想过关就一定要过关。要在着色器中使用多个纹理,应执行以下操作:

着色器启动后,将编译着色器阶段并链接着色器程序 可以获得纹理采样器的统一位置

int mTextureSamplerLoc = GLES20.glGetUniformLocation( GraphicTools.sp_Image_mix, "s_texture" );
int mMaskSamplerLoc    = GLES20.glGetUniformLocation( GraphicTools.sp_Image_mix, "s_mask" );
在绘制场景之前,必须将纹理绑定到纹理单元

int textureTexUnitIndex = 1;
GLES20.glActiveTexture( GLES20.GL_TEXTURE1 ); // GLES20.GL_TEXTURE1 <--> textureTexUnitIndex
GLES20.glBindTexture( GLES20.GL_TEXTURE_2D, textureHandle[textureIndex] );

int maskTexUnitIndex = 2;
GLES20.glActiveTexture( GLES20.GL_TEXTURE2 ); // GLES20.GL_TEXTURE2 <--> maskTexUnitIndex
GLES20.glBindTexture( GLES20.GL_TEXTURE_2D, ... ) // <-- here you have to add the texture handler of the texture
注意,我使用纹理单元1和2,但您可以使用任何想要的纹理单元。唯一的要求是使用2个不同的纹理单元

int textureTexUnitIndex = 1;
GLES20.glActiveTexture( GLES20.GL_TEXTURE1 ); // GLES20.GL_TEXTURE1 <--> textureTexUnitIndex
GLES20.glBindTexture( GLES20.GL_TEXTURE_2D, textureHandle[textureIndex] );

int maskTexUnitIndex = 2;
GLES20.glActiveTexture( GLES20.GL_TEXTURE2 ); // GLES20.GL_TEXTURE2 <--> maskTexUnitIndex
GLES20.glBindTexture( GLES20.GL_TEXTURE_2D, ... ) // <-- here you have to add the texture handler of the texture
给墙涂上颜色 我有一个环境图像(例如,一个房间),还有一个全白色的遮罩,在墙上的>位置用黑色标记。 我想把这两幅图像混合在一起,得到结果(例如,把墙涂成红色)

我假设您的纹理是RGB纹理,并且遮罩是至少具有一个通道(R)的黑白纹理。 在这些条件下,片段着色器的外观必须如下所示:

precision mediump float;

varying LOWP vec4 v_color;
varying vec2 v_texCoord;

uniform sampler2D s_texture;
uniform sampler2D s_mask;

void main()
{
    vec3  texCol  = texture2D( s_texture, v_texCoord ).rgb;
    float maskCol = texture2D( s_mask, v_texCoord ).r;
    vec3 finalCol = s_texture.rgb * mix( v_color.rgb, vec3(1.0), maskCol );
    gl_FragColor  = vec4( finalCol, 1.0 );
}

这对我很有效,我需要实施更多的行为,但现在我可以进步了,这对我真的很有帮助