|
|
|
|
|
|
// a. Get the corresponding color depending on the roughness from the gaussian pyramid of the color buffer |
|
|
|
// b. Multiply by the transmittance for absorption (depends on the optical depth) |
|
|
|
|
|
|
|
float3 positionVS = mul(UNITY_MATRIX_V, float4(preLightData.transparentPositionWS, 1)).xyz; |
|
|
|
float3 transparentRefractVVS = mul(UNITY_MATRIX_V, float4(preLightData.transparentRefractV, 0)).xyz; |
|
|
|
// Refraction process: |
|
|
|
// 1. Depending on the shape model, we calculate the refracted point in world space and the optical depth |
|
|
|
// 2. We calculate the screen space position of the refracted point |
|
|
|
// 3. If this point is available (ie: in color buffer and point is not in front of the object) |
|
|
|
// a. Get the corresponding color depending on the roughness from the gaussian pyramid of the color buffer |
|
|
|
// b. Multiply by the transmittance for absorption (depends on the optical depth) |
|
|
|
uint2 depthSize = uint2(_PyramidDepthMipSize.xy); |
|
|
|
float3 positionVS = mul(UNITY_MATRIX_V, float4(preLightData.transparentPositionWS, 1)).xyz; |
|
|
|
float3 transparentRefractVVS = mul(UNITY_MATRIX_V, float4(preLightData.transparentRefractV, 0)).xyz; |
|
|
|
ScreenSpaceRaymarchInput ssInput; |
|
|
|
ZERO_INITIALIZE(ScreenSpaceRaymarchInput, ssInput); |
|
|
|
uint2 depthSize = uint2(_PyramidDepthMipSize.xy); |
|
|
|
|
|
|
|
ScreenSpaceRaymarchInput ssInput; |
|
|
|
ZERO_INITIALIZE(ScreenSpaceRaymarchInput, ssInput); |
|
|
|
|
|
|
|
ScreenSpaceRayHit hit; |
|
|
|
ZERO_INITIALIZE(ScreenSpaceRayHit, hit); |
|
|
|
|
|
|
|
ssInput.startPositionVS = positionVS; |
|
|
|
ssInput.startLinearDepth = posInput.linearDepth; |
|
|
|
ssInput.dirVS = transparentRefractVVS; |
|
|
|
ssInput.projectionMatrix = UNITY_MATRIX_P; |
|
|
|
ssInput.bufferSize = depthSize; |
|
|
|
ssInput.minLevel = 2; |
|
|
|
ssInput.maxLevel = int(_PyramidDepthMipSize.z); |
|
|
|
ScreenSpaceRayHit hit; |
|
|
|
ZERO_INITIALIZE(ScreenSpaceRayHit, hit); |
|
|
|
|
|
|
|
ssInput.startPositionVS = positionVS; |
|
|
|
ssInput.startLinearDepth = posInput.linearDepth; |
|
|
|
ssInput.dirVS = transparentRefractVVS; |
|
|
|
ssInput.projectionMatrix = UNITY_MATRIX_P; |
|
|
|
ssInput.bufferSize = depthSize; |
|
|
|
ssInput.minLevel = 2; |
|
|
|
ssInput.maxLevel = int(_PyramidDepthMipSize.z); |
|
|
|
ssInput.writeStepDebug = (uint2(_MouseClickPixelCoord.xy) == posInput.positionSS); |
|
|
|
ssInput.writeStepDebug = (uint2(_MouseClickPixelCoord.xy) == posInput.positionSS); |
|
|
|
bool hitSuccessful = ScreenSpaceRaymarch(ssInput, hit); |
|
|
|
bool hitSuccessful = ScreenSpaceRaymarch(ssInput, hit); |
|
|
|
if (_DebugLightingMode == DEBUGLIGHTINGMODE_SCREEN_SPACE_TRACING_REFRACTION) |
|
|
|
{ |
|
|
|
float weight = 1.0; |
|
|
|
UpdateLightingHierarchyWeights(hierarchyWeight, weight); |
|
|
|
lighting.specularTransmitted = hit.debugOutput; |
|
|
|
return lighting; |
|
|
|
} |
|
|
|
if (_DebugLightingMode == DEBUGLIGHTINGMODE_SCREEN_SPACE_TRACING_REFRACTION) |
|
|
|
{ |
|
|
|
float weight = 1.0; |
|
|
|
UpdateLightingHierarchyWeights(hierarchyWeight, weight); |
|
|
|
lighting.specularTransmitted = hit.debugOutput; |
|
|
|
return lighting; |
|
|
|
} |
|
|
|
if (!hitSuccessful) |
|
|
|
return lighting; |
|
|
|
|
|
|
|
//float3 refractedBackPointWS = EstimateRaycast(V, posInput, preLightData.transparentPositionWS, preLightData.transparentRefractV); |
|
|
|
//float3 refractedBackPointWS = preLightData.transparentPositionWS + preLightData.transparentRefractV * hitDistance; |
|
|
|
|
|
|
|
|
|
|
|
// Calculate screen space coordinates of refracted point in back plane |
|
|
|
//float2 refractedBackPointNDC = ComputeNormalizedDeviceCoordinates(refractedBackPointWS, UNITY_MATRIX_VP); |
|
|
|
//float refractedBackPointDepth = LinearEyeDepth(LOAD_TEXTURE2D_LOD(_PyramidDepthTexture, refractedBackPointNDC * depthSize, 0).r, _ZBufferParams); |
|
|
|
if (!hitSuccessful) |
|
|
|
return lighting; |
|
|
|
// Exit if texel is out of color buffer |
|
|
|
// Or if the texel is from an object in front of the object |
|
|
|
if (hit.linearDepth < posInput.linearDepth |
|
|
|
|| any(hit.positionSS < 0.0) |
|
|
|
|| any(hit.positionSS > 1.0)) |
|
|
|
{ |
|
|
|
// Do nothing and don't update the hierarchy weight so we can fall back on refraction probe |
|
|
|
return lighting; |
|
|
|
} |
|
|
|
|
|
|
|
// Map the roughness to the correct mip map level of the color pyramid |
|
|
|
lighting.specularTransmitted = SAMPLE_TEXTURE2D_LOD(_GaussianPyramidColorTexture, s_trilinear_clamp_sampler, hit.positionSS * _GaussianPyramidColorMipSize.xy, preLightData.transparentSSMipLevel).rgb; |
|
|
|
// Exit if texel is out of color buffer |
|
|
|
// Or if the texel is from an object in front of the object |
|
|
|
if (hit.linearDepth < posInput.linearDepth |
|
|
|
|| any(hit.positionSS < 0.0) |
|
|
|
|| any(hit.positionSS > 1.0)) |
|
|
|
{ |
|
|
|
// Do nothing and don't update the hierarchy weight so we can fall back on refraction probe |
|
|
|
return lighting; |
|
|
|
} |
|
|
|
// Beer-Lamber law for absorption |
|
|
|
lighting.specularTransmitted *= preLightData.transparentTransmittance; |
|
|
|
// Map the roughness to the correct mip map level of the color pyramid |
|
|
|
lighting.specularTransmitted = SAMPLE_TEXTURE2D_LOD(_GaussianPyramidColorTexture, s_trilinear_clamp_sampler, hit.positionSS * _GaussianPyramidColorMipSize.xy, preLightData.transparentSSMipLevel).rgb; |
|
|
|
float weight = 1.0; |
|
|
|
UpdateLightingHierarchyWeights(hierarchyWeight, weight); // Shouldn't be needed, but safer in case we decide to change hierarchy priority |
|
|
|
// We use specularFGD as an approximation of the fresnel effect (that also handle smoothness), so take the remaining for transmission |
|
|
|
lighting.specularTransmitted *= (1.0 - preLightData.specularFGD) * weight; |
|
|
|
// Beer-Lamber law for absorption |
|
|
|
lighting.specularTransmitted *= preLightData.transparentTransmittance; |
|
|
|
// DEBUG Depth |
|
|
|
lighting.specularTransmitted = hit.linearDepth; |
|
|
|
float weight = 1.0; |
|
|
|
UpdateLightingHierarchyWeights(hierarchyWeight, weight); // Shouldn't be needed, but safer in case we decide to change hierarchy priority |
|
|
|
// We use specularFGD as an approximation of the fresnel effect (that also handle smoothness), so take the remaining for transmission |
|
|
|
lighting.specularTransmitted *= (1.0 - preLightData.specularFGD) * weight; |
|
|
|
|
|
|
|
#else |
|
|
|
// No refraction, no need to go further |
|
|
|