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

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,