由于缺乏对纹理坐标的理解,场景体素化不起作用

Scene voxelization not working due to lack of comprehension of texture coordinates

目标是采用任意几何体并创建包含场景的体素近似值的 3D 纹理。但是现在我们只有立方体。

场景如下:

这些场景最重要的两个方面如下:

场景中的每个立方体都应该对应于 3D 纹理中的一个体素。场景几何体随着高度的增加而变小(类似于金字塔)。场景几何体是空心的(也就是说,如果你进入这些山丘之一,内部没有立方体,只有轮廓有)。

为了对场景进行体素化,我们逐层渲染如下:

glViewport(0, 0, 7*16, 7*16);
glBindFramebuffer(GL_FRAMEBUFFER, FBOs[FBO_TEXTURE]);

for(int i=0; i<4*16; i++)
{
    glFramebufferTexture3D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_3D, 
        vMap->textureID, 0, i);

    glClearColor(0.f, 0.f, 0.f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    load_uniform((float)i, "level");
    draw();
}

其中"level"对应当前图层

然后在顶点着色器中,我们尝试创建一个单层,如下所示;

#version 450

layout(location = 0) in vec3 position; //(x,y,z) coordinates of a vertex

layout(std430, binding = 3) buffer instance_buffer
{
    vec4 cubes_info[];//first 3 values are position of object 
};

out vec3 normalized_pos;

out float test;

uniform float width = 128;
uniform float depth = 128;
uniform float height = 128;

uniform float voxel_size = 1;

uniform float level=0;

void main()
{
    vec4 pos = (vec4(position, 1.0) + vec4(vec3(cubes_info[gl_InstanceID]),0));

    pos.x = (2.f*pos.x-width)/(width);
    pos.y = (2.f*pos.y-depth)/(depth);
    pos.z = floor(pos.z);

    test = pos.z;
    pos.z -= level;

    gl_Position = pos;
}

最后是片段着色器:

#version 450

in vec3 normalized_pos;
in float l;

in float test;

out vec4 outColor;//Final color of the pixel

void main()
{
    outColor = vec4(vec3(test)/10.f, 1.0);

}

我使用 renderdoc 截取了一些结果纹理的截图:

第 0 层:

第 2 层:

眼前的两个值得注意的问题是:

一个图层不应该有多个灰色调,只有一个(因为每个图层对应不同的高度,所以不应该将多个高度渲染到同一图层)

第 2 层最暗的部分看起来像第 0 层应该看起来的样子(即没有 "holes" 的填充形状)。所以我不仅在同一层上渲染了多个高度,而且在渲染时我的偏移量似乎也为 2,这不应该发生。

有人知道问题出在哪里吗?

编辑:

如果有人想知道立方体的尺寸为 [1,1,1] 并且它们的坐标系与纹理对齐。即第一个立方体的左下角和前角位于 (0,0,0)

编辑 2:

改变

pos.z = floor(pos.z); 

收件人: pos.z = 楼层数(pos.z)+0.1;

部分解决了问题。最低层现在是正确的,但是现在有 2 个而不是 3 个不同的颜色(高度值)。

编辑 3:

问题似乎出在多次绘制几何体上。 即我实际的抽签看起来像:

for(uint i=0; i<render_queue.size(); i++)
    {
        Object_3D *render_data = render_queue[i]; 
        //Render multiple instances of the current object
        multi_render(render_data->VAO, &(render_data->VBOs), 
            &(render_data->types), render_data->layouts, 
            render_data->mesh_indices, render_data->render_instances);
    }

void Renderer::multi_render(GLuint VAO, vector<GLuint> *VBOs, 
    vector<GLuint> *buffer_types, GLuint layout_num, 
    GLuint index_num, GLuint instances)
{
    //error check
    if(VBOs->size() != buffer_types->size())
    {
        cerr << "Mismatching VBOs's and buffer_types sizes" << endl;
        return;
    }

    //Bind Vertex array object and rendering rpogram
    glBindVertexArray(VAO);
    glUseProgram(current_program);

    //enable shader layouts
    for(int i=0; i<layout_num;i++)
        glEnableVertexAttribArray(i);

    //Bind VBO's storing rendering data
    for(uint i=0; i<buffer_types->size(); i++)
    {
        if((*buffer_types)[i]==GL_SHADER_STORAGE_BUFFER)
        {
            glBindBuffer((*buffer_types)[i], (*VBOs)[i]);
            glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, (*VBOs)[i]);
        }
    }
    //Draw call
    glDrawElementsInstanced(GL_TRIANGLES, index_num, GL_UNSIGNED_INT, (void*)0, instances);
}

似乎由于一次渲染场景的多个子集,我最终在 2 个不同的绘制调用中将不同的立方体映射到同一体素。

我找到问题了

由于我的几何体与体素网格 1 比 1 匹配。不同的层可以映射到相同的体素,导致它们在同一层重叠。

修改片段着色器如下:

#version 450

layout(location = 0) in vec3 position; //(x,y,z) coordinates of a vertex

layout(std430, binding = 3) buffer instance_buffer
{
    vec4 cubes_info[];//first 3 values are position of object 
};

out vec3 normalized_pos;

out float test;

uniform float width = 128;
uniform float depth = 128;
uniform float height = 128;

uniform float voxel_size = 1;

uniform float level=0;

void main()
{
    vec4 pos = (vec4(position, 1.0) + vec4(vec3(cubes_info[gl_InstanceID]),0));

    pos.x = (2.f*pos.x-width)/(width);
    pos.y = (2.f*pos.y-depth)/(depth);

    pos.z = cubes_info[gl_InstanceID].z;

    test = pos.z + 1;
    pos.z -= level;

    if(pos.z >=0 && pos.z < 0.999f)
        pos.z = 1;
    else 
        pos.z = 2;

    gl_Position = pos;

    normalized_pos = vec3(pos);
}

修复了问题。

if 语句检查保证丢弃可能映射到当前层的不同层的几何图形。

可能有更好的方法来做到这一点。所以我会接受任何以更优雅的方式产生等效结果的答案。

这是第 0 层现在的样子:

这是第 2 层的样子: