#Batch drawing 2D circles while having different opacity for some

1 messages · Page 1 of 1 (latest)

dusty karma
#

Hi,
my game is 2D and has a bunch of circles of the same color and mesh, so I have done something similar to this (But in 2D).

However, my use case requires the alteration of the opacity of individual dots based on a distance to the player. As stated, I have many circles and wish to do a batched draw call for all the circles instead of individual ones, since they all share the same mesh and the same material, except the alpha.

I would like to use an automated method if possible, and I'd be open to trying a custom shader, but I have no experience with them in bevy / wgsl.

GitHub

A refreshingly simple data-driven game engine built in Rust - bevyengine/bevy

dark crescent
#

So, each circle is a dot, yes?

If as you say, you want to keep the same material for all the dots then a custom shader is what you want. In the material and shader, you'll add a position for your player, then in the shader you calculate the distance and then your alpha. You'll have to update the material each frame to update the player position.

dusty karma
#

Out of curiosity, how many of those dots doc you think I should have to implement this and not count as premature optimization?

scarlet cypress
dusty karma
#

I've tried that method and I failed to get the shader to compile. Here is what I have:

#import bevy_pbr::forward_io::VertexOutput

@group(0) @binding(0) var<uniform> player_position: vec2<f32>;
@group(0) @binding(1) var<uniform> fade_distance: f32;
@group(0) @binding(2) var<uniform> min_opacity: f32;
@group(0) @binding(3) var<uniform> base_color: vec4<f32>;

@fragment
fn fs(input: VertexOutput) -> @location(0) vec4<f32> {
    let dist = distance(input.world_position, player_position);
    let alpha = max(min_opacity, 1.0 - (dist / fade_distance));
    return vec4(base_color.rgb, alpha * base_color.a);
}

When running, the shader doesn't compile and says that:

 2025-01-31T15:03:02.080804Z ERROR bevy_render::render_resource::pipeline_cache: failed to process shader:
 error: failed to build a valid final module: Entry point fs at Fragment is invalid
    ┌─ shaders/particle_shader.wgsl:10:16
    │
 10 │     let dist = distance(input.world_position, player_position);
    │                ^^^^^^^^ naga::Expression [4]
    │
    = Expression [4] is invalid
    = Argument [1] to Distance as expression [3] has an invalid type.
dusty karma
#

ok I've solved it

#

input.world_position should be changed to input.world_position.xy, because my player position is 2d

#

also I had to change the alpha mode to blend or it wouldn't accually do anything