1#import bevy_gaussian_splatting::bindings::{ 6#import bevy_gaussian_splatting::classification::class_to_rgb 7#import bevy_gaussian_splatting::depth::depth_to_rgb 8#import bevy_gaussian_splatting::optical_flow::{ 9 calculate_motion_vector, 12#import bevy_gaussian_splatting::helpers::{ 16#import bevy_gaussian_splatting::transform::{ 22 #import bevy_gaussian_splatting::gaussian_2d::{ 24 get_bounding_box_cov2d, 25 surfel_fragment_power, 27#else ifdef GAUSSIAN_3D 28 #import bevy_gaussian_splatting::gaussian_3d::{ 31 #import bevy_gaussian_splatting::helpers::{ 32 get_bounding_box_clip, 34#else ifdef GAUSSIAN_4D 35 #import bevy_gaussian_splatting::gaussian_4d::{ 38 #import bevy_gaussian_splatting::helpers::{ 40 get_bounding_box_clip, 45 #ifdef PRECOMPUTE_COVARIANCE_3D 46 #import bevy_gaussian_splatting::packed::{ 54 #import bevy_gaussian_splatting::packed::{ 63#else ifdef BUFFER_STORAGE 64 #ifdef PRECOMPUTE_COVARIANCE_3D 65 #import bevy_gaussian_splatting::planar::{ 73 #import bevy_gaussian_splatting::planar::{ 82#else ifdef BUFFER_TEXTURE 83 #ifdef PRECOMPUTE_COVARIANCE_3D 84 #import bevy_gaussian_splatting::texture::{ 93 #import bevy_gaussian_splatting::texture::{ 106 @group(3) @binding(0) var<storage, read> sorted_entries: array<Entry>; 107 fn get_entry(index: u32) -> Entry { 108 return sorted_entries[index]; 110#else ifdef BUFFER_TEXTURE 111 @group(3) @binding(0) var sorted_entries: texture_2d<u32>; 112 fn get_entry(index: u32) -> Entry { 113 let sample = textureLoad( 127 struct GaussianVertexOutput { 128 @builtin(position) position: vec4<f32>, 129 @location(0) color: vec4<f32>, 130 @location(1) uv: vec2<f32>, 132 @location(2) local_to_pixel_u: vec3<f32>, 133 @location(3) local_to_pixel_v: vec3<f32>, 134 @location(4) local_to_pixel_w: vec3<f32>, 135 @location(5) mean_2d: vec2<f32>, 136 @location(6) radius: vec2<f32>, 137 #else #ifdef GAUSSIAN_3D 138 @location(2) conic: vec3<f32>, 139 @location(3) major_minor: vec2<f32>, 140 #else #ifdef GAUSSIAN_4D 141 @location(2) conic: vec3<f32>, 142 @location(3) major_minor: vec2<f32>, 146 struct GaussianVertexOutput { 147 @builtin(position) position: vec4<f32>, 148 @location(0) @interpolate(flat) color: vec4<f32>, 149 @location(1) @interpolate(linear) uv: vec2<f32>, 151 @location(2) @interpolate(flat) local_to_pixel_u: vec3<f32>, 152 @location(3) @interpolate(flat) local_to_pixel_v: vec3<f32>, 153 @location(4) @interpolate(flat) local_to_pixel_w: vec3<f32>, 154 @location(5) @interpolate(flat) mean_2d: vec2<f32>, 155 @location(6) @interpolate(flat) radius: vec2<f32>, 156 #else ifdef GAUSSIAN_3D 157 @location(2) @interpolate(flat) conic: vec3<f32>, 158 @location(3) @interpolate(linear) major_minor: vec2<f32>, 159 #else ifdef GAUSSIAN_4D 160 @location(2) @interpolate(flat) conic: vec3<f32>, 161 @location(3) @interpolate(linear) major_minor: vec2<f32>, 166fn world_to_local_direction(ray_direction_world: vec3<f32>, transform: mat4x4<f32>) -> vec3<f32> { 167 let basis = mat3x3<f32>( 172 let basis_x = normalize(basis[0]); 173 let basis_y = normalize(basis[1]); 174 let basis_z = normalize(basis[2]); 176 let local = vec3<f32>( 177 dot(basis_x, ray_direction_world), 178 dot(basis_y, ray_direction_world), 179 dot(basis_z, ray_direction_world), 182 return normalize(local); 186 @builtin(instance_index) instance_index: u32, 187 @builtin(vertex_index) vertex_index: u32, 188) -> GaussianVertexOutput { 189 var output: GaussianVertexOutput; 191 let entry = get_entry(instance_index); 192 let splat_index = entry.value; 194 var discard_quad = false; 196 discard_quad |= entry.key == 0xFFFFFFFFu; 198 let position = vec4<f32>(get_position(splat_index), 1.0); 200 var transformed_position = (gaussian_uniforms.transform * position).xyz; 201 var previous_transformed_position = transformed_position; 204 discard_quad |= get_visibility(splat_index) < 0.5; 209 let projected_position = world_to_clip(transformed_position); 210 discard_quad |= !in_frustum(projected_position.xyz); 214 output.color = vec4<f32>(0.0, 0.0, 0.0, 0.0); 215 output.position = vec4<f32>(0.0, 0.0, 0.0, 0.0); 219 var quad_vertices = array<vec2<f32>, 4>( 220 vec2<f32>(-1.0, -1.0), 221 vec2<f32>(-1.0, 1.0), 222 vec2<f32>( 1.0, -1.0), 223 vec2<f32>( 1.0, 1.0), 226 let quad_index = vertex_index % 4u; 227 let quad_offset = quad_vertices[quad_index]; 229 var opacity = get_opacity(splat_index); 231#ifdef OPACITY_ADAPTIVE_RADIUS 232 let cutoff = sqrt(max(9.0 + 2.0 * log(opacity), 0.000001)); 238 let surfel = compute_cov2d_surfel( 239 transformed_position, 244 output.local_to_pixel_u = surfel.local_to_pixel[0]; 245 output.local_to_pixel_v = surfel.local_to_pixel[1]; 246 output.local_to_pixel_w = surfel.local_to_pixel[2]; 247 output.mean_2d = surfel.mean_2d; 249 let bb = get_bounding_box_cov2d( 254 output.radius = bb.zw; 257 let gaussian_cov2d = compute_cov2d_3dgs( 258 transformed_position, 261 #else ifdef GAUSSIAN_4D 262 let gaussian_4d = conditional_cov3d( 263 transformed_position, 265 gaussian_uniforms.time, 268 if !gaussian_4d.mask { 269 output.color = vec4<f32>(0.0, 0.0, 0.0, 0.0); 270 output.position = vec4<f32>(0.0, 0.0, 0.0, 0.0); 274 let position_t = vec4<f32>(position.xyz + gaussian_4d.delta_mean, 1.0); 275 transformed_position = (gaussian_uniforms.transform * position_t).xyz; 277 let projected_position = world_to_clip(transformed_position); 279 if !in_frustum(projected_position.xyz) { 280 output.color = vec4<f32>(0.0, 0.0, 0.0, 0.0); 281 output.position = vec4<f32>(0.0, 0.0, 0.0, 0.0); 285 opacity = opacity * gaussian_4d.opacity_modifier; 287 let gaussian_cov2d = cov2d( 288 transformed_position, 293 let bb = get_bounding_box_clip( 300 let det = gaussian_cov2d.x * gaussian_cov2d.z - gaussian_cov2d.y * gaussian_cov2d.y; 301 let det_inv = 1.0 / det; 302 let conic = vec3<f32>( 303 gaussian_cov2d.z * det_inv, 304 -gaussian_cov2d.y * det_inv, 305 gaussian_cov2d.x * det_inv 307 output.conic = conic; 308 output.major_minor = bb.zw; 312 var rgb = vec3<f32>(0.0); 315#ifdef RASTERIZE_CLASSIFICATION 316 let ray_direction_world = normalize(transformed_position - view.world_position); 317 let ray_direction_local = world_to_local_direction(ray_direction_world, gaussian_uniforms.transform); 319 #ifdef GAUSSIAN_3D_STRUCTURE 320 rgb = get_color(splat_index, ray_direction_local); 321 #else ifdef GAUSSIAN_4D 322 rgb = get_color(splat_index, gaussian_4d.dir_t, ray_direction_local); 326 get_visibility(splat_index), 329#else ifdef RASTERIZE_DEPTH 331 let first_position = vec4<f32>(get_position(get_entry(1u).value), 1.0); 332 let last_position = vec4<f32>(get_position(get_entry(gaussian_uniforms.count - 1u).value), 1.0); 334 let min_position = (gaussian_uniforms.transform * first_position).xyz; 335 let max_position = (gaussian_uniforms.transform * last_position).xyz; 337 let camera_position = view.world_position; 339 let min_distance = length(min_position - camera_position); 340 let max_distance = length(max_position - camera_position); 342 let depth = length(transformed_position - camera_position); 348#else ifdef RASTERIZE_NORMAL 350 let R = get_rotation_matrix(get_rotation(splat_index)); 351 let S = get_scale_matrix(get_scale(splat_index)); 353 gaussian_uniforms.transform[0].xyz, 354 gaussian_uniforms.transform[1].xyz, 355 gaussian_uniforms.transform[2].xyz, 359 let local_normal = vec4<f32>(L[2], 0.0); 360 let world_normal = view.view_from_world * local_normal; 362 let t = normalize(world_normal); 369#else ifdef RASTERIZE_OPTICAL_FLOW 370 let motion_vector = calculate_motion_vector( 371 transformed_position, 372 previous_transformed_position, 375 rgb = optical_flow_to_rgb(motion_vector); 376#else ifdef RASTERIZE_POSITION 377 rgb = (transformed_position - gaussian_uniforms.min.xyz) / (gaussian_uniforms.max.xyz - gaussian_uniforms.min.xyz); 378#else ifdef RASTERIZE_VELOCITY 379 let time_delta = 1e-3; 380 let future_gaussian_4d = conditional_cov3d( 381 transformed_position, 383 gaussian_uniforms.time + time_delta, 385 let position_delta = future_gaussian_4d.delta_mean - gaussian_4d.delta_mean; 386 let velocity = position_delta / time_delta; 387 let velocity_magnitude = length(velocity); 388 let velocity_normalized = normalize(velocity); 391 let min_magnitude = 1.0; 392 let max_magnitude = 2.0; 394 let scaled_mag = clamp( 395 (velocity_magnitude - min_magnitude) / (max_magnitude - min_magnitude), 400 if scaled_mag < 1e-2 { 404 let base_color = 0.5 * (velocity_normalized + vec3<f32>(1.0, 1.0, 1.0)); 405 rgb = base_color * scaled_mag; 406#else ifdef RASTERIZE_COLOR 408 let ray_direction_world = normalize(transformed_position - view.world_position); 409 let ray_direction_local = world_to_local_direction(ray_direction_world, gaussian_uniforms.transform); 411 #ifdef GAUSSIAN_3D_STRUCTURE 412 rgb = get_color(splat_index, ray_direction_local); 413 #else ifdef GAUSSIAN_4D 414 rgb = get_color(splat_index, gaussian_4d.dir_t, ray_direction_local); 418 output.color = vec4<f32>( 420 opacity * gaussian_uniforms.global_opacity, 423#ifdef HIGHLIGHT_SELECTED 424 if (get_visibility(splat_index) > 0.5) { 425 output.color = vec4<f32>(0.3, 1.0, 0.1, 1.0); 429 output.uv = quad_offset; 430 output.position = vec4<f32>( 431 projected_position.xy + bb.xy, 432 projected_position.zw, 439fn fs_main(input: GaussianVertexOutput) -> @location(0) vec4<f32> { 442 let radius = input.radius; 443 let mean_2d = input.mean_2d; 444 let aspect = vec2<f32>( 446 view.viewport.z / view.viewport.w, 448 let pixel_coord = input.uv * radius * aspect + mean_2d; 450 let power = surfel_fragment_power( 452 input.local_to_pixel_u, 453 input.local_to_pixel_v, 454 input.local_to_pixel_w, 459#else ifdef GAUSSIAN_3D 460 let d = -input.major_minor; 461 let conic = input.conic; 462 let power = -0.5 * (conic.x * d.x * d.x + conic.z * d.y * d.y) + conic.y * d.x * d.y; 463#else ifdef GAUSSIAN_4D 464 let d = -input.major_minor; 465 let conic = input.conic; 466 let power = -0.5 * (conic.x * d.x * d.x + conic.z * d.y * d.y) + conic.y * d.x * d.y; 475 let sigma = 1.0 / 3.0; 476 let sigma_squared = 2.0 * sigma * sigma; 477 let distance_squared = dot(input.uv, input.uv); 479 let power = -distance_squared / sigma_squared; 481 if (distance_squared > 3.0 * 3.0) { 486#ifdef VISUALIZE_BOUNDING_BOX 487 let uv = input.uv * 0.5 + 0.5; 488 let edge_width = 0.08; 490 (uv.x < edge_width || uv.x > 1.0 - edge_width) || 491 (uv.y < edge_width || uv.y > 1.0 - edge_width) 493 return vec4<f32>(0.3, 1.0, 0.1, 1.0); 497 let alpha = min(exp(power) * input.color.a, 0.999); 502 input.color.rgb * alpha,