vkdoom_m/src/rendering/hwrenderer/hw_dynlightdata.cpp
Christoph Oelckers f662c629e3 - ensure that shadowmap indices only get set when shadowmaps are enabled.
Having valid indices set when shadowmaps are off would cause the shader to run the full checks for all lights.
2021-08-11 10:06:22 +02:00

157 lines
4.4 KiB
C++

//
//---------------------------------------------------------------------------
//
// Copyright(C) 2002-2018 Christoph Oelckers
// All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see http://www.gnu.org/licenses/
//
//--------------------------------------------------------------------------
//
/*
** gl_dynlight1.cpp
** dynamic light application
**
**/
#include "actorinlines.h"
#include "a_dynlight.h"
#include "hw_dynlightdata.h"
#include"hw_cvars.h"
#include "v_video.h"
#include "hwrenderer/scene/hw_drawstructs.h"
// If we want to share the array to avoid constant allocations it needs to be thread local unless it'd be littered with expensive synchronization.
thread_local FDynLightData lightdata;
//==========================================================================
//
// Light related CVARs
//
//==========================================================================
// These shouldn't be called 'gl...' anymore...
CVAR (Bool, gl_light_sprites, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
CVAR (Bool, gl_light_particles, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
//==========================================================================
//
// Sets up the parameters to render one dynamic light onto one plane
//
//==========================================================================
bool GetLight(FDynLightData& dld, int group, Plane & p, FDynamicLight * light, bool checkside)
{
DVector3 pos = light->PosRelative(group);
float radius = (light->GetRadius());
auto dist = fabs(p.DistToPoint((float)pos.X, (float)pos.Z, (float)pos.Y));
if (radius <= 0.f) return false;
if (dist > radius) return false;
if (checkside && p.PointOnSide((float)pos.X, (float)pos.Z, (float)pos.Y))
{
return false;
}
AddLightToList(dld, group, light, false);
return true;
}
//==========================================================================
//
// Add one dynamic light to the light data list
//
//==========================================================================
void AddLightToList(FDynLightData &dld, int group, FDynamicLight * light, bool forceAttenuate)
{
int i = 0;
DVector3 pos = light->PosRelative(group);
float radius = light->GetRadius();
float cs;
if (light->IsAdditive())
{
cs = 0.2f;
i = 2;
}
else
{
cs = 1.0f;
}
float r = light->GetRed() / 255.0f * cs;
float g = light->GetGreen() / 255.0f * cs;
float b = light->GetBlue() / 255.0f * cs;
if (light->IsSubtractive())
{
DVector3 v(r, g, b);
float length = (float)v.Length();
r = length - r;
g = length - g;
b = length - b;
i = 1;
}
float shadowIndex;
if (screen->mShadowMap.Enabled()) // note: with shadowmaps switched off, we cannot rely on properly set indices anymore.
{
shadowIndex = light->mShadowmapIndex + 1.0f;
}
else shadowIndex = 1025.f;
// Store attenuate flag in the sign bit of the float.
if (light->IsAttenuated() || forceAttenuate) shadowIndex = -shadowIndex;
float lightType = 0.0f;
float spotInnerAngle = 0.0f;
float spotOuterAngle = 0.0f;
float spotDirX = 0.0f;
float spotDirY = 0.0f;
float spotDirZ = 0.0f;
if (light->IsSpot())
{
lightType = 1.0f;
spotInnerAngle = (float)light->pSpotInnerAngle->Cos();
spotOuterAngle = (float)light->pSpotOuterAngle->Cos();
DAngle negPitch = -*light->pPitch;
DAngle Angle = light->target->Angles.Yaw;
double xzLen = negPitch.Cos();
spotDirX = float(-Angle.Cos() * xzLen);
spotDirY = float(-negPitch.Sin());
spotDirZ = float(-Angle.Sin() * xzLen);
}
float *data = &dld.arrays[i][dld.arrays[i].Reserve(16)];
data[0] = float(pos.X);
data[1] = float(pos.Z);
data[2] = float(pos.Y);
data[3] = radius;
data[4] = r;
data[5] = g;
data[6] = b;
data[7] = shadowIndex;
data[8] = spotDirX;
data[9] = spotDirY;
data[10] = spotDirZ;
data[11] = lightType;
data[12] = spotInnerAngle;
data[13] = spotOuterAngle;
data[14] = 0.0f; // unused
data[15] = 0.0f; // unused
}