Browse Source

Lesson 20.2

Godzil 3 years ago
parent
commit
e78a2b2c40
5 changed files with 62 additions and 13 deletions
  1. 1 1
      CMakeLists.txt
  2. 6 2
      source/include/triangle.h
  3. 22 2
      source/main.c
  4. 0 1
      source/matrix.c
  5. 33 7
      source/triangle.c

+ 1 - 1
CMakeLists.txt

@@ -10,7 +10,7 @@ git_describe(VERSION --tags --dirty=-dirty)
 
 option(WARN_AS_ERROR "Enable warning as error" OFF)
 
-set(COMP_FLAGS "-Wall -Wextra -Wno-unused-parameter -Wno-unused-result -Wno-write-strings")
+set(COMP_FLAGS "-march=native -Wall -Wextra -Wno-unused-parameter -Wno-unused-result -Wno-write-strings")
 
 if (WARN_AS_ERROR)
     set(COMP_FLAGS "${COMP_FLAGS} -Werror")

+ 6 - 2
source/include/triangle.h

@@ -18,7 +18,6 @@
 /***********************************************************************************************************************
  * Data types
  **********************************************************************************************************************/
-
 typedef struct face_t
 {
     int a, b, c;
@@ -31,7 +30,7 @@ typedef struct face_t
 
 typedef struct triangle_t
 {
-    vec2_t points[3];
+    vec4_t points[3];
     tex2_t textureCoordinates[3];
 
     colour_t colour;
@@ -40,6 +39,11 @@ typedef struct triangle_t
     uint32_t *texture;
 } triangle_t;
 
+/***********************************************************************************************************************
+ * Global variables
+ **********************************************************************************************************************/
+extern bool doPerpectiveCorrection;
+
 /***********************************************************************************************************************
  * Prototypes
  **********************************************************************************************************************/

+ 22 - 2
source/main.c

@@ -41,6 +41,7 @@ enum displayMode_t currentDisplayMode = DISPLAY_MODE_SOLID;
 matrix4_t projectionMatrix;
 light_t globalLight;
 double updateTime, renderTime, waitTime;
+int trianglesCount, trianglesTotal;
 
 vec3_t cameraPosition =
 {
@@ -80,6 +81,8 @@ void setup()
     //loadOBJFile("assets/f22.obj");
     loadCubeMeshData();
 
+    trianglesTotal = arrayGetSize(mesh.faces);
+
 exit:
     return;
 }
@@ -138,6 +141,14 @@ void processInput()
         case SDLK_d:
             doNotCull = true;
             break;
+
+        case SDLK_v:
+            doPerpectiveCorrection = false;
+            break;
+
+        case SDLK_f:
+            doPerpectiveCorrection = true;
+            break;
         }
         break;
 
@@ -171,7 +182,8 @@ void update()
     waitTime = (waitTime + (getMicroSecTime() - ticks) / 1000.) / 2.0;
     ticks = getMicroSecTime();
 
-    mesh.rotation.x += 0.01;
+    mesh.rotation.x += 0.001;
+    mesh.rotation.y += 0.01;
     mesh.translation.z = 5;
 
     worldMatrix = mat4Identity;
@@ -250,6 +262,8 @@ void update()
 
             currentTriangle.points[j].x = projected.x;
             currentTriangle.points[j].y = projected.y;
+            currentTriangle.points[j].w = projected.w;
+            currentTriangle.points[j].z = projected.z;
         }
 
         double lightLevel = -vec3Dot(triangleNormal, globalLight.direction);
@@ -262,8 +276,10 @@ void update()
         arrayAdd(projectedTriangles, currentTriangle);
     }
 
+    trianglesCount = arrayGetSize(projectedTriangles);
+
     qsort(projectedTriangles,
-          arrayGetSize(projectedTriangles),
+          trianglesCount,
           sizeof(triangle_t),
           compareTrianglesZOrder);
 
@@ -338,6 +354,10 @@ void render()
     drawText(5, 17, 0x11FF22, "Update time: %02.2f ms", updateTime);
     drawText(5, 29, 0x11FF22, "Render time: %02.2f ms", renderTime);
     drawText(5, 41, 0x11FF22, "FPS: %.2f", 1000 / (waitTime + updateTime + renderTime));
+    drawText(5, 53, 0x11FF22, "Triangles: %d / %d", triangleCount, trianglesTotal);
+    drawText(5, 65, 0x11FF22, "Culling: %s / PerspCorrection: %s",
+             doNotCull?"disabled":"enabled",
+             doPerpectiveCorrection?"enabled":"disabled");
     SDL_RenderPresent(renderer);
 }
 

+ 0 - 1
source/matrix.c

@@ -46,7 +46,6 @@ vec4_t mat4ProdVec4Project(matrix4_t mat, vec4_t v)
         result.x /= result.w;
         result.y /= result.w;
         result.z /= result.w;
