mirror of
https://github.com/GTNewHorizons/Angelica.git
synced 2026-11-15 09:44:52 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b5dd1c04ce | ||
|
|
6c5eedb7c1 | ||
|
|
9d5eb01091 | ||
|
|
0d54a65026 | ||
|
|
8148d8f927 | ||
|
|
5c441e4418 | ||
|
|
78562f12d9 | ||
|
|
031456f224 | ||
|
|
ff35c684ca | ||
|
|
5c4ef022d5 | ||
|
|
4eb837a2c0 |
No files matched your search
@@ -1051,6 +1051,7 @@ public class GLStateManager {
|
||||
case GL11.GL_SHADE_MODEL -> shadeModelState.getValue();
|
||||
// GL_TEXTURE_2D makes no sense here, but some mod still queries it...
|
||||
case GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_BINDING_2D -> getBoundTextureForServerState();
|
||||
case GL13.GL_ACTIVE_TEXTURE -> GL13.GL_TEXTURE0 + getActiveTextureUnitForServerState();
|
||||
case GL11.GL_COLOR_MATERIAL_FACE -> colorMaterialFace.getValue();
|
||||
case GL11.GL_COLOR_MATERIAL_PARAMETER -> colorMaterialParameter.getValue();
|
||||
case GL11.GL_MODELVIEW_STACK_DEPTH -> getMatrixStackDepth(modelViewMatrix);
|
||||
@@ -1059,15 +1060,18 @@ public class GLStateManager {
|
||||
case GL12.GL_LIGHT_MODEL_COLOR_CONTROL -> lightModel.colorControl;
|
||||
|
||||
case GL14.GL_BLEND_DST_ALPHA -> blendState.getDstAlpha();
|
||||
case GL14.GL_BLEND_DST_RGB -> blendState.getDstRgb();
|
||||
case GL11.GL_BLEND_DST, GL14.GL_BLEND_DST_RGB -> blendState.getDstRgb();
|
||||
case GL14.GL_BLEND_SRC_ALPHA -> blendState.getSrcAlpha();
|
||||
case GL14.GL_BLEND_SRC_RGB -> blendState.getSrcRgb();
|
||||
case GL11.GL_BLEND_SRC, GL14.GL_BLEND_SRC_RGB -> blendState.getSrcRgb();
|
||||
case GL14.GL_BLEND_EQUATION -> blendState.getEquationRgb();
|
||||
case GL20.GL_BLEND_EQUATION_ALPHA -> blendState.getEquationAlpha();
|
||||
|
||||
case GL11.GL_LOGIC_OP_MODE -> logicOpMode.getValue();
|
||||
case GL11.GL_DRAW_BUFFER -> drawBuffer.getValue();
|
||||
|
||||
case GL11.GL_CULL_FACE_MODE -> polygonState.getCullFaceMode();
|
||||
case GL11.GL_FRONT_FACE -> polygonState.getFrontFace();
|
||||
|
||||
case GL11.GL_STENCIL_FUNC -> stencilState.getFuncFront();
|
||||
case GL11.GL_STENCIL_REF -> stencilState.getRefFront();
|
||||
case GL11.GL_STENCIL_VALUE_MASK -> stencilState.getValueMaskFront();
|
||||
@@ -1106,6 +1110,10 @@ public class GLStateManager {
|
||||
|
||||
switch (pname) {
|
||||
case GL11.GL_VIEWPORT -> viewportState.get(params);
|
||||
case GL11.GL_POLYGON_MODE -> {
|
||||
params.put(0, polygonState.getFrontMode());
|
||||
params.put(1, polygonState.getBackMode());
|
||||
}
|
||||
default -> {
|
||||
if (!HAS_MULTIPLE_SET.contains(pname)) {
|
||||
params.put(0, glGetInteger(pname));
|
||||
@@ -5214,30 +5222,36 @@ public class GLStateManager {
|
||||
|
||||
private static void invalidateDeletedBuffer(int buffer) {
|
||||
if (buffer == 0) return;
|
||||
if (boundVBO == buffer) glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
if (VAOManager.boundEBO == buffer) glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
if (boundPixelUnpackBuffer == buffer) glBindBuffer(GL21.GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
if (boundPixelPackBuffer == buffer) glBindBuffer(GL21.GL_PIXEL_PACK_BUFFER, 0);
|
||||
final boolean locked = acquireDrawLock();
|
||||
try {
|
||||
if (boundVBO == buffer) glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
if (VAOManager.boundEBO == buffer) glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
if (boundPixelUnpackBuffer == buffer) glBindBuffer(GL21.GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
if (boundPixelPackBuffer == buffer) glBindBuffer(GL21.GL_PIXEL_PACK_BUFFER, 0);
|
||||
|
||||
// Sweep all VAOs: an unbound VAO may later rebind with a dangling EBO id.
|
||||
for (VAOManager.VAOData data : VAOManager.vaoMap.values()) {
|
||||
if (data.ebo == buffer) data.ebo = 0;
|
||||
VAOManager.onDeleteBuffer(buffer);
|
||||
} finally {
|
||||
if (locked) releaseDrawLock();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void glBindBuffer(int target, int buffer) {
|
||||
if (target == GL15.GL_ARRAY_BUFFER) {
|
||||
// if (boundVBO == buffer) return; TODO figure out why this breaks switching async occlusion mode
|
||||
boundVBO = buffer;
|
||||
} else if (target == GL15.GL_ELEMENT_ARRAY_BUFFER) {
|
||||
VAOManager.onBindEBO(buffer);
|
||||
} else if (target == GL21.GL_PIXEL_UNPACK_BUFFER) {
|
||||
boundPixelUnpackBuffer = buffer;
|
||||
} else if (target == GL21.GL_PIXEL_PACK_BUFFER) {
|
||||
boundPixelPackBuffer = buffer;
|
||||
final boolean locked = acquireDrawLock();
|
||||
try {
|
||||
if (target == GL15.GL_ARRAY_BUFFER) {
|
||||
// if (boundVBO == buffer) return; TODO figure out why this breaks switching async occlusion mode
|
||||
boundVBO = buffer;
|
||||
} else if (target == GL15.GL_ELEMENT_ARRAY_BUFFER) {
|
||||
VAOManager.onBindEBO(buffer);
|
||||
} else if (target == GL21.GL_PIXEL_UNPACK_BUFFER) {
|
||||
boundPixelUnpackBuffer = buffer;
|
||||
} else if (target == GL21.GL_PIXEL_PACK_BUFFER) {
|
||||
boundPixelPackBuffer = buffer;
|
||||
}
|
||||
RENDER_BACKEND.bindBuffer(target, buffer);
|
||||
} finally {
|
||||
if (locked) releaseDrawLock();
|
||||
}
|
||||
RENDER_BACKEND.bindBuffer(target, buffer);
|
||||
}
|
||||
|
||||
public static void forcePixelUnpackState(PixelUnpackState target) {
|
||||
@@ -5572,22 +5586,32 @@ public class GLStateManager {
|
||||
if (array == 0) {
|
||||
array = defaultVAO;
|
||||
}
|
||||
if (boundVAO != array) {
|
||||
boundVAO = array;
|
||||
VAOManager.onBindVertexArrayPre(array);
|
||||
RENDER_BACKEND.bindVertexArray(array);
|
||||
final boolean locked = acquireDrawLock();
|
||||
try {
|
||||
if (boundVAO != array) {
|
||||
boundVAO = array;
|
||||
VAOManager.onBindVertexArrayPre(array);
|
||||
RENDER_BACKEND.bindVertexArray(array);
|
||||
}
|
||||
} finally {
|
||||
if (locked) releaseDrawLock();
|
||||
}
|
||||
}
|
||||
|
||||
public static void glDeleteVertexArrays(int array) {
|
||||
VAOManager.onDeleteVertexArray(array);
|
||||
if (array == boundVAO) {
|
||||
// Deleting the bound VAO implicitly unbinds it. Rebind the default VAO.
|
||||
boundVAO = defaultVAO;
|
||||
VAOManager.onBindVertexArrayPre(defaultVAO);
|
||||
RENDER_BACKEND.bindVertexArray(defaultVAO);
|
||||
final boolean locked = acquireDrawLock();
|
||||
try {
|
||||
VAOManager.onDeleteVertexArray(array);
|
||||
if (array == boundVAO) {
|
||||
// Deleting the bound VAO implicitly unbinds it. Rebind the default VAO.
|
||||
boundVAO = defaultVAO;
|
||||
VAOManager.onBindVertexArrayPre(defaultVAO);
|
||||
RENDER_BACKEND.bindVertexArray(defaultVAO);
|
||||
}
|
||||
RENDER_BACKEND.deleteVertexArrays(array);
|
||||
} finally {
|
||||
if (locked) releaseDrawLock();
|
||||
}
|
||||
RENDER_BACKEND.deleteVertexArrays(array);
|
||||
}
|
||||
|
||||
public static int glGenVertexArrays() {
|
||||
|
||||
@@ -15,6 +15,8 @@ public final class VAOManager {
|
||||
|
||||
public static final Int2ObjectOpenHashMap<VAOData> vaoMap = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
static final Int2ObjectOpenHashMap<VAOData> eboOwners = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
private static VAOData current = null;
|
||||
private static int currentVertexFlags = 0;
|
||||
private static Attrib[] currentAttribs = null;
|
||||
@@ -38,7 +40,11 @@ public final class VAOManager {
|
||||
// Save old VAO data
|
||||
if (current != null) {
|
||||
current.vertexFlags = currentVertexFlags;
|
||||
current.ebo = boundEBO;
|
||||
if (current.ebo != boundEBO) {
|
||||
removeEboOwner(current.ebo, current);
|
||||
current.ebo = boundEBO;
|
||||
addEboOwner(current.ebo, current);
|
||||
}
|
||||
current.attribs = currentAttribs;
|
||||
current.clientSideEnabledCount = clientSideEnabledCount;
|
||||
}
|
||||
@@ -56,7 +62,46 @@ public final class VAOManager {
|
||||
}
|
||||
|
||||
public static void onDeleteVertexArray(int vaoId) {
|
||||
vaoMap.remove(vaoId);
|
||||
final VAOData data = vaoMap.remove(vaoId);
|
||||
if (data == null) return;
|
||||
removeEboOwner(data.ebo, data);
|
||||
if (data == current) current = null;
|
||||
}
|
||||
|
||||
public static void onDeleteBuffer(int buffer) {
|
||||
if (buffer == 0) return;
|
||||
VAOData owner = eboOwners.remove(buffer);
|
||||
while (owner != null) {
|
||||
final VAOData next = owner.nextEboOwner;
|
||||
owner.nextEboOwner = null;
|
||||
owner.ebo = 0;
|
||||
owner = next;
|
||||
}
|
||||
}
|
||||
|
||||
private static void addEboOwner(int ebo, VAOData data) {
|
||||
if (ebo == 0) return;
|
||||
data.nextEboOwner = eboOwners.put(ebo, data);
|
||||
}
|
||||
|
||||
private static void removeEboOwner(int ebo, VAOData data) {
|
||||
if (ebo == 0) return;
|
||||
VAOData node = eboOwners.get(ebo);
|
||||
if (node == data) {
|
||||
final VAOData next = data.nextEboOwner;
|
||||
if (next == null) eboOwners.remove(ebo); else eboOwners.put(ebo, next);
|
||||
data.nextEboOwner = null;
|
||||
return;
|
||||
}
|
||||
while (node != null) {
|
||||
final VAOData next = node.nextEboOwner;
|
||||
if (next == data) {
|
||||
node.nextEboOwner = data.nextEboOwner;
|
||||
data.nextEboOwner = null;
|
||||
return;
|
||||
}
|
||||
node = next;
|
||||
}
|
||||
}
|
||||
|
||||
public static void enableClientVertexFlag(int flag) { currentVertexFlags |= flag; }
|
||||
@@ -69,6 +114,7 @@ public final class VAOManager {
|
||||
public int vertexFlags;
|
||||
public int ebo;
|
||||
public int clientSideEnabledCount;
|
||||
private VAOData nextEboOwner;
|
||||
|
||||
public VAOData() {
|
||||
attribs = new Attrib[MAX_ATTRIBS];
|
||||
|
||||
@@ -62,11 +62,14 @@ public final class DisplayListVBO {
|
||||
}
|
||||
|
||||
public void render() {
|
||||
vao.bind();
|
||||
vao.draw(drawMode, start, count);
|
||||
vao.unbind();
|
||||
if (vao == null) return;
|
||||
vao.bind();
|
||||
if (count <= 0) { vao.unbind(); return; }
|
||||
vao.draw(drawMode, start, count);
|
||||
vao.unbind();
|
||||
}
|
||||
|
||||
|
||||
public IVertexArrayObject getVAO() {
|
||||
return vao;
|
||||
}
|
||||
|
||||
@@ -1131,4 +1131,52 @@ class GLSM_PushPop_UnitTest {
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0);
|
||||
GLStateManager.glDisable(GL11.GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBlendFuncGL11AliasesMatchGL14() {
|
||||
GLStateManager.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
verifyState(GL11.GL_BLEND_SRC, GL11.GL_SRC_ALPHA, "Blend Source");
|
||||
verifyState(GL14.GL_BLEND_SRC_RGB, GL11.GL_SRC_ALPHA, "Blend Source RGB");
|
||||
verifyState(GL11.GL_BLEND_DST, GL11.GL_ONE_MINUS_SRC_ALPHA, "Blend Destination");
|
||||
verifyState(GL14.GL_BLEND_DST_RGB, GL11.GL_ONE_MINUS_SRC_ALPHA, "Blend Destination RGB");
|
||||
|
||||
GLStateManager.glBlendFunc(GL11.GL_ONE, GL11.GL_ZERO);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBlendFuncSeparateGL11AliasesTrackRgb() {
|
||||
GLStateManager.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO);
|
||||
|
||||
verifyState(GL11.GL_BLEND_SRC, GL11.GL_SRC_ALPHA, "Blend Source");
|
||||
verifyState(GL11.GL_BLEND_DST, GL11.GL_ONE_MINUS_SRC_ALPHA, "Blend Destination");
|
||||
verifyState(GL14.GL_BLEND_SRC_ALPHA, GL11.GL_ONE, "Blend Source Alpha");
|
||||
verifyState(GL14.GL_BLEND_DST_ALPHA, GL11.GL_ZERO, "Blend Destination Alpha");
|
||||
|
||||
GLStateManager.glBlendFunc(GL11.GL_ONE, GL11.GL_ZERO);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPolygonStateReadBack() {
|
||||
GLStateManager.glCullFace(GL11.GL_FRONT);
|
||||
GLStateManager.glFrontFace(GL11.GL_CW);
|
||||
GLStateManager.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_LINE);
|
||||
|
||||
verifyState(GL11.GL_CULL_FACE_MODE, GL11.GL_FRONT, "Cull Face Mode");
|
||||
verifyState(GL11.GL_FRONT_FACE, GL11.GL_CW, "Front Face");
|
||||
verifyState(GL11.GL_POLYGON_MODE, new int[] { GL11.GL_LINE, GL11.GL_LINE }, "Polygon Mode");
|
||||
|
||||
GLStateManager.glCullFace(GL11.GL_BACK);
|
||||
GLStateManager.glFrontFace(GL11.GL_CCW);
|
||||
GLStateManager.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testActiveTextureReadBack() {
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE1);
|
||||
verifyState(GL13.GL_ACTIVE_TEXTURE, GL13.GL_TEXTURE1, "Active Texture");
|
||||
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0);
|
||||
verifyState(GL13.GL_ACTIVE_TEXTURE, GL13.GL_TEXTURE0, "Active Texture - Reset");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
package com.gtnewhorizons.angelica.glsm.ffp;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class VAOManagerEboIndexTest {
|
||||
|
||||
private static final int DEFAULT_VAO = 0;
|
||||
private static final int NO_VAO = -1;
|
||||
|
||||
private final Int2IntOpenHashMap expectedEbo = new Int2IntOpenHashMap();
|
||||
private int currentVao;
|
||||
|
||||
@BeforeEach
|
||||
void reset() {
|
||||
drainManagerState();
|
||||
expectedEbo.clear();
|
||||
VAOManager.init(DEFAULT_VAO);
|
||||
expectedEbo.put(DEFAULT_VAO, 0);
|
||||
currentVao = DEFAULT_VAO;
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void drain() {
|
||||
drainManagerState();
|
||||
}
|
||||
|
||||
private static void drainManagerState() {
|
||||
for (int vao : VAOManager.vaoMap.keySet().toIntArray()) {
|
||||
VAOManager.onDeleteVertexArray(vao);
|
||||
}
|
||||
VAOManager.boundEBO = 0;
|
||||
assertEquals(0, VAOManager.eboOwners.size(), "draining every VAO left entries in the index");
|
||||
}
|
||||
|
||||
private void bindVao(int vao) {
|
||||
if (currentVao != NO_VAO) expectedEbo.put(currentVao, VAOManager.boundEBO);
|
||||
VAOManager.onBindVertexArrayPre(vao);
|
||||
expectedEbo.putIfAbsent(vao, 0);
|
||||
currentVao = vao;
|
||||
}
|
||||
|
||||
private void bindEbo(int ebo) {
|
||||
VAOManager.onBindEBO(ebo);
|
||||
}
|
||||
|
||||
private int countOwners(int buffer) {
|
||||
int owners = 0;
|
||||
for (int vao : expectedEbo.keySet().toIntArray()) {
|
||||
if (expectedEbo.get(vao) == buffer) owners++;
|
||||
}
|
||||
return owners;
|
||||
}
|
||||
|
||||
private void deleteBuffer(int buffer) {
|
||||
VAOManager.onDeleteBuffer(buffer);
|
||||
for (int vao : expectedEbo.keySet().toIntArray()) {
|
||||
if (expectedEbo.get(vao) == buffer) expectedEbo.put(vao, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteVao(int vao) {
|
||||
VAOManager.onDeleteVertexArray(vao);
|
||||
expectedEbo.remove(vao);
|
||||
if (vao == currentVao) currentVao = NO_VAO;
|
||||
}
|
||||
|
||||
private void assertExpectedEbos(int op) {
|
||||
for (var entry : VAOManager.vaoMap.int2ObjectEntrySet()) {
|
||||
final int vao = entry.getIntKey();
|
||||
if (vao == currentVao) continue;
|
||||
assertEquals(expectedEbo.get(vao), entry.getValue().ebo, () -> "op " + op + ": vao " + vao + " ebo mismatch");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void everyVaoKeepsItsExpectedEboUnderRandomOps() {
|
||||
final Random random = new Random(0xC0FFEE);
|
||||
final IntArrayList liveVaos = new IntArrayList();
|
||||
final IntArrayList liveBuffers = new IntArrayList();
|
||||
int nextVao = 1;
|
||||
int nextBuffer = 1;
|
||||
int sharedEboDeletes = 0;
|
||||
|
||||
for (int op = 0; op < 200_000; op++) {
|
||||
switch (random.nextInt(5)) {
|
||||
case 0 -> {
|
||||
final int vao = nextVao++;
|
||||
liveVaos.add(vao);
|
||||
bindVao(vao);
|
||||
}
|
||||
case 1 -> {
|
||||
if (liveVaos.isEmpty()) break;
|
||||
bindVao(liveVaos.getInt(random.nextInt(liveVaos.size())));
|
||||
}
|
||||
case 2 -> {
|
||||
if (currentVao == NO_VAO) break;
|
||||
final int buffer = (random.nextBoolean() && nextBuffer > 8) ? 1 + random.nextInt(nextBuffer - 1) : nextBuffer++;
|
||||
liveBuffers.add(buffer);
|
||||
bindEbo(buffer);
|
||||
}
|
||||
case 3 -> {
|
||||
if (liveBuffers.isEmpty()) break;
|
||||
final int buffer = liveBuffers.removeInt(random.nextInt(liveBuffers.size()));
|
||||
if (countOwners(buffer) > 1) sharedEboDeletes++;
|
||||
deleteBuffer(buffer);
|
||||
}
|
||||
case 4 -> {
|
||||
if (liveVaos.isEmpty()) break;
|
||||
final int vao = liveVaos.removeInt(random.nextInt(liveVaos.size()));
|
||||
final boolean wasBound = vao == currentVao;
|
||||
deleteVao(vao);
|
||||
if (wasBound) bindVao(DEFAULT_VAO);
|
||||
}
|
||||
}
|
||||
assertExpectedEbos(op);
|
||||
}
|
||||
assertTrue(sharedEboDeletes > 20, "op stream never freed a multi-owner EBO (hits: " + sharedEboDeletes + ")");
|
||||
}
|
||||
|
||||
@Test
|
||||
void sharedEboClearsEveryOwner() {
|
||||
final int ebo = 77;
|
||||
bindVao(1);
|
||||
bindEbo(ebo);
|
||||
bindVao(2);
|
||||
bindEbo(ebo);
|
||||
bindVao(3);
|
||||
bindEbo(ebo);
|
||||
bindVao(DEFAULT_VAO);
|
||||
|
||||
deleteBuffer(ebo);
|
||||
|
||||
assertEquals(0, VAOManager.vaoMap.get(1).ebo, "vao 1 kept a freed shared EBO");
|
||||
assertEquals(0, VAOManager.vaoMap.get(2).ebo, "vao 2 kept a freed shared EBO");
|
||||
assertEquals(0, VAOManager.vaoMap.get(3).ebo, "vao 3 kept a freed shared EBO");
|
||||
assertFalse(VAOManager.eboOwners.containsKey(ebo), "index kept owners for a freed EBO");
|
||||
}
|
||||
|
||||
@Test
|
||||
void sharedEboEntryDropsOnlyAfterItsLastOwnerGoes() {
|
||||
final int ebo = 88;
|
||||
bindVao(1);
|
||||
bindEbo(ebo);
|
||||
bindVao(2);
|
||||
bindEbo(ebo);
|
||||
bindVao(DEFAULT_VAO);
|
||||
|
||||
deleteVao(1);
|
||||
assertTrue(VAOManager.eboOwners.containsKey(ebo), "index dropped a still-live owner");
|
||||
deleteVao(2);
|
||||
assertFalse(VAOManager.eboOwners.containsKey(ebo), "index kept an entry after its last owner went away");
|
||||
}
|
||||
|
||||
@Test
|
||||
void deletingTheBoundVaoDoesNotOrphanAnIndexEntry() {
|
||||
final int ebo = 99;
|
||||
bindVao(1);
|
||||
bindEbo(ebo);
|
||||
|
||||
deleteVao(1);
|
||||
bindVao(DEFAULT_VAO);
|
||||
|
||||
assertFalse(VAOManager.eboOwners.containsKey(ebo), "deleting the bound VAO left an unreachable owner in the index");
|
||||
assertEquals(0, VAOManager.eboOwners.size(), "index leaked an entry for a deleted VAO");
|
||||
}
|
||||
|
||||
@Test
|
||||
void indexEmptiesOutWhenEverythingIsDeleted() {
|
||||
for (int vao = 1; vao <= 64; vao++) {
|
||||
bindVao(vao);
|
||||
bindEbo(1000 + vao);
|
||||
}
|
||||
bindVao(DEFAULT_VAO);
|
||||
for (int vao = 1; vao <= 64; vao++) {
|
||||
deleteVao(vao);
|
||||
}
|
||||
assertEquals(0, VAOManager.eboOwners.size(), "index leaked entries after every VAO was deleted");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.gtnewhorizons.angelica.event;
|
||||
|
||||
import net.minecraftforge.eventbus.api.bus.EventBus;
|
||||
import net.minecraftforge.eventbus.api.event.RecordEvent;
|
||||
|
||||
public class RenderChunkEvent implements RecordEvent {
|
||||
public static final EventBus<RenderChunkEvent> BUS = EventBus.create(RenderChunkEvent.class);
|
||||
|
||||
private static final RenderChunkEvent INSTANCE = new RenderChunkEvent();
|
||||
|
||||
public static void post() {
|
||||
if (!BUS.hasListeners()) return;
|
||||
BUS.post(INSTANCE);
|
||||
}
|
||||
}
|
||||
@@ -157,6 +157,7 @@ public enum Mixins implements IMixins {
|
||||
.setPhase(Phase.EARLY)
|
||||
.addClientMixins(
|
||||
"angelica.itemrenderer.MixinItemRenderer",
|
||||
"angelica.itemrenderer.MixinRenderItemFrame",
|
||||
"angelica.itemrenderer.MixinRenderBlocks"
|
||||
)
|
||||
.setApplyIf(() -> AngelicaConfig.optimizeInWorldItemRendering)),
|
||||
@@ -292,8 +293,12 @@ public enum Mixins implements IMixins {
|
||||
, "shaders.MixinLocale"
|
||||
, "shaders.MixinRender"
|
||||
, "shaders.MixinRenderBiped"
|
||||
, "shaders.MixinRenderBlocks_FaceNormals"
|
||||
, "shaders.MixinRenderBlocks_FallingShading"
|
||||
, "shaders.MixinRenderBlocks_ItemId"
|
||||
, "shaders.MixinRenderDragon"
|
||||
, "shaders.MixinRenderEntityFlame"
|
||||
, "shaders.MixinRenderFallingBlock"
|
||||
, "shaders.MixinRendererLivingEntity"
|
||||
, "shaders.MixinRenderGlobal"
|
||||
, "shaders.AccessorEntityHorse"
|
||||
|
||||
@@ -296,7 +296,7 @@ public final class ClientProxy extends CommonProxy {
|
||||
event.left.set(i + 4, String.format(
|
||||
"lc: %d b: %s bl: %d sl: %d rl: %d",
|
||||
chunk.getTopFilledSegment() + 15,
|
||||
this.mc.theWorld.getBiomeGenForCoords(bX & 15, bZ & 15).biomeName,
|
||||
this.mc.theWorld.getBiomeGenForCoords(bX, bZ).biomeName,
|
||||
chunk.getSavedLightValue(EnumSkyBlock.Block, bX & 15, CompatMathHelper.clampHeight(bY), bZ & 15),
|
||||
chunk.getSavedLightValue(EnumSkyBlock.Sky, bX & 15, CompatMathHelper.clampHeight(bY), bZ & 15),
|
||||
chunk.getBlockLightValue(bX & 15, CompatMathHelper.clampHeight(bY), bZ & 15, 0)));
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
package com.gtnewhorizons.angelica.rendering;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.biome.BiomeGenBase;
|
||||
import net.minecraftforge.common.util.ForgeDirection;
|
||||
|
||||
|
||||
public final class FallingBlockMetaAccess implements IBlockAccess {
|
||||
|
||||
private IBlockAccess delegate;
|
||||
private int x;
|
||||
private int y;
|
||||
private int z;
|
||||
private int metadata;
|
||||
|
||||
public FallingBlockMetaAccess set(IBlockAccess delegate, int x, int y, int z, int metadata) {
|
||||
this.delegate = delegate;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.metadata = metadata;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
this.delegate = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlockMetadata(int x, int y, int z) {
|
||||
if (x == this.x && y == this.y && z == this.z) {
|
||||
return this.metadata;
|
||||
}
|
||||
return delegate.getBlockMetadata(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block getBlock(int x, int y, int z) {
|
||||
return delegate.getBlock(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TileEntity getTileEntity(int x, int y, int z) {
|
||||
return delegate.getTileEntity(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLightBrightnessForSkyBlocks(int x, int y, int z, int lightValue) {
|
||||
return delegate.getLightBrightnessForSkyBlocks(x, y, z, lightValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int isBlockProvidingPowerTo(int x, int y, int z, int direction) {
|
||||
return delegate.isBlockProvidingPowerTo(x, y, z, direction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAirBlock(int x, int y, int z) {
|
||||
return delegate.isAirBlock(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeGenBase getBiomeGenForCoords(int x, int z) {
|
||||
return delegate.getBiomeGenForCoords(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight() {
|
||||
return delegate.getHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean extendedLevelsInChunkCache() {
|
||||
return delegate.extendedLevelsInChunkCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSideSolid(int x, int y, int z, ForgeDirection side, boolean _default) {
|
||||
return delegate.isSideSolid(x, y, z, side, _default);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.gtnewhorizons.angelica.rendering;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.TessellatorManager;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectMap;
|
||||
import net.coderbot.iris.block_rendering.BlockMaterialMapping;
|
||||
import net.coderbot.iris.block_rendering.BlockRenderingSettings;
|
||||
import net.coderbot.iris.gl.shader.ProgramCreator;
|
||||
import net.irisshaders.iris.api.v0.IrisApi;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
|
||||
public final class FallingBlockRendering {
|
||||
|
||||
public static boolean active;
|
||||
|
||||
private static final FallingBlockMetaAccess META_ACCESS = new FallingBlockMetaAccess();
|
||||
|
||||
private FallingBlockRendering() {
|
||||
}
|
||||
|
||||
public static FallingBlockMetaAccess metaAccess(IBlockAccess world, int x, int y, int z, int metadata) {
|
||||
return META_ACCESS.set(world, x, y, z, metadata);
|
||||
}
|
||||
|
||||
public static void setEntityAttribute(Block block, int metadata) {
|
||||
if (!shadersActive()) return;
|
||||
GLStateManager.glVertexAttrib2s(ProgramCreator.MC_ENTITY, (short) blockMaterialId(block, metadata), (short) 0);
|
||||
}
|
||||
|
||||
public static void resetEntityAttribute() {
|
||||
if (!shadersActive()) return;
|
||||
GLStateManager.glVertexAttrib2s(ProgramCreator.MC_ENTITY, (short) -1, (short) -1);
|
||||
}
|
||||
|
||||
private static int blockMaterialId(Block block, int metadata) {
|
||||
final Reference2ObjectMap<Block, Int2IntMap> blockMetaMatches = BlockRenderingSettings.INSTANCE.getBlockMetaMatches();
|
||||
if (blockMetaMatches == null) return -1;
|
||||
|
||||
final Int2IntMap metaMap = blockMetaMatches.get(block);
|
||||
return metaMap != null ? BlockMaterialMapping.resolveId(metaMap, metadata) : -1;
|
||||
}
|
||||
|
||||
public static boolean isActive() {
|
||||
return active && shadersActive();
|
||||
}
|
||||
|
||||
private static boolean shadersActive() {
|
||||
return TessellatorManager.isOnMainThread() && IrisApi.getInstance().isShaderPackInUse();
|
||||
}
|
||||
|
||||
public static boolean skipDirectionalShading() {
|
||||
return isActive() && BlockRenderingSettings.INSTANCE.shouldDisableDirectionalShading();
|
||||
}
|
||||
}
|
||||
+21
-1
@@ -12,6 +12,7 @@ public class BlockRenderListManager {
|
||||
private static final BlockMeta key = new BlockMeta();
|
||||
|
||||
private static final Object2IntOpenHashMap<BlockMeta> displayListMap = new Object2IntOpenHashMap<>();
|
||||
private static final int[] itemFrameDisplayLists = new int[8];
|
||||
|
||||
|
||||
private static final int ISBRH_CUTOFF = 40;
|
||||
@@ -36,6 +37,10 @@ public class BlockRenderListManager {
|
||||
return displayListMap.getInt(key);
|
||||
}
|
||||
|
||||
public static int getItemFrameDisplayList(int variant) {
|
||||
return itemFrameDisplayLists[variant];
|
||||
}
|
||||
|
||||
public static int startCompiling() {
|
||||
final int list = GLStateManager.glGenLists(1);
|
||||
GLStateManager.glNewList(list, GL11.GL_COMPILE);
|
||||
@@ -43,9 +48,18 @@ public class BlockRenderListManager {
|
||||
}
|
||||
|
||||
public static void endCompiling(int list, Block block, int meta) {
|
||||
finishCompiling();
|
||||
displayListMap.put(new BlockMeta(block, meta), list);
|
||||
}
|
||||
|
||||
public static void endItemFrameCompiling(int list, int variant) {
|
||||
finishCompiling();
|
||||
itemFrameDisplayLists[variant] = list;
|
||||
}
|
||||
|
||||
private static void finishCompiling() {
|
||||
DisplayListManager.discardMatrixTransforms();
|
||||
GLStateManager.glEndList();
|
||||
displayListMap.put(new BlockMeta(block, meta), list);
|
||||
}
|
||||
|
||||
public static void registerReloadListener(){
|
||||
@@ -56,6 +70,12 @@ public class BlockRenderListManager {
|
||||
GLStateManager.glDeleteLists(list, 1);
|
||||
}
|
||||
displayListMap.clear();
|
||||
for (int i = 0; i < itemFrameDisplayLists.length; i++) {
|
||||
if (itemFrameDisplayLists[i] != 0) {
|
||||
GLStateManager.glDeleteLists(itemFrameDisplayLists[i], 1);
|
||||
itemFrameDisplayLists[i] = 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.world.ChunkPosition;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
@@ -16,8 +17,9 @@ import java.util.function.Consumer;
|
||||
/**
|
||||
* Thread-safe wrapper around a tile entity map for chunkTileEntityMap.
|
||||
* May wrap either a plain Object2ObjectOpenHashMap (vanilla) or a ColumnTileEntityMap (cubic chunks).
|
||||
* Extends HashMap for binary compatibility with mods that cast chunkTileEntityMap to HashMap.
|
||||
*/
|
||||
public class ConcurrentTileEntityMap implements Map<ChunkPosition, TileEntity> {
|
||||
public class ConcurrentTileEntityMap extends HashMap<ChunkPosition, TileEntity> {
|
||||
private final Object2ObjectOpenHashMap<ChunkPosition, TileEntity> flatDelegate;
|
||||
private final Map<ChunkPosition, TileEntity> delegate;
|
||||
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
|
||||
|
||||
@@ -8,8 +8,10 @@ import net.minecraft.block.BlockLeaves;
|
||||
import net.minecraft.block.BlockMushroom;
|
||||
import net.minecraft.block.BlockRedstoneWire;
|
||||
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Fallback {@link MipmapStrategy} assignments for sprites that carry no metadata.
|
||||
@@ -17,8 +19,8 @@ import java.util.Map;
|
||||
public final class MipmapStrategies {
|
||||
|
||||
private static final Map<Class<?>, MipmapStrategy> CLASS_RULES = new Object2ObjectOpenHashMap<>();
|
||||
private static final Map<String, MipmapStrategy> SPRITE_RULES = new Object2ObjectOpenHashMap<>();
|
||||
private static final LinkedList<MipmapStrategy> STRATEGY_STACK = new LinkedList<>();
|
||||
private static final Map<String, MipmapStrategy> SPRITE_RULES = new ConcurrentHashMap<>();
|
||||
private static final ThreadLocal<Deque<MipmapStrategy>> STRATEGY_STACK = ThreadLocal.withInitial(LinkedList::new);
|
||||
|
||||
static {
|
||||
CLASS_RULES.put(BlockLeaves.class, MipmapStrategy.DARK_CUTOUT);
|
||||
@@ -33,16 +35,17 @@ public final class MipmapStrategies {
|
||||
|
||||
public static void reset() {
|
||||
SPRITE_RULES.clear();
|
||||
STRATEGY_STACK.clear();
|
||||
STRATEGY_STACK.remove();
|
||||
}
|
||||
|
||||
public static void beginBlock(Block block) {
|
||||
STRATEGY_STACK.push(resolve(block.getClass()));
|
||||
STRATEGY_STACK.get().push(resolve(block.getClass()));
|
||||
}
|
||||
|
||||
public static void endBlock() {
|
||||
if (!STRATEGY_STACK.isEmpty()) {
|
||||
STRATEGY_STACK.pop();
|
||||
final Deque<MipmapStrategy> stack = STRATEGY_STACK.get();
|
||||
if (!stack.isEmpty()) {
|
||||
stack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +54,7 @@ public final class MipmapStrategies {
|
||||
return;
|
||||
}
|
||||
|
||||
MipmapStrategy strategy = STRATEGY_STACK.peek();
|
||||
MipmapStrategy strategy = STRATEGY_STACK.get().peek();
|
||||
if (strategy == null && textureType == 0 && iconName.contains("leaves")) {
|
||||
strategy = MipmapStrategy.DARK_CUTOUT;
|
||||
}
|
||||
@@ -59,10 +62,8 @@ public final class MipmapStrategies {
|
||||
return;
|
||||
}
|
||||
|
||||
final MipmapStrategy existing = SPRITE_RULES.get(iconName);
|
||||
if (existing == null || strategy.conflictPrecedence() > existing.conflictPrecedence()) {
|
||||
SPRITE_RULES.put(iconName, strategy);
|
||||
}
|
||||
SPRITE_RULES.merge(iconName, strategy,
|
||||
(existing, incoming) -> incoming.conflictPrecedence() > existing.conflictPrecedence() ? incoming : existing);
|
||||
}
|
||||
|
||||
public static MipmapStrategy inheritedFor(int textureType, String iconName) {
|
||||
|
||||
@@ -781,7 +781,11 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R
|
||||
}
|
||||
|
||||
public boolean shouldOverrideShaders() {
|
||||
return isRenderingWorld && !isRenderingFullScreenPass && !isPostChain && isMainBound;
|
||||
return isRenderingLevelGeometry() && isMainBound;
|
||||
}
|
||||
|
||||
public boolean isRenderingLevelGeometry() {
|
||||
return isRenderingWorld && !isRenderingFullScreenPass && !isPostChain;
|
||||
}
|
||||
|
||||
public Pass getActivePassProgram() {
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
package net.coderbot.iris.uniforms;
|
||||
|
||||
import net.coderbot.iris.Iris;
|
||||
import net.coderbot.iris.pipeline.DeferredWorldRenderingPipeline;
|
||||
import net.coderbot.iris.pipeline.WorldRenderingPipeline;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
/**
|
||||
@@ -23,6 +27,13 @@ public class ItemIdManager {
|
||||
CapturedRenderingState.INSTANCE.setCurrentRenderedItem(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the item ID for a Block rendered outside of terrain.
|
||||
*/
|
||||
public static void setBlockId(Block block, int metadata) {
|
||||
CapturedRenderingState.INSTANCE.setCurrentRenderedItem(Math.max(0, ItemMaterialHelper.getMaterialId(block, metadata)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the item ID to 0.
|
||||
* Used when entering/exiting render sections or before glint rendering.
|
||||
@@ -30,4 +41,28 @@ public class ItemIdManager {
|
||||
public static void resetItemId() {
|
||||
CapturedRenderingState.INSTANCE.setCurrentRenderedItem(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* The currently bound item ID.
|
||||
*/
|
||||
public static int getItemId() {
|
||||
return CapturedRenderingState.INSTANCE.getCurrentRenderedItem();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an already-resolved item ID without performing a lookup.
|
||||
*/
|
||||
public static void setItemIdRaw(int id) {
|
||||
CapturedRenderingState.INSTANCE.setCurrentRenderedItem(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Honestly I don't know why there's comments on a lot of these.
|
||||
* Guess I thought documentation is good but man if you can't figure this out
|
||||
* you're in trouble.
|
||||
*/
|
||||
public static boolean isWorldRenderActive() {
|
||||
final WorldRenderingPipeline pipeline = Iris.getPipelineManager().getPipelineNullable();
|
||||
return pipeline instanceof DeferredWorldRenderingPipeline drp && drp.isRenderingLevelGeometry();
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,8 @@ public class ItemMaterialHelper {
|
||||
private static final Reference2ObjectMap<Item, Int2IntMap> MATERIAL_CACHE = new Reference2ObjectOpenHashMap<>();
|
||||
private static final int CACHE_MISS_SENTINEL = Integer.MIN_VALUE;
|
||||
private static final Reference2ObjectMap<Item, NamespacedId> ITEM_NAME_CACHE = new Reference2ObjectOpenHashMap<>();
|
||||
private static final Reference2ObjectMap<Block, Int2IntMap> BLOCK_MATERIAL_CACHE = new Reference2ObjectOpenHashMap<>();
|
||||
|
||||
/**
|
||||
* Get the material ID for an ItemStack.
|
||||
* For ItemBlock: checks block.properties first, then item.properties.
|
||||
@@ -79,6 +81,52 @@ public class ItemMaterialHelper {
|
||||
return materialId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the material ID for a Block rendered outside of terrain.
|
||||
*
|
||||
* @return The material ID, or -1 if not found
|
||||
*/
|
||||
public static int getMaterialId(Block block, int metadata) {
|
||||
if (block == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
Int2IntMap metadataCache = BLOCK_MATERIAL_CACHE.get(block);
|
||||
if (metadataCache != null) {
|
||||
int cached = metadataCache.getOrDefault(metadata, CACHE_MISS_SENTINEL);
|
||||
if (cached != CACHE_MISS_SENTINEL) {
|
||||
return cached;
|
||||
}
|
||||
}
|
||||
|
||||
int materialId = lookupBlockMaterialId(block, metadata);
|
||||
|
||||
if (metadataCache == null) {
|
||||
metadataCache = new Int2IntOpenHashMap();
|
||||
metadataCache.defaultReturnValue(CACHE_MISS_SENTINEL);
|
||||
BLOCK_MATERIAL_CACHE.put(block, metadataCache);
|
||||
}
|
||||
metadataCache.put(metadata, materialId);
|
||||
|
||||
return materialId;
|
||||
}
|
||||
|
||||
private static int lookupBlockMaterialId(Block block, int metadata) {
|
||||
Reference2ObjectMap<Block, Int2IntMap> blockMetaMatches = BlockRenderingSettings.INSTANCE.getBlockMetaMatches();
|
||||
if (blockMetaMatches != null) {
|
||||
Int2IntMap metaMap = blockMetaMatches.get(block);
|
||||
if (metaMap != null) {
|
||||
int id = BlockMaterialMapping.resolveId(metaMap, metadata);
|
||||
if (id != -1) {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final Item item = Item.getItemFromBlock(block);
|
||||
return item != null ? lookupItemPropertiesId(item) : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the actual material ID lookup without caching.
|
||||
*
|
||||
@@ -107,16 +155,17 @@ public class ItemMaterialHelper {
|
||||
}
|
||||
|
||||
// Fall back to item.properties
|
||||
Object2IntFunction<NamespacedId> itemIds = BlockRenderingSettings.INSTANCE.getItemIds();
|
||||
if (itemIds != null) {
|
||||
String itemIdString = Item.itemRegistry.getNameForObject(item);
|
||||
if (itemIdString != null) {
|
||||
ResourceLocation itemId = new ResourceLocation(itemIdString);
|
||||
return itemIds.applyAsInt(new NamespacedId(itemId.getResourceDomain(), itemId.getResourcePath()));
|
||||
}
|
||||
return lookupItemPropertiesId(item);
|
||||
}
|
||||
|
||||
private static int lookupItemPropertiesId(Item item) {
|
||||
final Object2IntFunction<NamespacedId> itemIds = BlockRenderingSettings.INSTANCE.getItemIds();
|
||||
if (itemIds == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
final NamespacedId name = getCachedItemName(item);
|
||||
return name == null ? -1 : itemIds.applyAsInt(name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -126,6 +175,7 @@ public class ItemMaterialHelper {
|
||||
public static void clearCache() {
|
||||
MATERIAL_CACHE.clear();
|
||||
ITEM_NAME_CACHE.clear();
|
||||
BLOCK_MATERIAL_CACHE.clear();
|
||||
}
|
||||
|
||||
private static NamespacedId getCachedItemName(Item item) {
|
||||
|
||||
-7
@@ -20,9 +20,7 @@ import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Constant;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyConstant;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyVariable;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
@@ -194,11 +192,6 @@ public abstract class MixinFontRenderer implements FontRendererAccessor, IFontPa
|
||||
@Override
|
||||
public void angelica$bindTexture(ResourceLocation location) { this.bindTexture(location); }
|
||||
|
||||
@ModifyConstant(method = "getCharWidth", constant = @Constant(intValue = 7))
|
||||
private int angelica$maxCharWidth(int original) {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
@Inject(method = "getCharWidth", at = @At("HEAD"), cancellable = true)
|
||||
public void getCharWidth(char c, CallbackInfoReturnable<Integer> cir) {
|
||||
cir.setReturnValue((int) angelica$getBatcher().getCharWidthFine(c));
|
||||
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
package com.gtnewhorizons.angelica.mixins.early.angelica.itemrenderer;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.TessellatorManager;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.rendering.items.BlockRenderListManager;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.renderer.tileentity.RenderItemFrame;
|
||||
import net.minecraft.entity.item.EntityItemFrame;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
|
||||
@Mixin(RenderItemFrame.class)
|
||||
public class MixinRenderItemFrame {
|
||||
|
||||
@WrapOperation(
|
||||
method = "doRender(Lnet/minecraft/entity/item/EntityItemFrame;DDDFF)V",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/client/renderer/tileentity/RenderItemFrame;renderFrameItemAsBlock(Lnet/minecraft/entity/item/EntityItemFrame;)V"
|
||||
)
|
||||
)
|
||||
private void angelica$cacheFrame(RenderItemFrame renderer, EntityItemFrame frame, Operation<Void> original) {
|
||||
angelica$renderCached(renderer, frame, original, frame.hangingDirection);
|
||||
}
|
||||
|
||||
@WrapOperation(
|
||||
method = "doRender(Lnet/minecraft/entity/item/EntityItemFrame;DDDFF)V",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/client/renderer/tileentity/RenderItemFrame;func_147915_b(Lnet/minecraft/entity/item/EntityItemFrame;)V"
|
||||
)
|
||||
)
|
||||
private void angelica$cacheMapFrame(RenderItemFrame renderer, EntityItemFrame frame, Operation<Void> original) {
|
||||
angelica$renderCached(renderer, frame, original, 4 + frame.hangingDirection);
|
||||
}
|
||||
|
||||
@Unique
|
||||
private static void angelica$renderCached(RenderItemFrame renderer, EntityItemFrame frame,
|
||||
Operation<Void> original, int keyIndex) {
|
||||
if (GLStateManager.isRecordingDisplayList() || TessellatorManager.isCurrentlyCapturing()
|
||||
|| TessellatorManager.shouldInterceptDraw(Tessellator.instance)) {
|
||||
original.call(renderer, frame);
|
||||
return;
|
||||
}
|
||||
int list = BlockRenderListManager.getItemFrameDisplayList(keyIndex);
|
||||
if (list == 0) {
|
||||
list = BlockRenderListManager.startCompiling();
|
||||
original.call(renderer, frame);
|
||||
BlockRenderListManager.endItemFrameCompiling(list, keyIndex);
|
||||
}
|
||||
GLStateManager.glCallList(list);
|
||||
}
|
||||
}
|
||||
+5
-4
@@ -6,6 +6,8 @@ import com.gtnewhorizons.angelica.rendering.celeritas.TextureMapExtension;
|
||||
import com.gtnewhorizons.angelica.utils.MipmapStrategies;
|
||||
import com.gtnewhorizons.angelica.utils.MipmapStrategy;
|
||||
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import me.jellysquid.mods.sodium.client.gui.SodiumGameOptions;
|
||||
import net.minecraft.block.Block;
|
||||
@@ -27,7 +29,6 @@ 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.ModifyArg;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@@ -74,15 +75,15 @@ public class MixinTextureMap implements TextureMapExtension {
|
||||
/**
|
||||
* Brackets each block's icon registration so the sprites it registers can be attributed to it.
|
||||
*/
|
||||
@Redirect(
|
||||
@WrapOperation(
|
||||
method = "registerIcons",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/block/Block;registerBlockIcons(Lnet/minecraft/client/renderer/texture/IIconRegister;)V"))
|
||||
private void angelica$trackBlockIcons(Block block, IIconRegister reg) {
|
||||
private void angelica$trackBlockIcons(Block block, IIconRegister reg, Operation<Void> original) {
|
||||
MipmapStrategies.beginBlock(block);
|
||||
try {
|
||||
block.registerBlockIcons(reg);
|
||||
original.call(block, reg);
|
||||
} finally {
|
||||
MipmapStrategies.endBlock();
|
||||
}
|
||||
|
||||
+2
@@ -2,6 +2,7 @@ package com.gtnewhorizons.angelica.mixins.early.celeritas.terrain;
|
||||
|
||||
import com.gtnewhorizons.angelica.compat.mojang.Camera;
|
||||
import com.gtnewhorizons.angelica.compat.mojang.GameModeUtil;
|
||||
import com.gtnewhorizons.angelica.event.RenderChunkEvent;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.mixins.interfaces.IRenderGlobalExt;
|
||||
import com.gtnewhorizons.angelica.rendering.AngelicaRenderQueue;
|
||||
@@ -164,6 +165,7 @@ public class MixinRenderGlobal implements IRenderGlobalExt {
|
||||
} else {
|
||||
mc.mcProfiler.endStartSection("draw_chunk_layer_translucent");
|
||||
this.celeritas$renderer.drawChunkLayer(BlockRenderLayer.TRANSLUCENT, camX, camY, camZ);
|
||||
RenderChunkEvent.post();
|
||||
}
|
||||
} finally {
|
||||
RenderDevice.exitManagedCode();
|
||||
|
||||
+28
-1
@@ -8,7 +8,9 @@ import net.coderbot.iris.pipeline.HandRenderer;
|
||||
import net.coderbot.iris.uniforms.ItemIdManager;
|
||||
import net.irisshaders.iris.api.v0.IrisApi;
|
||||
import net.minecraft.client.renderer.ItemRenderer;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraftforge.client.IItemRenderer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
@@ -16,7 +18,8 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
/**
|
||||
* Mixin to handle item rendering in first-person.
|
||||
* Mixin to handle item rendering in first-person, and to set the currentRenderedItem for every
|
||||
* item rendered on an entity.
|
||||
*/
|
||||
@Mixin(ItemRenderer.class)
|
||||
public class MixinItemRenderer {
|
||||
@@ -53,6 +56,30 @@ public class MixinItemRenderer {
|
||||
ItemIdManager.resetItemId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the item ID for any item rendered on an entity.
|
||||
*/
|
||||
@Inject(
|
||||
method = "renderItem(Lnet/minecraft/entity/EntityLivingBase;Lnet/minecraft/item/ItemStack;ILnet/minecraftforge/client/IItemRenderer$ItemRenderType;)V",
|
||||
at = @At("HEAD"),
|
||||
remap = false
|
||||
)
|
||||
private void iris$setEntityItemId(EntityLivingBase entity, ItemStack itemStack, int renderPass, IItemRenderer.ItemRenderType type, CallbackInfo ci) {
|
||||
ItemIdManager.setItemId(itemStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the ID once the item is drawn.
|
||||
*/
|
||||
@Inject(
|
||||
method = "renderItem(Lnet/minecraft/entity/EntityLivingBase;Lnet/minecraft/item/ItemStack;ILnet/minecraftforge/client/IItemRenderer$ItemRenderType;)V",
|
||||
at = @At("RETURN"),
|
||||
remap = false
|
||||
)
|
||||
private void iris$clearEntityItemId(EntityLivingBase entity, ItemStack itemStack, int renderPass, IItemRenderer.ItemRenderType type, CallbackInfo ci) {
|
||||
ItemIdManager.resetItemId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate GLINT shader before rendering enchantment glint on held items (third person).
|
||||
*/
|
||||
|
||||
@@ -4,10 +4,8 @@ import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import net.coderbot.iris.uniforms.ItemIdManager;
|
||||
import net.minecraft.client.model.ModelBase;
|
||||
import net.minecraft.client.renderer.ItemRenderer;
|
||||
import net.minecraft.client.renderer.entity.RenderBiped;
|
||||
import net.minecraft.entity.EntityLiving;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
@@ -39,17 +37,4 @@ public class MixinRenderBiped {
|
||||
|
||||
original.call(instance, model);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set item ID when rendering held items on entities (third person).
|
||||
*/
|
||||
@WrapOperation(
|
||||
method = "renderEquippedItems(Lnet/minecraft/entity/EntityLiving;F)V",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/ItemRenderer;renderItem(Lnet/minecraft/entity/EntityLivingBase;Lnet/minecraft/item/ItemStack;I)V")
|
||||
)
|
||||
private void iris$setHeldItemId(ItemRenderer itemRenderer, EntityLivingBase entity, ItemStack itemStack, int renderPass, Operation<Void> original) {
|
||||
ItemIdManager.setItemId(itemStack);
|
||||
|
||||
original.call(itemRenderer, entity, itemStack, renderPass);
|
||||
}
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
package com.gtnewhorizons.angelica.mixins.early.shaders;
|
||||
|
||||
import com.gtnewhorizons.angelica.rendering.FallingBlockRendering;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.renderer.RenderBlocks;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.util.IIcon;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
/**
|
||||
* Emits a per-face normal while a falling block is rendering, so shader packs can light it.
|
||||
*/
|
||||
@Mixin(RenderBlocks.class)
|
||||
public class MixinRenderBlocks_FaceNormals {
|
||||
|
||||
@Redirect(
|
||||
method = {"renderBlockSandFalling", "renderStandardBlockWithColorMultiplier",
|
||||
"renderStandardBlockWithAmbientOcclusion", "renderStandardBlockWithAmbientOcclusionPartial"},
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderBlocks;renderFaceYNeg(Lnet/minecraft/block/Block;DDDLnet/minecraft/util/IIcon;)V")
|
||||
)
|
||||
private void angelica$normalYNeg(RenderBlocks instance, Block block, double x, double y, double z, IIcon icon) {
|
||||
if (FallingBlockRendering.isActive()) Tessellator.instance.setNormal(0.0F, -1.0F, 0.0F);
|
||||
instance.renderFaceYNeg(block, x, y, z, icon);
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = {"renderBlockSandFalling", "renderStandardBlockWithColorMultiplier",
|
||||
"renderStandardBlockWithAmbientOcclusion", "renderStandardBlockWithAmbientOcclusionPartial"},
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderBlocks;renderFaceYPos(Lnet/minecraft/block/Block;DDDLnet/minecraft/util/IIcon;)V")
|
||||
)
|
||||
private void angelica$normalYPos(RenderBlocks instance, Block block, double x, double y, double z, IIcon icon) {
|
||||
if (FallingBlockRendering.isActive()) Tessellator.instance.setNormal(0.0F, 1.0F, 0.0F);
|
||||
instance.renderFaceYPos(block, x, y, z, icon);
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = {"renderBlockSandFalling", "renderStandardBlockWithColorMultiplier",
|
||||
"renderStandardBlockWithAmbientOcclusion", "renderStandardBlockWithAmbientOcclusionPartial"},
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderBlocks;renderFaceZNeg(Lnet/minecraft/block/Block;DDDLnet/minecraft/util/IIcon;)V")
|
||||
)
|
||||
private void angelica$normalZNeg(RenderBlocks instance, Block block, double x, double y, double z, IIcon icon) {
|
||||
if (FallingBlockRendering.isActive()) Tessellator.instance.setNormal(0.0F, 0.0F, -1.0F);
|
||||
instance.renderFaceZNeg(block, x, y, z, icon);
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = {"renderBlockSandFalling", "renderStandardBlockWithColorMultiplier",
|
||||
"renderStandardBlockWithAmbientOcclusion", "renderStandardBlockWithAmbientOcclusionPartial"},
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderBlocks;renderFaceZPos(Lnet/minecraft/block/Block;DDDLnet/minecraft/util/IIcon;)V")
|
||||
)
|
||||
private void angelica$normalZPos(RenderBlocks instance, Block block, double x, double y, double z, IIcon icon) {
|
||||
if (FallingBlockRendering.isActive()) Tessellator.instance.setNormal(0.0F, 0.0F, 1.0F);
|
||||
instance.renderFaceZPos(block, x, y, z, icon);
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = {"renderBlockSandFalling", "renderStandardBlockWithColorMultiplier",
|
||||
"renderStandardBlockWithAmbientOcclusion", "renderStandardBlockWithAmbientOcclusionPartial"},
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderBlocks;renderFaceXNeg(Lnet/minecraft/block/Block;DDDLnet/minecraft/util/IIcon;)V")
|
||||
)
|
||||
private void angelica$normalXNeg(RenderBlocks instance, Block block, double x, double y, double z, IIcon icon) {
|
||||
if (FallingBlockRendering.isActive()) Tessellator.instance.setNormal(-1.0F, 0.0F, 0.0F);
|
||||
instance.renderFaceXNeg(block, x, y, z, icon);
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = {"renderBlockSandFalling", "renderStandardBlockWithColorMultiplier",
|
||||
"renderStandardBlockWithAmbientOcclusion", "renderStandardBlockWithAmbientOcclusionPartial"},
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderBlocks;renderFaceXPos(Lnet/minecraft/block/Block;DDDLnet/minecraft/util/IIcon;)V")
|
||||
)
|
||||
private void angelica$normalXPos(RenderBlocks instance, Block block, double x, double y, double z, IIcon icon) {
|
||||
if (FallingBlockRendering.isActive()) Tessellator.instance.setNormal(1.0F, 0.0F, 0.0F);
|
||||
instance.renderFaceXPos(block, x, y, z, icon);
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
package com.gtnewhorizons.angelica.mixins.early.shaders;
|
||||
|
||||
import com.gtnewhorizons.angelica.rendering.FallingBlockRendering;
|
||||
import net.minecraft.client.renderer.RenderBlocks;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.Constant;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyConstant;
|
||||
|
||||
/**
|
||||
* Replace vanilla's baked per-face directional shading while a falling block is rendering.
|
||||
*/
|
||||
@Mixin(RenderBlocks.class)
|
||||
public class MixinRenderBlocks_FallingShading {
|
||||
|
||||
@ModifyConstant(
|
||||
method = {
|
||||
"renderStandardBlockWithColorMultiplier",
|
||||
"renderStandardBlockWithAmbientOcclusion",
|
||||
"renderStandardBlockWithAmbientOcclusionPartial",
|
||||
"renderBlockSandFalling"
|
||||
},
|
||||
constant = @Constant(floatValue = 0.5F))
|
||||
private float angelica$flattenBottomShading(float original) {
|
||||
return FallingBlockRendering.skipDirectionalShading() ? 1.0F : original;
|
||||
}
|
||||
|
||||
@ModifyConstant(
|
||||
method = {
|
||||
"renderStandardBlockWithColorMultiplier",
|
||||
"renderStandardBlockWithAmbientOcclusion",
|
||||
"renderStandardBlockWithAmbientOcclusionPartial",
|
||||
"renderBlockSandFalling"
|
||||
},
|
||||
constant = @Constant(floatValue = 0.8F))
|
||||
private float angelica$flattenNorthSouthShading(float original) {
|
||||
return FallingBlockRendering.skipDirectionalShading() ? 1.0F : original;
|
||||
}
|
||||
|
||||
@ModifyConstant(
|
||||
method = {
|
||||
"renderStandardBlockWithColorMultiplier",
|
||||
"renderStandardBlockWithAmbientOcclusion",
|
||||
"renderStandardBlockWithAmbientOcclusionPartial",
|
||||
"renderBlockSandFalling"
|
||||
},
|
||||
constant = @Constant(floatValue = 0.6F))
|
||||
private float angelica$flattenEastWestShading(float original) {
|
||||
return FallingBlockRendering.skipDirectionalShading() ? 1.0F : original;
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
package com.gtnewhorizons.angelica.mixins.early.shaders;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.TessellatorManager;
|
||||
import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import net.coderbot.iris.uniforms.CapturedRenderingState;
|
||||
import net.coderbot.iris.uniforms.ItemIdManager;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.renderer.RenderBlocks;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
|
||||
/**
|
||||
* Sets the currentRenderedItem ID for blocks drawn outside of terrain.
|
||||
*/
|
||||
@Mixin(value = RenderBlocks.class, priority = 1500)
|
||||
public class MixinRenderBlocks_ItemId {
|
||||
|
||||
@WrapMethod(method = "renderBlockAsItem")
|
||||
private void iris$blockItemId(Block block, int metadata, float brightness, Operation<Void> original) {
|
||||
// renderBlockAsItem is shared with GUI and HUD item rendering
|
||||
if (!ItemIdManager.isWorldRenderActive() || !TessellatorManager.isOnMainThread()) {
|
||||
original.call(block, metadata, brightness);
|
||||
return;
|
||||
}
|
||||
|
||||
final int prevItemId = ItemIdManager.getItemId();
|
||||
final int prevBlockEntityId = CapturedRenderingState.INSTANCE.getCurrentRenderedBlockEntity();
|
||||
|
||||
CapturedRenderingState.INSTANCE.setCurrentBlockEntity(1);
|
||||
|
||||
if (prevItemId <= 0) {
|
||||
ItemIdManager.setBlockId(block, metadata);
|
||||
}
|
||||
|
||||
try {
|
||||
original.call(block, metadata, brightness);
|
||||
} finally {
|
||||
ItemIdManager.setItemIdRaw(prevItemId);
|
||||
CapturedRenderingState.INSTANCE.setCurrentBlockEntity(prevBlockEntityId);
|
||||
}
|
||||
}
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
package com.gtnewhorizons.angelica.mixins.early.shaders;
|
||||
|
||||
import com.gtnewhorizons.angelica.rendering.FallingBlockMetaAccess;
|
||||
import com.gtnewhorizons.angelica.rendering.FallingBlockRendering;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import net.coderbot.iris.layer.GbufferPrograms;
|
||||
import net.coderbot.iris.pipeline.WorldRenderingPhase;
|
||||
import net.coderbot.iris.uniforms.CapturedRenderingState;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.renderer.RenderBlocks;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.renderer.entity.RenderFallingBlock;
|
||||
import net.minecraft.entity.item.EntityFallingBlock;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.World;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
/**
|
||||
* Renders falling blocks through terrain.
|
||||
*/
|
||||
@Mixin(RenderFallingBlock.class)
|
||||
public class MixinRenderFallingBlock {
|
||||
|
||||
@Inject(method = "doRender(Lnet/minecraft/entity/item/EntityFallingBlock;DDDFF)V", at = @At("HEAD"))
|
||||
private void angelica$beginFallingBlock(EntityFallingBlock entity, double x, double y, double z, float entityYaw, float partialTicks, CallbackInfo ci) {
|
||||
FallingBlockRendering.active = true;
|
||||
|
||||
CapturedRenderingState.INSTANCE.setCurrentBlockEntity(0);
|
||||
GbufferPrograms.setOverridePhase(WorldRenderingPhase.TERRAIN_SOLID);
|
||||
FallingBlockRendering.setEntityAttribute(entity.func_145805_f(), entity.field_145814_a);
|
||||
}
|
||||
|
||||
@Inject(method = "doRender(Lnet/minecraft/entity/item/EntityFallingBlock;DDDFF)V", at = @At("RETURN"))
|
||||
private void angelica$endFallingBlock(EntityFallingBlock entity, double x, double y, double z, float entityYaw, float partialTicks, CallbackInfo ci) {
|
||||
FallingBlockRendering.active = false;
|
||||
|
||||
FallingBlockRendering.resetEntityAttribute();
|
||||
GbufferPrograms.setOverridePhase(null);
|
||||
CapturedRenderingState.INSTANCE.setCurrentBlockEntity(0);
|
||||
}
|
||||
|
||||
@WrapOperation(
|
||||
method = "doRender(Lnet/minecraft/entity/item/EntityFallingBlock;DDDFF)V",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderBlocks;renderBlockSandFalling(Lnet/minecraft/block/Block;Lnet/minecraft/world/World;IIII)V")
|
||||
)
|
||||
private void angelica$aoFallingBlock(RenderBlocks renderBlocks, Block block, World world, int x, int y, int z, int metadata, Operation<Void> original) {
|
||||
if (!FallingBlockRendering.isActive()) {
|
||||
original.call(renderBlocks, block, world, x, y, z, metadata);
|
||||
return;
|
||||
}
|
||||
|
||||
final IBlockAccess prevAccess = renderBlocks.blockAccess;
|
||||
final boolean prevRenderAllFaces = renderBlocks.renderAllFaces;
|
||||
final FallingBlockMetaAccess access = FallingBlockRendering.metaAccess(world, x, y, z, metadata);
|
||||
renderBlocks.blockAccess = access;
|
||||
renderBlocks.renderAllFaces = true;
|
||||
|
||||
final Tessellator tessellator = Tessellator.instance;
|
||||
tessellator.startDrawingQuads();
|
||||
tessellator.setTranslation(-x - 0.5D, -y - 0.5D, -z - 0.5D);
|
||||
|
||||
try {
|
||||
renderBlocks.renderStandardBlock(block, x, y, z);
|
||||
} finally {
|
||||
tessellator.setTranslation(0.0D, 0.0D, 0.0D);
|
||||
tessellator.draw();
|
||||
renderBlocks.renderAllFaces = prevRenderAllFaces;
|
||||
renderBlocks.blockAccess = prevAccess;
|
||||
access.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
-15
@@ -9,9 +9,7 @@ import net.coderbot.iris.uniforms.ItemIdManager;
|
||||
import net.minecraft.client.entity.AbstractClientPlayer;
|
||||
import net.minecraft.client.model.ModelBase;
|
||||
import net.minecraft.client.model.ModelBiped;
|
||||
import net.minecraft.client.renderer.ItemRenderer;
|
||||
import net.minecraft.client.renderer.entity.RenderPlayer;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
@@ -67,17 +65,4 @@ public class MixinRenderPlayerArmor {
|
||||
original.call(modelBiped, scale);
|
||||
ItemIdManager.resetItemId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set item ID when rendering held items in third person.
|
||||
*/
|
||||
@WrapOperation(
|
||||
method = "renderEquippedItems(Lnet/minecraft/client/entity/AbstractClientPlayer;F)V",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/ItemRenderer;renderItem(Lnet/minecraft/entity/EntityLivingBase;Lnet/minecraft/item/ItemStack;I)V")
|
||||
)
|
||||
private void iris$setHeldItemId(ItemRenderer itemRenderer, EntityLivingBase entity, ItemStack itemStack, int renderPass, Operation<Void> original) {
|
||||
ItemIdManager.setItemId(itemStack);
|
||||
|
||||
original.call(itemRenderer, entity, itemStack, renderPass);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user