fix gpu model lighting

This commit is contained in:
Ricardo Luís Vaz Silva 2025-01-19 01:09:56 -03:00 committed by Magnus Norddahl
commit 7f8830a4ff
8 changed files with 60 additions and 16 deletions

View file

@ -32,6 +32,7 @@ enum FDynLightInfoFlags
LIGHTINFO_SHADOWMAPPED = 2,
LIGHTINFO_SPOT = 4,
LIGHTINFO_TRACE = 8,
LIGHTINFO_SUN = 16,
};
struct FDynLightInfo

View file

@ -147,7 +147,7 @@ void AddLightToList(FDynLightData &dld, int group, FDynamicLight * light, bool f
if(light->Trace() && doTrace)
{
info.flags |= LIGHTINFO_TRACE;
info.flags |= (LIGHTINFO_TRACE | LIGHTINFO_SHADOWMAPPED);
}
info.x = float(pos.X);
@ -176,7 +176,7 @@ void AddSunLightToList(FDynLightData& dld, float x, float y, float z, const FVec
info.r = suncolor.X;
info.g = suncolor.Y;
info.b = suncolor.Z;
info.flags = LIGHTINFO_ATTENUATED | (doTrace ? LIGHTINFO_TRACE : 0);
info.flags = LIGHTINFO_ATTENUATED | (doTrace ? LIGHTINFO_TRACE : 0) | LIGHTINFO_SUN;
info.strength = 1500.0f;
dld.arrays[LIGHTARRAY_NORMAL].Push(info);

View file

@ -109,7 +109,7 @@ CVARD(Bool, r_showhitbox, false, CVAR_GLOBALCONFIG | CVAR_CHEAT, "show actor hit
void HWSprite::DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent)
{
state.SetShadeVertex(gl_spritelight < 2);
state.SetShadeVertex(gl_spritelight == 1);
bool additivefog = false;
bool foglayer = false;
int rel = fullbright ? 0 : getExtraLight();
@ -301,12 +301,15 @@ void HWSprite::DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent)
if (!modelframe)
{
state.SetLightNoNormals(true);
state.SetNormal(0, 0, 0);
if(actor && gl_spritelight < 2)
if(gl_spritelight > 0)
{
state.SetUseSpriteCenter(true);
state.SetLightNoNormals(true);
if(actor && gl_spritelight < 2)
{
state.SetUseSpriteCenter(true);
}
}
CreateVertices(di, state);

View file

@ -141,6 +141,7 @@ struct Fogball
#define LIGHTINFO_SHADOWMAPPED 2
#define LIGHTINFO_SPOT 4
#define LIGHTINFO_TRACE 8
#define LIGHTINFO_SUN 16
struct DynLightInfo
{

View file

@ -55,7 +55,7 @@ float traceShadow(vec3 lightpos, float softShadowRadius)
vec3 direction = normalize(target - origin);
origin -= direction;
#else
vec3 origin = pixelpos.xyz + vWorldNormal.xyz;
vec3 origin = pixelpos.xyz + (vWorldNormal.xyz * 0.1);
vec3 direction = normalize(target - origin);
#endif
@ -85,4 +85,37 @@ float traceShadow(vec3 lightpos, float softShadowRadius)
return (sum / step_count);
}
#endif
}
float traceSun(vec3 SunDir)
{
#ifdef USE_SPRITE_CENTER
vec3 origin = uActorCenter.xyz;
#elif defined(LIGHT_NONORMALS)
vec3 origin = pixelpos.xyz;
origin -= SunDir;
#else
vec3 origin = pixelpos.xyz + (vWorldNormal.xyz * 0.1);
#endif
float dist = 65536.0;
#if SHADOWMAP_FILTER == 0
return TraceDynLightRay(origin, 0.01f, SunDir, dist);
#else
vec3 target = (SunDir * dist) + origin;
vec3 v = (abs(SunDir.x) > abs(SunDir.y)) ? vec3(0.0, 1.0, 0.0) : vec3(1.0, 0.0, 0.0);
vec3 xdir = normalize(cross(SunDir, v));
vec3 ydir = cross(SunDir, xdir);
float sum = 0.0;
const int step_count = SHADOWMAP_FILTER * 4;
for (int i = 0; i < step_count; i++)
{
vec2 gridoffset = getVogelDiskSample(i, step_count, gl_FragCoord.x + gl_FragCoord.y * 13.37) * 100.0;
vec3 pos = target + xdir * gridoffset.x + ydir * gridoffset.y;
sum += TraceDynLightRay(origin, 0.01f, normalize(pos - origin), dist);
}
return (sum / step_count);
#endif
}

View file

@ -30,8 +30,11 @@
if (attenuation > 0.0) // Skip shadow map test if possible
{
// light.radius >= 1000000.0 is sunlight(?), skip attenuation
if(light.radius < 1000000.0 && (light.flags & LIGHTINFO_SHADOWMAPPED) != 0)
if((light.flags & (LIGHTINFO_SUN | LIGHTINFO_TRACE)) == (LIGHTINFO_SUN | LIGHTINFO_TRACE))
{
attenuation *= traceSun(lightdir);
}
else if((light.flags & (LIGHTINFO_SHADOWMAPPED | LIGHTINFO_SUN)) == LIGHTINFO_SHADOWMAPPED)
{
attenuation *= shadowAttenuation(light.pos.xyz, light.shadowIndex, light.softShadowRadius, light.flags);
}

View file

@ -3,6 +3,8 @@
float distanceAttenuation(float dist, float radius, float strength, float linearity)
{
// light.radius >= 1000000.0 is sunlight, skip attenuation
if(light.radius >= 1000000.0) return 1.0;
float a = dist / radius;
float b = clamp(1.0 - a * a * a * a, 0.0, 1.0);
return mix((b * b) / (dist * dist + 1.0) * strength, clamp((radius - dist) / radius, 0.0, 1.0), linearity);

View file

@ -44,13 +44,14 @@
if (attenuation > 0.0) // Skip shadow map test if possible
{
#ifdef USE_RAYTRACE
// light.radius >= 1000000.0 is sunlight(?), skip attenuation
if((light.flags & LIGHTINFO_SHADOWMAPPED) != 0)
{
attenuation *= traceShadow(light.pos.xyz, light.softShadowRadius);
}
#endif
if((light.flags & LIGHTINFO_SUN) != 0)
{
attenuation *= traceSun(lightdir);
}
else if((light.flags & LIGHTINFO_SHADOWMAPPED) != 0)
{
attenuation *= traceShadow(light.pos.xyz, light.softShadowRadius);
}
return light.color.rgb * attenuation;
}