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 };
 |