本文由zhangbaochong原創,轉載請註明出處http://www.cnblogs.com/zhangbaochong/p/5751111.htmlhtml
因爲開學就大四面臨找工做了,爲了整理下項目,最近又把上學期練手寫的一個c++軟光柵渲染demo拿出來從新改了改,稍微優化了一下,順便增長了光照。雖然寫的比較簡單,但仍是拿出來分享一下,但願能起個拋磚引玉的做用吧,也歡迎指點批評O(∩_∩)O~c++
(ps :項目代碼只有4000行左右,性能方面也比較渣,高性能的光柵渲染能夠看空明大大的SALVIAhttp://www.cnblogs.com/lingjingqiu/)git
向量、矩陣的實現與變換(矩陣平移、旋轉、轉置、行列式、逆矩陣);github
視角矩陣、投影矩陣和屏幕座標轉換矩陣;算法
一些經常使用函數(插值、RGB顏色轉UINT、角度弧度轉換、求反射向量).數據結構
設置像素,我一開始採用SetPixel()函數,發現速度慢的不忍直視。後來改爲用CreateDIBSections建立位圖,直接向內存中寫像素顏色值,完了後一塊BitBlt到窗口就好了。ide
因爲以前一直在寫directx11的代碼,因此這裏也採用標準d3d的座標模型,左手系+world view proj三矩陣函數
頂點從模型空間到世界空間到相機空間到齊次裁剪空間,對應的主要是三個矩陣world view proj,數學庫中提供了相應方法。性能
圖元裝配,也就是將頂點以必定順序組裝成三角形,本項目中採用頂點索引的方式來組織頂點,而且三角形順時針順序對應的法線朝向外面。之因此規定好順序,是爲了法線方向的一致性,只有這樣才能進行後面的背面消隱。優化
投影后的座標再進行透視除法,讓頂點座標位於cvv中(x[-1,1],y[-1,1],z[0,1]),裁剪事後再將cvv座標轉化爲屏幕中對應的座標。
線框模型使用的bresenham畫線算法。
三角形光柵算法:http://blog.csdn.net/cppyin/article/details/6232453
填充三角形使用的掃描線。
能夠參考:http://blog.csdn.net/cppyin/article/details/6207206
紋理uv座標同d3d,紋理座標尋址同d3d的wrap方式,貼圖在物體表面重復,相似於咱們設置桌面是圖片的平鋪方式。當座標大於1時,經過去掉整數部分,根據獲得的小數部分來獲得紋理值;座標小於0,則加上一個最小正數,讓座標大於0。
phong光照模型,實現平行光、點光源與聚光燈三種。
寫了一個着色器類,有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 }
圖片自己是木紋材質,顯得比較粗糙/(ㄒoㄒ)/~~
項目託管到Github上了:https://github.com/zhangbaochong/Tiny3D
等有時間我會再優化一下,好比採用SIMD加速等等。最近應該沒時間搞這個了,d3d最近都沒怎麼看,爲了開學找工做得把算法數據結構再複習下!