From 044ab3bb626fa0d798537e69d63a6ff2d1aa1bec Mon Sep 17 00:00:00 2001 From: IntegratedQuantum Date: Fri, 29 Sep 2023 17:28:38 +0200 Subject: [PATCH] Rework the fog, so it doesn't need the alpha component anymore. This also fixes #93 as a side effect This could also theoretically improve performance due to using a smaller image format, but I couldn't measure a bit difference on my computer, it might be that my driver/hardware just pads the alpha component. --- .../bloom/color_extractor_downsample.fs | 20 ++++++++---------- .../shaders/chunks/transparent_fragment.fs | 20 +++++++++++------- assets/cubyz/shaders/deferred_render_pass.fs | 21 ++++++++----------- assets/cubyz/shaders/item_texture_post.fs | 1 - src/graphics.zig | 12 ++++++++--- src/renderer.zig | 8 +++---- 6 files changed, 43 insertions(+), 39 deletions(-) diff --git a/assets/cubyz/shaders/bloom/color_extractor_downsample.fs b/assets/cubyz/shaders/bloom/color_extractor_downsample.fs index d2cd4f04..122a7e80 100644 --- a/assets/cubyz/shaders/bloom/color_extractor_downsample.fs +++ b/assets/cubyz/shaders/bloom/color_extractor_downsample.fs @@ -43,22 +43,20 @@ float calculateFogDistance(float depthBufferValue, float fogDensity) { } } +vec3 applyFrontfaceFog(float fogDistance, vec3 fogColor, vec3 inColor) { + float fogFactor = exp(fogDistance); + inColor *= fogFactor; + inColor += fogColor; + inColor -= fogColor*fogFactor; + return 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); vec3 fogColor = fog.color; - float fogFactor = exp(fogDistance); - vec4 sourceColor = vec4(fogColor, 1); - sourceColor.a = 1.0/fogFactor; - sourceColor.rgb *= sourceColor.a; - sourceColor.rgb -= fogColor; - vec3 source2Color = vec3(1); - rgba = vec4( - source2Color*rgba.rgb + rgba.a*sourceColor.rgb, - rgba.a*sourceColor.a - ); - if(rgba.a < 1) return vec3(0); // Prevent t-junctions from transparency from making a huge mess. + 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 a491435d..ae1883eb 100644 --- a/assets/cubyz/shaders/chunks/transparent_fragment.fs +++ b/assets/cubyz/shaders/chunks/transparent_fragment.fs @@ -105,17 +105,19 @@ float calculateFogDistance(float depthBufferValue, float fogDensity) { void applyFrontfaceFog(float fogDistance, vec3 fogColor) { float fogFactor = exp(fogDistance); - fragColor.a = 1.0/fogFactor; - fragColor.rgb = fragColor.a*fogColor; - fragColor.rgb -= fogColor; + fragColor.rgb *= fogFactor; + fragColor.rgb += fogColor; + fragColor.rgb -= fogColor*fogFactor; + fragColor.a = fogFactor; } void applyBackfaceFog(float fogDistance, vec3 fogColor) { float fogFactor = exp(fogDistance); float oldAlpha = fragColor.a; - fragColor.a *= fogFactor; - fragColor.rgb -= oldAlpha*fogColor; - fragColor.rgb += fragColor.a*fogColor; + fragColor.rgb *= 1.0/fogFactor; + fragColor.rgb -= fogColor/fogFactor; + fragColor.rgb += fogColor; + fragColor.a *= 1.0/fogFactor; } vec2 getTextureCoordsNormal(vec3 voxelPosition, int textureDir) { @@ -181,7 +183,7 @@ void main() { // Apply the texture+absorption fragColor.rgb *= blendColor.rgb; - fragColor.rgb += textureColor.rgb*fragColor.a; + fragColor.rgb += textureColor.rgb; // Apply the air fog: applyBackfaceFog(airFogDistance, fog.color); @@ -193,9 +195,11 @@ void main() { vec4 textureColor = texture(texture_sampler, vec3(getTextureCoordsNormal(startPosition/16, faceNormal), textureIndex))*vec4(ambientLight*normalVariation, 1); blendColor.rgb = vec3(1 - textureColor.a); fragColor.rgb *= blendColor.rgb; - fragColor.rgb += textureColor.rgb*textureColor.a*fragColor.a; + fragColor.rgb += textureColor.rgb*textureColor.a; // Apply the block fog: applyBackfaceFog(fogDistance, fogColor); } + blendColor.rgb *= fragColor.a; + fragColor.a = 1; } diff --git a/assets/cubyz/shaders/deferred_render_pass.fs b/assets/cubyz/shaders/deferred_render_pass.fs index 7c97af9b..9657dfc6 100644 --- a/assets/cubyz/shaders/deferred_render_pass.fs +++ b/assets/cubyz/shaders/deferred_render_pass.fs @@ -41,22 +41,19 @@ float calculateFogDistance(float depthBufferValue, float fogDensity) { } } +vec3 applyFrontfaceFog(float fogDistance, vec3 fogColor, vec3 inColor) { + float fogFactor = exp(fogDistance); + inColor *= fogFactor; + inColor += fogColor; + inColor -= fogColor*fogFactor; + return inColor; +} + void main() { fragColor = texture(color, texCoords); float densityAdjustment = sqrt(dot(tanXY*(texCoords*2 - 1), tanXY*(texCoords*2 - 1)) + 1); float fogDistance = calculateFogDistance(texelFetch(depthTexture, ivec2(gl_FragCoord.xy), 0).r, fog.density*densityAdjustment); - vec3 fogColor = fog.color; - float fogFactor = exp(fogDistance); - vec4 sourceColor = vec4(fogColor, 1); - sourceColor.a = 1.0/fogFactor; - sourceColor.rgb *= sourceColor.a; - sourceColor.rgb -= fogColor; - vec3 source2Color = vec3(1); - fragColor = vec4( - source2Color*fragColor.rgb + fragColor.a*sourceColor.rgb, - fragColor.a*sourceColor.a - ); - fragColor.rgb /= fragColor.a; + 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; } \ No newline at end of file diff --git a/assets/cubyz/shaders/item_texture_post.fs b/assets/cubyz/shaders/item_texture_post.fs index 8c06fb8f..6f7eae46 100644 --- a/assets/cubyz/shaders/item_texture_post.fs +++ b/assets/cubyz/shaders/item_texture_post.fs @@ -9,7 +9,6 @@ uniform bool transparent; void main() { fragColor = texture(color, texCoords); if(transparent) { - fragColor.rgb /= fragColor.a; fragColor.a = 1; // TODO: Remove the background color. Somehow? } diff --git a/src/graphics.zig b/src/graphics.zig index 4b7389ca..a57bb01e 100644 --- a/src/graphics.zig +++ b/src/graphics.zig @@ -1701,7 +1701,13 @@ const block_texture = struct { depthTexture = Texture.init(); depthTexture.bind(); var data: [128*128]f32 = undefined; - @memset(&data, main.renderer.zNear/132.0); + + const z: f32 = 134; + const near = main.renderer.zNear; + const far = main.renderer.zFar; + const depth = ((far + near)/(near - far)*z + 2*near*far/(near - far))/-z*0.5 + 0.5; + + @memset(&data, depth); c.glTexImage2D(c.GL_TEXTURE_2D, 0, c.GL_R32F, textureSize, textureSize, 0, c.GL_RED, c.GL_FLOAT, &data); c.glTexParameteri(c.GL_TEXTURE_2D, c.GL_TEXTURE_MIN_FILTER, c.GL_NEAREST); c.glTexParameteri(c.GL_TEXTURE_2D, c.GL_TEXTURE_MAG_FILTER, c.GL_NEAREST); @@ -1745,8 +1751,8 @@ pub fn generateBlockTexture(blockType: u16) !Texture { main.game.camera.viewMatrix = Mat4f.rotationX(std.math.pi/4.0).mul(Mat4f.rotationY(-std.math.pi/4.0)); defer main.game.camera.viewMatrix = oldViewMatrix; if(block.transparent()) { - c.glBlendEquationSeparate(c.GL_FUNC_ADD, c.GL_FUNC_ADD); - c.glBlendFuncSeparate(c.GL_DST_ALPHA, c.GL_SRC1_COLOR, c.GL_DST_ALPHA, c.GL_ZERO); + c.glBlendEquation(c.GL_FUNC_ADD); + c.glBlendFunc(c.GL_ONE, c.GL_SRC1_COLOR); main.chunk.meshing.bindTransparentShaderAndUniforms(projMatrix, .{1, 1, 1}, 0); } else { main.chunk.meshing.bindShaderAndUniforms(projMatrix, .{1, 1, 1}, 0); diff --git a/src/renderer.zig b/src/renderer.zig index 36ff1993..2b42fb5b 100644 --- a/src/renderer.zig +++ b/src/renderer.zig @@ -58,7 +58,7 @@ pub fn init() !void { deferredRenderPassShader = try Shader.initAndGetUniforms("assets/cubyz/shaders/deferred_render_pass.vs", "assets/cubyz/shaders/deferred_render_pass.fs", &deferredUniforms); fakeReflectionShader = try Shader.initAndGetUniforms("assets/cubyz/shaders/fake_reflection.vs", "assets/cubyz/shaders/fake_reflection.fs", &fakeReflectionUniforms); worldFrameBuffer.init(true, c.GL_NEAREST, c.GL_CLAMP_TO_EDGE); - worldFrameBuffer.updateSize(Window.width, Window.height, c.GL_RGBA16F); + worldFrameBuffer.updateSize(Window.width, Window.height, c.GL_RGB16F); try Bloom.init(); try MeshSelection.init(); try MenuBackGround.init(); @@ -109,7 +109,7 @@ pub fn updateViewport(width: u31, height: u31, fov: f32) void { lastFov = fov; c.glViewport(0, 0, width, height); game.projectionMatrix = Mat4f.perspective(std.math.degreesToRadians(f32, fov), @as(f32, @floatFromInt(width))/@as(f32, @floatFromInt(height)), zNear, zFar); - worldFrameBuffer.updateSize(width, height, c.GL_RGBA16F); + worldFrameBuffer.updateSize(width, height, c.GL_RGB16F); worldFrameBuffer.unbind(); } @@ -227,8 +227,8 @@ pub fn renderWorld(world: *World, ambientLight: Vec3f, skyColor: Vec3f, playerPo c.glTextureBarrier(); chunk.meshing.bindTransparentShaderAndUniforms(game.projectionMatrix, ambientLight, time); - c.glBlendEquationSeparate(c.GL_FUNC_ADD, c.GL_FUNC_ADD); - c.glBlendFuncSeparate(c.GL_DST_ALPHA, c.GL_SRC1_COLOR, c.GL_DST_ALPHA, c.GL_ZERO); + c.glBlendEquation(c.GL_FUNC_ADD); + c.glBlendFunc(c.GL_ONE, c.GL_SRC1_COLOR); c.glDepthFunc(c.GL_LEQUAL); c.glDepthMask(c.GL_FALSE); {