具有 alpha 且无乘法的 GLSL 分层纹理
GLSL layering textures with alpha and no multiplication
我希望那里可能有一位 GLSL 大师可以帮助解决这个问题,
我正在尝试使用三个单独的纹理作为 alpha 通道(黑白图像)将三个纹理混合在一起,我希望它们堆叠在彼此之上而不增加下面一个的亮度,但我使用 threejs 和着色器材质 class。我可以成功地将 opactiy 映射到每一层上,但是当我尝试将它们组合在一起时,它们似乎会奇怪地相乘和混合(这意味着在顶部应用每一层图像会变得更亮)
我在下面使用的纹理示例...
扩散:
Alpha 贴图(黑白):
我的片段着色器就是这样.....
#ifdef GL_ES
precision highp float;
#endif
uniform sampler2D tOne;
uniform sampler2D tSec;
uniform sampler2D tThi;
uniform sampler2D aOne;
uniform sampler2D aSec;
uniform sampler2D aThi;
varying vec2 vUv;
void main(void)
{
vec3 c;
vec3 d;
vec3 e;
vec3 f;
vec3 m1;
vec3 m2;
vec4 Ca = texture2D(tOne, vUv);
vec4 Cb = texture2D(tSec, vUv);
vec4 Cc = texture2D(tThi, vUv);
vec4 Aa = texture2D(aOne, vUv);
vec4 Ab = texture2D(aSec, vUv);
vec4 Ac = texture2D(aThi, vUv);
c = (Ca.rgb * Aa.rgb)*1.0;
d = (Cb.rgb * Ab.rgb)*1.0;
e = (Cc.rgb * Ac.rgb)*1.0;
f = (c.rgb + d.rgb + e.rgb * (1.0))*1.0;
gl_FragColor= vec4(f, 1.0);
}
如果我运行它与……
gl_FragColor= vec4(c, 1.0);
结果:
或
gl_FragColor= vec4(d, 1.0);
结果:
或
gl_FragColor= vec4(e, 1.0);
结果:
我可以看到每个图层都具有正确的不透明度和 rgb 值
但正如我所说,我无法将它们组合起来以保持正确的 rgb 值,它们现在似乎成倍增加并变得更亮。
我在某处读到有关指定混合模式为默认打开的内容。但我不确定你如何在 threejs 之类的东西上关闭它。
当前结果:
期望的结果:
或者我的计算可能只需要修复层的组合
如有任何帮助,我们将不胜感激?
谢谢大家的宝贵时间!
-里斯·托马斯
成功了!!
MarGenDo - 你是 star!!! ,你是对的,我必须开始添加 alpha 的反转部分,以便它进入下一层。
一切正常,按照您的建议修改了 alpha!
正确的字母:
尽管我确定我可以尝试将 alpha 与着色器合并,但您的逻辑绝对合理!
再次感谢MarGenDo
所以再次工作
首先感谢 MarGenDo 和传说中的 gman,对我来说最有效的解决方案是 gmans,因为我无法处理 minus'ing alpha 等,mix 命令工作得很好!!!此外,如果您想实际查看它,请查看 http://www.polygonprophecy.com/html5/Island - 在 phone 上查看效果最佳,因为它允许您放大和缩小(捏合和打孔)以及绕岛旋转(两个手指旋转),它现在非常快速地使用良好的着色器编程(再次感谢你们!!!),希望在糟糕的 phones 上也能快速工作! gman 你是个该死的明星!!
请注意,这是我的最终结果着色器:-
#ifdef GL_ES
precision highp float;
#endif
uniform sampler2D tOne;
uniform sampler2D tSec;
uniform sampler2D tThi;
uniform sampler2D aOne;
uniform sampler2D aSec;
uniform sampler2D aThi;
varying vec2 vUv;
void main(void)
{
vec4 Ca = texture2D(tOne, vUv);
vec4 Cb = texture2D(tSec, vUv);
vec4 Cc = texture2D(tThi, vUv);
vec4 Aa = texture2D(aOne, vUv);
vec4 Ab = texture2D(aSec, vUv);
vec4 Ac = texture2D(aThi, vUv);
vec4 g;
g = vec4(0);
g = mix(g, Ca, Aa);
g = mix(g, Cb, Ab);
g = mix(g, Cc, Ac);
gl_FragColor= vec4(g.rgb, Aa.rgb+Ab.rgb+Ac.rgb);
}
嗯,您的问题出在您的 alpha 纹理上。你必须稍微改变它们。例如在中间,您将所有三个纹理的颜色值相加,但您只想看到其中一个(岩石纹理)。除了岩石之外的每个 alpha 纹理中间应该是黑色的。
这是沙子 alpha 纹理的示例。
(对不起,我画得丑,但我希望你明白我的意思)
我认为这可能适用于您的原始 alpha 纹理
vec4 Ca = texture2D(tOne, vUv);
vec4 Cb = texture2D(tSec, vUv);
vec4 Cc = texture2D(tThi, vUv);
vec4 Aa = texture2D(aOne, vUv);
vec4 Ab = texture2D(aSec, vUv);
vec4 Ac = texture2D(aThi, vUv);
// This is the default color.
// The color when all the alphas are zero
f = vec4(0);
f = mix(f, Ca, Aa);
f = mix(f, Cb, Ab);
f = mix(f, Cc, Ac);
gl_FragColor= vec4(f, 1.0);
试用
"use strict";
var gl = twgl.getWebGLContext(document.getElementById("c"));
var programInfo = twgl.createProgramInfo(gl, ["vs", "fs"]);
var arrays = {
position: [-1, -1, 0, 1, -1, 0, -1, 1, 0, -1, 1, 0, 1, -1, 0, 1, 1, 0],
};
var bufferInfo = twgl.createBufferInfoFromArrays(gl, arrays);
var textures = twgl.createTextures(gl, {
tOne: { src: "https://i.imgur.com/P5bZckC.jpg", crossOrigin: "", },
tSec: { src: "https://i.imgur.com/2FI5CHY.jpg", crossOrigin: "", },
tThi: { src: "https://i.imgur.com/YV0Wrxn.jpg", crossOrigin: "", },
aOne: { src: "https://i.imgur.com/Kzk0cEx.jpg", crossOrigin: "", },
aSec: { src: "https://i.imgur.com/weFi9dr.jpg", crossOrigin: "", },
aThi: { src: "https://i.imgur.com/Ebkh1j1.jpg", crossOrigin: "", },
}, function() {
var uniforms = {
tOne: textures.tOne,
tSec: textures.tSec,
tThi: textures.tThi,
aOne: textures.aOne,
aSec: textures.aSec,
aThi: textures.aThi,
};
gl.useProgram(programInfo.program);
twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
twgl.setUniforms(programInfo, uniforms);
twgl.drawBufferInfo(gl, gl.TRIANGLES, bufferInfo);
});
<script id="vs" type="notjs">
attribute vec4 position;
varying vec2 vUv;
void main() {
gl_Position = position;
vUv = position.xy * 0.5 + 0.5;
}
</script>
<script id="fs" type="notjs">
precision mediump float;
uniform sampler2D tOne;
uniform sampler2D tSec;
uniform sampler2D tThi;
uniform sampler2D aOne;
uniform sampler2D aSec;
uniform sampler2D aThi;
varying vec2 vUv;
void main(void)
{
vec4 f;
vec4 Ca = texture2D(tOne, vUv);
vec4 Cb = texture2D(tSec, vUv);
vec4 Cc = texture2D(tThi, vUv);
vec4 Aa = texture2D(aOne, vUv);
vec4 Ab = texture2D(aSec, vUv);
vec4 Ac = texture2D(aThi, vUv);
// This is the default color.
// The color when all the alphas are zero
f = vec4(0);
f = mix(f, Ca, Aa);
f = mix(f, Cb, Ab);
f = mix(f, Cc, Ac);
gl_FragColor= vec4(f.rgb, 1.0);
}
</script>
<script src="https://twgljs.org/dist/twgl.min.js"></script>
<canvas id="c" width="128" height="128"></canvas>
我希望那里可能有一位 GLSL 大师可以帮助解决这个问题, 我正在尝试使用三个单独的纹理作为 alpha 通道(黑白图像)将三个纹理混合在一起,我希望它们堆叠在彼此之上而不增加下面一个的亮度,但我使用 threejs 和着色器材质 class。我可以成功地将 opactiy 映射到每一层上,但是当我尝试将它们组合在一起时,它们似乎会奇怪地相乘和混合(这意味着在顶部应用每一层图像会变得更亮)
我在下面使用的纹理示例...
扩散:
Alpha 贴图(黑白):
我的片段着色器就是这样.....
#ifdef GL_ES
precision highp float;
#endif
uniform sampler2D tOne;
uniform sampler2D tSec;
uniform sampler2D tThi;
uniform sampler2D aOne;
uniform sampler2D aSec;
uniform sampler2D aThi;
varying vec2 vUv;
void main(void)
{
vec3 c;
vec3 d;
vec3 e;
vec3 f;
vec3 m1;
vec3 m2;
vec4 Ca = texture2D(tOne, vUv);
vec4 Cb = texture2D(tSec, vUv);
vec4 Cc = texture2D(tThi, vUv);
vec4 Aa = texture2D(aOne, vUv);
vec4 Ab = texture2D(aSec, vUv);
vec4 Ac = texture2D(aThi, vUv);
c = (Ca.rgb * Aa.rgb)*1.0;
d = (Cb.rgb * Ab.rgb)*1.0;
e = (Cc.rgb * Ac.rgb)*1.0;
f = (c.rgb + d.rgb + e.rgb * (1.0))*1.0;
gl_FragColor= vec4(f, 1.0);
}
如果我运行它与……
gl_FragColor= vec4(c, 1.0);
结果:
或
gl_FragColor= vec4(d, 1.0);
结果:
或
gl_FragColor= vec4(e, 1.0);
结果:
我可以看到每个图层都具有正确的不透明度和 rgb 值 但正如我所说,我无法将它们组合起来以保持正确的 rgb 值,它们现在似乎成倍增加并变得更亮。
我在某处读到有关指定混合模式为默认打开的内容。但我不确定你如何在 threejs 之类的东西上关闭它。
当前结果:
期望的结果:
或者我的计算可能只需要修复层的组合
如有任何帮助,我们将不胜感激?
谢谢大家的宝贵时间!
-里斯·托马斯
成功了!!
MarGenDo - 你是 star!!! ,你是对的,我必须开始添加 alpha 的反转部分,以便它进入下一层。
一切正常,按照您的建议修改了 alpha!
正确的字母:
尽管我确定我可以尝试将 alpha 与着色器合并,但您的逻辑绝对合理!
再次感谢MarGenDo
所以再次工作
首先感谢 MarGenDo 和传说中的 gman,对我来说最有效的解决方案是 gmans,因为我无法处理 minus'ing alpha 等,mix 命令工作得很好!!!此外,如果您想实际查看它,请查看 http://www.polygonprophecy.com/html5/Island - 在 phone 上查看效果最佳,因为它允许您放大和缩小(捏合和打孔)以及绕岛旋转(两个手指旋转),它现在非常快速地使用良好的着色器编程(再次感谢你们!!!),希望在糟糕的 phones 上也能快速工作! gman 你是个该死的明星!!
请注意,这是我的最终结果着色器:-
#ifdef GL_ES
precision highp float;
#endif
uniform sampler2D tOne;
uniform sampler2D tSec;
uniform sampler2D tThi;
uniform sampler2D aOne;
uniform sampler2D aSec;
uniform sampler2D aThi;
varying vec2 vUv;
void main(void)
{
vec4 Ca = texture2D(tOne, vUv);
vec4 Cb = texture2D(tSec, vUv);
vec4 Cc = texture2D(tThi, vUv);
vec4 Aa = texture2D(aOne, vUv);
vec4 Ab = texture2D(aSec, vUv);
vec4 Ac = texture2D(aThi, vUv);
vec4 g;
g = vec4(0);
g = mix(g, Ca, Aa);
g = mix(g, Cb, Ab);
g = mix(g, Cc, Ac);
gl_FragColor= vec4(g.rgb, Aa.rgb+Ab.rgb+Ac.rgb);
}
嗯,您的问题出在您的 alpha 纹理上。你必须稍微改变它们。例如在中间,您将所有三个纹理的颜色值相加,但您只想看到其中一个(岩石纹理)。除了岩石之外的每个 alpha 纹理中间应该是黑色的。
这是沙子 alpha 纹理的示例。
(对不起,我画得丑,但我希望你明白我的意思)
我认为这可能适用于您的原始 alpha 纹理
vec4 Ca = texture2D(tOne, vUv);
vec4 Cb = texture2D(tSec, vUv);
vec4 Cc = texture2D(tThi, vUv);
vec4 Aa = texture2D(aOne, vUv);
vec4 Ab = texture2D(aSec, vUv);
vec4 Ac = texture2D(aThi, vUv);
// This is the default color.
// The color when all the alphas are zero
f = vec4(0);
f = mix(f, Ca, Aa);
f = mix(f, Cb, Ab);
f = mix(f, Cc, Ac);
gl_FragColor= vec4(f, 1.0);
试用
"use strict";
var gl = twgl.getWebGLContext(document.getElementById("c"));
var programInfo = twgl.createProgramInfo(gl, ["vs", "fs"]);
var arrays = {
position: [-1, -1, 0, 1, -1, 0, -1, 1, 0, -1, 1, 0, 1, -1, 0, 1, 1, 0],
};
var bufferInfo = twgl.createBufferInfoFromArrays(gl, arrays);
var textures = twgl.createTextures(gl, {
tOne: { src: "https://i.imgur.com/P5bZckC.jpg", crossOrigin: "", },
tSec: { src: "https://i.imgur.com/2FI5CHY.jpg", crossOrigin: "", },
tThi: { src: "https://i.imgur.com/YV0Wrxn.jpg", crossOrigin: "", },
aOne: { src: "https://i.imgur.com/Kzk0cEx.jpg", crossOrigin: "", },
aSec: { src: "https://i.imgur.com/weFi9dr.jpg", crossOrigin: "", },
aThi: { src: "https://i.imgur.com/Ebkh1j1.jpg", crossOrigin: "", },
}, function() {
var uniforms = {
tOne: textures.tOne,
tSec: textures.tSec,
tThi: textures.tThi,
aOne: textures.aOne,
aSec: textures.aSec,
aThi: textures.aThi,
};
gl.useProgram(programInfo.program);
twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
twgl.setUniforms(programInfo, uniforms);
twgl.drawBufferInfo(gl, gl.TRIANGLES, bufferInfo);
});
<script id="vs" type="notjs">
attribute vec4 position;
varying vec2 vUv;
void main() {
gl_Position = position;
vUv = position.xy * 0.5 + 0.5;
}
</script>
<script id="fs" type="notjs">
precision mediump float;
uniform sampler2D tOne;
uniform sampler2D tSec;
uniform sampler2D tThi;
uniform sampler2D aOne;
uniform sampler2D aSec;
uniform sampler2D aThi;
varying vec2 vUv;
void main(void)
{
vec4 f;
vec4 Ca = texture2D(tOne, vUv);
vec4 Cb = texture2D(tSec, vUv);
vec4 Cc = texture2D(tThi, vUv);
vec4 Aa = texture2D(aOne, vUv);
vec4 Ab = texture2D(aSec, vUv);
vec4 Ac = texture2D(aThi, vUv);
// This is the default color.
// The color when all the alphas are zero
f = vec4(0);
f = mix(f, Ca, Aa);
f = mix(f, Cb, Ab);
f = mix(f, Cc, Ac);
gl_FragColor= vec4(f.rgb, 1.0);
}
</script>
<script src="https://twgljs.org/dist/twgl.min.js"></script>
<canvas id="c" width="128" height="128"></canvas>