mirror of
https://github.com/jmarshall23/DoomRTX.git
synced 2026-08-17 19:23:51 +02:00
Added spotlight support.
This commit is contained in:
@@ -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
@@ -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
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -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
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user