three
Version:
JavaScript 3D library
88 lines (68 loc) • 2.93 kB
JavaScript
import {
Color,
ShaderChunk,
ShaderLib,
UniformsUtils
} from "../../../build/three.module.js";
/**
* ------------------------------------------------------------------------------------------
* Subsurface Scattering shader
* Based 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/
*------------------------------------------------------------------------------------------
*/
function replaceAll( string, find, replace ) {
return string.split( find ).join( replace );
}
var meshphong_frag_head = ShaderChunk[ "meshphong_frag" ].slice( 0, ShaderChunk[ "meshphong_frag" ].indexOf( 'void main() {' ) );
var meshphong_frag_body = ShaderChunk[ "meshphong_frag" ].slice( ShaderChunk[ "meshphong_frag" ].indexOf( 'void main() {' ) );
var SubsurfaceScatteringShader = {
uniforms: UniformsUtils.merge( [
ShaderLib[ "phong" ].uniforms,
{
"thicknessMap": { value: null },
"thicknessColor": { value: new Color( 0xffffff ) },
"thicknessDistortion": { value: 0.1 },
"thicknessAmbient": { value: 0.0 },
"thicknessAttenuation": { value: 0.1 },
"thicknessPower": { value: 2.0 },
"thicknessScale": { value: 10.0 }
}
] ),
vertexShader: [
"#define USE_UV",
ShaderChunk[ "meshphong_vert" ],
].join( "\n" ),
fragmentShader: [
"#define USE_UV",
"#define SUBSURFACE",
meshphong_frag_head,
"uniform sampler2D thicknessMap;",
"uniform float thicknessPower;",
"uniform float thicknessScale;",
"uniform float thicknessDistortion;",
"uniform float thicknessAmbient;",
"uniform float thicknessAttenuation;",
"uniform vec3 thicknessColor;",
"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;",
"}",
meshphong_frag_body.replace( "#include <lights_fragment_begin>",
replaceAll(
ShaderChunk[ 'lights_fragment_begin' ],
'RE_Direct( directLight, geometry, material, reflectedLight );',
[
"RE_Direct( directLight, geometry, material, reflectedLight );",
"#if defined( SUBSURFACE ) && defined( USE_UV )",
" RE_Direct_Scattering(directLight, vUv, geometry, reflectedLight);",
"#endif",
].join( "\n" )
),
),
].join( "\n" ),
};
export { SubsurfaceScatteringShader };