Skip to main content

BlendMode

Enum BlendMode 

Source
pub enum BlendMode {
    Replace,
    Alpha,
    PremultipliedAlpha,
    Additive,
    Multiply,
    Custom(BlendState),
}
Expand description

Predefined blend modes for common use cases.

Use these to configure how source and destination colors are combined during rendering.

Variants§

§

Replace

No blending - source completely replaces destination.

§

Alpha

Standard alpha blending for transparent content.

Formula: src.rgb * src.a + dst.rgb * (1 - src.a)

Use for: Transparent UI over game content, sprites with transparency.

§

PremultipliedAlpha

Premultiplied alpha blending.

Formula: src.rgb + dst.rgb * (1 - src.a)

Use for: Blitting framebuffers with premultiplied alpha, compositing.

§

Additive

Additive blending - colors are added together.

Formula: src.rgb + dst.rgb

Use for: Glow effects, particles, light sources.

§

Multiply

Multiplicative blending.

Formula: src.rgb * dst.rgb

Use for: Shadows, color tinting.

§

Custom(BlendState)

Custom blend state for advanced use cases.

Implementations§

Source§

impl BlendMode

Source

pub fn to_blend_state(self) -> Option<BlendState>

Convert to wgpu BlendState.

Source

pub fn to_color_target_state(self, format: TextureFormat) -> ColorTargetState

Create a color target state with this blend mode.

