#version 330 #moj_import #moj_import #moj_import 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); }