Files
wireless-docs/public/assets/minecraft/shaders/core/terrain.fsh

98 lines
3.3 KiB
GLSL

#version 330
#moj_import <minecraft:fog.glsl>
#moj_import <minecraft:globals.glsl>
#moj_import <minecraft:chunksection.glsl>
uniform sampler2D Sampler0;
in float sphericalVertexDistance;
in float cylindricalVertexDistance;
in vec4 vertexColor;
in vec2 texCoord0;
out vec4 fragColor;
vec4 sampleNearest(sampler2D source, vec2 uv, vec2 pixelSize, vec2 du, vec2 dv, vec2 texelScreenSize) {
// Convert our UV back up to texel coordinates and find out how far over we are from the center of each pixel
vec2 uvTexelCoords = uv / pixelSize;
vec2 texelCenter = round(uvTexelCoords) - 0.5f;
vec2 texelOffset = uvTexelCoords - texelCenter;
// Move our offset closer to the texel center based on texel size on screen
texelOffset = (texelOffset - 0.5f) * pixelSize / texelScreenSize + 0.5f;
texelOffset = clamp(texelOffset, 0.0f, 1.0f);
uv = (texelCenter + texelOffset) * pixelSize;
return textureGrad(source, uv, du, dv);
}
vec4 sampleNearest(sampler2D source, vec2 uv, vec2 pixelSize) {
vec2 du = dFdx(uv);
vec2 dv = dFdy(uv);
vec2 texelScreenSize = sqrt(du * du + dv * dv);
return sampleNearest(source, uv, pixelSize, du, dv, texelScreenSize);
}
// Rotated Grid Super-Sampling
vec4 sampleRGSS(sampler2D source, vec2 uv, vec2 pixelSize) {
vec2 du = dFdx(uv);
vec2 dv = dFdy(uv);
vec2 texelScreenSize = sqrt(du * du + dv * dv);
float maxTexelSize = max(texelScreenSize.x, texelScreenSize.y);
float minPixelSize = min(pixelSize.x, pixelSize.y);
float transitionStart = minPixelSize * 1.0;
float transitionEnd = minPixelSize * 2.0;
float blendFactor = smoothstep(transitionStart, transitionEnd, maxTexelSize);
float duLength = length(du);
float dvLength = length(dv);
float minDerivative = min(duLength, dvLength);
float maxDerivative = max(duLength, dvLength);
float effectiveDerivative = sqrt(minDerivative * maxDerivative);
float mipLevelExact = max(0.0, log2(effectiveDerivative / minPixelSize));
float mipLevelLow = floor(mipLevelExact);
float mipLevelHigh = mipLevelLow + 1.0;
float mipBlend = fract(mipLevelExact);
const vec2 offsets[4] = vec2[](
vec2(0.125, 0.375),
vec2(-0.125, -0.375),
vec2(0.375, -0.125),
vec2(-0.375, 0.125)
);
vec4 rgssColorLow = vec4(0.0);
vec4 rgssColorHigh = vec4(0.0);
for (int i = 0; i < 4; ++i) {
vec2 sampleUV = uv + offsets[i] * pixelSize;
rgssColorLow += textureLod(source, sampleUV, mipLevelLow);
rgssColorHigh += textureLod(source, sampleUV, mipLevelHigh);
}
rgssColorLow *= 0.25;
rgssColorHigh *= 0.25;
vec4 rgssColor = mix(rgssColorLow, rgssColorHigh, mipBlend);
vec4 nearestColor = sampleNearest(source, uv, pixelSize, du, dv, texelScreenSize);
return mix(nearestColor, rgssColor, blendFactor);
}
void main() {
vec4 color = (UseRgss == 1 ? sampleRGSS(Sampler0, texCoord0, 1.0f / TextureSize) : sampleNearest(Sampler0, texCoord0, 1.0f / TextureSize)) * vertexColor;
color = mix(FogColor * vec4(1, 1, 1, color.a), color, ChunkVisibility);
#ifdef ALPHA_CUTOUT
if (color.a < ALPHA_CUTOUT) {
discard;
}
#endif
fragColor = apply_fog(color, sphericalVertexDistance, cylindricalVertexDistance, FogEnvironmentalStart, FogEnvironmentalEnd, FogRenderDistanceStart, FogRenderDistanceEnd, FogColor);
}