2012-11-15 48 views
3

我正在嘗試向我的地形生成器添加陰影/照明。但由於某種原因,即使在計算表面法線之後,我的輸出仍然看起來很塊。在Open GL中計算表面法線

set<pair<int,int> >::const_iterator it; 

for (it = mRandomPoints.begin(); it != mRandomPoints.end(); ++it) 
{ 
    for (int i = 0; i < GetXSize(); ++i) 
    { 
     for (int j = 0; j < GetZSize(); ++j) 
     { 
      float pd = sqrt(pow((*it).first - i,2) + pow((*it).second - j,2))*2/mCircleSize; 
      if(fabs(pd) <= 1.0) 
      { 
       mMap[i][j][2] += mCircleHeight/2 + cos(pd*3.14)*mCircleHeight/2; ; 
      } 

     } 
    } 
} 

/* 
    The three points being considered to compute normals are 
    (i,j) 
    (i+1,j) 
    (i, j+1) 
*/ 

for (int i = 0; i < GetXSize() -1 ; ++i) 
{ 
    for (int j = 0; j < GetZSize() - 1; ++j) 
    { 
     float b[] = {mMap[i+1][j][0]-mMap[i][j][0], mMap[i+1][j][1]-mMap[i][j][1], mMap[i+1][j][2]-mMap[i][j][2] }; 
     float c[] = {mMap[i][j+1][0]-mMap[i][j][0], mMap[i][j+1][1]-mMap[i][j][1], mMap[i][j+1][2]-mMap[i][j][2] }; 
     float a[] = {b[1]*c[2] - b[2]*c[1], b[2]*c[0]-b[0]*c[2], b[0]*c[1]-b[1]*c[0]}; 

     float Vnorm = sqrt(pow(a[0],2) + pow(a[1],2) + pow(a[2],2)); 

     mNormalMap[i][j][0] = a[0]/Vnorm; 
     mNormalMap[i][j][1] = a[1]/Vnorm; 
     mNormalMap[i][j][2] = a[2]/Vnorm; 

    } 
} 

然後當繪製這個我用下面的

float*** normal = map->GetNormalMap(); 

for (int i = 0 ; i < map->GetXSize() - 1; ++i) 
{ 
    glBegin(GL_TRIANGLE_STRIP); 

    for (int j = 0; j < map->GetZSize() - 1; ++j) 
    { 

     glNormal3fv(normal[i][j]); 


     float color = 1 - (terrain[i][j][2]/height); 
     glColor3f(color,color, color); 
     glVertex3f(terrain[i][j][0], terrain[i][j][2], terrain[i][j][1]); 
     glVertex3f(terrain[i+1][j][0], terrain[i+1][j][2], terrain[i+1][j][1]); 
     glVertex3f(terrain[i][j+1][0], terrain[i][j+1][2], terrain[i][j+1][1]); 
     glVertex3f(terrain[i+1][j+1][0], terrain[i+1][j+1][2], terrain[i+1][j+1][1]); 
    } 

    glEnd(); 
} 

編輯:初始化代碼

glFrontFace(GL_CCW); 
glCullFace(GL_FRONT); // glCullFace(GL_BACK); 
glEnable(GL_CULL_FACE); 
glEnable(GL_DEPTH_TEST); 
glShadeModel(GL_SMOOTH); 
glEnable(GL_POLYGON_SMOOTH); 
glMatrixMode(GL_PROJECTION); 

我是不是計算法線是否正確?

+2

旁註:你正在使用的低效的代碼越好。爲什麼不''a [0] * a [0]'而不是'pow(a [0],2)'?爲什麼要計算平方根,然後使用slooooow浮點除法,而不是僅使用[快速倒平方根](http://en.wikipedia.org/wiki/Fast_inverse_square_root)? – 2012-11-15 07:19:58

+0

這裏對圖形編程不熟悉,我並不是真的希望使它更加高效,而是提到快速平方根的+1。 – Anonymous

+0

我剛纔補充說我看不出有什麼區別 – Anonymous

回答

8

除了Bovinedragon的建議,即glShadeModel(GL_SMOOTH);,你應該使用每個頂點的法線。這意味着每個glVertex3f之前都會有一個glNormal3fv調用,它將定義所有相鄰面的平均法線。要獲得它,您可以簡單地將這些相鄰的法向量相加並對結果進行歸一化。

enter image description here

參考這個問題:Techniques to smooth face edges in OpenGL

2

您是否將glShadeModel設置爲GL_SMOOTH?

請參見:http://www.khronos.org/opengles/documentation/opengles1_0/html/glShadeModel.html

這個設置也影響除了照明的頂點顏色。你似乎說甚至在照明之前它是塊狀的,這讓我覺得這是問題。

+0

我做到了,我將張貼初始化代碼 – Anonymous

+0

我認爲num3ric有正確的答案。我注意到的另一件事是,你沒有計算完全正確的頂點法線。通常要計算頂點的法線,以平均每個接觸該頂點的面的法線。看起來你只是選擇其中一個頂點並使用其正常而不考慮其他頂點。 – Bovinedragon