emplementation การใช้งานท่อส่งข้อมูลที่ตั้งโปรแกรมได้คำอธิบายประกอบภาษาจีนเต็มรูปแบบช่วยให้ผู้เริ่มต้นเรียนรู้หลักการการแสดงผล
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 เพื่ออำนวยความสะดวกในการอ่านข้อมูลจุดสุดยอดจากภายนอก
ตัวเรนเดอร์เรียก Pixel Shader สำหรับทุกจุดที่ต้องกรอกในรูปสามเหลี่ยม:
// 像素着色器:输入 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 | ไฟล์การใช้งาน Renderer เมื่อใช้รวมถึงมันก็เพียงพอแล้ว |
| model.h | กำลังโหลดรุ่น |
| ตัวอย่าง _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 | วาดไฮไลท์ |
กว่าสิบปีที่ผ่านมาฉันเขียน Soft Renderer Tutorial Mini3d ซึ่งอธิบายหลักการหลักของการแสดงผลซอฟต์แวร์อย่างชัดเจน
วิธีการใช้งานของโครงการนี้เป็นแบบจำลองบนวิธีการใช้งาน Edge Equation ของ GPU วิธีการใช้งานของโครงการนี้จำลอง GPU นั้นค่อนข้างง่ายและใช้งานง่าย แต่การคำนวณมีขนาดใหญ่มากและไม่เหมาะสำหรับ CPU แบบเรียลไทม์ แต่เหมาะสำหรับการประมวลผล GPU แบบขนานแบบหยาบ
มีการสอนมากมายสำหรับการใช้งานท่อส่งสัญญาณที่ตั้งโปรแกรมได้ แต่หลายคนมีปัญหา ตัวอย่างเช่นเมื่อการสุ่มตัวอย่างพื้นผิวการแปลงพิกัดจำนวนเต็มควรได้รับการปัดเศษมิฉะนั้นตำแหน่งของจุดยอดของพื้นผิวหลายอย่างนั้นไม่เสถียรพอและจะมีสัญญาณของการเคลื่อนไหวเล็กน้อย - - -
มีแง่มุมต่าง ๆ มากมายของการใช้งานการแสดงผล
อีกอย่างหนึ่งคือการอ่าน
ไฟล์หลัก RenderHelp.h ของโครงการนี้มีมากกว่าหนึ่งพันบรรทัดหนึ่งในสามซึ่งเป็นคำอธิบายประกอบภาษาจีน
หลักการพื้นฐานที่ฉันได้อธิบายในบทความต่อไปนี้:
เมื่ออ่านรหัสเป็นห้องสมุดเครื่องมือสองสามอย่างที่อยู่ด้านหน้าซึ่งสามารถอ่านได้จาก 200 บรรทัดที่ผ่านมาฉันเขียนแหล่งที่มาของแต่ละสูตร
หากคุณไม่เข้าใจรหัสคุณสามารถถามคำถามในปัญหานี้ได้