2017-04-05 26 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