Skip to content

Commit

Permalink
Uber smooth
Browse files Browse the repository at this point in the history
- Add material shader component to specify smooth lighting behavior
- Allows much easier composition of smooth lighting/material shader
  effects, and potentially gives backends the option to specialize
  shaders on the complexity of shader lighting
- Pack fog, cutout, and light into a single uint
  • Loading branch information
Jozufozu committed Jul 27, 2024
1 parent cdc6824 commit 69411fb
Show file tree
Hide file tree
Showing 20 changed files with 132 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package dev.engine_room.flywheel.api.material;

import dev.engine_room.flywheel.api.internal.FlwApiLink;
import dev.engine_room.flywheel.api.registry.Registry;
import net.minecraft.resources.ResourceLocation;

public interface LightShader {
Registry<LightShader> REGISTRY = FlwApiLink.INSTANCE.createRegistry();

ResourceLocation source();
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ public interface Material {

CutoutShader cutout();

LightShader light();

ResourceLocation texture();

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import dev.engine_room.flywheel.api.material.CutoutShader;
import dev.engine_room.flywheel.api.material.FogShader;
import dev.engine_room.flywheel.api.material.LightShader;
import dev.engine_room.flywheel.api.material.MaterialShaders;
import dev.engine_room.flywheel.api.registry.Registry;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
Expand All @@ -25,6 +26,8 @@ public final class MaterialShaderIndices {
private static Index fogSources;
@Nullable
private static Index cutoutSources;
@Nullable
private static Index lightSources;

private MaterialShaderIndices() {
}
Expand Down Expand Up @@ -57,6 +60,13 @@ public static Index cutoutSources() {
return cutoutSources;
}

public static Index lightSources() {
if (lightSources == null) {
lightSources = indexFromRegistry(LightShader.REGISTRY, LightShader::source);
}
return lightSources;
}

public static int vertexIndex(MaterialShaders shaders) {
return vertexSources().index(shaders.vertexSource());
}
Expand All @@ -73,6 +83,10 @@ public static int cutoutIndex(CutoutShader cutoutShader) {
return cutoutSources().index(cutoutShader.source());
}

public static int lightIndex(LightShader lightShader) {
return lightSources().index(lightShader.source());
}

private static <T> Index indexFromRegistry(Registry<T> registry, Function<T, ResourceLocation> sourceFunc) {
if (!registry.isFrozen()) {
throw new IllegalStateException("Cannot create index from registry that is not frozen!");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,16 @@ static void reload(ResourceManager resourceManager) {
var fragmentMaterialComponent = createFragmentMaterialComponent(loader);
var fogComponent = createFogComponent(loader);
var cutoutComponent = createCutoutComponent(loader);
var lightComponent = createLightComponent(loader);

if (stats.errored() || vertexComponentsHeader == null || fragmentComponentsHeader == null || vertexMaterialComponent == null || fragmentMaterialComponent == null || fogComponent == null || cutoutComponent == null) {
if (stats.errored() || vertexComponentsHeader == null || fragmentComponentsHeader == null || vertexMaterialComponent == null || fragmentMaterialComponent == null || fogComponent == null || cutoutComponent == null || lightComponent == null) {
// Probably means the shader sources are missing.
stats.emitErrorLog();
return;
}

List<SourceComponent> vertexComponents = List.of(vertexComponentsHeader, vertexMaterialComponent);
List<SourceComponent> fragmentComponents = List.of(fragmentComponentsHeader, fragmentMaterialComponent, fogComponent, cutoutComponent);
List<SourceComponent> fragmentComponents = List.of(fragmentComponentsHeader, fragmentMaterialComponent, fogComponent, cutoutComponent, lightComponent);

var pipelineKeys = createPipelineKeys();
InstancingPrograms.reload(sources, pipelineKeys, vertexComponents, fragmentComponents);
Expand Down Expand Up @@ -118,4 +119,17 @@ private static UberShaderComponent createCutoutComponent(SourceLoader loader) {
.switchOn(GlslExpr.variable("_flw_uberCutoutIndex"))
.build(loader);
}

@Nullable
private static UberShaderComponent createLightComponent(SourceLoader loader) {
return UberShaderComponent.builder(Flywheel.rl("light"))
.materialSources(MaterialShaderIndices.lightSources()
.all())
.adapt(FnSignature.create()
.returnType("void")
.name("flw_shaderLight")
.build())
.switchOn(GlslExpr.variable("_flw_uberLightIndex"))
.build(loader);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,11 @@ private static int bitMask(int bitLength, int bitOffset) {
return ((1 << bitLength) - 1) << bitOffset;
}

public static int packFogAndCutout(Material material) {
public static int packUberShader(Material material) {
var fog = MaterialShaderIndices.fogIndex(material.fog());
var cutout = MaterialShaderIndices.cutoutIndex(material.cutout());
return fog & 0xFFFF | (cutout & 0xFFFF) << 16;
var light = MaterialShaderIndices.lightIndex(material.light());
return (light & 0x3FF) | (cutout & 0x3FF) << 10 | (fog & 0x3FF) << 20;
}

// Packed format:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public IndirectDraw(IndirectInstancer<?> instancer, Material material, MeshPool.

this.materialVertexIndex = MaterialShaderIndices.vertexIndex(material.shaders());
this.materialFragmentIndex = MaterialShaderIndices.fragmentIndex(material.shaders());
this.packedFogAndCutout = MaterialEncoder.packFogAndCutout(material);
this.packedFogAndCutout = MaterialEncoder.packUberShader(material);
this.packedMaterialProperties = MaterialEncoder.packProperties(material);
}

Expand Down Expand Up @@ -88,7 +88,7 @@ public void writeWithOverrides(long ptr, int instanceIndex, Material materialOve

MemoryUtil.memPutInt(ptr + 24, MaterialShaderIndices.vertexIndex(materialOverride.shaders())); // materialVertexIndex
MemoryUtil.memPutInt(ptr + 28, MaterialShaderIndices.fragmentIndex(materialOverride.shaders())); // materialFragmentIndex
MemoryUtil.memPutInt(ptr + 32, MaterialEncoder.packFogAndCutout(materialOverride)); // packedFogAndCutout
MemoryUtil.memPutInt(ptr + 32, MaterialEncoder.packUberShader(materialOverride)); // packedFogAndCutout
MemoryUtil.memPutInt(ptr + 36, MaterialEncoder.packProperties(materialOverride)); // packedMaterialProperties
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ public static void uploadMaterialUniform(GlProgram program, Material material) {
int uniformLocation = program.getUniformLocation("_flw_packedMaterial");
int vertexIndex = MaterialShaderIndices.vertexIndex(material.shaders());
int fragmentIndex = MaterialShaderIndices.fragmentIndex(material.shaders());
int packedFogAndCutout = MaterialEncoder.packFogAndCutout(material);
int packedFogAndCutout = MaterialEncoder.packUberShader(material);
int packedMaterialProperties = MaterialEncoder.packProperties(material);
GL32.glUniform4ui(uniformLocation, vertexIndex, fragmentIndex, packedFogAndCutout, packedMaterialProperties);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ void _flw_main() {

vec4 color = flw_fragColor;

if (flw_discardPredicate(color)) {
discard;
}

float diffuseFactor = _flw_diffuseFactor();
color.rgb *= diffuseFactor;

Expand All @@ -57,14 +61,12 @@ void _flw_main() {

vec4 lightColor = vec4(1.);
if (flw_material.useLight) {
flw_shaderLight();

lightColor = texture(flw_lightTex, clamp(flw_fragLight, 0.5 / 16.0, 15.5 / 16.0));
color *= lightColor;
}

if (flw_discardPredicate(color)) {
discard;
}

switch (_flw_debugMode) {
case 1u:
color = vec4(flw_vertexNormal * .5 + .5, 1.);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
uint _flw_uberMaterialFragmentIndex;
uint _flw_uberFogIndex;
uint _flw_uberCutoutIndex;
uint _flw_uberLightIndex;
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ flat in uvec3 _flw_packedMaterial;

void main() {
_flw_uberMaterialFragmentIndex = _flw_packedMaterial.x;
_flw_unpackUint2x16(_flw_packedMaterial.y, _flw_uberCutoutIndex, _flw_uberFogIndex);
_flw_unpackUint3x10(_flw_packedMaterial.y, _flw_uberFogIndex, _flw_uberCutoutIndex, _flw_uberLightIndex);
_flw_unpackMaterialProperties(_flw_packedMaterial.z, flw_material);

_flw_main();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ uniform uvec4 _flw_packedMaterial;

void main() {
_flw_uberMaterialFragmentIndex = _flw_packedMaterial.y;
_flw_unpackUint2x16(_flw_packedMaterial.z, _flw_uberCutoutIndex, _flw_uberFogIndex);
_flw_unpackUint3x10(_flw_packedMaterial.z, _flw_uberFogIndex, _flw_uberCutoutIndex, _flw_uberLightIndex);
_flw_unpackMaterialProperties(_flw_packedMaterial.w, flw_material);

_flw_main();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,9 @@ void _flw_unpackUint2x16(uint s, out uint hi, out uint lo) {
hi = (s >> 16) & 0xFFFFu;
lo = s & 0xFFFFu;
}

void _flw_unpackUint3x10(uint s, out uint hi, out uint mi, out uint lo) {
hi = (s >> 20) & 0x3FFu;
mi = (s >> 10) & 0x3FFu;
lo = s & 0x3FFu;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package dev.engine_room.flywheel.lib.material;

import org.jetbrains.annotations.ApiStatus;

import dev.engine_room.flywheel.api.Flywheel;
import dev.engine_room.flywheel.api.material.LightShader;

public class LightShaders {
public static final LightShader SMOOTH_WHEN_EMBEDDED = LightShader.REGISTRY.registerAndGet(new SimpleLightShader(Flywheel.rl("light/smooth_when_embedded.glsl")));
public static final LightShader SMOOTH = LightShader.REGISTRY.registerAndGet(new SimpleLightShader(Flywheel.rl("light/smooth.glsl")));
public static final LightShader FLAT = LightShader.REGISTRY.registerAndGet(new SimpleLightShader(Flywheel.rl("light/flat.glsl")));

private LightShaders() {
}

@ApiStatus.Internal
public static void init() {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package dev.engine_room.flywheel.lib.material;

import dev.engine_room.flywheel.api.material.LightShader;
import net.minecraft.resources.ResourceLocation;

public record SimpleLightShader(@Override ResourceLocation source) implements LightShader {
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import dev.engine_room.flywheel.api.material.CutoutShader;
import dev.engine_room.flywheel.api.material.DepthTest;
import dev.engine_room.flywheel.api.material.FogShader;
import dev.engine_room.flywheel.api.material.LightShader;
import dev.engine_room.flywheel.api.material.Material;
import dev.engine_room.flywheel.api.material.MaterialShaders;
import dev.engine_room.flywheel.api.material.Transparency;
Expand All @@ -14,6 +15,7 @@ public class SimpleMaterial implements Material {
protected final MaterialShaders shaders;
protected final FogShader fog;
protected final CutoutShader cutout;
protected final LightShader light;

protected final ResourceLocation texture;
protected final boolean blur;
Expand All @@ -33,6 +35,7 @@ protected SimpleMaterial(Builder builder) {
shaders = builder.shaders();
fog = builder.fog();
cutout = builder.cutout();
light = builder.light();
texture = builder.texture();
blur = builder.blur();
mipmap = builder.mipmap();
Expand Down Expand Up @@ -69,6 +72,11 @@ public CutoutShader cutout() {
return cutout;
}

@Override
public LightShader light() {
return light;
}

@Override
public ResourceLocation texture() {
return texture;
Expand Down Expand Up @@ -128,6 +136,7 @@ public static class Builder implements Material {
protected MaterialShaders shaders;
protected FogShader fog;
protected CutoutShader cutout;
protected LightShader light;

protected ResourceLocation texture;
protected boolean blur;
Expand All @@ -147,6 +156,7 @@ public Builder() {
shaders = StandardMaterialShaders.DEFAULT;
fog = FogShaders.LINEAR;
cutout = CutoutShaders.OFF;
light = LightShaders.SMOOTH_WHEN_EMBEDDED;
texture = InventoryMenu.BLOCK_ATLAS;
blur = false;
mipmap = true;
Expand Down Expand Up @@ -197,6 +207,11 @@ public Builder cutout(CutoutShader value) {
return this;
}

public Builder light(LightShader value) {
this.light = value;
return this;
}

public Builder texture(ResourceLocation value) {
this.texture = value;
return this;
Expand Down Expand Up @@ -267,6 +282,11 @@ public CutoutShader cutout() {
return cutout;
}

@Override
public LightShader light() {
return light;
}

@Override
public ResourceLocation texture() {
return texture;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
void flw_shaderLight() {
vec2 embeddedLight;
if (flw_lightFetch(ivec3(floor(flw_vertexPos.xyz)), embeddedLight)) {
flw_fragLight = max(flw_fragLight, embeddedLight);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
void flw_shaderLight() {
vec2 embeddedLight;
if (flw_light(flw_vertexPos.xyz, flw_vertexNormal, embeddedLight)) {
flw_fragLight = max(flw_fragLight, embeddedLight);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
void flw_shaderLight() {
#ifdef FLW_EMBEDDED
vec2 embeddedLight;
if (flw_light(flw_vertexPos.xyz, flw_vertexNormal, embeddedLight)) {
flw_fragLight = max(flw_fragLight, embeddedLight);
}
#endif
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,2 @@
void flw_materialFragment() {
#ifdef FLW_EMBEDDED
vec2 embeddedLight;
if (flw_light(flw_vertexPos.xyz, flw_vertexNormal, embeddedLight)) {
flw_fragLight = max(flw_fragLight, embeddedLight);
}
#endif
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import dev.engine_room.flywheel.lib.instance.InstanceTypes;
import dev.engine_room.flywheel.lib.material.CutoutShaders;
import dev.engine_room.flywheel.lib.material.FogShaders;
import dev.engine_room.flywheel.lib.material.LightShaders;
import dev.engine_room.flywheel.lib.material.StandardMaterialShaders;
import dev.engine_room.flywheel.lib.util.ShadersModHandler;
import dev.engine_room.flywheel.vanilla.VanillaVisuals;
Expand All @@ -30,6 +31,7 @@ public static void init() {
InstanceTypes.init();
CutoutShaders.init();
FogShaders.init();
LightShaders.init();
StandardMaterialShaders.init();

// backend
Expand Down

0 comments on commit 69411fb

Please sign in to comment.