SubsurfaceScatteringShader.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. import {
  2. Color,
  3. ShaderChunk,
  4. ShaderLib,
  5. UniformsUtils
  6. } from "../../../build/three.module.js";
  7. /**
  8. * ------------------------------------------------------------------------------------------
  9. * Subsurface Scattering shader
  10. * Based on GDC 2011 – Approximating Translucency for a Fast, Cheap and Convincing Subsurface Scattering Look
  11. * https://colinbarrebrisebois.com/2011/03/07/gdc-2011-approximating-translucency-for-a-fast-cheap-and-convincing-subsurface-scattering-look/
  12. *------------------------------------------------------------------------------------------
  13. */
  14. function replaceAll( string, find, replace ) {
  15. return string.split( find ).join( replace );
  16. }
  17. var meshphong_frag_head = ShaderChunk[ "meshphong_frag" ].slice( 0, ShaderChunk[ "meshphong_frag" ].indexOf( 'void main() {' ) );
  18. var meshphong_frag_body = ShaderChunk[ "meshphong_frag" ].slice( ShaderChunk[ "meshphong_frag" ].indexOf( 'void main() {' ) );
  19. var SubsurfaceScatteringShader = {
  20. uniforms: UniformsUtils.merge( [
  21. ShaderLib[ "phong" ].uniforms,
  22. {
  23. "thicknessMap": { value: null },
  24. "thicknessColor": { value: new Color( 0xffffff ) },
  25. "thicknessDistortion": { value: 0.1 },
  26. "thicknessAmbient": { value: 0.0 },
  27. "thicknessAttenuation": { value: 0.1 },
  28. "thicknessPower": { value: 2.0 },
  29. "thicknessScale": { value: 10.0 }
  30. }
  31. ] ),
  32. vertexShader: [
  33. "#define USE_UV",
  34. ShaderChunk[ "meshphong_vert" ],
  35. ].join( "\n" ),
  36. fragmentShader: [
  37. "#define USE_UV",
  38. "#define SUBSURFACE",
  39. meshphong_frag_head,
  40. "uniform sampler2D thicknessMap;",
  41. "uniform float thicknessPower;",
  42. "uniform float thicknessScale;",
  43. "uniform float thicknessDistortion;",
  44. "uniform float thicknessAmbient;",
  45. "uniform float thicknessAttenuation;",
  46. "uniform vec3 thicknessColor;",
  47. "void RE_Direct_Scattering(const in IncidentLight directLight, const in vec2 uv, const in GeometricContext geometry, inout ReflectedLight reflectedLight) {",
  48. " vec3 thickness = thicknessColor * texture2D(thicknessMap, uv).r;",
  49. " vec3 scatteringHalf = normalize(directLight.direction + (geometry.normal * thicknessDistortion));",
  50. " float scatteringDot = pow(saturate(dot(geometry.viewDir, -scatteringHalf)), thicknessPower) * thicknessScale;",
  51. " vec3 scatteringIllu = (scatteringDot + thicknessAmbient) * thickness;",
  52. " reflectedLight.directDiffuse += scatteringIllu * thicknessAttenuation * directLight.color;",
  53. "}",
  54. meshphong_frag_body.replace( "#include <lights_fragment_begin>",
  55. replaceAll(
  56. ShaderChunk[ 'lights_fragment_begin' ],
  57. 'RE_Direct( directLight, geometry, material, reflectedLight );',
  58. [
  59. "RE_Direct( directLight, geometry, material, reflectedLight );",
  60. "#if defined( SUBSURFACE ) && defined( USE_UV )",
  61. " RE_Direct_Scattering(directLight, vUv, geometry, reflectedLight);",
  62. "#endif",
  63. ].join( "\n" )
  64. ),
  65. ),
  66. ].join( "\n" ),
  67. };
  68. export { SubsurfaceScatteringShader };