如果在 fragment 着色器中混合两个不同大小的纹理,是否可以将纹理映射到不同的坐标?
例如,如果混合来自以下两个图像的纹理:
使用以下着色器:
// Vertex shader
uniform mat4 uMVPMatrix;
attribute vec4 vPosition;
attribute vec2 aTexcoord;
varying vec2 vTexcoord;
void main() {
gl_Position = uMVPMatrix * vPosition;
vTexcoord = aTexcoord;
}
// Fragment shader
uniform sampler2D uContTexSampler;
uniform sampler2D uMaskTextSampler;
varying vec2 vTexcoord;
void main() {
vec4 mask = texture2D(uMaskTextSampler, vTexcoord);
vec4 text = texture2D(uContTexSampler, vTexcoord);
gl_FragColor = vec4(text.r * mask.r), text.g * mask.r, text.b * mask.r, text.a * mask.r);
}
( fragment 着色器用第二个纹理替换黑白蒙版的空白区域)。
由于两个纹理使用相同的 gl_Position 和坐标(1.0f、1.0f、1.0f、0.0f、0.0f、1.0f、0.0f、0.0f),两个纹理在 View 中映射到相同的坐标:
不过,我的目标是保持原来的纹理比例:
我想在着色器中实现这一点,而不是 glBlendFunc
和 glBlendFuncSeparate
,以便我自己的混合值。
有没有办法在 GLSL 中实现这一点?我有一种感觉,我为不同位置坐标混合纹理顶点的方法被设计破坏了...
最佳答案
这确实是可能的,但你需要为蒙版纹理坐标获得一个 2D 比例向量。我建议您在 CPU 上计算它们并通过统一将它们发送到着色器,替代方法是按顶点甚至每个 fragment 计算它们,但您仍然需要将图像尺寸传递给着色器,所以只需在 CPU 上执行并添加制服。
要获得该比例矢量,您需要一些简单的数学知识。你想要做的是尊重蒙版比例但缩放它所以 2 个比例坐标之一是 1.0
另一个是<=1.0
.这意味着您将看到整个 mask 的宽度或高度,而相反的尺寸将按比例缩小。例如,如果您有一个大小为 1.0x1.0 的图像和一个大小为 2.0x1.0 的 mask ,您的缩放向量将为 (.5, 1.0)。
使用这个scaleVector
你只需要乘以纹理坐标:
vec4 mask = texture2D(uMaskTextSampler, vTexcoord* scaleVector);
要计算比例向量试试这个:
float imageWidth;
float imageHeight;
float maskWidth;
float maskHeight;
float imageRatio = imageWidth/imageHeight;
float maskRatio = maskWidth/maskHeight;
float scaleX, scaleY;
if(imageRatio/maskRatio > 1.0f) {
//x will be 1.0
scaleX = 1.0f;
scaleY = 1.0f/(imageRatio/maskRatio);
}
else {
//y will be 1.0
scaleX = imageRatio/maskRatio;
scaleY = 1.0f;
}
请注意,我没有尝试过此代码,因此您可能需要尝试一下。
编辑:缩放纹理坐标修复
上面的纹理坐标比例使得 mask 纹理使用左上部分而不是中心部分。坐标必须围绕中心缩放。这意味着从中心获取原始向量 vTexcoord-vec2(.5,.5)
然后缩放此向量并将其从中心添加回来:
vec2 fromCentre = vTexcoord-vec2(.5,.5);
vec2 scaledFromCenter = fromCenter*scaleVector;
vec2 resultCoordinate = vec2(.5,.5) + scaledFromCenter;
你可以把它放在一行中,甚至可以试着缩短一点(先在纸上做)。
关于android - 在 GLSL 中混合不同大小/坐标的纹理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24651369/