具有 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>