#version 150 #define GL_core_profile 1 #extension GL_EXT_gpu_shader4 : enable precision highp float; uniform sampler2DMS tex_reflection; // Multisampled texture of processed scene (e.g. after shading, etc. done) uniform float IOR; // Index of refraction (not real, just hacky stuff) out vec3 vert_vout; // Vertices in view space out vec3 normal_vout; // Normals in view space out vec3 light_vout; // Light in view space out vec4 projCoord_vout; // Projection coordinates (projective texcoords between -1 - 1 from camera) out vec4 Gpu_FragColor; // Output color to fragments /** Main **/ void main() { // Projection coordinates for textures from <-1,1> to <0,1> vec2 projCoord = projCoord_vout.xy / projCoord_vout.w; projCoord *= 0.5; projCoord += 0.5; vec3 E = normalize(-vert_vout); // Eye vector vec3 N = normalize(normal_vout); // Normal vector vec3 L = normalize(light_vout - vert_vout); // Light vector vec3 H = normalize(L + E); // Half vector vec3 R = normalize(reflect(E, N)); // Reflection vector // Now do some *magic* to compute "reflective texture coordinates" from reflection vector R.x *= -1.0; R.y *= -1.0; float m = 2.0 * sqrt(R.x * R.x + R.y * R.y + (R.z + 1.0) * (R.z + 1.0)); float s = R.x / m + 0.5; float t = R.y / m + 0.5; float fresnel = 1.0 - pow(dot(E, N), 2.0); // Mixing reflections and refractions, not even Shlicks approx. float specular = pow(max(dot(H, N), 0.0), 16.0); // Specular light (Blinn) // Again *magic* to compute offsets for "dispersion" hack vec2 offset = projCoord + vec2(R.x, R.y) * 0.1 * IOR; offset.x = abs(max(floor(offset.x), 0.0) - fract(abs(offset.x))); offset.y = abs(max(floor(offset.y), 0.0) - fract(abs(offset.y))); ivec2 iTexCoord = ivec2(vec2(800.0, 600.0) * offset); // Sample refraction (with dispersion hack) vec3 refraction; refraction.x = texelFetch(tex_reflection, iTexCoord + ivec2(1, 0), 0).x; refraction.y = texelFetch(tex_reflection, iTexCoord, 0).y; refraction.z = texelFetch(tex_reflection, iTexCoord - ivec2(1, 0), 0).z; // Sample reflection vec3 reflection = texelFetch(tex_reflection, ivec2(vec2(800.0, 600.0) * vec2(s, t)), 0).xyz; // Write out depth (logarithmic depth buffer! - to linearize the errors) + color gl_FragDepth = log(1.0 * length(vert_vout) + 1.0) / log(1.0 * 10000.0 + 1.0) * 1.0; Gpu_FragColor = vec4(reflection * fresnel + refraction * (1.0 - fresnel) + specular, 1.0); }