這些都是超出White Paper的經(jīng)驗(yàn)總結(jié),如有錯(cuò)誤,請(qǐng)多多指正謝謝!
1、使用哪個(gè)苦力
你可以使用GPU或者是CPU,計(jì)算隨時(shí)間變化的高程。聽起來用GPU的Vertex Shader計(jì)算高程好像非常先進(jìn),其實(shí)不然。因?yàn)镚PU與CPU的運(yùn)作機(jī)制不同,每個(gè)FPS,傳入時(shí)間Uniform變量會(huì)導(dǎo)致GPU效率低下,在NVIDIA的GPU優(yōu)化指南中提到過這一點(diǎn)。所以我還是推薦用CPU計(jì)算高程,因?yàn)闋可娴酱罅康娜呛瘮?shù)的計(jì)算,不可能舍得寶貴的GPU資源浪費(fèi)在這些CPU可以運(yùn)作如飛的計(jì)算上。Vertex Shader應(yīng)該做矩陣變換,光照向量等等。如果可能用匯編代碼優(yōu)化一下,把傳入Vertex Shader的Normals給Normalize了。
2、I want get the Mesh
貼關(guān)鍵的完整代碼。
#ifndef?RK_HPP
#include?"rk.hpp"
#endif
extern?GLint?AttribTangentSlot;
extern?GLint?LightPositionLoc;
CStreamModel::CStreamModel(short?n?=?64,float?gl?=?1.0f)?:?N(n),GridLength(gl)
{
????//準(zhǔn)備物理參數(shù)
????EnvCubeMap?=?-1;//立方體環(huán)境貼圖
????NormalMap?=?-1;//發(fā)現(xiàn)貼圖,也就是凹凸圖
????RefractMap?=?-1;
????omiga?=?new?float[4];
????A?=?new?float[4];
????L?=?new?float[4];
????Q?=?new?float[4];
????A[0]?=?0.05f;
????A[1]?=?0.05f;
????A[2]?=?0.02f;
????A[3]?=?0.03f;
????L[0]?=?1.0f;
????L[1]?=?1.2f;
????L[2]?=?2.0f;
????L[3]?=?1.2f;
????for(int?i=0;i<4;i++){
????????omiga[i]?=?sqrt(9.8f*2.0f*3.14f/L[i]);//L?=?0.01
????????Q[i]?=?1/(omiga[i]*A[i]*4.0f);
????}
???
????//Q?=?0.01235;
????Mesh?=?new?float[N*N*3];
????VertexIndex?=?new?unsigned?short?[N*N*3];
????TexCoord?=?new?float[N*N*2];
????Binormal?=?new?float[N*N*3];
????Tangent?=?new?float[N*N*3];
????Normal?=?new?float[N*N*3];
????//生成頂點(diǎn)索引?
????//優(yōu)化乘法?*N可以表示為?<<6
????int?cnt?=?0;
????for(int?i=0;?i<N-2;?i++)?
????{
????????for(int?j=0;?j<N;?j++)?
????????{
????????????VertexIndex[cnt]?=?i*N?+?j;?cnt++;?
????????????VertexIndex[cnt]?=?i*N?+?j?+?N;?cnt++;?
????????}
????????i++;?
????????j?=?N-1;?
????????VertexIndex[cnt]?=?i*N?+?j?+?N;?cnt++;?
????????VertexIndex[cnt]?=?i*N?+?j;?cnt++;
????????for(j=N-2;j>=0;j--)?
????????{
????????????VertexIndex[cnt]?=?i*N?+?j?+?N;?cnt++;?
????????????VertexIndex[cnt]?=?i*N?+?j;?cnt++;?
????????}
????}
????cout<<"size?of?VertexIndex?:?"<<cnt<<endl;
????int?p?=?0;
????for(int?x?=?0;?x?<?N;?x++){
????????for(int?z?=?0;?z?<?N;?z++){
????????????TexCoord[p*2]?=?float(x)?/?float(N);
????????????TexCoord[1+p*2]?=?float(z)?/?float(N);
????????????p++;
????????}
????}
????
????for(int?i=0;?i<16;?i++)
????????cout<<"TexCoord?:?"<<TexCoord[i]<<endl;
????PixelProcesser?=?new?CPixel();
????PixelProcesser->LoadTextureFromBMP(".\\TEXTURES\\Waterbump.bmp",NormalMap);
????if?(?glIsTexture(NormalMap)){
????????cout<<"NormalMap?Texture?Loaded?Ok
"<<endl;
????}else{
????????cout<<"NormalMap?Faild?!"<<endl;
????????_sleep(2000);
????????exit(-1);
????}
????PixelProcesser->LoadTextureFromBMP(".\\TEXTURES\\WaterRefract.bmp",RefractMap);
????if?(?glIsTexture(RefractMap)?){
????????cout<<"WaterRefract?Texture?Loaded?Ok
"<<endl;
????}else{
????????cout<<"RefractMap?Faild?!"<<endl;
????????_sleep(2000);
????????exit(-1);
????}
????char?*szCubeFace[6]?=?{".\\TEXTURES\\RIGHT.bmp",".\\TEXTURES\\LEFT.bmp",".\\TEXTURES\\TOP.bmp",".\\TEXTURES\\BOTTOM.bmp",".\\TEXTURES\\BACK.bmp",".\\TEXTURES\\FRONT.bmp"};
?????PixelProcesser->LoadTextureFrom6CUBEMAP(szCubeFace,EnvCubeMap);
????if?(?glIsTexture(EnvCubeMap)){
????????cout<<"CubeMap?Texture?Loaded?Ok
"<<endl;
????}else{
????????cout<<"cubeMap?Faild?!"<<endl;
????????_sleep(2000);
????????exit(-1);
????}
};
void?CStreamModel::ReBuildHeightMap()
{
????//Dx?Dy還沒有選擇,就用從內(nèi)向外的斜方向?(-0.1,0,1)
????
????//生成網(wǎng)格與紋理坐標(biāo)還有TBN向量
????//測試:只有一個(gè)方向
????//i?行?j列?OpenGL是反的
????/**/
????//cout<<"N?is?:?"<<N<<",?And?N^2?is?:?"<<N*N<<endl;
????//float?fi?=?0.23;?//fi*t相位
????float?D[4][2]={};
????D[0][0]?=?0.23f;
????D[0][1]?=?-0.08f;
????
????D[1][0]?=?0.12f;
????D[1][1]?=?0.34f;
????
????D[2][0]?=?-0.23f;
????D[2][1]?=?-0.1f;
????D[3][0]?=?-0.2f;
????D[3][1]?=?0.01f;
????int?i?=?0;
????int?p?=?0;//位置
????for(?int?i?=?0?;?i?<??N?;?i++?){
????????for(?int?j?=?0?;?j?<?N?;?j++?){
????????????float?x?=?i?/?8.0?-?4.0f;
????????????float?z?=?j?/?8.0?-?4.0f;
????????????//定點(diǎn)需要的三角計(jì)算
????????????float?sigemaCx?=?0.0f,sigemaCz?=?0.0f;
????????????float?sigemaS?=?0.0f;
????????????//向量需要的三角計(jì)算
????????????float?N1?=?0.0f;
????????????float?N2?=?0.0f;
????????????float?N3?=?0.0f;
????????????float?T1?=?0.0f;
????????????float?T2?=?0.0f;
????????????float?T3?=?0.0f;
??????????? for(int?k=0;k<4;k++){
????????????????float?C?=?cos(omiga[k]*(D[k][0]*x+D[k][1]*z)+t);
????????????????float?S?=?sin(omiga[k]*(D[k][0]*x+D[k][1]*z)+t);
????????????????sigemaCx?+=?Q[k]*A[k]*D[k][0]*C;
????????????????sigemaCz?+=?Q[k]*A[k]*D[k][1]*C;
????????????????sigemaS?+=?A[k]*C;
????????????????float?OAC?=?omiga[k]*A[k]*C;
????????????????float?OAS?=?omiga[k]*A[k]*S;
????????????????N1?+=?D[k][0]*OAC;
????????????????N2?+=?D[k][1]*OAC;
????????????????N3?+=?Q[k]*OAS;
????????????????T1?+=?Q[k]*D[k][0]*D[k][1]*OAS;
????????????????T2?+=?Q[k]*pow(D[k][1],2)*OAS;
????????????????T3?+=?D[k][1]*OAC;
????????????};
????????????
????????????Mesh[p*3]?=?x?+?sigemaCx;
????????????Mesh[p*3+2]?=?z?+?sigemaCz;
????????????Mesh[p*3+1]?=?sigemaS;
????????????
????????????Normal[?p*3?]?=?-?N1;
????????????Normal[?p*3?+2]?=?-?N2;
????????????Normal[?p*3?+1]?=?1?-?N3;
????????????Tangent[?p*3?]?=?-T1;
????????????Tangent[?p*3?+2]?=?1-T2;?
????????????Tangent[?p*3?+1]?=?T3;
????????????p++;
????????}
????}
????//glEnableClientState(GL_INDEX_ARRAY);
????//glIndexPointer(GL_SHORT,0,VertexIndex);
????t+=0.1f;
};
void?CStreamModel::Draw()
{????
????//glutSolidSphere(1.0,32,32);
????glUniform3f(::LightPositionLoc,0,0,10);
????ReBuildHeightMap();
????glEnableClientState(GL_VERTEX_ARRAY);
????glEnableClientState(GL_NORMAL_ARRAY);
????glEnableVertexAttribArray(::AttribTangentSlot);
????glEnableClientState(GL_TEXTURE_COORD_ARRAY);
????glTexCoordPointer(2,GL_FLOAT,0,TexCoord);
????glVertexPointer(3,GL_FLOAT,0,Mesh);
????glNormalPointer(GL_FLOAT,0,Normal);
????glVertexAttribPointer(::AttribTangentSlot,3,GL_FLOAT,0,0,Tangent);
????glActiveTexture(GL_TEXTURE2);
????glEnable(GL_TEXTURE_CUBE_MAP);
????glBindTexture(GL_TEXTURE_CUBE_MAP,EnvCubeMap);
????glActiveTexture(GL_TEXTURE1);
????glBindTexture(GL_TEXTURE_2D,NormalMap);
????glActiveTexture(GL_TEXTURE0);
????glBindTexture(GL_TEXTURE_2D,RefractMap);
????glPushMatrix();
????????glTranslatef(0,0,15);
????????glDrawElements(GL_TRIANGLE_STRIP,7936,GL_UNSIGNED_SHORT,VertexIndex);
????glPopMatrix();
//????glPopMatrix();
????glDisableClientState(GL_VERTEX_ARRAY);
????glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableVertexAttribArray(::AttribTangentSlot);
}; 代碼很臭,大蝦不要見笑。在繪制函數(shù)中,最最關(guān)鍵的就是
ReBuildHeightMap()這個(gè)函數(shù)。每個(gè)fps它都將被渲染器執(zhí)行一次。公式參考了GPU GEMS。把參數(shù)解釋一下。Omiga,角頻率;A,水波的振幅;L,波長;Q很特殊,是一個(gè)可以控制水波形狀的參數(shù),太大了會(huì)導(dǎo)致一個(gè)環(huán)。可惜我沒有學(xué)過流體力學(xué)那個(gè)NS方程,實(shí)在不清楚怎么回事。把頂點(diǎn)的高程,向量計(jì)算后,就可以傳入Shader計(jì)算了。可是,且慢。
3、Vertex Or Triangles
地形的索引是如何做的?這里水波的索引也就是如何做的。地形也就是個(gè)三角形拼成的大網(wǎng)。所以,當(dāng)興沖沖的計(jì)算了一個(gè)1024x1024的巨大Water Vertex Mesh,卻發(fā)現(xiàn)需要的是三角形。看我上面的代碼中的一段,保準(zhǔn)你看的舒心,用的省心。(雞蛋皮鞋亂飛中)。
4、人要臉樹要皮
好了,可以貼圖了。由于水是沒有顏色的,他只是靠反射折射獲取顏色。所以說,在Pixel(Fragment) Shader完成的工作是進(jìn)行紋理貼圖的顏色調(diào)制。這個(gè)公式來自微軟研究院的幾個(gè)家伙的一White Paper。C
Water = F
aboveC
reflect+(1-F
above)C
refract+A
shadowC
specular 準(zhǔn)備好你的折射圖,也就是水底的貼圖,立方體貼圖也就是反射圖,以及你的Bump貼圖。這里陰影貼圖一般用BumpMapping了。那個(gè)GPU GEMS2中用Vertex Texture Fetch生成水波的,不是打擊其他人,需要一個(gè)非常有經(jīng)驗(yàn)的美工才行呵呵。F是Fresnel系數(shù),也就是衰減系數(shù)。簡便的公式是
Fresnel = 1 - EyeDir*N或者是寫作1-cos(b)
視覺向量與向量的點(diǎn)乘。我不知道應(yīng)該轉(zhuǎn)換到正切空間中,從幾何的角度來說應(yīng)該是一樣的。
上面的混色公式用GLSL還是cg還是FX都可以很簡單的使用。
關(guān)鍵就這些的差不多了。只需要一個(gè)很小的框架程序就可以很簡單的作一切了。
我從來不封裝DLL,對(duì)于任何人來說,那些都是神秘的二進(jìn)制。我只把我掌握的東西奉獻(xiàn)給大家,讓大多數(shù)人明白背后的道理。
posted on 2006-08-03 09:50
周波 閱讀(1143)
評(píng)論(0) 編輯 收藏 引用 所屬分類:
無庸技術(shù)