FarazzShaikh / THREE-CustomShaderMaterial

Extend Three.js standard materials with your own shaders!
Other
846 stars 54 forks source link

Override fragment normals? #23

Closed nwpointer closed 2 years ago

nwpointer commented 2 years ago

Would be nice to override normals in the fragment shader as well.

In the custom shader I was trying to port over to CSM I sample one or more normal maps and blend them together:

Screen Shot 2022-08-14 at 1 32 04 PM

more specifically updating the variable mapN or Normal is what I care about I guess: https://github.com/mrdoob/three.js/blob/dev/src/renderers/shaders/ShaderChunk/normal_fragment_maps.glsl.js#L23 https://github.com/mrdoob/three.js/blob/dev/src/renderers/shaders/ShaderChunk/normal_fragment_maps.glsl.js#L28

nwpointer commented 2 years ago

I think I figurered out how to use patchMap for this

FarazzShaikh commented 2 years ago

Yes patchMaps is the way to go for custom overrides, let me know if you need help with that.

Else let’s close this if you’ve figured it out, also please post the solution if you don’t mind so other can benefit too!

nwpointer commented 2 years ago

ok! will post my solution once I've got it working :)

thanks for confirming this is the way forward.

nwpointer commented 2 years ago

ok so here's the hello world for modifying normal maps. This basically is a simplified version of what the default shaders do when you set provide a normalmap img but the user of the CSM is free to replace the logic in Main() with what ever logic they want as long as it assigns a value to csm_NormalMap.

<CustomShaderMaterial
      baseMaterial={MeshStandardMaterial}
      normalMap={normalTexture}
      fragmentShader={glsl`
        precision mediump float;
        vec3 csm_NormalMap;

        void main(){
          csm_NormalMap = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;
        }
      `}
      patchMap={{
        csm_NormalMap: {
          "#include <normal_fragment_maps>": glsl`
            vec3 mapN = csm_NormalMap;
            mapN.xy *= normalScale;
            normal = perturbNormal2Arb( - vViewPosition, normal, mapN, faceDirection );
          `,
        },
      }}
    />
drone1 commented 1 year ago

Does one need to do anything special to use perturbNormal2Arb? I get an error when I try to use this code.

ERROR: 0:1412: 'perturbNormal2Arb' : no matching overloaded function found

Googled around but found nothing. Thanks.

drone1 commented 1 year ago

I forgot to comment again here. The issue was that I set normalMap after first render, which would cause a shader compilation failure. You gotta set normalMap before first render so that all the right #define's are in place.