mirror of
https://github.com/GTNewHorizons/Angelica.git
synced 2026-11-15 09:44:52 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
502f30c0f9 | ||
|
|
ceff04adba | ||
|
|
b4dfdb8cc5 | ||
|
|
3064818477 | ||
|
|
27524e6a89 | ||
|
|
5d5e910fc0 | ||
|
|
f325fd7fc3 | ||
|
|
ec278d3d7a | ||
|
|
eef3d2f50a | ||
|
|
3da597ab18 |
No files matched your search
+1
-1
@@ -66,7 +66,7 @@ configurations.all {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly("com.github.GTNewHorizons:Hodgepodge:2.7.14:dev")
|
||||
compileOnly("com.github.GTNewHorizons:Hodgepodge:2.7.158:dev")
|
||||
|
||||
compileOnly("com.gtnewhorizons.retrofuturabootstrap:RetroFuturaBootstrap:1.1.0") { transitive = false }
|
||||
// runtimeOnlyNonPublishable("com.github.GTNewHorizons:lwjgl3ify:3.0.99")
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.backend.RenderBackend;
|
||||
import org.taumc.glsl.ShaderParser;
|
||||
import org.taumc.glsl.Transformer;
|
||||
|
||||
@@ -114,13 +113,17 @@ public class CompatShaderTransformer {
|
||||
return result;
|
||||
}
|
||||
|
||||
private static boolean needsTransformation(String source) {
|
||||
// Shaders already at 330+ core don't need compat transformation
|
||||
public static boolean isCoreShader(String source) {
|
||||
final Matcher vm = VERSION_PATTERN.matcher(source);
|
||||
if (vm.find()) {
|
||||
final int version = Integer.parseInt(vm.group(1));
|
||||
if (version >= 330 && "core".equals(vm.group(2))) return false;
|
||||
return version >= 330 && "core".equals(vm.group(2));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean needsTransformation(String source) {
|
||||
if (isCoreShader(source)) return false;
|
||||
|
||||
return NEEDS_TRANSFORM_PATTERN.matcher(source).find();
|
||||
}
|
||||
|
||||
@@ -7,8 +7,6 @@ import com.gtnewhorizons.angelica.glsm.states.LightModelState;
|
||||
import com.gtnewhorizons.angelica.glsm.states.LightState;
|
||||
import com.gtnewhorizons.angelica.glsm.states.MaterialState;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
|
||||
import static com.gtnewhorizons.angelica.glsm.backend.BackendManager.RENDER_BACKEND;
|
||||
import org.joml.Matrix3f;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Vector3f;
|
||||
@@ -17,6 +15,8 @@ import org.lwjgl.opengl.GL11;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
import static com.gtnewhorizons.angelica.glsm.backend.BackendManager.RENDER_BACKEND;
|
||||
|
||||
/**
|
||||
* Per-program compat uniform location cache and upload manager.
|
||||
*
|
||||
@@ -103,8 +103,15 @@ public class CompatUniformManager {
|
||||
}
|
||||
}
|
||||
|
||||
/** Per-program cached uniform locations. Maps program ID → int[LOC_COUNT]. */
|
||||
private static final Int2ObjectOpenHashMap<int[]> programLocations = new Int2ObjectOpenHashMap<>();
|
||||
/** Per-program cached uniform locations + last-uploaded generations. Maps program ID -> state. */
|
||||
private static final Int2ObjectOpenHashMap<ProgramUniforms> programUniforms = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
private static final class ProgramUniforms {
|
||||
final int[] locs;
|
||||
int lastMvGen = -1, lastMvLinearGen = -1, lastProjGen = -1, lastTexMatGen = -1;
|
||||
int lastFragmentGen = -1, lastLightingGen = -1, lastClipPlaneGen = -1;
|
||||
ProgramUniforms(int[] locs) { this.locs = locs; }
|
||||
}
|
||||
|
||||
// Reusable NIO buffers for upload
|
||||
private static final FloatBuffer mat4Buf = BufferUtils.createFloatBuffer(16);
|
||||
@@ -123,15 +130,6 @@ public class CompatUniformManager {
|
||||
new Matrix4f().scale(LIGHTMAP_SCALE).translate(8.0f, 8.0f, 8.0f).get(lightmapMatrixBuf);
|
||||
}
|
||||
|
||||
// Dirty tracking: skip uploads when state hasn't changed and program is the same
|
||||
private static int lastProgram = -1;
|
||||
private static int lastMvGen = -1;
|
||||
private static int lastProjGen = -1;
|
||||
private static int lastTexMatGen = -1;
|
||||
private static int lastFragmentGen = -1;
|
||||
private static int lastLightingGen = -1;
|
||||
private static int lastClipPlaneGen = -1;
|
||||
|
||||
private CompatUniformManager() {}
|
||||
|
||||
/**
|
||||
@@ -154,45 +152,49 @@ public class CompatUniformManager {
|
||||
}
|
||||
|
||||
if (hasAny) {
|
||||
programLocations.put(program, locs);
|
||||
programUniforms.put(program, new ProgramUniforms(locs));
|
||||
GLStateManager.LOGGER.debug("CompatUniformManager: program {} has compat uniforms", program);
|
||||
}
|
||||
}
|
||||
|
||||
public static void onUseProgram(int program) {
|
||||
if (program == 0) return;
|
||||
/**
|
||||
* Uploads the emulated uniforms.
|
||||
*
|
||||
* @return Whether the program needs emulation (FFP or Iris Program)
|
||||
*/
|
||||
public static boolean refreshCompatUniforms(int program) {
|
||||
final ProgramUniforms pu = programUniforms.get(program);
|
||||
if (pu == null) return false;
|
||||
final int[] locs = pu.locs;
|
||||
|
||||
int[] locs = programLocations.get(program);
|
||||
if (locs == null) return;
|
||||
|
||||
final boolean programChanged = program != lastProgram;
|
||||
lastProgram = program;
|
||||
|
||||
// Matrix uniforms — skip if generation unchanged and same program
|
||||
// Matrix uniforms — skip if this program's storage already holds the current generation
|
||||
final int mvGen = GLStateManager.mvGeneration;
|
||||
final int mvLinearGen = GLStateManager.mvLinearGeneration;
|
||||
final int projGen = GLStateManager.projGeneration;
|
||||
final int texMatGen = GLStateManager.texMatrixGeneration;
|
||||
final boolean mvChanged = programChanged || mvGen != lastMvGen;
|
||||
final boolean projChanged = programChanged || projGen != lastProjGen;
|
||||
final boolean texMatChanged = programChanged || texMatGen != lastTexMatGen;
|
||||
final boolean mvChanged = mvGen != pu.lastMvGen;
|
||||
final boolean mvLinearChanged = mvLinearGen != pu.lastMvLinearGen;
|
||||
final boolean projChanged = projGen != pu.lastProjGen;
|
||||
final boolean texMatChanged = texMatGen != pu.lastTexMatGen;
|
||||
if (mvChanged || projChanged || texMatChanged) {
|
||||
uploadMatrices(locs, mvChanged, projChanged, texMatChanged);
|
||||
lastMvGen = mvGen;
|
||||
lastProjGen = projGen;
|
||||
lastTexMatGen = texMatGen;
|
||||
uploadMatrices(locs, mvChanged, mvLinearChanged, projChanged, texMatChanged);
|
||||
pu.lastMvGen = mvGen;
|
||||
pu.lastMvLinearGen = mvLinearGen;
|
||||
pu.lastProjGen = projGen;
|
||||
pu.lastTexMatGen = texMatGen;
|
||||
}
|
||||
|
||||
// Fragment-category uniforms (fog, alpha) — skip if generation unchanged
|
||||
final int fragGen = GLStateManager.fragmentGeneration;
|
||||
if (programChanged || fragGen != lastFragmentGen) {
|
||||
lastFragmentGen = fragGen;
|
||||
if (fragGen != pu.lastFragmentGen) {
|
||||
pu.lastFragmentGen = fragGen;
|
||||
uploadFragmentUniforms(locs);
|
||||
}
|
||||
|
||||
// Lighting-derived uniforms (scene color, light sources, material)
|
||||
final int litGen = GLStateManager.lightingGeneration;
|
||||
if (programChanged || litGen != lastLightingGen) {
|
||||
lastLightingGen = litGen;
|
||||
if (litGen != pu.lastLightingGen) {
|
||||
pu.lastLightingGen = litGen;
|
||||
if (locs[LOC_SCENE_COLOR] != -1) uploadSceneColor(locs);
|
||||
uploadLightSources(locs);
|
||||
uploadMaterial(locs);
|
||||
@@ -201,14 +203,16 @@ public class CompatUniformManager {
|
||||
// Clip plane equations + enabled bool — uploaded when enable state or equations change
|
||||
if (locs[LOC_CLIP_PLANES] != -1 || locs[LOC_CLIP_PLANES_ENABLED] != -1) {
|
||||
final int cpGen = GLStateManager.clipPlaneGeneration;
|
||||
if (programChanged || cpGen != lastClipPlaneGen) {
|
||||
lastClipPlaneGen = cpGen;
|
||||
if (cpGen != pu.lastClipPlaneGen) {
|
||||
pu.lastClipPlaneGen = cpGen;
|
||||
uploadClipPlanes(locs);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void uploadMatrices(int[] locs, boolean mvChanged, boolean projChanged, boolean texMatChanged) {
|
||||
private static void uploadMatrices(int[] locs, boolean mvChanged, boolean mvLinearChanged, boolean projChanged, boolean texMatChanged) {
|
||||
final Matrix4f mv = GLStateManager.getModelViewMatrix();
|
||||
final Matrix4f proj = GLStateManager.getProjectionMatrix();
|
||||
|
||||
@@ -230,7 +234,9 @@ public class CompatUniformManager {
|
||||
scratchMatrix.get(mat4Buf);
|
||||
RENDER_BACKEND.uniformMatrix4(locs[LOC_MODELVIEW_INVERSE], false, mat4Buf);
|
||||
}
|
||||
}
|
||||
|
||||
if (mvLinearChanged) {
|
||||
// Normal Matrix (inverse-transpose of upper-left 3x3 of ModelView)
|
||||
if (locs[LOC_NORMAL] != -1 || locs[LOC_IRIS_NORMAL] != -1) {
|
||||
mv.normal(normalMatrix);
|
||||
@@ -244,7 +250,6 @@ public class CompatUniformManager {
|
||||
normalMatrix.get(mat3Buf);
|
||||
RENDER_BACKEND.uniformMatrix3(locs[LOC_IRIS_NORMAL], false, mat3Buf);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -414,14 +419,15 @@ public class CompatUniformManager {
|
||||
}
|
||||
|
||||
public static void onDeleteProgram(int program) {
|
||||
programLocations.remove(program);
|
||||
programUniforms.remove(program);
|
||||
}
|
||||
|
||||
public static boolean hasProgram(int program) {
|
||||
return programLocations.containsKey(program);
|
||||
return programUniforms.containsKey(program);
|
||||
}
|
||||
|
||||
public static int[] getLocations(int program) {
|
||||
return programLocations.get(program);
|
||||
final ProgramUniforms pu = programUniforms.get(program);
|
||||
return pu == null ? null : pu.locs;
|
||||
}
|
||||
}
|
||||
@@ -144,7 +144,8 @@ public class GLStateManager {
|
||||
|
||||
// Generation counters for FFP uniform dirty tracking. Bumped when the corresponding GLSM state changes.
|
||||
// Per-matrix-mode generation counters — avoids re-uploading all matrices when only one mode changed
|
||||
public static int mvGeneration; // modelview matrix changes
|
||||
public static int mvGeneration; // modelview matrix changes (any: translation, rotation, scale)
|
||||
public static int mvLinearGeneration;
|
||||
public static int projGeneration; // projection matrix changes
|
||||
public static int texMatrixGeneration; // texture matrix changes
|
||||
public static int lightingGeneration;
|
||||
@@ -186,22 +187,23 @@ public class GLStateManager {
|
||||
private static boolean dirtyTexCoordAttrib;
|
||||
private static boolean dirtyLightmapAttrib = true;
|
||||
|
||||
/** Flush deferred vertex attribute uploads. Called before draw to ensure default attrib values are current. */
|
||||
public static void flushDeferredVertexAttribs() {
|
||||
if (dirtyColorAttrib) {
|
||||
// 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(int vertexFlags) {
|
||||
if (dirtyColorAttrib && (vertexFlags & VertexFlags.COLOR_BIT) == 0) {
|
||||
RENDER_BACKEND.vertexAttrib4f(Usage.COLOR.getAttributeLocation(), color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
|
||||
dirtyColorAttrib = false;
|
||||
}
|
||||
if (dirtyLightmapAttrib) {
|
||||
if (dirtyLightmapAttrib && (vertexFlags & VertexFlags.BRIGHTNESS_BIT) == 0) {
|
||||
RENDER_BACKEND.vertexAttrib4f(Usage.SECONDARY_UV.getAttributeLocation(), GLSMConfig.lastBrightnessX, GLSMConfig.lastBrightnessY, 0.0f, 1.0f);
|
||||
dirtyLightmapAttrib = false;
|
||||
}
|
||||
if (dirtyNormalAttrib) {
|
||||
if (dirtyNormalAttrib && (vertexFlags & VertexFlags.NORMAL_BIT) == 0) {
|
||||
final var n = ShaderManager.getCurrentNormal();
|
||||
RENDER_BACKEND.vertexAttrib3f(Usage.NORMAL.getAttributeLocation(), n.x, n.y, n.z);
|
||||
dirtyNormalAttrib = false;
|
||||
}
|
||||
if (dirtyTexCoordAttrib) {
|
||||
if (dirtyTexCoordAttrib && (vertexFlags & VertexFlags.TEXTURE_BIT) == 0) {
|
||||
final var tc = ShaderManager.getCurrentTexCoord();
|
||||
RENDER_BACKEND.vertexAttrib4f(Usage.PRIMARY_UV.getAttributeLocation(), tc.x, tc.y, tc.z, tc.w);
|
||||
dirtyTexCoordAttrib = false;
|
||||
@@ -301,6 +303,7 @@ public class GLStateManager {
|
||||
|
||||
// Saved generation counters at push time — used to detect whether state actually changed during push/pop scope
|
||||
private static final int[] savedMvGen = new int[MAX_ATTRIB_STACK_DEPTH];
|
||||
private static final int[] savedMvLinearGen = new int[MAX_ATTRIB_STACK_DEPTH];
|
||||
private static final int[] savedProjGen = new int[MAX_ATTRIB_STACK_DEPTH];
|
||||
private static final int[] savedTexMatGen = new int[MAX_ATTRIB_STACK_DEPTH];
|
||||
private static final int[] savedLightingGen = new int[MAX_ATTRIB_STACK_DEPTH];
|
||||
@@ -2876,6 +2879,22 @@ public class GLStateManager {
|
||||
}
|
||||
}
|
||||
colorMaterial.enable();
|
||||
bakeCurrentColorIntoTrackedMaterial();
|
||||
}
|
||||
|
||||
public static void disableColorMaterial() {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordDisable(GL11.GL_COLOR_MATERIAL);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
bakeCurrentColorIntoTrackedMaterial();
|
||||
colorMaterial.disable();
|
||||
}
|
||||
|
||||
private static void bakeCurrentColorIntoTrackedMaterial() {
|
||||
final float r = getColor().getRed();
|
||||
final float g = getColor().getGreen();
|
||||
final float b = getColor().getBlue();
|
||||
@@ -2906,17 +2925,6 @@ public class GLStateManager {
|
||||
}
|
||||
}
|
||||
|
||||
public static void disableColorMaterial() {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordDisable(GL11.GL_COLOR_MATERIAL);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
colorMaterial.disable();
|
||||
}
|
||||
|
||||
public static void disableLighting() {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
@@ -3047,16 +3055,19 @@ public class GLStateManager {
|
||||
}
|
||||
// Update cached state (FFP shader reads from cache)
|
||||
if (isCachingEnabled()) {
|
||||
boolean changed = true;
|
||||
boolean changed = false;
|
||||
switch (pname) {
|
||||
case GL11.GL_FOG_DENSITY -> { fogState.setDensity(param); fragmentGeneration++; }
|
||||
case GL11.GL_FOG_START -> { fogState.setStart(param); fragmentGeneration++; }
|
||||
case GL11.GL_FOG_END -> { fogState.setEnd(param); fragmentGeneration++; }
|
||||
case GL11.GL_FOG_MODE -> { fogState.setFogMode((int) param); fragmentGeneration++; }
|
||||
default -> changed = false;
|
||||
case GL11.GL_FOG_DENSITY -> { if (BYPASS_CACHE || fogState.getDensity() != param) { fogState.setDensity(param); changed = true; } }
|
||||
case GL11.GL_FOG_START -> { if (BYPASS_CACHE || fogState.getStart() != param) { fogState.setStart(param); changed = true; } }
|
||||
case GL11.GL_FOG_END -> { if (BYPASS_CACHE || fogState.getEnd() != param) { fogState.setEnd(param); changed = true; } }
|
||||
case GL11.GL_FOG_MODE -> { if (BYPASS_CACHE || fogState.getFogMode() != (int) param) { fogState.setFogMode((int) param); changed = true; } }
|
||||
default -> {}
|
||||
}
|
||||
if (changed && GLSMHooks.FOG_STATE_CHANGE.hasListeners()) {
|
||||
GLSMHooks.FOG_STATE_CHANGE.post(GLSMHooks.fogStateChangeEvent);
|
||||
if (changed) {
|
||||
fragmentGeneration++;
|
||||
if (GLSMHooks.FOG_STATE_CHANGE.hasListeners()) {
|
||||
GLSMHooks.FOG_STATE_CHANGE.post(GLSMHooks.fogStateChangeEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3070,7 +3081,7 @@ public class GLStateManager {
|
||||
}
|
||||
}
|
||||
// Update cached state (FFP shader reads from cache)
|
||||
if (isCachingEnabled() && pname == GL11.GL_FOG_MODE) {
|
||||
if (isCachingEnabled() && pname == GL11.GL_FOG_MODE && (BYPASS_CACHE || fogState.getFogMode() != param)) {
|
||||
fogState.setFogMode(param);
|
||||
fragmentGeneration++;
|
||||
if (GLSMHooks.FOG_STATE_CHANGE.hasListeners()) {
|
||||
@@ -3221,6 +3232,7 @@ public class GLStateManager {
|
||||
|
||||
// Snapshot generation counters so we can detect actual changes at pop time
|
||||
savedMvGen[attribDepth] = mvGeneration;
|
||||
savedMvLinearGen[attribDepth] = mvLinearGeneration;
|
||||
savedProjGen[attribDepth] = projGeneration;
|
||||
savedTexMatGen[attribDepth] = texMatrixGeneration;
|
||||
savedLightingGen[attribDepth] = lightingGeneration;
|
||||
@@ -3329,13 +3341,23 @@ public class GLStateManager {
|
||||
if ((mask & GL11.GL_TEXTURE_BIT) != 0 && fragmentGeneration != savedFragmentGen[depth]) fragmentGeneration++; // texenv state
|
||||
if ((mask & GL11.GL_TRANSFORM_BIT) != 0) {
|
||||
if (mvGeneration != savedMvGen[depth]) mvGeneration++;
|
||||
if (mvLinearGeneration != savedMvLinearGen[depth]) mvLinearGeneration++;
|
||||
if (projGeneration != savedProjGen[depth]) projGeneration++;
|
||||
if (texMatrixGeneration != savedTexMatGen[depth]) texMatrixGeneration++;
|
||||
}
|
||||
if ((mask & GL11.GL_CURRENT_BIT) != 0) {
|
||||
if (colorGeneration != savedColorGen[depth]) colorGeneration++;
|
||||
if (ShaderManager.getNormalGeneration() != savedNormalGen[depth]) ShaderManager.bumpNormalGeneration();
|
||||
if (ShaderManager.getTexCoordGeneration() != savedTexCoordGen[depth]) ShaderManager.bumpTexCoordGeneration();
|
||||
if (colorGeneration != savedColorGen[depth]) {
|
||||
colorGeneration++;
|
||||
dirtyColorAttrib = true;
|
||||
}
|
||||
if (ShaderManager.getNormalGeneration() != savedNormalGen[depth]) {
|
||||
ShaderManager.bumpNormalGeneration();
|
||||
dirtyNormalAttrib = true;
|
||||
}
|
||||
if (ShaderManager.getTexCoordGeneration() != savedTexCoordGen[depth]) {
|
||||
ShaderManager.bumpTexCoordGeneration();
|
||||
dirtyTexCoordAttrib = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3446,8 +3468,15 @@ public class GLStateManager {
|
||||
|
||||
/** Bump the generation counter for the currently active matrix mode. */
|
||||
private static void bumpMatrixGeneration() {
|
||||
bumpMatrixGeneration(true);
|
||||
}
|
||||
|
||||
private static void bumpMatrixGeneration(boolean linearChanged) {
|
||||
switch (matrixMode.getMode()) {
|
||||
case GL11.GL_MODELVIEW -> mvGeneration++;
|
||||
case GL11.GL_MODELVIEW -> {
|
||||
mvGeneration++;
|
||||
if (linearChanged) mvLinearGeneration++;
|
||||
}
|
||||
case GL11.GL_PROJECTION -> projGeneration++;
|
||||
case GL11.GL_TEXTURE -> texMatrixGeneration++;
|
||||
}
|
||||
@@ -3474,7 +3503,7 @@ public class GLStateManager {
|
||||
}
|
||||
if (isCachingEnabled()) {
|
||||
getMatrixStack().translate(x, y, z);
|
||||
bumpMatrixGeneration();
|
||||
bumpMatrixGeneration(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3485,7 +3514,7 @@ public class GLStateManager {
|
||||
}
|
||||
if (isCachingEnabled()) {
|
||||
getMatrixStack().translate((float) x, (float) y, (float) z);
|
||||
bumpMatrixGeneration();
|
||||
bumpMatrixGeneration(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3956,64 +3985,72 @@ public class GLStateManager {
|
||||
public static void glSamplerParameteri(int sampler, int pname, int param) { RENDER_BACKEND.samplerParameteri(sampler, pname, param); }
|
||||
public static void glSamplerParameterf(int sampler, int pname, float param) { RENDER_BACKEND.samplerParameterf(sampler, pname, param); }
|
||||
|
||||
private static void glMaterialFront(int pname, FloatBuffer params) {
|
||||
switch (pname) {
|
||||
private static boolean glMaterialFront(int pname, FloatBuffer params) {
|
||||
return switch (pname) {
|
||||
case GL11.GL_AMBIENT -> frontMaterial.setAmbient(params);
|
||||
case GL11.GL_DIFFUSE -> frontMaterial.setDiffuse(params);
|
||||
case GL11.GL_SPECULAR -> frontMaterial.setSpecular(params);
|
||||
case GL11.GL_EMISSION -> frontMaterial.setEmission(params);
|
||||
case GL11.GL_SHININESS -> frontMaterial.setShininess(params);
|
||||
case GL11.GL_AMBIENT_AND_DIFFUSE -> {
|
||||
frontMaterial.setAmbient(params);
|
||||
frontMaterial.setDiffuse(params);
|
||||
final boolean a = frontMaterial.setAmbient(params);
|
||||
final boolean d = frontMaterial.setDiffuse(params);
|
||||
yield a || d;
|
||||
}
|
||||
case GL11.GL_COLOR_INDEXES -> frontMaterial.setColorIndexes(params);
|
||||
}
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
|
||||
private static void glMaterialBack(int pname, FloatBuffer params) {
|
||||
switch (pname) {
|
||||
private static boolean glMaterialBack(int pname, FloatBuffer params) {
|
||||
return switch (pname) {
|
||||
case GL11.GL_AMBIENT -> backMaterial.setAmbient(params);
|
||||
case GL11.GL_DIFFUSE -> backMaterial.setDiffuse(params);
|
||||
case GL11.GL_SPECULAR -> backMaterial.setSpecular(params);
|
||||
case GL11.GL_EMISSION -> backMaterial.setEmission(params);
|
||||
case GL11.GL_SHININESS -> backMaterial.setShininess(params);
|
||||
case GL11.GL_AMBIENT_AND_DIFFUSE -> {
|
||||
backMaterial.setAmbient(params);
|
||||
backMaterial.setDiffuse(params);
|
||||
final boolean a = backMaterial.setAmbient(params);
|
||||
final boolean d = backMaterial.setDiffuse(params);
|
||||
yield a || d;
|
||||
}
|
||||
case GL11.GL_COLOR_INDEXES -> backMaterial.setColorIndexes(params);
|
||||
}
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
|
||||
private static void glMaterialFront(int pname, IntBuffer params) {
|
||||
switch (pname) {
|
||||
private static boolean glMaterialFront(int pname, IntBuffer params) {
|
||||
return switch (pname) {
|
||||
case GL11.GL_AMBIENT -> frontMaterial.setAmbient(params);
|
||||
case GL11.GL_DIFFUSE -> frontMaterial.setDiffuse(params);
|
||||
case GL11.GL_SPECULAR -> frontMaterial.setSpecular(params);
|
||||
case GL11.GL_EMISSION -> frontMaterial.setEmission(params);
|
||||
case GL11.GL_SHININESS -> frontMaterial.setShininess(params);
|
||||
case GL11.GL_AMBIENT_AND_DIFFUSE -> {
|
||||
frontMaterial.setAmbient(params);
|
||||
frontMaterial.setDiffuse(params);
|
||||
final boolean a = frontMaterial.setAmbient(params);
|
||||
final boolean d = frontMaterial.setDiffuse(params);
|
||||
yield a || d;
|
||||
}
|
||||
case GL11.GL_COLOR_INDEXES -> frontMaterial.setColorIndexes(params);
|
||||
}
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
|
||||
private static void glMaterialBack(int pname, IntBuffer params) {
|
||||
switch (pname) {
|
||||
private static boolean glMaterialBack(int pname, IntBuffer params) {
|
||||
return switch (pname) {
|
||||
case GL11.GL_AMBIENT -> backMaterial.setAmbient(params);
|
||||
case GL11.GL_DIFFUSE -> backMaterial.setDiffuse(params);
|
||||
case GL11.GL_SPECULAR -> backMaterial.setSpecular(params);
|
||||
case GL11.GL_EMISSION -> backMaterial.setEmission(params);
|
||||
case GL11.GL_SHININESS -> backMaterial.setShininess(params);
|
||||
case GL11.GL_AMBIENT_AND_DIFFUSE -> {
|
||||
backMaterial.setAmbient(params);
|
||||
backMaterial.setDiffuse(params);
|
||||
final boolean a = backMaterial.setAmbient(params);
|
||||
final boolean d = backMaterial.setDiffuse(params);
|
||||
yield a || d;
|
||||
}
|
||||
case GL11.GL_COLOR_INDEXES -> backMaterial.setColorIndexes(params);
|
||||
}
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
|
||||
public static void glMaterial(int face, int pname, FloatBuffer params) {
|
||||
@@ -4024,17 +4061,19 @@ public class GLStateManager {
|
||||
return;
|
||||
}
|
||||
}
|
||||
boolean changed = false;
|
||||
if (face == GL11.GL_FRONT) {
|
||||
glMaterialFront(pname, params);
|
||||
changed = glMaterialFront(pname, params);
|
||||
} else if (face == GL11.GL_BACK) {
|
||||
glMaterialBack(pname, params);
|
||||
changed = glMaterialBack(pname, params);
|
||||
} else if (face == GL11.GL_FRONT_AND_BACK) {
|
||||
glMaterialFront(pname, params);
|
||||
glMaterialBack(pname, params);
|
||||
final boolean f = glMaterialFront(pname, params);
|
||||
final boolean b = glMaterialBack(pname, params);
|
||||
changed = f || b;
|
||||
} else {
|
||||
throw new RuntimeException("Unsupported face value for glMaterial: " + face);
|
||||
}
|
||||
lightingGeneration++;
|
||||
if (changed) lightingGeneration++;
|
||||
}
|
||||
|
||||
public static void glMaterial(int face, int pname, IntBuffer params) {
|
||||
@@ -4053,17 +4092,19 @@ public class GLStateManager {
|
||||
return;
|
||||
}
|
||||
}
|
||||
boolean changed = false;
|
||||
if (face == GL11.GL_FRONT) {
|
||||
glMaterialFront(pname, params);
|
||||
changed = glMaterialFront(pname, params);
|
||||
} else if (face == GL11.GL_BACK) {
|
||||
glMaterialBack(pname, params);
|
||||
changed = glMaterialBack(pname, params);
|
||||
} else if (face == GL11.GL_FRONT_AND_BACK) {
|
||||
glMaterialFront(pname, params);
|
||||
glMaterialBack(pname, params);
|
||||
final boolean f = glMaterialFront(pname, params);
|
||||
final boolean b = glMaterialBack(pname, params);
|
||||
changed = f || b;
|
||||
} else {
|
||||
throw new RuntimeException("Unsupported face value for glMaterial: " + face);
|
||||
}
|
||||
lightingGeneration++;
|
||||
if (changed) lightingGeneration++;
|
||||
}
|
||||
|
||||
public static void glMaterialf(int face, int pname, float val) {
|
||||
@@ -4079,17 +4120,19 @@ public class GLStateManager {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean changed = false;
|
||||
if (face == GL11.GL_FRONT) {
|
||||
frontMaterial.setShininess(val);
|
||||
changed = frontMaterial.setShininess(val);
|
||||
} else if (face == GL11.GL_BACK) {
|
||||
backMaterial.setShininess(val);
|
||||
changed = backMaterial.setShininess(val);
|
||||
} else if (face == GL11.GL_FRONT_AND_BACK) {
|
||||
frontMaterial.setShininess(val);
|
||||
backMaterial.setShininess(val);
|
||||
final boolean f = frontMaterial.setShininess(val);
|
||||
final boolean b = backMaterial.setShininess(val);
|
||||
changed = f || b;
|
||||
} else {
|
||||
throw new RuntimeException("Unsupported face value for glMaterial: " + face);
|
||||
}
|
||||
lightingGeneration++;
|
||||
if (changed) lightingGeneration++;
|
||||
}
|
||||
|
||||
public static void glMateriali(int face, int pname, int val) {
|
||||
@@ -4107,7 +4150,7 @@ public class GLStateManager {
|
||||
}
|
||||
}
|
||||
final LightStateStack lightState = lightDataStates[light - GL11.GL_LIGHT0];
|
||||
switch (pname) {
|
||||
final boolean changed = switch (pname) {
|
||||
case GL11.GL_AMBIENT -> lightState.setAmbient(params);
|
||||
case GL11.GL_DIFFUSE -> lightState.setDiffuse(params);
|
||||
case GL11.GL_SPECULAR -> lightState.setSpecular(params);
|
||||
@@ -4118,9 +4161,9 @@ public class GLStateManager {
|
||||
case GL11.GL_CONSTANT_ATTENUATION -> lightState.setConstantAttenuation(params);
|
||||
case GL11.GL_LINEAR_ATTENUATION -> lightState.setLinearAttenuation(params);
|
||||
case GL11.GL_QUADRATIC_ATTENUATION -> lightState.setQuadraticAttenuation(params);
|
||||
default -> {}
|
||||
}
|
||||
lightingGeneration++;
|
||||
default -> false;
|
||||
};
|
||||
if (changed) lightingGeneration++;
|
||||
}
|
||||
|
||||
public static void glLight(int light, int pname, IntBuffer params) {
|
||||
@@ -4140,7 +4183,7 @@ public class GLStateManager {
|
||||
}
|
||||
}
|
||||
final LightStateStack lightState = lightDataStates[light - GL11.GL_LIGHT0];
|
||||
switch (pname) {
|
||||
final boolean changed = switch (pname) {
|
||||
case GL11.GL_AMBIENT -> lightState.setAmbient(params);
|
||||
case GL11.GL_DIFFUSE -> lightState.setDiffuse(params);
|
||||
case GL11.GL_SPECULAR -> lightState.setSpecular(params);
|
||||
@@ -4151,9 +4194,9 @@ public class GLStateManager {
|
||||
case GL11.GL_CONSTANT_ATTENUATION -> lightState.setConstantAttenuation(params);
|
||||
case GL11.GL_LINEAR_ATTENUATION -> lightState.setLinearAttenuation(params);
|
||||
case GL11.GL_QUADRATIC_ATTENUATION -> lightState.setQuadraticAttenuation(params);
|
||||
default -> {}
|
||||
}
|
||||
lightingGeneration++;
|
||||
default -> false;
|
||||
};
|
||||
if (changed) lightingGeneration++;
|
||||
}
|
||||
|
||||
public static void glLightf(int light, int pname, float param) {
|
||||
@@ -4165,15 +4208,15 @@ public class GLStateManager {
|
||||
}
|
||||
}
|
||||
final LightStateStack lightState = lightDataStates[light - GL11.GL_LIGHT0];
|
||||
switch (pname) {
|
||||
final boolean changed = switch (pname) {
|
||||
case GL11.GL_SPOT_EXPONENT -> lightState.setSpotExponent(param);
|
||||
case GL11.GL_SPOT_CUTOFF -> lightState.setSpotCutoff(param);
|
||||
case GL11.GL_CONSTANT_ATTENUATION -> lightState.setConstantAttenuation(param);
|
||||
case GL11.GL_LINEAR_ATTENUATION -> lightState.setLinearAttenuation(param);
|
||||
case GL11.GL_QUADRATIC_ATTENUATION -> lightState.setQuadraticAttenuation(param);
|
||||
default -> {}
|
||||
}
|
||||
lightingGeneration++;
|
||||
default -> false;
|
||||
};
|
||||
if (changed) lightingGeneration++;
|
||||
}
|
||||
|
||||
public static void glLighti(int light, int pname, int param) {
|
||||
@@ -4185,16 +4228,15 @@ public class GLStateManager {
|
||||
}
|
||||
}
|
||||
final LightStateStack lightState = lightDataStates[light - GL11.GL_LIGHT0];
|
||||
switch (pname) {
|
||||
final boolean changed = switch (pname) {
|
||||
case GL11.GL_SPOT_EXPONENT -> lightState.setSpotExponent(param);
|
||||
case GL11.GL_SPOT_CUTOFF -> lightState.setSpotCutoff(param);
|
||||
case GL11.GL_CONSTANT_ATTENUATION -> lightState.setConstantAttenuation(param);
|
||||
case GL11.GL_LINEAR_ATTENUATION -> lightState.setLinearAttenuation(param);
|
||||
case GL11.GL_QUADRATIC_ATTENUATION -> lightState.setQuadraticAttenuation(param);
|
||||
default -> {
|
||||
}
|
||||
}
|
||||
lightingGeneration++;
|
||||
default -> false;
|
||||
};
|
||||
if (changed) lightingGeneration++;
|
||||
}
|
||||
|
||||
public static void glLightModel(int pname, FloatBuffer params) {
|
||||
@@ -4205,14 +4247,13 @@ public class GLStateManager {
|
||||
return;
|
||||
}
|
||||
}
|
||||
switch (pname) {
|
||||
final boolean changed = switch (pname) {
|
||||
case GL11.GL_LIGHT_MODEL_AMBIENT -> lightModel.setAmbient(params);
|
||||
case GL11.GL_LIGHT_MODEL_LOCAL_VIEWER -> lightModel.setLocalViewer(params);
|
||||
case GL11.GL_LIGHT_MODEL_TWO_SIDE -> lightModel.setTwoSide(params);
|
||||
default -> {
|
||||
}
|
||||
}
|
||||
lightingGeneration++;
|
||||
default -> false;
|
||||
};
|
||||
if (changed) lightingGeneration++;
|
||||
}
|
||||
|
||||
public static void glLightModel(int pname, IntBuffer params) {
|
||||
@@ -4231,15 +4272,14 @@ public class GLStateManager {
|
||||
return;
|
||||
}
|
||||
}
|
||||
switch (pname) {
|
||||
final boolean changed = switch (pname) {
|
||||
case GL11.GL_LIGHT_MODEL_AMBIENT -> lightModel.setAmbient(params);
|
||||
case GL12.GL_LIGHT_MODEL_COLOR_CONTROL -> lightModel.setColorControl(params);
|
||||
case GL11.GL_LIGHT_MODEL_LOCAL_VIEWER -> lightModel.setLocalViewer(params);
|
||||
case GL11.GL_LIGHT_MODEL_TWO_SIDE -> lightModel.setTwoSide(params);
|
||||
default -> {
|
||||
}
|
||||
}
|
||||
lightingGeneration++;
|
||||
default -> false;
|
||||
};
|
||||
if (changed) lightingGeneration++;
|
||||
}
|
||||
|
||||
public static void glLightModelf(int pname, float param) {
|
||||
@@ -4252,13 +4292,12 @@ public class GLStateManager {
|
||||
}
|
||||
|
||||
if (isCachingEnabled()) {
|
||||
switch (pname) {
|
||||
final boolean changed = switch (pname) {
|
||||
case GL11.GL_LIGHT_MODEL_LOCAL_VIEWER -> lightModel.setLocalViewer(param);
|
||||
case GL11.GL_LIGHT_MODEL_TWO_SIDE -> lightModel.setTwoSide(param);
|
||||
default -> {
|
||||
}
|
||||
}
|
||||
lightingGeneration++;
|
||||
default -> false;
|
||||
};
|
||||
if (changed) lightingGeneration++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4272,14 +4311,13 @@ public class GLStateManager {
|
||||
}
|
||||
|
||||
if (isCachingEnabled()) {
|
||||
switch (pname) {
|
||||
final boolean changed = switch (pname) {
|
||||
case GL12.GL_LIGHT_MODEL_COLOR_CONTROL -> lightModel.setColorControl(param);
|
||||
case GL11.GL_LIGHT_MODEL_LOCAL_VIEWER -> lightModel.setLocalViewer(param);
|
||||
case GL11.GL_LIGHT_MODEL_TWO_SIDE -> lightModel.setTwoSide(param);
|
||||
default -> {
|
||||
}
|
||||
}
|
||||
lightingGeneration++;
|
||||
default -> false;
|
||||
};
|
||||
if (changed) lightingGeneration++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4354,7 +4392,6 @@ public class GLStateManager {
|
||||
GLDebug.debugMessage("Activating Program - " + program + ":" + programName);
|
||||
}
|
||||
RENDER_BACKEND.useProgram(program);
|
||||
CompatUniformManager.onUseProgram(program);
|
||||
if (GLSMHooks.PROGRAM_CHANGE.hasListeners()) {
|
||||
GLSMHooks.programChangeEvent.previousProgram = prev;
|
||||
GLSMHooks.programChangeEvent.newProgram = program;
|
||||
|
||||
@@ -26,6 +26,16 @@ public class Program {
|
||||
@Getter private final VertexKey vertexKey;
|
||||
@Getter private final FragmentKey fragmentKey;
|
||||
|
||||
// Per-program uniform dirty-tracking
|
||||
static final class UploadState {
|
||||
int mvGen = -1, mvLinearGen = -1, projGen = -1, texMatGen = -1;
|
||||
int lightingGen = -1, fragmentGen = -1, colorGen = -1, normalGen = -1, texCoordGen = -1;
|
||||
int texGenGen = -1, clipPlaneGen = -1;
|
||||
float lightmapX = Float.NaN, lightmapY = Float.NaN, lineWidth = Float.NaN;
|
||||
int viewportWidth = -1, viewportHeight = -1;
|
||||
}
|
||||
final UploadState uploadState = new UploadState();
|
||||
|
||||
// Uniform locations (-1 = not present in this variant)
|
||||
// Matrices
|
||||
public int locModelViewMatrix = -1;
|
||||
|
||||
@@ -22,7 +22,7 @@ import static com.gtnewhorizons.angelica.glsm.backend.BackendManager.RENDER_BACK
|
||||
/**
|
||||
* FFP shader manager
|
||||
*/
|
||||
public class ShaderManager {
|
||||
public final class ShaderManager {
|
||||
|
||||
private static final class Holder {
|
||||
|
||||
@@ -36,6 +36,7 @@ public class ShaderManager {
|
||||
@Getter
|
||||
private boolean active = false;
|
||||
private Program currentProgram = null;
|
||||
private int lastBoundProgramId = -1;
|
||||
private long currentVertexKeyPacked = Long.MIN_VALUE;
|
||||
private final long[] currentFKScratch = new long[FragmentKey.MAX_UNITS];
|
||||
private final long[] currentFKPacked = new long[FragmentKey.MAX_UNITS];
|
||||
@@ -87,35 +88,34 @@ public class ShaderManager {
|
||||
|
||||
public void activate() {
|
||||
active = true;
|
||||
updateVariant(true, true, true, true);
|
||||
uploadUniforms();
|
||||
lastBoundProgramId = GLStateManager.getActiveProgram();
|
||||
}
|
||||
|
||||
public void deactivate() {
|
||||
active = false;
|
||||
currentProgram = null;
|
||||
lastBoundProgramId = -1;
|
||||
currentVertexKeyPacked = Long.MIN_VALUE;
|
||||
currentFKLen = 0;
|
||||
}
|
||||
|
||||
public void preDraw(boolean hasColor, boolean hasNormal, boolean hasTexCoord, boolean hasLightmap) {
|
||||
GLStateManager.flushDeferredVertexAttribs();
|
||||
final DeferredBlendHandler bh = GLSMHooks.blendHandler;
|
||||
if (bh != null) bh.flushDeferredBlend();
|
||||
|
||||
if (!active) {
|
||||
if (enabled) {
|
||||
final int currentProgramId = GLStateManager.getActiveProgram();
|
||||
if (currentProgramId != 0) {
|
||||
CompatUniformManager.onUseProgram(currentProgramId);
|
||||
return;
|
||||
}
|
||||
active = true;
|
||||
} else {
|
||||
return;
|
||||
// Handle FFP & Iris uniforms
|
||||
final int currentProgramId = GLStateManager.getActiveProgram();
|
||||
if (currentProgramId != 0) {
|
||||
if (!CompatUniformManager.refreshCompatUniforms(currentProgramId)) {
|
||||
return; // Don't emulate FFP on non-iris core shaders
|
||||
}
|
||||
}
|
||||
|
||||
GLStateManager.flushDeferredVertexAttribs(currentVertexFlags);
|
||||
|
||||
if (!active) return;
|
||||
|
||||
|
||||
final int fkLen = FragmentKey.packFromState(currentFKScratch);
|
||||
final int fragMask = FragmentKey.unitMaskFromPacked(currentFKScratch, fkLen);
|
||||
final long vkPacked = VertexKey.packFromState(hasColor, hasNormal, hasTexCoord, hasLightmap, fragMask);
|
||||
@@ -141,19 +141,16 @@ public class ShaderManager {
|
||||
preDraw(currentVertexFlags);
|
||||
}
|
||||
|
||||
private void updateVariant(boolean hasColor, boolean hasNormal, boolean hasTexCoord, boolean hasLightmap) {
|
||||
final int fkLen = FragmentKey.packFromState(currentFKScratch);
|
||||
final int fragMask = FragmentKey.unitMaskFromPacked(currentFKScratch, fkLen);
|
||||
final long vkPacked = VertexKey.packFromState(hasColor, hasNormal, hasTexCoord, hasLightmap, fragMask);
|
||||
commitVariant(vkPacked, fkLen);
|
||||
}
|
||||
|
||||
private void commitVariant(long vkPacked, int fkLen) {
|
||||
currentVertexKeyPacked = vkPacked;
|
||||
System.arraycopy(currentFKScratch, 0, currentFKPacked, 0, fkLen);
|
||||
currentFKLen = fkLen;
|
||||
currentProgram = cache.getOrCreate(vkPacked, currentFKPacked, currentFKLen);
|
||||
RENDER_BACKEND.useProgram(currentProgram.getProgramId());
|
||||
final int programId = currentProgram.getProgramId();
|
||||
if (programId != lastBoundProgramId) {
|
||||
RENDER_BACKEND.useProgram(programId);
|
||||
lastBoundProgramId = programId;
|
||||
}
|
||||
}
|
||||
|
||||
private void uploadUniforms() {
|
||||
|
||||
@@ -46,116 +46,99 @@ public class Uniforms {
|
||||
private static final double LN2 = java.lang.Math.log(2.0);
|
||||
private static final double SQRT_LN2 = java.lang.Math.sqrt(LN2);
|
||||
|
||||
// Dirty tracking: last-uploaded generation per category + program ID.
|
||||
// Program change forces full re-upload since uniform locations differ.
|
||||
private int lastProgramId = -1;
|
||||
private int lastMvGen = -1;
|
||||
private int lastProjGen = -1;
|
||||
private int lastTexMatGen = -1;
|
||||
private int lastLightingGen = -1;
|
||||
private int lastFragmentGen = -1;
|
||||
private int lastColorGen = -1;
|
||||
private int lastNormalGen = -1;
|
||||
private int lastTexCoordGen = -1;
|
||||
private float lastLightmapX = Float.NaN;
|
||||
private float lastLightmapY = Float.NaN;
|
||||
private int lastTexGenGen = -1;
|
||||
private int lastClipPlaneGen = -1;
|
||||
private float lastLineWidth = Float.NaN;
|
||||
private int lastViewportWidth = -1;
|
||||
private int lastViewportHeight = -1;
|
||||
|
||||
/**
|
||||
* Upload all relevant uniforms to the given FFP program based on current GLSM state.
|
||||
* Uses generation counters to skip categories that haven't changed since last upload.
|
||||
*/
|
||||
public void upload(Program program) {
|
||||
final boolean programChanged = program.getProgramId() != lastProgramId;
|
||||
lastProgramId = program.getProgramId();
|
||||
final Program.UploadState st = program.uploadState;
|
||||
|
||||
final int mvGen = GLStateManager.mvGeneration;
|
||||
final int mvLinearGen = GLStateManager.mvLinearGeneration;
|
||||
final int projGen = GLStateManager.projGeneration;
|
||||
final int texMatGen = GLStateManager.texMatrixGeneration;
|
||||
final boolean mvChanged = programChanged || mvGen != lastMvGen;
|
||||
final boolean projChanged = programChanged || projGen != lastProjGen;
|
||||
final boolean texMatChanged = programChanged || texMatGen != lastTexMatGen;
|
||||
final boolean mvChanged = mvGen != st.mvGen;
|
||||
final boolean mvLinearChanged = mvLinearGen != st.mvLinearGen;
|
||||
final boolean projChanged = projGen != st.projGen;
|
||||
final boolean texMatChanged = texMatGen != st.texMatGen;
|
||||
if (mvChanged || projChanged || texMatChanged) {
|
||||
uploadMatrices(program, mvChanged, projChanged, texMatChanged);
|
||||
lastMvGen = mvGen;
|
||||
lastProjGen = projGen;
|
||||
lastTexMatGen = texMatGen;
|
||||
uploadMatrices(program, mvChanged, mvLinearChanged, projChanged, texMatChanged);
|
||||
st.mvGen = mvGen;
|
||||
st.mvLinearGen = mvLinearGen;
|
||||
st.projGen = projGen;
|
||||
st.texMatGen = texMatGen;
|
||||
}
|
||||
|
||||
if (program.getVertexKey().lightingEnabled()) {
|
||||
final int litGen = GLStateManager.lightingGeneration;
|
||||
if (programChanged || litGen != lastLightingGen) {
|
||||
if (litGen != st.lightingGen) {
|
||||
uploadLighting(program);
|
||||
lastLightingGen = litGen;
|
||||
st.lightingGen = litGen;
|
||||
}
|
||||
}
|
||||
|
||||
// Current color/normal/texcoord — skip if generation unchanged
|
||||
if (!program.getVertexKey().hasVertexColor()) {
|
||||
final int colorGen = GLStateManager.colorGeneration;
|
||||
if (programChanged || colorGen != lastColorGen) {
|
||||
if (colorGen != st.colorGen) {
|
||||
uploadCurrentColor(program);
|
||||
lastColorGen = colorGen;
|
||||
st.colorGen = colorGen;
|
||||
}
|
||||
}
|
||||
|
||||
if (!program.getVertexKey().hasVertexNormal() && program.getVertexKey().lightingEnabled()) {
|
||||
final int normalGen = ShaderManager.getNormalGeneration();
|
||||
if (programChanged || normalGen != lastNormalGen) {
|
||||
if (normalGen != st.normalGen) {
|
||||
uploadCurrentNormal(program);
|
||||
lastNormalGen = normalGen;
|
||||
st.normalGen = normalGen;
|
||||
}
|
||||
}
|
||||
|
||||
if (program.getVertexKey().anyUnitTexCoordEnabled()) {
|
||||
final int texGen = ShaderManager.getTexCoordGeneration();
|
||||
if (programChanged || texGen != lastTexCoordGen) {
|
||||
if (texGen != st.texCoordGen) {
|
||||
uploadCurrentTexCoords(program);
|
||||
lastTexCoordGen = texGen;
|
||||
st.texCoordGen = texGen;
|
||||
}
|
||||
}
|
||||
|
||||
if (program.getVertexKey().lightmapEnabled() && !program.getVertexKey().hasVertexLightmap()) {
|
||||
if (programChanged || GLSMConfig.lastBrightnessX != lastLightmapX || GLSMConfig.lastBrightnessY != lastLightmapY) {
|
||||
if (GLSMConfig.lastBrightnessX != st.lightmapX || GLSMConfig.lastBrightnessY != st.lightmapY) {
|
||||
uploadCurrentLightmapCoord(program);
|
||||
lastLightmapX = GLSMConfig.lastBrightnessX;
|
||||
lastLightmapY = GLSMConfig.lastBrightnessY;
|
||||
st.lightmapX = GLSMConfig.lastBrightnessX;
|
||||
st.lightmapY = GLSMConfig.lastBrightnessY;
|
||||
}
|
||||
}
|
||||
|
||||
if (program.getVertexKey().texGenEnabled()) {
|
||||
final int tgGen = GLStateManager.texGenGeneration;
|
||||
if (programChanged || tgGen != lastTexGenGen) {
|
||||
if (tgGen != st.texGenGen) {
|
||||
uploadTexGen(program);
|
||||
lastTexGenGen = tgGen;
|
||||
st.texGenGen = tgGen;
|
||||
}
|
||||
}
|
||||
|
||||
if (program.getVertexKey().clipPlanesEnabled()) {
|
||||
final int cpGen = GLStateManager.clipPlaneGeneration;
|
||||
if (programChanged || cpGen != lastClipPlaneGen) {
|
||||
if (cpGen != st.clipPlaneGen) {
|
||||
uploadClipPlanes(program);
|
||||
lastClipPlaneGen = cpGen;
|
||||
st.clipPlaneGen = cpGen;
|
||||
}
|
||||
}
|
||||
|
||||
final int fragGen = GLStateManager.fragmentGeneration;
|
||||
if (programChanged || fragGen != lastFragmentGen) {
|
||||
if (fragGen != st.fragmentGen) {
|
||||
uploadFragmentUniforms(program);
|
||||
lastFragmentGen = fragGen;
|
||||
st.fragmentGen = fragGen;
|
||||
}
|
||||
|
||||
// Wide line emulation uniforms
|
||||
if (program.locLineWidth != -1 && program.locViewportSize != -1) {
|
||||
uploadWideLineUniforms(program, programChanged);
|
||||
uploadWideLineUniforms(program);
|
||||
}
|
||||
}
|
||||
|
||||
private void uploadMatrices(Program program, boolean mvChanged, boolean projChanged, boolean texMatChanged) {
|
||||
private void uploadMatrices(Program program, boolean mvChanged, boolean mvLinearChanged, boolean projChanged, boolean texMatChanged) {
|
||||
final Matrix4f mv = GLStateManager.getModelViewMatrix();
|
||||
final Matrix4f proj = GLStateManager.getProjectionMatrix();
|
||||
|
||||
@@ -165,7 +148,9 @@ public class Uniforms {
|
||||
mv.get(mat4Buf);
|
||||
RENDER_BACKEND.uniformMatrix4(program.locModelViewMatrix, false, mat4Buf);
|
||||
}
|
||||
}
|
||||
|
||||
if (mvLinearChanged) {
|
||||
// Normal matrix = inverse transpose of upper-left 3x3 of ModelView
|
||||
if (program.locNormalMatrix != -1 || program.locNormalScale != -1) {
|
||||
mv.normal(normalMatrix);
|
||||
@@ -314,12 +299,13 @@ public class Uniforms {
|
||||
if (program.locCurrentColor == -1) return;
|
||||
// Upload the current color from GLSM
|
||||
final var color = GLStateManager.getColor();
|
||||
tempVec4.set(
|
||||
Math.clamp(0f, 1f, color.getRed()),
|
||||
Math.clamp(0f, 1f, color.getGreen()),
|
||||
Math.clamp(0f, 1f, color.getBlue()),
|
||||
Math.clamp(0f, 1f, color.getAlpha()));
|
||||
vec4Buf.clear();
|
||||
vec4Buf.put(Math.clamp(0f, 1f, color.getRed()));
|
||||
vec4Buf.put(Math.clamp(0f, 1f, color.getGreen()));
|
||||
vec4Buf.put(Math.clamp(0f, 1f, color.getBlue()));
|
||||
vec4Buf.put(Math.clamp(0f, 1f, color.getAlpha()));
|
||||
vec4Buf.flip();
|
||||
tempVec4.get(vec4Buf);
|
||||
RENDER_BACKEND.uniform4(program.locCurrentColor, vec4Buf);
|
||||
}
|
||||
|
||||
@@ -342,10 +328,7 @@ public class Uniforms {
|
||||
// Upload current normal from FFPShaderManager's tracked normal
|
||||
final var normal = ShaderManager.getCurrentNormal();
|
||||
vec3Buf.clear();
|
||||
vec3Buf.put(normal.x);
|
||||
vec3Buf.put(normal.y);
|
||||
vec3Buf.put(normal.z);
|
||||
vec3Buf.flip();
|
||||
normal.get(vec3Buf);
|
||||
RENDER_BACKEND.uniform3(program.locCurrentNormal, vec3Buf);
|
||||
}
|
||||
|
||||
@@ -381,10 +364,7 @@ public class Uniforms {
|
||||
private void uploadPlane(int loc, float[] plane) {
|
||||
if (loc == -1) return;
|
||||
vec4Buf.clear();
|
||||
vec4Buf.put(plane[0]);
|
||||
vec4Buf.put(plane[1]);
|
||||
vec4Buf.put(plane[2]);
|
||||
vec4Buf.put(plane[3]);
|
||||
vec4Buf.put(plane, 0, 4);
|
||||
vec4Buf.flip();
|
||||
RENDER_BACKEND.uniform4(loc, vec4Buf);
|
||||
}
|
||||
@@ -470,29 +450,26 @@ public class Uniforms {
|
||||
}
|
||||
}
|
||||
|
||||
private void uploadWideLineUniforms(Program program, boolean programChanged) {
|
||||
private void uploadWideLineUniforms(Program program) {
|
||||
final Program.UploadState st = program.uploadState;
|
||||
final float lineWidth = GLStateManager.getLineState().getWidth();
|
||||
if (programChanged || lineWidth != lastLineWidth) {
|
||||
if (lineWidth != st.lineWidth) {
|
||||
RENDER_BACKEND.uniform1f(program.locLineWidth, lineWidth);
|
||||
lastLineWidth = lineWidth;
|
||||
st.lineWidth = lineWidth;
|
||||
}
|
||||
final int vw = GLStateManager.getViewportState().width;
|
||||
final int vh = GLStateManager.getViewportState().height;
|
||||
if (programChanged || vw != lastViewportWidth || vh != lastViewportHeight) {
|
||||
if (vw != st.viewportWidth || vh != st.viewportHeight) {
|
||||
RENDER_BACKEND.uniform2f(program.locViewportSize, vw, vh);
|
||||
lastViewportWidth = vw;
|
||||
lastViewportHeight = vh;
|
||||
st.viewportWidth = vw;
|
||||
st.viewportHeight = vh;
|
||||
}
|
||||
}
|
||||
|
||||
private void uploadVec4(int loc, Vector4f v) {
|
||||
if (loc == -1) return;
|
||||
vec4Buf.clear();
|
||||
vec4Buf.put(v.x);
|
||||
vec4Buf.put(v.y);
|
||||
vec4Buf.put(v.z);
|
||||
vec4Buf.put(v.w);
|
||||
vec4Buf.flip();
|
||||
v.get(vec4Buf);
|
||||
RENDER_BACKEND.uniform4(loc, vec4Buf);
|
||||
}
|
||||
|
||||
|
||||
@@ -27,65 +27,75 @@ public class LightModelState implements ISettableState<LightModelState> {
|
||||
twoSide = 0.0F;
|
||||
}
|
||||
|
||||
public void setAmbient(FloatBuffer newBuffer) {
|
||||
public boolean setAmbient(FloatBuffer newBuffer) {
|
||||
vector4f.set(newBuffer);
|
||||
if (GLStateManager.shouldBypassCache() || !this.ambient.equals(vector4f)) {
|
||||
this.ambient.set(vector4f);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setAmbient(IntBuffer newBuffer) {
|
||||
public boolean setAmbient(IntBuffer newBuffer) {
|
||||
vector4i.set(newBuffer);
|
||||
vector4f.set(i2f(vector4i.x), i2f(vector4i.y), i2f(vector4i.z), i2f(vector4i.w));
|
||||
if (GLStateManager.shouldBypassCache() || !this.ambient.equals(vector4f)) {
|
||||
this.ambient.set(vector4f);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setColorControl(int val) {
|
||||
public boolean setColorControl(int val) {
|
||||
if (GLStateManager.shouldBypassCache() || this.colorControl != val) {
|
||||
this.colorControl = val;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setColorControl(IntBuffer newBuffer) {
|
||||
setColorControl(newBuffer.get());
|
||||
public boolean setColorControl(IntBuffer newBuffer) {
|
||||
return setColorControl(newBuffer.get());
|
||||
}
|
||||
|
||||
public void setLocalViewer(float val) {
|
||||
public boolean setLocalViewer(float val) {
|
||||
if (GLStateManager.shouldBypassCache() || Float.compare(this.localViewer, val) != 0) {
|
||||
this.localViewer = val;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setLocalViewer(FloatBuffer newBuffer) {
|
||||
setLocalViewer(newBuffer.get());
|
||||
public boolean setLocalViewer(FloatBuffer newBuffer) {
|
||||
return setLocalViewer(newBuffer.get());
|
||||
}
|
||||
|
||||
public void setLocalViewer(IntBuffer newBuffer) {
|
||||
setLocalViewer((float) newBuffer.get());
|
||||
public boolean setLocalViewer(IntBuffer newBuffer) {
|
||||
return setLocalViewer((float) newBuffer.get());
|
||||
}
|
||||
|
||||
public void setLocalViewer(int val) {
|
||||
setLocalViewer((float) val);
|
||||
public boolean setLocalViewer(int val) {
|
||||
return setLocalViewer((float) val);
|
||||
}
|
||||
|
||||
public void setTwoSide(float val) {
|
||||
public boolean setTwoSide(float val) {
|
||||
if (GLStateManager.shouldBypassCache() || Float.compare(this.twoSide, val) != 0) {
|
||||
this.twoSide = val;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setTwoSide(FloatBuffer newBuffer) {
|
||||
setTwoSide(newBuffer.get());
|
||||
public boolean setTwoSide(FloatBuffer newBuffer) {
|
||||
return setTwoSide(newBuffer.get());
|
||||
}
|
||||
|
||||
public void setTwoSide(IntBuffer newBuffer) {
|
||||
setTwoSide((float) newBuffer.get());
|
||||
public boolean setTwoSide(IntBuffer newBuffer) {
|
||||
return setTwoSide((float) newBuffer.get());
|
||||
}
|
||||
|
||||
public void setTwoSide(int val) {
|
||||
setTwoSide((float) val);
|
||||
public boolean setTwoSide(int val) {
|
||||
return setTwoSide((float) val);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -17,6 +17,7 @@ public class LightState implements ISettableState<LightState> {
|
||||
|
||||
private static final Vector4i vector4i = new Vector4i();
|
||||
private static final Vector4f vector4f = new Vector4f();
|
||||
private static final Vector3f vector3f = new Vector3f();
|
||||
private static final Vector3i vector3i = new Vector3i();
|
||||
private static final Matrix3f matrix3f = new Matrix3f();
|
||||
|
||||
@@ -27,6 +28,10 @@ public class LightState implements ISettableState<LightState> {
|
||||
public final Vector4f specular;
|
||||
public final Vector4f position;
|
||||
public final Vector3f spotDirection;
|
||||
private final Vector4f rawPosition;
|
||||
private int posMvGeneration = -1;
|
||||
private final Vector3f rawSpotDirection;
|
||||
private int spotDirLinearGeneration = -1;
|
||||
public float spotExponent;
|
||||
public float spotCutoff;
|
||||
public float spotCosCutoff;
|
||||
@@ -66,178 +71,221 @@ public class LightState implements ISettableState<LightState> {
|
||||
this.linearAttenuation = linearAttenuation;
|
||||
this.quadraticAttenuation = quadraticAttenuation;
|
||||
|
||||
this.rawPosition = new Vector4f(position);
|
||||
this.position = position;
|
||||
this.position.mul(GLStateManager.getModelViewMatrix());
|
||||
this.posMvGeneration = GLStateManager.mvGeneration;
|
||||
|
||||
this.rawSpotDirection = new Vector3f(spotDirection);
|
||||
this.spotDirection = spotDirection;
|
||||
GLStateManager.getModelViewMatrix().get3x3(matrix3f);
|
||||
this.spotDirection.mul(matrix3f);
|
||||
this.spotDirLinearGeneration = GLStateManager.mvLinearGeneration;
|
||||
}
|
||||
|
||||
public void setAmbient(FloatBuffer newBuffer) {
|
||||
public boolean setAmbient(FloatBuffer newBuffer) {
|
||||
vector4f.set(newBuffer);
|
||||
if (GLStateManager.shouldBypassCache() || !this.ambient.equals(vector4f)) {
|
||||
this.ambient.set(vector4f);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setAmbient(IntBuffer newBuffer) {
|
||||
public boolean setAmbient(IntBuffer newBuffer) {
|
||||
vector4i.set(newBuffer);
|
||||
vector4f.set(i2f(vector4i.x), i2f(vector4i.y), i2f(vector4i.z), i2f(vector4i.w));
|
||||
if (GLStateManager.shouldBypassCache() || !this.ambient.equals(vector4f)) {
|
||||
this.ambient.set(vector4f);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setDiffuse(FloatBuffer newBuffer) {
|
||||
public boolean setDiffuse(FloatBuffer newBuffer) {
|
||||
vector4f.set(newBuffer);
|
||||
if (GLStateManager.shouldBypassCache() || !this.diffuse.equals(vector4f)) {
|
||||
this.diffuse.set(vector4f);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setDiffuse(IntBuffer newBuffer) {
|
||||
public boolean setDiffuse(IntBuffer newBuffer) {
|
||||
vector4i.set(newBuffer);
|
||||
vector4f.set(i2f(vector4i.x), i2f(vector4i.y), i2f(vector4i.z), i2f(vector4i.w));
|
||||
if (GLStateManager.shouldBypassCache() || !this.diffuse.equals(vector4f)) {
|
||||
this.diffuse.set(vector4f);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setSpecular(FloatBuffer newBuffer) {
|
||||
public boolean setSpecular(FloatBuffer newBuffer) {
|
||||
vector4f.set(newBuffer);
|
||||
if (GLStateManager.shouldBypassCache() || !this.specular.equals(vector4f)) {
|
||||
this.specular.set(vector4f);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setSpecular(IntBuffer newBuffer) {
|
||||
public boolean setSpecular(IntBuffer newBuffer) {
|
||||
vector4i.set(newBuffer);
|
||||
vector4f.set(i2f(vector4i.x), i2f(vector4i.y), i2f(vector4i.z), i2f(vector4i.w));
|
||||
if (GLStateManager.shouldBypassCache() || !this.specular.equals(vector4f)) {
|
||||
this.specular.set(vector4f);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setPosition(FloatBuffer newBuffer) {
|
||||
// We are bypassing cache everytime for position, because the necessary components to enable tracking the cache
|
||||
// are big and probably more than just bypassing. We would need to track the modelview matrix it was transformed
|
||||
// with and the untransformed coordinates in addition to the final transformation.
|
||||
this.position.set(newBuffer);
|
||||
this.position.mul(GLStateManager.getModelViewMatrix());
|
||||
public boolean setPosition(FloatBuffer newBuffer) {
|
||||
vector4f.set(newBuffer);
|
||||
return applyPosition(vector4f);
|
||||
}
|
||||
|
||||
public void setPosition(IntBuffer newBuffer) {
|
||||
public boolean setPosition(IntBuffer newBuffer) {
|
||||
vector4i.set(newBuffer);
|
||||
this.position.set((float) vector4i.x, (float) vector4i.y, (float) vector4i.z, (float) vector4i.w);
|
||||
this.position.mul(GLStateManager.getModelViewMatrix());
|
||||
vector4f.set((float) vector4i.x, (float) vector4i.y, (float) vector4i.z, (float) vector4i.w);
|
||||
return applyPosition(vector4f);
|
||||
}
|
||||
|
||||
public void setSpotDirection(FloatBuffer newBuffer) {
|
||||
// We are bypassing cache everytime for spot direction, because the necessary components to enable tracking the cache
|
||||
// are big and probably more than just bypassing. We would need to track the modelview matrix it was transformed
|
||||
// with and the untransformed coordinates in addition to the final transformation.
|
||||
GLStateManager.getModelViewMatrix().get3x3(matrix3f);
|
||||
this.spotDirection.set(newBuffer);
|
||||
this.spotDirection.mul(matrix3f);
|
||||
private boolean applyPosition(Vector4f raw) {
|
||||
final int mvGen = GLStateManager.mvGeneration;
|
||||
if (GLStateManager.shouldBypassCache() || this.posMvGeneration != mvGen || !this.rawPosition.equals(raw)) {
|
||||
this.rawPosition.set(raw);
|
||||
this.posMvGeneration = mvGen;
|
||||
this.position.set(raw);
|
||||
this.position.mul(GLStateManager.getModelViewMatrix());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setSpotDirection(IntBuffer newBuffer) {
|
||||
public boolean setSpotDirection(FloatBuffer newBuffer) {
|
||||
vector3f.set(newBuffer);
|
||||
return applySpotDirection(vector3f);
|
||||
}
|
||||
|
||||
public boolean setSpotDirection(IntBuffer newBuffer) {
|
||||
vector3i.set(newBuffer);
|
||||
GLStateManager.getModelViewMatrix().get3x3(matrix3f);
|
||||
this.spotDirection.set((float) vector3i.x, (float) vector3i.y, (float) vector3i.z);
|
||||
this.spotDirection.mul(matrix3f);
|
||||
vector3f.set((float) vector3i.x, (float) vector3i.y, (float) vector3i.z);
|
||||
return applySpotDirection(vector3f);
|
||||
}
|
||||
|
||||
public void setSpotExponent(FloatBuffer newBuffer) {
|
||||
setSpotExponent(newBuffer.get());
|
||||
private boolean applySpotDirection(Vector3f raw) {
|
||||
final int mvLinearGen = GLStateManager.mvLinearGeneration;
|
||||
if (GLStateManager.shouldBypassCache() || this.spotDirLinearGeneration != mvLinearGen || !this.rawSpotDirection.equals(raw)) {
|
||||
this.rawSpotDirection.set(raw);
|
||||
this.spotDirLinearGeneration = mvLinearGen;
|
||||
GLStateManager.getModelViewMatrix().get3x3(matrix3f);
|
||||
this.spotDirection.set(raw);
|
||||
this.spotDirection.mul(matrix3f);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setSpotExponent(IntBuffer newBuffer) {
|
||||
setSpotExponent((float) newBuffer.get());
|
||||
public boolean setSpotExponent(FloatBuffer newBuffer) {
|
||||
return setSpotExponent(newBuffer.get());
|
||||
}
|
||||
|
||||
public void setSpotExponent(int i) {
|
||||
setSpotExponent((float) i);
|
||||
public boolean setSpotExponent(IntBuffer newBuffer) {
|
||||
return setSpotExponent((float) newBuffer.get());
|
||||
}
|
||||
|
||||
public void setSpotExponent(float f) {
|
||||
public boolean setSpotExponent(int i) {
|
||||
return setSpotExponent((float) i);
|
||||
}
|
||||
|
||||
public boolean setSpotExponent(float f) {
|
||||
if (GLStateManager.shouldBypassCache() || Float.compare(f, this.spotExponent) != 0) {
|
||||
this.spotExponent = f;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setSpotCutoff(FloatBuffer newBuffer) {
|
||||
setSpotCutoff(newBuffer.get());
|
||||
public boolean setSpotCutoff(FloatBuffer newBuffer) {
|
||||
return setSpotCutoff(newBuffer.get());
|
||||
}
|
||||
|
||||
public void setSpotCutoff(IntBuffer newBuffer) {
|
||||
setSpotCutoff((float) newBuffer.get());
|
||||
public boolean setSpotCutoff(IntBuffer newBuffer) {
|
||||
return setSpotCutoff((float) newBuffer.get());
|
||||
}
|
||||
|
||||
public void setSpotCutoff(int i) {
|
||||
setSpotCutoff((float) i);
|
||||
public boolean setSpotCutoff(int i) {
|
||||
return setSpotCutoff((float) i);
|
||||
}
|
||||
|
||||
public void setSpotCutoff(float f) {
|
||||
public boolean setSpotCutoff(float f) {
|
||||
if (GLStateManager.shouldBypassCache() || Float.compare(f, this.spotCutoff) != 0) {
|
||||
this.spotCutoff = f;
|
||||
this.spotCosCutoff = (float) Math.cos(Math.toRadians(f));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setConstantAttenuation(FloatBuffer newBuffer) {
|
||||
setConstantAttenuation(newBuffer.get());
|
||||
public boolean setConstantAttenuation(FloatBuffer newBuffer) {
|
||||
return setConstantAttenuation(newBuffer.get());
|
||||
}
|
||||
|
||||
public void setConstantAttenuation(IntBuffer newBuffer) {
|
||||
setConstantAttenuation((float) newBuffer.get());
|
||||
public boolean setConstantAttenuation(IntBuffer newBuffer) {
|
||||
return setConstantAttenuation((float) newBuffer.get());
|
||||
}
|
||||
|
||||
public void setConstantAttenuation(int i) {
|
||||
setConstantAttenuation((float) i);
|
||||
public boolean setConstantAttenuation(int i) {
|
||||
return setConstantAttenuation((float) i);
|
||||
}
|
||||
|
||||
public void setConstantAttenuation(float f) {
|
||||
public boolean setConstantAttenuation(float f) {
|
||||
if (GLStateManager.shouldBypassCache() || Float.compare(f, this.constantAttenuation) != 0) {
|
||||
this.constantAttenuation = f;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setLinearAttenuation(FloatBuffer newBuffer) {
|
||||
setLinearAttenuation(newBuffer.get());
|
||||
public boolean setLinearAttenuation(FloatBuffer newBuffer) {
|
||||
return setLinearAttenuation(newBuffer.get());
|
||||
}
|
||||
|
||||
public void setLinearAttenuation(IntBuffer newBuffer) {
|
||||
setLinearAttenuation((float) newBuffer.get());
|
||||
public boolean setLinearAttenuation(IntBuffer newBuffer) {
|
||||
return setLinearAttenuation((float) newBuffer.get());
|
||||
}
|
||||
|
||||
public void setLinearAttenuation(int i) {
|
||||
setLinearAttenuation((float) i);
|
||||
public boolean setLinearAttenuation(int i) {
|
||||
return setLinearAttenuation((float) i);
|
||||
}
|
||||
|
||||
public void setLinearAttenuation(float f) {
|
||||
public boolean setLinearAttenuation(float f) {
|
||||
if (GLStateManager.shouldBypassCache() || Float.compare(f, this.linearAttenuation) != 0) {
|
||||
this.linearAttenuation = f;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setQuadraticAttenuation(FloatBuffer newBuffer) {
|
||||
setQuadraticAttenuation(newBuffer.get());
|
||||
public boolean setQuadraticAttenuation(FloatBuffer newBuffer) {
|
||||
return setQuadraticAttenuation(newBuffer.get());
|
||||
}
|
||||
|
||||
public void setQuadraticAttenuation(IntBuffer newBuffer) {
|
||||
setQuadraticAttenuation((float) newBuffer.get());
|
||||
public boolean setQuadraticAttenuation(IntBuffer newBuffer) {
|
||||
return setQuadraticAttenuation((float) newBuffer.get());
|
||||
}
|
||||
|
||||
public void setQuadraticAttenuation(int i) {
|
||||
setQuadraticAttenuation((float) i);
|
||||
public boolean setQuadraticAttenuation(int i) {
|
||||
return setQuadraticAttenuation((float) i);
|
||||
}
|
||||
|
||||
public void setQuadraticAttenuation(float f) {
|
||||
public boolean setQuadraticAttenuation(float f) {
|
||||
if (GLStateManager.shouldBypassCache() || Float.compare(f, this.quadraticAttenuation) != 0) {
|
||||
this.quadraticAttenuation = f;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -246,7 +294,11 @@ public class LightState implements ISettableState<LightState> {
|
||||
this.diffuse.set(state.diffuse);
|
||||
this.specular.set(state.specular);
|
||||
this.position.set(state.position);
|
||||
this.rawPosition.set(state.rawPosition);
|
||||
this.posMvGeneration = state.posMvGeneration;
|
||||
this.spotDirection.set(state.spotDirection);
|
||||
this.rawSpotDirection.set(state.rawSpotDirection);
|
||||
this.spotDirLinearGeneration = state.spotDirLinearGeneration;
|
||||
this.spotExponent = state.spotExponent;
|
||||
this.spotCutoff = state.spotCutoff;
|
||||
this.spotCosCutoff = state.spotCosCutoff;
|
||||
|
||||
@@ -37,82 +37,100 @@ public class MaterialState implements ISettableState<MaterialState> {
|
||||
colorIndexes = new Vector3f(0.0F, 1.0F, 1.0F);
|
||||
}
|
||||
|
||||
public void setAmbient(FloatBuffer newBuffer) {
|
||||
public boolean setAmbient(FloatBuffer newBuffer) {
|
||||
vector4f.set(newBuffer);
|
||||
if (GLStateManager.shouldBypassCache() || !this.ambient.equals(vector4f)) {
|
||||
this.ambient.set(vector4f);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setAmbient(IntBuffer newBuffer) {
|
||||
public boolean setAmbient(IntBuffer newBuffer) {
|
||||
vector4i.set(newBuffer);
|
||||
vector4f.set(i2f(vector4i.x), i2f(vector4i.y), i2f(vector4i.z), i2f(vector4i.w));
|
||||
if (GLStateManager.shouldBypassCache() || !this.ambient.equals(vector4f)) {
|
||||
this.ambient.set(vector4f);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setDiffuse(FloatBuffer newBuffer) {
|
||||
public boolean setDiffuse(FloatBuffer newBuffer) {
|
||||
vector4f.set(newBuffer);
|
||||
if (GLStateManager.shouldBypassCache() || !this.diffuse.equals(vector4f)) {
|
||||
this.diffuse.set(vector4f);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setDiffuse(IntBuffer newBuffer) {
|
||||
public boolean setDiffuse(IntBuffer newBuffer) {
|
||||
vector4i.set(newBuffer);
|
||||
vector4f.set(i2f(vector4i.x), i2f(vector4i.y), i2f(vector4i.z), i2f(vector4i.w));
|
||||
if (GLStateManager.shouldBypassCache() || !this.diffuse.equals(vector4f)) {
|
||||
this.diffuse.set(vector4f);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setSpecular(FloatBuffer newBuffer) {
|
||||
public boolean setSpecular(FloatBuffer newBuffer) {
|
||||
vector4f.set(newBuffer);
|
||||
if (GLStateManager.shouldBypassCache() || !this.specular.equals(vector4f)) {
|
||||
this.specular.set(vector4f);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setSpecular(IntBuffer newBuffer) {
|
||||
public boolean setSpecular(IntBuffer newBuffer) {
|
||||
vector4i.set(newBuffer);
|
||||
vector4f.set(i2f(vector4i.x), i2f(vector4i.y), i2f(vector4i.z), i2f(vector4i.w));
|
||||
if (GLStateManager.shouldBypassCache() || !this.specular.equals(vector4f)) {
|
||||
this.specular.set(vector4f);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setEmission(FloatBuffer newBuffer) {
|
||||
public boolean setEmission(FloatBuffer newBuffer) {
|
||||
vector4f.set(newBuffer);
|
||||
if (GLStateManager.shouldBypassCache() || !this.emission.equals(vector4f)) {
|
||||
this.emission.set(vector4f);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setEmission(IntBuffer newBuffer) {
|
||||
public boolean setEmission(IntBuffer newBuffer) {
|
||||
vector4i.set(newBuffer);
|
||||
vector4f.set(i2f(vector4i.x), i2f(vector4i.y), i2f(vector4i.z), i2f(vector4i.w));
|
||||
if (GLStateManager.shouldBypassCache() || !this.emission.equals(vector4f)) {
|
||||
this.emission.set(vector4f);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setShininess(float val) {
|
||||
public boolean setShininess(float val) {
|
||||
if (GLStateManager.shouldBypassCache() || Float.compare(this.shininess, val) != 0) {
|
||||
this.shininess = val;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// On the buffer versions of shininess, we need to call `get(0)` explicitly specifying the index
|
||||
// otherwise calling `get()` advances the buffer position, and some mods may re-use the same buffer
|
||||
// in subsequent calls, resulting in a BufferUnderflowException.
|
||||
public void setShininess(FloatBuffer newBuffer) { setShininess(newBuffer.get(0)); }
|
||||
public boolean setShininess(FloatBuffer newBuffer) { return setShininess(newBuffer.get(0)); }
|
||||
|
||||
public void setShininess(IntBuffer newBuffer) { setShininess((float) newBuffer.get(0)); }
|
||||
public boolean setShininess(IntBuffer newBuffer) { return setShininess((float) newBuffer.get(0)); }
|
||||
|
||||
public void setShininess(int val) { setShininess((float) val);}
|
||||
public boolean setShininess(int val) { return setShininess((float) val);}
|
||||
|
||||
public void setColorIndexes(FloatBuffer newBuffer) {
|
||||
public boolean setColorIndexes(FloatBuffer newBuffer) {
|
||||
// You are reading this correctly, nvidia drivers flip the y and z values in
|
||||
// glMaterial specifically for GL_COLOR_INDEXES. Other drivers do not do this.
|
||||
// This probably breaks things but who knows, GLSM is setup to track to what the
|
||||
@@ -125,15 +143,19 @@ public class MaterialState implements ISettableState<MaterialState> {
|
||||
|
||||
if (GLStateManager.shouldBypassCache() || !this.colorIndexes.equals(vector3f)) {
|
||||
this.colorIndexes.set(vector3f);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setColorIndexes(IntBuffer newBuffer) {
|
||||
public boolean setColorIndexes(IntBuffer newBuffer) {
|
||||
vector3i.set(newBuffer.get(0), newBuffer.get(2), newBuffer.get(1));
|
||||
vector3f.set((float) vector3i.x, (float) vector3i.y, (float) vector3i.z);
|
||||
if (GLStateManager.shouldBypassCache() || !this.colorIndexes.equals(vector3f)) {
|
||||
this.colorIndexes.set(vector3f);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -68,7 +68,7 @@ class CompatUniformManagerTest {
|
||||
|
||||
// Use program and upload — should not error
|
||||
GL20.glUseProgram(program);
|
||||
CompatUniformManager.onUseProgram(program);
|
||||
CompatUniformManager.refreshCompatUniforms(program);
|
||||
|
||||
// Verify no GL errors
|
||||
assertEquals(0, org.lwjgl.opengl.GL11.glGetError(), "GL error after uniform upload");
|
||||
@@ -146,7 +146,7 @@ class CompatUniformManagerTest {
|
||||
|
||||
// Use program and upload — should not error
|
||||
GL20.glUseProgram(program);
|
||||
CompatUniformManager.onUseProgram(program);
|
||||
CompatUniformManager.refreshCompatUniforms(program);
|
||||
|
||||
assertEquals(0, org.lwjgl.opengl.GL11.glGetError(), "GL error after fog uniform upload");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.GLSMInitConfig;
|
||||
import org.junit.jupiter.api.extension.AfterAllCallback;
|
||||
import org.junit.jupiter.api.extension.BeforeAllCallback;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||
import org.lwjgl.LWJGLException;
|
||||
import org.lwjgl.opengl.ContextAttribs;
|
||||
import org.lwjgl.opengl.Display;
|
||||
import org.lwjgl.opengl.DisplayMode;
|
||||
import org.lwjgl.opengl.PixelFormat;
|
||||
|
||||
/**
|
||||
* 3.3 core-profile context extension
|
||||
*/
|
||||
public class GLSMCoreExtension implements BeforeAllCallback, AfterAllCallback {
|
||||
private boolean ownsDisplay = false;
|
||||
|
||||
@Override
|
||||
public void beforeAll(ExtensionContext context) throws LWJGLException {
|
||||
if (Display.isCreated()) return;
|
||||
Display.setDisplayModeAndFullscreen(new DisplayMode(800, 600));
|
||||
Display.setResizable(false);
|
||||
Display.setFullscreen(false);
|
||||
Display.create(
|
||||
new PixelFormat().withDepthBits(24).withStencilBits(8),
|
||||
new ContextAttribs(3, 3).withProfileCore(true).withForwardCompatible(true));
|
||||
ownsDisplay = true;
|
||||
GLStateManager.initialize(GLSMInitConfig.builder().displaySize(800, 600).build());
|
||||
GLStateManager.setRunningSplash(false);
|
||||
GLStateManager.markSplashComplete();
|
||||
GLStateManager.BYPASS_CACHE = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterAll(ExtensionContext context) {
|
||||
if (ownsDisplay && Display.isCreated()) Display.destroy();
|
||||
ownsDisplay = false;
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,8 @@ import com.gtnewhorizons.angelica.glsm.hooks.GLSMInitConfig;
|
||||
import org.junit.jupiter.api.extension.AfterEachCallback;
|
||||
import org.junit.jupiter.api.extension.BeforeAllCallback;
|
||||
import org.junit.jupiter.api.extension.BeforeEachCallback;
|
||||
import org.junit.jupiter.api.extension.ConditionEvaluationResult;
|
||||
import org.junit.jupiter.api.extension.ExecutionCondition;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||
import org.lwjgl.LWJGLException;
|
||||
import org.lwjgl.opengl.Display;
|
||||
@@ -19,7 +21,19 @@ import java.lang.reflect.Field;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.extension.ExtensionContext.Namespace.GLOBAL;
|
||||
|
||||
public class GLSMExtension implements BeforeAllCallback, BeforeEachCallback, AfterEachCallback, ExtensionContext.Store.CloseableResource {
|
||||
public class GLSMExtension implements BeforeAllCallback, BeforeEachCallback, AfterEachCallback, ExecutionCondition, ExtensionContext.Store.CloseableResource {
|
||||
|
||||
// Compat profile is not available on OSX
|
||||
private static final boolean IS_MAC = System.getProperty("os.name", "").toLowerCase().contains("mac");
|
||||
private static final boolean FORCE_RUN = Boolean.getBoolean("angelica.glsm.test.forceRun");
|
||||
|
||||
@Override
|
||||
public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) {
|
||||
if (IS_MAC && !FORCE_RUN) {
|
||||
return ConditionEvaluationResult.disabled("Skipped on macOS: needs GL3+ compat profile");
|
||||
}
|
||||
return ConditionEvaluationResult.enabled("OS supports GL3+ compat profile");
|
||||
}
|
||||
|
||||
private static final Unsafe theUnsafe;
|
||||
static {
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import org.joml.Vector4f;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
@ExtendWith(GLSMCoreExtension.class)
|
||||
public class GLSM_DirtyTracking_UnitTest {
|
||||
|
||||
static final FloatBuffer f4b = ByteBuffer.allocateDirect(4 << 2).order(ByteOrder.nativeOrder()).asFloatBuffer();
|
||||
static final FloatBuffer f3b = ByteBuffer.allocateDirect(3 << 2).order(ByteOrder.nativeOrder()).asFloatBuffer();
|
||||
|
||||
@BeforeEach
|
||||
void pushTrackedState() {
|
||||
GLStateManager.glPushAttrib(GL11.GL_LIGHTING_BIT | GL11.GL_FOG_BIT | GL11.GL_CURRENT_BIT);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void popTrackedState() {
|
||||
GLStateManager.glPopAttrib();
|
||||
}
|
||||
|
||||
@Test
|
||||
void materialBumpsOnlyOnChange() {
|
||||
newf4b(0.1F, 0.2F, 0.3F, 0.4F);
|
||||
GLStateManager.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT, f4b);
|
||||
final int gen = GLStateManager.lightingGeneration;
|
||||
|
||||
newf4b(0.1F, 0.2F, 0.3F, 0.4F);
|
||||
GLStateManager.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT, f4b);
|
||||
assertEquals(gen, GLStateManager.lightingGeneration, "identical material must not bump lightingGeneration");
|
||||
|
||||
newf4b(0.9F, 0.2F, 0.3F, 0.4F);
|
||||
GLStateManager.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT, f4b);
|
||||
assertEquals(gen + 1, GLStateManager.lightingGeneration, "changed material must bump lightingGeneration once");
|
||||
}
|
||||
|
||||
@Test
|
||||
void lightModelBumpsOnlyOnChange() {
|
||||
newf4b(0.5F, 0.5F, 0.5F, 1.0F);
|
||||
GLStateManager.glLightModel(GL11.GL_LIGHT_MODEL_AMBIENT, f4b);
|
||||
final int gen = GLStateManager.lightingGeneration;
|
||||
|
||||
newf4b(0.5F, 0.5F, 0.5F, 1.0F);
|
||||
GLStateManager.glLightModel(GL11.GL_LIGHT_MODEL_AMBIENT, f4b);
|
||||
assertEquals(gen, GLStateManager.lightingGeneration, "identical light model ambient must not bump");
|
||||
}
|
||||
|
||||
@Test
|
||||
void lightColorBumpsOnlyOnChange() {
|
||||
newf4b(0.25F, 0.5F, 0.75F, 1.0F);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_DIFFUSE, f4b);
|
||||
final int gen = GLStateManager.lightingGeneration;
|
||||
|
||||
newf4b(0.25F, 0.5F, 0.75F, 1.0F);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_DIFFUSE, f4b);
|
||||
assertEquals(gen, GLStateManager.lightingGeneration, "identical light diffuse must not bump");
|
||||
}
|
||||
|
||||
@Test
|
||||
void lightPositionDirtySkipsUnderSameModelview() {
|
||||
GLStateManager.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
GLStateManager.glPushMatrix();
|
||||
GLStateManager.glLoadIdentity();
|
||||
GLStateManager.glTranslatef(1.0F, 2.0F, 3.0F);
|
||||
|
||||
newf4b(0.1F, 0.2F, 0.3F, 1.0F);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_POSITION, f4b);
|
||||
final int gen = GLStateManager.lightingGeneration;
|
||||
|
||||
newf4b(0.1F, 0.2F, 0.3F, 1.0F);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_POSITION, f4b);
|
||||
assertEquals(gen, GLStateManager.lightingGeneration, "same position under same modelview must not bump");
|
||||
|
||||
GLStateManager.glTranslatef(5.0F, 0.0F, 0.0F);
|
||||
newf4b(0.1F, 0.2F, 0.3F, 1.0F);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_POSITION, f4b);
|
||||
assertEquals(gen + 1, GLStateManager.lightingGeneration, "same raw position under changed modelview must bump");
|
||||
|
||||
GLStateManager.glPopMatrix();
|
||||
}
|
||||
|
||||
@Test
|
||||
void translationDoesNotBumpLinearGeneration() {
|
||||
GLStateManager.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
GLStateManager.glPushMatrix();
|
||||
|
||||
final int mv = GLStateManager.mvGeneration;
|
||||
final int lin = GLStateManager.mvLinearGeneration;
|
||||
|
||||
GLStateManager.glTranslatef(1.0F, 2.0F, 3.0F);
|
||||
assertEquals(mv + 1, GLStateManager.mvGeneration, "translate must bump mvGeneration");
|
||||
assertEquals(lin, GLStateManager.mvLinearGeneration, "translate must NOT bump mvLinearGeneration");
|
||||
|
||||
GLStateManager.glRotatef(30.0F, 0.0F, 1.0F, 0.0F);
|
||||
assertEquals(mv + 2, GLStateManager.mvGeneration, "rotate must bump mvGeneration");
|
||||
assertEquals(lin + 1, GLStateManager.mvLinearGeneration, "rotate must bump mvLinearGeneration");
|
||||
|
||||
GLStateManager.glScalef(2.0F, 2.0F, 2.0F);
|
||||
assertEquals(lin + 2, GLStateManager.mvLinearGeneration, "scale must bump mvLinearGeneration");
|
||||
|
||||
GLStateManager.glPopMatrix();
|
||||
}
|
||||
|
||||
@Test
|
||||
void fogBumpsOnlyOnChange() {
|
||||
GLStateManager.glFogf(GL11.GL_FOG_DENSITY, 0.5F);
|
||||
final int gen = GLStateManager.fragmentGeneration;
|
||||
|
||||
GLStateManager.glFogf(GL11.GL_FOG_DENSITY, 0.5F);
|
||||
assertEquals(gen, GLStateManager.fragmentGeneration, "identical fog density must not bump fragmentGeneration");
|
||||
|
||||
GLStateManager.glFogf(GL11.GL_FOG_DENSITY, 0.7F);
|
||||
assertEquals(gen + 1, GLStateManager.fragmentGeneration, "changed fog density must bump fragmentGeneration");
|
||||
}
|
||||
|
||||
@Test
|
||||
void spotDirectionDirtySkipsUnderTranslationOnly() {
|
||||
GLStateManager.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
GLStateManager.glPushMatrix();
|
||||
GLStateManager.glLoadIdentity();
|
||||
|
||||
newf3b(0.0F, 0.0F, -1.0F);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_SPOT_DIRECTION, f3b);
|
||||
final int gen = GLStateManager.lightingGeneration;
|
||||
|
||||
GLStateManager.glTranslatef(5.0F, 0.0F, 0.0F);
|
||||
newf3b(0.0F, 0.0F, -1.0F);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_SPOT_DIRECTION, f3b);
|
||||
assertEquals(gen, GLStateManager.lightingGeneration, "spot direction under translation-only must not bump");
|
||||
|
||||
GLStateManager.glRotatef(90.0F, 0.0F, 1.0F, 0.0F);
|
||||
newf3b(0.0F, 0.0F, -1.0F);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_SPOT_DIRECTION, f3b);
|
||||
assertEquals(gen + 1, GLStateManager.lightingGeneration, "same raw spot direction under changed 3x3 must bump");
|
||||
|
||||
GLStateManager.glPopMatrix();
|
||||
}
|
||||
|
||||
@Test
|
||||
void colorMaterialFreezesLastColorOnDisable() {
|
||||
GLStateManager.glColorMaterial(GL11.GL_FRONT_AND_BACK, GL11.GL_AMBIENT_AND_DIFFUSE);
|
||||
GLStateManager.glColor4f(1.0F, 0.0F, 0.0F, 1.0F); // enable-time color
|
||||
GLStateManager.enableColorMaterial();
|
||||
GLStateManager.glColor4f(0.0F, 0.0F, 1.0F, 1.0F); // last color while enabled
|
||||
GLStateManager.disableColorMaterial();
|
||||
|
||||
final Vector4f diffuse = GLStateManager.getFrontMaterial().diffuse;
|
||||
assertEquals(0.0F, diffuse.x, "diffuse must freeze at last color (blue), not enable-time red");
|
||||
assertEquals(0.0F, diffuse.y, "green channel must be 0");
|
||||
assertEquals(1.0F, diffuse.z, "blue channel must be 1");
|
||||
}
|
||||
|
||||
static void newf4b(float x, float y, float z, float w) {
|
||||
f4b.clear();
|
||||
f4b.put(x).put(y).put(z).put(w);
|
||||
f4b.flip();
|
||||
}
|
||||
|
||||
static void newf3b(float x, float y, float z) {
|
||||
f3b.clear();
|
||||
f3b.put(x).put(y).put(z);
|
||||
f3b.flip();
|
||||
}
|
||||
}
|
||||
+6
-6
@@ -28,7 +28,7 @@ class VertexAttribDefaultBridgeTest {
|
||||
@Test
|
||||
void testGlColor4fSetsVertexAttrib() {
|
||||
GLStateManager.glColor4f(0.5f, 0.25f, 0.75f, 0.8f);
|
||||
GLStateManager.flushDeferredVertexAttribs();
|
||||
GLStateManager.flushDeferredVertexAttribs(0);
|
||||
|
||||
float[] color = getVertexAttrib4f(COLOR_ATTRIB);
|
||||
assertEquals(0.5f, color[0], EPSILON, "color.r");
|
||||
@@ -40,7 +40,7 @@ class VertexAttribDefaultBridgeTest {
|
||||
@Test
|
||||
void testGlNormal3fSetsVertexAttrib() {
|
||||
GLStateManager.glNormal3f(0.0f, 1.0f, 0.0f);
|
||||
GLStateManager.flushDeferredVertexAttribs();
|
||||
GLStateManager.flushDeferredVertexAttribs(0);
|
||||
|
||||
float[] normal = getVertexAttrib4f(NORMAL_ATTRIB);
|
||||
assertEquals(0.0f, normal[0], EPSILON, "normal.x");
|
||||
@@ -51,7 +51,7 @@ class VertexAttribDefaultBridgeTest {
|
||||
@Test
|
||||
void testSetLightmapTextureCoordsOnUnit1SetsVertexAttrib() {
|
||||
GLStateManager.setLightmapTextureCoords(GL13.GL_TEXTURE1, 240.0f, 128.0f);
|
||||
GLStateManager.flushDeferredVertexAttribs();
|
||||
GLStateManager.flushDeferredVertexAttribs(0);
|
||||
|
||||
float[] lm = getVertexAttrib4f(SECONDARY_UV_ATTRIB);
|
||||
assertEquals(240.0f, lm[0], EPSILON, "lightmap.s");
|
||||
@@ -64,7 +64,7 @@ class VertexAttribDefaultBridgeTest {
|
||||
void testGlTexCoord2fSetsVertexAttrib() {
|
||||
// glTexCoord2f outside recording → sets default vertex attrib 2 (PRIMARY_UV)
|
||||
GLStateManager.glTexCoord2f(0.5f, 0.75f);
|
||||
GLStateManager.flushDeferredVertexAttribs();
|
||||
GLStateManager.flushDeferredVertexAttribs(0);
|
||||
|
||||
float[] uv = getVertexAttrib4f(PRIMARY_UV_ATTRIB);
|
||||
assertEquals(0.5f, uv[0], EPSILON, "texcoord.s");
|
||||
@@ -77,7 +77,7 @@ class VertexAttribDefaultBridgeTest {
|
||||
// Second call is a cache hit — changeColor not called.
|
||||
// Vertex attrib should still hold the correct value from the first call.
|
||||
GLStateManager.glColor4f(0.3f, 0.6f, 0.9f, 1.0f);
|
||||
GLStateManager.flushDeferredVertexAttribs();
|
||||
GLStateManager.flushDeferredVertexAttribs(0);
|
||||
|
||||
float[] color = getVertexAttrib4f(COLOR_ATTRIB);
|
||||
assertEquals(0.3f, color[0], EPSILON, "color.r after dedup");
|
||||
@@ -89,7 +89,7 @@ class VertexAttribDefaultBridgeTest {
|
||||
@Test
|
||||
void testCompileMode_DoesNotSetVertexAttrib() {
|
||||
GLStateManager.glColor4f(0.1f, 0.2f, 0.3f, 1.0f);
|
||||
GLStateManager.flushDeferredVertexAttribs();
|
||||
GLStateManager.flushDeferredVertexAttribs(0);
|
||||
|
||||
int listId = GLStateManager.glGenLists(1);
|
||||
GLStateManager.glNewList(listId, org.lwjgl.opengl.GL11.GL_COMPILE);
|
||||
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
package com.gtnewhorizons.angelica.glsm.ffp;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMCoreExtension;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
|
||||
@ExtendWith(GLSMCoreExtension.class)
|
||||
class ProgramUniformTrackingTest {
|
||||
|
||||
private static Program buildProgram(boolean hasColor) {
|
||||
final VertexKey vk = VertexKey.fromState(hasColor, false, false, false, 0);
|
||||
final FragmentKey fk = FragmentKey.fromState();
|
||||
return Program.create(vk, fk, VertexShaderGenerator.generate(vk), FragmentShaderGenerator.generate(fk), null);
|
||||
}
|
||||
|
||||
@Test
|
||||
void matrixTrackingIsPerProgram() {
|
||||
final Uniforms uniforms = new Uniforms();
|
||||
final Program a = buildProgram(true);
|
||||
final Program b = buildProgram(false);
|
||||
assertNotEquals(a.getProgramId(), b.getProgramId(), "distinct vertex keys must yield distinct programs");
|
||||
try {
|
||||
GLStateManager.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
GLStateManager.glPushMatrix();
|
||||
GLStateManager.glLoadIdentity();
|
||||
|
||||
GLStateManager.glTranslatef(1.0F, 2.0F, 3.0F);
|
||||
final int genA = GLStateManager.mvGeneration;
|
||||
GL20.glUseProgram(a.getProgramId());
|
||||
uniforms.upload(a);
|
||||
assertEquals(genA, a.uploadState.mvGen, "A records the mv generation it uploaded");
|
||||
|
||||
GLStateManager.glTranslatef(4.0F, 0.0F, 0.0F);
|
||||
final int genB = GLStateManager.mvGeneration;
|
||||
assertNotEquals(genA, genB);
|
||||
GL20.glUseProgram(b.getProgramId());
|
||||
uniforms.upload(b);
|
||||
assertEquals(genB, b.uploadState.mvGen, "B records the new mv generation");
|
||||
assertEquals(genA, a.uploadState.mvGen, "A is unchanged -- tracking is per-program, not global");
|
||||
|
||||
// Return to A with the modelview still at genB: A is stale -> re-uploads and catches up.
|
||||
GL20.glUseProgram(a.getProgramId());
|
||||
uniforms.upload(a);
|
||||
assertEquals(genB, a.uploadState.mvGen, "A re-uploads on return and catches up to genB");
|
||||
|
||||
// Re-upload A with no change: gate (mvGeneration == A.mvGen) is satisfied -> skip.
|
||||
uniforms.upload(a);
|
||||
assertEquals(genB, a.uploadState.mvGen, "A already current -> skipped");
|
||||
|
||||
GLStateManager.glPopMatrix();
|
||||
} finally {
|
||||
GL20.glUseProgram(0);
|
||||
a.destroy();
|
||||
b.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -16,7 +16,7 @@ pluginManagement {
|
||||
}
|
||||
|
||||
plugins {
|
||||
id("com.gtnewhorizons.gtnhsettingsconvention") version ("2.0.24")
|
||||
id("com.gtnewhorizons.gtnhsettingsconvention") version ("2.0.25")
|
||||
}
|
||||
|
||||
include("glsm")
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.gtnewhorizons.angelica.event;
|
||||
|
||||
import net.minecraftforge.eventbus.api.bus.CancellableEventBus;
|
||||
import net.minecraftforge.eventbus.api.event.RecordEvent;
|
||||
import net.minecraftforge.eventbus.api.event.characteristic.Cancellable;
|
||||
|
||||
/**
|
||||
* Posted from {@link net.coderbot.iris.pipeline.HandRenderer}'s {@code canRender}
|
||||
* <p>
|
||||
* Cancel the event to prevent the hand from rendering.
|
||||
*/
|
||||
public record RenderHandEvent() implements RecordEvent, Cancellable {
|
||||
|
||||
public static final CancellableEventBus<RenderHandEvent> BUS = CancellableEventBus.create(RenderHandEvent.class);
|
||||
|
||||
private static final RenderHandEvent INSTANCE = new RenderHandEvent();
|
||||
|
||||
/**
|
||||
* @return true if a listener cancelled the event, meaning the hand should NOT render.
|
||||
*/
|
||||
public static boolean post() {
|
||||
if (!BUS.hasListeners()) return false;
|
||||
return BUS.post(INSTANCE);
|
||||
}
|
||||
}
|
||||
-1
@@ -17,7 +17,6 @@ public class CeleritasBlockTransformer implements IClassTransformer {
|
||||
public CeleritasBlockTransformer() {
|
||||
this.inner = new CeleritasBlockTransform(AngelicaClientTweaker.isObfEnv());
|
||||
this.exclusions = inner.getTransformerExclusions();
|
||||
this.inner.setCeleritasSetting();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+30
-34
@@ -31,16 +31,21 @@ public final class CeleritasBlockTransform implements Opcodes {
|
||||
private static final Logger LOGGER = LogManager.getLogger("CeleritasBlockTransformer");
|
||||
private static final String BlockClass = "net/minecraft/block/Block";
|
||||
private static final String ThreadedBlockData = "com/gtnewhorizons/angelica/client/rendering/ThreadedBlockData";
|
||||
/** All classes under <tt>net.minecraft.block.Block*</tt> are Block subclasses save for these. */
|
||||
private static final String[] VanillaBlockExclusions = {
|
||||
"net/minecraft/block/IGrowable",
|
||||
"net/minecraft/block/ITileEntityProvider",
|
||||
"net/minecraft/block/BlockEventData",
|
||||
"net/minecraft/block/BlockSourceImpl",
|
||||
"net/minecraft/block/material/"
|
||||
};
|
||||
|
||||
private final Map<String, String> fieldNameToRedirect = new HashMap<>();
|
||||
private final Set<String> blockSubclasses = Collections.newSetFromMap(new ConcurrentHashMap<>());
|
||||
private final Set<String> moddedBlockSubclasses = Collections.newSetFromMap(new ConcurrentHashMap<>());
|
||||
// Block subclass owners we shouldn't redirect because they shadow some fields we want to redirect
|
||||
private final Set<String> blockSubclassExclusions = Collections.newSetFromMap(new ConcurrentHashMap<>());
|
||||
private final ClassConstantPoolParser cstPoolParser;
|
||||
|
||||
private final MethodHandle celeritasEnabledGetter;
|
||||
private boolean isCeleritasEnabled;
|
||||
|
||||
public CeleritasBlockTransform(boolean isObf) {
|
||||
final List<Pair<String, String>> mappings = ImmutableList.of(
|
||||
Pair.of("minX", "field_149759_B"),
|
||||
@@ -56,37 +61,30 @@ public final class CeleritasBlockTransform implements Opcodes {
|
||||
}
|
||||
|
||||
this.cstPoolParser = new ClassConstantPoolParser(this.fieldNameToRedirect.keySet().toArray(new String[0]));
|
||||
}
|
||||
|
||||
blockSubclasses.add(BlockClass);
|
||||
|
||||
try {
|
||||
// Needed because the config is loaded in LaunchClassLoader, but we need to access it in the parent system loader.
|
||||
final Class<?> angelicaConfig = Class.forName("com.gtnewhorizons.angelica.config.AngelicaConfig", true, Launch.classLoader);
|
||||
celeritasEnabledGetter = MethodHandles.lookup().findStaticGetter(angelicaConfig, "enableCeleritas", boolean.class);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
private boolean isVanillaBlockSubclass(String className) {
|
||||
if (!className.startsWith(BlockClass)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void setCeleritasSetting() {
|
||||
isCeleritasEnabled = true;
|
||||
}
|
||||
|
||||
private boolean isCeleritasEnabled() {
|
||||
if (isCeleritasEnabled) return true;
|
||||
try {
|
||||
return (boolean) celeritasEnabledGetter.invokeExact();
|
||||
} catch (Throwable e) {
|
||||
throw new RuntimeException(e);
|
||||
for (String exclusion : VanillaBlockExclusions) {
|
||||
if (className.startsWith(exclusion)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// This method needs to be called for every class, including the ones we don't want to transform
|
||||
private boolean isBlockSubclass(String className) {
|
||||
return isVanillaBlockSubclass(className) || moddedBlockSubclasses.contains(className);
|
||||
}
|
||||
|
||||
// This method needs to be called for every class, including the ones we don't want to transform.
|
||||
// Vanilla blocks are recognized by name; only modded subclasses need tracking, and FML's
|
||||
// EventSubscriptionTransformer guarantees a modded class's superclass loads first.
|
||||
public void trackBlockSubclasses(String className, String superClassName) {
|
||||
// It works because the deepest subclasses are always transformed first due to
|
||||
// ForgeEventTransformer recursive superclass loading
|
||||
if (blockSubclasses.contains(superClassName)) {
|
||||
blockSubclasses.add(className);
|
||||
if (!isVanillaBlockSubclass(className) && isBlockSubclass(superClassName)) {
|
||||
moddedBlockSubclasses.add(className);
|
||||
|
||||
if (blockSubclassExclusions.contains(superClassName)) {
|
||||
LOGGER.info("Class {} extends a class with shadowed block bounds fields and will be skipped from redirecting", className);
|
||||
@@ -110,9 +108,6 @@ public final class CeleritasBlockTransform implements Opcodes {
|
||||
|
||||
/** @return Was the class changed? */
|
||||
public boolean transformClassNode(String transformedName, ClassNode cn) {
|
||||
if (!isCeleritasEnabled()) {
|
||||
return false;
|
||||
}
|
||||
boolean changed = false;
|
||||
if (BlockClass.equals(cn.name)) {
|
||||
changed = cn.fields.removeIf(field -> fieldNameToRedirect.containsKey(field.name));
|
||||
@@ -124,7 +119,8 @@ public final class CeleritasBlockTransform implements Opcodes {
|
||||
}
|
||||
|
||||
private void trackBlockShadowingFields(ClassNode cn) {
|
||||
if (blockSubclasses.contains(cn.name)) {
|
||||
// Only modded subclasses can shadow; vanilla declares these fields solely in Block.
|
||||
if (moddedBlockSubclasses.contains(cn.name)) {
|
||||
for (FieldNode field : cn.fields) {
|
||||
if (fieldNameToRedirect.containsKey(field.name)) {
|
||||
LOGGER.info("Class '{}' shadows one or more block bounds fields, these accesses won't be redirected!", cn.name);
|
||||
@@ -141,7 +137,7 @@ public final class CeleritasBlockTransform implements Opcodes {
|
||||
for (AbstractInsnNode node = mn.instructions.getFirst(); node != null; node = node.getNext()) {
|
||||
if ((node.getOpcode() == GETFIELD || node.getOpcode() == PUTFIELD) && node instanceof FieldInsnNode fNode) {
|
||||
String newFieldName = fieldNameToRedirect.get(fNode.name);
|
||||
if (newFieldName != null && blockSubclasses.contains(fNode.owner) && !blockSubclassExclusions.contains(fNode.owner)) {
|
||||
if (newFieldName != null && isBlockSubclass(fNode.owner) && !blockSubclassExclusions.contains(fNode.owner)) {
|
||||
if (LOG_SPAM) {
|
||||
LOGGER.info("Redirecting Block.{} in {} to thread-safe wrapper", fNode.name, transformedName);
|
||||
}
|
||||
|
||||
@@ -329,6 +329,15 @@ public enum Mixins implements IMixins {
|
||||
)
|
||||
),
|
||||
|
||||
IRIS_SHADERS_CHISEL_BEACON(new MixinBuilder("Iris Chisel Beacon Beam")
|
||||
.setPhase(Phase.LATE)
|
||||
.setApplyIf(() -> AngelicaConfig.enableIris)
|
||||
.addRequiredMod(TargetedMod.CHISEL)
|
||||
.addClientMixins(
|
||||
"chisel.MixinRenderCarvableBeacon"
|
||||
)
|
||||
),
|
||||
|
||||
ANGELICA_TEXTURE(new MixinBuilder()
|
||||
.setPhase(Phase.EARLY)
|
||||
.setApplyIf(() -> AngelicaConfig.enableIris || AngelicaConfig.enableCeleritas)
|
||||
|
||||
@@ -10,6 +10,7 @@ public enum TargetedMod implements ITargetMod {
|
||||
ARCHAICFIX("org.embeddedt.archaicfix.ArchaicCore", "archaicfix"),
|
||||
BACKHAND("xonin.backhand.coremod.BackhandLoadingPlugin", "backhand"),
|
||||
CAMPFIRE_BACKPORT(null, "campfirebackport"),
|
||||
CHISEL(null, "chisel"),
|
||||
COFHCORE( "cofh.asm.LoadingPlugin", "CoFHCore"),
|
||||
DYNAMIC_SURROUNDINGS_MIST("org.blockartistry.mod.DynSurround.mixinplugin.DynamicSurroundingsEarlyMixins", "dsurround"),
|
||||
DYNAMIC_SURROUNDINGS_ORIGINAL("org.blockartistry.mod.DynSurround.asm.TransformLoader", "dsurround"),
|
||||
|
||||
@@ -5,6 +5,10 @@ import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.texture.TextureMap;
|
||||
import net.minecraft.client.resources.FallbackResourceManager;
|
||||
import net.minecraft.client.resources.IResourceManager;
|
||||
import net.minecraft.client.resources.IResourcePack;
|
||||
import net.minecraft.client.resources.SimpleReloadableResourceManager;
|
||||
import net.minecraft.util.IIcon;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.client.event.TextureStitchEvent;
|
||||
@@ -50,8 +54,23 @@ public class EmissiveTextureAutoloader {
|
||||
loc.getResourceDomain(),
|
||||
"textures/blocks/" + loc.getResourcePath() + ".png"
|
||||
);
|
||||
|
||||
final IResourceManager resMan = Minecraft.getMinecraft().getResourceManager();
|
||||
if (resMan instanceof SimpleReloadableResourceManager simple) {
|
||||
FallbackResourceManager fallback = simple.domainResourceManagers.get(full.getResourceDomain());
|
||||
if (fallback != null) {
|
||||
for (IResourcePack rp : fallback.resourcePacks) {
|
||||
if (rp != null && rp.resourceExists(full)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback
|
||||
try {
|
||||
Minecraft.getMinecraft().getResourceManager().getResource(full);
|
||||
resMan.getResource(full);
|
||||
return true;
|
||||
} catch (Exception ignored) {
|
||||
return false;
|
||||
|
||||
@@ -1,28 +1,45 @@
|
||||
package com.gtnewhorizons.angelica.render;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vao.IVertexArrayObject;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vao.VertexBufferType;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.DefaultVertexFormat;
|
||||
import com.gtnewhorizons.angelica.config.AngelicaConfig;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.states.Color4;
|
||||
import com.gtnewhorizons.angelica.client.rendering.GlUniformFloat2v;
|
||||
import net.irisshaders.iris.api.v0.IrisApi;
|
||||
import net.minecraft.util.AxisAlignedBB;
|
||||
import org.embeddedt.embeddium.impl.gl.shader.GlProgram;
|
||||
import org.embeddedt.embeddium.impl.gl.shader.GlShader;
|
||||
import org.embeddedt.embeddium.impl.gl.shader.ShaderConstants;
|
||||
import org.embeddedt.embeddium.impl.gl.shader.ShaderType;
|
||||
import org.embeddedt.embeddium.impl.gl.shader.uniform.GlUniformFloat;
|
||||
import org.embeddedt.embeddium.impl.gl.shader.uniform.GlUniformFloat3v;
|
||||
import org.embeddedt.embeddium.impl.gl.shader.uniform.GlUniformFloat4v;
|
||||
import org.embeddedt.embeddium.impl.gl.shader.uniform.GlUniformMatrix4f;
|
||||
import org.embeddedt.embeddium.impl.render.shader.ShaderLoader;
|
||||
import org.joml.Matrix4f;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public final class SelectionBoxRenderer {
|
||||
|
||||
private static GlProgram<SelectionBoxUniforms> program;
|
||||
private static int emptyVao;
|
||||
private static IVertexArrayObject vao;
|
||||
private static final Matrix4f mvpMatrix = new Matrix4f();
|
||||
private static final float[] colorBuf = new float[4];
|
||||
|
||||
private static final int VERT_COUNT = 24;
|
||||
private static final float[] UNIT_EDGES = {
|
||||
0,0,0, 1,0,0, 1,0,0, 1,0,1,
|
||||
1,0,1, 0,0,1, 0,0,1, 0,0,0,
|
||||
0,1,0, 1,1,0, 1,1,0, 1,1,1,
|
||||
1,1,1, 0,1,1, 0,1,1, 0,1,0,
|
||||
0,0,0, 0,1,0, 1,0,0, 1,1,0,
|
||||
1,0,1, 1,1,1, 0,0,1, 0,1,1
|
||||
};
|
||||
|
||||
private SelectionBoxRenderer() {}
|
||||
|
||||
public static void init() {
|
||||
@@ -40,8 +57,6 @@ public final class SelectionBoxRenderer {
|
||||
|
||||
program = builder.link(ctx -> new SelectionBoxUniforms(
|
||||
ctx.bindUniform("u_MVP", GlUniformMatrix4f::new),
|
||||
ctx.bindUniform("u_Min", GlUniformFloat3v::new),
|
||||
ctx.bindUniform("u_Max", GlUniformFloat3v::new),
|
||||
ctx.bindUniform("u_Color", GlUniformFloat4v::new),
|
||||
needsGS ? ctx.bindUniform("u_ViewportSize", GlUniformFloat2v::new) : null,
|
||||
needsGS ? ctx.bindUniform("u_LineWidth", GlUniformFloat::new) : null));
|
||||
@@ -50,20 +65,34 @@ public final class SelectionBoxRenderer {
|
||||
fs.destroy();
|
||||
if (gs != null) gs.destroy();
|
||||
|
||||
emptyVao = GLStateManager.glGenVertexArrays();
|
||||
final ByteBuffer buf = BufferUtils.createByteBuffer(UNIT_EDGES.length * Float.BYTES);
|
||||
buf.asFloatBuffer().put(UNIT_EDGES);
|
||||
vao = VertexBufferType.IMMUTABLE.allocate(DefaultVertexFormat.POSITION, GL11.GL_LINES, buf, VERT_COUNT);
|
||||
}
|
||||
|
||||
public static void draw(AxisAlignedBB aabb, int color) {
|
||||
if (program == null) return;
|
||||
if (program == null || vao == null) return;
|
||||
|
||||
final float minX = (float) aabb.minX, minY = (float) aabb.minY, minZ = (float) aabb.minZ;
|
||||
final float extX = (float) (aabb.maxX - aabb.minX);
|
||||
final float extY = (float) (aabb.maxY - aabb.minY);
|
||||
final float extZ = (float) (aabb.maxZ - aabb.minZ);
|
||||
|
||||
if (AngelicaConfig.enableIris && IrisApi.getInstance().isShaderPackInUse()) {
|
||||
drawThroughShader(minX, minY, minZ, extX, extY, extZ, color);
|
||||
} else {
|
||||
drawFast(minX, minY, minZ, extX, extY, extZ, color);
|
||||
}
|
||||
}
|
||||
|
||||
private static void drawFast(float minX, float minY, float minZ, float extX, float extY, float extZ, int color) {
|
||||
final SelectionBoxUniforms uniforms = program.getInterface();
|
||||
|
||||
program.bind();
|
||||
|
||||
GLStateManager.getProjectionMatrix().mul(GLStateManager.getModelViewMatrix(), mvpMatrix);
|
||||
mvpMatrix.translate(minX, minY, minZ).scale(extX, extY, extZ);
|
||||
uniforms.mvp.set(mvpMatrix);
|
||||
uniforms.min.set((float) aabb.minX, (float) aabb.minY, (float) aabb.minZ);
|
||||
uniforms.max.set((float) aabb.maxX, (float) aabb.maxY, (float) aabb.maxZ);
|
||||
|
||||
if (color != -1) {
|
||||
colorBuf[0] = ((color >> 16) & 0xFF) / 255.0f;
|
||||
@@ -84,25 +113,42 @@ public final class SelectionBoxRenderer {
|
||||
uniforms.lineWidth.setFloat(GLStateManager.getLineState().getWidth());
|
||||
}
|
||||
|
||||
GLStateManager.glBindVertexArray(emptyVao);
|
||||
GLStateManager.glDrawArrays(GL11.GL_LINES, 0, 24);
|
||||
GLStateManager.glBindVertexArray(0);
|
||||
vao.render();
|
||||
|
||||
program.unbind();
|
||||
}
|
||||
|
||||
private static void drawThroughShader(float minX, float minY, float minZ, float extX, float extY, float extZ, int color) {
|
||||
GLStateManager.glPushMatrix();
|
||||
GLStateManager.glTranslatef(minX, minY, minZ);
|
||||
GLStateManager.glScalef(extX, extY, extZ);
|
||||
|
||||
final Color4 prev = GLStateManager.getColor();
|
||||
final boolean overrideColor = color != -1;
|
||||
if (overrideColor) {
|
||||
GLStateManager.glColor4f(((color >> 16) & 0xFF) / 255.0f, ((color >> 8) & 0xFF) / 255.0f, (color & 0xFF) / 255.0f, 1.0f);
|
||||
}
|
||||
|
||||
vao.render();
|
||||
|
||||
if (overrideColor) {
|
||||
GLStateManager.glColor4f(prev.getRed(), prev.getGreen(), prev.getBlue(), prev.getAlpha());
|
||||
}
|
||||
GLStateManager.glPopMatrix();
|
||||
}
|
||||
|
||||
public static void destroy() {
|
||||
if (program != null) {
|
||||
program.destroy();
|
||||
program = null;
|
||||
}
|
||||
if (emptyVao != 0) {
|
||||
GLStateManager.glDeleteVertexArrays(emptyVao);
|
||||
emptyVao = 0;
|
||||
if (vao != null) {
|
||||
vao.delete();
|
||||
vao = null;
|
||||
}
|
||||
}
|
||||
|
||||
private record SelectionBoxUniforms(GlUniformMatrix4f mvp, GlUniformFloat3v min, GlUniformFloat3v max, GlUniformFloat4v color, GlUniformFloat2v viewportSize, GlUniformFloat lineWidth) {
|
||||
private record SelectionBoxUniforms(GlUniformMatrix4f mvp, GlUniformFloat4v color, GlUniformFloat2v viewportSize, GlUniformFloat lineWidth) {
|
||||
|
||||
}
|
||||
}
|
||||
+3
@@ -15,6 +15,7 @@ import net.coderbot.iris.block_rendering.BlockRenderingSettings;
|
||||
import net.coderbot.iris.block_rendering.NbtConditionalIdMap;
|
||||
import net.coderbot.iris.vertices.ExtendedDataHelper;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockDoublePlant;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.RenderBlocks;
|
||||
@@ -275,6 +276,8 @@ public abstract class AngelicaChunkBuilderMeshingTask extends ChunkBuilderTask<C
|
||||
&& BlockRenderingSettings.INSTANCE.getSnowyBlocks().contains(block)
|
||||
&& RenderBlocksUtils.isSnowCovered(renderBlocks.blockAccess, x, y, z)) {
|
||||
effectiveMeta |= BlockMaterialMapping.SNOWY_META_BIT;
|
||||
} else if (block instanceof BlockDoublePlant doublePlant && BlockDoublePlant.func_149887_c(metadata)) {
|
||||
effectiveMeta = 0x8 | (doublePlant.func_149885_e(renderBlocks.blockAccess, x, y, z) & 7);
|
||||
}
|
||||
contextEncoder.prepareToRenderBlock(blockRenderContext, block, effectiveMeta,
|
||||
ExtendedDataHelper.BLOCK_RENDER_TYPE, lightValue);
|
||||
|
||||
@@ -20,11 +20,7 @@ final class BlockOrientation extends RenderBlockState {
|
||||
// 1 2 3
|
||||
// c: coordinate (x,y,z) 0-2
|
||||
private static final int[][][] NEIGHBOR_OFFSET = new int[][][] {
|
||||
(
|
||||
fixedBottomFaceUV
|
||||
? makeNeighborOffset(EAST_FACE, SOUTH_FACE, WEST_FACE, NORTH_FACE) // BOTTOM_FACE fixedBottomFaceUV
|
||||
: makeNeighborOffset(WEST_FACE, SOUTH_FACE, EAST_FACE, NORTH_FACE) // BOTTOM_FACE not fixed
|
||||
),
|
||||
makeNeighborOffset(EAST_FACE, SOUTH_FACE, WEST_FACE, NORTH_FACE), // BOTTOM_FACE
|
||||
makeNeighborOffset(WEST_FACE, SOUTH_FACE, EAST_FACE, NORTH_FACE), // TOP_FACE
|
||||
makeNeighborOffset(EAST_FACE, BOTTOM_FACE, WEST_FACE, TOP_FACE), // NORTH_FACE
|
||||
makeNeighborOffset(WEST_FACE, BOTTOM_FACE, EAST_FACE, TOP_FACE), // SOUTH_FACE
|
||||
@@ -48,6 +44,7 @@ final class BlockOrientation extends RenderBlockState {
|
||||
private int textureFace;
|
||||
private int textureFaceOrig;
|
||||
private int rotateUV;
|
||||
private boolean flipBottom;
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
@@ -60,6 +57,7 @@ final class BlockOrientation extends RenderBlockState {
|
||||
offsetsComputed = false;
|
||||
haveOffsets = false;
|
||||
dx = dy = dz = 0;
|
||||
flipBottom = !fixedBottomFaceUV;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -104,7 +102,7 @@ final class BlockOrientation extends RenderBlockState {
|
||||
|
||||
@Override
|
||||
public int[] getOffset(int blockFace, int relativeDirection) {
|
||||
return NEIGHBOR_OFFSET[blockFace][rotateUV(relativeDirection)];
|
||||
return NEIGHBOR_OFFSET[flipBottom && blockFace == 0 ? 1 : blockFace][rotateUV(relativeDirection)];
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -147,6 +145,11 @@ final class BlockOrientation extends RenderBlockState {
|
||||
return haveOffsets;
|
||||
}
|
||||
|
||||
|
||||
public void setFlipBottom(){
|
||||
flipBottom = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldConnectByBlock(Block neighbor, int neighborX, int neighborY, int neighborZ) {
|
||||
return block == neighbor
|
||||
@@ -172,6 +175,7 @@ final class BlockOrientation extends RenderBlockState {
|
||||
copy.textureFace = textureFace;
|
||||
copy.textureFaceOrig = textureFaceOrig;
|
||||
copy.rotateUV = rotateUV;
|
||||
copy.flipBottom = flipBottom;
|
||||
|
||||
copy.blockAccess = blockAccess;
|
||||
copy.block = block;
|
||||
@@ -204,6 +208,7 @@ final class BlockOrientation extends RenderBlockState {
|
||||
rotateUV = 0;
|
||||
textureFace = blockFaceToTextureFace(blockFace);
|
||||
metadataBits = (1 << metadata) | (1 << altMetadata);
|
||||
flipBottom = !fixedBottomFaceUV;
|
||||
}
|
||||
|
||||
void setBlockMetadata(Block block, int metadata, int face) {
|
||||
|
||||
@@ -53,6 +53,9 @@ public final class CompactCtmQuadProcessor {
|
||||
}
|
||||
|
||||
public boolean processFace(RenderBlocks rb, RenderBlockState renderBlockState, IIcon origIcon) {
|
||||
if(renderBlockState instanceof BlockOrientation blockOrientation){
|
||||
blockOrientation.setFlipBottom();
|
||||
}
|
||||
int neighborBits = override.getNeighborBits(renderBlockState, origIcon);
|
||||
|
||||
int ctmIndex = TileOverride.neighborMap[neighborBits & 0xFF];
|
||||
|
||||
@@ -14,6 +14,7 @@ import net.coderbot.iris.shaderpack.materialmap.BlockRenderType;
|
||||
import net.coderbot.iris.shaderpack.materialmap.FlatteningMap;
|
||||
import net.coderbot.iris.shaderpack.materialmap.NamespacedId;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockDoublePlant;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
@@ -25,9 +26,11 @@ public class BlockMaterialMapping {
|
||||
|
||||
public record BlockIdMaps(Reference2ObjectMap<Block, Int2IntMap> blockMetaMap, NbtConditionalIdMap<Block> tileEntityMap) {}
|
||||
|
||||
/** Meta-key bit OR'd in at runtime when a snowy-tagged block has snow above it. */
|
||||
// Meta-key bits OR'd in at runtime
|
||||
public static final int SNOWY_META_BIT = 0x10;
|
||||
|
||||
public static final int DOUBLE_PLANT_TOP_BIT = 0x8;
|
||||
|
||||
/**
|
||||
* Creates the standard block meta ID map, the TileEntity NBT-conditional map, and registers
|
||||
* snowy blocks on {@link BlockRenderingSettings}.
|
||||
@@ -129,6 +132,7 @@ public class BlockMaterialMapping {
|
||||
final Map<String, String> stateProps = entry.stateProperties();
|
||||
final String snowy = stateProps.get("snowy");
|
||||
final int snowyBit = "true".equals(snowy) ? SNOWY_META_BIT : 0;
|
||||
final boolean wantsDoublePlantTop = "upper".equals(stateProps.get("half"));
|
||||
|
||||
// Vanilla modern names go through FlatteningMap; legacy-section packs and modded blocks
|
||||
// resolve directly from the registry.
|
||||
@@ -145,12 +149,16 @@ public class BlockMaterialMapping {
|
||||
}
|
||||
final Block block = resolveBlockOrNull(target.id());
|
||||
if (block == null) continue;
|
||||
applyMetas(block, target.metas(), idMap, intId, snowyBit);
|
||||
int extraBits = snowyBit;
|
||||
if (wantsDoublePlantTop && block instanceof BlockDoublePlant) {
|
||||
extraBits |= DOUBLE_PLANT_TOP_BIT;
|
||||
}
|
||||
applyMetas(block, target.metas(), idMap, intId, extraBits);
|
||||
if (snowy != null) snowyBlocks.add(block);
|
||||
}
|
||||
}
|
||||
|
||||
private static void applyMetas(Block block, Set<Integer> metas, Reference2ObjectMap<Block, Int2IntMap> idMap, int intId, int snowyBit) {
|
||||
private static void applyMetas(Block block, Set<Integer> metas, Reference2ObjectMap<Block, Int2IntMap> idMap, int intId, int extraBits) {
|
||||
Int2IntMap metaMap = idMap.get(block);
|
||||
if (metaMap == null) {
|
||||
metaMap = new Int2IntOpenHashMap();
|
||||
@@ -159,9 +167,9 @@ public class BlockMaterialMapping {
|
||||
}
|
||||
|
||||
if (metas.isEmpty()) {
|
||||
for (int meta = 0; meta < 16; meta++) metaMap.putIfAbsent(meta | snowyBit, intId);
|
||||
for (int meta = 0; meta < 16; meta++) metaMap.putIfAbsent(meta | extraBits, intId);
|
||||
} else {
|
||||
for (int meta : metas) metaMap.putIfAbsent(meta | snowyBit, intId);
|
||||
for (int meta : metas) metaMap.putIfAbsent(meta | extraBits, intId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package net.coderbot.iris.pipeline;
|
||||
import com.gtnewhorizons.angelica.compat.mojang.Camera;
|
||||
import com.gtnewhorizons.angelica.compat.mojang.GameModeUtil;
|
||||
import com.gtnewhorizons.angelica.compat.mojang.InteractionHand;
|
||||
import com.gtnewhorizons.angelica.event.RenderHandEvent;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.rendering.RenderingState;
|
||||
import com.gtnewhorizons.angelica.rendering.celeritas.BlockRenderLayer;
|
||||
@@ -78,7 +79,8 @@ public class HandRenderer {
|
||||
!camera.isSleeping() &&
|
||||
!mc.gameSettings.hideGUI &&
|
||||
!GameModeUtil.isSpectator() &&
|
||||
!mc.playerController.enableEverythingIsScrewedUpMode();
|
||||
!mc.playerController.enableEverythingIsScrewedUpMode() &&
|
||||
!RenderHandEvent.post();
|
||||
}
|
||||
|
||||
public boolean isHandTranslucent(InteractionHand hand) {
|
||||
|
||||
@@ -373,13 +373,14 @@ public class FlatteningMap {
|
||||
colorVariants("carpet", "carpet");
|
||||
|
||||
// === Double plant (ID 175) ===
|
||||
// Bottom half has type in meta 0-5; top half is always meta 8 (shared by all types).
|
||||
meta("sunflower", "double_plant", 0);
|
||||
meta("lilac", "double_plant", 1);
|
||||
meta("tall_grass", "double_plant", 2);
|
||||
meta("large_fern", "double_plant", 3);
|
||||
meta("rose_bush", "double_plant", 4);
|
||||
meta("peony", "double_plant", 5);
|
||||
// Bottom half carries the variant in meta 0-5; the top half's real meta is 8-11.
|
||||
// We use a synthetic key to tie the variant the bottom is with the top half.
|
||||
doublePlant("sunflower", 0);
|
||||
doublePlant("lilac", 1);
|
||||
doublePlant("tall_grass", 2);
|
||||
doublePlant("large_fern", 3);
|
||||
doublePlant("rose_bush", 4);
|
||||
doublePlant("peony", 5);
|
||||
|
||||
// === Water / Lava (IDs 8-11) ===
|
||||
// In 1.13+, water/lava are single blocks. In 1.7.10, flowing variants are separate.
|
||||
@@ -861,21 +862,6 @@ public class FlatteningMap {
|
||||
state(WOOD_TYPES[i] + "_sapling", "stage", "0", entryMetas("sapling", i));
|
||||
state(WOOD_TYPES[i] + "_sapling", "stage", "1", entryMetas("sapling", i + 8));
|
||||
}
|
||||
|
||||
// === Double plant half (ID 175) ===
|
||||
// 1.7.10: bottom half has type in meta 0-5; top half is always meta 8
|
||||
state("sunflower", "half", "lower", entryMetas("double_plant", 0));
|
||||
state("sunflower", "half", "upper", entryMetas("double_plant", 8));
|
||||
state("lilac", "half", "lower", entryMetas("double_plant", 1));
|
||||
state("lilac", "half", "upper", entryMetas("double_plant", 8));
|
||||
state("tall_grass", "half", "lower", entryMetas("double_plant", 2));
|
||||
state("tall_grass", "half", "upper", entryMetas("double_plant", 8));
|
||||
state("large_fern", "half", "lower", entryMetas("double_plant", 3));
|
||||
state("large_fern", "half", "upper", entryMetas("double_plant", 8));
|
||||
state("rose_bush", "half", "lower", entryMetas("double_plant", 4));
|
||||
state("rose_bush", "half", "upper", entryMetas("double_plant", 8));
|
||||
state("peony", "half", "lower", entryMetas("double_plant", 5));
|
||||
state("peony", "half", "upper", entryMetas("double_plant", 8));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1053,6 +1039,17 @@ public class FlatteningMap {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Double plant: the bottom half stores the variant in meta 0-5; the top half stores facing
|
||||
* direction, so Angelica's chunk mesher rebuilds a synthetic key 0x8|variant for top halves.
|
||||
*/
|
||||
private static void doublePlant(String modern, int variant) {
|
||||
final int upper = 0x8 | variant;
|
||||
metas(modern, "double_plant", variant, upper);
|
||||
state(modern, "half", "lower", entryMetas("double_plant", variant));
|
||||
state(modern, "half", "upper", entryMetas("double_plant", upper));
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// Blockstate property mapping helpers
|
||||
// ==========================================
|
||||
|
||||
@@ -1,19 +1,9 @@
|
||||
#version 330 core
|
||||
|
||||
uniform mat4 u_MVP;
|
||||
uniform vec3 u_Min;
|
||||
uniform vec3 u_Max;
|
||||
layout(location = 0) in vec3 a_Position;
|
||||
|
||||
const vec3 edges[24] = vec3[24](
|
||||
vec3(0,0,0), vec3(1,0,0), vec3(1,0,0), vec3(1,0,1),
|
||||
vec3(1,0,1), vec3(0,0,1), vec3(0,0,1), vec3(0,0,0),
|
||||
vec3(0,1,0), vec3(1,1,0), vec3(1,1,0), vec3(1,1,1),
|
||||
vec3(1,1,1), vec3(0,1,1), vec3(0,1,1), vec3(0,1,0),
|
||||
vec3(0,0,0), vec3(0,1,0), vec3(1,0,0), vec3(1,1,0),
|
||||
vec3(1,0,1), vec3(1,1,1), vec3(0,0,1), vec3(0,1,1)
|
||||
);
|
||||
uniform mat4 u_MVP;
|
||||
|
||||
void main() {
|
||||
vec3 pos = mix(u_Min, u_Max, edges[gl_VertexID]);
|
||||
gl_Position = u_MVP * vec4(pos, 1.0);
|
||||
gl_Position = u_MVP * vec4(a_Position, 1.0);
|
||||
}
|
||||
+31
-7
@@ -9,9 +9,12 @@ import net.irisshaders.iris.api.v0.IrisApi;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.ItemRenderer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
/**
|
||||
@@ -19,6 +22,9 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
*/
|
||||
@Mixin(ItemRenderer.class)
|
||||
public class MixinItemRenderer {
|
||||
|
||||
@Shadow private ItemStack itemToRender;
|
||||
|
||||
/**
|
||||
* Render held item in first person.
|
||||
*/
|
||||
@@ -34,15 +40,33 @@ public class MixinItemRenderer {
|
||||
}
|
||||
}
|
||||
|
||||
Minecraft mc = Minecraft.getMinecraft();
|
||||
if (mc.thePlayer == null) {
|
||||
return;
|
||||
// Wait for hand to lower before setting ID
|
||||
ItemIdManager.setItemId(this.itemToRender);
|
||||
}
|
||||
|
||||
/**
|
||||
* Force the equip lower/raise animation whenever the held stack isn't an exact match for
|
||||
* the one being rendered.
|
||||
*/
|
||||
@Redirect(
|
||||
method = "updateEquippedItem",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;getItemDamage()I", ordinal = 0)
|
||||
)
|
||||
private int iris$animateStackSwap(ItemStack incoming) {
|
||||
if (this.itemToRender != null
|
||||
&& !ItemStack.areItemStacksEqual(incoming, this.itemToRender)) {
|
||||
return Integer.MIN_VALUE;
|
||||
}
|
||||
return incoming.getItemDamage();
|
||||
}
|
||||
|
||||
ItemStack itemStack = mc.thePlayer.getCurrentEquippedItem();
|
||||
|
||||
// Set item ID for first-person hand/item
|
||||
ItemIdManager.setItemId(itemStack);
|
||||
@Redirect(
|
||||
method = "updateEquippedItem",
|
||||
at = @At(value = "FIELD", target = "Lnet/minecraft/client/renderer/ItemRenderer;itemToRender:Lnet/minecraft/item/ItemStack;", opcode = Opcodes.PUTFIELD, ordinal = 0)
|
||||
)
|
||||
private void iris$commitSlotOnInstantSwap(ItemRenderer self, ItemStack value) {
|
||||
this.itemToRender = value;
|
||||
int equippedItemSlot = Minecraft.getMinecraft().thePlayer.inventory.currentItem;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+28
@@ -2,11 +2,14 @@ package com.gtnewhorizons.angelica.mixins.early.shaders;
|
||||
|
||||
import net.coderbot.iris.gbuffer_overrides.matching.SpecialCondition;
|
||||
import net.coderbot.iris.layer.GbufferPrograms;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.renderer.tileentity.TileEntityBeaconRenderer;
|
||||
import net.minecraft.tileentity.TileEntityBeacon;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(TileEntityBeaconRenderer.class)
|
||||
@@ -22,5 +25,30 @@ public class MixinTileEntityBeaconRenderer {
|
||||
GbufferPrograms.teardownSpecialRenderCondition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Whoever wrote this part of vanilla code sucks. Just change the alpha my guy.
|
||||
*/
|
||||
@Redirect(
|
||||
method = "Lnet/minecraft/client/renderer/tileentity/TileEntityBeaconRenderer;renderTileEntityAt(Lnet/minecraft/tileentity/TileEntityBeacon;DDDF)V",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/Tessellator;setColorRGBA(IIII)V", ordinal = 0))
|
||||
private void angelica$innerBeamColor(Tessellator tessellator, int r, int g, int b, int a) {
|
||||
angelica$beamColor(tessellator, r, g, b, 255);
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "Lnet/minecraft/client/renderer/tileentity/TileEntityBeaconRenderer;renderTileEntityAt(Lnet/minecraft/tileentity/TileEntityBeacon;DDDF)V",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/Tessellator;setColorRGBA(IIII)V", ordinal = 1))
|
||||
private void angelica$outerBeamColor(Tessellator tessellator, int r, int g, int b, int a) {
|
||||
angelica$beamColor(tessellator, r, g, b, a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make beam fullbright.
|
||||
*/
|
||||
@Unique
|
||||
private void angelica$beamColor(Tessellator tessellator, int r, int g, int b, int a) {
|
||||
tessellator.setColorRGBA(r, g, b, a);
|
||||
tessellator.setBrightness(0x00F000F0);
|
||||
}
|
||||
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
package com.gtnewhorizons.angelica.mixins.late.chisel;
|
||||
|
||||
import net.coderbot.iris.gbuffer_overrides.matching.SpecialCondition;
|
||||
import net.coderbot.iris.layer.GbufferPrograms;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.world.World;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Pseudo;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
/**
|
||||
* Chisel ships its own beacon beam renderer, we yoink a lot of the code from
|
||||
* {@link com.gtnewhorizons.angelica.mixins.early.shaders.MixinTileEntityBeaconRenderer} to apply the same fixes here.
|
||||
*/
|
||||
@Pseudo
|
||||
@Mixin(targets = { "team.chisel.client.render.tile.RenderCarvableBeacon" }, remap = false)
|
||||
public class MixinRenderCarvableBeacon {
|
||||
|
||||
@Inject(method = "renderBeam(FLnet/minecraft/world/World;DDDIF)V", at = @At("HEAD"))
|
||||
private void angelica$beginBeaconBeam(float f1, World world, double x, double y, double z, int meta, float partialTicks, CallbackInfo ci) {
|
||||
GbufferPrograms.setupSpecialRenderCondition(SpecialCondition.BEACON_BEAM);
|
||||
}
|
||||
|
||||
@Inject(method = "renderBeam(FLnet/minecraft/world/World;DDDIF)V", at = @At("RETURN"))
|
||||
private void angelica$endBeaconBeam(float f1, World world, double x, double y, double z, int meta, float partialTicks, CallbackInfo ci) {
|
||||
GbufferPrograms.teardownSpecialRenderCondition();
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "renderBeam(FLnet/minecraft/world/World;DDDIF)V",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/Tessellator;setColorRGBA(IIII)V", ordinal = 0, remap = true))
|
||||
private void angelica$innerBeamColor(Tessellator tessellator, int r, int g, int b, int a) {
|
||||
angelica$beamColor(tessellator, r, g, b, 255);
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "renderBeam(FLnet/minecraft/world/World;DDDIF)V",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/Tessellator;setColorRGBA(IIII)V", ordinal = 1, remap = true))
|
||||
private void angelica$outerBeamColor(Tessellator tessellator, int r, int g, int b, int a) {
|
||||
angelica$beamColor(tessellator, r, g, b, a);
|
||||
}
|
||||
|
||||
@Unique
|
||||
private void angelica$beamColor(Tessellator tessellator, int r, int g, int b, int a) {
|
||||
tessellator.setColorRGBA(r, g, b, a);
|
||||
tessellator.setBrightness(0x00F000F0);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user