Você está na página 1de 25

O Pipeline do OpenGL

Função do Pipeline
● Gerar imagens bidimensionais dado um
conjunto de primitivas e uma câmera virtual

Descrição
das Pipeline Framebuffer
primitivas 3D
Abrindo o Pipeline
Abrindo o Pipeline – Outra visão
Shader Vertex e Fragment
● Partes programáveis do pipeline
– No modo antigo de usar o OpenGL, essa parte
era configurável
● Antes de usar, é necessário instanciar cada
shader
– Vertex → lida com o processamento de vertex,
antes de se montar as primitivas
– Fragment → lida com o processamento dos
fragmentos antes de se tornarem pixels
Processador de Vertex
Processador Vertex e Fragment
● São baseados em uma linguagem Script
chamada de GLSL
– OpenGL Shading Language
– Muito parecida com a linguagem C
– Para cada shader:
● Precisa ser instalada e compilada
– Programa final
● Precisa se ligado e montado e, posteriormente,
ativado
Trabalhando com o Shader
● Criar um objeto do tipo shader
– glCreateShader
– Para deletar → glDeleteShader
● Carregar o objeto com a fonte do programa
– glShaderSource
● Compilar o programa que está no objeto
– glCompileShader
● Verificar se tudo deu certo até aqui
– glGetShaderiv -> com a diretiva
GL_COMPILE_STATUS
Trabalhando com o Programa
● Criar um objeto do tipo programa
– glCreateProgram
– Para deletar, posteriormente, glDeleteProgram
● Montar um programa
– Necessário 2 shaders, pelo menos
● Um para o vertex e outro para o fragment
● GlAttachShader
Trabalhando com o Programa (2)
● Ligar tudo no programa
– glLinkProgram
● Verificar se não houve erros
– glGetProgramiv com a diretiva
GL_LINK_STATUS
● Usar o programa
– glUseProgram
– Somente a partir de agora o pipeline está
completo e utilizável
Em Código – Shader Vertex
const GLchar **vertex; // ponteiro para onde está localizado o buffer
// com o programa do vertex

GLuint shader_vertex; // Objeto shader vertex


GLint success;
GLchar infoLog[512]; // buffer para a mensagem de erro

// Começando pelo shader do Vertex


shader_vertex = glCreateShader(GL_VERTEX_SHADER); // <-- Shader Vertex
glShaderSource(shader_vertex, 1, vertex, NULL);
glCompileShader(shader_vertex);

// Check for compile time errors


glGetShaderiv(shader_vertex, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(shader_vertex, 512, NULL, infoLog);
printf("ERROR::SHADER::VERTEX::COMPILATION_FAILED\n%s\n", infoLog);
}

// FAZER A MESMA COISA PARA O SHADER DE FRAGMENTO


Em Código – Programa
// Criando o Programa
GLint shader_program = glCreateProgram(); // Cria objeto programa

// Montando o programa (usa os objetos shaders)


glAttachShader(shader_program, shader_vertex);
glAttachShader(shader_program, shader_frag);

// Liga o programa e cria o executável


glLinkProgram(shader_program);

// Check for linking errors


glGetProgramiv(shader_program, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shader_program, 512, NULL, infoLog);
printf("ERROR::SHADER::PROGRAM::LINKING_FAILED\n%s\n", infoLog);
}

// Deletando os shaders (só efetiva na deleção do programa)


glDeleteShader(shader_vertex);
glDeleteShader(shader_frag);

// Posteriormente, deve-se usar o programa


glUseProgram(shader_program);
Versões do OpenGL
Core e Compatibility
● Até a versão 2.1 → Modo de compatibilidade
– Pode ser usado o pipeline fixo quando o
programável, mas não ambos ao mesmo
tempo
● Depois da versão 3.2 → Possibilidade de
escolha entre modo Core ou Compability
– Possível determinar qual versão de contexto do
openGL deseja-se criar
● Modo Core → somente funções “modernas”
Versões do OpenGL e do GLSL
Programa Fragment
const GLchar *frag21 =
" #version 120 \n"
" \n"
" void main() \n"
" { \n"
" gl_FragColor = vec4(1.0f, 1.0f, 1.0f, 1.0f); \n"
" } \n";

● gl_FragColor → cor do pixel após o


processamento do programa
Programa Vertex
const GLchar *vertex21 =
" #version 120 \n"
" attribute vec3 position; \n"
" uniform mat4 transform; \n"
" \n"
" void main() \n"
" { \n"
" gl_Position = transform * vec4(position, 1.f); \n"
" } \n";

● gl_Position → resultado do processamento


● attribute → qualifica a variável que recebe um
fluxo de dados do buffer de memória
● uniform → valor constante para o
processamento de uma primitiva
Sobre o Qualificador Attribute
● Conecta o buffer de dados (VRAM) com o
nome atribuido no programa vertex
– glVertexAttribPointer(index, size, type,
normalized, stride, *pointer)
● index permite essa conexão
– Para obter o valor correto de index:
● glGetAttribLocation(program, name)
● Usualmente começa no Zero
Do Programa Vertex Anterior
static void renderScene(GLuint vbo, double delta)
{
(...)
// Tecnicamente, no OGL 2.1, é necessário obter o índice do atributo
// position. Não fazer isso é considerado que o programa apresenta
// comportamento não definido. Maioria dos drivers colocam no índice 0.
// Vamos assumir que é isso, por simplificação apenas.
// No OGL3.3, o parâmetro layout diz que tá no índice 0.

pos = glGetAttribLocation(program, “position”);


glEnableVertexAttribArray(index);
glVertexAttribPointer(index, 3, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_POINTS, 0, 1);

glDisableVertexAttribArray(index);

(...)
return;
}
Sobre o Qualificador Uniform
● O valor desta variável só pode ser alterado
após um conjunto de primitivas terem sido
processados
– Pode ser assumido como um valor constante
para as primitivas
– Só pode ter o valor alterado após o termino do
processamento das chamadas do tipo
glDraw*
Sobre o Qualificador Uniform (2)
● Normalmente usado para passar valores
imutáveis em uma primitiva
– Exemplo: matrix de transformações
● Conexão entre o programa (CPU) e a variável
uniforme (shader) :
– glGetUniformLocation(program, name)
– Retorna uma referência para a localização do
uniform dentro do shader
Sobre o Qualificador Uniform (3)
● Para passar um valor:
– Família glUniform*
Exemplo
Transform = glGetUniformLocation(program, “transform”);
glUniformMatrix4fv(transform, 1, GL_FALSE, &trans[0][0]);

glClear(GL_COLOR_BUFFER_BIT);

glBindBuffer(GL_ARRAY_BUFFER, vbo);

glEnableVertexAttribArray(pos);
glVertexAttribPointer(pos, 3, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_POINTS, 0, 1);

glDisableVertexAttribArray(pos);
glBindBuffer(GL_ARRAY_BUFFER, 0);
Nota sobre o arquivo math3d.h
● Ordem da multiplicação das matrizes
– Segue a notação vetor coluna
– Pós multiplicação
● A = A.X
● Assim, uma transformação: primeiro uma escala
(S), depois rotação (R) e por fim translação (T)
– Tmp = Tmp.I (I → identidade)
– Tmp = S.Tmp
– Tmp = R.Tmp
– Tmp = T.Tmp
Sobre a passagem do tempo
● Glfw permite obter o tempo transcorrido desde
o inicio do programa
– glfwGetTime()
– Permite calcular intervalos de tempo
● Auxilia na montagens de animações mais suaves
● Exemplo:
– Δx = v . Δt
– x += delta*2/4.f

Você também pode gostar