mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-11-13 05:54:17 +01:00
kinda separate system capability stuff, should probably clean this up more.
fix lighting glitches on world load.
This commit is contained in:
parent
d824304f12
commit
a5f3d799d1
@ -1,6 +1,7 @@
|
|||||||
package com.simibubi.create.content.contraptions.components.structureMovement;
|
package com.simibubi.create.content.contraptions.components.structureMovement;
|
||||||
|
|
||||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||||
|
import com.simibubi.create.foundation.render.backend.Backend;
|
||||||
import com.simibubi.create.foundation.render.backend.FastRenderDispatcher;
|
import com.simibubi.create.foundation.render.backend.FastRenderDispatcher;
|
||||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||||
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||||
@ -56,11 +57,12 @@ public abstract class AbstractContraptionEntityRenderer<C extends AbstractContra
|
|||||||
transform(entity, partialTicks, matrixStacks);
|
transform(entity, partialTicks, matrixStacks);
|
||||||
Contraption contraption = entity.getContraption();
|
Contraption contraption = entity.getContraption();
|
||||||
if (contraption != null) {
|
if (contraption != null) {
|
||||||
if (!FastRenderDispatcher.available()) {
|
if (Backend.canUseVBOs()) {
|
||||||
ContraptionRenderer.render(entity.world, contraption, ms, msLocal, buffers);
|
|
||||||
} else {
|
|
||||||
ContraptionRenderer.renderDynamic(entity.world, contraption, ms, msLocal, buffers);
|
ContraptionRenderer.renderDynamic(entity.world, contraption, ms, msLocal, buffers);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
ContraptionRenderer.render(entity.world, contraption, ms, msLocal, buffers);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ms.pop();
|
ms.pop();
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import java.util.Random;
|
|||||||
|
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher;
|
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher;
|
||||||
import com.simibubi.create.foundation.render.*;
|
import com.simibubi.create.foundation.render.*;
|
||||||
|
import com.simibubi.create.foundation.render.backend.Backend;
|
||||||
import com.simibubi.create.foundation.render.backend.FastRenderDispatcher;
|
import com.simibubi.create.foundation.render.backend.FastRenderDispatcher;
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
import org.lwjgl.opengl.GL11;
|
import org.lwjgl.opengl.GL11;
|
||||||
@ -75,7 +76,7 @@ public class ContraptionRenderer {
|
|||||||
|
|
||||||
protected static void renderTileEntities(World world, Contraption c, MatrixStack ms, MatrixStack msLocal,
|
protected static void renderTileEntities(World world, Contraption c, MatrixStack ms, MatrixStack msLocal,
|
||||||
IRenderTypeBuffer buffer) {
|
IRenderTypeBuffer buffer) {
|
||||||
if (FastRenderDispatcher.available()) {
|
if (Backend.canUseVBOs()) {
|
||||||
ContraptionRenderDispatcher.renderTileEntities(world, c, ms, msLocal, buffer);
|
ContraptionRenderDispatcher.renderTileEntities(world, c, ms, msLocal, buffer);
|
||||||
} else {
|
} else {
|
||||||
TileEntityRenderHelper.renderTileEntities(world, c.maybeInstancedTileEntities, ms, msLocal, buffer);
|
TileEntityRenderHelper.renderTileEntities(world, c.maybeInstancedTileEntities, ms, msLocal, buffer);
|
||||||
|
@ -34,10 +34,6 @@ import java.util.Map;
|
|||||||
public class ContraptionRenderDispatcher {
|
public class ContraptionRenderDispatcher {
|
||||||
public static final HashMap<Integer, RenderedContraption> renderers = new HashMap<>();
|
public static final HashMap<Integer, RenderedContraption> renderers = new HashMap<>();
|
||||||
|
|
||||||
public static void markForRendering(Contraption c, MatrixStack model) {
|
|
||||||
getRenderer(c.entity.world, c).setRenderSettings(model.peek().getModel());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void notifyLightUpdate(ILightReader world, LightType type, SectionPos pos) {
|
public static void notifyLightUpdate(ILightReader world, LightType type, SectionPos pos) {
|
||||||
for (RenderedContraption renderer : renderers.values()) {
|
for (RenderedContraption renderer : renderers.values()) {
|
||||||
renderer.getLighter().lightVolume.notifyLightUpdate(world, type, pos);
|
renderer.getLighter().lightVolume.notifyLightUpdate(world, type, pos);
|
||||||
@ -73,7 +69,8 @@ public class ContraptionRenderDispatcher {
|
|||||||
private static <C extends AbstractContraptionEntity> void updateTransform(C c, AbstractContraptionEntityRenderer<C> entityRenderer) {
|
private static <C extends AbstractContraptionEntity> void updateTransform(C c, AbstractContraptionEntityRenderer<C> entityRenderer) {
|
||||||
MatrixStack stack = entityRenderer.makeTransformMatrix(c, AnimationTickHolder.getPartialTicks());
|
MatrixStack stack = entityRenderer.makeTransformMatrix(c, AnimationTickHolder.getPartialTicks());
|
||||||
|
|
||||||
markForRendering(c.getContraption(), stack);
|
Contraption c1 = c.getContraption();
|
||||||
|
getRenderer(c1.entity.world, c1).setRenderSettings(stack.peek().getModel());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void tick() {
|
public static void tick() {
|
||||||
@ -104,15 +101,19 @@ public class ContraptionRenderDispatcher {
|
|||||||
GL11.glEnable(GL13.GL_TEXTURE_3D);
|
GL11.glEnable(GL13.GL_TEXTURE_3D);
|
||||||
GL13.glActiveTexture(GL40.GL_TEXTURE4); // the shaders expect light volumes to be in texture 4
|
GL13.glActiveTexture(GL40.GL_TEXTURE4); // the shaders expect light volumes to be in texture 4
|
||||||
|
|
||||||
ContraptionProgram structureShader = Backend.getProgram(AllProgramSpecs.CONTRAPTION_STRUCTURE);
|
if (Backend.canUseVBOs()) {
|
||||||
structureShader.bind(viewProjection, camX, camY, camZ, FastRenderDispatcher.getDebugMode());
|
ContraptionProgram structureShader = Backend.getProgram(AllProgramSpecs.CONTRAPTION_STRUCTURE);
|
||||||
for (RenderedContraption renderer : renderers.values()) {
|
structureShader.bind(viewProjection, camX, camY, camZ, FastRenderDispatcher.getDebugMode());
|
||||||
renderer.doRenderLayer(layer, structureShader);
|
for (RenderedContraption renderer : renderers.values()) {
|
||||||
|
renderer.doRenderLayer(layer, structureShader);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (RenderedContraption renderer : renderers.values()) {
|
if (Backend.canUseInstancing()) {
|
||||||
renderer.kinetics.render(layer, viewProjection, camX, camY, camZ, renderer::setup);
|
for (RenderedContraption renderer : renderers.values()) {
|
||||||
renderer.teardown();
|
renderer.kinetics.render(layer, viewProjection, camX, camY, camZ, renderer::setup);
|
||||||
|
renderer.teardown();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
layer.endDrawing();
|
layer.endDrawing();
|
||||||
|
@ -6,6 +6,7 @@ import com.simibubi.create.content.contraptions.base.KineticRenderMaterials;
|
|||||||
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
|
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour;
|
import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
||||||
|
import com.simibubi.create.foundation.render.backend.Backend;
|
||||||
import com.simibubi.create.foundation.render.backend.instancing.*;
|
import com.simibubi.create.foundation.render.backend.instancing.*;
|
||||||
import com.simibubi.create.content.contraptions.components.actors.ContraptionActorData;
|
import com.simibubi.create.content.contraptions.components.actors.ContraptionActorData;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionLighter;
|
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionLighter;
|
||||||
@ -52,8 +53,10 @@ public class RenderedContraption {
|
|||||||
this.renderWorld = setupRenderWorld(world, contraption);
|
this.renderWorld = setupRenderWorld(world, contraption);
|
||||||
|
|
||||||
buildLayers();
|
buildLayers();
|
||||||
buildInstancedTiles();
|
if (Backend.canUseInstancing()) {
|
||||||
buildActors();
|
buildInstancedTiles();
|
||||||
|
buildActors();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getEntityId() {
|
public int getEntityId() {
|
||||||
|
@ -84,8 +84,9 @@ public class ConfigureConfigPacket extends SimplePacketBase {
|
|||||||
|
|
||||||
@OnlyIn(Dist.CLIENT)
|
@OnlyIn(Dist.CLIENT)
|
||||||
private static void experimentalRendering(String value) {
|
private static void experimentalRendering(String value) {
|
||||||
boolean last = AllConfigs.CLIENT.experimentalRendering.get();
|
if (!"".equals(value)) {
|
||||||
AllConfigs.CLIENT.experimentalRendering.set(Boolean.parseBoolean(value));
|
AllConfigs.CLIENT.experimentalRendering.set(Boolean.parseBoolean(value));
|
||||||
|
}
|
||||||
FastRenderDispatcher.refresh();
|
FastRenderDispatcher.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,8 +15,8 @@ public class CClient extends ConfigBase {
|
|||||||
public ConfigBool rainbowDebug =
|
public ConfigBool rainbowDebug =
|
||||||
b(true, "enableRainbowDebug", "Show colourful debug information while the F3-Menu is open.");
|
b(true, "enableRainbowDebug", "Show colourful debug information while the F3-Menu is open.");
|
||||||
|
|
||||||
public ConfigRender experimentalRendering =
|
public ConfigBool experimentalRendering =
|
||||||
new ConfigRender("experimentalRendering", true, "Use modern OpenGL features to drastically increase performance.");
|
b(true, "experimentalRendering", "Use modern OpenGL features to drastically increase performance.");
|
||||||
|
|
||||||
public ConfigInt overlayOffsetX = i(20, Integer.MIN_VALUE, Integer.MAX_VALUE, "overlayOffsetX", "Offset the overlay from goggle- and hover- information by this many pixels on the X axis; Use /create overlay");
|
public ConfigInt overlayOffsetX = i(20, Integer.MIN_VALUE, Integer.MAX_VALUE, "overlayOffsetX", "Offset the overlay from goggle- and hover- information by this many pixels on the X axis; Use /create overlay");
|
||||||
public ConfigInt overlayOffsetY = i(0, Integer.MIN_VALUE, Integer.MAX_VALUE, "overlayOffsetY", "Offset the overlay from goggle- and hover- information by this many pixels on the Y axis; Use /create overlay");
|
public ConfigInt overlayOffsetY = i(0, Integer.MIN_VALUE, Integer.MAX_VALUE, "overlayOffsetY", "Offset the overlay from goggle- and hover- information by this many pixels on the Y axis; Use /create overlay");
|
||||||
@ -25,27 +25,4 @@ public class CClient extends ConfigBase {
|
|||||||
public String getName() {
|
public String getName() {
|
||||||
return "client";
|
return "client";
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ConfigRender extends ConfigBool {
|
|
||||||
|
|
||||||
public ConfigRender(String name, boolean def, String... comment) {
|
|
||||||
super(name, def, comment);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the configured value and checks if the rendering is actually supported.
|
|
||||||
* @return True if fast rendering is enabled and the current system/configuration is capable.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Boolean get() {
|
|
||||||
return super.get() && Backend.canUse();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void set(Boolean value) {
|
|
||||||
super.set(value);
|
|
||||||
Backend.enabled = get();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
package com.simibubi.create.foundation.mixin;
|
package com.simibubi.create.foundation.mixin;
|
||||||
|
|
||||||
import com.simibubi.create.foundation.render.backend.FastRenderDispatcher;
|
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher;
|
||||||
|
import com.simibubi.create.foundation.render.backend.light.ILightListener;
|
||||||
import net.minecraft.client.multiplayer.ClientChunkProvider;
|
import net.minecraft.client.multiplayer.ClientChunkProvider;
|
||||||
import net.minecraft.util.math.SectionPos;
|
import net.minecraft.util.math.SectionPos;
|
||||||
|
import net.minecraft.world.ILightReader;
|
||||||
import net.minecraft.world.LightType;
|
import net.minecraft.world.LightType;
|
||||||
import net.minecraft.world.chunk.AbstractChunkProvider;
|
import net.minecraft.world.chunk.AbstractChunkProvider;
|
||||||
|
import net.minecraft.world.chunk.Chunk;
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
@ -12,6 +15,8 @@ import org.spongepowered.asm.mixin.injection.At;
|
|||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@OnlyIn(Dist.CLIENT)
|
@OnlyIn(Dist.CLIENT)
|
||||||
@Mixin(ClientChunkProvider.class)
|
@Mixin(ClientChunkProvider.class)
|
||||||
public abstract class LightUpdateMixin extends AbstractChunkProvider {
|
public abstract class LightUpdateMixin extends AbstractChunkProvider {
|
||||||
@ -24,6 +29,23 @@ public abstract class LightUpdateMixin extends AbstractChunkProvider {
|
|||||||
*/
|
*/
|
||||||
@Inject(at = @At("HEAD"), method = "markLightChanged")
|
@Inject(at = @At("HEAD"), method = "markLightChanged")
|
||||||
private void onLightUpdate(LightType type, SectionPos pos, CallbackInfo ci) {
|
private void onLightUpdate(LightType type, SectionPos pos, CallbackInfo ci) {
|
||||||
FastRenderDispatcher.notifyLightUpdate(((ClientChunkProvider) (Object) this), type, pos);
|
ClientChunkProvider thi = ((ClientChunkProvider) (Object) this);
|
||||||
|
|
||||||
|
Chunk chunk = thi.getChunk(pos.getSectionX(), pos.getSectionZ(), false);
|
||||||
|
|
||||||
|
int sectionY = pos.getSectionY();
|
||||||
|
|
||||||
|
if (chunk != null) {
|
||||||
|
chunk.getTileEntityMap()
|
||||||
|
.entrySet()
|
||||||
|
.stream()
|
||||||
|
.filter(entry -> SectionPos.toChunk(entry.getKey().getY()) == sectionY)
|
||||||
|
.map(Map.Entry::getValue)
|
||||||
|
.filter(tile -> tile instanceof ILightListener)
|
||||||
|
.map(tile -> (ILightListener) tile)
|
||||||
|
.forEach(ILightListener::onChunkLightUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
ContraptionRenderDispatcher.notifyLightUpdate((ILightReader) thi.getWorld(), type, pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,16 @@
|
|||||||
package com.simibubi.create.foundation.mixin;
|
package com.simibubi.create.foundation.mixin;
|
||||||
|
|
||||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher;
|
||||||
|
import com.simibubi.create.foundation.render.backend.Backend;
|
||||||
import com.simibubi.create.foundation.render.backend.FastRenderDispatcher;
|
import com.simibubi.create.foundation.render.backend.FastRenderDispatcher;
|
||||||
|
import com.simibubi.create.foundation.render.backend.OptifineHandler;
|
||||||
|
import net.minecraft.client.renderer.Matrix4f;
|
||||||
import net.minecraft.client.renderer.RenderType;
|
import net.minecraft.client.renderer.RenderType;
|
||||||
import net.minecraft.client.renderer.WorldRenderer;
|
import net.minecraft.client.renderer.WorldRenderer;
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
import org.lwjgl.opengl.GL20;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
@ -21,7 +26,21 @@ public class RenderInLayerMixin {
|
|||||||
* This should probably be a forge event.
|
* This should probably be a forge event.
|
||||||
*/
|
*/
|
||||||
@Inject(at = @At(value = "TAIL"), method = "renderLayer")
|
@Inject(at = @At(value = "TAIL"), method = "renderLayer")
|
||||||
private void renderLayer(RenderType type, MatrixStack stack, double cameraX, double cameraY, double cameraZ, CallbackInfo ci) {
|
private void renderLayer(RenderType type, MatrixStack stack, double camX, double camY, double camZ, CallbackInfo ci) {
|
||||||
FastRenderDispatcher.renderLayer(type, stack, (float) cameraX, (float) cameraY, (float) cameraZ);
|
if (!Backend.available()) return;
|
||||||
|
|
||||||
|
float cameraX = (float) camX;
|
||||||
|
float cameraY = (float) camY;
|
||||||
|
float cameraZ = (float) camZ;
|
||||||
|
|
||||||
|
Matrix4f viewProjection = Matrix4f.translate(-cameraX, -cameraY, -cameraZ);
|
||||||
|
viewProjection.multiplyBackward(stack.peek().getModel());
|
||||||
|
viewProjection.multiplyBackward(FastRenderDispatcher.getProjectionMatrix());
|
||||||
|
|
||||||
|
FastRenderDispatcher.renderLayer(type, viewProjection, cameraX, cameraY, cameraZ);
|
||||||
|
|
||||||
|
ContraptionRenderDispatcher.renderLayer(type, viewProjection, cameraX, cameraY, cameraZ);
|
||||||
|
|
||||||
|
GL20.glUseProgram(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,6 @@ import net.minecraftforge.resource.ISelectiveResourceReloadListener;
|
|||||||
import net.minecraftforge.resource.VanillaResourceType;
|
import net.minecraftforge.resource.VanillaResourceType;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.lwjgl.opengl.ARBVertexProgram;
|
|
||||||
import org.lwjgl.opengl.GL;
|
import org.lwjgl.opengl.GL;
|
||||||
import org.lwjgl.opengl.GLCapabilities;
|
import org.lwjgl.opengl.GLCapabilities;
|
||||||
import org.lwjgl.system.MemoryUtil;
|
import org.lwjgl.system.MemoryUtil;
|
||||||
@ -42,10 +41,9 @@ public class Backend {
|
|||||||
private static final Map<ResourceLocation, ProgramSpec<?>> registry = new HashMap<>();
|
private static final Map<ResourceLocation, ProgramSpec<?>> registry = new HashMap<>();
|
||||||
private static final Map<ProgramSpec<?>, GlProgram> programs = new HashMap<>();
|
private static final Map<ProgramSpec<?>, GlProgram> programs = new HashMap<>();
|
||||||
|
|
||||||
public static boolean enabled;
|
private static boolean enabled;
|
||||||
|
|
||||||
public static GLCapabilities capabilities;
|
public static GLCapabilities capabilities;
|
||||||
private static SystemCapability capability;
|
|
||||||
private static MapBuffer mapBuffer;
|
private static MapBuffer mapBuffer;
|
||||||
|
|
||||||
public Backend() {
|
public Backend() {
|
||||||
@ -102,16 +100,24 @@ public class Backend {
|
|||||||
return Arrays.stream(constants).filter(it -> it.supported(caps)).findFirst().orElse(last);
|
return Arrays.stream(constants).filter(it -> it.supported(caps)).findFirst().orElse(last);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean canUse() {
|
public static boolean canUseInstancing() {
|
||||||
return isCapable() && !OptifineHandler.usingShaders();
|
return enabled && gl33();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SystemCapability getCapability() {
|
public static boolean canUseVBOs() {
|
||||||
return capability;
|
return enabled && gl20();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isCapable() {
|
public static boolean available() {
|
||||||
return capability.isCapable();
|
return enabled && gl20();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean gl33() {
|
||||||
|
return capabilities.OpenGL33;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean gl20() {
|
||||||
|
return capabilities.OpenGL20;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void init() {
|
public static void init() {
|
||||||
@ -132,9 +138,10 @@ public class Backend {
|
|||||||
capabilities = GL.createCapabilities();
|
capabilities = GL.createCapabilities();
|
||||||
mapBuffer = getLatest(MapBuffer.class);
|
mapBuffer = getLatest(MapBuffer.class);
|
||||||
|
|
||||||
|
OptifineHandler.refresh();
|
||||||
refresh();
|
refresh();
|
||||||
|
|
||||||
if (isCapable()) {
|
if (gl20()) {
|
||||||
|
|
||||||
programs.values().forEach(GlProgram::delete);
|
programs.values().forEach(GlProgram::delete);
|
||||||
programs.clear();
|
programs.clear();
|
||||||
@ -146,13 +153,7 @@ public class Backend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void refresh() {
|
public static void refresh() {
|
||||||
if (capabilities.OpenGL33) {
|
enabled = AllConfigs.CLIENT.experimentalRendering.get() && !OptifineHandler.usingShaders();
|
||||||
capability = SystemCapability.CAPABLE;
|
|
||||||
} else {
|
|
||||||
capability = SystemCapability.INCAPABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
enabled = AllConfigs.CLIENT.experimentalRendering.get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <P extends GlProgram, S extends ProgramSpec<P>> void loadProgram(IResourceManager manager, S programSpec) {
|
private static <P extends GlProgram, S extends ProgramSpec<P>> void loadProgram(IResourceManager manager, S programSpec) {
|
||||||
|
@ -30,6 +30,7 @@ import net.minecraft.world.World;
|
|||||||
import net.minecraft.world.chunk.Chunk;
|
import net.minecraft.world.chunk.Chunk;
|
||||||
import org.lwjgl.opengl.GL11;
|
import org.lwjgl.opengl.GL11;
|
||||||
import org.lwjgl.opengl.GL20;
|
import org.lwjgl.opengl.GL20;
|
||||||
|
import org.lwjgl.system.CallbackI;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -40,7 +41,7 @@ import java.util.function.Consumer;
|
|||||||
public class FastRenderDispatcher {
|
public class FastRenderDispatcher {
|
||||||
|
|
||||||
public static WorldAttached<ConcurrentHashMap.KeySetView<TileEntity, Boolean>> queuedUpdates = new WorldAttached<>(ConcurrentHashMap::newKeySet);
|
public static WorldAttached<ConcurrentHashMap.KeySetView<TileEntity, Boolean>> queuedUpdates = new WorldAttached<>(ConcurrentHashMap::newKeySet);
|
||||||
public static WorldAttached<ConcurrentHashMap.KeySetView<TileEntity, Boolean>> addedLastTick = new WorldAttached<>(ConcurrentHashMap::newKeySet);
|
public static WorldAttached<ConcurrentHashMap<TileEntity, Integer>> addedLastTick = new WorldAttached<>(ConcurrentHashMap::new);
|
||||||
|
|
||||||
private static Matrix4f projectionMatrixThisFrame = null;
|
private static Matrix4f projectionMatrixThisFrame = null;
|
||||||
|
|
||||||
@ -55,18 +56,36 @@ public class FastRenderDispatcher {
|
|||||||
public static void tick() {
|
public static void tick() {
|
||||||
ClientWorld world = Minecraft.getInstance().world;
|
ClientWorld world = Minecraft.getInstance().world;
|
||||||
|
|
||||||
runQueue(addedLastTick.get(world), CreateClient.kineticRenderer::onLightUpdate);
|
// Clean up twice a second. This doesn't have to happen every tick,
|
||||||
CreateClient.kineticRenderer.clean();
|
// but this does need to be run to ensure we don't miss anything.
|
||||||
|
int ticks = AnimationTickHolder.getTicks();
|
||||||
|
|
||||||
|
ConcurrentHashMap<TileEntity, Integer> map = addedLastTick.get(world);
|
||||||
|
map
|
||||||
|
.entrySet()
|
||||||
|
.stream()
|
||||||
|
.filter(it -> ticks - it.getValue() > 10)
|
||||||
|
.map(Map.Entry::getKey)
|
||||||
|
.forEach(te -> {
|
||||||
|
map.remove(te);
|
||||||
|
|
||||||
|
CreateClient.kineticRenderer.onLightUpdate(te);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
if (ticks % 10 == 0) {
|
||||||
|
CreateClient.kineticRenderer.clean();
|
||||||
|
}
|
||||||
|
|
||||||
runQueue(queuedUpdates.get(world), CreateClient.kineticRenderer::update);
|
runQueue(queuedUpdates.get(world), CreateClient.kineticRenderer::update);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean available() {
|
public static boolean available() {
|
||||||
return Backend.enabled;
|
return Backend.canUseInstancing();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean available(World world) {
|
public static boolean available(World world) {
|
||||||
return Backend.enabled && !(world instanceof SchematicWorld);
|
return Backend.canUseInstancing() && !(world instanceof SchematicWorld);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getDebugMode() {
|
public static int getDebugMode() {
|
||||||
@ -77,6 +96,7 @@ public class FastRenderDispatcher {
|
|||||||
RenderWork.enqueue(() -> {
|
RenderWork.enqueue(() -> {
|
||||||
CreateClient.kineticRenderer.invalidate();
|
CreateClient.kineticRenderer.invalidate();
|
||||||
OptifineHandler.refresh();
|
OptifineHandler.refresh();
|
||||||
|
Backend.refresh();
|
||||||
Minecraft.getInstance().worldRenderer.loadRenderers();
|
Minecraft.getInstance().worldRenderer.loadRenderers();
|
||||||
ClientWorld world = Minecraft.getInstance().world;
|
ClientWorld world = Minecraft.getInstance().world;
|
||||||
if (world != null) world.loadedTileEntityList.forEach(CreateClient.kineticRenderer::add);
|
if (world != null) world.loadedTileEntityList.forEach(CreateClient.kineticRenderer::add);
|
||||||
@ -97,12 +117,8 @@ public class FastRenderDispatcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void renderLayer(RenderType layer, MatrixStack stack, float cameraX, float cameraY, float cameraZ) {
|
public static void renderLayer(RenderType layer, Matrix4f viewProjection, float cameraX, float cameraY, float cameraZ) {
|
||||||
if (!available()) return;
|
if (!Backend.canUseInstancing()) return;
|
||||||
|
|
||||||
Matrix4f viewProjection = Matrix4f.translate(-cameraX, -cameraY, -cameraZ);
|
|
||||||
viewProjection.multiplyBackward(stack.peek().getModel());
|
|
||||||
viewProjection.multiplyBackward(getProjectionMatrix());
|
|
||||||
|
|
||||||
layer.startDrawing();
|
layer.startDrawing();
|
||||||
|
|
||||||
@ -113,31 +129,9 @@ public class FastRenderDispatcher {
|
|||||||
RenderSystem.disableCull();
|
RenderSystem.disableCull();
|
||||||
//RenderSystem.disableDepthTest();
|
//RenderSystem.disableDepthTest();
|
||||||
|
|
||||||
ContraptionRenderDispatcher.renderLayer(layer, viewProjection, cameraX, cameraY, cameraZ);
|
|
||||||
if (!OptifineHandler.usingShaders())
|
|
||||||
GL20.glUseProgram(0);
|
|
||||||
layer.endDrawing();
|
layer.endDrawing();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void notifyLightUpdate(ClientChunkProvider world, LightType type, SectionPos pos) {
|
|
||||||
ContraptionRenderDispatcher.notifyLightUpdate((ILightReader) world.getWorld(), type, pos);
|
|
||||||
|
|
||||||
Chunk chunk = world.getChunk(pos.getSectionX(), pos.getSectionZ(), false);
|
|
||||||
|
|
||||||
int sectionY = pos.getSectionY();
|
|
||||||
|
|
||||||
if (chunk != null) {
|
|
||||||
chunk.getTileEntityMap()
|
|
||||||
.entrySet()
|
|
||||||
.stream()
|
|
||||||
.filter(entry -> SectionPos.toChunk(entry.getKey().getY()) == sectionY)
|
|
||||||
.map(Map.Entry::getValue)
|
|
||||||
.filter(tile -> tile instanceof ILightListener)
|
|
||||||
.map(tile -> (ILightListener) tile)
|
|
||||||
.forEach(ILightListener::onChunkLightUpdate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// copied from GameRenderer.renderWorld
|
// copied from GameRenderer.renderWorld
|
||||||
public static Matrix4f getProjectionMatrix() {
|
public static Matrix4f getProjectionMatrix() {
|
||||||
if (projectionMatrixThisFrame != null) return projectionMatrixThisFrame;
|
if (projectionMatrixThisFrame != null) return projectionMatrixThisFrame;
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
package com.simibubi.create.foundation.render.backend;
|
|
||||||
|
|
||||||
public enum SystemCapability {
|
|
||||||
/**
|
|
||||||
* The current system does not support enough
|
|
||||||
* OpenGL features to enable fast rendering.
|
|
||||||
*/
|
|
||||||
INCAPABLE,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The current system supports OpenGL 3.3.
|
|
||||||
*/
|
|
||||||
CAPABLE,
|
|
||||||
;
|
|
||||||
|
|
||||||
public boolean isCapable() {
|
|
||||||
return this == CAPABLE;
|
|
||||||
}
|
|
||||||
}
|
|
@ -37,7 +37,7 @@ public abstract class InstancedTileRenderer<P extends BasicProgram> {
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Nullable
|
@Nullable
|
||||||
public <T extends TileEntity> TileEntityInstance<? super T> getInstance(T tile, boolean create) {
|
public <T extends TileEntity> TileEntityInstance<? super T> getInstance(T tile, boolean create) {
|
||||||
if (!Backend.enabled) return null;
|
if (!Backend.canUseInstancing()) return null;
|
||||||
|
|
||||||
TileEntityInstance<?> instance = instances.get(tile);
|
TileEntityInstance<?> instance = instances.get(tile);
|
||||||
|
|
||||||
@ -47,7 +47,7 @@ public abstract class InstancedTileRenderer<P extends BasicProgram> {
|
|||||||
TileEntityInstance<? super T> renderer = InstancedTileRenderRegistry.instance.create(this, tile);
|
TileEntityInstance<? super T> renderer = InstancedTileRenderRegistry.instance.create(this, tile);
|
||||||
|
|
||||||
if (renderer != null) {
|
if (renderer != null) {
|
||||||
FastRenderDispatcher.addedLastTick.get(tile.getWorld()).add(tile);
|
FastRenderDispatcher.addedLastTick.get(tile.getWorld()).put(tile, AnimationTickHolder.getTicks());
|
||||||
instances.put(tile, renderer);
|
instances.put(tile, renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,11 +93,7 @@ public abstract class InstancedTileRenderer<P extends BasicProgram> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void clean() {
|
public void clean() {
|
||||||
// Clean up twice a second. This doesn't have to happen every tick,
|
instances.keySet().stream().filter(TileEntity::isRemoved).forEach(instances::remove);
|
||||||
// but this does need to be run to ensure we don't miss anything.
|
|
||||||
if (AnimationTickHolder.getTicks() % 10 == 0) {
|
|
||||||
instances.keySet().stream().filter(TileEntity::isRemoved).forEach(instances::remove);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void invalidate() {
|
public void invalidate() {
|
||||||
|
Loading…
Reference in New Issue
Block a user