Configurable clear color (#236)

- Closes #235
- Now using alpha blending (non-premultiplied) in the scaling renderer
  so that the clear color can be blended with the texture. This can be
  made configurable, but we'll go with this for now.
This commit is contained in:
Jay Oster 2021-12-05 14:23:06 -08:00 committed by GitHub
parent b15854b4d1
commit 4c6682e65b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 60 additions and 5 deletions

View file

@ -15,6 +15,7 @@ pub struct PixelsBuilder<'req, 'dev, 'win, W: HasRawWindowHandle> {
surface_texture: SurfaceTexture<'win, W>,
texture_format: wgpu::TextureFormat,
render_texture_format: Option<wgpu::TextureFormat>,
clear_color: wgpu::Color,
}
impl<'req, 'dev, 'win, W: HasRawWindowHandle> PixelsBuilder<'req, 'dev, 'win, W> {
@ -67,6 +68,7 @@ impl<'req, 'dev, 'win, W: HasRawWindowHandle> PixelsBuilder<'req, 'dev, 'win, W>
surface_texture,
texture_format: wgpu::TextureFormat::Rgba8UnormSrgb,
render_texture_format: None,
clear_color: wgpu::Color::BLACK,
}
}
@ -176,6 +178,33 @@ impl<'req, 'dev, 'win, W: HasRawWindowHandle> PixelsBuilder<'req, 'dev, 'win, W>
self
}
/// Set the default clear color.
///
/// Allows customization of the background color and the border drawn for non-integer scale
/// values.
///
/// ```no_run
/// use pixels::wgpu::Color;
///
/// # use pixels::PixelsBuilder;
/// # let window = pixels_mocks::Rwh;
/// # let surface_texture = pixels::SurfaceTexture::new(320, 240, &window);
/// // Set clear color to bright magenta.
/// let mut pixels = PixelsBuilder::new(320, 240, surface_texture)
/// .clear_color(Color {
/// r: 1.0,
/// g: 0.0,
/// b: 1.0,
/// a: 1.0,
/// })
/// .build()?;
/// # Ok::<(), pixels::Error>(())
/// ```
pub fn clear_color(mut self, color: wgpu::Color) -> Self {
self.clear_color = color;
self
}
/// Create a pixel buffer from the options builder.
///
/// This is the private implementation shared by [`PixelsBuilder::build`] and
@ -235,6 +264,7 @@ impl<'req, 'dev, 'win, W: HasRawWindowHandle> PixelsBuilder<'req, 'dev, 'win, W>
// Create the backing texture
let surface_size = self.surface_texture.size;
let clear_color = self.clear_color;
let (scaling_matrix_inverse, texture_extent, texture, scaling_renderer, pixels_buffer_size) =
create_backing_texture(
&device,
@ -245,6 +275,7 @@ impl<'req, 'dev, 'win, W: HasRawWindowHandle> PixelsBuilder<'req, 'dev, 'win, W>
// Render texture values
&surface_size,
render_texture_format,
clear_color,
);
// Create the pixel buffer
@ -323,6 +354,7 @@ pub(crate) fn create_backing_texture(
backing_texture_format: wgpu::TextureFormat,
surface_size: &SurfaceSize,
render_texture_format: wgpu::TextureFormat,
clear_color: wgpu::Color,
) -> (
ultraviolet::Mat4,
wgpu::Extent3d,
@ -360,6 +392,7 @@ pub(crate) fn create_backing_texture(
&texture_extent,
surface_size,
render_texture_format,
clear_color,
);
let texture_format_size = get_texture_format_size(backing_texture_format);

View file

@ -232,6 +232,27 @@ impl Pixels {
.await
}
/// Change the clear color.
///
/// Allows customization of the background color and the border drawn for non-integer scale
/// values.
///
/// ```no_run
/// use pixels::wgpu::Color;
///
/// # use pixels::Pixels;
/// # let window = pixels_mocks::Rwh;
/// # let surface_texture = pixels::SurfaceTexture::new(320, 240, &window);
/// let mut pixels = Pixels::new(320, 240, surface_texture)?;
///
/// // Set clear color to red.
/// pixels.set_clear_color(Color::RED);
/// # Ok::<(), pixels::Error>(())
/// ```
pub fn set_clear_color(&mut self, color: wgpu::Color) {
self.context.scaling_renderer.clear_color = color;
}
/// Resize the pixel buffer and zero its contents.
///
/// This does not resize the surface upon which the pixel buffer texture is rendered. Use
@ -262,6 +283,7 @@ impl Pixels {
// Render texture values
&self.surface_size,
self.render_texture_format,
self.context.scaling_renderer.clear_color,
);
self.scaling_matrix_inverse = scaling_matrix_inverse;

View file

@ -9,6 +9,7 @@ pub struct ScalingRenderer {
uniform_buffer: wgpu::Buffer,
bind_group: wgpu::BindGroup,
render_pipeline: wgpu::RenderPipeline,
pub(crate) clear_color: wgpu::Color,
width: f32,
height: f32,
clip_rect: (u32, u32, u32, u32),
@ -21,6 +22,7 @@ impl ScalingRenderer {
texture_size: &wgpu::Extent3d,
surface_size: &SurfaceSize,
render_texture_format: wgpu::TextureFormat,
clear_color: wgpu::Color,
) -> Self {
let shader = wgpu::include_wgsl!("../shaders/scale.wgsl");
let module = device.create_shader_module(&shader);
@ -153,10 +155,7 @@ impl ScalingRenderer {
entry_point: "fs_main",
targets: &[wgpu::ColorTargetState {
format: render_texture_format,
blend: Some(wgpu::BlendState {
color: wgpu::BlendComponent::REPLACE,
alpha: wgpu::BlendComponent::REPLACE,
}),
blend: Some(wgpu::BlendState::ALPHA_BLENDING),
write_mask: wgpu::ColorWrites::ALL,
}],
}),
@ -170,6 +169,7 @@ impl ScalingRenderer {
uniform_buffer,
bind_group,
render_pipeline,
clear_color,
width: texture_size.width as f32,
height: texture_size.height as f32,
clip_rect,
@ -184,7 +184,7 @@ impl ScalingRenderer {
view: render_target,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color::BLACK),
load: wgpu::LoadOp::Clear(self.clear_color),
store: true,
},
}],