summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/transparency.c188
-rw-r--r--sponge.h41
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;
+ }
+ }
+}
diff --git a/sponge.h b/sponge.h
index f5dcacb..51e1b7d 100644
--- a/sponge.h
+++ b/sponge.h
@@ -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;
}