mirror of
https://github.com/GTNewHorizons/Angelica.git
synced 2026-11-14 01:14:08 +00:00
* Moves CapturingTesselator, JSON Models, and misc utility classes to GTNHlib * Switch to separate source set for mixins - faster incremental builds
170 lines
6.1 KiB
Java
170 lines
6.1 KiB
Java
package net.coderbot.iris.pipeline;
|
|
|
|
import com.gtnewhorizon.gtnhlib.client.renderer.CapturingTessellator;
|
|
import com.gtnewhorizon.gtnhlib.client.renderer.TessellatorManager;
|
|
import com.gtnewhorizon.gtnhlib.client.renderer.vbo.VertexBuffer;
|
|
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.DefaultVertexFormat;
|
|
|
|
import net.minecraft.client.Minecraft;
|
|
import net.minecraft.client.renderer.Tessellator;
|
|
import org.lwjgl.opengl.GL11;
|
|
|
|
import java.nio.FloatBuffer;
|
|
|
|
/**
|
|
* Renders the sky horizon. Vanilla Minecraft simply uses the "clear color" for its horizon, and then draws a plane
|
|
* above the player. This class extends the sky rendering so that an octagonal prism is drawn around the player instead,
|
|
* allowing shaders to perform more advanced sky rendering.
|
|
* <p>
|
|
* However, the horizon rendering is designed so that when sky shaders are not being used, it looks almost exactly the
|
|
* same as vanilla sky rendering, except a few almost entirely imperceptible differences where the walls
|
|
* of the octagonal prism intersect the top plane.
|
|
*/
|
|
public class HorizonRenderer {
|
|
/**
|
|
* The Y coordinate of the top skybox plane. Acts as the upper bound for the horizon prism, since the prism lies
|
|
* between the bottom and top skybox planes.
|
|
*/
|
|
private static final float TOP = 16.0F;
|
|
|
|
/**
|
|
* The Y coordinate of the bottom skybox plane. Acts as the lower bound for the horizon prism, since the prism lies
|
|
* between the bottom and top skybox planes.
|
|
*/
|
|
private static final float BOTTOM = -16.0F;
|
|
|
|
/**
|
|
* Cosine of 22.5 degrees.
|
|
*/
|
|
private static final double COS_22_5 = Math.cos(Math.toRadians(22.5));
|
|
|
|
/**
|
|
* Sine of 22.5 degrees.
|
|
*/
|
|
private static final double SIN_22_5 = Math.sin(Math.toRadians(22.5));
|
|
private VertexBuffer vertexBuffer;
|
|
private int currentRenderDistance;
|
|
|
|
public HorizonRenderer() {
|
|
currentRenderDistance = Minecraft.getMinecraft().gameSettings.renderDistanceChunks;
|
|
|
|
rebuildBuffer();
|
|
}
|
|
|
|
private void rebuildBuffer() {
|
|
if (this.vertexBuffer != null) {
|
|
this.vertexBuffer.close();
|
|
}
|
|
TessellatorManager.startCapturing();
|
|
final CapturingTessellator tessellator = (CapturingTessellator) TessellatorManager.get();
|
|
|
|
// Build the horizon quads into a buffer
|
|
tessellator.startDrawingQuads(); //(GL11.GL_QUADS, DefaultVertexFormat.POSITION);
|
|
buildHorizon(currentRenderDistance * 16, tessellator);
|
|
|
|
this.vertexBuffer = TessellatorManager.stopCapturingToVBO(DefaultVertexFormat.POSITION);
|
|
}
|
|
|
|
private void buildQuad(Tessellator consumer, double x1, double z1, double x2, double z2) {
|
|
consumer.addVertex(x1, BOTTOM, z1);
|
|
consumer.addVertex(x1, TOP, z1);
|
|
consumer.addVertex(x2, TOP, z2);
|
|
consumer.addVertex(x2, BOTTOM, z2);
|
|
}
|
|
|
|
private void buildHalf(Tessellator consumer, double adjacent, double opposite, boolean invert) {
|
|
if (invert) {
|
|
adjacent = -adjacent;
|
|
opposite = -opposite;
|
|
}
|
|
|
|
// NB: Make sure that these vertices are being specified in counterclockwise order!
|
|
// Otherwise back face culling will remove your quads, and you'll be wondering why there's a hole in your horizon.
|
|
// Don't poke holes in the horizon. Specify vertices in counterclockwise order.
|
|
|
|
// +X,-Z face
|
|
buildQuad(consumer, adjacent, -opposite, opposite, -adjacent);
|
|
// +X face
|
|
buildQuad(consumer, adjacent, opposite, adjacent, -opposite);
|
|
// +X,+Z face
|
|
buildQuad(consumer, opposite, adjacent, adjacent, opposite);
|
|
// +Z face
|
|
buildQuad(consumer, -opposite, adjacent, opposite, adjacent);
|
|
}
|
|
|
|
/**
|
|
* @param adjacent the adjacent side length of the a triangle with a hypotenuse extending from the center of the
|
|
* octagon to a given vertex on the perimeter.
|
|
* @param opposite the opposite side length of the a triangle with a hypotenuse extending from the center of the
|
|
* octagon to a given vertex on the perimeter.
|
|
*/
|
|
private void buildOctagonalPrism(Tessellator consumer, double adjacent, double opposite) {
|
|
buildHalf(consumer, adjacent, opposite, false);
|
|
buildHalf(consumer, adjacent, opposite, true);
|
|
}
|
|
|
|
private void buildRegularOctagonalPrism(Tessellator consumer, double radius) {
|
|
buildOctagonalPrism(consumer, radius * COS_22_5, radius * SIN_22_5);
|
|
}
|
|
|
|
private void buildBottomPlane(Tessellator consumer, int radius) {
|
|
for (int x = -radius; x <= radius; x += 64) {
|
|
for (int z = -radius; z <= radius; z += 64) {
|
|
consumer.addVertex(x + 64, BOTTOM, z);
|
|
consumer.addVertex(x, BOTTOM, z);
|
|
consumer.addVertex(x, BOTTOM, z + 64);
|
|
consumer.addVertex(x + 64, BOTTOM, z + 64);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void buildTopPlane(Tessellator consumer, int radius) {
|
|
// You might be tempted to try to combine this with buildBottomPlane to avoid code duplication,
|
|
// but that won't work since the winding order has to be reversed or else one of the planes will be
|
|
// discarded by back face culling.
|
|
for (int x = -radius; x <= radius; x += 64) {
|
|
for (int z = -radius; z <= radius; z += 64) {
|
|
consumer.addVertex(x + 64, TOP, z);
|
|
consumer.addVertex(x + 64, TOP, z + 64);
|
|
consumer.addVertex(x, TOP, z + 64);
|
|
consumer.addVertex(x, TOP, z);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void buildHorizon(int radius, Tessellator consumer) {
|
|
if (radius > 256) {
|
|
// Prevent the prism from getting too large, this causes issues on some shader packs that modify the vanilla
|
|
// sky if we don't do this.
|
|
radius = 256;
|
|
}
|
|
|
|
buildRegularOctagonalPrism(consumer, radius);
|
|
|
|
// Replicate the vanilla top plane since we can't assume that it'll be rendered.
|
|
// TODO: Remove vanilla top plane
|
|
buildTopPlane(consumer, 384);
|
|
|
|
// Always make the bottom plane have a radius of 384, to match the top plane.
|
|
buildBottomPlane(consumer, 384);
|
|
}
|
|
|
|
public void renderHorizon(FloatBuffer floatBuffer) {
|
|
if (currentRenderDistance != Minecraft.getMinecraft().gameSettings.renderDistanceChunks) {
|
|
currentRenderDistance = Minecraft.getMinecraft().gameSettings.renderDistanceChunks;
|
|
rebuildBuffer();
|
|
}
|
|
|
|
vertexBuffer.bind();
|
|
GL11.glVertexPointer(3, GL11.GL_FLOAT, 12, 0L);
|
|
GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
|
|
vertexBuffer.draw(floatBuffer);
|
|
GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
|
|
vertexBuffer.unbind();
|
|
}
|
|
|
|
public void destroy() {
|
|
vertexBuffer.close();
|
|
}
|
|
}
|