我使用C ++ + SDL2 + GLEW + Opengl 4.1编写一个像Minecraft一样的小体素游戏。
我正在尽力优化体素渲染。
我将世界滑入大块,然后将这些块整理成块。
每个块包含16x16x16块。
现在,如果编辑一个块(删除/放置一个块),我会重建完整的块和邻居块,然后用vao和vbo将其上传到图形卡。
现在要最小化我必须从cpu传输到gpu的顶点数据,我使用几何着色器。
首先,这是一个好主意吗?
我的意思是几何着色器必须为每个体素面计算基元的每一帧。
然而,我编写了顶点着色器,因此我只需为每个块面传递一个顶点。
为了实现这一点,我使用了vec4。
我用于块位置的前3个元素(x,y,z)和4.用于表示面部显示方向的元素(w)。
0表示回来, 1表示正面, 2表示左, 3意味着对, 4表示底部, 5表示顶部。
现在请忽略UV和法线。
我还上传了GLbyte而不是GLfloat。
这是个好主意吗?
什么是更好/更快的方式?
#version 410
uniform mat4 un_Combined;
layout(points) in;
layout(triangle_strip, max_vertices = 4) out;
in vec2 ge_UV[];
out vec2 fr_UV;
out vec3 fr_Normal;
void main()
{
vec4 o = gl_in[0].gl_Position.xyzw;
if(o.w == 0)
{
gl_Position = un_Combined * vec4(o.x, o.y, o.z, 1);
fr_UV = vec2(0, 0);
fr_Normal = vec3(0, 0, 1);
EmitVertex();
gl_Position = un_Combined * vec4(o.x, o.y + 1, o.z, 1);
fr_UV = vec2(0, 0);
fr_Normal = vec3(0, 0, 1);
EmitVertex();
gl_Position = un_Combined * vec4(o.x + 1, o.y, o.z, 1);
fr_UV = vec2(0, 0);
fr_Normal = vec3(0, 0, 1);
EmitVertex();
gl_Position = un_Combined * vec4(o.x + 1, o.y + 1, o.z, 1);
fr_UV = vec2(0, 0);
fr_Normal = vec3(0, 0, -1);
EmitVertex();
}
else
if(o.w == 1)
{
gl_Position = un_Combined * vec4(o.x + 1, o.y, o.z + 1, 1);
fr_UV = vec2(0, 0);
fr_Normal = vec3(0, 0, 1);
EmitVertex();
gl_Position = un_Combined * vec4(o.x + 1, o.y + 1, o.z + 1, 1);
fr_UV = vec2(0, 0);
fr_Normal = vec3(0, 0, 1);
EmitVertex();
gl_Position = un_Combined * vec4(o.x, o.y, o.z + 1, 1);
fr_UV = vec2(0, 0);
fr_Normal = vec3(0, 0, 1);
EmitVertex();
gl_Position = un_Combined * vec4(o.x, o.y + 1, o.z + 1, 1);
fr_UV = vec2(0, 0);
fr_Normal = vec3(0, 0, 1);
EmitVertex();
}
else
if(o.w == 2)
{
gl_Position = un_Combined * vec4(o.x, o.y, o.z + 1, 1);
fr_UV = vec2(0, 0);
fr_Normal = vec3(0, 0, 1);
EmitVertex();
gl_Position = un_Combined * vec4(o.x, o.y + 1, o.z + 1, 1);
fr_UV = vec2(0, 0);
fr_Normal = vec3(0, 0, 1);
EmitVertex();
gl_Position = un_Combined * vec4(o.x, o.y, o.z, 1);
fr_UV = vec2(0, 0);
fr_Normal = vec3(0, 0, 1);
EmitVertex();
gl_Position = un_Combined * vec4(o.x, o.y + 1, o.z, 1);
fr_UV = vec2(0, 0);
fr_Normal = vec3(-1, 0, 0);
EmitVertex();
}
else
if(o.w == 3)
{
gl_Position = un_Combined * vec4(o.x + 1, o.y, o.z, 1);
fr_UV = vec2(0, 0);
fr_Normal = vec3(0, 0, 1);
EmitVertex();
gl_Position = un_Combined * vec4(o.x + 1, o.y + 1, o.z, 1);
fr_UV = vec2(0, 0);
fr_Normal = vec3(0, 0, 1);
EmitVertex();
gl_Position = un_Combined * vec4(o.x + 1, o.y, o.z + 1, 1);
fr_UV = vec2(0, 0);
fr_Normal = vec3(0, 0, 1);
EmitVertex();
gl_Position = un_Combined * vec4(o.x + 1, o.y + 1, o.z + 1, 1);
fr_UV = vec2(0, 0);
fr_Normal = vec3(1, 0, 0);
EmitVertex();
}
else
if(o.w == 4)
{
gl_Position = un_Combined * vec4(o.x + 1, o.y, o.z, 1);
fr_UV = vec2(0, 0);
fr_Normal = vec3(0, 0, 1);
EmitVertex();
gl_Position = un_Combined * vec4(o.x + 1, o.y, o.z + 1, 1);
fr_UV = vec2(0, 0);
fr_Normal = vec3(0, 0, 1);
EmitVertex();
gl_Position = un_Combined * vec4(o.x, o.y, o.z, 1);
fr_UV = vec2(0, 0);
fr_Normal = vec3(0, 0, 1);
EmitVertex();
gl_Position = un_Combined * vec4(o.x, o.y, o.z + 1, 1);
fr_UV = vec2(0, 0);
fr_Normal = vec3(0, -1, 0);
EmitVertex();
}
else
{
gl_Position = un_Combined * vec4(o.x, o.y + 1, o.z + 1, 1);
fr_UV = vec2(0, 0);
fr_Normal = vec3(0, 0, 1);
EmitVertex();
gl_Position = un_Combined * vec4(o.x + 1, o.y + 1, o.z + 1, 1);
fr_UV = vec2(0, 0);
fr_Normal = vec3(0, 0, 1);
EmitVertex();
gl_Position = un_Combined * vec4(o.x, o.y + 1, o.z, 1);
fr_UV = vec2(0, 0);
fr_Normal = vec3(0, 0, 1);
EmitVertex();
gl_Position = un_Combined * vec4(o.x + 1, o.y + 1, o.z, 1);
fr_UV = vec2(0, 0);
fr_Normal = vec3(0, 1, 0);
EmitVertex();
}
EndPrimitive();
}
答案 0 :(得分:2)
您可以测试自己,但通常情况下,几何着色器会减慢速度而不是加快速度。据我所知,AMD GPU有一个几何着色器的特殊情况,它总是输出4个顶点(在这种情况下是真的),英特尔GPU可以有相对于其他GPU的快速几何着色器,但一般来说,没有固定的输出大小优化,不同的几何着色器必须同步。因此,您可能会在某些或多个或大多数实现中遇到快速案例,但您必须进行测试。
考虑到顶点数据无论如何都可能不是很大:例如,每个顶点8个字节,或每个面32个字节。您甚至可以为所有块重用相同的索引缓冲区(例如0,1,2,3,0xffff,4,5,6,7,7xffff,...)。这将问题转化为非常传统的时间 - 空间权衡。您可以在几何着色器中花费更多时间,也可以花更多空间存储完整的顶点数据。您的程序是否已进入内存限制?或者您是否遇到计算限制?测试
请注意,几何着色器可以无分支编写。您可以使用数组来存储每个方向上面部输出的基础向量,而不是使用if / else。