TriPlanarMapping в ТРИ. js - PullRequest
1 голос
/ 29 мая 2020

Я пытаюсь реализовать трехпланарное сопоставление поверх MeshPhysicalMaterial, и у меня возникают некоторые проблемы с картой нормалей. Я использовал этот для его создания.

Я использовал onBeforeCompile, чтобы добиться этого.

Вот фрагмент кода:

 material.onBeforeCompile = (shader: Shader) => {
  shader.uniforms.scaler = { value: 0.0116 };
  shader.uniforms.gamma = { value: this.utilsService.overallGamma };
  shader.vertexShader = shader.vertexShader.replace(
    '#define STANDARD',
    `
    #define STANDARD
    varying vec3 wNormal;
    varying vec3 vUv2;
    `
  );
  shader.vertexShader = shader.vertexShader.replace(
    'void main() {',
    `
    void main() {
      vec4 worldPosition2 = modelMatrix * vec4( position, 1.0 );
      wNormal = normalize( mat3( modelMatrix[0].xyz, modelMatrix[1].xyz, modelMatrix[2].xyz ) * normal );
      vUv2 = worldPosition2.xyz;
    `
  );

  shader.fragmentShader = shader.fragmentShader.replace(
    'uniform float opacity;',
    `uniform float opacity;
     uniform float scaler;
     uniform float gamma;
     varying vec3 vUv2;
     varying vec3 wNormal;
     vec3 GetTriplanarWeights (vec3 normals) {
        vec3 triW = abs(normals);
        return triW / (triW.x + triW.y + triW.z);
      }
    struct TriplanarUV {
      vec2 x, y, z;
    };
    TriplanarUV GetTriplanarUV (vec3 pos) {
        TriplanarUV  triUV;
        triUV.x = pos.zy;
        triUV.y = pos.xz;
        triUV.z = pos.xy;
        return triUV;
      }
     `
  );

  shader.fragmentShader = shader.fragmentShader.replace(
    '#include <map_fragment>',
    `
    #ifdef USE_MAP
        vec3 xColor = texture2D(map, vUv2.yz * scaler).rgb;
        vec3 yColor = texture2D(map, vUv2.xz * scaler).rgb;
        vec3 zColor = texture2D(map, vUv2.xy * scaler).rgb;
        vec3 triW = GetTriplanarWeights(wNormal);
        vec4 easedColor = vec4( xColor * triW.x + yColor * triW.y + zColor * triW.z, 1.0);
        vec4 gammaCorrectedColor = vec4( pow(abs(easedColor.x),gamma), pow(abs(easedColor.y),gamma), pow(abs(easedColor.z),gamma), 1.0);
        vec4 texelColor3 = mapTexelToLinear( gammaCorrectedColor );
        diffuseColor *= texelColor3;
    #endif
    `
  );

  shader.fragmentShader = shader.fragmentShader.replace(
    '#include <roughnessmap_fragment>',
    `
    float roughnessFactor = roughness;

    #ifdef USE_ROUGHNESSMAP
      vec3 xColorR = texture2D(roughnessMap, vUv2.yz * scaler).rgb;
      vec3 yColorR = texture2D(roughnessMap, vUv2.xz * scaler).rgb;
      vec3 zColorR = texture2D(roughnessMap, vUv2.xy * scaler).rgb;

      vec3 triWR = GetTriplanarWeights(wNormal);
      vec4 easedColorR = vec4( xColorR * triWR.x + yColorR * triWR.y + zColorR * triWR.z, 1.0);
      vec4 gammaCorrectedColorR = vec4( pow(abs(easedColorR.x),gamma), pow(abs(easedColorR.y),gamma), pow(abs(easedColorR.z),gamma), 1.0);
      vec4 texelColorR = mapTexelToLinear( gammaCorrectedColorR );
      roughnessFactor *= texelColorR.g;
    #endif

    `
  );
  shader.fragmentShader = shader.fragmentShader.replace(
    '#include <normal_fragment_maps>',
    `
    #ifdef OBJECTSPACE_NORMALMAP
        normal = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0; // overrides both flatShading and attribute normals
        #ifdef FLIP_SIDED
            normal = - normal;
        #endif
        #ifdef DOUBLE_SIDED
            normal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );
        #endif
        normal = normalize( normalMatrix * normal );
    #elif defined( TANGENTSPACE_NORMALMAP )
        TriplanarUV triUV = GetTriplanarUV(vUv2);

        vec3 tangentNormalX = texture2D(normalMap, triUV.x * scaler).xyz;
        vec3 tangentNormalY = texture2D(normalMap, triUV.y * scaler).xyz;
        vec3 tangentNormalZ = texture2D(normalMap, triUV.z * scaler).xyz;

        vec3 worldNormalX = tangentNormalX.xyz;
        vec3 worldNormalY = tangentNormalY.xyz;
        vec3 worldNormalZ = tangentNormalZ;

        vec3 triWN = GetTriplanarWeights(wNormal);
        vec3 mapI = normalize(worldNormalX * triWN.x + worldNormalY * triWN.y + worldNormalZ * triWN.z);
        vec3 mapN = vec3(mapI.x, mapI.y, mapI.z);
        mapN.xy *= normalScale;
        #ifdef USE_TANGENT
            normal = normalize( vTBN * mapN );
        #else
            normal = perturbNormal2Arb( -vViewPosition, normal, mapN );
        #endif
    #elif defined( USE_BUMPMAP )
        normal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );
    #endif
    `
  )
};

А вот сравнение оригинального (без изменений нормалей) и трипланарного:

coparison

Я был бы очень признателен за помощь / руководство по этому топу c. Большое спасибо!

...