Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Downgrade quad materials by scanning their textures #2666

Merged
merged 14 commits into from
Aug 25, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import net.caffeinemc.mods.sodium.client.model.quad.properties.ModelQuadOrientation;
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.terrain.DefaultTerrainRenderPasses;
import net.caffeinemc.mods.sodium.client.render.chunk.terrain.material.DefaultMaterials;
import net.caffeinemc.mods.sodium.client.render.chunk.terrain.material.Material;
import net.caffeinemc.mods.sodium.client.render.chunk.translucent_sorting.TranslucentGeometryCollector;
Expand All @@ -28,6 +29,7 @@
import net.fabricmc.fabric.api.util.TriState;
import net.minecraft.client.renderer.ItemBlockRenderTypes;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.state.BlockState;
Expand Down Expand Up @@ -128,11 +130,9 @@ protected void processQuad(MutableQuadViewImpl quad) {
material = DefaultMaterials.forRenderLayer(blendMode.blockRenderLayer == null ? type : blendMode.blockRenderLayer);
}

ChunkModelBuilder builder = this.buffers.get(material);

this.colorizeQuad(quad, colorIndex);
this.shadeQuad(quad, lightMode, emissive, shadeMode);
this.bufferQuad(quad, this.quadLightData.br, material, builder);
this.bufferQuad(quad, this.quadLightData.br, material);
}

private void colorizeQuad(MutableQuadViewImpl quad, int colorIndex) {
Expand All @@ -152,7 +152,7 @@ private void colorizeQuad(MutableQuadViewImpl quad, int colorIndex) {
}
}

private void bufferQuad(MutableQuadViewImpl quad, float[] brightnesses, Material material, ChunkModelBuilder modelBuilder) {
private void bufferQuad(MutableQuadViewImpl quad, float[] brightnesses, Material material) {
ModelQuadOrientation orientation = defaultLightMode == LightMode.FLAT ? ModelQuadOrientation.NORMAL : ModelQuadOrientation.orientByBrightness(brightnesses, quad);
ChunkVertexEncoder.Vertex[] vertices = this.vertices;
Vector3f offset = this.posOffset;
Expand All @@ -175,15 +175,31 @@ private void bufferQuad(MutableQuadViewImpl quad, float[] brightnesses, Material
out.light = quad.lightmap(srcIndex);
}

var atlasSprite = SpriteFinderCache.forBlockAtlas().find(quad.getTexU(0), quad.getTexV(0));
material = getDowngradedMaterial(atlasSprite, material);

ModelQuadFacing normalFace = quad.normalFace();

if (material.isTranslucent() && this.collector != null) {
this.collector.appendQuad(quad.getFaceNormal(), vertices, normalFace);
}

ChunkMeshBufferBuilder vertexBuffer = modelBuilder.getVertexBuffer(normalFace);
ChunkModelBuilder builder = this.buffers.get(material);

ChunkMeshBufferBuilder vertexBuffer = builder.getVertexBuffer(normalFace);
vertexBuffer.push(vertices, material);

modelBuilder.addSprite(SpriteFinderCache.forBlockAtlas().find(quad.getTexU(0), quad.getTexV(0)));
builder.addSprite(atlasSprite);
}

private Material getDowngradedMaterial(TextureAtlasSprite sprite, Material material) {
douira marked this conversation as resolved.
Show resolved Hide resolved
var contents = (SpriteContentsExtension) (sprite.contents());
if (material.pass == DefaultTerrainRenderPasses.TRANSLUCENT && !contents.sodium$hasTranslucentPixels()) {
douira marked this conversation as resolved.
Show resolved Hide resolved
material = DefaultMaterials.CUTOUT_MIPPED;
}
if (material.pass == DefaultTerrainRenderPasses.CUTOUT && !contents.sodium$hasTransparentPixels()) {
material = DefaultMaterials.SOLID;
}
return material;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package net.caffeinemc.mods.sodium.client.render.chunk.compile.pipeline;

public interface SpriteContentsExtension {
boolean sodium$hasTransparentPixels();

boolean sodium$hasTranslucentPixels();
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package net.caffeinemc.mods.sodium.mixin.features.textures.mipmaps;

import com.mojang.blaze3d.platform.NativeImage;
import net.caffeinemc.mods.sodium.client.render.chunk.compile.pipeline.SpriteContentsExtension;
import net.caffeinemc.mods.sodium.client.util.NativeImageHelper;
import net.caffeinemc.mods.sodium.client.util.color.ColorSRGB;
import net.minecraft.client.renderer.texture.SpriteContents;
Expand All @@ -20,12 +21,18 @@
* This Mixin is ported from Iris at <a href="https://github.com/IrisShaders/Iris/blob/41095ac23ea0add664afd1b85c414d1f1ed94066/src/main/java/net/coderbot/iris/mixin/bettermipmaps/MixinTextureAtlasSprite.java">MixinTextureAtlasSprite</a>.
*/
@Mixin(SpriteContents.class)
public class SpriteContentsMixin {
public class SpriteContentsMixin implements SpriteContentsExtension {
@Mutable
@Shadow
@Final
private NativeImage originalImage;

@Unique
public boolean sodium$hasTransparentPixels = false;

@Unique
public boolean sodium$hasTranslucentPixels = false;

// While Fabric allows us to @Inject into the constructor here, that's just a specific detail of FabricMC's mixin
// fork. Upstream Mixin doesn't allow arbitrary @Inject usage in constructor. However, we can use @ModifyVariable
// just fine, in a way that hopefully doesn't conflict with other mods.
Expand All @@ -51,7 +58,7 @@ public class SpriteContentsMixin {
* black color does not leak over into sampling.
*/
@Unique
private static void sodium$fillInTransparentPixelColors(NativeImage nativeImage) {
private void sodium$fillInTransparentPixelColors(NativeImage nativeImage) {
douira marked this conversation as resolved.
Show resolved Hide resolved
final long ppPixel = NativeImageHelper.getPointerRGBA(nativeImage);
final int pixelCount = nativeImage.getHeight() * nativeImage.getWidth();

Expand Down Expand Up @@ -79,9 +86,18 @@ public class SpriteContentsMixin {
b += ColorSRGB.srgbToLinear(FastColor.ABGR32.blue(color)) * weight;

totalWeight += weight;

// track if this image has transparent or even translucent pixels
if (alpha < 255) {
this.sodium$hasTranslucentPixels = true;
}
} else {
this.sodium$hasTransparentPixels = true;
}
}

this.sodium$hasTransparentPixels |= this.sodium$hasTranslucentPixels;

// Bail if none of the pixels are semi-transparent.
if (totalWeight == 0.0f) {
return;
Expand All @@ -107,4 +123,14 @@ public class SpriteContentsMixin {
}
}
}

@Override
public boolean sodium$hasTransparentPixels() {
return this.sodium$hasTransparentPixels;
}

@Override
public boolean sodium$hasTranslucentPixels() {
return this.sodium$hasTranslucentPixels;
}
}
Loading