mirror of
https://github.com/Creators-of-Create/Create.git
synced 2025-01-03 19:06:39 +01:00
smarter light volumes
start the process of creating sane gl abstractions stabilized contraption bounds now fit tightly with them fix global tile entity issues
This commit is contained in:
parent
7bac93a03c
commit
93353b61d6
25 changed files with 328 additions and 158 deletions
|
@ -39,6 +39,11 @@ public class DeployerRenderer extends SafeTileEntityRenderer<DeployerTileEntity>
|
||||||
super(dispatcher);
|
super(dispatcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isGlobalRenderer(DeployerTileEntity te) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void renderSafe(DeployerTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer,
|
protected void renderSafe(DeployerTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer,
|
||||||
int light, int overlay) {
|
int light, int overlay) {
|
||||||
|
|
|
@ -376,10 +376,4 @@ public class DeployerTileEntity extends KineticTileEntity {
|
||||||
TooltipHelper.addHint(tooltip, "hint.full_deployer");
|
TooltipHelper.addHint(tooltip, "hint.full_deployer");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean shouldRenderAsTE() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,11 @@ public class MechanicalMixerRenderer extends KineticTileEntityRenderer {
|
||||||
super(dispatcher);
|
super(dispatcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isGlobalRenderer(KineticTileEntity te) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void renderSafe(KineticTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer,
|
protected void renderSafe(KineticTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer,
|
||||||
int light, int overlay) {
|
int light, int overlay) {
|
||||||
|
|
|
@ -9,6 +9,16 @@ public class NonStationaryLighter<C extends Contraption> extends ContraptionLigh
|
||||||
super(contraption);
|
super(contraption);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected GridAlignedBB contraptionBoundsToVolume(GridAlignedBB bounds) {
|
||||||
|
bounds = bounds.copy();
|
||||||
|
bounds.grow(2); // so we have at least enough data on the edges to avoid artifacts and have smooth lighting
|
||||||
|
bounds.minY = Math.max(bounds.minY, 0);
|
||||||
|
bounds.maxY = Math.min(bounds.maxY, 255);
|
||||||
|
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick(RenderedContraption owner) {
|
public void tick(RenderedContraption owner) {
|
||||||
GridAlignedBB contraptionBounds = getContraptionBounds();
|
GridAlignedBB contraptionBounds = getContraptionBounds();
|
||||||
|
|
|
@ -2,6 +2,10 @@ package com.simibubi.create.content.contraptions.components.structureMovement.be
|
||||||
|
|
||||||
import com.simibubi.create.foundation.render.light.ContraptionLighter;
|
import com.simibubi.create.foundation.render.light.ContraptionLighter;
|
||||||
import com.simibubi.create.foundation.render.light.GridAlignedBB;
|
import com.simibubi.create.foundation.render.light.GridAlignedBB;
|
||||||
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public class BearingLighter extends ContraptionLighter<BearingContraption> {
|
public class BearingLighter extends ContraptionLighter<BearingContraption> {
|
||||||
|
|
||||||
|
@ -11,9 +15,40 @@ public class BearingLighter extends ContraptionLighter<BearingContraption> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public GridAlignedBB getContraptionBounds() {
|
public GridAlignedBB getContraptionBounds() {
|
||||||
GridAlignedBB localBounds = GridAlignedBB.fromAABB(contraption.bounds);
|
Set<BlockPos> blocks = contraption.getBlocks().keySet();
|
||||||
localBounds.rotate45(contraption.getFacing().getAxis());
|
|
||||||
localBounds.translate(contraption.anchor);
|
Direction orientation = contraption.facing;
|
||||||
return localBounds;
|
|
||||||
|
float maxDistanceSq = -1;
|
||||||
|
for (BlockPos pos : blocks) {
|
||||||
|
float x = pos.getX();
|
||||||
|
float y = pos.getY();
|
||||||
|
float z = pos.getZ();
|
||||||
|
|
||||||
|
float distSq = x * x + y * y + z * z;
|
||||||
|
|
||||||
|
if (distSq > maxDistanceSq) maxDistanceSq = distSq;
|
||||||
|
}
|
||||||
|
|
||||||
|
int radius = (int) (Math.ceil(Math.sqrt(maxDistanceSq)));
|
||||||
|
|
||||||
|
GridAlignedBB betterBounds = GridAlignedBB.ofRadius(radius);
|
||||||
|
GridAlignedBB contraptionBounds = GridAlignedBB.fromAABB(contraption.bounds);
|
||||||
|
|
||||||
|
Direction.Axis axis = orientation.getAxis();
|
||||||
|
|
||||||
|
if (axis == Direction.Axis.X) {
|
||||||
|
betterBounds.maxX = contraptionBounds.maxX;
|
||||||
|
betterBounds.minX = contraptionBounds.minX;
|
||||||
|
} else if (axis == Direction.Axis.Y) {
|
||||||
|
betterBounds.maxY = contraptionBounds.maxY;
|
||||||
|
betterBounds.minY = contraptionBounds.minY;
|
||||||
|
} else if (axis == Direction.Axis.Z) {
|
||||||
|
betterBounds.maxZ = contraptionBounds.maxZ;
|
||||||
|
betterBounds.minZ = contraptionBounds.minZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
betterBounds.translate(contraption.anchor);
|
||||||
|
return betterBounds;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -393,4 +393,8 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldRenderAsTE() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -282,4 +282,8 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldRenderAsTE() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,6 @@ public class StabilizedContraption extends Contraption {
|
||||||
if (!searchMovedStructure(world, offset, null))
|
if (!searchMovedStructure(world, offset, null))
|
||||||
return false;
|
return false;
|
||||||
startMoving(world);
|
startMoving(world);
|
||||||
expandBoundsAroundAxis(Axis.Y);
|
|
||||||
if (blocks.isEmpty())
|
if (blocks.isEmpty())
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -143,8 +143,4 @@ public abstract class BasinOperatingTileEntity extends KineticTileEntity {
|
||||||
|
|
||||||
protected abstract Object getRecipeCacheKey();
|
protected abstract Object getRecipeCacheKey();
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean shouldRenderAsTE() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,11 @@ public class BeltRenderer extends SafeTileEntityRenderer<BeltTileEntity> impleme
|
||||||
renderItems(te, partialTicks, ms, buffer, light, overlay);
|
renderItems(te, partialTicks, ms, buffer, light, overlay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isGlobalRenderer(BeltTileEntity te) {
|
||||||
|
return te.isController();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addInstanceData(InstanceContext<BeltTileEntity> ctx) {
|
public void addInstanceData(InstanceContext<BeltTileEntity> ctx) {
|
||||||
BeltTileEntity te = ctx.te;
|
BeltTileEntity te = ctx.te;
|
||||||
|
|
|
@ -465,11 +465,4 @@ public class BeltTileEntity extends KineticTileEntity {
|
||||||
return new ModelDataMap.Builder().withInitial(CASING_PROPERTY, casing)
|
return new ModelDataMap.Builder().withInitial(CASING_PROPERTY, casing)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean shouldRenderAsTE() {
|
|
||||||
// Since only the controller does the item rendering, we potentially
|
|
||||||
// save a *lot* of time by not processing the other belts.
|
|
||||||
return isController();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,11 @@ public class ArmRenderer extends KineticTileEntityRenderer {
|
||||||
super(dispatcher);
|
super(dispatcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isGlobalRenderer(KineticTileEntity te) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void renderSafe(KineticTileEntity te, float pt, MatrixStack ms, IRenderTypeBuffer buffer, int light,
|
protected void renderSafe(KineticTileEntity te, float pt, MatrixStack ms, IRenderTypeBuffer buffer, int light,
|
||||||
int overlay) {
|
int overlay) {
|
||||||
|
|
|
@ -513,8 +513,4 @@ public class ArmTileEntity extends KineticTileEntity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean shouldRenderAsTE() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ import com.simibubi.create.foundation.networking.LeftClickPacket;
|
||||||
import com.simibubi.create.foundation.render.FastRenderDispatcher;
|
import com.simibubi.create.foundation.render.FastRenderDispatcher;
|
||||||
import com.simibubi.create.foundation.render.RenderWork;
|
import com.simibubi.create.foundation.render.RenderWork;
|
||||||
import com.simibubi.create.foundation.render.contraption.ContraptionRenderDispatcher;
|
import com.simibubi.create.foundation.render.contraption.ContraptionRenderDispatcher;
|
||||||
|
import com.simibubi.create.foundation.render.light.LightVolumeDebugger;
|
||||||
import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer;
|
import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer;
|
||||||
import com.simibubi.create.foundation.tileEntity.behaviour.edgeInteraction.EdgeInteractionRenderer;
|
import com.simibubi.create.foundation.tileEntity.behaviour.edgeInteraction.EdgeInteractionRenderer;
|
||||||
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringRenderer;
|
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringRenderer;
|
||||||
|
|
|
@ -1,18 +1,20 @@
|
||||||
package com.simibubi.create.foundation.render;
|
package com.simibubi.create.foundation.render;
|
||||||
|
|
||||||
import com.mojang.blaze3d.platform.GlStateManager;
|
import com.simibubi.create.foundation.render.gl.GlBuffer;
|
||||||
|
import com.simibubi.create.foundation.render.gl.GlVertexArray;
|
||||||
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 org.lwjgl.opengl.GL11;
|
|
||||||
import org.lwjgl.opengl.GL15;
|
import org.lwjgl.opengl.GL15;
|
||||||
import org.lwjgl.opengl.GL30;
|
|
||||||
import org.lwjgl.opengl.GL40;
|
import org.lwjgl.opengl.GL40;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
public abstract class GPUBuffer extends TemplateBuffer {
|
public abstract class GPUBuffer extends TemplateBuffer {
|
||||||
|
|
||||||
protected int vao, ebo, invariantVBO;
|
protected GlVertexArray vao;
|
||||||
|
|
||||||
|
protected GlBuffer ebo;
|
||||||
|
protected GlBuffer invariantVBO;
|
||||||
protected boolean removed;
|
protected boolean removed;
|
||||||
|
|
||||||
public GPUBuffer(BufferBuilder buf) {
|
public GPUBuffer(BufferBuilder buf) {
|
||||||
|
@ -25,12 +27,18 @@ public abstract class GPUBuffer extends TemplateBuffer {
|
||||||
|
|
||||||
int invariantSize = vertexCount * stride;
|
int invariantSize = vertexCount * stride;
|
||||||
|
|
||||||
vao = GL30.glGenVertexArrays();
|
vao = new GlVertexArray();
|
||||||
ebo = GlStateManager.genBuffers();
|
invariantVBO = new GlBuffer();
|
||||||
invariantVBO = GlStateManager.genBuffers();
|
ebo = createEBO();
|
||||||
|
|
||||||
GL30.glBindVertexArray(vao);
|
vao.bind();
|
||||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, invariantVBO);
|
|
||||||
|
int numAttributes = getTotalShaderAttributeCount();
|
||||||
|
for (int i = 0; i <= numAttributes; i++) {
|
||||||
|
GL40.glEnableVertexAttribArray(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
invariantVBO.bind(GL15.GL_ARRAY_BUFFER);
|
||||||
|
|
||||||
// allocate the buffer on the gpu
|
// allocate the buffer on the gpu
|
||||||
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, invariantSize, GL15.GL_STATIC_DRAW);
|
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, invariantSize, GL15.GL_STATIC_DRAW);
|
||||||
|
@ -44,14 +52,11 @@ public abstract class GPUBuffer extends TemplateBuffer {
|
||||||
constant.rewind();
|
constant.rewind();
|
||||||
GL15.glUnmapBuffer(GL15.GL_ARRAY_BUFFER);
|
GL15.glUnmapBuffer(GL15.GL_ARRAY_BUFFER);
|
||||||
|
|
||||||
buildEBO(ebo);
|
|
||||||
|
|
||||||
getModelFormat().informAttributes(0);
|
getModelFormat().informAttributes(0);
|
||||||
|
|
||||||
GlStateManager.bindBuffers(GL15.GL_ARRAY_BUFFER, 0);
|
invariantVBO.unbind(GL15.GL_ARRAY_BUFFER);
|
||||||
GlStateManager.bindBuffers(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
|
|
||||||
// Deselect (bind to 0) the VAO
|
// Deselect (bind to 0) the VAO
|
||||||
GL30.glBindVertexArray(0);
|
vao.unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void copyVertex(ByteBuffer to, int index);
|
protected abstract void copyVertex(ByteBuffer to, int index);
|
||||||
|
@ -69,26 +74,17 @@ public abstract class GPUBuffer extends TemplateBuffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void render() {
|
public void render() {
|
||||||
if (vao == 0 || removed) return;
|
if (vertexCount == 0 || removed) return;
|
||||||
|
|
||||||
GL30.glBindVertexArray(vao);
|
vao.bind();
|
||||||
preDrawTask();
|
preDrawTask();
|
||||||
|
|
||||||
int numAttributes = getTotalShaderAttributeCount();
|
ebo.bind(GL15.GL_ELEMENT_ARRAY_BUFFER);
|
||||||
for (int i = 0; i <= numAttributes; i++) {
|
|
||||||
GL40.glEnableVertexAttribArray(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
GlStateManager.bindBuffers(GL15.GL_ELEMENT_ARRAY_BUFFER, ebo);
|
|
||||||
|
|
||||||
drawCall();
|
drawCall();
|
||||||
|
|
||||||
for (int i = 0; i <= numAttributes; i++) {
|
ebo.unbind(GL15.GL_ELEMENT_ARRAY_BUFFER);
|
||||||
GL40.glDisableVertexAttribArray(i);
|
vao.unbind();
|
||||||
}
|
|
||||||
|
|
||||||
GlStateManager.bindBuffers(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
|
|
||||||
GL30.glBindVertexArray(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void delete() {
|
public void delete() {
|
||||||
|
@ -99,11 +95,8 @@ public abstract class GPUBuffer extends TemplateBuffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void deleteInternal() {
|
protected void deleteInternal() {
|
||||||
GL15.glDeleteBuffers(invariantVBO);
|
invariantVBO.delete();
|
||||||
GL15.glDeleteBuffers(ebo);
|
ebo.delete();
|
||||||
GL30.glDeleteVertexArrays(vao);
|
vao.delete();
|
||||||
vao = 0;
|
|
||||||
ebo = 0;
|
|
||||||
invariantVBO = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,6 @@
|
||||||
package com.simibubi.create.foundation.render;
|
package com.simibubi.create.foundation.render;
|
||||||
|
|
||||||
public class RenderMath {
|
public class RenderMath {
|
||||||
public static final float SQRT2 = 1.41421356237f;
|
|
||||||
|
|
||||||
public static int rotateSideLength(int i) {
|
|
||||||
return (int) Math.floor((float) i * SQRT2 / 4f);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int nextPowerOf2(int a) {
|
public static int nextPowerOf2(int a) {
|
||||||
int h = Integer.highestOneBit(a);
|
int h = Integer.highestOneBit(a);
|
||||||
return (h == a) ? h : (h << 1);
|
return (h == a) ? h : (h << 1);
|
||||||
|
|
|
@ -2,6 +2,7 @@ package com.simibubi.create.foundation.render;
|
||||||
|
|
||||||
import com.mojang.blaze3d.platform.GlStateManager;
|
import com.mojang.blaze3d.platform.GlStateManager;
|
||||||
import com.mojang.datafixers.util.Pair;
|
import com.mojang.datafixers.util.Pair;
|
||||||
|
import com.simibubi.create.foundation.render.gl.GlBuffer;
|
||||||
import net.minecraft.client.renderer.BufferBuilder;
|
import net.minecraft.client.renderer.BufferBuilder;
|
||||||
import net.minecraft.client.renderer.vertex.VertexFormatElement;
|
import net.minecraft.client.renderer.vertex.VertexFormatElement;
|
||||||
import org.lwjgl.opengl.GL15;
|
import org.lwjgl.opengl.GL15;
|
||||||
|
@ -32,10 +33,13 @@ public class TemplateBuffer {
|
||||||
((Buffer)template).rewind();
|
((Buffer)template).rewind();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void buildEBO(int ebo){
|
protected final GlBuffer createEBO(){
|
||||||
|
GlBuffer ebo = new GlBuffer();
|
||||||
|
|
||||||
int indicesSize = vertexCount * VertexFormatElement.Type.USHORT.getSize();
|
int indicesSize = vertexCount * VertexFormatElement.Type.USHORT.getSize();
|
||||||
|
|
||||||
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, ebo);
|
ebo.bind(GL15.GL_ELEMENT_ARRAY_BUFFER);
|
||||||
|
|
||||||
GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, indicesSize, GL15.GL_STATIC_DRAW);
|
GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, indicesSize, GL15.GL_STATIC_DRAW);
|
||||||
|
|
||||||
ByteBuffer indices = GL15.glMapBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, GL15.GL_WRITE_ONLY);
|
ByteBuffer indices = GL15.glMapBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, GL15.GL_WRITE_ONLY);
|
||||||
|
@ -46,6 +50,10 @@ public class TemplateBuffer {
|
||||||
indices.rewind();
|
indices.rewind();
|
||||||
|
|
||||||
GL15.glUnmapBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER);
|
GL15.glUnmapBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER);
|
||||||
|
|
||||||
|
ebo.unbind(GL15.GL_ELEMENT_ARRAY_BUFFER);
|
||||||
|
|
||||||
|
return ebo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
package com.simibubi.create.foundation.render.gl;
|
||||||
|
|
||||||
|
import org.lwjgl.opengl.GL20;
|
||||||
|
|
||||||
|
public class GlBuffer extends GlObject {
|
||||||
|
public GlBuffer() {
|
||||||
|
setHandle(GL20.glGenBuffers());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void bind(int target) {
|
||||||
|
GL20.glBindBuffer(target, handle());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unbind(int target) {
|
||||||
|
GL20.glBindBuffer(target, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void deleteInternal(int handle) {
|
||||||
|
GL20.glDeleteBuffers(handle);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package com.simibubi.create.foundation.render.gl;
|
||||||
|
|
||||||
|
// Utility class for safely dealing with gl object handles.
|
||||||
|
public abstract class GlObject {
|
||||||
|
private static final int INVALID_HANDLE = Integer.MIN_VALUE;
|
||||||
|
|
||||||
|
private int handle = INVALID_HANDLE;
|
||||||
|
|
||||||
|
protected final void setHandle(int handle) {
|
||||||
|
this.handle = handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final int handle() {
|
||||||
|
this.checkHandle();
|
||||||
|
|
||||||
|
return this.handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final void checkHandle() {
|
||||||
|
if (!this.isHandleValid()) {
|
||||||
|
throw new IllegalStateException("Handle is not valid");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final boolean isHandleValid() {
|
||||||
|
return this.handle != INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final void invalidateHandle() {
|
||||||
|
this.handle = INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void delete() {
|
||||||
|
if (!isHandleValid()) {
|
||||||
|
throw new IllegalStateException("Handle already deleted.");
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteInternal(handle);
|
||||||
|
invalidateHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void deleteInternal(int handle);
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package com.simibubi.create.foundation.render.gl;
|
||||||
|
|
||||||
|
import org.lwjgl.opengl.GL20;
|
||||||
|
|
||||||
|
public class GlTexture extends GlObject {
|
||||||
|
private final int textureType;
|
||||||
|
|
||||||
|
public GlTexture(int textureType) {
|
||||||
|
this.textureType = textureType;
|
||||||
|
setHandle(GL20.glGenTextures());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void deleteInternal(int handle) {
|
||||||
|
GL20.glDeleteTextures(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void bind() {
|
||||||
|
GL20.glBindTexture(textureType, handle());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unbind() {
|
||||||
|
GL20.glBindTexture(textureType, 0);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package com.simibubi.create.foundation.render.gl;
|
||||||
|
|
||||||
|
import org.lwjgl.opengl.GL30;
|
||||||
|
|
||||||
|
public class GlVertexArray extends GlObject {
|
||||||
|
public GlVertexArray() {
|
||||||
|
setHandle(GL30.glGenVertexArrays());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void bind() {
|
||||||
|
GL30.glBindVertexArray(handle());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unbind() {
|
||||||
|
GL30.glBindVertexArray(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void deleteInternal(int handle) {
|
||||||
|
GL30.glDeleteVertexArrays(handle);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +1,12 @@
|
||||||
package com.simibubi.create.foundation.render.instancing;
|
package com.simibubi.create.foundation.render.instancing;
|
||||||
|
|
||||||
|
import com.simibubi.create.foundation.render.gl.GlBuffer;
|
||||||
import net.minecraft.client.renderer.BufferBuilder;
|
import net.minecraft.client.renderer.BufferBuilder;
|
||||||
import org.lwjgl.opengl.*;
|
import org.lwjgl.opengl.*;
|
||||||
|
|
||||||
public abstract class DynamicInstanceBuffer<S extends InstanceData, D extends InstanceData> extends InstanceBuffer<S> {
|
public abstract class DynamicInstanceBuffer<S extends InstanceData, D extends InstanceData> extends InstanceBuffer<S> {
|
||||||
|
|
||||||
protected int dynamicVBO;
|
protected GlBuffer dynamicVBO;
|
||||||
|
|
||||||
protected int dynamicBufferSize = -1;
|
protected int dynamicBufferSize = -1;
|
||||||
|
|
||||||
|
@ -16,7 +17,7 @@ public abstract class DynamicInstanceBuffer<S extends InstanceData, D extends In
|
||||||
@Override
|
@Override
|
||||||
protected void setup() {
|
protected void setup() {
|
||||||
super.setup();
|
super.setup();
|
||||||
dynamicVBO = GL20.glGenBuffers();
|
dynamicVBO = new GlBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract VertexFormat getDynamicFormat();
|
protected abstract VertexFormat getDynamicFormat();
|
||||||
|
@ -31,7 +32,11 @@ public abstract class DynamicInstanceBuffer<S extends InstanceData, D extends In
|
||||||
@Override
|
@Override
|
||||||
protected void preDrawTask() {
|
protected void preDrawTask() {
|
||||||
super.preDrawTask();
|
super.preDrawTask();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void deleteInternal() {
|
||||||
|
super.deleteInternal();
|
||||||
|
dynamicVBO.delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import com.simibubi.create.foundation.render.GPUBuffer;
|
||||||
import com.simibubi.create.foundation.render.RenderMath;
|
import com.simibubi.create.foundation.render.RenderMath;
|
||||||
import com.simibubi.create.foundation.render.RenderWork;
|
import com.simibubi.create.foundation.render.RenderWork;
|
||||||
import com.simibubi.create.foundation.render.TemplateBuffer;
|
import com.simibubi.create.foundation.render.TemplateBuffer;
|
||||||
|
import com.simibubi.create.foundation.render.gl.GlBuffer;
|
||||||
import net.minecraft.client.renderer.BufferBuilder;
|
import net.minecraft.client.renderer.BufferBuilder;
|
||||||
import org.lwjgl.opengl.*;
|
import org.lwjgl.opengl.*;
|
||||||
|
|
||||||
|
@ -18,7 +19,7 @@ import static com.simibubi.create.foundation.render.instancing.VertexAttribute.*
|
||||||
public abstract class InstanceBuffer<D extends InstanceData> extends GPUBuffer {
|
public abstract class InstanceBuffer<D extends InstanceData> extends GPUBuffer {
|
||||||
public static final VertexFormat FORMAT = new VertexFormat(POSITION, NORMAL, UV);
|
public static final VertexFormat FORMAT = new VertexFormat(POSITION, NORMAL, UV);
|
||||||
|
|
||||||
protected int instanceVBO;
|
protected GlBuffer instanceVBO;
|
||||||
protected int instanceCount;
|
protected int instanceCount;
|
||||||
|
|
||||||
protected int instanceBufferSize = -1;
|
protected int instanceBufferSize = -1;
|
||||||
|
@ -34,7 +35,7 @@ public abstract class InstanceBuffer<D extends InstanceData> extends GPUBuffer {
|
||||||
@Override
|
@Override
|
||||||
protected void setup() {
|
protected void setup() {
|
||||||
super.setup();
|
super.setup();
|
||||||
instanceVBO = GlStateManager.genBuffers();
|
instanceVBO = new GlBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -76,15 +77,8 @@ public abstract class InstanceBuffer<D extends InstanceData> extends GPUBuffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void deleteInternal() {
|
protected void deleteInternal() {
|
||||||
GL15.glDeleteBuffers(invariantVBO);
|
super.deleteInternal();
|
||||||
GL15.glDeleteBuffers(instanceVBO);
|
instanceVBO.delete();
|
||||||
GL15.glDeleteBuffers(ebo);
|
|
||||||
GL30.glDeleteVertexArrays(vao);
|
|
||||||
vao = 0;
|
|
||||||
ebo = 0;
|
|
||||||
invariantVBO = 0;
|
|
||||||
instanceVBO = 0;
|
|
||||||
instanceBufferSize = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract D newInstance();
|
protected abstract D newInstance();
|
||||||
|
@ -116,7 +110,7 @@ public abstract class InstanceBuffer<D extends InstanceData> extends GPUBuffer {
|
||||||
|
|
||||||
int instanceSize = RenderMath.nextPowerOf2(instanceCount * instanceFormat.getStride());
|
int instanceSize = RenderMath.nextPowerOf2(instanceCount * instanceFormat.getStride());
|
||||||
|
|
||||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, instanceVBO);
|
instanceVBO.bind(GL15.GL_ARRAY_BUFFER);
|
||||||
|
|
||||||
// this changes enough that it's not worth reallocating the entire buffer every time.
|
// this changes enough that it's not worth reallocating the entire buffer every time.
|
||||||
if (instanceSize > instanceBufferSize) {
|
if (instanceSize > instanceBufferSize) {
|
||||||
|
@ -137,8 +131,7 @@ public abstract class InstanceBuffer<D extends InstanceData> extends GPUBuffer {
|
||||||
GL33.glVertexAttribDivisor(i + staticAttributes, 1);
|
GL33.glVertexAttribDivisor(i + staticAttributes, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deselect (bind to 0) the VBO
|
instanceVBO.unbind(GL15.GL_ARRAY_BUFFER);
|
||||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
|
||||||
|
|
||||||
shouldBuild = false;
|
shouldBuild = false;
|
||||||
rebuffer = false;
|
rebuffer = false;
|
||||||
|
|
|
@ -9,7 +9,6 @@ import net.minecraft.util.math.Vec3d;
|
||||||
import net.minecraft.util.math.Vec3i;
|
import net.minecraft.util.math.Vec3i;
|
||||||
|
|
||||||
import static com.simibubi.create.foundation.render.RenderMath.isPowerOf2;
|
import static com.simibubi.create.foundation.render.RenderMath.isPowerOf2;
|
||||||
import static com.simibubi.create.foundation.render.RenderMath.rotateSideLength;
|
|
||||||
|
|
||||||
public class GridAlignedBB {
|
public class GridAlignedBB {
|
||||||
public int minX;
|
public int minX;
|
||||||
|
@ -28,6 +27,10 @@ public class GridAlignedBB {
|
||||||
this.maxZ = maxZ;
|
this.maxZ = maxZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static GridAlignedBB ofRadius(int radius) {
|
||||||
|
return new GridAlignedBB(-radius, -radius, -radius, radius + 1, radius + 1, radius + 1);
|
||||||
|
}
|
||||||
|
|
||||||
public static GridAlignedBB copy(GridAlignedBB bb) {
|
public static GridAlignedBB copy(GridAlignedBB bb) {
|
||||||
return new GridAlignedBB(bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ);
|
return new GridAlignedBB(bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ);
|
||||||
}
|
}
|
||||||
|
@ -104,16 +107,6 @@ public class GridAlignedBB {
|
||||||
maxZ += z;
|
maxZ += z;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void rotate45(Direction.Axis axis) {
|
|
||||||
if (axis == Direction.Axis.X) {
|
|
||||||
this.grow(0, rotateSideLength(sizeY()), rotateSideLength(sizeZ()));
|
|
||||||
} else if (axis == Direction.Axis.Y) {
|
|
||||||
this.grow(rotateSideLength(sizeX()), 0, rotateSideLength(sizeZ()));
|
|
||||||
} else if (axis == Direction.Axis.Z) {
|
|
||||||
this.grow(rotateSideLength(sizeX()), rotateSideLength(sizeY()), 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void mirrorAbout(Direction.Axis axis) {
|
public void mirrorAbout(Direction.Axis axis) {
|
||||||
Vec3i axisVec = Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, axis).getDirectionVec();
|
Vec3i axisVec = Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, axis).getDirectionVec();
|
||||||
int flipX = axisVec.getX() - 1;
|
int flipX = axisVec.getX() - 1;
|
||||||
|
@ -131,38 +124,6 @@ public class GridAlignedBB {
|
||||||
this.minZ = maxZ;
|
this.minZ = maxZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void expandAroundAxis(Direction.Axis axis) {
|
|
||||||
int maxXDiff = Math.max(this.maxX - 1, -this.minX);
|
|
||||||
int maxYDiff = Math.max(this.maxY - 1, -this.minY);
|
|
||||||
int maxZDiff = Math.max(this.maxZ - 1, -this.minZ);
|
|
||||||
|
|
||||||
int maxDiff;
|
|
||||||
if (axis == Direction.Axis.X)
|
|
||||||
maxDiff = Math.max(maxZDiff, maxYDiff);
|
|
||||||
else if (axis == Direction.Axis.Y)
|
|
||||||
maxDiff = Math.max(maxZDiff, maxXDiff);
|
|
||||||
else if (axis == Direction.Axis.Z)
|
|
||||||
maxDiff = Math.max(maxXDiff, maxYDiff);
|
|
||||||
else
|
|
||||||
maxDiff = 0;
|
|
||||||
|
|
||||||
Vec3i axisVec = Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, axis).getDirectionVec();
|
|
||||||
int axisX = axisVec.getX();
|
|
||||||
int axisY = axisVec.getY();
|
|
||||||
int axisZ = axisVec.getZ();
|
|
||||||
|
|
||||||
int planeX = 1 - axisX;
|
|
||||||
int planeY = 1 - axisY;
|
|
||||||
int planeZ = 1 - axisZ;
|
|
||||||
|
|
||||||
minX = axisX * minX - maxDiff * planeX;
|
|
||||||
minY = axisY * minY - maxDiff * planeY;
|
|
||||||
minZ = axisZ * minZ - maxDiff * planeZ;
|
|
||||||
maxX = axisX * maxX + (maxDiff + 1) * planeX;
|
|
||||||
maxY = axisY * maxY + (maxDiff + 1) * planeY;
|
|
||||||
maxZ = axisZ * maxZ + (maxDiff + 1) * planeZ;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Grow this bounding box to have power of 2 side length, scaling from the center.
|
* Grow this bounding box to have power of 2 side length, scaling from the center.
|
||||||
*/
|
*/
|
||||||
|
@ -269,6 +230,19 @@ public class GridAlignedBB {
|
||||||
return this.intersects(other.minX, other.minY, other.minZ, other.maxX, other.maxY, other.maxZ);
|
return this.intersects(other.minX, other.minY, other.minZ, other.maxX, other.maxY, other.maxZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean contains(GridAlignedBB other) {
|
||||||
|
return other.minX >= this.minX &&
|
||||||
|
other.maxX <= this.maxX &&
|
||||||
|
other.minY >= this.minY &&
|
||||||
|
other.maxY <= this.maxY &&
|
||||||
|
other.minZ >= this.minZ &&
|
||||||
|
other.maxZ <= this.maxZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isContainedBy(GridAlignedBB other) {
|
||||||
|
return other.contains(this);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean intersects(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) {
|
public boolean intersects(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) {
|
||||||
return this.minX < maxX && this.maxX > minX && this.minY < maxY && this.maxY > minY && this.minZ < maxZ && this.maxZ > minZ;
|
return this.minX < maxX && this.maxX > minX && this.minY < maxY && this.maxY > minY && this.minZ < maxZ && this.maxZ > minZ;
|
||||||
}
|
}
|
||||||
|
@ -292,12 +266,7 @@ public class GridAlignedBB {
|
||||||
|
|
||||||
GridAlignedBB that = (GridAlignedBB) o;
|
GridAlignedBB that = (GridAlignedBB) o;
|
||||||
|
|
||||||
if (minX != that.minX) return false;
|
return this.sameAs(that);
|
||||||
if (minY != that.minY) return false;
|
|
||||||
if (minZ != that.minZ) return false;
|
|
||||||
if (maxX != that.maxX) return false;
|
|
||||||
if (maxY != that.maxY) return false;
|
|
||||||
return maxZ == that.maxZ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.simibubi.create.foundation.render.light;
|
package com.simibubi.create.foundation.render.light;
|
||||||
|
|
||||||
import com.simibubi.create.foundation.render.RenderWork;
|
import com.simibubi.create.foundation.render.RenderWork;
|
||||||
|
import com.simibubi.create.foundation.render.gl.GlTexture;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.SectionPos;
|
import net.minecraft.util.math.SectionPos;
|
||||||
import net.minecraft.world.ILightReader;
|
import net.minecraft.world.ILightReader;
|
||||||
|
@ -24,12 +25,12 @@ public class LightVolume {
|
||||||
private boolean bufferDirty;
|
private boolean bufferDirty;
|
||||||
private boolean removed;
|
private boolean removed;
|
||||||
|
|
||||||
private int glTexture;
|
private final GlTexture glTexture;
|
||||||
|
|
||||||
public LightVolume(GridAlignedBB sampleVolume) {
|
public LightVolume(GridAlignedBB sampleVolume) {
|
||||||
setSampleVolume(sampleVolume);
|
setSampleVolume(sampleVolume);
|
||||||
|
|
||||||
this.glTexture = GL11.glGenTextures();
|
this.glTexture = new GlTexture(GL20.GL_TEXTURE_3D);
|
||||||
this.lightData = MemoryUtil.memAlloc(this.textureVolume.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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,32 +85,48 @@ public class LightVolume {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void move(ILightReader world, GridAlignedBB newSampleVolume) {
|
public void move(ILightReader world, GridAlignedBB newSampleVolume) {
|
||||||
setSampleVolume(newSampleVolume);
|
if (textureVolume.contains(newSampleVolume)) {
|
||||||
initialize(world);
|
if (newSampleVolume.intersects(sampleVolume)) {
|
||||||
|
GridAlignedBB newArea = newSampleVolume.intersect(sampleVolume);
|
||||||
|
sampleVolume = newSampleVolume;
|
||||||
|
|
||||||
|
copyLight(world, newArea);
|
||||||
|
} else {
|
||||||
|
sampleVolume = newSampleVolume;
|
||||||
|
initialize(world);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setSampleVolume(newSampleVolume);
|
||||||
|
int volume = textureVolume.volume();
|
||||||
|
if (volume * 2 > lightData.capacity()) {
|
||||||
|
lightData = MemoryUtil.memRealloc(lightData, volume * 2);
|
||||||
|
}
|
||||||
|
initialize(world);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void notifyLightUpdate(ILightReader world, LightType type, SectionPos location) {
|
public void notifyLightUpdate(ILightReader world, LightType type, SectionPos location) {
|
||||||
GridAlignedBB changedVolume = GridAlignedBB.fromSection(location);
|
GridAlignedBB changedVolume = GridAlignedBB.fromSection(location);
|
||||||
|
if (!changedVolume.intersects(sampleVolume))
|
||||||
|
return;
|
||||||
changedVolume.intersectAssign(sampleVolume); // 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);
|
||||||
if (type == LightType.BLOCK) copyBlock(world, changedVolume);
|
else if (type == LightType.SKY) copySky(world, changedVolume);
|
||||||
else if (type == LightType.SKY) copySky(world, changedVolume);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Completely (re)populate this volume with block and sky lighting data.
|
* Completely (re)populate this volume with block and sky lighting data.
|
||||||
* This is expensive and should be avoided.
|
* This is expensive and should be avoided.
|
||||||
*/
|
*/
|
||||||
public synchronized void initialize(ILightReader world) {
|
public void initialize(ILightReader world) {
|
||||||
BlockPos.Mutable pos = new BlockPos.Mutable();
|
BlockPos.Mutable pos = new BlockPos.Mutable();
|
||||||
|
|
||||||
int shiftX = textureVolume.minX;
|
int shiftX = textureVolume.minX;
|
||||||
int shiftY = textureVolume.minY;
|
int shiftY = textureVolume.minY;
|
||||||
int shiftZ = textureVolume.minZ;
|
int shiftZ = textureVolume.minZ;
|
||||||
|
|
||||||
textureVolume.forEachContained((x, y, z) -> {
|
sampleVolume.forEachContained((x, y, z) -> {
|
||||||
pos.setPos(x, y, z);
|
pos.setPos(x, y, z);
|
||||||
|
|
||||||
int blockLight = world.getLightLevel(LightType.BLOCK, pos);
|
int blockLight = world.getLightLevel(LightType.BLOCK, pos);
|
||||||
|
@ -125,7 +142,7 @@ public class LightVolume {
|
||||||
* Copy block light from the world into this volume.
|
* Copy block light from the world into this volume.
|
||||||
* @param worldVolume the region in the world to copy data from.
|
* @param worldVolume the region in the world to copy data from.
|
||||||
*/
|
*/
|
||||||
public synchronized void copyBlock(ILightReader world, GridAlignedBB worldVolume) {
|
public void copyBlock(ILightReader world, GridAlignedBB worldVolume) {
|
||||||
BlockPos.Mutable pos = new BlockPos.Mutable();
|
BlockPos.Mutable pos = new BlockPos.Mutable();
|
||||||
|
|
||||||
int xShift = textureVolume.minX;
|
int xShift = textureVolume.minX;
|
||||||
|
@ -147,7 +164,7 @@ public class LightVolume {
|
||||||
* Copy sky light from the world into this volume.
|
* Copy sky light from the world into this volume.
|
||||||
* @param worldVolume the region in the world to copy data from.
|
* @param worldVolume the region in the world to copy data from.
|
||||||
*/
|
*/
|
||||||
public synchronized void copySky(ILightReader world, GridAlignedBB worldVolume) {
|
public void copySky(ILightReader world, GridAlignedBB worldVolume) {
|
||||||
BlockPos.Mutable pos = new BlockPos.Mutable();
|
BlockPos.Mutable pos = new BlockPos.Mutable();
|
||||||
|
|
||||||
int xShift = textureVolume.minX;
|
int xShift = textureVolume.minX;
|
||||||
|
@ -165,37 +182,66 @@ public class LightVolume {
|
||||||
bufferDirty = true;
|
bufferDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy all light from the world into this volume.
|
||||||
|
* @param worldVolume the region in the world to copy data from.
|
||||||
|
*/
|
||||||
|
public void copyLight(ILightReader world, GridAlignedBB worldVolume) {
|
||||||
|
BlockPos.Mutable pos = new BlockPos.Mutable();
|
||||||
|
|
||||||
|
int xShift = textureVolume.minX;
|
||||||
|
int yShift = textureVolume.minY;
|
||||||
|
int zShift = textureVolume.minZ;
|
||||||
|
|
||||||
|
worldVolume.forEachContained((x, y, z) -> {
|
||||||
|
pos.setPos(x, y, z);
|
||||||
|
|
||||||
|
int block = world.getLightLevel(LightType.BLOCK, pos);
|
||||||
|
int sky = world.getLightLevel(LightType.SKY, pos);
|
||||||
|
|
||||||
|
writeLight(x - xShift, y - yShift, z - zShift, block, sky);
|
||||||
|
});
|
||||||
|
|
||||||
|
bufferDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
public void use() {
|
public void use() {
|
||||||
// just in case something goes wrong or we accidentally call this before this volume is properly disposed of.
|
// just in case something goes wrong or we accidentally call this before this volume is properly disposed of.
|
||||||
if (glTexture == 0 || lightData == null || removed) return;
|
if (lightData == null || removed) return;
|
||||||
|
|
||||||
GL13.glActiveTexture(GL40.GL_TEXTURE4);
|
GL13.glActiveTexture(GL40.GL_TEXTURE4);
|
||||||
GL12.glBindTexture(GL12.GL_TEXTURE_3D, glTexture);
|
glTexture.bind();
|
||||||
GL11.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_MIN_FILTER, GL13.GL_LINEAR);
|
GL11.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_MIN_FILTER, GL13.GL_LINEAR);
|
||||||
GL11.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_MAG_FILTER, GL13.GL_LINEAR);
|
GL11.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_MAG_FILTER, GL13.GL_LINEAR);
|
||||||
GL11.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_WRAP_S, GL20.GL_MIRRORED_REPEAT);
|
GL11.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_WRAP_S, GL20.GL_MIRRORED_REPEAT);
|
||||||
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_R, GL20.GL_MIRRORED_REPEAT);
|
||||||
GL11.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_WRAP_T, GL20.GL_MIRRORED_REPEAT);
|
GL11.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_WRAP_T, GL20.GL_MIRRORED_REPEAT);
|
||||||
|
|
||||||
|
uploadTexture();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void uploadTexture() {
|
||||||
if (bufferDirty) {
|
if (bufferDirty) {
|
||||||
uploadTexture();
|
int sizeX = textureVolume.sizeX();
|
||||||
|
int sizeY = textureVolume.sizeY();
|
||||||
|
int sizeZ = textureVolume.sizeZ();
|
||||||
|
if (sizeX * sizeY * sizeZ * 2 > lightData.capacity())
|
||||||
|
throw new IllegalStateException("Volume too big for buffer");
|
||||||
|
|
||||||
|
lightData.rewind();
|
||||||
|
GL12.glTexImage3D(GL12.GL_TEXTURE_3D, 0, GL40.GL_RG8, sizeX, sizeY, sizeZ, 0, GL40.GL_RG, GL40.GL_UNSIGNED_BYTE, lightData);
|
||||||
|
bufferDirty = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void uploadTexture() {
|
|
||||||
lightData.rewind();
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void release() {
|
public void release() {
|
||||||
GL12.glBindTexture(GL12.GL_TEXTURE_3D, 0);
|
glTexture.unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void delete() {
|
public void delete() {
|
||||||
removed = true;
|
removed = true;
|
||||||
RenderWork.enqueue(() -> {
|
RenderWork.enqueue(() -> {
|
||||||
GL15.glDeleteTextures(glTexture);
|
glTexture.delete();
|
||||||
glTexture = 0;
|
|
||||||
MemoryUtil.memFree(lightData);
|
MemoryUtil.memFree(lightData);
|
||||||
lightData = null;
|
lightData = null;
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue