Files
2025-11-18 08:49:24 +01:00

292 lines
9.7 KiB
GLSL

#version 120
/* DRAWBUFFERS:34 */
#define gbuffers_shadows
#define composite0
#define composite2
#define lightingColors
#include "/shaders.settings"
#ifdef HandLight
uniform int heldBlockLightValue;
uniform int heldBlockLightValue2;
#endif
varying vec2 texcoord;
varying vec3 sunVec;
varying vec3 upVec;
varying vec3 sunlight;
varying float tr;
varying float sunVisibility;
varying float moonVisibility;
uniform sampler2D depthtex0;
uniform sampler2D depthtex1;
uniform sampler2D colortex0;
uniform sampler2D colortex1;
uniform sampler2D colortex2;
uniform sampler2D composite;
uniform mat4 gbufferProjectionInverse;
uniform int isEyeInWater;
uniform float aspectRatio;
uniform float near;
uniform float far;
uniform float viewWidth;
uniform float viewHeight;
uniform float rainStrength;
uniform float nightVision;
uniform float screenBrightness;
float comp = 1.0-near/far/far; //distance above that are considered as sky
const vec2 check_offsets[25] = vec2[25](vec2(-0.4894566f,-0.3586783f),
vec2(-0.1717194f,0.6272162f),
vec2(-0.4709477f,-0.01774091f),
vec2(-0.9910634f,0.03831699f),
vec2(-0.2101292f,0.2034733f),
vec2(-0.7889516f,-0.5671548f),
vec2(-0.1037751f,-0.1583221f),
vec2(-0.5728408f,0.3416965f),
vec2(-0.1863332f,0.5697952f),
vec2(0.3561834f,0.007138769f),
vec2(0.2868255f,-0.5463203f),
vec2(-0.4640967f,-0.8804076f),
vec2(0.1969438f,0.6236954f),
vec2(0.6999109f,0.6357007f),
vec2(-0.3462536f,0.8966291f),
vec2(0.172607f,0.2832828f),
vec2(0.4149241f,0.8816f),
vec2(0.136898f,-0.9716249f),
vec2(-0.6272043f,0.6721309f),
vec2(-0.8974028f,0.4271871f),
vec2(0.5551881f,0.324069f),
vec2(0.9487136f,0.2605085f),
vec2(0.7140148f,-0.312601f),
vec2(0.0440252f,0.9363738f),
vec2(0.620311f,-0.6673451f)
);
vec3 decode (vec2 enc){
vec2 fenc = enc*4-2;
float f = dot(fenc,fenc);
float g = sqrt(1-f/4.0);
vec3 n;
n.xy = fenc*g;
n.z = 1-f/2;
return n;
}
vec3 YCoCg2RGB(vec3 c){
c.y-=0.5;
c.z-=0.5;
return vec3(c.r+c.g-c.b, c.r + c.b, c.r - c.g - c.b);
}
#ifdef Celshading
float edepth(vec2 coord) {
return texture2D(depthtex1,coord).x;
}
vec3 celshade(vec3 clrr) {
//edge detect
float dtresh = 1.0/(far-near) / (5000.0*Celradius);
vec4 dc = vec4(edepth(texcoord.xy));
vec3 border = vec3(1.0/viewWidth, 1.0/viewHeight, 0.0)*Celborder;
vec4 sa = vec4(edepth(texcoord.xy + vec2(-border.x,-border.y)),
edepth(texcoord.xy + vec2(border.x,-border.y)),
edepth(texcoord.xy + vec2(-border.x,border.z)),
edepth(texcoord.xy + vec2(border.z,border.y)));
//opposite side samples
vec4 sb = vec4(edepth(texcoord.xy + vec2(border.x,border.y)),
edepth(texcoord.xy + vec2(-border.x,border.y)),
edepth(texcoord.xy + vec2(border.x,border.z)),
edepth(texcoord.xy + vec2(border.z,-border.y)));
vec4 dd = abs(2.0* dc - sa - sb) - dtresh;
dd = step(dd.xyzw, vec4(0.0));
float e = clamp(dot(dd,vec4(0.25f)),0.0,1.0);
return clrr*e;
}
#endif
#ifdef TAA
vec2 texelSize = vec2(1.0/viewWidth,1.0/viewHeight);
uniform int framemod8;
const vec2[8] offsets = vec2[8](vec2(1./8.,-3./8.),
vec2(-1.,3.)/8.,
vec2(5.0,1.)/8.,
vec2(-3,-5.)/8.,
vec2(-5.,5.)/8.,
vec2(-7.,-1.)/8.,
vec2(3,7.)/8.,
vec2(7.,-7.)/8.);
#endif
vec3 toScreenSpace(vec3 p) {
vec4 iProjDiag = vec4(gbufferProjectionInverse[0].x, gbufferProjectionInverse[1].y, gbufferProjectionInverse[2].zw);
vec3 p3 = p * 2.0 - 1.0;
vec4 fragposition = iProjDiag * p3.xyzz + gbufferProjectionInverse[3];
return fragposition.xyz / fragposition.w;
}
#ifdef SSDO
uniform float frameTimeCounter;
//modified version of Yuriy O'Donnell's SSDO (License MIT -> https://github.com/kayru/dssdo)
float calcSSDO(vec3 fragpos, vec3 normal){
float finalAO = 0.0;
float radius = 0.05 / (fragpos.z);
const float attenuation_angle_threshold = 0.1;
const int num_samples = 16;
const float ao_weight = 1.0;
#ifdef TAA
float noise = fract(0.75487765 * gl_FragCoord.x + 0.56984026 * gl_FragCoord.y);
noise = fract(frameTimeCounter * 2.0 + noise);
#else
float noise = 1.0;
#endif
for( int i=0; i<num_samples; ++i ){
vec2 texOffset = pow(length(check_offsets[i].xy),0.5)*radius*vec2(1.0,aspectRatio)*normalize(check_offsets[i].xy);
vec2 newTC = texcoord+texOffset*noise;
#ifdef TAA
vec3 t0 = toScreenSpace(vec3(newTC-offsets[framemod8]*texelSize*0.5, texture2D(depthtex1, newTC).x));
#else
vec3 t0 = toScreenSpace(vec3(newTC, texture2D(depthtex1, newTC).x));
#endif
vec3 center_to_sample = t0.xyz - fragpos.xyz;
float dist = length(center_to_sample);
vec3 center_to_sample_normalized = center_to_sample / dist;
float attenuation = 1.0-clamp(dist/6.0,0.0,1.0);
float dp = dot(normal, center_to_sample_normalized);
attenuation = sqrt(max(dp,0.0))*attenuation*attenuation * step(attenuation_angle_threshold, dp);
finalAO += attenuation * (ao_weight / num_samples);
}
return finalAO;
}
#endif
vec2 decodeVec2(float a){
const vec2 constant1 = 65535. / vec2( 256., 65536.);
const float constant2 = 256. / 255.;
return fract( a * constant1 ) * constant2 ;
}
uniform mat4 gbufferModelViewInverse;
void main() {
//Setup depth
float depth0 = texture2D(depthtex0, texcoord).x; //everything
float depth1 = texture2D(depthtex1, texcoord).x; //transparency
bool sky = (depth1 >= 1.0);
vec4 albedo = texture2D(colortex0,texcoord);
vec3 normal = decode(texture2D(colortex1, texcoord).xy);
vec2 lightmap = texture2D(colortex1, texcoord.xy).zw;
bool translucent = albedo.b > 0.69 && albedo.b < 0.71;
bool emissive = albedo.b > 0.59 && albedo.b < 0.61;
vec3 color = vec3(albedo.rg,0.0);
vec2 a0 = texture2D(colortex0,texcoord + vec2(1.0/viewWidth,0.0)).rg;
vec2 a1 = texture2D(colortex0,texcoord - vec2(1.0/viewWidth,0.0)).rg;
vec2 a2 = texture2D(colortex0,texcoord + vec2(0.0,1.0/viewHeight)).rg;
vec2 a3 = texture2D(colortex0,texcoord - vec2(0.0,1.0/viewHeight)).rg;
vec4 lumas = vec4(a0.x,a1.x,a2.x,a3.x);
vec4 chromas = vec4(a0.y,a1.y,a2.y,a3.y);
vec4 w = 1.0-step(0.1176, abs(lumas - color.x));
float W = dot(w,vec4(1.0));
w.x = (W==0.0)? 1.0:w.x; W = (W==0.0)? 1.0:W;
bool pattern = (mod(gl_FragCoord.x,2.0)==mod(gl_FragCoord.y,2.0));
color.b= dot(w,chromas)/W;
color.rgb = (pattern)?color.rbg:color.rgb;
color.rgb = YCoCg2RGB(color.rgb);
color = pow(color,vec3(2.2));
if (!sky){
//Water and Ice
vec3 Wnormal = texture2D(colortex2,texcoord).xyz;
bool iswater = Wnormal.z < 0.2499 && dot(Wnormal,Wnormal) > 0.0;
bool isice = Wnormal.z > 0.2499 && Wnormal.z < 0.4999 && dot(Wnormal,Wnormal) > 0.0;
bool isnsun = (iswater||isice) || ((!iswater||!isice) && isEyeInWater == 1);
/*--------------------------------------------------------------------------------------*/
#ifdef TAA
vec2 newTC = gl_FragCoord.xy*texelSize;
vec3 TAAfragpos = toScreenSpace(vec3(newTC-offsets[framemod8]*texelSize*0.5, texture2D(depthtex1, newTC).x));
#else
vec3 TAAfragpos = toScreenSpace(vec3(texcoord,depth1)); //was depth0 before, might cause issues
#endif
#ifdef Whiteworld
color += vec3(1.5);
#endif
#ifdef Celshading
color = celshade(color);
#endif
float ao = 1.0;
#ifdef SSDO
float occlusion = calcSSDO(TAAfragpos, normal);
if(!iswater)ao = pow(1.0-occlusion, ao_strength);
#endif
//Emissive blocks lighting and colors
#ifdef HandLight
bool underwaterlava = (isEyeInWater == 1.0 || isEyeInWater == 2.0);
if(!underwaterlava) lightmap.x = max(lightmap.x, max(max(float(heldBlockLightValue), float(heldBlockLightValue2)) - 1.0 - length(TAAfragpos), 0.0) / 15.0);
#endif
float torch_lightmap = 16.0-min(15.0,(lightmap.x-0.5/16.0)*16.0*16.0/15.0);
float fallof1 = clamp(1.0 - pow(torch_lightmap/16.0,4.0),0.0,1.0);
torch_lightmap = fallof1*fallof1/(torch_lightmap*torch_lightmap+1.0);
float c_emitted = dot((color.rgb),vec3(1.0,0.6,0.4))/2.0;
float emitted = emissive? clamp(c_emitted*c_emitted,0.0,1.0)*torch_lightmap : 0.0;
vec3 emissiveLightC = vec3(emissive_R,emissive_G,emissive_B);
/*------------------------------------------------------------------------------------------*/
//Lighting and colors
float NdotL = dot(normal,sunVec);
float NdotU = dot(normal,upVec);
const vec3 moonlight = vec3(0.5, 0.9, 1.8) * Moonlight;
vec2 visibility = vec2(sunVisibility,moonVisibility);
float skyL = max(lightmap.y-2./16.0,0.0)*1.14285714286;
float SkyL2 = skyL*skyL;
float skyc2 = mix(1.0,SkyL2,skyL);
vec4 bounced = vec4(NdotL,NdotL,NdotL,NdotU) * vec4(-0.14*skyL*skyL,0.33,0.7,0.1) + vec4(0.6,0.66,0.7,0.25);
bounced *= vec4(skyc2,skyc2,visibility.x-tr*visibility.x,0.8);
vec3 sun_ambient = bounced.w * (vec3(0.1, 0.5, 1.1)*2.4+rainStrength*2.3*vec3(0.05,-0.33,-0.9))+ 1.6*sunlight*(sqrt(bounced.w)*bounced.x*2.4 + bounced.z)*(1.0-rainStrength*0.99);
vec3 moon_ambient = (moonlight*0.7 + moonlight*bounced.y)*4.0;
vec3 amb1 = (sun_ambient*visibility.x + moon_ambient*visibility.y)*SkyL2*(0.03*0.65+tr*0.17*0.65);
float finalminlight = (nightVision > 0.01)? 0.15 : (minlight+0.006)+(screenBrightness*0.0125); //add nightvision support but make sure minlight is still adjustable.
vec3 ambientC = ao*amb1 + emissiveLightC*(emitted*15.*color + torch_lightmap*ao)*0.66 + ao*finalminlight*min(skyL+6/16.,9/16.)*normalize(amb1+0.0001);
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
color *= (ambientC*(isnsun?1.0/(SkyL2*skyL*0.5+0.5):1.0)*1.4)*0.63;
}
//Draw skytexture from gbuffers_skytextured
if (sky)color = pow(texture2D(composite, texcoord.xy).rgb,vec3(2.2));
gl_FragData[0] = vec4(0.0); //used by custom skycolor, godrays and VL not needed in end dimension
gl_FragData[1] = vec4(pow(color/257.0,vec3(0.454)), 1.0);
}