OpenGL ES 3.0球体渲染异常:内部水平圆环问题排查
OpenGL ES 3.0球体渲染出现内部水平圆环的原因排查
我用OpenGL ES 3.0渲染球体,把FragColor设为球体法线值,但渲染后球体出现内部水平圆环,请问可能是什么原因?
(异常渲染效果截图:
)
以下是我的球体顶点生成代码:
if(sphereVAO == 0){ struct Vertex { float x, y, z; // Position float nx, ny, nz; // Normal float u, v; // UV coordinates }; std::vector<Vertex> vertices; int stacks = 30; int slices = 30; float radius = 1.0f; for (int stack = 0; stack <= stacks; ++stack) { float phi = stack * M_PI / stacks; // Azimuthal angle float sinPhi = sin(phi); float cosPhi = cos(phi); for (int slice = 0; slice <= slices; ++slice) { float theta = slice * 2 * M_PI / slices; // Polar angle float sinTheta = sin(theta); float cosTheta = cos(theta); float x = cosTheta * sinPhi; float y = cosPhi; float z = sinTheta * sinPhi; float nx = x; float ny = y; float nz = z; float u = static_cast<float>(slice) / slices; float v = static_cast<float>(stack) / stacks; vertices.push_back({x * radius, y * radius, z * radius, nx, ny, nz, u, v}); } } std::vector<Vertex> sphereVertices; int numSlices = slices + 1; for (int stack = 0; stack < stacks; ++stack) { for (int slice = 0; slice < slices; ++slice) { int currRow = stack * numSlices; int nextRow = (stack + 1) * numSlices; // Add two triangles sphereVertices.push_back(vertices[currRow + slice]); sphereVertices.push_back(vertices[nextRow + slice]); sphereVertices.push_back(vertices[currRow + slice + 1]); sphereVertices.push_back(vertices[nextRow + slice]); sphereVertices.push_back(vertices[nextRow + slice + 1]); sphereVertices.push_back(vertices[currRow + slice + 1]); } } GLuint vbo; glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, sphereVertices.size() * sizeof(Vertex), sphereVertices.data(), GL_STATIC_DRAW); glGenVertexArrays(1, &sphereVAO); glBindVertexArray(sphereVAO); // Enable the vertex attributes glEnableVertexAttribArray(0); // Position attribute glEnableVertexAttribArray(1); // Normal attribute glEnableVertexAttribArray(2); // UV attribute // Specify the attribute pointers glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<const void*>(offsetof(Vertex, x))); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<const void*>(offsetof(Vertex, nx))); glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<const void*>(offsetof(Vertex, u))); glDrawArrays(GL_TRIANGLE_STRIP, 0, static_cast<GLsizei>(sphereVertices.size())); num_sphere_indices = static_cast<GLsizei>(sphereVertices.size()); } else{ // glBindVertexArray(sphereVAO); // glDrawElements(GL_TRIANGLES, num_sphere_indices, GL_UNSIGNED_INT, 0); glBindVertexArray(sphereVAO); glDrawArrays(GL_TRIANGLE_STRIP, 0, num_sphere_indices); }
问题根源
核心错误是渲染模式与顶点数据格式不匹配:
你的sphereVertices是按GL_TRIANGLES格式构建的——每3个顶点组成一个独立三角形,总共添加了两组三角形的顶点数据。但你调用glDrawArrays时用了GL_TRIANGLE_STRIP,这种模式会按连续顶点的顺序自动拼接三角形,导致原本独立的三角形被错误连接,生成额外的畸形面,也就是你看到的内部水平圆环。
解决方案
将渲染模式改为GL_TRIANGLES即可修复:
// 初始化时的绘制调用 glDrawArrays(GL_TRIANGLES, 0, static_cast<GLsizei>(sphereVertices.size())); // 后续渲染时的调用 glDrawArrays(GL_TRIANGLES, 0, num_sphere_indices);
另外,代码中注释掉的glDrawElements部分,若后续想优化顶点复用,可考虑使用索引缓冲(EBO)配合GL_TRIANGLES,能减少顶点数据冗余,但当前问题的核心是渲染模式不匹配。
内容的提问来源于stack exchange,提问作者Palash
相关产品推荐
相关产品推荐

