如何用opengl固定函数管道对3d多边形进行体素化

时间:2015-04-07 18:06:48

标签: c++ opengl minecraft voxel

我最近尝试使用固定功能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和网格加载器是正确的,但是即使我评论绘图部分,它仍然给我一些奇怪的结果。(请忽略随机立方体颜色)

enter image description here

1 个答案:

答案 0 :(得分:1)

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

如果您真的坚持使用OpenGL使用基于图像的方法来做到这一点,那么通过两个剪裁平面剪切网格的结果将是一组轮廓;然后,您可以将洪水填充应用于"巩固"它们,然后是3D纹理。