Commit: 330a74720ecc865ef988c42763d9f62ed7e10991
Parent: 99991ca2edf0d7e96ff989a366b58f7c13544ea4
Author: Randy Palamar
Date: Wed, 7 Aug 2024 22:15:24 -0600
move slider mode lerping to shader
Diffstat:
M | build.sh | | | 2 | +- |
M | colourpicker.c | | | 174 | +++++++++++++++++++++++++++++++------------------------------------------------ |
M | config.def.h | | | 2 | +- |
D | hsv_lerp.glsl | | | 86 | ------------------------------------------------------------------------------- |
A | slider_lerp.glsl | | | 132 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | util.c | | | 7 | +++---- |
6 files changed, 205 insertions(+), 198 deletions(-)
diff --git a/build.sh b/build.sh
@@ -30,7 +30,7 @@ fi
[ ! -s "config.h" ] && cp config.def.h config.h
-if [ ! -e "external/include/shader_inc.h" ] || [ "hsv_lerp.glsl" -nt "external/include/shader_inc.h" ]; then
+if [ ! -e "external/include/shader_inc.h" ] || [ "slider_lerp.glsl" -nt "external/include/shader_inc.h" ]; then
${cc} $cflags -o gen_incs gen_incs.c $ldflags
./gen_incs
mv lora_sb*.h external/include/
diff --git a/colourpicker.c b/colourpicker.c
@@ -214,38 +214,6 @@ step_colour_mode(ColourPickerCtx *ctx, i32 inc)
}
static void
-fill_hsv_texture(RenderTexture texture, v4 hsv, Color bg)
-{
- f32 line_length = (f32)texture.texture.height / 3;
- v2 vtop = {0};
- v2 vbot = { .y = vtop.y + line_length };
- v2 sbot = { .y = vbot.y + line_length };
- v2 hbot = { .y = sbot.y + line_length };
-
- v4 h = hsv, s = hsv, v = hsv;
- h.x = 0;
- s.y = 0;
- v.z = 0;
-
- f32 inc = 1.0 / texture.texture.width;
- BeginTextureMode(texture);
- ClearBackground(bg);
- for (u32 i = 0; i < texture.texture.width; i++) {
- DrawLineV(sbot.rv, hbot.rv, colour_from_normalized(hsv_to_rgb(h)));
- DrawLineV(vbot.rv, sbot.rv, colour_from_normalized(hsv_to_rgb(s)));
- DrawLineV(vtop.rv, vbot.rv, colour_from_normalized(hsv_to_rgb(v)));
- hbot.x += 1.0;
- sbot.x += 1.0;
- vtop.x += 1.0;
- vbot.x += 1.0;
- h.x += inc;
- s.y += inc;
- v.z += inc;
- }
- EndTextureMode();
-}
-
-static void
get_slider_subrects(Rect r, Rect *label, Rect *slider, Rect *value)
{
if (label) *label = cut_rect_left(r, 0.08);
@@ -500,42 +468,6 @@ do_slider(ColourPickerCtx *ctx, Rect r, i32 label_idx, v2 relative_origin)
ctx->held_idx = -1;
f32 current = ctx->colour.E[label_idx];
- Rect srl = cut_rect_left(sr, current);
- Rect srr = cut_rect_right(sr, current);
-
- /* TODO: this should probably be a switch */
- if (ctx->colour_mode == CM_RGB) {
- Color sel, left, right;
- v4 cl = ctx->colour;
- v4 cr = ctx->colour;
- cl.E[label_idx] = 0;
- cr.E[label_idx] = 1;
- left = colour_from_normalized(cl);
- right = colour_from_normalized(cr);
- sel = colour_from_normalized(ctx->colour);
- DrawRectangleGradientEx(srl.rr, left, left, sel, sel);
- DrawRectangleGradientEx(srr.rr, sel, sel, right, right);
- } else {
- if (label_idx == 3) { /* Alpha */
- Color sel = colour_from_normalized(hsv_to_rgb(ctx->colour));
- Color left = sel;
- Color right = sel;
- left.a = 0;
- right.a = 255;
- DrawRectangleGradientEx(srl.rr, left, left, sel, sel);
- DrawRectangleGradientEx(srr.rr, sel, sel, right, right);
- } else {
- Rect tr = {0};
- tr.pos.y += ctx->hsv_texture.texture.height / 3 * label_idx;
- tr.size.h = sr.size.h;
- tr.size.w = ctx->hsv_texture.texture.width;
- DrawTexturePro(ctx->hsv_texture.texture, tr.rr, sr.rr, (Vector2){0}, 0, WHITE);
- }
- }
-
- DrawRectangleRoundedLinesEx(sr.rr, SLIDER_ROUNDNESS, 0, 4.85 * SLIDER_BORDER_WIDTH, ctx->bg);
- DrawRectangleRoundedLinesEx(sr.rr, SLIDER_ROUNDNESS, 0, SLIDER_BORDER_WIDTH,
- SLIDER_BORDER_COLOUR);
{
f32 scale_delta = (SLIDER_SCALE_TARGET - 1.0) * SLIDER_SCALE_SPEED * ctx->dt;
@@ -811,36 +743,56 @@ do_slider_mode(ColourPickerCtx *ctx, v2 relative_origin)
};
Rect sb = tr;
Rect ss = tr;
+ sb.size.h *= 0.1;
ss.size.h *= 0.15;
-
- if (ctx->flags & CPF_REFILL_TEXTURE) {
- Rect sr;
- get_slider_subrects(ss, 0, &sr, 0);
- if (ctx->hsv_texture.texture.width != (i32)(sr.size.w + 0.5)) {
- i32 w = sr.size.w + 0.5;
- i32 h = sr.size.h * 3;
- h += 3 - (h % 3);
- UnloadRenderTexture(ctx->hsv_texture);
- ctx->hsv_texture = LoadRenderTexture(w, h);
- }
- fill_hsv_texture(ctx->hsv_texture, get_formatted_colour(ctx, CM_HSV), ctx->bg);
- ctx->flags &= ~CPF_REFILL_TEXTURE;
- }
+ ss.pos.y += 1.2 * sb.size.h;
BeginTextureMode(ctx->slider_texture);
ClearBackground(ctx->bg);
- sb.size.h *= 0.1;
do_status_bar(ctx, sb, relative_origin);
- ss.pos.y += 1.2 * sb.size.h;
- f32 y_pad = 0.525 * ss.size.h;
+ Rect sr;
+ get_slider_subrects(ss, 0, &sr, 0);
+ f32 r_bound = sr.pos.x + sr.size.w;
+ f32 y_step = 1.525 * ss.size.h;
for (i32 i = 0; i < 4; i++) {
do_slider(ctx, ss, i, relative_origin);
- ss.pos.y += ss.size.h + y_pad;
+ ss.pos.y += y_step;
}
+ BeginShaderMode(ctx->picker_shader);
+ {
+ f32 start_y = sr.pos.y - 0.5 * ss.size.h;
+ f32 end_y = start_y + sr.size.h;
+ f32 regions[] = {
+ sr.pos.x, start_y + 3 * y_step, r_bound, end_y + 3 * y_step,
+ sr.pos.x, start_y + 2 * y_step, r_bound, end_y + 2 * y_step,
+ sr.pos.x, start_y + 1 * y_step, r_bound, end_y + 1 * y_step,
+ sr.pos.x, start_y + 0 * y_step, r_bound, end_y + 0 * y_step
+ };
+
+ f32 radius = SLIDER_BORDER_RADIUS;
+ f32 border_thick = SLIDER_BORDER_WIDTH;
+ i32 cm_mode = ctx->colour_mode;
+ i32 mode = ctx->mode;
+
+ SetShaderValue(ctx->picker_shader, ctx->mode_id, &mode, SHADER_UNIFORM_INT);
+ SetShaderValue(ctx->picker_shader, ctx->radius_id, &radius, SHADER_UNIFORM_FLOAT);
+ SetShaderValue(ctx->picker_shader, ctx->border_thick_id, &border_thick,
+ SHADER_UNIFORM_FLOAT);
+ SetShaderValue(ctx->picker_shader, ctx->colour_mode_id, &cm_mode,
+ SHADER_UNIFORM_INT);
+ SetShaderValue(ctx->picker_shader, ctx->size_id, tr.size.E, SHADER_UNIFORM_VEC2);
+ SetShaderValue(ctx->picker_shader, ctx->colours_id, ctx->colour.E,
+ SHADER_UNIFORM_VEC4);
+ SetShaderValueV(ctx->picker_shader, ctx->regions_id, regions,
+ SHADER_UNIFORM_VEC4, 4);
+ DrawRectangleRec(tr.rr, BLACK);
+ }
+ EndShaderMode();
+
EndTextureMode();
}
@@ -895,20 +847,6 @@ do_vertical_slider(ColourPickerCtx *ctx, v2 test_pos, Rect r, i32 idx,
static void
do_picker_mode(ColourPickerCtx *ctx, v2 relative_origin)
{
- if (!IsShaderReady(ctx->picker_shader)) {
-#ifdef _DEBUG
- ctx->picker_shader = LoadShader(0, HSV_LERP_SHADER_NAME);
-#else
- ctx->picker_shader = LoadShaderFromMemory(0, g_hsv_shader_text);
-#endif
- ctx->colour_mode_id = GetShaderLocation(ctx->picker_shader, "u_colour_mode");
- ctx->colours_id = GetShaderLocation(ctx->picker_shader, "u_colours");
- ctx->regions_id = GetShaderLocation(ctx->picker_shader, "u_regions");
- ctx->size_id = GetShaderLocation(ctx->picker_shader, "u_size");
- ctx->radius_id = GetShaderLocation(ctx->picker_shader, "u_radius");
- ctx->border_thick_id = GetShaderLocation(ctx->picker_shader, "u_border_thick");
- }
-
v4 colour = get_formatted_colour(ctx, CM_HSV);
colour.x = ctx->pms.base_hue + ctx->pms.fractional_hue;
@@ -928,6 +866,7 @@ do_picker_mode(ColourPickerCtx *ctx, v2 relative_origin)
test_pos.y -= relative_origin.y;
BeginTextureMode(ctx->picker_texture);
+ ClearBackground(ctx->bg);
v4 hsv[3] = {colour, colour, colour};
hsv[1].x = 0;
@@ -952,7 +891,6 @@ do_picker_mode(ColourPickerCtx *ctx, v2 relative_origin)
colour = do_vertical_slider(ctx, test_pos, hs2, PM_MIDDLE, hsv[2], hsv[1], colour);
ctx->pms.fractional_hue = colour.x - ctx->pms.base_hue;
- ClearBackground(ctx->bg);
BeginShaderMode(ctx->picker_shader);
{
f32 regions[] = {
@@ -963,7 +901,9 @@ do_picker_mode(ColourPickerCtx *ctx, v2 relative_origin)
f32 radius = SLIDER_BORDER_RADIUS;
f32 border_thick = SLIDER_BORDER_WIDTH;
i32 cm_mode = CM_HSV;
+ i32 mode = ctx->mode;
+ SetShaderValue(ctx->picker_shader, ctx->mode_id, &mode, SHADER_UNIFORM_INT);
SetShaderValue(ctx->picker_shader, ctx->radius_id, &radius, SHADER_UNIFORM_FLOAT);
SetShaderValue(ctx->picker_shader, ctx->border_thick_id, &border_thick,
SHADER_UNIFORM_FLOAT);
@@ -1045,9 +985,8 @@ DEBUG_EXPORT void
do_colour_picker(ColourPickerCtx *ctx, f32 dt, Vector2 window_pos, Vector2 mouse_pos)
{
if (IsWindowResized()) {
- ctx->window_size.h = GetScreenHeight();
- ctx->window_size.w = ctx->window_size.h / WINDOW_ASPECT_RATIO;
- ctx->flags |= CPF_REFILL_TEXTURE;
+ ctx->window_size.h = GetScreenHeight();
+ ctx->window_size.w = ctx->window_size.h / WINDOW_ASPECT_RATIO;
SetWindowSize(ctx->window_size.w, ctx->window_size.h);
UnloadTexture(ctx->font.texture);
@@ -1056,6 +995,21 @@ do_colour_picker(ColourPickerCtx *ctx, f32 dt, Vector2 window_pos, Vector2 mouse
ctx->font_size = ctx->font.baseSize;
}
+ if (!IsShaderReady(ctx->picker_shader)) {
+#ifdef _DEBUG
+ ctx->picker_shader = LoadShader(0, HSV_LERP_SHADER_NAME);
+#else
+ ctx->picker_shader = LoadShaderFromMemory(0, g_hsv_shader_text);
+#endif
+ ctx->mode_id = GetShaderLocation(ctx->picker_shader, "u_mode");
+ ctx->colour_mode_id = GetShaderLocation(ctx->picker_shader, "u_colour_mode");
+ ctx->colours_id = GetShaderLocation(ctx->picker_shader, "u_colours");
+ ctx->regions_id = GetShaderLocation(ctx->picker_shader, "u_regions");
+ ctx->size_id = GetShaderLocation(ctx->picker_shader, "u_size");
+ ctx->radius_id = GetShaderLocation(ctx->picker_shader, "u_radius");
+ ctx->border_thick_id = GetShaderLocation(ctx->picker_shader, "u_border_thick");
+ }
+
ctx->dt = dt;
ctx->mouse_pos.rv = mouse_pos;
ctx->window_pos.rv = window_pos;
@@ -1084,8 +1038,12 @@ do_colour_picker(ColourPickerCtx *ctx, f32 dt, Vector2 window_pos, Vector2 mouse
i32 h = ma.size.h;
UnloadRenderTexture(ctx->picker_texture);
ctx->picker_texture = LoadRenderTexture(w, h);
- if (ctx->mode != CPM_PICKER)
+ if (ctx->mode != CPM_PICKER) {
+ i32 mode = ctx->mode;
+ ctx->mode = CPM_PICKER;
do_picker_mode(ctx, ma.pos);
+ ctx->mode = mode;
+ }
}
if (ctx->slider_texture.texture.width != (i32)(ma.size.w)) {
@@ -1093,8 +1051,12 @@ do_colour_picker(ColourPickerCtx *ctx, f32 dt, Vector2 window_pos, Vector2 mouse
i32 h = ma.size.h;
UnloadRenderTexture(ctx->slider_texture);
ctx->slider_texture = LoadRenderTexture(w, h);
- if (ctx->mode != CPM_SLIDERS)
+ if (ctx->mode != CPM_SLIDERS) {
+ i32 mode = ctx->mode;
+ ctx->mode = CPM_SLIDERS;
do_slider_mode(ctx, ma.pos);
+ ctx->mode = mode;
+ }
}
}
diff --git a/config.def.h b/config.def.h
@@ -1,6 +1,6 @@
/* NOTE: This is used by gen_incs for generating font_inc.h and shader_inc.h */
#define FONT_SIZE 40u
-#define HSV_LERP_SHADER_NAME "hsv_lerp.glsl"
+#define HSV_LERP_SHADER_NAME "slider_lerp.glsl"
/* NOTE: Values below here are just used for initializing the ctx in main.
* They are not needed if you are are embedding into another application. */
diff --git a/hsv_lerp.glsl b/hsv_lerp.glsl
@@ -1,86 +0,0 @@
-/* See LICENSE for copyright details */
-#version 330
-
-in vec2 fragTexCoord;
-in vec4 fragColor;
-
-out vec4 out_colour;
-
-#define CM_RGB 0
-#define CM_HSV 1
-
-uniform int u_colour_mode;
-uniform float u_radius;
-uniform float u_border_thick;
-uniform vec4 u_colours[3];
-uniform vec4 u_regions[4];
-uniform vec2 u_size;
-
-/* input: h [0,360] | s,v [0, 1] *
- * output: rgb [0,1] */
-vec3 hsv2rgb(vec3 hsv)
-{
- vec3 k = mod(vec3(5, 3, 1) + hsv.x / 60, 6);
- k = max(min(min(k, 4 - k), 1), 0);
- return hsv.z - hsv.z * hsv.y * k;
-}
-
-bool in_rounded_region(vec2 pos, vec4 min_max, float radius)
-{
- vec2 min_xy = min_max.xy;
- vec2 max_xy = min_max.zw;
- vec2 ulp = vec2(min_xy.x + radius, max_xy.y - radius);
- vec2 urp = vec2(max_xy.x - radius, max_xy.y - radius);
- vec2 blp = vec2(min_xy.x + radius, min_xy.y + radius);
- vec2 brp = vec2(max_xy.x - radius, min_xy.y + radius);
-
- bool ulr = length(ulp - pos) < radius;
- bool urr = length(urp - pos) < radius;
- bool blr = length(blp - pos) < radius;
- bool brr = length(brp - pos) < radius;
- bool rect = (pos.x > min_xy.x) && (pos.x < max_xy.x) &&
- (pos.y < max_xy.y - radius) && (pos.y > min_xy.y + radius);
- bool upr = (pos.x > ulp.x) && (pos.x < urp.x) && (pos.y < max_xy.y) && (pos.y > min_xy.y);
-
- return rect || ulr || urr || blr || brr || upr;
-}
-
-void main()
-{
- vec2 pos = gl_FragCoord.xy;
-
- vec4 colour = vec4(0);
- switch (u_colour_mode) {
- case CM_RGB:
- out_colour = vec4(0);
- break;
- case CM_HSV:
- vec4 shift = vec4(vec2(u_border_thick), -vec2(u_border_thick));
-
- if (in_rounded_region(pos, u_regions[0], u_radius + u_border_thick)) {
- colour.w = 1;
- if (in_rounded_region(pos, u_regions[0] + shift, u_radius)) {
- float scale = u_regions[0].w - u_regions[0].y;
- colour = mix(vec4(1, u_colours[0].yzw), vec4(0, u_colours[0].yzw),
- (pos.y - u_regions[0].y) / scale);
- }
- } else if (in_rounded_region(pos, u_regions[1], u_radius + u_border_thick)) {
- colour.w = 1;
- if (in_rounded_region(pos, u_regions[1] + shift, u_radius)) {
- float scale = u_regions[1].w - u_regions[1].y;
- colour = mix(u_colours[2], u_colours[1],
- (pos.y - u_regions[1].y) / scale);
- }
- } else if (in_rounded_region(pos, u_regions[2], u_radius + u_border_thick)) {
- colour.w = 1;
- if (in_rounded_region(pos, u_regions[2] + shift, u_radius)) {
- vec2 scale = u_regions[2].zw - u_regions[2].xy;
- vec2 t = (pos - u_regions[2].xy) / scale;
- colour = vec4(u_colours[0].x, t.x, t.y, 1);
- }
- }
- colour.x *= 360;
- out_colour = vec4(hsv2rgb(colour.xyz), colour.w);
- break;
- }
-}
diff --git a/slider_lerp.glsl b/slider_lerp.glsl
@@ -0,0 +1,132 @@
+/* See LICENSE for copyright details */
+#version 330
+
+/* TODO: this shader should be instanced!! */
+
+in vec2 fragTexCoord;
+in vec4 fragColor;
+
+out vec4 out_colour;
+
+#define CPM_PICKER 0
+#define CPM_SLIDERS 1
+
+#define CM_RGB 0
+#define CM_HSV 1
+
+uniform int u_mode;
+uniform int u_colour_mode;
+uniform float u_radius;
+uniform float u_border_thick;
+uniform vec4 u_colours[3];
+uniform vec4 u_regions[4];
+uniform vec2 u_size;
+
+/* input: h [0,360] | s,v [0, 1] *
+ * output: rgb [0,1] */
+vec3 hsv2rgb(vec3 hsv)
+{
+ vec3 k = mod(vec3(5, 3, 1) + hsv.x / 60, 6);
+ k = max(min(min(k, 4 - k), 1), 0);
+ return hsv.z - hsv.z * hsv.y * k;
+}
+
+bool in_rounded_region(vec2 pos, vec4 min_max, float radius)
+{
+ vec2 min_xy = min_max.xy;
+ vec2 max_xy = min_max.zw;
+ vec2 ulp = vec2(min_xy.x + radius, max_xy.y - radius);
+ vec2 urp = vec2(max_xy.x - radius, max_xy.y - radius);
+ vec2 blp = vec2(min_xy.x + radius, min_xy.y + radius);
+ vec2 brp = vec2(max_xy.x - radius, min_xy.y + radius);
+
+ bool ulr = length(ulp - pos) < radius;
+ bool urr = length(urp - pos) < radius;
+ bool blr = length(blp - pos) < radius;
+ bool brr = length(brp - pos) < radius;
+ bool rect = (pos.x > min_xy.x) && (pos.x < max_xy.x) &&
+ (pos.y < max_xy.y - radius) && (pos.y > min_xy.y + radius);
+ bool upr = (pos.x > ulp.x) && (pos.x < urp.x) && (pos.y < max_xy.y) && (pos.y > min_xy.y);
+
+ return rect || ulr || urr || blr || brr || upr;
+}
+
+vec4 picker_mode(vec2 pos)
+{
+ vec4 result = vec4(0);
+ vec4 shift = vec4(vec2(u_border_thick), -vec2(u_border_thick));
+
+ if (in_rounded_region(pos, u_regions[0], u_radius + u_border_thick)) {
+ result.w = 1;
+ if (in_rounded_region(pos, u_regions[0] + shift, u_radius)) {
+ float scale = u_regions[0].w - u_regions[0].y;
+ result = mix(vec4(1, u_colours[0].yzw), vec4(0, u_colours[0].yzw),
+ (pos.y - u_regions[0].y) / scale);
+ }
+ } else if (in_rounded_region(pos, u_regions[1], u_radius + u_border_thick)) {
+ result.w = 1;
+ if (in_rounded_region(pos, u_regions[1] + shift, u_radius)) {
+ float scale = u_regions[1].w - u_regions[1].y;
+ result = mix(u_colours[2], u_colours[1],
+ (pos.y - u_regions[1].y) / scale);
+ }
+ } else if (in_rounded_region(pos, u_regions[2], u_radius + u_border_thick)) {
+ result.w = 1;
+ if (in_rounded_region(pos, u_regions[2] + shift, u_radius)) {
+ vec2 scale = u_regions[2].zw - u_regions[2].xy;
+ vec2 t = (pos - u_regions[2].xy) / scale;
+ result = vec4(u_colours[0].x, t.x, t.y, 1);
+ }
+ }
+
+ result.x *= 360;
+ return vec4(hsv2rgb(result.xyz), result.w);
+}
+
+bool slider_fill(vec2 pos, int idx, out vec4 colour)
+{
+ bool result = false;
+ vec4 shift = vec4(vec2(u_border_thick), -vec2(u_border_thick));
+ colour = vec4(0);
+ if (in_rounded_region(pos, u_regions[idx], u_radius + u_border_thick)) {
+ colour.w = 1;
+ if (in_rounded_region(pos, u_regions[idx] + shift, u_radius)) {
+ float scale = u_regions[idx].z - u_regions[idx].x;
+ vec4 c1 = u_colours[0];
+ vec4 c2 = u_colours[0];
+ c1[idx] = 0;
+ c2[idx] = 1;
+ colour = mix(c1, c2, (pos.x - u_regions[idx].x) / scale);
+ }
+ result = true;
+ }
+ return result;
+}
+
+vec4 slider_mode(vec2 pos)
+{
+ vec4 result = vec4(0);
+ vec4 fill_out;
+
+ if (slider_fill(pos, 0, fill_out)) result = fill_out;
+ else if (slider_fill(pos, 1, fill_out)) result = fill_out;
+ else if (slider_fill(pos, 2, fill_out)) result = fill_out;
+ else if (slider_fill(pos, 3, fill_out)) result = fill_out;
+
+ switch (u_colour_mode) {
+ case CM_RGB: break;
+ case CM_HSV: result.x *= 360; result = vec4(hsv2rgb(result.xyz), result.w); break;
+ }
+
+ return result;
+}
+
+void main()
+{
+ vec2 pos = gl_FragCoord.xy;
+ out_colour = vec4(0);
+ switch (u_mode) {
+ case CPM_PICKER: out_colour = picker_mode(pos); break;
+ case CPM_SLIDERS: out_colour = slider_mode(pos); break;
+ }
+}
diff --git a/util.c b/util.c
@@ -64,8 +64,8 @@ enum colour_mode {
};
enum colour_picker_mode {
- CPM_PICKER,
- CPM_SLIDERS,
+ CPM_PICKER = 0,
+ CPM_SLIDERS = 1,
CPM_LAST
};
@@ -181,9 +181,8 @@ typedef struct {
Shader picker_shader;
RenderTexture slider_texture;
RenderTexture picker_texture;
- RenderTexture hsv_texture;
- i32 colour_mode_id, colours_id;
+ i32 mode_id, colour_mode_id, colours_id;
i32 regions_id, size_id;
i32 radius_id, border_thick_id;