Search code examples
rustwgpu-rs

wgpu doesn't render with alpha channels


I am trying to render a semi-transparent png-image with wgpu. I have an issue where some of the pixels that shouldn't be showing are showing. For example in the left of my image there is a gray (128, 128, 128) block, which has alpha value of 0, which means that it should be invisible, correct? I have set texture format to Rgba8UnormSrgb:

let texture = device.create_texture(
    &wgpu::TextureDescriptor {
        label,
        size,
        mip_level_count: 1,
        sample_count: 1,
        dimension: wgpu::TextureDimension::D2,
        format: wgpu::TextureFormat::Rgba8UnormSrgb,
        usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST | wgpu::TextureUsages::COPY_SRC | wgpu::TextureUsages::RENDER_ATTACHMENT,
    }
);

Here is the png image and the jpg equivalent, which is what wgpu is rendering.

https://user-images.githubusercontent.com/99501993/169669616-f3386235-73d3-45b8-9415-003c480f686f.png
https://user-images.githubusercontent.com/99501993/169669627-cdabd091-6886-43cd-b6f5-2c110d7b44d1.png


Solution

  • Changing the blend mode of the fragment shader fixed this for me.

    According to the docs there are 3 blend states implemented:

    1. Replace
    2. ALPHA_BLENDING
    3. PREMULTIPLIED_ALPHA_BLENDING

    Here's an example:

    fragment: Some(wgpu::FragmentState {
            module: &draw_signal_shader,
            entry_point: "fs_main",
            targets: &[
                wgpu::ColorTargetState{
                    format: surface.get_preferred_format(&adapter).unwrap().into(),
    
                    blend: Some(wgpu::BlendState{
                        color: wgpu::BlendComponent{
                            src_factor: wgpu::BlendFactor::SrcAlpha,
                            dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
                            operation: wgpu::BlendOperation::Add,},
                        alpha: wgpu::BlendComponent::OVER
                    }),
    
                    write_mask: wgpu::ColorWrites::ALL,
                }
            ],
        }),