mirror of
https://github.com/Creators-of-Create/Create.git
synced 2025-01-03 19:06:39 +01:00
Merge remote-tracking branch 'upstream/chromatic-projector' into
contraption-lighting # Conflicts: # src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/RenderedContraption.java # src/main/java/com/simibubi/create/foundation/render/SuperByteBuffer.java
This commit is contained in:
commit
fd6c930a65
58 changed files with 763 additions and 870 deletions
|
@ -26,10 +26,9 @@ import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
|
||||||
import com.jozufozu.flywheel.backend.gl.shader.ProgramSpec;
|
import com.jozufozu.flywheel.backend.gl.shader.ProgramSpec;
|
||||||
import com.jozufozu.flywheel.backend.gl.versioned.GlCompat;
|
import com.jozufozu.flywheel.backend.gl.versioned.GlCompat;
|
||||||
import com.jozufozu.flywheel.backend.instancing.IFlywheelWorld;
|
import com.jozufozu.flywheel.backend.instancing.IFlywheelWorld;
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedModel;
|
import com.jozufozu.flywheel.backend.instancing.InstanceData;
|
||||||
import com.jozufozu.flywheel.backend.instancing.MaterialSpec;
|
import com.jozufozu.flywheel.backend.instancing.MaterialSpec;
|
||||||
import com.jozufozu.flywheel.util.WorldAttached;
|
import com.jozufozu.flywheel.util.WorldAttached;
|
||||||
import com.simibubi.create.content.contraptions.KineticDebugger;
|
|
||||||
import com.simibubi.create.foundation.config.AllConfigs;
|
import com.simibubi.create.foundation.config.AllConfigs;
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
||||||
|
@ -131,7 +130,7 @@ public class Backend {
|
||||||
/**
|
/**
|
||||||
* Register an instancing material.
|
* Register an instancing material.
|
||||||
*/
|
*/
|
||||||
public static <M extends InstancedModel<?>> MaterialSpec<M> register(MaterialSpec<M> spec) {
|
public static <D extends InstanceData> MaterialSpec<D> register(MaterialSpec<D> spec) {
|
||||||
ResourceLocation name = spec.name;
|
ResourceLocation name = spec.name;
|
||||||
if (materialRegistry.containsKey(name)) {
|
if (materialRegistry.containsKey(name)) {
|
||||||
throw new IllegalStateException("Material spec '" + name + "' already registered.");
|
throw new IllegalStateException("Material spec '" + name + "' already registered.");
|
||||||
|
@ -275,14 +274,6 @@ public class Backend {
|
||||||
return canUseInstancing() && isFlywheelWorld(world);
|
return canUseInstancing() && isFlywheelWorld(world);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO: Remove in favor of separate debug programs specified by the SpecLoader/IMultiProgram
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public static int getDebugMode() {
|
|
||||||
return KineticDebugger.isActive() ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Collection<MaterialSpec<?>> allMaterials() {
|
public static Collection<MaterialSpec<?>> allMaterials() {
|
||||||
return materialRegistry.values();
|
return materialRegistry.values();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,89 +0,0 @@
|
||||||
package com.jozufozu.flywheel.backend;
|
|
||||||
|
|
||||||
import org.lwjgl.opengl.GL15;
|
|
||||||
import org.lwjgl.opengl.GL20;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.gl.GlBuffer;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.GlBufferType;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.MappedBufferRange;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
|
||||||
import com.simibubi.create.foundation.render.TemplateBuffer;
|
|
||||||
|
|
||||||
import net.minecraft.client.renderer.BufferBuilder;
|
|
||||||
|
|
||||||
public abstract class BufferedModel extends TemplateBuffer {
|
|
||||||
|
|
||||||
protected GlBuffer modelVBO;
|
|
||||||
protected boolean removed;
|
|
||||||
|
|
||||||
protected BufferedModel(BufferBuilder buf) {
|
|
||||||
super(buf);
|
|
||||||
if (vertexCount > 0) init();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void init() {
|
|
||||||
|
|
||||||
modelVBO = new GlBuffer(GlBufferType.ARRAY_BUFFER);
|
|
||||||
|
|
||||||
modelVBO.bind();
|
|
||||||
initModel();
|
|
||||||
modelVBO.unbind();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void initModel() {
|
|
||||||
int stride = getModelFormat().getStride();
|
|
||||||
int invariantSize = vertexCount * stride;
|
|
||||||
|
|
||||||
// allocate the buffer on the gpu
|
|
||||||
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, invariantSize, GL15.GL_STATIC_DRAW);
|
|
||||||
|
|
||||||
// mirror it in system memory so we can write to it
|
|
||||||
MappedBufferRange buffer = modelVBO.getBuffer(0, invariantSize);
|
|
||||||
for (int i = 0; i < vertexCount; i++) {
|
|
||||||
copyVertex(buffer, i);
|
|
||||||
}
|
|
||||||
buffer.unmap();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract void copyVertex(MappedBufferRange to, int index);
|
|
||||||
|
|
||||||
protected abstract VertexFormat getModelFormat();
|
|
||||||
|
|
||||||
protected int getTotalShaderAttributeCount() {
|
|
||||||
return getModelFormat().getShaderAttributeCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders this model, checking first if there is anything to render.
|
|
||||||
*/
|
|
||||||
public final void render() {
|
|
||||||
if (vertexCount == 0 || removed) return;
|
|
||||||
|
|
||||||
doRender();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set up any state and make the draw calls.
|
|
||||||
*/
|
|
||||||
protected abstract void doRender();
|
|
||||||
|
|
||||||
protected void setupAttributes() {
|
|
||||||
int numAttributes = getTotalShaderAttributeCount();
|
|
||||||
for (int i = 0; i <= numAttributes; i++) {
|
|
||||||
GL20.glEnableVertexAttribArray(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
getModelFormat().vertexAttribPointers(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void delete() {
|
|
||||||
removed = true;
|
|
||||||
if (vertexCount > 0) {
|
|
||||||
RenderWork.enqueue(this::deleteInternal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void deleteInternal() {
|
|
||||||
modelVBO.delete();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
package com.jozufozu.flywheel.backend.core;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.lwjgl.opengl.GL20;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.backend.RenderWork;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
||||||
|
|
||||||
|
public abstract class BufferedModel {
|
||||||
|
|
||||||
|
protected final ByteBuffer data;
|
||||||
|
protected final VertexFormat modelFormat;
|
||||||
|
protected final int vertexCount;
|
||||||
|
protected GlBuffer modelVBO;
|
||||||
|
private boolean initialized; // lazy init
|
||||||
|
private boolean removed;
|
||||||
|
|
||||||
|
protected BufferedModel(VertexFormat modelFormat, ByteBuffer data, int vertices) {
|
||||||
|
this.data = data;
|
||||||
|
this.modelFormat = modelFormat;
|
||||||
|
this.vertexCount = vertices;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders this model, checking first if there is anything to render.
|
||||||
|
*/
|
||||||
|
public final void render() {
|
||||||
|
if (vertexCount <= 0 || removed) return;
|
||||||
|
|
||||||
|
if (!initialized) {
|
||||||
|
// Lazily acquire resources in order to get around initialization order, as #getTotalShaderAttributeCount
|
||||||
|
// might depend on fields in subclasses.
|
||||||
|
init();
|
||||||
|
initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
doRender();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set up any state and make the draw calls.
|
||||||
|
*/
|
||||||
|
protected abstract void doRender();
|
||||||
|
|
||||||
|
public final void delete() {
|
||||||
|
removed = true;
|
||||||
|
if (initialized) {
|
||||||
|
RenderWork.enqueue(this::deleteInternal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void init() {
|
||||||
|
modelVBO = new GlBuffer(GlBufferType.ARRAY_BUFFER);
|
||||||
|
|
||||||
|
modelVBO.bind();
|
||||||
|
initModel();
|
||||||
|
modelVBO.unbind();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void initModel() {
|
||||||
|
// allocate the buffer on the gpu
|
||||||
|
modelVBO.alloc(data.capacity());
|
||||||
|
|
||||||
|
// mirror it in system memory so we can write to it
|
||||||
|
MappedBuffer buffer = modelVBO.getBuffer(0, data.capacity());
|
||||||
|
buffer.put(data);
|
||||||
|
buffer.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int getTotalShaderAttributeCount() {
|
||||||
|
return modelFormat.getShaderAttributeCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setupAttributes() {
|
||||||
|
int numAttributes = getTotalShaderAttributeCount();
|
||||||
|
for (int i = 0; i <= numAttributes; i++) {
|
||||||
|
GL20.glEnableVertexAttribArray(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
modelFormat.vertexAttribPointers(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void deleteInternal() {
|
||||||
|
modelVBO.delete();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
package com.jozufozu.flywheel.backend.core;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.lwjgl.opengl.GL20;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.backend.gl.GlPrimitiveType;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
||||||
|
|
||||||
|
public class IndexedModel extends BufferedModel {
|
||||||
|
|
||||||
|
protected GlPrimitiveType eboIndexType;
|
||||||
|
protected GlBuffer ebo;
|
||||||
|
|
||||||
|
public IndexedModel(VertexFormat modelFormat, ByteBuffer buf, int vertices) {
|
||||||
|
super(modelFormat, buf, vertices);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void init() {
|
||||||
|
super.init();
|
||||||
|
|
||||||
|
createEBO();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doRender() {
|
||||||
|
modelVBO.bind();
|
||||||
|
ebo.bind();
|
||||||
|
|
||||||
|
setupAttributes();
|
||||||
|
GL20.glDrawElements(GL20.GL_QUADS, vertexCount, eboIndexType.getGlConstant(), 0);
|
||||||
|
|
||||||
|
int numAttributes = getTotalShaderAttributeCount();
|
||||||
|
for (int i = 0; i <= numAttributes; i++) {
|
||||||
|
GL20.glDisableVertexAttribArray(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
ebo.unbind();
|
||||||
|
modelVBO.unbind();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final void createEBO() {
|
||||||
|
ebo = new GlBuffer(GlBufferType.ELEMENT_ARRAY_BUFFER);
|
||||||
|
eboIndexType = GlPrimitiveType.UINT; // TODO: choose this based on the number of vertices
|
||||||
|
|
||||||
|
int indicesSize = vertexCount * eboIndexType.getSize();
|
||||||
|
|
||||||
|
ebo.bind();
|
||||||
|
|
||||||
|
ebo.alloc(indicesSize);
|
||||||
|
MappedBuffer indices = ebo.getBuffer(0, indicesSize);
|
||||||
|
for (int i = 0; i < vertexCount; i++) {
|
||||||
|
indices.putInt(i);
|
||||||
|
}
|
||||||
|
indices.flush();
|
||||||
|
|
||||||
|
ebo.unbind();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void deleteInternal() {
|
||||||
|
super.deleteInternal();
|
||||||
|
ebo.delete();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
package com.jozufozu.flywheel.backend.core.materials;
|
package com.jozufozu.flywheel.backend.core.materials;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.gl.MappedBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstanceData;
|
import com.jozufozu.flywheel.backend.instancing.InstanceData;
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedModel;
|
import com.jozufozu.flywheel.backend.instancing.InstancedModel;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package com.jozufozu.flywheel.backend.core.materials;
|
package com.jozufozu.flywheel.backend.core.materials;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.gl.MappedBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedModel;
|
import com.jozufozu.flywheel.backend.instancing.InstancedModel;
|
||||||
import com.jozufozu.flywheel.util.RenderUtil;
|
import com.jozufozu.flywheel.util.RenderUtil;
|
||||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package com.jozufozu.flywheel.backend.core.materials;
|
package com.jozufozu.flywheel.backend.core.materials;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.gl.MappedBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedModel;
|
import com.jozufozu.flywheel.backend.instancing.InstancedModel;
|
||||||
|
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
package com.jozufozu.flywheel.backend.core.materials;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedModel;
|
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedTileRenderer;
|
|
||||||
|
|
||||||
import net.minecraft.client.renderer.BufferBuilder;
|
|
||||||
|
|
||||||
public class OrientedModel extends InstancedModel<OrientedData> {
|
|
||||||
public static final VertexFormat INSTANCE_FORMAT = VertexFormat.builder()
|
|
||||||
.addAttributes(BasicAttributes.class)
|
|
||||||
.addAttributes(OrientedAttributes.class)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
public OrientedModel(InstancedTileRenderer<?> renderer, BufferBuilder buf) {
|
|
||||||
super(renderer, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected OrientedData newInstance() {
|
|
||||||
return new OrientedData(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected VertexFormat getInstanceFormat() {
|
|
||||||
return INSTANCE_FORMAT;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
package com.jozufozu.flywheel.backend.core.materials;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedModel;
|
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedTileRenderer;
|
|
||||||
|
|
||||||
import net.minecraft.client.renderer.BufferBuilder;
|
|
||||||
|
|
||||||
public class TransformedModel extends InstancedModel<ModelData> {
|
|
||||||
public static final VertexFormat INSTANCE_FORMAT = VertexFormat.builder()
|
|
||||||
.addAttributes(BasicAttributes.class)
|
|
||||||
.addAttributes(TransformAttributes.class)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
public TransformedModel(InstancedTileRenderer<?> renderer, BufferBuilder buf) {
|
|
||||||
super(renderer, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ModelData newInstance() {
|
|
||||||
return new ModelData(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected VertexFormat getInstanceFormat() {
|
|
||||||
return INSTANCE_FORMAT;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
package com.jozufozu.flywheel.backend.gl;
|
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
import org.lwjgl.opengl.GL30;
|
|
||||||
|
|
||||||
public class MappedBufferRange extends MappedBuffer {
|
|
||||||
|
|
||||||
GlBuffer owner;
|
|
||||||
|
|
||||||
public MappedBufferRange(GlBuffer buffer, ByteBuffer internal) {
|
|
||||||
super(internal);
|
|
||||||
this.owner = buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static MappedBufferRange create(GlBuffer buffer, long offset, long length, int access) {
|
|
||||||
ByteBuffer byteBuffer = GL30.glMapBufferRange(buffer.type.glEnum, offset, length, access);
|
|
||||||
|
|
||||||
return new MappedBufferRange(buffer, byteBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MappedBuffer unmap() {
|
|
||||||
GL30.glUnmapBuffer(owner.type.glEnum);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() throws Exception {
|
|
||||||
unmap();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +1,13 @@
|
||||||
package com.jozufozu.flywheel.backend.gl;
|
package com.jozufozu.flywheel.backend.gl.buffer;
|
||||||
|
|
||||||
import org.lwjgl.opengl.GL15;
|
import org.lwjgl.opengl.GL15;
|
||||||
import org.lwjgl.opengl.GL20;
|
import org.lwjgl.opengl.GL20;
|
||||||
import org.lwjgl.opengl.GL30;
|
import org.lwjgl.opengl.GL30;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.backend.Backend;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.GlObject;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.versioned.MapBufferRange;
|
||||||
|
|
||||||
public class GlBuffer extends GlObject {
|
public class GlBuffer extends GlObject {
|
||||||
|
|
||||||
protected final GlBufferType type;
|
protected final GlBufferType type;
|
||||||
|
@ -43,8 +47,14 @@ public class GlBuffer extends GlObject {
|
||||||
GL15.glBufferData(type.glEnum, size, usage.glEnum);
|
GL15.glBufferData(type.glEnum, size, usage.glEnum);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MappedBufferRange getBuffer(int offset, int length) {
|
public MappedBuffer getBuffer(int offset, int length) {
|
||||||
return MappedBufferRange.create(this, offset, length, GL30.GL_MAP_WRITE_BIT);
|
if (Backend.compat.mapBufferRange != MapBufferRange.UNSUPPORTED) {
|
||||||
|
return new MappedBufferRange(this, offset, length, GL30.GL_MAP_WRITE_BIT);
|
||||||
|
} else {
|
||||||
|
MappedFullBuffer fullBuffer = new MappedFullBuffer(this, MappedBufferUsage.WRITE_ONLY);
|
||||||
|
fullBuffer.position(offset);
|
||||||
|
return fullBuffer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void deleteInternal(int handle) {
|
protected void deleteInternal(int handle) {
|
|
@ -1,4 +1,4 @@
|
||||||
package com.jozufozu.flywheel.backend.gl;
|
package com.jozufozu.flywheel.backend.gl.buffer;
|
||||||
|
|
||||||
import org.lwjgl.opengl.GL15C;
|
import org.lwjgl.opengl.GL15C;
|
||||||
import org.lwjgl.opengl.GL21;
|
import org.lwjgl.opengl.GL21;
|
|
@ -1,4 +1,4 @@
|
||||||
package com.jozufozu.flywheel.backend.gl;
|
package com.jozufozu.flywheel.backend.gl.buffer;
|
||||||
|
|
||||||
import org.lwjgl.opengl.GL15;
|
import org.lwjgl.opengl.GL15;
|
||||||
|
|
|
@ -1,16 +1,43 @@
|
||||||
package com.jozufozu.flywheel.backend.gl;
|
package com.jozufozu.flywheel.backend.gl.buffer;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.lwjgl.opengl.GL15;
|
||||||
|
|
||||||
public abstract class MappedBuffer implements AutoCloseable {
|
public abstract class MappedBuffer implements AutoCloseable {
|
||||||
|
|
||||||
private final ByteBuffer internal;
|
protected boolean mapped;
|
||||||
|
protected final GlBuffer owner;
|
||||||
|
protected ByteBuffer internal;
|
||||||
|
|
||||||
public MappedBuffer(ByteBuffer internal) {
|
public MappedBuffer(GlBuffer owner) {
|
||||||
|
this.owner = owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInternal(ByteBuffer internal) {
|
||||||
this.internal = internal;
|
this.internal = internal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected abstract void checkAndMap();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make the changes in client memory available to the GPU.
|
||||||
|
*/
|
||||||
|
public void flush() {
|
||||||
|
if (mapped) {
|
||||||
|
GL15.glUnmapBuffer(owner.type.glEnum);
|
||||||
|
mapped = false;
|
||||||
|
setInternal(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws Exception {
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
|
||||||
public MappedBuffer putFloatArray(float[] floats) {
|
public MappedBuffer putFloatArray(float[] floats) {
|
||||||
|
checkAndMap();
|
||||||
internal.asFloatBuffer().put(floats);
|
internal.asFloatBuffer().put(floats);
|
||||||
internal.position(internal.position() + floats.length * 4);
|
internal.position(internal.position() + floats.length * 4);
|
||||||
|
|
||||||
|
@ -18,32 +45,49 @@ public abstract class MappedBuffer implements AutoCloseable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public MappedBuffer putByteArray(byte[] bytes) {
|
public MappedBuffer putByteArray(byte[] bytes) {
|
||||||
|
checkAndMap();
|
||||||
internal.put(bytes);
|
internal.put(bytes);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Position this buffer relative to the 0-index in GPU memory.
|
||||||
|
*
|
||||||
|
* @return This buffer.
|
||||||
|
*/
|
||||||
public MappedBuffer position(int p) {
|
public MappedBuffer position(int p) {
|
||||||
|
checkAndMap();
|
||||||
internal.position(p);
|
internal.position(p);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MappedBuffer putFloat(float f) {
|
public MappedBuffer putFloat(float f) {
|
||||||
|
checkAndMap();
|
||||||
internal.putFloat(f);
|
internal.putFloat(f);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MappedBuffer putInt(int i) {
|
public MappedBuffer putInt(int i) {
|
||||||
|
checkAndMap();
|
||||||
internal.putInt(i);
|
internal.putInt(i);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MappedBuffer put(byte b) {
|
public MappedBuffer put(byte b) {
|
||||||
|
checkAndMap();
|
||||||
|
internal.put(b);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MappedBuffer put(ByteBuffer b) {
|
||||||
|
checkAndMap();
|
||||||
internal.put(b);
|
internal.put(b);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MappedBuffer putVec4(float x, float y, float z, float w) {
|
public MappedBuffer putVec4(float x, float y, float z, float w) {
|
||||||
|
checkAndMap();
|
||||||
internal.putFloat(x);
|
internal.putFloat(x);
|
||||||
internal.putFloat(y);
|
internal.putFloat(y);
|
||||||
internal.putFloat(z);
|
internal.putFloat(z);
|
||||||
|
@ -53,6 +97,7 @@ public abstract class MappedBuffer implements AutoCloseable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public MappedBuffer putVec3(float x, float y, float z) {
|
public MappedBuffer putVec3(float x, float y, float z) {
|
||||||
|
checkAndMap();
|
||||||
internal.putFloat(x);
|
internal.putFloat(x);
|
||||||
internal.putFloat(y);
|
internal.putFloat(y);
|
||||||
internal.putFloat(z);
|
internal.putFloat(z);
|
||||||
|
@ -61,6 +106,7 @@ public abstract class MappedBuffer implements AutoCloseable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public MappedBuffer putVec2(float x, float y) {
|
public MappedBuffer putVec2(float x, float y) {
|
||||||
|
checkAndMap();
|
||||||
internal.putFloat(x);
|
internal.putFloat(x);
|
||||||
internal.putFloat(y);
|
internal.putFloat(y);
|
||||||
|
|
||||||
|
@ -68,6 +114,7 @@ public abstract class MappedBuffer implements AutoCloseable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public MappedBuffer putVec3(byte x, byte y, byte z) {
|
public MappedBuffer putVec3(byte x, byte y, byte z) {
|
||||||
|
checkAndMap();
|
||||||
internal.put(x);
|
internal.put(x);
|
||||||
internal.put(y);
|
internal.put(y);
|
||||||
internal.put(z);
|
internal.put(z);
|
||||||
|
@ -76,6 +123,7 @@ public abstract class MappedBuffer implements AutoCloseable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public MappedBuffer putVec2(byte x, byte y) {
|
public MappedBuffer putVec2(byte x, byte y) {
|
||||||
|
checkAndMap();
|
||||||
internal.put(x);
|
internal.put(x);
|
||||||
internal.put(y);
|
internal.put(y);
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
package com.jozufozu.flywheel.backend.gl.buffer;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.backend.Backend;
|
||||||
|
|
||||||
|
public class MappedBufferRange extends MappedBuffer {
|
||||||
|
|
||||||
|
long offset, length;
|
||||||
|
int access;
|
||||||
|
|
||||||
|
public MappedBufferRange(GlBuffer buffer, long offset, long length, int access) {
|
||||||
|
super(buffer);
|
||||||
|
this.offset = offset;
|
||||||
|
this.length = length;
|
||||||
|
this.access = access;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MappedBuffer position(int p) {
|
||||||
|
if (p < offset || p >= offset + length) {
|
||||||
|
throw new IndexOutOfBoundsException("Index " + p + " is not mapped");
|
||||||
|
}
|
||||||
|
return super.position(p - (int) offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void checkAndMap() {
|
||||||
|
if (!mapped) {
|
||||||
|
setInternal(Backend.compat.mapBufferRange.mapBuffer(owner.type, offset, length, access));
|
||||||
|
mapped = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package com.jozufozu.flywheel.backend.gl.buffer;
|
||||||
|
|
||||||
|
import org.lwjgl.opengl.GL15C;
|
||||||
|
|
||||||
|
public enum MappedBufferUsage {
|
||||||
|
READ_ONLY(GL15C.GL_READ_ONLY),
|
||||||
|
WRITE_ONLY(GL15C.GL_WRITE_ONLY),
|
||||||
|
READ_WRITE(GL15C.GL_READ_WRITE),
|
||||||
|
;
|
||||||
|
|
||||||
|
int glEnum;
|
||||||
|
|
||||||
|
MappedBufferUsage(int glEnum) {
|
||||||
|
this.glEnum = glEnum;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package com.jozufozu.flywheel.backend.gl.buffer;
|
||||||
|
|
||||||
|
import org.lwjgl.opengl.GL15;
|
||||||
|
|
||||||
|
public class MappedFullBuffer extends MappedBuffer {
|
||||||
|
|
||||||
|
MappedBufferUsage usage;
|
||||||
|
|
||||||
|
public MappedFullBuffer(GlBuffer buffer, MappedBufferUsage usage) {
|
||||||
|
super(buffer);
|
||||||
|
this.usage = usage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void checkAndMap() {
|
||||||
|
if (!mapped) {
|
||||||
|
setInternal(GL15.glMapBuffer(owner.type.glEnum, usage.glEnum));
|
||||||
|
mapped = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,7 +23,7 @@ import com.jozufozu.flywheel.backend.gl.versioned.instancing.VertexArrayObject;
|
||||||
* most appropriate version of a feature for the current system.
|
* most appropriate version of a feature for the current system.
|
||||||
*/
|
*/
|
||||||
public class GlCompat {
|
public class GlCompat {
|
||||||
public final MapBuffer mapBuffer;
|
public final MapBufferRange mapBufferRange;
|
||||||
|
|
||||||
public final VertexArrayObject vao;
|
public final VertexArrayObject vao;
|
||||||
public final InstancedArrays instancedArrays;
|
public final InstancedArrays instancedArrays;
|
||||||
|
@ -34,7 +34,7 @@ public class GlCompat {
|
||||||
public final RGPixelFormat pixelFormat;
|
public final RGPixelFormat pixelFormat;
|
||||||
|
|
||||||
public GlCompat(GLCapabilities caps) {
|
public GlCompat(GLCapabilities caps) {
|
||||||
mapBuffer = getLatest(MapBuffer.class, caps);
|
mapBufferRange = getLatest(MapBufferRange.class, caps);
|
||||||
|
|
||||||
vao = getLatest(VertexArrayObject.class, caps);
|
vao = getLatest(VertexArrayObject.class, caps);
|
||||||
instancedArrays = getLatest(InstancedArrays.class, caps);
|
instancedArrays = getLatest(InstancedArrays.class, caps);
|
||||||
|
|
|
@ -1,94 +0,0 @@
|
||||||
package com.jozufozu.flywheel.backend.gl.versioned;
|
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
import org.lwjgl.opengl.ARBMapBufferRange;
|
|
||||||
import org.lwjgl.opengl.GL15;
|
|
||||||
import org.lwjgl.opengl.GL30;
|
|
||||||
import org.lwjgl.opengl.GLCapabilities;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.gl.GlBufferType;
|
|
||||||
|
|
||||||
public enum MapBuffer implements GlVersioned {
|
|
||||||
|
|
||||||
GL30_RANGE {
|
|
||||||
@Override
|
|
||||||
public boolean supported(GLCapabilities caps) {
|
|
||||||
return caps.OpenGL30;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ByteBuffer mapBuffer(GlBufferType target, long offset, long length, int access) {
|
|
||||||
return GL30.glMapBufferRange(target.glEnum, offset, length, access);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void mapBuffer(GlBufferType target, int offset, int length, Consumer<ByteBuffer> upload) {
|
|
||||||
ByteBuffer buffer = mapBuffer(target, offset, length, GL30.GL_MAP_WRITE_BIT);
|
|
||||||
|
|
||||||
upload.accept(buffer);
|
|
||||||
buffer.rewind();
|
|
||||||
|
|
||||||
GL30.glUnmapBuffer(target.glEnum);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
ARB_RANGE {
|
|
||||||
@Override
|
|
||||||
public boolean supported(GLCapabilities caps) {
|
|
||||||
return caps.GL_ARB_map_buffer_range;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ByteBuffer mapBuffer(GlBufferType target, long offset, long length, int access) {
|
|
||||||
return ARBMapBufferRange.glMapBufferRange(target.glEnum, offset, length, access);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void mapBuffer(GlBufferType target, int offset, int length, Consumer<ByteBuffer> upload) {
|
|
||||||
ByteBuffer buffer = ARBMapBufferRange.glMapBufferRange(target.glEnum, offset, length, GL30.GL_MAP_WRITE_BIT);
|
|
||||||
|
|
||||||
upload.accept(buffer);
|
|
||||||
buffer.rewind();
|
|
||||||
|
|
||||||
GL30.glUnmapBuffer(target.glEnum);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
GL15_MAP {
|
|
||||||
@Override
|
|
||||||
public boolean supported(GLCapabilities caps) {
|
|
||||||
return caps.OpenGL15;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void mapBuffer(GlBufferType target, int offset, int length, Consumer<ByteBuffer> upload) {
|
|
||||||
ByteBuffer buffer = GL15.glMapBuffer(target.glEnum, GL15.GL_WRITE_ONLY);
|
|
||||||
|
|
||||||
buffer.position(offset);
|
|
||||||
upload.accept(buffer);
|
|
||||||
buffer.rewind();
|
|
||||||
GL15.glUnmapBuffer(target.glEnum);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
UNSUPPORTED {
|
|
||||||
@Override
|
|
||||||
public boolean supported(GLCapabilities caps) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void mapBuffer(GlBufferType target, int offset, int length, Consumer<ByteBuffer> upload) {
|
|
||||||
throw new UnsupportedOperationException("glMapBuffer not supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void unmapBuffer(int target) {
|
|
||||||
throw new UnsupportedOperationException("glMapBuffer not supported");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
public void unmapBuffer(int target) {
|
|
||||||
GL15.glUnmapBuffer(target);
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract void mapBuffer(GlBufferType target, int offset, int length, Consumer<ByteBuffer> upload);
|
|
||||||
}
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
package com.jozufozu.flywheel.backend.gl.versioned;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.lwjgl.opengl.ARBMapBufferRange;
|
||||||
|
import org.lwjgl.opengl.GL30;
|
||||||
|
import org.lwjgl.opengl.GLCapabilities;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||||
|
|
||||||
|
public enum MapBufferRange implements GlVersioned {
|
||||||
|
|
||||||
|
GL30_RANGE {
|
||||||
|
@Override
|
||||||
|
public boolean supported(GLCapabilities caps) {
|
||||||
|
return caps.OpenGL30;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuffer mapBuffer(GlBufferType target, long offset, long length, int access) {
|
||||||
|
return GL30.glMapBufferRange(target.glEnum, offset, length, access);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ARB_RANGE {
|
||||||
|
@Override
|
||||||
|
public boolean supported(GLCapabilities caps) {
|
||||||
|
return caps.GL_ARB_map_buffer_range;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuffer mapBuffer(GlBufferType target, long offset, long length, int access) {
|
||||||
|
return ARBMapBufferRange.glMapBufferRange(target.glEnum, offset, length, access);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
UNSUPPORTED {
|
||||||
|
@Override
|
||||||
|
public boolean supported(GLCapabilities caps) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuffer mapBuffer(GlBufferType target, long offset, long length, int access) {
|
||||||
|
throw new UnsupportedOperationException("glMapBuffer not supported");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
public abstract ByteBuffer mapBuffer(GlBufferType target, long offset, long length, int access);
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
package com.jozufozu.flywheel.backend.instancing;
|
package com.jozufozu.flywheel.backend.instancing;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.gl.MappedBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
||||||
|
|
||||||
public abstract class InstanceData {
|
public abstract class InstanceData {
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
package com.jozufozu.flywheel.backend.instancing;
|
||||||
|
|
||||||
|
public interface InstanceFactory<D extends InstanceData> {
|
||||||
|
D create(InstancedModel<? super D> owner);
|
||||||
|
}
|
|
@ -1,27 +1,26 @@
|
||||||
package com.jozufozu.flywheel.backend.instancing;
|
package com.jozufozu.flywheel.backend.instancing;
|
||||||
|
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.BitSet;
|
import java.util.BitSet;
|
||||||
|
|
||||||
import org.lwjgl.opengl.GL11;
|
import org.lwjgl.opengl.GL11;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.Backend;
|
import com.jozufozu.flywheel.backend.Backend;
|
||||||
import com.jozufozu.flywheel.backend.BufferedModel;
|
import com.jozufozu.flywheel.backend.core.BufferedModel;
|
||||||
import com.jozufozu.flywheel.backend.core.materials.ModelAttributes;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.GlBuffer;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.GlBufferType;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.GlVertexArray;
|
import com.jozufozu.flywheel.backend.gl.GlVertexArray;
|
||||||
import com.jozufozu.flywheel.backend.gl.MappedBufferRange;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
||||||
|
|
||||||
import net.minecraft.client.renderer.BufferBuilder;
|
public class InstancedModel<D extends InstanceData> extends BufferedModel {
|
||||||
|
|
||||||
public abstract class InstancedModel<D extends InstanceData> extends BufferedModel {
|
|
||||||
public static final VertexFormat FORMAT = VertexFormat.builder().addAttributes(ModelAttributes.class).build();
|
|
||||||
|
|
||||||
public final InstancedTileRenderer<?> renderer;
|
public final InstancedTileRenderer<?> renderer;
|
||||||
|
|
||||||
|
protected final VertexFormat instanceFormat;
|
||||||
|
protected final InstanceFactory<D> factory;
|
||||||
protected GlVertexArray vao;
|
protected GlVertexArray vao;
|
||||||
protected GlBuffer instanceVBO;
|
protected GlBuffer instanceVBO;
|
||||||
protected int glBufferSize = -1;
|
protected int glBufferSize = -1;
|
||||||
|
@ -32,11 +31,22 @@ public abstract class InstancedModel<D extends InstanceData> extends BufferedMod
|
||||||
boolean anyToRemove;
|
boolean anyToRemove;
|
||||||
boolean anyToUpdate;
|
boolean anyToUpdate;
|
||||||
|
|
||||||
public InstancedModel(InstancedTileRenderer<?> renderer, BufferBuilder buf) {
|
public InstancedModel(VertexFormat modelFormat, ByteBuffer buf, int vertices, InstancedTileRenderer<?> renderer, VertexFormat instanceFormat, InstanceFactory<D> factory) {
|
||||||
super(buf);
|
super(modelFormat, buf, vertices);
|
||||||
|
this.factory = factory;
|
||||||
|
this.instanceFormat = instanceFormat;
|
||||||
this.renderer = renderer;
|
this.renderer = renderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public synchronized D createInstance() {
|
||||||
|
D instanceData = factory.create(this);
|
||||||
|
instanceData.dirty = true;
|
||||||
|
anyToUpdate = true;
|
||||||
|
data.add(instanceData);
|
||||||
|
|
||||||
|
return instanceData;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void init() {
|
protected void init() {
|
||||||
vao = new GlVertexArray();
|
vao = new GlVertexArray();
|
||||||
|
@ -53,14 +63,6 @@ public abstract class InstancedModel<D extends InstanceData> extends BufferedMod
|
||||||
setupAttributes();
|
setupAttributes();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int instanceCount() {
|
|
||||||
return data.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isEmpty() {
|
|
||||||
return instanceCount() == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void deleteInternal() {
|
protected void deleteInternal() {
|
||||||
super.deleteInternal();
|
super.deleteInternal();
|
||||||
|
|
||||||
|
@ -68,23 +70,13 @@ public abstract class InstancedModel<D extends InstanceData> extends BufferedMod
|
||||||
vao.delete();
|
vao.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized D createInstance() {
|
|
||||||
D instanceData = newInstance();
|
|
||||||
instanceData.dirty = true;
|
|
||||||
anyToUpdate = true;
|
|
||||||
data.add(instanceData);
|
|
||||||
|
|
||||||
return instanceData;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract D newInstance();
|
|
||||||
|
|
||||||
protected void doRender() {
|
protected void doRender() {
|
||||||
vao.bind();
|
vao.bind();
|
||||||
renderSetup();
|
renderSetup();
|
||||||
|
|
||||||
if (glInstanceCount > 0)
|
if (glInstanceCount > 0)
|
||||||
Backend.compat.drawInstanced.drawArraysInstanced(GL11.GL_QUADS, 0, vertexCount, glInstanceCount);
|
Backend.compat.drawInstanced.drawArraysInstanced(GL11.GL_QUADS, 0, vertexCount, glInstanceCount);
|
||||||
|
|
||||||
vao.unbind();
|
vao.unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,22 +107,22 @@ public abstract class InstancedModel<D extends InstanceData> extends BufferedMod
|
||||||
}
|
}
|
||||||
|
|
||||||
private void informAttribDivisors() {
|
private void informAttribDivisors() {
|
||||||
int staticAttributes = getModelFormat().getShaderAttributeCount();
|
int staticAttributes = modelFormat.getShaderAttributeCount();
|
||||||
getInstanceFormat().vertexAttribPointers(staticAttributes);
|
instanceFormat.vertexAttribPointers(staticAttributes);
|
||||||
|
|
||||||
for (int i = 0; i < getInstanceFormat().getShaderAttributeCount(); i++) {
|
for (int i = 0; i < instanceFormat.getShaderAttributeCount(); i++) {
|
||||||
Backend.compat.instancedArrays.vertexAttribDivisor(i + staticAttributes, 1);
|
Backend.compat.instancedArrays.vertexAttribDivisor(i + staticAttributes, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void clearBufferTail() {
|
private void clearBufferTail() {
|
||||||
int size = data.size();
|
int size = data.size();
|
||||||
final int offset = size * getInstanceFormat().getStride();
|
final int offset = size * instanceFormat.getStride();
|
||||||
final int length = glBufferSize - offset;
|
final int length = glBufferSize - offset;
|
||||||
if (length > 0) {
|
if (length > 0) {
|
||||||
MappedBufferRange buffer = instanceVBO.getBuffer(offset, length);
|
instanceVBO.getBuffer(offset, length)
|
||||||
buffer.putByteArray(new byte[length]);
|
.putByteArray(new byte[length])
|
||||||
buffer.unmap();
|
.flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,7 +131,7 @@ public abstract class InstancedModel<D extends InstanceData> extends BufferedMod
|
||||||
|
|
||||||
if (size <= 0) return;
|
if (size <= 0) return;
|
||||||
|
|
||||||
final int stride = getInstanceFormat().getStride();
|
final int stride = instanceFormat.getStride();
|
||||||
final BitSet dirtySet = getDirtyBitSet();
|
final BitSet dirtySet = getDirtyBitSet();
|
||||||
|
|
||||||
if (dirtySet.isEmpty()) return;
|
if (dirtySet.isEmpty()) return;
|
||||||
|
@ -151,14 +143,15 @@ public abstract class InstancedModel<D extends InstanceData> extends BufferedMod
|
||||||
final int length = (1 + lastDirty - firstDirty) * stride;
|
final int length = (1 + lastDirty - firstDirty) * stride;
|
||||||
|
|
||||||
if (length > 0) {
|
if (length > 0) {
|
||||||
MappedBufferRange mapped = instanceVBO.getBuffer(offset, length);
|
MappedBuffer mapped = instanceVBO.getBuffer(offset, length);
|
||||||
|
|
||||||
dirtySet.stream().forEach(i -> {
|
dirtySet.stream().forEach(i -> {
|
||||||
final D d = data.get(i);
|
final D d = data.get(i);
|
||||||
|
|
||||||
mapped.position(i * stride - offset);
|
mapped.position(i * stride);
|
||||||
d.write(mapped);
|
d.write(mapped);
|
||||||
});
|
});
|
||||||
mapped.unmap();
|
mapped.flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,17 +172,17 @@ public abstract class InstancedModel<D extends InstanceData> extends BufferedMod
|
||||||
|
|
||||||
private boolean realloc() {
|
private boolean realloc() {
|
||||||
int size = this.data.size();
|
int size = this.data.size();
|
||||||
int stride = getInstanceFormat().getStride();
|
int stride = instanceFormat.getStride();
|
||||||
int requiredSize = size * stride;
|
int requiredSize = size * stride;
|
||||||
if (requiredSize > glBufferSize) {
|
if (requiredSize > glBufferSize) {
|
||||||
glBufferSize = requiredSize + stride * 16;
|
glBufferSize = requiredSize + stride * 16;
|
||||||
instanceVBO.alloc(glBufferSize);
|
instanceVBO.alloc(glBufferSize);
|
||||||
|
|
||||||
MappedBufferRange buffer = instanceVBO.getBuffer(0, glBufferSize);
|
MappedBuffer buffer = instanceVBO.getBuffer(0, glBufferSize);
|
||||||
for (D datum : data) {
|
for (D datum : data) {
|
||||||
datum.write(buffer);
|
datum.write(buffer);
|
||||||
}
|
}
|
||||||
buffer.unmap();
|
buffer.flush();
|
||||||
|
|
||||||
glInstanceCount = size;
|
glInstanceCount = size;
|
||||||
return true;
|
return true;
|
||||||
|
@ -198,9 +191,7 @@ public abstract class InstancedModel<D extends InstanceData> extends BufferedMod
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeDeletedInstances() {
|
private void removeDeletedInstances() {
|
||||||
// figure out which elements are to be removed
|
// Figure out which elements are to be removed.
|
||||||
// any exception thrown from the filter predicate at this stage
|
|
||||||
// will leave the collection unmodified
|
|
||||||
final int oldSize = this.data.size();
|
final int oldSize = this.data.size();
|
||||||
int removeCount = 0;
|
int removeCount = 0;
|
||||||
final BitSet removeSet = new BitSet(oldSize);
|
final BitSet removeSet = new BitSet(oldSize);
|
||||||
|
@ -231,28 +222,7 @@ public abstract class InstancedModel<D extends InstanceData> extends BufferedMod
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void copyVertex(MappedBufferRange constant, int i) {
|
|
||||||
constant.putFloat(getX(template, i));
|
|
||||||
constant.putFloat(getY(template, i));
|
|
||||||
constant.putFloat(getZ(template, i));
|
|
||||||
|
|
||||||
constant.put(getNX(template, i));
|
|
||||||
constant.put(getNY(template, i));
|
|
||||||
constant.put(getNZ(template, i));
|
|
||||||
|
|
||||||
constant.putFloat(getU(template, i));
|
|
||||||
constant.putFloat(getV(template, i));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected VertexFormat getModelFormat() {
|
|
||||||
return FORMAT;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract VertexFormat getInstanceFormat();
|
|
||||||
|
|
||||||
protected int getTotalShaderAttributeCount() {
|
protected int getTotalShaderAttributeCount() {
|
||||||
return getInstanceFormat().getShaderAttributeCount() + super.getTotalShaderAttributeCount();
|
return instanceFormat.getShaderAttributeCount() + super.getTotalShaderAttributeCount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ public abstract class InstancedTileRenderer<P extends BasicProgram> {
|
||||||
|
|
||||||
materials = new HashMap<>();
|
materials = new HashMap<>();
|
||||||
for (MaterialSpec<?> spec : Backend.allMaterials()) {
|
for (MaterialSpec<?> spec : Backend.allMaterials()) {
|
||||||
materials.put(spec, spec.create(this));
|
materials.put(spec, new RenderMaterial<>(this, spec));
|
||||||
}
|
}
|
||||||
|
|
||||||
queuedUpdates = ConcurrentHashMap.newKeySet(64);
|
queuedUpdates = ConcurrentHashMap.newKeySet(64);
|
||||||
|
@ -137,15 +137,15 @@ public abstract class InstancedTileRenderer<P extends BasicProgram> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <M extends InstancedModel<?>> RenderMaterial<P, M> getMaterial(MaterialSpec<M> materialType) {
|
public <D extends InstanceData> RenderMaterial<P, D> getMaterial(MaterialSpec<D> materialType) {
|
||||||
return (RenderMaterial<P, M>) materials.get(materialType);
|
return (RenderMaterial<P, D>) materials.get(materialType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public RenderMaterial<P, InstancedModel<ModelData>> getTransformMaterial() {
|
public RenderMaterial<P, ModelData> getTransformMaterial() {
|
||||||
return getMaterial(AllMaterialSpecs.TRANSFORMED);
|
return getMaterial(AllMaterialSpecs.TRANSFORMED);
|
||||||
}
|
}
|
||||||
|
|
||||||
public RenderMaterial<P, InstancedModel<OrientedData>> getOrientedMaterial() {
|
public RenderMaterial<P, OrientedData> getOrientedMaterial() {
|
||||||
return getMaterial(AllMaterialSpecs.ORIENTED);
|
return getMaterial(AllMaterialSpecs.ORIENTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,32 +1,35 @@
|
||||||
package com.jozufozu.flywheel.backend.instancing;
|
package com.jozufozu.flywheel.backend.instancing;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.core.BasicProgram;
|
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
||||||
import com.jozufozu.flywheel.backend.gl.shader.ProgramSpec;
|
import com.jozufozu.flywheel.backend.gl.shader.ProgramSpec;
|
||||||
|
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
|
||||||
public class MaterialSpec<M extends InstancedModel<?>> {
|
public class MaterialSpec<D extends InstanceData> {
|
||||||
|
|
||||||
public final ResourceLocation name;
|
public final ResourceLocation name;
|
||||||
|
|
||||||
private final ProgramSpec programSpec;
|
private final ProgramSpec programSpec;
|
||||||
private final ModelFactory<M> modelFactory;
|
private final VertexFormat instanceFormat;
|
||||||
|
private final InstanceFactory<D> instanceFactory;
|
||||||
|
|
||||||
public MaterialSpec(ResourceLocation name, ProgramSpec programSpec, ModelFactory<M> modelFactory) {
|
public MaterialSpec(ResourceLocation name, ProgramSpec programSpec, VertexFormat instanceFormat, InstanceFactory<D> instanceFactory) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.programSpec = programSpec;
|
this.programSpec = programSpec;
|
||||||
this.modelFactory = modelFactory;
|
this.instanceFormat = instanceFormat;
|
||||||
|
this.instanceFactory = instanceFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProgramSpec getProgramSpec() {
|
public ProgramSpec getProgramSpec() {
|
||||||
return programSpec;
|
return programSpec;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModelFactory<M> getModelFactory() {
|
public VertexFormat getInstanceFormat() {
|
||||||
return modelFactory;
|
return instanceFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <P extends BasicProgram> RenderMaterial<P, M> create(InstancedTileRenderer<P> renderer) {
|
public InstanceFactory<D> getInstanceFactory() {
|
||||||
return new RenderMaterial<>(renderer, programSpec, modelFactory);
|
return instanceFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
package com.jozufozu.flywheel.backend.instancing;
|
|
||||||
|
|
||||||
import net.minecraft.client.renderer.BufferBuilder;
|
|
||||||
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface ModelFactory<B extends InstancedModel<?>> {
|
|
||||||
B makeModel(InstancedTileRenderer<?> renderer, BufferBuilder buf);
|
|
||||||
}
|
|
|
@ -1,9 +1,10 @@
|
||||||
package com.jozufozu.flywheel.backend.instancing;
|
package com.jozufozu.flywheel.backend.instancing;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Predicate;
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
@ -13,8 +14,10 @@ import com.google.common.cache.Cache;
|
||||||
import com.google.common.cache.CacheBuilder;
|
import com.google.common.cache.CacheBuilder;
|
||||||
import com.jozufozu.flywheel.backend.core.BasicProgram;
|
import com.jozufozu.flywheel.backend.core.BasicProgram;
|
||||||
import com.jozufozu.flywheel.backend.core.PartialModel;
|
import com.jozufozu.flywheel.backend.core.PartialModel;
|
||||||
import com.jozufozu.flywheel.backend.gl.shader.ProgramSpec;
|
import com.jozufozu.flywheel.backend.core.materials.ModelAttributes;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
||||||
import com.jozufozu.flywheel.backend.gl.shader.ShaderCallback;
|
import com.jozufozu.flywheel.backend.gl.shader.ShaderCallback;
|
||||||
|
import com.jozufozu.flywheel.util.BufferBuilderReader;
|
||||||
import com.jozufozu.flywheel.util.RenderUtil;
|
import com.jozufozu.flywheel.util.RenderUtil;
|
||||||
import com.jozufozu.flywheel.util.VirtualEmptyModelData;
|
import com.jozufozu.flywheel.util.VirtualEmptyModelData;
|
||||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||||
|
@ -32,33 +35,20 @@ import net.minecraft.util.Direction;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.vector.Matrix4f;
|
import net.minecraft.util.math.vector.Matrix4f;
|
||||||
|
|
||||||
public class RenderMaterial<P extends BasicProgram, MODEL extends InstancedModel<?>> {
|
public class RenderMaterial<P extends BasicProgram, D extends InstanceData> {
|
||||||
|
public static final VertexFormat MODEL_FORMAT = VertexFormat.builder().addAttributes(ModelAttributes.class).build();
|
||||||
|
|
||||||
protected final InstancedTileRenderer<P> renderer;
|
protected final InstancedTileRenderer<P> renderer;
|
||||||
protected final Cache<Object, MODEL> models;
|
protected final Cache<Object, InstancedModel<D>> models;
|
||||||
protected final ModelFactory<MODEL> factory;
|
protected final MaterialSpec<D> spec;
|
||||||
protected final ProgramSpec programSpec;
|
|
||||||
protected final Predicate<RenderType> layerPredicate;
|
|
||||||
|
|
||||||
/**
|
public RenderMaterial(InstancedTileRenderer<P> renderer, MaterialSpec<D> spec) {
|
||||||
* Creates a material that renders in the default layer (CUTOUT_MIPPED)
|
|
||||||
*/
|
|
||||||
public RenderMaterial(InstancedTileRenderer<P> renderer, ProgramSpec programSpec, ModelFactory<MODEL> factory) {
|
|
||||||
this(renderer, programSpec, factory, type -> type == RenderType.getCutoutMipped());
|
|
||||||
}
|
|
||||||
|
|
||||||
public RenderMaterial(InstancedTileRenderer<P> renderer, ProgramSpec programSpec, ModelFactory<MODEL> factory, Predicate<RenderType> layerPredicate) {
|
|
||||||
this.renderer = renderer;
|
this.renderer = renderer;
|
||||||
|
this.spec = spec;
|
||||||
|
|
||||||
this.models = CacheBuilder.newBuilder()
|
this.models = CacheBuilder.newBuilder()
|
||||||
.removalListener(notification -> ((InstancedModel<?>) notification.getValue()).delete())
|
.removalListener(notification -> ((InstancedModel<?>) notification.getValue()).delete())
|
||||||
.build();
|
.build();
|
||||||
this.factory = factory;
|
|
||||||
this.programSpec = programSpec;
|
|
||||||
this.layerPredicate = layerPredicate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean canRenderInLayer(RenderType layer) {
|
|
||||||
return layerPredicate.test(layer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void render(RenderType layer, Matrix4f projection, double camX, double camY, double camZ) {
|
public void render(RenderType layer, Matrix4f projection, double camX, double camY, double camZ) {
|
||||||
|
@ -66,9 +56,9 @@ public class RenderMaterial<P extends BasicProgram, MODEL extends InstancedModel
|
||||||
}
|
}
|
||||||
|
|
||||||
public void render(RenderType layer, Matrix4f viewProjection, double camX, double camY, double camZ, ShaderCallback<P> setup) {
|
public void render(RenderType layer, Matrix4f viewProjection, double camX, double camY, double camZ, ShaderCallback<P> setup) {
|
||||||
if (!canRenderInLayer(layer)) return;
|
if (!(layer == RenderType.getCutoutMipped())) return;
|
||||||
|
|
||||||
P program = renderer.context.getProgram(programSpec);
|
P program = renderer.context.getProgram(this.spec.getProgramSpec());
|
||||||
program.bind();
|
program.bind();
|
||||||
program.uploadViewProjection(viewProjection);
|
program.uploadViewProjection(viewProjection);
|
||||||
program.uploadCameraPos(camX, camY, camZ);
|
program.uploadCameraPos(camX, camY, camZ);
|
||||||
|
@ -87,30 +77,30 @@ public class RenderMaterial<P extends BasicProgram, MODEL extends InstancedModel
|
||||||
runOnAll(InstancedModel::render);
|
runOnAll(InstancedModel::render);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void runOnAll(Consumer<MODEL> f) {
|
public void runOnAll(Consumer<InstancedModel<D>> f) {
|
||||||
for (MODEL model : models.asMap().values()) {
|
for (InstancedModel<D> model : models.asMap().values()) {
|
||||||
f.accept(model);
|
f.accept(model);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public MODEL getModel(PartialModel partial, BlockState referenceState) {
|
public InstancedModel<D> getModel(PartialModel partial, BlockState referenceState) {
|
||||||
return get(partial, () -> buildModel(partial.get(), referenceState));
|
return get(partial, () -> buildModel(partial.get(), referenceState));
|
||||||
}
|
}
|
||||||
|
|
||||||
public MODEL getModel(PartialModel partial, BlockState referenceState, Direction dir) {
|
public InstancedModel<D> getModel(PartialModel partial, BlockState referenceState, Direction dir) {
|
||||||
return getModel(partial, referenceState, dir, RenderUtil.rotateToFace(dir));
|
return getModel(partial, referenceState, dir, RenderUtil.rotateToFace(dir));
|
||||||
}
|
}
|
||||||
|
|
||||||
public MODEL getModel(PartialModel partial, BlockState referenceState, Direction dir, Supplier<MatrixStack> modelTransform) {
|
public InstancedModel<D> getModel(PartialModel partial, BlockState referenceState, Direction dir, Supplier<MatrixStack> modelTransform) {
|
||||||
return get(Pair.of(dir, partial),
|
return get(Pair.of(dir, partial),
|
||||||
() -> buildModel(partial.get(), referenceState, modelTransform.get()));
|
() -> buildModel(partial.get(), referenceState, modelTransform.get()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public MODEL getModel(BlockState toRender) {
|
public InstancedModel<D> getModel(BlockState toRender) {
|
||||||
return get(toRender, () -> buildModel(toRender));
|
return get(toRender, () -> buildModel(toRender));
|
||||||
}
|
}
|
||||||
|
|
||||||
public MODEL get(Object key, Supplier<MODEL> supplier) {
|
public InstancedModel<D> get(Object key, Supplier<InstancedModel<D>> supplier) {
|
||||||
try {
|
try {
|
||||||
return models.get(key, supplier::get);
|
return models.get(key, supplier::get);
|
||||||
} catch (ExecutionException e) {
|
} catch (ExecutionException e) {
|
||||||
|
@ -119,19 +109,40 @@ public class RenderMaterial<P extends BasicProgram, MODEL extends InstancedModel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private MODEL buildModel(BlockState renderedState) {
|
private InstancedModel<D> buildModel(BlockState renderedState) {
|
||||||
BlockRendererDispatcher dispatcher = Minecraft.getInstance().getBlockRendererDispatcher();
|
BlockRendererDispatcher dispatcher = Minecraft.getInstance().getBlockRendererDispatcher();
|
||||||
return buildModel(dispatcher.getModelForState(renderedState), renderedState);
|
return buildModel(dispatcher.getModelForState(renderedState), renderedState);
|
||||||
}
|
}
|
||||||
|
|
||||||
private MODEL buildModel(IBakedModel model, BlockState renderedState) {
|
private InstancedModel<D> buildModel(IBakedModel model, BlockState renderedState) {
|
||||||
return buildModel(model, renderedState, new MatrixStack());
|
return buildModel(model, renderedState, new MatrixStack());
|
||||||
}
|
}
|
||||||
|
|
||||||
private MODEL buildModel(IBakedModel model, BlockState referenceState, MatrixStack ms) {
|
private InstancedModel<D> buildModel(IBakedModel model, BlockState referenceState, MatrixStack ms) {
|
||||||
BufferBuilder builder = getBufferBuilder(model, referenceState, ms);
|
BufferBuilderReader reader = new BufferBuilderReader(getBufferBuilder(model, referenceState, ms));
|
||||||
|
|
||||||
return factory.makeModel(renderer, builder);
|
VertexFormat format = MODEL_FORMAT;
|
||||||
|
int vertexCount = reader.getVertexCount();
|
||||||
|
|
||||||
|
ByteBuffer to = ByteBuffer.allocate(vertexCount * format.getStride());
|
||||||
|
to.order(ByteOrder.nativeOrder());
|
||||||
|
|
||||||
|
for (int i = 0; i < vertexCount; i++) {
|
||||||
|
to.putFloat(reader.getX(i));
|
||||||
|
to.putFloat(reader.getY(i));
|
||||||
|
to.putFloat(reader.getZ(i));
|
||||||
|
|
||||||
|
to.put(reader.getNX(i));
|
||||||
|
to.put(reader.getNY(i));
|
||||||
|
to.put(reader.getNZ(i));
|
||||||
|
|
||||||
|
to.putFloat(reader.getU(i));
|
||||||
|
to.putFloat(reader.getV(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
to.rewind();
|
||||||
|
|
||||||
|
return new InstancedModel<>(format, to, vertexCount, renderer, spec.getInstanceFormat(), spec.getInstanceFactory());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Direction[] dirs;
|
private static final Direction[] dirs;
|
||||||
|
|
|
@ -117,11 +117,11 @@ public abstract class TileEntityInstance<T extends TileEntity> implements IInsta
|
||||||
models.forEach(model -> model.setBlockLight(block).setSkyLight(sky));
|
models.forEach(model -> model.setBlockLight(block).setSkyLight(sky));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected RenderMaterial<?, InstancedModel<ModelData>> getTransformMaterial() {
|
protected RenderMaterial<?, ModelData> getTransformMaterial() {
|
||||||
return renderer.getTransformMaterial();
|
return renderer.getTransformMaterial();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected RenderMaterial<?, InstancedModel<OrientedData>> getOrientedMaterial() {
|
protected RenderMaterial<?, OrientedData> getOrientedMaterial() {
|
||||||
return renderer.getOrientedMaterial();
|
return renderer.getOrientedMaterial();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,106 @@
|
||||||
|
package com.jozufozu.flywheel.util;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import com.mojang.datafixers.util.Pair;
|
||||||
|
|
||||||
|
import net.minecraft.client.renderer.BufferBuilder;
|
||||||
|
import net.minecraft.client.renderer.vertex.VertexFormat;
|
||||||
|
|
||||||
|
public class BufferBuilderReader {
|
||||||
|
|
||||||
|
private final ByteBuffer buffer;
|
||||||
|
private final int vertexCount;
|
||||||
|
private final int formatSize;
|
||||||
|
private final int size;
|
||||||
|
|
||||||
|
public BufferBuilderReader(BufferBuilder builder) {
|
||||||
|
VertexFormat vertexFormat = builder.getVertexFormat();
|
||||||
|
Pair<BufferBuilder.DrawState, ByteBuffer> data = builder.popData();
|
||||||
|
buffer = data.getSecond();
|
||||||
|
|
||||||
|
formatSize = vertexFormat.getSize();
|
||||||
|
|
||||||
|
vertexCount = data.getFirst()
|
||||||
|
.getCount();
|
||||||
|
|
||||||
|
size = vertexCount * formatSize;
|
||||||
|
|
||||||
|
// TODO: adjust the getters based on the input format
|
||||||
|
// ImmutableList<VertexFormatElement> elements = vertexFormat.getElements();
|
||||||
|
// for (int i = 0, size = elements.size(); i < size; i++) {
|
||||||
|
// VertexFormatElement element = elements.get(i);
|
||||||
|
// int offset = vertexFormat.getOffset(i);
|
||||||
|
//
|
||||||
|
// element.getUsage()
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return vertexCount == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int vertIdx(int vertexIndex) {
|
||||||
|
return vertexIndex * formatSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getX(int index) {
|
||||||
|
return buffer.getFloat(vertIdx(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getY(int index) {
|
||||||
|
return buffer.getFloat(vertIdx(index) + 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getZ(int index) {
|
||||||
|
return buffer.getFloat(vertIdx(index) + 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getR(int index) {
|
||||||
|
return buffer.get(vertIdx(index) + 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getG(int index) {
|
||||||
|
return buffer.get(vertIdx(index) + 13);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getB(int index) {
|
||||||
|
return buffer.get(vertIdx(index) + 14);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getA(int index) {
|
||||||
|
return buffer.get(vertIdx(index) + 15);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getU(int index) {
|
||||||
|
return buffer.getFloat(vertIdx(index) + 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getV(int index) {
|
||||||
|
return buffer.getFloat(vertIdx(index) + 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLight(int index) {
|
||||||
|
return buffer.getInt(vertIdx(index) + 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getNX(int index) {
|
||||||
|
return buffer.get(vertIdx(index) + 28);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getNY(int index) {
|
||||||
|
return buffer.get(vertIdx(index) + 29);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getNZ(int index) {
|
||||||
|
return buffer.get(vertIdx(index) + 30);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getVertexCount() {
|
||||||
|
return vertexCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSize() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
package com.simibubi.create.content.contraptions.base;
|
package com.simibubi.create.content.contraptions.base;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.core.materials.BasicData;
|
import com.jozufozu.flywheel.backend.core.materials.BasicData;
|
||||||
import com.jozufozu.flywheel.backend.gl.MappedBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedModel;
|
import com.jozufozu.flywheel.backend.instancing.InstancedModel;
|
||||||
import com.simibubi.create.foundation.utility.ColorHelper;
|
import com.simibubi.create.foundation.utility.ColorHelper;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package com.simibubi.create.content.contraptions.base;
|
package com.simibubi.create.content.contraptions.base;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedModel;
|
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedTileRenderer;
|
import com.jozufozu.flywheel.backend.instancing.InstancedTileRenderer;
|
||||||
import com.jozufozu.flywheel.backend.instancing.RenderMaterial;
|
import com.jozufozu.flywheel.backend.instancing.RenderMaterial;
|
||||||
import com.jozufozu.flywheel.backend.instancing.TileEntityInstance;
|
import com.jozufozu.flywheel.backend.instancing.TileEntityInstance;
|
||||||
|
@ -85,7 +84,7 @@ public abstract class KineticTileInstance<T extends KineticTileEntity> extends T
|
||||||
return shaft(getRotationAxis());
|
return shaft(getRotationAxis());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final RenderMaterial<?, InstancedModel<RotatingData>> getRotatingMaterial() {
|
protected final RenderMaterial<?, RotatingData> getRotatingMaterial() {
|
||||||
return renderer.getMaterial(AllMaterialSpecs.ROTATING);
|
return renderer.getMaterial(AllMaterialSpecs.ROTATING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package com.simibubi.create.content.contraptions.base;
|
package com.simibubi.create.content.contraptions.base;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.gl.MappedBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedModel;
|
import com.jozufozu.flywheel.backend.instancing.InstancedModel;
|
||||||
|
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
|
@ -11,7 +11,7 @@ public class RotatingData extends KineticData {
|
||||||
private byte rotationAxisY;
|
private byte rotationAxisY;
|
||||||
private byte rotationAxisZ;
|
private byte rotationAxisZ;
|
||||||
|
|
||||||
protected RotatingData(InstancedModel<?> owner) {
|
public RotatingData(InstancedModel<?> owner) {
|
||||||
super(owner);
|
super(owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
package com.simibubi.create.content.contraptions.base;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.core.materials.BasicAttributes;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedModel;
|
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedTileRenderer;
|
|
||||||
|
|
||||||
import net.minecraft.client.renderer.BufferBuilder;
|
|
||||||
|
|
||||||
public class RotatingModel extends InstancedModel<RotatingData> {
|
|
||||||
public static VertexFormat FORMAT = VertexFormat.builder()
|
|
||||||
.addAttributes(BasicAttributes.class)
|
|
||||||
.addAttributes(KineticAttributes.class)
|
|
||||||
.addAttributes(RotatingAttributes.class)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
public RotatingModel(InstancedTileRenderer<?> renderer, BufferBuilder buf) {
|
|
||||||
super(renderer, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected RotatingData newInstance() {
|
|
||||||
return new RotatingData(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected VertexFormat getInstanceFormat() {
|
|
||||||
return FORMAT;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,6 +1,6 @@
|
||||||
package com.simibubi.create.content.contraptions.components.actors;
|
package com.simibubi.create.content.contraptions.components.actors;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.gl.MappedBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstanceData;
|
import com.jozufozu.flywheel.backend.instancing.InstanceData;
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedModel;
|
import com.jozufozu.flywheel.backend.instancing.InstancedModel;
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ public class ActorData extends InstanceData {
|
||||||
|
|
||||||
private float speed;
|
private float speed;
|
||||||
|
|
||||||
protected ActorData(InstancedModel<?> owner) {
|
public ActorData(InstancedModel<?> owner) {
|
||||||
super(owner);
|
super(owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
package com.simibubi.create.content.contraptions.components.actors;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedModel;
|
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedTileRenderer;
|
|
||||||
|
|
||||||
import net.minecraft.client.renderer.BufferBuilder;
|
|
||||||
|
|
||||||
public class ActorModel extends InstancedModel<ActorData> {
|
|
||||||
public static VertexFormat FORMAT = VertexFormat.builder()
|
|
||||||
.addAttributes(ActorVertexAttributes.class)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
public ActorModel(InstancedTileRenderer<?> renderer, BufferBuilder buf) {
|
|
||||||
super(renderer, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected VertexFormat getInstanceFormat() {
|
|
||||||
return FORMAT;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ActorData newInstance() {
|
|
||||||
return new ActorData(this);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +1,5 @@
|
||||||
package com.simibubi.create.content.contraptions.components.actors;
|
package com.simibubi.create.content.contraptions.components.actors;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedModel;
|
|
||||||
import com.jozufozu.flywheel.backend.instancing.RenderMaterial;
|
import com.jozufozu.flywheel.backend.instancing.RenderMaterial;
|
||||||
import com.simibubi.create.AllBlockPartials;
|
import com.simibubi.create.AllBlockPartials;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
||||||
|
@ -21,7 +20,7 @@ public class DrillActorInstance extends ActorInstance {
|
||||||
public DrillActorInstance(ContraptionKineticRenderer modelManager, MovementContext context) {
|
public DrillActorInstance(ContraptionKineticRenderer modelManager, MovementContext context) {
|
||||||
super(modelManager, context);
|
super(modelManager, context);
|
||||||
|
|
||||||
RenderMaterial<?, InstancedModel<ActorData>> renderMaterial = modelManager.getActorMaterial();
|
RenderMaterial<?, ActorData> renderMaterial = modelManager.getActorMaterial();
|
||||||
|
|
||||||
BlockState state = context.state;
|
BlockState state = context.state;
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ package com.simibubi.create.content.contraptions.components.actors;
|
||||||
import static net.minecraft.state.properties.BlockStateProperties.HORIZONTAL_FACING;
|
import static net.minecraft.state.properties.BlockStateProperties.HORIZONTAL_FACING;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.core.materials.ModelData;
|
import com.jozufozu.flywheel.backend.core.materials.ModelData;
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedModel;
|
|
||||||
import com.jozufozu.flywheel.backend.instancing.RenderMaterial;
|
import com.jozufozu.flywheel.backend.instancing.RenderMaterial;
|
||||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||||
import com.simibubi.create.AllBlockPartials;
|
import com.simibubi.create.AllBlockPartials;
|
||||||
|
@ -36,7 +35,7 @@ public class HarvesterActorInstance extends ActorInstance {
|
||||||
public HarvesterActorInstance(ContraptionKineticRenderer modelManager, MovementContext context) {
|
public HarvesterActorInstance(ContraptionKineticRenderer modelManager, MovementContext context) {
|
||||||
super(modelManager, context);
|
super(modelManager, context);
|
||||||
|
|
||||||
RenderMaterial<?, InstancedModel<ModelData>> renderMaterial = modelManager.getTransformMaterial();
|
RenderMaterial<?, ModelData> renderMaterial = modelManager.getTransformMaterial();
|
||||||
|
|
||||||
BlockState state = context.state;
|
BlockState state = context.state;
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ import static com.simibubi.create.content.contraptions.base.DirectionalKineticBl
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.core.PartialModel;
|
import com.jozufozu.flywheel.backend.core.PartialModel;
|
||||||
import com.jozufozu.flywheel.backend.core.materials.ModelData;
|
import com.jozufozu.flywheel.backend.core.materials.ModelData;
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedModel;
|
|
||||||
import com.jozufozu.flywheel.backend.instancing.RenderMaterial;
|
import com.jozufozu.flywheel.backend.instancing.RenderMaterial;
|
||||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||||
import com.simibubi.create.AllBlockPartials;
|
import com.simibubi.create.AllBlockPartials;
|
||||||
|
@ -45,7 +44,7 @@ public class DeployerActorInstance extends ActorInstance {
|
||||||
public DeployerActorInstance(ContraptionKineticRenderer modelManager, MovementContext context) {
|
public DeployerActorInstance(ContraptionKineticRenderer modelManager, MovementContext context) {
|
||||||
super(modelManager, context);
|
super(modelManager, context);
|
||||||
|
|
||||||
RenderMaterial<ContraptionProgram, InstancedModel<ModelData>> mat = modelManager.getTransformMaterial();
|
RenderMaterial<ContraptionProgram, ModelData> mat = modelManager.getTransformMaterial();
|
||||||
|
|
||||||
BlockState state = context.state;
|
BlockState state = context.state;
|
||||||
DeployerTileEntity.Mode mode = NBTHelper.readEnum(context.tileData, "Mode", DeployerTileEntity.Mode.class);
|
DeployerTileEntity.Mode mode = NBTHelper.readEnum(context.tileData, "Mode", DeployerTileEntity.Mode.class);
|
||||||
|
|
|
@ -63,7 +63,7 @@ public class FlyWheelInstance extends KineticTileInstance<FlywheelTileEntity> im
|
||||||
|
|
||||||
connectorAngleMult = flipAngle ? -1 : 1;
|
connectorAngleMult = flipAngle ? -1 : 1;
|
||||||
|
|
||||||
RenderMaterial<?, InstancedModel<ModelData>> mat = getTransformMaterial();
|
RenderMaterial<?, ModelData> mat = getTransformMaterial();
|
||||||
|
|
||||||
upperRotating = mat.getModel(AllBlockPartials.FLYWHEEL_UPPER_ROTATING, blockState).createInstance();
|
upperRotating = mat.getModel(AllBlockPartials.FLYWHEEL_UPPER_ROTATING, blockState).createInstance();
|
||||||
lowerRotating = mat.getModel(AllBlockPartials.FLYWHEEL_LOWER_ROTATING, blockState).createInstance();
|
lowerRotating = mat.getModel(AllBlockPartials.FLYWHEEL_LOWER_ROTATING, blockState).createInstance();
|
||||||
|
|
|
@ -7,7 +7,6 @@ import javax.annotation.Nullable;
|
||||||
|
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedModel;
|
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedTileRenderer;
|
import com.jozufozu.flywheel.backend.instancing.InstancedTileRenderer;
|
||||||
import com.jozufozu.flywheel.backend.instancing.RenderMaterial;
|
import com.jozufozu.flywheel.backend.instancing.RenderMaterial;
|
||||||
import com.simibubi.create.AllMovementBehaviours;
|
import com.simibubi.create.AllMovementBehaviours;
|
||||||
|
@ -65,7 +64,7 @@ public class ContraptionKineticRenderer extends InstancedTileRenderer<Contraptio
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RenderMaterial<?, InstancedModel<ActorData>> getActorMaterial() {
|
public RenderMaterial<?, ActorData> getActorMaterial() {
|
||||||
return getMaterial(AllMaterialSpecs.ACTORS);
|
return getMaterial(AllMaterialSpecs.ACTORS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,106 +0,0 @@
|
||||||
package com.simibubi.create.content.contraptions.components.structureMovement.render;
|
|
||||||
|
|
||||||
import org.lwjgl.opengl.GL20;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.BufferedModel;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.GlBuffer;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.GlBufferType;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.GlPrimitiveType;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.MappedBufferRange;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
|
||||||
|
|
||||||
import net.minecraft.client.renderer.BufferBuilder;
|
|
||||||
import net.minecraft.client.renderer.LightTexture;
|
|
||||||
|
|
||||||
public class ContraptionModel extends BufferedModel {
|
|
||||||
public static final VertexFormat FORMAT = VertexFormat.builder()
|
|
||||||
.addAttributes(ContraptionAttributes.class)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
protected GlPrimitiveType eboIndexType;
|
|
||||||
protected GlBuffer ebo;
|
|
||||||
|
|
||||||
public ContraptionModel(BufferBuilder buf) {
|
|
||||||
super(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void init() {
|
|
||||||
super.init();
|
|
||||||
|
|
||||||
createEBO();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doRender() {
|
|
||||||
modelVBO.bind();
|
|
||||||
ebo.bind();
|
|
||||||
|
|
||||||
setupAttributes();
|
|
||||||
GL20.glDrawElements(GL20.GL_QUADS, vertexCount, eboIndexType.getGlConstant(), 0);
|
|
||||||
|
|
||||||
int numAttributes = getTotalShaderAttributeCount();
|
|
||||||
for (int i = 0; i <= numAttributes; i++) {
|
|
||||||
GL20.glDisableVertexAttribArray(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
ebo.unbind();
|
|
||||||
modelVBO.unbind();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final void createEBO() {
|
|
||||||
ebo = new GlBuffer(GlBufferType.ELEMENT_ARRAY_BUFFER);
|
|
||||||
eboIndexType = GlPrimitiveType.UINT; // TODO: choose this based on the number of vertices
|
|
||||||
|
|
||||||
int indicesSize = vertexCount * eboIndexType.getSize();
|
|
||||||
|
|
||||||
ebo.bind();
|
|
||||||
|
|
||||||
ebo.alloc(indicesSize);
|
|
||||||
MappedBufferRange indices = ebo.getBuffer(0, indicesSize);
|
|
||||||
for (int i = 0; i < vertexCount; i++) {
|
|
||||||
indices.putInt(i);
|
|
||||||
}
|
|
||||||
indices.unmap();
|
|
||||||
|
|
||||||
ebo.unbind();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void copyVertex(MappedBufferRange to, int vertex) {
|
|
||||||
to.putFloat(getX(template, vertex));
|
|
||||||
to.putFloat(getY(template, vertex));
|
|
||||||
to.putFloat(getZ(template, vertex));
|
|
||||||
|
|
||||||
to.put(getNX(template, vertex));
|
|
||||||
to.put(getNY(template, vertex));
|
|
||||||
to.put(getNZ(template, vertex));
|
|
||||||
|
|
||||||
to.putFloat(getU(template, vertex));
|
|
||||||
to.putFloat(getV(template, vertex));
|
|
||||||
|
|
||||||
to.put(getR(template, vertex));
|
|
||||||
to.put(getG(template, vertex));
|
|
||||||
to.put(getB(template, vertex));
|
|
||||||
to.put(getA(template, vertex));
|
|
||||||
|
|
||||||
int light = getLight(template, vertex);
|
|
||||||
|
|
||||||
byte block = (byte) (LightTexture.getBlockLightCoordinates(light) << 4);
|
|
||||||
byte sky = (byte) (LightTexture.getSkyLightCoordinates(light) << 4);
|
|
||||||
|
|
||||||
to.put(block);
|
|
||||||
to.put(sky);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected VertexFormat getModelFormat() {
|
|
||||||
return FORMAT;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void deleteInternal() {
|
|
||||||
super.deleteInternal();
|
|
||||||
ebo.delete();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,13 +1,20 @@
|
||||||
package com.simibubi.create.content.contraptions.components.structureMovement.render;
|
package com.simibubi.create.content.contraptions.components.structureMovement.render;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.Backend;
|
import com.jozufozu.flywheel.backend.Backend;
|
||||||
|
import com.jozufozu.flywheel.backend.core.IndexedModel;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
||||||
import com.jozufozu.flywheel.backend.instancing.IInstanceRendered;
|
import com.jozufozu.flywheel.backend.instancing.IInstanceRendered;
|
||||||
import com.jozufozu.flywheel.backend.light.GridAlignedBB;
|
import com.jozufozu.flywheel.backend.light.GridAlignedBB;
|
||||||
|
import com.jozufozu.flywheel.util.BufferBuilderReader;
|
||||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
|
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
|
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
|
||||||
|
@ -16,7 +23,7 @@ import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||||
import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld;
|
import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld;
|
||||||
|
|
||||||
import net.minecraft.client.renderer.ActiveRenderInfo;
|
import net.minecraft.client.renderer.ActiveRenderInfo;
|
||||||
import net.minecraft.client.renderer.BufferBuilder;
|
import net.minecraft.client.renderer.LightTexture;
|
||||||
import net.minecraft.client.renderer.RenderType;
|
import net.minecraft.client.renderer.RenderType;
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.tileentity.TileEntity;
|
||||||
import net.minecraft.util.math.AxisAlignedBB;
|
import net.minecraft.util.math.AxisAlignedBB;
|
||||||
|
@ -26,10 +33,14 @@ import net.minecraft.util.math.vector.Matrix4f;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
public class RenderedContraption extends ContraptionWorldHolder {
|
public class RenderedContraption extends ContraptionWorldHolder {
|
||||||
|
public static final VertexFormat FORMAT = VertexFormat.builder()
|
||||||
|
.addAttributes(ContraptionAttributes.class)
|
||||||
|
.build();
|
||||||
|
|
||||||
private final ContraptionLighter<?> lighter;
|
private final ContraptionLighter<?> lighter;
|
||||||
public final ContraptionKineticRenderer kinetics;
|
public final ContraptionKineticRenderer kinetics;
|
||||||
|
|
||||||
private final Map<RenderType, ContraptionModel> renderLayers = new HashMap<>();
|
private final Map<RenderType, IndexedModel> renderLayers = new HashMap<>();
|
||||||
|
|
||||||
private Matrix4f model;
|
private Matrix4f model;
|
||||||
private AxisAlignedBB lightBox;
|
private AxisAlignedBB lightBox;
|
||||||
|
@ -51,7 +62,7 @@ public class RenderedContraption extends ContraptionWorldHolder {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void doRenderLayer(RenderType layer, ContraptionProgram shader) {
|
public void doRenderLayer(RenderType layer, ContraptionProgram shader) {
|
||||||
ContraptionModel structure = renderLayers.get(layer);
|
IndexedModel structure = renderLayers.get(layer);
|
||||||
if (structure != null) {
|
if (structure != null) {
|
||||||
setup(shader);
|
setup(shader);
|
||||||
structure.render();
|
structure.render();
|
||||||
|
@ -92,7 +103,7 @@ public class RenderedContraption extends ContraptionWorldHolder {
|
||||||
}
|
}
|
||||||
|
|
||||||
void invalidate() {
|
void invalidate() {
|
||||||
for (ContraptionModel buffer : renderLayers.values()) {
|
for (IndexedModel buffer : renderLayers.values()) {
|
||||||
buffer.delete();
|
buffer.delete();
|
||||||
}
|
}
|
||||||
renderLayers.clear();
|
renderLayers.clear();
|
||||||
|
@ -103,7 +114,7 @@ public class RenderedContraption extends ContraptionWorldHolder {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void buildLayers() {
|
private void buildLayers() {
|
||||||
for (ContraptionModel buffer : renderLayers.values()) {
|
for (IndexedModel buffer : renderLayers.values()) {
|
||||||
buffer.delete();
|
buffer.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,7 +123,8 @@ public class RenderedContraption extends ContraptionWorldHolder {
|
||||||
List<RenderType> blockLayers = RenderType.getBlockLayers();
|
List<RenderType> blockLayers = RenderType.getBlockLayers();
|
||||||
|
|
||||||
for (RenderType layer : blockLayers) {
|
for (RenderType layer : blockLayers) {
|
||||||
renderLayers.put(layer, buildStructureModel(renderWorld, contraption, layer));
|
IndexedModel layerModel = buildStructureModel(renderWorld, contraption, layer);
|
||||||
|
if (layerModel != null) renderLayers.put(layer, layerModel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,8 +147,46 @@ public class RenderedContraption extends ContraptionWorldHolder {
|
||||||
contraption.getActors().forEach(kinetics::createActor);
|
contraption.getActors().forEach(kinetics::createActor);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ContraptionModel buildStructureModel(PlacementSimulationWorld renderWorld, Contraption c, RenderType layer) {
|
@Nullable
|
||||||
BufferBuilder builder = ContraptionRenderDispatcher.buildStructure(renderWorld, c, layer);
|
private static IndexedModel buildStructureModel(PlacementSimulationWorld renderWorld, Contraption c, RenderType layer) {
|
||||||
return new ContraptionModel(builder);
|
BufferBuilderReader reader = new BufferBuilderReader(ContraptionRenderDispatcher.buildStructure(renderWorld, c, layer));
|
||||||
|
|
||||||
|
int vertexCount = reader.getVertexCount();
|
||||||
|
if (vertexCount == 0) return null;
|
||||||
|
|
||||||
|
VertexFormat format = FORMAT;
|
||||||
|
|
||||||
|
ByteBuffer to = ByteBuffer.allocate(format.getStride() * vertexCount);
|
||||||
|
to.order(ByteOrder.nativeOrder());
|
||||||
|
|
||||||
|
for (int i = 0; i < vertexCount; i++) {
|
||||||
|
to.putFloat(reader.getX(i));
|
||||||
|
to.putFloat(reader.getY(i));
|
||||||
|
to.putFloat(reader.getZ(i));
|
||||||
|
|
||||||
|
to.put(reader.getNX(i));
|
||||||
|
to.put(reader.getNY(i));
|
||||||
|
to.put(reader.getNZ(i));
|
||||||
|
|
||||||
|
to.putFloat(reader.getU(i));
|
||||||
|
to.putFloat(reader.getV(i));
|
||||||
|
|
||||||
|
to.put(reader.getR(i));
|
||||||
|
to.put(reader.getG(i));
|
||||||
|
to.put(reader.getB(i));
|
||||||
|
to.put(reader.getA(i));
|
||||||
|
|
||||||
|
int light = reader.getLight(i);
|
||||||
|
|
||||||
|
byte block = (byte) (LightTexture.getBlockLightCoordinates(light) << 4);
|
||||||
|
byte sky = (byte) (LightTexture.getSkyLightCoordinates(light) << 4);
|
||||||
|
|
||||||
|
to.put(block);
|
||||||
|
to.put(sky);
|
||||||
|
}
|
||||||
|
|
||||||
|
to.rewind();
|
||||||
|
|
||||||
|
return new IndexedModel(format, to, vertexCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package com.simibubi.create.content.contraptions.relays.belt;
|
package com.simibubi.create.content.contraptions.relays.belt;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.gl.MappedBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedModel;
|
import com.jozufozu.flywheel.backend.instancing.InstancedModel;
|
||||||
import com.simibubi.create.content.contraptions.base.KineticData;
|
import com.simibubi.create.content.contraptions.base.KineticData;
|
||||||
import com.simibubi.create.foundation.block.render.SpriteShiftEntry;
|
import com.simibubi.create.foundation.block.render.SpriteShiftEntry;
|
||||||
|
@ -21,7 +21,7 @@ public class BeltData extends KineticData {
|
||||||
private float maxV;
|
private float maxV;
|
||||||
private byte scrollMult;
|
private byte scrollMult;
|
||||||
|
|
||||||
protected BeltData(InstancedModel<?> owner) {
|
public BeltData(InstancedModel<?> owner) {
|
||||||
super(owner);
|
super(owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
package com.simibubi.create.content.contraptions.relays.belt;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.core.materials.BasicAttributes;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedModel;
|
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedTileRenderer;
|
|
||||||
import com.simibubi.create.content.contraptions.base.KineticAttributes;
|
|
||||||
|
|
||||||
import net.minecraft.client.renderer.BufferBuilder;
|
|
||||||
|
|
||||||
public class BeltInstancedModel extends InstancedModel<BeltData> {
|
|
||||||
public static VertexFormat FORMAT = VertexFormat.builder()
|
|
||||||
.addAttributes(BasicAttributes.class)
|
|
||||||
.addAttributes(KineticAttributes.class)
|
|
||||||
.addAttributes(BeltAttributes.class)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
public BeltInstancedModel(InstancedTileRenderer<?> renderer, BufferBuilder buf) {
|
|
||||||
super(renderer, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected BeltData newInstance() {
|
|
||||||
return new BeltData(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected VertexFormat getInstanceFormat() {
|
|
||||||
return FORMAT;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -26,7 +26,7 @@ public class SplitShaftInstance extends KineticTileInstance<SplitShaftTileEntity
|
||||||
|
|
||||||
float speed = tile.getSpeed();
|
float speed = tile.getSpeed();
|
||||||
|
|
||||||
RenderMaterial<?, InstancedModel<RotatingData>> rotatingMaterial = getRotatingMaterial();
|
RenderMaterial<?, RotatingData> rotatingMaterial = getRotatingMaterial();
|
||||||
|
|
||||||
for (Direction dir : Iterate.directionsInAxis(getRotationAxis())) {
|
for (Direction dir : Iterate.directionsInAxis(getRotationAxis())) {
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ public class GearboxInstance extends KineticTileInstance<GearboxTileEntity> {
|
||||||
int skyLight = world.getLightLevel(LightType.SKY, pos);
|
int skyLight = world.getLightLevel(LightType.SKY, pos);
|
||||||
updateSourceFacing();
|
updateSourceFacing();
|
||||||
|
|
||||||
RenderMaterial<?, InstancedModel<RotatingData>> rotatingMaterial = getRotatingMaterial();
|
RenderMaterial<?, RotatingData> rotatingMaterial = getRotatingMaterial();
|
||||||
|
|
||||||
for (Direction direction : Iterate.directions) {
|
for (Direction direction : Iterate.directions) {
|
||||||
final Direction.Axis axis = direction.getAxis();
|
final Direction.Axis axis = direction.getAxis();
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package com.simibubi.create.content.logistics.block;
|
package com.simibubi.create.content.logistics.block;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.core.materials.IFlatLight;
|
import com.jozufozu.flywheel.backend.core.materials.IFlatLight;
|
||||||
import com.jozufozu.flywheel.backend.gl.MappedBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstanceData;
|
import com.jozufozu.flywheel.backend.instancing.InstanceData;
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedModel;
|
import com.jozufozu.flywheel.backend.instancing.InstancedModel;
|
||||||
|
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
package com.simibubi.create.content.logistics.block;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedModel;
|
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedTileRenderer;
|
|
||||||
|
|
||||||
import net.minecraft.client.renderer.BufferBuilder;
|
|
||||||
|
|
||||||
public class FlapModel extends InstancedModel<FlapData> {
|
|
||||||
public static VertexFormat FORMAT = VertexFormat.builder()
|
|
||||||
.addAttributes(FlapAttributes.class)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
public FlapModel(InstancedTileRenderer<?> renderer, BufferBuilder buf) {
|
|
||||||
super(renderer, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected FlapData newInstance() {
|
|
||||||
return new FlapData(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected VertexFormat getInstanceFormat() {
|
|
||||||
return FORMAT;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -47,7 +47,7 @@ public class ArmInstance extends SingleRotatingInstance implements IDynamicInsta
|
||||||
public ArmInstance(InstancedTileRenderer<?> modelManager, ArmTileEntity tile) {
|
public ArmInstance(InstancedTileRenderer<?> modelManager, ArmTileEntity tile) {
|
||||||
super(modelManager, tile);
|
super(modelManager, tile);
|
||||||
|
|
||||||
RenderMaterial<?, InstancedModel<ModelData>> mat = getTransformMaterial();
|
RenderMaterial<?, ModelData> mat = getTransformMaterial();
|
||||||
|
|
||||||
base = mat.getModel(AllBlockPartials.ARM_BASE, blockState).createInstance();
|
base = mat.getModel(AllBlockPartials.ARM_BASE, blockState).createInstance();
|
||||||
lowerBody = mat.getModel(AllBlockPartials.ARM_LOWER_BODY, blockState).createInstance();
|
lowerBody = mat.getModel(AllBlockPartials.ARM_LOWER_BODY, blockState).createInstance();
|
||||||
|
|
|
@ -2,7 +2,6 @@ package com.simibubi.create.content.logistics.block.redstone;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.core.materials.ModelData;
|
import com.jozufozu.flywheel.backend.core.materials.ModelData;
|
||||||
import com.jozufozu.flywheel.backend.instancing.IDynamicInstance;
|
import com.jozufozu.flywheel.backend.instancing.IDynamicInstance;
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedModel;
|
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedTileRenderer;
|
import com.jozufozu.flywheel.backend.instancing.InstancedTileRenderer;
|
||||||
import com.jozufozu.flywheel.backend.instancing.RenderMaterial;
|
import com.jozufozu.flywheel.backend.instancing.RenderMaterial;
|
||||||
import com.jozufozu.flywheel.backend.instancing.TileEntityInstance;
|
import com.jozufozu.flywheel.backend.instancing.TileEntityInstance;
|
||||||
|
@ -27,7 +26,7 @@ public class AnalogLeverInstance extends TileEntityInstance<AnalogLeverTileEntit
|
||||||
public AnalogLeverInstance(InstancedTileRenderer<?> modelManager, AnalogLeverTileEntity tile) {
|
public AnalogLeverInstance(InstancedTileRenderer<?> modelManager, AnalogLeverTileEntity tile) {
|
||||||
super(modelManager, tile);
|
super(modelManager, tile);
|
||||||
|
|
||||||
RenderMaterial<?, InstancedModel<ModelData>> mat = getTransformMaterial();
|
RenderMaterial<?, ModelData> mat = getTransformMaterial();
|
||||||
|
|
||||||
handle = mat.getModel(AllBlockPartials.ANALOG_LEVER_HANDLE, blockState).createInstance();
|
handle = mat.getModel(AllBlockPartials.ANALOG_LEVER_HANDLE, blockState).createInstance();
|
||||||
indicator = mat.getModel(AllBlockPartials.ANALOG_LEVER_INDICATOR, blockState).createInstance();
|
indicator = mat.getModel(AllBlockPartials.ANALOG_LEVER_INDICATOR, blockState).createInstance();
|
||||||
|
|
|
@ -2,7 +2,6 @@ package com.simibubi.create.content.schematics.block;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.core.materials.ModelData;
|
import com.jozufozu.flywheel.backend.core.materials.ModelData;
|
||||||
import com.jozufozu.flywheel.backend.instancing.IDynamicInstance;
|
import com.jozufozu.flywheel.backend.instancing.IDynamicInstance;
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedModel;
|
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedTileRenderer;
|
import com.jozufozu.flywheel.backend.instancing.InstancedTileRenderer;
|
||||||
import com.jozufozu.flywheel.backend.instancing.RenderMaterial;
|
import com.jozufozu.flywheel.backend.instancing.RenderMaterial;
|
||||||
import com.jozufozu.flywheel.backend.instancing.TileEntityInstance;
|
import com.jozufozu.flywheel.backend.instancing.TileEntityInstance;
|
||||||
|
@ -21,7 +20,7 @@ public class SchematicannonInstance extends TileEntityInstance<SchematicannonTil
|
||||||
public SchematicannonInstance(InstancedTileRenderer<?> modelManager, SchematicannonTileEntity tile) {
|
public SchematicannonInstance(InstancedTileRenderer<?> modelManager, SchematicannonTileEntity tile) {
|
||||||
super(modelManager, tile);
|
super(modelManager, tile);
|
||||||
|
|
||||||
RenderMaterial<?, InstancedModel<ModelData>> mat = getTransformMaterial();
|
RenderMaterial<?, ModelData> mat = getTransformMaterial();
|
||||||
|
|
||||||
connector = mat.getModel(AllBlockPartials.SCHEMATICANNON_CONNECTOR, blockState).createInstance();
|
connector = mat.getModel(AllBlockPartials.SCHEMATICANNON_CONNECTOR, blockState).createInstance();
|
||||||
pipe = mat.getModel(AllBlockPartials.SCHEMATICANNON_PIPE, blockState).createInstance();
|
pipe = mat.getModel(AllBlockPartials.SCHEMATICANNON_PIPE, blockState).createInstance();
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
package com.simibubi.create.foundation.render;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.backend.core.materials.BasicAttributes;
|
||||||
|
import com.jozufozu.flywheel.backend.core.materials.OrientedAttributes;
|
||||||
|
import com.jozufozu.flywheel.backend.core.materials.TransformAttributes;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
||||||
|
import com.simibubi.create.content.contraptions.base.KineticAttributes;
|
||||||
|
import com.simibubi.create.content.contraptions.base.RotatingAttributes;
|
||||||
|
import com.simibubi.create.content.contraptions.components.actors.ActorVertexAttributes;
|
||||||
|
import com.simibubi.create.content.contraptions.relays.belt.BeltAttributes;
|
||||||
|
import com.simibubi.create.content.logistics.block.FlapAttributes;
|
||||||
|
|
||||||
|
public class AllInstanceFormats {
|
||||||
|
|
||||||
|
public static final VertexFormat MODEL = VertexFormat.builder()
|
||||||
|
.addAttributes(BasicAttributes.class)
|
||||||
|
.addAttributes(TransformAttributes.class)
|
||||||
|
.build();
|
||||||
|
public static final VertexFormat ORIENTED = VertexFormat.builder()
|
||||||
|
.addAttributes(BasicAttributes.class)
|
||||||
|
.addAttributes(OrientedAttributes.class)
|
||||||
|
.build();
|
||||||
|
public static VertexFormat ROTATING = VertexFormat.builder()
|
||||||
|
.addAttributes(BasicAttributes.class)
|
||||||
|
.addAttributes(KineticAttributes.class)
|
||||||
|
.addAttributes(RotatingAttributes.class)
|
||||||
|
.build();
|
||||||
|
public static VertexFormat ACTOR = VertexFormat.builder()
|
||||||
|
.addAttributes(ActorVertexAttributes.class)
|
||||||
|
.build();
|
||||||
|
public static VertexFormat BELT = VertexFormat.builder()
|
||||||
|
.addAttributes(BasicAttributes.class)
|
||||||
|
.addAttributes(KineticAttributes.class)
|
||||||
|
.addAttributes(BeltAttributes.class)
|
||||||
|
.build();
|
||||||
|
public static VertexFormat FLAP = VertexFormat.builder()
|
||||||
|
.addAttributes(FlapAttributes.class)
|
||||||
|
.build();
|
||||||
|
}
|
|
@ -4,19 +4,12 @@ import static com.jozufozu.flywheel.backend.Backend.register;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.core.materials.ModelData;
|
import com.jozufozu.flywheel.backend.core.materials.ModelData;
|
||||||
import com.jozufozu.flywheel.backend.core.materials.OrientedData;
|
import com.jozufozu.flywheel.backend.core.materials.OrientedData;
|
||||||
import com.jozufozu.flywheel.backend.core.materials.OrientedModel;
|
|
||||||
import com.jozufozu.flywheel.backend.core.materials.TransformedModel;
|
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedModel;
|
|
||||||
import com.jozufozu.flywheel.backend.instancing.MaterialSpec;
|
import com.jozufozu.flywheel.backend.instancing.MaterialSpec;
|
||||||
import com.simibubi.create.Create;
|
import com.simibubi.create.Create;
|
||||||
import com.simibubi.create.content.contraptions.base.RotatingData;
|
import com.simibubi.create.content.contraptions.base.RotatingData;
|
||||||
import com.simibubi.create.content.contraptions.base.RotatingModel;
|
|
||||||
import com.simibubi.create.content.contraptions.components.actors.ActorData;
|
import com.simibubi.create.content.contraptions.components.actors.ActorData;
|
||||||
import com.simibubi.create.content.contraptions.components.actors.ActorModel;
|
|
||||||
import com.simibubi.create.content.contraptions.relays.belt.BeltData;
|
import com.simibubi.create.content.contraptions.relays.belt.BeltData;
|
||||||
import com.simibubi.create.content.contraptions.relays.belt.BeltInstancedModel;
|
|
||||||
import com.simibubi.create.content.logistics.block.FlapData;
|
import com.simibubi.create.content.logistics.block.FlapData;
|
||||||
import com.simibubi.create.content.logistics.block.FlapModel;
|
|
||||||
|
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
|
||||||
|
@ -25,14 +18,13 @@ public class AllMaterialSpecs {
|
||||||
// noop, make sure the static field are loaded.
|
// noop, make sure the static field are loaded.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final MaterialSpec<ModelData> TRANSFORMED = register(new MaterialSpec<>(Locations.MODEL, AllProgramSpecs.MODEL, AllInstanceFormats.MODEL, ModelData::new));
|
||||||
|
public static final MaterialSpec<OrientedData> ORIENTED = register(new MaterialSpec<>(Locations.ORIENTED, AllProgramSpecs.ORIENTED, AllInstanceFormats.ORIENTED, OrientedData::new));
|
||||||
|
|
||||||
public static final MaterialSpec<InstancedModel<ModelData>> TRANSFORMED = register(new MaterialSpec<>(Locations.MODEL, AllProgramSpecs.MODEL, TransformedModel::new));
|
public static final MaterialSpec<RotatingData> ROTATING = register(new MaterialSpec<>(Locations.ROTATING, AllProgramSpecs.ROTATING, AllInstanceFormats.ROTATING, RotatingData::new));
|
||||||
public static final MaterialSpec<InstancedModel<OrientedData>> ORIENTED = register(new MaterialSpec<>(Locations.ORIENTED, AllProgramSpecs.ORIENTED, OrientedModel::new));
|
public static final MaterialSpec<BeltData> BELTS = register(new MaterialSpec<>(Locations.BELTS, AllProgramSpecs.BELT, AllInstanceFormats.BELT, BeltData::new));
|
||||||
|
public static final MaterialSpec<ActorData> ACTORS = register(new MaterialSpec<>(Locations.ACTORS, AllProgramSpecs.ACTOR, AllInstanceFormats.ACTOR, ActorData::new));
|
||||||
public static final MaterialSpec<InstancedModel<RotatingData>> ROTATING = register(new MaterialSpec<>(Locations.ROTATING, AllProgramSpecs.ROTATING, RotatingModel::new));
|
public static final MaterialSpec<FlapData> FLAPS = register(new MaterialSpec<>(Locations.FLAPS, AllProgramSpecs.FLAPS, AllInstanceFormats.FLAP, FlapData::new));
|
||||||
public static final MaterialSpec<InstancedModel<BeltData>> BELTS = register(new MaterialSpec<>(Locations.BELTS, AllProgramSpecs.BELT, BeltInstancedModel::new));
|
|
||||||
public static final MaterialSpec<InstancedModel<ActorData>> ACTORS = register(new MaterialSpec<>(Locations.ACTORS, AllProgramSpecs.ACTOR, ActorModel::new));
|
|
||||||
public static final MaterialSpec<InstancedModel<FlapData>> FLAPS = register(new MaterialSpec<>(Locations.FLAPS, AllProgramSpecs.FLAPS, FlapModel::new));
|
|
||||||
|
|
||||||
public static class Locations {
|
public static class Locations {
|
||||||
public static final ResourceLocation MODEL = new ResourceLocation("create", "model");
|
public static final ResourceLocation MODEL = new ResourceLocation("create", "model");
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package com.simibubi.create.foundation.render;
|
package com.simibubi.create.foundation.render;
|
||||||
|
|
||||||
import java.nio.Buffer;
|
import com.jozufozu.flywheel.util.BufferBuilderReader;
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||||
import com.mojang.blaze3d.vertex.IVertexBuilder;
|
import com.mojang.blaze3d.vertex.IVertexBuilder;
|
||||||
import com.simibubi.create.foundation.block.render.SpriteShiftEntry;
|
import com.simibubi.create.foundation.block.render.SpriteShiftEntry;
|
||||||
|
@ -26,7 +24,9 @@ import net.minecraft.util.math.vector.Vector4f;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraftforge.client.model.pipeline.LightUtil;
|
import net.minecraftforge.client.model.pipeline.LightUtil;
|
||||||
|
|
||||||
public class SuperByteBuffer extends TemplateBuffer {
|
public class SuperByteBuffer {
|
||||||
|
|
||||||
|
private final BufferBuilderReader template;
|
||||||
|
|
||||||
// Vertex Position
|
// Vertex Position
|
||||||
private MatrixStack transforms;
|
private MatrixStack transforms;
|
||||||
|
@ -46,7 +46,7 @@ public class SuperByteBuffer extends TemplateBuffer {
|
||||||
private Matrix4f lightTransform;
|
private Matrix4f lightTransform;
|
||||||
|
|
||||||
public SuperByteBuffer(BufferBuilder buf) {
|
public SuperByteBuffer(BufferBuilder buf) {
|
||||||
super(buf);
|
template = new BufferBuilderReader(buf);
|
||||||
transforms = new MatrixStack();
|
transforms = new MatrixStack();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,10 +66,8 @@ public class SuperByteBuffer extends TemplateBuffer {
|
||||||
Vector4f lightPos = new Vector4f();
|
Vector4f lightPos = new Vector4f();
|
||||||
|
|
||||||
public void renderInto(MatrixStack input, IVertexBuilder builder) {
|
public void renderInto(MatrixStack input, IVertexBuilder builder) {
|
||||||
ByteBuffer buffer = template;
|
if (isEmpty())
|
||||||
if (((Buffer) buffer).limit() == 0)
|
|
||||||
return;
|
return;
|
||||||
((Buffer) buffer).rewind();
|
|
||||||
|
|
||||||
Matrix3f normalMat = transforms.peek()
|
Matrix3f normalMat = transforms.peek()
|
||||||
.getNormal()
|
.getNormal()
|
||||||
|
@ -89,18 +87,18 @@ public class SuperByteBuffer extends TemplateBuffer {
|
||||||
|
|
||||||
boolean hasDefaultLight = packedLightCoords != 0;
|
boolean hasDefaultLight = packedLightCoords != 0;
|
||||||
float f = .5f;
|
float f = .5f;
|
||||||
int vertexCount = vertexCount(buffer);
|
int vertexCount = template.getVertexCount();
|
||||||
for (int i = 0; i < vertexCount; i++) {
|
for (int i = 0; i < vertexCount; i++) {
|
||||||
float x = getX(buffer, i);
|
float x = template.getX(i);
|
||||||
float y = getY(buffer, i);
|
float y = template.getY(i);
|
||||||
float z = getZ(buffer, i);
|
float z = template.getZ(i);
|
||||||
byte r = getR(buffer, i);
|
byte r = template.getR(i);
|
||||||
byte g = getG(buffer, i);
|
byte g = template.getG(i);
|
||||||
byte b = getB(buffer, i);
|
byte b = template.getB(i);
|
||||||
byte a = getA(buffer, i);
|
byte a = template.getA(i);
|
||||||
float normalX = getNX(buffer, i) / 127f;
|
float normalX = template.getNX(i) / 127f;
|
||||||
float normalY = getNY(buffer, i) / 127f;
|
float normalY = template.getNY(i) / 127f;
|
||||||
float normalZ = getNZ(buffer, i) / 127f;
|
float normalZ = template.getNZ(i) / 127f;
|
||||||
|
|
||||||
float staticDiffuse = LightUtil.diffuseLight(normalX, normalY, normalZ);
|
float staticDiffuse = LightUtil.diffuseLight(normalX, normalY, normalZ);
|
||||||
normal.set(normalX, normalY, normalZ);
|
normal.set(normalX, normalY, normalZ);
|
||||||
|
@ -134,8 +132,8 @@ public class SuperByteBuffer extends TemplateBuffer {
|
||||||
builder.color(colorR, colorG, colorB, a);
|
builder.color(colorR, colorG, colorB, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
float u = getU(buffer, i);
|
float u = template.getU(i);
|
||||||
float v = getV(buffer, i);
|
float v = template.getV(i);
|
||||||
|
|
||||||
if (spriteShiftFunc != null) {
|
if (spriteShiftFunc != null) {
|
||||||
spriteShiftFunc.shift(builder, u, v);
|
spriteShiftFunc.shift(builder, u, v);
|
||||||
|
@ -157,11 +155,11 @@ public class SuperByteBuffer extends TemplateBuffer {
|
||||||
} else if (hasDefaultLight) {
|
} else if (hasDefaultLight) {
|
||||||
light = packedLightCoords;
|
light = packedLightCoords;
|
||||||
} else {
|
} else {
|
||||||
light = getLight(buffer, i);
|
light = template.getLight(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hybridLight) {
|
if (hybridLight) {
|
||||||
builder.light(maxLight(light, getLight(buffer, i)));
|
builder.light(maxLight(light, template.getLight(i)));
|
||||||
} else {
|
} else {
|
||||||
builder.light(light);
|
builder.light(light);
|
||||||
}
|
}
|
||||||
|
@ -333,7 +331,7 @@ public class SuperByteBuffer extends TemplateBuffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
return ((Buffer) template).limit() == 0;
|
return template.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
|
|
|
@ -1,101 +0,0 @@
|
||||||
package com.simibubi.create.foundation.render;
|
|
||||||
|
|
||||||
import java.nio.Buffer;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.ByteOrder;
|
|
||||||
|
|
||||||
import com.mojang.datafixers.util.Pair;
|
|
||||||
|
|
||||||
import net.minecraft.client.renderer.BufferBuilder;
|
|
||||||
|
|
||||||
public class TemplateBuffer {
|
|
||||||
protected ByteBuffer template;
|
|
||||||
protected int formatSize;
|
|
||||||
protected int vertexCount;
|
|
||||||
|
|
||||||
public TemplateBuffer() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public TemplateBuffer(BufferBuilder buf) {
|
|
||||||
Pair<BufferBuilder.DrawState, ByteBuffer> state = buf.popData();
|
|
||||||
ByteBuffer rendered = state.getSecond();
|
|
||||||
rendered.order(ByteOrder.nativeOrder()); // Vanilla bug, endianness does not carry over into sliced buffers
|
|
||||||
|
|
||||||
formatSize = buf.getVertexFormat()
|
|
||||||
.getSize();
|
|
||||||
vertexCount = state.getFirst()
|
|
||||||
.getCount();
|
|
||||||
int size = vertexCount * formatSize;
|
|
||||||
|
|
||||||
template = ByteBuffer.allocate(size);
|
|
||||||
template.order(rendered.order());
|
|
||||||
((Buffer) template).limit(((Buffer) rendered).limit());
|
|
||||||
template.put(rendered);
|
|
||||||
((Buffer) template).rewind();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isEmpty() {
|
|
||||||
return ((Buffer) template).limit() == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected int vertexCount(ByteBuffer buffer) {
|
|
||||||
return ((Buffer) buffer).limit() / formatSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected int getBufferPosition(int vertexIndex) {
|
|
||||||
return vertexIndex * formatSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected float getX(ByteBuffer buffer, int index) {
|
|
||||||
return buffer.getFloat(getBufferPosition(index));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected float getY(ByteBuffer buffer, int index) {
|
|
||||||
return buffer.getFloat(getBufferPosition(index) + 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected float getZ(ByteBuffer buffer, int index) {
|
|
||||||
return buffer.getFloat(getBufferPosition(index) + 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected byte getR(ByteBuffer buffer, int index) {
|
|
||||||
return buffer.get(getBufferPosition(index) + 12);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected byte getG(ByteBuffer buffer, int index) {
|
|
||||||
return buffer.get(getBufferPosition(index) + 13);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected byte getB(ByteBuffer buffer, int index) {
|
|
||||||
return buffer.get(getBufferPosition(index) + 14);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected byte getA(ByteBuffer buffer, int index) {
|
|
||||||
return buffer.get(getBufferPosition(index) + 15);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected float getU(ByteBuffer buffer, int index) {
|
|
||||||
return buffer.getFloat(getBufferPosition(index) + 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected float getV(ByteBuffer buffer, int index) {
|
|
||||||
return buffer.getFloat(getBufferPosition(index) + 20);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected int getLight(ByteBuffer buffer, int index) {
|
|
||||||
return buffer.getInt(getBufferPosition(index) + 24);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected byte getNX(ByteBuffer buffer, int index) {
|
|
||||||
return buffer.get(getBufferPosition(index) + 28);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected byte getNY(ByteBuffer buffer, int index) {
|
|
||||||
return buffer.get(getBufferPosition(index) + 29);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected byte getNZ(ByteBuffer buffer, int index) {
|
|
||||||
return buffer.get(getBufferPosition(index) + 30);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -9,11 +9,10 @@ import org.lwjgl.opengl.GL20;
|
||||||
import org.lwjgl.opengl.GL30;
|
import org.lwjgl.opengl.GL30;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.Backend;
|
import com.jozufozu.flywheel.backend.Backend;
|
||||||
import com.jozufozu.flywheel.backend.gl.GlBuffer;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.GlBufferType;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.GlPrimitiveType;
|
import com.jozufozu.flywheel.backend.gl.GlPrimitiveType;
|
||||||
import com.jozufozu.flywheel.backend.gl.GlVertexArray;
|
import com.jozufozu.flywheel.backend.gl.GlVertexArray;
|
||||||
import com.jozufozu.flywheel.backend.gl.MappedBufferRange;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||||
import com.jozufozu.flywheel.util.RenderUtil;
|
import com.jozufozu.flywheel.util.RenderUtil;
|
||||||
import com.simibubi.create.foundation.render.AllProgramSpecs;
|
import com.simibubi.create.foundation.render.AllProgramSpecs;
|
||||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||||
|
@ -67,9 +66,9 @@ public class EffectsHandler {
|
||||||
private static final int bufferSize = vertices.length * 4;
|
private static final int bufferSize = vertices.length * 4;
|
||||||
|
|
||||||
private final Framebuffer framebuffer;
|
private final Framebuffer framebuffer;
|
||||||
private final GlVertexArray vao = new GlVertexArray();
|
private final GlVertexArray vao;
|
||||||
|
|
||||||
private final GlBuffer vbo = new GlBuffer(GlBufferType.ARRAY_BUFFER);
|
private final GlBuffer vbo;
|
||||||
|
|
||||||
private final ArrayList<FilterSphere> spheres;
|
private final ArrayList<FilterSphere> spheres;
|
||||||
|
|
||||||
|
@ -79,12 +78,14 @@ public class EffectsHandler {
|
||||||
Framebuffer render = Minecraft.getInstance().getFramebuffer();
|
Framebuffer render = Minecraft.getInstance().getFramebuffer();
|
||||||
framebuffer = new Framebuffer(render.framebufferWidth, render.framebufferHeight, false, Minecraft.IS_RUNNING_ON_MAC);
|
framebuffer = new Framebuffer(render.framebufferWidth, render.framebufferHeight, false, Minecraft.IS_RUNNING_ON_MAC);
|
||||||
|
|
||||||
|
vbo = new GlBuffer(GlBufferType.ARRAY_BUFFER);
|
||||||
vbo.bind();
|
vbo.bind();
|
||||||
vbo.alloc(bufferSize);
|
vbo.alloc(bufferSize);
|
||||||
MappedBufferRange buffer = vbo.getBuffer(0, bufferSize);
|
vbo.getBuffer(0, bufferSize)
|
||||||
buffer.putFloatArray(vertices);
|
.putFloatArray(vertices)
|
||||||
buffer.unmap();
|
.flush();
|
||||||
|
|
||||||
|
vao = new GlVertexArray();
|
||||||
vao.bind();
|
vao.bind();
|
||||||
|
|
||||||
GL20.glEnableVertexAttribArray(0);
|
GL20.glEnableVertexAttribArray(0);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package com.simibubi.create.foundation.render.effects;
|
package com.simibubi.create.foundation.render.effects;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.gl.MappedBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
||||||
import com.jozufozu.flywheel.util.RenderUtil;
|
import com.jozufozu.flywheel.util.RenderUtil;
|
||||||
|
|
||||||
import net.minecraft.util.math.vector.Matrix4f;
|
import net.minecraft.util.math.vector.Matrix4f;
|
||||||
|
|
|
@ -5,9 +5,9 @@ import java.util.ArrayList;
|
||||||
import org.lwjgl.opengl.GL20;
|
import org.lwjgl.opengl.GL20;
|
||||||
import org.lwjgl.opengl.GL31;
|
import org.lwjgl.opengl.GL31;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.gl.GlBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
||||||
import com.jozufozu.flywheel.backend.gl.GlBufferType;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||||
import com.jozufozu.flywheel.backend.gl.MappedBufferRange;
|
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
||||||
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
|
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
|
||||||
|
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
@ -81,13 +81,13 @@ public class SphereFilterProgram extends GlProgram {
|
||||||
|
|
||||||
public void uploadFilters(ArrayList<FilterSphere> filters) {
|
public void uploadFilters(ArrayList<FilterSphere> filters) {
|
||||||
effectsUBO.bind(GlBufferType.ARRAY_BUFFER);
|
effectsUBO.bind(GlBufferType.ARRAY_BUFFER);
|
||||||
MappedBufferRange buffer = effectsUBO.getBuffer(0, BUFFER_SIZE);
|
MappedBuffer buffer = effectsUBO.getBuffer(0, BUFFER_SIZE)
|
||||||
buffer.putInt(filters.size())
|
.putInt(filters.size())
|
||||||
.position(16);
|
.position(16);
|
||||||
|
|
||||||
filters.forEach(it -> it.write(buffer));
|
filters.forEach(it -> it.write(buffer));
|
||||||
|
|
||||||
buffer.unmap();
|
buffer.flush();
|
||||||
|
|
||||||
effectsUBO.unbind(GlBufferType.ARRAY_BUFFER);
|
effectsUBO.unbind(GlBufferType.ARRAY_BUFFER);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue