mirror of
https://github.com/Sollace/Unicopia.git
synced 2025-02-17 10:24:23 +01:00
Fix portal rendering issues :D
This commit is contained in:
parent
a19637a8e4
commit
1a17ff7dd0
3 changed files with 326 additions and 269 deletions
|
@ -0,0 +1,287 @@
|
||||||
|
package com.minelittlepony.unicopia.client.render.spell;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.joml.Matrix3f;
|
||||||
|
import org.joml.Matrix4f;
|
||||||
|
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
|
import com.google.common.cache.LoadingCache;
|
||||||
|
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||||
|
import com.minelittlepony.unicopia.ability.magic.spell.effect.PortalSpell;
|
||||||
|
import com.minelittlepony.unicopia.client.render.RenderLayers;
|
||||||
|
import com.minelittlepony.unicopia.client.render.model.SphereModel;
|
||||||
|
import com.minelittlepony.unicopia.client.render.model.TexturedSphereModel;
|
||||||
|
import com.minelittlepony.unicopia.entity.EntityReference;
|
||||||
|
import com.minelittlepony.unicopia.entity.mob.UEntities;
|
||||||
|
import com.minelittlepony.unicopia.mixin.client.MixinMinecraftClient;
|
||||||
|
import com.mojang.blaze3d.platform.GlConst;
|
||||||
|
import com.mojang.blaze3d.platform.GlStateManager;
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.mojang.blaze3d.systems.VertexSorter;
|
||||||
|
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.gl.SimpleFramebuffer;
|
||||||
|
import net.minecraft.client.option.Perspective;
|
||||||
|
import net.minecraft.client.render.BackgroundRenderer;
|
||||||
|
import net.minecraft.client.render.BufferBuilder;
|
||||||
|
import net.minecraft.client.render.Camera;
|
||||||
|
import net.minecraft.client.render.Frustum;
|
||||||
|
import net.minecraft.client.render.GameRenderer;
|
||||||
|
import net.minecraft.client.render.Tessellator;
|
||||||
|
import net.minecraft.client.render.VertexConsumerProvider;
|
||||||
|
import net.minecraft.client.render.VertexFormat;
|
||||||
|
import net.minecraft.client.render.VertexFormats;
|
||||||
|
import net.minecraft.client.render.WorldRenderer;
|
||||||
|
import net.minecraft.client.util.Window;
|
||||||
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
|
import net.minecraft.client.world.ClientWorld;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.screen.PlayerScreenHandler;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
|
||||||
|
class PortalFrameBuffer implements AutoCloseable {
|
||||||
|
private static final LoadingCache<UUID, PortalFrameBuffer> CACHE = CacheBuilder.newBuilder()
|
||||||
|
.expireAfterAccess(10, TimeUnit.SECONDS)
|
||||||
|
.<UUID, PortalFrameBuffer>removalListener(n -> n.getValue().close())
|
||||||
|
.build(CacheLoader.from(PortalFrameBuffer::new));
|
||||||
|
|
||||||
|
private static int recursionCount;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static PortalFrameBuffer unpool(UUID id) {
|
||||||
|
try {
|
||||||
|
return CACHE.get(id);
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private SimpleFramebuffer framebuffer;
|
||||||
|
@Nullable
|
||||||
|
private SimpleFramebuffer backgroundBuffer;
|
||||||
|
@Nullable
|
||||||
|
private WorldRenderer renderer;
|
||||||
|
@Nullable
|
||||||
|
private ClientWorld world;
|
||||||
|
|
||||||
|
private boolean closed;
|
||||||
|
|
||||||
|
private final MinecraftClient client = MinecraftClient.getInstance();
|
||||||
|
|
||||||
|
private boolean pendingDraw;
|
||||||
|
|
||||||
|
private final UUID id;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private Frustum frustum;
|
||||||
|
|
||||||
|
PortalFrameBuffer(UUID id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void draw(MatrixStack matrices, VertexConsumerProvider vertices) {
|
||||||
|
matrices.translate(0, -0.001, 0);
|
||||||
|
|
||||||
|
if (!(closed || framebuffer == null)) {
|
||||||
|
RenderSystem.assertOnRenderThread();
|
||||||
|
GlStateManager._colorMask(true, true, true, false);
|
||||||
|
GlStateManager._enableDepthTest();
|
||||||
|
GlStateManager._disableCull();
|
||||||
|
Tessellator tessellator = RenderSystem.renderThreadTesselator();
|
||||||
|
BufferBuilder buffer = tessellator.getBuffer();
|
||||||
|
float uScale = (float)framebuffer.viewportWidth / (float)framebuffer.textureWidth;
|
||||||
|
float vScale = (float)framebuffer.viewportHeight / (float)framebuffer.textureHeight;
|
||||||
|
RenderSystem.setShader(GameRenderer::getPositionTexColorProgram);
|
||||||
|
RenderSystem._setShaderTexture(0, framebuffer.getColorAttachment());
|
||||||
|
buffer.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR);
|
||||||
|
TexturedSphereModel.DISK.render(matrices, buffer, 2F, 1, 1, 1, 1, uScale, vScale);
|
||||||
|
tessellator.draw();
|
||||||
|
|
||||||
|
client.getTextureManager().bindTexture(PlayerScreenHandler.BLOCK_ATLAS_TEXTURE);
|
||||||
|
GlStateManager._enableCull();
|
||||||
|
GlStateManager._colorMask(true, true, true, true);
|
||||||
|
GlStateManager._depthMask(true);
|
||||||
|
} else {
|
||||||
|
Vec3d skyColor = client.world.getSkyColor(client.gameRenderer.getCamera().getPos(), client.getTickDelta());
|
||||||
|
SphereModel.DISK.render(matrices, vertices.getBuffer(RenderLayers.getMagicShield()), 0, 0, 2, (float)skyColor.x, (float)skyColor.y, (float)skyColor.z, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void build(PortalSpell spell, Caster<?> caster, EntityReference.EntityValues<Entity> target) {
|
||||||
|
|
||||||
|
if (framebuffer != null && System.currentTimeMillis() % 100 != 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pendingDraw && recursionCount > 0) {
|
||||||
|
innerBuild(spell, caster, target);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pendingDraw) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pendingDraw = true;
|
||||||
|
if (recursionCount > 0) {
|
||||||
|
innerBuild(spell, caster, target);
|
||||||
|
} else {
|
||||||
|
((MixinMinecraftClient)client).getRenderTaskQueue().add(() -> innerBuild(spell, caster, target));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void innerBuild(PortalSpell spell, Caster<?> caster, EntityReference.EntityValues<Entity> target) {
|
||||||
|
synchronized (client) {
|
||||||
|
pendingDraw = false;
|
||||||
|
|
||||||
|
if (recursionCount > 2) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
recursionCount++;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (closed || client.interactionManager == null) {
|
||||||
|
close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var fov = client.options.getFov();
|
||||||
|
int originalFov = fov.getValue();
|
||||||
|
fov.setValue(110);
|
||||||
|
|
||||||
|
Entity cameraEntity = UEntities.CAST_SPELL.create(caster.asWorld());
|
||||||
|
cameraEntity.setPosition(target.pos());
|
||||||
|
cameraEntity.setPitch(spell.getTargetPitch());
|
||||||
|
cameraEntity.setYaw(spell.getTargetYaw() + 180);
|
||||||
|
|
||||||
|
drawWorld(cameraEntity, 400, 400);
|
||||||
|
|
||||||
|
fov.setValue(originalFov);
|
||||||
|
} finally {
|
||||||
|
recursionCount--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drawWorld(Entity cameraEntity, int width, int height) {
|
||||||
|
Entity oldCameraEntity = client.cameraEntity;
|
||||||
|
Window window = client.getWindow();
|
||||||
|
|
||||||
|
int i = window.getFramebufferWidth();
|
||||||
|
int j = window.getFramebufferHeight();
|
||||||
|
|
||||||
|
width = i;
|
||||||
|
height = j;
|
||||||
|
|
||||||
|
Perspective perspective = client.options.getPerspective();
|
||||||
|
MatrixStack view = RenderSystem.getModelViewStack();
|
||||||
|
|
||||||
|
Matrix4f proj = RenderSystem.getProjectionMatrix();
|
||||||
|
Matrix3f invView = RenderSystem.getInverseViewRotationMatrix();
|
||||||
|
|
||||||
|
int fbo = client.getFramebuffer().fbo;
|
||||||
|
Camera camera = client.gameRenderer.getCamera();
|
||||||
|
|
||||||
|
WorldRenderer globalRenderer = client.worldRenderer;
|
||||||
|
try {
|
||||||
|
client.cameraEntity = cameraEntity;
|
||||||
|
client.getFramebuffer().endWrite();
|
||||||
|
|
||||||
|
if (framebuffer == null) {
|
||||||
|
framebuffer = new SimpleFramebuffer(width, height, true, MinecraftClient.IS_SYSTEM_MAC);
|
||||||
|
framebuffer.setClearColor(0, 0, 0, 0);
|
||||||
|
framebuffer.clear(MinecraftClient.IS_SYSTEM_MAC);
|
||||||
|
}
|
||||||
|
|
||||||
|
view.push();
|
||||||
|
view.loadIdentity();
|
||||||
|
RenderSystem.applyModelViewMatrix();
|
||||||
|
|
||||||
|
window.setFramebufferWidth(width);
|
||||||
|
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);
|
||||||
|
framebuffer.beginWrite(true);
|
||||||
|
BackgroundRenderer.clearFog();
|
||||||
|
RenderSystem.enableCull();
|
||||||
|
|
||||||
|
if (renderer == null) {
|
||||||
|
renderer = new WorldRenderer(client, client.getEntityRenderDispatcher(), client.getBlockEntityRenderDispatcher(), client.getBufferBuilders());
|
||||||
|
}
|
||||||
|
if (client.world != world) {
|
||||||
|
world = client.world;
|
||||||
|
renderer.setWorld(client.world);
|
||||||
|
}
|
||||||
|
((MixinMinecraftClient)client).setWorldRenderer(renderer);
|
||||||
|
|
||||||
|
renderer.scheduleBlockRenders((int)cameraEntity.getX() / 16, (int)cameraEntity.getY() / 16, (int)cameraEntity.getZ() / 16);
|
||||||
|
|
||||||
|
client.gameRenderer.setRenderHand(false);
|
||||||
|
MatrixStack matrices = new MatrixStack();
|
||||||
|
|
||||||
|
matrices.scale((float)width / height, 1, 1);
|
||||||
|
|
||||||
|
client.gameRenderer.renderWorld(1, 0, matrices);
|
||||||
|
|
||||||
|
// Strip transparency
|
||||||
|
RenderSystem.colorMask(false, false, false, true);
|
||||||
|
RenderSystem.clearColor(1, 1, 1, 1);
|
||||||
|
RenderSystem.clear(GlConst.GL_COLOR_BUFFER_BIT, MinecraftClient.IS_SYSTEM_MAC);
|
||||||
|
RenderSystem.colorMask(true, true, true, true);
|
||||||
|
|
||||||
|
framebuffer.endWrite();
|
||||||
|
} finally {
|
||||||
|
((MixinMinecraftClient)client).setWorldRenderer(globalRenderer);
|
||||||
|
|
||||||
|
client.getFramebuffer().fbo = fbo;
|
||||||
|
client.getFramebuffer().beginWrite(true);
|
||||||
|
|
||||||
|
view.pop();
|
||||||
|
RenderSystem.applyModelViewMatrix();
|
||||||
|
RenderSystem.setProjectionMatrix(proj, VertexSorter.BY_Z);
|
||||||
|
RenderSystem.setInverseViewRotationMatrix(invView);
|
||||||
|
|
||||||
|
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
|
||||||
|
public void close() {
|
||||||
|
closed = true;
|
||||||
|
if (framebuffer != null) {
|
||||||
|
SimpleFramebuffer fb = framebuffer;
|
||||||
|
framebuffer = null;
|
||||||
|
fb.delete();
|
||||||
|
}
|
||||||
|
if (backgroundBuffer != null) {
|
||||||
|
SimpleFramebuffer fb = backgroundBuffer;
|
||||||
|
backgroundBuffer = null;
|
||||||
|
fb.delete();
|
||||||
|
}
|
||||||
|
if (renderer != null) {
|
||||||
|
renderer.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,60 +1,21 @@
|
||||||
package com.minelittlepony.unicopia.client.render.spell;
|
package com.minelittlepony.unicopia.client.render.spell;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.joml.Matrix3f;
|
|
||||||
import org.joml.Matrix4f;
|
|
||||||
|
|
||||||
import com.google.common.cache.CacheBuilder;
|
|
||||||
import com.google.common.cache.CacheLoader;
|
|
||||||
import com.google.common.cache.LoadingCache;
|
|
||||||
import com.minelittlepony.common.util.Color;
|
|
||||||
import com.minelittlepony.unicopia.ability.magic.Caster;
|
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.effect.PortalSpell;
|
import com.minelittlepony.unicopia.ability.magic.spell.effect.PortalSpell;
|
||||||
import com.minelittlepony.unicopia.client.render.RenderLayers;
|
import com.minelittlepony.unicopia.client.render.RenderLayers;
|
||||||
import com.minelittlepony.unicopia.client.render.model.SphereModel;
|
import com.minelittlepony.unicopia.client.render.model.SphereModel;
|
||||||
import com.minelittlepony.unicopia.client.render.model.TexturedSphereModel;
|
|
||||||
import com.minelittlepony.unicopia.entity.EntityReference;
|
import com.minelittlepony.unicopia.entity.EntityReference;
|
||||||
import com.minelittlepony.unicopia.entity.mob.UEntities;
|
|
||||||
import com.minelittlepony.unicopia.mixin.client.MixinMinecraftClient;
|
|
||||||
import com.mojang.blaze3d.platform.GlConst;
|
|
||||||
import com.mojang.blaze3d.platform.GlStateManager;
|
|
||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
|
||||||
import com.mojang.blaze3d.systems.VertexSorter;
|
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.gl.SimpleFramebuffer;
|
import net.minecraft.client.render.Frustum;
|
||||||
import net.minecraft.client.option.Perspective;
|
|
||||||
import net.minecraft.client.render.BackgroundRenderer;
|
|
||||||
import net.minecraft.client.render.BufferBuilder;
|
|
||||||
import net.minecraft.client.render.Camera;
|
|
||||||
import net.minecraft.client.render.GameRenderer;
|
|
||||||
import net.minecraft.client.render.Tessellator;
|
|
||||||
import net.minecraft.client.render.VertexConsumer;
|
import net.minecraft.client.render.VertexConsumer;
|
||||||
import net.minecraft.client.render.VertexConsumerProvider;
|
import net.minecraft.client.render.VertexConsumerProvider;
|
||||||
import net.minecraft.client.render.VertexFormat;
|
|
||||||
import net.minecraft.client.render.VertexFormats;
|
|
||||||
import net.minecraft.client.util.Window;
|
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
import net.minecraft.entity.Entity;
|
|
||||||
import net.minecraft.screen.PlayerScreenHandler;
|
|
||||||
import net.minecraft.util.math.MathHelper;
|
|
||||||
import net.minecraft.util.math.RotationAxis;
|
import net.minecraft.util.math.RotationAxis;
|
||||||
import net.minecraft.util.math.Vec3d;
|
|
||||||
|
|
||||||
public class PortalSpellRenderer extends SpellRenderer<PortalSpell> {
|
public class PortalSpellRenderer extends SpellRenderer<PortalSpell> {
|
||||||
static boolean FANCY_PORTAlS = false;
|
static boolean FANCY_PORTAlS = true;
|
||||||
|
|
||||||
private static final LoadingCache<UUID, PortalFrameBuffer> FRAME_BUFFERS = CacheBuilder.newBuilder()
|
|
||||||
.expireAfterAccess(10, TimeUnit.SECONDS)
|
|
||||||
.<UUID, PortalFrameBuffer>removalListener(n -> n.getValue().close())
|
|
||||||
.build(CacheLoader.from(uuid -> new PortalFrameBuffer()));
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean shouldRenderEffectPass(int pass) {
|
public boolean shouldRenderEffectPass(int pass) {
|
||||||
|
@ -62,31 +23,21 @@ public class PortalSpellRenderer extends SpellRenderer<PortalSpell> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(MatrixStack matrices, VertexConsumerProvider vertices, PortalSpell spell, Caster<?> caster, int light, float limbAngle, float limbDistance, float tickDelta, float animationProgress, float headYaw, float headPitch) {
|
public void render(MatrixStack matrices, VertexConsumerProvider vertices, PortalSpell spell, Caster<?> caster, int light, float strength, float limbDistance, float tickDelta, float animationProgress, float headYaw, float headPitch) {
|
||||||
super.render(matrices, vertices, spell, caster, light, limbAngle, limbDistance, tickDelta, animationProgress, headYaw, headPitch);
|
super.render(matrices, vertices, spell, caster, light, strength, limbDistance, tickDelta, animationProgress, headYaw, headPitch);
|
||||||
|
|
||||||
if (!spell.isLinked()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int color = spell.getType().getColor();
|
|
||||||
|
|
||||||
float red = Color.r(color);
|
|
||||||
float green = Color.g(color);
|
|
||||||
float blue = Color.b(color);
|
|
||||||
|
|
||||||
VertexConsumer buff = vertices.getBuffer(RenderLayers.getEndGateway());
|
VertexConsumer buff = vertices.getBuffer(RenderLayers.getEndGateway());
|
||||||
|
|
||||||
matrices.push();
|
matrices.push();
|
||||||
matrices.translate(0, 0.02, 0);
|
matrices.translate(0, 0.02, 0);
|
||||||
SphereModel.DISK.render(matrices, buff, light, 0, 2F, red, green, blue, 1);
|
SphereModel.DISK.render(matrices, buff, light, 0, 2F * strength, 1, 1, 1, 1);
|
||||||
matrices.pop();
|
matrices.pop();
|
||||||
|
|
||||||
if (!FANCY_PORTAlS) {
|
if (!FANCY_PORTAlS || !spell.isLinked()) {
|
||||||
matrices.push();
|
matrices.push();
|
||||||
matrices.translate(0, -0.02, 0);
|
matrices.translate(0, -0.02, 0);
|
||||||
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(180));
|
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(180));
|
||||||
SphereModel.DISK.render(matrices, buff, light, 0, 2F, red, green, blue, 1);
|
SphereModel.DISK.render(matrices, buff, light, 0, 2F * strength, 1, 1, 1, 1);
|
||||||
matrices.pop();
|
matrices.pop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -94,231 +45,44 @@ public class PortalSpellRenderer extends SpellRenderer<PortalSpell> {
|
||||||
// Fancy portal rendering is disabled for now
|
// Fancy portal rendering is disabled for now
|
||||||
// Need to fix:
|
// Need to fix:
|
||||||
// 1. Transparent parts of the sky (because the game sets the clear to (0,0,0,0)
|
// 1. Transparent parts of the sky (because the game sets the clear to (0,0,0,0)
|
||||||
// 2. Chunk flickering at long distances between portals
|
|
||||||
|
|
||||||
if (caster.asEntity().distanceTo(client.cameraEntity) > 50) {
|
if (caster.asEntity().distanceTo(client.cameraEntity) > 50) {
|
||||||
return; // don't bother rendering if too far away
|
return; // don't bother rendering if too far away
|
||||||
}
|
}
|
||||||
|
|
||||||
|
matrices.push();
|
||||||
|
matrices.scale(strength, strength, strength);
|
||||||
|
|
||||||
spell.getTarget().ifPresent(target -> {
|
spell.getTarget().ifPresent(target -> {
|
||||||
try {
|
float grown = Math.min(caster.asEntity().age, 20) / 20F;
|
||||||
float grown = Math.min(caster.asEntity().age, 20) / 20F;
|
matrices.push();
|
||||||
matrices.push();
|
matrices.translate(0, -0.01, 0);
|
||||||
matrices.translate(0, -0.01, 0);
|
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(-spell.getYaw()));
|
||||||
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(-spell.getYaw()));
|
matrices.scale(grown, 1, grown);
|
||||||
matrices.scale(grown, 1, grown);
|
boolean inRange = MinecraftClient.getInstance().player.getPos().distanceTo(target.pos()) < MinecraftClient.getInstance().gameRenderer.getViewDistance();
|
||||||
PortalFrameBuffer buffer = FRAME_BUFFERS.get(target.uuid());
|
|
||||||
buffer.build(spell, caster, target);
|
PortalFrameBuffer buffer = PortalFrameBuffer.unpool(target.uuid());
|
||||||
|
if (buffer != null) {
|
||||||
|
if (inRange) {
|
||||||
|
buffer.build(spell, caster, target);
|
||||||
|
}
|
||||||
buffer.draw(matrices, vertices);
|
buffer.draw(matrices, vertices);
|
||||||
matrices.pop();
|
}
|
||||||
} catch (ExecutionException e) { }
|
if (!inRange) {
|
||||||
|
buffer = PortalFrameBuffer.unpool(caster.asEntity().getUuid());
|
||||||
|
if (buffer != null) {
|
||||||
|
buffer.build(spell, caster, new EntityReference.EntityValues<>(caster.asEntity()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
matrices.pop();
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
static class PortalFrameBuffer implements AutoCloseable {
|
matrices.pop();
|
||||||
@Nullable
|
|
||||||
private SimpleFramebuffer framebuffer;
|
|
||||||
@Nullable
|
|
||||||
private SimpleFramebuffer backgroundBuffer;
|
|
||||||
private boolean closed;
|
|
||||||
|
|
||||||
private final MinecraftClient client = MinecraftClient.getInstance();
|
|
||||||
|
|
||||||
private boolean pendingDraw;
|
|
||||||
|
|
||||||
private static int recursionCount;
|
|
||||||
|
|
||||||
public void draw(MatrixStack matrices, VertexConsumerProvider vertices) {
|
|
||||||
Vec3d skyColor = client.world.getSkyColor(client.gameRenderer.getCamera().getPos(), client.getTickDelta());
|
|
||||||
BackgroundRenderer.setFogBlack();
|
|
||||||
SphereModel.DISK.render(matrices, vertices.getBuffer(RenderLayers.getMagicShield()), 0, 0, 2, (float)skyColor.x, (float)skyColor.y, (float)skyColor.z, 1);
|
|
||||||
matrices.translate(0, -0.001, 0);
|
|
||||||
|
|
||||||
if (!(closed || framebuffer == null)) {
|
|
||||||
RenderSystem.assertOnRenderThread();
|
|
||||||
GlStateManager._colorMask(true, true, true, false);
|
|
||||||
GlStateManager._enableDepthTest();
|
|
||||||
GlStateManager._disableCull();
|
|
||||||
Tessellator tessellator = RenderSystem.renderThreadTesselator();
|
|
||||||
BufferBuilder buffer = tessellator.getBuffer();
|
|
||||||
float uScale = (float)framebuffer.viewportWidth / (float)framebuffer.textureWidth;
|
|
||||||
float vScale = (float)framebuffer.viewportHeight / (float)framebuffer.textureHeight;
|
|
||||||
RenderSystem.setShader(GameRenderer::getPositionTexColorProgram);
|
|
||||||
RenderSystem._setShaderTexture(0, framebuffer.getColorAttachment());
|
|
||||||
buffer.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR);
|
|
||||||
TexturedSphereModel.DISK.render(matrices, buffer, 2F, 1, 1, 1, 1, uScale, vScale);
|
|
||||||
tessellator.draw();
|
|
||||||
|
|
||||||
client.getTextureManager().bindTexture(PlayerScreenHandler.BLOCK_ATLAS_TEXTURE);
|
|
||||||
GlStateManager._enableCull();
|
|
||||||
GlStateManager._colorMask(true, true, true, true);
|
|
||||||
GlStateManager._depthMask(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void build(PortalSpell spell, Caster<?> caster, EntityReference.EntityValues<Entity> target) {
|
|
||||||
|
|
||||||
if (System.currentTimeMillis() % 100 < 50) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pendingDraw && recursionCount > 0) {
|
|
||||||
innerBuild(spell, caster, target);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pendingDraw) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
pendingDraw = true;
|
|
||||||
if (recursionCount > 0) {
|
|
||||||
innerBuild(spell, caster, target);
|
|
||||||
} else {
|
|
||||||
((MixinMinecraftClient)client).getRenderTaskQueue().add(() -> innerBuild(spell, caster, target));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void innerBuild(PortalSpell spell, Caster<?> caster, EntityReference.EntityValues<Entity> target) {
|
|
||||||
synchronized (client) {
|
|
||||||
pendingDraw = false;
|
|
||||||
|
|
||||||
if (recursionCount > 2) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
recursionCount++;
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (closed || client.interactionManager == null) {
|
|
||||||
close();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var fov = client.options.getFov();
|
|
||||||
int originalFov = fov.getValue();
|
|
||||||
fov.setValue(110);
|
|
||||||
|
|
||||||
Vec3d offset = new Vec3d(0, 1.8, 0);
|
|
||||||
float yaw = spell.getYawDifference();
|
|
||||||
|
|
||||||
offset = offset.rotateY(yaw * MathHelper.RADIANS_PER_DEGREE);
|
|
||||||
|
|
||||||
Entity cameraEntity = UEntities.CAST_SPELL.create(caster.asWorld());
|
|
||||||
cameraEntity.setPosition(target.pos().add(offset));
|
|
||||||
cameraEntity.setPitch(spell.getTargetPitch());
|
|
||||||
cameraEntity.setYaw(spell.getTargetYaw() + 180);
|
|
||||||
|
|
||||||
drawWorld(cameraEntity, 400, 400);
|
|
||||||
|
|
||||||
fov.setValue(originalFov);
|
|
||||||
} finally {
|
|
||||||
recursionCount--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
|
||||||
private void drawWorld(Entity cameraEntity, int width, int height) {
|
|
||||||
Entity oldCameraEntity = client.cameraEntity;
|
|
||||||
client.cameraEntity = cameraEntity;
|
|
||||||
|
|
||||||
Window window = client.getWindow();
|
|
||||||
|
|
||||||
Perspective perspective = client.options.getPerspective();
|
|
||||||
client.options.setPerspective(Perspective.FIRST_PERSON);
|
|
||||||
|
|
||||||
int i = window.getFramebufferWidth();
|
|
||||||
int j = window.getFramebufferHeight();
|
|
||||||
|
|
||||||
width = i;
|
|
||||||
height = j;
|
|
||||||
|
|
||||||
client.getFramebuffer().endWrite();
|
|
||||||
|
|
||||||
if (framebuffer == null) {
|
|
||||||
framebuffer = new SimpleFramebuffer(width, height, true, MinecraftClient.IS_SYSTEM_MAC);
|
|
||||||
framebuffer.setClearColor(0, 0, 0, 0);
|
|
||||||
framebuffer.clear(MinecraftClient.IS_SYSTEM_MAC);
|
|
||||||
}
|
|
||||||
|
|
||||||
window.setFramebufferWidth(width);
|
|
||||||
window.setFramebufferHeight(height);
|
|
||||||
|
|
||||||
MatrixStack view = RenderSystem.getModelViewStack();
|
|
||||||
view.push();
|
|
||||||
view.loadIdentity();
|
|
||||||
RenderSystem.applyModelViewMatrix();
|
|
||||||
Matrix4f proj = RenderSystem.getProjectionMatrix();
|
|
||||||
Matrix3f invView = RenderSystem.getInverseViewRotationMatrix();
|
|
||||||
|
|
||||||
int fbo = client.getFramebuffer().fbo;
|
|
||||||
client.getFramebuffer().fbo = framebuffer.fbo;
|
|
||||||
|
|
||||||
RenderSystem.clear(GlConst.GL_DEPTH_BUFFER_BIT | GlConst.GL_COLOR_BUFFER_BIT, MinecraftClient.IS_SYSTEM_MAC);
|
|
||||||
framebuffer.beginWrite(true);
|
|
||||||
BackgroundRenderer.clearFog();
|
|
||||||
RenderSystem.enableCull();
|
|
||||||
|
|
||||||
Camera camera = client.gameRenderer.getCamera();
|
|
||||||
|
|
||||||
ObjectArrayList<?> chunkInfos = ((WorldRendererDuck)client.worldRenderer).unicopia_getChunkInfos();
|
|
||||||
List<Object> backup = new ArrayList<>(chunkInfos);
|
|
||||||
|
|
||||||
client.gameRenderer.setRenderHand(false);
|
|
||||||
MatrixStack matrices = new MatrixStack();
|
|
||||||
|
|
||||||
matrices.scale((float)width / height, 1, 1);
|
|
||||||
|
|
||||||
client.gameRenderer.renderWorld(1, 0, matrices);
|
|
||||||
if (recursionCount <= 1) {
|
|
||||||
client.gameRenderer.setRenderHand(true);
|
|
||||||
}
|
|
||||||
framebuffer.endWrite();
|
|
||||||
|
|
||||||
client.getFramebuffer().fbo = fbo;
|
|
||||||
client.getFramebuffer().beginWrite(true);
|
|
||||||
|
|
||||||
chunkInfos.clear();
|
|
||||||
chunkInfos.addAll((List)backup);
|
|
||||||
|
|
||||||
view.pop();
|
|
||||||
RenderSystem.applyModelViewMatrix();
|
|
||||||
|
|
||||||
window.setFramebufferWidth(i);
|
|
||||||
window.setFramebufferHeight(j);
|
|
||||||
|
|
||||||
client.options.setPerspective(perspective);
|
|
||||||
client.cameraEntity = oldCameraEntity;
|
|
||||||
|
|
||||||
RenderSystem.setProjectionMatrix(proj, VertexSorter.BY_Z);
|
|
||||||
RenderSystem.setInverseViewRotationMatrix(invView);
|
|
||||||
|
|
||||||
if (recursionCount <= 1) {
|
|
||||||
camera.update(client.world,
|
|
||||||
client.getCameraEntity() == null ? client.player : client.getCameraEntity(),
|
|
||||||
perspective.isFirstPerson(),
|
|
||||||
perspective.isFrontView(),
|
|
||||||
1
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
closed = true;
|
|
||||||
if (framebuffer != null) {
|
|
||||||
SimpleFramebuffer fb = framebuffer;
|
|
||||||
framebuffer = null;
|
|
||||||
fb.delete();
|
|
||||||
}
|
|
||||||
if (backgroundBuffer != null) {
|
|
||||||
SimpleFramebuffer fb = backgroundBuffer;
|
|
||||||
backgroundBuffer = null;
|
|
||||||
fb.delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface WorldRendererDuck {
|
public interface WorldRendererDuck {
|
||||||
ObjectArrayList<?> unicopia_getChunkInfos();
|
ObjectArrayList<?> unicopia_getChunkInfos();
|
||||||
|
|
||||||
|
Frustum unicopia_getFrustum();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,12 +3,18 @@ package com.minelittlepony.unicopia.mixin.client;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Mutable;
|
||||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.render.WorldRenderer;
|
||||||
|
|
||||||
@Mixin(MinecraftClient.class)
|
@Mixin(MinecraftClient.class)
|
||||||
public interface MixinMinecraftClient {
|
public interface MixinMinecraftClient {
|
||||||
@Accessor("renderTaskQueue")
|
@Accessor("renderTaskQueue")
|
||||||
Queue<Runnable> getRenderTaskQueue();
|
Queue<Runnable> getRenderTaskQueue();
|
||||||
|
|
||||||
|
@Mutable
|
||||||
|
@Accessor("worldRenderer")
|
||||||
|
void setWorldRenderer(WorldRenderer worldRenderer);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue