summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/swgfx.h7
-rw-r--r--src/swgfx.c28
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;
53// TODO: Expose a macro to control the desired surface format. 53// TODO: Expose a macro to control the desired surface format.
54typedef sgBgra sgScreenPixel; 54typedef sgBgra sgScreenPixel;
55 55
56typedef enum sgTextureFilter {
57 sgNearest,
58 sgBilinear
59} sgTextureFilter;
60
56typedef struct sgImage { 61typedef struct sgImage {
57 int width; 62 int width;
58 int height; 63 int height;
@@ -76,7 +81,7 @@ void sgOrtho (swgfx*, R left, R right, R top, R bottom, R near, R far);
76void sgPerspective(swgfx*, R fovy, R aspect, R near, R far); 81void sgPerspective(swgfx*, R fovy, R aspect, R near, R far);
77void sgViewport (swgfx*, int x0, int y0, int width, int height); 82void sgViewport (swgfx*, int x0, int y0, int width, int height);
78 83
79void sgTexture(swgfx*, const sgImage*); 84void sgTexture(swgfx*, const sgImage*, sgTextureFilter);
80 85
81void sgClear(swgfx*); 86void sgClear(swgfx*);
82void sgPixels(swgfx*, size_t count, const sgVec2i* positions, sgPixel colour); 87void 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 {
44 // Make it so that changing the model matrix only requires one matrix 44 // Make it so that changing the model matrix only requires one matrix
45 // multiplication (mvp = model * viewProj) and not two (mvp = model * view * projection) 45 // multiplication (mvp = model * viewProj) and not two (mvp = model * view * projection)
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 sgImage* texture; // User-specified texture. 49 const sgImage* texture; // User-specified texture.
50 sgImage defaultTexture; // A default for when no texture is provided. 50 sgTextureFilter textureFilter; // Filter method for the texture.
51 sgPixel defaultPixel; // The single-pixel of the default texture. 51 sgImage defaultTexture; // A default for when no texture is provided.
52 sgPixel defaultPixel; // The single-pixel of the default texture.
52} swgfx; 53} swgfx;
53 54
54static inline int mod(int a, int m) { return (m + (a % m)) % m; } 55static 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) {
359 360
360// TODO: Mipmapping. 361// TODO: Mipmapping.
361// TODO: Clamping and other addressing strategies. 362// TODO: Clamping and other addressing strategies.
362static inline sgPixel Sample(const sgImage* texture, sgVec2 uv) { 363static inline sgPixel Sample(const sgImage* texture, sgTextureFilter filter, sgVec2 uv) {
363 // TODO: Add a member to sgImage that determines how it should be filtered. 364 switch (filter) {
364 //return FilterNearest(texture, uv); 365 case sgNearest: return FilterNearest(texture, uv);
365 return FilterBilinear(texture, uv); 366 case sgBilinear: return FilterBilinear(texture, uv);
367 default: assert(false); return (sgPixel){0};
368 }
366} 369}
367 370
368static inline sgAABB2 TriangleAabb2(sgVec2 p0, sgVec2 p1, sgVec2 p2) { 371static inline sgAABB2 TriangleAabb2(sgVec2 p0, sgVec2 p1, sgVec2 p2) {
@@ -433,7 +436,7 @@ static void DrawTriangle2(swgfx* gfx, const sgTri2* const tri) {
433 if ((bar.x >= 0) && (bar.y >= 0) && (bar.z >= 0)) { 436 if ((bar.x >= 0) && (bar.y >= 0) && (bar.z >= 0)) {
434 assert((bar.x + bar.y + bar.z - 1e7) <= 1.f); 437 assert((bar.x + bar.y + bar.z - 1e7) <= 1.f);
435 const sgVec2 uv = BarycentricInterp2(bar, tri->p0.uv, tri->p1.uv, tri->p2.uv); 438 const sgVec2 uv = BarycentricInterp2(bar, tri->p0.uv, tri->p1.uv, tri->p2.uv);
436 const sgPixel colour = Sample(gfx->texture, uv); 439 const sgPixel colour = Sample(gfx->texture, gfx->textureFilter, uv);
437 SetPixel(gfx, (sgVec2i){x,y}, colour); 440 SetPixel(gfx, (sgVec2i){x,y}, colour);
438 } 441 }
439 } 442 }
@@ -644,7 +647,7 @@ static void DrawTriangle3PostClip(swgfx* gfx, const sgTri4* const tri) {
644 R* depth = Depth(gfx, x, y); 647 R* depth = Depth(gfx, x, y);
645 if ((0.f <= p_depth) && (p_depth <= 1.f) && (p_depth <= *depth)) { 648 if ((0.f <= p_depth) && (p_depth <= 1.f) && (p_depth <= *depth)) {
646 *depth = p_depth; 649 *depth = p_depth;
647 const sgPixel colour = Sample(gfx->texture, uv); 650 const sgPixel colour = Sample(gfx->texture, gfx->textureFilter, uv);
648 // TODO: When doing lighting, need to tone-map here and apply inverse 651 // TODO: When doing lighting, need to tone-map here and apply inverse
649 // gamma here. 652 // gamma here.
650 //const sgPixel colour = {(uint8_t)(bar.x*255.f), (uint8_t)(bar.y*255.f), (uint8_t)(bar.z*255.f), 255}; 653 //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) {
800 gfx->viewport = (sgViewport_t){x0, y0, width, height}; 803 gfx->viewport = (sgViewport_t){x0, y0, width, height};
801} 804}
802 805
803void sgTexture(swgfx* gfx, const sgImage* texture) { 806void sgTexture(swgfx* gfx, const sgImage* texture, sgTextureFilter filter) {
804 assert(gfx); 807 assert(gfx);
805 assert(texture); 808 assert(texture);
806 gfx->texture = texture; 809 gfx->texture = texture;
810 gfx->textureFilter = filter;
807} 811}
808 812
809void sgClear(swgfx* gfx) { 813void sgClear(swgfx* gfx) {