mirror of
https://github.com/GTNewHorizons/Angelica.git
synced 2026-11-15 09:44:52 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
54c99386d4 | ||
|
|
465abf889a | ||
|
|
4acb83be6a | ||
|
|
80f9724ee6 | ||
|
|
8cf55bb216 | ||
|
|
3ebc8868c7 | ||
|
|
0938e6d975 | ||
|
|
d3022a40d2 | ||
|
|
2645c803f9 | ||
|
|
d91c356a99 | ||
|
|
189ff4a80f | ||
|
|
ffb4ca9472 | ||
|
|
7d8c8d306d | ||
|
|
117ff0cacf | ||
|
|
83fdd57534 | ||
|
|
951be04e9a | ||
|
|
0ad69f3433 | ||
|
|
0dabecc784 | ||
|
|
9b3fad4c6d | ||
|
|
e1e8256861 | ||
|
|
e65c01c2a3 | ||
|
|
b9de4df18e | ||
|
|
a5d31cd1b6 | ||
|
|
29f8d718cc | ||
|
|
52b0db2566 | ||
|
|
e9eb45f4f2 | ||
|
|
92e28a4cd5 | ||
|
|
f46a86889c | ||
|
|
c827d446d5 | ||
|
|
00ef355ce8 | ||
|
|
1282056fff | ||
|
|
6c422d47a2 | ||
|
|
057ea8035c | ||
|
|
3ea47c8385 | ||
|
|
306d732d81 | ||
|
|
a483669579 | ||
|
|
53996500d7 | ||
|
|
04dd8ce6c7 | ||
|
|
8c9edfa4c3 | ||
|
|
3f44195756 | ||
|
|
c98f056d74 | ||
|
|
7e25f5d03e | ||
|
|
b5553654d0 | ||
|
|
a3fffb47be | ||
|
|
09cc557be0 |
No files matched your search
+7
-2
@@ -83,7 +83,7 @@ dependencies {
|
||||
shadowImplementation("net.minecraftforge:eventbus:7.0-beta.15")
|
||||
|
||||
shadowImplementation("org.anarres:jcpp:1.4.14") // Apache 2.0
|
||||
shadowImplementation("org.taumc:glsl-transformation-lib:0.2.0-26.g5ee7d96-GTNH") {
|
||||
shadowImplementation("org.taumc:glsl-transformation-lib:0.2.0-32.g7dd88a4-GTNH") {
|
||||
exclude module: "antlr4" // we only want to shadow the runtime module
|
||||
}
|
||||
shadowImplementation("org.antlr:antlr4-runtime:4.13.2")
|
||||
@@ -119,7 +119,7 @@ dependencies {
|
||||
|
||||
compileOnly("com.github.GTNewHorizons:NotEnoughIds:2.1.10:dev")
|
||||
|
||||
compileOnly(rfg.deobf("maven.modrinth:ntmspace:X5593_H261"))
|
||||
compileOnly(rfg.deobf("maven.modrinth:ntmspace:X5634_H261"))
|
||||
|
||||
compileOnly(rfg.deobf("curse.maven:campfirebackport-387444:4611675"))
|
||||
compileOnly(rfg.deobf("curse.maven:xaeros-minimap-263420:5060684"))
|
||||
@@ -136,6 +136,9 @@ dependencies {
|
||||
// Better Crashes
|
||||
compileOnly("com.github.GTNewHorizons:BetterCrashes:1.4.1-GTNH:dev")
|
||||
|
||||
// Distant Horizons
|
||||
compileOnly("maven.modrinth:DistantHorizonsApi:5.1.0")
|
||||
|
||||
afterEvaluate {
|
||||
dependencies {
|
||||
testImplementation(platform('org.junit:junit-bom:5.14.1'))
|
||||
@@ -146,6 +149,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')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ dependencies {
|
||||
compileOnly("org.lwjgl.lwjgl:lwjgl:${property("lwjglVersion")}")
|
||||
compileOnly("org.lwjgl.lwjgl:lwjgl_util:${property("lwjglVersion")}")
|
||||
|
||||
compileOnly("org.ow2.asm:asm-tree:9.7")
|
||||
compileOnly("org.ow2.asm:asm-tree:5.0.3")
|
||||
|
||||
// Our Deps
|
||||
api("com.github.GTNewHorizons:GTNHLib:${property("gtnhlibVersion")}:dev")
|
||||
@@ -100,6 +100,7 @@ dependencies {
|
||||
testImplementation(sourceSets["stubs"].output)
|
||||
testImplementation(platform("org.junit:junit-bom:${property("junitBomVersion")}"))
|
||||
testImplementation("org.junit.jupiter:junit-jupiter")
|
||||
testImplementation("org.ow2.asm:asm-tree:9.7")
|
||||
testImplementation("org.lwjgl.lwjgl:lwjgl:${property("lwjglVersion")}")
|
||||
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
||||
testRuntimeOnly("org.apache.logging.log4j:log4j-core:${property("log4jVersion")}")
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -345,6 +345,27 @@ public class FeedbackManager {
|
||||
}
|
||||
break;
|
||||
|
||||
case GL11.GL_QUAD_STRIP:
|
||||
for (int i = 0; i + 3 < count; i += 2) {
|
||||
feedbackToken(GL11.GL_POLYGON_TOKEN);
|
||||
feedbackToken(4);
|
||||
emitVertex(reader.read(i), stride);
|
||||
emitVertex(reader.read(i + 1), stride);
|
||||
emitVertex(reader.read(i + 3), stride);
|
||||
emitVertex(reader.read(i + 2), stride);
|
||||
}
|
||||
break;
|
||||
|
||||
case GL11.GL_POLYGON:
|
||||
if (count >= 3) {
|
||||
feedbackToken(GL11.GL_POLYGON_TOKEN);
|
||||
feedbackToken(count);
|
||||
for (int i = 0; i < count; i++) {
|
||||
emitVertex(reader.read(i), stride);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new UnsupportedOperationException("Feedback mode: unsupported primitive mode 0x" + Integer.toHexString(mode));
|
||||
}
|
||||
|
||||
@@ -419,6 +419,9 @@ public class GLStateManager {
|
||||
@Getter protected static int boundVBO;
|
||||
@Getter protected static int boundEBO;
|
||||
@Getter protected static int boundVAO;
|
||||
private static int clientArraysVBO = 0;
|
||||
private static int clientArraysVBOCapacity = 0;
|
||||
private static final int[] clientArraysVBOOffsets = new int[VertexAttribState.MAX_ATTRIBS];
|
||||
private static int boundPixelUnpackBuffer;
|
||||
private static int boundPixelPackBuffer;
|
||||
private static final Int2IntOpenHashMap vaoEboMap = new Int2IntOpenHashMap();
|
||||
@@ -2145,6 +2148,7 @@ public class GLStateManager {
|
||||
}
|
||||
prepareWideLineEmulation(mode);
|
||||
ShaderManager.getInstance().preDraw();
|
||||
prepareClientArrays();
|
||||
RENDER_BACKEND.drawElements(mode, indices);
|
||||
}
|
||||
|
||||
@@ -2158,6 +2162,7 @@ public class GLStateManager {
|
||||
}
|
||||
prepareWideLineEmulation(mode);
|
||||
ShaderManager.getInstance().preDraw();
|
||||
prepareClientArrays();
|
||||
if (mode == GL11.GL_QUADS) {
|
||||
QuadConverter.drawQuadElementsAsTriangles(indices);
|
||||
} else {
|
||||
@@ -2175,6 +2180,7 @@ public class GLStateManager {
|
||||
}
|
||||
prepareWideLineEmulation(mode);
|
||||
ShaderManager.getInstance().preDraw();
|
||||
prepareClientArrays();
|
||||
if (mode == GL11.GL_QUADS) {
|
||||
QuadConverter.drawQuadElementsAsTriangles(indices);
|
||||
} else {
|
||||
@@ -2192,6 +2198,7 @@ public class GLStateManager {
|
||||
}
|
||||
prepareWideLineEmulation(mode);
|
||||
ShaderManager.getInstance().preDraw();
|
||||
prepareClientArrays();
|
||||
if (mode == GL11.GL_QUADS) {
|
||||
QuadConverter.drawQuadElementsAsTriangles(count, type, indices);
|
||||
} else {
|
||||
@@ -2223,6 +2230,7 @@ public class GLStateManager {
|
||||
}
|
||||
prepareWideLineEmulation(mode);
|
||||
ShaderManager.getInstance().preDraw();
|
||||
prepareClientArrays();
|
||||
if (mode == GL11.GL_QUADS) {
|
||||
QuadConverter.drawQuadElementsAsTriangles(indices_count, type, indices_buffer_offset);
|
||||
} else {
|
||||
@@ -2245,20 +2253,72 @@ public class GLStateManager {
|
||||
|
||||
public static void glMultiDrawElementsIndirect(int mode, int type, long indirect, int drawcount, int stride) {
|
||||
ShaderManager.getInstance().preDraw();
|
||||
prepareClientArrays();
|
||||
RENDER_BACKEND.multiDrawElementsIndirect(mode, type, indirect, drawcount, stride);
|
||||
}
|
||||
|
||||
public static void glMultiDrawElementsBaseVertex(int mode, long pCount, int type, long pIndices, int drawcount, long pBaseVertex) {
|
||||
ShaderManager.getInstance().preDraw();
|
||||
prepareClientArrays();
|
||||
RENDER_BACKEND.multiDrawElementsBaseVertex(mode, pCount, type, pIndices, drawcount, pBaseVertex);
|
||||
}
|
||||
|
||||
public static void glDrawElementsBaseVertex(int mode, int count, int type, long indices, int basevertex) {
|
||||
ShaderManager.getInstance().preDraw();
|
||||
prepareClientArrays();
|
||||
RENDER_BACKEND.drawElementsBaseVertex(mode, count, type, indices, basevertex);
|
||||
}
|
||||
|
||||
public static void glDrawElementsInstanced(int mode, int count, int type, long indices, int primcount) { RENDER_BACKEND.drawElementsInstanced(mode, count, type, indices, primcount); }
|
||||
public static void glDrawElementsInstanced(int mode, int count, int type, long indices, int primcount) {
|
||||
ShaderManager.getInstance().preDraw();
|
||||
prepareClientArrays();
|
||||
RENDER_BACKEND.drawElementsInstanced(mode, count, type, indices, primcount);
|
||||
}
|
||||
|
||||
private static void prepareClientArrays() {
|
||||
if (ShaderManager.getInstance().isEnabled() && VertexAttribState.hasAnyClientSideEnabledAttrib()) {
|
||||
uploadClientArraysToVBO();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If any enabled vertex attribute uses a client-side pointer (no VBO), upload all such
|
||||
* attribs into a shared stream VBO so the draw succeeds under core profile.
|
||||
*/
|
||||
private static void uploadClientArraysToVBO() {
|
||||
int totalBytes = 0;
|
||||
for (int i = 0; i < VertexAttribState.MAX_ATTRIBS; i++) {
|
||||
clientArraysVBOOffsets[i] = -1;
|
||||
final VertexAttribState.Attrib a = VertexAttribState.get(i);
|
||||
if (!a.enabled || a.clientPointer == null) continue;
|
||||
clientArraysVBOOffsets[i] = totalBytes;
|
||||
totalBytes += a.clientPointer.remaining();
|
||||
}
|
||||
if (totalBytes == 0) return;
|
||||
|
||||
if (clientArraysVBO == 0) {
|
||||
clientArraysVBO = RENDER_BACKEND.genBuffers();
|
||||
}
|
||||
|
||||
final int savedVBO = boundVBO;
|
||||
glBindBuffer(GL15.GL_ARRAY_BUFFER, clientArraysVBO);
|
||||
|
||||
if (totalBytes > clientArraysVBOCapacity) {
|
||||
int newCap = Math.max(4096, clientArraysVBOCapacity);
|
||||
while (newCap < totalBytes) newCap *= 2;
|
||||
clientArraysVBOCapacity = newCap;
|
||||
}
|
||||
RENDER_BACKEND.bufferData(GL15.GL_ARRAY_BUFFER, clientArraysVBOCapacity, GL15.GL_STREAM_DRAW);
|
||||
|
||||
for (int i = 0; i < VertexAttribState.MAX_ATTRIBS; i++) {
|
||||
if (clientArraysVBOOffsets[i] < 0) continue;
|
||||
final VertexAttribState.Attrib a = VertexAttribState.get(i);
|
||||
RENDER_BACKEND.bufferSubData(GL15.GL_ARRAY_BUFFER, clientArraysVBOOffsets[i], a.clientPointer.duplicate());
|
||||
RENDER_BACKEND.vertexAttribPointer(i, a.size, a.type, a.normalized, a.stride, (long) clientArraysVBOOffsets[i]);
|
||||
}
|
||||
|
||||
glBindBuffer(GL15.GL_ARRAY_BUFFER, savedVBO);
|
||||
}
|
||||
|
||||
public static void glDrawArrays(int mode, int first, int count) {
|
||||
CommandRecorder savedRecorder = null;
|
||||
@@ -2278,8 +2338,13 @@ public class GLStateManager {
|
||||
}
|
||||
prepareWideLineEmulation(mode);
|
||||
ShaderManager.getInstance().preDraw();
|
||||
prepareClientArrays();
|
||||
if (mode == GL11.GL_QUADS) {
|
||||
QuadConverter.drawQuadsAsTriangles(first, count);
|
||||
} else if (mode == GL11.GL_QUAD_STRIP) {
|
||||
RENDER_BACKEND.drawArrays(GL11.GL_TRIANGLE_STRIP, first, count & ~1);
|
||||
} else if (mode == GL11.GL_POLYGON) {
|
||||
RENDER_BACKEND.drawArrays(GL11.GL_TRIANGLE_FAN, first, count);
|
||||
} else {
|
||||
RENDER_BACKEND.drawArrays(mode, first, count);
|
||||
}
|
||||
@@ -2298,6 +2363,10 @@ public class GLStateManager {
|
||||
glVertexAttribPointer(Usage.POSITION.getAttributeLocation(), size, GL11.GL_FLOAT, false, stride, MemoryUtilities.memByteBuffer(pointer));
|
||||
}
|
||||
|
||||
public static void glVertexPointer(int size, int stride, DoubleBuffer pointer) {
|
||||
glVertexAttribPointer(Usage.POSITION.getAttributeLocation(), size, GL11.GL_DOUBLE, false, stride, MemoryUtilities.memByteBuffer(pointer));
|
||||
}
|
||||
|
||||
public static void glVertexPointer(int size, int type, int stride, ByteBuffer pointer) {
|
||||
glVertexAttribPointer(Usage.POSITION.getAttributeLocation(), size, type, false, stride, pointer);
|
||||
}
|
||||
@@ -2339,6 +2408,10 @@ public class GLStateManager {
|
||||
glNormalPointer(GL11.GL_INT, stride, pointer);
|
||||
}
|
||||
|
||||
public static void glNormalPointer(int stride, DoubleBuffer pointer) {
|
||||
glNormalPointer(GL11.GL_DOUBLE, stride, pointer);
|
||||
}
|
||||
|
||||
public static void glNormalPointer(int type, int stride, ByteBuffer pointer) {
|
||||
glVertexAttribPointer(Usage.NORMAL.getAttributeLocation(), 3, type, Usage.NORMAL.isNormalized(), stride, pointer);
|
||||
}
|
||||
@@ -2355,6 +2428,10 @@ public class GLStateManager {
|
||||
glVertexAttribPointer(Usage.NORMAL.getAttributeLocation(), 3, GL11.GL_INT, Usage.NORMAL.isNormalized(), stride, MemoryUtilities.memByteBuffer(pointer));
|
||||
}
|
||||
|
||||
public static void glNormalPointer(int type, int stride, DoubleBuffer pointer) {
|
||||
glVertexAttribPointer(Usage.NORMAL.getAttributeLocation(), 3, GL11.GL_DOUBLE, Usage.NORMAL.isNormalized(), stride, MemoryUtilities.memByteBuffer(pointer));
|
||||
}
|
||||
|
||||
public static void glNormalPointer(int type, int stride, long pointer_buffer_offset) {
|
||||
glVertexAttribPointer(Usage.NORMAL.getAttributeLocation(), 3, type, Usage.NORMAL.isNormalized(), stride, pointer_buffer_offset);
|
||||
}
|
||||
@@ -2377,6 +2454,10 @@ public class GLStateManager {
|
||||
glTexCoordPointer(size, GL11.GL_SHORT, stride, pointer);
|
||||
}
|
||||
|
||||
public static void glTexCoordPointer(int size, int stride, DoubleBuffer pointer) {
|
||||
glTexCoordPointer(size, GL11.GL_DOUBLE, stride, pointer);
|
||||
}
|
||||
|
||||
public static void glTexCoordPointer(int size, int type, int stride, FloatBuffer pointer) {
|
||||
final int loc = texCoordAttributeLocation();
|
||||
if (loc < 0) return;
|
||||
@@ -2395,6 +2476,12 @@ public class GLStateManager {
|
||||
glVertexAttribPointer(loc, size, GL11.GL_INT, false, stride, MemoryUtilities.memByteBuffer(pointer));
|
||||
}
|
||||
|
||||
public static void glTexCoordPointer(int size, int type, int stride, DoubleBuffer pointer) {
|
||||
final int loc = texCoordAttributeLocation();
|
||||
if (loc < 0) return;
|
||||
glVertexAttribPointer(loc, size, GL11.GL_DOUBLE, false, stride, MemoryUtilities.memByteBuffer(pointer));
|
||||
}
|
||||
|
||||
public static void glTexCoordPointer(int size, int type, int stride, long pointer_buffer_offset) {
|
||||
final int loc = texCoordAttributeLocation();
|
||||
if (loc < 0) return;
|
||||
@@ -2441,32 +2528,23 @@ public class GLStateManager {
|
||||
}
|
||||
|
||||
public static void glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, FloatBuffer pointer) {
|
||||
final ByteBuffer bb = MemoryUtilities.memByteBuffer(pointer);
|
||||
VertexAttribState.set(index, size, type, normalized, stride, bb, boundVBO);
|
||||
RENDER_BACKEND.vertexAttribPointer(index, size, type, normalized, stride, bb);
|
||||
VertexAttribState.set(index, size, type, normalized, stride, MemoryUtilities.memByteBuffer(pointer), 0);
|
||||
}
|
||||
|
||||
public static void glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, DoubleBuffer pointer) {
|
||||
final ByteBuffer bb = MemoryUtilities.memByteBuffer(pointer);
|
||||
VertexAttribState.set(index, size, type, normalized, stride, bb, boundVBO);
|
||||
RENDER_BACKEND.vertexAttribPointer(index, size, type, normalized, stride, bb);
|
||||
VertexAttribState.set(index, size, type, normalized, stride, MemoryUtilities.memByteBuffer(pointer), 0);
|
||||
}
|
||||
|
||||
public static void glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, IntBuffer pointer) {
|
||||
final ByteBuffer bb = MemoryUtilities.memByteBuffer(pointer);
|
||||
VertexAttribState.set(index, size, type, normalized, stride, bb, boundVBO);
|
||||
RENDER_BACKEND.vertexAttribPointer(index, size, type, normalized, stride, bb);
|
||||
VertexAttribState.set(index, size, type, normalized, stride, MemoryUtilities.memByteBuffer(pointer), 0);
|
||||
}
|
||||
|
||||
public static void glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, ShortBuffer pointer) {
|
||||
final ByteBuffer bb = MemoryUtilities.memByteBuffer(pointer);
|
||||
VertexAttribState.set(index, size, type, normalized, stride, bb, boundVBO);
|
||||
RENDER_BACKEND.vertexAttribPointer(index, size, type, normalized, stride, bb);
|
||||
VertexAttribState.set(index, size, type, normalized, stride, MemoryUtilities.memByteBuffer(pointer), 0);
|
||||
}
|
||||
|
||||
public static void glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, ByteBuffer pointer) {
|
||||
VertexAttribState.set(index, size, type, normalized, stride, pointer, boundVBO);
|
||||
RENDER_BACKEND.vertexAttribPointer(index, size, type, normalized, stride, pointer);
|
||||
VertexAttribState.set(index, size, type, normalized, stride, pointer, 0);
|
||||
}
|
||||
|
||||
public static void glVertexAttribIPointer(int index, int size, int type, int stride, long offset) {
|
||||
@@ -2475,20 +2553,15 @@ public class GLStateManager {
|
||||
}
|
||||
|
||||
public static void glVertexAttribIPointer(int index, int size, int type, int stride, ByteBuffer pointer) {
|
||||
VertexAttribState.set(index, size, type, false, stride, pointer, boundVBO);
|
||||
RENDER_BACKEND.vertexAttribIPointer(index, size, type, stride, pointer);
|
||||
VertexAttribState.set(index, size, type, false, stride, pointer, 0);
|
||||
}
|
||||
|
||||
public static void glVertexAttribIPointer(int index, int size, int type, int stride, IntBuffer pointer) {
|
||||
final ByteBuffer bb = MemoryUtilities.memByteBuffer(pointer);
|
||||
VertexAttribState.set(index, size, type, false, stride, bb, boundVBO);
|
||||
RENDER_BACKEND.vertexAttribIPointer(index, size, type, stride, bb);
|
||||
VertexAttribState.set(index, size, type, false, stride, MemoryUtilities.memByteBuffer(pointer), 0);
|
||||
}
|
||||
|
||||
public static void glVertexAttribIPointer(int index, int size, int type, int stride, ShortBuffer pointer) {
|
||||
final ByteBuffer bb = MemoryUtilities.memByteBuffer(pointer);
|
||||
VertexAttribState.set(index, size, type, false, stride, bb, boundVBO);
|
||||
RENDER_BACKEND.vertexAttribIPointer(index, size, type, stride, bb);
|
||||
VertexAttribState.set(index, size, type, false, stride, MemoryUtilities.memByteBuffer(pointer), 0);
|
||||
}
|
||||
|
||||
public static void glVertexAttribDivisor(int index, int divisor) { RENDER_BACKEND.vertexAttribDivisor(index, divisor); }
|
||||
@@ -4297,9 +4370,20 @@ public class GLStateManager {
|
||||
RENDER_BACKEND.finish();
|
||||
}
|
||||
|
||||
public static int glGetError() { return RENDER_BACKEND.getError(); }
|
||||
public static String glGetString(int pname) { return RENDER_BACKEND.getString(pname); }
|
||||
public static String glGetStringi(int name, int index) { return RENDER_BACKEND.getStringi(name, index); }
|
||||
public static int glGetError() {
|
||||
if (!RENDER_BACKEND.hasContext()) return 0;
|
||||
return RENDER_BACKEND.getError();
|
||||
}
|
||||
|
||||
public static String glGetString(int pname) {
|
||||
if (!RENDER_BACKEND.hasContext()) return "no valid GL/render context";
|
||||
return RENDER_BACKEND.getString(pname);
|
||||
}
|
||||
|
||||
public static String glGetStringi(int name, int index) {
|
||||
if (!RENDER_BACKEND.hasContext()) return "no valid GL/render context";
|
||||
return RENDER_BACKEND.getStringi(name, index);
|
||||
}
|
||||
|
||||
public static void glShaderSource(int shader, CharSequence source) {
|
||||
String src = source.toString();
|
||||
@@ -5033,6 +5117,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);
|
||||
}
|
||||
@@ -5806,5 +5898,7 @@ public class GLStateManager {
|
||||
public static void glGetUniform(int program, int location, IntBuffer params) {
|
||||
RENDER_BACKEND.getUniformiv(program, location, params);
|
||||
}
|
||||
|
||||
public static void glGetTexImage(int target, int level, int format, int type, long pixels) {
|
||||
GL11.glGetTexImage(target, level, format, type, pixels);
|
||||
}
|
||||
}
|
||||
@@ -36,8 +36,11 @@ public class GlslTransformUtils {
|
||||
/** Reserved words added in later GLSL versions that may appear as identifiers in older shaders. */
|
||||
private record ReservedWordRename(Pattern pattern, String replacement) {}
|
||||
private static final Map<Integer, List<ReservedWordRename>> VERSIONED_RESERVED_WORDS = Map.of(
|
||||
// Always rename sample, glsl-transformation-lib doesn't like it
|
||||
0, List.of(
|
||||
new ReservedWordRename(Pattern.compile("\\bsample\\b"), RENAMED_PREFIX + "sample")
|
||||
),
|
||||
400, List.of(
|
||||
new ReservedWordRename(Pattern.compile("\\bsample\\b"), RENAMED_PREFIX + "sample"),
|
||||
new ReservedWordRename(Pattern.compile("\\bsampler\\b(?!\\d)"), RENAMED_PREFIX + "sampler")
|
||||
)
|
||||
);
|
||||
|
||||
+11
-1
@@ -9,6 +9,7 @@ import org.lwjgl.opengl.ARBDebugOutputCallback;
|
||||
import org.lwjgl.opengl.ARBDirectStateAccess;
|
||||
import org.lwjgl.opengl.ContextCapabilities;
|
||||
import org.lwjgl.opengl.EXTDirectStateAccess;
|
||||
import org.lwjgl.opengl.GLContext;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
@@ -67,7 +68,7 @@ public final class Lwjgl2GLRenderBackend extends RenderBackend {
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
caps = org.lwjgl.opengl.GLContext.getCapabilities();
|
||||
caps = GLContext.getCapabilities();
|
||||
activeDebugExtension = 0;
|
||||
}
|
||||
|
||||
@@ -86,6 +87,15 @@ public final class Lwjgl2GLRenderBackend extends RenderBackend {
|
||||
return "OpenGL (LWJGL2)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasContext() {
|
||||
try {
|
||||
return GLContext.getCapabilities() != null;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinGLSLVersion() {return 330;}
|
||||
|
||||
|
||||
@@ -19,6 +19,9 @@ public abstract class RenderBackend {
|
||||
public abstract boolean isAvailable();
|
||||
public abstract String getName();
|
||||
|
||||
/** Returns true if the current thread has a valid render context. Safe to call from any thread. */
|
||||
public abstract boolean hasContext();
|
||||
|
||||
/** Higher priority backends are preferred. */
|
||||
public int getPriority() { return 0; }
|
||||
|
||||
|
||||
+14
-8
@@ -273,21 +273,27 @@ public final class FragmentShaderGenerator {
|
||||
sb.append(" // Alpha test\n");
|
||||
final int func = FragmentKey.decodeAlphaFunc(key.alphaTestFunc());
|
||||
|
||||
|
||||
sb.append(" float qa = round(color.a * 255.0);\n");
|
||||
switch (func) {
|
||||
case GL11.GL_NEVER ->
|
||||
sb.append(" discard;\n");
|
||||
case GL11.GL_LESS ->
|
||||
sb.append(" if (color.a >= u_AlphaRef) discard;\n");
|
||||
case GL11.GL_EQUAL ->
|
||||
sb.append(" if (color.a != u_AlphaRef) discard;\n");
|
||||
sb.append(" if (qa >= u_AlphaRef * 255.0) discard;\n");
|
||||
case GL11.GL_EQUAL -> {
|
||||
sb.append(" float qr = round(u_AlphaRef * 255.0);\n");
|
||||
sb.append(" if (qa != qr) discard;\n");
|
||||
}
|
||||
case GL11.GL_LEQUAL ->
|
||||
sb.append(" if (color.a > u_AlphaRef) discard;\n");
|
||||
sb.append(" if (qa > u_AlphaRef * 255.0) discard;\n");
|
||||
case GL11.GL_GREATER ->
|
||||
sb.append(" if (color.a <= u_AlphaRef) discard;\n");
|
||||
case GL11.GL_NOTEQUAL ->
|
||||
sb.append(" if (color.a == u_AlphaRef) discard;\n");
|
||||
sb.append(" if (qa <= u_AlphaRef * 255.0) discard;\n");
|
||||
case GL11.GL_NOTEQUAL -> {
|
||||
sb.append(" float qr = round(u_AlphaRef * 255.0);\n");
|
||||
sb.append(" if (qa == qr) discard;\n");
|
||||
}
|
||||
case GL11.GL_GEQUAL ->
|
||||
sb.append(" if (color.a < u_AlphaRef) discard;\n");
|
||||
sb.append(" if (qa < u_AlphaRef * 255.0) discard;\n");
|
||||
case GL11.GL_ALWAYS -> {}
|
||||
}
|
||||
}
|
||||
|
||||
+6
@@ -75,6 +75,12 @@ public final class DisplayListVBOBuilder {
|
||||
if (data.drawMode == GL11.GL_QUADS) {
|
||||
final IVertexArrayObject indexedVAO = new IndexedVAO(vbo, IndexBuffer.convertQuadsToTrigs(start, start + vertexCount));
|
||||
vbos[data.drawIndex] = new DisplayListVBO.SubVBO(indexedVAO, GL11.GL_TRIANGLES, 0, vertexCount / 4 * 6);
|
||||
} else if (data.drawMode == GL11.GL_QUAD_STRIP) {
|
||||
// GL_QUAD_STRIP is removed in core profile; an even-length GL_TRIANGLE_STRIP produces the same quads
|
||||
vbos[data.drawIndex] = new DisplayListVBO.SubVBO(vao, GL11.GL_TRIANGLE_STRIP, start, vertexCount & ~1);
|
||||
} else if (data.drawMode == GL11.GL_POLYGON) {
|
||||
// GL_POLYGON is removed in core profile; convert to GL_TRIANGLE_FAN which is equivalent for convex polygons
|
||||
vbos[data.drawIndex] = new DisplayListVBO.SubVBO(vao, GL11.GL_TRIANGLE_FAN, start, vertexCount);
|
||||
} else {
|
||||
vbos[data.drawIndex] = new DisplayListVBO.SubVBO(vao, data.drawMode, start, vertexCount);
|
||||
}
|
||||
|
||||
@@ -4,16 +4,19 @@ import com.google.common.collect.ImmutableSet;
|
||||
import com.gtnewhorizon.gtnhlib.asm.ClassConstantPoolParser;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.objectweb.asm.Handle;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.tree.AbstractInsnNode;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.objectweb.asm.tree.IntInsnNode;
|
||||
import org.objectweb.asm.tree.InvokeDynamicInsnNode;
|
||||
import org.objectweb.asm.tree.LdcInsnNode;
|
||||
import org.objectweb.asm.tree.MethodInsnNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
import org.objectweb.asm.tree.TypeInsnNode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -79,6 +82,9 @@ public class GLSMRedirector {
|
||||
glCapRedirects.put(org.lwjgl.opengl.GL11.GL_SCISSOR_TEST, "ScissorTest");
|
||||
|
||||
final var gl11 = RedirectMap.newMap()
|
||||
// glEnable/Disable - Special cased in GLSMRedirector, but included here for the external API
|
||||
.add("glEnable")
|
||||
.add("glDisable")
|
||||
.add("glAlphaFunc")
|
||||
.add("glBegin")
|
||||
.add("glBindTexture")
|
||||
@@ -495,6 +501,22 @@ public class GLSMRedirector {
|
||||
return CORE_EXCLUSIONS.clone();
|
||||
}
|
||||
|
||||
/** The internal-name prefix used to match GL version classes (e.g., {@code "org/lwjgl/opengl/GL"}). */
|
||||
public static String getGLPrefix() { return GL_PREFIX; }
|
||||
|
||||
/** The internal name of the redirect target class. */
|
||||
public static String getTargetClassName() { return GLStateManager; }
|
||||
|
||||
/** Method redirects for GL-prefix classes. Key: original method name, Value: GLStateManager method name. */
|
||||
public static Map<String, String> getGLPrefixMethodRedirects() {
|
||||
return Collections.unmodifiableMap(glMethodRedirects);
|
||||
}
|
||||
|
||||
/** Method redirects for named (non-GL-prefix) classes. Key: internal class name, Value: per-method redirect map. */
|
||||
public static Map<String, Map<String, String>> getNamedClassMethodRedirects() {
|
||||
return Collections.unmodifiableMap(methodRedirects);
|
||||
}
|
||||
|
||||
public boolean shouldTransform(byte[] basicClass) {
|
||||
return cstPoolParser.find(basicClass, true);
|
||||
}
|
||||
@@ -504,7 +526,7 @@ public class GLSMRedirector {
|
||||
boolean changed = false;
|
||||
final boolean isOpenGlHelper = transformedName.equals("net.minecraft.client.renderer.OpenGlHelper");
|
||||
|
||||
for (MethodNode mn : cn.methods) {
|
||||
for (MethodNode mn : (List<MethodNode>) cn.methods) {
|
||||
if (isOpenGlHelper && (mn.name.equals("glBlendFunc") || mn.name.equals("func_148821_a"))) {
|
||||
continue;
|
||||
}
|
||||
@@ -590,6 +612,22 @@ public class GLSMRedirector {
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
} else if (node instanceof InvokeDynamicInsnNode dynNode) {
|
||||
// Redirect method handles in invokedynamic bootstrap arguments
|
||||
for (int i = 0; i < dynNode.bsmArgs.length; i++) {
|
||||
if (!(dynNode.bsmArgs[i] instanceof Handle handle)) continue;
|
||||
final Map<String, String> redirects = handle.getOwner().startsWith(GL_PREFIX) ? glMethodRedirects : methodRedirects.get(handle.getOwner());
|
||||
if (redirects == null) continue;
|
||||
final String glsmName = redirects.get(handle.getName());
|
||||
if (glsmName == null) continue;
|
||||
if (LOG_SPAM) {
|
||||
final String shortOwner = handle.getOwner().substring(handle.getOwner().lastIndexOf("/") + 1);
|
||||
LOGGER.info("Redirecting invokedynamic handle in {} from {}.{}{} to GLStateManager.{}{}", transformedName, shortOwner, handle.getName(), handle.getDesc(), glsmName, handle.getDesc());
|
||||
}
|
||||
dynNode.bsmArgs[i] = new Handle(handle.getTag(), GLStateManager, glsmName, handle.getDesc());
|
||||
changed = true;
|
||||
redirectInMethod = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ASSERT_MAIN_THREAD && redirectInMethod && !transformedName.startsWith(SplashProgress) && !(transformedName.startsWith(MinecraftClient) && ExcludedMinecraftMainThreadChecks.contains(mn.name))) {
|
||||
|
||||
@@ -16,16 +16,19 @@ public class VertexAttribState {
|
||||
private static final Int2ObjectOpenHashMap<Attrib[]> vaoAttribs = new Int2ObjectOpenHashMap<>();
|
||||
private static Attrib[] current;
|
||||
private static final ArrayDeque<Attrib[]> pool = new ArrayDeque<>();
|
||||
private static int clientSideEnabledCount;
|
||||
|
||||
public static void init(int defaultVAO) {
|
||||
vaoAttribs.clear();
|
||||
pool.clear();
|
||||
current = allocAttribArray();
|
||||
vaoAttribs.put(defaultVAO, current);
|
||||
clientSideEnabledCount = 0;
|
||||
}
|
||||
|
||||
public static void onBindVertexArray(int newVAO) {
|
||||
current = vaoAttribs.computeIfAbsent(newVAO, k -> allocAttribArray());
|
||||
recomputeClientSideCount();
|
||||
}
|
||||
|
||||
public static void onDeleteVertexArray(int vaoId) {
|
||||
@@ -39,6 +42,7 @@ public class VertexAttribState {
|
||||
vaoAttribs.clear();
|
||||
pool.clear();
|
||||
current = null;
|
||||
clientSideEnabledCount = 0;
|
||||
}
|
||||
|
||||
private static Attrib[] allocAttribArray() {
|
||||
@@ -55,6 +59,7 @@ public class VertexAttribState {
|
||||
public static void set(int index, int size, int type, boolean normalized, int stride, long offset, int vboId) {
|
||||
if (index < 0 || index >= MAX_ATTRIBS) return;
|
||||
final Attrib a = current[index];
|
||||
final boolean was = a.isClientSide();
|
||||
a.size = size;
|
||||
a.type = type;
|
||||
a.normalized = normalized;
|
||||
@@ -62,11 +67,13 @@ public class VertexAttribState {
|
||||
a.offset = offset;
|
||||
a.vboId = vboId;
|
||||
a.clientPointer = null;
|
||||
if (was) clientSideEnabledCount--;
|
||||
}
|
||||
|
||||
public static void set(int index, int size, int type, boolean normalized, int stride, ByteBuffer pointer, int vboId) {
|
||||
if (index < 0 || index >= MAX_ATTRIBS) return;
|
||||
final Attrib a = current[index];
|
||||
final boolean was = a.isClientSide();
|
||||
a.size = size;
|
||||
a.type = type;
|
||||
a.normalized = normalized;
|
||||
@@ -74,17 +81,33 @@ public class VertexAttribState {
|
||||
a.offset = 0;
|
||||
a.vboId = vboId;
|
||||
a.clientPointer = (vboId == 0) ? pointer : null;
|
||||
final boolean now = a.isClientSide();
|
||||
if (was != now) clientSideEnabledCount += now ? 1 : -1;
|
||||
}
|
||||
|
||||
public static void setEnabled(int index, boolean enabled) {
|
||||
if (index < 0 || index >= MAX_ATTRIBS) return;
|
||||
current[index].enabled = enabled;
|
||||
final Attrib a = current[index];
|
||||
if (a.clientPointer != null && a.enabled != enabled) {
|
||||
clientSideEnabledCount += enabled ? 1 : -1;
|
||||
}
|
||||
a.enabled = enabled;
|
||||
}
|
||||
|
||||
public static Attrib get(int index) {
|
||||
return current[index];
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static void recomputeClientSideCount() {
|
||||
int count = 0;
|
||||
for (int i = 0; i < MAX_ATTRIBS; i++) {
|
||||
if (current[i].isClientSide()) count++;
|
||||
}
|
||||
clientSideEnabledCount = count;
|
||||
}
|
||||
|
||||
public static boolean hasVBOBoundAttrib() {
|
||||
for (int i = 0; i < MAX_ATTRIBS; i++) {
|
||||
if (current[i].enabled && current[i].vboId != 0) return true;
|
||||
@@ -92,6 +115,14 @@ public class VertexAttribState {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if any currently enabled vertex attribute was registered without a VBO
|
||||
* (i.e. as a client-side pointer). In core profile, such attribs are treated as null
|
||||
* offsets into a non-existent buffer, causing a native crash at draw time.
|
||||
*/
|
||||
public static boolean hasAnyClientSideEnabledAttrib() {
|
||||
return clientSideEnabledCount > 0;
|
||||
}
|
||||
public static class Attrib {
|
||||
public boolean enabled;
|
||||
public int size;
|
||||
@@ -102,6 +133,10 @@ public class VertexAttribState {
|
||||
public int vboId;
|
||||
public ByteBuffer clientPointer;
|
||||
|
||||
public boolean isClientSide() {
|
||||
return enabled && clientPointer != null;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
enabled = false;
|
||||
size = 0;
|
||||
|
||||
@@ -156,6 +156,108 @@ class FeedbackManagerTest {
|
||||
GLStateManager.glDeleteVertexArrays(vao);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPolygonFeedback_GL2D() {
|
||||
final FloatBuffer buf = BufferUtils.createFloatBuffer(128);
|
||||
FeedbackManager.glFeedbackBuffer(GL11.GL_2D, buf);
|
||||
FeedbackManager.glRenderMode(GL11.GL_FEEDBACK);
|
||||
|
||||
GLStateManager.getModelViewMatrix().identity();
|
||||
GLStateManager.getProjectionMatrix().identity();
|
||||
GLStateManager.getViewportState().setViewPort(0, 0, 800, 600);
|
||||
GLStateManager.getViewportState().setDepthRange(0.0, 1.0);
|
||||
|
||||
final int vao = GL30.glGenVertexArrays();
|
||||
GLStateManager.glBindVertexArray(vao);
|
||||
|
||||
final float[] verts = {
|
||||
0f, 0f, 0f,
|
||||
1f, 0f, 0f,
|
||||
1f, 1f, 0f,
|
||||
0f, 1f, 0f
|
||||
};
|
||||
final FloatBuffer vertBuf = BufferUtils.createFloatBuffer(verts.length);
|
||||
vertBuf.put(verts).flip();
|
||||
|
||||
final int vbo = GL15.glGenBuffers();
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
|
||||
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vertBuf, GL15.GL_STATIC_DRAW);
|
||||
GLStateManager.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 12, 0);
|
||||
GLStateManager.glEnableVertexAttribArray(0);
|
||||
|
||||
FeedbackManager.processDrawArrays(GL11.GL_POLYGON, 0, 4);
|
||||
|
||||
final int count = FeedbackManager.glRenderMode(GL11.GL_RENDER);
|
||||
|
||||
assertEquals(10, count, "Polygon in GL_2D should produce 10 floats");
|
||||
assertEquals(GL11.GL_POLYGON_TOKEN, buf.get(0), 0.001f);
|
||||
assertEquals(4.0f, buf.get(1), 0.001f);
|
||||
assertEquals(400.0f, buf.get(2), 0.01f);
|
||||
assertEquals(300.0f, buf.get(3), 0.01f);
|
||||
assertEquals(800.0f, buf.get(4), 0.01f);
|
||||
assertEquals(300.0f, buf.get(5), 0.01f);
|
||||
assertEquals(800.0f, buf.get(6), 0.01f);
|
||||
assertEquals(600.0f, buf.get(7), 0.01f);
|
||||
assertEquals(400.0f, buf.get(8), 0.01f);
|
||||
assertEquals(600.0f, buf.get(9), 0.01f);
|
||||
|
||||
GLStateManager.glDisableVertexAttribArray(0);
|
||||
GLStateManager.glBindVertexArray(0);
|
||||
GL15.glDeleteBuffers(vbo);
|
||||
GLStateManager.glDeleteVertexArrays(vao);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testQuadStripFeedback_GL2D() {
|
||||
final FloatBuffer buf = BufferUtils.createFloatBuffer(128);
|
||||
FeedbackManager.glFeedbackBuffer(GL11.GL_2D, buf);
|
||||
FeedbackManager.glRenderMode(GL11.GL_FEEDBACK);
|
||||
|
||||
GLStateManager.getModelViewMatrix().identity();
|
||||
GLStateManager.getProjectionMatrix().identity();
|
||||
GLStateManager.getViewportState().setViewPort(0, 0, 800, 600);
|
||||
GLStateManager.getViewportState().setDepthRange(0.0, 1.0);
|
||||
|
||||
final int vao = GL30.glGenVertexArrays();
|
||||
GLStateManager.glBindVertexArray(vao);
|
||||
|
||||
final float[] verts = {
|
||||
0f, 0f, 0f,
|
||||
0f, 1f, 0f,
|
||||
1f, 0f, 0f,
|
||||
1f, 1f, 0f
|
||||
};
|
||||
final FloatBuffer vertBuf = BufferUtils.createFloatBuffer(verts.length);
|
||||
vertBuf.put(verts).flip();
|
||||
|
||||
final int vbo = GL15.glGenBuffers();
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
|
||||
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vertBuf, GL15.GL_STATIC_DRAW);
|
||||
GLStateManager.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 12, 0);
|
||||
GLStateManager.glEnableVertexAttribArray(0);
|
||||
|
||||
FeedbackManager.processDrawArrays(GL11.GL_QUAD_STRIP, 0, 4);
|
||||
|
||||
final int count = FeedbackManager.glRenderMode(GL11.GL_RENDER);
|
||||
|
||||
assertEquals(10, count, "Quad strip in GL_2D should produce 10 floats");
|
||||
assertEquals(GL11.GL_POLYGON_TOKEN, buf.get(0), 0.001f);
|
||||
assertEquals(4.0f, buf.get(1), 0.001f);
|
||||
assertEquals(400.0f, buf.get(2), 0.01f);
|
||||
assertEquals(300.0f, buf.get(3), 0.01f);
|
||||
assertEquals(400.0f, buf.get(4), 0.01f);
|
||||
assertEquals(600.0f, buf.get(5), 0.01f);
|
||||
assertEquals(800.0f, buf.get(6), 0.01f);
|
||||
assertEquals(600.0f, buf.get(7), 0.01f);
|
||||
assertEquals(800.0f, buf.get(8), 0.01f);
|
||||
assertEquals(300.0f, buf.get(9), 0.01f);
|
||||
|
||||
GLStateManager.glDisableVertexAttribArray(0);
|
||||
GLStateManager.glBindVertexArray(0);
|
||||
GL15.glDeleteBuffers(vbo);
|
||||
GLStateManager.glDeleteVertexArrays(vao);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIdentityTransform_viewportMapping() {
|
||||
final FloatBuffer buf = BufferUtils.createFloatBuffer(64);
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
package com.gtnewhorizons.angelica.glsm.redirect;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.Handle;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.objectweb.asm.tree.InsnNode;
|
||||
import org.objectweb.asm.tree.InvokeDynamicInsnNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class GLSMRedirectorTest {
|
||||
|
||||
private static final String GLSM = GLSMRedirector.getTargetClassName();
|
||||
|
||||
private static final Handle LAMBDA_METAFACTORY = new Handle(
|
||||
Opcodes.H_INVOKESTATIC,
|
||||
"java/lang/invoke/LambdaMetafactory",
|
||||
"metafactory",
|
||||
"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;"
|
||||
+ "Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)"
|
||||
+ "Ljava/lang/invoke/CallSite;",
|
||||
false);
|
||||
|
||||
private static ClassNode makeClassWithInvokeDynamic(Handle implHandle) {
|
||||
final ClassNode cn = new ClassNode();
|
||||
cn.version = Opcodes.V1_8;
|
||||
cn.access = Opcodes.ACC_PUBLIC;
|
||||
cn.name = "com/example/TestClass";
|
||||
cn.superName = "java/lang/Object";
|
||||
cn.methods = new ArrayList<>();
|
||||
|
||||
final MethodNode mn = new MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "test", "()V", null, null);
|
||||
mn.instructions.add(new InvokeDynamicInsnNode(
|
||||
"run",
|
||||
"()Ljava/lang/Runnable;",
|
||||
LAMBDA_METAFACTORY,
|
||||
Type.getType("()V"),
|
||||
implHandle,
|
||||
Type.getType("()V")));
|
||||
mn.instructions.add(new InsnNode(Opcodes.RETURN));
|
||||
cn.methods.add(mn);
|
||||
|
||||
return cn;
|
||||
}
|
||||
|
||||
private static Handle getResultHandle(ClassNode cn) {
|
||||
final InvokeDynamicInsnNode dyn = (InvokeDynamicInsnNode) cn.methods.get(0).instructions.get(0);
|
||||
return (Handle) dyn.bsmArgs[1];
|
||||
}
|
||||
|
||||
@Test
|
||||
void invokeDynamicGL11HandleIsRedirected() {
|
||||
final Handle impl = new Handle(Opcodes.H_INVOKESTATIC, "org/lwjgl/opengl/GL11", "glPopMatrix", "()V", false);
|
||||
final ClassNode cn = makeClassWithInvokeDynamic(impl);
|
||||
|
||||
final boolean changed = new GLSMRedirector().transformClassNode("com.example.TestClass", cn);
|
||||
|
||||
assertTrue(changed);
|
||||
final Handle result = getResultHandle(cn);
|
||||
assertEquals(GLSM, result.getOwner());
|
||||
assertEquals("glPopMatrix", result.getName());
|
||||
assertEquals("()V", result.getDesc());
|
||||
assertEquals(Opcodes.H_INVOKESTATIC, result.getTag());
|
||||
}
|
||||
|
||||
@Test
|
||||
void invokeDynamicNamedClassHandleIsRedirected() {
|
||||
final Handle impl = new Handle(Opcodes.H_INVOKESTATIC, "org/lwjgl/opengl/EXTBlendFuncSeparate", "glBlendFuncSeparateEXT", "(IIII)V", false);
|
||||
final ClassNode cn = makeClassWithInvokeDynamic(impl);
|
||||
|
||||
final boolean changed = new GLSMRedirector().transformClassNode("com.example.TestClass", cn);
|
||||
|
||||
assertTrue(changed);
|
||||
final Handle result = getResultHandle(cn);
|
||||
assertEquals(GLSM, result.getOwner());
|
||||
assertEquals("tryBlendFuncSeparate", result.getName());
|
||||
assertEquals("(IIII)V", result.getDesc());
|
||||
}
|
||||
|
||||
@Test
|
||||
void invokeDynamicNonGLHandleIsNotTouched() {
|
||||
final Handle impl = new Handle(Opcodes.H_INVOKESTATIC, "java/lang/System", "currentTimeMillis", "()J", false);
|
||||
final ClassNode cn = makeClassWithInvokeDynamic(impl);
|
||||
|
||||
final boolean changed = new GLSMRedirector().transformClassNode("com.example.TestClass", cn);
|
||||
|
||||
assertFalse(changed);
|
||||
final Handle result = getResultHandle(cn);
|
||||
assertEquals("java/lang/System", result.getOwner());
|
||||
assertEquals("currentTimeMillis", result.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void invokeDynamicUnknownGLMethodIsNotTouched() {
|
||||
final Handle impl = new Handle(Opcodes.H_INVOKESTATIC, "org/lwjgl/opengl/GL11", "glNonexistent", "()V", false);
|
||||
final ClassNode cn = makeClassWithInvokeDynamic(impl);
|
||||
|
||||
final boolean changed = new GLSMRedirector().transformClassNode("com.example.TestClass", cn);
|
||||
|
||||
assertFalse(changed);
|
||||
final Handle result = getResultHandle(cn);
|
||||
assertEquals("org/lwjgl/opengl/GL11", result.getOwner());
|
||||
}
|
||||
|
||||
@Test
|
||||
void invokeDynamicGLCVariantIsRedirected() {
|
||||
final Handle impl = new Handle(Opcodes.H_INVOKESTATIC, "org/lwjgl/opengl/GL11C", "glDrawArrays", "(III)V", false);
|
||||
final ClassNode cn = makeClassWithInvokeDynamic(impl);
|
||||
|
||||
final boolean changed = new GLSMRedirector().transformClassNode("com.example.TestClass", cn);
|
||||
|
||||
assertTrue(changed);
|
||||
final Handle result = getResultHandle(cn);
|
||||
assertEquals(GLSM, result.getOwner());
|
||||
assertEquals("glDrawArrays", result.getName());
|
||||
assertEquals("(III)V", result.getDesc());
|
||||
}
|
||||
|
||||
@Test
|
||||
void transformedClassProducesValidBytecode() {
|
||||
final Handle impl = new Handle(Opcodes.H_INVOKESTATIC, "org/lwjgl/opengl/GL11", "glPopMatrix", "()V", false);
|
||||
final ClassNode cn = makeClassWithInvokeDynamic(impl);
|
||||
|
||||
new GLSMRedirector().transformClassNode("com.example.TestClass", cn);
|
||||
|
||||
final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
|
||||
assertDoesNotThrow(() -> {
|
||||
cn.accept(cw);
|
||||
final byte[] bytes = cw.toByteArray();
|
||||
assertTrue(bytes.length > 0);
|
||||
});
|
||||
}
|
||||
}
|
||||
+10
@@ -68,6 +68,16 @@ public final class Lwjgl3GLRenderBackend extends RenderBackend {
|
||||
return "OpenGL (LWJGL3)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasContext() {
|
||||
try {
|
||||
GL.getCapabilities();
|
||||
return true;
|
||||
} catch (IllegalStateException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() { return 50; }
|
||||
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
package com.gtnewhorizons.angelica;
|
||||
|
||||
import com.gtnewhorizons.angelica.common.BlockError;
|
||||
import com.gtnewhorizons.angelica.compat.ModStatus;
|
||||
import com.gtnewhorizons.angelica.config.ConfigMigrator;
|
||||
import com.gtnewhorizons.angelica.proxy.CommonProxy;
|
||||
import com.gtnewhorizons.angelica.utils.AnimationMode;
|
||||
import com.gtnewhorizons.angelica.utils.ManagedEnum;
|
||||
import cpw.mods.fml.common.Mod;
|
||||
import cpw.mods.fml.common.SidedProxy;
|
||||
import cpw.mods.fml.common.event.FMLInitializationEvent;
|
||||
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
|
||||
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
|
||||
import me.jellysquid.mods.sodium.client.gui.SodiumGameOptions;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
@@ -32,32 +26,19 @@ import static com.gtnewhorizons.angelica.AngelicaMod.MOD_ID;
|
||||
acceptableRemoteVersions = "*",
|
||||
guiFactory = "com.gtnewhorizons.angelica.config.AngelicaGuiConfigFactory")
|
||||
public class AngelicaMod {
|
||||
|
||||
public static final String MOD_ID = "angelica";
|
||||
public static final Logger LOGGER = LogManager.getLogger("Angelica");
|
||||
public static final boolean lwjglDebug = Boolean.getBoolean("org.lwjgl.util.Debug");
|
||||
|
||||
private static SodiumGameOptions CONFIG;
|
||||
|
||||
public static SodiumGameOptions options() {
|
||||
if (CONFIG == null) {
|
||||
CONFIG = SodiumGameOptions.load(ConfigMigrator.handleConfigMigration("angelica-options.json"));
|
||||
}
|
||||
return CONFIG;
|
||||
}
|
||||
|
||||
@SidedProxy(clientSide = "com.gtnewhorizons.angelica.proxy.ClientProxy", serverSide = "com.gtnewhorizons.angelica.proxy.CommonProxy")
|
||||
@SidedProxy(
|
||||
clientSide = "com.gtnewhorizons.angelica.proxy.ClientProxy",
|
||||
serverSide = "com.gtnewhorizons.angelica.proxy.CommonProxy")
|
||||
public static CommonProxy proxy;
|
||||
|
||||
public static final boolean lwjglDebug = Boolean.parseBoolean(System.getProperty("org.lwjgl.util.Debug", "false"));
|
||||
|
||||
public static final ManagedEnum<AnimationMode> animationsMode = new ManagedEnum<>(AnimationMode.VISIBLE_ONLY);
|
||||
|
||||
public static BlockError blockError;
|
||||
|
||||
@Mod.EventHandler
|
||||
public void preInit(FMLPreInitializationEvent event) {
|
||||
ModStatus.preInit();
|
||||
proxy.preInit(event);
|
||||
blockError = new BlockError();
|
||||
}
|
||||
|
||||
@Mod.EventHandler
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
package com.gtnewhorizons.angelica.api;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.redirect.GLSMRedirector;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.TreeSet;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Public API for querying Angelica's GL call redirections.
|
||||
* <p>
|
||||
* Angelica's bytecode transformer redirects GL calls (e.g., {@code GL11.glPushMatrix()}) to
|
||||
* {@link com.gtnewhorizons.angelica.glsm.GLStateManager GLStateManager} for state tracking and
|
||||
* core profile compatibility. This works for normal Java bytecode loaded through the Forge classloader,
|
||||
* but callers that bypass class transformation (e.g., Nashorn/script engines, reflection, MethodHandles)
|
||||
* need to perform their own redirection.
|
||||
* <p>
|
||||
* This class provides the redirect mapping data and a precompiled regex pattern for transforming
|
||||
* script source text before evaluation.
|
||||
*
|
||||
* <h3>Example: transforming a Nashorn script before eval</h3>
|
||||
* Given a script that uses {@code importPackage(Packages.org.lwjgl.opengl)} and calls
|
||||
* {@code GL11.glPushMatrix()}, the text transformation rewrites those calls before evaluation:
|
||||
* <pre>{@code
|
||||
* // Make GLStateManager available to the script -- either via importPackage:
|
||||
* script = "importPackage(Packages.com.gtnewhorizons.angelica.glsm);\n" + script;
|
||||
* // ... or via Java.type for an explicit binding:
|
||||
* // script = "var GLStateManager = Java.type('" + GLRedirects.TARGET_CLASS + "');\n" + script;
|
||||
*
|
||||
* // Rewrite: GL11.glPushMatrix() -> GLStateManager.glPushMatrix()
|
||||
* script = GLRedirects.getMethodRedirectPattern().matcher(script).replaceAll(mr -> {
|
||||
* String target = GLRedirects.getTargetMethodName(mr.group(0));
|
||||
* return target != null ? "GLStateManager." + target : mr.group(0);
|
||||
* });
|
||||
*
|
||||
* engine.eval(script);
|
||||
* }</pre>
|
||||
*/
|
||||
public final class GLRedirects {
|
||||
/** Fully qualified name of the GLStateManager class that all methods redirect to. */
|
||||
@SuppressWarnings("unused")
|
||||
public static final String TARGET_CLASS = "com.gtnewhorizons.angelica.glsm.GLStateManager";
|
||||
|
||||
private static final String SHORT_GL_PREFIX;
|
||||
private static final Map<String, Map<String, String>> NAMED_CLASS_SHORT_NAME_MAP;
|
||||
private static final Map<String, String> GL_PREFIX_METHOD_REDIRECTS;
|
||||
private static final Pattern METHOD_REDIRECT_PATTERN;
|
||||
|
||||
static {
|
||||
SHORT_GL_PREFIX = buildShortGLPrefix();
|
||||
NAMED_CLASS_SHORT_NAME_MAP = buildNamedClassShortNameMap();
|
||||
GL_PREFIX_METHOD_REDIRECTS = GLSMRedirector.getGLPrefixMethodRedirects();
|
||||
METHOD_REDIRECT_PATTERN = buildMethodRedirectPattern();
|
||||
}
|
||||
|
||||
private GLRedirects() {}
|
||||
|
||||
/**
|
||||
* Returns a precompiled pattern that matches redirected {@code ClassName.methodName} references
|
||||
* using short (simple) class names, as they might typically appear in script text.
|
||||
*
|
||||
* @return compiled regex pattern
|
||||
*/
|
||||
public static Pattern getMethodRedirectPattern() {
|
||||
return METHOD_REDIRECT_PATTERN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up the GLStateManager target method name for a short-name reference.
|
||||
*
|
||||
* @param classAndMethod short class name and method, e.g., {@code "GL11.glPushMatrix"}
|
||||
* @return the target method name on GLStateManager (e.g., {@code "glPushMatrix"}), or {@code null} if this reference is not redirected
|
||||
*/
|
||||
public static String getTargetMethodName(String classAndMethod) {
|
||||
final int dot = classAndMethod.indexOf('.');
|
||||
if (dot < 0) return null;
|
||||
|
||||
final String className = classAndMethod.substring(0, dot);
|
||||
final String methodName = classAndMethod.substring(dot + 1);
|
||||
|
||||
final Map<String, String> classRedirects = NAMED_CLASS_SHORT_NAME_MAP.get(className);
|
||||
if (classRedirects != null) {
|
||||
return classRedirects.get(methodName);
|
||||
}
|
||||
|
||||
if (className.startsWith(SHORT_GL_PREFIX)) {
|
||||
return GL_PREFIX_METHOD_REDIRECTS.get(methodName);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String buildShortGLPrefix() {
|
||||
final String glPrefix = GLSMRedirector.getGLPrefix();
|
||||
return glPrefix.substring(glPrefix.lastIndexOf('/') + 1);
|
||||
}
|
||||
|
||||
private static Map<String, Map<String, String>> buildNamedClassShortNameMap() {
|
||||
final Map<String, Map<String, String>> named = new HashMap<>();
|
||||
for (final var entry : GLSMRedirector.getNamedClassMethodRedirects().entrySet()) {
|
||||
final String internalName = entry.getKey();
|
||||
final String shortName = internalName.substring(internalName.lastIndexOf('/') + 1);
|
||||
named.put(shortName, entry.getValue());
|
||||
}
|
||||
return named;
|
||||
}
|
||||
|
||||
private static Pattern buildMethodRedirectPattern() {
|
||||
final TreeSet<String> alternatives = new TreeSet<>();
|
||||
alternatives.add(Pattern.quote(SHORT_GL_PREFIX) + "\\w+");
|
||||
for (final String shortName : NAMED_CLASS_SHORT_NAME_MAP.keySet()) {
|
||||
alternatives.add(Pattern.quote(shortName));
|
||||
}
|
||||
final String classAlt = String.join("|", alternatives);
|
||||
return Pattern.compile("\\b(" + classAlt + ")\\.\\w+\\b");
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -334,6 +334,7 @@ public class BatchingFontRenderer {
|
||||
batchCommands.sort(FontDrawCmd.DRAW_ORDER_COMPARATOR);
|
||||
|
||||
final boolean isTextureEnabledBefore = GLStateManager.glIsEnabled(GL11.GL_TEXTURE_2D);
|
||||
final boolean isBlendEnabledBefore = GLStateManager.glIsEnabled(GL11.GL_BLEND);
|
||||
final int boundTextureBefore = GLStateManager.glGetInteger(GL11.GL_TEXTURE_BINDING_2D);
|
||||
boolean textureChanged = false;
|
||||
|
||||
@@ -417,6 +418,9 @@ public class BatchingFontRenderer {
|
||||
if (isTextureEnabledBefore) {
|
||||
GLStateManager.glEnable(GL11.GL_TEXTURE_2D);
|
||||
}
|
||||
if (!isBlendEnabledBefore) {
|
||||
GLStateManager.disableBlend();
|
||||
}
|
||||
if (textureChanged) {
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, boundTextureBefore);
|
||||
}
|
||||
|
||||
+3
-5
@@ -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 =====================
|
||||
|
||||
+47
-20
@@ -2,6 +2,7 @@ package com.gtnewhorizons.angelica.client.rendering;
|
||||
|
||||
import com.github.bsideup.jabel.Desugar;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.DirectTessellator;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.ITessellatorInstance;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFlags;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFormat;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
@@ -33,10 +34,30 @@ class DeferredBatchTessellator extends DirectTessellator {
|
||||
private final Vector3f scratch = new Vector3f();
|
||||
private Matrix4fc currentTransform;
|
||||
|
||||
private Tessellator parentTessellator;
|
||||
private boolean inIntercept;
|
||||
|
||||
DeferredBatchTessellator(ByteBuffer buffer) {
|
||||
super(buffer, false); // deleteAfter=false: keep buffer across resets for reuse
|
||||
}
|
||||
|
||||
void setParentTessellator(Tessellator parent) {
|
||||
this.parentTessellator = parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int draw() {
|
||||
if (!inIntercept) {
|
||||
final Tessellator parent = parentTessellator;
|
||||
if (parent != null && parent.isDrawing) {
|
||||
interceptDraw(parent);
|
||||
((ITessellatorInstance) parent).discard();
|
||||
}
|
||||
}
|
||||
isDrawing = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long writeVertexData(VertexFormat format, int[] rawBuffer, int rawBufferIndex) {
|
||||
if (currentTransform != null) {
|
||||
@@ -53,27 +74,32 @@ class DeferredBatchTessellator extends DirectTessellator {
|
||||
|
||||
@Override
|
||||
protected int interceptDraw(Tessellator tess) {
|
||||
// Compute delta: if current MV differs from default, pre-transform vertices
|
||||
final Matrix4f currentMV = GLStateManager.getModelViewMatrix();
|
||||
if (!currentMV.equals(defaultModelview)) {
|
||||
defaultModelviewInverse.mul(currentMV, deltaMatrix);
|
||||
this.currentTransform = deltaMatrix;
|
||||
} else {
|
||||
this.currentTransform = null;
|
||||
inIntercept = true;
|
||||
try {
|
||||
// Compute delta: if current MV differs from default, pre-transform vertices
|
||||
final Matrix4f currentMV = GLStateManager.getModelViewMatrix();
|
||||
if (!currentMV.equals(defaultModelview)) {
|
||||
defaultModelviewInverse.mul(currentMV, deltaMatrix);
|
||||
this.currentTransform = deltaMatrix;
|
||||
} else {
|
||||
this.currentTransform = null;
|
||||
}
|
||||
|
||||
final int byteOffsetBefore = bufferLimit();
|
||||
final int vertCount = tess.vertexCount;
|
||||
final int drawMode = tess.drawMode;
|
||||
final int flags = VertexFlags.convertToFlags(tess.hasTexture, tess.hasColor, tess.hasNormals, tess.hasBrightness);
|
||||
final long stateKey = DeferredDrawBatcher.captureStateKey();
|
||||
|
||||
final int result = super.interceptDraw(tess); // repacks int[] -> ByteBuffer + transforms if vertexTransform set
|
||||
|
||||
final int byteOffsetAfter = bufferLimit();
|
||||
ranges.add(new DrawRange(stateKey, byteOffsetBefore, byteOffsetAfter - byteOffsetBefore, vertCount, drawMode, flags));
|
||||
this.currentTransform = null; // clear for next draw
|
||||
return result;
|
||||
} finally {
|
||||
inIntercept = false;
|
||||
}
|
||||
|
||||
final int byteOffsetBefore = bufferLimit();
|
||||
final int vertCount = tess.vertexCount;
|
||||
final int drawMode = tess.drawMode;
|
||||
final int flags = VertexFlags.convertToFlags(tess.hasTexture, tess.hasColor, tess.hasNormals, tess.hasBrightness);
|
||||
final long stateKey = DeferredDrawBatcher.captureStateKey();
|
||||
|
||||
final int result = super.interceptDraw(tess); // repacks int[] → ByteBuffer + transforms if vertexTransform set
|
||||
|
||||
final int byteOffsetAfter = bufferLimit();
|
||||
ranges.add(new DrawRange(stateKey, byteOffsetBefore, byteOffsetAfter - byteOffsetBefore, vertCount, drawMode, flags));
|
||||
this.currentTransform = null; // clear for next draw
|
||||
return result;
|
||||
}
|
||||
|
||||
List<DrawRange> getRanges() { return ranges; }
|
||||
@@ -86,6 +112,7 @@ class DeferredBatchTessellator extends DirectTessellator {
|
||||
|
||||
@Override
|
||||
protected void onRemovedFromStack() {
|
||||
parentTessellator = null;
|
||||
clearRanges();
|
||||
super.onRemovedFromStack(); // calls reset(), keeps baseBuffer (deleteAfter=false)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.gtnewhorizons.angelica.client.rendering;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.TessellatorManager;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import lombok.Getter;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import java.util.Comparator;
|
||||
@@ -37,6 +38,7 @@ public class DeferredDrawBatcher {
|
||||
batchTessellator = new DeferredBatchTessellator(memAlloc(INITIAL_BUFFER_SIZE));
|
||||
}
|
||||
batchTessellator.clearRanges();
|
||||
batchTessellator.setParentTessellator(Tessellator.instance);
|
||||
batchTessellator.snapshotDefaultModelview();
|
||||
TessellatorManager.startCapturingDirect(batchTessellator);
|
||||
}
|
||||
@@ -99,10 +101,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;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
package com.gtnewhorizons.angelica.client.rendering;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.RenderSystem;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.GLSMHooks;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import net.coderbot.iris.gl.state.StateUpdateNotifiers;
|
||||
import net.minecraft.client.renderer.texture.AbstractTexture;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -15,11 +13,15 @@ public class TextureTracker {
|
||||
*/
|
||||
|
||||
public static final TextureTracker INSTANCE = new TextureTracker();
|
||||
|
||||
|
||||
private static Runnable bindTextureListener;
|
||||
|
||||
static {
|
||||
StateUpdateNotifiers.bindTextureNotifier = listener -> bindTextureListener = listener;
|
||||
}
|
||||
|
||||
private final Int2ObjectMap<AbstractTexture> textures = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
private boolean lockBindCallback;
|
||||
|
||||
private TextureTracker() {
|
||||
}
|
||||
|
||||
@@ -31,23 +33,13 @@ public class TextureTracker {
|
||||
public AbstractTexture getTexture(int id) {
|
||||
return textures.get(id);
|
||||
}
|
||||
|
||||
public void onBindTexture(int id) {
|
||||
if (lockBindCallback) {
|
||||
return;
|
||||
}
|
||||
if (GLStateManager.getActiveTextureUnit() == 0) {
|
||||
lockBindCallback = true;
|
||||
if (GLSMHooks.TEXTURE_BIND.hasListeners()) {
|
||||
GLSMHooks.textureBindEvent.textureId = id;
|
||||
GLSMHooks.TEXTURE_BIND.post(GLSMHooks.textureBindEvent);
|
||||
}
|
||||
// Reset texture state
|
||||
RenderSystem.bindTextureToUnit(0, id);
|
||||
lockBindCallback = false;
|
||||
|
||||
public void onBindTexture() {
|
||||
if (bindTextureListener != null) {
|
||||
bindTextureListener.run();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void onDeleteTexture(int id) {
|
||||
textures.remove(id);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ public class ModStatus {
|
||||
public static boolean isThaumicHorizonsLoaded;
|
||||
public static boolean isBaublesLoaded;
|
||||
public static boolean isFluidLoggedLoaded;
|
||||
public static boolean isBOPLoaded;
|
||||
|
||||
public static void preInit() {
|
||||
if (Loader.isModLoaded("backhand")) {
|
||||
@@ -45,6 +46,7 @@ public class ModStatus {
|
||||
isFluidLoggedLoaded = Loader.isModLoaded("fluidlogged");
|
||||
|
||||
isHoloInventoryLoaded = Loader.isModLoaded("holoinventory");
|
||||
isBOPLoaded = Loader.isModLoaded("BiomesOPlenty");
|
||||
|
||||
// remove compat with original release of BG2
|
||||
if (isBattlegearLoaded){
|
||||
|
||||
+9
-10
@@ -1,34 +1,33 @@
|
||||
package com.gtnewhorizons.angelica.compat.bettercrashes;
|
||||
|
||||
import com.gtnewhorizons.angelica.AngelicaMod;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.mixins.interfaces.IRenderGlobalExt;
|
||||
import cpw.mods.fml.common.Optional;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import vfyjxf.bettercrashes.utils.StateManager;
|
||||
|
||||
import static com.gtnewhorizons.angelica.loading.AngelicaTweaker.LOGGER;
|
||||
|
||||
@Optional.Interface(modid = "angelica", iface = "vfyjxf.bettercrashes.utils.StateManager.IResettable")
|
||||
public class BetterCrashesCompat implements StateManager.IResettable {
|
||||
|
||||
private static BetterCrashesCompat INSTANCE;
|
||||
|
||||
public BetterCrashesCompat() {
|
||||
AngelicaMod.LOGGER.info("BetterCrashesCompat initialized");
|
||||
this.register();
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
if (INSTANCE == null) {
|
||||
INSTANCE = new BetterCrashesCompat();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public BetterCrashesCompat() {
|
||||
LOGGER.info("BetterCrashesCompat initialized");
|
||||
this.register();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetState() {
|
||||
LOGGER.info("Reloading SodiumRenderer");
|
||||
AngelicaMod.LOGGER.info("Reloading SodiumRenderer");
|
||||
((IRenderGlobalExt) Minecraft.getMinecraft().renderGlobal).angelica$reload();
|
||||
LOGGER.info("Resetting GLStateManager");
|
||||
AngelicaMod.LOGGER.info("Resetting GLStateManager");
|
||||
GLStateManager.reset();
|
||||
}
|
||||
}
|
||||
@@ -239,6 +239,36 @@ 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("Narrow Ears transformer exclusions to allow GL redirection")
|
||||
@Config.DefaultBoolean(true)
|
||||
@Config.RequiresMcRestart
|
||||
public boolean narrowEars;
|
||||
}
|
||||
|
||||
@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;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.gtnewhorizons.angelica.iris;
|
||||
|
||||
import com.gtnewhorizons.angelica.client.rendering.TextureTracker;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.DeferredAlphaHandler;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.DeferredBlendHandler;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.DeferredDepthColorHandler;
|
||||
@@ -10,13 +11,29 @@ import net.coderbot.iris.gl.blending.AlphaTestStorage;
|
||||
import net.coderbot.iris.gl.blending.BlendModeStorage;
|
||||
import net.coderbot.iris.gl.blending.DepthColorStorage;
|
||||
import net.coderbot.iris.gl.program.ProgramUniforms;
|
||||
import net.coderbot.iris.gl.state.StateUpdateNotifiers;
|
||||
import net.coderbot.iris.pipeline.DeferredWorldRenderingPipeline;
|
||||
import net.coderbot.iris.pipeline.WorldRenderingPipeline;
|
||||
import net.coderbot.iris.samplers.IrisSamplers;
|
||||
import net.coderbot.iris.texture.pbr.PBRTextureManager;
|
||||
import net.coderbot.iris.vertices.ImmediateState;
|
||||
|
||||
public class IrisGLSMBridge {
|
||||
|
||||
|
||||
private static Runnable blendFuncListener = null;
|
||||
private static Runnable fogModeListener = null;
|
||||
private static Runnable fogStartListener = null;
|
||||
private static Runnable fogEndListener = null;
|
||||
private static Runnable fogDensityListener = null;
|
||||
|
||||
static {
|
||||
StateUpdateNotifiers.blendFuncNotifier = listener -> blendFuncListener = listener;
|
||||
StateUpdateNotifiers.fogModeNotifier = listener -> fogModeListener = listener;
|
||||
StateUpdateNotifiers.fogStartNotifier = listener -> fogStartListener = listener;
|
||||
StateUpdateNotifiers.fogEndNotifier = listener -> fogEndListener = listener;
|
||||
StateUpdateNotifiers.fogDensityNotifier = listener -> fogDensityListener = listener;
|
||||
}
|
||||
|
||||
public static void register() {
|
||||
IrisSamplers.initRenderer();
|
||||
GLSMHooks.blendHandler = new DeferredBlendHandler() {
|
||||
@@ -74,9 +91,25 @@ public class IrisGLSMBridge {
|
||||
DepthColorStorage.deferColorMask(r, g, b, a);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
GLSMHooks.BLEND_FUNC_CHANGE.addListener(event -> {
|
||||
if (Iris.enabled) {
|
||||
if (blendFuncListener != null) blendFuncListener.run();
|
||||
}
|
||||
});
|
||||
|
||||
GLSMHooks.FOG_STATE_CHANGE.addListener(event -> {
|
||||
if (Iris.enabled) {
|
||||
if (fogModeListener != null) fogModeListener.run();
|
||||
if (fogStartListener != null) fogStartListener.run();
|
||||
if (fogEndListener != null) fogEndListener.run();
|
||||
if (fogDensityListener != null) fogDensityListener.run();
|
||||
}
|
||||
});
|
||||
|
||||
GLSMHooks.TEXTURE_BIND.addListener(event -> {
|
||||
if (Iris.enabled) {
|
||||
TextureTracker.INSTANCE.onBindTexture();
|
||||
final WorldRenderingPipeline pipeline = Iris.getPipelineManager().getPipelineNullable();
|
||||
if (pipeline != null) {
|
||||
pipeline.onBindTexture(event.textureId);
|
||||
@@ -114,10 +147,10 @@ public class IrisGLSMBridge {
|
||||
if (!drp.shouldOverrideShaders()) return;
|
||||
if (drp.getActivePassProgramId() == -1) return;
|
||||
|
||||
if (DepthColorStorage.isOwnedProgram(event.newProgram)) {
|
||||
if (!ImmediateState.isRenderingLevel || DepthColorStorage.isOwnedProgram(event.newProgram)) {
|
||||
DepthColorStorage.unlockDepthColor();
|
||||
} else {
|
||||
DepthColorStorage.disableDepthColor();
|
||||
drp.onModProgramOverride();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
package com.gtnewhorizons.angelica.loading;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.config.ConfigException;
|
||||
import com.gtnewhorizon.gtnhlib.config.ConfigurationManager;
|
||||
import com.gtnewhorizon.gtnhmixins.IEarlyMixinLoader;
|
||||
import com.gtnewhorizon.gtnhmixins.builders.IMixins;
|
||||
import com.gtnewhorizon.gtnhmixins.builders.ITransformers;
|
||||
import com.gtnewhorizons.angelica.config.AngelicaConfig;
|
||||
import com.gtnewhorizons.angelica.config.CompatConfig;
|
||||
import com.gtnewhorizons.angelica.config.FontConfig;
|
||||
import com.gtnewhorizons.angelica.loading.fml.compat.CompatHandlers;
|
||||
import com.gtnewhorizons.angelica.mixins.Mixins;
|
||||
import com.gtnewhorizons.retrofuturabootstrap.SharedConfig;
|
||||
import cpw.mods.fml.relauncher.FMLLaunchHandler;
|
||||
import cpw.mods.fml.relauncher.IFMLLoadingPlugin;
|
||||
import jss.notfine.asm.AsmTransformers;
|
||||
import jss.notfine.asm.mappings.Namer;
|
||||
import jss.notfine.config.MCPatcherForgeConfig;
|
||||
import jss.notfine.config.NotFineConfig;
|
||||
import net.minecraft.launchwrapper.Launch;
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.core.LoggerContext;
|
||||
import org.apache.logging.log4j.core.config.Configuration;
|
||||
import org.apache.logging.log4j.core.config.LoggerConfig;
|
||||
import org.spongepowered.asm.launch.GlobalProperties;
|
||||
import org.spongepowered.asm.service.mojang.MixinServiceLaunchWrapper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
// this is not the real IFMLLoadingPlugin, if you put any annotations
|
||||
// here it won't do anything, that's why we register transformer
|
||||
// exclusions manually in the constructor
|
||||
public final class AngelicaClientTweaker implements IFMLLoadingPlugin, IEarlyMixinLoader {
|
||||
|
||||
public static final Logger LOGGER = LogManager.getLogger("Angelica");
|
||||
private static Boolean OBF_ENV;
|
||||
private String[] transformerClasses;
|
||||
|
||||
public AngelicaClientTweaker() {
|
||||
Launch.classLoader.addTransformerExclusion("jss.notfine.asm");
|
||||
Launch.classLoader.addTransformerExclusion("com.gtnewhorizons.angelica.loading");
|
||||
Launch.classLoader.addTransformerExclusion("com.gtnewhorizons.angelica.glsm.GLStateManager");
|
||||
|
||||
if (Launch.blackboard.getOrDefault("angelica.rfbPluginLoaded", Boolean.FALSE) == Boolean.TRUE) {
|
||||
addLwjgl3ifyExclusions();
|
||||
}
|
||||
|
||||
try {
|
||||
// Angelica Config
|
||||
ConfigurationManager.registerConfig(AngelicaConfig.class);
|
||||
ConfigurationManager.registerConfig(CompatConfig.class);
|
||||
ConfigurationManager.registerConfig(FontConfig.class);
|
||||
MCPatcherForgeConfig.registerConfig();
|
||||
final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
|
||||
final Configuration config = ctx.getConfiguration();
|
||||
final LoggerConfig loggerConfig = config.getLoggerConfig(LogManager.ROOT_LOGGER_NAME);
|
||||
if (AngelicaConfig.enableDebugLogging) {
|
||||
loggerConfig.setLevel(Level.DEBUG);
|
||||
}
|
||||
ctx.updateLoggers();
|
||||
|
||||
// Debug features
|
||||
AngelicaConfig.enableTestBlocks = Boolean.getBoolean("angelica.enableTestBlocks");
|
||||
|
||||
} catch (ConfigException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
verifyDependencies();
|
||||
|
||||
// Register a scoped redirector early so classes prematurely loaded by other coremods during discovery/injectData
|
||||
// (e.g. Mycelium using HookLoader.class.getName()) still get GL calls redirected to GLSM. Only targets specific mod
|
||||
// packages to avoid interfering with mixin delegation on game classes. AngelicaLateTweaker removes this registration once
|
||||
// mixins are setup.
|
||||
if (FMLLaunchHandler.side().isClient()) {
|
||||
final boolean rfbLoaded = Launch.blackboard.getOrDefault("angelica.rfbPluginLoaded", Boolean.FALSE) == Boolean.TRUE;
|
||||
if (!rfbLoaded) {
|
||||
Launch.classLoader.registerTransformer("com.gtnewhorizons.angelica.loading.fml.transformers.EarlyRedirectorTransformer");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void addLwjgl3ifyExclusions() {
|
||||
final var handle = SharedConfig.getRfbTransformers().stream()
|
||||
.filter(transformer -> transformer.id().equals("lwjgl3ify:redirect"))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (handle != null) {
|
||||
handle.exclusions().add("org.embeddedt.embeddium");
|
||||
handle.exclusions().add("org.taumc.celeritas");
|
||||
handle.exclusions().add("com.mitchej123.lwjgl.lwjgl3");
|
||||
handle.exclusions().add("com.mitchej123.glsm");
|
||||
handle.exclusions().add("com.gtnewhorizons.angelica.lwjgl3");
|
||||
handle.exclusions().add("com.gtnewhorizons.angelica.vulkan");
|
||||
}
|
||||
}
|
||||
|
||||
private static void verifyDependencies() {
|
||||
// Check for fastutil (bundled with GTNHLib since 0.2.1)
|
||||
if (AngelicaTweaker.class.getResource("/it/unimi/dsi/fastutil/ints/Int2ObjectMap.class") == null) {
|
||||
throw new RuntimeException("Missing dependency: Angelica requires GTNHLib! Download: https://modrinth.com/mod/gtnhlib");
|
||||
}
|
||||
|
||||
// Check for PrimitiveExtractor/cel.model classes (added in GTNHLib 0.8.21)
|
||||
if (AngelicaTweaker.class.getResource("/com/gtnewhorizon/gtnhlib/client/renderer/PrimitiveExtractor.class") == null) {
|
||||
throw new RuntimeException("GTNHLib is outdated: Angelica requires GTNHLib 0.8.21 or newer! Download: https://modrinth.com/mod/gtnhlib");
|
||||
}
|
||||
|
||||
// Check for jvmdowngrader stubs (bundled with GTNHLib since 0.9.0)
|
||||
if (AngelicaTweaker.class.getResource("/xyz/wagyourtail/jvmdg/exc/MissingStubError.class") == null) {
|
||||
throw new RuntimeException("GTNHLib is outdated: Angelica requires GTNHLib 0.9.0 or newer! Download: https://modrinth.com/mod/gtnhlib");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getASMTransformerClass() {
|
||||
if (transformerClasses == null) {
|
||||
final List<String> transformers = new ArrayList<>();
|
||||
transformers.addAll(CompatHandlers.getTransformers());
|
||||
// Add NotFine transformers
|
||||
final List<String> notFineTransformers = Arrays.asList(ITransformers.getTransformers(AsmTransformers.class));
|
||||
if (!notFineTransformers.isEmpty()) Namer.initNames();
|
||||
transformers.addAll(notFineTransformers);
|
||||
transformerClasses = transformers.toArray(new String[0]);
|
||||
}
|
||||
return transformerClasses;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModContainerClass() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSetupClass() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@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);
|
||||
narrowTransformerConfig("Ears", AngelicaConfig.transformerCompat.narrowEars);
|
||||
|
||||
tweaks.add("com.gtnewhorizons.angelica.loading.fml.tweakers.IncompatibleModsDisablerTweaker");
|
||||
if (AngelicaConfig.enableHudCaching) {
|
||||
tweaks.add("com.gtnewhorizons.angelica.loading.fml.tweakers.XaerosTransformerDisablerTweaker");
|
||||
}
|
||||
if (FMLLaunchHandler.side().isClient()) {
|
||||
// We register ITweakers that will run last in order to register
|
||||
// specific IClassTransformers that will run last in the transformer chain.
|
||||
// If we were to register them normally in getASMTransformerClass(),
|
||||
// they would be sorted at index 0 which we do not want.
|
||||
final boolean rfbLoaded = Launch.blackboard.getOrDefault("angelica.rfbPluginLoaded", Boolean.FALSE) == Boolean.TRUE;
|
||||
if (!rfbLoaded) {
|
||||
tweaks.add("com.gtnewhorizons.angelica.loading.fml.tweakers.AngelicaLateTweaker");
|
||||
if (AngelicaConfig.enableCeleritas) {
|
||||
tweaks.add("com.gtnewhorizons.angelica.loading.fml.tweakers.CeleritasLateTweaker");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 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 String getAccessTransformerClass() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMixinConfig() {
|
||||
final int v = Runtime.version().feature();
|
||||
if (v >= 21) return "mixins.angelica.early.j21.json";
|
||||
if (v >= 17) return "mixins.angelica.early.j17.json";
|
||||
return "mixins.angelica.early.json";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getMixins(Set<String> loadedCoreMods) {
|
||||
NotFineConfig.loadSettings();
|
||||
//This may be possible to handle differently or fix.
|
||||
if (loadedCoreMods.contains("cofh.asm.LoadingPlugin")) {
|
||||
MCPatcherForgeConfig.ExtendedHD.hdFont = false;
|
||||
}
|
||||
return IMixins.getEarlyMixins(Mixins.class, loadedCoreMods);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if we are in an obfuscated environment, returns false in dev environment.
|
||||
*/
|
||||
public static boolean isObfEnv() {
|
||||
if (OBF_ENV == null) {
|
||||
throw new IllegalStateException("Obfuscation state has been accessed too early!");
|
||||
}
|
||||
return OBF_ENV;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the appropriate name according to current environment's obfuscation
|
||||
*/
|
||||
public static String obf(String deobf, String obf) {
|
||||
if (OBF_ENV == null) {
|
||||
throw new IllegalStateException("Obfuscation state has been accessed too early!");
|
||||
}
|
||||
if (OBF_ENV) {
|
||||
return obf;
|
||||
}
|
||||
return deobf;
|
||||
}
|
||||
}
|
||||
@@ -1,34 +1,12 @@
|
||||
package com.gtnewhorizons.angelica.loading;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.config.ConfigException;
|
||||
import com.gtnewhorizon.gtnhlib.config.ConfigurationManager;
|
||||
import com.gtnewhorizon.gtnhmixins.IEarlyMixinLoader;
|
||||
import com.gtnewhorizon.gtnhmixins.builders.IMixins;
|
||||
import com.gtnewhorizon.gtnhmixins.builders.ITransformers;
|
||||
import com.gtnewhorizons.angelica.config.AngelicaConfig;
|
||||
import com.gtnewhorizons.angelica.config.CompatConfig;
|
||||
import com.gtnewhorizons.angelica.config.FontConfig;
|
||||
import com.gtnewhorizons.angelica.mixins.Mixins;
|
||||
import com.gtnewhorizons.angelica.loading.fml.compat.CompatHandlers;
|
||||
import cpw.mods.fml.relauncher.FMLLaunchHandler;
|
||||
import cpw.mods.fml.relauncher.IFMLLoadingPlugin;
|
||||
import jss.notfine.asm.AsmTransformers;
|
||||
import jss.notfine.asm.mappings.Namer;
|
||||
import jss.notfine.config.MCPatcherForgeConfig;
|
||||
import jss.notfine.config.NotFineConfig;
|
||||
import com.gtnewhorizons.retrofuturabootstrap.SharedConfig;
|
||||
import net.minecraft.launchwrapper.Launch;
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.core.LoggerContext;
|
||||
import org.apache.logging.log4j.core.config.Configuration;
|
||||
import org.apache.logging.log4j.core.config.LoggerConfig;
|
||||
import org.spongepowered.asm.launch.GlobalProperties;
|
||||
import org.spongepowered.asm.service.mojang.MixinServiceLaunchWrapper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -41,184 +19,76 @@ import java.util.Set;
|
||||
// They will instead use default index 0 which means they will see
|
||||
// obfuscated mappings and not SRG mappings when running outside of dev env.
|
||||
// ===============================================
|
||||
//@IFMLLoadingPlugin.SortingIndex(Integer.MAX_VALUE - 5)
|
||||
@IFMLLoadingPlugin.MCVersion("1.7.10")
|
||||
@IFMLLoadingPlugin.TransformerExclusions({
|
||||
"jss.notfine.asm",
|
||||
"com.gtnewhorizons.angelica.loading",
|
||||
"com.gtnewhorizons.angelica.glsm.GLStateManager"
|
||||
})
|
||||
public class AngelicaTweaker implements IFMLLoadingPlugin, IEarlyMixinLoader {
|
||||
|
||||
private static Boolean OBF_ENV;
|
||||
public static final Logger LOGGER = LogManager.getLogger("Angelica");
|
||||
|
||||
private String[] transformerClasses;
|
||||
private final IFMLLoadingPlugin loadingPlugin;
|
||||
private final IEarlyMixinLoader mixinLoader;
|
||||
|
||||
public AngelicaTweaker() {
|
||||
if (Launch.blackboard.getOrDefault("angelica.rfbPluginLoaded", Boolean.FALSE) == Boolean.TRUE) {
|
||||
addLwjgl3ifyExclusions();
|
||||
}
|
||||
|
||||
try {
|
||||
// Angelica Config
|
||||
ConfigurationManager.registerConfig(AngelicaConfig.class);
|
||||
ConfigurationManager.registerConfig(CompatConfig.class);
|
||||
ConfigurationManager.registerConfig(FontConfig.class);
|
||||
MCPatcherForgeConfig.registerConfig();
|
||||
final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
|
||||
final Configuration config = ctx.getConfiguration();
|
||||
final LoggerConfig loggerConfig = config.getLoggerConfig(LogManager.ROOT_LOGGER_NAME);
|
||||
if (AngelicaConfig.enableDebugLogging) {
|
||||
loggerConfig.setLevel(Level.DEBUG);
|
||||
}
|
||||
ctx.updateLoggers();
|
||||
|
||||
// Debug features
|
||||
AngelicaConfig.enableTestBlocks = Boolean.getBoolean("angelica.enableTestBlocks");
|
||||
|
||||
} catch (ConfigException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
verifyDependencies();
|
||||
|
||||
// Register a scoped redirector early so classes prematurely loaded by other coremods during discovery/injectData
|
||||
// (e.g. Mycelium using HookLoader.class.getName()) still get GL calls redirected to GLSM. Only targets specific mod
|
||||
// packages to avoid interfering with mixin delegation on game classes. AngelicaLateTweaker removes this registration once
|
||||
// mixins are setup.
|
||||
if (FMLLaunchHandler.side().isClient()) {
|
||||
final boolean rfbLoaded = Launch.blackboard.getOrDefault("angelica.rfbPluginLoaded", Boolean.FALSE) == Boolean.TRUE;
|
||||
if (!rfbLoaded) {
|
||||
Launch.classLoader.registerTransformer("com.gtnewhorizons.angelica.loading.fml.transformers.EarlyRedirectorTransformer");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void verifyDependencies() {
|
||||
// Check for fastutil (bundled with GTNHLib since 0.2.1)
|
||||
if (AngelicaTweaker.class.getResource("/it/unimi/dsi/fastutil/ints/Int2ObjectMap.class") == null) {
|
||||
throw new RuntimeException("Missing dependency: Angelica requires GTNHLib! Download: https://modrinth.com/mod/gtnhlib");
|
||||
}
|
||||
|
||||
// Check for PrimitiveExtractor/cel.model classes (added in GTNHLib 0.8.21)
|
||||
if (AngelicaTweaker.class.getResource("/com/gtnewhorizon/gtnhlib/client/renderer/PrimitiveExtractor.class") == null) {
|
||||
throw new RuntimeException("GTNHLib is outdated: Angelica requires GTNHLib 0.8.21 or newer! Download: https://modrinth.com/mod/gtnhlib");
|
||||
}
|
||||
|
||||
// Check for jvmdowngrader stubs (bundled with GTNHLib since 0.9.0)
|
||||
if (AngelicaTweaker.class.getResource("/xyz/wagyourtail/jvmdg/exc/MissingStubError.class") == null) {
|
||||
throw new RuntimeException("GTNHLib is outdated: Angelica requires GTNHLib 0.9.0 or newer! Download: https://modrinth.com/mod/gtnhlib");
|
||||
final AngelicaClientTweaker clientTweaker = new AngelicaClientTweaker();
|
||||
loadingPlugin = clientTweaker;
|
||||
mixinLoader = clientTweaker;
|
||||
} else {
|
||||
loadingPlugin = null;
|
||||
mixinLoader = null;
|
||||
LogManager.getLogger("Angelica").info("Trying to get more FPS on your server ? :kekw:");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getASMTransformerClass() {
|
||||
if (transformerClasses == null) {
|
||||
final List<String> transformers = new ArrayList<>();
|
||||
transformers.addAll(CompatHandlers.getTransformers());
|
||||
// Add NotFine transformers
|
||||
final List<String> notFineTransformers = Arrays.asList(ITransformers.getTransformers(AsmTransformers.class));
|
||||
if (!notFineTransformers.isEmpty()) Namer.initNames();
|
||||
transformers.addAll(notFineTransformers);
|
||||
transformerClasses = transformers.toArray(new String[0]);
|
||||
if (this.loadingPlugin != null) {
|
||||
return this.loadingPlugin.getASMTransformerClass();
|
||||
}
|
||||
return transformerClasses;
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModContainerClass() {
|
||||
if (this.loadingPlugin != null) {
|
||||
return this.loadingPlugin.getModContainerClass();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSetupClass() {
|
||||
if (this.loadingPlugin != null) {
|
||||
return this.loadingPlugin.getSetupClass();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@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) {
|
||||
tweaks.add("com.gtnewhorizons.angelica.loading.fml.tweakers.IncompatibleModsDisablerTweaker");
|
||||
if (AngelicaConfig.enableHudCaching) {
|
||||
tweaks.add("com.gtnewhorizons.angelica.loading.fml.tweakers.XaerosTransformerDisablerTweaker");
|
||||
}
|
||||
if (FMLLaunchHandler.side().isClient()) {
|
||||
// We register ITweakers that will run last in order to register
|
||||
// specific IClassTransformers that will run last in the transformer chain.
|
||||
// If we were to register them normally in getASMTransformerClass(),
|
||||
// they would be sorted at index 0 which we do not want.
|
||||
final boolean rfbLoaded = Launch.blackboard.getOrDefault("angelica.rfbPluginLoaded", Boolean.FALSE) == Boolean.TRUE;
|
||||
if (!rfbLoaded) {
|
||||
tweaks.add("com.gtnewhorizons.angelica.loading.fml.tweakers.AngelicaLateTweaker");
|
||||
if (AngelicaConfig.enableCeleritas) {
|
||||
tweaks.add("com.gtnewhorizons.angelica.loading.fml.tweakers.CeleritasLateTweaker");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.loadingPlugin != null) {
|
||||
this.loadingPlugin.injectData(data);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccessTransformerClass() {
|
||||
if (this.loadingPlugin != null) {
|
||||
return this.loadingPlugin.getAccessTransformerClass();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMixinConfig() {
|
||||
final int v = Runtime.version().feature();
|
||||
if (v >= 21) return "mixins.angelica.early.j21.json";
|
||||
if (v >= 17) return "mixins.angelica.early.j17.json";
|
||||
return "mixins.angelica.early.json";
|
||||
if (this.mixinLoader != null) {
|
||||
return this.mixinLoader.getMixinConfig();
|
||||
}
|
||||
return "mixins.angelica.server.json";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getMixins(Set<String> loadedCoreMods) {
|
||||
NotFineConfig.loadSettings();
|
||||
//This may be possible to handle differently or fix.
|
||||
if (loadedCoreMods.contains("cofh.asm.LoadingPlugin")) {
|
||||
MCPatcherForgeConfig.ExtendedHD.hdFont = false;
|
||||
if (this.mixinLoader != null) {
|
||||
return this.mixinLoader.getMixins(loadedCoreMods);
|
||||
}
|
||||
return IMixins.getEarlyMixins(Mixins.class, loadedCoreMods);
|
||||
}
|
||||
|
||||
private static void addLwjgl3ifyExclusions() {
|
||||
final var handle = SharedConfig.getRfbTransformers().stream()
|
||||
.filter(transformer -> transformer.id().equals("lwjgl3ify:redirect"))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (handle != null) {
|
||||
handle.exclusions().add("org.embeddedt.embeddium");
|
||||
handle.exclusions().add("org.taumc.celeritas");
|
||||
handle.exclusions().add("com.mitchej123.lwjgl.lwjgl3");
|
||||
handle.exclusions().add("com.mitchej123.glsm");
|
||||
handle.exclusions().add("com.gtnewhorizons.angelica.lwjgl3");
|
||||
handle.exclusions().add("com.gtnewhorizons.angelica.vulkan");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if we are in an obfuscated environment, returns false in dev environment.
|
||||
*/
|
||||
public static boolean isObfEnv() {
|
||||
if (OBF_ENV == null) {
|
||||
throw new IllegalStateException("Obfuscation state has been accessed too early!");
|
||||
}
|
||||
return OBF_ENV;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the appropriate name according to current environment's obfuscation
|
||||
*/
|
||||
public static String obf(String deobf, String obf) {
|
||||
if (OBF_ENV == null) {
|
||||
throw new IllegalStateException("Obfuscation state has been accessed too early!");
|
||||
}
|
||||
if (OBF_ENV) {
|
||||
return obf;
|
||||
}
|
||||
return deobf;
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
package com.gtnewhorizons.angelica.loading.fml.compat.transformers.generic;
|
||||
|
||||
import com.gtnewhorizons.angelica.loading.AngelicaTweaker;
|
||||
import com.gtnewhorizons.angelica.loading.AngelicaClientTweaker;
|
||||
import org.spongepowered.asm.lib.Opcodes;
|
||||
import org.spongepowered.asm.lib.tree.AbstractInsnNode;
|
||||
import org.spongepowered.asm.lib.tree.ClassNode;
|
||||
@@ -62,7 +62,7 @@ public class FieldLevelTessellatorTransformer {
|
||||
new FieldInsnNode(
|
||||
Opcodes.GETSTATIC,
|
||||
"net/minecraft/client/renderer/Tessellator",
|
||||
AngelicaTweaker.obf("instance", "field_78398_a"),
|
||||
AngelicaClientTweaker.obf("instance", "field_78398_a"),
|
||||
"Lnet/minecraft/client/renderer/Tessellator;"));
|
||||
list.add(new VarInsnNode(Opcodes.ASTORE, localIndex));
|
||||
mn.instructions.insert(list);
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
package com.gtnewhorizons.angelica.loading.fml.compat.transformers.generic;
|
||||
|
||||
import com.gtnewhorizons.angelica.loading.AngelicaTweaker;
|
||||
import com.gtnewhorizons.angelica.loading.AngelicaClientTweaker;
|
||||
import org.spongepowered.asm.lib.Opcodes;
|
||||
import org.spongepowered.asm.lib.tree.ClassNode;
|
||||
import org.spongepowered.asm.lib.tree.InsnList;
|
||||
@@ -29,7 +29,7 @@ public class HUDCachingEarlyReturnTransformer {
|
||||
} else if (method.desc.endsWith("V")) {
|
||||
list.add(new InsnNode(Opcodes.RETURN));
|
||||
} else {
|
||||
AngelicaTweaker.LOGGER.warn(
|
||||
AngelicaClientTweaker.LOGGER.warn(
|
||||
"HUDCaching Conditional Return - Unknown return type: {}#{}:{}", cn.name, method.name, method.desc
|
||||
);
|
||||
return;
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
package com.gtnewhorizons.angelica.loading.fml.compat.transformers.generic;
|
||||
|
||||
import com.gtnewhorizons.angelica.loading.AngelicaTweaker;
|
||||
import com.gtnewhorizons.angelica.loading.AngelicaClientTweaker;
|
||||
import org.spongepowered.asm.lib.Opcodes;
|
||||
import org.spongepowered.asm.lib.tree.AbstractInsnNode;
|
||||
import org.spongepowered.asm.lib.tree.ClassNode;
|
||||
@@ -59,7 +59,7 @@ public class TileEntityNullGuardTransformer {
|
||||
AbstractInsnNode in = mn.instructions.get(i);
|
||||
if (in instanceof MethodInsnNode min) {
|
||||
if (min.getOpcode() == Opcodes.INVOKEINTERFACE
|
||||
&& min.name.equals(AngelicaTweaker.obf("getTileEntity", "func_147438_o"))
|
||||
&& min.name.equals(AngelicaClientTweaker.obf("getTileEntity", "func_147438_o"))
|
||||
&& min.owner.equals("net/minecraft/world/IBlockAccess")) {
|
||||
AbstractInsnNode castNodeAbstract = min.getNext();
|
||||
if (castNodeAbstract instanceof TypeInsnNode castNodeType) {
|
||||
@@ -77,7 +77,7 @@ public class TileEntityNullGuardTransformer {
|
||||
} else if (mn.desc.endsWith("V")) {
|
||||
list.add(new InsnNode(Opcodes.RETURN));
|
||||
} else {
|
||||
AngelicaTweaker.LOGGER.warn("TileEntityNullGuard - Unknown Return Type: {}:{}", mn.name, mn.desc);
|
||||
AngelicaClientTweaker.LOGGER.warn("TileEntityNullGuard - Unknown Return Type: {}:{}", mn.name, mn.desc);
|
||||
return;
|
||||
}
|
||||
list.add(exit);
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
package com.gtnewhorizons.angelica.loading.fml.compat.transformers.specific;
|
||||
|
||||
import com.gtnewhorizons.angelica.loading.AngelicaTweaker;
|
||||
import com.gtnewhorizons.angelica.loading.AngelicaClientTweaker;
|
||||
import com.gtnewhorizons.angelica.loading.shared.AngelicaClassDump;
|
||||
import net.minecraft.launchwrapper.IClassTransformer;
|
||||
import org.spongepowered.asm.lib.ClassReader;
|
||||
@@ -60,7 +60,7 @@ public class ImmersiveEngineeringTransformer implements IClassTransformer {
|
||||
MixinClassWriter cw = new MixinClassWriter(MixinClassWriter.COMPUTE_FRAMES);
|
||||
cn.accept(cw);
|
||||
final byte[] bytes = cw.toByteArray();
|
||||
AngelicaTweaker.LOGGER.info("[AngelicaCompat]Extra Transformers: Applied ImmersiveEngineeringTransformer");
|
||||
AngelicaClientTweaker.LOGGER.info("[AngelicaCompat]Extra Transformers: Applied ImmersiveEngineeringTransformer");
|
||||
AngelicaClassDump.dumpClass(transformedName, basicClass, bytes, this);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
package com.gtnewhorizons.angelica.loading.fml.compat.transformers.specific;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.gtnewhorizons.angelica.loading.AngelicaTweaker;
|
||||
import com.gtnewhorizons.angelica.loading.AngelicaClientTweaker;
|
||||
import com.gtnewhorizons.angelica.loading.shared.AngelicaClassDump;
|
||||
import net.minecraft.launchwrapper.IClassTransformer;
|
||||
import org.spongepowered.asm.lib.ClassReader;
|
||||
@@ -47,7 +47,7 @@ public class StacksOnStacksTransformer implements IClassTransformer {
|
||||
ClassWriter cw = new ClassWriter(0);
|
||||
cn.accept(cw);
|
||||
final byte[] bytes = cw.toByteArray();
|
||||
AngelicaTweaker.LOGGER.info("[AngelicaCompat]Extra Transformers: Applied StacksOnStacksTransformer");
|
||||
AngelicaClientTweaker.LOGGER.info("[AngelicaCompat]Extra Transformers: Applied StacksOnStacksTransformer");
|
||||
AngelicaClassDump.dumpClass(transformedName, basicClass, bytes, this);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
package com.gtnewhorizons.angelica.loading.fml.transformers;
|
||||
|
||||
import com.gtnewhorizons.angelica.loading.AngelicaTweaker;
|
||||
import com.gtnewhorizons.angelica.loading.AngelicaClientTweaker;
|
||||
import com.gtnewhorizons.angelica.loading.shared.AngelicaClassDump;
|
||||
import com.gtnewhorizons.angelica.loading.shared.transformers.CeleritasBlockTransform;
|
||||
import net.minecraft.launchwrapper.IClassTransformer;
|
||||
@@ -14,7 +14,7 @@ public class CeleritasBlockTransformer implements IClassTransformer {
|
||||
private final String[] exclusions;
|
||||
|
||||
public CeleritasBlockTransformer() {
|
||||
this.inner = new CeleritasBlockTransform(AngelicaTweaker.isObfEnv());
|
||||
this.inner = new CeleritasBlockTransform(AngelicaClientTweaker.isObfEnv());
|
||||
this.exclusions = inner.getTransformerExclusions();
|
||||
this.inner.setCeleritasSetting();
|
||||
}
|
||||
|
||||
+53
-11
@@ -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,66 @@ 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("Ears") && exceptions.remove("com.unascribed.ears")) {
|
||||
exceptions.add("com.unascribed.ears.asm");
|
||||
exceptions.add("com.unascribed.ears.common.agent");
|
||||
FMLRelaunchLog.info("[Angelica] Narrowed com.unascribed.ears 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;
|
||||
|
||||
@@ -15,6 +15,7 @@ public class AngelicaRfbPlugin implements RfbPlugin {
|
||||
@Override
|
||||
public void onConstruction(@NotNull PluginContext ctx) {
|
||||
Launch.blackboard.put("angelica.rfbPluginLoaded", Boolean.TRUE);
|
||||
Launch.classLoader.addClassLoaderExclusion("com.gtnewhorizons.angelica.glsm.redirect.");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -36,7 +36,15 @@ public enum Mixins implements IMixins {
|
||||
, "angelica.MixinMinecraft"
|
||||
, "angelica.MixinMinecraft_FrameHook"
|
||||
, "angelica.MixinMinecraftServer"
|
||||
, "angelica.bugfixes.MixinItemRenderer_EdgeDepth"
|
||||
, "angelica.bugfixes.MixinModelCreeper_AuraBodyInflate"
|
||||
, "angelica.bugfixes.MixinModelWither_ArmorCentering"
|
||||
, "angelica.bugfixes.MixinRenderBlocks_CrossedSquaresNormal"
|
||||
, "angelica.bugfixes.MixinRenderCreeper_AuraDepth"
|
||||
, "angelica.bugfixes.MixinRenderGlobal_DeferredEntityOverlay"
|
||||
, "angelica.bugfixes.MixinRenderGlobal_DestroyBlock"
|
||||
, "angelica.bugfixes.MixinRendererLivingEntity_DeferredEntityOverlay"
|
||||
, "angelica.bugfixes.MixinRenderWither_ArmorCentering"
|
||||
, "angelica.bugfixes.MixinRendererLivingEntity_EyeDepth"
|
||||
, "angelica.debug.MixinMinecraft_FPSCap"
|
||||
, "angelica.ffp.MixinTessellator_CoreProfile"
|
||||
@@ -236,6 +244,7 @@ public enum Mixins implements IMixins {
|
||||
.setApplyIf(() -> AngelicaConfig.enableIris)
|
||||
.addClientMixins(
|
||||
"shaders.MixinDroppedItemGlintEdges"
|
||||
, "shaders.MixinHeldItemGlintEdges"
|
||||
, "shaders.MixinEntityPickupFX"
|
||||
, "shaders.MixinEntityRenderer"
|
||||
, "shaders.MixinGuiIngameForge"
|
||||
@@ -248,6 +257,7 @@ public enum Mixins implements IMixins {
|
||||
, "shaders.MixinRenderEntityFlame"
|
||||
, "shaders.MixinRendererLivingEntity"
|
||||
, "shaders.MixinRenderGlobal"
|
||||
, "shaders.AccessorEntityHorse"
|
||||
, "shaders.MixinRenderHorse"
|
||||
, "shaders.MixinRenderItem"
|
||||
, "shaders.MixinRenderNameTag"
|
||||
|
||||
@@ -1,23 +1,25 @@
|
||||
package com.gtnewhorizons.angelica.proxy;
|
||||
|
||||
import biomesoplenty.api.content.BOPCBlocks;
|
||||
import com.google.common.base.Objects;
|
||||
import com.gtnewhorizon.gtnhlib.client.model.loading.ModelRegistry;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vao.VAOManager;
|
||||
import com.gtnewhorizons.angelica.commands.AngelicaCommand;
|
||||
import com.gtnewhorizons.angelica.common.BlockError;
|
||||
import com.gtnewhorizons.angelica.compat.ModStatus;
|
||||
import com.gtnewhorizons.angelica.compat.bettercrashes.BetterCrashesCompat;
|
||||
import com.gtnewhorizons.angelica.config.AngelicaConfig;
|
||||
import com.gtnewhorizons.angelica.config.CompatConfig;
|
||||
import com.gtnewhorizons.angelica.config.ConfigMigrator;
|
||||
import com.gtnewhorizons.angelica.debug.F3Direction;
|
||||
import com.gtnewhorizons.angelica.debug.FrametimeGraph;
|
||||
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;
|
||||
import com.gtnewhorizons.angelica.loading.AngelicaClientTweaker;
|
||||
import com.gtnewhorizons.angelica.mixins.interfaces.IGameSettingsExt;
|
||||
import com.gtnewhorizons.angelica.render.CloudRenderer;
|
||||
import com.gtnewhorizons.angelica.rendering.AngelicaBlockSafetyRegistry;
|
||||
@@ -26,8 +28,9 @@ import com.gtnewhorizons.angelica.rendering.celeritas.CeleritasSetup;
|
||||
import com.gtnewhorizons.angelica.rendering.celeritas.threading.ChunkTaskRegistry;
|
||||
import com.gtnewhorizons.angelica.rendering.celeritas.threading.DefaultChunkTaskProvider;
|
||||
import com.gtnewhorizons.angelica.rendering.celeritas.threading.ThreadedChunkTaskProvider;
|
||||
import com.gtnewhorizons.angelica.utils.AnimationMode;
|
||||
import com.gtnewhorizons.angelica.utils.ManagedEnum;
|
||||
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;
|
||||
@@ -41,20 +44,16 @@ import jss.notfine.core.Settings;
|
||||
import jss.notfine.gui.GuiCustomMenu;
|
||||
import jss.notfine.gui.NotFineGameOptionPages;
|
||||
import me.flashyreese.mods.reeses_sodium_options.client.gui.ReeseSodiumVideoOptionsScreen;
|
||||
import me.jellysquid.mods.sodium.client.gui.SodiumGameOptions;
|
||||
import me.jellysquid.mods.sodium.client.gui.SodiumOptionsGUI;
|
||||
import net.coderbot.iris.Iris;
|
||||
import net.coderbot.iris.client.IrisDebugScreenHandler;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.FontRenderer;
|
||||
import net.minecraft.client.gui.Gui;
|
||||
import net.minecraft.client.gui.GuiMainMenu;
|
||||
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;
|
||||
@@ -69,29 +68,41 @@ import net.minecraftforge.client.event.GuiScreenEvent;
|
||||
import net.minecraftforge.client.event.RenderGameOverlayEvent;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.world.WorldEvent;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import static com.gtnewhorizons.angelica.AngelicaMod.MOD_ID;
|
||||
import static com.gtnewhorizons.angelica.loading.AngelicaTweaker.LOGGER;
|
||||
|
||||
public class ClientProxy extends CommonProxy {
|
||||
public final class ClientProxy extends CommonProxy {
|
||||
|
||||
final Minecraft mc = Minecraft.getMinecraft();
|
||||
final FrametimeGraph frametimeGraph = new FrametimeGraph();
|
||||
final TPSGraph tpsGraph = new TPSGraph();
|
||||
public static BlockError blockError;
|
||||
public static final ManagedEnum<AnimationMode> animationsMode = new ManagedEnum<>(AnimationMode.VISIBLE_ONLY);
|
||||
private static final Logger LOGGER = LogManager.getLogger("Angelica");
|
||||
private static SodiumGameOptions CONFIG;
|
||||
private final Minecraft mc = Minecraft.getMinecraft();
|
||||
private final FrametimeGraph frametimeGraph = new FrametimeGraph();
|
||||
private final TPSGraph tpsGraph = new TPSGraph();
|
||||
public static Block bopGrass;
|
||||
|
||||
public static SodiumGameOptions options() {
|
||||
if (CONFIG == null) {
|
||||
CONFIG = SodiumGameOptions.load(ConfigMigrator.handleConfigMigration("angelica-options.json"));
|
||||
}
|
||||
return CONFIG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preInit(FMLPreInitializationEvent event) {
|
||||
ModStatus.preInit();
|
||||
super.preInit(event);
|
||||
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
|
||||
ModelRegistry.registerModid(MOD_ID);
|
||||
blockError = new BlockError();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
@@ -114,8 +125,6 @@ public class ClientProxy extends CommonProxy {
|
||||
}
|
||||
}
|
||||
|
||||
private static KeyBinding glsmKeyBinding;
|
||||
|
||||
@Override
|
||||
public void init(FMLInitializationEvent event) {
|
||||
super.init(event);
|
||||
@@ -144,9 +153,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();
|
||||
}
|
||||
@@ -158,23 +164,11 @@ public class ClientProxy extends CommonProxy {
|
||||
}
|
||||
|
||||
// Register debug commands in dev environment only
|
||||
if (!AngelicaTweaker.isObfEnv()) {
|
||||
if (!AngelicaClientTweaker.isObfEnv()) {
|
||||
ClientCommandHandler.instance.registerCommand(new AngelicaCommand());
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -190,6 +184,9 @@ public class ClientProxy extends CommonProxy {
|
||||
LOGGER.error("Could not replace LOTR handle render code with thread safe version");
|
||||
}
|
||||
}
|
||||
if(ModStatus.isBOPLoaded) {
|
||||
bopGrass = BOPCBlocks.newBopGrass;
|
||||
}
|
||||
}
|
||||
|
||||
float lastIntegratedTickTime;
|
||||
|
||||
@@ -10,8 +10,7 @@ import cpw.mods.fml.common.registry.GameRegistry;
|
||||
public class CommonProxy {
|
||||
|
||||
public void preInit(FMLPreInitializationEvent event) {
|
||||
|
||||
if (AngelicaConfig.enableTestBlocks){
|
||||
if (AngelicaConfig.enableTestBlocks) {
|
||||
GameRegistry.registerBlock(new BlockTest(), "test_block");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,215 @@
|
||||
package com.gtnewhorizons.angelica.rendering;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import lombok.Getter;
|
||||
import net.coderbot.iris.layer.GbufferPrograms;
|
||||
import net.coderbot.iris.uniforms.CapturedRenderingState;
|
||||
import net.coderbot.iris.uniforms.EntityIdHelper;
|
||||
import net.minecraft.client.renderer.OpenGlHelper;
|
||||
import net.minecraft.client.renderer.entity.RendererLivingEntity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Defers entity overlay rendering (auras, armor effects, etc.) to after all entities have been drawn.
|
||||
* This lets us fix z-fighting between overlay's own coplanar faces by disabling the depth mask,
|
||||
* and ensures the overlay composites correctly on top of all opaque geometry.
|
||||
*
|
||||
* Used by both the charged creeper aura and the Wither armor overlay.
|
||||
*
|
||||
* The deferred render replays shouldRenderPass on the original renderer instance so that any
|
||||
* mod mixins targeting that method still fire during the deferred pass.
|
||||
*/
|
||||
public class DeferredEntityOverlay {
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ShouldRenderPassFn {
|
||||
int invoke(EntityLivingBase entity, int pass, float partialTick);
|
||||
}
|
||||
|
||||
private static final int INITIAL_CAPACITY = 4;
|
||||
private static final List<DeferredEntry> deferred = new ArrayList<>(INITIAL_CAPACITY);
|
||||
private static final List<DeferredEntry> pool = new ArrayList<>(INITIAL_CAPACITY);
|
||||
|
||||
private static final FloatBuffer MATRIX_BUF = BufferUtils.createFloatBuffer(16);
|
||||
|
||||
// Set by the shouldRenderPass inject, consumed by the doRender WrapOperation.
|
||||
@Getter
|
||||
private static boolean overlayPassActive = false;
|
||||
|
||||
// Set during deferred flush to prevent re-deferring when shouldRenderPass is replayed.
|
||||
@Getter
|
||||
private static boolean replaying = false;
|
||||
|
||||
// Pending context from the shouldRenderPass inject, consumed by deferRender.
|
||||
private static ShouldRenderPassFn pendingShouldRenderPass;
|
||||
private static RendererLivingEntity pendingRenderer;
|
||||
private static EntityLivingBase pendingEntity;
|
||||
private static float pendingPartialTick;
|
||||
|
||||
/**
|
||||
* Called from shouldRenderPass HEAD injects. Marks that the upcoming renderPassModel.render()
|
||||
* should be deferred. If a previous mark was not consumed (shouldRenderPass returned <= 0,
|
||||
* so render() was never called).
|
||||
*/
|
||||
public static void markOverlayPass(ShouldRenderPassFn shouldRenderPass, RendererLivingEntity renderer,
|
||||
EntityLivingBase entity, float partialTick) {
|
||||
overlayPassActive = true;
|
||||
pendingShouldRenderPass = shouldRenderPass;
|
||||
pendingRenderer = renderer;
|
||||
pendingEntity = entity;
|
||||
pendingPartialTick = partialTick;
|
||||
}
|
||||
|
||||
public static void clearStaleOverlayFlag() {
|
||||
overlayPassActive = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from the WrapOperation on renderPassModel.render() in doRender.
|
||||
* Captures the modelview matrix and animation params, skipping the actual render.
|
||||
*/
|
||||
public static void deferRender(float limbSwing, float limbSwingAmount, float ageInTicks,
|
||||
float headYaw, float headPitch, float scale) {
|
||||
overlayPassActive = false;
|
||||
|
||||
DeferredEntry entry = acquireEntry();
|
||||
entry.set(pendingShouldRenderPass, pendingRenderer, pendingEntity, pendingPartialTick,
|
||||
limbSwing, limbSwingAmount, ageInTicks, headYaw, headPitch, scale);
|
||||
|
||||
MATRIX_BUF.clear();
|
||||
GLStateManager.glGetFloat(GL11.GL_MODELVIEW_MATRIX, MATRIX_BUF);
|
||||
MATRIX_BUF.get(entry.matrix);
|
||||
|
||||
deferred.add(entry);
|
||||
|
||||
pendingShouldRenderPass = null;
|
||||
pendingRenderer = null;
|
||||
pendingEntity = null;
|
||||
}
|
||||
|
||||
private static DeferredEntry acquireEntry() {
|
||||
int size = pool.size();
|
||||
if (size > 0) {
|
||||
return pool.remove(size - 1);
|
||||
}
|
||||
return new DeferredEntry();
|
||||
}
|
||||
|
||||
private static void recycle() {
|
||||
for (DeferredEntry entry : deferred) {
|
||||
entry.shouldRenderPass = null;
|
||||
entry.renderer = null;
|
||||
entry.entity = null;
|
||||
pool.add(entry);
|
||||
}
|
||||
deferred.clear();
|
||||
}
|
||||
|
||||
public static void clear() {
|
||||
recycle();
|
||||
overlayPassActive = false;
|
||||
replaying = false;
|
||||
}
|
||||
|
||||
public static void renderAll() {
|
||||
if (deferred.isEmpty()) return;
|
||||
|
||||
GbufferPrograms.beginEntities();
|
||||
try {
|
||||
for (DeferredEntry entry : deferred) {
|
||||
CapturedRenderingState.INSTANCE.setCurrentEntity(EntityIdHelper.getEntityId(entry.entity));
|
||||
renderOverlay(entry);
|
||||
}
|
||||
} finally {
|
||||
CapturedRenderingState.INSTANCE.setCurrentEntity(-1);
|
||||
GbufferPrograms.endEntities();
|
||||
}
|
||||
recycle();
|
||||
}
|
||||
|
||||
private static void renderOverlay(DeferredEntry entry) {
|
||||
EntityLivingBase entity = entry.entity;
|
||||
|
||||
// Restore the entity's lightmap coords
|
||||
int brightness = entity.getBrightnessForRender(entry.partialTick);
|
||||
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit,
|
||||
brightness % 65536, (float) brightness / 65536);
|
||||
|
||||
// Restore the saved modelview matrix
|
||||
GLStateManager.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
GLStateManager.glPushMatrix();
|
||||
boolean depthMaskDisabled = false;
|
||||
try {
|
||||
MATRIX_BUF.clear();
|
||||
MATRIX_BUF.put(entry.matrix);
|
||||
MATRIX_BUF.flip();
|
||||
GLStateManager.glLoadMatrix(MATRIX_BUF);
|
||||
|
||||
// Replay shouldRenderPass pass 1
|
||||
replaying = true;
|
||||
int result = entry.shouldRenderPass.invoke(entity, 1, entry.partialTick);
|
||||
if (result > 0) {
|
||||
// Disable depth writes so coplanar faces don't z-fight each other
|
||||
GLStateManager.glDepthMask(false);
|
||||
depthMaskDisabled = true;
|
||||
|
||||
// Disable backface culling so both sides of the overlay shell are visible
|
||||
GLStateManager.glDisable(GL11.GL_CULL_FACE);
|
||||
|
||||
// Render using the model set by shouldRenderPass
|
||||
entry.renderer.renderPassModel.setLivingAnimations(entity,
|
||||
entry.limbSwing, entry.limbSwingAmount, entry.partialTick);
|
||||
|
||||
entry.renderer.renderPassModel.render(entity,
|
||||
entry.limbSwing, entry.limbSwingAmount, entry.ageInTicks,
|
||||
entry.headYaw, entry.headPitch, entry.scale);
|
||||
}
|
||||
|
||||
// Replay shouldRenderPass pass 2
|
||||
entry.shouldRenderPass.invoke(entity, 2, entry.partialTick);
|
||||
} finally {
|
||||
replaying = false;
|
||||
if (depthMaskDisabled) {
|
||||
GLStateManager.glDepthMask(true);
|
||||
GLStateManager.glEnable(GL11.GL_CULL_FACE);
|
||||
}
|
||||
GLStateManager.glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
private static class DeferredEntry {
|
||||
final float[] matrix = new float[16];
|
||||
ShouldRenderPassFn shouldRenderPass;
|
||||
RendererLivingEntity renderer;
|
||||
EntityLivingBase entity;
|
||||
float partialTick;
|
||||
float limbSwing;
|
||||
float limbSwingAmount;
|
||||
float ageInTicks;
|
||||
float headYaw;
|
||||
float headPitch;
|
||||
float scale;
|
||||
|
||||
void set(ShouldRenderPassFn shouldRenderPass, RendererLivingEntity renderer,
|
||||
EntityLivingBase entity, float partialTick,
|
||||
float limbSwing, float limbSwingAmount, float ageInTicks,
|
||||
float headYaw, float headPitch, float scale) {
|
||||
this.shouldRenderPass = shouldRenderPass;
|
||||
this.renderer = renderer;
|
||||
this.entity = entity;
|
||||
this.partialTick = partialTick;
|
||||
this.limbSwing = limbSwing;
|
||||
this.limbSwingAmount = limbSwingAmount;
|
||||
this.ageInTicks = ageInTicks;
|
||||
this.headYaw = headYaw;
|
||||
this.headPitch = headPitch;
|
||||
this.scale = scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.gtnewhorizons.angelica.rendering;
|
||||
|
||||
import net.minecraft.client.model.ModelBox;
|
||||
import net.minecraft.client.model.ModelHorse;
|
||||
import net.minecraft.client.model.ModelRenderer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Horse model with all boxes inflated outward, used as a separate armor layer.
|
||||
* Extends ModelHorse to inherit all animation and render logic. The constructor
|
||||
* builds the default geometry, then we rebuild every box with inflate applied.
|
||||
* This mirrors how modern MC uses a separate ModelLayers.HORSE_ARMOR.
|
||||
*/
|
||||
public class ModelHorseArmor extends ModelHorse {
|
||||
|
||||
public ModelHorseArmor(float inflate) {
|
||||
super();
|
||||
for (ModelRenderer renderer : this.boxList) {
|
||||
List<ModelBox> originalBoxes = new ArrayList<>(renderer.cubeList);
|
||||
renderer.cubeList.clear();
|
||||
for (ModelBox box : originalBoxes) {
|
||||
int width = Math.round(box.posX2 - box.posX1);
|
||||
int height = Math.round(box.posY2 - box.posY1);
|
||||
int depth = Math.round(box.posZ2 - box.posZ1);
|
||||
renderer.addBox(box.posX1, box.posY1, box.posZ1, width, height, depth, inflate);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.gtnewhorizons.angelica.rendering;
|
||||
|
||||
public class WitherArmorState {
|
||||
public static boolean pendingInflate = false;
|
||||
}
|
||||
+3
-3
@@ -1,11 +1,11 @@
|
||||
package com.gtnewhorizons.angelica.rendering.celeritas;
|
||||
|
||||
import com.gtnewhorizons.angelica.AngelicaMod;
|
||||
import com.gtnewhorizons.angelica.api.ExtQuadLightData;
|
||||
import com.gtnewhorizons.angelica.api.TintComputer;
|
||||
import com.gtnewhorizons.angelica.api.TintRegistry;
|
||||
import com.gtnewhorizons.angelica.dynamiclights.DynamicLights;
|
||||
import com.gtnewhorizons.angelica.dynamiclights.IDynamicLightSource;
|
||||
import com.gtnewhorizons.angelica.proxy.ClientProxy;
|
||||
import com.gtnewhorizons.angelica.rendering.StateAwareTessellator;
|
||||
import com.gtnewhorizons.angelica.rendering.celeritas.iris.BlockRenderContext;
|
||||
import com.gtnewhorizons.angelica.rendering.celeritas.iris.IrisExtendedChunkVertexEncoder;
|
||||
@@ -99,7 +99,7 @@ public class AngelicaChunkBuildContext extends ChunkBuildContext {
|
||||
|
||||
private Material selectMaterial(Material material, TextureAtlasSprite sprite, boolean isShaderPackOverride) {
|
||||
// Don't apply transparency-based optimization when shader pack explicitly overrides the material
|
||||
if (!AngelicaMod.options().performance.useRenderPassOptimization || isShaderPackOverride) {
|
||||
if (!ClientProxy.options().performance.useRenderPassOptimization || isShaderPackOverride) {
|
||||
return material;
|
||||
}
|
||||
if (sprite != null && sprite.getClass() == TextureAtlasSprite.class && !sprite.hasAnimationMetadata()) {
|
||||
@@ -129,7 +129,7 @@ public class AngelicaChunkBuildContext extends ChunkBuildContext {
|
||||
|
||||
final boolean hasDynamicLights = chunkLightSources != null && !chunkLightSources.isEmpty();
|
||||
final boolean separateAo = BlockRenderingSettings.INSTANCE.shouldUseSeparateAo();
|
||||
final boolean celeritasSmoothLighting = AngelicaMod.options().quality.useCeleritasSmoothLighting;
|
||||
final boolean celeritasSmoothLighting = ClientProxy.options().quality.useCeleritasSmoothLighting;
|
||||
final boolean shaderActive = IrisApi.getInstance().isShaderPackInUse();
|
||||
final boolean useAoCalculation = lightPipelineReady && (separateAo || celeritasSmoothLighting || shaderActive);
|
||||
final boolean shouldApplyDiffuse = !BlockRenderingSettings.INSTANCE.shouldDisableDirectionalShading();
|
||||
|
||||
+15
-1
@@ -20,6 +20,7 @@ import net.minecraft.crash.CrashReport;
|
||||
import net.minecraft.crash.CrashReportCategory;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.AxisAlignedBB;
|
||||
import net.minecraft.util.ReportedException;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import org.embeddedt.embeddium.impl.render.chunk.RenderSection;
|
||||
@@ -139,7 +140,20 @@ public abstract class AngelicaChunkBuilderMeshingTask extends ChunkBuilderTask<C
|
||||
if (block.hasTileEntity(meta)) {
|
||||
final TileEntity tileEntity = region.getTileEntity(x, y, z);
|
||||
if (tileEntity != null && TileEntityRendererDispatcher.instance.hasSpecialRenderer(tileEntity)) {
|
||||
(TileEntityRenderBoundsRegistry.isAlwaysInfiniteExtent(tileEntity) ? renderData.globalBlockEntities : renderData.culledBlockEntities).add(tileEntity);
|
||||
final boolean isGlobal;
|
||||
if (TileEntityRenderBoundsRegistry.isAlwaysInfiniteExtent(tileEntity)) {
|
||||
isGlobal = true;
|
||||
} else {
|
||||
final AxisAlignedBB aabb = tileEntity.getRenderBoundingBox();
|
||||
if (aabb != null) {
|
||||
final int secMinX = x & ~15, secMinY = y & ~15, secMinZ = z & ~15;
|
||||
isGlobal = aabb.minX < secMinX || aabb.minY < secMinY || aabb.minZ < secMinZ
|
||||
|| aabb.maxX > secMinX + 16 || aabb.maxY > secMinY + 16 || aabb.maxZ > secMinZ + 16;
|
||||
} else {
|
||||
isGlobal = false;
|
||||
}
|
||||
}
|
||||
(isGlobal ? renderData.globalBlockEntities : renderData.culledBlockEntities).add(tileEntity);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -2,6 +2,7 @@ package com.gtnewhorizons.angelica.rendering.celeritas;
|
||||
|
||||
import com.gtnewhorizons.angelica.AngelicaMod;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.proxy.ClientProxy;
|
||||
import com.gtnewhorizons.angelica.rendering.celeritas.api.IrisShaderProvider;
|
||||
import com.gtnewhorizons.angelica.rendering.celeritas.api.IrisShaderProviderHolder;
|
||||
import me.jellysquid.mods.sodium.client.gui.options.named.MultiDrawMode;
|
||||
@@ -30,7 +31,7 @@ class AngelicaChunkRenderer extends DefaultChunkRenderer {
|
||||
}
|
||||
|
||||
private static MultiDrawEmitter createEmitter() {
|
||||
MultiDrawMode mode = AngelicaMod.options().advanced.multiDrawMode;
|
||||
MultiDrawMode mode = ClientProxy.options().advanced.multiDrawMode;
|
||||
|
||||
if (mode == MultiDrawMode.INDIRECT) {
|
||||
boolean supported = GLStateManager.capabilities != null && (GLStateManager.capabilities.OpenGL43 || GLStateManager.capabilities.GL_ARB_multi_draw_indirect);
|
||||
|
||||
+5
-5
@@ -1,7 +1,7 @@
|
||||
package com.gtnewhorizons.angelica.rendering.celeritas;
|
||||
|
||||
import com.gtnewhorizons.angelica.AngelicaMod;
|
||||
import com.gtnewhorizons.angelica.mixins.interfaces.RenderSectionManagerAccessor;
|
||||
import com.gtnewhorizons.angelica.proxy.ClientProxy;
|
||||
import com.gtnewhorizons.angelica.rendering.AngelicaRenderQueue;
|
||||
import com.gtnewhorizons.angelica.rendering.celeritas.api.IrisShaderProviderHolder;
|
||||
import com.gtnewhorizons.angelica.rendering.celeritas.threading.ChunkTaskProvider;
|
||||
@@ -87,7 +87,7 @@ public class AngelicaRenderSectionManager extends RenderSectionManager {
|
||||
|
||||
@Override
|
||||
protected AsyncOcclusionMode getAsyncOcclusionMode() {
|
||||
return AngelicaMod.options().performance.asyncOcclusionMode;
|
||||
return ClientProxy.options().performance.asyncOcclusionMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -97,7 +97,7 @@ public class AngelicaRenderSectionManager extends RenderSectionManager {
|
||||
|
||||
@Override
|
||||
protected boolean useFogOcclusion() {
|
||||
return AngelicaMod.options().performance.useFogOcclusion && !IrisShaderProviderHolder.isActive();
|
||||
return ClientProxy.options().performance.useFogOcclusion && !IrisShaderProviderHolder.isActive();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -113,7 +113,7 @@ public class AngelicaRenderSectionManager extends RenderSectionManager {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return AngelicaMod.options().performance.useOcclusionCulling;
|
||||
return ClientProxy.options().performance.useOcclusionCulling;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -152,7 +152,7 @@ public class AngelicaRenderSectionManager extends RenderSectionManager {
|
||||
|
||||
@Override
|
||||
protected boolean allowImportantRebuilds() {
|
||||
return !AngelicaMod.options().performance.alwaysDeferChunkUpdates;
|
||||
return !ClientProxy.options().performance.alwaysDeferChunkUpdates;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -2,9 +2,9 @@ package com.gtnewhorizons.angelica.rendering.celeritas;
|
||||
|
||||
import com.gtnewhorizons.angelica.config.AngelicaConfig;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.loading.AngelicaClientTweaker;
|
||||
import org.embeddedt.embeddium.impl.gl.device.GLRenderDevice;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import static com.gtnewhorizons.angelica.loading.AngelicaTweaker.LOGGER;
|
||||
|
||||
public class CeleritasSetup {
|
||||
private static boolean initialized = false;
|
||||
@@ -12,7 +12,7 @@ public class CeleritasSetup {
|
||||
public static void ensureInitialized() {
|
||||
if (!initialized && AngelicaConfig.enableCeleritas) {
|
||||
GLRenderDevice.VANILLA_STATE_RESETTER = () -> GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
LOGGER.debug("Celeritas init");
|
||||
AngelicaClientTweaker.LOGGER.debug("Celeritas init");
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -1,10 +1,10 @@
|
||||
package com.gtnewhorizons.angelica.rendering.celeritas;
|
||||
|
||||
import com.gtnewhorizons.angelica.AngelicaMod;
|
||||
import com.gtnewhorizons.angelica.dynamiclights.DynamicLights;
|
||||
import com.gtnewhorizons.angelica.dynamiclights.IDynamicLightWorldRenderer;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.mixins.interfaces.ITileEntityBoundingBoxCache;
|
||||
import com.gtnewhorizons.angelica.proxy.ClientProxy;
|
||||
import com.gtnewhorizons.angelica.rendering.RenderingState;
|
||||
import com.gtnewhorizons.angelica.rendering.TileEntityRenderBoundsRegistry;
|
||||
import com.gtnewhorizons.angelica.rendering.celeritas.api.IrisShaderProvider;
|
||||
@@ -127,7 +127,7 @@ public class CeleritasWorldRenderer extends SimpleWorldRenderer<WorldClient, Ang
|
||||
}
|
||||
}
|
||||
|
||||
if (AngelicaMod.options().performance.useCompactVertexFormat) {
|
||||
if (ClientProxy.options().performance.useCompactVertexFormat) {
|
||||
return ChunkMeshFormats.COMPACT;
|
||||
}
|
||||
return ChunkMeshFormats.VANILLA_LIKE;
|
||||
@@ -155,7 +155,7 @@ public class CeleritasWorldRenderer extends SimpleWorldRenderer<WorldClient, Ang
|
||||
|
||||
renderSectionManager.setCameraPosition(transform.x, transform.y, transform.z);
|
||||
|
||||
this.useEntityCulling = AngelicaMod.options().performance.useEntityCulling;
|
||||
this.useEntityCulling = ClientProxy.options().performance.useEntityCulling;
|
||||
|
||||
super.setupTerrain(viewport, cameraState, frame, spectator, updateChunksImmediately);
|
||||
|
||||
@@ -313,7 +313,7 @@ public class CeleritasWorldRenderer extends SimpleWorldRenderer<WorldClient, Ang
|
||||
public int renderBlockEntities(float partialTicks) {
|
||||
final int pass = MinecraftForgeClient.getRenderPass();
|
||||
teRenderContext.set(partialTicks, pass);
|
||||
if (pass == 0 || !AngelicaMod.options().performance.translucencySorting) {
|
||||
if (pass == 0 || !ClientProxy.options().performance.translucencySorting) {
|
||||
return super.renderBlockEntities(teRenderContext);
|
||||
}
|
||||
int count = 0;
|
||||
|
||||
+3
-8
@@ -79,13 +79,13 @@ public class IrisExtendedChunkVertexEncoder implements ContextAwareChunkVertexEn
|
||||
|
||||
baseEncoder.write(ptr, material, vertex, sectionIndex);
|
||||
|
||||
// Per-vertex: renderType, midBlock, lightValue
|
||||
memPutShort(ptr + MC_ENTITY_OFFSET + 2, ctx.renderType);
|
||||
// Per-vertex: mc_Entity (packed blockId + renderType), midBlock, lightValue
|
||||
memPutInt(ptr + MC_ENTITY_OFFSET, ((ctx.blockId + 1) << 1) | (ctx.renderType & 1));
|
||||
final int midBlock = ExtendedDataHelper.computeMidBlock(vertex.x, vertex.y, vertex.z, ctx.localPosX, ctx.localPosY, ctx.localPosZ);
|
||||
memPutInt(ptr + MID_BLOCK_OFFSET, midBlock);
|
||||
memPutByte(ptr + MID_BLOCK_OFFSET + 3, ctx.lightValue);
|
||||
|
||||
// Per-quad: midTexCoord, blockId, normal, tangent
|
||||
// Per-quad: midTexCoord, normal, tangent
|
||||
if (vertexCount == 4) {
|
||||
vertexCount = 0;
|
||||
|
||||
@@ -98,11 +98,6 @@ public class IrisExtendedChunkVertexEncoder implements ContextAwareChunkVertexEn
|
||||
memPutInt(ptr + MID_TEX_OFFSET - STRIDE * 2, midUV);
|
||||
memPutInt(ptr + MID_TEX_OFFSET - STRIDE * 3, midUV);
|
||||
|
||||
memPutShort(ptr + MC_ENTITY_OFFSET, ctx.blockId);
|
||||
memPutShort(ptr + MC_ENTITY_OFFSET - STRIDE, ctx.blockId);
|
||||
memPutShort(ptr + MC_ENTITY_OFFSET - STRIDE * 2, ctx.blockId);
|
||||
memPutShort(ptr + MC_ENTITY_OFFSET - STRIDE * 3, ctx.blockId);
|
||||
|
||||
quad.setup(ptr, STRIDE);
|
||||
NormalHelper.computeFaceNormal(normal, quad);
|
||||
final int packedNormal = NormI8.pack(normal);
|
||||
|
||||
+2
-2
@@ -13,7 +13,7 @@ import org.embeddedt.embeddium.impl.render.chunk.vertex.format.ChunkVertexType;
|
||||
* mc_midTexCoord ushort[2] - quad center UV (average of 4 vertices)
|
||||
* at_tangent byte[4] - tangent vector, normalized
|
||||
* iris_Normal byte[3]+1 - face normal, normalized
|
||||
* mc_Entity short[2] - (blockId, renderType)
|
||||
* mc_Entity uint - packed as ((blockId + 1) << 1) | (renderType & 1)
|
||||
* at_midBlock byte[4] - (xyz offset from block center, lightValue)
|
||||
*/
|
||||
public class IrisExtendedChunkVertexType implements ChunkVertexType {
|
||||
@@ -25,7 +25,7 @@ public class IrisExtendedChunkVertexType implements ChunkVertexType {
|
||||
.addElement("mc_midTexCoord", GlVertexFormat.NEXT_ALIGNED_POINTER, GlVertexAttributeFormat.UNSIGNED_SHORT, 2, false, false)
|
||||
.addElement("at_tangent", GlVertexFormat.NEXT_ALIGNED_POINTER, GlVertexAttributeFormat.BYTE, 4, true, false)
|
||||
.addElement("iris_Normal", GlVertexFormat.NEXT_ALIGNED_POINTER, GlVertexAttributeFormat.BYTE, 3, true, false)
|
||||
.addElement("mc_Entity", GlVertexFormat.NEXT_ALIGNED_POINTER, GlVertexAttributeFormat.SHORT, 2, false, false)
|
||||
.addElement("mc_Entity", GlVertexFormat.NEXT_ALIGNED_POINTER, GlVertexAttributeFormat.UNSIGNED_INT, 1, false, true)
|
||||
.addElement("at_midBlock", GlVertexFormat.NEXT_ALIGNED_POINTER, GlVertexAttributeFormat.BYTE, 4, false, false)
|
||||
.build();
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -2,7 +2,7 @@ package jss.notfine.asm;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import com.gtnewhorizons.angelica.loading.AngelicaTweaker;
|
||||
import com.gtnewhorizons.angelica.loading.AngelicaClientTweaker;
|
||||
import org.objectweb.asm.tree.AbstractInsnNode;
|
||||
import org.objectweb.asm.tree.FieldInsnNode;
|
||||
import org.objectweb.asm.tree.FrameNode;
|
||||
@@ -133,7 +133,7 @@ public class ASMUtils {
|
||||
yield false;
|
||||
}
|
||||
default -> {
|
||||
AngelicaTweaker.LOGGER.warn("Unchecked node found: " + node1.getClass());
|
||||
AngelicaClientTweaker.LOGGER.warn("Unchecked node found: " + node1.getClass());
|
||||
yield node1.toString()
|
||||
.equals(node2.toString());
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package jss.notfine.asm.mappings;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.gtnewhorizons.angelica.loading.AngelicaTweaker;
|
||||
import com.gtnewhorizons.angelica.loading.AngelicaClientTweaker;
|
||||
import net.minecraft.launchwrapper.Launch;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* This class und inherited classes are adapted from
|
||||
* <a href=
|
||||
@@ -48,7 +48,7 @@ public class Namer {
|
||||
|
||||
public static void initNames() {
|
||||
final boolean obfuscated = !(Boolean) Launch.blackboard.get("fml.deobfuscatedEnvironment");
|
||||
AngelicaTweaker.LOGGER.info("Environment obfuscated: {}", obfuscated);
|
||||
AngelicaClientTweaker.LOGGER.info("Environment obfuscated: {}", obfuscated);
|
||||
if (obfuscated) {
|
||||
new NamerObf().setNames();
|
||||
} else {
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
package jss.notfine.asm.mappings;
|
||||
|
||||
import com.gtnewhorizons.angelica.loading.AngelicaClientTweaker;
|
||||
import jss.notfine.asm.mappings.Names.Clas;
|
||||
import jss.notfine.asm.mappings.Names.Fiel;
|
||||
import jss.notfine.asm.mappings.Names.Meth;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.gtnewhorizons.angelica.loading.AngelicaTweaker;
|
||||
import jss.notfine.asm.mappings.Names.Clas;
|
||||
import jss.notfine.asm.mappings.Names.Fiel;
|
||||
import jss.notfine.asm.mappings.Names.Meth;
|
||||
|
||||
public class NamerMcp extends NamerSrg {
|
||||
|
||||
@Override
|
||||
@@ -71,15 +71,15 @@ public class NamerMcp extends NamerSrg {
|
||||
nameMap = loadReobfMap(confPath + "packaged.srg");
|
||||
for (Clas c : ac) {
|
||||
String s = nameMap.get(c.name);
|
||||
AngelicaTweaker.LOGGER.trace("C {} {}", c.name, s);
|
||||
AngelicaClientTweaker.LOGGER.trace("C {} {}", c.name, s);
|
||||
}
|
||||
for (Fiel f : af) {
|
||||
String s = nameMap.get(f.clas + "/" + f.name);
|
||||
AngelicaTweaker.LOGGER.trace("F {} {}", f.name, s);
|
||||
AngelicaClientTweaker.LOGGER.trace("F {} {}", f.name, s);
|
||||
}
|
||||
for (Meth m : am) {
|
||||
String s = nameMap.get(m.clas + "/" + m.name + m.desc);
|
||||
AngelicaTweaker.LOGGER.trace("M {} {}", m.name, s);
|
||||
AngelicaClientTweaker.LOGGER.trace("M {} {}", m.name, s);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -1,6 +1,7 @@
|
||||
package me.jellysquid.mods.sodium.client.gui.options.storage;
|
||||
|
||||
import com.gtnewhorizons.angelica.AngelicaMod;
|
||||
import com.gtnewhorizons.angelica.proxy.ClientProxy;
|
||||
import me.jellysquid.mods.sodium.client.gui.SodiumGameOptions;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -9,7 +10,7 @@ public class SodiumOptionsStorage implements OptionStorage<SodiumGameOptions> {
|
||||
private final SodiumGameOptions options;
|
||||
|
||||
public SodiumOptionsStorage() {
|
||||
this.options = AngelicaMod.options();
|
||||
this.options = ClientProxy.options();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -3,30 +3,30 @@ package net.coderbot.iris;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.CapturingTessellator;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.TessellatorManager;
|
||||
import com.gtnewhorizons.angelica.AngelicaMod;
|
||||
import com.gtnewhorizons.angelica.Tags;
|
||||
import com.gtnewhorizons.angelica.config.AngelicaConfig;
|
||||
import com.gtnewhorizons.angelica.proxy.ClientProxy;
|
||||
import com.gtnewhorizons.angelica.rendering.celeritas.api.IrisShaderProviderHolder;
|
||||
import cpw.mods.fml.client.registry.ClientRegistry;
|
||||
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||
import cpw.mods.fml.common.gameevent.InputEvent;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectMap;
|
||||
import lombok.Getter;
|
||||
import net.coderbot.iris.block_context.BlockContextHolder;
|
||||
import net.coderbot.iris.block_rendering.BlockRenderingSettings;
|
||||
import com.gtnewhorizons.angelica.config.AngelicaConfig;
|
||||
import net.coderbot.iris.celeritas.IrisCeleritasShaderProvider;
|
||||
import com.gtnewhorizons.angelica.rendering.celeritas.api.IrisShaderProviderHolder;
|
||||
import net.coderbot.iris.compat.dh.DHCompat;
|
||||
import net.coderbot.iris.config.IrisConfig;
|
||||
import net.coderbot.iris.gbuffer_overrides.matching.InputAvailability;
|
||||
import net.coderbot.iris.gl.shader.StandardMacros;
|
||||
import net.coderbot.iris.gui.screen.ShaderPackScreen;
|
||||
import net.coderbot.iris.pipeline.DeferredWorldRenderingPipeline;
|
||||
import net.coderbot.iris.pipeline.transform.ShaderTransformer;
|
||||
import net.coderbot.iris.pipeline.transform.TransformPatcher;
|
||||
import net.coderbot.iris.gbuffer_overrides.matching.InputAvailability;
|
||||
import net.coderbot.iris.pipeline.FixedFunctionWorldRenderingPipeline;
|
||||
import net.coderbot.iris.pipeline.PipelineManager;
|
||||
import net.coderbot.iris.pipeline.WorldRenderingPipeline;
|
||||
import net.coderbot.iris.pipeline.transform.ShaderTransformer;
|
||||
import net.coderbot.iris.pipeline.transform.TransformPatcher;
|
||||
import net.coderbot.iris.shaderpack.OptionalBoolean;
|
||||
import net.coderbot.iris.shaderpack.ProgramSet;
|
||||
import net.coderbot.iris.shaderpack.ShaderPack;
|
||||
@@ -35,7 +35,6 @@ import net.coderbot.iris.shaderpack.option.OptionSet;
|
||||
import net.coderbot.iris.shaderpack.option.Profile;
|
||||
import net.coderbot.iris.shaderpack.option.values.MutableOptionValues;
|
||||
import net.coderbot.iris.shaderpack.option.values.OptionValues;
|
||||
import net.coderbot.iris.block_context.BlockContextHolder;
|
||||
import net.coderbot.iris.texture.pbr.PBRTextureManager;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.Minecraft;
|
||||
@@ -64,7 +63,6 @@ import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
@@ -72,6 +70,7 @@ import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.ForkJoinWorkerThread;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.zip.ZipError;
|
||||
@@ -113,11 +112,31 @@ public class Iris {
|
||||
// Used in favor of queueDefaultShaderPackOptionValues() for resetting as the
|
||||
// behavior is more concrete and therefore is more likely to repair a user's issues
|
||||
private static boolean resetShaderPackOptions = false;
|
||||
private static boolean loadShaderPackWhenPossible = false;
|
||||
|
||||
private static String IRIS_VERSION;
|
||||
@Getter
|
||||
private static boolean fallback;
|
||||
|
||||
public static boolean loadedIncompatiblePack() {
|
||||
return DHCompat.lastPackIncompatible();
|
||||
}
|
||||
|
||||
public static void loadShaderpackWhenPossible() {
|
||||
loadShaderPackWhenPossible = true;
|
||||
}
|
||||
|
||||
public static void tryLoadShaderpackWhenPossible() {
|
||||
if (loadShaderPackWhenPossible) {
|
||||
loadShaderPackWhenPossible = false;
|
||||
try {
|
||||
reload();
|
||||
} catch (IOException e) {
|
||||
logger.error("Error during deferred shader reload", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazy executor for parallelizing shader transformations during shader pack loading.
|
||||
* Creates threads on demand and shuts down after a period of inactivity.
|
||||
@@ -335,7 +354,7 @@ public class Iris {
|
||||
final boolean released = !Keyboard.getEventKeyState();
|
||||
if (Minecraft.getMinecraft().gameSettings.showDebugInfo && GuiScreen.isShiftKeyDown() && GuiScreen.isCtrlKeyDown() && released) {
|
||||
if (key == Keyboard.KEY_N) {
|
||||
AngelicaMod.animationsMode.next();
|
||||
ClientProxy.animationsMode.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -350,6 +369,7 @@ public class Iris {
|
||||
* <p>This is called right before options are loaded, so we can add key bindings here.</p>
|
||||
*/
|
||||
public void onEarlyInitialize() {
|
||||
DHCompat.run();
|
||||
try {
|
||||
if (!Files.exists(getShaderpacksDirectory())) {
|
||||
Files.createDirectories(getShaderpacksDirectory());
|
||||
@@ -395,8 +415,19 @@ public class Iris {
|
||||
|
||||
PBRTextureManager.INSTANCE.init();
|
||||
|
||||
// Only load the shader pack when we can access OpenGL
|
||||
loadShaderpack();
|
||||
boolean isDHLoaded;
|
||||
try {
|
||||
Class.forName("com.seibel.distanthorizons.DistantHorizonsTweaker");
|
||||
isDHLoaded = true;
|
||||
}
|
||||
catch (Exception e) {
|
||||
isDHLoaded = false;
|
||||
}
|
||||
|
||||
// When DH is present, defer shaderpack loading until its init callback has run.
|
||||
if (!isDHLoaded) {
|
||||
loadShaderpack();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -448,11 +479,9 @@ public class Iris {
|
||||
// Attempt to load an external shaderpack if it is available
|
||||
final Optional<String> externalName = irisConfig.getShaderPackName();
|
||||
|
||||
if (!externalName.isPresent()) {
|
||||
if (externalName.isEmpty()) {
|
||||
logger.info("Shaders are disabled because no valid shaderpack is selected");
|
||||
|
||||
setShadersDisabled();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -721,6 +750,12 @@ public class Iris {
|
||||
|
||||
BlockRenderingSettings.INSTANCE.reloadRendererIfRequired();
|
||||
}
|
||||
|
||||
if (loadedIncompatiblePack() && Minecraft.getMinecraft().thePlayer != null) {
|
||||
Iris.logger.warn("Incompatible pack for DH!");
|
||||
Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.BOLD.toString() + EnumChatFormatting.RED + "This pack doesn't have DH support."));
|
||||
Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "Distant Horizons (DH) chunks won't show up. This isn't a bug, get another shader."));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -72,9 +72,11 @@ public class CeleritasTerrainPipeline {
|
||||
Optional<ProgramSource> terrainSource,
|
||||
Optional<ProgramSource> translucentSource,
|
||||
Optional<ProgramSource> shadowSource,
|
||||
Optional<ProgramSource> shadowTranslucentSource,
|
||||
CompletableFuture<Map<PatchShaderType, String>> terrainFuture,
|
||||
CompletableFuture<Map<PatchShaderType, String>> translucentFuture,
|
||||
CompletableFuture<Map<PatchShaderType, String>> shadowFuture,
|
||||
CompletableFuture<Map<PatchShaderType, String>> shadowTranslucentFuture,
|
||||
RenderTargets renderTargets,
|
||||
ImmutableSet<Integer> flippedAfterPrepare,
|
||||
ImmutableSet<Integer> flippedAfterTranslucent,
|
||||
@@ -92,6 +94,7 @@ public class CeleritasTerrainPipeline {
|
||||
gbufferProgramSource.put(IrisTerrainPass.GBUFFER_CUTOUT, terrainSource);
|
||||
gbufferProgramSource.put(IrisTerrainPass.GBUFFER_TRANSLUCENT, translucentSource.isPresent() ? translucentSource : terrainSource);
|
||||
gbufferProgramSource.put(IrisTerrainPass.SHADOW, shadowSource);
|
||||
gbufferProgramSource.put(IrisTerrainPass.SHADOW_TRANSLUCENT, shadowTranslucentSource.isPresent() ? shadowTranslucentSource : shadowSource);
|
||||
|
||||
// Initialize PassInfo, framebuffers, blend modes, and alpha in single pass
|
||||
for (IrisTerrainPass pass : IrisTerrainPass.VALUES) {
|
||||
@@ -101,11 +104,12 @@ public class CeleritasTerrainPipeline {
|
||||
// Set up framebuffer, blend mode, and buffer blend overrides
|
||||
final ProgramId programId = switch (pass) {
|
||||
case GBUFFER_TRANSLUCENT -> ProgramId.Water;
|
||||
case SHADOW_TRANSLUCENT -> ProgramId.ShadowWater;
|
||||
case SHADOW, SHADOW_CUTOUT -> ProgramId.Shadow;
|
||||
default -> ProgramId.Terrain;
|
||||
};
|
||||
|
||||
if (pass == IrisTerrainPass.SHADOW || pass == IrisTerrainPass.SHADOW_CUTOUT) {
|
||||
if (pass.isShadow()) {
|
||||
passInfo.framebuffer = shadowFramebuffer;
|
||||
passInfo.blendModeOverride = programId.getBlendModeOverride();
|
||||
passInfo.bufferBlendOverrides = Collections.emptyList();
|
||||
@@ -145,6 +149,7 @@ public class CeleritasTerrainPipeline {
|
||||
processShaderFuture(terrainFuture, terrainSource, passInfoMap.get(IrisTerrainPass.GBUFFER_SOLID), passInfoMap.get(IrisTerrainPass.GBUFFER_CUTOUT));
|
||||
processShaderFuture(translucentFuture, translucentSource, passInfoMap.get(IrisTerrainPass.GBUFFER_TRANSLUCENT));
|
||||
processShaderFuture(shadowFuture, shadowSource, passInfoMap.get(IrisTerrainPass.SHADOW), passInfoMap.get(IrisTerrainPass.SHADOW_CUTOUT));
|
||||
processShaderFuture(shadowTranslucentFuture, shadowTranslucentSource.isPresent() ? shadowTranslucentSource : shadowSource, passInfoMap.get(IrisTerrainPass.SHADOW_TRANSLUCENT));
|
||||
}
|
||||
|
||||
private void processShaderFuture(@Nullable CompletableFuture<Map<PatchShaderType, String>> future, Optional<ProgramSource> source, PassInfo... targets) {
|
||||
|
||||
@@ -136,8 +136,10 @@ public class IrisCeleritasChunkProgramOverrides {
|
||||
if (celeritasPipeline != null && !celeritasPipeline.hasShadowPass()) {
|
||||
throw new IllegalStateException("Shadow program requested, but shader pack has no shadow pass");
|
||||
}
|
||||
return programs.get(pass.supportsFragmentDiscard() ?
|
||||
IrisTerrainPass.SHADOW_CUTOUT : IrisTerrainPass.SHADOW);
|
||||
if (pass.isReverseOrder()) {
|
||||
return programs.get(IrisTerrainPass.SHADOW_TRANSLUCENT);
|
||||
}
|
||||
return programs.get(pass.supportsFragmentDiscard() ? IrisTerrainPass.SHADOW_CUTOUT : IrisTerrainPass.SHADOW);
|
||||
} else {
|
||||
if (pass.supportsFragmentDiscard()) {
|
||||
return programs.get(IrisTerrainPass.GBUFFER_CUTOUT);
|
||||
|
||||
@@ -187,7 +187,11 @@ public class IrisCeleritasChunkShaderInterface implements ChunkShaderInterface {
|
||||
final boolean isShadow = ShadowRenderingState.areShadowsCurrentlyBeingRendered();
|
||||
final IrisTerrainPass irisPass;
|
||||
if (isShadow) {
|
||||
irisPass = pass.supportsFragmentDiscard() ? IrisTerrainPass.SHADOW_CUTOUT : IrisTerrainPass.SHADOW;
|
||||
if (pass.isReverseOrder()) {
|
||||
irisPass = IrisTerrainPass.SHADOW_TRANSLUCENT;
|
||||
} else {
|
||||
irisPass = pass.supportsFragmentDiscard() ? IrisTerrainPass.SHADOW_CUTOUT : IrisTerrainPass.SHADOW;
|
||||
}
|
||||
} else if (pass.isReverseOrder()) {
|
||||
irisPass = IrisTerrainPass.GBUFFER_TRANSLUCENT;
|
||||
} else if (pass.supportsFragmentDiscard()) {
|
||||
|
||||
@@ -6,6 +6,7 @@ import org.embeddedt.embeddium.impl.render.chunk.terrain.TerrainRenderPass;
|
||||
public enum IrisTerrainPass {
|
||||
SHADOW("shadow"),
|
||||
SHADOW_CUTOUT("shadow"),
|
||||
SHADOW_TRANSLUCENT("shadow_water"),
|
||||
GBUFFER_SOLID("gbuffers_terrain"),
|
||||
GBUFFER_CUTOUT("gbuffers_terrain_cutout"),
|
||||
GBUFFER_TRANSLUCENT("gbuffers_water");
|
||||
@@ -23,19 +24,22 @@ public enum IrisTerrainPass {
|
||||
}
|
||||
|
||||
public boolean isShadow() {
|
||||
return this == SHADOW || this == SHADOW_CUTOUT;
|
||||
return this == SHADOW || this == SHADOW_CUTOUT || this == SHADOW_TRANSLUCENT;
|
||||
}
|
||||
|
||||
public TerrainRenderPass toTerrainPass(RenderPassConfiguration<?> config) {
|
||||
return switch (this) {
|
||||
case SHADOW, GBUFFER_SOLID -> config.defaultSolidMaterial().pass;
|
||||
case SHADOW_CUTOUT, GBUFFER_CUTOUT -> config.defaultCutoutMippedMaterial().pass;
|
||||
case GBUFFER_TRANSLUCENT -> config.defaultTranslucentMaterial().pass;
|
||||
case SHADOW_TRANSLUCENT, GBUFFER_TRANSLUCENT -> config.defaultTranslucentMaterial().pass;
|
||||
};
|
||||
}
|
||||
|
||||
public static IrisTerrainPass fromTerrainPass(TerrainRenderPass pass, boolean isShadow) {
|
||||
if (isShadow) {
|
||||
if (pass.isReverseOrder()) {
|
||||
return SHADOW_TRANSLUCENT;
|
||||
}
|
||||
return pass.supportsFragmentDiscard() ? SHADOW_CUTOUT : SHADOW;
|
||||
} else if (pass.supportsFragmentDiscard()) {
|
||||
return GBUFFER_CUTOUT;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package net.coderbot.iris.client;
|
||||
|
||||
import com.gtnewhorizons.angelica.AngelicaMod;
|
||||
import com.gtnewhorizons.angelica.config.AngelicaConfig;
|
||||
import com.gtnewhorizons.angelica.proxy.ClientProxy;
|
||||
import cpw.mods.fml.common.eventhandler.EventPriority;
|
||||
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.coderbot.iris.Iris;
|
||||
@@ -47,7 +47,7 @@ public class IrisDebugScreenHandler {
|
||||
event.right.add("[" + Iris.MODNAME + "] Shaders are disabled");
|
||||
}
|
||||
if (AngelicaConfig.speedupAnimations) {
|
||||
event.right.add(Math.min(event.right.size(), 9), "animationsMode: " + AngelicaMod.animationsMode);
|
||||
event.right.add(Math.min(event.right.size(), 9), "animationsMode: " + ClientProxy.animationsMode);
|
||||
}
|
||||
|
||||
Iris.getPipelineManager().getPipeline().ifPresent(pipeline -> pipeline.addDebugText(event.left));
|
||||
|
||||
@@ -1,14 +1,129 @@
|
||||
package net.coderbot.iris.compat.dh;
|
||||
|
||||
/**
|
||||
* Stub implementation of Distant Horizons compatibility.
|
||||
*/
|
||||
public class DHCompat {
|
||||
public int getDepthTex() {
|
||||
return 0;
|
||||
}
|
||||
import com.gtnewhorizons.angelica.rendering.RenderingState;
|
||||
import net.coderbot.iris.Iris;
|
||||
import net.coderbot.iris.pipeline.DeferredWorldRenderingPipeline;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Matrix4fc;
|
||||
|
||||
public int getDepthTexNoTranslucent() {
|
||||
return 0;
|
||||
}
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
public class DHCompat {
|
||||
private static boolean dhPresent;
|
||||
private static boolean lastIncompatible;
|
||||
private DHCompatInternal compatInternalInstance;
|
||||
private final static Matrix4f tempProj = new Matrix4f();
|
||||
|
||||
public DHCompat(DeferredWorldRenderingPipeline pipeline, boolean renderDHShadow) {
|
||||
if (pipeline == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (dhPresent) {
|
||||
compatInternalInstance = new DHCompatInternal(pipeline, renderDHShadow);
|
||||
lastIncompatible = compatInternalInstance.incompatiblePack();
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
lastIncompatible = false;
|
||||
if (e instanceof InvocationTargetException ite) {
|
||||
throw new RuntimeException("Unknown error loading Distant Horizons compatibility.", ite.getCause());
|
||||
} else {
|
||||
throw new RuntimeException("Unknown error loading Distant Horizons compatibility.", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static Matrix4fc getProjection() {
|
||||
Matrix4f projection = RenderingState.INSTANCE.getProjectionMatrix();
|
||||
if (!dhPresent) {
|
||||
return projection;
|
||||
}
|
||||
|
||||
return tempProj.setPerspective(projection.perspectiveFov(), projection.m11() / projection.m00(), DHCompat.getNearPlane(), DHCompat.getFarPlane());
|
||||
}
|
||||
|
||||
public static void run() {
|
||||
try {
|
||||
Class.forName("com.seibel.distanthorizons.DistantHorizonsTweaker");
|
||||
dhPresent = true;
|
||||
}
|
||||
catch (Exception e) {
|
||||
dhPresent = false;
|
||||
}
|
||||
try {
|
||||
if (dhPresent) {
|
||||
LodRendererEvents.setupEventHandlers();
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
dhPresent = false;
|
||||
if (e instanceof ExceptionInInitializerError eiie) {
|
||||
throw new RuntimeException("Failure loading DH compat.", eiie.getCause());
|
||||
} else {
|
||||
throw new RuntimeException("DH found, but one or more API methods are missing. Iris requires DH [2.0.4] or DH API version [1.1.0] or newer. Please make sure you are on the latest version of DH and Iris.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean lastPackIncompatible() {
|
||||
return dhPresent && hasRenderingEnabled() && lastIncompatible;
|
||||
}
|
||||
|
||||
public static float getFarPlane() {
|
||||
if (!dhPresent) return 0.01f;
|
||||
return DHCompatInternal.getFarPlane();
|
||||
}
|
||||
|
||||
public static float getNearPlane() {
|
||||
if (!dhPresent) return 0.01f;
|
||||
return DHCompatInternal.getNearPlane();
|
||||
}
|
||||
|
||||
public static int getRenderDistance() {
|
||||
if (!dhPresent) return Minecraft.getMinecraft().gameSettings.renderDistanceChunks * 16;
|
||||
|
||||
return DHCompatInternal.getRenderDistance();
|
||||
}
|
||||
|
||||
public static boolean checkFrame() {
|
||||
if (!dhPresent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return DHCompatInternal.checkFrame();
|
||||
}
|
||||
|
||||
public static boolean hasRenderingEnabled() {
|
||||
if (!dhPresent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return checkFrame();
|
||||
}
|
||||
|
||||
public void clearPipeline() {
|
||||
if (compatInternalInstance == null) return;
|
||||
|
||||
compatInternalInstance.clear();
|
||||
}
|
||||
|
||||
public int getDepthTex() {
|
||||
if (compatInternalInstance == null) return -1;
|
||||
|
||||
return compatInternalInstance.getStoredDepthTex();
|
||||
}
|
||||
|
||||
public int getDepthTexNoTranslucent() {
|
||||
if (compatInternalInstance == null) return -1;
|
||||
|
||||
return compatInternalInstance.getDepthTexNoTranslucent();
|
||||
}
|
||||
|
||||
public DHCompatInternal getInstance() {
|
||||
return compatInternalInstance;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,291 @@
|
||||
package net.coderbot.iris.compat.dh;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.seibel.distanthorizons.api.DhApi;
|
||||
import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiFramebuffer;
|
||||
import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiGenericObjectShaderProgram;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
|
||||
import com.seibel.distanthorizons.coreapi.DependencyInjection.OverrideInjector;
|
||||
import net.coderbot.iris.Iris;
|
||||
import net.coderbot.iris.gl.framebuffer.GlFramebuffer;
|
||||
import net.coderbot.iris.gl.texture.DepthBufferFormat;
|
||||
import net.coderbot.iris.gl.texture.DepthCopyStrategy;
|
||||
import net.coderbot.iris.pipeline.DeferredWorldRenderingPipeline;
|
||||
import net.coderbot.iris.rendertarget.DepthTexture;
|
||||
import net.coderbot.iris.rendertarget.IRenderTargetExt;
|
||||
import net.coderbot.iris.shaderpack.CloudSetting;
|
||||
import net.coderbot.iris.shaderpack.ProgramSource;
|
||||
import net.coderbot.iris.uniforms.CapturedRenderingState;
|
||||
import net.irisshaders.iris.api.v0.IrisApi;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class DHCompatInternal {
|
||||
public static final DHCompatInternal SHADERLESS = new DHCompatInternal(null, false);
|
||||
static boolean dhEnabled;
|
||||
private static int guiScale = -1;
|
||||
private final DeferredWorldRenderingPipeline pipeline;
|
||||
public boolean shouldOverrideShadow;
|
||||
public boolean shouldOverride;
|
||||
private GlFramebuffer dhGenericFramebuffer;
|
||||
private IrisLodRenderProgram solidProgram;
|
||||
private IrisGenericRenderProgram genericShader;
|
||||
private IrisLodRenderProgram translucentProgram;
|
||||
private IrisLodRenderProgram shadowProgram;
|
||||
private GlFramebuffer dhTerrainFramebuffer;
|
||||
private DhFrameBufferWrapper dhTerrainFramebufferWrapper;
|
||||
private GlFramebuffer dhWaterFramebuffer;
|
||||
private GlFramebuffer dhShadowFramebuffer;
|
||||
private DhFrameBufferWrapper dhShadowFramebufferWrapper;
|
||||
private DepthTexture depthTexNoTranslucent;
|
||||
private boolean translucentDepthDirty;
|
||||
private int storedDepthTex = -1;
|
||||
private boolean incompatible = false;
|
||||
private int cachedVersion;
|
||||
|
||||
public DHCompatInternal(DeferredWorldRenderingPipeline pipeline, boolean dhShadowEnabled) {
|
||||
this.pipeline = pipeline;
|
||||
|
||||
if (pipeline == null || !DhApi.Delayed.configs.graphics().renderingEnabled().getValue()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (pipeline.getDHTerrainShader().isEmpty() && pipeline.getDHWaterShader().isEmpty()) {
|
||||
Iris.logger.warn("No DH shader found in this pack.");
|
||||
incompatible = true;
|
||||
return;
|
||||
}
|
||||
|
||||
cachedVersion = ((IRenderTargetExt) Minecraft.getMinecraft().getFramebuffer()).iris$getDepthBufferVersion();
|
||||
|
||||
createDepthTex(Minecraft.getMinecraft().getFramebuffer().framebufferWidth, Minecraft.getMinecraft().getFramebuffer().framebufferHeight);
|
||||
translucentDepthDirty = true;
|
||||
|
||||
ProgramSource terrain = pipeline.getDHTerrainShader().get();
|
||||
solidProgram = IrisLodRenderProgram.createProgram(terrain.getName(), false, false, terrain, pipeline.getCustomUniforms(), pipeline);
|
||||
|
||||
ProgramSource generic = pipeline.getDHGenericShader().get();
|
||||
genericShader = IrisGenericRenderProgram.createProgram(generic.getName() + "_g", false, false, generic, pipeline.getCustomUniforms(), pipeline);
|
||||
dhGenericFramebuffer = pipeline.createDHFramebuffer(generic, false);
|
||||
|
||||
if (pipeline.getDHWaterShader().isPresent()) {
|
||||
ProgramSource water = pipeline.getDHWaterShader().get();
|
||||
translucentProgram = IrisLodRenderProgram.createProgram(water.getName(), false, true, water, pipeline.getCustomUniforms(), pipeline);
|
||||
dhWaterFramebuffer = pipeline.createDHFramebuffer(water, true);
|
||||
}
|
||||
|
||||
if (pipeline.getDHShadowShader().isPresent() && dhShadowEnabled) {
|
||||
ProgramSource shadow = pipeline.getDHShadowShader().get();
|
||||
shadowProgram = IrisLodRenderProgram.createProgram(shadow.getName(), true, false, shadow, pipeline.getCustomUniforms(), pipeline);
|
||||
if (pipeline.hasShadowRenderTargets()) {
|
||||
dhShadowFramebuffer = pipeline.createDHFramebufferShadow(shadow);
|
||||
dhShadowFramebufferWrapper = new DhFrameBufferWrapper(dhShadowFramebuffer);
|
||||
}
|
||||
shouldOverrideShadow = true;
|
||||
} else {
|
||||
shouldOverrideShadow = false;
|
||||
}
|
||||
|
||||
dhTerrainFramebuffer = pipeline.createDHFramebuffer(terrain, false);
|
||||
dhTerrainFramebufferWrapper = new DhFrameBufferWrapper(dhTerrainFramebuffer);
|
||||
|
||||
if (translucentProgram == null) {
|
||||
translucentProgram = solidProgram;
|
||||
}
|
||||
|
||||
shouldOverride = true;
|
||||
}
|
||||
|
||||
public static int getDhBlockRenderDistance() {
|
||||
if (DhApi.Delayed.configs == null || !dhEnabled) {
|
||||
// Called before DH has finished setup
|
||||
return Minecraft.getMinecraft().gameSettings.renderDistanceChunks * 16;
|
||||
}
|
||||
|
||||
return DhApi.Delayed.configs.graphics().chunkRenderDistance().getValue() * 16;
|
||||
}
|
||||
|
||||
public static int getRenderDistance() {
|
||||
return getDhBlockRenderDistance();
|
||||
}
|
||||
|
||||
public static float getFarPlane() {
|
||||
if (DhApi.Delayed.configs == null) {
|
||||
// Called before DH has finished setup
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lodChunkDist = DhApi.Delayed.configs.graphics().chunkRenderDistance().getValue();
|
||||
int lodBlockDist = lodChunkDist * 16;
|
||||
// sqrt 2 to prevent the corners from being cut off
|
||||
return (float) ((lodBlockDist + 512) * Math.sqrt(2));
|
||||
}
|
||||
|
||||
public static float getNearPlane() {
|
||||
if (DhApi.Delayed.renderProxy == null) {
|
||||
// Called before DH has finished setup
|
||||
return 0;
|
||||
}
|
||||
|
||||
return DhApi.Delayed.renderProxy.getNearClipPlaneDistanceInBlocks(CapturedRenderingState.INSTANCE.getTickDelta());
|
||||
}
|
||||
|
||||
public static boolean checkFrame() {
|
||||
if (guiScale == -1) {
|
||||
guiScale = Minecraft.getMinecraft().gameSettings.guiScale;
|
||||
}
|
||||
|
||||
if (DhApi.Delayed.configs == null) return dhEnabled;
|
||||
|
||||
if ((dhEnabled != DhApi.Delayed.configs.graphics().renderingEnabled().getValue() || guiScale != Minecraft.getMinecraft().gameSettings.guiScale)
|
||||
&& IrisApi.getInstance().isShaderPackInUse()) {
|
||||
guiScale = Minecraft.getMinecraft().gameSettings.guiScale;
|
||||
dhEnabled = DhApi.Delayed.configs.graphics().renderingEnabled().getValue();
|
||||
try {
|
||||
Iris.reload();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
return dhEnabled;
|
||||
}
|
||||
|
||||
public boolean incompatiblePack() {
|
||||
return incompatible;
|
||||
}
|
||||
|
||||
public void reconnectDHTextures(int depthTex) {
|
||||
if (((IRenderTargetExt) Minecraft.getMinecraft().getFramebuffer()).iris$getDepthBufferVersion() != cachedVersion) {
|
||||
cachedVersion = ((IRenderTargetExt) Minecraft.getMinecraft().getFramebuffer()).iris$getDepthBufferVersion();
|
||||
createDepthTex(Minecraft.getMinecraft().getFramebuffer().framebufferWidth, Minecraft.getMinecraft().getFramebuffer().framebufferHeight);
|
||||
}
|
||||
if (storedDepthTex != depthTex && dhTerrainFramebuffer != null) {
|
||||
storedDepthTex = depthTex;
|
||||
dhTerrainFramebuffer.addDepthAttachmentBypass(depthTex);
|
||||
if (dhWaterFramebuffer != null) {
|
||||
dhWaterFramebuffer.addDepthAttachmentBypass(depthTex);
|
||||
}
|
||||
if (dhGenericFramebuffer != null) {
|
||||
dhGenericFramebuffer.addDepthAttachmentBypass(depthTex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void createDepthTex(int width, int height) {
|
||||
if (depthTexNoTranslucent != null) {
|
||||
depthTexNoTranslucent.destroy();
|
||||
depthTexNoTranslucent = null;
|
||||
}
|
||||
|
||||
translucentDepthDirty = true;
|
||||
|
||||
depthTexNoTranslucent = new DepthTexture(width, height, DepthBufferFormat.DEPTH32F);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
if (solidProgram != null) {
|
||||
solidProgram.free();
|
||||
solidProgram = null;
|
||||
}
|
||||
if (translucentProgram != null) {
|
||||
translucentProgram.free();
|
||||
translucentProgram = null;
|
||||
}
|
||||
if (shadowProgram != null) {
|
||||
shadowProgram.free();
|
||||
shadowProgram = null;
|
||||
}
|
||||
shouldOverrideShadow = false;
|
||||
shouldOverride = false;
|
||||
dhTerrainFramebuffer = null;
|
||||
dhWaterFramebuffer = null;
|
||||
dhShadowFramebuffer = null;
|
||||
storedDepthTex = -1;
|
||||
translucentDepthDirty = true;
|
||||
|
||||
OverrideInjector.INSTANCE.unbind(IDhApiFramebuffer.class, dhTerrainFramebufferWrapper);
|
||||
OverrideInjector.INSTANCE.unbind(IDhApiGenericObjectShaderProgram.class, genericShader);
|
||||
OverrideInjector.INSTANCE.unbind(IDhApiFramebuffer.class, dhShadowFramebufferWrapper);
|
||||
dhTerrainFramebufferWrapper = null;
|
||||
dhShadowFramebufferWrapper = null;
|
||||
}
|
||||
|
||||
public void setModelPos(DhApiVec3f modelPos) {
|
||||
solidProgram.bind();
|
||||
solidProgram.setModelPos(modelPos);
|
||||
translucentProgram.bind();
|
||||
translucentProgram.setModelPos(modelPos);
|
||||
solidProgram.bind();
|
||||
}
|
||||
|
||||
public IrisLodRenderProgram getSolidShader() {
|
||||
return solidProgram;
|
||||
}
|
||||
|
||||
public GlFramebuffer getSolidFB() {
|
||||
return dhTerrainFramebuffer;
|
||||
}
|
||||
|
||||
public DhFrameBufferWrapper getSolidFBWrapper() {
|
||||
return dhTerrainFramebufferWrapper;
|
||||
}
|
||||
|
||||
public IrisLodRenderProgram getShadowShader() {
|
||||
return shadowProgram;
|
||||
}
|
||||
|
||||
public GlFramebuffer getShadowFB() {
|
||||
return dhShadowFramebuffer;
|
||||
}
|
||||
|
||||
public DhFrameBufferWrapper getShadowFBWrapper() {
|
||||
return dhShadowFramebufferWrapper;
|
||||
}
|
||||
|
||||
public IrisLodRenderProgram getTranslucentShader() {
|
||||
if (translucentProgram == null) {
|
||||
return solidProgram;
|
||||
}
|
||||
return translucentProgram;
|
||||
}
|
||||
|
||||
public int getStoredDepthTex() {
|
||||
return storedDepthTex;
|
||||
}
|
||||
|
||||
public void copyTranslucents(int width, int height) {
|
||||
if (translucentDepthDirty) {
|
||||
translucentDepthDirty = false;
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, depthTexNoTranslucent.getTextureId());
|
||||
dhTerrainFramebuffer.bindAsReadBuffer();
|
||||
GLStateManager.glCopyTexImage2D(GL11.GL_TEXTURE_2D, 0, DepthBufferFormat.DEPTH32F.getGlInternalFormat(), 0, 0, width, height, 0);
|
||||
} else {
|
||||
DepthCopyStrategy.fastest(false).copy(dhTerrainFramebuffer, storedDepthTex, null, depthTexNoTranslucent.getTextureId(), width, height);
|
||||
}
|
||||
}
|
||||
|
||||
public GlFramebuffer getTranslucentFB() {
|
||||
return dhWaterFramebuffer;
|
||||
}
|
||||
|
||||
public GlFramebuffer getGenericFB() {
|
||||
return dhGenericFramebuffer;
|
||||
}
|
||||
|
||||
public int getDepthTexNoTranslucent() {
|
||||
if (depthTexNoTranslucent == null) return 0;
|
||||
|
||||
return depthTexNoTranslucent.getTextureId();
|
||||
}
|
||||
|
||||
public IDhApiGenericObjectShaderProgram getGenericShader() {
|
||||
return genericShader;
|
||||
}
|
||||
|
||||
public boolean avoidRenderingClouds() {
|
||||
return pipeline != null && (pipeline.getDHCloudSetting() == CloudSetting.OFF || (pipeline.getDHCloudSetting() == CloudSetting.DEFAULT && pipeline.getCloudSetting() == CloudSetting.OFF));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package net.coderbot.iris.compat.dh;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiFramebuffer;
|
||||
import net.coderbot.iris.gl.framebuffer.GlFramebuffer;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
|
||||
public class DhFrameBufferWrapper implements IDhApiFramebuffer {
|
||||
private final GlFramebuffer framebuffer;
|
||||
|
||||
|
||||
public DhFrameBufferWrapper(GlFramebuffer framebuffer) {
|
||||
this.framebuffer = framebuffer;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean overrideThisFrame() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bind() {
|
||||
this.framebuffer.bind();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDepthAttachment(int i, boolean b) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return this.framebuffer.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStatus() {
|
||||
this.bind();
|
||||
int status = GLStateManager.glCheckFramebufferStatus(GL30.GL_FRAMEBUFFER);
|
||||
return status;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addColorAttachment(int i, int i1) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
// ignore
|
||||
//this.framebuffer.destroy();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,351 @@
|
||||
package net.coderbot.iris.compat.dh;
|
||||
|
||||
import com.google.common.primitives.Ints;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.mixins.interfaces.EntityRendererAccessor;
|
||||
import com.mitchej123.lwjgl.MemoryStack;
|
||||
import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiGenericObjectShaderProgram;
|
||||
import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup;
|
||||
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiMat4f;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3d;
|
||||
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
|
||||
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading;
|
||||
import net.coderbot.iris.gl.blending.BlendModeOverride;
|
||||
import net.coderbot.iris.gl.blending.BufferBlendOverride;
|
||||
import net.coderbot.iris.gl.program.ProgramImages;
|
||||
import net.coderbot.iris.gl.program.ProgramSamplers;
|
||||
import net.coderbot.iris.gl.program.ProgramUniforms;
|
||||
import net.coderbot.iris.gl.shader.GlShader;
|
||||
import net.coderbot.iris.gl.shader.ShaderType;
|
||||
import net.coderbot.iris.gl.state.FogMode;
|
||||
import net.coderbot.iris.pipeline.DeferredWorldRenderingPipeline;
|
||||
import net.coderbot.iris.pipeline.PatchedShaderPrinter;
|
||||
import net.coderbot.iris.pipeline.transform.PatchShaderType;
|
||||
import net.coderbot.iris.pipeline.transform.TransformPatcher;
|
||||
import net.coderbot.iris.samplers.IrisSamplers;
|
||||
import net.coderbot.iris.shaderpack.ProgramSource;
|
||||
import net.coderbot.iris.uniforms.CommonUniforms;
|
||||
import net.coderbot.iris.uniforms.builtin.BuiltinReplacementUniforms;
|
||||
import net.coderbot.iris.uniforms.custom.CustomUniforms;
|
||||
import net.irisshaders.iris.api.v0.IrisApi;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.texture.DynamicTexture;
|
||||
import org.joml.Matrix3f;
|
||||
import org.joml.Matrix4f;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class IrisGenericRenderProgram implements IDhApiGenericObjectShaderProgram {
|
||||
// Uniforms
|
||||
public final int modelViewUniform;
|
||||
public final int modelViewInverseUniform;
|
||||
public final int projectionUniform;
|
||||
public final int projectionInverseUniform;
|
||||
public final int normalMatrix3fUniform;
|
||||
// Fog/Clip Uniforms
|
||||
private final int id;
|
||||
private final ProgramUniforms uniforms;
|
||||
private final CustomUniforms customUniforms;
|
||||
private final ProgramSamplers samplers;
|
||||
private final ProgramImages images;
|
||||
private final BlendModeOverride blend;
|
||||
private final BufferBlendOverride[] bufferBlendOverrides;
|
||||
private final Matrix4f tempModel = new Matrix4f();
|
||||
private final Matrix4f tempProj = new Matrix4f();
|
||||
private final Matrix4f tempMat4 = new Matrix4f();
|
||||
private final Matrix3f tempMat3 = new Matrix3f();
|
||||
|
||||
private final int instancedShaderOffsetChunkUniform;
|
||||
private final int instancedShaderOffsetSubChunkUniform;
|
||||
private final int instancedShaderCameraChunkPosUniform;
|
||||
private final int instancedShaderCameraSubChunkPosUniform;
|
||||
private final int instancedShaderProjectionModelViewMatrixUniform;
|
||||
private final int va;
|
||||
private final int uBlockLight;
|
||||
private final int uSkyLight;
|
||||
|
||||
// This will bind AbstractVertexAttribute
|
||||
private IrisGenericRenderProgram(String name, boolean isShadowPass, boolean translucent, BlendModeOverride override, BufferBlendOverride[] bufferBlendOverrides, String vertex, String tessControl, String tessEval, String geometry, String fragment, CustomUniforms customUniforms, DeferredWorldRenderingPipeline pipeline) {
|
||||
id = GLStateManager.glCreateProgram();
|
||||
|
||||
GLStateManager.glBindAttribLocation(this.id, 0, "vPosition");
|
||||
|
||||
this.bufferBlendOverrides = bufferBlendOverrides;
|
||||
|
||||
GlShader vert = new GlShader(ShaderType.VERTEX, name + ".vsh", vertex);
|
||||
GLStateManager.glAttachShader(id, vert.getHandle());
|
||||
|
||||
GlShader tessCont = null;
|
||||
if (tessControl != null) {
|
||||
tessCont = new GlShader(ShaderType.TESSELATION_CONTROL, name + ".tcs", tessControl);
|
||||
GLStateManager.glAttachShader(id, tessCont.getHandle());
|
||||
}
|
||||
|
||||
GlShader tessE = null;
|
||||
if (tessEval != null) {
|
||||
tessE = new GlShader(ShaderType.TESSELATION_EVAL, name + ".tes", tessEval);
|
||||
GLStateManager.glAttachShader(id, tessE.getHandle());
|
||||
}
|
||||
|
||||
GlShader geom = null;
|
||||
if (geometry != null) {
|
||||
geom = new GlShader(ShaderType.GEOMETRY, name + ".gsh", geometry);
|
||||
GLStateManager.glAttachShader(id, geom.getHandle());
|
||||
}
|
||||
|
||||
GlShader frag = new GlShader(ShaderType.FRAGMENT, name + ".fsh", fragment);
|
||||
GLStateManager.glAttachShader(id, frag.getHandle());
|
||||
|
||||
GLStateManager.glLinkProgram(this.id);
|
||||
int status = GLStateManager.glGetProgrami(this.id, GL20.GL_LINK_STATUS);
|
||||
if (status != 1) {
|
||||
String message = "Shader link error in Iris DH program! Details: " + GLStateManager.glGetProgramInfoLog(this.id, 9999);
|
||||
this.free();
|
||||
throw new RuntimeException(message);
|
||||
} else {
|
||||
GLStateManager.glUseProgram(this.id);
|
||||
}
|
||||
|
||||
vert.destroy();
|
||||
frag.destroy();
|
||||
|
||||
if (tessCont != null) tessCont.destroy();
|
||||
if (tessE != null) tessE.destroy();
|
||||
if (geom != null) geom.destroy();
|
||||
|
||||
blend = override;
|
||||
ProgramUniforms.Builder uniformBuilder = ProgramUniforms.builder(name, id);
|
||||
ProgramSamplers.Builder samplerBuilder = ProgramSamplers.builder(id, IrisSamplers.WORLD_RESERVED_TEXTURE_UNITS);
|
||||
CommonUniforms.addDynamicUniforms(uniformBuilder, FogMode.PER_VERTEX);
|
||||
customUniforms.assignTo(uniformBuilder);
|
||||
BuiltinReplacementUniforms.addBuiltinReplacementUniforms(uniformBuilder);
|
||||
ProgramImages.Builder builder = ProgramImages.builder(id);
|
||||
pipeline.addGbufferOrShadowSamplers(samplerBuilder, builder,
|
||||
isShadowPass ? pipeline::getFlippedBeforeShadow : () -> translucent ? pipeline.getFlippedAfterTranslucent() : pipeline.getFlippedAfterPrepare(),
|
||||
isShadowPass, true, true, false);
|
||||
customUniforms.mapholderToPass(uniformBuilder, this);
|
||||
this.uniforms = uniformBuilder.buildUniforms();
|
||||
this.customUniforms = customUniforms;
|
||||
samplers = samplerBuilder.build();
|
||||
images = builder.build();
|
||||
|
||||
this.va = GLStateManager.glGenVertexArrays();
|
||||
GLStateManager.glBindVertexArray(va);
|
||||
GLStateManager.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 0, 0);
|
||||
GLStateManager.glEnableVertexAttribArray(0);
|
||||
|
||||
projectionUniform = tryGetUniformLocation2("iris_ProjectionMatrix");
|
||||
projectionInverseUniform = tryGetUniformLocation2("iris_ProjectionMatrixInverse");
|
||||
modelViewUniform = tryGetUniformLocation2("iris_ModelViewMatrix");
|
||||
modelViewInverseUniform = tryGetUniformLocation2("iris_ModelViewMatrixInverse");
|
||||
normalMatrix3fUniform = tryGetUniformLocation2("iris_NormalMatrix");
|
||||
|
||||
this.instancedShaderOffsetChunkUniform = this.tryGetUniformLocation2("uOffsetChunk");
|
||||
this.instancedShaderOffsetSubChunkUniform = this.tryGetUniformLocation2("uOffsetSubChunk");
|
||||
this.instancedShaderCameraChunkPosUniform = this.tryGetUniformLocation2("uCameraPosChunk");
|
||||
this.instancedShaderCameraSubChunkPosUniform = this.tryGetUniformLocation2("uCameraPosSubChunk");
|
||||
this.instancedShaderProjectionModelViewMatrixUniform = this.tryGetUniformLocation2("uProjectionMvm");
|
||||
this.uBlockLight = this.tryGetUniformLocation2("uBlockLight");
|
||||
this.uSkyLight = this.tryGetUniformLocation2("uSkyLight");
|
||||
}
|
||||
|
||||
public static IrisGenericRenderProgram createProgram(String name, boolean isShadowPass, boolean translucent, ProgramSource source, CustomUniforms uniforms, DeferredWorldRenderingPipeline pipeline) {
|
||||
Map<PatchShaderType, String> transformed = TransformPatcher.patchDHGeneric(
|
||||
name,
|
||||
source.getVertexSource().orElseThrow(RuntimeException::new),
|
||||
source.getTessControlSource().orElse(null),
|
||||
source.getTessEvalSource().orElse(null),
|
||||
source.getGeometrySource().orElse(null),
|
||||
source.getFragmentSource().orElseThrow(RuntimeException::new),
|
||||
pipeline.getTextureMap());
|
||||
String vertex = transformed.get(PatchShaderType.VERTEX);
|
||||
String tessControl = transformed.get(PatchShaderType.TESS_CONTROL);
|
||||
String tessEval = transformed.get(PatchShaderType.TESS_EVAL);
|
||||
String geometry = transformed.get(PatchShaderType.GEOMETRY);
|
||||
String fragment = transformed.get(PatchShaderType.FRAGMENT);
|
||||
PatchedShaderPrinter.debugPatchedShaders(source.getName() + "_g", vertex, geometry, tessControl, tessEval, fragment);
|
||||
|
||||
List<BufferBlendOverride> bufferOverrides = new ArrayList<>();
|
||||
|
||||
source.getDirectives().getBufferBlendOverrides().forEach(information -> {
|
||||
int index = Ints.indexOf(source.getDirectives().getDrawBuffers(), information.getIndex());
|
||||
if (index > -1) {
|
||||
bufferOverrides.add(new BufferBlendOverride(index, information.getBlendMode()));
|
||||
}
|
||||
});
|
||||
|
||||
return new IrisGenericRenderProgram(name, isShadowPass, translucent, source.getDirectives().getBlendModeOverride().orElse(null), bufferOverrides.toArray(BufferBlendOverride[]::new), vertex, tessControl, tessEval, geometry, fragment, uniforms, pipeline);
|
||||
}
|
||||
|
||||
// Noise Uniforms
|
||||
|
||||
private static int getChunkPosFromDouble(double value) {
|
||||
return (int) Math.floor(value / 16);
|
||||
}
|
||||
|
||||
private static float getSubChunkPosFromDouble(double value) {
|
||||
double chunkPos = Math.floor(value / 16);
|
||||
return (float) (value - chunkPos * 16);
|
||||
}
|
||||
|
||||
public int tryGetUniformLocation2(CharSequence name) {
|
||||
return GLStateManager.glGetUniformLocation(this.id, name);
|
||||
}
|
||||
|
||||
public void setUniform(int index, Matrix4f matrix) {
|
||||
if (index == -1 || matrix == null) return;
|
||||
|
||||
try (MemoryStack stack = MemoryStack.stackPush()) {
|
||||
FloatBuffer buffer = stack.callocFloat(16);
|
||||
matrix.get(buffer);
|
||||
buffer.rewind();
|
||||
|
||||
GLStateManager.glUniformMatrix4(index, false, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public void setUniform(int index, Matrix3f matrix) {
|
||||
if (index == -1) return;
|
||||
|
||||
try (MemoryStack stack = MemoryStack.stackPush()) {
|
||||
FloatBuffer buffer = stack.callocFloat(9);
|
||||
matrix.get(buffer);
|
||||
buffer.rewind();
|
||||
|
||||
GLStateManager.glUniformMatrix3(index, false, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
// Override ShaderProgram.bind()
|
||||
public void bind(DhApiRenderParam renderParam) {
|
||||
GLStateManager.glBindVertexArray(va);
|
||||
GLStateManager.glUseProgram(id);
|
||||
if (blend != null) blend.apply();
|
||||
|
||||
for (BufferBlendOverride override : bufferBlendOverrides) {
|
||||
override.apply();
|
||||
}
|
||||
|
||||
toJOML(tempModel, renderParam.dhModelViewMatrix);
|
||||
toJOML(tempProj, renderParam.dhProjectionMatrix);
|
||||
|
||||
setUniform(modelViewUniform, tempModel);
|
||||
setUniform(projectionUniform, tempProj);
|
||||
this.setUniform(this.instancedShaderProjectionModelViewMatrixUniform, tempMat4.set(tempProj).mul(tempModel));
|
||||
tempModel.invert();
|
||||
tempProj.invert();
|
||||
setUniform(modelViewInverseUniform, tempModel);
|
||||
setUniform(projectionInverseUniform, tempProj);
|
||||
setUniform(normalMatrix3fUniform, tempModel.transpose3x3(tempMat3));
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0 + IrisSamplers.LIGHTMAP_TEXTURE_UNIT);
|
||||
DynamicTexture lightmapTexture = ((EntityRendererAccessor) Minecraft.getMinecraft().entityRenderer).getLightmapTexture();
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, lightmapTexture.getGlTextureId());
|
||||
|
||||
samplers.update();
|
||||
uniforms.update();
|
||||
|
||||
customUniforms.push(this);
|
||||
|
||||
images.update();
|
||||
}
|
||||
|
||||
public void unbind() {
|
||||
GLStateManager.glBindVertexArray(0);
|
||||
GLStateManager.glUseProgram(0);
|
||||
ProgramUniforms.clearActiveUniforms();
|
||||
ProgramSamplers.clearActiveSamplers();
|
||||
BlendModeOverride.restore();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindVertexBuffer(int i) {
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, i);
|
||||
GLStateManager.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 12, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean overrideThisFrame() {
|
||||
return IrisApi.getInstance().isShaderPackInUse();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void free() {
|
||||
GLStateManager.glDeleteProgram(id);
|
||||
}
|
||||
|
||||
public void fillIndirectUniformData(DhApiRenderParam dhApiRenderParam, DhApiRenderableBoxGroupShading dhApiRenderableBoxGroupShading, IDhApiRenderableBoxGroup boxGroup, DhApiVec3d camPos) {
|
||||
bind(dhApiRenderParam);
|
||||
GLStateManager.enableDepthTest();
|
||||
GLStateManager.glDepthFunc(GL11.GL_LEQUAL);
|
||||
this.setUniform(this.instancedShaderOffsetChunkUniform,
|
||||
getChunkPosFromDouble(boxGroup.getOriginBlockPos().x),
|
||||
getChunkPosFromDouble(boxGroup.getOriginBlockPos().y),
|
||||
getChunkPosFromDouble(boxGroup.getOriginBlockPos().z)
|
||||
);
|
||||
this.setUniform(this.instancedShaderOffsetSubChunkUniform,
|
||||
getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().x),
|
||||
getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().y),
|
||||
getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().z)
|
||||
);
|
||||
|
||||
this.setUniform(this.instancedShaderCameraChunkPosUniform,
|
||||
getChunkPosFromDouble(camPos.x),
|
||||
getChunkPosFromDouble(camPos.y),
|
||||
getChunkPosFromDouble(camPos.z)
|
||||
);
|
||||
this.setUniform(this.instancedShaderCameraSubChunkPosUniform,
|
||||
getSubChunkPosFromDouble(camPos.x),
|
||||
getSubChunkPosFromDouble(camPos.y),
|
||||
getSubChunkPosFromDouble(camPos.z)
|
||||
);
|
||||
this.setUniform(this.uBlockLight,
|
||||
boxGroup.getBlockLight());
|
||||
this.setUniform(this.uSkyLight,
|
||||
boxGroup.getSkyLight());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillSharedDirectUniformData(DhApiRenderParam dhApiRenderParam, DhApiRenderableBoxGroupShading dhApiRenderableBoxGroupShading, IDhApiRenderableBoxGroup iDhApiRenderableBoxGroup, DhApiVec3d dhApiVec3d) {
|
||||
throw new IllegalStateException("Only indirect is supported with Iris.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillDirectUniformData(DhApiRenderParam dhApiRenderParam, IDhApiRenderableBoxGroup iDhApiRenderableBoxGroup, DhApiRenderableBox dhApiRenderableBox, DhApiVec3d dhApiVec3d) {
|
||||
throw new IllegalStateException("Only indirect is supported with Iris.");
|
||||
}
|
||||
|
||||
private void toJOML(Matrix4f target, DhApiMat4f mat4f) {
|
||||
target.setTransposed(mat4f.getValuesAsArray());
|
||||
}
|
||||
|
||||
private void setUniform(int index, int value) {
|
||||
GLStateManager.glUniform1i(index, value);
|
||||
}
|
||||
|
||||
private void setUniform(int index, float value) {
|
||||
GLStateManager.glUniform1f(index, value);
|
||||
}
|
||||
|
||||
private void setUniform(int index, float x, float y, float z) {
|
||||
GLStateManager.glUniform3f(index, x, y, z);
|
||||
}
|
||||
|
||||
private void setUniform(int index, int x, int y, int z) {
|
||||
GLStateManager.glUniform3i(index, x, y, z);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,266 @@
|
||||
package net.coderbot.iris.compat.dh;
|
||||
|
||||
import com.google.common.primitives.Ints;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.mixins.interfaces.EntityRendererAccessor;
|
||||
import com.mitchej123.lwjgl.MemoryStack;
|
||||
import com.seibel.distanthorizons.api.DhApi;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
|
||||
import net.coderbot.iris.gl.blending.BlendModeOverride;
|
||||
import net.coderbot.iris.gl.blending.BufferBlendOverride;
|
||||
import net.coderbot.iris.gl.program.ProgramImages;
|
||||
import net.coderbot.iris.gl.program.ProgramSamplers;
|
||||
import net.coderbot.iris.gl.program.ProgramUniforms;
|
||||
import net.coderbot.iris.gl.shader.GlShader;
|
||||
import net.coderbot.iris.gl.shader.ShaderType;
|
||||
import net.coderbot.iris.gl.state.FogMode;
|
||||
import net.coderbot.iris.gl.texture.TextureType;
|
||||
import net.coderbot.iris.pipeline.DeferredWorldRenderingPipeline;
|
||||
import net.coderbot.iris.pipeline.PatchedShaderPrinter;
|
||||
import net.coderbot.iris.pipeline.transform.PatchShaderType;
|
||||
import net.coderbot.iris.pipeline.transform.TransformPatcher;
|
||||
import net.coderbot.iris.samplers.IrisSamplers;
|
||||
import net.coderbot.iris.shaderpack.ProgramSource;
|
||||
import net.coderbot.iris.uniforms.CommonUniforms;
|
||||
import net.coderbot.iris.uniforms.builtin.BuiltinReplacementUniforms;
|
||||
import net.coderbot.iris.uniforms.custom.CustomUniforms;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.texture.DynamicTexture;
|
||||
import org.joml.Matrix3f;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Matrix4fc;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class IrisLodRenderProgram {
|
||||
// Uniforms
|
||||
public final int modelOffsetUniform;
|
||||
public final int worldYOffsetUniform;
|
||||
public final int mircoOffsetUniform;
|
||||
public final int modelViewUniform;
|
||||
public final int modelViewInverseUniform;
|
||||
public final int projectionUniform;
|
||||
public final int projectionInverseUniform;
|
||||
public final int normalMatrix3fUniform;
|
||||
// Fog/Clip Uniforms
|
||||
public final int clipDistanceUniform;
|
||||
private final int id;
|
||||
private final ProgramUniforms uniforms;
|
||||
private final CustomUniforms customUniforms;
|
||||
private final ProgramSamplers samplers;
|
||||
private final ProgramImages images;
|
||||
private final BlendModeOverride blend;
|
||||
private final BufferBlendOverride[] bufferBlendOverrides;
|
||||
private final Matrix4f tempMat4a = new Matrix4f();
|
||||
private final Matrix4f tempMat4b = new Matrix4f();
|
||||
private final Matrix3f tempMat3 = new Matrix3f();
|
||||
|
||||
// This will bind AbstractVertexAttribute
|
||||
private IrisLodRenderProgram(String name, boolean isShadowPass, boolean translucent, BlendModeOverride override, BufferBlendOverride[] bufferBlendOverrides, String vertex, String tessControl, String tessEval, String geometry, String fragment, CustomUniforms customUniforms, DeferredWorldRenderingPipeline pipeline) {
|
||||
id = GLStateManager.glCreateProgram();
|
||||
|
||||
GLStateManager.glBindAttribLocation(this.id, 0, "vPosition");
|
||||
GLStateManager.glBindAttribLocation(this.id, 1, "iris_color");
|
||||
GLStateManager.glBindAttribLocation(this.id, 2, "irisExtra");
|
||||
|
||||
this.bufferBlendOverrides = bufferBlendOverrides;
|
||||
|
||||
GlShader vert = new GlShader(ShaderType.VERTEX, name + ".vsh", vertex);
|
||||
GLStateManager.glAttachShader(id, vert.getHandle());
|
||||
|
||||
GlShader tessCont = null;
|
||||
if (tessControl != null) {
|
||||
tessCont = new GlShader(ShaderType.TESSELATION_CONTROL, name + ".tcs", tessControl);
|
||||
GLStateManager.glAttachShader(id, tessCont.getHandle());
|
||||
}
|
||||
|
||||
GlShader tessE = null;
|
||||
if (tessEval != null) {
|
||||
tessE = new GlShader(ShaderType.TESSELATION_EVAL, name + ".tes", tessEval);
|
||||
GLStateManager.glAttachShader(id, tessE.getHandle());
|
||||
}
|
||||
|
||||
GlShader geom = null;
|
||||
if (geometry != null) {
|
||||
geom = new GlShader(ShaderType.GEOMETRY, name + ".gsh", geometry);
|
||||
GLStateManager.glAttachShader(id, geom.getHandle());
|
||||
}
|
||||
|
||||
GlShader frag = new GlShader(ShaderType.FRAGMENT, name + ".fsh", fragment);
|
||||
GLStateManager.glAttachShader(id, frag.getHandle());
|
||||
|
||||
GLStateManager.glLinkProgram(this.id);
|
||||
int status = GLStateManager.glGetProgrami(this.id, GL20.GL_LINK_STATUS);
|
||||
if (status != 1) {
|
||||
String message = "Shader link error in Iris DH program! Details: " + GLStateManager.glGetProgramInfoLog(this.id, 9999);
|
||||
this.free();
|
||||
throw new RuntimeException(message);
|
||||
} else {
|
||||
GLStateManager.glUseProgram(this.id);
|
||||
}
|
||||
|
||||
vert.destroy();
|
||||
frag.destroy();
|
||||
|
||||
if (tessCont != null) tessCont.destroy();
|
||||
if (tessE != null) tessE.destroy();
|
||||
if (geom != null) geom.destroy();
|
||||
|
||||
blend = override;
|
||||
ProgramUniforms.Builder uniformBuilder = ProgramUniforms.builder(name, id);
|
||||
ProgramSamplers.Builder samplerBuilder = ProgramSamplers.builder(id, IrisSamplers.WORLD_RESERVED_TEXTURE_UNITS);
|
||||
CommonUniforms.addDynamicUniforms(uniformBuilder, FogMode.PER_VERTEX);
|
||||
customUniforms.assignTo(uniformBuilder);
|
||||
BuiltinReplacementUniforms.addBuiltinReplacementUniforms(uniformBuilder);
|
||||
ProgramImages.Builder builder = ProgramImages.builder(id);
|
||||
pipeline.addGbufferOrShadowSamplers(samplerBuilder, builder,
|
||||
isShadowPass ? pipeline::getFlippedBeforeShadow : () -> translucent ? pipeline.getFlippedAfterTranslucent() : pipeline.getFlippedAfterPrepare(),
|
||||
isShadowPass, true, true, false);
|
||||
customUniforms.mapholderToPass(uniformBuilder, this);
|
||||
this.uniforms = uniformBuilder.buildUniforms();
|
||||
this.customUniforms = customUniforms;
|
||||
samplers = samplerBuilder.build();
|
||||
images = builder.build();
|
||||
|
||||
modelOffsetUniform = tryGetUniformLocation2("modelOffset");
|
||||
worldYOffsetUniform = tryGetUniformLocation2("worldYOffset");
|
||||
mircoOffsetUniform = tryGetUniformLocation2("mircoOffset");
|
||||
projectionUniform = tryGetUniformLocation2("iris_ProjectionMatrix");
|
||||
projectionInverseUniform = tryGetUniformLocation2("iris_ProjectionMatrixInverse");
|
||||
modelViewUniform = tryGetUniformLocation2("iris_ModelViewMatrix");
|
||||
modelViewInverseUniform = tryGetUniformLocation2("iris_ModelViewMatrixInverse");
|
||||
normalMatrix3fUniform = tryGetUniformLocation2("iris_NormalMatrix");
|
||||
|
||||
// Fog/Clip Uniforms
|
||||
clipDistanceUniform = tryGetUniformLocation2("clipDistance");
|
||||
}
|
||||
|
||||
public static IrisLodRenderProgram createProgram(String name, boolean isShadowPass, boolean translucent, ProgramSource source, CustomUniforms uniforms, DeferredWorldRenderingPipeline pipeline) {
|
||||
Map<PatchShaderType, String> transformed = TransformPatcher.patchDHTerrain(
|
||||
name,
|
||||
source.getVertexSource().orElseThrow(RuntimeException::new),
|
||||
source.getTessControlSource().orElse(null),
|
||||
source.getTessEvalSource().orElse(null),
|
||||
source.getGeometrySource().orElse(null),
|
||||
source.getFragmentSource().orElseThrow(RuntimeException::new),
|
||||
pipeline.getTextureMap());
|
||||
String vertex = transformed.get(PatchShaderType.VERTEX);
|
||||
String tessControl = transformed.get(PatchShaderType.TESS_CONTROL);
|
||||
String tessEval = transformed.get(PatchShaderType.TESS_EVAL);
|
||||
String geometry = transformed.get(PatchShaderType.GEOMETRY);
|
||||
String fragment = transformed.get(PatchShaderType.FRAGMENT);
|
||||
PatchedShaderPrinter.debugPatchedShaders(source.getName(), vertex, geometry, tessControl, tessEval, fragment);
|
||||
|
||||
List<BufferBlendOverride> bufferOverrides = new ArrayList<>();
|
||||
|
||||
source.getDirectives().getBufferBlendOverrides().forEach(information -> {
|
||||
int index = Ints.indexOf(source.getDirectives().getDrawBuffers(), information.getIndex());
|
||||
if (index > -1) {
|
||||
bufferOverrides.add(new BufferBlendOverride(index, information.getBlendMode()));
|
||||
}
|
||||
});
|
||||
|
||||
return new IrisLodRenderProgram(name, isShadowPass, translucent, source.getDirectives().getBlendModeOverride().orElse(null), bufferOverrides.toArray(BufferBlendOverride[]::new), vertex, tessControl, tessEval, geometry, fragment, uniforms, pipeline);
|
||||
}
|
||||
|
||||
// Noise Uniforms
|
||||
|
||||
public int tryGetUniformLocation2(CharSequence name) {
|
||||
return GLStateManager.glGetUniformLocation(this.id, name);
|
||||
}
|
||||
|
||||
public void setUniform(int index, Matrix4fc matrix) {
|
||||
if (index == -1 || matrix == null) return;
|
||||
|
||||
try (MemoryStack stack = MemoryStack.stackPush()) {
|
||||
FloatBuffer buffer = stack.callocFloat(16);
|
||||
matrix.get(buffer);
|
||||
buffer.rewind();
|
||||
|
||||
GLStateManager.glUniformMatrix4(index, false, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public void setUniform(int index, Matrix3f matrix) {
|
||||
if (index == -1) return;
|
||||
|
||||
try (MemoryStack stack = MemoryStack.stackPush()) {
|
||||
FloatBuffer buffer = stack.callocFloat(9);
|
||||
matrix.get(buffer);
|
||||
buffer.rewind();
|
||||
|
||||
GLStateManager.glUniformMatrix3(index, false, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
// Override ShaderProgram.bind()
|
||||
public void bind() {
|
||||
GLStateManager.glUseProgram(id);
|
||||
if (blend != null) blend.apply();
|
||||
|
||||
for (BufferBlendOverride override : bufferBlendOverrides) {
|
||||
override.apply();
|
||||
}
|
||||
}
|
||||
|
||||
public void unbind() {
|
||||
GLStateManager.glUseProgram(0);
|
||||
ProgramUniforms.clearActiveUniforms();
|
||||
ProgramSamplers.clearActiveSamplers();
|
||||
BlendModeOverride.restore();
|
||||
}
|
||||
|
||||
public void free() {
|
||||
GLStateManager.glDeleteProgram(id);
|
||||
}
|
||||
|
||||
public void fillUniformData(Matrix4fc projection, Matrix4fc modelView, int worldYOffset, float partialTicks) {
|
||||
GLStateManager.glUseProgram(id);
|
||||
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0 + IrisSamplers.LIGHTMAP_TEXTURE_UNIT);
|
||||
DynamicTexture lightmapTexture = ((EntityRendererAccessor) Minecraft.getMinecraft().entityRenderer).getLightmapTexture();
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, lightmapTexture.getGlTextureId());
|
||||
setUniform(modelViewUniform, modelView);
|
||||
setUniform(modelViewInverseUniform, modelView.invert(tempMat4a));
|
||||
setUniform(projectionUniform, projection);
|
||||
setUniform(projectionInverseUniform, projection.invert(tempMat4b));
|
||||
setUniform(normalMatrix3fUniform, tempMat4a.set(modelView).invert().transpose3x3(tempMat3));
|
||||
|
||||
setUniform(mircoOffsetUniform, 0.01f); // 0.01 block offset
|
||||
|
||||
// setUniform(skyLightUniform, skyLight);
|
||||
|
||||
if (worldYOffsetUniform != -1) setUniform(worldYOffsetUniform, (float) worldYOffset);
|
||||
|
||||
// Fog/Clip Uniforms
|
||||
float dhNearClipDistance = DhApi.Delayed.renderProxy.getNearClipPlaneDistanceInBlocks(partialTicks);
|
||||
setUniform(clipDistanceUniform, dhNearClipDistance);
|
||||
|
||||
samplers.update();
|
||||
uniforms.update();
|
||||
|
||||
customUniforms.push(this);
|
||||
|
||||
images.update();
|
||||
}
|
||||
|
||||
private void setUniform(int index, float value) {
|
||||
GLStateManager.glUniform1f(index, value);
|
||||
}
|
||||
|
||||
public void setModelPos(DhApiVec3f modelPos) {
|
||||
setUniform(modelOffsetUniform, modelPos);
|
||||
}
|
||||
|
||||
private void setUniform(int index, DhApiVec3f pos) {
|
||||
GLStateManager.glUniform3f(index, pos.x, pos.y, pos.z);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,383 @@
|
||||
package net.coderbot.iris.compat.dh;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.rendering.RenderingState;
|
||||
import com.seibel.distanthorizons.api.DhApi;
|
||||
import com.seibel.distanthorizons.api.enums.rendering.EDhApiFogDrawMode;
|
||||
import com.seibel.distanthorizons.api.enums.rendering.EDhApiRenderPass;
|
||||
import com.seibel.distanthorizons.api.interfaces.override.IDhApiOverrideable;
|
||||
import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiFramebuffer;
|
||||
import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiGenericObjectShaderProgram;
|
||||
import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiShadowCullingFrustum;
|
||||
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiAfterDhInitEvent;
|
||||
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeApplyShaderRenderEvent;
|
||||
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeBufferRenderEvent;
|
||||
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeDeferredRenderEvent;
|
||||
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeGenericObjectRenderEvent;
|
||||
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeGenericRenderSetupEvent;
|
||||
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeRenderCleanupEvent;
|
||||
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeRenderEvent;
|
||||
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeRenderPassEvent;
|
||||
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeRenderSetupEvent;
|
||||
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeTextureClearEvent;
|
||||
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiColorDepthTextureCreatedEvent;
|
||||
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiCancelableEventParam;
|
||||
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam;
|
||||
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
|
||||
import com.seibel.distanthorizons.coreapi.DependencyInjection.OverrideInjector;
|
||||
import net.coderbot.iris.Iris;
|
||||
import net.coderbot.iris.pipeline.ShadowRenderer;
|
||||
import net.coderbot.iris.pipeline.WorldRenderingPipeline;
|
||||
import net.coderbot.iris.shadows.ShadowRenderingState;
|
||||
import net.coderbot.iris.uniforms.CapturedRenderingState;
|
||||
import net.irisshaders.iris.api.v0.IrisApi;
|
||||
import org.joml.Matrix4f;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
public class LodRendererEvents {
|
||||
// TODO: Query actual world min height for Cubic Chunks compatibility
|
||||
private static final int WORLD_MIN_Y = 0;
|
||||
|
||||
private static boolean eventHandlersBound = false;
|
||||
|
||||
private static boolean atTranslucent = false;
|
||||
private static int textureWidth;
|
||||
private static int textureHeight;
|
||||
private static final Matrix4f tempMat4 = new Matrix4f();
|
||||
|
||||
|
||||
// constructor //
|
||||
|
||||
public static void setupEventHandlers() {
|
||||
if (!eventHandlersBound) {
|
||||
eventHandlersBound = true;
|
||||
Iris.logger.info("Queuing DH event binding...");
|
||||
|
||||
DhApiAfterDhInitEvent beforeCleanupEvent = new DhApiAfterDhInitEvent() {
|
||||
@Override
|
||||
public void afterDistantHorizonsInit(DhApiEventParam<Void> event) {
|
||||
Iris.logger.info("DH Ready, binding Iris event handlers...");
|
||||
|
||||
Iris.loadShaderpackWhenPossible();
|
||||
|
||||
setupSetDeferredBeforeRenderingEvent();
|
||||
setupReconnectDepthTextureEvent();
|
||||
setupGenericEvent();
|
||||
setupCreateDepthTextureEvent();
|
||||
setupTransparentRendererEventCancling();
|
||||
setupBeforeBufferClearEvent();
|
||||
setupBeforeRenderCleanupEvent();
|
||||
beforeBufferRenderEvent();
|
||||
setupBeforeRenderFrameBufferBinding();
|
||||
setupBeforeRenderPassEvent();
|
||||
setupBeforeApplyShaderEvent();
|
||||
DHCompatInternal.dhEnabled = DhApi.Delayed.configs.graphics().renderingEnabled().getValue();
|
||||
Iris.logger.info("DH Iris events bound.");
|
||||
}
|
||||
};
|
||||
DhApi.events.bind(DhApiAfterDhInitEvent.class, beforeCleanupEvent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// setup event handlers //
|
||||
|
||||
|
||||
private static void setupSetDeferredBeforeRenderingEvent() {
|
||||
DhApiBeforeRenderEvent beforeRenderEvent = new DhApiBeforeRenderEvent() {
|
||||
// this event is called before DH starts any rendering prep
|
||||
// canceling it will prevent DH from rendering for that frame
|
||||
@Override
|
||||
public void beforeRender(DhApiCancelableEventParam<DhApiRenderParam> event) {
|
||||
|
||||
DhApi.Delayed.renderProxy.setDeferTransparentRendering(IrisApi.getInstance().isShaderPackInUse() && getInstance().shouldOverride);
|
||||
DhApi.Delayed.configs.graphics().fog().drawMode().setValue(getInstance().shouldOverride ? EDhApiFogDrawMode.FOG_DISABLED : EDhApiFogDrawMode.FOG_ENABLED);
|
||||
}
|
||||
};
|
||||
|
||||
DhApi.events.bind(DhApiBeforeRenderEvent.class, beforeRenderEvent);
|
||||
}
|
||||
|
||||
private static void setupReconnectDepthTextureEvent() {
|
||||
DhApiBeforeTextureClearEvent beforeRenderEvent = new DhApiBeforeTextureClearEvent() {
|
||||
@Override
|
||||
public void beforeClear(DhApiCancelableEventParam<DhApiRenderParam> event) {
|
||||
var getResult = DhApi.Delayed.renderProxy.getDhDepthTextureId();
|
||||
if (getResult.success) {
|
||||
int depthTextureId = getResult.payload;
|
||||
getInstance().reconnectDHTextures(depthTextureId);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
DhApi.events.bind(DhApiBeforeTextureClearEvent.class, beforeRenderEvent);
|
||||
}
|
||||
|
||||
private static void setupGenericEvent() {
|
||||
DhApiBeforeGenericRenderSetupEvent beforeRenderEvent = new DhApiBeforeGenericRenderSetupEvent() {
|
||||
@Override
|
||||
public void beforeSetup(DhApiEventParam<DhApiRenderParam> dhApiEventParam) {
|
||||
if (getInstance().getGenericFB() != null) {
|
||||
getInstance().getGenericFB().bind();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
DhApiBeforeGenericObjectRenderEvent beforeDrawEvent = new DhApiBeforeGenericObjectRenderEvent() {
|
||||
@Override
|
||||
public void beforeRender(DhApiCancelableEventParam<EventParam> dhApiCancelableEventParam) {
|
||||
if (dhApiCancelableEventParam.value.resourceLocationPath.equalsIgnoreCase("Clouds")) {
|
||||
if (getInstance().avoidRenderingClouds()) {
|
||||
dhApiCancelableEventParam.cancelEvent();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
DhApi.events.bind(DhApiBeforeGenericRenderSetupEvent.class, beforeRenderEvent);
|
||||
DhApi.events.bind(DhApiBeforeGenericObjectRenderEvent.class, beforeDrawEvent);
|
||||
}
|
||||
|
||||
private static DHCompatInternal getInstance() {
|
||||
return Iris.getPipelineManager().getPipeline().map(WorldRenderingPipeline::getDHCompat).map(DHCompat::getInstance).orElse(DHCompatInternal.SHADERLESS);
|
||||
}
|
||||
|
||||
private static void setupCreateDepthTextureEvent() {
|
||||
DhApiColorDepthTextureCreatedEvent beforeRenderEvent = new DhApiColorDepthTextureCreatedEvent() {
|
||||
@Override
|
||||
public void onResize(DhApiEventParam<EventParam> input) {
|
||||
textureWidth = input.value.newWidth;
|
||||
textureHeight = input.value.newHeight;
|
||||
}
|
||||
};
|
||||
|
||||
DhApi.events.bind(DhApiColorDepthTextureCreatedEvent.class, beforeRenderEvent);
|
||||
}
|
||||
|
||||
private static void setupTransparentRendererEventCancling() {
|
||||
DhApiBeforeRenderEvent beforeRenderEvent = new DhApiBeforeRenderEvent() {
|
||||
@Override
|
||||
public void beforeRender(DhApiCancelableEventParam<DhApiRenderParam> event) {
|
||||
if (ShadowRenderingState.areShadowsCurrentlyBeingRendered() && (!getInstance().shouldOverrideShadow)) {
|
||||
event.cancelEvent();
|
||||
}
|
||||
}
|
||||
};
|
||||
DhApiBeforeDeferredRenderEvent beforeRenderEvent2 = new DhApiBeforeDeferredRenderEvent() {
|
||||
@Override
|
||||
public void beforeRender(DhApiCancelableEventParam<DhApiRenderParam> event) {
|
||||
if (ShadowRenderingState.areShadowsCurrentlyBeingRendered() && (!getInstance().shouldOverrideShadow)) {
|
||||
event.cancelEvent();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
DhApi.events.bind(DhApiBeforeRenderEvent.class, beforeRenderEvent);
|
||||
DhApi.events.bind(DhApiBeforeDeferredRenderEvent.class, beforeRenderEvent2);
|
||||
}
|
||||
|
||||
private static void setupBeforeRenderCleanupEvent() {
|
||||
DhApiBeforeRenderCleanupEvent beforeCleanupEvent = new DhApiBeforeRenderCleanupEvent() {
|
||||
@Override
|
||||
public void beforeCleanup(DhApiEventParam<DhApiRenderParam> event) {
|
||||
if (getInstance().shouldOverride) {
|
||||
if (ShadowRenderingState.areShadowsCurrentlyBeingRendered()) {
|
||||
getInstance().getShadowShader().unbind();
|
||||
} else {
|
||||
getInstance().getSolidShader().unbind();
|
||||
if (atTranslucent) {
|
||||
GLStateManager.enableCull();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
DhApi.events.bind(DhApiBeforeRenderCleanupEvent.class, beforeCleanupEvent);
|
||||
}
|
||||
|
||||
private static void setupBeforeBufferClearEvent() {
|
||||
DhApiBeforeTextureClearEvent beforeCleanupEvent = new DhApiBeforeTextureClearEvent() {
|
||||
@Override
|
||||
public void beforeClear(DhApiCancelableEventParam<DhApiRenderParam> event) {
|
||||
if (event.value.renderPass == EDhApiRenderPass.OPAQUE) {
|
||||
if (ShadowRenderingState.areShadowsCurrentlyBeingRendered()) {
|
||||
event.cancelEvent();
|
||||
} else if (getInstance().shouldOverride) {
|
||||
GLStateManager.glClear(GL11.GL_DEPTH_BUFFER_BIT);
|
||||
event.cancelEvent();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
DhApi.events.bind(DhApiBeforeTextureClearEvent.class, beforeCleanupEvent);
|
||||
}
|
||||
|
||||
private static void beforeBufferRenderEvent() {
|
||||
DhApiBeforeBufferRenderEvent beforeCleanupEvent = new DhApiBeforeBufferRenderEvent() {
|
||||
@Override
|
||||
public void beforeRender(DhApiEventParam<EventParam> input) {
|
||||
DHCompatInternal instance = getInstance();
|
||||
if (instance.shouldOverride) {
|
||||
DhApiVec3f modelPos = input.value.modelPos;
|
||||
if (ShadowRenderingState.areShadowsCurrentlyBeingRendered()) {
|
||||
instance.getShadowShader().bind();
|
||||
instance.getShadowShader().setModelPos(modelPos);
|
||||
} else if (atTranslucent) {
|
||||
instance.getTranslucentShader().bind();
|
||||
instance.getTranslucentShader().setModelPos(modelPos);
|
||||
} else {
|
||||
instance.getSolidShader().bind();
|
||||
instance.getSolidShader().setModelPos(modelPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
DhApi.events.bind(DhApiBeforeBufferRenderEvent.class, beforeCleanupEvent);
|
||||
}
|
||||
|
||||
private static void setupBeforeRenderFrameBufferBinding() {
|
||||
DhApiBeforeRenderSetupEvent beforeRenderPassEvent = new DhApiBeforeRenderSetupEvent() {
|
||||
@Override
|
||||
public void beforeSetup(DhApiEventParam<DhApiRenderParam> event) {
|
||||
DHCompatInternal instance = getInstance();
|
||||
|
||||
OverrideInjector.INSTANCE.unbind(IDhApiShadowCullingFrustum.class, (IDhApiOverrideable) ShadowRenderer.FRUSTUM);
|
||||
OverrideInjector.INSTANCE.unbind(IDhApiFramebuffer.class, instance.getShadowFBWrapper());
|
||||
OverrideInjector.INSTANCE.unbind(IDhApiFramebuffer.class, instance.getSolidFBWrapper());
|
||||
OverrideInjector.INSTANCE.unbind(IDhApiGenericObjectShaderProgram.class, instance.getGenericShader());
|
||||
|
||||
if (instance.shouldOverride) {
|
||||
if (instance.getGenericShader() != null) {
|
||||
OverrideInjector.INSTANCE.bind(IDhApiGenericObjectShaderProgram.class, instance.getGenericShader());
|
||||
}
|
||||
if (ShadowRenderingState.areShadowsCurrentlyBeingRendered() && instance.shouldOverrideShadow) {
|
||||
OverrideInjector.INSTANCE.bind(IDhApiFramebuffer.class, instance.getShadowFBWrapper());
|
||||
OverrideInjector.INSTANCE.bind(IDhApiShadowCullingFrustum.class, (IDhApiOverrideable) ShadowRenderer.FRUSTUM);
|
||||
} else {
|
||||
OverrideInjector.INSTANCE.bind(IDhApiFramebuffer.class, instance.getSolidFBWrapper());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
DhApi.events.bind(DhApiBeforeRenderSetupEvent.class, beforeRenderPassEvent);
|
||||
|
||||
}
|
||||
|
||||
private static void setupBeforeRenderPassEvent() {
|
||||
DhApiBeforeRenderPassEvent beforeCleanupEvent = new DhApiBeforeRenderPassEvent() {
|
||||
@Override
|
||||
public void beforeRender(DhApiEventParam<DhApiRenderParam> event) {
|
||||
DHCompatInternal instance = getInstance();
|
||||
|
||||
// config overrides
|
||||
if (instance.shouldOverride) {
|
||||
DhApi.Delayed.configs.graphics().ambientOcclusion().enabled().setValue(false);
|
||||
DhApi.Delayed.configs.graphics().fog().drawMode().setValue(EDhApiFogDrawMode.FOG_DISABLED);
|
||||
|
||||
if (event.value.renderPass == EDhApiRenderPass.OPAQUE_AND_TRANSPARENT) {
|
||||
Iris.logger.error("Unexpected; somehow the Opaque + Translucent pass ran with shaders on.");
|
||||
}
|
||||
} else {
|
||||
DhApi.Delayed.configs.graphics().ambientOcclusion().enabled().clearValue();
|
||||
DhApi.Delayed.configs.graphics().fog().drawMode().clearValue();
|
||||
}
|
||||
|
||||
|
||||
// cleanup
|
||||
if (event.value.renderPass == EDhApiRenderPass.OPAQUE) {
|
||||
if (instance.shouldOverride) {
|
||||
if (ShadowRenderingState.areShadowsCurrentlyBeingRendered()) {
|
||||
instance.getShadowShader().bind();
|
||||
} else {
|
||||
instance.getSolidShader().bind();
|
||||
}
|
||||
atTranslucent = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// opaque
|
||||
if (event.value.renderPass == EDhApiRenderPass.OPAQUE) {
|
||||
float partialTicks = event.value.partialTicks;
|
||||
|
||||
if (instance.shouldOverride) {
|
||||
if (ShadowRenderingState.areShadowsCurrentlyBeingRendered()) {
|
||||
instance.getShadowShader().fillUniformData(
|
||||
ShadowRenderer.PROJECTION, ShadowRenderer.MODELVIEW,
|
||||
WORLD_MIN_Y,
|
||||
partialTicks);
|
||||
} else {
|
||||
Matrix4f projection = RenderingState.INSTANCE.getProjectionMatrix();;
|
||||
|
||||
instance.getSolidShader().fillUniformData(
|
||||
tempMat4.setPerspective(projection.perspectiveFov(), projection.m11() / projection.m00(), event.value.nearClipPlane, event.value.farClipPlane),
|
||||
RenderingState.INSTANCE.getModelViewMatrix(),
|
||||
WORLD_MIN_Y,
|
||||
partialTicks);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// transparent
|
||||
if (event.value.renderPass == EDhApiRenderPass.TRANSPARENT) {
|
||||
float partialTicks = event.value.partialTicks;
|
||||
int depthTextureId = DhApi.Delayed.renderProxy.getDhDepthTextureId().payload;
|
||||
|
||||
if (instance.shouldOverrideShadow && ShadowRenderingState.areShadowsCurrentlyBeingRendered()) {
|
||||
instance.getShadowShader().bind();
|
||||
instance.getShadowFB().bind();
|
||||
atTranslucent = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (instance.shouldOverride && instance.getTranslucentFB() != null) {
|
||||
instance.copyTranslucents(textureWidth, textureHeight);
|
||||
instance.getTranslucentShader().bind();
|
||||
Matrix4f projection = RenderingState.INSTANCE.getProjectionMatrix();
|
||||
GLStateManager.disableCull();
|
||||
|
||||
instance.getTranslucentShader().fillUniformData(
|
||||
new Matrix4f().setPerspective(projection.perspectiveFov(), projection.m11() / projection.m00(), event.value.nearClipPlane, event.value.farClipPlane),
|
||||
RenderingState.INSTANCE.getModelViewMatrix(),
|
||||
WORLD_MIN_Y,
|
||||
partialTicks);
|
||||
|
||||
instance.getTranslucentFB().bind();
|
||||
}
|
||||
|
||||
atTranslucent = true;
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
DhApi.events.bind(DhApiBeforeRenderPassEvent.class, beforeCleanupEvent);
|
||||
}
|
||||
|
||||
private static void setupBeforeApplyShaderEvent() {
|
||||
DhApiBeforeApplyShaderRenderEvent beforeApplyShaderEvent = new DhApiBeforeApplyShaderRenderEvent() {
|
||||
@Override
|
||||
public void beforeRender(DhApiCancelableEventParam<DhApiRenderParam> event) {
|
||||
if (IrisApi.getInstance().isShaderPackInUse()) {
|
||||
DHCompatInternal instance = getInstance();
|
||||
|
||||
OverrideInjector.INSTANCE.unbind(IDhApiShadowCullingFrustum.class, (IDhApiOverrideable) ShadowRenderer.FRUSTUM);
|
||||
OverrideInjector.INSTANCE.unbind(IDhApiFramebuffer.class, instance.getShadowFBWrapper());
|
||||
OverrideInjector.INSTANCE.unbind(IDhApiFramebuffer.class, instance.getSolidFBWrapper());
|
||||
|
||||
event.cancelEvent();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
DhApi.events.bind(DhApiBeforeApplyShaderRenderEvent.class, beforeApplyShaderEvent);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -33,12 +33,18 @@ public class IrisConfig {
|
||||
*/
|
||||
private boolean disableUpdateMessage;
|
||||
|
||||
/**
|
||||
* If debug features should be enabled. Gives much more detailed OpenGL error outputs at the cost of performance.
|
||||
*/
|
||||
private boolean enableDebugOptions;
|
||||
|
||||
private final Path propertiesPath;
|
||||
|
||||
public IrisConfig(Path propertiesPath) {
|
||||
shaderPackName = null;
|
||||
enableShaders = true;
|
||||
disableUpdateMessage = false;
|
||||
enableDebugOptions = false;
|
||||
this.propertiesPath = propertiesPath;
|
||||
}
|
||||
|
||||
@@ -103,6 +109,10 @@ public class IrisConfig {
|
||||
this.enableShaders = enabled;
|
||||
}
|
||||
|
||||
public boolean areDebugOptionsEnabled() {
|
||||
return enableDebugOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* loads the config file and then populates the string, int, and boolean entries with the parsed entries
|
||||
*
|
||||
@@ -121,6 +131,7 @@ public class IrisConfig {
|
||||
}
|
||||
shaderPackName = properties.getProperty("shaderPack");
|
||||
enableShaders = !"false".equals(properties.getProperty("enableShaders"));
|
||||
enableDebugOptions = "true".equals(properties.getProperty("enableDebugOptions"));
|
||||
disableUpdateMessage = "true".equals(properties.getProperty("disableUpdateMessage"));
|
||||
// TODO: GUI
|
||||
try {
|
||||
@@ -147,6 +158,7 @@ public class IrisConfig {
|
||||
final Properties properties = new Properties();
|
||||
properties.setProperty("shaderPack", getShaderPackName().orElse(""));
|
||||
properties.setProperty("enableShaders", enableShaders ? "true" : "false");
|
||||
properties.setProperty("enableDebugOptions", enableDebugOptions ? "true" : "false");
|
||||
properties.setProperty("disableUpdateMessage", disableUpdateMessage ? "true" : "false");
|
||||
properties.setProperty("maxShadowRenderDistance", String.valueOf(IrisVideoSettings.shadowDistance));
|
||||
// NB: This uses ISO-8859-1 with unicode escapes as the encoding
|
||||
|
||||
@@ -8,6 +8,7 @@ public enum RenderCondition {
|
||||
CLOUDS,
|
||||
DESTROY,
|
||||
BLOCK_ENTITIES,
|
||||
BLOCK_ENTITIES_TRANSLUCENT,
|
||||
BEACON_BEAM,
|
||||
ENTITIES,
|
||||
ENTITIES_TRANSLUCENT,
|
||||
@@ -17,6 +18,7 @@ public enum RenderCondition {
|
||||
HAND_TRANSLUCENT,
|
||||
RAIN_SNOW,
|
||||
WORLD_BORDER,
|
||||
SHADOW_TRANSLUCENT,
|
||||
// NB: Must be last due to implementation details of DeferredWorldRenderingPipeline
|
||||
SHADOW
|
||||
}
|
||||
@@ -45,6 +45,12 @@ public class GlFramebuffer extends GlResource {
|
||||
this.hasDepthAttachment = true;
|
||||
}
|
||||
|
||||
public void addDepthAttachmentBypass(int texture) {
|
||||
final int fb = getGlId();
|
||||
RenderSystem.framebufferTexture2D(fb, GL30.GL_FRAMEBUFFER, GL30.GL_DEPTH_ATTACHMENT, GL11.GL_TEXTURE_2D, texture, 0);
|
||||
this.hasDepthAttachment = true;
|
||||
}
|
||||
|
||||
public void addColorAttachment(int index, int texture) {
|
||||
final int fb = getGlId();
|
||||
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.google.common.collect.ImmutableList;
|
||||
import com.gtnewhorizons.angelica.Tags;
|
||||
import com.gtnewhorizons.angelica.config.AngelicaConfig;
|
||||
import cpw.mods.fml.common.Loader;
|
||||
import net.coderbot.iris.compat.dh.DHCompat;
|
||||
import net.coderbot.iris.parsing.BiomeCategories;
|
||||
import net.coderbot.iris.pipeline.HandRenderer;
|
||||
import net.coderbot.iris.pipeline.WorldRenderingPhase;
|
||||
@@ -77,10 +78,32 @@ public class StandardMacros {
|
||||
define(standardDefines, "MC_SPECULAR_MAP");
|
||||
define(standardDefines, "MC_RENDER_QUALITY", "1.0");
|
||||
define(standardDefines, "MC_SHADOW_QUALITY", "1.0");
|
||||
define(standardDefines, "IS_ANGELICA");
|
||||
if (AngelicaConfig.defineIsIris) {
|
||||
define(standardDefines, "IS_IRIS");
|
||||
}
|
||||
define(standardDefines, "IS_ANGELICA");
|
||||
if (AngelicaConfig.defineIsIris) {
|
||||
define(standardDefines, "IS_IRIS");
|
||||
}
|
||||
|
||||
if (DHCompat.hasRenderingEnabled()) {
|
||||
define(standardDefines, "DISTANT_HORIZONS");
|
||||
}
|
||||
|
||||
define(standardDefines, "DH_BLOCK_UNKNOWN", String.valueOf(0));
|
||||
define(standardDefines, "DH_BLOCK_LEAVES", String.valueOf(1));
|
||||
define(standardDefines, "DH_BLOCK_STONE", String.valueOf(2));
|
||||
define(standardDefines, "DH_BLOCK_WOOD", String.valueOf(3));
|
||||
define(standardDefines, "DH_BLOCK_METAL", String.valueOf(4));
|
||||
define(standardDefines, "DH_BLOCK_DIRT", String.valueOf(5));
|
||||
define(standardDefines, "DH_BLOCK_LAVA", String.valueOf(6));
|
||||
define(standardDefines, "DH_BLOCK_DEEPSLATE", String.valueOf(7));
|
||||
define(standardDefines, "DH_BLOCK_SNOW", String.valueOf(8));
|
||||
define(standardDefines, "DH_BLOCK_SAND", String.valueOf(9));
|
||||
define(standardDefines, "DH_BLOCK_TERRACOTTA", String.valueOf(10));
|
||||
define(standardDefines, "DH_BLOCK_NETHER_STONE", String.valueOf(11));
|
||||
define(standardDefines, "DH_BLOCK_WATER", String.valueOf(12));
|
||||
define(standardDefines, "DH_BLOCK_GRASS", String.valueOf(13));
|
||||
define(standardDefines, "DH_BLOCK_AIR", String.valueOf(14));
|
||||
define(standardDefines, "DH_BLOCK_ILLUMINATED", String.valueOf(15));
|
||||
|
||||
define(standardDefines, "ANGELICA_VERSION", makeAngelicaVersion());
|
||||
define(standardDefines, "MC_HAND_DEPTH", Float.toString(HandRenderer.DEPTH));
|
||||
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
package net.coderbot.iris.gl.state;
|
||||
|
||||
/**
|
||||
* Holds update notifiers for PBR texture changes.
|
||||
* Holds some standard update notifiers for various elements of GL state.
|
||||
*/
|
||||
public class StateUpdateNotifiers {
|
||||
public static ValueUpdateNotifier fogModeNotifier;
|
||||
public static ValueUpdateNotifier fogStartNotifier;
|
||||
public static ValueUpdateNotifier fogEndNotifier;
|
||||
public static ValueUpdateNotifier fogDensityNotifier;
|
||||
public static ValueUpdateNotifier blendFuncNotifier;
|
||||
public static ValueUpdateNotifier bindTextureNotifier;
|
||||
public static ValueUpdateNotifier normalTextureChangeNotifier;
|
||||
public static ValueUpdateNotifier specularTextureChangeNotifier;
|
||||
public static ValueUpdateNotifier phaseChangeNotifier;
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
package net.coderbot.iris.gl.uniform;
|
||||
|
||||
import net.coderbot.iris.gl.state.ValueUpdateNotifier;
|
||||
import org.joml.Vector2i;
|
||||
import org.joml.Vector3i;
|
||||
import org.joml.Vector4f;
|
||||
import org.joml.Vector4i;
|
||||
import org.joml.Vector2ic;
|
||||
import org.joml.Vector3ic;
|
||||
import org.joml.Vector4fc;
|
||||
import org.joml.Vector4ic;
|
||||
|
||||
import java.util.function.DoubleSupplier;
|
||||
import java.util.function.IntSupplier;
|
||||
@@ -37,19 +37,19 @@ public interface DynamicLocationalUniformHolder extends LocationalUniformHolder,
|
||||
return this;
|
||||
}
|
||||
|
||||
default DynamicLocationalUniformHolder uniform2i(String name, Supplier<Vector2i> value, ValueUpdateNotifier notifier) {
|
||||
default DynamicLocationalUniformHolder uniform2i(String name, Supplier<Vector2ic> value, ValueUpdateNotifier notifier) {
|
||||
location(name, UniformType.VEC2I).ifPresent(id -> addDynamicUniform(new Vector2IntegerJomlUniform(id, value, notifier), notifier));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
default DynamicUniformHolder uniform3i(String name, Supplier<Vector3i> value, ValueUpdateNotifier notifier) {
|
||||
default DynamicUniformHolder uniform3i(String name, Supplier<Vector3ic> value, ValueUpdateNotifier notifier) {
|
||||
location(name, UniformType.VEC3I).ifPresent(id -> addDynamicUniform(new Vector3IntegerJomlUniform(id, value, notifier), notifier));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
default DynamicUniformHolder uniform4f(String name, Supplier<Vector4f> value, ValueUpdateNotifier notifier) {
|
||||
default DynamicUniformHolder uniform4f(String name, Supplier<Vector4fc> value, ValueUpdateNotifier notifier) {
|
||||
location(name, UniformType.VEC4).ifPresent(id -> addDynamicUniform(new Vector4Uniform(id, value, notifier), notifier));
|
||||
|
||||
return this;
|
||||
@@ -60,7 +60,7 @@ public interface DynamicLocationalUniformHolder extends LocationalUniformHolder,
|
||||
return this;
|
||||
}
|
||||
|
||||
default DynamicUniformHolder uniform4i(String name, Supplier<Vector4i> value, ValueUpdateNotifier notifier) {
|
||||
default DynamicUniformHolder uniform4i(String name, Supplier<Vector4ic> value, ValueUpdateNotifier notifier) {
|
||||
location(name, UniformType.VEC4I).ifPresent(id -> addDynamicUniform(new Vector4IntegerJomlUniform(id, value, notifier), notifier));
|
||||
|
||||
return this;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package net.coderbot.iris.gl.uniform;
|
||||
|
||||
import net.coderbot.iris.gl.state.ValueUpdateNotifier;
|
||||
import org.joml.Vector2i;
|
||||
import org.joml.Vector3i;
|
||||
import org.joml.Vector4f;
|
||||
import org.joml.Vector4i;
|
||||
import org.joml.Vector2ic;
|
||||
import org.joml.Vector3ic;
|
||||
import org.joml.Vector4fc;
|
||||
import org.joml.Vector4ic;
|
||||
|
||||
import java.util.function.DoubleSupplier;
|
||||
import java.util.function.IntSupplier;
|
||||
@@ -15,9 +15,9 @@ public interface DynamicUniformHolder extends UniformHolder {
|
||||
DynamicUniformHolder uniform1f(String name, IntSupplier value, ValueUpdateNotifier notifier);
|
||||
DynamicUniformHolder uniform1f(String name, DoubleSupplier value, ValueUpdateNotifier notifier);
|
||||
DynamicUniformHolder uniform1i(String name, IntSupplier value, ValueUpdateNotifier notifier);
|
||||
DynamicUniformHolder uniform2i(String name, Supplier<Vector2i> value, ValueUpdateNotifier notifier);
|
||||
DynamicUniformHolder uniform3i(String name, Supplier<Vector3i> value, ValueUpdateNotifier notifier);
|
||||
DynamicUniformHolder uniform4f(String name, Supplier<Vector4f> value, ValueUpdateNotifier notifier);
|
||||
DynamicUniformHolder uniform2i(String name, Supplier<Vector2ic> value, ValueUpdateNotifier notifier);
|
||||
DynamicUniformHolder uniform3i(String name, Supplier<Vector3ic> value, ValueUpdateNotifier notifier);
|
||||
DynamicUniformHolder uniform4f(String name, Supplier<Vector4fc> value, ValueUpdateNotifier notifier);
|
||||
DynamicUniformHolder uniform4fArray(String name, Supplier<float[]> value, ValueUpdateNotifier notifier);
|
||||
DynamicUniformHolder uniform4i(String name, Supplier<Vector4i> value, ValueUpdateNotifier notifier);
|
||||
DynamicUniformHolder uniform4i(String name, Supplier<Vector4ic> value, ValueUpdateNotifier notifier);
|
||||
}
|
||||
@@ -2,12 +2,15 @@ package net.coderbot.iris.gl.uniform;
|
||||
|
||||
import net.minecraft.util.Vec3;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Matrix4fc;
|
||||
import org.joml.Vector2f;
|
||||
import org.joml.Vector2i;
|
||||
import org.joml.Vector2ic;
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.Vector3fc;
|
||||
import org.joml.Vector3i;
|
||||
import org.joml.Vector4f;
|
||||
import org.joml.Vector3ic;
|
||||
import org.joml.Vector4fc;
|
||||
|
||||
import java.util.OptionalInt;
|
||||
import java.util.function.BooleanSupplier;
|
||||
@@ -63,21 +66,21 @@ public interface LocationalUniformHolder extends UniformHolder {
|
||||
}
|
||||
|
||||
@Override
|
||||
default LocationalUniformHolder uniform2i(UniformUpdateFrequency updateFrequency, String name, Supplier<Vector2i> value) {
|
||||
default LocationalUniformHolder uniform2i(UniformUpdateFrequency updateFrequency, String name, Supplier<Vector2ic> value) {
|
||||
location(name, UniformType.VEC2I).ifPresent(id -> addUniform(updateFrequency, new Vector2IntegerJomlUniform(id, value)));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
default LocationalUniformHolder uniform3f(UniformUpdateFrequency updateFrequency, String name, Supplier<Vector3f> value) {
|
||||
default LocationalUniformHolder uniform3f(UniformUpdateFrequency updateFrequency, String name, Supplier<Vector3fc> value) {
|
||||
location(name, UniformType.VEC3).ifPresent(id -> addUniform(updateFrequency, new Vector3Uniform(id, value)));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
default LocationalUniformHolder uniform3i(UniformUpdateFrequency updateFrequency, String name, Supplier<Vector3i> value) {
|
||||
default LocationalUniformHolder uniform3i(UniformUpdateFrequency updateFrequency, String name, Supplier<Vector3ic> value) {
|
||||
location(name, UniformType.VEC3I).ifPresent(id -> addUniform(updateFrequency, new Vector3IntegerJomlUniform(id, value)));
|
||||
|
||||
return this;
|
||||
@@ -91,7 +94,7 @@ public interface LocationalUniformHolder extends UniformHolder {
|
||||
}
|
||||
|
||||
@Override
|
||||
default LocationalUniformHolder uniformTruncated3f(UniformUpdateFrequency updateFrequency, String name, Supplier<Vector4f> value) {
|
||||
default LocationalUniformHolder uniformTruncated3f(UniformUpdateFrequency updateFrequency, String name, Supplier<Vector4fc> value) {
|
||||
location(name, UniformType.VEC3).ifPresent(id -> addUniform(updateFrequency, Vector3Uniform.truncated(id, value)));
|
||||
|
||||
return this;
|
||||
@@ -105,7 +108,7 @@ public interface LocationalUniformHolder extends UniformHolder {
|
||||
}
|
||||
|
||||
@Override
|
||||
default LocationalUniformHolder uniform4f(UniformUpdateFrequency updateFrequency, String name, Supplier<Vector4f> value) {
|
||||
default LocationalUniformHolder uniform4f(UniformUpdateFrequency updateFrequency, String name, Supplier<Vector4fc> value) {
|
||||
location(name, UniformType.VEC4).ifPresent(id -> addUniform(updateFrequency, new Vector4Uniform(id, value)));
|
||||
|
||||
return this;
|
||||
@@ -119,7 +122,7 @@ public interface LocationalUniformHolder extends UniformHolder {
|
||||
}
|
||||
|
||||
@Override
|
||||
default LocationalUniformHolder uniformMatrix(UniformUpdateFrequency updateFrequency, String name, Supplier<Matrix4f> value) {
|
||||
default LocationalUniformHolder uniformMatrix(UniformUpdateFrequency updateFrequency, String name, Supplier<Matrix4fc> value) {
|
||||
location(name, UniformType.MAT4).ifPresent(id -> addUniform(updateFrequency, new MatrixUniform(id, value)));
|
||||
|
||||
return this;
|
||||
|
||||
@@ -2,6 +2,7 @@ package net.coderbot.iris.gl.uniform;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.RenderSystem;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Matrix4fc;
|
||||
import org.lwjgl.BufferUtils;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
@@ -10,9 +11,9 @@ import java.util.function.Supplier;
|
||||
public class MatrixUniform extends Uniform {
|
||||
private final FloatBuffer buffer = BufferUtils.createFloatBuffer(16);
|
||||
private Matrix4f cachedValue;
|
||||
private final Supplier<Matrix4f> value;
|
||||
private final Supplier<Matrix4fc> value;
|
||||
|
||||
MatrixUniform(int location, Supplier<Matrix4f> value) {
|
||||
MatrixUniform(int location, Supplier<Matrix4fc> value) {
|
||||
super(location);
|
||||
|
||||
this.cachedValue = null;
|
||||
@@ -21,7 +22,7 @@ public class MatrixUniform extends Uniform {
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
final Matrix4f newValue = value.get();
|
||||
final Matrix4fc newValue = value.get();
|
||||
if( newValue == null ){
|
||||
throw new RuntimeException("MatrixUniform value is null");
|
||||
}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
package net.coderbot.iris.gl.uniform;
|
||||
|
||||
import net.minecraft.util.Vec3;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Matrix4fc;
|
||||
import org.joml.Vector2f;
|
||||
import org.joml.Vector2i;
|
||||
import org.joml.Vector2ic;
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.Vector3fc;
|
||||
import org.joml.Vector3i;
|
||||
import org.joml.Vector4f;
|
||||
import org.joml.Vector3ic;
|
||||
import org.joml.Vector4fc;
|
||||
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.DoubleSupplier;
|
||||
@@ -27,23 +28,23 @@ public interface UniformHolder {
|
||||
|
||||
UniformHolder uniform2f(UniformUpdateFrequency updateFrequency, String name, Supplier<Vector2f> value);
|
||||
|
||||
UniformHolder uniform2i(UniformUpdateFrequency updateFrequency, String name, Supplier<Vector2i> value);
|
||||
UniformHolder uniform2i(UniformUpdateFrequency updateFrequency, String name, Supplier<Vector2ic> value);
|
||||
|
||||
UniformHolder uniform3f(UniformUpdateFrequency updateFrequency, String name, Supplier<Vector3f> value);
|
||||
UniformHolder uniform3f(UniformUpdateFrequency updateFrequency, String name, Supplier<Vector3fc> value);
|
||||
|
||||
UniformHolder uniform3i(UniformUpdateFrequency updateFrequency, String name, Supplier<Vector3i> value);
|
||||
UniformHolder uniform3i(UniformUpdateFrequency updateFrequency, String name, Supplier<Vector3ic> value);
|
||||
|
||||
UniformHolder uniformVanilla3f(UniformUpdateFrequency updateFrequency, String name, Supplier<Vec3> value);
|
||||
|
||||
UniformHolder uniformTruncated3f(UniformUpdateFrequency updateFrequency, String name, Supplier<Vector4f> value);
|
||||
UniformHolder uniformTruncated3f(UniformUpdateFrequency updateFrequency, String name, Supplier<Vector4fc> value);
|
||||
|
||||
UniformHolder uniform3d(UniformUpdateFrequency updateFrequency, String name, Supplier<Vector3d> value);
|
||||
|
||||
UniformHolder uniform4f(UniformUpdateFrequency updateFrequency, String name, Supplier<Vector4f> value);
|
||||
UniformHolder uniform4f(UniformUpdateFrequency updateFrequency, String name, Supplier<Vector4fc> value);
|
||||
|
||||
UniformHolder uniform4fArray(UniformUpdateFrequency updateFrequency, String name, Supplier<float[]> value);
|
||||
|
||||
UniformHolder uniformMatrix(UniformUpdateFrequency updateFrequency, String name, Supplier<Matrix4f> value);
|
||||
UniformHolder uniformMatrix(UniformUpdateFrequency updateFrequency, String name, Supplier<Matrix4fc> value);
|
||||
|
||||
UniformHolder uniformMatrixFromArray(UniformUpdateFrequency updateFrequency, String name, Supplier<float[]> value);
|
||||
|
||||
|
||||
@@ -3,21 +3,22 @@ package net.coderbot.iris.gl.uniform;
|
||||
import com.gtnewhorizons.angelica.glsm.RenderSystem;
|
||||
import net.coderbot.iris.gl.state.ValueUpdateNotifier;
|
||||
import org.joml.Vector2i;
|
||||
import org.joml.Vector2ic;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class Vector2IntegerJomlUniform extends Uniform {
|
||||
private Vector2i cachedValue;
|
||||
private final Supplier<Vector2i> value;
|
||||
private final Vector2i cachedValue;
|
||||
private final Supplier<Vector2ic> value;
|
||||
|
||||
Vector2IntegerJomlUniform(int location, Supplier<Vector2i> value) {
|
||||
Vector2IntegerJomlUniform(int location, Supplier<Vector2ic> value) {
|
||||
this(location, value, null);
|
||||
}
|
||||
|
||||
Vector2IntegerJomlUniform(int location, Supplier<Vector2i> value, ValueUpdateNotifier notifier) {
|
||||
Vector2IntegerJomlUniform(int location, Supplier<Vector2ic> value, ValueUpdateNotifier notifier) {
|
||||
super(location, notifier);
|
||||
|
||||
this.cachedValue = null;
|
||||
this.cachedValue = new Vector2i();
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@@ -31,11 +32,11 @@ public class Vector2IntegerJomlUniform extends Uniform {
|
||||
}
|
||||
|
||||
private void updateValue() {
|
||||
Vector2i newValue = value.get();
|
||||
Vector2ic newValue = value.get();
|
||||
|
||||
if (cachedValue == null || !newValue.equals(cachedValue)) {
|
||||
cachedValue = newValue;
|
||||
RenderSystem.uniform2i(this.location, newValue.x, newValue.y);
|
||||
if (!newValue.equals(cachedValue)) {
|
||||
cachedValue.set(newValue.x(), newValue.y());
|
||||
RenderSystem.uniform2i(this.location, cachedValue.x, cachedValue.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,21 +3,22 @@ package net.coderbot.iris.gl.uniform;
|
||||
import com.gtnewhorizons.angelica.glsm.RenderSystem;
|
||||
import net.coderbot.iris.gl.state.ValueUpdateNotifier;
|
||||
import org.joml.Vector3i;
|
||||
import org.joml.Vector3ic;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class Vector3IntegerJomlUniform extends Uniform {
|
||||
private Vector3i cachedValue;
|
||||
private final Supplier<Vector3i> value;
|
||||
private final Vector3i cachedValue;
|
||||
private final Supplier<Vector3ic> value;
|
||||
|
||||
Vector3IntegerJomlUniform(int location, Supplier<Vector3i> value) {
|
||||
Vector3IntegerJomlUniform(int location, Supplier<Vector3ic> value) {
|
||||
this(location, value, null);
|
||||
}
|
||||
|
||||
Vector3IntegerJomlUniform(int location, Supplier<Vector3i> value, ValueUpdateNotifier notifier) {
|
||||
Vector3IntegerJomlUniform(int location, Supplier<Vector3ic> value, ValueUpdateNotifier notifier) {
|
||||
super(location, notifier);
|
||||
|
||||
this.cachedValue = null;
|
||||
this.cachedValue = new Vector3i();
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@@ -31,11 +32,11 @@ public class Vector3IntegerJomlUniform extends Uniform {
|
||||
}
|
||||
|
||||
private void updateValue() {
|
||||
Vector3i newValue = value.get();
|
||||
Vector3ic newValue = value.get();
|
||||
|
||||
if (cachedValue == null || !newValue.equals(cachedValue)) {
|
||||
cachedValue = newValue;
|
||||
RenderSystem.uniform3i(this.location, newValue.x, newValue.y, newValue.z);
|
||||
if (!newValue.equals(cachedValue)) {
|
||||
cachedValue.set(newValue.x(), newValue.y(), newValue.z());
|
||||
RenderSystem.uniform3i(this.location, cachedValue.x(), cachedValue.y(), cachedValue.z());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,15 +3,16 @@ package net.coderbot.iris.gl.uniform;
|
||||
import com.gtnewhorizons.angelica.glsm.RenderSystem;
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.Vector4f;
|
||||
import org.joml.Vector3fc;
|
||||
import org.joml.Vector4fc;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class Vector3Uniform extends Uniform {
|
||||
private final Vector3f cachedValue;
|
||||
private final Supplier<Vector3f> value;
|
||||
private final Supplier<Vector3fc> value;
|
||||
|
||||
Vector3Uniform(int location, Supplier<Vector3f> value) {
|
||||
Vector3Uniform(int location, Supplier<Vector3fc> value) {
|
||||
super(location);
|
||||
|
||||
this.cachedValue = new Vector3f();
|
||||
@@ -30,11 +31,11 @@ public class Vector3Uniform extends Uniform {
|
||||
});
|
||||
}
|
||||
|
||||
static Vector3Uniform truncated(int location, Supplier<Vector4f> value) {
|
||||
static Vector3Uniform truncated(int location, Supplier<Vector4fc> value) {
|
||||
Vector3f held = new Vector3f();
|
||||
|
||||
return new Vector3Uniform(location, () -> {
|
||||
Vector4f updated = value.get();
|
||||
Vector4fc updated = value.get();
|
||||
|
||||
held.set(updated.x(), updated.y(), updated.z());
|
||||
|
||||
@@ -44,7 +45,7 @@ public class Vector3Uniform extends Uniform {
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
Vector3f newValue = value.get();
|
||||
Vector3fc newValue = value.get();
|
||||
|
||||
if (!newValue.equals(cachedValue)) {
|
||||
cachedValue.set(newValue.x(), newValue.y(), newValue.z());
|
||||
|
||||
@@ -3,21 +3,22 @@ package net.coderbot.iris.gl.uniform;
|
||||
import com.gtnewhorizons.angelica.glsm.RenderSystem;
|
||||
import net.coderbot.iris.gl.state.ValueUpdateNotifier;
|
||||
import org.joml.Vector4i;
|
||||
import org.joml.Vector4ic;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class Vector4IntegerJomlUniform extends Uniform {
|
||||
private Vector4i cachedValue;
|
||||
private final Supplier<Vector4i> value;
|
||||
private final Vector4i cachedValue;
|
||||
private final Supplier<Vector4ic> value;
|
||||
|
||||
Vector4IntegerJomlUniform(int location, Supplier<Vector4i> value) {
|
||||
Vector4IntegerJomlUniform(int location, Supplier<Vector4ic> value) {
|
||||
this(location, value, null);
|
||||
}
|
||||
|
||||
Vector4IntegerJomlUniform(int location, Supplier<Vector4i> value, ValueUpdateNotifier notifier) {
|
||||
Vector4IntegerJomlUniform(int location, Supplier<Vector4ic> value, ValueUpdateNotifier notifier) {
|
||||
super(location, notifier);
|
||||
|
||||
this.cachedValue = null;
|
||||
this.cachedValue = new Vector4i();
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@@ -31,11 +32,11 @@ public class Vector4IntegerJomlUniform extends Uniform {
|
||||
}
|
||||
|
||||
private void updateValue() {
|
||||
Vector4i newValue = value.get();
|
||||
Vector4ic newValue = value.get();
|
||||
|
||||
if (cachedValue == null || !newValue.equals(cachedValue)) {
|
||||
cachedValue = newValue;
|
||||
RenderSystem.uniform4i(this.location, newValue.x, newValue.y, newValue.z, newValue.w);
|
||||
if (!newValue.equals(cachedValue)) {
|
||||
cachedValue.set(newValue.x(), newValue.y(), newValue.z(), newValue.w());
|
||||
RenderSystem.uniform4i(this.location, cachedValue.x, cachedValue.y, cachedValue.z, cachedValue.w);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,18 +3,19 @@ package net.coderbot.iris.gl.uniform;
|
||||
import com.gtnewhorizons.angelica.glsm.RenderSystem;
|
||||
import net.coderbot.iris.gl.state.ValueUpdateNotifier;
|
||||
import org.joml.Vector4f;
|
||||
import org.joml.Vector4fc;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class Vector4Uniform extends Uniform {
|
||||
private final Vector4f cachedValue;
|
||||
private final Supplier<Vector4f> value;
|
||||
private final Supplier<Vector4fc> value;
|
||||
|
||||
Vector4Uniform(int location, Supplier<Vector4f> value) {
|
||||
Vector4Uniform(int location, Supplier<Vector4fc> value) {
|
||||
this(location, value, null);
|
||||
}
|
||||
|
||||
Vector4Uniform(int location, Supplier<Vector4f> value, ValueUpdateNotifier notifier) {
|
||||
Vector4Uniform(int location, Supplier<Vector4fc> value, ValueUpdateNotifier notifier) {
|
||||
super(location, notifier);
|
||||
|
||||
this.cachedValue = new Vector4f();
|
||||
@@ -31,7 +32,7 @@ public class Vector4Uniform extends Uniform {
|
||||
}
|
||||
|
||||
private void updateValue() {
|
||||
Vector4f newValue = value.get();
|
||||
Vector4fc newValue = value.get();
|
||||
|
||||
if (!newValue.equals(cachedValue)) {
|
||||
cachedValue.set(newValue.x(), newValue.y(), newValue.z(), newValue.w());
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package net.coderbot.iris.gui.screen;
|
||||
|
||||
import com.gtnewhorizons.angelica.AngelicaMod;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.loading.AngelicaTweaker;
|
||||
import net.coderbot.iris.Iris;
|
||||
import net.coderbot.iris.gui.GuiUtil;
|
||||
import net.coderbot.iris.gui.NavigationController;
|
||||
@@ -460,7 +460,7 @@ public class ShaderPackScreen extends GuiScreen implements HudHideable {
|
||||
}
|
||||
|
||||
if (openViaSystemClass) {
|
||||
AngelicaTweaker.LOGGER.debug("Opening via system class!");
|
||||
AngelicaMod.LOGGER.debug("Opening via system class!");
|
||||
Sys.openURL("file://" + uri);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import net.coderbot.iris.Iris;
|
||||
import net.coderbot.iris.gbuffer_overrides.matching.SpecialCondition;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import net.coderbot.iris.gl.shader.ProgramCreator;
|
||||
import net.coderbot.iris.gl.state.StateUpdateNotifiers;
|
||||
import net.coderbot.iris.pipeline.WorldRenderingPhase;
|
||||
import net.coderbot.iris.pipeline.WorldRenderingPipeline;
|
||||
|
||||
@@ -11,7 +12,12 @@ public class GbufferPrograms {
|
||||
private static boolean entities;
|
||||
private static boolean blockEntities;
|
||||
private static boolean outline;
|
||||
|
||||
private static Runnable phaseChangeListener;
|
||||
|
||||
static {
|
||||
StateUpdateNotifiers.phaseChangeNotifier = listener -> phaseChangeListener = listener;
|
||||
}
|
||||
|
||||
private static void checkReentrancy() {
|
||||
if (entities || blockEntities || outline) {
|
||||
throw new IllegalStateException("GbufferPrograms in weird state, tried to call begin function when entities = "
|
||||
@@ -106,7 +112,13 @@ public class GbufferPrograms {
|
||||
public static void teardownSpecialRenderCondition() {
|
||||
Iris.getPipelineManager().getPipeline().ifPresent(p -> p.setSpecialCondition(null));
|
||||
}
|
||||
|
||||
|
||||
public static void runPhaseChangeNotifier() {
|
||||
if (phaseChangeListener != null) {
|
||||
phaseChangeListener.run();
|
||||
}
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
// Empty initializer to run static
|
||||
}
|
||||
|
||||
@@ -29,22 +29,26 @@ import net.coderbot.iris.gl.buffer.ShaderStorageBufferHolder;
|
||||
import net.coderbot.iris.gl.buffer.ShaderStorageInfo;
|
||||
import net.coderbot.iris.gl.framebuffer.GlFramebuffer;
|
||||
import net.coderbot.iris.gl.image.GlImage;
|
||||
import net.coderbot.iris.gl.image.ImageHolder;
|
||||
import net.coderbot.iris.gl.image.ImageInformation;
|
||||
import net.coderbot.iris.gl.program.ComputeProgram;
|
||||
import net.coderbot.iris.gl.program.Program;
|
||||
import net.coderbot.iris.gl.program.ProgramBuilder;
|
||||
import net.coderbot.iris.gl.program.ProgramImages;
|
||||
import net.coderbot.iris.gl.program.ProgramSamplers;
|
||||
import net.coderbot.iris.gl.sampler.SamplerHolder;
|
||||
import net.coderbot.iris.gl.state.FogMode;
|
||||
import net.coderbot.iris.gl.texture.DepthBufferFormat;
|
||||
import net.coderbot.iris.gl.texture.TextureType;
|
||||
import net.coderbot.iris.helpers.Tri;
|
||||
import net.coderbot.iris.layer.GbufferPrograms;
|
||||
import net.coderbot.iris.pipeline.transform.PatchShaderType;
|
||||
import net.coderbot.iris.pipeline.transform.TransformPatcher;
|
||||
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;
|
||||
@@ -176,6 +180,7 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R
|
||||
private final boolean oldLighting;
|
||||
private final boolean allowConcurrentCompute;
|
||||
private final OptionalInt forcedShadowRenderDistanceChunks;
|
||||
private final CloudSetting dhCloudSetting;
|
||||
|
||||
private Pass current = null;
|
||||
|
||||
@@ -191,31 +196,37 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R
|
||||
private int currentSpecularTexture;
|
||||
private PackDirectives packDirectives;
|
||||
private final Set<FeatureFlags> activeFeatures;
|
||||
private final ProgramFallbackResolver resolver;
|
||||
|
||||
public DeferredWorldRenderingPipeline(ProgramSet programs) {
|
||||
Objects.requireNonNull(programs);
|
||||
|
||||
final Map<Integer, CompletableFuture<Map<PatchShaderType, String>>> prepareTransformFutures = submitCompositeTransforms(programs.getPrepare());
|
||||
final Map<Integer, CompletableFuture<Map<PatchShaderType, String>>> deferredTransformFutures = submitCompositeTransforms(programs.getDeferred());
|
||||
final Map<Integer, CompletableFuture<Map<PatchShaderType, String>>> compositeTransformFutures = submitCompositeTransforms(programs.getComposite());
|
||||
final Map<Integer, CompletableFuture<Map<PatchShaderType, String>>> prepareTransformFutures =
|
||||
submitCompositeTransforms(programs.getPrepare(), TextureStage.PREPARE, programs.getPackDirectives().getTextureMap());
|
||||
final Map<Integer, CompletableFuture<Map<PatchShaderType, String>>> deferredTransformFutures =
|
||||
submitCompositeTransforms(programs.getDeferred(), TextureStage.DEFERRED, programs.getPackDirectives().getTextureMap());
|
||||
final Map<Integer, CompletableFuture<Map<PatchShaderType, String>>> compositeTransformFutures =
|
||||
submitCompositeTransforms(programs.getComposite(), TextureStage.COMPOSITE_AND_FINAL, programs.getPackDirectives().getTextureMap());
|
||||
|
||||
final CompletableFuture<Map<PatchShaderType, String>> finalTransformFuture =
|
||||
programs.getCompositeFinal()
|
||||
.filter(ProgramSource::isValid)
|
||||
.map(DeferredWorldRenderingPipeline::submitCompositeTransform)
|
||||
.map(source -> submitCompositeTransform(source, TextureStage.COMPOSITE_AND_FINAL, programs.getPackDirectives().getTextureMap()))
|
||||
.orElse(null);
|
||||
|
||||
final ProgramFallbackResolver resolver = new ProgramFallbackResolver(programs);
|
||||
resolver = new ProgramFallbackResolver(programs);
|
||||
final Map<Pair<String, InputAvailability>, CompletableFuture<Map<PatchShaderType, String>>> attributeTransformFutures = submitAttributeTransforms(resolver);
|
||||
|
||||
final Optional<ProgramSource> terrainSource = first(programs.getGbuffersTerrain(), programs.getGbuffersTexturedLit(), programs.getGbuffersTextured(), programs.getGbuffersBasic());
|
||||
final Optional<ProgramSource> translucentSource = first(programs.getGbuffersWater(), terrainSource);
|
||||
final Optional<ProgramSource> shadowSource = programs.getShadow();
|
||||
final Optional<ProgramSource> shadowTranslucentSource = first(programs.getShadowWater(), shadowSource);
|
||||
|
||||
// Celeritas terrain transform futures
|
||||
final CompletableFuture<Map<PatchShaderType, String>> celeritasTerrainFuture = terrainSource.map(DeferredWorldRenderingPipeline::submitCeleritasTerrainTransform).orElse(null);
|
||||
final CompletableFuture<Map<PatchShaderType, String>> celeritasTranslucentFuture = translucentSource.map(DeferredWorldRenderingPipeline::submitCeleritasTerrainTransform).orElse(null);
|
||||
final CompletableFuture<Map<PatchShaderType, String>> celeritasShadowFuture = shadowSource.map(DeferredWorldRenderingPipeline::submitCeleritasTerrainTransform).orElse(null);
|
||||
final CompletableFuture<Map<PatchShaderType, String>> celeritasShadowTranslucentFuture = shadowTranslucentSource.map(DeferredWorldRenderingPipeline::submitCeleritasTerrainTransform).orElse(null);
|
||||
|
||||
this.cloudSetting = programs.getPackDirectives().getCloudSetting();
|
||||
this.shouldRenderUnderwaterOverlay = programs.getPackDirectives().underwaterOverlay();
|
||||
@@ -227,6 +238,7 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R
|
||||
this.shouldRenderWeather = programs.getPackDirectives().shouldRenderWeather();
|
||||
this.shouldRenderWeatherParticles = programs.getPackDirectives().shouldRenderWeatherParticles();
|
||||
this.shouldWriteRainAndSnowToDepthBuffer = programs.getPackDirectives().rainDepth();
|
||||
this.dhCloudSetting = programs.getPackDirectives().getDHCloudSetting();
|
||||
this.shouldRenderParticlesBeforeDeferred = programs.getPackDirectives().getParticleRenderingSettings()
|
||||
.map(s -> s == net.coderbot.iris.shaderpack.ParticleRenderingSettings.BEFORE || s == net.coderbot.iris.shaderpack.ParticleRenderingSettings.MIXED)
|
||||
.orElse(false);
|
||||
@@ -367,6 +379,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,
|
||||
@@ -377,6 +390,7 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R
|
||||
null, null, ProgramId.Weather,
|
||||
// world border uses textured_lit even though it has no lightmap :/
|
||||
null, ProgramId.TexturedLit, ProgramId.TexturedLit,
|
||||
ProgramId.ShadowWater, ProgramId.ShadowWater, ProgramId.ShadowWater,
|
||||
ProgramId.Shadow, ProgramId.Shadow, ProgramId.Shadow
|
||||
};
|
||||
|
||||
@@ -420,7 +434,7 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R
|
||||
return cachedPasses.computeIfAbsent(Pair.of(id, availability), p -> {
|
||||
final ProgramSource source = resolver.resolveNullable(p.getLeft());
|
||||
|
||||
if (condition == RenderCondition.SHADOW) {
|
||||
if (condition == RenderCondition.SHADOW || condition == RenderCondition.SHADOW_TRANSLUCENT) {
|
||||
if (!shadowDirectives.isShadowEnabled().orElse(shadowRenderTargets != null)) {
|
||||
// shadow is not used
|
||||
return null;
|
||||
@@ -437,7 +451,8 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R
|
||||
}
|
||||
|
||||
try {
|
||||
return createPass(source, availability, condition == RenderCondition.SHADOW, finalId);
|
||||
return createPass(source, availability,
|
||||
condition == RenderCondition.SHADOW || condition == RenderCondition.SHADOW_TRANSLUCENT, finalId);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to create pass for " + source.getName() + " for rendering condition "
|
||||
+ condition + " specialized to input availability " + availability, e);
|
||||
@@ -464,7 +479,9 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R
|
||||
this.shadowRenderer = new ShadowRenderer(programs.getShadow().orElse(null),
|
||||
programs.getPackDirectives(), shadowRenderTargets, shadowCompositeRenderer);
|
||||
Program shadowProgram = table.match(RenderCondition.SHADOW, new InputAvailability(true, true)).getProgram();
|
||||
shadowRenderer.setUsesImages(shadowProgram != null && shadowProgram.getActiveImages() > 0);
|
||||
Program shadowWaterProgram = table.match(RenderCondition.SHADOW_TRANSLUCENT, new InputAvailability(true, true)).getProgram();
|
||||
shadowRenderer.setUsesImages((shadowProgram != null && shadowProgram.getActiveImages() > 0)
|
||||
|| (shadowWaterProgram != null && shadowWaterProgram.getActiveImages() > 0));
|
||||
} else {
|
||||
shadowRenderer = null;
|
||||
}
|
||||
@@ -581,11 +598,12 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R
|
||||
terrainSource,
|
||||
translucentSource,
|
||||
shadowSource,
|
||||
celeritasTerrainFuture, celeritasTranslucentFuture, celeritasShadowFuture,
|
||||
shadowTranslucentSource,
|
||||
celeritasTerrainFuture, celeritasTranslucentFuture, celeritasShadowFuture, celeritasShadowTranslucentFuture,
|
||||
renderTargets, flippedAfterPrepare, flippedAfterTranslucent,
|
||||
celeritasShadowFb);
|
||||
|
||||
this.dhCompat = new DHCompat();
|
||||
this.dhCompat = new DHCompat(this, shadowDirectives.isDhShadowEnabled().orElse(true));
|
||||
}
|
||||
|
||||
private RenderTargets getRenderTargets() {
|
||||
@@ -688,7 +706,10 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R
|
||||
|
||||
private RenderCondition getCondition(WorldRenderingPhase phase) {
|
||||
if (isRenderingShadow) {
|
||||
return RenderCondition.SHADOW;
|
||||
return switch (phase) {
|
||||
case TERRAIN_TRANSLUCENT, TRIPWIRE -> RenderCondition.SHADOW_TRANSLUCENT;
|
||||
default -> RenderCondition.SHADOW;
|
||||
};
|
||||
}
|
||||
|
||||
if (special != null) {
|
||||
@@ -719,6 +740,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,14 +774,21 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
final RenderCondition condition = getCondition(getPhase());
|
||||
final Pass matched = table.match(condition, inputs);
|
||||
|
||||
|
||||
beginPass(matched);
|
||||
}
|
||||
|
||||
@@ -883,7 +915,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<>();
|
||||
|
||||
@@ -902,6 +935,38 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R
|
||||
return pass;
|
||||
}
|
||||
|
||||
public void addGbufferOrShadowSamplers(SamplerHolder samplers, ImageHolder images, Supplier<ImmutableSet<Integer>> flipped,
|
||||
boolean isShadowPass, boolean hasTexture, boolean hasLightmap, boolean hasOverlay) {
|
||||
TextureStage textureStage = TextureStage.GBUFFERS_AND_SHADOW;
|
||||
|
||||
ProgramSamplers.CustomTextureSamplerInterceptor customTextureSamplerInterceptor =
|
||||
ProgramSamplers.customTextureSamplerInterceptor(samplers, customTextureManager.getCustomTextureIdMap(textureStage));
|
||||
|
||||
IrisSamplers.addRenderTargetSamplers(customTextureSamplerInterceptor, flipped, renderTargets, false, this);
|
||||
IrisImages.addRenderTargetImages(images, flipped, renderTargets);
|
||||
|
||||
if (!shouldBindPBR) {
|
||||
shouldBindPBR = IrisSamplers.hasPBRSamplers(customTextureSamplerInterceptor);
|
||||
}
|
||||
|
||||
IrisSamplers.addLevelSamplers(customTextureSamplerInterceptor, this, whitePixel, new InputAvailability(hasTexture, hasLightmap));
|
||||
if (!isShadowPass) {
|
||||
IrisSamplers.addWorldDepthSamplers(customTextureSamplerInterceptor, renderTargets);
|
||||
}
|
||||
IrisSamplers.addNoiseSampler(customTextureSamplerInterceptor, customTextureManager.getNoiseTexture());
|
||||
IrisSamplers.addCustomImages(customTextureSamplerInterceptor, customImages);
|
||||
IrisSamplers.addCustomTextures(customTextureSamplerInterceptor, customTextureManager.getIrisCustomTextures());
|
||||
IrisImages.addCustomImages(images, customImages);
|
||||
|
||||
if (IrisSamplers.hasShadowSamplers(customTextureSamplerInterceptor)) {
|
||||
IrisSamplers.addShadowSamplers(customTextureSamplerInterceptor, shadowTargetsSupplier.get(), null, true);
|
||||
}
|
||||
|
||||
if (isShadowPass || IrisImages.hasShadowImages(images)) {
|
||||
IrisImages.addShadowColorImages(images, shadowTargetsSupplier.get(), null);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isPostChain;
|
||||
private boolean isMainBound = true;
|
||||
|
||||
@@ -933,6 +998,56 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R
|
||||
}
|
||||
}
|
||||
|
||||
public CloudSetting getDHCloudSetting() {
|
||||
return dhCloudSetting;
|
||||
}
|
||||
|
||||
public Optional<ProgramSource> getDHTerrainShader() {
|
||||
return resolver.resolve(ProgramId.DhTerrain);
|
||||
}
|
||||
|
||||
public Optional<ProgramSource> getDHGenericShader() {
|
||||
return resolver.resolve(ProgramId.DhGeneric);
|
||||
}
|
||||
|
||||
public Optional<ProgramSource> getDHWaterShader() {
|
||||
return resolver.resolve(ProgramId.DhWater);
|
||||
}
|
||||
|
||||
public Optional<ProgramSource> getDHShadowShader() {
|
||||
return resolver.resolve(ProgramId.DhShadow);
|
||||
}
|
||||
|
||||
public CustomUniforms getCustomUniforms() {
|
||||
return customUniforms;
|
||||
}
|
||||
|
||||
public GlFramebuffer createDHFramebuffer(ProgramSource sources, boolean trans) {
|
||||
return renderTargets.createDHFramebuffer(trans ? flippedAfterTranslucent : flippedAfterPrepare,
|
||||
sources.getDirectives().getDrawBuffers());
|
||||
}
|
||||
|
||||
public ImmutableSet<Integer> getFlippedBeforeShadow() {
|
||||
return flippedBeforeShadow;
|
||||
}
|
||||
|
||||
public ImmutableSet<Integer> getFlippedAfterPrepare() {
|
||||
return flippedAfterPrepare;
|
||||
}
|
||||
|
||||
public ImmutableSet<Integer> getFlippedAfterTranslucent() {
|
||||
return flippedAfterTranslucent;
|
||||
}
|
||||
|
||||
public GlFramebuffer createDHFramebufferShadow(ProgramSource sources) {
|
||||
|
||||
return shadowRenderTargets.createDHFramebuffer(ImmutableSet.of(), new int[]{0, 1});
|
||||
}
|
||||
|
||||
public boolean hasShadowRenderTargets() {
|
||||
return shadowRenderTargets != null;
|
||||
}
|
||||
|
||||
private final class Pass {
|
||||
@Nullable
|
||||
private final Program program;
|
||||
@@ -973,12 +1088,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 +1107,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 +1145,7 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R
|
||||
BlendModeOverride.restore();
|
||||
AlphaTestOverride.restore();
|
||||
|
||||
FullScreenQuadRenderer.clearLocCache();
|
||||
destroyPasses(table);
|
||||
|
||||
// Destroy the composite rendering pipeline
|
||||
@@ -1077,6 +1195,7 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R
|
||||
// While it's possible to just clear them instead and reuse them, we'd need to investigate whether or not this
|
||||
// would help performance.
|
||||
renderTargets.destroy();
|
||||
dhCompat.clearPipeline();
|
||||
|
||||
// destroy the shadow render targets
|
||||
if (shadowRenderTargets != null) {
|
||||
@@ -1548,12 +1667,14 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R
|
||||
public void setOverridePhase(WorldRenderingPhase phase) {
|
||||
this.overridePhase = phase;
|
||||
matchPass();
|
||||
GbufferPrograms.runPhaseChangeNotifier();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPhase(WorldRenderingPhase phase) {
|
||||
this.phase = phase;
|
||||
matchPass();
|
||||
GbufferPrograms.runPhaseChangeNotifier();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1605,11 +1726,20 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R
|
||||
private static final InputAvailability INPUT_TEXTURE_LIGHTMAP = new InputAvailability(true, true);
|
||||
private static final InputAvailability[] INPUT_AVAILABILITIES = { INPUT_NONE, INPUT_TEXTURE, INPUT_TEXTURE_LIGHTMAP };
|
||||
|
||||
private static CompletableFuture<Map<PatchShaderType, String>> submitCompositeTransform(ProgramSource source) {
|
||||
return Iris.ShaderTransformExecutor.submitTracked(() -> TransformPatcher.patchComposite(source.getVertexSource().orElse(null), source.getGeometrySource().orElse(null), source.getTessControlSource().orElse(null), source.getTessEvalSource().orElse(null), source.getFragmentSource().orElse(null)));
|
||||
private static CompletableFuture<Map<PatchShaderType, String>> submitCompositeTransform(ProgramSource source, TextureStage stage,
|
||||
Object2ObjectMap<Tri<String, TextureType, TextureStage>, String> textureMap) {
|
||||
return Iris.ShaderTransformExecutor.submitTracked(() -> TransformPatcher.patchComposite(
|
||||
source.getVertexSource().orElse(null),
|
||||
source.getGeometrySource().orElse(null),
|
||||
source.getTessControlSource().orElse(null),
|
||||
source.getTessEvalSource().orElse(null),
|
||||
source.getFragmentSource().orElse(null),
|
||||
stage,
|
||||
textureMap));
|
||||
}
|
||||
|
||||
private static Map<Integer, CompletableFuture<Map<PatchShaderType, String>>> submitCompositeTransforms(ProgramSource[] sources) {
|
||||
private static Map<Integer, CompletableFuture<Map<PatchShaderType, String>>> submitCompositeTransforms(ProgramSource[] sources,
|
||||
TextureStage stage, Object2ObjectMap<Tri<String, TextureType, TextureStage>, String> textureMap) {
|
||||
// Count valid sources for initial capacity
|
||||
int count = 0;
|
||||
for (ProgramSource source : sources) {
|
||||
@@ -1618,7 +1748,7 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R
|
||||
final Map<Integer, CompletableFuture<Map<PatchShaderType, String>>> futures = new HashMap<>(count);
|
||||
for (int i = 0; i < sources.length; i++) {
|
||||
if (sources[i] != null && sources[i].isValid()) {
|
||||
futures.put(i, submitCompositeTransform(sources[i]));
|
||||
futures.put(i, submitCompositeTransform(sources[i], stage, textureMap));
|
||||
}
|
||||
}
|
||||
return futures;
|
||||
|
||||
@@ -130,7 +130,7 @@ public class FixedFunctionWorldRenderingPipeline implements WorldRenderingPipeli
|
||||
return new FrameUpdateNotifier();
|
||||
}
|
||||
|
||||
private static final DHCompat DH_COMPAT = new DHCompat();
|
||||
private static final DHCompat DH_COMPAT = new DHCompat(null, false);
|
||||
|
||||
@Override
|
||||
public DHCompat getDHCompat() {
|
||||
|
||||
@@ -39,53 +39,54 @@ public class PatchedShaderPrinter {
|
||||
}
|
||||
|
||||
public static void debugPatchedShaders(String name, String vertex, String geometry, String tessControl, String tessEval, String fragment, String compute) {
|
||||
if (prettyPrintShaders) {
|
||||
final Path debugOutDir = Minecraft.getMinecraft().mcDataDir.toPath().resolve("patched_shaders");
|
||||
if (!outputLocationCleared) {
|
||||
try {
|
||||
if (Files.exists(debugOutDir)) {
|
||||
try (Stream<Path> stream = Files.list(debugOutDir)) {
|
||||
stream.forEach(path -> {
|
||||
try {
|
||||
Files.delete(path);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Files.createDirectories(debugOutDir);
|
||||
} catch (IOException e) {
|
||||
Iris.logger.warn("Failed to initialize debug patched shader source location", e);
|
||||
}
|
||||
outputLocationCleared = true;
|
||||
}
|
||||
|
||||
if (!prettyPrintShaders && !Iris.getIrisConfig().areDebugOptionsEnabled()) {
|
||||
return;
|
||||
}
|
||||
final Path debugOutDir = Minecraft.getMinecraft().mcDataDir.toPath().resolve("patched_shaders");
|
||||
if (!outputLocationCleared) {
|
||||
try {
|
||||
programCounter++;
|
||||
String prefix = String.format("%03d_", programCounter);
|
||||
if (vertex != null) {
|
||||
Files.write(debugOutDir.resolve(prefix + name + ".vsh"), vertex.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
if (geometry != null) {
|
||||
Files.write(debugOutDir.resolve(prefix + name + ".gsh"), geometry.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
if (tessControl != null) {
|
||||
Files.write(debugOutDir.resolve(prefix + name + ".tcs"), tessControl.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
if (tessEval != null) {
|
||||
Files.write(debugOutDir.resolve(prefix + name + ".tes"), tessEval.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
if (fragment != null) {
|
||||
Files.write(debugOutDir.resolve(prefix + name + ".fsh"), fragment.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
if (compute != null) {
|
||||
Files.write(debugOutDir.resolve(prefix + name + ".csh"), compute.getBytes(StandardCharsets.UTF_8));
|
||||
if (Files.exists(debugOutDir)) {
|
||||
try (Stream<Path> stream = Files.list(debugOutDir)) {
|
||||
stream.forEach(path -> {
|
||||
try {
|
||||
Files.delete(path);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Files.createDirectories(debugOutDir);
|
||||
} catch (IOException e) {
|
||||
Iris.logger.warn("Failed to write debug patched shader source", e);
|
||||
Iris.logger.warn("Failed to initialize debug patched shader source location", e);
|
||||
}
|
||||
outputLocationCleared = true;
|
||||
}
|
||||
|
||||
try {
|
||||
programCounter++;
|
||||
String prefix = String.format("%03d_", programCounter);
|
||||
if (vertex != null) {
|
||||
Files.write(debugOutDir.resolve(prefix + name + ".vsh"), vertex.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
if (geometry != null) {
|
||||
Files.write(debugOutDir.resolve(prefix + name + ".gsh"), geometry.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
if (tessControl != null) {
|
||||
Files.write(debugOutDir.resolve(prefix + name + ".tcs"), tessControl.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
if (tessEval != null) {
|
||||
Files.write(debugOutDir.resolve(prefix + name + ".tes"), tessEval.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
if (fragment != null) {
|
||||
Files.write(debugOutDir.resolve(prefix + name + ".fsh"), fragment.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
if (compute != null) {
|
||||
Files.write(debugOutDir.resolve(prefix + name + ".csh"), compute.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Iris.logger.warn("Failed to write debug patched shader source", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import com.gtnewhorizons.angelica.glsm.RenderSystem;
|
||||
import com.gtnewhorizons.angelica.rendering.RenderingState;
|
||||
import com.gtnewhorizons.angelica.rendering.celeritas.CeleritasWorldRenderer;
|
||||
import net.coderbot.iris.Iris;
|
||||
import net.coderbot.iris.compat.dh.DHCompat;
|
||||
import net.coderbot.iris.gui.option.IrisVideoSettings;
|
||||
import net.coderbot.iris.layer.GbufferPrograms;
|
||||
import net.coderbot.iris.shaderpack.PackDirectives;
|
||||
@@ -43,6 +44,7 @@ import net.minecraft.profiler.Profiler;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import org.embeddedt.embeddium.impl.render.viewport.ViewportProvider;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Matrix4fc;
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.Vector4f;
|
||||
@@ -68,6 +70,8 @@ public class ShadowRenderer {
|
||||
public static final List<TileEntity> globalTileEntities = new ArrayList<>();
|
||||
public static boolean ACTIVE = false;
|
||||
|
||||
public static Frustrum FRUSTUM;
|
||||
|
||||
private static final Comparator<Entity> ENTITY_CLASS_COMPARATOR = Comparator.comparingInt(a -> System.identityHashCode(a.getClass()));
|
||||
private static final NonCullingFrustum NON_CULLING_FRUSTUM = new NonCullingFrustum();
|
||||
private static final CullEverythingFrustum CULL_EVERYTHING_FRUSTUM = new CullEverythingFrustum();
|
||||
@@ -111,12 +115,16 @@ public class ShadowRenderer {
|
||||
private double lastBoxCullerDistance = -1;
|
||||
private double lastAdvancedBoxCullerDistance = -1;
|
||||
private double lastTileEntityCullerDistance = -1;
|
||||
private final boolean shouldRenderDH;
|
||||
private final float nearPlane, farPlane;
|
||||
|
||||
public ShadowRenderer(ProgramSource shadow, PackDirectives directives, ShadowRenderTargets shadowRenderTargets, ShadowCompositeRenderer compositeRenderer) {
|
||||
|
||||
this.profiler = Minecraft.getMinecraft().mcProfiler;
|
||||
|
||||
final PackShadowDirectives shadowDirectives = directives.getShadowDirectives();
|
||||
this.nearPlane = shadowDirectives.getNearPlane();
|
||||
this.farPlane = shadowDirectives.getFarPlane();
|
||||
|
||||
this.halfPlaneLength = shadowDirectives.getDistance();
|
||||
this.voxelDistance = shadowDirectives.getVoxelDistance();
|
||||
@@ -129,6 +137,7 @@ public class ShadowRenderer {
|
||||
this.shouldRenderEntities = shadowDirectives.shouldRenderEntities();
|
||||
this.shouldRenderPlayer = shadowDirectives.shouldRenderPlayer();
|
||||
this.shouldRenderBlockEntities = shadowDirectives.shouldRenderBlockEntities();
|
||||
this.shouldRenderDH = shadowDirectives.isDhShadowEnabled().orElse(false);
|
||||
|
||||
this.compositeRenderer = compositeRenderer;
|
||||
|
||||
@@ -348,14 +357,16 @@ public class ShadowRenderer {
|
||||
shadowLightVectorCache.set(shadowLightPosition.x(), shadowLightPosition.y(), shadowLightPosition.z());
|
||||
shadowLightVectorCache.normalize();
|
||||
|
||||
Matrix4fc projView = ((shouldRenderDH && DHCompat.hasRenderingEnabled()) ? DHCompat.getProjection() : RenderingState.INSTANCE.getProjectionMatrix());
|
||||
|
||||
if (hasSafeZone) {
|
||||
BoxCuller distanceCuller = new BoxCuller(halfPlaneLength * renderMultiplier);
|
||||
SafeZoneCullingFrustum safeZoneFrustum = new SafeZoneCullingFrustum(
|
||||
RenderingState.INSTANCE.getModelViewMatrix(), RenderingState.INSTANCE.getProjectionMatrix(),
|
||||
RenderingState.INSTANCE.getModelViewMatrix(), projView,
|
||||
shadowLightVectorCache, boxCuller, distanceCuller);
|
||||
return holder.setInfo(safeZoneFrustum, distanceInfo, cullingInfo);
|
||||
} else {
|
||||
cachedAdvancedFrustum.init(RenderingState.INSTANCE.getModelViewMatrix(), RenderingState.INSTANCE.getProjectionMatrix(), shadowLightVectorCache, boxCuller);
|
||||
cachedAdvancedFrustum.init(RenderingState.INSTANCE.getModelViewMatrix(), projView, shadowLightVectorCache, boxCuller);
|
||||
return holder.setInfo(cachedAdvancedFrustum, distanceInfo, cullingInfo);
|
||||
}
|
||||
}
|
||||
@@ -630,12 +641,12 @@ public class ShadowRenderer {
|
||||
final MatrixStack modelView = getShadowModelView();
|
||||
MODELVIEW.set(modelView.peek().getModel());
|
||||
|
||||
final Matrix4f shadowProjection;
|
||||
final Matrix4f shadowProjection;
|
||||
if (this.fov != null) {
|
||||
// If FOV is not null, the pack wants a perspective based projection matrix. (This is to support legacy packs)
|
||||
shadowProjection = ShadowMatrices.createPerspectiveMatrix(this.fov);
|
||||
shadowProjection = ShadowMatrices.createPerspectiveMatrix(this.fov);
|
||||
} else {
|
||||
shadowProjection = ShadowMatrices.createOrthoMatrix(halfPlaneLength);
|
||||
shadowProjection = ShadowMatrices.createOrthoMatrix(halfPlaneLength, nearPlane < 0 ? -DHCompat.getRenderDistance() : nearPlane, farPlane < 0 ? DHCompat.getRenderDistance() : farPlane);
|
||||
}
|
||||
|
||||
PROJECTION.set(shadowProjection);
|
||||
@@ -649,6 +660,7 @@ public class ShadowRenderer {
|
||||
profiler.startSection("initialize frustum");
|
||||
|
||||
terrainFrustumHolder = createShadowFrustum(renderDistanceMultiplier, terrainFrustumHolder);
|
||||
FRUSTUM = terrainFrustumHolder.getFrustum();
|
||||
|
||||
// Use the player/entity position for shadow rendering
|
||||
final Vector3d entityPos = playerCamera.getEntityPos();
|
||||
|
||||
@@ -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))");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
package net.coderbot.iris.pipeline.transform;
|
||||
|
||||
import net.coderbot.iris.gl.shader.ShaderType;
|
||||
import net.coderbot.iris.pipeline.transform.parameter.Parameters;
|
||||
import org.taumc.glsl.Transformer;
|
||||
|
||||
public class DHGenericTransformer {
|
||||
public static void transform(Transformer transformer, Parameters parameters, int glslVersion) {
|
||||
CommonTransformer.transform(transformer, parameters, true, glslVersion);
|
||||
|
||||
transformer.replaceExpression("gl_TextureMatrix[0]", "mat4(1.0)");
|
||||
transformer.replaceExpression("gl_TextureMatrix[1]", "mat4(1.0)");
|
||||
transformer.rename("gl_ProjectionMatrix", "iris_ProjectionMatrix");
|
||||
|
||||
if (parameters.type == ShaderType.VERTEX) {
|
||||
// Alias of gl_MultiTexCoord1 on 1.15+ for OptiFine
|
||||
// See https://github.com/IrisShaders/Iris/issues/1149
|
||||
transformer.rename("gl_MultiTexCoord2", "gl_MultiTexCoord1");
|
||||
|
||||
transformer.replaceExpression("gl_MultiTexCoord0", "vec4(0.0, 0.0, 0.0, 1.0)");
|
||||
transformer.replaceExpression("gl_MultiTexCoord1", "vec4(_vert_tex_light_coord, 0.0, 1.0)");
|
||||
|
||||
replaceGlMultiTexCoordBounded(transformer, 4, 7);
|
||||
}
|
||||
|
||||
transformer.rename("gl_Color", "_vert_color");
|
||||
|
||||
if (parameters.type == ShaderType.VERTEX) {
|
||||
transformer.replaceExpression("gl_Normal", "_vert_normal");
|
||||
}
|
||||
|
||||
transformer.replaceExpression("gl_NormalMatrix", "iris_NormalMatrix");
|
||||
addIfNotExists(transformer, "iris_NormalMatrix", "uniform mat3 iris_NormalMatrix;");
|
||||
addIfNotExists(transformer, "iris_ModelViewMatrixInverse", "uniform mat4 iris_ModelViewMatrixInverse;");
|
||||
addIfNotExists(transformer, "iris_ProjectionMatrixInverse", "uniform mat4 iris_ProjectionMatrixInverse;");
|
||||
|
||||
transformer.rename("gl_ModelViewMatrix", "iris_ModelViewMatrix");
|
||||
transformer.rename("gl_ModelViewMatrixInverse", "iris_ModelViewMatrixInverse");
|
||||
transformer.rename("gl_ProjectionMatrixInverse", "iris_ProjectionMatrixInverse");
|
||||
|
||||
if (parameters.type == ShaderType.VERTEX) {
|
||||
if (transformer.containsCall("ftransform")) {
|
||||
transformer.injectFunction("vec4 ftransform() { return gl_ModelViewProjectionMatrix * gl_Vertex; }");
|
||||
}
|
||||
|
||||
addIfNotExists(transformer, "iris_ProjectionMatrix", "uniform mat4 iris_ProjectionMatrix;");
|
||||
addIfNotExists(transformer, "iris_ModelViewMatrix", "uniform mat4 iris_ModelViewMatrix;");
|
||||
transformer.injectFunction("vec4 getVertexPosition() { return vec4(_vert_position, 1.0); }");
|
||||
transformer.replaceExpression("gl_Vertex", "getVertexPosition()");
|
||||
|
||||
injectVertInit(transformer);
|
||||
} else {
|
||||
addIfNotExists(transformer, "iris_ModelViewMatrix", "uniform mat4 iris_ModelViewMatrix;");
|
||||
addIfNotExists(transformer, "iris_ProjectionMatrix", "uniform mat4 iris_ProjectionMatrix;");
|
||||
}
|
||||
|
||||
transformer.replaceExpression("gl_ModelViewProjectionMatrix", "(iris_ProjectionMatrix * iris_ModelViewMatrix)");
|
||||
ShaderTransformer.applyIntelHd4000Workaround(transformer);
|
||||
}
|
||||
|
||||
public static void injectVertInit(Transformer transformer) {
|
||||
addIfNotExists(transformer, "_vert_position", "vec3 _vert_position;");
|
||||
addIfNotExists(transformer, "_vert_tex_light_coord", "vec2 _vert_tex_light_coord;");
|
||||
addIfNotExists(transformer, "dhMaterialId", "int dhMaterialId;");
|
||||
addIfNotExists(transformer, "_vert_color", "vec4 _vert_color;");
|
||||
addIfNotExists(transformer, "_vert_normal", "vec3 _vert_normal;");
|
||||
addIfNotExists(transformer, "uOffsetChunk", "uniform ivec3 uOffsetChunk;");
|
||||
addIfNotExists(transformer, "uOffsetSubChunk", "uniform vec3 uOffsetSubChunk;");
|
||||
addIfNotExists(transformer, "uCameraPosChunk", "uniform ivec3 uCameraPosChunk;");
|
||||
addIfNotExists(transformer, "uCameraPosSubChunk", "uniform vec3 uCameraPosSubChunk;");
|
||||
addIfNotExists(transformer, "uSkyLight", "uniform int uSkyLight;");
|
||||
addIfNotExists(transformer, "uBlockLight", "uniform int uBlockLight;");
|
||||
addIfNotExists(transformer, "iris_color", "in vec4 iris_color;");
|
||||
addIfNotExists(transformer, "aScale", "in vec3 aScale;");
|
||||
addIfNotExists(transformer, "aTranslateChunk", "in ivec3 aTranslateChunk;");
|
||||
addIfNotExists(transformer, "aTranslateSubChunk", "in vec3 aTranslateSubChunk;");
|
||||
addIfNotExists(transformer, "aMaterial", "in int aMaterial;");
|
||||
addIfNotExists(transformer, "vPosition", "in vec3 vPosition;");
|
||||
|
||||
transformer.injectFunction("const vec3 irisNormals[6] = vec3[](vec3(0,0,-1), vec3(0,0,1), vec3(-1,0,0), vec3(1,0,0), vec3(0,-1,0), vec3(0,1,0));");
|
||||
transformer.injectFunction(
|
||||
"void _vert_init() {"
|
||||
+ " vec3 trans = vec3(aTranslateChunk + uOffsetChunk - uCameraPosChunk) * 16.0;"
|
||||
+ " trans += (aTranslateSubChunk + uOffsetSubChunk - uCameraPosSubChunk);"
|
||||
+ " mat4 transform = mat4("
|
||||
+ " aScale.x, 0.0, 0.0, 0.0,"
|
||||
+ " 0.0, aScale.y, 0.0, 0.0,"
|
||||
+ " 0.0, 0.0, aScale.z, 0.0,"
|
||||
+ " trans.x, trans.y, trans.z, 1.0"
|
||||
+ " );"
|
||||
+ " _vert_position = (transform * vec4(vPosition, 1.0)).xyz;"
|
||||
+ " _vert_normal = irisNormals[int(floor(float(gl_VertexID) / 4.0))];"
|
||||
+ " float blockLight = (float(uBlockLight) + 0.5) / 16.0;"
|
||||
+ " float skyLight = (float(uSkyLight) + 0.5) / 16.0;"
|
||||
+ " _vert_tex_light_coord = vec2(blockLight, skyLight);"
|
||||
+ " dhMaterialId = aMaterial;"
|
||||
+ " _vert_color = iris_color;"
|
||||
+ " }"
|
||||
);
|
||||
transformer.prependMain("_vert_init();");
|
||||
}
|
||||
|
||||
private static void addIfNotExists(Transformer transformer, String name, String code) {
|
||||
if (!transformer.hasVariable(name)) {
|
||||
transformer.injectVariable(code);
|
||||
}
|
||||
}
|
||||
|
||||
private static void replaceGlMultiTexCoordBounded(Transformer transformer, int from, int to) {
|
||||
for (int i = from; i <= to; i++) {
|
||||
transformer.replaceExpression("gl_MultiTexCoord" + i, "vec4(0.0, 0.0, 0.0, 1.0)");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package net.coderbot.iris.pipeline.transform;
|
||||
|
||||
import net.coderbot.iris.gl.shader.ShaderType;
|
||||
import net.coderbot.iris.pipeline.transform.parameter.Parameters;
|
||||
import org.taumc.glsl.Transformer;
|
||||
|
||||
public class DHTerrainTransformer {
|
||||
public static void transform(Transformer transformer, Parameters parameters, int glslVersion) {
|
||||
CommonTransformer.transform(transformer, parameters, true, glslVersion);
|
||||
|
||||
transformer.replaceExpression("gl_TextureMatrix[0]", "mat4(1.0)");
|
||||
transformer.replaceExpression("gl_TextureMatrix[1]", "mat4(1.0)");
|
||||
transformer.rename("gl_ProjectionMatrix", "iris_ProjectionMatrix");
|
||||
|
||||
if (parameters.type == ShaderType.VERTEX) {
|
||||
// Alias of gl_MultiTexCoord1 on 1.15+ for OptiFine
|
||||
// See https://github.com/IrisShaders/Iris/issues/1149
|
||||
transformer.rename("gl_MultiTexCoord2", "gl_MultiTexCoord1");
|
||||
|
||||
transformer.replaceExpression("gl_MultiTexCoord0", "vec4(0.0, 0.0, 0.0, 1.0)");
|
||||
transformer.replaceExpression("gl_MultiTexCoord1", "vec4(_vert_tex_light_coord, 0.0, 1.0)");
|
||||
|
||||
replaceGlMultiTexCoordBounded(transformer, 4, 7);
|
||||
}
|
||||
|
||||
transformer.rename("gl_Color", "_vert_color");
|
||||
|
||||
if (parameters.type == ShaderType.VERTEX) {
|
||||
transformer.replaceExpression("gl_Normal", "_vert_normal");
|
||||
}
|
||||
|
||||
transformer.replaceExpression("gl_NormalMatrix", "iris_NormalMatrix");
|
||||
addIfNotExists(transformer, "iris_NormalMatrix", "uniform mat3 iris_NormalMatrix;");
|
||||
addIfNotExists(transformer, "iris_ModelViewMatrixInverse", "uniform mat4 iris_ModelViewMatrixInverse;");
|
||||
addIfNotExists(transformer, "iris_ProjectionMatrixInverse", "uniform mat4 iris_ProjectionMatrixInverse;");
|
||||
|
||||
transformer.rename("gl_ModelViewMatrix", "iris_ModelViewMatrix");
|
||||
transformer.rename("gl_ModelViewMatrixInverse", "iris_ModelViewMatrixInverse");
|
||||
transformer.rename("gl_ProjectionMatrixInverse", "iris_ProjectionMatrixInverse");
|
||||
|
||||
if (parameters.type == ShaderType.VERTEX) {
|
||||
if (transformer.containsCall("ftransform")) {
|
||||
transformer.injectFunction("vec4 ftransform() { return gl_ModelViewProjectionMatrix * gl_Vertex; }");
|
||||
}
|
||||
|
||||
addIfNotExists(transformer, "iris_ProjectionMatrix", "uniform mat4 iris_ProjectionMatrix;");
|
||||
addIfNotExists(transformer, "iris_ModelViewMatrix", "uniform mat4 iris_ModelViewMatrix;");
|
||||
transformer.injectFunction("vec4 getVertexPosition() { return vec4(modelOffset + _vert_position, 1.0); }");
|
||||
transformer.replaceExpression("gl_Vertex", "getVertexPosition()");
|
||||
|
||||
injectVertInit(transformer);
|
||||
} else {
|
||||
addIfNotExists(transformer, "iris_ModelViewMatrix", "uniform mat4 iris_ModelViewMatrix;");
|
||||
addIfNotExists(transformer, "iris_ProjectionMatrix", "uniform mat4 iris_ProjectionMatrix;");
|
||||
}
|
||||
|
||||
transformer.replaceExpression("gl_ModelViewProjectionMatrix", "(iris_ProjectionMatrix * iris_ModelViewMatrix)");
|
||||
ShaderTransformer.applyIntelHd4000Workaround(transformer);
|
||||
}
|
||||
|
||||
public static void injectVertInit(Transformer transformer) {
|
||||
addIfNotExists(transformer, "_vert_position", "vec3 _vert_position;");
|
||||
addIfNotExists(transformer, "_vert_tex_light_coord", "vec2 _vert_tex_light_coord;");
|
||||
addIfNotExists(transformer, "dhMaterialId", "int dhMaterialId;");
|
||||
addIfNotExists(transformer, "_vert_color", "vec4 _vert_color;");
|
||||
addIfNotExists(transformer, "_vert_normal", "vec3 _vert_normal;");
|
||||
addIfNotExists(transformer, "mircoOffset", "uniform float mircoOffset;");
|
||||
addIfNotExists(transformer, "modelOffset", "uniform vec3 modelOffset;");
|
||||
addIfNotExists(transformer, "iris_color", "in vec4 iris_color;");
|
||||
addIfNotExists(transformer, "vPosition", "in uvec4 vPosition;");
|
||||
addIfNotExists(transformer, "irisExtra", "in uvec4 irisExtra;");
|
||||
|
||||
transformer.injectFunction("const vec3 irisNormals[6] = vec3[](vec3(0,-1,0), vec3(0,1,0), vec3(0,0,-1), vec3(0,0,1), vec3(-1,0,0), vec3(1,0,0));");
|
||||
transformer.injectFunction(
|
||||
"void _vert_init() {"
|
||||
+ " uint meta = vPosition.a;"
|
||||
+ " uint mirco = (meta & 0xFF00u) >> 8u;"
|
||||
+ " float mx = (mirco & 1u) != 0u ? mircoOffset : 0.0;"
|
||||
+ " mx = (mirco & 2u) != 0u ? -mx : mx;"
|
||||
+ " float my = (mirco & 4u) != 0u ? mircoOffset : 0.0;"
|
||||
+ " my = (mirco & 8u) != 0u ? -my : my;"
|
||||
+ " float mz = (mirco & 16u) != 0u ? mircoOffset : 0.0;"
|
||||
+ " mz = (mirco & 32u) != 0u ? -mz : mz;"
|
||||
+ " uint lights = meta & 0xFFu;"
|
||||
+ " _vert_position = (vPosition.xyz + vec3(mx, my, mz));"
|
||||
+ " _vert_normal = irisNormals[int(irisExtra.y)];"
|
||||
+ " dhMaterialId = int(irisExtra.x);"
|
||||
+ " _vert_tex_light_coord = vec2((float(lights / 16u) + 0.5) / 16.0, (mod(float(lights), 16.0) + 0.5) / 16.0);"
|
||||
+ " _vert_color = iris_color;"
|
||||
+ " }"
|
||||
);
|
||||
transformer.prependMain("_vert_init();");
|
||||
}
|
||||
|
||||
private static void addIfNotExists(Transformer transformer, String name, String code) {
|
||||
if (!transformer.hasVariable(name)) {
|
||||
transformer.injectVariable(code);
|
||||
}
|
||||
}
|
||||
|
||||
private static void replaceGlMultiTexCoordBounded(Transformer transformer, int from, int to) {
|
||||
for (int i = from; i <= to; i++) {
|
||||
transformer.replaceExpression("gl_MultiTexCoord" + i, "vec4(0.0, 0.0, 0.0, 1.0)");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,5 +4,7 @@ public enum Patch {
|
||||
ATTRIBUTES,
|
||||
CELERITAS_TERRAIN,
|
||||
COMPOSITE,
|
||||
COMPUTE
|
||||
COMPUTE,
|
||||
DH_TERRAIN,
|
||||
DH_GENERIC
|
||||
}
|
||||
@@ -428,6 +428,7 @@ public class ShaderTransformer {
|
||||
// Handle mc_midTexCoord for Celeritas
|
||||
patchMultiTexCoord3(transformer, parameters);
|
||||
replaceMidTexCoord(transformer, IrisExtendedChunkVertexType.MID_TEX_SCALE);
|
||||
replaceMCEntity(transformer, parameters);
|
||||
applyIntelHd4000Workaround(transformer);
|
||||
break;
|
||||
case COMPOSITE:
|
||||
@@ -439,9 +440,16 @@ public class ShaderTransformer {
|
||||
case COMPUTE:
|
||||
ComputeTransformer.transform(transformer, parameters, versionInt);
|
||||
break;
|
||||
case DH_TERRAIN:
|
||||
DHTerrainTransformer.transform(transformer, parameters, versionInt);
|
||||
break;
|
||||
case DH_GENERIC:
|
||||
DHGenericTransformer.transform(transformer, parameters, versionInt);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unknown patch type: " + patchType.name());
|
||||
}
|
||||
TextureTransformer.transform(transformer, parameters);
|
||||
CompatibilityTransformer.transformEach(transformer, parameters);
|
||||
}
|
||||
|
||||
@@ -487,6 +495,55 @@ public class ShaderTransformer {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces shader-declared mc_Entity (vec2/ivec2/float/int/etc.) with upstream-compatible unpacking
|
||||
* from a single uint attribute. The uint is packed as ((blockId + 1) << 1) | (renderType & 1).
|
||||
*/
|
||||
public static void replaceMCEntity(Transformer transformer, Parameters parameters) {
|
||||
if (parameters.type != ShaderType.VERTEX) return;
|
||||
|
||||
final int type = transformer.findType("mc_Entity");
|
||||
if (type != 0) {
|
||||
transformer.removeVariable("mc_Entity");
|
||||
}
|
||||
transformer.replaceExpression("mc_Entity", "iris_Entity");
|
||||
switch (type) {
|
||||
case 0:
|
||||
case GLSLLexer.BOOL:
|
||||
return;
|
||||
case GLSLLexer.FLOAT:
|
||||
transformer.injectFunction("float iris_Entity = float(int(mc_Entity >> 1u) - 1);");
|
||||
break;
|
||||
case GLSLLexer.VEC2:
|
||||
transformer.injectFunction("vec2 iris_Entity = vec2(int(mc_Entity >> 1u) - 1, mc_Entity & 1u);");
|
||||
break;
|
||||
case GLSLLexer.VEC3:
|
||||
transformer.injectFunction("vec3 iris_Entity = vec3(int(mc_Entity >> 1u) - 1, mc_Entity & 1u, 0.0);");
|
||||
break;
|
||||
case GLSLLexer.VEC4:
|
||||
transformer.injectFunction("vec4 iris_Entity = vec4(int(mc_Entity >> 1u) - 1, mc_Entity & 1u, 0.0, 1.0);");
|
||||
break;
|
||||
case GLSLLexer.UINT:
|
||||
transformer.injectFunction("uint iris_Entity = uint(int(mc_Entity >> 1u) - 1);");
|
||||
break;
|
||||
case GLSLLexer.INT:
|
||||
transformer.injectFunction("int iris_Entity = int(mc_Entity >> 1u) - 1;");
|
||||
break;
|
||||
case GLSLLexer.IVEC2:
|
||||
transformer.injectFunction("ivec2 iris_Entity = ivec2(int(mc_Entity >> 1u) - 1, mc_Entity & 1u);");
|
||||
break;
|
||||
case GLSLLexer.IVEC3:
|
||||
transformer.injectFunction("ivec3 iris_Entity = ivec3(int(mc_Entity >> 1u) - 1, mc_Entity & 1u, 0);");
|
||||
break;
|
||||
case GLSLLexer.IVEC4:
|
||||
transformer.injectFunction("ivec4 iris_Entity = ivec4(int(mc_Entity >> 1u) - 1, mc_Entity & 1u, 0, 1);");
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Got an invalid format mc_Entity (type token " + type + ").");
|
||||
}
|
||||
transformer.injectVariable("in uint mc_Entity;");
|
||||
}
|
||||
|
||||
public static void addIfNotExists(Transformer transformer, String name, String code) {
|
||||
if (!transformer.hasVariable(name)) {
|
||||
transformer.injectVariable(code);
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package net.coderbot.iris.pipeline.transform;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
|
||||
import net.coderbot.iris.gl.texture.TextureType;
|
||||
import net.coderbot.iris.helpers.Tri;
|
||||
import net.coderbot.iris.pipeline.transform.parameter.Parameters;
|
||||
import net.coderbot.iris.shaderpack.texture.TextureStage;
|
||||
import org.taumc.glsl.Transformer;
|
||||
import org.taumc.glsl.grammar.GLSLLexer;
|
||||
|
||||
final class TextureTransformer {
|
||||
private TextureTransformer() {
|
||||
}
|
||||
|
||||
static void transform(Transformer transformer, Parameters parameters) {
|
||||
final Object2ObjectMap<Tri<String, TextureType, TextureStage>, String> textureMap = parameters.getTextureMap();
|
||||
if (textureMap == null || textureMap.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final TextureStage stage = parameters.getTextureStage();
|
||||
textureMap.forEach((key, replacement) -> {
|
||||
if (key.third() != stage) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String name = key.first();
|
||||
final int type = transformer.findType(name);
|
||||
if (type != 0 && isTypeValid(key.second(), type)) {
|
||||
transformer.rename(name, replacement);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static boolean isTypeValid(TextureType expectedType, int extractedType) {
|
||||
return switch (expectedType) {
|
||||
case TEXTURE_1D -> extractedType == GLSLLexer.SAMPLER1D ||
|
||||
extractedType == GLSLLexer.ISAMPLER1D ||
|
||||
extractedType == GLSLLexer.USAMPLER1D;
|
||||
case TEXTURE_RECTANGLE -> extractedType == GLSLLexer.SAMPLER2DRECT ||
|
||||
extractedType == GLSLLexer.ISAMPLER2DRECT ||
|
||||
extractedType == GLSLLexer.USAMPLER2DRECT;
|
||||
case TEXTURE_2D -> extractedType == GLSLLexer.SAMPLER2D ||
|
||||
extractedType == GLSLLexer.ISAMPLER2D ||
|
||||
extractedType == GLSLLexer.USAMPLER2D;
|
||||
case TEXTURE_3D -> extractedType == GLSLLexer.SAMPLER3D ||
|
||||
extractedType == GLSLLexer.ISAMPLER3D ||
|
||||
extractedType == GLSLLexer.USAMPLER3D;
|
||||
};
|
||||
}
|
||||
}
|
||||
Loaded 100 of 165 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user