From 1ae1b370da0ce0cf8501b9e6be8c6ac25e249e1a Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Wed, 31 Dec 2025 14:46:33 -0800 Subject: Initial texturing changes --- src/swgfx.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 49 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/swgfx.c b/src/swgfx.c index c298fb4..612f82d 100644 --- a/src/swgfx.c +++ b/src/swgfx.c @@ -46,6 +46,9 @@ typedef struct swgfx { // before rendering the model's triangles. sgMat4 viewProj; // View-projection matrix. sgMat4 mvp; // Model-view-projection matrix. + const sgTexture_t* texture;// User-specified texture. + sgTexture_t defaultTexture; // A default for when no texture is provided. + sgPixel defaultPixel; // The single-pixel of the default texture. } swgfx; static inline R rmin(R a, R b) { return (a <= b) ? a : b; } @@ -265,6 +268,22 @@ void SetDepth(swgfx* gfx, const sgVec2i p, R depth) { *Depth(gfx, p.x, p.y) = depth; } +// TODO: Mipmapping. +sgPixel Sample(const sgTexture_t* texture, sgVec2 uv) { + assert(texture); + assert(texture->pixels); + // TODO: (1/2, 1/2) is the center of the pixel. Do we need to do something + // about it here? +#define INDEX(X,Y) texture->pixels[(Y) * texture->width + (X)] + // Doing a nearest sample for now. TODO: Other sampling strategies. + const int x = (int)(uv.x * (R)texture->width); + const int y = (int)(uv.y * (R)texture->height); + // Repeat for now. TODO: Clamping and other strategies. + const int xx = x % texture->width; + const int yy = y % texture->height; + return INDEX(xx,yy); +} + static inline sgAABB2 TriangleAabb2(sgVec2 p0, sgVec2 p1, sgVec2 p2) { return (sgAABB2){.pmin = min2(min2(p0, p1), p2), .pmax = max2(max2(p0, p1), p2)}; @@ -340,12 +359,16 @@ static void DrawTriangle2(swgfx* gfx, const sgTri3* const tri) { R* depth = Depth(gfx, x, y); if ((0.f <= z) && (z <= 1.f) && (z <= *depth)) { *depth = z; - const sgVec3 depths = (sgVec3){tri->p0.pos.z, tri->p1.pos.z, tri->p2.pos.z}; - const sgVec2 uv = PerspectiveInterp2(bar, depths, z, tri->p0.uv, tri->p1.uv, tri->p2.uv); - const int r = (int)(uv.x * 255.f); + const sgVec3 depths = (sgVec3){tri->p0.pos.z, tri->p1.pos.z, tri->p2.pos.z}; + const sgVec2 uv = PerspectiveInterp2(bar, depths, z, tri->p0.uv, tri->p1.uv, tri->p2.uv); + const sgPixel colour = Sample(gfx->texture, uv); + //const sgPixel colour = (sgPixel){255, 0, 255, 255}; + // TODO: When doing lighting, need to tone-map here. + /*const int r = (int)(uv.x * 255.f); const int g = (int)(uv.y * 255.f); - const sgVec2i pix = (sgVec2i){(int)x, (int)y}; - SetPixel(gfx, pix, (sgPixel){r, g, 255, 255}); + const sgPixel colour = (sgPixel){r, g, 255, 255};*/ + const sgVec2i pix = (sgVec2i){x,y}; + SetPixel(gfx, pix, colour); } } } @@ -436,6 +459,12 @@ swgfx* sgNew(int width, int height, void* mem) { gfx->dims = (sgVec2i){width, height}; gfx->colour = SG_ALLOC(&aligned, width * height, sgPixel); gfx->depth = SG_ALLOC(&aligned, width * height, R); + gfx->defaultPixel = (sgPixel){255, 255, 255, 255}; + gfx->defaultTexture = (sgTexture_t){ + .width = 1, + .height = 1, + .pixels = &gfx->defaultPixel, + }; return gfx; } @@ -446,7 +475,7 @@ void sgDel(swgfx** ppSwgfx) { } } -void sgPresent(swgfx* gfx, sgVec2i dimensions, sgPixel* screen) { +void sgPresent(swgfx* gfx, sgVec2i dimensions, sgScreenPixel* screen) { assert(gfx); assert(screen); // Integer scaling only. @@ -457,16 +486,18 @@ void sgPresent(swgfx* gfx, sgVec2i dimensions, sgPixel* screen) { const int sy = dimensions.y / gfx->dims.y; const sgPixel* src = gfx->colour; - sgPixel* dst = screen; - // Replicate each row 'sy' times. for (int y = 0; y < gfx->dims.y; ++y, src += gfx->dims.x) { - for (int yy = y*sy; yy < (y+1)*sy; ++yy) { - // Replicate each column 'sx' times. + // Replicate each row 'sy' times. + for (int yy = 0; yy < sy; ++yy) { const sgPixel* src_col = src; for (int x = 0; x < gfx->dims.x; ++x, ++src_col) { - for (int xx = x*sx; xx < (x+1)*sx; ++xx, ++dst) { - *dst = *src_col; + // Replicate each column 'sx' times. + for (int xx = 0; xx < sx; ++xx, ++screen) { + screen->r = src_col->r; + screen->g = src_col->g; + screen->b = src_col->b; + screen->a = src_col->a; } } } @@ -518,6 +549,12 @@ 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 sgTexture_t* texture) { + assert(gfx); + assert(texture); + gfx->texture = texture; +} + void sgClear(swgfx* gfx) { assert(gfx); const int N = gfx->dims.x * gfx->dims.y; -- cgit v1.2.3