使用 ShaderMaterial 复制 MeshLambertMaterial 忽略纹理 [英] Replicating MeshLambertMaterial Using ShaderMaterial ignores textures

查看:18
本文介绍了使用 ShaderMaterial 复制 MeshLambertMaterial 忽略纹理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我注意到 THREE.js 在内部使用着色器来创建核心材质例如 MeshLambertMaterial",所以我决定将 Three.js 代码中的兰伯特着色器复制到一个新的着色器中并在其上构建.

I noticed that THREE.js uses shaders internally to create core material "e.g. MeshLambertMaterial", So I decided to copy the lambert shader from Three.js code into a new shader and build on it.

这是我得到的代码(忠实复制自 Three.js r66)

This is the code I got (Copied faithfully from Three.js r66)

THREE.MyShader = {

uniforms: THREE.UniformsUtils.merge( [
    THREE.UniformsLib[ "common" ],
    THREE.UniformsLib[ "fog" ],
    THREE.UniformsLib[ "lights" ],
    THREE.UniformsLib[ "shadowmap" ],
    {
        "ambient"  : { type: "c", value: new THREE.Color( 0xffffff ) },
        "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[ "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" ],

    "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[ "worldpos_vertex" ],
        THREE.ShaderChunk[ "envmap_vertex" ],
        THREE.ShaderChunk[ "lights_lambert_vertex" ],
        THREE.ShaderChunk[ "shadowmap_vertex" ],

    "}"

].join("
"),

fragmentShader: [

    "uniform float opacity;",

    "varying vec3 vLightFront;",

    "#ifdef DOUBLE_SIDED",

        "varying vec3 vLightBack;",

    "#endif",

    THREE.ShaderChunk[ "color_pars_fragment" ],
    THREE.ShaderChunk[ "map_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" ],



    "void main() {",

        "gl_FragColor = vec4( vec3 ( 1.0 ), opacity );",

        THREE.ShaderChunk[ "map_fragment" ],
        THREE.ShaderChunk[ "alphatest_fragment" ],
        THREE.ShaderChunk[ "specularmap_fragment" ],

        "#ifdef DOUBLE_SIDED",

            //"float isFront = float( gl_FrontFacing );",
            //"gl_FragColor.xyz *= isFront * vLightFront + ( 1.0 - isFront ) * vLightBack;",

            "if ( gl_FrontFacing )",
                "gl_FragColor.xyz *= vLightFront;",
            "else",
                "gl_FragColor.xyz *= vLightBack;",

        "#else",

            "gl_FragColor.xyz *= vLightFront;",

        "#endif",

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

        THREE.ShaderChunk[ "linear_to_gamma_fragment" ],

        THREE.ShaderChunk[ "fog_fragment" ],

    "}"

].join("
")

}

这是我用来设置制服和创建材料的代码.

and this is the code that I use to setup my uniforms and create the material.

var textureUsed = 'rock_1';
var texture = THREE.ImageUtils.loadTexture( texturePath + textureUsed + "/diffuse.png");
texture.wrapS   = THREE.RepeatWrapping;
texture.wrapT   = THREE.RepeatWrapping;
texture.repeat.x = 128;
texture.repeat.y = 128;
var shaderUniforms = THREE.UniformsUtils.clone( THREE.MyShader.uniforms );
shaderUniforms[ "map" ].value = texture;
var material =  new THREE.ShaderMaterial({
                    name: "TerrainShader",
                    uniforms    : shaderUniforms,
                    vertexShader: THREE.MyShader.vertexShader,
                    fragmentShader: THREE.MyShader.fragmentShader,
                    fog:false,
                    lights:true
                });

问题是,当我使用这些参数创建 MeshLambertMaterial 时,我得到了正确的照明和纹理重复,当我使用它创建 ShaderMaterial 时,灯光和阴影似乎在工作,但未加载纹理贴图解决这个问题我通过代码挖掘并设法通过在我的代码中添加这个丑陋的hack"来加载地图,就在材料定义之后

The problem is that when I use these parameters to create a MeshLambertMaterial I get the correct lighting and texture repetitions, when I use it to create ShaderMaterial the lights and shadows seem to be working but the texture map isn't loaded, to fix this I dug through the code and managed to get the map to load by adding this ugly "hack" to my code, right after the material definition

material.map = true;

现在纹理已加载并显示,但看起来纹理坐标混乱,而不是重复,着色器似乎忽略了我提供的重复值.

Now the texture is loaded and displayed but it looks like the texture coordinates are messed up, instead of repeating, the Shader seems to be ignoring the repeat values I supplied.

为什么我需要那个 hack 来处理我的纹理,我该怎么做才能获得正确的纹理重复?

Why did I need that hack to get my texture processed and what can I do to get the correct texture repetitions?

推荐答案

three.js 旨在易于使用,不易修改.这在未来可能会改变......

three.js was designed to be easy to use, not easy to modify. This may change in the future...

你需要像这样设置material.defines:

var defines = {};

defines[ "USE_MAP" ] = "";. 

然后在材质构造函数中指定defines.

Then specify defines in the material constructor.

var material =  new THREE.ShaderMaterial({
   name: "TerrainShader",
   defines     : defines,
   uniforms    : shaderUniforms,
   vertexShader: THREE.MyShader.vertexShader,
   fragmentShader: THREE.MyShader.fragmentShader,
   fog:false,
   lights:true
});

关于纹理重复,您需要将重复添加到您的制服中:

Regarding the texture repetitions, you need to add the repeat to your uniforms:

shaderUniforms[ "offsetRepeat" ].value.set( 0, 0, 2, 2 );

three.js r.66

three.js r.66

这篇关于使用 ShaderMaterial 复制 MeshLambertMaterial 忽略纹理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