Merge remote-tracking branch 'origin/1.16' into 1.16

This commit is contained in:
modmuss50 2020-05-29 20:12:35 +01:00
commit 4a01746c06
9 changed files with 89 additions and 140 deletions
fabric-renderer-indigo/src/main/java/net/fabricmc/fabric/impl/client/indigo/renderer
fabric-rendering-v1
build.gradle
src/main/java/net/fabricmc/fabric/mixin/client/rendering

View file

@ -20,12 +20,6 @@ import java.nio.ByteOrder;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
import net.minecraft.client.render.model.BakedQuadFactory;
import net.minecraft.client.util.math.Vector3f;
import net.minecraft.util.math.Direction;
import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
/**
* Static routines of general utility for renderer implementations.
* Renderers are not required to use these helpers, but they were
@ -34,19 +28,6 @@ import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
public abstract class ColorHelper {
private ColorHelper() { }
/**
* Implement on quads to use methods that require it.
* Allows for much cleaner method signatures.
*/
public interface ShadeableQuad extends MutableQuadView {
boolean isFaceAligned();
boolean needsDiffuseShading(int textureIndex);
}
/** Same as vanilla values. */
private static final float[] FACE_SHADE_FACTORS = { 0.5F, 1.0F, 0.8F, 0.8F, 0.6F, 0.6F };
private static final Int2IntFunction colorSwapper = ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN ? color -> ((color & 0xFF00FF00) | ((color & 0x00FF0000) >> 16) | ((color & 0xFF) << 16)) : color -> color;
/**
@ -64,109 +45,24 @@ public abstract class ColorHelper {
return color1;
}
int alpha = ((color1 >> 24) & 0xFF) * ((color2 >> 24) & 0xFF) / 0xFF;
int red = ((color1 >> 16) & 0xFF) * ((color2 >> 16) & 0xFF) / 0xFF;
int green = ((color1 >> 8) & 0xFF) * ((color2 >> 8) & 0xFF) / 0xFF;
int blue = (color1 & 0xFF) * (color2 & 0xFF) / 0xFF;
final int alpha = ((color1 >> 24) & 0xFF) * ((color2 >> 24) & 0xFF) / 0xFF;
final int red = ((color1 >> 16) & 0xFF) * ((color2 >> 16) & 0xFF) / 0xFF;
final int green = ((color1 >> 8) & 0xFF) * ((color2 >> 8) & 0xFF) / 0xFF;
final int blue = (color1 & 0xFF) * (color2 & 0xFF) / 0xFF;
return (alpha << 24) | (red << 16) | (green << 8) | blue;
}
/** Multiplies three lowest components by shade. High byte (usually alpha) unchanged. */
public static int multiplyRGB(int color, float shade) {
int alpha = ((color >> 24) & 0xFF);
int red = (int) (((color >> 16) & 0xFF) * shade);
int green = (int) (((color >> 8) & 0xFF) * shade);
int blue = (int) ((color & 0xFF) * shade);
final int alpha = ((color >> 24) & 0xFF);
final int red = (int) (((color >> 16) & 0xFF) * shade);
final int green = (int) (((color >> 8) & 0xFF) * shade);
final int blue = (int) ((color & 0xFF) * shade);
return (alpha << 24) | (red << 16) | (green << 8) | blue;
}
/**
* Same results as {@link BakedQuadFactory#method_3456(Direction)}.
*/
public static float diffuseShade(Direction direction) {
return FACE_SHADE_FACTORS[direction.getId()];
}
/**
* Formula mimics vanilla lighting for plane-aligned quads and
* is vaguely consistent with Phong lighting ambient + diffuse for others.
*/
public static float normalShade(float normalX, float normalY, float normalZ) {
return Math.min(0.5f + Math.abs(normalX) * 0.1f + (normalY > 0 ? 0.5f * normalY : 0) + Math.abs(normalZ) * 0.3f, 1f);
}
public static float normalShade(Vector3f normal) {
return normalShade(normal.getX(), normal.getY(), normal.getZ());
}
/**
* @see #diffuseShade
*/
public static float vertexShade(ShadeableQuad q, int vertexIndex, float faceShade) {
return q.hasNormal(vertexIndex) ? normalShade(q.normalX(vertexIndex), q.normalY(vertexIndex), q.normalZ(vertexIndex)) : faceShade;
}
/**
* Returns {@link #diffuseShade(Direction)} if quad is aligned to light face,
* otherwise uses face normal and {@link #normalShade}.
*/
public static float faceShade(ShadeableQuad quad) {
return quad.isFaceAligned() ? diffuseShade(quad.lightFace()) : normalShade(quad.faceNormal());
}
@FunctionalInterface
private interface VertexLighter {
void shade(ShadeableQuad quad, int vertexIndex, float shade);
}
private static VertexLighter[] VERTEX_LIGHTERS = new VertexLighter[8];
static {
VERTEX_LIGHTERS[0b000] = (q, i, s) -> { };
VERTEX_LIGHTERS[0b001] = (q, i, s) -> q.spriteColor(i, 0, multiplyRGB(q.spriteColor(i, 0), s));
VERTEX_LIGHTERS[0b010] = (q, i, s) -> q.spriteColor(i, 1, multiplyRGB(q.spriteColor(i, 1), s));
VERTEX_LIGHTERS[0b011] = (q, i, s) -> q.spriteColor(i, 0, multiplyRGB(q.spriteColor(i, 0), s)).spriteColor(i, 1, multiplyRGB(q.spriteColor(i, 1), s));
VERTEX_LIGHTERS[0b100] = (q, i, s) -> q.spriteColor(i, 2, multiplyRGB(q.spriteColor(i, 2), s));
VERTEX_LIGHTERS[0b101] = (q, i, s) -> q.spriteColor(i, 0, multiplyRGB(q.spriteColor(i, 0), s)).spriteColor(i, 2, multiplyRGB(q.spriteColor(i, 2), s));
VERTEX_LIGHTERS[0b110] = (q, i, s) -> q.spriteColor(i, 1, multiplyRGB(q.spriteColor(i, 1), s)).spriteColor(i, 2, multiplyRGB(q.spriteColor(i, 2), s));
VERTEX_LIGHTERS[0b111] = (q, i, s) -> q.spriteColor(i, 0, multiplyRGB(q.spriteColor(i, 0), s)).spriteColor(i, 1, multiplyRGB(q.spriteColor(i, 1), s)).spriteColor(i, 2, multiplyRGB(q.spriteColor(i, 2), s));
}
/**
* Honors vertex normals and uses non-cubic face normals for non-cubic quads.
*
* @param quad Quad to be shaded/unshaded.
*
* @param undo If true, will reverse prior application. Does not check that
* prior application actually happened. Use to "unbake" a quad.
* Some drift of colors may occur due to floating-point precision error.
*/
public static void applyDiffuseShading(ShadeableQuad quad, boolean undo) {
final float faceShade = faceShade(quad);
int i = quad.needsDiffuseShading(0) ? 1 : 0;
if (quad.needsDiffuseShading(1)) {
i |= 2;
}
if (quad.needsDiffuseShading(2)) {
i |= 4;
}
if (i == 0) {
return;
}
final VertexLighter shader = VERTEX_LIGHTERS[i];
for (int j = 0; j < 4; j++) {
final float vertexShade = vertexShade(quad, j, faceShade);
shader.shade(quad, j, undo ? 1f / vertexShade : vertexShade);
}
}
/**
* Component-wise max.
*/

