mirror of
https://github.com/GTNewHorizons/Angelica.git
synced 2026-11-15 01:34:48 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
03d908d658 | ||
|
|
76bf19c8f6 | ||
|
|
b27834cbd9 | ||
|
|
eb0ecb0483 | ||
|
|
9acb0e67a7 | ||
|
|
f4f9b56b17 | ||
|
|
2196439e6c | ||
|
|
dd68c64239 | ||
|
|
0decc515e4 |
No files matched your search
@@ -23,7 +23,7 @@ Targets GL 3.3+ core profile
|
||||
|
||||
# Required Dependencies
|
||||
* [UniMixins](https://github.com/LegacyModdingMC/UniMixins/releases) >= 0.1.23
|
||||
* [GTNHLib](https://github.com/GTNewHorizons/GTNHLib/releases) >= 0.9.0
|
||||
* [GTNHLib](https://github.com/GTNewHorizons/GTNHLib/releases) >= 0.11.19
|
||||
* NOTE: Some mods are not required, but a specific version is required if present - see: `Permanent Incompatibilities` below.
|
||||
|
||||
# Known (temporary) Incompatibilities
|
||||
|
||||
+4
-1
@@ -76,7 +76,7 @@ dependencies {
|
||||
|
||||
// Iris Shaders
|
||||
compileOnly('org.jetbrains:annotations:26.0.2')
|
||||
api("com.github.GTNewHorizons:GTNHLib:0.11.4:dev")
|
||||
api("com.github.GTNewHorizons:GTNHLib:0.11.19:dev")
|
||||
|
||||
shadowImplementation(project(":glsm")) { transitive = false }
|
||||
shadowImplementation(project(":lwjgl3-backend")) { transitive = false }
|
||||
@@ -173,6 +173,9 @@ dependencies {
|
||||
testImplementation('org.junit.platform:junit-platform-launcher')
|
||||
|
||||
testImplementation('com.tngtech.archunit:archunit-junit5:1.4.1')
|
||||
|
||||
testRuntimeOnly("it.unimi.dsi:fastutil:8.5.18")
|
||||
testRuntimeOnly("org.joml:joml:1.10.8")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -96,6 +96,8 @@ dependencies {
|
||||
// Deps (normally from MC) - compile only, but needed at test runtime
|
||||
compileOnly("com.google.guava:guava:${property("guavaVersion")}")
|
||||
testRuntimeOnly("com.google.guava:guava:${property("guavaVersion")}")
|
||||
testRuntimeOnly("it.unimi.dsi:fastutil:${property("fastutilVersion")}")
|
||||
testRuntimeOnly("org.joml:joml:${property("jomlVersion")}") { isTransitive = false }
|
||||
|
||||
// Test
|
||||
testImplementation(sourceSets["stubs"].output)
|
||||
|
||||
@@ -4,7 +4,9 @@ celeritasVersion = 2.5.3-GTNH
|
||||
lombokVersion = 1.18.42
|
||||
log4jVersion = 2.0-beta9
|
||||
guavaVersion = 18.0
|
||||
gtnhlibVersion = 0.10.0
|
||||
gtnhlibVersion = 0.11.19
|
||||
fastutilVersion = 8.5.18
|
||||
jomlVersion = 1.10.8
|
||||
glslTransformLibVersion = 0.2.0-26.g5ee7d96-GTNH
|
||||
antlr4RuntimeVersion = 4.13.2
|
||||
jcppVersion = 1.4.14
|
||||
|
||||
@@ -16,6 +16,7 @@ import com.gtnewhorizons.angelica.glsm.hooks.DeferredDepthColorHandler;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.GLSMConfig;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.GLSMHooks;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.GLSMInitConfig;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.GlintColorHandler;
|
||||
import com.gtnewhorizons.angelica.glsm.recording.CommandRecorder;
|
||||
import com.gtnewhorizons.angelica.glsm.recording.CompiledDisplayList;
|
||||
import com.gtnewhorizons.angelica.glsm.recording.ImmediateModeRecorder;
|
||||
@@ -187,6 +188,14 @@ public class GLStateManager {
|
||||
private static boolean dirtyTexCoordAttrib;
|
||||
private static boolean dirtyLightmapAttrib = true;
|
||||
|
||||
private static boolean unit23TexCoordSetDuringDraw = false;
|
||||
|
||||
public static boolean consumeUnit23TexCoordSetDuringDraw() {
|
||||
boolean v = unit23TexCoordSetDuringDraw;
|
||||
unit23TexCoordSetDuringDraw = false;
|
||||
return v;
|
||||
}
|
||||
|
||||
// vertexFlags bits mark attribs the VBO already supplies; FFP supplies the rest via u_Current* uniforms.
|
||||
// Skip the backend vertexAttrib call in either case.
|
||||
public static void flushDeferredVertexAttribs(boolean hasColor, boolean hasNormal, boolean hasTexCoord, boolean hasLightmap) {
|
||||
@@ -1605,6 +1614,11 @@ public class GLStateManager {
|
||||
ImmediateModeRecorder.setColor(red, green, blue, alpha);
|
||||
}
|
||||
dirtyColorAttrib = true;
|
||||
// Only set while an enchantment-glint span is active
|
||||
final GlintColorHandler glintHandler = GLSMHooks.glintColorHandler;
|
||||
if (glintHandler != null) {
|
||||
glintHandler.onColorChanged(red, green, blue, alpha);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -2158,6 +2172,7 @@ public class GLStateManager {
|
||||
}
|
||||
|
||||
public static void glBegin(int mode) {
|
||||
unit23TexCoordSetDuringDraw = false;
|
||||
if (DisplayListManager.isRecording()) {
|
||||
ImmediateModeRecorder.begin(mode);
|
||||
return;
|
||||
@@ -5325,6 +5340,9 @@ public class GLStateManager {
|
||||
} else {
|
||||
final int unit = target - GL13.GL_TEXTURE0;
|
||||
if (unit >= 2 && unit < 4) {
|
||||
if (DisplayListManager.isRecording() || ImmediateModeRecorder.isDrawing()) {
|
||||
unit23TexCoordSetDuringDraw = true;
|
||||
}
|
||||
ShaderManager.setCurrentTexCoord(unit, s, t, 0.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
@@ -6030,15 +6048,15 @@ public class GLStateManager {
|
||||
}
|
||||
|
||||
public static void glUniform1(int location, IntBuffer values) {
|
||||
if (values.remaining() >= 1) RENDER_BACKEND.uniform1i(location, values.get(values.position()));
|
||||
RENDER_BACKEND.uniform1iv(location, values);
|
||||
}
|
||||
|
||||
public static void glUniform2(int location, FloatBuffer values) {
|
||||
if (values.remaining() >= 2) RENDER_BACKEND.uniform2f(location, values.get(values.position()), values.get(values.position() + 1));
|
||||
RENDER_BACKEND.uniform2(location, values);
|
||||
}
|
||||
|
||||
public static void glUniform2(int location, IntBuffer values) {
|
||||
if (values.remaining() >= 2) RENDER_BACKEND.uniform2i(location, values.get(values.position()), values.get(values.position() + 1));
|
||||
RENDER_BACKEND.uniform2iv(location, values);
|
||||
}
|
||||
|
||||
public static void glUniform3(int location, FloatBuffer values) {
|
||||
@@ -6046,7 +6064,7 @@ public class GLStateManager {
|
||||
}
|
||||
|
||||
public static void glUniform3(int location, IntBuffer values) {
|
||||
if (values.remaining() >= 3) RENDER_BACKEND.uniform3i(location, values.get(values.position()), values.get(values.position() + 1), values.get(values.position() + 2));
|
||||
RENDER_BACKEND.uniform3iv(location, values);
|
||||
}
|
||||
|
||||
public static void glUniform4(int location, FloatBuffer values) {
|
||||
@@ -6054,7 +6072,7 @@ public class GLStateManager {
|
||||
}
|
||||
|
||||
public static void glUniform4(int location, IntBuffer values) {
|
||||
if (values.remaining() >= 4) RENDER_BACKEND.uniform4i(location, values.get(values.position()), values.get(values.position() + 1), values.get(values.position() + 2), values.get(values.position() + 3));
|
||||
RENDER_BACKEND.uniform4iv(location, values);
|
||||
}
|
||||
|
||||
public static void glUniformMatrix2(int location, boolean transpose, FloatBuffer matrices) {
|
||||
|
||||
@@ -822,6 +822,11 @@ public final class Lwjgl2GLRenderBackend extends RenderBackend {
|
||||
GL20.glUniform4i(location, v0, v1, v2, v3);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uniform2(int location, FloatBuffer value) {
|
||||
GL20.glUniform2(location, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uniform3(int location, FloatBuffer value) {
|
||||
GL20.glUniform3(location, value);
|
||||
@@ -832,6 +837,26 @@ public final class Lwjgl2GLRenderBackend extends RenderBackend {
|
||||
GL20.glUniform4(location, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uniform1iv(int location, IntBuffer value) {
|
||||
GL20.glUniform1(location, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uniform2iv(int location, IntBuffer value) {
|
||||
GL20.glUniform2(location, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uniform3iv(int location, IntBuffer value) {
|
||||
GL20.glUniform3(location, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uniform4iv(int location, IntBuffer value) {
|
||||
GL20.glUniform4(location, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uniformMatrix3(int location, boolean transpose, FloatBuffer value) {
|
||||
GL20.glUniformMatrix3(location, transpose, value);
|
||||
|
||||
@@ -201,8 +201,13 @@ public abstract class RenderBackend {
|
||||
public abstract void uniform3i(int location, int v0, int v1, int v2);
|
||||
public abstract void uniform4f(int location, float v0, float v1, float v2, float v3);
|
||||
public abstract void uniform4i(int location, int v0, int v1, int v2, int v3);
|
||||
public abstract void uniform2(int location, FloatBuffer value);
|
||||
public abstract void uniform3(int location, FloatBuffer value);
|
||||
public abstract void uniform4(int location, FloatBuffer value);
|
||||
public abstract void uniform1iv(int location, IntBuffer value);
|
||||
public abstract void uniform2iv(int location, IntBuffer value);
|
||||
public abstract void uniform3iv(int location, IntBuffer value);
|
||||
public abstract void uniform4iv(int location, IntBuffer value);
|
||||
public abstract void uniformMatrix3(int location, boolean transpose, FloatBuffer value);
|
||||
public abstract void uniformMatrix4(int location, boolean transpose, FloatBuffer value);
|
||||
public void uniformMatrix2(int location, boolean transpose, FloatBuffer matrices) {}
|
||||
|
||||
@@ -78,7 +78,7 @@ public final class FragmentShaderGenerator {
|
||||
private static void emitTextureSampling(StringBuilder sb, FragmentKey key) {
|
||||
for (int i = 0; i < key.nrEnabledUnits(); i++) {
|
||||
if (!key.unitEnabled(i)) continue;
|
||||
sb.append(" vec4 tex").append(i).append("Color = texture(u_Sampler").append(i).append(", v_TexCoord").append(i).append(".st);\n");
|
||||
sb.append(" vec4 tex").append(i).append("Color = textureProj(u_Sampler").append(i).append(", v_TexCoord").append(i).append(");\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ public final class VertexKey {
|
||||
private static final int BIT_WIDE_LINE = 36;
|
||||
// Per-unit texmat enable: bits 37-40 (unit 0..3). Unit 1 is the lightmap matrix.
|
||||
private static final int BIT_UNIT_TEXMAT_BASE = 37;
|
||||
private static final int BIT_UNIT23_UV_FROM_UNIT0 = 41;
|
||||
|
||||
public static final int TG_NONE = 0;
|
||||
public static final int TG_OBJ_LINEAR = 1;
|
||||
@@ -85,6 +86,7 @@ public final class VertexKey {
|
||||
public boolean hasVertexNormal() { return bit(BIT_HAS_VERTEX_NORMAL); }
|
||||
public boolean hasVertexTexCoord() { return bit(BIT_HAS_VERTEX_TEX); }
|
||||
public boolean hasVertexLightmap() { return bit(BIT_HAS_VERTEX_LIGHTMAP); }
|
||||
public boolean unit23UvFromUnit0() { return bit(BIT_UNIT23_UV_FROM_UNIT0); }
|
||||
/** Color material mode (CM_AMBIENT, CM_DIFFUSE, CM_SPECULAR, CM_EMISSION, CM_AMBIENT_AND_DIFFUSE). Only meaningful when colorMaterialEnabled(). */
|
||||
public int colorMaterialMode() { return (int)((packed >> BIT_COLOR_MAT_MODE) & 0x7); }
|
||||
|
||||
@@ -213,6 +215,10 @@ public final class VertexKey {
|
||||
if (hasTexCoord) bits |= (1L << BIT_HAS_VERTEX_TEX);
|
||||
if (hasLightmap) bits |= (1L << BIT_HAS_VERTEX_LIGHTMAP);
|
||||
|
||||
if (GLStateManager.consumeUnit23TexCoordSetDuringDraw() && hasTexCoord) {
|
||||
bits |= (1L << BIT_UNIT23_UV_FROM_UNIT0);
|
||||
}
|
||||
|
||||
if (GLStateManager.anyClipPlaneEnabled()) {
|
||||
bits |= (1L << BIT_CLIP_PLANES);
|
||||
}
|
||||
|
||||
@@ -106,8 +106,8 @@ public final class VertexShaderGenerator {
|
||||
if (key.unitTexCoordEnabled(0) && !key.hasVertexTexCoord()) {
|
||||
sb.append("uniform vec4 u_CurrentTexCoord0;\n");
|
||||
}
|
||||
if (key.unitTexCoordEnabled(2)) sb.append("uniform vec4 u_CurrentTexCoord2;\n");
|
||||
if (key.unitTexCoordEnabled(3)) sb.append("uniform vec4 u_CurrentTexCoord3;\n");
|
||||
if (key.unitTexCoordEnabled(2) && !key.unit23UvFromUnit0()) sb.append("uniform vec4 u_CurrentTexCoord2;\n");
|
||||
if (key.unitTexCoordEnabled(3) && !key.unit23UvFromUnit0()) sb.append("uniform vec4 u_CurrentTexCoord3;\n");
|
||||
|
||||
if (key.lightmapEnabled() && !key.hasVertexLightmap()) {
|
||||
sb.append("uniform vec2 u_CurrentLightmapCoord;\n");
|
||||
@@ -363,8 +363,10 @@ public final class VertexShaderGenerator {
|
||||
|
||||
for (int i = 2; i < VertexKey.MAX_UNITS; i++) {
|
||||
if (!key.unitTexCoordEnabled(i)) continue;
|
||||
final String src = "u_CurrentTexCoord" + i;
|
||||
if (key.unitTexMatEnabled(i)) {
|
||||
final String src = key.unit23UvFromUnit0()
|
||||
? "vec4(a_TexCoord0, 0.0, 1.0)"
|
||||
: "u_CurrentTexCoord" + i;
|
||||
if (!key.unit23UvFromUnit0() && key.unitTexMatEnabled(i)) {
|
||||
sb.append(" v_TexCoord").append(i).append(" = u_TextureMatrix").append(i).append(" * ").append(src).append(";\n");
|
||||
} else {
|
||||
sb.append(" v_TexCoord").append(i).append(" = ").append(src).append(";\n");
|
||||
@@ -383,7 +385,7 @@ public final class VertexShaderGenerator {
|
||||
|
||||
emitTexGenComponent(sb, key.texGenModeS(), "s", "S", key);
|
||||
emitTexGenComponent(sb, key.texGenModeT(), "t", "T", key);
|
||||
emitTexGenComponent(sb, key.texGenModeR(), "r", "R", key);
|
||||
emitTexGenComponent(sb, key.texGenModeR(), "p", "R", key);
|
||||
emitTexGenComponent(sb, key.texGenModeQ(), "q", "Q", key);
|
||||
|
||||
// Always apply texture matrix when texgen is active (forced on in VertexKey)
|
||||
|
||||
@@ -8,6 +8,7 @@ public final class GLSMHooks {
|
||||
public static DeferredBlendHandler blendHandler;
|
||||
public static DeferredAlphaHandler alphaHandler;
|
||||
public static DeferredDepthColorHandler depthColorHandler;
|
||||
public static GlintColorHandler glintColorHandler;
|
||||
|
||||
// EventBus instances
|
||||
public static final EventBus<TextureBindEvent> TEXTURE_BIND = EventBus.create(TextureBindEvent.class);
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.gtnewhorizons.angelica.glsm.hooks;
|
||||
|
||||
public interface GlintColorHandler {
|
||||
void onColorChanged(float red, float green, float blue, float alpha);
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@ExtendWith(GLSMCoreExtension.class)
|
||||
class ArrayUniformUploadGLTest {
|
||||
|
||||
private static int compile(int type, String src) {
|
||||
final int s = GL20.glCreateShader(type);
|
||||
GL20.glShaderSource(s, src);
|
||||
GL20.glCompileShader(s);
|
||||
assertEquals(GL11.GL_TRUE, GL20.glGetShaderi(s, GL20.GL_COMPILE_STATUS), () -> "shader compile failed: " + GL20.glGetShaderInfoLog(s, 4096));
|
||||
return s;
|
||||
}
|
||||
|
||||
private static int link(String vs, String fs) {
|
||||
final int v = compile(GL20.GL_VERTEX_SHADER, vs);
|
||||
final int f = compile(GL20.GL_FRAGMENT_SHADER, fs);
|
||||
final int p = GL20.glCreateProgram();
|
||||
GL20.glAttachShader(p, v);
|
||||
GL20.glAttachShader(p, f);
|
||||
GL20.glLinkProgram(p);
|
||||
assertEquals(GL11.GL_TRUE, GL20.glGetProgrami(p, GL20.GL_LINK_STATUS), () -> "link failed: " + GL20.glGetProgramInfoLog(p, 4096));
|
||||
GL20.glDeleteShader(v);
|
||||
GL20.glDeleteShader(f);
|
||||
return p;
|
||||
}
|
||||
|
||||
private static final String VS = "#version 330 core\nvoid main(){ gl_Position = vec4(0.0); }\n";
|
||||
|
||||
@Test
|
||||
void glUniform2FloatBufferUploadsWholeArray() {
|
||||
// Runtime index keeps the whole array active so element locations stay queryable.
|
||||
final String fs = "#version 330 core\n"
|
||||
+ "uniform vec2 cosmicuvs[10];\n"
|
||||
+ "uniform int idx;\n"
|
||||
+ "out vec4 o;\n"
|
||||
+ "void main(){ o = vec4(cosmicuvs[idx], cosmicuvs[(idx+1)%10]); }\n";
|
||||
final int p = link(VS, fs);
|
||||
try {
|
||||
GL20.glUseProgram(p);
|
||||
|
||||
final FloatBuffer buf = BufferUtils.createFloatBuffer(20);
|
||||
for (int i = 0; i < 20; i++) buf.put(i + 1.0f); // 1..20, all distinct, all non-zero
|
||||
buf.flip();
|
||||
|
||||
GLStateManager.glUniform2(GL20.glGetUniformLocation(p, "cosmicuvs"), buf);
|
||||
|
||||
final FloatBuffer read = BufferUtils.createFloatBuffer(2);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
final int loc = GL20.glGetUniformLocation(p, "cosmicuvs[" + i + "]");
|
||||
assertTrue(loc >= 0, "element " + i + " optimized out");
|
||||
read.clear();
|
||||
GL20.glGetUniform(p, loc, read);
|
||||
assertEquals(2 * i + 1.0f, read.get(0), 0.0f, "cosmicuvs[" + i + "].x");
|
||||
assertEquals(2 * i + 2.0f, read.get(1), 0.0f, "cosmicuvs[" + i + "].y");
|
||||
}
|
||||
} finally {
|
||||
GL20.glUseProgram(0);
|
||||
GL20.glDeleteProgram(p);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void glUniform1IntBufferUploadsWholeArray() {
|
||||
final String fs = "#version 330 core\n"
|
||||
+ "uniform int vals[4];\n"
|
||||
+ "uniform int idx;\n"
|
||||
+ "out vec4 o;\n"
|
||||
+ "void main(){ o = vec4(float(vals[idx])); }\n";
|
||||
final int p = link(VS, fs);
|
||||
try {
|
||||
GL20.glUseProgram(p);
|
||||
|
||||
final IntBuffer buf = BufferUtils.createIntBuffer(4);
|
||||
buf.put(11).put(22).put(33).put(44).flip();
|
||||
GLStateManager.glUniform1(GL20.glGetUniformLocation(p, "vals"), buf);
|
||||
|
||||
final IntBuffer read = BufferUtils.createIntBuffer(1);
|
||||
final int[] expect = {11, 22, 33, 44};
|
||||
for (int i = 0; i < 4; i++) {
|
||||
final int loc = GL20.glGetUniformLocation(p, "vals[" + i + "]");
|
||||
assertTrue(loc >= 0, "element " + i + " optimized out");
|
||||
read.clear();
|
||||
GL20.glGetUniform(p, loc, read);
|
||||
assertEquals(expect[i], read.get(0), "vals[" + i + "]");
|
||||
}
|
||||
} finally {
|
||||
GL20.glUseProgram(0);
|
||||
GL20.glDeleteProgram(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,6 +34,10 @@ repositories {
|
||||
name = "GTNH Maven"
|
||||
url = uri("https://nexus.gtnewhorizons.com/repository/public/")
|
||||
}
|
||||
maven {
|
||||
name = "Minecraft Libraries"
|
||||
url = uri("https://libraries.minecraft.net")
|
||||
}
|
||||
maven {
|
||||
name = "Forge"
|
||||
url = uri("https://maven.minecraftforge.net/")
|
||||
|
||||
+25
@@ -866,6 +866,11 @@ public final class Lwjgl3GLRenderBackend extends RenderBackend {
|
||||
GL20C.glUniform4i(location, v0, v1, v2, v3);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uniform2(int location, FloatBuffer value) {
|
||||
GL20C.glUniform2fv(location, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uniform3(int location, FloatBuffer value) {
|
||||
GL20C.glUniform3fv(location, value);
|
||||
@@ -876,6 +881,26 @@ public final class Lwjgl3GLRenderBackend extends RenderBackend {
|
||||
GL20C.glUniform4fv(location, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uniform1iv(int location, IntBuffer value) {
|
||||
GL20C.glUniform1iv(location, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uniform2iv(int location, IntBuffer value) {
|
||||
GL20C.glUniform2iv(location, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uniform3iv(int location, IntBuffer value) {
|
||||
GL20C.glUniform3iv(location, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uniform4iv(int location, IntBuffer value) {
|
||||
GL20C.glUniform4iv(location, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uniformMatrix3(int location, boolean transpose, FloatBuffer value) {
|
||||
GL20C.glUniformMatrix3fv(location, transpose, value);
|
||||
|
||||
@@ -16,7 +16,7 @@ import static com.gtnewhorizons.angelica.AngelicaMod.MOD_ID;
|
||||
name = "Angelica",
|
||||
version = Tags.VERSION,
|
||||
dependencies = """
|
||||
required-after:gtnhlib@[0.8.21,);\
|
||||
required-after:gtnhlib@[0.11.19,);\
|
||||
before:lwjgl3ify@[1.5.3,);\
|
||||
after:hodgepodge@[2.4.4,);\
|
||||
after:CodeChickenCore@[1.2.0,);\
|
||||
|
||||
@@ -30,6 +30,7 @@ public class ModStatus {
|
||||
public static boolean isCosmeticArmorReworkedLoaded;
|
||||
public static boolean isFluidLoggedLoaded;
|
||||
public static boolean isBOPLoaded;
|
||||
public static boolean isEtFuturumLoaded;
|
||||
|
||||
public static void preInit() {
|
||||
if (Loader.isModLoaded("backhand")) {
|
||||
@@ -49,6 +50,7 @@ public class ModStatus {
|
||||
isBaublesLoaded = Loader.isModLoaded("Baubles");
|
||||
isCosmeticArmorReworkedLoaded = Loader.isModLoaded("cosmeticarmorreworked");
|
||||
isFluidLoggedLoaded = Loader.isModLoaded("fluidlogged");
|
||||
isEtFuturumLoaded = Loader.isModLoaded("etfuturum");
|
||||
|
||||
isHoloInventoryLoaded = Loader.isModLoaded("holoinventory");
|
||||
isBOPLoaded = Loader.isModLoaded("BiomesOPlenty");
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.gtnewhorizons.angelica.compat.etfuturum;
|
||||
|
||||
import cpw.mods.fml.common.Loader;
|
||||
import cpw.mods.fml.relauncher.ReflectionHelper;
|
||||
import lombok.Getter;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
|
||||
import static com.gtnewhorizons.angelica.compat.ModStatus.LOGGER;
|
||||
|
||||
public final class EtFuturumCompat {
|
||||
private static final String IELYTRA_PLAYER = "ganymedes01.etfuturum.api.elytra.IElytraPlayer";
|
||||
|
||||
@Getter
|
||||
private static boolean loaded;
|
||||
private static Class<?> elytraPlayerClass;
|
||||
private static final MethodHandle isElytraFlyingHandle;
|
||||
|
||||
static {
|
||||
MethodHandle handle = null;
|
||||
try {
|
||||
if (Loader.isModLoaded("etfuturum")) {
|
||||
elytraPlayerClass = ReflectionHelper.getClass(EtFuturumCompat.class.getClassLoader(), IELYTRA_PLAYER);
|
||||
handle = MethodHandles.lookup().findVirtual(elytraPlayerClass, "etfu$isElytraFlying",
|
||||
MethodType.methodType(boolean.class));
|
||||
loaded = true;
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error("Failed to load Et Futurum Requiem elytra compat", t);
|
||||
loaded = false;
|
||||
}
|
||||
isElytraFlyingHandle = handle;
|
||||
}
|
||||
|
||||
private EtFuturumCompat() {
|
||||
}
|
||||
|
||||
public static boolean isElytraFlying(EntityPlayer player) {
|
||||
if (!loaded || isElytraFlyingHandle == null || !elytraPlayerClass.isInstance(player)) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return (boolean) isElytraFlyingHandle.invoke(player);
|
||||
} catch (Throwable t) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -357,8 +357,13 @@ public class AngelicaConfig {
|
||||
@Config.RequiresMcRestart
|
||||
public static boolean disableErrorChecks;
|
||||
|
||||
@Config.Comment("Fixes various issues with entity overlays, such as z-fighting, damage animations and eyes.")
|
||||
@Config.Comment("Fixes various issues with entity overlays, such as z-fighting and eyes.")
|
||||
@Config.DefaultBoolean(true)
|
||||
@Config.RequiresMcRestart
|
||||
public static boolean entityOverlayFixes;
|
||||
|
||||
@Config.Comment("Swap the vanilla damage overlay with one similar to modern. Fixes specific issues with z-fighting.")
|
||||
@Config.DefaultBoolean(true)
|
||||
@Config.RequiresMcRestart
|
||||
public static boolean entityModernDamageOverlay;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.gtnewhorizons.angelica.event;
|
||||
|
||||
import net.minecraft.client.renderer.EntityRenderer;
|
||||
import net.minecraftforge.eventbus.api.bus.EventBus;
|
||||
import net.minecraftforge.eventbus.api.event.MutableEvent;
|
||||
|
||||
public class ClientEvent extends MutableEvent {
|
||||
public static final EventBus<ClientEvent> BUS = EventBus.create(ClientEvent.class);
|
||||
|
||||
public final ClientEventType event;
|
||||
public final EntityRenderer renderer;
|
||||
public final float partialTicks;
|
||||
|
||||
private ClientEvent(ClientEventType event) {
|
||||
this.event = event;
|
||||
this.renderer = null;
|
||||
this.partialTicks = 0;
|
||||
}
|
||||
|
||||
private ClientEvent(ClientEventType event, EntityRenderer renderer, float partialTicks) {
|
||||
this.event = event;
|
||||
this.renderer = renderer;
|
||||
this.partialTicks = partialTicks;
|
||||
}
|
||||
|
||||
public static void post(ClientEventType event, EntityRenderer renderer, float partialTicks) {
|
||||
if (!BUS.hasListeners()) return;
|
||||
BUS.post(new ClientEvent(event, renderer, partialTicks));
|
||||
}
|
||||
|
||||
public static void post(ClientEventType event) {
|
||||
if (!BUS.hasListeners()) return;
|
||||
BUS.post(new ClientEvent(event));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.gtnewhorizons.angelica.event;
|
||||
|
||||
public enum ClientEventType {
|
||||
PRE_RENDER_GUI,
|
||||
PRE_RENDER_HUD,
|
||||
POST_RENDER_HUD,
|
||||
ON_TICK,
|
||||
}
|
||||
@@ -6,11 +6,12 @@ import com.gtnewhorizon.gtnhlib.client.renderer.postprocessing.CustomFramebuffer
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.postprocessing.SharedDepthFramebuffer;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vao.IVertexArrayObject;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vao.VertexBufferType;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vbo.IVertexBuffer;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.DefaultVertexFormat;
|
||||
import com.gtnewhorizons.angelica.compat.ModStatus;
|
||||
import com.gtnewhorizons.angelica.compat.holoinventory.HoloInventoryReflectionCompat;
|
||||
import com.gtnewhorizons.angelica.config.AngelicaConfig;
|
||||
import com.gtnewhorizons.angelica.event.ClientEvent;
|
||||
import com.gtnewhorizons.angelica.event.ClientEventType;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.GLSMConfig;
|
||||
import com.gtnewhorizons.angelica.mixins.interfaces.GuiIngameAccessor;
|
||||
@@ -65,6 +66,8 @@ public class HUDCaching {
|
||||
}
|
||||
|
||||
public static void renderCachedHud(EntityRenderer renderer, GuiIngame ingame, float partialTicks, boolean hasScreen, int mouseX, int mouseY) {
|
||||
ClientEvent.post(ClientEventType.PRE_RENDER_GUI, renderer, partialTicks);
|
||||
ClientEvent.post(ClientEventType.PRE_RENDER_HUD, renderer, partialTicks);
|
||||
if (ModStatus.isXaerosMinimapLoaded && ingame instanceof GuiIngameForge) {
|
||||
// this used to be called by asming into renderGameOverlay, but we removed it
|
||||
XaeroMinimapCore.beforeIngameGuiRender(partialTicks);
|
||||
@@ -78,6 +81,7 @@ public class HUDCaching {
|
||||
|
||||
if (!AngelicaConfig.hudCachingActive || mc.displayWidth < 16 || mc.displayHeight < 16) {
|
||||
ingame.renderGameOverlay(partialTicks, hasScreen, mouseX, mouseY);
|
||||
ClientEvent.post(ClientEventType.POST_RENDER_HUD, renderer, partialTicks);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -170,6 +174,8 @@ public class HUDCaching {
|
||||
|
||||
GLStateManager.tryBlendFuncSeparate(GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO);
|
||||
mc.getTextureManager().bindTexture(Gui.icons);
|
||||
|
||||
ClientEvent.post(ClientEventType.POST_RENDER_HUD, renderer, partialTicks);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -120,7 +120,10 @@ public final class AngelicaClientTweaker implements IFMLLoadingPlugin, IEarlyMix
|
||||
"Missing dependency: Angelica requires GTNHLib! Download: https://modrinth.com/mod/gtnhlib"),
|
||||
new DependencyVerifier.Check(
|
||||
"/com/gtnewhorizon/gtnhlib/client/renderer/VertexCallbackManager.class",
|
||||
"GTNHLib is outdated: Angelica requires GTNHLib 0.10.0 or newer! Download: https://modrinth.com/mod/gtnhlib")
|
||||
"GTNHLib is outdated: Angelica requires GTNHLib 0.10.0 or newer! Download: https://modrinth.com/mod/gtnhlib"),
|
||||
new DependencyVerifier.Check(
|
||||
"/it/unimi/dsi/fastutil/objects/ObjectBooleanBiConsumer.class",
|
||||
"GTNHLib is outdated: Angelica requires GTNHLib 0.11.19 or newer (fastutil 8.5.18+)! Download: https://modrinth.com/mod/gtnhlib")
|
||||
));
|
||||
} catch (RuntimeException ex) {
|
||||
fatalDependencyError(ex.getMessage());
|
||||
|
||||
@@ -64,7 +64,15 @@ public enum Mixins implements IMixins {
|
||||
.addExcludedMod(TargetedMod.CUSTOM_PLAYER_MODELS)
|
||||
.addClientMixins(
|
||||
"angelica.bugfixes.MixinRendererLivingEntity_EyeDepth"
|
||||
, "angelica.bugfixes.MixinRendererLivingEntity_OverlayTint"
|
||||
)
|
||||
),
|
||||
|
||||
ANGELICA_DAMAGE_OVERLAY(new MixinBuilder()
|
||||
.setPhase(Phase.EARLY)
|
||||
.setApplyIf(() -> AngelicaConfig.entityModernDamageOverlay)
|
||||
.addExcludedMod(TargetedMod.CUSTOM_PLAYER_MODELS)
|
||||
.addClientMixins(
|
||||
"angelica.bugfixes.MixinRendererLivingEntity_OverlayTint"
|
||||
)
|
||||
),
|
||||
|
||||
@@ -290,6 +298,7 @@ public enum Mixins implements IMixins {
|
||||
, "shaders.MixinRenderEndPortal"
|
||||
, "shaders.MixinTileEntityRendererDispatcher"
|
||||
, "shaders.MixinGlProgram"
|
||||
, "shaders.MixinTextureManager_ReloadCount"
|
||||
)
|
||||
),
|
||||
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
package com.gtnewhorizons.angelica.shadercompat;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.GLSMHooks;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.GlintColorHandler;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntLinkedOpenHashMap;
|
||||
import net.coderbot.iris.pipeline.ShadowRenderer;
|
||||
import net.irisshaders.iris.api.v0.IrisApi;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* Maybe overcomplicated, but it's required to bridge the gap between the modern glint texture and white texture 1.7.10
|
||||
* has. Some shaders are able to render the glint just fine as they seem to have some amount of support for older
|
||||
* Minecraft, but others like AstraLex do *not* render correctly. It expects the color to be within the texture.
|
||||
* This might introduce some oddities that I'm not seeing, but for now this appears to fix the issue.
|
||||
*/
|
||||
public final class ShaderGlint {
|
||||
|
||||
private static final ResourceLocation GLINT_MASK = new ResourceLocation("textures/misc/enchanted_item_glint.png");
|
||||
private static final int MAX_CACHE = 64;
|
||||
|
||||
private static boolean maskLoaded;
|
||||
private static boolean maskFailed;
|
||||
private static int maskW;
|
||||
private static int maskH;
|
||||
private static int[] maskLum;
|
||||
|
||||
private static final Int2IntLinkedOpenHashMap colorToTexture = new Int2IntLinkedOpenHashMap();
|
||||
static {
|
||||
colorToTexture.defaultReturnValue(0);
|
||||
}
|
||||
|
||||
private static final GlintColorHandler COLOR_HANDLER = ShaderGlint::onColorChanged;
|
||||
|
||||
private static boolean injecting;
|
||||
private static boolean swapped;
|
||||
private static int depth;
|
||||
|
||||
private static int prevTexture;
|
||||
|
||||
private static ByteBuffer tintBuffer;
|
||||
|
||||
private ShaderGlint() {}
|
||||
|
||||
public static void beginGlint() {
|
||||
if (ShadowRenderer.ACTIVE || !IrisApi.getInstance().isShaderPackInUse()) return;
|
||||
|
||||
// If a glint span is already active, keep the outer span's saved state and
|
||||
// let the nested render ride on its handler.
|
||||
if (depth++ > 0) return;
|
||||
|
||||
swapped = false;
|
||||
injecting = false;
|
||||
|
||||
// Save the texture bound before the glint section so endGlint can put it back if we swap
|
||||
prevTexture = GLStateManager.getBoundTextureForServerState(0);
|
||||
|
||||
// Observe vertex-color changes for the rest of the glint section
|
||||
GLSMHooks.glintColorHandler = COLOR_HANDLER;
|
||||
}
|
||||
|
||||
public static void endGlint() {
|
||||
if (depth == 0 || --depth > 0) return;
|
||||
if (GLSMHooks.glintColorHandler != COLOR_HANDLER) return;
|
||||
GLSMHooks.glintColorHandler = null;
|
||||
|
||||
if (swapped) {
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, prevTexture);
|
||||
}
|
||||
swapped = false;
|
||||
injecting = false;
|
||||
}
|
||||
|
||||
private static void onColorChanged(float red, float green, float blue, float alpha) {
|
||||
if (injecting) return;
|
||||
|
||||
final int texture = getTintedTexture(red, green, blue);
|
||||
if (texture <= 0) return;
|
||||
|
||||
injecting = true;
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, texture);
|
||||
GLStateManager.glColor4f(1.0F, 1.0F, 1.0F, alpha);
|
||||
injecting = false;
|
||||
swapped = true;
|
||||
}
|
||||
|
||||
private static int getTintedTexture(float r, float g, float b) {
|
||||
ensureMaskLoaded();
|
||||
if (!maskLoaded) return -1;
|
||||
|
||||
final int ri = clamp8(r);
|
||||
final int gi = clamp8(g);
|
||||
final int bi = clamp8(b);
|
||||
final int key = (ri << 16) | (gi << 8) | bi;
|
||||
|
||||
final int cached = colorToTexture.getAndMoveToLast(key);
|
||||
if (cached != 0) return cached;
|
||||
|
||||
if (colorToTexture.size() >= MAX_CACHE) {
|
||||
GLStateManager.glDeleteTextures(colorToTexture.remove(colorToTexture.firstIntKey()));
|
||||
}
|
||||
|
||||
final int texture = uploadTinted(ri / 255.0F, gi / 255.0F, bi / 255.0F);
|
||||
colorToTexture.putAndMoveToLast(key, texture);
|
||||
return texture;
|
||||
}
|
||||
|
||||
private static int uploadTinted(float r, float g, float b) {
|
||||
final ByteBuffer pixels = tintBuffer;
|
||||
pixels.clear();
|
||||
for (final int l : maskLum) {
|
||||
pixels.put((byte) Math.round(l * r));
|
||||
pixels.put((byte) Math.round(l * g));
|
||||
pixels.put((byte) Math.round(l * b));
|
||||
pixels.put((byte) 0xFF);
|
||||
}
|
||||
pixels.flip();
|
||||
|
||||
final int texture = GLStateManager.glGenTextures();
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, texture);
|
||||
// Match the vanilla glint texture
|
||||
GLStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
|
||||
GLStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
|
||||
GLStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT);
|
||||
GLStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT);
|
||||
GLStateManager.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, maskW, maskH, 0,
|
||||
GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, pixels);
|
||||
return texture;
|
||||
}
|
||||
|
||||
private static void ensureMaskLoaded() {
|
||||
if (maskLoaded || maskFailed) return;
|
||||
try (final InputStream in = Minecraft.getMinecraft().getResourceManager().getResource(GLINT_MASK).getInputStream()) {
|
||||
final BufferedImage img = ImageIO.read(in);
|
||||
maskW = img.getWidth();
|
||||
maskH = img.getHeight();
|
||||
maskLum = new int[maskW * maskH];
|
||||
final int[] argb = img.getRGB(0, 0, maskW, maskH, null, 0, maskW);
|
||||
for (int i = 0; i < argb.length; i++) {
|
||||
final int p = argb[i];
|
||||
final int rr = (p >> 16) & 0xFF;
|
||||
final int gg = (p >> 8) & 0xFF;
|
||||
final int bb = p & 0xFF;
|
||||
maskLum[i] = (rr + gg + bb) / 3;
|
||||
}
|
||||
tintBuffer = BufferUtils.createByteBuffer(maskW * maskH * 4);
|
||||
maskLoaded = true;
|
||||
} catch (final Exception e) {
|
||||
maskFailed = true;
|
||||
}
|
||||
}
|
||||
|
||||
private static int clamp8(float v) {
|
||||
final int i = Math.round(v * 255.0F);
|
||||
if (i < 0) return 0;
|
||||
return Math.min(i, 255);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,8 @@ import cpw.mods.fml.client.registry.ClientRegistry;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||
import cpw.mods.fml.common.gameevent.InputEvent;
|
||||
import cpw.mods.fml.common.gameevent.TickEvent;
|
||||
import jss.notfine.core.Settings;
|
||||
import lombok.Getter;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.settings.KeyBinding;
|
||||
@@ -19,6 +21,13 @@ public class Zoom {
|
||||
|
||||
@Getter
|
||||
private static float zoom = ZOOM_DEFAULT;
|
||||
|
||||
public static final float ZOOM_SMOOTH_SNAP_EPSILON = 0.001F;
|
||||
|
||||
@Getter
|
||||
private static float currentZoom = 1.0F;
|
||||
private static long zoomLerpLastNano = 0L;
|
||||
|
||||
@Getter
|
||||
private static final KeyBinding zoomKey = new KeyBinding("Zoom", 0, "key.categories.misc");
|
||||
|
||||
@@ -38,6 +47,29 @@ public class Zoom {
|
||||
zoom = MathHelper.clamp_float((float) (zoom * Math.pow(ZOOM_STEP, Integer.signum(eventDWheel))), ZOOM_MIN, ZOOM_MAX);
|
||||
}
|
||||
|
||||
public static void updateZoomLerp() {
|
||||
final long now = System.nanoTime();
|
||||
float dt = zoomLerpLastNano == 0L ? 0.0F : (now - zoomLerpLastNano) / 1.0e9F;
|
||||
zoomLerpLastNano = now;
|
||||
|
||||
final float target = zoomEnabled ? zoom : 1.0F;
|
||||
|
||||
if (dt <= 0.0F || !(boolean) Settings.ZOOM_SMOOTH.option.getStore()) {
|
||||
currentZoom = target;
|
||||
return;
|
||||
}
|
||||
|
||||
// Clamp dt so a long frame (alt-tab, GC pause) does not snap the zoom.
|
||||
dt = Math.min(dt, 0.1F);
|
||||
|
||||
final int rate = (int) Settings.ZOOM_SMOOTH_SPEED.option.getStore();
|
||||
currentZoom += (target - currentZoom) * (1.0F - (float) Math.exp(-dt * rate));
|
||||
|
||||
if (Math.abs(target - currentZoom) < ZOOM_SMOOTH_SNAP_EPSILON) {
|
||||
currentZoom = target;
|
||||
}
|
||||
}
|
||||
|
||||
private static void resetMouseFilters(Minecraft mc) {
|
||||
if (mc.entityRenderer != null) {
|
||||
((IMouseFilterExt) mc.entityRenderer.mouseFilterXAxis).angelica$reset();
|
||||
@@ -79,4 +111,10 @@ public class Zoom {
|
||||
handleKeyEvent();
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onRenderTick(TickEvent.RenderTickEvent e) {
|
||||
if (e.phase != TickEvent.Phase.START) return;
|
||||
updateZoomLerp();
|
||||
}
|
||||
}
|
||||
@@ -174,7 +174,9 @@ public enum Settings {
|
||||
RenderStars.reloadStarRenderList(Minecraft.getMinecraft().renderGlobal);
|
||||
}
|
||||
},
|
||||
VOID_FOG(new NotFineOptionTickBox(false, OptionImpact.LOW));
|
||||
VOID_FOG(new NotFineOptionTickBox(false, OptionImpact.LOW)),
|
||||
ZOOM_SMOOTH(new NotFineOptionTickBox(true, OptionImpact.LOW)),
|
||||
ZOOM_SMOOTH_SPEED(new NotFineOptionSlider(14, 1, 30, 1, OptionImpact.LOW));
|
||||
|
||||
public final NotFineOption<?> option;
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package jss.notfine.gui;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.gtnewhorizons.angelica.config.AngelicaConfig;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import jss.notfine.config.NotFineConfig;
|
||||
import jss.notfine.core.Settings;
|
||||
@@ -169,6 +170,12 @@ public class NotFineGameOptionPages {
|
||||
.build());
|
||||
}
|
||||
|
||||
if (AngelicaConfig.enableZoom) {
|
||||
groups.add(OptionGroup.createBuilder()
|
||||
.add(Settings.ZOOM_SMOOTH.option)
|
||||
.add(Settings.ZOOM_SMOOTH_SPEED.option)
|
||||
.build());
|
||||
}
|
||||
|
||||
return new OptionPage(I18n.format("options.video"), ImmutableList.copyOf(groups));
|
||||
}
|
||||
|
||||
@@ -532,6 +532,13 @@ public class SodiumGameOptionPages {
|
||||
.build())
|
||||
.build());
|
||||
|
||||
if (AngelicaConfig.enableZoom) {
|
||||
groups.add(OptionGroup.createBuilder()
|
||||
.add(Settings.ZOOM_SMOOTH.option)
|
||||
.add(Settings.ZOOM_SMOOTH_SPEED.option)
|
||||
.build());
|
||||
}
|
||||
|
||||
return new OptionPage(I18n.format("sodium.options.pages.appearance"), ImmutableList.copyOf(groups));
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ import net.coderbot.iris.shaderpack.option.Profile;
|
||||
import net.coderbot.iris.shaderpack.option.values.MutableOptionValues;
|
||||
import net.coderbot.iris.shaderpack.option.values.OptionValues;
|
||||
import net.coderbot.iris.texture.pbr.PBRTextureManager;
|
||||
import net.coderbot.iris.uniforms.CapturedRenderingState;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
@@ -567,11 +568,11 @@ public class Iris {
|
||||
|
||||
// If it's a folder-based shaderpack, just use the shaders subdirectory
|
||||
shaderPackPath = shaderPackRoot.resolve("shaders");
|
||||
}
|
||||
|
||||
if (!Files.exists(shaderPackPath)) {
|
||||
logger.error("Could not load the shaderpack \"{}\" because it appears to lack a \"shaders\" directory", name);
|
||||
return false;
|
||||
if (!Files.exists(shaderPackPath)) {
|
||||
logger.error("Could not load the shaderpack \"{}\" because it appears to lack a \"shaders\" directory", name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -762,6 +763,9 @@ public class Iris {
|
||||
// allows shaderpacks to be changed at runtime
|
||||
irisConfig.initialize();
|
||||
|
||||
// Reset the texture reload counter
|
||||
CapturedRenderingState.INSTANCE.resetTextureReloadCount();
|
||||
|
||||
// Destroy all allocated resources
|
||||
destroyEverything();
|
||||
|
||||
|
||||
@@ -10,13 +10,13 @@ import java.util.function.BooleanSupplier;
|
||||
public enum FeatureFlags {
|
||||
SEPARATE_HARDWARE_SAMPLERS(() -> true, () -> true),
|
||||
PER_BUFFER_BLENDING(() -> true, RenderSystem::supportsBufferBlending),
|
||||
COMPUTE_SHADERS(() -> true, RenderSystem::supportsCompute),
|
||||
COMPUTE_SHADERS(() -> false, RenderSystem::supportsCompute),
|
||||
ENTITY_TRANSLUCENT(() -> true, () -> true),
|
||||
BLOCK_EMISSION_ATTRIBUTE(() -> true, () -> true),
|
||||
CUSTOM_IMAGES(() -> true, RenderSystem::supportsImageLoadStore),
|
||||
SSBO(() -> true, RenderSystem::supportsSSBO),
|
||||
HIGHER_SHADOWCOLOR(() -> true, () -> true),
|
||||
TESSELLATION_SHADERS(() -> true, RenderSystem::supportsTesselation),
|
||||
TESSELLATION_SHADERS(() -> false, RenderSystem::supportsTesselation),
|
||||
REVERSED_CULLING(() -> true, () -> true),
|
||||
CAN_DISABLE_WEATHER(() -> true, () -> true),
|
||||
UNKNOWN(() -> false, () -> false);
|
||||
|
||||
@@ -4,5 +4,7 @@ public enum GlVersion {
|
||||
GL_11,
|
||||
GL_12,
|
||||
GL_30,
|
||||
GL_31
|
||||
GL_31,
|
||||
GL_33,
|
||||
GL_41
|
||||
}
|
||||
@@ -132,6 +132,11 @@ public class StandardMacros {
|
||||
getBiomeCategoryDefines().forEach((category, ordinal) -> define(standardDefines, category, ordinal));
|
||||
getVanillaBiomeDefines().forEach((biome, id) -> define(standardDefines, biome, id));
|
||||
|
||||
// rain type constants
|
||||
define(standardDefines, "PPT_NONE", "0");
|
||||
define(standardDefines, "PPT_RAIN", "1");
|
||||
define(standardDefines, "PPT_SNOW", "2");
|
||||
|
||||
return ImmutableList.copyOf(standardDefines);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@ import net.coderbot.iris.gl.GlVersion;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
import org.lwjgl.opengl.GL31;
|
||||
import org.lwjgl.opengl.GL33;
|
||||
import org.lwjgl.opengl.GL41;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -72,10 +74,16 @@ public enum InternalTextureFormat {
|
||||
RG32UI(GL30.GL_RG32UI, GlVersion.GL_30, PixelFormat.RG_INTEGER),
|
||||
RGB32UI(GL30.GL_RGB32UI, GlVersion.GL_30, PixelFormat.RGB_INTEGER),
|
||||
RGBA32UI(GL30.GL_RGBA32UI, GlVersion.GL_30, PixelFormat.RGBA_INTEGER),
|
||||
// 2-bit normalized
|
||||
RGBA2(GL11.GL_RGBA2, GlVersion.GL_11, PixelFormat.RGBA),
|
||||
// 4-bit normalized
|
||||
RGBA4(GL11.GL_RGBA4, GlVersion.GL_11, PixelFormat.RGBA),
|
||||
// Mixed
|
||||
R3_G3_B2(GL11.GL_R3_G3_B2, GlVersion.GL_11, PixelFormat.RGB),
|
||||
RGB5_A1(GL11.GL_RGB5_A1, GlVersion.GL_11, PixelFormat.RGBA),
|
||||
RGB565(GL41.GL_RGB565, GlVersion.GL_41, PixelFormat.RGB),
|
||||
RGB10_A2(GL11.GL_RGB10_A2, GlVersion.GL_11, PixelFormat.RGBA),
|
||||
RGB10_A2UI(GL33.GL_RGB10_A2UI, GlVersion.GL_33, PixelFormat.RGBA_INTEGER),
|
||||
R11F_G11F_B10F(GL30.GL_R11F_G11F_B10F, GlVersion.GL_30, PixelFormat.RGB),
|
||||
RGB9_E5(GL30.GL_RGB9_E5, GlVersion.GL_30, PixelFormat.RGB);
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ import net.coderbot.iris.gl.texture.DepthBufferFormat;
|
||||
import net.coderbot.iris.gl.texture.TextureType;
|
||||
import net.coderbot.iris.helpers.Tri;
|
||||
import net.coderbot.iris.layer.GbufferPrograms;
|
||||
import net.coderbot.iris.pipeline.transform.GlintScrollInjector;
|
||||
import net.coderbot.iris.pipeline.transform.PatchShaderType;
|
||||
import net.coderbot.iris.pipeline.transform.TransformPatcher;
|
||||
import net.coderbot.iris.postprocess.BufferFlipper;
|
||||
@@ -838,13 +839,16 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R
|
||||
|
||||
if (transformed == null) {
|
||||
// Fallback to synchronous transform if not pre-computed
|
||||
String vertex = source.getVertexSource().orElseThrow(NullPointerException::new);
|
||||
final boolean scrollGlint = GlintScrollInjector.shouldInject(id, source);
|
||||
transformed = TransformPatcher.patchAttributes(
|
||||
source.getVertexSource().orElseThrow(NullPointerException::new),
|
||||
vertex,
|
||||
source.getGeometrySource().orElse(null),
|
||||
source.getTessControlSource().orElse(null),
|
||||
source.getTessEvalSource().orElse(null),
|
||||
source.getFragmentSource().orElseThrow(NullPointerException::new),
|
||||
availability);
|
||||
availability,
|
||||
scrollGlint);
|
||||
}
|
||||
|
||||
String vertex = transformed.get(PatchShaderType.VERTEX);
|
||||
@@ -1784,9 +1788,12 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R
|
||||
ProgramSource source = resolver.resolveNullable(id);
|
||||
if (source != null && !processedSourceNames.contains(source.getName())) {
|
||||
processedSourceNames.add(source.getName());
|
||||
final ProgramSource src = source;
|
||||
final String vertexSource = src.getVertexSource().orElse(null);
|
||||
final boolean scrollGlint = GlintScrollInjector.shouldInject(id, src);
|
||||
for (InputAvailability avail : INPUT_AVAILABILITIES) {
|
||||
Pair<String, InputAvailability> key = Pair.of(source.getName(), avail);
|
||||
futures.put(key, Iris.ShaderTransformExecutor.submitTracked(() -> TransformPatcher.patchAttributes(source.getVertexSource().orElse(null), source.getGeometrySource().orElse(null), source.getTessControlSource().orElse(null), source.getTessEvalSource().orElse(null), source.getFragmentSource().orElse(null), avail)));
|
||||
Pair<String, InputAvailability> key = Pair.of(src.getName(), avail);
|
||||
futures.put(key, Iris.ShaderTransformExecutor.submitTracked(() -> TransformPatcher.patchAttributes(vertexSource, src.getGeometrySource().orElse(null), src.getTessControlSource().orElse(null), src.getTessEvalSource().orElse(null), src.getFragmentSource().orElse(null), avail, scrollGlint)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package net.coderbot.iris.pipeline.transform;
|
||||
import net.coderbot.iris.gl.shader.ShaderType;
|
||||
import net.coderbot.iris.pipeline.transform.parameter.AttributeParameters;
|
||||
import org.taumc.glsl.Transformer;
|
||||
import org.taumc.glsl.grammar.GLSLParser;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -13,6 +14,10 @@ import java.util.Map;
|
||||
*/
|
||||
class AttributeTransformer {
|
||||
public static void transform(Transformer transformer, AttributeParameters parameters, int version) {
|
||||
if (parameters.scrollGlint && parameters.type == ShaderType.VERTEX) {
|
||||
transformer.replaceExpression("gl_MultiTexCoord0", "(gl_TextureMatrix[0] * gl_MultiTexCoord0)", GLSLParser::postfix_expression);
|
||||
}
|
||||
|
||||
// Always core profile — minimum GLSL version is 330 (see ShaderTransformer.getStageMinimumVersion)
|
||||
CommonTransformer.transform(transformer, parameters, true, version);
|
||||
|
||||
|
||||
@@ -46,6 +46,10 @@ class CeleritasTransformer {
|
||||
vertexReplacements.put("gl_MultiTexCoord2", "iris_LightTexCoord");
|
||||
vertexReplacements.forEach(transformer::replaceExpression);
|
||||
|
||||
if (transformer.hasVariable("chunkOffset")) {
|
||||
transformer.removeVariable("chunkOffset");
|
||||
}
|
||||
|
||||
final Map<String, String> vertexRenames = new HashMap<>();
|
||||
vertexRenames.put("gl_Color", "_vert_color");
|
||||
vertexRenames.put("ftransform", "iris_ftransform");
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.gtnewhorizons.angelica.glsm.GlslTransformUtils;
|
||||
import net.coderbot.iris.gl.shader.ShaderType;
|
||||
import net.coderbot.iris.pipeline.transform.parameter.Parameters;
|
||||
import org.taumc.glsl.Transformer;
|
||||
import org.taumc.glsl.grammar.GLSLParser;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
@@ -29,6 +30,16 @@ public class CommonTransformer {
|
||||
root.rename("gl_Color", "iris_FrontColor");
|
||||
}
|
||||
|
||||
if (root.hasVariable("gl_TexCoord")) {
|
||||
if (parameters.type == ShaderType.VERTEX) {
|
||||
root.rename("gl_TexCoord", "irs_texCoords");
|
||||
root.injectVariable("out vec4 irs_texCoords[3];");
|
||||
} else if (parameters.type == ShaderType.FRAGMENT) {
|
||||
root.rename("gl_TexCoord", "irs_texCoords");
|
||||
root.injectVariable("in vec4 irs_texCoords[3];");
|
||||
}
|
||||
}
|
||||
|
||||
if (parameters.type == ShaderType.FRAGMENT) {
|
||||
if (root.containsCall("gl_FragColor")) {
|
||||
root.replaceExpression("gl_FragColor", "gl_FragData[0]");
|
||||
@@ -91,6 +102,27 @@ public class CommonTransformer {
|
||||
root.renameAndWrapShadow("shadow2D", "texture");
|
||||
root.renameAndWrapShadow("shadow2DLod", "textureLod");
|
||||
|
||||
if (root.containsCall("textureLodOffset")) {
|
||||
root.injectFunction("vec4 iris_textureLodOffset(sampler2D iris_tlo_s, vec2 iris_tlo_c, float iris_tlo_l, ivec2 iris_tlo_o) { return textureLod(iris_tlo_s, iris_tlo_c + vec2(iris_tlo_o) / vec2(textureSize(iris_tlo_s, int(iris_tlo_l))), iris_tlo_l); }");
|
||||
root.injectFunction("float iris_textureLodOffset(sampler2DShadow iris_tlo_s, vec3 iris_tlo_c, float iris_tlo_l, ivec2 iris_tlo_o) { return textureLod(iris_tlo_s, vec3(iris_tlo_c.xy + vec2(iris_tlo_o) / vec2(textureSize(iris_tlo_s, int(iris_tlo_l))), iris_tlo_c.z), iris_tlo_l); }");
|
||||
root.injectFunction("vec4 iris_textureLodOffset(sampler3D iris_tlo_s, vec3 iris_tlo_c, float iris_tlo_l, ivec3 iris_tlo_o) { return textureLod(iris_tlo_s, iris_tlo_c + vec3(iris_tlo_o) / vec3(textureSize(iris_tlo_s, int(iris_tlo_l))), iris_tlo_l); }");
|
||||
root.injectFunction("vec4 iris_textureLodOffset(sampler2DArray iris_tlo_s, vec3 iris_tlo_c, float iris_tlo_l, ivec2 iris_tlo_o) { return textureLod(iris_tlo_s, vec3(iris_tlo_c.xy + vec2(iris_tlo_o) / vec2(textureSize(iris_tlo_s, int(iris_tlo_l)).xy), iris_tlo_c.z), iris_tlo_l); }");
|
||||
root.injectFunction("ivec4 iris_textureLodOffset(isampler2D iris_tlo_s, vec2 iris_tlo_c, float iris_tlo_l, ivec2 iris_tlo_o) { return textureLod(iris_tlo_s, iris_tlo_c + vec2(iris_tlo_o) / vec2(textureSize(iris_tlo_s, int(iris_tlo_l))), iris_tlo_l); }");
|
||||
root.injectFunction("uvec4 iris_textureLodOffset(usampler2D iris_tlo_s, vec2 iris_tlo_c, float iris_tlo_l, ivec2 iris_tlo_o) { return textureLod(iris_tlo_s, iris_tlo_c + vec2(iris_tlo_o) / vec2(textureSize(iris_tlo_s, int(iris_tlo_l))), iris_tlo_l); }");
|
||||
root.renameFunctionCall("textureLodOffset", "iris_textureLodOffset");
|
||||
}
|
||||
|
||||
if (parameters.type == ShaderType.VERTEX) {
|
||||
root.mutateTree(tree -> {
|
||||
if (tree.children != null) {
|
||||
tree.children.removeIf(child ->
|
||||
child instanceof GLSLParser.External_declarationContext
|
||||
&& ((GLSLParser.External_declarationContext) child).declaration() != null
|
||||
&& child.getText().contains("gl_PerVertex"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (parameters.patch == Patch.ATTRIBUTES && parameters.type == ShaderType.VERTEX) {
|
||||
root.injectVariable("uniform bool angelica_ClipPlanesEnabled;");
|
||||
root.injectVariable("uniform vec4 angelica_ClipPlane[8];");
|
||||
|
||||
@@ -3,6 +3,7 @@ package net.coderbot.iris.pipeline.transform;
|
||||
import net.coderbot.iris.gl.shader.ShaderType;
|
||||
import net.coderbot.iris.pipeline.transform.parameter.Parameters;
|
||||
import org.antlr.v4.runtime.tree.ParseTree;
|
||||
import org.taumc.glsl.ShaderPrinter;
|
||||
import org.taumc.glsl.Transformer;
|
||||
import org.taumc.glsl.grammar.GLSLLexer;
|
||||
import org.taumc.glsl.grammar.GLSLParser;
|
||||
@@ -109,7 +110,10 @@ public class CompatibilityTransformer {
|
||||
continue;
|
||||
}
|
||||
|
||||
prevTransformer.makeOutDeclaration(inDec.get(in), in);
|
||||
String outDeclaration = ShaderPrinter.getFormattedShader(inDec.get(in).fully_specified_type())
|
||||
+ " " + in + ";";
|
||||
prevTransformer.variable = null;
|
||||
prevTransformer.injectVariable(outDeclaration.replaceFirst("in", "out"));
|
||||
|
||||
if (!prevTransformer.hasAssigment(in)) {
|
||||
prevTransformer.initialize(inDec.get(in), in);
|
||||
@@ -126,6 +130,23 @@ public class CompatibilityTransformer {
|
||||
if (!prevTransformer.hasAssigment(in)) {
|
||||
prevTransformer.initialize(inDec.get(in), in);
|
||||
}
|
||||
} else {
|
||||
int outComp = vecComponents(outType.getText());
|
||||
int inComp = vecComponents(inType.getText());
|
||||
if (outComp < 0 || inComp < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String temp = "iris_template_" + in;
|
||||
prevTransformer.rename(in, temp);
|
||||
String newOut = ShaderPrinter.getFormattedShader(inDec.get(in).fully_specified_type())
|
||||
+ " " + in + ";";
|
||||
prevTransformer.variable = null;
|
||||
prevTransformer.injectVariable(newOut.replaceFirst("in", "out"));
|
||||
String cast = outComp < inComp
|
||||
? in + " = " + inType.getText() + "(" + temp + ", vec4(0));"
|
||||
: in + " = " + inType.getText() + "(" + temp + ");";
|
||||
prevTransformer.appendMain(cast);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -133,4 +154,13 @@ public class CompatibilityTransformer {
|
||||
prevType = type;
|
||||
}
|
||||
}
|
||||
|
||||
private static int vecComponents(String type) {
|
||||
return switch (type) {
|
||||
case "vec2" -> 2;
|
||||
case "vec3" -> 3;
|
||||
case "vec4" -> 4;
|
||||
default -> -1;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,7 @@ class CompositeDepthTransformer {
|
||||
final int type = transformer.findType("centerDepthSmooth");
|
||||
if (type != 0) {
|
||||
transformer.injectVariable("uniform sampler2D iris_centerDepthSmooth;");
|
||||
transformer.replaceExpression("centerDepthSmooth", "texture2D(iris_centerDepthSmooth, vec2(0.5)).r");
|
||||
transformer.replaceExpression("centerDepthSmooth", "texture(iris_centerDepthSmooth, vec2(0.5)).r");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,6 +51,13 @@ class CoreTransformHelper {
|
||||
transformer.rename("gl_Vertex", "iris_Vertex");
|
||||
transformer.rename("gl_MultiTexCoord0", "iris_MultiTexCoord0");
|
||||
|
||||
for (int i = 1; i <= 7; i++) {
|
||||
transformer.replaceExpression("gl_MultiTexCoord" + i, "vec4(0.0, 0.0, 0.0, 1.0)");
|
||||
}
|
||||
|
||||
transformer.replaceExpression("gl_Color", "vec4(1.0, 1.0, 1.0, 1.0)");
|
||||
transformer.replaceExpression("gl_Normal", "vec3(0.0, 0.0, 1.0)");
|
||||
|
||||
transformer.renameFunctionCall("ftransform", "iris_ftransform");
|
||||
transformer.injectFunction("vec4 iris_ftransform() { return (iris_ProjectionMatrix * iris_ModelViewMatrix) * iris_Vertex; }");
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package net.coderbot.iris.pipeline.transform;
|
||||
|
||||
import net.coderbot.iris.shaderpack.ProgramSource;
|
||||
import net.coderbot.iris.shaderpack.loading.ProgramId;
|
||||
|
||||
/**
|
||||
* For some reason not all shaders read from gl_MultiTexCoord0 through the texture matrix to scroll the enchant glint?
|
||||
* Maybe a modern thing but a few shaders just look wrong without it. Technically not in spec, but it looks better.
|
||||
*/
|
||||
public final class GlintScrollInjector {
|
||||
|
||||
private GlintScrollInjector() {}
|
||||
|
||||
public static boolean shouldInject(ProgramId id, ProgramSource source) {
|
||||
if (id != ProgramId.ArmorGlint || source == null) return false;
|
||||
if (!ProgramId.ArmorGlint.getSourceName().equals(source.getName())) return false;
|
||||
|
||||
final String vertex = source.getVertexSource().orElse(null);
|
||||
if (vertex == null) return false;
|
||||
// Already scrolls through the texture matrix itself
|
||||
if (vertex.contains("gl_TextureMatrix[0]")) return false;
|
||||
return vertex.contains("gl_MultiTexCoord0");
|
||||
}
|
||||
}
|
||||
@@ -104,8 +104,12 @@ public class TransformPatcher {
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Map<PatchShaderType, String> patchAttributes(String vertex, String geometry, String tessControl, String tessEval, String fragment, InputAvailability inputs, boolean scrollGlint) {
|
||||
return transform(vertex, geometry, tessControl, tessEval, fragment, new AttributeParameters(Patch.ATTRIBUTES, geometry != null, inputs, scrollGlint));
|
||||
}
|
||||
|
||||
public static Map<PatchShaderType, String> patchAttributes(String vertex, String geometry, String tessControl, String tessEval, String fragment, InputAvailability inputs) {
|
||||
return transform(vertex, geometry, tessControl, tessEval, fragment, new AttributeParameters(Patch.ATTRIBUTES, geometry != null, inputs));
|
||||
return patchAttributes(vertex, geometry, tessControl, tessEval, fragment, inputs, false);
|
||||
}
|
||||
|
||||
public static Map<PatchShaderType, String> patchAttributes(String vertex, String geometry, String fragment, InputAvailability inputs) {
|
||||
|
||||
+6
-1
@@ -7,12 +7,14 @@ import net.coderbot.iris.shaderpack.texture.TextureStage;
|
||||
public class AttributeParameters extends Parameters {
|
||||
public final boolean hasGeometry;
|
||||
public final InputAvailability inputs;
|
||||
public final boolean scrollGlint;
|
||||
// WARNING: adding new fields requires updating hashCode and equals methods!
|
||||
|
||||
public AttributeParameters(Patch patch, boolean hasGeometry, InputAvailability inputs) {
|
||||
public AttributeParameters(Patch patch, boolean hasGeometry, InputAvailability inputs, boolean scrollGlint) {
|
||||
super(patch, null);
|
||||
this.hasGeometry = hasGeometry;
|
||||
this.inputs = inputs;
|
||||
this.scrollGlint = scrollGlint;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -25,6 +27,7 @@ public class AttributeParameters extends Parameters {
|
||||
final int prime = 31;
|
||||
int result = super.hashCode();
|
||||
result = prime * result + (hasGeometry ? 1231 : 1237);
|
||||
result = prime * result + (scrollGlint ? 1231 : 1237);
|
||||
result = prime * result + ((inputs == null) ? 0 : inputs.hashCode());
|
||||
return result;
|
||||
}
|
||||
@@ -40,6 +43,8 @@ public class AttributeParameters extends Parameters {
|
||||
AttributeParameters other = (AttributeParameters) obj;
|
||||
if (hasGeometry != other.hasGeometry)
|
||||
return false;
|
||||
if (scrollGlint != other.scrollGlint)
|
||||
return false;
|
||||
if (inputs == null) {
|
||||
if (other.inputs != null)
|
||||
return false;
|
||||
|
||||
@@ -77,11 +77,22 @@ public class IdMap {
|
||||
private static final Pattern LEGACY_DIRECTIVE_PATTERN = Pattern.compile(
|
||||
"(?m)^\\s*#\\s*(?:if|elif|ifdef|ifndef)\\b[^\\n]*\\bMC_VERSION\\b[^\\n]*\\b10710\\b");
|
||||
|
||||
/**
|
||||
* Detects whether a pack's block.properties has a dedicated 1.7.10 section.
|
||||
*/
|
||||
public static boolean detectLegacySection(Path shaderPath) {
|
||||
String rawBlockProperties = readProperties(shaderPath, "block.properties");
|
||||
return rawBlockProperties != null && LEGACY_DIRECTIVE_PATTERN.matcher(rawBlockProperties).find();
|
||||
}
|
||||
|
||||
public static String modernFallbackMcVersion() {
|
||||
return AngelicaConfig.modernFallbackMcVersion > 0
|
||||
? String.valueOf(AngelicaConfig.modernFallbackMcVersion) : "260101";
|
||||
}
|
||||
|
||||
IdMap(Path shaderPath, ShaderPackOptions shaderPackOptions, Iterable<StringPair> environmentDefines) {
|
||||
// Check if block.properties has a dedicated 1.7.10 section
|
||||
String rawBlockProperties = readProperties(shaderPath, "block.properties");
|
||||
this.hasLegacySection = rawBlockProperties != null
|
||||
&& LEGACY_DIRECTIVE_PATTERN.matcher(rawBlockProperties).find();
|
||||
this.hasLegacySection = detectLegacySection(shaderPath);
|
||||
|
||||
Iterable<StringPair> resolvedDefines;
|
||||
if (this.hasLegacySection) {
|
||||
@@ -100,9 +111,7 @@ public class IdMap {
|
||||
}
|
||||
}
|
||||
|
||||
String modernVersion = AngelicaConfig.modernFallbackMcVersion > 0
|
||||
? String.valueOf(AngelicaConfig.modernFallbackMcVersion) : "260101";
|
||||
modernDefines.add(new StringPair("MC_VERSION", modernVersion));
|
||||
modernDefines.add(new StringPair("MC_VERSION", modernFallbackMcVersion()));
|
||||
resolvedDefines = modernDefines;
|
||||
|
||||
loadProperties(shaderPath, "block.properties", shaderPackOptions, modernDefines).ifPresent(blockProperties -> {
|
||||
|
||||
@@ -55,7 +55,7 @@ public class PackRenderTargetDirectives {
|
||||
|
||||
renderTargetSettings.forEach((index, settings) -> {
|
||||
if (settings.shouldClear()) {
|
||||
buffersToBeCleared.add(index.intValue());
|
||||
buffersToBeCleared.add(index);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.coderbot.iris.shaderpack;
|
||||
|
||||
import net.coderbot.iris.Iris;
|
||||
import net.coderbot.iris.features.FeatureFlags;
|
||||
import net.coderbot.iris.gl.blending.BlendModeOverride;
|
||||
import net.coderbot.iris.shaderpack.include.AbsolutePackPath;
|
||||
import net.coderbot.iris.shaderpack.loading.ProgramId;
|
||||
@@ -529,7 +530,8 @@ public class ProgramSet {
|
||||
|
||||
String tessControlSource = null;
|
||||
String tessEvalSource = null;
|
||||
if (programSet.pack.hasFeature(net.coderbot.iris.features.FeatureFlags.TESSELLATION_SHADERS)) {
|
||||
if (programSet.pack.hasFeature(FeatureFlags.TESSELLATION_SHADERS)
|
||||
&& FeatureFlags.TESSELLATION_SHADERS.isUsable()) {
|
||||
AbsolutePackPath tessControlPath = directory.resolve(program + ".tcs");
|
||||
tessControlSource = sourceProvider.apply(tessControlPath);
|
||||
|
||||
@@ -547,6 +549,10 @@ public class ProgramSet {
|
||||
private static ComputeSource readComputeSource(AbsolutePackPath directory,
|
||||
Function<AbsolutePackPath, String> sourceProvider, String program,
|
||||
ProgramSet programSet) {
|
||||
if (!FeatureFlags.COMPUTE_SHADERS.isUsable()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
AbsolutePackPath computePath = directory.resolve(program + ".csh");
|
||||
String computeSource = sourceProvider.apply(computePath);
|
||||
|
||||
|
||||
@@ -207,8 +207,16 @@ public class ShaderPack {
|
||||
this.shaderPackOptions = new ShaderPackOptions(graph, changedConfigs);
|
||||
graph = this.shaderPackOptions.getIncludes();
|
||||
|
||||
final String mcVersionOverride = IdMap.detectLegacySection(root) ? null : IdMap.modernFallbackMcVersion();
|
||||
|
||||
List<StringPair> finalEnvironmentDefines = new ArrayList<>();
|
||||
environmentDefines.forEach(finalEnvironmentDefines::add);
|
||||
for (StringPair define : environmentDefines) {
|
||||
if (mcVersionOverride != null && "MC_VERSION".equals(define.getKey())) {
|
||||
finalEnvironmentDefines.add(new StringPair("MC_VERSION", mcVersionOverride));
|
||||
} else {
|
||||
finalEnvironmentDefines.add(define);
|
||||
}
|
||||
}
|
||||
for (FeatureFlags flag : FeatureFlags.values()) {
|
||||
boolean usable = flag.isUsable();
|
||||
Iris.logger.info("FeatureFlag {} usable: {}", flag.name(), usable);
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package net.coderbot.iris.shaderpack.loading;
|
||||
|
||||
public enum ProgramArrayId {
|
||||
Setup(ProgramGroup.Setup, 100),
|
||||
Begin(ProgramGroup.Begin, 100),
|
||||
ShadowComposite(ProgramGroup.ShadowComposite, 99),
|
||||
Prepare(ProgramGroup.Prepare, 99),
|
||||
Deferred(ProgramGroup.Deferred, 99),
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
package net.coderbot.iris.shaderpack.loading;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum ProgramGroup {
|
||||
Setup("setup"),
|
||||
Begin("begin"),
|
||||
Shadow("shadow"),
|
||||
ShadowComposite("shadowcomp"),
|
||||
Prepare("prepare"),
|
||||
@@ -17,7 +22,4 @@ public enum ProgramGroup {
|
||||
this.baseName = baseName;
|
||||
}
|
||||
|
||||
public String getBaseName() {
|
||||
return baseName;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
package net.coderbot.iris.shaderpack.materialmap;
|
||||
|
||||
import net.coderbot.iris.Iris;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -263,7 +263,19 @@ public final class PropertiesTokenizer {
|
||||
);
|
||||
}
|
||||
|
||||
final String[] splitStates = baseEntry.split(":");
|
||||
// Drop empty segments produced by consecutive colons (like "betterendforge::lumecorn")
|
||||
final String[] splitStates = Arrays.stream(baseEntry.split(":"))
|
||||
.filter(s -> !s.isEmpty())
|
||||
.toArray(String[]::new);
|
||||
|
||||
if (splitStates.length == 0) {
|
||||
return new ParsedBlockIdentifier(
|
||||
new NamespacedId("minecraft", baseEntry),
|
||||
Collections.emptySet(),
|
||||
Collections.emptyMap(),
|
||||
nbtProperties
|
||||
);
|
||||
}
|
||||
|
||||
// Vanilla block (minecraft namespaced)
|
||||
if (splitStates.length == 1) {
|
||||
@@ -277,7 +289,7 @@ public final class PropertiesTokenizer {
|
||||
|
||||
// Two-segment with no metas/state properties: "minecraft:stone"
|
||||
if (splitStates.length == 2
|
||||
&& !StringUtils.isNumeric(splitStates[1].substring(0, 1))
|
||||
&& !startsWithDigit(splitStates[1])
|
||||
&& !splitStates[1].contains("=")) {
|
||||
return new ParsedBlockIdentifier(
|
||||
new NamespacedId(splitStates[0], splitStates[1]),
|
||||
@@ -296,7 +308,7 @@ public final class PropertiesTokenizer {
|
||||
id = new NamespacedId("minecraft", splitStates[0]);
|
||||
statesStart = 1;
|
||||
|
||||
} else if (StringUtils.isNumeric(splitStates[1].substring(0, 1)) || splitStates[1].contains("=")) {
|
||||
} else if (startsWithDigit(splitStates[1]) || splitStates[1].contains("=")) {
|
||||
// "stone:0:something" or "stone:lit=true:something", likely will need this for snowy blocks in the future.
|
||||
id = new NamespacedId("minecraft", splitStates[0]);
|
||||
statesStart = 1;
|
||||
@@ -339,6 +351,10 @@ public final class PropertiesTokenizer {
|
||||
);
|
||||
}
|
||||
|
||||
private static boolean startsWithDigit(String s) {
|
||||
return !s.isEmpty() && Character.isDigit(s.charAt(0));
|
||||
}
|
||||
|
||||
private static void appendCurrent(boolean inBracket, boolean readingValue,
|
||||
StringBuilder blockIdBuilder, StringBuilder nbtKey,
|
||||
StringBuilder nbtValue, char c) {
|
||||
|
||||
@@ -80,7 +80,7 @@ public class PropertiesPreprocessor {
|
||||
// Not super efficient, but this removes trailing whitespace on lines, fixing an issue with whitespace after
|
||||
// line continuations (see PreprocessorTest#testWeirdPropertiesLineContinuation)
|
||||
// Required for Voyager Shader
|
||||
source = Arrays.stream(source.split("\\R")).map(String::trim).filter(s -> !s.isEmpty())
|
||||
source = Arrays.stream(source.split("\\r\\n|\\n|\\r")).map(String::trim).filter(s -> !s.isEmpty())
|
||||
.map(line -> {
|
||||
if (line.startsWith("#")) {
|
||||
for (PreprocessorCommand command : PreprocessorCommand.values()) {
|
||||
|
||||
@@ -13,6 +13,9 @@ public class CapturedRenderingState {
|
||||
@Getter
|
||||
private float tickDelta;
|
||||
@Getter
|
||||
private int textureReloadCount;
|
||||
private Runnable textureReloadListener = null;
|
||||
@Getter
|
||||
private int currentRenderedBlockEntity;
|
||||
private Runnable blockEntityIdListener = null;
|
||||
|
||||
@@ -31,6 +34,18 @@ public class CapturedRenderingState {
|
||||
private CapturedRenderingState() {
|
||||
}
|
||||
|
||||
public void incrementTextureReloadCount() {
|
||||
this.textureReloadCount++;
|
||||
|
||||
if (this.textureReloadListener != null) {
|
||||
this.textureReloadListener.run();
|
||||
}
|
||||
}
|
||||
|
||||
public void resetTextureReloadCount() {
|
||||
this.textureReloadCount = 0;
|
||||
}
|
||||
|
||||
public void setCurrentBlockEntity(int entity) {
|
||||
this.currentRenderedBlockEntity = entity;
|
||||
|
||||
@@ -80,5 +95,9 @@ public class CapturedRenderingState {
|
||||
return listener -> this.itemIdListener = listener;
|
||||
}
|
||||
|
||||
public ValueUpdateNotifier getTextureReloadNotifier() {
|
||||
return listener -> this.textureReloadListener = listener;
|
||||
}
|
||||
|
||||
public ValueUpdateNotifier getEntityColorNotifier() { return listener -> this.entityColorListener = listener; }
|
||||
}
|
||||
@@ -96,6 +96,12 @@ public final class CommonUniforms {
|
||||
|
||||
}, StateUpdateNotifiers.bindTextureNotifier);
|
||||
|
||||
uniforms.uniform1i("gtextureId", () -> GLStateManager.getBoundTextureForServerState(0),
|
||||
StateUpdateNotifiers.bindTextureNotifier);
|
||||
|
||||
uniforms.uniform1i("textureReloadCount", CapturedRenderingState.INSTANCE::getTextureReloadCount,
|
||||
CapturedRenderingState.INSTANCE.getTextureReloadNotifier());
|
||||
|
||||
uniforms.uniform4i("blendFunc", () -> {
|
||||
if(GLStateManager.getBlendMode().isEnabled()) {
|
||||
final BlendState blend = GLStateManager.getBlendState();
|
||||
|
||||
@@ -1,18 +1,27 @@
|
||||
package net.coderbot.iris.uniforms;
|
||||
|
||||
import com.gtnewhorizons.angelica.compat.etfuturum.EtFuturumCompat;
|
||||
import com.gtnewhorizons.angelica.compat.mojang.Camera;
|
||||
import com.gtnewhorizons.angelica.compat.mojang.GameModeUtil;
|
||||
import com.gtnewhorizons.angelica.render.CloudRenderer;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectMap;
|
||||
import net.coderbot.iris.block_rendering.BlockMaterialMapping;
|
||||
import net.coderbot.iris.block_rendering.BlockRenderingSettings;
|
||||
import net.coderbot.iris.gl.uniform.UniformHolder;
|
||||
import net.coderbot.iris.gl.uniform.UniformUpdateFrequency;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.effect.EntityLightningBolt;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.util.MovingObjectPosition;
|
||||
import org.joml.Math;
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector3dc;
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.Vector4f;
|
||||
|
||||
import java.util.List;
|
||||
@@ -21,9 +30,17 @@ public class IrisExclusiveUniforms {
|
||||
// Reusable vectors to avoid allocations every frame
|
||||
private static final Vector3d eyePositionCache = new Vector3d();
|
||||
private static final Vector3d relativeEyePositionCache = new Vector3d();
|
||||
private static final Vector3d playerLookCache = new Vector3d();
|
||||
private static final Vector3d playerBodyCache = new Vector3d();
|
||||
private static final Vector3d vehicleLookCache = new Vector3d();
|
||||
private static final Vector3d relativeVehiclePositionCache = new Vector3d();
|
||||
private static final Vector3f selectedBlockPosCache = new Vector3f();
|
||||
private static final Vector4f lightningBoltPositionCache = new Vector4f();
|
||||
private static final Vector4f ZERO_VECTOR_4f = new Vector4f(0, 0, 0, 0);
|
||||
|
||||
private static int cachedSelectedFrame = -1;
|
||||
private static int cachedSelectedBlockId;
|
||||
|
||||
public static void addIrisExclusiveUniforms(UniformHolder uniforms) {
|
||||
WorldInfoUniforms.addWorldInfoUniforms(uniforms);
|
||||
|
||||
@@ -42,6 +59,21 @@ public class IrisExclusiveUniforms {
|
||||
uniforms.uniform3d(UniformUpdateFrequency.PER_FRAME, "relativeEyePosition", IrisExclusiveUniforms::getRelativeEyePosition);
|
||||
uniforms.uniform4f(UniformUpdateFrequency.PER_TICK, "lightningBoltPosition", IrisExclusiveUniforms::getLightningBoltPosition);
|
||||
uniforms.uniform1f(UniformUpdateFrequency.PER_FRAME, "cloudTime", IrisExclusiveUniforms::getCloudTime);
|
||||
uniforms.uniform1b(UniformUpdateFrequency.PER_TICK, "feetInWater", IrisExclusiveUniforms::isFeetInWater);
|
||||
uniforms.uniform1b(UniformUpdateFrequency.PER_TICK, "isRiding", IrisExclusiveUniforms::isRiding);
|
||||
uniforms.uniform1b(UniformUpdateFrequency.PER_TICK, "vehicleInWater", IrisExclusiveUniforms::isVehicleInWater);
|
||||
uniforms.uniform1i(UniformUpdateFrequency.PER_TICK, "vehicleId", IrisExclusiveUniforms::getVehicleId);
|
||||
uniforms.uniform3d(UniformUpdateFrequency.PER_FRAME, "vehicleLookVector", IrisExclusiveUniforms::getVehicleLookVector);
|
||||
uniforms.uniform3d(UniformUpdateFrequency.PER_FRAME, "relativeVehiclePosition", IrisExclusiveUniforms::getRelativeVehiclePosition);
|
||||
uniforms.uniform1f(UniformUpdateFrequency.PER_TICK, "currentPlayerArmor", IrisExclusiveUniforms::getCurrentArmor);
|
||||
uniforms.uniform1f(UniformUpdateFrequency.PER_TICK, "maxPlayerArmor", () -> 50);
|
||||
uniforms.uniform1i(UniformUpdateFrequency.PER_FRAME, "currentSelectedBlockId", IrisExclusiveUniforms::getCurrentSelectedBlockId);
|
||||
uniforms.uniform3f(UniformUpdateFrequency.PER_FRAME, "currentSelectedBlockPos", IrisExclusiveUniforms::getCurrentSelectedBlockPos);
|
||||
uniforms.uniform1i(UniformUpdateFrequency.PER_FRAME, "seaLevel", IrisExclusiveUniforms::getSeaLevel);
|
||||
uniforms.uniform3d(UniformUpdateFrequency.PER_FRAME, "playerLookVector", IrisExclusiveUniforms::getPlayerLookVector);
|
||||
uniforms.uniform3d(UniformUpdateFrequency.PER_FRAME, "playerBodyVector", IrisExclusiveUniforms::getPlayerBodyVector);
|
||||
// Target the Elytra from EFR
|
||||
uniforms.uniform1b(UniformUpdateFrequency.PER_TICK, "isElytraFlying", IrisExclusiveUniforms::isElytraFlying);
|
||||
}
|
||||
|
||||
private static float getCloudTime() {
|
||||
@@ -137,6 +169,149 @@ public class IrisExclusiveUniforms {
|
||||
return ZERO_VECTOR_4f;
|
||||
}
|
||||
|
||||
private static EntityLivingBase cameraEntity() {
|
||||
return Minecraft.getMinecraft().renderViewEntity;
|
||||
}
|
||||
|
||||
private static Vector3d forwardVector(Vector3d dest, float yawDeg, float pitchDeg) {
|
||||
final double yr = -yawDeg * 0.017453292 - Math.PI;
|
||||
final double pr = -pitchDeg * 0.017453292;
|
||||
final double cy = Math.cos(yr);
|
||||
final double sy = Math.sin(yr);
|
||||
final double cp = -Math.cos(pr);
|
||||
final double sp = Math.sin(pr);
|
||||
return dest.set(sy * cp, sp, cy * cp);
|
||||
}
|
||||
|
||||
private static boolean isFeetInWater() {
|
||||
final EntityPlayer player = Minecraft.getMinecraft().thePlayer;
|
||||
return player != null && player.isInWater();
|
||||
}
|
||||
|
||||
private static boolean isElytraFlying() {
|
||||
return EtFuturumCompat.isElytraFlying(Minecraft.getMinecraft().thePlayer);
|
||||
}
|
||||
|
||||
private static boolean isRiding() {
|
||||
final EntityPlayer player = Minecraft.getMinecraft().thePlayer;
|
||||
return player != null && player.ridingEntity != null;
|
||||
}
|
||||
|
||||
private static boolean isVehicleInWater() {
|
||||
final EntityPlayer player = Minecraft.getMinecraft().thePlayer;
|
||||
return player != null && player.ridingEntity != null && player.ridingEntity.isInWater();
|
||||
}
|
||||
|
||||
private static int getVehicleId() {
|
||||
final EntityPlayer player = Minecraft.getMinecraft().thePlayer;
|
||||
if (player == null || player.ridingEntity == null) return 0;
|
||||
final int id = EntityIdHelper.getEntityId(player.ridingEntity);
|
||||
return Math.max(id, 0);
|
||||
}
|
||||
|
||||
private static Vector3d getVehicleLookVector() {
|
||||
final EntityPlayer player = Minecraft.getMinecraft().thePlayer;
|
||||
if (player == null || player.ridingEntity == null) return vehicleLookCache.set(0, 0, 0);
|
||||
final Entity v = player.ridingEntity;
|
||||
return forwardVector(vehicleLookCache, v.rotationYaw, v.rotationPitch);
|
||||
}
|
||||
|
||||
private static Vector3d getRelativeVehiclePosition() {
|
||||
final EntityPlayer player = Minecraft.getMinecraft().thePlayer;
|
||||
if (player == null || player.ridingEntity == null) return relativeVehiclePositionCache.set(0, 0, 0);
|
||||
final Entity v = player.ridingEntity;
|
||||
final float delta = CapturedRenderingState.INSTANCE.getTickDelta();
|
||||
final double vx = v.prevPosX + (v.posX - v.prevPosX) * delta;
|
||||
final double vy = v.prevPosY + (v.posY - v.prevPosY) * delta;
|
||||
final double vz = v.prevPosZ + (v.posZ - v.prevPosZ) * delta;
|
||||
// Match Angelica's relativeEyePosition convention (entity - camera).
|
||||
final Vector3dc cam = CameraUniforms.getUnshiftedCameraPosition();
|
||||
return relativeVehiclePositionCache.set(vx - cam.x(), vy - cam.y(), vz - cam.z());
|
||||
}
|
||||
|
||||
private static float getCurrentArmor() {
|
||||
final Minecraft mc = Minecraft.getMinecraft();
|
||||
if (mc.thePlayer == null || !mc.playerController.gameIsSurvivalOrAdventure()) {
|
||||
return -1;
|
||||
}
|
||||
return mc.thePlayer.getTotalArmorValue() / 50.0f;
|
||||
}
|
||||
|
||||
private static Vector3d getPlayerLookVector() {
|
||||
final EntityLivingBase e = cameraEntity();
|
||||
if (e == null) return playerLookCache.set(0, 0, 0);
|
||||
final float delta = CapturedRenderingState.INSTANCE.getTickDelta();
|
||||
final float yaw = e.prevRotationYaw + (e.rotationYaw - e.prevRotationYaw) * delta;
|
||||
final float pitch = e.prevRotationPitch + (e.rotationPitch - e.prevRotationPitch) * delta;
|
||||
return forwardVector(playerLookCache, yaw, pitch);
|
||||
}
|
||||
|
||||
private static Vector3d getPlayerBodyVector() {
|
||||
final EntityLivingBase e = cameraEntity();
|
||||
if (e == null) return playerBodyCache.set(0, 0, 0);
|
||||
return forwardVector(playerBodyCache, e.renderYawOffset, 0.0f);
|
||||
}
|
||||
|
||||
private static int getSeaLevel() {
|
||||
// 1.7.10 has no per-world sea level accessor, best to guess 63?
|
||||
return 63;
|
||||
}
|
||||
|
||||
private static void updateSelectedBlock() {
|
||||
final int frame = SystemTimeUniforms.COUNTER.getAsInt();
|
||||
if (frame == cachedSelectedFrame) {
|
||||
return;
|
||||
}
|
||||
cachedSelectedFrame = frame;
|
||||
|
||||
final Minecraft mc = Minecraft.getMinecraft();
|
||||
final MovingObjectPosition hit = mc.objectMouseOver;
|
||||
if (mc.theWorld == null || hit == null || hit.typeOfHit != MovingObjectPosition.MovingObjectType.BLOCK) {
|
||||
cachedSelectedBlockId = 0;
|
||||
selectedBlockPosCache.set(-256.0f, -256.0f, -256.0f);
|
||||
return;
|
||||
}
|
||||
|
||||
final Vector3dc cam = CameraUniforms.getUnshiftedCameraPosition();
|
||||
selectedBlockPosCache.set(
|
||||
(float) ((hit.blockX + 0.5) - cam.x()),
|
||||
(float) ((hit.blockY + 0.5) - cam.y()),
|
||||
(float) ((hit.blockZ + 0.5) - cam.z()));
|
||||
|
||||
final Block block = mc.theWorld.getBlock(hit.blockX, hit.blockY, hit.blockZ);
|
||||
if (block == null || block.isAir(mc.theWorld, hit.blockX, hit.blockY, hit.blockZ)) {
|
||||
cachedSelectedBlockId = 0;
|
||||
return;
|
||||
}
|
||||
final Reference2ObjectMap<Block, Int2IntMap> blockMetaMatches = BlockRenderingSettings.INSTANCE.getBlockMetaMatches();
|
||||
if (blockMetaMatches == null) {
|
||||
cachedSelectedBlockId = 0;
|
||||
return;
|
||||
}
|
||||
final Int2IntMap metaMap = blockMetaMatches.get(block);
|
||||
if (metaMap == null) {
|
||||
cachedSelectedBlockId = 0;
|
||||
return;
|
||||
}
|
||||
final int meta = mc.theWorld.getBlockMetadata(hit.blockX, hit.blockY, hit.blockZ);
|
||||
cachedSelectedBlockId = Math.max(BlockMaterialMapping.resolveId(metaMap, meta), 0);
|
||||
}
|
||||
|
||||
private static int getCurrentSelectedBlockId() {
|
||||
updateSelectedBlock();
|
||||
return cachedSelectedBlockId;
|
||||
}
|
||||
|
||||
private static Vector3f getCurrentSelectedBlockPos() {
|
||||
updateSelectedBlock();
|
||||
return selectedBlockPosCache;
|
||||
}
|
||||
|
||||
private static int worldHeight() {
|
||||
final WorldClient level = Minecraft.getMinecraft().theWorld;
|
||||
return (level != null && level.provider != null) ? level.provider.getHeight() : 256;
|
||||
}
|
||||
|
||||
public static class WorldInfoUniforms {
|
||||
public static void addWorldInfoUniforms(UniformHolder uniforms) {
|
||||
uniforms.uniform1i(UniformUpdateFrequency.PER_FRAME, "bedrockLevel", () -> 0);
|
||||
@@ -148,14 +323,8 @@ public class IrisExclusiveUniforms {
|
||||
return 192.0;
|
||||
}
|
||||
});
|
||||
uniforms.uniform1i(UniformUpdateFrequency.PER_FRAME, "heightLimit", () -> {
|
||||
final WorldClient level = Minecraft.getMinecraft().theWorld;
|
||||
if (level != null && level.provider != null) {
|
||||
return level.provider.getHeight();
|
||||
} else {
|
||||
return 256;
|
||||
}
|
||||
});
|
||||
uniforms.uniform1i(UniformUpdateFrequency.PER_FRAME, "heightLimit", IrisExclusiveUniforms::worldHeight);
|
||||
uniforms.uniform1i(UniformUpdateFrequency.PER_FRAME, "logicalHeightLimit", IrisExclusiveUniforms::worldHeight);
|
||||
uniforms.uniform1b(UniformUpdateFrequency.PER_FRAME, "hasCeiling", () -> {
|
||||
final WorldClient level = Minecraft.getMinecraft().theWorld;
|
||||
if (level != null && level.provider != null) {
|
||||
|
||||
@@ -3,7 +3,10 @@ package net.coderbot.iris.uniforms;
|
||||
import lombok.Getter;
|
||||
import net.coderbot.iris.gl.uniform.UniformHolder;
|
||||
import net.coderbot.iris.gl.uniform.UniformUpdateFrequency;
|
||||
import org.joml.Vector2i;
|
||||
import org.joml.Vector3i;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.OptionalLong;
|
||||
import java.util.function.IntSupplier;
|
||||
|
||||
@@ -16,19 +19,47 @@ public final class SystemTimeUniforms {
|
||||
public static final Timer TIMER = new Timer();
|
||||
public static final FrameCounter COUNTER = new FrameCounter();
|
||||
|
||||
private static LocalDateTime cachedDateTime = LocalDateTime.now();
|
||||
private static long cachedDateTimeAtMs = 0L;
|
||||
|
||||
private SystemTimeUniforms() {
|
||||
}
|
||||
|
||||
private static LocalDateTime dateTimeSnapshot() {
|
||||
final long now = System.currentTimeMillis();
|
||||
if (now - cachedDateTimeAtMs >= 50L) {
|
||||
cachedDateTime = LocalDateTime.now();
|
||||
cachedDateTimeAtMs = now;
|
||||
}
|
||||
return cachedDateTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes system time uniforms available to the given program
|
||||
*
|
||||
* @param uniforms the program to make the uniforms available to
|
||||
*/
|
||||
public static void addSystemTimeUniforms(UniformHolder uniforms) {
|
||||
final Vector3i date = new Vector3i();
|
||||
final Vector3i time = new Vector3i();
|
||||
final Vector2i yearTime = new Vector2i();
|
||||
uniforms
|
||||
.uniform1i(UniformUpdateFrequency.PER_FRAME, "frameCounter", COUNTER)
|
||||
.uniform1f(UniformUpdateFrequency.PER_FRAME, "frameTime", TIMER::getLastFrameTime)
|
||||
.uniform1f(UniformUpdateFrequency.PER_FRAME, "frameTimeCounter", TIMER::getFrameTimeCounter);
|
||||
.uniform1f(UniformUpdateFrequency.PER_FRAME, "frameTimeCounter", TIMER::getFrameTimeCounter)
|
||||
.uniform3i(UniformUpdateFrequency.PER_TICK, "currentDate", () -> {
|
||||
final LocalDateTime dt = dateTimeSnapshot();
|
||||
return date.set(dt.getYear(), dt.getMonthValue(), dt.getDayOfMonth());
|
||||
})
|
||||
.uniform3i(UniformUpdateFrequency.PER_TICK, "currentTime", () -> {
|
||||
final LocalDateTime dt = dateTimeSnapshot();
|
||||
return time.set(dt.getHour(), dt.getMinute(), dt.getSecond());
|
||||
})
|
||||
.uniform2i(UniformUpdateFrequency.PER_TICK, "currentYearTime", () -> {
|
||||
final LocalDateTime dt = dateTimeSnapshot();
|
||||
final int elapsed = ((dt.getDayOfYear() - 1) * 86400) + (dt.getHour() * 3600) + (dt.getMinute() * 60) + dt.getSecond();
|
||||
return yearTime.set(elapsed, (dt.toLocalDate().lengthOfYear() * 86400) - elapsed);
|
||||
});
|
||||
}
|
||||
|
||||
public static void addFloatFrameMod8Uniform(UniformHolder uniforms) {
|
||||
|
||||
@@ -78,3 +78,7 @@ options.void_fog=Void Fog
|
||||
options.void_fog.tooltip=Void Fog
|
||||
options.hurt_shake=Hurt Screen Shake
|
||||
options.background.random=Random
|
||||
options.zoom_smooth=Smooth Zoom
|
||||
options.zoom_smooth.tooltip=Smoothly interpolates the camera toward the zoom level instead of snapping instantly.
|
||||
options.zoom_smooth_speed=Smooth Zoom Speed
|
||||
options.zoom_smooth_speed.tooltip=How fast smooth zoom converges to the target zoom. Higher is snappier, lower is floatier. No effect when Smooth Zoom is off.
|
||||
+3
@@ -1,5 +1,7 @@
|
||||
package com.gtnewhorizons.angelica.mixins.early.angelica;
|
||||
|
||||
import com.gtnewhorizons.angelica.event.ClientEvent;
|
||||
import com.gtnewhorizons.angelica.event.ClientEventType;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.EntityRenderer;
|
||||
import net.minecraft.client.shader.Framebuffer;
|
||||
@@ -15,6 +17,7 @@ public class MixinMinecraft_IconifyGuard {
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/EntityRenderer;updateCameraAndRender(F)V")
|
||||
)
|
||||
private void angelica$skipRenderWhenIconified(EntityRenderer entityRenderer, float partialTicks) {
|
||||
ClientEvent.post(ClientEventType.ON_TICK);
|
||||
final Framebuffer fb = Minecraft.getMinecraft().getFramebuffer();
|
||||
if (fb == null || fb.framebufferWidth < 16 || fb.framebufferHeight < 16) {
|
||||
return;
|
||||
|
||||
+12
-70
@@ -13,7 +13,6 @@ import net.minecraft.client.renderer.entity.RendererLivingEntity;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL14;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
@@ -23,6 +22,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
/**
|
||||
* Single-pass damage-overlay tint, modeled on modern Minecraft's OverlayTexture.
|
||||
* The tint is applied only while the main body model renders.
|
||||
*/
|
||||
@Mixin(RendererLivingEntity.class)
|
||||
public class MixinRendererLivingEntity_OverlayTint {
|
||||
@@ -33,8 +33,6 @@ public class MixinRendererLivingEntity_OverlayTint {
|
||||
@Unique private boolean angelica$ffpOverlayActive;
|
||||
@Unique private boolean angelica$shaderEntityColorActive;
|
||||
|
||||
@Unique private boolean angelica$emissivePass;
|
||||
|
||||
@Inject(
|
||||
method = "doRender(Lnet/minecraft/entity/EntityLivingBase;DDDFF)V",
|
||||
at = @At(value = "INVOKE",
|
||||
@@ -64,20 +62,13 @@ public class MixinRendererLivingEntity_OverlayTint {
|
||||
@Inject(
|
||||
method = "doRender(Lnet/minecraft/entity/EntityLivingBase;DDDFF)V",
|
||||
at = @At(value = "INVOKE",
|
||||
target = "Lnet/minecraft/client/renderer/entity/RendererLivingEntity;renderEquippedItems(Lnet/minecraft/entity/EntityLivingBase;F)V"),
|
||||
target = "Lnet/minecraft/client/renderer/entity/RendererLivingEntity;renderModel(Lnet/minecraft/entity/EntityLivingBase;FFFFFF)V",
|
||||
shift = At.Shift.AFTER),
|
||||
require = 1, expect = 1
|
||||
)
|
||||
private void angelica$teardownOverlay(EntityLivingBase entity, double x, double y, double z,
|
||||
float yaw, float partialTick, CallbackInfo ci) {
|
||||
if (angelica$ffpOverlayActive) {
|
||||
GLStateManager.setOverlayColor(0.0F, 0.0F, 0.0F, 0.0F);
|
||||
angelica$ffpOverlayActive = false;
|
||||
}
|
||||
if (angelica$shaderEntityColorActive) {
|
||||
// Don't tint held items
|
||||
CapturedRenderingState.INSTANCE.setCurrentEntityColor(0.0F, 0.0F, 0.0F, 0.0F);
|
||||
angelica$shaderEntityColorActive = false;
|
||||
}
|
||||
private void angelica$clearBodyTint(EntityLivingBase entity, double x, double y, double z,
|
||||
float yaw, float partialTick, CallbackInfo ci) {
|
||||
angelica$clearOverlayColor();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,64 +91,17 @@ public class MixinRendererLivingEntity_OverlayTint {
|
||||
original.call(model, entity, p1, p2, p3, p4, p5, p6);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent bleed by saving last state and comparing with current blend state.
|
||||
*/
|
||||
@WrapOperation(
|
||||
method = "doRender(Lnet/minecraft/entity/EntityLivingBase;DDDFF)V",
|
||||
at = @At(value = "INVOKE",
|
||||
target = "Lnet/minecraft/client/renderer/entity/RendererLivingEntity;shouldRenderPass(Lnet/minecraft/entity/EntityLivingBase;IF)I"),
|
||||
require = 1, expect = 1
|
||||
)
|
||||
private int angelica$detectEmissivePass(RendererLivingEntity self, EntityLivingBase entity, int pass,
|
||||
float partialTick, Operation<Integer> original) {
|
||||
GLStateManager.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
final int result = original.call(self, entity, pass, partialTick);
|
||||
final int srcAfter = GLStateManager.glGetInteger(GL14.GL_BLEND_SRC_RGB);
|
||||
final int dstAfter = GLStateManager.glGetInteger(GL14.GL_BLEND_DST_RGB);
|
||||
angelica$emissivePass = srcAfter == GL11.GL_ONE && dstAfter == GL11.GL_ONE;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip the overlay on emissive eye pass.
|
||||
*/
|
||||
@WrapOperation(
|
||||
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"),
|
||||
to = @At(value = "INVOKE",
|
||||
target = "Lnet/minecraft/client/renderer/entity/RendererLivingEntity;renderEquippedItems(Lnet/minecraft/entity/EntityLivingBase;F)V")
|
||||
),
|
||||
require = 1, expect = 1
|
||||
)
|
||||
private void angelica$untintEmissivePass(ModelBase model, Entity entity,
|
||||
float p1, float p2, float p3, float p4, float p5, float p6, Operation<Void> original) {
|
||||
if (!angelica$skipReRender || !angelica$emissivePass) {
|
||||
original.call(model, entity, p1, p2, p3, p4, p5, p6);
|
||||
return;
|
||||
}
|
||||
if (angelica$ffpOverlayActive) {
|
||||
GLStateManager.setOverlayColor(0.0F, 0.0F, 0.0F, 0.0F);
|
||||
original.call(model, entity, p1, p2, p3, p4, p5, p6);
|
||||
GLStateManager.setOverlayColor(1.0F, 0.0F, 0.0F, ANGELICA$RED_MIX);
|
||||
} else if (angelica$shaderEntityColorActive) {
|
||||
CapturedRenderingState.INSTANCE.setCurrentEntityColor(0.0F, 0.0F, 0.0F, 0.0F);
|
||||
original.call(model, entity, p1, p2, p3, p4, p5, p6);
|
||||
CapturedRenderingState.INSTANCE.setCurrentEntityColor(1.0F, 0.0F, 0.0F, ANGELICA$RED_MIX);
|
||||
} else {
|
||||
original.call(model, entity, p1, p2, p3, p4, p5, p6);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "doRender(Lnet/minecraft/entity/EntityLivingBase;DDDFF)V",
|
||||
at = @At("RETURN")
|
||||
)
|
||||
private void angelica$reset(CallbackInfo ci) {
|
||||
angelica$clearOverlayColor();
|
||||
angelica$skipReRender = false;
|
||||
}
|
||||
|
||||
@Unique
|
||||
private void angelica$clearOverlayColor() {
|
||||
if (angelica$ffpOverlayActive) {
|
||||
GLStateManager.setOverlayColor(0.0F, 0.0F, 0.0F, 0.0F);
|
||||
angelica$ffpOverlayActive = false;
|
||||
@@ -166,8 +110,6 @@ public class MixinRendererLivingEntity_OverlayTint {
|
||||
CapturedRenderingState.INSTANCE.setCurrentEntityColor(0.0F, 0.0F, 0.0F, 0.0F);
|
||||
angelica$shaderEntityColorActive = false;
|
||||
}
|
||||
angelica$skipReRender = false;
|
||||
angelica$emissivePass = false;
|
||||
}
|
||||
|
||||
@Unique
|
||||
|
||||
+2
-4
@@ -16,10 +16,8 @@ public class MixinEntityRenderer_Zoom {
|
||||
|
||||
@ModifyReturnValue(method = "getFOVModifier", at = @At("RETURN"))
|
||||
private float angelica$modifyFOV(float original) {
|
||||
if (Zoom.getZoomKey().getIsKeyPressed()) {
|
||||
return original / Zoom.getZoom();
|
||||
}
|
||||
return original;
|
||||
final float current = Zoom.getCurrentZoom();
|
||||
return current > 1.0001F ? original / current : original;
|
||||
}
|
||||
|
||||
@ModifyConstant(method = "updateCameraAndRender", constant = @Constant(floatValue = 8.0F))
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.gtnewhorizons.angelica.mixins.early.shaders;
|
||||
|
||||
import com.gtnewhorizons.angelica.compat.mojang.InteractionHand;
|
||||
import com.gtnewhorizons.angelica.shadercompat.ShaderGlint;
|
||||
import net.coderbot.iris.gbuffer_overrides.matching.SpecialCondition;
|
||||
import net.coderbot.iris.layer.GbufferPrograms;
|
||||
import net.coderbot.iris.pipeline.HandRenderer;
|
||||
@@ -63,6 +64,7 @@ public class MixinItemRenderer {
|
||||
private void iris$glintStart(CallbackInfo ci) {
|
||||
ItemIdManager.resetItemId();
|
||||
GbufferPrograms.setupSpecialRenderCondition(SpecialCondition.GLINT);
|
||||
ShaderGlint.beginGlint();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,5 +77,6 @@ public class MixinItemRenderer {
|
||||
)
|
||||
private void iris$glintEnd(CallbackInfo ci) {
|
||||
GbufferPrograms.teardownSpecialRenderCondition();
|
||||
ShaderGlint.endGlint();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.gtnewhorizons.angelica.mixins.early.shaders;
|
||||
|
||||
import com.gtnewhorizons.angelica.shadercompat.ShaderGlint;
|
||||
import net.coderbot.iris.gbuffer_overrides.matching.SpecialCondition;
|
||||
import net.coderbot.iris.layer.GbufferPrograms;
|
||||
import net.coderbot.iris.uniforms.ItemIdManager;
|
||||
@@ -41,6 +42,7 @@ public class MixinRenderItem {
|
||||
private void iris$glintStart(CallbackInfo ci) {
|
||||
ItemIdManager.resetItemId();
|
||||
GbufferPrograms.setupSpecialRenderCondition(SpecialCondition.GLINT);
|
||||
ShaderGlint.beginGlint();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,5 +55,6 @@ public class MixinRenderItem {
|
||||
)
|
||||
private void iris$glintEnd(CallbackInfo ci) {
|
||||
GbufferPrograms.teardownSpecialRenderCondition();
|
||||
ShaderGlint.endGlint();
|
||||
}
|
||||
}
|
||||
+3
@@ -1,5 +1,6 @@
|
||||
package com.gtnewhorizons.angelica.mixins.early.shaders;
|
||||
|
||||
import com.gtnewhorizons.angelica.shadercompat.ShaderGlint;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import net.coderbot.iris.gbuffer_overrides.matching.SpecialCondition;
|
||||
@@ -80,6 +81,7 @@ public class MixinRendererLivingEntity {
|
||||
)
|
||||
private void iris$glintStart(CallbackInfo ci) {
|
||||
GbufferPrograms.setupSpecialRenderCondition(SpecialCondition.GLINT);
|
||||
ShaderGlint.beginGlint();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,6 +94,7 @@ public class MixinRendererLivingEntity {
|
||||
)
|
||||
private void iris$glintEnd(CallbackInfo ci) {
|
||||
GbufferPrograms.teardownSpecialRenderCondition();
|
||||
ShaderGlint.endGlint();
|
||||
}
|
||||
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package com.gtnewhorizons.angelica.mixins.early.shaders;
|
||||
|
||||
import net.coderbot.iris.uniforms.CapturedRenderingState;
|
||||
import net.minecraft.client.renderer.texture.TextureManager;
|
||||
import net.minecraft.client.resources.IResourceManager;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
/**
|
||||
* Hook into TextureManger to increment the reload count.
|
||||
*/
|
||||
@Mixin(TextureManager.class)
|
||||
public class MixinTextureManager_ReloadCount {
|
||||
|
||||
@Inject(method = "onResourceManagerReload", at = @At("TAIL"))
|
||||
private void angelica$bumpTextureReloadCount(IResourceManager resourceManager, CallbackInfo ci) {
|
||||
CapturedRenderingState.INSTANCE.incrementTextureReloadCount();
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user