diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltTileEntity.java index 95b756234..4fe5b0f48 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltTileEntity.java @@ -548,18 +548,20 @@ public class BeltTileEntity extends KineticTileEntity implements LightUpdateList } private void initializeLight() { - light = new byte[beltLength * 2]; + if (beltLength > 0) { + light = new byte[beltLength * 2]; - Vec3i vec = getBeltFacing().getDirectionVec(); - BeltSlope slope = getBlockState().get(BeltBlock.SLOPE); - int verticality = slope == BeltSlope.DOWNWARD ? -1 : slope == BeltSlope.UPWARD ? 1 : 0; + Vec3i vec = getBeltFacing().getDirectionVec(); + BeltSlope slope = getBlockState().get(BeltBlock.SLOPE); + int verticality = slope == BeltSlope.DOWNWARD ? -1 : slope == BeltSlope.UPWARD ? 1 : 0; - BlockPos.Mutable pos = new BlockPos.Mutable(controller); - for (int i = 0; i < beltLength * 2; i += 2) { - light[i] = (byte) world.getLightLevel(LightType.BLOCK, pos); - light[i + 1] = (byte) world.getLightLevel(LightType.SKY, pos); + BlockPos.Mutable pos = new BlockPos.Mutable(controller); + for (int i = 0; i < beltLength * 2; i += 2) { + light[i] = (byte) world.getLightLevel(LightType.BLOCK, pos); + light[i + 1] = (byte) world.getLightLevel(LightType.SKY, pos); - pos.move(vec.getX(), verticality, vec.getZ()); + pos.move(vec.getX(), verticality, vec.getZ()); + } } } diff --git a/src/main/java/com/simibubi/create/foundation/mixin/AddRemoveTileMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/AddRemoveTileMixin.java deleted file mode 100644 index 8496fdee8..000000000 --- a/src/main/java/com/simibubi/create/foundation/mixin/AddRemoveTileMixin.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.simibubi.create.foundation.mixin; - -import com.simibubi.create.foundation.render.KineticRenderer; -import org.spongepowered.asm.mixin.Final; -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 org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; - -import com.simibubi.create.CreateClient; - -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -import java.util.Set; - -@OnlyIn(Dist.CLIENT) -@Mixin(value = World.class, priority = 1042) -public class AddRemoveTileMixin { - - @Shadow @Final public boolean isRemote; - - @Shadow @Final protected Set tileEntitiesToBeRemoved; - - /** - * JUSTIFICATION: This method is called whenever a tile entity is removed due - * to a change in block state, even on the client. By hooking into this method, - * we gain easy access to the information while having no impact on performance. - */ - @Inject(at = @At( - value = "INVOKE_ASSIGN", - target = "Lnet/minecraft/world/World;getTileEntity(Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/tileentity/TileEntity;" - ), - method = "removeTileEntity", - locals = LocalCapture.CAPTURE_FAILHARD - ) - private void onRemoveTile(BlockPos pos, CallbackInfo ci, TileEntity te) { - if (isRemote) { - World thi = (World)(Object) this; - CreateClient.kineticRenderer.get(thi).remove(te); - } - } - - @Inject(at = @At("TAIL"), method = "addTileEntity") - private void onAddTile(TileEntity te, CallbackInfoReturnable cir) { - if (isRemote) { - World thi = (World)(Object) this; - CreateClient.kineticRenderer.get(thi).queueAdd(te); - } - } - - @Inject(at = @At( - value = "INVOKE", - target = "Ljava/util/Set;clear()V", ordinal = 0 - ), - method = "tickBlockEntities") - private void onChunkUnload(CallbackInfo ci) { - if (isRemote) { - World thi = (World)(Object) this; - KineticRenderer kineticRenderer = CreateClient.kineticRenderer.get(thi); - for (TileEntity tile : tileEntitiesToBeRemoved) { - kineticRenderer.remove(tile); - } - } - } -} diff --git a/src/main/java/com/simibubi/create/foundation/mixin/TileAddMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/TileAddMixin.java new file mode 100644 index 000000000..650968b45 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/mixin/TileAddMixin.java @@ -0,0 +1,29 @@ +package com.simibubi.create.foundation.mixin; + +import org.spongepowered.asm.mixin.Final; +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.CallbackInfoReturnable; + +import com.simibubi.create.CreateClient; + +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +@OnlyIn(Dist.CLIENT) +@Mixin(World.class) +public class TileAddMixin { + + @Shadow @Final public boolean isRemote; + + @Inject(at = @At("TAIL"), method = "addTileEntity") + private void onAddTile(TileEntity te, CallbackInfoReturnable cir) { + if (isRemote) { + CreateClient.kineticRenderer.get((World)(Object) this).queueAdd(te); + } + } +} diff --git a/src/main/java/com/simibubi/create/foundation/mixin/TileRemoveMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/TileRemoveMixin.java new file mode 100644 index 000000000..c34c25c79 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/mixin/TileRemoveMixin.java @@ -0,0 +1,25 @@ +package com.simibubi.create.foundation.mixin; + +import net.minecraft.client.world.ClientWorld; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; + +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.simibubi.create.CreateClient; + +@Mixin(TileEntity.class) +public class TileRemoveMixin { + + @Shadow @Nullable protected World world; + + @Inject(at = @At("TAIL"), method = "remove") + private void onRemove(CallbackInfo ci) { + if (world instanceof ClientWorld) + CreateClient.kineticRenderer.get(this.world).remove((TileEntity) (Object) this); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/Backend.java b/src/main/java/com/simibubi/create/foundation/render/backend/Backend.java index 3c3891c17..20292f6d7 100644 --- a/src/main/java/com/simibubi/create/foundation/render/backend/Backend.java +++ b/src/main/java/com/simibubi/create/foundation/render/backend/Backend.java @@ -11,6 +11,7 @@ import com.simibubi.create.foundation.render.backend.instancing.IFlywheelWorld; import net.minecraft.world.World; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.lwjgl.opengl.GL; import org.lwjgl.opengl.GLCapabilities; import org.lwjgl.system.MemoryUtil; @@ -23,82 +24,85 @@ import net.minecraft.util.ResourceLocation; import net.minecraftforge.resource.ISelectiveResourceReloadListener; public class Backend { - public static final Boolean SHADER_DEBUG_OUTPUT = true; + public static final Boolean SHADER_DEBUG_OUTPUT = true; - public static final Logger log = LogManager.getLogger(Backend.class); - public static final FloatBuffer MATRIX_BUFFER = MemoryUtil.memAllocFloat(16); + public static final Logger log = LogManager.getLogger(Backend.class); + public static GLCapabilities capabilities; + public static GlFeatureCompat compat; - static final Map> registry = new HashMap<>(); - static final Map, ProgramGroup> programs = new HashMap<>(); + private static boolean instancingAvailable; + private static boolean enabled; - private static boolean enabled; + static final Map> registry = new HashMap<>(); + static final Map, ProgramGroup> programs = new HashMap<>(); - public static GLCapabilities capabilities; - public static GlFeatureCompat compat; + public Backend() { + throw new IllegalStateException(); + } - public Backend() { - throw new IllegalStateException(); - } + /** + * Register a shader program. TODO: replace with forge registry? + */ + public static

> S register(S spec) { + ResourceLocation name = spec.name; + if (registry.containsKey(name)) { + throw new IllegalStateException("Program spec '" + name + "' already registered."); + } + registry.put(name, spec); + return spec; + } - /** - * Register a shader program. TODO: replace with forge registry? - */ - public static

> S register(S spec) { - ResourceLocation name = spec.name; - if (registry.containsKey(name)) { - throw new IllegalStateException("Program spec '" + name + "' already registered."); - } - registry.put(name, spec); - return spec; - } + @SuppressWarnings("unchecked") + public static

> P getProgram(S spec) { + return (P) programs.get(spec).get(GlFog.getFogMode()); + } - @SuppressWarnings("unchecked") - public static

> P getProgram(S spec) { - return (P) programs.get(spec).get(GlFog.getFogMode()); - } + public static boolean isFlywheelWorld(World world) { + return world == Minecraft.getInstance().world || (world instanceof IFlywheelWorld && ((IFlywheelWorld) world).supportsFlywheel()); + } - public static boolean isFlywheelWorld(World world) { - return world == Minecraft.getInstance().world || (world instanceof IFlywheelWorld && ((IFlywheelWorld) world).supportsFlywheel()); - } + public static boolean available() { + return canUseVBOs(); + } - public static boolean available() { - return canUseVBOs(); - } + public static boolean canUseInstancing() { + return enabled && instancingAvailable; + } - public static boolean canUseInstancing() { - return enabled && - compat.vertexArrayObjectsSupported() && - compat.drawInstancedSupported() && - compat.instancedArraysSupported(); - } + public static boolean canUseVBOs() { + return enabled && gl20(); + } - public static boolean canUseVBOs() { - return enabled && gl20(); - } + public static boolean gl33() { + return capabilities.OpenGL33; + } - public static boolean gl33() { - return capabilities.OpenGL33; - } + public static boolean gl20() { + return capabilities.OpenGL20; + } - public static boolean gl20() { - return capabilities.OpenGL20; - } + public static void init() { + // Can be null when running datagenerators due to the unfortunate time we call this + Minecraft mc = Minecraft.getInstance(); + if (mc == null) return; - public static void init() { - // Can be null when running datagenerators due to the unfortunate time we call this - Minecraft mc = Minecraft.getInstance(); - if (mc == null) return; + IResourceManager manager = mc.getResourceManager(); - IResourceManager manager = mc.getResourceManager(); + if (manager instanceof IReloadableResourceManager) { + ISelectiveResourceReloadListener listener = ShaderLoader::onResourceManagerReload; + ((IReloadableResourceManager) manager).addReloadListener(listener); + } + } - if (manager instanceof IReloadableResourceManager) { - ISelectiveResourceReloadListener listener = ShaderLoader::onResourceManagerReload; - ((IReloadableResourceManager) manager).addReloadListener(listener); - } - } + public static void refresh() { + capabilities = GL.createCapabilities(); - public static void refresh() { - enabled = AllConfigs.CLIENT.experimentalRendering.get() && !OptifineHandler.usingShaders(); - } + compat = new GlFeatureCompat(capabilities); + instancingAvailable = compat.vertexArrayObjectsSupported() && + compat.drawInstancedSupported() && + compat.instancedArraysSupported(); + + enabled = AllConfigs.CLIENT.experimentalRendering.get() && !OptifineHandler.usingShaders(); + } } diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/RenderUtil.java b/src/main/java/com/simibubi/create/foundation/render/backend/RenderUtil.java index e5ee528c2..dde1e9a15 100644 --- a/src/main/java/com/simibubi/create/foundation/render/backend/RenderUtil.java +++ b/src/main/java/com/simibubi/create/foundation/render/backend/RenderUtil.java @@ -3,8 +3,7 @@ package com.simibubi.create.foundation.render.backend; import net.minecraft.client.renderer.Matrix3f; import net.minecraft.client.renderer.Matrix4f; -import java.nio.ByteBuffer; -import java.nio.FloatBuffer; +import com.mojang.blaze3d.matrix.MatrixStack; public class RenderUtil { public static int nextPowerOf2(int a) { @@ -17,9 +16,12 @@ public class RenderUtil { return b == 0 && n != 0; } - // GPUs want matrices in column major order. + public static float[] writeMatrixStack(MatrixStack stack) { + return writeMatrixStack(stack.peek().getModel(), stack.peek().getNormal()); + } - public static float[] bufferMatrices(Matrix4f model, Matrix3f normal) { + // GPUs want matrices in column major order. + public static float[] writeMatrixStack(Matrix4f model, Matrix3f normal) { return new float[] { model.a00, model.a10, @@ -48,4 +50,25 @@ public class RenderUtil { normal.a22, }; } + + public static float[] writeMatrix(Matrix4f model) { + return new float[]{ + model.a00, + model.a10, + model.a20, + model.a30, + model.a01, + model.a11, + model.a21, + model.a31, + model.a02, + model.a12, + model.a22, + model.a32, + model.a03, + model.a13, + model.a23, + model.a33, + }; + } } diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/ShaderLoader.java b/src/main/java/com/simibubi/create/foundation/render/backend/ShaderLoader.java index a9a4119e5..c512fd8a7 100644 --- a/src/main/java/com/simibubi/create/foundation/render/backend/ShaderLoader.java +++ b/src/main/java/com/simibubi/create/foundation/render/backend/ShaderLoader.java @@ -28,175 +28,172 @@ import java.util.stream.Collectors; import java.util.stream.Stream; public class ShaderLoader { - public static final String SHADER_DIR = "flywheel/shaders/"; - public static final ArrayList EXTENSIONS = Lists.newArrayList(".vert", ".vsh", ".frag", ".fsh", ".glsl"); + public static final String SHADER_DIR = "flywheel/shaders/"; + public static final ArrayList EXTENSIONS = Lists.newArrayList(".vert", ".vsh", ".frag", ".fsh", ".glsl"); - static final Map shaderSource = new HashMap<>(); + static final Map shaderSource = new HashMap<>(); - static void onResourceManagerReload(IResourceManager manager, Predicate predicate) { - if (predicate.test(VanillaResourceType.SHADERS)) { - Backend.capabilities = GL.createCapabilities(); - Backend.compat = new GlFeatureCompat(Backend.capabilities); + static void onResourceManagerReload(IResourceManager manager, Predicate predicate) { + if (predicate.test(VanillaResourceType.SHADERS)) { + OptifineHandler.refresh(); + Backend.refresh(); - OptifineHandler.refresh(); - Backend.refresh(); + if (Backend.gl20()) { + shaderSource.clear(); + loadShaderSources(manager); - if (Backend.gl20()) { - shaderSource.clear(); - loadShaderSources(manager); + Backend.programs.values().forEach(ProgramGroup::delete); + Backend.programs.clear(); + Backend.registry.values().forEach(ShaderLoader::loadProgram); - Backend.programs.values().forEach(ProgramGroup::delete); - Backend.programs.clear(); - Backend.registry.values().forEach(ShaderLoader::loadProgram); + Backend.log.info("Loaded all shader programs."); + } + } + } - Backend.log.info("Loaded all shader programs."); - } - } - } + private static void loadShaderSources(IResourceManager manager){ + Collection allShaders = manager.getAllResourceLocations(SHADER_DIR, s -> { + for (String ext : EXTENSIONS) { + if (s.endsWith(ext)) return true; + } + return false; + }); - private static void loadShaderSources(IResourceManager manager){ - Collection allShaders = manager.getAllResourceLocations(SHADER_DIR, s -> { - for (String ext : EXTENSIONS) { - if (s.endsWith(ext)) return true; - } - return false; - }); + for (ResourceLocation location : allShaders) { + try { + IResource resource = manager.getResource(location); - for (ResourceLocation location : allShaders) { - try { - IResource resource = manager.getResource(location); + String file = readToString(resource.getInputStream()); - String file = readToString(resource.getInputStream()); + ResourceLocation name = new ResourceLocation(location.getNamespace(), + location.getPath().substring(SHADER_DIR.length())); - ResourceLocation name = new ResourceLocation(location.getNamespace(), - location.getPath().substring(SHADER_DIR.length())); + shaderSource.put(name, file); + } catch (IOException e) { - shaderSource.put(name, file); - } catch (IOException e) { + } + } + } - } - } - } + static

> void loadProgram(S programSpec) { + Map programGroup = new EnumMap<>(GlFogMode.class); - static

> void loadProgram(S programSpec) { - Map programGroup = new EnumMap<>(GlFogMode.class); + for (GlFogMode fogMode : GlFogMode.values()) { + programGroup.put(fogMode, loadProgram(programSpec, fogMode)); + } - for (GlFogMode fogMode : GlFogMode.values()) { - programGroup.put(fogMode, loadProgram(programSpec, fogMode)); - } + Backend.programs.put(programSpec, new ProgramGroup<>(programGroup)); - Backend.programs.put(programSpec, new ProgramGroup<>(programGroup)); + Backend.log.debug("Loaded program {}", programSpec.name); + } - Backend.log.debug("Loaded program {}", programSpec.name); - } + private static

> P loadProgram(S programSpec, GlFogMode fogMode) { + GlShader vert = null; + GlShader frag = null; + try { + ShaderConstants defines = new ShaderConstants(programSpec.defines); - private static

> P loadProgram(S programSpec, GlFogMode fogMode) { - GlShader vert = null; - GlShader frag = null; - try { - ShaderConstants defines = new ShaderConstants(programSpec.defines); + defines.defineAll(fogMode.getDefines()); - defines.defineAll(fogMode.getDefines()); + vert = loadShader(programSpec.getVert(), ShaderType.VERTEX, defines); + frag = loadShader(programSpec.getFrag(), ShaderType.FRAGMENT, defines); - vert = loadShader(programSpec.getVert(), ShaderType.VERTEX, defines); - frag = loadShader(programSpec.getFrag(), ShaderType.FRAGMENT, defines); + GlProgram.Builder builder = GlProgram.builder(programSpec.name, fogMode).attachShader(vert).attachShader(frag); - GlProgram.Builder builder = GlProgram.builder(programSpec.name, fogMode).attachShader(vert).attachShader(frag); + programSpec.attributes.forEach(builder::addAttribute); - programSpec.attributes.forEach(builder::addAttribute); + return builder.build(programSpec.factory); - return builder.build(programSpec.factory); + } finally { + if (vert != null) vert.delete(); + if (frag != null) frag.delete(); + } + } - } finally { - if (vert != null) vert.delete(); - if (frag != null) frag.delete(); - } - } + private static final Pattern includePattern = Pattern.compile("#flwinclude <\"([\\w\\d_]+:[\\w\\d_./]+)\">"); - private static final Pattern includePattern = Pattern.compile("#flwinclude <\"([\\w\\d_]+:[\\w\\d_./]+)\">"); + private static String processIncludes(ResourceLocation baseName, String source) { + HashSet seen = new HashSet<>(); + seen.add(baseName); - private static String processIncludes(ResourceLocation baseName, String source) { - HashSet seen = new HashSet<>(); - seen.add(baseName); + return includeRecursive(source, seen).collect(Collectors.joining("\n")); + } - return includeRecursive(source, seen).collect(Collectors.joining("\n")); - } + private static Stream includeRecursive(String source, Set seen) { + return new BufferedReader(new StringReader(source)).lines().flatMap(line -> { - private static Stream includeRecursive(String source, Set seen) { - return new BufferedReader(new StringReader(source)).lines().flatMap(line -> { + Matcher matcher = includePattern.matcher(line); - Matcher matcher = includePattern.matcher(line); + if (matcher.find()) { + String includeName = matcher.group(1); - if (matcher.find()) { - String includeName = matcher.group(1); + ResourceLocation include = new ResourceLocation(includeName); - ResourceLocation include = new ResourceLocation(includeName); + if (seen.add(include)) { + String includeSource = shaderSource.get(include); - if (seen.add(include)) { - String includeSource = shaderSource.get(include); + if (includeSource != null) { + return includeRecursive(includeSource, seen); + } + } + } - if (includeSource != null) { - return includeRecursive(includeSource, seen); - } - } - } + return Stream.of(line); + }); + } - return Stream.of(line); - }); - } + private static GlShader loadShader(ResourceLocation name, ShaderType type, ShaderConstants defines) { + String source = shaderSource.get(name); - private static GlShader loadShader(ResourceLocation name, ShaderType type, ShaderConstants defines) { - String source = shaderSource.get(name); + source = processIncludes(name, source); - source = processIncludes(name, source); - - if (defines != null) - source = defines.process(source); + if (defines != null) + source = defines.process(source); - return new GlShader(type, name, source); - } + return new GlShader(type, name, source); + } - public static String readToString(InputStream is) { - RenderSystem.assertThread(RenderSystem::isOnRenderThread); - ByteBuffer bytebuffer = null; + public static String readToString(InputStream is) { + RenderSystem.assertThread(RenderSystem::isOnRenderThread); + ByteBuffer bytebuffer = null; - try { - bytebuffer = readToBuffer(is); - int i = bytebuffer.position(); - ((Buffer)bytebuffer).rewind(); - return MemoryUtil.memASCII(bytebuffer, i); - } catch (IOException e) { + try { + bytebuffer = readToBuffer(is); + int i = bytebuffer.position(); + ((Buffer)bytebuffer).rewind(); + return MemoryUtil.memASCII(bytebuffer, i); + } catch (IOException e) { - } finally { - if (bytebuffer != null) { - MemoryUtil.memFree(bytebuffer); - } + } finally { + if (bytebuffer != null) { + MemoryUtil.memFree(bytebuffer); + } - } + } - return null; - } + return null; + } - public static ByteBuffer readToBuffer(InputStream is) throws IOException { - ByteBuffer bytebuffer; - if (is instanceof FileInputStream) { - FileInputStream fileinputstream = (FileInputStream)is; - FileChannel filechannel = fileinputstream.getChannel(); - bytebuffer = MemoryUtil.memAlloc((int)filechannel.size() + 1); + public static ByteBuffer readToBuffer(InputStream is) throws IOException { + ByteBuffer bytebuffer; + if (is instanceof FileInputStream) { + FileInputStream fileinputstream = (FileInputStream)is; + FileChannel filechannel = fileinputstream.getChannel(); + bytebuffer = MemoryUtil.memAlloc((int)filechannel.size() + 1); - while (filechannel.read(bytebuffer) != -1) { } - } else { - bytebuffer = MemoryUtil.memAlloc(8192); - ReadableByteChannel readablebytechannel = Channels.newChannel(is); + while (filechannel.read(bytebuffer) != -1) { } + } else { + bytebuffer = MemoryUtil.memAlloc(8192); + ReadableByteChannel readablebytechannel = Channels.newChannel(is); - while (readablebytechannel.read(bytebuffer) != -1) { - if (bytebuffer.remaining() == 0) { - bytebuffer = MemoryUtil.memRealloc(bytebuffer, bytebuffer.capacity() * 2); - } - } - } + while (readablebytechannel.read(bytebuffer) != -1) { + if (bytebuffer.remaining() == 0) { + bytebuffer = MemoryUtil.memRealloc(bytebuffer, bytebuffer.capacity() * 2); + } + } + } - return bytebuffer; - } + return bytebuffer; + } } diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/gl/BasicProgram.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/BasicProgram.java index bef778f9a..29467719e 100644 --- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/BasicProgram.java +++ b/src/main/java/com/simibubi/create/foundation/render/backend/gl/BasicProgram.java @@ -1,5 +1,6 @@ package com.simibubi.create.foundation.render.backend.gl; +import com.simibubi.create.foundation.render.backend.RenderUtil; import com.simibubi.create.foundation.render.backend.gl.shader.ProgramFogMode; import org.lwjgl.opengl.GL20; @@ -53,9 +54,6 @@ public class BasicProgram extends GlProgram { } protected static void uploadMatrixUniform(int uniform, Matrix4f mat) { - Backend.MATRIX_BUFFER.position(0); - mat.write(Backend.MATRIX_BUFFER); - Backend.MATRIX_BUFFER.rewind(); - GL20.glUniformMatrix4fv(uniform, false, Backend.MATRIX_BUFFER); + GL20.glUniformMatrix4fv(uniform, false, RenderUtil.writeMatrix(mat)); } } diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/IDynamicInstance.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/IDynamicInstance.java index 0af4bc1eb..2e0914698 100644 --- a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/IDynamicInstance.java +++ b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/IDynamicInstance.java @@ -2,7 +2,8 @@ package com.simibubi.create.foundation.render.backend.instancing; public interface IDynamicInstance { /** - * Called every frame, this can be used to make more dynamic animations. + * Called every frame. This can be used to smoothly change instance data + * to allow for fancy animations that could not be achieved on the GPU alone. */ void beginFrame(); } diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/ITickableInstance.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/ITickableInstance.java index 04a6f7ec0..a93f7b8d3 100644 --- a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/ITickableInstance.java +++ b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/ITickableInstance.java @@ -2,5 +2,9 @@ package com.simibubi.create.foundation.render.backend.instancing; public interface ITickableInstance { + /** + * Called every tick. This is useful for things that don't have to be smooth, + * or to recalculate something that would only change after a game tick. + */ void tick(); } diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/InstancedTileRenderer.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/InstancedTileRenderer.java index 74bda0057..a0a488329 100644 --- a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/InstancedTileRenderer.java +++ b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/InstancedTileRenderer.java @@ -39,14 +39,6 @@ public abstract class InstancedTileRenderer

{ public abstract void registerMaterials(); public void tick() { - int ticks = AnimationTickHolder.getTicks(); - - // Clean up twice a second. This doesn't have to happen every tick, - // but this does need to be run to ensure we don't miss anything. - if (ticks % 10 == 0) { - clean(); - } - if (tickableInstances.size() > 0) tickableInstances.values().forEach(ITickableInstance::tick); } @@ -187,16 +179,13 @@ public abstract class InstancedTileRenderer

{ return renderer; } - private void clean() { - instances.keySet().removeIf(TileEntity::isRemoved); - } - public void invalidate() { for (RenderMaterial material : materials.values()) { material.delete(); } instances.clear(); dynamicInstances.clear(); + tickableInstances.clear(); } public boolean canCreateInstance(TileEntity tile) { diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/ModelData.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/ModelData.java index 170d555a7..2ad27e1b2 100644 --- a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/ModelData.java +++ b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/ModelData.java @@ -16,7 +16,7 @@ public class ModelData extends BasicData { } public ModelData setTransform(MatrixStack stack) { - matrices = RenderUtil.bufferMatrices(stack.peek().getModel(), stack.peek().getNormal()); + matrices = RenderUtil.writeMatrixStack(stack); return this; } diff --git a/src/main/resources/create.mixins.json b/src/main/resources/create.mixins.json index 285af7c77..1789b3b03 100644 --- a/src/main/resources/create.mixins.json +++ b/src/main/resources/create.mixins.json @@ -3,9 +3,19 @@ "package": "com.simibubi.create.foundation.mixin", "compatibilityLevel": "JAVA_8", "refmap": "create.refmap.json", - "client": ["AddRemoveTileMixin", "CancelTileEntityRenderMixin", "FogColorTrackerMixin", "LightUpdateMixin", "NetworkLightUpdateMixin", "RenderHooksMixin", "ShaderCloseMixin"], + "mixins": ["StepSoundMixin"], + "client": [ + "TileAddMixin", + "CancelTileEntityRenderMixin", + "FogColorTrackerMixin", + "LightUpdateMixin", + "NetworkLightUpdateMixin", + "RenderHooksMixin", + "ShaderCloseMixin", + "TileRemoveMixin" + ], "injectors": { "defaultRequire": 1 }, - "minVersion": "0.8", "mixins": ["StepSoundMixin"] + "minVersion": "0.8" } \ No newline at end of file