ThreeJS [r85]:带有Shadowmap的自定义着色器

Yen*_*nza 8 shader vertex-shader fragment-shader three.js shadow-mapping

我已经创建了一个自定义着色器,可以使用具有4种不同纹理的BlendMap,但我无法使用阴影/闪电效果来处理它.

我在这里错过了什么?或者是否有其他方法可以实现相同的功能?

下面的网格创建方法显示所有纹理正确混合.

// Creates the ground
function CreateGround() {
    var uniforms = THREE.UniformsUtils.merge([
        THREE.UniformsLib["lights"],
        THREE.UniformsLib["shadowmap"],
    {
        TextureBackground: { type: "t", value: null },
        TextureR: { type: "t", value: null },
        TextureG: { type: "t", value: null },
        TextureB: { type: "t", value: null },
        TextureBlendMap: { type: "t", value: null }
    }]);

    var shaderMaterial;
    try {
        shaderMaterial = new THREE.ShaderMaterial({
            lights: true,
            uniforms: uniforms,
            vertexShader: BlendMapVertexShader,
            fragmentShader: BlendMapFragmentShader
        });
    } catch (e) {
        alert("Error 'CreateGround' : GPU Shader couldn't compile");
    }


    shaderMaterial.uniforms.TextureBlendMap.value = _TextureBlendMap;
    shaderMaterial.uniforms.TextureBackground.value = _TextureSand;
    shaderMaterial.uniforms.TextureR.value = _TextureClay;
    shaderMaterial.uniforms.TextureG.value = _TextureClay;
    shaderMaterial.uniforms.TextureB.value = _TextureRock;

    var geometry = new THREE.BoxGeometry(GROUND_SIZE, GROUND_HEIGHT, GROUND_SIZE);
    var mesh = new THREE.Mesh(geometry, shaderMaterial);

    mesh.castShadow = false;
    mesh.receiveShadow = true;

    return mesh;
}
Run Code Online (Sandbox Code Playgroud)

这是我目前的着色器:

BlendMapVertexShader = [
THREE.ShaderChunk["shadowmap_pars_vertex"],
"varying vec2 vUv;",
"varying vec3 vPosition;",

"void main( void ) {",
    "vUv = uv;",
    "vPosition = position;",
    "gl_Position = projectionMatrix * modelViewMatrix * vec4(vPosition, 1);",

    THREE.ShaderChunk["begin_vertex"],
    THREE.ShaderChunk["worldpos_vertex"],
    THREE.ShaderChunk["shadowmap_vertex"],
"}",
].join("\n");

BlendMapFragmentShader = [
THREE.ShaderChunk["common"],
THREE.ShaderChunk["packing"],
THREE.ShaderChunk["shadowmap_pars_fragment"],

"varying vec2 vUv;",
"varying vec3 vPosition;",
"uniform sampler2D TextureBlendMap;",
"uniform sampler2D TextureBackground;",
"uniform sampler2D TextureR;",
"uniform sampler2D TextureG;",
"uniform sampler2D TextureB;",

"void main() {",

    "vec4 cBlend = texture2D(TextureBlendMap, vUv);",
    "float bText = 1.0 - (cBlend.r + cBlend.g + cBlend.b);",
    "vec2 tiledCoords = vUv * 40.0;",
    "vec4 cBack = texture2D(TextureBackground, tiledCoords) * bText;",
    "vec4 cR = texture2D(TextureR, tiledCoords) * cBlend.r;",
    "vec4 cG = texture2D(TextureG, tiledCoords) * cBlend.g;",
    "vec4 cB = texture2D(TextureB, tiledCoords) * cBlend.b;",
    "vec4 cTot = cBack + cR + cG + cB;",
    "gl_FragColor = cTot;",
    THREE.ShaderChunk["shadowmap_fragment"],
"}",
].join("\n");
Run Code Online (Sandbox Code Playgroud)

我在浏览器中没有错误或警告.

three.js r85Dev

Yen*_*nza 1

好吧。我最终复制了 PHONG 着色器,然后覆盖漫反射颜色输入。解决方案如下。

这是使用 BlendMapShader 创建网格的方法

// Creates the ground
function CreateGround(material) {
    var uniforms = THREE.UniformsUtils.merge([
        THREE.UniformsLib["common"],
        THREE.UniformsLib["aomap"],
        THREE.UniformsLib["lightmap"],
        THREE.UniformsLib["emissivemap"],
        THREE.UniformsLib["bumpmap"],
        THREE.UniformsLib["normalmap"],
        THREE.UniformsLib["displacementmap"],
        THREE.UniformsLib["gradientmap"],
        THREE.UniformsLib["fog"],
        THREE.UniformsLib["lights"],
    {
        emissive: { type: "c", value: new THREE.Color(0x000000) },
        specular: { type: "c", value: new THREE.Color(0x111111) },
        shininess: { type: "f", value: 30 },

        TextureBackground: { type: "t", value: null },
        TextureR: { type: "t", value: null },
        TextureG: { type: "t", value: null },
        TextureB: { type: "t", value: null },
        TextureBlendMap: { type: "t", value: null },
    }]);

    var shaderMaterial;
    try {
        shaderMaterial = new THREE.ShaderMaterial({
            lights: true,
            uniforms: uniforms,
            vertexShader: BlendMapVertexShader,
            fragmentShader: BlendMapFragmentShader
        });
    } catch (e) {
        alert("Error 'CreateGround' : GPU Shader couldn't compile");
    }

    shaderMaterial.uniforms.TextureBlendMap.value = _TextureBlendMap;
    shaderMaterial.uniforms.TextureBackground.value = _TextureSand;
    shaderMaterial.uniforms.TextureR.value = _TextureClay;
    shaderMaterial.uniforms.TextureG.value = _TextureGrass;
    shaderMaterial.uniforms.TextureB.value = _TextureSandRock;

    var geometry = new THREE.BoxGeometry(GROUND_SIZE, GROUND_HEIGHT, GROUND_SIZE);
    var mesh = new THREE.Mesh(geometry, shaderMaterial);

    mesh.castShadow = false;
    mesh.receiveShadow = true;

    return mesh;
}
Run Code Online (Sandbox Code Playgroud)

