From 6a748574828f34b5d5bfd2f5872ac0ae86bea829 Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Thu, 7 Apr 2022 22:59:14 -0500 Subject: [PATCH] smoothing out movement; correcting fog --- .vscode/tasks.json | 3 ++ run_tree/assets/shaders/world.glsl | 8 ++-- run_tree/assets/shaders/world_object.glsl | 46 ++++++++++++++++++ src/client/game.onyx | 30 +++++++++--- src/client/gfx/shader.onyx | 48 +++++++++++++++++++ src/client/net.onyx | 20 ++++---- src/client/utils/vecmath.onyx | 6 ++- src/client/world/physics.onyx | 58 ++++++++++++++++++----- src/server/server.onyx | 8 ++-- src/shared/packets.onyx | 1 + 10 files changed, 194 insertions(+), 34 deletions(-) create mode 100644 run_tree/assets/shaders/world_object.glsl diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 77fd05c..3eb74f1 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -9,6 +9,9 @@ "problemMatcher": "$onyx", "options": { "cwd": "${workspaceFolder}/run_tree", + "shell": { + "executable": "/bin/sh", + } }, "presentation": { "echo": true, diff --git a/run_tree/assets/shaders/world.glsl b/run_tree/assets/shaders/world.glsl index afc9b6c..d873957 100644 --- a/run_tree/assets/shaders/world.glsl +++ b/run_tree/assets/shaders/world.glsl @@ -40,9 +40,11 @@ void main() { uniform sampler2D u_sampler; -uniform vec3 u_fog_color; -uniform float u_fog_start; -uniform float u_fog_range; +layout(std140) uniform u_game_fog_block { + uniform vec3 u_fog_color; + uniform float u_fog_start; + uniform float u_fog_range; +}; out vec4 fragColor; void main() { diff --git a/run_tree/assets/shaders/world_object.glsl b/run_tree/assets/shaders/world_object.glsl new file mode 100644 index 0000000..d97d514 --- /dev/null +++ b/run_tree/assets/shaders/world_object.glsl @@ -0,0 +1,46 @@ +precision mediump float; + +COMM vec4 v_col; +COMM float v_dist; + +#ifdef VERTEX_SHADER + +layout(location = 0) in vec3 a_pos; +layout(location = 1) in vec4 a_col; + +layout(std140) uniform u_world_matrix_block { + mat4 u_view; + mat4 u_world; + mat4 u_model; +}; + +void main() { + vec4 pos = u_world * u_model * vec4(a_pos, 1); + v_dist = length(pos); + gl_Position = u_view * pos; + v_col = a_col; +} + +#endif + +#ifdef FRAGMENT_SHADER + +layout(std140) uniform u_game_fog_block { + uniform vec3 u_fog_color; + uniform float u_fog_start; + uniform float u_fog_range; +}; + +uniform vec4 color; +out vec4 fragColor; + +void main() { + vec4 output_color = v_col * color; + + // Not going to rely on clamp() existing. + float fog = min(1.0f, max(0.0f, (v_dist - u_fog_start) / u_fog_range)); + + fragColor = mix(output_color, vec4(u_fog_color, 1), fog); +} + +#endif diff --git a/src/client/game.onyx b/src/client/game.onyx index 565a56e..ed4993c 100644 --- a/src/client/game.onyx +++ b/src/client/game.onyx @@ -18,6 +18,13 @@ world: ^World; selected_block: Vector3i; player_shader: Shader; +world_fog_block: Shader_Block; + +World_Fog :: struct { + u_fog_color: Vector3; + u_fog_start: f32; + u_fog_range: f32; +} Game_State :: struct { init :: game_init; @@ -28,12 +35,16 @@ Game_State :: struct { game_init :: (_: rawptr) { world_shader = shader_make("assets/shaders/world.glsl"); - player_shader = shader_make("assets/shaders/basic.glsl"); + player_shader = shader_make("assets/shaders/world_object.glsl"); shader_link_world_matrix_block(world_shader); shader_link_world_matrix_block(player_shader); - shader_set_uniform(world_shader, #cstr "u_fog_start", 50.0f); - shader_set_uniform(world_shader, #cstr "u_fog_range", 10.0f); + shader_block_link(^world_fog_block, world_shader, #cstr "u_game_fog_block"); + shader_block_link(^world_fog_block, player_shader, #cstr "u_game_fog_block"); + + world_fog_block = shader_block_create(World_Fog); + shader_block_update(^world_fog_block, "u_fog_start", 50.0f); + shader_block_update(^world_fog_block, "u_fog_range", 10.0f); font = font_lookup(.{"./assets/fonts/calibri.ttf", 32}); chat_font = font_lookup(.{"./assets/fonts/calibri.ttf", 16}); @@ -74,8 +85,13 @@ game_update :: (_: rawptr, dt: f32) { send_movement_timeout -= dt; if send_movement_timeout < 0 { - send_movement_timeout = 0.05f; - net_send_movement_update(player.body.pos, player.body.vel, .{1,0,0}); + send_movement_timeout = 0.1f; + net_send_movement_update(player.body.pos, player.body.vel, .{1,0,0}, player.body.on_ground); + } + + for ^other_players.entries { + if it.value.on_ground do it.value.velocity.y = 0; + it.value.position += it.value.velocity * dt; } if is_key_just_down(GLFW_KEY_F7) { @@ -115,7 +131,7 @@ draw_scene :: () { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); shader_use(world_shader); - shader_set_uniform(world_shader, #cstr "u_fog_color", fog_color); + shader_block_update(^world_fog_block, "u_fog_color", fog_color); shader_set_uniform(world_shader, #cstr "u_texture", 0); glEnable(GL_DEPTH_TEST); world_draw(world); @@ -126,6 +142,8 @@ draw_scene :: () { shader_use(player_shader); shader_set_uniform(player_shader, #cstr "color", Color.{1,0,0}); for^ other_players.entries { + if (it.value.position - player.body.pos)->square_mag() >= 70 * 70 do continue; + update_model_matrix(it.value.position - .{0,0.8,0}, .{0.3, 1, 0.3}); mesh_draw(Meshes.white_box); } diff --git a/src/client/gfx/shader.onyx b/src/client/gfx/shader.onyx index cdc2615..7aafca9 100644 --- a/src/client/gfx/shader.onyx +++ b/src/client/gfx/shader.onyx @@ -169,3 +169,51 @@ update_model_matrix :: (v: Vector3, scale := Vector3.{1,1,1}) { } } + + +Shader_Block :: struct { + block_buffer: GLuint; + uniform_block: u32; + type: type_expr; +} + +shader_block_create :: (T: type_expr) -> Shader_Block { + #persist next_block_id := 0; + + block: Shader_Block; + block.type = T; + glGenBuffers(1, ^block.block_buffer); + + size := type_info.size_of(T); + + glBindBuffer(GL_UNIFORM_BUFFER, block.block_buffer); + glBufferData(GL_UNIFORM_BUFFER, size, null, GL_DYNAMIC_DRAW); + + block.uniform_block = next_block_id; + next_block_id += 1; + + glBindBufferBase(GL_UNIFORM_BUFFER, block.uniform_block, block.block_buffer); + + return block; +} + +shader_block_link :: (s: ^Shader_Block, use shader: Shader, field_name: cstr) { + index := glGetUniformBlockIndex(prog, field_name); + glUniformBlockBinding(prog, index, s.uniform_block); +} + +shader_block_update :: (s: ^Shader_Block, field: str, value: $T) { + glBindBuffer(GL_UNIFORM_BUFFER, s.block_buffer); + defer glBindBuffer(GL_UNIFORM_BUFFER, -1); + + v := value; + + s_info := cast(^type_info.Type_Info_Struct) type_info.get_type_info(s.type); + for^ s_info.members { + if it.name == field { + if it.type != T do return; + glBufferSubData(GL_UNIFORM_BUFFER, it.offset, sizeof T, ^v); + break; + } + } +} \ No newline at end of file diff --git a/src/client/net.onyx b/src/client/net.onyx index 3ae5481..4898ff0 100644 --- a/src/client/net.onyx +++ b/src/client/net.onyx @@ -51,7 +51,8 @@ net_handle_packet :: (packet_data: [] u8) { other_players[~~ joined_packet.player_id] = .{ name, - .{0, 0, 0}, .{0, 0, 0}, .{0, 0, 0} + .{0, 0, 0}, .{0, 0, 0}, .{0, 0, 0}, + false }; if joined_packet.player_id != player_id { @@ -95,9 +96,10 @@ net_handle_packet :: (packet_data: [] u8) { if moved.player_id == player_id do return; player := ^other_players[~~ moved.player_id]; - player.position = moved.position; - player.velocity = moved.velocity; - player.facing = moved.facing; + player.position = moved.position; + player.velocity = moved.velocity; + player.facing = moved.facing; + player.on_ground = moved.on_ground; } case .Block_Updates { @@ -151,12 +153,13 @@ net_send_chat_message :: (message: str) { onet.peer_send(peer, 0, p); } -net_send_movement_update :: (position: Vector3, velocity: Vector3, facing: Vector3) { +net_send_movement_update :: (position: Vector3, velocity: Vector3, facing: Vector3, on_ground: bool) { movement := new(packets.Player_Moved); movement.player_id = player_id; movement.position = position; movement.velocity = velocity; movement.facing = facing; + movement.on_ground = on_ground; p := new(onet.Packet); p.data = .{ ~~movement, sizeof typeof *movement }; @@ -185,9 +188,10 @@ net_send_block_updates :: (updates: [] packets.Block_Updates.Update) { Remote_Player :: struct { name: str; - position: Vector3; - velocity: Vector3; - facing: Vector3; + position: Vector3; + velocity: Vector3; + facing: Vector3; + on_ground: bool; } @TEMPORARY diff --git a/src/client/utils/vecmath.onyx b/src/client/utils/vecmath.onyx index c3e02e3..bbad972 100644 --- a/src/client/utils/vecmath.onyx +++ b/src/client/utils/vecmath.onyx @@ -36,6 +36,8 @@ Vector3 :: struct { mag :: macro (v: Vector3) => math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z); + square_mag :: macro (v: Vector3) => v.x * v.x + v.y * v.y + v.z * v.z; + neg :: macro (v: Vector3) => Vector3.{ -v.x, -v.y, -v.z }; dot :: macro (v1, v2: Vector3) -> f32 { @@ -82,13 +84,13 @@ Vector3 :: struct { #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 }; -#operator * macro (v1, v2: Vector3) => (typeof v1).{ v1.x * v2.x, v1.y * v2.y, v1.z * v3.z }; +#operator * macro (v1, v2: Vector3) => (typeof v1).{ v1.x * v2.x, v1.y * v2.y, v1.z * v2.z }; #operator == macro (v1, v2: Vector3) => v1.x == v2.x && v1.y == v2.y && v1.z == v2.z; #operator + macro (v1, v2: Vector3i) => Vector3i.{ v1.x + v2.x, v1.y + v2.y, v1.z + v2.z }; #operator - macro (v1, v2: Vector3i) => Vector3i.{ v1.x - v2.x, v1.y - v2.y, v1.z - v2.z }; #operator * macro (v: Vector3i, s: i32) => Vector3i.{ v.x * s, v.y * s, v.z * s }; -#operator * macro (v1, v2: Vector3i) => (typeof v1).{ v1.x * v2.x, v1.y * v2.y, v1.z * v3.z }; +#operator * macro (v1, v2: Vector3i) => (typeof v1).{ v1.x * v2.x, v1.y * v2.y, v1.z * v2.z }; #operator == macro (v1, v2: Vector3i) => v1.x == v2.x && v1.y == v2.y && v1.z == v2.z; #local { diff --git a/src/client/world/physics.onyx b/src/client/world/physics.onyx index 2c725c2..66cf957 100644 --- a/src/client/world/physics.onyx +++ b/src/client/world/physics.onyx @@ -9,6 +9,32 @@ AABB :: struct { && a1.z0 < a2.z1 && a1.z1 > a2.z0; } + overlap :: (a1, a2: AABB) -> Vector3 { + ox, oy, oz: f32; + if a1.x0 < a2.x1 && a1.x1 > a2.x0 { + dx1 := a1.x0 - a2.x1; + dx2 := a1.x1 - a2.x0; + if math.abs(dx1) < math.abs(dx2) do ox = dx1; + else do ox = dx2; + } + + if a1.y0 < a2.y1 && a1.y1 > a2.y0 { + dy1 := a1.y0 - a2.y1; + dy2 := a1.y1 - a2.y0; + if math.abs(dy1) < math.abs(dy2) do oy = dy1; + else do oy = dy2; + } + + if a1.z0 < a2.z1 && a1.z1 > a2.z0 { + dz1 := a1.z0 - a2.z1; + dz2 := a1.z1 - a2.z0; + if math.abs(dz1) < math.abs(dz2) do oz = dz1; + else do oz = dz2; + } + + return .{ox, oy, oz}; + } + contains :: (a: AABB, v: Vector3) -> bool { return a.x0 < v.x && v.x < a.x1 && a.y0 < v.y && v.y < a.y1 @@ -21,6 +47,7 @@ PhysicsBody :: struct { vel: Vector3; acc: Vector3; + collied := false; on_ground := false; get_collision_object: (pos: Vector3) -> AABB; // This will get expanded on when other collision objects are defined @@ -31,35 +58,42 @@ physics_apply_gravity :: (use body: ^PhysicsBody) { } physics_simulate :: (use body: ^PhysicsBody, dt: f32, world: ^World) { - aabb_buffer := (cast(^AABB) alloc.from_stack(sizeof [256] AABB))[0..256]; + aabb_buffer := alloc.array_from_stack(AABB, 256); aabbs := world_get_aabbs(world, pos, 3, aabb_buffer); - try_move :: macro (delta: Vector3) -> f32 { + try_move :: macro (d: f32, dir: Vector3) -> (f32, f32) { + delta := dir * d; new_pos := body.pos + delta; body_aabb := get_collision_object(new_pos); for^ aabbs { - if body_aabb->intersects(*it) { + if body_aabb->intersects(*it) { if delta.y < 0 do on_ground = true; - return 0; + + overlap := body_aabb->overlap(*it); + overlap *= 1.1f; + change := delta - overlap; + + return 0, change->dot(dir); } } - return 1; + return 1, 0; } on_ground = false; - move_x := try_move(.{acc.x*0.5*dt*dt + vel.x * dt, 0, 0}); - move_y := try_move(.{0, acc.y*0.5*dt*dt + vel.y * dt, 0}); - move_z := try_move(.{0, 0, acc.z*0.5*dt*dt + vel.z * dt}); + move_x, overlap_x := try_move(acc.x*0.5*dt*dt + vel.x*dt, .{1,0,0}); + move_y, overlap_y := try_move(acc.y*0.5*dt*dt + vel.y*dt, .{0,1,0}); + move_z, overlap_z := try_move(acc.z*0.5*dt*dt + vel.z*dt, .{0,0,1}); - pos.x += vel.x * dt * move_x; - pos.y += vel.y * dt * move_y; - pos.z += vel.z * dt * move_z; + pos.x += vel.x * dt * move_x + overlap_x; + pos.y += vel.y * dt * move_y + overlap_y; + pos.z += vel.z * dt * move_z + overlap_z; vel += acc * dt; + vel *= .{ move_x, move_y, move_z }; - if on_ground do vel.y = 0; + // if on_ground do vel.y = 0; } diff --git a/src/server/server.onyx b/src/server/server.onyx index 0719a08..9fd480a 100644 --- a/src/server/server.onyx +++ b/src/server/server.onyx @@ -15,6 +15,7 @@ Player_Data :: struct { position: Vector3 = .{0,0,0}; velocity: Vector3 = .{0,0,0}; facing: Vector3 = .{0,0,0}; + on_ground := false; } max_connected_players := 8; @@ -107,9 +108,10 @@ handle_packet :: (peer: ^onet.Peer, packet_data: [] u8) { player := ^connected_players[~~ moved.player_id]; if player == null do return; - player.position = moved.position; - player.velocity = moved.velocity; - player.facing = moved.facing; + player.position = moved.position; + player.velocity = moved.velocity; + player.facing = moved.facing; + player.on_ground = moved.on_ground; packet := new(onet.Packet); packet.data = memory.copy_slice(packet_data); diff --git a/src/shared/packets.onyx b/src/shared/packets.onyx index b50d5df..be3312a 100644 --- a/src/shared/packets.onyx +++ b/src/shared/packets.onyx @@ -67,6 +67,7 @@ Player_Moved :: struct #pack { position: Vector3; velocity: Vector3; facing: Vector3; + on_ground: bool; } Chat_Message :: struct #pack { -- 2.25.1