Implementação do algoritmo Marching Cubes usando shaders
Luiz Fernando Oliveira Corte Real [email protected]
Marching Cubes
Textura 3D Isosuperfície
3 9 8 7
6 8 5 4
9 9 7 6
10 6 4 2
Marching Cubes
Textura 3D Isosuperfície
3 9 8 7
6 8 5 4
9 9 7 6
10 6 4 2
Marching Cubes
Isosuperfície:
6
Marching Cubes
Isosuperfície:
6
(marcação apenas ilustrativa e errada)
Marching Cubes
Isosuperfície:
6
(marcação apenas ilustrativa e errada)
Marching Cubes
http://upload.wikimedia.org/wikipedia/commons/thumb/a/a7/MarchingCubes.svg/1000px-MarchingCubes.svg.png
OpenGL Pipeline
Pipeline fixo
OpenGL Pipeline
Pipeline fixo
● Padrão até OpenGL 2.1
● Removido no 3.1
OpenGL Pipeline
Pipeline programável
OpenGL Pipeline
Vertex Shader:
transformações vértice a vértice
● Posição
● Normal
● Cor
OpenGL Pipeline
Geometry Shader:
transformações em primitivas
● Uma entrada
● Várias saídas
OpenGL Pipeline
Fragment Shader:
transformações
fragmento a fragmento
● Iluminação
● Texturização
OpenGL Pipeline
Paralelismo: de graça!
● Vértices
processados em paralelo
● OpenGL cuida dos problemas de
concorrência
OpenGL Pipeline
Ideia:
patches do algoritmo produzidos no
Geometry Shader
Implementação
Paralelismo no processamento dos vértices
Implementação
Paralelismo no processamento dos vértices Cubos do algoritmo independentes
Implementação
Paralelismo no processamento dos vértices Cubos do algoritmo independentes
Um vértice para cada cubo!
Implementação
1º passo: um vértice para cada cubo
Implementação
0 1
0 0 1
1
Resolução:
H x W x D
Implementação
0 1
0 0 1
1
dx dz
dy
Resolução:
H x W x D dx = 1 / W dy = 1 / H dz = 1 / D
Implementação
Vértices: (-1, -1, -1) -> (1, 1, 1)
Implementação
Vértices: (-1, -0.95, -0.8) -> (1, 0.95, 0.8)
(supondo W > H > D)
Implementação
Vértices: (-1, -0.95, -0.8) -> (1, 0.95, 0.8)
Voxel: (x, y, z)
Vértice: (-1, -0.95, -0.8) + 2 (dx.x, dy.y, dz.z)
Implementação
Vértices: (-1, -0.95, -0.8) -> (1, 0.95, 0.8)
glBegin(GL_POINTS);
for (double x = -maxX; x <= maxX; x += 2 * dx) {
for (double y = -maxY; y <= maxY; y += 2 * dy) { for (double z = -maxZ; z <= maxZ; z += 2 * dz) {
glVertex3f(x, y, z);
} }
}
glEnd(GL_POINTS);
Implementação
Vértices: (-1, -0.95, -0.8) -> (1, 0.95, 0.8)
glBegin(GL_POINTS);
for (double x = -maxX; x <= maxX; x += 2 * dx) {
for (double y = -maxY; y <= maxY; y += 2 * dy) { for (double z = -maxZ; z <= maxZ; z += 2 * dz) {
glVertex3f(x, y, z);
} }
}
glEnd(GL_POINTS);
Implementação
1º passo: um vértice para cada cubo 2º passo: tabela de patches no shader
Implementação
Tabela:
● 1 linha = 1 possível configuração do cubo
Implementação
Tabela:
● 1 linha = 1 possível configuração do cubo
○ 8 vértices = 28 possibilidades = 256 linhas
Implementação
Tabela:
● 1 linha = 1 possível configuração do cubo
○ 8 vértices = 28 possibilidades = 256 linhas
● Colunas = arestas do cubo c/ ponto do patch
○ Maior patch: 16 vértices => 16 colunas
Implementação
Tabela:
● 1 linha = 1 possível configuração do cubo
○ 8 vértices = 28 possibilidades = 256 linhas
● Colunas = arestas do cubo c/ ponto do patch
○ Maior patch: 16 vértices => 16 colunas
256 x 16 = 4096 inteiros
Implementação
1 linha:
● índices das arestas do cubo com vértices
● -1 = fim
3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1
Implementação
int RawTriangleTable[] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, ...
...
...
...
2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1,
1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
Implementação
Muitos dados para
passar para shader Textura
Implementação
glGenTextures(1, &triangleTableTexture);
glActiveTexture(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, triangleTableTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA16I_EXT, 16, 256, 0, GL_ALPHA_INTEGER_EXT, GL_INT, &RawTriangleTable);
Implementação
glGenTextures(1, &triangleTableTexture);
glActiveTexture(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, triangleTableTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA16I_EXT, 16, 256, 0, GL_ALPHA_INTEGER_EXT, GL_INT, &RawTriangleTable);
Sem
interpolação!
Implementação
1. Calcular valor da textura nos vértices do cubo
2. Marcar quais são maiores e menores que o valor da superfície
3. Obter linha da tabela correspondente
4. Calcular posição dos vértices nas arestas 5. Gerar triângulos
Implementação
Vertex Shader: apenas passa os vértices (pontos) para o Geometry Shader
Fragment Shader: colore e ilumina os
triângulos rasterizados do Geometry Shader
Implementação
Vertex Shader: apenas passa os vértices (pontos) para o Geometry Shader
Fragment Shader: colore e ilumina os
triângulos rasterizados do Geometry Shader
Usa a textura para calcular as normais
Demonstração
Otimização
Toda a superfície é regerada a cada alteração na cena
OpenGL Pipeline
OpenGL Pipeline
Transform feedback
OpenGL Pipeline
Transform feedback
● Extensão OpenGL até versão 2.1
● Core a partir da 3.0
Otimização
Otimização
Demonstração
Links
● Implementação original: http://www.icare3d.
org/blog_techno/gpu/opengl_geometry_shader_marching_cubes.html
● Transform feedback: http://www.opengl.
org/registry/specs/EXT/transform_feedback.txt
● Implementação no MedSquare: https://medsquare.svn.sourceforge.
net/svnroot/medsquare/branches/marching-
cubes/Rendering/vtkmsqOpenGLShadersImageMarchingCubesMapper.
cxx