qzdoom/src/hwrenderer/dynlights/hw_dynlightdata.cpp
2018-05-25 19:23:47 +02:00

154 lines
4.3 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 "hw_dynlightdata.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);
CVAR(Int, gl_attenuate, -1, 0); // This is mainly a debug option.
//==========================================================================
//
// Sets up the parameters to render one dynamic light onto one plane
//
//==========================================================================
bool FDynLightData::GetLight(int group, Plane & p, ADynamicLight * 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(group, light, false);
return true;
}
//==========================================================================
//
// Add one dynamic light to the light data list
//
//==========================================================================
void FDynLightData::AddLightToList(int group, ADynamicLight * 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 = light->mShadowmapIndex + 1.0f;
bool attenuate;
// Store attenuate flag in the sign bit of the float.
if (gl_attenuate == -1) attenuate = !!(light->lightflags & LF_ATTENUATE) || forceAttenuate;
else attenuate = !!gl_attenuate;
if (attenuate) 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->SpotInnerAngle.Cos();
spotOuterAngle = (float)light->SpotOuterAngle.Cos();
DAngle negPitch = -light->Angles.Pitch;
double xzLen = negPitch.Cos();
spotDirX = float(-light->Angles.Yaw.Cos() * xzLen);
spotDirY = float(-negPitch.Sin());
spotDirZ = float(-light->Angles.Yaw.Sin() * xzLen);
}
float *data = &arrays[i][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
}