Merge pull request #833 from b-guild/graphics

Clarifying graphics code with comments and slight corrections.
This commit is contained in:
Dmitry Stepanov
2025-08-31 17:08:03 +03:00
committed by GitHub
14 changed files with 475 additions and 60 deletions
+7 -5
View File
@@ -123,8 +123,8 @@ impl GlFrameBuffer {
server,
depth_attachment_kind,
texture,
depth_attachment.level as i32,
depth_attachment.cube_map_face,
depth_attachment.level() as i32,
depth_attachment.cube_map_face(),
);
}
@@ -141,8 +141,8 @@ impl GlFrameBuffer {
server,
color_attachment_kind,
texture,
color_attachment.level as i32,
color_attachment.cube_map_face,
color_attachment.level() as i32,
color_attachment.cube_map_face(),
);
color_buffers.push(color_attachment_kind);
}
@@ -198,7 +198,9 @@ impl GpuFrameBufferTrait for GlFrameBuffer {
unsafe {
server.set_framebuffer(FrameBufferBindingPoint::ReadWrite, self.fbo);
let attachment = self.color_attachments.get(attachment_index).unwrap();
let attachment = &self.color_attachments[attachment_index];
attachment.set_cube_map_face(Some(face));
attachment.set_level(level);
let texture = attachment
.texture
.as_any()
+7
View File
@@ -141,6 +141,13 @@ impl ToGlConstant for ShaderKind {
impl GpuShaderTrait for GlShader {}
impl GlShader {
/// Generate and compile the source code for a shader.
/// * `server`: The OpenGL context that is used to compile the shader.
/// * `name`: The name of the shader that will be used to log messages about the compilation and report errors.
/// * `kind`: Is this a vertex shader or a fragment shader?
/// * `source`: The source code for the shader, excluding the uniform declarations that are automatically generated.
/// * `resources`: Resource definitions that are used to automatically generate uniform declarations in the source code before compiling.
/// * `line_offset`: The position of the first line of source code in whatever file it came from, for error reporting.
pub fn new(
server: &GlGraphicsServer,
name: String,
+188 -17
View File
@@ -167,50 +167,122 @@ impl ToGlConstant for CullFace {
}
}
/// Indicator of whether we are using the embedded version of OpenGL.
#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
pub enum GlKind {
/// The full Open Graphics Library, without restrictions for embedded systems.
OpenGL,
/// OpenGL for Embedded Systems is a subset of OpenGL designed for systems such as smartphones, tablet computers, and PDAs.
OpenGLES,
}
/// A representation of the state of the GL context. OpenGL keeps track of various flags and values internally,
/// and this struct remembers those settings. This makes it possible to check if a setting is actually being changed
/// when a new value is supplied, so we can avoid calling OpenGL functions unnecessarily.
///
/// For example: we can call [`GlGraphicsServer::set_clear_color`] multiple times with the same color, and it will not
/// result in repeated calls to the underlying `glClearColor` function because `GlGraphicsServer` will store the color
/// in its `InnerState` and avoid calling `glClearColor` when it would be redundant.
pub(crate) struct InnerState {
/// True if blending is currently enabled in the GL context due to a blending function being set in the [`DrawParameters`].
/// Protects `glEnable(GL_BLEND)` and `glDisable(GL_BLEND)`.
blend: bool,
/// True if depth testing is currently enabled in the GL contex due to a depth test function being set in [`DrawParameters`].
/// Protects `glEnable(GL_DEPTH_TEST)` and `glDisable(GL_DEPTH_TEST)`.
depth_test: bool,
/// True if depth mask is currently enabled in the GL context.
/// Protects `glDepthMask`.
depth_write: bool,
/// The depth test function currently set in the context, only to be used if `depth_test` is true.
/// Protects `glDepthFunc`.
depth_func: CompareFunc,
/// A mask that defines which colors will be stored in a frame buffer during rendering operation.
/// By default, all colors are stored (every field is set to `true`).
/// Protects `glColorMask`.
color_write: ColorMask,
/// True if stencil testing is currently enabled in the GL contex due to a stencil function being set in [`DrawParameters`].
/// Protects `glEnable(GL_STENCIL_TEST)` and `glDisable(GL_STENCIL_TEST)`.
stencil_test: bool,
/// Which side of the geometry is OpenGL set to cull?
/// Protects `glCullFace`.
cull_face: CullFace,
/// True if culling is enabled, with `cull_face` determining whether to cull the front or the back.
/// Protects `glEnable(GL_CULL_FACE)` and `glDisable(GL_CULL_FACE)`.
culling: bool,
stencil_mask: u32,
/// The color that GL will use when clearing color buffers.
/// Protects `glClearColor`.
clear_color: Color,
/// The stencil value that GL will use when clearing the stencil buffer.
/// Protects `glClearStencil`.
clear_stencil: i32,
/// The depth value that GL will use when clearing the depth buffer.
/// Protects `glClearDepth`.
clear_depth: f32,
/// True if OpenGL is limiting rendering to a specific rectangle.
/// The size and position of the rectangle is not stored in `InnerState`, but it is changed in
/// OpenGL by calling [`GlGraphicsServer::set_scissor_box`].
/// Protects `glEnable(GL_SCISSOR_TEST)` and `glDisable(GL_SCISSOR_TEST)`.
scissor_test: bool,
polygon_face: PolygonFace,
polygon_fill_mode: PolygonFillMode,
/// The fill mode for the front of polygons.
/// Protects `glPolygonMode`.
front_fill_mode: PolygonFillMode,
/// The fill mode for the back of polygons.
/// Protects `glPolygonMode`.
back_fill_mode: PolygonFillMode,
/// The identifier for the currently bound frame buffer for writing. Frame buffers in OpenGL are identified by numbers.
/// If there is a currently bound frame buffer for writing, then this will be that frame buffer's number.
/// Otherwise, this will be None.
/// Protects `glBindFramebuffer`.
write_framebuffer: Option<glow::Framebuffer>,
/// The identifier for the currently bound frame buffer for reading. Frame buffers in OpenGL are identified by numbers.
/// If there is a currently bound frame buffer for reading, then this will be that frame buffer's number.
/// Otherwise, this will be None.
/// Protects `glBindFramebuffer`.
read_framebuffer: Option<glow::Framebuffer>,
/// Protects `glViewport`.
viewport: Rect<i32>,
/// Protects `glBlendFuncSeparate`.
blend_func: BlendFunc,
/// Protects `glBlendEquationSeparate`.
blend_equation: BlendEquation,
/// Protects `glUseProgram`.
program: Option<glow::Program>,
/// Protects `glBindTexture` and `glActiveTexture`.
texture_units_storage: TextureUnitsStorage,
/// Similar to `depth_func`, this controls how the stencil buffer will determine which fragments to draw.
/// Protects `glStencilFunc`.
stencil_func: StencilFunc,
/// A set of actions that will be performed with the stencil buffer during various testing stages.
/// `stencil_mask` can limit which bits of the stencil buffer are affected.
/// Protects `glStencilOp` and `glStencilMask`.
stencil_op: StencilOp,
/// Protects `glBindVertexArray`.
vao: Option<glow::VertexArray>,
/// Counts of various rendering operations.
frame_statistics: PipelineStatistics,
/// Indicator of whether we are using the embedded version of OpenGL.
gl_kind: GlKind,
/// A pool of available query identifiers for use by [`GlQuery`].
/// Each time a `GlQuery` is created, it checks this list for unused query identifies and pops off
/// the last one to use, or it creates a new query if the list is empty. When `GlQuery` is dropped,
/// it returns its query identifier to this list.
///
/// Each query corresponds to some count that is recorded during rendering, such as the number of
/// sambles that pass the depth check or the number of primitives that are generated.
/// The only query types that are supported by Fyrox are given in `QueryKind` in the fyrox-graphics crate.
///
/// Once the rendering commands have been sent, we may use the query identifier to wait until the
/// rendering is finished the desired number is available.
pub(crate) queries: Vec<glow::Query>,
#[cfg(not(target_arch = "wasm32"))]
@@ -234,13 +306,12 @@ impl InnerState {
stencil_test: false,
cull_face: CullFace::Back,
culling: false,
stencil_mask: 0xFFFF_FFFF,
clear_color: Color::from_rgba(0, 0, 0, 0),
clear_stencil: 0,
clear_depth: 1.0,
scissor_test: false,
polygon_face: Default::default(),
polygon_fill_mode: Default::default(),
front_fill_mode: PolygonFillMode::default(),
back_fill_mode: PolygonFillMode::default(),
read_framebuffer: None,
write_framebuffer: None,
blend_func: Default::default(),
@@ -335,6 +406,10 @@ impl InnerState {
}
}
/// Bind the texture with the given identifier to the given target in the given unit.
/// Target numbers can be found using [`ToGlConstant::into_gl`] on `GpuTextureKind` from the `fyrox-graphics` crate.
/// The given unit will be activated if it is not already active.
/// If a texture is already bound in the unit, it will be unbound.
pub(crate) fn set_texture(
&mut self,
unit_index: u32,
@@ -428,17 +503,32 @@ impl InnerState {
}
}
/// A frame buffer can be bound for reading, writing, or both.
pub enum FrameBufferBindingPoint {
Read,
Write,
ReadWrite,
}
/// `GlGraphicsServer` implements the [`GraphicsServer`] trait using the `glow` crate.
/// `glow` is "GL on Whatever: a set of bindings to run GL anywhere (Open GL, OpenGL ES, and WebGL) and avoid target-specific code."
pub struct GlGraphicsServer {
/// `glow::Context` provides access to the current rendering state.
/// It creates buffers, creates textures, compiles shaders, accepts geometry data,
/// and broadly provides access too all sorts of rendering services.
pub gl: glow::Context,
/// Controls whether objects the `glow::Context::object_label` method should be used
/// to assign labels to rendering objects. These labels can help with debugging.
pub named_objects: Cell<bool>,
/// A representation of the state of the GL context. OpenGL keeps track of various flags and values internally,
/// and this struct remembers those settings. This makes it possible to check if a setting is actually being changed
/// when a new value is supplied, so we can avoid calling OpenGL functions unnecessarily.
pub(crate) state: RefCell<InnerState>,
/// Contains information about used memory per each category of GPU resource.
pub(crate) memory_usage: RefCell<ServerMemoryUsage>,
/// A weak reference to the `Rc` that contains this server.
/// This is needed in order to convert a borrow of this server into an `Rc` reference of
/// this server, for implementing [`GlGraphicsServer::weak`] and [`GraphicsServer::weak`].
this: RefCell<Option<Weak<GlGraphicsServer>>>,
}
@@ -448,12 +538,20 @@ struct TextureBinding {
texture: Option<glow::Texture>,
}
/// A record of which texture is bound to each target.
/// There is one binding for each of the texture targets
/// defined by `GpuTextureKind` in the `fyrox-graphics` crate.
/// It is forbidden to have multiple targets bound at once in any unit,
/// and [`GlGraphicsServer::set_texture`] enforces this by automatically unbinding other targets.
#[derive(Copy, Clone)]
struct TextureUnit {
bindings: [TextureBinding; 4],
}
impl Default for TextureUnit {
/// Initialize the array of texture bindings with the valid target
/// values that can be produced by [`ToGlConstant::into_gl`] on `GpuTextureKind`
/// in the `fyrox-graphics` crate.
fn default() -> Self {
Self {
bindings: [
@@ -478,9 +576,12 @@ impl Default for TextureUnit {
}
}
/// A record of every texture binding in every unit and the currently active unit.
#[derive(Default)]
struct TextureUnitsStorage {
/// The currently active texture unit, as set by `glActiveTexture`.
active_unit: u32,
/// The textures that are bound to each target in each texture unit.
units: [TextureUnit; 32],
}
@@ -769,14 +870,17 @@ impl GlGraphicsServer {
Ok((window, shared))
}
/// A weak reference to the `Rc` where the server is stored.
pub fn weak(&self) -> Weak<Self> {
self.this.borrow().as_ref().unwrap().clone()
}
/// Determine if we are using the embedded version of OpenGL.
pub fn gl_kind(&self) -> GlKind {
self.state.borrow().gl_kind
}
/// Find the number of a texture unit where no texture is bound, if possible.
pub fn free_texture_unit(&self) -> Option<u32> {
let state = self.state.borrow();
for (index, unit) in state.texture_units_storage.units.iter().enumerate() {
@@ -791,12 +895,16 @@ impl GlGraphicsServer {
None
}
/// `glDeleteFramebuffers`
pub(crate) fn delete_framebuffer(&self, framebuffer: Option<glow::Framebuffer>) {
self.state
.borrow_mut()
.delete_framebuffer(framebuffer, &self.gl)
}
/// Choose the current frame buffer for reading or writing. See `glBindFramebuffer` from OpenGL.
/// * `binding_point`: Are we going to read from this buffer, write to it, or both?
/// * `framebuffer`: The buffer that we are going to use.
pub(crate) fn set_framebuffer(
&self,
binding_point: FrameBufferBindingPoint,
@@ -807,6 +915,7 @@ impl GlGraphicsServer {
.set_framebuffer(binding_point, framebuffer, &self.gl)
}
/// Choose a rectangle where rendering will happen. See `glViewport` from OpenGL.
pub(crate) fn set_viewport(&self, viewport: Rect<i32>) {
let mut state = self.state.borrow_mut();
if state.viewport != viewport {
@@ -823,6 +932,8 @@ impl GlGraphicsServer {
}
}
/// Turn blending on or off, allowing rendered pixels to be influenced by the pixels that
/// are already in the frame buffer. See 'glEnable(GL_BLEND)` or `glDisable(GL_BLEND)` from OpenGL.
pub(crate) fn set_blend(&self, blend: bool) {
let mut state = self.state.borrow_mut();
if state.blend != blend {
@@ -840,6 +951,9 @@ impl GlGraphicsServer {
}
}
/// Turn depth testing on or off, allowing the content of the depth buffer to determine whether
/// a rendered pixel will be written to the frame buffer.
/// See `glEnable(GL_DEPTH_TEST)` or `glDisable(GL_DEPTH_TEST)` from OpenGL.
pub(crate) fn set_depth_test(&self, depth_test: bool) {
let mut state = self.state.borrow_mut();
if state.depth_test != depth_test {
@@ -855,6 +969,8 @@ impl GlGraphicsServer {
}
}
/// Turn depth writing on or off, allowing the depth buffer to be modified when rendering.
/// See `glDepthMask` from OpenGL.
pub(crate) fn set_depth_write(&self, depth_write: bool) {
let mut state = self.state.borrow_mut();
if state.depth_write != depth_write {
@@ -866,6 +982,8 @@ impl GlGraphicsServer {
}
}
/// Turn writing to each color channel on or off. For example, writing red values might be disabled.
/// See `glColorMask` from OpenGL.
pub(crate) fn set_color_write(&self, color_write: ColorMask) {
let mut state = self.state.borrow_mut();
if state.color_write != color_write {
@@ -882,6 +1000,9 @@ impl GlGraphicsServer {
}
}
/// Turn stencil testing on or off, allowing the content of the stencil buffer to determine whether
/// each rendered pixel will be written.
/// See `glEnable(GL_STENCIL_TEST)` or `glDisable(GL_STENCIL_TEST)` from OpenGL.
pub(crate) fn set_stencil_test(&self, stencil_test: bool) {
let mut state = self.state.borrow_mut();
if state.stencil_test != stencil_test {
@@ -897,6 +1018,7 @@ impl GlGraphicsServer {
}
}
/// See `glCullFace` from OpenGL.
pub(crate) fn set_cull_face(&self, cull_face: CullFace) {
let mut state = self.state.borrow_mut();
if state.cull_face != cull_face {
@@ -906,6 +1028,7 @@ impl GlGraphicsServer {
}
}
/// See `glEnable(GL_CULL_FACE)` or `glDisable(GL_CULL_FACE)` from OpenGL.
pub(crate) fn set_culling(&self, culling: bool) {
let mut state = self.state.borrow_mut();
if state.culling != culling {
@@ -921,10 +1044,14 @@ impl GlGraphicsServer {
}
}
/// Control which bits of the stencil buffer may be modified.
/// Bits of `stencil_mask` that are 1 correspond to bits of the buffer that may be modified.
/// If `stencil_mask` is 0 then nothing in the stencil mask can be modified.
/// See `glStencilMask` from OpenGL.
pub(crate) fn set_stencil_mask(&self, stencil_mask: u32) {
let mut state = self.state.borrow_mut();
if state.stencil_mask != stencil_mask {
state.stencil_mask = stencil_mask;
if state.stencil_op.write_mask != stencil_mask {
state.stencil_op.write_mask = stencil_mask;
unsafe {
self.gl.stencil_mask(stencil_mask);
@@ -932,6 +1059,7 @@ impl GlGraphicsServer {
}
}
/// Set the color used when clearing a color buffer. See `glClearColor`.
pub(crate) fn set_clear_color(&self, color: Color) {
let mut state = self.state.borrow_mut();
if state.clear_color != color {
@@ -944,6 +1072,7 @@ impl GlGraphicsServer {
}
}
/// Set the depth used when clearing a depth buffer. See `glClearDepth`.
pub(crate) fn set_clear_depth(&self, depth: f32) {
let mut state = self.state.borrow_mut();
if (state.clear_depth - depth).abs() > f32::EPSILON {
@@ -955,6 +1084,7 @@ impl GlGraphicsServer {
}
}
/// Set the value used when clearing a stencil buffer. See `glClearStencil`.
pub(crate) fn set_clear_stencil(&self, stencil: i32) {
let mut state = self.state.borrow_mut();
if state.clear_stencil != stencil {
@@ -966,6 +1096,10 @@ impl GlGraphicsServer {
}
}
/// Modify how pixels are blended by changing the factors that multiply the source pixel
/// (coming from the fragment shader) and the destination pixel (already in the frame buffer).
/// See [`BlendFactor`] for available factors.
/// See `glBlendFuncSeparate` from OpenGL.
pub(crate) fn set_blend_func(&self, func: BlendFunc) {
let mut state = self.state.borrow_mut();
if state.blend_func != func {
@@ -982,6 +1116,9 @@ impl GlGraphicsServer {
}
}
/// Modify how pixels are blended by changing the formula that is used to combine the source pixel
/// (coming from the fragment shader) and the destination pixel (already in the frame buffer).
/// See `glBlendEquationSeparate` from OpenGL.
pub(crate) fn set_blend_equation(&self, equation: BlendEquation) {
let mut state = self.state.borrow_mut();
if state.blend_equation != equation {
@@ -996,6 +1133,8 @@ impl GlGraphicsServer {
}
}
/// Set the function used to compare the fragment shader's z to the depth buffer
/// and thereby decide whether to render the pixel. See `glDepthFunc` from OpenGL.
pub(crate) fn set_depth_func(&self, depth_func: CompareFunc) {
let mut state = self.state.borrow_mut();
if state.depth_func != depth_func {
@@ -1007,24 +1146,34 @@ impl GlGraphicsServer {
}
}
/// Delete the given program. See `glDeleteProgram` from OpenGL.
pub fn delete_program(&self, program: glow::Program) {
self.state.borrow_mut().delete_program(program, &self.gl);
}
/// Choose the program to use for the following rendering commands. See `glUseProgram` from OpenGL.
pub(crate) fn set_program(&self, program: Option<glow::Program>) {
self.state.borrow_mut().set_program(program, &self.gl)
}
/// Delete the given texture. See `glDeleteTextures` from OpenGL.
pub(crate) fn delete_texture(&self, texture: glow::Texture) {
self.state.borrow_mut().delete_texture(texture, &self.gl)
}
/// Bind the texture with the given identifier to the given target in the given unit.
/// Target numbers can be found using [`ToGlConstant::into_gl`] on `GpuTextureKind` from the `fyrox-graphics` crate.
/// The given unit will be activated if it is not already active.
/// If a texture is already bound in the unit, it will be unbound.
pub(crate) fn set_texture(&self, unit_index: u32, target: u32, texture: Option<glow::Texture>) {
self.state
.borrow_mut()
.set_texture(unit_index, target, texture, &self.gl)
}
/// Modify how the stencil buffer prevents pixels from being drawn.
/// See [`StencilFunc`] for the available options.
/// See `glStencilFunc` from OpenGL.
pub(crate) fn set_stencil_func(&self, func: StencilFunc) {
let mut state = self.state.borrow_mut();
if state.stencil_func != func {
@@ -1040,9 +1189,13 @@ impl GlGraphicsServer {
}
}
/// Modify how the stencil buffer is written to by rendering.
/// See [`StencilOp`] for details of the available options.
/// See `glStencilOp` and `glStencilMask` from OpenGL.
pub(crate) fn set_stencil_op(&self, op: StencilOp) {
let mut state = self.state.borrow_mut();
if state.stencil_op != op {
let new_mask = op.write_mask;
if !state.stencil_op.eq_actions(&op) {
state.stencil_op = op;
unsafe {
@@ -1051,24 +1204,31 @@ impl GlGraphicsServer {
state.stencil_op.zfail.into_gl(),
state.stencil_op.zpass.into_gl(),
);
}
}
if state.stencil_op.write_mask != new_mask {
state.stencil_op.write_mask = new_mask;
unsafe {
self.gl.stencil_mask(state.stencil_op.write_mask);
}
}
}
/// `glDeleteVertexArrays`
pub(crate) fn delete_vertex_array_object(&self, vao: glow::VertexArray) {
self.state
.borrow_mut()
.delete_vertex_array_object(vao, &self.gl);
}
/// `glBindVertexArray`
pub(crate) fn set_vertex_array_object(&self, vao: Option<glow::VertexArray>) {
self.state
.borrow_mut()
.set_vertex_array_object(vao, &self.gl);
}
/// `glEnable(GL_SCISSOR_TEST)` or `glDisable(GL_SCISSOR_TEST)`.
pub(crate) fn set_scissor_test(&self, scissor_test: bool) {
let mut state = self.state.borrow_mut();
if state.scissor_test != scissor_test {
@@ -1084,6 +1244,7 @@ impl GlGraphicsServer {
}
}
/// `glScissor`
pub(crate) fn set_scissor_box(&self, scissor_box: &ScissorBox) {
unsafe {
self.gl.scissor(
@@ -1095,6 +1256,7 @@ impl GlGraphicsServer {
}
}
/// Call the necessary GL functions to set the given parameters.
pub(crate) fn apply_draw_parameters(&self, draw_params: &DrawParameters) {
let DrawParameters {
cull_face,
@@ -1336,16 +1498,25 @@ impl GraphicsServer for GlGraphicsServer {
}
fn set_polygon_fill_mode(&self, polygon_face: PolygonFace, polygon_fill_mode: PolygonFillMode) {
let (set_front, set_back) = match polygon_face {
PolygonFace::Front => (true, false),
PolygonFace::Back => (false, true),
PolygonFace::FrontAndBack => (true, true),
};
let mut state = self.state.borrow_mut();
if state.polygon_fill_mode != polygon_fill_mode || state.polygon_face != polygon_face {
state.polygon_fill_mode = polygon_fill_mode;
state.polygon_face = polygon_face;
if (set_front && state.front_fill_mode != polygon_fill_mode)
|| (set_back && state.back_fill_mode != polygon_fill_mode)
{
if set_front {
state.front_fill_mode = polygon_fill_mode;
}
if set_back {
state.back_fill_mode = polygon_fill_mode;
}
unsafe {
self.gl.polygon_mode(
state.polygon_face.into_gl(),
state.polygon_fill_mode.into_gl(),
)
self.gl
.polygon_mode(polygon_face.into_gl(), polygon_fill_mode.into_gl())
}
}
}
+7 -1
View File
@@ -26,14 +26,20 @@ use crate::error::FrameworkError;
use bytemuck::Pod;
use fyrox_core::{array_as_u8_slice, array_as_u8_slice_mut, define_as_any_trait};
/// Specifications for a buffer that are passed to [`crate::server::GraphicsServer::create_buffer`] so that the server
/// knows what buffer to create.
pub struct GpuBufferDescriptor<'a> {
/// A label for the buffer for debugging, as might be passed to `glObjectLabel` in an OpenGL server.
pub name: &'a str,
/// The size of the buffer in bytes, as might be passed to `glBufferData` in an OpenGL server.
pub size: usize,
/// What is stored in the buffer? Vertices, indices, uniforms, pixels, etc.
pub kind: BufferKind,
/// An efficiency hint for how the buffer will be used.
pub usage: BufferUsage,
}
/// GPU buffer kind.
/// GPU buffer kind, as used in [`GpuBufferDescriptor`].
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub enum BufferKind {
/// Vertex buffer. It is used to supply vertex data (such as positions, normals, texture
+49 -22
View File
@@ -20,9 +20,11 @@
#![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 [`GpuFrameBufferTrait`]
//! docs for more info.
//! Framebuffer objects are user-defined framebuffers which allow one to render to memory locations
//! instead of the screen. First a framebuffer is created, and then textures are attached to it in order
//! to control where the rendering data is stored. There are attachments for color, attachments for depth,
//! and attachments for stencil, thereby providing memory for everything that is required for rendering.
//! See [`GpuFrameBufferTrait`] docs for more info.
use crate::sampler::GpuSampler;
use crate::{
@@ -37,6 +39,7 @@ use crate::{
};
use bytemuck::Pod;
use fyrox_core::define_as_any_trait;
use std::cell::Cell;
/// Frame buffer attachment kind.
#[derive(Copy, Clone, PartialOrd, PartialEq, Hash, Debug, Eq)]
@@ -50,26 +53,48 @@ pub enum AttachmentKind {
Depth,
}
/// Frame buffer attachment.
/// A frame buffer attachment that tells the frame buffer object where to store the results of rendering.
pub struct Attachment {
/// Current kind of attachment. Tells the renderer how the texture should be used.
/// Current kind of attachment. Tells the renderer how the texture should be used
/// when rendering to the frame buffer. For example, is it color or depth?
pub kind: AttachmentKind,
/// A texture that is used to write the rendered image to.
/// A texture the renderer writes to. It may be writing the actual image, or it may just be writing
/// the depth, or stencil, depending on `kind`.
pub texture: GpuTexture,
/// Mip level of the texture. In most cases, it can be zero.
pub level: usize,
/// Face of the cube map, this field is used only if the `texture` is a cube map.
pub cube_map_face: Option<CubeMapFace>,
/// Mip level of the texture where the rendering should happen. In most cases, it can be zero,
/// but this allows us to render multiple mipmap levels into a texture.
level: Cell<usize>,
/// Face of the cube map. This field is used only if the `texture` is a cube map.
/// This indicates which face of the cube will be rendered to.
cube_map_face: Cell<Option<CubeMapFace>>,
}
impl Attachment {
/// Mip level of the texture where the rendering should happen. In most cases, it can be zero.
pub fn level(&self) -> usize {
self.level.get()
}
/// Face of the cube map, this field is used only if the `texture` is a cube map.
/// This indicates which face of the cube will be rendered to.
pub fn cube_map_face(&self) -> Option<CubeMapFace> {
self.cube_map_face.get()
}
/// Mip level of the texture where the rendering should happen. In most cases, it can be zero.
pub fn set_level(&self, level: usize) {
self.level.set(level)
}
/// Face of the cube map, this field is used only if the `texture` is a cube map.
/// This indicates which face of the cube will be rendered to.
pub fn set_cube_map_face(&self, face: Option<CubeMapFace>) {
self.cube_map_face.set(face)
}
/// Creates a new [`AttachmentKind::Color`] attachment with the given texture.
pub fn color(texture: GpuTexture) -> Self {
Self {
kind: AttachmentKind::Color,
texture,
level: 0,
cube_map_face: None,
level: Cell::new(0),
cube_map_face: Cell::new(None),
}
}
@@ -78,8 +103,8 @@ impl Attachment {
Self {
kind: AttachmentKind::Color,
texture,
level,
cube_map_face: None,
level: Cell::new(level),
cube_map_face: Cell::new(None),
}
}
@@ -89,8 +114,8 @@ impl Attachment {
Self {
kind: AttachmentKind::Color,
texture,
level: 0,
cube_map_face: Some(cube_map_face),
level: Cell::new(0),
cube_map_face: Cell::new(Some(cube_map_face)),
}
}
@@ -99,8 +124,8 @@ impl Attachment {
Self {
kind: AttachmentKind::Depth,
texture,
level: 0,
cube_map_face: None,
level: Cell::new(0),
cube_map_face: Cell::new(None),
}
}
@@ -109,8 +134,8 @@ impl Attachment {
Self {
kind: AttachmentKind::DepthStencil,
texture,
level: 0,
cube_map_face: None,
level: Cell::new(0),
cube_map_face: Cell::new(None),
}
}
}
@@ -143,6 +168,7 @@ pub enum ResourceBinding {
/// A sampler that will be used to fetch the data from the texture.
sampler: GpuSampler,
/// Binding mode for the texture.
/// `glUniform1i` is used to assign this binding point to a texture uniform.
binding: usize,
},
/// Generic data buffer binding.
@@ -213,8 +239,9 @@ pub trait GpuFrameBufferTrait: GpuFrameBufferAsAny {
/// Returns an optional depth/stencil attachment.
fn depth_attachment(&self) -> Option<&Attachment>;
/// Sets an active face of a cube map of the given mip level. Only for frame buffers that using
/// cube maps for rendering.
/// Chooses a different face and mipmap level for the texture attached at the given index.
/// When the texture is a cubemap texture, this allows the framebuffer to render to a different
/// face of the cube. This method must not be called if the texture is not a cubemap.
fn set_cubemap_face(&self, attachment_index: usize, face: CubeMapFace, level: usize);
/// Performs data transfer from one frame buffer to another with scaling. It copies a region
+93 -1
View File
@@ -18,6 +18,9 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//! A GPU program is a collection of shaders that are linked together so that they
//! can run on the GPU to control how rendering is performed.
use crate::{
core::{
algebra::{Matrix2, Matrix3, Matrix4, Vector2, Vector3, Vector4},
@@ -33,15 +36,30 @@ use serde::{Deserialize, Serialize};
use strum_macros::{AsRefStr, EnumString, VariantNames};
define_as_any_trait!(GpuProgramAsAny => GpuProgramTrait);
/// A trait for whatever objects a graphics server is using to represent programs.
/// There are no methods because all interactions with programs are done through the server,
/// such as with [`crate::server::GraphicsServer::create_program`]
/// and [`crate::framebuffer::GpuFrameBufferTrait::draw`].
pub trait GpuProgramTrait: GpuProgramAsAny {}
define_shared_wrapper!(GpuProgram<dyn GpuProgramTrait>);
/// A shader can be either a fragment shader that produces pixels or
/// a vertex shader that controls where triangles are drawn on the screen.
pub enum ShaderKind {
/// A vertex shader takes vertices in world coordinates and mathematically
/// transforms them into screen coordinates for rendering. The vertex shader
/// runs before the fragment shader and creates the input to the fragment shader.
Vertex,
/// The fragment shader determines whether a pixel should be drawn and what color it should be.
/// It uses the data produced by the vertex shader after it has been interpolated by the GPU
/// for the particular pixel under consideration.
Fragment,
}
define_as_any_trait!(GpuShaderAsAny => GpuShaderTrait);
/// A trait for whatever objects a graphics server is using to represent shaders.
/// There are no methods because all interactions with programs are done through the server,
/// such as with [`crate::server::GraphicsServer::create_shader`].
pub trait GpuShaderTrait: GpuShaderAsAny {}
define_shared_wrapper!(GpuShader<dyn GpuShaderTrait>);
@@ -89,16 +107,38 @@ pub enum SamplerFallback {
Volume,
}
/// A sampler represents how the data of a texture is accessed, and different kinds of samplers
/// are intended for different kinds of textures.
#[derive(Serialize, Deserialize, Default, Debug, PartialEq, Clone, Copy, Visit, Eq, Reflect)]
pub enum SamplerKind {
/// A sampler for a 1D linear texture, a series of values that are indexed by a single coordinate
/// and where each component of the value is a float.
Sampler1D,
/// A sampler for the usual 2D image texture, a flat area of values that are indexed by a pair of coordinates (x, y)
/// and where each component of the value is a float.
#[default]
Sampler2D,
/// A sampler for a 3D texture, a volume of values that are indexed by three coordinates (x, y, z)
/// and where each component of the value is a float.
Sampler3D,
/// A sampler for six square 2D images where each image represents one face of a cube.
/// It is indexed by a three coordinate direction from the center of the cube (x, y, z) where the magnitude of the coordinates do not matter.
/// The sampler follows the direction of the coordinates until it finds a place on one of the six faces of the cube.
/// Each component of the resulting value is a float.
SamplerCube,
/// A sampler for a 1D linear texture, a series of values that are indexed by a single coordinate
/// and where each component of the value is an unsigned integer.
USampler1D,
/// A sampler for the usual 2D image texture, a flat area of values that are indexed by a pair of coordinates (x, y)
/// and where each component of the value is an unsigned integer.
USampler2D,
/// A sampler for a 3D texture, a volume of values that are indexed by three coordinates (x, y, z)
/// and where each component of the value is an unsigned integer.
USampler3D,
/// A sampler for six square 2D images where each image represents one face of a cube.
/// It is indexed by a three coordinate direction from the center of the cube (x, y, z) where the magnitude of the coordinates do not matter.
/// The sampler follows the direction of the coordinates until it finds a place on one of the six faces of the cube.
/// Each component of the resulting value is an unsigned integer.
USamplerCube,
}
@@ -125,19 +165,26 @@ pub enum ShaderResourceKind {
/// missing by very specific value in the fallback texture.
fallback: SamplerFallback,
},
/// A list of properties with names and values that represents a uniform struct within the shader
/// and the default values for each field of the struct.
PropertyGroup(Vec<ShaderProperty>),
}
/// A data type and default value for a uniform within a shader.
/// When a material supplies an actual value, it is done using a `MaterialProperty` value
/// from the `fyrox-material` crate.
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Reflect, Visit)]
pub enum ShaderPropertyKind {
/// Real number.
Float {
/// Default value
#[serde(default)]
value: f32,
},
/// Real number array.
FloatArray {
/// Default value
value: Vec<f32>,
/// `max_len` defines the maximum number of elements in the shader.
max_len: usize,
@@ -145,12 +192,14 @@ pub enum ShaderPropertyKind {
/// Integer number.
Int {
/// Default value
#[serde(default)]
value: i32,
},
/// Integer number array.
IntArray {
/// Default value
value: Vec<i32>,
/// `max_len` defines the maximum number of elements in the shader.
max_len: usize,
@@ -158,12 +207,14 @@ pub enum ShaderPropertyKind {
/// Natural number.
UInt {
/// Default value
#[serde(default)]
value: u32,
},
/// Natural number array.
UIntArray {
/// Default value
value: Vec<u32>,
/// `max_len` defines the maximum number of elements in the shader.
max_len: usize,
@@ -171,18 +222,21 @@ pub enum ShaderPropertyKind {
/// Boolean value.
Bool {
/// Default value
#[serde(default)]
value: bool,
},
/// Two-dimensional vector.
Vector2 {
/// Default value
#[serde(default)]
value: Vector2<f32>,
},
/// Two-dimensional vector array.
Vector2Array {
/// Default value
value: Vec<Vector2<f32>>,
/// `max_len` defines the maximum number of elements in the shader.
max_len: usize,
@@ -190,12 +244,14 @@ pub enum ShaderPropertyKind {
/// Three-dimensional vector.
Vector3 {
/// Default value
#[serde(default)]
value: Vector3<f32>,
},
/// Three-dimensional vector array.
Vector3Array {
/// Default value
value: Vec<Vector3<f32>>,
/// `max_len` defines the maximum number of elements in the shader.
max_len: usize,
@@ -203,12 +259,14 @@ pub enum ShaderPropertyKind {
/// Four-dimensional vector.
Vector4 {
/// Default value
#[serde(default)]
value: Vector4<f32>,
},
/// Four-dimensional vector array.
Vector4Array {
/// Default value
value: Vec<Vector4<f32>>,
/// `max_len` defines the maximum number of elements in the shader.
max_len: usize,
@@ -216,12 +274,14 @@ pub enum ShaderPropertyKind {
/// 2x2 Matrix.
Matrix2 {
/// Default value
#[serde(default)]
value: Matrix2<f32>,
},
/// 2x2 Matrix array.
Matrix2Array {
/// Default value
value: Vec<Matrix2<f32>>,
/// `max_len` defines the maximum number of elements in the shader.
max_len: usize,
@@ -229,12 +289,14 @@ pub enum ShaderPropertyKind {
/// 3x3 Matrix.
Matrix3 {
/// Default value
#[serde(default)]
value: Matrix3<f32>,
},
/// 3x3 Matrix array.
Matrix3Array {
/// Default value
value: Vec<Matrix3<f32>>,
/// `max_len` defines the maximum number of elements in the shader.
max_len: usize,
@@ -242,12 +304,14 @@ pub enum ShaderPropertyKind {
/// 4x4 Matrix.
Matrix4 {
/// Default value
#[serde(default)]
value: Matrix4<f32>,
},
/// 4x4 Matrix array.
Matrix4Array {
/// Default value
value: Vec<Matrix4<f32>>,
/// `max_len` defines the maximum number of elements in the shader.
max_len: usize,
@@ -277,13 +341,17 @@ fn default_color_component() -> u8 {
255
}
/// A uniform value that is supplied to a shader by a material.
#[derive(Serialize, Deserialize, Debug, PartialEq, Reflect, Visit, Clone, Default)]
pub struct ShaderProperty {
/// The name of the value in the shader and when editing the value in the material.
pub name: ImmutableString,
/// The property's data type and default value.
pub kind: ShaderPropertyKind,
}
impl ShaderProperty {
/// Create a property with the given name and value.
pub fn new(name: impl Into<ImmutableString>, kind: ShaderPropertyKind) -> Self {
Self {
name: name.into(),
@@ -291,6 +359,7 @@ impl ShaderProperty {
}
}
/// Create a property with the 2x2 identity matrix as its value.
pub fn new_matrix2(name: impl Into<ImmutableString>) -> Self {
Self::new(
name,
@@ -300,6 +369,7 @@ impl ShaderProperty {
)
}
/// Create a property with the 3x3 identity matrix as its value.
pub fn new_matrix3(name: impl Into<ImmutableString>) -> Self {
Self::new(
name,
@@ -309,6 +379,7 @@ impl ShaderProperty {
)
}
/// Create a property with the 4x4 identity matrix as its value.
pub fn new_matrix4(name: impl Into<ImmutableString>) -> Self {
Self::new(
name,
@@ -318,6 +389,7 @@ impl ShaderProperty {
)
}
/// Create a property with the vector (0,0) as its value.
pub fn new_vector2(name: impl Into<ImmutableString>) -> Self {
Self::new(
name,
@@ -327,6 +399,7 @@ impl ShaderProperty {
)
}
/// Create a property with the vector (0,0,0) as its value.
pub fn new_vector3(name: impl Into<ImmutableString>) -> Self {
Self::new(
name,
@@ -336,6 +409,7 @@ impl ShaderProperty {
)
}
/// Create a property with the vector (0,0,0,0) as its value.
pub fn new_vector4(name: impl Into<ImmutableString>) -> Self {
Self::new(
name,
@@ -345,18 +419,22 @@ impl ShaderProperty {
)
}
/// Create a property with the float 0.0 as its value.
pub fn new_float(name: impl Into<ImmutableString>) -> Self {
Self::new(name, ShaderPropertyKind::Float { value: 0.0 })
}
/// Create a property with false as its value.
pub fn new_bool(name: impl Into<ImmutableString>) -> Self {
Self::new(name, ShaderPropertyKind::Bool { value: false })
}
/// Create a property with the integer 0 as its value.
pub fn new_int(name: impl Into<ImmutableString>) -> Self {
Self::new(name, ShaderPropertyKind::Int { value: 0 })
}
/// Create a property with white as its value.
pub fn new_color(name: impl Into<ImmutableString>) -> Self {
Self::new(
name,
@@ -369,6 +447,7 @@ impl ShaderProperty {
)
}
/// Create a property with an empty list of 4x4 matrices and the given maximum length for the list.
pub fn new_mat4_f32_array(name: impl Into<ImmutableString>, max_len: usize) -> Self {
Self::new(
name,
@@ -379,6 +458,7 @@ impl ShaderProperty {
)
}
/// Create a property with an empty list of floats and the given maximum length for the list.
pub fn new_f32_array(name: impl Into<ImmutableString>, max_len: usize) -> Self {
Self::new(
name,
@@ -389,6 +469,7 @@ impl ShaderProperty {
)
}
/// Create a property with an empty list of vectors and the given maximum length for the list.
pub fn new_vec4_f32_array(name: impl Into<ImmutableString>, max_len: usize) -> Self {
Self::new(
name,
@@ -399,6 +480,7 @@ impl ShaderProperty {
)
}
/// Create a property with an empty list of vectors and the given maximum length for the list.
pub fn new_vec3_f32_array(name: impl Into<ImmutableString>, max_len: usize) -> Self {
Self::new(
name,
@@ -409,6 +491,7 @@ impl ShaderProperty {
)
}
/// Create a property with an empty list of vectors and the given maximum length for the list.
pub fn new_vec2_f32_array(name: impl Into<ImmutableString>, max_len: usize) -> Self {
Self::new(
name,
@@ -435,14 +518,23 @@ impl Default for ShaderResourceKind {
/// Shader resource definition.
#[derive(Default, Serialize, Deserialize, Clone, Debug, PartialEq, Reflect, Visit)]
pub struct ShaderResourceDefinition {
/// A name of the resource.
/// The name of the uniform as it appears in the source code, ready to be passed to `glGetUniformLocation`.
/// If the name begins with "fyrox_" then Fyrox will treat it specially and try to automatically generate
/// the uniform's value based on its name, such as "fyrox_sceneDepth".
pub name: ImmutableString,
/// A kind of resource.
pub kind: ShaderResourceKind,
/// Each of a program's active uniform blocks has a corresponding uniform buffer binding point.
/// Binding points for active uniform blocks are assigned using `glUniformBlockBinding`.
/// For textures, `glUniform1i` is used to assign the texture's binding point to the texture uniform.
pub binding: usize,
}
impl ShaderResourceDefinition {
/// Fyrox provides certain resources to shaders automatically, without the resources needing
/// to be part of the material. This method is used by the `fyrox-impl` crate to decide whether
/// it should look for the resource in the material (if `false`) or whether it should assume
/// that this resource will be among the automatically provided resources.
pub fn is_built_in(&self) -> bool {
self.name.starts_with("fyrox_")
}
+71 -10
View File
@@ -18,7 +18,13 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//! This crate is an abstraction layer for graphical services like OpenGL.
//! See the [`server::GraphicsServer`] trait for the rendering features that are available through
//! this abstraction layer.
//! The `fyrox-graphics-gl` crate provides an OpenGL implementation of `GraphicsServer`.
#![allow(clippy::too_many_arguments)]
#![warn(missing_docs)]
pub use fyrox_core as core;
use std::fmt::Debug;
@@ -40,6 +46,24 @@ pub mod server;
pub mod stats;
pub mod uniform;
/// Define a wrapper struct that holds an `Rc` containing the given type.
/// It implements `Clone` to copy the `Rc` and
/// implements `Deref` to access the value inside the `Rc`.
///
/// For example: `define_shared_wrapper!(Example<usize>)` would expand to:
/// ```
/// #[derive(Clone)]
/// #[doc(hidden)]
/// pub struct Example(pub std::rc::Rc<usize>);
///
/// impl std::ops::Deref for Example {
/// type Target = usize;
///
/// fn deref(&self) -> &Self::Target {
/// self.0.deref()
/// }
/// }
/// ```
#[macro_export]
macro_rules! define_shared_wrapper {
($name:ident<$ty:ty>) => {
@@ -133,7 +157,10 @@ pub enum CompareFunc {
Always,
}
/// Defines a set values (per color) for blending operation.
/// Defines how some color will be multiplied before being blended.
/// The destination color is the color that is currently in the frame buffer,
/// and the source color is the color that is produced by the fragment shader.
/// See [`BlendFunc`] for more about how to use these.
#[derive(
Copy,
Clone,
@@ -153,25 +180,45 @@ pub enum CompareFunc {
Default,
)]
pub enum BlendFactor {
/// The color is multiplied by zero, turning it black.
#[default]
Zero,
/// The color is multiplied by one, leaving it unchanged.
One,
/// The color is multiplied by the source color.
SrcColor,
/// The color is multiplied by (1 - src), the inverted source color.
OneMinusSrcColor,
/// The color is multiplied by the destination color.
DstColor,
/// The color is multiplied by (1 - dst), the inverted destination color.
OneMinusDstColor,
/// The color is multiplied by the alpha of the source color.
SrcAlpha,
/// The color is multiplied by (1 - alpha), the inverted alpha of the source color.
OneMinusSrcAlpha,
/// The color is multiplied by the alpha of the destination color.
DstAlpha,
/// The color is multiplied by (1 - alpha), the inverted alpha of the destination color.
OneMinusDstAlpha,
/// The color is multiplied by the blend constant.
ConstantColor,
/// The color is multiplied by (1 - constant), the inverted blend constant.
OneMinusConstantColor,
/// The color is multiplied by the alpha of the blend constant.
ConstantAlpha,
/// The color is multiplied by (1 - alpha), the inverted alpha of the blend constant.
OneMinusConstantAlpha,
/// Red, green, and blue channels are multiplied by min(src alpha, 1 - dst alpha),
/// and the alpha channel is multiplied by 1.
SrcAlphaSaturate,
/// The color is multiplied by the color of the second source.
Src1Color,
/// The color is multiplied by (1 - src1), the inverted color of the second source.
OneMinusSrc1Color,
/// The color is multiplied by the alpha of the second source.
Src1Alpha,
/// The color is multiplied by (1 - alpha), the inverted alpha of the second source.
OneMinusSrc1Alpha,
}
@@ -229,21 +276,21 @@ pub struct BlendEquation {
pub alpha: BlendMode,
}
/// Blending function defines sources of data for both operands in blending equation (separately
/// Blending function defines factors for both operands in blending equation (separately
/// for RGB and Alpha parts). Default blending function is replacing destination values with the
/// source ones.
#[derive(
Copy, Clone, PartialOrd, PartialEq, Ord, Eq, Hash, Serialize, Deserialize, Visit, Debug, Reflect,
)]
pub struct BlendFunc {
/// Data for source (the value that is produced by a shader) in the blending equation (RGB part).
/// Factor for the source (the value that is produced by a shader) in the blending equation (RGB part).
pub sfactor: BlendFactor,
/// Data for destination (the value that is already in a frame buffer) in the blending equation
/// Factor for the destination (the value that is already in a frame buffer) in the blending equation
/// (RGB part).
pub dfactor: BlendFactor,
/// Data for source (the value that is produced by a shader) in the blending equation (alpha part).
/// Factor for the source (the value that is produced by a shader) in the blending equation (alpha part).
pub alpha_sfactor: BlendFactor,
/// Data for destination (the value that is already in a frame buffer) in the blending equation
/// Factor for the destination (the value that is already in a frame buffer) in the blending equation
/// (alpha part).
pub alpha_dfactor: BlendFactor,
}
@@ -353,12 +400,16 @@ pub enum PolygonFace {
FrontAndBack,
}
/// Defines a function that used in a stencil test.
/// Defines a function that used in a stencil test by comparing the `ref_value` to the stencil buffer.
#[derive(
Copy, Clone, PartialOrd, PartialEq, Hash, Debug, Serialize, Deserialize, Visit, Eq, Reflect,
)]
pub struct StencilFunc {
/// A function that is used to compare two values. Default value is [`CompareFunc::Always`].
/// The function that is used to compare the stencil buffer value against `ref_value`.
/// In this case the incoming value is `ref_value` and the stored value is the stencil buffer value
/// for the pixel. So [`CompareFunc::Less`] which means `ref_value` must be less than the stencil buffer value
/// or else the pixel will not draw.
/// Default value is [`CompareFunc::Always`], which means draw every pixel.
pub func: CompareFunc,
/// Reference value that is used to compare against the current value in the stencil buffer.
/// Default value is 0.
@@ -442,11 +493,20 @@ pub struct StencilOp {
pub zfail: StencilAction,
/// An action that happens when the depth test has passed.
pub zpass: StencilAction,
/// A mask that is used to filter out some bits (using `AND` logical operation) from the source
/// value before writing it to the stencil buffer.
/// Specifies a bit mask to enable and disable writing of individual bits in the stencil planes. Initially, the mask is all 1's,
/// which means that all bits of the stencil buffer may be written by the stencil operations specified in `stencil_op`.
/// 0 bits protect the corresponding bits of the stencil from changing.
pub write_mask: u32,
}
impl StencilOp {
/// Compare the actions of this `StencilOp` with the actions of another `StencilOp`. True if all actions match.
/// This comparison ignores the `write_mask`.
pub fn eq_actions(&self, other: &StencilOp) -> bool {
self.fail == other.fail && self.zfail == other.zfail && self.zpass == other.zpass
}
}
impl Default for StencilOp {
fn default() -> Self {
Self {
@@ -568,6 +628,7 @@ pub enum ElementKind {
}
impl ElementKind {
/// The number of indices that are required to represent the element.
pub fn index_per_element(self) -> usize {
match self {
ElementKind::Triangle => 3,
+25
View File
@@ -18,6 +18,10 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//! A [`GpuAsyncReadBufferTrait`] object handles the transfering pixel data from a frame buffer
//! into a color buffer in the background, and provides a method to poll the object and take the
//! data once it arrives.
use crate::{
core::math::Rect, define_shared_wrapper, error::FrameworkError,
framebuffer::GpuFrameBufferTrait,
@@ -27,18 +31,39 @@ use fyrox_core::define_as_any_trait;
define_as_any_trait!(GpuAsyncReadBufferAsAny => GpuAsyncReadBufferTrait);
/// Trait for objects that represent a request to transfer pixel data from some frame buffer
/// into a color buffer.
pub trait GpuAsyncReadBufferTrait: GpuAsyncReadBufferAsAny {
/// Begin the pixel data transfer by specifying a particular attachment of a particular framebuffer to read from.
/// * `framebuffer`: The source of the data.
/// * `color_buffer_index`: The index of the color attachment of the framebuffer.
/// * `rect`: The portion of the framebuffer to read.
///
/// After this is called, [`is_request_running`](GpuAsyncReadBufferTrait::is_request_running) will
/// return true.
fn schedule_pixels_transfer(
&self,
framebuffer: &dyn GpuFrameBufferTrait,
color_buffer_index: u32,
rect: Option<Rect<i32>>,
) -> Result<(), FrameworkError>;
/// Return true if a request has been made and the data has not yet been
/// retrieved with [`try_read`](GpuAsyncReadBufferTrait::try_read).
/// Returning false does *not* indicate that the data is read; this method
/// will continue to return true long after the data is read, until `try_read` is
/// called to actually read the data.
fn is_request_running(&self) -> bool;
/// Check the state of the data and return the data if it is read, or else
/// return None. After the data is returned, [`is_request_running`](GpuAsyncReadBufferTrait::is_request_running)
/// will return false.
fn try_read(&self) -> Option<Vec<u8>>;
}
impl dyn GpuAsyncReadBufferTrait {
/// Check the state of the data and return the data if it is read, or else
/// return None. The data is converted into the given type before being returned.
/// After the data is returned, [`is_request_running`](GpuAsyncReadBufferTrait::is_request_running)
/// will return false.
pub fn try_read_of_type<T>(&self) -> Option<Vec<T>>
where
T: Pod,
+4
View File
@@ -18,6 +18,9 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//! A sampler is a GPU entity that defines how texels will be fetched from a texture. See [`GpuSamplerDescriptor`]
//! docs for more info.
use crate::define_shared_wrapper;
use fyrox_core::define_as_any_trait;
use std::fmt::Debug;
@@ -70,6 +73,7 @@ impl Default for GpuSamplerDescriptor {
}
impl GpuSamplerDescriptor {
/// Create a sampler for a rander target.
pub fn new_rt_sampler() -> Self {
Self {
min_filter: MinificationFilter::Nearest,
+4 -1
View File
@@ -197,7 +197,10 @@ pub trait GraphicsServer: GraphicsServerAsAny {
/// Returns current capabilities of the graphics server. See [`ServerCapabilities`] for more info.
fn capabilities(&self) -> ServerCapabilities;
/// Sets current polygon fill mode. See [`PolygonFace`] and [`PolygonFillMode`] docs for more info.
/// Sets current polygon fill mode for front faces, back faces, or both.
/// The mode of front faces is controlled separately from the mode of back faces,
/// and `polygon_face` determines which mode is set by this method.
/// See [`PolygonFace`] and [`PolygonFillMode`] docs for more info.
fn set_polygon_fill_mode(&self, polygon_face: PolygonFace, polygon_fill_mode: PolygonFillMode);
/// Generates mipmaps for the given texture. Graphics server implementation can pick any desired
+3
View File
@@ -18,6 +18,9 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//! Structs to keep count of the numbers of various operations that are performed during
//! rendering.
use crate::framebuffer::DrawCallStatistics;
use std::fmt::{Display, Formatter};
+9 -3
View File
@@ -172,18 +172,24 @@ impl Default for SurfaceInstanceData {
}
/// A set of surface instances that share the same vertex/index data and a material.
/// Geometry instancing means rendering multiple copies of the same mesh in a scene at once,
/// reusing the same vertex data but with a different world transform each time.
/// This technique can be used for objects such as trees that may need to be repeated many times in a scene.
/// See [`SurfaceInstanceData`] for the properties that can change between instances of the bundle.
pub struct RenderDataBundle {
/// A pointer to shared surface data.
/// A pointer to shared surface data, such as vertices, triangle indices, and blend shapes.
pub data: SurfaceResource,
/// Amount of time (in seconds) for GPU geometry buffer (vertex + index buffers) generated for
/// the `data`.
pub time_to_live: TimeToLive,
/// A set of instances.
/// A set of instances, each with their own world transform and other properties.
pub instances: Vec<SurfaceInstanceData>,
/// A material that is shared across all instances.
pub material: MaterialResource,
/// A render path of the bundle.
pub render_path: RenderPath,
/// The priority of this bundle when sorting the bundles to determine which will be rendered
/// first. Bundles with lower values are rendered before bundles with higher values.
sort_index: u64,
}
@@ -210,7 +216,7 @@ pub struct InstanceUniformData {
/// Describes where to the actual uniform data is located in the memory backed by the uniform
/// memory allocator on per-bundle basis.
pub struct BundleUniformData {
/// Material info block location.
/// Material info block location in the form of (binding point, position within allocator)
pub material_property_group_blocks: Vec<(usize, UniformBlockLocation)>,
/// Lights info block location.
pub light_data_block: UniformBlockLocation,
+4
View File
@@ -128,10 +128,14 @@ struct Page {
is_submitted: bool,
}
/// The position of a uniform within a [`UniformMemoryAllocator`].
#[derive(Clone, Copy, Debug)]
pub struct UniformBlockLocation {
/// Index of the buffer in the buffer list of [`UniformMemoryAllocator`].
pub page: usize,
/// The position of the uniform within the buffer.
pub offset: usize,
/// The size of the uniform.
pub size: usize,
}
+4
View File
@@ -141,7 +141,11 @@ impl ObserversCollection {
}
}
/// An Observer holds all the information required to render a scene from a particular point of view,
/// including everything except the actual scene to be rendered.
/// Observers are naturally constructed using the data from some camera in the scene.
pub struct Observer {
/// The handle of the camera that was used to create this Observer.
pub handle: Handle<Node>,
pub cube_map_face: Option<CubeMapFace>,
pub render_target: Option<TextureResource>,