⚡ تنفيذ خط أنابيب عرض قابل للبرمجة ، التعليقات التوضيحية الصينية الكاملة ، مما يساعد المبتدئين على تعلم مبادئ التقديم.
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 ثم احصل على ملف Image 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 العارض:
// 顶点着色器:因为是 C++ 编写,无需传递 attribute,传个 0-2 的顶点序号
// 着色器函数直接在外层根据序号读取响应数据即可,最后需要返回一个坐标 pos
// 各项 varying 设置到 output 里,由渲染器插值后传递给 PS
typedef std::function<Vec4f( int index, ShaderContext &output)> VertexShader; في كل مرة يتم فيها استدعاء المكالمة ، سيقوم العارض بتمرير الأرقام 0 و 1 index 2 من الرؤوس الثلاثة لبرنامج VS بدوره لتسهيل قراءة بيانات Vertex من الخارج.
يطلق العارض تظليل البكسل لكل نقطة يجب ملؤها في المثلث:
// 像素着色器:输入 ShaderContext,需要返回 Vec4f 类型的颜色
// 三角形内每个点的 input 具体值会根据前面三个顶点的 output 插值得到
typedef std::function<Vec4f(ShaderContext &input)> PixelShader;سيتم رسم اللون الذي يتم إرجاعه بواسطة برنامج تظليل البكسل إلى الموضع المقابل للمخزن المؤقت للإطار.
يمكن استدعاء الواجهة التالية رسم مثلث:
bool RenderHelp::DrawPrimitive ()هذه الوظيفة هي جوهر العارض.
بعد ذلك ، تتكرر طبقتان من الحلقة على كل نقطة من المثلث الذي يربط مستطيل على الشاشة ، ثم حدد أنه في نطاق المثلث ، اتصل ببرنامج VS لحساب لون النقطة.
الآن تريد أن تكتب رسمًا مثلثًا لـ D3D 12. لا يمكنك التعامل معه بدون ألف سطر ، ولكن الآن نحتاج فقط إلى الأسطر التالية:
# 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 | ملف تنفيذ العارض ، عند استخدامه ، يتضمن ذلك يكفي |
| نموذج | تحميل النموذج |
| 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_specular.cpp | ارسم النقاط البارزة |
منذ أكثر من عشر سنوات ، كتبت تعليميًا ناعمًا Mini3d ، والذي أوضح بوضوح المبادئ الأساسية لعارضات البرامج.
تم تصميم طريقة تنفيذ هذا المشروع على طريقة تنفيذ معادلة GPU. تعمل طريقة تنفيذ هذا المشروع على محاكاة GPU بسيطة نسبيًا وبديهية ، لكن الحساب كبير جدًا وغير مناسب لوحدة المعالجة المركزية في الوقت الفعلي ، ولكنه مناسب للمعالجة الموازية الخام ل GPU.
هناك العديد من البرامج التعليمية لتنفيذ خطوط العرض القابلة للبرمجة على الإنترنت ، على سبيل المثال ، تُحدد الإحداثيات في الشاشة اليسرى من شبكة البيكسل ، وإلا فإن الحافة الصحيح ، عند أخذ عينات من الملمس ، يجب أن يتم تقريب تحويل عدد صحيح ، وإلا فإن موضع العديد من القمم للملمس غير مستقر بما فيه الكفاية ، وستكون هناك علامات على التحرك قليلاً ؛ . . .
هناك العديد من الجوانب التفصيلية لتنفيذ العارض.
آخر هو قابلية القراءة.
يحتوي الملف الرئيسي RenderHelp.h هذا المشروع على أكثر من ألف سطر ، حيث أن ثلثه من التعليقات التوضيحية الصينية.
المبادئ الأساسية ، لقد شرحت في المقالة التالية:
عند القراءة ، يكون الكود في الأساس عدد قليل من مكتبات الأدوات ، والتي يمكن قراءتها من آخر 200 سطر.
إذا كنت لا تفهم الرمز ، فيمكنك طرح سؤال في هذه القضية.