1
0
Fork 0

Add bilinear filtering

master
Austin Morlan 4 years ago
parent 20402784f7
commit 21fb0058ad
Signed by: austin
GPG Key ID: FD6B27654AF5E348
  1. 3
      include/engine.h
  2. 6
      include/geometry.h
  3. 17
      src/engine.cpp
  4. 72
      src/geometry.cpp
  5. 8
      src/platform.cpp

@ -19,8 +19,7 @@ enum Engine_Input
ROTATE_Z_POS,
ROTATE_Z_NEG,
SCALE_UP,
SCALE_DOWN,
SHADING_TOGGLE
SCALE_DOWN
};

@ -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<TextureCoord> &uvs);
Engine_Buffer &buffer, Mesh_TransformedData &mesh,
Texture &texture, std::vector<TextureCoord> &uvs);
#define GEOMETRY_H

@ -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;
}
}

@ -66,8 +66,9 @@ void CullBackfaces(
}
void RenderMesh(Engine_Buffer &buffer, Mesh_TransformedData &mesh, bool smooth, Texture &texture,
std::vector<TextureCoord> &uvs)
void RenderMesh(
Engine_Buffer &buffer, Mesh_TransformedData &mesh,
Texture &texture, std::vector<TextureCoord> &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
ColorF32 shading =
(barycenter[0] * v0.color)
+ (barycenter[1] * v1.color)
+ (barycenter[2] * v2.color);
// 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;
}
// Bilinear filtering
float du = uInterp - u;
float dv = vInterp - v;
float duDiff = 1-du;
float dvDiff = 1-dv;
ColorU32 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;
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;
}

@ -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);

Loading…
Cancel
Save