import msp_interface; import lighting; uniform Tessellation { float tessellation_level; }; uniform Region { vec2 scale; vec2 offset; float amplitude; } region; uniform sampler2D bottom; uniform sampler2D surface; uniform sampler2D normals; uniform sampler2D variance; #pragma MSP stage(vertex) void main() { gl_Position = world_obj_matrix*vertex; } #pragma MSP stage(tess_control) layout(vertices=4) out; void main() { gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; gl_TessLevelInner[0] = tessellation_level; gl_TessLevelInner[1] = tessellation_level; for(int i=0; i<4; ++i) gl_TessLevelOuter[i] = tessellation_level; } #pragma MSP stage(tess_eval) layout(quads) in; void main() { float w0 = (1.0-gl_TessCoord.x)*(1.0-gl_TessCoord.y); float w1 = gl_TessCoord.x*(1.0-gl_TessCoord.y); float w2 = gl_TessCoord.x*gl_TessCoord.y; float w3 = (1.0-gl_TessCoord.x)*gl_TessCoord.y; vec4 pos = w0*gl_in[0].gl_Position+w1*gl_in[1].gl_Position+w2*gl_in[2].gl_Position+w3*gl_in[3].gl_Position; out vec2 texcoord = pos.xy*region.scale+region.offset; pos.z = textureLod(surface, texcoord, 0).x*region.amplitude-0.01; out vec3 world_look = pos.xyz-world_eye_matrix[3].xyz; gl_Position = clip_eye_matrix*eye_world_matrix*pos; } #pragma MSP stage(fragment) layout(location=0) out vec4 frag_color; float shadowing(vec3 dir, vec3 normal, float slope_var) { float d_dot_n = dot(dir, normal); float a = d_dot_n/sqrt(2*slope_var*(1-d_dot_n*d_dot_n)); return exp(-a*a)/(a*3.544908); } void main() { vec3 offset = vec3(fwidth(texcoord)/2.0, 0.0); float level = texture(surface, texcoord).x; float depth = level-texture(bottom, texcoord).x; if(depth<0.5) discard; vec2 normal_xy = texture(normals, texcoord).xy*2.0-1.0; vec3 normal = normalize(vec3(normal_xy, sqrt(max(1-dot(normal_xy, normal_xy), 0.0)))); float slope_var = texture(variance, texcoord).x; vec3 light = normalize(light_sources[0].position.xyz); vec3 look = normalize(world_look); vec3 halfway = normalize(light-look); float fresnel_d = 0.02+0.98*pow(1.0-dot(halfway, light), 5.0); vec2 half_slope = halfway.xy/dot(halfway, normal); float sdist = 1.0/(6.2831853*slope_var)*exp(-dot(half_slope, half_slope)/(slope_var*2.0)); float geom = 1.0/(1.0+shadowing(light, normal, slope_var)+shadowing(-look, normal, slope_var)); float h_dot_n = dot(halfway, normal); float h_dot_n_sq = h_dot_n*h_dot_n; vec3 color = light_sources[0].color*fresnel_d*sdist*geom/(4*h_dot_n_sq*h_dot_n_sq*dot(-look, normal)); float std_dev = sqrt(slope_var); float fresnel_e = 0.02+0.98*pow(1.0+dot(look, normal), 5.0*exp(-2.69*std_dev))/(1+22.7*pow(std_dev, 1.5)); vec3 reflect_dir = reflect(look, normal); vec3 env_color = (reflect_dir.z>0 ? vec3(0.34, 0.54, 0.9) : vec3(0.0)); color += env_color*fresnel_e; frag_color = vec4(color, 1.0); }