这是修改后的 PHONG 着色器:

BlendMapVertexShader = [
"#define PHONG",

"varying vec3 vViewPosition;",
"varying vec2 vUv;",

"#ifndef FLAT_SHADED",

"varying vec3 vNormal;",

"#endif",


THREE.ShaderChunk["common"],
THREE.ShaderChunk["uv_pars_vertex"],
THREE.ShaderChunk["uv2_pars_vertex"],
THREE.ShaderChunk["displacementmap_pars_vertex"],
THREE.ShaderChunk["envmap_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"],
THREE.ShaderChunk["clipping_planes_pars_vertex"],

"void main() {",
    THREE.ShaderChunk["uv_vertex"],
    THREE.ShaderChunk["uv2_vertex"],
    THREE.ShaderChunk["color_vertex"],

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

    "#ifndef FLAT_SHADED // Normal computed with derivatives when FLAT_SHADED",

        "vNormal = normalize( transformedNormal );",

    "#endif",
    THREE.ShaderChunk["begin_vertex"],
    THREE.ShaderChunk["displacementmap_vertex"],
    THREE.ShaderChunk["morphtarget_vertex"],
    THREE.ShaderChunk["skinning_vertex"],
    THREE.ShaderChunk["project_vertex"],
    THREE.ShaderChunk["logdepthbuf_vertex"],
    THREE.ShaderChunk["clipping_planes_vertex"],

    "vUv = uv;",
    "vViewPosition = - mvPosition.xyz;",

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

"}",
].join("\n");

BlendMapFragmentShader = [
"#define PHONG",

"varying vec2 vUv;",

"uniform vec3 diffuse;",
"uniform vec3 emissive;",
"uniform vec3 specular;",
"uniform float shininess;",
"uniform float opacity;",

"uniform sampler2D TextureBlendMap;",
"uniform sampler2D TextureBackground;",
"uniform sampler2D TextureR;",
"uniform sampler2D TextureG;",
"uniform sampler2D TextureB;",

THREE.ShaderChunk["common"],
THREE.ShaderChunk["packing"],
THREE.ShaderChunk["color_pars_fragment"],
THREE.ShaderChunk["uv_pars_fragment"],
THREE.ShaderChunk["uv2_pars_fragment"],
THREE.ShaderChunk["map_pars_fragment"],
THREE.ShaderChunk["alphamap_pars_fragment"],
THREE.ShaderChunk["aomap_pars_fragment"],
THREE.ShaderChunk["lightmap_pars_fragment"],
THREE.ShaderChunk["emissivemap_pars_fragment"],
THREE.ShaderChunk["envmap_pars_fragment"],
THREE.ShaderChunk["fog_pars_fragment"],
THREE.ShaderChunk["bsdfs"],
THREE.ShaderChunk["lights_pars"],
THREE.ShaderChunk["lights_phong_pars_fragment"],
THREE.ShaderChunk["shadowmap_pars_fragment"],
THREE.ShaderChunk["bumpmap_pars_fragment"],
THREE.ShaderChunk["normalmap_pars_fragment"],
THREE.ShaderChunk["specularmap_pars_fragment"],
THREE.ShaderChunk["logdepthbuf_pars_fragment"],
THREE.ShaderChunk["clipping_planes_pars_fragment"],

"void main() {",

    THREE.ShaderChunk["clipping_planes_fragment"],
    "// THIS IS CUSTOM CODE TO OVERRIDE THE DIFFUSE COLOR WITH BLENDMAP TEXTURES",
    "vec4 cBlend = texture2D(TextureBlendMap, vUv);",
    "float bText = 1.0 - (cBlend.r + cBlend.g + cBlend.b);",
    "vec2 tiledCoords = vUv * 40.0;",
    "vec4 cBack = texture2D(TextureBackground, tiledCoords) * bText;",
    "vec4 cR = texture2D(TextureR, tiledCoords) * cBlend.r;",
    "vec4 cG = texture2D(TextureG, tiledCoords) * cBlend.g;",
    "vec4 cB = texture2D(TextureB, tiledCoords) * cBlend.b;",
    "vec4 cTot = cBack + cR + cG + cB;",

    "vec4 diffuseColor = vec4( diffuse, opacity );",
    "diffuseColor.r = cTot.r;",
    "diffuseColor.g = cTot.g;",
    "diffuseColor.b = cTot.b;",
    "ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );",
    "vec3 totalEmissiveRadiance = emissive;",

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

    "// accumulation",
    THREE.ShaderChunk["lights_phong_fragment"],
    THREE.ShaderChunk["lights_template"],

    "// modulation",
    THREE.ShaderChunk["aomap_fragment"],

    "vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;",

    THREE.ShaderChunk["envmap_fragment"],

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

    THREE.ShaderChunk["premultiplied_alpha_fragment"],
    THREE.ShaderChunk["tonemapping_fragment"],
    THREE.ShaderChunk["encodings_fragment"],
    THREE.ShaderChunk["fog_fragment"],
"}",
 ].join("\n");
Run Code Online (Sandbox Code Playgroud)