You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OpenGL ES 3.0球体渲染异常:内部水平圆环问题排查

OpenGL ES 3.0球体渲染出现内部水平圆环的原因排查

我用OpenGL ES 3.0渲染球体,把FragColor设为球体法线值,但渲染后球体出现内部水平圆环,请问可能是什么原因?

(异常渲染效果截图:Sphere Image)

以下是我的球体顶点生成代码:

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 11:08:15