Added spotlight support.

This commit is contained in:
Justin Marshall
2026-04-23 17:05:49 -07:00
parent ef5b5f107d
commit 7877bcb26c
6 changed files with 467 additions and 97 deletions
+1 -1
View File
@@ -2465,7 +2465,7 @@ void idCommonLocal::Frame(void) {
eventLoop->RunEventLoop(); eventLoop->RunEventLoop();
if (1) if (Sys_IsWindowVisible())
{ {
//-------------------------------------------- //--------------------------------------------
// Determine how many game tics we are going to run, // Determine how many game tics we are going to run,
+220 -15
View File
@@ -1924,9 +1924,11 @@ struct Light
float pad1; float pad1;
// For point lights, this is the axis-aligned XYZ attenuation radius. // For point lights, this is the axis-aligned XYZ attenuation radius.
// The scalar radius above is still kept as a max/fallback range and for rect lights. // For spot lights, pointRadius.x stores the near clip plane.
// The scalar radius above is still kept as a max/fallback range for point lights,
// as the influence range for rect lights, and as the far clip distance for spot lights.
float3 pointRadius; float3 pointRadius;
float pointRadiusPad; float pointRadiusPad; // non-zero disables specular for this light
}; };
struct ShadowPayload struct ShadowPayload
@@ -1958,6 +1960,7 @@ RWTexture2D<float4> gOutputTex : register(u0);
static const uint GL_RAYTRACING_LIGHT_TYPE_POINT = 0; static const uint GL_RAYTRACING_LIGHT_TYPE_POINT = 0;
static const uint GL_RAYTRACING_LIGHT_TYPE_RECT = 1; static const uint GL_RAYTRACING_LIGHT_TYPE_RECT = 1;
static const uint GL_RAYTRACING_LIGHT_TYPE_SPOT = 2;
static const uint GEOMETRY_FLAG_SKELETAL = 1; static const uint GEOMETRY_FLAG_SKELETAL = 1;
static const uint GEOMETRY_FLAG_UNLIT = 2; static const uint GEOMETRY_FLAG_UNLIT = 2;
@@ -2097,7 +2100,55 @@ float ComputePointLightAttenuation(float3 worldPos, Light Lgt)
// and radius.z controls Z reach in world space. // and radius.z controls Z reach in world space.
float ellipsoidDistance = length(normalizedOffset); float ellipsoidDistance = length(normalizedOffset);
float atten = saturate(1.0 - ellipsoidDistance); float atten = saturate(1.0 - ellipsoidDistance);
return atten * atten; return atten;
}
float ComputeSpotLightAttenuation(float3 worldPos, Light Lgt)
{
float3 lightToSurface = worldPos - Lgt.position;
float nearClip = max(Lgt.pointRadius.x, 0.0);
float farClip = max(Lgt.radius, nearClip + 1e-4);
float depth = dot(lightToSurface, Lgt.normal);
if (depth <= nearClip || depth >= farClip)
return 0.0;
float invDepth = 1.0 / max(depth, 1e-4);
float projU = dot(lightToSurface, Lgt.axisU) * invDepth;
float projV = dot(lightToSurface, Lgt.axisV) * invDepth;
float halfU = max(abs(Lgt.halfWidth), 1e-4);
float halfV = max(abs(Lgt.halfHeight), 1e-4);
float edgeU = abs(projU) / halfU;
float edgeV = abs(projV) / halfV;
float edge = max(edgeU, edgeV);
if (edge >= 1.0)
return 0.0;
float coneAtten = saturate(1.0 - edge);
coneAtten = coneAtten;
float rangeAtten = saturate((farClip - depth) / max(farClip - nearClip, 1e-4));
rangeAtten = rangeAtten;
return coneAtten * rangeAtten;
}
float TraceSpotShadow(float3 worldPos, float3 N, float3 toLight, float dist)
{
float3 L = toLight / max(dist, 1e-6);
float NdotLRaw = saturate(dot(N, L));
float normalBias = lerp(gShadowBias * 3.0, gShadowBias * 0.75, NdotLRaw);
float3 shadowOrigin = worldPos + N * normalBias + L * (gShadowBias * 0.5);
float shadowTMax = max(dist - gShadowBias * 0.5, 0.001);
return TraceShadow(shadowOrigin, L, shadowTMax);
} }
float TraceSoftShadow(float3 worldPos, float3 N, Light Lgt, float3 toLight, float dist) float TraceSoftShadow(float3 worldPos, float3 N, Light Lgt, float3 toLight, float dist)
@@ -2438,7 +2489,7 @@ void RayGen()
float NdotLWrap = saturate((dot(N, L) + wrap) / (1.0 + wrap)); float NdotLWrap = saturate((dot(N, L) + wrap) / (1.0 + wrap));
float shadow = 1.0; float shadow = 1.0;
if (NdotLWrap > 0.0001 && atten > 0.0 && dist > 0.01) if (Lgt.samples != 0u && NdotLWrap > 0.0001 && atten > 0.0 && dist > 0.01)
{ {
shadow = TraceSoftShadow(worldPos, N, Lgt, toLight, dist); shadow = TraceSoftShadow(worldPos, N, Lgt, toLight, dist);
} }
@@ -2446,7 +2497,44 @@ void RayGen()
float3 diffuse = Lgt.color * (Lgt.intensity * atten * NdotLWrap * shadow); float3 diffuse = Lgt.color * (Lgt.intensity * atten * NdotLWrap * shadow);
lightingAccum += diffuse; lightingAccum += diffuse;
specularAccum += ComputeSpecular(N, V, L, Lgt.color, Lgt.intensity, atten, shadow, baseAlbedo); if (Lgt.pointRadiusPad <= 0.5)
{
specularAccum += ComputeSpecular(N, V, L, Lgt.color, Lgt.intensity, atten, shadow, baseAlbedo);
}
}
else if (Lgt.type == GL_RAYTRACING_LIGHT_TYPE_SPOT)
{
float3 toLight = Lgt.position - worldPos;
float distSq = dot(toLight, toLight);
float dist = sqrt(max(distSq, 1e-6));
float3 L = toLight / dist;
float atten = ComputeSpotLightAttenuation(worldPos, Lgt);
float wrap = 0.35;
float NdotLWrap = saturate((dot(N, L) + wrap) / (1.0 + wrap));
float shadow = 1.0;
if (Lgt.samples != 0u && NdotLWrap > 0.0001 && atten > 0.0 && dist > 0.01)
{
shadow = TraceSpotShadow(worldPos, N, toLight, dist);
}
float3 diffuse = Lgt.color * (Lgt.intensity * atten * NdotLWrap * shadow);
lightingAccum += diffuse;
if (Lgt.pointRadiusPad <= 0.5)
{
specularAccum += ComputeSpecular(
N,
V,
L,
Lgt.color,
Lgt.intensity,
atten,
shadow,
baseAlbedo);
}
} }
else if (Lgt.type == GL_RAYTRACING_LIGHT_TYPE_RECT) else if (Lgt.type == GL_RAYTRACING_LIGHT_TYPE_RECT)
{ {
@@ -2460,7 +2548,7 @@ void RayGen()
atten = atten * atten * atten * atten; atten = atten * atten * atten * atten;
float shadow = 1.0; float shadow = 1.0;
if (atten > 0.0 && centerDist > 0.01) if (Lgt.samples != 0u && atten > 0.0 && centerDist > 0.01)
{ {
shadow = RectLightShadow(worldPos, N, Lgt, pixel); shadow = RectLightShadow(worldPos, N, Lgt, pixel);
} }
@@ -2498,15 +2586,18 @@ void RayGen()
rectDiffuseAccum += Lgt.color * sampleWeight; rectDiffuseAccum += Lgt.color * sampleWeight;
rectSpecAccum += ComputeSpecular( if (Lgt.pointRadiusPad <= 0.5)
N, {
V, rectSpecAccum += ComputeSpecular(
L, N,
Lgt.color, V,
Lgt.intensity * faceTerm, L,
1.0, Lgt.color,
1.0, Lgt.intensity * faceTerm,
baseAlbedo); 1.0,
1.0,
baseAlbedo);
}
} }
rectDiffuseAccum /= (float)sampleCount; rectDiffuseAccum /= (float)sampleCount;
@@ -3329,6 +3420,120 @@ glRaytracingLight_t glRaytracingLightingMakePointLight(
return l; return l;
} }
glRaytracingLight_t glRaytracingLightingMakeSpotLight(
float px, float py, float pz,
float dx, float dy, float dz,
float ux, float uy, float uz,
float vx, float vy, float vz,
float nearPlane,
float farPlane,
float tanHalfWidth,
float tanHalfHeight,
float r, float g, float b,
float intensity,
uint32_t samples)
{
glRaytracingLight_t l = {};
glRaytracingNormalize3(dx, dy, dz);
// Make U perpendicular to D.
{
const float du = dx * ux + dy * uy + dz * uz;
ux -= dx * du;
uy -= dy * du;
uz -= dz * du;
const float uLenSq = ux * ux + uy * uy + uz * uz;
if (uLenSq <= 1e-20f)
{
const float absDz = (dz < 0.0f) ? -dz : dz;
if (absDz < 0.999f)
{
glRaytracingCross3(0.0f, 0.0f, 1.0f, dx, dy, dz, ux, uy, uz);
}
else
{
glRaytracingCross3(0.0f, 1.0f, 0.0f, dx, dy, dz, ux, uy, uz);
}
}
glRaytracingNormalize3(ux, uy, uz);
}
// Rebuild V from D x U so the basis is orthonormal, while preserving the
// sign of the caller-provided V whenever possible.
{
float builtVx, builtVy, builtVz;
glRaytracingCross3(dx, dy, dz, ux, uy, uz, builtVx, builtVy, builtVz);
glRaytracingNormalize3(builtVx, builtVy, builtVz);
const float sign = builtVx * vx + builtVy * vy + builtVz * vz;
if (sign < 0.0f)
{
builtVx = -builtVx;
builtVy = -builtVy;
builtVz = -builtVz;
}
vx = builtVx;
vy = builtVy;
vz = builtVz;
}
if (nearPlane < 0.0f)
nearPlane = 0.0f;
if (farPlane <= nearPlane)
farPlane = nearPlane + 1e-3f;
if (tanHalfWidth < 0.0f) tanHalfWidth = -tanHalfWidth;
if (tanHalfHeight < 0.0f) tanHalfHeight = -tanHalfHeight;
if (tanHalfWidth <= 1e-4f)
tanHalfWidth = 1e-4f;
if (tanHalfHeight <= 1e-4f)
tanHalfHeight = 1e-4f;
l.position.x = px;
l.position.y = py;
l.position.z = pz;
// For spot lights, radius stores the far clip distance while pointRadius.x
// stores the near clip distance.
l.radius = farPlane;
l.pointRadius.x = nearPlane;
l.pointRadius.y = 0.0f;
l.pointRadius.z = 0.0f;
l.pointRadiusPad = 0.0f;
l.color.x = r;
l.color.y = g;
l.color.z = b;
l.intensity = intensity;
l.normal.x = dx;
l.normal.y = dy;
l.normal.z = dz;
l.type = GL_RAYTRACING_LIGHT_TYPE_SPOT;
l.axisU.x = ux;
l.axisU.y = uy;
l.axisU.z = uz;
l.halfWidth = tanHalfWidth;
l.axisV.x = vx;
l.axisV.y = vy;
l.axisV.z = vz;
l.halfHeight = tanHalfHeight;
l.samples = samples ? samples : 1u;
l.twoSided = 0;
l.persistant = 0.0f;
l.pad1 = 0.0f;
return l;
}
glRaytracingLight_t glRaytracingLightingMakeRectLight( glRaytracingLight_t glRaytracingLightingMakeRectLight(
float px, float py, float pz, float px, float py, float pz,
float nx, float ny, float nz, float nx, float ny, float nz,
+37 -12
View File
@@ -1636,27 +1636,38 @@ typedef struct glRaytracingVec3_s
typedef struct glRaytracingLight_s typedef struct glRaytracingLight_s
{ {
glRaytracingVec3_t position; glRaytracingVec3_t position;
float radius; float radius; // point: max XYZ radius / fallback range
// rect : influence range
// spot : far clip distance
glRaytracingVec3_t color; glRaytracingVec3_t color;
float intensity; float intensity;
glRaytracingVec3_t normal; glRaytracingVec3_t normal; // rect: emitter normal
uint32_t type; // spot: forward direction
// point: ignored
uint32_t type; // POINT / RECT / SPOT
glRaytracingVec3_t axisU; glRaytracingVec3_t axisU; // rect: local X axis
float halfWidth; // spot: right basis
float halfWidth; // rect: half extent along axisU
// spot: projected half-width slope
glRaytracingVec3_t axisV; glRaytracingVec3_t axisV; // rect: local Y axis
float halfHeight; // spot: up basis
float halfHeight; // rect: half extent along axisV
// spot: projected half-height slope
uint32_t samples; uint32_t samples; // rect: sample count
uint32_t twoSided; // point/spot: 0 disables shadows, non-zero enables them
uint32_t twoSided; // rect: 0/1, ignored for point / spot
float persistant; float persistant;
float pad1; float pad1;
glRaytracingVec3_t pointRadius; glRaytracingVec3_t pointRadius; // point: XYZ attenuation radii
float pointRadiusPad; // spot: x = near clip, y/z unused
// rect : scalar range copy
float pointRadiusPad; // non-zero disables specular for this light
} glRaytracingLight_t; } glRaytracingLight_t;
typedef struct glRaytracingLightingPassDesc_s typedef struct glRaytracingLightingPassDesc_s
@@ -1746,7 +1757,20 @@ glRaytracingLight_t glRaytracingLightingMakePointLight(
float r, float g, float b, float r, float g, float b,
float intensity); float intensity);
glRaytracingLight_t glRaytracingLightingMakeRectLight( glRaytracingLight_t glRaytracingLightingMakeSpotLight(
float px, float py, float pz,
float dx, float dy, float dz,
float ux, float uy, float uz,
float vx, float vy, float vz,
float nearPlane,
float farPlane,
float tanHalfWidth,
float tanHalfHeight,
float r, float g, float b,
float intensity,
uint32_t samples);
glRaytracingLight_t glRaytracingLightingMakeRectLight(
float px, float py, float pz, float px, float py, float pz,
float nx, float ny, float nz, float nx, float ny, float nz,
float ux, float uy, float uz, float ux, float uy, float uz,
@@ -1801,6 +1825,7 @@ static void glRaytracingCross3(
static const int GL_RAYTRACING_LIGHT_TYPE_POINT = 0; static const int GL_RAYTRACING_LIGHT_TYPE_POINT = 0;
static const int GL_RAYTRACING_LIGHT_TYPE_RECT = 1; static const int GL_RAYTRACING_LIGHT_TYPE_RECT = 1;
static const int GL_RAYTRACING_LIGHT_TYPE_SPOT = 2;
void TessellatePolygon(const std::vector<GLVertex>& src, std::vector<GLVertex>& out); void TessellatePolygon(const std::vector<GLVertex>& src, std::vector<GLVertex>& out);
-48
View File
@@ -417,55 +417,7 @@ helper function that takes the current width/height and might make them smaller
================ ================
*/ */
void idImage::GetDownsize( int &scaled_width, int &scaled_height ) const { void idImage::GetDownsize( int &scaled_width, int &scaled_height ) const {
int size = 0;
// perform optional picmip operation to save texture memory
if ( depth == TD_SPECULAR && globalImages->image_downSizeSpecular.GetInteger() ) {
size = globalImages->image_downSizeSpecularLimit.GetInteger();
if ( size == 0 ) {
size = 64;
}
} else if ( depth == TD_BUMP && globalImages->image_downSizeBump.GetInteger() ) {
size = globalImages->image_downSizeBumpLimit.GetInteger();
if ( size == 0 ) {
size = 64;
}
} else if ( ( allowDownSize || globalImages->image_forceDownSize.GetBool() ) && globalImages->image_downSize.GetInteger() ) {
size = globalImages->image_downSizeLimit.GetInteger();
if ( size == 0 ) {
size = 256;
}
}
if ( size > 0 ) {
while ( scaled_width > size || scaled_height > size ) {
if ( scaled_width > 1 ) {
scaled_width >>= 1;
}
if ( scaled_height > 1 ) {
scaled_height >>= 1;
}
}
}
// clamp to minimum size
if ( scaled_width < 1 ) {
scaled_width = 1;
}
if ( scaled_height < 1 ) {
scaled_height = 1;
}
// clamp size to the hardware specific upper limit
// scale both axis down equally so we don't have to
// deal with a half mip resampling
// This causes a 512*256 texture to sample down to
// 256*128 on a voodoo3, even though it could be 256*256
while ( scaled_width > glConfig.maxTextureSize
|| scaled_height > glConfig.maxTextureSize ) {
scaled_width >>= 1;
scaled_height >>= 1;
}
} }
/* /*
+8
View File
@@ -428,6 +428,14 @@ static bool R_ParseImageProgram_r( idLexer &src, byte **pic, int *width, int *he
return false; return false;
} }
if (width2 <= 0 || height2 <= 0) {
if (pic) {
R_StaticFree(*pic);
*pic = NULL;
}
return false;
}
// process it // process it
if ( pic ) { if ( pic ) {
R_AddNormalMaps( *pic, *width, *height, pic2, width2, height2 ); R_AddNormalMaps( *pic, *width, *height, pic2, width2, height2 );
+199 -19
View File
@@ -2,52 +2,232 @@
#pragma hdrstop #pragma hdrstop
#include "tr_local.h" #include "tr_local.h"
#include <math.h>
static idVec3 RB_DXRMakeVec3(float x, float y, float z)
{
idVec3 v;
v.x = x;
v.y = y;
v.z = z;
return v;
}
static idVec3 RB_DXRSubVec3(const idVec3& a, const idVec3& b)
{
return RB_DXRMakeVec3(a.x - b.x, a.y - b.y, a.z - b.z);
}
static idVec3 RB_DXRScaleVec3(const idVec3& v, float s)
{
return RB_DXRMakeVec3(v.x * s, v.y * s, v.z * s);
}
static float RB_DXRDotVec3(const idVec3& a, const idVec3& b)
{
return a.x * b.x + a.y * b.y + a.z * b.z;
}
static idVec3 RB_DXRCrossVec3(const idVec3& a, const idVec3& b)
{
return RB_DXRMakeVec3(
a.y * b.z - a.z * b.y,
a.z * b.x - a.x * b.z,
a.x * b.y - a.y * b.x);
}
static float RB_DXRLengthVec3(const idVec3& v)
{
return sqrtf(v.x * v.x + v.y * v.y + v.z * v.z);
}
static idVec3 RB_DXRNormalizeVec3Safe(const idVec3& v, const idVec3& fallback)
{
const float len = RB_DXRLengthVec3(v);
if (len > 1e-20f)
{
const float invLen = 1.0f / len;
return RB_DXRMakeVec3(v.x * invLen, v.y * invLen, v.z * invLen);
}
return fallback;
}
static idVec3 RB_DXRTransformLightVector(const idMat3& axis, const idVec3& v)
{
return RB_DXRMakeVec3(
axis[0].x * v.x + axis[1].x * v.y + axis[2].x * v.z,
axis[0].y * v.x + axis[1].y * v.y + axis[2].y * v.z,
axis[0].z * v.x + axis[1].z * v.y + axis[2].z * v.z);
}
static glRaytracingLight_t RB_DXRMakeSpotLightFromRenderLight(
const renderLight_t& srcLight,
const idVec3& worldOrigin,
float r, float g, float b,
float intensity)
{
const idVec3 targetW = RB_DXRTransformLightVector(srcLight.axis, srcLight.target);
const idVec3 rightW = RB_DXRTransformLightVector(srcLight.axis, srcLight.right);
const idVec3 upW = RB_DXRTransformLightVector(srcLight.axis, srcLight.up);
const idVec3 startW = RB_DXRTransformLightVector(srcLight.axis, srcLight.start);
const idVec3 endW = RB_DXRTransformLightVector(srcLight.axis, srcLight.end);
idVec3 fallbackDir = RB_DXRCrossVec3(rightW, upW);
fallbackDir = RB_DXRNormalizeVec3Safe(fallbackDir, RB_DXRMakeVec3(0.0f, 0.0f, -1.0f));
const idVec3 dir = RB_DXRNormalizeVec3Safe(targetW, fallbackDir);
float centerDepth = RB_DXRDotVec3(targetW, dir);
if (centerDepth <= 1e-4f)
{
centerDepth = RB_DXRLengthVec3(targetW);
}
if (centerDepth <= 1e-4f)
{
centerDepth = RB_DXRDotVec3(endW, dir);
}
if (centerDepth <= 1e-4f)
{
centerDepth = 64.0f;
}
const idVec3 rightPerp = RB_DXRSubVec3(
rightW,
RB_DXRScaleVec3(dir, RB_DXRDotVec3(rightW, dir)));
const idVec3 upPerp = RB_DXRSubVec3(
upW,
RB_DXRScaleVec3(dir, RB_DXRDotVec3(upW, dir)));
idVec3 axisU = RB_DXRCrossVec3(RB_DXRMakeVec3(0.0f, 0.0f, 1.0f), dir);
axisU = RB_DXRNormalizeVec3Safe(axisU, RB_DXRMakeVec3(1.0f, 0.0f, 0.0f));
axisU = RB_DXRNormalizeVec3Safe(rightPerp, axisU);
idVec3 axisV = RB_DXRCrossVec3(dir, axisU);
axisV = RB_DXRNormalizeVec3Safe(axisV, RB_DXRMakeVec3(0.0f, 1.0f, 0.0f));
if (RB_DXRDotVec3(axisV, upPerp) < 0.0f)
{
axisV = RB_DXRScaleVec3(axisV, -1.0f);
}
float tanHalfWidth = RB_DXRLengthVec3(rightPerp) / centerDepth;
float tanHalfHeight = RB_DXRLengthVec3(upPerp) / centerDepth;
float nearPlane = RB_DXRDotVec3(startW, dir);
if (nearPlane < 0.0f)
{
nearPlane = 0.0f;
}
float farPlane = RB_DXRDotVec3(endW, dir);
if (farPlane < centerDepth)
{
farPlane = centerDepth;
}
if (farPlane <= nearPlane)
{
farPlane = nearPlane + 64.0f;
}
glRaytracingLight_t light = glRaytracingLightingMakeSpotLight(
worldOrigin.x, worldOrigin.y, worldOrigin.z,
dir.x, dir.y, dir.z,
axisU.x, axisU.y, axisU.z,
axisV.x, axisV.y, axisV.z,
nearPlane,
farPlane,
tanHalfWidth,
tanHalfHeight,
r, g, b,
intensity,
1u);
light.samples = srcLight.noShadows ? 0u : 1u;
light.pointRadiusPad = srcLight.noSpecular ? 1.0f : 0.0f;
return light;
}
/* /*
==================== ====================
RB_DXDrawInteractions RB_DXDrawInteractions
==================== ====================
*/ */
void RB_DXDrawInteractions(void) { void RB_DXDrawInteractions(void)
{
viewLight_t* vLight; viewLight_t* vLight;
bool hasLight = false; bool hasLight = false;
for (vLight = backEnd.viewDef->viewLights; vLight; vLight = vLight->next) { for (vLight = backEnd.viewDef->viewLights; vLight; vLight = vLight->next)
{
backEnd.vLight = vLight; backEnd.vLight = vLight;
// do fogging later // do fogging later
if (vLight->lightShader->IsFogLight()) { if (vLight->lightShader->IsFogLight())
{
continue; continue;
} }
if (vLight->lightShader->IsBlendLight()) { if (vLight->lightShader->IsBlendLight())
{
continue; continue;
} }
if (!vLight->localInteractions && !vLight->globalInteractions if (!vLight->localInteractions && !vLight->globalInteractions
&& !vLight->translucentInteractions) { && !vLight->translucentInteractions)
{
continue; continue;
} }
hasLight = true; const renderLight_t& srcLight = vLight->lightDef->parms;
const float r = srcLight.shaderParms[SHADERPARM_RED];
const float g = srcLight.shaderParms[SHADERPARM_GREEN];
const float b = srcLight.shaderParms[SHADERPARM_BLUE];
const float intensity = 1.0f;
glRaytracingLight_t light = {}; glRaytracingLight_t light = {};
light.color.x = vLight->lightDef->parms.shaderParms[SHADERPARM_RED]; bool supported = true;
light.color.y = vLight->lightDef->parms.shaderParms[SHADERPARM_GREEN];
light.color.z = vLight->lightDef->parms.shaderParms[SHADERPARM_BLUE]; if (srcLight.pointLight)
light.type = GL_RAYTRACING_LIGHT_TYPE_POINT; {
light.pointRadius.x = vLight->lightDef->parms.lightRadius[0] * 2; light = glRaytracingLightingMakePointLight(
light.pointRadius.y = vLight->lightDef->parms.lightRadius[1] * 2; vLight->globalLightOrigin.x,
light.pointRadius.z = vLight->lightDef->parms.lightRadius[2] * 2; vLight->globalLightOrigin.y,
light.intensity = 1; vLight->globalLightOrigin.z,
light.position.x = vLight->globalLightOrigin.x; srcLight.lightRadius[0] * 1.4f,
light.position.y = vLight->globalLightOrigin.y; srcLight.lightRadius[1] * 1.4f,
light.position.z = vLight->globalLightOrigin.z; srcLight.lightRadius[2] * 1.4f,
glRaytracingLightingAddLight(&light); r, g, b,
intensity);
light.samples = srcLight.noShadows ? 0u : 1u;
light.pointRadiusPad = srcLight.noSpecular ? 1.0f : 0.0f;
}
else if (!srcLight.parallel)
{
light = RB_DXRMakeSpotLightFromRenderLight(
srcLight,
vLight->globalLightOrigin,
r, g, b,
intensity);
}
else
{
// Parallel projected lights are not spot lights.
// Handle them in a separate directional/orthographic path.
supported = false;
common->Warning("Parallel lights are not needed with raytracing! Just place a skybox.");
}
if (supported && glRaytracingLightingAddLight(&light))
{
hasLight = true;
}
} }
if (!hasLight) if (!hasLight)
{
return; return;
}
glFinish(); glFinish();
glLightScene(backEnd.viewDef->renderWorld->dxrWorldId); glLightScene(backEnd.viewDef->renderWorld->dxrWorldId);