Simplify "unlit" quad loading and move to Mixins (#4569)

* Simplified the UV loader concept: We only need it to make quads "unlit" which means that the lighting system is not applied to them. They always render at their full brightness.

* More documentation and slight cleanups.
This commit is contained in:
shartte
2020-08-09 01:27:19 +02:00
committed by GitHub
parent fe753c540b
commit 9456f639d4
66 changed files with 450 additions and 1230 deletions
@@ -0,0 +1,127 @@
package appeng.hooks;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.model.BakedQuad;
import net.minecraft.client.renderer.model.BlockFaceUV;
import net.minecraft.client.renderer.model.BlockPartFace;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.client.renderer.vertex.VertexFormatElement;
import net.minecraft.util.Direction;
import net.minecraft.util.JSONUtils;
import net.minecraft.util.ResourceLocation;
import appeng.core.AppEng;
import appeng.mixins.unlitquad.BakedQuadAccessor;
/**
* Implementation details of allowing quads to be defined as "unlit" in JSON
* models by specifying an "unlit" boolean property on the face.
*/
public class UnlitQuadHooks {
/**
* Offset into the vertex data (which is represented as integers).
*/
private static final int LIGHT_OFFSET = getLightOffset();
// Lightmap texture coordinate with full intensity light leading to no drop in
// brightness
private static final int UNLIT_LIGHT_UV = LightTexture.packLight(15, 15);
/**
* Thread-Local flag to indicate that an enhanced Applied Energistics model is
* currently being deserialized.
*/
private static final ThreadLocal<Boolean> ENABLE_UNLIT_EXTENSIONS = new ThreadLocal<>();
/**
* Notify the unlit model system that a specific model is about to be
* deserialized by {@link net.minecraft.client.renderer.model.ModelBakery}.
*/
public static void beginDeserializingModel(ResourceLocation location) {
String namespace = location.getNamespace();
if (namespace.equals(AppEng.MOD_ID)) {
ENABLE_UNLIT_EXTENSIONS.set(true);
}
}
/**
* Notify the unlit model system that deserialization of a model has ended.
*/
public static void endDeserializingModel() {
ENABLE_UNLIT_EXTENSIONS.set(false);
}
public static boolean isUnlitExtensionEnabled() {
Boolean b = ENABLE_UNLIT_EXTENSIONS.get();
return b != null && b;
}
public static BlockPartFace enhanceModelElementFace(BlockPartFace modelElement, JsonElement jsonElement) {
JsonObject jsonObject = jsonElement.getAsJsonObject();
if (JSONUtils.getBoolean(jsonObject, "unlit", false)) {
return new UnlitBlockPartFace(modelElement.cullFace, modelElement.tintIndex, modelElement.texture,
modelElement.blockFaceUV);
}
return modelElement;
}
/**
* Creates a new quad from the given quad and pre-bakes it to not be affected by
* lighting (neither diffuse lighting nor the prebaked lightmap). This works on
* the assumption that Vanilla will not modify a quad's lightmap data if it's
* not zero.
*/
public static BakedQuad makeUnlit(BakedQuad quad) {
int[] vertexData = quad.getVertexData().clone();
int stride = DefaultVertexFormats.BLOCK.getIntegerSize();
// Set the pre-baked texture coords for the lightmap.
// Vanilla will not overwrite them if they are non-zero
for (int i = 0; i < 4; i++) {
vertexData[stride * i + LIGHT_OFFSET] = UNLIT_LIGHT_UV;
}
TextureAtlasSprite sprite = ((BakedQuadAccessor) quad).getSprite();
// Copy the quad to disable diffuse lighting
return new BakedQuad(vertexData, quad.getTintIndex(), quad.getFace(), sprite, false /* diffuse lighting */);
}
/**
* This subclass is used as a marker to indicate this face deserialized from
* JSON is supposed to be unlit, which translates to processing by
* {@link #makeUnlit(BakedQuad)}.
*/
public static class UnlitBlockPartFace extends BlockPartFace {
public UnlitBlockPartFace(Direction cullFaceIn, int tintIndexIn, String textureIn, BlockFaceUV blockFaceUVIn) {
super(cullFaceIn, tintIndexIn, textureIn, blockFaceUVIn);
}
}
/**
* Find the index in the BakedQuad vertex data (for vertex 0) where the lightmap
* coordinates are. Assumes the BLOCK vertex format.
*/
private static int getLightOffset() {
VertexFormat format = DefaultVertexFormats.BLOCK;
int offset = 0;
for (VertexFormatElement element : format.getElements()) {
// TEX_2SB is the lightmap vertex element
if (element == DefaultVertexFormats.TEX_2SB) {
if (element.getType() != VertexFormatElement.Type.SHORT) {
throw new UnsupportedOperationException("Expected light map format to be of type SHORT");
}
if (offset % 4 != 0) {
throw new UnsupportedOperationException("Expected light map offset to be 4-byte aligned");
}
return offset / 4;
}
offset += element.getSize();
}
throw new UnsupportedOperationException("Failed to find the lightmap index in the block vertex format");
}
}