Compare commits

...
16 Commits
Author SHA1 Message Date
Jason Mitchell 3ea47c8385 Various fixes (#1571) 2026-03-24 22:17:40 -07:00
Eclipse-Sol 306d732d81 Fixes 3rd person enchant glints z-fighting with the item model (#1569) 2026-03-24 17:24:23 -07:00
Jason Mitchell a483669579 Maybe fix botania mana pool rendering 2026-03-23 21:09:33 -07:00
Eclipse-SolandJason Mitchell 53996500d7 Fix modded enchant glints not being animated (#1566)
Co-authored-by: Jason Mitchell <[email protected]>
2026-03-23 22:41:29 -04:00
Jason Mitchell 04dd8ce6c7 narrow scope of mixin per Eclipse 2026-03-23 19:24:16 -07:00
Jason Mitchell 8c9edfa4c3 Fix alpha test 2026-03-23 19:24:16 -07:00
Jason Mitchell 3f44195756 Change compat config 2026-03-23 09:27:56 -07:00
Jason Mitchell c98f056d74 ASM Hook Compat
* Adds a config to allow disabling
* Narrows Advanced LightSabers
* Narrows Alfheim (unreleased versions have compat, might make this version restricted)
2026-03-23 09:00:24 -07:00
Jason Mitchell 7e25f5d03e tweak wording 2026-03-22 18:41:58 -07:00
Jason Mitchell b5553654d0 More pass throughs 2026-03-22 18:41:58 -07:00
Jason Mitchell a3fffb47be Ban GL usage.
* Everything must go through GLSM/Render Backend
2026-03-22 11:56:08 -07:00
Jason Mitchell 09cc557be0 Clear cache on reload shaders 2026-03-22 11:07:37 -07:00
SpacEagle17 aff5ff7e7b Add a second profiles button to Angelica 2026-03-22 10:09:23 -07:00
Jason Mitchell e7d08a53b6 Add debug context 2026-03-22 10:08:49 -07:00
Jason Mitchell 3b2a0af5c4 Add missing overrides 2026-03-22 10:08:49 -07:00
Jason Mitchell 8c44e79990 Add always translucent config for brandyn 2026-03-22 10:08:49 -07:00
38 changed files with 588 additions and 797 deletions

No files matched your search

+2
View File
@@ -146,6 +146,8 @@ dependencies {
testImplementation('org.junit.platform:junit-platform-engine')
testImplementation('org.junit.platform:junit-platform-reporting')
testImplementation('org.junit.platform:junit-platform-launcher')
testImplementation('com.tngtech.archunit:archunit-junit5:1.4.1')
}
}
@@ -42,10 +42,11 @@ public class CompatUniformManager {
static final int LOC_IRIS_PROJECTION = 11;
static final int LOC_IRIS_NORMAL = 12;
static final int LOC_IRIS_LIGHTMAP_TEXTURE_MATRIX = 13;
static final int LOC_ALPHA_TEST_REF = 14;
static final int LOC_SCENE_COLOR = 15;
static final int LOC_CLIP_PLANES = 16;
static final int LOC_CLIP_PLANES_ENABLED = 17;
static final int LOC_IRIS_TEXTURE_MATRIX = 14;
static final int LOC_ALPHA_TEST_REF = 15;
static final int LOC_SCENE_COLOR = 16;
static final int LOC_CLIP_PLANES = 17;
static final int LOC_CLIP_PLANES_ENABLED = 18;
// Light source fields: 12 per light × 2 lights = 24 locations
static final int LIGHT_FIELDS = 12;
@@ -53,14 +54,14 @@ public class CompatUniformManager {
static final int LF_HALF_VECTOR = 4, LF_SPOT_DIRECTION = 5, LF_SPOT_EXPONENT = 6;
static final int LF_SPOT_CUTOFF = 7, LF_SPOT_COS_CUTOFF = 8;
static final int LF_CONSTANT_ATTEN = 9, LF_LINEAR_ATTEN = 10, LF_QUADRATIC_ATTEN = 11;
static final int LOC_LIGHT_BASE = 18;
static final int LOC_LIGHT_BASE = 19;
// Material fields: 5 locations
static final int MF_EMISSION = 0, MF_AMBIENT = 1, MF_DIFFUSE = 2, MF_SPECULAR = 3, MF_SHININESS = 4;
static final int MAT_FIELDS = 5;
static final int LOC_MAT_BASE = LOC_LIGHT_BASE + 2 * LIGHT_FIELDS; // 42
static final int LOC_MAT_BASE = LOC_LIGHT_BASE + 2 * LIGHT_FIELDS; // 43
static final int LOC_COUNT = LOC_MAT_BASE + MAT_FIELDS; // 47
static final int LOC_COUNT = LOC_MAT_BASE + MAT_FIELDS; // 48
private static final String[] LIGHT_FIELD_NAMES = {
"ambient", "diffuse", "specular", "position", "halfVector",
@@ -89,6 +90,7 @@ public class CompatUniformManager {
UNIFORM_NAMES[LOC_IRIS_PROJECTION] = "iris_ProjectionMatrix";
UNIFORM_NAMES[LOC_IRIS_NORMAL] = "iris_NormalMatrix";
UNIFORM_NAMES[LOC_IRIS_LIGHTMAP_TEXTURE_MATRIX] = "iris_LightmapTextureMatrix";
UNIFORM_NAMES[LOC_IRIS_TEXTURE_MATRIX] = "iris_TextureMatrix";
UNIFORM_NAMES[LOC_ALPHA_TEST_REF] = "angelica_currentAlphaTest";
UNIFORM_NAMES[LOC_SCENE_COLOR] = "angelica_SceneColor";
UNIFORM_NAMES[LOC_CLIP_PLANES] = "angelica_ClipPlane[0]";
@@ -264,6 +266,12 @@ public class CompatUniformManager {
GLStateManager.getTextures().getTextureUnitMatrix(1).get(mat4Buf);
RENDER_BACKEND.uniformMatrix4(locs[LOC_LIGHTMAP_TEXTURE_MATRIX], false, mat4Buf);
}
// iris_TextureMatrix — texture unit 0 matrix (animated by glints, etc.)
if (locs[LOC_IRIS_TEXTURE_MATRIX] != -1) {
GLStateManager.getTextures().getTextureUnitMatrix(0).get(mat4Buf);
RENDER_BACKEND.uniformMatrix4(locs[LOC_IRIS_TEXTURE_MATRIX], false, mat4Buf);
}
}
}
@@ -4901,13 +4901,23 @@ public class GLStateManager {
public static void glBufferData(int target, int[] data, int usage) { RENDER_BACKEND.bufferData(target, data, usage); }
public static void glBufferData(int target, float[] data, int usage) { RENDER_BACKEND.bufferData(target, data, usage); }
public static void glBufferData(int target, java.nio.ByteBuffer data, int usage) { RENDER_BACKEND.bufferData(target, data, usage); }
public static void glBufferData(int target, java.nio.FloatBuffer data, int usage) { RENDER_BACKEND.bufferData(target, data, usage); }
public static void glBufferData(int target, java.nio.ShortBuffer data, int usage) { RENDER_BACKEND.bufferData(target, data, usage); }
public static void glBufferData(int target, java.nio.IntBuffer data, int usage) { RENDER_BACKEND.bufferData(target, data, usage); }
public static void glBufferData(int target, java.nio.FloatBuffer data, int usage) { RENDER_BACKEND.bufferData(target, data, usage); }
public static void glBufferData(int target, java.nio.DoubleBuffer data, int usage) { RENDER_BACKEND.bufferData(target, data, usage); }
public static void glBufferSubData(int target, long offset, java.nio.ByteBuffer data) { RENDER_BACKEND.bufferSubData(target, offset, data); }
public static void glBufferSubData(int target, long offset, java.nio.ShortBuffer data) { RENDER_BACKEND.bufferSubData(target, offset, data); }
public static void glBufferSubData(int target, long offset, java.nio.IntBuffer data) { RENDER_BACKEND.bufferSubData(target, offset, data); }
public static void glBufferSubData(int target, long offset, java.nio.FloatBuffer data) { RENDER_BACKEND.bufferSubData(target, offset, data); }
public static void glBufferSubData(int target, long offset, java.nio.DoubleBuffer data) { RENDER_BACKEND.bufferSubData(target, offset, data); }
public static ByteBuffer glMapBuffer(int target, int access) { return RENDER_BACKEND.mapBuffer(target, access); }
public static ByteBuffer glMapBuffer(int target, int access, long length, ByteBuffer old_buffer) { return RENDER_BACKEND.mapBuffer(target, access, length, old_buffer); }
public static boolean glUnmapBuffer(int target) { return RENDER_BACKEND.unmapBuffer(target); }
public static void glGetBufferSubData(int target, long offset, java.nio.ByteBuffer data) { RENDER_BACKEND.getBufferSubData(target, offset, data); }
public static void glGetBufferSubData(int target, long offset, java.nio.ShortBuffer data) { RENDER_BACKEND.getBufferSubData(target, offset, data); }
public static void glGetBufferSubData(int target, long offset, java.nio.IntBuffer data) { RENDER_BACKEND.getBufferSubData(target, offset, data); }
public static void glGetBufferSubData(int target, long offset, java.nio.FloatBuffer data) { RENDER_BACKEND.getBufferSubData(target, offset, data); }
public static void glGetBufferSubData(int target, long offset, java.nio.DoubleBuffer data) { RENDER_BACKEND.getBufferSubData(target, offset, data); }
public static int glGetBufferParameteri(int target, int pname) { return RENDER_BACKEND.getBufferParameteri(target, pname); }
public static void glBufferStorage(int target, java.nio.ByteBuffer data, int flags) { RENDER_BACKEND.bufferStorage(target, data, flags); }
public static void glBufferStorage(int target, long size, int flags) { RENDER_BACKEND.bufferStorage(target, size, flags); }
@@ -5023,6 +5033,14 @@ public class GLStateManager {
public static void glFramebufferTexture(int target, int attachment, int texture, int level) { RENDER_BACKEND.framebufferTexture(target, attachment, texture, level); }
public static void glGenerateMipmap(int target) {
RENDER_BACKEND.generateMipmap(target);
}
public static void glBlitFramebuffer(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, int mask, int filter) {
RENDER_BACKEND.blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
}
public static void setActiveTexture(int textureUnit) {
glActiveTexture(textureUnit);
}
@@ -902,6 +902,16 @@ public final class Lwjgl2GLRenderBackend extends RenderBackend {
GL15.glBufferData(target, data, usage);
}
@Override
public void bufferData(int target, IntBuffer data, int usage) {
GL15.glBufferData(target, data, usage);
}
@Override
public void bufferData(int target, DoubleBuffer data, int usage) {
GL15.glBufferData(target, data, usage);
}
@Override
public void bufferData(int target, int[] data, int usage) {
final IntBuffer buffer = getIntArrayBuffer(data.length);
@@ -923,6 +933,26 @@ public final class Lwjgl2GLRenderBackend extends RenderBackend {
GL15.glBufferSubData(target, offset, data);
}
@Override
public void bufferSubData(int target, long offset, ShortBuffer data) {
GL15.glBufferSubData(target, offset, data);
}
@Override
public void bufferSubData(int target, long offset, IntBuffer data) {
GL15.glBufferSubData(target, offset, data);
}
@Override
public void bufferSubData(int target, long offset, FloatBuffer data) {
GL15.glBufferSubData(target, offset, data);
}
@Override
public void bufferSubData(int target, long offset, DoubleBuffer data) {
GL15.glBufferSubData(target, offset, data);
}
@Override
public ByteBuffer mapBuffer(int target, int access) {
return GL15.glMapBuffer(target, access, null);
@@ -953,6 +983,26 @@ public final class Lwjgl2GLRenderBackend extends RenderBackend {
GL15.glGetBufferSubData(target, offset, data);
}
@Override
public void getBufferSubData(int target, long offset, ShortBuffer data) {
GL15.glGetBufferSubData(target, offset, data);
}
@Override
public void getBufferSubData(int target, long offset, IntBuffer data) {
GL15.glGetBufferSubData(target, offset, data);
}
@Override
public void getBufferSubData(int target, long offset, FloatBuffer data) {
GL15.glGetBufferSubData(target, offset, data);
}
@Override
public void getBufferSubData(int target, long offset, DoubleBuffer data) {
GL15.glGetBufferSubData(target, offset, data);
}
@Override
public int getBufferParameteri(int target, int pname) {
return GL15.glGetBufferParameteri(target, pname);
@@ -208,15 +208,25 @@ public abstract class RenderBackend {
public abstract void bufferData(int target, ByteBuffer data, int usage);
public abstract void bufferData(int target, FloatBuffer data, int usage);
public abstract void bufferData(int target, ShortBuffer data, int usage);
public abstract void bufferData(int target, IntBuffer data, int usage);
public abstract void bufferData(int target, DoubleBuffer data, int usage);
public abstract void bufferData(int target, int[] data, int usage);
public abstract void bufferData(int target, float[] data, int usage);
public abstract void bufferSubData(int target, long offset, ByteBuffer data);
public abstract void bufferSubData(int target, long offset, ShortBuffer data);
public abstract void bufferSubData(int target, long offset, IntBuffer data);
public abstract void bufferSubData(int target, long offset, FloatBuffer data);
public abstract void bufferSubData(int target, long offset, DoubleBuffer data);
public abstract ByteBuffer mapBuffer(int target, int access);
public abstract ByteBuffer mapBuffer(int target, int access, long length, ByteBuffer old_buffer);
public abstract boolean unmapBuffer(int target);
public abstract void bufferStorage(int target, ByteBuffer data, int flags);
public abstract void bufferStorage(int target, long size, int flags);
public abstract void getBufferSubData(int target, long offset, ByteBuffer data);
public abstract void getBufferSubData(int target, long offset, ShortBuffer data);
public abstract void getBufferSubData(int target, long offset, IntBuffer data);
public abstract void getBufferSubData(int target, long offset, FloatBuffer data);
public abstract void getBufferSubData(int target, long offset, DoubleBuffer data);
public abstract int getBufferParameteri(int target, int pname);
public abstract boolean isBuffer(int buffer);
public abstract ByteBuffer mapBufferRange(int target, long offset, long length, int access);
@@ -893,6 +893,16 @@ public final class Lwjgl3GLRenderBackend extends RenderBackend {
GL15C.glBufferData(target, data, usage);
}
@Override
public void bufferData(int target, IntBuffer data, int usage) {
GL15C.glBufferData(target, data, usage);
}
@Override
public void bufferData(int target, DoubleBuffer data, int usage) {
GL15C.glBufferData(target, data, usage);
}
@Override
public void bufferData(int target, int[] data, int usage) {
GL15C.glBufferData(target, data, usage);
@@ -908,6 +918,26 @@ public final class Lwjgl3GLRenderBackend extends RenderBackend {
GL15C.glBufferSubData(target, offset, data);
}
@Override
public void bufferSubData(int target, long offset, ShortBuffer data) {
GL15C.glBufferSubData(target, offset, data);
}
@Override
public void bufferSubData(int target, long offset, IntBuffer data) {
GL15C.glBufferSubData(target, offset, data);
}
@Override
public void bufferSubData(int target, long offset, FloatBuffer data) {
GL15C.glBufferSubData(target, offset, data);
}
@Override
public void bufferSubData(int target, long offset, DoubleBuffer data) {
GL15C.glBufferSubData(target, offset, data);
}
@Override
public ByteBuffer mapBuffer(int target, int access) {
return GL15C.glMapBuffer(target, access);
@@ -938,6 +968,26 @@ public final class Lwjgl3GLRenderBackend extends RenderBackend {
GL15C.glGetBufferSubData(target, offset, data);
}
@Override
public void getBufferSubData(int target, long offset, ShortBuffer data) {
GL15C.glGetBufferSubData(target, offset, data);
}
@Override
public void getBufferSubData(int target, long offset, IntBuffer data) {
GL15C.glGetBufferSubData(target, offset, data);
}
@Override
public void getBufferSubData(int target, long offset, FloatBuffer data) {
GL15C.glGetBufferSubData(target, offset, data);
}
@Override
public void getBufferSubData(int target, long offset, DoubleBuffer data) {
GL15C.glGetBufferSubData(target, offset, data);
}
@Override
public int getBufferParameteri(int target, int pname) {
return GL15C.glGetBufferParameteri(target, pname);
@@ -1,707 +0,0 @@
package com.gtnewhorizons.angelica.client.debug;
import com.gtnewhorizons.angelica.glsm.GLDebug;
import com.gtnewhorizons.angelica.glsm.GLStateManager;
import com.gtnewhorizons.angelica.glsm.states.TextureUnitArray;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.texture.ITextureObject;
import net.minecraft.util.ResourceLocation;
import org.apache.commons.io.FileUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.joml.Matrix4f;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12;
import org.lwjgl.opengl.GL13;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
// Adapted from https://github.com/makamys/CoreTweaks/blob/master/src/main/java/makamys/coretweaks/util/OpenGLDebugging.java;
// originally from https://github.com/TheGreyGhost/MinecraftByExample/blob/1-8final/src/main/java/minecraftbyexample/usefultools/OpenGLdebugging.java
public class OpenGLDebugging {
public static final Logger LOGGER = LogManager.getLogger("gldumper");
private static final Consumer<String> LINE_LOGGER = LOGGER::debug;
private static final Set<String> seenErrors = new HashSet<>();
public static final String GL_IS_ENABLED = "glIsEnabled()";
public static final String GL_GET_BOOLEANV = "glGetBooleanv()";
public static final String GL_GET_INTEGERV = "glGetIntegerv()";
public static final String GL_GET_FLOATV = "glGetFloatv()";
public static class GLproperty {
public GLproperty(int glConstant, String name, String description, String category, String fetchCommand) {
this.gLConstant = glConstant;
this.name = name;
this.description = description;
this.category = category;
this.fetchCommand = fetchCommand;
}
public int gLConstant;
public String name;
public String description;
public String category;
public String fetchCommand;
static final ByteBuffer byteBuffer = BufferUtils.createByteBuffer(16);
static final IntBuffer intBuffer = BufferUtils.createIntBuffer(16);
static final FloatBuffer floatBuffer = BufferUtils.createFloatBuffer(16);
public String getAsString(boolean glsm) {
switch(fetchCommand) {
case GL_IS_ENABLED: {
return "" + (glsm ? GLStateManager.glIsEnabled(gLConstant) : GL11.glIsEnabled(gLConstant));
}
case GL_GET_BOOLEANV: {
if(GLStateManager.HAS_MULTIPLE_SET.contains(gLConstant)) {
byteBuffer.clear();
if(glsm) {
GLStateManager.glGetBoolean(gLConstant, byteBuffer);
} else {
GL11.glGetBoolean(gLConstant, byteBuffer);
}
final StringBuilder out = new StringBuilder();
for (int i = 0; i < byteBuffer.capacity(); ++i) {
out.append(i == 0 ? "" : ", ").append(byteBuffer.get(i));
}
return out.toString();
} else {
return "" + (glsm ? GLStateManager.glGetBoolean(gLConstant) : GL11.glGetBoolean(gLConstant));
}
}
case GL_GET_INTEGERV: {
if(GLStateManager.HAS_MULTIPLE_SET.contains(gLConstant)) {
intBuffer.clear();
if(glsm) {
GLStateManager.glGetInteger(gLConstant, intBuffer);
} else {
GL11.glGetInteger(gLConstant, intBuffer);
}
final StringBuilder out = new StringBuilder();
for (int i = 0; i < intBuffer.remaining(); ++i) {
out.append(i == 0 ? "" : ", ").append(intBuffer.get(i));
}
return out.toString();
} else {
return "" + (glsm ? GLStateManager.glGetInteger(gLConstant) : GL11.glGetInteger(gLConstant));
}
}
case GL_GET_FLOATV: {
if(GLStateManager.HAS_MULTIPLE_SET.contains(gLConstant)) {
floatBuffer.clear();
if(glsm) {
GLStateManager.glGetFloat(gLConstant, floatBuffer);
} else {
GL11.glGetFloat(gLConstant, floatBuffer);
}
final StringBuilder out = new StringBuilder();
for (int i = 0; i < floatBuffer.remaining(); ++i) {
out.append(i == 0 ? "" : ", ").append(String.format("%f", floatBuffer.get(i)));
}
return out.toString();
} else {
return "" + (glsm ? GLStateManager.glGetFloat(gLConstant) : GL11.glGetFloat(gLConstant));
}
}
default: return "";
}
}
static final Matrix4f cachedMatrix = new Matrix4f();
static final Matrix4f uncachedMatrix = new Matrix4f();
public Matrix4f getAsMatrix4f(boolean glsm) {
if(!fetchCommand.equals(GL_GET_FLOATV)) {
throw new IllegalArgumentException("This property does not return a matrix");
}
floatBuffer.clear();
if(glsm) {
GLStateManager.glGetFloat(gLConstant, floatBuffer);
return cachedMatrix.set(0, floatBuffer);
} else {
GL11.glGetFloat(gLConstant, floatBuffer);
return uncachedMatrix.set(0, floatBuffer);
}
}
}
public static OpenGLDebugging instance = new OpenGLDebugging();
public GLproperty[] propertyList = {
new GLproperty(GL11.GL_ACCUM_ALPHA_BITS, "GL_ACCUM_ALPHA_BITS", "Number of bits per alpha component in the accumulation buffer", "capability", GL_GET_INTEGERV),
new GLproperty(GL11.GL_ACCUM_BLUE_BITS, "GL_ACCUM_BLUE_BITS", "Number of bits per blue component in the accumulation buffer", "capability", GL_GET_INTEGERV),
new GLproperty(GL11.GL_ACCUM_CLEAR_VALUE, "GL_ACCUM_CLEAR_VALUE", "Accumulation-buffer clear value", "accum-buffer", GL_GET_FLOATV),
new GLproperty(GL11.GL_ACCUM_GREEN_BITS, "GL_ACCUM_GREEN_BITS", "Number of bits per green component in the accumulation buffer", "capability", GL_GET_INTEGERV),
new GLproperty(GL11.GL_ACCUM_RED_BITS, "GL_ACCUM_RED_BITS", "Number of bits per red component in the accumulation buffer", "capability", GL_GET_INTEGERV),
new GLproperty(GL11.GL_ALPHA_BITS, "GL_ALPHA_BITS", "Number of bits per alpha component in color buffers", "capability", GL_GET_INTEGERV),
new GLproperty(GL11.GL_ALPHA_TEST, "GL_ALPHA_TEST", "Alpha test enabled", "color-buffer/enable", GL_IS_ENABLED),
new GLproperty(GL11.GL_ALPHA_TEST_FUNC, "GL_ALPHA_TEST_FUNC", "Alpha test function", "color-buffer", GL_GET_INTEGERV),
new GLproperty(GL11.GL_ALPHA_TEST_REF, "GL_ALPHA_TEST_REF", "Alpha test reference value", "color-buffer", GL_GET_FLOATV),
new GLproperty(GL11.GL_AMBIENT, "GL_AMBIENT", "Ambient intensity of light i", "lighting", "glGetLightfv()"),
new GLproperty(GL11.GL_AMBIENT, "GL_AMBIENT", "Ambient material color", "lighting", "glGetMaterialfv()"),
new GLproperty(GL11.GL_ATTRIB_STACK_DEPTH, "GL_ATTRIB_STACK_DEPTH", "Attribute stack pointer", "current", GL_GET_INTEGERV),
new GLproperty(GL11.GL_AUTO_NORMAL, "GL_AUTO_NORMAL", "True if automatic normal generation enabled", "eval", GL_IS_ENABLED),
new GLproperty(GL11.GL_AUX_BUFFERS, "GL_AUX_BUFFERS", "Number of auxiliary buffers", "capability", GL_GET_BOOLEANV),
new GLproperty(GL11.GL_BLEND, "GL_BLEND", "Blending enabled", "color-buffer/enable", GL_IS_ENABLED),
new GLproperty(GL11.GL_BLEND_DST, "GL_BLEND_DST", "Blending destination function", "color-buffer", GL_GET_INTEGERV),
new GLproperty(GL11.GL_BLEND_SRC, "GL_BLEND_SRC", "Blending source function", "color-buffer", GL_GET_INTEGERV),
new GLproperty(GL11.GL_BLUE_BITS, "GL_BLUE_BITS", "Number of bits per blue component in color buffers", "capability", GL_GET_INTEGERV),
new GLproperty(GL11.GL_CLIENT_ATTRIB_STACK_DEPTH, "GL_CLIENT_ATTRIB_STACK_DEPTH", "Client attribute stack pointer", "current", GL_GET_INTEGERV),
new GLproperty(GL11.GL_COEFF, "GL_COEFF", "1D control points", "capability", "glGetMapfv()"),
new GLproperty(GL11.GL_COEFF, "GL_COEFF", "2D control points", "capability", "glGetMapfv()"),
new GLproperty(GL11.GL_COLOR_ARRAY, "GL_COLOR_ARRAY", "RGBA color array enable", "vertex-array", GL_IS_ENABLED),
new GLproperty(GL11.GL_COLOR_ARRAY_POINTER, "GL_COLOR_ARRAY_POINTER", "Pointer to the color array", "vertex-array", "glGetPointerv()"),
new GLproperty(GL11.GL_COLOR_ARRAY_SIZE, "GL_COLOR_ARRAY_SIZE", "Colors per vertex", "vertex-array", GL_GET_INTEGERV),
new GLproperty(GL11.GL_COLOR_ARRAY_STRIDE, "GL_COLOR_ARRAY_STRIDE", "Stride between colors", "vertex-array", GL_GET_INTEGERV),
new GLproperty(GL11.GL_COLOR_ARRAY_TYPE, "GL_COLOR_ARRAY_TYPE", "Type of color components", "vertex-array", GL_GET_INTEGERV),
new GLproperty(GL11.GL_COLOR_CLEAR_VALUE, "GL_COLOR_CLEAR_VALUE", "Color-buffer clear value (RGBA mode)", "color-buffer", GL_GET_FLOATV),
new GLproperty(GL11.GL_COLOR_INDEXES, "GL_COLOR_INDEXES", "ca, cd, and cs for color-index lighting", "lighting/e nable", "glGetMaterialfv()"),
new GLproperty(GL11.GL_COLOR_LOGIC_OP, "GL_COLOR_LOGIC_OP", "RGBA color logical operation enabled", "color-buffer/enable", GL_IS_ENABLED),
new GLproperty(GL11.GL_COLOR_MATERIAL, "GL_COLOR_MATERIAL", "True if color tracking is enabled", "lighting", GL_IS_ENABLED),
new GLproperty(GL11.GL_COLOR_MATERIAL_FACE, "GL_COLOR_MATERIAL_FACE", "Face(s) affected by color tracking", "lighting", GL_GET_INTEGERV),
new GLproperty(GL11.GL_COLOR_MATERIAL_PARAMETER, "GL_COLOR_MATERIAL_PARAMETER", "Material properties tracking current color", "lighting", GL_GET_INTEGERV),
new GLproperty(GL11.GL_COLOR_WRITEMASK, "GL_COLOR_WRITEMASK", "Color write enables; R, G, B, or A", "color-buffer", GL_GET_BOOLEANV),
new GLproperty(GL11.GL_CONSTANT_ATTENUATION, "GL_CONSTANT_ATTENUATION", "Constant attenuation factor", "lighting", "glGetLightfv()"),
new GLproperty(GL11.GL_CULL_FACE, "GL_CULL_FACE", "Polygon culling enabled", "polygon/enable", GL_IS_ENABLED),
new GLproperty(GL11.GL_CULL_FACE_MODE, "GL_CULL_FACE_MODE", "Cull front-/back-facing polygons", "polygon", GL_GET_INTEGERV),
new GLproperty(GL11.GL_CURRENT_COLOR, "GL_CURRENT_COLOR", "Current color", "current", GL_GET_FLOATV),
new GLproperty(GL11.GL_CURRENT_INDEX, "GL_CURRENT_INDEX", "Current color index", "current", GL_GET_FLOATV),
new GLproperty(GL11.GL_CURRENT_NORMAL, "GL_CURRENT_NORMAL", "Current normal", "current", GL_GET_FLOATV),
new GLproperty(GL11.GL_CURRENT_RASTER_COLOR, "GL_CURRENT_RASTER_COLOR", "Color associated with raster position", "current", GL_GET_FLOATV),
new GLproperty(GL11.GL_CURRENT_RASTER_DISTANCE, "GL_CURRENT_RASTER_DISTANCE", "Current raster distance", "current", GL_GET_FLOATV),
new GLproperty(GL11.GL_CURRENT_RASTER_INDEX, "GL_CURRENT_RASTER_INDEX", "Color index associated with raster position", "current", GL_GET_FLOATV),
new GLproperty(GL11.GL_CURRENT_RASTER_POSITION, "GL_CURRENT_RASTER_POSITION", "Current raster position", "current", GL_GET_FLOATV),
new GLproperty(GL11.GL_CURRENT_RASTER_POSITION_VALID, "GL_CURRENT_RASTER_POSITION_VALID", "Raster position valid bit", "current", GL_GET_BOOLEANV),
new GLproperty(GL11.GL_CURRENT_RASTER_TEXTURE_COORDS, "GL_CURRENT_RASTER_TEXTURE_COORDS", "Texture coordinates associated with raster position", "current", GL_GET_FLOATV),
new GLproperty(GL11.GL_CURRENT_TEXTURE_COORDS, "GL_CURRENT_TEXTURE_COORDS", "Current texture coordinates", "current", GL_GET_FLOATV),
new GLproperty(GL11.GL_DEPTH_BITS, "GL_DEPTH_BITS", "Number of depth-buffer bitplanes", "capability", GL_GET_INTEGERV),
new GLproperty(GL11.GL_DEPTH_CLEAR_VALUE, "GL_DEPTH_CLEAR_VALUE", "Depth-buffer clear value", "depth-buffer", GL_GET_INTEGERV),
new GLproperty(GL11.GL_DEPTH_FUNC, "GL_DEPTH_FUNC", "Depth buffer test function", "depth-buffer", GL_GET_INTEGERV),
new GLproperty(GL11.GL_DEPTH_RANGE, "GL_DEPTH_RANGE", "Depth range near and far", "viewport", GL_GET_FLOATV),
new GLproperty(GL11.GL_DEPTH_TEST, "GL_DEPTH_TEST", "Depth buffer enabled", "depth-buffer/ena ble", GL_IS_ENABLED),
new GLproperty(GL11.GL_DEPTH_WRITEMASK, "GL_DEPTH_WRITEMASK", "Depth buffer enabled for writing", "depth-buffer", GL_GET_BOOLEANV),
new GLproperty(GL11.GL_DIFFUSE, "GL_DIFFUSE", "Diffuse intensity of light i", "lighting", "glGetLightfv()"),
new GLproperty(GL11.GL_DIFFUSE, "GL_DIFFUSE", "Diffuse material color", "lighting", "glGetMaterialfv()"),
new GLproperty(GL11.GL_DITHER, "GL_DITHER", "Dithering enabled", "color-buffer/enable", GL_IS_ENABLED),
new GLproperty(GL11.GL_DOMAIN, "GL_DOMAIN", "1D domain endpoints", "capability", "glGetMapfv()"),
new GLproperty(GL11.GL_DOMAIN, "GL_DOMAIN", "2D domain endpoints", "capability", "glGetMapfv()"),
new GLproperty(GL11.GL_DOUBLEBUFFER, "GL_DOUBLEBUFFER", "True if front and back buffers exist", "capability", GL_GET_BOOLEANV),
new GLproperty(GL11.GL_DRAW_BUFFER, "GL_DRAW_BUFFER", "Buffers selected for drawing", "color-buffer", GL_GET_INTEGERV),
new GLproperty(GL11.GL_EDGE_FLAG, "GL_EDGE_FLAG", "Edge flag", "current", GL_GET_BOOLEANV),
new GLproperty(GL11.GL_EDGE_FLAG_ARRAY, "GL_EDGE_FLAG_ARRAY", "Edge flag array enable", "vertex-array", GL_IS_ENABLED),
new GLproperty(GL11.GL_EDGE_FLAG_ARRAY_POINTER, "GL_EDGE_FLAG_ARRAY_POINTER", "Pointer to the edge flag array", "vertex-array", "glGetPointerv()"),
new GLproperty(GL11.GL_EDGE_FLAG_ARRAY_STRIDE, "GL_EDGE_FLAG_ARRAY_STRIDE", "Stride between edge flags", "vertex-array", GL_GET_INTEGERV),
new GLproperty(GL11.GL_EMISSION, "GL_EMISSION", "Emissive material color", "lighting", "glGetMaterialfv()"),
new GLproperty(GL11.GL_EYE_PLANE, "GL_EYE_PLANE", "Texgen plane equation coefficients", "texture", "glGetTexGenfv()"),
new GLproperty(GL11.GL_FEEDBACK_BUFFER_POINTER, "GL_FEEDBACK_BUFFER_POINTER", "Pointer to feedback buffer", "feedback", "glGetPointerv()"),
new GLproperty(GL11.GL_FEEDBACK_BUFFER_SIZE, "GL_FEEDBACK_BUFFER_SIZE", "Size of feedback buffer", "feedback", GL_GET_INTEGERV),
new GLproperty(GL11.GL_FEEDBACK_BUFFER_TYPE, "GL_FEEDBACK_BUFFER_TYPE", "Type of feedback buffer", "feedback", GL_GET_INTEGERV),
new GLproperty(GL11.GL_FOG, "GL_FOG", "True if fog enabled", "fog/enable", GL_IS_ENABLED),
new GLproperty(GL11.GL_FOG_COLOR, "GL_FOG_COLOR", "Fog color", "fog", GL_GET_FLOATV),
new GLproperty(GL11.GL_FOG_DENSITY, "GL_FOG_DENSITY", "Exponential fog density", "fog", GL_GET_FLOATV),
new GLproperty(GL11.GL_FOG_END, "GL_FOG_END", "Linear fog end", "fog", GL_GET_FLOATV),
new GLproperty(GL11.GL_FOG_HINT, "GL_FOG_HINT", "Fog hint", "hint", GL_GET_INTEGERV),
new GLproperty(GL11.GL_FOG_INDEX, "GL_FOG_INDEX", "Fog index", "fog", GL_GET_FLOATV),
new GLproperty(GL11.GL_FOG_MODE, "GL_FOG_MODE", "Fog mode", "fog", GL_GET_INTEGERV),
new GLproperty(GL11.GL_FOG_START, "GL_FOG_START", "Linear fog start", "fog", GL_GET_FLOATV),
new GLproperty(GL11.GL_FRONT_FACE, "GL_FRONT_FACE", "Polygon front-face CW/CCW indicator", "polygon", GL_GET_INTEGERV),
new GLproperty(GL11.GL_GREEN_BITS, "GL_GREEN_BITS", "Number of bits per green component in color buffers", "capability", GL_GET_INTEGERV),
new GLproperty(GL11.GL_INDEX_ARRAY, "GL_INDEX_ARRAY", "Color-index array enable", "vertex-array", GL_IS_ENABLED),
new GLproperty(GL11.GL_INDEX_ARRAY_POINTER, "GL_INDEX_ARRAY_POINTER", "Pointer to the index array", "vertex-array", "glGetPointerv()"),
new GLproperty(GL11.GL_INDEX_ARRAY_STRIDE, "GL_INDEX_ARRAY_STRIDE", "Stride between color indices", "vertex-array", GL_GET_INTEGERV),
new GLproperty(GL11.GL_INDEX_ARRAY_TYPE, "GL_INDEX_ARRAY_TYPE", "Type of color indices", "vertex-array", GL_GET_INTEGERV),
new GLproperty(GL11.GL_INDEX_BITS, "GL_INDEX_BITS", "Number of bits per index in color buffers", "capability", GL_GET_INTEGERV),
new GLproperty(GL11.GL_INDEX_CLEAR_VALUE, "GL_INDEX_CLEAR_VALUE", "Color-buffer clear value (color-index mode)", "color-buffer", GL_GET_FLOATV),
new GLproperty(GL11.GL_INDEX_LOGIC_OP, "GL_INDEX_LOGIC_OP", "Color index logical operation enabled", "color-buffer/enable", GL_IS_ENABLED),
new GLproperty(GL11.GL_INDEX_MODE, "GL_INDEX_MODE", "True if color buffers store indices", "capability", GL_GET_BOOLEANV),
new GLproperty(GL11.GL_INDEX_OFFSET, "GL_INDEX_OFFSET", "Value of GL_INDEX_OFFSET", "pixel", GL_GET_INTEGERV),
new GLproperty(GL11.GL_INDEX_SHIFT, "GL_INDEX_SHIFT", "Value of GL_INDEX_SHIFT", "pixel", GL_GET_INTEGERV),
new GLproperty(GL11.GL_INDEX_WRITEMASK, "GL_INDEX_WRITEMASK", "Color-index writemask", "color-buffer", GL_GET_INTEGERV),
new GLproperty(GL11.GL_LIGHT0, "GL_LIGHT0", "True if light 0 enabled", "lighting/enable", GL_IS_ENABLED),
new GLproperty(GL11.GL_LIGHT1, "GL_LIGHT1", "True if light 1 enabled", "lighting/enable", GL_IS_ENABLED),
new GLproperty(GL11.GL_LIGHT2, "GL_LIGHT2", "True if light 2 enabled", "lighting/enable", GL_IS_ENABLED),
new GLproperty(GL11.GL_LIGHT3, "GL_LIGHT3", "True if light 3 enabled", "lighting/enable", GL_IS_ENABLED),
new GLproperty(GL11.GL_LIGHT4, "GL_LIGHT4", "True if light 4 enabled", "lighting/enable", GL_IS_ENABLED),
new GLproperty(GL11.GL_LIGHT5, "GL_LIGHT5", "True if light 5 enabled", "lighting/enable", GL_IS_ENABLED),
new GLproperty(GL11.GL_LIGHT6, "GL_LIGHT6", "True if light 6 enabled", "lighting/enable", GL_IS_ENABLED),
new GLproperty(GL11.GL_LIGHT7, "GL_LIGHT7", "True if light 7 enabled", "lighting/enable", GL_IS_ENABLED),
new GLproperty(GL11.GL_LIGHTING, "GL_LIGHTING", "True if lighting is enabled", "lighting/e nable", GL_IS_ENABLED),
new GLproperty(GL11.GL_LIGHT_MODEL_AMBIENT, "GL_LIGHT_MODEL_AMBIENT", "Ambient scene color", "lighting", GL_GET_FLOATV),
new GLproperty(GL11.GL_LIGHT_MODEL_LOCAL_VIEWER, "GL_LIGHT_MODEL_LOCAL_VIEWER", "Viewer is local", "lighting", GL_GET_BOOLEANV),
new GLproperty(GL11.GL_LIGHT_MODEL_TWO_SIDE, "GL_LIGHT_MODEL_TWO_SIDE", "Use two-sided lighting", "lighting", GL_GET_BOOLEANV),
new GLproperty(GL11.GL_LINEAR_ATTENUATION, "GL_LINEAR_ATTENUATION", "Linear attenuation factor", "lighting", "glGetLightfv()"),
new GLproperty(GL11.GL_LINE_SMOOTH, "GL_LINE_SMOOTH", "Line antialiasing on", "line/enable", GL_IS_ENABLED),
new GLproperty(GL11.GL_LINE_SMOOTH_HINT, "GL_LINE_SMOOTH_HINT", "Line smooth hint", "hint", GL_GET_INTEGERV),
new GLproperty(GL11.GL_LINE_STIPPLE, "GL_LINE_STIPPLE", "Line stipple enable", "line/enable", GL_IS_ENABLED),
new GLproperty(GL11.GL_LINE_STIPPLE_PATTERN, "GL_LINE_STIPPLE_PATTERN", "Line stipple", "line", GL_GET_INTEGERV),
new GLproperty(GL11.GL_LINE_STIPPLE_REPEAT, "GL_LINE_STIPPLE_REPEAT", "Line stipple repeat", "line", GL_GET_INTEGERV),
new GLproperty(GL11.GL_LINE_WIDTH, "GL_LINE_WIDTH", "Line width", "line", GL_GET_FLOATV),
new GLproperty(GL11.GL_LINE_WIDTH_GRANULARITY, "GL_LINE_WIDTH_GRANULARITY", "Antialiased line-width granularity", "capability", GL_GET_FLOATV),
new GLproperty(GL11.GL_LINE_WIDTH_RANGE, "GL_LINE_WIDTH_RANGE", "Range (low to high) of antialiased line widths", "capability", GL_GET_FLOATV),
new GLproperty(GL11.GL_LIST_BASE, "GL_LIST_BASE", "Setting of glListBase()", "list", GL_GET_INTEGERV),
new GLproperty(GL11.GL_LIST_INDEX, "GL_LIST_INDEX", "Number of display list under construction; 0 if none", "current", GL_GET_INTEGERV),
new GLproperty(GL11.GL_LIST_MODE, "GL_LIST_MODE", "Mode of display list under construction; undefined if none", "current", GL_GET_INTEGERV),
new GLproperty(GL11.GL_LOGIC_OP_MODE, "GL_LOGIC_OP_MODE", "Logical operation function", "color-buffer", GL_GET_INTEGERV),
new GLproperty(GL11.GL_MAP1_GRID_DOMAIN, "GL_MAP1_GRID_DOMAIN", "1D grid endpoints", "eval", GL_GET_FLOATV),
new GLproperty(GL11.GL_MAP1_GRID_SEGMENTS, "GL_MAP1_GRID_SEGMENTS", "1D grid divisions", "eval", GL_GET_FLOATV),
new GLproperty(GL11.GL_MAP2_GRID_DOMAIN, "GL_MAP2_GRID_DOMAIN", "2D grid endpoints", "eval", GL_GET_FLOATV),
new GLproperty(GL11.GL_MAP2_GRID_SEGMENTS, "GL_MAP2_GRID_SEGMENTS", "2D grid divisions", "eval", GL_GET_FLOATV),
new GLproperty(GL11.GL_MAP_COLOR, "GL_MAP_COLOR", "True if colors are mapped", "pixel", GL_GET_BOOLEANV),
new GLproperty(GL11.GL_MAP_STENCIL, "GL_MAP_STENCIL", "True if stencil values are mapped", "pixel", GL_GET_BOOLEANV),
new GLproperty(GL11.GL_MATRIX_MODE, "GL_MATRIX_MODE", "Current matrix mode", "transform", GL_GET_INTEGERV),
new GLproperty(GL11.GL_MAX_ATTRIB_STACK_DEPTH, "GL_MAX_ATTRIB_STACK_DEPTH", "Maximum depth of the attribute stack", "capability", GL_GET_INTEGERV),
new GLproperty(GL11.GL_MAX_CLIENT_ATTRIB_STACK_DEPTH, "GL_MAX_CLIENT_ATTRIB_STACK_DEPTH", "Maximum depth of the client attribute stack", "capability", GL_GET_INTEGERV),
new GLproperty(GL11.GL_MAX_CLIP_PLANES, "GL_MAX_CLIP_PLANES", "Maximum number of user clipping planes", "capability", GL_GET_INTEGERV),
new GLproperty(GL11.GL_MAX_EVAL_ORDER, "GL_MAX_EVAL_ORDER", "Maximum evaluator polynomial order", "capability", GL_GET_INTEGERV),
new GLproperty(GL11.GL_MAX_LIGHTS, "GL_MAX_LIGHTS", "Maximum number of lights", "capability", GL_GET_INTEGERV),
new GLproperty(GL11.GL_MAX_LIST_NESTING, "GL_MAX_LIST_NESTING", "Maximum display-list call nesting", "capability", GL_GET_INTEGERV),
new GLproperty(GL11.GL_MAX_MODELVIEW_STACK_DEPTH, "GL_MAX_MODELVIEW_STACK_DEPTH", "Maximum modelview-matrix stack depth", "capability", GL_GET_INTEGERV),
new GLproperty(GL11.GL_MAX_NAME_STACK_DEPTH, "GL_MAX_NAME_STACK_DEPTH", "Maximum selection-name stack depth", "capability", GL_GET_INTEGERV),
new GLproperty(GL11.GL_MAX_PIXEL_MAP_TABLE, "GL_MAX_PIXEL_MAP_TABLE", "Maximum size of a glPixelMap() translation table", "capability", GL_GET_INTEGERV),
new GLproperty(GL11.GL_MAX_PROJECTION_STACK_DEPTH, "GL_MAX_PROJECTION_STACK_DEPTH", "Maximum projection-matrix stack depth", "capability", GL_GET_INTEGERV),
new GLproperty(GL11.GL_MAX_TEXTURE_SIZE, "GL_MAX_TEXTURE_SIZE", "See discussion in Texture Proxy in Chapter 9", "capability", GL_GET_INTEGERV),
new GLproperty(GL11.GL_MAX_TEXTURE_STACK_DEPTH, "GL_MAX_TEXTURE_STACK_DEPTH", "Maximum depth of texture matrix stack", "capability", GL_GET_INTEGERV),
new GLproperty(GL11.GL_MAX_VIEWPORT_DIMS, "GL_MAX_VIEWPORT_DIMS", "Maximum viewport dimensions", "capability", GL_GET_INTEGERV),
new GLproperty(GL11.GL_MODELVIEW_MATRIX, "GL_MODELVIEW_MATRIX", "Modelview matrix stack", "matrix", GL_GET_FLOATV),
new GLproperty(GL11.GL_MODELVIEW_STACK_DEPTH, "GL_MODELVIEW_STACK_DEPTH", "Modelview matrix stack pointer", "matrix", GL_GET_INTEGERV),
new GLproperty(GL11.GL_NAME_STACK_DEPTH, "GL_NAME_STACK_DEPTH", "Name stack depth", "current", GL_GET_INTEGERV),
new GLproperty(GL11.GL_NORMALIZE, "GL_NORMALIZE", "Current normal normalization on/off", "transform/ enable", GL_IS_ENABLED),
new GLproperty(GL11.GL_NORMAL_ARRAY, "GL_NORMAL_ARRAY", "Normal array enable", "vertex-array", GL_IS_ENABLED),
new GLproperty(GL11.GL_NORMAL_ARRAY_POINTER, "GL_NORMAL_ARRAY_POINTER", "Pointer to the normal array", "vertex-array", "glGetPointerv()"),
new GLproperty(GL11.GL_NORMAL_ARRAY_STRIDE, "GL_NORMAL_ARRAY_STRIDE", "Stride between normals", "vertex-array", GL_GET_INTEGERV),
new GLproperty(GL11.GL_NORMAL_ARRAY_TYPE, "GL_NORMAL_ARRAY_TYPE", "Type of normal coordinates", "vertex-array", GL_GET_INTEGERV),
new GLproperty(GL11.GL_OBJECT_PLANE, "GL_OBJECT_PLANE", "Texgen object linear coefficients", "texture", "glGetTexGenfv()"),
new GLproperty(GL11.GL_ORDER, "GL_ORDER", "1D map order", "capability", "glGetMapiv()"),
new GLproperty(GL11.GL_ORDER, "GL_ORDER", "2D map orders", "capability", "glGetMapiv()"),
new GLproperty(GL11.GL_PACK_ALIGNMENT, "GL_PACK_ALIGNMENT", "Value of GL_PACK_ALIGNMENT", "pixel-store", GL_GET_INTEGERV),
new GLproperty(GL11.GL_PACK_LSB_FIRST, "GL_PACK_LSB_FIRST", "Value of GL_PACK_LSB_FIRST", "pixel-store", GL_GET_BOOLEANV),
new GLproperty(GL11.GL_PACK_ROW_LENGTH, "GL_PACK_ROW_LENGTH", "Value of GL_PACK_ROW_LENGTH", "pixel-store", GL_GET_INTEGERV),
new GLproperty(GL11.GL_PACK_SKIP_PIXELS, "GL_PACK_SKIP_PIXELS", "Value of GL_PACK_SKIP_PIXELS", "pixel-store", GL_GET_INTEGERV),
new GLproperty(GL11.GL_PACK_SKIP_ROWS, "GL_PACK_SKIP_ROWS", "Value of GL_PACK_SKIP_ROWS", "pixel-store", GL_GET_INTEGERV),
new GLproperty(GL11.GL_PACK_SWAP_BYTES, "GL_PACK_SWAP_BYTES", "Value of GL_PACK_SWAP_BYTES", "pixel-store", GL_GET_BOOLEANV),
new GLproperty(GL11.GL_PERSPECTIVE_CORRECTION_HINT, "GL_PERSPECTIVE_CORRECTION_HINT", "Perspective correction hint", "hint", GL_GET_INTEGERV),
new GLproperty(GL11.GL_POINT_SIZE, "GL_POINT_SIZE", "Point size", "point", GL_GET_FLOATV),
new GLproperty(GL11.GL_POINT_SIZE_GRANULARITY, "GL_POINT_SIZE_GRANULARITY", "Antialiased point-size granularity", "capability", GL_GET_FLOATV),
new GLproperty(GL11.GL_POINT_SIZE_RANGE, "GL_POINT_SIZE_RANGE", "Range (low to high) of antialiased point sizes", "capability", GL_GET_FLOATV),
new GLproperty(GL11.GL_POINT_SMOOTH, "GL_POINT_SMOOTH", "Point antialiasing on", "point/enable", GL_IS_ENABLED),
new GLproperty(GL11.GL_POINT_SMOOTH_HINT, "GL_POINT_SMOOTH_HINT", "Point smooth hint", "hint", GL_GET_INTEGERV),
new GLproperty(GL11.GL_POLYGON_MODE, "GL_POLYGON_MODE", "Polygon rasterization mode (front and back)", "polygon", GL_GET_INTEGERV),
new GLproperty(GL11.GL_POLYGON_OFFSET_FACTOR, "GL_POLYGON_OFFSET_FACTOR", "Polygon offset factor", "polygon", GL_GET_FLOATV),
new GLproperty(GL11.GL_POLYGON_OFFSET_FILL, "GL_POLYGON_OFFSET_FILL", "Polygon offset enable for GL_FILL mode rasterization", "polygon/enable", GL_IS_ENABLED),
new GLproperty(GL11.GL_POLYGON_OFFSET_LINE, "GL_POLYGON_OFFSET_LINE", "Polygon offset enable for GL_LINE mode rasterization", "polygon/enable", GL_IS_ENABLED),
new GLproperty(GL11.GL_POLYGON_OFFSET_POINT, "GL_POLYGON_OFFSET_POINT", "Polygon offset enable for GL_POINT mode rasterization", "polygon/enable", GL_IS_ENABLED),
new GLproperty(GL11.GL_POLYGON_SMOOTH, "GL_POLYGON_SMOOTH", "Polygon antialiasing on", "polygon/enable", GL_IS_ENABLED),
new GLproperty(GL11.GL_POLYGON_SMOOTH_HINT, "GL_POLYGON_SMOOTH_HINT", "Polygon smooth hint", "hint", GL_GET_INTEGERV),
new GLproperty(GL11.GL_POLYGON_STIPPLE, "GL_POLYGON_STIPPLE", "Polygon stipple enable", "polygon/enable", GL_IS_ENABLED),
new GLproperty(GL11.GL_POSITION, "GL_POSITION", "Position of light i", "lighting", "glGetLightfv()"),
new GLproperty(GL11.GL_PROJECTION_MATRIX, "GL_PROJECTION_MATRIX", "Projection matrix stack", "matrix", GL_GET_FLOATV),
new GLproperty(GL11.GL_PROJECTION_STACK_DEPTH, "GL_PROJECTION_STACK_DEPTH", "Projection matrix stack pointer", "matrix", GL_GET_INTEGERV),
new GLproperty(GL11.GL_QUADRATIC_ATTENUATION, "GL_QUADRATIC_ATTENUATION", "Quadratic attenuation factor", "lighting", "glGetLightfv()"),
new GLproperty(GL11.GL_READ_BUFFER, "GL_READ_BUFFER", "Read source buffer", "pixel", GL_GET_INTEGERV),
new GLproperty(GL11.GL_RED_BITS, "GL_RED_BITS", "Number of bits per red component in color buffers", "capability", GL_GET_INTEGERV),
new GLproperty(GL11.GL_RENDER_MODE, "GL_RENDER_MODE", "glRenderMode() setting", "current", GL_GET_INTEGERV),
new GLproperty(GL11.GL_RGBA_MODE, "GL_RGBA_MODE", "True if color buffers store RGBA", "capability", GL_GET_BOOLEANV),
new GLproperty(GL11.GL_SCISSOR_BOX, "GL_SCISSOR_BOX", "Scissor box", "scissor", GL_GET_INTEGERV),
new GLproperty(GL11.GL_SCISSOR_TEST, "GL_SCISSOR_TEST", "Scissoring enabled", "scissor/enable", GL_IS_ENABLED),
new GLproperty(GL11.GL_SELECTION_BUFFER_POINTER, "GL_SELECTION_BUFFER_POINTER", "Pointer to selection buffer", "select", "glGetPointerv()"),
new GLproperty(GL11.GL_SELECTION_BUFFER_SIZE, "GL_SELECTION_BUFFER_SIZE", "Size of selection buffer", "select", GL_GET_INTEGERV),
new GLproperty(GL11.GL_SHADE_MODEL, "GL_SHADE_MODEL", "glShadeModel() setting", "lighting", GL_GET_INTEGERV),
new GLproperty(GL11.GL_SHININESS, "GL_SHININESS", "Specular exponent of material", "lighting", "glGetMaterialfv()"),
new GLproperty(GL11.GL_SPECULAR, "GL_SPECULAR", "Specular intensity of light i", "lighting", "glGetLightfv()"),
new GLproperty(GL11.GL_SPECULAR, "GL_SPECULAR", "Specular material color", "lighting", "glGetMaterialfv()"),
new GLproperty(GL11.GL_SPOT_CUTOFF, "GL_SPOT_CUTOFF", "Spotlight angle of light i", "lighting", "glGetLightfv()"),
new GLproperty(GL11.GL_SPOT_DIRECTION, "GL_SPOT_DIRECTION", "Spotlight direction of light i", "lighting", "glGetLightfv()"),
new GLproperty(GL11.GL_SPOT_EXPONENT, "GL_SPOT_EXPONENT", "Spotlight exponent of light i", "lighting", "glGetLightfv()"),
new GLproperty(GL11.GL_STENCIL_BITS, "GL_STENCIL_BITS", "Number of stencil bitplanes", "capability", GL_GET_INTEGERV),
new GLproperty(GL11.GL_STENCIL_CLEAR_VALUE, "GL_STENCIL_CLEAR_VALUE", "Stencil-buffer clear value", "stencil-buffer", GL_GET_INTEGERV),
new GLproperty(GL11.GL_STENCIL_FAIL, "GL_STENCIL_FAIL", "Stencil fail action", "stencil-buffer", GL_GET_INTEGERV),
new GLproperty(GL11.GL_STENCIL_FUNC, "GL_STENCIL_FUNC", "Stencil function", "stencil-buffer", GL_GET_INTEGERV),
new GLproperty(GL11.GL_STENCIL_PASS_DEPTH_FAIL, "GL_STENCIL_PASS_DEPTH_FAIL", "Stencil depth buffer fail action", "stencil-buffer", GL_GET_INTEGERV),
new GLproperty(GL11.GL_STENCIL_PASS_DEPTH_PASS, "GL_STENCIL_PASS_DEPTH_PASS", "Stencil depth buffer pass action", "stencil-buffer", GL_GET_INTEGERV),
new GLproperty(GL11.GL_STENCIL_REF, "GL_STENCIL_REF", "Stencil reference value", "stencil-buffer", GL_GET_INTEGERV),
new GLproperty(GL11.GL_STENCIL_TEST, "GL_STENCIL_TEST", "Stenciling enabled", "stencil-buffer/enable", GL_IS_ENABLED),
new GLproperty(GL11.GL_STENCIL_VALUE_MASK, "GL_STENCIL_VALUE_MASK", "Stencil mask", "stencil-buffer", GL_GET_INTEGERV),
new GLproperty(GL11.GL_STENCIL_WRITEMASK, "GL_STENCIL_WRITEMASK", "Stencil-buffer writemask", "stencil-buffer", GL_GET_INTEGERV),
new GLproperty(GL11.GL_STEREO, "GL_STEREO", "True if left and right buffers exist", "capability", GL_GET_BOOLEANV),
new GLproperty(GL11.GL_SUBPIXEL_BITS, "GL_SUBPIXEL_BITS", "Number of bits of subpixel precision in x and y", "capability", GL_GET_INTEGERV),
new GLproperty(GL11.GL_TEXTURE, "GL_TEXTURE", "x-D texture image at level of detail i", "UNUSED", "glGetTexImage()"),
new GLproperty(GL11.GL_TEXTURE_1D, "GL_TEXTURE_1D", "True if 1-D texturing enabled ", "texture/enable", GL_IS_ENABLED),
new GLproperty(GL11.GL_TEXTURE_2D, "GL_TEXTURE_2D", "True if 2-D texturing enabled ", "texture/enable", GL_IS_ENABLED),
new GLproperty(GL11.GL_TEXTURE_ALPHA_SIZE, "GL_TEXTURE_ALPHA_SIZE", "x-D texture image i's alpha resolution", "UNUSED", "glGetTexLevelParameter*()"),
new GLproperty(GL11.GL_TEXTURE_BINDING_1D, "GL_TEXTURE_BINDING_1D", "Texture object bound to GL_TEXTURE_1D", "texture", GL_GET_INTEGERV),
new GLproperty(GL11.GL_TEXTURE_BINDING_2D, "GL_TEXTURE_BINDING_2D", "Texture object bound to GL_TEXTURE_2D", "texture", GL_GET_INTEGERV),
new GLproperty(GL11.GL_TEXTURE_BLUE_SIZE, "GL_TEXTURE_BLUE_SIZE", "x-D texture image i's blue resolution", "UNUSED", "glGetTexLevelParameter*()"),
new GLproperty(GL11.GL_TEXTURE_BORDER, "GL_TEXTURE_BORDER", "x-D texture image i's border width", "UNUSED", "glGetTexLevelParameter*()"),
new GLproperty(GL11.GL_TEXTURE_BORDER_COLOR, "GL_TEXTURE_BORDER_COLOR", "Texture border color", "texture", "glGetTexParameter*()"),
new GLproperty(GL11.GL_TEXTURE_COORD_ARRAY, "GL_TEXTURE_COORD_ARRAY", "Texture coordinate array enable", "vertex-array", GL_IS_ENABLED),
new GLproperty(GL11.GL_TEXTURE_COORD_ARRAY_POINTER, "GL_TEXTURE_COORD_ARRAY_POINTER", "Pointer to the texture coordinate array", "vertex-array", "glGetPointerv()"),
new GLproperty(GL11.GL_TEXTURE_COORD_ARRAY_SIZE, "GL_TEXTURE_COORD_ARRAY_SIZE", "Texture coordinates per element", "vertex-array", GL_GET_INTEGERV),
new GLproperty(GL11.GL_TEXTURE_COORD_ARRAY_STRIDE, "GL_TEXTURE_COORD_ARRAY_STRIDE", "Stride between texture coordinates", "vertex-array", GL_GET_INTEGERV),
new GLproperty(GL11.GL_TEXTURE_COORD_ARRAY_TYPE, "GL_TEXTURE_COORD_ARRAY_TYPE", "Type of texture coordinates", "vertex-array", GL_GET_INTEGERV),
new GLproperty(GL11.GL_TEXTURE_ENV_COLOR, "GL_TEXTURE_ENV_COLOR", "Texture environment color", "texture", "glGetTexEnvfv()"),
new GLproperty(GL11.GL_TEXTURE_ENV_MODE, "GL_TEXTURE_ENV_MODE", "Texture application function", "texture", "glGetTexEnviv()"),
new GLproperty(GL11.GL_TEXTURE_GEN_MODE, "GL_TEXTURE_GEN_MODE", "Function used for texgen", "texture", "glGetTexGeniv()"),
new GLproperty(GL11.GL_TEXTURE_GEN_Q, "GL_TEXTURE_GEN_Q", "Texgen enabled (x is S, T, R, or Q)", "texture/enable", GL_IS_ENABLED),
new GLproperty(GL11.GL_TEXTURE_GEN_R, "GL_TEXTURE_GEN_R", "Texgen enabled (x is S, T, R, or Q)", "texture/enable", GL_IS_ENABLED),
new GLproperty(GL11.GL_TEXTURE_GEN_S, "GL_TEXTURE_GEN_S", "Texgen enabled (x is S, T, R, or Q)", "texture/enable", GL_IS_ENABLED),
new GLproperty(GL11.GL_TEXTURE_GEN_T, "GL_TEXTURE_GEN_T", "Texgen enabled (x is S, T, R, or Q)", "texture/enable", GL_IS_ENABLED),
new GLproperty(GL11.GL_TEXTURE_GREEN_SIZE, "GL_TEXTURE_GREEN_SIZE", "x-D texture image i's green resolution", "UNUSED", "glGetTexLevelParameter*()"),
new GLproperty(GL11.GL_TEXTURE_HEIGHT, "GL_TEXTURE_HEIGHT", "x-D texture image i's height", "UNUSED", "glGetTexLevelParameter*()"),
new GLproperty(GL11.GL_TEXTURE_INTENSITY_SIZE, "GL_TEXTURE_INTENSITY_SIZE", "x-D texture image i's intensity resolution", "UNUSED", "glGetTexLevelParameter*()"),
new GLproperty(GL11.GL_TEXTURE_LUMINANCE_SIZE, "GL_TEXTURE_LUMINANCE_SIZE", "x-D texture image i's luminance resolution", "UNUSED", "glGetTexLevelParameter*()"),
new GLproperty(GL11.GL_TEXTURE_MAG_FILTER, "GL_TEXTURE_MAG_FILTER", "Texture magnification function", "texture", "glGetTexParameter*()"),
new GLproperty(GL11.GL_TEXTURE_MATRIX, "GL_TEXTURE_MATRIX", "Texture matrix stack", "matrix", GL_GET_FLOATV),
new GLproperty(GL11.GL_TEXTURE_MIN_FILTER, "GL_TEXTURE_MIN_FILTER", "Texture minification function", "texture", "glGetTexParameter*()"),
new GLproperty(GL11.GL_TEXTURE_PRIORITY, "GL_TEXTURE_PRIORITY", "Texture object priority", "texture", "glGetTexParameter*()"),
new GLproperty(GL11.GL_TEXTURE_RED_SIZE, "GL_TEXTURE_RED_SIZE", "x-D texture image i's red resolution", "UNUSED", "glGetTexLevelParameter*()"),
new GLproperty(GL11.GL_TEXTURE_STACK_DEPTH, "GL_TEXTURE_STACK_DEPTH", "Texture matrix stack pointer", "matrix", GL_GET_INTEGERV),
new GLproperty(GL11.GL_TEXTURE_WIDTH, "GL_TEXTURE_WIDTH", "x-D texture image i's width", "UNUSED", "glGetTexLevelParameter*()"),
new GLproperty(GL11.GL_TEXTURE_WRAP_S, "GL_TEXTURE_WRAP_S", "Texture wrap mode (x is S or T)", "texture", "glGetTexParameter*()"),
new GLproperty(GL11.GL_TEXTURE_WRAP_T, "GL_TEXTURE_WRAP_T", "Texture wrap mode (x is S or T)", "texture", "glGetTexParameter*()"),
new GLproperty(GL11.GL_UNPACK_ALIGNMENT, "GL_UNPACK_ALIGNMENT", "Value of GL_UNPACK_ALIGNMENT", "pixel-store", GL_GET_INTEGERV),
new GLproperty(GL11.GL_UNPACK_LSB_FIRST, "GL_UNPACK_LSB_FIRST", "Value of GL_UNPACK_LSB_FIRST", "pixel-store", GL_GET_BOOLEANV),
new GLproperty(GL11.GL_UNPACK_ROW_LENGTH, "GL_UNPACK_ROW_LENGTH", "Value of GL_UNPACK_ROW_LENGTH", "pixel-store", GL_GET_INTEGERV),
new GLproperty(GL11.GL_UNPACK_SKIP_PIXELS, "GL_UNPACK_SKIP_PIXELS", "Value of GL_UNPACK_SKIP_PIXELS", "pixel-store", GL_GET_INTEGERV),
new GLproperty(GL11.GL_UNPACK_SKIP_ROWS, "GL_UNPACK_SKIP_ROWS", "Value of GL_UNPACK_SKIP_ROWS", "pixel-store", GL_GET_INTEGERV),
new GLproperty(GL11.GL_UNPACK_SWAP_BYTES, "GL_UNPACK_SWAP_BYTES", "Value of GL_UNPACK_SWAP_BYTES", "pixel-store", GL_GET_BOOLEANV),
new GLproperty(GL11.GL_VERTEX_ARRAY, "GL_VERTEX_ARRAY", "Vertex array enable", "vertex-array", GL_IS_ENABLED),
new GLproperty(GL11.GL_VERTEX_ARRAY_POINTER, "GL_VERTEX_ARRAY_POINTER", "Pointer to the vertex array", "vertex-array", "glGetPointerv()"),
new GLproperty(GL11.GL_VERTEX_ARRAY_SIZE, "GL_VERTEX_ARRAY_SIZE", "Coordinates per vertex", "vertex-array", GL_GET_INTEGERV),
new GLproperty(GL11.GL_VERTEX_ARRAY_STRIDE, "GL_VERTEX_ARRAY_STRIDE", "Stride between vertices", "vertex-array", GL_GET_INTEGERV),
new GLproperty(GL11.GL_VERTEX_ARRAY_TYPE, "GL_VERTEX_ARRAY_TYPE", "Type of vertex coordinates", "vertex-array", GL_GET_INTEGERV),
new GLproperty(GL11.GL_VIEWPORT, "GL_VIEWPORT", "Viewport origin and extent", "viewport", GL_GET_INTEGERV),
new GLproperty(GL11.GL_ZOOM_X, "GL_ZOOM_X", "x zoom factor", "pixel", GL_GET_FLOATV),
new GLproperty(GL11.GL_ZOOM_Y, "GL_ZOOM_Y", "y zoom factor", "pixel", GL_GET_FLOATV),
};
public static void dumpToFile(Consumer<Consumer<String>> dumper, String fileName) {
final List<String> lines = new ArrayList<>();
dumper.accept(lines::add);
try {
FileUtils.writeLines(new File(fileName), lines);
} catch (IOException e) {
LOGGER.error("Failed to write file");
e.printStackTrace();
}
}
public static void dumpStateToFile() {
dumpToFile(p -> dumpState(p, false), "gl-dump-state.txt");
}
public static void dumpGLSMStateToFile() {
dumpToFile(p -> dumpState(p, true), "glsm-dump-state.txt");
}
public static void dumpState(boolean glsm) {
dumpState(LINE_LOGGER, glsm);
}
public static void dumpState(Consumer<String> printer, boolean glsm) {
for (int i = 0; i < instance.propertyList.length; ++i) {
final GLproperty gLProperty = instance.propertyList[i];
printer.accept(gLProperty.name + ":" + gLProperty.getAsString(glsm) + " (" + gLProperty.description + ")");
}
}
public static void dumpIsEnabledToFile(boolean glsm) {
dumpToFile(p -> dumpIsEnabled(p, glsm), (glsm ? "glsm" : "gl") + "-dump-enabled.txt");
}
public static void dumpIsEnabled(boolean glsm) {
dumpIsEnabled(LINE_LOGGER, glsm);
}
public static void dumpIsEnabled(Consumer<String> printer, boolean glsm) {
for (int i = 0; i < instance.propertyList.length; ++i) {
final GLproperty gLProperty = instance.propertyList[i];
if (gLProperty.fetchCommand.equals(GL_IS_ENABLED)) {
printer.accept(gLProperty.name + ":");
printer.accept("" + gLProperty.getAsString(glsm));
printer.accept(" (" + gLProperty.description + ")");
}
}
}
public static void dumpTypeToFile(String type, boolean glsm) {
dumpToFile(p -> dumpType(type, p, glsm), (glsm ? "glsm" : "gl") + "-dump-type-" + type + ".txt");
}
public static void dumpType(String type, boolean glsm) {
dumpType(type, LINE_LOGGER, glsm);
}
public static void dumpType(String type, Consumer<String> printer, boolean glsm) {
for (int i = 0; i < instance.propertyList.length; ++i) {
final GLproperty gLProperty = instance.propertyList[i];
if (gLProperty.category.equals(type)) {
printer.accept(gLProperty.name + ":");
printer.accept(gLProperty.getAsString(glsm));
printer.accept(" (" + gLProperty.description + ")");
}
}
}
public static String getGLSMErrorLog() {
return getGLSMErrorLog(null, false, false);
}
// Re-entrancy guard - getGLSMErrorLog calls glActiveTexture which could trigger checkGLSMOnce
private static boolean inCheck = false;
/**
* Enhanced GLSM error logging with context, stack trace, and first-occurrence filtering.
*
* @param context Optional context string to include in error messages (e.g., "During rendering")
* @param logStacktrace If true, includes the current stack trace in the error output
* @param onlyFirstOccurrence If true, only logs each unique error once
* @return Error log string if mismatches found, null otherwise
*/
public static String getGLSMErrorLog(String context, boolean logStacktrace, boolean onlyFirstOccurrence) {
if (inCheck) return null;
if (!GLStateManager.isCachingEnabled() || GLStateManager.isRecordingDisplayList()) {
return null;
}
inCheck = true;
try {
String group = "checkGLSM" + (context == null ? "" : " " + context);
GLDebug.pushGroup(group);
final StringBuilder error = new StringBuilder();
boolean mismatch = false;
if (context != null && !context.isEmpty()) {
error.append("[").append(context).append("] ");
}
for (int i = 0; i < instance.propertyList.length; ++i) {
final GLproperty gLProperty = instance.propertyList[i];
if (gLProperty.fetchCommand.equals(GL_GET_FLOATV) && gLProperty.name.endsWith("_MATRIX")) {
final Matrix4f cached = gLProperty.getAsMatrix4f(true);
final Matrix4f uncached = gLProperty.getAsMatrix4f(false);
// Skip comparison if either matrix is degenerate (contains NaN/Infinity) these represent invalid GL state from bad parameters, not cache bugs
if (isMatrixDegenerate(cached) || isMatrixDegenerate(uncached)) continue;
if (!matricesEquivalent(cached, uncached, 0.001f)) {
final String errorKey = "MATRIX:" + gLProperty.name;
if (!onlyFirstOccurrence || seenErrors.add(errorKey)) {
final String errorMsg = "GLSM mismatch: " + gLProperty.name + "\ncached:\n" + cached + "uncached:\n" + uncached;
LOGGER.error(errorMsg);
error.append(errorMsg).append('\n');
mismatch = true;
}
}
} else {
final String cached = gLProperty.getAsString(true);
final String uncached = gLProperty.getAsString(false);
if (!cached.equals(uncached)) {
final String errorKey = "PROPERTY:" + gLProperty.name + ":" + cached + ":" + uncached;
if (!onlyFirstOccurrence || seenErrors.add(errorKey)) {
error.append("GLSM mismatch: ").append(gLProperty.name).append(" cached: ").append(cached).append(" uncached: ").append(uncached);
error.append('\n');
mismatch = true;
}
}
}
}
final TextureUnitArray textureUnits = GLStateManager.getTextures();
final int currentActiveTexture = GLStateManager.getActiveTextureUnit();
// Check GL_ACTIVE_TEXTURE
final int glActiveUnit = GL11.glGetInteger(GL13.GL_ACTIVE_TEXTURE) - GL13.GL_TEXTURE0;
if (glActiveUnit != currentActiveTexture) {
final String errorKey = "ACTIVE_TEXTURE:" + currentActiveTexture + ":" + glActiveUnit;
if (!onlyFirstOccurrence || seenErrors.add(errorKey)) {
error.append("GLSM mismatch: GL_ACTIVE_TEXTURE cached: ").append(currentActiveTexture)
.append(" uncached: ").append(glActiveUnit).append('\n');
mismatch = true;
}
}
// Check per-unit texture state
for (int i = 0; i < textureUnits.textureMatricies.length; i++) {
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0 + i);
// Check GL_TEXTURE_2D enabled
final boolean cachedEnabled = textureUnits.getTextureUnitStates(i).isEnabled();
final boolean uncachedEnabled = GL11.glIsEnabled(GL11.GL_TEXTURE_2D);
if (cachedEnabled != uncachedEnabled) {
final String errorKey = "TEXTURE_2D:" + i + ":" + cachedEnabled + ":" + uncachedEnabled;
if (!onlyFirstOccurrence || seenErrors.add(errorKey)) {
error.append("GLSM mismatch: GL_TEXTURE_2D cached: ").append(cachedEnabled)
.append(" uncached: ").append(uncachedEnabled)
.append(", texture unit: GL_TEXTURE").append(i).append('\n');
mismatch = true;
}
}
// Check GL_TEXTURE_BINDING_2D
final int cachedBinding = textureUnits.getTextureUnitBindings(i).getBinding();
final int uncachedBinding = GL11.glGetInteger(GL11.GL_TEXTURE_BINDING_2D);
if (cachedBinding != uncachedBinding) {
final String errorKey = "TEXTURE_BINDING_2D:" + i + ":" + cachedBinding + ":" + uncachedBinding;
if (!onlyFirstOccurrence || seenErrors.add(errorKey)) {
error.append("GLSM mismatch: GL_TEXTURE_BINDING_2D cached: ").append(cachedBinding)
.append(" uncached: ").append(uncachedBinding)
.append(", texture unit: GL_TEXTURE").append(i).append('\n');
mismatch = true;
}
}
}
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0 + currentActiveTexture);
// Add stack trace if requested
if (mismatch && logStacktrace) {
error.append("\nStack trace:\n");
final StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
for (int i = 2; i < stackTrace.length; i++) {
error.append(" at ").append(stackTrace[i].toString()).append('\n');
}
}
GLDebug.popGroup();
return mismatch ? error.toString() : null;
} finally {
inCheck = false;
}
}
public static boolean checkGLSMOnce(String context) {
final String output = getGLSMErrorLog(context, true, true);
if (output != null) {
// Only log on actual mismatch
LOGGER.error("[{}] MISMATCH thread={}\n{}", context, Thread.currentThread().getName(), output);
return false;
}
return true;
}
/**
* Check if a matrix contains any non-finite values (NaN or Infinity).
* Such matrices represent invalid/degenerate GL state (e.g., zero near/far in projection).
*/
private static boolean isMatrixDegenerate(Matrix4f matrix) {
for (int col = 0; col < 4; col++) {
for (int row = 0; row < 4; row++) {
if (!Float.isFinite(matrix.get(col, row))) {
return true;
}
}
}
return false;
}
/**
* Compare two matrices with tolerance for NaN/Infinity.
* Treats NaN == NaN and Infinity == Infinity as equal (both are degenerate states).
* For finite values, uses epsilon comparison.
*/
private static boolean matricesEquivalent(Matrix4f a, Matrix4f b, float epsilon) {
// Compare all 16 elements
for (int col = 0; col < 4; col++) {
for (int row = 0; row < 4; row++) {
final float aVal = a.get(col, row);
final float bVal = b.get(col, row);
// If both are non-finite (NaN or Infinity), consider them equal
if (!Float.isFinite(aVal) && !Float.isFinite(bVal)) {
// Both non-finite: check if both NaN or both same Infinity
if (Float.isNaN(aVal) && Float.isNaN(bVal)) continue;
if (Float.isInfinite(aVal) && Float.isInfinite(bVal)) {
// Check same sign of infinity
if ((aVal > 0) == (bVal > 0)) continue;
}
return false; // Different non-finite values
}
// If one is finite and other is not, they differ
if (Float.isFinite(aVal) != Float.isFinite(bVal)) {
return false;
}
// Both finite: use epsilon comparison
if (Math.abs(aVal - bVal) > epsilon) {
return false;
}
}
}
return true;
}
public static void checkGLSM() {
final String output = getGLSMErrorLog();
if (output == null) {
LOGGER.info("GLSM state matches!");
} else {
LOGGER.error(output);
}
}
public static void copyTexture(ResourceLocation resource, File output) {
final Object object = Minecraft.getMinecraft().renderEngine.mapTextureObjects.get(resource);
if (object != null) {
copyTexture(((ITextureObject) object).getGlTextureId(), output);
}
}
public static void copyTexture(int textureID, File output) {
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, textureID);
int width = GL11.glGetTexLevelParameteri(GL11.GL_TEXTURE_2D, 0, GL11.GL_TEXTURE_WIDTH);
int height = GL11.glGetTexLevelParameteri(GL11.GL_TEXTURE_2D, 0, GL11.GL_TEXTURE_HEIGHT);
BufferedImage bufferedimage = new BufferedImage(width, height, 1);
final int[] pixelValues = ((DataBufferInt) bufferedimage.getRaster().getDataBuffer()).getData();
IntBuffer pixelBuffer = BufferUtils.createIntBuffer(pixelValues.length);
GL11.glGetTexImage(GL11.GL_TEXTURE_2D, 0, GL12.GL_BGRA, GL12.GL_UNSIGNED_INT_8_8_8_8_REV, pixelBuffer);
pixelBuffer.get(pixelValues);
// Flip texture
final int halfHeight = height / 2;
final int[] rowBuffer = new int[width];
for (int y = 0; y < halfHeight; y++) {
final int top = y * width;
final int bottom = (height - 1 - y) * width;
System.arraycopy(pixelValues, top, rowBuffer, 0, width);
System.arraycopy(pixelValues, bottom, pixelValues, top, width);
System.arraycopy(rowBuffer, 0, pixelValues, bottom, width);
}
File dir = output.getParentFile();
dir.mkdirs();
copyBufferedImageToFile(bufferedimage, output);
bufferedimage.flush();
}
private static void copyBufferedImageToFile(BufferedImage image, File file) {
try {
ImageIO.write(image, "png", file);
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -5,8 +5,6 @@ import com.mitchej123.glsm.RenderSystemService;
import org.joml.Matrix4f;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL20;
import java.nio.FloatBuffer;
public class AngelicaRenderSystemService implements RenderSystemService {
@@ -115,17 +113,17 @@ public class AngelicaRenderSystemService implements RenderSystemService {
@Override
public void glUniform1i(int location, int value) {
GL20.glUniform1i(location, value);
GLStateManager.glUniform1i(location, value);
}
@Override
public void glUniformMatrix3(int location, boolean transpose, FloatBuffer value) {
GL20.glUniformMatrix3(location, transpose, value);
GLStateManager.glUniformMatrix3(location, transpose, value);
}
@Override
public void glUniformMatrix4(int location, boolean transpose, FloatBuffer value) {
GL20.glUniformMatrix4(location, transpose, value);
GLStateManager.glUniformMatrix4(location, transpose, value);
}
// ===================== THREAD ASSERTIONS =====================
@@ -99,10 +99,14 @@ public class DeferredDrawBatcher {
totalBytes += e.byteLength();
totalVertices += e.vertexCount();
subEnd++;
// Don't try to merge strips, fans, loops or polygons
if (drawMode == GL11.GL_TRIANGLE_STRIP || drawMode == GL11.GL_TRIANGLE_FAN || drawMode == GL11.GL_LINE_STRIP ||
drawMode == GL11.GL_LINE_LOOP || drawMode == GL11.GL_QUAD_STRIP || drawMode == GL11.GL_POLYGON)
break;
}
TessellatorStreamingDrawer.drawPackedBatch(
batchTessellator, ranges, i, subEnd, totalBytes, totalVertices, drawMode, flags);
TessellatorStreamingDrawer.drawPackedBatch(batchTessellator, ranges, i, subEnd, totalBytes, totalVertices, drawMode, flags);
i = subEnd;
}
@@ -224,6 +224,13 @@ public class AngelicaConfig {
})
public static String[] blockCrackFixRenderPassWhitelist__;
@Config.Comment({"List of sprites which should always be treated as translucent.",
"Sprites added to this list will always be considered translucent,",
"",
"Requires texture reload (F3+T) to take effect."})
@Config.DefaultStringList({"jewelrycraft2:blockCrystal"})
public static String[] alwaysTranslucentSprites;
@Config.Comment("Register HardcodedCustomUniforms in Iris Shaders. May help with compatibility in certain shader packs")
@Config.DefaultBoolean(false)
public static boolean enableHardcodedCustomUniforms;
@@ -232,6 +239,31 @@ public class AngelicaConfig {
@Config.DefaultBoolean(true)
public static boolean defineIsIris;
@Config.Comment("ASM transformer exclusion narrowing for mod compatibility. Disable per-mod if narrowing causes class loading issues.")
public static TransformerCompat transformerCompat = new TransformerCompat();
public static class TransformerCompat {
@Config.Comment("Narrow DragonAPI transformer exclusions to allow GL redirection")
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public boolean narrowDragonAPI;
@Config.Comment("Narrow Xaeros Minimap/Worldmap transformer exclusions to allow GL redirection")
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public boolean narrowXaeros;
@Config.Comment("Narrow AdvancedLightsabers transformer exclusions to allow GL redirection")
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public boolean narrowAdvancedLightsabers;
@Config.Comment("Narrow Alfheim transformer exclusions to allow GL redirection")
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public boolean narrowAlfheim;
}
@Config.Comment("Renders chunks before neighbors are ready. Improves loading at render distance edges, useful for low render distance servers.")
@Config.DefaultBoolean(false)
public static boolean useVanillaChunkTracking;
@@ -25,6 +25,7 @@ import net.minecraft.client.renderer.EntityRenderer;
import net.minecraftforge.client.GuiIngameForge;
import net.minecraftforge.client.event.RenderGameOverlayEvent;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL13;
import thaumcraft.common.Thaumcraft;
import xaero.common.core.XaeroMinimapCore;
@@ -69,6 +70,12 @@ public class HUDCaching {
XaeroMinimapCore.beforeIngameGuiRender(partialTicks);
}
GLStateManager.disableLighting();
GLStateManager.glActiveTexture(GL13.GL_TEXTURE1);
GLStateManager.disableTexture();
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0);
GLStateManager.enableTexture();
if (!AngelicaConfig.hudCachingActive || !GLStateManager.isFramebufferEnabled()) {
ingame.renderGameOverlay(partialTicks, hasScreen, mouseX, mouseY);
return;
@@ -117,7 +117,7 @@ public class IrisGLSMBridge {
if (DepthColorStorage.isOwnedProgram(event.newProgram)) {
DepthColorStorage.unlockDepthColor();
} else {
DepthColorStorage.disableDepthColor();
drp.onModProgramOverride();
}
});
}
@@ -135,12 +135,23 @@ public class AngelicaTweaker implements IFMLLoadingPlugin, IEarlyMixinLoader {
return null;
}
/** Publish a transformer-narrowing toggle to the blackboard; read by AngelicaLateTweaker.narrowEnabled(). */
private static void narrowTransformerConfig(String mod, boolean enabled) {
Launch.blackboard.put("angelica.narrow." + mod, enabled);
}
@Override
public void injectData(Map<String, Object> data) {
OBF_ENV = (Boolean) data.get("runtimeDeobfuscationEnabled");
// Directly add this to the MixinServiceLaunchWrapper tweaker's list of Tweak Classes
final List<String> tweaks = GlobalProperties.get(MixinServiceLaunchWrapper.BLACKBOARD_KEY_TWEAKCLASSES);
if (tweaks != null) {
// Bridge transformer compat config to blackboard for AngelicaLateTweaker
narrowTransformerConfig("DragonAPI", AngelicaConfig.transformerCompat.narrowDragonAPI);
narrowTransformerConfig("Xaeros", AngelicaConfig.transformerCompat.narrowXaeros);
narrowTransformerConfig("AdvancedLightsabers", AngelicaConfig.transformerCompat.narrowAdvancedLightsabers);
narrowTransformerConfig("Alfheim", AngelicaConfig.transformerCompat.narrowAlfheim);
tweaks.add("com.gtnewhorizons.angelica.loading.fml.tweakers.IncompatibleModsDisablerTweaker");
if (AngelicaConfig.enableHudCaching) {
tweaks.add("com.gtnewhorizons.angelica.loading.fml.tweakers.XaerosTransformerDisablerTweaker");
@@ -37,10 +37,8 @@ public class AngelicaLateTweaker implements ITweaker {
exceptionsField.setAccessible(true);
final Set<String> exceptions = (Set<String>) exceptionsField.get(classLoader);
if (exceptions.remove("Reika.DragonAPI.ASM")) {
// Don't read ASMCallsClient and Patchers/Fixes/WorldRenderAlpha. The rest are fair game.
// Re-add the other non utility classes
if (narrowEnabled("DragonAPI") && exceptions.remove("Reika.DragonAPI.ASM")) {
// Re-add non-GL classes; ASMCallsClient and utility classes with GL calls are left exposed
exceptions.add("Reika.DragonAPI.ASM.Patchers");
exceptions.add("Reika.DragonAPI.ASM.Profiling");
exceptions.add("Reika.DragonAPI.ASM.APIStripper");
@@ -52,22 +50,60 @@ public class AngelicaLateTweaker implements ITweaker {
exceptions.add("Reika.DragonAPI.ASM.InterfaceInjector");
exceptions.add("Reika.DragonAPI.ASM.SpecialBiomePlacement");
exceptions.add("Reika.DragonAPI.ASM.StructureLootHooks");
FMLRelaunchLog.info("[Angelica] Narrowed Reika.DragonAPI.ASM transformer exclusion to allow GL redirection of utility classes");
FMLRelaunchLog.info("[Angelica] Narrowed Reika.DragonAPI.ASM transformer exclusion to allow GL redirection");
}
if (exceptions.remove("xaero.common.core")) {
exceptions.add("xaero.common.core.transformer");
FMLRelaunchLog.info("[Angelica] Narrowed xaero.common.core transformer exclusion to allow GL redirection");
if (narrowEnabled("Xaeros")) {
if (exceptions.remove("xaero.common.core")) {
exceptions.add("xaero.common.core.transformer");
FMLRelaunchLog.info("[Angelica] Narrowed xaero.common.core transformer exclusion to allow GL redirection");
}
if (exceptions.remove("xaero.map.core")) {
exceptions.add("xaero.map.core.transformer");
FMLRelaunchLog.info("[Angelica] Narrowed xaero.map.core transformer exclusion to allow GL redirection");
}
}
if (exceptions.remove("xaero.map.core")) {
exceptions.add("xaero.map.core.transformer");
FMLRelaunchLog.info("[Angelica] Narrowed xaero.map.core transformer exclusion to allow GL redirection");
if (narrowEnabled("AdvancedLightsabers") && exceptions.remove("com.fiskmods.lightsabers.asm")) {
exceptions.add("com.fiskmods.lightsabers.asm.ALLoadingPlugin");
exceptions.add("com.fiskmods.lightsabers.asm.ASMHooks");
exceptions.add("com.fiskmods.lightsabers.asm.transformers");
FMLRelaunchLog.info("[Angelica] Narrowed com.fiskmods.lightsabers.asm transformer exclusion to allow GL redirection");
}
if (narrowEnabled("Alfheim") && exceptions.remove("alfheim.common.core.asm.hook")) {
exceptions.add("alfheim.common.core.asm.hook.AlfheimFieldHookHandler");
exceptions.add("alfheim.common.core.asm.hook.AlfheimHPHooks");
exceptions.add("alfheim.common.core.asm.hook.Botania18AndUpBackport");
exceptions.add("alfheim.common.core.asm.hook.ElementalDamageAdapter");
exceptions.add("alfheim.common.core.asm.hook.integration");
exceptions.add("alfheim.common.core.asm.hook.extender.FurnaceExtender");
exceptions.add("alfheim.common.core.asm.hook.extender.ItemAuraRingExtender");
exceptions.add("alfheim.common.core.asm.hook.extender.ItemLensExtender");
exceptions.add("alfheim.common.core.asm.hook.extender.ItemTwigWandExtender");
exceptions.add("alfheim.common.core.asm.hook.extender.LightRelayExtender");
exceptions.add("alfheim.common.core.asm.hook.extender.PureDaisyExtender");
exceptions.add("alfheim.common.core.asm.hook.extender.QuartzExtender");
exceptions.add("alfheim.common.core.asm.hook.extender.RelicHooks");
exceptions.add("alfheim.common.core.asm.hook.extender.SparkExtender");
exceptions.add("alfheim.common.core.asm.hook.fixes.BotaniaGlowingRenderFixes");
exceptions.add("alfheim.common.core.asm.hook.fixes.CorporeaInputFix");
exceptions.add("alfheim.common.core.asm.hook.fixes.GodAttributesHooks");
exceptions.add("alfheim.common.core.asm.hook.fixes.RecipeAncientWillsFix");
FMLRelaunchLog.info("[Angelica] Narrowed alfheim.common.core.asm.hook transformer exclusion to allow GL redirection");
}
} catch (Exception e) {
FMLRelaunchLog.warning("[Angelica] Failed to narrow transformer exclusions: %s", e.getMessage());
}
}
private static boolean narrowEnabled(String mod) {
return !Boolean.FALSE.equals(Launch.blackboard.get("angelica.narrow." + mod));
}
@Override
public String getLaunchTarget() {
return null;
@@ -36,6 +36,7 @@ public enum Mixins implements IMixins {
, "angelica.MixinMinecraft"
, "angelica.MixinMinecraft_FrameHook"
, "angelica.MixinMinecraftServer"
, "angelica.bugfixes.MixinItemRenderer_EdgeDepth"
, "angelica.bugfixes.MixinRenderGlobal_DestroyBlock"
, "angelica.bugfixes.MixinRendererLivingEntity_EyeDepth"
, "angelica.debug.MixinMinecraft_FPSCap"
@@ -14,7 +14,6 @@ import com.gtnewhorizons.angelica.debug.TPSGraph;
import com.gtnewhorizons.angelica.dynamiclights.DynamicLights;
import com.gtnewhorizons.angelica.dynamiclights.config.EntityLightConfig;
import com.gtnewhorizons.angelica.glsm.GLStateManager;
import com.gtnewhorizons.angelica.client.debug.OpenGLDebugging;
import com.gtnewhorizons.angelica.hudcaching.HUDCaching;
import com.gtnewhorizons.angelica.iris.IrisGLSMBridge;
import com.gtnewhorizons.angelica.loading.AngelicaTweaker;
@@ -27,7 +26,6 @@ import com.gtnewhorizons.angelica.rendering.celeritas.threading.ChunkTaskRegistr
import com.gtnewhorizons.angelica.rendering.celeritas.threading.DefaultChunkTaskProvider;
import com.gtnewhorizons.angelica.rendering.celeritas.threading.ThreadedChunkTaskProvider;
import com.gtnewhorizons.angelica.zoom.Zoom;
import cpw.mods.fml.client.registry.ClientRegistry;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
@@ -53,8 +51,6 @@ import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.GuiVideoSettings;
import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.network.NetHandlerPlayClient;
import net.minecraft.client.settings.GameSettings;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.server.integrated.IntegratedServer;
import net.minecraft.util.Direction;
import net.minecraft.util.MathHelper;
@@ -114,8 +110,6 @@ public class ClientProxy extends CommonProxy {
}
}
private static KeyBinding glsmKeyBinding;
@Override
public void init(FMLInitializationEvent event) {
super.init(event);
@@ -144,8 +138,6 @@ public class ClientProxy extends CommonProxy {
FMLCommonHandler.instance().bus().register(this);
MinecraftForge.EVENT_BUS.register(this);
glsmKeyBinding = new KeyBinding("Print GLSM Debug", Keyboard.KEY_NONE, "Angelica");
ClientRegistry.registerKeyBinding(glsmKeyBinding);
if (ModStatus.isBetterCrashesLoaded) {
BetterCrashesCompat.init();
@@ -163,18 +155,6 @@ public class ClientProxy extends CommonProxy {
}
}
private boolean wasGLSMKeyPressed;
@SubscribeEvent
public void onKeypress(TickEvent.ClientTickEvent event) {
if (event.phase != TickEvent.Phase.END) return;
final boolean isPressed = glsmKeyBinding.getKeyCode() != 0 && GameSettings.isKeyDown(glsmKeyBinding);
if (isPressed && !wasGLSMKeyPressed) {
OpenGLDebugging.checkGLSM();
}
wasGLSMKeyPressed = isPressed;
}
@Override
public void postInit(FMLPostInitializationEvent event) {
@@ -56,16 +56,19 @@ final class Enchantment extends OverrideBase {
GLStateManager.glEnable(GL11.GL_ALPHA_TEST);
GLStateManager.glAlphaFunc(GL11.GL_GREATER, 0.01f);
GLStateManager.glEnable(GL11.GL_BLEND);
GLStateManager.glDepthFunc(GL11.GL_EQUAL);
lightingWasEnabled = GLStateManager.glGetBoolean(GL11.GL_LIGHTING);
GLStateManager.glDisable(GL11.GL_LIGHTING);
GLStateManager.glMatrixMode(GL11.GL_TEXTURE);
GLStateManager.glStencilFunc(GL11.GL_EQUAL, 1, 0xFF);
GLStateManager.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP);
}
static void endOuter3D() {
GLStateManager.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
GLStateManager.glDisable(GL11.GL_BLEND);
GLStateManager.glDepthFunc(GL11.GL_LEQUAL);
GLStateManager.glDepthMask(true);
GLStateManager.glDisable(GL11.GL_STENCIL_TEST);
if (lightingWasEnabled) {
GLStateManager.glEnable(GL11.GL_LIGHTING);
}
@@ -139,6 +142,17 @@ final class Enchantment extends OverrideBase {
return;
}
begin(intensity);
// Depth pre-pass
GLStateManager.glColorMask(false, false, false, false);
GLStateManager.glDepthMask(true);
GLStateManager.glDepthFunc(GL11.GL_LEQUAL);
ItemRenderer.renderItemIn2D(Tessellator.instance, 1.0f, 0.0f, 0.0f, 1.0f, width, height, ITEM_2D_THICKNESS);
// Color pass
GLStateManager.glColorMask(true, true, true, true);
GLStateManager.glDepthMask(false);
GLStateManager.glDepthFunc(GL11.GL_EQUAL);
ItemRenderer.renderItemIn2D(Tessellator.instance, 1.0f, 0.0f, 0.0f, 1.0f, width, height, ITEM_2D_THICKNESS);
end();
}
@@ -26,7 +26,6 @@ import org.lwjgl.opengl.EXTFramebufferObject;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12;
import org.lwjgl.opengl.GL13;
import org.lwjgl.opengl.GLContext;
import org.lwjgl.util.glu.GLU;
import com.gtnewhorizons.angelica.glsm.GLStateManager;
@@ -47,8 +46,8 @@ public class FancyDial {
private static final double ANGLE_UNSET = Double.MAX_VALUE;
private static final int NUM_SCRATCH_TEXTURES = 3;
private static final boolean fboSupported = GLContext.getCapabilities().GL_EXT_framebuffer_object;
private static final boolean gl13Supported = GLContext.getCapabilities().OpenGL13;
private static final boolean fboSupported = GLStateManager.capabilities.GL_EXT_framebuffer_object;
private static final boolean gl13Supported = GLStateManager.capabilities.OpenGL13;
private static final boolean enableCompass = MCPatcherForgeConfig.ExtendedHD.fancyCompass;
private static final boolean enableClock = MCPatcherForgeConfig.ExtendedHD.fancyClock;
private static final boolean useGL13 = gl13Supported && MCPatcherForgeConfig.ExtendedHD.useGL13;
@@ -148,7 +147,7 @@ public class FancyDial {
FancyDial instance = getInstance(icon);
return instance != null && instance.render(itemFrameRenderer);
} finally {
EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, oldFB);
GLStateManager.glBindFramebuffer(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, oldFB);
GLAPI.glBindTexture(oldTexture);
}
}
@@ -603,13 +602,13 @@ public class FancyDial {
this.width = width;
this.height = height;
frameBuffer = EXTFramebufferObject.glGenFramebuffersEXT();
frameBuffer = GLStateManager.glGenFramebuffers();
if (frameBuffer < 0) {
throw new RuntimeException("could not get framebuffer object");
}
GLAPI.glBindTexture(texture);
EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, frameBuffer);
EXTFramebufferObject.glFramebufferTexture2DEXT(
GLStateManager.glBindFramebuffer(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, frameBuffer);
GLStateManager.glFramebufferTexture2D(
EXTFramebufferObject.GL_FRAMEBUFFER_EXT,
EXTFramebufferObject.GL_COLOR_ATTACHMENT0_EXT,
GL11.GL_TEXTURE_2D,
@@ -618,7 +617,7 @@ public class FancyDial {
}
void bind() {
EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, frameBuffer);
GLStateManager.glBindFramebuffer(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, frameBuffer);
GLStateManager.glPushAttrib(glAttributes);
GLStateManager.glViewport(x0, y0, width, height);
@@ -674,11 +673,11 @@ public class FancyDial {
GLStateManager.glEnable(GL11.GL_BLEND);
GLAPI.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO);
EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, 0);
GLStateManager.glBindFramebuffer(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, 0);
}
void read(ByteBuffer buffer) {
EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, frameBuffer);
GLStateManager.glBindFramebuffer(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, frameBuffer);
buffer.position(0);
GLStateManager.glReadPixels(x0, y0, width, height, MipmapHelper.TEX_FORMAT, MipmapHelper.TEX_DATA_TYPE, buffer);
}
@@ -704,7 +703,7 @@ public class FancyDial {
if (ownTexture) {
GLStateManager.glDeleteTextures(texture);
}
EXTFramebufferObject.glDeleteFramebuffersEXT(frameBuffer);
GLStateManager.glDeleteFramebuffers(frameBuffer);
}
}
@@ -11,7 +11,6 @@ import org.lwjgl.opengl.EXTTextureFilterAnisotropic;
import org.lwjgl.opengl.EXTTextureLODBias;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12;
import org.lwjgl.opengl.GLContext;
import org.lwjgl.util.glu.GLU;
import com.gtnewhorizons.angelica.glsm.GLStateManager;
@@ -47,10 +46,10 @@ public class MipmapHelper {
private static final Map<String, Boolean> mipmapType = new HashMap<>();
static {
mipmapSupported = GLContext.getCapabilities().OpenGL12;
mipmapSupported = GLStateManager.capabilities.OpenGL12;
useMipmap = mipmapSupported && mipmapEnabled && maxMipmapLevel > 0;
anisoSupported = GLContext.getCapabilities().GL_EXT_texture_filter_anisotropic;
anisoSupported = GLStateManager.capabilities.GL_EXT_texture_filter_anisotropic;
if (anisoSupported) {
anisoMax = (int) GLStateManager.glGetFloat(EXTTextureFilterAnisotropic.GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT);
checkGLError("glGetFloat(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT)");
@@ -59,7 +58,7 @@ public class MipmapHelper {
anisoMax = anisoLevel = 1;
}
lodSupported = GLContext.getCapabilities().GL_EXT_texture_lod_bias;
lodSupported = GLStateManager.capabilities.GL_EXT_texture_lod_bias;
if (lodSupported) {
lodBias = MCPatcherForgeConfig.ExtendedHD.lodBias;
} else {
@@ -1,13 +1,11 @@
package com.prupe.mcpatcher.mal.resource;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GLContext;
import com.gtnewhorizons.angelica.glsm.GLStateManager;
public class GLAPI {
private static final boolean useGlBlendFuncSeparate = GLContext.getCapabilities().OpenGL14;
private static final boolean useGlBlendFuncSeparate = GLStateManager.capabilities.OpenGL14;
public static void glBindTexture(int texture) {
if (texture >= 0) {
@@ -8,6 +8,7 @@ public enum RenderCondition {
CLOUDS,
DESTROY,
BLOCK_ENTITIES,
BLOCK_ENTITIES_TRANSLUCENT,
BEACON_BEAM,
ENTITIES,
ENTITIES_TRANSLUCENT,
@@ -2,6 +2,7 @@ package net.coderbot.iris.gl.program;
import com.google.common.collect.ImmutableList;
import com.gtnewhorizons.angelica.config.AngelicaConfig;
import com.gtnewhorizons.angelica.glsm.GLStateManager;
import com.gtnewhorizons.angelica.glsm.RenderSystem;
import java.nio.IntBuffer;
import java.util.ArrayList;
@@ -189,7 +190,7 @@ public class ProgramUniforms {
public ProgramUniforms buildUniforms() {
// Check for any unsupported uniforms and warn about them so that we can easily figure out what uniforms we need to add.
final int activeUniforms = GL20.glGetProgrami(program, GL20.GL_ACTIVE_UNIFORMS);
final int activeUniforms = GLStateManager.glGetProgrami(program, GL20.GL_ACTIVE_UNIFORMS);
IntBuffer sizeType = BufferUtils.createIntBuffer(2);
for (int index = 0; index < activeUniforms; index++) {
@@ -8,6 +8,7 @@ import net.coderbot.iris.shaderpack.option.OptionSet;
import net.coderbot.iris.shaderpack.option.Profile;
import net.coderbot.iris.shaderpack.option.ProfileSet;
import net.coderbot.iris.shaderpack.option.menu.OptionMenuProfileElement;
import net.coderbot.iris.shaderpack.option.menu.ProfileElementTracker;
import net.coderbot.iris.shaderpack.option.values.OptionValues;
import net.minecraft.client.Minecraft;
import net.minecraft.client.resources.I18n;
@@ -30,6 +31,7 @@ public class ProfileElementWidget extends BaseOptionElementWidget<OptionMenuProf
public void init(ShaderPackScreen screen, NavigationController navigation) {
super.init(screen, navigation);
this.setLabel(PROFILE_LABEL);
boolean secondProfileSet = ProfileElementTracker.isSecondProfileSet(this.element);
final ProfileSet profiles = this.element.profiles;
final OptionSet options = this.element.options;
@@ -41,7 +43,8 @@ public class ProfileElementWidget extends BaseOptionElementWidget<OptionMenuProf
this.previous = result.previous;
final Optional<String> profileName = result.current.map(p -> p.name);
this.profileLabel = profileName.map(name -> GuiUtil.translateOrDefault(name, "profile." + name)).orElse(PROFILE_CUSTOM);
String translationKey = "profile" + (secondProfileSet ? "2." : ".") + profileName.orElse("custom");
this.profileLabel = profileName.map(name -> GuiUtil.translateOrDefault(name, translationKey)).orElse(PROFILE_CUSTOM);
}
@Override
@@ -63,7 +66,7 @@ public class ProfileElementWidget extends BaseOptionElementWidget<OptionMenuProf
@Override
public String getCommentKey() {
return "profile.comment";
return ProfileElementTracker.isSecondProfileSet(this.element) ? "profile2.comment" : "profile.comment";
}
@Override
@@ -45,6 +45,7 @@ import net.coderbot.iris.postprocess.BufferFlipper;
import net.coderbot.iris.postprocess.CenterDepthSampler;
import net.coderbot.iris.postprocess.CompositeRenderer;
import net.coderbot.iris.postprocess.FinalPassRenderer;
import net.coderbot.iris.postprocess.FullScreenQuadRenderer;
import net.coderbot.iris.postprocess.ProgramBuildContext;
import net.coderbot.iris.rendertarget.IRenderTargetExt;
import net.coderbot.iris.rendertarget.NativeImageBackedSingleColorTexture;
@@ -367,6 +368,7 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R
null, ProgramId.Clouds, ProgramId.Clouds,
null, ProgramId.DamagedBlock, ProgramId.DamagedBlock,
ProgramId.Block, ProgramId.Block, ProgramId.Block,
ProgramId.BlockTrans, ProgramId.BlockTrans, ProgramId.BlockTrans,
ProgramId.BeaconBeam, ProgramId.BeaconBeam, ProgramId.BeaconBeam,
ProgramId.Entities, ProgramId.Entities, ProgramId.Entities,
ProgramId.EntitiesTrans, ProgramId.EntitiesTrans, ProgramId.EntitiesTrans,
@@ -719,6 +721,10 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R
return RenderCondition.ENTITIES;
}
case BLOCK_ENTITIES:
if (GLStateManager.getBlendState().getSrcRgb() == SRC_ALPHA &&
GLStateManager.getBlendState().getDstRgb() == ONE_MINUS_SRC_ALPHA) {
return RenderCondition.BLOCK_ENTITIES_TRANSLUCENT;
}
return RenderCondition.BLOCK_ENTITIES;
case DESTROY:
return RenderCondition.DESTROY;
@@ -749,6 +755,13 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R
return p != null ? p.getProgramId() : -1;
}
/**
* Called when a mod overrides the GL program away from the active Iris pass
*/
public void onModProgramOverride() {
current = null;
}
private void matchPass() {
if (!isRenderingWorld || isRenderingFullScreenPass || isPostChain || !isMainBound) {
return;
@@ -883,7 +896,8 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R
builder.bindAttributeLocation(13, "at_tangent");
builder.bindAttributeLocation(14, "at_midBlock");
AlphaTestOverride alphaTestOverride = programDirectives.getAlphaTestOverride().orElse(null);
AlphaTestOverride alphaTestOverride = programDirectives.getAlphaTestOverride()
.orElse(id.getDefaultAlphaTestOverride());
List<BufferBlendOverride> bufferOverrides = new ArrayList<>();
@@ -973,12 +987,8 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R
GLStateManager.glViewport(0, 0, main.framebufferWidth, main.framebufferHeight);
}
if (program != null) {
program.use();
}
DeferredWorldRenderingPipeline.this.customUniforms.push(this);
// Apply state overrides before program.use() so that uniforms (e.g. iris_currentAlphaTest)
// read the correct GLSM state during upload, not the stale vanilla state.
if (alphaTestOverride != null) {
alphaTestOverride.apply();
} else {
@@ -996,6 +1006,12 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R
if (bufferBlendOverrides != null && !bufferBlendOverrides.isEmpty()) {
bufferBlendOverrides.forEach(BufferBlendOverride::apply);
}
if (program != null) {
program.use();
}
DeferredWorldRenderingPipeline.this.customUniforms.push(this);
}
public void stopUsing() {
@@ -1028,6 +1044,7 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R
BlendModeOverride.restore();
AlphaTestOverride.restore();
FullScreenQuadRenderer.clearLocCache();
destroyPasses(table);
// Destroy the composite rendering pipeline
@@ -21,6 +21,7 @@ class CoreTransformHelper {
transformer.injectVariable("uniform mat4 iris_ProjectionMatrixInverse;");
transformer.injectVariable("uniform mat3 iris_NormalMatrix;");
transformer.injectVariable("uniform mat4 iris_LightmapTextureMatrix;");
transformer.injectVariable("uniform mat4 iris_TextureMatrix;");
final Map<String, String> renames = new HashMap<>();
renames.put("gl_ModelViewMatrix", "iris_ModelViewMatrix");
@@ -32,12 +33,12 @@ class CoreTransformHelper {
final Map<String, String> replacements = new HashMap<>();
replacements.put("gl_ModelViewProjectionMatrix", "(iris_ProjectionMatrix * iris_ModelViewMatrix)");
replacements.put("gl_TextureMatrix[0]", "mat4(1.0)");
replacements.put("gl_TextureMatrix[0]", "iris_TextureMatrix");
replacements.put("gl_TextureMatrix[1]", "iris_LightmapTextureMatrix");
replacements.forEach(transformer::replaceExpression);
// Catch any remaining gl_TextureMatrix references (e.g. [2]-[7])
transformer.replaceExpression("gl_TextureMatrix", "mat4[8](mat4(1.0), iris_LightmapTextureMatrix, mat4(1.0), mat4(1.0), mat4(1.0), mat4(1.0), mat4(1.0), mat4(1.0))");
transformer.replaceExpression("gl_TextureMatrix", "mat4[8](iris_TextureMatrix, iris_LightmapTextureMatrix, mat4(1.0), mat4(1.0), mat4(1.0), mat4(1.0), mat4(1.0), mat4(1.0))");
}
/**
@@ -78,6 +78,11 @@ public class FullScreenQuadRenderer {
/** Per-program cached uniform locations: [mvLoc, projLoc]. Populated on first miss. */
private static final Int2ObjectOpenHashMap<int[]> compositeLocCache = new Int2ObjectOpenHashMap<>();
/** Clear cached uniform locations. Must be called when composite programs are destroyed (e.g. shader reload). */
public static void clearLocCache() {
compositeLocCache.clear();
}
public static void uploadCompositeMatrices() {
final int program = GLStateManager.glGetInteger(GL20.GL_CURRENT_PROGRAM);
if (program == 0) return;
@@ -43,6 +43,7 @@ public class ProgramSet {
private final ProgramSource gbuffersGlint;
private final ProgramSource gbuffersEntityEyes;
private final ProgramSource gbuffersBlock;
private final ProgramSource gbuffersBlockTrans;
private final ProgramSource gbuffersHand;
private final ProgramSource[] deferred;
@@ -116,6 +117,7 @@ public class ProgramSet {
this.gbuffersGlint = readProgramSource(directory, sourceProvider, "gbuffers_armor_glint", this, shaderProperties);
this.gbuffersEntityEyes = readProgramSource(directory, sourceProvider, "gbuffers_spidereyes", this, shaderProperties);
this.gbuffersBlock = readProgramSource(directory, sourceProvider, "gbuffers_block", this, shaderProperties);
this.gbuffersBlockTrans = readProgramSource(directory, sourceProvider, "gbuffers_block_translucent", this, shaderProperties);
this.gbuffersHand = readProgramSource(directory, sourceProvider, "gbuffers_hand", this, shaderProperties);
this.deferred = readProgramArray(directory, sourceProvider, "deferred", shaderProperties);
@@ -216,7 +218,7 @@ public class ProgramSet {
programs.addAll (Arrays.asList(
gbuffersBasic, gbuffersBeaconBeam, gbuffersTextured, gbuffersTexturedLit, gbuffersTerrain,
gbuffersDamagedBlock, gbuffersSkyBasic, gbuffersSkyTextured, gbuffersClouds, gbuffersWeather,
gbuffersEntities, gbuffersEntitiesTrans, gbuffersEntitiesGlowing, gbuffersGlint, gbuffersEntityEyes, gbuffersBlock,
gbuffersEntities, gbuffersEntitiesTrans, gbuffersEntitiesGlowing, gbuffersGlint, gbuffersEntityEyes, gbuffersBlock, gbuffersBlockTrans,
gbuffersHand
));
@@ -377,6 +379,10 @@ public class ProgramSet {
return gbuffersBlock.requireValid();
}
public Optional<ProgramSource> getGbuffersBlockTrans() {
return gbuffersBlockTrans.requireValid();
}
public Optional<ProgramSource> getGbuffersHand() {
return gbuffersHand.requireValid();
}
@@ -394,6 +400,7 @@ public class ProgramSet {
case Terrain -> getGbuffersTerrain();
case DamagedBlock -> getGbuffersDamagedBlock();
case Block -> getGbuffersBlock();
case BlockTrans -> getGbuffersBlockTrans();
case BeaconBeam -> getGbuffersBeaconBeam();
case Entities -> getGbuffersEntities();
case EntitiesTrans -> getGbuffersEntitiesTrans();
@@ -97,6 +97,7 @@ public class ShaderProperties {
@Getter private OptionalBoolean prepareBeforeShadow = OptionalBoolean.DEFAULT;
@Getter private List<String> sliderOptions = new ArrayList<>();
@Getter private final Map<String, List<String>> profiles = new LinkedHashMap<>();
@Getter private final Map<String, List<String>> profiles2 = new LinkedHashMap<>();
private List<String> mainScreenOptions = null;
@Getter private final Map<String, List<String>> subScreenOptions = new HashMap<>();
private Integer mainScreenColumnCount = null;
@@ -517,6 +518,7 @@ public class ShaderProperties {
// the last definition being used, should be tested if behavior matches OptiFine
handleWhitespacedListDirective(key, value, "sliders", sliders -> sliderOptions = sliders);
handlePrefixedWhitespacedListDirective("profile.", key, value, profiles::put);
handlePrefixedWhitespacedListDirective("profile2.", key, value, profiles2::put);
if (handleIntDirective(key, value, "screen.columns", columns -> mainScreenColumnCount = columns)) {
return;
@@ -1,6 +1,11 @@
package net.coderbot.iris.shaderpack.loading;
import com.gtnewhorizons.angelica.glsm.states.BlendState;
import net.coderbot.iris.gl.blending.AlphaTest;
import net.coderbot.iris.gl.blending.AlphaTestFunction;
import net.coderbot.iris.gl.blending.AlphaTestOverride;
import net.coderbot.iris.gl.blending.BlendModeOverride;
import org.lwjgl.opengl.GL11;
import java.util.Objects;
import java.util.Optional;
@@ -26,6 +31,7 @@ public enum ProgramId {
DamagedBlock(ProgramGroup.Gbuffers, "damagedblock", Terrain),
Block(ProgramGroup.Gbuffers, "block", Terrain),
BlockTrans(ProgramGroup.Gbuffers, "block_translucent", Block, BlendModeOverride.OFF),
BeaconBeam(ProgramGroup.Gbuffers, "beaconbeam", Textured),
Item(ProgramGroup.Gbuffers, "item", TexturedLit),
@@ -33,7 +39,9 @@ public enum ProgramId {
EntitiesTrans(ProgramGroup.Gbuffers, "entities_translucent", Entities),
EntitiesGlowing(ProgramGroup.Gbuffers, "entities_glowing", Entities),
ArmorGlint(ProgramGroup.Gbuffers, "armor_glint", Textured),
SpiderEyes(ProgramGroup.Gbuffers, "spidereyes", Textured),
SpiderEyes(ProgramGroup.Gbuffers, "spidereyes", Textured,
new BlendModeOverride(new BlendState(GL11.GL_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO, GL11.GL_ONE)),
new AlphaTestOverride(new AlphaTest(AlphaTestFunction.GREATER, 0.0001F))),
Hand(ProgramGroup.Gbuffers, "hand", TexturedLit),
Weather(ProgramGroup.Gbuffers, "weather", TexturedLit),
@@ -47,12 +55,14 @@ public enum ProgramId {
private final String sourceName;
private final ProgramId fallback;
private final BlendModeOverride defaultBlendOverride;
private final AlphaTestOverride defaultAlphaTestOverride;
ProgramId(ProgramGroup group, String name) {
this.group = group;
this.sourceName = name.isEmpty() ? group.getBaseName() : group.getBaseName() + "_" + name;
this.fallback = null;
this.defaultBlendOverride = null;
this.defaultAlphaTestOverride = null;
}
ProgramId(ProgramGroup group, String name, ProgramId fallback) {
@@ -60,6 +70,7 @@ public enum ProgramId {
this.sourceName = name.isEmpty() ? group.getBaseName() : group.getBaseName() + "_" + name;
this.fallback = Objects.requireNonNull(fallback);
this.defaultBlendOverride = null;
this.defaultAlphaTestOverride = null;
}
ProgramId(ProgramGroup group, String name, ProgramId fallback, BlendModeOverride defaultBlendOverride) {
@@ -67,6 +78,15 @@ public enum ProgramId {
this.sourceName = name.isEmpty() ? group.getBaseName() : group.getBaseName() + "_" + name;
this.fallback = Objects.requireNonNull(fallback);
this.defaultBlendOverride = defaultBlendOverride;
this.defaultAlphaTestOverride = null;
}
ProgramId(ProgramGroup group, String name, ProgramId fallback, BlendModeOverride defaultBlendOverride, AlphaTestOverride defaultAlphaTestOverride) {
this.group = group;
this.sourceName = name.isEmpty() ? group.getBaseName() : group.getBaseName() + "_" + name;
this.fallback = Objects.requireNonNull(fallback);
this.defaultBlendOverride = defaultBlendOverride;
this.defaultAlphaTestOverride = defaultAlphaTestOverride;
}
public ProgramGroup getGroup() {
@@ -84,4 +104,8 @@ public enum ProgramId {
public BlendModeOverride getBlendModeOverride() {
return defaultBlendOverride;
}
public AlphaTestOverride getDefaultAlphaTestOverride() {
return defaultAlphaTestOverride;
}
}
@@ -1,6 +1,7 @@
package net.coderbot.iris.shaderpack.option.menu;
import com.google.common.collect.Lists;
import lombok.Getter;
import net.coderbot.iris.Iris;
import net.coderbot.iris.shaderpack.ShaderProperties;
import net.coderbot.iris.shaderpack.option.ProfileSet;
@@ -21,10 +22,12 @@ public class OptionMenuContainer {
private final List<String> usedOptions = new ArrayList<>();
private final List<String> unusedOptions = new ArrayList<>(); // To be used when screens contain a "*" element
private final Map<List<OptionMenuElement>, Integer> unusedOptionDumpQueue = new HashMap<>(); // Used by screens with "*" element
private final ProfileSet profiles;
@Getter private final ProfileSet profiles;
@Getter private final ProfileSet profiles2;
public OptionMenuContainer(ShaderProperties shaderProperties, ShaderPackOptions shaderPackOptions, ProfileSet profiles) {
this.profiles = profiles;
this.profiles2 = ProfileSet.fromTree(shaderProperties.getProfiles2(), shaderPackOptions.getOptionSet());
// note: if the Shader Pack does not provide a list of options for the main screen, then dump all options on to
// the main screen by default.
@@ -68,10 +71,6 @@ public class OptionMenuContainer {
}
}
public ProfileSet getProfiles() {
return profiles;
}
// Screens will call this when they contain a "*" element, so that the list of
// unused options can be added after all other screens have been resolved
public void queueForUnusedOptionDump(int index, List<OptionMenuElement> elementList) {
@@ -12,6 +12,7 @@ public abstract class OptionMenuElement {
private static final String ELEMENT_EMPTY = "<empty>";
private static final String ELEMENT_PROFILE = "<profile>";
private static final String ELEMENT_PROFILE2 = "<profile2>";
public static OptionMenuElement create(String elementString, OptionMenuContainer container, ShaderProperties shaderProperties, ShaderPackOptions shaderPackOptions) throws IllegalArgumentException {
// Empty element
@@ -24,6 +25,13 @@ public abstract class OptionMenuElement {
// null indicates that the element should be forgotten (not treated as empty)
return container.getProfiles().size() > 0 ? new OptionMenuProfileElement(container.getProfiles(), shaderPackOptions.getOptionSet(), shaderPackOptions.getOptionValues()) : null;
}
// Second profile element
if (ELEMENT_PROFILE2.equals(elementString)) {
// null indicates that the element should be forgotten (not treated as empty)
return container.getProfiles2().size() > 0
? ProfileElementTracker.markSecondProfileSet(new OptionMenuProfileElement(container.getProfiles2(), shaderPackOptions.getOptionSet(), shaderPackOptions.getOptionValues()))
: null;
}
// Link to sub screen element
if (elementString.startsWith("[") && elementString.endsWith("]")) {
return new OptionMenuLinkElement(elementString.substring(1, elementString.length() - 1));
@@ -0,0 +1,22 @@
package net.coderbot.iris.shaderpack.option.menu;
import java.util.Collections;
import java.util.Set;
import java.util.WeakHashMap;
public final class ProfileElementTracker {
private static final Set<Object> SECOND_PROFILE_ELEMENTS =
Collections.newSetFromMap(new WeakHashMap<>());
private ProfileElementTracker() {
}
public static <T> T markSecondProfileSet(T element) {
SECOND_PROFILE_ELEMENTS.add(element);
return element;
}
public static boolean isSecondProfileSet(Object element) {
return SECOND_PROFILE_ELEMENTS.contains(element);
}
}
@@ -14,6 +14,7 @@ public class ExternallyManagedUniforms {
addMat4(uniformHolder, "iris_ProjectionMatrix");
addMat4(uniformHolder, "iris_ProjectionMatrixInverse");
addMat4(uniformHolder, "iris_LightmapTextureMatrix");
addMat4(uniformHolder, "iris_TextureMatrix");
addMat4(uniformHolder, "u_ModelViewProjectionMatrix");
addMat3(uniformHolder, "iris_NormalMatrix");
uniformHolder.externallyManagedUniform("heavyFog", UniformType.BOOL);
@@ -1,6 +1,7 @@
package com.gtnewhorizons.angelica.mixins.early.angelica;
import com.gtnewhorizon.gtnhlib.config.ConfigurationManager;
import com.gtnewhorizons.angelica.AngelicaMod;
import com.gtnewhorizons.angelica.config.AngelicaConfig;
import com.gtnewhorizons.angelica.glsm.GLStateManager;
import net.minecraftforge.client.ForgeHooksClient;
@@ -39,13 +40,12 @@ public abstract class MixinForgeHooksClient_CoreProfile {
@Overwrite
public static void createDisplay() throws LWJGLException {
ImageIO.setUseCache(false);
// Preserve vanilla Forge stencil support -- enabled via -Dforge.forceDisplayStencil=true by users/modpacks
final boolean wantStencil = Boolean.parseBoolean(System.getProperty("forge.forceDisplayStencil", "false"));
stencilBits = wantStencil ? 8 : 0;
// Always enable 8-bit stencil, was an option before "-Dforge.forceDisplayStencil=true"
stencilBits = 8;
final PixelFormat format = new PixelFormat().withDepthBits(24).withStencilBits(stencilBits);
final ContextAttribs attribs = new ContextAttribs(3, 3).withProfileCore(true).withForwardCompatible(true);
final ContextAttribs attribs = new ContextAttribs(3, 3).withProfileCore(true).withForwardCompatible(true).withDebug(AngelicaMod.lwjglDebug);
final MethodHandle setMajor, setMinor;
try {
final Field majorField = ContextAttribs.class.getDeclaredField("majorVersion");
@@ -0,0 +1,125 @@
package com.gtnewhorizons.angelica.mixins.early.angelica.bugfixes;
import com.gtnewhorizons.angelica.glsm.GLStateManager;
import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import net.minecraft.client.renderer.ItemRenderer;
import net.minecraft.client.renderer.Tessellator;
import org.lwjgl.opengl.GL11;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
/**
* Fix enchantment glint z-fighting on held item edges using stencil masking.
*
* Vanilla uses GL_EQUAL to restrict the glint to item pixels, but GPU depth
* non-determinism between draw calls causes GL_EQUAL to fail on edge quads.
*
* This mixin uses a stencil-based check instead of a GL_EQUAL check.
* 1. During item render: write stencil value 1 wherever the item draws.
* 2. During each glint renderItemIn2D call:
* a. Pre-pass: no color/depth writes, GL_LEQUAL depth test, increment the stencil 1→2
* where depth passes. This determines pixel ownership without corrupting the depth buffer (damn potions...)
* b. Color pass: draw only where stencil == 2, GL_ALWAYS depth test, decrement the stencil
* 2→1 to reset for the next glint pass.
*/
@Mixin(value = ItemRenderer.class, priority = 1100)
public class MixinItemRenderer_EdgeDepth {
@Unique private static boolean angelica$glintMode = false;
@Unique private static boolean angelica$inPrepass = false;
// Item render: write stencil value 1 at all visible item pixels
@Inject(
method = "renderItem(Lnet/minecraft/entity/EntityLivingBase;Lnet/minecraft/item/ItemStack;ILnet/minecraftforge/client/IItemRenderer$ItemRenderType;)V",
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/ItemRenderer;renderItemIn2D(Lnet/minecraft/client/renderer/Tessellator;FFFFIIF)V", ordinal = 0, remap = true),
remap = false
)
private void angelica$stencilWriteStart(CallbackInfo ci) {
GLStateManager.glEnable(GL11.GL_STENCIL_TEST);
GLStateManager.glStencilMask(0xFF);
GLStateManager.glClearStencil(0);
GLStateManager.glClear(GL11.GL_STENCIL_BUFFER_BIT);
GLStateManager.glStencilFunc(GL11.GL_ALWAYS, 1, 0xFF);
GLStateManager.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_REPLACE);
}
@Inject(
method = "renderItem(Lnet/minecraft/entity/EntityLivingBase;Lnet/minecraft/item/ItemStack;ILnet/minecraftforge/client/IItemRenderer$ItemRenderType;)V",
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/ItemRenderer;renderItemIn2D(Lnet/minecraft/client/renderer/Tessellator;FFFFIIF)V", ordinal = 0, remap = true, shift = At.Shift.AFTER),
remap = false
)
private void angelica$stencilWriteEnd(CallbackInfo ci) {
GLStateManager.glStencilMask(0x00);
GLStateManager.glDisable(GL11.GL_STENCIL_TEST);
}
// Glint section: replace GL_EQUAL with stencil-based masking
@Redirect(
method = "renderItem(Lnet/minecraft/entity/EntityLivingBase;Lnet/minecraft/item/ItemStack;ILnet/minecraftforge/client/IItemRenderer$ItemRenderType;)V",
at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/GL11;glDepthFunc(I)V", ordinal = 0, remap = false),
remap = false
)
private void angelica$glintStart(int func) {
angelica$glintMode = true;
GLStateManager.glEnable(GL11.GL_STENCIL_TEST);
GLStateManager.glStencilFunc(GL11.GL_EQUAL, 1, 0xFF);
GLStateManager.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP);
}
@Redirect(
method = "renderItem(Lnet/minecraft/entity/EntityLivingBase;Lnet/minecraft/item/ItemStack;ILnet/minecraftforge/client/IItemRenderer$ItemRenderType;)V",
at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/GL11;glDepthFunc(I)V", ordinal = 1, remap = false),
remap = false
)
private void angelica$glintEnd(int func) {
angelica$glintMode = false;
GLStateManager.glDepthFunc(GL11.GL_LEQUAL);
GLStateManager.glDepthMask(true);
GLStateManager.glDisable(GL11.GL_STENCIL_TEST);
GLStateManager.glStencilMask(0xFF);
}
// Stencil pre-pass inside renderItemIn2D when in glint mode
@WrapMethod(method = "renderItemIn2D")
private static void angelica$glintPrepass(Tessellator tess, float minU, float minV, float maxU, float maxV,
int w, int h, float thickness, Operation<Void> original) {
if (!angelica$glintMode || angelica$inPrepass) {
original.call(tess, minU, minV, maxU, maxV, w, h, thickness);
return;
}
angelica$inPrepass = true;
// Pre-pass: determine pixel ownership via GL_LEQUAL depth test.
GLStateManager.glColorMask(false, false, false, false);
GLStateManager.glDepthMask(false);
GLStateManager.glDepthFunc(GL11.GL_LEQUAL);
GLStateManager.glStencilMask(0xFF);
GLStateManager.glStencilFunc(GL11.GL_EQUAL, 1, 0xFF);
GLStateManager.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_INCR);
original.call(tess, minU, minV, maxU, maxV, w, h, thickness);
// Color pass: draw only at pre-pass pixels.
GLStateManager.glColorMask(true, true, true, true);
GLStateManager.glStencilFunc(GL11.GL_EQUAL, 2, 0xFF);
GLStateManager.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_DECR);
GLStateManager.glDepthFunc(GL11.GL_ALWAYS);
original.call(tess, minU, minV, maxU, maxV, w, h, thickness);
// Restore state for the next glint renderItemIn2D call
GLStateManager.glStencilMask(0x00);
GLStateManager.glStencilFunc(GL11.GL_EQUAL, 1, 0xFF);
GLStateManager.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP);
GLStateManager.glDepthFunc(GL11.GL_LEQUAL);
angelica$inPrepass = false;
}
}
@@ -24,7 +24,8 @@ public class MixinRendererLivingEntity_EyeDepth {
method = "doRender(Lnet/minecraft/entity/EntityLivingBase;DDDFF)V",
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/model/ModelBase;render(Lnet/minecraft/entity/Entity;FFFFFF)V"),
slice = @Slice(
from = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/entity/RendererLivingEntity;shouldRenderPass(Lnet/minecraft/entity/EntityLivingBase;IF)I")
from = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/entity/RendererLivingEntity;shouldRenderPass(Lnet/minecraft/entity/EntityLivingBase;IF)I"),
to = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/entity/RendererLivingEntity;renderEquippedItems(Lnet/minecraft/entity/EntityLivingBase;F)V")
)
)
private void angelica$eyePassPolygonOffset(ModelBase instance, Entity entity, float a, float b, float c, float d, float e, float f, Operation<Void> original) {
@@ -1,5 +1,6 @@
package com.gtnewhorizons.angelica.mixins.early.celeritas.features.mipmaps;
import com.gtnewhorizons.angelica.config.AngelicaConfig;
import com.gtnewhorizons.angelica.rendering.celeritas.SpriteExtension;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import org.embeddedt.embeddium.api.util.ColorABGR;
@@ -29,9 +30,23 @@ public abstract class MixinTextureAtlasSprite implements SpriteExtension {
if (this.framesTextureData.isEmpty() || this.framesTextureData.get(0) == null) {
return;
}
if (celeritas$isAlwaysTranslucent(this.iconName)) {
this.celeritas$transparencyLevel = SpriteTransparencyLevel.TRANSLUCENT;
return;
}
celeritas$processTransparentImages(this.framesTextureData.get(0)[0], level > 0 && !iconName.contains("leaves"));
}
@Unique
private static boolean celeritas$isAlwaysTranslucent(String name) {
final String[] list = AngelicaConfig.alwaysTranslucentSprites;
if (list == null || list.length == 0) return false;
for (String s : list) {
if (name.equals(s)) return true;
}
return false;
}
// Ordinals: OPAQUE=0, TRANSPARENT=1, TRANSLUCENT=2
@Unique private static final int ORDINAL_OPAQUE = SpriteTransparencyLevel.OPAQUE.ordinal();
@Unique private static final int ORDINAL_TRANSPARENT = SpriteTransparencyLevel.TRANSPARENT.ordinal();
@@ -0,0 +1,49 @@
package com.gtnewhorizons.angelica.arch;
import com.tngtech.archunit.core.domain.JavaClasses;
import com.tngtech.archunit.core.importer.ClassFileImporter;
import com.tngtech.archunit.core.importer.ImportOption;
import com.tngtech.archunit.lang.ArchRule;
import org.junit.jupiter.api.Test;
import static com.tngtech.archunit.core.domain.JavaCall.Predicates.target;
import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.nameMatching;
import static com.tngtech.archunit.core.domain.properties.HasOwner.Predicates.With.owner;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;
/**
* Enforces that all GL calls go through GLStateManager / RENDER_BACKEND. Direct method calls on org.lwjgl.opengl GL command classes are banned outside
* of the GL backend implementation and the bytecode redirector.
*
* Field access (GL constants like GL11.GL_BLEND) is not affected
*
* LWJGL infrastructure classes (Display, ContextAttribs, PixelFormat, Drawable) are excluded
*/
class NoDirectGLCallsTest {
// Matches GL command classes but not LWJGL infrastructure (Display, etc.)
// Covers: GL11-GL44, ARB*, EXT*, NV*, AMD*, ATI*, KHR*, INTEL*, GLContext, plus OpenGlHelper
private static final String GL_COMMAND_CLASSES = "org\\.lwjgl\\.opengl\\.(?!Display|ContextAttribs|PixelFormat|Drawable|SharedDrawable).*";
private static final JavaClasses classes = new ClassFileImporter()
.withImportOption(ImportOption.Predefined.DO_NOT_INCLUDE_TESTS)
.importPaths(
"build/classes/java/main",
"build/classes/java/mixin"
);
private static final ArchRule NO_DIRECT_GL_CALLS = noClasses()
.that().resideOutsideOfPackages(
"com.gtnewhorizons.angelica.glsm.backend..",
"com.gtnewhorizons.angelica.loading.."
)
.should().callMethodWhere(
target(owner(nameMatching(GL_COMMAND_CLASSES)))
)
.because("GL calls must go through GLStateManager, not directly to LWJGL or the RENDER_BACKEND");
@Test
void noDirectGLCalls() {
NO_DIRECT_GL_CALLS.check(classes);
}
}