/* Complex grain shader ported over from MariENB This is a simplified version that uses three PRNG calls (C)2012-2022 Marisa the Magician */ #define overlay(a,b) (a<0.5)?(2.0*a*b):(1.0-(2.0*(1.0-a)*(1.0-b))) #define darkmask(a,b) (a>0.5)?(2.0*a*(0.5+b)):(1.0-2.0*(1.0-a)*(1.0-((0.5+b)))) // simplified PRNG, for performance float rnd( in vec2 sd ) { return fract(sin(dot(sd,vec2(12.9898,78.233)))*43758.5453); } vec3 grain( in vec3 res, in vec2 coord ) { float ts = Timer; vec2 s1 = coord+vec2(0.,ts); vec2 s2 = coord+vec2(ts,0.); vec2 s3 = coord+vec2(ts,ts); float n1 = rnd(s1); float n2 = rnd(s2); float n3 = rnd(s3); float n4 = (n1+n2+n3)/3.; vec3 ng = vec3(n4); vec3 nc = vec3(n1,n2,n3); vec3 nt = pow(clamp(mix(ng,nc,ns),.0,1.),vec3(np)); if ( nb == 1 ) res.rgb += nt*ni; else if ( nb == 2 ) { res.r = overlay(res.r,(nt.r*ni)); res.g = overlay(res.g,(nt.g*ni)); res.b = overlay(res.b,(nt.b*ni)); } else if ( nb == 3 ) { float bn = 1.-clamp((res.r+res.g+res.b)/3.,0.,1.); bn = pow(bn,bnp); vec3 nn = clamp(nt*bn,vec3(0.),vec3(1.)); res.r = darkmask(res.r,(nn.r*ni)); res.g = darkmask(res.g,(nn.g*ni)); res.b = darkmask(res.b,(nn.b*ni)); } else res.rgb = mix(res.rgb,nt,ni); return res; } void main() { vec2 coord = TexCoord; vec4 res = texture(InputTexture,coord); res.rgb = grain(res.rgb,coord); FragColor = res; }