three_d/core/render_target/multisample.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
use crate::core::*;
///
/// A multisampled render target for color and depth data. Use this if you want to avoid aliasing, ie. jagged edges, when rendering to a [RenderTarget].
///
/// After rendering into this target, it needs to be resolved to a non-multisample texture to be able to sample it in a shader.
/// To do this, use the [RenderTargetMultisample::resolve], [RenderTargetMultisample::resolve_to], [RenderTargetMultisample::resolve_color_to]
/// or [RenderTargetMultisample::resolve_depth_to] methods.
///
/// Also see [ColorTargetMultisample] and [DepthTargetMultisample].
///
pub struct RenderTargetMultisample<C: TextureDataType, D: DepthTextureDataType> {
pub(crate) context: Context,
color: Texture2DMultisample,
depth: DepthTexture2DMultisample,
_c: std::marker::PhantomData<C>,
_d: std::marker::PhantomData<D>,
}
impl<C: TextureDataType, D: DepthTextureDataType> RenderTargetMultisample<C, D> {
///
/// Constructs a new multisample render target with the given dimensions and number of samples.
/// The number of samples must be larger than 0, less than or equal to the maximum number of samples supported by the hardware and power of two.
///
pub fn new(context: &Context, width: u32, height: u32, number_of_samples: u32) -> Self {
#[cfg(debug_assertions)]
super::multisample_sanity_check(context, number_of_samples);
Self {
context: context.clone(),
color: Texture2DMultisample::new::<C>(context, width, height, number_of_samples),
depth: DepthTexture2DMultisample::new::<D>(context, width, height, number_of_samples),
_c: std::marker::PhantomData,
_d: std::marker::PhantomData,
}
}
///
/// Clears the color and depth of this target as defined by the given clear state.
///
pub fn clear(&self, clear_state: ClearState) -> &Self {
self.clear_partially(self.scissor_box(), clear_state)
}
///
/// Clears the color and depth of the part of this target that is inside the given scissor box.
///
pub fn clear_partially(&self, scissor_box: ScissorBox, clear_state: ClearState) -> &Self {
self.as_render_target()
.clear_partially(scissor_box, clear_state);
self
}
///
/// Writes whatever rendered in the `render` closure into this target.
///
pub fn write<E: std::error::Error>(
&self,
render: impl FnOnce() -> Result<(), E>,
) -> Result<&Self, E> {
self.write_partially(self.scissor_box(), render)
}
///
/// Writes whatever rendered in the `render` closure into the part of this target defined by the scissor box.
///
pub fn write_partially<E: std::error::Error>(
&self,
scissor_box: ScissorBox,
render: impl FnOnce() -> Result<(), E>,
) -> Result<&Self, E> {
self.as_render_target()
.write_partially(scissor_box, render)?;
Ok(self)
}
/// The width of this target.
pub fn width(&self) -> u32 {
self.color.width()
}
/// The height of this target.
pub fn height(&self) -> u32 {
self.color.height()
}
/// The number of samples for each fragment.
pub fn number_of_samples(&self) -> u32 {
self.color.number_of_samples()
}
pub(super) fn as_render_target(&self) -> RenderTarget<'_> {
RenderTarget::new(
ColorTarget::new_texture_2d_multisample(&self.context, &self.color),
DepthTarget::new_texture_2d_multisample(&self.context, &self.depth),
)
}
///
/// Resolves the color of the multisample render target into the given non-multisample color target.
/// The target must have the same width, height and [TextureDataType] as the color part of this target.
///
pub fn resolve_color_to(&self, target: &ColorTarget<'_>) {
ColorTarget::new_texture_2d_multisample(&self.context, &self.color)
.as_render_target()
.blit_to(&target.as_render_target());
}
///
/// Resolves the depth of the multisample render target into the given non-multisample depth target.
/// The target must have the same width, height and [DepthTextureDataType] as the depth part of this target.
///
pub fn resolve_depth_to(&self, target: &DepthTarget<'_>) {
DepthTarget::new_texture_2d_multisample(&self.context, &self.depth)
.as_render_target()
.blit_to(&target.as_render_target());
}
///
/// Resolves the multisample render target into the given non-multisample render target.
/// The target must have the same width, height, [TextureDataType] and [DepthTextureDataType] as this target.
/// If the given render target is the screen render target, it must be non-multisampled or have the same number of samples as this target.
///
pub fn resolve_to(&self, target: &RenderTarget<'_>) {
self.as_render_target().blit_to(target);
}
///
/// Resolves the color of the multisample render target to a default non-multisample [Texture2D].
/// Use [RenderTargetMultisample::resolve_color_to] to resolve to a custom non-multisample texture.
///
pub fn resolve_color(&self) -> Texture2D {
let mut color_texture = Texture2D::new_empty::<C>(
&self.context,
self.color.width(),
self.color.height(),
Interpolation::Linear,
Interpolation::Linear,
None,
Wrapping::ClampToEdge,
Wrapping::ClampToEdge,
);
self.resolve_color_to(&color_texture.as_color_target(None));
color_texture
}
///
/// Resolves the depth of the multisample render target to a default non-multisample [DepthTexture2D].
/// Use [RenderTargetMultisample::resolve_depth_to] to resolve to a custom non-multisample texture.
///
pub fn resolve_depth(&self) -> DepthTexture2D {
let mut depth_texture = DepthTexture2D::new::<D>(
&self.context,
self.width(),
self.height(),
Wrapping::ClampToEdge,
Wrapping::ClampToEdge,
);
self.resolve_depth_to(&depth_texture.as_depth_target());
depth_texture
}
///
/// Resolves the multisample render target to default non-multisample [Texture2D] and [DepthTexture2D].
/// Use [RenderTargetMultisample::resolve_to] to resolve to custom non-multisample textures.
///
pub fn resolve(&self) -> (Texture2D, DepthTexture2D) {
let mut color_texture = Texture2D::new_empty::<C>(
&self.context,
self.color.width(),
self.color.height(),
Interpolation::Linear,
Interpolation::Linear,
None,
Wrapping::ClampToEdge,
Wrapping::ClampToEdge,
);
let mut depth_texture = DepthTexture2D::new::<D>(
&self.context,
self.width(),
self.height(),
Wrapping::ClampToEdge,
Wrapping::ClampToEdge,
);
self.resolve_to(&RenderTarget::new(
color_texture.as_color_target(None),
depth_texture.as_depth_target(),
));
(color_texture, depth_texture)
}
}