diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/uniform/FrameUniforms.java b/src/main/java/com/jozufozu/flywheel/backend/engine/uniform/FrameUniforms.java index 2f334f02e..cc23e8233 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/uniform/FrameUniforms.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/uniform/FrameUniforms.java @@ -2,26 +2,58 @@ package com.jozufozu.flywheel.backend.engine.uniform; import org.jetbrains.annotations.Nullable; import org.joml.Matrix4f; +import org.joml.Vector2f; +import org.joml.Vector3f; import org.lwjgl.system.MemoryUtil; import com.jozufozu.flywheel.api.event.RenderContext; import com.jozufozu.flywheel.api.visualization.VisualizationManager; +import com.jozufozu.flywheel.backend.mixin.GameRendererAccessor; import com.jozufozu.flywheel.lib.math.MatrixMath; +import com.mojang.blaze3d.vertex.PoseStack; + import net.minecraft.client.Camera; import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.core.BlockPos; import net.minecraft.core.Vec3i; +import net.minecraft.tags.FluidTags; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.FluidState; import net.minecraft.world.phys.Vec3; public class FrameUniforms implements UniformProvider { - public static final int SIZE = 304; + public static final int SIZE = 1188; public int debugMode; - @Nullable + @Nullable private RenderContext context; + private final Matrix4f view = new Matrix4f(); + private final Matrix4f viewInverse = new Matrix4f(); + private final Matrix4f viewPrev = new Matrix4f(); + private final Matrix4f projection = new Matrix4f(); + private final Matrix4f projectionInverse = new Matrix4f(); + private final Matrix4f projectionPrev = new Matrix4f(); private final Matrix4f viewProjection = new Matrix4f(); private final Matrix4f viewProjectionInverse = new Matrix4f(); + private final Matrix4f viewProjectionPrev = new Matrix4f(); + + private final Matrix4f cleanProjection = new Matrix4f(); + private final Matrix4f cleanProjectionInverse = new Matrix4f(); + private final Matrix4f cleanProjectionPrev = new Matrix4f(); + private final Matrix4f cleanViewProjection = new Matrix4f(); + private final Matrix4f cleanViewProjectionInverse = new Matrix4f(); + private final Matrix4f cleanViewProjectionPrev = new Matrix4f(); + + private final Vector3f cameraPositionPrev = new Vector3f(); + private final Vector3f cameraLookPrev = new Vector3f(); + private final Vector2f cameraRotPrev = new Vector2f(); + + private boolean lastInit = false; public int byteSize() { return SIZE; @@ -46,8 +78,12 @@ public class FrameUniforms implements UniformProvider { var camY = (float) (cameraPos.y - renderOrigin.getY()); var camZ = (float) (cameraPos.z - renderOrigin.getZ()); + view.set(context.stack().last().pose()); + view.translate(-camX, -camY, -camZ); + projection.set(context.projection()); viewProjection.set(context.viewProjection()); viewProjection.translate(-camX, -camY, -camZ); + setupCleanMatrices(context.stack(), camera, context.partialTick()); if (!Uniforms.frustumPaused || Uniforms.frustumCapture) { MatrixMath.writePackedFrustumPlanes(ptr, viewProjection); @@ -56,9 +92,34 @@ public class FrameUniforms implements UniformProvider { ptr += 96; + // manage last values of matrices + if (!lastInit) { + viewPrev.set(view); + projectionPrev.set(projection); + viewProjectionPrev.set(viewProjectionPrev); + cleanProjectionPrev.set(cleanProjection); + cleanViewProjectionPrev.set(cleanViewProjection); + } ptr = writeMatrices(ptr); + viewPrev.set(view); + projectionPrev.set(projection); + viewProjectionPrev.set(viewProjection); + cleanProjectionPrev.set(cleanProjection); + cleanViewProjectionPrev.set(cleanViewProjection); - ptr = writeCamera(ptr, camX, camY, camZ, camera); + ptr = writeCamera(ptr, camX, camY, camZ, camera.getLookVector(), camera.getXRot(), camera.getYRot()); + + // last values for camera + if (!lastInit) { + cameraPositionPrev.set(camX, camY, camZ); + cameraLookPrev.set(camera.getLookVector()); + cameraRotPrev.set(camera.getXRot(), camera.getYRot()); + } + ptr = writeCamera(ptr, cameraPositionPrev.x, cameraPositionPrev.y, cameraPositionPrev.z, cameraLookPrev, + cameraRotPrev.x, cameraRotPrev.y); + cameraPositionPrev.set(camX, camY, camZ); + cameraLookPrev.set(camera.getLookVector()); + cameraRotPrev.set(camera.getXRot(), camera.getYRot()); var window = Minecraft.getInstance() .getWindow(); @@ -68,27 +129,69 @@ public class FrameUniforms implements UniformProvider { MemoryUtil.memPutFloat(ptr, Math.max(2.5F, (float) window.getWidth() / 1920.0F * 2.5F)); ptr += 4; + MemoryUtil.memPutFloat(ptr, (float) window.getWidth() / (float) window.getHeight()); + ptr += 4; + + MemoryUtil.memPutFloat(ptr, Minecraft.getInstance().gameRenderer.getDepthFar()); + ptr += 4; + MemoryUtil.memPutInt(ptr, getConstantAmbientLightFlag(context)); ptr += 4; ptr = writeTime(ptr); + ptr = writeCameraIn(ptr); + MemoryUtil.memPutInt(ptr, debugMode); + + lastInit = true; } private long writeMatrices(long ptr) { - MatrixMath.writeUnsafe(viewProjection, ptr); - MatrixMath.writeUnsafe(viewProjection.invert(viewProjectionInverse), ptr + 64); - return ptr + 128; + MatrixMath.writeUnsafe(view, ptr); + MatrixMath.writeUnsafe(view.invert(viewInverse), ptr + 64); + MatrixMath.writeUnsafe(viewPrev, ptr + 64 * 2); + MatrixMath.writeUnsafe(projection, ptr + 64 * 3); + MatrixMath.writeUnsafe(projection.invert(projectionInverse), ptr + 64 * 4); + MatrixMath.writeUnsafe(projectionPrev, ptr + 64 * 5); + MatrixMath.writeUnsafe(viewProjection, ptr + 64 * 6); + MatrixMath.writeUnsafe(viewProjection.invert(viewProjectionInverse), ptr + 64 * 7); + MatrixMath.writeUnsafe(viewProjectionPrev, ptr + 64 * 8); + MatrixMath.writeUnsafe(cleanProjection, ptr + 64 * 9); + MatrixMath.writeUnsafe(cleanProjection.invert(cleanProjectionInverse), ptr + 64 * 10); + MatrixMath.writeUnsafe(cleanProjectionPrev, ptr + 64 * 11); + MatrixMath.writeUnsafe(cleanViewProjection, ptr + 64 * 12); + MatrixMath.writeUnsafe(cleanViewProjection.invert(cleanViewProjectionInverse), ptr + 64 * 13); + MatrixMath.writeUnsafe(cleanViewProjectionPrev, ptr + 64 * 14); + return ptr + 64 * 15; } - private static long writeCamera(long ptr, float camX, float camY, float camZ, Camera camera) { + private void setupCleanMatrices(PoseStack stack, Camera camera, float partialTicks) { + Minecraft mc = Minecraft.getInstance(); + GameRenderer gr = mc.gameRenderer; + GameRendererAccessor gra = (GameRendererAccessor) gr; + + float fov = (float) gra.flywheel$getFov(camera, partialTicks, true); + + cleanProjection.identity(); + + if (gra.flywheel$getZoom() != 1.0F) { + cleanProjection.translate(gra.flywheel$getZoomX(), -gra.flywheel$getZoomY(), 0.0F); + cleanProjection.scale(gra.flywheel$getZoom(), gra.flywheel$getZoom(), 1.0F); + } + + cleanProjection.mul(new Matrix4f().setPerspective(fov * ((float) Math.PI / 180F), (float) mc.getWindow().getWidth() / (float) mc.getWindow().getHeight(), 0.05F, gr.getDepthFar())); + + cleanViewProjection.set(cleanProjection).mul(stack.last().pose()); + } + + private static long writeCamera(long ptr, float camX, float camY, float camZ, Vector3f lookVector, float xRot, + float yRot) { ptr = writeVec3(ptr, camX, camY, camZ); - var lookVector = camera.getLookVector(); ptr = writeVec3(ptr, lookVector.x, lookVector.y, lookVector.z); - ptr = writeVec2(ptr, camera.getXRot(), camera.getYRot()); + ptr = writeVec2(ptr, xRot, yRot); return ptr; } @@ -106,6 +209,45 @@ public class FrameUniforms implements UniformProvider { return ptr + 16; } + private long writeCameraIn(long ptr) { + Camera camera = context.camera(); + if (!camera.isInitialized()) { + MemoryUtil.memPutInt(ptr, 0); + MemoryUtil.memPutInt(ptr + 4, 0); + return ptr + 8; + } + Level level = camera.getEntity().level(); + BlockPos blockPos = camera.getBlockPosition(); + Vec3 cameraPos = camera.getPosition(); + FluidState fState = level.getFluidState(blockPos); + BlockState bState = level.getBlockState(blockPos); + float height = fState.getHeight(level, blockPos); + + if (fState.isEmpty()) { + MemoryUtil.memPutInt(ptr, 0); + } else if (cameraPos.y < blockPos.getY() + height) { + if (fState.is(FluidTags.WATER)) { + MemoryUtil.memPutInt(ptr, 1); + } else if (fState.is(FluidTags.LAVA)) { + MemoryUtil.memPutInt(ptr, 2); + } else { + MemoryUtil.memPutInt(ptr, -1); + } + } + + if (bState.isAir()) { + MemoryUtil.memPutInt(ptr + 4, 0); + } else { + if (bState.is(Blocks.POWDER_SNOW)) { + MemoryUtil.memPutInt(ptr + 4, 0); + } else { + MemoryUtil.memPutInt(ptr + 4, -1); + } + } + + return ptr + 8; + } + private static long writeVec3(long ptr, float camX, float camY, float camZ) { MemoryUtil.memPutFloat(ptr, camX); MemoryUtil.memPutFloat(ptr + 4, camY); diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/uniform/OptionsUniforms.java b/src/main/java/com/jozufozu/flywheel/backend/engine/uniform/OptionsUniforms.java new file mode 100644 index 000000000..207a4b0c9 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/uniform/OptionsUniforms.java @@ -0,0 +1,61 @@ +package com.jozufozu.flywheel.backend.engine.uniform; + +import org.lwjgl.system.MemoryUtil; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.Options; + +public class OptionsUniforms implements UniformProvider { + public static final int SIZE = 4 * 14; + + @Override + public int byteSize() { + return SIZE; + } + + @Override + public void write(long ptr) { + Options options = Minecraft.getInstance().options; + + MemoryUtil.memPutFloat(ptr, options.gamma().get().floatValue()); + ptr += 4; + + MemoryUtil.memPutInt(ptr, options.fov().get()); + ptr += 4; + + MemoryUtil.memPutFloat(ptr, options.screenEffectScale().get().floatValue()); + ptr += 4; + + MemoryUtil.memPutFloat(ptr, options.glintSpeed().get().floatValue()); + ptr += 4; + + MemoryUtil.memPutFloat(ptr, options.glintStrength().get().floatValue()); + ptr += 4; + + MemoryUtil.memPutInt(ptr, options.biomeBlendRadius().get()); + ptr += 4; + + MemoryUtil.memPutInt(ptr, options.ambientOcclusion().get() ? 1 : 0); + ptr += 4; + + MemoryUtil.memPutInt(ptr, options.bobView().get() ? 1 : 0); + ptr += 4; + + MemoryUtil.memPutInt(ptr, options.highContrast().get() ? 1 : 0); + ptr += 4; + + MemoryUtil.memPutFloat(ptr, options.textBackgroundOpacity().get().floatValue()); + ptr += 4; + + MemoryUtil.memPutInt(ptr, options.backgroundForChatOnly().get() ? 1 : 0); + ptr += 4; + + MemoryUtil.memPutFloat(ptr, options.darknessEffectScale().get().floatValue()); + ptr += 4; + + MemoryUtil.memPutFloat(ptr, options.damageTiltStrength().get().floatValue()); + ptr += 4; + + MemoryUtil.memPutInt(ptr, options.hideLightningFlash().get() ? 1 : 0); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/uniform/Uniforms.java b/src/main/java/com/jozufozu/flywheel/backend/engine/uniform/Uniforms.java index a6836d40b..163fb7ba7 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/uniform/Uniforms.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/uniform/Uniforms.java @@ -5,11 +5,14 @@ import com.jozufozu.flywheel.api.event.RenderContext; import com.jozufozu.flywheel.backend.gl.GlStateTracker; import com.jozufozu.flywheel.config.DebugMode; +import org.jetbrains.annotations.Nullable; + public class Uniforms { public static boolean frustumPaused = false; public static boolean frustumCapture = false; - private static UniformBuffer frame; - private static UniformBuffer fog; + private static @Nullable UniformBuffer frame; + private static @Nullable UniformBuffer fog; + private static @Nullable UniformBuffer options; public static UniformBuffer frame() { if (frame == null) { @@ -25,9 +28,17 @@ public class Uniforms { return fog; } + public static UniformBuffer options() { + if (options == null) { + options = new UniformBuffer<>(2, new OptionsUniforms()); + } + return options; + } + public static void bindForDraw() { bindFrame(); bindFog(); + bindOptions(); } public static void bindFrame() { @@ -42,6 +53,12 @@ public class Uniforms { } } + public static void bindOptions() { + if (options != null) { + options.bind(); + } + } + public static void onFogUpdate() { try (var restoreState = GlStateTracker.getRestoreState()) { fog().update(); @@ -52,6 +69,8 @@ public class Uniforms { var ubo = frame(); ubo.provider.setContext(ctx); ubo.update(); + + options(); } public static void setDebugMode(DebugMode mode) { @@ -68,5 +87,10 @@ public class Uniforms { fog.delete(); fog = null; } + + if (options != null) { + options.delete(); + options = null; + } } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/mixin/GameRendererAccessor.java b/src/main/java/com/jozufozu/flywheel/backend/mixin/GameRendererAccessor.java new file mode 100644 index 000000000..cf92578fb --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/mixin/GameRendererAccessor.java @@ -0,0 +1,23 @@ +package com.jozufozu.flywheel.backend.mixin; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.gen.Invoker; + +import net.minecraft.client.Camera; +import net.minecraft.client.renderer.GameRenderer; + +@Mixin(GameRenderer.class) +public interface GameRendererAccessor { + @Invoker("getFov") + double flywheel$getFov(Camera pActiveRenderInfo, float pPartialTicks, boolean pUseFOVSetting); + + @Accessor("zoom") + float flywheel$getZoom(); + + @Accessor("zoomX") + float flywheel$getZoomX(); + + @Accessor("zoomY") + float flywheel$getZoomY(); +} diff --git a/src/main/resources/assets/flywheel/flywheel/internal/common_api_impl.frag b/src/main/resources/assets/flywheel/flywheel/internal/common_api_impl.frag index b63c8cead..dc8334916 100644 --- a/src/main/resources/assets/flywheel/flywheel/internal/common_api_impl.frag +++ b/src/main/resources/assets/flywheel/flywheel/internal/common_api_impl.frag @@ -1,6 +1,5 @@ #include "flywheel:internal/material.glsl" -#include "flywheel:internal/uniforms/frame.glsl" -#include "flywheel:internal/uniforms/fog.glsl" +#include "flywheel:internal/uniforms/uniforms.glsl" in vec4 flw_vertexPos; in vec4 flw_vertexColor; diff --git a/src/main/resources/assets/flywheel/flywheel/internal/common_api_impl.vert b/src/main/resources/assets/flywheel/flywheel/internal/common_api_impl.vert index 2cddb2e42..18128f125 100644 --- a/src/main/resources/assets/flywheel/flywheel/internal/common_api_impl.vert +++ b/src/main/resources/assets/flywheel/flywheel/internal/common_api_impl.vert @@ -1,6 +1,5 @@ #include "flywheel:internal/material.glsl" -#include "flywheel:internal/uniforms/frame.glsl" -#include "flywheel:internal/uniforms/fog.glsl" +#include "flywheel:internal/uniforms/uniforms.glsl" // TODO: can we combine some of these internally to use fewer in/out slots? out vec4 flw_vertexPos; diff --git a/src/main/resources/assets/flywheel/flywheel/internal/uniforms/frame.glsl b/src/main/resources/assets/flywheel/flywheel/internal/uniforms/frame.glsl index dcc401409..add2e2764 100644 --- a/src/main/resources/assets/flywheel/flywheel/internal/uniforms/frame.glsl +++ b/src/main/resources/assets/flywheel/flywheel/internal/uniforms/frame.glsl @@ -12,15 +12,34 @@ struct FrustumPlanes { layout(std140) uniform _FlwFrameUniforms { FrustumPlanes flw_frustumPlanes; + mat4 flw_view; + mat4 flw_viewInverse; + mat4 flw_viewPrev; + mat4 flw_projection; + mat4 flw_projectionInverse; + mat4 flw_projectionPrev; mat4 flw_viewProjection; mat4 flw_viewProjectionInverse; + mat4 flw_viewProjectionPrev; + + mat4 flw_cleanProjection; + mat4 flw_cleanProjectionInverse; + mat4 flw_cleanProjectionPrev; + mat4 flw_cleanViewProjection; + mat4 flw_cleanViewProjectionInverse; + mat4 flw_cleanViewProjectionPrev; vec4 _flw_cameraPos; vec4 _flw_cameraLook; vec2 flw_cameraRot; + vec4 _flw_cameraPosPrev; + vec4 _flw_cameraLookPrev; + vec2 flw_cameraRotPrev; vec2 flw_viewportSize; float flw_defaultLineWidth; + float flw_aspectRatio; + float flw_viewDistance; uint flw_constantAmbientLight; @@ -30,8 +49,15 @@ layout(std140) uniform _FlwFrameUniforms { float flw_renderTicks; float flw_renderSeconds; + /** Contains 1 for water, 2 for lava, max-value for any other fluid, 0 for no fluid. */ + uint flw_cameraInFluid; + /** Contains 1 for powder snow, max-value for any other block, 0 for no block. */ + uint flw_cameraInBlock; + uint _flw_debugMode; }; #define flw_cameraPos _flw_cameraPos.xyz #define flw_cameraLook _flw_cameraLook.xyz +#define flw_cameraPosPrev _flw_cameraPosPrev.xyz +#define flw_cameraLookPrev _flw_cameraLookPrev.xyz diff --git a/src/main/resources/assets/flywheel/flywheel/internal/uniforms/options.glsl b/src/main/resources/assets/flywheel/flywheel/internal/uniforms/options.glsl new file mode 100644 index 000000000..7ea97b33a --- /dev/null +++ b/src/main/resources/assets/flywheel/flywheel/internal/uniforms/options.glsl @@ -0,0 +1,19 @@ +// options.glsl - Houses uniforms for many of the game's settings, focusing on video and accessibility settings. + +layout(std140) uniform _FlwOptionsUniforms { + float flw_brightnessOption; + uint flw_fovOption; + float flw_distortionOption; + float flw_glintSpeedOption; + float flw_glintStrengthOption; + uint flw_biomeBlendOption; + uint flw_smoothLightingOption; + uint flw_viewBobbingOption; + + uint flw_highContrastOption; + float flw_textBackgroundOpacityOption; + uint flw_textBackgroundForChatOnlyOption; + float flw_darknessPulsingOption; + float flw_damageTiltOption; + uint hideLightningFlashesOption; +}; diff --git a/src/main/resources/assets/flywheel/flywheel/internal/uniforms/uniforms.glsl b/src/main/resources/assets/flywheel/flywheel/internal/uniforms/uniforms.glsl new file mode 100644 index 000000000..0cd465a5b --- /dev/null +++ b/src/main/resources/assets/flywheel/flywheel/internal/uniforms/uniforms.glsl @@ -0,0 +1,5 @@ +// uniforms.glsl - Includes common uniforms. + +#include "flywheel:internal/uniforms/frame.glsl" +#include "flywheel:internal/uniforms/fog.glsl" +#include "flywheel:internal/uniforms/options.glsl" diff --git a/src/main/resources/flywheel.backend.mixins.json b/src/main/resources/flywheel.backend.mixins.json index c5948b498..0a9b436df 100644 --- a/src/main/resources/flywheel.backend.mixins.json +++ b/src/main/resources/flywheel.backend.mixins.json @@ -5,6 +5,7 @@ "compatibilityLevel": "JAVA_17", "refmap": "flywheel.refmap.json", "client": [ + "GameRendererAccessor", "GlStateManagerMixin", "LightTextureAccessor", "OverlayTextureAccessor",