mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-01-06 04:16:36 +01:00
Merge remote-tracking branch 'origin/1.20/next' into 1.20/next
# Conflicts: # src/main/java/com/jozufozu/flywheel/backend/compile/PipelineCompiler.java # src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectBuffers.java # src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectCullingGroup.java # src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectDrawManager.java # src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectEngine.java # src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectInstancer.java # src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectModel.java # src/main/resources/assets/flywheel/flywheel/internal/indirect/draw.vert # src/main/resources/assets/flywheel/flywheel/internal/instancing/main.vert # src/main/resources/assets/flywheel/flywheel/internal/layout.vert
This commit is contained in:
commit
ea4ec918a6
100 changed files with 830 additions and 884 deletions
|
@ -7,22 +7,17 @@
|
|||
/*const*/ vec2 flw_vertexLight;
|
||||
/*const*/ vec3 flw_vertexNormal;
|
||||
|
||||
/*const*/ float flw_distance;
|
||||
|
||||
/*const*/ vec4 flw_var0;
|
||||
/*const*/ vec4 flw_var1;
|
||||
/*const*/ vec4 flw_var2;
|
||||
/*const*/ vec4 flw_var3;
|
||||
|
||||
/*const*/ FlwMaterial flw_material;
|
||||
|
||||
/*const*/ vec4 flw_sampleColor;
|
||||
|
||||
/*const*/ float flw_distance;
|
||||
|
||||
vec4 flw_fragColor;
|
||||
ivec2 flw_fragOverlay;
|
||||
vec2 flw_fragLight;
|
||||
|
||||
// To be implemented by material shaders.
|
||||
// To be implemented by the material fragment shader.
|
||||
vec4 flw_fogFilter(vec4 color);
|
||||
bool flw_discardPredicate(vec4 finalColor);
|
||||
void flw_materialFragment();
|
|
@ -10,12 +10,12 @@ const uint FLW_MAT_DEPTH_TEST_ALWAYS = 8u;
|
|||
|
||||
const uint FLW_MAT_TRANSPARENCY_OPAQUE = 0u;
|
||||
const uint FLW_MAT_TRANSPARENCY_ADDITIVE = 1u;
|
||||
const uint FLW_MAT_TRANSPARENCY_LIGHTING = 2u;
|
||||
const uint FLW_MAT_TRANSPARENCY_LIGHTNING = 2u;
|
||||
const uint FLW_MAT_TRANSPARENCY_GLINT = 3u;
|
||||
const uint FLW_MAT_TRANSPARENCY_CRUMBLING = 4u;
|
||||
const uint FLW_MAT_TRANSPARENCY_TRANSLUCENT = 5u;
|
||||
|
||||
const uint FLW_MAT_WRITE_MASK_BOTH = 0u;
|
||||
const uint FLW_MAT_WRITE_MASK_COLOR_DEPTH = 0u;
|
||||
const uint FLW_MAT_WRITE_MASK_COLOR = 1u;
|
||||
const uint FLW_MAT_WRITE_MASK_DEPTH = 2u;
|
||||
|
|
@ -7,20 +7,13 @@ ivec2 flw_vertexOverlay;
|
|||
vec2 flw_vertexLight;
|
||||
vec3 flw_vertexNormal;
|
||||
|
||||
float flw_distance;
|
||||
|
||||
vec4 flw_var0;
|
||||
vec4 flw_var1;
|
||||
vec4 flw_var2;
|
||||
vec4 flw_var3;
|
||||
|
||||
/*const*/ FlwMaterial flw_material;
|
||||
|
||||
// To be implemented by the instance shader.
|
||||
void flw_transformBoundingSphere(in FlwInstance i, inout vec3 center, inout float radius);
|
||||
void flw_instanceVertex(FlwInstance i);
|
||||
|
||||
// To be implemented by material shaders.
|
||||
// To be implemented by the material vertex shader.
|
||||
void flw_materialVertex();
|
||||
|
||||
// To be implemented by the context shader.
|
|
@ -14,7 +14,7 @@ public interface Material {
|
|||
|
||||
CutoutShader cutout();
|
||||
|
||||
ResourceLocation baseTexture();
|
||||
ResourceLocation texture();
|
||||
|
||||
/**
|
||||
* Should this material have linear filtering applied to the diffuse sampler?
|
||||
|
|
|
@ -3,7 +3,7 @@ package com.jozufozu.flywheel.api.material;
|
|||
public enum Transparency {
|
||||
OPAQUE,
|
||||
ADDITIVE,
|
||||
LIGHTING,
|
||||
LIGHTNING,
|
||||
GLINT,
|
||||
CRUMBLING,
|
||||
TRANSLUCENT,
|
||||
|
|
|
@ -4,7 +4,7 @@ public enum WriteMask {
|
|||
/**
|
||||
* Write to both the color and depth buffers.
|
||||
*/
|
||||
BOTH,
|
||||
COLOR_DEPTH,
|
||||
/**
|
||||
* Write to the color buffer only.
|
||||
*/
|
||||
|
@ -15,11 +15,11 @@ public enum WriteMask {
|
|||
DEPTH,
|
||||
;
|
||||
|
||||
public boolean depth() {
|
||||
return this == BOTH || this == DEPTH;
|
||||
public boolean color() {
|
||||
return this == COLOR_DEPTH || this == COLOR;
|
||||
}
|
||||
|
||||
public boolean color() {
|
||||
return this == BOTH || this == COLOR;
|
||||
public boolean depth() {
|
||||
return this == COLOR_DEPTH || this == DEPTH;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,18 +2,24 @@ package com.jozufozu.flywheel.api.model;
|
|||
|
||||
import java.util.Map;
|
||||
|
||||
import org.joml.Vector4fc;
|
||||
|
||||
import com.jozufozu.flywheel.api.material.Material;
|
||||
|
||||
public interface Model {
|
||||
Map<Material, Mesh> getMeshes();
|
||||
Map<Material, Mesh> meshes();
|
||||
|
||||
/**
|
||||
* Get a vec4 representing this model's bounding sphere in the format (x, y, z, radius).
|
||||
* It should encompass all meshes' bounding spheres.
|
||||
*
|
||||
* @return A vec4 view.
|
||||
*/
|
||||
Vector4fc boundingSphere();
|
||||
|
||||
// TODO: unused. remove?
|
||||
@Deprecated
|
||||
int vertexCount();
|
||||
|
||||
void delete();
|
||||
|
||||
default int getVertexCount() {
|
||||
int size = 0;
|
||||
for (Mesh mesh : getMeshes().values()) {
|
||||
size += mesh.vertexCount();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,9 @@ package com.jozufozu.flywheel.api.task;
|
|||
import java.util.concurrent.Executor;
|
||||
import java.util.function.BooleanSupplier;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
@ApiStatus.NonExtendable
|
||||
public interface TaskExecutor extends Executor {
|
||||
/**
|
||||
* Wait for <em>all</em> running tasks to finish.
|
||||
|
@ -38,15 +41,6 @@ public interface TaskExecutor extends Executor {
|
|||
*/
|
||||
boolean syncWhile(BooleanSupplier cond);
|
||||
|
||||
/**
|
||||
* Check for the number of threads this executor uses.
|
||||
* <br>
|
||||
* May be helpful when determining how many chunks to divide a task into.
|
||||
*
|
||||
* @return The number of threads this executor uses.
|
||||
*/
|
||||
int getThreadCount();
|
||||
|
||||
/**
|
||||
* Schedule a task to be run on the main thread.
|
||||
* <br>
|
||||
|
@ -64,4 +58,13 @@ public interface TaskExecutor extends Executor {
|
|||
* @return {@code true} if the current thread is the main thread.
|
||||
*/
|
||||
boolean isMainThread();
|
||||
|
||||
/**
|
||||
* Check for the number of threads this executor uses.
|
||||
* <br>
|
||||
* May be helpful when determining how many chunks to divide a task into.
|
||||
*
|
||||
* @return The number of threads this executor uses.
|
||||
*/
|
||||
int getThreadCount();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package com.jozufozu.flywheel.api.visualization;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
@ApiStatus.NonExtendable
|
||||
public interface VisualManager<T> {
|
||||
/**
|
||||
* Get the number of game objects that are currently being visualized.
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.jozufozu.flywheel.api.visualization;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.jozufozu.flywheel.api.visual.Effect;
|
||||
|
@ -12,6 +13,7 @@ import net.minecraft.world.level.Level;
|
|||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
|
||||
@ApiStatus.NonExtendable
|
||||
public interface VisualizationManager {
|
||||
static boolean supportsVisualization(@Nullable LevelAccessor level) {
|
||||
return VisualizationManagerImpl.supportsVisualization(level);
|
||||
|
|
|
@ -19,7 +19,7 @@ import com.jozufozu.flywheel.backend.compile.core.ShaderCompiler;
|
|||
import com.jozufozu.flywheel.gl.shader.GlProgram;
|
||||
import com.jozufozu.flywheel.gl.shader.GlShader;
|
||||
import com.jozufozu.flywheel.gl.shader.ShaderType;
|
||||
import com.jozufozu.flywheel.glsl.GLSLVersion;
|
||||
import com.jozufozu.flywheel.glsl.GlslVersion;
|
||||
import com.jozufozu.flywheel.glsl.ShaderSources;
|
||||
import com.jozufozu.flywheel.glsl.SourceComponent;
|
||||
|
||||
|
@ -36,7 +36,7 @@ import net.minecraft.resources.ResourceLocation;
|
|||
* @param <K> The type of the key used to compile shaders.
|
||||
*/
|
||||
public class Compile<K> {
|
||||
public ShaderCompilerBuilder<K> shader(GLSLVersion glslVersion, ShaderType shaderType) {
|
||||
public ShaderCompilerBuilder<K> shader(GlslVersion glslVersion, ShaderType shaderType) {
|
||||
return new ShaderCompilerBuilder<>(glslVersion, shaderType);
|
||||
}
|
||||
|
||||
|
@ -99,13 +99,13 @@ public class Compile<K> {
|
|||
}
|
||||
|
||||
public static class ShaderCompilerBuilder<K> {
|
||||
private final GLSLVersion glslVersion;
|
||||
private final GlslVersion glslVersion;
|
||||
private final ShaderType shaderType;
|
||||
private Consumer<Compilation> compilationCallbacks = $ -> {
|
||||
};
|
||||
private final List<BiFunction<K, SourceLoader, SourceComponent>> fetchers = new ArrayList<>();
|
||||
|
||||
public ShaderCompilerBuilder(GLSLVersion glslVersion, ShaderType shaderType) {
|
||||
public ShaderCompilerBuilder(GlslVersion glslVersion, ShaderType shaderType) {
|
||||
this.glslVersion = glslVersion;
|
||||
this.shaderType = shaderType;
|
||||
}
|
||||
|
|
|
@ -24,8 +24,7 @@ public class FlwPrograms {
|
|||
}
|
||||
|
||||
public static void reload(ResourceManager resourceManager) {
|
||||
var empty = List.of(Flywheel.rl("api/fragment.glsl"), Flywheel.rl("api/vertex.glsl"));
|
||||
var sources = new ShaderSources(resourceManager, empty);
|
||||
var sources = new ShaderSources(resourceManager);
|
||||
|
||||
var preLoadStats = new CompilerStats();
|
||||
var loadChecker = new SourceLoader(sources, preLoadStats);
|
||||
|
@ -43,12 +42,31 @@ public class FlwPrograms {
|
|||
}
|
||||
}
|
||||
|
||||
private static ImmutableList<PipelineProgramKey> createPipelineKeys() {
|
||||
ImmutableList.Builder<PipelineProgramKey> builder = ImmutableList.builder();
|
||||
for (Context context : Context.REGISTRY) {
|
||||
for (InstanceType<?> instanceType : InstanceType.REGISTRY) {
|
||||
builder.add(new PipelineProgramKey(instanceType, context));
|
||||
}
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private static UberShaderComponent createVertexMaterialComponent(SourceLoader loadChecker) {
|
||||
return UberShaderComponent.builder(Flywheel.rl("uber_material_vertex"))
|
||||
.materialSources(ShaderIndices.materialVertex()
|
||||
.all())
|
||||
.adapt(FnSignature.ofVoid("flw_materialVertex"))
|
||||
.switchOn(GlslExpr.variable("_flw_uberMaterialVertexIndex"))
|
||||
.build(loadChecker);
|
||||
}
|
||||
|
||||
private static UberShaderComponent createFragmentMaterialComponent(SourceLoader loadChecker) {
|
||||
return UberShaderComponent.builder(Flywheel.rl("uber_fragment_material"))
|
||||
return UberShaderComponent.builder(Flywheel.rl("uber_material_fragment"))
|
||||
.materialSources(ShaderIndices.materialFragment()
|
||||
.all())
|
||||
.adapt(FnSignature.ofVoid("flw_materialFragment"))
|
||||
.switchOn(GlslExpr.variable("_flw_materialFragmentID"))
|
||||
.switchOn(GlslExpr.variable("_flw_uberMaterialFragmentIndex"))
|
||||
.build(loadChecker);
|
||||
}
|
||||
|
||||
|
@ -61,7 +79,7 @@ public class FlwPrograms {
|
|||
.name("flw_fogFilter")
|
||||
.arg("vec4", "color")
|
||||
.build(), GlslExpr.variable("color"))
|
||||
.switchOn(GlslExpr.variable("_flw_fogID"))
|
||||
.switchOn(GlslExpr.variable("_flw_uberFogIndex"))
|
||||
.build(loadChecker);
|
||||
}
|
||||
|
||||
|
@ -74,16 +92,7 @@ public class FlwPrograms {
|
|||
.name("flw_discardPredicate")
|
||||
.arg("vec4", "color")
|
||||
.build(), GlslExpr.boolLiteral(false))
|
||||
.switchOn(GlslExpr.variable("_flw_cutoutID"))
|
||||
.build(loadChecker);
|
||||
}
|
||||
|
||||
private static UberShaderComponent createVertexMaterialComponent(SourceLoader loadChecker) {
|
||||
return UberShaderComponent.builder(Flywheel.rl("vertex_material_adapter"))
|
||||
.materialSources(ShaderIndices.materialVertex()
|
||||
.all())
|
||||
.adapt(FnSignature.ofVoid("flw_materialVertex"))
|
||||
.switchOn(GlslExpr.variable("_flw_materialVertexID"))
|
||||
.switchOn(GlslExpr.variable("_flw_uberCutoutIndex"))
|
||||
.build(loadChecker);
|
||||
}
|
||||
|
||||
|
@ -96,16 +105,6 @@ public class FlwPrograms {
|
|||
.build(loadChecker);
|
||||
}
|
||||
|
||||
private static ImmutableList<PipelineProgramKey> createPipelineKeys() {
|
||||
ImmutableList.Builder<PipelineProgramKey> builder = ImmutableList.builder();
|
||||
for (Context context : Context.REGISTRY) {
|
||||
for (InstanceType<?> instanceType : InstanceType.REGISTRY) {
|
||||
builder.add(new PipelineProgramKey(instanceType, context));
|
||||
}
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public static class ResourceReloadListener implements ResourceManagerReloadListener {
|
||||
public static final ResourceReloadListener INSTANCE = new ResourceReloadListener();
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ import com.jozufozu.flywheel.backend.compile.component.UniformComponent;
|
|||
import com.jozufozu.flywheel.gl.GlCompat;
|
||||
import com.jozufozu.flywheel.gl.shader.GlProgram;
|
||||
import com.jozufozu.flywheel.gl.shader.ShaderType;
|
||||
import com.jozufozu.flywheel.glsl.GLSLVersion;
|
||||
import com.jozufozu.flywheel.glsl.GlslVersion;
|
||||
import com.jozufozu.flywheel.glsl.ShaderSources;
|
||||
import com.jozufozu.flywheel.glsl.SourceComponent;
|
||||
import com.jozufozu.flywheel.lib.util.Unit;
|
||||
|
@ -39,21 +39,22 @@ public class IndirectPrograms {
|
|||
_delete();
|
||||
var pipelineCompiler = PipelineCompiler.create(sources, Pipelines.INDIRECT, pipelineKeys, uniformComponent, vertexComponents, fragmentComponents);
|
||||
var cullingCompiler = createCullingCompiler(uniformComponent, sources);
|
||||
var stage2Compiler = createStage2Compiler(sources);
|
||||
var applyCompiler = createApplyCompiler(sources);
|
||||
|
||||
try {
|
||||
var pipelineResult = pipelineCompiler.compileAndReportErrors();
|
||||
var cullingResult = cullingCompiler.compileAndReportErrors();
|
||||
var stage2Result = stage2Compiler.compileAndReportErrors();
|
||||
var applyResult = applyCompiler.compileAndReportErrors();
|
||||
|
||||
if (pipelineResult != null && cullingResult != null && stage2Result != null) {
|
||||
instance = new IndirectPrograms(pipelineResult, cullingResult, stage2Result.get(Unit.INSTANCE));
|
||||
if (pipelineResult != null && cullingResult != null && applyResult != null) {
|
||||
instance = new IndirectPrograms(pipelineResult, cullingResult, applyResult.get(Unit.INSTANCE));
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
Flywheel.LOGGER.error("Failed to compile indirect programs", e);
|
||||
}
|
||||
pipelineCompiler.delete();
|
||||
cullingCompiler.delete();
|
||||
applyCompiler.delete();
|
||||
}
|
||||
|
||||
private static ImmutableList<InstanceType<?>> createCullingKeys() {
|
||||
|
@ -84,22 +85,22 @@ public class IndirectPrograms {
|
|||
return CULL.harness(sources)
|
||||
.keys(createCullingKeys())
|
||||
.compiler(CULL.program()
|
||||
.link(CULL.shader(GLSLVersion.V460, ShaderType.COMPUTE)
|
||||
.define("FLW_SUBGROUP_SIZE", GlCompat.SUBGROUP_SIZE)
|
||||
.link(CULL.shader(GlslVersion.V460, ShaderType.COMPUTE)
|
||||
.define("_FLW_SUBGROUP_SIZE", GlCompat.SUBGROUP_SIZE)
|
||||
.withComponent(uniformComponent)
|
||||
.withComponent(IndirectComponent::create)
|
||||
.withResource(Files.INDIRECT_CULL)
|
||||
.withResource(InstanceType::instanceShader))
|
||||
.then((key, program) -> program.setUniformBlockBinding("FLWUniforms", 0)))
|
||||
.then((key, program) -> program.setUniformBlockBinding("FlwUniforms", 0)))
|
||||
.build();
|
||||
}
|
||||
|
||||
private static CompilationHarness<Unit> createStage2Compiler(ShaderSources sources) {
|
||||
private static CompilationHarness<Unit> createApplyCompiler(ShaderSources sources) {
|
||||
return APPLY.harness(sources)
|
||||
.keys(ImmutableList.of(Unit.INSTANCE))
|
||||
.compiler(APPLY.program()
|
||||
.link(APPLY.shader(GLSLVersion.V460, ShaderType.COMPUTE)
|
||||
.define("FLW_SUBGROUP_SIZE", GlCompat.SUBGROUP_SIZE)
|
||||
.link(APPLY.shader(GlslVersion.V460, ShaderType.COMPUTE)
|
||||
.define("_FLW_SUBGROUP_SIZE", GlCompat.SUBGROUP_SIZE)
|
||||
.withResource(Files.INDIRECT_APPLY)))
|
||||
.build();
|
||||
}
|
||||
|
|
|
@ -3,13 +3,13 @@ package com.jozufozu.flywheel.backend.compile;
|
|||
import java.util.Objects;
|
||||
|
||||
import com.jozufozu.flywheel.api.instance.InstanceType;
|
||||
import com.jozufozu.flywheel.glsl.GLSLVersion;
|
||||
import com.jozufozu.flywheel.glsl.GlslVersion;
|
||||
import com.jozufozu.flywheel.glsl.SourceComponent;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
public record Pipeline(GLSLVersion glslVersion, ResourceLocation vertexShader, ResourceLocation fragmentShader,
|
||||
ResourceLocation vertexAPI, ResourceLocation fragmentAPI, InstanceAssembler assembler) {
|
||||
public record Pipeline(GlslVersion glslVersion, ResourceLocation vertexMain, ResourceLocation fragmentMain,
|
||||
ResourceLocation vertexApiImpl, ResourceLocation fragmentApiImpl, InstanceAssembler assembler) {
|
||||
@FunctionalInterface
|
||||
public interface InstanceAssembler {
|
||||
/**
|
||||
|
@ -28,35 +28,35 @@ public record Pipeline(GLSLVersion glslVersion, ResourceLocation vertexShader, R
|
|||
}
|
||||
|
||||
public static class Builder {
|
||||
private GLSLVersion glslVersion;
|
||||
private ResourceLocation vertex;
|
||||
private ResourceLocation fragment;
|
||||
private ResourceLocation vertexAPI;
|
||||
private ResourceLocation fragmentAPI;
|
||||
private GlslVersion glslVersion;
|
||||
private ResourceLocation vertexMain;
|
||||
private ResourceLocation fragmentMain;
|
||||
private ResourceLocation vertexApiImpl;
|
||||
private ResourceLocation fragmentApiImpl;
|
||||
private InstanceAssembler assembler;
|
||||
|
||||
public Builder glslVersion(GLSLVersion glslVersion) {
|
||||
public Builder glslVersion(GlslVersion glslVersion) {
|
||||
this.glslVersion = glslVersion;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder vertex(ResourceLocation vertex) {
|
||||
this.vertex = vertex;
|
||||
public Builder vertexMain(ResourceLocation shader) {
|
||||
this.vertexMain = shader;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder fragment(ResourceLocation fragment) {
|
||||
this.fragment = fragment;
|
||||
public Builder fragmentMain(ResourceLocation shader) {
|
||||
this.fragmentMain = shader;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder vertexAPI(ResourceLocation vertex) {
|
||||
this.vertexAPI = vertex;
|
||||
public Builder vertexApiImpl(ResourceLocation shader) {
|
||||
this.vertexApiImpl = shader;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder fragmentAPI(ResourceLocation fragment) {
|
||||
this.fragmentAPI = fragment;
|
||||
public Builder fragmentApiImpl(ResourceLocation shader) {
|
||||
this.fragmentApiImpl = shader;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -67,12 +67,12 @@ public record Pipeline(GLSLVersion glslVersion, ResourceLocation vertexShader, R
|
|||
|
||||
public Pipeline build() {
|
||||
Objects.requireNonNull(glslVersion);
|
||||
Objects.requireNonNull(vertex);
|
||||
Objects.requireNonNull(fragment);
|
||||
Objects.requireNonNull(vertexAPI);
|
||||
Objects.requireNonNull(fragmentAPI);
|
||||
Objects.requireNonNull(vertexMain);
|
||||
Objects.requireNonNull(fragmentMain);
|
||||
Objects.requireNonNull(vertexApiImpl);
|
||||
Objects.requireNonNull(fragmentApiImpl);
|
||||
Objects.requireNonNull(assembler);
|
||||
return new Pipeline(glslVersion, vertex, fragment, vertexAPI, fragmentAPI, assembler);
|
||||
return new Pipeline(glslVersion, vertexMain, fragmentMain, vertexApiImpl, fragmentApiImpl, assembler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,25 +20,25 @@ public class PipelineCompiler {
|
|||
.withComponent(uniformComponent)
|
||||
.withComponent(key -> pipeline.assembler()
|
||||
.assemble(new Pipeline.InstanceAssemblerContext(InternalLayout.LAYOUT.getAttributeCount(), key.instanceType())))
|
||||
.withResource(pipeline.vertexAPI())
|
||||
.withResource(pipeline.vertexApiImpl())
|
||||
.withComponents(vertexComponents)
|
||||
.withResource(key -> key.instanceType()
|
||||
.instanceShader())
|
||||
.withResource(key -> key.contextShader()
|
||||
.vertexShader())
|
||||
.withResource(pipeline.vertexShader()))
|
||||
.withResource(pipeline.vertexMain()))
|
||||
.link(PIPELINE.shader(pipeline.glslVersion(), ShaderType.FRAGMENT)
|
||||
.enableExtension("GL_ARB_conservative_depth")
|
||||
.withComponent(uniformComponent)
|
||||
.withResource(pipeline.fragmentAPI())
|
||||
.withResource(pipeline.fragmentApiImpl())
|
||||
.withComponents(fragmentComponents)
|
||||
.withResource(key -> key.contextShader()
|
||||
.fragmentShader())
|
||||
.withResource(pipeline.fragmentShader()))
|
||||
.withResource(pipeline.fragmentMain()))
|
||||
.then((key, program) -> {
|
||||
key.contextShader()
|
||||
.onProgramLink(program);
|
||||
program.setUniformBlockBinding("FLWUniforms", 0);
|
||||
program.setUniformBlockBinding("FlwUniforms", 0);
|
||||
}))
|
||||
.build();
|
||||
}
|
||||
|
|
|
@ -3,23 +3,23 @@ package com.jozufozu.flywheel.backend.compile;
|
|||
import com.jozufozu.flywheel.Flywheel;
|
||||
import com.jozufozu.flywheel.backend.compile.component.IndirectComponent;
|
||||
import com.jozufozu.flywheel.backend.compile.component.InstancedArraysComponent;
|
||||
import com.jozufozu.flywheel.glsl.GLSLVersion;
|
||||
import com.jozufozu.flywheel.glsl.GlslVersion;
|
||||
|
||||
public final class Pipelines {
|
||||
public static final Pipeline INSTANCED_ARRAYS = Pipeline.builder()
|
||||
.glslVersion(GLSLVersion.V330)
|
||||
.vertex(Flywheel.rl("internal/instancing/draw.vert"))
|
||||
.fragment(Flywheel.rl("internal/instancing/draw.frag"))
|
||||
.vertexAPI(Flywheel.rl("internal/instancing/api/vertex.glsl"))
|
||||
.fragmentAPI(Flywheel.rl("internal/instancing/api/fragment.glsl"))
|
||||
.glslVersion(GlslVersion.V330)
|
||||
.vertexMain(Flywheel.rl("internal/instancing/main.vert"))
|
||||
.fragmentMain(Flywheel.rl("internal/instancing/main.frag"))
|
||||
.vertexApiImpl(Flywheel.rl("internal/instancing/api_impl.vert"))
|
||||
.fragmentApiImpl(Flywheel.rl("internal/instancing/api_impl.frag"))
|
||||
.assembler(InstancedArraysComponent::new)
|
||||
.build();
|
||||
public static final Pipeline INDIRECT = Pipeline.builder()
|
||||
.glslVersion(GLSLVersion.V460)
|
||||
.vertex(Flywheel.rl("internal/indirect/draw.vert"))
|
||||
.fragment(Flywheel.rl("internal/indirect/draw.frag"))
|
||||
.vertexAPI(Flywheel.rl("internal/indirect/api/vertex.glsl"))
|
||||
.fragmentAPI(Flywheel.rl("internal/indirect/api/fragment.glsl"))
|
||||
.glslVersion(GlslVersion.V460)
|
||||
.vertexMain(Flywheel.rl("internal/indirect/main.vert"))
|
||||
.fragmentMain(Flywheel.rl("internal/indirect/main.frag"))
|
||||
.vertexApiImpl(Flywheel.rl("internal/indirect/api_impl.vert"))
|
||||
.fragmentApiImpl(Flywheel.rl("internal/indirect/api_impl.frag"))
|
||||
.assembler(IndirectComponent::create)
|
||||
.build();
|
||||
}
|
||||
|
|
|
@ -36,8 +36,8 @@ public class UniformComponent implements SourceComponent {
|
|||
|
||||
builder.uniformBlock()
|
||||
.layout("std140")
|
||||
.name("FLWUniforms")
|
||||
.member("flywheel_uniforms", "flywheel");
|
||||
.name("FlwUniforms")
|
||||
.member("FlywheelUniforms", "flywheel");
|
||||
|
||||
builder.blankLine();
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ import com.jozufozu.flywheel.Flywheel;
|
|||
import com.jozufozu.flywheel.gl.GlCompat;
|
||||
import com.jozufozu.flywheel.gl.shader.GlShader;
|
||||
import com.jozufozu.flywheel.gl.shader.ShaderType;
|
||||
import com.jozufozu.flywheel.glsl.GLSLVersion;
|
||||
import com.jozufozu.flywheel.glsl.GlslVersion;
|
||||
import com.jozufozu.flywheel.glsl.SourceComponent;
|
||||
import com.jozufozu.flywheel.glsl.SourceFile;
|
||||
import com.jozufozu.flywheel.lib.util.StringUtil;
|
||||
|
@ -31,11 +31,11 @@ public class Compilation {
|
|||
private final List<SourceFile> files = new ArrayList<>();
|
||||
private final StringBuilder generatedSource;
|
||||
private final StringBuilder fullSource;
|
||||
private final GLSLVersion glslVersion;
|
||||
private final GlslVersion glslVersion;
|
||||
private final ShaderType shaderType;
|
||||
private int generatedLines = 0;
|
||||
|
||||
public Compilation(GLSLVersion glslVersion, ShaderType shaderType) {
|
||||
public Compilation(GlslVersion glslVersion, ShaderType shaderType) {
|
||||
this.glslVersion = glslVersion;
|
||||
this.shaderType = shaderType;
|
||||
|
||||
|
@ -88,12 +88,12 @@ public class Compilation {
|
|||
|
||||
private void appendHeader(SourceComponent component, String source) {
|
||||
if (component instanceof SourceFile file) {
|
||||
int fileID = files.size() + 1;
|
||||
int fileId = files.size() + 1;
|
||||
|
||||
files.add(file);
|
||||
|
||||
fullSource.append("\n#line 0 ")
|
||||
.append(fileID)
|
||||
.append(fileId)
|
||||
.append(" // ")
|
||||
.append(file.name)
|
||||
.append('\n');
|
||||
|
|
|
@ -12,7 +12,7 @@ import org.jetbrains.annotations.Nullable;
|
|||
|
||||
import com.jozufozu.flywheel.gl.shader.GlShader;
|
||||
import com.jozufozu.flywheel.gl.shader.ShaderType;
|
||||
import com.jozufozu.flywheel.glsl.GLSLVersion;
|
||||
import com.jozufozu.flywheel.glsl.GlslVersion;
|
||||
import com.jozufozu.flywheel.glsl.SourceComponent;
|
||||
|
||||
public class ShaderCompiler {
|
||||
|
@ -24,7 +24,7 @@ public class ShaderCompiler {
|
|||
}
|
||||
|
||||
@Nullable
|
||||
public GlShader compile(GLSLVersion glslVersion, ShaderType shaderType, Consumer<Compilation> callback, List<SourceComponent> sourceComponents) {
|
||||
public GlShader compile(GlslVersion glslVersion, ShaderType shaderType, Consumer<Compilation> callback, List<SourceComponent> sourceComponents) {
|
||||
var key = new ShaderKey(glslVersion, shaderType, sourceComponents);
|
||||
var cached = shaderCache.get(key);
|
||||
if (cached != null) {
|
||||
|
@ -67,6 +67,6 @@ public class ShaderCompiler {
|
|||
included.addAll(component.included());
|
||||
}
|
||||
|
||||
private record ShaderKey(GLSLVersion glslVersion, ShaderType shaderType, List<SourceComponent> sourceComponents) {
|
||||
private record ShaderKey(GlslVersion glslVersion, ShaderType shaderType, List<SourceComponent> sourceComponents) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
package com.jozufozu.flywheel.backend;
|
||||
package com.jozufozu.flywheel.backend.engine;
|
||||
|
||||
import com.jozufozu.flywheel.api.material.DepthTest;
|
||||
import com.jozufozu.flywheel.api.material.Material;
|
||||
import com.jozufozu.flywheel.api.material.Transparency;
|
||||
import com.jozufozu.flywheel.api.material.WriteMask;
|
||||
import com.jozufozu.flywheel.backend.ShaderIndices;
|
||||
|
||||
import net.minecraft.util.Mth;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.jozufozu.flywheel.backend;
|
||||
package com.jozufozu.flywheel.backend.engine;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
|
@ -16,7 +16,7 @@ import net.minecraft.client.Minecraft;
|
|||
import net.minecraft.client.renderer.texture.AbstractTexture;
|
||||
|
||||
public final class MaterialRenderState {
|
||||
public static final Comparator<Material> COMPARATOR = Comparator.comparing(Material::baseTexture)
|
||||
public static final Comparator<Material> COMPARATOR = Comparator.comparing(Material::texture)
|
||||
.thenComparing(Material::blur)
|
||||
.thenComparing(Material::mipmap)
|
||||
.thenComparing(Material::backfaceCulling)
|
||||
|
@ -41,7 +41,7 @@ public final class MaterialRenderState {
|
|||
GlTextureUnit.T0.makeActive();
|
||||
AbstractTexture texture = Minecraft.getInstance()
|
||||
.getTextureManager()
|
||||
.getTexture(material.baseTexture());
|
||||
.getTexture(material.texture());
|
||||
texture.setFilter(material.blur(), material.mipmap());
|
||||
var textureId = texture.getId();
|
||||
RenderSystem.setShaderTexture(0, textureId);
|
||||
|
@ -62,7 +62,7 @@ public final class MaterialRenderState {
|
|||
RenderSystem.enablePolygonOffset();
|
||||
} else {
|
||||
RenderSystem.polygonOffset(0.0F, 0.0F);
|
||||
RenderSystem.enablePolygonOffset();
|
||||
RenderSystem.disablePolygonOffset();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,7 +115,7 @@ public final class MaterialRenderState {
|
|||
RenderSystem.enableBlend();
|
||||
RenderSystem.blendFunc(GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ONE);
|
||||
}
|
||||
case LIGHTING -> {
|
||||
case LIGHTNING -> {
|
||||
RenderSystem.enableBlend();
|
||||
RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE);
|
||||
}
|
|
@ -9,39 +9,30 @@ import com.google.common.collect.ImmutableList;
|
|||
import com.jozufozu.flywheel.api.event.ReloadLevelRendererEvent;
|
||||
import com.jozufozu.flywheel.api.uniform.ShaderUniforms;
|
||||
import com.jozufozu.flywheel.gl.buffer.GlBuffer;
|
||||
import com.jozufozu.flywheel.gl.shader.GlProgram;
|
||||
import com.jozufozu.flywheel.lib.math.MoreMath;
|
||||
import com.jozufozu.flywheel.lib.memory.MemoryBlock;
|
||||
|
||||
import net.minecraft.util.Mth;
|
||||
|
||||
public class UniformBuffer {
|
||||
|
||||
private static final int OFFSET_ALIGNMENT = GL32.glGetInteger(GL32.GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT);
|
||||
private static final int MAX_SIZE = GL32.glGetInteger(GL32.GL_MAX_UNIFORM_BLOCK_SIZE);
|
||||
private static final int MAX_BINDINGS = GL32.glGetInteger(GL32.GL_MAX_UNIFORM_BUFFER_BINDINGS);
|
||||
private static final boolean PO2_ALIGNMENT = Mth.isPowerOfTwo(OFFSET_ALIGNMENT);
|
||||
// private static final int OFFSET_ALIGNMENT = GL32.glGetInteger(GL32.GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT);
|
||||
// private static final int MAX_SIZE = GL32.glGetInteger(GL32.GL_MAX_UNIFORM_BLOCK_SIZE);
|
||||
// private static final int MAX_BINDINGS = GL32.glGetInteger(GL32.GL_MAX_UNIFORM_BUFFER_BINDINGS);
|
||||
// private static final boolean PO2_ALIGNMENT = Mth.isPowerOfTwo(OFFSET_ALIGNMENT);
|
||||
|
||||
private static UniformBuffer instance;
|
||||
private final ProviderSet providerSet;
|
||||
|
||||
public static UniformBuffer getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new UniformBuffer();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private final GlBuffer buffer;
|
||||
private final ProviderSet providerSet;
|
||||
|
||||
private UniformBuffer() {
|
||||
buffer = new GlBuffer();
|
||||
providerSet = new ProviderSet(ShaderUniforms.REGISTRY.getAll());
|
||||
}
|
||||
|
||||
public static void syncAndBind(GlProgram program) {
|
||||
getInstance().sync();
|
||||
program.bind();
|
||||
public static UniformBuffer get() {
|
||||
if (instance == null) {
|
||||
instance = new UniformBuffer();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void sync() {
|
||||
|
@ -52,15 +43,6 @@ public class UniformBuffer {
|
|||
GL32.glBindBufferRange(GL32.GL_UNIFORM_BUFFER, 0, buffer.handle(), 0, providerSet.data.size());
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/questions/3407012/rounding-up-to-the-nearest-multiple-of-a-number
|
||||
private static int alignUniformBuffer(int numToRound) {
|
||||
if (PO2_ALIGNMENT) {
|
||||
return (numToRound + OFFSET_ALIGNMENT - 1) & -OFFSET_ALIGNMENT;
|
||||
} else {
|
||||
return ((numToRound + OFFSET_ALIGNMENT - 1) / OFFSET_ALIGNMENT) * OFFSET_ALIGNMENT;
|
||||
}
|
||||
}
|
||||
|
||||
private void delete() {
|
||||
providerSet.delete();
|
||||
buffer.delete();
|
||||
|
@ -73,6 +55,15 @@ public class UniformBuffer {
|
|||
}
|
||||
}
|
||||
|
||||
// // https://stackoverflow.com/questions/3407012/rounding-up-to-the-nearest-multiple-of-a-number
|
||||
// private static int alignUniformBuffer(int numToRound) {
|
||||
// if (PO2_ALIGNMENT) {
|
||||
// return (numToRound + OFFSET_ALIGNMENT - 1) & -OFFSET_ALIGNMENT;
|
||||
// } else {
|
||||
// return ((numToRound + OFFSET_ALIGNMENT - 1) / OFFSET_ALIGNMENT) * OFFSET_ALIGNMENT;
|
||||
// }
|
||||
// }
|
||||
|
||||
private static class LiveProvider {
|
||||
private final ShaderUniforms shaderUniforms;
|
||||
private final int offset;
|
||||
|
|
|
@ -48,7 +48,7 @@ class BatchedDrawManager extends InstancerStorage<BatchedInstancer<?>> {
|
|||
@Override
|
||||
protected <I extends Instance> void add(InstancerKey<I> key, BatchedInstancer<?> instancer, Model model, RenderStage stage) {
|
||||
var stagePlan = stagePlans.computeIfAbsent(stage, renderStage -> new BatchedStagePlan(renderStage, drawTracker));
|
||||
var meshes = model.getMeshes();
|
||||
var meshes = model.meshes();
|
||||
for (var entry : meshes.entrySet()) {
|
||||
var material = entry.getKey();
|
||||
RenderType renderType = material.getFallbackRenderType();
|
||||
|
|
|
@ -16,12 +16,12 @@ public class IndirectBuffers {
|
|||
public static final long INT_SIZE = Integer.BYTES;
|
||||
public static final long PTR_SIZE = Pointer.POINTER_SIZE;
|
||||
|
||||
public static final long MODEL_STRIDE = 24;
|
||||
|
||||
// Byte size of a draw command, plus our added mesh data.
|
||||
public static final long DRAW_COMMAND_STRIDE = 40;
|
||||
public static final long DRAW_COMMAND_OFFSET = 0;
|
||||
|
||||
public static final long MODEL_STRIDE = 24;
|
||||
|
||||
// Offsets to the 3 segments
|
||||
private static final long HANDLE_OFFSET = 0;
|
||||
private static final long OFFSET_OFFSET = BUFFER_COUNT * INT_SIZE;
|
||||
|
@ -41,6 +41,9 @@ public class IndirectBuffers {
|
|||
private static final long MODEL_SIZE_OFFSET = SIZE_OFFSET + PTR_SIZE * 2;
|
||||
private static final long DRAW_SIZE_OFFSET = SIZE_OFFSET + PTR_SIZE * 3;
|
||||
|
||||
private static final float OBJECT_GROWTH_FACTOR = 1.25f;
|
||||
private static final float MODEL_GROWTH_FACTOR = 2f;
|
||||
private static final float DRAW_GROWTH_FACTOR = 2f;
|
||||
|
||||
/**
|
||||
* A small block of memory divided into 3 contiguous segments:
|
||||
|
@ -65,13 +68,13 @@ public class IndirectBuffers {
|
|||
this.objectStride = objectStride;
|
||||
this.multiBindBlock = MemoryBlock.calloc(BUFFERS_SIZE_BYTES, 1);
|
||||
|
||||
object = new ResizableStorageArray(objectStride, 1.75);
|
||||
target = new ResizableStorageArray(INT_SIZE, 1.75);
|
||||
model = new ResizableStorageArray(MODEL_STRIDE, 2);
|
||||
draw = new ResizableStorageArray(DRAW_COMMAND_STRIDE, 2);
|
||||
object = new ResizableStorageArray(objectStride, OBJECT_GROWTH_FACTOR);
|
||||
target = new ResizableStorageArray(INT_SIZE, OBJECT_GROWTH_FACTOR);
|
||||
model = new ResizableStorageArray(MODEL_STRIDE, MODEL_GROWTH_FACTOR);
|
||||
draw = new ResizableStorageArray(DRAW_COMMAND_STRIDE, DRAW_GROWTH_FACTOR);
|
||||
}
|
||||
|
||||
void updateCounts(int objectCount, int drawCount, int modelCount) {
|
||||
void updateCounts(int objectCount, int modelCount, int drawCount) {
|
||||
object.ensureCapacity(objectCount);
|
||||
target.ensureCapacity(objectCount);
|
||||
model.ensureCapacity(modelCount);
|
||||
|
|
|
@ -21,67 +21,114 @@ import com.jozufozu.flywheel.api.instance.InstanceType;
|
|||
import com.jozufozu.flywheel.api.material.Material;
|
||||
import com.jozufozu.flywheel.api.model.Mesh;
|
||||
import com.jozufozu.flywheel.api.model.Model;
|
||||
import com.jozufozu.flywheel.backend.MaterialRenderState;
|
||||
import com.jozufozu.flywheel.backend.compile.IndirectPrograms;
|
||||
import com.jozufozu.flywheel.backend.engine.MaterialRenderState;
|
||||
import com.jozufozu.flywheel.backend.engine.UniformBuffer;
|
||||
import com.jozufozu.flywheel.gl.GlCompat;
|
||||
import com.jozufozu.flywheel.gl.shader.GlProgram;
|
||||
import com.jozufozu.flywheel.lib.context.Contexts;
|
||||
import com.jozufozu.flywheel.lib.model.ModelUtil;
|
||||
|
||||
public class IndirectCullingGroup<I extends Instance> {
|
||||
private static final Comparator<IndirectDraw> DRAW_COMPARATOR = Comparator.comparing(IndirectDraw::stage)
|
||||
.thenComparing(IndirectDraw::material, MaterialRenderState.COMPARATOR);
|
||||
|
||||
private static final int DRAW_BARRIER_BITS = GL_SHADER_STORAGE_BARRIER_BIT | GL_COMMAND_BARRIER_BIT;
|
||||
|
||||
private final GlProgram cull;
|
||||
private final GlProgram draw;
|
||||
private final GlProgram cullProgram;
|
||||
private final GlProgram applyProgram;
|
||||
private final GlProgram drawProgram;
|
||||
|
||||
private final long objectStride;
|
||||
private final IndirectBuffers buffers;
|
||||
public final IndirectMeshPool meshPool;
|
||||
private final IndirectMeshPool meshPool;
|
||||
private final List<IndirectModel> indirectModels = new ArrayList<>();
|
||||
private final List<IndirectDraw> indirectDraws = new ArrayList<>();
|
||||
private final Map<RenderStage, List<MultiDraw>> multiDraws = new EnumMap<>(RenderStage.class);
|
||||
private boolean needsDrawBarrier;
|
||||
private boolean needsSortDraws;
|
||||
private int instanceCountThisFrame;
|
||||
private final GlProgram apply;
|
||||
|
||||
IndirectCullingGroup(InstanceType<I> instanceType) {
|
||||
var programs = IndirectPrograms.get();
|
||||
cullProgram = programs.getCullingProgram(instanceType);
|
||||
applyProgram = programs.getApplyProgram();
|
||||
drawProgram = programs.getIndirectProgram(instanceType, Contexts.DEFAULT);
|
||||
|
||||
objectStride = instanceType.getLayout()
|
||||
.getStride() + IndirectBuffers.INT_SIZE;
|
||||
|
||||
buffers = new IndirectBuffers(objectStride);
|
||||
|
||||
meshPool = new IndirectMeshPool();
|
||||
|
||||
var indirectPrograms = IndirectPrograms.get();
|
||||
cull = indirectPrograms.getCullingProgram(instanceType);
|
||||
apply = indirectPrograms.getApplyProgram();
|
||||
draw = indirectPrograms.getIndirectProgram(instanceType, Contexts.WORLD);
|
||||
}
|
||||
|
||||
public void add(IndirectInstancer<I> instancer, RenderStage stage, Model model) {
|
||||
var meshes = model.getMeshes();
|
||||
public void flush(StagingBuffer stagingBuffer) {
|
||||
needsDrawBarrier = true;
|
||||
instanceCountThisFrame = prepareModels();
|
||||
|
||||
var boundingSphere = ModelUtil.computeBoundingSphere(meshes.values());
|
||||
|
||||
int modelId = indirectModels.size();
|
||||
instancer.setModelId(modelId);
|
||||
var indirectModel = new IndirectModel(instancer, modelId, boundingSphere);
|
||||
indirectModels.add(indirectModel);
|
||||
|
||||
for (Map.Entry<Material, Mesh> materialMeshEntry : meshes.entrySet()) {
|
||||
IndirectMeshPool.BufferedMesh bufferedMesh = meshPool.alloc(materialMeshEntry.getValue());
|
||||
indirectDraws.add(new IndirectDraw(indirectModel, materialMeshEntry.getKey(), bufferedMesh, stage));
|
||||
if (nothingToDo()) {
|
||||
return;
|
||||
}
|
||||
|
||||
needsSortDraws = true;
|
||||
buffers.updateCounts(instanceCountThisFrame, indirectModels.size(), indirectDraws.size());
|
||||
|
||||
if (needsSortDraws) {
|
||||
sortDraws();
|
||||
needsSortDraws = false;
|
||||
}
|
||||
|
||||
meshPool.flush(stagingBuffer);
|
||||
uploadObjects(stagingBuffer);
|
||||
uploadModels(stagingBuffer);
|
||||
uploadDraws(stagingBuffer);
|
||||
}
|
||||
|
||||
public void dispatchCull() {
|
||||
if (nothingToDo()) {
|
||||
return;
|
||||
}
|
||||
|
||||
UniformBuffer.get().sync();
|
||||
cullProgram.bind();
|
||||
buffers.bindForCompute();
|
||||
glDispatchCompute(GlCompat.getComputeGroupCount(instanceCountThisFrame), 1, 1);
|
||||
}
|
||||
|
||||
public void dispatchApply() {
|
||||
if (nothingToDo()) {
|
||||
return;
|
||||
}
|
||||
|
||||
applyProgram.bind();
|
||||
buffers.bindForCompute();
|
||||
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
|
||||
glDispatchCompute(GlCompat.getComputeGroupCount(indirectDraws.size()), 1, 1);
|
||||
}
|
||||
|
||||
private boolean nothingToDo() {
|
||||
return indirectDraws.isEmpty() || instanceCountThisFrame == 0;
|
||||
}
|
||||
|
||||
private boolean nothingToDo(RenderStage stage) {
|
||||
return nothingToDo() || !multiDraws.containsKey(stage);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the total instance count
|
||||
*/
|
||||
private int prepareModels() {
|
||||
int baseInstance = 0;
|
||||
for (var model : indirectModels) {
|
||||
model.prepare(baseInstance);
|
||||
baseInstance += model.instancer.getInstanceCount();
|
||||
}
|
||||
return baseInstance;
|
||||
}
|
||||
|
||||
private void sortDraws() {
|
||||
multiDraws.clear();
|
||||
// sort by stage, then material
|
||||
indirectDraws.sort(Comparator.comparing(IndirectDraw::stage)
|
||||
.thenComparing(IndirectDraw::material, MaterialRenderState.COMPARATOR));
|
||||
indirectDraws.sort(DRAW_COMPARATOR);
|
||||
|
||||
for (int start = 0, i = 0; i < indirectDraws.size(); i++) {
|
||||
var draw1 = indirectDraws.get(i);
|
||||
|
@ -99,52 +146,22 @@ public class IndirectCullingGroup<I extends Instance> {
|
|||
}
|
||||
}
|
||||
|
||||
public void flush(StagingBuffer stagingBuffer) {
|
||||
needsDrawBarrier = true;
|
||||
instanceCountThisFrame = calculateTotalInstanceCountAndPrepareBatches();
|
||||
|
||||
if (nothingToDo()) {
|
||||
return;
|
||||
}
|
||||
|
||||
buffers.updateCounts(instanceCountThisFrame, indirectDraws.size(), indirectModels.size());
|
||||
|
||||
if (needsSortDraws) {
|
||||
sortDraws();
|
||||
needsSortDraws = false;
|
||||
}
|
||||
|
||||
meshPool.flush(stagingBuffer);
|
||||
uploadInstances(stagingBuffer);
|
||||
uploadModels(stagingBuffer);
|
||||
uploadIndirectCommands(stagingBuffer);
|
||||
public boolean hasStage(RenderStage stage) {
|
||||
return multiDraws.containsKey(stage);
|
||||
}
|
||||
|
||||
public void dispatchCull() {
|
||||
if (nothingToDo()) {
|
||||
return;
|
||||
public void add(IndirectInstancer<I> instancer, Model model, RenderStage stage) {
|
||||
int modelIndex = indirectModels.size();
|
||||
instancer.setModelIndex(modelIndex);
|
||||
var indirectModel = new IndirectModel(instancer, modelIndex, model.boundingSphere());
|
||||
indirectModels.add(indirectModel);
|
||||
|
||||
for (Map.Entry<Material, Mesh> entry : model.meshes().entrySet()) {
|
||||
IndirectMeshPool.BufferedMesh bufferedMesh = meshPool.alloc(entry.getValue());
|
||||
indirectDraws.add(new IndirectDraw(indirectModel, entry.getKey(), bufferedMesh, stage));
|
||||
}
|
||||
UniformBuffer.syncAndBind(cull);
|
||||
buffers.bindForCompute();
|
||||
glDispatchCompute(getGroupCount(instanceCountThisFrame), 1, 1);
|
||||
}
|
||||
|
||||
public void dispatchApply() {
|
||||
if (nothingToDo()) {
|
||||
return;
|
||||
}
|
||||
apply.bind();
|
||||
buffers.bindForCompute();
|
||||
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
|
||||
glDispatchCompute(getGroupCount(indirectDraws.size()), 1, 1);
|
||||
}
|
||||
|
||||
private boolean nothingToDo() {
|
||||
return indirectDraws.isEmpty() || instanceCountThisFrame == 0;
|
||||
}
|
||||
|
||||
private boolean nothingToDo(RenderStage stage) {
|
||||
return nothingToDo() || !multiDraws.containsKey(stage);
|
||||
needsSortDraws = true;
|
||||
}
|
||||
|
||||
public void submit(RenderStage stage) {
|
||||
|
@ -152,13 +169,14 @@ public class IndirectCullingGroup<I extends Instance> {
|
|||
return;
|
||||
}
|
||||
|
||||
UniformBuffer.syncAndBind(draw);
|
||||
UniformBuffer.get().sync();
|
||||
drawProgram.bind();
|
||||
meshPool.bindForDraw();
|
||||
buffers.bindForDraw();
|
||||
|
||||
drawBarrier();
|
||||
|
||||
var flwBaseDraw = draw.getUniformLocation("_flw_baseDraw");
|
||||
var flwBaseDraw = drawProgram.getUniformLocation("_flw_baseDraw");
|
||||
|
||||
for (var multiDraw : multiDraws.get(stage)) {
|
||||
glUniform1ui(flwBaseDraw, multiDraw.start);
|
||||
|
@ -173,7 +191,7 @@ public class IndirectCullingGroup<I extends Instance> {
|
|||
}
|
||||
}
|
||||
|
||||
private void uploadInstances(StagingBuffer stagingBuffer) {
|
||||
private void uploadObjects(StagingBuffer stagingBuffer) {
|
||||
long pos = 0;
|
||||
for (IndirectModel batch : indirectModels) {
|
||||
var instanceCount = batch.instancer.getInstanceCount();
|
||||
|
@ -190,7 +208,7 @@ public class IndirectCullingGroup<I extends Instance> {
|
|||
stagingBuffer.enqueueCopy(totalSize, handle, 0, this::writeModels);
|
||||
}
|
||||
|
||||
private void uploadIndirectCommands(StagingBuffer stagingBuffer) {
|
||||
private void uploadDraws(StagingBuffer stagingBuffer) {
|
||||
var totalSize = indirectDraws.size() * IndirectBuffers.DRAW_COMMAND_STRIDE;
|
||||
var handle = buffers.draw.handle();
|
||||
|
||||
|
@ -199,44 +217,23 @@ public class IndirectCullingGroup<I extends Instance> {
|
|||
|
||||
private void writeModels(long writePtr) {
|
||||
for (var batch : indirectModels) {
|
||||
batch.writeModel(writePtr);
|
||||
batch.write(writePtr);
|
||||
writePtr += IndirectBuffers.MODEL_STRIDE;
|
||||
}
|
||||
}
|
||||
|
||||
private void writeCommands(long writePtr) {
|
||||
for (var batch : indirectDraws) {
|
||||
batch.writeIndirectCommand(writePtr);
|
||||
batch.write(writePtr);
|
||||
writePtr += IndirectBuffers.DRAW_COMMAND_STRIDE;
|
||||
}
|
||||
}
|
||||
|
||||
private int calculateTotalInstanceCountAndPrepareBatches() {
|
||||
int baseInstance = 0;
|
||||
for (var batch : indirectModels) {
|
||||
batch.prepare(baseInstance);
|
||||
baseInstance += batch.instancer.getInstanceCount();
|
||||
}
|
||||
return baseInstance;
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
buffers.delete();
|
||||
meshPool.delete();
|
||||
}
|
||||
|
||||
public boolean hasStage(RenderStage stage) {
|
||||
return multiDraws.containsKey(stage);
|
||||
}
|
||||
|
||||
private static int getGroupCount(int threadCount) {
|
||||
if (GlCompat.amd) {
|
||||
return (threadCount + 63) >> 6; // ceil(threadCount / 64)
|
||||
} else {
|
||||
return (threadCount + 31) >> 5; // ceil(threadCount / 32)
|
||||
}
|
||||
}
|
||||
|
||||
private record MultiDraw(Material material, int start, int end) {
|
||||
void submit() {
|
||||
MaterialRenderState.setup(material);
|
||||
|
|
|
@ -4,17 +4,17 @@ import org.lwjgl.system.MemoryUtil;
|
|||
|
||||
import com.jozufozu.flywheel.api.event.RenderStage;
|
||||
import com.jozufozu.flywheel.api.material.Material;
|
||||
import com.jozufozu.flywheel.backend.MaterialEncoder;
|
||||
import com.jozufozu.flywheel.backend.ShaderIndices;
|
||||
import com.jozufozu.flywheel.backend.engine.MaterialEncoder;
|
||||
|
||||
public class IndirectDraw {
|
||||
private final IndirectModel model;
|
||||
private final IndirectMeshPool.BufferedMesh mesh;
|
||||
private final Material material;
|
||||
private final IndirectMeshPool.BufferedMesh mesh;
|
||||
private final RenderStage stage;
|
||||
|
||||
private final int vertexMaterialID;
|
||||
private final int fragmentMaterialID;
|
||||
private final int materialVertexIndex;
|
||||
private final int materialFragmentIndex;
|
||||
private final int packedFogAndCutout;
|
||||
private final int packedMaterialProperties;
|
||||
|
||||
|
@ -24,8 +24,8 @@ public class IndirectDraw {
|
|||
this.mesh = mesh;
|
||||
this.stage = stage;
|
||||
|
||||
this.vertexMaterialID = ShaderIndices.getVertexShaderIndex(material.shaders());
|
||||
this.fragmentMaterialID = ShaderIndices.getFragmentShaderIndex(material.shaders());
|
||||
this.materialVertexIndex = ShaderIndices.getVertexShaderIndex(material.shaders());
|
||||
this.materialFragmentIndex = ShaderIndices.getFragmentShaderIndex(material.shaders());
|
||||
this.packedFogAndCutout = MaterialEncoder.packFogAndCutout(material);
|
||||
this.packedMaterialProperties = MaterialEncoder.packProperties(material);
|
||||
}
|
||||
|
@ -42,16 +42,17 @@ public class IndirectDraw {
|
|||
return stage;
|
||||
}
|
||||
|
||||
public void writeIndirectCommand(long ptr) {
|
||||
public void write(long ptr) {
|
||||
MemoryUtil.memPutInt(ptr, mesh.indexCount()); // count
|
||||
MemoryUtil.memPutInt(ptr + 4, 0); // instanceCount
|
||||
MemoryUtil.memPutInt(ptr + 8, mesh.firstIndex); // firstIndex
|
||||
MemoryUtil.memPutInt(ptr + 12, mesh.baseVertex); // baseVertex
|
||||
MemoryUtil.memPutInt(ptr + 16, model.baseInstance); // baseInstance
|
||||
MemoryUtil.memPutInt(ptr + 4, 0); // instanceCount - to be set by the apply shader
|
||||
MemoryUtil.memPutInt(ptr + 8, mesh.firstIndex()); // firstIndex
|
||||
MemoryUtil.memPutInt(ptr + 12, mesh.baseVertex()); // baseVertex
|
||||
MemoryUtil.memPutInt(ptr + 16, model.baseInstance()); // baseInstance
|
||||
|
||||
MemoryUtil.memPutInt(ptr + 20, model.id); // modelID
|
||||
MemoryUtil.memPutInt(ptr + 24, vertexMaterialID); // vertexMaterialID
|
||||
MemoryUtil.memPutInt(ptr + 28, fragmentMaterialID); // fragmentMaterialID
|
||||
MemoryUtil.memPutInt(ptr + 20, model.index); // modelIndex
|
||||
|
||||
MemoryUtil.memPutInt(ptr + 24, materialVertexIndex); // materialVertexIndex
|
||||
MemoryUtil.memPutInt(ptr + 28, materialFragmentIndex); // materialFragmentIndex
|
||||
MemoryUtil.memPutInt(ptr + 32, packedFogAndCutout); // packedFogAndCutout
|
||||
MemoryUtil.memPutInt(ptr + 36, packedMaterialProperties); // packedMaterialProperties
|
||||
}
|
||||
|
|
|
@ -12,29 +12,35 @@ import com.jozufozu.flywheel.backend.engine.InstancerStorage;
|
|||
|
||||
public class IndirectDrawManager extends InstancerStorage<IndirectInstancer<?>> {
|
||||
private final StagingBuffer stagingBuffer = new StagingBuffer();
|
||||
public final Map<InstanceType<?>, IndirectCullingGroup<?>> cullingGroups = new HashMap<>();
|
||||
private final Map<InstanceType<?>, IndirectCullingGroup<?>> cullingGroups = new HashMap<>();
|
||||
|
||||
@Override
|
||||
protected <I extends Instance> IndirectInstancer<?> create(InstanceType<I> type) {
|
||||
return new IndirectInstancer<>(type);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected <I extends Instance> void add(InstancerKey<I> key, IndirectInstancer<?> instancer, Model model, RenderStage stage) {
|
||||
var indirectList = (IndirectCullingGroup<I>) cullingGroups.computeIfAbsent(key.type(), IndirectCullingGroup::new);
|
||||
|
||||
indirectList.add((IndirectInstancer<I>) instancer, stage, model);
|
||||
var group = (IndirectCullingGroup<I>) cullingGroups.computeIfAbsent(key.type(), IndirectCullingGroup::new);
|
||||
group.add((IndirectInstancer<I>) instancer, model, stage);
|
||||
}
|
||||
|
||||
public boolean hasStage(RenderStage stage) {
|
||||
for (var list : cullingGroups.values()) {
|
||||
if (list.hasStage(stage)) {
|
||||
for (var group : cullingGroups.values()) {
|
||||
if (group.hasStage(stage)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void renderStage(RenderStage stage) {
|
||||
for (var group : cullingGroups.values()) {
|
||||
group.submit(stage);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
super.flush();
|
||||
|
|
|
@ -6,10 +6,10 @@ import com.jozufozu.flywheel.api.event.RenderContext;
|
|||
import com.jozufozu.flywheel.api.event.RenderStage;
|
||||
import com.jozufozu.flywheel.api.task.Plan;
|
||||
import com.jozufozu.flywheel.api.task.TaskExecutor;
|
||||
import com.jozufozu.flywheel.backend.MaterialRenderState;
|
||||
import com.jozufozu.flywheel.backend.engine.AbstractEngine;
|
||||
import com.jozufozu.flywheel.backend.engine.AbstractInstancer;
|
||||
import com.jozufozu.flywheel.backend.engine.InstancerStorage;
|
||||
import com.jozufozu.flywheel.backend.engine.MaterialRenderState;
|
||||
import com.jozufozu.flywheel.gl.GlStateTracker;
|
||||
import com.jozufozu.flywheel.gl.GlTextureUnit;
|
||||
import com.jozufozu.flywheel.lib.task.Flag;
|
||||
|
@ -61,9 +61,7 @@ public class IndirectEngine extends AbstractEngine {
|
|||
GlTextureUnit.T2.makeActive();
|
||||
RenderSystem.bindTexture(RenderSystem.getShaderTexture(2));
|
||||
|
||||
for (var list : drawManager.cullingGroups.values()) {
|
||||
list.submit(stage);
|
||||
}
|
||||
drawManager.renderStage(stage);
|
||||
|
||||
MaterialRenderState.reset();
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ import com.jozufozu.flywheel.backend.engine.AbstractInstancer;
|
|||
public class IndirectInstancer<I extends Instance> extends AbstractInstancer<I> {
|
||||
private final long objectStride;
|
||||
private final InstanceWriter<I> writer;
|
||||
private int modelId;
|
||||
private int modelIndex;
|
||||
|
||||
public IndirectInstancer(InstanceType<I> type) {
|
||||
super(type);
|
||||
|
@ -24,7 +24,7 @@ public class IndirectInstancer<I extends Instance> extends AbstractInstancer<I>
|
|||
removeDeletedInstances();
|
||||
}
|
||||
|
||||
public void writeSparse(StagingBuffer stagingBuffer, long start, int dstVbo) {
|
||||
public void writeChanged(StagingBuffer stagingBuffer, long start, int dstVbo) {
|
||||
int count = instances.size();
|
||||
for (int i = changed.nextSetBit(0); i >= 0 && i < count; i = changed.nextSetBit(i + 1)) {
|
||||
var instance = instances.get(i);
|
||||
|
@ -33,7 +33,7 @@ public class IndirectInstancer<I extends Instance> extends AbstractInstancer<I>
|
|||
changed.clear();
|
||||
}
|
||||
|
||||
public void writeFull(StagingBuffer stagingBuffer, long start, int dstVbo) {
|
||||
public void writeAll(StagingBuffer stagingBuffer, long start, int dstVbo) {
|
||||
long totalSize = objectStride * instances.size();
|
||||
|
||||
stagingBuffer.enqueueCopy(totalSize, dstVbo, start, this::writeAll);
|
||||
|
@ -50,12 +50,12 @@ public class IndirectInstancer<I extends Instance> extends AbstractInstancer<I>
|
|||
|
||||
private void writeOne(long ptr, I instance) {
|
||||
// write modelID
|
||||
MemoryUtil.memPutInt(ptr, modelId);
|
||||
MemoryUtil.memPutInt(ptr, modelIndex);
|
||||
// write object
|
||||
writer.write(ptr + IndirectBuffers.INT_SIZE, instance);
|
||||
}
|
||||
|
||||
public void setModelId(int modelId) {
|
||||
this.modelId = modelId;
|
||||
public void setModelIndex(int modelIndex) {
|
||||
this.modelIndex = modelIndex;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Vector4fc;
|
||||
|
||||
import com.jozufozu.flywheel.api.model.Mesh;
|
||||
import com.jozufozu.flywheel.backend.InternalLayout;
|
||||
|
@ -20,9 +19,9 @@ public class IndirectMeshPool {
|
|||
private final Map<Mesh, BufferedMesh> meshes = new HashMap<>();
|
||||
private final List<BufferedMesh> meshList = new ArrayList<>();
|
||||
|
||||
final GlVertexArray vertexArray;
|
||||
final GlBuffer vbo;
|
||||
final GlBuffer ebo;
|
||||
private final GlVertexArray vertexArray;
|
||||
private final GlBuffer vbo;
|
||||
private final GlBuffer ebo;
|
||||
|
||||
private boolean dirty;
|
||||
|
||||
|
@ -142,9 +141,9 @@ public class IndirectMeshPool {
|
|||
|
||||
public static class BufferedMesh {
|
||||
private final Mesh mesh;
|
||||
public long byteIndex;
|
||||
public int firstIndex;
|
||||
public int baseVertex;
|
||||
private long byteIndex;
|
||||
private int baseVertex;
|
||||
private int firstIndex;
|
||||
|
||||
private BufferedMesh(Mesh mesh) {
|
||||
this.mesh = mesh;
|
||||
|
@ -158,8 +157,12 @@ public class IndirectMeshPool {
|
|||
return mesh.indexCount();
|
||||
}
|
||||
|
||||
public Vector4fc boundingSphere() {
|
||||
return mesh.boundingSphere();
|
||||
public int baseVertex() {
|
||||
return baseVertex;
|
||||
}
|
||||
|
||||
public int firstIndex() {
|
||||
return firstIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,28 +1,24 @@
|
|||
package com.jozufozu.flywheel.backend.engine.indirect;
|
||||
|
||||
import org.joml.Vector4f;
|
||||
import org.joml.Vector4fc;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
public class IndirectModel {
|
||||
public final IndirectInstancer<?> instancer;
|
||||
public final int id;
|
||||
|
||||
public int baseInstance = -1;
|
||||
private boolean needsFullWrite = true;
|
||||
|
||||
public final int index;
|
||||
private final Vector4fc boundingSphere;
|
||||
|
||||
public IndirectModel(IndirectInstancer<?> instancer, int id, Vector4f boundingSphere) {
|
||||
private int baseInstance = -1;
|
||||
private boolean needsFullWrite = true;
|
||||
|
||||
public IndirectModel(IndirectInstancer<?> instancer, int index, Vector4fc boundingSphere) {
|
||||
this.instancer = instancer;
|
||||
this.id = id;
|
||||
this.index = index;
|
||||
this.boundingSphere = boundingSphere;
|
||||
}
|
||||
|
||||
public void writeModel(long ptr) {
|
||||
MemoryUtil.memPutInt(ptr, 0); // instanceCount - to be incremented by the compute shader
|
||||
MemoryUtil.memPutInt(ptr + 4, baseInstance); // baseInstance
|
||||
boundingSphere.getToAddress(ptr + 8); // boundingSphere
|
||||
public int baseInstance() {
|
||||
return baseInstance;
|
||||
}
|
||||
|
||||
public void prepare(int baseInstance) {
|
||||
|
@ -37,9 +33,15 @@ public class IndirectModel {
|
|||
|
||||
public void writeObjects(StagingBuffer stagingBuffer, long start, int dstVbo) {
|
||||
if (needsFullWrite) {
|
||||
instancer.writeFull(stagingBuffer, start, dstVbo);
|
||||
instancer.writeAll(stagingBuffer, start, dstVbo);
|
||||
} else {
|
||||
instancer.writeSparse(stagingBuffer, start, dstVbo);
|
||||
instancer.writeChanged(stagingBuffer, start, dstVbo);
|
||||
}
|
||||
}
|
||||
|
||||
public void write(long ptr) {
|
||||
MemoryUtil.memPutInt(ptr, 0); // instanceCount - to be incremented by the cull shader
|
||||
MemoryUtil.memPutInt(ptr + 4, baseInstance); // baseInstance
|
||||
boundingSphere.getToAddress(ptr + 8); // boundingSphere
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ import com.mojang.blaze3d.platform.GlStateManager;
|
|||
import it.unimi.dsi.fastutil.objects.Object2ReferenceMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ReferenceOpenHashMap;
|
||||
|
||||
public class EBOCache {
|
||||
public class EboCache {
|
||||
private final List<Entry> quads = new ArrayList<>();
|
||||
private final Object2ReferenceMap<Key, Entry> others = new Object2ReferenceOpenHashMap<>();
|
||||
|
||||
|
@ -37,9 +37,9 @@ public class EBOCache {
|
|||
|
||||
private int getQuads(int indexCount) {
|
||||
// Use an existing quad EBO if there's one big enough.
|
||||
for (Entry quadEBO : quads) {
|
||||
if (quadEBO.gpuSize >= indexCount * GlNumericType.UINT.byteWidth()) {
|
||||
return quadEBO.ebo;
|
||||
for (Entry quadEbo : quads) {
|
||||
if (quadEbo.gpuSize >= indexCount * GlNumericType.UINT.byteWidth()) {
|
||||
return quadEbo.ebo;
|
||||
}
|
||||
}
|
||||
// If not, create a new one.
|
||||
|
@ -55,7 +55,6 @@ public class EBOCache {
|
|||
}
|
||||
|
||||
private record Entry(int ebo, int gpuSize) {
|
||||
|
||||
@NotNull
|
||||
private static Entry create(IndexSequence provider, int indexCount) {
|
||||
int byteSize = indexCount * GlNumericType.UINT.byteWidth();
|
|
@ -12,14 +12,15 @@ import com.jozufozu.flywheel.api.instance.Instance;
|
|||
import com.jozufozu.flywheel.api.material.Material;
|
||||
import com.jozufozu.flywheel.api.material.Transparency;
|
||||
import com.jozufozu.flywheel.api.material.WriteMask;
|
||||
import com.jozufozu.flywheel.backend.MaterialRenderState;
|
||||
import com.jozufozu.flywheel.backend.compile.InstancingPrograms;
|
||||
import com.jozufozu.flywheel.backend.engine.InstanceHandleImpl;
|
||||
import com.jozufozu.flywheel.backend.engine.MaterialRenderState;
|
||||
import com.jozufozu.flywheel.backend.engine.UniformBuffer;
|
||||
import com.jozufozu.flywheel.gl.GlStateTracker;
|
||||
import com.jozufozu.flywheel.gl.GlTextureUnit;
|
||||
import com.jozufozu.flywheel.lib.context.Contexts;
|
||||
import com.jozufozu.flywheel.lib.material.CutoutShaders;
|
||||
import com.jozufozu.flywheel.lib.material.FogShaders;
|
||||
import com.jozufozu.flywheel.lib.material.SimpleMaterial;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
|
||||
|
@ -37,6 +38,8 @@ public class InstancedCrumbling {
|
|||
return;
|
||||
}
|
||||
|
||||
var crumblingMaterial = SimpleMaterial.builder();
|
||||
|
||||
try (var state = GlStateTracker.getRestoreState()) {
|
||||
for (var shaderStateEntry : byShaderState.entrySet()) {
|
||||
var byProgress = shaderStateEntry.getValue();
|
||||
|
@ -50,8 +53,9 @@ public class InstancedCrumbling {
|
|||
var baseMaterial = shader.material();
|
||||
int diffuseTexture = getDiffuseTexture(baseMaterial);
|
||||
|
||||
var crumblingMaterial = SimpleMaterial.builderOf(baseMaterial)
|
||||
.cutout(CutoutShaders.OFF)
|
||||
crumblingMaterial.copyFrom(baseMaterial)
|
||||
.fog(FogShaders.NONE)
|
||||
.cutout(CutoutShaders.ONE_TENTH)
|
||||
.polygonOffset(true)
|
||||
.transparency(Transparency.CRUMBLING)
|
||||
.writeMask(WriteMask.COLOR)
|
||||
|
@ -60,8 +64,9 @@ public class InstancedCrumbling {
|
|||
|
||||
var program = InstancingPrograms.get()
|
||||
.get(shader.instanceType(), Contexts.CRUMBLING);
|
||||
UniformBuffer.syncAndBind(program);
|
||||
program.bind();
|
||||
|
||||
UniformBuffer.get().sync();
|
||||
InstancingEngine.uploadMaterialUniform(program, crumblingMaterial);
|
||||
|
||||
for (Int2ObjectMap.Entry<List<Runnable>> progressEntry : byProgress.int2ObjectEntrySet()) {
|
||||
|
@ -71,7 +76,7 @@ public class InstancedCrumbling {
|
|||
continue;
|
||||
}
|
||||
|
||||
crumblingMaterial.baseTexture(ModelBakery.BREAKING_LOCATIONS.get(progressEntry.getIntKey()));
|
||||
crumblingMaterial.texture(ModelBakery.BREAKING_LOCATIONS.get(progressEntry.getIntKey()));
|
||||
|
||||
MaterialRenderState.setup(crumblingMaterial);
|
||||
|
||||
|
@ -126,7 +131,7 @@ public class InstancedCrumbling {
|
|||
private static int getDiffuseTexture(Material material) {
|
||||
return Minecraft.getInstance()
|
||||
.getTextureManager()
|
||||
.getTexture(material.baseTexture())
|
||||
.getTexture(material.texture())
|
||||
.getId();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ public class InstancedDrawManager extends InstancerStorage<InstancedInstancer<?>
|
|||
* A map of vertex types to their mesh pools.
|
||||
*/
|
||||
private final InstancedMeshPool meshPool = new InstancedMeshPool();
|
||||
private final EBOCache eboCache = new EBOCache();
|
||||
private final EboCache eboCache = new EboCache();
|
||||
|
||||
public DrawSet get(RenderStage stage) {
|
||||
return drawSets.getOrDefault(stage, DrawSet.EMPTY);
|
||||
|
@ -66,7 +66,7 @@ public class InstancedDrawManager extends InstancerStorage<InstancedInstancer<?>
|
|||
|
||||
DrawSet drawSet = drawSets.computeIfAbsent(stage, DrawSet::new);
|
||||
|
||||
var meshes = model.getMeshes();
|
||||
var meshes = model.meshes();
|
||||
for (var entry : meshes.entrySet()) {
|
||||
var mesh = alloc(entry.getValue());
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ public class InstancedMeshPool {
|
|||
* @param eboCache The EBO cache to use.
|
||||
* @return A handle to the allocated mesh.
|
||||
*/
|
||||
public BufferedMesh alloc(Mesh mesh, EBOCache eboCache) {
|
||||
public BufferedMesh alloc(Mesh mesh, EboCache eboCache) {
|
||||
return meshes.computeIfAbsent(mesh, m -> {
|
||||
BufferedMesh bufferedMesh = new BufferedMesh(m, byteSize, eboCache);
|
||||
byteSize += bufferedMesh.size();
|
||||
|
@ -143,7 +143,7 @@ public class InstancedMeshPool {
|
|||
|
||||
private final Set<GlVertexArray> boundTo = new HashSet<>();
|
||||
|
||||
private BufferedMesh(Mesh mesh, long byteIndex, EBOCache eboCache) {
|
||||
private BufferedMesh(Mesh mesh, long byteIndex, EboCache eboCache) {
|
||||
this.mesh = mesh;
|
||||
this.byteIndex = byteIndex;
|
||||
this.ebo = eboCache.get(mesh.indexSequence(), mesh.indexCount());
|
||||
|
|
|
@ -9,13 +9,13 @@ import com.jozufozu.flywheel.api.event.RenderStage;
|
|||
import com.jozufozu.flywheel.api.material.Material;
|
||||
import com.jozufozu.flywheel.api.task.Plan;
|
||||
import com.jozufozu.flywheel.api.task.TaskExecutor;
|
||||
import com.jozufozu.flywheel.backend.MaterialEncoder;
|
||||
import com.jozufozu.flywheel.backend.MaterialRenderState;
|
||||
import com.jozufozu.flywheel.backend.ShaderIndices;
|
||||
import com.jozufozu.flywheel.backend.compile.InstancingPrograms;
|
||||
import com.jozufozu.flywheel.backend.engine.AbstractEngine;
|
||||
import com.jozufozu.flywheel.backend.engine.AbstractInstancer;
|
||||
import com.jozufozu.flywheel.backend.engine.InstancerStorage;
|
||||
import com.jozufozu.flywheel.backend.engine.MaterialEncoder;
|
||||
import com.jozufozu.flywheel.backend.engine.MaterialRenderState;
|
||||
import com.jozufozu.flywheel.backend.engine.UniformBuffer;
|
||||
import com.jozufozu.flywheel.gl.GlStateTracker;
|
||||
import com.jozufozu.flywheel.gl.GlTextureUnit;
|
||||
|
@ -111,9 +111,10 @@ public class InstancingEngine extends AbstractEngine {
|
|||
}
|
||||
|
||||
var program = InstancingPrograms.get()
|
||||
.get(shader.instanceType(), Contexts.WORLD);
|
||||
UniformBuffer.syncAndBind(program);
|
||||
.get(shader.instanceType(), Contexts.DEFAULT);
|
||||
program.bind();
|
||||
|
||||
UniformBuffer.get().sync();
|
||||
uploadMaterialUniform(program, shader.material());
|
||||
|
||||
MaterialRenderState.setup(shader.material());
|
||||
|
|
|
@ -135,18 +135,18 @@ public class FlwCommands {
|
|||
command.then(Commands.literal("debugFrustum")
|
||||
.then(Commands.literal("pause")
|
||||
.executes(context -> {
|
||||
FlwShaderUniforms.FRUSTUM_PAUSED = true;
|
||||
FlwShaderUniforms.frustumPaused = true;
|
||||
return 1;
|
||||
}))
|
||||
.then(Commands.literal("unpause")
|
||||
.executes(context -> {
|
||||
FlwShaderUniforms.FRUSTUM_PAUSED = false;
|
||||
FlwShaderUniforms.frustumPaused = false;
|
||||
return 1;
|
||||
}))
|
||||
.then(Commands.literal("capture")
|
||||
.executes(context -> {
|
||||
FlwShaderUniforms.FRUSTUM_PAUSED = true;
|
||||
FlwShaderUniforms.FRUSTUM_CAPTURE = true;
|
||||
FlwShaderUniforms.frustumPaused = true;
|
||||
FlwShaderUniforms.frustumCapture = true;
|
||||
return 1;
|
||||
})));
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@ import org.lwjgl.opengl.GLCapabilities;
|
|||
import org.lwjgl.opengl.KHRShaderSubgroup;
|
||||
import org.lwjgl.system.MemoryStack;
|
||||
|
||||
import com.jozufozu.flywheel.lib.math.MoreMath;
|
||||
|
||||
import net.minecraft.Util;
|
||||
|
||||
/**
|
||||
|
@ -18,19 +20,19 @@ import net.minecraft.Util;
|
|||
* Each field stores an enum variant that provides access to the most appropriate version of a feature for the current
|
||||
* system.
|
||||
*/
|
||||
public class GlCompat {
|
||||
public static final boolean ALLOW_DSA = true;
|
||||
public final class GlCompat {
|
||||
public static final GLCapabilities CAPABILITIES = GL.createCapabilities();
|
||||
public static final boolean amd = _decideIfWeAreAMD();
|
||||
public static final boolean windows = _decideIfWeAreWindows();
|
||||
public static final boolean supportsIndirect = _decideIfWeSupportIndirect();
|
||||
public static final boolean AMD = _decideIfWeAreAMD();
|
||||
public static final boolean WINDOWS = _decideIfWeAreWindows();
|
||||
public static final boolean ALLOW_DSA = true;
|
||||
public static final boolean SUPPORTS_INDIRECT = _decideIfWeSupportIndirect();
|
||||
public static final int SUBGROUP_SIZE = _subgroupSize();
|
||||
|
||||
private GlCompat() {
|
||||
}
|
||||
|
||||
public static boolean onAMDWindows() {
|
||||
return amd && windows;
|
||||
return AMD && WINDOWS;
|
||||
}
|
||||
|
||||
public static boolean supportsInstancing() {
|
||||
|
@ -38,7 +40,22 @@ public class GlCompat {
|
|||
}
|
||||
|
||||
public static boolean supportsIndirect() {
|
||||
return supportsIndirect;
|
||||
return SUPPORTS_INDIRECT;
|
||||
}
|
||||
|
||||
private static boolean _decideIfWeAreAMD() {
|
||||
String vendor = GL20C.glGetString(GL20C.GL_VENDOR);
|
||||
|
||||
if (vendor == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// vendor string I got was "ATI Technologies Inc."
|
||||
return vendor.contains("ATI") || vendor.contains("AMD");
|
||||
}
|
||||
|
||||
private static boolean _decideIfWeAreWindows() {
|
||||
return Util.getPlatform() == Util.OS.WINDOWS;
|
||||
}
|
||||
|
||||
private static boolean _decideIfWeSupportIndirect() {
|
||||
|
@ -50,7 +67,11 @@ public class GlCompat {
|
|||
return GL31C.glGetInteger(KHRShaderSubgroup.GL_SUBGROUP_SIZE_KHR);
|
||||
}
|
||||
// try to guess
|
||||
return amd ? 64 : 32;
|
||||
return AMD ? 64 : 32;
|
||||
}
|
||||
|
||||
public static int getComputeGroupCount(int invocations) {
|
||||
return MoreMath.ceilingDiv(invocations, SUBGROUP_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -73,20 +94,5 @@ public class GlCompat {
|
|||
GL20C.nglShaderSource(glId, 1, pointers.address0(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean _decideIfWeAreWindows() {
|
||||
return Util.getPlatform() == Util.OS.WINDOWS;
|
||||
}
|
||||
|
||||
private static boolean _decideIfWeAreAMD() {
|
||||
String vendor = GL20C.glGetString(GL20C.GL_VENDOR);
|
||||
|
||||
if (vendor == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// vendor string I got was "ATI Technologies Inc."
|
||||
return vendor.contains("ATI") || vendor.contains("AMD");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package com.jozufozu.flywheel.glsl;
|
||||
|
||||
public enum GLSLVersion {
|
||||
public enum GlslVersion {
|
||||
V110(110),
|
||||
V120(120),
|
||||
V130(130),
|
||||
|
@ -18,7 +18,7 @@ public enum GLSLVersion {
|
|||
|
||||
public final int version;
|
||||
|
||||
GLSLVersion(int version) {
|
||||
GlslVersion(int version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
|
@ -40,13 +40,6 @@ public class ShaderSources {
|
|||
cache.putAll(preloadCache);
|
||||
}
|
||||
|
||||
public ShaderSources(ResourceManager manager, List<ResourceLocation> preloadEmpty) {
|
||||
this.manager = manager;
|
||||
for (ResourceLocation rl : preloadEmpty) {
|
||||
cache.put(rl, SourceFile.empty(rl));
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public LoadResult find(ResourceLocation location) {
|
||||
if (findStack.contains(location)) {
|
||||
|
|
|
@ -39,9 +39,9 @@ public class GlslSwitch implements GlslStmt {
|
|||
@Override
|
||||
public String prettyPrint() {
|
||||
return """
|
||||
switch (%s) {
|
||||
%s
|
||||
}""".formatted(on.prettyPrint(), formatCases());
|
||||
switch (%s) {
|
||||
%s
|
||||
}""".formatted(on.prettyPrint(), formatCases());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
|
|
@ -9,7 +9,7 @@ import com.jozufozu.flywheel.gl.shader.GlProgram;
|
|||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
public final class Contexts {
|
||||
public static final SimpleContext WORLD = Context.REGISTRY.registerAndGet(new SimpleContext(Files.WORLD_VERTEX, Files.WORLD_FRAGMENT, program -> {
|
||||
public static final SimpleContext DEFAULT = Context.REGISTRY.registerAndGet(new SimpleContext(Files.DEFAULT_VERTEX, Files.DEFAULT_FRAGMENT, program -> {
|
||||
program.bind();
|
||||
program.setSamplerBinding("_flw_diffuseTex", 0);
|
||||
program.setSamplerBinding("_flw_overlayTex", 1);
|
||||
|
@ -32,14 +32,14 @@ public final class Contexts {
|
|||
}
|
||||
|
||||
public static final class Files {
|
||||
public static final ResourceLocation WORLD_VERTEX = Names.WORLD.withSuffix(".vert");
|
||||
public static final ResourceLocation WORLD_FRAGMENT = Names.WORLD.withSuffix(".frag");
|
||||
public static final ResourceLocation DEFAULT_VERTEX = Names.DEFAULT.withSuffix(".vert");
|
||||
public static final ResourceLocation DEFAULT_FRAGMENT = Names.DEFAULT.withSuffix(".frag");
|
||||
public static final ResourceLocation CRUMBLING_VERTEX = Names.CRUMBLING.withSuffix(".vert");
|
||||
public static final ResourceLocation CRUMBLING_FRAGMENT = Names.CRUMBLING.withSuffix(".frag");
|
||||
}
|
||||
|
||||
public static final class Names {
|
||||
public static final ResourceLocation WORLD = Flywheel.rl("context/world");
|
||||
public static final ResourceLocation DEFAULT = Flywheel.rl("context/default");
|
||||
public static final ResourceLocation CRUMBLING = Flywheel.rl("context/crumbling");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,12 +14,12 @@ public abstract class AbstractInstance implements Instance {
|
|||
}
|
||||
|
||||
@Override
|
||||
public InstanceType<?> type() {
|
||||
public final InstanceType<?> type() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InstanceHandle handle() {
|
||||
public final InstanceHandle handle() {
|
||||
return handle;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,10 @@ public class CutoutShaders {
|
|||
* Discard fragments with alpha close to or equal to zero.
|
||||
*/
|
||||
public static final CutoutShader EPSILON = CutoutShader.REGISTRY.registerAndGet(new SimpleCutoutShader(Flywheel.rl("cutout/epsilon.glsl")));
|
||||
/**
|
||||
* Discard fragments with alpha less than to 0.1.
|
||||
*/
|
||||
public static final CutoutShader ONE_TENTH = CutoutShader.REGISTRY.registerAndGet(new SimpleCutoutShader(Flywheel.rl("cutout/one_tenth.glsl")));
|
||||
/**
|
||||
* Discard fragments with alpha less than to 0.5.
|
||||
*/
|
||||
|
|
|
@ -39,27 +39,27 @@ public final class Materials {
|
|||
.build();
|
||||
|
||||
public static final Material CHUNK_CUTOUT_MIPPED_SHADED = SimpleMaterial.builder()
|
||||
.cutout(CutoutShaders.EPSILON)
|
||||
.cutout(CutoutShaders.HALF)
|
||||
.useOverlay(false)
|
||||
.fallbackRenderType(RenderType.cutoutMipped())
|
||||
.vertexTransformer(SHADING_TRANSFORMER)
|
||||
.build();
|
||||
public static final Material CHUNK_CUTOUT_MIPPED_UNSHADED = SimpleMaterial.builder()
|
||||
.cutout(CutoutShaders.EPSILON)
|
||||
.cutout(CutoutShaders.HALF)
|
||||
.useOverlay(false)
|
||||
.diffuse(false)
|
||||
.fallbackRenderType(RenderType.cutoutMipped())
|
||||
.build();
|
||||
|
||||
public static final Material CHUNK_CUTOUT_SHADED = SimpleMaterial.builder()
|
||||
.cutout(CutoutShaders.EPSILON)
|
||||
.cutout(CutoutShaders.ONE_TENTH)
|
||||
.mipmap(false)
|
||||
.useOverlay(false)
|
||||
.fallbackRenderType(RenderType.cutout())
|
||||
.vertexTransformer(SHADING_TRANSFORMER)
|
||||
.build();
|
||||
public static final Material CHUNK_CUTOUT_UNSHADED = SimpleMaterial.builder()
|
||||
.cutout(CutoutShaders.EPSILON)
|
||||
.cutout(CutoutShaders.ONE_TENTH)
|
||||
.mipmap(false)
|
||||
.useOverlay(false)
|
||||
.diffuse(false)
|
||||
|
@ -80,14 +80,14 @@ public final class Materials {
|
|||
.build();
|
||||
|
||||
public static final Material CHUNK_TRIPWIRE_SHADED = SimpleMaterial.builder()
|
||||
.cutout(CutoutShaders.EPSILON)
|
||||
.cutout(CutoutShaders.ONE_TENTH)
|
||||
.transparency(Transparency.TRANSLUCENT)
|
||||
.useOverlay(false)
|
||||
.fallbackRenderType(RenderType.tripwire())
|
||||
.vertexTransformer(SHADING_TRANSFORMER)
|
||||
.build();
|
||||
public static final Material CHUNK_TRIPWIRE_UNSHADED = SimpleMaterial.builder()
|
||||
.cutout(CutoutShaders.EPSILON)
|
||||
.cutout(CutoutShaders.ONE_TENTH)
|
||||
.transparency(Transparency.TRANSLUCENT)
|
||||
.useOverlay(false)
|
||||
.diffuse(false)
|
||||
|
@ -95,13 +95,14 @@ public final class Materials {
|
|||
.build();
|
||||
|
||||
public static final Material CHEST = SimpleMaterial.builder()
|
||||
.baseTexture(Sheets.CHEST_SHEET)
|
||||
.cutout(CutoutShaders.ONE_TENTH)
|
||||
.texture(Sheets.CHEST_SHEET)
|
||||
.mipmap(false)
|
||||
.fallbackRenderType(Sheets.chestSheet())
|
||||
.build();
|
||||
public static final Material SHULKER = SimpleMaterial.builder()
|
||||
.cutout(CutoutShaders.EPSILON)
|
||||
.baseTexture(Sheets.SHULKER_SHEET)
|
||||
.cutout(CutoutShaders.ONE_TENTH)
|
||||
.texture(Sheets.SHULKER_SHEET)
|
||||
.mipmap(false)
|
||||
.backfaceCulling(false)
|
||||
.fallbackRenderType(Sheets.shulkerBoxSheet())
|
||||
|
@ -111,7 +112,7 @@ public final class Materials {
|
|||
.fallbackRenderType(Sheets.solidBlockSheet())
|
||||
.build();
|
||||
public static final Material MINECART = SimpleMaterial.builder()
|
||||
.baseTexture(MINECART_LOCATION)
|
||||
.texture(MINECART_LOCATION)
|
||||
.mipmap(false)
|
||||
.fallbackRenderType(RenderType.entitySolid(MINECART_LOCATION))
|
||||
.build();
|
||||
|
|
|
@ -21,7 +21,7 @@ public class SimpleMaterial implements Material {
|
|||
protected final FogShader fog;
|
||||
protected final CutoutShader cutout;
|
||||
|
||||
protected final ResourceLocation baseTexture;
|
||||
protected final ResourceLocation texture;
|
||||
protected final boolean blur;
|
||||
protected final boolean mipmap;
|
||||
|
||||
|
@ -41,7 +41,7 @@ public class SimpleMaterial implements Material {
|
|||
shaders = builder.shaders();
|
||||
fog = builder.fog();
|
||||
cutout = builder.cutout();
|
||||
baseTexture = builder.baseTexture();
|
||||
texture = builder.texture();
|
||||
blur = builder.blur();
|
||||
mipmap = builder.mipmap();
|
||||
backfaceCulling = builder.backfaceCulling();
|
||||
|
@ -88,8 +88,8 @@ public class SimpleMaterial implements Material {
|
|||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation baseTexture() {
|
||||
return baseTexture;
|
||||
public ResourceLocation texture() {
|
||||
return texture;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -150,7 +150,7 @@ public class SimpleMaterial implements Material {
|
|||
protected FogShader fog;
|
||||
protected CutoutShader cutout;
|
||||
|
||||
protected ResourceLocation baseTexture;
|
||||
protected ResourceLocation texture;
|
||||
protected boolean blur;
|
||||
protected boolean mipmap;
|
||||
|
||||
|
@ -171,14 +171,14 @@ public class SimpleMaterial implements Material {
|
|||
shaders = StandardMaterialShaders.DEFAULT;
|
||||
fog = FogShaders.LINEAR;
|
||||
cutout = CutoutShaders.OFF;
|
||||
baseTexture = InventoryMenu.BLOCK_ATLAS;
|
||||
texture = InventoryMenu.BLOCK_ATLAS;
|
||||
blur = false;
|
||||
mipmap = true;
|
||||
backfaceCulling = true;
|
||||
polygonOffset = false;
|
||||
depthTest = DepthTest.LEQUAL;
|
||||
transparency = Transparency.OPAQUE;
|
||||
writeMask = WriteMask.BOTH;
|
||||
writeMask = WriteMask.COLOR_DEPTH;
|
||||
useOverlay = true;
|
||||
useLight = true;
|
||||
diffuse = true;
|
||||
|
@ -194,7 +194,7 @@ public class SimpleMaterial implements Material {
|
|||
shaders = material.shaders();
|
||||
fog = material.fog();
|
||||
cutout = material.cutout();
|
||||
baseTexture = material.baseTexture();
|
||||
texture = material.texture();
|
||||
blur = material.blur();
|
||||
mipmap = material.mipmap();
|
||||
backfaceCulling = material.backfaceCulling();
|
||||
|
@ -233,8 +233,8 @@ public class SimpleMaterial implements Material {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder baseTexture(ResourceLocation value) {
|
||||
this.baseTexture = value;
|
||||
public Builder texture(ResourceLocation value) {
|
||||
this.texture = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -314,8 +314,8 @@ public class SimpleMaterial implements Material {
|
|||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation baseTexture() {
|
||||
return baseTexture;
|
||||
public ResourceLocation texture() {
|
||||
return texture;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -2,7 +2,6 @@ package com.jozufozu.flywheel.lib.model;
|
|||
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Vector4f;
|
||||
|
@ -101,29 +100,33 @@ public final class ModelUtil {
|
|||
return null;
|
||||
}
|
||||
|
||||
public static Vector4f computeBoundingSphere(Collection<Mesh> values) {
|
||||
int totalVertices = 0;
|
||||
for (Mesh value : values) {
|
||||
totalVertices += value.vertexCount();
|
||||
public static int computeTotalVertexCount(Iterable<Mesh> meshes) {
|
||||
int vertexCount = 0;
|
||||
for (Mesh mesh : meshes) {
|
||||
vertexCount += mesh.vertexCount();
|
||||
}
|
||||
var block = MemoryBlock.malloc((long) totalVertices * PositionOnlyVertexList.STRIDE);
|
||||
return vertexCount;
|
||||
}
|
||||
|
||||
public static Vector4f computeBoundingSphere(Iterable<Mesh> meshes) {
|
||||
int vertexCount = computeTotalVertexCount(meshes);
|
||||
var block = MemoryBlock.malloc((long) vertexCount * PositionOnlyVertexList.STRIDE);
|
||||
var vertexList = new PositionOnlyVertexList();
|
||||
|
||||
int baseVertex = 0;
|
||||
for (Mesh value : values) {
|
||||
for (Mesh mesh : meshes) {
|
||||
vertexList.ptr(block.ptr() + (long) baseVertex * PositionOnlyVertexList.STRIDE);
|
||||
value.write(vertexList);
|
||||
baseVertex += value.vertexCount();
|
||||
mesh.write(vertexList);
|
||||
baseVertex += mesh.vertexCount();
|
||||
}
|
||||
|
||||
vertexList.ptr(block.ptr());
|
||||
vertexList.vertexCount(totalVertices);
|
||||
|
||||
var out = computeBoundingSphere(vertexList);
|
||||
vertexList.vertexCount(vertexCount);
|
||||
var sphere = computeBoundingSphere(vertexList);
|
||||
|
||||
block.free();
|
||||
return out;
|
||||
|
||||
return sphere;
|
||||
}
|
||||
|
||||
public static Vector4f computeBoundingSphere(VertexList vertexList) {
|
||||
|
|
|
@ -2,27 +2,42 @@ package com.jozufozu.flywheel.lib.model;
|
|||
|
||||
import java.util.Map;
|
||||
|
||||
import org.joml.Vector4fc;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.jozufozu.flywheel.api.material.Material;
|
||||
import com.jozufozu.flywheel.api.model.Mesh;
|
||||
import com.jozufozu.flywheel.api.model.Model;
|
||||
|
||||
public class SimpleModel implements Model {
|
||||
private final Mesh mesh;
|
||||
private final Map<Material, Mesh> meshMap;
|
||||
private final ImmutableMap<Material, Mesh> meshes;
|
||||
private final Vector4fc boundingSphere;
|
||||
private final int vertexCount;
|
||||
|
||||
public SimpleModel(Mesh mesh, Material material) {
|
||||
this.mesh = mesh;
|
||||
meshMap = ImmutableMap.of(material, mesh);
|
||||
public SimpleModel(ImmutableMap<Material, Mesh> meshes) {
|
||||
this.meshes = meshes;
|
||||
this.boundingSphere = ModelUtil.computeBoundingSphere(meshes.values());
|
||||
this.vertexCount = ModelUtil.computeTotalVertexCount(meshes.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Material, Mesh> getMeshes() {
|
||||
return meshMap;
|
||||
public Map<Material, Mesh> meshes() {
|
||||
return meshes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector4fc boundingSphere() {
|
||||
return boundingSphere;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int vertexCount() {
|
||||
return vertexCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() {
|
||||
mesh.delete();
|
||||
meshes.values()
|
||||
.forEach(Mesh::delete);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
package com.jozufozu.flywheel.lib.model;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.joml.Vector4fc;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.jozufozu.flywheel.api.material.Material;
|
||||
import com.jozufozu.flywheel.api.model.Mesh;
|
||||
import com.jozufozu.flywheel.api.model.Model;
|
||||
|
||||
public class SingleMeshModel implements Model {
|
||||
private final Mesh mesh;
|
||||
private final Map<Material, Mesh> meshMap;
|
||||
|
||||
public SingleMeshModel(Mesh mesh, Material material) {
|
||||
this.mesh = mesh;
|
||||
meshMap = ImmutableMap.of(material, mesh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Material, Mesh> meshes() {
|
||||
return meshMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector4fc boundingSphere() {
|
||||
return mesh.boundingSphere();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int vertexCount() {
|
||||
return mesh.vertexCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() {
|
||||
mesh.delete();
|
||||
}
|
||||
}
|
|
@ -1,32 +1,18 @@
|
|||
package com.jozufozu.flywheel.lib.model.baked;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.jozufozu.flywheel.api.material.Material;
|
||||
import com.jozufozu.flywheel.api.model.Mesh;
|
||||
import com.jozufozu.flywheel.api.model.Model;
|
||||
import com.jozufozu.flywheel.lib.model.SimpleModel;
|
||||
|
||||
public class TessellatedModel implements Model {
|
||||
private final ImmutableMap<Material, Mesh> meshes;
|
||||
public class TessellatedModel extends SimpleModel {
|
||||
private final boolean shadeSeparated;
|
||||
|
||||
public TessellatedModel(ImmutableMap<Material, Mesh> meshes, boolean shadeSeparated) {
|
||||
this.meshes = meshes;
|
||||
super(meshes);
|
||||
this.shadeSeparated = shadeSeparated;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Material, Mesh> getMeshes() {
|
||||
return meshes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() {
|
||||
meshes.values()
|
||||
.forEach(Mesh::delete);
|
||||
}
|
||||
|
||||
public boolean isShadeSeparated() {
|
||||
return shadeSeparated;
|
||||
}
|
||||
|
|
|
@ -24,9 +24,9 @@ public class FlwShaderUniforms implements ShaderUniforms {
|
|||
public static final ResourceLocation FILE = Flywheel.rl("uniform/flywheel.glsl");
|
||||
public static final int SIZE = 224;
|
||||
|
||||
public static boolean FRUSTUM_PAUSED = false;
|
||||
public static boolean FRUSTUM_CAPTURE = false;
|
||||
public static boolean FOG_UPDATE = true;
|
||||
public static boolean frustumPaused = false;
|
||||
public static boolean frustumCapture = false;
|
||||
public static boolean fogUpdate = true;
|
||||
|
||||
@Override
|
||||
public int byteSize() {
|
||||
|
@ -94,9 +94,9 @@ public class FlwShaderUniforms implements ShaderUniforms {
|
|||
MemoryUtil.memPutFloat(ptr + 108, 0f); // vec4 alignment
|
||||
MemoryUtil.memPutInt(ptr + 112, getConstantAmbientLightFlag(context));
|
||||
|
||||
if (!FRUSTUM_PAUSED || FRUSTUM_CAPTURE) {
|
||||
if (!frustumPaused || frustumCapture) {
|
||||
MatrixMath.writePackedFrustumPlanes(ptr + 128, viewProjection);
|
||||
FRUSTUM_CAPTURE = false;
|
||||
frustumCapture = false;
|
||||
}
|
||||
|
||||
dirty = true;
|
||||
|
@ -110,7 +110,7 @@ public class FlwShaderUniforms implements ShaderUniforms {
|
|||
}
|
||||
|
||||
private boolean maybeUpdateFog() {
|
||||
if (!FOG_UPDATE || ptr == MemoryUtil.NULL) {
|
||||
if (!fogUpdate || ptr == MemoryUtil.NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -125,7 +125,7 @@ public class FlwShaderUniforms implements ShaderUniforms {
|
|||
MemoryUtil.memPutInt(ptr + 24, RenderSystem.getShaderFogShape()
|
||||
.getIndex());
|
||||
|
||||
FOG_UPDATE = false;
|
||||
fogUpdate = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ import net.minecraft.client.renderer.FogRenderer;
|
|||
abstract class FogUpdateMixin {
|
||||
@Unique
|
||||
private static void flywheel$updateFog() {
|
||||
FlwShaderUniforms.FOG_UPDATE = true;
|
||||
FlwShaderUniforms.fogUpdate = true;
|
||||
}
|
||||
|
||||
@Inject(method = "setupNoFog()V", at = @At("RETURN"))
|
||||
|
|
|
@ -15,7 +15,7 @@ import com.jozufozu.flywheel.lib.instance.InstanceTypes;
|
|||
import com.jozufozu.flywheel.lib.instance.OrientedInstance;
|
||||
import com.jozufozu.flywheel.lib.material.Materials;
|
||||
import com.jozufozu.flywheel.lib.model.ModelHolder;
|
||||
import com.jozufozu.flywheel.lib.model.SimpleModel;
|
||||
import com.jozufozu.flywheel.lib.model.SingleMeshModel;
|
||||
import com.jozufozu.flywheel.lib.model.part.ModelPartConverter;
|
||||
import com.jozufozu.flywheel.lib.visual.AbstractBlockEntityVisual;
|
||||
|
||||
|
@ -26,7 +26,7 @@ import net.minecraft.world.level.block.entity.BellBlockEntity;
|
|||
|
||||
public class BellVisual extends AbstractBlockEntityVisual<BellBlockEntity> implements DynamicVisual {
|
||||
private static final ModelHolder BELL_MODEL = new ModelHolder(() -> {
|
||||
return new SimpleModel(ModelPartConverter.convert(ModelLayers.BELL, BellRenderer.BELL_RESOURCE_LOCATION.sprite(), "bell_body"), Materials.BELL);
|
||||
return new SingleMeshModel(ModelPartConverter.convert(ModelLayers.BELL, BellRenderer.BELL_RESOURCE_LOCATION.sprite(), "bell_body"), Materials.BELL);
|
||||
});
|
||||
|
||||
private OrientedInstance bell;
|
||||
|
|
|
@ -17,7 +17,7 @@ import com.jozufozu.flywheel.lib.instance.OrientedInstance;
|
|||
import com.jozufozu.flywheel.lib.instance.TransformedInstance;
|
||||
import com.jozufozu.flywheel.lib.material.Materials;
|
||||
import com.jozufozu.flywheel.lib.model.ModelCache;
|
||||
import com.jozufozu.flywheel.lib.model.SimpleModel;
|
||||
import com.jozufozu.flywheel.lib.model.SingleMeshModel;
|
||||
import com.jozufozu.flywheel.lib.model.part.ModelPartConverter;
|
||||
import com.jozufozu.flywheel.lib.util.Pair;
|
||||
import com.jozufozu.flywheel.lib.visual.AbstractBlockEntityVisual;
|
||||
|
@ -45,13 +45,13 @@ public class ChestVisual<T extends BlockEntity & LidBlockEntity> extends Abstrac
|
|||
}
|
||||
|
||||
private static final ModelCache<Pair<ChestType, Material>> BOTTOM_MODELS = new ModelCache<>(key -> {
|
||||
return new SimpleModel(ModelPartConverter.convert(LAYER_LOCATIONS.get(key.first()), key.second().sprite(), "bottom"), Materials.CHEST);
|
||||
return new SingleMeshModel(ModelPartConverter.convert(LAYER_LOCATIONS.get(key.first()), key.second().sprite(), "bottom"), Materials.CHEST);
|
||||
});
|
||||
private static final ModelCache<Pair<ChestType, Material>> LID_MODELS = new ModelCache<>(key -> {
|
||||
return new SimpleModel(ModelPartConverter.convert(LAYER_LOCATIONS.get(key.first()), key.second().sprite(), "lid"), Materials.CHEST);
|
||||
return new SingleMeshModel(ModelPartConverter.convert(LAYER_LOCATIONS.get(key.first()), key.second().sprite(), "lid"), Materials.CHEST);
|
||||
});
|
||||
private static final ModelCache<Pair<ChestType, Material>> LOCK_MODELS = new ModelCache<>(key -> {
|
||||
return new SimpleModel(ModelPartConverter.convert(LAYER_LOCATIONS.get(key.first()), key.second().sprite(), "lock"), Materials.CHEST);
|
||||
return new SingleMeshModel(ModelPartConverter.convert(LAYER_LOCATIONS.get(key.first()), key.second().sprite(), "lock"), Materials.CHEST);
|
||||
});
|
||||
|
||||
private OrientedInstance bottom;
|
||||
|
|
|
@ -11,7 +11,7 @@ import com.jozufozu.flywheel.lib.instance.TransformedInstance;
|
|||
import com.jozufozu.flywheel.lib.material.Materials;
|
||||
import com.jozufozu.flywheel.lib.model.ModelHolder;
|
||||
import com.jozufozu.flywheel.lib.model.Models;
|
||||
import com.jozufozu.flywheel.lib.model.SimpleModel;
|
||||
import com.jozufozu.flywheel.lib.model.SingleMeshModel;
|
||||
import com.jozufozu.flywheel.lib.model.part.ModelPartConverter;
|
||||
import com.jozufozu.flywheel.lib.visual.AbstractEntityVisual;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
|
@ -26,7 +26,7 @@ import net.minecraft.world.phys.Vec3;
|
|||
|
||||
public class MinecartVisual<T extends AbstractMinecart> extends AbstractEntityVisual<T> implements TickableVisual, DynamicVisual {
|
||||
private static final ModelHolder BODY_MODEL = new ModelHolder(() -> {
|
||||
return new SimpleModel(ModelPartConverter.convert(ModelLayers.MINECART), Materials.MINECART);
|
||||
return new SingleMeshModel(ModelPartConverter.convert(ModelLayers.MINECART), Materials.MINECART);
|
||||
});
|
||||
|
||||
private TransformedInstance body;
|
||||
|
|
|
@ -13,7 +13,7 @@ import com.jozufozu.flywheel.lib.instance.InstanceTypes;
|
|||
import com.jozufozu.flywheel.lib.instance.TransformedInstance;
|
||||
import com.jozufozu.flywheel.lib.material.Materials;
|
||||
import com.jozufozu.flywheel.lib.model.ModelCache;
|
||||
import com.jozufozu.flywheel.lib.model.SimpleModel;
|
||||
import com.jozufozu.flywheel.lib.model.SingleMeshModel;
|
||||
import com.jozufozu.flywheel.lib.model.part.ModelPartConverter;
|
||||
import com.jozufozu.flywheel.lib.transform.TransformStack;
|
||||
import com.jozufozu.flywheel.lib.visual.AbstractBlockEntityVisual;
|
||||
|
@ -30,10 +30,10 @@ import net.minecraft.world.level.block.entity.ShulkerBoxBlockEntity;
|
|||
|
||||
public class ShulkerBoxVisual extends AbstractBlockEntityVisual<ShulkerBoxBlockEntity> implements DynamicVisual {
|
||||
private static final ModelCache<Material> BASE_MODELS = new ModelCache<>(texture -> {
|
||||
return new SimpleModel(ModelPartConverter.convert(ModelLayers.SHULKER, texture.sprite(), "base"), Materials.SHULKER);
|
||||
return new SingleMeshModel(ModelPartConverter.convert(ModelLayers.SHULKER, texture.sprite(), "base"), Materials.SHULKER);
|
||||
});
|
||||
private static final ModelCache<Material> LID_MODELS = new ModelCache<>(texture -> {
|
||||
return new SimpleModel(ModelPartConverter.convert(ModelLayers.SHULKER, texture.sprite(), "lid"), Materials.SHULKER);
|
||||
return new SingleMeshModel(ModelPartConverter.convert(ModelLayers.SHULKER, texture.sprite(), "lid"), Materials.SHULKER);
|
||||
});
|
||||
|
||||
private TransformedInstance base;
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
#include "flywheel:api/fragment.glsl"
|
||||
|
||||
uniform sampler2D _flw_crumblingTex;
|
||||
|
||||
in vec2 crumblingTexCoord;
|
||||
|
@ -7,16 +5,12 @@ in vec2 crumblingTexCoord;
|
|||
vec4 crumblingSampleColor;
|
||||
|
||||
void flw_beginFragment() {
|
||||
crumblingSampleColor = texture(_flw_crumblingTex, crumblingTexCoord);
|
||||
|
||||
// Make the crumbling overlay transparent when the diffuse layer is transparent.
|
||||
crumblingSampleColor.a *= flw_fragColor.a;
|
||||
|
||||
if (crumblingSampleColor.a < 0.01) {
|
||||
discard;
|
||||
}
|
||||
}
|
||||
|
||||
void flw_endFragment() {
|
||||
flw_fragColor = crumblingSampleColor;
|
||||
crumblingSampleColor = texture(_flw_crumblingTex, crumblingTexCoord);
|
||||
|
||||
// Make the crumbling overlay transparent when the fragment color after the material shader is transparent.
|
||||
flw_fragColor.rgb = crumblingSampleColor.rgb;
|
||||
flw_fragColor.a *= crumblingSampleColor.a;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
#include "flywheel:api/vertex.glsl"
|
||||
#include "flywheel:util/fog.glsl"
|
||||
|
||||
out vec2 crumblingTexCoord;
|
||||
|
||||
const int DOWN = 0;
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
#include "flywheel:api/fragment.glsl"
|
||||
|
||||
void flw_beginFragment() {
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
void flw_beginVertex() {
|
||||
}
|
||||
|
||||
void flw_endVertex() {
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
#include "flywheel:api/vertex.glsl"
|
||||
#include "flywheel:util/fog.glsl"
|
||||
|
||||
void flw_beginVertex() {
|
||||
}
|
||||
|
||||
void flw_endVertex() {
|
||||
}
|
|
@ -1,3 +1,3 @@
|
|||
bool flw_discardPredicate(vec4 finalColor) {
|
||||
return finalColor.a < 0.01;
|
||||
bool flw_discardPredicate(vec4 color) {
|
||||
return color.a < 0.01;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
bool flw_discardPredicate(vec4 finalColor) {
|
||||
return finalColor.a < 0.5;
|
||||
bool flw_discardPredicate(vec4 color) {
|
||||
return color.a < 0.5;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
bool flw_discardPredicate(vec4 finalColor) {
|
||||
bool flw_discardPredicate(vec4 color) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
bool flw_discardPredicate(vec4 color) {
|
||||
return color.a < 0.1;
|
||||
}
|
|
@ -1,5 +1,12 @@
|
|||
#include "flywheel:util/fog.glsl"
|
||||
vec4 linearFog(vec4 color, float distance, float fogStart, float fogEnd, vec4 fogColor) {
|
||||
if (distance <= fogStart) {
|
||||
return color;
|
||||
}
|
||||
|
||||
float fogValue = distance < fogEnd ? smoothstep(fogStart, fogEnd, distance) : 1.0;
|
||||
return vec4(mix(color.rgb, fogColor.rgb, fogValue * fogColor.a), color.a);
|
||||
}
|
||||
|
||||
vec4 flw_fogFilter(vec4 color) {
|
||||
return linear_fog(color, flw_distance, flywheel.fogRange.x, flywheel.fogRange.y, flywheel.fogColor);
|
||||
return linearFog(color, flw_distance, flywheel.fogRange.x, flywheel.fogRange.y, flywheel.fogColor);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,13 @@
|
|||
#include "flywheel:util/fog.glsl"
|
||||
vec4 linearFogFade(vec4 color, float distance, float fogStart, float fogEnd) {
|
||||
if (distance <= fogStart) {
|
||||
return color;
|
||||
} else if (distance >= fogEnd) {
|
||||
return vec4(0.0);
|
||||
}
|
||||
|
||||
return color * smoothstep(fogEnd, fogStart, distance);
|
||||
}
|
||||
|
||||
vec4 flw_fogFilter(vec4 color) {
|
||||
return linear_fog_fade(color, flw_distance, flywheel.fogRange.x, flywheel.fogRange.y);
|
||||
return linearFogFade(color, flw_distance, flywheel.fogRange.x, flywheel.fogRange.y);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#include "flywheel:api/vertex.glsl"
|
||||
#include "flywheel:util/quaternion.glsl"
|
||||
|
||||
void flw_transformBoundingSphere(in FlwInstance i, inout vec3 center, inout float radius) {
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
#include "flywheel:api/vertex.glsl"
|
||||
|
||||
void flw_transformBoundingSphere(in FlwInstance i, inout vec3 center, inout float radius) {
|
||||
mat4 pose = i.pose;
|
||||
center = (pose * vec4(center, 1.0)).xyz;
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
#include "flywheel:internal/material.glsl"
|
||||
|
||||
in vec4 flw_vertexPos;
|
||||
in vec4 flw_vertexColor;
|
||||
in vec2 flw_vertexTexCoord;
|
||||
flat in ivec2 flw_vertexOverlay;
|
||||
in vec2 flw_vertexLight;
|
||||
in vec3 flw_vertexNormal;
|
||||
|
||||
in float flw_distance;
|
||||
|
||||
vec4 flw_sampleColor;
|
||||
|
||||
FlwMaterial flw_material;
|
||||
|
||||
vec4 flw_fragColor;
|
||||
ivec2 flw_fragOverlay;
|
||||
vec2 flw_fragLight;
|
|
@ -0,0 +1,12 @@
|
|||
#include "flywheel:internal/material.glsl"
|
||||
|
||||
out vec4 flw_vertexPos;
|
||||
out vec4 flw_vertexColor;
|
||||
out vec2 flw_vertexTexCoord;
|
||||
flat out ivec2 flw_vertexOverlay;
|
||||
out vec2 flw_vertexLight;
|
||||
out vec3 flw_vertexNormal;
|
||||
|
||||
out float flw_distance;
|
||||
|
||||
FlwMaterial flw_material;
|
|
@ -0,0 +1,21 @@
|
|||
float sphericalDistance(vec3 relativePos) {
|
||||
return length(relativePos);
|
||||
}
|
||||
|
||||
float cylindricalDistance(vec3 relativePos) {
|
||||
float distXZ = length(relativePos.xz);
|
||||
float distY = abs(relativePos.y);
|
||||
return max(distXZ, distY);
|
||||
}
|
||||
|
||||
float fogDistance(vec3 relativePos, int fogShape) {
|
||||
if (fogShape == 0) {
|
||||
return sphericalDistance(relativePos);
|
||||
} else {
|
||||
return cylindricalDistance(relativePos);
|
||||
}
|
||||
}
|
||||
|
||||
float fogDistance(vec3 worldPos, vec3 cameraPos, int fogShape) {
|
||||
return fogDistance(worldPos - cameraPos, fogShape);
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
// API
|
||||
// ------------------------------------------
|
||||
|
||||
#include "flywheel:api/material.glsl"
|
||||
|
||||
in vec4 flw_vertexPos;
|
||||
in vec4 flw_vertexColor;
|
||||
in vec2 flw_vertexTexCoord;
|
||||
flat in ivec2 flw_vertexOverlay;
|
||||
in vec2 flw_vertexLight;
|
||||
in vec3 flw_vertexNormal;
|
||||
|
||||
in float flw_distance;
|
||||
|
||||
in vec4 flw_var0;
|
||||
in vec4 flw_var1;
|
||||
in vec4 flw_var2;
|
||||
in vec4 flw_var3;
|
||||
|
||||
FlwMaterial flw_material;
|
||||
|
||||
vec4 flw_sampleColor;
|
||||
|
||||
vec4 flw_fragColor;
|
||||
ivec2 flw_fragOverlay;
|
||||
vec2 flw_fragLight;
|
||||
|
||||
vec4 flw_fogFilter(vec4 color);
|
||||
|
||||
bool flw_discardPredicate(vec4 finalColor);
|
||||
|
||||
void flw_beginFragment();
|
||||
void flw_materialFragment();
|
||||
void flw_endFragment();
|
||||
|
||||
// ------------------------------------------
|
||||
// INTERNAL
|
||||
// ------------------------------------------
|
||||
|
||||
uint _flw_materialFragmentID;
|
||||
uint _flw_fogID;
|
||||
uint _flw_cutoutID;
|
||||
|
||||
// ------------------------------------------
|
|
@ -1,36 +0,0 @@
|
|||
// API
|
||||
// ------------------------------------------
|
||||
|
||||
#include "flywheel:api/material.glsl"
|
||||
|
||||
out vec4 flw_vertexPos;
|
||||
out vec4 flw_vertexColor;
|
||||
out vec2 flw_vertexTexCoord;
|
||||
flat out ivec2 flw_vertexOverlay;
|
||||
out vec2 flw_vertexLight;
|
||||
out vec3 flw_vertexNormal;
|
||||
|
||||
out float flw_distance;
|
||||
|
||||
out vec4 flw_var0;
|
||||
out vec4 flw_var1;
|
||||
out vec4 flw_var2;
|
||||
out vec4 flw_var3;
|
||||
|
||||
FlwMaterial flw_material;
|
||||
|
||||
void flw_layoutVertex();
|
||||
void flw_beginVertex();
|
||||
void flw_instanceVertex(FlwInstance i);
|
||||
void flw_materialVertex();
|
||||
void flw_endVertex();
|
||||
|
||||
// ------------------------------------------
|
||||
// INTERNAL
|
||||
// ------------------------------------------
|
||||
|
||||
uint _flw_materialVertexID;
|
||||
|
||||
FlwInstance _flw_unpackInstance(FlwPackedInstance i);
|
||||
|
||||
// ------------------------------------------
|
|
@ -0,0 +1,5 @@
|
|||
#include "flywheel:internal/common_api_impl.frag"
|
||||
|
||||
uint _flw_uberMaterialFragmentIndex;
|
||||
uint _flw_uberFogIndex;
|
||||
uint _flw_uberCutoutIndex;
|
|
@ -0,0 +1,3 @@
|
|||
#include "flywheel:internal/common_api_impl.vert"
|
||||
|
||||
uint _flw_uberMaterialVertexIndex;
|
|
@ -2,27 +2,25 @@
|
|||
#include "flywheel:internal/indirect/model_descriptor.glsl"
|
||||
#include "flywheel:internal/indirect/draw_command.glsl"
|
||||
|
||||
layout(local_size_x = FLW_SUBGROUP_SIZE) in;
|
||||
layout(local_size_x = _FLW_SUBGROUP_SIZE) in;
|
||||
|
||||
layout(std430, binding = MODEL_BINDING) restrict readonly buffer ModelDescriptors {
|
||||
layout(std430, binding = _FLW_MODEL_BUFFER_BINDING) restrict readonly buffer ModelBuffer {
|
||||
ModelDescriptor models[];
|
||||
};
|
||||
|
||||
layout(std430, binding = DRAW_BINDING) restrict buffer MeshDrawCommands {
|
||||
layout(std430, binding = _FLW_DRAW_BUFFER_BINDING) restrict buffer DrawBuffer {
|
||||
MeshDrawCommand drawCommands[];
|
||||
};
|
||||
|
||||
// Apply the results of culling to the draw commands.
|
||||
void main() {
|
||||
uint drawID = gl_GlobalInvocationID.x;
|
||||
uint drawIndex = gl_GlobalInvocationID.x;
|
||||
|
||||
if (drawID >= drawCommands.length()) {
|
||||
if (drawIndex >= drawCommands.length()) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint modelID = drawCommands[drawID].modelID;
|
||||
|
||||
uint instanceCount = models[modelID].instanceCount;
|
||||
|
||||
drawCommands[drawID].instanceCount = instanceCount;
|
||||
uint modelIndex = drawCommands[drawIndex].modelIndex;
|
||||
uint instanceCount = models[modelIndex].instanceCount;
|
||||
drawCommands[drawIndex].instanceCount = instanceCount;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#define OBJECT_BINDING 0
|
||||
#define TARGET_BINDING 1
|
||||
#define MODEL_BINDING 2
|
||||
#define DRAW_BINDING 3
|
||||
#define _FLW_OBJECT_BUFFER_BINDING 0
|
||||
#define _FLW_TARGET_BUFFER_BINDING 1
|
||||
#define _FLW_MODEL_BUFFER_BINDING 2
|
||||
#define _FLW_DRAW_BUFFER_BINDING 3
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#include "flywheel:internal/indirect/model_descriptor.glsl"
|
||||
#include "flywheel:internal/indirect/object.glsl"
|
||||
|
||||
layout(local_size_x = FLW_SUBGROUP_SIZE) in;
|
||||
layout(local_size_x = _FLW_SUBGROUP_SIZE) in;
|
||||
|
||||
// need to add stubs so the instance shader compiles.
|
||||
vec4 flw_vertexPos;
|
||||
|
@ -19,15 +19,15 @@ vec4 flw_var3;
|
|||
|
||||
void flw_transformBoundingSphere(in FlwInstance i, inout vec3 center, inout float radius);
|
||||
|
||||
layout(std430, binding = OBJECT_BINDING) restrict readonly buffer ObjectBuffer {
|
||||
layout(std430, binding = _FLW_OBJECT_BUFFER_BINDING) restrict readonly buffer ObjectBuffer {
|
||||
Object objects[];
|
||||
};
|
||||
|
||||
layout(std430, binding = TARGET_BINDING) restrict writeonly buffer TargetBuffer {
|
||||
uint objectIDs[];
|
||||
layout(std430, binding = _FLW_TARGET_BUFFER_BINDING) restrict writeonly buffer TargetBuffer {
|
||||
uint objectIndices[];
|
||||
};
|
||||
|
||||
layout(std430, binding = MODEL_BINDING) restrict buffer ModelDescriptors {
|
||||
layout(std430, binding = _FLW_MODEL_BUFFER_BINDING) restrict buffer ModelBuffer {
|
||||
ModelDescriptor models[];
|
||||
};
|
||||
|
||||
|
@ -44,14 +44,14 @@ bool testSphere(vec3 center, float radius) {
|
|||
return all(xyInside) && all(zInside);
|
||||
}
|
||||
|
||||
bool isVisible(uint objectID, uint modelID) {
|
||||
BoundingSphere sphere = models[modelID].boundingSphere;
|
||||
bool isVisible(uint objectIndex, uint modelIndex) {
|
||||
BoundingSphere sphere = models[modelIndex].boundingSphere;
|
||||
|
||||
vec3 center;
|
||||
float radius;
|
||||
unpackBoundingSphere(sphere, center, radius);
|
||||
_flw_unpackBoundingSphere(sphere, center, radius);
|
||||
|
||||
FlwInstance instance = _flw_unpackInstance(objects[objectID].instance);
|
||||
FlwInstance instance = _flw_unpackInstance(objects[objectIndex].instance);
|
||||
|
||||
flw_transformBoundingSphere(instance, center, radius);
|
||||
|
||||
|
@ -59,18 +59,17 @@ bool isVisible(uint objectID, uint modelID) {
|
|||
}
|
||||
|
||||
void main() {
|
||||
uint objectID = gl_GlobalInvocationID.x;
|
||||
uint objectIndex = gl_GlobalInvocationID.x;
|
||||
|
||||
if (objectID >= objects.length()) {
|
||||
if (objectIndex >= objects.length()) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint modelID = objects[objectID].modelID;
|
||||
uint modelIndex = objects[objectIndex].modelIndex;
|
||||
|
||||
if (isVisible(objectID, modelID)) {
|
||||
uint batchIndex = atomicAdd(models[modelID].instanceCount, 1);
|
||||
uint globalIndex = models[modelID].baseInstance + batchIndex;
|
||||
|
||||
objectIDs[globalIndex] = objectID;
|
||||
if (isVisible(objectIndex, modelIndex)) {
|
||||
uint localIndex = atomicAdd(models[modelIndex].instanceCount, 1);
|
||||
uint targetIndex = models[modelIndex].baseInstance + localIndex;
|
||||
objectIndices[targetIndex] = objectIndex;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
#include "flywheel:internal/indirect/api/vertex.glsl"
|
||||
#include "flywheel:internal/indirect/buffers.glsl"
|
||||
#include "flywheel:internal/indirect/draw_command.glsl"
|
||||
#include "flywheel:internal/indirect/object.glsl"
|
||||
#include "flywheel:internal/material.glsl"
|
||||
#include "flywheel:internal/vertex_input.glsl"
|
||||
#include "flywheel:util/diffuse.glsl"
|
||||
|
||||
flat out uvec3 _flw_material;
|
||||
|
||||
layout(std430, binding = OBJECT_BINDING) restrict readonly buffer ObjectBuffer {
|
||||
Object objects[];
|
||||
};
|
||||
|
||||
layout(std430, binding = TARGET_BINDING) restrict readonly buffer TargetBuffer {
|
||||
uint objectIDs[];
|
||||
};
|
||||
|
||||
layout(std430, binding = DRAW_BINDING) restrict readonly buffer DrawCommands {
|
||||
MeshDrawCommand drawCommands[];
|
||||
};
|
||||
|
||||
uniform uint _flw_baseDraw;
|
||||
|
||||
void main() {
|
||||
uint instanceIndex = objectIDs[gl_BaseInstance + gl_InstanceID];
|
||||
uint batchID = gl_DrawID + _flw_baseDraw;
|
||||
FlwInstance i = _flw_unpackInstance(objects[instanceIndex].instance);
|
||||
|
||||
_flw_materialVertexID = drawCommands[batchID].vertexMaterialID;
|
||||
uint p = drawCommands[batchID].packedMaterialProperties;
|
||||
|
||||
_flw_unpackMaterialProperties(p, flw_material);
|
||||
_flw_material = uvec3(drawCommands[batchID].fragmentMaterialID, drawCommands[batchID].packedFogAndCutout, p);
|
||||
|
||||
_flw_layoutVertex();
|
||||
flw_beginVertex();
|
||||
flw_instanceVertex(i);
|
||||
flw_materialVertex();
|
||||
flw_endVertex();
|
||||
|
||||
flw_vertexNormal = normalize(flw_vertexNormal);
|
||||
|
||||
if (flw_material.diffuse) {
|
||||
float diffuseFactor;
|
||||
if (flywheel.constantAmbientLight == 1) {
|
||||
diffuseFactor = diffuseNether(flw_vertexNormal);
|
||||
} else {
|
||||
diffuseFactor = diffuse(flw_vertexNormal);
|
||||
}
|
||||
flw_vertexColor = vec4(flw_vertexColor.rgb * diffuseFactor, flw_vertexColor.a);
|
||||
}
|
||||
|
||||
flw_distance = fog_distance(flw_vertexPos.xyz, flywheel.cameraPos.xyz, flywheel.fogShape);
|
||||
gl_Position = flywheel.viewProjection * flw_vertexPos;
|
||||
}
|
|
@ -5,9 +5,10 @@ struct MeshDrawCommand {
|
|||
uint vertexOffset;
|
||||
uint baseInstance;
|
||||
|
||||
uint modelID;
|
||||
uint vertexMaterialID;
|
||||
uint fragmentMaterialID;
|
||||
uint modelIndex;
|
||||
|
||||
uint materialVertexIndex;
|
||||
uint materialFragmentIndex;
|
||||
uint packedFogAndCutout;
|
||||
uint packedMaterialProperties;
|
||||
};
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#include "flywheel:internal/indirect/api/fragment.glsl"
|
||||
#include "flywheel:internal/material.glsl"
|
||||
#include "flywheel:internal/packed_material.glsl"
|
||||
|
||||
// optimize discard usage
|
||||
#ifdef GL_ARB_conservative_depth
|
||||
|
@ -10,15 +9,14 @@ uniform sampler2D _flw_diffuseTex;
|
|||
uniform sampler2D _flw_overlayTex;
|
||||
uniform sampler2D _flw_lightTex;
|
||||
|
||||
flat in uvec3 _flw_material;
|
||||
flat in uvec3 _flw_packedMaterial;
|
||||
|
||||
out vec4 _flw_fragColor;
|
||||
out vec4 _flw_outputColor;
|
||||
|
||||
void main() {
|
||||
_flw_materialFragmentID = _flw_material.x;
|
||||
|
||||
_flw_unpackUint2x16(_flw_material.y, _flw_cutoutID, _flw_fogID);
|
||||
_flw_unpackMaterialProperties(_flw_material.z, flw_material);
|
||||
_flw_uberMaterialFragmentIndex = _flw_packedMaterial.x;
|
||||
_flw_unpackUint2x16(_flw_packedMaterial.y, _flw_uberCutoutIndex, _flw_uberFogIndex);
|
||||
_flw_unpackMaterialProperties(_flw_packedMaterial.z, flw_material);
|
||||
|
||||
flw_sampleColor = texture(_flw_diffuseTex, flw_vertexTexCoord);
|
||||
flw_fragColor = flw_vertexColor * flw_sampleColor;
|
||||
|
@ -45,5 +43,5 @@ void main() {
|
|||
discard;
|
||||
}
|
||||
|
||||
_flw_fragColor = flw_fogFilter(color);
|
||||
_flw_outputColor = flw_fogFilter(color);
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
#include "flywheel:internal/diffuse.glsl"
|
||||
#include "flywheel:internal/fog_distance.glsl"
|
||||
#include "flywheel:internal/vertex_input.glsl"
|
||||
#include "flywheel:internal/packed_material.glsl"
|
||||
#include "flywheel:internal/indirect/buffers.glsl"
|
||||
#include "flywheel:internal/indirect/draw_command.glsl"
|
||||
#include "flywheel:internal/indirect/object.glsl"
|
||||
|
||||
layout(std430, binding = _FLW_OBJECT_BUFFER_BINDING) restrict readonly buffer ObjectBuffer {
|
||||
Object objects[];
|
||||
};
|
||||
|
||||
layout(std430, binding = _FLW_TARGET_BUFFER_BINDING) restrict readonly buffer TargetBuffer {
|
||||
uint objectIndices[];
|
||||
};
|
||||
|
||||
layout(std430, binding = _FLW_DRAW_BUFFER_BINDING) restrict readonly buffer DrawBuffer {
|
||||
MeshDrawCommand drawCommands[];
|
||||
};
|
||||
|
||||
uniform uint _flw_baseDraw;
|
||||
|
||||
flat out uvec3 _flw_packedMaterial;
|
||||
|
||||
void main() {
|
||||
uint drawIndex = gl_DrawID + _flw_baseDraw;
|
||||
MeshDrawCommand draw = drawCommands[drawIndex];
|
||||
|
||||
_flw_uberMaterialVertexIndex = draw.materialVertexIndex;
|
||||
uint packedMaterialProperties = draw.packedMaterialProperties;
|
||||
_flw_unpackMaterialProperties(packedMaterialProperties, flw_material);
|
||||
_flw_packedMaterial = uvec3(draw.materialFragmentIndex, draw.packedFogAndCutout, packedMaterialProperties);
|
||||
|
||||
uint objectIndex = objectIndices[gl_BaseInstance + gl_InstanceID];
|
||||
FlwInstance instance = _flw_unpackInstance(objects[objectIndex].instance);
|
||||
|
||||
_flw_layoutVertex();
|
||||
flw_beginVertex();
|
||||
flw_instanceVertex(instance);
|
||||
flw_materialVertex();
|
||||
flw_endVertex();
|
||||
|
||||
flw_vertexNormal = normalize(flw_vertexNormal);
|
||||
|
||||
if (flw_material.diffuse) {
|
||||
float diffuseFactor;
|
||||
if (flywheel.constantAmbientLight == 1) {
|
||||
diffuseFactor = diffuseNether(flw_vertexNormal);
|
||||
} else {
|
||||
diffuseFactor = diffuse(flw_vertexNormal);
|
||||
}
|
||||
flw_vertexColor = vec4(flw_vertexColor.rgb * diffuseFactor, flw_vertexColor.a);
|
||||
}
|
||||
|
||||
flw_distance = fogDistance(flw_vertexPos.xyz, flywheel.cameraPos.xyz, flywheel.fogShape);
|
||||
gl_Position = flywheel.viewProjection * flw_vertexPos;
|
||||
}
|
|
@ -5,13 +5,13 @@ struct BoundingSphere {
|
|||
float radius;
|
||||
};
|
||||
|
||||
void unpackBoundingSphere(in BoundingSphere sphere, out vec3 center, out float radius) {
|
||||
center = vec3(sphere.x, sphere.y, sphere.z);
|
||||
radius = sphere.radius;
|
||||
}
|
||||
|
||||
struct ModelDescriptor {
|
||||
uint instanceCount;
|
||||
uint baseInstance;
|
||||
BoundingSphere boundingSphere;
|
||||
};
|
||||
|
||||
void _flw_unpackBoundingSphere(in BoundingSphere sphere, out vec3 center, out float radius) {
|
||||
center = vec3(sphere.x, sphere.y, sphere.z);
|
||||
radius = sphere.radius;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
struct Object {
|
||||
uint modelID;
|
||||
uint modelIndex;
|
||||
FlwPackedInstance instance;
|
||||
};
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
// API
|
||||
// -----------------------------------------
|
||||
#include "flywheel:api/material.glsl"
|
||||
|
||||
in vec4 flw_vertexPos;
|
||||
in vec4 flw_vertexColor;
|
||||
in vec2 flw_vertexTexCoord;
|
||||
flat in ivec2 flw_vertexOverlay;
|
||||
in vec2 flw_vertexLight;
|
||||
in vec3 flw_vertexNormal;
|
||||
|
||||
in float flw_distance;
|
||||
|
||||
in vec4 flw_var0;
|
||||
in vec4 flw_var1;
|
||||
in vec4 flw_var2;
|
||||
in vec4 flw_var3;
|
||||
|
||||
vec4 flw_sampleColor;
|
||||
|
||||
vec4 flw_fragColor;
|
||||
ivec2 flw_fragOverlay;
|
||||
vec2 flw_fragLight;
|
||||
|
||||
FlwMaterial flw_material;
|
||||
|
||||
vec4 flw_fogFilter(vec4 color);
|
||||
|
||||
bool flw_discardPredicate(vec4 finalColor);
|
||||
|
||||
void flw_beginFragment();
|
||||
void flw_materialFragment();
|
||||
void flw_endFragment();
|
||||
|
||||
// -----------------------------------------
|
||||
// INTERNAL
|
||||
// -----------------------------------------
|
||||
|
||||
uint _flw_materialFragmentID;
|
||||
uint _flw_fogID;
|
||||
uint _flw_cutoutID;
|
||||
|
||||
// -----------------------------------------
|
|
@ -1,35 +0,0 @@
|
|||
// API
|
||||
// ------------------------------------
|
||||
#include "flywheel:api/material.glsl"
|
||||
|
||||
out vec4 flw_vertexPos;
|
||||
out vec4 flw_vertexColor;
|
||||
out vec2 flw_vertexTexCoord;
|
||||
flat out ivec2 flw_vertexOverlay;
|
||||
out vec2 flw_vertexLight;
|
||||
out vec3 flw_vertexNormal;
|
||||
|
||||
out float flw_distance;
|
||||
|
||||
out vec4 flw_var0;
|
||||
out vec4 flw_var1;
|
||||
out vec4 flw_var2;
|
||||
out vec4 flw_var3;
|
||||
|
||||
FlwMaterial flw_material;
|
||||
|
||||
void flw_layoutVertex();
|
||||
void flw_beginVertex();
|
||||
void flw_instanceVertex(FlwInstance i);
|
||||
void flw_materialVertex();
|
||||
void flw_endVertex();
|
||||
|
||||
// ------------------------------------
|
||||
// INTERNAL
|
||||
// ------------------------------------
|
||||
|
||||
uint _flw_materialVertexID;
|
||||
|
||||
FlwInstance _flw_unpackInstance();
|
||||
|
||||
// ------------------------------------
|
|
@ -0,0 +1,5 @@
|
|||
#include "flywheel:internal/common_api_impl.frag"
|
||||
|
||||
uint _flw_uberMaterialFragmentIndex;
|
||||
uint _flw_uberFogIndex;
|
||||
uint _flw_uberCutoutIndex;
|
|
@ -0,0 +1,3 @@
|
|||
#include "flywheel:internal/common_api_impl.vert"
|
||||
|
||||
uint _flw_uberMaterialVertexIndex;
|
|
@ -1,5 +1,4 @@
|
|||
#include "flywheel:internal/instancing/api/fragment.glsl"
|
||||
#include "flywheel:internal/material.glsl"
|
||||
#include "flywheel:internal/packed_material.glsl"
|
||||
|
||||
// optimize discard usage
|
||||
#ifdef GL_ARB_conservative_depth
|
||||
|
@ -12,12 +11,11 @@ uniform sampler2D _flw_lightTex;
|
|||
|
||||
uniform uvec4 _flw_packedMaterial;
|
||||
|
||||
out vec4 _flw_fragColor;
|
||||
out vec4 _flw_outputColor;
|
||||
|
||||
void main() {
|
||||
_flw_materialFragmentID = _flw_packedMaterial.y;
|
||||
|
||||
_flw_unpackUint2x16(_flw_packedMaterial.z, _flw_cutoutID, _flw_fogID);
|
||||
_flw_uberMaterialFragmentIndex = _flw_packedMaterial.y;
|
||||
_flw_unpackUint2x16(_flw_packedMaterial.z, _flw_uberCutoutIndex, _flw_uberFogIndex);
|
||||
_flw_unpackMaterialProperties(_flw_packedMaterial.w, flw_material);
|
||||
|
||||
flw_sampleColor = texture(_flw_diffuseTex, flw_vertexTexCoord);
|
||||
|
@ -45,5 +43,5 @@ void main() {
|
|||
discard;
|
||||
}
|
||||
|
||||
_flw_fragColor = flw_fogFilter(color);
|
||||
_flw_outputColor = flw_fogFilter(color);
|
||||
}
|
|
@ -1,20 +1,19 @@
|
|||
#include "flywheel:internal/instancing/api/vertex.glsl"
|
||||
#include "flywheel:internal/material.glsl"
|
||||
#include "flywheel:internal/diffuse.glsl"
|
||||
#include "flywheel:internal/fog_distance.glsl"
|
||||
#include "flywheel:internal/vertex_input.glsl"
|
||||
#include "flywheel:util/diffuse.glsl"
|
||||
#include "flywheel:internal/packed_material.glsl"
|
||||
|
||||
uniform uvec4 _flw_packedMaterial;
|
||||
|
||||
void main() {
|
||||
_flw_materialVertexID = _flw_packedMaterial.x;
|
||||
|
||||
_flw_uberMaterialVertexIndex = _flw_packedMaterial.x;
|
||||
_flw_unpackMaterialProperties(_flw_packedMaterial.w, flw_material);
|
||||
|
||||
FlwInstance i = _flw_unpackInstance();
|
||||
FlwInstance instance = _flw_unpackInstance();
|
||||
|
||||
_flw_layoutVertex();
|
||||
flw_beginVertex();
|
||||
flw_instanceVertex(i);
|
||||
flw_instanceVertex(instance);
|
||||
flw_materialVertex();
|
||||
flw_endVertex();
|
||||
|
||||
|
@ -30,6 +29,6 @@ void main() {
|
|||
flw_vertexColor = vec4(flw_vertexColor.rgb * diffuseFactor, flw_vertexColor.a);
|
||||
}
|
||||
|
||||
flw_distance = fog_distance(flw_vertexPos.xyz, flywheel.cameraPos.xyz, flywheel.fogShape);
|
||||
flw_distance = fogDistance(flw_vertexPos.xyz, flywheel.cameraPos.xyz, flywheel.fogShape);
|
||||
gl_Position = flywheel.viewProjection * flw_vertexPos;
|
||||
}
|
|
@ -1,57 +1,33 @@
|
|||
#include "flywheel:api/material.glsl"
|
||||
const uint FLW_MAT_DEPTH_TEST_OFF = 0u;
|
||||
const uint FLW_MAT_DEPTH_TEST_NEVER = 1u;
|
||||
const uint FLW_MAT_DEPTH_TEST_LESS = 2u;
|
||||
const uint FLW_MAT_DEPTH_TEST_EQUAL = 3u;
|
||||
const uint FLW_MAT_DEPTH_TEST_LEQUAL = 4u;
|
||||
const uint FLW_MAT_DEPTH_TEST_GREATER = 5u;
|
||||
const uint FLW_MAT_DEPTH_TEST_NOTEQUAL = 6u;
|
||||
const uint FLW_MAT_DEPTH_TEST_GEQUAL = 7u;
|
||||
const uint FLW_MAT_DEPTH_TEST_ALWAYS = 8u;
|
||||
|
||||
// The number of bits each property takes up
|
||||
const uint _FLW_BLUR_LENGTH = 1u;
|
||||
const uint _FLW_MIPMAP_LENGTH = 1u;
|
||||
const uint _FLW_BACKFACE_CULLING_LENGTH = 1u;
|
||||
const uint _FLW_POLYGON_OFFSET_LENGTH = 1u;
|
||||
const uint _FLW_DEPTH_TEST_LENGTH = 4u;
|
||||
const uint _FLW_TRANSPARENCY_LENGTH = 3u;
|
||||
const uint _FLW_WRITE_MASK_LENGTH = 2u;
|
||||
const uint _FLW_USE_OVERLAY_LENGTH = 1u;
|
||||
const uint _FLW_USE_LIGHT_LENGTH = 1u;
|
||||
const uint _FLW_DIFFUSE_LENGTH = 1u;
|
||||
const uint FLW_MAT_TRANSPARENCY_OPAQUE = 0u;
|
||||
const uint FLW_MAT_TRANSPARENCY_ADDITIVE = 1u;
|
||||
const uint FLW_MAT_TRANSPARENCY_LIGHTNING = 2u;
|
||||
const uint FLW_MAT_TRANSPARENCY_GLINT = 3u;
|
||||
const uint FLW_MAT_TRANSPARENCY_CRUMBLING = 4u;
|
||||
const uint FLW_MAT_TRANSPARENCY_TRANSLUCENT = 5u;
|
||||
|
||||
// The bit offset of each property
|
||||
const uint _FLW_BLUR_OFFSET = 0u;
|
||||
const uint _FLW_MIPMAP_OFFSET = _FLW_BLUR_OFFSET + _FLW_BLUR_LENGTH;
|
||||
const uint _FLW_BACKFACE_CULLING_OFFSET = _FLW_MIPMAP_OFFSET + _FLW_MIPMAP_LENGTH;
|
||||
const uint _FLW_POLYGON_OFFSET_OFFSET = _FLW_BACKFACE_CULLING_OFFSET + _FLW_BACKFACE_CULLING_LENGTH;
|
||||
const uint _FLW_DEPTH_TEST_OFFSET = _FLW_POLYGON_OFFSET_OFFSET + _FLW_POLYGON_OFFSET_LENGTH;
|
||||
const uint _FLW_TRANSPARENCY_OFFSET = _FLW_DEPTH_TEST_OFFSET + _FLW_DEPTH_TEST_LENGTH;
|
||||
const uint _FLW_WRITE_MASK_OFFSET = _FLW_TRANSPARENCY_OFFSET + _FLW_TRANSPARENCY_LENGTH;
|
||||
const uint _FLW_USE_OVERLAY_OFFSET = _FLW_WRITE_MASK_OFFSET + _FLW_WRITE_MASK_LENGTH;
|
||||
const uint _FLW_USE_LIGHT_OFFSET = _FLW_USE_OVERLAY_OFFSET + _FLW_USE_OVERLAY_LENGTH;
|
||||
const uint _FLW_DIFFUSE_OFFSET = _FLW_USE_LIGHT_OFFSET + _FLW_USE_LIGHT_LENGTH;
|
||||
const uint FLW_MAT_WRITE_MASK_COLOR_DEPTH = 0u;
|
||||
const uint FLW_MAT_WRITE_MASK_COLOR = 1u;
|
||||
const uint FLW_MAT_WRITE_MASK_DEPTH = 2u;
|
||||
|
||||
// The bit mask for each property
|
||||
const uint _FLW_BLUR_MASK = ((1u << _FLW_BLUR_LENGTH) - 1u) << _FLW_BLUR_OFFSET;
|
||||
const uint _FLW_MIPMAP_MASK = ((1u << _FLW_MIPMAP_LENGTH) - 1u) << _FLW_MIPMAP_OFFSET;
|
||||
const uint _FLW_BACKFACE_CULLING_MASK = ((1u << _FLW_BACKFACE_CULLING_LENGTH) - 1u) << _FLW_BACKFACE_CULLING_OFFSET;
|
||||
const uint _FLW_POLYGON_OFFSET_MASK = ((1u << _FLW_POLYGON_OFFSET_LENGTH) - 1u) << _FLW_POLYGON_OFFSET_OFFSET;
|
||||
const uint _FLW_DEPTH_TEST_MASK = ((1u << _FLW_DEPTH_TEST_LENGTH) - 1u) << _FLW_DEPTH_TEST_OFFSET;
|
||||
const uint _FLW_TRANSPARENCY_MASK = ((1u << _FLW_TRANSPARENCY_LENGTH) - 1u) << _FLW_TRANSPARENCY_OFFSET;
|
||||
const uint _FLW_WRITE_MASK_MASK = ((1u << _FLW_WRITE_MASK_LENGTH) - 1u) << _FLW_WRITE_MASK_OFFSET;
|
||||
const uint _FLW_USE_OVERLAY_MASK = ((1u << _FLW_USE_OVERLAY_LENGTH) - 1u) << _FLW_USE_OVERLAY_OFFSET;
|
||||
const uint _FLW_USE_LIGHT_MASK = ((1u << _FLW_USE_LIGHT_LENGTH) - 1u) << _FLW_USE_LIGHT_OFFSET;
|
||||
const uint _FLW_DIFFUSE_MASK = ((1u << _FLW_DIFFUSE_LENGTH) - 1u) << _FLW_DIFFUSE_OFFSET;
|
||||
|
||||
// Packed format:
|
||||
// diffuse[1] | useOverlay[1] | useLight[1] | writeMask[2] | transparency[3] | depthTest[4] | polygonOffset[1] | backfaceCulling[1] | mipmap[1] | blur[1]
|
||||
void _flw_unpackMaterialProperties(uint p, out FlwMaterial m) {
|
||||
m.blur = (p & _FLW_BLUR_MASK) != 0u;
|
||||
m.mipmap = (p & _FLW_MIPMAP_MASK) != 0u;
|
||||
m.backfaceCulling = (p & _FLW_BACKFACE_CULLING_MASK) != 0u;
|
||||
m.polygonOffset = (p & _FLW_POLYGON_OFFSET_MASK) != 0u;
|
||||
m.depthTest = (p & _FLW_DEPTH_TEST_MASK) >> _FLW_DEPTH_TEST_OFFSET;
|
||||
m.transparency = (p & _FLW_TRANSPARENCY_MASK) >> _FLW_TRANSPARENCY_OFFSET;
|
||||
m.writeMask = (p & _FLW_WRITE_MASK_MASK) >> _FLW_WRITE_MASK_OFFSET;
|
||||
m.useOverlay = (p & _FLW_USE_OVERLAY_MASK) != 0u;
|
||||
m.useLight = (p & _FLW_USE_LIGHT_MASK) != 0u;
|
||||
m.diffuse = (p & _FLW_DIFFUSE_MASK) != 0u;
|
||||
}
|
||||
|
||||
void _flw_unpackUint2x16(uint s, out uint hi, out uint lo) {
|
||||
hi = (s >> 16) & 0xFFFFu;
|
||||
lo = s & 0xFFFFu;
|
||||
}
|
||||
struct FlwMaterial {
|
||||
bool blur;
|
||||
bool mipmap;
|
||||
bool backfaceCulling;
|
||||
bool polygonOffset;
|
||||
uint depthTest;
|
||||
uint transparency;
|
||||
uint writeMask;
|
||||
bool useOverlay;
|
||||
bool useLight;
|
||||
bool diffuse;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
// The number of bits each property takes up
|
||||
const uint _FLW_BLUR_LENGTH = 1u;
|
||||
const uint _FLW_MIPMAP_LENGTH = 1u;
|
||||
const uint _FLW_BACKFACE_CULLING_LENGTH = 1u;
|
||||
const uint _FLW_POLYGON_OFFSET_LENGTH = 1u;
|
||||
const uint _FLW_DEPTH_TEST_LENGTH = 4u;
|
||||
const uint _FLW_TRANSPARENCY_LENGTH = 3u;
|
||||
const uint _FLW_WRITE_MASK_LENGTH = 2u;
|
||||
const uint _FLW_USE_OVERLAY_LENGTH = 1u;
|
||||
const uint _FLW_USE_LIGHT_LENGTH = 1u;
|
||||
const uint _FLW_DIFFUSE_LENGTH = 1u;
|
||||
|
||||
// The bit offset of each property
|
||||
const uint _FLW_BLUR_OFFSET = 0u;
|
||||
const uint _FLW_MIPMAP_OFFSET = _FLW_BLUR_OFFSET + _FLW_BLUR_LENGTH;
|
||||
const uint _FLW_BACKFACE_CULLING_OFFSET = _FLW_MIPMAP_OFFSET + _FLW_MIPMAP_LENGTH;
|
||||
const uint _FLW_POLYGON_OFFSET_OFFSET = _FLW_BACKFACE_CULLING_OFFSET + _FLW_BACKFACE_CULLING_LENGTH;
|
||||
const uint _FLW_DEPTH_TEST_OFFSET = _FLW_POLYGON_OFFSET_OFFSET + _FLW_POLYGON_OFFSET_LENGTH;
|
||||
const uint _FLW_TRANSPARENCY_OFFSET = _FLW_DEPTH_TEST_OFFSET + _FLW_DEPTH_TEST_LENGTH;
|
||||
const uint _FLW_WRITE_MASK_OFFSET = _FLW_TRANSPARENCY_OFFSET + _FLW_TRANSPARENCY_LENGTH;
|
||||
const uint _FLW_USE_OVERLAY_OFFSET = _FLW_WRITE_MASK_OFFSET + _FLW_WRITE_MASK_LENGTH;
|
||||
const uint _FLW_USE_LIGHT_OFFSET = _FLW_USE_OVERLAY_OFFSET + _FLW_USE_OVERLAY_LENGTH;
|
||||
const uint _FLW_DIFFUSE_OFFSET = _FLW_USE_LIGHT_OFFSET + _FLW_USE_LIGHT_LENGTH;
|
||||
|
||||
// The bit mask for each property
|
||||
const uint _FLW_BLUR_MASK = ((1u << _FLW_BLUR_LENGTH) - 1u) << _FLW_BLUR_OFFSET;
|
||||
const uint _FLW_MIPMAP_MASK = ((1u << _FLW_MIPMAP_LENGTH) - 1u) << _FLW_MIPMAP_OFFSET;
|
||||
const uint _FLW_BACKFACE_CULLING_MASK = ((1u << _FLW_BACKFACE_CULLING_LENGTH) - 1u) << _FLW_BACKFACE_CULLING_OFFSET;
|
||||
const uint _FLW_POLYGON_OFFSET_MASK = ((1u << _FLW_POLYGON_OFFSET_LENGTH) - 1u) << _FLW_POLYGON_OFFSET_OFFSET;
|
||||
const uint _FLW_DEPTH_TEST_MASK = ((1u << _FLW_DEPTH_TEST_LENGTH) - 1u) << _FLW_DEPTH_TEST_OFFSET;
|
||||
const uint _FLW_TRANSPARENCY_MASK = ((1u << _FLW_TRANSPARENCY_LENGTH) - 1u) << _FLW_TRANSPARENCY_OFFSET;
|
||||
const uint _FLW_WRITE_MASK_MASK = ((1u << _FLW_WRITE_MASK_LENGTH) - 1u) << _FLW_WRITE_MASK_OFFSET;
|
||||
const uint _FLW_USE_OVERLAY_MASK = ((1u << _FLW_USE_OVERLAY_LENGTH) - 1u) << _FLW_USE_OVERLAY_OFFSET;
|
||||
const uint _FLW_USE_LIGHT_MASK = ((1u << _FLW_USE_LIGHT_LENGTH) - 1u) << _FLW_USE_LIGHT_OFFSET;
|
||||
const uint _FLW_DIFFUSE_MASK = ((1u << _FLW_DIFFUSE_LENGTH) - 1u) << _FLW_DIFFUSE_OFFSET;
|
||||
|
||||
// Packed format:
|
||||
// diffuse[1] | useOverlay[1] | useLight[1] | writeMask[2] | transparency[3] | depthTest[4] | polygonOffset[1] | backfaceCulling[1] | mipmap[1] | blur[1]
|
||||
void _flw_unpackMaterialProperties(uint p, out FlwMaterial m) {
|
||||
m.blur = (p & _FLW_BLUR_MASK) != 0u;
|
||||
m.mipmap = (p & _FLW_MIPMAP_MASK) != 0u;
|
||||
m.backfaceCulling = (p & _FLW_BACKFACE_CULLING_MASK) != 0u;
|
||||
m.polygonOffset = (p & _FLW_POLYGON_OFFSET_MASK) != 0u;
|
||||
m.depthTest = (p & _FLW_DEPTH_TEST_MASK) >> _FLW_DEPTH_TEST_OFFSET;
|
||||
m.transparency = (p & _FLW_TRANSPARENCY_MASK) >> _FLW_TRANSPARENCY_OFFSET;
|
||||
m.writeMask = (p & _FLW_WRITE_MASK_MASK) >> _FLW_WRITE_MASK_OFFSET;
|
||||
m.useOverlay = (p & _FLW_USE_OVERLAY_MASK) != 0u;
|
||||
m.useLight = (p & _FLW_USE_LIGHT_MASK) != 0u;
|
||||
m.diffuse = (p & _FLW_DIFFUSE_MASK) != 0u;
|
||||
}
|
||||
|
||||
void _flw_unpackUint2x16(uint s, out uint hi, out uint lo) {
|
||||
hi = (s >> 16) & 0xFFFFu;
|
||||
lo = s & 0xFFFFu;
|
||||
}
|
|
@ -1,5 +1,3 @@
|
|||
#include "flywheel:api/vertex.glsl"
|
||||
|
||||
layout(location = 0) in vec3 _flw_pos;
|
||||
layout(location = 1) in vec4 _flw_color;
|
||||
layout(location = 2) in vec2 _flw_texCoord;
|
||||
|
|
|
@ -1,4 +1,2 @@
|
|||
#include "flywheel:api/fragment.glsl"
|
||||
|
||||
void flw_materialFragment() {
|
||||
}
|
||||
|
|
|
@ -1,4 +1,2 @@
|
|||
#include "flywheel:api/vertex.glsl"
|
||||
|
||||
void flw_materialVertex() {
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
struct FLWPackedPlanes {
|
||||
struct FrustumPlanes {
|
||||
vec4 xyX; // <nx.x, px.x, ny.x, py.x>
|
||||
vec4 xyY; // <nx.y, px.y, ny.y, py.y>
|
||||
vec4 xyZ; // <nx.z, px.z, ny.z, py.z>
|
||||
|
@ -9,12 +9,12 @@ struct FLWPackedPlanes {
|
|||
vec2 zW; // <nz.w, pz.w>
|
||||
};
|
||||
|
||||
struct flywheel_uniforms {
|
||||
struct FlywheelUniforms {
|
||||
vec4 fogColor;
|
||||
vec2 fogRange;
|
||||
int fogShape;
|
||||
mat4 viewProjection;
|
||||
vec4 cameraPos;
|
||||
int constantAmbientLight;
|
||||
FLWPackedPlanes planes;
|
||||
FrustumPlanes planes;
|
||||
};
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
float spherical_distance(vec3 relativePos) {
|
||||
return length(relativePos);
|
||||
}
|
||||
|
||||
float cylindrical_distance(vec3 relativePos) {
|
||||
float distXZ = length(relativePos.xz);
|
||||
float distY = abs(relativePos.y);
|
||||
return max(distXZ, distY);
|
||||
}
|
||||
|
||||
float fog_distance(vec3 relativePos, int fogShape) {
|
||||
if (fogShape == 0) {
|
||||
return spherical_distance(relativePos);
|
||||
} else {
|
||||
return cylindrical_distance(relativePos);
|
||||
}
|
||||
}
|
||||
|
||||
float fog_distance(vec3 worldPos, vec3 cameraPos, int fogShape) {
|
||||
return fog_distance(worldPos - cameraPos, fogShape);
|
||||
}
|
||||
|
||||
vec4 linear_fog(vec4 color, float distance, float fogStart, float fogEnd, vec4 fogColor) {
|
||||
if (distance <= fogStart) {
|
||||
return color;
|
||||
}
|
||||
|
||||
float fogValue = distance < fogEnd ? smoothstep(fogStart, fogEnd, distance) : 1.0;
|
||||
return vec4(mix(color.rgb, fogColor.rgb, fogValue * fogColor.a), color.a);
|
||||
}
|
||||
|
||||
vec4 linear_fog_fade(vec4 color, float distance, float fogStart, float fogEnd) {
|
||||
if (distance <= fogStart) {
|
||||
return color;
|
||||
} else if (distance >= fogEnd) {
|
||||
return vec4(0.0);
|
||||
}
|
||||
|
||||
return color * smoothstep(fogEnd, fogStart, distance);
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
#define PIOVER2 1.5707963268
|
||||
#define PI_OVER_2 1.5707963268
|
||||
|
||||
vec4 quat(vec3 axis, float angle) {
|
||||
float halfAngle = angle * PIOVER2 / 180.0;
|
||||
vec2 cs = sin(vec2(PIOVER2 - halfAngle, halfAngle)); // compute sin and cos in one instruction
|
||||
float halfAngle = angle * PI_OVER_2 / 180.0;
|
||||
vec2 cs = sin(vec2(PI_OVER_2 - halfAngle, halfAngle)); // compute sin and cos in one instruction
|
||||
return vec4(axis.xyz * cs.y, cs.x);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue