summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/graph.c2
-rw-r--r--examples/julia_set.c2
-rw-r--r--examples/ui.c8
-rw-r--r--graphics.c165
4 files changed, 116 insertions, 61 deletions
diff --git a/examples/graph.c b/examples/graph.c
index 99f916d..f196d3d 100644
--- a/examples/graph.c
+++ b/examples/graph.c
@@ -502,7 +502,7 @@ void update_and_render_frame(void) {
// Render
- fill_rectangle((Brush) { .color = { .7f, .8f, .9f, 1.f } }, 0, 0, g_platform.frame_width, g_platform.frame_height);
+ fill_rectangle((Brush) { .color = { .7f, .8f, .9f, 1.f } }, 0, 0, g_platform.real_width, g_platform.real_height);
if (adding_edge) {
f64 x0 = world.nodes[adding_src].x;
diff --git a/examples/julia_set.c b/examples/julia_set.c
index c7f7e9b..a5b733e 100644
--- a/examples/julia_set.c
+++ b/examples/julia_set.c
@@ -71,7 +71,7 @@ void update_and_render_frame(void) {
for (i32 jj = 0; jj < p; ++jj)
for (i32 ii = 0; ii < p; ++ii)
- g_platform.pixels[(j + jj) * g_platform.frame_width + (i + ii)] = with_alpha(rgb_f32_from_u32(c), 1.f);
+ g_platform.pixels[(j + jj) * g_platform.frame_width + (i + ii)] = vec4_from_vec3_f32(rgb_f32_from_u32(c), 1.f);
}
p_render_frame();
diff --git a/examples/ui.c b/examples/ui.c
index 8375e4d..c10a9c6 100644
--- a/examples/ui.c
+++ b/examples/ui.c
@@ -60,11 +60,11 @@ void update_and_render_frame(void) {
f64 x0 = w / 2.0;
f64 y0 = h / 2.0;
- vec3_f32 color = { 1.f, .5f, .5f };
+ vec4_f32 color = { 1.f, .5f, .5f, 1.f };
if (g_platform.cursor_x >= x0 && g_platform.cursor_x < x0 + w &&
g_platform.cursor_y >= y0 && g_platform.cursor_y < y0 + h)
- color = (vec3_f32) { 1.f, 1.f, 1.f };
+ color = (vec4_f32) { 1.f, 1.f, 1.f, 1.f };
for (i64 i = 0; i < g_platform.input_size; ++i)
if (g_platform.input[i].ctrl)
@@ -223,8 +223,8 @@ void update_and_render_frame(void) {
}
draw_text_area(RGB(0.f, 0.f, 0.f), x0 + 8, y0 - 8, w, h, 10., 10., text_len, text);
- draw_text_area((Brush) { .color = with_alpha(color, 1.f) }, x0, y0, w, h, 10., 10., text_len, text);
- draw_text_cursor((Brush) { .xor_color = 1, .color = { 1.f, 1.f, 1.f, 1.f } }, x0, y0, w, h, 10., 10., cursor, selection, text_len, text);
+ draw_text_area((Brush) { .color = color, }, x0, y0, w, h, 10., 10., text_len, text);
+ draw_text_cursor((Brush) { .xor_color = 1, .color = { 1.f, 1.f, 1.f, 1.f }, }, x0, y0, w, h, 10., 10., cursor, selection, text_len, text);
p_render_frame();
}
diff --git a/graphics.c b/graphics.c
index dc2a88e..62a6472 100644
--- a/graphics.c
+++ b/graphics.c
@@ -23,8 +23,8 @@
//
// ================================================================
-vec4_f32 vec4_from_vec3_f32(vec3_f32 v, f32 w);
vec3_f32 vec3_from_vec4_f32(vec4_f32 v);
+vec4_f32 vec4_from_vec3_f32(vec3_f32 v, f32 w);
vec3_f32 vec3_f32_lerp (vec3_f32 a, vec3_f32 b, f32 t);
vec4_f32 vec4_f32_lerp (vec4_f32 a, vec4_f32 b, f32 t);
@@ -149,15 +149,8 @@ static f64 gamma_re_(f64 x) {
return x / 12.92;
}
-static void put_pixel_xor_(Brush brush, i64 x, i64 y) {
- i64 n = y * brush.buffer.line_size + x;
-
- vec3_f32 c = rgb_f32_from_u32(
- rgb_u32_from_f32(vec3_from_vec4_f32(brush.buffer.pixels[n]))
- ^ rgb_u32_from_f32(vec3_from_vec4_f32(brush.color))
- );
-
- brush.buffer.pixels[n] = vec4_from_vec3_f32(c, 1.f);;
+static void put_pixel_color_(Brush brush, i64 x, i64 y) {
+ brush.buffer.pixels[y * brush.buffer.line_size + x] = brush.color;
}
static void put_pixel_alpha_(Brush brush, i64 x, i64 y) {
@@ -174,8 +167,20 @@ static void put_pixel_alpha_(Brush brush, i64 x, i64 y) {
};
}
-static void put_pixel_color_(Brush brush, i64 x, i64 y) {
- brush.buffer.pixels[y * brush.buffer.line_size + x] = brush.color;
+static void put_pixel_xor_(Brush brush, i64 x, i64 y) {
+ i64 n = y * brush.buffer.line_size + x;
+
+ vec3_f32 c = rgb_f32_from_u32(
+ rgb_u32_from_f32(vec3_from_vec4_f32(brush.buffer.pixels[n]))
+ ^ rgb_u32_from_f32(vec3_from_vec4_f32(brush.color))
+ );
+
+ brush.color = vec4_from_vec3_f32(c, brush.color.w);
+
+ if (brush.alpha)
+ put_pixel_alpha_(brush, x, y);
+ else
+ brush.buffer.pixels[n] = brush.color;
}
static void put_pixel_(Brush brush, i64 x, i64 y) {
@@ -188,6 +193,9 @@ static void put_pixel_(Brush brush, i64 x, i64 y) {
}
void fill_rectangle_(Brush brush, f64 x, f64 y, f64 width, f64 height) {
+ if (width < EPSILON || height < EPSILON)
+ return;
+
f64 x0, y0, x1, y1;
if (brush.scale.x < 0) {
@@ -245,50 +253,50 @@ void fill_rectangle_(Brush brush, f64 x, f64 y, f64 width, f64 height) {
brush.alpha = 1;
if (i00 - 1 >= 0 && i00 - 1 < brush.buffer.width) {
- brush.color.w = alpha * gamma_(kx0);
+ brush.color.w = gamma_(gamma_re_(alpha) * kx0);
for (i64 j = j0; j < j1; ++j)
put_pixel_(brush, i00 - 1, j);
}
if (i10 >= 0 && i10 < brush.buffer.width) {
- brush.color.w = alpha * gamma_(kx1);
+ brush.color.w = gamma_(gamma_re_(alpha) * kx1);
for (i64 j = j0; j < j1; ++j)
put_pixel_(brush, i10, j);
}
if (j00 - 1 >= 0 && j00 - 1 < brush.buffer.height) {
- brush.color.w = alpha * gamma_(ky0);
+ brush.color.w = gamma_(gamma_re_(alpha) * ky0);
for (i64 i = i0; i < i1; ++i)
put_pixel_(brush, i, j00 - 1);
}
if (j10 >= 0 && j10 < brush.buffer.height) {
- brush.color.w = alpha * gamma_(ky1);
+ brush.color.w = gamma_(gamma_re_(alpha) * ky1);
for (i64 i = i0; i < i1; ++i)
put_pixel_(brush, i, j10);
}
if ( i00 - 1 >= 0 && i00 - 1 < brush.buffer.width
&& j00 - 1 >= 0 && j00 - 1 < brush.buffer.height) {
- brush.color.w = alpha * gamma_(kx0 * ky0);
+ brush.color.w = gamma_(gamma_re_(alpha) * kx0 * ky0);
put_pixel_(brush, i00 - 1, j00 - 1);
}
if ( i10 >= 0 && i10 < brush.buffer.width
&& j00 - 1 >= 0 && j00 - 1 < brush.buffer.height) {
- brush.color.w = alpha * gamma_(kx1 * ky0);
+ brush.color.w = gamma_(gamma_re_(alpha) * kx1 * ky0);
put_pixel_(brush, i10, j00 - 1);
}
if ( i00 - 1 >= 0 && i00 - 1 < brush.buffer.width
&& j10 >= 0 && j10 < brush.buffer.height) {
- brush.color.w = alpha * gamma_(kx0 * ky1);
+ brush.color.w = gamma_(gamma_re_(alpha) * kx0 * ky1);
put_pixel_(brush, i00 - 1, j10);
}
if ( i10 >= 0 && i10 < brush.buffer.width
&& j10 >= 0 && j10 < brush.buffer.height) {
- brush.color.w = alpha * gamma_(kx1 * ky1);
+ brush.color.w = gamma_(gamma_re_(alpha) * kx1 * ky1);
put_pixel_(brush, i10, j10);
}
} else {
@@ -302,9 +310,18 @@ void fill_rectangle_(Brush brush, f64 x, f64 y, f64 width, f64 height) {
if (j0 < 0) j0 = 0;
if (j1 > brush.buffer.height) j1 = brush.buffer.height;
- for (i64 j = j0; j < j1; ++j)
- for (i64 i = i0; i < i1; ++i)
- put_pixel_(brush, i, j);
+ if (brush.xor_color)
+ for (i64 j = j0; j < j1; ++j)
+ for (i64 i = i0; i < i1; ++i)
+ put_pixel_xor_(brush, i, j);
+ else if (brush.alpha)
+ for (i64 j = j0; j < j1; ++j)
+ for (i64 i = i0; i < i1; ++i)
+ put_pixel_alpha_(brush, i, j);
+ else
+ for (i64 j = j0; j < j1; ++j)
+ for (i64 i = i0; i < i1; ++i)
+ put_pixel_color_(brush, i, j);
}
}
@@ -323,18 +340,34 @@ void fill_triangle_(Brush brush, f64 x0, f64 y0, f64 x1, f64 y1, f64 x2, f64 y2)
i64 i0 = (i64) floor(min3_(x0, x1, x2));
i64 j0 = (i64) floor(min3_(y0, y1, y2));
- i64 i1 = (i64) ceil (max3_(x0, x1, x2)) + 1;
- i64 j1 = (i64) ceil (max3_(y0, y1, y2)) + 1;
+ i64 i1 = (i64) ceil (max3_(x0, x1, x2));
+ i64 j1 = (i64) ceil (max3_(y0, y1, y2));
+
+ if (j0 < 0) j0 = 0;
+ if (j1 >= brush.buffer.height) j1 = brush.buffer.height - 1;
- if (i0 < 0) i0 = 0;
- if (i1 > brush.buffer.width) i1 = brush.buffer.width;
- if (j0 < 0) j0 = 0;
- if (j1 > brush.buffer.height) j1 = brush.buffer.height;
+ for (i64 j = j0; j <= j1; ++j) {
+ i64 left = i1;
+ i64 right = i0;
- for (i64 j = j0; j < j1; ++j)
- for (i64 i = i0; i < i1; ++i)
- if (triangle_contains(x0, y0, x1, y1, x2, y2, (f64) i, (f64) j))
- put_pixel_(brush, i, j);
+ for (i64 i = i0; i <= i1; ++i)
+ if (triangle_contains(x0, y0, x1, y1, x2, y2, (f64) i, (f64) j)) {
+ left = i;
+ break;
+ }
+
+ for (i64 i = i1; i >= i0; --i)
+ if (triangle_contains(x0, y0, x1, y1, x2, y2, (f64) i, (f64) j)) {
+ right = i;
+ break;
+ }
+
+ if (left < 0) left = 0;
+ if (right >= brush.buffer.width) right = brush.buffer.width - 1;
+
+ for (i64 i = left; i <= right; ++i)
+ put_pixel_(brush, i, j);
+ }
}
static i64 char_column_offset_(c32 c, i64 column_index) {
@@ -568,20 +601,20 @@ static Brush brush_defaults_(Brush b) {
// ================================================================
-vec4_f32 vec4_from_vec3_f32(vec3_f32 v, f32 w) {
- return (vec4_f32) {
+vec3_f32 vec3_from_vec4_f32(vec4_f32 v) {
+ return (vec3_f32) {
.x = v.x,
.y = v.y,
.z = v.z,
- .w = w,
};
}
-vec3_f32 vec3_from_vec4_f32(vec4_f32 v) {
- return (vec3_f32) {
+vec4_f32 vec4_from_vec3_f32(vec3_f32 v, f32 w) {
+ return (vec4_f32) {
.x = v.x,
.y = v.y,
.z = v.z,
+ .w = w,
};
}
@@ -807,13 +840,21 @@ b8 triangle_contains(f64 x0, f64 y0, f64 x1, f64 y1, f64 x2, f64 y2, f64 px, f64
// Z-components of cross-products
//
- f64 z0 = (x1 - x0) * (y2 - y0) - (x2 - x0) * (y1 - y0);
- f64 z1 = (x2 - x1) * (y0 - y1) - (x0 - x1) * (y2 - y1);
- f64 z2 = (x0 - x2) * (y1 - y2) - (x1 - x2) * (y0 - y2);
+ f64 x10 = x1 - x0;
+ f64 x21 = x2 - x1;
+ f64 x02 = x0 - x2;
+
+ f64 y10 = y1 - y0;
+ f64 y21 = y2 - y1;
+ f64 y02 = y0 - y2;
- f64 pz0 = (px - x0) * (y2 - y0) - (x2 - x0) * (py - y0);
- f64 pz1 = (px - x1) * (y0 - y1) - (x0 - x1) * (py - y1);
- f64 pz2 = (px - x2) * (y1 - y2) - (x1 - x2) * (py - y2);
+ f64 z0 = x02 * y10 - x10 * y02;
+ f64 z1 = x10 * y21 - x21 * y10;
+ f64 z2 = x21 * y02 - x02 * y21;
+
+ f64 pz0 = x02 * (py - y0) - (px - x0) * y02;
+ f64 pz1 = x10 * (py - y1) - (px - x1) * y10;
+ f64 pz2 = x21 * (py - y2) - (px - x2) * y21;
return
same_sign_(z0, pz0)
@@ -949,9 +990,6 @@ void draw_pixels(Brush brush, f64 x, f64 y, f64 width, f64 height, Pixel_Buffer
}
void fill_rectangle(Brush brush, f64 x, f64 y, f64 width, f64 height) {
- if (width < EPSILON || height < EPSILON)
- return;
-
fill_rectangle_(brush_defaults_(brush), x, y, width, height);
}
@@ -991,15 +1029,32 @@ void fill_ellipse(Brush brush, f64 x, f64 y, f64 width, f64 height) {
i64 j0 = (i64) floor(y0);
i64 j1 = (i64) ceil (y1);
- if (i0 < 0) i0 = 0;
- if (i1 > brush.buffer.width) i1 = brush.buffer.width;
- if (j0 < 0) j0 = 0;
- if (j1 > brush.buffer.height) j1 = brush.buffer.height;
+ if (j0 < 0) j0 = 0;
+ if (j1 >= brush.buffer.height) j1 = brush.buffer.height - 1;
- for (i64 j = j0; j < j1; ++j)
- for (i64 i = i0; i < i1; ++i)
- if (ellipse_contains(x0, y0, x1 - x0, y1 - y0, (f64) i, (f64) j))
- put_pixel_(brush, i, j);
+ for (i64 j = j0; j <= j1; ++j) {
+ i64 left = i1;
+ i64 right = i0;
+
+ for (i64 i = i0; i <= i1; ++i)
+ if (ellipse_contains(x0, y0, x1 - x0, y1 - y0, (f64) i, (f64) j)) {
+ left = i;
+ right = (i64) ceil(x0 + x1 - left); // symmetry
+ break;
+ }
+
+ for (i64 i = right; i >= i0; --i)
+ if (ellipse_contains(x0, y0, x1 - x0, y1 - y0, (f64) i, (f64) j)) {
+ right = i;
+ break;
+ }
+
+ if (left < 0) left = 0;
+ if (right >= brush.buffer.width) right = brush.buffer.width - 1;
+
+ for (i64 i = left; i <= right; ++i)
+ put_pixel_(brush, i, j);
+ }
}
void fill_line(Brush brush, f64 x0, f64 y0, f64 x1, f64 y1, f64 width) {