LumixEngine/data/pipelines/film_grain.shd

113 lines
No EOL
3.5 KiB
Text

vertex_shader [[
out vec2 v_uv;
void main() {
v_uv = vec2(gl_VertexID & 1, (gl_VertexID & 2) * 0.5);
vec4 pos = vec4((gl_VertexID & 1) * 2 - 1, (gl_VertexID & 2) - 1, 0, 1);
gl_Position = pos;
}
]]
fragment_shader [[
#define timer u_time.x * 0.01
vec2 coordRot(vec2 tex_coord, float angle, vec2 tex_size)
{
float aspect = tex_size.x / tex_size.y;
float s = sin(angle);
float c = cos(angle);
vec2 tc = tex_coord * 2.0 - 1.0;
float rotX = (tc.x * aspect * c) - (tc.y * s);
float rotY = (tc.y * c) + (tc.x * aspect * s);
rotX = rotX / aspect;
rotY = rotY;
return vec2(rotX, rotY) * 0.5 + 0.5;
}
vec3 luma(vec3 _rgb)
{
float yy = dot(vec3(0.2126729, 0.7151522, 0.0721750), _rgb);
return vec3(yy);
}
vec4 rnm(in vec2 tc)
{
float noise = sin(dot(tc + vec2(timer,timer),vec2(12.9898,78.233))) * 43758.5453;
float noiseR = fract(noise)*2.0-1.0;
float noiseG = fract(noise*1.2154)*2.0-1.0;
float noiseB = fract(noise*1.3453)*2.0-1.0;
float noiseA = fract(noise*1.3647)*2.0-1.0;
return vec4(noiseR,noiseG,noiseB,noiseA);
}
float fade(float t) {
return t*t*t*(t*(t*6.0-15.0)+10.0);
}
float pnoise3D(vec3 p)
{
const float permTexUnit = 1.0 / 256.0;
const float permTexUnitHalf = 0.5 / 256.0;
vec3 pi = permTexUnit * floor(p) + permTexUnitHalf; // Integer part, scaled so +1 moves permTexUnit texel
vec3 pf = fract(p); // Fractional part for interpolation
float perm00 = rnm(pi.xy).a;
vec3 grad000 = rnm(vec2(perm00, pi.z)).rgb * 4.0 - 1.0;
float n000 = dot(grad000, pf);
vec3 grad001 = rnm(vec2(perm00, pi.z + permTexUnit)).rgb * 4.0 - 1.0;
float n001 = dot(grad001, pf - vec3(0.0, 0.0, 1.0));
float perm01 = rnm(pi.xy + vec2(0.0, permTexUnit)).a;
vec3 grad010 = rnm(vec2(perm01, pi.z)).rgb * 4.0 - 1.0;
float n010 = dot(grad010, pf - vec3(0.0, 1.0, 0.0));
vec3 grad011 = rnm(vec2(perm01, pi.z + permTexUnit)).rgb * 4.0 - 1.0;
float n011 = dot(grad011, pf - vec3(0.0, 1.0, 1.0));
float perm10 = rnm(pi.xy + vec2(permTexUnit, 0.0)).a;
vec3 grad100 = rnm(vec2(perm10, pi.z)).rgb * 4.0 - 1.0;
float n100 = dot(grad100, pf - vec3(1.0, 0.0, 0.0));
vec3 grad101 = rnm(vec2(perm10, pi.z + permTexUnit)).rgb * 4.0 - 1.0;
float n101 = dot(grad101, pf - vec3(1.0, 0.0, 1.0));
float perm11 = rnm(pi.xy + vec2(permTexUnit, permTexUnit)).a;
vec3 grad110 = rnm(vec2(perm11, pi.z)).rgb * 4.0 - 1.0;
float n110 = dot(grad110, pf - vec3(1.0, 1.0, 0.0));
vec3 grad111 = rnm(vec2(perm11, pi.z + permTexUnit)).rgb * 4.0 - 1.0;
float n111 = dot(grad111, pf - vec3(1.0, 1.0, 1.0));
vec4 n_x = mix(vec4(n000, n001, n010, n011), vec4(n100, n101, n110, n111), fade(pf.x));
vec2 n_xy = mix(n_x.xy, n_x.zw, fade(pf.y));
float n_xyz = mix(n_xy.x, n_xy.y, fade(pf.z));
return n_xyz;
}
vec3 filmGrain(vec2 tex_coord, vec2 tex_size, vec3 in_color)
{
const float grainsize = 1;
const float grainamount = 0.02;
const float lumamount = 0.1;
vec2 rotCoordsR = coordRot(tex_coord, timer, tex_size);
vec3 noise = vec3(pnoise3D(vec3(rotCoordsR * vec2(tex_size.xy / grainsize),0.0)));
float luminance = mix(0.0, luma(in_color).x, lumamount);
float lum = smoothstep(0.2, 0.0, luminance);
lum += luminance;
noise = mix(vec3(0.0), vec3(pow(lum, 4.0)), noise);
return in_color + noise * grainamount;
}
layout (binding=0) uniform sampler2D u_source;
in vec2 v_uv;
out vec4 o_color;
void main() {
vec3 c = texture(u_source, v_uv).rgb;
vec2 tex_size = textureSize(u_source, 0);
o_color.rgb = filmGrain(v_uv, tex_size, c);
o_color.w = 1;
}
]]