摘要: 我的古董顯卡很操蛋,好端端的shader,傳骨骼矩陣進去,硬是沒反應。。
尋尋覓覓,找到了 NVIDIA SDK 的example,終于解決了。
難道我的顯卡不支持BLENDINDICES和BLENDWEIGHT?
把BLENDINDICES和BLENDWEIGHT用TEXCOORD[n]表示才正常。。
不說廢話,直接上代碼。 閱讀全文
感覺fstream有些地方設計的不太合理,不知道是bug還是那些牛X們故意這樣的。
首先,fstream竟然在中文路徑這種東西上不支持,網上也可以看到許多實現方法,但有的方法其實并不是太好。
我覺得這樣做最簡單:
setlocale(LC_ALL,"");//設置成當前語言環境
ofstream?out(filename);//打開文件
setlocale(LC_CTYPE,?0);
還有,fstream的getline也有問題,對于那些\n \r 空行 什么的都沒考慮,用起來會出錯。
在網上看到一個函數可以完美解決這個問題:
bool?readline(ifstream&?infile,?string&?textline)
{
while(getline(infile,?textline,?'\n'))
{
??int?prev_pos?=?0;?//最開始有效字符位置.
??int?post_pos?=?0;?//最后有效字符位置
??//下面的循環語句能夠用textline.find_first_not_of(filter,pos)來處理,出于效率考慮本處使用這樣的算法
??while(textline[prev_pos]?==?'?'?||?textline[prev_pos]?==?'\t'?||?textline[prev_pos]?==?'\r')//過濾開始空白
???prev_pos++;
??if(textline[prev_pos]?==?'\0')
???continue;//假如是空白行則再讀一行進行處理.
??else
??{
?????? post_pos=textline.length()-1;
?????? while(textline[post_pos]?==?'?'?||?textline[post_pos]?==?'\t'?||?textline[post_pos]?==?'\r')//過濾最后的空白
???????????? {
????????????????? post_pos--;
???????????? }
?????? textline=textline.substr(prev_pos,post_pos+1-prev_pos);
???return?true;//成功讀取一有效行
??}
??
}
return?false;//讀到文檔的末尾
}
我根據上面這個函數 重載了一個char* 版的:
bool?readline(ifstream&?infile,?char*?textline)
{
while(infile.getline(textline,32))
{
??int?prev_pos?=?0;?//最開始有效字符位置
??int?post_pos?=?0;?//最后有效字符位置.??
??string?str=textline;
??//下面的循環語句能夠用textline.find_first_not_of(filter,pos)來處理,出于效率考慮本處使用這樣的算法
??while(str[prev_pos]?==?'?'?||?str[prev_pos]?==?'\t'?||?str[prev_pos]?==?'\r')//過濾開始空白
???prev_pos++;
??if(str[prev_pos]?==?'\0')
???continue;//假如是空白行則再讀一行進行處理
??else
??{
???????? post_pos=str.length()-1;
???????? while(str[post_pos]?==?'?'?||?str[post_pos]?==?'\t'?||?str[post_pos]?==?'\r')//過濾最后的空白
???????? {
?????????????? post_pos--;
???????? }
???????? string?str2=str.substr(prev_pos,post_pos+1-prev_pos);
???????? strcpy(textline,str2.c_str());
????????
???return?true;//成功讀取一有效行
??}
}
return?false;//讀到文檔的末尾
}
先上個自己實現的水面模擬圖:

效果比較簡單,只是模擬了下水面的反射效果。折射與Fresnel系數沒有考慮。
水面模擬大致需要分這么幾步:
1.剪裁掉水面以下的頂點[gpu里的clipplane要注意轉換到Clip Space],
將攝像機放到同原攝像機關于水面對稱的位置,比如原來攝像機在(x,y,z),
此時就該把攝像機放在(x,-y,z),up向量也要設置成向下的。
再把場景渲染到Render Target的紋理上(我用的紋理大小是256*256),不知道為什么Render Target的紋理大小不能超過窗口大小,超過的話渲染會出錯,知道的大大告訴我一下哈。
于是,就得到了這樣一個紋理:

