168 auto* renderer = app->GetRenderer();
169 if (!renderer)
return;
173 for (
size_t i = 0; i < m_lights.GetSize(); ++i) {
174 Light* light = m_lights[i];
179 shadowLight = dirLight;
188 for (
size_t i = 0; i < m_lights.GetSize(); ++i) {
189 Light* light = m_lights[i];
190 if (!light || !light->
IsEnabled())
continue;
193 anyDirLight = dirLight;
200 renderer->SetShadowPassEnabled(shadowLight !=
nullptr);
206 static bool warned =
false;
207 if (!warned) {
SLEAK_WARN(
"UpdateShadowData: No directional light found!"); warned =
true; }
212 auto color = activeLight->
GetColor();
229 + dir * (-shadowDist);
246 float left = -frustumSize, right = frustumSize;
247 float bottom = -frustumSize, top = frustumSize;
249 lightProj(0, 0) = 2.0f / (right - left);
250 lightProj(1, 1) = 2.0f / (top - bottom);
251 lightProj(2, 2) = 1.0f / (farP - nearP);
252 lightProj(3, 0) = -(right + left) / (right - left);
253 lightProj(3, 1) = -(top + bottom) / (top - bottom);
254 lightProj(3, 2) = -nearP / (farP - nearP);
265 const float shadowMapSize =
266 static_cast<float>(renderer->GetShadowMapResolution());
267 const float halfShadow = shadowMapSize * 0.5f;
277 float clipX = lightVP_raw(3, 0);
278 float clipY = lightVP_raw(3, 1);
279 float clipW = lightVP_raw(3, 3);
281 float ndcX = clipX / clipW;
282 float ndcY = clipY / clipW;
283 float texX = ndcX * halfShadow;
284 float texY = ndcY * halfShadow;
285 float roundedX = std::round(texX);
286 float roundedY = std::round(texY);
287 float offsetNdcX = (roundedX - texX) / halfShadow;
288 float offsetNdcY = (roundedY - texY) / halfShadow;
289 lightProj(3, 0) += offsetNdcX;
290 lightProj(3, 1) += offsetNdcY;
294 lightVP = lightView * lightProj;
302 static bool s_latched =
false;
303 static float s_frozenVP[16];
304 if (s_freeze && shadowLight) {
306 std::memcpy(s_frozenVP, &lightVP(0, 0),
sizeof(s_frozenVP));
308 SLEAK_WARN(
"shadowfreeze: light frustum latched");
310 std::memcpy(&lightVP(0, 0), s_frozenVP,
sizeof(s_frozenVP));
316 renderer->SetLightVP(&lightVP(0, 0));
335 ubo.
Ambient[3] = m_ambientIntensity;
352 std::memcpy(ubo.
LightVP, &lightVP(0, 0),
sizeof(
float) * 16);
363 if (Invert4x4(&camVP(0, 0), invVP)) {
365 std::memcpy(&invVPm(0, 0), invVP,
sizeof(
float) * 16);
366 std::memcpy(&lightVPm(0, 0), ubo.
LightVP,
sizeof(
float) * 16);
368 std::memcpy(ubo.
NdcToShadow, &comp(0, 0),
sizeof(
float) * 16);
377 1.0f /
static_cast<float>(renderer->GetShadowMapResolution());
406 for (
size_t i = 0; i < m_lights.GetSize() && ubo.
NumExtraLights < 3; ++i) {
407 Light* light = m_lights[i];
408 if (!light || !light->
IsEnabled())
continue;
409 if (light == activeLight)
continue;
411 if (!dlight)
continue;
413 auto eColor = dlight->GetColor();
426 renderer->UpdateShadowLightUBO(&ubo,
sizeof(ubo));