当前位置: 首页 > 知识库问答 >
问题:

使用几何体着色器优化体素渲染

哈翔
2023-03-14

我用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(); 
    }

共有1个答案

司寇星海
2023-03-14

您可以测试自己,但通常情况下,几何体着色器会减慢速度,而不是加快速度。据我所知,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写文档一样