vkdoom_m/src/rendering/hwrenderer/hw_dynlightdata.cpp
Magnus Norddahl 6894eb013f Begin removing binding points from the hwrenderer layer.
Well known buffers should be created and managed by the backend, otherwise the backend just becomes an OpenGL emulator.
2023-04-16 19:30:27 +02:00

193 lines
5.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
}
void AddSunLightToList(FDynLightData& dld, float x, float y, float z, const FVector3& sundir, const FVector3& suncolor)
{
// Cheap way of faking a directional light
float dist = 100000.0f;
float radius = 100000000.0f;
x += sundir.X * dist;
y += sundir.Y * dist;
z += sundir.Z * dist;
int i = 0;
float lightType = 0.0f;
float spotInnerAngle = 0.0f;
float spotOuterAngle = 0.0f;
float spotDirX = 0.0f;
float spotDirY = 0.0f;
float spotDirZ = 0.0f;
float shadowIndex = -1025.f; // Note: 1025 disables shadowmap and the attenuate flag is in the sign bit of the float
float* data = &dld.arrays[i][dld.arrays[i].Reserve(16)];
data[0] = float(x);
data[1] = float(z);
data[2] = float(y);
data[3] = radius;
data[4] = suncolor.X;
data[5] = suncolor.Y;
data[6] = suncolor.Z;
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
}