mirror of
https://github.com/GTNewHorizons/Angelica.git
synced 2026-11-15 01:34:48 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
057ea8035c | ||
|
|
3ea47c8385 | ||
|
|
306d732d81 | ||
|
|
a483669579 | ||
|
|
53996500d7 | ||
|
|
04dd8ce6c7 | ||
|
|
8c9edfa4c3 | ||
|
|
3f44195756 | ||
|
|
c98f056d74 | ||
|
|
7e25f5d03e | ||
|
|
b5553654d0 | ||
|
|
a3fffb47be | ||
|
|
09cc557be0 | ||
|
|
aff5ff7e7b | ||
|
|
e7d08a53b6 | ||
|
|
3b2a0af5c4 | ||
|
|
8c44e79990 | ||
|
|
d2e491ed47 | ||
|
|
bccc5b00ca |
No files matched your search
+6
-1
@@ -90,7 +90,7 @@ dependencies {
|
||||
compileOnly "org.apache.ant:ant:1.8.2"
|
||||
|
||||
// Celeritas (transitive=false: deps provided by GTNHLib/runtime)
|
||||
embedOnly("org.embeddedt.celeritas:celeritas-common:2.5.3-GTNH") { transitive = false }
|
||||
embedOnly("org.embeddedt.celeritas:celeritas-common:2.5.4-GTNH") { transitive = false }
|
||||
embedOnly("org.embeddedt.celeritas:celeritas-lwjgl2-service:2.5.3-GTNH") { transitive = false }
|
||||
|
||||
// Because who doesn't want NEI
|
||||
@@ -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')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -72,6 +72,7 @@ import org.lwjgl.opengl.GL13;
|
||||
import org.lwjgl.opengl.GL14;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
import org.lwjgl.opengl.GL21;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
import org.lwjgl.opengl.GL31;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
@@ -418,6 +419,8 @@ public class GLStateManager {
|
||||
@Getter protected static int boundVBO;
|
||||
@Getter protected static int boundEBO;
|
||||
@Getter protected static int boundVAO;
|
||||
private static int boundPixelUnpackBuffer;
|
||||
private static int boundPixelPackBuffer;
|
||||
private static final Int2IntOpenHashMap vaoEboMap = new Int2IntOpenHashMap();
|
||||
|
||||
static {
|
||||
@@ -1005,6 +1008,8 @@ public class GLStateManager {
|
||||
|
||||
case GL15.GL_ARRAY_BUFFER_BINDING -> boundVBO;
|
||||
case GL15.GL_ELEMENT_ARRAY_BUFFER_BINDING -> boundEBO;
|
||||
case GL21.GL_PIXEL_UNPACK_BUFFER_BINDING -> boundPixelUnpackBuffer;
|
||||
case GL21.GL_PIXEL_PACK_BUFFER_BINDING -> boundPixelPackBuffer;
|
||||
|
||||
case GL20.GL_CURRENT_PROGRAM -> activeProgram;
|
||||
|
||||
@@ -1789,6 +1794,7 @@ public class GLStateManager {
|
||||
}
|
||||
}
|
||||
TextureInfoCache.INSTANCE.onTexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
|
||||
suspendPixelUnpackBuffer();
|
||||
if (shouldUseDSA(target)) {
|
||||
// Use DSA to upload directly to the texture
|
||||
RenderSystem.textureImage2D(getBoundTextureForServerState(), target, level, internalformat, width, height, border, format, type, pixels);
|
||||
@@ -1796,6 +1802,7 @@ public class GLStateManager {
|
||||
// Non-main thread or proxy texture - use direct GL call
|
||||
RENDER_BACKEND.texImage2D(target, level, internalformat, width, height, border, format, type, pixels);
|
||||
}
|
||||
restorePixelUnpackBuffer();
|
||||
}
|
||||
|
||||
public static void glTexImage2D(int target, int level, int internalformat, int width, int height, int border, int format, int type, FloatBuffer pixels) {
|
||||
@@ -1808,7 +1815,9 @@ public class GLStateManager {
|
||||
}
|
||||
}
|
||||
TextureInfoCache.INSTANCE.onTexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
|
||||
suspendPixelUnpackBuffer();
|
||||
RENDER_BACKEND.texImage2D(target, level, internalformat, width, height, border, format, type, pixels);
|
||||
restorePixelUnpackBuffer();
|
||||
}
|
||||
|
||||
public static void glTexImage2D(int target, int level, int internalformat, int width, int height, int border, int format, int type, DoubleBuffer pixels) {
|
||||
@@ -1821,7 +1830,9 @@ public class GLStateManager {
|
||||
}
|
||||
}
|
||||
TextureInfoCache.INSTANCE.onTexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
|
||||
suspendPixelUnpackBuffer();
|
||||
RENDER_BACKEND.texImage2D(target, level, internalformat, width, height, border, format, type, pixels);
|
||||
restorePixelUnpackBuffer();
|
||||
}
|
||||
|
||||
public static void glTexImage2D(int target, int level, int internalformat, int width, int height, int border, int format, int type, ByteBuffer pixels) {
|
||||
@@ -1834,13 +1845,13 @@ public class GLStateManager {
|
||||
}
|
||||
}
|
||||
TextureInfoCache.INSTANCE.onTexImage2D(target, level, internalformat, width, height, border, format, type, pixels != null ? pixels.asIntBuffer() : null);
|
||||
suspendPixelUnpackBuffer();
|
||||
if (shouldUseDSA(target)) {
|
||||
// Use DSA to upload directly to the texture - keeps GL binding state unchanged
|
||||
RenderSystem.textureImage2D(getBoundTextureForServerState(), target, level, internalformat, width, height, border, format, type, pixels);
|
||||
} else {
|
||||
// Non-main thread or proxy texture - use direct GL call
|
||||
RENDER_BACKEND.texImage2D(target, level, internalformat, width, height, border, format, type, pixels);
|
||||
}
|
||||
restorePixelUnpackBuffer();
|
||||
}
|
||||
|
||||
public static void glTexImage2D(int target, int level, int internalformat, int width, int height, int border, int format, int type, long pixels_buffer_offset) {
|
||||
@@ -3780,12 +3791,32 @@ public class GLStateManager {
|
||||
};
|
||||
}
|
||||
|
||||
public static void glGetTexImage(int target, int level, int format, int type, java.nio.ByteBuffer pixels) { RENDER_BACKEND.getTexImage(target, level, format, type, pixels); }
|
||||
public static void glGetTexImage(int target, int level, int format, int type, java.nio.IntBuffer pixels) { RENDER_BACKEND.getTexImage(target, level, format, type, pixels); }
|
||||
public static void glGetTexImage(int target, int level, int format, int type, java.nio.ByteBuffer pixels) {
|
||||
suspendPixelPackBuffer();
|
||||
RENDER_BACKEND.getTexImage(target, level, format, type, pixels);
|
||||
restorePixelPackBuffer();
|
||||
}
|
||||
public static void glGetTexImage(int target, int level, int format, int type, java.nio.IntBuffer pixels) {
|
||||
suspendPixelPackBuffer();
|
||||
RENDER_BACKEND.getTexImage(target, level, format, type, pixels);
|
||||
restorePixelPackBuffer();
|
||||
}
|
||||
|
||||
public static void glReadPixels(int x, int y, int width, int height, int format, int type, ByteBuffer pixels) { RENDER_BACKEND.readPixels(x, y, width, height, format, type, pixels); }
|
||||
public static void glReadPixels(int x, int y, int width, int height, int format, int type, FloatBuffer pixels) { RENDER_BACKEND.readPixels(x, y, width, height, format, type, pixels); }
|
||||
public static void glReadPixels(int x, int y, int width, int height, int format, int type, IntBuffer pixels) { RENDER_BACKEND.readPixels(x, y, width, height, format, type, pixels); }
|
||||
public static void glReadPixels(int x, int y, int width, int height, int format, int type, ByteBuffer pixels) {
|
||||
suspendPixelPackBuffer();
|
||||
RENDER_BACKEND.readPixels(x, y, width, height, format, type, pixels);
|
||||
restorePixelPackBuffer();
|
||||
}
|
||||
public static void glReadPixels(int x, int y, int width, int height, int format, int type, FloatBuffer pixels) {
|
||||
suspendPixelPackBuffer();
|
||||
RENDER_BACKEND.readPixels(x, y, width, height, format, type, pixels);
|
||||
restorePixelPackBuffer();
|
||||
}
|
||||
public static void glReadPixels(int x, int y, int width, int height, int format, int type, IntBuffer pixels) {
|
||||
suspendPixelPackBuffer();
|
||||
RENDER_BACKEND.readPixels(x, y, width, height, format, type, pixels);
|
||||
restorePixelPackBuffer();
|
||||
}
|
||||
public static void glTexStorage2D(int target, int levels, int internalFormat, int width, int height) { RENDER_BACKEND.texStorage2D(target, levels, internalFormat, width, height); }
|
||||
public static void glClearTexImage(int texture, int level, int format, int type, java.nio.ByteBuffer data) { RENDER_BACKEND.clearTexImage(texture, level, format, type); }
|
||||
|
||||
@@ -4201,7 +4232,9 @@ public class GLStateManager {
|
||||
if (DisplayListManager.isRecording()) {
|
||||
throw new UnsupportedOperationException("glTexImage1D in display lists not yet implemented");
|
||||
}
|
||||
suspendPixelUnpackBuffer();
|
||||
RENDER_BACKEND.texImage1D(target, level, internalformat, width, border, format, type, pixels);
|
||||
restorePixelUnpackBuffer();
|
||||
}
|
||||
|
||||
public static void glTexImage3D(int target, int level, int internalformat, int width, int height, int depth, int border, int format, int type, ByteBuffer pixels) {
|
||||
@@ -4209,7 +4242,9 @@ public class GLStateManager {
|
||||
if (DisplayListManager.isRecording()) {
|
||||
throw new UnsupportedOperationException("glTexImage3D in display lists not yet implemented");
|
||||
}
|
||||
suspendPixelUnpackBuffer();
|
||||
RENDER_BACKEND.texImage3D(target, level, internalformat, width, height, depth, border, format, type, pixels);
|
||||
restorePixelUnpackBuffer();
|
||||
}
|
||||
|
||||
public static void glTexImage3D(int target, int level, int internalformat, int width, int height, int depth, int border, int format, int type, IntBuffer pixels) {
|
||||
@@ -4217,14 +4252,18 @@ public class GLStateManager {
|
||||
if (DisplayListManager.isRecording()) {
|
||||
throw new UnsupportedOperationException("glTexImage3D in display lists not yet implemented");
|
||||
}
|
||||
suspendPixelUnpackBuffer();
|
||||
RENDER_BACKEND.texImage3D(target, level, internalformat, width, height, depth, border, format, type, pixels);
|
||||
restorePixelUnpackBuffer();
|
||||
}
|
||||
|
||||
public static void glTexSubImage1D(int target, int level, int xoffset, int width, int format, int type, ByteBuffer pixels) {
|
||||
if (DisplayListManager.isRecording()) {
|
||||
throw new UnsupportedOperationException("glTexSubImage1D in display lists not yet implemented");
|
||||
}
|
||||
suspendPixelUnpackBuffer();
|
||||
RENDER_BACKEND.texSubImage1D(target, level, xoffset, width, format, type, pixels);
|
||||
restorePixelUnpackBuffer();
|
||||
}
|
||||
|
||||
public static void glLineWidth(float width) {
|
||||
@@ -4302,6 +4341,7 @@ public class GLStateManager {
|
||||
return;
|
||||
}
|
||||
}
|
||||
suspendPixelUnpackBuffer();
|
||||
if (shouldUseDSA(target)) {
|
||||
// Use DSA to upload directly to the texture - keeps GL binding state unchanged
|
||||
RenderSystem.textureSubImage2D(getBoundTextureForServerState(), target, level, xoffset, yoffset, width, height, format, type, pixels);
|
||||
@@ -4309,6 +4349,7 @@ public class GLStateManager {
|
||||
// Non-main thread or proxy texture - use direct GL call
|
||||
RENDER_BACKEND.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
|
||||
}
|
||||
restorePixelUnpackBuffer();
|
||||
}
|
||||
|
||||
public static void glTexSubImage2D(int target, int level, int xoffset, int yoffset, int width, int height, int format, int type, IntBuffer pixels) {
|
||||
@@ -4319,6 +4360,7 @@ public class GLStateManager {
|
||||
return;
|
||||
}
|
||||
}
|
||||
suspendPixelUnpackBuffer();
|
||||
if (shouldUseDSA(target)) {
|
||||
// Use DSA to upload directly to the texture
|
||||
RenderSystem.textureSubImage2D(getBoundTextureForServerState(), target, level, xoffset, yoffset, width, height, format, type, pixels);
|
||||
@@ -4326,6 +4368,7 @@ public class GLStateManager {
|
||||
// Non-main thread or proxy texture - use direct GL call
|
||||
RENDER_BACKEND.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
|
||||
}
|
||||
restorePixelUnpackBuffer();
|
||||
}
|
||||
|
||||
public static void glTexSubImage2D(int target, int level, int xoffset, int yoffset, int width, int height, int format, int type, long pixels_buffer_offset) {
|
||||
@@ -4339,7 +4382,9 @@ public class GLStateManager {
|
||||
if (DisplayListManager.isRecording()) {
|
||||
throw new UnsupportedOperationException("glTexSubImage3D in display lists not yet implemented - if you see this, please report!");
|
||||
}
|
||||
suspendPixelUnpackBuffer();
|
||||
RENDER_BACKEND.texSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
|
||||
restorePixelUnpackBuffer();
|
||||
}
|
||||
|
||||
public static void glCopyTexImage1D(int target, int level, int internalFormat, int x, int y, int width, int border) {
|
||||
@@ -4816,10 +4861,38 @@ public class GLStateManager {
|
||||
} else if (target == GL15.GL_ELEMENT_ARRAY_BUFFER) {
|
||||
boundEBO = buffer;
|
||||
vaoEboMap.put(boundVAO, buffer);
|
||||
} else if (target == GL21.GL_PIXEL_UNPACK_BUFFER) {
|
||||
boundPixelUnpackBuffer = buffer;
|
||||
} else if (target == GL21.GL_PIXEL_PACK_BUFFER) {
|
||||
boundPixelPackBuffer = buffer;
|
||||
}
|
||||
RENDER_BACKEND.bindBuffer(target, buffer);
|
||||
}
|
||||
|
||||
private static void suspendPixelUnpackBuffer() {
|
||||
if (boundPixelUnpackBuffer != 0) {
|
||||
RENDER_BACKEND.bindBuffer(GL21.GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private static void restorePixelUnpackBuffer() {
|
||||
if (boundPixelUnpackBuffer != 0) {
|
||||
RENDER_BACKEND.bindBuffer(GL21.GL_PIXEL_UNPACK_BUFFER, boundPixelUnpackBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
private static void suspendPixelPackBuffer() {
|
||||
if (boundPixelPackBuffer != 0) {
|
||||
RENDER_BACKEND.bindBuffer(GL21.GL_PIXEL_PACK_BUFFER, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private static void restorePixelPackBuffer() {
|
||||
if (boundPixelPackBuffer != 0) {
|
||||
RENDER_BACKEND.bindBuffer(GL21.GL_PIXEL_PACK_BUFFER, boundPixelPackBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
public static int glGenBuffers() {
|
||||
return RENDER_BACKEND.genBuffers();
|
||||
}
|
||||
@@ -4828,12 +4901,23 @@ public class GLStateManager {
|
||||
public static void glBufferData(int target, int[] data, int usage) { RENDER_BACKEND.bufferData(target, data, usage); }
|
||||
public static void glBufferData(int target, float[] data, int usage) { RENDER_BACKEND.bufferData(target, data, usage); }
|
||||
public static void glBufferData(int target, java.nio.ByteBuffer data, int usage) { RENDER_BACKEND.bufferData(target, data, usage); }
|
||||
public static void glBufferData(int target, java.nio.FloatBuffer data, int usage) { RENDER_BACKEND.bufferData(target, data, usage); }
|
||||
public static void glBufferData(int target, java.nio.ShortBuffer data, int usage) { RENDER_BACKEND.bufferData(target, data, usage); }
|
||||
public static void glBufferData(int target, java.nio.IntBuffer data, int usage) { RENDER_BACKEND.bufferData(target, data, usage); }
|
||||
public static void glBufferData(int target, java.nio.FloatBuffer data, int usage) { RENDER_BACKEND.bufferData(target, data, usage); }
|
||||
public static void glBufferData(int target, java.nio.DoubleBuffer data, int usage) { RENDER_BACKEND.bufferData(target, data, usage); }
|
||||
public static void glBufferSubData(int target, long offset, java.nio.ByteBuffer data) { RENDER_BACKEND.bufferSubData(target, offset, data); }
|
||||
public static void glBufferSubData(int target, long offset, java.nio.ShortBuffer data) { RENDER_BACKEND.bufferSubData(target, offset, data); }
|
||||
public static void glBufferSubData(int target, long offset, java.nio.IntBuffer data) { RENDER_BACKEND.bufferSubData(target, offset, data); }
|
||||
public static void glBufferSubData(int target, long offset, java.nio.FloatBuffer data) { RENDER_BACKEND.bufferSubData(target, offset, data); }
|
||||
public static void glBufferSubData(int target, long offset, java.nio.DoubleBuffer data) { RENDER_BACKEND.bufferSubData(target, offset, data); }
|
||||
public static ByteBuffer glMapBuffer(int target, int access) { return RENDER_BACKEND.mapBuffer(target, access); }
|
||||
public static ByteBuffer glMapBuffer(int target, int access, long length, ByteBuffer old_buffer) { return RENDER_BACKEND.mapBuffer(target, access, length, old_buffer); }
|
||||
public static boolean glUnmapBuffer(int target) { return RENDER_BACKEND.unmapBuffer(target); }
|
||||
public static void glGetBufferSubData(int target, long offset, java.nio.ByteBuffer data) { RENDER_BACKEND.getBufferSubData(target, offset, data); }
|
||||
public static void glGetBufferSubData(int target, long offset, java.nio.ShortBuffer data) { RENDER_BACKEND.getBufferSubData(target, offset, data); }
|
||||
public static void glGetBufferSubData(int target, long offset, java.nio.IntBuffer data) { RENDER_BACKEND.getBufferSubData(target, offset, data); }
|
||||
public static void glGetBufferSubData(int target, long offset, java.nio.FloatBuffer data) { RENDER_BACKEND.getBufferSubData(target, offset, data); }
|
||||
public static void glGetBufferSubData(int target, long offset, java.nio.DoubleBuffer data) { RENDER_BACKEND.getBufferSubData(target, offset, data); }
|
||||
public static int glGetBufferParameteri(int target, int pname) { return RENDER_BACKEND.getBufferParameteri(target, pname); }
|
||||
public static void glBufferStorage(int target, java.nio.ByteBuffer data, int flags) { RENDER_BACKEND.bufferStorage(target, data, flags); }
|
||||
public static void glBufferStorage(int target, long size, int flags) { RENDER_BACKEND.bufferStorage(target, size, flags); }
|
||||
@@ -4949,6 +5033,14 @@ public class GLStateManager {
|
||||
|
||||
public static void glFramebufferTexture(int target, int attachment, int texture, int level) { RENDER_BACKEND.framebufferTexture(target, attachment, texture, level); }
|
||||
|
||||
public static void glGenerateMipmap(int target) {
|
||||
RENDER_BACKEND.generateMipmap(target);
|
||||
}
|
||||
|
||||
public static void glBlitFramebuffer(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, int mask, int filter) {
|
||||
RENDER_BACKEND.blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
|
||||
}
|
||||
|
||||
public static void setActiveTexture(int textureUnit) {
|
||||
glActiveTexture(textureUnit);
|
||||
}
|
||||
|
||||
@@ -902,6 +902,16 @@ public final class Lwjgl2GLRenderBackend extends RenderBackend {
|
||||
GL15.glBufferData(target, data, usage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bufferData(int target, IntBuffer data, int usage) {
|
||||
GL15.glBufferData(target, data, usage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bufferData(int target, DoubleBuffer data, int usage) {
|
||||
GL15.glBufferData(target, data, usage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bufferData(int target, int[] data, int usage) {
|
||||
final IntBuffer buffer = getIntArrayBuffer(data.length);
|
||||
@@ -923,11 +933,36 @@ public final class Lwjgl2GLRenderBackend extends RenderBackend {
|
||||
GL15.glBufferSubData(target, offset, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bufferSubData(int target, long offset, ShortBuffer data) {
|
||||
GL15.glBufferSubData(target, offset, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bufferSubData(int target, long offset, IntBuffer data) {
|
||||
GL15.glBufferSubData(target, offset, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bufferSubData(int target, long offset, FloatBuffer data) {
|
||||
GL15.glBufferSubData(target, offset, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bufferSubData(int target, long offset, DoubleBuffer data) {
|
||||
GL15.glBufferSubData(target, offset, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer mapBuffer(int target, int access) {
|
||||
return GL15.glMapBuffer(target, access, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer mapBuffer(int target, int access, long length, ByteBuffer old_buffer) {
|
||||
return GL15.glMapBuffer(target, access, length, old_buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean unmapBuffer(int target) {
|
||||
return GL15.glUnmapBuffer(target);
|
||||
@@ -948,6 +983,26 @@ public final class Lwjgl2GLRenderBackend extends RenderBackend {
|
||||
GL15.glGetBufferSubData(target, offset, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getBufferSubData(int target, long offset, ShortBuffer data) {
|
||||
GL15.glGetBufferSubData(target, offset, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getBufferSubData(int target, long offset, IntBuffer data) {
|
||||
GL15.glGetBufferSubData(target, offset, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getBufferSubData(int target, long offset, FloatBuffer data) {
|
||||
GL15.glGetBufferSubData(target, offset, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getBufferSubData(int target, long offset, DoubleBuffer data) {
|
||||
GL15.glGetBufferSubData(target, offset, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBufferParameteri(int target, int pname) {
|
||||
return GL15.glGetBufferParameteri(target, pname);
|
||||
|
||||
@@ -208,14 +208,25 @@ public abstract class RenderBackend {
|
||||
public abstract void bufferData(int target, ByteBuffer data, int usage);
|
||||
public abstract void bufferData(int target, FloatBuffer data, int usage);
|
||||
public abstract void bufferData(int target, ShortBuffer data, int usage);
|
||||
public abstract void bufferData(int target, IntBuffer data, int usage);
|
||||
public abstract void bufferData(int target, DoubleBuffer data, int usage);
|
||||
public abstract void bufferData(int target, int[] data, int usage);
|
||||
public abstract void bufferData(int target, float[] data, int usage);
|
||||
public abstract void bufferSubData(int target, long offset, ByteBuffer data);
|
||||
public abstract void bufferSubData(int target, long offset, ShortBuffer data);
|
||||
public abstract void bufferSubData(int target, long offset, IntBuffer data);
|
||||
public abstract void bufferSubData(int target, long offset, FloatBuffer data);
|
||||
public abstract void bufferSubData(int target, long offset, DoubleBuffer data);
|
||||
public abstract ByteBuffer mapBuffer(int target, int access);
|
||||
public abstract ByteBuffer mapBuffer(int target, int access, long length, ByteBuffer old_buffer);
|
||||
public abstract boolean unmapBuffer(int target);
|
||||
public abstract void bufferStorage(int target, ByteBuffer data, int flags);
|
||||
public abstract void bufferStorage(int target, long size, int flags);
|
||||
public abstract void getBufferSubData(int target, long offset, ByteBuffer data);
|
||||
public abstract void getBufferSubData(int target, long offset, ShortBuffer data);
|
||||
public abstract void getBufferSubData(int target, long offset, IntBuffer data);
|
||||
public abstract void getBufferSubData(int target, long offset, FloatBuffer data);
|
||||
public abstract void getBufferSubData(int target, long offset, DoubleBuffer data);
|
||||
public abstract int getBufferParameteri(int target, int pname);
|
||||
public abstract boolean isBuffer(int buffer);
|
||||
public abstract ByteBuffer mapBufferRange(int target, long offset, long length, int access);
|
||||
|
||||
+55
@@ -893,6 +893,16 @@ public final class Lwjgl3GLRenderBackend extends RenderBackend {
|
||||
GL15C.glBufferData(target, data, usage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bufferData(int target, IntBuffer data, int usage) {
|
||||
GL15C.glBufferData(target, data, usage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bufferData(int target, DoubleBuffer data, int usage) {
|
||||
GL15C.glBufferData(target, data, usage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bufferData(int target, int[] data, int usage) {
|
||||
GL15C.glBufferData(target, data, usage);
|
||||
@@ -908,11 +918,36 @@ public final class Lwjgl3GLRenderBackend extends RenderBackend {
|
||||
GL15C.glBufferSubData(target, offset, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bufferSubData(int target, long offset, ShortBuffer data) {
|
||||
GL15C.glBufferSubData(target, offset, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bufferSubData(int target, long offset, IntBuffer data) {
|
||||
GL15C.glBufferSubData(target, offset, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bufferSubData(int target, long offset, FloatBuffer data) {
|
||||
GL15C.glBufferSubData(target, offset, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bufferSubData(int target, long offset, DoubleBuffer data) {
|
||||
GL15C.glBufferSubData(target, offset, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer mapBuffer(int target, int access) {
|
||||
return GL15C.glMapBuffer(target, access);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer mapBuffer(int target, int access, long length, ByteBuffer old_buffer) {
|
||||
return GL15C.glMapBuffer(target, access, length, old_buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean unmapBuffer(int target) {
|
||||
return GL15C.glUnmapBuffer(target);
|
||||
@@ -933,6 +968,26 @@ public final class Lwjgl3GLRenderBackend extends RenderBackend {
|
||||
GL15C.glGetBufferSubData(target, offset, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getBufferSubData(int target, long offset, ShortBuffer data) {
|
||||
GL15C.glGetBufferSubData(target, offset, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getBufferSubData(int target, long offset, IntBuffer data) {
|
||||
GL15C.glGetBufferSubData(target, offset, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getBufferSubData(int target, long offset, FloatBuffer data) {
|
||||
GL15C.glGetBufferSubData(target, offset, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getBufferSubData(int target, long offset, DoubleBuffer data) {
|
||||
GL15C.glGetBufferSubData(target, offset, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBufferParameteri(int target, int pname) {
|
||||
return GL15C.glGetBufferParameteri(target, pname);
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
package com.gtnewhorizons.angelica.api;
|
||||
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
|
||||
/**
|
||||
* Provides per-block RGB light color data for the rendering pipeline. Mods that replace the lighting engine (e.g. Supernova) implement this
|
||||
* and register via {@link #register(BlockLightProvider)}.
|
||||
*
|
||||
*/
|
||||
public interface BlockLightProvider {
|
||||
|
||||
/**
|
||||
* Get RGB block light at the given world coordinates.
|
||||
*
|
||||
* @param blockAccess the block access context (WorldSlice on builder threads, World on main thread)
|
||||
* @return packed RGB (see class Javadoc), or {@code -1} if no data is available
|
||||
*/
|
||||
int getBlockLightRGB(IBlockAccess blockAccess, int x, int y, int z);
|
||||
|
||||
/**
|
||||
* Get RGB sky light at the given world coordinates.
|
||||
*
|
||||
* @param blockAccess the block access context (WorldSlice on builder threads, World on main thread)
|
||||
* @return packed RGB (see class Javadoc), or {@code -1} if no data
|
||||
*/
|
||||
default int getSkyLightRGB(IBlockAccess blockAccess, int x, int y, int z) { return -1; }
|
||||
|
||||
/**
|
||||
* Capture per-section light data on the main thread for use by builder threads.
|
||||
* Called during {@code ClonedChunkSection.init()}.
|
||||
*
|
||||
* @return a {@link SectionLightData} snapshot, or {@code null} if not supported
|
||||
*/
|
||||
default SectionLightData prepareSectionData(Chunk chunk, int sectionY) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Pack three 0-15 channels into a single int. */
|
||||
static int packRGB(int r, int g, int b) {
|
||||
return (r << 8) | (g << 4) | b;
|
||||
}
|
||||
|
||||
/** Extract the red channel (0-15) from a packed RGB word. */
|
||||
static int unpackR(int word) {
|
||||
return (word >> 8) & 0xF;
|
||||
}
|
||||
|
||||
/** Extract the green channel (0-15) from a packed RGB word. */
|
||||
static int unpackG(int word) {
|
||||
return (word >> 4) & 0xF;
|
||||
}
|
||||
|
||||
/** Extract the blue channel (0-15) from a packed RGB word. */
|
||||
static int unpackB(int word) {
|
||||
return word & 0xF;
|
||||
}
|
||||
|
||||
static BlockLightProvider getInstance() {
|
||||
return Holder.INSTANCE;
|
||||
}
|
||||
|
||||
static boolean isRegistered() {
|
||||
return Holder.INSTANCE != Holder.DEFAULT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the global block light provider. Must be called exactly once.
|
||||
*
|
||||
* @throws IllegalStateException if a provider has already been registered
|
||||
*/
|
||||
static void register(BlockLightProvider provider) {
|
||||
if (Holder.INSTANCE != Holder.DEFAULT) {
|
||||
throw new IllegalStateException("BlockLightProvider already registered: " + Holder.INSTANCE.getClass().getName() + ". Cannot register " + provider.getClass().getName());
|
||||
}
|
||||
Holder.INSTANCE = provider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call from your {@code IFMLLoadingPlugin} static initializer to enable colored light support.
|
||||
* Must be called before mixin application (i.e. during coremod loading). Calling after mixins are frozen will throw.
|
||||
*/
|
||||
static void enableColoredLight() {
|
||||
if (EarlyFlags.MIXINS_FROZEN) {
|
||||
throw new IllegalStateException("Too late to enable colored light -- mixin configs have already been evaluated. Call BlockLightProvider.enableColoredLight() from your IFMLLoadingPlugin.");
|
||||
}
|
||||
EarlyFlags.COLORED_LIGHT = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Freeze the mixin config gate. After this call, {@link #enableColoredLight()} will throw.
|
||||
* Called by the mixin config evaluation path before reading {@link #coloredLightEnabled()}.
|
||||
*/
|
||||
static void freezeMixinConfig() {
|
||||
EarlyFlags.MIXINS_FROZEN = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether colored light support was enabled via {@link #enableColoredLight()}.
|
||||
* Call {@link #freezeMixinConfig()} separately to close the enablement window.
|
||||
*/
|
||||
static boolean coloredLightEnabled() {
|
||||
return EarlyFlags.COLORED_LIGHT;
|
||||
}
|
||||
|
||||
final class EarlyFlags {
|
||||
static boolean COLORED_LIGHT = false;
|
||||
static boolean MIXINS_FROZEN = false;
|
||||
}
|
||||
|
||||
final class Holder {
|
||||
static final BlockLightProvider DEFAULT = (_, _, _, _) -> -1;
|
||||
static BlockLightProvider INSTANCE = DEFAULT;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.gtnewhorizons.angelica.api;
|
||||
|
||||
/**
|
||||
* Mixin interface for {@code AoFaceData} providing per-corner RGB light values.
|
||||
* Each array has 4 elements corresponding to the quad's corner vertices.
|
||||
*/
|
||||
public interface ExtAoFaceData {
|
||||
|
||||
/** Per-corner red light values (block light, 0-15 range). */
|
||||
float[] angelica$getRl();
|
||||
|
||||
/** Per-corner green light values (block light, 0-15 range). */
|
||||
float[] angelica$getGl();
|
||||
|
||||
/** Per-corner blue light values (block light, 0-15 range). */
|
||||
float[] angelica$getBl();
|
||||
|
||||
float angelica$getBlendedR(float[] w);
|
||||
float angelica$getBlendedG(float[] w);
|
||||
float angelica$getBlendedB(float[] w);
|
||||
|
||||
/** Per-corner red light values (sky light, 0-15 range). */
|
||||
float[] angelica$getSkyRl();
|
||||
|
||||
/** Per-corner green light values (sky light, 0-15 range). */
|
||||
float[] angelica$getSkyGl();
|
||||
|
||||
/** Per-corner blue light values (sky light, 0-15 range). */
|
||||
float[] angelica$getSkyBl();
|
||||
|
||||
float angelica$getBlendedSkyR(float[] w);
|
||||
float angelica$getBlendedSkyG(float[] w);
|
||||
float angelica$getBlendedSkyB(float[] w);
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.gtnewhorizons.angelica.api;
|
||||
|
||||
import org.embeddedt.embeddium.impl.model.quad.properties.ModelQuadFacing;
|
||||
|
||||
/**
|
||||
* Mixin interface for {@code LightDataAccess} providing per-block RGB light cache.
|
||||
*
|
||||
* <h3>Channel format</h3>
|
||||
* Individual RGB words use the {@link BlockLightProvider} packing: {@code (r << 8) | (g << 4) | b}, each channel 0-15.
|
||||
*
|
||||
*/
|
||||
public interface ExtLightDataAccess {
|
||||
|
||||
/** RGB block light at exact world coordinates. */
|
||||
int angelica$getRGB(int x, int y, int z);
|
||||
|
||||
/** RGB block light offset one block in {@code dir} (face neighbor lookup). */
|
||||
int angelica$getRGB(int x, int y, int z, ModelQuadFacing dir);
|
||||
|
||||
/** RGB block light offset by two directions (edge/corner neighbor for AO). */
|
||||
int angelica$getRGB(int x, int y, int z, ModelQuadFacing d1, ModelQuadFacing d2);
|
||||
|
||||
boolean angelica$isRGBEnabled();
|
||||
|
||||
/** RGB sky light at exact world coordinates. */
|
||||
int angelica$getSkyRGB(int x, int y, int z);
|
||||
|
||||
/** RGB sky light offset one block in {@code dir} (face neighbor lookup). */
|
||||
int angelica$getSkyRGB(int x, int y, int z, ModelQuadFacing dir);
|
||||
|
||||
/** RGB sky light offset by two directions (edge/corner neighbor for AO). */
|
||||
int angelica$getSkyRGB(int x, int y, int z, ModelQuadFacing d1, ModelQuadFacing d2);
|
||||
|
||||
boolean angelica$isSkyRGBEnabled();
|
||||
|
||||
/**
|
||||
* Compute cache array index for the given world coordinates. Use with
|
||||
* {@link #angelica$getRGBByIndex}, {@link #angelica$getSkyRGBByIndex}, or
|
||||
* {@link #angelica$getFusedByIndex}
|
||||
*/
|
||||
int angelica$getIndex(int x, int y, int z);
|
||||
|
||||
/** Like {@link #angelica$getRGB(int, int, int)} but with a pre-computed cache index. */
|
||||
int angelica$getRGBByIndex(int idx, int x, int y, int z);
|
||||
|
||||
/** Like {@link #angelica$getSkyRGB(int, int, int)} but with a pre-computed cache index. */
|
||||
int angelica$getSkyRGBByIndex(int idx, int x, int y, int z);
|
||||
|
||||
/**
|
||||
* Single cache lookup returning both block and sky RGB in the <b>cache format</b>.
|
||||
* Upper 32 bits = block word (packed RGB | SENTINEL), lower 32 bits = sky word (packed RGB | SENTINEL).
|
||||
*/
|
||||
long angelica$getFusedByIndex(int idx, int x, int y, int z);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.gtnewhorizons.angelica.api;
|
||||
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
|
||||
/**
|
||||
* Interface for {@code LightDataCache} exposing its block access reference.
|
||||
*/
|
||||
public interface ExtLightDataCache {
|
||||
|
||||
IBlockAccess angelica$getBlockAccess();
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.gtnewhorizons.angelica.api;
|
||||
|
||||
/**
|
||||
* Interface for {@code QuadLightData} providing per-vertex RGB light values.
|
||||
*/
|
||||
public interface ExtQuadLightData {
|
||||
|
||||
float[] angelica$getR();
|
||||
float[] angelica$getG();
|
||||
float[] angelica$getB();
|
||||
|
||||
boolean angelica$isRGBValid();
|
||||
void angelica$setRGBValid(boolean valid);
|
||||
|
||||
float[] angelica$getSkyR();
|
||||
float[] angelica$getSkyG();
|
||||
float[] angelica$getSkyB();
|
||||
|
||||
boolean angelica$isSkyRGBValid();
|
||||
void angelica$setSkyRGBValid(boolean valid);
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.gtnewhorizons.angelica.api;
|
||||
|
||||
/**
|
||||
* Provides RGB light data for a single chunk section. Implemented by external providers (e.g. Supernova)
|
||||
* and returned from {@link BlockLightProvider#prepareSectionData}.
|
||||
*
|
||||
* <h3>Transport format</h3>
|
||||
* {@link #getRGBAndSkyRGB} returns a compact <b>transport format</b>: {@code ((block & 0xFFFF) << 16) | (sky & 0xFFFF)}.
|
||||
*/
|
||||
public interface SectionLightData {
|
||||
|
||||
/**
|
||||
* Get RGB block light at section-local coordinates.
|
||||
*
|
||||
* @param localX 0-15
|
||||
* @param localY 0-15
|
||||
* @param localZ 0-15
|
||||
* @return packed {@code (r << 8) | (g << 4) | b}, each channel 0-15, or {@code -1} if unavailable
|
||||
*/
|
||||
int getRGB(int localX, int localY, int localZ);
|
||||
|
||||
/**
|
||||
* Get RGB sky light at section-local coordinates.
|
||||
*
|
||||
* @param localX 0-15
|
||||
* @param localY 0-15
|
||||
* @param localZ 0-15
|
||||
* @return packed {@code (r << 8) | (g << 4) | b}, each channel 0-15, or {@code -1} if unavailable
|
||||
*/
|
||||
default int getSkyRGB(int localX, int localY, int localZ) { return -1; }
|
||||
|
||||
/**
|
||||
* Get both block and sky RGB in a single call (transport format). Implementations can override
|
||||
* to share index computation and apply section-level fast paths.
|
||||
*
|
||||
* @return {@code ((block & 0xFFFF) << 16) | (sky & 0xFFFF)}
|
||||
*/
|
||||
default long getRGBAndSkyRGB(int localX, int localY, int localZ) {
|
||||
return ((long)(getRGB(localX, localY, localZ) & 0xFFFF) << 16) | (getSkyRGB(localX, localY, localZ) & 0xFFFF);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.gtnewhorizons.angelica.api;
|
||||
|
||||
/**
|
||||
* Computes an RGB tint from block light and sky light channel values. The lightmap handles brightness; the tint only controls color.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface TintComputer {
|
||||
|
||||
/**
|
||||
* Blend block light RGB and sky light RGB into a tint color.
|
||||
*
|
||||
* @param br block light red (0-15)
|
||||
* @param bg block light green (0-15)
|
||||
* @param bb block light blue (0-15)
|
||||
* @param sr sky light red (0-15, already adjusted for sky subtraction)
|
||||
* @param sg sky light green (0-15)
|
||||
* @param sb sky light blue (0-15)
|
||||
* @param out float[3] output: R, G, B tint multipliers (typically 0-1)
|
||||
*/
|
||||
void computeTint(float br, float bg, float bb, float sr, float sg, float sb, float[] out);
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package com.gtnewhorizons.angelica.api;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Registry for tint blend modes used by the colored light pipeline. Provides a default no-tint mode.
|
||||
* External mods (e.g. Supernova) can register additional modes via {@link #registerMode(String, TintComputer)}.
|
||||
*
|
||||
*/
|
||||
public final class TintRegistry {
|
||||
|
||||
private static final TintComputer NO_TINT = (br, bg, bb, sr, sg, sb, out) -> {
|
||||
out[0] = 1f;
|
||||
out[1] = 1f;
|
||||
out[2] = 1f;
|
||||
};
|
||||
|
||||
private static final List<TintComputer> computers = new ArrayList<>();
|
||||
private static final List<String> names = new ArrayList<>();
|
||||
private static TintComputer current;
|
||||
private static volatile int currentOrdinal;
|
||||
|
||||
static {
|
||||
registerMode("NONE", NO_TINT);
|
||||
current = NO_TINT;
|
||||
currentOrdinal = 0;
|
||||
}
|
||||
|
||||
private TintRegistry() {}
|
||||
|
||||
/** Register a named tint blend mode. Returns the ordinal assigned. */
|
||||
public static int registerMode(String name, TintComputer computer) {
|
||||
final int ordinal = computers.size();
|
||||
computers.add(computer);
|
||||
names.add(name);
|
||||
return ordinal;
|
||||
}
|
||||
|
||||
/** Returns the currently active tint computer. */
|
||||
public static TintComputer getCurrent() {
|
||||
return current;
|
||||
}
|
||||
|
||||
/** Returns the ordinal of the current mode, or -1 if a custom (non-registered) computer is active. */
|
||||
public static int getCurrentOrdinal() {
|
||||
return currentOrdinal;
|
||||
}
|
||||
|
||||
/** Switch to a registered mode by ordinal. */
|
||||
public static void setCurrentByOrdinal(int ordinal) {
|
||||
if (ordinal < 0 || ordinal >= computers.size()) {
|
||||
throw new IllegalArgumentException("Invalid tint mode ordinal: " + ordinal + " (registered modes: " + computers.size() + ")");
|
||||
}
|
||||
current = computers.get(ordinal);
|
||||
currentOrdinal = ordinal;
|
||||
}
|
||||
|
||||
/** Set a custom tint computer directly. */
|
||||
public static void setCurrent(TintComputer computer) {
|
||||
current = computer;
|
||||
// Resolve ordinal; custom computers not in the registry get -1
|
||||
for (int i = 0; i < computers.size(); i++) {
|
||||
if (computers.get(i) == computer) {
|
||||
currentOrdinal = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
currentOrdinal = -1;
|
||||
}
|
||||
|
||||
/** Returns the number of registered blend modes. */
|
||||
public static int getModeCount() {
|
||||
return computers.size();
|
||||
}
|
||||
|
||||
/** Returns the display name of a registered mode by ordinal. */
|
||||
public static String getModeName(int ordinal) {
|
||||
if (ordinal < 0 || ordinal >= names.size()) return "UNKNOWN";
|
||||
return names.get(ordinal);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+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 =====================
|
||||
|
||||
@@ -99,10 +99,14 @@ public class DeferredDrawBatcher {
|
||||
totalBytes += e.byteLength();
|
||||
totalVertices += e.vertexCount();
|
||||
subEnd++;
|
||||
|
||||
// Don't try to merge strips, fans, loops or polygons
|
||||
if (drawMode == GL11.GL_TRIANGLE_STRIP || drawMode == GL11.GL_TRIANGLE_FAN || drawMode == GL11.GL_LINE_STRIP ||
|
||||
drawMode == GL11.GL_LINE_LOOP || drawMode == GL11.GL_QUAD_STRIP || drawMode == GL11.GL_POLYGON)
|
||||
break;
|
||||
}
|
||||
|
||||
TessellatorStreamingDrawer.drawPackedBatch(
|
||||
batchTessellator, ranges, i, subEnd, totalBytes, totalVertices, drawMode, flags);
|
||||
TessellatorStreamingDrawer.drawPackedBatch(batchTessellator, ranges, i, subEnd, totalBytes, totalVertices, drawMode, flags);
|
||||
|
||||
i = subEnd;
|
||||
}
|
||||
|
||||
@@ -224,6 +224,13 @@ public class AngelicaConfig {
|
||||
})
|
||||
public static String[] blockCrackFixRenderPassWhitelist__;
|
||||
|
||||
@Config.Comment({"List of sprites which should always be treated as translucent.",
|
||||
"Sprites added to this list will always be considered translucent,",
|
||||
"",
|
||||
"Requires texture reload (F3+T) to take effect."})
|
||||
@Config.DefaultStringList({"jewelrycraft2:blockCrystal"})
|
||||
public static String[] alwaysTranslucentSprites;
|
||||
|
||||
@Config.Comment("Register HardcodedCustomUniforms in Iris Shaders. May help with compatibility in certain shader packs")
|
||||
@Config.DefaultBoolean(false)
|
||||
public static boolean enableHardcodedCustomUniforms;
|
||||
@@ -232,6 +239,31 @@ public class AngelicaConfig {
|
||||
@Config.DefaultBoolean(true)
|
||||
public static boolean defineIsIris;
|
||||
|
||||
@Config.Comment("ASM transformer exclusion narrowing for mod compatibility. Disable per-mod if narrowing causes class loading issues.")
|
||||
public static TransformerCompat transformerCompat = new TransformerCompat();
|
||||
|
||||
public static class TransformerCompat {
|
||||
@Config.Comment("Narrow DragonAPI transformer exclusions to allow GL redirection")
|
||||
@Config.DefaultBoolean(true)
|
||||
@Config.RequiresMcRestart
|
||||
public boolean narrowDragonAPI;
|
||||
|
||||
@Config.Comment("Narrow Xaeros Minimap/Worldmap transformer exclusions to allow GL redirection")
|
||||
@Config.DefaultBoolean(true)
|
||||
@Config.RequiresMcRestart
|
||||
public boolean narrowXaeros;
|
||||
|
||||
@Config.Comment("Narrow AdvancedLightsabers transformer exclusions to allow GL redirection")
|
||||
@Config.DefaultBoolean(true)
|
||||
@Config.RequiresMcRestart
|
||||
public boolean narrowAdvancedLightsabers;
|
||||
|
||||
@Config.Comment("Narrow Alfheim transformer exclusions to allow GL redirection")
|
||||
@Config.DefaultBoolean(true)
|
||||
@Config.RequiresMcRestart
|
||||
public boolean narrowAlfheim;
|
||||
}
|
||||
|
||||
@Config.Comment("Renders chunks before neighbors are ready. Improves loading at render distance edges, useful for low render distance servers.")
|
||||
@Config.DefaultBoolean(false)
|
||||
public static boolean useVanillaChunkTracking;
|
||||
|
||||
@@ -4,6 +4,7 @@ import baubles.common.lib.PlayerHandler;
|
||||
import com.gtnewhorizon.gtnhlib.blockpos.BlockPos;
|
||||
import com.gtnewhorizon.gtnhlib.blockpos.IBlockPos;
|
||||
import com.gtnewhorizon.gtnhlib.util.CoordinatePacker;
|
||||
import com.gtnewhorizons.angelica.api.BlockLightProvider;
|
||||
import com.gtnewhorizons.angelica.api.IDynamicLightProducer;
|
||||
import com.gtnewhorizons.angelica.compat.ModStatus;
|
||||
import com.gtnewhorizons.angelica.compat.backhand.BackhandReflectionCompat;
|
||||
@@ -52,12 +53,18 @@ public class DynamicLights {
|
||||
private static final double MAX_RADIUS = 7.75;
|
||||
private static final double MAX_RADIUS_SQUARED = MAX_RADIUS * MAX_RADIUS;
|
||||
private final Set<IDynamicLightSource> dynamicLightSources = new ObjectOpenHashSet<>();
|
||||
private IDynamicLightSource[] lightSourceArray = new IDynamicLightSource[0];
|
||||
private final ReentrantReadWriteLock lightSourcesLock = new ReentrantReadWriteLock();
|
||||
private volatile int lightSourceCount = 0;
|
||||
private final ChunkRebuildManager chunkRebuildManager = new ChunkRebuildManager();
|
||||
private long lastUpdate = System.currentTimeMillis();
|
||||
private int lastUpdateCount = 0;
|
||||
|
||||
/** Must be called under write lock. */
|
||||
private void rebuildLightSourceArray() {
|
||||
this.lightSourceArray = this.dynamicLightSources.toArray(new IDynamicLightSource[0]);
|
||||
}
|
||||
|
||||
public static DynamicLights get() {
|
||||
if (instance == null)
|
||||
instance = new DynamicLights();
|
||||
@@ -93,7 +100,7 @@ public class DynamicLights {
|
||||
if (!isEnabled())
|
||||
return;
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
final long now = System.currentTimeMillis();
|
||||
if (now >= this.lastUpdate + Mode.getDelay()) {
|
||||
this.lastUpdate = now;
|
||||
this.lastUpdateCount = 0;
|
||||
@@ -104,7 +111,7 @@ public class DynamicLights {
|
||||
int worldTick = 0;
|
||||
|
||||
if (AdaptiveTickingEnabled) {
|
||||
Minecraft mc = Minecraft.getMinecraft();
|
||||
final Minecraft mc = Minecraft.getMinecraft();
|
||||
if (mc.theWorld != null && mc.renderViewEntity != null) {
|
||||
cameraX = mc.renderViewEntity.posX;
|
||||
cameraY = mc.renderViewEntity.posY + mc.renderViewEntity.getEyeHeight();
|
||||
@@ -112,15 +119,15 @@ public class DynamicLights {
|
||||
worldTick = (int) (mc.theWorld.getTotalWorldTime() & 0x7FFFFFFF);
|
||||
|
||||
// Calculate look direction from yaw (normalized horizontal direction)
|
||||
float yaw = mc.renderViewEntity.rotationYaw;
|
||||
double yawRad = Math.toRadians(yaw);
|
||||
final float yaw = mc.renderViewEntity.rotationYaw;
|
||||
final double yawRad = Math.toRadians(yaw);
|
||||
lookDirX = -Math.sin(yawRad);
|
||||
lookDirZ = Math.cos(yawRad);
|
||||
}
|
||||
}
|
||||
|
||||
this.lightSourcesLock.readLock().lock();
|
||||
for (var lightSource : this.dynamicLightSources) {
|
||||
for (var lightSource : this.lightSourceArray) {
|
||||
// Entity type filter
|
||||
if (!EntityLightConfig.isEntityTypeEnabled(lightSource)) {
|
||||
continue;
|
||||
@@ -128,7 +135,7 @@ public class DynamicLights {
|
||||
|
||||
// Adaptive ticking filter
|
||||
if (AdaptiveTickingEnabled) {
|
||||
AdaptiveTickMode mode = AdaptiveTickCalculator.calculate(
|
||||
final AdaptiveTickMode mode = AdaptiveTickCalculator.calculate(
|
||||
lightSource, cameraX, cameraY, cameraZ, lookDirX, lookDirZ);
|
||||
if (!mode.shouldTickThisFrame(worldTick, lightSource.hashCode())) {
|
||||
continue;
|
||||
@@ -150,6 +157,7 @@ public class DynamicLights {
|
||||
this.lightSourcesLock.writeLock().lock();
|
||||
if (this.dynamicLightSources.add(lightSource)) {
|
||||
this.lightSourceCount = this.dynamicLightSources.size();
|
||||
rebuildLightSourceArray();
|
||||
}
|
||||
this.lightSourcesLock.writeLock().unlock();
|
||||
}
|
||||
@@ -162,17 +170,11 @@ public class DynamicLights {
|
||||
public void removeLightSource(@NotNull IDynamicLightSource lightSource) {
|
||||
this.lightSourcesLock.writeLock().lock();
|
||||
|
||||
var dynamicLightSources = this.dynamicLightSources.iterator();
|
||||
IDynamicLightSource it;
|
||||
while (dynamicLightSources.hasNext()) {
|
||||
it = dynamicLightSources.next();
|
||||
if (it.equals(lightSource)) {
|
||||
dynamicLightSources.remove();
|
||||
this.lightSourceCount = this.dynamicLightSources.size();
|
||||
if (activeRenderer != null)
|
||||
lightSource.angelica$scheduleTrackedChunksRebuild(activeRenderer);
|
||||
break;
|
||||
}
|
||||
if (this.dynamicLightSources.remove(lightSource)) {
|
||||
this.lightSourceCount = this.dynamicLightSources.size();
|
||||
rebuildLightSourceArray();
|
||||
if (activeRenderer != null)
|
||||
lightSource.angelica$scheduleTrackedChunksRebuild(activeRenderer);
|
||||
}
|
||||
|
||||
this.lightSourcesLock.writeLock().unlock();
|
||||
@@ -186,13 +188,14 @@ public class DynamicLights {
|
||||
public void removeLightSources(@NotNull Predicate<IDynamicLightSource> filter) {
|
||||
this.lightSourcesLock.writeLock().lock();
|
||||
|
||||
var dynamicLightSources = this.dynamicLightSources.iterator();
|
||||
final var dynamicLightSources = this.dynamicLightSources.iterator();
|
||||
IDynamicLightSource it;
|
||||
boolean changed = false;
|
||||
while (dynamicLightSources.hasNext()) {
|
||||
it = dynamicLightSources.next();
|
||||
if (filter.test(it)) {
|
||||
dynamicLightSources.remove();
|
||||
this.lightSourceCount = this.dynamicLightSources.size();
|
||||
changed = true;
|
||||
if (activeRenderer != null) {
|
||||
if (it.angelica$getLuminance() > 0)
|
||||
it.angelica$resetDynamicLight();
|
||||
@@ -201,6 +204,10 @@ public class DynamicLights {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (changed) {
|
||||
this.lightSourceCount = this.dynamicLightSources.size();
|
||||
rebuildLightSourceArray();
|
||||
}
|
||||
|
||||
this.lightSourcesLock.writeLock().unlock();
|
||||
}
|
||||
@@ -211,7 +218,7 @@ public class DynamicLights {
|
||||
public void clearLightSources() {
|
||||
this.lightSourcesLock.writeLock().lock();
|
||||
|
||||
var dynamicLightSources = this.dynamicLightSources.iterator();
|
||||
final var dynamicLightSources = this.dynamicLightSources.iterator();
|
||||
IDynamicLightSource it;
|
||||
while (dynamicLightSources.hasNext()) {
|
||||
it = dynamicLightSources.next();
|
||||
@@ -223,6 +230,7 @@ public class DynamicLights {
|
||||
}
|
||||
}
|
||||
this.lightSourceCount = 0;
|
||||
this.lightSourceArray = new IDynamicLightSource[0];
|
||||
|
||||
this.lightSourcesLock.writeLock().unlock();
|
||||
}
|
||||
@@ -234,7 +242,7 @@ public class DynamicLights {
|
||||
* @return {@code true} if the light source is tracked, else {@code false}
|
||||
*/
|
||||
public boolean containsLightSource(@NotNull IDynamicLightSource lightSource) {
|
||||
boolean result;
|
||||
final boolean result;
|
||||
this.lightSourcesLock.readLock().lock();
|
||||
result = this.dynamicLightSources.contains(lightSource);
|
||||
this.lightSourcesLock.readLock().unlock();
|
||||
@@ -247,7 +255,7 @@ public class DynamicLights {
|
||||
* @return the number of dynamic light sources emitting light
|
||||
*/
|
||||
public int getLightSourcesCount() {
|
||||
int result;
|
||||
final int result;
|
||||
|
||||
this.lightSourcesLock.readLock().lock();
|
||||
result = this.dynamicLightSources.size();
|
||||
@@ -259,7 +267,7 @@ public class DynamicLights {
|
||||
public double getDynamicLightLevel(int x, int y, int z) {
|
||||
double result = 0;
|
||||
this.lightSourcesLock.readLock().lock();
|
||||
for (var lightSource : this.dynamicLightSources) {
|
||||
for (var lightSource : this.lightSourceArray) {
|
||||
result = maxDynamicLightLevel(x, y, z, lightSource, result);
|
||||
}
|
||||
this.lightSourcesLock.readLock().unlock();
|
||||
@@ -273,7 +281,7 @@ public class DynamicLights {
|
||||
public double getDynamicLightLevel(double x, double y, double z) {
|
||||
double result = 0;
|
||||
this.lightSourcesLock.readLock().lock();
|
||||
for (var lightSource : this.dynamicLightSources) {
|
||||
for (var lightSource : this.lightSourceArray) {
|
||||
result = maxDynamicLightLevelExact(x, y, z, lightSource, result);
|
||||
}
|
||||
this.lightSourcesLock.readLock().unlock();
|
||||
@@ -286,19 +294,19 @@ public class DynamicLights {
|
||||
}
|
||||
|
||||
public static double maxDynamicLightLevel(int x, int y, int z, @NotNull IDynamicLightSource lightSource, double currentLightLevel) {
|
||||
int luminance = lightSource.angelica$getLuminance();
|
||||
final int luminance = lightSource.angelica$getLuminance();
|
||||
if (luminance > 0) {
|
||||
// Can't use Entity#squaredDistanceTo because of eye Y coordinate.
|
||||
double dx = x - lightSource.angelica$getDynamicLightX() + 0.5;
|
||||
double dy = y - lightSource.angelica$getDynamicLightY() + 0.5;
|
||||
double dz = z - lightSource.angelica$getDynamicLightZ() + 0.5;
|
||||
final double dx = x - lightSource.angelica$getDynamicLightX() + 0.5;
|
||||
final double dy = y - lightSource.angelica$getDynamicLightY() + 0.5;
|
||||
final double dz = z - lightSource.angelica$getDynamicLightZ() + 0.5;
|
||||
|
||||
double distanceSquared = dx * dx + dy * dy + dz * dz;
|
||||
final double distanceSquared = dx * dx + dy * dy + dz * dz;
|
||||
// 7.75 because else we would have to update more chunks and that's not a good idea.
|
||||
// 15 (max range for blocks) would be too much and a bit cheaty.
|
||||
if (distanceSquared <= MAX_RADIUS_SQUARED) {
|
||||
double multiplier = 1.0 - Math.sqrt(distanceSquared) / MAX_RADIUS;
|
||||
double lightLevel = multiplier * (double) luminance;
|
||||
final double multiplier = 1.0 - Math.sqrt(distanceSquared) / MAX_RADIUS;
|
||||
final double lightLevel = multiplier * (double) luminance;
|
||||
if (lightLevel > currentLightLevel) {
|
||||
return lightLevel;
|
||||
}
|
||||
@@ -312,16 +320,16 @@ public class DynamicLights {
|
||||
* Used for smooth per-vertex lighting.
|
||||
*/
|
||||
public static double maxDynamicLightLevelExact(double x, double y, double z, @NotNull IDynamicLightSource lightSource, double currentLightLevel) {
|
||||
int luminance = lightSource.angelica$getLuminance();
|
||||
final int luminance = lightSource.angelica$getLuminance();
|
||||
if (luminance > 0) {
|
||||
double dx = x - lightSource.angelica$getDynamicLightX();
|
||||
double dy = y - lightSource.angelica$getDynamicLightY();
|
||||
double dz = z - lightSource.angelica$getDynamicLightZ();
|
||||
final double dx = x - lightSource.angelica$getDynamicLightX();
|
||||
final double dy = y - lightSource.angelica$getDynamicLightY();
|
||||
final double dz = z - lightSource.angelica$getDynamicLightZ();
|
||||
|
||||
double distanceSquared = dx * dx + dy * dy + dz * dz;
|
||||
final double distanceSquared = dx * dx + dy * dy + dz * dz;
|
||||
if (distanceSquared <= MAX_RADIUS_SQUARED) {
|
||||
double multiplier = 1.0 - Math.sqrt(distanceSquared) / MAX_RADIUS;
|
||||
double lightLevel = multiplier * (double) luminance;
|
||||
final double multiplier = 1.0 - Math.sqrt(distanceSquared) / MAX_RADIUS;
|
||||
final double lightLevel = multiplier * (double) luminance;
|
||||
if (lightLevel > currentLightLevel) {
|
||||
return lightLevel;
|
||||
}
|
||||
@@ -360,11 +368,11 @@ public class DynamicLights {
|
||||
|
||||
this.lightSourcesLock.readLock().lock();
|
||||
try {
|
||||
for (IDynamicLightSource source : this.dynamicLightSources) {
|
||||
double dx = source.angelica$getDynamicLightX() - centerX;
|
||||
double dy = source.angelica$getDynamicLightY() - centerY;
|
||||
double dz = source.angelica$getDynamicLightZ() - centerZ;
|
||||
double distSq = dx * dx + dy * dy + dz * dz;
|
||||
for (var source : this.lightSourceArray) {
|
||||
final double dx = source.angelica$getDynamicLightX() - centerX;
|
||||
final double dy = source.angelica$getDynamicLightY() - centerY;
|
||||
final double dz = source.angelica$getDynamicLightZ() - centerZ;
|
||||
final double distSq = dx * dx + dy * dy + dz * dz;
|
||||
|
||||
if (distSq <= searchRadiusSq) {
|
||||
if (result == null) {
|
||||
@@ -380,6 +388,53 @@ public class DynamicLights {
|
||||
return result != null ? result : Collections.emptyList();
|
||||
}
|
||||
|
||||
public int getDynamicLightRGB(double x, double y, double z) {
|
||||
int accum = 0;
|
||||
this.lightSourcesLock.readLock().lock();
|
||||
try {
|
||||
for (var lightSource : this.lightSourceArray) {
|
||||
accum = accumulateSourceRGB(x, y, z, lightSource, accum);
|
||||
}
|
||||
} finally {
|
||||
this.lightSourcesLock.readLock().unlock();
|
||||
}
|
||||
return accum;
|
||||
}
|
||||
|
||||
public int getDynamicLightRGBFromSources(double x, double y, double z, List<IDynamicLightSource> sources) {
|
||||
if (sources == null || sources.isEmpty()) return 0;
|
||||
int accum = 0;
|
||||
for (int i = 0, size = sources.size(); i < size; i++) {
|
||||
accum = accumulateSourceRGB(x, y, z, sources.get(i), accum);
|
||||
}
|
||||
return accum;
|
||||
}
|
||||
|
||||
private static int accumulateSourceRGB(double x, double y, double z, IDynamicLightSource source, int accum) {
|
||||
final int luminance = source.angelica$getLuminance();
|
||||
if (luminance <= 0) return accum;
|
||||
|
||||
final int rgb = source.angelica$getLuminanceRGB();
|
||||
if (rgb == 0) return accum;
|
||||
|
||||
final double dx = x - source.angelica$getDynamicLightX();
|
||||
final double dy = y - source.angelica$getDynamicLightY();
|
||||
final double dz = z - source.angelica$getDynamicLightZ();
|
||||
final double distSq = dx * dx + dy * dy + dz * dz;
|
||||
|
||||
if (distSq > MAX_RADIUS_SQUARED) return accum;
|
||||
|
||||
final double multiplier = 1.0 - Math.sqrt(distSq) / MAX_RADIUS;
|
||||
final int r = (int) (BlockLightProvider.unpackR(rgb) * multiplier);
|
||||
final int g = (int) (BlockLightProvider.unpackG(rgb) * multiplier);
|
||||
final int b = (int) (BlockLightProvider.unpackB(rgb) * multiplier);
|
||||
|
||||
return BlockLightProvider.packRGB(
|
||||
Math.max(BlockLightProvider.unpackR(accum), r),
|
||||
Math.max(BlockLightProvider.unpackG(accum), g),
|
||||
Math.max(BlockLightProvider.unpackB(accum), b));
|
||||
}
|
||||
|
||||
public double getDynamicLightLevelFromSources(double x, double y, double z, List<IDynamicLightSource> sources) {
|
||||
if (sources == null || sources.isEmpty()) {
|
||||
return 0;
|
||||
@@ -403,10 +458,10 @@ public class DynamicLights {
|
||||
// lightmap is (skyLevel << 20 | blockLevel << 4)
|
||||
|
||||
// Get vanilla block light level.
|
||||
int blockLevel = (lightmap & 0xFFFF) >> 4;
|
||||
final int blockLevel = (lightmap & 0xFFFF) >> 4;
|
||||
if (dynamicLightLevel > blockLevel) {
|
||||
// Equivalent to a << 4 bitshift with a little quirk: this one ensure more precision (more decimals are saved).
|
||||
int luminance = (int) (dynamicLightLevel * 16.0);
|
||||
final int luminance = (int) (dynamicLightLevel * 16.0);
|
||||
lightmap &= 0xfff00000;
|
||||
lightmap |= luminance & 0x000fffff;
|
||||
}
|
||||
@@ -485,8 +540,8 @@ public class DynamicLights {
|
||||
* @param lightSource the light source
|
||||
*/
|
||||
public static void updateTracking(@NotNull IDynamicLightSource lightSource) {
|
||||
boolean enabled = lightSource.angelica$isDynamicLightEnabled();
|
||||
int luminance = lightSource.angelica$getLuminance();
|
||||
final boolean enabled = lightSource.angelica$isDynamicLightEnabled();
|
||||
final int luminance = lightSource.angelica$getLuminance();
|
||||
|
||||
if (!enabled && luminance > 0) {
|
||||
lightSource.angelica$setDynamicLightEnabled(true);
|
||||
@@ -503,9 +558,9 @@ public class DynamicLights {
|
||||
* @return the luminance of the item
|
||||
*/
|
||||
public static int getLuminanceFromItemStack(@NotNull ItemStack stack) {
|
||||
Item item = stack.getItem();
|
||||
final Item item = stack.getItem();
|
||||
if (item instanceof ItemBlock itemBlock) {
|
||||
Block block = itemBlock.field_150939_a;
|
||||
final Block block = itemBlock.field_150939_a;
|
||||
if (block != null) {
|
||||
return block.getLightValue();
|
||||
}
|
||||
@@ -522,7 +577,7 @@ public class DynamicLights {
|
||||
|
||||
if (entity.isBurning()) return 15;
|
||||
|
||||
boolean inWater = entity.isInsideOfMaterial(Material.water);
|
||||
final boolean inWater = entity.isInsideOfMaterial(Material.water);
|
||||
|
||||
// TODO only have certain items not glow in water?
|
||||
if (inWater) return 0;
|
||||
@@ -547,23 +602,23 @@ public class DynamicLights {
|
||||
player instanceof IBattlePlayer battlePlayer &&
|
||||
battlePlayer.battlegear2$isBattlemode()
|
||||
) {
|
||||
ItemStack offhand = Battlegear2Compat.getBattlegear2Offhand(player);
|
||||
final ItemStack offhand = Battlegear2Compat.getBattlegear2Offhand(player);
|
||||
if (offhand != null) {
|
||||
luminance = Math.max(luminance, getLuminanceFromItemStack(offhand));
|
||||
}
|
||||
}
|
||||
else if (ModStatus.isBackhandLoaded){
|
||||
ItemStack offhand = BackhandReflectionCompat.getOffhandItem(player);
|
||||
final ItemStack offhand = BackhandReflectionCompat.getOffhandItem(player);
|
||||
if (offhand != null) {
|
||||
luminance = Math.max(luminance, getLuminanceFromItemStack(offhand));
|
||||
}
|
||||
}
|
||||
|
||||
if (ModStatus.isBaublesLoaded){
|
||||
var playerBaubles = PlayerHandler.getPlayerBaubles(player);
|
||||
final var playerBaubles = PlayerHandler.getPlayerBaubles(player);
|
||||
if (playerBaubles != null){
|
||||
for (int i = 0; i < playerBaubles.getSizeInventory(); i++){
|
||||
var stack = playerBaubles.getStackInSlot(i);
|
||||
final var stack = playerBaubles.getStackInSlot(i);
|
||||
if (stack != null){
|
||||
luminance = Math.max(luminance, getLuminanceFromItemStack(stack));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.gtnewhorizons.angelica.dynamiclights;
|
||||
|
||||
import com.gtnewhorizons.angelica.api.BlockLightProvider;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -78,4 +79,13 @@ public interface IDynamicLightSource {
|
||||
boolean angelica$updateDynamicLight(@NotNull IDynamicLightWorldRenderer renderer);
|
||||
|
||||
void angelica$scheduleTrackedChunksRebuild(@NotNull IDynamicLightWorldRenderer renderer);
|
||||
|
||||
/**
|
||||
* Returns the RGB luminance of the light source. Each channel 0-15, packed as {@code (r << 8) | (g << 4) | b}.
|
||||
* Default implementation returns white light at the scalar luminance level.
|
||||
*/
|
||||
default int angelica$getLuminanceRGB() {
|
||||
final int l = angelica$getLuminance();
|
||||
return BlockLightProvider.packRGB(l, l, l);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -14,6 +14,7 @@ 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 {
|
||||
|
||||
@@ -114,10 +115,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();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -135,12 +135,23 @@ public class AngelicaTweaker implements IFMLLoadingPlugin, IEarlyMixinLoader {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Publish a transformer-narrowing toggle to the blackboard; read by AngelicaLateTweaker.narrowEnabled(). */
|
||||
private static void narrowTransformerConfig(String mod, boolean enabled) {
|
||||
Launch.blackboard.put("angelica.narrow." + mod, enabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectData(Map<String, Object> data) {
|
||||
OBF_ENV = (Boolean) data.get("runtimeDeobfuscationEnabled");
|
||||
// Directly add this to the MixinServiceLaunchWrapper tweaker's list of Tweak Classes
|
||||
final List<String> tweaks = GlobalProperties.get(MixinServiceLaunchWrapper.BLACKBOARD_KEY_TWEAKCLASSES);
|
||||
if (tweaks != null) {
|
||||
// Bridge transformer compat config to blackboard for AngelicaLateTweaker
|
||||
narrowTransformerConfig("DragonAPI", AngelicaConfig.transformerCompat.narrowDragonAPI);
|
||||
narrowTransformerConfig("Xaeros", AngelicaConfig.transformerCompat.narrowXaeros);
|
||||
narrowTransformerConfig("AdvancedLightsabers", AngelicaConfig.transformerCompat.narrowAdvancedLightsabers);
|
||||
narrowTransformerConfig("Alfheim", AngelicaConfig.transformerCompat.narrowAlfheim);
|
||||
|
||||
tweaks.add("com.gtnewhorizons.angelica.loading.fml.tweakers.IncompatibleModsDisablerTweaker");
|
||||
if (AngelicaConfig.enableHudCaching) {
|
||||
tweaks.add("com.gtnewhorizons.angelica.loading.fml.tweakers.XaerosTransformerDisablerTweaker");
|
||||
|
||||
+47
-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,60 @@ public class AngelicaLateTweaker implements ITweaker {
|
||||
exceptions.add("Reika.DragonAPI.ASM.InterfaceInjector");
|
||||
exceptions.add("Reika.DragonAPI.ASM.SpecialBiomePlacement");
|
||||
exceptions.add("Reika.DragonAPI.ASM.StructureLootHooks");
|
||||
FMLRelaunchLog.info("[Angelica] Narrowed Reika.DragonAPI.ASM transformer exclusion to allow GL redirection of utility classes");
|
||||
FMLRelaunchLog.info("[Angelica] Narrowed Reika.DragonAPI.ASM transformer exclusion to allow GL redirection");
|
||||
}
|
||||
|
||||
if (exceptions.remove("xaero.common.core")) {
|
||||
exceptions.add("xaero.common.core.transformer");
|
||||
FMLRelaunchLog.info("[Angelica] Narrowed xaero.common.core transformer exclusion to allow GL redirection");
|
||||
if (narrowEnabled("Xaeros")) {
|
||||
if (exceptions.remove("xaero.common.core")) {
|
||||
exceptions.add("xaero.common.core.transformer");
|
||||
FMLRelaunchLog.info("[Angelica] Narrowed xaero.common.core transformer exclusion to allow GL redirection");
|
||||
}
|
||||
if (exceptions.remove("xaero.map.core")) {
|
||||
exceptions.add("xaero.map.core.transformer");
|
||||
FMLRelaunchLog.info("[Angelica] Narrowed xaero.map.core transformer exclusion to allow GL redirection");
|
||||
}
|
||||
}
|
||||
if (exceptions.remove("xaero.map.core")) {
|
||||
exceptions.add("xaero.map.core.transformer");
|
||||
FMLRelaunchLog.info("[Angelica] Narrowed xaero.map.core transformer exclusion to allow GL redirection");
|
||||
|
||||
if (narrowEnabled("AdvancedLightsabers") && exceptions.remove("com.fiskmods.lightsabers.asm")) {
|
||||
exceptions.add("com.fiskmods.lightsabers.asm.ALLoadingPlugin");
|
||||
exceptions.add("com.fiskmods.lightsabers.asm.ASMHooks");
|
||||
exceptions.add("com.fiskmods.lightsabers.asm.transformers");
|
||||
FMLRelaunchLog.info("[Angelica] Narrowed com.fiskmods.lightsabers.asm transformer exclusion to allow GL redirection");
|
||||
}
|
||||
|
||||
if (narrowEnabled("Alfheim") && exceptions.remove("alfheim.common.core.asm.hook")) {
|
||||
exceptions.add("alfheim.common.core.asm.hook.AlfheimFieldHookHandler");
|
||||
exceptions.add("alfheim.common.core.asm.hook.AlfheimHPHooks");
|
||||
exceptions.add("alfheim.common.core.asm.hook.Botania18AndUpBackport");
|
||||
exceptions.add("alfheim.common.core.asm.hook.ElementalDamageAdapter");
|
||||
|
||||
exceptions.add("alfheim.common.core.asm.hook.integration");
|
||||
|
||||
exceptions.add("alfheim.common.core.asm.hook.extender.FurnaceExtender");
|
||||
exceptions.add("alfheim.common.core.asm.hook.extender.ItemAuraRingExtender");
|
||||
exceptions.add("alfheim.common.core.asm.hook.extender.ItemLensExtender");
|
||||
exceptions.add("alfheim.common.core.asm.hook.extender.ItemTwigWandExtender");
|
||||
exceptions.add("alfheim.common.core.asm.hook.extender.LightRelayExtender");
|
||||
exceptions.add("alfheim.common.core.asm.hook.extender.PureDaisyExtender");
|
||||
exceptions.add("alfheim.common.core.asm.hook.extender.QuartzExtender");
|
||||
exceptions.add("alfheim.common.core.asm.hook.extender.RelicHooks");
|
||||
exceptions.add("alfheim.common.core.asm.hook.extender.SparkExtender");
|
||||
|
||||
exceptions.add("alfheim.common.core.asm.hook.fixes.BotaniaGlowingRenderFixes");
|
||||
exceptions.add("alfheim.common.core.asm.hook.fixes.CorporeaInputFix");
|
||||
exceptions.add("alfheim.common.core.asm.hook.fixes.GodAttributesHooks");
|
||||
exceptions.add("alfheim.common.core.asm.hook.fixes.RecipeAncientWillsFix");
|
||||
FMLRelaunchLog.info("[Angelica] Narrowed alfheim.common.core.asm.hook transformer exclusion to allow GL redirection");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FMLRelaunchLog.warning("[Angelica] Failed to narrow transformer exclusions: %s", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean narrowEnabled(String mod) {
|
||||
return !Boolean.FALSE.equals(Launch.blackboard.get("angelica.narrow." + mod));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLaunchTarget() {
|
||||
return null;
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.gtnewhorizons.angelica.mixins;
|
||||
import com.gtnewhorizon.gtnhmixins.builders.IMixins;
|
||||
import com.gtnewhorizon.gtnhmixins.builders.MixinBuilder;
|
||||
import com.gtnewhorizons.angelica.AngelicaMod;
|
||||
import com.gtnewhorizons.angelica.api.BlockLightProvider;
|
||||
import com.gtnewhorizons.angelica.config.AngelicaConfig;
|
||||
import com.gtnewhorizons.angelica.config.CompatConfig;
|
||||
import jss.notfine.config.MCPatcherForgeConfig;
|
||||
@@ -35,6 +36,7 @@ public enum Mixins implements IMixins {
|
||||
, "angelica.MixinMinecraft"
|
||||
, "angelica.MixinMinecraft_FrameHook"
|
||||
, "angelica.MixinMinecraftServer"
|
||||
, "angelica.bugfixes.MixinItemRenderer_EdgeDepth"
|
||||
, "angelica.bugfixes.MixinRenderGlobal_DestroyBlock"
|
||||
, "angelica.bugfixes.MixinRendererLivingEntity_EyeDepth"
|
||||
, "angelica.debug.MixinMinecraft_FPSCap"
|
||||
@@ -214,6 +216,22 @@ public enum Mixins implements IMixins {
|
||||
)
|
||||
),
|
||||
|
||||
CELERITAS_COLORED_LIGHT(new MixinBuilder("Colored light infrastructure for celeritas light pipeline")
|
||||
.setPhase(Phase.EARLY)
|
||||
.setApplyIf(() -> {
|
||||
BlockLightProvider.freezeMixinConfig();
|
||||
return AngelicaConfig.enableCeleritas && BlockLightProvider.coloredLightEnabled();
|
||||
})
|
||||
.addClientMixins(
|
||||
"celeritas.light.MixinQuadLightData",
|
||||
"celeritas.light.MixinLightDataAccess",
|
||||
"celeritas.light.MixinLightDataCache",
|
||||
"celeritas.light.MixinAoFaceData",
|
||||
"celeritas.light.MixinSmoothLightPipeline",
|
||||
"celeritas.light.MixinFlatLightPipeline"
|
||||
)
|
||||
),
|
||||
|
||||
IRIS_SHADERS(new MixinBuilder()
|
||||
.setPhase(Phase.EARLY)
|
||||
.setApplyIf(() -> AngelicaConfig.enableIris)
|
||||
@@ -698,7 +716,7 @@ public enum Mixins implements IMixins {
|
||||
private final MixinBuilder builder;
|
||||
|
||||
private static String[] addPrefix(String prefix, String... values) {
|
||||
List<String> list = new ArrayList<>(values.length);
|
||||
final List<String> list = new ArrayList<>(values.length);
|
||||
for (String s : values) {
|
||||
list.add(prefix + s);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import com.gtnewhorizons.angelica.debug.TPSGraph;
|
||||
import com.gtnewhorizons.angelica.dynamiclights.DynamicLights;
|
||||
import com.gtnewhorizons.angelica.dynamiclights.config.EntityLightConfig;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.client.debug.OpenGLDebugging;
|
||||
import com.gtnewhorizons.angelica.hudcaching.HUDCaching;
|
||||
import com.gtnewhorizons.angelica.iris.IrisGLSMBridge;
|
||||
import com.gtnewhorizons.angelica.loading.AngelicaTweaker;
|
||||
@@ -27,7 +26,6 @@ import com.gtnewhorizons.angelica.rendering.celeritas.threading.ChunkTaskRegistr
|
||||
import com.gtnewhorizons.angelica.rendering.celeritas.threading.DefaultChunkTaskProvider;
|
||||
import com.gtnewhorizons.angelica.rendering.celeritas.threading.ThreadedChunkTaskProvider;
|
||||
import com.gtnewhorizons.angelica.zoom.Zoom;
|
||||
import cpw.mods.fml.client.registry.ClientRegistry;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.event.FMLInitializationEvent;
|
||||
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
|
||||
@@ -46,12 +44,13 @@ 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;
|
||||
@@ -111,8 +110,6 @@ public class ClientProxy extends CommonProxy {
|
||||
}
|
||||
}
|
||||
|
||||
private static KeyBinding glsmKeyBinding;
|
||||
|
||||
@Override
|
||||
public void init(FMLInitializationEvent event) {
|
||||
super.init(event);
|
||||
@@ -141,8 +138,6 @@ public class ClientProxy extends CommonProxy {
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
|
||||
glsmKeyBinding = new KeyBinding("Print GLSM Debug", Keyboard.KEY_NONE, "Angelica");
|
||||
ClientRegistry.registerKeyBinding(glsmKeyBinding);
|
||||
|
||||
if (ModStatus.isBetterCrashesLoaded) {
|
||||
BetterCrashesCompat.init();
|
||||
@@ -160,16 +155,6 @@ public class ClientProxy extends CommonProxy {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean wasGLSMKeyPressed;
|
||||
|
||||
@SubscribeEvent
|
||||
public void onKeypress(TickEvent.ClientTickEvent event) {
|
||||
final boolean isPressed = glsmKeyBinding.getKeyCode() != 0 && GameSettings.isKeyDown(glsmKeyBinding);
|
||||
if (isPressed && !wasGLSMKeyPressed) {
|
||||
OpenGLDebugging.checkGLSM();
|
||||
}
|
||||
wasGLSMKeyPressed = isPressed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postInit(FMLPostInitializationEvent event) {
|
||||
@@ -177,7 +162,7 @@ public class ClientProxy extends CommonProxy {
|
||||
|
||||
if (ModStatus.isLotrLoaded && AngelicaConfig.enableCeleritas && CompatConfig.fixLotr) {
|
||||
try {
|
||||
Class<?> lotrRendering = Class.forName("lotr.common.coremod.LOTRReplacedMethods$BlockRendering");
|
||||
final Class<?> lotrRendering = Class.forName("lotr.common.coremod.LOTRReplacedMethods$BlockRendering");
|
||||
ReflectionHelper.setPrivateValue(lotrRendering, null, new ConcurrentHashMap<>(), "naturalBlockClassTable");
|
||||
ReflectionHelper.setPrivateValue(lotrRendering, null, new ConcurrentHashMap<>(), "naturalBlockTable");
|
||||
ReflectionHelper.setPrivateValue(lotrRendering, null, new ConcurrentHashMap<>(), "cachedNaturalBlocks");
|
||||
@@ -192,9 +177,9 @@ public class ClientProxy extends CommonProxy {
|
||||
@SubscribeEvent
|
||||
public void onTick(TickEvent.ServerTickEvent event) {
|
||||
if (FMLCommonHandler.instance().getSide().isClient() && event.phase == TickEvent.Phase.END) {
|
||||
IntegratedServer srv = Minecraft.getMinecraft().getIntegratedServer();
|
||||
final IntegratedServer srv = Minecraft.getMinecraft().getIntegratedServer();
|
||||
if (srv != null) {
|
||||
long currentTickTime = srv.tickTimeArray[srv.getTickCounter() % 100];
|
||||
final long currentTickTime = srv.tickTimeArray[srv.getTickCounter() % 100];
|
||||
lastIntegratedTickTime = lastIntegratedTickTime * 0.8F + (float) currentTickTime / 1000000.0F * 0.2F;
|
||||
} else lastIntegratedTickTime = 0;
|
||||
}
|
||||
@@ -211,30 +196,30 @@ public class ClientProxy extends CommonProxy {
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.LOWEST)
|
||||
public void onRenderOverlay(RenderGameOverlayEvent.Text event) {
|
||||
Minecraft mc = Minecraft.getMinecraft();
|
||||
if (!mc.gameSettings.showDebugInfo || event.left.isEmpty()) return;
|
||||
final Minecraft mc = Minecraft.getMinecraft();
|
||||
if (event.isCanceled() || !mc.gameSettings.showDebugInfo || event.left.isEmpty()) return;
|
||||
|
||||
NetHandlerPlayClient cl = mc.getNetHandler();
|
||||
final NetHandlerPlayClient cl = mc.getNetHandler();
|
||||
if (cl != null) {
|
||||
IntegratedServer srv = mc.getIntegratedServer();
|
||||
final IntegratedServer srv = mc.getIntegratedServer();
|
||||
|
||||
if (srv != null) {
|
||||
String s = String.format("Integrated server @ %.0f ms ticks", lastIntegratedTickTime);
|
||||
final String s = String.format("Integrated server @ %.0f ms ticks", lastIntegratedTickTime);
|
||||
event.left.add(Math.min(event.left.size(), 1), s);
|
||||
}
|
||||
}
|
||||
|
||||
if (AngelicaConfig.showBlockDebugInfo && mc.objectMouseOver != null && mc.objectMouseOver.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK) {
|
||||
if (!event.right.isEmpty() && !Objects.firstNonNull(event.right.get(event.right.size() - 1), "").isEmpty()) event.right.add("");
|
||||
Block block = mc.theWorld.getBlock(mc.objectMouseOver.blockX, mc.objectMouseOver.blockY, mc.objectMouseOver.blockZ);
|
||||
int meta = mc.theWorld.getBlockMetadata(mc.objectMouseOver.blockX, mc.objectMouseOver.blockY, mc.objectMouseOver.blockZ);
|
||||
final Block block = mc.theWorld.getBlock(mc.objectMouseOver.blockX, mc.objectMouseOver.blockY, mc.objectMouseOver.blockZ);
|
||||
final int meta = mc.theWorld.getBlockMetadata(mc.objectMouseOver.blockX, mc.objectMouseOver.blockY, mc.objectMouseOver.blockZ);
|
||||
event.right.add(Block.blockRegistry.getNameForObject(block));
|
||||
event.right.add("meta: " + meta);
|
||||
}
|
||||
|
||||
if (DynamicLights.isEnabled()) {
|
||||
var builder = new StringBuilder("Dynamic Light Sources: ");
|
||||
DynamicLights dl = DynamicLights.get();
|
||||
final var builder = new StringBuilder("Dynamic Light Sources: ");
|
||||
final DynamicLights dl = DynamicLights.get();
|
||||
builder.append(dl.getLightSourcesCount()).append(" (U: ").append(dl.getLastUpdateCount()).append(')');
|
||||
|
||||
event.right.add(builder.toString());
|
||||
@@ -248,8 +233,8 @@ public class ClientProxy extends CommonProxy {
|
||||
.startsWith("y:") && Objects.firstNonNull(event.left.get(i + 2), "").startsWith("z:") && Objects.firstNonNull(event.left.get(i + 3), "")
|
||||
.startsWith("f:")) {
|
||||
hasReplacedXYZ = true;
|
||||
int heading = MathHelper.floor_double((double) (mc.thePlayer.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3;
|
||||
String heading_str = switch (heading) {
|
||||
final int heading = MathHelper.floor_double((double) (mc.thePlayer.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3;
|
||||
final String heading_str = switch (heading) {
|
||||
case 0 -> "Towards positive Z";
|
||||
case 1 -> "Towards negative X";
|
||||
case 2 -> "Towards negative Z";
|
||||
@@ -257,9 +242,9 @@ public class ClientProxy extends CommonProxy {
|
||||
default -> throw new RuntimeException();
|
||||
};
|
||||
event.left.set(i, String.format("XYZ: %.3f / %.5f / %.3f", mc.thePlayer.posX, mc.thePlayer.boundingBox.minY, mc.thePlayer.posZ));
|
||||
int bX = MathHelper.floor_double(mc.thePlayer.posX);
|
||||
int bY = MathHelper.floor_double(mc.thePlayer.boundingBox.minY);
|
||||
int bZ = MathHelper.floor_double(mc.thePlayer.posZ);
|
||||
final int bX = MathHelper.floor_double(mc.thePlayer.posX);
|
||||
final int bY = MathHelper.floor_double(mc.thePlayer.boundingBox.minY);
|
||||
final int bZ = MathHelper.floor_double(mc.thePlayer.posZ);
|
||||
event.left.set(i + 1, String.format("Block: %d %d %d [%d %d %d]", bX, bY, bZ, bX & 15, bY & 15, bZ & 15));
|
||||
event.left.set(i + 2, String.format("Chunk: %d %d %d", bX >> 4, bY >> 4, bZ >> 4));
|
||||
event.left.set(
|
||||
@@ -270,15 +255,14 @@ public class ClientProxy extends CommonProxy {
|
||||
MathHelper.wrapAngleTo180_float(mc.thePlayer.rotationYaw),
|
||||
MathHelper.wrapAngleTo180_float(mc.thePlayer.rotationPitch)));
|
||||
|
||||
Chunk chunk = this.mc.theWorld.getChunkFromBlockCoords(bX, bZ);
|
||||
event.left.set(
|
||||
i + 4, String.format(
|
||||
"lc: %d b: %s bl: %d sl: %d rl: %d",
|
||||
chunk.getTopFilledSegment() + 15,
|
||||
chunk.getBiomeGenForWorldCoords(bX & 15, bZ & 15, mc.theWorld.getWorldChunkManager()).biomeName,
|
||||
chunk.getSavedLightValue(EnumSkyBlock.Block, bX & 15, MathHelper.clamp_int(bY, 0, 255), bZ & 15),
|
||||
chunk.getSavedLightValue(EnumSkyBlock.Sky, bX & 15, MathHelper.clamp_int(bY, 0, 255), bZ & 15),
|
||||
chunk.getBlockLightValue(bX & 15, MathHelper.clamp_int(bY, 0, 255), bZ & 15, 0)));
|
||||
final Chunk chunk = this.mc.theWorld.getChunkFromBlockCoords(bX, bZ);
|
||||
event.left.set(i + 4, String.format(
|
||||
"lc: %d b: %s bl: %d sl: %d rl: %d",
|
||||
chunk.getTopFilledSegment() + 15,
|
||||
chunk.getBiomeGenForWorldCoords(bX & 15, bZ & 15, mc.theWorld.getWorldChunkManager()).biomeName,
|
||||
chunk.getSavedLightValue(EnumSkyBlock.Block, bX & 15, MathHelper.clamp_int(bY, 0, 255), bZ & 15),
|
||||
chunk.getSavedLightValue(EnumSkyBlock.Sky, bX & 15, MathHelper.clamp_int(bY, 0, 255), bZ & 15),
|
||||
chunk.getBlockLightValue(bX & 15, MathHelper.clamp_int(bY, 0, 255), bZ & 15, 0)));
|
||||
}
|
||||
}
|
||||
// Draw a frametime graph
|
||||
|
||||
+58
-5
@@ -1,6 +1,9 @@
|
||||
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.rendering.StateAwareTessellator;
|
||||
@@ -17,8 +20,8 @@ import net.minecraft.client.multiplayer.WorldClient;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import org.embeddedt.embeddium.api.util.ColorABGR;
|
||||
import org.embeddedt.embeddium.impl.model.light.LightPipeline;
|
||||
import org.embeddedt.embeddium.impl.model.light.data.LightDataAccess;
|
||||
import org.embeddedt.embeddium.impl.model.light.data.QuadLightData;
|
||||
import org.embeddedt.embeddium.impl.model.light.flat.FlatLightPipeline;
|
||||
import org.embeddedt.embeddium.impl.model.light.smooth.SmoothLightPipeline;
|
||||
@@ -33,7 +36,6 @@ import org.embeddedt.embeddium.impl.render.chunk.terrain.material.Material;
|
||||
import org.embeddedt.embeddium.impl.render.chunk.vertex.format.ChunkVertexEncoder;
|
||||
import org.embeddedt.embeddium.impl.util.QuadUtil;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class AngelicaChunkBuildContext extends ChunkBuildContext {
|
||||
@@ -56,7 +58,8 @@ public class AngelicaChunkBuildContext extends ChunkBuildContext {
|
||||
private final VertexArrayQuadView quadView;
|
||||
private boolean lightPipelineReady = false;
|
||||
private int originX, originY, originZ;
|
||||
private IBlockAccess blockAccess;
|
||||
private float cachedSkylightSubtracted;
|
||||
private final boolean hasColoredLight;
|
||||
|
||||
public AngelicaChunkBuildContext(RenderPassConfiguration<?> renderPassConfiguration, WorldClient world) {
|
||||
super(renderPassConfiguration);
|
||||
@@ -65,6 +68,7 @@ public class AngelicaChunkBuildContext extends ChunkBuildContext {
|
||||
this.smoothLightPipeline = new SmoothLightPipeline(lightDataCache, VanillaDiffuseProvider.INSTANCE, false);
|
||||
this.flatLightPipeline = new FlatLightPipeline(lightDataCache, VanillaDiffuseProvider.INSTANCE, false);
|
||||
this.quadView = new VertexArrayQuadView(vertices);
|
||||
this.hasColoredLight = quadLightData instanceof ExtQuadLightData;
|
||||
}
|
||||
|
||||
public void setupLightPipeline(int minBlockX, int minBlockY, int minBlockZ) {
|
||||
@@ -72,7 +76,6 @@ public class AngelicaChunkBuildContext extends ChunkBuildContext {
|
||||
}
|
||||
|
||||
public void setupLightPipeline(IBlockAccess blockAccess, int minBlockX, int minBlockY, int minBlockZ) {
|
||||
this.blockAccess = blockAccess;
|
||||
this.originX = minBlockX;
|
||||
this.originY = minBlockY;
|
||||
this.originZ = minBlockZ;
|
||||
@@ -81,6 +84,7 @@ public class AngelicaChunkBuildContext extends ChunkBuildContext {
|
||||
smoothLightPipeline.reset();
|
||||
flatLightPipeline.reset();
|
||||
lightPipelineReady = true;
|
||||
cachedSkylightSubtracted = Minecraft.getMinecraft().theWorld.skylightSubtracted;
|
||||
}
|
||||
|
||||
public void setupDynamicLights(int chunkOriginX, int chunkOriginY, int chunkOriginZ) {
|
||||
@@ -219,10 +223,13 @@ public class AngelicaChunkBuildContext extends ChunkBuildContext {
|
||||
}
|
||||
}
|
||||
|
||||
// Apply RGB block light tint from provider
|
||||
applyBlockLightTint(worldX, worldY, worldZ, vertices);
|
||||
|
||||
final int faceBit = 1 << facing.ordinal();
|
||||
final Material correctMaterial;
|
||||
if ((facesAtBaseMaterial & faceBit) != 0) {
|
||||
// Face already has a non-demoted quad — skip selectMaterial entirely
|
||||
// Face already has a non-demoted quad, skip selectMaterial entirely
|
||||
correctMaterial = material;
|
||||
} else {
|
||||
correctMaterial = selectMaterial(material, sprite, isShaderPackOverride);
|
||||
@@ -239,4 +246,50 @@ public class AngelicaChunkBuildContext extends ChunkBuildContext {
|
||||
builder.getVertexBuffer(facing).push(vertices, correctMaterial);
|
||||
}
|
||||
}
|
||||
|
||||
private final float[] tintResult = new float[3];
|
||||
|
||||
private void applyBlockLightTint(int x, int y, int z, ChunkVertexEncoder.Vertex[] vertices) {
|
||||
if (!hasColoredLight) return;
|
||||
final ExtQuadLightData ext = (ExtQuadLightData) quadLightData;
|
||||
final boolean hasBlock = ext.angelica$isRGBValid();
|
||||
final boolean hasSky = ext.angelica$isSkyRGBValid();
|
||||
if (!hasBlock && !hasSky) return;
|
||||
if (hasBlock) ext.angelica$setRGBValid(false);
|
||||
if (hasSky) ext.angelica$setSkyRGBValid(false);
|
||||
|
||||
final float[] blockR = hasBlock ? ext.angelica$getR() : null;
|
||||
final float[] blockG = hasBlock ? ext.angelica$getG() : null;
|
||||
final float[] blockB = hasBlock ? ext.angelica$getB() : null;
|
||||
final float[] skyR = hasSky ? ext.angelica$getSkyR() : null;
|
||||
final float[] skyG = hasSky ? ext.angelica$getSkyG() : null;
|
||||
final float[] skyB = hasSky ? ext.angelica$getSkyB() : null;
|
||||
|
||||
final float sub = cachedSkylightSubtracted;
|
||||
final TintComputer tintComputer = TintRegistry.getCurrent();
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
final float br = hasBlock ? blockR[i] : 0;
|
||||
final float bg = hasBlock ? blockG[i] : 0;
|
||||
final float bb = hasBlock ? blockB[i] : 0;
|
||||
final float sr = hasSky ? Math.max(0, skyR[i] - sub) : 0;
|
||||
final float sg = hasSky ? Math.max(0, skyG[i] - sub) : 0;
|
||||
final float sb = hasSky ? Math.max(0, skyB[i] - sub) : 0;
|
||||
|
||||
// Fast-path: full white sky with no block light, no tint needed
|
||||
if (br == 0 && bg == 0 && bb == 0 && sr >= 15f && sg >= 15f && sb >= 15f) continue;
|
||||
|
||||
tintComputer.computeTint(br, bg, bb, sr, sg, sb, tintResult);
|
||||
final float rTint = tintResult[0];
|
||||
final float gTint = tintResult[1];
|
||||
final float bTint = tintResult[2];
|
||||
if (rTint >= 1.0f && gTint >= 1.0f && bTint >= 1.0f) continue;
|
||||
|
||||
final int color = vertices[i].color;
|
||||
final int vr = Math.min(255, (int) (ColorABGR.unpackRed(color) * rTint));
|
||||
final int vg = Math.min(255, (int) (ColorABGR.unpackGreen(color) * gTint));
|
||||
final int vb = Math.min(255, (int) (ColorABGR.unpackBlue(color) * bTint));
|
||||
vertices[i].color = ColorABGR.pack(vr, vg, vb, ColorABGR.unpackAlpha(color));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package com.gtnewhorizons.angelica.rendering.celeritas.compat;
|
||||
|
||||
import org.embeddedt.embeddium.impl.model.quad.properties.ModelQuadFacing;
|
||||
|
||||
/**
|
||||
* Inlined data from package-private {@code AoNeighborInfo} -- edge face directions,
|
||||
* bilinear corner weight formulas, and depth formulas per face direction.
|
||||
*/
|
||||
public final class AoHelper {
|
||||
|
||||
private static final ModelQuadFacing[][] FACES = {
|
||||
{ ModelQuadFacing.NEG_Y, ModelQuadFacing.POS_Y, ModelQuadFacing.NEG_Z, ModelQuadFacing.POS_Z }, // POS_X
|
||||
{ ModelQuadFacing.POS_X, ModelQuadFacing.NEG_X, ModelQuadFacing.NEG_Z, ModelQuadFacing.POS_Z }, // POS_Y
|
||||
{ ModelQuadFacing.NEG_X, ModelQuadFacing.POS_X, ModelQuadFacing.NEG_Y, ModelQuadFacing.POS_Y }, // POS_Z
|
||||
{ ModelQuadFacing.POS_Y, ModelQuadFacing.NEG_Y, ModelQuadFacing.NEG_Z, ModelQuadFacing.POS_Z }, // NEG_X
|
||||
{ ModelQuadFacing.NEG_X, ModelQuadFacing.POS_X, ModelQuadFacing.NEG_Z, ModelQuadFacing.POS_Z }, // NEG_Y
|
||||
{ ModelQuadFacing.POS_Y, ModelQuadFacing.NEG_Y, ModelQuadFacing.POS_X, ModelQuadFacing.NEG_X }, // NEG_Z
|
||||
};
|
||||
|
||||
/**
|
||||
* Corner remap table derived from each AoNeighborInfo.mapCorners.
|
||||
* remap[outIdx] = inIdx.
|
||||
*/
|
||||
public static final int[][] CORNER_REMAP = {
|
||||
{ 3, 0, 1, 2 }, // POS_X
|
||||
{ 2, 3, 0, 1 }, // POS_Y
|
||||
{ 0, 1, 2, 3 }, // POS_Z
|
||||
{ 1, 2, 3, 0 }, // NEG_X
|
||||
{ 0, 1, 2, 3 }, // NEG_Y
|
||||
{ 1, 2, 3, 0 }, // NEG_Z
|
||||
};
|
||||
|
||||
private AoHelper() {}
|
||||
|
||||
public static ModelQuadFacing[] getFaces(ModelQuadFacing direction) {
|
||||
return FACES[direction.ordinal()];
|
||||
}
|
||||
|
||||
public static void calculateCornerWeights(ModelQuadFacing direction, float x, float y, float z, float[] out) {
|
||||
final float u, v;
|
||||
switch (direction) {
|
||||
case POS_X -> {
|
||||
u = z;
|
||||
v = 1.0f - y;
|
||||
}
|
||||
case POS_Y -> {
|
||||
u = z;
|
||||
v = x;
|
||||
}
|
||||
case POS_Z -> {
|
||||
u = y;
|
||||
v = 1.0f - x;
|
||||
}
|
||||
case NEG_X -> {
|
||||
u = z;
|
||||
v = y;
|
||||
}
|
||||
case NEG_Y -> {
|
||||
u = z;
|
||||
v = 1.0f - x;
|
||||
}
|
||||
case NEG_Z -> {
|
||||
u = 1.0f - x;
|
||||
v = y;
|
||||
}
|
||||
default -> throw new IllegalArgumentException();
|
||||
}
|
||||
out[0] = v * u;
|
||||
out[1] = v * (1.0f - u);
|
||||
out[2] = (1.0f - v) * (1.0f - u);
|
||||
out[3] = (1.0f - v) * u;
|
||||
}
|
||||
|
||||
public static float getDepth(ModelQuadFacing direction, float x, float y, float z) {
|
||||
return switch (direction) {
|
||||
case POS_X -> 1.0f - x;
|
||||
case POS_Y -> 1.0f - y;
|
||||
case POS_Z -> 1.0f - z;
|
||||
case NEG_X -> x;
|
||||
case NEG_Y -> y;
|
||||
case NEG_Z -> z;
|
||||
default -> throw new IllegalArgumentException();
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.gtnewhorizons.angelica.rendering.celeritas.world;
|
||||
|
||||
import com.gtnewhorizons.angelica.api.SectionLightData;
|
||||
import com.gtnewhorizons.angelica.api.IBlockAccessExtended;
|
||||
import com.gtnewhorizons.angelica.compat.ModStatus;
|
||||
import com.gtnewhorizons.angelica.compat.mojang.ChunkSectionPos;
|
||||
@@ -84,11 +85,14 @@ public class WorldSlice implements IBlockAccessExtended, FLBlockAccess {
|
||||
// Local Section->Light table
|
||||
private final NibbleArray[][] lightArrays;
|
||||
|
||||
// Per-section RGB light data (captured from BlockLightProvider on main thread)
|
||||
private final SectionLightData[] sectionLightData;
|
||||
|
||||
// Local section copies
|
||||
private ClonedChunkSection[] sections;
|
||||
|
||||
// Biome data for each chunk section
|
||||
private BiomeGenBase[][] biomeData;
|
||||
private final BiomeGenBase[][] biomeData;
|
||||
|
||||
// The starting point from which this slice captures blocks
|
||||
private int baseX, baseY, baseZ;
|
||||
@@ -158,6 +162,7 @@ public class WorldSlice implements IBlockAccessExtended, FLBlockAccess {
|
||||
this.metadataArrays = new int[SECTION_TABLE_ARRAY_SIZE][];
|
||||
this.biomeData = new BiomeGenBase[SECTION_TABLE_ARRAY_SIZE][];
|
||||
this.lightArrays = new NibbleArray[SECTION_TABLE_ARRAY_SIZE][LIGHT_TYPES.length];
|
||||
this.sectionLightData = new SectionLightData[SECTION_TABLE_ARRAY_SIZE];
|
||||
|
||||
if (ModStatus.isFluidLoggedLoaded) {
|
||||
this.fluidArrays = new Fluid[SECTION_TABLE_ARRAY_SIZE][];
|
||||
@@ -220,6 +225,7 @@ public class WorldSlice implements IBlockAccessExtended, FLBlockAccess {
|
||||
|
||||
this.lightArrays[idx][EnumSkyBlock.Block.ordinal()] = section.getLightArray(EnumSkyBlock.Block);
|
||||
this.lightArrays[idx][EnumSkyBlock.Sky.ordinal()] = section.getLightArray(EnumSkyBlock.Sky);
|
||||
this.sectionLightData[idx] = section.getSectionLightData();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -380,6 +386,24 @@ public class WorldSlice implements IBlockAccessExtended, FLBlockAccess {
|
||||
return lightArray.get(relX & 15, relY & 15, relZ & 15);
|
||||
}
|
||||
|
||||
public SectionLightData getSectionLightData(int x, int y, int z) {
|
||||
if (!blockBoxContains(this.volume, x, y, z)) {
|
||||
return null;
|
||||
}
|
||||
final int relX = x - this.baseX;
|
||||
final int relY = y - this.baseY;
|
||||
final int relZ = z - this.baseZ;
|
||||
return this.sectionLightData[getLocalSectionIndex(relX >> 4, relY >> 4, relZ >> 4)];
|
||||
}
|
||||
|
||||
public List<IDynamicLightSource> getChunkLightSources() {
|
||||
return chunkLightSources;
|
||||
}
|
||||
|
||||
public DynamicLights getDynamicLightsInstance() {
|
||||
return dynamicLightsInstance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public World getWorld() {
|
||||
return this.world;
|
||||
|
||||
+9
@@ -1,6 +1,8 @@
|
||||
package com.gtnewhorizons.angelica.rendering.celeritas.world.cloned;
|
||||
|
||||
import com.falsepattern.endlessids.mixin.helpers.ChunkBiomeHook;
|
||||
import com.gtnewhorizons.angelica.api.BlockLightProvider;
|
||||
import com.gtnewhorizons.angelica.api.SectionLightData;
|
||||
import com.gtnewhorizons.angelica.compat.ExtendedBlockStorageExt;
|
||||
import com.gtnewhorizons.angelica.compat.ModStatus;
|
||||
import com.gtnewhorizons.angelica.compat.mojang.ChunkSectionPos;
|
||||
@@ -33,6 +35,7 @@ public class ClonedChunkSection {
|
||||
private ChunkSectionPos pos;
|
||||
private ExtendedBlockStorageExt data;
|
||||
private BiomeGenBase[] biomeData;
|
||||
private SectionLightData sectionLightData;
|
||||
private final Short2ObjectOpenHashMap<TileEntity> tileEntities;
|
||||
|
||||
private long lastUsedTimestamp = Long.MAX_VALUE;
|
||||
@@ -75,6 +78,8 @@ public class ClonedChunkSection {
|
||||
this.biomeData[(x & 15) | ((z & 15) << 4)] = world.getBiomeGenForCoords(x, z);
|
||||
}
|
||||
}
|
||||
|
||||
this.sectionLightData = BlockLightProvider.getInstance().prepareSectionData(chunk, pos.y);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -127,6 +132,10 @@ public class ClonedChunkSection {
|
||||
return data.getBlocklightArray();
|
||||
}
|
||||
|
||||
public SectionLightData getSectionLightData() {
|
||||
return this.sectionLightData;
|
||||
}
|
||||
|
||||
public BiomeGenBase[] getBiomeData() {
|
||||
return this.biomeData;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -100,6 +100,10 @@ public class SodiumGameOptions {
|
||||
|
||||
config.configPath = path;
|
||||
|
||||
if (config.advanced.streamingUploadStrategy == null) {
|
||||
config.advanced.streamingUploadStrategy = StreamingUploader.UploadStrategy.MAP_BUFFER_RANGE;
|
||||
}
|
||||
|
||||
// Clamp render-ahead to 0 if GL 3.2 fences aren't available
|
||||
if (GLStateManager.capabilities == null || !GLStateManager.capabilities.OpenGL32) {
|
||||
config.performance.cpuRenderAheadLimit = 0;
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.gtnewhorizons.angelica.AngelicaMod;
|
||||
import com.gtnewhorizons.angelica.Tags;
|
||||
import com.gtnewhorizons.angelica.config.AngelicaConfig;
|
||||
import cpw.mods.fml.client.registry.ClientRegistry;
|
||||
import cpw.mods.fml.common.Loader;
|
||||
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||
import cpw.mods.fml.common.gameevent.InputEvent;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||
@@ -17,6 +18,7 @@ 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.gl.shader.StandardMacros;
|
||||
import net.coderbot.iris.gui.screen.ShaderPackScreen;
|
||||
@@ -113,11 +115,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.
|
||||
@@ -350,6 +372,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 +418,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();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -721,6 +755,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."));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package net.coderbot.iris.gl.uniform;
|
||||
import net.coderbot.iris.gl.state.ValueUpdateNotifier;
|
||||
import org.joml.Vector2i;
|
||||
import org.joml.Vector3i;
|
||||
import org.joml.Vector3ic;
|
||||
import org.joml.Vector4f;
|
||||
import org.joml.Vector4i;
|
||||
|
||||
@@ -43,7 +44,7 @@ public interface DynamicLocationalUniformHolder extends LocationalUniformHolder,
|
||||
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;
|
||||
|
||||
@@ -3,6 +3,7 @@ package net.coderbot.iris.gl.uniform;
|
||||
import net.coderbot.iris.gl.state.ValueUpdateNotifier;
|
||||
import org.joml.Vector2i;
|
||||
import org.joml.Vector3i;
|
||||
import org.joml.Vector3ic;
|
||||
import org.joml.Vector4f;
|
||||
import org.joml.Vector4i;
|
||||
|
||||
@@ -16,7 +17,7 @@ public interface DynamicUniformHolder extends UniformHolder {
|
||||
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 uniform3i(String name, Supplier<Vector3ic> value, ValueUpdateNotifier notifier);
|
||||
DynamicUniformHolder uniform4f(String name, Supplier<Vector4f> value, ValueUpdateNotifier notifier);
|
||||
DynamicUniformHolder uniform4fArray(String name, Supplier<float[]> value, ValueUpdateNotifier notifier);
|
||||
DynamicUniformHolder uniform4i(String name, Supplier<Vector4i> value, ValueUpdateNotifier notifier);
|
||||
|
||||
@@ -2,11 +2,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.Vector3d;
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.Vector3fc;
|
||||
import org.joml.Vector3i;
|
||||
import org.joml.Vector3ic;
|
||||
import org.joml.Vector4f;
|
||||
|
||||
import java.util.OptionalInt;
|
||||
@@ -70,14 +73,14 @@ public interface LocationalUniformHolder extends UniformHolder {
|
||||
}
|
||||
|
||||
@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;
|
||||
@@ -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,12 +1,13 @@
|
||||
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.Vector3d;
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.Vector3fc;
|
||||
import org.joml.Vector3i;
|
||||
import org.joml.Vector3ic;
|
||||
import org.joml.Vector4f;
|
||||
|
||||
import java.util.function.BooleanSupplier;
|
||||
@@ -29,9 +30,9 @@ public interface UniformHolder {
|
||||
|
||||
UniformHolder uniform2i(UniformUpdateFrequency updateFrequency, String name, Supplier<Vector2i> 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);
|
||||
|
||||
@@ -43,7 +44,7 @@ public interface UniformHolder {
|
||||
|
||||
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.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.Vector3fc;
|
||||
import org.joml.Vector4f;
|
||||
|
||||
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();
|
||||
@@ -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());
|
||||
|
||||
@@ -8,6 +8,7 @@ import net.coderbot.iris.shaderpack.option.OptionSet;
|
||||
import net.coderbot.iris.shaderpack.option.Profile;
|
||||
import net.coderbot.iris.shaderpack.option.ProfileSet;
|
||||
import net.coderbot.iris.shaderpack.option.menu.OptionMenuProfileElement;
|
||||
import net.coderbot.iris.shaderpack.option.menu.ProfileElementTracker;
|
||||
import net.coderbot.iris.shaderpack.option.values.OptionValues;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
@@ -30,6 +31,7 @@ public class ProfileElementWidget extends BaseOptionElementWidget<OptionMenuProf
|
||||
public void init(ShaderPackScreen screen, NavigationController navigation) {
|
||||
super.init(screen, navigation);
|
||||
this.setLabel(PROFILE_LABEL);
|
||||
boolean secondProfileSet = ProfileElementTracker.isSecondProfileSet(this.element);
|
||||
|
||||
final ProfileSet profiles = this.element.profiles;
|
||||
final OptionSet options = this.element.options;
|
||||
@@ -41,7 +43,8 @@ public class ProfileElementWidget extends BaseOptionElementWidget<OptionMenuProf
|
||||
this.previous = result.previous;
|
||||
final Optional<String> profileName = result.current.map(p -> p.name);
|
||||
|
||||
this.profileLabel = profileName.map(name -> GuiUtil.translateOrDefault(name, "profile." + name)).orElse(PROFILE_CUSTOM);
|
||||
String translationKey = "profile" + (secondProfileSet ? "2." : ".") + profileName.orElse("custom");
|
||||
this.profileLabel = profileName.map(name -> GuiUtil.translateOrDefault(name, translationKey)).orElse(PROFILE_CUSTOM);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -63,7 +66,7 @@ public class ProfileElementWidget extends BaseOptionElementWidget<OptionMenuProf
|
||||
|
||||
@Override
|
||||
public String getCommentKey() {
|
||||
return "profile.comment";
|
||||
return ProfileElementTracker.isSecondProfileSet(this.element) ? "profile2.comment" : "profile.comment";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -29,12 +29,14 @@ 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;
|
||||
@@ -45,6 +47,7 @@ import net.coderbot.iris.postprocess.BufferFlipper;
|
||||
import net.coderbot.iris.postprocess.CenterDepthSampler;
|
||||
import net.coderbot.iris.postprocess.CompositeRenderer;
|
||||
import net.coderbot.iris.postprocess.FinalPassRenderer;
|
||||
import net.coderbot.iris.postprocess.FullScreenQuadRenderer;
|
||||
import net.coderbot.iris.postprocess.ProgramBuildContext;
|
||||
import net.coderbot.iris.rendertarget.IRenderTargetExt;
|
||||
import net.coderbot.iris.rendertarget.NativeImageBackedSingleColorTexture;
|
||||
@@ -176,6 +179,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,6 +195,7 @@ 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);
|
||||
@@ -205,7 +210,7 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R
|
||||
.map(DeferredWorldRenderingPipeline::submitCompositeTransform)
|
||||
.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());
|
||||
@@ -227,6 +232,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 +373,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,
|
||||
@@ -585,7 +592,7 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R
|
||||
renderTargets, flippedAfterPrepare, flippedAfterTranslucent,
|
||||
celeritasShadowFb);
|
||||
|
||||
this.dhCompat = new DHCompat();
|
||||
this.dhCompat = new DHCompat(this, shadowDirectives.isDhShadowEnabled().orElse(true));
|
||||
}
|
||||
|
||||
private RenderTargets getRenderTargets() {
|
||||
@@ -719,6 +726,10 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R
|
||||
return RenderCondition.ENTITIES;
|
||||
}
|
||||
case BLOCK_ENTITIES:
|
||||
if (GLStateManager.getBlendState().getSrcRgb() == SRC_ALPHA &&
|
||||
GLStateManager.getBlendState().getDstRgb() == ONE_MINUS_SRC_ALPHA) {
|
||||
return RenderCondition.BLOCK_ENTITIES_TRANSLUCENT;
|
||||
}
|
||||
return RenderCondition.BLOCK_ENTITIES;
|
||||
case DESTROY:
|
||||
return RenderCondition.DESTROY;
|
||||
@@ -749,6 +760,13 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R
|
||||
return p != null ? p.getProgramId() : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a mod overrides the GL program away from the active Iris pass
|
||||
*/
|
||||
public void onModProgramOverride() {
|
||||
current = null;
|
||||
}
|
||||
|
||||
private void matchPass() {
|
||||
if (!isRenderingWorld || isRenderingFullScreenPass || isPostChain || !isMainBound) {
|
||||
return;
|
||||
@@ -883,7 +901,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 +921,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 +984,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 +1074,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 +1093,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 +1131,7 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R
|
||||
BlendModeOverride.restore();
|
||||
AlphaTestOverride.restore();
|
||||
|
||||
FullScreenQuadRenderer.clearLocCache();
|
||||
destroyPasses(table);
|
||||
|
||||
// Destroy the composite rendering pipeline
|
||||
@@ -1077,6 +1181,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) {
|
||||
|
||||
@@ -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,6 +39,9 @@ public class PatchedShaderPrinter {
|
||||
}
|
||||
|
||||
public static void debugPatchedShaders(String name, String vertex, String geometry, String tessControl, String tessEval, String fragment, String compute) {
|
||||
if (!Iris.getIrisConfig().areDebugOptionsEnabled()) {
|
||||
return;
|
||||
}
|
||||
if (prettyPrintShaders) {
|
||||
final Path debugOutDir = Minecraft.getMinecraft().mcDataDir.toPath().resolve("patched_shaders");
|
||||
if (!outputLocationCleared) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -439,6 +439,12 @@ 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());
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import net.coderbot.iris.helpers.Tri;
|
||||
import net.coderbot.iris.pipeline.transform.parameter.AttributeParameters;
|
||||
import net.coderbot.iris.pipeline.transform.parameter.CeleritasTerrainParameters;
|
||||
import net.coderbot.iris.pipeline.transform.parameter.ComputeParameters;
|
||||
import net.coderbot.iris.pipeline.transform.parameter.DHParameters;
|
||||
import net.coderbot.iris.pipeline.transform.parameter.Parameters;
|
||||
import net.coderbot.iris.pipeline.transform.parameter.TextureStageParameters;
|
||||
import net.coderbot.iris.shaderpack.texture.TextureStage;
|
||||
@@ -127,6 +128,23 @@ public class TransformPatcher {
|
||||
return transform(vertex, geometry, tessControl, tessEval, fragment, new TextureStageParameters(Patch.COMPOSITE, stage, textureMap));
|
||||
}
|
||||
|
||||
|
||||
public static Map<PatchShaderType, String> patchDHTerrain(
|
||||
String name, String vertex, String tessControl, String tessEval, String geometry, String fragment,
|
||||
Object2ObjectMap<Tri<String, TextureType, TextureStage>, String> textureMap) {
|
||||
return transform(vertex, geometry, tessControl, tessEval, fragment,
|
||||
new DHParameters(Patch.DH_TERRAIN, textureMap));
|
||||
}
|
||||
|
||||
|
||||
public static Map<PatchShaderType, String> patchDHGeneric(
|
||||
String name, String vertex, String tessControl, String tessEval, String geometry, String fragment,
|
||||
Object2ObjectMap<Tri<String, TextureType, TextureStage>, String> textureMap) {
|
||||
return transform(vertex, geometry, tessControl, tessEval, fragment,
|
||||
new DHParameters(Patch.DH_GENERIC, textureMap));
|
||||
|
||||
}
|
||||
|
||||
public static Map<PatchShaderType, String> patchComposite(String vertex, String geometry, String fragment, TextureStage stage, Object2ObjectMap<Tri<String, TextureType, TextureStage>, String> textureMap) {
|
||||
return patchComposite(vertex, geometry, null, null, fragment, stage, textureMap);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package net.coderbot.iris.pipeline.transform.parameter;
|
||||
|
||||
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.Patch;
|
||||
import net.coderbot.iris.shaderpack.texture.TextureStage;
|
||||
|
||||
public class DHParameters extends Parameters {
|
||||
public DHParameters(Patch patch, Object2ObjectMap<Tri<String, TextureType, TextureStage>, String> textureMap) {
|
||||
super(patch, textureMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureStage getTextureStage() {
|
||||
return TextureStage.GBUFFERS_AND_SHADOW;
|
||||
}
|
||||
}
|
||||
@@ -78,6 +78,11 @@ public class FullScreenQuadRenderer {
|
||||
/** Per-program cached uniform locations: [mvLoc, projLoc]. Populated on first miss. */
|
||||
private static final Int2ObjectOpenHashMap<int[]> compositeLocCache = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
/** Clear cached uniform locations. Must be called when composite programs are destroyed (e.g. shader reload). */
|
||||
public static void clearLocCache() {
|
||||
compositeLocCache.clear();
|
||||
}
|
||||
|
||||
public static void uploadCompositeMatrices() {
|
||||
final int program = GLStateManager.glGetInteger(GL20.GL_CURRENT_PROGRAM);
|
||||
if (program == 0) return;
|
||||
|
||||
@@ -248,6 +248,16 @@ public class RenderTargets {
|
||||
return framebuffer;
|
||||
}
|
||||
|
||||
public GlFramebuffer createDHFramebuffer(ImmutableSet<Integer> stageWritesToAlt, int[] drawBuffers) {
|
||||
if (drawBuffers.length == 0) {
|
||||
return createEmptyFramebuffer();
|
||||
}
|
||||
|
||||
ImmutableSet<Integer> stageWritesToMain = invert(stageWritesToAlt, drawBuffers);
|
||||
|
||||
return createColorFramebuffer(stageWritesToMain, drawBuffers);
|
||||
}
|
||||
|
||||
public GlFramebuffer createGbufferFramebuffer(ImmutableSet<Integer> stageWritesToAlt, int[] drawBuffers) {
|
||||
if (drawBuffers.length == 0) {
|
||||
return createEmptyFramebuffer();
|
||||
|
||||
@@ -28,7 +28,7 @@ public class PackDirectives {
|
||||
@Getter private float eyeBrightnessHalfLife;
|
||||
@Getter private float centerDepthHalfLife;
|
||||
@Getter private CloudSetting cloudSetting;
|
||||
@Getter private CloudSetting dhCloudSetting;
|
||||
private CloudSetting dhCloudSetting;
|
||||
private boolean underwaterOverlay;
|
||||
private boolean vignette;
|
||||
private boolean sun;
|
||||
@@ -181,6 +181,10 @@ public class PackDirectives {
|
||||
return concurrentCompute;
|
||||
}
|
||||
|
||||
public CloudSetting getDHCloudSetting() {
|
||||
return dhCloudSetting;
|
||||
}
|
||||
|
||||
private static float clamp(float val, float lo, float hi) {
|
||||
return Math.max(lo, Math.min(hi, val));
|
||||
}
|
||||
|
||||
@@ -30,6 +30,8 @@ public class PackShadowDirectives {
|
||||
private final boolean shouldRenderPlayer;
|
||||
private final boolean shouldRenderBlockEntities;
|
||||
@Getter private final ShadowCullState cullingState;
|
||||
private final OptionalBoolean dhShadowEnabled;
|
||||
private float nearPlane, farPlane;
|
||||
|
||||
private final ImmutableList<DepthSamplingSettings> depthSamplingSettings;
|
||||
private final ImmutableList<SamplingSettings> colorSamplingSettings;
|
||||
@@ -53,6 +55,8 @@ public class PackShadowDirectives {
|
||||
// shadowRenderDistanceMul to a nonzero value, since having a high shadow render distance will impact
|
||||
// performance quite heavily on most systems.
|
||||
this.distance = 160.0f;
|
||||
this.nearPlane = 0.05f;
|
||||
this.farPlane = 256.0f;
|
||||
this.voxelDistance = 0.0f;
|
||||
|
||||
// By default, shadows are not culled based on distance from the player. However, pack authors may
|
||||
@@ -81,6 +85,7 @@ public class PackShadowDirectives {
|
||||
this.shouldRenderBlockEntities = properties.getShadowBlockEntities().orElse(true);
|
||||
this.cullingState = properties.getShadowCulling();
|
||||
this.shadowEnabled = properties.getShadowEnabled();
|
||||
this.dhShadowEnabled = properties.getDhShadowEnabled();
|
||||
|
||||
this.depthSamplingSettings = ImmutableList.of(new DepthSamplingSettings(), new DepthSamplingSettings());
|
||||
|
||||
@@ -97,6 +102,8 @@ public class PackShadowDirectives {
|
||||
this.resolution = shadowDirectives.resolution;
|
||||
this.fov = shadowDirectives.fov;
|
||||
this.distance = shadowDirectives.distance;
|
||||
this.nearPlane = shadowDirectives.nearPlane;
|
||||
this.farPlane = shadowDirectives.farPlane;
|
||||
this.voxelDistance = shadowDirectives.voxelDistance;
|
||||
this.distanceRenderMul = shadowDirectives.distanceRenderMul;
|
||||
this.entityShadowDistanceMul = shadowDirectives.entityShadowDistanceMul;
|
||||
@@ -111,6 +118,7 @@ public class PackShadowDirectives {
|
||||
this.depthSamplingSettings = shadowDirectives.depthSamplingSettings;
|
||||
this.colorSamplingSettings = shadowDirectives.colorSamplingSettings;
|
||||
this.shadowEnabled = shadowDirectives.shadowEnabled;
|
||||
this.dhShadowEnabled = shadowDirectives.dhShadowEnabled;
|
||||
}
|
||||
|
||||
public int getResolution() {
|
||||
@@ -125,6 +133,18 @@ public class PackShadowDirectives {
|
||||
return distance;
|
||||
}
|
||||
|
||||
public float getNearPlane() {
|
||||
return nearPlane;
|
||||
}
|
||||
|
||||
public float getFarPlane() {
|
||||
return farPlane;
|
||||
}
|
||||
|
||||
public OptionalBoolean isDhShadowEnabled() {
|
||||
return dhShadowEnabled;
|
||||
}
|
||||
|
||||
public float getVoxelDistance() {
|
||||
return voxelDistance;
|
||||
}
|
||||
@@ -186,7 +206,8 @@ public class PackShadowDirectives {
|
||||
|
||||
directives.acceptCommentFloatDirective("SHADOWHPL", distance -> this.distance = distance);
|
||||
directives.acceptConstFloatDirective("shadowDistance", distance -> this.distance = distance);
|
||||
|
||||
directives.acceptConstFloatDirective("shadowNearPlane", nearPlane -> this.nearPlane = nearPlane);
|
||||
directives.acceptConstFloatDirective("shadowFarPlane", farPlane -> this.farPlane = farPlane);
|
||||
directives.acceptConstFloatDirective("entityShadowDistanceMul", distance -> this.entityShadowDistanceMul = distance);
|
||||
|
||||
directives.acceptConstFloatDirective("shadowDistanceRenderMul", distanceRenderMul -> {
|
||||
|
||||
@@ -43,6 +43,7 @@ public class ProgramSet {
|
||||
private final ProgramSource gbuffersGlint;
|
||||
private final ProgramSource gbuffersEntityEyes;
|
||||
private final ProgramSource gbuffersBlock;
|
||||
private final ProgramSource gbuffersBlockTrans;
|
||||
private final ProgramSource gbuffersHand;
|
||||
|
||||
private final ProgramSource[] deferred;
|
||||
@@ -55,7 +56,10 @@ public class ProgramSet {
|
||||
private final ComputeSource[][] compositeCompute;
|
||||
private final ProgramSource compositeFinal;
|
||||
private final ComputeSource[] finalCompute;
|
||||
|
||||
private final ProgramSource dhTerrain;
|
||||
private final ProgramSource dhGeneric;
|
||||
private final ProgramSource dhWater;
|
||||
private final ProgramSource dhShadow;
|
||||
|
||||
private final ShaderPack pack;
|
||||
|
||||
@@ -116,7 +120,12 @@ public class ProgramSet {
|
||||
this.gbuffersGlint = readProgramSource(directory, sourceProvider, "gbuffers_armor_glint", this, shaderProperties);
|
||||
this.gbuffersEntityEyes = readProgramSource(directory, sourceProvider, "gbuffers_spidereyes", this, shaderProperties);
|
||||
this.gbuffersBlock = readProgramSource(directory, sourceProvider, "gbuffers_block", this, shaderProperties);
|
||||
this.gbuffersBlockTrans = readProgramSource(directory, sourceProvider, "gbuffers_block_translucent", this, shaderProperties);
|
||||
this.gbuffersHand = readProgramSource(directory, sourceProvider, "gbuffers_hand", this, shaderProperties);
|
||||
this.dhTerrain = readProgramSource(directory, sourceProvider, "dh_terrain", this, shaderProperties);
|
||||
this.dhGeneric = readProgramSource(directory, sourceProvider, "dh_generic", this, shaderProperties);
|
||||
this.dhWater = readProgramSource(directory, sourceProvider, "dh_water", this, shaderProperties);
|
||||
this.dhShadow = readProgramSource(directory, sourceProvider, "dh_shadow", this, shaderProperties);
|
||||
|
||||
this.deferred = readProgramArray(directory, sourceProvider, "deferred", shaderProperties);
|
||||
this.deferredCompute = new ComputeSource[deferred.length][];
|
||||
@@ -216,8 +225,8 @@ public class ProgramSet {
|
||||
programs.addAll (Arrays.asList(
|
||||
gbuffersBasic, gbuffersBeaconBeam, gbuffersTextured, gbuffersTexturedLit, gbuffersTerrain,
|
||||
gbuffersDamagedBlock, gbuffersSkyBasic, gbuffersSkyTextured, gbuffersClouds, gbuffersWeather,
|
||||
gbuffersEntities, gbuffersEntitiesTrans, gbuffersEntitiesGlowing, gbuffersGlint, gbuffersEntityEyes, gbuffersBlock,
|
||||
gbuffersHand
|
||||
gbuffersEntities, gbuffersEntitiesTrans, gbuffersEntitiesGlowing, gbuffersGlint, gbuffersEntityEyes, gbuffersBlock, gbuffersBlockTrans,
|
||||
gbuffersHand, dhShadow, dhTerrain, dhGeneric, dhWater
|
||||
));
|
||||
|
||||
for (ComputeSource[] computeSources : compositeCompute) {
|
||||
@@ -377,36 +386,61 @@ public class ProgramSet {
|
||||
return gbuffersBlock.requireValid();
|
||||
}
|
||||
|
||||
public Optional<ProgramSource> getGbuffersBlockTrans() {
|
||||
return gbuffersBlockTrans.requireValid();
|
||||
}
|
||||
|
||||
public Optional<ProgramSource> getGbuffersHand() {
|
||||
return gbuffersHand.requireValid();
|
||||
}
|
||||
|
||||
public Optional<ProgramSource> getDhTerrain() {
|
||||
return dhTerrain.requireValid();
|
||||
}
|
||||
|
||||
public Optional<ProgramSource> getDhGeneric() {
|
||||
return dhGeneric.requireValid();
|
||||
}
|
||||
|
||||
public Optional<ProgramSource> getDhWater() {
|
||||
return dhWater.requireValid();
|
||||
}
|
||||
|
||||
public Optional<ProgramSource> getDhShadow() {
|
||||
return dhShadow.requireValid();
|
||||
}
|
||||
|
||||
public Optional<ProgramSource> get(ProgramId programId) {
|
||||
return switch (programId) {
|
||||
case Shadow -> getShadow();
|
||||
case Basic -> getGbuffersBasic();
|
||||
case Line -> gbuffersLine.requireValid();
|
||||
case Textured -> getGbuffersTextured();
|
||||
case TexturedLit -> getGbuffersTexturedLit();
|
||||
case SkyBasic -> getGbuffersSkyBasic();
|
||||
case SkyTextured -> getGbuffersSkyTextured();
|
||||
case Clouds -> getGbuffersClouds();
|
||||
case Terrain -> getGbuffersTerrain();
|
||||
case DamagedBlock -> getGbuffersDamagedBlock();
|
||||
case Block -> getGbuffersBlock();
|
||||
case BeaconBeam -> getGbuffersBeaconBeam();
|
||||
case Entities -> getGbuffersEntities();
|
||||
case EntitiesTrans -> getGbuffersEntitiesTrans();
|
||||
case EntitiesGlowing -> getGbuffersEntitiesGlowing();
|
||||
case ArmorGlint -> getGbuffersGlint();
|
||||
case SpiderEyes -> getGbuffersEntityEyes();
|
||||
case Hand -> getGbuffersHand();
|
||||
case Weather -> getGbuffersWeather();
|
||||
case Water -> getGbuffersWater();
|
||||
case HandWater -> getGbuffersHandWater();
|
||||
case Final -> getCompositeFinal();
|
||||
default -> Optional.empty();
|
||||
};
|
||||
return switch (programId) {
|
||||
case Shadow -> getShadow();
|
||||
case Basic -> getGbuffersBasic();
|
||||
case Line -> gbuffersLine.requireValid();
|
||||
case Textured -> getGbuffersTextured();
|
||||
case TexturedLit -> getGbuffersTexturedLit();
|
||||
case SkyBasic -> getGbuffersSkyBasic();
|
||||
case SkyTextured -> getGbuffersSkyTextured();
|
||||
case Clouds -> getGbuffersClouds();
|
||||
case Terrain -> getGbuffersTerrain();
|
||||
case DamagedBlock -> getGbuffersDamagedBlock();
|
||||
case Block -> getGbuffersBlock();
|
||||
case BlockTrans -> getGbuffersBlockTrans();
|
||||
case BeaconBeam -> getGbuffersBeaconBeam();
|
||||
case Entities -> getGbuffersEntities();
|
||||
case EntitiesTrans -> getGbuffersEntitiesTrans();
|
||||
case EntitiesGlowing -> getGbuffersEntitiesGlowing();
|
||||
case ArmorGlint -> getGbuffersGlint();
|
||||
case SpiderEyes -> getGbuffersEntityEyes();
|
||||
case Hand -> getGbuffersHand();
|
||||
case Weather -> getGbuffersWeather();
|
||||
case Water -> getGbuffersWater();
|
||||
case HandWater -> getGbuffersHandWater();
|
||||
case Final -> getCompositeFinal();
|
||||
case DhTerrain -> getDhTerrain();
|
||||
case DhGeneric -> getDhGeneric();
|
||||
case DhWater -> getDhWater();
|
||||
case DhShadow -> getDhShadow();
|
||||
default -> Optional.empty();
|
||||
};
|
||||
}
|
||||
|
||||
public ProgramSource[] getDeferred() {
|
||||
|
||||
@@ -97,6 +97,7 @@ public class ShaderProperties {
|
||||
@Getter private OptionalBoolean prepareBeforeShadow = OptionalBoolean.DEFAULT;
|
||||
@Getter private List<String> sliderOptions = new ArrayList<>();
|
||||
@Getter private final Map<String, List<String>> profiles = new LinkedHashMap<>();
|
||||
@Getter private final Map<String, List<String>> profiles2 = new LinkedHashMap<>();
|
||||
private List<String> mainScreenOptions = null;
|
||||
@Getter private final Map<String, List<String>> subScreenOptions = new HashMap<>();
|
||||
private Integer mainScreenColumnCount = null;
|
||||
@@ -494,15 +495,15 @@ public class ShaderProperties {
|
||||
customUniforms.addVariable(parts[0], parts[1], value, false);
|
||||
});
|
||||
|
||||
handlePassDirective("uniform.", key, value, pass -> {
|
||||
String[] parts = pass.split("\\.");
|
||||
if (parts.length != 2) {
|
||||
Iris.logger.warn("Custom uniforms sould take the form of `uniform.<type>.<name> = <expression>. Ignoring " + key);
|
||||
return;
|
||||
}
|
||||
handlePassDirective("uniform.", key, value, pass -> {
|
||||
String[] parts = pass.split("\\.");
|
||||
if (parts.length != 2) {
|
||||
Iris.logger.warn("Custom uniforms sould take the form of `uniform.<type>.<name> = <expression>. Ignoring " + key);
|
||||
return;
|
||||
}
|
||||
|
||||
customUniforms.addVariable(parts[0], parts[1], value, true);
|
||||
});
|
||||
customUniforms.addVariable(parts[0], parts[1], value, true);
|
||||
});
|
||||
|
||||
// TODO: Buffer size directives
|
||||
// TODO: Conditional program enabling directives
|
||||
@@ -517,6 +518,7 @@ public class ShaderProperties {
|
||||
// the last definition being used, should be tested if behavior matches OptiFine
|
||||
handleWhitespacedListDirective(key, value, "sliders", sliders -> sliderOptions = sliders);
|
||||
handlePrefixedWhitespacedListDirective("profile.", key, value, profiles::put);
|
||||
handlePrefixedWhitespacedListDirective("profile2.", key, value, profiles2::put);
|
||||
|
||||
if (handleIntDirective(key, value, "screen.columns", columns -> mainScreenColumnCount = columns)) {
|
||||
return;
|
||||
|
||||
@@ -7,7 +7,8 @@ public enum ProgramGroup {
|
||||
Gbuffers("gbuffers"),
|
||||
Deferred("deferred"),
|
||||
Composite("composite"),
|
||||
Final("final")
|
||||
Final("final"),
|
||||
Dh("dh")
|
||||
;
|
||||
|
||||
private final String baseName;
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
package net.coderbot.iris.shaderpack.loading;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.states.BlendState;
|
||||
import net.coderbot.iris.gl.blending.AlphaTest;
|
||||
import net.coderbot.iris.gl.blending.AlphaTestFunction;
|
||||
import net.coderbot.iris.gl.blending.AlphaTestOverride;
|
||||
import net.coderbot.iris.gl.blending.BlendModeOverride;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
@@ -26,6 +31,7 @@ public enum ProgramId {
|
||||
DamagedBlock(ProgramGroup.Gbuffers, "damagedblock", Terrain),
|
||||
|
||||
Block(ProgramGroup.Gbuffers, "block", Terrain),
|
||||
BlockTrans(ProgramGroup.Gbuffers, "block_translucent", Block, BlendModeOverride.OFF),
|
||||
BeaconBeam(ProgramGroup.Gbuffers, "beaconbeam", Textured),
|
||||
Item(ProgramGroup.Gbuffers, "item", TexturedLit),
|
||||
|
||||
@@ -33,12 +39,18 @@ public enum ProgramId {
|
||||
EntitiesTrans(ProgramGroup.Gbuffers, "entities_translucent", Entities),
|
||||
EntitiesGlowing(ProgramGroup.Gbuffers, "entities_glowing", Entities),
|
||||
ArmorGlint(ProgramGroup.Gbuffers, "armor_glint", Textured),
|
||||
SpiderEyes(ProgramGroup.Gbuffers, "spidereyes", Textured),
|
||||
SpiderEyes(ProgramGroup.Gbuffers, "spidereyes", Textured,
|
||||
new BlendModeOverride(new BlendState(GL11.GL_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO, GL11.GL_ONE)),
|
||||
new AlphaTestOverride(new AlphaTest(AlphaTestFunction.GREATER, 0.0001F))),
|
||||
|
||||
Hand(ProgramGroup.Gbuffers, "hand", TexturedLit),
|
||||
Weather(ProgramGroup.Gbuffers, "weather", TexturedLit),
|
||||
Water(ProgramGroup.Gbuffers, "water", Terrain),
|
||||
HandWater(ProgramGroup.Gbuffers, "hand_water", Hand),
|
||||
DhTerrain(ProgramGroup.Dh, "terrain"),
|
||||
DhWater(ProgramGroup.Dh, "water", DhTerrain),
|
||||
DhGeneric(ProgramGroup.Dh, "generic", DhTerrain),
|
||||
DhShadow(ProgramGroup.Dh, "shadow"),
|
||||
|
||||
Final(ProgramGroup.Final, ""),
|
||||
;
|
||||
@@ -47,12 +59,14 @@ public enum ProgramId {
|
||||
private final String sourceName;
|
||||
private final ProgramId fallback;
|
||||
private final BlendModeOverride defaultBlendOverride;
|
||||
private final AlphaTestOverride defaultAlphaTestOverride;
|
||||
|
||||
ProgramId(ProgramGroup group, String name) {
|
||||
this.group = group;
|
||||
this.sourceName = name.isEmpty() ? group.getBaseName() : group.getBaseName() + "_" + name;
|
||||
this.fallback = null;
|
||||
this.defaultBlendOverride = null;
|
||||
this.defaultAlphaTestOverride = null;
|
||||
}
|
||||
|
||||
ProgramId(ProgramGroup group, String name, ProgramId fallback) {
|
||||
@@ -60,6 +74,7 @@ public enum ProgramId {
|
||||
this.sourceName = name.isEmpty() ? group.getBaseName() : group.getBaseName() + "_" + name;
|
||||
this.fallback = Objects.requireNonNull(fallback);
|
||||
this.defaultBlendOverride = null;
|
||||
this.defaultAlphaTestOverride = null;
|
||||
}
|
||||
|
||||
ProgramId(ProgramGroup group, String name, ProgramId fallback, BlendModeOverride defaultBlendOverride) {
|
||||
@@ -67,6 +82,15 @@ public enum ProgramId {
|
||||
this.sourceName = name.isEmpty() ? group.getBaseName() : group.getBaseName() + "_" + name;
|
||||
this.fallback = Objects.requireNonNull(fallback);
|
||||
this.defaultBlendOverride = defaultBlendOverride;
|
||||
this.defaultAlphaTestOverride = null;
|
||||
}
|
||||
|
||||
ProgramId(ProgramGroup group, String name, ProgramId fallback, BlendModeOverride defaultBlendOverride, AlphaTestOverride defaultAlphaTestOverride) {
|
||||
this.group = group;
|
||||
this.sourceName = name.isEmpty() ? group.getBaseName() : group.getBaseName() + "_" + name;
|
||||
this.fallback = Objects.requireNonNull(fallback);
|
||||
this.defaultBlendOverride = defaultBlendOverride;
|
||||
this.defaultAlphaTestOverride = defaultAlphaTestOverride;
|
||||
}
|
||||
|
||||
public ProgramGroup getGroup() {
|
||||
@@ -84,4 +108,8 @@ public enum ProgramId {
|
||||
public BlendModeOverride getBlendModeOverride() {
|
||||
return defaultBlendOverride;
|
||||
}
|
||||
|
||||
public AlphaTestOverride getDefaultAlphaTestOverride() {
|
||||
return defaultAlphaTestOverride;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.coderbot.iris.shaderpack.option.menu;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.Getter;
|
||||
import net.coderbot.iris.Iris;
|
||||
import net.coderbot.iris.shaderpack.ShaderProperties;
|
||||
import net.coderbot.iris.shaderpack.option.ProfileSet;
|
||||
@@ -21,10 +22,12 @@ public class OptionMenuContainer {
|
||||
private final List<String> usedOptions = new ArrayList<>();
|
||||
private final List<String> unusedOptions = new ArrayList<>(); // To be used when screens contain a "*" element
|
||||
private final Map<List<OptionMenuElement>, Integer> unusedOptionDumpQueue = new HashMap<>(); // Used by screens with "*" element
|
||||
private final ProfileSet profiles;
|
||||
@Getter private final ProfileSet profiles;
|
||||
@Getter private final ProfileSet profiles2;
|
||||
|
||||
public OptionMenuContainer(ShaderProperties shaderProperties, ShaderPackOptions shaderPackOptions, ProfileSet profiles) {
|
||||
this.profiles = profiles;
|
||||
this.profiles2 = ProfileSet.fromTree(shaderProperties.getProfiles2(), shaderPackOptions.getOptionSet());
|
||||
|
||||
// note: if the Shader Pack does not provide a list of options for the main screen, then dump all options on to
|
||||
// the main screen by default.
|
||||
@@ -68,10 +71,6 @@ public class OptionMenuContainer {
|
||||
}
|
||||
}
|
||||
|
||||
public ProfileSet getProfiles() {
|
||||
return profiles;
|
||||
}
|
||||
|
||||
// Screens will call this when they contain a "*" element, so that the list of
|
||||
// unused options can be added after all other screens have been resolved
|
||||
public void queueForUnusedOptionDump(int index, List<OptionMenuElement> elementList) {
|
||||
|
||||
@@ -12,6 +12,7 @@ public abstract class OptionMenuElement {
|
||||
|
||||
private static final String ELEMENT_EMPTY = "<empty>";
|
||||
private static final String ELEMENT_PROFILE = "<profile>";
|
||||
private static final String ELEMENT_PROFILE2 = "<profile2>";
|
||||
|
||||
public static OptionMenuElement create(String elementString, OptionMenuContainer container, ShaderProperties shaderProperties, ShaderPackOptions shaderPackOptions) throws IllegalArgumentException {
|
||||
// Empty element
|
||||
@@ -24,6 +25,13 @@ public abstract class OptionMenuElement {
|
||||
// null indicates that the element should be forgotten (not treated as empty)
|
||||
return container.getProfiles().size() > 0 ? new OptionMenuProfileElement(container.getProfiles(), shaderPackOptions.getOptionSet(), shaderPackOptions.getOptionValues()) : null;
|
||||
}
|
||||
// Second profile element
|
||||
if (ELEMENT_PROFILE2.equals(elementString)) {
|
||||
// null indicates that the element should be forgotten (not treated as empty)
|
||||
return container.getProfiles2().size() > 0
|
||||
? ProfileElementTracker.markSecondProfileSet(new OptionMenuProfileElement(container.getProfiles2(), shaderPackOptions.getOptionSet(), shaderPackOptions.getOptionValues()))
|
||||
: null;
|
||||
}
|
||||
// Link to sub screen element
|
||||
if (elementString.startsWith("[") && elementString.endsWith("]")) {
|
||||
return new OptionMenuLinkElement(elementString.substring(1, elementString.length() - 1));
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package net.coderbot.iris.shaderpack.option.menu;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
public final class ProfileElementTracker {
|
||||
private static final Set<Object> SECOND_PROFILE_ELEMENTS =
|
||||
Collections.newSetFromMap(new WeakHashMap<>());
|
||||
|
||||
private ProfileElementTracker() {
|
||||
}
|
||||
|
||||
public static <T> T markSecondProfileSet(T element) {
|
||||
SECOND_PROFILE_ELEMENTS.add(element);
|
||||
return element;
|
||||
}
|
||||
|
||||
public static boolean isSecondProfileSet(Object element) {
|
||||
return SECOND_PROFILE_ELEMENTS.contains(element);
|
||||
}
|
||||
}
|
||||
@@ -11,16 +11,16 @@ public class ShadowMatrices {
|
||||
|
||||
// NB: These matrices are in column-major order, not row-major order like what you'd expect!
|
||||
|
||||
public static Matrix4f createOrthoMatrix(float halfPlaneLength) {
|
||||
public static Matrix4f createOrthoMatrix(float halfPlaneLength, float nearPlane, float farPlane) {
|
||||
return new Matrix4f(
|
||||
// column 1
|
||||
1.0f / halfPlaneLength, 0f, 0f, 0f,
|
||||
// column 2
|
||||
0f, 1.0f / halfPlaneLength, 0f, 0f,
|
||||
// column 3
|
||||
0f, 0f, 2.0f / (NEAR - FAR), 0f,
|
||||
0f, 0f, 2.0f / (nearPlane - farPlane), 0f,
|
||||
// column 4
|
||||
0f, 0f, -(FAR + NEAR) / (FAR - NEAR), 1f
|
||||
0f, 0f, -(farPlane + nearPlane) / (farPlane - nearPlane), 1f
|
||||
);
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ public class ShadowMatrices {
|
||||
0f, 0f, -1.000390648841858f, 1f
|
||||
);
|
||||
|
||||
test("ortho projection hpl=32", expected, createOrthoMatrix(32.0f));
|
||||
test("ortho projection hpl=32", expected, createOrthoMatrix(32.0f, 0.05f, 256.0f));
|
||||
|
||||
// const float shadowDistance = 110.0;
|
||||
// /* SHADOWHPL:110.0 */
|
||||
@@ -115,7 +115,7 @@ public class ShadowMatrices {
|
||||
0, 0, -1.000390648841858f, 1
|
||||
);
|
||||
|
||||
test("ortho projection hpl=110", expected110, createOrthoMatrix(110.0f));
|
||||
test("ortho projection hpl=110", expected110, createOrthoMatrix(110.0f, 0.05f, 256.0f));
|
||||
|
||||
Matrix4f expected90Proj = new Matrix4f(
|
||||
1.0f, 0.0f, 0.0f, 0.0f,
|
||||
|
||||
@@ -206,6 +206,20 @@ public class ShadowRenderTargets {
|
||||
return framebuffer;
|
||||
}
|
||||
|
||||
public GlFramebuffer createDHFramebuffer(ImmutableSet<Integer> stageWritesToAlt, int[] drawBuffers) {
|
||||
if (drawBuffers.length == 0) {
|
||||
return createEmptyFramebuffer();
|
||||
}
|
||||
|
||||
ImmutableSet<Integer> stageWritesToMain = invert(stageWritesToAlt, drawBuffers);
|
||||
|
||||
GlFramebuffer framebuffer = createColorFramebuffer(stageWritesToMain, drawBuffers);
|
||||
|
||||
framebuffer.addDepthAttachment(mainDepth.getTextureId());
|
||||
|
||||
return framebuffer;
|
||||
}
|
||||
|
||||
public GlFramebuffer createShadowFramebuffer(ImmutableSet<Integer> stageWritesToAlt, int[] drawBuffers) {
|
||||
if (drawBuffers.length == 0) {
|
||||
return createEmptyFramebuffer();
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package net.coderbot.iris.shadows.frustum;
|
||||
|
||||
import cpw.mods.fml.common.Optional;
|
||||
import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiShadowCullingFrustum;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiMat4f;
|
||||
import net.minecraft.client.renderer.culling.Frustrum;
|
||||
import net.minecraft.util.AxisAlignedBB;
|
||||
import org.embeddedt.embeddium.impl.render.viewport.Viewport;
|
||||
@@ -7,7 +10,8 @@ import org.embeddedt.embeddium.impl.render.viewport.ViewportProvider;
|
||||
import org.embeddedt.embeddium.impl.render.viewport.frustum.Frustum;
|
||||
import org.joml.Vector3d;
|
||||
|
||||
public class CullEverythingFrustum extends Frustrum implements ViewportProvider, Frustum {
|
||||
@Optional.Interface(modid = "distanthorizons", iface = "com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiShadowCullingFrustum")
|
||||
public class CullEverythingFrustum extends Frustrum implements ViewportProvider, Frustum, IDhApiShadowCullingFrustum {
|
||||
private final Vector3d position = new Vector3d();
|
||||
|
||||
@Override
|
||||
@@ -24,4 +28,16 @@ public class CullEverythingFrustum extends Frustrum implements ViewportProvider,
|
||||
public Viewport sodium$createViewport() {
|
||||
return new Viewport(this, position.set(xPosition, yPosition, zPosition));
|
||||
}
|
||||
|
||||
@Optional.Method(modid = "distanthorizons")
|
||||
@Override
|
||||
public void update(int worldMinBlockY, int worldMaxBlockY, DhApiMat4f worldViewProjection) {
|
||||
|
||||
}
|
||||
|
||||
@Optional.Method(modid = "distanthorizons")
|
||||
@Override
|
||||
public boolean intersects(int lodBlockPosMinX, int lodBlockPosMinZ, int lodBlockWidth, int lodDetailLevel) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+22
-2
@@ -1,5 +1,8 @@
|
||||
package net.coderbot.iris.shadows.frustum.advanced;
|
||||
|
||||
import cpw.mods.fml.common.Optional;
|
||||
import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiShadowCullingFrustum;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiMat4f;
|
||||
import net.coderbot.iris.shadows.frustum.BoxCuller;
|
||||
import net.minecraft.client.renderer.culling.Frustrum;
|
||||
import net.minecraft.util.AxisAlignedBB;
|
||||
@@ -8,6 +11,7 @@ import org.embeddedt.embeddium.impl.render.viewport.ViewportProvider;
|
||||
import org.embeddedt.embeddium.impl.render.viewport.frustum.Frustum;
|
||||
import org.joml.Math;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Matrix4fc;
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.Vector4f;
|
||||
@@ -32,7 +36,8 @@ import org.joml.Vector4f;
|
||||
* are not sensitive to the specific internal ordering of planes and corners, in order to avoid potential bugs at the
|
||||
* cost of slightly more computations.</p>
|
||||
*/
|
||||
public class AdvancedShadowCullingFrustum extends Frustrum implements ViewportProvider, Frustum {
|
||||
@Optional.Interface(modid = "distanthorizons", iface = "com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiShadowCullingFrustum")
|
||||
public class AdvancedShadowCullingFrustum extends Frustrum implements ViewportProvider, Frustum, IDhApiShadowCullingFrustum {
|
||||
private static final int MAX_CLIPPING_PLANES = 13;
|
||||
|
||||
/**
|
||||
@@ -79,6 +84,8 @@ public class AdvancedShadowCullingFrustum extends Frustrum implements ViewportPr
|
||||
|
||||
private final BaseClippingPlanes baseClippingPlanes = new BaseClippingPlanes();
|
||||
private final boolean[] isBackArray = new boolean[6];
|
||||
private int worldMinYDH;
|
||||
private int worldMaxYDH;
|
||||
|
||||
public AdvancedShadowCullingFrustum() {
|
||||
for (int i = 0; i < MAX_CLIPPING_PLANES; i++) {
|
||||
@@ -86,7 +93,7 @@ public class AdvancedShadowCullingFrustum extends Frustrum implements ViewportPr
|
||||
}
|
||||
}
|
||||
|
||||
public void init(Matrix4f playerView, Matrix4f playerProjection, Vector3f shadowLightVector, BoxCuller boxCuller) {
|
||||
public void init(Matrix4fc playerView, Matrix4fc playerProjection, Vector3f shadowLightVector, BoxCuller boxCuller) {
|
||||
this.shadowLightVectorFromOrigin.set(shadowLightVector);
|
||||
this.boxCuller = boxCuller;
|
||||
this.planeCount = 0;
|
||||
@@ -298,4 +305,17 @@ public class AdvancedShadowCullingFrustum extends Frustrum implements ViewportPr
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Optional.Method(modid = "distanthorizons")
|
||||
@Override
|
||||
public void update(int worldMinBlockY, int worldMaxBlockY, DhApiMat4f worldViewProjection) {
|
||||
this.worldMinYDH = worldMinBlockY;
|
||||
this.worldMaxYDH = worldMaxBlockY;
|
||||
}
|
||||
|
||||
@Optional.Method(modid = "distanthorizons")
|
||||
@Override
|
||||
public boolean intersects(int lodBlockPosMinX, int lodBlockPosMinZ, int lodBlockWidth, int lodDetailLevel) {
|
||||
return this.isVisible(lodBlockPosMinX, this.worldMinYDH, lodBlockPosMinZ, lodBlockPosMinX + lodBlockWidth, this.worldMaxYDH, lodBlockPosMinZ + lodBlockWidth);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.coderbot.iris.shadows.frustum.advanced;
|
||||
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Matrix4fc;
|
||||
import org.joml.Vector4f;
|
||||
|
||||
public class BaseClippingPlanes {
|
||||
@@ -13,7 +14,7 @@ public class BaseClippingPlanes {
|
||||
}
|
||||
}
|
||||
|
||||
public void init(Matrix4f view, Matrix4f projection) {
|
||||
public void init(Matrix4fc view, Matrix4fc projection) {
|
||||
// Transform = Transpose(Projection x View)
|
||||
transformScratch.set(projection);
|
||||
transformScratch.mul(view);
|
||||
|
||||
+2
-1
@@ -3,12 +3,13 @@ package net.coderbot.iris.shadows.frustum.advanced;
|
||||
import net.coderbot.iris.shadows.frustum.BoxCuller;
|
||||
import net.minecraft.util.AxisAlignedBB;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Matrix4fc;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
public class SafeZoneCullingFrustum extends AdvancedShadowCullingFrustum {
|
||||
private final BoxCuller distanceCuller;
|
||||
|
||||
public SafeZoneCullingFrustum(Matrix4f playerView, Matrix4f playerProjection, Vector3f shadowLightVector, BoxCuller voxelCuller, BoxCuller distanceCuller) {
|
||||
public SafeZoneCullingFrustum(Matrix4fc playerView, Matrix4fc playerProjection, Vector3f shadowLightVector, BoxCuller voxelCuller, BoxCuller distanceCuller) {
|
||||
super();
|
||||
init(playerView, playerProjection, shadowLightVector, voxelCuller);
|
||||
this.distanceCuller = distanceCuller;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package net.coderbot.iris.shadows.frustum.fallback;
|
||||
|
||||
import cpw.mods.fml.common.Optional;
|
||||
import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiShadowCullingFrustum;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiMat4f;
|
||||
import net.coderbot.iris.shadows.frustum.BoxCuller;
|
||||
import net.minecraft.client.renderer.culling.Frustrum;
|
||||
import net.minecraft.util.AxisAlignedBB;
|
||||
@@ -8,9 +11,12 @@ import org.embeddedt.embeddium.impl.render.viewport.ViewportProvider;
|
||||
import org.embeddedt.embeddium.impl.render.viewport.frustum.Frustum;
|
||||
import org.joml.Vector3d;
|
||||
|
||||
public class BoxCullingFrustum extends Frustrum implements ViewportProvider, Frustum {
|
||||
@Optional.Interface(modid = "distanthorizons", iface = "com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiShadowCullingFrustum")
|
||||
public class BoxCullingFrustum extends Frustrum implements ViewportProvider, Frustum, IDhApiShadowCullingFrustum {
|
||||
private final BoxCuller boxCuller;
|
||||
private final Vector3d position = new Vector3d();
|
||||
private int worldMinYDH;
|
||||
private int worldMaxYDH;
|
||||
|
||||
public BoxCullingFrustum(BoxCuller boxCuller) {
|
||||
this.boxCuller = boxCuller;
|
||||
@@ -36,4 +42,17 @@ public class BoxCullingFrustum extends Frustrum implements ViewportProvider, Fru
|
||||
public Viewport sodium$createViewport() {
|
||||
return new Viewport(this, position.set(xPosition, yPosition, zPosition));
|
||||
}
|
||||
|
||||
@Optional.Method(modid = "distanthorizons")
|
||||
@Override
|
||||
public void update(int worldMinBlockY, int worldMaxBlockY, DhApiMat4f worldViewProjection) {
|
||||
this.worldMinYDH = worldMinBlockY;
|
||||
this.worldMaxYDH = worldMaxBlockY;
|
||||
}
|
||||
|
||||
@Optional.Method(modid = "distanthorizons")
|
||||
@Override
|
||||
public boolean intersects(int lodBlockPosMinX, int lodBlockPosMinZ, int lodBlockWidth, int lodDetailLevel) {
|
||||
return !boxCuller.isCulled(lodBlockPosMinX, this.worldMinYDH, lodBlockPosMinZ, lodBlockPosMinX + lodBlockWidth, this.worldMaxYDH, lodBlockPosMinZ + lodBlockWidth);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
package net.coderbot.iris.shadows.frustum.fallback;
|
||||
|
||||
import cpw.mods.fml.common.Optional;
|
||||
import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiShadowCullingFrustum;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiMat4f;
|
||||
import net.minecraft.client.renderer.culling.Frustrum;
|
||||
import net.minecraft.util.AxisAlignedBB;
|
||||
import org.embeddedt.embeddium.impl.render.viewport.Viewport;
|
||||
@@ -7,7 +10,8 @@ import org.embeddedt.embeddium.impl.render.viewport.ViewportProvider;
|
||||
import org.embeddedt.embeddium.impl.render.viewport.frustum.Frustum;
|
||||
import org.joml.Vector3d;
|
||||
|
||||
public class NonCullingFrustum extends Frustrum implements ViewportProvider, Frustum {
|
||||
@Optional.Interface(modid = "distanthorizons", iface = "com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiShadowCullingFrustum")
|
||||
public class NonCullingFrustum extends Frustrum implements ViewportProvider, Frustum, IDhApiShadowCullingFrustum {
|
||||
private final Vector3d position = new Vector3d();
|
||||
|
||||
@Override
|
||||
@@ -24,4 +28,17 @@ public class NonCullingFrustum extends Frustrum implements ViewportProvider, Fru
|
||||
public Viewport sodium$createViewport() {
|
||||
return new Viewport(this, position.set(xPosition, yPosition, zPosition));
|
||||
}
|
||||
|
||||
@Optional.Method(modid = "distanthorizons")
|
||||
@Override
|
||||
public void update(int worldMinBlockY, int worldMaxBlockY, DhApiMat4f worldViewProjection) {
|
||||
|
||||
}
|
||||
|
||||
@Optional.Method(modid = "distanthorizons")
|
||||
@Override
|
||||
public boolean intersects(int lodBlockPosMinX, int lodBlockPosMinZ, int lodBlockWidth, int lodDetailLevel) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,8 +4,12 @@ import com.gtnewhorizons.angelica.rendering.RenderingState;
|
||||
import lombok.Getter;
|
||||
import net.coderbot.iris.gl.uniform.UniformHolder;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import org.joml.Matrix3f;
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector3dc;
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.Vector3fc;
|
||||
import org.joml.Vector3i;
|
||||
import org.joml.Vector3ic;
|
||||
|
||||
import static net.coderbot.iris.gl.uniform.UniformUpdateFrequency.ONCE;
|
||||
import static net.coderbot.iris.gl.uniform.UniformUpdateFrequency.PER_FRAME;
|
||||
@@ -15,6 +19,8 @@ import static net.coderbot.iris.gl.uniform.UniformUpdateFrequency.PER_FRAME;
|
||||
*/
|
||||
public class CameraUniforms {
|
||||
private static final Minecraft client = Minecraft.getMinecraft();
|
||||
private static final Vector3f tempVec3f = new Vector3f();
|
||||
private static final Vector3i tempVec3i = new Vector3i();
|
||||
|
||||
private CameraUniforms() {
|
||||
}
|
||||
@@ -27,7 +33,27 @@ public class CameraUniforms {
|
||||
.uniform1f(PER_FRAME, "far", CameraUniforms::getRenderDistanceInBlocks)
|
||||
.uniform3d(PER_FRAME, "cameraPosition", tracker::getCurrentCameraPosition)
|
||||
.uniform1f(PER_FRAME, "eyeAltitude", tracker::getCurrentCameraPositionY)
|
||||
.uniform3d(PER_FRAME, "previousCameraPosition", tracker::getPreviousCameraPosition);
|
||||
.uniform3d(PER_FRAME, "previousCameraPosition", tracker::getPreviousCameraPosition)
|
||||
.uniform3i(PER_FRAME, "cameraPositionInt", () -> getCameraPositionInt(getUnshiftedCameraPosition()))
|
||||
.uniform3f(PER_FRAME, "cameraPositionFract", () -> getCameraPositionFract(getUnshiftedCameraPosition()))
|
||||
.uniform3i(PER_FRAME, "previousCameraPositionInt", () -> getCameraPositionInt(tracker.getPreviousCameraPositionUnshifted()))
|
||||
.uniform3f(PER_FRAME, "previousCameraPositionFract", () -> getCameraPositionFract(tracker.getPreviousCameraPositionUnshifted()));
|
||||
}
|
||||
|
||||
public static Vector3fc getCameraPositionFract(Vector3d originalPos) {
|
||||
return tempVec3f.set(
|
||||
(float) (originalPos.x - Math.floor(originalPos.x)),
|
||||
(float) (originalPos.y - Math.floor(originalPos.y)),
|
||||
(float) (originalPos.z - Math.floor(originalPos.z))
|
||||
);
|
||||
}
|
||||
|
||||
public static Vector3ic getCameraPositionInt(Vector3d originalPos) {
|
||||
return tempVec3i.set(
|
||||
(int) Math.floor(originalPos.x),
|
||||
(int) Math.floor(originalPos.y),
|
||||
(int) Math.floor(originalPos.z)
|
||||
);
|
||||
}
|
||||
|
||||
private static int getRenderDistanceInBlocks() {
|
||||
@@ -35,7 +61,7 @@ public class CameraUniforms {
|
||||
return client.gameSettings.renderDistanceChunks * 16;
|
||||
}
|
||||
|
||||
public static Vector3dc getUnshiftedCameraPosition() {
|
||||
public static Vector3d getUnshiftedCameraPosition() {
|
||||
return RenderingState.INSTANCE.getCameraPosition();
|
||||
}
|
||||
|
||||
@@ -50,10 +76,12 @@ public class CameraUniforms {
|
||||
private static final double TP_RANGE = 1000;
|
||||
|
||||
@Getter
|
||||
private Vector3d previousCameraPosition = new Vector3d();
|
||||
private Vector3d previousCameraPosition = new Vector3d();
|
||||
@Getter
|
||||
private Vector3d currentCameraPosition = new Vector3d();
|
||||
private Vector3d currentCameraPosition = new Vector3d();
|
||||
private final Vector3d shift = new Vector3d();
|
||||
private Vector3d previousCameraPositionUnshifted = new Vector3d();
|
||||
private Vector3d currentCameraPositionUnshifted = new Vector3d();
|
||||
|
||||
CameraPositionTracker(FrameUpdateNotifier notifier) {
|
||||
notifier.addListener(this::update);
|
||||
@@ -61,7 +89,9 @@ public class CameraUniforms {
|
||||
|
||||
private void update() {
|
||||
previousCameraPosition.set(currentCameraPosition);
|
||||
previousCameraPositionUnshifted = currentCameraPositionUnshifted;
|
||||
currentCameraPosition.set(getUnshiftedCameraPosition()).add(shift);
|
||||
currentCameraPositionUnshifted.set(getUnshiftedCameraPosition());
|
||||
|
||||
updateShift();
|
||||
}
|
||||
@@ -104,8 +134,12 @@ public class CameraUniforms {
|
||||
previousCameraPosition.z += dZ;
|
||||
}
|
||||
|
||||
public double getCurrentCameraPositionY() {
|
||||
public double getCurrentCameraPositionY() {
|
||||
return currentCameraPosition.y;
|
||||
}
|
||||
|
||||
public Vector3d getPreviousCameraPositionUnshifted() {
|
||||
return previousCameraPositionUnshifted;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import com.gtnewhorizons.angelica.glsm.texture.TextureInfo;
|
||||
import com.gtnewhorizons.angelica.glsm.texture.TextureInfoCache;
|
||||
import com.gtnewhorizons.angelica.client.rendering.TextureTracker;
|
||||
import com.gtnewhorizons.angelica.mixins.interfaces.EntityRendererAccessor;
|
||||
import net.coderbot.iris.compat.dh.DHCompat;
|
||||
import net.coderbot.iris.gl.state.FogMode;
|
||||
import net.coderbot.iris.gl.state.ValueUpdateNotifier;
|
||||
import net.coderbot.iris.gl.uniform.DynamicUniformHolder;
|
||||
@@ -137,7 +138,10 @@ public final class CommonUniforms {
|
||||
.uniform1f(PER_TICK, "rainStrength", CommonUniforms::getRainStrength)
|
||||
.uniform1f(PER_TICK, "wetness", new SmoothedFloat(directives.getWetnessHalfLife(), directives.getDrynessHalfLife(), CommonUniforms::getRainStrength, updateNotifier))
|
||||
.uniform3d(PER_FRAME, "skyColor", CommonUniforms::getSkyColor)
|
||||
.uniform3d(PER_FRAME, "fogColor", GLStateManager::getFogColor);
|
||||
.uniform3d(PER_FRAME, "fogColor", GLStateManager::getFogColor)
|
||||
.uniform1f(PER_FRAME, "dhFarPlane", DHCompat::getFarPlane)
|
||||
.uniform1f(PER_FRAME, "dhNearPlane", DHCompat::getNearPlane)
|
||||
.uniform1i(PER_FRAME, "dhRenderDistance", DHCompat::getRenderDistance);
|
||||
}
|
||||
|
||||
private static boolean isOnGround() {
|
||||
|
||||
@@ -14,6 +14,7 @@ public class ExternallyManagedUniforms {
|
||||
addMat4(uniformHolder, "iris_ProjectionMatrix");
|
||||
addMat4(uniformHolder, "iris_ProjectionMatrixInverse");
|
||||
addMat4(uniformHolder, "iris_LightmapTextureMatrix");
|
||||
addMat4(uniformHolder, "iris_TextureMatrix");
|
||||
addMat4(uniformHolder, "u_ModelViewProjectionMatrix");
|
||||
addMat3(uniformHolder, "iris_NormalMatrix");
|
||||
uniformHolder.externallyManagedUniform("heavyFog", UniformType.BOOL);
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package net.coderbot.iris.uniforms;
|
||||
|
||||
import com.gtnewhorizons.angelica.rendering.RenderingState;
|
||||
import net.coderbot.iris.compat.dh.DHCompat;
|
||||
import net.coderbot.iris.gl.uniform.UniformHolder;
|
||||
import net.coderbot.iris.pipeline.ShadowRenderer;
|
||||
import net.coderbot.iris.shaderpack.PackDirectives;
|
||||
import net.coderbot.iris.shadow.ShadowMatrices;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Matrix4fc;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@@ -20,27 +22,37 @@ public final class MatrixUniforms {
|
||||
// TODO: In some cases, gbufferProjectionInverse takes on a value much different than OptiFine...
|
||||
// We need to audit Mojang's linear algebra.
|
||||
addMatrix(uniforms, "Projection", RenderingState.INSTANCE::getProjectionMatrix);
|
||||
addDHMatrix(uniforms, "Projection", DHCompat::getProjection);
|
||||
addShadowMatrix(uniforms, "ModelView", () -> ShadowRenderer.createShadowModelView(directives.getSunPathRotation(), directives.getShadowDirectives().getIntervalSize()).peek().getModel());
|
||||
addShadowMatrix(uniforms, "Projection", () -> ShadowMatrices.createOrthoMatrix(directives.getShadowDirectives().getDistance()));
|
||||
addShadowMatrix(uniforms, "Projection", () -> ShadowMatrices.createOrthoMatrix(directives.getShadowDirectives().getDistance(), directives.getShadowDirectives().getNearPlane() < 0 ? -DHCompat.getRenderDistance() : directives.getShadowDirectives().getNearPlane(),
|
||||
directives.getShadowDirectives().getFarPlane() < 0 ? DHCompat.getRenderDistance() : directives.getShadowDirectives().getFarPlane()));
|
||||
}
|
||||
|
||||
private static void addMatrix(UniformHolder uniforms, String name, Supplier<Matrix4f> supplier) {
|
||||
private static void addMatrix(UniformHolder uniforms, String name, Supplier<Matrix4fc> supplier) {
|
||||
uniforms
|
||||
.uniformMatrix(PER_FRAME, "gbuffer" + name, supplier)
|
||||
.uniformMatrix(PER_FRAME, "gbuffer" + name + "Inverse", new Inverted(supplier))
|
||||
.uniformMatrix(PER_FRAME, "gbufferPrevious" + name, new Previous(supplier));
|
||||
}
|
||||
|
||||
private static void addShadowMatrix(UniformHolder uniforms, String name, Supplier<Matrix4f> supplier) {
|
||||
private static void addDHMatrix(UniformHolder uniforms, String name, Supplier<Matrix4fc> supplier) {
|
||||
uniforms
|
||||
.uniformMatrix(PER_FRAME, "dh" + name, supplier)
|
||||
.uniformMatrix(PER_FRAME, "dh" + name + "Inverse", new Inverted(supplier))
|
||||
.uniformMatrix(PER_FRAME, "dhPrevious" + name, new Previous(supplier));
|
||||
}
|
||||
|
||||
|
||||
private static void addShadowMatrix(UniformHolder uniforms, String name, Supplier<Matrix4fc> supplier) {
|
||||
uniforms
|
||||
.uniformMatrix(PER_FRAME, "shadow" + name, supplier)
|
||||
.uniformMatrix(PER_FRAME, "shadow" + name + "Inverse", new Inverted(supplier));
|
||||
}
|
||||
|
||||
private static class Inverted implements Supplier<Matrix4f> {
|
||||
private final Supplier<Matrix4f> parent;
|
||||
private static class Inverted implements Supplier<Matrix4fc> {
|
||||
private final Supplier<Matrix4fc> parent;
|
||||
|
||||
Inverted(Supplier<Matrix4f> parent) {
|
||||
Inverted(Supplier<Matrix4fc> parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
@@ -56,11 +68,11 @@ public final class MatrixUniforms {
|
||||
}
|
||||
|
||||
|
||||
private static class Previous implements Supplier<Matrix4f> {
|
||||
private final Supplier<Matrix4f> parent;
|
||||
private Matrix4f previous;
|
||||
private static class Previous implements Supplier<Matrix4fc> {
|
||||
private final Supplier<Matrix4fc> parent;
|
||||
private Matrix4fc previous;
|
||||
|
||||
Previous(Supplier<Matrix4f> parent) {
|
||||
Previous(Supplier<Matrix4fc> parent) {
|
||||
this.parent = parent;
|
||||
this.previous = new Matrix4f();
|
||||
}
|
||||
|
||||
+5
-4
@@ -25,7 +25,8 @@ import org.joml.Vector2f;
|
||||
import org.joml.Vector2i;
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.Vector3i;
|
||||
import org.joml.Vector3fc;
|
||||
import org.joml.Vector3ic;
|
||||
import org.joml.Vector4f;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -116,12 +117,12 @@ public class CustomUniformFixedInputUniformsHolder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder uniform3f(UniformUpdateFrequency updateFrequency, String name, Supplier<Vector3f> value) {
|
||||
public Builder uniform3f(UniformUpdateFrequency updateFrequency, String name, Supplier<Vector3fc> value) {
|
||||
return this.put(name, new Float3VectorCachedUniform(name, updateFrequency, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder uniform3i(UniformUpdateFrequency updateFrequency, String name, Supplier<Vector3i> value) {
|
||||
public Builder uniform3i(UniformUpdateFrequency updateFrequency, String name, Supplier<Vector3ic> value) {
|
||||
return this.put(name, new Int3VectorCachedUniform(name, updateFrequency, value));
|
||||
}
|
||||
|
||||
@@ -172,7 +173,7 @@ public class CustomUniformFixedInputUniformsHolder {
|
||||
|
||||
@Override
|
||||
public UniformHolder uniformMatrix(
|
||||
UniformUpdateFrequency updateFrequency, String name, Supplier<Matrix4f> value) {
|
||||
UniformUpdateFrequency updateFrequency, String name, Supplier<Matrix4fc> value) {
|
||||
return this.put(name, new Float4MatrixCachedUniform(name, updateFrequency, value));
|
||||
}
|
||||
|
||||
|
||||
+6
-5
@@ -4,23 +4,24 @@ import net.coderbot.iris.gl.uniform.UniformUpdateFrequency;
|
||||
import net.coderbot.iris.parsing.VectorType;
|
||||
import org.joml.Vector3f;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import org.joml.Vector3fc;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class Float3VectorCachedUniform extends VectorCachedUniform<Vector3f> {
|
||||
public class Float3VectorCachedUniform extends VectorCachedUniform<Vector3fc> {
|
||||
|
||||
public Float3VectorCachedUniform(String name, UniformUpdateFrequency updateFrequency, Supplier<Vector3f> supplier) {
|
||||
public Float3VectorCachedUniform(String name, UniformUpdateFrequency updateFrequency, Supplier<Vector3fc> supplier) {
|
||||
super(name, updateFrequency, new Vector3f(), supplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setFrom(Vector3f other) {
|
||||
this.cached.set(other);
|
||||
protected void setFrom(Vector3fc other) {
|
||||
((Vector3f)this.cached).set(other);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void push(int location) {
|
||||
GLStateManager.glUniform3f(location, this.cached.x, this.cached.y, this.cached.z);
|
||||
GLStateManager.glUniform3f(location, this.cached.x(), this.cached.y(), this.cached.z());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+4
-3
@@ -4,21 +4,22 @@ import net.coderbot.iris.gl.uniform.UniformUpdateFrequency;
|
||||
import net.coderbot.iris.parsing.MatrixType;
|
||||
import org.joml.Matrix4f;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import org.joml.Matrix4fc;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class Float4MatrixCachedUniform extends VectorCachedUniform<Matrix4f> {
|
||||
public class Float4MatrixCachedUniform extends VectorCachedUniform<Matrix4fc> {
|
||||
final private FloatBuffer buffer = ByteBuffer.allocateDirect(16 << 2).order(ByteOrder.nativeOrder()).asFloatBuffer();
|
||||
|
||||
public Float4MatrixCachedUniform(String name, UniformUpdateFrequency updateFrequency, Supplier<Matrix4f> supplier) {
|
||||
public Float4MatrixCachedUniform(String name, UniformUpdateFrequency updateFrequency, Supplier<Matrix4fc> supplier) {
|
||||
super(name, updateFrequency, new Matrix4f(), supplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setFrom(Matrix4f other) {
|
||||
protected void setFrom(Matrix4fc other) {
|
||||
((Matrix4f) this.cached).set(other);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,23 +4,24 @@ import net.coderbot.iris.gl.uniform.UniformUpdateFrequency;
|
||||
import net.coderbot.iris.parsing.VectorType;
|
||||
import org.joml.Vector3i;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import org.joml.Vector3ic;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class Int3VectorCachedUniform extends VectorCachedUniform<Vector3i> {
|
||||
public class Int3VectorCachedUniform extends VectorCachedUniform<Vector3ic> {
|
||||
|
||||
public Int3VectorCachedUniform(String name, UniformUpdateFrequency updateFrequency, Supplier<Vector3i> supplier) {
|
||||
public Int3VectorCachedUniform(String name, UniformUpdateFrequency updateFrequency, Supplier<Vector3ic> supplier) {
|
||||
super(name, updateFrequency, new Vector3i(), supplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setFrom(Vector3i other) {
|
||||
this.cached.set(other);
|
||||
protected void setFrom(Vector3ic other) {
|
||||
((Vector3i)this.cached).set(other);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void push(int location) {
|
||||
GLStateManager.glUniform3i(location, this.cached.x, this.cached.y, this.cached.z);
|
||||
GLStateManager.glUniform3i(location, this.cached.x(), this.cached.y(), this.cached.z());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+4
-4
@@ -1,6 +1,7 @@
|
||||
package com.gtnewhorizons.angelica.mixins.early.angelica;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.config.ConfigurationManager;
|
||||
import com.gtnewhorizons.angelica.AngelicaMod;
|
||||
import com.gtnewhorizons.angelica.config.AngelicaConfig;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import net.minecraftforge.client.ForgeHooksClient;
|
||||
@@ -39,13 +40,12 @@ public abstract class MixinForgeHooksClient_CoreProfile {
|
||||
@Overwrite
|
||||
public static void createDisplay() throws LWJGLException {
|
||||
ImageIO.setUseCache(false);
|
||||
// Preserve vanilla Forge stencil support -- enabled via -Dforge.forceDisplayStencil=true by users/modpacks
|
||||
final boolean wantStencil = Boolean.parseBoolean(System.getProperty("forge.forceDisplayStencil", "false"));
|
||||
stencilBits = wantStencil ? 8 : 0;
|
||||
// Always enable 8-bit stencil, was an option before "-Dforge.forceDisplayStencil=true"
|
||||
stencilBits = 8;
|
||||
|
||||
final PixelFormat format = new PixelFormat().withDepthBits(24).withStencilBits(stencilBits);
|
||||
|
||||
final ContextAttribs attribs = new ContextAttribs(3, 3).withProfileCore(true).withForwardCompatible(true);
|
||||
final ContextAttribs attribs = new ContextAttribs(3, 3).withProfileCore(true).withForwardCompatible(true).withDebug(AngelicaMod.lwjglDebug);
|
||||
final MethodHandle setMajor, setMinor;
|
||||
try {
|
||||
final Field majorField = ContextAttribs.class.getDeclaredField("majorVersion");
|
||||
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
package com.gtnewhorizons.angelica.mixins.early.angelica.bugfixes;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import net.minecraft.client.renderer.ItemRenderer;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
/**
|
||||
* Fix enchantment glint z-fighting on held item edges using stencil masking.
|
||||
*
|
||||
* Vanilla uses GL_EQUAL to restrict the glint to item pixels, but GPU depth
|
||||
* non-determinism between draw calls causes GL_EQUAL to fail on edge quads.
|
||||
*
|
||||
* This mixin uses a stencil-based check instead of a GL_EQUAL check.
|
||||
* 1. During item render: write stencil value 1 wherever the item draws.
|
||||
* 2. During each glint renderItemIn2D call:
|
||||
* a. Pre-pass: no color/depth writes, GL_LEQUAL depth test, increment the stencil 1→2
|
||||
* where depth passes. This determines pixel ownership without corrupting the depth buffer (damn potions...)
|
||||
* b. Color pass: draw only where stencil == 2, GL_ALWAYS depth test, decrement the stencil
|
||||
* 2→1 to reset for the next glint pass.
|
||||
*/
|
||||
@Mixin(value = ItemRenderer.class, priority = 1100)
|
||||
public class MixinItemRenderer_EdgeDepth {
|
||||
|
||||
@Unique private static boolean angelica$glintMode = false;
|
||||
@Unique private static boolean angelica$inPrepass = false;
|
||||
|
||||
// Item render: write stencil value 1 at all visible item pixels
|
||||
|
||||
@Inject(
|
||||
method = "renderItem(Lnet/minecraft/entity/EntityLivingBase;Lnet/minecraft/item/ItemStack;ILnet/minecraftforge/client/IItemRenderer$ItemRenderType;)V",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/ItemRenderer;renderItemIn2D(Lnet/minecraft/client/renderer/Tessellator;FFFFIIF)V", ordinal = 0, remap = true),
|
||||
remap = false
|
||||
)
|
||||
private void angelica$stencilWriteStart(CallbackInfo ci) {
|
||||
GLStateManager.glEnable(GL11.GL_STENCIL_TEST);
|
||||
GLStateManager.glStencilMask(0xFF);
|
||||
GLStateManager.glClearStencil(0);
|
||||
GLStateManager.glClear(GL11.GL_STENCIL_BUFFER_BIT);
|
||||
GLStateManager.glStencilFunc(GL11.GL_ALWAYS, 1, 0xFF);
|
||||
GLStateManager.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_REPLACE);
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "renderItem(Lnet/minecraft/entity/EntityLivingBase;Lnet/minecraft/item/ItemStack;ILnet/minecraftforge/client/IItemRenderer$ItemRenderType;)V",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/ItemRenderer;renderItemIn2D(Lnet/minecraft/client/renderer/Tessellator;FFFFIIF)V", ordinal = 0, remap = true, shift = At.Shift.AFTER),
|
||||
remap = false
|
||||
)
|
||||
private void angelica$stencilWriteEnd(CallbackInfo ci) {
|
||||
GLStateManager.glStencilMask(0x00);
|
||||
GLStateManager.glDisable(GL11.GL_STENCIL_TEST);
|
||||
}
|
||||
|
||||
// Glint section: replace GL_EQUAL with stencil-based masking
|
||||
|
||||
@Redirect(
|
||||
method = "renderItem(Lnet/minecraft/entity/EntityLivingBase;Lnet/minecraft/item/ItemStack;ILnet/minecraftforge/client/IItemRenderer$ItemRenderType;)V",
|
||||
at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/GL11;glDepthFunc(I)V", ordinal = 0, remap = false),
|
||||
remap = false
|
||||
)
|
||||
private void angelica$glintStart(int func) {
|
||||
angelica$glintMode = true;
|
||||
GLStateManager.glEnable(GL11.GL_STENCIL_TEST);
|
||||
GLStateManager.glStencilFunc(GL11.GL_EQUAL, 1, 0xFF);
|
||||
GLStateManager.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP);
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "renderItem(Lnet/minecraft/entity/EntityLivingBase;Lnet/minecraft/item/ItemStack;ILnet/minecraftforge/client/IItemRenderer$ItemRenderType;)V",
|
||||
at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/GL11;glDepthFunc(I)V", ordinal = 1, remap = false),
|
||||
remap = false
|
||||
)
|
||||
private void angelica$glintEnd(int func) {
|
||||
angelica$glintMode = false;
|
||||
GLStateManager.glDepthFunc(GL11.GL_LEQUAL);
|
||||
GLStateManager.glDepthMask(true);
|
||||
GLStateManager.glDisable(GL11.GL_STENCIL_TEST);
|
||||
GLStateManager.glStencilMask(0xFF);
|
||||
}
|
||||
|
||||
// Stencil pre-pass inside renderItemIn2D when in glint mode
|
||||
|
||||
@WrapMethod(method = "renderItemIn2D")
|
||||
private static void angelica$glintPrepass(Tessellator tess, float minU, float minV, float maxU, float maxV,
|
||||
int w, int h, float thickness, Operation<Void> original) {
|
||||
if (!angelica$glintMode || angelica$inPrepass) {
|
||||
original.call(tess, minU, minV, maxU, maxV, w, h, thickness);
|
||||
return;
|
||||
}
|
||||
|
||||
angelica$inPrepass = true;
|
||||
|
||||
// Pre-pass: determine pixel ownership via GL_LEQUAL depth test.
|
||||
GLStateManager.glColorMask(false, false, false, false);
|
||||
GLStateManager.glDepthMask(false);
|
||||
GLStateManager.glDepthFunc(GL11.GL_LEQUAL);
|
||||
GLStateManager.glStencilMask(0xFF);
|
||||
GLStateManager.glStencilFunc(GL11.GL_EQUAL, 1, 0xFF);
|
||||
GLStateManager.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_INCR);
|
||||
original.call(tess, minU, minV, maxU, maxV, w, h, thickness);
|
||||
|
||||
// Color pass: draw only at pre-pass pixels.
|
||||
GLStateManager.glColorMask(true, true, true, true);
|
||||
GLStateManager.glStencilFunc(GL11.GL_EQUAL, 2, 0xFF);
|
||||
GLStateManager.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_DECR);
|
||||
GLStateManager.glDepthFunc(GL11.GL_ALWAYS);
|
||||
original.call(tess, minU, minV, maxU, maxV, w, h, thickness);
|
||||
|
||||
// Restore state for the next glint renderItemIn2D call
|
||||
GLStateManager.glStencilMask(0x00);
|
||||
GLStateManager.glStencilFunc(GL11.GL_EQUAL, 1, 0xFF);
|
||||
GLStateManager.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP);
|
||||
GLStateManager.glDepthFunc(GL11.GL_LEQUAL);
|
||||
|
||||
angelica$inPrepass = false;
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -24,7 +24,8 @@ public class MixinRendererLivingEntity_EyeDepth {
|
||||
method = "doRender(Lnet/minecraft/entity/EntityLivingBase;DDDFF)V",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/model/ModelBase;render(Lnet/minecraft/entity/Entity;FFFFFF)V"),
|
||||
slice = @Slice(
|
||||
from = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/entity/RendererLivingEntity;shouldRenderPass(Lnet/minecraft/entity/EntityLivingBase;IF)I")
|
||||
from = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/entity/RendererLivingEntity;shouldRenderPass(Lnet/minecraft/entity/EntityLivingBase;IF)I"),
|
||||
to = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/entity/RendererLivingEntity;renderEquippedItems(Lnet/minecraft/entity/EntityLivingBase;F)V")
|
||||
)
|
||||
)
|
||||
private void angelica$eyePassPolygonOffset(ModelBase instance, Entity entity, float a, float b, float c, float d, float e, float f, Operation<Void> original) {
|
||||
|
||||
+15
@@ -1,5 +1,6 @@
|
||||
package com.gtnewhorizons.angelica.mixins.early.celeritas.features.mipmaps;
|
||||
|
||||
import com.gtnewhorizons.angelica.config.AngelicaConfig;
|
||||
import com.gtnewhorizons.angelica.rendering.celeritas.SpriteExtension;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import org.embeddedt.embeddium.api.util.ColorABGR;
|
||||
@@ -29,9 +30,23 @@ public abstract class MixinTextureAtlasSprite implements SpriteExtension {
|
||||
if (this.framesTextureData.isEmpty() || this.framesTextureData.get(0) == null) {
|
||||
return;
|
||||
}
|
||||
if (celeritas$isAlwaysTranslucent(this.iconName)) {
|
||||
this.celeritas$transparencyLevel = SpriteTransparencyLevel.TRANSLUCENT;
|
||||
return;
|
||||
}
|
||||
celeritas$processTransparentImages(this.framesTextureData.get(0)[0], level > 0 && !iconName.contains("leaves"));
|
||||
}
|
||||
|
||||
@Unique
|
||||
private static boolean celeritas$isAlwaysTranslucent(String name) {
|
||||
final String[] list = AngelicaConfig.alwaysTranslucentSprites;
|
||||
if (list == null || list.length == 0) return false;
|
||||
for (String s : list) {
|
||||
if (name.equals(s)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ordinals: OPAQUE=0, TRANSPARENT=1, TRANSLUCENT=2
|
||||
@Unique private static final int ORDINAL_OPAQUE = SpriteTransparencyLevel.OPAQUE.ordinal();
|
||||
@Unique private static final int ORDINAL_TRANSPARENT = SpriteTransparencyLevel.TRANSPARENT.ordinal();
|
||||
|
||||
+249
@@ -0,0 +1,249 @@
|
||||
package com.gtnewhorizons.angelica.mixins.early.celeritas.light;
|
||||
|
||||
import com.gtnewhorizons.angelica.api.BlockLightProvider;
|
||||
import com.gtnewhorizons.angelica.api.ExtAoFaceData;
|
||||
import com.gtnewhorizons.angelica.api.ExtLightDataAccess;
|
||||
import com.gtnewhorizons.angelica.rendering.celeritas.compat.AoHelper;
|
||||
import org.embeddedt.embeddium.impl.model.light.data.LightDataAccess;
|
||||
import org.embeddedt.embeddium.impl.model.light.smooth.AoFaceData;
|
||||
import org.embeddedt.embeddium.impl.model.quad.properties.ModelQuadFacing;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(value = AoFaceData.class, remap = false)
|
||||
public class MixinAoFaceData implements ExtAoFaceData {
|
||||
|
||||
@Unique private final float[] angelica$rl = new float[4];
|
||||
@Unique private final float[] angelica$gl = new float[4];
|
||||
@Unique private final float[] angelica$bl = new float[4];
|
||||
@Unique private final float[] angelica$skyRl = new float[4];
|
||||
@Unique private final float[] angelica$skyGl = new float[4];
|
||||
@Unique private final float[] angelica$skyBl = new float[4];
|
||||
|
||||
@Override
|
||||
public float[] angelica$getRl() {
|
||||
return angelica$rl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float[] angelica$getGl() {
|
||||
return angelica$gl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float[] angelica$getBl() {
|
||||
return angelica$bl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float angelica$getBlendedR(float[] w) {
|
||||
return angelica$rl[0] * w[0] + angelica$rl[1] * w[1] + angelica$rl[2] * w[2] + angelica$rl[3] * w[3];
|
||||
}
|
||||
|
||||
@Override
|
||||
public float angelica$getBlendedG(float[] w) {
|
||||
return angelica$gl[0] * w[0] + angelica$gl[1] * w[1] + angelica$gl[2] * w[2] + angelica$gl[3] * w[3];
|
||||
}
|
||||
|
||||
@Override
|
||||
public float angelica$getBlendedB(float[] w) {
|
||||
return angelica$bl[0] * w[0] + angelica$bl[1] * w[1] + angelica$bl[2] * w[2] + angelica$bl[3] * w[3];
|
||||
}
|
||||
|
||||
@Override
|
||||
public float[] angelica$getSkyRl() {
|
||||
return angelica$skyRl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float[] angelica$getSkyGl() {
|
||||
return angelica$skyGl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float[] angelica$getSkyBl() {
|
||||
return angelica$skyBl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float angelica$getBlendedSkyR(float[] w) {
|
||||
return angelica$skyRl[0] * w[0] + angelica$skyRl[1] * w[1] + angelica$skyRl[2] * w[2] + angelica$skyRl[3] * w[3];
|
||||
}
|
||||
|
||||
@Override
|
||||
public float angelica$getBlendedSkyG(float[] w) {
|
||||
return angelica$skyGl[0] * w[0] + angelica$skyGl[1] * w[1] + angelica$skyGl[2] * w[2] + angelica$skyGl[3] * w[3];
|
||||
}
|
||||
|
||||
@Override
|
||||
public float angelica$getBlendedSkyB(float[] w) {
|
||||
return angelica$skyBl[0] * w[0] + angelica$skyBl[1] * w[1] + angelica$skyBl[2] * w[2] + angelica$skyBl[3] * w[3];
|
||||
}
|
||||
|
||||
@Inject(method = "initLightData", at = @At("TAIL"))
|
||||
private void angelica$initRGBData(LightDataAccess cache, int x, int y, int z, ModelQuadFacing direction, boolean offset, CallbackInfo ci) {
|
||||
final ExtLightDataAccess rgbCache = (ExtLightDataAccess) cache;
|
||||
final boolean doBlock = rgbCache.angelica$isRGBEnabled();
|
||||
final boolean doSky = rgbCache.angelica$isSkyRGBEnabled();
|
||||
if (!doBlock && !doSky) return;
|
||||
|
||||
final int adjX, adjY, adjZ;
|
||||
|
||||
if (offset) {
|
||||
adjX = x + direction.getStepX();
|
||||
adjY = y + direction.getStepY();
|
||||
adjZ = z + direction.getStepZ();
|
||||
} else {
|
||||
adjX = x;
|
||||
adjY = y;
|
||||
adjZ = z;
|
||||
}
|
||||
|
||||
final ModelQuadFacing[] faces = AoHelper.getFaces(direction);
|
||||
|
||||
// Edge opacity
|
||||
final boolean e0op = LightDataAccess.unpackOP(cache.get(adjX, adjY, adjZ, faces[0]));
|
||||
final boolean e1op = LightDataAccess.unpackOP(cache.get(adjX, adjY, adjZ, faces[1]));
|
||||
final boolean e2op = LightDataAccess.unpackOP(cache.get(adjX, adjY, adjZ, faces[2]));
|
||||
final boolean e3op = LightDataAccess.unpackOP(cache.get(adjX, adjY, adjZ, faces[3]));
|
||||
|
||||
// Center
|
||||
final int adjWord = cache.get(adjX, adjY, adjZ);
|
||||
final boolean useFallback = offset && LightDataAccess.unpackFO(adjWord);
|
||||
final int caX = useFallback ? x : adjX;
|
||||
final int caY = useFallback ? y : adjY;
|
||||
final int caZ = useFallback ? z : adjZ;
|
||||
final int caIdx = rgbCache.angelica$getIndex(caX, caY, caZ);
|
||||
|
||||
// Edge world coords
|
||||
final int e0x = adjX + faces[0].getStepX(), e0y = adjY + faces[0].getStepY(), e0z = adjZ + faces[0].getStepZ();
|
||||
final int e1x = adjX + faces[1].getStepX(), e1y = adjY + faces[1].getStepY(), e1z = adjZ + faces[1].getStepZ();
|
||||
final int e2x = adjX + faces[2].getStepX(), e2y = adjY + faces[2].getStepY(), e2z = adjZ + faces[2].getStepZ();
|
||||
final int e3x = adjX + faces[3].getStepX(), e3y = adjY + faces[3].getStepY(), e3z = adjZ + faces[3].getStepZ();
|
||||
|
||||
// Edge indices
|
||||
final int e0Idx = rgbCache.angelica$getIndex(e0x, e0y, e0z);
|
||||
final int e1Idx = rgbCache.angelica$getIndex(e1x, e1y, e1z);
|
||||
final int e2Idx = rgbCache.angelica$getIndex(e2x, e2y, e2z);
|
||||
final int e3Idx = rgbCache.angelica$getIndex(e3x, e3y, e3z);
|
||||
|
||||
// Corner world coords + indices; only compute if not occluded
|
||||
final int c0x, c0y, c0z, c0Idx;
|
||||
if (e2op && e0op) { c0x = c0y = c0z = c0Idx = 0; }
|
||||
else {
|
||||
c0x = e0x + faces[2].getStepX(); c0y = e0y + faces[2].getStepY(); c0z = e0z + faces[2].getStepZ();
|
||||
c0Idx = rgbCache.angelica$getIndex(c0x, c0y, c0z);
|
||||
}
|
||||
|
||||
final int c1x, c1y, c1z, c1Idx;
|
||||
if (e3op && e0op) { c1x = c1y = c1z = c1Idx = 0; }
|
||||
else {
|
||||
c1x = e0x + faces[3].getStepX(); c1y = e0y + faces[3].getStepY(); c1z = e0z + faces[3].getStepZ();
|
||||
c1Idx = rgbCache.angelica$getIndex(c1x, c1y, c1z);
|
||||
}
|
||||
|
||||
final int c2x, c2y, c2z, c2Idx;
|
||||
if (e2op && e1op) { c2x = c2y = c2z = c2Idx = 0; }
|
||||
else {
|
||||
c2x = e1x + faces[2].getStepX(); c2y = e1y + faces[2].getStepY(); c2z = e1z + faces[2].getStepZ();
|
||||
c2Idx = rgbCache.angelica$getIndex(c2x, c2y, c2z);
|
||||
}
|
||||
|
||||
final int c3x, c3y, c3z, c3Idx;
|
||||
if (e3op && e1op) { c3x = c3y = c3z = c3Idx = 0; }
|
||||
else {
|
||||
c3x = e1x + faces[3].getStepX(); c3y = e1y + faces[3].getStepY(); c3z = e1z + faces[3].getStepZ();
|
||||
c3Idx = rgbCache.angelica$getIndex(c3x, c3y, c3z);
|
||||
}
|
||||
|
||||
final long caF = rgbCache.angelica$getFusedByIndex(caIdx, caX, caY, caZ);
|
||||
final long e0F = rgbCache.angelica$getFusedByIndex(e0Idx, e0x, e0y, e0z);
|
||||
final long e1F = rgbCache.angelica$getFusedByIndex(e1Idx, e1x, e1y, e1z);
|
||||
final long e2F = rgbCache.angelica$getFusedByIndex(e2Idx, e2x, e2y, e2z);
|
||||
final long e3F = rgbCache.angelica$getFusedByIndex(e3Idx, e3x, e3y, e3z);
|
||||
final long c0F = (e2op && e0op) ? e0F : rgbCache.angelica$getFusedByIndex(c0Idx, c0x, c0y, c0z);
|
||||
final long c1F = (e3op && e0op) ? e0F : rgbCache.angelica$getFusedByIndex(c1Idx, c1x, c1y, c1z);
|
||||
final long c2F = (e2op && e1op) ? e1F : rgbCache.angelica$getFusedByIndex(c2Idx, c2x, c2y, c2z);
|
||||
final long c3F = (e3op && e1op) ? e1F : rgbCache.angelica$getFusedByIndex(c3Idx, c3x, c3y, c3z);
|
||||
|
||||
if (doBlock) {
|
||||
final int caRGB = (int)(caF >>> 32);
|
||||
final int e0RGB = (int)(e0F >>> 32);
|
||||
final int e1RGB = (int)(e1F >>> 32);
|
||||
final int e2RGB = (int)(e2F >>> 32);
|
||||
final int e3RGB = (int)(e3F >>> 32);
|
||||
final int c0RGB = (int)(c0F >>> 32);
|
||||
final int c1RGB = (int)(c1F >>> 32);
|
||||
final int c2RGB = (int)(c2F >>> 32);
|
||||
final int c3RGB = (int)(c3F >>> 32);
|
||||
|
||||
final int caR = BlockLightProvider.unpackR(caRGB), caG = BlockLightProvider.unpackG(caRGB), caB = BlockLightProvider.unpackB(caRGB);
|
||||
final int e0R = BlockLightProvider.unpackR(e0RGB), e0G = BlockLightProvider.unpackG(e0RGB), e0B = BlockLightProvider.unpackB(e0RGB);
|
||||
final int e1R = BlockLightProvider.unpackR(e1RGB), e1G = BlockLightProvider.unpackG(e1RGB), e1B = BlockLightProvider.unpackB(e1RGB);
|
||||
final int e2R = BlockLightProvider.unpackR(e2RGB), e2G = BlockLightProvider.unpackG(e2RGB), e2B = BlockLightProvider.unpackB(e2RGB);
|
||||
final int e3R = BlockLightProvider.unpackR(e3RGB), e3G = BlockLightProvider.unpackG(e3RGB), e3B = BlockLightProvider.unpackB(e3RGB);
|
||||
final int c0R = BlockLightProvider.unpackR(c0RGB), c0G = BlockLightProvider.unpackG(c0RGB), c0B = BlockLightProvider.unpackB(c0RGB);
|
||||
final int c1R = BlockLightProvider.unpackR(c1RGB), c1G = BlockLightProvider.unpackG(c1RGB), c1B = BlockLightProvider.unpackB(c1RGB);
|
||||
final int c2R = BlockLightProvider.unpackR(c2RGB), c2G = BlockLightProvider.unpackG(c2RGB), c2B = BlockLightProvider.unpackB(c2RGB);
|
||||
final int c3R = BlockLightProvider.unpackR(c3RGB), c3G = BlockLightProvider.unpackG(c3RGB), c3B = BlockLightProvider.unpackB(c3RGB);
|
||||
|
||||
angelica$rl[0] = (e3R + e0R + c1R + caR) * 0.25f;
|
||||
angelica$gl[0] = (e3G + e0G + c1G + caG) * 0.25f;
|
||||
angelica$bl[0] = (e3B + e0B + c1B + caB) * 0.25f;
|
||||
|
||||
angelica$rl[1] = (e2R + e0R + c0R + caR) * 0.25f;
|
||||
angelica$gl[1] = (e2G + e0G + c0G + caG) * 0.25f;
|
||||
angelica$bl[1] = (e2B + e0B + c0B + caB) * 0.25f;
|
||||
|
||||
angelica$rl[2] = (e2R + e1R + c2R + caR) * 0.25f;
|
||||
angelica$gl[2] = (e2G + e1G + c2G + caG) * 0.25f;
|
||||
angelica$bl[2] = (e2B + e1B + c2B + caB) * 0.25f;
|
||||
|
||||
angelica$rl[3] = (e3R + e1R + c3R + caR) * 0.25f;
|
||||
angelica$gl[3] = (e3G + e1G + c3G + caG) * 0.25f;
|
||||
angelica$bl[3] = (e3B + e1B + c3B + caB) * 0.25f;
|
||||
}
|
||||
|
||||
if (doSky) {
|
||||
final int caSky = (int)(caF & 0xFFFFFFFFL);
|
||||
final int e0Sky = (int)(e0F & 0xFFFFFFFFL);
|
||||
final int e1Sky = (int)(e1F & 0xFFFFFFFFL);
|
||||
final int e2Sky = (int)(e2F & 0xFFFFFFFFL);
|
||||
final int e3Sky = (int)(e3F & 0xFFFFFFFFL);
|
||||
final int c0Sky = (int)(c0F & 0xFFFFFFFFL);
|
||||
final int c1Sky = (int)(c1F & 0xFFFFFFFFL);
|
||||
final int c2Sky = (int)(c2F & 0xFFFFFFFFL);
|
||||
final int c3Sky = (int)(c3F & 0xFFFFFFFFL);
|
||||
|
||||
final int caR = BlockLightProvider.unpackR(caSky), caG = BlockLightProvider.unpackG(caSky), caB = BlockLightProvider.unpackB(caSky);
|
||||
final int e0R = BlockLightProvider.unpackR(e0Sky), e0G = BlockLightProvider.unpackG(e0Sky), e0B = BlockLightProvider.unpackB(e0Sky);
|
||||
final int e1R = BlockLightProvider.unpackR(e1Sky), e1G = BlockLightProvider.unpackG(e1Sky), e1B = BlockLightProvider.unpackB(e1Sky);
|
||||
final int e2R = BlockLightProvider.unpackR(e2Sky), e2G = BlockLightProvider.unpackG(e2Sky), e2B = BlockLightProvider.unpackB(e2Sky);
|
||||
final int e3R = BlockLightProvider.unpackR(e3Sky), e3G = BlockLightProvider.unpackG(e3Sky), e3B = BlockLightProvider.unpackB(e3Sky);
|
||||
final int c0R = BlockLightProvider.unpackR(c0Sky), c0G = BlockLightProvider.unpackG(c0Sky), c0B = BlockLightProvider.unpackB(c0Sky);
|
||||
final int c1R = BlockLightProvider.unpackR(c1Sky), c1G = BlockLightProvider.unpackG(c1Sky), c1B = BlockLightProvider.unpackB(c1Sky);
|
||||
final int c2R = BlockLightProvider.unpackR(c2Sky), c2G = BlockLightProvider.unpackG(c2Sky), c2B = BlockLightProvider.unpackB(c2Sky);
|
||||
final int c3R = BlockLightProvider.unpackR(c3Sky), c3G = BlockLightProvider.unpackG(c3Sky), c3B = BlockLightProvider.unpackB(c3Sky);
|
||||
|
||||
angelica$skyRl[0] = (e3R + e0R + c1R + caR) * 0.25f;
|
||||
angelica$skyGl[0] = (e3G + e0G + c1G + caG) * 0.25f;
|
||||
angelica$skyBl[0] = (e3B + e0B + c1B + caB) * 0.25f;
|
||||
|
||||
angelica$skyRl[1] = (e2R + e0R + c0R + caR) * 0.25f;
|
||||
angelica$skyGl[1] = (e2G + e0G + c0G + caG) * 0.25f;
|
||||
angelica$skyBl[1] = (e2B + e0B + c0B + caB) * 0.25f;
|
||||
|
||||
angelica$skyRl[2] = (e2R + e1R + c2R + caR) * 0.25f;
|
||||
angelica$skyGl[2] = (e2G + e1G + c2G + caG) * 0.25f;
|
||||
angelica$skyBl[2] = (e2B + e1B + c2B + caB) * 0.25f;
|
||||
|
||||
angelica$skyRl[3] = (e3R + e1R + c3R + caR) * 0.25f;
|
||||
angelica$skyGl[3] = (e3G + e1G + c3G + caG) * 0.25f;
|
||||
angelica$skyBl[3] = (e3B + e1B + c3B + caB) * 0.25f;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
package com.gtnewhorizons.angelica.mixins.early.celeritas.light;
|
||||
|
||||
import com.gtnewhorizons.angelica.api.BlockLightProvider;
|
||||
import com.gtnewhorizons.angelica.api.ExtLightDataAccess;
|
||||
import com.gtnewhorizons.angelica.api.ExtQuadLightData;
|
||||
import org.embeddedt.embeddium.impl.model.light.data.LightDataAccess;
|
||||
import org.embeddedt.embeddium.impl.model.light.data.QuadLightData;
|
||||
import org.embeddedt.embeddium.impl.model.light.flat.FlatLightPipeline;
|
||||
import org.embeddedt.embeddium.impl.model.quad.ModelQuadView;
|
||||
import org.embeddedt.embeddium.impl.model.quad.properties.ModelQuadFacing;
|
||||
import org.embeddedt.embeddium.impl.model.quad.properties.ModelQuadFlags;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(value = FlatLightPipeline.class, remap = false)
|
||||
public class MixinFlatLightPipeline {
|
||||
|
||||
@Shadow @Final private LightDataAccess lightCache;
|
||||
|
||||
@Inject(method = "calculate", at = @At("TAIL"))
|
||||
private void angelica$populateRGBFlat(ModelQuadView quad, int x, int y, int z, QuadLightData out, ModelQuadFacing cullFace, ModelQuadFacing lightFace, boolean shade, boolean applyAoDepthBlending, CallbackInfo ci) {
|
||||
final ExtLightDataAccess rgbCache = (ExtLightDataAccess) this.lightCache;
|
||||
final ExtQuadLightData outExt = (ExtQuadLightData) out;
|
||||
|
||||
final boolean blockEnabled = rgbCache.angelica$isRGBEnabled();
|
||||
final boolean skyEnabled = rgbCache.angelica$isSkyRGBEnabled();
|
||||
|
||||
if (!blockEnabled && !skyEnabled) {
|
||||
outExt.angelica$setRGBValid(false);
|
||||
outExt.angelica$setSkyRGBValid(false);
|
||||
return;
|
||||
}
|
||||
|
||||
final int lx, ly, lz;
|
||||
if (cullFace.isDirection()) {
|
||||
lx = x + cullFace.getStepX();
|
||||
ly = y + cullFace.getStepY();
|
||||
lz = z + cullFace.getStepZ();
|
||||
} else {
|
||||
final int flags = quad.getFlags();
|
||||
if ((flags & ModelQuadFlags.IS_ALIGNED) != 0 || ((flags & ModelQuadFlags.IS_PARALLEL) != 0 && LightDataAccess.unpackFC(this.lightCache.get(x, y, z)))) {
|
||||
lx = x + lightFace.getStepX();
|
||||
ly = y + lightFace.getStepY();
|
||||
lz = z + lightFace.getStepZ();
|
||||
} else {
|
||||
lx = x;
|
||||
ly = y;
|
||||
lz = z;
|
||||
}
|
||||
}
|
||||
|
||||
// Block RGB
|
||||
if (blockEnabled) {
|
||||
final int rgb = rgbCache.angelica$getRGB(lx, ly, lz);
|
||||
final float r = BlockLightProvider.unpackR(rgb), g = BlockLightProvider.unpackG(rgb), b = BlockLightProvider.unpackB(rgb);
|
||||
final float[] ra = outExt.angelica$getR(), ga = outExt.angelica$getG(), ba = outExt.angelica$getB();
|
||||
ra[0] = ra[1] = ra[2] = ra[3] = r;
|
||||
ga[0] = ga[1] = ga[2] = ga[3] = g;
|
||||
ba[0] = ba[1] = ba[2] = ba[3] = b;
|
||||
outExt.angelica$setRGBValid(true);
|
||||
} else {
|
||||
outExt.angelica$setRGBValid(false);
|
||||
}
|
||||
|
||||
// Sky RGB
|
||||
if (skyEnabled) {
|
||||
final int skyRgb = rgbCache.angelica$getSkyRGB(lx, ly, lz);
|
||||
final float r = BlockLightProvider.unpackR(skyRgb), g = BlockLightProvider.unpackG(skyRgb), b = BlockLightProvider.unpackB(skyRgb);
|
||||
final float[] ra = outExt.angelica$getSkyR(), ga = outExt.angelica$getSkyG(), ba = outExt.angelica$getSkyB();
|
||||
ra[0] = ra[1] = ra[2] = ra[3] = r;
|
||||
ga[0] = ga[1] = ga[2] = ga[3] = g;
|
||||
ba[0] = ba[1] = ba[2] = ba[3] = b;
|
||||
outExt.angelica$setSkyRGBValid(true);
|
||||
} else {
|
||||
outExt.angelica$setSkyRGBValid(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
+215
@@ -0,0 +1,215 @@
|
||||
package com.gtnewhorizons.angelica.mixins.early.celeritas.light;
|
||||
|
||||
import com.gtnewhorizons.angelica.api.BlockLightProvider;
|
||||
import com.gtnewhorizons.angelica.api.ExtLightDataAccess;
|
||||
import com.gtnewhorizons.angelica.api.ExtLightDataCache;
|
||||
import com.gtnewhorizons.angelica.api.SectionLightData;
|
||||
import com.gtnewhorizons.angelica.dynamiclights.DynamicLights;
|
||||
import com.gtnewhorizons.angelica.rendering.celeritas.world.WorldSlice;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import org.embeddedt.embeddium.impl.model.light.data.LightDataAccess;
|
||||
import org.embeddedt.embeddium.impl.model.quad.properties.ModelQuadFacing;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@Mixin(value = LightDataAccess.class, remap = false)
|
||||
public abstract class MixinLightDataAccess implements ExtLightDataAccess {
|
||||
|
||||
@Unique private static final int ANGELICA$CACHE_SIZE = 20 * 20 * 20;
|
||||
@Unique private static final int ANGELICA$SENTINEL = 0x1000;
|
||||
|
||||
@Shadow
|
||||
private int index(int x, int y, int z) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
/** Fused cache: upper 32 bits = block RGB word, lower 32 bits = sky RGB word. Zero = uncached. */
|
||||
@Unique private long[] angelica$fusedLight;
|
||||
|
||||
@Unique private boolean angelica$rgbEnabled;
|
||||
|
||||
@Unique private boolean angelica$skyRgbEnabled;
|
||||
|
||||
@Unique private BlockLightProvider angelica$provider;
|
||||
|
||||
@Unique private IBlockAccess angelica$blockAccess;
|
||||
|
||||
@Inject(method = "reset", at = @At("TAIL"))
|
||||
private void angelica$resetRGB(int minBlockX, int minBlockY, int minBlockZ, CallbackInfo ci) {
|
||||
angelica$rgbEnabled = BlockLightProvider.isRegistered();
|
||||
angelica$provider = BlockLightProvider.getInstance();
|
||||
angelica$blockAccess = ((ExtLightDataCache) this).angelica$getBlockAccess();
|
||||
angelica$skyRgbEnabled = angelica$rgbEnabled;
|
||||
if (angelica$rgbEnabled) {
|
||||
if (angelica$fusedLight == null) {
|
||||
angelica$fusedLight = new long[ANGELICA$CACHE_SIZE];
|
||||
} else {
|
||||
Arrays.fill(angelica$fusedLight, 0L);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int angelica$getRGB(int x, int y, int z) {
|
||||
if (!angelica$rgbEnabled) return 0;
|
||||
final int idx = this.index(x, y, z);
|
||||
return angelica$getBlockFromFused(idx, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int angelica$getRGB(int x, int y, int z, ModelQuadFacing dir) {
|
||||
return angelica$getRGB(
|
||||
x + dir.getStepX(),
|
||||
y + dir.getStepY(),
|
||||
z + dir.getStepZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int angelica$getRGB(int x, int y, int z, ModelQuadFacing d1, ModelQuadFacing d2) {
|
||||
return angelica$getRGB(
|
||||
x + d1.getStepX() + d2.getStepX(),
|
||||
y + d1.getStepY() + d2.getStepY(),
|
||||
z + d1.getStepZ() + d2.getStepZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean angelica$isRGBEnabled() {
|
||||
return angelica$rgbEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int angelica$getSkyRGB(int x, int y, int z) {
|
||||
if (!angelica$skyRgbEnabled) return 0;
|
||||
final int idx = this.index(x, y, z);
|
||||
return angelica$getSkyFromFused(idx, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int angelica$getSkyRGB(int x, int y, int z, ModelQuadFacing dir) {
|
||||
return angelica$getSkyRGB(
|
||||
x + dir.getStepX(),
|
||||
y + dir.getStepY(),
|
||||
z + dir.getStepZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int angelica$getSkyRGB(int x, int y, int z, ModelQuadFacing d1, ModelQuadFacing d2) {
|
||||
return angelica$getSkyRGB(
|
||||
x + d1.getStepX() + d2.getStepX(),
|
||||
y + d1.getStepY() + d2.getStepY(),
|
||||
z + d1.getStepZ() + d2.getStepZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean angelica$isSkyRGBEnabled() {
|
||||
return angelica$skyRgbEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int angelica$getIndex(int x, int y, int z) {
|
||||
return this.index(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int angelica$getRGBByIndex(int idx, int x, int y, int z) {
|
||||
if (!angelica$rgbEnabled) return 0;
|
||||
return angelica$getBlockFromFused(idx, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int angelica$getSkyRGBByIndex(int idx, int x, int y, int z) {
|
||||
if (!angelica$skyRgbEnabled) return 0;
|
||||
return angelica$getSkyFromFused(idx, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long angelica$getFusedByIndex(int idx, int x, int y, int z) {
|
||||
long fused = angelica$fusedLight[idx];
|
||||
if (fused == 0L) {
|
||||
fused = angelica$fusedLight[idx] = angelica$computeFused(x, y, z);
|
||||
}
|
||||
return fused;
|
||||
}
|
||||
|
||||
@Unique
|
||||
private int angelica$getBlockFromFused(int idx, int x, int y, int z) {
|
||||
long fused = angelica$fusedLight[idx];
|
||||
if (fused == 0L) {
|
||||
fused = angelica$fusedLight[idx] = angelica$computeFused(x, y, z);
|
||||
}
|
||||
return (int)(fused >>> 32);
|
||||
}
|
||||
|
||||
@Unique
|
||||
private int angelica$getSkyFromFused(int idx, int x, int y, int z) {
|
||||
long fused = angelica$fusedLight[idx];
|
||||
if (fused == 0L) {
|
||||
fused = angelica$fusedLight[idx] = angelica$computeFused(x, y, z);
|
||||
}
|
||||
return (int)(fused & 0xFFFFFFFFL);
|
||||
}
|
||||
|
||||
@Unique
|
||||
private long angelica$computeFused(int x, int y, int z) {
|
||||
final IBlockAccess blockAccess = angelica$blockAccess;
|
||||
|
||||
if (blockAccess instanceof WorldSlice ws) {
|
||||
int blockRGB = 0xFFFF; // sentinel: no data
|
||||
int skyRGB = 0xFFFF;
|
||||
|
||||
final SectionLightData data = ws.getSectionLightData(x, y, z);
|
||||
if (data != null) {
|
||||
final long fused = data.getRGBAndSkyRGB(x & 15, y & 15, z & 15);
|
||||
blockRGB = (int)(fused >>> 16) & 0xFFFF;
|
||||
skyRGB = (int)fused & 0xFFFF;
|
||||
}
|
||||
|
||||
// Overlay dynamic light RGB (thread-safe: uses pre-filtered chunk-local sources)
|
||||
final var dlSources = ws.getChunkLightSources();
|
||||
if (dlSources != null && !dlSources.isEmpty()) {
|
||||
final int dlRGB = ws.getDynamicLightsInstance()
|
||||
.getDynamicLightRGBFromSources(x + 0.5, y + 0.5, z + 0.5, dlSources);
|
||||
if (dlRGB != 0) {
|
||||
blockRGB = angelica$mergeMaxRGB(blockRGB, dlRGB);
|
||||
}
|
||||
}
|
||||
|
||||
final long blockWord = (blockRGB == 0xFFFF) ? ANGELICA$SENTINEL : (blockRGB | ANGELICA$SENTINEL);
|
||||
final long skyWord = (skyRGB == 0xFFFF) ? ANGELICA$SENTINEL : (skyRGB | ANGELICA$SENTINEL);
|
||||
return (blockWord << 32) | (skyWord & 0xFFFFFFFFL);
|
||||
}
|
||||
|
||||
final BlockLightProvider provider = angelica$provider;
|
||||
int brgb = provider.getBlockLightRGB(blockAccess, x, y, z);
|
||||
final int srgb = provider.getSkyLightRGB(blockAccess, x, y, z);
|
||||
|
||||
if (DynamicLights.isEnabled()) {
|
||||
final int dlRGB = DynamicLights.get().getDynamicLightRGB(x + 0.5, y + 0.5, z + 0.5);
|
||||
if (dlRGB != 0) {
|
||||
brgb = angelica$mergeMaxRGB(brgb, dlRGB);
|
||||
}
|
||||
}
|
||||
|
||||
final long blockWord = (brgb == -1) ? ANGELICA$SENTINEL : (brgb | ANGELICA$SENTINEL);
|
||||
final long skyWord = (srgb == -1) ? ANGELICA$SENTINEL : (srgb | ANGELICA$SENTINEL);
|
||||
return (blockWord << 32) | (skyWord & 0xFFFFFFFFL);
|
||||
}
|
||||
|
||||
/** Max-per-channel merge. Treats sentinel (0xFFFF or -1) as (0,0,0). */
|
||||
@Unique
|
||||
private static int angelica$mergeMaxRGB(int staticRGB, int dynamicRGB) {
|
||||
final int sR = (staticRGB == 0xFFFF || staticRGB == -1) ? 0 : BlockLightProvider.unpackR(staticRGB);
|
||||
final int sG = (staticRGB == 0xFFFF || staticRGB == -1) ? 0 : BlockLightProvider.unpackG(staticRGB);
|
||||
final int sB = (staticRGB == 0xFFFF || staticRGB == -1) ? 0 : BlockLightProvider.unpackB(staticRGB);
|
||||
return BlockLightProvider.packRGB(
|
||||
Math.max(sR, BlockLightProvider.unpackR(dynamicRGB)),
|
||||
Math.max(sG, BlockLightProvider.unpackG(dynamicRGB)),
|
||||
Math.max(sB, BlockLightProvider.unpackB(dynamicRGB)));
|
||||
}
|
||||
}
|
||||
Loaded 100 of 105 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user