fyrox_graphics/framebuffer.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 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
// Copyright (c) 2019-present Dmitry Stepanov and Fyrox Engine contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#![warn(missing_docs)]
//! Frame buffer is a set of images that is used as a storage for an image generated by a renderer.
//! It consists of one or more color buffers and an optional depth/stencil buffer. See [`FrameBuffer`]
//! docs for more info.
use crate::{
buffer::Buffer,
core::{color::Color, math::Rect, Downcast},
error::FrameworkError,
geometry_buffer::GeometryBuffer,
gpu_program::{GpuProgram, UniformLocation},
gpu_texture::{CubeMapFace, GpuTexture},
DrawParameters, ElementRange,
};
use std::{cell::RefCell, rc::Rc};
/// Frame buffer attachment kind.
#[derive(Copy, Clone, PartialOrd, PartialEq, Hash, Debug, Eq)]
pub enum AttachmentKind {
/// Color attachment, it should have a format that supports rendering (for example it cannot be
/// a compressed texture format).
Color,
/// Combined depth + stencil (usually it is 24 bits for depth and 8 for stencil) attachment.
DepthStencil,
/// Depth-only attachment. Usually it is 16 or 32 bits texture.
Depth,
}
/// Frame buffer attachment.
pub struct Attachment {
/// Current kind of attachment. Tells the renderer how the texture should be used.
pub kind: AttachmentKind,
/// A texture that is used to write the rendered image to.
pub texture: Rc<RefCell<dyn GpuTexture>>,
}
/// Defines a range of data in a particular buffer.
#[derive(Default)]
pub enum BufferDataUsage {
/// Use everything at once.
#[default]
UseEverything,
/// Use just a segment of data starting from the given `offset` with `size` bytes. It is used
/// in cases where you have a large buffer with lots of small blocks of information about
/// different objects. Instead of having a number of small buffers (which is memory- and performance
/// inefficient), you put everything into a large buffer and fill it lots of info at once and then
/// binding segments of the data the to the pipeline.
UseSegment {
/// Offset from the beginning of the buffer in bytes.
offset: usize,
/// Size of the data block in bytes.
size: usize,
},
}
/// Defines a way how a texture will be bound to a pipeline.
pub enum TextureShaderLocation {
/// Obsolete texture binding mode where the video driver decides binding point (index) for a specific
/// uniform location automatically. It is not advised to use this mode, and you should always
/// prefer using [`TextureShaderLocation::ExplicitBinding`] instead.
Uniform(UniformLocation),
/// Defines a texture binding point explicitly using a number.
ExplicitBinding(usize),
}
/// Data buffer binding location.
// TODO: Remove when raw shaders will be replaced with Fyrox-native ones. This struct should turn
// into a simple index.
pub enum BufferLocation {
/// Obsolete automatic binding mode. It is a sort of implicit binding mode where the video driver
/// automatically assigns binding points for shader resources, and then you need to fetch these
/// values by name of a uniform variable and provide them in as `shader_location`. It is strongly
/// advised to use [`BufferLocation::Explicit`] mode instead. This mode is left mostly for
/// compatibility with the old code.
Auto {
/// An automatically generated index fetched from the video driver using
/// [`GpuProgram::uniform_block_index`].
shader_location: usize,
},
/// Explicit binding mode where you strictly define expected binding point for the buffer.
Explicit {
/// Binding point index.
binding: usize,
},
}
/// A resource binding defines where to bind specific GPU resources.
pub enum ResourceBinding<'a> {
/// Texture binding.
Texture {
/// A shared reference to a texture.
texture: Rc<RefCell<dyn GpuTexture>>,
/// Binding mode for the texture.
shader_location: TextureShaderLocation,
},
/// Generic data buffer binding.
Buffer {
/// A reference to a buffer.
buffer: &'a dyn Buffer,
/// Binding mode for the buffer.
binding: BufferLocation,
/// Data portion to use.
data_usage: BufferDataUsage,
},
}
impl ResourceBinding<'_> {
/// Creates a new texture binding using uniform location. See [`TextureShaderLocation::Uniform`]
/// docs for more info.
pub fn texture(
texture: &Rc<RefCell<dyn GpuTexture>>,
shader_location: &UniformLocation,
) -> Self {
Self::Texture {
texture: texture.clone(),
shader_location: TextureShaderLocation::Uniform(shader_location.clone()),
}
}
/// Creates a new explicit texture binding. See [`TextureShaderLocation::ExplicitBinding`] for
/// more info.
pub fn texture_with_binding(texture: &Rc<RefCell<dyn GpuTexture>>, binding: usize) -> Self {
Self::Texture {
texture: texture.clone(),
shader_location: TextureShaderLocation::ExplicitBinding(binding),
}
}
}
/// Resource binding group defines a set of bindings.
pub struct ResourceBindGroup<'a> {
/// A reference to resource bindings array.
pub bindings: &'a [ResourceBinding<'a>],
}
/// Statistics for a single GPU draw call.
#[derive(Debug, Copy, Clone, Default)]
pub struct DrawCallStatistics {
/// Total number of rendered triangles.
pub triangles: usize,
}
/// Frame buffer is a set of images that is used as a storage for an image generated by a renderer.
/// It consists of one or more color buffers and an optional depth/stencil buffer. Frame buffer is
/// a high level abstraction that consolidates multiple images and supports drawing meshes to them
/// with various drawing options.
pub trait FrameBuffer: Downcast {
/// Returns a list of color attachments.
fn color_attachments(&self) -> &[Attachment];
/// Returns an optional depth/stencil attachment.
fn depth_attachment(&self) -> Option<&Attachment>;
/// Sets an active face of a cube map (only for frame buffers that using cube maps for rendering).
fn set_cubemap_face(&mut self, attachment_index: usize, face: CubeMapFace);
/// Performs data transfer from one frame buffer to another with scaling. It copies a region
/// defined by `src_x0`, `src_y0`, `src_x1`, `src_y1` coordinates from the frame buffer and
/// "pastes" it to the other frame buffer into a region defined by `dst_x0`, `dst_y0`, `dst_x1`,
/// `dst_y1` coordinates. If the source rectangle does not match the destination, the image will
/// be interpolated using nearest interpolation.
///
/// This method can copy only specific parts of the image: `copy_color` tells the method to copy
/// the data from
fn blit_to(
&self,
dest: &dyn FrameBuffer,
src_x0: i32,
src_y0: i32,
src_x1: i32,
src_y1: i32,
dst_x0: i32,
dst_y0: i32,
dst_x1: i32,
dst_y1: i32,
copy_color: bool,
copy_depth: bool,
copy_stencil: bool,
);
/// Clears the frame buffer in the given viewport with the given set of optional values. This
/// method clears multiple attachments at once. What will be cleared defined by the provided
/// values. If `color` is not [`None`], then all the color attachments will be cleared with the
/// given color. The same applies to depth and stencil buffers.
fn clear(
&mut self,
viewport: Rect<i32>,
color: Option<Color>,
depth: Option<f32>,
stencil: Option<i32>,
);
/// Draws the specified geometry buffer using the given GPU program and a set of resources. This
/// method the main method to draw anything.
///
/// `geometry` - defines a [`GeometryBuffer`], that contains vertices and index buffers and
/// essentially defines a mesh to render.
/// `viewport` - defines an area on screen that will be used to draw.
/// `program` - a [`GpuProgram`] defines a set of shaders (usually a pair of vertex + fragment)
/// that will define how the mesh will be rendered.
/// `params` - [`DrawParameters`] defines the state of graphics pipeline and essentially sets
/// a bunch of various parameters (such as backface culling, blending mode, various tests, etc.)
/// that will define how the rendering process is performed.
/// `resources` - a set of resource bind groups, that in their turn provides a set of resources
/// that bound to specific binding points.
/// `element_range` - defines which range of elements to draw.
fn draw(
&mut self,
geometry: &dyn GeometryBuffer,
viewport: Rect<i32>,
program: &dyn GpuProgram,
params: &DrawParameters,
resources: &[ResourceBindGroup],
element_range: ElementRange,
) -> Result<DrawCallStatistics, FrameworkError>;
/// Almost the same as [`Self::draw`], but draws multiple instances at once. The caller must
/// supply all the required data per each instance, it could be done in different ways. The data
/// could be supplied in vertex attributes, uniform buffers, textures, etc.
fn draw_instances(
&mut self,
count: usize,
geometry: &dyn GeometryBuffer,
viewport: Rect<i32>,
program: &dyn GpuProgram,
params: &DrawParameters,
resources: &[ResourceBindGroup],
) -> DrawCallStatistics;
}