2015-07-08 3 views
0

I программирование с C++ + SDL2 + GLEW + Opengl 4.1 небольшая игра воксела, немного напоминающая Minecraft.Оптимизация рендеринга Voxel с геометрическим шейдером

Я пытаюсь оптимизировать рендеринг вокселей, где могу.

Я помещаю мир в куски, и это куски в блоки.

Каждый блок содержит блоки 16x16x16.

Теперь, если отредактируйте фрагмент (удалите/поместите блок) Я перестрою полный кусок и соседний кусок и загружаю его с помощью vao и vbo на графическую карту.

Теперь, чтобы свести к минимуму данные вершин, я должен перейти от процессора к gpu. Я использую геометрические шейдеры.

Прежде всего, это хорошая идея?

Я имею в виду, что каждый кадр геометрического шейдера должен вычислять примитив для каждой поверхности вокселя.

Однако я запрограммировал вершинный шейдер так, что мне нужно передать только одну вершину для каждой грани блока.

Чтобы сделать это, я использовал vec4.

Первые 3 элемента (x, y, z), которые я использовал для положения блока, и 4. Элемент (w) Я использовал для указания, в каком направлении отображается лицо.

0 означает назад, 1 означает фронт, 2 означает левый, 3 означает право, 4 означает дно, 5 означает верх.

Просьба игнорировать УФ и нормальные на данный момент.

Далее я загружаю 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

Слишком плохо, что вы не используете 4.3, тогда вы можете запускать вычислительные шейдеры для генерации кусков. –

+0

Спасибо, я не знал, что «вычислительный шейдер», похоже, является еще одним хорошим подходом. –

ответ

2

Вы можете проверить себя, но в целом геометрический шейдер замедлит работу, а не ускорит работу. Насколько я понимаю, графические процессоры AMD имеют особый случай для геометрических шейдеров, которые всегда выводят ровно 4 вершины (правда в этом случае), а графические процессоры Intel могут иметь быстрые геометрические шейдеры относительно других графических процессоров, но в целом без оптимизации фиксированного размера выхода , различные геометрические шейдеры должны быть синхронизированы. Таким образом, вы можете столкнуться с быстрыми случаями здесь для некоторых или многих или большинства реализаций, но вам придется протестировать.

Учитывайте, что данные вершин могут быть не очень большими: скажем, 8 байт на вершину или 32 байта на лицо. Вы даже можете повторно использовать один и тот же индексный буфер для всех фрагментов (например, 0, 1, 2, 3, 0xffff, 4, 5, 6, 7, 0xffff, ...). Это превращает проблему в очень традиционный компромисс между временем и временем. Вы можете потратить больше времени в геометрическом шейдере или потратить больше места на хранение полных данных вершин. Ваша программа работает в области памяти? Или вы сталкиваетесь с ограничениями вычислений? Контрольная работа.

Обратите внимание, что ваш геометрический шейдер может быть записан без разветвления. Вместо использования if/else вы можете просто использовать массив для хранения базисных векторов для вывода граней в каждом направлении.

 Смежные вопросы

  • Нет связанных вопросов^_^