简体   繁体   English

opengl计算脸部正常

[英]opengl calculate normal for face

I am attempting to load models exported from Blender into OpenGL. 我试图将从Blender导出的模型加载到OpenGL中。 Particularly, I followed the source code from this tutorial to help me get started. 特别是,我遵循了本教程中的源代码来帮助我入门。 Because the loader is fairly simple, it only read in the vertex coordinates as well as face indices, ignoring the normal and tex. 因为加载程序非常简单,所以它仅读取顶点坐标和面索引,而忽略法线和tex。

It then calculates the normal for each face: 然后计算每个面孔的法线:

        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;
        }

I have 2 questions. 我有两个问题。

  1. How do I know if the normal is facing inwards or outwards? 我怎么知道法线是朝内还是朝外? Is there some ordering of the vertices in each row in the .obj file that gives indication how to calculate the normal? .obj文件中每行的顶点是否有一定顺序,以指示如何计算法线?
  2. In the initialization function, he uses GL_SMOOTH . 在初始化函数中,他使用GL_SMOOTH Is this incorrect, since I need to provide normals for each vertex if using GL_SMOOTH instead of GL_FLAT ? 这是不正确的,因为如果使用GL_SMOOTH而不是GL_FLAT则需要为每个顶点提供法线?

Question 1 问题1

glFrontFace determines wind order glFrontFace确定风向

Wind order means, what order a set of vertexes should appear for a normal to be considered positive. 风序是指一组法线应以什么顺序出现才能将法线视为正值。 Consider the triangle below. 考虑下面的三角形。 It's vertexes are defined clockwise. 它的顶点是顺时针定义的。 If we told OpenGL glFrontFace(GL_CW) (That clockwise means front face) then the normal would essentially be sticking right out of the screen towards you in order to be considered "outward". 如果我们告诉OpenGL glFrontFace(GL_CW)glFrontFace(GL_CW) (顺时针表示正面),则法线从本质上将一直朝着您伸出屏幕,以便被视为“向外”。

On a side note, counter-clockwise is the default and what you should stick with. 顺便说一句, 逆时针是默认设置,也是您应该遵循的设置。

No matter what, you need should really define normals especially if you want to do any lighting in your scene as they are used for lighting calculation. 无论如何,您需要真正定义法线,尤其是当您想要在场景中进行任何照明时,因为法线用于照明计算。 glFrontFace just lets you tell OpenGL which way you want to interpret what the front of a polygon is. glFrontFace只是让您告诉OpenGL您想用哪种方式解释多边形的前面。

In the above example, and below diagram, if we told OpenGL that we define faces counter-clockwise and also glEnable d glCullFace and set it to GL_BACK then our triangle wouldn't show up because we would be looking at the back of it and we told OpenGL not to show the back of polygons. 在上面的示例和下面的图中,如果我们告诉OpenGL我们定义了逆时针方向的面孔,并且还定义了glEnable d glCullFace并将其设置为GL_BACK那么我们的三角形将不会显示,因为我们正在看它的背面并且我们告诉OpenGL不要显示多边形的背面。

You can read more about face culling here: Face Culling . 您可以在这里阅读更多有关人脸剔除的信息:人剔除。

三角带顺时针风

Wavefront .obj has support for declaring normals in a file if you don't want to create them yourself. 如果您不想自己创建法线,则Wavefront .obj 支持在文件中声明法线。 Just make sure your exporter adds them. 只要确保您的出口商添加了它们。

Additionaly, Wavefront wants each vertex to have a normal defined: 另外,Wavefront希望每个顶点都有一个法线定义:

f v1//vn1 v2//vn2 v3//vn3 ...

Where vN is the vertex of the f face and vnN is the normal of the vertex. 其中vNf面的顶点,而vnN是该顶点的法线。 By providing a normal for each vertex, you achieve a smoother looking surface than you would by defining a normal per face or by setting all of the normals of vertexes of the same face to be the same. 通过为每个顶点提供法线,与通过为每个面定义法线或将同一面的顶点的所有法线都设置为相同相比,您可以获得外观更平滑的表面。 Take a look at this question to see the difference you can make on a sphere: OpenGL: why do I have to set a normal with glNormal? 看一下这个问题,看看可以在球体上产生什么变化: OpenGL:为什么必须使用glNormal设置法线?

If your .obj file doesn't have normals defined, I would use the face definition order and cross two edges of the defined face. 如果您的.obj文件未定义法线,则将使用面定义顺序并交叉定义的面的两个边缘。 Consider the method used here: Calculating a Surface Normal 考虑此处使用的方法: 计算表面法线

Edit 编辑

I think I may be a little confusing. 我想我可能会有些困惑。 The front face of a polygon is only slightly related to its normals. 多边形的正面与其法线仅稍微相关。 Normals are only really used for lighting calculations. 法线仅真正用于照明计算。 You don't have to have them, but they are one of the big variables used in calculating how lit your object is. 您不必一定要使用它们,但是它们是用于计算对象照明程度的主要变量之一。

I am explaining the "front-faced-ness" of a polygon at the same time because it sort of makes sense, when talking about convex polygons, that your normal would stick out of the "front" of your triangle with respect to the shape you are making. 我正在同时解释多边形的“正面”,因为在谈论凸多边形时,某种意义上说您的法线相对于形状会突出于三角形的“正面”你在做。

If you created a huge cave, or if your camera were to mostly reside inside of some concave shape, then it would make sense to have your normals point inwards since your light sources are probably going to want to bounce off of the inside of your shape. 如果您创建了一个巨大的洞穴,或者您的相机主要位于某个凹形形状内,那么将法线指向内是有意义的,因为光源可能会想要从形状内部反弹。

Question 2 问题2

GL_SMOOTH determines which of the shading models you want to use with glShadeModel GL_SMOOTH确定要与glShadeModel一起使用的阴影模型

GL_SMOOTH means smooth shading, where color is actually interpolated between each vertex, vs GL_FLAT means flat shading, where only one one color will be used. GL_SMOOTH表示平滑阴影,其中颜色实际上是在每个顶点之间插入的,而GL_FLAT表示平面阴影,其中将仅使用一种颜色。 Typically, you'll use the default value, GL_SMOOTH . 通常,您将使用默认值GL_SMOOTH

You don't have to define normals for each vertex in either case. 不必定义为法线在这两种情况下每个顶点。 However, if you want GL_SMOOTH to look "good" you'll probably want to as it will interpolate as it renders between each vertex rather than just picking one vertex for properties. 但是,如果您希望GL_SMOOTH看起来“不错”,您可能会想要它,因为它将在每个顶点之间进行渲染时进行内插,而不是仅选择一个顶点作为属性。


Also, bear in mind that all of this goes out the window whenever you leave the fixed-function pipeline and start using shaders. 另外,请记住,每当您离开固定功能管线并开始使用着色器时,所有这些内容都会消失。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM