- Go through some TODOs
- Simplify FlatLit interface and directly store packed light
- Rename getters in Events
- Document Effects
- LitVisualStorage: atomics are slow
- BakedModelBufferer: vanilla leaks too, they'll be freed when the game
  exits
This commit is contained in:
Jozufozu 2024-04-02 12:36:40 -07:00
parent 506f2d5158
commit 833fadbbdc
16 changed files with 60 additions and 69 deletions

View file

@ -12,7 +12,7 @@ public final class BeginFrameEvent extends Event {
this.context = context;
}
public RenderContext getContext() {
public RenderContext context() {
return context;
}
}

View file

@ -24,11 +24,11 @@ public final class EndClientResourceReloadEvent extends Event implements IModBus
this.error = error;
}
public Minecraft getMinecraft() {
public Minecraft minecraft() {
return minecraft;
}
public ResourceManager getResourceManager() {
public ResourceManager resourceManager() {
return resourceManager;
}
@ -36,7 +36,7 @@ public final class EndClientResourceReloadEvent extends Event implements IModBus
return initialReload;
}
public Optional<Throwable> getError() {
public Optional<Throwable> error() {
return error;
}
}

View file

@ -17,7 +17,7 @@ public final class ReloadLevelRendererEvent extends Event {
}
@Nullable
public ClientLevel getLevel() {
public ClientLevel level() {
return level;
}
}

View file

@ -21,31 +21,31 @@ public final class RenderStageEvent extends Event {
this.stage = stage;
}
public RenderContext getContext() {
public RenderContext context() {
return context;
}
public RenderStage getStage() {
public RenderStage stage() {
return stage;
}
public ClientLevel getLevel() {
public ClientLevel level() {
return context.level();
}
public PoseStack getStack() {
public PoseStack stack() {
return context.stack();
}
public Matrix4f getViewProjection() {
public Matrix4f viewProjection() {
return context.viewProjection();
}
public RenderBuffers getBuffers() {
public RenderBuffers buffers() {
return context.buffers();
}
public Camera getCamera() {
public Camera camera() {
return context.camera();
}

View file

@ -2,7 +2,17 @@ package com.jozufozu.flywheel.api.visual;
import com.jozufozu.flywheel.api.visualization.VisualizationContext;
// TODO: Consider adding LevelAccessor getter
/**
* An effect is not attached to any formal game object, but allows you to hook into
* flywheel's systems to render things. They're closely analogous to particles but
* without any built in support for networking.
*/
public interface Effect {
/**
* Create a visual that will be keyed by this effect object.
*
* @param ctx The visualization context.
* @return An arbitrary EffectVisual.
*/
EffectVisual<?> visualize(VisualizationContext ctx);
}

View file

@ -71,7 +71,8 @@ public final class BackendManagerImpl {
}
public static void onEndClientResourceReload(EndClientResourceReloadEvent event) {
if (event.getError().isPresent()) {
if (event.error()
.isPresent()) {
return;
}
@ -82,7 +83,7 @@ public final class BackendManagerImpl {
public static void onReloadLevelRenderer(ReloadLevelRendererEvent event) {
chooseBackend();
ClientLevel level = event.getLevel();
ClientLevel level = event.level();
if (level != null) {
VisualizationManagerImpl.reset(level);
}

View file

@ -36,23 +36,25 @@ public final class VisualizationEventHandler {
}
public static void onBeginFrame(BeginFrameEvent event) {
ClientLevel level = event.getContext().level();
ClientLevel level = event.context()
.level();
VisualizationManagerImpl manager = VisualizationManagerImpl.get(level);
if (manager == null) {
return;
}
manager.beginFrame(event.getContext());
manager.beginFrame(event.context());
}
public static void onRenderStage(RenderStageEvent event) {
ClientLevel level = event.getContext().level();
ClientLevel level = event.context()
.level();
VisualizationManagerImpl manager = VisualizationManagerImpl.get(level);
if (manager == null) {
return;
}
manager.renderStage(event.getContext(), event.getStage());
manager.renderStage(event.context(), event.stage());
}
public static void onEntityJoinLevel(EntityJoinLevelEvent event) {

View file

@ -167,8 +167,7 @@ public class LitVisualStorage {
}
}
// Breaking this into 2 separate cases allows us to avoid the sync overhead in the common case.
// TODO: is it faster to only use the synced variant to avoid virtual dispatches?
// Breaking this into 2 separate cases allows us to avoid the overhead of atomics in the common case.
sealed interface Updater {
void updateLight(long updateId);

View file

@ -12,8 +12,7 @@ public abstract class ColoredLitInstance extends AbstractInstance implements Fla
public byte b = (byte) 0xFF;
public byte a = (byte) 0xFF;
public byte blockLight;
public byte skyLight;
public int packedLight;
public int overlay = OverlayTexture.NO_OVERLAY;
@ -58,22 +57,16 @@ public abstract class ColoredLitInstance extends AbstractInstance implements Fla
}
@Override
public ColoredLitInstance setBlockLight(int blockLight) {
this.blockLight = (byte) blockLight;
return this;
public ColoredLitInstance light(int blockLight, int skyLight) {
return light(LightTexture.pack(blockLight, skyLight));
}
@Override
public ColoredLitInstance setSkyLight(int skyLight) {
this.skyLight = (byte) skyLight;
public ColoredLitInstance light(int packedLight) {
this.packedLight = packedLight;
return this;
}
@Override
public int getPackedLight() {
return LightTexture.pack(blockLight, skyLight);
}
public ColoredLitInstance setOverlay(int overlay) {
this.overlay = overlay;
return this;

View file

@ -2,38 +2,25 @@ package com.jozufozu.flywheel.lib.instance;
import com.jozufozu.flywheel.api.instance.Instance;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.LightLayer;
import net.minecraft.client.renderer.LightTexture;
/**
* An interface that implementors of {@link Instance} should also implement
* if they wish to make use of Flywheel's provided light update methods.
* <p>
* This only covers flat lighting, smooth lighting is still TODO.
*/
public interface FlatLit extends Instance {
/**
* @param blockLight An integer in the range [0, 15] representing the
* amount of block light this instance should receive.
* @return {@code this}
* Set the block and sky light values for this instance.
* @param blockLight Block light value
* @param skyLight Sky light value
* @return {@code this} for chaining
*/
FlatLit setBlockLight(int blockLight);
FlatLit light(int blockLight, int skyLight);
/**
* @param skyLight An integer in the range [0, 15] representing the
* amount of sky light this instance should receive.
* @return {@code this}
* Set the packed light value for this instance.
* @param packedLight Packed block and sky light per {@link LightTexture#pack(int, int)}
* @return {@code this} for chaining
*/
FlatLit setSkyLight(int skyLight);
default FlatLit setLight(int blockLight, int skyLight) {
return setBlockLight(blockLight).setSkyLight(skyLight);
}
default FlatLit updateLight(BlockAndTintGetter level, BlockPos pos) {
return setLight(level.getBrightness(LightLayer.BLOCK, pos), level.getBrightness(LightLayer.SKY, pos));
}
int getPackedLight();
FlatLit light(int packedLight);
}

View file

@ -26,8 +26,8 @@ public final class InstanceTypes {
MemoryUtil.memPutByte(ptr + 3, instance.a);
MemoryUtil.memPutShort(ptr + 4, (short) (instance.overlay & 0xFFFF));
MemoryUtil.memPutShort(ptr + 6, (short) (instance.overlay >> 16 & 0xFFFF));
MemoryUtil.memPutShort(ptr + 8, (short) (Byte.toUnsignedInt(instance.blockLight) << 4));
MemoryUtil.memPutShort(ptr + 10, (short) (Byte.toUnsignedInt(instance.skyLight) << 4));
MemoryUtil.memPutShort(ptr + 8, (short) (instance.packedLight & 0xFFFF));
MemoryUtil.memPutShort(ptr + 10, (short) (instance.packedLight >> 16 & 0xFFFF));
MatrixMath.writeUnsafe(instance.model, ptr + 12);
MatrixMath.writeUnsafe(instance.normal, ptr + 76);
})
@ -51,8 +51,8 @@ public final class InstanceTypes {
MemoryUtil.memPutByte(ptr + 3, instance.a);
MemoryUtil.memPutShort(ptr + 4, (short) (instance.overlay & 0xFFFF));
MemoryUtil.memPutShort(ptr + 6, (short) (instance.overlay >> 16 & 0xFFFF));
MemoryUtil.memPutShort(ptr + 8, (short) (Byte.toUnsignedInt(instance.blockLight) << 4));
MemoryUtil.memPutShort(ptr + 10, (short) (Byte.toUnsignedInt(instance.skyLight) << 4));
MemoryUtil.memPutShort(ptr + 8, (short) (instance.packedLight & 0xFFFF));
MemoryUtil.memPutShort(ptr + 10, (short) (instance.packedLight >> 16 & 0xFFFF));
MemoryUtil.memPutFloat(ptr + 12, instance.posX);
MemoryUtil.memPutFloat(ptr + 16, instance.posY);
MemoryUtil.memPutFloat(ptr + 20, instance.posZ);

View file

@ -147,7 +147,6 @@ final class BakedModelBufferer {
{
for (int layerIndex = 0; layerIndex < CHUNK_LAYER_AMOUNT; layerIndex++) {
var renderType = CHUNK_LAYERS[layerIndex];
// FIXME: We leak the memory owned by the BufferBuilder here.
var buffer = new BufferBuilder(renderType.bufferSize());
emitters[layerIndex] = new MeshEmitter(buffer, renderType);
}

View file

@ -61,8 +61,8 @@ public abstract class AbstractVisual implements Visual {
continue;
}
instance.setLight(block, sky);
instance.handle()
instance.light(block, sky)
.handle()
.setChanged();
}
}
@ -73,7 +73,7 @@ public abstract class AbstractVisual implements Visual {
protected void relight(int block, int sky, Stream<? extends @Nullable FlatLit> instances) {
instances.filter(Objects::nonNull)
.forEach(instance -> instance.setLight(block, sky)
.forEach(instance -> instance.light(block, sky)
.handle()
.setChanged());
}
@ -87,7 +87,7 @@ public abstract class AbstractVisual implements Visual {
if (instance == null) {
continue;
}
instance.setLight(block, sky)
instance.light(block, sky)
.handle()
.setChanged();
}

View file

@ -56,7 +56,7 @@ public class FireComponent implements EntityComponent {
TransformedInstance instance = context.instancerProvider()
.instancer(InstanceTypes.TRANSFORMED, model)
.createInstance();
instance.setBlockLight(LightTexture.block(LightTexture.FULL_BLOCK));
instance.light(LightTexture.FULL_BLOCK);
instance.setChanged();
return instance;
}

View file

@ -70,7 +70,7 @@ public class HitboxComponent implements EntityComponent {
TransformedInstance instance = context.instancerProvider()
.instancer(InstanceTypes.TRANSFORMED, model)
.createInstance();
instance.setBlockLight(LightTexture.block(LightTexture.FULL_BLOCK));
instance.light(LightTexture.FULL_BLOCK);
instance.setChanged();
return instance;
}

View file

@ -21,6 +21,7 @@ import com.jozufozu.flywheel.lib.model.Models;
import com.jozufozu.flywheel.lib.task.ForEachPlan;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.core.Vec3i;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.player.Player;
@ -271,8 +272,7 @@ public class ExampleEffect implements Effect {
.instancer(InstanceTypes.TRANSFORMED, Models.block(Blocks.SHROOMLIGHT.defaultBlockState()))
.createInstance();
instance.setBlockLight(15)
.setSkyLight(15);
instance.light(LightTexture.FULL_BRIGHT);
}
public void _delete() {