View file

@ -19,7 +19,6 @@ package net.fabricmc.fabric.impl.client.indigo.renderer.mesh;
import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh;
import net.fabricmc.fabric.api.renderer.v1.mesh.MeshBuilder;
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter;
import net.fabricmc.fabric.impl.client.indigo.renderer.helper.ColorHelper;
import net.fabricmc.fabric.impl.client.indigo.renderer.helper.GeometryHelper;
/**
@ -38,7 +37,7 @@ public class MeshBuilderImpl implements MeshBuilder {
protected void ensureCapacity(int stride) {
if (stride > limit - index) {
limit *= 2;
int[] bigger = new int[limit];
final int[] bigger = new int[limit];
System.arraycopy(data, 0, bigger, 0, index);
data = bigger;
maker.data = bigger;
@ -47,7 +46,7 @@ public class MeshBuilderImpl implements MeshBuilder {
@Override
public Mesh build() {
int[] packed = new int[index];
final int[] packed = new int[index];
System.arraycopy(data, 0, packed, 0, index);
index = 0;
maker.begin(data, index);
@ -76,7 +75,6 @@ public class MeshBuilderImpl implements MeshBuilder {
geometryFlags(GeometryHelper.computeShapeFlags(this));
}
ColorHelper.applyDiffuseShading(this, false);
index += EncodingFormat.TOTAL_STRIDE;
ensureCapacity(EncodingFormat.TOTAL_STRIDE);
baseIndex = index;

View file

@ -38,16 +38,14 @@ import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial;
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter;
import net.fabricmc.fabric.impl.client.indigo.renderer.IndigoRenderer;
import net.fabricmc.fabric.impl.client.indigo.renderer.RenderMaterialImpl.Value;
import net.fabricmc.fabric.impl.client.indigo.renderer.helper.GeometryHelper;
import net.fabricmc.fabric.impl.client.indigo.renderer.helper.NormalHelper;
import net.fabricmc.fabric.impl.client.indigo.renderer.helper.TextureHelper;
import net.fabricmc.fabric.impl.client.indigo.renderer.helper.ColorHelper.ShadeableQuad;
/**
* Almost-concrete implementation of a mutable quad. The only missing part is {@link #emit()},
* because that depends on where/how it is used. (Mesh encoding vs. render-time transformation).
*/
public abstract class MutableQuadViewImpl extends QuadViewImpl implements QuadEmitter, ShadeableQuad {
public abstract class MutableQuadViewImpl extends QuadViewImpl implements QuadEmitter {
public final void begin(int[] data, int baseIndex) {
this.data = data;
this.baseIndex = baseIndex;
@ -115,16 +113,6 @@ public abstract class MutableQuadViewImpl extends QuadViewImpl implements QuadEm
return this;
}
@Override
public boolean isFaceAligned() {
return (geometryFlags() & GeometryHelper.AXIS_ALIGNED_FLAG) != 0;
}
@Override
public boolean needsDiffuseShading(int textureIndex) {
return textureIndex == 0 && !material().disableDiffuse(textureIndex);
}
@Override
public MutableQuadViewImpl pos(int vertexIndex, float x, float y, float z) {
final int index = baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_X;

View file

@ -170,7 +170,7 @@ public class QuadViewImpl implements QuadView {
@Override
public void copyTo(MutableQuadView target) {
MutableQuadViewImpl quad = (MutableQuadViewImpl) target;
final MutableQuadViewImpl quad = (MutableQuadViewImpl) target;
// copy everything except the header/material
System.arraycopy(data, baseIndex + 1, quad.data, quad.baseIndex + 1, EncodingFormat.TOTAL_STRIDE - 1);
quad.isFaceNormalInvalid = this.isFaceNormalInvalid;
@ -288,7 +288,7 @@ public class QuadViewImpl implements QuadView {
}
public boolean hasShade() {
return shade;
return shade && !material().disableDiffuse(0);
}
public void shade(boolean shade) {

View file

@ -29,7 +29,6 @@ import net.fabricmc.fabric.api.renderer.v1.render.RenderContext.QuadTransform;
import net.fabricmc.fabric.impl.client.indigo.renderer.IndigoRenderer;
import net.fabricmc.fabric.impl.client.indigo.renderer.RenderMaterialImpl;
import net.fabricmc.fabric.impl.client.indigo.renderer.aocalc.AoCalculator;
import net.fabricmc.fabric.impl.client.indigo.renderer.helper.ColorHelper;
import net.fabricmc.fabric.impl.client.indigo.renderer.helper.GeometryHelper;
import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.EncodingFormat;
import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.MeshImpl;
@ -58,7 +57,6 @@ public abstract class AbstractMeshConsumer extends AbstractQuadRenderer implemen
@Override
public Maker emit() {
lightFace(GeometryHelper.lightFace(this));
ColorHelper.applyDiffuseShading(this, false);
renderQuad(this);
clear();
return this;
@ -69,7 +67,7 @@ public abstract class AbstractMeshConsumer extends AbstractQuadRenderer implemen
@Override
public void accept(Mesh mesh) {
MeshImpl m = (MeshImpl) mesh;
final MeshImpl m = (MeshImpl) mesh;
final int[] data = m.data();
final int limit = data.length;
int index = 0;

View file

@ -25,14 +25,16 @@ import net.minecraft.block.BlockState;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.WorldRenderer;
import net.minecraft.util.math.Matrix4f;
import net.minecraft.client.util.math.Vector3f;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Matrix3f;
import net.minecraft.util.math.Matrix4f;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext.QuadTransform;
import net.fabricmc.fabric.impl.client.indigo.renderer.aocalc.AoCalculator;
import net.fabricmc.fabric.impl.client.indigo.renderer.helper.ColorHelper;
import net.fabricmc.fabric.impl.client.indigo.renderer.helper.GeometryHelper;
import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.MutableQuadViewImpl;
/**
@ -139,7 +141,9 @@ public abstract class AbstractQuadRenderer {
/** for non-emissive mesh quads and all fallback quads with flat lighting. */
protected void tesselateFlat(MutableQuadViewImpl quad, RenderLayer renderLayer, int blockColorIndex) {
colorizeQuad(quad, blockColorIndex);
final int brightness = ColorHelper.multiplyRGB(flatBrightness(quad, blockInfo.blockState, blockInfo.blockPos), blockInfo.blockView.getBrightness(quad.lightFace(), quad.hasShade()));
shadeFlatQuad(quad);
final int brightness = flatBrightness(quad, blockInfo.blockState, blockInfo.blockPos);
for (int i = 0; i < 4; i++) {
quad.lightmap(i, ColorHelper.maxBrightness(quad.lightmap(i), brightness));
@ -151,6 +155,7 @@ public abstract class AbstractQuadRenderer {
/** for emissive mesh quads with flat lighting. */
protected void tesselateFlatEmissive(MutableQuadViewImpl quad, RenderLayer renderLayer, int blockColorIndex) {
colorizeQuad(quad, blockColorIndex);
shadeFlatQuad(quad);
for (int i = 0; i < 4; i++) {
quad.lightmap(i, FULL_BRIGHTNESS);
@ -175,4 +180,68 @@ public abstract class AbstractQuadRenderer {
// Unfortunately cannot use brightness cache here unless we implement one specifically for flat lighting. See #329
return WorldRenderer.getLightmapCoordinates(blockInfo.blockView, blockState, mpos);
}
/**
* Starting in 1.16 flat shading uses dimension-specific diffuse factors that can be < 1.0
* even for un-shaded quads. These are also applied with AO shading but that is done in AO calculator.
*/
private void shadeFlatQuad(MutableQuadViewImpl quad) {
if ((quad.geometryFlags() & GeometryHelper.AXIS_ALIGNED_FLAG) == 0 || quad.hasVertexNormals()) {
// Quads that aren't direction-aligned or that have vertex normals need to be shaded
// using interpolation - vanilla can't handle them. Generally only applies to modded models.
final float faceShade = blockInfo.blockView.getBrightness(quad.lightFace(), quad.hasShade());
for (int i = 0; i < 4; i++) {
quad.spriteColor(i, 0, ColorHelper.multiplyRGB(quad.spriteColor(i, 0), vertexShade(quad, i, faceShade)));
}
} else {
final float diffuseShade = blockInfo.blockView.getBrightness(quad.lightFace(), quad.hasShade());
if (diffuseShade != 1.0f) {
for (int i = 0; i < 4; i++) {
quad.spriteColor(i, 0, ColorHelper.multiplyRGB(quad.spriteColor(i, 0), diffuseShade));
}
}
}
}
private float vertexShade(MutableQuadViewImpl quad, int vertexIndex, float faceShade) {
return quad.hasNormal(vertexIndex) ? normalShade(quad.normalX(vertexIndex), quad.normalY(vertexIndex), quad.normalZ(vertexIndex), quad.hasShade()) : faceShade;
}
/**
* Finds mean of per-face shading factors weighted by normal components.
* Not how light actually works but the vanilla diffuse shading model is a hack to start with
* and this gives reasonable results for non-cubic surfaces in a vanilla-style renderer.
*/
private float normalShade(float normalX, float normalY, float normalZ, boolean hasShade) {
float sum = 0;
float div = 0;
if (normalX > 0) {
sum += normalX * blockInfo.blockView.getBrightness(Direction.EAST, hasShade);
div += normalX;
} else if (normalX < 0) {
sum += -normalX * blockInfo.blockView.getBrightness(Direction.WEST, hasShade);
div -= normalX;
}
if (normalY > 0) {
sum += normalY * blockInfo.blockView.getBrightness(Direction.UP, hasShade);
div += normalY;
} else if (normalY < 0) {
sum += -normalY * blockInfo.blockView.getBrightness(Direction.DOWN, hasShade);
div -= normalY;
}
if (normalZ > 0) {
sum += normalZ * blockInfo.blockView.getBrightness(Direction.SOUTH, hasShade);
div += normalZ;
} else if (normalZ < 0) {
sum += -normalZ * blockInfo.blockView.getBrightness(Direction.NORTH, hasShade);
div -= normalZ;
}
return sum / div;
}
}

View file

@ -33,11 +33,11 @@ import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.render.model.json.ModelTransformation;
import net.minecraft.client.render.model.json.ModelTransformation.Mode;
import net.minecraft.util.math.Matrix4f;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.client.util.math.Vector3f;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Matrix4f;
import net.fabricmc.fabric.api.renderer.v1.material.BlendMode;
import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh;
@ -144,7 +144,6 @@ public class ItemRenderContext extends AbstractRenderContext implements RenderCo
@Override
public Maker emit() {
lightFace(GeometryHelper.lightFace(this));
ColorHelper.applyDiffuseShading(this, false);
renderQuad();
clear();
return this;

View file

@ -1,5 +1,5 @@
archivesBaseName = "fabric-rendering-v1"
version = getSubprojectVersion(project, "1.1.0")
version = getSubprojectVersion(project, "1.1.1")
dependencies {
compile project(path: ':fabric-api-base', configuration: 'dev')

View file

@ -19,6 +19,7 @@ package net.fabricmc.fabric.mixin.client.rendering;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Slice;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import net.minecraft.client.util.math.MatrixStack;
@ -28,7 +29,7 @@ import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback;
@Mixin(InGameHud.class)
public class MixinInGameHud {
@Inject(method = "render", at = @At(value = "RETURN", shift = At.Shift.BY, by = -6))
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/systems/RenderSystem;color4f(FFFF)V"), slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/PlayerListHud;render(Lnet/minecraft/client/util/math/MatrixStack;ILnet/minecraft/scoreboard/Scoreboard;Lnet/minecraft/scoreboard/ScoreboardObjective;)V")))
public void render(MatrixStack matrixStack, float tickDelta, CallbackInfo callbackInfo) {
HudRenderCallback.EVENT.invoker().onHudRender(matrixStack, tickDelta);
}