MaterialManager and MaterialGroup refactor

- Material manager builder
 - No more overload render method/IProgramCallback
 - MaterialRenderers accept a Program consumer instead
This commit is contained in:
Jozufozu 2021-07-23 23:45:31 -07:00
parent 38418b2f91
commit fd96df1abe
7 changed files with 62 additions and 69 deletions

View file

@ -30,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)));

View file

@ -6,10 +6,8 @@ import java.util.Map;
import com.jozufozu.flywheel.backend.instancing.InstanceData;
import com.jozufozu.flywheel.backend.state.IRenderState;
import com.jozufozu.flywheel.core.shader.IProgramCallback;
import com.jozufozu.flywheel.core.shader.WorldProgram;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.util.math.vector.Matrix4f;
public class MaterialGroup<P extends WorldProgram> {
@ -26,12 +24,16 @@ public class MaterialGroup<P extends WorldProgram> {
this.state = state;
}
public void render(Matrix4f viewProjection, double camX, double camY, double camZ, IProgramCallback<P> callback) {
public void render(Matrix4f viewProjection, double camX, double camY, double camZ) {
for (MaterialRenderer<P> renderer : renderers) {
renderer.render(viewProjection, camX, camY, camZ, callback);
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);
@ -40,7 +42,7 @@ public class MaterialGroup<P extends WorldProgram> {
private InstanceMaterial<?> createInstanceMaterial(MaterialSpec<?> type) {
InstanceMaterial<?> material = new InstanceMaterial<>(owner::getOriginCoordinate, type);
this.renderers.add(new MaterialRenderer<>(owner.getProgram(type.getProgramName()), material));
this.renderers.add(new MaterialRenderer<>(owner.getProgram(type.getProgramName()), material, this::setup));
return material;
}

View file

@ -1,5 +1,6 @@
package com.jozufozu.flywheel.backend.material;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;
@ -12,7 +13,6 @@ 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;
@ -29,23 +29,32 @@ public class MaterialManager<P extends WorldProgram> {
public static int MAX_ORIGIN_DISTANCE = 100;
protected BlockPos originCoordinate = BlockPos.ZERO;
protected final WorldContext<P> context;
protected GroupFactory<P> groupFactory;
protected boolean ignoreOriginCoordinate;
protected final GroupFactory<P> groupFactory;
protected final boolean ignoreOriginCoordinate;
protected final Map<RenderLayer, Map<IRenderState, MaterialGroup<P>>> layers;
protected BlockPos originCoordinate = BlockPos.ZERO;
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.layers = new HashMap<>();
this.listeners = new WeakHashSet<>();
this.groupFactory = MaterialGroup::new;
this.groupFactory = groupFactory;
this.layers = new EnumMap<>(RenderLayer.class);
for (RenderLayer value : RenderLayer.values()) {
layers.put(value, new HashMap<>());
}
@ -53,20 +62,10 @@ public class MaterialManager<P extends WorldProgram> {
/**
* Render every model for every material.
* @param layer Which vanilla {@link RenderType} is being drawn?
* @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) {
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(RenderLayer layer, Matrix4f viewProjection, double camX, double camY, double camZ, IProgramCallback<P> callback) {
if (!ignoreOriginCoordinate) {
camX -= originCoordinate.getX();
camY -= originCoordinate.getY();
@ -84,7 +83,7 @@ public class MaterialManager<P extends WorldProgram> {
MaterialGroup<P> group = entry.getValue();
state.bind();
group.render(viewProjection, camX, camY, camZ, callback);
group.render(viewProjection, camX, camY, camZ);
state.unbind();
}
}
@ -148,16 +147,6 @@ public class MaterialManager<P extends WorldProgram> {
return context.getProgramSupplier(name);
}
public MaterialManager<P> setIgnoreOriginCoordinate(boolean ignoreOriginCoordinate) {
this.ignoreOriginCoordinate = ignoreOriginCoordinate;
return this;
}
public MaterialManager<P> setGroupFactory(GroupFactory<P> factory) {
this.groupFactory = factory;
return this;
}
public Vector3i getOriginCoordinate() {
return originCoordinate;
}
@ -200,4 +189,28 @@ public class MaterialManager<P extends WorldProgram> {
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);
}
}
}

View file

@ -1,9 +1,9 @@
package com.jozufozu.flywheel.backend.material;
import java.util.function.Consumer;
import java.util.function.Supplier;
import com.jozufozu.flywheel.backend.instancing.Instancer;
import com.jozufozu.flywheel.core.shader.IProgramCallback;
import com.jozufozu.flywheel.core.shader.WorldProgram;
import net.minecraft.util.math.vector.Matrix4f;
@ -13,12 +13,15 @@ public class MaterialRenderer<P extends WorldProgram> {
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(Matrix4f viewProjection, double camX, double camY, double camZ, IProgramCallback<P> setup) {
public void render(Matrix4f viewProjection, double camX, double camY, double camZ) {
if (material.nothingToRender()) return;
P program = this.program.get();
@ -27,7 +30,7 @@ public class MaterialRenderer<P extends WorldProgram> {
program.uploadViewProjection(viewProjection);
program.uploadCameraPos(camX, camY, camZ);
if (setup != null) setup.call(program);
setupFunc.accept(program);
material.forEachInstancer(Instancer::render);
}

View file

@ -1,15 +1,13 @@
package com.jozufozu.flywheel.core.crumbling;
import com.jozufozu.flywheel.backend.gl.GlTextureUnit;
import com.jozufozu.flywheel.backend.material.MaterialManager;
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 com.jozufozu.flywheel.core.shader.IProgramCallback;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.vector.Matrix4f;
public class CrumblingGroup<P extends CrumblingProgram> extends MaterialGroup<P> {
@ -32,11 +30,7 @@ public class CrumblingGroup<P extends CrumblingProgram> extends MaterialGroup<P>
}
@Override
public void render(Matrix4f viewProjection, double camX, double camY, double camZ, IProgramCallback<P> callback) {
super.render(viewProjection, camX, camY, camZ, ((IProgramCallback<P>) this::setup).andThen(callback));
}
private void setup(P p) {
public void setup(P p) {
p.setAtlasSize(width, height);
}
}

View file

@ -148,7 +148,9 @@ public class CrumblingRenderer {
private final InstanceManager<TileEntity> instanceManager;
private State() {
materialManager = new MaterialManager<>(Contexts.CRUMBLING).setGroupFactory(CrumblingGroup::new);
materialManager = MaterialManager.builder(Contexts.CRUMBLING)
.setGroupFactory(CrumblingGroup::new)
.build();
instanceManager = new CrumblingInstanceManager(materialManager);
}

View file

@ -1,21 +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) {
if (other == null) return this;
return program -> {
call(program);
other.call(program);
};
}
}