Examples found in repository?
examples/renderer_api.rs (line 142)
37fn main() {
38    logging::init();
39
40    run_app(|ctx| {
41        let graphics_ctx =
42            GraphicsContext::new_owned_sync().expect("Failed to create graphics context");
43        let renderer = Renderer::new(graphics_ctx.clone());
44
45        let window = ctx
46            .create_window(WindowDescriptor {
47                title: "Renderer API Example".to_string(),
48                size: Some(WinitPhysicalSize::new(800.0, 600.0)),
49                ..Default::default()
50            })
51            .expect("Failed to create window");
52
53        let window = RenderWindowBuilder::new()
54            .color_format(wgpu::TextureFormat::Bgra8UnormSrgb)
55            .with_depth_default()
56            .build(window, graphics_ctx.clone())
57            .expect("Failed to create render window");
58
59        let window_id = window.id();
60
61        // Create shader using Renderer API
62        let shader = renderer.create_shader(Some("Color Shader"), SHADER_SOURCE);
63
64        // Create texture using Renderer helper
65        let texture_data = create_gradient_texture();
66        let texture = renderer.create_texture_2d(
67            Some("Gradient Texture"),
68            256,
69            256,
70            wgpu::TextureFormat::Rgba8UnormSrgb,
71            wgpu::TextureUsages::TEXTURE_BINDING,
72            &texture_data,
73        );
74
75        let texture_view = texture.create_view(&wgpu::TextureViewDescriptor::default());
76        let sampler = renderer.create_linear_sampler(Some("Linear Sampler"));
77
78        // Create bind group using Renderer API
79        let bind_group_layout = renderer.create_bind_group_layout(
80            Some("Texture Bind Group Layout"),
81            &[
82                wgpu::BindGroupLayoutEntry {
83                    binding: 0,
84                    visibility: wgpu::ShaderStages::FRAGMENT,
85                    ty: wgpu::BindingType::Texture {
86                        multisampled: false,
87                        view_dimension: wgpu::TextureViewDimension::D2,
88                        sample_type: wgpu::TextureSampleType::Float { filterable: true },
89                    },
90                    count: None,
91                },
92                wgpu::BindGroupLayoutEntry {
93                    binding: 1,
94                    visibility: wgpu::ShaderStages::FRAGMENT,
95                    ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
96                    count: None,
97                },
98            ],
99        );
100
101        let bind_group = renderer.create_bind_group(
102            Some("Texture Bind Group"),
103            &bind_group_layout,
104            &[
105                wgpu::BindGroupEntry {
106                    binding: 0,
107                    resource: wgpu::BindingResource::TextureView(&texture_view),
108                },
109                wgpu::BindGroupEntry {
110                    binding: 1,
111                    resource: wgpu::BindingResource::Sampler(&sampler),
112                },
113            ],
114        );
115
116        let pipeline_layout = renderer.create_pipeline_layout(
117            Some("Render Pipeline Layout"),
118            &[&bind_group_layout],
119            &[],
120        );
121
122        // Create pipeline using Renderer API with BlendMode
123        let pipeline = renderer.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
124            label: Some("Render Pipeline"),
125            layout: Some(&pipeline_layout),
126            vertex: wgpu::VertexState {
127                module: &shader,
128                entry_point: Some("vs_main"),
129                buffers: &[wgpu::VertexBufferLayout {
130                    // 4 floats × 4 bytes = 16 bytes per vertex (2×f32 pos + 2×f32 UV)
131                    array_stride: 4 * 4,
132                    step_mode: wgpu::VertexStepMode::Vertex,
133                    attributes: &wgpu::vertex_attr_array![0 => Float32x2, 1 => Float32x2],
134                }],
135                compilation_options: wgpu::PipelineCompilationOptions::default(),
136            },
137            fragment: Some(wgpu::FragmentState {
138                module: &shader,
139                entry_point: Some("fs_main"),
140                // Use BlendMode for transparent rendering
141                targets: &[Some(
142                    BlendMode::Alpha.to_color_target_state(wgpu::TextureFormat::Rgba8UnormSrgb),
143                )],
144                compilation_options: wgpu::PipelineCompilationOptions::default(),
145            }),
146            primitive: wgpu::PrimitiveState {
147                topology: wgpu::PrimitiveTopology::TriangleList,
148                strip_index_format: None,
149                front_face: wgpu::FrontFace::Ccw,
150                cull_mode: Some(wgpu::Face::Back),
151                polygon_mode: wgpu::PolygonMode::Fill,
152                unclipped_depth: false,
153                conservative: false,
154            },
155            depth_stencil: None,
156            multisample: wgpu::MultisampleState {
157                count: 1,
158                mask: !0,
159                alpha_to_coverage_enabled: false,
160            },
161            multiview: None,
162            cache: None,
163        });
164
165        #[rustfmt::skip]
166        let vertices: &[f32] = &[
167            -0.8, -0.8,  0.0, 1.0,
168             0.8, -0.8,  1.0, 1.0,
169             0.8,  0.8,  1.0, 0.0,
170            -0.8, -0.8,  0.0, 1.0,
171             0.8,  0.8,  1.0, 0.0,
172            -0.8,  0.8,  0.0, 0.0,
173        ];
174
175        // Create vertex buffer using Renderer helper
176        let vertex_buffer = renderer.create_vertex_buffer(Some("Vertex Buffer"), vertices);
177
178        // Create offscreen framebuffer using the new Framebuffer abstraction
179        let offscreen_fb = Framebuffer::builder(400, 300)
180            .format(wgpu::TextureFormat::Rgba8UnormSrgb)
181            .label("Offscreen FB")
182            .build(&graphics_ctx);
183
184        // Create blit shader and pipeline for rendering framebuffer to surface
185        let blit_shader = renderer.create_shader(Some("Blit Shader"), BLIT_SHADER_SOURCE);
186
187        let blit_bind_group_layout = renderer.create_bind_group_layout(
188            Some("Blit Bind Group Layout"),
189            &[
190                wgpu::BindGroupLayoutEntry {
191                    binding: 0,
192                    visibility: wgpu::ShaderStages::FRAGMENT,
193                    ty: wgpu::BindingType::Texture {
194                        multisampled: false,
195                        view_dimension: wgpu::TextureViewDimension::D2,
196                        sample_type: wgpu::TextureSampleType::Float { filterable: true },
197                    },
198                    count: None,
199                },
200                wgpu::BindGroupLayoutEntry {
201                    binding: 1,
202                    visibility: wgpu::ShaderStages::FRAGMENT,
203                    ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
204                    count: None,
205                },
206            ],
207        );
208
209        let blit_bind_group = renderer.create_bind_group(
210            Some("Blit Bind Group"),
211            &blit_bind_group_layout,
212            &[
213                wgpu::BindGroupEntry {
214                    binding: 0,
215                    resource: wgpu::BindingResource::TextureView(offscreen_fb.color_view()),
216                },
217                wgpu::BindGroupEntry {
218                    binding: 1,
219                    resource: wgpu::BindingResource::Sampler(&sampler),
220                },
221            ],
222        );
223
224        let blit_pipeline_layout = renderer.create_pipeline_layout(
225            Some("Blit Pipeline Layout"),
226            &[&blit_bind_group_layout],
227            &[],
228        );
229
230        let blit_pipeline = renderer.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
231            label: Some("Blit Pipeline"),
232            layout: Some(&blit_pipeline_layout),
233            vertex: wgpu::VertexState {
234                module: &blit_shader,
235                entry_point: Some("vs_main"),
236                buffers: &[],
237                compilation_options: wgpu::PipelineCompilationOptions::default(),
238            },
239            fragment: Some(wgpu::FragmentState {
240                module: &blit_shader,
241                entry_point: Some("fs_main"),
242                // Use PremultipliedAlpha for framebuffer blitting
243                targets: &[Some(
244                    BlendMode::PremultipliedAlpha
245                        .to_color_target_state(wgpu::TextureFormat::Bgra8UnormSrgb),
246                )],
247                compilation_options: wgpu::PipelineCompilationOptions::default(),
248            }),
249            primitive: wgpu::PrimitiveState {
250                topology: wgpu::PrimitiveTopology::TriangleList,
251                ..Default::default()
252            },
253            depth_stencil: None,
254            multisample: wgpu::MultisampleState::default(),
255            multiview: None,
256            cache: None,
257        });
258
259        tracing::info!("Renderer initialized successfully");
260        tracing::info!("Device: {:?}", renderer.context().info());
261
262        Box::new(RendererApp {
263            _context: graphics_ctx,
264            _renderer: renderer,
265            window,
266            window_id,
267            pipeline,
268            bind_group,
269            vertex_buffer,
270            offscreen_fb,
271            blit_pipeline,
272            blit_bind_group,
273            time: 0.0,
274        })
275    });
276}

Trait Implementations§

Source§

impl Clone for BlendMode

Source§

fn clone(&self) -> BlendMode

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for BlendMode

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for BlendMode

Source§

fn default() -> BlendMode

Returns the “default value” for a type. Read more
Source§

impl From<BlendMode> for Option<BlendState>

Source§

fn from(mode: BlendMode) -> Self

Converts to this type from the input type.
Source§

impl From<BlendState> for BlendMode

Source§

fn from(state: BlendState) -> Self

Converts to this type from the input type.
Source§

impl Hash for BlendMode

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl PartialEq for BlendMode

Source§

fn eq(&self, other: &BlendMode) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Copy for BlendMode

Source§

impl Eq for BlendMode

Source§

impl StructuralPartialEq for BlendMode

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> Downcast<T> for T

Source§

fn downcast(&self) -> &T

Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> Upcast<T> for T

Source§

fn upcast(&self) -> Option<&T>

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> WasmNotSend for T
where T: Send,

Source§

impl<T> WasmNotSendSync for T

Source§

impl<T> WasmNotSync for T
where T: Sync,