BumpMapNode.js 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. import TempNode from '../core/TempNode.js';
  2. import { texture } from '../accessors/TextureNode.js';
  3. import { addNodeClass } from '../core/Node.js';
  4. import { uv } from '../accessors/UVNode.js';
  5. import { normalView } from '../accessors/NormalNode.js';
  6. import { positionView } from '../accessors/PositionNode.js';
  7. import { faceDirection } from './FrontFacingNode.js';
  8. import { tslFn, nodeProxy, vec2 } from '../shadernode/ShaderNode.js';
  9. // Bump Mapping Unparametrized Surfaces on the GPU by Morten S. Mikkelsen
  10. // https://mmikk.github.io/papers3d/mm_sfgrad_bump.pdf
  11. // Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2)
  12. const dHdxy_fwd = tslFn( ( { bumpTexture, bumpScale } ) => {
  13. const uvNode = uv();
  14. const Hll = texture( bumpTexture, uvNode ).x;
  15. return vec2(
  16. texture( bumpTexture, uvNode.add( uvNode.dFdx() ) ).x.sub( Hll ),
  17. texture( bumpTexture, uvNode.add( uvNode.dFdy() ) ).x.sub( Hll )
  18. ).mul( bumpScale );
  19. } );
  20. const perturbNormalArb = tslFn( ( inputs ) => {
  21. const { surf_pos, surf_norm, dHdxy } = inputs;
  22. const vSigmaX = surf_pos.dFdx();
  23. const vSigmaY = surf_pos.dFdy();
  24. const vN = surf_norm; // normalized
  25. const R1 = vSigmaY.cross( vN );
  26. const R2 = vN.cross( vSigmaX );
  27. const fDet = vSigmaX.dot( R1 ).mul( faceDirection );
  28. const vGrad = fDet.sign().mul( dHdxy.x.mul( R1 ).add( dHdxy.y.mul( R2 ) ) );
  29. return fDet.abs().mul( surf_norm ).sub( vGrad ).normalize();
  30. } );
  31. class BumpMapNode extends TempNode {
  32. constructor( texture, scaleNode = null ) {
  33. super( 'vec3' );
  34. this.texture = texture;
  35. this.scaleNode = scaleNode;
  36. }
  37. setup() {
  38. const bumpScale = this.scaleNode !== null ? this.scaleNode : 1;
  39. const dHdxy = dHdxy_fwd( { bumpTexture: this.texture, bumpScale } );
  40. return perturbNormalArb( {
  41. surf_pos: positionView.negate(),
  42. surf_norm: normalView,
  43. dHdxy
  44. } );
  45. }
  46. }
  47. export default BumpMapNode;
  48. export const bumpMap = nodeProxy( BumpMapNode );
  49. addNodeClass( 'BumpMapNode', BumpMapNode );