| 1107 | } |
| 1108 | |
| 1109 | void ShadowsPass::SetupShadows(RenderContext& renderContext, RenderContextBatch& renderContextBatch) |
| 1110 | { |
| 1111 | PROFILE_CPU(); |
| 1112 | |
| 1113 | // Early out and skip shadows setup if no lights is actively casting shadows |
| 1114 | // RenderBuffers will automatically free any old ShadowsCustomBuffer after a few frames if we don't update LastFrameUsed |
| 1115 | Array<RenderLightData*, RendererAllocation> shadowedLights; |
| 1116 | if (_shadowMapFormat != PixelFormat::Unknown && EnumHasAllFlags(renderContext.View.Flags, ViewFlags::Shadows) && !checkIfSkipPass()) |
| 1117 | { |
| 1118 | for (auto& light : renderContext.List->DirectionalLights) |
| 1119 | { |
| 1120 | if (light.CanRenderShadow(renderContext.View)) |
| 1121 | shadowedLights.Add(&light); |
| 1122 | } |
| 1123 | for (auto& light : renderContext.List->SpotLights) |
| 1124 | { |
| 1125 | if (light.CanRenderShadow(renderContext.View)) |
| 1126 | shadowedLights.Add(&light); |
| 1127 | } |
| 1128 | for (auto& light : renderContext.List->PointLights) |
| 1129 | { |
| 1130 | if (light.CanRenderShadow(renderContext.View)) |
| 1131 | shadowedLights.Add(&light); |
| 1132 | } |
| 1133 | } |
| 1134 | const auto currentFrame = Engine::FrameCount; |
| 1135 | if (shadowedLights.IsEmpty()) |
| 1136 | { |
| 1137 | // Invalidate any existing custom buffer that could have been used by the same task (eg. when rendering 6 sides of env probe) |
| 1138 | if (auto* old = (ShadowsCustomBuffer*)renderContext.Buffers->FindCustomBuffer<ShadowsCustomBuffer>(TEXT("Shadows"), false)) |
| 1139 | { |
| 1140 | if (old->LastFrameUsed == currentFrame) |
| 1141 | old->LastFrameUsed = 0; |
| 1142 | } |
| 1143 | return; |
| 1144 | } |
| 1145 | |
| 1146 | // Initialize shadow atlas |
| 1147 | auto& shadows = *renderContext.Buffers->GetCustomBuffer<ShadowsCustomBuffer>(TEXT("Shadows"), false); |
| 1148 | shadows.LinkedShadows = renderContext.Buffers->FindLinkedBuffer<ShadowsCustomBuffer>(TEXT("Shadows")); |
| 1149 | if (shadows.LinkedShadows && (shadows.LinkedShadows->LastFrameUsed != currentFrame || shadows.LinkedShadows->ViewOrigin != renderContext.View.Origin)) |
| 1150 | shadows.LinkedShadows = nullptr; // Don't use incompatible linked shadows buffer |
| 1151 | if (shadows.LastFrameUsed == currentFrame) |
| 1152 | shadows.Reset(); |
| 1153 | shadows.LastFrameUsed = currentFrame; |
| 1154 | shadows.MaxShadowsQuality = Math::Clamp(Math::Min<int32>((int32)Graphics::ShadowsQuality, (int32)renderContext.View.MaxShadowsQuality), 0, (int32)Quality::MAX - 1); |
| 1155 | shadows.EnableStaticShadows = !renderContext.View.IsOfflinePass && !renderContext.View.IsSingleFrame && !shadows.LinkedShadows; |
| 1156 | int32 atlasResolution; |
| 1157 | switch (Graphics::ShadowMapsQuality) |
| 1158 | { |
| 1159 | case Quality::Low: |
| 1160 | atlasResolution = 1024; |
| 1161 | break; |
| 1162 | case Quality::Medium: |
| 1163 | atlasResolution = 2048; |
| 1164 | break; |
| 1165 | case Quality::High: |
| 1166 | atlasResolution = 4096; |
no test coverage detected