diff options
Diffstat (limited to 'src/swgfx.c')
| -rw-r--r-- | src/swgfx.c | 61 |
1 files changed, 49 insertions, 12 deletions
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 { | |||
| 46 | // before rendering the model's triangles. | 46 | // before rendering the model's triangles. |
| 47 | sgMat4 viewProj; // View-projection matrix. | 47 | sgMat4 viewProj; // View-projection matrix. |
| 48 | sgMat4 mvp; // Model-view-projection matrix. | 48 | sgMat4 mvp; // Model-view-projection matrix. |
| 49 | const sgTexture_t* texture;// User-specified texture. | ||
| 50 | sgTexture_t defaultTexture; // A default for when no texture is provided. | ||
| 51 | sgPixel defaultPixel; // The single-pixel of the default texture. | ||
| 49 | } swgfx; | 52 | } swgfx; |
| 50 | 53 | ||
| 51 | static inline R rmin(R a, R b) { return (a <= b) ? a : b; } | 54 | 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) { | |||
| 265 | *Depth(gfx, p.x, p.y) = depth; | 268 | *Depth(gfx, p.x, p.y) = depth; |
| 266 | } | 269 | } |
| 267 | 270 | ||
| 271 | // TODO: Mipmapping. | ||
| 272 | sgPixel Sample(const sgTexture_t* texture, sgVec2 uv) { | ||
| 273 | assert(texture); | ||
| 274 | assert(texture->pixels); | ||
| 275 | // TODO: (1/2, 1/2) is the center of the pixel. Do we need to do something | ||
| 276 | // about it here? | ||
| 277 | #define INDEX(X,Y) texture->pixels[(Y) * texture->width + (X)] | ||
| 278 | // Doing a nearest sample for now. TODO: Other sampling strategies. | ||
| 279 | const int x = (int)(uv.x * (R)texture->width); | ||
| 280 | const int y = (int)(uv.y * (R)texture->height); | ||
| 281 | // Repeat for now. TODO: Clamping and other strategies. | ||
| 282 | const int xx = x % texture->width; | ||
| 283 | const int yy = y % texture->height; | ||
| 284 | return INDEX(xx,yy); | ||
| 285 | } | ||
| 286 | |||
| 268 | static inline sgAABB2 TriangleAabb2(sgVec2 p0, sgVec2 p1, sgVec2 p2) { | 287 | static inline sgAABB2 TriangleAabb2(sgVec2 p0, sgVec2 p1, sgVec2 p2) { |
| 269 | return (sgAABB2){.pmin = min2(min2(p0, p1), p2), | 288 | return (sgAABB2){.pmin = min2(min2(p0, p1), p2), |
| 270 | .pmax = max2(max2(p0, p1), p2)}; | 289 | .pmax = max2(max2(p0, p1), p2)}; |
| @@ -340,12 +359,16 @@ static void DrawTriangle2(swgfx* gfx, const sgTri3* const tri) { | |||
| 340 | R* depth = Depth(gfx, x, y); | 359 | R* depth = Depth(gfx, x, y); |
| 341 | if ((0.f <= z) && (z <= 1.f) && (z <= *depth)) { | 360 | if ((0.f <= z) && (z <= 1.f) && (z <= *depth)) { |
| 342 | *depth = z; | 361 | *depth = z; |
| 343 | const sgVec3 depths = (sgVec3){tri->p0.pos.z, tri->p1.pos.z, tri->p2.pos.z}; | 362 | const sgVec3 depths = (sgVec3){tri->p0.pos.z, tri->p1.pos.z, tri->p2.pos.z}; |
| 344 | const sgVec2 uv = PerspectiveInterp2(bar, depths, z, tri->p0.uv, tri->p1.uv, tri->p2.uv); | 363 | const sgVec2 uv = PerspectiveInterp2(bar, depths, z, tri->p0.uv, tri->p1.uv, tri->p2.uv); |
| 345 | const int r = (int)(uv.x * 255.f); | 364 | const sgPixel colour = Sample(gfx->texture, uv); |
| 365 | //const sgPixel colour = (sgPixel){255, 0, 255, 255}; | ||
| 366 | // TODO: When doing lighting, need to tone-map here. | ||
| 367 | /*const int r = (int)(uv.x * 255.f); | ||
| 346 | const int g = (int)(uv.y * 255.f); | 368 | const int g = (int)(uv.y * 255.f); |
| 347 | const sgVec2i pix = (sgVec2i){(int)x, (int)y}; | 369 | const sgPixel colour = (sgPixel){r, g, 255, 255};*/ |
| 348 | SetPixel(gfx, pix, (sgPixel){r, g, 255, 255}); | 370 | const sgVec2i pix = (sgVec2i){x,y}; |
| 371 | SetPixel(gfx, pix, colour); | ||
| 349 | } | 372 | } |
| 350 | } | 373 | } |
| 351 | } | 374 | } |
| @@ -436,6 +459,12 @@ swgfx* sgNew(int width, int height, void* mem) { | |||
| 436 | gfx->dims = (sgVec2i){width, height}; | 459 | gfx->dims = (sgVec2i){width, height}; |
| 437 | gfx->colour = SG_ALLOC(&aligned, width * height, sgPixel); | 460 | gfx->colour = SG_ALLOC(&aligned, width * height, sgPixel); |
| 438 | gfx->depth = SG_ALLOC(&aligned, width * height, R); | 461 | gfx->depth = SG_ALLOC(&aligned, width * height, R); |
| 462 | gfx->defaultPixel = (sgPixel){255, 255, 255, 255}; | ||
| 463 | gfx->defaultTexture = (sgTexture_t){ | ||
| 464 | .width = 1, | ||
| 465 | .height = 1, | ||
| 466 | .pixels = &gfx->defaultPixel, | ||
| 467 | }; | ||
| 439 | return gfx; | 468 | return gfx; |
| 440 | } | 469 | } |
| 441 | 470 | ||
| @@ -446,7 +475,7 @@ void sgDel(swgfx** ppSwgfx) { | |||
| 446 | } | 475 | } |
| 447 | } | 476 | } |
| 448 | 477 | ||
| 449 | void sgPresent(swgfx* gfx, sgVec2i dimensions, sgPixel* screen) { | 478 | void sgPresent(swgfx* gfx, sgVec2i dimensions, sgScreenPixel* screen) { |
| 450 | assert(gfx); | 479 | assert(gfx); |
| 451 | assert(screen); | 480 | assert(screen); |
| 452 | // Integer scaling only. | 481 | // Integer scaling only. |
| @@ -457,16 +486,18 @@ void sgPresent(swgfx* gfx, sgVec2i dimensions, sgPixel* screen) { | |||
| 457 | const int sy = dimensions.y / gfx->dims.y; | 486 | const int sy = dimensions.y / gfx->dims.y; |
| 458 | 487 | ||
| 459 | const sgPixel* src = gfx->colour; | 488 | const sgPixel* src = gfx->colour; |
| 460 | sgPixel* dst = screen; | ||
| 461 | 489 | ||
| 462 | // Replicate each row 'sy' times. | ||
| 463 | for (int y = 0; y < gfx->dims.y; ++y, src += gfx->dims.x) { | 490 | for (int y = 0; y < gfx->dims.y; ++y, src += gfx->dims.x) { |
| 464 | for (int yy = y*sy; yy < (y+1)*sy; ++yy) { | 491 | // Replicate each row 'sy' times. |
| 465 | // Replicate each column 'sx' times. | 492 | for (int yy = 0; yy < sy; ++yy) { |
| 466 | const sgPixel* src_col = src; | 493 | const sgPixel* src_col = src; |
| 467 | for (int x = 0; x < gfx->dims.x; ++x, ++src_col) { | 494 | for (int x = 0; x < gfx->dims.x; ++x, ++src_col) { |
| 468 | for (int xx = x*sx; xx < (x+1)*sx; ++xx, ++dst) { | 495 | // Replicate each column 'sx' times. |
| 469 | *dst = *src_col; | 496 | for (int xx = 0; xx < sx; ++xx, ++screen) { |
| 497 | screen->r = src_col->r; | ||
| 498 | screen->g = src_col->g; | ||
| 499 | screen->b = src_col->b; | ||
| 500 | screen->a = src_col->a; | ||
| 470 | } | 501 | } |
| 471 | } | 502 | } |
| 472 | } | 503 | } |
| @@ -518,6 +549,12 @@ void sgViewport(swgfx* gfx, int x0, int y0, int width, int height) { | |||
| 518 | gfx->viewport = (sgViewport_t){x0, y0, width, height}; | 549 | gfx->viewport = (sgViewport_t){x0, y0, width, height}; |
| 519 | } | 550 | } |
| 520 | 551 | ||
| 552 | void sgTexture(swgfx* gfx, const sgTexture_t* texture) { | ||
| 553 | assert(gfx); | ||
| 554 | assert(texture); | ||
| 555 | gfx->texture = texture; | ||
| 556 | } | ||
| 557 | |||
| 521 | void sgClear(swgfx* gfx) { | 558 | void sgClear(swgfx* gfx) { |
| 522 | assert(gfx); | 559 | assert(gfx); |
| 523 | const int N = gfx->dims.x * gfx->dims.y; | 560 | const int N = gfx->dims.x * gfx->dims.y; |
