struct VertexInput { @builtin(vertex_index) index: u32, @location(0) origin: u32, @location(1) position: vec3 }; struct VertexOutput { @builtin(position) clip_position: vec4, }; struct CameraUniform { view: mat4x4, proj: mat4x4, abs_pos: vec3, rel_pos: vec3, scale: f32 }; @group(0) @binding(0) var camera: CameraUniform; @group(1) @binding(0) var origins: array>; const POINT_NORMALS = array( -0.5, 0.5 ); @vertex fn vs_main( model: VertexInput, ) -> VertexOutput { var out: VertexOutput; let index = model.index % 2u; let origin = vec3( origins[model.origin][0], origins[model.origin][1], origins[model.origin][2]); let offset_pos = model.position; let origin_pos = origin - camera.abs_pos - camera.rel_pos; 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; 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 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 segment_vp_pos = point_vp_pos + (view_proj * vec4(normal * 0.005, 0.0)); out.clip_position = segment_vp_pos; return out; } @fragment fn fs_main(in: VertexOutput ) -> @location(0) vec4 { return vec4(0.0, 0.5, 0.0, 1.0); }