summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author3gg <3gg@shellblade.net>2026-02-05 19:06:44 -0800
committer3gg <3gg@shellblade.net>2026-02-05 19:06:44 -0800
commit85a5ad70b7fa4844e37fe06463ea82d8e6f1abaf (patch)
tree3b2cea07437cd8d239cac5c843a7e67f7d8d0480
parentd44df852bbdcb58d634413d69eaa288a7b4573f3 (diff)
Expose functions for gamma correction
-rw-r--r--include/swgfx.h6
-rw-r--r--src/swgfx.c34
2 files changed, 38 insertions, 2 deletions
diff --git a/include/swgfx.h b/include/swgfx.h
index e9e69b8..9c3361d 100644
--- a/include/swgfx.h
+++ b/include/swgfx.h
@@ -72,7 +72,8 @@ void sgDel(swgfx**);
72 72
73// TODO: Write client app first, then implement the functions below in the C file. 73// TODO: Write client app first, then implement the functions below in the C file.
74 74
75void sgPresent(swgfx*, sgVec2i dimensions, sgScreenPixel* screen); 75sgPixel* sgColourBuffer(swgfx*);
76void sgPresent(swgfx*, sgVec2i dimensions, sgScreenPixel* screen);
76 77
77void sgModelId (swgfx*); 78void sgModelId (swgfx*);
78void sgModel (swgfx*, sgVec3 position, sgVec3 right, sgVec3 up, sgVec3 forward); 79void sgModel (swgfx*, sgVec3 position, sgVec3 right, sgVec3 up, sgVec3 forward);
@@ -94,4 +95,7 @@ void sgTriangleStrip (swgfx*, size_t count, const sgVec3*, const sgNormal*);
94void sgTrianglesIndexed(swgfx*, size_t numIndices, const sgIdx* indices, const sgVec3* positions, const sgVec2* texcoords); 95void sgTrianglesIndexed(swgfx*, size_t numIndices, const sgIdx* indices, const sgVec3* positions, const sgVec2* texcoords);
95void sgTrianglesIndexedNonUniform(swgfx*, size_t numTris, const sgTriIdx* tris, const sgVec3* positions, const sgVec2* texcoords); 96void sgTrianglesIndexedNonUniform(swgfx*, size_t numTris, const sgTriIdx* tris, const sgVec3* positions, const sgVec2* texcoords);
96 97
98void sgGamma (swgfx*, sgPixel*, int width, int height);
99void sgGammaInv(swgfx*, sgPixel*, int width, int height);
100
97void sgCheck(swgfx*); 101void sgCheck(swgfx*);
diff --git a/src/swgfx.c b/src/swgfx.c
index 153a5f4..bbf9a5b 100644
--- a/src/swgfx.c
+++ b/src/swgfx.c
@@ -78,6 +78,7 @@ static inline sgVec3 neg3(sgVec3 v) { return (sgVec3){-v.x, -v.y, -v.z}; }
78static inline sgVec3 sub3(sgVec3 a, sgVec3 b) { return (sgVec3){a.x - b.x, a.y - b.y, a.z - b.z}; } 78static inline sgVec3 sub3(sgVec3 a, sgVec3 b) { return (sgVec3){a.x - b.x, a.y - b.y, a.z - b.z}; }
79static inline sgVec3 div3(sgVec3 a, sgVec3 b) { return (sgVec3){a.x / b.x, a.y / b.y, a.z / b.z}; } 79static inline sgVec3 div3(sgVec3 a, sgVec3 b) { return (sgVec3){a.x / b.x, a.y / b.y, a.z / b.z}; }
80static inline sgVec3 scale3(sgVec3 v, R s) { return (sgVec3){v.x * s, v.y * s, v.z * s}; } 80static inline sgVec3 scale3(sgVec3 v, R s) { return (sgVec3){v.x * s, v.y * s, v.z * s}; }
81static inline sgVec3 exp3(sgVec3 v, R exp) { return (sgVec3){powf(v.x, exp), powf(v.y, exp), powf(v.z, exp)};}
81static inline R dot3(sgVec3 a, sgVec3 b) { return a.x * b.x + a.y * b.y + a.z * b.z; } 82static inline R dot3(sgVec3 a, sgVec3 b) { return a.x * b.x + a.y * b.y + a.z * b.z; }
82static inline R normsq3(sgVec3 v) { return v.x * v.x + v.y * v.y + v.z * v.z; } 83static inline R normsq3(sgVec3 v) { return v.x * v.x + v.y * v.y + v.z * v.z; }
83static inline R norm3 (sgVec3 v) { return (R)sqrt(normsq3(v)); } 84static inline R norm3 (sgVec3 v) { return (R)sqrt(normsq3(v)); }
@@ -268,11 +269,17 @@ static inline sgMat4 Mat4Perspective(R fovy, R aspect, R near, R far) {
268 0, 0, -1, 0); 269 0, 0, -1, 0);
269} 270}
270 271
272static inline sgVec3 PixelToVec3(sgPixel p) {
273 return (sgVec3){(R)p.r / 255.f, (R)p.g / 255.f, (R)p.b / 255.f};
274}
275static inline sgPixel Vec3ToPixel(sgVec3 p, R a) {
276 return (sgPixel){(uint8_t)(p.x * 255.f), (uint8_t)(p.y * 255.f), (uint8_t)(p.z * 255.f), (uint8_t)(a * 255.f)};
277}
271static inline sgVec4 PixelToVec4(sgPixel p) { 278static inline sgVec4 PixelToVec4(sgPixel p) {
272 return (sgVec4){(R)p.r / 255.f, (R)p.g / 255.f, (R)p.b / 255.f, (R)p.a / 255.f}; 279 return (sgVec4){(R)p.r / 255.f, (R)p.g / 255.f, (R)p.b / 255.f, (R)p.a / 255.f};
273} 280}
274static inline sgPixel Vec4ToPixel(sgVec4 p) { 281static inline sgPixel Vec4ToPixel(sgVec4 p) {
275 return (sgPixel){(int)(p.x * 255.f), (int)(p.y * 255.f), (int)(p.z * 255.f), (int)(p.w * 255.f)}; 282 return (sgPixel){(uint8_t)(p.x * 255.f), (uint8_t)(p.y * 255.f), (uint8_t)(p.z * 255.f), (uint8_t)(p.w * 255.f)};
276} 283}
277 284
278#ifndef _NDEBUG 285#ifndef _NDEBUG
@@ -729,6 +736,11 @@ void sgDel(swgfx** ppSwgfx) {
729 } 736 }
730} 737}
731 738
739sgPixel* sgColourBuffer(swgfx* gfx) {
740 assert(gfx);
741 return gfx->colour;
742}
743
732void sgPresent(swgfx* gfx, sgVec2i dimensions, sgScreenPixel* screen) { 744void sgPresent(swgfx* gfx, sgVec2i dimensions, sgScreenPixel* screen) {
733 assert(gfx); 745 assert(gfx);
734 assert(screen); 746 assert(screen);
@@ -891,6 +903,26 @@ void sgTrianglesIndexedNonUniform(swgfx* gfx, size_t numTris, const sgTriIdx* tr
891 } 903 }
892} 904}
893 905
906static void ImageExp(sgPixel* pixels, int width, int height, R exp) {
907 assert(pixels);
908 for (int i = 0; i < width * height; ++i) {
909 sgPixel* p = &pixels[i];
910 *p = Vec3ToPixel(exp3(PixelToVec3(*p), exp), p->a);
911 }
912}
913
914void sgGamma(swgfx* gfx, sgPixel* pixels, int width, int height) {
915 assert(gfx);
916 assert(pixels);
917 ImageExp(pixels, width, height, 2.2f);
918}
919
920void sgGammaInv(swgfx* gfx, sgPixel* pixels, int width, int height) {
921 assert(gfx);
922 assert(pixels);
923 ImageExp(pixels, width, height, 1.0f/2.2f);
924}
925
894static bool ViewportWithinBuffer(swgfx* gfx) { 926static bool ViewportWithinBuffer(swgfx* gfx) {
895 assert(gfx); 927 assert(gfx);
896 const sgViewport_t vp = gfx->viewport; 928 const sgViewport_t vp = gfx->viewport;