TranslucentShader.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. /**
  2. * @author daoshengmu / http://dsmu.me/
  3. *
  4. * ------------------------------------------------------------------------------------------
  5. * Subsurface Scattering shader
  6. * Base 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. THREE.TranslucentShader = {
  11. uniforms: THREE.UniformsUtils.merge( [
  12. THREE.UniformsLib[ "common" ],
  13. THREE.UniformsLib[ "lights" ],
  14. {
  15. "color": { value: new THREE.Color( 0xffffff ) },
  16. "diffuse": { value: new THREE.Color( 0xffffff ) },
  17. "specular": { value: new THREE.Color( 0xffffff ) },
  18. "emissive": { value: new THREE.Color( 0x000000 ) },
  19. "opacity": { value: 1 },
  20. "shininess": { value: 1 },
  21. "thicknessMap": { value: null },
  22. "thicknessColor": { value: new THREE.Color( 0xffffff ) },
  23. "thicknessDistortion": { value: 0.1 },
  24. "thicknessAmbient": { value: 0.0 },
  25. "thicknessAttenuation": { value: 0.1 },
  26. "thicknessPower": { value: 2.0 },
  27. "thicknessScale": { value: 10.0 }
  28. }
  29. ] ),
  30. vertexShader: [
  31. "varying vec3 vNormal;",
  32. "varying vec2 vUv;",
  33. "varying vec3 vViewPosition;",
  34. THREE.ShaderChunk[ "common" ],
  35. "void main() {",
  36. " vec4 worldPosition = modelMatrix * vec4( position, 1.0 );",
  37. " vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
  38. " vViewPosition = -mvPosition.xyz;",
  39. " vNormal = normalize( normalMatrix * normal );",
  40. " vUv = uv;",
  41. " gl_Position = projectionMatrix * mvPosition;",
  42. "}",
  43. ].join( "\n" ),
  44. fragmentShader: [
  45. "#define USE_UV",
  46. "#define USE_MAP",
  47. "#define PHONG",
  48. "#define TRANSLUCENT",
  49. "#include <common>",
  50. "#include <bsdfs>",
  51. "#include <uv_pars_fragment>",
  52. "#include <map_pars_fragment>",
  53. "#include <lights_phong_pars_fragment>",
  54. "varying vec3 vColor;",
  55. "uniform vec3 diffuse;",
  56. "uniform vec3 specular;",
  57. "uniform vec3 emissive;",
  58. "uniform float opacity;",
  59. "uniform float shininess;",
  60. // Translucency
  61. "uniform sampler2D thicknessMap;",
  62. "uniform float thicknessPower;",
  63. "uniform float thicknessScale;",
  64. "uniform float thicknessDistortion;",
  65. "uniform float thicknessAmbient;",
  66. "uniform float thicknessAttenuation;",
  67. "uniform vec3 thicknessColor;",
  68. THREE.ShaderChunk[ "lights_pars_begin" ],
  69. "void RE_Direct_Scattering(const in IncidentLight directLight, const in vec2 uv, const in GeometricContext geometry, inout ReflectedLight reflectedLight) {",
  70. " vec3 thickness = thicknessColor * texture2D(thicknessMap, uv).r;",
  71. " vec3 scatteringHalf = normalize(directLight.direction + (geometry.normal * thicknessDistortion));",
  72. " float scatteringDot = pow(saturate(dot(geometry.viewDir, -scatteringHalf)), thicknessPower) * thicknessScale;",
  73. " vec3 scatteringIllu = (scatteringDot + thicknessAmbient) * thickness;",
  74. " reflectedLight.directDiffuse += scatteringIllu * thicknessAttenuation * directLight.color;",
  75. "}",
  76. "void main() {",
  77. " vec3 normal = normalize( vNormal );",
  78. " vec3 viewerDirection = normalize( vViewPosition );",
  79. " vec4 diffuseColor = vec4( diffuse, opacity );",
  80. " ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );",
  81. THREE.ShaderChunk[ "map_fragment" ],
  82. THREE.ShaderChunk[ "color_fragment" ],
  83. THREE.ShaderChunk[ "specularmap_fragment" ],
  84. " vec3 totalEmissiveRadiance = emissive;",
  85. THREE.ShaderChunk[ "lights_phong_fragment" ],
  86. // Doing lights fragment begin.
  87. " GeometricContext geometry;",
  88. " geometry.position = - vViewPosition;",
  89. " geometry.normal = normal;",
  90. " geometry.viewDir = normalize( vViewPosition );",
  91. " IncidentLight directLight;",
  92. " #if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )",
  93. " PointLight pointLight;",
  94. " #pragma unroll_loop_start",
  95. " for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {",
  96. " pointLight = pointLights[ i ];",
  97. " getPointDirectLightIrradiance( pointLight, geometry, directLight );",
  98. " #ifdef USE_SHADOWMAP",
  99. " directLight.color *= all( bvec2( pointLight.shadow, directLight.visible ) ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;",
  100. " #endif",
  101. " RE_Direct( directLight, geometry, material, reflectedLight );",
  102. " #if defined( TRANSLUCENT ) && defined( USE_UV )",
  103. " RE_Direct_Scattering(directLight, vUv, geometry, reflectedLight);",
  104. " #endif",
  105. " }",
  106. " #pragma unroll_loop_end",
  107. " #endif",
  108. " #if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )",
  109. " DirectionalLight directionalLight;",
  110. " #pragma unroll_loop_start",
  111. " for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {",
  112. " directionalLight = directionalLights[ i ];",
  113. " getDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );",
  114. " #ifdef USE_SHADOWMAP",
  115. " directLight.color *= all( bvec2( directionalLight.shadow, directLight.visible ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;",
  116. " #endif",
  117. " RE_Direct( directLight, geometry, material, reflectedLight );",
  118. " #if defined( TRANSLUCENT ) && defined( USE_UV )",
  119. " RE_Direct_Scattering(directLight, vUv, geometry, reflectedLight);",
  120. " #endif",
  121. " }",
  122. " #pragma unroll_loop_end",
  123. " #endif",
  124. " #if defined( RE_IndirectDiffuse )",
  125. " vec3 irradiance = getAmbientLightIrradiance( ambientLightColor );",
  126. " #if ( NUM_HEMI_LIGHTS > 0 )",
  127. " #pragma unroll_loop_start",
  128. " for ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {",
  129. " irradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );",
  130. " }",
  131. " #pragma unroll_loop_end",
  132. " #endif",
  133. " #endif",
  134. " #if defined( RE_IndirectSpecular )",
  135. " vec3 radiance = vec3( 0.0 );",
  136. " vec3 clearcoatRadiance = vec3( 0.0 );",
  137. " #endif",
  138. THREE.ShaderChunk[ "lights_fragment_end" ],
  139. " vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;",
  140. " gl_FragColor = vec4( outgoingLight, diffuseColor.a );", // TODO, this should be pre-multiplied to allow for bright highlights on very transparent objects
  141. THREE.ShaderChunk[ "encodings_fragment" ],
  142. "}"
  143. ].join( "\n" ),
  144. };