From 4a2a2ecd423f8e9f7d61e51bd5ba86cc985293aa Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Sat, 22 Jan 2022 22:09:44 -0600 Subject: [PATCH] started basics of immediate mode gui --- run_tree/assets/shaders/imgui_fragment.glsl | 13 ++++ run_tree/assets/shaders/imgui_vertex.glsl | 18 +++++ src/build.onyx | 1 + src/font.onyx | 2 + src/imgui.onyx | 83 +++++++++++++++++++++ src/main.onyx | 5 ++ src/mesh.onyx | 11 ++- src/vecmath.onyx | 5 ++ src/world.onyx | 6 +- src/worldgen.onyx | 4 +- 10 files changed, 140 insertions(+), 8 deletions(-) create mode 100644 run_tree/assets/shaders/imgui_fragment.glsl create mode 100644 run_tree/assets/shaders/imgui_vertex.glsl create mode 100644 src/imgui.onyx diff --git a/run_tree/assets/shaders/imgui_fragment.glsl b/run_tree/assets/shaders/imgui_fragment.glsl new file mode 100644 index 0000000..b174047 --- /dev/null +++ b/run_tree/assets/shaders/imgui_fragment.glsl @@ -0,0 +1,13 @@ +#version 300 es +precision mediump float; + +in vec4 v_col; +in vec2 v_tex; + +uniform sampler2D u_texture; + +out vec4 fragColor; + +void main() { + fragColor = v_col; +} diff --git a/run_tree/assets/shaders/imgui_vertex.glsl b/run_tree/assets/shaders/imgui_vertex.glsl new file mode 100644 index 0000000..3fa601e --- /dev/null +++ b/run_tree/assets/shaders/imgui_vertex.glsl @@ -0,0 +1,18 @@ +#version 300 es +precision mediump float; +layout(location = 0) in vec2 a_pos; +layout(location = 1) in vec2 a_tex; +layout(location = 2) in vec4 a_col; + +layout(std140) uniform u_window_matrix_block { + mat4 u_window; +}; + +out vec4 v_col; +out vec2 v_tex; + +void main() { + gl_Position = u_window * vec4(a_pos, 0, 1); + v_tex = a_tex; + v_col = a_col; +} \ No newline at end of file diff --git a/src/build.onyx b/src/build.onyx index 8667782..bd2e98e 100644 --- a/src/build.onyx +++ b/src/build.onyx @@ -11,6 +11,7 @@ #load "chunk" #load "config" #load "font" +#load "imgui" #load "input" #load "main" #load "mesh" diff --git a/src/font.onyx b/src/font.onyx index ca0ca28..e7ff023 100644 --- a/src/font.onyx +++ b/src/font.onyx @@ -133,10 +133,12 @@ font_draw :: (font: Font, x, y: f32, msg: str) { shader_use(font_shader); shader_set_uniform(font_shader, #cstr "u_texture", 0); + glDisable(GL_DEPTH_TEST); glBindVertexArray(font_vao); glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, ~~0, quad_num); glBindTexture(GL_TEXTURE_2D, -1); glBindVertexArray(-1); + glEnable(GL_DEPTH_TEST); } diff --git a/src/imgui.onyx b/src/imgui.onyx new file mode 100644 index 0000000..8b66b01 --- /dev/null +++ b/src/imgui.onyx @@ -0,0 +1,83 @@ + +use package core +use package opengles +use package glfw3 + +immediate_init :: () { + memory.alloc_slice(^vertex_data, Maximum_Vertex_Count); + vertex_count = 0; + + imgui_shader = shader_make(Shader_Vertex_Path, Shader_Fragment_Path); + shader_use(imgui_shader); + shader_link_window_matrix_block(imgui_shader); + + immediate_mesh = mesh_make(vertex_data, .[], GL_DYNAMIC_DRAW); +} + +immediate_flush :: () { + if vertex_count == 0 do return; + + immediate_mesh.vertex_count = vertex_count; + mesh_update_verticies(immediate_mesh, vertex_data); + + shader_use(imgui_shader); + glDisable(GL_DEPTH_TEST); + mesh_draw(immediate_mesh); + glEnable(GL_DEPTH_TEST); + + vertex_count = 0; +} + +immediate_vertex :: (position: Vector2, texture := Vector2.{0,0}, color := Color.{1,1,1}) { + if vertex_count >= Maximum_Vertex_Count do immediate_flush(); + + vertex_data[vertex_count] = .{ position, texture, color }; +} + +immediate_triangle :: (x1, x2, x3: Vector2, color := Color.{1,1,1}) { + if vertex_count + 3 > Maximum_Vertex_Count do immediate_flush(); + + vertex_data[vertex_count + 0] = .{ x1, .{0,0}, color }; + vertex_data[vertex_count + 1] = .{ x2, .{0,0}, color }; + vertex_data[vertex_count + 2] = .{ x3, .{0,0}, color }; + vertex_count += 3; +} + +immediate_rectangle :: (top_left: Vector2, size: Vector2, color := Color.{1,1,1}) { + if vertex_count + 6 > Maximum_Vertex_Count do immediate_flush(); + + vertex_data[vertex_count + 0] = .{ top_left, .{0,0}, color }; + vertex_data[vertex_count + 1] = .{ top_left + .{size.x,0}, .{0,0}, color }; + vertex_data[vertex_count + 2] = .{ top_left + .{size.x,size.y}, .{0,0}, color }; + vertex_data[vertex_count + 3] = .{ top_left, .{0,0}, color }; + vertex_data[vertex_count + 4] = .{ top_left + .{size.x,size.y}, .{0,0}, color }; + vertex_data[vertex_count + 5] = .{ top_left + .{0,size.y}, .{0,0}, color }; + vertex_count += 6; +} + +immediate_image :: () {} + +immediate_ellipse :: () {} + +Color :: struct { + r, g, b : f32; + a := 1.0f; +} + +Immediate_Vertex :: struct { + pos: Vector2; + tex: Vector2; + color: Color; +} + +#local { + Shader_Vertex_Path :: "./assets/shaders/imgui_vertex.glsl" + Shader_Fragment_Path :: "./assets/shaders/imgui_fragment.glsl" + imgui_shader: Shader; + + Maximum_Vertex_Count :: 1023; + vertex_count: i32; + vertex_data: [] Immediate_Vertex; + + immediate_mesh: ^Mesh(Immediate_Vertex); +} diff --git a/src/main.onyx b/src/main.onyx index c5f6175..e1c79a4 100644 --- a/src/main.onyx +++ b/src/main.onyx @@ -99,6 +99,8 @@ setup_opengl :: () { shader_set_uniform(world_shader, #cstr "u_fog_start", 40.0f); shader_set_uniform(world_shader, #cstr "u_fog_range", 5.0f); + immediate_init(); + font = font_lookup(.{"./assets/fonts/calibri.ttf", 32}); shader_use(world_shader); @@ -165,6 +167,9 @@ draw :: () { font_print(font, ~~(ww / 2), ~~(wh / 2), "."); if debug_screen { + immediate_rectangle(.{0, 0}, .{528, 220}, .{1, 0, 1, 0.5}); + immediate_flush(); + player_chunk := world_position_to_chunk(world, player.body.pos); font_print(font, 0, 32, "FPS: {}", game_fps); font_print(font, 0, 64, "Position: {}", camera.position); diff --git a/src/mesh.onyx b/src/mesh.onyx index 132a4c2..db769a9 100644 --- a/src/mesh.onyx +++ b/src/mesh.onyx @@ -11,7 +11,7 @@ Mesh :: struct (Vertex_Type: type_expr) { primitive: GLuint = GL_TRIANGLES; } -mesh_make :: (verticies: [] $T, indicies: [] u32) -> ^Mesh(T) { +mesh_make :: (verticies: [] $T, indicies: [] u32, gl_hint := GL_STATIC_DRAW) -> ^Mesh(T) { mesh := new(Mesh(T)); mesh.vertex_count = verticies.count; mesh.index_count = indicies.count; @@ -21,7 +21,7 @@ mesh_make :: (verticies: [] $T, indicies: [] u32) -> ^Mesh(T) { glGenBuffers(1, ^mesh.vertex_handle); glBindBuffer(GL_ARRAY_BUFFER, mesh.vertex_handle); - glBufferData(GL_ARRAY_BUFFER, sizeof T * verticies.count, verticies.data, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, sizeof T * verticies.count, verticies.data, gl_hint); vertex_info := cast(^type_info.Type_Info_Struct) type_info.get_type_info(T); vertex_attr := 0; @@ -34,6 +34,11 @@ mesh_make :: (verticies: [] $T, indicies: [] u32) -> ^Mesh(T) { case Vector3 do glVertexAttribPointer(vertex_attr, 3, GL_FLOAT, false, sizeof T, ~~attr.offset); case u32 do glVertexAttribIPointer(vertex_attr, 1, GL_UNSIGNED_INT, sizeof T, ~~attr.offset); case i32 do glVertexAttribIPointer(vertex_attr, 1, GL_INT, sizeof T, ~~attr.offset); + + // It would be nice to not have to have all the cases here. + // Instead allow for an extensible way of defining them at compile time. + case Color do glVertexAttribPointer(vertex_attr, 4, GL_FLOAT, false, sizeof T, ~~attr.offset); + case #default { buf: [256] u8; msg := conv.str_format(buf, "Unknown type for GL vertex attribute, {}.", attr.type); @@ -45,7 +50,7 @@ mesh_make :: (verticies: [] $T, indicies: [] u32) -> ^Mesh(T) { if indicies.count > 0 { glGenBuffers(1, ^mesh.index_handle); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.index_handle); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof i32 * indicies.count, indicies.data, GL_STATIC_DRAW); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof i32 * indicies.count, indicies.data, gl_hint); } glBindVertexArray(-1); diff --git a/src/vecmath.onyx b/src/vecmath.onyx index caf6a3f..eb6f639 100644 --- a/src/vecmath.onyx +++ b/src/vecmath.onyx @@ -39,6 +39,11 @@ Vector3 :: struct [conv.Custom_Format.{format_vector3}] { } } +#operator + macro (v1, v2: Vector2) => (typeof v1).{ v1.x + v2.x, v1.y + v2.y }; +#operator - macro (v1, v2: Vector2) => Vector2.{ v1.x - v2.x, v1.y - v2.y }; +#operator * macro (v: Vector2, s: f32) => Vector2.{ v.x * s, v.y * s }; +#operator == macro (v1, v2: Vector2) => v1.x == v2.x && v1.y == v2.y; + #operator + macro (v1, v2: Vector3) => Vector3.{ v1.x + v2.x, v1.y + v2.y, v1.z + v2.z }; #operator - macro (v1, v2: Vector3) => Vector3.{ v1.x - v2.x, v1.y - v2.y, v1.z - v2.z }; #operator * macro (v: Vector3, s: f32) => Vector3.{ v.x * s, v.y * s, v.z * s }; diff --git a/src/world.onyx b/src/world.onyx index a7c1686..397b380 100644 --- a/src/world.onyx +++ b/src/world.onyx @@ -55,7 +55,6 @@ world_get_chunk :: #match { // should be a special case for parsing this? I've always hated how parsing // inside of a #match block works. // - (world: ^World, v: Vector3i) -> #auto { return world_get_chunk(world, v.x, v.y, v.z); }, (world: ^World, x, y, z: i32) -> ^Chunk { d := world.chunk_dist; @@ -69,7 +68,9 @@ world_get_chunk :: #match { if iz < 0 || iz > 2 * world.chunk_dist do return null; return world.chunks[ix * sl * sl + iy * sl + iz]; - } + }, + + (world: ^World, v: Vector3i) => world_get_chunk(world, v.x, v.y, v.z) } world_set_chunk :: #match { @@ -192,7 +193,6 @@ world_update :: (use world: ^World, dt: f32) { if chunks_to_load.count > 0 { chunk_to_load := chunks_to_load[0]; array.delete(^chunks_to_load, 0); - printf("Loading {}\n", chunk_to_load); world_load_chunk(world, chunk_to_load); } diff --git a/src/worldgen.onyx b/src/worldgen.onyx index 038b5ef..3e662e2 100644 --- a/src/worldgen.onyx +++ b/src/worldgen.onyx @@ -11,8 +11,8 @@ generate_chunk :: (world: ^World, chunk: ^Chunk) { pz := cast(f64) t.z / 24; n := perlin.noise(px, ~~(10 * seed), pz); - l := perlin.noise(px, ~~(10 * seed + 6), pz); - l = (math.clamp(math.abs(l), 0.2, 0.5) - 0.2) / 0.6 + 0.5; + l := perlin.noise(px, ~~(10 * seed), pz); + l = (math.clamp(math.max(0, l), 0.2, 0.5) - 0.2) / 0.6 + 0.5; h := cast(i32) (n * 32 + 18); h = math.max(h, 14); if n < -0.9 do h += ~~((n + 0.9) * 4); -- 2.25.1