4

車のベースカラーを動的に変更できるthree.jsで車のモデルのマテリアルを作ろうとしています。これは、私が使用している MeshPhongMaterial の色属性を変更するだけで簡単にできました。次に、上にテクスチャを適用する必要があり、マテリアルのマップ アトリビュートに画像を追加するだけで十分簡単だと考えました。結果は私が期待したものではありませんでしたが、マップ/テクスチャ イメージも color アトリビュートによって設定された色でシェーディングされました。基本的にベースカラーの上に重ねていきたいです。

誰かが私を正しい方向に向けることができますか?

4

2 に答える 2

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>

three.js phong マテリアルについて少し学びました。さらに洗練されたものが必要な場合は、代わりに ShaderMaterial を使用することをお勧めします。

于 2012-12-05T22:58:16.503 に答える
0

そのためには、カスタム シェーダーと、アルファ チャネル (本質的には 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" にあります) が乗算されます。代わりに、ベース カラーの上にマップをオーバーレイするように聞こえますが、それをペイントした場合 (クロム バンパーとヘッドライトなど) だけです。

これを行う簡単な方法は、「map_fragment」文字列の値を変更することにより、「phone」マテリアルをインスタンス化する前に「phong」の動作方法を変更することです。

"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 を作成する必要があります。

于 2012-12-03T22:36:33.467 に答える