Provide actual bounds to Shader primitives

... and allow for proper translation and scissoring.
This commit is contained in:
Héctor Ramón Jiménez 2023-11-28 23:13:38 +01:00
parent 100d15f306
commit ab7dae554c
No known key found for this signature in database
GPG key ID: 7CC46565708259A7
8 changed files with 54 additions and 40 deletions

View file

@ -5,9 +5,7 @@ use scene::Scene;
use iced::executor; use iced::executor;
use iced::time::Instant; use iced::time::Instant;
use iced::widget::shader::wgpu; use iced::widget::shader::wgpu;
use iced::widget::{ use iced::widget::{checkbox, column, container, row, shader, slider, text};
checkbox, column, container, row, shader, slider, text, vertical_space,
};
use iced::window; use iced::window;
use iced::{ use iced::{
Alignment, Application, Color, Command, Element, Length, Renderer, Alignment, Application, Color, Command, Element, Length, Renderer,
@ -138,21 +136,18 @@ impl Application for IcedCubes {
let controls = column![top_controls, bottom_controls,] let controls = column![top_controls, bottom_controls,]
.spacing(10) .spacing(10)
.padding(20)
.align_items(Alignment::Center); .align_items(Alignment::Center);
let shader = let shader =
shader(&self.scene).width(Length::Fill).height(Length::Fill); shader(&self.scene).width(Length::Fill).height(Length::Fill);
container( container(column![shader, controls].align_items(Alignment::Center))
column![shader, controls, vertical_space(20),] .width(Length::Fill)
.spacing(40) .height(Length::Fill)
.align_items(Alignment::Center), .center_x()
) .center_y()
.width(Length::Fill) .into()
.height(Length::Fill)
.center_x()
.center_y()
.into()
} }
fn subscription(&self) -> Subscription<Self::Message> { fn subscription(&self) -> Subscription<Self::Message> {

View file

@ -133,9 +133,9 @@ impl shader::Primitive for Primitive {
format: wgpu::TextureFormat, format: wgpu::TextureFormat,
device: &wgpu::Device, device: &wgpu::Device,
queue: &wgpu::Queue, queue: &wgpu::Queue,
_bounds: Rectangle,
target_size: Size<u32>, target_size: Size<u32>,
_scale_factor: f32, _scale_factor: f32,
_transform: shader::Transformation,
storage: &mut shader::Storage, storage: &mut shader::Storage,
) { ) {
if !storage.has::<Pipeline>() { if !storage.has::<Pipeline>() {
@ -158,9 +158,9 @@ impl shader::Primitive for Primitive {
fn render( fn render(
&self, &self,
storage: &shader::Storage, storage: &shader::Storage,
bounds: Rectangle<u32>,
target: &wgpu::TextureView, target: &wgpu::TextureView,
_target_size: Size<u32>, _target_size: Size<u32>,
viewport: Rectangle<u32>,
encoder: &mut wgpu::CommandEncoder, encoder: &mut wgpu::CommandEncoder,
) { ) {
//at this point our pipeline should always be initialized //at this point our pipeline should always be initialized
@ -170,7 +170,7 @@ impl shader::Primitive for Primitive {
pipeline.render( pipeline.render(
target, target,
encoder, encoder,
bounds, viewport,
self.cubes.len() as u32, self.cubes.len() as u32,
self.show_depth_buffer, self.show_depth_buffer,
); );

View file

@ -351,7 +351,7 @@ impl Pipeline {
&self, &self,
target: &wgpu::TextureView, target: &wgpu::TextureView,
encoder: &mut wgpu::CommandEncoder, encoder: &mut wgpu::CommandEncoder,
bounds: Rectangle<u32>, viewport: Rectangle<u32>,
num_cubes: u32, num_cubes: u32,
show_depth: bool, show_depth: bool,
) { ) {
@ -384,10 +384,10 @@ impl Pipeline {
}); });
pass.set_scissor_rect( pass.set_scissor_rect(
bounds.x, viewport.x,
bounds.y, viewport.y,
bounds.width, viewport.width,
bounds.height, viewport.height,
); );
pass.set_pipeline(&self.pipeline); pass.set_pipeline(&self.pipeline);
pass.set_bind_group(0, &self.uniform_bind_group, &[]); pass.set_bind_group(0, &self.uniform_bind_group, &[]);
@ -397,7 +397,7 @@ impl Pipeline {
} }
if show_depth { if show_depth {
self.depth_pipeline.render(encoder, target, bounds); self.depth_pipeline.render(encoder, target, viewport);
} }
} }
} }
@ -550,7 +550,7 @@ impl DepthPipeline {
&self, &self,
encoder: &mut wgpu::CommandEncoder, encoder: &mut wgpu::CommandEncoder,
target: &wgpu::TextureView, target: &wgpu::TextureView,
bounds: Rectangle<u32>, viewport: Rectangle<u32>,
) { ) {
let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("cubes.pipeline.depth_pass"), label: Some("cubes.pipeline.depth_pass"),
@ -573,7 +573,12 @@ impl DepthPipeline {
occlusion_query_set: None, occlusion_query_set: None,
}); });
pass.set_scissor_rect(bounds.x, bounds.y, bounds.width, bounds.height); pass.set_scissor_rect(
viewport.x,
viewport.y,
viewport.width,
viewport.height,
);
pass.set_pipeline(&self.pipeline); pass.set_pipeline(&self.pipeline);
pass.set_bind_group(0, &self.bind_group, &[]); pass.set_bind_group(0, &self.bind_group, &[]);
pass.draw(0..6, 0..1); pass.draw(0..6, 0..1);

View file

@ -192,9 +192,9 @@ impl Backend {
format, format,
device, device,
queue, queue,
pipeline.bounds,
target_size, target_size,
scale_factor, scale_factor,
transformation,
&mut self.pipeline_storage, &mut self.pipeline_storage,
); );
} }
@ -327,17 +327,17 @@ impl Backend {
let _ = ManuallyDrop::into_inner(render_pass); let _ = ManuallyDrop::into_inner(render_pass);
for pipeline in &layer.pipelines { for pipeline in &layer.pipelines {
let bounds = (pipeline.bounds * scale_factor).snap(); let viewport = (pipeline.viewport * scale_factor).snap();
if bounds.width < 1 || bounds.height < 1 { if viewport.width < 1 || viewport.height < 1 {
continue; continue;
} }
pipeline.primitive.render( pipeline.primitive.render(
&self.pipeline_storage, &self.pipeline_storage,
bounds,
target, target,
target_size, target_size,
viewport,
encoder, encoder,
); );
} }

View file

@ -1,11 +1,13 @@
//! Organize rendering primitives into a flattened list of layers. //! Organize rendering primitives into a flattened list of layers.
mod image; mod image;
mod pipeline;
mod text; mod text;
pub mod mesh; pub mod mesh;
pub use image::Image; pub use image::Image;
pub use mesh::Mesh; pub use mesh::Mesh;
pub use pipeline::Pipeline;
pub use text::Text; pub use text::Text;
use crate::core; use crate::core;
@ -36,7 +38,7 @@ pub struct Layer<'a> {
pub images: Vec<Image>, pub images: Vec<Image>,
/// The custom pipelines of this [`Layer`]. /// The custom pipelines of this [`Layer`].
pub pipelines: Vec<primitive::Pipeline>, pub pipelines: Vec<Pipeline>,
} }
impl<'a> Layer<'a> { impl<'a> Layer<'a> {
@ -314,17 +316,14 @@ impl<'a> Layer<'a> {
}, },
primitive::Custom::Pipeline(pipeline) => { primitive::Custom::Pipeline(pipeline) => {
let layer = &mut layers[current_layer]; let layer = &mut layers[current_layer];
let bounds = pipeline.bounds + translation;
let bounds = Rectangle::new(
Point::new(translation.x, translation.y),
pipeline.bounds.size(),
);
if let Some(clip_bounds) = if let Some(clip_bounds) =
layer.bounds.intersection(&bounds) layer.bounds.intersection(&bounds)
{ {
layer.pipelines.push(primitive::Pipeline { layer.pipelines.push(Pipeline {
bounds: clip_bounds, bounds,
viewport: clip_bounds,
primitive: pipeline.primitive.clone(), primitive: pipeline.primitive.clone(),
}); });
} }

View file

@ -0,0 +1,17 @@
use crate::core::Rectangle;
use crate::primitive::pipeline::Primitive;
use std::sync::Arc;
#[derive(Clone, Debug)]
/// A custom primitive which can be used to render primitives associated with a custom pipeline.
pub struct Pipeline {
/// The bounds of the [`Pipeline`].
pub bounds: Rectangle,
/// The viewport of the [`Pipeline`].
pub viewport: Rectangle,
/// The [`Primitive`] to render.
pub primitive: Arc<dyn Primitive>,
}

View file

@ -1,6 +1,5 @@
//! Draw primitives using custom pipelines. //! Draw primitives using custom pipelines.
use crate::core::{Rectangle, Size}; use crate::core::{Rectangle, Size};
use crate::graphics::Transformation;
use std::any::{Any, TypeId}; use std::any::{Any, TypeId};
use std::collections::HashMap; use std::collections::HashMap;
@ -41,9 +40,9 @@ pub trait Primitive: Debug + Send + Sync + 'static {
format: wgpu::TextureFormat, format: wgpu::TextureFormat,
device: &wgpu::Device, device: &wgpu::Device,
queue: &wgpu::Queue, queue: &wgpu::Queue,
bounds: Rectangle,
target_size: Size<u32>, target_size: Size<u32>,
scale_factor: f32, scale_factor: f32,
transform: Transformation,
storage: &mut Storage, storage: &mut Storage,
); );
@ -51,9 +50,9 @@ pub trait Primitive: Debug + Send + Sync + 'static {
fn render( fn render(
&self, &self,
storage: &Storage, storage: &Storage,
bounds: Rectangle<u32>,
target: &wgpu::TextureView, target: &wgpu::TextureView,
target_size: Size<u32>, target_size: Size<u32>,
viewport: Rectangle<u32>,
encoder: &mut wgpu::CommandEncoder, encoder: &mut wgpu::CommandEncoder,
); );
} }

View file

@ -17,7 +17,6 @@ use crate::renderer::wgpu::primitive::pipeline;
use std::marker::PhantomData; use std::marker::PhantomData;
pub use crate::graphics::Transformation;
pub use crate::renderer::wgpu::wgpu; pub use crate::renderer::wgpu::wgpu;
pub use pipeline::{Primitive, Storage}; pub use pipeline::{Primitive, Storage};