2017-04-05 76 views
2

我目前正在實現一個基於these lessons的模擬OpenGL作爲學習體驗的軟件渲染器。我的項目代碼可以是found here.3D圖形網格法向量旋轉加倍

我在處理頂點法線方面遇到了一些困難。我想用模型矩陣對它們進行變換,我知道當矩陣不正交時應該使用模型矩陣的逆轉置。光的方向應該在世界空間中指定,因此應該轉換法線,然後用世界空間光方向的點積來計算光強。

雖然這是個問題。它在這裏工作得很好,請注意相機在向上旋轉45度時看着模型。

Front view

如果我旋轉模型以任何軸旋轉90度,取向上軸現在,光的方向翻轉到指向的其他方式。正如你在這裏看到的那樣,光線從後面傳來。

enter image description here

如果我轉180度,它的罰款一次。

enter image description here

如果我旋轉到45度的光點在90度在此顯示。注意尖峯,看看光線從哪裏來。

enter image description here

這已經困擾了我好幾個小時。我無法弄清楚什麼是錯的。就好像旋轉在光線上翻了一番。光矢量未被雖然改變了,看看這裏:

vec4 SmoothShader::Vertex(int iFace, int nthVert) 
{ 
    vec3 vposition = model->vert(iFace, nthVert); 
    vec4 projectionSpace = MVP * embed<4>(vposition); 

    vec3 light = vec3(0, 0, 1); 

    mat4 normTrans = M.invert_transpose(); 
    vec4 normal = normTrans * embed<4>(model->normal(iFace, nthVert), 0.f); 
    vec3 norm = proj<3>(normal); 
    intensity[nthVert] = std::max(0.0f, norm.normalise() * light.normalise()); 

    return projectionSpace; 
} 

bool SmoothShader::Fragment(vec3 barycentric, vec3 &Colour) 
{ 
    float pixelIntensity = intensity * barycentric; 
    Colour = vec3(255, 122, 122) * pixelIntensity; 
    return true; 
} 

的MVP(模型,視圖投影)和M(模式)矩陣計算如下:

// Model Matrix, converts to world space 
mat4 scale = MakeScale(o->scale); 
mat4 translate = MakeTranslate(o->position); 
mat4 rotate = MakeRotate(o->rotation); 

// Move objects backward from the camera's position 
mat4 cameraTranslate = MakeTranslate(vec3(-cameraPosition.x, -cameraPosition.y, -cameraPosition.z)); 

// Get the camera's rotated basis vectors to rotate everything to camera space. 
vec3 Forward; 
vec3 Right; 
vec3 Up; 
GetAxesFromRotation(cameraRotation, Forward, Right, Up); 
mat4 cameraRotate = MakeLookAt(Forward, Up); 

// Convert from camera space to perspective projection space 
mat4 projection = MakePerspective(surf->w, surf->h, 1, 10, cameraFOV); 

// Convert from projection space (-1, 1) to viewport space 
mat4 viewport = MakeViewport(surf->w, surf->h); 

mat4 M = translate * rotate * scale; 
mat4 MVP = viewport * projection * cameraRotate * cameraTranslate * M; 

任何想法我做錯了?

回答

1

您應該使用模型矩陣而不是其倒數來轉換法線。你的照明行爲就像它一樣,因爲你正在向與頂點位置相反的方向旋轉頂點法線。

vec4 normal = M * embed<4>(model->normal(iFace, nthVert), 0.f); 

爲了避免這樣的困惑,我會建議使用的命名方案advocated by Tom Forsyth,並調用Mworld_from_object矩陣,因爲它是從對象空間世界空間的轉換。

vec4 light_world = vec4(0.f, 0.f, 1.f, 0.f); 
vec4 normal_object = embed<4>(model->normal(iFace, nthVert), 0.f); 
vec4 normal_world = world_from_object * normal_object; 
float intensity = std::max(0.f, light_world * normal_world); 

如果您使用過這種方案,那很明顯您正在使用錯誤的轉換。

mat4 object_from_world = world_from_object.invert_transpose(); 
vec4 normal_world = object_from_world * normal_object; // wrong! 

我個人使用下面的術語來描述不同的空間:

  • 對象空間 - 本地座標系統模型
  • 視野空間的 - 局部座標系統你的相機
  • 光照空間 - 你的光源的局部座標系統
  • 世界空間 - 場景
  • 夾空間的全球座標系 - 歸一化的屏幕座標

因此,我會打電話的MVP矩陣的矩陣clip_from_object

+0

恐怕這不起作用,沒有任何改變。模型矩陣在這種情況下是正交的,所以它的逆轉換實際上是同樣的事情。儘管許多在線資源都表示,當進行非均勻縮放(非正交)時,例如在轉換法線時需要逆轉置。 – Constan7ine

+0

@ Constan7ine對不起。我錯誤地認爲你正在乘以逆。逆轉置是有意義的。我會再看一次。 –

+0

@ Constan7ine我看不到任何其他問題。我認爲你的問題可能在於你的代碼庫中的其他地方。 –

1

你的模型矩陣傳遞給着色器:

   o->shader->M = cameraRotate * cameraTranslate * Model; 

所以實際的M矩陣不是型號矩陣,但模型視圖矩陣,即你現在乘以模型視圖空間。我不確定,但可能會導致模糊的結果。

+0

是的,這是從github回購不是它,它有點過時。上面的圖片是在傳遞模型矩陣時拍攝的。謝謝您的好意。 – Constan7ine