mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-01-07 12:56:31 +01:00
Crumbling away
- Fix and improve crumbling rendering - Rename Batched to BatchedStructType and Instanced to InstancedStructType - Normalize flw_vertexNormal in context/common.vert - Add TODO and FIXME comments
This commit is contained in:
parent
9886dca1e2
commit
2632cd385c
27 changed files with 138 additions and 292 deletions
|
@ -2,7 +2,6 @@ package com.jozufozu.flywheel.api.struct;
|
|||
|
||||
import com.jozufozu.flywheel.core.model.ModelTransformer;
|
||||
|
||||
public interface Batched<S> extends StructType<S> {
|
||||
|
||||
public interface BatchedStructType<S> extends StructType<S> {
|
||||
void transform(S d, ModelTransformer.Params b);
|
||||
}
|
|
@ -3,7 +3,7 @@ package com.jozufozu.flywheel.api.struct;
|
|||
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
|
||||
import com.jozufozu.flywheel.core.source.FileResolution;
|
||||
|
||||
public interface Instanced<S> extends StructType<S> {
|
||||
public interface InstancedStructType<S> extends StructType<S> {
|
||||
/**
|
||||
* Create a {@link StructWriter} that will consume instances of S and write them to the given buffer.
|
||||
*
|
|
@ -30,6 +30,7 @@ public class GlShader extends GlObject {
|
|||
GlCompat.safeShaderSource(handle, source);
|
||||
GL20.glCompileShader(handle);
|
||||
|
||||
// TODO: control this via a JVM flag or other
|
||||
dumpSource(source, type);
|
||||
|
||||
// String log = GL20.glGetShaderInfoLog(handle);
|
||||
|
|
|
@ -141,19 +141,19 @@ public abstract class InstanceManager<T> implements InstancingEngine.OriginShift
|
|||
if (tick.shouldUpdate(dX, dY, dZ)) instance.tick();
|
||||
}
|
||||
|
||||
public void beginFrame(TaskEngine taskEngine, Camera info) {
|
||||
public void beginFrame(TaskEngine taskEngine, Camera camera) {
|
||||
frame.tick();
|
||||
processQueuedAdditions();
|
||||
|
||||
Vector3f look = info.getLookVector();
|
||||
Vector3f look = camera.getLookVector();
|
||||
float lookX = look.x();
|
||||
float lookY = look.y();
|
||||
float lookZ = look.z();
|
||||
|
||||
// integer camera pos
|
||||
int cX = (int) info.getPosition().x;
|
||||
int cY = (int) info.getPosition().y;
|
||||
int cZ = (int) info.getPosition().z;
|
||||
int cX = (int) camera.getPosition().x;
|
||||
int cY = (int) camera.getPosition().y;
|
||||
int cZ = (int) camera.getPosition().z;
|
||||
|
||||
ArrayList<DynamicInstance> instances = new ArrayList<>(dynamicInstances.values());
|
||||
int incr = 500;
|
||||
|
|
|
@ -5,7 +5,7 @@ import java.util.Map;
|
|||
|
||||
import com.jozufozu.flywheel.api.InstanceData;
|
||||
import com.jozufozu.flywheel.api.MaterialGroup;
|
||||
import com.jozufozu.flywheel.api.struct.Batched;
|
||||
import com.jozufozu.flywheel.api.struct.BatchedStructType;
|
||||
import com.jozufozu.flywheel.api.struct.StructType;
|
||||
import com.jozufozu.flywheel.backend.instancing.BatchDrawingTracker;
|
||||
import com.jozufozu.flywheel.backend.instancing.TaskEngine;
|
||||
|
@ -17,7 +17,7 @@ public class BatchedMaterialGroup implements MaterialGroup {
|
|||
|
||||
protected final RenderType state;
|
||||
|
||||
private final Map<Batched<? extends InstanceData>, CPUInstancerFactory<?>> materials = new HashMap<>();
|
||||
private final Map<BatchedStructType<? extends InstanceData>, CPUInstancerFactory<?>> materials = new HashMap<>();
|
||||
private int vertexCount;
|
||||
private int instanceCount;
|
||||
|
||||
|
@ -28,7 +28,7 @@ public class BatchedMaterialGroup implements MaterialGroup {
|
|||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <D extends InstanceData> CPUInstancerFactory<D> material(StructType<D> type) {
|
||||
if (type instanceof Batched<D> batched) {
|
||||
if (type instanceof BatchedStructType<D> batched) {
|
||||
return (CPUInstancerFactory<D>) materials.computeIfAbsent(batched, CPUInstancerFactory::new);
|
||||
} else {
|
||||
throw new ClassCastException("Cannot use type '" + type + "' with CPU instancing.");
|
||||
|
|
|
@ -5,7 +5,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
import com.jozufozu.flywheel.api.InstanceData;
|
||||
import com.jozufozu.flywheel.api.struct.Batched;
|
||||
import com.jozufozu.flywheel.api.struct.BatchedStructType;
|
||||
import com.jozufozu.flywheel.api.struct.StructType;
|
||||
import com.jozufozu.flywheel.backend.instancing.BatchDrawingTracker;
|
||||
import com.jozufozu.flywheel.backend.instancing.Engine;
|
||||
|
@ -21,13 +21,13 @@ import net.minecraft.core.Vec3i;
|
|||
|
||||
public class BatchingEngine implements Engine {
|
||||
|
||||
private final Map<Batched<? extends InstanceData>, CPUInstancerFactory<?>> factories = new HashMap<>();
|
||||
private final Map<BatchedStructType<? extends InstanceData>, CPUInstancerFactory<?>> factories = new HashMap<>();
|
||||
private final BatchDrawingTracker batchTracker = new BatchDrawingTracker();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <D extends InstanceData> CPUInstancerFactory<D> factory(StructType<D> type) {
|
||||
if (type instanceof Batched<D> batched) {
|
||||
if (type instanceof BatchedStructType<D> batched) {
|
||||
return (CPUInstancerFactory<D>) factories.computeIfAbsent(batched, CPUInstancerFactory::new);
|
||||
} else {
|
||||
throw new ClassCastException("Cannot use type '" + type + "' with CPU instancing.");
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package com.jozufozu.flywheel.backend.instancing.batching;
|
||||
|
||||
import com.jozufozu.flywheel.api.InstanceData;
|
||||
import com.jozufozu.flywheel.api.struct.Batched;
|
||||
import com.jozufozu.flywheel.api.struct.BatchedStructType;
|
||||
import com.jozufozu.flywheel.backend.instancing.AbstractInstancer;
|
||||
import com.jozufozu.flywheel.backend.instancing.TaskEngine;
|
||||
import com.jozufozu.flywheel.backend.model.DirectVertexConsumer;
|
||||
|
@ -14,7 +14,7 @@ public class CPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
|
|||
//
|
||||
// final ModelTransformer sbb;
|
||||
|
||||
public CPUInstancer(Batched<D> type) {
|
||||
public CPUInstancer(BatchedStructType<D> type) {
|
||||
super(type::create);
|
||||
// batchingType = type;
|
||||
//
|
||||
|
|
|
@ -6,7 +6,7 @@ import java.util.Map;
|
|||
import com.jozufozu.flywheel.api.InstanceData;
|
||||
import com.jozufozu.flywheel.api.Instancer;
|
||||
import com.jozufozu.flywheel.api.InstancerFactory;
|
||||
import com.jozufozu.flywheel.api.struct.Batched;
|
||||
import com.jozufozu.flywheel.api.struct.BatchedStructType;
|
||||
import com.jozufozu.flywheel.core.model.ModelSupplier;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
|
@ -14,9 +14,9 @@ import com.mojang.blaze3d.vertex.VertexConsumer;
|
|||
public class CPUInstancerFactory<D extends InstanceData> implements InstancerFactory<D> {
|
||||
|
||||
protected final Map<ModelSupplier, CPUInstancer<D>> models;
|
||||
private final Batched<D> type;
|
||||
private final BatchedStructType<D> type;
|
||||
|
||||
public CPUInstancerFactory(Batched<D> type) {
|
||||
public CPUInstancerFactory(BatchedStructType<D> type) {
|
||||
this.type = type;
|
||||
|
||||
this.models = new HashMap<>();
|
||||
|
|
|
@ -7,7 +7,7 @@ import org.lwjgl.system.MemoryUtil;
|
|||
|
||||
import com.jozufozu.flywheel.Flywheel;
|
||||
import com.jozufozu.flywheel.api.InstanceData;
|
||||
import com.jozufozu.flywheel.api.struct.Instanced;
|
||||
import com.jozufozu.flywheel.api.struct.InstancedStructType;
|
||||
import com.jozufozu.flywheel.api.struct.StructWriter;
|
||||
import com.jozufozu.flywheel.backend.gl.GlVertexArray;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
||||
|
@ -19,7 +19,7 @@ import com.jozufozu.flywheel.core.layout.BufferLayout;
|
|||
public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
|
||||
|
||||
final BufferLayout instanceFormat;
|
||||
final Instanced<D> instancedType;
|
||||
final InstancedStructType<D> instancedType;
|
||||
|
||||
GlBuffer vbo;
|
||||
int attributeBaseIndex;
|
||||
|
@ -27,7 +27,7 @@ public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
|
|||
|
||||
boolean anyToUpdate;
|
||||
|
||||
public GPUInstancer(Instanced<D> type) {
|
||||
public GPUInstancer(InstancedStructType<D> type) {
|
||||
super(type::create);
|
||||
this.instanceFormat = type.getLayout();
|
||||
instancedType = type;
|
||||
|
|
|
@ -12,7 +12,7 @@ import com.jozufozu.flywheel.api.InstanceData;
|
|||
import com.jozufozu.flywheel.api.Instancer;
|
||||
import com.jozufozu.flywheel.api.InstancerFactory;
|
||||
import com.jozufozu.flywheel.api.material.Material;
|
||||
import com.jozufozu.flywheel.api.struct.Instanced;
|
||||
import com.jozufozu.flywheel.api.struct.InstancedStructType;
|
||||
import com.jozufozu.flywheel.backend.model.MeshPool;
|
||||
import com.jozufozu.flywheel.core.model.ModelSupplier;
|
||||
|
||||
|
@ -25,14 +25,15 @@ import net.minecraft.client.renderer.RenderType;
|
|||
public class GPUInstancerFactory<D extends InstanceData> implements InstancerFactory<D> {
|
||||
|
||||
protected final Map<ModelSupplier, InstancedModel<D>> models = new HashMap<>();
|
||||
protected final Instanced<D> type;
|
||||
protected final InstancedStructType<D> type;
|
||||
|
||||
protected final List<InstancedModel<D>> uninitialized = new ArrayList<>();
|
||||
|
||||
protected final Multimap<RenderType, Material> materials = HashMultimap.create();
|
||||
protected final Multimap<Material, Renderable> renderables = ArrayListMultimap.create();
|
||||
// FIXME: these should not be public
|
||||
public final Multimap<RenderType, Material> materials = HashMultimap.create();
|
||||
public final Multimap<Material, Renderable> renderables = ArrayListMultimap.create();
|
||||
|
||||
public GPUInstancerFactory(Instanced<D> type) {
|
||||
public GPUInstancerFactory(InstancedStructType<D> type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ import org.jetbrains.annotations.NotNull;
|
|||
|
||||
import com.jozufozu.flywheel.api.InstanceData;
|
||||
import com.jozufozu.flywheel.api.material.Material;
|
||||
import com.jozufozu.flywheel.api.struct.Instanced;
|
||||
import com.jozufozu.flywheel.api.struct.InstancedStructType;
|
||||
import com.jozufozu.flywheel.api.struct.StructType;
|
||||
import com.jozufozu.flywheel.backend.instancing.Engine;
|
||||
import com.jozufozu.flywheel.backend.instancing.TaskEngine;
|
||||
|
@ -44,7 +44,7 @@ public class InstancingEngine<P extends WorldProgram> implements Engine {
|
|||
protected final ProgramCompiler<P> context;
|
||||
private MeshPool allocator;
|
||||
|
||||
protected final Map<Instanced<? extends InstanceData>, GPUInstancerFactory<?>> factories = new HashMap<>();
|
||||
protected final Map<InstancedStructType<? extends InstanceData>, GPUInstancerFactory<?>> factories = new HashMap<>();
|
||||
|
||||
protected final Set<RenderType> toRender = new HashSet<>();
|
||||
|
||||
|
@ -62,7 +62,7 @@ public class InstancingEngine<P extends WorldProgram> implements Engine {
|
|||
@NotNull
|
||||
@Override
|
||||
public <D extends InstanceData> GPUInstancerFactory<D> factory(StructType<D> type) {
|
||||
if (type instanceof Instanced<D> instanced) {
|
||||
if (type instanceof InstancedStructType<D> instanced) {
|
||||
return (GPUInstancerFactory<D>) factories.computeIfAbsent(instanced, GPUInstancerFactory::new);
|
||||
} else {
|
||||
throw new ClassCastException("Cannot use type '" + type + "' with GPU instancing.");
|
||||
|
@ -108,8 +108,8 @@ public class InstancingEngine<P extends WorldProgram> implements Engine {
|
|||
Textures.bindActiveTextures();
|
||||
CoreShaderInfo coreShaderInfo = getCoreShaderInfo();
|
||||
|
||||
for (Map.Entry<Instanced<? extends InstanceData>, GPUInstancerFactory<?>> entry : factories.entrySet()) {
|
||||
Instanced<? extends InstanceData> instanceType = entry.getKey();
|
||||
for (Map.Entry<InstancedStructType<? extends InstanceData>, GPUInstancerFactory<?>> entry : factories.entrySet()) {
|
||||
InstancedStructType<? extends InstanceData> instanceType = entry.getKey();
|
||||
GPUInstancerFactory<?> factory = entry.getValue();
|
||||
|
||||
var materials = factory.materials.get(type);
|
||||
|
@ -146,7 +146,7 @@ public class InstancingEngine<P extends WorldProgram> implements Engine {
|
|||
return coreShaderInfo;
|
||||
}
|
||||
|
||||
protected P setup(Instanced<?> instanceType, Material material, CoreShaderInfo coreShaderInfo, double camX, double camY, double camZ, Matrix4f viewProjection, ClientLevel level) {
|
||||
protected P setup(InstancedStructType<?> instanceType, Material material, CoreShaderInfo coreShaderInfo, double camX, double camY, double camZ, Matrix4f viewProjection, ClientLevel level) {
|
||||
float alphaDiscard = coreShaderInfo.alphaDiscard();
|
||||
if (alphaDiscard == 0) {
|
||||
alphaDiscard = 0.0001f;
|
||||
|
@ -201,7 +201,6 @@ public class InstancingEngine<P extends WorldProgram> implements Engine {
|
|||
}
|
||||
|
||||
allocator.flush();
|
||||
|
||||
}
|
||||
|
||||
private void checkOriginDistance(Camera info) {
|
||||
|
|
|
@ -69,6 +69,7 @@ public class ProgramCompiler<P extends GlProgram> extends Memoizer<ProgramCompil
|
|||
|
||||
@Override
|
||||
protected P _create(Context ctx) {
|
||||
// TODO: try-catch here to prevent crashing if shaders failed to compile
|
||||
return new ProgramAssembler(ctx.instanceShader().getFileLoc())
|
||||
.attachShader(vertexCompiler.get(new VertexCompiler.Context(ctx.vertexType(), ctx.instanceShader().getFile(), ctx.vertexMaterialShader().getFile(), ctx.ctx())))
|
||||
.attachShader(fragmentCompiler.get(new FragmentCompiler.Context(ctx.fragmentMaterialShader().getFile(), ctx.alphaDiscard(), ctx.fogType(), ctx.ctx())))
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
package com.jozufozu.flywheel.core.crumbling;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.jozufozu.flywheel.mixin.atlas.SheetDataAccessor;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.texture.AbstractTexture;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlas;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
/**
|
||||
* Track width and height of all created texture atlases.
|
||||
*
|
||||
* @see com.jozufozu.flywheel.mixin.atlas.AtlasDataMixin
|
||||
*/
|
||||
public class AtlasInfo {
|
||||
|
||||
private static final Map<ResourceLocation, SheetSize> sheetData = new HashMap<>();
|
||||
|
||||
@Nullable
|
||||
public static TextureAtlas getAtlas(ResourceLocation name) {
|
||||
AbstractTexture texture = Minecraft.getInstance().getTextureManager().getTexture(name);
|
||||
|
||||
if (texture instanceof TextureAtlas atlas)
|
||||
return atlas;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static SheetSize getSheetSize(@Nullable ResourceLocation loc) {
|
||||
return sheetData.get(loc);
|
||||
}
|
||||
|
||||
/**
|
||||
* FOR USE IN MIXIN
|
||||
*/
|
||||
public static void _setAtlasData(ResourceLocation atlas, SheetDataAccessor accessor) {
|
||||
sheetData.put(atlas, new SheetSize(accessor.flywheel$getWidth(), accessor.flywheel$getHeight()));
|
||||
}
|
||||
|
||||
public record SheetSize(int width, int height) {
|
||||
}
|
||||
}
|
|
@ -1,42 +1,18 @@
|
|||
package com.jozufozu.flywheel.core.crumbling;
|
||||
|
||||
import static org.lwjgl.opengl.GL20.glUniform2f;
|
||||
|
||||
import com.jozufozu.flywheel.core.shader.WorldProgram;
|
||||
|
||||
import net.minecraft.client.renderer.texture.TextureAtlas;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.resources.model.ModelBakery;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.inventory.InventoryMenu;
|
||||
|
||||
public class CrumblingProgram extends WorldProgram {
|
||||
protected final int uTextureScale;
|
||||
protected int uCrumbling;
|
||||
protected int uCrumblingTex;
|
||||
|
||||
public CrumblingProgram(ResourceLocation name, int handle) {
|
||||
super(name, handle);
|
||||
|
||||
uTextureScale = getUniformLocation("uTextureScale");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerSamplers() {
|
||||
super.registerSamplers();
|
||||
uCrumbling = setSamplerBinding("uCrumbling", 4);
|
||||
uCrumblingTex = setSamplerBinding("uCrumblingTex", 0);
|
||||
}
|
||||
|
||||
public void setTextureScale(float x, float y) {
|
||||
glUniform2f(uTextureScale, x, y);
|
||||
}
|
||||
|
||||
public void setAtlasSize(int width, int height) {
|
||||
TextureAtlas blockAtlas = AtlasInfo.getAtlas(InventoryMenu.BLOCK_ATLAS);
|
||||
if (blockAtlas == null) return;
|
||||
|
||||
TextureAtlasSprite sprite = blockAtlas.getSprite(ModelBakery.BREAKING_LOCATIONS.get(0));
|
||||
|
||||
setTextureScale(width / (float) sprite.getWidth(), height / (float) sprite.getHeight());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,13 +6,15 @@ import java.util.Map;
|
|||
import java.util.SortedSet;
|
||||
|
||||
import com.jozufozu.flywheel.api.InstanceData;
|
||||
import com.jozufozu.flywheel.api.struct.Instanced;
|
||||
import com.jozufozu.flywheel.api.material.Material;
|
||||
import com.jozufozu.flywheel.api.struct.InstancedStructType;
|
||||
import com.jozufozu.flywheel.backend.Backend;
|
||||
import com.jozufozu.flywheel.backend.gl.GlTextureUnit;
|
||||
import com.jozufozu.flywheel.backend.gl.GlStateTracker;
|
||||
import com.jozufozu.flywheel.backend.instancing.InstanceManager;
|
||||
import com.jozufozu.flywheel.backend.instancing.SerialTaskEngine;
|
||||
import com.jozufozu.flywheel.backend.instancing.instancing.GPUInstancerFactory;
|
||||
import com.jozufozu.flywheel.backend.instancing.instancing.InstancingEngine;
|
||||
import com.jozufozu.flywheel.backend.instancing.instancing.Renderable;
|
||||
import com.jozufozu.flywheel.core.Contexts;
|
||||
import com.jozufozu.flywheel.core.CoreShaderInfoMap.CoreShaderInfo;
|
||||
import com.jozufozu.flywheel.core.RenderContext;
|
||||
|
@ -20,101 +22,110 @@ import com.jozufozu.flywheel.event.ReloadRenderersEvent;
|
|||
import com.jozufozu.flywheel.mixin.LevelRendererAccessor;
|
||||
import com.jozufozu.flywheel.util.Lazy;
|
||||
import com.jozufozu.flywheel.util.Textures;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.math.Matrix4f;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.texture.AbstractTexture;
|
||||
import net.minecraft.client.renderer.texture.TextureManager;
|
||||
import net.minecraft.client.resources.model.ModelBakery;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.BlockDestructionProgress;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
|
||||
// TODO: merge directly into InstancingEngine for efficiency
|
||||
/**
|
||||
* Responsible for rendering the block breaking overlay for instanced block entities.
|
||||
* Responsible for rendering the crumbling overlay for instanced block entities.
|
||||
*/
|
||||
@Mod.EventBusSubscriber(Dist.CLIENT)
|
||||
public class CrumblingRenderer {
|
||||
|
||||
static RenderType _currentLayer;
|
||||
|
||||
private static Lazy<State> STATE;
|
||||
|
||||
static {
|
||||
_init();
|
||||
}
|
||||
|
||||
public static void renderBreaking(ClientLevel level, PoseStack stack, double x, double y, double z, Matrix4f viewProjection) {
|
||||
|
||||
public static void renderCrumbling(LevelRenderer levelRenderer, ClientLevel level, PoseStack poseStack, Camera camera, Matrix4f projectionMatrix) {
|
||||
if (!Backend.canUseInstancing(level)) return;
|
||||
|
||||
Int2ObjectMap<List<BlockEntity>> activeStages = getActiveStageBlockEntities(level);
|
||||
|
||||
Int2ObjectMap<List<BlockEntity>> activeStages = getActiveStageBlockEntities(levelRenderer, level);
|
||||
if (activeStages.isEmpty()) return;
|
||||
|
||||
GlStateTracker.State restoreState = GlStateTracker.getRestoreState();
|
||||
|
||||
Matrix4f viewProjection = poseStack.last()
|
||||
.pose()
|
||||
.copy();
|
||||
viewProjection.multiplyBackward(projectionMatrix);
|
||||
|
||||
State state = STATE.get();
|
||||
var instanceManager = state.instanceManager;
|
||||
var engine = state.instancerManager;
|
||||
|
||||
TextureManager textureManager = Minecraft.getInstance().getTextureManager();
|
||||
Camera info = Minecraft.getInstance().gameRenderer.getMainCamera();
|
||||
renderCrumblingInner(activeStages, instanceManager, engine, level, poseStack, camera, viewProjection);
|
||||
|
||||
restoreState.restore();
|
||||
}
|
||||
|
||||
private static void renderCrumblingInner(Int2ObjectMap<List<BlockEntity>> activeStages, InstanceManager<BlockEntity> instanceManager, CrumblingEngine engine, ClientLevel level, PoseStack stack, Camera camera, Matrix4f viewProjection) {
|
||||
Vec3 cameraPos = camera.getPosition();
|
||||
RenderContext ctx = new RenderContext(level, stack, viewProjection, null, cameraPos.x, cameraPos.y, cameraPos.z);
|
||||
|
||||
for (Int2ObjectMap.Entry<List<BlockEntity>> stage : activeStages.int2ObjectEntrySet()) {
|
||||
_currentLayer = ModelBakery.DESTROY_TYPES.get(stage.getIntKey());
|
||||
RenderType 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 (_currentLayer != null) {
|
||||
if (currentLayer != null) {
|
||||
engine.currentLayer = currentLayer;
|
||||
|
||||
stage.getValue().forEach(instanceManager::add);
|
||||
|
||||
instanceManager.beginFrame(SerialTaskEngine.INSTANCE, info);
|
||||
engine.beginFrame(info);
|
||||
|
||||
var ctx = new RenderContext(level, stack, viewProjection, null, x, y, z);
|
||||
instanceManager.beginFrame(SerialTaskEngine.INSTANCE, camera);
|
||||
engine.beginFrame(camera);
|
||||
|
||||
engine.renderAllRemaining(SerialTaskEngine.INSTANCE, ctx);
|
||||
|
||||
instanceManager.invalidate();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
GlTextureUnit.T0.makeActive();
|
||||
AbstractTexture breaking = textureManager.getTexture(ModelBakery.BREAKING_LOCATIONS.get(0));
|
||||
if (breaking != null) RenderSystem.bindTexture(breaking.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Associate each breaking stage with a list of all block entities at that stage.
|
||||
*/
|
||||
private static Int2ObjectMap<List<BlockEntity>> getActiveStageBlockEntities(ClientLevel world) {
|
||||
private static Int2ObjectMap<List<BlockEntity>> getActiveStageBlockEntities(LevelRenderer levelRenderer, ClientLevel level) {
|
||||
Long2ObjectMap<SortedSet<BlockDestructionProgress>> destructionProgress = ((LevelRendererAccessor) levelRenderer).flywheel$getDestructionProgress();
|
||||
if (destructionProgress.isEmpty()) {
|
||||
return Int2ObjectMaps.emptyMap();
|
||||
}
|
||||
|
||||
Int2ObjectMap<List<BlockEntity>> breakingEntities = new Int2ObjectArrayMap<>();
|
||||
BlockPos.MutableBlockPos breakingPos = new BlockPos.MutableBlockPos();
|
||||
|
||||
for (Long2ObjectMap.Entry<SortedSet<BlockDestructionProgress>> entry : ((LevelRendererAccessor) Minecraft.getInstance().levelRenderer).flywheel$getDestructionProgress()
|
||||
.long2ObjectEntrySet()) {
|
||||
BlockPos breakingPos = BlockPos.of(entry.getLongKey());
|
||||
for (Long2ObjectMap.Entry<SortedSet<BlockDestructionProgress>> entry : destructionProgress.long2ObjectEntrySet()) {
|
||||
breakingPos.set(entry.getLongKey());
|
||||
|
||||
SortedSet<BlockDestructionProgress> progresses = entry.getValue();
|
||||
if (progresses != null && !progresses.isEmpty()) {
|
||||
int blockDamage = progresses.last()
|
||||
int progress = progresses.last()
|
||||
.getProgress();
|
||||
if (progress >= 0) {
|
||||
BlockEntity blockEntity = level.getBlockEntity(breakingPos);
|
||||
|
||||
BlockEntity blockEntity = world.getBlockEntity(breakingPos);
|
||||
|
||||
if (blockEntity != null) {
|
||||
List<BlockEntity> blockEntities = breakingEntities.computeIfAbsent(blockDamage, $ -> new ArrayList<>());
|
||||
blockEntities.add(blockEntity);
|
||||
if (blockEntity != null) {
|
||||
List<BlockEntity> blockEntities = breakingEntities.computeIfAbsent(progress, $ -> new ArrayList<>());
|
||||
blockEntities.add(blockEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -156,6 +167,7 @@ public class CrumblingRenderer {
|
|||
}
|
||||
|
||||
private static class CrumblingEngine extends InstancingEngine<CrumblingProgram> {
|
||||
private RenderType currentLayer;
|
||||
|
||||
public CrumblingEngine() {
|
||||
super(Contexts.CRUMBLING);
|
||||
|
@ -163,42 +175,32 @@ public class CrumblingRenderer {
|
|||
|
||||
@Override
|
||||
protected void render(RenderType type, double camX, double camY, double camZ, Matrix4f viewProjection, ClientLevel level) {
|
||||
type.setupRenderState();
|
||||
|
||||
int renderTex = RenderSystem.getShaderTexture(0);
|
||||
|
||||
AtlasInfo.SheetSize sheetSize = AtlasInfo.getSheetSize(Textures.getShaderTexture(0));
|
||||
|
||||
int width;
|
||||
int height;
|
||||
if (sheetSize != null) {
|
||||
width = sheetSize.width();
|
||||
height = sheetSize.height();
|
||||
} else {
|
||||
width = height = 256;
|
||||
if (!type.affectsCrumbling()) {
|
||||
return;
|
||||
}
|
||||
|
||||
type.clearRenderState();
|
||||
|
||||
CrumblingRenderer._currentLayer.setupRenderState();
|
||||
|
||||
int breakingTex = RenderSystem.getShaderTexture(0);
|
||||
|
||||
RenderSystem.setShaderTexture(0, renderTex);
|
||||
RenderSystem.setShaderTexture(4, breakingTex);
|
||||
|
||||
currentLayer.setupRenderState();
|
||||
Textures.bindActiveTextures();
|
||||
CoreShaderInfo coreShaderInfo = getCoreShaderInfo();
|
||||
|
||||
for (Map.Entry<Instanced<? extends InstanceData>, GPUInstancerFactory<?>> entry : factories.entrySet()) {
|
||||
//CrumblingProgram program = setup(entry.getKey(), coreShaderInfo, camX, camY, camZ, viewProjection, level);
|
||||
for (Map.Entry<InstancedStructType<? extends InstanceData>, GPUInstancerFactory<?>> entry : factories.entrySet()) {
|
||||
InstancedStructType<? extends InstanceData> instanceType = entry.getKey();
|
||||
GPUInstancerFactory<?> factory = entry.getValue();
|
||||
|
||||
//program.setAtlasSize(width, height);
|
||||
var materials = factory.materials.get(type);
|
||||
for (Material material : materials) {
|
||||
var toRender = factory.renderables.get(material);
|
||||
toRender.removeIf(Renderable::shouldRemove);
|
||||
|
||||
//entry.getValue().getAllRenderables().forEach(Renderable::draw);
|
||||
if (!toRender.isEmpty()) {
|
||||
setup(instanceType, material, coreShaderInfo, camX, camY, camZ, viewProjection, level);
|
||||
|
||||
toRender.forEach(Renderable::render);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CrumblingRenderer._currentLayer.clearRenderState();
|
||||
currentLayer.clearRenderState();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ public class WorldProgram extends GlProgram {
|
|||
uLightMap = setSamplerBinding("uLightMap", 2);
|
||||
}
|
||||
|
||||
// TODO: create uniform registry
|
||||
public void uploadUniforms(double camX, double camY, double camZ, Matrix4f viewProjection, ClientLevel level) {
|
||||
fog.uploadUniforms();
|
||||
uploadTime(AnimationTickHolder.getRenderTime());
|
||||
|
|
|
@ -246,6 +246,7 @@ public class SourceFile {
|
|||
|
||||
String fileName = file.get();
|
||||
if (importedFiles.add(fileName)) {
|
||||
// FIXME: creating imports after the first resource reload crashes the game
|
||||
var checked = Import.create(errorReporter, use, file);
|
||||
if (checked != null) {
|
||||
imports.add(checked);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package com.jozufozu.flywheel.core.structs.model;
|
||||
|
||||
import com.jozufozu.flywheel.api.struct.Batched;
|
||||
import com.jozufozu.flywheel.api.struct.Instanced;
|
||||
import com.jozufozu.flywheel.api.struct.BatchedStructType;
|
||||
import com.jozufozu.flywheel.api.struct.InstancedStructType;
|
||||
import com.jozufozu.flywheel.api.struct.StructWriter;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
|
||||
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
||||
|
@ -10,7 +10,7 @@ import com.jozufozu.flywheel.core.model.ModelTransformer;
|
|||
import com.jozufozu.flywheel.core.source.FileResolution;
|
||||
import com.jozufozu.flywheel.core.structs.InstanceShaders;
|
||||
|
||||
public class ModelType implements Instanced<ModelData>, Batched<ModelData> {
|
||||
public class ModelType implements InstancedStructType<ModelData>, BatchedStructType<ModelData> {
|
||||
|
||||
public static final BufferLayout FORMAT = BufferLayout.builder()
|
||||
.addItems(CommonItems.LIGHT, CommonItems.RGBA)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package com.jozufozu.flywheel.core.structs.oriented;
|
||||
|
||||
import com.jozufozu.flywheel.api.struct.Batched;
|
||||
import com.jozufozu.flywheel.api.struct.Instanced;
|
||||
import com.jozufozu.flywheel.api.struct.BatchedStructType;
|
||||
import com.jozufozu.flywheel.api.struct.InstancedStructType;
|
||||
import com.jozufozu.flywheel.api.struct.StructWriter;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
|
||||
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
||||
|
@ -11,7 +11,7 @@ import com.jozufozu.flywheel.core.source.FileResolution;
|
|||
import com.jozufozu.flywheel.core.structs.InstanceShaders;
|
||||
import com.mojang.math.Quaternion;
|
||||
|
||||
public class OrientedType implements Instanced<OrientedData>, Batched<OrientedData> {
|
||||
public class OrientedType implements InstancedStructType<OrientedData>, BatchedStructType<OrientedData> {
|
||||
|
||||
public static final BufferLayout FORMAT = BufferLayout.builder()
|
||||
.addItems(CommonItems.LIGHT, CommonItems.RGBA)
|
||||
|
|
|
@ -4,6 +4,7 @@ import org.spongepowered.asm.mixin.Final;
|
|||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.At.Shift;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
|
@ -15,7 +16,6 @@ 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;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.math.Matrix4f;
|
||||
|
||||
|
@ -74,22 +74,10 @@ public class LevelRendererMixin {
|
|||
MinecraftForge.EVENT_BUS.post(new ReloadRenderersEvent(level));
|
||||
}
|
||||
|
||||
|
||||
@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/LevelRenderer;checkPoseStack(Lcom/mojang/blaze3d/vertex/PoseStack;)V", ordinal = 2 // after the game renders the breaking overlay normally
|
||||
@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderBuffers;crumblingBufferSource()Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;", ordinal = 2, shift = Shift.BY, by = 2 // after the game renders the breaking overlay normally
|
||||
), method = "renderLevel")
|
||||
private void renderBlockBreaking(PoseStack stack, float p_228426_2_, long p_228426_3_, boolean p_228426_5_, Camera info, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f p_228426_9_, CallbackInfo ci) {
|
||||
if (!Backend.isOn()) return;
|
||||
|
||||
Vec3 cameraPos = info.getPosition();
|
||||
|
||||
Matrix4f viewProjection = stack.last()
|
||||
.pose()
|
||||
.copy();
|
||||
viewProjection.multiplyBackward(RenderSystem.getProjectionMatrix());
|
||||
|
||||
GlStateTracker.State restoreState = GlStateTracker.getRestoreState();
|
||||
CrumblingRenderer.renderBreaking(level, stack, cameraPos.x, cameraPos.y, cameraPos.z, viewProjection);
|
||||
restoreState.restore();
|
||||
private void renderBlockBreaking(PoseStack poseStack, float partialTick, long finishNanoTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f projectionMatrix, CallbackInfo ci) {
|
||||
CrumblingRenderer.renderCrumbling((LevelRenderer) (Object) this, level, poseStack, camera, projectionMatrix);
|
||||
}
|
||||
|
||||
// Instancing
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
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.Textures;
|
||||
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/AbstractTexture;getId()I"))
|
||||
private static void storeTextureLoc(int pShaderTexture, ResourceLocation pTextureId, CallbackInfo ci) {
|
||||
Textures._setShaderTexture(pShaderTexture, pTextureId);
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
package com.jozufozu.flywheel.mixin.atlas;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import com.jozufozu.flywheel.core.crumbling.AtlasInfo;
|
||||
|
||||
import net.minecraft.client.renderer.texture.TextureAtlas;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
import net.minecraft.util.profiling.ProfilerFiller;
|
||||
|
||||
@Mixin(TextureAtlas.class)
|
||||
public abstract class AtlasDataMixin {
|
||||
|
||||
@Shadow
|
||||
public abstract ResourceLocation location();
|
||||
|
||||
@Inject(method = "prepareToStitch", at = @At("RETURN"))
|
||||
public void stealAtlasData(ResourceManager resourceManager, Stream<ResourceLocation> locationStream, ProfilerFiller profiler, int mipMapLevels, CallbackInfoReturnable<TextureAtlas.Preparations> cir) {
|
||||
AtlasInfo._setAtlasData(location(), (SheetDataAccessor) cir.getReturnValue());
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
package com.jozufozu.flywheel.mixin.atlas;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
import net.minecraft.client.renderer.texture.TextureAtlas;
|
||||
|
||||
@Mixin(TextureAtlas.Preparations.class)
|
||||
public interface SheetDataAccessor {
|
||||
|
||||
@Accessor("width")
|
||||
int flywheel$getWidth();
|
||||
|
||||
@Accessor("height")
|
||||
int flywheel$getHeight();
|
||||
|
||||
}
|
|
@ -1,33 +1,12 @@
|
|||
package com.jozufozu.flywheel.util;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
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 Textures {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this after calling {@link RenderType#setupRenderState()}.
|
||||
*/
|
||||
|
|
|
@ -6,11 +6,12 @@ uniform vec3 uCameraPos;
|
|||
uniform int uFogShape;
|
||||
|
||||
void flw_contextVertex() {
|
||||
flw_distance = fog_distance(flw_vertexPos.xyz, uCameraPos, uFogShape);
|
||||
gl_Position = uViewProjection * flw_vertexPos;
|
||||
|
||||
// TODO: remove this
|
||||
#ifdef DEBUG_NORMAL
|
||||
flw_vertexColor = vec4(flw_vertexNormal, 1.0);
|
||||
#endif
|
||||
|
||||
flw_distance = fog_distance(flw_vertexPos.xyz, uCameraPos, uFogShape);
|
||||
gl_Position = uViewProjection * flw_vertexPos;
|
||||
flw_vertexNormal = normalize(flw_vertexNormal);
|
||||
}
|
||||
|
|
|
@ -3,18 +3,31 @@
|
|||
|
||||
uniform vec2 uFogRange;
|
||||
uniform vec4 uFogColor;
|
||||
uniform vec2 uTextureScale;
|
||||
|
||||
uniform sampler2D uBlockAtlas;
|
||||
uniform sampler2D uCrumbling;
|
||||
uniform sampler2D uCrumblingTex;
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
vec2 flattenedPos(vec3 pos, vec3 normal) {
|
||||
pos -= floor(pos) + vec3(0.5);
|
||||
|
||||
float sinYRot = -normal.x;
|
||||
float sqLength = normal.x * normal.x + normal.z * normal.z;
|
||||
if (sqLength > 0) {
|
||||
sinYRot /= sqrt(sqLength);
|
||||
sinYRot = clamp(sinYRot, -1, 1);
|
||||
}
|
||||
|
||||
vec3 tangent = vec3(sqrt(1 - sinYRot * sinYRot) * (normal.z < 0 ? -1 : 1), 0, sinYRot);
|
||||
vec3 bitangent = cross(tangent, normal);
|
||||
mat3 tbn = mat3(tangent, bitangent, normal);
|
||||
|
||||
// transpose is the same as inverse for orthonormal matrices
|
||||
return (transpose(tbn) * pos).xy + vec2(0.5);
|
||||
}
|
||||
|
||||
void flw_contextFragment() {
|
||||
vec4 texColor = texture(uBlockAtlas, flw_vertexTexCoord);
|
||||
vec4 crumblingColor = texture(uCrumbling, flw_vertexTexCoord * uTextureScale);
|
||||
crumblingColor.a *= texColor.a;
|
||||
vec4 color = flw_vertexColor * vec4(crumblingColor.rgb, crumblingColor.a);
|
||||
vec4 color = texture(uCrumblingTex, flattenedPos(flw_vertexPos.xyz, flw_vertexNormal));
|
||||
|
||||
#ifdef ALPHA_DISCARD
|
||||
if (color.a < ALPHA_DISCARD) {
|
||||
|
|
|
@ -22,10 +22,7 @@
|
|||
"LevelRendererMixin",
|
||||
"MultiBufferSourceMixin",
|
||||
"PausedPartialTickAccessor",
|
||||
"RenderTexturesMixin",
|
||||
"RenderTypeMixin",
|
||||
"atlas.AtlasDataMixin",
|
||||
"atlas.SheetDataAccessor",
|
||||
"light.LightUpdateMixin",
|
||||
"light.NetworkLightUpdateMixin",
|
||||
"matrix.Matrix3fMixin",
|
||||
|
|
Loading…
Reference in a new issue