Fix fancy portal rendering

This commit is contained in:
Sollace 2024-11-19 00:51:14 +00:00
parent 3603819860
commit 6215252b57
No known key found for this signature in database
GPG key ID: E52FACE7B5C773DB

View file

@ -6,7 +6,7 @@ import java.util.concurrent.TimeUnit;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.joml.Matrix4f; import org.joml.Matrix4f;
import org.joml.Matrix4fStack; import org.joml.Quaternionf;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader; import com.google.common.cache.CacheLoader;
@ -24,13 +24,11 @@ import com.minelittlepony.unicopia.mixin.client.MixinMinecraftClient;
import com.mojang.blaze3d.platform.GlConst; import com.mojang.blaze3d.platform.GlConst;
import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.systems.VertexSorter;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gl.SimpleFramebuffer; import net.minecraft.client.gl.SimpleFramebuffer;
import net.minecraft.client.option.Perspective;
import net.minecraft.client.render.BackgroundRenderer; import net.minecraft.client.render.BackgroundRenderer;
import net.minecraft.client.render.BufferBuilder; import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.BufferRenderer;
import net.minecraft.client.render.Camera; import net.minecraft.client.render.Camera;
import net.minecraft.client.render.Frustum; import net.minecraft.client.render.Frustum;
import net.minecraft.client.render.Tessellator; import net.minecraft.client.render.Tessellator;
@ -49,7 +47,7 @@ import net.minecraft.util.math.Vec3d;
class PortalFrameBuffer implements AutoCloseable { class PortalFrameBuffer implements AutoCloseable {
private static final LoadingCache<UUID, PortalFrameBuffer> CACHE = CacheBuilder.newBuilder() private static final LoadingCache<UUID, PortalFrameBuffer> CACHE = CacheBuilder.newBuilder()
.expireAfterAccess(10, TimeUnit.SECONDS) .expireAfterAccess(1, TimeUnit.HOURS)
.<UUID, PortalFrameBuffer>removalListener(n -> n.getValue().close()) .<UUID, PortalFrameBuffer>removalListener(n -> n.getValue().close())
.build(CacheLoader.from(PortalFrameBuffer::new)); .build(CacheLoader.from(PortalFrameBuffer::new));
@ -67,12 +65,12 @@ class PortalFrameBuffer implements AutoCloseable {
@Nullable @Nullable
private SimpleFramebuffer framebuffer; private SimpleFramebuffer framebuffer;
@Nullable @Nullable
private SimpleFramebuffer backgroundBuffer;
@Nullable
private WorldRenderer renderer; private WorldRenderer renderer;
@Nullable @Nullable
private ClientWorld world; private ClientWorld world;
private final Camera camera = new Camera();
private boolean closed; private boolean closed;
private final MinecraftClient client = MinecraftClient.getInstance(); private final MinecraftClient client = MinecraftClient.getInstance();
@ -87,11 +85,12 @@ class PortalFrameBuffer implements AutoCloseable {
public void draw(MatrixStack matrices, VertexConsumerProvider vertices) { public void draw(MatrixStack matrices, VertexConsumerProvider vertices) {
matrices.translate(0, -0.001, 0); matrices.translate(0, -0.001, 0);
RenderSystem.assertOnRenderThread();
GlStateManager._colorMask(true, true, true, false);
GlStateManager._enableDepthTest();
GlStateManager._disableCull();
if (!(closed || framebuffer == null)) { if (!(closed || framebuffer == null)) {
RenderSystem.assertOnRenderThread();
GlStateManager._colorMask(true, true, true, false);
GlStateManager._enableDepthTest();
GlStateManager._disableCull();
Tessellator tessellator = RenderSystem.renderThreadTesselator(); Tessellator tessellator = RenderSystem.renderThreadTesselator();
float uScale = (float)framebuffer.viewportWidth / (float)framebuffer.textureWidth; float uScale = (float)framebuffer.viewportWidth / (float)framebuffer.textureWidth;
float vScale = (float)framebuffer.viewportHeight / (float)framebuffer.textureHeight; float vScale = (float)framebuffer.viewportHeight / (float)framebuffer.textureHeight;
@ -102,16 +101,17 @@ class PortalFrameBuffer implements AutoCloseable {
RenderSystem.setTextureMatrix(SphereModel.DISK.getTextureMatrix()); RenderSystem.setTextureMatrix(SphereModel.DISK.getTextureMatrix());
SphereModel.DISK.render(matrices, buffer, 1, 2F, Colors.WHITE); SphereModel.DISK.render(matrices, buffer, 1, 2F, Colors.WHITE);
buffer.end(); BufferRenderer.drawWithGlobalProgram(buffer.end());
client.getTextureManager().bindTexture(PlayerScreenHandler.BLOCK_ATLAS_TEXTURE); client.getTextureManager().bindTexture(PlayerScreenHandler.BLOCK_ATLAS_TEXTURE);
GlStateManager._enableCull();
GlStateManager._colorMask(true, true, true, true);
GlStateManager._depthMask(true);
} else { } else {
Vec3d skyColor = client.world.getSkyColor(client.gameRenderer.getCamera().getPos(), client.getRenderTickCounter().getTickDelta(false)); Vec3d skyColor = client.world.getSkyColor(client.gameRenderer.getCamera().getPos(), client.getRenderTickCounter().getTickDelta(false));
SphereModel.DISK.render(matrices, vertices.getBuffer(RenderLayers.getMagicShield()), 0, 0, 2, Color.argbToHex(1, (float)skyColor.x, (float)skyColor.y, (float)skyColor.z)); SphereModel.DISK.render(matrices, vertices.getBuffer(RenderLayers.getMagicShield()), 0, 0, 2, Color.argbToHex(1, (float)skyColor.x, (float)skyColor.y, (float)skyColor.z));
} }
GlStateManager._enableCull();
GlStateManager._colorMask(true, true, true, true);
GlStateManager._depthMask(true);
} }
public void build(PortalSpell spell, Caster<?> caster, EntityReference.EntityValues<Entity> target) { public void build(PortalSpell spell, Caster<?> caster, EntityReference.EntityValues<Entity> target) {
@ -152,25 +152,19 @@ class PortalFrameBuffer implements AutoCloseable {
return; return;
} }
var fov = client.options.getFov();
int originalFov = fov.getValue();
fov.setValue(110);
Camera camera = client.gameRenderer.getCamera(); Camera camera = client.gameRenderer.getCamera();
Entity cameraEntity = UEntities.CAST_SPELL.create(caster.asWorld()); Entity cameraEntity = UEntities.CAST_SPELL.create(caster.asWorld());
Vec3d offset = new Vec3d(0, 0, -0.1F).rotateY(-spell.getTargetYaw() * MathHelper.RADIANS_PER_DEGREE); Vec3d offset = new Vec3d(0, 1, -0.1F).rotateY(-spell.getTargetYaw() * MathHelper.RADIANS_PER_DEGREE);
float yaw = spell.getTargetYaw() + camera.getYaw() - spell.getYaw() + 180; float yaw = spell.getTargetYaw() + camera.getYaw() - spell.getYaw();
float pitch = spell.getTargetPitch() + (camera.getPitch() - spell.getPitch()) * 1.65F; float pitch = spell.getTargetPitch();//MathHelper.clamp(spell.getTargetPitch() + (camera.getPitch() - spell.getPitch()) * 0.65F, -90, 90) + 90;
cameraEntity.setPosition(target.pos().add(offset)); cameraEntity.setPosition(target.pos().add(offset));
cameraEntity.setPitch(90 + pitch); cameraEntity.setPitch(pitch % 180);
cameraEntity.setYaw(yaw); cameraEntity.setYaw((yaw + 180) % 360);
drawWorld(cameraEntity, 400, 400); drawWorld(cameraEntity, 400, 400);
fov.setValue(originalFov);
} finally { } finally {
recursionCount--; recursionCount--;
} }
@ -178,26 +172,16 @@ class PortalFrameBuffer implements AutoCloseable {
} }
private void drawWorld(Entity cameraEntity, int width, int height) { private void drawWorld(Entity cameraEntity, int width, int height) {
Entity oldCameraEntity = client.cameraEntity;
Window window = client.getWindow(); Window window = client.getWindow();
int i = window.getFramebufferWidth(); int globalFramebufferWidth = window.getFramebufferWidth();
int j = window.getFramebufferHeight(); int globalFramebufferHeight = window.getFramebufferHeight();
width = i; width = globalFramebufferWidth;
height = j; height = globalFramebufferHeight;
Perspective perspective = client.options.getPerspective();
Matrix4fStack view = RenderSystem.getModelViewStack();
Matrix4f proj = RenderSystem.getProjectionMatrix(); Matrix4f proj = RenderSystem.getProjectionMatrix();
int fbo = client.getFramebuffer().fbo;
Camera camera = client.gameRenderer.getCamera();
WorldRenderer globalRenderer = client.worldRenderer;
try { try {
client.cameraEntity = cameraEntity;
client.getFramebuffer().endWrite(); client.getFramebuffer().endWrite();
if (framebuffer == null) { if (framebuffer == null) {
@ -206,15 +190,8 @@ class PortalFrameBuffer implements AutoCloseable {
framebuffer.clear(MinecraftClient.IS_SYSTEM_MAC); framebuffer.clear(MinecraftClient.IS_SYSTEM_MAC);
} }
view.pushMatrix();
view.identity();
RenderSystem.applyModelViewMatrix();
window.setFramebufferWidth(width); window.setFramebufferWidth(width);
window.setFramebufferHeight(height); window.setFramebufferHeight(height);
client.getFramebuffer().fbo = framebuffer.fbo;
client.options.setPerspective(Perspective.FIRST_PERSON);
RenderSystem.clear(GlConst.GL_DEPTH_BUFFER_BIT | GlConst.GL_COLOR_BUFFER_BIT, MinecraftClient.IS_SYSTEM_MAC); RenderSystem.clear(GlConst.GL_DEPTH_BUFFER_BIT | GlConst.GL_COLOR_BUFFER_BIT, MinecraftClient.IS_SYSTEM_MAC);
framebuffer.beginWrite(true); framebuffer.beginWrite(true);
@ -224,17 +201,40 @@ class PortalFrameBuffer implements AutoCloseable {
if (renderer == null) { if (renderer == null) {
renderer = new WorldRenderer(client, client.getEntityRenderDispatcher(), client.getBlockEntityRenderDispatcher(), client.getBufferBuilders()); renderer = new WorldRenderer(client, client.getEntityRenderDispatcher(), client.getBlockEntityRenderDispatcher(), client.getBufferBuilders());
} }
if (client.world != world) { if (cameraEntity.getWorld() != world) {
world = client.world; world = (ClientWorld)cameraEntity.getWorld();
renderer.setWorld(client.world); renderer.setWorld(world);
} }
((MixinMinecraftClient)client).setWorldRenderer(renderer); //((MixinMinecraftClient)client).setWorldRenderer(renderer);
renderer.scheduleBlockRenders((int)cameraEntity.getX() / 16, (int)cameraEntity.getY() / 16, (int)cameraEntity.getZ() / 16); var tickCounter = client.getRenderTickCounter();
client.gameRenderer.setRenderHand(false); camera.update(world, cameraEntity, false, false, 1);
client.gameRenderer.renderWorld(client.getRenderTickCounter()); double fov = 110;
Matrix4f projectionMatrix = client.gameRenderer.getBasicProjectionMatrix(fov);
Matrix4f cameraTransform = new Matrix4f().rotation(camera.getRotation().conjugate(new Quaternionf()));
client.gameRenderer.loadProjectionMatrix(projectionMatrix);
/*renderer.scheduleBlockRenders(
ChunkSectionPos.getSectionCoord((int)cameraEntity.getX()),
ChunkSectionPos.getSectionCoord((int)cameraEntity.getY()),
ChunkSectionPos.getSectionCoord((int)cameraEntity.getZ())
);*/
renderer.setupFrustum(
camera.getPos(),
cameraTransform,
client.gameRenderer.getBasicProjectionMatrix(Math.max(fov, this.client.options.getFov().getValue().intValue()))
);
try {
renderer.render(tickCounter, false, camera, client.gameRenderer,
client.gameRenderer.getLightmapTextureManager(),
cameraTransform,
projectionMatrix
);
} catch (Throwable t) {
close();
}
// Strip transparency // Strip transparency
RenderSystem.colorMask(false, false, false, true); RenderSystem.colorMask(false, false, false, true);
@ -244,48 +244,27 @@ class PortalFrameBuffer implements AutoCloseable {
framebuffer.endWrite(); framebuffer.endWrite();
} finally { } finally {
((MixinMinecraftClient)client).setWorldRenderer(globalRenderer);
client.getFramebuffer().fbo = fbo;
client.getFramebuffer().beginWrite(true); client.getFramebuffer().beginWrite(true);
client.gameRenderer.loadProjectionMatrix(proj);
view.popMatrix(); window.setFramebufferWidth(globalFramebufferWidth);
RenderSystem.applyModelViewMatrix(); window.setFramebufferHeight(globalFramebufferHeight);
RenderSystem.setProjectionMatrix(proj, VertexSorter.BY_Z);
window.setFramebufferWidth(i);
window.setFramebufferHeight(j);
client.options.setPerspective(perspective);
client.cameraEntity = oldCameraEntity;
if (recursionCount <= 1) {
client.gameRenderer.setRenderHand(true);
camera.update(client.world,
client.getCameraEntity() == null ? client.player : client.getCameraEntity(),
perspective.isFirstPerson(),
perspective.isFrontView(),
1
);
}
} }
} }
@Override @Override
public void close() { public void close() {
closed = true; synchronized (client) {
if (framebuffer != null) { closed = true;
SimpleFramebuffer fb = framebuffer; if (framebuffer != null) {
framebuffer = null; SimpleFramebuffer fb = framebuffer;
fb.delete(); framebuffer = null;
} fb.delete();
if (backgroundBuffer != null) { }
SimpleFramebuffer fb = backgroundBuffer; if (renderer != null) {
backgroundBuffer = null; renderer.getChunkBuilder().stop();
fb.delete(); renderer.close();
} }
if (renderer != null) {
renderer.close();
} }
} }
} }