From fe22b476acf711e1b8a7054c666e9351c48b7230 Mon Sep 17 00:00:00 2001 From: FalsePattern Date: Tue, 5 Dec 2023 18:36:05 +0100 Subject: [PATCH 01/11] begin shader compat --- src/main/java/makamys/neodymium/Compat.java | 4 + .../makamys/neodymium/renderer/MeshQuad.java | 84 +++++++++++++++---- .../neodymium/renderer/NeoRenderer.java | 13 ++- 3 files changed, 82 insertions(+), 19 deletions(-) diff --git a/src/main/java/makamys/neodymium/Compat.java b/src/main/java/makamys/neodymium/Compat.java index 8af4319..ba22265 100644 --- a/src/main/java/makamys/neodymium/Compat.java +++ b/src/main/java/makamys/neodymium/Compat.java @@ -44,6 +44,10 @@ public static boolean RPLE() { return RPLE; } + public static boolean isShaders() { + return false; + } + private static void disableTriangulator() { ((ToggleableTessellator)Tessellator.instance).disableTriangulator(); } diff --git a/src/main/java/makamys/neodymium/renderer/MeshQuad.java b/src/main/java/makamys/neodymium/renderer/MeshQuad.java index 484ab8b..f748488 100644 --- a/src/main/java/makamys/neodymium/renderer/MeshQuad.java +++ b/src/main/java/makamys/neodymium/renderer/MeshQuad.java @@ -1,11 +1,8 @@ package makamys.neodymium.renderer; import java.io.IOException; -import java.util.Arrays; -import java.util.Comparator; import java.util.Locale; -import makamys.neodymium.Neodymium; import makamys.neodymium.Compat; import org.lwjgl.opengl.GL11; import org.lwjgl.util.vector.Vector3f; @@ -31,6 +28,21 @@ public class MeshQuad { public int[] bsG = new int[4]; public int[] bsB = new int[4]; + public int[] e1 = new int[4]; + public int[] e2 = new int[4]; + + public float[] xn = new float[4]; + public float[] yn = new float[4]; + public float[] zn = new float[4]; + + public float[] xt = new float[4]; + public float[] yt = new float[4]; + public float[] zt = new float[4]; + public float[] wt = new float[4]; + + public float[] um = new float[4]; + public float[] vm = new float[4]; + public boolean deleted; public QuadNormal normal; @@ -55,15 +67,30 @@ private void read(int[] rawBuffer, int tessellatorVertexSize, int offset, float // TODO normals? - bs[vi] = flags.hasBrightness ? rawBuffer[i + 7] : DEFAULT_BRIGHTNESS; - - if (Compat.RPLE()) { - if (flags.hasBrightness) { - bsG[vi] = rawBuffer[i + 8]; - bsB[vi] = rawBuffer[i + 9]; - } else { - bsG[vi] = DEFAULT_BRIGHTNESS; - bsB[vi] = DEFAULT_BRIGHTNESS; + if (Compat.isShaders()) { + bs[vi] = flags.hasBrightness ? rawBuffer[i + 6] : DEFAULT_BRIGHTNESS; + e1[vi] = rawBuffer[i + 7]; + e2[vi] = rawBuffer[i + 8]; + xn[vi] = Float.intBitsToFloat(rawBuffer[i + 9]); + yn[vi] = Float.intBitsToFloat(rawBuffer[i + 10]); + zn[vi] = Float.intBitsToFloat(rawBuffer[i + 11]); + xt[vi] = Float.intBitsToFloat(rawBuffer[i + 12]); + yt[vi] = Float.intBitsToFloat(rawBuffer[i + 13]); + zt[vi] = Float.intBitsToFloat(rawBuffer[i + 14]); + wt[vi] = Float.intBitsToFloat(rawBuffer[i + 15]); + um[vi] = Float.intBitsToFloat(rawBuffer[i + 16]); + vm[vi] = Float.intBitsToFloat(rawBuffer[i + 17]); + } else { + bs[vi] = flags.hasBrightness ? rawBuffer[i + 7] : DEFAULT_BRIGHTNESS; + + if (Compat.RPLE()) { + if (flags.hasBrightness) { + bsG[vi] = rawBuffer[i + 8]; + bsB[vi] = rawBuffer[i + 9]; + } else { + bsG[vi] = DEFAULT_BRIGHTNESS; + bsB[vi] = DEFAULT_BRIGHTNESS; + } } } } @@ -83,6 +110,19 @@ private void read(int[] rawBuffer, int tessellatorVertexSize, int offset, float bsB[3] = bsB[2]; } cs[3] = cs[2]; + if (Compat.isShaders()) { + e1[3] = e1[2]; + e2[3] = e2[2]; + xn[3] = xn[2]; + yn[3] = yn[2]; + zn[3] = zn[2]; + xt[3] = xt[2]; + yt[3] = yt[2]; + zt[3] = zt[2]; + wt[3] = wt[2]; + um[3] = um[2]; + vm[3] = vm[2]; + } } } @@ -128,15 +168,29 @@ public void writeToBuffer(BufferWriter out, int expectedStride) throws IOExcepti out.writeFloat(v); } + int c = cs[vi]; + + out.writeInt(c); + out.writeInt(bs[vi]); if (Compat.RPLE()) { out.writeInt(bsG[vi]); out.writeInt(bsB[vi]); } - int c = cs[vi]; - - out.writeInt(c); + if (Compat.isShaders()) { + out.writeInt(e1[vi]); + out.writeInt(e2[vi]); + out.writeFloat(xn[vi]); + out.writeFloat(yn[vi]); + out.writeFloat(zn[vi]); + out.writeFloat(xt[vi]); + out.writeFloat(yt[vi]); + out.writeFloat(zt[vi]); + out.writeFloat(wt[vi]); + out.writeFloat(um[vi]); + out.writeFloat(vm[vi]); + } assert out.position() % expectedStride == 0; diff --git a/src/main/java/makamys/neodymium/renderer/NeoRenderer.java b/src/main/java/makamys/neodymium/renderer/NeoRenderer.java index 6c0b015..fcd4c67 100644 --- a/src/main/java/makamys/neodymium/renderer/NeoRenderer.java +++ b/src/main/java/makamys/neodymium/renderer/NeoRenderer.java @@ -419,14 +419,19 @@ public boolean init() { } else { attributes.addAttribute("TEXTURE", 2, 4, GL_FLOAT); } - if (Compat.RPLE()) { + attributes.addAttribute("COLOR", 4, 1, GL_UNSIGNED_BYTE); + attributes.addAttribute("BRIGHTNESS", 2, 2, GL_SHORT); + if (Compat.isShaders()) { + attributes.addAttribute("ENTITY_DATA_1", 1, 4, GL_UNSIGNED_INT); + attributes.addAttribute("ENTITY_DATA_2", 1, 4, GL_UNSIGNED_INT); + attributes.addAttribute("NORMAL", 3, 4, GL_FLOAT); + attributes.addAttribute("TANGENT", 4, 4, GL_FLOAT); + attributes.addAttribute("MIDTEXTURE", 2, 4, GL_FLOAT); + } else if (Compat.RPLE()) { attributes.addAttribute("BRIGHTNESS_RED", 2, 2, GL_SHORT); attributes.addAttribute("BRIGHTNESS_GREEN", 2, 2, GL_SHORT); attributes.addAttribute("BRIGHTNESS_BLUE", 2, 2, GL_SHORT); - } else { - attributes.addAttribute("BRIGHTNESS", 2, 2, GL_SHORT); } - attributes.addAttribute("COLOR", 4, 1, GL_UNSIGNED_BYTE); reloadShader(); From ee875ea73b52ac9d571285de7baa7547372e1fe0 Mon Sep 17 00:00:00 2001 From: FalsePattern Date: Tue, 5 Dec 2023 18:41:00 +0100 Subject: [PATCH 02/11] disable shaderpack disabling --- src/main/java/makamys/neodymium/Compat.java | 28 ++++++++++----------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/main/java/makamys/neodymium/Compat.java b/src/main/java/makamys/neodymium/Compat.java index ba22265..acb76ca 100644 --- a/src/main/java/makamys/neodymium/Compat.java +++ b/src/main/java/makamys/neodymium/Compat.java @@ -57,20 +57,20 @@ public static void getCompatibilityWarnings(List warns, List c warns.add(new Warning("Advanced OpenGL is enabled, performance may be poor." + (statusCommand ? " Click here to disable it." : "")).chatAction("neodymium disable_advanced_opengl")); } - try { - Class shaders = Class.forName("shadersmod.client.Shaders"); - try { - String shaderPack = (String)shaders.getMethod("getShaderPackName").invoke(null); - if(shaderPack != null) { - criticalWarns.add(new Warning("A shader pack is enabled, this is not supported.")); - } - } catch(Exception e) { - LOGGER.warn("Failed to get shader pack name"); - e.printStackTrace(); - } - } catch (ClassNotFoundException e) { - - } +// try { +// Class shaders = Class.forName("shadersmod.client.Shaders"); +// try { +// String shaderPack = (String)shaders.getMethod("getShaderPackName").invoke(null); +// if(shaderPack != null) { +// criticalWarns.add(new Warning("A shader pack is enabled, this is not supported.")); +// } +// } catch(Exception e) { +// LOGGER.warn("Failed to get shader pack name"); +// e.printStackTrace(); +// } +// } catch (ClassNotFoundException e) { +// +// } if(!isGL33Supported) { criticalWarns.add(new Warning("OpenGL 3.3 is not supported.")); From ba17ea4c673b5bc7ccceb6f27e684da7f6170af8 Mon Sep 17 00:00:00 2001 From: FalsePattern Date: Tue, 5 Dec 2023 19:48:02 +0100 Subject: [PATCH 03/11] shaders detection --- src/main/java/makamys/neodymium/Compat.java | 40 +++++++++++-------- .../neodymium/renderer/NeoRenderer.java | 2 + 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/main/java/makamys/neodymium/Compat.java b/src/main/java/makamys/neodymium/Compat.java index acb76ca..6343e14 100644 --- a/src/main/java/makamys/neodymium/Compat.java +++ b/src/main/java/makamys/neodymium/Compat.java @@ -44,8 +44,29 @@ public static boolean RPLE() { return RPLE; } + private static boolean shadersEnabled; + public static boolean isShaders() { - return false; + return shadersEnabled; + } + + public static void updateShadersState() { + try { + Class shaders = Class.forName("shadersmod.client.Shaders"); + try { + String shaderPack = (String)shaders.getMethod("getShaderPackName").invoke(null); + if(shaderPack != null) { + shadersEnabled = true; + return; + } + } catch(Exception e) { + LOGGER.warn("Failed to get shader pack name"); + e.printStackTrace(); + } + } catch (ClassNotFoundException e) { + + } + shadersEnabled = false; } private static void disableTriangulator() { @@ -57,21 +78,6 @@ public static void getCompatibilityWarnings(List warns, List c warns.add(new Warning("Advanced OpenGL is enabled, performance may be poor." + (statusCommand ? " Click here to disable it." : "")).chatAction("neodymium disable_advanced_opengl")); } -// try { -// Class shaders = Class.forName("shadersmod.client.Shaders"); -// try { -// String shaderPack = (String)shaders.getMethod("getShaderPackName").invoke(null); -// if(shaderPack != null) { -// criticalWarns.add(new Warning("A shader pack is enabled, this is not supported.")); -// } -// } catch(Exception e) { -// LOGGER.warn("Failed to get shader pack name"); -// e.printStackTrace(); -// } -// } catch (ClassNotFoundException e) { -// -// } - if(!isGL33Supported) { criticalWarns.add(new Warning("OpenGL 3.3 is not supported.")); } @@ -122,7 +128,7 @@ public static boolean disableAdvancedOpenGL() { } return false; } - + private static class OptiFineStubVirtualJar implements IVirtualJar { @Override diff --git a/src/main/java/makamys/neodymium/renderer/NeoRenderer.java b/src/main/java/makamys/neodymium/renderer/NeoRenderer.java index fcd4c67..ff13dd7 100644 --- a/src/main/java/makamys/neodymium/renderer/NeoRenderer.java +++ b/src/main/java/makamys/neodymium/renderer/NeoRenderer.java @@ -412,6 +412,8 @@ public boolean init() { // This means 1 MB of index data per 512 MB of VRAM. MAX_MESHES = Config.VRAMSize * 128; + Compat.updateShadersState(); + attributes = new AttributeSet(); attributes.addAttribute("POS", 3, 4, GL_FLOAT); if (Config.shortUV) { From 6a42f82db6fe713fce90f537fdc02cd6edc639c0 Mon Sep 17 00:00:00 2001 From: Ven Date: Tue, 5 Dec 2023 19:11:22 +0000 Subject: [PATCH 04/11] Dirty OF Shader Compat --- .../makamys/neodymium/renderer/ChunkMesh.java | 2 +- .../neodymium/renderer/NeoRenderer.java | 550 ++++++++++-------- 2 files changed, 314 insertions(+), 238 deletions(-) diff --git a/src/main/java/makamys/neodymium/renderer/ChunkMesh.java b/src/main/java/makamys/neodymium/renderer/ChunkMesh.java index 24acc30..72c20ff 100644 --- a/src/main/java/makamys/neodymium/renderer/ChunkMesh.java +++ b/src/main/java/makamys/neodymium/renderer/ChunkMesh.java @@ -110,7 +110,7 @@ private void addTessellatorData(Tessellator t) { int verticesPerPrimitive = t.drawMode == GL11.GL_QUADS ? 4 : 3; - int tessellatorVertexSize = Compat.RPLE() ? 12 : 8; + int tessellatorVertexSize = Compat.isShaders() ? 18 : Compat.RPLE() ? 12 : 8; for(int quadI = 0; quadI < t.vertexCount / verticesPerPrimitive; quadI++) { MeshQuad quad = quadBuf.next(); diff --git a/src/main/java/makamys/neodymium/renderer/NeoRenderer.java b/src/main/java/makamys/neodymium/renderer/NeoRenderer.java index ff13dd7..0cc7692 100644 --- a/src/main/java/makamys/neodymium/renderer/NeoRenderer.java +++ b/src/main/java/makamys/neodymium/renderer/NeoRenderer.java @@ -1,69 +1,66 @@ package makamys.neodymium.renderer; -import static makamys.neodymium.Constants.VERSION; - -import static org.lwjgl.opengl.GL11.*; -import static org.lwjgl.opengl.GL14.*; -import static org.lwjgl.opengl.GL15.*; -import static org.lwjgl.opengl.GL20.*; -import static org.lwjgl.opengl.GL30.*; - -import java.nio.FloatBuffer; -import java.nio.IntBuffer; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - +import lombok.val; import makamys.neodymium.Compat; -import makamys.neodymium.renderer.attribs.AttributeSet; -import makamys.neodymium.util.BufferWriter; -import org.lwjgl.BufferUtils; -import org.lwjgl.input.Keyboard; -import org.lwjgl.opengl.GL11; -import org.lwjgl.util.vector.Matrix4f; -import org.lwjgl.util.vector.Vector4f; - import makamys.neodymium.Neodymium; import makamys.neodymium.config.Config; import makamys.neodymium.ducks.IWorldRenderer; import makamys.neodymium.renderer.Mesh.GPUStatus; -import makamys.neodymium.util.CheatHelper; -import makamys.neodymium.util.GuiHelper; -import makamys.neodymium.util.OFUtil; -import makamys.neodymium.util.Preprocessor; -import makamys.neodymium.util.Util; +import makamys.neodymium.renderer.attribs.AttributeSet; +import makamys.neodymium.util.*; import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.OpenGlHelper; import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.entity.Entity; import net.minecraft.util.EnumChatFormatting; import net.minecraft.world.ChunkCoordIntPair; import net.minecraft.world.World; +import org.lwjgl.BufferUtils; +import org.lwjgl.input.Keyboard; +import org.lwjgl.opengl.ARBVertexShader; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL13; +import org.lwjgl.opengl.GL20; +import org.lwjgl.util.vector.Matrix4f; +import org.lwjgl.util.vector.Vector4f; + +import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import java.util.*; +import java.util.Map.Entry; + +import static makamys.neodymium.Constants.VERSION; +import static org.lwjgl.opengl.GL11.glGetInteger; +import static org.lwjgl.opengl.GL11.*; +import static org.lwjgl.opengl.GL14.glMultiDrawArrays; +import static org.lwjgl.opengl.GL15.GL_ARRAY_BUFFER; +import static org.lwjgl.opengl.GL15.glBindBuffer; +import static org.lwjgl.opengl.GL20.*; +import static org.lwjgl.opengl.GL30.*; -/** The main renderer class. */ +/** + * The main renderer class. + */ public class NeoRenderer { - + public boolean hasInited = false; public boolean destroyPending; public boolean reloadPending; public int rendererSpeedup; - + private static boolean[] wasDown = new boolean[256]; - + public boolean renderWorld; public boolean rendererActive; private boolean showMemoryDebugger; - + public boolean forceRenderFog; public boolean hasIncompatibilities; - + private boolean fogEnabled; - + private static int MAX_MESHES; - + private int VAO; private int[] shaderProgramsFog = {0, 0}; private int[] shaderProgramsNoFog = {0, 0}; @@ -71,136 +68,136 @@ public class NeoRenderer { private IntBuffer[] piCount = new IntBuffer[2]; GPUMemoryManager mem; private AttributeSet attributes; - + private Map loadedRegionsMap = new HashMap<>(); private List loadedRegionsList = new ArrayList<>(); - + public World world; - + // Eye position in world space private double eyePosX; private double eyePosY; private double eyePosZ; - + // Eye position in world space, transformed by model-view matrix (takes third person camera offset into account) private double eyePosXT; private double eyePosYT; private double eyePosZT; - + // eyePos?T divided by 16 int eyePosXTDiv; int eyePosYTDiv; int eyePosZTDiv; - + private int renderedMeshes, renderedQuads; private int frameCount; - - public NeoRenderer(World world){ + + public NeoRenderer(World world) { this.world = world; - if(shouldRenderInWorld(world)) { + if (shouldRenderInWorld(world)) { hasInited = init(); } - + renderWorld = true; rendererActive = true; } - + Vector4f transformedOrigin = new Vector4f(); - + public void preRenderSortedRenderers(int renderPass, double alpha, WorldRenderer[] sortedWorldRenderers) { - if(hasInited) { - if(renderPass == 0) { + if (hasInited) { + if (renderPass == 0) { renderedMeshes = 0; renderedQuads = 0; - + mainLoop(); - if(Minecraft.getMinecraft().currentScreen == null) { + if (Minecraft.getMinecraft().currentScreen == null) { handleKeyboard(); } - if(mem.getCoherenceRate() < 0.95f || frameCount % 4 == 0) { + if (mem.getCoherenceRate() < 0.95f || frameCount % 4 == 0) { mem.runGC(false); } - - if(rendererActive && renderWorld) { + + if (rendererActive && renderWorld) { updateGLValues(); - + transformedOrigin.set(0, 0, 0, 1); Matrix4f.transform(modelViewMatrixInv, transformedOrigin, transformedOrigin); - + Entity rve = Minecraft.getMinecraft().renderViewEntity; - + eyePosX = rve.lastTickPosX + (rve.posX - rve.lastTickPosX) * alpha; eyePosY = rve.lastTickPosY + (rve.posY - rve.lastTickPosY) * alpha + rve.getEyeHeight(); eyePosZ = rve.lastTickPosZ + (rve.posZ - rve.lastTickPosZ) * alpha; - + eyePosXT = eyePosX + transformedOrigin.x; eyePosYT = eyePosY + transformedOrigin.y; eyePosZT = eyePosZ + transformedOrigin.z; - - eyePosXTDiv = Math.floorDiv((int)Math.floor(eyePosXT), 16); - eyePosYTDiv = Math.floorDiv((int)Math.floor(eyePosYT), 16); - eyePosZTDiv = Math.floorDiv((int)Math.floor(eyePosZT), 16); - + + eyePosXTDiv = Math.floorDiv((int) Math.floor(eyePosXT), 16); + eyePosYTDiv = Math.floorDiv((int) Math.floor(eyePosYT), 16); + eyePosZTDiv = Math.floorDiv((int) Math.floor(eyePosZT), 16); + sort(frameCount % 100 == 0, frameCount % Config.sortFrequency == 0); - + initIndexBuffers(); } - + frameCount++; } - - if(rendererActive && renderWorld) { - Minecraft.getMinecraft().entityRenderer.enableLightmap((double)alpha); - + + if (rendererActive && renderWorld) { + Minecraft.getMinecraft().entityRenderer.enableLightmap((double) alpha); + render(renderPass, alpha); - - Minecraft.getMinecraft().entityRenderer.disableLightmap((double)alpha); + + Minecraft.getMinecraft().entityRenderer.disableLightmap((double) alpha); } } } - + public void onRenderTickEnd() { - if(Neodymium.isActive()) { - if(reloadPending) { + if (Neodymium.isActive()) { + if (reloadPending) { Minecraft.getMinecraft().renderGlobal.loadRenderers(); } - if(showMemoryDebugger && mem != null) { + if (showMemoryDebugger && mem != null) { GuiHelper.begin(); mem.drawInfo(); GuiHelper.end(); } - } else if(destroyPending) { + } else if (destroyPending) { destroy(); destroyPending = false; Neodymium.renderer = null; Minecraft.getMinecraft().renderGlobal.loadRenderers(); } } - + private void sort(boolean pass0, boolean pass1) { - for(NeoRegion r : loadedRegionsMap.values()) { + for (NeoRegion r : loadedRegionsMap.values()) { r.getRenderData().sort(eyePosX, eyePosY, eyePosZ, pass0, pass1); } } - + private void initIndexBuffers() { loadedRegionsList.clear(); loadedRegionsList.addAll(loadedRegionsMap.values()); loadedRegionsList.sort(Comparators.REGION_DISTANCE_COMPARATOR.setOrigin(eyePosX, eyePosY, eyePosZ)); - - for(int i = 0; i < 2; i++) { + + for (int i = 0; i < 2; i++) { piFirst[i].limit(MAX_MESHES); piCount[i].limit(MAX_MESHES); int order = i == 0 ? 1 : -1; - for(int regionI = order == 1 ? 0 : loadedRegionsList.size() - 1; regionI >= 0 && regionI < loadedRegionsList.size(); regionI += order) { + for (int regionI = order == 1 ? 0 : loadedRegionsList.size() - 1; regionI >= 0 && regionI < loadedRegionsList.size(); regionI += order) { NeoRegion.RenderData region = loadedRegionsList.get(regionI).getRenderData(); region.batchFirst[i] = piFirst[i].position(); - for(Mesh mesh : region.getSentMeshes(i)) { - WorldRenderer wr = ((ChunkMesh)mesh).wr; - if(mesh.visible && wr.isVisible && shouldRenderMesh(mesh)) { + for (Mesh mesh : region.getSentMeshes(i)) { + WorldRenderer wr = ((ChunkMesh) mesh).wr; + if (mesh.visible && wr.isVisible && shouldRenderMesh(mesh)) { int meshes = mesh.writeToIndexBuffer(piFirst[i], piCount[i], eyePosXTDiv, eyePosYTDiv, eyePosZTDiv, i); renderedMeshes += meshes; - for(int j = piCount[i].position() - meshes; j < piCount[i].position(); j++) { + for (int j = piCount[i].position() - meshes; j < piCount[i].position(); j++) { renderedQuads += piCount[i].get(j) / 4; } } @@ -211,29 +208,29 @@ private void initIndexBuffers() { piCount[i].flip(); } } - + private boolean shouldRenderMesh(Mesh mesh) { - if((Config.maxMeshesPerFrame == -1 || renderedMeshes < Config.maxMeshesPerFrame)) { - if((!isFogEnabled() && !Config.fogOcclusionWithoutFog) - || Config.fogOcclusion == !Config.fogOcclusion - || mesh.distSq( - eyePosX / 16.0, - mesh.y + 0.5, - eyePosZ / 16.0) - < Math.pow((fogStartEnd.get(1)) / 16.0 + 1.0, 2)) { + if ((Config.maxMeshesPerFrame == -1 || renderedMeshes < Config.maxMeshesPerFrame)) { + if ((!isFogEnabled() && !Config.fogOcclusionWithoutFog) + || Config.fogOcclusion == !Config.fogOcclusion + || mesh.distSq( + eyePosX / 16.0, + mesh.y + 0.5, + eyePosZ / 16.0) + < Math.pow((fogStartEnd.get(1)) / 16.0 + 1.0, 2)) { return true; } } return false; } - + private void mainLoop() { - if(Minecraft.getMinecraft().playerController.netClientHandler.doneLoadingTerrain) { - for(Iterator> it = loadedRegionsMap.entrySet().iterator(); it.hasNext();) { + if (Minecraft.getMinecraft().playerController.netClientHandler.doneLoadingTerrain) { + for (Iterator> it = loadedRegionsMap.entrySet().iterator(); it.hasNext(); ) { Entry kv = it.next(); NeoRegion v = kv.getValue(); - - if(v.shouldDelete()) { + + if (v.shouldDelete()) { v.destroy(); it.remove(); } else { @@ -242,42 +239,42 @@ private void mainLoop() { } } } - + private void handleKeyboard() { - if(Config.debugPrefix == 0 || (Config.debugPrefix != -1 && Keyboard.isKeyDown(Config.debugPrefix))) { - if(CheatHelper.canCheat()) { - if(Keyboard.isKeyDown(Keyboard.KEY_F) && !wasDown[Keyboard.KEY_F]) { + if (Config.debugPrefix == 0 || (Config.debugPrefix != -1 && Keyboard.isKeyDown(Config.debugPrefix))) { + if (CheatHelper.canCheat()) { + if (Keyboard.isKeyDown(Keyboard.KEY_F) && !wasDown[Keyboard.KEY_F]) { rendererActive = !rendererActive; } - if(Keyboard.isKeyDown(Keyboard.KEY_V) && !wasDown[Keyboard.KEY_V]) { + if (Keyboard.isKeyDown(Keyboard.KEY_V) && !wasDown[Keyboard.KEY_V]) { renderWorld = !renderWorld; } } - if(Keyboard.isKeyDown(Keyboard.KEY_R) && !wasDown[Keyboard.KEY_R]) { + if (Keyboard.isKeyDown(Keyboard.KEY_R) && !wasDown[Keyboard.KEY_R]) { reloadShader(); } - if(Keyboard.isKeyDown(Keyboard.KEY_M) && !wasDown[Keyboard.KEY_M]) { + if (Keyboard.isKeyDown(Keyboard.KEY_M) && !wasDown[Keyboard.KEY_M]) { showMemoryDebugger = !showMemoryDebugger; } - if(Keyboard.isKeyDown(Keyboard.KEY_P) && !wasDown[Keyboard.KEY_P]) { + if (Keyboard.isKeyDown(Keyboard.KEY_P) && !wasDown[Keyboard.KEY_P]) { Util.dumpTexture(); } - if(Keyboard.isKeyDown(Keyboard.KEY_LEFT) && !wasDown[Keyboard.KEY_LEFT]) { + if (Keyboard.isKeyDown(Keyboard.KEY_LEFT) && !wasDown[Keyboard.KEY_LEFT]) { reloadPending = true; } - if(Keyboard.isKeyDown(Keyboard.KEY_RIGHT) && !wasDown[Keyboard.KEY_RIGHT]) { - if(rendererSpeedup == 0) { + if (Keyboard.isKeyDown(Keyboard.KEY_RIGHT) && !wasDown[Keyboard.KEY_RIGHT]) { + if (rendererSpeedup == 0) { rendererSpeedup = 300; } else { rendererSpeedup = 0; } } } - for(int i = 0; i < 256; i++) { + for (int i = 0; i < 256; i++) { wasDown[i] = Keyboard.isKeyDown(i); } } - + FloatBuffer modelView = BufferUtils.createFloatBuffer(16); FloatBuffer projBuf = BufferUtils.createFloatBuffer(16); IntBuffer viewportBuf = BufferUtils.createIntBuffer(16); @@ -287,76 +284,100 @@ private void handleKeyboard() { Matrix4f modelViewMatrix = new Matrix4f(); Matrix4f modelViewMatrixInv = new Matrix4f(); Matrix4f projMatrix = new Matrix4f(); - + private void render(int pass, double alpha) { int shader = getShaderProgram(pass); - - if(shader == 0) return; - - glBindVertexArray(VAO); - glUseProgram(shader); - updateUniforms(alpha, pass); - - if(isWireframeEnabled()) { + + if (shader == 0) return; + + glBindVertexArray(VAO); + + if (!Compat.isShaders()) { + glUseProgram(shader); + updateUniforms(alpha, pass); + } + + if (isWireframeEnabled()) { GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_LINE); } - - int u_renderOffset = glGetUniformLocation(getShaderProgram(pass), "renderOffset"); - + + int u_renderOffset = -1; + if (!Compat.isShaders()) { + u_renderOffset = glGetUniformLocation(getShaderProgram(pass), "renderOffset"); + } + int oldLimit = piFirst[pass].limit(); - + int order = pass == 0 ? 1 : -1; - for(int regionI = order == 1 ? 0 : loadedRegionsList.size() - 1; regionI >= 0 && regionI < loadedRegionsList.size(); regionI += order) { + for (int regionI = order == 1 ? 0 : loadedRegionsList.size() - 1; regionI >= 0 && regionI < loadedRegionsList.size(); regionI += order) { NeoRegion.RenderData region = loadedRegionsList.get(regionI).getRenderData(); Util.setPositionAndLimit(piFirst[pass], region.batchFirst[pass], region.batchLimit[pass]); Util.setPositionAndLimit(piCount[pass], region.batchFirst[pass], region.batchLimit[pass]); - - glUniform3f(u_renderOffset, (float)(region.originX - eyePosX), (float)(region.originY - eyePosY), (float)(region.originZ - eyePosZ)); + + if (Compat.isShaders()) { + GL11.glMatrixMode(GL_MODELVIEW); + + val offsetX = (float) (region.originX - eyePosX); + val offsetY = (float) ((region.originY - eyePosY) + 0.12); + val offsetZ = (float) (region.originZ - eyePosZ); + + GL11.glPushMatrix(); + GL11.glTranslatef(offsetX, offsetY, offsetZ); + } else { + glUniform3f(u_renderOffset, (float) (region.originX - eyePosX), (float) (region.originY - eyePosY), (float) (region.originZ - eyePosZ)); + } + glMultiDrawArrays(GL_QUADS, piFirst[pass], piCount[pass]); + + if (Compat.isShaders()) + GL11.glPopMatrix(); } Util.setPositionAndLimit(piFirst[pass], 0, oldLimit); Util.setPositionAndLimit(piCount[pass], 0, oldLimit); - - if(isWireframeEnabled()) { + + if (isWireframeEnabled()) { GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL); } - + + if (!Compat.isShaders()) { + glUseProgram(0); + } + glBindVertexArray(0); - glUseProgram(0); } - + private void updateGLValues() { glGetFloat(GL_MODELVIEW_MATRIX, modelView); - + glGetFloat(GL_PROJECTION_MATRIX, projBuf); - + glGetInteger(GL_VIEWPORT, viewportBuf); - + projMatrix.load(projBuf); projBuf.flip(); projMatrix.invert(); projMatrix.store(projInvBuf); projInvBuf.flip(); - + modelViewMatrix.load(modelView); modelView.flip(); modelViewMatrixInv.load(modelViewMatrix).invert(); - + fogColorBuf.limit(16); glGetFloat(GL_FOG_COLOR, fogColorBuf); fogColorBuf.limit(4); - + fogStartEnd.put(glGetFloat(GL_FOG_START)); fogStartEnd.put(glGetFloat(GL_FOG_END)); - + fogStartEnd.flip(); - + fogEnabled = GL11.glIsEnabled(GL11.GL_FOG) && !OFUtil.isFogOff(); } - + private void updateUniforms(double alpha, int pass) { int shaderProgram = getShaderProgram(pass); - + int u_modelView = glGetUniformLocation(shaderProgram, "modelView"); int u_proj = glGetUniformLocation(shaderProgram, "proj"); int u_playerPos = glGetUniformLocation(shaderProgram, "playerPos"); @@ -374,17 +395,17 @@ private void updateUniforms(double alpha, int pass) { int u_fogStartEnd = glGetUniformLocation(shaderProgram, "fogStartEnd"); int u_fogMode = glGetUniformLocation(shaderProgram, "fogMode"); int u_fogDensity = glGetUniformLocation(shaderProgram, "fogDensity"); - + glUniformMatrix4(u_modelView, false, modelView); glUniformMatrix4(u_proj, false, projBuf); glUniformMatrix4(u_projInv, false, projInvBuf); - glUniform4f(u_viewport, viewportBuf.get(0),viewportBuf.get(1),viewportBuf.get(2),viewportBuf.get(3)); + glUniform4f(u_viewport, viewportBuf.get(0), viewportBuf.get(1), viewportBuf.get(2), viewportBuf.get(3)); glUniform4(u_fogColor, fogColorBuf); glUniform2(u_fogStartEnd, fogStartEnd); glUniform1i(u_fogMode, glGetInteger(GL_FOG_MODE)); glUniform1f(u_fogDensity, glGetFloat(GL_FOG_DENSITY)); - glUniform3f(u_playerPos, (float)eyePosX, (float)eyePosY, (float)eyePosZ); + glUniform3f(u_playerPos, (float) eyePosX, (float) eyePosY, (float) eyePosZ); if (Compat.RPLE()) { //TODO connect to RPLE gl api (once that exists) @@ -395,7 +416,7 @@ private void updateUniforms(double alpha, int pass) { } else { glUniform1i(u_light, 1); } - + modelView.position(0); projBuf.position(0); viewportBuf.position(0); @@ -434,125 +455,180 @@ public boolean init() { attributes.addAttribute("BRIGHTNESS_GREEN", 2, 2, GL_SHORT); attributes.addAttribute("BRIGHTNESS_BLUE", 2, 2, GL_SHORT); } - + reloadShader(); - + VAO = glGenVertexArrays(); glBindVertexArray(VAO); - + mem = new GPUMemoryManager(); - + glBindBuffer(GL_ARRAY_BUFFER, mem.VBO); - attributes.enable(); - - for(int i = 0; i < 2; i++) { + // position 3 floats 12 bytes offset 0 + // texture 2 floats 8 bytes offset 12 + // color 4 bytes 4 bytes offset 20 + // brightness 2 shorts 4 bytes offset 24 + // entitydata 3 shorts 6 bytes offset 28 + // 2 bytes + // normal 3 floats 12 bytes offset 36 + // tangent 4 floats 16 bytes offset 48 + // midtexture 2 floats 8 bytes offset 64 + if (Compat.isShaders()) { + val stride = 72; + val entityAttrib = 10; + val midTexCoordAttrib = 11; + val tangentAttrib = 12; + + // position 3 floats 12 bytes offset 0 + GL11.glVertexPointer(3, GL11.GL_FLOAT, stride, 0); + GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY); + + // texture 2 floats 8 bytes offset 12 + GL11.glTexCoordPointer(2, GL11.GL_FLOAT, stride, 12); + GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY); + + // color 4 bytes 4 bytes offset 20 + GL11.glColorPointer(4, GL11.GL_UNSIGNED_BYTE, stride, 20); + GL11.glEnableClientState(GL11.GL_COLOR_ARRAY); + + // brightness 2 shorts 4 bytes offset 24 + OpenGlHelper.setClientActiveTexture(OpenGlHelper.lightmapTexUnit); + GL11.glTexCoordPointer(2, GL11.GL_SHORT, stride, 24); + GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY); + OpenGlHelper.setClientActiveTexture(OpenGlHelper.defaultTexUnit); + + // entitydata 3 shorts 6 bytes offset 28 + GL20.glVertexAttribPointer(entityAttrib, 3, GL11.GL_SHORT, false, stride, 28); + GL20.glEnableVertexAttribArray(entityAttrib); + + // normal 3 floats 12 bytes offset 36 + GL11.glNormalPointer(GL11.GL_FLOAT, stride, 36); + GL11.glEnableClientState(GL11.GL_NORMAL_ARRAY); + + // tangent 4 floats 16 bytes offset 48 + GL20.glVertexAttribPointer(tangentAttrib, 4, GL11.GL_FLOAT, false, stride, 48); + GL20.glEnableVertexAttribArray(tangentAttrib); + + // midtexture 2 floats 8 bytes offset 64 + GL13.glClientActiveTexture(GL13.GL_TEXTURE3); + GL11.glTexCoordPointer(2, GL11.GL_FLOAT, stride, 64); + GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY); + OpenGlHelper.setClientActiveTexture(OpenGlHelper.defaultTexUnit); + + ARBVertexShader.glVertexAttribPointerARB(midTexCoordAttrib, 2, GL11.GL_FLOAT, false, stride, 64); + ARBVertexShader.glEnableVertexAttribArrayARB(midTexCoordAttrib); + } else { + attributes.enable(); + } + + for (int i = 0; i < 2; i++) { piFirst[i] = BufferUtils.createIntBuffer(MAX_MESHES); piFirst[i].flip(); piCount[i] = BufferUtils.createIntBuffer(MAX_MESHES); piCount[i].flip(); } - + glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); - + return true; } public int getStride() { return attributes.stride(); } - + public void reloadShader(int pass, AttributeSet attributeSet) { - for(int hasFog = 0; hasFog <= 1; hasFog++) { + for (int hasFog = 0; hasFog <= 1; hasFog++) { Map defines = new HashMap<>(); - if(hasFog == 1) { + if (hasFog == 1) { defines.put("RENDER_FOG", ""); } - if(Config.shortUV) { + if (Config.shortUV) { defines.put("SHORT_UV", ""); } if (Compat.RPLE()) { defines.put("RPLE", ""); } - if(pass == 0) { + if (pass == 0) { defines.put("PASS_0", ""); } attributeSet.addDefines(defines); - + boolean errors = false; - + int vertexShader; vertexShader = glCreateShader(GL_VERTEX_SHADER); - + glShaderSource(vertexShader, Preprocessor.preprocess(Util.readFile("shaders/chunk.vert"), defines)); glCompileShader(vertexShader); - - if(glGetShaderi(vertexShader, GL_COMPILE_STATUS) == 0) { + + if (glGetShaderi(vertexShader, GL_COMPILE_STATUS) == 0) { System.out.println("Error compiling vertex shader: " + glGetShaderInfoLog(vertexShader, 256)); errors = true; } - + int fragmentShader; fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); - + glShaderSource(fragmentShader, Preprocessor.preprocess(Util.readFile("shaders/chunk.frag"), defines)); glCompileShader(fragmentShader); - - if(glGetShaderi(fragmentShader, GL_COMPILE_STATUS) == 0) { + + if (glGetShaderi(fragmentShader, GL_COMPILE_STATUS) == 0) { System.out.println("Error compiling fragment shader: " + glGetShaderInfoLog(fragmentShader, 256)); errors = true; } - + int newShaderProgram = glCreateProgram(); glAttachShader(newShaderProgram, vertexShader); glAttachShader(newShaderProgram, fragmentShader); glLinkProgram(newShaderProgram); - - if(glGetProgrami(newShaderProgram, GL_LINK_STATUS) == 0) { + + if (glGetProgrami(newShaderProgram, GL_LINK_STATUS) == 0) { System.out.println("Error linking shader: " + glGetShaderInfoLog(newShaderProgram, 256)); errors = true; } - - if(!errors) { + + if (!errors) { ((hasFog == 1) ? shaderProgramsFog : shaderProgramsNoFog)[pass] = newShaderProgram; } - + glDeleteShader(vertexShader); glDeleteShader(fragmentShader); } } - + public void reloadShader() { reloadShader(0, attributes); reloadShader(1, attributes); } - + public void destroy() { - if(!hasInited) return; - + if (!hasInited) return; + glDeleteProgram(shaderProgramsFog[0]); glDeleteProgram(shaderProgramsFog[1]); glDeleteProgram(shaderProgramsNoFog[0]); glDeleteProgram(shaderProgramsNoFog[1]); glDeleteVertexArrays(VAO); mem.destroy(); - + ChunkMesh.instances = 0; ChunkMesh.usedRAM = 0; } - + public void onWorldRendererChanged(WorldRenderer wr, WorldRendererChange change) { int x = Math.floorDiv(wr.posX, 16); int y = Math.floorDiv(wr.posY, 16); int z = Math.floorDiv(wr.posZ, 16); NeoChunk neoChunk = getNeoChunk(x, z); - + neoChunk.isSectionVisible[y] = change == WorldRendererChange.VISIBLE; - if(change == WorldRendererChange.DELETED) { + if (change == WorldRendererChange.DELETED) { removeMesh(neoChunk.chunkMeshes[y]); - if(neoChunk.chunkMeshes[y] != null) { + if (neoChunk.chunkMeshes[y] != null) { neoChunk.chunkMeshes[y].destroy(); neoChunk.chunkMeshes[y] = null; neoChunk.region.meshes--; @@ -560,63 +636,63 @@ public void onWorldRendererChanged(WorldRenderer wr, WorldRendererChange change) } neoChunkChanged(neoChunk); } - + public void onWorldRendererPost(WorldRenderer wr, boolean sort) { int x = Math.floorDiv(wr.posX, 16); int y = Math.floorDiv(wr.posY, 16); int z = Math.floorDiv(wr.posZ, 16); - - if(Minecraft.getMinecraft().theWorld.getChunkFromChunkCoords(x, z).isChunkLoaded) { + + if (Minecraft.getMinecraft().theWorld.getChunkFromChunkCoords(x, z).isChunkLoaded) { NeoChunk neoChunk = getNeoChunk(x, z); - neoChunk.isSectionVisible[y] = ((IWorldRenderer)wr).isDrawn(); - neoChunk.putChunkMeshes(y, ((IWorldRenderer)wr).getChunkMeshes(), sort); + neoChunk.isSectionVisible[y] = ((IWorldRenderer) wr).isDrawn(); + neoChunk.putChunkMeshes(y, ((IWorldRenderer) wr).getChunkMeshes(), sort); } } - + public void onRenderFog() { forceRenderFog = false; } - + private NeoChunk getNeoChunk(int chunkX, int chunkZ) { return getRegionContaining(chunkX, chunkZ).getChunkAbsolute(chunkX, chunkZ); } - + private NeoRegion getRegionContaining(int chunkX, int chunkZ) { int regionX = Math.floorDiv(chunkX, NeoRegion.SIZE); int regionZ = Math.floorDiv(chunkZ, NeoRegion.SIZE); ChunkCoordIntPair key = new ChunkCoordIntPair(regionX, regionZ); - + NeoRegion region = loadedRegionsMap.get(key); - if(region == null) { + if (region == null) { region = NeoRegion.load(regionX, regionZ); loadedRegionsMap.put(key, region); } return region; } - + public void setVisible(NeoChunk chunk, boolean visible) { setVisible(chunk, visible, false); } - + public void setVisible(NeoChunk neoChunk, boolean visible, boolean forceCheck) { - if(!forceCheck && visible == neoChunk.visible) return; - + if (!forceCheck && visible == neoChunk.visible) return; + neoChunk.visible = visible; neoChunkChanged(neoChunk); } - + public void neoChunkChanged(NeoChunk neoChunk) { int newLOD = neoChunk.hasChunkMeshes() ? 2 : 0; - for(int y = 0; y < 16; y++) { - for(int pass = 0; pass < 2; pass++) { + for (int y = 0; y < 16; y++) { + for (int pass = 0; pass < 2; pass++) { ChunkMesh cm = neoChunk.chunkMeshes[y * 2 + pass]; - if(cm != null) { - if(neoChunk.isSectionVisible[y] && newLOD == 2) { - if(!cm.visible) { + if (cm != null) { + if (neoChunk.isSectionVisible[y] && newLOD == 2) { + if (!cm.visible) { setMeshVisible(cm, true); } } else { - if(cm.visible) { + if (cm.visible) { setMeshVisible(cm, false); } } @@ -624,14 +700,14 @@ public void neoChunkChanged(NeoChunk neoChunk) { } } } - + protected void setMeshVisible(Mesh mesh, boolean visible) { - if(mesh == null) return; - - if(mesh.visible != visible) { + if (mesh == null) return; + + if (mesh.visible != visible) { mesh.visible = visible; - - if(mesh.gpuStatus == GPUStatus.UNSENT) { + + if (mesh.gpuStatus == GPUStatus.UNSENT) { mem.sendMeshToGPU(mesh); NeoRegion region = getRegionContaining(mesh.x, mesh.z); region.getRenderData().getSentMeshes(mesh.pass).add(mesh); @@ -639,17 +715,17 @@ protected void setMeshVisible(Mesh mesh, boolean visible) { } } } - + public void removeMesh(Mesh mesh) { - if(mesh == null) return; - + if (mesh == null) return; + mem.deleteMeshFromGPU(mesh); - if(mesh.containingRegion != null) { + if (mesh.containingRegion != null) { mesh.containingRegion.getRenderData().getSentMeshes(mesh.pass).remove(mesh); } setMeshVisible(mesh, false); } - + public List getDebugText(boolean statusCommand) { List text = new ArrayList<>(); text.add( @@ -662,41 +738,41 @@ public List getDebugText(boolean statusCommand) { "Meshes: " + ChunkMesh.instances + " (" + ChunkMesh.usedRAM / 1024 / 1024 + "MB)", "Rendered: " + renderedMeshes + " (" + renderedQuads / 1000 + "KQ)" )); - if(rendererSpeedup > 0) { + if (rendererSpeedup > 0) { text.add(EnumChatFormatting.YELLOW + "(!) Renderer speedup active"); } - if(hasIncompatibilities) { + if (hasIncompatibilities) { text.add(EnumChatFormatting.YELLOW + "(!) Incompatibilities"); - if(!statusCommand) { + if (!statusCommand) { text.add(EnumChatFormatting.YELLOW + "Type '/neodymium status'"); } } return text; } - + private int getShaderProgram(int pass) { return ((forceRenderFog || isFogEnabled()) ? shaderProgramsFog : shaderProgramsNoFog)[pass]; } - + private boolean isFogEnabled() { - switch(Config.renderFog) { - case TRUE: - return true; - case FALSE: - return false; - default: - return fogEnabled; + switch (Config.renderFog) { + case TRUE: + return true; + case FALSE: + return false; + default: + return fogEnabled; } } - + private boolean shouldRenderInWorld(World world) { return world != null; } - + private static boolean isWireframeEnabled() { return Config.wireframe && CheatHelper.canCheat(); } - + public static enum WorldRendererChange { VISIBLE, INVISIBLE, DELETED } From 428f6d328fb15a5bd140cc15802179226602a1ed Mon Sep 17 00:00:00 2001 From: Ven Date: Fri, 5 Jan 2024 18:30:34 +0000 Subject: [PATCH 05/11] Skip frustrum check with shaders --- .../neodymium/mixin/MixinWorldRenderer.java | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/main/java/makamys/neodymium/mixin/MixinWorldRenderer.java b/src/main/java/makamys/neodymium/mixin/MixinWorldRenderer.java index a794931..42cedfe 100644 --- a/src/main/java/makamys/neodymium/mixin/MixinWorldRenderer.java +++ b/src/main/java/makamys/neodymium/mixin/MixinWorldRenderer.java @@ -1,17 +1,7 @@ package makamys.neodymium.mixin; -import java.util.Collections; -import java.util.List; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - import com.google.common.collect.Lists; - +import makamys.neodymium.Compat; import makamys.neodymium.Neodymium; import makamys.neodymium.ducks.ITessellator; import makamys.neodymium.ducks.IWorldRenderer; @@ -20,6 +10,15 @@ import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.entity.EntityLivingBase; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.Collections; +import java.util.List; /** Inserts hooks in WorldRenderer to listen for changes, and to grab the tessellator data right before rendering. */ @Mixin(WorldRenderer.class) @@ -150,6 +149,10 @@ private void notifyIfDrawnStatusChanged() { @Override public boolean isDrawn() { - return isInFrustum && (!skipRenderPass[0] || !skipRenderPass[1]); + if (!(skipRenderPass[0] && skipRenderPass[1])) + return true; + if (!Compat.isShaders()) + return isInFrustum; + return true; } } From 30f596f5a150b10be769e5d219fafdeaddfbc45a Mon Sep 17 00:00:00 2001 From: FalsePattern Date: Sun, 7 Jan 2024 12:44:30 +0100 Subject: [PATCH 06/11] stop renderlists logic from running at all --- .../neodymium/mixin/MixinRenderGlobal.java | 9 +++++--- .../neodymium/mixin/MixinWorldRenderer.java | 22 +++++++++++++++++++ .../neodymium/renderer/NeoRenderer.java | 22 +++++++++++-------- 3 files changed, 41 insertions(+), 12 deletions(-) diff --git a/src/main/java/makamys/neodymium/mixin/MixinRenderGlobal.java b/src/main/java/makamys/neodymium/mixin/MixinRenderGlobal.java index f3a4301..791dd5d 100644 --- a/src/main/java/makamys/neodymium/mixin/MixinRenderGlobal.java +++ b/src/main/java/makamys/neodymium/mixin/MixinRenderGlobal.java @@ -30,10 +30,13 @@ private void blockVanillaChunkRendering(int p1, double p2, CallbackInfo ci) { } } - @Inject(method = "renderSortedRenderers", at = @At(value = "HEAD")) - public void preRenderSortedRenderers(int startRenderer, int numRenderers, int renderPass, double partialTickTime, CallbackInfoReturnable cir) { + @Inject(method = "renderSortedRenderers", + at = @At(value = "HEAD"), + cancellable = true, + require = 1) + public void preRenderSortedRenderers(int startRenderer, int numRenderers, int renderPass, double partialTickTime, CallbackInfoReturnable cir) { if(Neodymium.isActive()) { - Neodymium.renderer.preRenderSortedRenderers(renderPass, partialTickTime, sortedWorldRenderers); + cir.setReturnValue(Neodymium.renderer.preRenderSortedRenderers(renderPass, partialTickTime, sortedWorldRenderers)); } } diff --git a/src/main/java/makamys/neodymium/mixin/MixinWorldRenderer.java b/src/main/java/makamys/neodymium/mixin/MixinWorldRenderer.java index 42cedfe..6ddf377 100644 --- a/src/main/java/makamys/neodymium/mixin/MixinWorldRenderer.java +++ b/src/main/java/makamys/neodymium/mixin/MixinWorldRenderer.java @@ -10,11 +10,14 @@ import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.entity.EntityLivingBase; + +import org.lwjgl.opengl.GL11; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.util.Collections; @@ -90,6 +93,25 @@ private void prePreRenderBlocks(int pass, CallbackInfo ci) { ChunkMesh.setCaptureTarget(cm); } } + + @Redirect(method = "preRenderBlocks", + at = @At(value = "INVOKE", + target = "Lorg/lwjgl/opengl/GL11;glNewList(II)V"), + require = 1) + private void noNewList(int list, int mode) { + if (!Neodymium.isActive()) { + GL11.glNewList(list, mode); + } + } + + @Redirect(method = "postRenderBlocks", + at = @At(value = "INVOKE", + target = "Lorg/lwjgl/opengl/GL11;glEndList()V"), + require = 1) + private void noEndList() { + if (!Neodymium.isActive()) + GL11.glEndList(); + } @Inject(method = "postRenderBlocks", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/Tessellator;draw()I")) private void prePostRenderBlocks(int pass, EntityLivingBase entity, CallbackInfo ci) { diff --git a/src/main/java/makamys/neodymium/renderer/NeoRenderer.java b/src/main/java/makamys/neodymium/renderer/NeoRenderer.java index 0cc7692..7d5928d 100644 --- a/src/main/java/makamys/neodymium/renderer/NeoRenderer.java +++ b/src/main/java/makamys/neodymium/renderer/NeoRenderer.java @@ -104,7 +104,8 @@ public NeoRenderer(World world) { Vector4f transformedOrigin = new Vector4f(); - public void preRenderSortedRenderers(int renderPass, double alpha, WorldRenderer[] sortedWorldRenderers) { + public int preRenderSortedRenderers(int renderPass, double alpha, WorldRenderer[] sortedWorldRenderers) { + int rendered = 0; if (hasInited) { if (renderPass == 0) { renderedMeshes = 0; @@ -149,11 +150,12 @@ public void preRenderSortedRenderers(int renderPass, double alpha, WorldRenderer if (rendererActive && renderWorld) { Minecraft.getMinecraft().entityRenderer.enableLightmap((double) alpha); - render(renderPass, alpha); + rendered += render(renderPass, alpha); Minecraft.getMinecraft().entityRenderer.disableLightmap((double) alpha); } } + return rendered; } public void onRenderTickEnd() { @@ -285,18 +287,17 @@ private void handleKeyboard() { Matrix4f modelViewMatrixInv = new Matrix4f(); Matrix4f projMatrix = new Matrix4f(); - private void render(int pass, double alpha) { - int shader = getShaderProgram(pass); - - if (shader == 0) return; - - glBindVertexArray(VAO); - + private int render(int pass, double alpha) { if (!Compat.isShaders()) { + int shader = getShaderProgram(pass); + + if (shader == 0) return 0; glUseProgram(shader); updateUniforms(alpha, pass); } + glBindVertexArray(VAO); + if (isWireframeEnabled()) { GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_LINE); } @@ -308,9 +309,11 @@ private void render(int pass, double alpha) { int oldLimit = piFirst[pass].limit(); + int rendered = 0; int order = pass == 0 ? 1 : -1; for (int regionI = order == 1 ? 0 : loadedRegionsList.size() - 1; regionI >= 0 && regionI < loadedRegionsList.size(); regionI += order) { NeoRegion.RenderData region = loadedRegionsList.get(regionI).getRenderData(); + rendered += region.batchLimit[pass] - region.batchFirst[pass]; Util.setPositionAndLimit(piFirst[pass], region.batchFirst[pass], region.batchLimit[pass]); Util.setPositionAndLimit(piCount[pass], region.batchFirst[pass], region.batchLimit[pass]); @@ -344,6 +347,7 @@ private void render(int pass, double alpha) { } glBindVertexArray(0); + return rendered; } private void updateGLValues() { From 988ac0f917d7842c137a30e894469eea587ccedb Mon Sep 17 00:00:00 2001 From: FalsePattern Date: Sun, 7 Jan 2024 13:51:03 +0100 Subject: [PATCH 07/11] more robust mixins --- .../mixin/MixinGameSettings_OptiFine.java | 7 +++- .../neodymium/mixin/MixinGuiMainMenu.java | 4 +- .../neodymium/mixin/MixinRenderGlobal.java | 13 ++++-- .../mixin/MixinRenderGlobal_OptiFine.java | 8 +++- .../neodymium/mixin/MixinTessellator.java | 5 ++- .../neodymium/mixin/MixinWorldRenderer.java | 41 ++++++++++++++----- 6 files changed, 60 insertions(+), 18 deletions(-) diff --git a/src/main/java/makamys/neodymium/mixin/MixinGameSettings_OptiFine.java b/src/main/java/makamys/neodymium/mixin/MixinGameSettings_OptiFine.java index 43fa0b9..2e3fb0d 100644 --- a/src/main/java/makamys/neodymium/mixin/MixinGameSettings_OptiFine.java +++ b/src/main/java/makamys/neodymium/mixin/MixinGameSettings_OptiFine.java @@ -1,5 +1,6 @@ package makamys.neodymium.mixin; +import org.spongepowered.asm.mixin.Dynamic; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Pseudo; import org.spongepowered.asm.mixin.Shadow; @@ -7,10 +8,12 @@ import makamys.neodymium.ducks.IMixinGameSettings_OptiFine; import net.minecraft.client.settings.GameSettings; -@Mixin(value = GameSettings.class, remap = false) +@Mixin(value = GameSettings.class, + remap = false) @Pseudo public class MixinGameSettings_OptiFine implements IMixinGameSettings_OptiFine { - + + @Dynamic @Shadow private int ofFogType; diff --git a/src/main/java/makamys/neodymium/mixin/MixinGuiMainMenu.java b/src/main/java/makamys/neodymium/mixin/MixinGuiMainMenu.java index 27f6b07..2851830 100644 --- a/src/main/java/makamys/neodymium/mixin/MixinGuiMainMenu.java +++ b/src/main/java/makamys/neodymium/mixin/MixinGuiMainMenu.java @@ -15,7 +15,9 @@ abstract class MixinGuiMainMenu { @Shadow private String splashText; - @Inject(method = "*", at = @At("RETURN")) + @Inject(method = "", + at = @At("RETURN"), + require = 1) private void postConstructor(CallbackInfo ci) { splashText = Neodymium.modifySplash(splashText); } diff --git a/src/main/java/makamys/neodymium/mixin/MixinRenderGlobal.java b/src/main/java/makamys/neodymium/mixin/MixinRenderGlobal.java index 791dd5d..c430bf6 100644 --- a/src/main/java/makamys/neodymium/mixin/MixinRenderGlobal.java +++ b/src/main/java/makamys/neodymium/mixin/MixinRenderGlobal.java @@ -23,7 +23,10 @@ abstract class MixinRenderGlobal { private boolean nd$isInsideUpdateRenderers; - @Inject(method = "renderAllRenderLists", at = @At(value = "HEAD"), cancellable = true) + @Inject(method = "renderAllRenderLists", + at = @At(value = "HEAD"), + cancellable = true, + require = 1) private void blockVanillaChunkRendering(int p1, double p2, CallbackInfo ci) { if(!Neodymium.shouldRenderVanillaWorld()) { ci.cancel(); @@ -40,12 +43,16 @@ public void preRenderSortedRenderers(int startRenderer, int numRenderers, int re } } - @Inject(method = "loadRenderers", at = @At(value = "HEAD")) + @Inject(method = "loadRenderers", + at = @At(value = "HEAD"), + require = 1) public void preLoadRenderers(CallbackInfo ci) { Neodymium.destroyRenderer(); } - @Inject(method = "updateRenderers", at = @At(value = "RETURN")) + @Inject(method = "updateRenderers", + at = @At(value = "RETURN"), + require = 1) public void speedUpChunkUpdatesForDebug(EntityLivingBase entity, boolean flag, CallbackInfoReturnable cir) { if(Neodymium.isActive() && !nd$isInsideUpdateRenderers) { nd$isInsideUpdateRenderers = true; diff --git a/src/main/java/makamys/neodymium/mixin/MixinRenderGlobal_OptiFine.java b/src/main/java/makamys/neodymium/mixin/MixinRenderGlobal_OptiFine.java index e79f4b7..8d491d0 100644 --- a/src/main/java/makamys/neodymium/mixin/MixinRenderGlobal_OptiFine.java +++ b/src/main/java/makamys/neodymium/mixin/MixinRenderGlobal_OptiFine.java @@ -3,6 +3,7 @@ import java.nio.IntBuffer; import org.lwjgl.opengl.GL11; +import org.spongepowered.asm.mixin.Dynamic; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; @@ -15,7 +16,12 @@ abstract class MixinRenderGlobal_OptiFine { // for OptiFine's Fast Render option - @Redirect(method = "renderSortedRenderersFast", at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/GL11;glCallLists(Ljava/nio/IntBuffer;)V"), remap=false) + @Dynamic + @Redirect(method = "renderSortedRenderersFast", + at = @At(value = "INVOKE", + target = "Lorg/lwjgl/opengl/GL11;glCallLists(Ljava/nio/IntBuffer;)V"), + remap=false, + require = 1) private void redirectRenderAllRenderLists(IntBuffer buffer) { if(Neodymium.shouldRenderVanillaWorld()) { GL11.glCallLists(buffer); diff --git a/src/main/java/makamys/neodymium/mixin/MixinTessellator.java b/src/main/java/makamys/neodymium/mixin/MixinTessellator.java index cdd4ffe..935b860 100644 --- a/src/main/java/makamys/neodymium/mixin/MixinTessellator.java +++ b/src/main/java/makamys/neodymium/mixin/MixinTessellator.java @@ -20,7 +20,10 @@ abstract class MixinTessellator implements ITessellator { @Shadow private boolean isDrawing; - @Inject(method = "draw", at = @At(value = "HEAD"), cancellable = true) + @Inject(method = "draw", + at = @At(value = "HEAD"), + cancellable = true, + require = 1) private void preDraw(CallbackInfoReturnable cir) { if(nd$captureMeshes) { ChunkMesh.preTessellatorDraw((Tessellator)(Object)this); diff --git a/src/main/java/makamys/neodymium/mixin/MixinWorldRenderer.java b/src/main/java/makamys/neodymium/mixin/MixinWorldRenderer.java index 6ddf377..4daa525 100644 --- a/src/main/java/makamys/neodymium/mixin/MixinWorldRenderer.java +++ b/src/main/java/makamys/neodymium/mixin/MixinWorldRenderer.java @@ -39,12 +39,16 @@ abstract class MixinWorldRenderer implements IWorldRenderer { private List nd$chunkMeshes; - @Inject(method = {"updateRenderer"}, at = @At(value = "HEAD")) + @Inject(method = {"updateRenderer"}, + at = @At(value = "HEAD"), + require = 1) private void preUpdateRenderer(CallbackInfo ci) { preUpdateRenderer(false); } - @Inject(method = {"updateRendererSort"}, at = @At(value = "HEAD")) + @Inject(method = {"updateRendererSort"}, + at = @At(value = "HEAD"), + require = 1) private void preUpdateRendererSort(CallbackInfo ci) { preUpdateRenderer(true); } @@ -62,12 +66,16 @@ private void preUpdateRenderer(boolean sort) { } } - @Inject(method = {"updateRenderer"}, at = @At(value = "RETURN")) + @Inject(method = {"updateRenderer"}, + at = @At(value = "RETURN"), + require = 1) private void postUpdateRenderer(CallbackInfo ci) { postUpdateRenderer(false); } - @Inject(method = {"updateRendererSort"}, at = @At(value = "RETURN")) + @Inject(method = {"updateRendererSort"}, + at = @At(value = "RETURN"), + require = 1) private void postUpdateRendererSort(CallbackInfo ci) { postUpdateRenderer(true); } @@ -84,7 +92,9 @@ private void postUpdateRenderer(boolean sort) { } } - @Inject(method = "preRenderBlocks", at = @At("HEAD")) + @Inject(method = "preRenderBlocks", + at = @At("HEAD"), + require = 1) private void prePreRenderBlocks(int pass, CallbackInfo ci) { if(Neodymium.isActive()) { ((ITessellator)Tessellator.instance).enableMeshCapturing(true); @@ -113,7 +123,10 @@ private void noEndList() { GL11.glEndList(); } - @Inject(method = "postRenderBlocks", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/Tessellator;draw()I")) + @Inject(method = "postRenderBlocks", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/client/renderer/Tessellator;draw()I"), + require = 1) private void prePostRenderBlocks(int pass, EntityLivingBase entity, CallbackInfo ci) { /*if(Neodymium.isActive()) { if(nd$chunkMeshes != null) { @@ -125,7 +138,9 @@ private void prePostRenderBlocks(int pass, EntityLivingBase entity, CallbackInfo }*/ } - @Inject(method = "postRenderBlocks", at = @At("RETURN")) + @Inject(method = "postRenderBlocks", + at = @At("RETURN"), + require = 1) private void postPostRenderBlocks(int pass, EntityLivingBase entity, CallbackInfo ci) { if(Neodymium.isActive()) { nd$chunkMeshes.get(pass).finishConstruction(); @@ -134,7 +149,9 @@ private void postPostRenderBlocks(int pass, EntityLivingBase entity, CallbackInf } } - @Inject(method = "setDontDraw", at = @At(value = "HEAD")) + @Inject(method = "setDontDraw", + at = @At(value = "HEAD"), + require = 1) private void preSetDontDraw(CallbackInfo ci) { if(Neodymium.isActive()) { Neodymium.renderer.onWorldRendererChanged(WorldRenderer.class.cast(this), NeoRenderer.WorldRendererChange.DELETED); @@ -146,12 +163,16 @@ public List getChunkMeshes() { return nd$chunkMeshes; } - @Inject(method = "updateInFrustum", at = @At(value = "HEAD")) + @Inject(method = "updateInFrustum", + at = @At(value = "HEAD"), + require = 1) private void preUpdateInFrustum(CallbackInfo ci) { saveDrawnStatus(); } - @Inject(method = "updateInFrustum", at = @At(value = "RETURN")) + @Inject(method = "updateInFrustum", + at = @At(value = "RETURN"), + require = 1) private void postUpdateInFrustum(CallbackInfo ci) { notifyIfDrawnStatusChanged(); } From 4412a9fe29d765deb200ddbf08caef6a150fa339 Mon Sep 17 00:00:00 2001 From: FalsePattern Date: Sun, 7 Jan 2024 17:50:15 +0100 Subject: [PATCH 08/11] RPLE shader compat --- project.gradle | 3 ++ src/main/java/makamys/neodymium/Compat.java | 11 ++++- .../makamys/neodymium/renderer/ChunkMesh.java | 8 +++- .../makamys/neodymium/renderer/MeshQuad.java | 26 +++++++++-- .../neodymium/renderer/NeoRenderer.java | 43 ++++++++++++++++--- 5 files changed, 77 insertions(+), 14 deletions(-) diff --git a/project.gradle b/project.gradle index 271901b..c6d2f72 100644 --- a/project.gradle +++ b/project.gradle @@ -17,6 +17,9 @@ repositories { dependencies { compileOnly("com.falsepattern:triangulator-mc1.7.10:1.7.0:api") + + compileOnly("com.falsepattern:rple-mc1.7.10:1.0.0-rc8:api") + compileOnly("com.falsepattern:falsetweaks-mc1.7.10:2.7.4:api") } runClient { diff --git a/src/main/java/makamys/neodymium/Compat.java b/src/main/java/makamys/neodymium/Compat.java index 6343e14..debb6d6 100644 --- a/src/main/java/makamys/neodymium/Compat.java +++ b/src/main/java/makamys/neodymium/Compat.java @@ -11,7 +11,6 @@ import com.falsepattern.triangulator.api.ToggleableTessellator; import cpw.mods.fml.common.Loader; import makamys.neodymium.config.Config; -import makamys.neodymium.util.OFUtil; import makamys.neodymium.util.virtualjar.IVirtualJar; import makamys.neodymium.util.virtualjar.VirtualJar; import net.minecraft.client.Minecraft; @@ -27,6 +26,8 @@ public class Compat { private static int notEnoughVRAMAmountMB = -1; private static boolean RPLE; + + private static boolean FALSE_TWEAKS; public static void init() { isGL33Supported = GLContext.getCapabilities().OpenGL33; @@ -38,12 +39,20 @@ public static void init() { if (Loader.isModLoaded("rple")) { RPLE = true; } + + if (Loader.isModLoaded("falsetweaks")) { + FALSE_TWEAKS = true; + } } public static boolean RPLE() { return RPLE; } + public static boolean FalseTweaks() { + return FALSE_TWEAKS; + } + private static boolean shadersEnabled; public static boolean isShaders() { diff --git a/src/main/java/makamys/neodymium/renderer/ChunkMesh.java b/src/main/java/makamys/neodymium/renderer/ChunkMesh.java index 72c20ff..decc90d 100644 --- a/src/main/java/makamys/neodymium/renderer/ChunkMesh.java +++ b/src/main/java/makamys/neodymium/renderer/ChunkMesh.java @@ -110,8 +110,12 @@ private void addTessellatorData(Tessellator t) { int verticesPerPrimitive = t.drawMode == GL11.GL_QUADS ? 4 : 3; - int tessellatorVertexSize = Compat.isShaders() ? 18 : Compat.RPLE() ? 12 : 8; - + int tessellatorVertexSize = 8; + if (Compat.isShaders()) + tessellatorVertexSize += 10; + if (Compat.RPLE()) + tessellatorVertexSize += 4; + for(int quadI = 0; quadI < t.vertexCount / verticesPerPrimitive; quadI++) { MeshQuad quad = quadBuf.next(); quad.setState(t.rawBuffer, tessellatorVertexSize, quadI * (verticesPerPrimitive * tessellatorVertexSize), FLAGS, t.drawMode, NeoRegion.toRelativeOffset(-t.xOffset), NeoRegion.toRelativeOffset(-t.yOffset), NeoRegion.toRelativeOffset(-t.zOffset)); diff --git a/src/main/java/makamys/neodymium/renderer/MeshQuad.java b/src/main/java/makamys/neodymium/renderer/MeshQuad.java index f748488..4e72535 100644 --- a/src/main/java/makamys/neodymium/renderer/MeshQuad.java +++ b/src/main/java/makamys/neodymium/renderer/MeshQuad.java @@ -43,6 +43,9 @@ public class MeshQuad { public float[] um = new float[4]; public float[] vm = new float[4]; + public float[] ue = new float[4]; + public float[] ve = new float[4]; + public boolean deleted; public QuadNormal normal; @@ -80,6 +83,12 @@ private void read(int[] rawBuffer, int tessellatorVertexSize, int offset, float wt[vi] = Float.intBitsToFloat(rawBuffer[i + 15]); um[vi] = Float.intBitsToFloat(rawBuffer[i + 16]); vm[vi] = Float.intBitsToFloat(rawBuffer[i + 17]); + if (Compat.RPLE()) { + bsG[vi] = rawBuffer[i + 18]; + bsB[vi] = rawBuffer[i + 19]; + ue[vi] = Float.intBitsToFloat(rawBuffer[i + 20]); + ve[vi] = Float.intBitsToFloat(rawBuffer[i + 21]); + } } else { bs[vi] = flags.hasBrightness ? rawBuffer[i + 7] : DEFAULT_BRIGHTNESS; @@ -108,6 +117,10 @@ private void read(int[] rawBuffer, int tessellatorVertexSize, int offset, float if (Compat.RPLE()) { bsG[3] = bsG[2]; bsB[3] = bsB[2]; + if (Compat.isShaders()) { + ue[3] = ue[2]; + ve[3] = ve[2]; + } } cs[3] = cs[2]; if (Compat.isShaders()) { @@ -173,10 +186,6 @@ public void writeToBuffer(BufferWriter out, int expectedStride) throws IOExcepti out.writeInt(c); out.writeInt(bs[vi]); - if (Compat.RPLE()) { - out.writeInt(bsG[vi]); - out.writeInt(bsB[vi]); - } if (Compat.isShaders()) { out.writeInt(e1[vi]); @@ -191,6 +200,15 @@ public void writeToBuffer(BufferWriter out, int expectedStride) throws IOExcepti out.writeFloat(um[vi]); out.writeFloat(vm[vi]); } + + if (Compat.RPLE()) { + out.writeInt(bsG[vi]); + out.writeInt(bsB[vi]); + if (Compat.isShaders()) { + out.writeFloat(ue[vi]); + out.writeFloat(ve[vi]); + } + } assert out.position() % expectedStride == 0; diff --git a/src/main/java/makamys/neodymium/renderer/NeoRenderer.java b/src/main/java/makamys/neodymium/renderer/NeoRenderer.java index 7d5928d..ed8be73 100644 --- a/src/main/java/makamys/neodymium/renderer/NeoRenderer.java +++ b/src/main/java/makamys/neodymium/renderer/NeoRenderer.java @@ -1,5 +1,8 @@ package makamys.neodymium.renderer; +import com.falsepattern.falsetweaks.api.triangulator.VertexAPI; +import com.falsepattern.rple.api.client.RPLELightMapUtil; +import com.falsepattern.rple.api.client.RPLEShaderConstants; import lombok.val; import makamys.neodymium.Compat; import makamys.neodymium.Neodymium; @@ -430,7 +433,7 @@ private void updateUniforms(double alpha, int pass) { } /** - * @implSpec The attributes here need to be kept in sync with {@link MeshQuad#writeToBuffer(BufferWriter)} + * @implSpec The attributes here need to be kept in sync with {@link MeshQuad#writeToBuffer(BufferWriter, int)} */ public boolean init() { // The average mesh is 60 KB. Let's be safe and assume 8 KB per mesh. @@ -447,17 +450,27 @@ public boolean init() { attributes.addAttribute("TEXTURE", 2, 4, GL_FLOAT); } attributes.addAttribute("COLOR", 4, 1, GL_UNSIGNED_BYTE); - attributes.addAttribute("BRIGHTNESS", 2, 2, GL_SHORT); + if (Compat.RPLE()) { + attributes.addAttribute("BRIGHTNESS_RED", 2, 2, GL_SHORT); + } else { + attributes.addAttribute("BRIGHTNESS", 2, 2, GL_SHORT); + } if (Compat.isShaders()) { attributes.addAttribute("ENTITY_DATA_1", 1, 4, GL_UNSIGNED_INT); attributes.addAttribute("ENTITY_DATA_2", 1, 4, GL_UNSIGNED_INT); attributes.addAttribute("NORMAL", 3, 4, GL_FLOAT); attributes.addAttribute("TANGENT", 4, 4, GL_FLOAT); attributes.addAttribute("MIDTEXTURE", 2, 4, GL_FLOAT); - } else if (Compat.RPLE()) { - attributes.addAttribute("BRIGHTNESS_RED", 2, 2, GL_SHORT); - attributes.addAttribute("BRIGHTNESS_GREEN", 2, 2, GL_SHORT); - attributes.addAttribute("BRIGHTNESS_BLUE", 2, 2, GL_SHORT); + if (Compat.RPLE()) { + attributes.addAttribute("BRIGHTNESS_GREEN", 2, 2, GL_SHORT); + attributes.addAttribute("BRIGHTNESS_BLUE", 2, 2, GL_SHORT); + attributes.addAttribute("EDGE_TEX", 2, 4, GL_FLOAT); + } + } else { + if (Compat.RPLE()) { + attributes.addAttribute("BRIGHTNESS_GREEN", 2, 2, GL_SHORT); + attributes.addAttribute("BRIGHTNESS_BLUE", 2, 2, GL_SHORT); + } } reloadShader(); @@ -479,7 +492,12 @@ public boolean init() { // tangent 4 floats 16 bytes offset 48 // midtexture 2 floats 8 bytes offset 64 if (Compat.isShaders()) { - val stride = 72; + int stride; + if (Compat.FalseTweaks()) { + stride = VertexAPI.recomputeVertexInfo(18, 4); + } else { + stride = 72; + } val entityAttrib = 10; val midTexCoordAttrib = 11; val tangentAttrib = 12; @@ -522,6 +540,17 @@ public boolean init() { ARBVertexShader.glVertexAttribPointerARB(midTexCoordAttrib, 2, GL11.GL_FLOAT, false, stride, 64); ARBVertexShader.glEnableVertexAttribArrayARB(midTexCoordAttrib); + + if (Compat.RPLE()) { + RPLELightMapUtil.enableVertexPointersVBO(); + ARBVertexShader.glVertexAttribPointerARB(RPLEShaderConstants.edgeTexCoordAttrib, + 2, + GL_FLOAT, + false, + stride, + 80); + ARBVertexShader.glEnableVertexAttribArrayARB(RPLEShaderConstants.edgeTexCoordAttrib); + } } else { attributes.enable(); } From 25f758025a2ffbda3ef9dd220cb9813c14836903 Mon Sep 17 00:00:00 2001 From: FalsePattern Date: Sun, 7 Jan 2024 20:43:47 +0000 Subject: [PATCH 09/11] cleanup run Co-authored-by: Ven --- src/main/java/makamys/neodymium/Compat.java | 44 +- .../neodymium/mixin/MixinWorldRenderer.java | 2 +- .../makamys/neodymium/renderer/ChunkMesh.java | 33 +- .../makamys/neodymium/renderer/MeshQuad.java | 461 ++++++++++++++---- .../neodymium/renderer/NeoRenderer.java | 254 ++++++---- 5 files changed, 544 insertions(+), 250 deletions(-) diff --git a/src/main/java/makamys/neodymium/Compat.java b/src/main/java/makamys/neodymium/Compat.java index debb6d6..40feb47 100644 --- a/src/main/java/makamys/neodymium/Compat.java +++ b/src/main/java/makamys/neodymium/Compat.java @@ -1,13 +1,5 @@ package makamys.neodymium; -import static makamys.neodymium.Constants.LOGGER; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.util.List; - -import org.lwjgl.opengl.GLContext; - import com.falsepattern.triangulator.api.ToggleableTessellator; import cpw.mods.fml.common.Loader; import makamys.neodymium.config.Config; @@ -16,6 +8,13 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.settings.GameSettings; +import org.lwjgl.opengl.GLContext; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.util.List; + +import static makamys.neodymium.Constants.LOGGER; public class Compat { @@ -25,9 +24,11 @@ public class Compat { private static int notEnoughVRAMAmountMB = -1; - private static boolean RPLE; + private static boolean IS_RPLE_PRESENT; + + private static boolean IS_FALSE_TWEAKS_PRESENT; - private static boolean FALSE_TWEAKS; + private static boolean isShadersEnabled; public static void init() { isGL33Supported = GLContext.getCapabilities().OpenGL33; @@ -37,35 +38,34 @@ public static void init() { } if (Loader.isModLoaded("rple")) { - RPLE = true; + IS_RPLE_PRESENT = true; } if (Loader.isModLoaded("falsetweaks")) { - FALSE_TWEAKS = true; + IS_FALSE_TWEAKS_PRESENT = true; } } - public static boolean RPLE() { - return RPLE; + public static boolean isRPLEModPresent() { + return IS_RPLE_PRESENT; } - public static boolean FalseTweaks() { - return FALSE_TWEAKS; + public static boolean isFalseTweaksModPresent() { + return IS_FALSE_TWEAKS_PRESENT; } - private static boolean shadersEnabled; - public static boolean isShaders() { - return shadersEnabled; + public static boolean isOptiFineShadersEnabled() { + return isShadersEnabled; } - public static void updateShadersState() { + public static void updateOptiFineShadersState() { try { Class shaders = Class.forName("shadersmod.client.Shaders"); try { String shaderPack = (String)shaders.getMethod("getShaderPackName").invoke(null); if(shaderPack != null) { - shadersEnabled = true; + isShadersEnabled = true; return; } } catch(Exception e) { @@ -75,7 +75,7 @@ public static void updateShadersState() { } catch (ClassNotFoundException e) { } - shadersEnabled = false; + isShadersEnabled = false; } private static void disableTriangulator() { diff --git a/src/main/java/makamys/neodymium/mixin/MixinWorldRenderer.java b/src/main/java/makamys/neodymium/mixin/MixinWorldRenderer.java index 4daa525..16c4ea6 100644 --- a/src/main/java/makamys/neodymium/mixin/MixinWorldRenderer.java +++ b/src/main/java/makamys/neodymium/mixin/MixinWorldRenderer.java @@ -194,7 +194,7 @@ private void notifyIfDrawnStatusChanged() { public boolean isDrawn() { if (!(skipRenderPass[0] && skipRenderPass[1])) return true; - if (!Compat.isShaders()) + if (!Compat.isOptiFineShadersEnabled()) return isInFrustum; return true; } diff --git a/src/main/java/makamys/neodymium/renderer/ChunkMesh.java b/src/main/java/makamys/neodymium/renderer/ChunkMesh.java index decc90d..9d98bd3 100644 --- a/src/main/java/makamys/neodymium/renderer/ChunkMesh.java +++ b/src/main/java/makamys/neodymium/renderer/ChunkMesh.java @@ -2,7 +2,6 @@ import static makamys.neodymium.Constants.LOGGER; -import java.io.IOException; import java.nio.ByteBuffer; import java.nio.IntBuffer; import java.util.ArrayList; @@ -111,9 +110,9 @@ private void addTessellatorData(Tessellator t) { int verticesPerPrimitive = t.drawMode == GL11.GL_QUADS ? 4 : 3; int tessellatorVertexSize = 8; - if (Compat.isShaders()) + if (Compat.isOptiFineShadersEnabled()) tessellatorVertexSize += 10; - if (Compat.RPLE()) + if (Compat.isRPLEModPresent()) tessellatorVertexSize += 4; for(int quadI = 0; quadI < t.vertexCount / verticesPerPrimitive; quadI++) { @@ -190,26 +189,22 @@ private ByteBuffer createBuffer(List quads, int quadCount) { quads.sort(MESH_QUAD_RENDER_COMPARATOR); } - try { - int i = 0; - for(MeshQuad quad : quads) { - if(i < quadCount) { - if(MeshQuad.isValid(quad)) { - int subMeshStartIdx = sortByNormals ? QUAD_NORMAL_TO_NORMAL_ORDER[quad.normal.ordinal()] : 0; - if(subMeshStart[subMeshStartIdx] == -1) { - subMeshStart[subMeshStartIdx] = i; - } - quad.writeToBuffer(out, stride); - i++; - } else if(sortByNormals){ - break; + int i = 0; + for(MeshQuad quad : quads) { + if(i < quadCount) { + if(MeshQuad.isValid(quad)) { + int subMeshStartIdx = sortByNormals ? QUAD_NORMAL_TO_NORMAL_ORDER[quad.normal.ordinal()] : 0; + if(subMeshStart[subMeshStartIdx] == -1) { + subMeshStart[subMeshStartIdx] = i; } + quad.writeToBuffer(out, stride); + i++; + } else if(sortByNormals){ + break; } } - } catch(IOException e) { - e.printStackTrace(); } - + buffer.flip(); return buffer; diff --git a/src/main/java/makamys/neodymium/renderer/MeshQuad.java b/src/main/java/makamys/neodymium/renderer/MeshQuad.java index 4e72535..2a9fe2d 100644 --- a/src/main/java/makamys/neodymium/renderer/MeshQuad.java +++ b/src/main/java/makamys/neodymium/renderer/MeshQuad.java @@ -1,20 +1,20 @@ package makamys.neodymium.renderer; -import java.io.IOException; -import java.util.Locale; - import makamys.neodymium.Compat; -import org.lwjgl.opengl.GL11; -import org.lwjgl.util.vector.Vector3f; - import makamys.neodymium.config.Config; import makamys.neodymium.util.BufferWriter; import makamys.neodymium.util.Util; +import org.lwjgl.opengl.GL11; +import org.lwjgl.util.vector.Vector3f; + +import java.util.Locale; public class MeshQuad { private final static int DEFAULT_BRIGHTNESS = Util.createBrightness(15, 15); private final static int DEFAULT_COLOR = 0xFFFFFFFF; - + + //region common + public float[] xs = new float[4]; public float[] ys = new float[4]; public float[] zs = new float[4]; @@ -24,10 +24,18 @@ public class MeshQuad { // TODO normals? public int[] bs = new int[4]; - //RPLE compat. bs reused as RED + //endregion common + + //region RPLE + + // bs used as RED public int[] bsG = new int[4]; public int[] bsB = new int[4]; + //endregion RPLE + + //region Shaders + public int[] e1 = new int[4]; public int[] e2 = new int[4]; @@ -43,9 +51,15 @@ public class MeshQuad { public float[] um = new float[4]; public float[] vm = new float[4]; + //endregion Shaders + + //region Shaders + RPLE + public float[] ue = new float[4]; public float[] ve = new float[4]; + //endregion Shaders + RPLE + public boolean deleted; public QuadNormal normal; @@ -53,91 +67,245 @@ public class MeshQuad { private static Vector3f vectorA = new Vector3f(); private static Vector3f vectorB = new Vector3f(); private static Vector3f vectorC = new Vector3f(); - + + private void read(int[] rawBuffer, int tessellatorVertexSize, int offset, float offsetX, float offsetY, float offsetZ, int drawMode, ChunkMesh.Flags flags) { + boolean rple = Compat.isRPLEModPresent(); + boolean optiFineShaders = Compat.isOptiFineShadersEnabled(); + + if (rple && optiFineShaders) { + readRPLEAndShaders(rawBuffer, tessellatorVertexSize, offset, offsetX, offsetY, offsetZ, drawMode, flags); + } else if (optiFineShaders) { + readShaders(rawBuffer, tessellatorVertexSize, offset, offsetX, offsetY, offsetZ, drawMode, flags); + } else if (rple) { + readRPLE(rawBuffer, tessellatorVertexSize, offset, offsetX, offsetY, offsetZ, drawMode, flags); + } else { + readVanilla(rawBuffer, tessellatorVertexSize, offset, offsetX, offsetY, offsetZ, drawMode, flags); + } + } + + //region read implementations + + private void readRPLEAndShaders(int[] rawBuffer, int tessellatorVertexSize, int offset, float offsetX, float offsetY, float offsetZ, int drawMode, ChunkMesh.Flags flags) { + //RPLE and Shaders int vertices = drawMode == GL11.GL_TRIANGLES ? 3 : 4; for(int vi = 0; vi < vertices; vi++) { int i = offset + vi * tessellatorVertexSize; - - xs[vi] = Float.intBitsToFloat(rawBuffer[i + 0]) + offsetX; + + xs[vi] = Float.intBitsToFloat(rawBuffer[i]) + offsetX; ys[vi] = Float.intBitsToFloat(rawBuffer[i + 1]) + offsetY; zs[vi] = Float.intBitsToFloat(rawBuffer[i + 2]) + offsetZ; - + us[vi] = Float.intBitsToFloat(rawBuffer[i + 3]); vs[vi] = Float.intBitsToFloat(rawBuffer[i + 4]); cs[vi] = flags.hasColor ? rawBuffer[i + 5] : DEFAULT_COLOR; - // TODO normals? + bs[vi] = flags.hasBrightness ? rawBuffer[i + 6] : DEFAULT_BRIGHTNESS; + + e1[vi] = rawBuffer[i + 7]; + e2[vi] = rawBuffer[i + 8]; + + xn[vi] = Float.intBitsToFloat(rawBuffer[i + 9]); + yn[vi] = Float.intBitsToFloat(rawBuffer[i + 10]); + zn[vi] = Float.intBitsToFloat(rawBuffer[i + 11]); - if (Compat.isShaders()) { - bs[vi] = flags.hasBrightness ? rawBuffer[i + 6] : DEFAULT_BRIGHTNESS; - e1[vi] = rawBuffer[i + 7]; - e2[vi] = rawBuffer[i + 8]; - xn[vi] = Float.intBitsToFloat(rawBuffer[i + 9]); - yn[vi] = Float.intBitsToFloat(rawBuffer[i + 10]); - zn[vi] = Float.intBitsToFloat(rawBuffer[i + 11]); - xt[vi] = Float.intBitsToFloat(rawBuffer[i + 12]); - yt[vi] = Float.intBitsToFloat(rawBuffer[i + 13]); - zt[vi] = Float.intBitsToFloat(rawBuffer[i + 14]); - wt[vi] = Float.intBitsToFloat(rawBuffer[i + 15]); - um[vi] = Float.intBitsToFloat(rawBuffer[i + 16]); - vm[vi] = Float.intBitsToFloat(rawBuffer[i + 17]); - if (Compat.RPLE()) { - bsG[vi] = rawBuffer[i + 18]; - bsB[vi] = rawBuffer[i + 19]; - ue[vi] = Float.intBitsToFloat(rawBuffer[i + 20]); - ve[vi] = Float.intBitsToFloat(rawBuffer[i + 21]); - } + xt[vi] = Float.intBitsToFloat(rawBuffer[i + 12]); + yt[vi] = Float.intBitsToFloat(rawBuffer[i + 13]); + zt[vi] = Float.intBitsToFloat(rawBuffer[i + 14]); + wt[vi] = Float.intBitsToFloat(rawBuffer[i + 15]); + + um[vi] = Float.intBitsToFloat(rawBuffer[i + 16]); + vm[vi] = Float.intBitsToFloat(rawBuffer[i + 17]); + + if (flags.hasBrightness) { + bsG[vi] = rawBuffer[i + 18]; + bsB[vi] = rawBuffer[i + 19]; } else { - bs[vi] = flags.hasBrightness ? rawBuffer[i + 7] : DEFAULT_BRIGHTNESS; - - if (Compat.RPLE()) { - if (flags.hasBrightness) { - bsG[vi] = rawBuffer[i + 8]; - bsB[vi] = rawBuffer[i + 9]; - } else { - bsG[vi] = DEFAULT_BRIGHTNESS; - bsB[vi] = DEFAULT_BRIGHTNESS; - } - } + bsG[vi] = DEFAULT_BRIGHTNESS; + bsB[vi] = DEFAULT_BRIGHTNESS; } + + ue[vi] = Float.intBitsToFloat(rawBuffer[i + 20]); + ve[vi] = Float.intBitsToFloat(rawBuffer[i + 21]); } - + if(vertices == 3) { - // Quadrangulate! + // Quadrangulate! xs[3] = xs[2]; ys[3] = ys[2]; zs[3] = zs[2]; - + us[3] = us[2]; vs[3] = vs[2]; - + + cs[3] = cs[2]; + bs[3] = bs[2]; - if (Compat.RPLE()) { - bsG[3] = bsG[2]; - bsB[3] = bsB[2]; - if (Compat.isShaders()) { - ue[3] = ue[2]; - ve[3] = ve[2]; - } - } + + e1[3] = e1[2]; + e2[3] = e2[2]; + + xn[3] = xn[2]; + yn[3] = yn[2]; + zn[3] = zn[2]; + + xt[3] = xt[2]; + yt[3] = yt[2]; + zt[3] = zt[2]; + wt[3] = wt[2]; + + um[3] = um[2]; + vm[3] = vm[2]; + + bsG[3] = bsG[2]; + bsB[3] = bsB[2]; + + ue[3] = ue[2]; + ve[3] = ve[2]; + } + } + + private void readShaders(int[] rawBuffer, int tessellatorVertexSize, int offset, float offsetX, float offsetY, float offsetZ, int drawMode, ChunkMesh.Flags flags) { + //Only shaders + int vertices = drawMode == GL11.GL_TRIANGLES ? 3 : 4; + for (int vi = 0; vi < vertices; vi++) { + int i = offset + vi * tessellatorVertexSize; + + xs[vi] = Float.intBitsToFloat(rawBuffer[i]) + offsetX; + ys[vi] = Float.intBitsToFloat(rawBuffer[i + 1]) + offsetY; + zs[vi] = Float.intBitsToFloat(rawBuffer[i + 2]) + offsetZ; + + us[vi] = Float.intBitsToFloat(rawBuffer[i + 3]); + vs[vi] = Float.intBitsToFloat(rawBuffer[i + 4]); + + cs[vi] = flags.hasColor ? rawBuffer[i + 5] : DEFAULT_COLOR; + + bs[vi] = flags.hasBrightness ? rawBuffer[i + 6] : DEFAULT_BRIGHTNESS; + e1[vi] = rawBuffer[i + 7]; + e2[vi] = rawBuffer[i + 8]; + xn[vi] = Float.intBitsToFloat(rawBuffer[i + 9]); + yn[vi] = Float.intBitsToFloat(rawBuffer[i + 10]); + zn[vi] = Float.intBitsToFloat(rawBuffer[i + 11]); + xt[vi] = Float.intBitsToFloat(rawBuffer[i + 12]); + yt[vi] = Float.intBitsToFloat(rawBuffer[i + 13]); + zt[vi] = Float.intBitsToFloat(rawBuffer[i + 14]); + wt[vi] = Float.intBitsToFloat(rawBuffer[i + 15]); + um[vi] = Float.intBitsToFloat(rawBuffer[i + 16]); + vm[vi] = Float.intBitsToFloat(rawBuffer[i + 17]); + } + + if (vertices == 3) { + // Quadrangulate! + xs[3] = xs[2]; + ys[3] = ys[2]; + zs[3] = zs[2]; + + us[3] = us[2]; + vs[3] = vs[2]; + cs[3] = cs[2]; - if (Compat.isShaders()) { - e1[3] = e1[2]; - e2[3] = e2[2]; - xn[3] = xn[2]; - yn[3] = yn[2]; - zn[3] = zn[2]; - xt[3] = xt[2]; - yt[3] = yt[2]; - zt[3] = zt[2]; - wt[3] = wt[2]; - um[3] = um[2]; - vm[3] = vm[2]; + + bs[3] = bs[2]; + + e1[3] = e1[2]; + e2[3] = e2[2]; + + xn[3] = xn[2]; + yn[3] = yn[2]; + zn[3] = zn[2]; + + xt[3] = xt[2]; + yt[3] = yt[2]; + zt[3] = zt[2]; + wt[3] = wt[2]; + + um[3] = um[2]; + vm[3] = vm[2]; + } + } + + private void readRPLE(int[] rawBuffer, int tessellatorVertexSize, int offset, float offsetX, float offsetY, float offsetZ, int drawMode, ChunkMesh.Flags flags) { + //Only RPLE + int vertices = drawMode == GL11.GL_TRIANGLES ? 3 : 4; + for(int vi = 0; vi < vertices; vi++) { + int i = offset + vi * tessellatorVertexSize; + + xs[vi] = Float.intBitsToFloat(rawBuffer[i]) + offsetX; + ys[vi] = Float.intBitsToFloat(rawBuffer[i + 1]) + offsetY; + zs[vi] = Float.intBitsToFloat(rawBuffer[i + 2]) + offsetZ; + + us[vi] = Float.intBitsToFloat(rawBuffer[i + 3]); + vs[vi] = Float.intBitsToFloat(rawBuffer[i + 4]); + + cs[vi] = flags.hasColor ? rawBuffer[i + 5] : DEFAULT_COLOR; + + // TODO normals? + + if (flags.hasBrightness) { + bs[vi] = rawBuffer[i + 7]; + bsG[vi] = rawBuffer[i + 8]; + bsB[vi] = rawBuffer[i + 9]; + } else { + bs[vi] = DEFAULT_BRIGHTNESS; + bsG[vi] = DEFAULT_BRIGHTNESS; + bsB[vi] = DEFAULT_BRIGHTNESS; } } + + if(vertices == 3) { + // Quadrangulate! + xs[3] = xs[2]; + ys[3] = ys[2]; + zs[3] = zs[2]; + + us[3] = us[2]; + vs[3] = vs[2]; + + cs[3] = cs[2]; + + bs[3] = bs[2]; + bsG[3] = bsG[2]; + bsB[3] = bsB[2]; + } } + + private void readVanilla(int[] rawBuffer, int tessellatorVertexSize, int offset, float offsetX, float offsetY, float offsetZ, int drawMode, ChunkMesh.Flags flags) { + //No RPLE or Shaders + int vertices = drawMode == GL11.GL_TRIANGLES ? 3 : 4; + for(int vi = 0; vi < vertices; vi++) { + int i = offset + vi * tessellatorVertexSize; + + xs[vi] = Float.intBitsToFloat(rawBuffer[i]) + offsetX; + ys[vi] = Float.intBitsToFloat(rawBuffer[i + 1]) + offsetY; + zs[vi] = Float.intBitsToFloat(rawBuffer[i + 2]) + offsetZ; + + us[vi] = Float.intBitsToFloat(rawBuffer[i + 3]); + vs[vi] = Float.intBitsToFloat(rawBuffer[i + 4]); + + cs[vi] = flags.hasColor ? rawBuffer[i + 5] : DEFAULT_COLOR; + + // TODO normals? + + bs[vi] = flags.hasBrightness ? rawBuffer[i + 7] : DEFAULT_BRIGHTNESS; + } + + if(vertices == 3) { + // Quadrangulate! + xs[3] = xs[2]; + ys[3] = ys[2]; + zs[3] = zs[2]; + + us[3] = us[2]; + vs[3] = vs[2]; + + cs[3] = cs[2]; + + bs[3] = bs[2]; + } + } + + //endregion read implementations public void setState(int[] rawBuffer, int tessellatorVertexSize, int offset, ChunkMesh.Flags flags, int drawMode, float offsetX, float offsetY, float offsetZ) { deleted = false; @@ -158,21 +326,104 @@ public void setState(int[] rawBuffer, int tessellatorVertexSize, int offset, Chu } /** - * @implSpec This needs to be kept in sync with the attributes in {@link NeoRenderer#init()} + * @implSpec These needs to be kept in sync with the attributes in {@link NeoRenderer#init()} */ - public void writeToBuffer(BufferWriter out, int expectedStride) throws IOException { + public void writeToBuffer(BufferWriter out, int expectedStride) { + boolean rple = Compat.isRPLEModPresent(); + boolean shaders = Compat.isOptiFineShadersEnabled(); + + if (rple && shaders) { + writeToBufferRPLEAndShaders(out, expectedStride); + } else if (shaders) { + writeToBufferShaders(out, expectedStride); + } else if (rple) { + writeToBufferRPLE(out, expectedStride); + } else { + writeToBufferVanilla(out, expectedStride); + } + } + + //region writeToBuffer implementations + + public void writeToBufferRPLEAndShaders(BufferWriter out, int expectedStride) { + for(int vi = 0; vi < 4; vi++) { + out.writeFloat(xs[vi]); + out.writeFloat(ys[vi]); + out.writeFloat(zs[vi]); + + out.writeFloat(us[vi]); + out.writeFloat(vs[vi]); + + out.writeInt(cs[vi]); + + out.writeInt(bs[vi]); + + out.writeInt(e1[vi]); + out.writeInt(e2[vi]); + + out.writeFloat(xn[vi]); + out.writeFloat(yn[vi]); + out.writeFloat(zn[vi]); + + out.writeFloat(xt[vi]); + out.writeFloat(yt[vi]); + out.writeFloat(zt[vi]); + out.writeFloat(wt[vi]); + + out.writeFloat(um[vi]); + out.writeFloat(vm[vi]); + + out.writeInt(bsG[vi]); + out.writeInt(bsB[vi]); + + out.writeFloat(ue[vi]); + out.writeFloat(ve[vi]); + + assert out.position() % expectedStride == 0; + } + } + + public void writeToBufferShaders(BufferWriter out, int expectedStride) { for(int vi = 0; vi < 4; vi++) { - float x = xs[vi]; - float y = ys[vi]; - float z = zs[vi]; - - out.writeFloat(x); - out.writeFloat(y); - out.writeFloat(z); - + out.writeFloat(xs[vi]); + out.writeFloat(ys[vi]); + out.writeFloat(zs[vi]); + + out.writeFloat(us[vi]); + out.writeFloat(vs[vi]); + + out.writeInt( cs[vi]); + + out.writeInt(bs[vi]); + + out.writeInt(e1[vi]); + out.writeInt(e2[vi]); + + out.writeFloat(xn[vi]); + out.writeFloat(yn[vi]); + out.writeFloat(zn[vi]); + + out.writeFloat(xt[vi]); + out.writeFloat(yt[vi]); + out.writeFloat(zt[vi]); + out.writeFloat(wt[vi]); + + out.writeFloat(um[vi]); + out.writeFloat(vm[vi]); + + assert out.position() % expectedStride == 0; + } + } + + public void writeToBufferRPLE(BufferWriter out, int expectedStride) { + for(int vi = 0; vi < 4; vi++) { + out.writeFloat(xs[vi]); + out.writeFloat(ys[vi]); + out.writeFloat(zs[vi]); + float u = us[vi]; float v = vs[vi]; - + if(Config.shortUV) { out.writeShort((short)(Math.round(u * 32768f))); out.writeShort((short)(Math.round(v * 32768f))); @@ -181,41 +432,43 @@ public void writeToBuffer(BufferWriter out, int expectedStride) throws IOExcepti out.writeFloat(v); } - int c = cs[vi]; - - out.writeInt(c); + out.writeInt(cs[vi]); out.writeInt(bs[vi]); + out.writeInt(bsG[vi]); + out.writeInt(bsB[vi]); - if (Compat.isShaders()) { - out.writeInt(e1[vi]); - out.writeInt(e2[vi]); - out.writeFloat(xn[vi]); - out.writeFloat(yn[vi]); - out.writeFloat(zn[vi]); - out.writeFloat(xt[vi]); - out.writeFloat(yt[vi]); - out.writeFloat(zt[vi]); - out.writeFloat(wt[vi]); - out.writeFloat(um[vi]); - out.writeFloat(vm[vi]); - } + assert out.position() % expectedStride == 0; + } + } + + public void writeToBufferVanilla(BufferWriter out, int expectedStride) { + for(int vi = 0; vi < 4; vi++) { + out.writeFloat(xs[vi]); + out.writeFloat(ys[vi]); + out.writeFloat(zs[vi]); + + float u = us[vi]; + float v = vs[vi]; - if (Compat.RPLE()) { - out.writeInt(bsG[vi]); - out.writeInt(bsB[vi]); - if (Compat.isShaders()) { - out.writeFloat(ue[vi]); - out.writeFloat(ve[vi]); - } + if(Config.shortUV) { + out.writeShort((short)(Math.round(u * 32768f))); + out.writeShort((short)(Math.round(v * 32768f))); + } else { + out.writeFloat(u); + out.writeFloat(v); } - + + out.writeInt(cs[vi]); + + out.writeInt(bs[vi]); + assert out.position() % expectedStride == 0; - - //System.out.println("[" + vertexI + "] x: " + x + ", y: " + y + " z: " + z + ", u: " + u + ", v: " + v + ", b: " + b + ", c: " + c); } } + //endregion + @Override public String toString() { return String.format(Locale.ENGLISH, "%s[(%.1f, %.1f, %.1f), (%.1f, %.1f, %.1f), (%.1f, %.1f, %.1f), (%.1f, %.1f, %.1f)]", deleted ? "XXX " : "", xs[0], ys[0], zs[0], xs[1], ys[1], zs[1], xs[2], ys[2], zs[2], xs[3], ys[3], zs[3]); diff --git a/src/main/java/makamys/neodymium/renderer/NeoRenderer.java b/src/main/java/makamys/neodymium/renderer/NeoRenderer.java index ed8be73..79b6117 100644 --- a/src/main/java/makamys/neodymium/renderer/NeoRenderer.java +++ b/src/main/java/makamys/neodymium/renderer/NeoRenderer.java @@ -291,7 +291,7 @@ private void handleKeyboard() { Matrix4f projMatrix = new Matrix4f(); private int render(int pass, double alpha) { - if (!Compat.isShaders()) { + if (!Compat.isOptiFineShadersEnabled()) { int shader = getShaderProgram(pass); if (shader == 0) return 0; @@ -306,7 +306,7 @@ private int render(int pass, double alpha) { } int u_renderOffset = -1; - if (!Compat.isShaders()) { + if (!Compat.isOptiFineShadersEnabled()) { u_renderOffset = glGetUniformLocation(getShaderProgram(pass), "renderOffset"); } @@ -320,7 +320,7 @@ private int render(int pass, double alpha) { Util.setPositionAndLimit(piFirst[pass], region.batchFirst[pass], region.batchLimit[pass]); Util.setPositionAndLimit(piCount[pass], region.batchFirst[pass], region.batchLimit[pass]); - if (Compat.isShaders()) { + if (Compat.isOptiFineShadersEnabled()) { GL11.glMatrixMode(GL_MODELVIEW); val offsetX = (float) (region.originX - eyePosX); @@ -335,7 +335,7 @@ private int render(int pass, double alpha) { glMultiDrawArrays(GL_QUADS, piFirst[pass], piCount[pass]); - if (Compat.isShaders()) + if (Compat.isOptiFineShadersEnabled()) GL11.glPopMatrix(); } Util.setPositionAndLimit(piFirst[pass], 0, oldLimit); @@ -345,7 +345,7 @@ private int render(int pass, double alpha) { GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL); } - if (!Compat.isShaders()) { + if (!Compat.isOptiFineShadersEnabled()) { glUseProgram(0); } @@ -389,7 +389,7 @@ private void updateUniforms(double alpha, int pass) { int u_proj = glGetUniformLocation(shaderProgram, "proj"); int u_playerPos = glGetUniformLocation(shaderProgram, "playerPos"); int u_light = 0, u_light_r = 0, u_light_g = 0, u_light_b = 0; - if (Compat.RPLE()) { + if (Compat.isRPLEModPresent()) { u_light_r = glGetUniformLocation(shaderProgram, "lightTexR"); u_light_g = glGetUniformLocation(shaderProgram, "lightTexG"); u_light_b = glGetUniformLocation(shaderProgram, "lightTexB"); @@ -414,7 +414,7 @@ private void updateUniforms(double alpha, int pass) { glUniform3f(u_playerPos, (float) eyePosX, (float) eyePosY, (float) eyePosZ); - if (Compat.RPLE()) { + if (Compat.isRPLEModPresent()) { //TODO connect to RPLE gl api (once that exists) // For now we just use the RPLE default texture indices glUniform1i(u_light_r, 1); @@ -432,6 +432,56 @@ private void updateUniforms(double alpha, int pass) { fogStartEnd.position(0); } + private void initAttributesRPLEAndShaders() { + attributes.addAttribute("POS", 3, 4, GL_FLOAT); + attributes.addAttribute("TEXTURE", 2, 4, GL_FLOAT); + attributes.addAttribute("COLOR", 4, 1, GL_UNSIGNED_BYTE); + attributes.addAttribute("BRIGHTNESS_RED", 2, 2, GL_SHORT); + attributes.addAttribute("ENTITY_DATA_1", 1, 4, GL_UNSIGNED_INT); + attributes.addAttribute("ENTITY_DATA_2", 1, 4, GL_UNSIGNED_INT); + attributes.addAttribute("NORMAL", 3, 4, GL_FLOAT); + attributes.addAttribute("TANGENT", 4, 4, GL_FLOAT); + attributes.addAttribute("MIDTEXTURE", 2, 4, GL_FLOAT); + attributes.addAttribute("BRIGHTNESS_GREEN", 2, 2, GL_SHORT); + attributes.addAttribute("BRIGHTNESS_BLUE", 2, 2, GL_SHORT); + attributes.addAttribute("EDGE_TEX", 2, 4, GL_FLOAT); + } + + private void initAttributesShaders() { + attributes.addAttribute("POS", 3, 4, GL_FLOAT); + attributes.addAttribute("TEXTURE", 2, 4, GL_FLOAT); + attributes.addAttribute("COLOR", 4, 1, GL_UNSIGNED_BYTE); + attributes.addAttribute("BRIGHTNESS", 2, 2, GL_SHORT); + attributes.addAttribute("ENTITY_DATA_1", 1, 4, GL_UNSIGNED_INT); + attributes.addAttribute("ENTITY_DATA_2", 1, 4, GL_UNSIGNED_INT); + attributes.addAttribute("NORMAL", 3, 4, GL_FLOAT); + attributes.addAttribute("TANGENT", 4, 4, GL_FLOAT); + attributes.addAttribute("MIDTEXTURE", 2, 4, GL_FLOAT); + } + + private void initAttributesRPLE() { + attributes.addAttribute("POS", 3, 4, GL_FLOAT); + if (Config.shortUV) { + attributes.addAttribute("TEXTURE", 2, 2, GL_UNSIGNED_SHORT); + } else { + attributes.addAttribute("TEXTURE", 2, 4, GL_FLOAT); + } + attributes.addAttribute("COLOR", 4, 1, GL_UNSIGNED_BYTE); + attributes.addAttribute("BRIGHTNESS_RED", 2, 2, GL_SHORT); + attributes.addAttribute("BRIGHTNESS_GREEN", 2, 2, GL_SHORT); + attributes.addAttribute("BRIGHTNESS_BLUE", 2, 2, GL_SHORT); + } + + private void initAttributesVanilla() { + attributes.addAttribute("POS", 3, 4, GL_FLOAT); + if (Config.shortUV) { + attributes.addAttribute("TEXTURE", 2, 2, GL_UNSIGNED_SHORT); + } else { + attributes.addAttribute("TEXTURE", 2, 4, GL_FLOAT); + } + attributes.addAttribute("COLOR", 4, 1, GL_UNSIGNED_BYTE); + attributes.addAttribute("BRIGHTNESS", 2, 2, GL_SHORT); + } /** * @implSpec The attributes here need to be kept in sync with {@link MeshQuad#writeToBuffer(BufferWriter, int)} */ @@ -440,37 +490,20 @@ public boolean init() { // This means 1 MB of index data per 512 MB of VRAM. MAX_MESHES = Config.VRAMSize * 128; - Compat.updateShadersState(); + Compat.updateOptiFineShadersState(); attributes = new AttributeSet(); - attributes.addAttribute("POS", 3, 4, GL_FLOAT); - if (Config.shortUV) { - attributes.addAttribute("TEXTURE", 2, 2, GL_UNSIGNED_SHORT); - } else { - attributes.addAttribute("TEXTURE", 2, 4, GL_FLOAT); - } - attributes.addAttribute("COLOR", 4, 1, GL_UNSIGNED_BYTE); - if (Compat.RPLE()) { - attributes.addAttribute("BRIGHTNESS_RED", 2, 2, GL_SHORT); - } else { - attributes.addAttribute("BRIGHTNESS", 2, 2, GL_SHORT); - } - if (Compat.isShaders()) { - attributes.addAttribute("ENTITY_DATA_1", 1, 4, GL_UNSIGNED_INT); - attributes.addAttribute("ENTITY_DATA_2", 1, 4, GL_UNSIGNED_INT); - attributes.addAttribute("NORMAL", 3, 4, GL_FLOAT); - attributes.addAttribute("TANGENT", 4, 4, GL_FLOAT); - attributes.addAttribute("MIDTEXTURE", 2, 4, GL_FLOAT); - if (Compat.RPLE()) { - attributes.addAttribute("BRIGHTNESS_GREEN", 2, 2, GL_SHORT); - attributes.addAttribute("BRIGHTNESS_BLUE", 2, 2, GL_SHORT); - attributes.addAttribute("EDGE_TEX", 2, 4, GL_FLOAT); - } + + boolean rple = Compat.isRPLEModPresent(); + boolean optiFineShaders = Compat.isOptiFineShadersEnabled(); + if (rple && optiFineShaders) { + initAttributesRPLEAndShaders(); + } else if (optiFineShaders) { + initAttributesShaders(); + } else if (rple) { + initAttributesRPLE(); } else { - if (Compat.RPLE()) { - attributes.addAttribute("BRIGHTNESS_GREEN", 2, 2, GL_SHORT); - attributes.addAttribute("BRIGHTNESS_BLUE", 2, 2, GL_SHORT); - } + initAttributesVanilla(); } reloadShader(); @@ -481,76 +514,10 @@ public boolean init() { mem = new GPUMemoryManager(); glBindBuffer(GL_ARRAY_BUFFER, mem.VBO); - - // position 3 floats 12 bytes offset 0 - // texture 2 floats 8 bytes offset 12 - // color 4 bytes 4 bytes offset 20 - // brightness 2 shorts 4 bytes offset 24 - // entitydata 3 shorts 6 bytes offset 28 - // 2 bytes - // normal 3 floats 12 bytes offset 36 - // tangent 4 floats 16 bytes offset 48 - // midtexture 2 floats 8 bytes offset 64 - if (Compat.isShaders()) { - int stride; - if (Compat.FalseTweaks()) { - stride = VertexAPI.recomputeVertexInfo(18, 4); - } else { - stride = 72; - } - val entityAttrib = 10; - val midTexCoordAttrib = 11; - val tangentAttrib = 12; - // position 3 floats 12 bytes offset 0 - GL11.glVertexPointer(3, GL11.GL_FLOAT, stride, 0); - GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY); - // texture 2 floats 8 bytes offset 12 - GL11.glTexCoordPointer(2, GL11.GL_FLOAT, stride, 12); - GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY); - - // color 4 bytes 4 bytes offset 20 - GL11.glColorPointer(4, GL11.GL_UNSIGNED_BYTE, stride, 20); - GL11.glEnableClientState(GL11.GL_COLOR_ARRAY); - - // brightness 2 shorts 4 bytes offset 24 - OpenGlHelper.setClientActiveTexture(OpenGlHelper.lightmapTexUnit); - GL11.glTexCoordPointer(2, GL11.GL_SHORT, stride, 24); - GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY); - OpenGlHelper.setClientActiveTexture(OpenGlHelper.defaultTexUnit); - - // entitydata 3 shorts 6 bytes offset 28 - GL20.glVertexAttribPointer(entityAttrib, 3, GL11.GL_SHORT, false, stride, 28); - GL20.glEnableVertexAttribArray(entityAttrib); - - // normal 3 floats 12 bytes offset 36 - GL11.glNormalPointer(GL11.GL_FLOAT, stride, 36); - GL11.glEnableClientState(GL11.GL_NORMAL_ARRAY); - - // tangent 4 floats 16 bytes offset 48 - GL20.glVertexAttribPointer(tangentAttrib, 4, GL11.GL_FLOAT, false, stride, 48); - GL20.glEnableVertexAttribArray(tangentAttrib); - - // midtexture 2 floats 8 bytes offset 64 - GL13.glClientActiveTexture(GL13.GL_TEXTURE3); - GL11.glTexCoordPointer(2, GL11.GL_FLOAT, stride, 64); - GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY); - OpenGlHelper.setClientActiveTexture(OpenGlHelper.defaultTexUnit); - - ARBVertexShader.glVertexAttribPointerARB(midTexCoordAttrib, 2, GL11.GL_FLOAT, false, stride, 64); - ARBVertexShader.glEnableVertexAttribArrayARB(midTexCoordAttrib); - - if (Compat.RPLE()) { - RPLELightMapUtil.enableVertexPointersVBO(); - ARBVertexShader.glVertexAttribPointerARB(RPLEShaderConstants.edgeTexCoordAttrib, - 2, - GL_FLOAT, - false, - stride, - 80); - ARBVertexShader.glEnableVertexAttribArrayARB(RPLEShaderConstants.edgeTexCoordAttrib); - } + if (optiFineShaders) { + initOptiFineShadersVertexPointers(); } else { attributes.enable(); } @@ -568,6 +535,85 @@ public boolean init() { return true; } + // TODO: This format is nice, we should have it in the docs too! + // position 3 floats 12 bytes offset 0 + // texture 2 floats 8 bytes offset 12 + // color 4 bytes 4 bytes offset 20 + // brightness 2 shorts 4 bytes offset 24 (brightness_R with RPLE) + // entitydata 3 shorts 6 bytes offset 28 + // -------- 2 bytes offset 34 + // normal 3 floats 12 bytes offset 36 + // tangent 4 floats 16 bytes offset 48 + // midtexture 2 floats 8 bytes offset 64 + + // ---RPLE EXTRAS--- + // brightness_G 2 shorts 4 bytes offset 72 + // brightness_B 2 shorts 4 bytes offset 76 + // edgeTex 2 floats 8 bytes offset 80 + private static void initOptiFineShadersVertexPointers() { + int stride; + if (Compat.isFalseTweaksModPresent()) { + stride = VertexAPI.recomputeVertexInfo(18, 4); + } else { + stride = 72; + } + val entityAttrib = 10; + val midTexCoordAttrib = 11; + val tangentAttrib = 12; + + // position 3 floats 12 bytes offset 0 + GL11.glVertexPointer(3, GL11.GL_FLOAT, stride, 0); + GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY); + + // texture 2 floats 8 bytes offset 12 + GL11.glTexCoordPointer(2, GL11.GL_FLOAT, stride, 12); + GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY); + + // color 4 bytes 4 bytes offset 20 + GL11.glColorPointer(4, GL11.GL_UNSIGNED_BYTE, stride, 20); + GL11.glEnableClientState(GL11.GL_COLOR_ARRAY); + + // brightness 2 shorts 4 bytes offset 24 + if (!Compat.isRPLEModPresent()) { // RPLE sets this up in enableVertexPointersVBO + OpenGlHelper.setClientActiveTexture(OpenGlHelper.lightmapTexUnit); + GL11.glTexCoordPointer(2, GL11.GL_SHORT, stride, 24); + GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY); + OpenGlHelper.setClientActiveTexture(OpenGlHelper.defaultTexUnit); + } + + // entitydata 3 shorts 6 bytes offset 28 + GL20.glVertexAttribPointer(entityAttrib, 3, GL11.GL_SHORT, false, stride, 28); + GL20.glEnableVertexAttribArray(entityAttrib); + + // normal 3 floats 12 bytes offset 36 + GL11.glNormalPointer(GL11.GL_FLOAT, stride, 36); + GL11.glEnableClientState(GL11.GL_NORMAL_ARRAY); + + // tangent 4 floats 16 bytes offset 48 + GL20.glVertexAttribPointer(tangentAttrib, 4, GL11.GL_FLOAT, false, stride, 48); + GL20.glEnableVertexAttribArray(tangentAttrib); + + // midtexture 2 floats 8 bytes offset 64 + GL13.glClientActiveTexture(GL13.GL_TEXTURE3); + GL11.glTexCoordPointer(2, GL11.GL_FLOAT, stride, 64); + GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY); + OpenGlHelper.setClientActiveTexture(OpenGlHelper.defaultTexUnit); + + ARBVertexShader.glVertexAttribPointerARB(midTexCoordAttrib, 2, GL11.GL_FLOAT, false, stride, 64); + ARBVertexShader.glEnableVertexAttribArrayARB(midTexCoordAttrib); + + if (Compat.isRPLEModPresent()) { + RPLELightMapUtil.enableVertexPointersVBO(); + ARBVertexShader.glVertexAttribPointerARB(RPLEShaderConstants.edgeTexCoordAttrib, + 2, + GL_FLOAT, + false, + stride, + 80); + ARBVertexShader.glEnableVertexAttribArrayARB(RPLEShaderConstants.edgeTexCoordAttrib); + } + } + public int getStride() { return attributes.stride(); } @@ -581,7 +627,7 @@ public void reloadShader(int pass, AttributeSet attributeSet) { if (Config.shortUV) { defines.put("SHORT_UV", ""); } - if (Compat.RPLE()) { + if (Compat.isRPLEModPresent()) { defines.put("RPLE", ""); } if (pass == 0) { From 9d83b4a76e041d5ee5f66863e66753fd8d2f938a Mon Sep 17 00:00:00 2001 From: FalsePattern Date: Mon, 8 Jan 2024 00:08:25 +0100 Subject: [PATCH 10/11] fix frustum check boolean logic --- .../java/makamys/neodymium/mixin/MixinWorldRenderer.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/main/java/makamys/neodymium/mixin/MixinWorldRenderer.java b/src/main/java/makamys/neodymium/mixin/MixinWorldRenderer.java index 16c4ea6..be3cadd 100644 --- a/src/main/java/makamys/neodymium/mixin/MixinWorldRenderer.java +++ b/src/main/java/makamys/neodymium/mixin/MixinWorldRenderer.java @@ -192,10 +192,6 @@ private void notifyIfDrawnStatusChanged() { @Override public boolean isDrawn() { - if (!(skipRenderPass[0] && skipRenderPass[1])) - return true; - if (!Compat.isOptiFineShadersEnabled()) - return isInFrustum; - return true; + return (isInFrustum || Compat.isOptiFineShadersEnabled()) && !(skipRenderPass[0] && skipRenderPass[1]); } } From 3dfe82e4674221e5d316a56f0e8fb27fa8da8bf2 Mon Sep 17 00:00:00 2001 From: FalsePattern Date: Mon, 8 Jan 2024 17:02:43 +0100 Subject: [PATCH 11/11] Make the multi-implementation methods a bit nicer to work with --- .../java/makamys/neodymium/Neodymium.java | 21 +- .../makamys/neodymium/renderer/ChunkMesh.java | 12 +- .../makamys/neodymium/renderer/MeshQuad.java | 392 +----------------- .../neodymium/renderer/NeoRenderer.java | 64 +-- .../neodymium/renderer/compat/RenderUtil.java | 18 + .../renderer/compat/RenderUtilRPLE.java | 109 +++++ .../renderer/compat/RenderUtilShaderRPLE.java | 156 +++++++ .../renderer/compat/RenderUtilShaders.java | 126 ++++++ .../renderer/compat/RenderUtilVanilla.java | 96 +++++ 9 files changed, 536 insertions(+), 458 deletions(-) create mode 100644 src/main/java/makamys/neodymium/renderer/compat/RenderUtil.java create mode 100644 src/main/java/makamys/neodymium/renderer/compat/RenderUtilRPLE.java create mode 100644 src/main/java/makamys/neodymium/renderer/compat/RenderUtilShaderRPLE.java create mode 100644 src/main/java/makamys/neodymium/renderer/compat/RenderUtilShaders.java create mode 100644 src/main/java/makamys/neodymium/renderer/compat/RenderUtilVanilla.java diff --git a/src/main/java/makamys/neodymium/Neodymium.java b/src/main/java/makamys/neodymium/Neodymium.java index 3750ddd..320e46a 100644 --- a/src/main/java/makamys/neodymium/Neodymium.java +++ b/src/main/java/makamys/neodymium/Neodymium.java @@ -7,9 +7,12 @@ import java.util.ArrayList; import java.util.List; +import makamys.neodymium.renderer.compat.RenderUtil; +import makamys.neodymium.renderer.compat.RenderUtilRPLE; +import makamys.neodymium.renderer.compat.RenderUtilShaderRPLE; +import makamys.neodymium.renderer.compat.RenderUtilShaders; +import makamys.neodymium.renderer.compat.RenderUtilVanilla; import org.apache.commons.lang3.tuple.Pair; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; import cpw.mods.fml.client.event.ConfigChangedEvent; import cpw.mods.fml.common.FMLCommonHandler; @@ -18,7 +21,6 @@ import cpw.mods.fml.common.event.FMLConstructionEvent; import cpw.mods.fml.common.event.FMLInitializationEvent; import cpw.mods.fml.common.event.FMLPreInitializationEvent; -import cpw.mods.fml.common.event.FMLServerAboutToStartEvent; import cpw.mods.fml.common.eventhandler.SubscribeEvent; import cpw.mods.fml.common.gameevent.TickEvent; import cpw.mods.fml.common.network.FMLNetworkEvent.ClientConnectedToServerEvent; @@ -49,6 +51,8 @@ public class Neodymium private boolean renderDebugText = false; public static NeoRenderer renderer; + + public static RenderUtil util; private static World rendererWorld; @@ -97,6 +101,17 @@ private void onPlayerWorldChanged(World newWorld) { List criticalWarns = warnsAndCriticalWarns.getRight(); if(criticalWarns.isEmpty()) { + boolean rple = Compat.isRPLEModPresent(); + boolean optiFineShaders = Compat.isOptiFineShadersEnabled(); + if (rple && optiFineShaders) { + util = RenderUtilShaderRPLE.INSTANCE; + } else if (optiFineShaders) { + util = RenderUtilShaders.INSTANCE; + } else if (rple) { + util = RenderUtilRPLE.INSTANCE; + } else { + util = RenderUtilVanilla.INSTANCE; + } renderer = new NeoRenderer(newWorld); renderer.hasIncompatibilities = !warns.isEmpty() || !criticalWarns.isEmpty(); } diff --git a/src/main/java/makamys/neodymium/renderer/ChunkMesh.java b/src/main/java/makamys/neodymium/renderer/ChunkMesh.java index 9d98bd3..9f1e8fc 100644 --- a/src/main/java/makamys/neodymium/renderer/ChunkMesh.java +++ b/src/main/java/makamys/neodymium/renderer/ChunkMesh.java @@ -197,7 +197,7 @@ private ByteBuffer createBuffer(List quads, int quadCount) { if(subMeshStart[subMeshStartIdx] == -1) { subMeshStart[subMeshStartIdx] = i; } - quad.writeToBuffer(out, stride); + Neodymium.util.writeMeshQuadToBuffer(quad, out, stride); i++; } else if(sortByNormals){ break; @@ -301,12 +301,12 @@ public double distSq(Entity player) { public static void setCaptureTarget(ChunkMesh cm) { meshCaptureTarget = cm; } - + public static class Flags { - boolean hasTexture; - boolean hasBrightness; - boolean hasColor; - boolean hasNormals; + public boolean hasTexture; + public boolean hasBrightness; + public boolean hasColor; + public boolean hasNormals; public Flags(byte flags) { hasTexture = (flags & 1) != 0; diff --git a/src/main/java/makamys/neodymium/renderer/MeshQuad.java b/src/main/java/makamys/neodymium/renderer/MeshQuad.java index 2a9fe2d..cfae0b3 100644 --- a/src/main/java/makamys/neodymium/renderer/MeshQuad.java +++ b/src/main/java/makamys/neodymium/renderer/MeshQuad.java @@ -1,6 +1,7 @@ package makamys.neodymium.renderer; import makamys.neodymium.Compat; +import makamys.neodymium.Neodymium; import makamys.neodymium.config.Config; import makamys.neodymium.util.BufferWriter; import makamys.neodymium.util.Util; @@ -10,8 +11,8 @@ import java.util.Locale; public class MeshQuad { - private final static int DEFAULT_BRIGHTNESS = Util.createBrightness(15, 15); - private final static int DEFAULT_COLOR = 0xFFFFFFFF; + public final static int DEFAULT_BRIGHTNESS = Util.createBrightness(15, 15); + public final static int DEFAULT_COLOR = 0xFFFFFFFF; //region common @@ -68,250 +69,11 @@ public class MeshQuad { private static Vector3f vectorB = new Vector3f(); private static Vector3f vectorC = new Vector3f(); - - private void read(int[] rawBuffer, int tessellatorVertexSize, int offset, float offsetX, float offsetY, float offsetZ, int drawMode, ChunkMesh.Flags flags) { - boolean rple = Compat.isRPLEModPresent(); - boolean optiFineShaders = Compat.isOptiFineShadersEnabled(); - - if (rple && optiFineShaders) { - readRPLEAndShaders(rawBuffer, tessellatorVertexSize, offset, offsetX, offsetY, offsetZ, drawMode, flags); - } else if (optiFineShaders) { - readShaders(rawBuffer, tessellatorVertexSize, offset, offsetX, offsetY, offsetZ, drawMode, flags); - } else if (rple) { - readRPLE(rawBuffer, tessellatorVertexSize, offset, offsetX, offsetY, offsetZ, drawMode, flags); - } else { - readVanilla(rawBuffer, tessellatorVertexSize, offset, offsetX, offsetY, offsetZ, drawMode, flags); - } - } - - //region read implementations - - private void readRPLEAndShaders(int[] rawBuffer, int tessellatorVertexSize, int offset, float offsetX, float offsetY, float offsetZ, int drawMode, ChunkMesh.Flags flags) { - //RPLE and Shaders - int vertices = drawMode == GL11.GL_TRIANGLES ? 3 : 4; - for(int vi = 0; vi < vertices; vi++) { - int i = offset + vi * tessellatorVertexSize; - - xs[vi] = Float.intBitsToFloat(rawBuffer[i]) + offsetX; - ys[vi] = Float.intBitsToFloat(rawBuffer[i + 1]) + offsetY; - zs[vi] = Float.intBitsToFloat(rawBuffer[i + 2]) + offsetZ; - - us[vi] = Float.intBitsToFloat(rawBuffer[i + 3]); - vs[vi] = Float.intBitsToFloat(rawBuffer[i + 4]); - - cs[vi] = flags.hasColor ? rawBuffer[i + 5] : DEFAULT_COLOR; - - bs[vi] = flags.hasBrightness ? rawBuffer[i + 6] : DEFAULT_BRIGHTNESS; - - e1[vi] = rawBuffer[i + 7]; - e2[vi] = rawBuffer[i + 8]; - - xn[vi] = Float.intBitsToFloat(rawBuffer[i + 9]); - yn[vi] = Float.intBitsToFloat(rawBuffer[i + 10]); - zn[vi] = Float.intBitsToFloat(rawBuffer[i + 11]); - - xt[vi] = Float.intBitsToFloat(rawBuffer[i + 12]); - yt[vi] = Float.intBitsToFloat(rawBuffer[i + 13]); - zt[vi] = Float.intBitsToFloat(rawBuffer[i + 14]); - wt[vi] = Float.intBitsToFloat(rawBuffer[i + 15]); - - um[vi] = Float.intBitsToFloat(rawBuffer[i + 16]); - vm[vi] = Float.intBitsToFloat(rawBuffer[i + 17]); - - if (flags.hasBrightness) { - bsG[vi] = rawBuffer[i + 18]; - bsB[vi] = rawBuffer[i + 19]; - } else { - bsG[vi] = DEFAULT_BRIGHTNESS; - bsB[vi] = DEFAULT_BRIGHTNESS; - } - - ue[vi] = Float.intBitsToFloat(rawBuffer[i + 20]); - ve[vi] = Float.intBitsToFloat(rawBuffer[i + 21]); - } - - if(vertices == 3) { - // Quadrangulate! - xs[3] = xs[2]; - ys[3] = ys[2]; - zs[3] = zs[2]; - - us[3] = us[2]; - vs[3] = vs[2]; - - cs[3] = cs[2]; - - bs[3] = bs[2]; - - e1[3] = e1[2]; - e2[3] = e2[2]; - - xn[3] = xn[2]; - yn[3] = yn[2]; - zn[3] = zn[2]; - - xt[3] = xt[2]; - yt[3] = yt[2]; - zt[3] = zt[2]; - wt[3] = wt[2]; - - um[3] = um[2]; - vm[3] = vm[2]; - - bsG[3] = bsG[2]; - bsB[3] = bsB[2]; - - ue[3] = ue[2]; - ve[3] = ve[2]; - } - } - - private void readShaders(int[] rawBuffer, int tessellatorVertexSize, int offset, float offsetX, float offsetY, float offsetZ, int drawMode, ChunkMesh.Flags flags) { - //Only shaders - int vertices = drawMode == GL11.GL_TRIANGLES ? 3 : 4; - for (int vi = 0; vi < vertices; vi++) { - int i = offset + vi * tessellatorVertexSize; - - xs[vi] = Float.intBitsToFloat(rawBuffer[i]) + offsetX; - ys[vi] = Float.intBitsToFloat(rawBuffer[i + 1]) + offsetY; - zs[vi] = Float.intBitsToFloat(rawBuffer[i + 2]) + offsetZ; - - us[vi] = Float.intBitsToFloat(rawBuffer[i + 3]); - vs[vi] = Float.intBitsToFloat(rawBuffer[i + 4]); - - cs[vi] = flags.hasColor ? rawBuffer[i + 5] : DEFAULT_COLOR; - - bs[vi] = flags.hasBrightness ? rawBuffer[i + 6] : DEFAULT_BRIGHTNESS; - e1[vi] = rawBuffer[i + 7]; - e2[vi] = rawBuffer[i + 8]; - xn[vi] = Float.intBitsToFloat(rawBuffer[i + 9]); - yn[vi] = Float.intBitsToFloat(rawBuffer[i + 10]); - zn[vi] = Float.intBitsToFloat(rawBuffer[i + 11]); - xt[vi] = Float.intBitsToFloat(rawBuffer[i + 12]); - yt[vi] = Float.intBitsToFloat(rawBuffer[i + 13]); - zt[vi] = Float.intBitsToFloat(rawBuffer[i + 14]); - wt[vi] = Float.intBitsToFloat(rawBuffer[i + 15]); - um[vi] = Float.intBitsToFloat(rawBuffer[i + 16]); - vm[vi] = Float.intBitsToFloat(rawBuffer[i + 17]); - } - - if (vertices == 3) { - // Quadrangulate! - xs[3] = xs[2]; - ys[3] = ys[2]; - zs[3] = zs[2]; - - us[3] = us[2]; - vs[3] = vs[2]; - - cs[3] = cs[2]; - - bs[3] = bs[2]; - - e1[3] = e1[2]; - e2[3] = e2[2]; - - xn[3] = xn[2]; - yn[3] = yn[2]; - zn[3] = zn[2]; - - xt[3] = xt[2]; - yt[3] = yt[2]; - zt[3] = zt[2]; - wt[3] = wt[2]; - - um[3] = um[2]; - vm[3] = vm[2]; - } - } - - private void readRPLE(int[] rawBuffer, int tessellatorVertexSize, int offset, float offsetX, float offsetY, float offsetZ, int drawMode, ChunkMesh.Flags flags) { - //Only RPLE - int vertices = drawMode == GL11.GL_TRIANGLES ? 3 : 4; - for(int vi = 0; vi < vertices; vi++) { - int i = offset + vi * tessellatorVertexSize; - - xs[vi] = Float.intBitsToFloat(rawBuffer[i]) + offsetX; - ys[vi] = Float.intBitsToFloat(rawBuffer[i + 1]) + offsetY; - zs[vi] = Float.intBitsToFloat(rawBuffer[i + 2]) + offsetZ; - - us[vi] = Float.intBitsToFloat(rawBuffer[i + 3]); - vs[vi] = Float.intBitsToFloat(rawBuffer[i + 4]); - - cs[vi] = flags.hasColor ? rawBuffer[i + 5] : DEFAULT_COLOR; - - // TODO normals? - - if (flags.hasBrightness) { - bs[vi] = rawBuffer[i + 7]; - bsG[vi] = rawBuffer[i + 8]; - bsB[vi] = rawBuffer[i + 9]; - } else { - bs[vi] = DEFAULT_BRIGHTNESS; - bsG[vi] = DEFAULT_BRIGHTNESS; - bsB[vi] = DEFAULT_BRIGHTNESS; - } - } - - if(vertices == 3) { - // Quadrangulate! - xs[3] = xs[2]; - ys[3] = ys[2]; - zs[3] = zs[2]; - - us[3] = us[2]; - vs[3] = vs[2]; - - cs[3] = cs[2]; - - bs[3] = bs[2]; - bsG[3] = bsG[2]; - bsB[3] = bsB[2]; - } - } - - private void readVanilla(int[] rawBuffer, int tessellatorVertexSize, int offset, float offsetX, float offsetY, float offsetZ, int drawMode, ChunkMesh.Flags flags) { - //No RPLE or Shaders - int vertices = drawMode == GL11.GL_TRIANGLES ? 3 : 4; - for(int vi = 0; vi < vertices; vi++) { - int i = offset + vi * tessellatorVertexSize; - - xs[vi] = Float.intBitsToFloat(rawBuffer[i]) + offsetX; - ys[vi] = Float.intBitsToFloat(rawBuffer[i + 1]) + offsetY; - zs[vi] = Float.intBitsToFloat(rawBuffer[i + 2]) + offsetZ; - - us[vi] = Float.intBitsToFloat(rawBuffer[i + 3]); - vs[vi] = Float.intBitsToFloat(rawBuffer[i + 4]); - - cs[vi] = flags.hasColor ? rawBuffer[i + 5] : DEFAULT_COLOR; - - // TODO normals? - - bs[vi] = flags.hasBrightness ? rawBuffer[i + 7] : DEFAULT_BRIGHTNESS; - } - - if(vertices == 3) { - // Quadrangulate! - xs[3] = xs[2]; - ys[3] = ys[2]; - zs[3] = zs[2]; - - us[3] = us[2]; - vs[3] = vs[2]; - - cs[3] = cs[2]; - - bs[3] = bs[2]; - } - } - - //endregion read implementations - public void setState(int[] rawBuffer, int tessellatorVertexSize, int offset, ChunkMesh.Flags flags, int drawMode, float offsetX, float offsetY, float offsetZ) { deleted = false; - read(rawBuffer, tessellatorVertexSize, offset, offsetX, offsetY, offsetZ, drawMode, flags); - + Neodymium.util.readMeshQuad(this, rawBuffer, tessellatorVertexSize, offset, offsetX, offsetY, offsetZ, drawMode, flags); + if(xs[0] == xs[1] && xs[1] == xs[2] && xs[2] == xs[3] && ys[0] == ys[1] && ys[1] == ys[2] && ys[2] == ys[3]) { // ignore empty quads (e.g. alpha pass of EnderIO item conduits) deleted = true; @@ -325,150 +87,6 @@ public void setState(int[] rawBuffer, int tessellatorVertexSize, int offset, Chu normal = QuadNormal.fromVector(vectorC); } - /** - * @implSpec These needs to be kept in sync with the attributes in {@link NeoRenderer#init()} - */ - public void writeToBuffer(BufferWriter out, int expectedStride) { - boolean rple = Compat.isRPLEModPresent(); - boolean shaders = Compat.isOptiFineShadersEnabled(); - - if (rple && shaders) { - writeToBufferRPLEAndShaders(out, expectedStride); - } else if (shaders) { - writeToBufferShaders(out, expectedStride); - } else if (rple) { - writeToBufferRPLE(out, expectedStride); - } else { - writeToBufferVanilla(out, expectedStride); - } - } - - //region writeToBuffer implementations - - public void writeToBufferRPLEAndShaders(BufferWriter out, int expectedStride) { - for(int vi = 0; vi < 4; vi++) { - out.writeFloat(xs[vi]); - out.writeFloat(ys[vi]); - out.writeFloat(zs[vi]); - - out.writeFloat(us[vi]); - out.writeFloat(vs[vi]); - - out.writeInt(cs[vi]); - - out.writeInt(bs[vi]); - - out.writeInt(e1[vi]); - out.writeInt(e2[vi]); - - out.writeFloat(xn[vi]); - out.writeFloat(yn[vi]); - out.writeFloat(zn[vi]); - - out.writeFloat(xt[vi]); - out.writeFloat(yt[vi]); - out.writeFloat(zt[vi]); - out.writeFloat(wt[vi]); - - out.writeFloat(um[vi]); - out.writeFloat(vm[vi]); - - out.writeInt(bsG[vi]); - out.writeInt(bsB[vi]); - - out.writeFloat(ue[vi]); - out.writeFloat(ve[vi]); - - assert out.position() % expectedStride == 0; - } - } - - public void writeToBufferShaders(BufferWriter out, int expectedStride) { - for(int vi = 0; vi < 4; vi++) { - out.writeFloat(xs[vi]); - out.writeFloat(ys[vi]); - out.writeFloat(zs[vi]); - - out.writeFloat(us[vi]); - out.writeFloat(vs[vi]); - - out.writeInt( cs[vi]); - - out.writeInt(bs[vi]); - - out.writeInt(e1[vi]); - out.writeInt(e2[vi]); - - out.writeFloat(xn[vi]); - out.writeFloat(yn[vi]); - out.writeFloat(zn[vi]); - - out.writeFloat(xt[vi]); - out.writeFloat(yt[vi]); - out.writeFloat(zt[vi]); - out.writeFloat(wt[vi]); - - out.writeFloat(um[vi]); - out.writeFloat(vm[vi]); - - assert out.position() % expectedStride == 0; - } - } - - public void writeToBufferRPLE(BufferWriter out, int expectedStride) { - for(int vi = 0; vi < 4; vi++) { - out.writeFloat(xs[vi]); - out.writeFloat(ys[vi]); - out.writeFloat(zs[vi]); - - float u = us[vi]; - float v = vs[vi]; - - if(Config.shortUV) { - out.writeShort((short)(Math.round(u * 32768f))); - out.writeShort((short)(Math.round(v * 32768f))); - } else { - out.writeFloat(u); - out.writeFloat(v); - } - - out.writeInt(cs[vi]); - - out.writeInt(bs[vi]); - out.writeInt(bsG[vi]); - out.writeInt(bsB[vi]); - - assert out.position() % expectedStride == 0; - } - } - - public void writeToBufferVanilla(BufferWriter out, int expectedStride) { - for(int vi = 0; vi < 4; vi++) { - out.writeFloat(xs[vi]); - out.writeFloat(ys[vi]); - out.writeFloat(zs[vi]); - - float u = us[vi]; - float v = vs[vi]; - - if(Config.shortUV) { - out.writeShort((short)(Math.round(u * 32768f))); - out.writeShort((short)(Math.round(v * 32768f))); - } else { - out.writeFloat(u); - out.writeFloat(v); - } - - out.writeInt(cs[vi]); - - out.writeInt(bs[vi]); - - assert out.position() % expectedStride == 0; - } - } - - //endregion - @Override public String toString() { return String.format(Locale.ENGLISH, "%s[(%.1f, %.1f, %.1f), (%.1f, %.1f, %.1f), (%.1f, %.1f, %.1f), (%.1f, %.1f, %.1f)]", deleted ? "XXX " : "", xs[0], ys[0], zs[0], xs[1], ys[1], zs[1], xs[2], ys[2], zs[2], xs[3], ys[3], zs[3]); diff --git a/src/main/java/makamys/neodymium/renderer/NeoRenderer.java b/src/main/java/makamys/neodymium/renderer/NeoRenderer.java index 79b6117..d6becc8 100644 --- a/src/main/java/makamys/neodymium/renderer/NeoRenderer.java +++ b/src/main/java/makamys/neodymium/renderer/NeoRenderer.java @@ -432,56 +432,6 @@ private void updateUniforms(double alpha, int pass) { fogStartEnd.position(0); } - private void initAttributesRPLEAndShaders() { - attributes.addAttribute("POS", 3, 4, GL_FLOAT); - attributes.addAttribute("TEXTURE", 2, 4, GL_FLOAT); - attributes.addAttribute("COLOR", 4, 1, GL_UNSIGNED_BYTE); - attributes.addAttribute("BRIGHTNESS_RED", 2, 2, GL_SHORT); - attributes.addAttribute("ENTITY_DATA_1", 1, 4, GL_UNSIGNED_INT); - attributes.addAttribute("ENTITY_DATA_2", 1, 4, GL_UNSIGNED_INT); - attributes.addAttribute("NORMAL", 3, 4, GL_FLOAT); - attributes.addAttribute("TANGENT", 4, 4, GL_FLOAT); - attributes.addAttribute("MIDTEXTURE", 2, 4, GL_FLOAT); - attributes.addAttribute("BRIGHTNESS_GREEN", 2, 2, GL_SHORT); - attributes.addAttribute("BRIGHTNESS_BLUE", 2, 2, GL_SHORT); - attributes.addAttribute("EDGE_TEX", 2, 4, GL_FLOAT); - } - - private void initAttributesShaders() { - attributes.addAttribute("POS", 3, 4, GL_FLOAT); - attributes.addAttribute("TEXTURE", 2, 4, GL_FLOAT); - attributes.addAttribute("COLOR", 4, 1, GL_UNSIGNED_BYTE); - attributes.addAttribute("BRIGHTNESS", 2, 2, GL_SHORT); - attributes.addAttribute("ENTITY_DATA_1", 1, 4, GL_UNSIGNED_INT); - attributes.addAttribute("ENTITY_DATA_2", 1, 4, GL_UNSIGNED_INT); - attributes.addAttribute("NORMAL", 3, 4, GL_FLOAT); - attributes.addAttribute("TANGENT", 4, 4, GL_FLOAT); - attributes.addAttribute("MIDTEXTURE", 2, 4, GL_FLOAT); - } - - private void initAttributesRPLE() { - attributes.addAttribute("POS", 3, 4, GL_FLOAT); - if (Config.shortUV) { - attributes.addAttribute("TEXTURE", 2, 2, GL_UNSIGNED_SHORT); - } else { - attributes.addAttribute("TEXTURE", 2, 4, GL_FLOAT); - } - attributes.addAttribute("COLOR", 4, 1, GL_UNSIGNED_BYTE); - attributes.addAttribute("BRIGHTNESS_RED", 2, 2, GL_SHORT); - attributes.addAttribute("BRIGHTNESS_GREEN", 2, 2, GL_SHORT); - attributes.addAttribute("BRIGHTNESS_BLUE", 2, 2, GL_SHORT); - } - - private void initAttributesVanilla() { - attributes.addAttribute("POS", 3, 4, GL_FLOAT); - if (Config.shortUV) { - attributes.addAttribute("TEXTURE", 2, 2, GL_UNSIGNED_SHORT); - } else { - attributes.addAttribute("TEXTURE", 2, 4, GL_FLOAT); - } - attributes.addAttribute("COLOR", 4, 1, GL_UNSIGNED_BYTE); - attributes.addAttribute("BRIGHTNESS", 2, 2, GL_SHORT); - } /** * @implSpec The attributes here need to be kept in sync with {@link MeshQuad#writeToBuffer(BufferWriter, int)} */ @@ -494,17 +444,7 @@ public boolean init() { attributes = new AttributeSet(); - boolean rple = Compat.isRPLEModPresent(); - boolean optiFineShaders = Compat.isOptiFineShadersEnabled(); - if (rple && optiFineShaders) { - initAttributesRPLEAndShaders(); - } else if (optiFineShaders) { - initAttributesShaders(); - } else if (rple) { - initAttributesRPLE(); - } else { - initAttributesVanilla(); - } + Neodymium.util.initVertexAttributes(attributes); reloadShader(); @@ -515,7 +455,7 @@ public boolean init() { glBindBuffer(GL_ARRAY_BUFFER, mem.VBO); - + boolean optiFineShaders = Compat.isOptiFineShadersEnabled(); if (optiFineShaders) { initOptiFineShadersVertexPointers(); } else { diff --git a/src/main/java/makamys/neodymium/renderer/compat/RenderUtil.java b/src/main/java/makamys/neodymium/renderer/compat/RenderUtil.java new file mode 100644 index 0000000..70996eb --- /dev/null +++ b/src/main/java/makamys/neodymium/renderer/compat/RenderUtil.java @@ -0,0 +1,18 @@ +package makamys.neodymium.renderer.compat; + +import makamys.neodymium.renderer.ChunkMesh; +import makamys.neodymium.renderer.MeshQuad; +import makamys.neodymium.renderer.NeoRenderer; +import makamys.neodymium.renderer.attribs.AttributeSet; +import makamys.neodymium.util.BufferWriter; + +public interface RenderUtil { + void readMeshQuad(MeshQuad meshQuad, int[] rawBuffer, int tessellatorVertexSize, int offset, float offsetX, float offsetY, float offsetZ, int drawMode, ChunkMesh.Flags flags); + + /** + * @implSpec These needs to be kept in sync with the attributes in {@link NeoRenderer#init()} + */ + void writeMeshQuadToBuffer(MeshQuad meshQuad, BufferWriter out, int expectedStride); + + void initVertexAttributes(AttributeSet attributes); +} diff --git a/src/main/java/makamys/neodymium/renderer/compat/RenderUtilRPLE.java b/src/main/java/makamys/neodymium/renderer/compat/RenderUtilRPLE.java new file mode 100644 index 0000000..fb27fee --- /dev/null +++ b/src/main/java/makamys/neodymium/renderer/compat/RenderUtilRPLE.java @@ -0,0 +1,109 @@ +package makamys.neodymium.renderer.compat; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import makamys.neodymium.config.Config; +import makamys.neodymium.renderer.ChunkMesh; +import makamys.neodymium.renderer.MeshQuad; +import makamys.neodymium.renderer.attribs.AttributeSet; +import makamys.neodymium.util.BufferWriter; +import org.lwjgl.opengl.GL11; + +import static makamys.neodymium.renderer.MeshQuad.DEFAULT_BRIGHTNESS; +import static makamys.neodymium.renderer.MeshQuad.DEFAULT_COLOR; +import static org.lwjgl.opengl.GL11.GL_FLOAT; +import static org.lwjgl.opengl.GL11.GL_SHORT; +import static org.lwjgl.opengl.GL11.GL_UNSIGNED_BYTE; +import static org.lwjgl.opengl.GL11.GL_UNSIGNED_SHORT; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class RenderUtilRPLE implements RenderUtil { + public static final RenderUtilRPLE INSTANCE = new RenderUtilRPLE(); + + @Override + public void readMeshQuad(MeshQuad meshQuad, int[] rawBuffer, int tessellatorVertexSize, int offset, float offsetX, float offsetY, float offsetZ, int drawMode, ChunkMesh.Flags flags) { + int vertices = drawMode == GL11.GL_TRIANGLES ? 3 : 4; + for(int vi = 0; vi < vertices; vi++) { + int i = offset + vi * tessellatorVertexSize; + + meshQuad.xs[vi] = Float.intBitsToFloat(rawBuffer[i]) + offsetX; + meshQuad.ys[vi] = Float.intBitsToFloat(rawBuffer[i + 1]) + offsetY; + meshQuad.zs[vi] = Float.intBitsToFloat(rawBuffer[i + 2]) + offsetZ; + + meshQuad.us[vi] = Float.intBitsToFloat(rawBuffer[i + 3]); + meshQuad.vs[vi] = Float.intBitsToFloat(rawBuffer[i + 4]); + + meshQuad.cs[vi] = flags.hasColor ? rawBuffer[i + 5] : DEFAULT_COLOR; + + // TODO normals? + + if (flags.hasBrightness) { + meshQuad.bs[vi] = rawBuffer[i + 7]; + meshQuad.bsG[vi] = rawBuffer[i + 8]; + meshQuad.bsB[vi] = rawBuffer[i + 9]; + } else { + meshQuad.bs[vi] = DEFAULT_BRIGHTNESS; + meshQuad.bsG[vi] = DEFAULT_BRIGHTNESS; + meshQuad.bsB[vi] = DEFAULT_BRIGHTNESS; + } + } + + if(vertices == 3) { + // Quadrangulate! + meshQuad.xs[3] = meshQuad.xs[2]; + meshQuad.ys[3] = meshQuad.ys[2]; + meshQuad.zs[3] = meshQuad.zs[2]; + + meshQuad.us[3] = meshQuad.us[2]; + meshQuad.vs[3] = meshQuad.vs[2]; + + meshQuad.cs[3] = meshQuad.cs[2]; + + meshQuad.bs[3] = meshQuad.bs[2]; + meshQuad.bsG[3] = meshQuad.bsG[2]; + meshQuad.bsB[3] = meshQuad.bsB[2]; + } + } + + @Override + public void writeMeshQuadToBuffer(MeshQuad meshQuad, BufferWriter out, int expectedStride) { + for(int vi = 0; vi < 4; vi++) { + out.writeFloat(meshQuad.xs[vi]); + out.writeFloat(meshQuad.ys[vi]); + out.writeFloat(meshQuad.zs[vi]); + + float u = meshQuad.us[vi]; + float v = meshQuad.vs[vi]; + + if(Config.shortUV) { + out.writeShort((short)(Math.round(u * 32768f))); + out.writeShort((short)(Math.round(v * 32768f))); + } else { + out.writeFloat(u); + out.writeFloat(v); + } + + out.writeInt(meshQuad.cs[vi]); + + out.writeInt(meshQuad.bs[vi]); + out.writeInt(meshQuad.bsG[vi]); + out.writeInt(meshQuad.bsB[vi]); + + assert out.position() % expectedStride == 0; + } + } + + @Override + public void initVertexAttributes(AttributeSet attributes) { + attributes.addAttribute("POS", 3, 4, GL_FLOAT); + if (Config.shortUV) { + attributes.addAttribute("TEXTURE", 2, 2, GL_UNSIGNED_SHORT); + } else { + attributes.addAttribute("TEXTURE", 2, 4, GL_FLOAT); + } + attributes.addAttribute("COLOR", 4, 1, GL_UNSIGNED_BYTE); + attributes.addAttribute("BRIGHTNESS_RED", 2, 2, GL_SHORT); + attributes.addAttribute("BRIGHTNESS_GREEN", 2, 2, GL_SHORT); + attributes.addAttribute("BRIGHTNESS_BLUE", 2, 2, GL_SHORT); + } +} diff --git a/src/main/java/makamys/neodymium/renderer/compat/RenderUtilShaderRPLE.java b/src/main/java/makamys/neodymium/renderer/compat/RenderUtilShaderRPLE.java new file mode 100644 index 0000000..731bfd6 --- /dev/null +++ b/src/main/java/makamys/neodymium/renderer/compat/RenderUtilShaderRPLE.java @@ -0,0 +1,156 @@ +package makamys.neodymium.renderer.compat; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import makamys.neodymium.renderer.ChunkMesh; +import makamys.neodymium.renderer.MeshQuad; +import makamys.neodymium.renderer.attribs.AttributeSet; +import makamys.neodymium.util.BufferWriter; +import org.lwjgl.opengl.GL11; + +import static makamys.neodymium.renderer.MeshQuad.DEFAULT_BRIGHTNESS; +import static makamys.neodymium.renderer.MeshQuad.DEFAULT_COLOR; +import static org.lwjgl.opengl.GL11.GL_FLOAT; +import static org.lwjgl.opengl.GL11.GL_SHORT; +import static org.lwjgl.opengl.GL11.GL_UNSIGNED_BYTE; +import static org.lwjgl.opengl.GL11.GL_UNSIGNED_INT; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class RenderUtilShaderRPLE implements RenderUtil { + public static final RenderUtilShaderRPLE INSTANCE = new RenderUtilShaderRPLE(); + + @Override + public void readMeshQuad(MeshQuad meshQuad, int[] rawBuffer, int tessellatorVertexSize, int offset, float offsetX, float offsetY, float offsetZ, int drawMode, ChunkMesh.Flags flags) { + int vertices = drawMode == GL11.GL_TRIANGLES ? 3 : 4; + for(int vi = 0; vi < vertices; vi++) { + int i = offset + vi * tessellatorVertexSize; + + meshQuad.xs[vi] = Float.intBitsToFloat(rawBuffer[i]) + offsetX; + meshQuad.ys[vi] = Float.intBitsToFloat(rawBuffer[i + 1]) + offsetY; + meshQuad.zs[vi] = Float.intBitsToFloat(rawBuffer[i + 2]) + offsetZ; + + meshQuad.us[vi] = Float.intBitsToFloat(rawBuffer[i + 3]); + meshQuad.vs[vi] = Float.intBitsToFloat(rawBuffer[i + 4]); + + meshQuad.cs[vi] = flags.hasColor ? rawBuffer[i + 5] : DEFAULT_COLOR; + + meshQuad.bs[vi] = flags.hasBrightness ? rawBuffer[i + 6] : DEFAULT_BRIGHTNESS; + + meshQuad.e1[vi] = rawBuffer[i + 7]; + meshQuad.e2[vi] = rawBuffer[i + 8]; + + meshQuad.xn[vi] = Float.intBitsToFloat(rawBuffer[i + 9]); + meshQuad.yn[vi] = Float.intBitsToFloat(rawBuffer[i + 10]); + meshQuad.zn[vi] = Float.intBitsToFloat(rawBuffer[i + 11]); + + meshQuad.xt[vi] = Float.intBitsToFloat(rawBuffer[i + 12]); + meshQuad.yt[vi] = Float.intBitsToFloat(rawBuffer[i + 13]); + meshQuad.zt[vi] = Float.intBitsToFloat(rawBuffer[i + 14]); + meshQuad.wt[vi] = Float.intBitsToFloat(rawBuffer[i + 15]); + + meshQuad.um[vi] = Float.intBitsToFloat(rawBuffer[i + 16]); + meshQuad.vm[vi] = Float.intBitsToFloat(rawBuffer[i + 17]); + + if (flags.hasBrightness) { + meshQuad.bsG[vi] = rawBuffer[i + 18]; + meshQuad.bsB[vi] = rawBuffer[i + 19]; + } else { + meshQuad.bsG[vi] = DEFAULT_BRIGHTNESS; + meshQuad.bsB[vi] = DEFAULT_BRIGHTNESS; + } + + meshQuad.ue[vi] = Float.intBitsToFloat(rawBuffer[i + 20]); + meshQuad.ve[vi] = Float.intBitsToFloat(rawBuffer[i + 21]); + } + + if(vertices == 3) { + // Quadrangulate! + meshQuad.xs[3] = meshQuad.xs[2]; + meshQuad.ys[3] = meshQuad.ys[2]; + meshQuad.zs[3] = meshQuad.zs[2]; + + meshQuad.us[3] = meshQuad.us[2]; + meshQuad.vs[3] = meshQuad.vs[2]; + + meshQuad.cs[3] = meshQuad.cs[2]; + + meshQuad.bs[3] = meshQuad.bs[2]; + + meshQuad.e1[3] = meshQuad.e1[2]; + meshQuad.e2[3] = meshQuad.e2[2]; + + meshQuad.xn[3] = meshQuad.xn[2]; + meshQuad.yn[3] = meshQuad.yn[2]; + meshQuad.zn[3] = meshQuad.zn[2]; + + meshQuad.xt[3] = meshQuad.xt[2]; + meshQuad.yt[3] = meshQuad.yt[2]; + meshQuad.zt[3] = meshQuad.zt[2]; + meshQuad.wt[3] = meshQuad.wt[2]; + + meshQuad.um[3] = meshQuad.um[2]; + meshQuad.vm[3] = meshQuad.vm[2]; + + meshQuad.bsG[3] = meshQuad.bsG[2]; + meshQuad.bsB[3] = meshQuad.bsB[2]; + + meshQuad.ue[3] = meshQuad.ue[2]; + meshQuad.ve[3] = meshQuad.ve[2]; + } + } + + @Override + public void writeMeshQuadToBuffer(MeshQuad meshQuad, BufferWriter out, int expectedStride) { + for(int vi = 0; vi < 4; vi++) { + out.writeFloat(meshQuad.xs[vi]); + out.writeFloat(meshQuad.ys[vi]); + out.writeFloat(meshQuad.zs[vi]); + + out.writeFloat(meshQuad.us[vi]); + out.writeFloat(meshQuad.vs[vi]); + + out.writeInt(meshQuad.cs[vi]); + + out.writeInt(meshQuad.bs[vi]); + + out.writeInt(meshQuad.e1[vi]); + out.writeInt(meshQuad.e2[vi]); + + out.writeFloat(meshQuad.xn[vi]); + out.writeFloat(meshQuad.yn[vi]); + out.writeFloat(meshQuad.zn[vi]); + + out.writeFloat(meshQuad.xt[vi]); + out.writeFloat(meshQuad.yt[vi]); + out.writeFloat(meshQuad.zt[vi]); + out.writeFloat(meshQuad.wt[vi]); + + out.writeFloat(meshQuad.um[vi]); + out.writeFloat(meshQuad.vm[vi]); + + out.writeInt(meshQuad.bsG[vi]); + out.writeInt(meshQuad.bsB[vi]); + + out.writeFloat(meshQuad.ue[vi]); + out.writeFloat(meshQuad.ve[vi]); + + assert out.position() % expectedStride == 0; + } + } + + @Override + public void initVertexAttributes(AttributeSet attributes) { + attributes.addAttribute("POS", 3, 4, GL_FLOAT); + attributes.addAttribute("TEXTURE", 2, 4, GL_FLOAT); + attributes.addAttribute("COLOR", 4, 1, GL_UNSIGNED_BYTE); + attributes.addAttribute("BRIGHTNESS_RED", 2, 2, GL_SHORT); + attributes.addAttribute("ENTITY_DATA_1", 1, 4, GL_UNSIGNED_INT); + attributes.addAttribute("ENTITY_DATA_2", 1, 4, GL_UNSIGNED_INT); + attributes.addAttribute("NORMAL", 3, 4, GL_FLOAT); + attributes.addAttribute("TANGENT", 4, 4, GL_FLOAT); + attributes.addAttribute("MIDTEXTURE", 2, 4, GL_FLOAT); + attributes.addAttribute("BRIGHTNESS_GREEN", 2, 2, GL_SHORT); + attributes.addAttribute("BRIGHTNESS_BLUE", 2, 2, GL_SHORT); + attributes.addAttribute("EDGE_TEX", 2, 4, GL_FLOAT); + } +} diff --git a/src/main/java/makamys/neodymium/renderer/compat/RenderUtilShaders.java b/src/main/java/makamys/neodymium/renderer/compat/RenderUtilShaders.java new file mode 100644 index 0000000..b621e2c --- /dev/null +++ b/src/main/java/makamys/neodymium/renderer/compat/RenderUtilShaders.java @@ -0,0 +1,126 @@ +package makamys.neodymium.renderer.compat; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import makamys.neodymium.renderer.ChunkMesh; +import makamys.neodymium.renderer.MeshQuad; +import makamys.neodymium.renderer.attribs.AttributeSet; +import makamys.neodymium.util.BufferWriter; +import org.lwjgl.opengl.GL11; + +import static makamys.neodymium.renderer.MeshQuad.DEFAULT_BRIGHTNESS; +import static makamys.neodymium.renderer.MeshQuad.DEFAULT_COLOR; +import static org.lwjgl.opengl.GL11.GL_FLOAT; +import static org.lwjgl.opengl.GL11.GL_SHORT; +import static org.lwjgl.opengl.GL11.GL_UNSIGNED_BYTE; +import static org.lwjgl.opengl.GL11.GL_UNSIGNED_INT; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class RenderUtilShaders implements RenderUtil { + public static final RenderUtilShaders INSTANCE = new RenderUtilShaders(); + + @Override + public void readMeshQuad(MeshQuad meshQuad, int[] rawBuffer, int tessellatorVertexSize, int offset, float offsetX, float offsetY, float offsetZ, int drawMode, ChunkMesh.Flags flags) { + int vertices = drawMode == GL11.GL_TRIANGLES ? 3 : 4; + for (int vi = 0; vi < vertices; vi++) { + int i = offset + vi * tessellatorVertexSize; + + meshQuad.xs[vi] = Float.intBitsToFloat(rawBuffer[i]) + offsetX; + meshQuad.ys[vi] = Float.intBitsToFloat(rawBuffer[i + 1]) + offsetY; + meshQuad.zs[vi] = Float.intBitsToFloat(rawBuffer[i + 2]) + offsetZ; + + meshQuad.us[vi] = Float.intBitsToFloat(rawBuffer[i + 3]); + meshQuad.vs[vi] = Float.intBitsToFloat(rawBuffer[i + 4]); + + meshQuad.cs[vi] = flags.hasColor ? rawBuffer[i + 5] : DEFAULT_COLOR; + + meshQuad.bs[vi] = flags.hasBrightness ? rawBuffer[i + 6] : DEFAULT_BRIGHTNESS; + meshQuad.e1[vi] = rawBuffer[i + 7]; + meshQuad.e2[vi] = rawBuffer[i + 8]; + meshQuad.xn[vi] = Float.intBitsToFloat(rawBuffer[i + 9]); + meshQuad.yn[vi] = Float.intBitsToFloat(rawBuffer[i + 10]); + meshQuad.zn[vi] = Float.intBitsToFloat(rawBuffer[i + 11]); + meshQuad.xt[vi] = Float.intBitsToFloat(rawBuffer[i + 12]); + meshQuad.yt[vi] = Float.intBitsToFloat(rawBuffer[i + 13]); + meshQuad.zt[vi] = Float.intBitsToFloat(rawBuffer[i + 14]); + meshQuad.wt[vi] = Float.intBitsToFloat(rawBuffer[i + 15]); + meshQuad.um[vi] = Float.intBitsToFloat(rawBuffer[i + 16]); + meshQuad.vm[vi] = Float.intBitsToFloat(rawBuffer[i + 17]); + } + + if (vertices == 3) { + // Quadrangulate! + meshQuad.xs[3] = meshQuad.xs[2]; + meshQuad.ys[3] = meshQuad.ys[2]; + meshQuad.zs[3] = meshQuad.zs[2]; + + meshQuad.us[3] = meshQuad.us[2]; + meshQuad.vs[3] = meshQuad.vs[2]; + + meshQuad.cs[3] = meshQuad.cs[2]; + + meshQuad.bs[3] = meshQuad.bs[2]; + + meshQuad.e1[3] = meshQuad.e1[2]; + meshQuad.e2[3] = meshQuad.e2[2]; + + meshQuad.xn[3] = meshQuad.xn[2]; + meshQuad.yn[3] = meshQuad.yn[2]; + meshQuad.zn[3] = meshQuad.zn[2]; + + meshQuad.xt[3] = meshQuad.xt[2]; + meshQuad.yt[3] = meshQuad.yt[2]; + meshQuad.zt[3] = meshQuad.zt[2]; + meshQuad.wt[3] = meshQuad.wt[2]; + + meshQuad.um[3] = meshQuad.um[2]; + meshQuad.vm[3] = meshQuad.vm[2]; + } + } + + @Override + public void writeMeshQuadToBuffer(MeshQuad meshQuad, BufferWriter out, int expectedStride) { + for(int vi = 0; vi < 4; vi++) { + out.writeFloat(meshQuad.xs[vi]); + out.writeFloat(meshQuad.ys[vi]); + out.writeFloat(meshQuad.zs[vi]); + + out.writeFloat(meshQuad.us[vi]); + out.writeFloat(meshQuad.vs[vi]); + + out.writeInt(meshQuad.cs[vi]); + + out.writeInt(meshQuad.bs[vi]); + + out.writeInt(meshQuad.e1[vi]); + out.writeInt(meshQuad.e2[vi]); + + out.writeFloat(meshQuad.xn[vi]); + out.writeFloat(meshQuad.yn[vi]); + out.writeFloat(meshQuad.zn[vi]); + + out.writeFloat(meshQuad.xt[vi]); + out.writeFloat(meshQuad.yt[vi]); + out.writeFloat(meshQuad.zt[vi]); + out.writeFloat(meshQuad.wt[vi]); + + out.writeFloat(meshQuad.um[vi]); + out.writeFloat(meshQuad.vm[vi]); + + assert out.position() % expectedStride == 0; + } + } + + @Override + public void initVertexAttributes(AttributeSet attributes) { + attributes.addAttribute("POS", 3, 4, GL_FLOAT); + attributes.addAttribute("TEXTURE", 2, 4, GL_FLOAT); + attributes.addAttribute("COLOR", 4, 1, GL_UNSIGNED_BYTE); + attributes.addAttribute("BRIGHTNESS", 2, 2, GL_SHORT); + attributes.addAttribute("ENTITY_DATA_1", 1, 4, GL_UNSIGNED_INT); + attributes.addAttribute("ENTITY_DATA_2", 1, 4, GL_UNSIGNED_INT); + attributes.addAttribute("NORMAL", 3, 4, GL_FLOAT); + attributes.addAttribute("TANGENT", 4, 4, GL_FLOAT); + attributes.addAttribute("MIDTEXTURE", 2, 4, GL_FLOAT); + } +} diff --git a/src/main/java/makamys/neodymium/renderer/compat/RenderUtilVanilla.java b/src/main/java/makamys/neodymium/renderer/compat/RenderUtilVanilla.java new file mode 100644 index 0000000..46f5a2a --- /dev/null +++ b/src/main/java/makamys/neodymium/renderer/compat/RenderUtilVanilla.java @@ -0,0 +1,96 @@ +package makamys.neodymium.renderer.compat; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import makamys.neodymium.config.Config; +import makamys.neodymium.renderer.ChunkMesh; +import makamys.neodymium.renderer.MeshQuad; +import makamys.neodymium.renderer.attribs.AttributeSet; +import makamys.neodymium.util.BufferWriter; +import org.lwjgl.opengl.GL11; + +import static makamys.neodymium.renderer.MeshQuad.DEFAULT_BRIGHTNESS; +import static makamys.neodymium.renderer.MeshQuad.DEFAULT_COLOR; +import static org.lwjgl.opengl.GL11.GL_FLOAT; +import static org.lwjgl.opengl.GL11.GL_SHORT; +import static org.lwjgl.opengl.GL11.GL_UNSIGNED_BYTE; +import static org.lwjgl.opengl.GL11.GL_UNSIGNED_SHORT; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class RenderUtilVanilla implements RenderUtil { + public static final RenderUtilVanilla INSTANCE = new RenderUtilVanilla(); + + @Override + public void readMeshQuad(MeshQuad meshQuad, int[] rawBuffer, int tessellatorVertexSize, int offset, float offsetX, float offsetY, float offsetZ, int drawMode, ChunkMesh.Flags flags) { + //No RPLE or Shaders + int vertices = drawMode == GL11.GL_TRIANGLES ? 3 : 4; + for(int vi = 0; vi < vertices; vi++) { + int i = offset + vi * tessellatorVertexSize; + + meshQuad.xs[vi] = Float.intBitsToFloat(rawBuffer[i]) + offsetX; + meshQuad.ys[vi] = Float.intBitsToFloat(rawBuffer[i + 1]) + offsetY; + meshQuad.zs[vi] = Float.intBitsToFloat(rawBuffer[i + 2]) + offsetZ; + + meshQuad.us[vi] = Float.intBitsToFloat(rawBuffer[i + 3]); + meshQuad.vs[vi] = Float.intBitsToFloat(rawBuffer[i + 4]); + + meshQuad.cs[vi] = flags.hasColor ? rawBuffer[i + 5] : DEFAULT_COLOR; + + // TODO normals? + + meshQuad.bs[vi] = flags.hasBrightness ? rawBuffer[i + 7] : DEFAULT_BRIGHTNESS; + } + + if(vertices == 3) { + // Quadrangulate! + meshQuad.xs[3] = meshQuad.xs[2]; + meshQuad.ys[3] = meshQuad.ys[2]; + meshQuad.zs[3] = meshQuad.zs[2]; + + meshQuad.us[3] = meshQuad.us[2]; + meshQuad.vs[3] = meshQuad.vs[2]; + + meshQuad.cs[3] = meshQuad.cs[2]; + + meshQuad.bs[3] = meshQuad.bs[2]; + } + } + + @Override + public void writeMeshQuadToBuffer(MeshQuad meshQuad, BufferWriter out, int expectedStride) { + for(int vi = 0; vi < 4; vi++) { + out.writeFloat(meshQuad.xs[vi]); + out.writeFloat(meshQuad.ys[vi]); + out.writeFloat(meshQuad.zs[vi]); + + float u = meshQuad.us[vi]; + float v = meshQuad.vs[vi]; + + if(Config.shortUV) { + out.writeShort((short)(Math.round(u * 32768f))); + out.writeShort((short)(Math.round(v * 32768f))); + } else { + out.writeFloat(u); + out.writeFloat(v); + } + + out.writeInt(meshQuad.cs[vi]); + + out.writeInt(meshQuad.bs[vi]); + + assert out.position() % expectedStride == 0; + } + } + + @Override + public void initVertexAttributes(AttributeSet attributes) { + attributes.addAttribute("POS", 3, 4, GL_FLOAT); + if (Config.shortUV) { + attributes.addAttribute("TEXTURE", 2, 2, GL_UNSIGNED_SHORT); + } else { + attributes.addAttribute("TEXTURE", 2, 4, GL_FLOAT); + } + attributes.addAttribute("COLOR", 4, 1, GL_UNSIGNED_BYTE); + attributes.addAttribute("BRIGHTNESS", 2, 2, GL_SHORT); + } +}