-        result.w = 0;
     }
 
     return result;

+ 33 - 7
source/triangle.c

@@ -7,10 +7,15 @@
  * Created by Manoël Trapier on 04/03/2021.
  */
 
+#include <stdint.h>
+#include <stdbool.h>
+
 #include <display.h>
 #include <triangle.h>
 #include <math.h>
 
+bool doPerpectiveCorrection = true;
+
 void drawTriangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, colour_t colour)
 {
     drawLine(x0, y0, x1, y1, colour);
@@ -132,10 +137,14 @@ static vec3_t barycentricWeights(vec2_t a, vec2_t b, vec2_t c, vec2_t p)
     return ret;
 }
 
-static void drawTexel(int32_t x, int32_t y, vec2_t a, vec2_t b, vec2_t c, tex2_t ta, tex2_t tb, tex2_t tc, uint32_t *texture)
+static void drawTexel(int32_t x, int32_t y, vec4_t a, vec4_t b, vec4_t c, tex2_t ta, tex2_t tb, tex2_t tc, colour_t *texture)
 {
     vec2_t pointP = { x, y };
-    vec3_t weights = barycentricWeights(a, b, c, pointP);
+    vec2_t a2 = vec2FromVec4(a);
+    vec2_t b2 = vec2FromVec4(b);
+    vec2_t c2 = vec2FromVec4(c);
+
+    vec3_t weights = barycentricWeights(a2, b2, c2, pointP);
 
     double alpha = weights.x;
     double beta = weights.y;
@@ -143,8 +152,22 @@ static void drawTexel(int32_t x, int32_t y, vec2_t a, vec2_t b, vec2_t c, tex2_t
     double interpolatedU, interpolatedV;
     int32_t texX, texY;
 
-    interpolatedU = ta.u * alpha + tb.u * beta + tc.u * gamma;
-    interpolatedV = ta.v * alpha + tb.v * beta + tc.v * gamma;
+    if (doPerpectiveCorrection)
+    {
+        double interpolatedReciprocalW;
+
+        interpolatedU = (ta.u / a.w) * alpha + (tb.u / b.w) * beta + (tc.u / c.w) * gamma;
+        interpolatedV = (ta.v / a.w) * alpha + (tb.v / b.w) * beta + (tc.v / c.w) * gamma;
+        interpolatedReciprocalW = (1 / a.w) * alpha + (1 / b.w) * beta + (1 / c.w) * gamma;
+
+        interpolatedU /= interpolatedReciprocalW;
+        interpolatedV /= interpolatedReciprocalW;
+    }
+    else
+    {
+        interpolatedU = ta.u * alpha + tb.u * beta + tc.u * gamma;
+        interpolatedV = ta.v * alpha + tb.v * beta + tc.v * gamma;
+    }
 
     texX = abs((int32_t)(interpolatedU * textureWidth));
     texY = abs((int32_t)(interpolatedV * textureHeight));
@@ -163,25 +186,28 @@ void drawTextureTriangle(struct triangle_t *t)
     if (t->points[0].y > t->points[1].y)
     {
         doubleSwap(&t->points[0].x, &t->points[1].x); doubleSwap(&t->points[0].y, &t->points[1].y);
+        doubleSwap(&t->points[0].z, &t->points[1].z); doubleSwap(&t->points[0].w, &t->points[1].w);
         doubleSwap(&t->textureCoordinates[0].u, &t->textureCoordinates[1].u);
         doubleSwap(&t->textureCoordinates[0].v, &t->textureCoordinates[1].v);
     }
     if (t->points[1].y > t->points[2].y)
     {
         doubleSwap(&t->points[1].x, &t->points[2].x); doubleSwap(&t->points[1].y, &t->points[2].y);
+        doubleSwap(&t->points[1].z, &t->points[2].z); doubleSwap(&t->points[1].w, &t->points[2].w);
         doubleSwap(&t->textureCoordinates[1].u, &t->textureCoordinates[2].u);
         doubleSwap(&t->textureCoordinates[1].v, &t->textureCoordinates[2].v);
     }
     if (t->points[0].y > t->points[1].y)
     {
         doubleSwap(&t->points[0].x, &t->points[1].x); doubleSwap(&t->points[0].y, &t->points[1].y);
+        doubleSwap(&t->points[0].z, &t->points[1].z); doubleSwap(&t->points[0].w, &t->points[1].w);
         doubleSwap(&t->textureCoordinates[0].u, &t->textureCoordinates[1].u);
         doubleSwap(&t->textureCoordinates[0].v, &t->textureCoordinates[1].v);
     }
 
-    vec2_t a = t->points[0];
-    vec2_t b = t->points[1];
-    vec2_t c = t->points[2];
+    vec4_t a = t->points[0];
+    vec4_t b = t->points[1];
+    vec4_t c = t->points[2];
 
     /* Render the top part */
     double inverseSlope1 = 0;