Cubyz/assets/cubyz/shaders/chunks/chunk_fragment.fs
IntegratedQuantum 9898db654b Specify the location of all shader in/out parameters.
also normalized the version and layout formatting
progress towards #1376
2025-05-02 14:53:57 +02:00

88 lines
2.9 KiB
GLSL

#version 460
layout(location = 0) in vec3 mvVertexPos;
layout(location = 1) in vec3 direction;
layout(location = 2) in vec3 light;
layout(location = 3) in vec2 uv;
layout(location = 4) flat in vec3 normal;
layout(location = 5) flat in int textureIndex;
layout(location = 6) flat in int isBackFace;
layout(location = 7) flat in int ditherSeed;
layout(location = 8) flat in float distanceForLodCheck;
layout(location = 9) flat in int opaqueInLod;
uniform sampler2DArray texture_sampler;
uniform sampler2DArray emissionSampler;
uniform sampler2DArray reflectivityAndAbsorptionSampler;
uniform samplerCube reflectionMap;
uniform float reflectionMapSize;
uniform float contrast;
uniform float lodDistance;
layout(location = 0) out vec4 fragColor;
layout(std430, binding = 1) buffer _animatedTexture
{
float animatedTexture[];
};
float lightVariation(vec3 normal) {
const vec3 directionalPart = vec3(0, contrast/2, contrast);
const float baseLighting = 1 - contrast;
return baseLighting + dot(normal, directionalPart);
}
float ditherThresholds[16] = float[16] (
1/17.0, 9/17.0, 3/17.0, 11/17.0,
13/17.0, 5/17.0, 15/17.0, 7/17.0,
4/17.0, 12/17.0, 2/17.0, 10/17.0,
16/17.0, 8/17.0, 14/17.0, 6/17.0
);
ivec2 random1to2(int v) {
ivec4 fac = ivec4(11248723, 105436839, 45399083, 5412951);
int seed = v.x*fac.x ^ fac.y;
return seed*fac.zw;
}
bool passDitherTest(float alpha) {
if(opaqueInLod != 0) {
if(distanceForLodCheck > lodDistance) return true;
float factor = max(0, distanceForLodCheck - (lodDistance - 32.0))/32.0;
alpha = alpha*(1 - factor) + factor;
}
ivec2 screenPos = ivec2(gl_FragCoord.xy);
screenPos += random1to2(ditherSeed);
screenPos &= 3;
return alpha > ditherThresholds[screenPos.x*4 + screenPos.y];
}
vec4 fixedCubeMapLookup(vec3 v) { // Taken from http://the-witness.net/news/2012/02/seamless-cube-map-filtering/
float M = max(max(abs(v.x), abs(v.y)), abs(v.z));
float scale = (reflectionMapSize - 1)/reflectionMapSize;
if (abs(v.x) != M) v.x *= scale;
if (abs(v.y) != M) v.y *= scale;
if (abs(v.z) != M) v.z *= scale;
return texture(reflectionMap, v);
}
void main() {
float animatedTextureIndex = animatedTexture[textureIndex];
float normalVariation = lightVariation(normal);
vec3 textureCoords = vec3(uv, animatedTextureIndex);
float reflectivity = texture(reflectivityAndAbsorptionSampler, textureCoords).a;
float fresnelReflection = (1 + dot(normalize(direction), normal));
fresnelReflection *= fresnelReflection;
fresnelReflection *= min(1, 2*reflectivity); // Limit it to 2*reflectivity to avoid making every block reflective.
reflectivity = reflectivity*fixedCubeMapLookup(reflect(direction, normal)).x;
reflectivity = reflectivity*(1 - fresnelReflection) + fresnelReflection;
vec3 pixelLight = max(light*normalVariation, texture(emissionSampler, textureCoords).r*4);
fragColor = texture(texture_sampler, textureCoords)*vec4(pixelLight, 1);
fragColor.rgb += reflectivity*pixelLight;
if(!passDitherTest(fragColor.a)) discard;
fragColor.a = 1;
}