|
@@ -29,61 +29,76 @@ export default /* glsl */`
|
|
|
|
|
|
varying vec3 vWorldPosition;
|
|
varying vec3 vWorldPosition;
|
|
|
|
|
|
- vec3 getVolumeTransmissionRay(vec3 n, vec3 v, float thickness, float ior, mat4 modelMatrix) {
|
|
|
|
|
|
+ vec3 getVolumeTransmissionRay( vec3 n, vec3 v, float thickness, float ior, mat4 modelMatrix ) {
|
|
|
|
+
|
|
// Direction of refracted light.
|
|
// Direction of refracted light.
|
|
- vec3 refractionVector = refract(-v, normalize(n), 1.0 / ior);
|
|
|
|
|
|
+ vec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );
|
|
|
|
|
|
// Compute rotation-independant scaling of the model matrix.
|
|
// Compute rotation-independant scaling of the model matrix.
|
|
vec3 modelScale;
|
|
vec3 modelScale;
|
|
- modelScale.x = length(vec3(modelMatrix[0].xyz));
|
|
|
|
- modelScale.y = length(vec3(modelMatrix[1].xyz));
|
|
|
|
- modelScale.z = length(vec3(modelMatrix[2].xyz));
|
|
|
|
|
|
+ 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.
|
|
// The thickness is specified in local space.
|
|
- return normalize(refractionVector) * thickness * modelScale;
|
|
|
|
|
|
+ return normalize( refractionVector ) * thickness * modelScale;
|
|
|
|
+
|
|
}
|
|
}
|
|
|
|
|
|
- float applyIorToRoughness(float roughness, float ior) {
|
|
|
|
|
|
+ float applyIorToRoughness( float roughness, float ior ) {
|
|
|
|
+
|
|
// Scale roughness with IOR so that an IOR of 1.0 results in no microfacet refraction and
|
|
// 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.
|
|
// 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);
|
|
|
|
|
|
+ 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);
|
|
|
|
- return texture2DLodEXT(transmissionSamplerMap, fragCoord.xy, framebufferLod).rgb;
|
|
|
|
|
|
+ vec3 getTransmissionSample( vec2 fragCoord, float roughness, float ior ) {
|
|
|
|
+
|
|
|
|
+ float framebufferLod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );
|
|
|
|
+
|
|
|
|
+ return texture2DLodEXT( transmissionSamplerMap, fragCoord.xy, framebufferLod ).rgb;
|
|
|
|
+
|
|
}
|
|
}
|
|
|
|
|
|
- vec3 applyVolumeAttenuation(vec3 radiance, float transmissionDistance, vec3 attenuationColor, float attenuationDistance) {
|
|
|
|
- if (attenuationDistance == 0.0) {
|
|
|
|
|
|
+ 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.
|
|
// Attenuation distance is +∞ (which we indicate by zero), i.e. the transmitted color is not attenuated at all.
|
|
return radiance;
|
|
return radiance;
|
|
|
|
+
|
|
} else {
|
|
} else {
|
|
|
|
+
|
|
// Compute light attenuation using Beer's law.
|
|
// Compute light attenuation using Beer's law.
|
|
- vec3 attenuationCoefficient = -log(attenuationColor) / attenuationDistance;
|
|
|
|
- vec3 transmittance = exp(-attenuationCoefficient * transmissionDistance); // Beer's law
|
|
|
|
|
|
+ vec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;
|
|
|
|
+ vec3 transmittance = exp( - attenuationCoefficient * transmissionDistance ); // Beer's law
|
|
return transmittance * radiance;
|
|
return transmittance * radiance;
|
|
|
|
+
|
|
}
|
|
}
|
|
|
|
+
|
|
}
|
|
}
|
|
|
|
|
|
- vec3 getIBLVolumeRefraction(vec3 n, vec3 v, float perceptualRoughness, vec3 baseColor, vec3 specularColor,
|
|
|
|
|
|
+ vec3 getIBLVolumeRefraction( vec3 n, vec3 v, float perceptualRoughness, vec3 baseColor, vec3 specularColor,
|
|
vec3 position, mat4 modelMatrix, mat4 viewMatrix, mat4 projMatrix, float ior, float thickness,
|
|
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 attenuationColor, float attenuationDistance ) {
|
|
|
|
+
|
|
|
|
+ vec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );
|
|
vec3 refractedRayExit = position + transmissionRay;
|
|
vec3 refractedRayExit = position + transmissionRay;
|
|
|
|
|
|
// Project refracted vector on the framebuffer, while mapping to normalized device coordinates.
|
|
// Project refracted vector on the framebuffer, while mapping to normalized device coordinates.
|
|
- vec4 ndcPos = projMatrix * viewMatrix * vec4(refractedRayExit, 1.0);
|
|
|
|
|
|
+ vec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );
|
|
vec2 refractionCoords = ndcPos.xy / ndcPos.w;
|
|
vec2 refractionCoords = ndcPos.xy / ndcPos.w;
|
|
refractionCoords += 1.0;
|
|
refractionCoords += 1.0;
|
|
refractionCoords /= 2.0;
|
|
refractionCoords /= 2.0;
|
|
|
|
|
|
// Sample framebuffer to get pixel the refracted ray hits.
|
|
// Sample framebuffer to get pixel the refracted ray hits.
|
|
- vec3 transmittedLight = getTransmissionSample(refractionCoords, perceptualRoughness, ior);
|
|
|
|
|
|
+ vec3 transmittedLight = getTransmissionSample( refractionCoords, perceptualRoughness, ior );
|
|
|
|
+
|
|
|
|
+ vec3 attenuatedColor = applyVolumeAttenuation( transmittedLight, length( transmissionRay ), attenuationColor, attenuationDistance );
|
|
|
|
|
|
- vec3 attenuatedColor = applyVolumeAttenuation(transmittedLight, length(transmissionRay), attenuationColor, attenuationDistance);
|
|
|
|
|
|
+ return ( 1.0 - specularColor ) * attenuatedColor * baseColor;
|
|
|
|
|
|
- return (1.0 - specularColor) * attenuatedColor * baseColor;
|
|
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
`;
|
|
`;
|