From 6e004da8daecf761a3bbb325b8c7b72cfb16d3df Mon Sep 17 00:00:00 2001 From: greyishsong Date: Tue, 17 Sep 2024 23:41:02 +0800 Subject: [PATCH] docs: new rasterization pipeline and some corrections --- src/render/graphics_interface.h | 92 +++++++++++++++++++++----------- src/render/rasterizer.h | 30 ++++------- src/render/rasterizer_renderer.h | 13 +++-- src/render/render_engine.h | 37 +++++++------ src/render/triangle.h | 1 + 5 files changed, 102 insertions(+), 71 deletions(-) diff --git a/src/render/graphics_interface.h b/src/render/graphics_interface.h index c32c403..4d4923f 100644 --- a/src/render/graphics_interface.h +++ b/src/render/graphics_interface.h @@ -12,25 +12,33 @@ #include "../scene/scene.h" /*! - * \file render/shader.h + * \file render/graphics_interface.h * \ingroup rendering * \~chinese - * \brief 软渲染器使用的模拟着色器。 + * \brief 一些公用的渲染管线接口。 */ +/*! + * \ingroup rendering + * \~chinese + * \brief 顶点着色器的输入和输出单位。 + */ struct VertexShaderPayload { /*! \~chinese 顶点世界坐标系坐标 */ Eigen::Vector4f world_position; /*! \~chinese 顶点视口坐标系坐标 */ Eigen::Vector4f viewport_position; - /*! \~chinese 法线向量 */ + /*! \~chinese 顶点法线 */ Eigen::Vector3f normal; }; /*! + * \ingroup rendering * \~chinese - * \brief 作用于每个屏幕上的片元,通常是计算颜色。 + * \brief 片元着色器的输入单位。 + * + * “片元”相当于未着色的像素,每个片元数据中均包含为该片元着色所需的局部信息(全局信息则位于 `Uniforms` 中)。 */ struct FragmentShaderPayload { @@ -38,17 +46,18 @@ struct FragmentShaderPayload Eigen::Vector3f world_pos; /*! \~chinese 世界坐标系下的法向量 */ Eigen::Vector3f world_normal; - /*! \~chinese 屏幕的像素坐标*/ + /*! \~chinese 屏幕空间坐标 */ int x, y; - /*! \~chinese 当前片元的深度*/ + /*! \~chinese 当前片元的深度 */ float depth; - /*! \~chinese 当前片元的颜色*/ + /*! \~chinese 当前片元的颜色 */ Eigen::Vector3f color; }; /*! + * \ingroup rendering * \~chinese - * \brief 计算顶点的各项属性几何变化 + * \brief 计算顶点的各项属性几何变化。 * * 首先是将顶点坐标变换到投影平面,再进行视口变换; * 其次是将法线向量变换到世界坐标系 @@ -59,24 +68,22 @@ struct FragmentShaderPayload VertexShaderPayload vertex_shader(const VertexShaderPayload& payload); /*! + * \ingroup rendering * \~chinese - * \brief 计算每个片元(像素)的颜色 - * - * 根据输入参数:计算好的片元的位置和法线方向;材质(ka,kd,ks);场景光源以及视角 - * 计算当前片元的颜色 + * \brief 使用 Blinn Phong 着色模型计算每个片元(像素)的颜色。 * * \param payload 装的是相机坐标系下的片元位置以及法向量 - * \param material 当前片元所在物体的材质,包括ka,kd,ks + * \param material 当前片元所在物体的材质,包括环境光、漫反射和镜面反射系数等 * \param lights 当前场景中的所有光源 - * \param camera 当前观察相机 - * + * \param camera 离线渲染所用的相机 */ Eigen::Vector3f phong_fragment_shader(const FragmentShaderPayload& payload, const GL::Material& material, const std::list& lights, const Camera& camera); /*! + * \ingroup rendering * \~chinese - * \brief 用于选择buffer的类型 + * \brief 用于选择 buffer 的类型 */ enum class BufferType { @@ -94,36 +101,50 @@ inline BufferType operator&(BufferType a, BufferType b) return BufferType((int)a & (int)b); } +/*! + * \ingroup utils + * \~chinese + * \brief 自旋锁 + * + * 一个比较高效的自旋锁实现,做了局部自旋和主动退避优化。 + */ class SpinLock { public: + /*! \~chinese 加锁。 */ void lock(); + /*! \~chinese 解锁。 */ void unlock(); private: + /*! \~chinese 内部用于实现锁的原子变量。 */ std::atomic_flag locked; }; /*! * \ingroup rendering * \~chinese - * \brief color buffer以及depth buffer + * \brief 一个最简化的 Frame Buffer 。 + * + * 要渲染一帧,通常至少需要一个 color buffer 用于输出颜色、一个 depth buffer 用于记录深度。 */ class FrameBuffer { public: + /*! \~chinese 初始化一个 frame buffer 。 */ FrameBuffer(int width, int height); + /*! \~chinese Frame buffer 对应图像的宽度和高度 */ int width, height; /*! * \~chinese * \brief 设置当前像素点的颜色 * - * 根据计算出的index,对frame buffer中的color buffer和 - * depth buffer进行填充 + * 根据计算出的 index,对 frame buffer 中的 color buffer 和 + * depth buffer 进行填充 * - * \param index 填充位置对应的索引 + * \param index 填充位置对应的一维索引 * \param depth 当前着色点计算出的深度 * \param color 当前着色点计算出的颜色值 */ @@ -131,32 +152,33 @@ class FrameBuffer /*! * \~chinese - * \brief 将color buffer和depth buffer内容初始化 + * \brief 初始化指定类型的 buffer。 * - * color buffer最后会传递给rendering_res,所以可以直接初始化为背景颜色, - * depth buffer则可以初始化为最大值 + * color buffer 最后会传递给 rendering_res,所以可以直接初始化为背景颜色 + * depth buffer 则可以初始化为最大值 * - * \param buff 根据传入的buffer类型,初始化相应类型的buffer + * \param buff 根据传入的 buffer 类型,初始化相应类型的 buffer */ void clear(BufferType buff); - /*! \~chinese frame buffer的存储元素为Eigen::Vector3f,范围在[0,255],三个分量分别表示(R,G,B) */ + /*! \~chinese color buffer 的存储元素为 Eigen::Vector3f,范围在 [0,255],三个分量分别表示 (R,G,B) */ std::vector color_buffer; - /*! \~chinese depth buffer也可以叫做z-buffer,用于判断像素点相较于观察点的前后关系 */ + /*! \~chinese depth buffer 也可以叫做 z-buffer,用于判断像素点相较于观察点的前后关系 */ std::vector depth_buffer; private: - /*! \~chinese spin_locks用于在深度测试和着色时对depth buffer以及frame buffer加锁*/ + /*! \~chinese 用于在深度测试和着色时对相应位置的像素加锁 */ std::vector spin_locks; }; /*! + * \ingroup rendering * \~chinese - * \brief 用于存储RasterizerRenderer所需的全局变量 + * \brief 用于存储 RasterizerRenderer 所需的全局变量。 */ struct Uniforms { - /*! \~chinese 当前渲染物体的MVP矩阵 */ + /*! \~chinese 当前渲染物体的 MVP 矩阵 */ static Eigen::Matrix4f MVP; /*! \~chinese 当前渲染物体的model.inverse().transpose() */ static Eigen::Matrix4f inv_trans_M; @@ -174,6 +196,11 @@ struct Uniforms static Camera& camera; }; +/*! + * \ingroup rendering + * \~chinese + * \brief 存放实现渲染管线所需的一些全局数据。 + */ struct Context { /*!\~chinese 保护队列的互斥锁 */ @@ -185,12 +212,15 @@ struct Context /*! \~chinese rasterizer的输出队列 */ static std::queue rasterizer_output_queue; + /*! \~chinese 标识顶点着色器是否全部执行完毕。 */ static bool vertex_finish; + /*! \~chinese 标识三角形是否全部被光栅化。 */ static bool rasterizer_finish; + /*! \~chinese 标识片元着色器是否全部执行完毕。 */ static bool fragment_finish; - /*! \~chinese 渲染使用的frame buffer(color buffer & depth buffer)*/ + /*! \~chinese 渲染使用的 frame buffer 。 */ static FrameBuffer frame_buffer; }; -#endif // DANDELION_RENDER_GRAPHICS_INTERFACE_H \ No newline at end of file +#endif // DANDELION_RENDER_GRAPHICS_INTERFACE_H diff --git a/src/render/rasterizer.h b/src/render/rasterizer.h index 2dbb859..46b6f8c 100644 --- a/src/render/rasterizer.h +++ b/src/render/rasterizer.h @@ -19,10 +19,10 @@ #include "rasterizer_renderer.h" /*! - * \file render/rasterizer_mt.h + * \file render/rasterizer.h * \ingroup rendering * \~chinese - * 给定材质、Model/View/Projection Matrix 的光栅化器。 + * \brief 光栅化渲染器中光栅化阶段的实现。 */ float sign(Eigen::Vector2f p1, Eigen::Vector2f p2, Eigen::Vector2f p3); @@ -30,37 +30,25 @@ float sign(Eigen::Vector2f p1, Eigen::Vector2f p2, Eigen::Vector2f p3); /*! * \ingroup rendering * \~chinese - * \brief 软光栅渲染器 - * - * 这个类主要由光栅化所需的各种属性(如成像平面的长宽,以及M,V,P矩阵等),以及光栅化 - * 整个流程所需的各种操作对应的函数构成(如vertex shader, fragment shader,等) + * \brief 光栅化器 */ class Rasterizer { public: void worker_thread(); - void rasterize_triangle(Triangle& t); private: /*! * \~chinese - * \brief 光栅化当前三角形 - * - * 整个光栅化渲染应当包含:VERTEX SHADER -> MVP -> Clipping -> VIEWPORT -> DRAWLINE/DRAWTRI -> - * FRAGMENT SHADER 在进入rasterize_triangle之前已经完成了VERTEX - * SHADER到VIEWPORT的整个过程,可以被看作几何阶段 - * 在进入rasterize_triangle之后,就开始进行真正的光栅化了,逐片元的进行着色 + * \brief 将指定三角形光栅化为片元。 * - * \param t 当前进行光栅化的三角形 - * \param world_pos 三角形三个顶点的坐标(已经变换到world_space下) - * \param material 当前三角形所在物体的材质 - * \param lights 当前场景的所有光源(已经变换到world_space下) - * \param camera 当前使用的相机(观察点) + * \param t 要进行光栅化的三角形 */ + void rasterize_triangle(Triangle& t); - /*! \~chinese 判断像素坐标(x,y)是否在给定三个顶点的三角形内 */ + /*! \~chinese 判断像素坐标 (x,y) 是否在给定三个顶点的三角形内 */ static bool inside_triangle(int x, int y, const Eigen::Vector4f* vertices); - /*! \~chinese 计算像素坐标(x,y)在给定三个顶点的三角形内的重心坐标 */ + /*! \~chinese 计算像素坐标 (x,y) 在给定三个顶点的三角形内的重心坐标 */ static std::tuple compute_barycentric_2d(float x, float y, const Eigen::Vector4f* v); /*! @@ -71,7 +59,7 @@ class Rasterizer * * \param alpha, beta, gamma 计算出的重心坐标 * \param vert1, vert2, vert3 三角形的三个顶点的任意待插值属性 - * \param weight Vector3f{v[0].w(), v[1].w(), v[2].w()} + * \param weight 三个顶点的 w 坐标 (`Vector3f{v[0].w(), v[1].w(), v[2].w()}`) * \param Z 1 / (alpha / v[0].w() + beta / v[1].w() + gamma / v[2].w()); */ static Eigen::Vector3f interpolate(float alpha, float beta, float gamma, diff --git a/src/render/rasterizer_renderer.h b/src/render/rasterizer_renderer.h index bcad8f5..e0194ff 100644 --- a/src/render/rasterizer_renderer.h +++ b/src/render/rasterizer_renderer.h @@ -13,11 +13,11 @@ #include "../scene/camera.h" #include "graphics_interface.h" -using Eigen::Vector3f; - /*! + * \file render/rasterizer_renderer.h + * \ingroup rendering * \~chinese - * \brief 作用于每个顶点,通常是处理从世界空间到屏幕空间的坐标变化,后面紧接着光栅化。 + * \brief 光栅化渲染器中顶点处理、片元处理两个阶段的实现。 */ class VertexProcessor { @@ -31,6 +31,11 @@ class VertexProcessor std::mutex queue_mutex; }; +/*! + * \ingroup rendering + * \~chinese + * \brief 负责执行片元着色器的工作线程。 + */ class FragmentProcessor { public: @@ -43,4 +48,4 @@ class FragmentProcessor private: }; -#endif // DANDELION_RENDER_RASTERIZER_RENDERER_H \ No newline at end of file +#endif // DANDELION_RENDER_RASTERIZER_RENDERER_H diff --git a/src/render/render_engine.h b/src/render/render_engine.h index 73f8fc8..32b3eb3 100644 --- a/src/render/render_engine.h +++ b/src/render/render_engine.h @@ -16,11 +16,19 @@ /*! * \file render/render_engine.h + * \ingroup rendering + * \~chinese + * \brief 定义了渲染引擎和渲染器。 */ class RasterizerRenderer; class WhittedRenderer; +/*! + * \ingroup rendering + * \~chinese + * \brief 可用的渲染器类型 + */ enum class RendererType { RASTERIZER, @@ -31,7 +39,7 @@ enum class RendererType /*! * \ingroup rendering * \~chinese - * \brief 负责实现整个渲染的接口 + * \brief 离线渲染的执行入口 */ class RenderEngine { @@ -40,14 +48,14 @@ class RenderEngine /*! \~chinese 渲染的结果(以无符号字符型变量进行存储)*/ std::vector rendering_res; - /*! \~chinese 根据aspect_ratio对渲染出图片的长和宽进行设置*/ + /*! \~chinese 根据aspect_ratio对渲染出图片的长和宽进行设置 */ float width, height; - /*! \~chinese whitted_style renderer使用多线程时的线程数设置*/ + /*! \~chinese whitted_style renderer使用多线程时的线程数设置 */ int n_threads; /*! * \~chinese - * \brief 渲染器的渲染函数 + * \brief 离线渲染入口,负责调用渲染器的渲染函数 * * 可以选择不同的渲染方式,在设置好场景之后,执行该函数能够得到 * 使用选定方式对当前场景的渲染结果 @@ -56,19 +64,19 @@ class RenderEngine * \param type 渲染器类型 */ void render(Scene& scene, RendererType type); - /*! \~chinese 渲染结果预览的背景颜色*/ + /*! \~chinese 渲染结果预览的背景颜色 */ static Eigen::Vector3f background_color; - /*! \~chinese 光栅化渲染器*/ + /*! \~chinese 光栅化渲染器 */ std::unique_ptr rasterizer_render; - /*! \~chinese whitted style渲染器*/ + /*! \~chinese whitted style渲染器 */ std::unique_ptr whitted_render; }; /*! * \ingroup rendering * \~chinese - * \brief 负责实现Rasterizition的整个pipeline + * \brief 实现光栅化渲染管线。 */ class RasterizerRenderer { @@ -105,20 +113,20 @@ class RasterizerRenderer /*! * \ingroup rendering * \~chinese - * \brief 负责实现Whitted_style的整个pipeline + * \brief 实现 Whitted-Style 光线追踪管线。 */ class WhittedRenderer { public: WhittedRenderer(RenderEngine& engine); - /*! \~chinese whitted-style渲染器的渲染调用接口*/ + /*! \~chinese whitted-style渲染器的渲染调用接口 */ void render(Scene& scene); - /*! \~chinese 镜面反射的阈值为material.shiness>=1000*/ + /*! \~chinese 镜面反射的阈值 */ static constexpr float mirror_threshold = 1000.0f; float& width; float& height; int& n_threads; - /*! \~chinese 是否使用BVH进行加速*/ + /*! \~chinese 是否使用 BVH 进行加速*/ bool use_bvh; std::vector& rendering_res; @@ -136,12 +144,11 @@ class WhittedRenderer std::optional> trace(const Ray& ray, const Scene& scene); /*! * \~chinese - * \brief 实现光线追踪 + * \brief 追踪指定光线得到颜色 * * \param ray 当前追踪的光线 * \param scene 当前渲染的场景 - * \param depth 当前反射的次数 - * + * \param depth 最大反射次数 */ Eigen::Vector3f cast_ray(const Ray& ray, const Scene& scene, int depth); std::shared_ptr logger; diff --git a/src/render/triangle.h b/src/render/triangle.h index 8f6b605..6dc9455 100644 --- a/src/render/triangle.h +++ b/src/render/triangle.h @@ -5,6 +5,7 @@ #include /*! + * \ingroup rendering * \file render/triangle.h */