#version 150 compatibility // bump map texture uniform sampler2D bump_map; // bump map texture resolution uniform int bump_map_res; // scaling of height function uniform float bump_scale; vec3 bump_map_normal(vec3 s, vec2 tc, vec3 N) { // lookup height value float h_0 = texture2D(bump_map,tc).x; // derivatives in image space mat2 tc_i = mat2(dFdx(tc),dFdy(tc)); vec2 h_i = vec2(texture2D(bump_map,tc+tc_i[0]).x - h_0, texture2D(bump_map,tc+tc_i[1]).x - h_0); vec3 s_x = dFdx(s); vec3 s_y = dFdy(s); // compute T_i^(-1) float det_tc_i = tc_i[0][0]*tc_i[1][1] - tc_i[1][0]*tc_i[0][1]; mat2 i_tc = mat2(tc_i[1][1], -tc_i[1][0], -tc_i[0][1], tc_i[0][0])/det_tc_i; // transform derivatives to texture space vec2 h_tc = i_tc*h_i; vec2 s_tc0 = i_tc * vec2(s_x[0],s_y[0]); vec2 s_tc1 = i_tc * vec2(s_x[1],s_y[1]); vec2 s_tc2 = i_tc * vec2(s_x[2],s_y[2]); vec3 s_u = vec3(s_tc0.x,s_tc1.x,s_tc2.x); vec3 s_v = vec3(s_tc0.y,s_tc1.y,s_tc2.y); // compute scaling factor for original normal float f = length(cross(s_u,s_v)); // compute bump mapped normal vec3 n = normalize(N); float height_scale = bump_scale / float(bump_map_res); n = f*n + cross(height_scale*(h_tc[1]*s_u-h_tc[0]*s_v),n); return normalize(n); }