如何使用 opengl 固定功能管道对 3d 多边形进行体素化

How to voxelize 3d polygon with opengl fixed function pipeline

我最近尝试使用固定函数 opengl 对 3D 多边形网格进行体素化。

void VoxelizeWithOpenGL(const Mesh &in, uint32_t width, uint32_t height, 
    uint32_t depth, uint8_t *out)
{
    GLuint texture_id, fbo_id;

    glGenTextures(1, &texture_id);
    glEnable(GL_TEXTURE_3D);
    glBindTexture(GL_TEXTURE_3D, texture_id);
    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB8, width, height, depth, 0, GL_RGB, 
         GL_UNSIGNED_BYTE, (void *)0);

    glGenFramebuffers(1, &fbo_id);
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_id);
    glFramebufferTexture3D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_3D, texture_id, 0, 0);
    GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0 };
    glDrawBuffers( 1, drawBuffers );

    GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
    if (status != GL_FRAMEBUFFER_COMPLETE)
        throw std::runtime_error("Cannot create 3D framebuffer.");

    glViewport(0, 0, width, height);

    const AABB &aabb = FindAABB(in);
    const glm::mat4 &proj = glm::ortho(aabb.min_x, aabb.max_x, aabb.min_y, aabb.max_y,
        aabb.min_z, aabb.max_z);

    glMatrixMode(GL_PROJECTION);
    glLoadMatrixf(glm::value_ptr(proj));
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    //glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    /*glBegin(GL_TRIANGLES);
    for(const Face &c: in.faces)
    {
        const glm::vec3 &o=c.o.pos;
        const glm::vec3 &a=c.a.pos;
        const glm::vec3 &b=c.b.pos;

        glVertex3fv(glm::value_ptr(o));
        glVertex3fv(glm::value_ptr(a));
        glVertex3fv(glm::value_ptr(b));
    }
    glEnd();*/

    //Read from GPU to RAM
    glBindTexture(GL_TEXTURE_3D, texture_id);
    glGetTexImage(GL_TEXTURE_3D, 0, GL_RGB, GL_UNSIGNED_BYTE, out);

    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
    glDeleteFramebuffers(1, &fbo_id);
    glDeleteTextures(1, &texture_id);
}

我很确定 FindAABB 和网格加载器是正确的,但是它总是给我奇怪的结果,即使我评论了绘图部分。(请忽略随机立方体颜色)

你在那里试图做什么,它不是那样工作的。当您将 3D 纹理绑定为 FBO 的颜色附件时,您实际上只绑定了一层纹理。为此,您还必须 "cut away" 沿该层跨度一定深度之外的网格的所有部分。然而,三角网格不是实体的,它们只是一个轮廓。所以这并不适用于应用裁剪平面。您必须 "solidify" 您的网格。在没有 OpenGL 的情况下,通过将网格数据放入空间细分结构(如八叉树),可以更轻松地完成此操作。网格必须是可定向的;如果满足这个约束,那么就可以直接从空间细分结构中读出体素。

如果您真的坚持使用基于图像的方法使用 OpenGL 来执行此操作,则用两个裁剪平面裁剪网格的结果将是一组轮廓;然后,您可以对 "solidify" 它们应用洪水填充,这就是进入 3D 纹理的内容。