Spaces:
Running
Running
| /** | |
| * @author daoshengmu / http://dsmu.me/ | |
| * | |
| */ | |
| THREE.TranslucentShader = function TranslucentShader() { | |
| /* ------------------------------------------------------------------------------------------ | |
| // Subsurface Scattering shader | |
| // - Base on GDC 2011 – Approximating Translucency for a Fast, Cheap and Convincing Subsurface Scattering Look | |
| // https://colinbarrebrisebois.com/2011/03/07/gdc-2011-approximating-translucency-for-a-fast-cheap-and-convincing-subsurface-scattering-look/ | |
| // ------------------------------------------------------------------------------------------ */ | |
| this.uniforms = THREE.UniformsUtils.merge( [ | |
| THREE.UniformsLib[ "common" ], | |
| THREE.UniformsLib[ "lights" ], | |
| { | |
| "color": { value: new THREE.Color( 0xffffff ) }, | |
| "diffuse": { value: new THREE.Color( 0xffffff ) }, | |
| "specular": { value: new THREE.Color( 0xffffff ) }, | |
| "emissive": { value: new THREE.Color( 0x000000 ) }, | |
| "opacity": { value: 1 }, | |
| "shininess": { value: 1 }, | |
| "thicknessMap": { value: null }, | |
| "thicknessColor": { value: new THREE.Color( 0xffffff ) }, | |
| "thicknessDistortion": { value: 0.1 }, | |
| "thicknessAmbient": { value: 0.0 }, | |
| "thicknessAttenuation": { value: 0.1 }, | |
| "thicknessPower": { value: 2.0 }, | |
| "thicknessScale": { value: 10.0 } | |
| } | |
| ] ); | |
| this.fragmentShader = [ | |
| "#define USE_MAP", | |
| "#define PHONG", | |
| "#define TRANSLUCENT", | |
| "#include <common>", | |
| "#include <bsdfs>", | |
| "#include <uv_pars_fragment>", | |
| "#include <map_pars_fragment>", | |
| "#include <lights_phong_pars_fragment>", | |
| "varying vec3 vColor;", | |
| "uniform vec3 diffuse;", | |
| "uniform vec3 specular;", | |
| "uniform vec3 emissive;", | |
| "uniform float opacity;", | |
| "uniform float shininess;", | |
| // Translucency | |
| "uniform sampler2D thicknessMap;", | |
| "uniform float thicknessPower;", | |
| "uniform float thicknessScale;", | |
| "uniform float thicknessDistortion;", | |
| "uniform float thicknessAmbient;", | |
| "uniform float thicknessAttenuation;", | |
| "uniform vec3 thicknessColor;", | |
| THREE.ShaderChunk[ "lights_pars_begin" ], | |
| "void RE_Direct_Scattering(const in IncidentLight directLight, const in vec2 uv, const in GeometricContext geometry, inout ReflectedLight reflectedLight) {", | |
| " vec3 thickness = thicknessColor * texture2D(thicknessMap, uv).r;", | |
| " vec3 scatteringHalf = normalize(directLight.direction + (geometry.normal * thicknessDistortion));", | |
| " float scatteringDot = pow(saturate(dot(geometry.viewDir, -scatteringHalf)), thicknessPower) * thicknessScale;", | |
| " vec3 scatteringIllu = (scatteringDot + thicknessAmbient) * thickness;", | |
| " reflectedLight.directDiffuse += scatteringIllu * thicknessAttenuation * directLight.color;", | |
| "}", | |
| "void main() {", | |
| " vec3 normal = normalize( vNormal );", | |
| " vec3 viewerDirection = normalize( vViewPosition );", | |
| " vec4 diffuseColor = vec4( diffuse, opacity );", | |
| " ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );", | |
| THREE.ShaderChunk[ "map_fragment" ], | |
| THREE.ShaderChunk[ "color_fragment" ], | |
| THREE.ShaderChunk[ "specularmap_fragment" ], | |
| " vec3 totalEmissiveRadiance = emissive;", | |
| THREE.ShaderChunk["lights_phong_fragment"], | |
| // Doing lights fragment begin. | |
| " GeometricContext geometry;", | |
| " geometry.position = - vViewPosition;", | |
| " geometry.normal = normal;", | |
| " geometry.viewDir = normalize( vViewPosition );", | |
| " IncidentLight directLight;", | |
| " #if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )", | |
| " PointLight pointLight;", | |
| " #pragma unroll_loop", | |
| " for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {", | |
| " pointLight = pointLights[ i ];", | |
| " getPointDirectLightIrradiance( pointLight, geometry, directLight );", | |
| " #ifdef USE_SHADOWMAP", | |
| " 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;", | |
| " #endif", | |
| " RE_Direct( directLight, geometry, material, reflectedLight );", | |
| " #if defined( TRANSLUCENT ) && defined( USE_MAP )", | |
| " RE_Direct_Scattering(directLight, vUv, geometry, reflectedLight);", | |
| " #endif", | |
| " }", | |
| " #endif", | |
| " #if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )", | |
| " DirectionalLight directionalLight;", | |
| " #pragma unroll_loop", | |
| " for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {", | |
| " directionalLight = directionalLights[ i ];", | |
| " getDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );", | |
| " #ifdef USE_SHADOWMAP", | |
| " directLight.color *= all( bvec2( directionalLight.shadow, directLight.visible ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;", | |
| " #endif", | |
| " RE_Direct( directLight, geometry, material, reflectedLight );", | |
| " #if defined( TRANSLUCENT ) && defined( USE_MAP )", | |
| " RE_Direct_Scattering(directLight, vUv, geometry, reflectedLight);", | |
| " #endif", | |
| " }", | |
| " #endif", | |
| " #if defined( RE_IndirectDiffuse )", | |
| " vec3 irradiance = getAmbientLightIrradiance( ambientLightColor );", | |
| " #if ( NUM_HEMI_LIGHTS > 0 )", | |
| " #pragma unroll_loop", | |
| " for ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {", | |
| " irradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );", | |
| " }", | |
| " #endif", | |
| " #endif", | |
| " #if defined( RE_IndirectSpecular )", | |
| " vec3 radiance = vec3( 0.0 );", | |
| " vec3 clearCoatRadiance = vec3( 0.0 );", | |
| " #endif", | |
| THREE.ShaderChunk["lights_fragment_end"], | |
| " vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;", | |
| " gl_FragColor = vec4( outgoingLight, diffuseColor.a );", // TODO, this should be pre-multiplied to allow for bright highlights on very transparent objects | |
| THREE.ShaderChunk["encodings_fragment"], | |
| "}" | |
| ].join( "\n" ), | |
| this.vertexShader = [ | |
| "varying vec3 vNormal;", | |
| "varying vec2 vUv;", | |
| "varying vec3 vViewPosition;", | |
| THREE.ShaderChunk[ "common" ], | |
| "void main() {", | |
| " vec4 worldPosition = modelMatrix * vec4( position, 1.0 );", | |
| " vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );", | |
| " vViewPosition = -mvPosition.xyz;", | |
| " vNormal = normalize( normalMatrix * normal );", | |
| " vUv = uv;", | |
| " gl_Position = projectionMatrix * mvPosition;", | |
| "}", | |
| ].join( "\n" ) | |
| }; | |