如何使用 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 纹理的内容。
我最近尝试使用固定函数 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 纹理的内容。