From de6429a2a147c661cf98bdae6668d6844fdddea5 Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Tue, 8 Oct 2019 12:02:04 -0700 Subject: [PATCH] Good rounded rectangles finished --- 4ed_render_target.cpp | 267 +++----------------------------- 4ed_render_target.h | 7 +- custom/4coder_default_hooks.cpp | 4 +- custom/4coder_helper.cpp | 28 ++++ opengl/4ed_opengl_funcs.h | 1 + opengl/4ed_opengl_render.cpp | 60 ++++++- 6 files changed, 111 insertions(+), 256 deletions(-) diff --git a/4ed_render_target.cpp b/4ed_render_target.cpp index 105f4833..902a8edd 100644 --- a/4ed_render_target.cpp +++ b/4ed_render_target.cpp @@ -131,253 +131,34 @@ end_render_section(Render_Target *target){ //////////////////////////////// internal void -draw_rectangle_sharp(Render_Target *target, Rect_f32 rect, u32 color){ - Render_Vertex vertices[6] = {}; - vertices[0].xy = V2(rect.x0, rect.y0); - vertices[1].xy = V2(rect.x1, rect.y0); - vertices[2].xy = V2(rect.x0, rect.y1); - vertices[3].xy = V2(rect.x1, rect.y0); - vertices[4].xy = V2(rect.x0, rect.y1); - vertices[5].xy = V2(rect.x1, rect.y1); - Vec4_f32 c = unpack_color4(color); - for (i32 i = 0; i < 6; i += 1){ - vertices[i].color = c; +draw_rectangle_outline(Render_Target *target, Rect_f32 rect, f32 roundness, f32 thickness, u32 color){ + if (roundness < epsilon_f32){ + roundness = 0.f; } - draw__write_vertices_in_current_group(target, vertices, 6); -} - -global b32 filled_round_corner = false; -global_const i32 baked_tri_count = 12; -global Vec2_f32 baked_round_corner[baked_tri_count + 1] = {}; - -internal void -bake_round_corner(void){ - if (!filled_round_corner){ - filled_round_corner = true; - Range_f32 theta = If32(0.f, half_pi_f32); - for (i32 k = 0; k < baked_tri_count + 1; k += 1){ - f32 t = ((f32)k)/((f32)baked_tri_count); - f32 theta1 = lerp(t, theta); - baked_round_corner[k] = V2f32(cos_f32(theta1), sin_f32(theta1)); - } - } -} - -internal void -draw_round_corners(Render_Target *target, Rect_f32 mid, f32 roundness, u32 color){ - bake_round_corner(); + thickness = clamp_bot(1.f, thickness); + f32 half_thickness = thickness*0.5f; - for (i32 i = 0; i < 2; i += 1){ - for (i32 j = 0; j < 2; j += 1){ - Vec2_f32 d = {}; - Vec2_f32 p = {}; - if (i == 0){ - if (j == 0){ - p = V2f32(mid.x0, mid.y0); - d = V2f32(-1.f, -1.f); - } - else{ - p = V2f32(mid.x1, mid.y0); - d = V2f32( 1.f, -1.f); - } - } - else{ - if (j == 0){ - p = V2f32(mid.x0, mid.y1); - d = V2f32(-1.f, 1.f); - } - else{ - p = V2f32(mid.x1, mid.y1); - d = V2f32( 1.f, 1.f); - } - } - d *= roundness; - - Render_Vertex vertices[baked_tri_count*3] = {}; - i32 m = 0; - for (i32 k = 0; k < baked_tri_count; k += 1){ - Vec2_f32 p0 = baked_round_corner[k + 0]; - Vec2_f32 p1 = baked_round_corner[k + 1]; - vertices[m].xy = p; - m += 1; - vertices[m].xy = p + hadamard(p0, d); - m += 1; - vertices[m].xy = p + hadamard(p1, d); - m += 1; - } - Vec4_f32 c = unpack_color4(color); - for (i32 k = 0; k < ArrayCount(vertices); k += 1){ - vertices[k].color = c; - } - draw__write_vertices_in_current_group(target, vertices, ArrayCount(vertices)); - } + Render_Vertex vertices[6] = {}; + vertices[0].xy = V2f32(rect.x0, rect.y0); + vertices[1].xy = V2f32(rect.x1, rect.y0); + vertices[2].xy = V2f32(rect.x0, rect.y1); + vertices[3].xy = V2f32(rect.x1, rect.y0); + vertices[4].xy = V2f32(rect.x0, rect.y1); + vertices[5].xy = V2f32(rect.x1, rect.y1); + + Vec2_f32 center = rect_center(rect); + for (i32 i = 0; i < ArrayCount(vertices); i += 1){ + vertices[i].uvw = V3f32(center.x, center.y, roundness); + vertices[i].color = color; + vertices[i].half_thickness = half_thickness; } + draw__write_vertices_in_current_group(target, vertices, ArrayCount(vertices)); } internal void draw_rectangle(Render_Target *target, Rect_f32 rect, f32 roundness, u32 color){ - if (roundness < epsilon_f32){ - draw_rectangle_sharp(target, rect, color); - } - else{ - Vec2_f32 dim = rect_dim(rect); - Vec2_f32 half_dim = dim*0.5f; - roundness = min(roundness, half_dim.x); - roundness = min(roundness, half_dim.y); - - Rect_f32 mid = rect_inner(rect, roundness); - b32 has_x = (mid.x1 > mid.x0); - b32 has_y = (mid.y1 > mid.y0); - - if (has_x && has_y){ - draw_rectangle_sharp(target, mid, color); - } - if (has_x){ - draw_rectangle_sharp(target, - Rf32(mid.x0, rect.y0, mid.x1, mid.y0), - color); - draw_rectangle_sharp(target, - Rf32(mid.x0, mid.y0, mid.x1, rect.y1), - color); - } - if (has_y){ - draw_rectangle_sharp(target, - Rf32(rect.x0, mid.y0, mid.x0, mid.y1), - color); - draw_rectangle_sharp(target, - Rf32(mid.x1, mid.y0, rect.x1, mid.y1), - color); - } - - draw_round_corners(target, mid, roundness, color); - } -} - -internal void -draw_rectangle_outline(Render_Target *target, Rect_f32 rect, f32 roundness, f32 thickness, u32 color){ Vec2_f32 dim = rect_dim(rect); - Vec2_f32 half_dim = dim*0.5f; - f32 max_thickness = min(half_dim.x, half_dim.y); - thickness = clamp(1.f, thickness, max_thickness); - Rect_f32 inner = rect_inner(rect, thickness); - - if (roundness < epsilon_f32){ - Render_Vertex vertices[24] = {}; - vertices[ 0].xy = V2(rect.x0, rect.y0); - vertices[ 1].xy = V2(inner.x0, inner.y0); - vertices[ 2].xy = V2(rect.x1, rect.y0); - vertices[ 3].xy = V2(inner.x0, inner.y0); - vertices[ 4].xy = V2(rect.x1, rect.y0); - vertices[ 5].xy = V2(inner.x1, inner.y0); - vertices[ 6].xy = V2(rect.x1, rect.y0); - vertices[ 7].xy = V2(inner.x1, inner.y0); - vertices[ 8].xy = V2(rect.x1, rect.y1); - vertices[ 9].xy = V2(inner.x1, inner.y0); - vertices[10].xy = V2(rect.x1, rect.y1); - vertices[11].xy = V2(inner.x1, inner.y1); - vertices[12].xy = V2(rect.x1, rect.y1); - vertices[13].xy = V2(inner.x1, inner.y1); - vertices[14].xy = V2(rect.x0, rect.y1); - vertices[15].xy = V2(inner.x1, inner.y1); - vertices[16].xy = V2(rect.x0, rect.y1); - vertices[17].xy = V2(inner.x0, inner.y1); - vertices[18].xy = V2(rect.x0, rect.y1); - vertices[19].xy = V2(inner.x0, inner.y1); - vertices[20].xy = V2(rect.x0, rect.y0); - vertices[21].xy = V2(inner.x0, inner.y1); - vertices[22].xy = V2(rect.x0, rect.y0); - vertices[23].xy = V2(inner.x0, inner.y0); - Vec4_f32 c = unpack_color4(color); - for (i32 i = 0; i < ArrayCount(vertices); i += 1){ - vertices[i].color = c; - } - draw__write_vertices_in_current_group(target, vertices, ArrayCount(vertices)); - } - else{ - roundness = min(roundness, half_dim.x); - roundness = min(roundness, half_dim.y); - - Rect_f32 mid = rect_inner(rect, roundness); - b32 has_x = (mid.x1 > mid.x0); - b32 has_y = (mid.y1 > mid.y0); - - if (has_x){ - draw_rectangle_sharp(target, - Rf32(mid.x0, rect.y0, mid.x1, inner.y0), - color); - draw_rectangle_sharp(target, - Rf32(mid.x0, inner.y1, mid.x1, rect.y1), - color); - } - if (has_y){ - draw_rectangle_sharp(target, - Rf32(rect.x0, mid.y0, inner.x0, mid.y1), - color); - draw_rectangle_sharp(target, - Rf32(inner.x1, mid.y0, rect.x1, mid.y1), - color); - } - - if (roundness <= thickness){ - draw_round_corners(target, mid, roundness, color); - } - else{ - bake_round_corner(); - - for (i32 i = 0; i < 2; i += 1){ - for (i32 j = 0; j < 2; j += 1){ - Vec2_f32 d = {}; - Vec2_f32 p = {}; - if (i == 0){ - if (j == 0){ - p = V2f32(mid.x0, mid.y0); - d = V2f32(-1.f, -1.f); - } - else{ - p = V2f32(mid.x1, mid.y0); - d = V2f32( 1.f, -1.f); - } - } - else{ - if (j == 0){ - p = V2f32(mid.x0, mid.y1); - d = V2f32(-1.f, 1.f); - } - else{ - p = V2f32(mid.x1, mid.y1); - d = V2f32( 1.f, 1.f); - } - } - Vec2_f32 d1 = d*roundness; - Vec2_f32 d2 = d*(roundness - thickness); - - Render_Vertex vertices[baked_tri_count*6] = {}; - i32 m = 0; - for (i32 k = 0; k < baked_tri_count; k += 1){ - Vec2_f32 p0 = baked_round_corner[k + 0]; - Vec2_f32 p1 = baked_round_corner[k + 1]; - vertices[m].xy = p + hadamard(p0, d1); - m += 1; - vertices[m].xy = p + hadamard(p0, d2); - m += 1; - vertices[m].xy = p + hadamard(p1, d1); - m += 1; - vertices[m].xy = p + hadamard(p0, d2); - m += 1; - vertices[m].xy = p + hadamard(p1, d1); - m += 1; - vertices[m].xy = p + hadamard(p1, d2); - m += 1; - } - Vec4_f32 c = unpack_color4(color); - for (i32 k = 0; k < ArrayCount(vertices); k += 1){ - vertices[k].color = c; - } - draw__write_vertices_in_current_group(target, vertices, ArrayCount(vertices)); - } - } - } - } + draw_rectangle_outline(target, rect, roundness, max(dim.x, dim.y), color); } internal void @@ -416,12 +197,12 @@ draw_font_glyph(Render_Target *target, Face *face, u32 codepoint, f32 x, f32 y, vertices[3] = vertices[1]; vertices[4] = vertices[2]; - Vec4 c = unpack_color4(color); - for (i32 i = 0; i < 6; i += 1){ - vertices[i].color = c; + for (i32 i = 0; i < ArrayCount(vertices); i += 1){ + vertices[i].color = color; + vertices[i].half_thickness = 0.f; } - draw__write_vertices_in_current_group(target, vertices, 6); + draw__write_vertices_in_current_group(target, vertices, ArrayCount(vertices)); } //////////////////////////////// diff --git a/4ed_render_target.h b/4ed_render_target.h index 3ea7fcdc..0e83060f 100644 --- a/4ed_render_target.h +++ b/4ed_render_target.h @@ -18,9 +18,10 @@ struct Render_Free_Texture{ }; struct Render_Vertex{ - Vec2 xy; - Vec3 uvw; - Vec4 color; + Vec2_f32 xy; + Vec3_f32 uvw; + u32 color; + f32 half_thickness; }; struct Render_Vertex_Array_Node{ diff --git a/custom/4coder_default_hooks.cpp b/custom/4coder_default_hooks.cpp index 6e827b17..d1fedc0f 100644 --- a/custom/4coder_default_hooks.cpp +++ b/custom/4coder_default_hooks.cpp @@ -441,8 +441,8 @@ default_buffer_render_caller(Application_Links *app, Frame_Info frame_info, View } // NOTE(allen): Roundness - f32 cursor_roundness = 0.f; - f32 mark_thickness = 0.f; + f32 cursor_roundness = 4.f; + f32 mark_thickness = 2.f; // NOTE(allen): Highlight range b32 has_highlight_range = false; diff --git a/custom/4coder_helper.cpp b/custom/4coder_helper.cpp index 498f0696..f62a276a 100644 --- a/custom/4coder_helper.cpp +++ b/custom/4coder_helper.cpp @@ -2340,6 +2340,34 @@ draw_character_block(Application_Links *app, Text_Layout_ID layout, i64 pos, f32 internal void draw_character_block(Application_Links *app, Text_Layout_ID layout, Range_i64 range, f32 roundness, int_color color){ + if (range.first < range.one_past_last){ + i64 i = range.first; + Rect_f32 first_rect = text_layout_character_on_screen(app, layout, i); + i += 1; + Range_f32 y = rect_range_y(first_rect); + Range_f32 x = rect_range_x(first_rect); + for (;i < range.one_past_last; i += 1){ + Rect_f32 rect = text_layout_character_on_screen(app, layout, i); + if (rect.x0 < rect.x1 && rect.y0 < rect.y1){ + Range_f32 new_y = rect_range_y(rect); + Range_f32 new_x = rect_range_x(rect); + b32 joinable = false; + if (new_y == y && (range_overlap(x, new_x) || x.max == new_x.min || new_x.max == x.min)){ + joinable = true; + } + + if (!joinable){ + draw_rectangle(app, Rf32(x, y), roundness, color); + y = new_y; + x = new_x; + } + else{ + x = range_union(x, new_x); + } + } + } + draw_rectangle(app, Rf32(x, y), roundness, color); + } for (i64 i = range.first; i < range.one_past_last; i += 1){ draw_character_block(app, layout, i, roundness, color); } diff --git a/opengl/4ed_opengl_funcs.h b/opengl/4ed_opengl_funcs.h index dd6c9aef..c9e93a7c 100644 --- a/opengl/4ed_opengl_funcs.h +++ b/opengl/4ed_opengl_funcs.h @@ -51,6 +51,7 @@ GL_FUNC(glDisableVertexAttribArray, void, (GLuint index)) GL_FUNC(glEnableVertexAttribArray, void, (GLuint index)) GL_FUNC(glVertexAttribPointer, void, (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer)) +GL_FUNC(glVertexAttribIPointer, void, (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer)) GL_FUNC(glUniform1f, void, (GLint location, GLfloat v0)) GL_FUNC(glUniform2f, void, (GLint location, GLfloat v0, GLfloat v1)) diff --git a/opengl/4ed_opengl_render.cpp b/opengl/4ed_opengl_render.cpp index a0f49c97..40d4f8d4 100644 --- a/opengl/4ed_opengl_render.cpp +++ b/opengl/4ed_opengl_render.cpp @@ -68,32 +68,68 @@ uniform vec2 view_t; uniform mat2x2 view_m; in vec2 vertex_p; in vec3 vertex_t; -in vec4 vertex_c; +in uint vertex_c; +in float vertex_ht; smooth out vec4 fragment_color; smooth out vec3 uvw; +smooth out vec2 xy; +smooth out vec2 adjusted_half_dim; +smooth out float half_thickness; void main(void) { -gl_Position = vec4(view_m*(vertex_p - view_t), 0.f, 1.f); -fragment_color = vertex_c; +gl_Position = vec4(view_m*(vertex_p - view_t), 0.0, 1.0); + fragment_color.b = ((vertex_c )&0xFF)/255.0; +fragment_color.g = ((vertex_c>> 8)&0xFF)/255.0; +fragment_color.r = ((vertex_c>>16)&0xFF)/255.0; +fragment_color.a = ((vertex_c>>24)&0xFF)/255.0; uvw = vertex_t; +vec2 center = vertex_t.xy; +vec2 half_dim = abs(vertex_p - center); +adjusted_half_dim = half_dim - vertex_t.zz + vec2(0.5, 0.5); +half_thickness = vertex_ht; +xy = vertex_p; } )foo"; char *gl__fragment = R"foo( smooth in vec4 fragment_color; smooth in vec3 uvw; +smooth in vec2 xy; +smooth in vec2 adjusted_half_dim; +smooth in float half_thickness; uniform sampler2DArray sampler; out vec4 out_color; + +float rectangle_sd(vec2 p, vec2 b){ +vec2 d = abs(p) - b; +return(length(max(d, vec2(0.0, 0.0))) + min(max(d.x, d.y), 0.0)); +} + void main(void) { -out_color = vec4(fragment_color.xyz, fragment_color.a*texture(sampler, uvw).r); +float has_thickness = (step(0.49, half_thickness)); +float does_not_have_thickness = 1.0 - has_thickness; + +float sample_value = texture(sampler, uvw).r; +sample_value *= does_not_have_thickness; + +vec2 center = uvw.xy; +float roundness = uvw.z; +float sd = rectangle_sd(xy - center, adjusted_half_dim); +sd = sd - roundness; +sd = abs(sd + half_thickness) - half_thickness; +float shape_value = 1.0 - smoothstep(-1.0, 0.0, sd); +shape_value *= has_thickness; + +out_color = vec4(fragment_color.xyz, fragment_color.a*(sample_value + shape_value)); } )foo"; #define AttributeList(X) \ X(vertex_p) \ X(vertex_t) \ -X(vertex_c) +X(vertex_c) \ +X(vertex_ht) #define UniformList(X) \ X(view_t) \ @@ -265,9 +301,16 @@ gl_render(Render_Target *t){ glEnableVertexAttribArray(gpu_program.vertex_p); glEnableVertexAttribArray(gpu_program.vertex_t); glEnableVertexAttribArray(gpu_program.vertex_c); - glVertexAttribPointer(gpu_program.vertex_p, 2, GL_FLOAT, true, sizeof(Render_Vertex), GLOffset(Render_Vertex, xy)); - glVertexAttribPointer(gpu_program.vertex_t, 3, GL_FLOAT, true, sizeof(Render_Vertex), GLOffset(Render_Vertex, uvw)); - glVertexAttribPointer(gpu_program.vertex_c, 4, GL_FLOAT, true, sizeof(Render_Vertex), GLOffset(Render_Vertex, color)); + glEnableVertexAttribArray(gpu_program.vertex_ht); + + glVertexAttribPointer(gpu_program.vertex_p, 2, GL_FLOAT, true, sizeof(Render_Vertex), + GLOffset(Render_Vertex, xy)); + glVertexAttribPointer(gpu_program.vertex_t, 3, GL_FLOAT, true, sizeof(Render_Vertex), + GLOffset(Render_Vertex, uvw)); + glVertexAttribIPointer(gpu_program.vertex_c, 1, GL_UNSIGNED_INT, sizeof(Render_Vertex), + GLOffset(Render_Vertex, color)); + glVertexAttribPointer(gpu_program.vertex_ht, 1, GL_FLOAT, true, sizeof(Render_Vertex), + GLOffset(Render_Vertex, half_thickness)); glUniform2f(gpu_program.view_t, width/2.f, height/2.f); f32 m[4] = { @@ -281,6 +324,7 @@ gl_render(Render_Target *t){ glDisableVertexAttribArray(gpu_program.vertex_p); glDisableVertexAttribArray(gpu_program.vertex_t); glDisableVertexAttribArray(gpu_program.vertex_c); + glDisableVertexAttribArray(gpu_program.vertex_ht); } }