From ba68f22bee03922760ed78b67761c3a20b3306ff Mon Sep 17 00:00:00 2001 From: Austin Morlan Date: Wed, 19 Sep 2018 19:16:14 -0700 Subject: [PATCH] Add alpha blending of transparent textures --- src/engine.cpp | 14 ++++++------ src/loader.cpp | 9 +++++--- src/render.cpp | 59 +++++++++++++++++++++++++++++++++++--------------- 3 files changed, 54 insertions(+), 28 deletions(-) diff --git a/src/engine.cpp b/src/engine.cpp index 0cf0e7e..8ff18c0 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -64,7 +64,7 @@ int EngineInit(char *objFilename, char *mtlFilename) // Mesh configuration - mesh.position.z = 175; + mesh.position.z = 50; mesh.position.y = -175; mesh.scale = 1.0f; @@ -152,29 +152,29 @@ static void CheckInputs(uint32_t input) if (CHECK_BIT(input, ROTATE_X_POS)) { - mesh.position.x += 10; + mesh.rotation.x += 0.10f; } else if (CHECK_BIT(input, ROTATE_X_NEG)) { - mesh.position.x -= 10; + mesh.rotation.x -= 0.10f; } if (CHECK_BIT(input, ROTATE_Y_POS)) { - mesh.position.y += 10; + mesh.rotation.y += 0.10f; } else if (CHECK_BIT(input, ROTATE_Y_NEG)) { - mesh.position.y -= 10; + mesh.rotation.y -= 0.10f; } if (CHECK_BIT(input, ROTATE_Z_POS)) { - mesh.position.z += 10; + mesh.rotation.z += 0.10f; } else if (CHECK_BIT(input, ROTATE_Z_NEG)) { - mesh.position.z -= 10; + mesh.rotation.z -= 0.10f; } if (CHECK_BIT(input, SCALE_UP)) diff --git a/src/loader.cpp b/src/loader.cpp index efc7e78..0214108 100644 --- a/src/loader.cpp +++ b/src/loader.cpp @@ -8,7 +8,7 @@ // STATIC PROTOTYPES -static int LoadTexture(char *filename, Texture &texture); +static int LoadTexture(char *filename, Texture &texture, float opacity); #pragma pack(push, 1) @@ -194,7 +194,9 @@ int ParseMTL(char *filename, EngineMemory &memory) { char *textureFilename = data; textureFilename[strcspn(textureFilename, "\r\n")] = 0; - LoadTexture(textureFilename, textures.data[materialIndex]); + LoadTexture( + textureFilename, textures.data[materialIndex], + materials.data[materialIndex].opacity); } } } @@ -204,7 +206,7 @@ int ParseMTL(char *filename, EngineMemory &memory) return 0; } -static int LoadTexture(char *filename, Texture &texture) +static int LoadTexture(char *filename, Texture &texture, float opacity) { FILE *fp = fopen(filename, "r"); if (fp == NULL) @@ -227,6 +229,7 @@ static int LoadTexture(char *filename, Texture &texture) fread(&texture.texels[y][x].b, 1, 1, fp); fread(&texture.texels[y][x].g, 1, 1, fp); fread(&texture.texels[y][x].r, 1, 1, fp); + texture.texels[y][x].a = (uint8_t)(255 * opacity); } // Discard padding byte diff --git a/src/render.cpp b/src/render.cpp index 44006a1..dadeaef 100644 --- a/src/render.cpp +++ b/src/render.cpp @@ -114,24 +114,32 @@ void Render(EngineBuffer &buffer, EngineMemory &memory) 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); + ColorU32 color = + { + (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); + (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); + (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), + + (uint8_t) + (duDiff * dvDiff * texture.texels[v][u].a + + du * dvDiff * texture.texels[v][u+1].a + + du * dv * texture.texels[v+1][u+1].a + + duDiff * dv * texture.texels[v+1][u].a) + }; // Perform Gouraud shading on the texture @@ -145,7 +153,7 @@ void Render(EngineBuffer &buffer, EngineMemory &memory) + (barycenter[2] * c2); - // Ensure no color channel exceeds 1.0 + // Ensure no color channel exceeds max ScaleColor(shading); @@ -154,6 +162,7 @@ void Render(EngineBuffer &buffer, EngineMemory &memory) color.g *= shading.g; color.r *= shading.r; + // Interpolate 1/z for the z-buffer float zInv = 1.0f / @@ -165,7 +174,21 @@ void Render(EngineBuffer &buffer, EngineMemory &memory) // Draw the pixel if it's closer than what's in the z-buffer if (zInv > memory.zbuffer[y][x]) { - DrawPixel(buffer.buffer, buffer.width, color.u32, x, y); + ColorU32 *pixel = (ColorU32*)&buffer.buffer[y*buffer.width+x]; + + float alpha = color.a / 255.0f; + float alphaDiff = 1.0f - alpha; + + // Blend new color with the existing color + ColorU32 blended = + { + (uint8_t)((alpha * color.b) + (alphaDiff * pixel->b)), + (uint8_t)((alpha * color.g) + (alphaDiff * pixel->g)), + (uint8_t)((alpha * color.r) + (alphaDiff * pixel->r)), + (uint8_t)((alpha * color.a) + (alphaDiff * pixel->a)) + }; + + DrawPixel(buffer.buffer, buffer.width, blended.u32, x, y); memory.zbuffer[y][x] = zInv; }