2
0

SubsurfaceScatteringShader.js 2.8 KB

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