diff --git a/changelog.txt b/changelog.txt index 5efc1aa0b..ccd0e4240 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,13 @@ +0.5.1: +Fixes + - Fix crash on resource reload with backend off + - Fix artifacts while using Optifine shaders + - Fix crash when trying to access biomes in a VirtualRenderWorld +Technical/API + - Refactor instance renderer registration to separate client and server logic (thanks Pepper!) + - VirtualRenderWorlds now have a "biomeOffset" field which gets added when looking up biomes + - Added GlStateTracker which hooks into GlStateManager to track changes in buffer, vertex array, and program bindings + 0.5.0a: Fixes - Address crash experienced by some users while rendering any tile. diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/GlStateTracker.java b/src/main/java/com/jozufozu/flywheel/backend/gl/GlStateTracker.java new file mode 100644 index 000000000..eec0a4cf8 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/gl/GlStateTracker.java @@ -0,0 +1,62 @@ +package com.jozufozu.flywheel.backend.gl; + +import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType; +import com.mojang.blaze3d.platform.GlStateManager; + +/** + * Tracks bound buffers/vbos because GlStateManager doesn't do that for us. + */ +public class GlStateTracker { + + private static final int[] buffers = new int[GlBufferType.values().length]; + private static int vao; + private static int program; + + public static int getBuffer(GlBufferType type) { + return buffers[type.ordinal()]; + } + + public static int getVertexArray() { + return vao; + } + + public static int getProgram() { + return program; + } + + public static void _setBuffer(GlBufferType type, int buffer) { + buffers[type.ordinal()] = buffer; + } + + public static void _setProgram(int id) { + program = id; + } + + public static void _setVertexArray(int id) { + vao = id; + } + + public static State getRestoreState() { + return new State(buffers.clone(), vao, program); + } + + public static record State(int[] buffers, int vao, int program) { + public void restore() { + GlBufferType[] values = GlBufferType.values(); + + for (int i = 0; i < values.length; i++) { + if (buffers[i] != GlStateTracker.buffers[i]) { + GlStateManager._glBindBuffer(values[i].glEnum, buffers[i]); + } + } + + if (vao != GlStateTracker.vao) { + GlStateManager._glBindVertexArray(vao); + } + + if (program != GlStateTracker.program) { + GlStateManager._glUseProgram(program); + } + } + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/GlVertexArray.java b/src/main/java/com/jozufozu/flywheel/backend/gl/GlVertexArray.java index 44541854c..d757cfbb8 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/GlVertexArray.java +++ b/src/main/java/com/jozufozu/flywheel/backend/gl/GlVertexArray.java @@ -4,7 +4,6 @@ import org.lwjgl.opengl.GL20; import com.jozufozu.flywheel.core.layout.BufferLayout; import com.jozufozu.flywheel.core.layout.LayoutItem; -import com.jozufozu.flywheel.mixin.BufferUploaderAccessor; import com.mojang.blaze3d.platform.GlStateManager; public class GlVertexArray extends GlObject { @@ -14,20 +13,14 @@ public class GlVertexArray extends GlObject { public static void bind(int vao) { GlStateManager._glBindVertexArray(vao); - BufferUploaderAccessor.flywheel$setLastVAO(vao); } public void bind() { bind(handle()); } - public static int getBoundVertexArray() { - return BufferUploaderAccessor.flywheel$getLastVAO(); - } - public static void unbind() { GlStateManager._glBindVertexArray(0); - BufferUploaderAccessor.flywheel$setLastVAO(0); } public void enableArrays(int count) { diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/GlBufferType.java b/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/GlBufferType.java index 16f0c450a..776ed6328 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/GlBufferType.java +++ b/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/GlBufferType.java @@ -8,7 +8,7 @@ import org.lwjgl.opengl.GL40; import org.lwjgl.opengl.GL42; import org.lwjgl.opengl.GL43; -import com.jozufozu.flywheel.mixin.BufferUploaderAccessor; +import com.jozufozu.flywheel.backend.gl.GlStateTracker; import com.mojang.blaze3d.platform.GlStateManager; public enum GlBufferType { @@ -33,29 +33,34 @@ public enum GlBufferType { this.glEnum = glEnum; } - public void bind(int buffer) { - GlStateManager._glBindBuffer(glEnum, buffer); + public static GlBufferType fromTarget(int pTarget) { + return switch (pTarget) { + case GL15C.GL_ARRAY_BUFFER -> ARRAY_BUFFER; + case GL15C.GL_ELEMENT_ARRAY_BUFFER -> ELEMENT_ARRAY_BUFFER; + case GL21.GL_PIXEL_PACK_BUFFER -> PIXEL_PACK_BUFFER; + case GL21.GL_PIXEL_UNPACK_BUFFER -> PIXEL_UNPACK_BUFFER; + case GL30.GL_TRANSFORM_FEEDBACK_BUFFER -> TRANSFORM_FEEDBACK_BUFFER; + case GL31.GL_UNIFORM_BUFFER -> UNIFORM_BUFFER; + case GL31.GL_TEXTURE_BUFFER -> TEXTURE_BUFFER; + case GL31.GL_COPY_READ_BUFFER -> COPY_READ_BUFFER; + case GL31.GL_COPY_WRITE_BUFFER -> COPY_WRITE_BUFFER; + case GL40.GL_DRAW_INDIRECT_BUFFER -> DRAW_INDIRECT_BUFFER; + case GL42.GL_ATOMIC_COUNTER_BUFFER -> ATOMIC_COUNTER_BUFFER; + case GL43.GL_DISPATCH_INDIRECT_BUFFER -> DISPATCH_INDIRECT_BUFFER; + case GL43.GL_SHADER_STORAGE_BUFFER -> SHADER_STORAGE_BUFFER; + default -> throw new IllegalArgumentException("Unknown target: " + pTarget); + }; + } - switch (this.glEnum) { - case GL15C.GL_ELEMENT_ARRAY_BUFFER -> BufferUploaderAccessor.flywheel$setLastEBO(buffer); - case GL15C.GL_ARRAY_BUFFER -> BufferUploaderAccessor.flywheel$setLastVBO(buffer); - } + public void bind(int buffer) { + GlStateManager._glBindBuffer(glEnum, buffer); } public void unbind() { GlStateManager._glBindBuffer(glEnum, 0); - - switch (this.glEnum) { - case GL15C.GL_ELEMENT_ARRAY_BUFFER -> BufferUploaderAccessor.flywheel$setLastEBO(0); - case GL15C.GL_ARRAY_BUFFER -> BufferUploaderAccessor.flywheel$setLastVBO(0); - } } public int getBoundBuffer() { - return switch (this.glEnum) { - case GL15C.GL_ELEMENT_ARRAY_BUFFER -> BufferUploaderAccessor.flywheel$getLastEBO(); - case GL15C.GL_ARRAY_BUFFER -> BufferUploaderAccessor.flywheel$getLastVBO(); - default -> -1; - }; + return GlStateTracker.getBuffer(this); } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlProgram.java b/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlProgram.java index c73a5f428..465766adb 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlProgram.java +++ b/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlProgram.java @@ -13,7 +13,6 @@ import org.lwjgl.system.MemoryStack; import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.gl.GlObject; -import com.jozufozu.flywheel.mixin.ShaderInstanceAccessor; import com.mojang.blaze3d.shaders.ProgramManager; import com.mojang.math.Matrix4f; @@ -31,14 +30,11 @@ public abstract class GlProgram extends GlObject { } public void bind() { - int handle = handle(); - ProgramManager.glUseProgram(handle); - ShaderInstanceAccessor.flywheel$setLastProgramId(handle); + ProgramManager.glUseProgram(handle()); } - public void unbind() { + public static void unbind() { ProgramManager.glUseProgram(0); - ShaderInstanceAccessor.flywheel$setLastProgramId(0); } /** diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancingEngine.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancingEngine.java index 37f4669b0..c7848e19a 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancingEngine.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancingEngine.java @@ -3,6 +3,7 @@ package com.jozufozu.flywheel.backend.instancing.instancing; import java.util.EnumMap; import java.util.HashMap; import java.util.Map; +import java.util.function.Supplier; import java.util.stream.Stream; import javax.annotation.Nullable; @@ -23,6 +24,7 @@ import net.minecraft.client.Camera; import net.minecraft.client.renderer.RenderType; import net.minecraft.core.BlockPos; import net.minecraft.core.Vec3i; +import net.minecraft.resources.ResourceLocation; import net.minecraft.util.Mth; public class InstancingEngine

implements Engine { @@ -73,10 +75,6 @@ public class InstancingEngine

implements Engine { */ @Override public void render(TaskEngine taskEngine, RenderLayerEvent event) { - int ebo = GlBufferType.ELEMENT_ARRAY_BUFFER.getBoundBuffer(); - int vbo = GlBufferType.ARRAY_BUFFER.getBoundBuffer(); - int vao = GlVertexArray.getBoundVertexArray(); - double camX; double camY; double camZ; @@ -96,10 +94,6 @@ public class InstancingEngine

implements Engine { } getGroupsToRender(event.getLayer()).forEach(group -> group.render(viewProjection, camX, camY, camZ, event.getLayer())); - - GlBufferType.ELEMENT_ARRAY_BUFFER.bind(ebo); - GlBufferType.ARRAY_BUFFER.bind(vbo); - GlVertexArray.bind(vao); } private Stream> getGroupsToRender(@Nullable RenderLayer layer) { diff --git a/src/main/java/com/jozufozu/flywheel/core/shader/WorldProgram.java b/src/main/java/com/jozufozu/flywheel/core/shader/WorldProgram.java index 0dce27d7d..26fa6838f 100644 --- a/src/main/java/com/jozufozu/flywheel/core/shader/WorldProgram.java +++ b/src/main/java/com/jozufozu/flywheel/core/shader/WorldProgram.java @@ -29,7 +29,7 @@ public class WorldProgram extends GlProgram { super.bind(); registerSamplers(); - super.unbind(); + unbind(); } protected void registerSamplers() { diff --git a/src/main/java/com/jozufozu/flywheel/core/virtual/VirtualRenderWorld.java b/src/main/java/com/jozufozu/flywheel/core/virtual/VirtualRenderWorld.java index a0687b992..d8a55397e 100644 --- a/src/main/java/com/jozufozu/flywheel/core/virtual/VirtualRenderWorld.java +++ b/src/main/java/com/jozufozu/flywheel/core/virtual/VirtualRenderWorld.java @@ -17,6 +17,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.RegistryAccess; import net.minecraft.core.SectionPos; +import net.minecraft.core.Vec3i; import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundSource; import net.minecraft.tags.TagContainer; @@ -25,6 +26,7 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.crafting.RecipeManager; import net.minecraft.world.level.Level; import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.biome.BiomeManager; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.entity.BlockEntity; @@ -54,21 +56,39 @@ public class VirtualRenderWorld extends Level implements FlywheelWorld { protected final int height; protected final int minBuildHeight; + protected final Vec3i biomeOffset; public VirtualRenderWorld(Level level) { - this(level, level.getHeight(), level.getMinBuildHeight()); + this(level, Vec3i.ZERO, level.getHeight(), level.getMinBuildHeight()); } - public VirtualRenderWorld(Level level, int height, int minBuildHeight) { + public VirtualRenderWorld(Level level, Vec3i biomeOffset) { + this(level, biomeOffset, level.getHeight(), level.getMinBuildHeight()); + } + + public VirtualRenderWorld(Level level, Vec3i biomeOffset, int height, int minBuildHeight) { super((WritableLevelData) level.getLevelData(), level.dimension(), level.dimensionType(), level::getProfiler, true, false, 0); + this.biomeOffset = biomeOffset; this.level = level; - this.height = height; - this.minBuildHeight = minBuildHeight; + this.height = nextMultipleOf16(height); + this.minBuildHeight = nextMultipleOf16(minBuildHeight); this.chunkSource = new VirtualChunkSource(this); this.lighter = new LevelLightEngine(chunkSource, true, false); } + /** + * We need to ensure that height and minBuildHeight are multiples of 16. + * Adapted from: https://math.stackexchange.com/questions/291468 + */ + public static int nextMultipleOf16(int a) { + if (a < 0) { + return -(((Math.abs(a) - 1) | 15) + 1); + } else { + return ((a - 1) | 15) + 1; + } + } + /** * Run this after you're done using setBlock(). */ @@ -165,6 +185,27 @@ public class VirtualRenderWorld extends Level implements FlywheelWorld { return getBlockState(scratch.set(x, y, z)); } + // BIOME OFFSET + + @Override + public Biome getBiome(BlockPos pPos) { + return super.getBiome(pPos.offset(biomeOffset)); + } + + @Override + public Biome getUncachedNoiseBiome(int pX, int pY, int pZ) { + // Control flow should never reach this method, + // so we add biomeOffset in case some other mod calls this directly. + return level.getUncachedNoiseBiome(pX + biomeOffset.getX(), pY + biomeOffset.getY(), pZ + biomeOffset.getZ()); + } + + @Override + public Biome getNoiseBiome(int pX, int pY, int pZ) { + // Control flow should never reach this method, + // so we add biomeOffset in case some other mod calls this directly. + return level.getNoiseBiome(pX + biomeOffset.getX(), pY + biomeOffset.getY(), pZ + biomeOffset.getZ()); + } + // RENDERING CONSTANTS @Override @@ -179,6 +220,11 @@ public class VirtualRenderWorld extends Level implements FlywheelWorld { // THIN WRAPPERS AHEAD + @Override + public BiomeManager getBiomeManager() { + return level.getBiomeManager(); + } + @Override public RegistryAccess registryAccess() { return level.registryAccess(); @@ -214,11 +260,6 @@ public class VirtualRenderWorld extends Level implements FlywheelWorld { return level.getScoreboard(); } - @Override - public Biome getUncachedNoiseBiome(int p_225604_1_, int p_225604_2_, int p_225604_3_) { - return level.getUncachedNoiseBiome(p_225604_1_, p_225604_2_, p_225604_3_); - } - // UNIMPORTANT CONSTANTS @Override diff --git a/src/main/java/com/jozufozu/flywheel/mixin/BufferUploaderAccessor.java b/src/main/java/com/jozufozu/flywheel/mixin/BufferUploaderAccessor.java deleted file mode 100644 index f7d609805..000000000 --- a/src/main/java/com/jozufozu/flywheel/mixin/BufferUploaderAccessor.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.jozufozu.flywheel.mixin; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -import com.mojang.blaze3d.vertex.BufferUploader; - -@Mixin(BufferUploader.class) -public interface BufferUploaderAccessor { - @Accessor("lastVertexArrayObject") - static void flywheel$setLastVAO(int id) { - throw new AssertionError(); - } - - @Accessor("lastVertexBufferObject") - static void flywheel$setLastVBO(int id) { - throw new AssertionError(); - } - - @Accessor("lastIndexBufferObject") - static void flywheel$setLastEBO(int id) { - throw new AssertionError(); - } - - @Accessor("lastIndexBufferObject") - static int flywheel$getLastEBO() { - throw new AssertionError(); - } - - @Accessor("lastVertexBufferObject") - static int flywheel$getLastVBO() { - throw new AssertionError(); - } - - @Accessor("lastVertexArrayObject") - static int flywheel$getLastVAO() { - throw new AssertionError(); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/mixin/BufferUploaderMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/BufferUploaderMixin.java new file mode 100644 index 000000000..7cd63581c --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/mixin/BufferUploaderMixin.java @@ -0,0 +1,29 @@ +package com.jozufozu.flywheel.mixin; + +import javax.annotation.Nullable; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.jozufozu.flywheel.backend.gl.GlStateTracker; +import com.mojang.blaze3d.vertex.BufferUploader; +import com.mojang.blaze3d.vertex.VertexFormat; + +@Mixin(BufferUploader.class) +public class BufferUploaderMixin { + + @Shadow + @Nullable + private static VertexFormat lastFormat; + + @Inject(method = "reset", at = @At("HEAD")) + private static void stopBufferUploaderFromClearingBufferStateIfNothingIsBound(CallbackInfo ci) { + // Trust our tracker over BufferUploader's. + if (GlStateTracker.getVertexArray() == 0) { + lastFormat = null; + } + } +} diff --git a/src/main/java/com/jozufozu/flywheel/mixin/GlStateManagerMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/GlStateManagerMixin.java new file mode 100644 index 000000000..db707892b --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/mixin/GlStateManagerMixin.java @@ -0,0 +1,29 @@ +package com.jozufozu.flywheel.mixin; + +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; + +import com.jozufozu.flywheel.backend.gl.GlStateTracker; +import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType; +import com.mojang.blaze3d.platform.GlStateManager; + +@Mixin(GlStateManager.class) +public class GlStateManagerMixin { + + @Inject(method = "_glBindBuffer", at = @At("TAIL")) + private static void onBindBuffer(int pTarget, int pBuffer, CallbackInfo ci) { + GlStateTracker._setBuffer(GlBufferType.fromTarget(pTarget), pBuffer); + } + + @Inject(method = "_glBindVertexArray", at = @At("TAIL")) + private static void onBindVertexArray(int pArray, CallbackInfo ci) { + GlStateTracker._setVertexArray(pArray); + } + + @Inject(method = "_glUseProgram", at = @At("TAIL")) + private static void onUseProgram(int pProgram, CallbackInfo ci) { + GlStateTracker._setProgram(pProgram); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/mixin/LevelRendererMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/LevelRendererMixin.java index 3dbe19701..026105389 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/LevelRendererMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/LevelRendererMixin.java @@ -8,6 +8,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.backend.gl.GlStateTracker; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.jozufozu.flywheel.core.crumbling.CrumblingRenderer; import com.jozufozu.flywheel.event.BeginFrameEvent; @@ -57,7 +58,11 @@ public class LevelRendererMixin { RenderBuffers renderBuffers = this.renderBuffers; + GlStateTracker.State restoreState = GlStateTracker.getRestoreState(); + MinecraftForge.EVENT_BUS.post(new RenderLayerEvent(level, type, stack, renderBuffers, camX, camY, camZ)); + + restoreState.restore(); } @Inject(at = @At("TAIL"), method = "allChanged") @@ -76,7 +81,9 @@ public class LevelRendererMixin { Vec3 cameraPos = info.getPosition(); + GlStateTracker.State restoreState = GlStateTracker.getRestoreState(); CrumblingRenderer.renderBreaking(new RenderLayerEvent(level, null, stack, null, cameraPos.x, cameraPos.y, cameraPos.z)); + restoreState.restore(); } // Instancing diff --git a/src/main/java/com/jozufozu/flywheel/mixin/ShaderInstanceAccessor.java b/src/main/java/com/jozufozu/flywheel/mixin/ShaderInstanceAccessor.java deleted file mode 100644 index 6f7538a4d..000000000 --- a/src/main/java/com/jozufozu/flywheel/mixin/ShaderInstanceAccessor.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.jozufozu.flywheel.mixin; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -import net.minecraft.client.renderer.ShaderInstance; - -@Mixin(ShaderInstance.class) -public interface ShaderInstanceAccessor { - @Accessor("lastProgramId") - static void flywheel$setLastProgramId(int id) { - throw new AssertionError(); - } -} diff --git a/src/main/resources/flywheel.mixins.json b/src/main/resources/flywheel.mixins.json index 54eb1247d..bbf0648db 100644 --- a/src/main/resources/flywheel.mixins.json +++ b/src/main/resources/flywheel.mixins.json @@ -1,37 +1,37 @@ { - "required": true, - "minVersion": "0.8", - "package": "com.jozufozu.flywheel.mixin", - "compatibilityLevel": "JAVA_17", - "refmap": "flywheel.refmap.json", - "client": [ - "BlockEntityTypeMixin", - "BufferBuilderMixin", - "BufferUploaderAccessor", - "CameraMixin", - "CancelEntityRenderMixin", - "ChunkRebuildHooksMixin", - "EntityTypeMixin", - "FixFabulousDepthMixin", - "FrustumMixin", - "InstanceAddMixin", - "InstanceRemoveMixin", - "LevelRendererAccessor", - "LevelRendererMixin", - "PausedPartialTickAccessor", - "RenderTexturesMixin", - "RenderTypeMixin", - "ShaderCloseMixin", - "ShaderInstanceAccessor", - "atlas.AtlasDataMixin", - "atlas.SheetDataAccessor", - "light.LightUpdateMixin", - "light.NetworkLightUpdateMixin", - "matrix.Matrix3fMixin", - "matrix.Matrix4fMixin", - "matrix.PoseStackMixin" - ], - "injectors": { - "defaultRequire": 1 + "required": true, + "minVersion": "0.8", + "package": "com.jozufozu.flywheel.mixin", + "compatibilityLevel": "JAVA_17", + "refmap": "flywheel.refmap.json", + "client": [ + "BlockEntityTypeMixin", + "BufferBuilderMixin", + "BufferUploaderMixin", + "CameraMixin", + "CancelEntityRenderMixin", + "ChunkRebuildHooksMixin", + "EntityTypeMixin", + "FixFabulousDepthMixin", + "FrustumMixin", + "GlStateManagerMixin", + "InstanceAddMixin", + "InstanceRemoveMixin", + "LevelRendererAccessor", + "LevelRendererMixin", + "PausedPartialTickAccessor", + "RenderTexturesMixin", + "RenderTypeMixin", + "ShaderCloseMixin", + "atlas.AtlasDataMixin", + "atlas.SheetDataAccessor", + "light.LightUpdateMixin", + "light.NetworkLightUpdateMixin", + "matrix.Matrix3fMixin", + "matrix.Matrix4fMixin", + "matrix.PoseStackMixin" + ], + "injectors": { + "defaultRequire": 1 } }