pipelineパイプラインの実装、完全な中国語の注釈をレンダリングするプログラム可能なレンダリング、初心者がレンダリング原則を学ぶのに役立ちます。
mkdir build
cmake -S . -B ./build
cmake --build ./build --config Release実行可能ファイルが配置されているパスにRESフォルダをコピーすることに注意してください。
sample_から始まるサンプルファイルを見つけて、GCCシングルファイルで直接コンパイルします。
gcc -O2 sample_07_specular.cpp -o sample_07_specular -lstdc++ -std=c++17 macに追加する必要があるようですが、環境がないかどうかはわかりません。リンク数学ライブラリを表示および宣言するには、 -lmを追加する必要がある場合があります。
走る:
./sample_07_specular次に、画像ファイルoutput.bmp取得します:
このプロジェクトのモデルは、Tinyrenderのオープンソースモデルを使用しています。
主にShaderContext構造を使用します。これは、vs-> ps間のパラメーターを渡すために使用され、さまざまなタイプのバリエーションでいっぱいです。
// 着色器上下文,由 VS 设置,再由渲染器按像素逐点插值后,供 PS 读取
struct ShaderContext {
std::map< int , float > varying_float; // 浮点数 varying 列表
std::map< int , Vec2f> varying_vec2f; // 二维矢量 varying 列表
std::map< int , Vec3f> varying_vec3f; // 三维矢量 varying 列表
std::map< int , Vec4f> varying_vec4f; // 四维矢量 varying 列表
};外側の層は、レンダラーとレンダラーに関数ポインターを提供し、レンダラーのDrawPrimitive関数が初期化されたときに、順番に三角形の3つの頂点を呼び出す必要があります。
// 顶点着色器:因为是 C++ 编写,无需传递 attribute,传个 0-2 的顶点序号
// 着色器函数直接在外层根据序号读取响应数据即可,最后需要返回一个坐标 pos
// 各项 varying 设置到 output 里,由渲染器插值后传递给 PS
typedef std::function<Vec4f( int index, ShaderContext &output)> VertexShader;呼び出しが呼び出されるたびに、レンダラーはVSプログラムの3つの頂点のうち0 、 index 2 1に渡し、外部からの頂点データの読み取りを容易にします。
レンダラーは、三角形に記入する必要があるすべてのポイントのピクセルシェーダーを呼び出します。
// 像素着色器:输入 ShaderContext,需要返回 Vec4f 类型的颜色
// 三角形内每个点的 input 具体值会根据前面三个顶点的 output 插值得到
typedef std::function<Vec4f(ShaderContext &input)> PixelShader;ピクセルシェーディングプログラムによって返される色は、フレームバッファーの対応する位置に描画されます。
次のインターフェイスを呼び出すと、三角形を描画できます。
bool RenderHelp::DrawPrimitive ()この関数は、最初にレンダラーのコアであり、VSを呼び出して頂点を初期化し、頂点を取得し、均一なスペーストリミングを実行し、正規化後に三角形の画面座標を取得します。
次に、画面上の長方形を接続する三角形の各ポイントをforループの2層を繰り返し、トライアングル範囲内でVSプログラムを呼び出してポイントの色を計算します。
次に、D3D 12の三角形の図面を書きたいと思います。1000行なしではそれを処理することはできませんが、今では次の行が必要です。
# include " RenderHelp.h "
int main ( void )
{
// 初始化渲染器和帧缓存大小
RenderHelp rh ( 800 , 600 );
const int VARYING_COLOR = 0 ; // 定义一个 varying 的 key
// 顶点数据,由 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 } },
};
// 顶点着色器,初始化 varying 并返回坐标,
// 参数 index 是渲染器传入的顶点序号,范围 [0, 2] 用于读取顶点数据
rh. SetVertexShader ([&] ( int index , ShaderContext& output) -> Vec4f {
output. varying_vec4f [VARYING_COLOR] = vs_input[ index ]. color ;
return vs_input[ index ]. pos ; // 直接返回坐标
});
// 像素着色器,返回颜色
rh. SetPixelShader ([&] (ShaderContext& input) -> Vec4f {
return input. varying_vec4f [VARYING_COLOR];
});
// 渲染并保存
rh. DrawPrimitive ();
rh. SaveFile ( " output.bmp " );
return 0 ;
}実行結果:
| ファイル名 | 説明します |
|---|---|
| renderhelp.h | レンダラーの実装ファイルは、使用すると十分です |
| Model.H | モデルのロード |
| sample_01_triangle.cpp | 描画三角形の例 |
| sample_02_texture.cpp | テクスチャの使用方法、カメラマトリックスの設定方法など。 |
| sample_03_box.cpp | 箱を描く方法 |
| sample_04_gouraud.cpp | 箱のシンプルなガロード色 |
| sample_05_model.cpp | モデルをロードして描画する方法 |
| sample_06_normal.cpp | 通常のマップでモデルの詳細を強化します |
| sample_07_spacular.cpp | ハイライトを描きます |
10年以上前、私はソフトレンダリングチュートリアルMini3Dを書きました。これは、主にエッジウォーキングとスキャンラインアルゴリズムに基づいて、ソフトウェアレンダラーのコア原則を明確に説明しました。
このプロジェクトの実装方法は、GPUのEdge方程式実装方法をモデル化しています。このプロジェクトの実装方法は、GPUをシミュレートすることは比較的単純で直感的ですが、計算は非常に大きく、リアルタイムCPUには適していませんが、GPUの大まかな並列処理に適しています。
たとえば、インターネット上でプログラム可能なレンダリングパイプラインを実装するためのチュートリアルがあります。テクスチャサンプリングの場合、整数座標変換は丸くする必要があります。そうしないと、テクスチャのいくつかの頂点が十分に安定しておらず、一部のソフトウェアレンダラーは正しい視点でテクスチャを見ることさえできず、まだ模倣テクスチャマッピングを使用しています。 。 。 。
レンダリングの実装には非常に詳細な側面があります。
もう1つは、コードの量を故意に減らすために、多くの操作を削減します。
このプロジェクトのメインRenderHelp.hは、合計1,000行以上を持ち、その3分の1はすべての複雑な操作を拡大し、実際にコードサイズを節約するために読みやすくなります。
基本原則は、次の記事で説明しました。
読んでいるとき、コードは基本的には、各式のソースを書いた後、その前のいくつかのツールライブラリです。
コードを理解していない場合は、この問題で質問することもできます。