Skip to content

Commit

Permalink
Add support for vertex alphas
Browse files Browse the repository at this point in the history
  • Loading branch information
IMS212 committed Aug 15, 2024
1 parent 4ef46b7 commit a86df1d
Show file tree
Hide file tree
Showing 13 changed files with 88 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap;
import it.unimi.dsi.fastutil.objects.ReferenceSet;
import net.caffeinemc.mods.sodium.client.model.color.interop.BlockColorsExtension;
import net.caffeinemc.mods.sodium.client.services.FluidRendererFactory;
import net.minecraft.client.color.block.BlockColors;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
Expand Down Expand Up @@ -42,10 +43,10 @@ private void installOverrides() {
Blocks.OAK_LEAVES, Blocks.JUNGLE_LEAVES, Blocks.ACACIA_LEAVES,
Blocks.DARK_OAK_LEAVES, Blocks.VINE, Blocks.MANGROVE_LEAVES);

this.registerBlocks(DefaultColorProviders.WaterColorProvider.BLOCKS,
this.registerBlocks(FluidRendererFactory.getInstance().getWaterBlockColorProvider(),
Blocks.WATER, Blocks.BUBBLE_COLUMN);

this.registerFluids(DefaultColorProviders.WaterColorProvider.FLUIDS,
this.registerFluids(FluidRendererFactory.getInstance().getWaterColorProvider(),
Fluids.WATER, Fluids.FLOWING_WATER);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ private GrassColorProvider() {
}

@Override
protected int getColor(LevelSlice slice, BlockPos pos) {
protected int getColor(LevelSlice slice, T state, BlockPos pos) {
return BiomeColors.getAverageGrassColor(slice, pos);
}
}
Expand All @@ -36,7 +36,7 @@ private FoliageColorProvider() {
}

@Override
protected int getColor(LevelSlice slice, BlockPos pos) {
protected int getColor(LevelSlice slice, T state, BlockPos pos) {
return BiomeColors.getAverageFoliageColor(slice, pos);
}
}
Expand All @@ -50,7 +50,7 @@ private WaterColorProvider() {
}

@Override
protected int getColor(LevelSlice slice, BlockPos pos) {
protected int getColor(LevelSlice slice, T state, BlockPos pos) {
return BiomeColors.getAverageWaterColor(slice, pos);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ public abstract class BlendedColorProvider<T> implements ColorProvider<T> {
@Override
public void getColors(LevelSlice slice, BlockPos pos, BlockPos.MutableBlockPos scratchPos, T state, ModelQuadView quad, int[] output) {
for (int vertexIndex = 0; vertexIndex < 4; vertexIndex++) {
output[vertexIndex] = this.getVertexColor(slice, pos, scratchPos, quad, vertexIndex);
output[vertexIndex] = this.getVertexColor(slice, pos, scratchPos, quad, state, vertexIndex);
}
}

private int getVertexColor(LevelSlice slice, BlockPos pos, BlockPos.MutableBlockPos scratchPos, ModelQuadView quad, int vertexIndex) {
private int getVertexColor(LevelSlice slice, BlockPos pos, BlockPos.MutableBlockPos scratchPos, ModelQuadView quad, T state, int vertexIndex) {
// Offset the position by -0.5f to align smooth blending with flat blending.
final float posX = quad.getX(vertexIndex) - 0.5f;
final float posY = quad.getY(vertexIndex) - 0.5f;
Expand All @@ -35,10 +35,10 @@ private int getVertexColor(LevelSlice slice, BlockPos pos, BlockPos.MutableBlock
final int blockIntZ = pos.getZ() + posIntZ;

// Retrieve the color values for each neighboring block
final int c00 = this.getColor(slice, scratchPos.set(blockIntX + 0, blockIntY, blockIntZ + 0));
final int c01 = this.getColor(slice, scratchPos.set(blockIntX + 0, blockIntY, blockIntZ + 1));
final int c10 = this.getColor(slice, scratchPos.set(blockIntX + 1, blockIntY, blockIntZ + 0));
final int c11 = this.getColor(slice, scratchPos.set(blockIntX + 1, blockIntY, blockIntZ + 1));
final int c00 = this.getColor(slice, state, scratchPos.set(blockIntX + 0, blockIntY, blockIntZ + 0));
final int c01 = this.getColor(slice, state, scratchPos.set(blockIntX + 0, blockIntY, blockIntZ + 1));
final int c10 = this.getColor(slice, state, scratchPos.set(blockIntX + 1, blockIntY, blockIntZ + 0));
final int c11 = this.getColor(slice, state, scratchPos.set(blockIntX + 1, blockIntY, blockIntZ + 1));

// Linear interpolation across the Z-axis
int z0;
Expand Down Expand Up @@ -69,5 +69,5 @@ private int getVertexColor(LevelSlice slice, BlockPos pos, BlockPos.MutableBlock
return x0;
}

protected abstract int getColor(LevelSlice slice, BlockPos pos);
protected abstract int getColor(LevelSlice slice, T state, BlockPos pos);
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public void setData(Material material, TranslucentGeometryCollector collector) {
vertex.x = x;
vertex.y = y;
vertex.z = z;
vertex.ao = 1.0f;
this.writtenAttributes |= ATTRIBUTE_POSITION_BIT;
return potentiallyEndVertex();
}
Expand All @@ -51,23 +52,23 @@ public void setData(Material material, TranslucentGeometryCollector collector) {
@Override
public @NotNull VertexConsumer setColor(int red, int green, int blue, int alpha) {
ChunkVertexEncoder.Vertex vertex = this.vertices[this.vertexIndex];
vertex.color = ColorABGR.pack(red, green, blue, 0xFF);
vertex.color = ColorABGR.pack(red, green, blue, alpha);
this.writtenAttributes |= ATTRIBUTE_COLOR_BIT;
return potentiallyEndVertex();
}

@Override
public @NotNull VertexConsumer setColor(float red, float green, float blue, float alpha) {
ChunkVertexEncoder.Vertex vertex = this.vertices[this.vertexIndex];
vertex.color = ColorABGR.pack(red, green, blue, 1);
vertex.color = ColorABGR.pack(red, green, blue, alpha);
this.writtenAttributes |= ATTRIBUTE_COLOR_BIT;
return potentiallyEndVertex();
}

@Override
public @NotNull VertexConsumer setColor(int argb) {
ChunkVertexEncoder.Vertex vertex = this.vertices[this.vertexIndex];
vertex.color = ColorARGB.toABGR(argb, 0xFF);
vertex.color = ColorARGB.toABGR(argb);
this.writtenAttributes |= ATTRIBUTE_COLOR_BIT;
return potentiallyEndVertex();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,7 @@ private void colorizeQuad(MutableQuadViewImpl quad, int colorIndex) {
colorProvider.getColors(this.slice, this.pos, this.scratchPos, this.state, quad, vertexColors);

for (int i = 0; i < 4; i++) {
// Set alpha to 0xFF in case a quad transform inspects the color.
// We do not support per-vertex alpha, however, so this will get discarded at vertex encoding time.
quad.color(i, ColorHelper.multiplyColor(0xFF000000 | vertexColors[i], quad.color(i)));
quad.color(i, ColorHelper.multiplyColor(vertexColors[i], quad.color(i)));
}
}
}
Expand All @@ -166,9 +164,8 @@ private void bufferQuad(MutableQuadViewImpl quad, float[] brightnesses, Material
out.z = quad.z(srcIndex) + offset.z;

// FRAPI uses ARGB color format; convert to ABGR.
// Due to our vertex format, the alpha from the quad color is ignored entirely.
out.color = ColorARGB.toABGR(quad.color(srcIndex), brightnesses[srcIndex]);

out.color = ColorARGB.toABGR(quad.color(srcIndex));
out.ao = brightnesses[srcIndex];
out.u = quad.u(srcIndex);
out.v = quad.v(srcIndex);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public class DefaultFluidRenderer {

private final QuadLightData quadLightData = new QuadLightData();
private final int[] quadColors = new int[4];
private final float[] brightness = new float[4];

private final ChunkVertexEncoder.Vertex[] vertices = ChunkVertexEncoder.Vertex.uninitializedQuad();
private final ColorProviderRegistry colorProviderRegistry;
Expand Down Expand Up @@ -385,7 +386,8 @@ private void updateQuad(ModelQuadViewMutable quad, LevelSlice level, BlockPos po
// multiply the per-vertex color against the combined brightness
// the combined brightness is the per-vertex brightness multiplied by the block's brightness
for (int i = 0; i < 4; i++) {
this.quadColors[i] = ColorARGB.toABGR(this.quadColors[i], light.br[i] * brightness);
this.quadColors[i] = ColorARGB.toABGR(this.quadColors[i]);
this.brightness[i] = light.br[i] * brightness;
}
}

Expand All @@ -400,6 +402,7 @@ private void writeQuad(ChunkModelBuilder builder, TranslucentGeometryCollector c
out.z = offset.getZ() + quad.getZ(i);

out.color = this.quadColors[i];
out.ao = this.brightness[i];
out.u = quad.getTexU(i);
out.v = quad.getTexV(i);
out.light = this.quadLightData.lm[i];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class Vertex {
public float y;
public float z;
public int color;
public float ao;
public float u;
public float v;
public int light;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import net.caffeinemc.mods.sodium.client.render.chunk.vertex.format.ChunkMeshAttribute;
import net.caffeinemc.mods.sodium.client.render.chunk.vertex.format.ChunkVertexEncoder;
import net.caffeinemc.mods.sodium.client.render.chunk.vertex.format.ChunkVertexType;
import net.caffeinemc.mods.sodium.client.render.frapi.helper.ColorHelper;
import net.minecraft.util.Mth;
import org.lwjgl.system.MemoryUtil;

Expand Down Expand Up @@ -59,7 +60,7 @@ public ChunkVertexEncoder getEncoder() {

MemoryUtil.memPutInt(ptr + 0L, packPositionHi(x, y, z));
MemoryUtil.memPutInt(ptr + 4L, packPositionLo(x, y, z));
MemoryUtil.memPutInt(ptr + 8L, vertex.color);
MemoryUtil.memPutInt(ptr + 8L, ColorHelper.multiplyRGB(vertex.color, vertex.ao));
MemoryUtil.memPutInt(ptr + 12L, packTexture(u, v));
MemoryUtil.memPutInt(ptr + 16L, packLightAndData(light, material.bits(), section));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ protected void processQuad(MutableQuadViewImpl quad) {

private void colorizeQuad(MutableQuadViewImpl quad, int colorIndex) {
if (colorIndex != -1) {
final int blockColor = 0xFF000000 | this.colorMap.getColor(this.state, this.level, this.pos, colorIndex);
final int blockColor = this.colorMap.getColor(this.state, this.level, this.pos, colorIndex);

for (int i = 0; i < 4; i++) {
quad.color(i, ColorHelper.multiplyColor(blockColor, quad.color(i)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

import net.caffeinemc.mods.sodium.client.model.color.ColorProviderRegistry;
import net.caffeinemc.mods.sodium.client.model.light.LightPipelineProvider;
import net.caffeinemc.mods.sodium.client.model.quad.blender.BlendedColorProvider;
import net.caffeinemc.mods.sodium.client.render.chunk.compile.pipeline.FluidRenderer;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.FluidState;

public interface FluidRendererFactory {
FluidRendererFactory INSTANCE = Services.load(FluidRendererFactory.class);
Expand All @@ -18,4 +21,8 @@ static FluidRendererFactory getInstance() {
* @return A new fluid renderer.
*/
FluidRenderer createPlatformFluidRenderer(ColorProviderRegistry colorRegistry, LightPipelineProvider lightPipelineProvider);

BlendedColorProvider<FluidState> getWaterColorProvider();

BlendedColorProvider<BlockState> getWaterBlockColorProvider();
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,14 @@ out vec4 fragColor; // The output fragment for the color framebuffer
void main() {
vec4 diffuseColor = texture(u_BlockTex, v_TexCoord, v_MaterialMipBias);

// Apply per-vertex color
diffuseColor *= v_Color;

#ifdef USE_FRAGMENT_DISCARD
if (diffuseColor.a < v_MaterialAlphaCutoff) {
discard;
}
#endif

// Apply per-vertex color
diffuseColor.rgb *= v_Color.rgb;

// Apply ambient occlusion "shade"
diffuseColor.rgb *= v_Color.a;

fragColor = _linearFog(diffuseColor, v_FragDistance, u_FogColor, u_FogStart, u_FogEnd);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import net.caffeinemc.mods.sodium.client.model.color.ColorProvider;
import net.caffeinemc.mods.sodium.client.model.color.ColorProviderRegistry;
import net.caffeinemc.mods.sodium.client.model.light.LightPipelineProvider;
import net.caffeinemc.mods.sodium.client.model.quad.blender.BlendedColorProvider;
import net.caffeinemc.mods.sodium.client.render.chunk.compile.ChunkBuildBuffers;
import net.caffeinemc.mods.sodium.client.render.chunk.compile.buffers.ChunkModelBuilder;
import net.caffeinemc.mods.sodium.client.render.chunk.compile.pipeline.DefaultFluidRenderer;
Expand All @@ -16,6 +17,7 @@
import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandler;
import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandlerRegistry;
import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRendering;
import net.minecraft.client.renderer.BiomeColors;
import net.minecraft.core.BlockPos;
import net.minecraft.tags.FluidTags;
import net.minecraft.world.level.BlockAndTintGetter;
Expand Down Expand Up @@ -140,5 +142,25 @@ public static class FabricFactory implements FluidRendererFactory {
public FluidRenderer createPlatformFluidRenderer(ColorProviderRegistry colorRegistry, LightPipelineProvider lightPipelineProvider) {
return new FluidRendererImpl(colorRegistry, lightPipelineProvider);
}

@Override
public BlendedColorProvider<FluidState> getWaterColorProvider() {
return new BlendedColorProvider<>() {
@Override
protected int getColor(LevelSlice slice, FluidState state, BlockPos pos) {
return BiomeColors.getAverageWaterColor(slice, pos) | 0xFF000000;
}
};
}

@Override
public BlendedColorProvider<BlockState> getWaterBlockColorProvider() {
return new BlendedColorProvider<>() {
@Override
protected int getColor(LevelSlice slice, BlockState state, BlockPos pos) {
return BiomeColors.getAverageWaterColor(slice, pos) | 0xFF000000;
}
};
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import net.caffeinemc.mods.sodium.client.model.color.ColorProvider;
import net.caffeinemc.mods.sodium.client.model.color.ColorProviderRegistry;
import net.caffeinemc.mods.sodium.client.model.light.LightPipelineProvider;
import net.caffeinemc.mods.sodium.client.model.quad.blender.BlendedColorProvider;
import net.caffeinemc.mods.sodium.client.render.chunk.compile.ChunkBuildBuffers;
import net.caffeinemc.mods.sodium.client.render.chunk.compile.buffers.ChunkModelBuilder;
import net.caffeinemc.mods.sodium.client.render.chunk.compile.pipeline.DefaultFluidRenderer;
Expand All @@ -16,9 +17,12 @@
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluids;
import net.neoforged.neoforge.client.extensions.common.IClientFluidTypeExtensions;
import net.neoforged.neoforge.client.textures.FluidSpriteCache;

import java.util.Objects;

public class FluidRendererImpl extends FluidRenderer {
// The current default context is set up before invoking FluidRenderHandler#renderFluid and cleared afterwards.
private static final ThreadLocal<DefaultRenderContext> CURRENT_DEFAULT_CONTEXT = ThreadLocal.withInitial(DefaultRenderContext::new);
Expand Down Expand Up @@ -128,5 +132,29 @@ public static class ForgeFactory implements FluidRendererFactory {
public FluidRenderer createPlatformFluidRenderer(ColorProviderRegistry colorRegistry, LightPipelineProvider lightPipelineProvider) {
return new FluidRendererImpl(colorRegistry, lightPipelineProvider);
}

@Override
public BlendedColorProvider<FluidState> getWaterColorProvider() {
final IClientFluidTypeExtensions ext = IClientFluidTypeExtensions.of(Fluids.WATER);

return new BlendedColorProvider<>() {
@Override
protected int getColor(LevelSlice slice, FluidState state, BlockPos pos) {
return ext.getTintColor(state, slice, pos);
}
};
}

@Override
public BlendedColorProvider<BlockState> getWaterBlockColorProvider() {
final IClientFluidTypeExtensions ext = IClientFluidTypeExtensions.of(Fluids.WATER);

return new BlendedColorProvider<>() {
@Override
protected int getColor(LevelSlice slice, BlockState state, BlockPos pos) {
return ext.getTintColor(state.getFluidState().isEmpty() ? Fluids.WATER.defaultFluidState() : state.getFluidState(), slice, pos);
}
};
}
}
}

0 comments on commit a86df1d

Please sign in to comment.