在 THREE.JS 中组合着色器

combining shaders in THREE.JS

我正在编写一个着色器来从高度图渲染地形并且一切顺利,除了在我拥有我的着色器之后我失去了灯光和阴影。这就是地狱般的痛苦开始的时候。我应该使用 THREE.ShaderChunk 添加默认着色器块,而不仅仅是添加 - 弄乱我的着色器。

所以经过长时间的谷歌搜索,我来到 this advise

You just need to add few snippets to your custom ShaderMaterial at proper places:

// uniforms

THREE.UniformsLib[ "shadowmap" ],

// fragment shader

THREE.ShaderChunk[ "shadowmap_pars_fragment" ], THREE.ShaderChunk[ "shadowmap_fragment" ],

// vertex shader

THREE.ShaderChunk[ "shadowmap_pars_vertex" ], THREE.ShaderChunk[ "shadowmap_vertex" ],

但对我来说,没有添加灯光和阴影。那么我能想到的最好的办法就是查看 ShaderLib.js 并尝试使用默认着色器之一的设置。所以我为 lambert 进行了设置,最后得到了这段代码:

        @tileMaterial = new THREE.ShaderMaterial
        uniforms:  THREE.UniformsUtils.merge [
            THREE.UniformsLib[ "common" ],
            THREE.UniformsLib[ "fog" ],
            THREE.UniformsLib[ "lights" ],
            THREE.UniformsLib[ "shadowmap" ],

            {
                "emissive" : { type: "c", value: new THREE.Color( 0x000000 ) },
                "wrapRGB"  : { type: "v3", value: new THREE.Vector3( 1, 1, 1 ) }
            }

        ]
        vertexShader: [
            "#define LAMBERT",

            "varying vec3 vLightFront;",

            "#ifdef DOUBLE_SIDED",

            "   varying vec3 vLightBack;",

            "#endif",

            THREE.ShaderChunk[ "common" ],
            THREE.ShaderChunk[ "map_pars_vertex" ],
            THREE.ShaderChunk[ "lightmap_pars_vertex" ],
            THREE.ShaderChunk[ "envmap_pars_vertex" ],
            THREE.ShaderChunk[ "lights_lambert_pars_vertex" ],
            THREE.ShaderChunk[ "color_pars_vertex" ],
            THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
            THREE.ShaderChunk[ "skinning_pars_vertex" ],
            THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
            THREE.ShaderChunk[ "logdepthbuf_pars_vertex" ],

            "void main() {",

                THREE.ShaderChunk[ "map_vertex" ],
                THREE.ShaderChunk[ "lightmap_vertex" ],
                THREE.ShaderChunk[ "color_vertex" ],

                THREE.ShaderChunk[ "morphnormal_vertex" ],
                THREE.ShaderChunk[ "skinbase_vertex" ],
                THREE.ShaderChunk[ "skinnormal_vertex" ],
                THREE.ShaderChunk[ "defaultnormal_vertex" ],

                THREE.ShaderChunk[ "morphtarget_vertex" ],
                THREE.ShaderChunk[ "skinning_vertex" ],
                THREE.ShaderChunk[ "default_vertex" ],
                THREE.ShaderChunk[ "logdepthbuf_vertex" ],

                THREE.ShaderChunk[ "worldpos_vertex" ],
                THREE.ShaderChunk[ "envmap_vertex" ],
                THREE.ShaderChunk[ "lights_lambert_vertex" ],
                THREE.ShaderChunk[ "shadowmap_vertex" ],

            "}"

        ].join "\n"
        fragmentShader: [
            "uniform vec3 diffuse;",
        "uniform vec3 emissive;",
        "uniform float opacity;",

        "varying vec3 vLightFront;",

        "#ifdef DOUBLE_SIDED",

        "   varying vec3 vLightBack;",

        "#endif",

        THREE.ShaderChunk[ "common" ],
        THREE.ShaderChunk[ "color_pars_fragment" ],
        THREE.ShaderChunk[ "map_pars_fragment" ],
        THREE.ShaderChunk[ "alphamap_pars_fragment" ],
        THREE.ShaderChunk[ "lightmap_pars_fragment" ],
        THREE.ShaderChunk[ "envmap_pars_fragment" ],
        THREE.ShaderChunk[ "fog_pars_fragment" ],
        THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
        THREE.ShaderChunk[ "specularmap_pars_fragment" ],
        THREE.ShaderChunk[ "logdepthbuf_pars_fragment" ],

        "void main() {",

        "   vec3 outgoingLight = vec3( 0.0 );",
        "   vec4 diffuseColor = vec4( diffuse, opacity );",

            THREE.ShaderChunk[ "logdepthbuf_fragment" ],
            THREE.ShaderChunk[ "map_fragment" ],
            THREE.ShaderChunk[ "color_fragment" ],
            THREE.ShaderChunk[ "alphamap_fragment" ],
            THREE.ShaderChunk[ "alphatest_fragment" ],
            THREE.ShaderChunk[ "specularmap_fragment" ],

        "   #ifdef DOUBLE_SIDED",


        "       if ( gl_FrontFacing )",
        "           outgoingLight += diffuseColor.rgb * vLightFront + emissive;",
        "       else",
        "           outgoingLight += diffuseColor.rgb * vLightBack + emissive;",

        "   #else",

        "       outgoingLight += diffuseColor.rgb * vLightFront + emissive;",

        "   #endif",

            THREE.ShaderChunk[ "lightmap_fragment" ],
            THREE.ShaderChunk[ "envmap_fragment" ],
            THREE.ShaderChunk[ "shadowmap_fragment" ],

            THREE.ShaderChunk[ "linear_to_gamma_fragment" ],

            THREE.ShaderChunk[ "fog_fragment" ],

        "   gl_FragColor = vec4( outgoingLight, diffuseColor.a );",

        "}"
        ].join "\n"
        attributes:
            height:
                type: "f"
                value: heightData
        wireframe: no

仍然没有添加光影并且还抛出错误:

three.js:22804 WebGL: INVALID_VALUE: uniform3fv: no array
three.js:22804 WebGL: INVALID_VALUE: uniform3fv: no array

所以问题是 - 将灯光和阴影添加到自定义着色器(对于 r71)的步骤是什么?

jsfiddle - http://jsfiddle.net/SET001/0wzqemks/2/

我的解决方案是将 lights: yes 添加到 ShaderMaterial