Vanillaization

- IModels now accept a VertexConsumer
 - IRenderState -> RenderType
 - AbstractInstancer for dealing with InstanceData tidyness
 - Alter crumbling renderer to match new system
 - Add hack to keep track of bound atlas textures
This commit is contained in:
Jozufozu 2021-12-06 01:47:52 -08:00
parent c54514cf47
commit b9352bc3a4
40 changed files with 462 additions and 543 deletions

View file

@ -1,5 +1,8 @@
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;
@ -16,6 +19,7 @@ import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
public class Flywheel {
public static final String ID = "flywheel";
public static final Logger log = LogManager.getLogger(Flywheel.class);
public Flywheel() {
FMLJavaModLoadingContext.get()

View file

@ -51,4 +51,12 @@ public enum GlTextureUnit {
public void makeActive() {
GlStateManager._activeTexture(glEnum);
}
public static GlTextureUnit getActive() {
return fromGlEnum(GlStateManager._getActiveTexture());
}
public static GlTextureUnit fromGlEnum(int glEnum) {
return GlTextureUnit.values()[glEnum - GL_TEXTURE0];
}
}

View file

@ -5,6 +5,8 @@ import java.util.function.Supplier;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import com.jozufozu.flywheel.Flywheel;
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
@ -42,7 +44,7 @@ public enum GlError {
// TODO: build flag? to enable or disable this function
GlError poll = GlError.poll();
if (poll != null) {
//throw new GlException(poll, context.get());
Flywheel.log.error("{}: {}", poll.name(), context.get());
}
}
}

View file

@ -0,0 +1,128 @@
package com.jozufozu.flywheel.backend.instancing;
import java.util.ArrayList;
import java.util.BitSet;
import com.jozufozu.flywheel.backend.struct.StructType;
import com.jozufozu.flywheel.core.model.IModel;
public class AbstractInstancer<D extends InstanceData> implements Instancer<D> {
protected final StructType<D> type;
protected final IModel modelData;
protected final ArrayList<D> data = new ArrayList<>();
boolean anyToRemove;
boolean anyToUpdate;
public AbstractInstancer(StructType<D> type, IModel modelData) {
this.type = type;
this.modelData = modelData;
}
/**
* @return a handle to a new copy of this model.
*/
@Override
public D createInstance() {
D data = type.create();
data.owner = this;
return _add(data);
}
/**
* Copy a data from another Instancer to this.
*
* This has the effect of swapping out one model for another.
* @param inOther the data associated with a different model.
*/
@Override
public void stealInstance(D inOther) {
if (inOther.owner == this) return;
inOther.delete();
// sike, we want to keep it, changing the owner reference will still delete it in the other
inOther.removed = false;
_add(inOther);
}
@Override
public void markDirty(InstanceData instanceData) {
anyToUpdate = true;
instanceData.dirty = true;
}
@Override
public void markRemoval(InstanceData instanceData) {
anyToRemove = true;
instanceData.removed = true;
}
/**
* Clear all instance data without freeing resources.
*/
public void clear() {
data.clear();
anyToRemove = true;
}
protected BitSet getDirtyBitSet() {
final int size = data.size();
final BitSet dirtySet = new BitSet(size);
for (int i = 0; i < size; i++) {
D element = data.get(i);
if (element.dirty) {
dirtySet.set(i);
element.dirty = false;
}
}
return dirtySet;
}
protected void removeDeletedInstances() {
// Figure out which elements are to be removed.
final int oldSize = this.data.size();
int removeCount = 0;
final BitSet removeSet = new BitSet(oldSize);
for (int i = 0; i < oldSize; i++) {
final D element = this.data.get(i);
if (element.removed || element.owner != this) {
removeSet.set(i);
removeCount++;
}
}
final int newSize = oldSize - removeCount;
// shift surviving elements left over the spaces left by removed elements
for (int i = 0, j = 0; (i < oldSize) && (j < newSize); i++, j++) {
i = removeSet.nextClearBit(i);
if (i != j) {
D element = data.get(i);
data.set(j, element);
element.dirty = true;
}
}
anyToUpdate = true;
data.subList(newSize, oldSize)
.clear();
}
private D _add(D instanceData) {
instanceData.owner = this;
instanceData.dirty = true;
anyToUpdate = true;
synchronized (data) {
data.add(instanceData);
}
return instanceData;
}
}

View file

@ -1,6 +1,5 @@
package com.jozufozu.flywheel.backend.instancing;
import java.util.ArrayList;
import java.util.BitSet;
import com.jozufozu.flywheel.backend.Backend;
@ -17,12 +16,10 @@ import com.jozufozu.flywheel.backend.struct.StructWriter;
import com.jozufozu.flywheel.core.model.IModel;
import com.jozufozu.flywheel.util.AttribUtil;
public class GPUInstancer<D extends InstanceData> implements Instancer<D> {
public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
private final ModelAllocator modelAllocator;
private final IModel modelData;
private final VertexFormat instanceFormat;
private final StructType<D> type;
private IBufferedModel model;
private GlVertexArray vao;
@ -32,44 +29,12 @@ public class GPUInstancer<D extends InstanceData> implements Instancer<D> {
private boolean deleted;
private boolean initialized;
private final ArrayList<D> data = new ArrayList<>();
boolean anyToRemove;
boolean anyToUpdate;
public GPUInstancer(ModelAllocator modelAllocator, IModel model, StructType<D> type) {
public GPUInstancer(StructType<D> type, IModel model, ModelAllocator modelAllocator) {
super(type, model);
this.modelAllocator = modelAllocator;
this.modelData = model;
this.type = type;
this.instanceFormat = type.format();
}
/**
* @return a handle to a new copy of this model.
*/
@Override
public D createInstance() {
D data = type.create();
data.owner = this;
return _add(data);
}
/**
* Copy a data from another Instancer to this.
*
* This has the effect of swapping out one model for another.
* @param inOther the data associated with a different model.
*/
@Override
public void stealInstance(D inOther) {
if (inOther.owner == this) return;
inOther.delete();
// sike, we want to keep it, changing the owner reference will still delete it in the other
inOther.removed = false;
_add(inOther);
}
public void render() {
if (invalid()) return;
@ -127,14 +92,6 @@ public class GPUInstancer<D extends InstanceData> implements Instancer<D> {
return !anyToUpdate && !anyToRemove && glInstanceCount == 0;
}
/**
* Clear all instance data without freeing resources.
*/
public void clear() {
data.clear();
anyToRemove = true;
}
/**
* Free acquired resources. All other Instancer methods are undefined behavior after calling delete.
*/
@ -149,18 +106,6 @@ public class GPUInstancer<D extends InstanceData> implements Instancer<D> {
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() {
if (anyToRemove) {
removeDeletedInstances();
@ -215,7 +160,7 @@ public class GPUInstancer<D extends InstanceData> implements Instancer<D> {
if (length > 0) {
MappedBuffer mapped = instanceVBO.getBuffer(offset, length);
StructWriter<D> writer = type.getWriter(mapped);
StructWriter<D> writer = type.asWriteable().getWriter(mapped);
dirtySet.stream()
.forEach(i -> {
@ -226,21 +171,6 @@ public class GPUInstancer<D extends InstanceData> implements Instancer<D> {
}
}
private BitSet getDirtyBitSet() {
final int size = data.size();
final BitSet dirtySet = new BitSet(size);
for (int i = 0; i < size; i++) {
D element = data.get(i);
if (element.dirty) {
dirtySet.set(i);
element.dirty = false;
}
}
return dirtySet;
}
private boolean realloc() {
int size = this.data.size();
int stride = instanceFormat.getStride();
@ -250,7 +180,7 @@ public class GPUInstancer<D extends InstanceData> implements Instancer<D> {
instanceVBO.alloc(glBufferSize);
MappedBuffer buffer = instanceVBO.getBuffer(0, glBufferSize);
StructWriter<D> writer = type.getWriter(buffer);
StructWriter<D> writer = type.asWriteable().getWriter(buffer);
for (D datum : data) {
writer.write(datum);
}
@ -265,39 +195,6 @@ public class GPUInstancer<D extends InstanceData> implements Instancer<D> {
return false;
}
private void removeDeletedInstances() {
// Figure out which elements are to be removed.
final int oldSize = this.data.size();
int removeCount = 0;
final BitSet removeSet = new BitSet(oldSize);
for (int i = 0; i < oldSize; i++) {
final D element = this.data.get(i);
if (element.removed || element.owner != this) {
removeSet.set(i);
removeCount++;
}
}
final int newSize = oldSize - removeCount;
// shift surviving elements left over the spaces left by removed elements
for (int i = 0, j = 0; (i < oldSize) && (j < newSize); i++, j++) {
i = removeSet.nextClearBit(i);
if (i != j) {
D element = data.get(i);
data.set(j, element);
element.dirty = true;
}
}
anyToUpdate = true;
data.subList(newSize, oldSize)
.clear();
}
private void informAttribDivisors() {
int staticAttributes = model.getAttributeCount();
instanceFormat.vertexAttribPointers(staticAttributes);
@ -306,16 +203,4 @@ public class GPUInstancer<D extends InstanceData> implements Instancer<D> {
Backend.getInstance().compat.instancedArrays.vertexAttribDivisor(i + staticAttributes, 1);
}
}
@Override
public void markDirty(InstanceData instanceData) {
anyToUpdate = true;
instanceData.dirty = true;
}
@Override
public void markRemoval(InstanceData instanceData) {
anyToRemove = true;
instanceData.removed = true;
}
}

View file

@ -9,7 +9,6 @@ import com.jozufozu.flywheel.core.shader.WorldProgram;
import com.jozufozu.flywheel.event.BeginFrameEvent;
import com.jozufozu.flywheel.event.RenderLayerEvent;
import com.jozufozu.flywheel.util.ChunkIter;
import com.jozufozu.flywheel.util.TextureBinder;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
@ -100,12 +99,6 @@ public class InstanceWorld {
* Draw the given layer.
*/
public void renderLayer(RenderLayerEvent event) {
event.type.setupRenderState();
TextureBinder.bindActiveTextures();
materialManager.render(event.layer, event.viewProjection, event.camX, event.camY, event.camZ);
event.type.clearRenderState();
}
}

View file

@ -5,10 +5,12 @@ 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 com.jozufozu.flywheel.util.TextureBinder;
import com.mojang.math.Matrix4f;
import net.minecraft.client.renderer.RenderType;
/**
* A group of materials all rendered with the same GL state.
*
@ -18,15 +20,13 @@ import com.mojang.math.Matrix4f;
public class MaterialGroupImpl<P extends WorldProgram> implements MaterialGroup {
protected final MaterialManagerImpl<P> owner;
protected final IRenderState state;
private final ArrayList<MaterialRenderer<P>> renderers = new ArrayList<>();
protected final ArrayList<MaterialRenderer<P>> renderers = new ArrayList<>();
private final Map<MaterialSpec<?>, MaterialImpl<?>> materials = new HashMap<>();
public MaterialGroupImpl(MaterialManagerImpl<P> owner, IRenderState state) {
public MaterialGroupImpl(MaterialManagerImpl<P> owner) {
this.owner = owner;
this.state = state;
}
/**
@ -41,10 +41,13 @@ public class MaterialGroupImpl<P extends WorldProgram> implements MaterialGroup
return (MaterialImpl<D>) materials.computeIfAbsent(spec, this::createInstanceMaterial);
}
public void render(Matrix4f viewProjection, double camX, double camY, double camZ) {
public void render(RenderType type, Matrix4f viewProjection, double camX, double camY, double camZ) {
type.setupRenderState();
TextureBinder.bindActiveTextures();
for (MaterialRenderer<P> renderer : renderers) {
renderer.render(viewProjection, camX, camY, camZ);
}
type.clearRenderState();
}
public void setup(P program) {

View file

@ -10,6 +10,7 @@ import com.jozufozu.flywheel.backend.instancing.GPUInstancer;
import com.jozufozu.flywheel.backend.instancing.InstanceData;
import com.jozufozu.flywheel.backend.instancing.Instancer;
import com.jozufozu.flywheel.backend.model.ModelPool;
import com.jozufozu.flywheel.backend.struct.StructType;
import com.jozufozu.flywheel.core.model.IModel;
/**
@ -20,12 +21,12 @@ public class MaterialImpl<D extends InstanceData> implements Material<D> {
final ModelPool modelPool;
protected final Cache<Object, GPUInstancer<D>> models;
protected final MaterialSpec<D> spec;
protected final StructType<D> type;
public MaterialImpl(MaterialSpec<D> spec) {
this.spec = spec;
this.type = spec.getInstanceType();
modelPool = new ModelPool(spec.getModelFormat(), spec.getModelFormat().getStride() * 64);
modelPool = new ModelPool(spec.getModelFormat(), 64);
this.models = CacheBuilder.newBuilder()
.removalListener(notification -> {
GPUInstancer<?> instancer = (GPUInstancer<?>) notification.getValue();
@ -44,7 +45,7 @@ public class MaterialImpl<D extends InstanceData> implements Material<D> {
@Override
public Instancer<D> model(Object key, Supplier<IModel> modelSupplier) {
try {
return models.get(key, () -> new GPUInstancer<>(modelPool, modelSupplier.get(), spec.getInstanceType()));
return models.get(key, () -> new GPUInstancer<>(type, modelSupplier.get(), modelPool));
} catch (ExecutionException e) {
throw new RuntimeException("error creating instancer", e);
}

View file

@ -1,11 +1,9 @@
package com.jozufozu.flywheel.backend.material;
import com.jozufozu.flywheel.backend.state.IRenderState;
import com.jozufozu.flywheel.backend.state.RenderLayer;
import com.jozufozu.flywheel.backend.state.TextureRenderState;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.core.Vec3i;
import net.minecraft.world.inventory.InventoryMenu;
public interface MaterialManager {
@ -13,34 +11,34 @@ public interface MaterialManager {
* Get a material group that will render in the given layer with the given state.
*
* @param layer The {@link RenderLayer} you want to draw in.
* @param state The {@link IRenderState} you need to draw with.
* @param state The {@link net.minecraft.client.renderer.RenderType} you need to draw with.
* @return A material group whose children will
*/
MaterialGroup state(RenderLayer layer, IRenderState state);
MaterialGroup state(RenderLayer layer, RenderType state);
Vec3i getOriginCoordinate();
default MaterialGroup solid(IRenderState state) {
default MaterialGroup solid(RenderType state) {
return state(RenderLayer.SOLID, state);
}
default MaterialGroup cutout(IRenderState state) {
default MaterialGroup cutout(RenderType state) {
return state(RenderLayer.CUTOUT, state);
}
default MaterialGroup transparent(IRenderState state) {
default MaterialGroup transparent(RenderType state) {
return state(RenderLayer.TRANSPARENT, state);
}
default MaterialGroup defaultSolid() {
return solid(TextureRenderState.get(InventoryMenu.BLOCK_ATLAS));
return solid(RenderType.solid());
}
default MaterialGroup defaultCutout() {
return cutout(TextureRenderState.get(InventoryMenu.BLOCK_ATLAS));
return cutout(RenderType.cutout());
}
default MaterialGroup defaultTransparent() {
return transparent(TextureRenderState.get(InventoryMenu.BLOCK_ATLAS));
return transparent(RenderType.translucent());
}
}

View file

@ -5,7 +5,6 @@ import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;
import com.jozufozu.flywheel.backend.state.IRenderState;
import com.jozufozu.flywheel.backend.state.RenderLayer;
import com.jozufozu.flywheel.core.WorldContext;
import com.jozufozu.flywheel.core.shader.WorldProgram;
@ -13,6 +12,7 @@ import com.jozufozu.flywheel.util.WeakHashSet;
import com.mojang.math.Matrix4f;
import net.minecraft.client.Camera;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Vec3i;
import net.minecraft.resources.ResourceLocation;
@ -28,7 +28,7 @@ public class MaterialManagerImpl<P extends WorldProgram> implements MaterialMana
protected final GroupFactory<P> groupFactory;
protected final boolean ignoreOriginCoordinate;
protected final Map<RenderLayer, Map<IRenderState, MaterialGroupImpl<P>>> layers;
protected final Map<RenderLayer, Map<RenderType, MaterialGroupImpl<P>>> layers;
private final WeakHashSet<OriginShiftListener> listeners;
@ -57,12 +57,12 @@ public class MaterialManagerImpl<P extends WorldProgram> implements MaterialMana
* Get a material group that will render in the given layer with the given state.
*
* @param layer The {@link RenderLayer} you want to draw in.
* @param state The {@link IRenderState} you need to draw with.
* @param state The {@link RenderType} you need to draw with.
* @return A material group whose children will
*/
@Override
public MaterialGroup state(RenderLayer layer, IRenderState state) {
return layers.get(layer).computeIfAbsent(state, this::createGroup);
public MaterialGroup state(RenderLayer layer, RenderType state) {
return layers.get(layer).computeIfAbsent(state, $ -> groupFactory.create(this));
}
/**
@ -83,18 +83,16 @@ public class MaterialManagerImpl<P extends WorldProgram> implements MaterialMana
viewProjection = translate;
}
for (Map.Entry<IRenderState, MaterialGroupImpl<P>> entry : layers.get(layer).entrySet()) {
IRenderState state = entry.getKey();
for (Map.Entry<RenderType, MaterialGroupImpl<P>> entry : layers.get(layer).entrySet()) {
RenderType state = entry.getKey();
MaterialGroupImpl<P> group = entry.getValue();
state.bind();
group.render(viewProjection, camX, camY, camZ);
state.unbind();
group.render(state, viewProjection, camX, camY, camZ);
}
}
public void delete() {
for (Map<IRenderState, MaterialGroupImpl<P>> groups : layers.values()) {
for (Map<RenderType, MaterialGroupImpl<P>> groups : layers.values()) {
groups.values().forEach(MaterialGroupImpl::delete);
}
@ -131,7 +129,7 @@ public class MaterialManagerImpl<P extends WorldProgram> implements MaterialMana
originCoordinate = new BlockPos(cX, cY, cZ);
for (Map<IRenderState, MaterialGroupImpl<P>> groups : layers.values()) {
for (Map<RenderType, MaterialGroupImpl<P>> groups : layers.values()) {
groups.values().forEach(MaterialGroupImpl::clear);
}
@ -139,10 +137,6 @@ public class MaterialManagerImpl<P extends WorldProgram> implements MaterialMana
}
}
private MaterialGroupImpl<P> createGroup(IRenderState state) {
return groupFactory.create(this, state);
}
@FunctionalInterface
public interface OriginShiftListener {
void onOriginShift();
@ -150,7 +144,7 @@ public class MaterialManagerImpl<P extends WorldProgram> implements MaterialMana
@FunctionalInterface
public interface GroupFactory<P extends WorldProgram> {
MaterialGroupImpl<P> create(MaterialManagerImpl<P> materialManager, IRenderState state);
MaterialGroupImpl<P> create(MaterialManagerImpl<P> materialManager);
}
public static class Builder<P extends WorldProgram> {

View file

@ -10,6 +10,7 @@ import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
import com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer;
import com.jozufozu.flywheel.core.model.IModel;
import com.jozufozu.flywheel.core.model.VecBufferConsumer;
import com.jozufozu.flywheel.util.AttribUtil;
public class BufferedModel implements IBufferedModel {
@ -31,7 +32,7 @@ public class BufferedModel implements IBufferedModel {
// mirror it in system memory so we can write to it, and upload our model.
MappedBuffer buffer = vbo.getBuffer(0, model.size());
model.buffer(buffer);
model.buffer(new VecBufferConsumer(buffer, model.format()));
buffer.flush();
vbo.unbind();

View file

@ -11,6 +11,7 @@ import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
import com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer;
import com.jozufozu.flywheel.core.model.IModel;
import com.jozufozu.flywheel.core.model.VecBufferConsumer;
import com.jozufozu.flywheel.util.AttribUtil;
public class ModelPool implements ModelAllocator {
@ -31,7 +32,7 @@ public class ModelPool implements ModelAllocator {
public ModelPool(VertexFormat format, int initialSize) {
this.format = format;
bufferSize = initialSize;
bufferSize = format.getStride() * initialSize;
vbo = new MappedGlBuffer(GlBufferType.ARRAY_BUFFER);
@ -115,8 +116,10 @@ public class ModelPool implements ModelAllocator {
private void uploadAll() {
MappedBuffer buffer = vbo.getBuffer(0, bufferSize);
VecBufferConsumer consumer = new VecBufferConsumer(buffer, format);
for (PooledModel model : models) {
model.model.buffer(buffer);
model.model.buffer(consumer);
if (model.callback != null)
model.callback.onAlloc(model);
}
@ -126,12 +129,13 @@ public class ModelPool implements ModelAllocator {
private void uploadPending() {
MappedBuffer buffer = vbo.getBuffer(0, bufferSize);
VecBufferConsumer consumer = new VecBufferConsumer(buffer, format);
int stride = format.getStride();
for (PooledModel model : pendingUpload) {
int pos = model.first * stride;
buffer.position(pos);
model.model.buffer(buffer);
model.model.buffer(consumer);
if (model.callback != null)
model.callback.onAlloc(model);
}

View file

@ -1,19 +0,0 @@
package com.jozufozu.flywheel.backend.state;
import javax.annotation.Nullable;
import com.jozufozu.flywheel.backend.gl.GlTextureUnit;
import net.minecraft.resources.ResourceLocation;
public interface IRenderState {
void bind();
void unbind();
@Nullable
default ResourceLocation getTexture(GlTextureUnit textureUnit) {
return null;
}
}

View file

@ -1,20 +0,0 @@
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();
}
}

View file

@ -1,81 +0,0 @@
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.resources.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());
}
}
}

View file

@ -1,64 +0,0 @@
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.resources.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().getTextureManager().bindForSetup(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);
}
}

View file

@ -1,7 +1,6 @@
package com.jozufozu.flywheel.backend.struct;
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
/**
* A StructType contains metadata for a specific instance struct that Flywheel can interface with.
@ -19,10 +18,5 @@ public interface StructType<S> {
*/
VertexFormat format();
/**
* Create a {@link StructWriter} that will consume instances of S and write them to the given buffer.
*
* @param backing The buffer that the StructWriter will write to.
*/
StructWriter<S> getWriter(VecBuffer backing);
Writeable<S> asWriteable();
}

View file

@ -0,0 +1,17 @@
package com.jozufozu.flywheel.backend.struct;
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
public interface Writeable<S> extends StructType<S> {
/**
* Create a {@link StructWriter} that will consume instances of S and write them to the given buffer.
*
* @param backing The buffer that the StructWriter will write to.
*/
StructWriter<S> getWriter(VecBuffer backing);
@Override
default Writeable<S> asWriteable() {
return this;
}
}

View file

@ -1,23 +1,34 @@
package com.jozufozu.flywheel.core.crumbling;
import com.jozufozu.flywheel.backend.gl.GlTextureUnit;
import com.jozufozu.flywheel.backend.material.MaterialGroupImpl;
import com.jozufozu.flywheel.backend.material.MaterialManagerImpl;
import com.jozufozu.flywheel.backend.state.IRenderState;
import com.jozufozu.flywheel.backend.material.MaterialRenderer;
import com.jozufozu.flywheel.core.atlas.AtlasInfo;
import com.jozufozu.flywheel.core.atlas.SheetData;
import com.jozufozu.flywheel.util.RenderTextures;
import com.jozufozu.flywheel.util.TextureBinder;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.math.Matrix4f;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.resources.ResourceLocation;
public class CrumblingGroup<P extends CrumblingProgram> extends MaterialGroupImpl<P> {
private final int width;
private final int height;
private int width;
private int height;
public CrumblingGroup(MaterialManagerImpl<P> owner, IRenderState state) {
super(owner, state);
public CrumblingGroup(MaterialManagerImpl<P> owner) {
super(owner);
}
ResourceLocation texture = state.getTexture(GlTextureUnit.T0);
@Override
public void render(RenderType type, Matrix4f viewProjection, double camX, double camY, double camZ) {
type.setupRenderState();
int renderTex = RenderSystem.getShaderTexture(0);
ResourceLocation texture = RenderTextures.getShaderTexture(0);
if (texture != null) {
SheetData atlasData = AtlasInfo.getAtlasData(texture);
@ -27,6 +38,22 @@ public class CrumblingGroup<P extends CrumblingProgram> extends MaterialGroupImp
} else {
width = height = 256;
}
type.clearRenderState();
CrumblingRenderer._currentLayer.setupRenderState();
int breakingTex = RenderSystem.getShaderTexture(0);
RenderSystem.setShaderTexture(0, renderTex);
RenderSystem.setShaderTexture(4, breakingTex);
TextureBinder.bindActiveTextures();
for (MaterialRenderer<P> renderer : renderers) {
renderer.render(viewProjection, camX, camY, camZ);
}
CrumblingRenderer._currentLayer.clearRenderState();
}
@Override

View file

@ -1,14 +1,12 @@
package com.jozufozu.flywheel.core.crumbling;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
import static org.lwjgl.opengl.GL11.glBindTexture;
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.gl.error.GlError;
import com.jozufozu.flywheel.backend.instancing.InstanceManager;
import com.jozufozu.flywheel.backend.material.MaterialManagerImpl;
import com.jozufozu.flywheel.backend.state.RenderLayer;
@ -17,6 +15,7 @@ import com.jozufozu.flywheel.event.ReloadRenderersEvent;
import com.jozufozu.flywheel.mixin.LevelRendererAccessor;
import com.jozufozu.flywheel.util.Lazy;
import com.jozufozu.flywheel.util.Pair;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.math.Matrix4f;
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
@ -44,6 +43,8 @@ import net.minecraftforge.fml.common.Mod;
@Mod.EventBusSubscriber(Dist.CLIENT)
public class CrumblingRenderer {
static RenderType _currentLayer;
private static final Lazy<State> STATE;
private static final Lazy.KillSwitch<State> INVALIDATOR;
@ -63,40 +64,31 @@ public class CrumblingRenderer {
if (activeStages.isEmpty()) return;
State state = STATE.get();
RenderType layer = ModelBakery.DESTROY_TYPES.get(0);
InstanceManager<BlockEntity> renderer = state.instanceManager;
InstanceManager<BlockEntity> instanceManager = state.instanceManager;
MaterialManagerImpl<CrumblingProgram> materials = state.materialManager;
TextureManager textureManager = Minecraft.getInstance().getTextureManager();
Camera info = Minecraft.getInstance().gameRenderer.getMainCamera();
MaterialManagerImpl<CrumblingProgram> materials = state.materialManager;
layer.setupRenderState();
for (Int2ObjectMap.Entry<List<BlockEntity>> stage : activeStages.int2ObjectEntrySet()) {
int i = stage.getIntKey();
AbstractTexture breaking = textureManager.getTexture(ModelBakery.BREAKING_LOCATIONS.get(i));
_currentLayer = ModelBakery.DESTROY_TYPES.get(stage.getIntKey());
// something about when we call this means that the textures are not ready for use on the first frame they should appear
if (breaking != null) {
stage.getValue().forEach(renderer::add);
if (_currentLayer != null) {
stage.getValue().forEach(instanceManager::add);
renderer.beginFrame(info);
instanceManager.beginFrame(info);
GlTextureUnit.T4.makeActive();
glBindTexture(GL_TEXTURE_2D, breaking.getId());
materials.render(RenderLayer.SOLID, viewProjection, cameraX, cameraY, cameraZ);
renderer.invalidate();
instanceManager.invalidate();
}
}
layer.clearRenderState();
GlTextureUnit.T0.makeActive();
AbstractTexture breaking = textureManager.getTexture(ModelBakery.BREAKING_LOCATIONS.get(0));
if (breaking != null) glBindTexture(GL_TEXTURE_2D, breaking.getId());
if (breaking != null) RenderSystem.bindTexture(breaking.getId());
}
/**

View file

@ -2,12 +2,12 @@ package com.jozufozu.flywheel.core.materials.model;
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
import com.jozufozu.flywheel.backend.struct.StructType;
import com.jozufozu.flywheel.backend.struct.StructWriter;
import com.jozufozu.flywheel.backend.struct.Writeable;
import com.jozufozu.flywheel.core.Formats;
import com.jozufozu.flywheel.core.materials.model.writer.UnsafeModelWriter;
public class ModelType implements StructType<ModelData> {
public class ModelType implements Writeable<ModelData> {
@Override
public ModelData create() {

View file

@ -2,12 +2,12 @@ package com.jozufozu.flywheel.core.materials.oriented;
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
import com.jozufozu.flywheel.backend.struct.StructType;
import com.jozufozu.flywheel.backend.struct.StructWriter;
import com.jozufozu.flywheel.backend.struct.Writeable;
import com.jozufozu.flywheel.core.Formats;
import com.jozufozu.flywheel.core.materials.oriented.writer.UnsafeOrientedWriter;
public class OrientedType implements StructType<OrientedData> {
public class OrientedType implements Writeable<OrientedData> {
@Override
public OrientedData create() {

View file

@ -1,7 +1,5 @@
package com.jozufozu.flywheel.core.model;
import static com.jozufozu.flywheel.util.RenderMath.nb;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
@ -12,10 +10,10 @@ import java.util.Random;
import org.lwjgl.system.MemoryStack;
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
import com.jozufozu.flywheel.core.Formats;
import com.jozufozu.flywheel.util.VirtualEmptyModelData;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.VertexConsumer;
import com.mojang.math.Vector3f;
import net.minecraft.client.Minecraft;
@ -62,7 +60,7 @@ public class BakedModelModel implements IModel {
}
@Override
public void buffer(VecBuffer buffer) {
public void buffer(VertexConsumer buffer) {
Minecraft mc = Minecraft.getInstance();
@ -118,9 +116,10 @@ public class BakedModelModel implements IModel {
float u = bytebuffer.getFloat(16);
float v = bytebuffer.getFloat(20);
buffer.putVec3(f, f1, f2);
buffer.putVec3(nb(normal.x()), nb(normal.y()), nb(normal.z()));
buffer.putVec2(u, v);
buffer.vertex(f, f1, f2);
buffer.normal(normal.x(), normal.y(), normal.z());
buffer.uv(u, v);
buffer.endVertex();
}
}
}

View file

@ -3,13 +3,14 @@ package com.jozufozu.flywheel.core.model;
import java.util.Arrays;
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
import com.jozufozu.flywheel.core.Formats;
import com.jozufozu.flywheel.util.BufferBuilderReader;
import com.jozufozu.flywheel.util.RenderMath;
import com.jozufozu.flywheel.util.VirtualEmptyModelData;
import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
@ -61,16 +62,18 @@ public class BlockModel implements IModel {
}
@Override
public void buffer(VecBuffer buffer) {
public void buffer(VertexConsumer buffer) {
int vertexCount = vertexCount();
for (int i = 0; i < vertexCount; i++) {
buffer.putVec3(reader.getX(i), reader.getY(i), reader.getZ(i));
buffer.vertex(reader.getX(i), reader.getY(i), reader.getZ(i));
buffer.putVec3(reader.getNX(i), reader.getNY(i), reader.getNZ(i));
buffer.normal(RenderMath.f(reader.getNX(i)), RenderMath.f(reader.getNY(i)), RenderMath.f(reader.getNZ(i)));
buffer.putVec2(reader.getU(i), reader.getV(i));
buffer.uv(reader.getU(i), reader.getV(i));
buffer.endVertex();
}
}

View file

@ -1,9 +1,9 @@
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;
import com.jozufozu.flywheel.core.QuadConverter;
import com.mojang.blaze3d.vertex.VertexConsumer;
/**
* A model that can be rendered by flywheel.
@ -35,7 +35,7 @@ public interface IModel {
/**
* Copy this model into the given buffer.
*/
void buffer(VecBuffer buffer);
void buffer(VertexConsumer buffer);
/**
* @return The number of vertices the model has.

View file

@ -3,8 +3,8 @@ package com.jozufozu.flywheel.core.model;
import java.util.List;
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
import com.jozufozu.flywheel.core.Formats;
import com.mojang.blaze3d.vertex.VertexConsumer;
public class ModelPart implements IModel {
@ -33,7 +33,7 @@ public class ModelPart implements IModel {
}
@Override
public void buffer(VecBuffer buffer) {
public void buffer(VertexConsumer buffer) {
for (PartBuilder.CuboidBuilder cuboid : cuboids) {
cuboid.buffer(buffer);
}

View file

@ -8,6 +8,7 @@ import java.util.List;
import java.util.Set;
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
import com.mojang.blaze3d.vertex.VertexConsumer;
import com.mojang.math.Matrix3f;
import com.mojang.math.Quaternion;
import com.mojang.math.Vector3f;
@ -156,7 +157,7 @@ public class PartBuilder {
return visibleFaces.size() * 4;
}
public void buffer(VecBuffer buffer) {
public void buffer(VertexConsumer buffer) {
float sizeX = posX2 - posX1;
float sizeY = posY2 - posY1;
@ -231,12 +232,11 @@ public class PartBuilder {
}
}
public void quad(VecBuffer buffer, Vector3f[] vertices, float minU, float minV, float maxU, float maxV, Vector3f normal) {
buffer.putVec3(vertices[0].x(), vertices[0].y(), vertices[0].z()).putVec3(nb(normal.x()), nb(normal.y()), nb(normal.z())).putVec2(maxU, minV);
buffer.putVec3(vertices[1].x(), vertices[1].y(), vertices[1].z()).putVec3(nb(normal.x()), nb(normal.y()), nb(normal.z())).putVec2(minU, minV);
buffer.putVec3(vertices[2].x(), vertices[2].y(), vertices[2].z()).putVec3(nb(normal.x()), nb(normal.y()), nb(normal.z())).putVec2(minU, maxV);
buffer.putVec3(vertices[3].x(), vertices[3].y(), vertices[3].z()).putVec3(nb(normal.x()), nb(normal.y()), nb(normal.z())).putVec2(maxU, maxV);
public void quad(VertexConsumer buffer, Vector3f[] vertices, float minU, float minV, float maxU, float maxV, Vector3f normal) {
buffer.vertex(vertices[0].x(), vertices[0].y(), vertices[0].z()).normal(normal.x(), normal.y(), normal.z()).uv(maxU, minV).endVertex();
buffer.vertex(vertices[1].x(), vertices[1].y(), vertices[1].z()).normal(normal.x(), normal.y(), normal.z()).uv(minU, minV).endVertex();
buffer.vertex(vertices[2].x(), vertices[2].y(), vertices[2].z()).normal(normal.x(), normal.y(), normal.z()).uv(minU, maxV).endVertex();
buffer.vertex(vertices[3].x(), vertices[3].y(), vertices[3].z()).normal(normal.x(), normal.y(), normal.z()).uv(maxU, maxV).endVertex();
}

View file

@ -0,0 +1,69 @@
package com.jozufozu.flywheel.core.model;
import static com.jozufozu.flywheel.util.RenderMath.nb;
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
import com.mojang.blaze3d.vertex.VertexConsumer;
public class VecBufferConsumer implements VertexConsumer {
private final VecBuffer buffer;
private final VertexFormat format;
public VecBufferConsumer(VecBuffer buffer, VertexFormat format) {
this.buffer = buffer;
this.format = format;
}
@Override
public VertexConsumer vertex(double v, double v1, double v2) {
buffer.putVec3((float) v, (float) v1, (float) v2);
return this;
}
@Override
public VertexConsumer color(int i, int i1, int i2, int i3) {
buffer.putColor(i, i1, i2, i3);
return this;
}
@Override
public VertexConsumer uv(float v, float v1) {
buffer.putVec2(v, v1);
return this;
}
@Override
public VertexConsumer overlayCoords(int i, int i1) {
return this;
}
@Override
public VertexConsumer uv2(int i, int i1) {
buffer.putVec2((byte) i, (byte) i1);
return this;
}
@Override
public VertexConsumer normal(float v, float v1, float v2) {
buffer.putVec3(nb(v), nb(v1), nb(v2));
return this;
}
@Override
public void endVertex() {
}
@Override
public void defaultColor(int i, int i1, int i2, int i3) {
}
@Override
public void unsetDefaultColor() {
}
}

View file

@ -3,9 +3,10 @@ package com.jozufozu.flywheel.core.model;
import java.util.Collection;
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
import com.jozufozu.flywheel.core.Formats;
import com.jozufozu.flywheel.util.BufferBuilderReader;
import com.jozufozu.flywheel.util.RenderMath;
import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.RenderType;
@ -28,22 +29,24 @@ public class WorldModel implements IModel {
}
@Override
public void buffer(VecBuffer vertices) {
public void buffer(VertexConsumer vertices) {
for (int i = 0; i < vertexCount(); i++) {
vertices.putVec3(reader.getX(i), reader.getY(i), reader.getZ(i));
vertices.vertex(reader.getX(i), reader.getY(i), reader.getZ(i));
vertices.putVec3(reader.getNX(i), reader.getNY(i), reader.getNZ(i));
vertices.normal(RenderMath.f(reader.getNX(i)), RenderMath.f(reader.getNY(i)), RenderMath.f(reader.getNZ(i)));
vertices.putVec2(reader.getU(i), reader.getV(i));
vertices.uv(reader.getU(i), reader.getV(i));
vertices.putColor(reader.getR(i), reader.getG(i), reader.getB(i), reader.getA(i));
vertices.color(reader.getR(i), reader.getG(i), reader.getB(i), reader.getA(i));
int light = reader.getLight(i);
byte block = (byte) (LightTexture.block(light) << 4);
byte sky = (byte) (LightTexture.sky(light) << 4);
vertices.putVec2(block, sky);
vertices.uv2(block, sky);
vertices.endVertex();
}
}

View file

@ -33,7 +33,7 @@ public class WorldProgram extends ExtensibleGlProgram {
protected void registerSamplers() {
uBlockAtlas = setSamplerBinding("uBlockAtlas", 0);
uLightMap = setSamplerBinding("uLightMap", 1);
uLightMap = setSamplerBinding("uLightMap", 2);
}
public void uploadViewProjection(Matrix4f viewProjection) {

View file

@ -69,4 +69,9 @@ public class RenderLayerEvent extends Event {
public double getCamZ() {
return camZ;
}
@Override
public String toString() {
return "RenderLayerEvent{" + "world=" + world + ", type=" + type + ", stack=" + stack + ", viewProjection=" + viewProjection + ", buffers=" + buffers + ", camX=" + camX + ", camY=" + camY + ", camZ=" + camZ + ", layer=" + layer + '}';
}
}

View file

@ -0,0 +1,20 @@
package com.jozufozu.flywheel.mixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.jozufozu.flywheel.util.RenderTextures;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.resources.ResourceLocation;
@Mixin(RenderSystem.class)
public class RenderTexturesMixin {
@Inject(method = "_setShaderTexture(ILnet/minecraft/resources/ResourceLocation;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/texture/TextureManager;getTexture(Lnet/minecraft/resources/ResourceLocation;)Lnet/minecraft/client/renderer/texture/AbstractTexture;"))
private static void storeTextureLoc(int pShaderTexture, ResourceLocation pTextureId, CallbackInfo ci) {
RenderTextures._setShaderTexture(pShaderTexture, pTextureId);
}
}

View file

@ -1,59 +0,0 @@
package com.jozufozu.flywheel.mixin;
import java.util.List;
import java.util.Map;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import com.jozufozu.flywheel.util.TextureBinder;
import com.mojang.blaze3d.pipeline.RenderTarget;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.renderer.ShaderInstance;
import net.minecraft.client.renderer.texture.AbstractTexture;
@Mixin(ShaderInstance.class)
public class ShaderInstanceMixin implements TextureBinder {
@Shadow
@Final
private List<Integer> samplerLocations;
@Shadow
@Final
private List<String> samplerNames;
@Shadow
@Final
private Map<String, Object> samplerMap;
@Override
public void bind() {
int i = GlStateManager._getActiveTexture();
for(int j = 0; j < samplerLocations.size(); ++j) {
String s = samplerNames.get(j);
if (samplerMap.get(s) != null) {
RenderSystem.activeTexture('\u84c0' + j);
RenderSystem.enableTexture();
Object object = this.samplerMap.get(s);
int l = -1;
if (object instanceof RenderTarget) {
l = ((RenderTarget)object).getColorTextureId();
} else if (object instanceof AbstractTexture) {
l = ((AbstractTexture)object).getId();
} else if (object instanceof Integer) {
l = (Integer)object;
}
if (l != -1) {
RenderSystem.bindTexture(l);
}
}
}
GlStateManager._activeTexture(i);
}
}

View file

@ -0,0 +1,26 @@
package com.jozufozu.flywheel.util;
import javax.annotation.Nullable;
import net.minecraft.resources.ResourceLocation;
/**
* Helper class to keep track of what texture atlases are bound to what texture units.
*
* <p>
* Works with {@link com.jozufozu.flywheel.mixin.RenderTexturesMixin}.
* </p>
*/
public class RenderTextures {
private static final ResourceLocation[] shaderTextures = new ResourceLocation[12];
@Nullable
public static ResourceLocation getShaderTexture(int pShaderTexture) {
return shaderTextures[pShaderTexture];
}
public static void _setShaderTexture(int pShaderTexture, ResourceLocation pTextureId) {
shaderTextures[pShaderTexture] = pTextureId;
}
}

View file

@ -1,30 +1,29 @@
package com.jozufozu.flywheel.util;
import org.lwjgl.opengl.GL32;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.ShaderInstance;
/**
* This is a silly hack that's needed because flywheel does things too different from vanilla.
*
* <p>
* When a {@link RenderType} is setup, the associated textures are passed to the active ShaderInstance, and properly
* bound later on when {@link ShaderInstance#apply()} is called.
* This interface (and {@link com.jozufozu.flywheel.mixin.ShaderInstanceMixin mixin} binds textures to opengl
* without binding the shader.
* When a {@link RenderType} is setup, the associated textures are "bound" within RenderSystem, but not actually
* bound via opengl. This class provides a helper function to forward the bindings to opengl.
* </p>
*/
public interface TextureBinder {
public class TextureBinder {
/**
* Call this after calling {@link RenderType#setupRenderState()}.
*/
static void bindActiveTextures() {
TextureBinder shader = (TextureBinder) RenderSystem.getShader();
if (shader != null)
shader.bind();
public static void bindActiveTextures() {
for (int i = 0; i < 12; i++) {
int shaderTexture = RenderSystem.getShaderTexture(i);
RenderSystem.activeTexture(GL32.GL_TEXTURE0 + i);
RenderSystem.bindTexture(shaderTexture);
}
}
void bind();
}

View file

@ -7,7 +7,6 @@ import javax.annotation.Nonnull;
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.backend.state.TextureRenderState;
import com.jozufozu.flywheel.core.Materials;
import com.jozufozu.flywheel.core.materials.model.ModelData;
import com.jozufozu.flywheel.core.materials.oriented.OrientedData;
@ -17,6 +16,7 @@ import com.mojang.math.Quaternion;
import com.mojang.math.Vector3f;
import it.unimi.dsi.fastutil.floats.Float2FloatFunction;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.Sheets;
import net.minecraft.client.resources.model.Material;
import net.minecraft.world.level.block.AbstractChestBlock;
@ -111,7 +111,7 @@ public class ChestInstance<T extends BlockEntity & LidBlockEntity> extends TileE
private OrientedData baseInstance() {
return materialManager.solid(TextureRenderState.get(renderMaterial.atlasLocation()))
return materialManager.solid(RenderType.entitySolid(renderMaterial.atlasLocation()))
.material(Materials.ORIENTED)
.model("base_" + renderMaterial.texture(), this::getBaseModel)
.createInstance();
@ -119,7 +119,7 @@ public class ChestInstance<T extends BlockEntity & LidBlockEntity> extends TileE
private ModelData lidInstance() {
return materialManager.solid(TextureRenderState.get(renderMaterial.atlasLocation()))
return materialManager.solid(RenderType.entitySolid(renderMaterial.atlasLocation()))
.material(Materials.TRANSFORMED)
.model("lid_" + renderMaterial.texture(), this::getLidModel)
.createInstance();

View file

@ -4,7 +4,6 @@ import com.jozufozu.flywheel.backend.instancing.IDynamicInstance;
import com.jozufozu.flywheel.backend.instancing.ITickableInstance;
import com.jozufozu.flywheel.backend.instancing.entity.EntityInstance;
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.model.ModelData;
import com.jozufozu.flywheel.core.model.IModel;
@ -13,6 +12,7 @@ import com.jozufozu.flywheel.util.AnimationTickHolder;
import com.jozufozu.flywheel.util.transform.MatrixTransformStack;
import com.mojang.math.Vector3f;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.core.Vec3i;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth;
@ -147,7 +147,7 @@ public class MinecartInstance<T extends AbstractMinecart> extends EntityInstance
}
private ModelData getBody() {
return materialManager.solid(TextureRenderState.get(MINECART_LOCATION))
return materialManager.solid(RenderType.entitySolid(MINECART_LOCATION))
.material(Materials.TRANSFORMED)
.model(entity.getType(), this::getBodyModel)
.createInstance();

View file

@ -1,14 +0,0 @@
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.Sheets;
public class RenderStates {
public static final IRenderState SHULKER = RenderState.builder()
.texture(Sheets.SHULKER_SHEET)
.addState(NoCullRenderState.INSTANCE)
.build();
}

View file

@ -11,6 +11,7 @@ import com.jozufozu.flywheel.util.transform.MatrixTransformStack;
import com.mojang.math.Quaternion;
import com.mojang.math.Vector3f;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.Sheets;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.Direction;
@ -85,14 +86,14 @@ public class ShulkerBoxInstance extends TileEntityInstance<ShulkerBoxBlockEntity
}
private ModelData makeBaseInstance() {
return materialManager.cutout(RenderStates.SHULKER)
return materialManager.cutout(RenderType.entityCutout(Sheets.SHULKER_SHEET))
.material(Materials.TRANSFORMED)
.model("base_" + texture.getName(), this::makeBaseModel)
.createInstance();
}
private ModelData makeLidInstance() {
return materialManager.cutout(RenderStates.SHULKER)
return materialManager.cutout(RenderType.entityCutout(Sheets.SHULKER_SHEET))
.material(Materials.TRANSFORMED)
.model("lid_" + texture.getName(), this::makeLidModel)
.createInstance();

View file

@ -1,30 +1,30 @@
{
"required": true,
"minVersion": "0.8",
"package": "com.jozufozu.flywheel.mixin",
"compatibilityLevel": "JAVA_16",
"refmap": "flywheel.refmap.json",
"client": [
"CancelEntityRenderMixin",
"ChunkRebuildHooksMixin",
"FixFabulousDepthMixin",
"InstanceAddMixin",
"InstanceRemoveMixin",
"LeakChunkStorageArrayMixin",
"LevelRendererAccessor",
"PausedPartialTickAccessor",
"RenderHooksMixin",
"ShaderCloseMixin",
"ShaderInstanceMixin",
"atlas.AtlasDataMixin",
"atlas.SheetDataAccessor",
"light.LightUpdateMixin",
"light.NetworkLightUpdateMixin",
"matrix.Matrix3fMixin",
"matrix.Matrix4fMixin",
"matrix.PoseStackMixin"
],
"injectors": {
"defaultRequire": 1
}
"required": true,
"minVersion": "0.8",
"package": "com.jozufozu.flywheel.mixin",
"compatibilityLevel": "JAVA_16",
"refmap": "flywheel.refmap.json",
"client": [
"CancelEntityRenderMixin",
"ChunkRebuildHooksMixin",
"FixFabulousDepthMixin",
"InstanceAddMixin",
"InstanceRemoveMixin",
"LeakChunkStorageArrayMixin",
"LevelRendererAccessor",
"PausedPartialTickAccessor",
"RenderHooksMixin",
"RenderTexturesMixin",
"ShaderCloseMixin",
"atlas.AtlasDataMixin",
"atlas.SheetDataAccessor",
"light.LightUpdateMixin",
"light.NetworkLightUpdateMixin",
"matrix.Matrix3fMixin",
"matrix.Matrix4fMixin",
"matrix.PoseStackMixin"
],
"injectors": {
"defaultRequire": 1
}
}