mojira.dev
MC-260099

Sniffer's snout shading changes during sniffing

The bug

During the sniffer's sniffing animation, its snout inflates. However, the shading of it also changes, creating a clear line in its geometry and breaking the illusion. The snout may appear brighter or darker depending on the direction the sniffer is facing.

Code analysis

Code analysis by @unknown can be found in this comment.

Linked issues

Attachments

Comments 3

I was able to create a Fabric mod that fixes this issue by changing Minecraft's code. Hopefully the way I resolved this issue and the following insights will be useful.

The issue was mostly fixed after the following change in com.mojang.blaze3d.vertex.PoseStack.

public void scale(float f, float g, float h) {
	PoseStack.Pose pose = (PoseStack.Pose)this.poseStack.getLast();
	pose.pose.scale(f, g, h);
	if (f == g && g == h) {
		if (f > 0.0F) {
			return;
		}

		pose.normal.scale(-1.0F);
	}

	float i = 1.0F / f;
	float j = 1.0F / g;
	float k = 1.0F / h;
	// Commented vanilla code
//	float l = Mth.fastInvCubeRoot(i * j * k);
//	pose.normal.scale(l * i, l * j, l * k);
	// New code
	pose.normal.scale(i, j, k);
}

However, after this change, the top of nose got darker the more the nose was scaled up. This is because Minecraft does not normalize the normal vector after it is transformed by the normal matrix. When the fragment shader uses the vertex normal vector to calculate lighting, it is not unit length, which results in dark lighting. Normalizing the vector after it is transformed in net.minecraft.client.model.geom.ModelPart$Cube#compile fixes this issue, and thus completely resolves the initial issue.

public void compile(PoseStack.Pose pose, VertexConsumer vertexConsumer, int i, int j, float f, float g, float h, float k) {
	Matrix4f matrix4f = pose.pose();
	Matrix3f matrix3f = pose.normal();

	for (ModelPart.Polygon polygon : this.polygons) {
		Vector3f vector3f = matrix3f.transform(new Vector3f((Vector3fc)polygon.normal));
		// Added code: normalize the vector
		vector3f.normalize();
		float l = vector3f.x();
		float m = vector3f.y();
		float n = vector3f.z();

		for (ModelPart.Vertex vertex : polygon.vertices) {
			float o = vertex.pos.x() / 16.0F;
			float p = vertex.pos.y() / 16.0F;
			float q = vertex.pos.z() / 16.0F;
			Vector4f vector4f = matrix4f.transform(new Vector4f(o, p, q, 1.0F));
			vertexConsumer.vertex(vector4f.x(), vector4f.y(), vector4f.z(), f, g, h, k, vertex.u, vertex.v, j, i, l, m, n);
		}
	}
}

Can confirm for 23w12a

[Mod] LateLag

gegy

Confirmed

Platform

Normal

Lighting, Rendering

23w07a, 1.19.4 Pre-release 1, 1.19.4 Release Candidate 2, 1.19.4, 23w12a, ..., 23w18a, 1.20, 1.20.1 Release Candidate 1, 1.20.1, 1.20.4

24w05a

Retrieved