【问题标题】:Blend two textures with different coordinates and sizes in the same shader在同一着色器中混合具有不同坐标和大小的两个纹理
【发布时间】:2017-04-24 18:15:45
【问题描述】:

我的片段着色器中有两个具有不同坐标 尺寸的纹理:

varying highp vec2 v_currentTextureCoords;
varying highp vec2 v_backgroundTextureCoords;
uniform sampler2D u_currentTexture;
uniform sampler2D u_backgroundTexture;

void main()
{
    vec4 currentColor = texture2D(u_currentTexture, v_currentTextureCoords);
    vec4 backgroundColor = texture2D(u_backgroundTexture, v_backgroundTextureCoords);

    gl_FragColor = backgroundColor;
}

下面是对应的顶点着色器:

attribute vec4 a_position;
attribute vec2 a_currentTextureCoords;
attribute vec2 a_backgroundTextureCoords;
varying vec2 v_currentTextureCoords;
varying vec2 v_backgroundTextureCoords;

void main()
{
    gl_Position = a_position;
    v_currentTextureCoords = a_currentTextureCoords;
    v_backgroundTextureCoords = a_backgroundTextureCoords;
}

那些着色器负责渲染u_currentTexture

编辑:用我的真实应用程序(Android 应用程序)和问题更新了帖子。

正如您在上面看到的,这两个纹理是:

  • u_backgroundTexture:是视频流,全屏,大小为1080x1920
  • u_currentTexture:可以是任意图片,尺寸为469x833(较小相同比例)。

为了简单起见,目前,我不想混合任何东西,只是在u_currentTexture的着色器程序中显示u_backgroundTexture的像素 >.

如您所见,上面带有着色器的渲染图像(左上角,不是整个图像)与背景图像相同,但按比例缩小以适应较小的矩形。 这不是我想要的。

我想显示u_currentTexture“后面”的像素u_backgroundTexture 的像素),所以到最后,你甚至不会注意到有两个纹理。 p>

但由于纹理有不同的大小和坐标,它根本不会给出这个结果(现在,就是你在上面看到的)。

然后,在我的片段着色器中,我设法“缩放”纹理,使左上角的图像具有与背景图像相同的“缩放”:

为此,我修改了片段着色器:

varying highp vec2 v_currentTextureCoords;
varying highp vec2 v_backgroundTextureCoords;
uniform sampler2D u_currentTexture;
uniform sampler2D u_backgroundTexture;
uniform vec2 u_scaleRatio; // Notice here

void main()
{
    vec4 currentColor = texture2D(u_currentTexture, v_currentTextureCoords);
    vec4 backgroundColor = texture2D(u_backgroundTexture, v_backgroundTextureCoords * u_scaleRatio); // And here

    gl_FragColor = backgroundColor;
}

我在我的程序中将u_scaleRatio 设置为glUniform2fv()。这些值基本上是(伪代码):

u_scaleRatio = vec2(currentTextureWidth / backgroundTextureWidth, currentTextureHeight / backgroundTextureHeight);

如您所见,它几乎可以工作了,但看起来 X 轴上有一个 偏移:在顶部 left 角的渲染图像实际上是我们在右上角看到...我找不到纠正它的方法。

如果知道纹理具有不同的大小和坐标,如何修改我的着色器以便更正此偏移?

编辑 2:

要回答下面的评论,这是一个截图

vec4 backgroundColor = texture2D(u_backgroundTexture, v_currentTextureCoords);

并与:

vec4 backgroundColor = texture2D(u_backgroundTexture, v_currentTextureCoords * u_scaleRatio);

编辑 3: 回复this answer,这里是截图:

uniform vec2 texelSize; // (1.0/windowResolution.x, 1.0/windowResolution.y)

vec2 uv = gl_FragCoord.xy * texelSize;
vec4 backgroundColor = texture2D(u_backgroundTexture, uv);

我了解您要做什么,我认为如果两个纹理的顶点位置和纹理坐标相同,那么它会起作用,但是......它们不是。你知道如何解决它吗?

【问题讨论】:

  • 您可以使用不同大小的纹理发布您的结果。
  • 我不认为你的片段着色器给你正确的颜色。红色和蓝色相乘的结果是黑色。 vec4(1, 0, 0, 1) * vec4(0, 0, 1, 1) = vec4(0, 0, 0, 1) 您应该使用另一种混合方法,例如 mix 函数。
  • @eldo 我在原始帖子中添加了更多解释和屏幕截图。
  • 能否提供计算a_currentTextureCoords的代码?这可能就是失真的来源。
  • 纹理实际上并没有你认为的大小。这些纹理查找函数采用标准化坐标(如果纹理为 256x256 或 16x16,则 0-1 相同)。您始终可以将坐标限制在某个范围内,然后如果坐标超出所述范围,则将纹理视为半透明。这实际上就是边界纹素(已弃用)。

标签: android opengl-es glsl fragment-shader vertex-shader


【解决方案1】:

如果我正确理解你的问题,你应该可以计算

uniform vec2 texelSize; // (1.0/windowResolution.x, 1.0/windowResolution.y)

vec2 uv = gl_FragCoord.xy * texelSize;
vec4 backgroundColor = texture2D(u_backgroundTexture, uv);

内置变量gl_FragCoord.xy“包含片段的窗口相对坐标(x、y、z、1/w)值”https://www.opengl.org/sdk/docs/man/html/gl_FragCoord.xhtml)。由于您基本上需要片段的纹理坐标,就好像它是全屏四边形的一部分一样,这应该会给您预期的结果。您只需将全屏纹素的相对大小作为统一传递(查看注释部分以进行计算)。

【讨论】:

  • 我了解您要做什么,我认为如果两个纹理的顶点位置和纹理坐标相同,那么它会起作用,但是......它们不是。你知道如何解决它吗? PS:我用截图更新了我原来的帖子。
  • 您能否发布一些代码,您是如何实现我的建议的?
  • 这与我在原始帖子中发布的代码完全相同,只是我添加了uniform vec2 texelSize;vec2 uv = gl_FragCoord.xy * texelSize; 并将vec4 backgroundColor = ... 替换为您的行。当然,我将texelSize 设置为GLES20.glUniform2fv(mTexelSizeUniformLocation, 1, mTexelSize, 0);mTexelSizefloat 2 个元素的数组。
  • 你能截图看看当你按照建议计算uv然后写vec4 backgroundColor = vec4(uv, 0.0, 1.0);时会发生什么吗?我问这个是因为您可能需要反转 v 坐标。
  • 嗯,它是……绿色的。 i.stack.imgur.com/fiz9m.jpg你为什么问我这个? “查看”uv.xuv.y 值?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-27
  • 1970-01-01
  • 2018-06-26
  • 2013-04-21
  • 2012-03-05
  • 2014-03-14
相关资源
最近更新 更多