From 45a9d2d6bc308ef108c0738e1047422e26a7cb2f Mon Sep 17 00:00:00 2001 From: Try Date: Thu, 7 Mar 2024 12:51:03 +0100 Subject: [PATCH] RT-lighting in progress #510 --- game/graphics/renderer.cpp | 5 ++++ game/graphics/shaders.cpp | 2 +- game/graphics/sky/sky.cpp | 34 ++++++++++++++++------ shader/common.glsl | 8 +----- shader/lighting/ambient_light.frag | 7 +++-- shader/lighting/direct_light.frag | 2 +- shader/lighting/irradiance.comp | 2 +- shader/lighting/light.frag | 2 +- shader/lighting/rt/probe_ambient.frag | 22 +++++++++------ shader/lighting/rt/probe_lighting.comp | 39 +++++++++++++++++++------- shader/lighting/sky_exposure.comp | 3 +- shader/lighting/tonemapping.frag | 10 ++++++- shader/lighting/tonemapping.glsl | 12 ++++++-- shader/sky/sky_view_lut.frag | 2 +- 14 files changed, 103 insertions(+), 47 deletions(-) diff --git a/game/graphics/renderer.cpp b/game/graphics/renderer.cpp index 2d5df0ca2..cf2efceb9 100644 --- a/game/graphics/renderer.cpp +++ b/game/graphics/renderer.cpp @@ -585,6 +585,7 @@ void Renderer::drawTonemapping(Encoder& cmd) { float brightness = 0; float contrast = 1; float gamma = 1.f/2.2f; + float mul = 1; }; Push p; @@ -592,6 +593,10 @@ void Renderer::drawTonemapping(Encoder& cmd) { p.contrast = std::max(1.5f - settings.zVidContrast, 0.01f); p.gamma = p.gamma/std::max(2.0f*settings.zVidGamma, 0.01f); + static float mul = 1.f; + if(mul>0) + p.mul = mul; + cmd.setUniforms(*tonemapping.pso, tonemapping.uboTone, &p, sizeof(p)); cmd.draw(Resources::fsqVbo()); } diff --git a/game/graphics/shaders.cpp b/game/graphics/shaders.cpp index ffa61a74e..fa07821b9 100644 --- a/game/graphics/shaders.cpp +++ b/game/graphics/shaders.cpp @@ -161,7 +161,7 @@ Shaders::Shaders() { state.setBlendSource (RenderState::BlendMode::One); state.setBlendDest (RenderState::BlendMode::SrcAlpha); // for debugging - state.setZTestMode (RenderState::ZTestMode::Always); + state.setZTestMode (RenderState::ZTestMode::NoEqual); state.setZWriteEnabled(false); sh = GothicShader::get("probe_ambient.vert.sprv"); vs = device.shader(sh.data,sh.len); diff --git a/game/graphics/sky/sky.cpp b/game/graphics/sky/sky.cpp index 84738492c..db04b2c12 100644 --- a/game/graphics/sky/sky.cpp +++ b/game/graphics/sky/sky.cpp @@ -17,12 +17,23 @@ using namespace Tempest; // https://www.slideshare.net/LukasLang/physically-based-lighting-in-unreal-engine-4 // https://www.slideshare.net/DICEStudio/moving-frostbite-to-physically-based-rendering -// static const float DirectSunLux = 64'000.f; // 85'000.f; -static const float DirectSunLux = 143'000.f; -static const float DirectMoonLux = 0.27f; + +/* https://physicallybased.info + * The changing color of the Sun over the course of the day is mainly a result of the scattering of sunlight + * and is not due to changes in black-body radiation. The solar illuminance constant is equal to 128 000 lux, + * but atmospheric extinction brings the number of lux down to around 100 000 lux. + * + * clear sky = 6000 lx + * sky overcast = 2000 lx + * + * opaque = (100'000/pi)*NdotL = 31'800*NdotL + * + */ +static const float DirectSunLux = 128'000.f; +static const float DirectMoonLux = 1.f; // static const float NightLight = 0.36f; -// static const float ShadowSunLux = 10'000.f; +// static const float ShadowSunLux = 10'000.f; // static const float StreetLight = 10.f; static float smoothstep(float edge0, float edge1, float x) { @@ -236,17 +247,22 @@ void Sky::updateLight(const int64_t now) { static float ambMul = 1; // static auto groundAlbedo = Vec3(0.34f, 0.42f, 0.26f); // Foliage(MacBeth) // static auto groundAlbedo = Vec3(0.39f, 0.40f, 0.33f); - static auto groundAlbedo = Vec3(0.47f); // Neutral5 (MacBeth) + static auto groundAlbedo = Vec3(0.3f); // aligned to sky-shading - const float dirY = sun.dir().y; + // const float dirY = sun.dir().y; // float dayTint = std::max(dirY+0.01f, 0.f); - const float aDirect = linearstep(-0.0f, 0.8f, dirY); + // const float aDirect = linearstep(-0.0f, 0.8f, dirY); const float sunOcclude = smoothstep(0.0f, 0.01f, sun.dir().y); Vec3 direct; - direct = Vec3(1.0f) * DirectSunLux; - ambient = groundAlbedo * DirectSunLux * aDirect * sunOcclude * 0.02f; + direct = DirectSunLux * Vec3(1.0f); + ambient = DirectSunLux * float(1.0/M_PI) * groundAlbedo * sunOcclude; + // ambient *= 0.78f; // atmosphere transmission is in shader + ambient *= 0.68f; // NdoL prediction + ambient *= 0.5; // maybe in shadow or maybe not + ambient *= 2.0; // 2*pi, pi accounted in shader + ambient += Vec3(0.01f); // should avoid zeros sun.setColor(direct*sunMul); ambient = ambient*ambMul; diff --git a/shader/common.glsl b/shader/common.glsl index 8967ad831..856f01b7b 100644 --- a/shader/common.glsl +++ b/shader/common.glsl @@ -13,16 +13,10 @@ const float IorWater = 1.0 / 1.52; // air / water const float IorAir = 1.52; // water /air const vec3 WaterAlbedo = vec3(0.8,0.9,1.0); -const vec3 GGroundAlbedo = vec3(0.1); +const vec3 GGroundAlbedo = vec3(0.3); const float Fd_Lambert = (1.0/M_PI); const float Fd_LambertInv = (M_PI); -/* Color value is multiplied to achive adequate albedo and correctness in GI. - * Need to scale it back, when material receives direct light. - */ -const float GColorScaleInv = 8;//(6); -const float GColorScale = (1.0/GColorScaleInv); - float linearDepth(float d, vec3 clipInfo) { // z_n * z_f, z_n - z_f, z_f return (clipInfo[0] / (clipInfo[1] * d + clipInfo[2])); diff --git a/shader/lighting/ambient_light.frag b/shader/lighting/ambient_light.frag index fc194687f..41421c230 100644 --- a/shader/lighting/ambient_light.frag +++ b/shader/lighting/ambient_light.frag @@ -61,17 +61,18 @@ void main() { const vec3 norm = normalFetch(gbufNormal, fragCoord); // const vec3 linear = vec3(1); - const vec3 linear = textureLinear(diff); // * Fd_Lambert is accounted in integration + const vec3 linear = textureLinear(diff); const float ao = textureSsao(); vec3 ambient = scene.ambient; vec3 sky = skyIrradiance(); - vec3 lcolor = mix(ambient, sky, max(0, 0.25 + norm.y*0.25)); + //vec3 lcolor = mix(ambient, sky, max(0, norm.y*0.8)); + vec3 lcolor = (ambient + sky)*0.5; // vec3 lcolor = ambient + sky*clamp(norm.y*0.5, 0,1); vec3 color = lcolor.rgb; - color *= linear; + color *= linear; // * Fd_Lambert is accounted in integration color *= (1-ao); // outColor = vec4(vec3(grayscale(color)), 0); diff --git a/shader/lighting/direct_light.frag b/shader/lighting/direct_light.frag index d72c67f01..f8db7cf12 100644 --- a/shader/lighting/direct_light.frag +++ b/shader/lighting/direct_light.frag @@ -161,7 +161,7 @@ void main(void) { */ #endif - const vec3 lcolor = scene.sunColor * Fd_Lambert * light * shadow * GColorScale; + const vec3 lcolor = scene.sunColor * Fd_Lambert * light * shadow; const vec3 linear = textureLinear(diff.rgb); vec3 color = linear*lcolor*scene.exposure; diff --git a/shader/lighting/irradiance.comp b/shader/lighting/irradiance.comp index ba5643251..18c271799 100644 --- a/shader/lighting/irradiance.comp +++ b/shader/lighting/irradiance.comp @@ -27,7 +27,7 @@ void storeSample(vec3 dir, vec3 val) { vec3 resolveMiss(const vec3 rayOrigin, const vec3 rayDirection) { // PERF: need to preload sky lut early in shader - return textureSkyLUT(skyLUT, vec3(0,RPlanet,0), rayDirection, scene.sunDir) * scene.GSunIntensity * GColorScale; + return textureSkyLUT(skyLUT, vec3(0,RPlanet,0), rayDirection, scene.sunDir) * scene.GSunIntensity; } void gather() { diff --git a/shader/lighting/light.frag b/shader/lighting/light.frag index ba8e23c7b..29594bb9c 100644 --- a/shader/lighting/light.frag +++ b/shader/lighting/light.frag @@ -87,7 +87,7 @@ void main(void) { const vec3 d = texelFetch(gbufDiffuse, ivec2(gl_FragCoord.xy), 0).xyz; const vec3 linear = textureLinear(d.rgb); - vec3 color = linear*color*light*Fd_Lambert*GColorScale*0.5; + vec3 color = linear*color*light*Fd_Lambert*0.5; //color *= scene.exposure; outColor = vec4(color,0.0); diff --git a/shader/lighting/rt/probe_ambient.frag b/shader/lighting/rt/probe_ambient.frag index 2e3fcb2a4..056b1f2af 100644 --- a/shader/lighting/rt/probe_ambient.frag +++ b/shader/lighting/rt/probe_ambient.frag @@ -4,6 +4,8 @@ #extension GL_GOOGLE_include_directive : enable #extension GL_EXT_control_flow_attributes : enable +//#extension GL_KHR_shader_subgroup_vote : enable + #include "lighting/rt/probe_common.glsl" #include "lighting/tonemapping.glsl" #include "lighting/purkinje_shift.glsl" @@ -134,6 +136,10 @@ void gather(vec3 basePos, vec3 pos, vec3 norm, int lod) { probeQuery pq; probeQueryInitialize(pq, pos, lod); + + // if(subgroupAllEqual(pq.pLow) && subgroupAllEqual(pq.pHigh)) + // return; + while(probeQueryProceed(pq)) { vec3 wpos = probeQueryWorldPos(pq); ivec3 gPos = probeQueryGridPos(pq); @@ -151,17 +157,15 @@ float textureSsao() { return 0; } #endif void main() { - const float minW = uintBitsToFloat(0x00000008); - const float z = texelFetch(depth,ivec2(gl_FragCoord.xy),0).x; - if(z>=1.0) - discard; // sky + const float minW = uintBitsToFloat(0x00000008); + const float z = texelFetch(depth,ivec2(gl_FragCoord.xy),0).x; - const vec3 diff = texelFetch(gbufDiffuse, ivec2(gl_FragCoord.xy), 0).rgb; - const vec3 norm = normalFetch(gbufNormal, ivec2(gl_FragCoord.xy)); + const vec3 diff = texelFetch(gbufDiffuse, ivec2(gl_FragCoord.xy), 0).rgb; + const vec3 norm = normalFetch(gbufNormal, ivec2(gl_FragCoord.xy)); - const int lod = probeGridComputeLod(); - const vec3 basePos = unprojectDepth(z); - const vec3 pos = basePos + norm*probeCageBias; + const int lod = probeGridComputeLod(); + const vec3 basePos = unprojectDepth(z); + const vec3 pos = basePos + norm*probeCageBias; gather(basePos, pos, norm, lod); diff --git a/shader/lighting/rt/probe_lighting.comp b/shader/lighting/rt/probe_lighting.comp index ca24b4422..679c74933 100644 --- a/shader/lighting/rt/probe_lighting.comp +++ b/shader/lighting/rt/probe_lighting.comp @@ -80,7 +80,7 @@ vec3 resolveHit(const vec3 rayOrigin, const vec3 rayDirection, float rayT, vec3 const float lambert = max(0, dt); //max(opaque ? 0 : 0.2, dt); const float shadow = max(0, shMap); - const vec3 lcolor = scene.sunColor * Fd_Lambert * lambert * shadow * GColorScale; + const vec3 lcolor = scene.sunColor * Fd_Lambert * lambert * shadow; return lcolor; //return scene.sunColor * scene.ambient; @@ -88,12 +88,25 @@ vec3 resolveHit(const vec3 rayOrigin, const vec3 rayDirection, float rayT, vec3 vec3 resolveMiss(const vec3 rayOrigin, const vec3 rayDirection) { // PERF: need to preload sky lut early in shader - return textureSkyLUT(skyLUT, vec3(0,RPlanet,0), rayDirection, scene.sunDir) * scene.GSunIntensity * GColorScale; + return textureSkyLUT(skyLUT, vec3(0,RPlanet,0), rayDirection, scene.sunDir) * scene.GSunIntensity; } vec3 resolveSecondBounce(vec3 pos, vec3 norm, uint selfProbeId) { - return scene.ambient;// * 2.0; - +#if 0 + return scene.ambient; +#elif 1 + vec3 ambient = scene.ambient; + vec3 sky = probeReadAmbient(probesLightingPrev, 0, norm, vec3(0,1,0)); + return (ambient + sky)*0.5; +#elif 0 + vec3 ambient = scene.ambient; + // vec3 sky = skyIrradiance(); + // vec3 sky = resolveMiss(pos, -norm); + vec3 sky = probeReadAmbient(probesLightingPrev, 0, norm, vec3(0,1,0)); + return mix(ambient, sky, max(0, norm.y*0.8)); +#elif 0 + return resolveMiss(pos, -norm); +#else // doesn't look coherent yet - need to keep offscreen data for long term const ivec3 gridPos = ivec3(round(pos/(probeGridStep*1))); const uint h = probeGridPosHash(gridPos) % hashTable.length(); @@ -110,19 +123,19 @@ vec3 resolveSecondBounce(vec3 pos, vec3 norm, uint selfProbeId) { continue; } + //return vec3(1000, 0,0); return probeReadAmbient(probesLightingPrev, probeId, norm, p.normal); } // probeId = selfProbeId; // return vec3(0.01,0,0)*scene.GSunIntensity; - return scene.ambient; - // return resolveMiss(pos, -norm); + // return scene.ambient; + return resolveMiss(pos, -norm); // return vec3(0); +#endif } vec4 processSample(const vec3 rayOrigin, const vec3 rayDirection, uint probeId, uint sampleId) { - //return vec4(max(vec3(0),rayDirection*scene.GSunIntensity), 1);//*0.5 + vec3(0.5); - const ivec2 uv = gbufferCoord(probeId, sampleId); const vec4 diff = texelFetch(gbufferDiff, uv, 0); const vec4 nr = texelFetch(gbufferNorm, uv, 0); @@ -137,11 +150,17 @@ vec4 processSample(const vec3 rayOrigin, const vec3 rayDirection, uint probeId, // hit *= 0.001; return vec4(hit, badbit ? 0 : 1); } +#if 0 + { + vec3 hit = resolveMiss(rayOrigin, rayDirection); + return vec4(hit, badbit ? 0 : 1); + } +#endif const bool opaque = (bits & 0x1)!=0; const bool semiSky = (bits & 0x8)!=0; - const vec3 albedo = textureLinear(diff.rgb); + const vec3 albedo = textureAlbedo(diff.rgb); const vec3 norm = normalize(nr.xyz*2.0-vec3(1)); const float rayT = rt * probeRayDistance; @@ -153,7 +172,7 @@ vec4 processSample(const vec3 rayOrigin, const vec3 rayDirection, uint probeId, vec3 hit = vec3(0); hit += albedo * resolveHit(rayOrigin, rayDirection, rayT, norm, opaque, shadow); - hit += albedo * resolveSecondBounce(pos, -rayDirection, probeId); + hit += albedo * resolveSecondBounce(pos, norm, probeId); // hit += albedo * resolveHit(rayOrigin, rayDirection, rayT, norm, opaque, shadow); // hit += albedo * resolveSecondBounce(pos, -rayDirection, probeId) / max(1.0 - albedo, 0.1); diff --git a/shader/lighting/sky_exposure.comp b/shader/lighting/sky_exposure.comp index 6027a6edd..5d95c6179 100644 --- a/shader/lighting/sky_exposure.comp +++ b/shader/lighting/sky_exposure.comp @@ -114,12 +114,13 @@ void main() { vec3 light = sunColor*Fd_Lambert*1.25 + ambient + skyIrradiance(); float lum = (vmax+vmin) * 0.5 * scene.GSunIntensity; //lum = dot(light, vec3(1.0/3.0)); - lum = dot(light, vec3(0.2125, 0.7154, 0.0721))*0.6 + lum*0.4; + lum = dot(light, vec3(0.2125, 0.7154, 0.0721))*0.9 + lum*0.1; // float lum = tr.b; scene.sunColor = sunColor * clouds * push.sunOcclusion; scene.ambient = ambient * clouds; scene.exposure = 1.0 / max(lum+push.baseL, 0.0000005); + //scene.exposure = 1.0 / max(6400, 0.0000005); scene.luminanceMed = lum; } } diff --git a/shader/lighting/tonemapping.frag b/shader/lighting/tonemapping.frag index 64e5afa41..2a0d17efa 100644 --- a/shader/lighting/tonemapping.frag +++ b/shader/lighting/tonemapping.frag @@ -11,6 +11,7 @@ layout(push_constant, std140) uniform PushConstant { float brightness; float contrast; float gamma; + float mulExposure; } push; layout(binding = 0, std140) uniform UboScene { @@ -118,6 +119,11 @@ void main() { // return; } + { + // outColor = vec4(vec3(luminance(color/exposure)/100000.0), 1); + // return; + } + { // outColor = vec4(colorTemperatureToRGB(luminance(color) / push.exposure), 1); // return; @@ -130,12 +136,14 @@ void main() { // color += vec3(0,0, shift.b); } + color *= push.mulExposure; + // Brightness & Contrast color = max(vec3(0), color + vec3(brightness)); color = color * vec3(contrast); // Tonemapping - color = acesTonemap(color)*1.28; + color = acesTonemap(color); // Gamma //color = srgbEncode(color); diff --git a/shader/lighting/tonemapping.glsl b/shader/lighting/tonemapping.glsl index 95c1c52b0..51d0a0844 100644 --- a/shader/lighting/tonemapping.glsl +++ b/shader/lighting/tonemapping.glsl @@ -42,14 +42,22 @@ vec3 textureLinear(vec3 rgb) { // emissive objects, spells return acesTonemapInv(linear); #else + // NOTE: in theory, need to be same as textureAlbedo, but game does't look like gothic then :( + return acesTonemapInv(linear*0.78+0.001)*2.0; +#endif + } + +vec3 textureAlbedo(vec3 rgb) { // return vec3(0.58, 0.49, 0.46); // brick + // return vec3(0.26, 0.11, 0.06); // brick2 // return vec3(0.52, 0.41, 0.36); // wood // return vec3(0.48, 0.53, 0.30); // grass + // return vec3(0.44, 0.39, 0.23); // sand // return vec3(0.9); // return acesTonemapInv(linear*0.8); // return acesTonemapInv(linear*0.78+0.001); - return acesTonemapInv(linear*0.78+0.001)*GColorScaleInv; // adjusted to have 'realistic' albedo values -#endif + const vec3 linear = srgbDecode(rgb); + return acesTonemapInv(linear*0.78+0.001)*5.0; // adjusted to have 'realistic' albedo values } #endif diff --git a/shader/sky/sky_view_lut.frag b/shader/sky/sky_view_lut.frag index 80e732c86..4633a3108 100644 --- a/shader/sky/sky_view_lut.frag +++ b/shader/sky/sky_view_lut.frag @@ -63,7 +63,7 @@ void main() { const vec3 viewPos = vec3(0.0, RPlanet + push.plPosY, 0.0); const float DirectSunLux = scene.GSunIntensity; - const float DirectMoonLux = 0.27f; + const float DirectMoonLux = 0.32f; // const float NightLight = 0.36f; const float moonInt = DirectMoonLux/DirectSunLux;