smoothing out movement; correcting fog
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 8 Apr 2022 03:59:14 +0000 (22:59 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 8 Apr 2022 03:59:14 +0000 (22:59 -0500)
.vscode/tasks.json
run_tree/assets/shaders/world.glsl
run_tree/assets/shaders/world_object.glsl [new file with mode: 0644]
src/client/game.onyx
src/client/gfx/shader.onyx
src/client/net.onyx
src/client/utils/vecmath.onyx
src/client/world/physics.onyx
src/server/server.onyx
src/shared/packets.onyx

index 77fd05cfa4d03faab8e9c27d663c65ab13e987e9..3eb74f17fdfa1c2c8b167ef7849b2913f2a47772 100644 (file)
@@ -9,6 +9,9 @@
             "problemMatcher": "$onyx",
             "options": {
                 "cwd": "${workspaceFolder}/run_tree",
+                "shell": {
+                    "executable": "/bin/sh",
+                }
             },
             "presentation": {
                 "echo": true,
index afc9b6c46322df58ea26f512092ab745c2f6984c..d873957d0ecf05a17e40ff76148ab2363666036b 100644 (file)
@@ -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 (file)
index 0000000..d97d514
--- /dev/null
@@ -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
index 565a56ebf6ac78d96928229fc290b070d6d87e75..ed4993c5825a3713661d6fc0e9ffb0fb7b02ba3b 100644 (file)
@@ -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);
     }
index cdc2615e68623e8290bf44cff9c14f80a6ca27a5..7aafca94de7a1ed36989cac357565c817b150d1d 100644 (file)
@@ -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
index 3ae54818b9d64df1671263ae57f18653a77dfdb9..4898ff0ccdcc34363f0511499ba54e282a030af8 100644 (file)
@@ -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
index c3e02e31d80e3d8094b2d6bdbbaab63620cd0463..bbad972b81490966bea78f461d06cc4a0e1f2209 100644 (file)
@@ -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 {
index 2c725c2937793cdf015ea5fe59228e0dab3f5e3e..66cf95749a2b16cf7ab673c12fe8d31a1e716a51 100644 (file)
@@ -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;
 }
 
 
index 0719a08657d566fca611914855b6e1eb9951856d..9fd480ac237b4aa60a8a2a7a4cbe372bea57a230 100644 (file)
@@ -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);
index b50d5dfb645437f81236a921326d03c041a89e2a..be3312a7ca1b1f67fb9ab8acff177665d08a587a 100644 (file)
@@ -67,6 +67,7 @@ Player_Moved :: struct #pack {
     position: Vector3; 
     velocity: Vector3;
     facing:   Vector3;
+    on_ground: bool;
 }
 
 Chat_Message :: struct #pack {