-
-
Notifications
You must be signed in to change notification settings - Fork 35.4k
/
transmission_pars_fragment.glsl.js
119 lines (75 loc) · 3.6 KB
/
transmission_pars_fragment.glsl.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
export default /* glsl */`
#ifdef USE_TRANSMISSION
// Transmission code is based on glTF-Sampler-Viewer
// https://github.com/KhronosGroup/glTF-Sample-Viewer
uniform float transmission;
uniform float thickness;
uniform float attenuationDistance;
uniform vec3 attenuationTint;
#ifdef USE_TRANSMISSIONMAP
uniform sampler2D transmissionMap;
#endif
#ifdef USE_THICKNESSMAP
uniform sampler2D thicknessMap;
#endif
uniform vec2 transmissionSamplerSize;
uniform sampler2D transmissionSamplerMap;
uniform mat4 modelMatrix;
uniform mat4 projectionMatrix;
varying vec3 vWorldPosition;
vec3 getVolumeTransmissionRay( vec3 n, vec3 v, float thickness, float ior, mat4 modelMatrix ) {
// Direction of refracted light.
vec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );
// Compute rotation-independant scaling of the model matrix.
vec3 modelScale;
modelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );
modelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );
modelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );
// The thickness is specified in local space.
return normalize( refractionVector ) * thickness * modelScale;
}
float applyIorToRoughness( float roughness, float ior ) {
// Scale roughness with IOR so that an IOR of 1.0 results in no microfacet refraction and
// an IOR of 1.5 results in the default amount of microfacet refraction.
return roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );
}
vec3 getTransmissionSample( vec2 fragCoord, float roughness, float ior ) {
float framebufferLod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );
#ifdef TEXTURE_LOD_EXT
return texture2DLodEXT( transmissionSamplerMap, fragCoord.xy, framebufferLod ).rgb;
#else
return texture2D( transmissionSamplerMap, fragCoord.xy, framebufferLod ).rgb;
#endif
}
vec3 applyVolumeAttenuation( vec3 radiance, float transmissionDistance, vec3 attenuationColor, float attenuationDistance ) {
if ( attenuationDistance == 0.0 ) {
// Attenuation distance is +∞ (which we indicate by zero), i.e. the transmitted color is not attenuated at all.
return radiance;
} else {
// Compute light attenuation using Beer's law.
vec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;
vec3 transmittance = exp( - attenuationCoefficient * transmissionDistance ); // Beer's law
return transmittance * radiance;
}
}
vec3 getIBLVolumeRefraction( vec3 n, vec3 v, float roughness, vec3 diffuseColor, vec3 specularColor, float specularF90,
vec3 position, mat4 modelMatrix, mat4 viewMatrix, mat4 projMatrix, float ior, float thickness,
vec3 attenuationColor, float attenuationDistance ) {
vec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );
vec3 refractedRayExit = position + transmissionRay;
// Project refracted vector on the framebuffer, while mapping to normalized device coordinates.
vec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );
vec2 refractionCoords = ndcPos.xy / ndcPos.w;
refractionCoords += 1.0;
refractionCoords /= 2.0;
// Sample framebuffer to get pixel the refracted ray hits.
vec3 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );
vec3 attenuatedColor = applyVolumeAttenuation( transmittedLight, length( transmissionRay ), attenuationColor, attenuationDistance );
// Get the specular component.
float dotNV = saturate( dot( n, v ) );
vec2 brdf = integrateSpecularBRDF( dotNV, roughness );
vec3 F = specularColor * brdf.x + specularF90 * brdf.y;
return ( 1.0 - F ) * attenuatedColor * diffuseColor;
}
#endif
`;