mirror of
https://github.com/GTNewHorizons/Angelica.git
synced 2026-10-26 14:24:30 +00:00
VAO stuff (#1858)
This commit is contained in:
1 parent
20c3caaed4
commit
a7fac16d97
18 files changed
+491
-432
No files matched your search
@@ -1,7 +1,7 @@
|
|||||||
package com.gtnewhorizons.angelica.glsm;
|
package com.gtnewhorizons.angelica.glsm;
|
||||||
|
|
||||||
|
import com.gtnewhorizons.angelica.glsm.ffp.VAOManager;
|
||||||
import com.gtnewhorizons.angelica.glsm.recording.ImmediateModeRecorder;
|
import com.gtnewhorizons.angelica.glsm.recording.ImmediateModeRecorder;
|
||||||
import com.gtnewhorizons.angelica.glsm.states.VertexAttribState;
|
|
||||||
import com.gtnewhorizons.angelica.glsm.states.ViewportState;
|
import com.gtnewhorizons.angelica.glsm.states.ViewportState;
|
||||||
import org.joml.Matrix4f;
|
import org.joml.Matrix4f;
|
||||||
import org.joml.Vector4f;
|
import org.joml.Vector4f;
|
||||||
@@ -9,13 +9,13 @@ import org.lwjgl.opengl.GL11;
|
|||||||
import org.lwjgl.opengl.GL15;
|
import org.lwjgl.opengl.GL15;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
import static com.gtnewhorizons.angelica.glsm.backend.BackendManager.RENDER_BACKEND;
|
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
import java.nio.FloatBuffer;
|
import java.nio.FloatBuffer;
|
||||||
import java.nio.IntBuffer;
|
import java.nio.IntBuffer;
|
||||||
import java.nio.ShortBuffer;
|
import java.nio.ShortBuffer;
|
||||||
|
|
||||||
|
import static com.gtnewhorizons.angelica.glsm.backend.BackendManager.RENDER_BACKEND;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Software emulation of GL feedback mode
|
* Software emulation of GL feedback mode
|
||||||
*/
|
*/
|
||||||
@@ -127,12 +127,12 @@ public class FeedbackManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static int positionStride() {
|
private static int positionStride() {
|
||||||
final int s = VertexAttribState.get(0).effectiveStride();
|
final int s = VAOManager.getAttribEffectiveStride(0);
|
||||||
return (s != 0) ? s : 12;
|
return (s != 0) ? s : 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static long positionOffset() {
|
private static long positionOffset() {
|
||||||
return VertexAttribState.get(0).offset;
|
return VAOManager.getAttribOffset(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void processDrawArrays(int mode, int first, int count) {
|
public static void processDrawArrays(int mode, int first, int count) {
|
||||||
@@ -151,7 +151,7 @@ public class FeedbackManager {
|
|||||||
computeMVP();
|
computeMVP();
|
||||||
final int stride = positionStride();
|
final int stride = positionStride();
|
||||||
|
|
||||||
final int elementSize = VertexAttribState.Attrib.glTypeSizeBytes(type);
|
final int elementSize = VAOManager.Attrib.glTypeSizeBytes(type);
|
||||||
final int indexByteCount = indexCount * elementSize;
|
final int indexByteCount = indexCount * elementSize;
|
||||||
ensureIndexReadbackCapacity(indexByteCount);
|
ensureIndexReadbackCapacity(indexByteCount);
|
||||||
indexReadbackBuf.clear().limit(indexByteCount);
|
indexReadbackBuf.clear().limit(indexByteCount);
|
||||||
@@ -255,7 +255,7 @@ public class FeedbackManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void readPositionBuffer(long offset, ByteBuffer destination) {
|
private static void readPositionBuffer(long offset, ByteBuffer destination) {
|
||||||
final int positionVbo = VertexAttribState.get(0).vboId;
|
final int positionVbo = VAOManager.getAttribVBO(0);
|
||||||
final int previousVbo = GLStateManager.getBoundVBO();
|
final int previousVbo = GLStateManager.getBoundVBO();
|
||||||
|
|
||||||
if (positionVbo != 0 && positionVbo != previousVbo) {
|
if (positionVbo != 0 && positionVbo != previousVbo) {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFormatElement.Usage
|
|||||||
import com.gtnewhorizons.angelica.glsm.DisplayListManager.RecordMode;
|
import com.gtnewhorizons.angelica.glsm.DisplayListManager.RecordMode;
|
||||||
import com.gtnewhorizons.angelica.glsm.backend.BackendManager;
|
import com.gtnewhorizons.angelica.glsm.backend.BackendManager;
|
||||||
import com.gtnewhorizons.angelica.glsm.ffp.ShaderManager;
|
import com.gtnewhorizons.angelica.glsm.ffp.ShaderManager;
|
||||||
|
import com.gtnewhorizons.angelica.glsm.ffp.VAOManager;
|
||||||
import com.gtnewhorizons.angelica.glsm.hooks.DeferredAlphaHandler;
|
import com.gtnewhorizons.angelica.glsm.hooks.DeferredAlphaHandler;
|
||||||
import com.gtnewhorizons.angelica.glsm.hooks.DeferredBlendHandler;
|
import com.gtnewhorizons.angelica.glsm.hooks.DeferredBlendHandler;
|
||||||
import com.gtnewhorizons.angelica.glsm.hooks.DeferredDepthColorHandler;
|
import com.gtnewhorizons.angelica.glsm.hooks.DeferredDepthColorHandler;
|
||||||
@@ -39,15 +40,12 @@ import com.gtnewhorizons.angelica.glsm.stacks.PolygonStateStack;
|
|||||||
import com.gtnewhorizons.angelica.glsm.stacks.StencilStateStack;
|
import com.gtnewhorizons.angelica.glsm.stacks.StencilStateStack;
|
||||||
import com.gtnewhorizons.angelica.glsm.stacks.ViewPortStateStack;
|
import com.gtnewhorizons.angelica.glsm.stacks.ViewPortStateStack;
|
||||||
import com.gtnewhorizons.angelica.glsm.states.ClipPlaneState;
|
import com.gtnewhorizons.angelica.glsm.states.ClipPlaneState;
|
||||||
import com.gtnewhorizons.angelica.glsm.states.PixelUnpackState;
|
|
||||||
import com.gtnewhorizons.angelica.glsm.states.Color4;
|
import com.gtnewhorizons.angelica.glsm.states.Color4;
|
||||||
|
import com.gtnewhorizons.angelica.glsm.states.PixelUnpackState;
|
||||||
import com.gtnewhorizons.angelica.glsm.states.TextureBinding;
|
import com.gtnewhorizons.angelica.glsm.states.TextureBinding;
|
||||||
import com.gtnewhorizons.angelica.glsm.states.TextureUnitArray;
|
import com.gtnewhorizons.angelica.glsm.states.TextureUnitArray;
|
||||||
import com.gtnewhorizons.angelica.glsm.states.VertexAttribState;
|
|
||||||
import com.gtnewhorizons.angelica.glsm.texture.TextureInfo;
|
import com.gtnewhorizons.angelica.glsm.texture.TextureInfo;
|
||||||
import com.gtnewhorizons.angelica.glsm.texture.TextureInfoCache;
|
import com.gtnewhorizons.angelica.glsm.texture.TextureInfoCache;
|
||||||
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
|
||||||
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
|
||||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||||
import it.unimi.dsi.fastutil.ints.IntStack;
|
import it.unimi.dsi.fastutil.ints.IntStack;
|
||||||
@@ -64,7 +62,6 @@ import org.joml.Vector3f;
|
|||||||
import org.joml.Vector4f;
|
import org.joml.Vector4f;
|
||||||
import org.lwjgl.BufferUtils;
|
import org.lwjgl.BufferUtils;
|
||||||
import org.lwjgl.LWJGLException;
|
import org.lwjgl.LWJGLException;
|
||||||
|
|
||||||
import org.lwjgl.opengl.ARBShaderObjects;
|
import org.lwjgl.opengl.ARBShaderObjects;
|
||||||
import org.lwjgl.opengl.ContextCapabilities;
|
import org.lwjgl.opengl.ContextCapabilities;
|
||||||
import org.lwjgl.opengl.Display;
|
import org.lwjgl.opengl.Display;
|
||||||
@@ -99,10 +96,10 @@ import java.util.Set;
|
|||||||
import java.util.function.IntSupplier;
|
import java.util.function.IntSupplier;
|
||||||
|
|
||||||
import static com.gtnewhorizons.angelica.glsm.Vendor.AMD;
|
import static com.gtnewhorizons.angelica.glsm.Vendor.AMD;
|
||||||
import static com.gtnewhorizons.angelica.glsm.backend.BackendManager.RENDER_BACKEND;
|
|
||||||
import static com.gtnewhorizons.angelica.glsm.Vendor.INTEL;
|
import static com.gtnewhorizons.angelica.glsm.Vendor.INTEL;
|
||||||
import static com.gtnewhorizons.angelica.glsm.Vendor.MESA;
|
import static com.gtnewhorizons.angelica.glsm.Vendor.MESA;
|
||||||
import static com.gtnewhorizons.angelica.glsm.Vendor.NVIDIA;
|
import static com.gtnewhorizons.angelica.glsm.Vendor.NVIDIA;
|
||||||
|
import static com.gtnewhorizons.angelica.glsm.backend.BackendManager.RENDER_BACKEND;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OpenGL State Manager - Provides cached state tracking and management for Backend Renderer Actions
|
* OpenGL State Manager - Provides cached state tracking and management for Backend Renderer Actions
|
||||||
@@ -191,22 +188,22 @@ public class GLStateManager {
|
|||||||
|
|
||||||
// vertexFlags bits mark attribs the VBO already supplies; FFP supplies the rest via u_Current* uniforms.
|
// vertexFlags bits mark attribs the VBO already supplies; FFP supplies the rest via u_Current* uniforms.
|
||||||
// Skip the backend vertexAttrib call in either case.
|
// Skip the backend vertexAttrib call in either case.
|
||||||
public static void flushDeferredVertexAttribs(int vertexFlags) {
|
public static void flushDeferredVertexAttribs(boolean hasColor, boolean hasNormal, boolean hasTexCoord, boolean hasLightmap) {
|
||||||
if (dirtyColorAttrib && (vertexFlags & VertexFlags.COLOR_BIT) == 0) {
|
if (!hasColor && dirtyColorAttrib) {
|
||||||
RENDER_BACKEND.vertexAttrib4f(Usage.COLOR.getAttributeLocation(), color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
|
RENDER_BACKEND.vertexAttrib4f(Usage.COLOR.getAttributeLocation(), color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
|
||||||
dirtyColorAttrib = false;
|
dirtyColorAttrib = false;
|
||||||
}
|
}
|
||||||
if (dirtyNormalAttrib && (vertexFlags & VertexFlags.NORMAL_BIT) == 0) {
|
if (!hasNormal && dirtyNormalAttrib) {
|
||||||
final var n = ShaderManager.getCurrentNormal();
|
final var n = ShaderManager.getCurrentNormal();
|
||||||
RENDER_BACKEND.vertexAttrib3f(Usage.NORMAL.getAttributeLocation(), n.x, n.y, n.z);
|
RENDER_BACKEND.vertexAttrib3f(Usage.NORMAL.getAttributeLocation(), n.x, n.y, n.z);
|
||||||
dirtyNormalAttrib = false;
|
dirtyNormalAttrib = false;
|
||||||
}
|
}
|
||||||
if (dirtyTexCoordAttrib && (vertexFlags & VertexFlags.TEXTURE_BIT) == 0) {
|
if (!hasTexCoord && dirtyTexCoordAttrib) {
|
||||||
final var tc = ShaderManager.getCurrentTexCoord();
|
final var tc = ShaderManager.getCurrentTexCoord();
|
||||||
RENDER_BACKEND.vertexAttrib4f(Usage.PRIMARY_UV.getAttributeLocation(), tc.x, tc.y, tc.z, tc.w);
|
RENDER_BACKEND.vertexAttrib4f(Usage.PRIMARY_UV.getAttributeLocation(), tc.x, tc.y, tc.z, tc.w);
|
||||||
dirtyTexCoordAttrib = false;
|
dirtyTexCoordAttrib = false;
|
||||||
}
|
}
|
||||||
if (dirtyLightmapAttrib) {
|
if (!hasLightmap && dirtyLightmapAttrib) {
|
||||||
RENDER_BACKEND.vertexAttrib4f(Usage.SECONDARY_UV.getAttributeLocation(), GLSMConfig.lastBrightnessX, GLSMConfig.lastBrightnessY, 0.0f, 1.0f);
|
RENDER_BACKEND.vertexAttrib4f(Usage.SECONDARY_UV.getAttributeLocation(), GLSMConfig.lastBrightnessX, GLSMConfig.lastBrightnessY, 0.0f, 1.0f);
|
||||||
dirtyLightmapAttrib = false;
|
dirtyLightmapAttrib = false;
|
||||||
}
|
}
|
||||||
@@ -458,19 +455,16 @@ public class GLStateManager {
|
|||||||
@Getter protected static int listBase = 0;
|
@Getter protected static int listBase = 0;
|
||||||
|
|
||||||
@Getter protected static int boundVBO;
|
@Getter protected static int boundVBO;
|
||||||
@Getter protected static int boundEBO;
|
|
||||||
@Getter protected static int boundVAO;
|
@Getter protected static int boundVAO;
|
||||||
private static int clientArraysVBO = 0;
|
|
||||||
private static int clientArraysVBOCapacity = 0;
|
public static int getBoundEBO() {
|
||||||
private static final int[] clientArraysVBOOffsets = new int[VertexAttribState.MAX_ATTRIBS];
|
return VAOManager.boundEBO;
|
||||||
|
}
|
||||||
|
|
||||||
private static int boundPixelUnpackBuffer;
|
private static int boundPixelUnpackBuffer;
|
||||||
private static int boundPixelPackBuffer;
|
private static int boundPixelPackBuffer;
|
||||||
private static PixelUnpackState pixelUnpackState = PixelUnpackState.DEFAULT;
|
private static PixelUnpackState pixelUnpackState = PixelUnpackState.DEFAULT;
|
||||||
private static final Int2IntOpenHashMap vaoEboMap = new Int2IntOpenHashMap();
|
|
||||||
|
|
||||||
static {
|
|
||||||
vaoEboMap.defaultReturnValue(0);
|
|
||||||
}
|
|
||||||
@Getter private static int defaultVAO; // Non-zero on core profile
|
@Getter private static int defaultVAO; // Non-zero on core profile
|
||||||
|
|
||||||
public static void reset() {
|
public static void reset() {
|
||||||
@@ -492,8 +486,6 @@ public class GLStateManager {
|
|||||||
|
|
||||||
modelViewMatrix.clear();
|
modelViewMatrix.clear();
|
||||||
projectionMatrix.clear();
|
projectionMatrix.clear();
|
||||||
vaoEboMap.clear();
|
|
||||||
VertexAttribState.reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -644,7 +636,7 @@ public class GLStateManager {
|
|||||||
defaultVAO = RENDER_BACKEND.genVertexArrays();
|
defaultVAO = RENDER_BACKEND.genVertexArrays();
|
||||||
RENDER_BACKEND.bindVertexArray(defaultVAO);
|
RENDER_BACKEND.bindVertexArray(defaultVAO);
|
||||||
boundVAO = defaultVAO;
|
boundVAO = defaultVAO;
|
||||||
VertexAttribState.init(defaultVAO);
|
VAOManager.init(defaultVAO);
|
||||||
if (initCallback != null) {
|
if (initCallback != null) {
|
||||||
initCallback.run();
|
initCallback.run();
|
||||||
}
|
}
|
||||||
@@ -1022,7 +1014,8 @@ public class GLStateManager {
|
|||||||
case GL11.GL_LIST_MODE -> DisplayListManager.getListMode();
|
case GL11.GL_LIST_MODE -> DisplayListManager.getListMode();
|
||||||
case GL11.GL_MATRIX_MODE -> matrixMode.getMode();
|
case GL11.GL_MATRIX_MODE -> matrixMode.getMode();
|
||||||
case GL11.GL_SHADE_MODEL -> shadeModelState.getValue();
|
case GL11.GL_SHADE_MODEL -> shadeModelState.getValue();
|
||||||
case GL11.GL_TEXTURE_BINDING_2D -> getBoundTextureForServerState();
|
// GL_TEXTURE_2D makes no sense here, but some mod still queries it...
|
||||||
|
case GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_BINDING_2D -> getBoundTextureForServerState();
|
||||||
case GL11.GL_COLOR_MATERIAL_FACE -> colorMaterialFace.getValue();
|
case GL11.GL_COLOR_MATERIAL_FACE -> colorMaterialFace.getValue();
|
||||||
case GL11.GL_COLOR_MATERIAL_PARAMETER -> colorMaterialParameter.getValue();
|
case GL11.GL_COLOR_MATERIAL_PARAMETER -> colorMaterialParameter.getValue();
|
||||||
case GL11.GL_MODELVIEW_STACK_DEPTH -> getMatrixStackDepth(modelViewMatrix);
|
case GL11.GL_MODELVIEW_STACK_DEPTH -> getMatrixStackDepth(modelViewMatrix);
|
||||||
@@ -1050,7 +1043,7 @@ public class GLStateManager {
|
|||||||
case GL11.GL_STENCIL_CLEAR_VALUE -> stencilState.getClearValue();
|
case GL11.GL_STENCIL_CLEAR_VALUE -> stencilState.getClearValue();
|
||||||
|
|
||||||
case GL15.GL_ARRAY_BUFFER_BINDING -> boundVBO;
|
case GL15.GL_ARRAY_BUFFER_BINDING -> boundVBO;
|
||||||
case GL15.GL_ELEMENT_ARRAY_BUFFER_BINDING -> boundEBO;
|
case GL15.GL_ELEMENT_ARRAY_BUFFER_BINDING -> VAOManager.boundEBO;
|
||||||
case GL21.GL_PIXEL_UNPACK_BUFFER_BINDING -> boundPixelUnpackBuffer;
|
case GL21.GL_PIXEL_UNPACK_BUFFER_BINDING -> boundPixelUnpackBuffer;
|
||||||
case GL21.GL_PIXEL_PACK_BUFFER_BINDING -> boundPixelPackBuffer;
|
case GL21.GL_PIXEL_PACK_BUFFER_BINDING -> boundPixelPackBuffer;
|
||||||
|
|
||||||
@@ -2223,6 +2216,18 @@ public class GLStateManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void preDraw(int drawMode) {
|
||||||
|
prepareWideLineEmulation(drawMode);
|
||||||
|
ShaderManager.getInstance().preDraw();
|
||||||
|
prepareClientArrays();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void preDraw() {
|
||||||
|
disableWideLineEmulation();
|
||||||
|
ShaderManager.getInstance().preDraw();
|
||||||
|
prepareClientArrays();
|
||||||
|
}
|
||||||
|
|
||||||
public static void glDrawElements(int mode, ByteBuffer indices) {
|
public static void glDrawElements(int mode, ByteBuffer indices) {
|
||||||
if (DisplayListManager.isRecording()) {
|
if (DisplayListManager.isRecording()) {
|
||||||
throw DisplayListManager.unsupportedInList("glDrawElements");
|
throw DisplayListManager.unsupportedInList("glDrawElements");
|
||||||
@@ -2231,9 +2236,7 @@ public class GLStateManager {
|
|||||||
FeedbackManager.processDrawElements(mode, indices);
|
FeedbackManager.processDrawElements(mode, indices);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
prepareWideLineEmulation(mode);
|
preDraw(mode);
|
||||||
ShaderManager.getInstance().preDraw();
|
|
||||||
prepareClientArrays();
|
|
||||||
RENDER_BACKEND.drawElements(mode, indices);
|
RENDER_BACKEND.drawElements(mode, indices);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2245,14 +2248,13 @@ public class GLStateManager {
|
|||||||
FeedbackManager.processDrawElements(mode, indices);
|
FeedbackManager.processDrawElements(mode, indices);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
prepareWideLineEmulation(mode);
|
|
||||||
ShaderManager.getInstance().preDraw();
|
|
||||||
prepareClientArrays();
|
|
||||||
if (mode == GL11.GL_QUADS) {
|
if (mode == GL11.GL_QUADS) {
|
||||||
QuadConverter.drawQuadElementsAsTriangles(indices);
|
QuadConverter.drawQuadElementsAsTriangles(indices);
|
||||||
} else {
|
return;
|
||||||
RENDER_BACKEND.drawElements(mode, indices);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
preDraw(mode);
|
||||||
|
RENDER_BACKEND.drawElements(mode, indices);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void glDrawElements(int mode, ShortBuffer indices) {
|
public static void glDrawElements(int mode, ShortBuffer indices) {
|
||||||
@@ -2263,14 +2265,13 @@ public class GLStateManager {
|
|||||||
FeedbackManager.processDrawElements(mode, indices);
|
FeedbackManager.processDrawElements(mode, indices);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
prepareWideLineEmulation(mode);
|
|
||||||
ShaderManager.getInstance().preDraw();
|
|
||||||
prepareClientArrays();
|
|
||||||
if (mode == GL11.GL_QUADS) {
|
if (mode == GL11.GL_QUADS) {
|
||||||
QuadConverter.drawQuadElementsAsTriangles(indices);
|
QuadConverter.drawQuadElementsAsTriangles(indices);
|
||||||
} else {
|
return;
|
||||||
RENDER_BACKEND.drawElements(mode, indices);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
preDraw(mode);
|
||||||
|
RENDER_BACKEND.drawElements(mode, indices);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void glDrawElements(int mode, int count, int type, ByteBuffer indices) {
|
public static void glDrawElements(int mode, int count, int type, ByteBuffer indices) {
|
||||||
@@ -2281,14 +2282,13 @@ public class GLStateManager {
|
|||||||
FeedbackManager.processDrawElements(mode, count, type, indices);
|
FeedbackManager.processDrawElements(mode, count, type, indices);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
prepareWideLineEmulation(mode);
|
|
||||||
ShaderManager.getInstance().preDraw();
|
|
||||||
prepareClientArrays();
|
|
||||||
if (mode == GL11.GL_QUADS) {
|
if (mode == GL11.GL_QUADS) {
|
||||||
QuadConverter.drawQuadElementsAsTriangles(count, type, indices);
|
QuadConverter.drawQuadElementsAsTriangles(count, type, indices);
|
||||||
} else {
|
return;
|
||||||
RENDER_BACKEND.drawElements(mode, count, type, indices);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
preDraw(mode);
|
||||||
|
RENDER_BACKEND.drawElements(mode, count, type, indices);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void glDrawElements(int mode, int indices_count, int type, long indices_buffer_offset) {
|
public static void glDrawElements(int mode, int indices_count, int type, long indices_buffer_offset) {
|
||||||
@@ -2297,7 +2297,7 @@ public class GLStateManager {
|
|||||||
if (recordMode != RecordMode.NONE) {
|
if (recordMode != RecordMode.NONE) {
|
||||||
// Core profile: a default VAO is generated at init and glBindVertexArray(0)
|
// Core profile: a default VAO is generated at init and glBindVertexArray(0)
|
||||||
// is redirected to it, so a VAO is always bound here — no fallback branches.
|
// is redirected to it, so a VAO is always bound here — no fallback branches.
|
||||||
final IndexedDrawCapture capture = IndexedDrawCapture.create(mode, indices_count, type, indices_buffer_offset, boundEBO);
|
final IndexedDrawCapture capture = IndexedDrawCapture.create(mode, indices_count, type, indices_buffer_offset, VAOManager.boundEBO);
|
||||||
if (capture != null) {
|
if (capture != null) {
|
||||||
DisplayListManager.recordIndexedDrawCapture(capture);
|
DisplayListManager.recordIndexedDrawCapture(capture);
|
||||||
}
|
}
|
||||||
@@ -2309,14 +2309,13 @@ public class GLStateManager {
|
|||||||
FeedbackManager.processDrawElements(mode, indices_count, type, indices_buffer_offset);
|
FeedbackManager.processDrawElements(mode, indices_count, type, indices_buffer_offset);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
prepareWideLineEmulation(mode);
|
|
||||||
ShaderManager.getInstance().preDraw();
|
|
||||||
prepareClientArrays();
|
|
||||||
if (mode == GL11.GL_QUADS) {
|
if (mode == GL11.GL_QUADS) {
|
||||||
QuadConverter.drawQuadElementsAsTriangles(indices_count, type, indices_buffer_offset);
|
QuadConverter.drawQuadElementsAsTriangles(indices_count, type, indices_buffer_offset);
|
||||||
} else {
|
return;
|
||||||
RENDER_BACKEND.drawElements(mode, indices_count, type, indices_buffer_offset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
preDraw(mode);
|
||||||
|
RENDER_BACKEND.drawElements(mode, indices_count, type, indices_buffer_offset);
|
||||||
if (savedRecorder != null) DisplayListManager.resumeRecording(savedRecorder);
|
if (savedRecorder != null) DisplayListManager.resumeRecording(savedRecorder);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2345,62 +2344,21 @@ public class GLStateManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void glDrawElementsBaseVertex(int mode, int count, int type, long indices, int basevertex) {
|
public static void glDrawElementsBaseVertex(int mode, int count, int type, long indices, int basevertex) {
|
||||||
ShaderManager.getInstance().preDraw();
|
preDraw(mode);
|
||||||
prepareClientArrays();
|
|
||||||
RENDER_BACKEND.drawElementsBaseVertex(mode, count, type, indices, basevertex);
|
RENDER_BACKEND.drawElementsBaseVertex(mode, count, type, indices, basevertex);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void glDrawElementsInstanced(int mode, int count, int type, long indices, int primcount) {
|
public static void glDrawElementsInstanced(int mode, int count, int type, long indices, int primcount) {
|
||||||
ShaderManager.getInstance().preDraw();
|
preDraw(mode);
|
||||||
prepareClientArrays();
|
|
||||||
RENDER_BACKEND.drawElementsInstanced(mode, count, type, indices, primcount);
|
RENDER_BACKEND.drawElementsInstanced(mode, count, type, indices, primcount);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void prepareClientArrays() {
|
private static void prepareClientArrays() {
|
||||||
if (ShaderManager.getInstance().isEnabled() && VertexAttribState.hasAnyClientSideEnabledAttrib()) {
|
if (VAOManager.hasAnyClientSideEnabledAttrib()) {
|
||||||
uploadClientArraysToVBO();
|
VAOManager.uploadClientArraysToVBO();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* If any enabled vertex attribute uses a client-side pointer (no VBO), upload all such
|
|
||||||
* attribs into a shared stream VBO so the draw succeeds under core profile.
|
|
||||||
*/
|
|
||||||
private static void uploadClientArraysToVBO() {
|
|
||||||
int totalBytes = 0;
|
|
||||||
for (int i = 0; i < VertexAttribState.MAX_ATTRIBS; i++) {
|
|
||||||
clientArraysVBOOffsets[i] = -1;
|
|
||||||
final VertexAttribState.Attrib a = VertexAttribState.get(i);
|
|
||||||
if (!a.enabled || a.clientPointer == null) continue;
|
|
||||||
clientArraysVBOOffsets[i] = totalBytes;
|
|
||||||
totalBytes += a.clientPointer.remaining();
|
|
||||||
}
|
|
||||||
if (totalBytes == 0) return;
|
|
||||||
|
|
||||||
if (clientArraysVBO == 0) {
|
|
||||||
clientArraysVBO = RENDER_BACKEND.genBuffers();
|
|
||||||
}
|
|
||||||
|
|
||||||
final int savedVBO = boundVBO;
|
|
||||||
glBindBuffer(GL15.GL_ARRAY_BUFFER, clientArraysVBO);
|
|
||||||
|
|
||||||
if (totalBytes > clientArraysVBOCapacity) {
|
|
||||||
int newCap = Math.max(4096, clientArraysVBOCapacity);
|
|
||||||
while (newCap < totalBytes) newCap *= 2;
|
|
||||||
clientArraysVBOCapacity = newCap;
|
|
||||||
}
|
|
||||||
RENDER_BACKEND.bufferData(GL15.GL_ARRAY_BUFFER, clientArraysVBOCapacity, GL15.GL_STREAM_DRAW);
|
|
||||||
|
|
||||||
for (int i = 0; i < VertexAttribState.MAX_ATTRIBS; i++) {
|
|
||||||
if (clientArraysVBOOffsets[i] < 0) continue;
|
|
||||||
final VertexAttribState.Attrib a = VertexAttribState.get(i);
|
|
||||||
RENDER_BACKEND.bufferSubData(GL15.GL_ARRAY_BUFFER, clientArraysVBOOffsets[i], a.clientPointer.duplicate());
|
|
||||||
RENDER_BACKEND.vertexAttribPointer(i, a.size, a.type, a.normalized, a.stride, (long) clientArraysVBOOffsets[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
glBindBuffer(GL15.GL_ARRAY_BUFFER, savedVBO);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void glDrawArrays(int mode, int first, int count) {
|
public static void glDrawArrays(int mode, int first, int count) {
|
||||||
CommandRecorder savedRecorder = null;
|
CommandRecorder savedRecorder = null;
|
||||||
final RecordMode recordMode = DisplayListManager.getRecordMode();
|
final RecordMode recordMode = DisplayListManager.getRecordMode();
|
||||||
@@ -2417,16 +2375,16 @@ public class GLStateManager {
|
|||||||
FeedbackManager.processDrawArrays(mode, first, count);
|
FeedbackManager.processDrawArrays(mode, first, count);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
prepareWideLineEmulation(mode);
|
|
||||||
ShaderManager.getInstance().preDraw();
|
|
||||||
prepareClientArrays();
|
|
||||||
if (mode == GL11.GL_QUADS) {
|
if (mode == GL11.GL_QUADS) {
|
||||||
QuadConverter.drawQuadsAsTriangles(first, count);
|
QuadConverter.drawQuadsAsTriangles(first, count);
|
||||||
} else if (mode == GL11.GL_QUAD_STRIP) {
|
} else if (mode == GL11.GL_QUAD_STRIP) {
|
||||||
|
preDraw();
|
||||||
RENDER_BACKEND.drawArrays(GL11.GL_TRIANGLE_STRIP, first, count & ~1);
|
RENDER_BACKEND.drawArrays(GL11.GL_TRIANGLE_STRIP, first, count & ~1);
|
||||||
} else if (mode == GL11.GL_POLYGON) {
|
} else if (mode == GL11.GL_POLYGON) {
|
||||||
|
preDraw();
|
||||||
RENDER_BACKEND.drawArrays(GL11.GL_TRIANGLE_FAN, first, count);
|
RENDER_BACKEND.drawArrays(GL11.GL_TRIANGLE_FAN, first, count);
|
||||||
} else {
|
} else {
|
||||||
|
preDraw(mode);
|
||||||
RENDER_BACKEND.drawArrays(mode, first, count);
|
RENDER_BACKEND.drawArrays(mode, first, count);
|
||||||
}
|
}
|
||||||
if (savedRecorder != null) DisplayListManager.resumeRecording(savedRecorder);
|
if (savedRecorder != null) DisplayListManager.resumeRecording(savedRecorder);
|
||||||
@@ -2573,14 +2531,14 @@ public class GLStateManager {
|
|||||||
final int location = clientStateToAttributeLocation(cap);
|
final int location = clientStateToAttributeLocation(cap);
|
||||||
if (location >= 0) glEnableVertexAttribArray(location);
|
if (location >= 0) glEnableVertexAttribArray(location);
|
||||||
final int flag = clientStateToVertexFlag(cap);
|
final int flag = clientStateToVertexFlag(cap);
|
||||||
if (flag != 0) ShaderManager.getInstance().enableClientVertexFlag(flag);
|
if (flag != 0) VAOManager.enableClientVertexFlag(flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void glDisableClientState(int cap) {
|
public static void glDisableClientState(int cap) {
|
||||||
final int location = clientStateToAttributeLocation(cap);
|
final int location = clientStateToAttributeLocation(cap);
|
||||||
if (location >= 0) glDisableVertexAttribArray(location);
|
if (location >= 0) glDisableVertexAttribArray(location);
|
||||||
final int flag = clientStateToVertexFlag(cap);
|
final int flag = clientStateToVertexFlag(cap);
|
||||||
if (flag != 0) ShaderManager.getInstance().disableClientVertexFlag(flag);
|
if (flag != 0) VAOManager.disableClientVertexFlag(flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void glVertexAttrib2f(int index, float v0, float v1) {
|
public static void glVertexAttrib2f(int index, float v0, float v1) {
|
||||||
@@ -2600,7 +2558,7 @@ public class GLStateManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, long offset) {
|
public static void glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, long offset) {
|
||||||
VertexAttribState.set(index, size, type, normalized, stride, offset, boundVBO);
|
VAOManager.setAttribute(index, size, type, normalized, stride, offset, boundVBO);
|
||||||
RENDER_BACKEND.vertexAttribPointer(index, size, type, normalized, stride, offset);
|
RENDER_BACKEND.vertexAttribPointer(index, size, type, normalized, stride, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2609,40 +2567,40 @@ public class GLStateManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, FloatBuffer pointer) {
|
public static void glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, FloatBuffer pointer) {
|
||||||
VertexAttribState.set(index, size, type, normalized, stride, MemoryUtilities.memByteBuffer(pointer), 0);
|
VAOManager.setAttribute(index, size, type, normalized, stride, MemoryUtilities.memByteBuffer(pointer));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, DoubleBuffer pointer) {
|
public static void glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, DoubleBuffer pointer) {
|
||||||
VertexAttribState.set(index, size, type, normalized, stride, MemoryUtilities.memByteBuffer(pointer), 0);
|
VAOManager.setAttribute(index, size, type, normalized, stride, MemoryUtilities.memByteBuffer(pointer));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, IntBuffer pointer) {
|
public static void glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, IntBuffer pointer) {
|
||||||
VertexAttribState.set(index, size, type, normalized, stride, MemoryUtilities.memByteBuffer(pointer), 0);
|
VAOManager.setAttribute(index, size, type, normalized, stride, MemoryUtilities.memByteBuffer(pointer));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, ShortBuffer pointer) {
|
public static void glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, ShortBuffer pointer) {
|
||||||
VertexAttribState.set(index, size, type, normalized, stride, MemoryUtilities.memByteBuffer(pointer), 0);
|
VAOManager.setAttribute(index, size, type, normalized, stride, MemoryUtilities.memByteBuffer(pointer));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, ByteBuffer pointer) {
|
public static void glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, ByteBuffer pointer) {
|
||||||
VertexAttribState.set(index, size, type, normalized, stride, pointer, 0);
|
VAOManager.setAttribute(index, size, type, normalized, stride, pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void glVertexAttribIPointer(int index, int size, int type, int stride, long offset) {
|
public static void glVertexAttribIPointer(int index, int size, int type, int stride, long offset) {
|
||||||
VertexAttribState.set(index, size, type, false, stride, offset, boundVBO);
|
VAOManager.setAttribute(index, size, type, false, stride, offset, boundVBO);
|
||||||
RENDER_BACKEND.vertexAttribIPointer(index, size, type, stride, offset);
|
RENDER_BACKEND.vertexAttribIPointer(index, size, type, stride, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void glVertexAttribIPointer(int index, int size, int type, int stride, ByteBuffer pointer) {
|
public static void glVertexAttribIPointer(int index, int size, int type, int stride, ByteBuffer pointer) {
|
||||||
VertexAttribState.set(index, size, type, false, stride, pointer, 0);
|
VAOManager.setAttribute(index, size, type, false, stride, pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void glVertexAttribIPointer(int index, int size, int type, int stride, IntBuffer pointer) {
|
public static void glVertexAttribIPointer(int index, int size, int type, int stride, IntBuffer pointer) {
|
||||||
VertexAttribState.set(index, size, type, false, stride, MemoryUtilities.memByteBuffer(pointer), 0);
|
VAOManager.setAttribute(index, size, type, false, stride, MemoryUtilities.memByteBuffer(pointer));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void glVertexAttribIPointer(int index, int size, int type, int stride, ShortBuffer pointer) {
|
public static void glVertexAttribIPointer(int index, int size, int type, int stride, ShortBuffer pointer) {
|
||||||
VertexAttribState.set(index, size, type, false, stride, MemoryUtilities.memByteBuffer(pointer), 0);
|
VAOManager.setAttribute(index, size, type, false, stride, MemoryUtilities.memByteBuffer(pointer));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void glVertexAttribDivisor(int index, int divisor) { RENDER_BACKEND.vertexAttribDivisor(index, divisor); }
|
public static void glVertexAttribDivisor(int index, int divisor) { RENDER_BACKEND.vertexAttribDivisor(index, divisor); }
|
||||||
@@ -2653,12 +2611,12 @@ public class GLStateManager {
|
|||||||
public static void glVertexAttribBinding(int attribindex, int bindingindex) { RENDER_BACKEND.vertexAttribBinding(attribindex, bindingindex); }
|
public static void glVertexAttribBinding(int attribindex, int bindingindex) { RENDER_BACKEND.vertexAttribBinding(attribindex, bindingindex); }
|
||||||
|
|
||||||
public static void glEnableVertexAttribArray(int index) {
|
public static void glEnableVertexAttribArray(int index) {
|
||||||
VertexAttribState.setEnabled(index, true);
|
VAOManager.enableAttribute(index);
|
||||||
RENDER_BACKEND.enableVertexAttribArray(index);
|
RENDER_BACKEND.enableVertexAttribArray(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void glDisableVertexAttribArray(int index) {
|
public static void glDisableVertexAttribArray(int index) {
|
||||||
VertexAttribState.setEnabled(index, false);
|
VAOManager.disableAttribute(index);
|
||||||
RENDER_BACKEND.disableVertexAttribArray(index);
|
RENDER_BACKEND.disableVertexAttribArray(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2693,7 +2651,7 @@ public class GLStateManager {
|
|||||||
public static void glPushClientAttrib(int mask) {
|
public static void glPushClientAttrib(int mask) {
|
||||||
if (clientAttribStackPointer < CLIENT_ATTRIB_STACK_DEPTH) {
|
if (clientAttribStackPointer < CLIENT_ATTRIB_STACK_DEPTH) {
|
||||||
clientAttribSavedTextureUnit[clientAttribStackPointer] = clientActiveTextureUnit;
|
clientAttribSavedTextureUnit[clientAttribStackPointer] = clientActiveTextureUnit;
|
||||||
clientAttribSavedVertexFlags[clientAttribStackPointer] = ShaderManager.getInstance().getCurrentVertexFlags();
|
clientAttribSavedVertexFlags[clientAttribStackPointer] = VAOManager.getCurrentVertexFlags();
|
||||||
clientAttribStackPointer++;
|
clientAttribStackPointer++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2702,7 +2660,7 @@ public class GLStateManager {
|
|||||||
if (clientAttribStackPointer > 0) {
|
if (clientAttribStackPointer > 0) {
|
||||||
clientAttribStackPointer--;
|
clientAttribStackPointer--;
|
||||||
clientActiveTextureUnit = clientAttribSavedTextureUnit[clientAttribStackPointer];
|
clientActiveTextureUnit = clientAttribSavedTextureUnit[clientAttribStackPointer];
|
||||||
ShaderManager.getInstance().setCurrentVertexFlags(clientAttribSavedVertexFlags[clientAttribStackPointer]);
|
VAOManager.setCurrentVertexFlags(clientAttribSavedVertexFlags[clientAttribStackPointer]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4516,9 +4474,14 @@ public class GLStateManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void prepareWideLineEmulation(int drawMode) {
|
public static void prepareWideLineEmulation(int drawMode) {
|
||||||
wideLineEmulationActive = wideLineEmulationEnabled
|
wideLineEmulationActive =
|
||||||
&& (drawMode == GL11.GL_LINES || drawMode == GL11.GL_LINE_STRIP || drawMode == GL11.GL_LINE_LOOP)
|
(drawMode == GL11.GL_LINES || drawMode == GL11.GL_LINE_STRIP || drawMode == GL11.GL_LINE_LOOP)
|
||||||
&& lineState.getWidth() > 1.0f;
|
&& lineState.getWidth() > 1.0f
|
||||||
|
&& wideLineEmulationEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void disableWideLineEmulation() {
|
||||||
|
wideLineEmulationActive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void glFlush() {
|
public static void glFlush() {
|
||||||
@@ -5106,13 +5069,13 @@ public class GLStateManager {
|
|||||||
private static void invalidateDeletedBuffer(int buffer) {
|
private static void invalidateDeletedBuffer(int buffer) {
|
||||||
if (buffer == 0) return;
|
if (buffer == 0) return;
|
||||||
if (boundVBO == buffer) boundVBO = 0;
|
if (boundVBO == buffer) boundVBO = 0;
|
||||||
if (boundEBO == buffer) boundEBO = 0;
|
if (VAOManager.boundEBO == buffer) VAOManager.boundEBO = 0;
|
||||||
if (boundPixelUnpackBuffer == buffer) boundPixelUnpackBuffer = 0;
|
if (boundPixelUnpackBuffer == buffer) boundPixelUnpackBuffer = 0;
|
||||||
if (boundPixelPackBuffer == buffer) boundPixelPackBuffer = 0;
|
if (boundPixelPackBuffer == buffer) boundPixelPackBuffer = 0;
|
||||||
|
|
||||||
// Sweep all VAOs: an unbound VAO may later rebind with a dangling EBO id.
|
// Sweep all VAOs: an unbound VAO may later rebind with a dangling EBO id.
|
||||||
for (Int2IntMap.Entry e : vaoEboMap.int2IntEntrySet()) {
|
for (VAOManager.VAOData data : VAOManager.vaoMap.values()) {
|
||||||
if (e.getIntValue() == buffer) e.setValue(0);
|
if (data.ebo == buffer) data.ebo = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5121,8 +5084,7 @@ public class GLStateManager {
|
|||||||
// if (boundVBO == buffer) return; TODO figure out why this breaks switching async occlusion mode
|
// if (boundVBO == buffer) return; TODO figure out why this breaks switching async occlusion mode
|
||||||
boundVBO = buffer;
|
boundVBO = buffer;
|
||||||
} else if (target == GL15.GL_ELEMENT_ARRAY_BUFFER) {
|
} else if (target == GL15.GL_ELEMENT_ARRAY_BUFFER) {
|
||||||
boundEBO = buffer;
|
VAOManager.onBindEBO(buffer);
|
||||||
vaoEboMap.put(boundVAO, buffer);
|
|
||||||
} else if (target == GL21.GL_PIXEL_UNPACK_BUFFER) {
|
} else if (target == GL21.GL_PIXEL_UNPACK_BUFFER) {
|
||||||
boundPixelUnpackBuffer = buffer;
|
boundPixelUnpackBuffer = buffer;
|
||||||
} else if (target == GL21.GL_PIXEL_PACK_BUFFER) {
|
} else if (target == GL21.GL_PIXEL_PACK_BUFFER) {
|
||||||
@@ -5206,24 +5168,17 @@ public class GLStateManager {
|
|||||||
}
|
}
|
||||||
if (boundVAO != array) {
|
if (boundVAO != array) {
|
||||||
boundVAO = array;
|
boundVAO = array;
|
||||||
boundEBO = vaoEboMap.get(array);
|
VAOManager.onBindVertexArrayPre(array);
|
||||||
VertexAttribState.onBindVertexArray(array);
|
|
||||||
RENDER_BACKEND.bindVertexArray(array);
|
RENDER_BACKEND.bindVertexArray(array);
|
||||||
if (ShaderManager.getInstance().isEnabled()) {
|
|
||||||
ShaderManager.getInstance().onBindVertexArray(array);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void glDeleteVertexArrays(int array) {
|
public static void glDeleteVertexArrays(int array) {
|
||||||
ShaderManager.getInstance().onDeleteVertexArray(array);
|
VAOManager.onDeleteVertexArray(array);
|
||||||
VertexAttribState.onDeleteVertexArray(array);
|
|
||||||
vaoEboMap.remove(array);
|
|
||||||
if (array == boundVAO) {
|
if (array == boundVAO) {
|
||||||
// Deleting the bound VAO implicitly unbinds it. Rebind the default VAO.
|
// Deleting the bound VAO implicitly unbinds it. Rebind the default VAO.
|
||||||
boundVAO = defaultVAO;
|
boundVAO = defaultVAO;
|
||||||
boundEBO = vaoEboMap.get(defaultVAO);
|
VAOManager.onBindVertexArrayPre(defaultVAO);
|
||||||
VertexAttribState.onBindVertexArray(defaultVAO);
|
|
||||||
RENDER_BACKEND.bindVertexArray(defaultVAO);
|
RENDER_BACKEND.bindVertexArray(defaultVAO);
|
||||||
}
|
}
|
||||||
RENDER_BACKEND.deleteVertexArrays(array);
|
RENDER_BACKEND.deleteVertexArrays(array);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.gtnewhorizons.angelica.glsm;
|
package com.gtnewhorizons.angelica.glsm;
|
||||||
|
|
||||||
import com.gtnewhorizons.angelica.glsm.states.VertexAttribState;
|
import com.gtnewhorizons.angelica.glsm.ffp.VAOManager;
|
||||||
import org.lwjgl.opengl.GL11;
|
import org.lwjgl.opengl.GL11;
|
||||||
import org.lwjgl.opengl.GL15;
|
import org.lwjgl.opengl.GL15;
|
||||||
|
|
||||||
@@ -9,7 +9,6 @@ import java.nio.IntBuffer;
|
|||||||
import java.nio.ShortBuffer;
|
import java.nio.ShortBuffer;
|
||||||
|
|
||||||
import static com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities.memAddress0;
|
import static com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities.memAddress0;
|
||||||
import static com.gtnewhorizons.angelica.glsm.backend.BackendManager.RENDER_BACKEND;
|
|
||||||
import static com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities.memAlloc;
|
import static com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities.memAlloc;
|
||||||
import static com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities.memFree;
|
import static com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities.memFree;
|
||||||
import static com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities.memGetByte;
|
import static com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities.memGetByte;
|
||||||
@@ -17,6 +16,7 @@ import static com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities.memGetInt;
|
|||||||
import static com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities.memGetShort;
|
import static com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities.memGetShort;
|
||||||
import static com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities.memPutInt;
|
import static com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities.memPutInt;
|
||||||
import static com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities.memPutShort;
|
import static com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities.memPutShort;
|
||||||
|
import static com.gtnewhorizons.angelica.glsm.backend.BackendManager.RENDER_BACKEND;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shared quad-to-triangle EBO for core profile GL_QUADS emulation.
|
* Shared quad-to-triangle EBO for core profile GL_QUADS emulation.
|
||||||
@@ -83,6 +83,7 @@ public final class QuadConverter {
|
|||||||
* @param vertexCount number of vertices (must be multiple of 4)
|
* @param vertexCount number of vertices (must be multiple of 4)
|
||||||
*/
|
*/
|
||||||
public static void drawQuadsAsTriangles(int first, int vertexCount) {
|
public static void drawQuadsAsTriangles(int first, int vertexCount) {
|
||||||
|
GLStateManager.preDraw();
|
||||||
assert first % 4 == 0 : "QuadConverter: first (" + first + ") must be a multiple of 4";
|
assert first % 4 == 0 : "QuadConverter: first (" + first + ") must be a multiple of 4";
|
||||||
assert vertexCount % 4 == 0 : "QuadConverter: vertexCount (" + vertexCount + ") must be a multiple of 4";
|
assert vertexCount % 4 == 0 : "QuadConverter: vertexCount (" + vertexCount + ") must be a multiple of 4";
|
||||||
final int quadCount = vertexCount / 4;
|
final int quadCount = vertexCount / 4;
|
||||||
@@ -106,6 +107,7 @@ public final class QuadConverter {
|
|||||||
* @param bytesPerIndex bytes per index element
|
* @param bytesPerIndex bytes per index element
|
||||||
*/
|
*/
|
||||||
private static void uploadAndDraw(ByteBuffer dst, int triIndexCount, int indexType, int bytesPerIndex) {
|
private static void uploadAndDraw(ByteBuffer dst, int triIndexCount, int indexType, int bytesPerIndex) {
|
||||||
|
GLStateManager.preDraw();
|
||||||
final int needed = triIndexCount * bytesPerIndex;
|
final int needed = triIndexCount * bytesPerIndex;
|
||||||
final int prevEbo = GLStateManager.getBoundEBO();
|
final int prevEbo = GLStateManager.getBoundEBO();
|
||||||
|
|
||||||
@@ -144,7 +146,7 @@ public final class QuadConverter {
|
|||||||
final int quadCount = indexCount / 4;
|
final int quadCount = indexCount / 4;
|
||||||
final int triIndexCount = quadCount * 6;
|
final int triIndexCount = quadCount * 6;
|
||||||
|
|
||||||
final int bytesPerIndex = VertexAttribState.Attrib.glTypeSizeBytes(type);
|
final int bytesPerIndex = VAOManager.Attrib.glTypeSizeBytes(type);
|
||||||
|
|
||||||
final ByteBuffer src = memAlloc(indexCount * bytesPerIndex);
|
final ByteBuffer src = memAlloc(indexCount * bytesPerIndex);
|
||||||
RENDER_BACKEND.getBufferSubData(GL15.GL_ELEMENT_ARRAY_BUFFER, offset, src);
|
RENDER_BACKEND.getBufferSubData(GL15.GL_ELEMENT_ARRAY_BUFFER, offset, src);
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import com.gtnewhorizons.angelica.glsm.dsa.DSACore;
|
|||||||
import com.gtnewhorizons.angelica.glsm.dsa.DSAEXT;
|
import com.gtnewhorizons.angelica.glsm.dsa.DSAEXT;
|
||||||
import com.gtnewhorizons.angelica.glsm.dsa.DSAUnsupported;
|
import com.gtnewhorizons.angelica.glsm.dsa.DSAUnsupported;
|
||||||
import com.gtnewhorizons.angelica.glsm.ffp.ShaderManager;
|
import com.gtnewhorizons.angelica.glsm.ffp.ShaderManager;
|
||||||
import com.gtnewhorizons.angelica.glsm.hooks.GLSMInitConfig;
|
|
||||||
import com.gtnewhorizons.angelica.glsm.texture.TextureInfoCache;
|
import com.gtnewhorizons.angelica.glsm.texture.TextureInfoCache;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|||||||
@@ -1,15 +1,13 @@
|
|||||||
package com.gtnewhorizons.angelica.glsm.ffp;
|
package com.gtnewhorizons.angelica.glsm.ffp;
|
||||||
|
|
||||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFlags;
|
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFlags;
|
||||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFormat;
|
|
||||||
import com.gtnewhorizons.angelica.glsm.CompatUniformManager;
|
import com.gtnewhorizons.angelica.glsm.CompatUniformManager;
|
||||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||||
import com.gtnewhorizons.angelica.glsm.hooks.DeferredBlendHandler;
|
import com.gtnewhorizons.angelica.glsm.hooks.DeferredBlendHandler;
|
||||||
import com.gtnewhorizons.angelica.glsm.hooks.GLSMHooks;
|
import com.gtnewhorizons.angelica.glsm.hooks.GLSMHooks;
|
||||||
|
import com.gtnewhorizons.angelica.glsm.hooks.GLSMInitConfig;
|
||||||
import com.gtnewhorizons.angelica.glsm.stacks.Vec3fStack;
|
import com.gtnewhorizons.angelica.glsm.stacks.Vec3fStack;
|
||||||
import com.gtnewhorizons.angelica.glsm.stacks.Vec4fStack;
|
import com.gtnewhorizons.angelica.glsm.stacks.Vec4fStack;
|
||||||
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
|
||||||
import com.gtnewhorizons.angelica.glsm.hooks.GLSMInitConfig;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.joml.Vector3f;
|
import org.joml.Vector3f;
|
||||||
import org.joml.Vector4f;
|
import org.joml.Vector4f;
|
||||||
@@ -31,7 +29,6 @@ public final class ShaderManager {
|
|||||||
|
|
||||||
private final ShaderCache cache = new ShaderCache();
|
private final ShaderCache cache = new ShaderCache();
|
||||||
private final Uniforms uniforms = new Uniforms();
|
private final Uniforms uniforms = new Uniforms();
|
||||||
private final Int2IntOpenHashMap vaoVertexFlags = new Int2IntOpenHashMap();
|
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private boolean active = false;
|
private boolean active = false;
|
||||||
@@ -57,10 +54,8 @@ public final class ShaderManager {
|
|||||||
public static Vector4f getCurrentTexCoord() { return currentTexCoords[0]; }
|
public static Vector4f getCurrentTexCoord() { return currentTexCoords[0]; }
|
||||||
public static Vector4f getCurrentTexCoord(int unit) { return currentTexCoords[unit]; }
|
public static Vector4f getCurrentTexCoord(int unit) { return currentTexCoords[unit]; }
|
||||||
@Getter private boolean enabled = false;
|
@Getter private boolean enabled = false;
|
||||||
private int currentVertexFlags = VertexFlags.TEXTURE_BIT | VertexFlags.COLOR_BIT | VertexFlags.NORMAL_BIT;
|
|
||||||
|
|
||||||
private ShaderManager() {
|
private ShaderManager() {
|
||||||
vaoVertexFlags.defaultReturnValue(-1);
|
|
||||||
if (Boolean.parseBoolean(System.getProperty("angelica.dumpShaders", "false"))) {
|
if (Boolean.parseBoolean(System.getProperty("angelica.dumpShaders", "false"))) {
|
||||||
cache.setDumpDir(Paths.get("ffp_shaders"));
|
cache.setDumpDir(Paths.get("ffp_shaders"));
|
||||||
}
|
}
|
||||||
@@ -73,12 +68,6 @@ public final class ShaderManager {
|
|||||||
public void enable() {
|
public void enable() {
|
||||||
enabled = true;
|
enabled = true;
|
||||||
|
|
||||||
VertexFormat.registerSetupBufferStateOverride((format, offset) -> {
|
|
||||||
currentVertexFlags = format.getVertexFlags();
|
|
||||||
vaoVertexFlags.put(GLStateManager.getBoundVAO(), currentVertexFlags);
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
GLStateManager.LOGGER.info("FFP shader emulation enabled");
|
GLStateManager.LOGGER.info("FFP shader emulation enabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,7 +88,7 @@ public final class ShaderManager {
|
|||||||
currentFKLen = 0;
|
currentFKLen = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void preDraw(boolean hasColor, boolean hasNormal, boolean hasTexCoord, boolean hasLightmap) {
|
public void preDraw() {
|
||||||
final DeferredBlendHandler bh = GLSMHooks.blendHandler;
|
final DeferredBlendHandler bh = GLSMHooks.blendHandler;
|
||||||
if (bh != null) bh.flushDeferredBlend();
|
if (bh != null) bh.flushDeferredBlend();
|
||||||
|
|
||||||
@@ -111,7 +100,12 @@ public final class ShaderManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GLStateManager.flushDeferredVertexAttribs(currentVertexFlags);
|
final int vertexFlags = VAOManager.getCurrentVertexFlags();
|
||||||
|
final boolean hasColor = (vertexFlags & VertexFlags.COLOR_BIT) != 0;
|
||||||
|
final boolean hasNormal = (vertexFlags & VertexFlags.NORMAL_BIT) != 0;
|
||||||
|
final boolean hasTexCoord = (vertexFlags & VertexFlags.TEXTURE_BIT) != 0;
|
||||||
|
final boolean hasLightmap = (vertexFlags & VertexFlags.BRIGHTNESS_BIT) != 0;
|
||||||
|
GLStateManager.flushDeferredVertexAttribs(hasColor, hasNormal, hasTexCoord, hasLightmap);
|
||||||
|
|
||||||
if (!active) return;
|
if (!active) return;
|
||||||
|
|
||||||
@@ -127,20 +121,6 @@ public final class ShaderManager {
|
|||||||
uploadUniforms();
|
uploadUniforms();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void preDraw(int vertexFlags) {
|
|
||||||
currentVertexFlags = vertexFlags;
|
|
||||||
preDraw(
|
|
||||||
(vertexFlags & VertexFlags.COLOR_BIT) != 0,
|
|
||||||
(vertexFlags & VertexFlags.NORMAL_BIT) != 0,
|
|
||||||
(vertexFlags & VertexFlags.TEXTURE_BIT) != 0,
|
|
||||||
(vertexFlags & VertexFlags.BRIGHTNESS_BIT) != 0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void preDraw() {
|
|
||||||
preDraw(currentVertexFlags);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void commitVariant(long vkPacked, int fkLen) {
|
private void commitVariant(long vkPacked, int fkLen) {
|
||||||
currentVertexKeyPacked = vkPacked;
|
currentVertexKeyPacked = vkPacked;
|
||||||
System.arraycopy(currentFKScratch, 0, currentFKPacked, 0, fkLen);
|
System.arraycopy(currentFKScratch, 0, currentFKPacked, 0, fkLen);
|
||||||
@@ -177,22 +157,6 @@ public final class ShaderManager {
|
|||||||
public static void bumpNormalGeneration() { normalGeneration++; }
|
public static void bumpNormalGeneration() { normalGeneration++; }
|
||||||
public static void bumpTexCoordGeneration() { texCoordGeneration++; }
|
public static void bumpTexCoordGeneration() { texCoordGeneration++; }
|
||||||
|
|
||||||
public void enableClientVertexFlag(int flag) {currentVertexFlags |= flag;}
|
|
||||||
public void disableClientVertexFlag(int flag) {currentVertexFlags &= ~flag;}
|
|
||||||
public int getCurrentVertexFlags() {return currentVertexFlags;}
|
|
||||||
public void setCurrentVertexFlags(int flags) {currentVertexFlags = flags;}
|
|
||||||
|
|
||||||
public void onBindVertexArray(int vaoId) {
|
|
||||||
final int flags = vaoVertexFlags.get(vaoId);
|
|
||||||
if (flags != -1) {
|
|
||||||
currentVertexFlags = flags;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onDeleteVertexArray(int vaoId) {
|
|
||||||
vaoVertexFlags.remove(vaoId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
cache.destroy();
|
cache.destroy();
|
||||||
uniforms.destroy();
|
uniforms.destroy();
|
||||||
|
|||||||
@@ -0,0 +1,312 @@
|
|||||||
|
package com.gtnewhorizons.angelica.glsm.ffp;
|
||||||
|
|
||||||
|
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||||
|
import org.lwjgl.opengl.GL11;
|
||||||
|
import org.lwjgl.opengl.GL15;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import static com.gtnewhorizons.angelica.glsm.backend.BackendManager.RENDER_BACKEND;
|
||||||
|
|
||||||
|
public final class VAOManager {
|
||||||
|
public static final int MAX_ATTRIBS = 16;
|
||||||
|
|
||||||
|
public static final Int2ObjectOpenHashMap<VAOData> vaoMap = new Int2ObjectOpenHashMap<>();
|
||||||
|
|
||||||
|
private static VAOData current = null;
|
||||||
|
private static int currentVertexFlags = 0;
|
||||||
|
private static Attrib[] currentAttribs = null;
|
||||||
|
public static int boundEBO = 0;
|
||||||
|
|
||||||
|
private static int clientSideEnabledCount = 0;
|
||||||
|
|
||||||
|
|
||||||
|
public static void init(int defaultVAO) {
|
||||||
|
final VAOData data = new VAOData();
|
||||||
|
current = data;
|
||||||
|
currentAttribs = data.attribs;
|
||||||
|
vaoMap.put(defaultVAO, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void onBindEBO(int ebo) {
|
||||||
|
boundEBO = ebo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void onBindVertexArrayPre(int vaoId) {
|
||||||
|
// Save old VAO data
|
||||||
|
if (current != null) {
|
||||||
|
current.vertexFlags = currentVertexFlags;
|
||||||
|
current.ebo = boundEBO;
|
||||||
|
current.attribs = currentAttribs;
|
||||||
|
}
|
||||||
|
|
||||||
|
VAOData data = vaoMap.get(vaoId);
|
||||||
|
if (data == null) {
|
||||||
|
data = new VAOData();
|
||||||
|
vaoMap.put(vaoId, data);
|
||||||
|
}
|
||||||
|
current = data;
|
||||||
|
currentVertexFlags = data.vertexFlags;
|
||||||
|
currentAttribs = data.attribs;
|
||||||
|
boundEBO = data.ebo;
|
||||||
|
|
||||||
|
recomputeClientSideCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void onDeleteVertexArray(int vaoId) {
|
||||||
|
vaoMap.remove(vaoId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void enableClientVertexFlag(int flag) { currentVertexFlags |= flag; }
|
||||||
|
public static void disableClientVertexFlag(int flag) { currentVertexFlags &= ~flag; }
|
||||||
|
public static int getCurrentVertexFlags() { return currentVertexFlags; }
|
||||||
|
public static void setCurrentVertexFlags(int flags) { currentVertexFlags = flags; }
|
||||||
|
|
||||||
|
public static final class VAOData {
|
||||||
|
public Attrib[] attribs;
|
||||||
|
public int vertexFlags;
|
||||||
|
public int ebo;
|
||||||
|
|
||||||
|
public VAOData() {
|
||||||
|
attribs = new Attrib[MAX_ATTRIBS];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setAttribute(int index, int size, int type, boolean normalized, int stride, long offset, int vboId) {
|
||||||
|
if (index < 0 || index >= MAX_ATTRIBS) return;
|
||||||
|
final Attrib a = getAttrib(index);
|
||||||
|
final boolean wasClient = a.clientPointer != null;
|
||||||
|
a.size = size;
|
||||||
|
a.type = type;
|
||||||
|
a.normalized = normalized;
|
||||||
|
a.stride = stride;
|
||||||
|
a.offset = offset;
|
||||||
|
a.vboId = vboId;
|
||||||
|
a.clientPointer = null;
|
||||||
|
if (wasClient && a.enabled) {
|
||||||
|
clientSideEnabledCount--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setAttribute(int index, int size, int type, boolean normalized, int stride, ByteBuffer pointer) {
|
||||||
|
if (index < 0 || index >= MAX_ATTRIBS) return;
|
||||||
|
final Attrib a = getAttrib(index);
|
||||||
|
final boolean wasClient = a.clientPointer != null;
|
||||||
|
a.size = size;
|
||||||
|
a.type = type;
|
||||||
|
a.normalized = normalized;
|
||||||
|
a.stride = stride;
|
||||||
|
a.offset = 0;
|
||||||
|
a.vboId = 0;
|
||||||
|
a.clientPointer = pointer;
|
||||||
|
if (!wasClient && a.enabled) {
|
||||||
|
clientSideEnabledCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setEnabled(int index, boolean enabled) {
|
||||||
|
if (index < 0 || index >= MAX_ATTRIBS) return;
|
||||||
|
final Attrib a = getAttrib(index);
|
||||||
|
if (a.clientPointer != null && a.enabled != enabled) {
|
||||||
|
clientSideEnabledCount += enabled ? 1 : -1;
|
||||||
|
}
|
||||||
|
a.enabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void enableAttribute(int index) {
|
||||||
|
if (index < 0 || index >= MAX_ATTRIBS) return;
|
||||||
|
final Attrib a = getAttrib(index);
|
||||||
|
if (a.clientPointer != null && !a.enabled) {
|
||||||
|
clientSideEnabledCount++;
|
||||||
|
}
|
||||||
|
a.enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void disableAttribute(int index) {
|
||||||
|
if (index < 0 || index >= MAX_ATTRIBS) return;
|
||||||
|
final Attrib a = getAttrib(index);
|
||||||
|
if (a.clientPointer != null && a.enabled) {
|
||||||
|
clientSideEnabledCount--;
|
||||||
|
}
|
||||||
|
a.enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lazily allocate each attrib. Most VAOs don't even have 4 attribs, let alone 16.
|
||||||
|
private static Attrib getAttrib(int index) {
|
||||||
|
Attrib a = currentAttribs[index];
|
||||||
|
if (a == null) {
|
||||||
|
a = new Attrib();
|
||||||
|
currentAttribs[index] = a;
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isClientSideAttrib(int index) {
|
||||||
|
final Attrib attrib = currentAttribs[index];
|
||||||
|
return attrib != null && attrib.isClientSide();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getAttribEffectiveStride(int index) {
|
||||||
|
final Attrib attrib = currentAttribs[index];
|
||||||
|
return attrib != null ? attrib.effectiveStride() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long getAttribOffset(int index) {
|
||||||
|
final Attrib attrib = currentAttribs[index];
|
||||||
|
return attrib != null ? attrib.offset : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getAttribVBO(int index) {
|
||||||
|
final Attrib attrib = currentAttribs[index];
|
||||||
|
return attrib != null ? attrib.vboId : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static @Nullable Attrib get(int index) {
|
||||||
|
return currentAttribs[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private static void recomputeClientSideCount() {
|
||||||
|
int count = 0;
|
||||||
|
for (int i = 0; i < MAX_ATTRIBS; i++) {
|
||||||
|
if (isClientSideAttrib(i)) count++;
|
||||||
|
}
|
||||||
|
clientSideEnabledCount = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if any currently enabled vertex attribute was registered without a VBO
|
||||||
|
* (i.e. as a client-side pointer). In core profile, such attribs are treated as null
|
||||||
|
* offsets into a non-existent buffer, causing a native crash at draw time.
|
||||||
|
*/
|
||||||
|
public static boolean hasAnyClientSideEnabledAttrib() {
|
||||||
|
return clientSideEnabledCount > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If any enabled vertex attribute uses a client-side pointer (no VBO), upload all such
|
||||||
|
* attribs into a shared stream VBO so the draw succeeds under core profile.
|
||||||
|
*/
|
||||||
|
private static int clientArraysVBO = 0;
|
||||||
|
private static int clientArraysVBOCapacity = 0;
|
||||||
|
private static final int[] clientArraysVBOOffsets = new int[VAOManager.MAX_ATTRIBS];
|
||||||
|
|
||||||
|
public static void uploadClientArraysToVBO() {
|
||||||
|
int totalBytes = 0;
|
||||||
|
for (int i = 0; i < VAOManager.MAX_ATTRIBS; i++) {
|
||||||
|
clientArraysVBOOffsets[i] = -1;
|
||||||
|
final VAOManager.Attrib a = VAOManager.get(i);
|
||||||
|
if (a == null || !a.enabled || a.clientPointer == null) continue;
|
||||||
|
clientArraysVBOOffsets[i] = totalBytes;
|
||||||
|
totalBytes += a.clientPointer.remaining();
|
||||||
|
}
|
||||||
|
if (totalBytes == 0) return;
|
||||||
|
|
||||||
|
if (clientArraysVBO == 0) {
|
||||||
|
clientArraysVBO = RENDER_BACKEND.genBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
final int savedVBO = GLStateManager.getBoundVBO();
|
||||||
|
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, clientArraysVBO);
|
||||||
|
|
||||||
|
if (totalBytes > clientArraysVBOCapacity) {
|
||||||
|
int newCap = Math.max(4096, clientArraysVBOCapacity);
|
||||||
|
while (newCap < totalBytes) newCap *= 2;
|
||||||
|
clientArraysVBOCapacity = newCap;
|
||||||
|
}
|
||||||
|
RENDER_BACKEND.bufferData(GL15.GL_ARRAY_BUFFER, clientArraysVBOCapacity, GL15.GL_STREAM_DRAW);
|
||||||
|
|
||||||
|
for (int i = 0; i < VAOManager.MAX_ATTRIBS; i++) {
|
||||||
|
if (clientArraysVBOOffsets[i] < 0) continue;
|
||||||
|
final VAOManager.Attrib a = VAOManager.get(i);
|
||||||
|
RENDER_BACKEND.bufferSubData(GL15.GL_ARRAY_BUFFER, clientArraysVBOOffsets[i], a.clientPointer.duplicate());
|
||||||
|
RENDER_BACKEND.vertexAttribPointer(i, a.size, a.type, a.normalized, a.stride, (long) clientArraysVBOOffsets[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, savedVBO);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static final class Attrib {
|
||||||
|
public boolean enabled;
|
||||||
|
public int size;
|
||||||
|
public int type;
|
||||||
|
public boolean normalized;
|
||||||
|
public int stride;
|
||||||
|
public long offset;
|
||||||
|
public int vboId;
|
||||||
|
public ByteBuffer clientPointer;
|
||||||
|
|
||||||
|
public boolean isClientSide() {
|
||||||
|
return enabled && clientPointer != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset() {
|
||||||
|
enabled = false;
|
||||||
|
size = 0;
|
||||||
|
type = 0;
|
||||||
|
normalized = false;
|
||||||
|
stride = 0;
|
||||||
|
offset = 0;
|
||||||
|
vboId = 0;
|
||||||
|
clientPointer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int effectiveStride() {
|
||||||
|
return (stride != 0) ? stride : size * typeSizeBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int typeSizeBytes() {
|
||||||
|
return glTypeSizeBytes(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int glTypeSizeBytes(int glType) {
|
||||||
|
return switch (glType) {
|
||||||
|
case GL11.GL_FLOAT, GL11.GL_INT, GL11.GL_UNSIGNED_INT -> 4;
|
||||||
|
case GL11.GL_DOUBLE -> 8;
|
||||||
|
case GL11.GL_SHORT, GL11.GL_UNSIGNED_SHORT -> 2;
|
||||||
|
case GL11.GL_BYTE, GL11.GL_UNSIGNED_BYTE -> 1;
|
||||||
|
default -> 4;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public float readComponent(ByteBuffer buf, int base, int component) {
|
||||||
|
return readComponent(type, normalized, buf, base, component);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float readComponent(int type, boolean normalized, ByteBuffer buf, int base, int component) {
|
||||||
|
return switch (type) {
|
||||||
|
case GL11.GL_FLOAT -> buf.getFloat(base + component * 4);
|
||||||
|
case GL11.GL_DOUBLE -> (float) buf.getDouble(base + component * 8);
|
||||||
|
case GL11.GL_INT -> {
|
||||||
|
final int v = buf.getInt(base + component * 4);
|
||||||
|
yield normalized ? v / (float) Integer.MAX_VALUE : (float) v;
|
||||||
|
}
|
||||||
|
case GL11.GL_UNSIGNED_INT -> {
|
||||||
|
final int v = buf.getInt(base + component * 4);
|
||||||
|
yield normalized ? (v & 0xFFFFFFFFL) / (float) 0xFFFFFFFFL : (float) (v & 0xFFFFFFFFL);
|
||||||
|
}
|
||||||
|
case GL11.GL_SHORT -> {
|
||||||
|
final short v = buf.getShort(base + component * 2);
|
||||||
|
yield normalized ? v / (float) Short.MAX_VALUE : (float) v;
|
||||||
|
}
|
||||||
|
case GL11.GL_UNSIGNED_SHORT -> {
|
||||||
|
final int v = buf.getShort(base + component * 2) & 0xFFFF;
|
||||||
|
yield normalized ? v / (float) 0xFFFF : (float) v;
|
||||||
|
}
|
||||||
|
case GL11.GL_BYTE -> {
|
||||||
|
final byte v = buf.get(base + component);
|
||||||
|
yield normalized ? v / 127.0f : (float) v;
|
||||||
|
}
|
||||||
|
case GL11.GL_UNSIGNED_BYTE -> {
|
||||||
|
final int v = buf.get(base + component) & 0xFF;
|
||||||
|
yield normalized ? v / 255.0f : (float) v;
|
||||||
|
}
|
||||||
|
default -> 0.0f;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@ package com.gtnewhorizons.angelica.glsm.recording;
|
|||||||
|
|
||||||
import com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities;
|
import com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities;
|
||||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||||
import com.gtnewhorizons.angelica.glsm.states.VertexAttribState;
|
import com.gtnewhorizons.angelica.glsm.ffp.VAOManager;
|
||||||
import it.unimi.dsi.fastutil.ints.Int2LongOpenHashMap;
|
import it.unimi.dsi.fastutil.ints.Int2LongOpenHashMap;
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||||
import org.lwjgl.opengl.GL15;
|
import org.lwjgl.opengl.GL15;
|
||||||
@@ -15,11 +15,11 @@ public final class AttribSnapshot {
|
|||||||
|
|
||||||
public record AttribDesc(int location, int size, int type, boolean normalized, int stride, long offset, int sourceVboId, ByteBuffer readBuffer, long readBufferBaseOffset) {
|
public record AttribDesc(int location, int size, int type, boolean normalized, int stride, long offset, int sourceVboId, ByteBuffer readBuffer, long readBufferBaseOffset) {
|
||||||
public int effectiveStride() {
|
public int effectiveStride() {
|
||||||
return stride != 0 ? stride : size * VertexAttribState.Attrib.glTypeSizeBytes(type);
|
return stride != 0 ? stride : size * VAOManager.Attrib.glTypeSizeBytes(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int typeSizeBytes() {
|
public int typeSizeBytes() {
|
||||||
return VertexAttribState.Attrib.glTypeSizeBytes(type);
|
return VAOManager.Attrib.glTypeSizeBytes(type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,7 +56,7 @@ public final class AttribSnapshot {
|
|||||||
* allocating any hashmaps. A second distinct VBO promotes to the map-backed fallback.
|
* allocating any hashmaps. A second distinct VBO promotes to the map-backed fallback.
|
||||||
*/
|
*/
|
||||||
public static AttribSnapshot snapshot(int firstVertex, int vertexCount) {
|
public static AttribSnapshot snapshot(int firstVertex, int vertexCount) {
|
||||||
final AttribDesc[] out = new AttribDesc[VertexAttribState.MAX_ATTRIBS];
|
final AttribDesc[] out = new AttribDesc[VAOManager.MAX_ATTRIBS];
|
||||||
final List<ByteBuffer> allocated = new ArrayList<>();
|
final List<ByteBuffer> allocated = new ArrayList<>();
|
||||||
final int prevVBO = GLStateManager.getBoundVBO();
|
final int prevVBO = GLStateManager.getBoundVBO();
|
||||||
|
|
||||||
@@ -67,11 +67,11 @@ public final class AttribSnapshot {
|
|||||||
Int2ObjectOpenHashMap<long[]> vboRanges = null;
|
Int2ObjectOpenHashMap<long[]> vboRanges = null;
|
||||||
|
|
||||||
final long lastVtx = (long) firstVertex + vertexCount - 1;
|
final long lastVtx = (long) firstVertex + vertexCount - 1;
|
||||||
for (int i = 0; i < VertexAttribState.MAX_ATTRIBS; i++) {
|
for (int i = 0; i < VAOManager.MAX_ATTRIBS; i++) {
|
||||||
final VertexAttribState.Attrib a = VertexAttribState.get(i);
|
final VAOManager.Attrib a = VAOManager.get(i);
|
||||||
if (!a.enabled || a.vboId == 0) continue;
|
if (a == null || !a.enabled || a.vboId == 0) continue;
|
||||||
final int stride = a.effectiveStride();
|
final int stride = a.effectiveStride();
|
||||||
final long typeBytes = (long) a.size * VertexAttribState.Attrib.glTypeSizeBytes(a.type);
|
final long typeBytes = (long) a.size * VAOManager.Attrib.glTypeSizeBytes(a.type);
|
||||||
final long start = a.offset + (long) firstVertex * stride;
|
final long start = a.offset + (long) firstVertex * stride;
|
||||||
final long end = a.offset + lastVtx * stride + typeBytes;
|
final long end = a.offset + lastVtx * stride + typeBytes;
|
||||||
|
|
||||||
@@ -103,9 +103,9 @@ public final class AttribSnapshot {
|
|||||||
Int2LongOpenHashMap vboReadOffsets = null;
|
Int2LongOpenHashMap vboReadOffsets = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (int i = 0; i < VertexAttribState.MAX_ATTRIBS; i++) {
|
for (int i = 0; i < VAOManager.MAX_ATTRIBS; i++) {
|
||||||
final VertexAttribState.Attrib a = VertexAttribState.get(i);
|
final VAOManager.Attrib a = VAOManager.get(i);
|
||||||
if (!a.enabled) continue;
|
if (a == null || !a.enabled) continue;
|
||||||
|
|
||||||
if (a.vboId != 0) {
|
if (a.vboId != 0) {
|
||||||
ByteBuffer buf;
|
ByteBuffer buf;
|
||||||
|
|||||||
+34
-2
@@ -5,7 +5,7 @@ import com.gtnewhorizon.gtnhlib.client.renderer.DirectTessellator;
|
|||||||
import com.gtnewhorizon.gtnhlib.client.renderer.TessellatorManager;
|
import com.gtnewhorizon.gtnhlib.client.renderer.TessellatorManager;
|
||||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFormatElement.Usage;
|
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFormatElement.Usage;
|
||||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||||
import com.gtnewhorizons.angelica.glsm.states.VertexAttribState;
|
import com.gtnewhorizons.angelica.glsm.ffp.VAOManager;
|
||||||
import org.lwjgl.opengl.GL11;
|
import org.lwjgl.opengl.GL11;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
@@ -293,7 +293,39 @@ public final class ImmediateModeRecorder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static float readComponent(AttribReader r, int base, int component) {
|
private static float readComponent(AttribReader r, int base, int component) {
|
||||||
return VertexAttribState.Attrib.readComponent(r.type, r.normalized, r.data, base, component);
|
return VAOManager.Attrib.readComponent(r.type, r.normalized, r.data, base, component);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float readComponent(int type, boolean normalized, ByteBuffer buf, int base, int component) {
|
||||||
|
return switch (type) {
|
||||||
|
case GL11.GL_FLOAT -> buf.getFloat(base + component * 4);
|
||||||
|
case GL11.GL_DOUBLE -> (float) buf.getDouble(base + component * 8);
|
||||||
|
case GL11.GL_INT -> {
|
||||||
|
final int v = buf.getInt(base + component * 4);
|
||||||
|
yield normalized ? v / (float) Integer.MAX_VALUE : (float) v;
|
||||||
|
}
|
||||||
|
case GL11.GL_UNSIGNED_INT -> {
|
||||||
|
final int v = buf.getInt(base + component * 4);
|
||||||
|
yield normalized ? (v & 0xFFFFFFFFL) / (float) 0xFFFFFFFFL : (float) (v & 0xFFFFFFFFL);
|
||||||
|
}
|
||||||
|
case GL11.GL_SHORT -> {
|
||||||
|
final short v = buf.getShort(base + component * 2);
|
||||||
|
yield normalized ? v / (float) Short.MAX_VALUE : (float) v;
|
||||||
|
}
|
||||||
|
case GL11.GL_UNSIGNED_SHORT -> {
|
||||||
|
final int v = buf.getShort(base + component * 2) & 0xFFFF;
|
||||||
|
yield normalized ? v / (float) 0xFFFF : (float) v;
|
||||||
|
}
|
||||||
|
case GL11.GL_BYTE -> {
|
||||||
|
final byte v = buf.get(base + component);
|
||||||
|
yield normalized ? v / 127.0f : (float) v;
|
||||||
|
}
|
||||||
|
case GL11.GL_UNSIGNED_BYTE -> {
|
||||||
|
final int v = buf.get(base + component) & 0xFF;
|
||||||
|
yield normalized ? v / 255.0f : (float) v;
|
||||||
|
}
|
||||||
|
default -> 0.0f;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
package com.gtnewhorizons.angelica.glsm.recording.commands;
|
package com.gtnewhorizons.angelica.glsm.recording.commands;
|
||||||
|
|
||||||
import com.gtnewhorizons.angelica.glsm.states.VertexAttribState;
|
import com.gtnewhorizons.angelica.glsm.ffp.VAOManager;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ public final class AttribLayoutKey {
|
|||||||
int base = 0;
|
int base = 0;
|
||||||
int maxAlign = 1;
|
int maxAlign = 1;
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
final int typeSize = VertexAttribState.Attrib.glTypeSizeBytes(types[i]);
|
final int typeSize = VAOManager.Attrib.glTypeSizeBytes(types[i]);
|
||||||
if (typeSize > maxAlign) maxAlign = typeSize;
|
if (typeSize > maxAlign) maxAlign = typeSize;
|
||||||
base = (base + typeSize - 1) & -typeSize;
|
base = (base + typeSize - 1) & -typeSize;
|
||||||
off[i] = base;
|
off[i] = base;
|
||||||
|
|||||||
+5
-5
@@ -3,14 +3,14 @@ package com.gtnewhorizons.angelica.glsm.recording.commands;
|
|||||||
import com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities;
|
import com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities;
|
||||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||||
import com.gtnewhorizons.angelica.glsm.QuadConverter;
|
import com.gtnewhorizons.angelica.glsm.QuadConverter;
|
||||||
|
import com.gtnewhorizons.angelica.glsm.ffp.VAOManager;
|
||||||
import com.gtnewhorizons.angelica.glsm.recording.AttribSnapshot;
|
import com.gtnewhorizons.angelica.glsm.recording.AttribSnapshot;
|
||||||
import com.gtnewhorizons.angelica.glsm.states.VertexAttribState;
|
|
||||||
import org.lwjgl.opengl.GL11;
|
import org.lwjgl.opengl.GL11;
|
||||||
import org.lwjgl.opengl.GL15;
|
import org.lwjgl.opengl.GL15;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import static com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities.memGetInt;
|
import static com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities.memGetInt;
|
||||||
import static com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities.memGetLong;
|
import static com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities.memGetLong;
|
||||||
@@ -68,7 +68,7 @@ public final class IndexedDrawCapture {
|
|||||||
warnOnce("quads-misaligned", "[IndexedDrawCapture] GL_QUADS with indicesCount={} not a multiple of 4 — skipping", indicesCount);
|
warnOnce("quads-misaligned", "[IndexedDrawCapture] GL_QUADS with indicesCount={} not a multiple of 4 — skipping", indicesCount);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
final int srcIndexSize = VertexAttribState.Attrib.glTypeSizeBytes(srcIndexType);
|
final int srcIndexSize = VAOManager.Attrib.glTypeSizeBytes(srcIndexType);
|
||||||
if (srcIndexSize <= 0) return null;
|
if (srcIndexSize <= 0) return null;
|
||||||
|
|
||||||
final int prevEBO = GLStateManager.getBoundEBO();
|
final int prevEBO = GLStateManager.getBoundEBO();
|
||||||
@@ -106,7 +106,7 @@ public final class IndexedDrawCapture {
|
|||||||
snap = AttribSnapshot.snapshot(minVtx, vertexCount);
|
snap = AttribSnapshot.snapshot(minVtx, vertexCount);
|
||||||
|
|
||||||
int enabledCount = 0;
|
int enabledCount = 0;
|
||||||
for (int i = 0; i < VertexAttribState.MAX_ATTRIBS; i++) {
|
for (int i = 0; i < VAOManager.MAX_ATTRIBS; i++) {
|
||||||
if (snap.get(i) != null) enabledCount++;
|
if (snap.get(i) != null) enabledCount++;
|
||||||
}
|
}
|
||||||
if (enabledCount == 0) {
|
if (enabledCount == 0) {
|
||||||
@@ -118,7 +118,7 @@ public final class IndexedDrawCapture {
|
|||||||
final int[] types = new int[enabledCount];
|
final int[] types = new int[enabledCount];
|
||||||
final boolean[] normalized = new boolean[enabledCount];
|
final boolean[] normalized = new boolean[enabledCount];
|
||||||
int k = 0;
|
int k = 0;
|
||||||
for (int i = 0; i < VertexAttribState.MAX_ATTRIBS; i++) {
|
for (int i = 0; i < VAOManager.MAX_ATTRIBS; i++) {
|
||||||
final AttribSnapshot.AttribDesc d = snap.get(i);
|
final AttribSnapshot.AttribDesc d = snap.get(i);
|
||||||
if (d == null) continue;
|
if (d == null) continue;
|
||||||
locations[k] = i;
|
locations[k] = i;
|
||||||
|
|||||||
@@ -1,198 +0,0 @@
|
|||||||
package com.gtnewhorizons.angelica.glsm.states;
|
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
|
||||||
|
|
||||||
import org.lwjgl.opengl.GL11;
|
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.util.ArrayDeque;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Per-VAO vertex attribute pointer state tracking (Mesa-style).
|
|
||||||
*/
|
|
||||||
public class VertexAttribState {
|
|
||||||
public static final int MAX_ATTRIBS = 16;
|
|
||||||
|
|
||||||
private static final Int2ObjectOpenHashMap<Attrib[]> vaoAttribs = new Int2ObjectOpenHashMap<>();
|
|
||||||
private static Attrib[] current;
|
|
||||||
private static final ArrayDeque<Attrib[]> pool = new ArrayDeque<>();
|
|
||||||
private static int clientSideEnabledCount;
|
|
||||||
|
|
||||||
public static void init(int defaultVAO) {
|
|
||||||
vaoAttribs.clear();
|
|
||||||
pool.clear();
|
|
||||||
current = allocAttribArray();
|
|
||||||
vaoAttribs.put(defaultVAO, current);
|
|
||||||
clientSideEnabledCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void onBindVertexArray(int newVAO) {
|
|
||||||
current = vaoAttribs.computeIfAbsent(newVAO, k -> allocAttribArray());
|
|
||||||
recomputeClientSideCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void onDeleteVertexArray(int vaoId) {
|
|
||||||
final Attrib[] arr = vaoAttribs.remove(vaoId);
|
|
||||||
if (arr != null) {
|
|
||||||
pool.addLast(arr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void reset() {
|
|
||||||
vaoAttribs.clear();
|
|
||||||
pool.clear();
|
|
||||||
current = null;
|
|
||||||
clientSideEnabledCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Attrib[] allocAttribArray() {
|
|
||||||
Attrib[] arr = pool.pollFirst();
|
|
||||||
if (arr != null) {
|
|
||||||
for (Attrib a : arr) a.reset();
|
|
||||||
return arr;
|
|
||||||
}
|
|
||||||
arr = new Attrib[MAX_ATTRIBS];
|
|
||||||
for (int i = 0; i < MAX_ATTRIBS; i++) arr[i] = new Attrib();
|
|
||||||
return arr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void set(int index, int size, int type, boolean normalized, int stride, long offset, int vboId) {
|
|
||||||
if (index < 0 || index >= MAX_ATTRIBS) return;
|
|
||||||
final Attrib a = current[index];
|
|
||||||
final boolean was = a.isClientSide();
|
|
||||||
a.size = size;
|
|
||||||
a.type = type;
|
|
||||||
a.normalized = normalized;
|
|
||||||
a.stride = stride;
|
|
||||||
a.offset = offset;
|
|
||||||
a.vboId = vboId;
|
|
||||||
a.clientPointer = null;
|
|
||||||
if (was) clientSideEnabledCount--;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void set(int index, int size, int type, boolean normalized, int stride, ByteBuffer pointer, int vboId) {
|
|
||||||
if (index < 0 || index >= MAX_ATTRIBS) return;
|
|
||||||
final Attrib a = current[index];
|
|
||||||
final boolean was = a.isClientSide();
|
|
||||||
a.size = size;
|
|
||||||
a.type = type;
|
|
||||||
a.normalized = normalized;
|
|
||||||
a.stride = stride;
|
|
||||||
a.offset = 0;
|
|
||||||
a.vboId = vboId;
|
|
||||||
a.clientPointer = (vboId == 0) ? pointer : null;
|
|
||||||
final boolean now = a.isClientSide();
|
|
||||||
if (was != now) clientSideEnabledCount += now ? 1 : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setEnabled(int index, boolean enabled) {
|
|
||||||
if (index < 0 || index >= MAX_ATTRIBS) return;
|
|
||||||
final Attrib a = current[index];
|
|
||||||
if (a.clientPointer != null && a.enabled != enabled) {
|
|
||||||
clientSideEnabledCount += enabled ? 1 : -1;
|
|
||||||
}
|
|
||||||
a.enabled = enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Attrib get(int index) {
|
|
||||||
return current[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private static void recomputeClientSideCount() {
|
|
||||||
int count = 0;
|
|
||||||
for (int i = 0; i < MAX_ATTRIBS; i++) {
|
|
||||||
if (current[i].isClientSide()) count++;
|
|
||||||
}
|
|
||||||
clientSideEnabledCount = count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if any currently enabled vertex attribute was registered without a VBO
|
|
||||||
* (i.e. as a client-side pointer). In core profile, such attribs are treated as null
|
|
||||||
* offsets into a non-existent buffer, causing a native crash at draw time.
|
|
||||||
*/
|
|
||||||
public static boolean hasAnyClientSideEnabledAttrib() {
|
|
||||||
return clientSideEnabledCount > 0;
|
|
||||||
}
|
|
||||||
public static class Attrib {
|
|
||||||
public boolean enabled;
|
|
||||||
public int size;
|
|
||||||
public int type;
|
|
||||||
public boolean normalized;
|
|
||||||
public int stride;
|
|
||||||
public long offset;
|
|
||||||
public int vboId;
|
|
||||||
public ByteBuffer clientPointer;
|
|
||||||
|
|
||||||
public boolean isClientSide() {
|
|
||||||
return enabled && clientPointer != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void reset() {
|
|
||||||
enabled = false;
|
|
||||||
size = 0;
|
|
||||||
type = 0;
|
|
||||||
normalized = false;
|
|
||||||
stride = 0;
|
|
||||||
offset = 0;
|
|
||||||
vboId = 0;
|
|
||||||
clientPointer = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int effectiveStride() {
|
|
||||||
return (stride != 0) ? stride : size * typeSizeBytes();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int typeSizeBytes() {
|
|
||||||
return glTypeSizeBytes(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int glTypeSizeBytes(int glType) {
|
|
||||||
return switch (glType) {
|
|
||||||
case GL11.GL_FLOAT, GL11.GL_INT, GL11.GL_UNSIGNED_INT -> 4;
|
|
||||||
case GL11.GL_DOUBLE -> 8;
|
|
||||||
case GL11.GL_SHORT, GL11.GL_UNSIGNED_SHORT -> 2;
|
|
||||||
case GL11.GL_BYTE, GL11.GL_UNSIGNED_BYTE -> 1;
|
|
||||||
default -> 4;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public float readComponent(ByteBuffer buf, int base, int component) {
|
|
||||||
return readComponent(type, normalized, buf, base, component);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static float readComponent(int type, boolean normalized, ByteBuffer buf, int base, int component) {
|
|
||||||
return switch (type) {
|
|
||||||
case GL11.GL_FLOAT -> buf.getFloat(base + component * 4);
|
|
||||||
case GL11.GL_DOUBLE -> (float) buf.getDouble(base + component * 8);
|
|
||||||
case GL11.GL_INT -> {
|
|
||||||
final int v = buf.getInt(base + component * 4);
|
|
||||||
yield normalized ? v / (float) Integer.MAX_VALUE : (float) v;
|
|
||||||
}
|
|
||||||
case GL11.GL_UNSIGNED_INT -> {
|
|
||||||
final int v = buf.getInt(base + component * 4);
|
|
||||||
yield normalized ? (v & 0xFFFFFFFFL) / (float) 0xFFFFFFFFL : (float) (v & 0xFFFFFFFFL);
|
|
||||||
}
|
|
||||||
case GL11.GL_SHORT -> {
|
|
||||||
final short v = buf.getShort(base + component * 2);
|
|
||||||
yield normalized ? v / (float) Short.MAX_VALUE : (float) v;
|
|
||||||
}
|
|
||||||
case GL11.GL_UNSIGNED_SHORT -> {
|
|
||||||
final int v = buf.getShort(base + component * 2) & 0xFFFF;
|
|
||||||
yield normalized ? v / (float) 0xFFFF : (float) v;
|
|
||||||
}
|
|
||||||
case GL11.GL_BYTE -> {
|
|
||||||
final byte v = buf.get(base + component);
|
|
||||||
yield normalized ? v / 127.0f : (float) v;
|
|
||||||
}
|
|
||||||
case GL11.GL_UNSIGNED_BYTE -> {
|
|
||||||
final int v = buf.get(base + component) & 0xFF;
|
|
||||||
yield normalized ? v / 255.0f : (float) v;
|
|
||||||
}
|
|
||||||
default -> 0.0f;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-7
@@ -7,7 +7,6 @@ import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFormat;
|
|||||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||||
import com.gtnewhorizons.angelica.glsm.QuadConverter;
|
import com.gtnewhorizons.angelica.glsm.QuadConverter;
|
||||||
import com.gtnewhorizons.angelica.glsm.RenderSystem;
|
import com.gtnewhorizons.angelica.glsm.RenderSystem;
|
||||||
import com.gtnewhorizons.angelica.glsm.ffp.ShaderManager;
|
|
||||||
import net.minecraft.client.renderer.Tessellator;
|
import net.minecraft.client.renderer.Tessellator;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
@@ -204,14 +203,8 @@ public class TessellatorStreamingDrawer {
|
|||||||
firstVertex = 0;
|
firstVertex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLStateManager.prepareWideLineEmulation(drawMode);
|
|
||||||
ShaderManager.getInstance().preDraw(flags);
|
|
||||||
drawWithQuadConversion(drawMode, firstVertex, vertexCount);
|
drawWithQuadConversion(drawMode, firstVertex, vertexCount);
|
||||||
GLStateManager.glBindVertexArray(0);
|
GLStateManager.glBindVertexArray(0);
|
||||||
GLStateManager.glDisableClientState(GL11.GL_VERTEX_ARRAY);
|
|
||||||
GLStateManager.glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
|
|
||||||
GLStateManager.glDisableClientState(GL11.GL_COLOR_ARRAY);
|
|
||||||
GLStateManager.glDisableClientState(GL11.GL_NORMAL_ARRAY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void drawWithQuadConversion(int drawMode, int firstVertex, int vertexCount) {
|
private static void drawWithQuadConversion(int drawMode, int firstVertex, int vertexCount) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.gtnewhorizons.angelica.glsm;
|
package com.gtnewhorizons.angelica.glsm;
|
||||||
|
|
||||||
import com.gtnewhorizon.gtnhlib.client.opengl.UniversalVAO;
|
import com.gtnewhorizon.gtnhlib.client.opengl.UniversalVAO;
|
||||||
import com.gtnewhorizons.angelica.glsm.states.VertexAttribState;
|
import com.gtnewhorizons.angelica.glsm.ffp.VAOManager;
|
||||||
import com.gtnewhorizons.angelica.util.GLSMUtil;
|
import com.gtnewhorizons.angelica.util.GLSMUtil;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
@@ -133,7 +133,7 @@ public class GLSM_VAO_UnitTest {
|
|||||||
private static void glBindVertexArray(int array) {
|
private static void glBindVertexArray(int array) {
|
||||||
if (array == 0) array = GLStateManager.getDefaultVAO();
|
if (array == 0) array = GLStateManager.getDefaultVAO();
|
||||||
GLStateManager.boundVAO = array;
|
GLStateManager.boundVAO = array;
|
||||||
VertexAttribState.onBindVertexArray(array);
|
VAOManager.onBindVertexArrayPre(array);
|
||||||
UniversalVAO.bindVertexArray(array);
|
UniversalVAO.bindVertexArray(array);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+6
-6
@@ -28,7 +28,7 @@ class VertexAttribDefaultBridgeTest {
|
|||||||
@Test
|
@Test
|
||||||
void testGlColor4fSetsVertexAttrib() {
|
void testGlColor4fSetsVertexAttrib() {
|
||||||
GLStateManager.glColor4f(0.5f, 0.25f, 0.75f, 0.8f);
|
GLStateManager.glColor4f(0.5f, 0.25f, 0.75f, 0.8f);
|
||||||
GLStateManager.flushDeferredVertexAttribs(0);
|
GLStateManager.flushDeferredVertexAttribs(false, false, false, false);
|
||||||
|
|
||||||
float[] color = getVertexAttrib4f(COLOR_ATTRIB);
|
float[] color = getVertexAttrib4f(COLOR_ATTRIB);
|
||||||
assertEquals(0.5f, color[0], EPSILON, "color.r");
|
assertEquals(0.5f, color[0], EPSILON, "color.r");
|
||||||
@@ -40,7 +40,7 @@ class VertexAttribDefaultBridgeTest {
|
|||||||
@Test
|
@Test
|
||||||
void testGlNormal3fSetsVertexAttrib() {
|
void testGlNormal3fSetsVertexAttrib() {
|
||||||
GLStateManager.glNormal3f(0.0f, 1.0f, 0.0f);
|
GLStateManager.glNormal3f(0.0f, 1.0f, 0.0f);
|
||||||
GLStateManager.flushDeferredVertexAttribs(0);
|
GLStateManager.flushDeferredVertexAttribs(false, false, false, false);
|
||||||
|
|
||||||
float[] normal = getVertexAttrib4f(NORMAL_ATTRIB);
|
float[] normal = getVertexAttrib4f(NORMAL_ATTRIB);
|
||||||
assertEquals(0.0f, normal[0], EPSILON, "normal.x");
|
assertEquals(0.0f, normal[0], EPSILON, "normal.x");
|
||||||
@@ -51,7 +51,7 @@ class VertexAttribDefaultBridgeTest {
|
|||||||
@Test
|
@Test
|
||||||
void testSetLightmapTextureCoordsOnUnit1SetsVertexAttrib() {
|
void testSetLightmapTextureCoordsOnUnit1SetsVertexAttrib() {
|
||||||
GLStateManager.setLightmapTextureCoords(GL13.GL_TEXTURE1, 240.0f, 128.0f);
|
GLStateManager.setLightmapTextureCoords(GL13.GL_TEXTURE1, 240.0f, 128.0f);
|
||||||
GLStateManager.flushDeferredVertexAttribs(0);
|
GLStateManager.flushDeferredVertexAttribs(false, false, false, false);
|
||||||
|
|
||||||
float[] lm = getVertexAttrib4f(SECONDARY_UV_ATTRIB);
|
float[] lm = getVertexAttrib4f(SECONDARY_UV_ATTRIB);
|
||||||
assertEquals(240.0f, lm[0], EPSILON, "lightmap.s");
|
assertEquals(240.0f, lm[0], EPSILON, "lightmap.s");
|
||||||
@@ -64,7 +64,7 @@ class VertexAttribDefaultBridgeTest {
|
|||||||
void testGlTexCoord2fSetsVertexAttrib() {
|
void testGlTexCoord2fSetsVertexAttrib() {
|
||||||
// glTexCoord2f outside recording → sets default vertex attrib 2 (PRIMARY_UV)
|
// glTexCoord2f outside recording → sets default vertex attrib 2 (PRIMARY_UV)
|
||||||
GLStateManager.glTexCoord2f(0.5f, 0.75f);
|
GLStateManager.glTexCoord2f(0.5f, 0.75f);
|
||||||
GLStateManager.flushDeferredVertexAttribs(0);
|
GLStateManager.flushDeferredVertexAttribs(false, false, false, false);
|
||||||
|
|
||||||
float[] uv = getVertexAttrib4f(PRIMARY_UV_ATTRIB);
|
float[] uv = getVertexAttrib4f(PRIMARY_UV_ATTRIB);
|
||||||
assertEquals(0.5f, uv[0], EPSILON, "texcoord.s");
|
assertEquals(0.5f, uv[0], EPSILON, "texcoord.s");
|
||||||
@@ -77,7 +77,7 @@ class VertexAttribDefaultBridgeTest {
|
|||||||
// Second call is a cache hit — changeColor not called.
|
// Second call is a cache hit — changeColor not called.
|
||||||
// Vertex attrib should still hold the correct value from the first call.
|
// Vertex attrib should still hold the correct value from the first call.
|
||||||
GLStateManager.glColor4f(0.3f, 0.6f, 0.9f, 1.0f);
|
GLStateManager.glColor4f(0.3f, 0.6f, 0.9f, 1.0f);
|
||||||
GLStateManager.flushDeferredVertexAttribs(0);
|
GLStateManager.flushDeferredVertexAttribs(false, false, false, false);
|
||||||
|
|
||||||
float[] color = getVertexAttrib4f(COLOR_ATTRIB);
|
float[] color = getVertexAttrib4f(COLOR_ATTRIB);
|
||||||
assertEquals(0.3f, color[0], EPSILON, "color.r after dedup");
|
assertEquals(0.3f, color[0], EPSILON, "color.r after dedup");
|
||||||
@@ -89,7 +89,7 @@ class VertexAttribDefaultBridgeTest {
|
|||||||
@Test
|
@Test
|
||||||
void testCompileMode_DoesNotSetVertexAttrib() {
|
void testCompileMode_DoesNotSetVertexAttrib() {
|
||||||
GLStateManager.glColor4f(0.1f, 0.2f, 0.3f, 1.0f);
|
GLStateManager.glColor4f(0.1f, 0.2f, 0.3f, 1.0f);
|
||||||
GLStateManager.flushDeferredVertexAttribs(0);
|
GLStateManager.flushDeferredVertexAttribs(false, false, false, false);
|
||||||
|
|
||||||
int listId = GLStateManager.glGenLists(1);
|
int listId = GLStateManager.glGenLists(1);
|
||||||
GLStateManager.glNewList(listId, org.lwjgl.opengl.GL11.GL_COMPILE);
|
GLStateManager.glNewList(listId, org.lwjgl.opengl.GL11.GL_COMPILE);
|
||||||
|
|||||||
+5
-5
@@ -3,10 +3,10 @@ package com.gtnewhorizons.angelica.glsm.recording;
|
|||||||
import com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities;
|
import com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities;
|
||||||
import com.gtnewhorizons.angelica.glsm.DisplayListManager;
|
import com.gtnewhorizons.angelica.glsm.DisplayListManager;
|
||||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||||
|
import com.gtnewhorizons.angelica.glsm.ffp.VAOManager;
|
||||||
import com.gtnewhorizons.angelica.glsm.recording.commands.BatchedIndexedDrawCmd;
|
import com.gtnewhorizons.angelica.glsm.recording.commands.BatchedIndexedDrawCmd;
|
||||||
import com.gtnewhorizons.angelica.glsm.recording.commands.IndexedDrawBatch;
|
import com.gtnewhorizons.angelica.glsm.recording.commands.IndexedDrawBatch;
|
||||||
import com.gtnewhorizons.angelica.glsm.recording.support.DisplayListTestFixture;
|
import com.gtnewhorizons.angelica.glsm.recording.support.DisplayListTestFixture;
|
||||||
import com.gtnewhorizons.angelica.glsm.states.VertexAttribState;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
import org.junit.jupiter.params.provider.ValueSource;
|
import org.junit.jupiter.params.provider.ValueSource;
|
||||||
@@ -307,10 +307,10 @@ class IndexedDrawBatchBuilderTest extends DisplayListTestFixture {
|
|||||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||||
final ByteBuffer colorSlice = clientData.duplicate().order(ByteOrder.nativeOrder());
|
final ByteBuffer colorSlice = clientData.duplicate().order(ByteOrder.nativeOrder());
|
||||||
colorSlice.position(8);
|
colorSlice.position(8);
|
||||||
VertexAttribState.set(0, 2, GL11.GL_FLOAT, false, POS_COLOR_STRIDE, clientData, 0);
|
VAOManager.setAttribute(0, 2, GL11.GL_FLOAT, false, POS_COLOR_STRIDE, clientData);
|
||||||
VertexAttribState.setEnabled(0, true);
|
VAOManager.enableAttribute(0);
|
||||||
VertexAttribState.set(1, 4, GL11.GL_UNSIGNED_BYTE, true, POS_COLOR_STRIDE, colorSlice, 0);
|
VAOManager.setAttribute(1, 4, GL11.GL_UNSIGNED_BYTE, true, POS_COLOR_STRIDE, colorSlice);
|
||||||
VertexAttribState.setEnabled(1, true);
|
VAOManager.enableAttribute(1);
|
||||||
GLStateManager.glBindVertexArray(0);
|
GLStateManager.glBindVertexArray(0);
|
||||||
|
|
||||||
final int ebo = uploadEbo(GL11.GL_UNSIGNED_SHORT, 0, 1, 2);
|
final int ebo = uploadEbo(GL11.GL_UNSIGNED_SHORT, 0, 1, 2);
|
||||||
|
|||||||
@@ -227,13 +227,13 @@ public class AngelicaConfig {
|
|||||||
|
|
||||||
@Config.Comment({"Block corners and edges between chunks might have \"cracks\" (various lines/dots) in them.",
|
@Config.Comment({"Block corners and edges between chunks might have \"cracks\" (various lines/dots) in them.",
|
||||||
"While using \"Compact Vertex Format\" makes the situation even worse.",
|
"While using \"Compact Vertex Format\" makes the situation even worse.",
|
||||||
"This option fixes it.",
|
"This option fixes it, though may lead to other visual artifacts.",
|
||||||
"Requires texture reloading (F3 + T) after changing this option to take effect"})
|
"Requires game restart after changing this option to take effect"})
|
||||||
@Config.DefaultBoolean(true)
|
@Config.DefaultBoolean(false)
|
||||||
public static boolean fixBlockCrack;
|
public static boolean blockCrackFix;
|
||||||
|
|
||||||
@Config.Comment({
|
@Config.Comment({
|
||||||
"The \"epsilon\" value for the fixBlockCrack option. ",
|
"The \"epsilon\" value for the blockCrackFix option. ",
|
||||||
"Set this a bit higher if you can still see lines/dots between solid blocks in dark areas.",
|
"Set this a bit higher if you can still see lines/dots between solid blocks in dark areas.",
|
||||||
"May cause intense flickering (z-fighting) between blocks if the value is too high"
|
"May cause intense flickering (z-fighting) between blocks if the value is too high"
|
||||||
})
|
})
|
||||||
@@ -241,7 +241,7 @@ public class AngelicaConfig {
|
|||||||
@Config.DefaultDouble(0.001)
|
@Config.DefaultDouble(0.001)
|
||||||
public static double blockCrackFixEpsilon;
|
public static double blockCrackFixEpsilon;
|
||||||
|
|
||||||
@Config.Comment("Block classes that have bugs when rendering with the fixBlockCrack can be put here to avoid manipulating them")
|
@Config.Comment("Block classes that have bugs when rendering with the blockCrackFix can be put here to avoid manipulating them")
|
||||||
@Config.DefaultStringList({
|
@Config.DefaultStringList({
|
||||||
"net.minecraft.block.BlockCauldron",
|
"net.minecraft.block.BlockCauldron",
|
||||||
"net.minecraft.block.BlockStairs"
|
"net.minecraft.block.BlockStairs"
|
||||||
@@ -249,7 +249,7 @@ public class AngelicaConfig {
|
|||||||
public static String[] blockCrackFixBlacklist;
|
public static String[] blockCrackFixBlacklist;
|
||||||
|
|
||||||
@Config.Comment({"Block classes that have render pass other than 0 but still need to be manipulated.",
|
@Config.Comment({"Block classes that have render pass other than 0 but still need to be manipulated.",
|
||||||
"Add a block class here if you see flickering (z-fighting) with fixBlockCrack enabled"
|
"Add a block class here if you see flickering (z-fighting) with blockCrackFix enabled"
|
||||||
})
|
})
|
||||||
@Config.DefaultStringList({
|
@Config.DefaultStringList({
|
||||||
"gregtech.common.blocks.BlockOres",
|
"gregtech.common.blocks.BlockOres",
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ public enum Mixins implements IMixins {
|
|||||||
.setPhase(Phase.EARLY)
|
.setPhase(Phase.EARLY)
|
||||||
.addClientMixins("angelica.bugfixes.MixinRenderBlocks_CrackFix")
|
.addClientMixins("angelica.bugfixes.MixinRenderBlocks_CrackFix")
|
||||||
.addExcludedMod(TargetedMod.FALSETWEAKS)
|
.addExcludedMod(TargetedMod.FALSETWEAKS)
|
||||||
.setApplyIf(() -> AngelicaConfig.fixBlockCrack)),
|
.setApplyIf(() -> AngelicaConfig.blockCrackFix)),
|
||||||
|
|
||||||
ANGELICA_FIX_FLUID_RENDERER_CHECKING_BLOCK_AGAIN(
|
ANGELICA_FIX_FLUID_RENDERER_CHECKING_BLOCK_AGAIN(
|
||||||
new MixinBuilder("Fix RenderBlockFluid reading the block type from the world access multiple times")
|
new MixinBuilder("Fix RenderBlockFluid reading the block type from the world access multiple times")
|
||||||
|
|||||||
+1
-1
@@ -254,6 +254,6 @@ public class MixinRenderBlocks_CrackFix {
|
|||||||
}
|
}
|
||||||
@Unique
|
@Unique
|
||||||
private boolean angelica$crackFixOff() {
|
private boolean angelica$crackFixOff() {
|
||||||
return !AngelicaConfig.fixBlockCrack || angelica$disableCrackFix;
|
return !AngelicaConfig.blockCrackFix || angelica$disableCrackFix;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user