mojira.dev
MC-222104

Beacon beam fog is incorrectly computed

This happens since 21w13a and is probably affected by the new shaders: fog on beacon beams is not correctly computed, the fog is computed from the perspective of the beacon instead of the player causing nearby beacon beams to fade to the sky color even when they are close to the player.

What I expected to happen:

I expected beacon beams to render just like before the move to OpenGL 3. They don't seem to have any fog at all in that version so it's expectable that they should neither have fog after being ported to OpenGL 3.

Screenshot from 20w51a:

[media]

What actually happens:

Dependent on how far away the player is from the beacon, fog is applied at a certain distance from the beacon. The further away the player, the closer the fog to the beacon. 

Other screenshots:

[media]

(while this above screenshot was taken in my modded environment, the issue exists in vanilla)

[media]

Steps to reproduce

  1. Activate a beacon (build the structure in such a way it starts emititing a beam)

  2. To make a clear contrast between fog and not-fog, place some stained glass on top of the beacon. Orange contrasts very well against the sky color.

  3. Fly up into the sky while watching the beam
    ❌  In 21w11a and later: The beam fog fades towards the beacon
    ✔  Before 21w11a: The beam has no fog and renders correctly

Placing two beacons at different heights clearly demonstrates the bug:

[media]

Code analysis

It was pretty embarrassing that I could see the issue in the assets of the vanilla game. In assets/minecraft/shaders/core/rendertype_beacon_beam.vsh, the vertex distance is computed as the distance from the beacon origin. This vertex distance is then used to compute the fog.

Here's the shader for reference:

 

// VERTEX SHADER: rendertype_beacon_beam.vsh

#version 150

in vec3 Position;
in vec4 Color;
in vec2 UV0;

uniform mat4 ModelViewMat;
uniform mat4 ProjMat;

out float vertexDistance;
out vec4 vertexColor;
out vec2 texCoord0;

void main() {
    gl_Position = ProjMat * ModelViewMat * vec4(Position, 1.0);

    // The 'length' operation is not linear, this causes the issue. It must be computed in the fragment
    // shader
    vertexDistance = length((ModelViewMat * vec4(Position, 1.0)).xyz);
    vertexColor = Color;
    texCoord0 = UV0;
}

 

// FRAGMENT SHADER: rendertype_beacon_beam.fsh

#version 150

#moj_import <fog.glsl>

uniform sampler2D Sampler0;

uniform vec4 ColorModulator;
uniform float FogStart;
uniform float FogEnd;
uniform vec4 FogColor;

// If two vertices are equally far away from the player, but their average is close to the player,
// this value is constant and linearly interpolates the distance to the two distant vertices and is
// incorrect. Compute this in the fragment shader instead!!!
in float vertexDistance;
in vec4 vertexColor;
in vec2 texCoord0;

out vec4 fragColor;

void main() {
    vec4 color = texture(Sampler0, texCoord0);
    color *= vertexColor * ColorModulator;

    fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor);
}

 

 

 

Linked issues

Attachments

Comments 1

Can confirm in 21w14a.

Samū

Felix Jones

Confirmed

Important

Rendering

21w13a, 21w14a

21w15a

Retrieved