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

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

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

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

     

1.主要模塊功能

1.1數學庫

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

      視角矩陣、投影矩陣和屏幕座標轉換矩陣;算法

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

1.2後緩衝區

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

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最近都沒怎麼看,爲了開學找工做得把算法數據結構再複習下!

相關文章
相關標籤/搜索