代码之家  ›  专栏  ›  技术社区  ›  AGogel

三个多贴图通道模型和纹理。js公司

  •  0
  • AGogel  · 技术社区  · 7 年前

    我正在尝试在三个贴图通道中使用两个以上的贴图通道。js为我的模型指定纹理。令我惊讶的是,这三种材料中没有本土材料。js支持多组UV。。因此,我必须使用ShaderMaterial并编写自己的顶点/片段着色器才能访问多个贴图通道。

    现在,我确实设法让多通道UV使用我编写的一个简单代码:

    <script id="vertex_shh" type="x-shader/x-vertex">
    
        //VERTEX SHADER//
    
            varying vec2 vUv;
            attribute vec2 uv2;
            varying vec2 vUv2;
            attribute vec2 uv3;
            varying vec2 vUv3;
            attribute vec2 uv4;
            varying vec2 vUv4;
            attribute vec2 uv5;
            varying vec2 vUv5;
    
    
            void main()
            {
                vUv = uv;
                vUv2 = uv2;
                vUv3 = uv3;
                vUv4 = uv4;
                vUv5 = uv5;                 
    
                vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
                gl_Position = projectionMatrix * mvPosition;
            }
    
        // END //
    
        </script>       
    
    
    
        <script id="fragment_shh" type="x-shader/x-fragment">   
    
        //FRAGMENT SHADER//
    
            uniform sampler2D tCh1;
            uniform sampler2D tCh2;
            uniform sampler2D tCh3;
            uniform sampler2D tCh4;         
            uniform sampler2D tCh5;
    
            varying vec2 vUv;
            varying vec2 vUv2;
            varying vec2 vUv3;
            varying vec2 vUv4;
            varying vec2 vUv5;
    
    
            void main(void)
            {
                vec3 DiffuseComp;
                vec4 TexCh1 = texture2D(tCh1, vUv);
                vec4 TexCh2 = texture2D(tCh2, vUv2);
                vec4 TexCh3 = texture2D(tCh3, vUv3);
                vec4 TexCh4 = texture2D(tCh4, vUv4);
                vec4 TexCh5 = texture2D(tCh5, vUv5);
    
                DiffuseComp = ((TexCh1.rgb * (1.0 - TexCh4.rgb) + (TexCh2.rgb * TexCh4.rgb)) * (1.0 - TexCh5.rgb)) + (TexCh3.rgb * TexCh5.rgb);
                gl_FragColor= vec4(DiffuseComp, 1.0);   
            }
    
        // END //
    
            /* SHADER */
            var vertShader = document.getElementById('vertex_shh').innerHTML;
            var fragShader = document.getElementById('fragment_shh').innerHTML;
    
            var attributes = {};
    
            var uniforms = {
            tCh1: { type: "t", value: Textura1},
            tCh2: { type: "t", value: Textura2},
            tCh3: { type: "t", value: Textura3},
            tCh4: { type: "t", value: Textura4},
            tCh5: { type: "t", value: Textura5}
            };          
    
    
            /* MATERIAL */
            var multitexsh = new THREE.ShaderMaterial({
            uniforms: uniforms,
            attributes: attributes,
            vertexShader: vertShader,
            fragmentShader: fragShader
            });
    

    然而,我的问题是,我基本上需要一个具有此功能的着色器和Phong着色器的一些基本功能:照明(来自场景灯光)和镜面反射高光。我在这里完全迷路了。我尝试过寻找将此功能添加到本机着色器的方法,或者将phong材质中提到的功能添加到我自己的着色器中,但没有找到足以使用我的基本编码技能实现这一点的信息。。谁能进来帮我一下吗?


    编辑:

    幸亏 桶头 在onBeforeCompile上使用它。这是在r89上,更新代码如下:

            /* MANAGERS, LOADERS */
            var manager = new THREE.LoadingManager();
            var loader = new THREE.FBXLoader( manager );
            var textureLoader = new THREE.TextureLoader( manager );
    
            /*TEXTURE */
            var prodtex ='textures/testing/cubetex.jpg';
            var prodtex2 ='textures/testing/cube_blendmap.jpg';
    
            var Textura1 = textureLoader.load (prodtex);
            var Textura2 = textureLoader.load (prodtex);
            var Textura3 = textureLoader.load (prodtex2);
    
            /* MATERIAL */
            var MAT = new THREE.MeshPhongMaterial();
            MAT.map = Textura1;     
    
            /* MY SHADER CHANGES*/
            const uv2_chunkToReplaceVS = 'attribute vec2 uv2; varying vec2 vUv2; attribute vec2 uv3; varying vec2 vUv3;'
            const uv2_chunkToReplaceVSV = 'vUv2 = uv2; vUv3 = uv3;'
            const uv2_chunkToReplaceFS = 'uniform sampler2D tCh1; uniform sampler2D tCh2; uniform sampler2D tCh3; varying vec2 vUv2; varying vec2 vUv3;'
            const map_chunkToReplaceFSV = 'vec4 TexCh1 = texture2D(tCh1, vUv); vec4 TexCh2 = texture2D(tCh2, vUv2); vec4 TexCh3 = texture2D(tCh3, vUv3); vec4 texelColor = texture2D( map, vUv ); texelColor = mapTexelToLinear( texelColor ); TexCh1 = mapTexelToLinear( TexCh1 ); TexCh2 = mapTexelToLinear( TexCh2 ); TexCh2 = mapTexelToLinear( TexCh2 ); diffuseColor *= TexCh1 * (1.0 - TexCh3) + (TexCh2 * TexCh3);'
    
            MAT.onBeforeCompile = shader=>{
            shader.uniforms.tCh1= {type: "t", value: Textura1};
            shader.uniforms.tCh2= {type: "t", value: Textura2};
            shader.uniforms.tCh3= {type: "t", value: Textura3};
    
            shader.fragmentShader = shader.fragmentShader.replace('#include <map_fragment>', map_chunkToReplaceFSV);
            shader.vertexShader = shader.vertexShader.replace('#include <uv2_pars_vertex>', uv2_chunkToReplaceVS );
            shader.vertexShader = shader.vertexShader.replace('#include <uv2_vertex>', uv2_chunkToReplaceVSV );
            shader.fragmentShader = shader.fragmentShader.replace('#include <uv2_pars_fragment>', uv2_chunkToReplaceFS);
            };
    
    
            /* MODEL */
            loader.load( ('models/' + 'cube' + '.FBX'), function( object ) {
                //set material//
                object.traverse( function ( child ) {
                    if ( child instanceof THREE.Mesh ) {
                        child.material = MAT;
                    };
                } );                
                scene.add (object);
            });
    
    1 回复  |  直到 7 年前
        1
  •  2
  •   pailhead    7 年前

    您可以使用名为 onBeforeCompile .

    它是在三次解析着色器模板之前以及在编译着色器之前调用的回调。

    模板可能如下所示

    //someTemplate.vert
    
    #include <common>
    #include <some_pars_vertex>
    
    void main(){
      #include <some_vertex>
      #include <another_vertex>
    
      gl_Position = projectionMatrix * foobar;
    }
    

    假设要添加更多uv通道。您可以在GLSL中创建一些代码片段/函数。这必须在全球范围内发生(如上所述 void main(){...} ):

    //myBeforeVoidMain.vert
    
    attribute vec2 aUV2;
    attribute vec2 aUV3;
    
    varying vec2 vUv2;
    varying vec2 vUv3;
    

    然后,这必须在主功能中发生:

    //myUv.vert
    vUv2 = aUV2;
    vUv3 = aUV3;
    

    您可以注入此代码,但在何处以及如何注入?

    怎样:

    const chunkToReplace = THREE.ShaderChunk.uv_pars_vertex
    
    myMaterial = new THREE.MeshPhongMaterial()
    myMaterial.onBeforeCompile( shader=>{
      shader.uniforms.myUniform = {value:foo} 
      shader.vertexShader = shader.vertexShader.replace( '#include <uv_pars_vertex>', chunkToReplace + myChunk )
    })
    

    哪里:

    您需要熟悉这两个方面: https://github.com/mrdoob/three.js/tree/dev/src/renderers/shaders/ShaderChunk https://github.com/mrdoob/three.js/tree/dev/src/renderers/shaders/ShaderLib

    你需要好好想想。可以注意到 <common> 几乎在每个lib的全局范围内都存在。但是,因为它包含在vert和frag着色器中,所以您无法提及 attribute 在其中,frag着色器将无法编译。

    向顶点着色器添加属性、一致性和变化的一个好块是 uv_pars_vertex 因为它也存在于几乎所有着色器中。

    对于此特定问题,还必须扩展片段着色器。再把瓦林一家 uv_pars_fragment ,然后您必须找到剩余的逻辑,在那里您可以使用这些uv通道。

    注:

    将两个通道打包到一个属性中可能是一个好主意:

    attribute vec4 aUv23;
    
    ...
      vUv2 = aUv23.xy;
      vUv3 = aUv23.zw;
    
    推荐文章