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

时间:2018-03-07 22:05:21

标签: c++ opengl textures shader vertex-shader

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

场景如下:

enter image description here

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

场景中的每个立方体应该对应于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层: enter image description here

第2层:

enter image description here

直接的两个明显问题是:

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

第2层最暗的部分看起来像0层应该是什么样的(即没有“洞”的填充形状)。因此,不仅看起来我在同一层渲染多个高度,在渲染时我似乎也有2的偏移,这不应该发生。

有没有人知道问题可能是什么?

编辑:

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

编辑2:

更改

pos.z = floor(pos.z); 

要:     pos.z = floor(pos.z)+0.1;

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

编辑3:

似乎问题来自多次绘制几何体。 ,我的实际绘制clal看起来像:

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 个答案:

答案 0 :(得分:0)

我已经找到了问题。

由于我的几何与体素网格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层:

enter image description here

这就是第2层的样子:

enter image description here