started basics of immediate mode gui
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 23 Jan 2022 04:09:44 +0000 (22:09 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 23 Jan 2022 04:09:44 +0000 (22:09 -0600)
run_tree/assets/shaders/imgui_fragment.glsl [new file with mode: 0644]
run_tree/assets/shaders/imgui_vertex.glsl [new file with mode: 0644]
src/build.onyx
src/font.onyx
src/imgui.onyx [new file with mode: 0644]
src/main.onyx
src/mesh.onyx
src/vecmath.onyx
src/world.onyx
src/worldgen.onyx

diff --git a/run_tree/assets/shaders/imgui_fragment.glsl b/run_tree/assets/shaders/imgui_fragment.glsl
new file mode 100644 (file)
index 0000000..b174047
--- /dev/null
@@ -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 (file)
index 0000000..3fa601e
--- /dev/null
@@ -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
index 8667782e2dc0ead35da926832e8c22058c15972f..bd2e98e0fdf74b84a877c49f5967e4fe2652ed72 100644 (file)
@@ -11,6 +11,7 @@
 #load "chunk"
 #load "config"
 #load "font"
+#load "imgui"
 #load "input"
 #load "main"
 #load "mesh"
index ca0ca281bcde7fcb8ed1171ea3888a778233d766..e7ff023be37bd767f58ae9a29ff37f63a9e69f41 100644 (file)
@@ -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 (file)
index 0000000..8b66b01
--- /dev/null
@@ -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);
+}
index c5f61758b9b30acde7ef7de7c51ee24505a47795..e1c79a4b9dfe5368b501bfcadc4884f0d6a10671 100644 (file)
@@ -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);
index 132a4c27ea527f0c43f6b233fa3f99f50919f0e1..db769a997cf1b8341f389872f2d84b61129ae5da 100644 (file)
@@ -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);
index caf6a3f12fc7f3742ffffcee978f743e2eb3de30..eb6f639a89faaf86a9f5ae3b7e4c923e35ced791 100644 (file)
@@ -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 };
index a7c16868a47f6def2d6fb7106c0531620c37ec04..397b3802e7029a2f9ca94436fde1217d984c80b4 100644 (file)
@@ -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);
     }
index 038b5efc6f6a49f44fc55df1207cfcde6111c4c4..3e662e2cd967bb7cbe4e511bc1f76c88db3af799 100644 (file)
@@ -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);