// Z range (relative to camera) must be 3..7 varying vec3 n, l, h, rn, rv; varying float z; #vertex void main() { // vertex position vec4 v = gl_ModelViewMatrix * gl_Vertex; gl_Position = gl_ProjectionMatrix * v; // normal vector n = normalize(gl_NormalMatrix * gl_Normal); // lighting stuff l = normalize(vec3(gl_LightSource[0].position) - vec3(gl_ModelViewMatrix * gl_Vertex)); h = normalize(gl_LightSource[0].halfVector.xyz); gl_FrontColor = gl_Color; // generate some varyings rn = gl_Normal; rv = gl_Vertex.xyz; z = -0.25 * (v.z + 3.0); } #fragment uniform sampler2D tex; uniform sampler2D bkside; uniform sampler2D bkgnd; uniform vec2 tscale, toffs, tasp; vec3 smpl(in vec3 en, in vec2 tc) { return 0.5 * dot(rn, en) * (texture2D(tex, 0.5 * tc + vec2(0.5, 0.5)).xyz - vec3(0.5, 0.5, 0.5)); } vec3 refract(in float idx, in vec3 inc, in vec3 norm) { return mix(norm, inc, idx); } void main() { float d; // prepare texture lookups vec2 tc = tscale * (gl_FragCoord.xy + toffs); // compute effective normal vec3 nn = normalize(normalize(n) + smpl(vec3(1.0, 0.0, 0.0), rv.yz) + smpl(vec3(0.0, 1.0, 0.0), rv.xz) + smpl(vec3(0.0, 0.0, 1.0), rv.xy)); // compute standard phong lighting first vec4 col = gl_Color * gl_LightModel.ambient; d = dot(nn, normalize(l)); if (d > 0.0) col += gl_Color * d; d = dot(nn, normalize(h)); if (d > 0.0) col += gl_FrontMaterial.specular * pow(d, gl_FrontMaterial.shininess); // refract the incident ray at the front side vec3 r = refract(1.0/1.6, vec3(0.0, 0.0, -1.0), -nn); // compute Z difference between front and back side of the crystal d = texture2D(bkside, tc).a - z; // modify texture coordinate to look up the normal from the back side tc += (-0.05 * d / r.z) * r.xy * tasp; // get back side normal vec4 back = texture2D(bkside, tc); nn = 2.0 * (back.xyz - 0.5); // refract again at the back side r = refract(1.6, normalize(r), nn); // compute Z difference to background d = 5.0 - back.a; // modify texture coordinate to get final coordinate tc += (-0.05 * d / r.z) * r.xy * tasp; // add the background value at the indicated location gl_FragColor = col + texture2D(bkgnd, tc); }