MeshSSSNodeMaterial.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. import { addNodeMaterial } from './NodeMaterial.js';
  2. import { transformedNormalView } from '../accessors/NormalNode.js';
  3. import { positionViewDirection } from '../accessors/PositionNode.js';
  4. import PhysicalLightingModel from '../functions/PhysicalLightingModel.js';
  5. import MeshPhysicalNodeMaterial from './MeshPhysicalNodeMaterial.js';
  6. import { float, vec3 } from '../shadernode/ShaderNode.js';
  7. class SSSLightingModel extends PhysicalLightingModel {
  8. constructor( useClearcoat, useSheen, useIridescence, useSSS ) {
  9. super( useClearcoat, useSheen, useIridescence );
  10. this.useSSS = useSSS;
  11. }
  12. direct( { lightDirection, lightColor, reflectedLight }, stack, builder ) {
  13. if ( this.useSSS === true ) {
  14. const material = builder.material;
  15. const { thicknessColorNode, thicknessDistortionNode, thicknessAmbientNode, thicknessAttenuationNode, thicknessPowerNode, thicknessScaleNode } = material;
  16. const scatteringHalf = lightDirection.add( transformedNormalView.mul( thicknessDistortionNode ) ).normalize();
  17. const scatteringDot = float( positionViewDirection.dot( scatteringHalf.negate() ).saturate().pow( thicknessPowerNode ).mul( thicknessScaleNode ) );
  18. const scatteringIllu = vec3( scatteringDot.add( thicknessAmbientNode ).mul( thicknessColorNode ) );
  19. reflectedLight.directDiffuse.addAssign( scatteringIllu.mul( thicknessAttenuationNode.mul( lightColor ) ) );
  20. }
  21. super.direct( { lightDirection, lightColor, reflectedLight }, stack, builder );
  22. }
  23. }
  24. class MeshSSSNodeMaterial extends MeshPhysicalNodeMaterial {
  25. constructor( parameters ) {
  26. super( parameters );
  27. this.thicknessColorNode = null;
  28. this.thicknessDistortionNode = float( 0.1 );
  29. this.thicknessAmbientNode = float( 0.0 );
  30. this.thicknessAttenuationNode = float( .1 );
  31. this.thicknessPowerNode = float( 2.0 );
  32. this.thicknessScaleNode = float( 10.0 );
  33. }
  34. get useSSS() {
  35. return this.thicknessColorNode !== null;
  36. }
  37. setupLightingModel( /*builder*/ ) {
  38. return new SSSLightingModel( this.useClearcoat, this.useSheen, this.useIridescence, this.useSSS );
  39. }
  40. copy( source ) {
  41. this.thicknessColorNode = source.thicknessColorNode;
  42. this.thicknessDistortionNode = source.thicknessDistortionNode;
  43. this.thicknessAmbientNode = source.thicknessAmbientNode;
  44. this.thicknessAttenuationNode = source.thicknessAttenuationNode;
  45. this.thicknessPowerNode = source.thicknessPowerNode;
  46. this.thicknessScaleNode = source.thicknessScaleNode;
  47. return super.copy( source );
  48. }
  49. }
  50. export default MeshSSSNodeMaterial;
  51. addNodeMaterial( 'MeshSSSNodeMaterial', MeshSSSNodeMaterial );