Forráskód Böngészése

More robust check for OcclusionBuffer culling mode. Now also CULL_NONE mode should detect triangle facing correctly.

Lasse Öörni 11 éve
szülő
commit
8557571cb4

+ 14 - 20
Source/Engine/Graphics/OcclusionBuffer.cpp

@@ -503,21 +503,13 @@ inline Vector4 OcclusionBuffer::ClipEdge(const Vector4& v0, const Vector4& v1, f
     return v0 + t * (v1 - v0);
 }
 
-inline bool OcclusionBuffer::CheckFacing(const Vector3& v0, const Vector3& v1, const Vector3& v2) const
+inline float OcclusionBuffer::SignedArea(const Vector3& v0, const Vector3& v1, const Vector3& v2) const
 {
-    if (cullMode_ == CULL_NONE)
-        return true;
-    
     float aX = v0.x_ - v1.x_;
     float aY = v0.y_ - v1.y_;
     float bX = v2.x_ - v1.x_;
     float bY = v2.y_ - v1.y_;
-    float signedArea = aX * bY - aY * bX;
-    
-    if (cullMode_ == CULL_CCW)
-        return signedArea < 0.0f;
-    else
-        return signedArea > 0.0f;
+    return aX * bY - aY * bX;
 }
 
 void OcclusionBuffer::CalculateViewport()
@@ -575,9 +567,10 @@ void OcclusionBuffer::DrawTriangle(Vector4* vertices)
         projected[1] = ViewportTransform(vertices[1]);
         projected[2] = ViewportTransform(vertices[2]);
         
-        if (CheckFacing(projected[0], projected[1], projected[2]))
+        bool clockwise = SignedArea(projected[0], projected[1], projected[2]) < 0.0f;
+        if (cullMode_ == CULL_NONE || (cullMode_ == CULL_CCW && clockwise) || (cullMode_ == CULL_CW && !clockwise))
         {
-            DrawTriangle2D(projected);
+            DrawTriangle2D(projected, clockwise);
             drawOk = true;
         }
     }
@@ -612,9 +605,10 @@ void OcclusionBuffer::DrawTriangle(Vector4* vertices)
                 projected[1] = ViewportTransform(vertices[index + 1]);
                 projected[2] = ViewportTransform(vertices[index + 2]);
                 
-                if (CheckFacing(projected[0], projected[1], projected[2]))
+                bool clockwise = SignedArea(projected[0], projected[1], projected[2]) < 0.0f;
+                if (cullMode_ == CULL_NONE || (cullMode_ == CULL_CCW && clockwise) || (cullMode_ == CULL_CW && !clockwise))
                 {
-                    DrawTriangle2D(projected);
+                    DrawTriangle2D(projected, clockwise);
                     drawOk = true;
                 }
             }
@@ -755,7 +749,7 @@ struct Edge
     int invZStep_;
 };
 
-void OcclusionBuffer::DrawTriangle2D(const Vector3* vertices)
+void OcclusionBuffer::DrawTriangle2D(const Vector3* vertices, bool clockwise)
 {
     int top, middle, bottom;
     bool middleIsRight;
@@ -805,11 +799,7 @@ void OcclusionBuffer::DrawTriangle2D(const Vector3* vertices)
             }
         }
     }
-    
-    // If culling is reversed, also reverse the middleIsRight assumption
-    if (cullMode_ == CULL_CW)
-        middleIsRight = !middleIsRight;
-    
+
     int topY = (int)vertices[top].y_;
     int middleY = (int)vertices[middle].y_;
     int bottomY = (int)vertices[bottom].y_;
@@ -818,6 +808,10 @@ void OcclusionBuffer::DrawTriangle2D(const Vector3* vertices)
     if (topY == bottomY)
         return;
     
+    // Reverse middleIsRight test if triangle is counterclockwise
+    if (!clockwise)
+        middleIsRight = !middleIsRight;
+
     Gradients gradients(vertices);
     Edge topToMiddle(gradients, vertices[top], vertices[middle], topY);
     Edge topToBottom(gradients, vertices[top], vertices[bottom], topY);

+ 3 - 3
Source/Engine/Graphics/OcclusionBuffer.h

@@ -115,8 +115,8 @@ private:
     inline Vector3 ViewportTransform(const Vector4& vertex) const;
     /// Clip an edge.
     inline Vector4 ClipEdge(const Vector4& v0, const Vector4& v1, float d0, float d1) const;
-    /// Check facing of a triangle.
-    inline bool CheckFacing(const Vector3& v0, const Vector3& v1, const Vector3& v2) const;
+    /// Return signed area of a triangle. If negative, is clockwise.
+    inline float SignedArea(const Vector3& v0, const Vector3& v1, const Vector3& v2) const;
     /// Calculate viewport transform.
     void CalculateViewport();
     /// Draw a triangle.
@@ -124,7 +124,7 @@ private:
     /// Clip vertices against a plane.
     void ClipVertices(const Vector4& plane, Vector4* vertices, bool* triangles, unsigned& numTriangles);
     /// Draw a clipped triangle.
-    void DrawTriangle2D(const Vector3* vertices);
+    void DrawTriangle2D(const Vector3* vertices, bool clockwise);
     
     /// Highest level depth buffer.
     int* buffer_;