開源一個簡單的c++軟光柵渲染器


     本文由zhangbaochong原創,轉載請注明出處http://www.cnblogs.com/zhangbaochong/p/5751111.html

     由於開學就大四面臨找工作了,為了整理下項目,最近又把上學期練手寫的一個c++軟光柵渲染demo拿出來重新改了改,稍微優化了一下,順便增加了光照。雖然寫的比較簡單,但還是拿出來分享一下,希望能起個拋磚引玉的作用吧,也歡迎指點批評O(∩_∩)O~

  (ps :項目代碼只有4000行左右,性能方面也比較渣,高性能的光柵渲染可以看空明大大的SALVIAhttp://www.cnblogs.com/lingjingqiu/)

     

1.主要模塊功能

1.1數學庫

  向量、矩陣的實現與變換(矩陣平移、旋轉、轉置、行列式、逆矩陣);

      視角矩陣、投影矩陣和屏幕坐標轉換矩陣;

  一些常用函數(插值、RGB顏色轉UINT、角度弧度轉換、求反射向量).

1.2后緩沖區

      設置像素,我一開始采用SetPixel()函數,發現速度慢的不忍直視。后來改成用CreateDIBSections創建位圖,直接向內存中寫像素顏色值,完了后一塊BitBlt到窗口就行了。

1.3模型標准

  由於之前一直在寫directx11的代碼,所以這里也采用標准d3d的坐標模型,左手系+world view proj三矩陣

1.4幾何階段

      頂點從模型空間到世界空間到相機空間到齊次裁剪空間,對應的主要是三個矩陣world view proj,數學庫中提供了相應方法。

      圖元裝配,也就是將頂點以一定順序組裝成三角形,本項目中采用頂點索引的方式來組織頂點,並且三角形順時針順序對應的法線朝向外面。之所以規定好順序,是為了法線方向的一致性,只有這樣才能進行后面的背面消隱。

      投影后的坐標再進行透視除法,讓頂點坐標位於cvv中(x[-1,1],y[-1,1],z[0,1]),裁剪過后再將cvv坐標轉化為屏幕中對應的坐標。

1.4三角形光柵化

     線框模型使用的bresenham畫線算法。

     三角形光柵算法:http://blog.csdn.net/cppyin/article/details/6232453

     填充三角形使用的掃描線。

1.5背面消隱

     可以參考:http://blog.csdn.net/cppyin/article/details/6207206

1.6簡單CVV裁剪

1.7支持紋理

  紋理uv坐標同d3d,紋理坐標尋址同d3d的wrap方式,貼圖在物體表面重復,類似於我們設置桌面是圖片的平鋪方式。當坐標大於1時,通過去掉整數部分,根據得到的小數部分來得到紋理值;坐標小於0,則加上一個最小正數,讓坐標大於0。

1.8簡單光照

  phong光照模型,實現平行光、點光源與聚光燈三種。

1.9簡單着色器

     寫了一個着色器類,有VS和PS兩個函數對應頂點着色器和像素着色器,部分代碼如下:

 1 VertexOut BoxShader::VS(const VertexIn& vin)
 2 {
 3     VertexOut out;
 4     out.posH = vin.pos * m_worldViewProj;
 5     
 6     out.posTrans = vin.pos * m_world;
 7     out.normal = out.normal * m_worldInvTranspose;
 8 
 9      out.color = vin.color;
10      out.tex = vin.tex;
11 
12     return out;
13 }
14 
15 ZCVector BoxShader::PS(VertexOut& pin)
16 {
17     //單位化法線
18     pin.normal.Normalize();
19 
20     //紋理采樣
21     ZCVector texColor = m_tex.Sample(pin.tex);
22 
23     //頂點到觀察點向量
24     ZCVector toEye = (m_eyePos - pin.posTrans).Normalize();
25 
26     //初始化顏色值全部為0
27     ZCVector ambient(0.f, 0.f, 0.f, 0.f);
28     ZCVector diffuse(0.f, 0.f, 0.f, 0.f);
29     ZCVector specular(0.f, 0.f, 0.f, 0.f);
30 
31     //光源計算后得到的環境光、漫反射 、高光
32     ZCVector A, D, S;
33 
34     Lights::ComputeDirectionalLight(m_material, m_dirLight, pin.normal, toEye, A, D, S);
35 
36     ambient = ambient + A;
37     diffuse = diffuse + D;
38     specular = specular + S;
39 
40 
41     //紋理+光照計算公式: 紋理*(環境光+漫反射光)+高光
42     ZCVector litColor = texColor * (ambient + diffuse) + specular;
43 
44     //最終顏色透明度使用漫反射光的透明度
45     litColor.w = m_material.diffuse.w * texColor.w;
46 
47     return litColor;
48 }
View Code

 

2.截圖效果

2.1線框模型

2.2頂點色

2.3紋理+光照

圖片本身是木紋材質,顯得比較粗糙/(ㄒoㄒ)/~~

 

3.源碼

     項目托管到Github上了:https://github.com/zhangbaochong/Tiny3D

     等有時間我會再優化一下,比如采用SIMD加速等等。最近應該沒時間搞這個了,d3d最近都沒怎么看,為了開學找工作得把算法數據結構再復習下!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM