mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-02-10 12:15:03 +01:00
We need to go deeper
- Compose transformations of embeddings - Make EmbeddedEnvironment abstract and move light stuffs into TopLevelEmbeddedEnvironment - Add NestedEmbeddedEnvironment that only handles matrices, and tracks a parent EmbeddedEnvironment - AbstractEmbeddedEnvironment handles most of the deletion/update logic, and also creates further NestedEmbeddedEnvironments - EnvironmentStorage now only tracks environments and does not creat them.
This commit is contained in:
parent
277597d6bf
commit
ff7130c71c
9 changed files with 328 additions and 193 deletions
|
@ -14,8 +14,8 @@ import com.jozufozu.flywheel.api.task.Plan;
|
||||||
import com.jozufozu.flywheel.api.task.TaskExecutor;
|
import com.jozufozu.flywheel.api.task.TaskExecutor;
|
||||||
import com.jozufozu.flywheel.api.visualization.VisualEmbedding;
|
import com.jozufozu.flywheel.api.visualization.VisualEmbedding;
|
||||||
import com.jozufozu.flywheel.api.visualization.VisualizationContext;
|
import com.jozufozu.flywheel.api.visualization.VisualizationContext;
|
||||||
import com.jozufozu.flywheel.backend.engine.embed.EmbeddedEnvironment;
|
|
||||||
import com.jozufozu.flywheel.backend.engine.embed.Environment;
|
import com.jozufozu.flywheel.backend.engine.embed.Environment;
|
||||||
|
import com.jozufozu.flywheel.backend.engine.embed.TopLevelEmbeddedEnvironment;
|
||||||
import com.jozufozu.flywheel.backend.engine.uniform.Uniforms;
|
import com.jozufozu.flywheel.backend.engine.uniform.Uniforms;
|
||||||
import com.jozufozu.flywheel.backend.gl.GlStateTracker;
|
import com.jozufozu.flywheel.backend.gl.GlStateTracker;
|
||||||
import com.jozufozu.flywheel.lib.task.Flag;
|
import com.jozufozu.flywheel.lib.task.Flag;
|
||||||
|
@ -30,7 +30,7 @@ import net.minecraft.world.phys.Vec3;
|
||||||
public class EngineImpl implements Engine {
|
public class EngineImpl implements Engine {
|
||||||
private final int sqrMaxOriginDistance;
|
private final int sqrMaxOriginDistance;
|
||||||
private final DrawManager<? extends AbstractInstancer<?>> drawManager;
|
private final DrawManager<? extends AbstractInstancer<?>> drawManager;
|
||||||
private final EnvironmentStorage environmentStorage = new EnvironmentStorage(this);
|
private final EnvironmentStorage environmentStorage = new EnvironmentStorage();
|
||||||
private final Flag flushFlag = new NamedFlag("flushed");
|
private final Flag flushFlag = new NamedFlag("flushed");
|
||||||
|
|
||||||
private BlockPos renderOrigin = BlockPos.ZERO;
|
private BlockPos renderOrigin = BlockPos.ZERO;
|
||||||
|
@ -110,12 +110,8 @@ public class EngineImpl implements Engine {
|
||||||
flushFlag.raise();
|
flushFlag.raise();
|
||||||
}
|
}
|
||||||
|
|
||||||
public VisualEmbedding createEmbedding(RenderStage renderStage) {
|
public EnvironmentStorage environmentStorage() {
|
||||||
return environmentStorage.create(renderStage);
|
return environmentStorage;
|
||||||
}
|
|
||||||
|
|
||||||
public void freeEmbedding(EmbeddedEnvironment embeddedEnvironment) {
|
|
||||||
environmentStorage.enqueueDeletion(embeddedEnvironment);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class VisualizationContextImpl implements VisualizationContext {
|
private class VisualizationContextImpl implements VisualizationContext {
|
||||||
|
@ -139,7 +135,9 @@ public class EngineImpl implements Engine {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VisualEmbedding createEmbedding() {
|
public VisualEmbedding createEmbedding() {
|
||||||
return EngineImpl.this.createEmbedding(stage);
|
var out = new TopLevelEmbeddedEnvironment(EngineImpl.this, stage);
|
||||||
|
environmentStorage.track(out);
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,49 +3,38 @@ package com.jozufozu.flywheel.backend.engine;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.event.RenderStage;
|
import com.jozufozu.flywheel.backend.engine.embed.AbstractEmbeddedEnvironment;
|
||||||
import com.jozufozu.flywheel.api.visualization.VisualEmbedding;
|
|
||||||
import com.jozufozu.flywheel.backend.engine.embed.EmbeddedEnvironment;
|
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.objects.ReferenceLinkedOpenHashSet;
|
import it.unimi.dsi.fastutil.objects.ReferenceLinkedOpenHashSet;
|
||||||
import it.unimi.dsi.fastutil.objects.ReferenceSet;
|
import it.unimi.dsi.fastutil.objects.ReferenceSet;
|
||||||
import it.unimi.dsi.fastutil.objects.ReferenceSets;
|
import it.unimi.dsi.fastutil.objects.ReferenceSets;
|
||||||
|
|
||||||
public class EnvironmentStorage {
|
public class EnvironmentStorage {
|
||||||
protected final ReferenceSet<EmbeddedEnvironment> environments = ReferenceSets.synchronize(new ReferenceLinkedOpenHashSet<>());
|
protected final ReferenceSet<AbstractEmbeddedEnvironment> environments = ReferenceSets.synchronize(new ReferenceLinkedOpenHashSet<>());
|
||||||
private final Queue<EmbeddedEnvironment> forDeletion = new ConcurrentLinkedQueue<>();
|
private final Queue<AbstractEmbeddedEnvironment> forDeletion = new ConcurrentLinkedQueue<>();
|
||||||
private final EngineImpl engine;
|
|
||||||
|
|
||||||
public EnvironmentStorage(EngineImpl engine) {
|
public void track(AbstractEmbeddedEnvironment environment) {
|
||||||
this.engine = engine;
|
environments.add(environment);
|
||||||
}
|
}
|
||||||
|
|
||||||
public VisualEmbedding create(RenderStage stage) {
|
public void enqueueDeletion(AbstractEmbeddedEnvironment environment) {
|
||||||
var out = new EmbeddedEnvironment(engine, stage);
|
|
||||||
|
|
||||||
environments.add(out);
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void enqueueDeletion(EmbeddedEnvironment environment) {
|
|
||||||
environments.remove(environment);
|
environments.remove(environment);
|
||||||
|
|
||||||
forDeletion.add(environment);
|
forDeletion.add(environment);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void flush() {
|
public void flush() {
|
||||||
EmbeddedEnvironment env;
|
AbstractEmbeddedEnvironment env;
|
||||||
|
|
||||||
while ((env = forDeletion.poll()) != null) {
|
while ((env = forDeletion.poll()) != null) {
|
||||||
env.actuallyDelete();
|
env.actuallyDelete();
|
||||||
}
|
}
|
||||||
|
|
||||||
environments.forEach(EmbeddedEnvironment::flush);
|
environments.forEach(AbstractEmbeddedEnvironment::flush);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void delete() {
|
public void delete() {
|
||||||
environments.forEach(EmbeddedEnvironment::actuallyDelete);
|
environments.forEach(AbstractEmbeddedEnvironment::actuallyDelete);
|
||||||
environments.clear();
|
environments.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
package com.jozufozu.flywheel.backend.engine.embed;
|
||||||
|
|
||||||
|
import org.joml.Matrix3f;
|
||||||
|
import org.joml.Matrix3fc;
|
||||||
|
import org.joml.Matrix4f;
|
||||||
|
import org.joml.Matrix4fc;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.api.event.RenderStage;
|
||||||
|
import com.jozufozu.flywheel.api.instance.Instance;
|
||||||
|
import com.jozufozu.flywheel.api.instance.InstanceType;
|
||||||
|
import com.jozufozu.flywheel.api.instance.Instancer;
|
||||||
|
import com.jozufozu.flywheel.api.instance.InstancerProvider;
|
||||||
|
import com.jozufozu.flywheel.api.model.Model;
|
||||||
|
import com.jozufozu.flywheel.api.visualization.VisualEmbedding;
|
||||||
|
import com.jozufozu.flywheel.backend.compile.ContextShader;
|
||||||
|
import com.jozufozu.flywheel.backend.engine.EngineImpl;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
|
||||||
|
import com.jozufozu.flywheel.backend.util.AtomicReferenceCounted;
|
||||||
|
|
||||||
|
import net.minecraft.core.Vec3i;
|
||||||
|
|
||||||
|
public abstract class AbstractEmbeddedEnvironment extends AtomicReferenceCounted implements Environment, VisualEmbedding {
|
||||||
|
protected final Matrix4f pose = new Matrix4f();
|
||||||
|
protected final Matrix3f normal = new Matrix3f();
|
||||||
|
private final Matrix4f poseComposed = new Matrix4f();
|
||||||
|
private final Matrix3f normalComposed = new Matrix3f();
|
||||||
|
private final InstancerProvider instancerProvider;
|
||||||
|
private final EngineImpl engine;
|
||||||
|
private final RenderStage renderStage;
|
||||||
|
|
||||||
|
public AbstractEmbeddedEnvironment(EngineImpl engine, RenderStage renderStage) {
|
||||||
|
this.engine = engine;
|
||||||
|
this.renderStage = renderStage;
|
||||||
|
|
||||||
|
instancerProvider = new InstancerProvider() {
|
||||||
|
@Override
|
||||||
|
public <I extends Instance> Instancer<I> instancer(InstanceType<I> type, Model model) {
|
||||||
|
// Kinda cursed usage of anonymous classes here, but it does the job.
|
||||||
|
return engine.instancer(AbstractEmbeddedEnvironment.this, type, model, renderStage);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Acquire the reference owned by the visual that created this.
|
||||||
|
acquire();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void transforms(Matrix4fc pose, Matrix3fc normal) {
|
||||||
|
this.pose.set(pose);
|
||||||
|
this.normal.set(normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void flush() {
|
||||||
|
poseComposed.identity();
|
||||||
|
normalComposed.identity();
|
||||||
|
|
||||||
|
composeMatrices(poseComposed, normalComposed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setupDraw(GlProgram program) {
|
||||||
|
setupLight(program);
|
||||||
|
|
||||||
|
program.setMat4("_flw_modelMatrix", poseComposed);
|
||||||
|
program.setMat3("_flw_normalMatrix", normalComposed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setupCull(GlProgram program) {
|
||||||
|
program.setBool("_flw_useModelMatrix", true);
|
||||||
|
|
||||||
|
program.setMat4("_flw_modelMatrix", poseComposed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ContextShader contextShader() {
|
||||||
|
return ContextShader.EMBEDDED;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InstancerProvider instancerProvider() {
|
||||||
|
return instancerProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vec3i renderOrigin() {
|
||||||
|
return Vec3i.ZERO;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VisualEmbedding createEmbedding() {
|
||||||
|
var out = new NestedEmbeddedEnvironment(this, engine, renderStage);
|
||||||
|
engine.environmentStorage()
|
||||||
|
.track(out);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by visuals
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void delete() {
|
||||||
|
// Release the reference owned by the visual that created this.
|
||||||
|
// Note that visuals don't explicitly call acquire, instead the
|
||||||
|
// storage acquired a reference when this was constructed.
|
||||||
|
release();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when referenceCount goes to 0
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void _delete() {
|
||||||
|
engine.environmentStorage().enqueueDeletion(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void setupLight(GlProgram program);
|
||||||
|
|
||||||
|
public abstract void composeMatrices(Matrix4f pose, Matrix3f normal);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called in EnvironmentStorage#flush
|
||||||
|
*/
|
||||||
|
public abstract void actuallyDelete();
|
||||||
|
}
|
|
@ -1,156 +0,0 @@
|
||||||
package com.jozufozu.flywheel.backend.engine.embed;
|
|
||||||
|
|
||||||
import org.joml.Matrix3f;
|
|
||||||
import org.joml.Matrix3fc;
|
|
||||||
import org.joml.Matrix4f;
|
|
||||||
import org.joml.Matrix4fc;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.event.RenderStage;
|
|
||||||
import com.jozufozu.flywheel.api.instance.Instance;
|
|
||||||
import com.jozufozu.flywheel.api.instance.InstanceType;
|
|
||||||
import com.jozufozu.flywheel.api.instance.Instancer;
|
|
||||||
import com.jozufozu.flywheel.api.instance.InstancerProvider;
|
|
||||||
import com.jozufozu.flywheel.api.model.Model;
|
|
||||||
import com.jozufozu.flywheel.api.visualization.VisualEmbedding;
|
|
||||||
import com.jozufozu.flywheel.backend.Samplers;
|
|
||||||
import com.jozufozu.flywheel.backend.compile.ContextShader;
|
|
||||||
import com.jozufozu.flywheel.backend.engine.EngineImpl;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
|
|
||||||
import com.jozufozu.flywheel.backend.util.AtomicReferenceCounted;
|
|
||||||
|
|
||||||
import net.minecraft.core.Vec3i;
|
|
||||||
import net.minecraft.world.level.BlockAndTintGetter;
|
|
||||||
|
|
||||||
public class EmbeddedEnvironment extends AtomicReferenceCounted implements Environment, VisualEmbedding {
|
|
||||||
private final Matrix4f pose = new Matrix4f();
|
|
||||||
private final Matrix3f normal = new Matrix3f();
|
|
||||||
|
|
||||||
private final EmbeddedLightVolume lightVolume = new EmbeddedLightVolume();
|
|
||||||
private final EmbeddedLightTexture lightTexture = new EmbeddedLightTexture();
|
|
||||||
|
|
||||||
private final InstancerProvider instancerProvider;
|
|
||||||
private final EngineImpl engine;
|
|
||||||
private final RenderStage renderStage;
|
|
||||||
|
|
||||||
public EmbeddedEnvironment(EngineImpl engine, RenderStage renderStage) {
|
|
||||||
this.engine = engine;
|
|
||||||
this.renderStage = renderStage;
|
|
||||||
|
|
||||||
instancerProvider = new InstancerProvider() {
|
|
||||||
@Override
|
|
||||||
public <I extends Instance> Instancer<I> instancer(InstanceType<I> type, Model model) {
|
|
||||||
// Kinda cursed usage of anonymous classes here, but it does the job.
|
|
||||||
return engine.instancer(EmbeddedEnvironment.this, type, model, renderStage);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Acquire the reference owned by the visual that created this.
|
|
||||||
acquire();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void flush() {
|
|
||||||
if (lightVolume.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Samplers.EMBEDDED_LIGHT.makeActive();
|
|
||||||
|
|
||||||
lightTexture.bind();
|
|
||||||
|
|
||||||
lightTexture.ensureCapacity(lightVolume.sizeX(), lightVolume.sizeY(), lightVolume.sizeZ());
|
|
||||||
|
|
||||||
lightTexture.upload(lightVolume.ptr(), lightVolume.sizeX(), lightVolume.sizeY(), lightVolume.sizeZ());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void transforms(Matrix4fc pose, Matrix3fc normal) {
|
|
||||||
this.pose.set(pose);
|
|
||||||
this.normal.set(normal);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void collectLight(BlockAndTintGetter level, int minX, int minY, int minZ, int sizeX, int sizeY, int sizeZ) {
|
|
||||||
lightVolume.collect(level, minX, minY, minZ, sizeX, sizeY, sizeZ);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void invalidateLight() {
|
|
||||||
lightVolume.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ContextShader contextShader() {
|
|
||||||
return ContextShader.EMBEDDED;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setupDraw(GlProgram drawProgram) {
|
|
||||||
if (!lightVolume.empty()) {
|
|
||||||
Samplers.EMBEDDED_LIGHT.makeActive();
|
|
||||||
|
|
||||||
lightTexture.bind();
|
|
||||||
|
|
||||||
float oneOverSizeX = 1f / (float) lightTexture.sizeX;
|
|
||||||
float oneOverSizeY = 1f / (float) lightTexture.sizeY;
|
|
||||||
float oneOverSizeZ = 1f / (float) lightTexture.sizeZ;
|
|
||||||
|
|
||||||
drawProgram.setVec3("_flw_oneOverLightBoxSize", oneOverSizeX, oneOverSizeY, oneOverSizeZ);
|
|
||||||
drawProgram.setVec3("_flw_lightVolumeMin", lightVolume.x(), lightVolume.y(), lightVolume.z());
|
|
||||||
drawProgram.setBool("_flw_useLightVolume", true);
|
|
||||||
} else {
|
|
||||||
drawProgram.setBool("_flw_useLightVolume", false);
|
|
||||||
}
|
|
||||||
drawProgram.setMat4("_flw_model", pose);
|
|
||||||
drawProgram.setMat3("_flw_normal", normal);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setupCull(GlProgram cullProgram) {
|
|
||||||
cullProgram.setBool("_flw_useEmbeddedModel", true);
|
|
||||||
cullProgram.setMat4("_flw_embeddedModel", pose);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public InstancerProvider instancerProvider() {
|
|
||||||
return instancerProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Vec3i renderOrigin() {
|
|
||||||
return Vec3i.ZERO;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public VisualEmbedding createEmbedding() {
|
|
||||||
return engine.createEmbedding(renderStage);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called by visuals
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void delete() {
|
|
||||||
// Release the reference owned by the visual that created this.
|
|
||||||
// Note that visuals don't explicitly call acquire, instead the
|
|
||||||
// storage acquired a reference when this was constructed.
|
|
||||||
release();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when referenceCount goes to 0
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void _delete() {
|
|
||||||
engine.freeEmbedding(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called in EnvironmentStorage#flush
|
|
||||||
*/
|
|
||||||
public void actuallyDelete() {
|
|
||||||
// We could technically free the light volume right away in _delete, but
|
|
||||||
// the control flow here is so convoluted that it's probably best to do
|
|
||||||
// everything in one place.
|
|
||||||
lightVolume.delete();
|
|
||||||
lightTexture.delete();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
package com.jozufozu.flywheel.backend.engine.embed;
|
||||||
|
|
||||||
|
import org.joml.Matrix3f;
|
||||||
|
import org.joml.Matrix4f;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.api.event.RenderStage;
|
||||||
|
import com.jozufozu.flywheel.backend.engine.EngineImpl;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
|
||||||
|
|
||||||
|
import net.minecraft.world.level.BlockAndTintGetter;
|
||||||
|
|
||||||
|
public class NestedEmbeddedEnvironment extends AbstractEmbeddedEnvironment {
|
||||||
|
private final AbstractEmbeddedEnvironment parent;
|
||||||
|
|
||||||
|
public NestedEmbeddedEnvironment(AbstractEmbeddedEnvironment parent, EngineImpl engine, RenderStage renderStage) {
|
||||||
|
super(engine, renderStage);
|
||||||
|
this.parent = parent;
|
||||||
|
parent.acquire();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void collectLight(BlockAndTintGetter level, int minX, int minY, int minZ, int sizeX, int sizeY, int sizeZ) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invalidateLight() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setupLight(GlProgram program) {
|
||||||
|
parent.setupLight(program);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void composeMatrices(Matrix4f pose, Matrix3f normal) {
|
||||||
|
parent.composeMatrices(pose, normal);
|
||||||
|
pose.mul(this.pose);
|
||||||
|
normal.mul(this.normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actuallyDelete() {
|
||||||
|
parent.release();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
package com.jozufozu.flywheel.backend.engine.embed;
|
||||||
|
|
||||||
|
import org.joml.Matrix3f;
|
||||||
|
import org.joml.Matrix4f;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.api.event.RenderStage;
|
||||||
|
import com.jozufozu.flywheel.backend.Samplers;
|
||||||
|
import com.jozufozu.flywheel.backend.engine.EngineImpl;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
|
||||||
|
|
||||||
|
import net.minecraft.world.level.BlockAndTintGetter;
|
||||||
|
|
||||||
|
public class TopLevelEmbeddedEnvironment extends AbstractEmbeddedEnvironment {
|
||||||
|
private final EmbeddedLightVolume lightVolume = new EmbeddedLightVolume();
|
||||||
|
private final EmbeddedLightTexture lightTexture = new EmbeddedLightTexture();
|
||||||
|
|
||||||
|
public TopLevelEmbeddedEnvironment(EngineImpl engine, RenderStage renderStage) {
|
||||||
|
super(engine, renderStage);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void flush() {
|
||||||
|
super.flush();
|
||||||
|
|
||||||
|
if (lightVolume.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Samplers.EMBEDDED_LIGHT.makeActive();
|
||||||
|
|
||||||
|
lightTexture.bind();
|
||||||
|
|
||||||
|
lightTexture.ensureCapacity(lightVolume.sizeX(), lightVolume.sizeY(), lightVolume.sizeZ());
|
||||||
|
|
||||||
|
lightTexture.upload(lightVolume.ptr(), lightVolume.sizeX(), lightVolume.sizeY(), lightVolume.sizeZ());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void collectLight(BlockAndTintGetter level, int minX, int minY, int minZ, int sizeX, int sizeY, int sizeZ) {
|
||||||
|
lightVolume.collect(level, minX, minY, minZ, sizeX, sizeY, sizeZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invalidateLight() {
|
||||||
|
lightVolume.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setupLight(GlProgram program) {
|
||||||
|
if (!lightVolume.empty()) {
|
||||||
|
Samplers.EMBEDDED_LIGHT.makeActive();
|
||||||
|
|
||||||
|
lightTexture.bind();
|
||||||
|
|
||||||
|
float oneOverSizeX = 1f / (float) lightTexture.sizeX;
|
||||||
|
float oneOverSizeY = 1f / (float) lightTexture.sizeY;
|
||||||
|
float oneOverSizeZ = 1f / (float) lightTexture.sizeZ;
|
||||||
|
|
||||||
|
program.setVec3("_flw_oneOverLightBoxSize", oneOverSizeX, oneOverSizeY, oneOverSizeZ);
|
||||||
|
program.setVec3("_flw_lightVolumeMin", lightVolume.x(), lightVolume.y(), lightVolume.z());
|
||||||
|
program.setBool("_flw_useLightVolume", true);
|
||||||
|
} else {
|
||||||
|
program.setBool("_flw_useLightVolume", false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void composeMatrices(Matrix4f pose, Matrix3f normal) {
|
||||||
|
pose.set(this.pose);
|
||||||
|
normal.set(this.normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actuallyDelete() {
|
||||||
|
// We could technically free the light volume right away in _delete, but
|
||||||
|
// the control flow here is so convoluted that it's probably best to do
|
||||||
|
// everything in one place.
|
||||||
|
lightVolume.delete();
|
||||||
|
lightTexture.delete();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
package com.jozufozu.flywheel.lib.util;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.function.LongConsumer;
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.SectionPos;
|
||||||
|
|
||||||
|
public class SectionUtil {
|
||||||
|
public static void containingAll(Collection<BlockPos> blocks, LongConsumer consumer) {
|
||||||
|
if (blocks.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int minX = Integer.MAX_VALUE;
|
||||||
|
int minY = Integer.MAX_VALUE;
|
||||||
|
int minZ = Integer.MAX_VALUE;
|
||||||
|
int maxX = Integer.MIN_VALUE;
|
||||||
|
int maxY = Integer.MIN_VALUE;
|
||||||
|
int maxZ = Integer.MIN_VALUE;
|
||||||
|
for (BlockPos pos : blocks) {
|
||||||
|
minX = Math.min(minX, pos.getX());
|
||||||
|
minY = Math.min(minY, pos.getY());
|
||||||
|
minZ = Math.min(minZ, pos.getZ());
|
||||||
|
maxX = Math.max(maxX, pos.getX());
|
||||||
|
maxY = Math.max(maxY, pos.getY());
|
||||||
|
maxZ = Math.max(maxZ, pos.getZ());
|
||||||
|
}
|
||||||
|
|
||||||
|
betweenClosedBlocks(minX, minY, minZ, maxX, maxY, maxZ, consumer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void betweenClosedBox(int x, int y, int z, int sizeX, int sizeY, int sizeZ, LongConsumer consumer) {
|
||||||
|
betweenClosedBlocks(x, y, z, x + sizeX, y + sizeY, z + sizeZ, consumer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void betweenClosedBlocks(int minX, int minY, int minZ, int maxX, int maxY, int maxZ, LongConsumer consumer) {
|
||||||
|
int minSectionX = SectionPos.blockToSectionCoord(minX);
|
||||||
|
int minSectionY = SectionPos.blockToSectionCoord(minY);
|
||||||
|
int minSectionZ = SectionPos.blockToSectionCoord(minZ);
|
||||||
|
int maxSectionX = SectionPos.blockToSectionCoord(maxX);
|
||||||
|
int maxSectionY = SectionPos.blockToSectionCoord(maxY);
|
||||||
|
int maxSectionZ = SectionPos.blockToSectionCoord(maxZ);
|
||||||
|
|
||||||
|
for (int sectionX = minSectionX; sectionX <= maxSectionX; sectionX++) {
|
||||||
|
for (int sectionY = minSectionY; sectionY <= maxSectionY; sectionY++) {
|
||||||
|
for (int sectionZ = minSectionZ; sectionZ <= maxSectionZ; sectionZ++) {
|
||||||
|
consumer.accept(SectionPos.asLong(sectionX, sectionY, sectionZ));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -69,8 +69,8 @@ vec2 getCrumblingTexCoord() {
|
||||||
#ifdef _FLW_EMBEDDED
|
#ifdef _FLW_EMBEDDED
|
||||||
uniform vec3 _flw_oneOverLightBoxSize;
|
uniform vec3 _flw_oneOverLightBoxSize;
|
||||||
uniform vec3 _flw_lightVolumeMin;
|
uniform vec3 _flw_lightVolumeMin;
|
||||||
uniform mat4 _flw_model;
|
uniform mat4 _flw_modelMatrix;
|
||||||
uniform mat3 _flw_normal;
|
uniform mat3 _flw_normalMatrix;
|
||||||
|
|
||||||
out vec3 _flw_lightVolumeCoord;
|
out vec3 _flw_lightVolumeCoord;
|
||||||
#endif
|
#endif
|
||||||
|
@ -87,8 +87,8 @@ void _flw_main(in FlwInstance instance, in uint stableInstanceID) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _FLW_EMBEDDED
|
#ifdef _FLW_EMBEDDED
|
||||||
flw_vertexPos = _flw_model * flw_vertexPos;
|
flw_vertexPos = _flw_modelMatrix * flw_vertexPos;
|
||||||
flw_vertexNormal = _flw_normal * flw_vertexNormal;
|
flw_vertexNormal = _flw_normalMatrix * flw_vertexNormal;
|
||||||
|
|
||||||
_flw_lightVolumeCoord = (flw_vertexPos.xyz - _flw_lightVolumeMin) * _flw_oneOverLightBoxSize;
|
_flw_lightVolumeCoord = (flw_vertexPos.xyz - _flw_lightVolumeMin) * _flw_oneOverLightBoxSize;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -17,8 +17,8 @@ layout(std430, binding = _FLW_MODEL_BUFFER_BINDING) restrict buffer ModelBuffer
|
||||||
ModelDescriptor _flw_models[];
|
ModelDescriptor _flw_models[];
|
||||||
};
|
};
|
||||||
|
|
||||||
uniform mat4 _flw_embeddedModel;
|
uniform mat4 _flw_modelMatrix;
|
||||||
uniform bool _flw_useEmbeddedModel = false;
|
uniform bool _flw_useModelMatrix = false;
|
||||||
|
|
||||||
// Disgustingly vectorized sphere frustum intersection taking advantage of ahead of time packing.
|
// Disgustingly vectorized sphere frustum intersection taking advantage of ahead of time packing.
|
||||||
// Only uses 6 fmas and some boolean ops.
|
// Only uses 6 fmas and some boolean ops.
|
||||||
|
@ -44,8 +44,8 @@ bool _flw_isVisible(uint instanceIndex, uint modelIndex) {
|
||||||
|
|
||||||
flw_transformBoundingSphere(instance, center, radius);
|
flw_transformBoundingSphere(instance, center, radius);
|
||||||
|
|
||||||
if (_flw_useEmbeddedModel) {
|
if (_flw_useModelMatrix) {
|
||||||
transformBoundingSphere(_flw_embeddedModel, center, radius);
|
transformBoundingSphere(_flw_modelMatrix, center, radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
return _flw_testSphere(center, radius);
|
return _flw_testSphere(center, radius);
|
||||||
|
|
Loading…
Reference in a new issue