diff --git a/src/common/rendering/hwrenderer/data/hw_dynlightdata.h b/src/common/rendering/hwrenderer/data/hw_dynlightdata.h index a0abc850f..030df5dfc 100644 --- a/src/common/rendering/hwrenderer/data/hw_dynlightdata.h +++ b/src/common/rendering/hwrenderer/data/hw_dynlightdata.h @@ -32,6 +32,7 @@ enum FDynLightInfoFlags LIGHTINFO_SHADOWMAPPED = 2, LIGHTINFO_SPOT = 4, LIGHTINFO_TRACE = 8, + LIGHTINFO_SUN = 16, }; struct FDynLightInfo diff --git a/src/rendering/hwrenderer/hw_dynlightdata.cpp b/src/rendering/hwrenderer/hw_dynlightdata.cpp index 826328160..0f1d5db9f 100644 --- a/src/rendering/hwrenderer/hw_dynlightdata.cpp +++ b/src/rendering/hwrenderer/hw_dynlightdata.cpp @@ -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); diff --git a/src/rendering/hwrenderer/scene/hw_sprites.cpp b/src/rendering/hwrenderer/scene/hw_sprites.cpp index b7f6878cd..493610f8a 100644 --- a/src/rendering/hwrenderer/scene/hw_sprites.cpp +++ b/src/rendering/hwrenderer/scene/hw_sprites.cpp @@ -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); diff --git a/wadsrc/static/shaders/binding_struct_definitions.glsl b/wadsrc/static/shaders/binding_struct_definitions.glsl index d71fda5c9..92d9342df 100644 --- a/wadsrc/static/shaders/binding_struct_definitions.glsl +++ b/wadsrc/static/shaders/binding_struct_definitions.glsl @@ -141,6 +141,7 @@ struct Fogball #define LIGHTINFO_SHADOWMAPPED 2 #define LIGHTINFO_SPOT 4 #define LIGHTINFO_TRACE 8 +#define LIGHTINFO_SUN 16 struct DynLightInfo { diff --git a/wadsrc/static/shaders/scene/light_trace.glsl b/wadsrc/static/shaders/scene/light_trace.glsl index bc9e34768..f483b8506 100644 --- a/wadsrc/static/shaders/scene/light_trace.glsl +++ b/wadsrc/static/shaders/scene/light_trace.glsl @@ -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 } \ No newline at end of file diff --git a/wadsrc/static/shaders/scene/lightmodel_normal.glsl b/wadsrc/static/shaders/scene/lightmodel_normal.glsl index 6e501e0f3..1dc3db247 100644 --- a/wadsrc/static/shaders/scene/lightmodel_normal.glsl +++ b/wadsrc/static/shaders/scene/lightmodel_normal.glsl @@ -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); } diff --git a/wadsrc/static/shaders/scene/lightmodel_shared.glsl b/wadsrc/static/shaders/scene/lightmodel_shared.glsl index 4b570d2ad..993ef0c9f 100644 --- a/wadsrc/static/shaders/scene/lightmodel_shared.glsl +++ b/wadsrc/static/shaders/scene/lightmodel_shared.glsl @@ -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); diff --git a/wadsrc/static/shaders/scene/vert_main.glsl b/wadsrc/static/shaders/scene/vert_main.glsl index 395724f6d..4774c8db6 100644 --- a/wadsrc/static/shaders/scene/vert_main.glsl +++ b/wadsrc/static/shaders/scene/vert_main.glsl @@ -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; }