diff --git a/fabric-item-groups-v0/src/main/resources/assets/fabric/lang/et_ee.json b/fabric-item-groups-v0/src/main/resources/assets/fabric/lang/et_ee.json
new file mode 100644
index 000000000..efa3b18cc
--- /dev/null
+++ b/fabric-item-groups-v0/src/main/resources/assets/fabric/lang/et_ee.json
@@ -0,0 +1,3 @@
+{
+  "fabric.gui.creativeTabPage": "Leht %d/%d"
+}
diff --git a/fabric-mining-levels-v0/src/main/java/net/fabricmc/fabric/api/tools/FabricToolTags.java b/fabric-mining-levels-v0/src/main/java/net/fabricmc/fabric/api/tools/FabricToolTags.java
index f25a74c1b..5fe971d26 100644
--- a/fabric-mining-levels-v0/src/main/java/net/fabricmc/fabric/api/tools/FabricToolTags.java
+++ b/fabric-mining-levels-v0/src/main/java/net/fabricmc/fabric/api/tools/FabricToolTags.java
@@ -24,7 +24,6 @@ import net.minecraft.util.Identifier;
 /**
  * Tool item tags provided by Fabric.
  */
-@Deprecated
 public class FabricToolTags {
 	public static final Tag<Item> AXES = register("axes");
 	public static final Tag<Item> HOES = register("hoes");
diff --git a/fabric-renderer-api-v1/build.gradle b/fabric-renderer-api-v1/build.gradle
index 87695a145..d718c7667 100644
--- a/fabric-renderer-api-v1/build.gradle
+++ b/fabric-renderer-api-v1/build.gradle
@@ -1,5 +1,5 @@
 archivesBaseName = "fabric-renderer-api-v1"
-version = getSubprojectVersion(project, "0.1.0")
+version = getSubprojectVersion(project, "0.1.1")
 
 dependencies {
 	compile project(path: ':fabric-api-base', configuration: 'dev')
diff --git a/fabric-renderer-api-v1/src/main/java/net/fabricmc/fabric/api/renderer/v1/mesh/QuadEmitter.java b/fabric-renderer-api-v1/src/main/java/net/fabricmc/fabric/api/renderer/v1/mesh/QuadEmitter.java
index b9a79af42..71eafe4ff 100644
--- a/fabric-renderer-api-v1/src/main/java/net/fabricmc/fabric/api/renderer/v1/mesh/QuadEmitter.java
+++ b/fabric-renderer-api-v1/src/main/java/net/fabricmc/fabric/api/renderer/v1/mesh/QuadEmitter.java
@@ -21,6 +21,7 @@ import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
 import net.minecraft.client.texture.Sprite;
 import net.minecraft.client.util.math.Vector3f;
 import net.minecraft.util.math.Direction;
+import net.minecraft.util.math.MathHelper;
 
 /**
  * Specialized {@link MutableQuadView} obtained via {@link MeshBuilder#getEmitter()}
@@ -99,17 +100,31 @@ public interface QuadEmitter extends MutableQuadView {
     
     @Override
     QuadEmitter spriteBake(int spriteIndex, Sprite sprite, int bakeFlags);
-
+    
+    /**
+     * Tolerance for determining if the depth parameter to {@link #square(Direction, float, float, float, float, float)} 
+     * is effectively zero - meaning the face is a cull face.
+     */
+    final float CULL_FACE_EPSILON = 0.00001f;
+    
     /**
      * Helper method to assign vertex coordinates for a square aligned with the given face.
      * Ensures that vertex order is consistent with vanilla convention. (Incorrect order can
-     * lead to bad AO lighting.)<p>
+     * lead to bad AO lighting unless enhanced lighting logic is available/enabled.)<p>
      * 
-     * Square will be parallel to the given face and coplanar with the face if depth == 0.
-     * All coordinates are normalized (0-1).
+     * Square will be parallel to the given face and coplanar with the face (and culled if the
+     * face is occluded) if the depth parameter is approximately zero. See {@link #CULL_FACE_EPSILON}.<p>
+     * 
+     * All coordinates should be normalized (0-1).
      */
     default QuadEmitter square(Direction nominalFace, float left, float bottom, float right, float top, float depth) {
-        cullFace(depth == 0 ? nominalFace : null);
+        if(Math.abs(depth) < CULL_FACE_EPSILON) {
+            cullFace(nominalFace);
+            depth = 0; // avoid any inconsistency for face quads
+        } else {
+            cullFace(null);
+        }
+        
         nominalFace(nominalFace);
         switch(nominalFace)
         {
diff --git a/fabric-renderer-indigo/build.gradle b/fabric-renderer-indigo/build.gradle
index 196927bb4..29c10b8cb 100644
--- a/fabric-renderer-indigo/build.gradle
+++ b/fabric-renderer-indigo/build.gradle
@@ -1,5 +1,5 @@
 archivesBaseName = "fabric-renderer-indigo"
-version = getSubprojectVersion(project, "0.1.7")
+version = getSubprojectVersion(project, "0.1.9")
 
 dependencies {
 	compile project(path: ':fabric-api-base', configuration: 'dev')
diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/Indigo.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/Indigo.java
index 0a982840d..c31b6a228 100644
--- a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/Indigo.java
+++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/Indigo.java
@@ -34,13 +34,15 @@ import java.util.Properties;
 
 public class Indigo implements ClientModInitializer {
 	public static final boolean ALWAYS_TESSELATE_INDIGO;
+	public static final boolean ENSURE_VERTEX_FORMAT_COMPATIBILITY;
 	public static final AoConfig AMBIENT_OCCLUSION_MODE;
 	/** Set true in dev env to confirm results match vanilla when they should */
 	public static final boolean DEBUG_COMPARE_LIGHTING;
 	public static final boolean FIX_SMOOTH_LIGHTING_OFFSET;
 	public static final boolean FIX_EXTERIOR_VERTEX_LIGHTING;
-
-	private static final Logger LOGGER = LogManager.getLogger();
+	public static final boolean FIX_LUMINOUS_AO_SHADE;
+	
+	public static final Logger LOGGER = LogManager.getLogger();
 
 	private static boolean asBoolean(String property, boolean defValue) {
 		switch (asTriState(property)) {
@@ -53,7 +55,8 @@ public class Indigo implements ClientModInitializer {
 		}
 	}
 
-	private static <T extends Enum> T asEnum(String property, T defValue) {
+	@SuppressWarnings({ "rawtypes", "unchecked" })
+    private static <T extends Enum> T asEnum(String property, T defValue) {
 		if (property == null || property.isEmpty()) {
 			return defValue;
 		} else {
@@ -102,12 +105,16 @@ public class Indigo implements ClientModInitializer {
 			}
 		}
 
-		ALWAYS_TESSELATE_INDIGO = asBoolean((String) properties.computeIfAbsent("always-tesselate-blocks", (a) -> "auto"), true);
+		final boolean forceCompatibility = IndigoMixinConfigPlugin.shouldForceCompatibility();
+		ENSURE_VERTEX_FORMAT_COMPATIBILITY = forceCompatibility;
+		// necessary because OF alters the BakedModel vertex format and will confuse the fallback model consumer
+		ALWAYS_TESSELATE_INDIGO = !forceCompatibility && asBoolean((String) properties.computeIfAbsent("always-tesselate-blocks", (a) -> "auto"), true);
 		AMBIENT_OCCLUSION_MODE = asEnum((String) properties.computeIfAbsent("ambient-occlusion-mode", (a) -> "hybrid"), AoConfig.HYBRID);
 		DEBUG_COMPARE_LIGHTING = asBoolean((String) properties.computeIfAbsent("debug-compare-lighting", (a) -> "auto"), false);
 		FIX_SMOOTH_LIGHTING_OFFSET = asBoolean((String) properties.computeIfAbsent("fix-smooth-lighting-offset", (a) -> "auto"), true);
 		FIX_EXTERIOR_VERTEX_LIGHTING = asBoolean((String) properties.computeIfAbsent("fix-exterior-vertex-lighting", (a) -> "auto"), true);
-
+		FIX_LUMINOUS_AO_SHADE = asBoolean((String) properties.computeIfAbsent("fix-luminous-block-ambient-occlusion", (a) -> "auto"), false);
+		
 		try (FileOutputStream stream = new FileOutputStream(configFile)) {
 			properties.store(stream, "Indigo properties file");
 		} catch (IOException e) {
@@ -119,6 +126,9 @@ public class Indigo implements ClientModInitializer {
     public void onInitializeClient() {
     	if (IndigoMixinConfigPlugin.shouldApplyIndigo()) {
 		    LOGGER.info("[Indigo] Registering Indigo renderer!");
+		    if(IndigoMixinConfigPlugin.shouldForceCompatibility()) {
+		    	LOGGER.info("[Indigo] Compatibility mode enabled.");
+		    }
 		    RendererAccess.INSTANCE.registerRenderer(IndigoRenderer.INSTANCE);
 	    } else {
     		LOGGER.info("[Indigo] Different rendering plugin detected; not applying Indigo.");
diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/IndigoMixinConfigPlugin.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/IndigoMixinConfigPlugin.java
index e875b296e..de8337017 100644
--- a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/IndigoMixinConfigPlugin.java
+++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/IndigoMixinConfigPlugin.java
@@ -18,6 +18,8 @@ package net.fabricmc.indigo;
 
 import net.fabricmc.loader.api.FabricLoader;
 import net.fabricmc.loader.api.ModContainer;
+import net.fabricmc.loader.api.metadata.ModMetadata;
+
 import org.spongepowered.asm.lib.tree.ClassNode;
 import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
 import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
@@ -26,23 +28,39 @@ import java.util.List;
 import java.util.Set;
 
 public class IndigoMixinConfigPlugin implements IMixinConfigPlugin {
-	private static final String JSON_ELEMENT = "fabric-renderer-api-v1:contains_renderer";
-	private static Boolean indigoApplicable;
+    /** Set by other renderers to disable loading of Indigo */
+	private static final String JSON_KEY_DISABLE_INDIGO = "fabric-renderer-api-v1:contains_renderer";
+	/** Disables vanilla block tesselation and ensures vertex format compatibility */
+	private static final String JSON_KEY_FORCE_COMPATIBILITY = "fabric-renderer-indigo:force_compatibility";
+	
+	private static boolean needsLoad = true;
+	
+	private static boolean indigoApplicable = true;
+	private static boolean forceCompatibility = false;
 
+	private static void loadIfNeeded() {
+	    if(needsLoad) {
+	        for (ModContainer container : FabricLoader.getInstance().getAllMods()) {
+	            final ModMetadata meta = container.getMetadata();
+	            if (meta.containsCustomElement(JSON_KEY_DISABLE_INDIGO)) {
+	                indigoApplicable = false;
+	            } else if (meta.containsCustomElement(JSON_KEY_FORCE_COMPATIBILITY)) {
+	                forceCompatibility = true;
+	            }
+	        }
+	        needsLoad = false;
+	    }
+	}
 	static boolean shouldApplyIndigo() {
-		if (indigoApplicable != null) return indigoApplicable;
-
-		for (ModContainer container : FabricLoader.getInstance().getAllMods()) {
-			if (container.getMetadata().containsCustomElement(JSON_ELEMENT)) {
-				indigoApplicable = false;
-				return false;
-			}
-		}
-
-		indigoApplicable = true;
-		return true;
+	    loadIfNeeded();
+		return indigoApplicable;
 	}
 
+   static boolean shouldForceCompatibility() {
+        loadIfNeeded();
+        return forceCompatibility;
+    }
+	   
 	@Override
 	public void onLoad(String mixinPackage) {
 
diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/accessor/AccessBufferBuilder.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/accessor/AccessBufferBuilder.java
index 82e8b5643..1554aa1b9 100644
--- a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/accessor/AccessBufferBuilder.java
+++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/accessor/AccessBufferBuilder.java
@@ -16,6 +16,8 @@
 
 package net.fabricmc.indigo.renderer.accessor;
 
+import net.fabricmc.indigo.renderer.mesh.QuadViewImpl;
+
 public interface AccessBufferBuilder {
-    void fabric_putVanillaData(int[] data, int start, boolean isItemFormat);
+    void fabric_putQuad(QuadViewImpl quad);
 }
diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/aocalc/AoCalculator.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/aocalc/AoCalculator.java
index ca80ea78b..d0471f907 100644
--- a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/aocalc/AoCalculator.java
+++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/aocalc/AoCalculator.java
@@ -112,31 +112,37 @@ public class AoCalculator {
     
     public void compute(MutableQuadViewImpl quad, boolean isVanilla) {
         final AoConfig config = Indigo.AMBIENT_OCCLUSION_MODE;
-        boolean shouldMatch = false;
+        final boolean shouldCompare;
         
         switch(config) {
         case VANILLA:
             calcVanilla(quad);
+            // no point in comparing vanilla with itself
+            shouldCompare = false;
             break;
             
         case EMULATE:
             calcFastVanilla(quad);
-            shouldMatch = Indigo.DEBUG_COMPARE_LIGHTING && isVanilla;
+            shouldCompare = Indigo.DEBUG_COMPARE_LIGHTING && isVanilla;
             break;
             
+        default:
         case HYBRID:
             if(isVanilla) {
+                shouldCompare = Indigo.DEBUG_COMPARE_LIGHTING;
                 calcFastVanilla(quad);
-                break;
+            } else {
+                shouldCompare = false;
+                calcEnhanced(quad);
             }
-            // else fall through to enhanced
+            break;
         
-        default:
         case ENHANCED:
-            shouldMatch = calcEnhanced(quad);
+            shouldCompare = false;
+            calcEnhanced(quad);
         }
         
-        if (shouldMatch) {
+        if (shouldCompare) {
             float[] vanillaAo = new float[4];
             int[] vanillaLight = new int[4];
             
@@ -178,28 +184,21 @@ public class AoCalculator {
 		}
     }
     
-    /** returns true if should match vanilla results */
-    private boolean calcEnhanced(MutableQuadViewImpl quad) {
+    private void calcEnhanced(MutableQuadViewImpl quad) {
         switch(quad.geometryFlags()) {
             case AXIS_ALIGNED_FLAG | CUBIC_FLAG | LIGHT_FACE_FLAG:
-                vanillaFullFace(quad, true);
-                return Indigo.DEBUG_COMPARE_LIGHTING;
-                
             case AXIS_ALIGNED_FLAG | LIGHT_FACE_FLAG:
                 vanillaPartialFace(quad, true);
-                return Indigo.DEBUG_COMPARE_LIGHTING;
+                break;
                 
             case AXIS_ALIGNED_FLAG | CUBIC_FLAG:
-                blendedFullFace(quad);
-                return false;
-                
             case AXIS_ALIGNED_FLAG:
                 blendedPartialFace(quad);
-                return false;
+                break;
                 
             default:
                 irregularFace(quad);
-                return false;
+                break;
         }
     }
     
@@ -246,11 +245,6 @@ public class AoCalculator {
         }
     }
     
-    private void blendedFullFace(QuadViewImpl quad) {
-        final Direction lightFace = quad.lightFace();
-        blendedInsetFace(quad, 0, lightFace).toArray(ao, light, VERTEX_MAP[lightFace.getId()]);
-    }
-    
     private void blendedPartialFace(QuadViewImpl quad) {
         final Direction lightFace = quad.lightFace();
         AoFaceData faceData = blendedInsetFace(quad, 0, lightFace);
@@ -283,12 +277,15 @@ public class AoCalculator {
                 final AoFaceData fd = gatherInsetFace(quad, i, face);
                 AoFace.get(face).weightFunc.apply(quad, i, w);
                 final float n = x * x;
-                ao += n * fd.weigtedAo(w);
-                sky += n * fd.weigtedSkyLight(w);
-                block += n * fd.weigtedBlockLight(w);
-                maxAo = fd.maxAo(maxAo);
-                maxSky = fd.maxSkyLight(maxSky);
-                maxBlock = fd.maxBlockLight(maxBlock);
+                final float a = fd.weigtedAo(w);
+                final int s = fd.weigtedSkyLight(w);
+                final int b = fd.weigtedBlockLight(w);
+                ao += n * a;
+                sky += n * s;
+                block += n * b;
+                maxAo = a;
+                maxSky = s;
+                maxBlock = b;
             }
             
             final float y = normal.getY();
@@ -297,12 +294,15 @@ public class AoCalculator {
                 final AoFaceData fd = gatherInsetFace(quad, i, face);
                 AoFace.get(face).weightFunc.apply(quad, i, w);
                 final float n = y * y;
-                ao += n * fd.weigtedAo(w);
-                sky += n * fd.weigtedSkyLight(w);
-                block += n * fd.weigtedBlockLight(w);
-                maxAo = fd.maxAo(maxAo);
-                maxSky = fd.maxSkyLight(maxSky);
-                maxBlock = fd.maxBlockLight(maxBlock);
+                final float a = fd.weigtedAo(w);
+                final int s = fd.weigtedSkyLight(w);
+                final int b = fd.weigtedBlockLight(w);
+                ao += n * a;
+                sky += n * s;
+                block += n * b;
+                maxAo = Math.max(maxAo, a);
+                maxSky = Math.max(maxSky, s);
+                maxBlock = Math.max(maxBlock, b);
             }
             
             final float z = normal.getZ();
@@ -311,12 +311,15 @@ public class AoCalculator {
                 final AoFaceData fd = gatherInsetFace(quad, i, face);
                 AoFace.get(face).weightFunc.apply(quad, i, w);
                 final float n = z * z;
-                ao += n * fd.weigtedAo(w);
-                sky += n * fd.weigtedSkyLight(w);
-                block += n * fd.weigtedBlockLight(w);
-                maxAo = fd.maxAo(maxAo);
-                maxSky = fd.maxSkyLight(maxSky);
-                maxBlock = fd.maxBlockLight(maxBlock);
+                final float a = fd.weigtedAo(w);
+                final int s = fd.weigtedSkyLight(w);
+                final int b = fd.weigtedBlockLight(w);
+                ao += n * a;
+                sky += n * s;
+                block += n * b;
+                maxAo = Math.max(maxAo, a);
+                maxSky = Math.max(maxSky, s);
+                maxBlock = Math.max(maxBlock, b);
             }
             
             aoResult[i] = (ao + maxAo) * 0.5f;
diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/aocalc/AoConfig.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/aocalc/AoConfig.java
index 1b41b5152..cc5155f0b 100644
--- a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/aocalc/AoConfig.java
+++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/aocalc/AoConfig.java
@@ -36,8 +36,7 @@ public enum AoConfig {
      * aligned quads not on the block face will have interpolated brightness based
      * on depth instead of the all-or-nothing brightness of vanilla.<p>
      * 
-     * Unit (full face) quads must still have the vanilla fixed winding order but smaller
-     * quads can have vertices in any (counter-clockwise) order.<p>
+     * Non-vanilla quads can have vertices in any (counter-clockwise) order.<p>
      */
     ENHANCED,
     
diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/aocalc/AoFaceData.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/aocalc/AoFaceData.java
index a39a716c8..d19273b4e 100644
--- a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/aocalc/AoFaceData.java
+++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/aocalc/AoFaceData.java
@@ -58,22 +58,10 @@ class AoFaceData {
         return (int) (b0 * w[0] + b1 * w[1] + b2 * w[2] + b3 * w[3]) & 0xFF;
     }
     
-    int maxBlockLight(int oldMax) {
-        final int i = b0 > b1 ? b0 : b1;
-        final int j = b2 > b3 ? b2 : b3;
-        return Math.max(oldMax, i > j ? i : j);
-    }
-    
     int weigtedSkyLight(float[] w) {
         return (int) (s0 * w[0] + s1 * w[1] + s2 * w[2] + s3 * w[3]) & 0xFF;
     }
     
-    int maxSkyLight(int oldMax) {
-        final int i = s0 > s1 ? s0 : s1;
-        final int j = s2 > s3 ? s2 : s3;
-        return Math.max(oldMax, i > j ? i : j);
-    }
-    
     int weightedCombinedLight(float[] w) {
         return weigtedSkyLight(w) << 16 | weigtedBlockLight(w);
     }
@@ -82,13 +70,6 @@ class AoFaceData {
         return a0 * w[0] + a1 * w[1] + a2 * w[2] + a3 * w[3];
     }
     
-    float maxAo(float oldMax) {
-        final float x = a0 > a1 ? a0 : a1;
-        final float y = a2 > a3 ? a2 : a3;
-        final float z =  x > y ? x : y;
-        return oldMax > z ? oldMax : z;
-    }
-    
     void toArray(float[] aOut, int[] bOut, int[] vertexMap) {
         aOut[vertexMap[0]] = a0;
         aOut[vertexMap[1]] = a1;
diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/aocalc/AoLuminanceFix.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/aocalc/AoLuminanceFix.java
new file mode 100644
index 000000000..69b4634d6
--- /dev/null
+++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/aocalc/AoLuminanceFix.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2016, 2017, 2018, 2019 FabricMC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.fabricmc.indigo.renderer.aocalc;
+
+import net.fabricmc.indigo.Indigo;
+import net.minecraft.block.BlockState;
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.world.BlockView;
+
+/**
+ * Implements a fix to prevent luminous blocks from casting AO shade.
+ * Will give normal result if fix is disabled.
+ */
+@FunctionalInterface
+public interface AoLuminanceFix {
+    float apply(BlockView view, BlockPos pos);
+    
+    AoLuminanceFix INSTANCE = Indigo.FIX_LUMINOUS_AO_SHADE ? AoLuminanceFix::fixed : AoLuminanceFix::vanilla;
+    
+    static float vanilla(BlockView view, BlockPos pos) {
+        return view.getBlockState(pos).getAmbientOcclusionLightLevel(view, pos);
+    }
+    
+    static float fixed(BlockView view, BlockPos pos) {
+        final BlockState state = view.getBlockState(pos);
+        return state.getLuminance() == 0 ? state.getAmbientOcclusionLightLevel(view, pos) : 1f;
+    }
+}
diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/helper/BufferBuilderTransformHelper.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/helper/BufferBuilderTransformHelper.java
deleted file mode 100644
index 8102a77c4..000000000
--- a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/helper/BufferBuilderTransformHelper.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (c) 2016, 2017, 2018, 2019 FabricMC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.fabricmc.indigo.renderer.helper;
-
-import com.google.common.collect.Sets;
-import it.unimi.dsi.fastutil.objects.Object2IntMap;
-import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
-import net.minecraft.client.render.VertexFormat;
-import net.minecraft.client.render.VertexFormatElement;
-import net.minecraft.client.render.VertexFormats;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-
-public class BufferBuilderTransformHelper {
-	/**
-	 * Fast copying mode; used only if the vanilla format is an exact match.
-	 */
-	public static final int MODE_COPY_FAST = 0;
-
-	/**
-	 * Padded copying mode; used when the vanilla format is an exact match,
-	 * but includes additional data at the end. Will emit a warning.
-	 */
-	public static final int MODE_COPY_PADDED = 1;
-
-	/**
-	 * ShadersMod compatibility mode; as MODE_COPY_PADDED, but populates in
-	 * the correct normal values as provided by the mod.
-	 *
-	 * Assumes a format of [vertex, color, texture, lmap, normal], all in
-	 * their respective vanilla formats, plus any amount of additional data
-	 * afterwards.
-	 */
-	public static final int MODE_COPY_PADDED_SHADERSMOD = 2;
-
-	/**
-	 * Unsupported mode; an error will be emitted and no quads will be
-	 * pushed to the buffer builder.
-	 */
-	public static final int MODE_UNSUPPORTED = 3;
-
-	private static final Map<VertexFormat, Integer> vertexFormatCache = new ConcurrentHashMap<>();
-	private static final Set<VertexFormat> errorEmittedFormats = Sets.newConcurrentHashSet();
-	private static final Logger logger = LogManager.getLogger();
-
-	public static void emitUnsupportedError(VertexFormat format) {
-		// This can be slow, as it's only called on unsupported formats - which is already an error condition.
-		if (errorEmittedFormats.add(format)) {
-			logger.error("[Indigo] Unsupported vertex format! " + format);
-		}
-	}
-
-	private static int computeProcessingMode(VertexFormat f) {
-		if (
-			f.getElementCount() >= 4 && f.getVertexSizeInteger() >= 7
-				&& f.getElement(0).equals(VertexFormats.POSITION_ELEMENT)
-				&& f.getElement(1).equals(VertexFormats.COLOR_ELEMENT)
-				&& f.getElement(2).equals(VertexFormats.UV_ELEMENT)
-		) {
-			if (
-				f.getElement(3).equals(VertexFormats.LMAP_ELEMENT)
-					|| f.getElement(3).equals(VertexFormats.NORMAL_ELEMENT)
-			) {
-				if (
-					f.getElementCount() >= 5
-						&& f.getElement(3).equals(VertexFormats.LMAP_ELEMENT)
-						&& f.getElement(4).equals(VertexFormats.NORMAL_ELEMENT)
-				) {
-					logger.debug("[Indigo] Classified format as ShadersMod-compatible: " + f);
-					return MODE_COPY_PADDED_SHADERSMOD;
-				} else if (f.getElementCount() == 4) {
-					logger.debug("[Indigo] Classified format as vanilla-like: " + f);
-					return MODE_COPY_FAST;
-				} else {
-					logger.debug("[Indigo] Unsupported but likely vanilla-compliant vertex format. " + f);
-					return MODE_COPY_PADDED;
-				}
-			}
-		}
-
-		return MODE_UNSUPPORTED;
-	}
-
-	public static int getProcessingMode(VertexFormat format) {
-		// Fast passthrough for the most common vanilla block/item formats.
-		if (format == VertexFormats.POSITION_COLOR_UV_LMAP || format == VertexFormats.POSITION_COLOR_UV_NORMAL) {
-			return MODE_COPY_FAST;
-		} else {
-			Integer cached = vertexFormatCache.get(format);
-
-			if (cached == null) {
-				// VertexFormats are mutable, so we need to make an immutable copy.
-				format = new VertexFormat(format);
-				cached = computeProcessingMode(format);
-				vertexFormatCache.put(format, cached);
-			}
-
-			return cached;
-		}
-	}
-}
diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/mesh/MeshBuilderImpl.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/mesh/MeshBuilderImpl.java
index a3f8c82e4..1ad88977e 100644
--- a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/mesh/MeshBuilderImpl.java
+++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/mesh/MeshBuilderImpl.java
@@ -50,6 +50,7 @@ public class MeshBuilderImpl implements MeshBuilder {
         int[] packed = new int[index];
         System.arraycopy(data, 0, packed, 0, index);
         index = 0;
+        maker.begin(data, index);
         return new MeshImpl(packed);
     }
 
diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/mixin/MixinBufferBuilder.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/mixin/MixinBufferBuilder.java
index cc25fd06d..da1e9a4af 100644
--- a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/mixin/MixinBufferBuilder.java
+++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/mixin/MixinBufferBuilder.java
@@ -18,18 +18,15 @@ package net.fabricmc.indigo.renderer.mixin;
 
 import java.nio.IntBuffer;
 
-import net.fabricmc.indigo.Indigo;
-import net.fabricmc.indigo.renderer.helper.BufferBuilderTransformHelper;
-import net.fabricmc.indigo.renderer.mesh.EncodingFormat;
-import net.minecraft.client.render.VertexFormat;
 import org.spongepowered.asm.mixin.Mixin;
 import org.spongepowered.asm.mixin.Shadow;
 
+import net.fabricmc.indigo.Indigo;
 import net.fabricmc.indigo.renderer.accessor.AccessBufferBuilder;
+import net.fabricmc.indigo.renderer.mesh.QuadViewImpl;
 import net.minecraft.client.render.BufferBuilder;
-import org.spongepowered.asm.mixin.injection.At;
-import org.spongepowered.asm.mixin.injection.Inject;
-import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+import net.minecraft.client.render.VertexFormat;
+import net.minecraft.client.render.VertexFormatElement;
 
 @Mixin(BufferBuilder.class)
 public abstract class MixinBufferBuilder implements AccessBufferBuilder {
@@ -40,73 +37,71 @@ public abstract class MixinBufferBuilder implements AccessBufferBuilder {
     @Shadow public abstract VertexFormat getVertexFormat();
 
 	private static final int VERTEX_STRIDE_INTS = 7;
-	private static final int VERTEX_STRIDE_BYTES = VERTEX_STRIDE_INTS * 4;
     private static final int QUAD_STRIDE_INTS = VERTEX_STRIDE_INTS * 4;
     private static final int QUAD_STRIDE_BYTES = QUAD_STRIDE_INTS * 4;
 
-    private int fabric_processingMode;
+    @Override
+    public void fabric_putQuad(QuadViewImpl quad) {
+        if(Indigo.ENSURE_VERTEX_FORMAT_COMPATIBILITY) {
+            bufferCompatibly(quad);
+        } else {
+            bufferFast(quad);
+        }
+    }
 
-    @Inject(at = @At("RETURN"), method = "begin")
-	private void afterBegin(int mode, VertexFormat passedFormat, CallbackInfo info) {
-    	fabric_processingMode = BufferBuilderTransformHelper.getProcessingMode(getVertexFormat());
-	}
+    private void bufferFast(QuadViewImpl quad) {
+        grow(QUAD_STRIDE_BYTES);
+        bufInt.position(getCurrentSize());
+        bufInt.put(quad.data(), quad.vertexStart(), QUAD_STRIDE_INTS);
+        vertexCount += 4;
+    }
 
     /**
-     * Similar to {@link BufferBuilder#putVertexData(int[])} but
-     * accepts an array index so that arrays containing more than one
-     * quad don't have to be copied to a transfer array before the call.
-	 *
-	 * It also always assumes the vanilla data format and is capable of
-	 * transforming data from it to a different, non-vanilla data format.
+     * Uses buffer vertex format to drive buffer population.
+     * Relies on logic elsewhere to ensure coordinates don't include chunk offset
+     * (because buffer builder will handle that.)<p>
+     * 
+     * Calling putVertexData() would likely be a little faster but this approach
+     * gives us a chance to pass vertex normals to shaders, which isn't possible
+     * with the standard block format. It also doesn't require us to encode a specific
+     * custom format directly, which would be prone to breakage outside our control. 
      */
-    @Override
-    public void fabric_putVanillaData(int[] data, int start, boolean isItemFormat) {
-    	switch (fabric_processingMode) {
-			case BufferBuilderTransformHelper.MODE_COPY_FAST: {
-				this.grow(QUAD_STRIDE_BYTES);
-				this.bufInt.position(this.getCurrentSize());
-				this.bufInt.put(data, start, QUAD_STRIDE_INTS);
-			} break;
-			case BufferBuilderTransformHelper.MODE_COPY_PADDED: {
-				int currSize = this.getCurrentSize();
-				int formatSizeBytes = getVertexFormat().getVertexSize();
-				int formatSizeInts = formatSizeBytes / 4;
-				this.grow(formatSizeBytes * 4);
+    private void bufferCompatibly(QuadViewImpl quad) {
+        final VertexFormat format = getVertexFormat();;
+        final int elementCount = format.getElementCount();
+        for(int i = 0; i < 4; i++) {
+            for(int j = 0; j < elementCount; j++) {
+                VertexFormatElement e = format.getElement(j);
+                switch(e.getType()) {
+                case COLOR:
+                    final int c = quad.spriteColor(i, 0);
+                    ((BufferBuilder)(Object)this).color(c & 0xFF, (c >>> 8) & 0xFF, (c >>> 16) & 0xFF, (c >>> 24) & 0xFF);
+                    break;
+                case NORMAL:
+                    ((BufferBuilder)(Object)this).normal(quad.normalX(i), quad.normalY(i), quad.normalZ(i));
+                    break;
+                case POSITION:
+                    ((BufferBuilder)(Object)this).vertex(quad.x(i), quad.y(i), quad.z(i));
+                    break;
+                case UV:
+                    if(e.getIndex() == 0) {
+                        ((BufferBuilder)(Object)this).texture(quad.spriteU(i, 0), quad.spriteV(i, 0));
+                    } else {
+                        final int b = quad.lightmap(i);
+                        ((BufferBuilder)(Object)this).texture((b >> 16) & 0xFFFF, b & 0xFFFF);
+                    }
+                    break;
 
-				this.bufInt.position(currSize);
-				this.bufInt.put(data, start, VERTEX_STRIDE_INTS);
-				this.bufInt.position(currSize + formatSizeInts);
-				this.bufInt.put(data, start + 7, VERTEX_STRIDE_INTS);
-				this.bufInt.position(currSize + formatSizeInts * 2);
-				this.bufInt.put(data, start + 14, VERTEX_STRIDE_INTS);
-				this.bufInt.position(currSize + formatSizeInts * 3);
-				this.bufInt.put(data, start + 21, VERTEX_STRIDE_INTS);
-			} break;
-    		case BufferBuilderTransformHelper.MODE_COPY_PADDED_SHADERSMOD: {
-				int currSize = this.getCurrentSize();
-				int formatSizeBytes = getVertexFormat().getVertexSize();
-				int formatSizeInts = formatSizeBytes / 4;
-				this.grow(formatSizeBytes * 4);
+                // these types should never occur and/or require no action
+                case MATRIX:
+                case BLEND_WEIGHT:
+                case PADDING:
+                default:
+                    break;
 
-				this.bufInt.position(currSize);
-				this.bufInt.put(data, start, VERTEX_STRIDE_INTS);
-				this.bufInt.put(data[start + EncodingFormat.NORMALS_OFFSET_VANILLA]);
-				this.bufInt.position(currSize + formatSizeInts);
-				this.bufInt.put(data, start + 7, VERTEX_STRIDE_INTS);
-				this.bufInt.put(data[start + EncodingFormat.NORMALS_OFFSET_VANILLA + 1]);
-				this.bufInt.position(currSize + formatSizeInts * 2);
-				this.bufInt.put(data, start + 14, VERTEX_STRIDE_INTS);
-				this.bufInt.put(data[start + EncodingFormat.NORMALS_OFFSET_VANILLA + 2]);
-				this.bufInt.position(currSize + formatSizeInts * 3);
-				this.bufInt.put(data, start + 21, VERTEX_STRIDE_INTS);
-				this.bufInt.put(data[start + EncodingFormat.NORMALS_OFFSET_VANILLA + 3]);
-			} break;
-    		case BufferBuilderTransformHelper.MODE_UNSUPPORTED:
-    			// Don't emit any quads.
-				BufferBuilderTransformHelper.emitUnsupportedError(getVertexFormat());
-    			return;
-		}
-
-		this.vertexCount += 4;
+                }
+            }
+            ((BufferBuilder)(Object)this).next();
+        }
     }
 }
diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/AbstractMeshConsumer.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/AbstractMeshConsumer.java
index 276f43808..1aadb2e7c 100644
--- a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/AbstractMeshConsumer.java
+++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/AbstractMeshConsumer.java
@@ -28,6 +28,8 @@ import net.fabricmc.indigo.renderer.RenderMaterialImpl.Value;
 import net.fabricmc.indigo.renderer.IndigoRenderer;
 import net.fabricmc.indigo.renderer.accessor.AccessBufferBuilder;
 import net.fabricmc.indigo.renderer.aocalc.AoCalculator;
+import net.fabricmc.indigo.renderer.helper.ColorHelper;
+import net.fabricmc.indigo.renderer.helper.GeometryHelper;
 import net.fabricmc.indigo.renderer.mesh.EncodingFormat;
 import net.fabricmc.indigo.renderer.mesh.MeshImpl;
 import net.fabricmc.indigo.renderer.mesh.MutableQuadViewImpl;
@@ -57,6 +59,8 @@ public abstract class AbstractMeshConsumer extends AbstractQuadRenderer implemen
         // only used via RenderContext.getEmitter() 
         @Override
         public Maker emit() {
+            lightFace = GeometryHelper.lightFace(this);
+            ColorHelper.applyDiffuseShading(this, false);
             renderQuad(this);
             clear();
             return this;
diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/AbstractQuadRenderer.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/AbstractQuadRenderer.java
index 8c3ef17fa..7fa9e4dc0 100644
--- a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/AbstractQuadRenderer.java
+++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/AbstractQuadRenderer.java
@@ -69,7 +69,7 @@ public abstract class AbstractQuadRenderer {
     
     /** final output step, common to all renders */
     private void bufferQuad(MutableQuadViewImpl quad, int renderLayer) {
-        bufferFunc.get(renderLayer).fabric_putVanillaData(quad.data(), quad.vertexStart(), false);
+        bufferFunc.get(renderLayer).fabric_putQuad(quad);
     }
 
     // routines below have a bit of copy-paste code reuse to avoid conditional execution inside a hot loop
diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/BlockRenderContext.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/BlockRenderContext.java
index 5bb0d0275..b12f810ad 100644
--- a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/BlockRenderContext.java
+++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/BlockRenderContext.java
@@ -27,6 +27,7 @@ import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel;
 import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
 import net.fabricmc.indigo.renderer.accessor.AccessBufferBuilder;
 import net.fabricmc.indigo.renderer.aocalc.AoCalculator;
+import net.fabricmc.indigo.renderer.aocalc.AoLuminanceFix;
 import net.fabricmc.indigo.renderer.mesh.MutableQuadViewImpl;
 import net.fabricmc.indigo.renderer.mixin.BufferBuilderOffsetAccessor;
 import net.minecraft.block.BlockState;
@@ -67,10 +68,7 @@ public class BlockRenderContext extends AbstractRenderContext implements RenderC
 
     private float aoLevel(BlockPos pos) {
         final ExtendedBlockView blockView = blockInfo.blockView;
-        if(blockView == null) {
-            return 1f;
-        }
-        return blockView.getBlockState(pos).getAmbientOcclusionLightLevel(blockView, pos);
+        return blockView == null ? 1f : AoLuminanceFix.INSTANCE.apply(blockView, pos);
     }
     
     private AccessBufferBuilder outputBuffer(int renderLayer) {
diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/ChunkRenderInfo.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/ChunkRenderInfo.java
index 2ffa5951b..26e83c133 100644
--- a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/ChunkRenderInfo.java
+++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/ChunkRenderInfo.java
@@ -18,8 +18,10 @@ package net.fabricmc.indigo.renderer.render;
 
 import it.unimi.dsi.fastutil.longs.Long2FloatOpenHashMap;
 import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap;
+import net.fabricmc.indigo.Indigo;
 import net.fabricmc.indigo.renderer.accessor.AccessBufferBuilder;
 import net.fabricmc.indigo.renderer.accessor.AccessChunkRenderer;
+import net.fabricmc.indigo.renderer.aocalc.AoLuminanceFix;
 import net.fabricmc.indigo.renderer.mesh.MutableQuadViewImpl;
 import net.minecraft.block.Block.OffsetType;
 import net.minecraft.block.BlockRenderLayer;
@@ -67,6 +69,7 @@ public class ChunkRenderInfo {
     private final Long2FloatOpenHashMap aoLevelCache;
     
     private final BlockRenderInfo blockInfo;
+    private final BlockPos.Mutable chunkOrigin = new BlockPos.Mutable();
     ChunkRenderTask chunkTask; 
     ChunkRenderData chunkData;
     ChunkRenderer chunkRenderer;
@@ -102,6 +105,7 @@ public class ChunkRenderInfo {
     }
     
     void prepare(ChunkRenderer chunkRenderer, BlockPos.Mutable chunkOrigin, boolean [] resultFlags) {
+        this.chunkOrigin.set(chunkOrigin);
         this.chunkData = chunkTask.getRenderData();
         this.chunkRenderer = chunkRenderer;
         this.resultFlags = resultFlags;
@@ -129,10 +133,19 @@ public class ChunkRenderInfo {
     void beginBlock() {
         final BlockState blockState = blockInfo.blockState;
         final BlockPos blockPos = blockInfo.blockPos;
-        offsetX = (float) (chunkOffsetX + blockPos.getX());
-        offsetY = (float) (chunkOffsetY + blockPos.getY());
-        offsetZ = (float) (chunkOffsetZ + blockPos.getZ());
-
+        
+        // When we are using the BufferBuilder input methods, the builder will
+        // add the chunk offset for us, so we should only apply the block offset.
+        if(Indigo.ENSURE_VERTEX_FORMAT_COMPATIBILITY) {
+            offsetX = (float) (blockPos.getX());
+            offsetY = (float) (blockPos.getY());
+            offsetZ = (float) (blockPos.getZ());
+        } else {
+            offsetX = (float) (chunkOffsetX + blockPos.getX());
+            offsetY = (float) (chunkOffsetY + blockPos.getY());
+            offsetZ = (float) (chunkOffsetZ + blockPos.getZ());
+        }
+        
         if(blockState.getBlock().getOffsetType() != OffsetType.NONE) {
             Vec3d offset = blockState.getOffsetPos(blockInfo.blockView, blockPos);
             offsetX += (float)offset.x;
@@ -153,7 +166,7 @@ public class ChunkRenderInfo {
             BlockRenderLayer layer = LAYERS[layerIndex];
             if (!chunkData.isBufferInitialized(layer)) {
                 chunkData.markBufferInitialized(layer); // start buffer
-                ((AccessChunkRenderer) chunkRenderer).fabric_beginBufferBuilding(builder, blockInfo.blockPos);
+                ((AccessChunkRenderer) chunkRenderer).fabric_beginBufferBuilding(builder, chunkOrigin);
             }
             result = (AccessBufferBuilder) builder;
         }
@@ -188,7 +201,7 @@ public class ChunkRenderInfo {
         long key = pos.asLong();
         float result = aoLevelCache.get(key);
         if (result == Float.MAX_VALUE) {
-            result = blockView.getBlockState(pos).getAmbientOcclusionLightLevel(blockView, pos);
+            result = AoLuminanceFix.INSTANCE.apply(blockView, pos);
             aoLevelCache.put(key, result);
         }
         return result;
diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/ItemRenderContext.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/ItemRenderContext.java
index feeadd75e..e5dce89b8 100644
--- a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/ItemRenderContext.java
+++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/ItemRenderContext.java
@@ -33,6 +33,7 @@ import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
 import net.fabricmc.indigo.renderer.RenderMaterialImpl;
 import net.fabricmc.indigo.renderer.accessor.AccessBufferBuilder;
 import net.fabricmc.indigo.renderer.helper.ColorHelper;
+import net.fabricmc.indigo.renderer.helper.GeometryHelper;
 import net.fabricmc.indigo.renderer.mesh.EncodingFormat;
 import net.fabricmc.indigo.renderer.mesh.MeshImpl;
 import net.fabricmc.indigo.renderer.mesh.MutableQuadViewImpl;
@@ -127,6 +128,8 @@ public class ItemRenderContext extends AbstractRenderContext implements RenderCo
         
         @Override
         public Maker emit() {
+            lightFace = GeometryHelper.lightFace(this);
+            ColorHelper.applyDiffuseShading(this, false);
             renderQuad();
             clear();
             return this;
@@ -168,7 +171,7 @@ public class ItemRenderContext extends AbstractRenderContext implements RenderCo
     private int quadColor() {
         final int colorIndex = editorQuad.colorIndex();
         int quadColor = color;
-        if (!enchantment && quadColor == -1 && colorIndex != 1) {
+        if (!enchantment && quadColor == -1 && colorIndex != -1) {
             quadColor = colorMap.getColorMultiplier(itemStack, colorIndex);
             quadColor |= -16777216;
          }
@@ -182,7 +185,7 @@ public class ItemRenderContext extends AbstractRenderContext implements RenderCo
             c = ColorHelper.multiplyColor(quadColor, c);
             q.spriteColor(i, 0, ColorHelper.swapRedBlueIfNeeded(c));
         }
-        fabricBuffer.fabric_putVanillaData(quadData, EncodingFormat.VERTEX_START_OFFSET, true);
+        fabricBuffer.fabric_putQuad(q);
     }
     
     private void renderQuad() {
diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/TerrainFallbackConsumer.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/TerrainFallbackConsumer.java
index afb08c7cb..55e51811c 100644
--- a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/TerrainFallbackConsumer.java
+++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/TerrainFallbackConsumer.java
@@ -25,6 +25,7 @@ import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter;
 import net.fabricmc.fabric.api.renderer.v1.model.ModelHelper;
 import net.fabricmc.fabric.api.renderer.v1.render.RenderContext.QuadTransform;
 import net.fabricmc.indigo.renderer.RenderMaterialImpl.Value;
+import net.fabricmc.indigo.Indigo;
 import net.fabricmc.indigo.renderer.IndigoRenderer;
 import net.fabricmc.indigo.renderer.aocalc.AoCalculator;
 import net.fabricmc.indigo.renderer.helper.GeometryHelper;
@@ -58,6 +59,20 @@ public class TerrainFallbackConsumer extends AbstractQuadRenderer implements Con
     private static Value MATERIAL_FLAT = (Value) IndigoRenderer.INSTANCE.materialFinder().disableAo(0, true).find();
     private static Value MATERIAL_SHADED = (Value) IndigoRenderer.INSTANCE.materialFinder().find();
     
+    /**
+     * Controls 1x warning for vanilla quad vertex format when running in compatibility mode.
+     */
+    private static boolean logCompatibilityWarning = true;
+    
+    private static boolean isCompatible(int[] vertexData) {
+    	final boolean result = vertexData.length == 28;
+    	if(!result && logCompatibilityWarning) {
+    		logCompatibilityWarning = false;
+			Indigo.LOGGER.warn("[Indigo] Encountered baked quad with non-standard vertex format. Some blocks will not be rendered");
+    	}
+    	return result;
+    }
+    
     private final int[] editorBuffer = new int[28];
     private final ChunkRenderInfo chunkInfo;
     
@@ -109,8 +124,13 @@ public class TerrainFallbackConsumer extends AbstractQuadRenderer implements Con
     }
     
     private void renderQuad(BakedQuad quad, Direction cullFace, Value defaultMaterial) {
+        final int[] vertexData = quad.getVertexData();
+        if(Indigo.ENSURE_VERTEX_FORMAT_COMPATIBILITY && !isCompatible(vertexData)) {
+        	return;
+        }
+        
         final MutableQuadViewImpl editorQuad = this.editorQuad;
-        System.arraycopy(quad.getVertexData(), 0, editorBuffer, 0, 28);
+        System.arraycopy(vertexData, 0, editorBuffer, 0, 28);
         editorQuad.cullFace(cullFace);
         final Direction lightFace = quad.getFace();
         editorQuad.lightFace(lightFace);
diff --git a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/TerrainRenderContext.java b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/TerrainRenderContext.java
index a71f3df3f..e98fee10c 100644
--- a/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/TerrainRenderContext.java
+++ b/fabric-renderer-indigo/src/main/java/net/fabricmc/indigo/renderer/render/TerrainRenderContext.java
@@ -24,8 +24,6 @@ import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel;
 import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
 import net.fabricmc.indigo.renderer.aocalc.AoCalculator;
 import net.minecraft.block.BlockState;
-import net.minecraft.client.MinecraftClient;
-import net.minecraft.client.render.block.BlockRenderManager;
 import net.minecraft.client.render.chunk.ChunkRenderTask;
 import net.minecraft.client.render.chunk.ChunkRenderer;
 import net.minecraft.client.render.chunk.ChunkRendererRegion;
@@ -34,7 +32,6 @@ import net.minecraft.util.crash.CrashException;
 import net.minecraft.util.crash.CrashReport;
 import net.minecraft.util.crash.CrashReportSection;
 import net.minecraft.util.math.BlockPos;
-import net.minecraft.world.ExtendedBlockView;
 
 /**
  * Implementation of {@link RenderContext} used during terrain rendering.
@@ -48,7 +45,6 @@ public class TerrainRenderContext extends AbstractRenderContext implements Rende
     private final AoCalculator aoCalc = new AoCalculator(blockInfo, chunkInfo::cachedBrightness, chunkInfo::cachedAoLevel);
     private final TerrainMeshConsumer meshConsumer = new TerrainMeshConsumer(blockInfo, chunkInfo, aoCalc, this::transform);
     private final TerrainFallbackConsumer fallbackConsumer = new TerrainFallbackConsumer(blockInfo, chunkInfo, aoCalc, this::transform);
-    private final BlockRenderManager blockRenderManager = MinecraftClient.getInstance().getBlockRenderManager();
     
     public void setBlockView(ChunkRendererRegion blockView) {
         blockInfo.setBlockView(blockView);