2014-02-21 98 views
7

我注意到THREE.js内部使用着色器来创建核心材质“例如MeshLambertMaterial”,所以我决定将来自Three.js代码的lambert着色器复制到新的着色器中并在其上构建。使用ShaderMaterial复制MeshLambertMaterial忽略纹理

这是我得到的代码(从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("\n"), 

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("\n") 

} 

,这是我用它来设置我的制服和创造物质的代码。

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的灯光和阴影似乎工作,但纹理贴图ISN”牛逼装,要解决这个问题我通过代码挖掘和管理,以获取地图加入这个丑陋的“黑客”我的代码,材料定义之后

material.map = true; 

现在纹理加载并显示加载但它看起来像纹理坐标混乱了,而不是重复,Shader似乎忽略了我提供的重复值。

为什么我需要黑客来处理我的纹理,以及我能做些什么来获得正确的纹理重复?

+3

three.js所被设计成易于使用,不容易修改。这可能会在将来发生变化......作为开始,尝试添加'material.defines'就像这样:'var defines = {};定义[“USE_MAP”] =“”;'。在材质构造函数中指定'定义:定义',看看是否有帮助。 – WestLangley

+0

谢谢,您的修改与我使用的“materials.map”hack具有相同的效果。纹理贴图加载但重复不是 –

+1

'shaderUniforms [“offsetRepeat”] .value.set(0,0,2,2);' – WestLangley

回答

7

three.js被设计为易于使用,不容易修改。这可能会改变未来......

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

var defines = {}; 

defines[ "USE_MAP" ] = "";. 

的材料构造然后指定defines

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

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

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

three.js所r.66