From 7f63ec5c10eb7e8dd4edaabd1a6a437328911d39 Mon Sep 17 00:00:00 2001 From: Jon Santmyer Date: Sun, 10 May 2026 13:29:56 -0400 Subject: fleets --- assets/shaders/tacmap/body.wgsl | 51 +++++++++++++--------------- assets/shaders/tacmap/fleet.wgsl | 73 ++++++++++++++++++++++++++++++++++++++++ assets/shaders/tacmap/orbit.wgsl | 22 ++++++++---- 3 files changed, 111 insertions(+), 35 deletions(-) create mode 100644 assets/shaders/tacmap/fleet.wgsl (limited to 'assets') diff --git a/assets/shaders/tacmap/body.wgsl b/assets/shaders/tacmap/body.wgsl index 0cfd5f9..9e6419e 100644 --- a/assets/shaders/tacmap/body.wgsl +++ b/assets/shaders/tacmap/body.wgsl @@ -7,7 +7,6 @@ struct InstanceInput { struct VertexOutput { @builtin(position) clip_position: vec4, @location(0) local_position: vec3, - @location(1) distance: f32 }; struct CameraUniform { @@ -40,46 +39,42 @@ fn vs_main( let model = QUAD_VERTICES[index]; var view = camera.view; - //Billboard the circle - let camera_right = vec3(view[0][0], view[1][0], view[2][0]); - let camera_up = vec3(view[0][1], view[1][1], view[2][1]); - let model_pos = camera_right * model.x + - camera_up * model.y; + out.local_position = model; let min_size = 0.025; + let real_radius = max(min_size / 2.0, instance.radius * camera.scale); //Scale the world around the camera scale and translate about the camera's //absolute (/target) position let relative_pos = instance.position; - let origin_pos = instance.origin - camera.abs_pos; - - /*if all(relative_pos != origin_pos) { - if length(relative_pos) < 0.01 / camera.scale { - if length(relative_pos) != 0.0 { - out.clip_position = vec4(0.0, 0.0, 0.0, 1.0); - return out; - } - } - }*/ - - let instance_pos = (relative_pos + origin_pos - camera.rel_pos) * camera.scale; + let origin_pos = instance.origin - camera.abs_pos - camera.rel_pos; let view_proj = camera.proj * view; - let center_view_pos = view_proj * vec4(instance_pos, 1.0); - let vertex_view_pos = view_proj * vec4(instance_pos + (model_pos * instance.radius * camera.scale), 1.0); + let origin_vp_pos = view_proj * vec4(origin_pos * camera.scale, 1.0); + let offset_vp = view_proj * vec4(relative_pos * camera.scale, 0.0); + let center_vp_pos = origin_vp_pos + offset_vp; + + let offset_ndc = offset_vp.xy / origin_vp_pos.w; + + if (length(offset_ndc) < 2.0 * min_size){ + if all(offset_vp != vec4(0.0)) { + out.clip_position = vec4(0.0, 0.0, 0.0, 1.0); + return out; + } + } + + let model_proj = camera.proj * vec4(model.xy, 0.0, 0.0); + let vertex_vp_pos = center_vp_pos + vec4(model_proj.xy * instance.radius * camera.scale, 0.0, 0.0); - let vertex_dist = length(vertex_view_pos - center_view_pos) / center_view_pos.w; + let vertex_dist = length(vertex_vp_pos - center_vp_pos) / center_vp_pos.w; if vertex_dist < min_size { - out.clip_position = center_view_pos / center_view_pos.w; - out.clip_position += camera.proj * vec4(model.xy * (min_size / 2.0), 0.0, 0.0); + out.clip_position = center_vp_pos / center_vp_pos.w; + out.clip_position += model_proj * (min_size / 2.0); }else{ - out.clip_position = vertex_view_pos; + out.clip_position = vertex_vp_pos; } - out.local_position = model; - out.distance = length(instance_pos); - return out; } @@ -91,6 +86,6 @@ fn fs_main(in: VertexOutput if point_dist > 1.0 { alpha = 0.0; } - let color = vec3(1.0, 1.0, 1.0) / clamp(in.distance, 1.0, 1.5); + let color = vec3(1.0); return vec4(color, alpha); } diff --git a/assets/shaders/tacmap/fleet.wgsl b/assets/shaders/tacmap/fleet.wgsl new file mode 100644 index 0000000..8a87fb9 --- /dev/null +++ b/assets/shaders/tacmap/fleet.wgsl @@ -0,0 +1,73 @@ +struct InstanceInput { + @location(0) rotmat_0: vec3, + @location(1) rotmat_1: vec3, + @location(2) rotmat_2: vec3, + @location(3) origin: vec3, + @location(4) offset: vec3, +}; + +struct VertexOutput { + @builtin(position) clip_position: vec4, + @location(0) color: vec3 +}; + +struct CameraUniform { + view: mat4x4, + proj: mat4x4, + abs_pos: vec3, + rel_pos: vec3, + scale: f32, +}; + +@group(0) @binding(0) +var camera: CameraUniform; + +const FLEET_VERTICES = array,6>( + vec3(-1.0, -1.0, 0.0), + vec3(-1.0, 1.0 , 0.0), + vec3(1.0, 0.0 , 0.0), + + vec3(-1.0, 0.0, -1.0), + vec3(-1.0, 0.0, 1.0 ), + vec3(1.0, 0.0, 0.0 ), +); + +@vertex +fn vs_main( + @builtin(vertex_index) index: u32, + instance: InstanceInput +) -> VertexOutput { + var out: VertexOutput; + + let rotmat = mat3x3( + instance.rotmat_0, + instance.rotmat_1, + instance.rotmat_2 + ); + let model_pos = rotmat * FLEET_VERTICES[index] * 0.025; + var view = camera.view; + + let min_size = 0.025; + + //Scale the world around the camera scale and translate about the camera's + //absolute (/target) position + let origin_pos = instance.origin - camera.abs_pos; + let offset_pos = instance.offset - camera.rel_pos; + + let instance_pos = (offset_pos + origin_pos) * camera.scale; + let vertex_pos = instance_pos + model_pos; + + let view_proj = camera.proj * view; + let instance_vp_pos = view_proj * vec4(instance_pos, 1.0); + let model_vp_pos = view_proj * vec4(model_pos, 0.0); + + out.clip_position = instance_vp_pos + model_vp_pos; + out.color = vec3(0.75, 1.0, 0.75); + return out; +} + +@fragment +fn fs_main(in: VertexOutput +) -> @location(0) vec4 { + return vec4(in.color, 1.0); +} diff --git a/assets/shaders/tacmap/orbit.wgsl b/assets/shaders/tacmap/orbit.wgsl index a890fd8..7276345 100644 --- a/assets/shaders/tacmap/orbit.wgsl +++ b/assets/shaders/tacmap/orbit.wgsl @@ -38,24 +38,32 @@ fn vs_main( origins[model.origin][1], origins[model.origin][2]); - let model_pos = ((origin - camera.abs_pos - camera.rel_pos) + model.position) * camera.scale; - let origin_pos = (origin - camera.abs_pos - camera.rel_pos) * camera.scale; + let offset_pos = model.position; + let origin_pos = origin - camera.abs_pos - camera.rel_pos; - let view = camera.view; + let view_proj = camera.proj * camera.view; + + let origin_view_pos = camera.view * vec4(origin_pos * camera.scale, 1.0); + let offset_view = camera.view * vec4(offset_pos * camera.scale, 0.0); + let point_view_pos = origin_view_pos + offset_view; let orbit_normal = normalize(model.position); var normal = orbit_normal; - if length(model_pos - origin_pos) > 0.01 { + let offset_ndc = offset_view.xy / origin_view_pos.z; + + let discard_radius = 0.05; + + if length(offset_ndc) > discard_radius { normal *= POINT_NORMALS[index]; } - let view_proj = camera.proj * camera.view; + let point_vp_pos = camera.proj * point_view_pos; //Scale the world around the camera scale and translate about the camera's //absolute (/target) position - let point_view_pos = view_proj * vec4(model_pos + normal * 0.005, 1.0); - out.clip_position = point_view_pos; + let segment_vp_pos = point_vp_pos + (view_proj * vec4(normal * 0.005, 0.0)); + out.clip_position = segment_vp_pos; return out; } -- cgit v1.2.3