Three.js材质和颜色

时间:2012-12-03 06:55:24

标签: three.js

我试图为具有three.js的汽车模型制作材料,其中汽车的基色可以动态改变。通过更改我正在使用的MeshPhongMaterial的颜色属性,这很容易。 然后我需要在顶部应用纹理,并认为通过将图像添加到材质的地图属性可以很容易。 结果不是我预期的结果,地图/纹理图像也被颜色属性设置的颜色着色。我希望它基本上覆盖基色。

有人能指出我正确的方向吗?

2 个答案:

答案 0 :(得分:3)

这是一个完整的脚本块。阅读three.js后立即插入

<script>
THREE.ShaderChunk.map_fragment = [
    "#ifdef USE_MAP",
        "vec4 texelColor = texture2D( map, vUv ); /* NEWWW */",
        "#ifdef GAMMA_INPUT",
        "texelColor.xyz *= texelColor.xyz;",
        "#endif",
        "gl_FragColor.rgb = mix(gl_FragColor.rgb,texelColor.rgb,texelColor.a);",
        "vec3 surfDiffuse = mix(diffuse,vec3(1,1,1),texelColor.a);",
    "#else",
        "vec3 surfDiffuse = diffuse;",
    "#endif"].join('\n');
// now replace references to 'diffuse' with 'surfDiffuse'
THREE.ShaderChunk.lights_phong_fragment = 
    THREE.ShaderChunk.lights_phong_fragment.replace(/\bdiffuse\b/gm,'surfDiffuse')
THREE.ShaderLib.phong.fragmentShader = [
    "uniform vec3 diffuse;",
    "uniform float opacity;",
    "uniform vec3 ambient;",
    "uniform vec3 emissive;",
    "uniform vec3 specular;",
    "uniform float shininess;",
    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[ "lights_phong_pars_fragment" ],
    THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
    THREE.ShaderChunk[ "bumpmap_pars_fragment" ],
    THREE.ShaderChunk[ "normalmap_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" ],
        THREE.ShaderChunk[ "lights_phong_fragment" ],
        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');
</script>

了解了这三种材料 - 它没有按照我喜欢的方式处理亮点,但......无论如何。如果你需要更复杂的话,我建议使用ShaderMaterial。

答案 1 :(得分:0)

您需要一个自定义着色器 - 以及带有Alpha通道的纹理(基本上是DDS格式)。如果您查看three.js源代码,您会看到一些名为“map_fragment”的片段着色器代码,如下所示:

    "#ifdef USE_MAP",

        "#ifdef GAMMA_INPUT",

            "vec4 texelColor = texture2D( map, vUv );",
            "texelColor.xyz *= texelColor.xyz;",

            "gl_FragColor = gl_FragColor * texelColor;",

        "#else",

            "gl_FragColor = gl_FragColor * texture2D( map, vUv );",

        "#endif",

    "#endif"

正如您所看到的,它将纹理贴图乘以颜色(此时的颜色位于“gl_FragColor”中)。相反,它听起来就像你希望你的地图叠加在基色上,只有你画了它(比如镀铬保险杠和前灯)。

一种简单的方法可能就是在实例化任何phong材料之前改变'phong'的工作方式,方法是改变“map_fragment”字符串的值。

而不是“gl_FragColor *(something)” - 尝试将其作为THREE.ShaderChunk.map_fragment的重新赋值:

 [

    "#ifdef USE_MAP",

        "vec4 texelColor = texture2D( map, vUv );",

        "#ifdef GAMMA_INPUT",

            "texelColor.xyz *= texelColor.xyz;",

        "#endif",

        "gl_FragColor = vec4(mix(gl_FragColor.rgb,texelColor.rgb,texelColor.a),(gl_FragColor.a*texelColor.a));",

    "#endif"

].join('\n');

以这种方式覆盖库存方法的危险在于它将适用于场景中的所有模型 - 绘制的纹理将覆盖材料颜色。如果没关系,那就完成了。否则你应该创建一个新的THREE.ShaderMaterial,就像“phong”一样,除了这里引用的差异。