91 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			91 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|  | import { | |||
|  | 	Color, | |||
|  | 	ShaderChunk, | |||
|  | 	ShaderLib, | |||
|  | 	UniformsUtils | |||
|  | } from 'three'; | |||
|  | 
 | |||
|  | /** | |||
|  |  * ------------------------------------------------------------------------------------------ | |||
|  |  * 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 ); | |||
|  | 
 | |||
|  | } | |||
|  | 
 | |||
|  | const meshphong_frag_head = ShaderChunk[ 'meshphong_frag' ].slice( 0, ShaderChunk[ 'meshphong_frag' ].indexOf( 'void main() {' ) ); | |||
|  | const meshphong_frag_body = ShaderChunk[ 'meshphong_frag' ].slice( ShaderChunk[ 'meshphong_frag' ].indexOf( 'void main() {' ) ); | |||
|  | 
 | |||
|  | const SubsurfaceScatteringShader = { | |||
|  | 
 | |||
|  | 	name: '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 vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, inout ReflectedLight reflectedLight) {', | |||
|  | 		'	vec3 thickness = thicknessColor * texture2D(thicknessMap, uv).r;', | |||
|  | 		'	vec3 scatteringHalf = normalize(directLight.direction + (geometryNormal * thicknessDistortion));', | |||
|  | 		'	float scatteringDot = pow(saturate(dot(geometryViewDir, -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, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );', | |||
|  | 				[ | |||
|  | 					'RE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );', | |||
|  | 
 | |||
|  | 					'#if defined( SUBSURFACE ) && defined( USE_UV )', | |||
|  | 					' RE_Direct_Scattering(directLight, vUv, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, reflectedLight);', | |||
|  | 					'#endif', | |||
|  | 				].join( '\n' ) | |||
|  | 			), | |||
|  | 
 | |||
|  | 		), | |||
|  | 
 | |||
|  | 	].join( '\n' ), | |||
|  | 
 | |||
|  | }; | |||
|  | 
 | |||
|  | export { SubsurfaceScatteringShader }; |