Uniforms!!!

- Basic idea is to let each mode get one uniform shader
- Uniform shader provides a struct with the mod's id as its name
- All structs get placed into one (1) ubo
- Uniforms are implicitly available in all shaders
- Add GlslUniformBlock for new codegen in UniformComponent
- Condense old uniform providers into one object
- ShaderStructs capture the optional variable name in struct definitions
- Change RecursiveIncluder to interleave root components with included
- GlProgram calls UniformBuffer#sync
This commit is contained in:
Jozufozu 2023-03-25 13:41:45 -07:00
parent 9a746f700d
commit d197fe0a4f
30 changed files with 403 additions and 394 deletions

View file

@ -1,13 +1,12 @@
package com.jozufozu.flywheel.backend.gl.shader;
import static org.lwjgl.opengl.GL20.glDeleteProgram;
import static org.lwjgl.opengl.GL20.glGetUniformLocation;
import static org.lwjgl.opengl.GL20.glUniform1i;
import static org.lwjgl.opengl.GL20.*;
import org.jetbrains.annotations.NotNull;
import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.gl.GlObject;
import com.jozufozu.flywheel.core.uniform.UniformBuffer;
import com.mojang.blaze3d.shaders.ProgramManager;
public class GlProgram extends GlObject {
@ -18,6 +17,9 @@ public class GlProgram extends GlObject {
// TODO: Programs bind the uniform buffers they need, no more GlProgram inheritance
public void bind() {
// TODO: bind textures?
UniformBuffer.getInstance()
.sync();
ProgramManager.glUseProgram(handle());
}

View file

@ -1,19 +1,14 @@
package com.jozufozu.flywheel.backend.instancing.compile;
import static org.lwjgl.opengl.GL20.glAttachShader;
import static org.lwjgl.opengl.GL20.glCreateProgram;
import static org.lwjgl.opengl.GL20.glLinkProgram;
import static org.lwjgl.opengl.GL20.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Multimap;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.context.ContextShader;
import com.jozufozu.flywheel.api.pipeline.Pipeline;
@ -41,6 +36,7 @@ public class FlwCompiler {
final long compileStart = System.nanoTime();
private final ShaderSources sources;
private final UniformComponent uniformComponent;
private final MaterialAdapterComponent vertexMaterialComponent;
private final MaterialAdapterComponent fragmentMaterialComponent;
@ -48,7 +44,6 @@ public class FlwCompiler {
private final CullingContextSet cullingContexts;
final ShaderCompiler shaderCompiler;
final Multimap<Set<UniformProvider>, PipelineContext> uniformProviderGroups = ArrayListMultimap.create();
final Map<PipelineContext, GlProgram> pipelinePrograms = new HashMap<>();
final Map<StructType<?>, GlProgram> cullingPrograms = new HashMap<>();
final List<FailedCompilation> errors = new ArrayList<>();
@ -69,16 +64,22 @@ public class FlwCompiler {
.adapt(FnSignature.ofVoid("flw_materialFragment"))
.adapt(FnSignature.create()
.returnType("bool")
.name("flw_discardPredicate")
.arg("vec4", "color")
.build(), GlslExpr.literal(false))
.adapt(FnSignature.create()
.returnType("vec4")
.name("flw_fogFilter")
.arg("vec4", "color")
.build(), GlslExpr.variable("color"))
.switchOn(GlslExpr.variable("flw_materialFragmentID"))
.build(sources);
.name("flw_discardPredicate")
.arg("vec4", "color")
.build(), GlslExpr.literal(false))
.adapt(FnSignature.create()
.returnType("vec4")
.name("flw_fogFilter")
.arg("vec4", "color")
.build(), GlslExpr.variable("color"))
.switchOn(GlslExpr.variable("flw_materialFragmentID"))
.build(sources);
this.uniformComponent = UniformComponent.builder(Flywheel.rl("uniforms"))
.sources(ComponentRegistry.getAllUniformProviders()
.stream()
.map(UniformProvider::uniformShader)
.toList())
.build(sources);
this.pipelineContexts = PipelineContextSet.create();
this.cullingContexts = CullingContextSet.create();
@ -186,7 +187,7 @@ public class FlwCompiler {
.vertex()
.resourceLocation());
return ImmutableList.of(vertexMaterialComponent, instanceAssembly, layout, instance, context, pipeline);
return ImmutableList.of(uniformComponent, vertexMaterialComponent, instanceAssembly, layout, instance, context, pipeline);
}
private ImmutableList<SourceComponent> getFragmentComponents(PipelineContext ctx) {
@ -196,7 +197,7 @@ public class FlwCompiler {
var pipeline = sources.find(ctx.pipelineShader()
.fragment()
.resourceLocation());
return ImmutableList.of(fragmentMaterialComponent, context, pipeline);
return ImmutableList.of(uniformComponent, fragmentMaterialComponent, context, pipeline);
}
private ImmutableList<SourceComponent> getComputeComponents(StructType<?> structType) {
@ -205,7 +206,7 @@ public class FlwCompiler {
.resourceLocation());
var pipeline = sources.find(Pipelines.Files.INDIRECT_CULL.resourceLocation());
return ImmutableList.of(instanceAssembly, instance, pipeline);
return ImmutableList.of(uniformComponent, instanceAssembly, instance, pipeline);
}
}

View file

@ -14,11 +14,7 @@ import com.google.common.collect.ImmutableList;
import com.jozufozu.flywheel.core.SourceComponent;
import com.jozufozu.flywheel.core.source.FileResolution;
import com.jozufozu.flywheel.core.source.ShaderSources;
import com.jozufozu.flywheel.core.source.generate.FnSignature;
import com.jozufozu.flywheel.core.source.generate.GlslBlock;
import com.jozufozu.flywheel.core.source.generate.GlslBuilder;
import com.jozufozu.flywheel.core.source.generate.GlslExpr;
import com.jozufozu.flywheel.core.source.generate.GlslSwitch;
import com.jozufozu.flywheel.core.source.generate.*;
import com.jozufozu.flywheel.util.ResourceUtil;
import net.minecraft.resources.ResourceLocation;
@ -29,9 +25,9 @@ public class MaterialAdapterComponent implements SourceComponent {
private final ResourceLocation name;
private final GlslExpr switchArg;
private final List<AdaptedFn> functionsToAdapt;
private final List<RenamedFunctionsSourceComponent> adaptedComponents;
private final List<StringSubstitutionSourceComponent> adaptedComponents;
public MaterialAdapterComponent(ResourceLocation name, GlslExpr switchArg, List<AdaptedFn> functionsToAdapt, List<RenamedFunctionsSourceComponent> adaptedComponents) {
public MaterialAdapterComponent(ResourceLocation name, GlslExpr switchArg, List<AdaptedFn> functionsToAdapt, List<StringSubstitutionSourceComponent> adaptedComponents) {
this.name = name;
this.switchArg = switchArg;
this.functionsToAdapt = functionsToAdapt;
@ -157,13 +153,13 @@ public class MaterialAdapterComponent implements SourceComponent {
throw new NullPointerException("Switch argument must be set");
}
var transformed = ImmutableList.<RenamedFunctionsSourceComponent>builder();
var transformed = ImmutableList.<StringSubstitutionSourceComponent>builder();
for (FileResolution fileResolution : sourceMaterials) {
var loc = fileResolution.resourceLocation();
var sourceFile = sources.find(loc);
transformed.add(new RenamedFunctionsSourceComponent(sourceFile, createAdapterMap(adaptedFunctions, loc)));
transformed.add(new StringSubstitutionSourceComponent(sourceFile, createAdapterMap(adaptedFunctions, loc)));
}
return new MaterialAdapterComponent(name, switchArg, adaptedFunctions, transformed.build());

View file

@ -16,18 +16,13 @@ public class RecursiveIncluder implements Includer {
@Override
public void expand(ImmutableList<SourceComponent> rootSources, Consumer<SourceComponent> out) {
var included = depthFirstInclude(rootSources);
included.forEach(out);
rootSources.forEach(out);
}
private static LinkedHashSet<SourceComponent> depthFirstInclude(ImmutableList<SourceComponent> root) {
var included = new LinkedHashSet<SourceComponent>(); // linked to preserve order
for (var component : root) {
recursiveDepthFirstInclude(included, component);
}
return included;
}
var included = new LinkedHashSet<SourceComponent>(); // use hash set to deduplicate. linked to preserve order
for (var component : rootSources) {
recursiveDepthFirstInclude(included, component);
included.add(component);
}
included.forEach(out);
}
private static void recursiveDepthFirstInclude(Set<SourceComponent> included, SourceComponent component) {
for (var include : component.included()) {

View file

@ -8,16 +8,16 @@ import com.jozufozu.flywheel.util.ResourceUtil;
import net.minecraft.resources.ResourceLocation;
public final class RenamedFunctionsSourceComponent implements SourceComponent {
public final class StringSubstitutionSourceComponent implements SourceComponent {
private final SourceComponent source;
private final Map<String, String> replacements;
private final String sourceString;
public RenamedFunctionsSourceComponent(SourceComponent source, String find, String replace) {
public StringSubstitutionSourceComponent(SourceComponent source, String find, String replace) {
this(source, Map.of(find, replace));
}
public RenamedFunctionsSourceComponent(SourceComponent source, Map<String, String> replacements) {
public StringSubstitutionSourceComponent(SourceComponent source, Map<String, String> replacements) {
this.source = source;
this.replacements = replacements;
this.sourceString = source.source();
@ -44,7 +44,7 @@ public final class RenamedFunctionsSourceComponent implements SourceComponent {
@Override
public ResourceLocation name() {
return ResourceUtil.subPath(source.name(), "_renamed");
return ResourceUtil.subPath(source.name(), "_string_substitution");
}
@Override

View file

@ -0,0 +1,77 @@
package com.jozufozu.flywheel.backend.instancing.compile;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import com.google.common.collect.ImmutableList;
import com.jozufozu.flywheel.core.SourceComponent;
import com.jozufozu.flywheel.core.source.FileResolution;
import com.jozufozu.flywheel.core.source.ShaderSources;
import com.jozufozu.flywheel.core.source.SourceFile;
import com.jozufozu.flywheel.core.source.generate.GlslBuilder;
import net.minecraft.resources.ResourceLocation;
public class UniformComponent implements SourceComponent {
private final ResourceLocation name;
private final ImmutableList<SourceFile> uniformShaders;
public static Builder builder(ResourceLocation uniforms) {
return new Builder(uniforms);
}
private UniformComponent(ResourceLocation name, ImmutableList<SourceFile> uniformShaders) {
this.name = name;
this.uniformShaders = uniformShaders;
}
@Override
public Collection<? extends SourceComponent> included() {
return uniformShaders;
}
@Override
public String source() {
var builder = new GlslBuilder();
builder.uniformBlock()
.layout("std140")
.binding(0)
.name("FLWUniforms")
.member("flywheel_uniforms", "flywheel");
return builder.build();
}
@Override
public ResourceLocation name() {
return name;
}
public static class Builder {
private final ResourceLocation name;
private final List<FileResolution> uniformShaders = new ArrayList<>();
public Builder(ResourceLocation name) {
this.name = name;
}
public Builder sources(List<FileResolution> sources) {
this.uniformShaders.addAll(sources);
return this;
}
public UniformComponent build(ShaderSources sources) {
var out = ImmutableList.<SourceFile>builder();
for (var fileResolution : uniformShaders) {
out.add(sources.find(fileResolution.resourceLocation()));
}
return new UniformComponent(name, out.build());
}
}
}

View file

@ -8,7 +8,7 @@ import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.BackendType;
import com.jozufozu.flywheel.backend.SimpleBackendType;
import com.jozufozu.flywheel.core.BackendTypes;
import com.jozufozu.flywheel.core.uniform.FrustumProvider;
import com.jozufozu.flywheel.core.uniform.FlwUniformProvider;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.IntegerArgumentType;
@ -111,17 +111,17 @@ public class FlwCommands {
commandBuilder.command.then(Commands.literal("debugFrustum")
.then(Commands.literal("pause")
.executes(context -> {
FrustumProvider.PAUSED = true;
FlwUniformProvider.FRUSTUM_PAUSED = true;
return 1;
}))
.then(Commands.literal("unpause")
.executes(context -> {
FrustumProvider.PAUSED = false;
FlwUniformProvider.FRUSTUM_PAUSED = false;
return 1;
}))
.then(Commands.literal("capture")
.executes(context -> {
FrustumProvider.CAPTURE = true;
FlwUniformProvider.FRUSTUM_CAPTURE = true;
return 1;
})));

View file

@ -10,9 +10,7 @@ import com.jozufozu.flywheel.core.source.SourceChecks;
import com.jozufozu.flywheel.core.source.SourceFile;
import com.jozufozu.flywheel.core.source.error.ErrorReporter;
import com.jozufozu.flywheel.core.structs.StructTypes;
import com.jozufozu.flywheel.core.uniform.FogProvider;
import com.jozufozu.flywheel.core.uniform.FrustumProvider;
import com.jozufozu.flywheel.core.uniform.ViewProvider;
import com.jozufozu.flywheel.core.uniform.FlwUniformProvider;
import com.jozufozu.flywheel.core.vertex.Formats;
import com.jozufozu.flywheel.util.ResourceUtil;
@ -21,10 +19,8 @@ import net.minecraft.resources.ResourceLocation;
public class Components {
public static final ViewProvider VIEW_PROVIDER = ComponentRegistry.register(new ViewProvider());
public static final FogProvider FOG_PROVIDER = ComponentRegistry.register(new FogProvider());
public static final FrustumProvider FRUSTUM_PROVIDER = ComponentRegistry.register(new FrustumProvider());
public static final ContextShader WORLD = ComponentRegistry.register(new ContextShader(WorldProgram::new, Files.WORLD_VERTEX, Files.WORLD_FRAGMENT));
public static final FlwUniformProvider UNIFORM_PROVIDER = ComponentRegistry.register(new FlwUniformProvider());
public static final ContextShader WORLD = ComponentRegistry.register(new ContextShader(WorldProgram::new, Files.WORLD_VERTEX, Files.WORLD_FRAGMENT));
public static final ContextShader CRUMBLING = ComponentRegistry.register(new ContextShader(CrumblingProgram::new, Files.WORLD_VERTEX, Files.CRUMBLING_FRAGMENT));
public static void init() {
@ -37,10 +33,8 @@ public class Components {
public static class Files {
public static final FileResolution VIEW_UNIFORMS = uniform(Flywheel.rl("uniform/view.glsl"));
public static final FileResolution FOG_UNIFORMS = uniform(Flywheel.rl("uniform/fog.glsl"));
public static final FileResolution FRUSTUM_UNIFORMS = uniform(Flywheel.rl("uniform/frustum.glsl"));
public static final FileResolution BLOCK_LAYOUT = layoutVertex(ResourceUtil.subPath(Names.BLOCK, ".vert"));
public static final FileResolution UNIFORMS = uniform(Flywheel.rl("uniform/flywheel.glsl"));
public static final FileResolution BLOCK_LAYOUT = layoutVertex(ResourceUtil.subPath(Names.BLOCK, ".vert"));
public static final FileResolution POS_TEX_NORMAL_LAYOUT = layoutVertex(ResourceUtil.subPath(Names.POS_TEX_NORMAL, ".vert"));
public static final FileResolution TRANSFORMED = instanceVertex(ResourceUtil.subPath(Names.TRANSFORMED, ".vert"));
public static final FileResolution ORIENTED = instanceVertex(ResourceUtil.subPath(Names.ORIENTED, ".vert"));

View file

@ -1,10 +1,6 @@
package com.jozufozu.flywheel.core.source;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.*;
import java.util.regex.Matcher;
import com.google.common.collect.ImmutableList;
@ -72,10 +68,7 @@ public class SourceFile implements SourceComponent {
try {
var loc = new ResourceLocation(file);
var sourceFile = sourceFinder.find(loc);
if (sourceFile != null) {
sink.accept(sourceFile);
}
sink.accept(sourceFile);
} catch (Exception ignored) {
}
})
@ -122,10 +115,12 @@ public class SourceFile implements SourceComponent {
* @param name The name of the struct to find.
* @return null if no definition matches the name.
*/
public Optional<ShaderStruct> findStruct(String name) {
public Optional<ShaderStruct> findStructByName(String name) {
ShaderStruct struct = structs.get(name);
if (struct != null) return Optional.of(struct);
if (struct != null) {
return Optional.of(struct);
}
for (var include : included) {
var external = include.structs.get(name);
@ -268,8 +263,9 @@ public class SourceFile implements SourceComponent {
Span self = Span.fromMatcher(this, matcher);
Span name = Span.fromMatcher(this, matcher, 1);
Span body = Span.fromMatcher(this, matcher, 2);
Span variableName = Span.fromMatcher(this, matcher, 3);
ShaderStruct shaderStruct = new ShaderStruct(self, name, body);
ShaderStruct shaderStruct = new ShaderStruct(self, name, body, variableName);
structs.put(name.get(), shaderStruct);
}

View file

@ -17,24 +17,28 @@ public class GlslBuilder {
public GlslStruct struct() {
return add(new GlslStruct());
}
}
public GlslFn function() {
return add(new GlslFn());
}
public GlslFn function() {
return add(new GlslFn());
}
public GlslVertexInput vertexInput() {
return add(new GlslVertexInput());
}
public GlslVertexInput vertexInput() {
return add(new GlslVertexInput());
}
public <T extends Declaration> T add(T element) {
elements.add(element);
return element;
}
public GlslUniformBlock uniformBlock() {
return add(new GlslUniformBlock());
}
public void blankLine() {
elements.add(Separators.BLANK_LINE);
}
public <T extends Declaration> T add(T element) {
elements.add(element);
return element;
}
public void blankLine() {
elements.add(Separators.BLANK_LINE);
}
public void _addRaw(String sourceString) {
elements.add(() -> sourceString);

View file

@ -35,21 +35,21 @@ public class GlslSwitch implements GlslStmt {
@Override
public String prettyPrint() {
return """
switch (%s) {
%s
}""".formatted(on.prettyPrint(), getCaseStream());
switch (%s) {
%s
}""".formatted(on.prettyPrint(), formatCases());
}
@NotNull
private String getCaseStream() {
var cases = this.cases.stream()
.map(GlslSwitch::prettyPrintCase)
.collect(Collectors.joining("\n"));
if (defaultCase != null) {
cases += "\ndefault:\n" + StringUtil.indent(defaultCase.prettyPrint(), 4);
}
return cases;
}
@NotNull
private String formatCases() {
var cases = this.cases.stream()
.map(GlslSwitch::prettyPrintCase)
.collect(Collectors.joining("\n"));
if (defaultCase != null) {
cases += "\ndefault:\n" + StringUtil.indent(defaultCase.prettyPrint(), 4);
}
return cases;
}
private static String prettyPrintCase(Pair<GlslExpr, GlslBlock> p) {
var variant = p.first()

View file

@ -0,0 +1,52 @@
package com.jozufozu.flywheel.core.source.generate;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import com.jozufozu.flywheel.util.Pair;
import com.jozufozu.flywheel.util.StringUtil;
public class GlslUniformBlock implements GlslBuilder.Declaration {
private String qualifier;
private int binding;
private String name;
private final List<Pair<String, String>> members = new ArrayList<>();
@Override
public String prettyPrint() {
return """
layout(%s, binding = %d) uniform %s {
%s
};
""".formatted(qualifier, binding, name, StringUtil.indent(formatMembers(), 4));
}
private String formatMembers() {
return members.stream()
.map(p -> p.first() + " " + p.second() + ";")
.collect(Collectors.joining("\n"));
}
public GlslUniformBlock layout(String qualifier) {
this.qualifier = qualifier;
return this;
}
public GlslUniformBlock binding(int i) {
binding = i;
return this;
}
public GlslUniformBlock name(String name) {
this.name = name;
return this;
}
public GlslUniformBlock member(String typeName, String variableName) {
members.add(Pair.of(typeName, variableName));
return this;
}
}

View file

@ -10,19 +10,21 @@ import com.jozufozu.flywheel.core.source.span.Span;
public class ShaderStruct {
// https://regexr.com/61rpe
public static final Pattern PATTERN = Pattern.compile("struct\\s+([\\w\\d]*)\\s*\\{([\\w\\d\\s,;]*)}\\s*;\\s");
public static final Pattern PATTERN = Pattern.compile("struct\\s+([\\w_]*)\\s*\\{(.*?)}\\s*([\\w_]*)?\\s*;\\s", Pattern.DOTALL);
public final Span name;
public final Span body;
public final Span self;
public final Span variableName;
private final ImmutableList<StructField> fields;
private final ImmutableMap<String, Span> fields2Types;
public ShaderStruct(Span self, Span name, Span body) {
public ShaderStruct(Span self, Span name, Span body, Span variableName) {
this.self = self;
this.name = name;
this.body = body;
this.variableName = variableName;
this.fields = parseFields();
this.fields2Types = createTypeLookup();
}

View file

@ -131,7 +131,7 @@ public abstract class Span implements CharSequence, Comparable<Span> {
if (isErr()) {
return Optional.empty();
}
return in.findStruct(this.toString());
return in.findStructByName(this.toString());
}
public Optional<ShaderFunction> findFunction() {

View file

@ -0,0 +1,148 @@
package com.jozufozu.flywheel.core.uniform;
import java.util.function.Consumer;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.uniform.UniformProvider;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.core.Components;
import com.jozufozu.flywheel.core.RenderContext;
import com.jozufozu.flywheel.core.source.FileResolution;
import com.jozufozu.flywheel.event.BeginFrameEvent;
import com.jozufozu.flywheel.extension.MatrixWrite;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.core.Vec3i;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.common.MinecraftForge;
public class FlwUniformProvider implements UniformProvider {
public static final int SIZE = 224;
public static boolean FRUSTUM_PAUSED = false;
public static boolean FRUSTUM_CAPTURE = false;
public static boolean FOG_UPDATE = true;
@Override
public int byteSize() {
return SIZE;
}
@Override
public FileResolution uniformShader() {
return Components.Files.UNIFORMS;
}
@Override
public ActiveUniformProvider activate(long ptr) {
return new Active(ptr);
}
public static class Active implements ActiveUniformProvider, Consumer<BeginFrameEvent> {
private final long ptr;
private boolean dirty;
public Active(long ptr) {
this.ptr = ptr;
MinecraftForge.EVENT_BUS.addListener(this);
}
@Override
public void delete() {
MinecraftForge.EVENT_BUS.unregister(this);
}
@Override
public boolean poll() {
boolean updated = maybeUpdateFog();
updated |= dirty;
dirty = false;
return updated;
}
@Override
public void accept(BeginFrameEvent event) {
updateFrustum(event.getContext());
updateView(event.getContext());
}
private boolean maybeUpdateFog() {
if (!FOG_UPDATE || ptr == MemoryUtil.NULL) {
return false;
}
var color = RenderSystem.getShaderFogColor();
MemoryUtil.memPutFloat(ptr, color[0]);
MemoryUtil.memPutFloat(ptr + 4, color[1]);
MemoryUtil.memPutFloat(ptr + 8, color[2]);
MemoryUtil.memPutFloat(ptr + 12, color[3]);
MemoryUtil.memPutFloat(ptr + 16, RenderSystem.getShaderFogStart());
MemoryUtil.memPutFloat(ptr + 20, RenderSystem.getShaderFogEnd());
MemoryUtil.memPutInt(ptr + 24, RenderSystem.getShaderFogShape()
.getIndex());
FOG_UPDATE = false;
return true;
}
public void updateFrustum(RenderContext context) {
if (ptr == MemoryUtil.NULL || (FRUSTUM_PAUSED && !FRUSTUM_CAPTURE)) {
return;
}
Vec3i originCoordinate = InstancedRenderDispatcher.getOriginCoordinate(context.level());
Vec3 camera = context.camera()
.getPosition();
var camX = (float) (camera.x - originCoordinate.getX());
var camY = (float) (camera.y - originCoordinate.getY());
var camZ = (float) (camera.z - originCoordinate.getZ());
var shiftedCuller = RenderContext.createCuller(context.viewProjection(), -camX, -camY, -camZ);
shiftedCuller.getJozuPackedPlanes(ptr + 128);
dirty = true;
FRUSTUM_CAPTURE = false;
}
public void updateView(RenderContext context) {
if (ptr == MemoryUtil.NULL) {
return;
}
ClientLevel level = context.level();
int constantAmbientLight = level.effects()
.constantAmbientLight() ? 1 : 0;
Vec3i originCoordinate = InstancedRenderDispatcher.getOriginCoordinate(level);
Vec3 camera = context.camera()
.getPosition();
var camX = (float) (camera.x - originCoordinate.getX());
var camY = (float) (camera.y - originCoordinate.getY());
var camZ = (float) (camera.z - originCoordinate.getZ());
// don't want to mutate viewProjection
var vp = context.viewProjection()
.copy();
vp.multiplyWithTranslation(-camX, -camY, -camZ);
MatrixWrite.writeUnsafe(vp, ptr + 32);
MemoryUtil.memPutFloat(ptr + 96, camX);
MemoryUtil.memPutFloat(ptr + 100, camY);
MemoryUtil.memPutFloat(ptr + 104, camZ);
MemoryUtil.memPutFloat(ptr + 108, 0f); // vec4 alignment
MemoryUtil.memPutInt(ptr + 112, constantAmbientLight);
dirty = true;
}
}
}

View file

@ -1,63 +0,0 @@
package com.jozufozu.flywheel.core.uniform;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.uniform.UniformProvider;
import com.jozufozu.flywheel.core.Components;
import com.jozufozu.flywheel.core.source.FileResolution;
import com.mojang.blaze3d.systems.RenderSystem;
public class FogProvider implements UniformProvider {
public static boolean FOG_UPDATE = true;
@Override
public int byteSize() {
return 16 + 8 + 4;
}
@Override
public FileResolution uniformShader() {
return Components.Files.FOG_UNIFORMS;
}
@Override
public ActiveUniformProvider activate(long ptr) {
return new Active(ptr);
}
public static class Active implements ActiveUniformProvider {
private final long ptr;
public Active(long ptr) {
this.ptr = ptr;
}
@Override
public void delete() {
}
@Override
public boolean poll() {
if (!FOG_UPDATE) {
return false;
}
var color = RenderSystem.getShaderFogColor();
MemoryUtil.memPutFloat(ptr, color[0]);
MemoryUtil.memPutFloat(ptr + 4, color[1]);
MemoryUtil.memPutFloat(ptr + 8, color[2]);
MemoryUtil.memPutFloat(ptr + 12, color[3]);
MemoryUtil.memPutFloat(ptr + 16, RenderSystem.getShaderFogStart());
MemoryUtil.memPutFloat(ptr + 20, RenderSystem.getShaderFogEnd());
MemoryUtil.memPutInt(ptr + 24, RenderSystem.getShaderFogShape()
.getIndex());
FOG_UPDATE = false;
return true;
}
}
}

View file

@ -1,88 +0,0 @@
package com.jozufozu.flywheel.core.uniform;
import java.util.function.Consumer;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.uniform.UniformProvider;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.core.Components;
import com.jozufozu.flywheel.core.RenderContext;
import com.jozufozu.flywheel.core.source.FileResolution;
import com.jozufozu.flywheel.event.BeginFrameEvent;
import net.minecraft.core.Vec3i;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.common.MinecraftForge;
public class FrustumProvider implements UniformProvider {
public static boolean PAUSED = false;
public static boolean CAPTURE = false;
@Override
public int byteSize() {
return 96;
}
@Override
public FileResolution uniformShader() {
return Components.Files.FRUSTUM_UNIFORMS;
}
@Override
public ActiveUniformProvider activate(long ptr) {
return new Active(ptr);
}
static class Active implements ActiveUniformProvider, Consumer<BeginFrameEvent> {
private final long ptr;
private boolean dirty = true;
public Active(long ptr) {
this.ptr = ptr;
MinecraftForge.EVENT_BUS.addListener(this);
}
@Override
public void delete() {
MinecraftForge.EVENT_BUS.unregister(this);
}
@Override
public boolean poll() {
if (dirty) {
dirty = false;
return true;
}
return false;
}
@Override
public void accept(BeginFrameEvent event) {
update(event.getContext());
}
public void update(RenderContext context) {
if (ptr == MemoryUtil.NULL || (PAUSED && !CAPTURE)) {
return;
}
Vec3i originCoordinate = InstancedRenderDispatcher.getOriginCoordinate(context.level());
Vec3 camera = context.camera()
.getPosition();
var camX = (float) (camera.x - originCoordinate.getX());
var camY = (float) (camera.y - originCoordinate.getY());
var camZ = (float) (camera.z - originCoordinate.getZ());
var shiftedCuller = RenderContext.createCuller(context.viewProjection(), -camX, -camY, -camZ);
shiftedCuller.getJozuPackedPlanes(ptr);
dirty = true;
CAPTURE = false;
}
}
}

View file

@ -34,6 +34,7 @@ public class UniformBuffer {
private final GlBuffer buffer;
private UniformBuffer() {
// TODO: put everything into one ubo
buffer = new GlBuffer(GlBufferType.UNIFORM_BUFFER);
providerSet = new AllocatedProviderSet(ComponentRegistry.getAllUniformProviders());
}

View file

@ -1,95 +0,0 @@
package com.jozufozu.flywheel.core.uniform;
import java.util.function.Consumer;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.uniform.UniformProvider;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.core.Components;
import com.jozufozu.flywheel.core.RenderContext;
import com.jozufozu.flywheel.core.source.FileResolution;
import com.jozufozu.flywheel.event.BeginFrameEvent;
import com.jozufozu.flywheel.extension.MatrixWrite;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.core.Vec3i;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.common.MinecraftForge;
public class ViewProvider implements UniformProvider {
public static final int SIZE = 4 * 16 + 16 + 4;
@Override
public int byteSize() {
return SIZE;
}
@Override
public FileResolution uniformShader() {
return Components.Files.VIEW_UNIFORMS;
}
@Override
public ActiveUniformProvider activate(long ptr) {
return new Active(ptr);
}
public static class Active implements ActiveUniformProvider, Consumer<BeginFrameEvent> {
private final long ptr;
private boolean dirty = true;
public Active(long ptr) {
this.ptr = ptr;
MinecraftForge.EVENT_BUS.addListener(this);
}
@Override
public void delete() {
MinecraftForge.EVENT_BUS.unregister(this);
}
@Override
public boolean poll() {
if (dirty) {
dirty = false;
return true;
}
return false;
}
@Override
public void accept(BeginFrameEvent event) {
update(event.getContext());
}
public void update(RenderContext context) {
ClientLevel level = context.level();
int constantAmbientLight = level.effects()
.constantAmbientLight() ? 1 : 0;
Vec3i originCoordinate = InstancedRenderDispatcher.getOriginCoordinate(level);
Vec3 camera = context.camera()
.getPosition();
var camX = (float) (camera.x - originCoordinate.getX());
var camY = (float) (camera.y - originCoordinate.getY());
var camZ = (float) (camera.z - originCoordinate.getZ());
// don't want to mutate viewProjection
var vp = context.viewProjection()
.copy();
vp.multiplyWithTranslation(-camX, -camY, -camZ);
MatrixWrite.writeUnsafe(vp, ptr);
MemoryUtil.memPutFloat(ptr + 64, camX);
MemoryUtil.memPutFloat(ptr + 68, camY);
MemoryUtil.memPutFloat(ptr + 72, camZ);
MemoryUtil.memPutInt(ptr + 76, constantAmbientLight);
dirty = true;
}
}
}

View file

@ -5,14 +5,14 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.jozufozu.flywheel.core.uniform.FogProvider;
import com.jozufozu.flywheel.core.uniform.FlwUniformProvider;
import net.minecraft.client.renderer.FogRenderer;
@Mixin(FogRenderer.class)
public class FogUpdateMixin {
private static void flywheel$updateFog() {
FogProvider.FOG_UPDATE = true;
FlwUniformProvider.FOG_UPDATE = true;
}
@Inject(method = "setupNoFog", at = @At("TAIL"))

View file

@ -1,10 +1,8 @@
#use "flywheel:api/vertex.glsl"
#use "flywheel:util/fog.glsl"
#use "flywheel:uniform/fog.glsl"
#use "flywheel:uniform/view.glsl"
void flw_contextVertex() {
flw_distance = fog_distance(flw_vertexPos.xyz, flw_cameraPos.xyz, flw_fogShape);
gl_Position = flw_viewProjection * flw_vertexPos;
flw_distance = fog_distance(flw_vertexPos.xyz, flywheel.cameraPos.xyz, flywheel.fogShape);
gl_Position = flywheel.viewProjection * flw_vertexPos;
flw_vertexNormal = normalize(flw_vertexNormal);
}

View file

@ -1,7 +1,5 @@
#use "flywheel:uniform/view.glsl"
layout(location = 0) in vec3 worldPos;
void main() {
gl_Position = flw_viewProjection * vec4(worldPos, 1.0);
gl_Position = flywheel.viewProjection * vec4(worldPos, 1.0);
}

View file

@ -1,6 +1,5 @@
#use "flywheel:api/fragment.glsl"
#use "flywheel:util/fog.glsl"
#use "flywheel:uniform/fog.glsl"
void flw_materialFragment() {
}
@ -11,5 +10,5 @@ bool flw_discardPredicate(vec4 finalColor) {
}
vec4 flw_fogFilter(vec4 color) {
return linear_fog(color, flw_distance, flw_fogRange.x, flw_fogRange.y, flw_fogColor);
return linear_fog(color, flw_distance, flywheel.fogRange.x, flywheel.fogRange.y, flywheel.fogColor);
}

View file

@ -1,10 +1,9 @@
#use "flywheel:api/fragment.glsl"
#use "flywheel:util/fog.glsl"
#use "flywheel:uniform/fog.glsl"
void flw_materialFragment() {
}
vec4 flw_fogFilter(vec4 color) {
return linear_fog(color, flw_distance, flw_fogRange.x, flw_fogRange.y, flw_fogColor);
return linear_fog(color, flw_distance, flywheel.fogRange.x, flywheel.fogRange.y, flywheel.fogColor);
}

View file

@ -1,12 +1,11 @@
#use "flywheel:api/vertex.glsl"
#use "flywheel:util/diffuse.glsl"
#use "flywheel:uniform/view.glsl"
void flw_materialVertex() {
flw_vertexNormal = normalize(flw_vertexNormal);
float diffuseFactor;
if (flw_constantAmbientLight == 1) {
if (flywheel.constantAmbientLight == 1) {
diffuseFactor = diffuseNether(flw_vertexNormal);
} else {
diffuseFactor = diffuse(flw_vertexNormal);

View file

@ -1,7 +1,6 @@
#define FLW_SUBGROUP_SIZE 32
layout(local_size_x = FLW_SUBGROUP_SIZE) in;
#use "flywheel:api/cull.glsl"
#use "flywheel:uniform/frustum.glsl"
#use "flywheel:util/types.glsl"
struct MeshDrawCommand {
@ -33,8 +32,8 @@ layout(std430, binding = 3) restrict buffer DrawCommands {
// 83 - 27 = 56 spirv instruction results
bool testSphere(vec3 center, float radius) {
bvec4 xyInside = greaterThanEqual(fma(flw_planes.xyX, center.xxxx, fma(flw_planes.xyY, center.yyyy, fma(flw_planes.xyZ, center.zzzz, flw_planes.xyW))), -radius.xxxx);
bvec2 zInside = greaterThanEqual(fma(flw_planes.zX, center.xx, fma(flw_planes.zY, center.yy, fma(flw_planes.zZ, center.zz, flw_planes.zW))), -radius.xx);
bvec4 xyInside = greaterThanEqual(fma(flywheel.planes.xyX, center.xxxx, fma(flywheel.planes.xyY, center.yyyy, fma(flywheel.planes.xyZ, center.zzzz, flywheel.planes.xyW))), -radius.xxxx);
bvec2 zInside = greaterThanEqual(fma(flywheel.planes.zX, center.xx, fma(flywheel.planes.zY, center.yy, fma(flywheel.planes.zZ, center.zz, flywheel.planes.zW))), -radius.xx);
return all(xyInside) && all(zInside);
}

View file

@ -0,0 +1,20 @@
struct FLWPackedPlanes {
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>
vec4 xyW;// <nx.w, px.w, ny.w, py.w>
vec2 zX;// <nz.x, pz.x>
vec2 zY;// <nz.y, pz.y>
vec2 zZ;// <nz.z, pz.z>
vec2 zW;// <nz.w, pz.w>
};
struct flywheel_uniforms {
vec4 fogColor;
vec2 fogRange;
int fogShape;
mat4 viewProjection;
vec4 cameraPos;
int constantAmbientLight;
FLWPackedPlanes planes;
};

View file

@ -1,6 +0,0 @@
// TODO: inject FLW_UNIFORM_BINDING definitions
layout(std140, binding = FLW_UNIFORM_BINDING) uniform flw_fog {
vec4 flw_fogColor;
vec2 flw_fogRange;
int flw_fogShape;
};

View file

@ -1,14 +0,0 @@
struct FLWPackedPlanes {
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>
vec4 xyW; // <nx.w, px.w, ny.w, py.w>
vec2 zX; // <nz.x, pz.x>
vec2 zY; // <nz.y, pz.y>
vec2 zZ; // <nz.z, pz.z>
vec2 zW; // <nz.w, pz.w>
};
layout(std140, binding = FLW_UNIFORM_BINDING) uniform FLWFrustum {
FLWPackedPlanes flw_planes;
};

View file

@ -1,5 +0,0 @@
layout(std140, binding = FLW_UNIFORM_BINDING) uniform flw_view {
mat4 flw_viewProjection;
vec4 flw_cameraPos;
int flw_constantAmbientLight;
};