我正在尝试将从Blender导出的模型加载到OpenGL中。特别是,我按照这个tutorial的源代码来帮助我开始。因为加载器相当简单,它只读取顶点坐标和面索引,忽略法线和tex。
然后计算每张脸的法线:
float coord1[3] = { Faces_Triangles[triangle_index], Faces_Triangles[triangle_index+1],Faces_Triangles[triangle_index+2]};
float coord2[3] = {Faces_Triangles[triangle_index+3],Faces_Triangles[triangle_index+4],Faces_Triangles[triangle_index+5]};
float coord3[3] = {Faces_Triangles[triangle_index+6],Faces_Triangles[triangle_index+7],Faces_Triangles[triangle_index+8]};
float *norm = this->calculateNormal( coord1, coord2, coord3 );
float* Model_OBJ::calculateNormal( float *coord1, float *coord2, float *coord3 )
{
/* calculate Vector1 and Vector2 */
float va[3], vb[3], vr[3], val;
va[0] = coord1[0] - coord2[0];
va[1] = coord1[1] - coord2[1];
va[2] = coord1[2] - coord2[2];
vb[0] = coord1[0] - coord3[0];
vb[1] = coord1[1] - coord3[1];
vb[2] = coord1[2] - coord3[2];
/* cross product */
vr[0] = va[1] * vb[2] - vb[1] * va[2];
vr[1] = vb[0] * va[2] - va[0] * vb[2];
vr[2] = va[0] * vb[1] - vb[0] * va[1];
/* normalization factor */
val = sqrt( vr[0]*vr[0] + vr[1]*vr[1] + vr[2]*vr[2] );
float norm[3];
norm[0] = vr[0]/val;
norm[1] = vr[1]/val;
norm[2] = vr[2]/val;
return norm;
}
我有2个问题。
GL_SMOOTH
。这是不正确的,因为如果使用GL_SMOOTH
而不是GL_FLAT
,我需要为每个顶点提供法线? 答案 0 :(得分:4)
glFrontFace
确定风顺序
风顺序意味着一组顶点应该出现的顺序,以使法线被认为是正数。考虑下面的三角形。它的顶点是顺时针定义的。如果我们告诉OpenGL glFrontFace(GL_CW)
(顺时针方向是指正面),那么法线基本上就会从屏幕上向你伸出,以便被认为是“向外”。
在旁注中,逆时针是默认值,您应该坚持使用。
无论如何,您需要真正定义法线,尤其是当您想要在场景中进行任何照明时,因为它们用于照明计算。 glFrontFace
只是让你告诉OpenGL你想要解释多边形的前面是什么。
在上面的示例和下图中,如果我们告诉OpenGL我们定义了面逆时针以及glEnable
d glCullFace
并将其设置为{{1然后我们的三角形不会出现,因为我们会看到它的后面,我们告诉OpenGL不要显示多边形的背面。
您可以在此处详细了解面部剔除:Face Culling。
Wavefront GL_BACK
has support,如果您不想自己创建法线,则可以在文件中声明法线。只需确保您的导出商添加它们。
另外,Wavefront希望每个顶点都有一个正常的定义:
.obj
其中f v1//vn1 v2//vn2 v3//vn3 ...
是vN
面的顶点,而f
是顶点的法线。通过为每个顶点提供法线,您可以获得比通过定义每个面的法线或通过将同一个面的顶点的所有法线设置为相同更平滑的外观。看看这个问题,看看你可以在球体上做出的区别:OpenGL: why do I have to set a normal with glNormal?
如果您的.obj文件没有定义法线,我会使用面定义顺序并跨越定义面的两条边。请考虑此处使用的方法:Calculating a Surface Normal
修改强>
我想我可能有点困惑。多边形的正面仅与其法线略微相关。法线仅用于照明计算。你没有拥有来拥有它们,但它们是计算对象亮度时使用的一大变量。
我正在同时解释多边形的“前脸”,因为在讨论凸多边形时,你的法线会突然从三角形的“前面”伸出来你想要的形状。
如果你创造了一个巨大的洞穴,或者你的相机主要位于一些凹形内部,那么将法线指向内部是有意义的,因为你的光源可能想要从内部反弹你的形状。
vnN
确定要与GL_SMOOTH
glShadeModel
表示平滑着色,其中颜色实际上在每个顶点之间插值,而GL_SMOOTH
表示平面着色,其中仅使用一种颜色。通常,您将使用默认值GL_FLAT
。
在任何一种情况下,你都没有拥有来定义每个顶点的法线。但是,如果你希望GL_SMOOTH
看起来“好”,你可能会想要,因为它会在每个顶点之间渲染时进行插值,而不是仅为属性选择一个顶点。
另外,请记住,每当您离开固定功能管道并开始使用着色器时,所有这些都会消失。