contraptions self light but man it is slow

optimization in PlacementSimulationWorld.getBlockState
This commit is contained in:
JozsefA 2021-01-30 15:00:26 -08:00
parent 751fc7192d
commit 16b8e1175e
11 changed files with 438 additions and 10 deletions

View file

@ -217,6 +217,8 @@ public abstract class KineticTileEntity extends SmartTileEntity
@Override @Override
protected void read(CompoundNBT compound, boolean clientPacket) { protected void read(CompoundNBT compound, boolean clientPacket) {
boolean overStressedBefore = overStressed; boolean overStressedBefore = overStressed;
Long networkBefore = network;
float speedBefore = speed;
clearKineticInformation(); clearKineticInformation();
// DO NOT READ kinetic information when placed after movement // DO NOT READ kinetic information when placed after movement

View file

@ -3,6 +3,7 @@ package com.simibubi.create.content.contraptions.components.structureMovement;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
import net.minecraft.world.lighting.WorldLightManager;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
@ -101,6 +102,15 @@ public class ContraptionRenderer {
for (BlockInfo info : c.getBlocks() for (BlockInfo info : c.getBlocks()
.values()) .values())
renderWorld.setBlockState(info.pos, info.state); renderWorld.setBlockState(info.pos, info.state);
WorldLightManager lighter = renderWorld.lighter;
renderWorld.chunkProvider.getLightSources().forEach((pos) -> {
lighter.func_215573_a(pos, renderWorld.getLightValue(pos));
});
lighter.tick(Integer.MAX_VALUE, true, false);
for (BlockInfo info : c.getBlocks() for (BlockInfo info : c.getBlocks()
.values()) { .values()) {
BlockState state = info.state; BlockState state = info.state;
@ -120,6 +130,7 @@ public class ContraptionRenderer {
builder.finishDrawing(); builder.finishDrawing();
renderWorld.clear(); renderWorld.clear();
renderWorld = null;
return builder; return builder;
} }

View file

@ -4,15 +4,17 @@ import com.simibubi.create.foundation.render.BufferedModel;
import com.simibubi.create.foundation.render.instancing.InstancedModel; import com.simibubi.create.foundation.render.instancing.InstancedModel;
import com.simibubi.create.foundation.render.instancing.VertexFormat; import com.simibubi.create.foundation.render.instancing.VertexFormat;
import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.LightTexture;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL40; import org.lwjgl.opengl.GL40;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import static com.simibubi.create.foundation.render.instancing.VertexAttribute.LIGHT;
import static com.simibubi.create.foundation.render.instancing.VertexAttribute.RGBA; import static com.simibubi.create.foundation.render.instancing.VertexAttribute.RGBA;
public class ContraptionModel extends BufferedModel { public class ContraptionModel extends BufferedModel {
public static final VertexFormat FORMAT = new VertexFormat(InstancedModel.FORMAT, RGBA); public static final VertexFormat FORMAT = new VertexFormat(InstancedModel.FORMAT, RGBA, LIGHT);
public ContraptionModel(BufferBuilder buf) { public ContraptionModel(BufferBuilder buf) {
super(buf); super(buf);
@ -35,6 +37,14 @@ public class ContraptionModel extends BufferedModel {
to.put(getG(template, vertex)); to.put(getG(template, vertex));
to.put(getB(template, vertex)); to.put(getB(template, vertex));
to.put(getA(template, vertex)); to.put(getA(template, vertex));
int light = getLight(template, vertex);
byte sky = (byte) (LightTexture.getSkyLightCoordinates(light) << 4);
byte block = (byte) (LightTexture.getBlockLightCoordinates(light) << 4);
to.put(block);
to.put(sky);
} }
@Override @Override

View file

@ -7,10 +7,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Con
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.gl.shader.ShaderHelper; import com.simibubi.create.foundation.render.gl.shader.ShaderHelper;
import com.simibubi.create.foundation.render.instancing.IInstanceRendered; import com.simibubi.create.foundation.render.instancing.*;
import com.simibubi.create.foundation.render.instancing.InstancedModel;
import com.simibubi.create.foundation.render.instancing.KineticRenderMaterials;
import com.simibubi.create.foundation.render.instancing.RenderMaterial;
import com.simibubi.create.foundation.render.instancing.actors.StaticRotatingActorData; import com.simibubi.create.foundation.render.instancing.actors.StaticRotatingActorData;
import com.simibubi.create.foundation.render.light.ContraptionLighter; import com.simibubi.create.foundation.render.light.ContraptionLighter;
import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.BufferBuilder;

View file

@ -3,7 +3,7 @@ package com.simibubi.create.foundation.render.gl.shader;
public enum Shader { public enum Shader {
ROTATING("shader/rotating.vert", "shader/instanced.frag"), ROTATING("shader/rotating.vert", "shader/instanced.frag"),
BELT("shader/belt.vert", "shader/instanced.frag"), BELT("shader/belt.vert", "shader/instanced.frag"),
CONTRAPTION_STRUCTURE("shader/contraption.vert", "shader/contraption.frag"), CONTRAPTION_STRUCTURE("shader/contraption_structure.vert", "shader/contraption_structure.frag"),
CONTRAPTION_ROTATING("shader/contraption_rotating.vert", "shader/contraption.frag"), CONTRAPTION_ROTATING("shader/contraption_rotating.vert", "shader/contraption.frag"),
CONTRAPTION_BELT("shader/contraption_belt.vert", "shader/contraption.frag"), CONTRAPTION_BELT("shader/contraption_belt.vert", "shader/contraption.frag"),
CONTRAPTION_ACTOR("shader/contraption_actor.vert", "shader/contraption.frag"), CONTRAPTION_ACTOR("shader/contraption_actor.vert", "shader/contraption.frag"),

View file

@ -2,24 +2,50 @@ package com.simibubi.create.foundation.utility.worldWrappers;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.function.Predicate; import java.util.function.Predicate;
import com.simibubi.create.foundation.render.light.GridAlignedBB;
import com.simibubi.create.foundation.utility.Iterate;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.math.SectionPos;
import net.minecraft.world.LightType;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.chunk.NibbleArray;
import net.minecraft.world.lighting.WorldLightManager;
public class PlacementSimulationWorld extends WrappedWorld { public class PlacementSimulationWorld extends WrappedWorld {
public HashMap<BlockPos, BlockState> blocksAdded; public HashMap<BlockPos, BlockState> blocksAdded;
public HashMap<BlockPos, TileEntity> tesAdded; public HashMap<BlockPos, TileEntity> tesAdded;
public HashSet<SectionPos> spannedChunks;
public WorldLightManager lighter;
public WrappedChunkProvider chunkProvider;
private final BlockPos.Mutable scratch = new BlockPos.Mutable();
public PlacementSimulationWorld(World wrapped) { public PlacementSimulationWorld(World wrapped) {
super(wrapped); this(wrapped, new WrappedChunkProvider());
}
public PlacementSimulationWorld(World wrapped, WrappedChunkProvider chunkProvider) {
super(wrapped, chunkProvider);
this.chunkProvider = chunkProvider.setWorld(this);
spannedChunks = new HashSet<>();
lighter = new WorldLightManager(chunkProvider, true, false); // blockLight, skyLight
blocksAdded = new HashMap<>(); blocksAdded = new HashMap<>();
tesAdded = new HashMap<>(); tesAdded = new HashMap<>();
} }
@Override
public WorldLightManager getLightingProvider() {
return lighter;
}
public void setTileEntities(Collection<TileEntity> tileEntities) { public void setTileEntities(Collection<TileEntity> tileEntities) {
tesAdded.clear(); tesAdded.clear();
tileEntities.forEach(te -> tesAdded.put(te.getPos(), te)); tileEntities.forEach(te -> tesAdded.put(te.getPos(), te));
@ -31,6 +57,15 @@ public class PlacementSimulationWorld extends WrappedWorld {
@Override @Override
public boolean setBlockState(BlockPos pos, BlockState newState, int flags) { public boolean setBlockState(BlockPos pos, BlockState newState, int flags) {
SectionPos sectionPos = SectionPos.from(pos);
if (spannedChunks.add(sectionPos)) {
lighter.updateSectionStatus(sectionPos, false);
}
lighter.checkBlock(pos);
blocksAdded.put(pos, newState); blocksAdded.put(pos, newState);
return true; return true;
} }
@ -62,9 +97,11 @@ public class PlacementSimulationWorld extends WrappedWorld {
@Override @Override
public BlockState getBlockState(BlockPos pos) { public BlockState getBlockState(BlockPos pos) {
if (blocksAdded.containsKey(pos)) BlockState state = blocksAdded.get(pos);
return blocksAdded.get(pos); if (state != null)
return Blocks.AIR.getDefaultState(); return state;
else
return Blocks.AIR.getDefaultState();
} }
} }

View file

@ -0,0 +1,82 @@
package com.simibubi.create.foundation.utility.worldWrappers;
import com.simibubi.create.foundation.utility.worldWrappers.chunk.WrappedChunk;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.chunk.AbstractChunkProvider;
import net.minecraft.world.chunk.ChunkStatus;
import net.minecraft.world.chunk.IChunk;
import net.minecraft.world.chunk.IChunkLightProvider;
import net.minecraft.world.lighting.WorldLightManager;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BooleanSupplier;
import java.util.stream.Stream;
public class WrappedChunkProvider extends AbstractChunkProvider {
private PlacementSimulationWorld world;
public HashMap<Long, WrappedChunk> chunks;
public WrappedChunkProvider setWorld(PlacementSimulationWorld world) {
this.world = world;
this.chunks = new HashMap<>();
return this;
}
public Stream<BlockPos> getLightSources() {
return world.blocksAdded
.entrySet()
.stream()
.filter(it -> it.getValue().getLightValue(world, it.getKey()) != 0)
.map(Map.Entry::getKey);
}
@Nullable
@Override
public IBlockReader getChunkForLight(int x, int z) {
return getChunk(x, z);
}
@Override
public IBlockReader getWorld() {
return world;
}
@Nullable
@Override
public IChunk getChunk(int x, int z, ChunkStatus status, boolean p_212849_4_) {
return getChunk(x, z);
}
public WrappedChunk getChunk(int x, int z) {
long pos = ChunkPos.asLong(x, z);
WrappedChunk chunk = chunks.get(pos);
if (chunk == null) {
chunk = new WrappedChunk(world, x, z);
chunks.put(pos, chunk);
}
return chunk;
}
@Override
public void tick(BooleanSupplier p_217207_1_) {
}
@Override
public String makeString() {
return "WrappedChunkProvider";
}
@Override
public WorldLightManager getLightManager() {
return world.getLightingProvider();
}
}

View file

@ -19,18 +19,30 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.world.ITickList; import net.minecraft.world.ITickList;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.biome.Biome; import net.minecraft.world.biome.Biome;
import net.minecraft.world.lighting.WorldLightManager;
import net.minecraft.world.storage.MapData; import net.minecraft.world.storage.MapData;
public class WrappedWorld extends World { public class WrappedWorld extends World {
protected World world; protected World world;
public WrappedWorld(World world, WrappedChunkProvider provider) {
super(world.getWorldInfo(), world.getDimension().getType(), (w, d) -> provider,
world.getProfiler(), world.isRemote);
this.world = world;
}
public WrappedWorld(World world) { public WrappedWorld(World world) {
super(world.getWorldInfo(), world.getDimension().getType(), (w, d) -> world.getChunkProvider(), super(world.getWorldInfo(), world.getDimension().getType(), (w, d) -> world.getChunkProvider(),
world.getProfiler(), world.isRemote); world.getProfiler(), world.isRemote);
this.world = world; this.world = world;
} }
@Override
public WorldLightManager getLightingProvider() {
return super.getLightingProvider();
}
@Override @Override
public World getWorld() { public World getWorld() {
return world; return world;

View file

@ -0,0 +1,250 @@
package com.simibubi.create.foundation.utility.worldWrappers.chunk;
import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld;
import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld;
import it.unimi.dsi.fastutil.longs.LongSet;
import it.unimi.dsi.fastutil.shorts.ShortList;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity;
import net.minecraft.fluid.Fluid;
import net.minecraft.fluid.IFluidState;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.palette.UpgradeData;
import net.minecraft.world.ITickList;
import net.minecraft.world.biome.BiomeContainer;
import net.minecraft.world.chunk.ChunkSection;
import net.minecraft.world.chunk.ChunkStatus;
import net.minecraft.world.chunk.IChunk;
import net.minecraft.world.gen.Heightmap;
import net.minecraft.world.gen.feature.structure.StructureStart;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.stream.Stream;
public class WrappedChunk implements IChunk {
private final PlacementSimulationWorld world;
private boolean needsLight;
private final int x;
private final int z;
private final ChunkPos pos;
public WrappedChunk(PlacementSimulationWorld world, int x, int z) {
this.world = world;
this.needsLight = true;
this.x = x;
this.z = z;
this.pos = new ChunkPos(x, z);
}
@Override
public Stream<BlockPos> getLightSources() {
return world.blocksAdded
.entrySet()
.stream()
.filter(it -> {
BlockPos blockPos = it.getKey();
boolean chunkContains = blockPos.getX() >> 4 == x && blockPos.getZ() >> 4 == z;
return chunkContains && it.getValue().getLightValue(world, blockPos) != 0;
})
.map(Map.Entry::getKey);
}
@Nullable
@Override
public BlockState setBlockState(BlockPos p_177436_1_, BlockState p_177436_2_, boolean p_177436_3_) {
return null;
}
@Override
public void addTileEntity(BlockPos p_177426_1_, TileEntity p_177426_2_) {
}
@Override
public void addEntity(Entity p_76612_1_) {
}
@Override
public Set<BlockPos> getTileEntitiesPos() {
return null;
}
@Override
public ChunkSection[] getSections() {
return new ChunkSection[0];
}
@Override
public Collection<Map.Entry<Heightmap.Type, Heightmap>> func_217311_f() {
return null;
}
@Override
public void setHeightmap(Heightmap.Type p_201607_1_, long[] p_201607_2_) {
}
@Override
public Heightmap getHeightmap(Heightmap.Type p_217303_1_) {
return null;
}
@Override
public int getTopBlockY(Heightmap.Type p_201576_1_, int p_201576_2_, int p_201576_3_) {
return 0;
}
@Override
public ChunkPos getPos() {
return null;
}
@Override
public void setLastSaveTime(long p_177432_1_) {
}
@Override
public Map<String, StructureStart> getStructureStarts() {
return null;
}
@Override
public void setStructureStarts(Map<String, StructureStart> p_201612_1_) {
}
@Nullable
@Override
public BiomeContainer getBiomeArray() {
return null;
}
@Override
public void setModified(boolean p_177427_1_) {
}
@Override
public boolean isModified() {
return false;
}
@Override
public ChunkStatus getStatus() {
return null;
}
@Override
public void removeTileEntity(BlockPos p_177425_1_) {
}
@Override
public ShortList[] getPackedPositions() {
return new ShortList[0];
}
@Nullable
@Override
public CompoundNBT getDeferredTileEntity(BlockPos p_201579_1_) {
return null;
}
@Nullable
@Override
public CompoundNBT func_223134_j(BlockPos p_223134_1_) {
return null;
}
@Override
public ITickList<Block> getBlocksToBeTicked() {
return null;
}
@Override
public ITickList<Fluid> getFluidsToBeTicked() {
return null;
}
@Override
public UpgradeData getUpgradeData() {
return null;
}
@Override
public void setInhabitedTime(long p_177415_1_) {
}
@Override
public long getInhabitedTime() {
return 0;
}
@Override
public boolean hasLight() {
return needsLight;
}
@Override
public void setLight(boolean needsLight) {
this.needsLight = needsLight;
}
@Nullable
@Override
public TileEntity getTileEntity(BlockPos pos) {
return null;
}
@Override
public BlockState getBlockState(BlockPos pos) {
return world.getBlockState(pos);
}
@Override
public IFluidState getFluidState(BlockPos pos) {
return null;
}
@Nullable
@Override
public StructureStart getStructureStart(String p_201585_1_) {
return null;
}
@Override
public void putStructureStart(String p_201584_1_, StructureStart p_201584_2_) {
}
@Override
public LongSet getStructureReferences(String p_201578_1_) {
return null;
}
@Override
public void addStructureReference(String p_201583_1_, long p_201583_2_) {
}
@Override
public Map<String, LongSet> getStructureReferences() {
return null;
}
@Override
public void setStructureReferences(Map<String, LongSet> p_201606_1_) {
}
}

View file

@ -0,0 +1,24 @@
#version 440 core
in vec2 TexCoords;
in vec4 Color;
in float Diffuse;
in vec3 BoxCoord;
in vec2 ModelLight;
out vec4 fragColor;
layout(binding=0) uniform sampler2D BlockAtlas;
layout(binding=2) uniform sampler2D LightMap;
layout(binding=4) uniform sampler3D LightVolume;
vec4 light() {
vec2 lm = texture(LightVolume, BoxCoord).rg * 0.9375 + 0.03125;
return texture2D(LightMap, max(lm, ModelLight));
}
void main() {
vec4 tex = texture2D(BlockAtlas, TexCoords);
fragColor = vec4(tex.rgb * light().rgb * Diffuse * Color.rgb, tex.a);
}

View file

@ -5,11 +5,13 @@ layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal; layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords; layout (location = 2) in vec2 aTexCoords;
layout (location = 3) in vec4 aColor; layout (location = 3) in vec4 aColor;
layout (location = 4) in vec2 modelLight;
out float Diffuse; out float Diffuse;
out vec2 TexCoords; out vec2 TexCoords;
out vec4 Color; out vec4 Color;
out vec3 BoxCoord; out vec3 BoxCoord;
out vec2 ModelLight;
uniform vec3 lightBoxSize; uniform vec3 lightBoxSize;
uniform vec3 lightBoxMin; uniform vec3 lightBoxMin;
@ -48,6 +50,7 @@ void main() {
Diffuse = diffuse(norm); Diffuse = diffuse(norm);
Color = aColor / diffuse(aNormal); Color = aColor / diffuse(aNormal);
TexCoords = aTexCoords; TexCoords = aTexCoords;
ModelLight = modelLight;
gl_Position = projection * view * worldPos; gl_Position = projection * view * worldPos;
if (debug == 2) { if (debug == 2) {