aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar gingerBill 2016-04-27 00:16:24 +0100
committerGravatar gingerBill 2016-04-27 00:16:24 +0100
commit0431e9e03c6096d07d66da3c538fec33351fa2e5 (patch)
treea043ed12d0fed7fe408517233210d5c18f4199c3
parentBasic State Rendering (diff)
Better Rounded Rect
-rw-r--r--README.md2
-rw-r--r--gb_gl.h253
2 files changed, 143 insertions, 112 deletions
diff --git a/README.md b/README.md
index a18394d..8af472d 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@ library | latest version | category | languages | description
----------------|----------------|----------|-----------|-------------
**gb.h** | 0.04 | misc | C, C++ | A C helper library for C & C++
**gb_math.h** | 0.05 | math | C, C++ | A C/C++ vector math library geared towards game development
-**gb_gl.h** | 0.03 | graphics | C, C++ | A C/C++ OpenGL Helper Library
+**gb_gl.h** | 0.03a | graphics | C, C++ | A C/C++ OpenGL Helper Library
**gb_string.h** | 0.94 | strings | C, C++ | A better string library for C & C++ (this is built into gb.h too with custom allocator support!)
**gb_ini.h** | 0.92 | misc | C, C++ | A simple ini file loader library for C & C++
diff --git a/gb_gl.h b/gb_gl.h
index b41fbdf..94eeafa 100644
--- a/gb_gl.h
+++ b/gb_gl.h
@@ -1,4 +1,4 @@
-/* gb.h - v0.03 - OpenGL Helper Library - public domain
+/* gb.h - v0.03a - OpenGL Helper Library - public domain
- no warranty implied; use at your own risk
This is a single header file with a bunch of useful stuff
@@ -34,6 +34,7 @@ Conventions used:
Version History:
+ 0.03a - Better Rounded Rect
0.03 - Basic State Rendering
0.02 - Font Caching and Rendering
0.01 - Initial Version
@@ -170,7 +171,7 @@ extern "C" {
#endif
-GBGL_DEF u32 gbgl_generate_sampler(u32 min_filter, u32 max_filter, u32 s_wrap, u32 t_wrap);
+GBGL_DEF u32 gbgl_make_sampler(u32 min_filter, u32 max_filter, u32 s_wrap, u32 t_wrap);
@@ -635,6 +636,9 @@ GBGL_DEF void gbgl_bs_draw_circle_outline(gbglBasicState *bs, gbVec2 p, f32 radi
GBGL_DEF void gbgl_bs_draw_rounded_rect_corners(gbglBasicState *bs, gbVec2 pos, gbVec2 dim, f32 roundness, gbColour col, u32 corners);
GBGL_DEF void gbgl_bs_draw_rounded_rect(gbglBasicState *bs, gbVec2 pos, gbVec2 dim, f32 roundness, gbColour col);
+GBGL_DEF void gbgl_bs_draw_rounded_rect_corners_outline(gbglBasicState *bs, gbVec2 pos, gbVec2 dim, f32 roundness, gbColour col, f32 thickness, u32 corners);
+GBGL_DEF void gbgl_bs_draw_rounded_rect_outline(gbglBasicState *bs, gbVec2 pos, gbVec2 dim, f32 roundness, gbColour col, f32 thickness);
+
GBGL_DEF isize gbgl_bs_draw_substring(gbglBasicState *bs, gbglFont *font, i32 x, i32 y, gbColour col, char const *str, isize len);
GBGL_DEF isize gbgl_bs_draw_string (gbglBasicState *bs, gbglFont *font, i32 x, i32 y, gbColour col, char const *fmt, ...);
@@ -701,7 +705,7 @@ GBGL_DEF isize gbgl_bs_draw_string_va(gbglBasicState *bs, gbglFont *font, i32 x,
u32
-gbgl_generate_sampler(u32 min_filter, u32 max_filter, u32 s_wrap, u32 t_wrap)
+gbgl_make_sampler(u32 min_filter, u32 max_filter, u32 s_wrap, u32 t_wrap)
{
u32 samp;
glGenSamplers(1, &samp);
@@ -1138,61 +1142,6 @@ gbgl_set_uniform_colour(gbglShader *s, char const *name, gbColour col)
//
//
-#if 0
-b32
-gbgl_render_buffer_init(gbglRenderBuffer *in_out_rb)
-{
- i32 i;
- if (in_out_rb->colour_buffer_count >= GBGL_MAX_RENDER_COLOUR_BUFFERS) {
- return false;
- }
- glGenFramebuffers(1, &in_out_rb->gl_frame_buffer_handle);
- glBindFramebuffer(GL_FRAMEBUFFER, in_out_rb->gl_frame_buffer_handle);
-
- glGenTextures(in_out_rb->colour_buffer_count, in_out_rb->handles);
- for (i = 0; i < in_out_rb->colour_buffer_count; i++) {
- i32 channel_count = in_out_rb->channel_count[i];
- glBindTexture(GL_TEXTURE_2D, in_out_rb->handles[i]);
- glTexImage2D(GL_TEXTURE_2D, 0,
- GBGL_INTERNAL_TEXTURE_FORMAT_8[channel_count-1],
- in_out_rb->width, in_out_rb->height, 0,
- GBGL_TEXTURE_FORMAT[channel_count-1],
- in_out_rb->data_type[0], 0);
- glBindTexture(GL_TEXTURE_2D, 0);
- glFramebufferTexture2D(GL_FRAMEBUFFER,
- GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D,
- in_out_rb->handles[0], 0);
- }
- glDrawBuffers(in_out_rb->colour_buffer_count, GBGL_COLOUR_BUFFER_ATTACHMENTS);
- //@TODO: not every valid permutation has been tested, it's likely that there's a format/internal format mismatch somewhere
- if (in_out_rb->has_depth || in_out_rb->has_stencil) {
- if (in_out_rb->has_depth && in_out_rb->has_stencil) {
- glGenRenderbuffers(1, &in_out_rb->gl_depth_stencil_buffer_handle);
- glBindRenderbuffer(GL_RENDERBUFFER, in_out_rb->gl_depth_stencil_buffer_handle);
- glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, in_out_rb->width, in_out_rb->height);
- glBindRenderbuffer(GL_RENDERBUFFER, 0);
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, in_out_rb->gl_depth_stencil_buffer_handle);
- } else if (in_out_rb->has_depth) {
- glGenRenderbuffers(1, &in_out_rb->gl_depth_stencil_buffer_handle);
- glBindRenderbuffer(GL_RENDERBUFFER, in_out_rb->gl_depth_stencil_buffer_handle);
- glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, in_out_rb->width, in_out_rb->height);
- glBindRenderbuffer(GL_RENDERBUFFER, 0);
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, in_out_rb->gl_depth_stencil_buffer_handle);
- } else if (in_out_rb->has_stencil) {
- GB_PANIC("A framebuffer cannot have a stencil without depth"); // NOTE(bill): no stencil w/o depth
- }
- }
-
- in_out_rb->gl_frame_buffer_status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
-
- if (in_out_rb->gl_frame_buffer_status != GL_FRAMEBUFFER_COMPLETE) {
- gb_fprintf(stderr, "Unable to create OpenGL Frame buffer. Frame buffer incomplete: %d\n", in_out_rb->gl_frame_buffer_status);
- }
-
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- return in_out_rb->gl_frame_buffer_status == GL_FRAMEBUFFER_COMPLETE;
-}
-#endif
b32
gbgl_init_render_buffer(gbglRenderBuffer *rb, i32 width, i32 height, i32 channel_count)
@@ -1891,8 +1840,8 @@ gbgl_bs_init(gbglBasicState *bs, i32 window_width, i32 window_height)
}
bs->ebo = gbgl_make_ebo(bs->indices, gb_size_of(u16) * GBGL_BS_MAX_INDEX_COUNT, GL_STATIC_DRAW);
- bs->nearest_sampler = gbgl_generate_sampler(GL_NEAREST, GL_NEAREST, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
- bs->linear_sampler = gbgl_generate_sampler(GL_LINEAR, GL_LINEAR, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
+ bs->nearest_sampler = gbgl_make_sampler(GL_NEAREST, GL_NEAREST, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
+ bs->linear_sampler = gbgl_make_sampler(GL_LINEAR, GL_LINEAR, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
gbgl_load_shader_vf_from_source(&bs->ortho_tex_shader,
"#version 410 core\n"
@@ -1968,8 +1917,8 @@ gbgl_bs_init(gbglBasicState *bs, i32 window_width, i32 window_height)
}
bs->font_ebo = gbgl_make_ebo(bs->font_indices, gb_size_of(u16) * GBGL_MAX_RENDER_STRING_LENGTH * 6, GL_STATIC_DRAW);
- bs->font_samplers[0] = gbgl_generate_sampler(GL_NEAREST, GL_NEAREST, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
- bs->font_samplers[1] = gbgl_generate_sampler(GL_LINEAR, GL_LINEAR, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
+ bs->font_samplers[0] = gbgl_make_sampler(GL_NEAREST, GL_NEAREST, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
+ bs->font_samplers[1] = gbgl_make_sampler(GL_LINEAR, GL_LINEAR, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
bs->text_params[GBGL_TEXT_PARAM_MAX_WIDTH].val_i32 = 0;
bs->text_params[GBGL_TEXT_PARAM_JUSTIFY].val_i32 = GBGL_JUSTIFY_LEFT;
@@ -2150,9 +2099,9 @@ gbgl_bs_draw_elliptical_arc(gbglBasicState *bs, gbVec2 p, f32 radius_a, f32 radi
for (i = 0; i < 31; i++) {
f32 t = cast(f32)i / 30.0f;
- f32 theta = gb_lerp(min_angle, max_angle, t);
- f32 c = gb_cos(theta);
- f32 s = gb_sin(theta);
+ f32 a = gb_lerp(min_angle, max_angle, t);
+ f32 c = gb_cos(a);
+ f32 s = gb_sin(a);
bs->vertices[i+1].x = p.x + c*radius_a;
bs->vertices[i+1].y = p.y + s*radius_b;
}
@@ -2169,16 +2118,16 @@ gbgl_bs_draw_elliptical_arc_outline(gbglBasicState *bs, gbVec2 p, f32 radius_a,
for (i = 0; i < 32; i++) {
f32 t = cast(f32)i / 31.0f;
- f32 theta = gb_lerp(min_angle, max_angle, t);
- f32 c = gb_cos(theta);
- f32 s = gb_sin(theta);
+ f32 a = gb_lerp(min_angle, max_angle, t);
+ f32 c = gb_cos(a);
+ f32 s = gb_sin(a);
bs->vertices[i+1].x = p.x + c*radius_a;
bs->vertices[i+1].y = p.y + s*radius_b;
}
gbgl__bs_setup_ortho_colour_state(bs, 32, col);
glLineWidth(thickness);
- glDrawArrays(GL_LINE_LOOP, 0, 32);
+ glDrawArrays(GL_LINES, 0, 32);
}
@@ -2208,93 +2157,83 @@ gbgl_bs_draw_rounded_rect_corners(gbglBasicState *bs, gbVec2 pos, gbVec2 dim, f3
} else {
isize i, vc = 0;
- bs->vertices[0].x = pos.x + 0.5f*dim.x;
- bs->vertices[0].y = pos.y + 0.5f*dim.y;
+ bs->vertices[vc].x = pos.x + 0.5f*dim.x;
+ bs->vertices[vc].y = pos.y + 0.5f*dim.y;
vc++;
if (corners & 1) {
for (i = 0; i < 6; i++) {
f32 t = cast(f32)i / 5.0f;
- f32 theta = gb_lerp(0.5f*GB_MATH_TAU, 0.75f*GB_MATH_TAU, t);
- f32 c = gb_cos(theta);
- f32 s = gb_sin(theta);
+ f32 a = gb_lerp(0.5f*GB_MATH_TAU, 0.75f*GB_MATH_TAU, t);
+ f32 c = gb_cos(a);
+ f32 s = gb_sin(a);
bs->vertices[vc].x = pos.x + roundness + c*roundness;
bs->vertices[vc].y = pos.y + roundness + s*roundness;
vc++;
}
} else {
bs->vertices[vc].x = pos.x;
- bs->vertices[vc].y = pos.y + roundness;
- bs->vertices[vc+1].x = pos.x;
- bs->vertices[vc+1].y = pos.y;
- bs->vertices[vc+2].x = pos.x + roundness;
- bs->vertices[vc+2].y = pos.y;
- vc += 3;
+ bs->vertices[vc].y = pos.y;
+ vc++;
}
if (corners & 2) {
for (i = 0; i < 6; i++) {
f32 t = cast(f32)i / 5.0f;
- f32 theta = gb_lerp(0.75f*GB_MATH_TAU, 1.00f*GB_MATH_TAU, t);
- f32 c = gb_cos(theta);
- f32 s = gb_sin(theta);
+ f32 a = gb_lerp(0.75f*GB_MATH_TAU, 1.00f*GB_MATH_TAU, t);
+ f32 c = gb_cos(a);
+ f32 s = gb_sin(a);
bs->vertices[vc].x = pos.x + dim.x - roundness + c*roundness;
bs->vertices[vc].y = pos.y + roundness + s*roundness;
vc++;
}
} else {
- bs->vertices[vc].x = pos.x + dim.x - roundness;
+ bs->vertices[vc].x = pos.x + dim.x;
bs->vertices[vc].y = pos.y;
- bs->vertices[vc+1].x = pos.x + dim.x;
- bs->vertices[vc+1].y = pos.y;
- bs->vertices[vc+2].x = pos.x + dim.x;
- bs->vertices[vc+2].y = pos.y + roundness;
- vc += 3;
+ vc++;
}
if (corners & 4) {
for (i = 0; i < 6; i++) {
f32 t = cast(f32)i / 5.0f;
- f32 theta = gb_lerp(0.00f*GB_MATH_TAU, 0.25f*GB_MATH_TAU, t);
- f32 c = gb_cos(theta);
- f32 s = gb_sin(theta);
+ f32 a = gb_lerp(0.00f*GB_MATH_TAU, 0.25f*GB_MATH_TAU, t);
+ f32 c = gb_cos(a);
+ f32 s = gb_sin(a);
bs->vertices[vc].x = pos.x + dim.x - roundness + c*roundness;
bs->vertices[vc].y = pos.y + dim.y - roundness + s*roundness;
vc++;
}
} else {
bs->vertices[vc].x = pos.x + dim.x;
- bs->vertices[vc].y = pos.y + dim.y - roundness;
- bs->vertices[vc+1].x = pos.x + dim.x;
- bs->vertices[vc+1].y = pos.y + dim.y;
- bs->vertices[vc+2].x = pos.x + dim.x - roundness;
- bs->vertices[vc+2].y = pos.y + dim.y;
- vc += 3;
+ bs->vertices[vc].y = pos.y + dim.y;
+ vc++;
}
if (corners & 8) {
for (i = 0; i < 6; i++) {
f32 t = cast(f32)i / 5.0f;
- f32 theta = gb_lerp(0.25f*GB_MATH_TAU, 0.50f*GB_MATH_TAU, t);
- f32 c = gb_cos(theta);
- f32 s = gb_sin(theta);
+ f32 a = gb_lerp(0.25f*GB_MATH_TAU, 0.50f*GB_MATH_TAU, t);
+ f32 c = gb_cos(a);
+ f32 s = gb_sin(a);
bs->vertices[vc].x = pos.x + roundness + c*roundness;
bs->vertices[vc].y = pos.y + dim.y - roundness + s*roundness;
vc++;
}
} else {
- bs->vertices[vc].x = pos.x + roundness;
+ bs->vertices[vc].x = pos.x;
bs->vertices[vc].y = pos.y + dim.y;
- bs->vertices[vc+1].x = pos.x;
- bs->vertices[vc+1].y = pos.y + dim.y;
- bs->vertices[vc+2].x = pos.x;
- bs->vertices[vc+2].y = pos.y + dim.y - roundness;
- vc += 3;
+ vc++;
}
- bs->vertices[vc-1].x = pos.x;
- bs->vertices[vc-1].y = pos.y + roundness;
+ if (corners & 1) {
+ bs->vertices[vc].x = pos.x;
+ bs->vertices[vc].y = pos.y + roundness;
+ } else {
+ bs->vertices[vc].x = pos.x;
+ bs->vertices[vc].y = pos.y;
+ }
+ vc++;
gbgl__bs_setup_ortho_colour_state(bs, vc, col);
glDrawArrays(GL_TRIANGLE_FAN, 0, vc);
@@ -2308,6 +2247,99 @@ gbgl_bs_draw_rounded_rect(gbglBasicState *bs, gbVec2 pos, gbVec2 dim, f32 roundn
}
+void
+gbgl_bs_draw_rounded_rect_corners_outline(gbglBasicState *bs, gbVec2 pos, gbVec2 dim, f32 roundness, gbColour col, f32 thickness, u32 corners)
+{
+ if ((2.0f*roundness > gb_abs(dim.x)) ||
+ (2.0f*roundness > gb_abs(dim.y))) {
+ roundness = 0.5f*gb_min(gb_abs(dim.x), gb_abs(dim.y));
+ }
+
+ if (roundness == 0 || corners == 0) {
+ gbgl_bs_draw_rect_outline(bs, pos, dim, col, thickness);
+ } else {
+ isize i, vc = 0;
+
+ if (corners & 1) {
+ for (i = 0; i < 6; i++) {
+ f32 t = cast(f32)i / 5.0f;
+ f32 a = gb_lerp(0.5f*GB_MATH_TAU, 0.75f*GB_MATH_TAU, t);
+ f32 c = gb_cos(a);
+ f32 s = gb_sin(a);
+ bs->vertices[vc].x = pos.x + roundness + c*roundness;
+ bs->vertices[vc].y = pos.y + roundness + s*roundness;
+ vc++;
+ }
+ } else {
+ bs->vertices[vc].x = pos.x;
+ bs->vertices[vc].y = pos.y;
+ vc++;
+ }
+
+ if (corners & 2) {
+ for (i = 0; i < 6; i++) {
+ f32 t = cast(f32)i / 5.0f;
+ f32 a = gb_lerp(0.75f*GB_MATH_TAU, 1.00f*GB_MATH_TAU, t);
+ f32 c = gb_cos(a);
+ f32 s = gb_sin(a);
+ bs->vertices[vc].x = pos.x + dim.x - roundness + c*roundness;
+ bs->vertices[vc].y = pos.y + roundness + s*roundness;
+ vc++;
+ }
+ } else {
+ bs->vertices[vc].x = pos.x + dim.x;
+ bs->vertices[vc].y = pos.y;
+ vc++;
+ }
+
+
+ if (corners & 4) {
+ for (i = 0; i < 6; i++) {
+ f32 t = cast(f32)i / 5.0f;
+ f32 a = gb_lerp(0.00f*GB_MATH_TAU, 0.25f*GB_MATH_TAU, t);
+ f32 c = gb_cos(a);
+ f32 s = gb_sin(a);
+ bs->vertices[vc].x = pos.x + dim.x - roundness + c*roundness;
+ bs->vertices[vc].y = pos.y + dim.y - roundness + s*roundness;
+ vc++;
+ }
+ } else {
+ bs->vertices[vc].x = pos.x + dim.x;
+ bs->vertices[vc].y = pos.y + dim.y;
+ vc++;
+ }
+
+ if (corners & 8) {
+ for (i = 0; i < 6; i++) {
+ f32 t = cast(f32)i / 5.0f;
+ f32 a = gb_lerp(0.25f*GB_MATH_TAU, 0.50f*GB_MATH_TAU, t);
+ f32 c = gb_cos(a);
+ f32 s = gb_sin(a);
+ bs->vertices[vc].x = pos.x + roundness + c*roundness;
+ bs->vertices[vc].y = pos.y + dim.y - roundness + s*roundness;
+ vc++;
+ }
+ } else {
+ bs->vertices[vc].x = pos.x;
+ bs->vertices[vc].y = pos.y + dim.y;
+ vc++;
+ }
+
+ gbgl__bs_setup_ortho_colour_state(bs, vc, col);
+ glLineWidth(thickness);
+ glDrawArrays(GL_LINE_LOOP, 0, vc);
+ }
+}
+
+gb_inline void
+gbgl_bs_draw_rounded_rect_outline(gbglBasicState *bs, gbVec2 pos, gbVec2 dim, f32 roundness, gbColour col, f32 thickness)
+{
+ gbgl_bs_draw_rounded_rect_corners_outline(bs, pos, dim, roundness, col, thickness, 1|2|4|8);
+}
+
+
+
+
isize
@@ -2327,7 +2359,6 @@ gbgl_bs_draw_substring(gbglBasicState *bs, gbglFont *font, i32 x, i32 y, gbColou
isize glyph_count = 0, i;
f32 font_height = font->size;
i32 max_width = bs->text_params[GBGL_TEXT_PARAM_MAX_WIDTH].val_i32;
- f32 max_width32 = cast(f32)max_width;
gbglJustifyType justify = cast(gbglJustifyType)bs->text_params[GBGL_TEXT_PARAM_JUSTIFY].val_i32;
if (justify == GBGL_JUSTIFY_CENTRE) {
@@ -2376,7 +2407,7 @@ gbgl_bs_draw_substring(gbglBasicState *bs, gbglFont *font, i32 x, i32 y, gbColou
if (cp == '\r' || cp == '\n' ||
- (max_width > 0 && px - ox + gi->xadv >= max_width32)) {
+ (max_width > 0 && px - ox + gi->xadv >= cast(f32)max_width)) {
px = ox;
py -= font_height;