mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-01-27 21:37:56 +01:00
Merge branch 'dev' into shader-pipeline
# Conflicts: # src/main/java/com/jozufozu/flywheel/backend/ShaderSources.java
This commit is contained in:
commit
88241c2a58
64 changed files with 1396 additions and 623 deletions
|
@ -1,6 +1,6 @@
|
|||
buildscript {
|
||||
repositories {
|
||||
maven { url = 'https://files.minecraftforge.net/maven' }
|
||||
maven { url = 'https://maven.minecraftforge.net' }
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
maven { url = 'https://repo.spongepowered.org/repository/maven-public/' }
|
||||
|
@ -15,6 +15,7 @@ plugins {
|
|||
}
|
||||
|
||||
apply plugin: 'net.minecraftforge.gradle'
|
||||
apply plugin: 'eclipse'
|
||||
apply plugin: 'maven-publish'
|
||||
apply plugin: 'org.spongepowered.mixin'
|
||||
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
org.gradle.jvmargs=-Xmx3G
|
||||
org.gradle.daemon=false
|
||||
# mod version info
|
||||
mod_version=0.1.1
|
||||
mod_version=0.2.0
|
||||
mc_update_version=1.16
|
||||
minecraft_version=1.16.5
|
||||
forge_version=36.0.42
|
||||
mcp_mappings=20200920-mixed-1.16.3
|
||||
forge_version=36.1.66
|
||||
|
||||
# curseforge info
|
||||
projectId=486392
|
||||
curse_type=beta
|
||||
|
||||
# github info
|
||||
github_project=Jozufozu/Flywheel
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
package com.jozufozu.flywheel;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import com.jozufozu.flywheel.config.FlwCommands;
|
||||
import com.jozufozu.flywheel.config.FlwConfig;
|
||||
import com.jozufozu.flywheel.config.FlwPackets;
|
||||
|
@ -18,7 +15,6 @@ import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
|||
public class Flywheel {
|
||||
|
||||
public static final String ID = "flywheel";
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
|
||||
public Flywheel() {
|
||||
FMLJavaModLoadingContext.get()
|
||||
|
|
|
@ -15,7 +15,7 @@ import org.lwjgl.opengl.GLCapabilities;
|
|||
|
||||
import com.jozufozu.flywheel.backend.gl.versioned.GlCompat;
|
||||
import com.jozufozu.flywheel.backend.instancing.InstanceData;
|
||||
import com.jozufozu.flywheel.backend.instancing.MaterialSpec;
|
||||
import com.jozufozu.flywheel.backend.material.MaterialSpec;
|
||||
import com.jozufozu.flywheel.config.FlwConfig;
|
||||
import com.jozufozu.flywheel.core.shader.spec.ProgramSpec;
|
||||
|
||||
|
|
|
@ -28,13 +28,13 @@ import com.google.gson.GsonBuilder;
|
|||
import com.google.gson.JsonElement;
|
||||
import com.jozufozu.flywheel.Flywheel;
|
||||
import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
|
||||
import com.jozufozu.flywheel.core.crumbling.CrumblingRenderer;
|
||||
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
|
||||
import com.jozufozu.flywheel.backend.loading.Shader;
|
||||
import com.jozufozu.flywheel.backend.loading.ShaderLoadingException;
|
||||
import com.jozufozu.flywheel.backend.pipeline.SourceFile;
|
||||
import com.jozufozu.flywheel.backend.pipeline.WorldShaderPipeline;
|
||||
import com.jozufozu.flywheel.core.shader.WorldProgram;
|
||||
import com.jozufozu.flywheel.core.crumbling.CrumblingRenderer;
|
||||
import com.jozufozu.flywheel.core.shader.spec.ProgramSpec;
|
||||
import com.jozufozu.flywheel.event.GatherContextEvent;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
package com.jozufozu.flywheel.backend.gl;
|
||||
|
||||
import static org.lwjgl.opengl.GL13.GL_TEXTURE0;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
|
||||
public enum GlTextureUnit {
|
||||
T0(0),
|
||||
T1(1),
|
||||
T2(2),
|
||||
T3(3),
|
||||
T4(4),
|
||||
T5(5),
|
||||
T6(6),
|
||||
T7(7),
|
||||
T8(8),
|
||||
T9(9),
|
||||
T10(10),
|
||||
T11(11),
|
||||
T12(12),
|
||||
T13(13),
|
||||
T14(14),
|
||||
T15(15),
|
||||
T16(16),
|
||||
T17(17),
|
||||
T18(18),
|
||||
T19(19),
|
||||
T20(20),
|
||||
T21(21),
|
||||
T22(22),
|
||||
T23(23),
|
||||
T24(24),
|
||||
T25(25),
|
||||
T26(26),
|
||||
T27(27),
|
||||
T28(28),
|
||||
T29(29),
|
||||
T30(30),
|
||||
T31(31),
|
||||
|
||||
;
|
||||
|
||||
public final int number;
|
||||
public final int glEnum;
|
||||
|
||||
GlTextureUnit(int unit) {
|
||||
this.number = unit;
|
||||
this.glEnum = GL_TEXTURE0 + unit;
|
||||
}
|
||||
|
||||
public void makeActive() {
|
||||
GlStateManager._activeTexture(glEnum);
|
||||
}
|
||||
}
|
|
@ -89,6 +89,14 @@ public class VecBuffer {
|
|||
return this;
|
||||
}
|
||||
|
||||
public VecBuffer putColor(int r, int g, int b, int a) {
|
||||
internal.put((byte) r);
|
||||
internal.put((byte) g);
|
||||
internal.put((byte) b);
|
||||
internal.put((byte) a);
|
||||
return this;
|
||||
}
|
||||
|
||||
public VecBuffer putVec3(float x, float y, float z) {
|
||||
internal.putFloat(x);
|
||||
internal.putFloat(y);
|
||||
|
|
|
@ -4,7 +4,7 @@ import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
|||
|
||||
public abstract class InstanceData {
|
||||
|
||||
protected final Instancer<?> owner;
|
||||
Instancer<?> owner;
|
||||
|
||||
boolean dirty;
|
||||
boolean removed;
|
||||
|
|
|
@ -8,6 +8,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
import javax.annotation.Nullable;
|
||||
|
||||
import com.jozufozu.flywheel.backend.Backend;
|
||||
import com.jozufozu.flywheel.backend.material.MaterialManager;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||
import net.minecraft.client.renderer.ActiveRenderInfo;
|
||||
|
@ -55,10 +56,11 @@ public abstract class InstanceManager<T> implements MaterialManager.OriginShiftL
|
|||
int cZ = (int) cameraZ;
|
||||
|
||||
if (tickableInstances.size() > 0) {
|
||||
for (ITickableInstance instance : tickableInstances.values()) {
|
||||
tickableInstances.object2ObjectEntrySet().parallelStream().forEach(e -> {
|
||||
ITickableInstance instance = e.getValue();
|
||||
if (!instance.decreaseTickRateWithDistance()) {
|
||||
instance.tick();
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
|
||||
BlockPos pos = instance.getWorldPosition();
|
||||
|
@ -68,7 +70,7 @@ public abstract class InstanceManager<T> implements MaterialManager.OriginShiftL
|
|||
int dZ = pos.getZ() - cZ;
|
||||
|
||||
if ((tick % getUpdateDivisor(dX, dY, dZ)) == 0) instance.tick();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
queuedUpdates.forEach(te -> {
|
||||
|
@ -94,7 +96,8 @@ public abstract class InstanceManager<T> implements MaterialManager.OriginShiftL
|
|||
|
||||
if (dynamicInstances.size() > 0) {
|
||||
dynamicInstances.object2ObjectEntrySet()
|
||||
.fastForEach(e -> {
|
||||
.parallelStream()
|
||||
.forEach(e -> {
|
||||
IDynamicInstance dyn = e.getValue();
|
||||
if (!dyn.decreaseFramerateWithDistance() || shouldFrameUpdate(dyn.getWorldPosition(), lookX, lookY, lookZ, cX, cY, cZ))
|
||||
dyn.beginFrame();
|
||||
|
@ -210,10 +213,14 @@ public abstract class InstanceManager<T> implements MaterialManager.OriginShiftL
|
|||
return (frame % getUpdateDivisor(dX, dY, dZ)) == 0;
|
||||
}
|
||||
|
||||
// 1 followed by the prime numbers
|
||||
private static final int[] divisorSequence = new int[] { 1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31 };
|
||||
protected int getUpdateDivisor(int dX, int dY, int dZ) {
|
||||
int dSq = dX * dX + dY * dY + dZ * dZ;
|
||||
|
||||
return (dSq / 1024) + 1;
|
||||
int i = (dSq / 2048);
|
||||
|
||||
return divisorSequence[Math.min(i, divisorSequence.length - 1)];
|
||||
}
|
||||
|
||||
protected void addInternal(T tile) {
|
||||
|
|
|
@ -1,176 +0,0 @@
|
|||
package com.jozufozu.flywheel.backend.instancing;
|
||||
|
||||
import java.nio.Buffer;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.jozufozu.flywheel.backend.RenderWork;
|
||||
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
||||
import com.jozufozu.flywheel.backend.model.BufferedModel;
|
||||
import com.jozufozu.flywheel.backend.model.IndexedModel;
|
||||
import com.jozufozu.flywheel.core.PartialModel;
|
||||
import com.jozufozu.flywheel.util.BufferBuilderReader;
|
||||
import com.jozufozu.flywheel.util.RenderUtil;
|
||||
import com.jozufozu.flywheel.util.VirtualEmptyModelData;
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.BlockModelRenderer;
|
||||
import net.minecraft.client.renderer.BlockRendererDispatcher;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.model.IBakedModel;
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.vector.Vector3i;
|
||||
|
||||
public class InstanceMaterial<D extends InstanceData> {
|
||||
|
||||
protected final Supplier<Vector3i> originCoordinate;
|
||||
protected final Cache<Object, Instancer<D>> models;
|
||||
protected final MaterialSpec<D> spec;
|
||||
private final VertexFormat modelFormat;
|
||||
|
||||
public InstanceMaterial(Supplier<Vector3i> renderer, MaterialSpec<D> spec) {
|
||||
this.originCoordinate = renderer;
|
||||
this.spec = spec;
|
||||
|
||||
this.models = CacheBuilder.newBuilder()
|
||||
.removalListener(notification -> {
|
||||
Instancer<?> instancer = (Instancer<?>) notification.getValue();
|
||||
RenderWork.enqueue(instancer::delete);
|
||||
})
|
||||
.build();
|
||||
modelFormat = this.spec.getModelFormat();
|
||||
}
|
||||
|
||||
public boolean nothingToRender() {
|
||||
return models.size() > 0 && models.asMap()
|
||||
.values()
|
||||
.stream()
|
||||
.allMatch(Instancer::empty);
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
models.invalidateAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all instance data without freeing resources.
|
||||
*/
|
||||
public void clear() {
|
||||
models.asMap()
|
||||
.values()
|
||||
.forEach(Instancer::clear);
|
||||
}
|
||||
|
||||
public void forEachInstancer(Consumer<Instancer<D>> f) {
|
||||
for (Instancer<D> model : models.asMap()
|
||||
.values()) {
|
||||
f.accept(model);
|
||||
}
|
||||
}
|
||||
|
||||
public Instancer<D> getModel(PartialModel partial, BlockState referenceState) {
|
||||
return get(partial, () -> buildModel(partial.get(), referenceState));
|
||||
}
|
||||
|
||||
public Instancer<D> getModel(PartialModel partial, BlockState referenceState, Direction dir) {
|
||||
return getModel(partial, referenceState, dir, RenderUtil.rotateToFace(dir));
|
||||
}
|
||||
|
||||
public Instancer<D> getModel(PartialModel partial, BlockState referenceState, Direction dir, Supplier<MatrixStack> modelTransform) {
|
||||
return get(Pair.of(dir, partial), () -> buildModel(partial.get(), referenceState, modelTransform.get()));
|
||||
}
|
||||
|
||||
public Instancer<D> getModel(BlockState toRender) {
|
||||
return get(toRender, () -> buildModel(toRender));
|
||||
}
|
||||
|
||||
public Instancer<D> get(Object key, Supplier<BufferedModel> supplier) {
|
||||
try {
|
||||
return models.get(key, () -> new Instancer<>(supplier.get(), originCoordinate, spec));
|
||||
} catch (ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private BufferedModel buildModel(BlockState renderedState) {
|
||||
BlockRendererDispatcher dispatcher = Minecraft.getInstance()
|
||||
.getBlockRenderer();
|
||||
return buildModel(dispatcher.getBlockModel(renderedState), renderedState);
|
||||
}
|
||||
|
||||
private BufferedModel buildModel(IBakedModel model, BlockState renderedState) {
|
||||
return buildModel(model, renderedState, new MatrixStack());
|
||||
}
|
||||
|
||||
private BufferedModel buildModel(IBakedModel model, BlockState referenceState, MatrixStack ms) {
|
||||
BufferBuilderReader reader = new BufferBuilderReader(getBufferBuilder(model, referenceState, ms));
|
||||
|
||||
int vertexCount = reader.getVertexCount();
|
||||
|
||||
ByteBuffer vertices = ByteBuffer.allocate(vertexCount * modelFormat.getStride());
|
||||
vertices.order(ByteOrder.nativeOrder());
|
||||
|
||||
for (int i = 0; i < vertexCount; i++) {
|
||||
vertices.putFloat(reader.getX(i));
|
||||
vertices.putFloat(reader.getY(i));
|
||||
vertices.putFloat(reader.getZ(i));
|
||||
|
||||
vertices.put(reader.getNX(i));
|
||||
vertices.put(reader.getNY(i));
|
||||
vertices.put(reader.getNZ(i));
|
||||
|
||||
vertices.putFloat(reader.getU(i));
|
||||
vertices.putFloat(reader.getV(i));
|
||||
}
|
||||
|
||||
((Buffer) vertices).rewind();
|
||||
|
||||
// return new BufferedModel(GlPrimitive.QUADS, format, vertices, vertexCount);
|
||||
|
||||
return IndexedModel.fromSequentialQuads(modelFormat, vertices, vertexCount);
|
||||
}
|
||||
|
||||
// DOWN, UP, NORTH, SOUTH, WEST, EAST, null
|
||||
private static final Direction[] dirs;
|
||||
|
||||
static {
|
||||
Direction[] directions = Direction.values();
|
||||
|
||||
dirs = Arrays.copyOf(directions, directions.length + 1);
|
||||
}
|
||||
|
||||
public static BufferBuilder getBufferBuilder(IBakedModel model, BlockState referenceState, MatrixStack ms) {
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
BlockRendererDispatcher dispatcher = mc.getBlockRenderer();
|
||||
BlockModelRenderer blockRenderer = dispatcher.getModelRenderer();
|
||||
BufferBuilder builder = new BufferBuilder(512);
|
||||
|
||||
// BakedQuadWrapper quadReader = new BakedQuadWrapper();
|
||||
//
|
||||
// IModelData modelData = model.getModelData(mc.world, BlockPos.ZERO.up(255), referenceState, VirtualEmptyModelData.INSTANCE);
|
||||
// List<BakedQuad> quads = Arrays.stream(dirs)
|
||||
// .flatMap(dir -> model.getQuads(referenceState, dir, mc.world.rand, modelData).stream())
|
||||
// .collect(Collectors.toList());
|
||||
|
||||
builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK);
|
||||
blockRenderer.renderModel(mc.level, model, referenceState, BlockPos.ZERO.above(255), ms, builder, true, mc.level.random, 42, OverlayTexture.NO_OVERLAY, VirtualEmptyModelData.INSTANCE);
|
||||
builder.end();
|
||||
return builder;
|
||||
}
|
||||
|
||||
}
|
|
@ -5,6 +5,8 @@ import javax.annotation.Nonnull;
|
|||
import com.jozufozu.flywheel.backend.Backend;
|
||||
import com.jozufozu.flywheel.backend.instancing.entity.EntityInstanceManager;
|
||||
import com.jozufozu.flywheel.backend.instancing.tile.TileInstanceManager;
|
||||
import com.jozufozu.flywheel.backend.material.MaterialManager;
|
||||
import com.jozufozu.flywheel.backend.state.RenderLayer;
|
||||
import com.jozufozu.flywheel.core.Contexts;
|
||||
import com.jozufozu.flywheel.core.shader.WorldProgram;
|
||||
import com.jozufozu.flywheel.event.BeginFrameEvent;
|
||||
|
@ -28,7 +30,7 @@ import net.minecraftforge.fml.common.Mod;
|
|||
@Mod.EventBusSubscriber(Dist.CLIENT)
|
||||
public class InstancedRenderDispatcher {
|
||||
|
||||
private static final WorldAttached<MaterialManager<WorldProgram>> materialManagers = new WorldAttached<>($ -> new MaterialManager<>(Contexts.WORLD));
|
||||
private static final WorldAttached<MaterialManager<WorldProgram>> materialManagers = new WorldAttached<>($ -> MaterialManager.builder(Contexts.WORLD).build());
|
||||
|
||||
private static final WorldAttached<InstanceManager<Entity>> entityInstanceManager = new WorldAttached<>(world -> new EntityInstanceManager(materialManagers.get(world)));
|
||||
private static final WorldAttached<InstanceManager<TileEntity>> tileInstanceManager = new WorldAttached<>(world -> new TileInstanceManager(materialManagers.get(world)));
|
||||
|
@ -84,10 +86,14 @@ public class InstancedRenderDispatcher {
|
|||
if (!Backend.getInstance()
|
||||
.canUseInstancing(world)) return;
|
||||
|
||||
RenderLayer renderLayer = RenderLayer.fromRenderType(event.type);
|
||||
|
||||
if (renderLayer == null) return;
|
||||
|
||||
event.type.setupRenderState();
|
||||
|
||||
materialManagers.get(world)
|
||||
.render(event.type, event.viewProjection, event.camX, event.camY, event.camZ);
|
||||
.render(renderLayer, event.viewProjection, event.camX, event.camY, event.camZ);
|
||||
|
||||
event.type.clearRenderState();
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import com.jozufozu.flywheel.backend.instancing.entity.EntityInstance;
|
|||
import com.jozufozu.flywheel.backend.instancing.entity.IEntityInstanceFactory;
|
||||
import com.jozufozu.flywheel.backend.instancing.tile.ITileInstanceFactory;
|
||||
import com.jozufozu.flywheel.backend.instancing.tile.TileEntityInstance;
|
||||
import com.jozufozu.flywheel.backend.material.MaterialManager;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Object2BooleanLinkedOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2BooleanMap;
|
||||
|
|
|
@ -11,7 +11,10 @@ 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 com.jozufozu.flywheel.backend.material.MaterialSpec;
|
||||
import com.jozufozu.flywheel.backend.model.BufferedModel;
|
||||
import com.jozufozu.flywheel.core.model.IModel;
|
||||
import com.jozufozu.flywheel.core.model.ModelUtil;
|
||||
import com.jozufozu.flywheel.util.AttribUtil;
|
||||
|
||||
import net.minecraft.util.math.vector.Vector3i;
|
||||
|
@ -20,7 +23,8 @@ public class Instancer<D extends InstanceData> {
|
|||
|
||||
public final Supplier<Vector3i> originCoordinate;
|
||||
|
||||
protected final BufferedModel model;
|
||||
protected final Supplier<IModel> gen;
|
||||
protected BufferedModel model;
|
||||
|
||||
protected final VertexFormat instanceFormat;
|
||||
protected final IInstanceFactory<D> factory;
|
||||
|
@ -29,17 +33,46 @@ public class Instancer<D extends InstanceData> {
|
|||
protected int glBufferSize = -1;
|
||||
protected int glInstanceCount = 0;
|
||||
private boolean deleted;
|
||||
private boolean initialized;
|
||||
|
||||
protected final ArrayList<D> data = new ArrayList<>();
|
||||
|
||||
boolean anyToRemove;
|
||||
boolean anyToUpdate;
|
||||
|
||||
public Instancer(BufferedModel model, Supplier<Vector3i> originCoordinate, MaterialSpec<D> spec) {
|
||||
this.model = model;
|
||||
public Instancer(Supplier<IModel> model, Supplier<Vector3i> originCoordinate, MaterialSpec<D> spec) {
|
||||
this.gen = model;
|
||||
this.factory = spec.getInstanceFactory();
|
||||
this.instanceFormat = spec.getInstanceFormat();
|
||||
this.originCoordinate = originCoordinate;
|
||||
}
|
||||
|
||||
public void render() {
|
||||
if (!isInitialized()) init();
|
||||
if (deleted) return;
|
||||
|
||||
vao.bind();
|
||||
renderSetup();
|
||||
|
||||
if (glInstanceCount > 0) model.drawInstances(glInstanceCount);
|
||||
|
||||
vao.unbind();
|
||||
}
|
||||
|
||||
public D createInstance() {
|
||||
return _add(factory.create(this));
|
||||
}
|
||||
|
||||
public void stealInstance(D inOther) {
|
||||
if (inOther.owner == this) return;
|
||||
|
||||
inOther.owner.anyToRemove = true;
|
||||
_add(inOther);
|
||||
}
|
||||
|
||||
private void init() {
|
||||
model = ModelUtil.getIndexedModel(gen.get());
|
||||
initialized = true;
|
||||
|
||||
if (model.getVertexCount() <= 0)
|
||||
throw new IllegalArgumentException("Refusing to instance a model with no vertices.");
|
||||
|
@ -59,27 +92,11 @@ public class Instancer<D extends InstanceData> {
|
|||
model.clearState();
|
||||
}
|
||||
|
||||
public void render() {
|
||||
if (deleted) return;
|
||||
|
||||
vao.bind();
|
||||
renderSetup();
|
||||
|
||||
if (glInstanceCount > 0) model.drawInstances(glInstanceCount);
|
||||
|
||||
vao.unbind();
|
||||
public boolean isInitialized() {
|
||||
return initialized;
|
||||
}
|
||||
|
||||
public D createInstance() {
|
||||
D instanceData = factory.create(this);
|
||||
instanceData.dirty = true;
|
||||
anyToUpdate = true;
|
||||
data.add(instanceData);
|
||||
|
||||
return instanceData;
|
||||
}
|
||||
|
||||
public boolean empty() {
|
||||
public boolean isEmpty() {
|
||||
return !anyToUpdate && !anyToRemove && glInstanceCount == 0;
|
||||
}
|
||||
|
||||
|
@ -92,17 +109,31 @@ public class Instancer<D extends InstanceData> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Free acquired resources. Attempting to use this after calling delete is undefined behavior.
|
||||
* Free acquired resources. All other Instancer methods are undefined behavior after calling delete.
|
||||
*/
|
||||
public void delete() {
|
||||
if (deleted) return;
|
||||
|
||||
deleted = true;
|
||||
|
||||
model.delete();
|
||||
if (isInitialized()) {
|
||||
model.delete();
|
||||
|
||||
instanceVBO.delete();
|
||||
vao.delete();
|
||||
instanceVBO.delete();
|
||||
vao.delete();
|
||||
}
|
||||
}
|
||||
|
||||
private D _add(D instanceData) {
|
||||
instanceData.owner = this;
|
||||
|
||||
instanceData.dirty = true;
|
||||
anyToUpdate = true;
|
||||
synchronized (data) {
|
||||
data.add(instanceData);
|
||||
}
|
||||
|
||||
return instanceData;
|
||||
}
|
||||
|
||||
protected void renderSetup() {
|
||||
|
@ -215,7 +246,7 @@ public class Instancer<D extends InstanceData> {
|
|||
final BitSet removeSet = new BitSet(oldSize);
|
||||
for (int i = 0; i < oldSize; i++) {
|
||||
final D element = this.data.get(i);
|
||||
if (element.removed) {
|
||||
if (element.removed || element.owner != this) {
|
||||
removeSet.set(i);
|
||||
removeCount++;
|
||||
}
|
||||
|
|
|
@ -1,179 +0,0 @@
|
|||
package com.jozufozu.flywheel.backend.instancing;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.jozufozu.flywheel.backend.Backend;
|
||||
import com.jozufozu.flywheel.core.Materials;
|
||||
import com.jozufozu.flywheel.core.WorldContext;
|
||||
import com.jozufozu.flywheel.core.materials.ModelData;
|
||||
import com.jozufozu.flywheel.core.materials.OrientedData;
|
||||
import com.jozufozu.flywheel.core.shader.IProgramCallback;
|
||||
import com.jozufozu.flywheel.core.shader.WorldProgram;
|
||||
import com.jozufozu.flywheel.util.WeakHashSet;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.ActiveRenderInfo;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.inventory.container.PlayerContainer;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.vector.Matrix4f;
|
||||
import net.minecraft.util.math.vector.Vector3i;
|
||||
|
||||
// TODO: 0.2 block atlas should not be a special case
|
||||
public class MaterialManager<P extends WorldProgram> {
|
||||
|
||||
public static int MAX_ORIGIN_DISTANCE = 100;
|
||||
|
||||
protected final WorldContext<P> context;
|
||||
|
||||
protected final Map<MaterialSpec<?>, InstanceMaterial<?>> atlasMaterials;
|
||||
protected final ArrayList<MaterialRenderer<P>> atlasRenderers;
|
||||
|
||||
protected final Map<ResourceLocation, ArrayList<MaterialRenderer<P>>> renderers;
|
||||
protected final Map<ResourceLocation, Map<MaterialSpec<?>, InstanceMaterial<?>>> materials;
|
||||
|
||||
protected BlockPos originCoordinate = BlockPos.ZERO;
|
||||
|
||||
private final WeakHashSet<OriginShiftListener> listeners;
|
||||
|
||||
public MaterialManager(WorldContext<P> context) {
|
||||
this.context = context;
|
||||
|
||||
this.atlasMaterials = new HashMap<>();
|
||||
this.atlasRenderers = new ArrayList<>(Backend.getInstance()
|
||||
.allMaterials()
|
||||
.size());
|
||||
|
||||
this.materials = new HashMap<>();
|
||||
this.renderers = new HashMap<>();
|
||||
|
||||
this.listeners = new WeakHashSet<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Render every model for every material.
|
||||
*
|
||||
* @param layer Which vanilla {@link RenderType} is being drawn?
|
||||
* @param viewProjection How do we get from camera space to clip space?
|
||||
*/
|
||||
public void render(RenderType layer, Matrix4f viewProjection, double camX, double camY, double camZ) {
|
||||
render(layer, viewProjection, camX, camY, camZ, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render every model for every material.
|
||||
*
|
||||
* @param layer Which vanilla {@link RenderType} is being drawn?
|
||||
* @param viewProjection How do we get from camera space to clip space?
|
||||
* @param callback Provide additional uniforms or state here.
|
||||
*/
|
||||
public void render(RenderType layer, Matrix4f viewProjection, double camX, double camY, double camZ, IProgramCallback<P> callback) {
|
||||
camX -= originCoordinate.getX();
|
||||
camY -= originCoordinate.getY();
|
||||
camZ -= originCoordinate.getZ();
|
||||
|
||||
Matrix4f translate = Matrix4f.createTranslateMatrix((float) -camX, (float) -camY, (float) -camZ);
|
||||
|
||||
translate.multiplyBackward(viewProjection);
|
||||
|
||||
for (MaterialRenderer<P> material : atlasRenderers) {
|
||||
material.render(layer, translate, camX, camY, camZ, callback);
|
||||
}
|
||||
|
||||
for (Map.Entry<ResourceLocation, ArrayList<MaterialRenderer<P>>> entry : renderers.entrySet()) {
|
||||
Minecraft.getInstance().textureManager.bind(entry.getKey());
|
||||
|
||||
for (MaterialRenderer<P> materialRenderer : entry.getValue()) {
|
||||
materialRenderer.render(layer, translate, camX, camY, camZ, callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
atlasMaterials.values()
|
||||
.forEach(InstanceMaterial::delete);
|
||||
materials.values()
|
||||
.stream()
|
||||
.flatMap(m -> m.values()
|
||||
.stream())
|
||||
.forEach(InstanceMaterial::delete);
|
||||
|
||||
atlasMaterials.clear();
|
||||
atlasRenderers.clear();
|
||||
materials.clear();
|
||||
renderers.clear();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <D extends InstanceData> InstanceMaterial<D> getMaterial(MaterialSpec<D> materialType) {
|
||||
return (InstanceMaterial<D>) this.atlasMaterials.computeIfAbsent(materialType, type -> {
|
||||
InstanceMaterial<?> material = new InstanceMaterial<>(this::getOriginCoordinate, type);
|
||||
|
||||
this.atlasRenderers.add(new MaterialRenderer<>(context.getProgramSupplier(type.getProgramName()), material));
|
||||
|
||||
return material;
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <D extends InstanceData> InstanceMaterial<D> getMaterial(MaterialSpec<D> materialType, ResourceLocation texture) {
|
||||
return (InstanceMaterial<D>) materials.computeIfAbsent(texture, $ -> new HashMap<>())
|
||||
.computeIfAbsent(materialType, type -> {
|
||||
InstanceMaterial<?> material = new InstanceMaterial<>(this::getOriginCoordinate, type);
|
||||
|
||||
this.renderers.computeIfAbsent(texture, $ -> new ArrayList<>())
|
||||
.add(new MaterialRenderer<>(context.getProgramSupplier(type.getProgramName()), material));
|
||||
|
||||
return material;
|
||||
});
|
||||
}
|
||||
|
||||
public InstanceMaterial<ModelData> getTransformMaterial() {
|
||||
return getMaterial(Materials.TRANSFORMED);
|
||||
}
|
||||
|
||||
public InstanceMaterial<OrientedData> getOrientedMaterial() {
|
||||
return getMaterial(Materials.ORIENTED);
|
||||
}
|
||||
|
||||
public Vector3i getOriginCoordinate() {
|
||||
return originCoordinate;
|
||||
}
|
||||
|
||||
public void addListener(OriginShiftListener listener) {
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
public void checkAndShiftOrigin(ActiveRenderInfo info) {
|
||||
int cX = MathHelper.floor(info.getPosition().x);
|
||||
int cY = MathHelper.floor(info.getPosition().y);
|
||||
int cZ = MathHelper.floor(info.getPosition().z);
|
||||
|
||||
int dX = cX - originCoordinate.getX();
|
||||
int dY = cY - originCoordinate.getY();
|
||||
int dZ = cZ - originCoordinate.getZ();
|
||||
|
||||
if (Math.abs(dX) > MAX_ORIGIN_DISTANCE || Math.abs(dY) > MAX_ORIGIN_DISTANCE || Math.abs(dZ) > MAX_ORIGIN_DISTANCE) {
|
||||
|
||||
originCoordinate = new BlockPos(cX, cY, cZ);
|
||||
|
||||
materials.values()
|
||||
.stream()
|
||||
.flatMap(m -> m.values()
|
||||
.stream())
|
||||
.forEach(InstanceMaterial::clear);
|
||||
atlasMaterials.values()
|
||||
.forEach(InstanceMaterial::clear);
|
||||
listeners.forEach(OriginShiftListener::onOriginShift);
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface OriginShiftListener {
|
||||
void onOriginShift();
|
||||
}
|
||||
}
|
|
@ -6,9 +6,10 @@ import java.util.stream.Stream;
|
|||
import com.jozufozu.flywheel.backend.instancing.IDynamicInstance;
|
||||
import com.jozufozu.flywheel.backend.instancing.IInstance;
|
||||
import com.jozufozu.flywheel.backend.instancing.ITickableInstance;
|
||||
import com.jozufozu.flywheel.backend.instancing.InstanceMaterial;
|
||||
import com.jozufozu.flywheel.backend.instancing.MaterialManager;
|
||||
import com.jozufozu.flywheel.backend.instancing.tile.TileInstanceManager;
|
||||
import com.jozufozu.flywheel.backend.material.InstanceMaterial;
|
||||
import com.jozufozu.flywheel.backend.material.MaterialManager;
|
||||
import com.jozufozu.flywheel.core.Materials;
|
||||
import com.jozufozu.flywheel.core.materials.IFlatLight;
|
||||
import com.jozufozu.flywheel.core.materials.ModelData;
|
||||
import com.jozufozu.flywheel.core.materials.OrientedData;
|
||||
|
@ -120,11 +121,11 @@ public abstract class EntityInstance<E extends Entity> implements IInstance {
|
|||
}
|
||||
|
||||
protected InstanceMaterial<ModelData> getTransformMaterial() {
|
||||
return materialManager.getTransformMaterial();
|
||||
}
|
||||
return materialManager.defaultSolid().material(Materials.TRANSFORMED);
|
||||
}
|
||||
|
||||
protected InstanceMaterial<OrientedData> getOrientedMaterial() {
|
||||
return materialManager.getOrientedMaterial();
|
||||
return materialManager.defaultSolid().material(Materials.ORIENTED);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import com.jozufozu.flywheel.backend.Backend;
|
|||
import com.jozufozu.flywheel.backend.instancing.IInstance;
|
||||
import com.jozufozu.flywheel.backend.instancing.InstanceManager;
|
||||
import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry;
|
||||
import com.jozufozu.flywheel.backend.instancing.MaterialManager;
|
||||
import com.jozufozu.flywheel.backend.material.MaterialManager;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package com.jozufozu.flywheel.backend.instancing.entity;
|
||||
|
||||
import com.jozufozu.flywheel.backend.instancing.MaterialManager;
|
||||
import com.jozufozu.flywheel.backend.material.MaterialManager;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault
|
||||
package com.jozufozu.flywheel.backend.instancing;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import mcp.MethodsReturnNonnullByDefault;
|
|
@ -1,6 +1,6 @@
|
|||
package com.jozufozu.flywheel.backend.instancing.tile;
|
||||
|
||||
import com.jozufozu.flywheel.backend.instancing.MaterialManager;
|
||||
import com.jozufozu.flywheel.backend.material.MaterialManager;
|
||||
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
|
||||
|
|
|
@ -6,8 +6,9 @@ import java.util.stream.Stream;
|
|||
import com.jozufozu.flywheel.backend.instancing.IDynamicInstance;
|
||||
import com.jozufozu.flywheel.backend.instancing.IInstance;
|
||||
import com.jozufozu.flywheel.backend.instancing.ITickableInstance;
|
||||
import com.jozufozu.flywheel.backend.instancing.InstanceMaterial;
|
||||
import com.jozufozu.flywheel.backend.instancing.MaterialManager;
|
||||
import com.jozufozu.flywheel.backend.material.InstanceMaterial;
|
||||
import com.jozufozu.flywheel.backend.material.MaterialManager;
|
||||
import com.jozufozu.flywheel.core.Materials;
|
||||
import com.jozufozu.flywheel.core.materials.IFlatLight;
|
||||
import com.jozufozu.flywheel.core.materials.ModelData;
|
||||
import com.jozufozu.flywheel.core.materials.OrientedData;
|
||||
|
@ -122,10 +123,10 @@ public abstract class TileEntityInstance<T extends TileEntity> implements IInsta
|
|||
}
|
||||
|
||||
protected InstanceMaterial<ModelData> getTransformMaterial() {
|
||||
return materialManager.getTransformMaterial();
|
||||
}
|
||||
return materialManager.defaultCutout().material(Materials.TRANSFORMED);
|
||||
}
|
||||
|
||||
protected InstanceMaterial<OrientedData> getOrientedMaterial() {
|
||||
return materialManager.getOrientedMaterial();
|
||||
return materialManager.defaultCutout().material(Materials.ORIENTED);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import com.jozufozu.flywheel.backend.Backend;
|
|||
import com.jozufozu.flywheel.backend.instancing.IInstance;
|
||||
import com.jozufozu.flywheel.backend.instancing.InstanceManager;
|
||||
import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry;
|
||||
import com.jozufozu.flywheel.backend.instancing.MaterialManager;
|
||||
import com.jozufozu.flywheel.backend.material.MaterialManager;
|
||||
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
package com.jozufozu.flywheel.backend.material;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.jozufozu.flywheel.backend.RenderWork;
|
||||
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
||||
import com.jozufozu.flywheel.backend.instancing.InstanceData;
|
||||
import com.jozufozu.flywheel.backend.instancing.Instancer;
|
||||
import com.jozufozu.flywheel.core.PartialModel;
|
||||
import com.jozufozu.flywheel.core.model.BlockModel;
|
||||
import com.jozufozu.flywheel.core.model.IModel;
|
||||
import com.jozufozu.flywheel.util.RenderUtil;
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.BlockRendererDispatcher;
|
||||
import net.minecraft.client.renderer.model.IBakedModel;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.vector.Vector3i;
|
||||
|
||||
public class InstanceMaterial<D extends InstanceData> {
|
||||
|
||||
protected final Supplier<Vector3i> originCoordinate;
|
||||
protected final Cache<Object, Instancer<D>> models;
|
||||
protected final MaterialSpec<D> spec;
|
||||
private final VertexFormat modelFormat;
|
||||
|
||||
public InstanceMaterial(Supplier<Vector3i> renderer, MaterialSpec<D> spec) {
|
||||
this.originCoordinate = renderer;
|
||||
this.spec = spec;
|
||||
|
||||
this.models = CacheBuilder.newBuilder()
|
||||
.removalListener(notification -> {
|
||||
Instancer<?> instancer = (Instancer<?>) notification.getValue();
|
||||
RenderWork.enqueue(instancer::delete);
|
||||
})
|
||||
.build();
|
||||
modelFormat = this.spec.getModelFormat();
|
||||
}
|
||||
|
||||
public boolean nothingToRender() {
|
||||
return models.size() > 0 && models.asMap()
|
||||
.values()
|
||||
.stream()
|
||||
.allMatch(Instancer::isEmpty);
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
models.invalidateAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all instance data without freeing resources.
|
||||
*/
|
||||
public void clear() {
|
||||
models.asMap()
|
||||
.values()
|
||||
.forEach(Instancer::clear);
|
||||
}
|
||||
|
||||
public void forEachInstancer(Consumer<Instancer<D>> f) {
|
||||
for (Instancer<D> model : models.asMap()
|
||||
.values()) {
|
||||
f.accept(model);
|
||||
}
|
||||
}
|
||||
|
||||
public Instancer<D> getModel(PartialModel partial, BlockState referenceState) {
|
||||
return model(partial, () -> buildModel(partial.get(), referenceState));
|
||||
}
|
||||
|
||||
public Instancer<D> getModel(PartialModel partial, BlockState referenceState, Direction dir) {
|
||||
return getModel(partial, referenceState, dir, RenderUtil.rotateToFace(dir));
|
||||
}
|
||||
|
||||
public Instancer<D> getModel(PartialModel partial, BlockState referenceState, Direction dir, Supplier<MatrixStack> modelTransform) {
|
||||
return model(Pair.of(dir, partial), () -> buildModel(partial.get(), referenceState, modelTransform.get()));
|
||||
}
|
||||
|
||||
public Instancer<D> getModel(BlockState toRender) {
|
||||
return model(toRender, () -> buildModel(toRender));
|
||||
}
|
||||
|
||||
public Instancer<D> model(Object key, Supplier<IModel> supplier) {
|
||||
try {
|
||||
return models.get(key, () -> new Instancer<>(supplier, originCoordinate, spec));
|
||||
} catch (ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private IModel buildModel(BlockState renderedState) {
|
||||
BlockRendererDispatcher dispatcher = Minecraft.getInstance()
|
||||
.getBlockRenderer();
|
||||
return buildModel(dispatcher.getBlockModel(renderedState), renderedState);
|
||||
}
|
||||
|
||||
private IModel buildModel(IBakedModel model, BlockState renderedState) {
|
||||
return buildModel(model, renderedState, new MatrixStack());
|
||||
}
|
||||
|
||||
private IModel buildModel(IBakedModel model, BlockState referenceState, MatrixStack ms) {
|
||||
|
||||
return new BlockModel(modelFormat, model, referenceState, ms);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package com.jozufozu.flywheel.backend.material;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.jozufozu.flywheel.backend.instancing.InstanceData;
|
||||
import com.jozufozu.flywheel.backend.state.IRenderState;
|
||||
import com.jozufozu.flywheel.core.shader.WorldProgram;
|
||||
|
||||
import net.minecraft.util.math.vector.Matrix4f;
|
||||
|
||||
public class MaterialGroup<P extends WorldProgram> {
|
||||
|
||||
protected final MaterialManager<P> owner;
|
||||
protected final IRenderState state;
|
||||
|
||||
private final ArrayList<MaterialRenderer<P>> renderers = new ArrayList<>();
|
||||
|
||||
private final Map<MaterialSpec<?>, InstanceMaterial<?>> materials = new HashMap<>();
|
||||
|
||||
public MaterialGroup(MaterialManager<P> owner, IRenderState state) {
|
||||
this.owner = owner;
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public void render(Matrix4f viewProjection, double camX, double camY, double camZ) {
|
||||
for (MaterialRenderer<P> renderer : renderers) {
|
||||
renderer.render(viewProjection, camX, camY, camZ);
|
||||
}
|
||||
}
|
||||
|
||||
public void setup(P program) {
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <D extends InstanceData> InstanceMaterial<D> material(MaterialSpec<D> spec) {
|
||||
return (InstanceMaterial<D>) materials.computeIfAbsent(spec, this::createInstanceMaterial);
|
||||
}
|
||||
|
||||
private InstanceMaterial<?> createInstanceMaterial(MaterialSpec<?> type) {
|
||||
InstanceMaterial<?> material = new InstanceMaterial<>(owner::getOriginCoordinate, type);
|
||||
|
||||
this.renderers.add(new MaterialRenderer<>(owner.getProgram(type.getProgramName()), material, this::setup));
|
||||
|
||||
return material;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
materials.values().forEach(InstanceMaterial::clear);
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
materials.values()
|
||||
.forEach(InstanceMaterial::delete);
|
||||
|
||||
materials.clear();
|
||||
renderers.clear();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,216 @@
|
|||
package com.jozufozu.flywheel.backend.material;
|
||||
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.jozufozu.flywheel.backend.instancing.InstanceData;
|
||||
import com.jozufozu.flywheel.backend.state.IRenderState;
|
||||
import com.jozufozu.flywheel.backend.state.RenderLayer;
|
||||
import com.jozufozu.flywheel.backend.state.TextureRenderState;
|
||||
import com.jozufozu.flywheel.core.Materials;
|
||||
import com.jozufozu.flywheel.core.WorldContext;
|
||||
import com.jozufozu.flywheel.core.materials.ModelData;
|
||||
import com.jozufozu.flywheel.core.materials.OrientedData;
|
||||
import com.jozufozu.flywheel.core.shader.WorldProgram;
|
||||
import com.jozufozu.flywheel.util.WeakHashSet;
|
||||
|
||||
import net.minecraft.client.renderer.ActiveRenderInfo;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.inventory.container.PlayerContainer;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.vector.Matrix4f;
|
||||
import net.minecraft.util.math.vector.Vector3i;
|
||||
|
||||
public class MaterialManager<P extends WorldProgram> {
|
||||
|
||||
public static int MAX_ORIGIN_DISTANCE = 100;
|
||||
|
||||
protected BlockPos originCoordinate = BlockPos.ZERO;
|
||||
|
||||
protected final WorldContext<P> context;
|
||||
protected final GroupFactory<P> groupFactory;
|
||||
protected final boolean ignoreOriginCoordinate;
|
||||
|
||||
protected final Map<RenderLayer, Map<IRenderState, MaterialGroup<P>>> layers;
|
||||
|
||||
private final WeakHashSet<OriginShiftListener> listeners;
|
||||
|
||||
public MaterialManager(WorldContext<P> context) {
|
||||
this(context, MaterialGroup::new, false);
|
||||
}
|
||||
|
||||
public static <P extends WorldProgram> Builder<P> builder(WorldContext<P> context) {
|
||||
return new Builder<>(context);
|
||||
}
|
||||
|
||||
public MaterialManager(WorldContext<P> context, GroupFactory<P> groupFactory, boolean ignoreOriginCoordinate) {
|
||||
this.context = context;
|
||||
this.ignoreOriginCoordinate = ignoreOriginCoordinate;
|
||||
|
||||
this.listeners = new WeakHashSet<>();
|
||||
this.groupFactory = groupFactory;
|
||||
|
||||
this.layers = new EnumMap<>(RenderLayer.class);
|
||||
for (RenderLayer value : RenderLayer.values()) {
|
||||
layers.put(value, new HashMap<>());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render every model for every material.
|
||||
* @param layer Which vanilla {@link RenderType} is being drawn?
|
||||
* @param viewProjection How do we get from camera space to clip space?
|
||||
*/
|
||||
public void render(RenderLayer layer, Matrix4f viewProjection, double camX, double camY, double camZ) {
|
||||
if (!ignoreOriginCoordinate) {
|
||||
camX -= originCoordinate.getX();
|
||||
camY -= originCoordinate.getY();
|
||||
camZ -= originCoordinate.getZ();
|
||||
|
||||
Matrix4f translate = Matrix4f.createTranslateMatrix((float) -camX, (float) -camY, (float) -camZ);
|
||||
|
||||
translate.multiplyBackward(viewProjection);
|
||||
|
||||
viewProjection = translate;
|
||||
}
|
||||
|
||||
for (Map.Entry<IRenderState, MaterialGroup<P>> entry : layers.get(layer).entrySet()) {
|
||||
IRenderState state = entry.getKey();
|
||||
MaterialGroup<P> group = entry.getValue();
|
||||
|
||||
state.bind();
|
||||
group.render(viewProjection, camX, camY, camZ);
|
||||
state.unbind();
|
||||
}
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
for (Map<IRenderState, MaterialGroup<P>> groups : layers.values()) {
|
||||
|
||||
groups.values().forEach(MaterialGroup::delete);
|
||||
}
|
||||
}
|
||||
|
||||
public MaterialGroup<P> state(RenderLayer layer, IRenderState state) {
|
||||
return layers.get(layer).computeIfAbsent(state, this::createGroup);
|
||||
}
|
||||
|
||||
public MaterialGroup<P> solid(IRenderState state) {
|
||||
return layers.get(RenderLayer.SOLID).computeIfAbsent(state, this::createGroup);
|
||||
}
|
||||
|
||||
public MaterialGroup<P> cutout(IRenderState state) {
|
||||
return layers.get(RenderLayer.CUTOUT).computeIfAbsent(state, this::createGroup);
|
||||
}
|
||||
|
||||
public MaterialGroup<P> transparent(IRenderState state) {
|
||||
return layers.get(RenderLayer.TRANSPARENT).computeIfAbsent(state, this::createGroup);
|
||||
}
|
||||
|
||||
public MaterialGroup<P> defaultSolid() {
|
||||
return solid(TextureRenderState.get(PlayerContainer.BLOCK_ATLAS));
|
||||
}
|
||||
|
||||
public MaterialGroup<P> defaultCutout() {
|
||||
return cutout(TextureRenderState.get(PlayerContainer.BLOCK_ATLAS));
|
||||
}
|
||||
|
||||
public MaterialGroup<P> defaultTransparent() {
|
||||
return transparent(TextureRenderState.get(PlayerContainer.BLOCK_ATLAS));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public <D extends InstanceData> InstanceMaterial<D> getMaterial(MaterialSpec<D> materialType) {
|
||||
return defaultCutout().material(materialType);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public <D extends InstanceData> InstanceMaterial<D> getMaterial(MaterialSpec<D> materialType, ResourceLocation texture) {
|
||||
return cutout(TextureRenderState.get(texture)).material(materialType);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public InstanceMaterial<ModelData> getTransformMaterial() {
|
||||
return defaultCutout().material(Materials.TRANSFORMED);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public InstanceMaterial<OrientedData> getOrientedMaterial() {
|
||||
return defaultCutout().material(Materials.ORIENTED);
|
||||
}
|
||||
|
||||
public Supplier<P> getProgram(ResourceLocation name) {
|
||||
return context.getProgramSupplier(name);
|
||||
}
|
||||
|
||||
public Vector3i getOriginCoordinate() {
|
||||
return originCoordinate;
|
||||
}
|
||||
|
||||
public void addListener(OriginShiftListener listener) {
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
public void checkAndShiftOrigin(ActiveRenderInfo info) {
|
||||
int cX = MathHelper.floor(info.getPosition().x);
|
||||
int cY = MathHelper.floor(info.getPosition().y);
|
||||
int cZ = MathHelper.floor(info.getPosition().z);
|
||||
|
||||
int dX = cX - originCoordinate.getX();
|
||||
int dY = cY - originCoordinate.getY();
|
||||
int dZ = cZ - originCoordinate.getZ();
|
||||
|
||||
if (Math.abs(dX) > MAX_ORIGIN_DISTANCE || Math.abs(dY) > MAX_ORIGIN_DISTANCE || Math.abs(dZ) > MAX_ORIGIN_DISTANCE) {
|
||||
|
||||
originCoordinate = new BlockPos(cX, cY, cZ);
|
||||
|
||||
for (Map<IRenderState, MaterialGroup<P>> groups : layers.values()) {
|
||||
groups.values().forEach(MaterialGroup::clear);
|
||||
}
|
||||
|
||||
listeners.forEach(OriginShiftListener::onOriginShift);
|
||||
}
|
||||
}
|
||||
|
||||
private MaterialGroup<P> createGroup(IRenderState state) {
|
||||
return groupFactory.create(this, state);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface OriginShiftListener {
|
||||
void onOriginShift();
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface GroupFactory<P extends WorldProgram> {
|
||||
MaterialGroup<P> create(MaterialManager<P> materialManager, IRenderState state);
|
||||
}
|
||||
|
||||
public static class Builder<P extends WorldProgram> {
|
||||
protected final WorldContext<P> context;
|
||||
protected GroupFactory<P> groupFactory = MaterialGroup::new;
|
||||
protected boolean ignoreOriginCoordinate;
|
||||
|
||||
public Builder(WorldContext<P> context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public Builder<P> setGroupFactory(GroupFactory<P> groupFactory) {
|
||||
this.groupFactory = groupFactory;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<P> setIgnoreOriginCoordinate(boolean ignoreOriginCoordinate) {
|
||||
this.ignoreOriginCoordinate = ignoreOriginCoordinate;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MaterialManager<P> build() {
|
||||
return new MaterialManager<>(context, groupFactory, ignoreOriginCoordinate);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,26 +1,27 @@
|
|||
package com.jozufozu.flywheel.backend.instancing;
|
||||
package com.jozufozu.flywheel.backend.material;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.jozufozu.flywheel.core.shader.IProgramCallback;
|
||||
import com.jozufozu.flywheel.backend.instancing.Instancer;
|
||||
import com.jozufozu.flywheel.core.shader.WorldProgram;
|
||||
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.util.math.vector.Matrix4f;
|
||||
|
||||
public class MaterialRenderer<P extends WorldProgram> {
|
||||
|
||||
private final Supplier<P> program;
|
||||
private final InstanceMaterial<?> material;
|
||||
protected final Supplier<P> program;
|
||||
protected final InstanceMaterial<?> material;
|
||||
|
||||
public MaterialRenderer(Supplier<P> programSupplier, InstanceMaterial<?> material) {
|
||||
protected final Consumer<P> setupFunc;
|
||||
|
||||
public MaterialRenderer(Supplier<P> programSupplier, InstanceMaterial<?> material, Consumer<P> setupFunc) {
|
||||
this.program = programSupplier;
|
||||
this.material = material;
|
||||
this.setupFunc = setupFunc;
|
||||
}
|
||||
|
||||
public void render(RenderType layer, Matrix4f viewProjection, double camX, double camY, double camZ, IProgramCallback<P> setup) {
|
||||
if (!(layer == RenderType.cutoutMipped())) return;
|
||||
|
||||
public void render(Matrix4f viewProjection, double camX, double camY, double camZ) {
|
||||
if (material.nothingToRender()) return;
|
||||
|
||||
P program = this.program.get();
|
||||
|
@ -29,12 +30,9 @@ public class MaterialRenderer<P extends WorldProgram> {
|
|||
program.uploadViewProjection(viewProjection);
|
||||
program.uploadCameraPos(camX, camY, camZ);
|
||||
|
||||
if (setup != null) setup.call(program);
|
||||
setupFunc.accept(program);
|
||||
|
||||
makeRenderCalls();
|
||||
}
|
||||
|
||||
protected void makeRenderCalls() {
|
||||
material.forEachInstancer(Instancer::render);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
package com.jozufozu.flywheel.backend.instancing;
|
||||
package com.jozufozu.flywheel.backend.material;
|
||||
|
||||
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
||||
import com.jozufozu.flywheel.backend.instancing.IInstanceFactory;
|
||||
import com.jozufozu.flywheel.backend.instancing.InstanceData;
|
||||
|
||||
import net.minecraft.inventory.container.PlayerContainer;
|
||||
import net.minecraft.util.ResourceLocation;
|
|
@ -0,0 +1,19 @@
|
|||
package com.jozufozu.flywheel.backend.state;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.jozufozu.flywheel.backend.gl.GlTextureUnit;
|
||||
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public interface IRenderState {
|
||||
|
||||
void bind();
|
||||
|
||||
void unbind();
|
||||
|
||||
@Nullable
|
||||
default ResourceLocation getTexture(GlTextureUnit textureUnit) {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package com.jozufozu.flywheel.backend.state;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
|
||||
public class NoCullRenderState implements IRenderState {
|
||||
|
||||
public static final NoCullRenderState INSTANCE = new NoCullRenderState();
|
||||
|
||||
protected NoCullRenderState() { }
|
||||
|
||||
@Override
|
||||
public void bind() {
|
||||
GlStateManager._disableCull();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unbind() {
|
||||
GlStateManager._enableCull();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package com.jozufozu.flywheel.backend.state;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
|
||||
public enum RenderLayer {
|
||||
SOLID,
|
||||
CUTOUT,
|
||||
TRANSPARENT,
|
||||
;
|
||||
|
||||
@Nullable
|
||||
public static RenderLayer fromRenderType(RenderType type) {
|
||||
if (type == RenderType.solid()) {
|
||||
return SOLID;
|
||||
} else if (type == RenderType.cutoutMipped()) {
|
||||
return CUTOUT;
|
||||
} else if (type == RenderType.translucent()) {
|
||||
return TRANSPARENT;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
package com.jozufozu.flywheel.backend.state;
|
||||
|
||||
import java.util.EnumMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.jozufozu.flywheel.backend.gl.GlTextureUnit;
|
||||
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class RenderState implements IRenderState {
|
||||
|
||||
private final Map<GlTextureUnit, ResourceLocation> textures;
|
||||
private final ImmutableList<IRenderState> states;
|
||||
|
||||
public RenderState(Map<GlTextureUnit, ResourceLocation> textures, ImmutableList<IRenderState> states) {
|
||||
this.textures = textures;
|
||||
this.states = states;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bind() {
|
||||
states.forEach(IRenderState::bind);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unbind() {
|
||||
states.forEach(IRenderState::unbind);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public ResourceLocation getTexture(GlTextureUnit textureUnit) {
|
||||
return textures.get(textureUnit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
RenderState that = (RenderState) o;
|
||||
return states.equals(that.states);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(states);
|
||||
}
|
||||
|
||||
public static StateBuilder builder() {
|
||||
return new StateBuilder();
|
||||
}
|
||||
|
||||
public static class StateBuilder {
|
||||
private final ImmutableList.Builder<IRenderState> states = ImmutableList.builder();
|
||||
private final Map<GlTextureUnit, ResourceLocation> textures = new EnumMap<>(GlTextureUnit.class);
|
||||
|
||||
public StateBuilder texture(ResourceLocation name) {
|
||||
return addState(TextureRenderState.get(name));
|
||||
}
|
||||
|
||||
public StateBuilder addState(IRenderState state) {
|
||||
if (state instanceof TextureRenderState) {
|
||||
TextureRenderState tex = (TextureRenderState) state;
|
||||
if (textures.put(tex.unit, tex.location) == null) {
|
||||
states.add(state);
|
||||
}
|
||||
} else {
|
||||
states.add(state);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public RenderState build() {
|
||||
return new RenderState(textures, states.build());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
package com.jozufozu.flywheel.backend.state;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.jozufozu.flywheel.backend.gl.GlTextureUnit;
|
||||
import com.jozufozu.flywheel.util.Pair;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class TextureRenderState implements IRenderState {
|
||||
private static final Map<Pair<GlTextureUnit, ResourceLocation>, TextureRenderState> states = new HashMap<>();
|
||||
|
||||
public final GlTextureUnit unit;
|
||||
public final ResourceLocation location;
|
||||
|
||||
private TextureRenderState(GlTextureUnit unit, ResourceLocation location) {
|
||||
this.unit = unit;
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public static TextureRenderState get(ResourceLocation texture) {
|
||||
return get(GlTextureUnit.T0, texture);
|
||||
}
|
||||
|
||||
public static TextureRenderState get(GlTextureUnit unit, ResourceLocation texture) {
|
||||
return states.computeIfAbsent(Pair.of(unit, texture), p -> new TextureRenderState(p.getFirst(), p.getSecond()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bind() {
|
||||
unit.makeActive();
|
||||
Minecraft.getInstance().textureManager.bind(location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unbind() {
|
||||
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public ResourceLocation getTexture(GlTextureUnit textureUnit) {
|
||||
if (textureUnit == unit) return location;
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
TextureRenderState that = (TextureRenderState) o;
|
||||
return location.equals(that.location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(location);
|
||||
}
|
||||
}
|
|
@ -36,20 +36,20 @@ public enum BooleanConfig {
|
|||
if (player == null || state == null) return;
|
||||
|
||||
if (state == BooleanDirective.DISPLAY) {
|
||||
ITextComponent text = new StringTextComponent("Flywheel Renderer is currently: ").append(boolToText(FlwConfig.get().client.enabled.get()));
|
||||
ITextComponent text = new StringTextComponent("Flywheel renderer is currently: ").append(boolToText(FlwConfig.get().client.enabled.get()));
|
||||
player.displayClientMessage(text, false);
|
||||
return;
|
||||
}
|
||||
|
||||
boolean enabled = state.get();
|
||||
boolean cannotUseER = OptifineHandler.usingShaders() && enabled;
|
||||
boolean cannotUse = OptifineHandler.usingShaders() && enabled;
|
||||
|
||||
FlwConfig.get().client.enabled.set(enabled);
|
||||
|
||||
ITextComponent text = boolToText(FlwConfig.get().client.enabled.get()).append(new StringTextComponent(" Flywheel Renderer").withStyle(TextFormatting.WHITE));
|
||||
ITextComponent error = new StringTextComponent("Flywheel Renderer does not support Optifine Shaders").withStyle(TextFormatting.RED);
|
||||
ITextComponent text = boolToText(FlwConfig.get().client.enabled.get()).append(new StringTextComponent(" Flywheel renderer").withStyle(TextFormatting.WHITE));
|
||||
ITextComponent error = new StringTextComponent("Flywheel renderer does not support Optifine Shaders").withStyle(TextFormatting.RED);
|
||||
|
||||
player.displayClientMessage(cannotUseER ? error : text, false);
|
||||
player.displayClientMessage(cannotUse ? error : text, false);
|
||||
Backend.reloadWorldRenderers();
|
||||
}
|
||||
|
||||
|
@ -59,14 +59,14 @@ public enum BooleanConfig {
|
|||
if (player == null || state == null) return;
|
||||
|
||||
if (state == BooleanDirective.DISPLAY) {
|
||||
ITextComponent text = new StringTextComponent("Normal overlay is currently: ").append(boolToText(FlwConfig.get().client.normalDebug.get()));
|
||||
ITextComponent text = new StringTextComponent("Normal debug mode is currently: ").append(boolToText(FlwConfig.get().client.debugNormals.get()));
|
||||
player.displayClientMessage(text, false);
|
||||
return;
|
||||
}
|
||||
|
||||
FlwConfig.get().client.normalDebug.set(state.get());
|
||||
FlwConfig.get().client.debugNormals.set(state.get());
|
||||
|
||||
ITextComponent text = boolToText(FlwConfig.get().client.normalDebug.get()).append(new StringTextComponent(" Normal Overlay").withStyle(TextFormatting.WHITE));
|
||||
ITextComponent text = boolToText(FlwConfig.get().client.debugNormals.get()).append(new StringTextComponent(" normal debug mode").withStyle(TextFormatting.WHITE));
|
||||
|
||||
player.displayClientMessage(text, false);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,6 @@ public class FlwCommands {
|
|||
|
||||
dispatcher.register(Commands.literal("flywheel")
|
||||
.then(new BooleanConfigCommand("backend", BooleanConfig.ENGINE).register())
|
||||
.then(new BooleanConfigCommand("normalOverlay", BooleanConfig.NORMAL_OVERLAY).register()));
|
||||
.then(new BooleanConfigCommand("debugNormals", BooleanConfig.NORMAL_OVERLAY).register()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,8 +30,8 @@ public class FlwConfig {
|
|||
return client.enabled.get();
|
||||
}
|
||||
|
||||
public boolean normalOverlayEnabled() {
|
||||
return client.normalDebug.get();
|
||||
public boolean debugNormals() {
|
||||
return client.debugNormals.get();
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
|
@ -39,15 +39,15 @@ public class FlwConfig {
|
|||
|
||||
public static class ClientConfig {
|
||||
public final BooleanValue enabled;
|
||||
public final BooleanValue normalDebug;
|
||||
public final BooleanValue debugNormals;
|
||||
|
||||
public ClientConfig(ForgeConfigSpec.Builder builder) {
|
||||
|
||||
enabled = builder.comment("Enable or disable the entire engine")
|
||||
.define("enabled", true);
|
||||
|
||||
normalDebug = builder.comment("Enable or disable a debug overlay that colors pixels by their normal")
|
||||
.define("normalDebug", false);
|
||||
debugNormals = builder.comment("Enable or disable a debug overlay that colors pixels by their normal")
|
||||
.define("debugNormals", false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package com.jozufozu.flywheel.core;
|
||||
|
||||
import com.jozufozu.flywheel.backend.instancing.MaterialSpec;
|
||||
import com.jozufozu.flywheel.backend.material.MaterialSpec;
|
||||
import com.jozufozu.flywheel.core.materials.ModelData;
|
||||
import com.jozufozu.flywheel.core.materials.OrientedData;
|
||||
import com.jozufozu.flywheel.event.GatherContextEvent;
|
||||
|
|
|
@ -14,13 +14,13 @@ import com.jozufozu.flywheel.backend.ResourceUtil;
|
|||
import com.jozufozu.flywheel.backend.ShaderContext;
|
||||
import com.jozufozu.flywheel.backend.ShaderSources;
|
||||
import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
|
||||
import com.jozufozu.flywheel.backend.instancing.MaterialSpec;
|
||||
import com.jozufozu.flywheel.backend.loading.InstancedArraysTemplate;
|
||||
import com.jozufozu.flywheel.backend.loading.Program;
|
||||
import com.jozufozu.flywheel.backend.loading.ProgramTemplate;
|
||||
import com.jozufozu.flywheel.backend.loading.Shader;
|
||||
import com.jozufozu.flywheel.backend.loading.ShaderLoadingException;
|
||||
import com.jozufozu.flywheel.backend.loading.ShaderTransformer;
|
||||
import com.jozufozu.flywheel.backend.material.MaterialSpec;
|
||||
import com.jozufozu.flywheel.core.shader.ExtensibleGlProgram;
|
||||
import com.jozufozu.flywheel.core.shader.GameStateProgram;
|
||||
import com.jozufozu.flywheel.core.shader.WorldProgram;
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
package com.jozufozu.flywheel.core.crumbling;
|
||||
|
||||
import com.jozufozu.flywheel.backend.gl.GlTextureUnit;
|
||||
import com.jozufozu.flywheel.backend.material.MaterialGroup;
|
||||
import com.jozufozu.flywheel.backend.material.MaterialManager;
|
||||
import com.jozufozu.flywheel.backend.state.IRenderState;
|
||||
import com.jozufozu.flywheel.core.atlas.AtlasInfo;
|
||||
import com.jozufozu.flywheel.core.atlas.SheetData;
|
||||
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class CrumblingGroup<P extends CrumblingProgram> extends MaterialGroup<P> {
|
||||
|
||||
private final int width;
|
||||
private final int height;
|
||||
|
||||
public CrumblingGroup(MaterialManager<P> owner, IRenderState state) {
|
||||
super(owner, state);
|
||||
|
||||
ResourceLocation texture = state.getTexture(GlTextureUnit.T0);
|
||||
|
||||
if (texture != null) {
|
||||
SheetData atlasData = AtlasInfo.getAtlasData(texture);
|
||||
|
||||
width = atlasData.width;
|
||||
height = atlasData.height;
|
||||
} else {
|
||||
width = height = 256;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setup(P p) {
|
||||
p.setAtlasSize(width, height);
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
package com.jozufozu.flywheel.core.crumbling;
|
||||
|
||||
import com.jozufozu.flywheel.backend.instancing.MaterialManager;
|
||||
import com.jozufozu.flywheel.backend.instancing.tile.TileInstanceManager;
|
||||
import com.jozufozu.flywheel.backend.material.MaterialManager;
|
||||
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
|
|
|
@ -1,66 +0,0 @@
|
|||
package com.jozufozu.flywheel.core.crumbling;
|
||||
|
||||
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
|
||||
import static org.lwjgl.opengl.GL11.glBindTexture;
|
||||
import static org.lwjgl.opengl.GL13.GL_TEXTURE0;
|
||||
import static org.lwjgl.opengl.GL13.glActiveTexture;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
|
||||
import com.jozufozu.flywheel.backend.instancing.MaterialManager;
|
||||
import com.jozufozu.flywheel.backend.instancing.MaterialRenderer;
|
||||
import com.jozufozu.flywheel.core.WorldContext;
|
||||
import com.jozufozu.flywheel.core.atlas.AtlasInfo;
|
||||
import com.jozufozu.flywheel.core.atlas.SheetData;
|
||||
import com.jozufozu.flywheel.core.shader.IProgramCallback;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.texture.TextureManager;
|
||||
import net.minecraft.inventory.container.PlayerContainer;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.vector.Matrix4f;
|
||||
|
||||
public class CrumblingMaterialManager extends MaterialManager<CrumblingProgram> {
|
||||
|
||||
public CrumblingMaterialManager(WorldContext<CrumblingProgram> context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render every model for every material.
|
||||
*
|
||||
* @param layer Which vanilla {@link RenderType} is being drawn?
|
||||
* @param viewProjection How do we get from camera space to clip space?
|
||||
* @param callback Provide additional uniforms or state here.
|
||||
*/
|
||||
public void render(RenderType layer, Matrix4f viewProjection, double camX, double camY, double camZ, IProgramCallback<CrumblingProgram> callback) {
|
||||
camX -= originCoordinate.getX();
|
||||
camY -= originCoordinate.getY();
|
||||
camZ -= originCoordinate.getZ();
|
||||
|
||||
Matrix4f translate = Matrix4f.createTranslateMatrix((float) -camX, (float) -camY, (float) -camZ);
|
||||
|
||||
translate.multiplyBackward(viewProjection);
|
||||
|
||||
TextureManager textureManager = Minecraft.getInstance().textureManager;
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, textureManager.getTexture(PlayerContainer.BLOCK_ATLAS)
|
||||
.getId());
|
||||
|
||||
for (MaterialRenderer<CrumblingProgram> material : atlasRenderers) {
|
||||
material.render(layer, translate, camX, camY, camZ, CrumblingProgram::setDefaultAtlasSize);
|
||||
}
|
||||
|
||||
for (Map.Entry<ResourceLocation, ArrayList<MaterialRenderer<CrumblingProgram>>> entry : renderers.entrySet()) {
|
||||
glBindTexture(GL_TEXTURE_2D, textureManager.getTexture(entry.getKey())
|
||||
.getId());
|
||||
SheetData atlasData = AtlasInfo.getAtlasData(entry.getKey());
|
||||
for (MaterialRenderer<CrumblingProgram> materialRenderer : entry.getValue()) {
|
||||
materialRenderer.render(layer, translate, camX, camY, camZ, p -> p.setAtlasSize(atlasData.width, atlasData.height));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,7 +6,6 @@ import java.util.List;
|
|||
|
||||
import com.jozufozu.flywheel.backend.loading.Program;
|
||||
import com.jozufozu.flywheel.core.atlas.AtlasInfo;
|
||||
import com.jozufozu.flywheel.core.atlas.SheetData;
|
||||
import com.jozufozu.flywheel.core.shader.WorldProgram;
|
||||
import com.jozufozu.flywheel.core.shader.extension.IProgramExtension;
|
||||
|
||||
|
@ -35,16 +34,6 @@ public class CrumblingProgram extends WorldProgram {
|
|||
glUniform2f(uTextureScale, x, y);
|
||||
}
|
||||
|
||||
public void setDefaultAtlasSize() {
|
||||
SheetData atlasData = AtlasInfo.getAtlasData(PlayerContainer.BLOCK_ATLAS);
|
||||
if (atlasData == null) return;
|
||||
|
||||
int width = atlasData.width;
|
||||
int height = atlasData.height;
|
||||
|
||||
setAtlasSize(width, height);
|
||||
}
|
||||
|
||||
public void setAtlasSize(int width, int height) {
|
||||
AtlasTexture blockAtlas = AtlasInfo.getAtlas(PlayerContainer.BLOCK_ATLAS);
|
||||
if (blockAtlas == null) return;
|
||||
|
|
|
@ -2,17 +2,16 @@ package com.jozufozu.flywheel.core.crumbling;
|
|||
|
||||
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
|
||||
import static org.lwjgl.opengl.GL11.glBindTexture;
|
||||
import static org.lwjgl.opengl.GL13.GL_TEXTURE0;
|
||||
import static org.lwjgl.opengl.GL13.GL_TEXTURE4;
|
||||
import static org.lwjgl.opengl.GL13.glActiveTexture;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.SortedSet;
|
||||
|
||||
import com.jozufozu.flywheel.backend.Backend;
|
||||
import com.jozufozu.flywheel.backend.gl.GlTextureUnit;
|
||||
import com.jozufozu.flywheel.backend.instancing.InstanceManager;
|
||||
import com.jozufozu.flywheel.backend.instancing.MaterialManager;
|
||||
import com.jozufozu.flywheel.backend.material.MaterialManager;
|
||||
import com.jozufozu.flywheel.backend.state.RenderLayer;
|
||||
import com.jozufozu.flywheel.core.Contexts;
|
||||
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
|
||||
import com.jozufozu.flywheel.util.Lazy;
|
||||
|
@ -84,9 +83,9 @@ public class CrumblingRenderer {
|
|||
|
||||
renderer.beginFrame(info);
|
||||
|
||||
glActiveTexture(GL_TEXTURE4);
|
||||
GlTextureUnit.T4.makeActive();
|
||||
glBindTexture(GL_TEXTURE_2D, breaking.getId());
|
||||
materials.render(RenderType.cutoutMipped(), viewProjection, cameraX, cameraY, cameraZ);
|
||||
materials.render(RenderLayer.SOLID, viewProjection, cameraX, cameraY, cameraZ);
|
||||
|
||||
renderer.invalidate();
|
||||
}
|
||||
|
@ -95,7 +94,7 @@ public class CrumblingRenderer {
|
|||
|
||||
crumblingLayer.clearRenderState();
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
GlTextureUnit.T0.makeActive();
|
||||
Texture breaking = textureManager.getTexture(ModelBakery.BREAKING_LOCATIONS.get(0));
|
||||
if (breaking != null) glBindTexture(GL_TEXTURE_2D, breaking.getId());
|
||||
}
|
||||
|
@ -146,7 +145,9 @@ public class CrumblingRenderer {
|
|||
private final InstanceManager<TileEntity> instanceManager;
|
||||
|
||||
private State() {
|
||||
materialManager = new CrumblingMaterialManager(Contexts.CRUMBLING);
|
||||
materialManager = MaterialManager.builder(Contexts.CRUMBLING)
|
||||
.setGroupFactory(CrumblingGroup::new)
|
||||
.build();
|
||||
instanceManager = new CrumblingInstanceManager(materialManager);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
package com.jozufozu.flywheel.core.model;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
|
||||
import com.jozufozu.flywheel.backend.model.ElementBuffer;
|
||||
import com.jozufozu.flywheel.core.QuadConverter;
|
||||
import com.jozufozu.flywheel.util.BufferBuilderReader;
|
||||
import com.jozufozu.flywheel.util.VirtualEmptyModelData;
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.BlockModelRenderer;
|
||||
import net.minecraft.client.renderer.BlockRendererDispatcher;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.model.IBakedModel;
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
public class BlockModel implements IModel {
|
||||
private static final MatrixStack IDENTITY = new MatrixStack();
|
||||
|
||||
private final BufferBuilderReader reader;
|
||||
|
||||
private final VertexFormat modelFormat;
|
||||
|
||||
public BlockModel(VertexFormat modelFormat, IBakedModel model, BlockState referenceState) {
|
||||
this(modelFormat, model, referenceState, IDENTITY);
|
||||
}
|
||||
|
||||
public BlockModel(VertexFormat modelFormat, IBakedModel model, BlockState referenceState, MatrixStack ms) {
|
||||
this.modelFormat = modelFormat;
|
||||
reader = new BufferBuilderReader(getBufferBuilder(model, referenceState, ms));
|
||||
}
|
||||
|
||||
@Override
|
||||
public VertexFormat format() {
|
||||
return modelFormat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int vertexCount() {
|
||||
return reader.getVertexCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buffer(VecBuffer buffer) {
|
||||
|
||||
int vertexCount = vertexCount();
|
||||
|
||||
for (int i = 0; i < vertexCount; i++) {
|
||||
buffer.putVec3(reader.getX(i), reader.getY(i), reader.getZ(i));
|
||||
|
||||
buffer.putVec3(reader.getNX(i), reader.getNY(i), reader.getNZ(i));
|
||||
|
||||
buffer.putVec2(reader.getU(i), reader.getV(i));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ElementBuffer createEBO() {
|
||||
return QuadConverter.getInstance()
|
||||
.quads2Tris(vertexCount() / 4);
|
||||
}
|
||||
|
||||
public static BufferBuilder getBufferBuilder(IBakedModel model, BlockState referenceState, MatrixStack ms) {
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
BlockRendererDispatcher dispatcher = mc.getBlockRenderer();
|
||||
BlockModelRenderer blockRenderer = dispatcher.getModelRenderer();
|
||||
BufferBuilder builder = new BufferBuilder(512);
|
||||
|
||||
// BakedQuadWrapper quadReader = new BakedQuadWrapper();
|
||||
//
|
||||
// IModelData modelData = model.getModelData(mc.world, BlockPos.ZERO.up(255), referenceState, VirtualEmptyModelData.INSTANCE);
|
||||
// List<BakedQuad> quads = Arrays.stream(dirs)
|
||||
// .flatMap(dir -> model.getQuads(referenceState, dir, mc.world.rand, modelData).stream())
|
||||
// .collect(Collectors.toList());
|
||||
|
||||
builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK);
|
||||
blockRenderer.renderModel(mc.level, model, referenceState, BlockPos.ZERO.above(255), ms, builder, true, mc.level.random, 42, OverlayTexture.NO_OVERLAY, VirtualEmptyModelData.INSTANCE);
|
||||
builder.end();
|
||||
return builder;
|
||||
}
|
||||
|
||||
// DOWN, UP, NORTH, SOUTH, WEST, EAST, null
|
||||
private static final Direction[] dirs;
|
||||
|
||||
static {
|
||||
Direction[] directions = Direction.values();
|
||||
|
||||
dirs = Arrays.copyOf(directions, directions.length + 1);
|
||||
}
|
||||
}
|
26
src/main/java/com/jozufozu/flywheel/core/model/IModel.java
Normal file
26
src/main/java/com/jozufozu/flywheel/core/model/IModel.java
Normal file
|
@ -0,0 +1,26 @@
|
|||
package com.jozufozu.flywheel.core.model;
|
||||
|
||||
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
|
||||
import com.jozufozu.flywheel.backend.model.ElementBuffer;
|
||||
|
||||
/**
|
||||
* A model that can be rendered by flywheel.
|
||||
*/
|
||||
public interface IModel {
|
||||
|
||||
/**
|
||||
* Copy this model into the given buffer.
|
||||
*/
|
||||
void buffer(VecBuffer buffer);
|
||||
|
||||
int vertexCount();
|
||||
|
||||
VertexFormat format();
|
||||
|
||||
ElementBuffer createEBO();
|
||||
|
||||
default int size() {
|
||||
return vertexCount() * format().getStride();
|
||||
}
|
||||
}
|
|
@ -1,8 +1,52 @@
|
|||
package com.jozufozu.flywheel.core.model;
|
||||
|
||||
public class ModelPart {
|
||||
import java.util.List;
|
||||
|
||||
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
|
||||
import com.jozufozu.flywheel.backend.model.ElementBuffer;
|
||||
import com.jozufozu.flywheel.core.Formats;
|
||||
import com.jozufozu.flywheel.core.QuadConverter;
|
||||
|
||||
public class ModelPart implements IModel {
|
||||
|
||||
private final List<PartBuilder.CuboidBuilder> cuboids;
|
||||
private int vertices;
|
||||
|
||||
public ModelPart(List<PartBuilder.CuboidBuilder> cuboids) {
|
||||
this.cuboids = cuboids;
|
||||
|
||||
vertices = 0;
|
||||
|
||||
for (PartBuilder.CuboidBuilder cuboid : cuboids) {
|
||||
vertices += cuboid.vertices();
|
||||
}
|
||||
}
|
||||
|
||||
public static PartBuilder builder(int sizeU, int sizeV) {
|
||||
return new PartBuilder(sizeU, sizeV);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buffer(VecBuffer buffer) {
|
||||
for (PartBuilder.CuboidBuilder cuboid : cuboids) {
|
||||
cuboid.buffer(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int vertexCount() {
|
||||
return vertices;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VertexFormat format() {
|
||||
return Formats.UNLIT_MODEL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ElementBuffer createEBO() {
|
||||
return QuadConverter.getInstance()
|
||||
.quads2Tris(vertices / 4);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
package com.jozufozu.flywheel.core.model;
|
||||
|
||||
import java.nio.Buffer;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
|
||||
import com.jozufozu.flywheel.backend.model.IndexedModel;
|
||||
|
||||
public class ModelUtil {
|
||||
public static IndexedModel getIndexedModel(IModel blockModel) {
|
||||
ByteBuffer vertices = ByteBuffer.allocate(blockModel.size());
|
||||
vertices.order(ByteOrder.nativeOrder());
|
||||
|
||||
blockModel.buffer(new VecBuffer(vertices));
|
||||
|
||||
((Buffer) vertices).rewind();
|
||||
|
||||
return new IndexedModel(blockModel.format(), vertices, blockModel.vertexCount(), blockModel.createEBO());
|
||||
}
|
||||
}
|
|
@ -8,9 +8,6 @@ import java.util.List;
|
|||
import java.util.Set;
|
||||
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
|
||||
import com.jozufozu.flywheel.backend.model.BufferedModel;
|
||||
import com.jozufozu.flywheel.backend.model.IndexedModel;
|
||||
import com.jozufozu.flywheel.core.Formats;
|
||||
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.util.Direction;
|
||||
|
@ -18,23 +15,16 @@ import net.minecraft.util.math.vector.Vector3f;
|
|||
|
||||
public class PartBuilder {
|
||||
|
||||
private float sizeU = 64.0F;
|
||||
private float sizeV = 32.0F;
|
||||
private final float sizeU;
|
||||
private final float sizeV;
|
||||
|
||||
private TextureAtlasSprite sprite;
|
||||
|
||||
private final List<CuboidBuilder> cuboids = new ArrayList<>();
|
||||
|
||||
public PartBuilder() { }
|
||||
|
||||
public PartBuilder(int sizeU, int sizeV) {
|
||||
this.setTextureSize(sizeU, sizeV);
|
||||
}
|
||||
|
||||
public PartBuilder setTextureSize(int textureWidth, int textureHeight) {
|
||||
this.sizeU = (float)textureWidth;
|
||||
this.sizeV = (float)textureHeight;
|
||||
return this;
|
||||
this.sizeU = (float) sizeU;
|
||||
this.sizeV = (float) sizeV;
|
||||
}
|
||||
|
||||
public PartBuilder sprite(TextureAtlasSprite sprite) {
|
||||
|
@ -46,22 +36,8 @@ public class PartBuilder {
|
|||
return new CuboidBuilder(this);
|
||||
}
|
||||
|
||||
public BufferedModel build() {
|
||||
int vertices = 0;
|
||||
|
||||
for (CuboidBuilder cuboid : cuboids) {
|
||||
vertices += cuboid.vertices();
|
||||
}
|
||||
|
||||
VecBuffer buffer = VecBuffer.allocate(vertices * Formats.UNLIT_MODEL.getStride());
|
||||
|
||||
for (CuboidBuilder cuboid : cuboids) {
|
||||
cuboid.buffer(buffer);
|
||||
}
|
||||
|
||||
buffer.rewind();
|
||||
|
||||
return IndexedModel.fromSequentialQuads(Formats.UNLIT_MODEL, buffer.unwrap(), vertices);
|
||||
public ModelPart build() {
|
||||
return new ModelPart(cuboids);
|
||||
}
|
||||
|
||||
private PartBuilder addCuboid(CuboidBuilder builder) {
|
||||
|
@ -84,6 +60,8 @@ public class PartBuilder {
|
|||
float posY2;
|
||||
float posZ2;
|
||||
|
||||
boolean invertYZ;
|
||||
|
||||
final PartBuilder partBuilder;
|
||||
|
||||
CuboidBuilder(PartBuilder partBuilder) {
|
||||
|
@ -123,6 +101,14 @@ public class PartBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pulls the cuboid "inside out" through the Y and Z axes.
|
||||
*/
|
||||
public CuboidBuilder invertYZ() {
|
||||
this.invertYZ = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PartBuilder endCuboid() {
|
||||
return partBuilder.addCuboid(this);
|
||||
}
|
||||
|
@ -137,14 +123,21 @@ public class PartBuilder {
|
|||
float sizeY = posY2 - posY1;
|
||||
float sizeZ = posZ2 - posZ1;
|
||||
|
||||
Vector3f lll = new Vector3f(posX1 / 16f, posY1 / 16f, posZ1 / 16f);
|
||||
Vector3f hll = new Vector3f(posX2 / 16f, posY1 / 16f, posZ1 / 16f);
|
||||
Vector3f hhl = new Vector3f(posX2 / 16f, posY2 / 16f, posZ1 / 16f);
|
||||
Vector3f lhl = new Vector3f(posX1 / 16f, posY2 / 16f, posZ1 / 16f);
|
||||
Vector3f llh = new Vector3f(posX1 / 16f, posY1 / 16f, posZ2 / 16f);
|
||||
Vector3f hlh = new Vector3f(posX2 / 16f, posY1 / 16f, posZ2 / 16f);
|
||||
Vector3f hhh = new Vector3f(posX2 / 16f, posY2 / 16f, posZ2 / 16f);
|
||||
Vector3f lhh = new Vector3f(posX1 / 16f, posY2 / 16f, posZ2 / 16f);
|
||||
float posX1 = this.posX1 / 16f;
|
||||
float posY1 = this.posY1 / 16f;
|
||||
float posZ1 = this.posZ1 / 16f;
|
||||
float posX2 = this.posX2 / 16f;
|
||||
float posY2 = this.posY2 / 16f;
|
||||
float posZ2 = this.posZ2 / 16f;
|
||||
|
||||
Vector3f lll = new Vector3f(posX1, posY1, posZ1);
|
||||
Vector3f hll = new Vector3f(posX2, posY1, posZ1);
|
||||
Vector3f hhl = new Vector3f(posX2, posY2, posZ1);
|
||||
Vector3f lhl = new Vector3f(posX1, posY2, posZ1);
|
||||
Vector3f llh = new Vector3f(posX1, posY1, posZ2);
|
||||
Vector3f hlh = new Vector3f(posX2, posY1, posZ2);
|
||||
Vector3f hhh = new Vector3f(posX2, posY2, posZ2);
|
||||
Vector3f lhh = new Vector3f(posX1, posY2, posZ2);
|
||||
float f4 = getU((float)textureOffsetU);
|
||||
float f5 = getU((float)textureOffsetU + sizeZ);
|
||||
float f6 = getU((float)textureOffsetU + sizeZ + sizeX);
|
||||
|
@ -155,12 +148,21 @@ public class PartBuilder {
|
|||
float f11 = getV((float)textureOffsetV + sizeZ);
|
||||
float f12 = getV((float)textureOffsetV + sizeZ + sizeY);
|
||||
|
||||
quad(buffer, new Vector3f[]{hlh, llh, lll, hll}, f5, f10, f6, f11, Direction.DOWN);
|
||||
quad(buffer, new Vector3f[]{hhl, lhl, lhh, hhh}, f6, f11, f7, f10, Direction.UP);
|
||||
quad(buffer, new Vector3f[]{lll, llh, lhh, lhl}, f4, f11, f5, f12, Direction.WEST);
|
||||
quad(buffer, new Vector3f[]{hll, lll, lhl, hhl}, f5, f11, f6, f12, Direction.NORTH);
|
||||
quad(buffer, new Vector3f[]{hlh, hll, hhl, hhh}, f6, f11, f8, f12, Direction.EAST);
|
||||
quad(buffer, new Vector3f[]{llh, hlh, hhh, lhh}, f8, f11, f9, f12, Direction.SOUTH);
|
||||
if (invertYZ) {
|
||||
quad(buffer, new Vector3f[]{hlh, llh, lll, hll}, f6, f11, f7, f10, Direction.DOWN);
|
||||
quad(buffer, new Vector3f[]{hhl, lhl, lhh, hhh}, f5, f10, f6, f11, Direction.UP);
|
||||
quad(buffer, new Vector3f[]{lll, llh, lhh, lhl}, f5, f12, f4, f11, Direction.WEST);
|
||||
quad(buffer, new Vector3f[]{hll, lll, lhl, hhl}, f9, f12, f8, f11, Direction.NORTH);
|
||||
quad(buffer, new Vector3f[]{hlh, hll, hhl, hhh}, f8, f12, f6, f11, Direction.EAST);
|
||||
quad(buffer, new Vector3f[]{llh, hlh, hhh, lhh}, f6, f12, f5, f11, Direction.SOUTH);
|
||||
} else {
|
||||
quad(buffer, new Vector3f[]{hlh, llh, lll, hll}, f5, f10, f6, f11, Direction.DOWN);
|
||||
quad(buffer, new Vector3f[]{hhl, lhl, lhh, hhh}, f6, f11, f7, f10, Direction.UP);
|
||||
quad(buffer, new Vector3f[]{lll, llh, lhh, lhl}, f4, f11, f5, f12, Direction.WEST);
|
||||
quad(buffer, new Vector3f[]{hll, lll, lhl, hhl}, f5, f11, f6, f12, Direction.NORTH);
|
||||
quad(buffer, new Vector3f[]{hlh, hll, hhl, hhh}, f6, f11, f8, f12, Direction.EAST);
|
||||
quad(buffer, new Vector3f[]{llh, hlh, hhh, lhh}, f8, f11, f9, f12, Direction.SOUTH);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault
|
||||
package com.jozufozu.flywheel.core.model;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import mcp.MethodsReturnNonnullByDefault;
|
|
@ -1,19 +0,0 @@
|
|||
package com.jozufozu.flywheel.core.shader;
|
||||
|
||||
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
|
||||
|
||||
/**
|
||||
* Used to define shader uniforms.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface IProgramCallback<P extends GlProgram> {
|
||||
|
||||
void call(P program);
|
||||
|
||||
default IProgramCallback<P> andThen(IProgramCallback<P> other) {
|
||||
return program -> {
|
||||
call(program);
|
||||
other.call(program);
|
||||
};
|
||||
}
|
||||
}
|
|
@ -5,7 +5,6 @@ import static org.lwjgl.opengl.GL20.glUniform3f;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
|
||||
import com.jozufozu.flywheel.backend.loading.Program;
|
||||
import com.jozufozu.flywheel.core.shader.extension.IProgramExtension;
|
||||
import com.jozufozu.flywheel.util.AnimationTickHolder;
|
||||
|
|
|
@ -18,7 +18,7 @@ public class NormalDebugStateProvider implements IBooleanStateProvider {
|
|||
@Override
|
||||
public boolean isTrue() {
|
||||
return FlwConfig.get()
|
||||
.normalOverlayEnabled();
|
||||
.debugNormals();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.lwjgl.system.MemoryUtil;
|
|||
|
||||
import com.jozufozu.flywheel.backend.Backend;
|
||||
import com.jozufozu.flywheel.backend.gl.GlTexture;
|
||||
import com.jozufozu.flywheel.backend.gl.GlTextureUnit;
|
||||
import com.jozufozu.flywheel.backend.gl.versioned.RGPixelFormat;
|
||||
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
@ -257,7 +258,7 @@ public class LightVolume {
|
|||
// just in case something goes wrong or we accidentally call this before this volume is properly disposed of.
|
||||
if (lightData == null || removed) return;
|
||||
|
||||
glActiveTexture(GL_TEXTURE4);
|
||||
GlTextureUnit.T4.makeActive();
|
||||
glTexture.bind();
|
||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
package com.jozufozu.flywheel.mixin;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import net.minecraft.client.multiplayer.ClientChunkProvider;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.world.biome.BiomeContainer;
|
||||
import net.minecraft.world.chunk.AbstractChunkProvider;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.ChunkStatus;
|
||||
import net.minecraft.world.chunk.IChunk;
|
||||
|
||||
@Mixin(ClientChunkProvider.class)
|
||||
public abstract class FastChunkProviderMixin extends AbstractChunkProvider {
|
||||
|
||||
@Unique
|
||||
private int lastX;
|
||||
@Unique
|
||||
private int lastZ;
|
||||
|
||||
@Unique
|
||||
private IChunk lastChunk;
|
||||
|
||||
@Inject(method = "getChunk",
|
||||
at = @At("HEAD"),
|
||||
cancellable = true)
|
||||
public void returnCachedChunk(int x, int z, ChunkStatus status, boolean create, CallbackInfoReturnable<IChunk> cir) {
|
||||
if (status.isOrAfter(ChunkStatus.FULL) && lastChunk != null && x == lastX && z == lastZ) {
|
||||
cir.setReturnValue(lastChunk);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "getChunk",
|
||||
at = @At("RETURN"))
|
||||
public void cacheChunk(int x, int z, ChunkStatus status, boolean create, CallbackInfoReturnable<IChunk> cir) {
|
||||
if (status.isOrAfter(ChunkStatus.FULL)) {
|
||||
lastChunk = cir.getReturnValue();
|
||||
lastX = x;
|
||||
lastZ = z;
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "drop", at = @At("HEAD"))
|
||||
public void invalidateOnDrop(int x, int z, CallbackInfo ci) {
|
||||
if (x == lastX && z == lastZ)
|
||||
lastChunk = null;
|
||||
}
|
||||
|
||||
@Inject(method = "replaceWithPacketData", at = @At("HEAD"))
|
||||
public void invalidateOnPacket(int x, int z, BiomeContainer p_228313_3_, PacketBuffer p_228313_4_, CompoundNBT p_228313_5_, int p_228313_6_, boolean p_228313_7_, CallbackInfoReturnable<Chunk> cir) {
|
||||
if (x == lastX && z == lastZ)
|
||||
lastChunk = null;
|
||||
}
|
||||
|
||||
@Redirect(method = "isTickingChunk", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/ClientChunkProvider;hasChunk(II)Z"))
|
||||
public boolean redirectTicking(ClientChunkProvider clientChunkProvider, int x, int z) {
|
||||
if (lastChunk != null && x == lastX && z == lastZ) return true;
|
||||
|
||||
return clientChunkProvider.hasChunk(x, z);
|
||||
}
|
||||
}
|
|
@ -9,8 +9,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|||
|
||||
import com.jozufozu.flywheel.backend.Backend;
|
||||
import com.jozufozu.flywheel.backend.OptifineHandler;
|
||||
import com.jozufozu.flywheel.core.crumbling.CrumblingRenderer;
|
||||
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
|
||||
import com.jozufozu.flywheel.core.crumbling.CrumblingRenderer;
|
||||
import com.jozufozu.flywheel.event.BeginFrameEvent;
|
||||
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
|
||||
import com.jozufozu.flywheel.event.RenderLayerEvent;
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package com.jozufozu.flywheel.util;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
|
|
|
@ -10,6 +10,20 @@ import net.minecraft.util.math.vector.Matrix4f;
|
|||
import net.minecraft.util.math.vector.Vector3f;
|
||||
|
||||
public class RenderUtil {
|
||||
|
||||
private static final Matrix4f IDENTITY = new Matrix4f();
|
||||
static {
|
||||
IDENTITY.setIdentity();
|
||||
}
|
||||
|
||||
public static Matrix4f getIdentity() {
|
||||
return IDENTITY;
|
||||
}
|
||||
|
||||
public static Matrix4f copyIdentity() {
|
||||
return IDENTITY.copy();
|
||||
}
|
||||
|
||||
public static int nextPowerOf2(int a) {
|
||||
int h = Integer.highestOneBit(a);
|
||||
return (h == a) ? h : (h << 1);
|
||||
|
|
|
@ -6,7 +6,19 @@ import net.minecraft.util.math.vector.Quaternion;
|
|||
|
||||
public class MatrixTransformStack implements TransformStack {
|
||||
|
||||
private final MatrixStack internal = new MatrixStack();
|
||||
private final MatrixStack internal;
|
||||
|
||||
public MatrixTransformStack() {
|
||||
this(new MatrixStack());
|
||||
}
|
||||
|
||||
public MatrixTransformStack(MatrixStack internal) {
|
||||
this.internal = internal;
|
||||
}
|
||||
|
||||
public static MatrixTransformStack of(MatrixStack ms) {
|
||||
return new MatrixTransformStack(ms);
|
||||
}
|
||||
|
||||
public MatrixStack unwrap() {
|
||||
return internal;
|
||||
|
@ -24,13 +36,21 @@ public class MatrixTransformStack implements TransformStack {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransformStack scale(float factor) {
|
||||
internal.scale(factor, factor, factor);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransformStack push() {
|
||||
internal.pushPose();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransformStack pop() {
|
||||
internal.popPose();
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,11 @@ public class QuaternionTransformStack implements TransformStack {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransformStack scale(float factor) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransformStack pop() {
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@ public interface TransformStack {
|
|||
|
||||
TransformStack multiply(Quaternion quaternion);
|
||||
|
||||
TransformStack scale(float factor);
|
||||
|
||||
TransformStack push();
|
||||
|
||||
TransformStack pop();
|
||||
|
@ -43,11 +45,27 @@ public interface TransformStack {
|
|||
}
|
||||
|
||||
default TransformStack centre() {
|
||||
return translate(CENTER);
|
||||
return translateAll(0.5);
|
||||
}
|
||||
|
||||
default TransformStack unCentre() {
|
||||
return translateBack(CENTER);
|
||||
return translateAll(-0.5);
|
||||
}
|
||||
|
||||
default TransformStack translateAll(double v) {
|
||||
return translate(v, v, v);
|
||||
}
|
||||
|
||||
default TransformStack translateX(double x) {
|
||||
return translate(x, 0, 0);
|
||||
}
|
||||
|
||||
default TransformStack translateY(double y) {
|
||||
return translate(0, y, 0);
|
||||
}
|
||||
|
||||
default TransformStack translateZ(double z) {
|
||||
return translate(0, 0, z);
|
||||
}
|
||||
|
||||
default TransformStack translate(Vector3i vec) {
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
package com.jozufozu.flywheel.vanilla;
|
||||
|
||||
import com.jozufozu.flywheel.backend.instancing.IDynamicInstance;
|
||||
import com.jozufozu.flywheel.backend.instancing.MaterialManager;
|
||||
import com.jozufozu.flywheel.backend.instancing.tile.TileEntityInstance;
|
||||
import com.jozufozu.flywheel.backend.model.BufferedModel;
|
||||
import com.jozufozu.flywheel.backend.material.MaterialManager;
|
||||
import com.jozufozu.flywheel.core.Materials;
|
||||
import com.jozufozu.flywheel.core.materials.OrientedData;
|
||||
import com.jozufozu.flywheel.core.model.ModelPart;
|
||||
|
@ -58,12 +57,13 @@ public class BellInstance extends TileEntityInstance<BellTileEntity> implements
|
|||
}
|
||||
|
||||
private OrientedData createBellInstance() {
|
||||
return materialManager.getMaterial(Materials.ORIENTED)
|
||||
.get(tile.getType(), BellInstance::createBellModel)
|
||||
return materialManager.defaultCutout()
|
||||
.material(Materials.ORIENTED)
|
||||
.model(tile.getType(), BellInstance::createBellModel)
|
||||
.createInstance();
|
||||
}
|
||||
|
||||
private static BufferedModel createBellModel() {
|
||||
private static ModelPart createBellModel() {
|
||||
return ModelPart.builder(32, 32)
|
||||
.sprite(BellTileEntityRenderer.BELL_RESOURCE_LOCATION.sprite())
|
||||
.cuboid()
|
||||
|
|
|
@ -5,9 +5,9 @@ import java.util.Calendar;
|
|||
import javax.annotation.Nonnull;
|
||||
|
||||
import com.jozufozu.flywheel.backend.instancing.IDynamicInstance;
|
||||
import com.jozufozu.flywheel.backend.instancing.MaterialManager;
|
||||
import com.jozufozu.flywheel.backend.instancing.tile.TileEntityInstance;
|
||||
import com.jozufozu.flywheel.backend.model.BufferedModel;
|
||||
import com.jozufozu.flywheel.backend.material.MaterialManager;
|
||||
import com.jozufozu.flywheel.backend.state.TextureRenderState;
|
||||
import com.jozufozu.flywheel.core.Materials;
|
||||
import com.jozufozu.flywheel.core.materials.ModelData;
|
||||
import com.jozufozu.flywheel.core.materials.OrientedData;
|
||||
|
@ -119,19 +119,21 @@ public class ChestInstance<T extends TileEntity & IChestLid> extends TileEntityI
|
|||
|
||||
private OrientedData baseInstance() {
|
||||
|
||||
return materialManager.getMaterial(Materials.ORIENTED, renderMaterial.atlasLocation())
|
||||
.get("base_" + renderMaterial.texture(), this::getBaseModel)
|
||||
return materialManager.solid(TextureRenderState.get(renderMaterial.atlasLocation()))
|
||||
.material(Materials.ORIENTED)
|
||||
.model("base_" + renderMaterial.texture(), this::getBaseModel)
|
||||
.createInstance();
|
||||
}
|
||||
|
||||
private ModelData lidInstance() {
|
||||
|
||||
return materialManager.getMaterial(Materials.TRANSFORMED, renderMaterial.atlasLocation())
|
||||
.get("lid_" + renderMaterial.texture(), this::getLidModel)
|
||||
return materialManager.solid(TextureRenderState.get(renderMaterial.atlasLocation()))
|
||||
.material(Materials.TRANSFORMED)
|
||||
.model("lid_" + renderMaterial.texture(), this::getLidModel)
|
||||
.createInstance();
|
||||
}
|
||||
|
||||
private BufferedModel getBaseModel() {
|
||||
private ModelPart getBaseModel() {
|
||||
|
||||
switch (chestType) {
|
||||
case LEFT:
|
||||
|
@ -164,7 +166,7 @@ public class ChestInstance<T extends TileEntity & IChestLid> extends TileEntityI
|
|||
.build();
|
||||
}
|
||||
|
||||
private BufferedModel getLidModel() {
|
||||
private ModelPart getLidModel() {
|
||||
|
||||
switch (chestType) {
|
||||
case LEFT:
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
package com.jozufozu.flywheel.vanilla;
|
||||
|
||||
import com.jozufozu.flywheel.backend.state.IRenderState;
|
||||
import com.jozufozu.flywheel.backend.state.NoCullRenderState;
|
||||
import com.jozufozu.flywheel.backend.state.RenderState;
|
||||
|
||||
import net.minecraft.client.renderer.Atlases;
|
||||
|
||||
public class RenderStates {
|
||||
public static final IRenderState SHULKER = RenderState.builder()
|
||||
.texture(Atlases.SHULKER_SHEET)
|
||||
.addState(NoCullRenderState.INSTANCE)
|
||||
.build();
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
package com.jozufozu.flywheel.vanilla;
|
||||
|
||||
import com.jozufozu.flywheel.backend.instancing.IDynamicInstance;
|
||||
import com.jozufozu.flywheel.backend.instancing.tile.TileEntityInstance;
|
||||
import com.jozufozu.flywheel.backend.material.MaterialManager;
|
||||
import com.jozufozu.flywheel.core.Materials;
|
||||
import com.jozufozu.flywheel.core.materials.ModelData;
|
||||
import com.jozufozu.flywheel.core.model.ModelPart;
|
||||
import com.jozufozu.flywheel.util.AnimationTickHolder;
|
||||
import com.jozufozu.flywheel.util.transform.MatrixTransformStack;
|
||||
|
||||
import net.minecraft.block.ShulkerBoxBlock;
|
||||
import net.minecraft.client.renderer.Atlases;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.item.DyeColor;
|
||||
import net.minecraft.tileentity.ShulkerBoxTileEntity;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.vector.Quaternion;
|
||||
import net.minecraft.util.math.vector.Vector3f;
|
||||
|
||||
public class ShulkerBoxInstance extends TileEntityInstance<ShulkerBoxTileEntity> implements IDynamicInstance {
|
||||
|
||||
private final TextureAtlasSprite texture;
|
||||
|
||||
private final ModelData base;
|
||||
private final ModelData lid;
|
||||
private final MatrixTransformStack stack;
|
||||
|
||||
private float lastProgress = Float.NaN;
|
||||
|
||||
public ShulkerBoxInstance(MaterialManager<?> materialManager, ShulkerBoxTileEntity tile) {
|
||||
super(materialManager, tile);
|
||||
|
||||
DyeColor color = tile.getColor();
|
||||
if (color == null) {
|
||||
texture = Atlases.DEFAULT_SHULKER_TEXTURE_LOCATION.sprite();
|
||||
} else {
|
||||
texture = Atlases.SHULKER_TEXTURE_LOCATION.get(color.getId()).sprite();
|
||||
}
|
||||
Quaternion rotation = getDirection().getRotation();
|
||||
|
||||
stack = new MatrixTransformStack();
|
||||
|
||||
stack.translate(getInstancePosition())
|
||||
.scale(0.9995f)
|
||||
.translateAll(0.00025)
|
||||
.centre()
|
||||
.multiply(rotation)
|
||||
.unCentre();
|
||||
|
||||
base = makeBaseInstance().setTransform(stack.unwrap());
|
||||
|
||||
stack.translateY(0.25);
|
||||
|
||||
lid = makeLidInstance().setTransform(stack.unwrap());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginFrame() {
|
||||
float progress = tile.getProgress(AnimationTickHolder.getPartialTicks());
|
||||
|
||||
if (progress == lastProgress) return;
|
||||
lastProgress = progress;
|
||||
|
||||
Quaternion spin = Vector3f.YP.rotationDegrees(270.0F * progress);
|
||||
|
||||
stack.push()
|
||||
.centre()
|
||||
.multiply(spin)
|
||||
.unCentre()
|
||||
.translateY(progress * 0.5f);
|
||||
|
||||
lid.setTransform(stack.unwrap());
|
||||
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
base.delete();
|
||||
lid.delete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLight() {
|
||||
relight(pos, base, lid);
|
||||
}
|
||||
|
||||
private ModelData makeBaseInstance() {
|
||||
return materialManager.cutout(RenderStates.SHULKER)
|
||||
.material(Materials.TRANSFORMED)
|
||||
.model("base_" + texture.getName(), this::makeBaseModel)
|
||||
.createInstance();
|
||||
}
|
||||
|
||||
private ModelData makeLidInstance() {
|
||||
return materialManager.cutout(RenderStates.SHULKER)
|
||||
.material(Materials.TRANSFORMED)
|
||||
.model("lid_" + texture.getName(), this::makeLidModel)
|
||||
.createInstance();
|
||||
}
|
||||
|
||||
private ModelPart makeBaseModel() {
|
||||
return ModelPart.builder(64, 64)
|
||||
.sprite(texture)
|
||||
.cuboid()
|
||||
.textureOffset(0, 28)
|
||||
.size(16, 8, 16)
|
||||
.invertYZ()
|
||||
.endCuboid()
|
||||
.build();
|
||||
}
|
||||
|
||||
private ModelPart makeLidModel() {
|
||||
return ModelPart.builder(64, 64)
|
||||
.sprite(texture)
|
||||
.cuboid()
|
||||
.size(16, 12, 16)
|
||||
.invertYZ()
|
||||
.endCuboid()
|
||||
.build();
|
||||
}
|
||||
|
||||
private Direction getDirection() {
|
||||
if (blockState.getBlock() instanceof ShulkerBoxBlock) {
|
||||
return blockState.getValue(ShulkerBoxBlock.FACING);
|
||||
}
|
||||
|
||||
return Direction.UP;
|
||||
}
|
||||
}
|
|
@ -8,20 +8,19 @@ import net.minecraft.tileentity.TileEntityType;
|
|||
* TODO:
|
||||
* <table>
|
||||
* <tr><td>{@link TileEntityType#SIGN}</td><td> {@link net.minecraft.client.renderer.tileentity.SignTileEntityRenderer SignTileEntityRenderer}</td></tr>
|
||||
* <tr><td>{@link TileEntityType#MOB_SPAWNER}</td><td> {@link net.minecraft.client.renderer.tileentity.MobSpawnerTileEntityRenderer MobSpawnerTileEntityRenderer}</td></tr>
|
||||
* <tr><td>{@link TileEntityType#PISTON}</td><td> {@link net.minecraft.client.renderer.tileentity.PistonTileEntityRenderer PistonTileEntityRenderer}</td></tr>
|
||||
* <tr><td>{@link TileEntityType#CONDUIT}</td><td> {@link net.minecraft.client.renderer.tileentity.ConduitTileEntityRenderer ConduitTileEntityRenderer}</td></tr>
|
||||
* <tr><td>{@link TileEntityType#ENCHANTING_TABLE}</td><td> {@link net.minecraft.client.renderer.tileentity.EnchantmentTableTileEntityRenderer EnchantmentTableTileEntityRenderer}</td></tr>
|
||||
* <tr><td>{@link TileEntityType#LECTERN}</td><td> {@link net.minecraft.client.renderer.tileentity.LecternTileEntityRenderer LecternTileEntityRenderer}</td></tr>
|
||||
* <tr><td>{@link TileEntityType#MOB_SPAWNER}</td><td> {@link net.minecraft.client.renderer.tileentity.MobSpawnerTileEntityRenderer MobSpawnerTileEntityRenderer}</td></tr>
|
||||
* <tr><td>{@link TileEntityType#BED}</td><td> {@link net.minecraft.client.renderer.tileentity.BedTileEntityRenderer BedTileEntityRenderer}</td></tr>
|
||||
* <tr><td>^^ Interesting - Major vv</td></tr>
|
||||
* <tr><td>{@link TileEntityType#END_PORTAL}</td><td> {@link net.minecraft.client.renderer.tileentity.EndPortalTileEntityRenderer EndPortalTileEntityRenderer}</td></tr>
|
||||
* <tr><td>{@link TileEntityType#END_GATEWAY}</td><td> {@link net.minecraft.client.renderer.tileentity.EndGatewayTileEntityRenderer EndGatewayTileEntityRenderer}</td></tr>
|
||||
* <tr><td>{@link TileEntityType#BEACON}</td><td> {@link net.minecraft.client.renderer.tileentity.BeaconTileEntityRenderer BeaconTileEntityRenderer}</td></tr>
|
||||
* <tr><td>{@link TileEntityType#SKULL}</td><td> {@link net.minecraft.client.renderer.tileentity.SkullTileEntityRenderer SkullTileEntityRenderer}</td></tr>
|
||||
* <tr><td>{@link TileEntityType#BANNER}</td><td> {@link net.minecraft.client.renderer.tileentity.BannerTileEntityRenderer BannerTileEntityRenderer}</td></tr>
|
||||
* <tr><td>{@link TileEntityType#STRUCTURE_BLOCK}</td><td> {@link net.minecraft.client.renderer.tileentity.StructureTileEntityRenderer StructureTileEntityRenderer}</td></tr>
|
||||
* <tr><td>{@link TileEntityType#SHULKER_BOX}</td><td> {@link net.minecraft.client.renderer.tileentity.ShulkerBoxTileEntityRenderer ShulkerBoxTileEntityRenderer}</td></tr>
|
||||
* <tr><td>{@link TileEntityType#BED}</td><td> {@link net.minecraft.client.renderer.tileentity.BedTileEntityRenderer BedTileEntityRenderer}</td></tr>
|
||||
* <tr><td>{@link TileEntityType#CONDUIT}</td><td> {@link net.minecraft.client.renderer.tileentity.ConduitTileEntityRenderer ConduitTileEntityRenderer}</td></tr>
|
||||
* <tr><td>{@link TileEntityType#BELL}</td><td> {@link net.minecraft.client.renderer.tileentity.BellTileEntityRenderer BellTileEntityRenderer}</td></tr>
|
||||
* <tr><td>{@link TileEntityType#CAMPFIRE}</td><td> {@link net.minecraft.client.renderer.tileentity.CampfireTileEntityRenderer CampfireTileEntityRenderer}</td></tr>
|
||||
* </table>
|
||||
*/
|
||||
|
@ -43,5 +42,9 @@ public class VanillaInstances {
|
|||
r.tile(TileEntityType.BELL)
|
||||
.setSkipRender(true)
|
||||
.factory(BellInstance::new);
|
||||
|
||||
r.tile(TileEntityType.SHULKER_BOX)
|
||||
.setSkipRender(true)
|
||||
.factory(ShulkerBoxInstance::new);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
"package": "com.jozufozu.flywheel.mixin",
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"refmap": "flywheel.refmap.json",
|
||||
"mixins": [],
|
||||
"client": [
|
||||
"CancelEntityRenderMixin",
|
||||
"CancelTileEntityRenderMixin",
|
||||
|
@ -18,7 +17,8 @@
|
|||
"atlas.AtlasDataMixin",
|
||||
"atlas.SheetDataAccessor",
|
||||
"light.LightUpdateMixin",
|
||||
"light.NetworkLightUpdateMixin"
|
||||
"light.NetworkLightUpdateMixin",
|
||||
"FastChunkProviderMixin"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 0
|
||||
|
|
Loading…
Reference in a new issue