2.將上面得到的紋理與水面的頂點對應.
把Vertex Shader中乘過變換矩陣后的坐標傳到Pixel Shader,
在PS中計算
?? ???? float2 clipspace = input.Coord.xy / input.Coord.w;
?? ???? clipspace.x=((clipspace.x * 0.5f) + 0.5f);
?? ???? clipspace.y = ((clipspace.y * -0.5f) + 0.5f);
?? ???? clipspace.x=1-clipspace.x;
既可以讓水面頂點與紋理對應,然后再想辦法把紋理坐標擾亂來模擬水面波動。
3.再渲染一次場景就可以了。
大家也可以參考下Azure的水面渲染源代碼:
http://www.azure.com.cn/article.asp?id=186
剪裁平面
(Clip Plane)
在圖形學領域有著重要的作用,比如水面模擬中,渲染折射紋理時,我們就必須將水面以上的頂點通過剪裁平面剪裁掉。
在過去的固定渲染管道時代,剪裁平面的實現較為簡單,比如在
DirectX 9
中,可以先設定剪裁平面在世界坐標系下的方程
(ax+by+cz+d=0)
,再調用
SetClipPlane(DWORD Index,CONST float * pPlane)
這個
API
函數就可以了。
?
附上例子程序:
vPosition=D3DXVECTOR3(0,0,0);
//
平面上一個點
vNormal=D3DXVECTOR3(0,1,0);
//
法向量
D3DXPlaneFromPointNormal(?&clipplane,?&vPosition,?&vNormal?);
//
生成剪裁平面
m_pDevice()->SetClipPlane(?0,?(
float
*)clipplane);?
?
然而,在現在的可編程管道
(programmable pipeline)
下,設置的剪裁平面會被在剪裁坐標系下處理,而不是在世界坐標系下。
解決這個問題的方法有:
1)? 給要剪裁的頂點做標記,在Pixel Shader中把它剪裁掉。
2)? 使用近斜平面裁剪(Oblique Near-Plane Clipping),即修改投影矩陣,將要剪裁的頂點放在視截體之外,從而避免了該頂點的繪制。
3)? 修改平面方程,使之從世界坐標系轉換到剪裁坐標系。
上述方法中,第一種和第二種效率并不高:在Pixel Shader中剪裁沒有減少任何不必要的頂點處理,而計算近斜平面裁剪矩陣較為繁瑣。所以,方法三是最佳選擇。?要將一個平面從世界坐標系轉換到剪裁坐標系,必須求出這個變換矩陣。
設平面方程ax+by+cz+d=0,用一個4維向量來n表示(a,b,c,d),設平面上有個點p:(x,y,z,1)。根據平面方程的定義,有:
nTp = ax + by + cz + d = 0
設矩陣R可以讓點P從世界坐標系轉換到剪裁坐標系,矩陣Q可以讓平面n實現同樣的變換。那么,有:
p'= Rp
n'= Qn
其中p'、n'分別是轉換后的點與平面。
n'Tp'= 0
(Qn)T (Rp) = 0
nTQTRp = 0
如果:QTR = I
那么:
nTQTRp = nTIp = nTp = 0
于是:
QT = R-1
Q = (R-1)T
在DirectX 3D中,將一個點從世界坐標系轉換到剪裁坐標系,所用的矩陣為觀察矩陣與投影矩陣的乘積,即:
D3DXMATRIX??TranMatrix?=?matView*matProj;
(TranMatrix為所求的變換矩陣,matView和matProj分別為觀察矩陣與投影矩陣)
?
附上在D3D中變換的完整代碼:
D3DXPLANE?tempPlane?=?clipplane;
D3DXPlaneNormalize(&tempPlane,?&tempPlane);
D3DXMATRIX??TranMatrix?=?matView*matProj;
D3DXMatrixInverse(&TranMatrix,?NULL,?&TranMatrix);
D3DXMatrixTranspose(&TranMatrix,?&TranMatrix);
D3DXPlaneTransform(&tempPlane,?&tempPlane,?&TranMatrix);
參考資料:
1.Back Face Culling Notes ,Jordan Smith (University of California, Berkeley)
http://www.cs.berkeley.edu/~ug/slide/pipeline/assignments/backfacecull.shtml?
2.GameDev Forum
http://www.gamedev.net/community/forums/topic.asp?topic_id=402381
3.Oblique Near-Plane Clipping with Orthographic Camera ,Aras
http://aras-p.info/texts/obliqueortho.html
摘要: 感覺線性代數作業里一直少不了矩陣求逆,
寫個帶輸出算逆矩陣的步驟的矩陣求逆程序,希望給即將或正在學線代的同學一點方便。 閱讀全文