Refactor InstancedModel to not rely on inheritance

- Instead, MaterialSpecs store the information
 - RenderMaterials are now generic on InstanceData instead of InstancedModel
 - RenderMaterials are directly constructed with and store a MaterialSpec
This commit is contained in:
JozsefA 2021-05-15 16:41:56 -07:00
parent 79977aee14
commit 9ff193946c
35 changed files with 195 additions and 379 deletions

View File

@ -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.versioned.GlCompat;
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.util.WorldAttached;
import com.simibubi.create.content.contraptions.KineticDebugger;
import com.simibubi.create.foundation.config.AllConfigs;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
@ -131,7 +130,7 @@ public class Backend {
/**
* 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;
if (materialRegistry.containsKey(name)) {
throw new IllegalStateException("Material spec '" + name + "' already registered.");
@ -275,14 +274,6 @@ public class Backend {
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() {
return materialRegistry.values();
}

View File

@ -13,16 +13,45 @@ import net.minecraft.client.renderer.BufferBuilder;
public abstract class BufferedModel extends TemplateBuffer {
protected final VertexFormat modelFormat;
protected GlBuffer modelVBO;
protected boolean removed;
private boolean initialized; // lazy init
private boolean removed;
protected BufferedModel(BufferBuilder buf) {
protected BufferedModel(VertexFormat modelFormat, BufferBuilder buf) {
super(buf);
if (vertexCount > 0) init();
this.modelFormat = modelFormat;
}
/**
* 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();
@ -31,7 +60,7 @@ public abstract class BufferedModel extends TemplateBuffer {
}
protected void initModel() {
int stride = getModelFormat().getStride();
int stride = modelFormat.getStride();
int invariantSize = vertexCount * stride;
// allocate the buffer on the gpu
@ -47,40 +76,17 @@ public abstract class BufferedModel extends TemplateBuffer {
protected abstract void copyVertex(MappedBuffer to, int index);
protected abstract VertexFormat getModelFormat();
protected int getTotalShaderAttributeCount() {
return getModelFormat().getShaderAttributeCount();
return modelFormat.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);
}
modelFormat.vertexAttribPointers(0);
}
protected void deleteInternal() {

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -20,6 +20,9 @@ public abstract class MappedBuffer implements AutoCloseable {
protected abstract void checkAndMap();
/**
* Make the changes in client memory available to the GPU.
*/
public void flush() {
if (mapped) {
GL15.glUnmapBuffer(owner.type.glEnum);
@ -51,7 +54,6 @@ public abstract class MappedBuffer implements AutoCloseable {
/**
* Position this buffer relative to the 0-index in GPU memory.
*
* @param p
* @return This buffer.
*/
public MappedBuffer position(int p) {

View File

@ -0,0 +1,5 @@
package com.jozufozu.flywheel.backend.instancing;
public interface InstanceFactory<D extends InstanceData> {
D create(InstancedModel<? super D> owner);
}

View File

@ -17,11 +17,13 @@ import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
import net.minecraft.client.renderer.BufferBuilder;
public abstract class InstancedModel<D extends InstanceData> extends BufferedModel {
public class InstancedModel<D extends InstanceData> extends BufferedModel {
public static final VertexFormat FORMAT = VertexFormat.builder().addAttributes(ModelAttributes.class).build();
public final InstancedTileRenderer<?> renderer;
protected final VertexFormat instanceFormat;
protected final InstanceFactory<D> factory;
protected GlVertexArray vao;
protected GlBuffer instanceVBO;
protected int glBufferSize = -1;
@ -32,11 +34,22 @@ public abstract class InstancedModel<D extends InstanceData> extends BufferedMod
boolean anyToRemove;
boolean anyToUpdate;
public InstancedModel(InstancedTileRenderer<?> renderer, BufferBuilder buf) {
super(buf);
public InstancedModel(InstancedTileRenderer<?> renderer, VertexFormat instanceFormat, InstanceFactory<D> factory, BufferBuilder buf) {
super(FORMAT, buf);
this.factory = factory;
this.instanceFormat = instanceFormat;
this.renderer = renderer;
}
public synchronized D createInstance() {
D instanceData = factory.create(this);
instanceData.dirty = true;
anyToUpdate = true;
data.add(instanceData);
return instanceData;
}
@Override
protected void init() {
vao = new GlVertexArray();
@ -53,14 +66,6 @@ public abstract class InstancedModel<D extends InstanceData> extends BufferedMod
setupAttributes();
}
public int instanceCount() {
return data.size();
}
public boolean isEmpty() {
return instanceCount() == 0;
}
protected void deleteInternal() {
super.deleteInternal();
@ -68,23 +73,13 @@ public abstract class InstancedModel<D extends InstanceData> extends BufferedMod
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() {
vao.bind();
renderSetup();
if (glInstanceCount > 0)
Backend.compat.drawInstanced.drawArraysInstanced(GL11.GL_QUADS, 0, vertexCount, glInstanceCount);
vao.unbind();
}
@ -115,22 +110,22 @@ public abstract class InstancedModel<D extends InstanceData> extends BufferedMod
}
private void informAttribDivisors() {
int staticAttributes = getModelFormat().getShaderAttributeCount();
getInstanceFormat().vertexAttribPointers(staticAttributes);
int staticAttributes = modelFormat.getShaderAttributeCount();
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);
}
}
private void clearBufferTail() {
int size = data.size();
final int offset = size * getInstanceFormat().getStride();
final int offset = size * instanceFormat.getStride();
final int length = glBufferSize - offset;
if (length > 0) {
MappedBuffer buffer = instanceVBO.getBuffer(offset, length);
buffer.putByteArray(new byte[length]);
buffer.flush();
instanceVBO.getBuffer(offset, length)
.putByteArray(new byte[length])
.flush();
}
}
@ -139,7 +134,7 @@ public abstract class InstancedModel<D extends InstanceData> extends BufferedMod
if (size <= 0) return;
final int stride = getInstanceFormat().getStride();
final int stride = instanceFormat.getStride();
final BitSet dirtySet = getDirtyBitSet();
if (dirtySet.isEmpty()) return;
@ -180,7 +175,7 @@ public abstract class InstancedModel<D extends InstanceData> extends BufferedMod
private boolean realloc() {
int size = this.data.size();
int stride = getInstanceFormat().getStride();
int stride = instanceFormat.getStride();
int requiredSize = size * stride;
if (requiredSize > glBufferSize) {
glBufferSize = requiredSize + stride * 16;
@ -199,9 +194,7 @@ public abstract class InstancedModel<D extends InstanceData> extends BufferedMod
}
private void removeDeletedInstances() {
// figure out which elements are to be removed
// any exception thrown from the filter predicate at this stage
// will leave the collection unmodified
// Figure out which elements are to be removed.
final int oldSize = this.data.size();
int removeCount = 0;
final BitSet removeSet = new BitSet(oldSize);
@ -246,14 +239,7 @@ public abstract class InstancedModel<D extends InstanceData> extends BufferedMod
constant.putFloat(getV(template, i));
}
@Override
protected VertexFormat getModelFormat() {
return FORMAT;
}
protected abstract VertexFormat getInstanceFormat();
protected int getTotalShaderAttributeCount() {
return getInstanceFormat().getShaderAttributeCount() + super.getTotalShaderAttributeCount();
return instanceFormat.getShaderAttributeCount() + super.getTotalShaderAttributeCount();
}
}

View File

@ -46,7 +46,7 @@ public abstract class InstancedTileRenderer<P extends BasicProgram> {
materials = new HashMap<>();
for (MaterialSpec<?> spec : Backend.allMaterials()) {
materials.put(spec, spec.create(this));
materials.put(spec, new RenderMaterial<>(this, spec));
}
queuedUpdates = ConcurrentHashMap.newKeySet(64);
@ -137,15 +137,15 @@ public abstract class InstancedTileRenderer<P extends BasicProgram> {
}
@SuppressWarnings("unchecked")
public <M extends InstancedModel<?>> RenderMaterial<P, M> getMaterial(MaterialSpec<M> materialType) {
return (RenderMaterial<P, M>) materials.get(materialType);
public <D extends InstanceData> RenderMaterial<P, D> getMaterial(MaterialSpec<D> materialType) {
return (RenderMaterial<P, D>) materials.get(materialType);
}
public RenderMaterial<P, InstancedModel<ModelData>> getTransformMaterial() {
public RenderMaterial<P, ModelData> getTransformMaterial() {
return getMaterial(AllMaterialSpecs.TRANSFORMED);
}
public RenderMaterial<P, InstancedModel<OrientedData>> getOrientedMaterial() {
public RenderMaterial<P, OrientedData> getOrientedMaterial() {
return getMaterial(AllMaterialSpecs.ORIENTED);
}

View File

@ -1,32 +1,35 @@
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 net.minecraft.util.ResourceLocation;
public class MaterialSpec<M extends InstancedModel<?>> {
public class MaterialSpec<D extends InstanceData> {
public final ResourceLocation name;
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.programSpec = programSpec;
this.modelFactory = modelFactory;
this.instanceFormat = instanceFormat;
this.instanceFactory = instanceFactory;
}
public ProgramSpec getProgramSpec() {
return programSpec;
}
public ModelFactory<M> getModelFactory() {
return modelFactory;
public VertexFormat getInstanceFormat() {
return instanceFormat;
}
public <P extends BasicProgram> RenderMaterial<P, M> create(InstancedTileRenderer<P> renderer) {
return new RenderMaterial<>(renderer, programSpec, modelFactory);
public InstanceFactory<D> getInstanceFactory() {
return instanceFactory;
}
}

View File

@ -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);
}

View File

@ -3,7 +3,6 @@ package com.jozufozu.flywheel.backend.instancing;
import java.util.Arrays;
import java.util.concurrent.ExecutionException;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.Supplier;
import org.apache.commons.lang3.tuple.Pair;
@ -13,7 +12,6 @@ import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.jozufozu.flywheel.backend.core.BasicProgram;
import com.jozufozu.flywheel.backend.core.PartialModel;
import com.jozufozu.flywheel.backend.gl.shader.ProgramSpec;
import com.jozufozu.flywheel.backend.gl.shader.ShaderCallback;
import com.jozufozu.flywheel.util.RenderUtil;
import com.jozufozu.flywheel.util.VirtualEmptyModelData;
@ -32,33 +30,19 @@ import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
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> {
protected final InstancedTileRenderer<P> renderer;
protected final Cache<Object, MODEL> models;
protected final ModelFactory<MODEL> factory;
protected final ProgramSpec programSpec;
protected final Predicate<RenderType> layerPredicate;
protected final Cache<Object, InstancedModel<D>> models;
protected final 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) {
public RenderMaterial(InstancedTileRenderer<P> renderer, MaterialSpec<D> spec) {
this.renderer = renderer;
this.spec = spec;
this.models = CacheBuilder.newBuilder()
.removalListener(notification -> ((InstancedModel<?>) notification.getValue()).delete())
.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) {
@ -66,9 +50,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) {
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.uploadViewProjection(viewProjection);
program.uploadCameraPos(camX, camY, camZ);
@ -87,30 +71,30 @@ public class RenderMaterial<P extends BasicProgram, MODEL extends InstancedModel
runOnAll(InstancedModel::render);
}
public void runOnAll(Consumer<MODEL> f) {
for (MODEL model : models.asMap().values()) {
public void runOnAll(Consumer<InstancedModel<D>> f) {
for (InstancedModel<D> model : models.asMap().values()) {
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));
}
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));
}
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),
() -> buildModel(partial.get(), referenceState, modelTransform.get()));
}
public MODEL getModel(BlockState toRender) {
public InstancedModel<D> getModel(BlockState 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 {
return models.get(key, supplier::get);
} catch (ExecutionException e) {
@ -119,19 +103,19 @@ 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();
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());
}
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);
return factory.makeModel(renderer, builder);
return new InstancedModel<>(renderer, spec.getInstanceFormat(), spec.getInstanceFactory(), builder);
}
private static final Direction[] dirs;

View File

@ -117,11 +117,11 @@ public abstract class TileEntityInstance<T extends TileEntity> implements IInsta
models.forEach(model -> model.setBlockLight(block).setSkyLight(sky));
}
protected RenderMaterial<?, InstancedModel<ModelData>> getTransformMaterial() {
protected RenderMaterial<?, ModelData> getTransformMaterial() {
return renderer.getTransformMaterial();
}
protected RenderMaterial<?, InstancedModel<OrientedData>> getOrientedMaterial() {
protected RenderMaterial<?, OrientedData> getOrientedMaterial() {
return renderer.getOrientedMaterial();
}
}

View File

@ -1,6 +1,5 @@
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.RenderMaterial;
import com.jozufozu.flywheel.backend.instancing.TileEntityInstance;
@ -85,9 +84,9 @@ public abstract class KineticTileInstance<T extends KineticTileEntity> extends T
return shaft(getRotationAxis());
}
protected final RenderMaterial<?, InstancedModel<RotatingData>> getRotatingMaterial() {
protected final RenderMaterial<?, RotatingData> getRotatingMaterial() {
return renderer.getMaterial(AllMaterialSpecs.ROTATING);
}
}
public static BlockState shaft(Direction.Axis axis) {
return AllBlocks.SHAFT.getDefaultState()

View File

@ -11,9 +11,9 @@ public class RotatingData extends KineticData {
private byte rotationAxisY;
private byte rotationAxisZ;
protected RotatingData(InstancedModel<?> owner) {
super(owner);
}
public RotatingData(InstancedModel<?> owner) {
super(owner);
}
public RotatingData setRotationAxis(Direction.Axis axis) {
Direction orientation = Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, axis);

View File

@ -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;
}
}

View File

@ -28,9 +28,9 @@ public class ActorData extends InstanceData {
private float speed;
protected ActorData(InstancedModel<?> owner) {
super(owner);
}
public ActorData(InstancedModel<?> owner) {
super(owner);
}
public ActorData setPosition(BlockPos pos) {

View File

@ -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);
}
}

View File

@ -1,6 +1,5 @@
package com.simibubi.create.content.contraptions.components.actors;
import com.jozufozu.flywheel.backend.instancing.InstancedModel;
import com.jozufozu.flywheel.backend.instancing.RenderMaterial;
import com.simibubi.create.AllBlockPartials;
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
@ -21,7 +20,7 @@ public class DrillActorInstance extends ActorInstance {
public DrillActorInstance(ContraptionKineticRenderer modelManager, MovementContext context) {
super(modelManager, context);
RenderMaterial<?, InstancedModel<ActorData>> renderMaterial = modelManager.getActorMaterial();
RenderMaterial<?, ActorData> renderMaterial = modelManager.getActorMaterial();
BlockState state = context.state;

View File

@ -3,7 +3,6 @@ package com.simibubi.create.content.contraptions.components.actors;
import static net.minecraft.state.properties.BlockStateProperties.HORIZONTAL_FACING;
import com.jozufozu.flywheel.backend.core.materials.ModelData;
import com.jozufozu.flywheel.backend.instancing.InstancedModel;
import com.jozufozu.flywheel.backend.instancing.RenderMaterial;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.AllBlockPartials;
@ -36,7 +35,7 @@ public class HarvesterActorInstance extends ActorInstance {
public HarvesterActorInstance(ContraptionKineticRenderer modelManager, MovementContext context) {
super(modelManager, context);
RenderMaterial<?, InstancedModel<ModelData>> renderMaterial = modelManager.getTransformMaterial();
RenderMaterial<?, ModelData> renderMaterial = modelManager.getTransformMaterial();
BlockState state = context.state;

View File

@ -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.materials.ModelData;
import com.jozufozu.flywheel.backend.instancing.InstancedModel;
import com.jozufozu.flywheel.backend.instancing.RenderMaterial;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.AllBlockPartials;
@ -45,7 +44,7 @@ public class DeployerActorInstance extends ActorInstance {
public DeployerActorInstance(ContraptionKineticRenderer modelManager, MovementContext context) {
super(modelManager, context);
RenderMaterial<ContraptionProgram, InstancedModel<ModelData>> mat = modelManager.getTransformMaterial();
RenderMaterial<ContraptionProgram, ModelData> mat = modelManager.getTransformMaterial();
BlockState state = context.state;
DeployerTileEntity.Mode mode = NBTHelper.readEnum(context.tileData, "Mode", DeployerTileEntity.Mode.class);

View File

@ -63,15 +63,15 @@ public class FlyWheelInstance extends KineticTileInstance<FlywheelTileEntity> im
connectorAngleMult = flipAngle ? -1 : 1;
RenderMaterial<?, InstancedModel<ModelData>> mat = getTransformMaterial();
RenderMaterial<?, ModelData> mat = getTransformMaterial();
upperRotating = mat.getModel(AllBlockPartials.FLYWHEEL_UPPER_ROTATING, blockState).createInstance();
lowerRotating = mat.getModel(AllBlockPartials.FLYWHEEL_LOWER_ROTATING, blockState).createInstance();
upperSliding = mat.getModel(AllBlockPartials.FLYWHEEL_UPPER_SLIDING, blockState).createInstance();
lowerSliding = mat.getModel(AllBlockPartials.FLYWHEEL_LOWER_SLIDING, blockState).createInstance();
upperRotating = mat.getModel(AllBlockPartials.FLYWHEEL_UPPER_ROTATING, blockState).createInstance();
lowerRotating = mat.getModel(AllBlockPartials.FLYWHEEL_LOWER_ROTATING, blockState).createInstance();
upperSliding = mat.getModel(AllBlockPartials.FLYWHEEL_UPPER_SLIDING, blockState).createInstance();
lowerSliding = mat.getModel(AllBlockPartials.FLYWHEEL_LOWER_SLIDING, blockState).createInstance();
connectors = Lists.newArrayList(upperRotating, lowerRotating, upperSliding, lowerSliding);
} else {
connectors = Lists.newArrayList(upperRotating, lowerRotating, upperSliding, lowerSliding);
} else {
connectors = Collections.emptyList();
}

View File

@ -7,7 +7,6 @@ import javax.annotation.Nullable;
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.RenderMaterial;
import com.simibubi.create.AllMovementBehaviours;
@ -65,9 +64,9 @@ public class ContraptionKineticRenderer extends InstancedTileRenderer<Contraptio
return null;
}
public RenderMaterial<?, InstancedModel<ActorData>> getActorMaterial() {
public RenderMaterial<?, ActorData> getActorMaterial() {
return getMaterial(AllMaterialSpecs.ACTORS);
}
}
public RenderedContraption getContraption() {
return contraption.get();

View File

@ -21,7 +21,7 @@ public class ContraptionModel extends BufferedModel {
protected GlBuffer ebo;
public ContraptionModel(BufferBuilder buf) {
super(buf);
super(FORMAT, buf);
}
@Override
@ -93,11 +93,6 @@ public class ContraptionModel extends BufferedModel {
to.put(sky);
}
@Override
protected VertexFormat getModelFormat() {
return FORMAT;
}
@Override
protected void deleteInternal() {
super.deleteInternal();

View File

@ -21,9 +21,9 @@ public class BeltData extends KineticData {
private float maxV;
private byte scrollMult;
protected BeltData(InstancedModel<?> owner) {
super(owner);
}
public BeltData(InstancedModel<?> owner) {
super(owner);
}
public BeltData setRotation(Quaternion q) {
this.qX = q.getX();

View File

@ -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;
}
}

View File

@ -26,7 +26,7 @@ public class SplitShaftInstance extends KineticTileInstance<SplitShaftTileEntity
float speed = tile.getSpeed();
RenderMaterial<?, InstancedModel<RotatingData>> rotatingMaterial = getRotatingMaterial();
RenderMaterial<?, RotatingData> rotatingMaterial = getRotatingMaterial();
for (Direction dir : Iterate.directionsInAxis(getRotationAxis())) {

View File

@ -33,7 +33,7 @@ public class GearboxInstance extends KineticTileInstance<GearboxTileEntity> {
int skyLight = world.getLightLevel(LightType.SKY, pos);
updateSourceFacing();
RenderMaterial<?, InstancedModel<RotatingData>> rotatingMaterial = getRotatingMaterial();
RenderMaterial<?, RotatingData> rotatingMaterial = getRotatingMaterial();
for (Direction direction : Iterate.directions) {
final Direction.Axis axis = direction.getAxis();

View File

@ -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;
}
}

View File

@ -47,7 +47,7 @@ public class ArmInstance extends SingleRotatingInstance implements IDynamicInsta
public ArmInstance(InstancedTileRenderer<?> modelManager, ArmTileEntity tile) {
super(modelManager, tile);
RenderMaterial<?, InstancedModel<ModelData>> mat = getTransformMaterial();
RenderMaterial<?, ModelData> mat = getTransformMaterial();
base = mat.getModel(AllBlockPartials.ARM_BASE, blockState).createInstance();
lowerBody = mat.getModel(AllBlockPartials.ARM_LOWER_BODY, blockState).createInstance();

View File

@ -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.instancing.IDynamicInstance;
import com.jozufozu.flywheel.backend.instancing.InstancedModel;
import com.jozufozu.flywheel.backend.instancing.InstancedTileRenderer;
import com.jozufozu.flywheel.backend.instancing.RenderMaterial;
import com.jozufozu.flywheel.backend.instancing.TileEntityInstance;
@ -27,7 +26,7 @@ public class AnalogLeverInstance extends TileEntityInstance<AnalogLeverTileEntit
public AnalogLeverInstance(InstancedTileRenderer<?> modelManager, AnalogLeverTileEntity tile) {
super(modelManager, tile);
RenderMaterial<?, InstancedModel<ModelData>> mat = getTransformMaterial();
RenderMaterial<?, ModelData> mat = getTransformMaterial();
handle = mat.getModel(AllBlockPartials.ANALOG_LEVER_HANDLE, blockState).createInstance();
indicator = mat.getModel(AllBlockPartials.ANALOG_LEVER_INDICATOR, blockState).createInstance();

View File

@ -2,7 +2,6 @@ package com.simibubi.create.content.schematics.block;
import com.jozufozu.flywheel.backend.core.materials.ModelData;
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.RenderMaterial;
import com.jozufozu.flywheel.backend.instancing.TileEntityInstance;
@ -21,7 +20,7 @@ public class SchematicannonInstance extends TileEntityInstance<SchematicannonTil
public SchematicannonInstance(InstancedTileRenderer<?> modelManager, SchematicannonTileEntity tile) {
super(modelManager, tile);
RenderMaterial<?, InstancedModel<ModelData>> mat = getTransformMaterial();
RenderMaterial<?, ModelData> mat = getTransformMaterial();
connector = mat.getModel(AllBlockPartials.SCHEMATICANNON_CONNECTOR, blockState).createInstance();
pipe = mat.getModel(AllBlockPartials.SCHEMATICANNON_PIPE, blockState).createInstance();

View File

@ -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();
}

View File

@ -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.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.simibubi.create.Create;
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.ActorModel;
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.FlapModel;
import net.minecraft.util.ResourceLocation;
@ -25,14 +18,13 @@ public class AllMaterialSpecs {
// 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<InstancedModel<OrientedData>> ORIENTED = register(new MaterialSpec<>(Locations.ORIENTED, AllProgramSpecs.ORIENTED, OrientedModel::new));
public static final MaterialSpec<InstancedModel<RotatingData>> ROTATING = register(new MaterialSpec<>(Locations.ROTATING, AllProgramSpecs.ROTATING, RotatingModel::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 final MaterialSpec<RotatingData> ROTATING = register(new MaterialSpec<>(Locations.ROTATING, AllProgramSpecs.ROTATING, AllInstanceFormats.ROTATING, RotatingData::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<FlapData> FLAPS = register(new MaterialSpec<>(Locations.FLAPS, AllProgramSpecs.FLAPS, AllInstanceFormats.FLAP, FlapData::new));
public static class Locations {
public static final ResourceLocation MODEL = new ResourceLocation("create", "model");

View File

@ -13,7 +13,6 @@ import com.jozufozu.flywheel.backend.gl.GlPrimitiveType;
import com.jozufozu.flywheel.backend.gl.GlVertexArray;
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 com.jozufozu.flywheel.util.RenderUtil;
import com.simibubi.create.foundation.render.AllProgramSpecs;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
@ -67,9 +66,9 @@ public class EffectsHandler {
private static final int bufferSize = vertices.length * 4;
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;
@ -79,12 +78,14 @@ public class EffectsHandler {
Framebuffer render = Minecraft.getInstance().getFramebuffer();
framebuffer = new Framebuffer(render.framebufferWidth, render.framebufferHeight, false, Minecraft.IS_RUNNING_ON_MAC);
vbo = new GlBuffer(GlBufferType.ARRAY_BUFFER);
vbo.bind();
vbo.alloc(bufferSize);
MappedBuffer buffer = vbo.getBuffer(0, bufferSize);
buffer.putFloatArray(vertices);
buffer.flush();
vbo.getBuffer(0, bufferSize)
.putFloatArray(vertices)
.flush();
vao = new GlVertexArray();
vao.bind();
GL20.glEnableVertexAttribArray(0);

View File

@ -81,8 +81,8 @@ public class SphereFilterProgram extends GlProgram {
public void uploadFilters(ArrayList<FilterSphere> filters) {
effectsUBO.bind(GlBufferType.ARRAY_BUFFER);
MappedBuffer buffer = effectsUBO.getBuffer(0, BUFFER_SIZE);
buffer.putInt(filters.size())
MappedBuffer buffer = effectsUBO.getBuffer(0, BUFFER_SIZE)
.putInt(filters.size())
.position(16);
filters.forEach(it -> it.write(buffer));