From 21fb0058add4cb01f43c8431e3c9a196703bc5d4 Mon Sep 17 00:00:00 2001 From: Austin Morlan Date: Thu, 13 Sep 2018 19:19:59 -0700 Subject: [PATCH] Add bilinear filtering --- include/engine.h | 3 +- include/geometry.h | 6 ++-- src/engine.cpp | 17 +++-------- src/geometry.cpp | 74 ++++++++++++++++++++++++++++------------------ src/platform.cpp | 8 ----- 5 files changed, 54 insertions(+), 54 deletions(-) diff --git a/include/engine.h b/include/engine.h index 8221e4c..bb9d214 100644 --- a/include/engine.h +++ b/include/engine.h @@ -19,8 +19,7 @@ enum Engine_Input ROTATE_Z_POS, ROTATE_Z_NEG, SCALE_UP, - SCALE_DOWN, - SHADING_TOGGLE + SCALE_DOWN }; diff --git a/include/geometry.h b/include/geometry.h index 792cfbf..8a3e6d8 100644 --- a/include/geometry.h +++ b/include/geometry.h @@ -10,6 +10,7 @@ // STRUCTURES struct Material { + bool smooth; ColorF32 kAmbient; ColorF32 kDiffuse; }; @@ -75,7 +76,6 @@ struct Mesh float scale; Material material; - bool smooth; Mesh_LocalData local; Mesh_TransformedData transformed; @@ -88,8 +88,8 @@ void CullBackfaces( Point &camPosition); void RenderMesh( - Engine_Buffer &buffer, Mesh_TransformedData &mesh, bool smooth, Texture &texture, - std::vector &uvs); + Engine_Buffer &buffer, Mesh_TransformedData &mesh, + Texture &texture, std::vector &uvs); #define GEOMETRY_H diff --git a/src/engine.cpp b/src/engine.cpp index 4e06749..04396c1 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -35,6 +35,7 @@ int Engine_Init(Engine_Buffer &buffer, char *filename) mesh.position.z = 250; mesh.material.kDiffuse = {1.0,1.0,1.0,1.0}; mesh.material.kAmbient = {1.0,1.0,1.0,1.0}; + mesh.material.smooth = true; camera.SetFOV(90.0f, buffer.width, buffer.height); @@ -53,8 +54,7 @@ void Engine_Render(Engine_Buffer &buffer, uint32_t input) // Clear the z-buffer - unsigned long bufferSize = (unsigned long)(buffer.width * buffer.height); - memset(buffer.zbuffer, 0, bufferSize * sizeof(float)); + memset(buffer.zbuffer, 0, sizeof(float) * (size_t)(buffer.width * buffer.height)); // Local space to world space @@ -78,7 +78,7 @@ void Engine_Render(Engine_Buffer &buffer, uint32_t input) // Color the vertices for Gouraud shading - if (mesh.smooth) + if (mesh.material.smooth) { for (size_t f = 0; f < mesh.transformed.faces.size(); ++f) { @@ -135,7 +135,7 @@ void Engine_Render(Engine_Buffer &buffer, uint32_t input) mesh.transformed.verts[v].point.z /= mesh.transformed.verts[v].point.w; } - RenderMesh(buffer, mesh.transformed, mesh.smooth, texture, mesh.local.uvs); + RenderMesh(buffer, mesh.transformed, texture, mesh.local.uvs); } void Engine_Shutdown(void) @@ -208,13 +208,4 @@ static void CheckInputs(uint32_t input) { mesh.scale -= 0.1f; } - - if (CHECK_BIT(input, SHADING_TOGGLE)) - { - mesh.smooth = true; - } - else - { - mesh.smooth = false; - } } diff --git a/src/geometry.cpp b/src/geometry.cpp index 967755a..a598e71 100644 --- a/src/geometry.cpp +++ b/src/geometry.cpp @@ -66,8 +66,9 @@ void CullBackfaces( } -void RenderMesh(Engine_Buffer &buffer, Mesh_TransformedData &mesh, bool smooth, Texture &texture, - std::vector &uvs) +void RenderMesh( + Engine_Buffer &buffer, Mesh_TransformedData &mesh, + Texture &texture, std::vector &uvs) { for(size_t f = 0; f < mesh.faces.size(); ++f) { @@ -138,37 +139,55 @@ void RenderMesh(Engine_Buffer &buffer, Mesh_TransformedData &mesh, bool smooth, // Interpolate U and V - float u = ((a * t0.u) + (b * t1.u) + (c * t2.u)) * abc; - float v = ((a * t0.v) + (b * t1.v) + (c * t2.v)) * abc; + float uInterp = ((a * t0.u) + (b * t1.u) + (c * t2.u)) * abc; + float vInterp = ((a * t0.v) + (b * t1.v) + (c * t2.v)) * abc; // Convert U and V to pixels in the texture image - unsigned int uPixel = (unsigned int)(u * texture.width); - unsigned int vPixel = (unsigned int)(v * texture.height); + uInterp *= texture.width; + vInterp *= texture.height; + unsigned int u = (unsigned int)uInterp; + unsigned int v = (unsigned int)vInterp; - ColorF32 shading; - - // Gouraud shading - interpolate color based on vertices - if (smooth) - { - shading = - (barycenter[0] * v0.color) - + (barycenter[1] * v1.color) - + (barycenter[2] * v2.color); - } - // Flat shading - base color on single face color - else - { - shading = mesh.faces[f].color; - } + // Gouraud shading + ColorF32 shading = + (barycenter[0] * v0.color) + + (barycenter[1] * v1.color) + + (barycenter[2] * v2.color); - // Shade the texel with lighting calculations - ColorU32 texel = texture.texels[vPixel][uPixel]; - texel.r *= shading.r; - texel.g *= shading.g; - texel.b *= shading.b; + // Bilinear filtering + float du = uInterp - u; + float dv = vInterp - v; + float duDiff = 1-du; + float dvDiff = 1-dv; + + ColorU32 color; + + color.b = (uint8_t) + (duDiff * dvDiff * texture.texels[v][u].b + + du * dvDiff * texture.texels[v][u+1].b + + du * dv * texture.texels[v+1][u+1].b + + duDiff * dv * texture.texels[v+1][u].b); + + color.g = (uint8_t) + (duDiff * dvDiff * texture.texels[v][u].g + + du * dvDiff * texture.texels[v][u+1].g + + du * dv * texture.texels[v+1][u+1].g + + duDiff * dv * texture.texels[v+1][u].g); + + color.r = (uint8_t) + (duDiff * dvDiff * texture.texels[v][u].r + + du * dvDiff * texture.texels[v][u+1].r + + du * dv * texture.texels[v+1][u+1].r + + duDiff * dv * texture.texels[v+1][u].r); + + + // Shade the texture with the light calculations + color.b *= shading.b; + color.g *= shading.g; + color.r *= shading.r; // Interpolate 1/z for the z-buffer @@ -179,12 +198,11 @@ void RenderMesh(Engine_Buffer &buffer, Mesh_TransformedData &mesh, bool smooth, + (barycenter[2] * v2.point.w)); - // Draw the pixel if it's closer than what's in the z-buffer int pixel = (y * buffer.width + x); if (zInv > buffer.zbuffer[pixel]) { - DrawPixel(buffer.buffer, buffer.width, texel.u32, x, y); + DrawPixel(buffer.buffer, buffer.width, color.u32, x, y); buffer.zbuffer[pixel] = zInv; } diff --git a/src/platform.cpp b/src/platform.cpp index 61339a0..bd1bf8f 100644 --- a/src/platform.cpp +++ b/src/platform.cpp @@ -169,10 +169,6 @@ static void HandleEvent( { SET_BIT(platform.input, ROTATE_Y_NEG); } break; - case SDLK_g: - { - SET_BIT(platform.input, SHADING_TOGGLE); - } break; case SDLK_UP: { SET_BIT(platform.input, SCALE_UP); @@ -235,10 +231,6 @@ static void HandleEvent( { CLEAR_BIT(platform.input, ROTATE_Y_NEG); } break; - case SDLK_g: - { - CLEAR_BIT(platform.input, SHADING_TOGGLE); - } break; case SDLK_UP: { CLEAR_BIT(platform.input, SCALE_UP);