由于缺乏对纹理坐标的理解,场景体素化不起作用
Posted
技术标签:
【中文标题】由于缺乏对纹理坐标的理解,场景体素化不起作用【英文标题】:Scene voxelization not working due to lack of comprehension of texture coordinates 【发布时间】:2018-03-07 22:05:20 【问题描述】:目标是采用任意几何形状并创建包含场景体素近似值的 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();
其中“级别”对应于当前层。
然后在顶点着色器中我们尝试如下创建一个单层;
#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 个明显问题是:
一个图层不应该有多个灰色调,只有一个(因为每个图层对应不同的高度,所以不应将多个高度渲染到同一图层)
第 2 层的最暗部分看起来像第 0 层的样子(即没有“孔”的填充形状)。因此,我不仅似乎将多个高度渲染到同一层,而且在渲染时似乎我的偏移量为 2,这是不应该发生的。
有人知道问题可能是什么吗?
编辑:
如果有人想知道立方体的尺寸为 [1,1,1] 并且它们的坐标系与纹理对齐。即第一个立方体的底部,左侧,前角位于(0,0,0)
编辑 2:
变化
pos.z = floor(pos.z);
到: pos.z = 地板(pos.z)+0.1;
部分解决了问题。最低层现在是正确的,但是现在不是 3 种不同的颜色(高度值),而是 2 种。
编辑 3:
问题似乎来自多次绘制几何图形。 即我的实际draw 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 个不同的绘制调用中将不同的立方体映射到同一个体素。
【问题讨论】:
您的实际绘图调用是什么样的?我假设您正在调用 glDrawArrays|ElementsInstanced,因为您正在从顶点着色器中的 gl_InstanceID 读取数据? 没错,我的实际绘制调用是一个实例化绘制调用,它在不同位置呈现相同的立方体网格。我将添加一些我刚刚遇到的问题的信息。 @Jay 问题已解决,但我对我的回答不满意。如果您有更好的建议,我将不胜感激。 【参考方案1】:我已经解决了问题。
由于我的几何图形与体素网格 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 层的样子:
【讨论】:
切换到非实例化渲染可能很有用,这样您就可以查看 RenderDoc 中的每个实例。 IE。调用 glDrawElements N 次而不是调用 glDrawElementsInstanced 一次,并使用手动更新的统一而不是 gl_InstanceID。这样您就可以在 RenderDoc 中查看每个单独的绘图。以上是关于由于缺乏对纹理坐标的理解,场景体素化不起作用的主要内容,如果未能解决你的问题,请参考以下文章