我正在尝试构建一个着色器,它允许您通过将渐变不透明蒙版应用于顶部的一个来组合两个图像,就像在photoshop中一样。我已经达到了可以将蒙面图像覆盖在另一个上面的程度,但是作为一个新手我对一些事情感到困惑。
似乎着色器内部的图像有时会倾斜以适合画布大小,并且它们始终从位置0,0开始。我已经找到了一些我发现尝试扩展纹理的片段,但总是得不到令人满意的结果。
我很好奇是否在视图中有大小,倾斜和翻译纹理的标准方法,或者GLSL中的图像是否必然以某种方式限制,这将阻止我完成目标
我也不确定我是如何应用渐变/蒙版的,如果这是正确的方法,因为我目前对渐变的形状没有很多控制。 / p>
这是我到目前为止所拥有的:
precision highp float;
varying vec2 uv;
uniform sampler2D originalImage;
uniform sampler2D image;
uniform vec2 resolution;
void main(){
float mask;
vec4 result;
vec2 position = gl_FragCoord.xy / ((resolution.x + resolution.y) * 2.0 );
mask = vec4(1.0,1.0,1.0,1.0 - position.x).a;
vec4 B = texture2D(image,uv);
vec4 A = texture2D(originalImage,uv) * (mask);
result = mix(B, A, A.a);
gl_FragColor = result;
}
产生如下图像:
我希望能够独立改变图像的位置,并确保它们符合适当的尺寸。
我试过天真地改变这样的立场:
vec2 pos = uv;
pos.y = pos.y + 0.25;
texture2D(image, pos)
哪个会移动纹理,但会导致一堆奇怪的线条拖动:
我试图像这样摆脱它们:
gl_FragColor = uv.y < 0.25 ? vec4(0.0,0.0,0.0,0.0) : result;
但它什么都不做
答案 0 :(得分:2)
当图像尺寸不同时,你真的需要决定你想要发生什么。您可能想要的是它出现没有图像所以检查您的UV坐标并在图像外使用0,0,0,0
//vec4 B = texture2D(image,uv);
vec4 getImage(sampler2D img, vec2 uv) {
if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) {
return vec4(0);
}
return texture2D(img, uv);
}
vec4 B = getImage(image, uv);
对于尺寸/倾斜/平移图像的标准方法,请使用矩阵
uniform mat4 u_imageMatrix;
...
vec2 newUv = u_imageMatrix * vec4(uv, 0, 1).xy;
An example of implementing canvas 2d's drawImage
using a texture matrix
总的来说,虽然我不认为大多数图像处理程序/库会尝试在着色器中执行所有操作。相反,他们用非常简单的原语构建图像。我最好的猜测是他们使用仅A * MASK
的着色器然后绘制B
,然后在A * MASK
上进行混合。
换句话说,如果你在Photoshop中有30层,他们就不会生成一个着色器,它可以在一个巨型着色器中同时计算所有30个层中的最终图像。相反,每个图层都将使用更简单的着色器自行应用。
我也希望他们为蒙版创建一个纹理,而不是在着色器中使用数学。这样,掩模可以是任意复杂的,而不仅仅是2级斜坡。
注意我不说你做错了。你可以自由地做任何你想做的事。我只是说我怀疑,如果你想构建一个通用的图像处理库,你可以用更小的构建块获得更多的成功,而不是试图在着色器中做更复杂的事情。
ps:我认为getImage
可以简化为
vec4 getImage(sampler2D img, vec2 uv) {
return texture2D(img, uv) * step(0.0, uv) * step(-1.0, -uv);
}