From 4eba43b2d6ed9ad4b9243abe48def1a2ba309b53 Mon Sep 17 00:00:00 2001 From: Jozufozu Date: Mon, 17 Feb 2025 20:12:17 -0800 Subject: [PATCH] 8 moments - Use 8 power moments - Fix compile errors with trig moments --- .../flywheel/backend/Samplers.java | 3 +- .../engine/indirect/MboitFramebuffer.java | 73 +++++++++++++++---- .../flywheel/flywheel/internal/common.frag | 5 +- .../internal/mboit/complex_algebra.glsl | 16 +++- .../flywheel/internal/mboit/moment_math.glsl | 12 +-- .../flywheel/internal/mboit/moment_oit.glsl | 48 ++++++------ .../mboit/trigonometric_moment_math.glsl | 8 +- .../vanillin/visuals/ShulkerBoxVisual.java | 7 -- 8 files changed, 104 insertions(+), 68 deletions(-) diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/Samplers.java b/common/src/backend/java/dev/engine_room/flywheel/backend/Samplers.java index b6e40e291..e89acccbb 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/Samplers.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/Samplers.java @@ -12,5 +12,6 @@ public class Samplers { public static final GlTextureUnit LIGHT_SECTIONS = GlTextureUnit.T6; public static final GlTextureUnit ZEROTH_MOMENT = GlTextureUnit.T7; - public static final GlTextureUnit MOMENTS = GlTextureUnit.T8; + public static final GlTextureUnit MOMENTS0 = GlTextureUnit.T8; + public static final GlTextureUnit MOMENTS1 = GlTextureUnit.T9; } diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/MboitFramebuffer.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/MboitFramebuffer.java index 06d283f20..747020e73 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/MboitFramebuffer.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/MboitFramebuffer.java @@ -10,6 +10,7 @@ import dev.engine_room.flywheel.backend.Samplers; import dev.engine_room.flywheel.backend.compile.IndirectPrograms; import dev.engine_room.flywheel.backend.gl.GlTextureUnit; import net.minecraft.client.Minecraft; +import net.minecraft.util.Mth; public class MboitFramebuffer { @@ -18,7 +19,8 @@ public class MboitFramebuffer { private final int vao; public int zerothMoment; - public int moments; + public int moments0; + public int moments1; public int accumulate; private int lastWidth = -1; @@ -44,10 +46,11 @@ public class MboitFramebuffer { GL46.glNamedFramebufferTexture(fbo, GL46.GL_DEPTH_ATTACHMENT, mainRenderTarget.getDepthTextureId(), 0); - GL46.glNamedFramebufferDrawBuffers(fbo, new int[]{GL46.GL_COLOR_ATTACHMENT0, GL46.GL_COLOR_ATTACHMENT1}); + GL46.glNamedFramebufferDrawBuffers(fbo, new int[]{GL46.GL_COLOR_ATTACHMENT0, GL46.GL_COLOR_ATTACHMENT1, GL46.GL_COLOR_ATTACHMENT2}); GL46.glClearNamedFramebufferfv(fbo, GL46.GL_COLOR, 0, new float[]{0, 0, 0, 0}); GL46.glClearNamedFramebufferfv(fbo, GL46.GL_COLOR, 1, new float[]{0, 0, 0, 0}); + GL46.glClearNamedFramebufferfv(fbo, GL46.GL_COLOR, 2, new float[]{0, 0, 0, 0}); GlStateManager._glBindFramebuffer(GL46.GL_FRAMEBUFFER, fbo); } @@ -62,10 +65,13 @@ public class MboitFramebuffer { Samplers.ZEROTH_MOMENT.makeActive(); GlStateManager._bindTexture(zerothMoment); - Samplers.MOMENTS.makeActive(); - GlStateManager._bindTexture(moments); + Samplers.MOMENTS0.makeActive(); + GlStateManager._bindTexture(moments0); - GL46.glNamedFramebufferDrawBuffers(fbo, new int[]{GL46.GL_COLOR_ATTACHMENT2}); + Samplers.MOMENTS1.makeActive(); + GlStateManager._bindTexture(moments1); + + GL46.glNamedFramebufferDrawBuffers(fbo, new int[]{GL46.GL_COLOR_ATTACHMENT3}); GL46.glClearNamedFramebufferfv(fbo, GL46.GL_COLOR, 0, new float[]{0, 0, 0, 0}); @@ -100,13 +106,18 @@ public class MboitFramebuffer { } public void delete() { - GL46.glDeleteTextures(zerothMoment); - GL46.glDeleteTextures(moments); - GL46.glDeleteTextures(accumulate); + deleteTextures(); GL46.glDeleteFramebuffers(fbo); GL46.glDeleteVertexArrays(vao); } + private void deleteTextures() { + GL46.glDeleteTextures(zerothMoment); + GL46.glDeleteTextures(moments0); + GL46.glDeleteTextures(moments1); + GL46.glDeleteTextures(accumulate); + } + private void createTextures(int width, int height) { if (lastWidth == width && lastHeight == height) { return; @@ -115,16 +126,17 @@ public class MboitFramebuffer { lastWidth = width; lastHeight = height; - GL46.glDeleteTextures(zerothMoment); - GL46.glDeleteTextures(moments); - GL46.glDeleteTextures(accumulate); + deleteTextures(); zerothMoment = GL46.glCreateTextures(GL46.GL_TEXTURE_2D); - moments = GL46.glCreateTextures(GL46.GL_TEXTURE_2D); + moments0 = GL46.glCreateTextures(GL46.GL_TEXTURE_2D); + moments1 = GL46.glCreateTextures(GL46.GL_TEXTURE_2D); accumulate = GL46.glCreateTextures(GL46.GL_TEXTURE_2D); GL46.glTextureStorage2D(zerothMoment, 1, GL32.GL_R16F, width, height); - GL46.glTextureStorage2D(moments, 1, GL32.GL_RGBA16F, width, height); + GL46.glTextureStorage2D(moments0, 1, GL32.GL_RGBA16F, width, height); + GL46.glTextureStorage2D(moments1, 1, GL32.GL_RGBA16F, width, height); + GL46.glTextureStorage2D(accumulate, 1, GL32.GL_RGBA16F, width, height); // for (int tex : new int[]{zerothMoment, moments, composite}) { @@ -136,7 +148,38 @@ public class MboitFramebuffer { // } GL46.glNamedFramebufferTexture(fbo, GL46.GL_COLOR_ATTACHMENT0, zerothMoment, 0); - GL46.glNamedFramebufferTexture(fbo, GL46.GL_COLOR_ATTACHMENT1, moments, 0); - GL46.glNamedFramebufferTexture(fbo, GL46.GL_COLOR_ATTACHMENT2, accumulate, 0); + GL46.glNamedFramebufferTexture(fbo, GL46.GL_COLOR_ATTACHMENT1, moments0, 0); + GL46.glNamedFramebufferTexture(fbo, GL46.GL_COLOR_ATTACHMENT2, moments1, 0); + GL46.glNamedFramebufferTexture(fbo, GL46.GL_COLOR_ATTACHMENT3, accumulate, 0); + } + + float circleToParameter(float angle) { + float x = Mth.cos(angle); + float y = Mth.sin(angle); + float result = Mth.abs(y) - Mth.abs(x); + result = (x < 0.0f) ? (2.0f - result) : result; + result = (y < 0.0f) ? (6.0f - result) : result; + result += (angle >= 2.0f * Mth.PI) ? 8.0f : 0.0f; + return result; + } + + void computeWrappingZoneParameters(float[] out) { + computeWrappingZoneParameters(out, 0.1f * Mth.PI); + } + + /*! Given an angle in radians providing the size of the wrapping zone, this + function computes all constants required by the shader.*/ + void computeWrappingZoneParameters(float[] p_out_wrapping_zone_parameters, float new_wrapping_zone_angle) { + p_out_wrapping_zone_parameters[0] = new_wrapping_zone_angle; + p_out_wrapping_zone_parameters[1] = Mth.PI - 0.5f * new_wrapping_zone_angle; + if (new_wrapping_zone_angle <= 0.0f) { + p_out_wrapping_zone_parameters[2] = 0.0f; + p_out_wrapping_zone_parameters[3] = 0.0f; + } else { + float zone_end_parameter = 7; + float zone_begin_parameter = circleToParameter(2.0f * Mth.PI - new_wrapping_zone_angle); + p_out_wrapping_zone_parameters[2] = 1.0f / (zone_end_parameter - zone_begin_parameter); + p_out_wrapping_zone_parameters[3] = 1.0f - zone_end_parameter * p_out_wrapping_zone_parameters[2]; + } } } diff --git a/common/src/backend/resources/assets/flywheel/flywheel/internal/common.frag b/common/src/backend/resources/assets/flywheel/flywheel/internal/common.frag index afd8ae647..3cb61f8a5 100644 --- a/common/src/backend/resources/assets/flywheel/flywheel/internal/common.frag +++ b/common/src/backend/resources/assets/flywheel/flywheel/internal/common.frag @@ -21,7 +21,8 @@ flat in uvec2 _flw_ids; #ifdef _FLW_OIT #ifdef _FLW_GENERATE_MOMENTS layout (location = 0) out float _flw_zerothMoment_out; -layout (location = 1) out vec4 _flw_moments_out; +layout (location = 1) out vec4 _flw_moments0_out; +layout (location = 2) out vec4 _flw_moments1_out; #endif #ifdef _FLW_RESOLVE_MOMENTS layout (location = 0) out vec4 _flw_accumulate_out; @@ -133,7 +134,7 @@ void _flw_main() { #ifdef _FLW_GENERATE_MOMENTS - generateMoments(depth, 1 - color.a, vec4(0), _flw_zerothMoment_out, _flw_moments_out); + generateMoments(depth, 1 - color.a, _flw_zerothMoment_out, _flw_moments0_out, _flw_moments1_out); #endif #ifdef _FLW_RESOLVE_MOMENTS diff --git a/common/src/backend/resources/assets/flywheel/flywheel/internal/mboit/complex_algebra.glsl b/common/src/backend/resources/assets/flywheel/flywheel/internal/mboit/complex_algebra.glsl index b2cf49485..30848e3f7 100644 --- a/common/src/backend/resources/assets/flywheel/flywheel/internal/mboit/complex_algebra.glsl +++ b/common/src/backend/resources/assets/flywheel/flywheel/internal/mboit/complex_algebra.glsl @@ -2,6 +2,16 @@ This header defines utility functions to deal with complex numbers and complex polynomials.*/ +void sincos(float theta, out float s, out float c) { + s = sin(theta); + c = cos(theta); +} + +float saturate(float a) { + return clamp(a, 0., 1.); +} + + /*! Returns the complex conjugate of the given complex number (i.e. it changes the sign of the y-component).*/ vec2 Conjugate(vec2 Z){ @@ -45,11 +55,11 @@ vec2 Cube(vec2 Z){ \sa SquareRoot() */ vec2 SquareRootUnsafe(vec2 Z){ float ZLengthSq=dot(Z, Z); - float ZLengthInv=rsqrt(ZLengthSq); + float ZLengthInv=inversesqrt(ZLengthSq); vec2 UnnormalizedRoot=Z*ZLengthInv+vec2(1.0f, 0.0f); float UnnormalizedRootLengthSq=dot(UnnormalizedRoot, UnnormalizedRoot); float NormalizationFactorInvSq=UnnormalizedRootLengthSq*ZLengthInv; - float NormalizationFactor=rsqrt(NormalizationFactorInvSq); + float NormalizationFactor=inversesqrt(NormalizationFactorInvSq); return NormalizationFactor*UnnormalizedRoot; } /*! This utility function computes one square root of the given complex value. @@ -65,7 +75,7 @@ vec2 SquareRoot(vec2 Z){ other roots can be found by multiplication by cubic roots of unity. \note This function has various discontinuities.*/ vec2 CubicRoot(vec2 Z){ - float Argument=atan2(Z.y, Z.x); + float Argument=atan(Z.y, Z.x); float NewArgument=Argument/3.0f; vec2 NormalizedRoot; sincos(NewArgument, NormalizedRoot.y, NormalizedRoot.x); diff --git a/common/src/backend/resources/assets/flywheel/flywheel/internal/mboit/moment_math.glsl b/common/src/backend/resources/assets/flywheel/flywheel/internal/mboit/moment_math.glsl index 0c2d23b72..4f730eada 100644 --- a/common/src/backend/resources/assets/flywheel/flywheel/internal/mboit/moment_math.glsl +++ b/common/src/backend/resources/assets/flywheel/flywheel/internal/mboit/moment_math.glsl @@ -5,17 +5,7 @@ roots of polynomials up to degree four are defined. */ -//#include "flywheel:internal/mboit/trigonometric_moment_math.glsl" - -void sincos(float theta, out float s, out float c) { - s = sin(theta); - c = cos(theta); -} - -float saturate(float a) { - return clamp(a, 0., 1.); -} - +#include "flywheel:internal/mboit/trigonometric_moment_math.glsl" /*! Given coefficients of a quadratic polynomial A*x^2+B*x+C, this function diff --git a/common/src/backend/resources/assets/flywheel/flywheel/internal/mboit/moment_oit.glsl b/common/src/backend/resources/assets/flywheel/flywheel/internal/mboit/moment_oit.glsl index f26d5582e..23ef4ec03 100644 --- a/common/src/backend/resources/assets/flywheel/flywheel/internal/mboit/moment_oit.glsl +++ b/common/src/backend/resources/assets/flywheel/flywheel/internal/mboit/moment_oit.glsl @@ -17,7 +17,7 @@ const float moment_bias = 0.25; const float overestimation = 0.25; -const vec4 wrapping_zone_parameters = vec4(0.); +const vec4 wrapping_zone_parameters = vec4(0.31415927, 2.984513, 2.7934167, -18.553917); void clip(float a) { @@ -28,7 +28,7 @@ void clip(float a) { // jozu: The trigonometric moments and higher order power moments rely on a second render target // which the java side is not set up to support. Trying to enable them as is will cause compile errors also. -#define NUM_MOMENTS 4 +#define NUM_MOMENTS 8 #define SINGLE_PRECISION 1 @@ -40,15 +40,15 @@ void clip(float a) { vector of moments.moment vector. The shader that calls this function must provide the required render targets.*/ #if NUM_MOMENTS == 4 -void generateMoments(float depth, float transmittance, vec4 wrapping_zone_parameters, out float b_0, out vec4 b) +void generateMoments(float depth, float transmittance, out float b_0, out vec4 b) #elif NUM_MOMENTS == 6 #if USE_R_RG_RBBA_FOR_MBOIT6 -void generateMoments(float depth, float transmittance, vec4 wrapping_zone_parameters, out float b_0, out vec2 b_12, out vec4 b_3456) +void generateMoments(float depth, float transmittance, out float b_0, out vec2 b_12, out vec4 b_3456) #else -void generateMoments(float depth, float transmittance, vec4 wrapping_zone_parameters, out float b_0, out vec2 b_12, out vec2 b_34, out vec2 b_56) +void generateMoments(float depth, float transmittance, out float b_0, out vec2 b_12, out vec2 b_34, out vec2 b_56) #endif #elif NUM_MOMENTS == 8 -void generateMoments(float depth, float transmittance, vec4 wrapping_zone_parameters, out float b_0, out vec4 b_even, out vec4 b_odd) +void generateMoments(float depth, float transmittance, out float b_0, out vec4 b_even, out vec4 b_odd) #endif { transmittance = max(transmittance, 0.000001); @@ -57,7 +57,7 @@ void generateMoments(float depth, float transmittance, vec4 wrapping_zone_parame b_0 = absorbance; #if TRIGONOMETRIC float phase = fma(depth, wrapping_zone_parameters.y, wrapping_zone_parameters.y); - vec2 circle_point = vec2(sin(phas), cos(phase)); + vec2 circle_point = vec2(sin(phase), cos(phase)); vec2 circle_point_pow2 = Multiply(circle_point, circle_point); #if NUM_MOMENTS == 4 @@ -98,10 +98,8 @@ void generateMoments(float depth, float transmittance, vec4 wrapping_zone_parame #else//MOMENT_GENERATION is disabled layout (binding = 7) uniform sampler2D _flw_zeroth_moment_sampler; -layout (binding = 8) uniform sampler2D _flw_moments_sampler; -#if USE_R_RG_RBBA_FOR_MBOIT6 -uniform sampler2D extra_moments; -#endif +layout (binding = 8) uniform sampler2D _flw_moments0_sampler; +layout (binding = 9) uniform sampler2D _flw_moments1_sampler; /*! This function is to be called from the shader that composites the transparent fragments. It reads the moments and calls the appropriate @@ -120,7 +118,7 @@ void resolveMoments(out float transmittance_at_depth, out float total_transmitta #if NUM_MOMENTS == 4 #if TRIGONOMETRIC - vec4 b_tmp = texelFetch(_flw_moments_sampler, idx0, 0); + vec4 b_tmp = texelFetch(_flw_moments0_sampler, idx0, 0); vec2 trig_b[2]; trig_b[0] = b_tmp.xy; trig_b[1] = b_tmp.zw; @@ -133,7 +131,7 @@ void resolveMoments(out float transmittance_at_depth, out float total_transmitta #endif transmittance_at_depth = computeTransmittanceAtDepthFrom2TrigonometricMoments(b_0, trig_b, depth, moment_bias, overestimation, wrapping_zone_parameters); #else - vec4 b_1234 = texelFetch(_flw_moments_sampler, idx0, 0).xyzw; + vec4 b_1234 = texelFetch(_flw_moments0_sampler, idx0, 0).xyzw; #if SINGLE_PRECISION vec2 b_even = b_1234.yw; vec2 b_odd = b_1234.xz; @@ -158,14 +156,14 @@ void resolveMoments(out float transmittance_at_depth, out float total_transmitta ivec2 idx2 = idx0; #if TRIGONOMETRIC vec2 trig_b[3]; - trig_b[0] = texelFetch(_flw_moments_sampler, idx0, 0).xy; + trig_b[0] = texelFetch(_flw_moments0_sampler, idx0, 0).xy; #if USE_R_RG_RBBA_FOR_MBOIT6 vec4 tmp = texelFetch(extra_moments, idx0, 0); trig_b[1] = tmp.xy; trig_b[2] = tmp.zw; #else - trig_b[1] = texelFetch(_flw_moments_sampler, idx1, 0).xy; - trig_b[2] = texelFetch(_flw_moments_sampler, idx2, 0).xy; + trig_b[1] = texelFetch(_flw_moments1_sampler, idx1, 0).xy; + trig_b[2] = texelFetch(_flw_moments0_sampler, idx2, 0).xy; #endif #if SINGLE_PRECISION trig_b[0] /= b_0; @@ -178,14 +176,14 @@ void resolveMoments(out float transmittance_at_depth, out float total_transmitta #endif transmittance_at_depth = computeTransmittanceAtDepthFrom3TrigonometricMoments(b_0, trig_b, depth, moment_bias, overestimation, wrapping_zone_parameters); #else - vec2 b_12 = texelFetch(_flw_moments_sampler, idx0, 0).xy; + vec2 b_12 = texelFetch(_flw_moments0_sampler, idx0, 0).xy; #if USE_R_RG_RBBA_FOR_MBOIT6 vec4 tmp = texelFetch(extra_moments, idx0, 0); vec2 b_34 = tmp.xy; vec2 b_56 = tmp.zw; #else - vec2 b_34 = texelFetch(_flw_moments_sampler, idx1, 0).xy; - vec2 b_56 = texelFetch(_flw_moments_sampler, idx2, 0).xy; + vec2 b_34 = texelFetch(_flw_moments1_sampler, idx1, 0).xy; + vec2 b_56 = texelFetch(_flw_moments0_sampler, idx2, 0).xy; #endif #if SINGLE_PRECISION vec3 b_even = vec3(b_12.y, b_34.y, b_56.y); @@ -209,8 +207,8 @@ void resolveMoments(out float transmittance_at_depth, out float total_transmitta #endif #elif NUM_MOMENTS == 8 #if TRIGONOMETRIC - vec4 b_tmp = texelFetch(_flw_moments_sampler, idx0, 0); - vec4 b_tmp2 = texelFetch(_flw_moments_sampler, idx1, 0); + vec4 b_tmp = texelFetch(_flw_moments0_sampler, idx0, 0); + vec4 b_tmp2 = texelFetch(_flw_moments1_sampler, idx1, 0); #if SINGLE_PRECISION vec2 trig_b[4] = { b_tmp2.xy / b_0, @@ -229,15 +227,15 @@ void resolveMoments(out float transmittance_at_depth, out float total_transmitta transmittance_at_depth = computeTransmittanceAtDepthFrom4TrigonometricMoments(b_0, trig_b, depth, moment_bias, overestimation, wrapping_zone_parameters); #else #if SINGLE_PRECISION - vec4 b_even = texelFetch(_flw_moments_sampler, idx0, 0); - vec4 b_odd = texelFetch(_flw_moments_sampler, idx1, 0); + vec4 b_even = texelFetch(_flw_moments0_sampler, idx0, 0); + vec4 b_odd = texelFetch(_flw_moments1_sampler, idx1, 0); b_even /= b_0; b_odd /= b_0; const float bias_vector[8] = { 0, 0.75, 0, 0.67666666666666664, 0, 0.63, 0, 0.60030303030303034 }; #else - vec4 b_even_q = texelFetch(_flw_moments_sampler, idx0, 0); - vec4 b_odd_q = texelFetch(_flw_moments_sampler, idx1, 0); + vec4 b_even_q = texelFetch(_flw_moments0_sampler, idx0, 0); + vec4 b_odd_q = texelFetch(_flw_moments1_sampler, idx1, 0); // Dequantize the moments vec4 b_even; diff --git a/common/src/backend/resources/assets/flywheel/flywheel/internal/mboit/trigonometric_moment_math.glsl b/common/src/backend/resources/assets/flywheel/flywheel/internal/mboit/trigonometric_moment_math.glsl index 4fc142d8f..30fe6a65e 100644 --- a/common/src/backend/resources/assets/flywheel/flywheel/internal/mboit/trigonometric_moment_math.glsl +++ b/common/src/backend/resources/assets/flywheel/flywheel/internal/mboit/trigonometric_moment_math.glsl @@ -21,7 +21,7 @@ float circleToParameter(vec2 circle_point){ returns 1.0, otherwise 0.0 or a linear ramp in the wrapping zone.*/ float getRootWeightFactor(float reference_parameter, float root_parameter, vec4 wrapping_zone_parameters){ float binary_weight_factor=(root_parameter