|
|
|
|
|
|
m_CascadeSlices[cascadeIndex].offsetX = (cascadeIndex % 2) * shadowResolution; |
|
|
|
m_CascadeSlices[cascadeIndex].offsetY = (cascadeIndex / 2) * shadowResolution; |
|
|
|
m_CascadeSlices[cascadeIndex].resolution = shadowResolution; |
|
|
|
m_CascadeSlices[cascadeIndex].shadowTransform = GetShadowTransform(proj, view); |
|
|
|
|
|
|
|
// If we have shadow cascades baked into the atlas we bake cascade transform
|
|
|
|
// in each shadow matrix to save shader ALU and L/S
|
|
|
|
if (m_ShadowCasterCascadesCount > 1) |
|
|
|
ApplySliceTransform(ref m_CascadeSlices[cascadeIndex], m_ShadowSettings.directionalShadowAtlasWidth, m_ShadowSettings.directionalShadowAtlasHeight); |
|
|
|
SetupShadowSliceTransform(ref m_CascadeSlices[cascadeIndex], m_ShadowSettings.directionalShadowAtlasWidth, m_ShadowSettings.directionalShadowAtlasHeight, proj, view); |
|
|
|
RenderShadowSlice(cmd, ref context, ref m_CascadeSlices[cascadeIndex], proj, view, settings); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
List<int> localLightIndices = lightData.localLightIndices; |
|
|
|
List<VisibleLight> visibleLights = lightData.visibleLights; |
|
|
|
|
|
|
|
// TODO: for now we just support 1 local shadow casting light
|
|
|
|
const int kMaxLocalShadowCastingLightsCount = 1; |
|
|
|
|
|
|
|
if (shadowLight.lightType == LightType.Spot && shadowLight.light.shadows != LightShadows.None) |
|
|
|
if (shadowLight.lightType == LightType.Spot && shadowLight.light.shadows != LightShadows.None && shadowCastingLightsCount < kMaxLocalShadowCastingLightsCount) |
|
|
|
shadowCastingLightsCount++; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
VisibleLight shadowLight = visibleLights[shadowLightIndex]; |
|
|
|
Light light = shadowLight.light; |
|
|
|
|
|
|
|
// TODO: Add support to point light shadows
|
|
|
|
if (shadowLight.lightType != LightType.Spot || shadowLight.light.shadows == LightShadows.None) |
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
// This way of computing the shadow slice only work for spots and with most 4 shadow casting lights per pass
|
|
|
|
// Change this when point lights are supported.
|
|
|
|
Debug.Assert(kMaxLocalPixelLightPerPass == 4 && shadowLight.lightType == LightType.Spot); |
|
|
|
|
|
|
|
// TODO: We need to pass bias and scale list to shader to be able to support multiple
|
|
|
|
// shadow casting local lights.
|
|
|
|
m_LocalLightSlices[i].shadowTransform = GetShadowTransform(proj, view); |
|
|
|
SetupShadowSliceTransform(ref m_LocalLightSlices[i], atlasWidth, atlasHeight, proj, view); |
|
|
|
|
|
|
|
// TODO: only one local shadow casting light is supported for now.
|
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
cmd.Clear(); |
|
|
|
} |
|
|
|
|
|
|
|
private void SetupShadowSliceTransform(ref ShadowSliceData shadowSliceData, int atlasWidth, int atlasHeight, Matrix4x4 proj, Matrix4x4 view) |
|
|
|
private Matrix4x4 GetShadowTransform(Matrix4x4 proj, Matrix4x4 view) |
|
|
|
{ |
|
|
|
// Currently CullResults ComputeDirectionalShadowMatricesAndCullingPrimitives doesn't
|
|
|
|
// apply z reversal to projection matrix. We need to do it manually here.
|
|
|
|
|
|
|
textureScaleAndBias.m13 = 0.5f; |
|
|
|
|
|
|
|
// Apply texture scale and offset to save a MAD in shader.
|
|
|
|
worldToShadow = textureScaleAndBias * worldToShadow; |
|
|
|
return textureScaleAndBias * worldToShadow; |
|
|
|
} |
|
|
|
var cascadeAtlas = Matrix4x4.identity; |
|
|
|
private void ApplySliceTransform(ref ShadowSliceData shadowSliceData, int atlasWidth, int atlasHeight) |
|
|
|
{ |
|
|
|
Matrix4x4 sliceTransform = Matrix4x4.identity; |
|
|
|
cascadeAtlas.m00 = shadowSliceData.resolution * oneOverAtlasWidth; |
|
|
|
cascadeAtlas.m11 = shadowSliceData.resolution * oneOverAtlasHeight; |
|
|
|
cascadeAtlas.m03 = shadowSliceData.offsetX * oneOverAtlasWidth; |
|
|
|
cascadeAtlas.m13 = shadowSliceData.offsetY * oneOverAtlasHeight; |
|
|
|
sliceTransform.m00 = shadowSliceData.resolution * oneOverAtlasWidth; |
|
|
|
sliceTransform.m11 = shadowSliceData.resolution * oneOverAtlasHeight; |
|
|
|
sliceTransform.m03 = shadowSliceData.offsetX * oneOverAtlasWidth; |
|
|
|
sliceTransform.m13 = shadowSliceData.offsetY * oneOverAtlasHeight; |
|
|
|
worldToShadow = cascadeAtlas * worldToShadow; |
|
|
|
|
|
|
|
shadowSliceData.shadowTransform = worldToShadow; |
|
|
|
shadowSliceData.shadowTransform = sliceTransform * shadowSliceData.shadowTransform; |
|
|
|
} |
|
|
|
|
|
|
|
private void RenderShadowSlice(CommandBuffer cmd, ref ScriptableRenderContext context, ref ShadowSliceData shadowSliceData, |
|
|
|