From d44df852bbdcb58d634413d69eaa288a7b4573f3 Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Thu, 5 Feb 2026 17:16:39 -0800 Subject: Expose texture filter. --- include/swgfx.h | 7 ++++++- src/swgfx.c | 28 ++++++++++++++++------------ 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/include/swgfx.h b/include/swgfx.h index cdeefe8..e9e69b8 100644 --- a/include/swgfx.h +++ b/include/swgfx.h @@ -53,6 +53,11 @@ typedef sgRgba sgPixel; // TODO: Expose a macro to control the desired surface format. typedef sgBgra sgScreenPixel; +typedef enum sgTextureFilter { + sgNearest, + sgBilinear +} sgTextureFilter; + typedef struct sgImage { int width; int height; @@ -76,7 +81,7 @@ void sgOrtho (swgfx*, R left, R right, R top, R bottom, R near, R far); void sgPerspective(swgfx*, R fovy, R aspect, R near, R far); void sgViewport (swgfx*, int x0, int y0, int width, int height); -void sgTexture(swgfx*, const sgImage*); +void sgTexture(swgfx*, const sgImage*, sgTextureFilter); void sgClear(swgfx*); void sgPixels(swgfx*, size_t count, const sgVec2i* positions, sgPixel colour); diff --git a/src/swgfx.c b/src/swgfx.c index 85844e0..153a5f4 100644 --- a/src/swgfx.c +++ b/src/swgfx.c @@ -44,11 +44,12 @@ typedef struct swgfx { // Make it so that changing the model matrix only requires one matrix // multiplication (mvp = model * viewProj) and not two (mvp = model * view * projection) // before rendering the model's triangles. - sgMat4 viewProj; // View-projection matrix. - sgMat4 mvp; // Model-view-projection matrix. - const sgImage* texture; // User-specified texture. - sgImage defaultTexture; // A default for when no texture is provided. - sgPixel defaultPixel; // The single-pixel of the default texture. + sgMat4 viewProj; // View-projection matrix. + sgMat4 mvp; // Model-view-projection matrix. + const sgImage* texture; // User-specified texture. + sgTextureFilter textureFilter; // Filter method for the texture. + sgImage defaultTexture; // A default for when no texture is provided. + sgPixel defaultPixel; // The single-pixel of the default texture. } swgfx; static inline int mod(int a, int m) { return (m + (a % m)) % m; } @@ -359,10 +360,12 @@ static inline sgPixel FilterBilinear(const sgImage* texture, sgVec2 uv) { // TODO: Mipmapping. // TODO: Clamping and other addressing strategies. -static inline sgPixel Sample(const sgImage* texture, sgVec2 uv) { - // TODO: Add a member to sgImage that determines how it should be filtered. - //return FilterNearest(texture, uv); - return FilterBilinear(texture, uv); +static inline sgPixel Sample(const sgImage* texture, sgTextureFilter filter, sgVec2 uv) { + switch (filter) { + case sgNearest: return FilterNearest(texture, uv); + case sgBilinear: return FilterBilinear(texture, uv); + default: assert(false); return (sgPixel){0}; + } } static inline sgAABB2 TriangleAabb2(sgVec2 p0, sgVec2 p1, sgVec2 p2) { @@ -433,7 +436,7 @@ static void DrawTriangle2(swgfx* gfx, const sgTri2* const tri) { if ((bar.x >= 0) && (bar.y >= 0) && (bar.z >= 0)) { assert((bar.x + bar.y + bar.z - 1e7) <= 1.f); const sgVec2 uv = BarycentricInterp2(bar, tri->p0.uv, tri->p1.uv, tri->p2.uv); - const sgPixel colour = Sample(gfx->texture, uv); + const sgPixel colour = Sample(gfx->texture, gfx->textureFilter, uv); SetPixel(gfx, (sgVec2i){x,y}, colour); } } @@ -644,7 +647,7 @@ static void DrawTriangle3PostClip(swgfx* gfx, const sgTri4* const tri) { R* depth = Depth(gfx, x, y); if ((0.f <= p_depth) && (p_depth <= 1.f) && (p_depth <= *depth)) { *depth = p_depth; - const sgPixel colour = Sample(gfx->texture, uv); + const sgPixel colour = Sample(gfx->texture, gfx->textureFilter, uv); // TODO: When doing lighting, need to tone-map here and apply inverse // gamma here. //const sgPixel colour = {(uint8_t)(bar.x*255.f), (uint8_t)(bar.y*255.f), (uint8_t)(bar.z*255.f), 255}; @@ -800,10 +803,11 @@ void sgViewport(swgfx* gfx, int x0, int y0, int width, int height) { gfx->viewport = (sgViewport_t){x0, y0, width, height}; } -void sgTexture(swgfx* gfx, const sgImage* texture) { +void sgTexture(swgfx* gfx, const sgImage* texture, sgTextureFilter filter) { assert(gfx); assert(texture); gfx->texture = texture; + gfx->textureFilter = filter; } void sgClear(swgfx* gfx) { -- cgit v1.2.3