From: Brendan Hansen Date: Thu, 3 Mar 2022 16:52:00 +0000 (-0600) Subject: updating graphics libraries X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=67e84de789f8f8b071aa97f67afe7a6b2bce139e;p=voxel-shooter.git updating graphics libraries --- diff --git a/src/gfx/canvas.onyx b/src/gfx/canvas.onyx index d2f08e4..f8ffef2 100644 --- a/src/gfx/canvas.onyx +++ b/src/gfx/canvas.onyx @@ -4,21 +4,58 @@ use package opengles Canvas :: struct { + width, height: i32; + framebuffer: GLint; depth_stencil_buffer: GLint; color_texture: GLint; } -canvas_make :: () -> Canvas { +canvas_make :: (width, height: i32) -> Canvas { canvas: Canvas; + canvas.width = width; + canvas.height = height; + + glGenFramebuffers(1, ^canvas.framebuffer); + glBindFramebuffer(GL_FRAMEBUFFER, canvas.framebuffer); + + glGenTextures(1, ^canvas.color_texture); + glBindTexture(GL_TEXTURE_2D, canvas.color_texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, null); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glBindTexture(GL_TEXTURE_2D, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, canvas.color_texture, 0); + + glGenRenderbuffers(1, ^canvas.depth_stencil_buffer); + glBindRenderbuffer(GL_RENDERBUFFER, canvas.depth_stencil_buffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, canvas.depth_stencil_buffer); + + if glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE { + debug_log(.Error, "Framebuffer is not complete!"); + } + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + return canvas; +} + +canvas_free :: (use canvas: ^Canvas) { + glDeleteFramebuffers(1, ^canvas.framebuffer); + glDeleteTextures(1, ^canvas.color_texture); + glDeleteRenderbuffers(1, ^canvas.depth_stencil_buffer); } canvas_use :: (use canvas: ^Canvas) { if canvas == null { glBindFramebuffer(GL_FRAMEBUFFER, 0); + update_view_matrix(); } else { glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); + // update_view_matrix(width, height); } } +canvas_to_texture :: (canvas: ^Canvas) => Texture.{ canvas.color_texture, canvas.width, canvas.height, 3, "" }; diff --git a/src/gfx/font.onyx b/src/gfx/font.onyx index 094760e..35994bb 100644 --- a/src/gfx/font.onyx +++ b/src/gfx/font.onyx @@ -19,6 +19,7 @@ fonts_init :: () { font_shader = shader_make("./assets/shaders/font.glsl"); shader_use(font_shader); shader_link_window_matrix_block(font_shader); + shader_link_world_matrix_block(font_shader); glGenVertexArrays(1, ^font_vao); glBindVertexArray(font_vao); diff --git a/src/gfx/immediate.onyx b/src/gfx/immediate.onyx index 7c6b5e6..8bdd5ba 100644 --- a/src/gfx/immediate.onyx +++ b/src/gfx/immediate.onyx @@ -3,9 +3,6 @@ use package core use package opengles use package glfw3 -#local window_width :: camera.window_width -#local window_height :: camera.window_height - immediate_init :: () { memory.alloc_slice(^vertex_data, Maximum_Vertex_Count); vertex_count = 0; @@ -13,6 +10,7 @@ immediate_init :: () { imgui_shader = shader_make(Shader_Path); shader_use(imgui_shader); shader_link_window_matrix_block(imgui_shader); + shader_link_world_matrix_block(imgui_shader); shader_set_uniform(imgui_shader, #cstr "u_texture_enabled", 0.0f); shader_set_uniform(imgui_shader, #cstr "u_texture", 0); @@ -131,7 +129,7 @@ immediate_push_scissor :: (x, y, w, h: f32) { scissors << .{x, y, w, h}; glEnable(GL_SCISSOR_TEST); - glScissor(~~x, ~~(window_height - ~~(y + h)), ~~w, ~~h); + glScissor(~~x, cast(i32) camera.window_height - ~~(y + h), ~~w, ~~h); } immediate_pop_scissor :: () { @@ -142,12 +140,19 @@ immediate_pop_scissor :: () { if scissors.count > 0 { glEnable(GL_SCISSOR_TEST); s := scissors[scissors.count - 1]; - glScissor(~~s.x, ~~(window_height - (s.y + s.h)), ~~s.w, ~~s.h); + glScissor(~~s.x, cast(i32) camera.window_height - ~~(s.y + s.h), ~~s.w, ~~s.h); } else { glDisable(GL_SCISSOR_TEST); } } +immediate_set_scroll :: (scroll_x, scroll_y: f32) { + offset = .{ scroll_x, scroll_y }; + update_model_matrix(.{ offset.x, offset.y, 0 }); +} + +immediate_get_scroll :: () => offset; + Color :: struct { r, g, b : f32; a := 1.0f; @@ -183,6 +188,8 @@ Immediate_Vertex :: struct { } scissors: [..] Scissor; + offset: Vector2; + set_rendering_type :: (new_type: typeof rendering_type) { if rendering_type != new_type { immediate_flush(); diff --git a/src/gfx/texture.onyx b/src/gfx/texture.onyx index 2ceb980..0df03b8 100644 --- a/src/gfx/texture.onyx +++ b/src/gfx/texture.onyx @@ -46,7 +46,7 @@ texture_lookup :: #match {} glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glBindTexture(GL_TEXTURE_2D, 0); @@ -65,3 +65,16 @@ texture_use :: (use tex: ^Texture, texture_binding := 0) { glActiveTexture(GL_TEXTURE0 + texture_binding); glBindTexture(GL_TEXTURE_2D, texture); } + + +Texture_Wrap :: enum { + Clamp :: GL_CLAMP_TO_EDGE | 0; + Repeat :: GL_REPEAT | 0; + Mirrored_Repeat :: GL_MIRRORED_REPEAT | 0; +} + +texture_wrap :: (use tex: ^Texture, wrap: Texture_Wrap) { + glBindTexture(GL_TEXTURE_2D, texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, ~~ wrap); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, ~~ wrap); +} \ No newline at end of file diff --git a/src/gfx/ui.onyx b/src/gfx/ui.onyx index 32264af..f0a50b0 100644 --- a/src/gfx/ui.onyx +++ b/src/gfx/ui.onyx @@ -342,6 +342,37 @@ draw_checkbox :: (use r: Rect, value: ^bool, text: str, theme := ^default_checkb return result; } + + +scrolling_region_start :: (r: Rect, max_y_scroll := 10000.0f, site := #callsite, increment := 0) { + hash := get_site_hash(site, increment); + mx, my := mouse_get_position(); + state := map.get_ptr(^scroll_states, hash); + if state == null { + animation_states[hash] = .{}; + state = ^scroll_states[hash]; + } + + contains := Rect.contains(r, .{~~mx, ~~my}); + if contains { + scroll_delta := mouse_get_scroll_vector(); + state.xscroll -= scroll_delta.x * 20; + state.yscroll -= scroll_delta.y * 20; + + state.yscroll = math.clamp(state.yscroll, 0, max_y_scroll); + } + + immediate_flush(); + immediate_push_scissor(r.x, r.y, r.w, r.h); + immediate_set_scroll(-state.xscroll, -state.yscroll); +} + +scrolling_region_stop :: () { + immediate_flush(); + immediate_pop_scissor(); + immediate_set_scroll(0, 0); +} + #if !#defined(Rect) { Rect :: struct { x, y, w, h: f32; @@ -366,9 +397,6 @@ draw_checkbox :: (use r: Rect, value: ^bool, text: str, theme := ^default_checkb *v = target; return; } - - if *v < target do *v += diff; - if *v > target do *v -= diff; } } @@ -453,6 +481,14 @@ draw_checkbox :: (use r: Rect, value: ^bool, text: str, theme := ^default_checkb return false; } + + Scroll_State :: struct { + xscroll: f32; + yscroll: f32; + } + + scroll_states : Map(UI_Id, Scroll_State); + get_site_hash :: macro (site: CallSite, increment := 0) -> UI_Id { hash :: package core.hash file_hash := hash.to_u32(site.file); diff --git a/src/utils/input.onyx b/src/utils/input.onyx index 77bca19..5273c50 100644 --- a/src/utils/input.onyx +++ b/src/utils/input.onyx @@ -1,39 +1,51 @@ use package core use package glfw3 +// If you are offseting the mouse coordinate for world space +// or UI scrolling etc., set this function to be the function +// to ask for the current offset. Currently scaling the mouse +// coordinate is not supported, only linear translations. +Mouse_Offset_Function :: immediate_get_scroll + + #local { - keys_this_frame : [..] u32 // Keys currently being pressed this frame - keys_pulse_frame : [..] u32 // Keys pressed during this frame, only set once per keypress - keys_last_frame : [..] u32 // Keys being pressed in the last frame + keys_this_frame : [..] u32 // Keys currently being pressed this frame + keys_pulse_frame : [..] u32 // Keys pressed during this frame, only set once per keypress + keys_last_frame : [..] u32 // Keys being pressed in the last frame - buttons_this_frame: [8] bool // Mouse buttons being pressed this frame - buttons_last_frame: [8] bool // Mouse buttons being pressed last frame + buttons_this_frame: [8] bool // Mouse buttons being pressed this frame + buttons_last_frame: [8] bool // Mouse buttons being pressed last frame + + scroll_x: f64 + scroll_y: f64 } input_update :: () { glfwGetCursorPos(window, ^mouse_x, ^mouse_y); - array.clear(^keys_pulse_frame); - for keys_this_frame { - if !array.contains(keys_last_frame, it) { - keys_pulse_frame << it; - } - } + array.clear(^keys_pulse_frame); + for keys_this_frame { + if !array.contains(keys_last_frame, it) { + keys_pulse_frame << it; + } + } } input_post_update :: () { - array.clear(^keys_pulse_frame); - array.clear(^keys_last_frame); - for keys_this_frame do keys_last_frame << it; + array.clear(^keys_pulse_frame); + array.clear(^keys_last_frame); + for keys_this_frame do keys_last_frame << it; - for 8 do buttons_last_frame[it] = buttons_this_frame[it]; + for 8 do buttons_last_frame[it] = buttons_this_frame[it]; - last_mouse_x = mouse_x; - last_mouse_y = mouse_y; + last_mouse_x = mouse_x; + last_mouse_y = mouse_y; + scroll_x = 0; + scroll_y = 0; } input_get_keys_this_frame :: () -> [] u32 { - return keys_pulse_frame; + return keys_pulse_frame; } is_key_down :: (key) => array.contains(keys_this_frame, key); @@ -45,57 +57,83 @@ is_button_just_down :: (button) => buttons_this_frame[button] && !buttons_last_f is_button_just_up :: (button) => !buttons_this_frame[button] && buttons_last_frame[button]; #local { - last_mouse_x: f64; - last_mouse_y: f64; + last_mouse_x: f64; + last_mouse_y: f64; - mouse_x: f64; - mouse_y: f64; + mouse_x: f64; + mouse_y: f64; } mouse_get_delta :: () -> (f64, f64) { - return mouse_x - last_mouse_x, mouse_y - last_mouse_y; + return mouse_x - last_mouse_x, mouse_y - last_mouse_y; } mouse_get_delta_vector :: () -> Vector2 { - dmx, dmy := mouse_get_delta(); - return .{ ~~dmx, ~~dmy }; + dmx, dmy := mouse_get_delta(); + return .{ ~~dmx, ~~dmy }; } mouse_get_position :: () -> (f64, f64) { - return mouse_x, mouse_y; + mx, my := mouse_x, mouse_y; + #if #defined(Mouse_Offset_Function) { + scroll := Mouse_Offset_Function(); + mx -= ~~ scroll.x; + my -= ~~ scroll.y; + } + return mx, my; } mouse_get_position_vector :: () -> Vector2 { - return .{ ~~mouse_x, ~~mouse_y }; + mx, my := mouse_x, mouse_y; + #if #defined(Mouse_Offset_Function) { + scroll := Mouse_Offset_Function(); + mx -= ~~ scroll.x; + my -= ~~ scroll.y; + } + return .{ ~~mx, ~~my }; +} + +mouse_get_scroll :: () -> (f64, f64) { + return scroll_x, scroll_y; } +mouse_get_scroll_vector :: () -> Vector2 { + return .{ ~~scroll_x, ~~scroll_y }; +} input_bind_glfw_events :: (window: GLFWwindow_p) { - glfwSetKeyCallback(window, INPUT_KEY_EVENT); - glfwSetMouseButtonCallback(window, INPUT_BUTTON_EVENT); + glfwSetKeyCallback(window, INPUT_KEY_EVENT); + glfwSetMouseButtonCallback(window, INPUT_BUTTON_EVENT); + glfwSetScrollCallback(window, INPUT_SCROLL_EVENT); } #local { - INPUT_BUTTON_EVENT :: "__input_button_event" - INPUT_KEY_EVENT :: "__input_key_event" + INPUT_BUTTON_EVENT :: "__input_button_event" + INPUT_KEY_EVENT :: "__input_key_event" + INPUT_SCROLL_EVENT :: "__input_scroll_event" } #export INPUT_BUTTON_EVENT (window: GLFWwindow_p, button, action, mod: u32) { - if action == GLFW_PRESS { - buttons_this_frame[button] = true; - } + if action == GLFW_PRESS { + buttons_this_frame[button] = true; + } - if action == GLFW_RELEASE { - buttons_this_frame[button] = false; - } + if action == GLFW_RELEASE { + buttons_this_frame[button] = false; + } } #export INPUT_KEY_EVENT (window: GLFWwindow_p, key, scancode, action, mod: u32) { - if action == GLFW_PRESS { - keys_this_frame << key; - } + if action == GLFW_PRESS { + keys_this_frame << key; + } + + if action == GLFW_RELEASE { + array.remove(^keys_this_frame, key); + } +} - if action == GLFW_RELEASE { - array.remove(^keys_this_frame, key); - } +#export INPUT_SCROLL_EVENT (window: GLFWwindow_p, xoff, yoff: f64) { + scroll_x = xoff; + scroll_y = yoff; }