SubsurfaceScatteringShader.js 2.9 KB

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