From 90d40f283f6e7a8a1c57849841ddee11f362d95e Mon Sep 17 00:00:00 2001 From: kkard2 Date: Sun, 14 Sep 2025 10:14:08 +0200 Subject: refactored everything procrastination experience --- examples/line.c | 8 +- examples/rainbow.c | 10 +- examples/rects.c | 6 +- examples/texture.c | 20 +-- examples/triangles.c | 2 +- platform_win32.c | 19 ++- run.bat | 2 +- sponge.h | 387 +++++++++++++++++++++++++++++---------------------- 8 files changed, 261 insertions(+), 193 deletions(-) diff --git a/examples/line.c b/examples/line.c index 31724a9..71d7492 100644 --- a/examples/line.c +++ b/examples/line.c @@ -10,7 +10,7 @@ static float angle = 0.0f; void init() {} void draw_frame(sponge_Texture c) { - sponge_clear(c, 0xFF000000); + sponge_clear(c, sponge_color32_make(0xFF000000)); angle += SPEED; float x = sinf(angle); @@ -19,7 +19,7 @@ void draw_frame(sponge_Texture c) { sponge_draw_line( c, - half + (int32_t)( x * (float)half), half + (int32_t)( y * (float)half), - half + (int32_t)(-x * (float)half), half + (int32_t)(-y * (float)half), - 0xFFFF00FF); + sponge_vec2i_make(half + (int32_t)( x * (float)half), half + (int32_t)( y * (float)half)), + sponge_vec2i_make(half + (int32_t)(-x * (float)half), half + (int32_t)(-y * (float)half)), + sponge_color32_make(0xFFFF00FF)); } diff --git a/examples/rainbow.c b/examples/rainbow.c index 31657ff..8439b0b 100644 --- a/examples/rainbow.c +++ b/examples/rainbow.c @@ -15,10 +15,10 @@ void draw_frame(sponge_Texture c) { float gf = (sinf(angle + (PI * 2.0f / 3.0f)) + 1.0f) * 255.0f / 2.0f; float bf = (sinf(angle + (PI * 4.0f / 3.0f)) + 1.0f) * 255.0f / 2.0f; - int r = (((int)rf) & 0xFF) << 16; - int g = (((int)gf) & 0xFF) << 8; - int b = (((int)bf) & 0xFF) << 0; - - uint32_t color = 0xFF000000 | r | g | b; + sponge_Color32 color; + color.a = 0xFF; + color.r = (((int)rf) & 0xFF); + color.g = (((int)gf) & 0xFF); + color.b = (((int)bf) & 0xFF); sponge_clear(c, color); } diff --git a/examples/rects.c b/examples/rects.c index 293f833..48cf5ba 100644 --- a/examples/rects.c +++ b/examples/rects.c @@ -7,7 +7,7 @@ void init() {} void draw_frame(sponge_Texture c) { assert(c.width > 140 + 20); assert(c.height > 70 + 40); - sponge_clear(c, 0xFF000000); - sponge_draw_rect(c, 80, 70, 80 + 20, 70 + 40, 0xFFFF00FF); - sponge_draw_rect(c, 140, 70, 140 + 20, 70 + 40, 0xFFFF00FF); + sponge_clear(c, sponge_color32_make(0xFF000000)); + sponge_draw_rect(c, sponge_vec2i_make(80, 70), sponge_vec2i_make(80 + 20, 70 + 40), sponge_color32_make(0xFFFF00FF)); + sponge_draw_rect(c, sponge_vec2i_make(140, 70), sponge_vec2i_make(140 + 20, 70 + 40), sponge_color32_make(0xFFFF00FF)); } diff --git a/examples/texture.c b/examples/texture.c index d6bee54..6467efe 100644 --- a/examples/texture.c +++ b/examples/texture.c @@ -20,16 +20,16 @@ void init() { assert(0); } - texture.stride = texture.width; - texture.pixels = (uint32_t *)data; // NOTE(kard): be careful if changing following loop + texture.stride_pixels = texture.width; + texture.pixels = (sponge_Color32 *)data; // NOTE(kard): be careful if changing following loop - // converting from stbi's RGBA to ARGB + // converting from stbi's RGBA for (size_t i = 0; i < texture.width * texture.height; i++) { - uint32_t result = 0; - result |= data[i * 4 + 0] << 16; // R - result |= data[i * 4 + 1] << 8; // G - result |= data[i * 4 + 2] << 0; // B - result |= data[i * 4 + 3] << 24; // A + sponge_Color32 result; + result.r = data[i * 4 + 0]; + result.g = data[i * 4 + 1]; + result.b = data[i * 4 + 2]; + result.a = data[i * 4 + 3]; texture.pixels[i] = result; } @@ -40,7 +40,7 @@ void init() { } void draw_frame(sponge_Texture c) { - sponge_clear(c, 0xFF000000); + sponge_clear(c, sponge_color32_make(0xFF000000)); pos_x += speed_x; pos_y += speed_y; @@ -59,5 +59,5 @@ void draw_frame(sponge_Texture c) { speed_y = -SPEED_Y_ABS; } - sponge_draw_texture(c, pos_x, pos_y, texture); + sponge_draw_texture(c, sponge_vec2i_make(pos_x, pos_y), texture); } diff --git a/examples/triangles.c b/examples/triangles.c index f995574..8515a28 100644 --- a/examples/triangles.c +++ b/examples/triangles.c @@ -31,7 +31,7 @@ void draw_frame(sponge_Texture c) { c, x, y + offset_y, x + offset_x, y, - x + (offset_x / 4), y + (offset_y / 4), + x + (offset_x * 3 / 4), y + (offset_y * 3 / 4), 0xFFFF0000, 0xFF00FF00, 0xFF0000FF); } } diff --git a/platform_win32.c b/platform_win32.c index e3563b5..be4d478 100644 --- a/platform_win32.c +++ b/platform_win32.c @@ -14,8 +14,8 @@ #include "example.h" -#define DEFAULT_WIDTH 256 -#define DEFAULT_HEIGHT 256 +#define DEFAULT_WIDTH 1280 +#define DEFAULT_HEIGHT 720 #define TARGET_FRAME_TIME_US 16666 @@ -26,7 +26,7 @@ static BITMAPINFO bmi; int update_canvas(sponge_Texture *canvas, uint32_t new_width, uint32_t new_height) { size_t new_count = new_width * new_height; if (new_count > pixels_buffer_count) { - uint32_t *new_pixels_buffer = malloc(new_count * sizeof(uint32_t)); + sponge_Color32 *new_pixels_buffer = malloc(new_count * sizeof(uint32_t)); if (!new_pixels_buffer) return 0; free(canvas->pixels); @@ -35,7 +35,7 @@ int update_canvas(sponge_Texture *canvas, uint32_t new_width, uint32_t new_heigh } canvas->width = new_width; canvas->height = new_height; - canvas->stride = new_width; // TODO(kard): think about this if we want image to stay the same without redraw + canvas->stride_pixels = new_width; // TODO(kard): think about this if we want image to stay the same without redraw ZeroMemory(&bmi, sizeof(bmi)); bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); @@ -126,6 +126,10 @@ int __stdcall WinMain( LARGE_INTEGER qpc_end; LARGE_INTEGER qpc_draw; LARGE_INTEGER qpc_frame; + + LARGE_INTEGER qpc_running_draw = { 0 }; + size_t qpc_running_draw_count = 0; + QueryPerformanceFrequency(&qpc_freq); QueryPerformanceCounter(&qpc_start); @@ -143,13 +147,15 @@ int __stdcall WinMain( if (!running) break; - if (sponge_canvas_valid(canvas)) + if (sponge_texture_valid(canvas)) draw_frame(canvas); QueryPerformanceCounter(&qpc_end); qpc_draw.QuadPart = qpc_end.QuadPart - qpc_start.QuadPart; qpc_draw.QuadPart *= 1000000; // microseconds qpc_draw.QuadPart /= qpc_freq.QuadPart; + qpc_running_draw.QuadPart += qpc_draw.QuadPart; + qpc_running_draw_count++; HDC hdc = GetDC(hwnd); StretchDIBits( @@ -171,8 +177,9 @@ int __stdcall WinMain( qpc_frame.QuadPart *= 1000000; // microseconds qpc_frame.QuadPart /= qpc_freq.QuadPart; - fprintf(stderr, "draw time: %3lld.%03lldms, frame time: %3lld.%03lldms\n", + fprintf(stderr, "draw time: %3lld.%03lldms (avg: %3lld.%03lldms), frame time: %3lld.%03lldms\n", qpc_draw.QuadPart / 1000, qpc_draw.QuadPart % 1000, + qpc_running_draw.QuadPart / qpc_running_draw_count / 1000, qpc_running_draw.QuadPart / qpc_running_draw_count % 1000, qpc_frame.QuadPart / 1000, qpc_frame.QuadPart % 1000); // TODO(kard): diff --git a/run.bat b/run.bat index f58c538..0ec23a4 100644 --- a/run.bat +++ b/run.bat @@ -1,4 +1,4 @@ del out.exe del *.obj -cl platform_win32.c "examples\%1" user32.lib gdi32.lib /W3 /Fe:out.exe /Z7 /O2 +cl platform_win32.c "examples\%1" user32.lib gdi32.lib /W3 /Fe:out.exe /Z7 out.exe diff --git a/sponge.h b/sponge.h index 02f1bcd..ce27f31 100644 --- a/sponge.h +++ b/sponge.h @@ -1,30 +1,92 @@ #include +typedef union { + // do not rely on byte order of this field (unless you only support one platform) + uint32_t value; + struct { + uint8_t b; + uint8_t g; + uint8_t r; + uint8_t a; + }; +} sponge_Color32; +sponge_Color32 sponge_color32_make(uint32_t value); + typedef struct { - uint32_t *pixels; // AARRGGBB - uint32_t width; - uint32_t height; - uint32_t stride; + sponge_Color32 *pixels; + uint32_t width; + uint32_t height; + size_t stride_pixels; } sponge_Texture; typedef struct { float x; float y; } sponge_Vec2; +sponge_Vec2 sponge_vec2_make(float x, float y); -sponge_Vec2 sponge_add2(sponge_Vec2 v0, sponge_Vec2 v1); -sponge_Vec2 sponge_sub2(sponge_Vec2 v0, sponge_Vec2 v1); -float sponge_dot2(sponge_Vec2 v0, sponge_Vec2 v1); +typedef struct { + float x; + float y; + float z; +} sponge_Vec3; +sponge_Vec3 sponge_vec3_make(float x, float y, float z); + +typedef union { + struct { + float x; + float y; + float z; + float w; + }; + struct { + float a; + float r; + float g; + float b; + }; +} sponge_Vec4; +sponge_Vec4 sponge_vec4_make(float x, float y, float z, float w); + +// in sponge apis components expected to be between 0.0 and 255.0 +#define sponge_ColorF sponge_Vec4 -int sponge_canvas_valid (sponge_Texture c); -void sponge_clear (sponge_Texture c, uint32_t color); -void sponge_draw_rect (sponge_Texture c, uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, uint32_t color); -void sponge_draw_line (sponge_Texture c, int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t color); -void sponge_draw_texture (sponge_Texture c, uint32_t x0, uint32_t y0, sponge_Texture tex); -void sponge_draw_triangle_col (sponge_Texture c, int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint32_t color); -void sponge_draw_triangle_col3( - sponge_Texture c, int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, - uint32_t color0, uint32_t color1, uint32_t color2); +typedef struct { + int32_t x; + int32_t y; +} sponge_Vec2I; +sponge_Vec2I sponge_vec2i_make(int32_t x, int32_t y); + +sponge_Vec2 sponge_vec2_add(sponge_Vec2 v0, sponge_Vec2 v1); +sponge_Vec2 sponge_vec2_sub(sponge_Vec2 v0, sponge_Vec2 v1); +float sponge_vec2_dot(sponge_Vec2 v0, sponge_Vec2 v1); + +sponge_Vec4 sponge_vec4_add(sponge_Vec4 v0, sponge_Vec4 v1); +sponge_Vec4 sponge_vec4_mul(sponge_Vec4 v0, float f); + +sponge_ColorF sponge_color32_to_colorf(sponge_Color32 col); +sponge_Color32 sponge_colorf_to_color32(sponge_ColorF col); + +// checks if tex.width or tex.height is equal to 0 +// calling sponge functions with invalid textures is not supported +int sponge_texture_valid(sponge_Texture tex); + +// first argument is always rendering target (canvas) +void sponge_clear (sponge_Texture c, sponge_Color32 col); + +void sponge_draw_rect (sponge_Texture c, sponge_Vec2I v0, sponge_Vec2I v1, sponge_Color32 col); +void sponge_draw_line (sponge_Texture c, sponge_Vec2I v0, sponge_Vec2I v1, sponge_Color32 col); +void sponge_draw_texture(sponge_Texture c, sponge_Vec2I offset, sponge_Texture tex); + +//void sponge_draw_triangle_col (sponge_Texture c, sponge_Vec2I v0, sponge_Vec2I v1, sponge_Vec2I v2, sponge_Color32 col); +//void sponge_draw_triangle_col3(sponge_Texture c, +// sponge_Vec2I v0, sponge_Vec2I v1, sponge_Vec2I v2, +// sponge_ColorF col0, sponge_ColorF col1, sponge_ColorF col2); + +#define SPONGE_CLAMP(val, min, max) ((val) < (min) ? (min) : ((val) > (max) ? (max) : (val))) +#define SPONGE_MIN(x, y) ((x) < (y) ? (x) : (y)) +#define SPONGE_MAX(x, y) ((x) > (y) ? (x) : (y)) +#define SPONGE_ABS(x) ((x) >= 0 ? (x) : -(x)) // TODO(kard): prefix stripping @@ -36,199 +98,193 @@ void sponge_draw_triangle_col3( #define SPONGE_ASSERT(x) assert(x) #endif // SPONGE_ASSERT -#define SPONGE__CLAMP(val, min, max) ((val) < (min) ? (min) : ((val) > (max) ? (max) : (val))) -#define SPONGE__MIN(x, y) ((x) < (y) ? (x) : (y)) -#define SPONGE__MAX(x, y) ((x) > (y) ? (x) : (y)) -#define SPONGE__ABS(x) ((x) >= 0 ? (x) : -(x)) - -typedef struct { - float a; - float r; - float g; - float b; -} sponge__ColorF; - -sponge__ColorF sponge__colf_unpack(uint32_t col) { - uint32_t b = col & 0xFF; - col = col >> 8; - uint32_t g = col & 0xFF; - col = col >> 8; - uint32_t r = col & 0xFF; - col = col >> 8; - uint32_t a = col & 0xFF; - sponge__ColorF result = { .a = (float)a, .r = (float)r, .g = (float)g, .b = (float)b }; +// TODO(kard): msvc does not inline this for some reason, explore if it's a concern +sponge_Color32 sponge_color32_make(uint32_t value) { + sponge_Color32 result; + result.a = (value & 0xFF000000) >> 24; + result.r = (value & 0x00FF0000) >> 16; + result.g = (value & 0x0000FF00) >> 8; + result.b = (value & 0x000000FF); return result; } - -uint32_t sponge__colf_pack(sponge__ColorF color) { - uint32_t result = 0; - result |= SPONGE__CLAMP((uint32_t)color.a, 0x00, 0xFF); - result = result << 8; - result |= SPONGE__CLAMP((uint32_t)color.r, 0x00, 0xFF); - result = result << 8; - result |= SPONGE__CLAMP((uint32_t)color.g, 0x00, 0xFF); - result = result << 8; - result |= SPONGE__CLAMP((uint32_t)color.b, 0x00, 0xFF); +sponge_Vec2 sponge_vec2_make(float x, float y) { + sponge_Vec2 result; + result.x = x; + result.y = y; return result; } - -sponge__ColorF sponge__colf_mul(sponge__ColorF color, float f) { - color.a *= f; - color.r *= f; - color.g *= f; - color.b *= f; - return color; -} - -sponge__ColorF sponge__colf_add(sponge__ColorF color0, sponge__ColorF color1) { - sponge__ColorF result; - result.a = color0.a + color1.a; - result.r = color0.r + color1.r; - result.g = color0.g + color1.g; - result.b = color0.b + color1.b; +sponge_Vec3 sponge_vec3_make(float x, float y, float z) { + sponge_Vec3 result; + result.x = x; + result.y = y; + result.z = z; return result; } - - -typedef struct { - sponge_Vec2 v0; - sponge_Vec2 v1; - float d00; - float d01; - float d11; - float denom; -} sponge__BarycentricContext; - -// TODO(kard): measure if caching this makes sense -sponge__BarycentricContext sponge__barycentric_init(sponge_Vec2 t0, sponge_Vec2 t1, sponge_Vec2 t2) { - sponge__BarycentricContext result; - result.v0 = sponge_sub2(t1, t0); - result.v1 = sponge_sub2(t2, t0); - result.d00 = sponge_dot2(result.v0, result.v0); - result.d01 = sponge_dot2(result.v0, result.v1); - result.d11 = sponge_dot2(result.v1, result.v1); - result.denom = (result.d00 * result.d11) - (result.d01 * result.d01); +sponge_Vec4 sponge_vec4_make(float x, float y, float z, float w) { + sponge_Vec4 result; + result.x = x; + result.y = y; + result.z = z; + result.w = w; return result; } - -void sponge__barycentric( - sponge__BarycentricContext ctx, sponge_Vec2 p, - sponge_Vec2 t0, - sponge_Vec2 t1, - sponge_Vec2 t2, - float *u, float *v, float *w -) { - sponge_Vec2 v2 = sponge_sub2(p, t0); - float d20 = sponge_dot2(v2, ctx.v0); - float d21 = sponge_dot2(v2, ctx.v1); - float vr = (ctx.d11 * d20 - ctx.d01 * d21) / ctx.denom; - float wr = (ctx.d00 * d21 - ctx.d01 * d20) / ctx.denom; - float ur = 1.0f - vr - wr; - *u = ur; - *v = vr; - *w = wr; -} - - -sponge_Vec2 sponge_add2(sponge_Vec2 v0, sponge_Vec2 v1) { - sponge_Vec2 result; - result.x = v0.x + v1.x; - result.y = v0.y + v1.y; +sponge_Vec2I sponge_vec2i_make(int32_t x, int32_t y) { + sponge_Vec2I result; + result.x = x; + result.y = y; return result; } -sponge_Vec2 sponge_sub2(sponge_Vec2 v0, sponge_Vec2 v1) { - sponge_Vec2 result; - result.x = v0.x - v1.x; - result.y = v0.y - v1.y; - return result; +sponge_Vec2 sponge_vec2_add(sponge_Vec2 v0, sponge_Vec2 v1) { + return (sponge_Vec2){ .x = v0.x + v1.x, .y = v0.y + v1.y }; } - -float sponge_dot2(sponge_Vec2 v0, sponge_Vec2 v1) { +sponge_Vec2 sponge_vec2_sub(sponge_Vec2 v0, sponge_Vec2 v1) { + return (sponge_Vec2){ .x = v0.x - v1.x, .y = v0.y - v1.y }; +} +float sponge_vec2_dot(sponge_Vec2 v0, sponge_Vec2 v1) { return (v0.x * v1.x) + (v0.y * v1.y); } -int sponge_canvas_valid(sponge_Texture c) { - return c.width != 0 && c.height != 0; +sponge_ColorF sponge_color32_to_colorf(sponge_Color32 col) { + return (sponge_ColorF){ .a = (float)col.a, .r = (float)col.r, .g = (float)col.g, .b = (float)col.b }; +} +sponge_Color32 sponge_colorf_to_color32(sponge_ColorF col) { + return (sponge_Color32){ .a = (uint8_t)col.a, .r = (uint8_t)col.r, .g = (uint8_t)col.g, .b = (uint8_t)col.b }; } -void sponge_clear(sponge_Texture c, uint32_t color) { - SPONGE_ASSERT(sponge_canvas_valid(c)); +sponge_Vec4 sponge_vec4_add(sponge_Vec4 v0, sponge_Vec4 v1) { + v0.a += v1.a; + v0.r += v1.r; + v0.g += v1.g; + v0.b += v1.b; + return v0; +} +sponge_Vec4 sponge_vec4_mul(sponge_Vec4 v0, float f) { + v0.a *= f; + v0.r *= f; + v0.g *= f; + v0.b *= f; + return v0; +} - sponge_draw_rect(c, 0, 0, c.width - 1, c.height - 1, color); +// sponge__BarycentricContext sponge__barycentric_init(sponge_Vec2 t0, sponge_Vec2 t1, sponge_Vec2 t2) { + // sponge__BarycentricContext result; + // result.v0 = sponge_sub2(t1, t0); + // result.v1 = sponge_sub2(t2, t0); + // result.d00 = sponge_dot2(result.v0, result.v0); + // result.d01 = sponge_dot2(result.v0, result.v1); + // result.d11 = sponge_dot2(result.v1, result.v1); + // result.denom = (result.d00 * result.d11) - (result.d01 * result.d01); + // return result; +// } +// +// void sponge__barycentric( + // sponge__BarycentricContext ctx, sponge_Vec2 p, + // sponge_Vec2 t0, + // sponge_Vec2 t1, + // sponge_Vec2 t2, + // float *u, float *v, float *w +// ) { + // sponge_Vec2 v2 = sponge_sub2(p, t0); + // float d20 = sponge_dot2(v2, ctx.v0); + // float d21 = sponge_dot2(v2, ctx.v1); + // float vr = (ctx.d11 * d20 - ctx.d01 * d21) / ctx.denom; + // float wr = (ctx.d00 * d21 - ctx.d01 * d20) / ctx.denom; + // float ur = 1.0f - vr - wr; + // *u = ur; + // *v = vr; + // *w = wr; +// } + + +int sponge_texture_valid(sponge_Texture tex) { + return tex.width != 0 && tex.height != 0 && tex.stride_pixels != 0; } -// TODO(kard): probably bounds checking -// TODO(kard): alpha blending maybe -void sponge_draw_rect(sponge_Texture c, uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, uint32_t color) { - SPONGE_ASSERT(sponge_canvas_valid(c)); +void sponge_clear(sponge_Texture c, sponge_Color32 col) { + SPONGE_ASSERT(sponge_texture_valid(c)); + sponge_Color32 *row = c.pixels; - uint32_t *row = c.pixels + (y0 * c.stride); + for (uint32_t y = 0; y < c.height; y++, row += c.stride_pixels) { + for (uint32_t x = 0; x < c.width; x++) { + row[x] = col; + } + } +} - for (uint32_t y = y0; y <= y1; y++, row += c.stride) { - for (uint32_t x = x0; x <= x1; x++) { - row[x] = color; +void sponge_draw_rect(sponge_Texture c, sponge_Vec2I v0, sponge_Vec2I v1, sponge_Color32 col) { + SPONGE_ASSERT(sponge_texture_valid(c)); + sponge_Vec2I min, max; + min.x = SPONGE_MIN(v0.x, v1.x); + min.y = SPONGE_MIN(v0.y, v1.y); + max.x = SPONGE_MAX(v0.x, v1.x); + max.y = SPONGE_MAX(v0.y, v1.y); + if (min.x >= (int32_t)c.width || min.y >= (int32_t)c.height || max.x < 0 || max.y < 0) + return; + min.x = SPONGE_MAX(min.x, 0); + min.y = SPONGE_MAX(min.y, 0); + max.x = SPONGE_MIN(max.x, (int32_t)c.width - 1); + max.y = SPONGE_MIN(max.y, (int32_t)c.height - 1); + + sponge_Color32 *row = c.pixels + (min.y * c.stride_pixels); + + for (int32_t y = min.y; y <= max.y; y++, row += c.stride_pixels) { + for (int32_t x = min.x; x <= max.x; x++) { + row[x] = col; } } } -void sponge_draw_line(sponge_Texture c, int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t color) { - SPONGE_ASSERT(sponge_canvas_valid(c)); +void sponge_draw_line(sponge_Texture c, sponge_Vec2I v0, sponge_Vec2I v1, sponge_Color32 col) { + SPONGE_ASSERT(sponge_texture_valid(c)); - int32_t dx = x1 - x0; - dx = SPONGE__ABS(dx); - int32_t dy = y1 - y0; - dy = SPONGE__ABS(dy); + int32_t dx = SPONGE_ABS(v1.x - v0.x); + int32_t dy = SPONGE_ABS(v1.y - v0.y); int32_t d = (2 * dy) - dx; - int32_t sx = (x0 < x1) ? 1 : -1; - int32_t sy = (y0 < y1) ? 1 : -1; + int32_t sx = (v0.x < v1.x) ? 1 : -1; + int32_t sy = (v0.y < v1.y) ? 1 : -1; int32_t err = dx - dy; while (1) { - if (x0 >= 0 && x0 < (int32_t)c.width && y0 >= 0 && y0 < (int32_t)c.height) - c.pixels[(y0 * c.stride) + x0] = color; + if (v0.x >= 0 && v0.x < (int32_t)c.width && v0.y >= 0 && v0.y < (int32_t)c.height) + c.pixels[(v0.y * c.stride_pixels) + v0.x] = col; - if (x0 == x1 && y0 == y1) break; + if (v0.x == v1.x && v0.y == v1.y) break; int32_t e2 = 2 * err; - if (e2 > -dy) { err -= dy; x0 += sx; } - if (e2 < dx) { err += dx; y0 += sy; } + if (e2 > -dy) { err -= dy; v0.x += sx; } + if (e2 < dx) { err += dx; v0.y += sy; } } } -void sponge_draw_texture(sponge_Texture c, uint32_t x0, uint32_t y0, sponge_Texture tex) { - SPONGE_ASSERT(sponge_canvas_valid(c)); - - uint32_t *row_dst = c.pixels + (y0 * c.stride); - uint32_t *row_src = tex.pixels; - uint32_t x1 = x0 + tex.width; - uint32_t y1 = y0 + tex.height; - - if (x1 >= c.width) - x1 = c.width - 1; - if (y1 >= c.height) - y1 = c.height - 1; - - for (uint32_t y = y0; y <= y1; y++, row_src += tex.stride, row_dst += c.stride) { - // TODO(kard): memcpy? - for (uint32_t x = x0, x_src = 0; x <= x1; x++, x_src++) { +void sponge_draw_texture(sponge_Texture c, sponge_Vec2I offset, sponge_Texture tex) { + SPONGE_ASSERT(sponge_texture_valid(c)); + SPONGE_ASSERT(sponge_texture_valid(tex)); + + sponge_Vec2I min, max; + min.x = SPONGE_MAX(offset.x, 0); + min.y = SPONGE_MAX(offset.y, 0); + max.x = SPONGE_MIN(offset.x + tex.width - 1, c.width - 1); + max.y = SPONGE_MIN(offset.y + tex.height - 1, c.height - 1); + sponge_Color32 *row_dst = c.pixels + (min.y * c.stride_pixels); + sponge_Color32 *row_src = (tex.pixels - (offset.y * c.stride_pixels)) + (min.y * c.stride_pixels); + uint32_t src_offset = min.x - offset.x; + + for (int32_t y = min.y; y <= max.y; y++, row_src += tex.stride_pixels, row_dst += c.stride_pixels) { + for (int32_t x = min.x, x_src = src_offset; x <= max.x; x++, x_src++) { row_dst[x] = row_src[x_src]; } } } +/* void sponge_draw_triangle_col(sponge_Texture c, int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint32_t color) { sponge_draw_triangle_col3(c, x0, y0, x1, y1, x2, y2, color, color, color); } // NOTE(kard): // this does not accept floats on purpose. -// there are more efficient algorithms for producing triangle pixels other than -// checking every one of them in rectangle with barycentric coords (e.g. using Brehensam algorithm) -// and they can work with integer coordinates. -// TODO(kard): this should be explored in the future -// TODO(kard): backface culling? void sponge_draw_triangle_col3( sponge_Texture c, int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint32_t color0, uint32_t color1, uint32_t color2) { @@ -248,7 +304,6 @@ void sponge_draw_triangle_col3( uint32_t min_y = (uint32_t)SPONGE__CLAMP(smin_y, 0, (int32_t)(c.height - 1)); uint32_t max_y = (uint32_t)SPONGE__CLAMP(smax_y, 0, (int32_t)(c.height - 1)); - sponge__BarycentricContext ctx = sponge__barycentric_init(t0, t1, t2); uint32_t *row = c.pixels + (min_y * c.stride); @@ -260,10 +315,10 @@ void sponge_draw_triangle_col3( for (uint32_t x = x0; x <= max_x; x++) { float u, v, w; sponge_Vec2 p = { .x = (float)x, .y = (float)y }; + sponge__BarycentricContext ctx = sponge__barycentric_init(t0, t1, t2); sponge__barycentric(ctx, p, t0, t1, t2, &u, &v, &w); if (u > 0.0f && v > 0.0f && w > 0.0f) { - // TODO(kard): make more robust, this probably has a lot of off by 1 errors sponge__ColorF c0 = sponge__colf_mul(color0f, u); sponge__ColorF c1 = sponge__colf_mul(color1f, v); sponge__ColorF c2 = sponge__colf_mul(color2f, w); @@ -274,5 +329,11 @@ void sponge_draw_triangle_col3( } } -#endif // SPONGE_IMPLEMENTATION +void sponge_draw_triangle_uv( + sponge_Texture c, int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, + uint32_t color0, uint32_t color1, uint32_t color2, + sponge_Vec2 uv0, sponge_Vec2 uv1, sponge_Vec2 uv2, sponge_Texture tex) { +} +*/ +#endif // SPONGE_IMPLEMENTATION -- cgit v1.3.1