我用C SDL2 GLEW Opengl 4.1编程一个小的体素游戏,有点像Minecraft。
我正在尽可能优化体素渲染。
我把世界滑成一块块,而这块块又滑成一块块。
每个块包含16x16x16个块。
现在,如果编辑块(删除/放置块),我将重建完整块和相邻块,并将其与vao和vbo一起上载到图形卡。
现在,为了最小化顶点数据,我必须从cpu传输到gpu,我使用几何体着色器。
首先,这是个好主意吗?
我的意思是几何体着色器必须为每个体素面计算每个帧的基本体。
但是,我对顶点着色器进行了编程,因此我只需要为每个块面传递一个顶点。
为了做到这一点,我使用了vec4。
前3个元素(x,y,z)用于块位置和4。元素(w)I用于指示面显示的方向。
0表示向后,1表示向前,2表示向左,3表示向右,4表示底部,5表示顶部。
请暂时忽略紫外线和正常光。
此外,我上传GLbyte的,而不是GL浮动的。
这是个好主意吗?
有什么更好/更快的方法?
#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();
}
您可以测试自己,但通常情况下,几何体着色器会减慢速度,而不是加快速度。据我所知,AMD GPU对于几何着色器有一个特殊的情况,它总是精确地输出4个顶点(在本例中为真),Intel GPU可以具有相对于其他GPU的快速几何着色器,但一般来说,如果没有固定的输出大小优化,则必须同步不同的几何着色器。因此,您可能会遇到一些、许多或大多数实现的快速情况,但您必须进行测试。
考虑顶点数据可能不是很大的:例如,每个顶点8个字节,或者每个面32个字节。您甚至可以对所有块(例如0、1、2、3、0xffff、4、5、6、7、0xffff等)重用相同的索引缓冲区。这将问题转化为非常传统的时间与空间权衡。您可以在几何体着色器中花费更多的时间,也可以花费更多的空间来存储完整的顶点数据。你的程序是否内存不足?还是说你的计算量已经达到极限了?测验
请注意,您的几何着色器可以被写入无分支。您可以使用一个数组来存储每个方向上的人脸输出的基向量,而不是使用if/ther。
在我的第一个opengl“体素”项目中,我使用几何着色器从gl_points创建立方体,它工作得很好,但我相信它可以做得更好。在alpha颜色中,我传递关于应该渲染哪些面的信息(跳过与其他立方体相邻的面),然后使用“引用”立方体定义创建可见面的顶点。每个点乘以3个矩阵。直觉告诉我,也许整张脸可以乘以它们,而不是每一点,但是我的数学技能很差,所以请建议。 ------- 更新的代码:------
我正在尝试制作一个几何体着色器(使用着色器生成器)来简化模型。首先,我试图做一个体素化,但结果不好,我找不到它的错。 在下面的代码中,想法是找到输入三角形的中心,然后使其成为我要创建的框的中心。 我知道这不是世界上最优雅的代码,但先走一步,我需要让它工作...
使用GLE管材和挤出库(http://www.linas.org/gle/)我能够使用OpenGL将2D计数挤出到3D对象中。该库在CPU上完成所有工作,并使用OpenGL即时模式。 我想在GPU上使用几何着色器进行挤压可能会更快,尤其是在渲染大量几何图形时。因为我还没有在OpenGL中使用几何着色器的任何经验,我想知道这是否可能,以及我必须注意什么。您认为将这些计算转移到GPU并提高性能是个好主
在顶点和片段着色器之间有一个可选的几何着色器(Geometry Shader),几何着色器的输入是一个图元(如点或三角形)的一组顶点。几何着色器可以在顶点发送到下一着色器阶段之前对它们随意变换。然而,几何着色器最有趣的地方在于,它能够将(这一组)顶点变换为完全不同的图元,并且还能生成比原来更多的顶点。 废话不多说,我们直接先看一个几何着色器的例子: #version 330 core layout
这是代码中唯一可能有错误的部分: 你能在这段代码中看到什么错误吗?启用glEnable(GL_TEXTURE_2D)并没有什么不同。纹理坐标是正确的,片段和顶点着色器肯定是正确的。 解决了这不是问题,我仍在使用glGenerateMipmap(…)在glTexImage2D(…)之前。真正的问题是,当我的图像是GL_RGB格式时,我通过了格式GL_RGBA。另外我的t-
“渲染”(Rendering)是即使非计算机专业的都不会觉得陌生的词,虽然在很多人说这个词的时候,并不清楚“渲染”究竟意味着什么。相反,“着色器”(Shader)很可能是大家比较陌生的词,从名字看上去似乎是用来上色的,但它具体能做什么呢? 在解释着色器之前,我们先来聊聊渲染。 渲染 用通俗的话来说,渲染就是将模型数据在屏幕上显示出来的过程。 这听起来好像很简单呢!但正如你打开一个Word写文档一样