RenderHelp可編程渲染管線實現(xiàn)
RenderHelp 是可編程渲染管線實現(xiàn),全中文注釋,幫助初學(xué)者學(xué)習(xí)渲染原理。
特性介紹
- 單個 RenderHelp.h 文件,從畫點開始實現(xiàn)可編程渲染管線,無外部依賴。
- 模型標(biāo)準(zhǔn),計算精確,使用類 Direct3D 接口。
- 包含一套完整的矢量/矩陣庫。
- 包含一套位圖 Bitmap 庫,方便畫點、畫線、加載紋理、紋理采樣等。
- 使用 C++ 編寫頂點著色器 (Vertex Shader) 和像素著色器 (Pixel Shader),方便斷點和調(diào)試。
- 使用 Edge Equation 精確計算三角形覆蓋范圍,處理好鄰接三角形的邊界。
- 使用重心坐標(biāo)公式計算 varying 插值。
- 使用 1/w 進行透視矯正,繪制透視正確的紋理。
- 使用二次線性插值進行采樣,更好的渲染效果。
- 核心渲染實現(xiàn)僅 200 行,突出易讀性。
- 寫滿中文注釋,每一處計算都有解釋。
- 多個教程例子,從如何畫三角形到模型以及光照。
編譯運行
隨便找個 sample_ 開頭的例子文件直接 gcc 單文件編譯即可:
gcc -O2 sample_07_specular.cpp -o sample_07_specular -lstdc++
在 Mac 下好像要加個 -std=c++17,我應(yīng)該沒用啥 17 的東西,不過沒環(huán)境不太確定。某些平臺下可能要加一個 -lm ,顯示聲明一下鏈接數(shù)學(xué)庫。
運行:
./sample_07_specular
然后得到一個圖片文件 output.bmp:
編程接口
著色器變量
主要使用一個 ShaderContext 的結(jié)構(gòu)體,用于 VS->PS 之間傳參,里面都是一堆各種類型的 varying。
// 著色器上下文,由 VS 設(shè)置,再由渲染器按像素逐點插值后,供 PS 讀取
struct ShaderContext {
std::map<int, float> varying_float; // 浮點數(shù) varying 列表
std::map<int, Vec2f> varying_vec2f; // 二維矢量 varying 列表
std::map<int, Vec3f> varying_vec3f; // 三維矢量 varying 列表
std::map<int, Vec4f> varying_vec4f; // 四維矢量 varying 列表
};
頂點著色器
外層需要提供給渲染器 VS 的函數(shù)指針,并在渲染器的 DrawPrimitive 函數(shù)進行頂點初始化時對三角形的三個頂點依次調(diào)用:
// 頂點著色器:因為是 C++ 編寫,無需傳遞 attribute,傳個 0-2 的頂點序號 // 著色器函數(shù)直接在外層根據(jù)序號讀取響應(yīng)數(shù)據(jù)即可,最后需要返回一個坐標(biāo) pos // 各項 varying 設(shè)置到 output 里,由渲染器插值后傳遞給 PS typedef std::function<Vec4f(int index, ShaderContext &output)> VertexShader;
每次調(diào)用時,渲染器會依次將三個頂點的編號 0, 1, 2 通過 index 字段傳遞給 VS 程序,方便從外部讀取頂點數(shù)據(jù)。
像素著色器
渲染器對三角形內(nèi)每個需要填充的點調(diào)用像素著色器:
// 像素著色器:輸入 ShaderContext,需要返回 Vec4f 類型的顏色 // 三角形內(nèi)每個點的 input 具體值會根據(jù)前面三個頂點的 output 插值得到 typedef std::function<Vec4f(ShaderContext &input)> PixelShader;
像素著色程序返回的顏色會被繪制到 Frame Buffer 的對應(yīng)位置。
繪制三角形
調(diào)用下面接口可以繪制一個三角形:
bool RenderHelp::DrawPrimitive()
該函數(shù)是渲染器的核心,先依次調(diào)用 VS 初始化頂點,獲得頂點坐標(biāo),然后進行齊次空間裁剪,歸一化后得到三角形的屏幕坐標(biāo)。
然后兩層 for 循環(huán)迭代屏幕上三角形外接矩形的每個點,判斷在三角形范圍內(nèi)以后就調(diào)用 VS 程序計算該點具體是什么顏色。
評論
圖片
表情
