1#import bevy_gaussian_splatting::bindings::{ 11#import bevy_gaussian_splatting::depth::{ 14#import bevy_gaussian_splatting::helpers::{ 18#import bevy_gaussian_splatting::transform::{ 24#import bevy_gaussian_splatting::surfel::{ 26 get_bounding_box_cov2d, 27 surfel_fragment_power, 32#ifdef PRECOMPUTE_COVARIANCE_3D 33#import bevy_gaussian_splatting::packed::{ 41#import bevy_gaussian_splatting::packed::{ 53#ifdef PRECOMPUTE_COVARIANCE_3D 54#import bevy_gaussian_splatting::planar::{ 62#import bevy_gaussian_splatting::planar::{ 77#ifdef PRECOMPUTE_COVARIANCE_3D 78#import bevy_gaussian_splatting::texture::{ 87#import bevy_gaussian_splatting::texture::{ 101@group(3) @binding(0) var<storage, read> sorted_entries: array<Entry>; 103fn get_entry(index: u32) -> Entry { 104 return sorted_entries[index]; 109@group(3) @binding(0) var sorted_entries: texture_2d<u32>; 111fn get_entry(index: u32) -> Entry { 112 let sample = textureLoad( 126struct GaussianVertexOutput { 127 @builtin(position) position: vec4<f32>, 128 @location(0) color: vec4<f32>, 129 @location(1) uv: vec2<f32>, 131 @location(2) conic: vec3<f32>, 132 @location(3) major_minor: vec2<f32>, 133#else ifdef GAUSSIAN_SURFEL 134 @location(2) local_to_pixel_u: vec3<f32>, 135 @location(3) local_to_pixel_v: vec3<f32>, 136 @location(4) local_to_pixel_w: vec3<f32>, 137 @location(5) mean_2d: vec2<f32>, 138 @location(6) radius: vec2<f32>, 142struct GaussianVertexOutput { 143 @builtin(position) position: vec4<f32>, 144 @location(0) @interpolate(flat) color: vec4<f32>, 145 @location(1) @interpolate(linear) uv: vec2<f32>, 147 @location(2) @interpolate(flat) conic: vec3<f32>, 148 @location(3) @interpolate(linear) major_minor: vec2<f32>, 149#else ifdef GAUSSIAN_SURFEL 150 @location(2) @interpolate(flat) local_to_pixel_u: vec3<f32>, 151 @location(3) @interpolate(flat) local_to_pixel_v: vec3<f32>, 152 @location(4) @interpolate(flat) local_to_pixel_w: vec3<f32>, 153 @location(5) @interpolate(flat) mean_2d: vec2<f32>, 154 @location(6) @interpolate(flat) radius: vec2<f32>, 162fn compute_cov3d(scale: vec3<f32>, rotation: vec4<f32>) -> array<f32, 6> { 163 let S = get_scale_matrix(scale); 166 gaussian_uniforms.transform[0].xyz, 167 gaussian_uniforms.transform[1].xyz, 168 gaussian_uniforms.transform[2].xyz, 171 let R = get_rotation_matrix(rotation); 174 let Sigma = transpose(M) * M; 175 let TS = T * Sigma * transpose(T); 177 return array<f32, 6>( 187fn compute_cov2d_3dgs( 191#ifdef PRECOMPUTE_COVARIANCE_3D 192 let cov3d = get_cov3d(index); 194 let rotation = get_rotation(index); 195 let scale = get_scale(index); 197 let cov3d = compute_cov3d(scale, rotation); 201 cov3d[0], cov3d[1], cov3d[2], 202 cov3d[1], cov3d[3], cov3d[4], 203 cov3d[2], cov3d[4], cov3d[5], 206 var t = view.view_from_world * vec4<f32>(position, 1.0); 208 let focal = vec2<f32>( 209 view.clip_from_view.x.x * view.viewport.z, 210 view.clip_from_view.y.y * view.viewport.w, 213 let s = 1.0 / (t.z * t.z); 215 focal.x / t.z, 0.0, -(focal.x * t.x) * s, 216 0.0, -focal.y / t.z, (focal.y * t.y) * s, 222 view.view_from_world.x.xyz, 223 view.view_from_world.y.xyz, 224 view.view_from_world.z.xyz, 230 var cov = transpose(T) * transpose(Vrk) * T; 234 return vec3<f32>(cov[0][0], cov[0][1], cov[1][1]); 239 direction: vec2<f32>, 244 let det = cov2d.x * cov2d.z - cov2d.y * cov2d.y; 245 let trace = cov2d.x + cov2d.z; 246 let mid = 0.5 * trace; 247 let discriminant = max(0.0, mid * mid - det); 249 let term = sqrt(discriminant); 251 let lambda1 = mid + term; 252 let lambda2 = max(mid - term, 0.0); 254 let x_axis_length = sqrt(lambda1); 255 let y_axis_length = sqrt(lambda2); 259 let radius_px = cutoff * max(x_axis_length, y_axis_length); 260 let radius_ndc = vec2<f32>( 261 radius_px / view.viewport.zw, 265 radius_ndc * direction, 266 radius_px * direction, 272 let a = (cov2d.x - cov2d.z) * (cov2d.x - cov2d.z); 273 let b = sqrt(a + 4.0 * cov2d.y * cov2d.y); 274 let major_radius = sqrt((cov2d.x + cov2d.z + b) * 0.5); 275 let minor_radius = sqrt((cov2d.x + cov2d.z - b) * 0.5); 277 let bounds = cutoff * vec2<f32>( 282 let eigvec1 = normalize(vec2<f32>( 286 let eigvec2 = vec2<f32>( 291 let rotation_matrix = transpose( 298 let scaled_vertex = direction * bounds; 299 let rotated_vertex = scaled_vertex * rotation_matrix; 301 let scaling_factor = 1.0 / view.viewport.zw; 302 let ndc_vertex = rotated_vertex * scaling_factor; 320fn inverted_infinity_norm(v: vec3<f32>) -> vec3<f32> { 321 let min_value = min(v.x, min(v.y, v.z)); 322 let min_vec = vec3<f32>(min_value); 334 @builtin(instance_index) instance_index: u32, 335 @builtin(vertex_index) vertex_index: u32, 336) -> GaussianVertexOutput { 337 var output: GaussianVertexOutput; 339 let entry = get_entry(instance_index); 340 let splat_index = entry.value; 342 var discard_quad = false; 344 discard_quad |= entry.key == 0xFFFFFFFFu; 346 let position = vec4<f32>(get_position(splat_index), 1.0); 348 let transformed_position = (gaussian_uniforms.transform * position).xyz; 349 let projected_position = world_to_clip(transformed_position); 351 discard_quad |= !in_frustum(projected_position.xyz); 354 discard_quad |= get_visibility(splat_index) < 0.5; 358 output.color = vec4<f32>(0.0, 0.0, 0.0, 0.0); 359 output.position = vec4<f32>(0.0, 0.0, 0.0, 0.0); 363 var quad_vertices = array<vec2<f32>, 4>( 364 vec2<f32>(-1.0, -1.0), 365 vec2<f32>(-1.0, 1.0), 366 vec2<f32>( 1.0, -1.0), 367 vec2<f32>( 1.0, 1.0), 370 let quad_index = vertex_index % 4u; 371 let quad_offset = quad_vertices[quad_index]; 373 let ray_direction = normalize(transformed_position - view.world_position); 375 var rgb = vec3<f32>(0.0); 377#ifdef RASTERIZE_DEPTH 379 let first_position = vec4<f32>(get_position(get_entry(1u).value), 1.0); 380 let last_position = vec4<f32>(get_position(get_entry(gaussian_uniforms.count - 1u).value), 1.0); 382 let min_position = (gaussian_uniforms.transform * first_position).xyz; 383 let max_position = (gaussian_uniforms.transform * last_position).xyz; 385 let camera_position = view.world_position; 387 let min_distance = length(min_position - camera_position); 388 let max_distance = length(max_position - camera_position); 390 let depth = length(transformed_position - camera_position); 396#else ifdef RASTERIZE_NORMAL 397 let R = get_rotation_matrix(get_rotation(splat_index)); 398 let S = get_scale_matrix(get_scale(splat_index)); 400 gaussian_uniforms.transform[0].xyz, 401 gaussian_uniforms.transform[1].xyz, 402 gaussian_uniforms.transform[2].xyz, 406 let local_normal = vec4<f32>(L.z, 0.0); 407 let world_normal = view.view_from_world * local_normal; 409 let t = normalize(world_normal); 417 rgb = get_color(splat_index, ray_direction); 420 let opacity = get_opacity(splat_index); 422#ifdef OPACITY_ADAPTIVE_RADIUS 423 let cutoff = sqrt(max(9.0 + 2.0 * log(opacity), 0.000001)); 429 output.color = vec4<f32>( 431 opacity * gaussian_uniforms.global_opacity, 434#ifdef HIGHLIGHT_SELECTED 435 if (get_visibility(splat_index) > 0.5) { 436 output.color = vec4<f32>(0.3, 1.0, 0.1, 1.0); 441 let cov2d = compute_cov2d_3dgs( 442 transformed_position, 445 let bb = get_bounding_box( 452 let det = cov2d.x * cov2d.z - cov2d.y * cov2d.y; 453 let det_inv = 1.0 / det; 454 let conic = vec3<f32>( 460 output.conic = conic; 461 output.major_minor = bb.zw; 464#else ifdef GAUSSIAN_SURFEL 465 let surfel = compute_cov2d_surfel( 466 transformed_position, 471 output.local_to_pixel_u = surfel.local_to_pixel.x; 472 output.local_to_pixel_v = surfel.local_to_pixel.y; 473 output.local_to_pixel_w = surfel.local_to_pixel.z; 474 output.mean_2d = surfel.mean_2d; 476 let bb = get_bounding_box_cov2d( 481 output.radius = bb.zw; 484 output.uv = quad_offset; 485 output.position = vec4<f32>( 486 projected_position.xy + bb.xy, 487 projected_position.zw, 494fn fs_main(input: GaussianVertexOutput) -> @location(0) vec4<f32> { 496#ifdef GAUSSIAN_SURFEL 497 let radius = input.radius; 498 let mean_2d = input.mean_2d; 499 let aspect = vec2<f32>( 501 view.viewport.z / view.viewport.w, 503 let pixel_coord = input.uv * radius * aspect + mean_2d; 506 let power = surfel_fragment_power( 508 input.local_to_pixel_u, 509 input.local_to_pixel_v, 510 input.local_to_pixel_w, 515#else ifdef GAUSSIAN_3D 516 let d = -input.major_minor; 517 let conic = input.conic; 518 let power = -0.5 * (conic.x * d.x * d.x + conic.z * d.y * d.y) + conic.y * d.x * d.y; 527 let sigma = 1.0 / 3.0; 528 let sigma_squared = 2.0 * sigma * sigma; 529 let distance_squared = dot(input.uv, input.uv); 531 let power = -distance_squared / sigma_squared; 533 if (distance_squared > 3.0 * 3.0) { 538#ifdef VISUALIZE_BOUNDING_BOX 539 let uv = input.uv * 0.5 + 0.5; 540 let edge_width = 0.08; 542 (uv.x < edge_width || uv.x > 1.0 - edge_width) || 543 (uv.y < edge_width || uv.y > 1.0 - edge_width) 545 return vec4<f32>(0.3, 1.0, 0.1, 1.0); 549 let alpha = min(exp(power) * input.color.a, 0.999); 554 input.color.rgb * alpha,