Fix more polygon winding, culling confusion.
authorBrian <brian.paul@tungstengraphics.com>
Fri, 13 Jul 2007 20:22:46 +0000 (14:22 -0600)
committerBrian <brian.paul@tungstengraphics.com>
Fri, 13 Jul 2007 20:22:46 +0000 (14:22 -0600)
If the determinant of the triangle is positive, its winding is CCW (right-handed coord system).

src/mesa/pipe/draw/draw_cull.c
src/mesa/pipe/draw/draw_twoside.c
src/mesa/state_tracker/st_atom_setup.c

index 863686f..e563f9f 100644 (file)
@@ -40,7 +40,7 @@
 
 struct cull_stage {
    struct draw_stage stage;
-   GLuint mode;  /**< one of PIPE_WINDING_x */
+   GLuint winding;  /**< which winding(s) to cull (one of PIPE_WINDING_x) */
 };
 
 
@@ -54,7 +54,7 @@ static void cull_begin( struct draw_stage *stage )
 {
    struct cull_stage *cull = cull_stage(stage);
 
-   cull->mode = stage->draw->setup.cull_mode;
+   cull->winding = stage->draw->setup.cull_mode;
 
    stage->next->begin( stage->next );
 }
@@ -78,10 +78,12 @@ static void cull_tri( struct draw_stage *stage,
    header->det = ex * fy - ey * fx;
 
    if (header->det != 0) {
-      /* non-zero area */
-      GLuint mode = (header->det > 0) ? PIPE_WINDING_CW : PIPE_WINDING_CCW;
+      /* if (det > 0 then Z points toward camera and triangle is 
+       * counter-clockwise winding.
+       */
+      GLuint winding = (header->det > 0) ? PIPE_WINDING_CCW : PIPE_WINDING_CW;
 
-      if ((mode & cull_stage(stage)->mode) == 0) {
+      if ((winding & cull_stage(stage)->winding) == 0) {
          /* triangle is not culled, pass to next stage */
         stage->next->tri( stage->next, header );
       }
index e86123e..9f26335 100644 (file)
@@ -35,8 +35,7 @@
 
 struct twoside_stage {
    struct draw_stage stage;
-   
-   GLfloat facing;
+   GLfloat sign;         /**< +1 or -1 */
    const GLuint *lookup;
 };
 
@@ -51,7 +50,12 @@ static void twoside_begin( struct draw_stage *stage )
 {
    struct twoside_stage *twoside = twoside_stage(stage);
 
-   twoside->facing = (stage->draw->setup.front_winding == PIPE_WINDING_CW) ? 1 : -1;
+   /*
+    * We'll multiply the primitive's determinant by this sign to determine
+    * if the triangle is back-facing (negative).
+    * sign = 1 for CCW, -1 for CW
+    */
+   twoside->sign = (stage->draw->setup.front_winding == PIPE_WINDING_CCW) ? 1 : -1;
 
    stage->next->begin( stage->next );
 }
@@ -94,7 +98,7 @@ static void twoside_tri( struct draw_stage *stage,
 {
    struct twoside_stage *twoside = twoside_stage(stage);
 
-   if (header->det * twoside->facing < 0) {
+   if (header->det * twoside->sign < 0.0) {
       /* this is a back-facing triangle */
       struct prim_header tmp;
 
index 8b95ea9..08f7a8a 100644 (file)
@@ -78,13 +78,19 @@ static void update_setup_state( struct st_context *st )
    /* _NEW_POLYGON, _NEW_BUFFERS
     */
    {
-      setup.front_winding = PIPE_WINDING_CW;
-       
+      if (ctx->Polygon.FrontFace == GL_CCW)
+         setup.front_winding = PIPE_WINDING_CCW;
+      else
+         setup.front_winding = PIPE_WINDING_CW;
+
+      /* XXX
+       * I think the intention here is that user-created framebuffer objects
+       * use Y=0=TOP layout instead of OpenGL's normal Y=0=bottom layout.
+       * Flipping Y changes CW to CCW and vice-versa.
+       * But this is an implementation/driver-specific artifact - remove...
+       */
       if (ctx->DrawBuffer && ctx->DrawBuffer->Name != 0)
-        setup.front_winding ^= PIPE_WINDING_BOTH;
-
-      if (ctx->Polygon.FrontFace != GL_CCW)
-        setup.front_winding ^= PIPE_WINDING_BOTH;
+         setup.front_winding ^= PIPE_WINDING_BOTH;
    }
 
    /* _NEW_LIGHT