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

时间:2015-07-08 22:42:18

标签: opengl voxel geometry-shader

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

1 个答案:

答案 0 :(得分:2)

您可以测试自己,但通常情况下,几何着色器会减慢速度而不是加快速度。据我所知,AMD GPU有一个几何着色器的特殊情况,它总是输出4个顶点(在这种情况下是真的),英特尔GPU可以有相对于其他GPU的快速几何着色器,但一般来说,没有固定的输出大小优化,不同的几何着色器必须同步。因此,您可能会在某些或多个或大多数实现中遇到快速案例,但您必须进行测试。

考虑到顶点数据无论如何都可能不是很大:例如,每个顶点8个字节,或每个面32个字节。您甚至可以为所有块重用相同的索引缓冲区(例如0,1,2,3,0xffff,4,5,6,7,7xffff,...)。这将问题转化为非常传统的时间 - 空间权衡。您可以在几何着色器中花费更多时间,也可以花更多空间存储完整的顶点数据。您的程序是否已进入内存限制?或者您是否遇到计算限制?测试

请注意,几何着色器可以无分支编写。您可以使用数组来存储每个方向上面部输出的基础向量,而不是使用if / else。