]> git.tdb.fi Git - libs/gl.git/blobdiff - demos/forestpond/data/water.glsl
Implement water simulation and surface shader for forest pond
[libs/gl.git] / demos / forestpond / data / water.glsl
diff --git a/demos/forestpond/data/water.glsl b/demos/forestpond/data/water.glsl
new file mode 100644 (file)
index 0000000..08ba393
--- /dev/null
@@ -0,0 +1,98 @@
+import msp_interface;
+
+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);
+}