From b85681573bf85bb2b0a691a50df0b016cd1cc3d8 Mon Sep 17 00:00:00 2001 From: IntegratedQuantum <jahe788@gmail.com> Date: Fri, 6 Dec 2024 21:47:12 +0100 Subject: [PATCH] Fog with ARB_fragment_shader_interlock: quick and dirty prototype a prototype of #817 --- .../bloom/color_extractor_downsample.fs | 4 +-- .../shaders/chunks/transparent_fragment.fs | 22 ++++++++---- assets/cubyz/shaders/deferred_render_pass.fs | 4 +-- assets/cubyz/shaders/depth_copy.fs | 16 +++++++++ assets/cubyz/shaders/depth_copy.vs | 10 ++++++ src/graphics.zig | 4 +++ src/renderer.zig | 34 +++++++++++++++++-- 7 files changed, 81 insertions(+), 13 deletions(-) create mode 100644 assets/cubyz/shaders/depth_copy.fs create mode 100644 assets/cubyz/shaders/depth_copy.vs diff --git a/assets/cubyz/shaders/bloom/color_extractor_downsample.fs b/assets/cubyz/shaders/bloom/color_extractor_downsample.fs index 122a7e80b..d7e82c7f8 100644 --- a/assets/cubyz/shaders/bloom/color_extractor_downsample.fs +++ b/assets/cubyz/shaders/bloom/color_extractor_downsample.fs @@ -44,7 +44,7 @@ float calculateFogDistance(float depthBufferValue, float fogDensity) { } vec3 applyFrontfaceFog(float fogDistance, vec3 fogColor, vec3 inColor) { - float fogFactor = exp(fogDistance); + float fogFactor = exp(-fogDistance); inColor *= fogFactor; inColor += fogColor; inColor -= fogColor*fogFactor; @@ -54,7 +54,7 @@ vec3 applyFrontfaceFog(float fogDistance, vec3 fogColor, vec3 inColor) { vec3 fetch(ivec2 pos) { vec4 rgba = texelFetch(color, pos, 0); float densityAdjustment = sqrt(dot(tanXY*(normalizedTexCoords*2 - 1), tanXY*(normalizedTexCoords*2 - 1)) + 1); - float fogDistance = calculateFogDistance(texelFetch(depthTexture, pos, 0).r, fog.density*densityAdjustment); + float fogDistance = texelFetch(depthTexture, pos, 0).r*fog.density*densityAdjustment; vec3 fogColor = fog.color; rgba.rgb = applyFrontfaceFog(fogDistance, fog.color, rgba.rgb); return rgba.rgb/rgba.a; diff --git a/assets/cubyz/shaders/chunks/transparent_fragment.fs b/assets/cubyz/shaders/chunks/transparent_fragment.fs index d398b74b7..ccc8acb70 100644 --- a/assets/cubyz/shaders/chunks/transparent_fragment.fs +++ b/assets/cubyz/shaders/chunks/transparent_fragment.fs @@ -1,5 +1,9 @@ #version 430 +#extension GL_ARB_fragment_shader_interlock : require +layout(sample_interlock_ordered) in; +layout(early_fragment_tests) in; + in vec3 mvVertexPos; in vec3 direction; in vec3 light; @@ -16,7 +20,7 @@ uniform samplerCube reflectionMap; uniform float reflectionMapSize; uniform float contrast; -layout(binding = 5) uniform sampler2D depthTexture; +layout(binding = 5, r16f) coherent uniform image2D depthTexture; layout (location = 0, index = 0) out vec4 fragColor; layout (location = 0, index = 1) out vec4 blendColor; @@ -91,9 +95,9 @@ void applyFrontfaceFog(float fogDistance, vec3 fogColor) { } void applyBackfaceFog(float fogDistance, vec3 fogColor) { - float fogFactor = exp(-fogDistance); - fragColor.rgb = fragColor.rgb*fogFactor + fogColor*(1 - fogFactor); - fragColor.a *= fogFactor; + //float fogFactor = exp(-fogDistance); + //fragColor.rgb = fragColor.rgb*fogFactor + fogColor*(1 - fogFactor); + //fragColor.a *= fogFactor; } vec4 fixedCubeMapLookup(vec3 v) { // Taken from http://the-witness.net/news/2012/02/seamless-cube-map-filtering/ @@ -106,13 +110,17 @@ vec4 fixedCubeMapLookup(vec3 v) { // Taken from http://the-witness.net/news/2012 } void main() { + beginInvocationInterlockARB(); + float prevDepth = imageLoad(depthTexture, ivec2(gl_FragCoord.xy)).r; + imageStore(depthTexture, ivec2(gl_FragCoord.xy), vec4(abs(mvVertexPos.y), 0, 0, 0)); + endInvocationInterlockARB(); float animatedTextureIndex = animatedTexture[textureIndex]; vec3 textureCoords = vec3(uv, animatedTextureIndex); float normalVariation = lightVariation(normal); float densityAdjustment = sqrt(dot(mvVertexPos, mvVertexPos))/abs(mvVertexPos.y); - float dist = zFromDepth(texelFetch(depthTexture, ivec2(gl_FragCoord.xy), 0).r); - float fogDistance = calculateFogDistance(dist, fogData[int(animatedTextureIndex)].fogDensity*densityAdjustment); - float airFogDistance = calculateFogDistance(dist, fog.density*densityAdjustment); + float dist = abs(mvVertexPos.y) - prevDepth;//zFromDepth(texelFetch(depthTexture1, ivec2(gl_FragCoord.xy), 0).r); + float fogDistance = dist*fogData[int(animatedTextureIndex)].fogDensity*densityAdjustment; + float airFogDistance = dist*fog.density*densityAdjustment; vec3 fogColor = unpackColor(fogData[int(animatedTextureIndex)].fogColor); vec3 pixelLight = max(light*normalVariation, texture(emissionSampler, textureCoords).r*4); vec4 textureColor = texture(texture_sampler, textureCoords)*vec4(pixelLight, 1); diff --git a/assets/cubyz/shaders/deferred_render_pass.fs b/assets/cubyz/shaders/deferred_render_pass.fs index 6441f5c66..585f8c8c5 100644 --- a/assets/cubyz/shaders/deferred_render_pass.fs +++ b/assets/cubyz/shaders/deferred_render_pass.fs @@ -43,7 +43,7 @@ float calculateFogDistance(float depthBufferValue, float fogDensity) { } vec3 applyFrontfaceFog(float fogDistance, vec3 fogColor, vec3 inColor) { - float fogFactor = exp(fogDistance); + float fogFactor = exp(-fogDistance); inColor *= fogFactor; inColor += fogColor; inColor -= fogColor*fogFactor; @@ -54,7 +54,7 @@ void main() { fragColor = texture(color, texCoords); fragColor += texture(bloomColor, texCoords); float densityAdjustment = sqrt(dot(tanXY*(texCoords*2 - 1), tanXY*(texCoords*2 - 1)) + 1); - float fogDistance = calculateFogDistance(texture(depthTexture, texCoords).r, fog.density*densityAdjustment); + float fogDistance = texture(depthTexture, texCoords).r*fog.density*densityAdjustment; fragColor.rgb = applyFrontfaceFog(fogDistance, fog.color, fragColor.rgb); float maxColor = max(1.0, max(fragColor.r, max(fragColor.g, fragColor.b))); fragColor.rgb = fragColor.rgb/maxColor; diff --git a/assets/cubyz/shaders/depth_copy.fs b/assets/cubyz/shaders/depth_copy.fs new file mode 100644 index 000000000..3f9da977d --- /dev/null +++ b/assets/cubyz/shaders/depth_copy.fs @@ -0,0 +1,16 @@ +#version 430 +out vec4 fragColor; +in vec2 texCoords; + +uniform float zNear; +uniform float zFar; + +layout(binding = 5) uniform sampler2D depthBuffer; + +float zFromDepth(float depthBufferValue) { + return zNear*zFar/(depthBufferValue*(zNear - zFar) + zFar); +} + +void main() { + fragColor.r = zFromDepth(texture(depthBuffer, texCoords).r); +} \ No newline at end of file diff --git a/assets/cubyz/shaders/depth_copy.vs b/assets/cubyz/shaders/depth_copy.vs new file mode 100644 index 000000000..ef5ed4080 --- /dev/null +++ b/assets/cubyz/shaders/depth_copy.vs @@ -0,0 +1,10 @@ +#version 430 + +layout (location=0) in vec2 inTexCoords; + +out vec2 texCoords; + +void main() { + texCoords = inTexCoords; + gl_Position = vec4(inTexCoords*2 - vec2(1, 1), 0, 1); +} \ No newline at end of file diff --git a/src/graphics.zig b/src/graphics.zig index 2f6846ada..e6a0e9121 100644 --- a/src/graphics.zig +++ b/src/graphics.zig @@ -1565,6 +1565,10 @@ pub const FrameBuffer = struct { // MARK: FrameBuffer c.glBindTexture(c.GL_TEXTURE_2D, self.texture); } + pub fn bindImage(self: *const FrameBuffer, binding: u5, format: c_uint) void { + c.glBindImageTexture(binding, self.texture, 0, c.GL_FALSE, 0, c.GL_READ_WRITE, format); + } + pub fn bindDepthTexture(self: *const FrameBuffer, target: c_uint) void { std.debug.assert(self.hasDepthTexture); c.glActiveTexture(target); diff --git a/src/renderer.zig b/src/renderer.zig index a03568c9f..d47c696a1 100644 --- a/src/renderer.zig +++ b/src/renderer.zig @@ -43,6 +43,11 @@ var deferredUniforms: struct { zNear: c_int, zFar: c_int, } = undefined; +var depthCopyShader: graphics.Shader = undefined; +var depthCopyUniforms: struct { + zNear: c_int, + zFar: c_int, +} = undefined; var fakeReflectionShader: graphics.Shader = undefined; var fakeReflectionUniforms: struct { normalVector: c_int, @@ -60,8 +65,11 @@ var reflectionCubeMap: graphics.CubeMapTexture = undefined; pub fn init() void { deferredRenderPassShader = Shader.initAndGetUniforms("assets/cubyz/shaders/deferred_render_pass.vs", "assets/cubyz/shaders/deferred_render_pass.fs", "", &deferredUniforms); fakeReflectionShader = Shader.initAndGetUniforms("assets/cubyz/shaders/fake_reflection.vs", "assets/cubyz/shaders/fake_reflection.fs", "", &fakeReflectionUniforms); + depthCopyShader = Shader.initAndGetUniforms("assets/cubyz/shaders/depth_copy.vs", "assets/cubyz/shaders/depth_copy.fs", "", &depthCopyUniforms); worldFrameBuffer.init(true, c.GL_NEAREST, c.GL_CLAMP_TO_EDGE); worldFrameBuffer.updateSize(Window.width, Window.height, c.GL_RGB16F); + transparentDepthFrameBuffer.init(false, c.GL_NEAREST, c.GL_CLAMP_TO_EDGE); + transparentDepthFrameBuffer.updateSize(Window.width, Window.height, c.GL_R16F); Bloom.init(); MeshSelection.init(); MenuBackGround.init() catch |err| { @@ -78,6 +86,7 @@ pub fn deinit() void { deferredRenderPassShader.deinit(); fakeReflectionShader.deinit(); worldFrameBuffer.deinit(); + transparentDepthFrameBuffer.deinit(); Bloom.deinit(); MeshSelection.deinit(); MenuBackGround.deinit(); @@ -108,6 +117,7 @@ fn initReflectionCubeMap() void { } var worldFrameBuffer: graphics.FrameBuffer = undefined; +var transparentDepthFrameBuffer: graphics.FrameBuffer = undefined; var lastWidth: u31 = 0; var lastHeight: u31 = 0; @@ -119,6 +129,8 @@ pub fn updateViewport(width: u31, height: u31, fov: f32) void { game.projectionMatrix = Mat4f.perspective(std.math.degreesToRadians(fov), @as(f32, @floatFromInt(lastWidth))/@as(f32, @floatFromInt(lastHeight)), zNear, zFar); worldFrameBuffer.updateSize(lastWidth, lastHeight, c.GL_RGB16F); worldFrameBuffer.unbind(); + transparentDepthFrameBuffer.updateSize(lastWidth, lastHeight, c.GL_R16F); + transparentDepthFrameBuffer.unbind(); } pub fn render(playerPosition: Vec3d) void { @@ -221,9 +233,27 @@ pub fn renderWorld(world: *World, ambientLight: Vec3f, skyColor: Vec3f, playerPo gpu_performance_measuring.stopQuery(); // Render transparent chunk meshes: - worldFrameBuffer.bindDepthTexture(c.GL_TEXTURE5); + gpu_performance_measuring.startQuery(.transparent_rendering_preparation); + + worldFrameBuffer.bindDepthTexture(c.GL_TEXTURE5); + c.glTextureBarrier(); + transparentDepthFrameBuffer.bind(); + depthCopyShader.bind(); + c.glUniform1f(depthCopyUniforms.zNear, zNear); + c.glUniform1f(depthCopyUniforms.zFar, zFar); + c.glDisable(c.GL_DEPTH_TEST); + c.glDisable(c.GL_CULL_FACE); + c.glDisable(c.GL_BLEND); + c.glBindVertexArray(graphics.draw.rectVAO); + c.glDrawArrays(c.GL_TRIANGLE_STRIP, 0, 4); + c.glEnable(c.GL_BLEND); + c.glEnable(c.GL_DEPTH_TEST); + c.glEnable(c.GL_CULL_FACE); + worldFrameBuffer.bind(); + transparentDepthFrameBuffer.bindImage(5, c.GL_R16F); + c.glMemoryBarrier(c.GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); c.glTextureBarrier(); c.glBlendEquation(c.GL_FUNC_ADD); @@ -260,7 +290,7 @@ pub fn renderWorld(world: *World, ambientLight: Vec3f, skyColor: Vec3f, playerPo gpu_performance_measuring.startQuery(.final_copy); if(activeFrameBuffer == 0) c.glViewport(0, 0, main.Window.width, main.Window.height); worldFrameBuffer.bindTexture(c.GL_TEXTURE3); - worldFrameBuffer.bindDepthTexture(c.GL_TEXTURE4); + transparentDepthFrameBuffer.bindTexture(c.GL_TEXTURE4); worldFrameBuffer.unbind(); deferredRenderPassShader.bind(); c.glUniform1i(deferredUniforms.color, 3);