diff options
| author | kkard2 <[email protected]> | 2025-09-22 20:35:57 +0200 |
|---|---|---|
| committer | kkard2 <[email protected]> | 2025-09-22 20:35:57 +0200 |
| commit | 42d3b218942d7ece8a15ef9298c8cd13974aa4c9 (patch) | |
| tree | 418e98e86c66fef515de65e917fcf8637531f44c | |
| parent | a17e7369bfe9cb4a23225084a396ec92823bad2b (diff) | |
add transparency
| -rw-r--r-- | examples/transparency.c | 188 | ||||
| -rw-r--r-- | sponge.h | 41 |
2 files changed, 218 insertions, 11 deletions
diff --git a/examples/transparency.c b/examples/transparency.c new file mode 100644 index 0000000..c12ea93 --- /dev/null +++ b/examples/transparency.c @@ -0,0 +1,188 @@ +#include <math.h> +#include <stdlib.h> + +#include "../sponge.h" +#define SPONGE_EXAMPLE_IMPLEMENTATION +#define SPONGE_EXAMPLE_INIT_DEFINED +#define SPONGE_EXAMPLE_MOUSE_MOVE_DEFINED +#define SPONGE_EXAMPLE_DRAW_FRAME_3D_DEFINED +#include "example.h" + +#define FOV (60.0f / PI * 2.0f) +#define DISTANCE (10.0f) +#define GOLDEN_RATIO (1.618033988749f) + +static int32_t mouse_x; +static int32_t mouse_y; + +static sponge_Vec3 positions[12]; +static sponge_Color32 colors[12]; +static sponge_Color32 colors_red[12]; +static sponge_Color32 colors_green[12]; +static sponge_Color32 colors_blue[12]; +static int32_t triangles[20 * 3]; + +void make_icosahedron(sponge_Vec3 out_positions[12], int32_t out_triangles[20 * 3]) { + float a = sqrtf(1.0f / (1.0f + (GOLDEN_RATIO * GOLDEN_RATIO))); + float b = a * GOLDEN_RATIO; + out_positions[0] = sponge_vec3_make(0.0f, -a, b); + out_positions[1] = sponge_vec3_make(0.0f, a, b); + out_positions[2] = sponge_vec3_make(0.0f, -a, -b); + out_positions[3] = sponge_vec3_make(0.0f, a, -b); + + out_positions[4] = sponge_vec3_make(-b, 0.0f, a); + out_positions[5] = sponge_vec3_make( b, 0.0f, a); + out_positions[6] = sponge_vec3_make(-b, 0.0f, -a); + out_positions[7] = sponge_vec3_make( b, 0.0f, -a); + + out_positions[8] = sponge_vec3_make(-a, b, 0.0f); + out_positions[9] = sponge_vec3_make( a, b, 0.0f); + out_positions[10] = sponge_vec3_make(-a, -b, 0.0f); + out_positions[11] = sponge_vec3_make( a, -b, 0.0f); + + size_t i = 0; + // 2x y + out_triangles[i++] = 4; out_triangles[i++] = 1; out_triangles[i++] = 0; + out_triangles[i++] = 0; out_triangles[i++] = 1; out_triangles[i++] = 5; + out_triangles[i++] = 3; out_triangles[i++] = 2; out_triangles[i++] = 7; + out_triangles[i++] = 2; out_triangles[i++] = 3; out_triangles[i++] = 6; + // 2y z + out_triangles[i++] = 4; out_triangles[i++] = 6; out_triangles[i++] = 8; + out_triangles[i++] = 10; out_triangles[i++] = 6; out_triangles[i++] = 4; + out_triangles[i++] = 7; out_triangles[i++] = 5; out_triangles[i++] = 9; + out_triangles[i++] = 5; out_triangles[i++] = 7; out_triangles[i++] = 11; + // 2z x + out_triangles[i++] = 8; out_triangles[i++] = 9; out_triangles[i++] = 1; + out_triangles[i++] = 3; out_triangles[i++] = 9; out_triangles[i++] = 8; + out_triangles[i++] = 0; out_triangles[i++] = 11; out_triangles[i++] = 10; + out_triangles[i++] = 10; out_triangles[i++] = 11; out_triangles[i++] = 2; + // xyz + out_triangles[i++] = 10; out_triangles[i++] = 4; out_triangles[i++] = 0; + out_triangles[i++] = 0; out_triangles[i++] = 5; out_triangles[i++] = 11; + out_triangles[i++] = 1; out_triangles[i++] = 4; out_triangles[i++] = 8; + out_triangles[i++] = 9; out_triangles[i++] = 5; out_triangles[i++] = 1; + out_triangles[i++] = 2; out_triangles[i++] = 6; out_triangles[i++] = 10; + out_triangles[i++] = 11; out_triangles[i++] = 7; out_triangles[i++] = 2; + out_triangles[i++] = 8; out_triangles[i++] = 6; out_triangles[i++] = 3; + out_triangles[i++] = 3; out_triangles[i++] = 7; out_triangles[i++] = 9; +} + +// NOTE(kard): +// there are many ways to handle opacity and base library doesn't provide one. +// this example implementation requires caller to order objects back to front. +// you could allocate multiple canvases and merge them at the end (after sorting pixel based on depth). +void draw_mesh_col_transparent( + sponge_Texture c, float *depths, + sponge_Mat4 model, sponge_Mat4 view, sponge_Mat4 proj, + sponge_Vec3 *positions, sponge_Color32 *colors, int32_t *triangles, size_t triangles_count, + float opacity +) { + sponge_Mat4 mvp = sponge_mat4_mul_mat4(sponge_mat4_mul_mat4(model, view), proj); + for (size_t i = 0; i < triangles_count; i += 3) { + sponge_DrawMeshTriangleContext ctx = sponge_draw_mesh_triangle_init(c, mvp, positions, triangles, i); + sponge_Color32 *row = c.pixels + (ctx.min_pixel.y * c.stride_pixels); + float *depth_row = depths + (ctx.min_pixel.y * c.stride_pixels); + + for (int32_t y = ctx.min_pixel.y; y <= ctx.max_pixel.y; y++, row += c.stride_pixels, depth_row += c.stride_pixels) { + for (int32_t x = ctx.min_pixel.x; x <= ctx.max_pixel.x; x++) { + float w0, w1, w2; + if (sponge_draw_mesh_triangle_iter(ctx, sponge_vec2i_make(x, y), &depth_row[x], &w0, &w1, &w2)) { + sponge_ColorF c0 = sponge_color32_to_colorf(colors[ctx.t0]); + sponge_ColorF c1 = sponge_color32_to_colorf(colors[ctx.t1]); + sponge_ColorF c2 = sponge_color32_to_colorf(colors[ctx.t2]); + sponge_ColorF result = sponge_vec4_make(0.0f, 0.0f, 0.0f, 0.0f); + result = sponge_vec4_add(result, sponge_vec4_mul(c0, w0)); + result = sponge_vec4_add(result, sponge_vec4_mul(c1, w1)); + result = sponge_vec4_add(result, sponge_vec4_mul(c2, w2)); + + sponge_ColorF cur = sponge_color32_to_colorf(row[x]); + result = sponge_vec4_add(cur, sponge_vec4_mul(sponge_vec4_sub(result, cur), opacity)); + row[x] = sponge_colorf_to_color32(result); + } + } + } + } +} + +void init() { + make_icosahedron(positions, triangles); + sponge_Vec3 light = sponge_vec3_make(1.0f, 1.0f, 1.0f); + float len = (light.x * light.x) + (light.y * light.y) + (light.z * light.z); + len = sqrtf(len); + light = sponge_vec3_mul(light, 1.0f / len); + for (uint32_t i = 0; i < 12; i++) { + sponge_Vec3 v = positions[i]; + float value = v.x * light.x + v.y * light.y + v.z * light.z; + value = SPONGE_CLAMP(value, 0.1f, 1.0f); + sponge_ColorF color = sponge_vec4_make(1.0f, value, value, value); + color = sponge_vec4_mul(color, 255.0f); + colors[i] = sponge_colorf_to_color32(color); + colors_red[i] = sponge_color32_make(0xFFFF0000); + colors_green[i] = sponge_color32_make(0xFF00FF00); + colors_blue[i] = sponge_color32_make(0xFF0000FF); + + //sponge_Vec3 v = sponge_vec3_mul(positions[i], 255.0f); + //colors[i] = sponge_colorf_to_color32(sponge_vec4_make(1.0f, SPONGE_ABS(v.x), SPONGE_ABS(v.y), SPONGE_ABS(v.z))); + } +} + +void mouse_move(int32_t x, int32_t y) { + mouse_x = x; + mouse_y = y; +} + +void draw_frame_3d(sponge_Texture c, float *depths) { + sponge_clear_3d(c, depths, sponge_color32_make(0xFF000000)); + + sponge_Mat4 model = sponge_mat4_translate(2.0f, 0.0f, 0.0f); + sponge_Mat4 rotate = sponge_mat4_rotate(0.0f, 90.0f / 360.0f * PI * 2.0f, 0.0f); + sponge_Mat4 model_red = sponge_mat4_mul_mat4(model, rotate); + sponge_Mat4 model_green = sponge_mat4_mul_mat4(model_red, rotate); + sponge_Mat4 model_blue = sponge_mat4_mul_mat4(model_green, rotate); + + float rot_y = (float)mouse_x / (float)c.width * PI * 2.0f; + float rot_x = ((float)mouse_y / (float)c.height * PI) - (PI * 0.5f); + sponge_Mat4 view = sponge_mat4_identity(); + view = sponge_mat4_mul_mat4(view, sponge_mat4_rotate(rot_x, rot_y, 0.0f)); + view = sponge_mat4_mul_mat4(view, sponge_mat4_translate(0.0f, 0.0f, -10.0f)); + + sponge_Mat4 proj = sponge_mat4_projection(FOV, (float)c.width / (float)c.height, 1.0f, 100.0f); + sponge_draw_mesh_col(c, depths, model, view, proj, positions, colors, triangles, 60); + + float z0 = sponge_vec3_mul_mat4(sponge_vec3_make(0.0f, 0.0f, 0.0f), sponge_mat4_mul_mat4(model_red, view)).z; + float z1 = sponge_vec3_mul_mat4(sponge_vec3_make(0.0f, 0.0f, 0.0f), sponge_mat4_mul_mat4(model_green, view)).z; + float z2 = sponge_vec3_mul_mat4(sponge_vec3_make(0.0f, 0.0f, 0.0f), sponge_mat4_mul_mat4(model_blue, view)).z; + float z[3] = { z0, z1, z2 }; + int order[3] = { 0, 1, 2 }; + + // do not look at this garbage + if (z[order[0]] > z[order[1]]) { + int tmp = order[0]; + order[0] = order[1]; + order[1] = tmp; + } + if (z[order[0]] > z[order[2]]) { + int tmp = order[0]; + order[0] = order[2]; + order[2] = tmp; + } + if (z[order[1]] > z[order[2]]) { + int tmp = order[1]; + order[1] = order[2]; + order[2] = tmp; + } + + for (int i = 0; i < 3; i++) { + switch(order[i]) { + case 0: + draw_mesh_col_transparent(c, depths, model_red, view, proj, positions, colors_red, triangles, 60, 0.1f); + break; + case 1: + draw_mesh_col_transparent(c, depths, model_green, view, proj, positions, colors_green, triangles, 60, 0.2f); + break; + case 2: + draw_mesh_col_transparent(c, depths, model_blue, view, proj, positions, colors_blue, triangles, 60, 0.3f); + break; + } + } +} @@ -61,9 +61,13 @@ 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); sponge_Vec2 sponge_vec2_mul(sponge_Vec2 v0, float f); -float sponge_vec2_dot(sponge_Vec2 v0, sponge_Vec2 v1); + +sponge_Vec3 sponge_vec3_add(sponge_Vec3 v0, sponge_Vec3 v1); +sponge_Vec3 sponge_vec3_sub(sponge_Vec3 v0, sponge_Vec3 v1); +sponge_Vec3 sponge_vec3_mul(sponge_Vec3 v0, float f); sponge_Vec4 sponge_vec4_add(sponge_Vec4 v0, sponge_Vec4 v1); +sponge_Vec4 sponge_vec4_sub(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); @@ -230,10 +234,18 @@ sponge_Vec2 sponge_vec2_sub(sponge_Vec2 v0, sponge_Vec2 v1) { sponge_Vec2 sponge_vec2_mul(sponge_Vec2 v0, float f) { return (sponge_Vec2){ .x = v0.x * f, .y = v0.y * f }; } -float sponge_vec2_dot(sponge_Vec2 v0, sponge_Vec2 v1) { - return (v0.x * v1.x) + (v0.y * v1.y); + +sponge_Vec3 sponge_vec3_add(sponge_Vec3 v0, sponge_Vec3 v1) { + return (sponge_Vec3){ .x = v0.x + v1.x, .y = v0.y + v1.y, .z = v0.z + v1.z }; +} +sponge_Vec3 sponge_vec3_sub(sponge_Vec3 v0, sponge_Vec3 v1) { + return (sponge_Vec3){ .x = v0.x - v1.x, .y = v0.y - v1.y, .z = v0.z - v1.z }; +} +sponge_Vec3 sponge_vec3_mul(sponge_Vec3 v0, float f) { + return (sponge_Vec3){ .x = v0.x * f, .y = v0.y * f, .z = v0.z * f }; } + 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 }; } @@ -242,17 +254,24 @@ sponge_Color32 sponge_colorf_to_color32(sponge_ColorF col) { } 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; + v0.x += v1.x; + v0.y += v1.y; + v0.z += v1.z; + v0.w += v1.w; + return v0; +} +sponge_Vec4 sponge_vec4_sub(sponge_Vec4 v0, sponge_Vec4 v1) { + v0.x -= v1.x; + v0.y -= v1.y; + v0.z -= v1.z; + v0.w -= v1.w; return v0; } sponge_Vec4 sponge_vec4_mul(sponge_Vec4 v0, float f) { - v0.a *= f; - v0.r *= f; - v0.g *= f; - v0.b *= f; + v0.x *= f; + v0.y *= f; + v0.z *= f; + v0.w *= f; return v0; } |
