日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

output怎么用_如何用 C++ 写一个可编程软件渲染器?

發(fā)布時間:2023/12/15 c/c++ 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 output怎么用_如何用 C++ 写一个可编程软件渲染器? 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

今天你想用最新的 D3D12 畫一個三角形,少說也要上千行代碼了,對于初學(xué)者來講,這個門檻是非常高的,太多干擾了,而一千多行代碼,已經(jīng)足夠你重頭實(shí)現(xiàn)一個簡易版 D3D 了,為什么不呢?比起從圖形 API 入門,不如從畫點(diǎn)開始,同樣一千行代碼,卻能讓你對 GPU 的工作原理有一個直觀的了解。

因此,為了讓希望學(xué)習(xí)渲染的人更快入門,我開源了一個 C++ 實(shí)現(xiàn)可編程渲染管線的教程:

skywind3000/RenderHelp

那么網(wǎng)上軟件渲染器其實(shí)不少,這個 RenderHelp 和他們有什么區(qū)別么?區(qū)別有三:

  • 實(shí)現(xiàn)精簡,沒依賴,就是一個 RenderHelp.h 文件,單獨(dú) include 它就能編譯了,不用復(fù)雜的工程,導(dǎo)入一堆源文件,vim/vscode 里設(shè)置個 gcc 命令行,F9 編譯單文件即可。
  • 模型標(biāo)準(zhǔn),計(jì)算精確,網(wǎng)上很多軟渲染器實(shí)現(xiàn)有很多大大小小的問題:比如紋理不是透視正確的,比如鄰接三角形的邊沒有處理正確,比如 Edge Equation 其實(shí)沒用對,比如完全沒有裁剪,比如到屏幕坐標(biāo)的計(jì)算有誤差,應(yīng)該以像素點(diǎn)方框的中心對齊,結(jié)果他們對齊到左上角去了,導(dǎo)致模型動起來三角形邊緣會有跳變的感覺,太多問題了,對于強(qiáng)迫癥,畫錯個點(diǎn)都是難接受的,RenderHelp 采用標(biāo)準(zhǔn)模型,不畫錯一個點(diǎn),不算錯一處坐標(biāo)。
  • 可讀性高,全中文注釋,一千多行代碼 1/3 是注釋,網(wǎng)上很多同類項(xiàng)目,屬于作者自己的習(xí)作,重在實(shí)現(xiàn),做完了事,注釋量不足 5%,一串矩陣套矩陣的操作過去,連行說明都沒有,你想搜索下相關(guān)概念,連個關(guān)鍵字都不知道。RenderHelp.h 是面向可讀性編寫的,雖然也比較小巧,但重點(diǎn)計(jì)算全部展開,每一處計(jì)算都有解釋。某些代碼其實(shí)可以提到外層運(yùn)行更快些,但為了可讀性,還是寫到了相關(guān)位置上,便于理解。

渲染效果圖片:

使用很簡單,include 項(xiàng)目內(nèi)的 RenderHelp.h 即可,VS 和 PS 之間傳參,主要使用一個 ShaderContext 的結(jié)構(gòu)體,里面都是一堆各種類型的 varying。

// 著色器上下文,由 VS 設(shè)置,再由渲染器按像素逐點(diǎn)插值后,供 PS 讀取 struct ShaderContext {std::map<int, float> varying_float; // 浮點(diǎn)數(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ù)進(jìn)行頂點(diǎn)初始化時對三角形的三個頂點(diǎn)依次調(diào)用:

// 頂點(diǎn)著色器:因?yàn)槭?C++ 編寫,無需傳遞 attribute,傳個 0-2 的頂點(diǎn)序號 // 著色器函數(shù)直接在外層根據(jù)序號讀取響應(yīng)數(shù)據(jù)即可,最后需要返回一個坐標(biāo) pos // 各項(xiàng) varying 設(shè)置到 output 里,由渲染器插值后傳遞給 PS typedef std::function<Vec4f(int index, ShaderContext &output)> VertexShader;

每次調(diào)用時,渲染器會依次將三個頂點(diǎn)的編號 0, 1, 2 通過 index 字段傳遞給 VS 程序,方便從外部讀取頂點(diǎn)數(shù)據(jù)。

渲染器對三角形內(nèi)每個需要填充的點(diǎn)調(diào)用像素著色器:

