Tecgraf/PUC-Rio
Geometry & Tesselation Shaders
Principais novidades com série NV8000
q
Novo estágio de programação
ð
Geometry shader
q
Suporte a inteiros
ð
Textura, operações, endereçamento
q
Modelo unificado de shaders
ð
Mesma funcionalidades nos diferentes shaders
q
Possível uso do pipeline para gerar geometria
ð
Sem a fase de rasterização
q
Arrays de texturas
ð
Renderização em camadas
Geometry shader
q
Pipeline programável antigo (D3D9)
Geometry shader
q
Pipeline programável novo (D3D10)
Geometry shader
q
Depois do VS, antes da rasterização
GS
Vertex T&L, vertex shader Clipping, color clamping, perspective divisionGeometry shader
q
Fluxo de dados
GS
Point, Line, Triangle Point, Line strip, Triangle stripPode gerar primitivas
API para novas primitivas
q
Primitivas com informação de adjacências
ð
Lines
²GL_LINES_ADJACENCY_EXT
ð
Line strip
²GL_LINE_STRIP_ADJACENC Y_EXT
ð
Triangle
²GL_TRIANGLES_ADJACENC Y_EXT
ð
Triangle strip
²GL_TRIANGLE_STRIPACENC Y_ADJ_EXT
1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 2 5 1 3 4 6 2 5 1 3 7 4 9 11 8 6 10 12Geometry shader
q
GS opera sobre uma primitiva por vez
ð
Gera como saída uma ou mais primitivas
²
Todas do mesmo tipo
ð
Primitiva original (de entrada) é descartada
q
Exige a presença de um vertex shader
Geometry shader
q
Input
ð
Tipo de primitiva de entrada: 1 a 6 vértices
²
Dependendo do tipo de primitiva de entrada
– Ponto: 1 - proveniente de pontos
– Linha: 2 - proveniente de linhas ou faixas de linhas
– Triângulo: 3 - proveniente de triângulos, faixas, leques
– Linha com adjacência: 4 - proveniente de linhas e faixa c/ adj
– Triângulo com adjacência: 6 - prov. de triângulos e faixa c/ adj
ð
GS deve ser compatível com tipo de primitiva
²
Tipo de primitiva é parâmetro de um GS
Geometry shader
q
Output
ð
Uma ou mais primitivas de um mesmo tipo
²
Points
²Line strip
²
Triangle strip
ð
GS deve ser compatível com tipo de primitiva
²
Tipo de primitiva de saída é parâmetro de um GS
GS variables
q
Uniforms
ð
Variáveis globais
²
Incluindo samplers para acesso de textura
q
Input variables
ð
Saída de um VS
²
Vertex attributes (built-in)
²
User-defined vertex attributes
ð
ID da primitiva (built-in)
²
Gerada automaticamente
²
ID inicializado com zero no “glBegin”
q
Output varying variables
ð
Saída de um GS
²
Vertex attributes (built-in)
GS
input variables
q
Atributos built-in de vértices
q
Atributos extras
ð Se no VS temos: ð No GS, teremos: qAtributos globais
ð in int gl_PrimitiveIDIn; ð in int gl_InvocationID; ptg The input primitive type is specified in the body of the geometry shader using a layoutqualifier. The general form of the input layout qualifier is
layout (primitive_type) in;
This specifies that primitive_type is the input primitive type that the geometry shader is expected to handle, and primitive_type must be one of the supported primitive modes:
points, lines, triangles, lines_adjacency, or triangles_adjacency. The geometry shader runs once per primitive. This means that it’ll run once per point for GL_POINTS; once per line for GL_LINES, GL_LINE_STRIP, and GL_LINE_LOOP; and once per triangle for GL_TRIANGLES, GL_TRIANGLE_STRIP, and GL_TRIANGLE_FAN. The inputs to the geometry
shader are presented in arrays containing all of the vertices making up the input primitive. The predefined inputs are stored in a built-in array called gl_in[], which is an array of structures and defined as shown in Listing 11.5.
LISTING 11.5 The Definition of gl_in[] in gl_PerVertex { vec4 gl_Position; float gl_PointSize; float gl_ClipDistance[]; } gl_in[];
The members of this structure are the built-in variables that are written in the vertex shader: gl_Position, gl_PointSize, and gl_ClipDistance[]. You should be very familiar with gl_Position and gl_PointSize by now, and gl_ClipDistance is explained in
Chapter 12. These variables appear as global variables in the vertex shader, but their values end up in the structure members when they appear in the geometry shader. Other vari-ables written by the vertex shader also become arrays in the geometry shader. In the case of individual varyings, outputs in the vertex shader are declared as normal, and the inputs to the geometry shader have a similar declaration, except that they are arrays. Consider a vertex shader that defines outputs as
out vec4 color; out vec3 normal;
The corresponding input to the geometry shader would be
in vec4 color[]; in vec3 normal[];
Notice that both the color and normal varyings have become arrays in the geometry
shader. If you have a large amount of data to pass from the vertex to the geometry shader,
Geometry Shaders 423
11
Download from www.wowebook.com
ptg The input primitive type is specified in the body of the geometry shader using a layout
qualifier. The general form of the input layout qualifier is layout (primitive_type) in;
This specifies that primitive_type is the input primitive type that the geometry shader is expected to handle, and primitive_type must be one of the supported primitive modes: points, lines, triangles, lines_adjacency, or triangles_adjacency. The geometry shader runs once per primitive. This means that it’ll run once per point for GL_POINTS; once per line for GL_LINES, GL_LINE_STRIP, and GL_LINE_LOOP; and once per triangle for GL_TRIANGLES, GL_TRIANGLE_STRIP, and GL_TRIANGLE_FAN. The inputs to the geometry
shader are presented in arrays containing all of the vertices making up the input primitive. The predefined inputs are stored in a built-in array called gl_in[], which is an array of structures and defined as shown in Listing 11.5.
LISTING 11.5 The Definition of gl_in[] in gl_PerVertex { vec4 gl_Position; float gl_PointSize; float gl_ClipDistance[]; } gl_in[];
The members of this structure are the built-in variables that are written in the vertex
shader: gl_Position, gl_PointSize, and gl_ClipDistance[]. You should be very familiar with gl_Position and gl_PointSize by now, and gl_ClipDistance is explained in
Chapter 12. These variables appear as global variables in the vertex shader, but their values end up in the structure members when they appear in the geometry shader. Other vari-ables written by the vertex shader also become arrays in the geometry shader. In the case of individual varyings, outputs in the vertex shader are declared as normal, and the inputs to the geometry shader have a similar declaration, except that they are arrays. Consider a vertex shader that defines outputs as
out vec4 color; out vec3 normal;
The corresponding input to the geometry shader would be in vec4 color[];
in vec3 normal[];
Notice that both the color and normal varyings have become arrays in the geometry
shader. If you have a large amount of data to pass from the vertex to the geometry shader,
Geometry Shaders 423
11
Download from www.wowebook.com
ptg The input primitive type is specified in the body of the geometry shader using a layout
qualifier. The general form of the input layout qualifier is
layout (primitive_type) in;
This specifies that primitive_type is the input primitive type that the geometry shader is
expected to handle, and primitive_type must be one of the supported primitive modes: points, lines, triangles, lines_adjacency, or triangles_adjacency. The geometry shader runs once per primitive. This means that it’ll run once per point for GL_POINTS;
once per line for GL_LINES, GL_LINE_STRIP, and GL_LINE_LOOP; and once per triangle for GL_TRIANGLES, GL_TRIANGLE_STRIP, and GL_TRIANGLE_FAN. The inputs to the geometry
shader are presented in arrays containing all of the vertices making up the input primitive. The predefined inputs are stored in a built-in array called gl_in[], which is an array of structures and defined as shown in Listing 11.5.
LISTING 11.5 The Definition of gl_in[] in gl_PerVertex { vec4 gl_Position; float gl_PointSize; float gl_ClipDistance[]; } gl_in[];
The members of this structure are the built-in variables that are written in the vertex
shader: gl_Position, gl_PointSize, and gl_ClipDistance[]. You should be very familiar
with gl_Position and gl_PointSize by now, and gl_ClipDistance is explained in
Chapter 12. These variables appear as global variables in the vertex shader, but their values end up in the structure members when they appear in the geometry shader. Other vari-ables written by the vertex shader also become arrays in the geometry shader. In the case of individual varyings, outputs in the vertex shader are declared as normal, and the inputs to the geometry shader have a similar declaration, except that they are arrays. Consider a vertex shader that defines outputs as
out vec4 color; out vec3 normal;
The corresponding input to the geometry shader would be
in vec4 color[]; in vec3 normal[];
Notice that both the color and normal varyings have become arrays in the geometry
shader. If you have a large amount of data to pass from the vertex to the geometry shader,
Geometry Shaders 423
11
Emissão de vértices no GS
q
Output variables (como no VS)
ð
gl_Position, gl_PointSize, gl_ClipDistance[], etc.
²
OBS: VS pode não escrever o valor de gl_Position
q
Emissão de vértices
ð
GS pode emitir um número variável de vértices por primitivas
²
Implementação pode limitar o máximo
²
Máximo de cada GS deve ser especificado para alocação de espaço
ð
Função built-in:
EmitVertex
( )
²
Valores das output variables são emitidos
Emissão de primitivas no GS
q
Variáveis built-in de saída
ð
out int gl_PrimitiveID
ð
out int gl_Layer
²
For multilayer rendering
q
Definição de primitivas
ð
GS pode definir um número variável de primitivas
²
Implementação pode limitar o máximo
ð
Função built-in:
EndPrimitive
( )
²
Finaliza uma primitiva: outra de mesmo tipo pode ser gerada
²O EndPrimitive da última primitiva é opcional
GS: exemplo pass-thourgh
ptg
The other difference between geometry shaders and vertex and fragment shaders is that
geometry shaders are an optional part of the OpenGL pipeline. It is perfectly legal to have
only a vertex and fragment shader linked into a program object, and this is, until now, the
only way you’ve used OpenGL. When no geometry shader is present, the OpenGL
pipeline operates as normal; the outputs from the vertex shader are interpolated across the
primitive being rendered and are fed directly to the fragment shader. When a geometry
shader is present, however, the outputs of the vertex shader become the inputs to the
geometry shader, and the outputs of the geometry shader are what are interpolated and
fed to the fragment shader. The geometry shader can further process the output of the
vertex shader, and if it is generating new primitives (this is called amplification) can apply
different transformations to each primitive as it creates them.
The Pass-Through Geometry Shader
Geometry shaders are written in GLSL, just like vertex and fragment shaders, and there’s
nothing magical about them. This will all be explained shortly, but Listing 11.2 shows a
simple geometry shader in its entirety.
LISTING 11.2 Source Code for a Simple Geometry Shader
#version 330
precision highp float; layout (triangles) in;
layout (triangle_strip) out; layout (max_vertices = 3) out; void main(void)
{
int i;
for (i = 0; i < gl_in.length(); i++) { gl_Position = gl_in[i].gl_Position; EmitVertex();
}
EndPrimitive(); }
This is a very simple pass-through geometry shader, which sends its input to its output
without modifying it. It looks similar to a vertex shader, but there are a few extra
differ-ences to cover. Going over the shader a few lines at a time makes everything clear. The
first few lines simply set up the version number (330) and the precision of the shader just
CHAPTER 11 Advanced Shader Usage
420
GS: exemplos de uso
q
Dado vértice e normal
ð
Gerar linha como glyph
Layered rendering
q
Layered framebuffer object
ð
cube map textures
²
Cada face representa uma camada
ð
three-dimensional textures
²
Cada fatia representa uma camada
ð
one- dimensional texture array
²
Cada textura representa uma camada
ð
two-dimensional texture array
²
Cada textura representa uma camada
q
Primitivas enviadas para diferentes camadas
ð
Definida em tempo de execução
Transform feedback
q
Novo modo de render do OpenGL
ð
Permite usar o pipeline para gerar primitivas
²
Armazenadas em buffer objects
– Arrays de atributos de vértices
ð
Primitivas armazenadas antes do clipping
²
Se exisitir GS, logo após ele
ð
Resultado usado posteriormente
²
Ou como dados de vértices
²Ou como array para FS
ð
Aplicações
²
Acelera algoritmo de múltiplas passadas
– Onde se tem criação de geometria
²
GPGPU
Novidades com OpenGL 4.0 (DX11)
q
Novos estágios: tessellation
ð
Processa nova primitiva
patch
Aplicação Vertex Shader Tess Control Shader Tess Evaluation Shader Geometry Shader Setup/Rasterizer Tess GeneratorTessellation Control Shader
q
Opcional
q
In/Out
ð
In: a patch
ð
Out: a patch
²
Array of vertices (and attribs)
²Per-patch attribs
q
Shader executado para cada vértice de saída
ð
Produz atributos do vértice correspondente
ð
Pode ler atributos gerados para outros vértices
ð
Pode ler e escrever atributos de patch
Tessellation Primitive Generator
q
Funcionalidade fixa, não programável
q
Subdivide primitiva
ð
De acordo com o nível pedido: tess level
ð
In/Out
²
In: triangles; Out: triangles
²In: quads; Out: quads or lines
q
A cada vértice gerado é atribuito
coordenadas paramétricas
²
Triangle: (u, v, w)
²Quad: (u, v)
Tessellation Evaluation Shader
q
Obrigatório para primitivas patch
q
Executado para cada vértice gerado
q
Propósito principal
ð
Gerar posição e atributos dos vértices
q
Pode ler atributos dos vértices do patch
q
Pode ler atributos associados ao patch
q
Requer vertex shader
Tessellation Control Shader
q
Variáveis de entrada
ð
gl_in[ ] à vetor de estrutura com os campos:
²
gl_Position, gl_FrontColor, gl_TexCoord[ ], etc.
ð
Variáveis built-in
²
gl_InvocationID, gl_PatchVerticesIn, gl_PrimitiveID
– gl_InvocationID indicates the vertex under consideration
q
Variáveis de saída
ð
Atributos de vértices
²
gl_out[ ]
– gl_Position, etc.
ð
Atributos de patch: GLSL qualifier à patch
²
Built-in
Tessellation Primitive Generator
q
Define-se tipo de subdivisão
Tessellation mode: triangles
1st inner level perpendicular lines inner subdivision
Tessellation mode: quads
1st, 2nd inner levels perpendicular lines inner subdivision
Tessellation mode: isolines
Tessellation Evaluation Shader
q
Variáveis de entrada
ð
Atributos dos vértices do patch: gl_in[ ]
ð
Variáveis built-in
²gl_PatchVerticesIn, gl_PrimitiveID
²gl_TessCoord
²gl_TessLevelOuter[ ], gl_TessLevelInner[ ]
q
Variáveis de saída
ð
gl_Position, etc.
Aplicações
Ref: http://castano.ludicon.com/blog/2009/01/10/10-fun-things-to-do-with-tessellation/
PN triangles Silhouette refinement