我该如何在iPhone上的OpenGL ES 2.0中混合具有不同坐标的两个纹理?

9

当两个纹理覆盖相同的矩形时,我可以在片段着色器中使用不同的混合模式混合两个纹理。但是现在我的问题是,一个纹理是没有旋转的普通矩形,而另一个纹理是旋转/缩放和平移的另一个矩形。我该如何按照想要的方式合并这些纹理?(如下图所示)

我知道如何做到这一点...

enter image description here

但不确定如何做到这一点...

enter image description here

为了混合第一张图片中的纹理,我使用了以下代码...

Objective C 代码...

- (void) display {
    [EAGLContext setCurrentContext:context];

    glBindFramebuffer(GL_FRAMEBUFFER, targetFBO);

    glUseProgram(program);

    glActiveTexture(GL_TEXTURE2);
    glBindTexture(GL_TEXTURE_2D, textureTop);

    glActiveTexture(GL_TEXTURE3);
    glBindTexture(GL_TEXTURE_2D, textureBot);

    glUniform1i(inputTextureTop, 2);
    glUniform1i(inputTextureBot, 3);

    glUniform1f(alphaTop, alpha);

    glEnable (GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    glVertexAttribPointer(position, 2, GL_FLOAT, 0, 0, imageVertices);
    glVertexAttribPointer(inputTextureCoordinate, 2, GL_FLOAT, 0, 0, textureCoordinates);

    glClearColor(0.0, 0.0, 0.0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
    [context presentRenderbuffer:GL_RENDERBUFFER];
}

Vertex shader...

 attribute vec4 position;
 attribute vec4 inputTextureCoordinate;

 varying vec2 textureCoordinate;

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

Fragment shader...

varying highp vec2 textureCoordinate;

uniform sampler2D inputTextureTop;
uniform sampler2D inputTextureBot;

uniform highp float alphaTop;

void main()
{
    lowp vec4 pixelTop = texture2D(inputTextureTop, textureCoordinate);
    lowp vec4 pixelBot = texture2D(inputTextureBot, textureCoordinate);

    gl_FragColor = someBlendOperation(pixelTop, pixelBot);
}

也许我可以在片段着色器中进行一些几何操作,以获取顶部像素的XY。 - abix
3
你好,我遇到了同样的问题,@Max的解决方案似乎不能满足需要以不同的大小和旋转角度绘制顶部图片和背景图片的要求,你是如何处理的呢? - Eyal
2个回答

8
您需要向着色器传递2个纹理坐标并修改着色器。 请将以下内容添加到ObjectiveC中。
glVertexAttribPointer(inputTextureCoordinate2, 2, GL_FLOAT, 0, 0, textureCoordinates2);

顶点着色器

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;
}

片段着色器

varying highp vec2 textureCoordinate;
varying highp vec2 textureCoordinate2;

uniform sampler2D inputTextureTop;
uniform sampler2D inputTextureBot;

uniform highp float alphaTop;

void main()
{
    lowp vec4 pixelTop = texture2D(inputTextureTop, textureCoordinate);
    lowp vec4 pixelBot = texture2D(inputTextureBot, textureCoordinate2);

    gl_FragColor = someBlendOperation(pixelTop, pixelBot);
}

顺便说一下,inputTextureCoordinate不一定是vec4,它也可以是vec2。


谢谢 Max!运行得很好! - abix
@Max,我有一个类似的问题,你能帮我解决一下吗?谢谢。 - Ragunath Jawahar
2
你把它发布到了哪里吗? - Max
1
我遇到了同样的问题,@Max你的解决方案如何处理需要以不同的大小和旋转绘制顶部图像和背景图像的需求? - Eyal
我建议您发布问题并描述所有内容。您可以在屏幕上绘制一张图像,然后在其上绘制第二张图像,或者您可以在着色器中混合2个纹理。当您考虑着色器时,应了解您绘制单个三角形,而完整的图像有许多三角形。因此,第一个解决方案可能更简单。 - Max
1
@Max 在你的回答中,我假设有两个三角形组成一个与较大纹理相同大小的矩形;这两个纹理将仅包裹在此单个矩形上。现在,较大纹理的纹理坐标是微不足道的,但较小纹理的纹理坐标会是什么呢?比如在问题中,为了得到第二张图片作为输出,左上顶点(猴子)的纹理坐标会是多少? - legends2k

5
如果您要在同一图元上混合两个纹理,则可以在着色器中混合颜色。
但是,如果您想混合两个不同的图元,则真正需要使用的是硬件混合(GL_BLEND)。
首先单独绘制底部图片,然后启用混合并绘制顶部图片。顶部图片的透明度值控制其透明度。
由于两个四边形不使用相同的坐标,因此您不需要尝试在同一个绘制调用中绘制它们。

1
是的,我可以做到。但是使用GL_BLEND,我只能进行一定数量的混合操作。我真正想做的是自己定义混合公式(就像Photoshop混合模式...乘法、叠加、屏幕等)。我在想如果我可以在将其传递给texture2D(inputTextureTop,textureCoordinate)函数之前对textureCoordinate.xy进行一些二维变换,使其旋转、平移和缩放呢? - abix
abix,我有一些OpenCL代码,用于对目标像素进行源坐标的反向转换查找。这里是一个Gist链接:https://gist.github.com/victusfate/bdbed266a73a19f81a94 - Mark Essel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接