pistons are lit and bearings are better lit in the corners

stop sampling light in places that don't matter
This commit is contained in:
JozsefA 2021-01-18 00:31:33 -08:00
parent 22a90c8e5d
commit 398a848791
13 changed files with 150 additions and 221 deletions

View File

@ -190,7 +190,7 @@ public abstract class Contraption {
// Create subcontraptions
for (BlockFace blockFace : pendingSubContraptions) {
Direction face = blockFace.getFace();
StabilizedContraption subContraption = new StabilizedContraption(face);
StabilizedContraption subContraption = new StabilizedContraption(this, face);
World world = entity.world;
BlockPos pos = blockFace.getPos();
if (!subContraption.assemble(world, pos))

View File

@ -13,6 +13,7 @@ public class BearingLighter extends ContraptionLighter<BearingContraption> {
@Override
public GridAlignedBB getContraptionBounds() {
GridAlignedBB localBounds = GridAlignedBB.fromAABB(contraption.bounds);
localBounds.rotate45(contraption.getFacing().getAxis());
localBounds.translate(contraption.anchor);
return localBounds;
}

View File

@ -11,11 +11,14 @@ import net.minecraft.world.World;
public class StabilizedContraption extends Contraption {
public Contraption parent;
private Direction facing;
public StabilizedContraption() {}
public StabilizedContraption(Direction facing) {
public StabilizedContraption(Contraption parent, Direction facing) {
this.parent = parent;
this.facing = facing;
}

View File

@ -5,6 +5,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Blo
import com.simibubi.create.content.contraptions.components.structureMovement.TranslatingContraption;
import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.*;
import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.render.light.ContraptionLighter;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.block.BlockState;
import net.minecraft.block.CarpetBlock;
@ -18,6 +19,8 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IWorld;
import net.minecraft.world.World;
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.apache.commons.lang3.tuple.Pair;
import java.util.ArrayList;
@ -226,4 +229,9 @@ public class PistonContraption extends TranslatingContraption {
return tag;
}
@OnlyIn(Dist.CLIENT)
@Override
public ContraptionLighter<?> makeLighter() {
return new PistonLighter(this);
}
}

View File

@ -0,0 +1,35 @@
package com.simibubi.create.content.contraptions.components.structureMovement.piston;
import com.simibubi.create.foundation.render.light.ContraptionLighter;
import com.simibubi.create.foundation.render.light.GridAlignedBB;
import net.minecraft.util.Direction;
import net.minecraft.util.math.Vec3i;
public class PistonLighter extends ContraptionLighter<PistonContraption> {
public PistonLighter(PistonContraption contraption) {
super(contraption);
}
@Override
public GridAlignedBB getContraptionBounds() {
GridAlignedBB bounds = GridAlignedBB.fromAABB(contraption.bounds);
bounds.translate(contraption.anchor);
int length = contraption.extensionLength;
Vec3i direction = contraption.orientation.getDirectionVec();
int shift = length / 2;
int shiftX = direction.getX() * shift;
int shiftY = direction.getY() * shift;
int shiftZ = direction.getZ() * shift;
bounds.translate(shiftX, shiftY, shiftZ);
int grow = (length + 1) / 2;
int extendX = Math.abs(direction.getX() * grow);
int extendY = Math.abs(direction.getY() * grow);
int extendZ = Math.abs(direction.getZ() * grow);
bounds.grow(extendX, extendY, extendZ);
return bounds;
}
}

View File

@ -126,7 +126,7 @@ public class ClientEvents {
CouplingRenderer.renderAll(ms, buffer);
CreateClient.schematicHandler.render(ms, buffer);
CreateClient.outliner.renderOutlines(ms, buffer);
LightVolumeDebugger.render(ms, buffer);
// LightVolumeDebugger.render(ms, buffer);
// CollisionDebugger.render(ms, buffer);
buffer.draw();

View File

@ -1,6 +1,12 @@
package com.simibubi.create.foundation.render;
public class RenderMath {
public static final float SQRT2 = 1.41421356237f;
public static int timesSqrt2(int i) {
return (int) Math.floor((float) i * SQRT2 / 4f);
}
public static int nextPowerOf2(int a) {
int h = Integer.highestOneBit(a);
return (h == a) ? h : (h << 1);

View File

@ -1,165 +0,0 @@
package com.simibubi.create.foundation.render;
import net.minecraft.client.renderer.GLAllocation;
import sun.nio.ch.DirectBuffer;
import java.nio.*;
public class SafeDirectBuffer implements AutoCloseable {
private ByteBuffer wrapped;
public SafeDirectBuffer(int capacity) {
this.wrapped = GLAllocation.createDirectByteBuffer(capacity);
}
public void close() throws Exception {
if (wrapped instanceof DirectBuffer) {
((DirectBuffer) wrapped).cleaner().clean();
}
}
/**
* Only use this function to pass information to OpenGL.
*/
@Deprecated
public ByteBuffer getBacking() {
return wrapped;
}
public void order(ByteOrder bo) {
wrapped.order(bo);
}
public void limit(int limit) {
wrapped.limit(limit);
}
public void rewind() {
wrapped.rewind();
}
public byte get() {
return wrapped.get();
}
public ByteBuffer put(byte b) {
return wrapped.put(b);
}
public byte get(int index) {
return wrapped.get();
}
public ByteBuffer put(int index, byte b) {
return wrapped.put(index, b);
}
public ByteBuffer compact() {
return wrapped.compact();
}
public boolean isReadOnly() {
return wrapped.isReadOnly();
}
public boolean isDirect() {
return wrapped.isDirect();
}
public char getChar() {
return wrapped.getChar();
}
public ByteBuffer putChar(char value) {
return wrapped.putChar(value);
}
public char getChar(int index) {
return wrapped.getChar(index);
}
public ByteBuffer putChar(int index, char value) {
return wrapped.putChar(index, value);
}
public short getShort() {
return wrapped.getShort();
}
public ByteBuffer putShort(short value) {
return wrapped.putShort(value);
}
public short getShort(int index) {
return wrapped.getShort(index);
}
public ByteBuffer putShort(int index, short value) {
return wrapped.putShort(index, value);
}
public int getInt() {
return wrapped.getInt();
}
public ByteBuffer putInt(int value) {
return wrapped.putInt(value);
}
public int getInt(int index) {
return wrapped.getInt(index);
}
public ByteBuffer putInt(int index, int value) {
return wrapped.putInt(index, value);
}
public long getLong() {
return wrapped.getLong();
}
public ByteBuffer putLong(long value) {
return wrapped.putLong(value);
}
public long getLong(int index) {
return wrapped.getLong(index);
}
public ByteBuffer putLong(int index, long value) {
return wrapped.putLong(index, value);
}
public float getFloat() {
return wrapped.getFloat();
}
public ByteBuffer putFloat(float value) {
return wrapped.putFloat(value);
}
public float getFloat(int index) {
return wrapped.getFloat(index);
}
public ByteBuffer putFloat(int index, float value) {
return wrapped.putFloat(index, value);
}
public double getDouble() {
return wrapped.getDouble();
}
public ByteBuffer putDouble(double value) {
return wrapped.putDouble(value);
}
public double getDouble(int index) {
return wrapped.getDouble(index);
}
public ByteBuffer putDouble(int index, double value) {
return wrapped.putDouble(index, value);
}
}

View File

@ -4,7 +4,6 @@ package com.simibubi.create.foundation.render.instancing;
import com.mojang.blaze3d.platform.GlStateManager;
import com.simibubi.create.foundation.render.RenderMath;
import com.simibubi.create.foundation.render.RenderWork;
import com.simibubi.create.foundation.render.SafeDirectBuffer;
import com.simibubi.create.foundation.render.TemplateBuffer;
import net.minecraft.client.renderer.BufferBuilder;
import org.lwjgl.opengl.*;

View File

@ -16,9 +16,10 @@ public abstract class ContraptionLighter<C extends Contraption> {
GridAlignedBB bounds = getContraptionBounds();
bounds.grow(1); // so we have at least enough data on the edges to avoid artifacts
GridAlignedBB importantArea = GridAlignedBB.copy(bounds);
bounds.nextPowerOf2Centered();
lightVolume = new LightVolume(bounds);
lightVolume = new LightVolume(bounds, importantArea);
lightVolume.initialize(contraption.entity.world);
}

View File

@ -1,6 +1,7 @@
package com.simibubi.create.foundation.render.light;
import com.simibubi.create.foundation.render.RenderMath;
import net.minecraft.util.Direction;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.SectionPos;
@ -79,12 +80,26 @@ public class GridAlignedBB {
}
public void translate(Vec3i by) {
this.minX += by.getX();
this.minY += by.getY();
this.minZ += by.getZ();
this.maxX += by.getX();
this.maxY += by.getY();
this.maxZ += by.getZ();
translate(by.getX(), by.getY(), by.getZ());
}
public void translate(int x, int y, int z) {
minX += x;
maxX += x;
minY += y;
maxY += y;
minZ += z;
maxZ += z;
}
public void rotate45(Direction.Axis axis) {
if (axis == Direction.Axis.X) {
this.grow(0, RenderMath.timesSqrt2(sizeY()), RenderMath.timesSqrt2(sizeZ()));
} else if (axis == Direction.Axis.Y) {
this.grow(RenderMath.timesSqrt2(sizeX()), 0, RenderMath.timesSqrt2(sizeZ()));
} else if (axis == Direction.Axis.Z) {
this.grow(RenderMath.timesSqrt2(sizeX()), RenderMath.timesSqrt2(sizeY()), 0);
}
}
/**
@ -103,12 +118,12 @@ public class GridAlignedBB {
int diffY = newSizeY - sizeY;
int diffZ = newSizeZ - sizeZ;
this.minX -= diffX / 2; // floor division for the minimums
this.minY -= diffY / 2;
this.minZ -= diffZ / 2;
this.maxX += (diffX + 1) / 2; // ceiling divison for the maximums
this.maxY += (diffY + 1) / 2;
this.maxZ += (diffZ + 1) / 2;
minX -= diffX / 2; // floor division for the minimums
minY -= diffY / 2;
minZ -= diffZ / 2;
maxX += (diffX + 1) / 2; // ceiling divison for the maximums
maxY += (diffY + 1) / 2;
maxZ += (diffZ + 1) / 2;
}
/**
@ -134,12 +149,12 @@ public class GridAlignedBB {
}
public void grow(int x, int y, int z) {
this.minX -= x;
this.minY -= y;
this.minZ -= z;
this.maxX += x;
this.maxY += y;
this.maxZ += z;
minX -= x;
minY -= y;
minZ -= z;
maxX += x;
maxY += y;
maxZ += z;
}
public GridAlignedBB intersect(GridAlignedBB other) {

View File

@ -10,70 +10,80 @@ import org.lwjgl.system.MemoryUtil;
import java.nio.ByteBuffer;
// TODO: Don't immediately destroy light volumes.
// There's a high chance that a contraption will stop and soon after start again.
// By caching lightvolumes based on their volumes/locations, we can save having
// to reread all the lighting data in those cases.
public class LightVolume {
private final GridAlignedBB volume;
private final GridAlignedBB sampleVolume;
private final GridAlignedBB textureVolume;
private ByteBuffer lightData;
private boolean bufferDirty;
private int glTexture;
public LightVolume(GridAlignedBB volume) {
public LightVolume(GridAlignedBB textureVolume, GridAlignedBB sampleVolume) {
// the gpu requires that all textures have power of 2 side lengths
if (!volume.hasPowerOf2Sides())
if (!textureVolume.hasPowerOf2Sides())
throw new IllegalArgumentException("LightVolume must have power of 2 side lengths");
this.volume = volume;
this.textureVolume = textureVolume;
this.sampleVolume = sampleVolume;
this.glTexture = GL11.glGenTextures();
this.lightData = MemoryUtil.memAlloc(this.volume.volume() * 2); // TODO: maybe figure out how to pack light coords into a single byte
this.lightData = MemoryUtil.memAlloc(this.textureVolume.volume() * 2); // TODO: maybe figure out how to pack light coords into a single byte
}
public GridAlignedBB getBox() {
return GridAlignedBB.copy(volume);
public GridAlignedBB getTextureVolume() {
return GridAlignedBB.copy(textureVolume);
}
public GridAlignedBB getSampleVolume() {
return GridAlignedBB.copy(sampleVolume);
}
public int getMinX() {
return volume.minX;
return textureVolume.minX;
}
public int getMinY() {
return volume.minY;
return textureVolume.minY;
}
public int getMinZ() {
return volume.minZ;
return textureVolume.minZ;
}
public int getMaxX() {
return volume.maxX;
return textureVolume.maxX;
}
public int getMaxY() {
return volume.maxY;
return textureVolume.maxY;
}
public int getMaxZ() {
return volume.maxZ;
return textureVolume.maxZ;
}
public int getSizeX() {
return volume.sizeX();
return textureVolume.sizeX();
}
public int getSizeY() {
return volume.sizeY();
return textureVolume.sizeY();
}
public int getSizeZ() {
return volume.sizeZ();
return textureVolume.sizeZ();
}
public void notifyLightUpdate(ILightReader world, LightType type, SectionPos location) {
GridAlignedBB changedVolume = GridAlignedBB.fromSection(location);
changedVolume.intersectAssign(volume); // compute the region contained by us that has dirty lighting data.
changedVolume.intersectAssign(sampleVolume); // compute the region contained by us that has dirty lighting data.
if (!changedVolume.empty()) {
if (type == LightType.BLOCK) copyBlock(world, changedVolume);
@ -88,11 +98,11 @@ public class LightVolume {
public void initialize(ILightReader world) {
BlockPos.Mutable pos = new BlockPos.Mutable();
int shiftX = volume.minX;
int shiftY = volume.minY;
int shiftZ = volume.minZ;
int shiftX = textureVolume.minX;
int shiftY = textureVolume.minY;
int shiftZ = textureVolume.minZ;
volume.forEachContained((x, y, z) -> {
textureVolume.forEachContained((x, y, z) -> {
pos.setPos(x, y, z);
int blockLight = world.getLightLevel(LightType.BLOCK, pos);
@ -111,9 +121,9 @@ public class LightVolume {
public void copyBlock(ILightReader world, GridAlignedBB worldVolume) {
BlockPos.Mutable pos = new BlockPos.Mutable();
int xShift = volume.minX;
int yShift = volume.minY;
int zShift = volume.minZ;
int xShift = textureVolume.minX;
int yShift = textureVolume.minY;
int zShift = textureVolume.minZ;
worldVolume.forEachContained((x, y, z) -> {
pos.setPos(x, y, z);
@ -133,9 +143,9 @@ public class LightVolume {
public void copySky(ILightReader world, GridAlignedBB worldVolume) {
BlockPos.Mutable pos = new BlockPos.Mutable();
int xShift = volume.minX;
int yShift = volume.minY;
int zShift = volume.minZ;
int xShift = textureVolume.minX;
int yShift = textureVolume.minY;
int zShift = textureVolume.minZ;
worldVolume.forEachContained((x, y, z) -> {
pos.setPos(x, y, z);
@ -159,7 +169,7 @@ public class LightVolume {
GL11.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_WRAP_R, GL20.GL_MIRRORED_REPEAT);
GL11.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_WRAP_T, GL20.GL_MIRRORED_REPEAT);
if (bufferDirty) {
GL12.glTexImage3D(GL12.GL_TEXTURE_3D, 0, GL40.GL_RG8, volume.sizeX(), volume.sizeY(), volume.sizeZ(), 0, GL40.GL_RG, GL40.GL_UNSIGNED_BYTE, lightData);
GL12.glTexImage3D(GL12.GL_TEXTURE_3D, 0, GL40.GL_RG8, textureVolume.sizeX(), textureVolume.sizeY(), textureVolume.sizeZ(), 0, GL40.GL_RG, GL40.GL_UNSIGNED_BYTE, lightData);
bufferDirty = false;
}
}
@ -199,6 +209,6 @@ public class LightVolume {
}
private int index(int x, int y, int z) {
return (x + volume.sizeX() * (y + z * volume.sizeY())) * 2;
return (x + textureVolume.sizeX() * (y + z * textureVolume.sizeY())) * 2;
}
}

View File

@ -2,17 +2,33 @@ package com.simibubi.create.foundation.render.light;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.render.ContraptionRenderDispatcher;
import com.simibubi.create.foundation.render.RenderedContraption;
import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer;
import com.simibubi.create.foundation.utility.Pair;
import com.simibubi.create.foundation.utility.outliner.AABBOutline;
import com.simibubi.create.foundation.utility.outliner.Outline;
import java.util.ArrayList;
public class LightVolumeDebugger {
public static void render(MatrixStack ms, SuperRenderTypeBuffer buffer) {
ContraptionRenderDispatcher.renderers.values()
.stream()
.map(r -> r.getLighter().lightVolume.getBox())
.map(volume -> new AABBOutline(GridAlignedBB.toAABB(volume)))
.flatMap(r -> {
GridAlignedBB texture = r.getLighter().lightVolume.getTextureVolume();
GridAlignedBB sample = r.getLighter().lightVolume.getSampleVolume();
ArrayList<Pair<GridAlignedBB, Integer>> pairs = new ArrayList<>(2);
pairs.add(Pair.of(texture, 0xFFFFFF));
pairs.add(Pair.of(sample, 0xFFFF00));
return pairs.stream();
})
.map(pair -> {
AABBOutline outline = new AABBOutline(GridAlignedBB.toAABB(pair.getFirst()));
outline.getParams().colored(pair.getSecond());
return outline;
})
.forEach(outline -> outline.render(ms, buffer));
}
}