// 像素著色器:輸入 ShaderContext,需要返回 Vec4f 類型的顏色 // 三角形內(nèi)每個點(diǎn)的 input 具體值會根據(jù)前面三個頂點(diǎn)的 output 插值得到 typedef std::function<Vec4f(ShaderContext &input)> PixelShader;

像素著色程序返回的顏色會被繪制到 Frame Buffer 的對應(yīng)位置。

完整例子很簡單,只需要下面幾行代碼就能工作了:

#include "RenderHelp.h"int main(void) {// 初始化渲染器和幀緩存大小RenderHelp rh(800, 600);const int VARYING_COLOR = 0; // 定義一個 varying 的 key// 頂點(diǎn)數(shù)據(jù),由 VS 讀取,如有多個三角形,可每次更新 vs_input 再繪制struct { Vec4f pos; Vec4f color; } vs_input[3] = {{ { 0.0, 0.7, 0.90, 1}, {1, 0, 0, 1} },{ { -0.6, -0.2, 0.01, 1}, {0, 1, 0, 1} },{ { +0.6, -0.2, 0.01, 1}, {0, 0, 1, 1} },};// 頂點(diǎn)著色器,初始化 varying 并返回坐標(biāo),// 參數(shù) index 是渲染器傳入的頂點(diǎn)序號,范圍 [0, 2] 用于讀取頂點(diǎn)數(shù)據(jù)rh.SetVertexShader([&] (int index, ShaderContext& output) -> Vec4f {output.varying_vec4f[VARYING_COLOR] = vs_input[index].color;return vs_input[index].pos; // 直接返回坐標(biāo)});// 像素著色器,返回顏色rh.SetPixelShader([&] (ShaderContext& input) -> Vec4f {return input.varying_vec4f[VARYING_COLOR];});// 渲染并保存rh.DrawPrimitive();rh.SaveFile("output.bmp");return 0; }

運(yùn)行后,生成一張 output.bmp 圖片:

由于 VS/PS 全部 C++ 編寫,因此開發(fā)和調(diào)試都較方便,無需分開單獨(dú)編譯,能直接訪問各種全局變量,能 printf 信息,還能斷點(diǎn)觀察問題。如果 Windows 的話,最后你可以加一行:

system("mspaint output.bmp");

這樣每次運(yùn)行后就能打開畫板程序查看最新的渲染效果。

有了上面繪制三角形的代碼,我們可以繼續(xù)改寫載入個模型繪制下:

直接顯示模型紋理,光禿禿的太丑,加個高洛德著色:

稍微能看一點(diǎn),像十多年前的網(wǎng)游,再加個法向貼圖,讓細(xì)節(jié)更豐富些:

看著還行,再加層高光:

看起來不錯,主要用于驗(yàn)證渲染器,有興趣你可以繼續(xù)折騰 PBR/BRDF 等高級渲染技巧。

渲染器的主要實(shí)現(xiàn)原理很簡單,我在下面這篇文章介紹過:

OpenGL 和 DirectX 是如何在只知道頂點(diǎn)的情況下得出像素位置的??www.zhihu.com

兩種光柵化的實(shí)現(xiàn)方式,基于 Edge Walking 和掃描線繪制的適合 CPU 的傳統(tǒng)實(shí)時軟渲染方法,和現(xiàn)在這個基于 Edge Equation 的適合 GPU 的方法。前者復(fù)雜但是速度快,適合 CPU 實(shí)時渲染;后者簡單,但是運(yùn)算量大,適合 GPU 并行處理。

歡迎參考我十多年前做的另外一個軟件渲染器:

  • mini3d:700 行 C 語言實(shí)現(xiàn)實(shí)時軟件渲染

走的是傳統(tǒng) CPU 實(shí)時渲染方法,其他參考:

  • 計(jì)算機(jī)底層是如何訪問顯卡的?
  • 256字節(jié)3D程序是如何實(shí)現(xiàn)3D引擎的呢?
  • 如何進(jìn)行三角形在齊次空間內(nèi)的裁剪?

--

收藏比點(diǎn)贊多一倍,怎么回事?點(diǎn)個贊那么難么?

總結(jié)

以上是生活随笔為你收集整理的output怎么用_如何用 C++ 写一个可编程软件渲染器?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。