Automatically calculate normals in GLKit / OpenGL-ES

I am making some fairly simple forms in OpenGL-ES based on Apple's sample code. They used an array of points with an array of indices in the first array, and each set of three indices creates a polygon. All this is great, I can make the shapes that I want. To properly shade the shapes, I believe that I need to calculate the normals for each vertex on each polygon. At first the shapes were cubic, so it was very easy, but now I am making (slightly) more complex shapes that I want to create these normals automatically. It seems easy enough if I get vectors for two edges of a polygon (here all policies are triangles) and use their cross-product for each vertex on this polygon. After that, I use the code as shown below to draw the figure.

glEnableVertexAttribArray(GLKVertexAttribPosition); glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 0, triangleVertices); glEnableVertexAttribArray(GLKVertexAttribColor); glVertexAttribPointer(GLKVertexAttribColor, 4, GL_FLOAT, GL_FALSE, 0, triangleColours); glEnableVertexAttribArray(GLKVertexAttribNormal); glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 0, triangleNormals); glDrawArrays(GL_TRIANGLES, 0, 48); glDisableVertexAttribArray(GLKVertexAttribPosition); glDisableVertexAttribArray(GLKVertexAttribColor); glDisableVertexAttribArray(GLKVertexAttribNormal); 

I am having trouble understanding, so I have to do it manually. I am sure that there are cases when you need something other than just a vector perpendicular to the surface, but I am also sure that this is the most popular use case today, so there shouldn't be an easier way? Am I missing something obvious? glCalculateNormals () would be great.

// And here is the answer Go to GLKVector3 [], which you want to fill with your normals, another with vertices (each three are grouped into polygons), and then a vertex counter.

 - (void) calculateSurfaceNormals: (GLKVector3 *) normals forVertices: (GLKVector3 *)incomingVertices count:(int) numOfVertices { for(int i = 0; i < numOfVertices; i+=3) { GLKVector3 vector1 = GLKVector3Subtract(incomingVertices[i+1],incomingVertices[i]); GLKVector3 vector2 = GLKVector3Subtract(incomingVertices[i+2],incomingVertices[i]); GLKVector3 normal = GLKVector3Normalize(GLKVector3CrossProduct(vector1, vector2)); normals[i] = normal; normals[i+1] = normal; normals[i+2] = normal; } } 
+4
source share
1 answer

And again the answer: OpenGL is neither a scene control library, nor a geometric library, but simply a drawing API that draws nice pictures on the screen. Normals are needed for lighting, and you give it normals. All this. Why should he calculate the normals if it can just be done by the user and has nothing to do with the actual drawing?

Often you do not calculate them at runtime anyway, but you load them from a file. And there are many ways to calculate normals. Do you want normal on the face or normal vertices? Do you need any specific hard edges or any special smooth spots? If you want to average face normals to get vertex normals, how do you want to average them?

And with the advent of shaders and the removal of built-in normal attributes and lighting calculations in new versions of OpenGL, this whole question becomes obsolete anyway, since you can do lighting in any way, and you do not need traditional normals.

By the way, it looks like you are using normals on the face, which means that each vertex of the face has the same normal character. This creates a very grandiose model with hard edges, and also does not work very well with indexes. If you want a smooth model (I don’t know, maybe you really need a faceted look), you should align the face normals of adjacent faces for each vertex to calculate the normals on the vertices. This would actually be a more common precedent, rather than normal for the face.

So you can do something like this pseudocode:

 for each vertex normal: intialize to zero vector for each face: compute face normal using cross product add face normal to each vertex normal of this face for each vertex normal: normalize 

to get smooth per-vertex normals. Even in real code, this should lead to something between 10 and 20 lines of code, which is not very difficult.

+2
source

Source: https://habr.com/ru/post/1384664/


All Articles