wined3d: Fix some upside-down rendering issues for shaders

Jason Green jave27 at gmail.com
Wed Jul 26 21:13:32 CDT 2006


Flips the resulting y position in both ARB and GLSL vertex shaders if
the current rendertarget was rendered upside down.  Also, slightly
decreases the number of available float PARAMs to ARB vertex shaders
to fix a recent regression for some ATI users and to accomodate the
reference to the PROJECTION matrix in the vertex shader.

This fixes most of the upside-down rendering issues in Max Payne 2,
Half Life 2, Civilization 4, and Tomb Raider: Legends and has no
noticeable drop in FPS.  Many of the character/object models are still
broken, but that's a different issue unfortunately.

Jason
-------------- next part --------------
diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index ee56e9c..a2b07db 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -144,6 +144,9 @@ void shader_generate_arb_declarations(
     unsigned max_constantsF = min(This->baseShader.limits.constant_float, 
             (pshader ? GL_LIMITS(pshader_constantsF) : GL_LIMITS(vshader_constantsF)));
 
+    /* Temporary Output register */
+    shader_addline(buffer, "TEMP TMP_OUT;\n");
+
     for(i = 0; i < This->baseShader.limits.temporary; i++) {
         if (reg_maps->temporary[i])
             shader_addline(buffer, "TEMP R%lu;\n", i);
@@ -168,6 +171,7 @@ void shader_generate_arb_declarations(
     /* Need to PARAM the environment parameters (constants) so we can use relative addressing */
     shader_addline(buffer, "PARAM C[%d] = { program.env[0..%d] };\n",
                    max_constantsF, max_constantsF - 1);
+    shader_addline(buffer, "PARAM PROJECTION = state.matrix.projection.row[1];\n");
 }
 
 static const char* shift_tab[] = {
@@ -344,7 +348,7 @@ static void vshader_program_add_param(SH
   IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl*) arg->shader;
 
   /* oPos, oFog and oPts in D3D */
-  static const char* hwrastout_reg_names[] = { "result.position", "TMP_FOG", "result.pointsize" };
+  static const char* hwrastout_reg_names[] = { "TMP_OUT", "TMP_FOG", "result.pointsize" };
 
   DWORD reg = param & D3DSP_REGNUM_MASK;
   DWORD regtype = shader_get_regtype(param);
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index d804f93..f2fbce0 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -247,8 +247,10 @@ void select_shader_max_constants(WineD3D
             gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - MAX_CONST_B - MAX_CONST_I;
             break;
         case SHADER_ARB:
-            /* ARB shaders seem to have an implicit PARAM when fog is used, so we need to subtract 1 from the total available */
-            gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF - 1;
+            /* We have to subtract any other PARAMs that we might use in our shader programs.
+             * ATI seems to count 2 implicit PARAMs when we use fog and NVIDIA counts 1,
+             * and we reference one row of the PROJECTION matrix which counts as 1 PARAM. */
+            gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF - 3;
             break;
         case SHADER_SW:
             gl_info->max_vshader_constantsF = 96;  /* TODO: Fixup software shaders */
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index a7dd644..ab6162c 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -304,9 +304,6 @@ static void primitiveInitState(
         }
 
         /* Vertex Shader output is already transformed, so set up identity matrices */
-        /* FIXME: Actually, only true for software emulated ones, so when h/w ones
-             come along this needs to take into account whether s/w ones were
-             requested or not                                                       */
         if (useVS) {
             glMatrixMode(GL_MODELVIEW);
             checkGLcall("glMatrixMode");
diff --git a/dlls/wined3d/vertexshader.c b/dlls/wined3d/vertexshader.c
index c0ee399..923f953 100644
--- a/dlls/wined3d/vertexshader.c
+++ b/dlls/wined3d/vertexshader.c
@@ -718,6 +718,11 @@ #endif
             This->usesFog = 1;
             shader_addline(&buffer, "gl_FogFragCoord = clamp(gl_FogFragCoord, 0.0, 1.0);\n");
         }
+        
+        /* Write the final position.
+         * Account for any inverted textures (render to texture case) by reversing the y coordinate
+         *  (this is handled in drawPrim() when it sets the MODELVIEW and PROJECTION matrices) */
+        shader_addline(&buffer, "gl_Position.y = gl_Position.y * gl_ProjectionMatrix[1][1];\n");
 
         shader_addline(&buffer, "}\n\0");
 
@@ -754,6 +759,12 @@ #endif
         if (reg_maps->fog)
             shader_addline(&buffer, "MAX result.fogcoord, TMP_FOG, 0.0;\n");
 
+        /* Write the final position.
+         * Account for any inverted textures (render to texture case) by reversing the y coordinate
+         *  (this is handled in drawPrim() when it sets the MODELVIEW and PROJECTION matrices) */
+        shader_addline(&buffer, "MOV result.position, TMP_OUT;\n");
+        shader_addline(&buffer, "MUL result.position.y, TMP_OUT.y, state.matrix.projection.row[1].y;\n");
+        
         shader_addline(&buffer, "END\n\0"); 
 
         /* TODO: change to resource.glObjectHandle or something like that */


More information about the wine-patches mailing list