mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-01-29 14:24:58 +01:00
Much ado
- 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:
parent
506f2d5158
commit
833fadbbdc
16 changed files with 60 additions and 69 deletions
|
@ -12,7 +12,7 @@ public final class BeginFrameEvent extends Event {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RenderContext getContext() {
|
public RenderContext context() {
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,11 +24,11 @@ public final class EndClientResourceReloadEvent extends Event implements IModBus
|
||||||
this.error = error;
|
this.error = error;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Minecraft getMinecraft() {
|
public Minecraft minecraft() {
|
||||||
return minecraft;
|
return minecraft;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResourceManager getResourceManager() {
|
public ResourceManager resourceManager() {
|
||||||
return resourceManager;
|
return resourceManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ public final class EndClientResourceReloadEvent extends Event implements IModBus
|
||||||
return initialReload;
|
return initialReload;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<Throwable> getError() {
|
public Optional<Throwable> error() {
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ public final class ReloadLevelRendererEvent extends Event {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public ClientLevel getLevel() {
|
public ClientLevel level() {
|
||||||
return level;
|
return level;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,31 +21,31 @@ public final class RenderStageEvent extends Event {
|
||||||
this.stage = stage;
|
this.stage = stage;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RenderContext getContext() {
|
public RenderContext context() {
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RenderStage getStage() {
|
public RenderStage stage() {
|
||||||
return stage;
|
return stage;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClientLevel getLevel() {
|
public ClientLevel level() {
|
||||||
return context.level();
|
return context.level();
|
||||||
}
|
}
|
||||||
|
|
||||||
public PoseStack getStack() {
|
public PoseStack stack() {
|
||||||
return context.stack();
|
return context.stack();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Matrix4f getViewProjection() {
|
public Matrix4f viewProjection() {
|
||||||
return context.viewProjection();
|
return context.viewProjection();
|
||||||
}
|
}
|
||||||
|
|
||||||
public RenderBuffers getBuffers() {
|
public RenderBuffers buffers() {
|
||||||
return context.buffers();
|
return context.buffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Camera getCamera() {
|
public Camera camera() {
|
||||||
return context.camera();
|
return context.camera();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,17 @@ package com.jozufozu.flywheel.api.visual;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.visualization.VisualizationContext;
|
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 {
|
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);
|
EffectVisual<?> visualize(VisualizationContext ctx);
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,7 +71,8 @@ public final class BackendManagerImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void onEndClientResourceReload(EndClientResourceReloadEvent event) {
|
public static void onEndClientResourceReload(EndClientResourceReloadEvent event) {
|
||||||
if (event.getError().isPresent()) {
|
if (event.error()
|
||||||
|
.isPresent()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +83,7 @@ public final class BackendManagerImpl {
|
||||||
public static void onReloadLevelRenderer(ReloadLevelRendererEvent event) {
|
public static void onReloadLevelRenderer(ReloadLevelRendererEvent event) {
|
||||||
chooseBackend();
|
chooseBackend();
|
||||||
|
|
||||||
ClientLevel level = event.getLevel();
|
ClientLevel level = event.level();
|
||||||
if (level != null) {
|
if (level != null) {
|
||||||
VisualizationManagerImpl.reset(level);
|
VisualizationManagerImpl.reset(level);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,23 +36,25 @@ public final class VisualizationEventHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void onBeginFrame(BeginFrameEvent event) {
|
public static void onBeginFrame(BeginFrameEvent event) {
|
||||||
ClientLevel level = event.getContext().level();
|
ClientLevel level = event.context()
|
||||||
|
.level();
|
||||||
VisualizationManagerImpl manager = VisualizationManagerImpl.get(level);
|
VisualizationManagerImpl manager = VisualizationManagerImpl.get(level);
|
||||||
if (manager == null) {
|
if (manager == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
manager.beginFrame(event.getContext());
|
manager.beginFrame(event.context());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void onRenderStage(RenderStageEvent event) {
|
public static void onRenderStage(RenderStageEvent event) {
|
||||||
ClientLevel level = event.getContext().level();
|
ClientLevel level = event.context()
|
||||||
|
.level();
|
||||||
VisualizationManagerImpl manager = VisualizationManagerImpl.get(level);
|
VisualizationManagerImpl manager = VisualizationManagerImpl.get(level);
|
||||||
if (manager == null) {
|
if (manager == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
manager.renderStage(event.getContext(), event.getStage());
|
manager.renderStage(event.context(), event.stage());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void onEntityJoinLevel(EntityJoinLevelEvent event) {
|
public static void onEntityJoinLevel(EntityJoinLevelEvent event) {
|
||||||
|
|
|
@ -167,8 +167,7 @@ public class LitVisualStorage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Breaking this into 2 separate cases allows us to avoid the sync overhead in the common case.
|
// Breaking this into 2 separate cases allows us to avoid the overhead of atomics in the common case.
|
||||||
// TODO: is it faster to only use the synced variant to avoid virtual dispatches?
|
|
||||||
sealed interface Updater {
|
sealed interface Updater {
|
||||||
void updateLight(long updateId);
|
void updateLight(long updateId);
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,7 @@ public abstract class ColoredLitInstance extends AbstractInstance implements Fla
|
||||||
public byte b = (byte) 0xFF;
|
public byte b = (byte) 0xFF;
|
||||||
public byte a = (byte) 0xFF;
|
public byte a = (byte) 0xFF;
|
||||||
|
|
||||||
public byte blockLight;
|
public int packedLight;
|
||||||
public byte skyLight;
|
|
||||||
|
|
||||||
public int overlay = OverlayTexture.NO_OVERLAY;
|
public int overlay = OverlayTexture.NO_OVERLAY;
|
||||||
|
|
||||||
|
@ -58,22 +57,16 @@ public abstract class ColoredLitInstance extends AbstractInstance implements Fla
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ColoredLitInstance setBlockLight(int blockLight) {
|
public ColoredLitInstance light(int blockLight, int skyLight) {
|
||||||
this.blockLight = (byte) blockLight;
|
return light(LightTexture.pack(blockLight, skyLight));
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ColoredLitInstance setSkyLight(int skyLight) {
|
public ColoredLitInstance light(int packedLight) {
|
||||||
this.skyLight = (byte) skyLight;
|
this.packedLight = packedLight;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getPackedLight() {
|
|
||||||
return LightTexture.pack(blockLight, skyLight);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ColoredLitInstance setOverlay(int overlay) {
|
public ColoredLitInstance setOverlay(int overlay) {
|
||||||
this.overlay = overlay;
|
this.overlay = overlay;
|
||||||
return this;
|
return this;
|
||||||
|
|
|
@ -2,38 +2,25 @@ package com.jozufozu.flywheel.lib.instance;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.instance.Instance;
|
import com.jozufozu.flywheel.api.instance.Instance;
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.client.renderer.LightTexture;
|
||||||
import net.minecraft.world.level.BlockAndTintGetter;
|
|
||||||
import net.minecraft.world.level.LightLayer;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An interface that implementors of {@link Instance} should also implement
|
* An interface that implementors of {@link Instance} should also implement
|
||||||
* if they wish to make use of Flywheel's provided light update methods.
|
* 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 {
|
public interface FlatLit extends Instance {
|
||||||
/**
|
/**
|
||||||
* @param blockLight An integer in the range [0, 15] representing the
|
* Set the block and sky light values for this instance.
|
||||||
* amount of block light this instance should receive.
|
* @param blockLight Block light value
|
||||||
* @return {@code this}
|
* @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
|
* Set the packed light value for this instance.
|
||||||
* amount of sky light this instance should receive.
|
* @param packedLight Packed block and sky light per {@link LightTexture#pack(int, int)}
|
||||||
* @return {@code this}
|
* @return {@code this} for chaining
|
||||||
*/
|
*/
|
||||||
FlatLit setSkyLight(int skyLight);
|
FlatLit light(int packedLight);
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,8 +26,8 @@ public final class InstanceTypes {
|
||||||
MemoryUtil.memPutByte(ptr + 3, instance.a);
|
MemoryUtil.memPutByte(ptr + 3, instance.a);
|
||||||
MemoryUtil.memPutShort(ptr + 4, (short) (instance.overlay & 0xFFFF));
|
MemoryUtil.memPutShort(ptr + 4, (short) (instance.overlay & 0xFFFF));
|
||||||
MemoryUtil.memPutShort(ptr + 6, (short) (instance.overlay >> 16 & 0xFFFF));
|
MemoryUtil.memPutShort(ptr + 6, (short) (instance.overlay >> 16 & 0xFFFF));
|
||||||
MemoryUtil.memPutShort(ptr + 8, (short) (Byte.toUnsignedInt(instance.blockLight) << 4));
|
MemoryUtil.memPutShort(ptr + 8, (short) (instance.packedLight & 0xFFFF));
|
||||||
MemoryUtil.memPutShort(ptr + 10, (short) (Byte.toUnsignedInt(instance.skyLight) << 4));
|
MemoryUtil.memPutShort(ptr + 10, (short) (instance.packedLight >> 16 & 0xFFFF));
|
||||||
MatrixMath.writeUnsafe(instance.model, ptr + 12);
|
MatrixMath.writeUnsafe(instance.model, ptr + 12);
|
||||||
MatrixMath.writeUnsafe(instance.normal, ptr + 76);
|
MatrixMath.writeUnsafe(instance.normal, ptr + 76);
|
||||||
})
|
})
|
||||||
|
@ -51,8 +51,8 @@ public final class InstanceTypes {
|
||||||
MemoryUtil.memPutByte(ptr + 3, instance.a);
|
MemoryUtil.memPutByte(ptr + 3, instance.a);
|
||||||
MemoryUtil.memPutShort(ptr + 4, (short) (instance.overlay & 0xFFFF));
|
MemoryUtil.memPutShort(ptr + 4, (short) (instance.overlay & 0xFFFF));
|
||||||
MemoryUtil.memPutShort(ptr + 6, (short) (instance.overlay >> 16 & 0xFFFF));
|
MemoryUtil.memPutShort(ptr + 6, (short) (instance.overlay >> 16 & 0xFFFF));
|
||||||
MemoryUtil.memPutShort(ptr + 8, (short) (Byte.toUnsignedInt(instance.blockLight) << 4));
|
MemoryUtil.memPutShort(ptr + 8, (short) (instance.packedLight & 0xFFFF));
|
||||||
MemoryUtil.memPutShort(ptr + 10, (short) (Byte.toUnsignedInt(instance.skyLight) << 4));
|
MemoryUtil.memPutShort(ptr + 10, (short) (instance.packedLight >> 16 & 0xFFFF));
|
||||||
MemoryUtil.memPutFloat(ptr + 12, instance.posX);
|
MemoryUtil.memPutFloat(ptr + 12, instance.posX);
|
||||||
MemoryUtil.memPutFloat(ptr + 16, instance.posY);
|
MemoryUtil.memPutFloat(ptr + 16, instance.posY);
|
||||||
MemoryUtil.memPutFloat(ptr + 20, instance.posZ);
|
MemoryUtil.memPutFloat(ptr + 20, instance.posZ);
|
||||||
|
|
|
@ -147,7 +147,6 @@ final class BakedModelBufferer {
|
||||||
{
|
{
|
||||||
for (int layerIndex = 0; layerIndex < CHUNK_LAYER_AMOUNT; layerIndex++) {
|
for (int layerIndex = 0; layerIndex < CHUNK_LAYER_AMOUNT; layerIndex++) {
|
||||||
var renderType = CHUNK_LAYERS[layerIndex];
|
var renderType = CHUNK_LAYERS[layerIndex];
|
||||||
// FIXME: We leak the memory owned by the BufferBuilder here.
|
|
||||||
var buffer = new BufferBuilder(renderType.bufferSize());
|
var buffer = new BufferBuilder(renderType.bufferSize());
|
||||||
emitters[layerIndex] = new MeshEmitter(buffer, renderType);
|
emitters[layerIndex] = new MeshEmitter(buffer, renderType);
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,8 +61,8 @@ public abstract class AbstractVisual implements Visual {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
instance.setLight(block, sky);
|
instance.light(block, sky)
|
||||||
instance.handle()
|
.handle()
|
||||||
.setChanged();
|
.setChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ public abstract class AbstractVisual implements Visual {
|
||||||
|
|
||||||
protected void relight(int block, int sky, Stream<? extends @Nullable FlatLit> instances) {
|
protected void relight(int block, int sky, Stream<? extends @Nullable FlatLit> instances) {
|
||||||
instances.filter(Objects::nonNull)
|
instances.filter(Objects::nonNull)
|
||||||
.forEach(instance -> instance.setLight(block, sky)
|
.forEach(instance -> instance.light(block, sky)
|
||||||
.handle()
|
.handle()
|
||||||
.setChanged());
|
.setChanged());
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,7 @@ public abstract class AbstractVisual implements Visual {
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
instance.setLight(block, sky)
|
instance.light(block, sky)
|
||||||
.handle()
|
.handle()
|
||||||
.setChanged();
|
.setChanged();
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ public class FireComponent implements EntityComponent {
|
||||||
TransformedInstance instance = context.instancerProvider()
|
TransformedInstance instance = context.instancerProvider()
|
||||||
.instancer(InstanceTypes.TRANSFORMED, model)
|
.instancer(InstanceTypes.TRANSFORMED, model)
|
||||||
.createInstance();
|
.createInstance();
|
||||||
instance.setBlockLight(LightTexture.block(LightTexture.FULL_BLOCK));
|
instance.light(LightTexture.FULL_BLOCK);
|
||||||
instance.setChanged();
|
instance.setChanged();
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ public class HitboxComponent implements EntityComponent {
|
||||||
TransformedInstance instance = context.instancerProvider()
|
TransformedInstance instance = context.instancerProvider()
|
||||||
.instancer(InstanceTypes.TRANSFORMED, model)
|
.instancer(InstanceTypes.TRANSFORMED, model)
|
||||||
.createInstance();
|
.createInstance();
|
||||||
instance.setBlockLight(LightTexture.block(LightTexture.FULL_BLOCK));
|
instance.light(LightTexture.FULL_BLOCK);
|
||||||
instance.setChanged();
|
instance.setChanged();
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ import com.jozufozu.flywheel.lib.model.Models;
|
||||||
import com.jozufozu.flywheel.lib.task.ForEachPlan;
|
import com.jozufozu.flywheel.lib.task.ForEachPlan;
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.renderer.LightTexture;
|
||||||
import net.minecraft.core.Vec3i;
|
import net.minecraft.core.Vec3i;
|
||||||
import net.minecraft.util.Mth;
|
import net.minecraft.util.Mth;
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
@ -271,8 +272,7 @@ public class ExampleEffect implements Effect {
|
||||||
.instancer(InstanceTypes.TRANSFORMED, Models.block(Blocks.SHROOMLIGHT.defaultBlockState()))
|
.instancer(InstanceTypes.TRANSFORMED, Models.block(Blocks.SHROOMLIGHT.defaultBlockState()))
|
||||||
.createInstance();
|
.createInstance();
|
||||||
|
|
||||||
instance.setBlockLight(15)
|
instance.light(LightTexture.FULL_BRIGHT);
|
||||||
.setSkyLight(15);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void _delete() {
|
public void _delete() {
|
||||||
|
|
Loading…
Reference in a new issue