我正在OpenGL-ES中制作一些基本图形,参考了Apple的示例代码。他们使用了一个点数组,并在第一个数组中用一个索引数组和每组三个索引创建多边形。这很不错,我可以做出我想要的形状。为了正确着色这些图形,我相信需要为每个多边形上的每个顶点计算法向量。最初这些形状是长方体,所以非常容易,但现在我正在制作(稍微)更高级的形状,我想自动创建这些法向量。如果我得到一个多边形两个边的向量(这里所有多边形都是三角形),并使用它们的叉积来计算该多边形上每个顶点的法向量,这似乎很容易。之后我使用下面的代码来绘制形状。
我不太理解的是为什么我必须手动执行此操作。我确信除了一个垂直于表面的向量以外,还有其他情况需要考虑,但我也确信这是最常见的用例,所以难道没有更简单的方法吗?我是否错过了一些显而易见的东西? glCalculateNormals() 将非常实用。
//以下是答案 传入一个 GLKVector3[] 数组来存储您的法线向量,另一个数组存储顶点(每个三角形都由三个顶点组成),然后再传入顶点的数量。
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);
我不太理解的是为什么我必须手动执行此操作。我确信除了一个垂直于表面的向量以外,还有其他情况需要考虑,但我也确信这是最常见的用例,所以难道没有更简单的方法吗?我是否错过了一些显而易见的东西? glCalculateNormals() 将非常实用。
//以下是答案 传入一个 GLKVector3[] 数组来存储您的法线向量,另一个数组存储顶点(每个三角形都由三个顶点组成),然后再传入顶点的数量。
- (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;
}
}
glDrawElements
)并完全减少重复,因为每个唯一的顶点具有相同的法线。对于每个面的法线,索引不会带来任何好处,因为您无论如何都需要复制顶点,因为每个具有唯一位置的顶点可能具有多个不同的法线。 - Christian RauglDrawArrays
。在这种情况下,你当然需要36个顶点。关键是,要时刻记住一个顶点不仅仅是一个位置,而是所有顶点属性的集合。因此,如果你想让两个顶点具有相同的位置但不同的法线,这在使用每个面法线时是必需的,所以重复是自然的。 - Christian Rau