Добавьте карту нормалей в ShaderMaterial

Я пытаюсь добавить несколько текстур на один и тот же объект в Three.js. У меня есть 3D-футболка и следующие элементы в формате .png для текстур футболки:

Перед, спинка и рукава футболки:

Горловина для футболки:

И карта нормалей, которая даст складки ткани:

Я использую этот код, чтобы добавить первые два изображения в качестве текстур к моему объекту, чтобы применить изображения спереди, сзади и рукавов, а также изображение шеи к моему материалу.

      const loader = new THREE.TextureLoader();

function initObject() {
    var texture1 = loader.load( 'img/ak-jersey-no-neck.png' );
    var texture2 = loader.load( 'img/ak-only-neck.png' );

    var pitchMaterialParams = {
        uniforms: THREE.UniformsUtils.merge([{

            texture1: null,
            texture2: null,

        }]),
        vertexShader:
            `

   varying vec2 vUv;

    void main()
    {
        vUv = uv;
        vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
        gl_Position = projectionMatrix * mvPosition;
    }

 `,
        fragmentShader:
            `

   precision mediump float;
   uniform sampler2D texture1;
   uniform sampler2D texture2;
   varying vec2 vUv;

   void main() {
     vec4 t1 = texture2D( texture1, vUv );
     vec4 t2 = texture2D( texture2, vUv );
     gl_FragColor = vec4(mix(t1.rgb, t2.rgb, t2.a), 1.0);
   }

 `
    };


    var material = new THREE.ShaderMaterial(pitchMaterialParams);
    material.uniforms.texture1.value = texture1;
    material.uniforms.texture2.value = texture2;

    const objLoader = new OBJLoader();

    objLoader.load('object.obj', (object) => {
            object.traverse( function ( child ) {

                if ( child instanceof THREE.Mesh ) {

                    child.material = material;

                }

            } );
            scene.add(object)
            //    console.log(object);
        },
        // called when loading is in progresses
        function ( xhr ) {

            console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );

        },
        (error) => {
            console.log('An error happened');
            console.log(error);
        }

    );
}

initObject();

С помощью этого кода две текстуры правильно применяются к моему объекту.

Я попытался добавить третью с картой нормалей, но она не смешивается правильно:

      const loader = new THREE.TextureLoader();
const normalTexture = new THREE.TextureLoader().load('img/228180-NormalMap.png')


function initObject() {
    var texture1 = loader.load( 'img/ak-jersey-no-neck.png' );
    var texture2 = loader.load( 'img/ak-only-neck.png' );

    var pitchMaterialParams = {
        uniforms: THREE.UniformsUtils.merge([{

            texture1: null,
            texture2: null,
            normalMap: null,

        }]),
        vertexShader:
            `

   varying vec2 vUv;

    void main()
    {
        vUv = uv;
        vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
        gl_Position = projectionMatrix * mvPosition;
    }

 `,
        fragmentShader:
            `

   precision mediump float;
   uniform sampler2D texture1;
   uniform sampler2D texture2;
   uniform sampler2D normalMap;
   varying vec2 vUv;

   void main() {
     vec4 t1 = texture2D( texture1, vUv );
     vec4 t2 = texture2D( texture2, vUv );
     vec4 t3 = texture2D( normalMap, vUv );
     gl_FragColor = vec4(mix(t1.rgb, t2.rgb, t3.rgb), 1.0);
   }

 `
    };


    var material = new THREE.ShaderMaterial(pitchMaterialParams);
    material.uniforms.texture1.value = texture1;
    material.uniforms.texture2.value = texture2;
    material.uniforms.normalMap.value = normalTexture;
    // material.normalMap = normalTexture;


    const objLoader = new OBJLoader();

    objLoader.load('object.obj', (object) => {
            object.traverse( function ( child ) {

                if ( child instanceof THREE.Mesh ) {

                    child.material = material;

                }

            } );
            scene.add(object)
            //    console.log(object);
        },
        // called when loading is in progresses
        function ( xhr ) {

            console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );

        },
        (error) => {
            console.log('An error happened');
            console.log(error);
        }

    );
}

initObject();

В результате получилось просто сочетание трех текстур:

Я хотел бы применить normalMap так же, как он был применен к MeshStandardMaterial, поэтому я получаю такой результат, где на футболке видны складки:

Есть ли способ объединить изображение normalMap с другими текстурами в моем ShaderMaterial, чтобы оно смешивалось, как и normalMap?

0 ответов

Другие вопросы по тегам