Skip to content

Commit

Permalink
docs: new rasterization pipeline and some corrections
Browse files Browse the repository at this point in the history
  • Loading branch information
greyishsong authored and greyishsong committed Sep 17, 2024
1 parent a6a23c6 commit 6e004da
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 71 deletions.
92 changes: 61 additions & 31 deletions src/render/graphics_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,43 +12,52 @@
#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
{
/*! \~chinese 世界坐标系下的位置 */
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 计算顶点的各项属性几何变化
*
* 首先是将顶点坐标变换到投影平面,再进行视口变换;
* 其次是将法线向量变换到世界坐标系
Expand All @@ -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<Light>& lights, const Camera& camera);

/*!
* \ingroup rendering
* \~chinese
* \brief 用于选择buffer的类型
* \brief 用于选择 buffer 的类型
*/
enum class BufferType
{
Expand All @@ -94,69 +101,84 @@ 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 当前着色点计算出的颜色值
*/
void set_pixel(int index, float depth, const Eigen::Vector3f& color);

/*!
* \~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<Eigen::Vector3f> color_buffer;
/*! \~chinese depth buffer也可以叫做z-buffer,用于判断像素点相较于观察点的前后关系 */
/*! \~chinese depth buffer 也可以叫做 z-buffer,用于判断像素点相较于观察点的前后关系 */
std::vector<float> depth_buffer;

private:
/*! \~chinese spin_locks用于在深度测试和着色时对depth buffer以及frame buffer加锁*/
/*! \~chinese 用于在深度测试和着色时对相应位置的像素加锁 */
std::vector<SpinLock> 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;
Expand All @@ -174,6 +196,11 @@ struct Uniforms
static Camera& camera;
};

/*!
* \ingroup rendering
* \~chinese
* \brief 存放实现渲染管线所需的一些全局数据。
*/
struct Context
{
/*!\~chinese 保护队列的互斥锁 */
Expand All @@ -185,12 +212,15 @@ struct Context
/*! \~chinese rasterizer的输出队列 */
static std::queue<FragmentShaderPayload> 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
#endif // DANDELION_RENDER_GRAPHICS_INTERFACE_H
30 changes: 9 additions & 21 deletions src/render/rasterizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,48 +19,36 @@
#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);

/*!
* \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<float, float, float> compute_barycentric_2d(float x, float y,
const Eigen::Vector4f* v);
/*!
Expand All @@ -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,
Expand Down
13 changes: 9 additions & 4 deletions src/render/rasterizer_renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand All @@ -31,6 +31,11 @@ class VertexProcessor
std::mutex queue_mutex;
};

/*!
* \ingroup rendering
* \~chinese
* \brief 负责执行片元着色器的工作线程。
*/
class FragmentProcessor
{
public:
Expand All @@ -43,4 +48,4 @@ class FragmentProcessor
private:
};

#endif // DANDELION_RENDER_RASTERIZER_RENDERER_H
#endif // DANDELION_RENDER_RASTERIZER_RENDERER_H
Loading

0 comments on commit 6e004da

Please sign in to comment.