changeset 401:3ce4065840e9

Calculate the fog per-fragment and remove the fixed-pipeline glFog* functions; now both vertex shaders are the same.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Thu, 14 Feb 2013 20:07:23 +0100
parents 7aa70f0def38
children 88e2a2485b2b
files pytouhou/ui/gamerenderer.py pytouhou/ui/shaders/eosd.py
diffstat 2 files changed, 30 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/pytouhou/ui/gamerenderer.py
+++ b/pytouhou/ui/gamerenderer.py
@@ -71,27 +71,37 @@ class GameRenderer(Renderer):
             dx, dy, dz = back.position2_interpolator.values
             fog_b, fog_g, fog_r, fog_start, fog_end = back.fog_interpolator.values
 
+            # Those two lines may come from the difference between Direct3D and
+            # OpenGL’s distance handling.  The first one seem to calculate fog
+            # from the eye, while the second does that starting from the near
+            # plane.
+            #TODO: investigate, and use a variable to keep the near plane
+            # distance at a single place.
+            fog_start -= 101010101./2010101.
+            fog_end -= 101010101./2010101.
+
             model = Matrix()
             model.data[3] = [-x, -y, -z, 1]
             view = self.setup_camera(dx, dy, dz)
-
-            glFogi(GL_FOG_MODE, GL_LINEAR)
-            glFogf(GL_FOG_START, fog_start)
-            glFogf(GL_FOG_END,  fog_end)
-            glFogfv(GL_FOG_COLOR, (GLfloat * 4)(fog_r / 255., fog_g / 255., fog_b / 255., 1.))
+            model_view_projection = model * view * self.proj
+            mvp = model_view_projection.get_c_data()
 
             if self.use_fixed_pipeline:
-                glEnable(GL_FOG)
+                glMatrixMode(GL_MODELVIEW)
+                glLoadMatrixf(mvp)
 
-                model_view_projection = model * view * self.proj
-                glMatrixMode(GL_MODELVIEW)
-                glLoadMatrixf(model_view_projection.get_c_data())
+                glEnable(GL_FOG)
+                glFogi(GL_FOG_MODE, GL_LINEAR)
+                glFogf(GL_FOG_START, fog_start)
+                glFogf(GL_FOG_END,  fog_end)
+                glFogfv(GL_FOG_COLOR, (GLfloat * 4)(fog_r / 255., fog_g / 255., fog_b / 255., 1.))
             else:
                 self.background_shader.bind()
+                self.background_shader.uniform_matrixf('mvp', mvp)
 
-                model_view = model * view
-                self.background_shader.uniform_matrixf('model_view', model_view.get_c_data())
-                self.background_shader.uniform_matrixf('projection', self.proj.get_c_data())
+                self.background_shader.uniformf('fog_scale', 1. / (fog_end - fog_start))
+                self.background_shader.uniformf('fog_end', fog_end)
+                self.background_shader.uniformf('fog_color', fog_r / 255., fog_g / 255., fog_b / 255., 1.)
 
             self.render_background()
         else:
--- a/pytouhou/ui/shaders/eosd.py
+++ b/pytouhou/ui/shaders/eosd.py
@@ -60,37 +60,33 @@ class BackgroundShader(Shader):
             attribute vec2 in_texcoord;
             attribute vec4 in_color;
 
-            uniform mat4 model_view;
-            uniform mat4 projection;
+            uniform mat4 mvp;
 
             varying vec2 texcoord;
             varying vec4 color;
-            varying float fog_density;
 
             void main()
             {
-                vec4 position = model_view * vec4(in_position, 1.0);
+                gl_Position = mvp * vec4(in_position, 1.0);
                 texcoord = in_texcoord;
                 color = in_color;
-
-                float fog_position = -position.z / position.w;
-                fog_density = clamp((gl_Fog.end - fog_position) * gl_Fog.scale, 0.0f, 1.0f);
-
-                gl_Position = projection * position;
             }
         '''], ['''
             #version 120
 
             varying vec2 texcoord;
             varying vec4 color;
-            varying float fog_density;
 
             uniform sampler2D color_map;
+            uniform float fog_scale;
+            uniform float fog_end;
+            uniform vec4 fog_color;
 
             void main()
             {
                 vec4 temp_color = texture2D(color_map, texcoord) * color;
-                gl_FragColor = mix(gl_Fog.color, temp_color, fog_density);
-                gl_FragColor.a = temp_color.a;
+                float depth = gl_FragCoord.z / gl_FragCoord.w;
+                float fog_density = clamp((fog_end - depth) * fog_scale, 0.0f, 1.0f);
+                gl_FragColor = vec4(mix(fog_color, temp_color, fog_density).rgb, temp_color.a);
             }
         '''])