Primitivas do OpenGL Tomás Antônio C. Badan 1
Primitivas Formas simples que combinadas, geram objetos mais complexos Blocos de construção de objetos Podem ser 1D, 2D ou 3D Vão desde pontos, linhas até polígonos 2
Volume de Visualização Estabelecido no espaço de modelagem Definido, por exemplo, pela função: glortho(-100, 100, -100, 100, -100, 100); 3
Pixel e Vertex Pixel Menor elemento do monitor de computador Vertex Definido em um plano 2D Um ponto no espaço de modelagem Definido em um espaço 3D Pode ser definido em um espaço 2D Basta considerar Z = 0 No OpenGL glvertex 4
Definindo pontos no Espaço 3D É estabelecido por uma série de pontos (função glvertex), encapsulado pelo bloco glbegin(gl_points)/glend() 5
Vertex* - GL_POINTS GLint p[5][2] = {{0,50}, {-47,15}, {-29,-40}, {29,-40}, {47,15}}; glbegin(gl_points); glvertex2iv(p[0]); glvertex2iv(p[2]); glvertex2iv(p[4]); glvertex2iv(p[1]); glvertex2iv(p[3]); glend(); 6
Propriedades de Pontos Tamanho do ponto (padrão) 1 pixel Alterando o tamanho: void glpointsize(glfloat size); Existem valores máximos e mínimos Obtendo a faixa permissível: GLfloat sizes[2], step; glgetfloatv(gl_point_size_range, sizes); glgetfloatv(gl_point_size_granularity, &step); 7
Propriedades de Pontos (2) Pontos são desenhados no formato quadricular Valores de tamanhos não necessitam ser inteiros São aproximações do diâmetro de um círculo contendo todos os pixels que são usados para desenhar o ponto 8
Definindo Retas no Espaço 3D Uma reta é definida por 2 pontos Ponto é definido pela função glvertex Em OpenGL Encapsular os pontos pelo bloco glbegin(gl_lines)/glend() Cada 2 pontos define uma reta Ponto solteiro é descartado 9
Vertex* - GL_LINES GLint p[5][2] = {{0,50}, {-47,15}, {-29,-40}, {29,-40}, {47,15}}; glbegin(gl_lines); glvertex2iv(p[0]); glvertex2iv(p[2]); glvertex2iv(p[4]); glvertex2iv(p[1]); glvertex2iv(p[3]); glend(); 10
Definindo Segmentos de Retas Reta definida por 2 pontos Último ponto de um segmento de reta pode ser considerado como primeiro ponto para o próximo segmento Em OpenGL Encapsular os pontos pelo bloco glbegin(gl_line_strip)/glend() Todos os pontos são utilizados 11
Vertex* - GL_LINE_STRIP GLint p[5][2] = {{0,50}, {-47,15}, {-29,-40}, {29,-40}, {47,15}}; glbegin(gl_line_strip); glvertex2iv(p[0]); glvertex2iv(p[2]); glvertex2iv(p[4]); glvertex2iv(p[1]); glvertex2iv(p[3]); glend(); 12
Definindo Segmentos Fechados Equivale ao caso anterior, exceto que o último ponto é conectado ao primeiro Em OpenGL Encapsular os pontos pelo bloco glbegin(gl_line_loop)/glend() 13
Vertex* - GL_LINE_LOOP GLint p[5][2] = {{0,50}, {-47,15}, {-29,-40}, {29,-40}, {47,15}}; glbegin(gl_line_loop); glvertex2iv(p[0]); glvertex2iv(p[2]); glvertex2iv(p[4]); glvertex2iv(p[1]); glvertex2iv(p[3]); glend(); 14
Propriedades das Linhas Tamanho da linha 1 pixel Alterando o tamanho: void gllinewidth(glfloat width); Obtendo os valores máximo e mínimo Sizes[0] valor mínimo Sizes[1] valor máximo GLfloat sizes[2], step; glgetfloatv(gl_line_width_range, sizes); glgetfloatv(gl_line_width_granularity, &step); 15
Propriedades das Linhas (2) Tracejado Primeiramente, deve ser habilitado com: glenable(gl_line_stipple); Pode ser desabilitado a qualquer momento por: gldisable(gl_line_stipple); Tipo de tracejado é definido por: void gllinestipple(glint factor, Glushort pattern); 16
Propriedades do Tracejado (2) Pattern 16 bits, onde cada bit representa 1 pixel que está on ou off Factor multiplicador de pixels Cada pixel do pattern é multiplicado por este valor 17
Definindo Polígonos Polígonos são consideradas superfícies Não definem apenas o perímetro, mas são fechadas e opacas Possuem dois lados Definido pela ordem que pontos são definidos (winding) Interno Sentido horário regra da mão esquerda Externo Sentido antihorário mão direita 18
Polígonos Definições Composto de vértices, arestas (edges) e faces Devem ser convexos Não podem haver arestas cruzadas 19
Triângulos É definido por 3 pontos Ponto é definido pela função glvertex Em OpenGL Encapsular os pontos pelo bloco glbegin(gl_triangles)/glend() Se os pontos forem menor do que 3, são descartados 20
Triângulos (2) GLint pts[6][2] = {{-100, 0}, {-50, -86}, {50, -86}, {100, 0}, {50, 86}, {-50, 86}}; glbegin(gl_triangles); glvertex2iv(pts[0]); glvertex2iv(pts[1]); glvertex2iv(pts[5]); glvertex2iv(pts[2]); glvertex2iv(pts[3]); glvertex2iv(pts[4]); glend(); 21
Winding 22
Tiras de Triângulos Um novo triângulo pode ser definido pelos dois últimos pontos do triângulo anterior e definindo um novo ponto Em OpenGL Encapsular os pontos pelo bloco glbegin(gl_triangle_strip)/glend() 23
Tiras de Triângulos (2) GLint pts[6][2] = {{-100, 0}, {-50, -86}, {50, -86}, {100, 0}, {50, 86}, {-50, 86}}; glbegin(gl_triangle_strip); glvertex2iv(pts[0]); glvertex2iv(pts[1]); glvertex2iv(pts[5]); glvertex2iv(pts[2]); glvertex2iv(pts[4]); glvertex2iv(pts[3]); glend(); 24
Tiras de Triângulos (3) Definição do winding Triângulos numerados de 0 a n face externa é definida como: Triângulos pares p n, p n+1 p n+2 Triângulos impares p n+1, p n, p n+2 25
Ventoinha de Triângulos Um novo triângulo é formado pelo primeiro ponto, pelo último utilizado e pelo novo ponto definido Em OpenGL Encapsular os pontos pelo bloco glbegin(gl_triangle_fan)/glend() 26
Ventoinha de Triângulos (2) GLint pts[6][2] = {{-100, 0}, {-50, -86}, {50, -86}, {100, 0}, {50, 86}, {-50, 86}}; glbegin(gl_triangle_fan); glvertex2iv(pts[0]); glvertex2iv(pts[1]); glvertex2iv(pts[2]); glvertex2iv(pts[3]); glvertex2iv(pts[4]); glvertex2iv(pts[5]); glend(); 27
Cores É especificado por Vertex Cada vértice pode ter uma cor distinta Função: glcolor Qual cor o polígono vai ter? Depende do modelo de sombreamento glshademodel(gl_flat); Cor do último vértice define a cor do polígono glshademodel(gl_smooth); Cor do polígono é a interpolação das cores de cada vértice 28
Exemplo do glshademodel 29
Escondendo Superfícies Ocultas Performance Se superfície oculta não precisa ser vista Performance é melhorada se não for desenhada Chamado de culling glenable(gl_cull_face); Voltando a desenhar as superfícies glenable(gl_cull_face); Note que superfícies parcialmente ocultas são desenhadas Note a diferença entre superfície interna e externa interna não é vista quando habilitada 30
Culling 31
Formatação do Polígono Padrão polígono é preenchido pela cor sólida glpolygonmode(face, modo); Onde: Face GL_FRONT, GL_BACK, GL_FRONT_AND_BACK Mode GL_POINT, GL_LINE, GL_FILL 32
Quadriláteros (2) GLint pts[8][2] = { {-10, 10}, {-10, 0}, {0, 0}, {0,10}, {5,5}, {5,0}, {10,0}, {10,5}}; glbegin(gl_quads); glvertex2iv(pts[0]); glvertex2iv(pts[1]); glvertex2iv(pts[2]); glvertex2iv(pts[3]); glvertex2iv(pts[4]); glvertex2iv(pts[5]); glvertex2iv(pts[6]); glvertex2iv(pts[7]); glend(); 33
Tiras de Quadriláteros Novo quadrilátero é definido usando os dois últimos pontos e definindo 2 novos pontos Em OpenGL Encapsular os pontos pelo bloco glbegin(gl_quad_strip)/glend() 34
Tiras de Quadriláteros (2) GLint pts[8][2] = { {-10, 10}, {-10, 0}, {0, 0}, {0,10}, {5,5}, {5,0}, {10,0}, {10,5}}; glbegin(gl_quad_strip); glvertex2iv(pts[0]); glvertex2iv(pts[1]); glvertex2iv(pts[3]); glvertex2iv(pts[2]); glvertex2iv(pts[4]); glvertex2iv(pts[5]); glvertex2iv(pts[7]); glvertex2iv(pts[6]); glend(); 35
Tiras de Quadriláteros (3) Definição do winding GL_QUAD_STRIP Vertices face externa 2n 1, 2n, 2n + 2 e 2n + 1 36
Preenchimento de Polígonos 2 modos: Texturização Aplicando padrões Composto de um bitmap de 32x32 pontos 37
Resumo Note que está sendo usado a regra da mão esquerda (visão interior das faces 38
FIM 39
GL Funções Funções de linhas: GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_LINE_LOOP Funções de preenchimento de áreas: GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_QUADS, GL_QUAD_STRIP, GL_POLYGON Curvas são aproximadas por polígonos Processo conhecido por Tessellation 40
Polígonos - Definições Composto de vértices, arestas (edges) e faces Devem ser convexos Não podem haver arestas cruzadas 41
Face Frontal e Traseira Todo polígono tem duas faces Visibilidade diferente para cada face glpolygonmode(face, mode); Vetor normal à superfície mostra a face externa, ou frontal Vértices posicionados no sentido contrário do relógio fornece a face frontal Regra da mão direita Eliminar faces escondidas glenable(gl_cull_face); gldisable(gl_cull_face); 42
GL Funções glvertex*: especifica pontos glbegin, glend Delimita os vértices de uma primitiva Primitivas de linha GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_LINE_LOOP, Primitivas de Área GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_QUADS, GL_QUAD_STRIP, GL_POLYGON glrect*: desenha um retângulo 2D glpushmatrix, glpopmatrix Operações de pilha sobre a matriz corrente 43
GL Operação de Matrizes glmatrixmode GL_MODELVIEW, GL_PROJECTION, GL_TEXTURE e GL_COLOR glloadidentity: Substitui a corrente pela matriz identidade glloadmatrix*: substitui a matriz corrente pela especificada glmultmatrix* Multiplica a matriz corrente com a especificada 44
Exemplo void desenha(void) { GLfloat cubo[8][3] = { { 1.000000, -1.000000, -1.000000}, { 1.000000, -1.000000, 1.000000}, {-1.000000, -1.000000, 1.000000}, {-1.000000, -1.000000, -1.000000}, { 1.000000, 1.000000, -1.000000}, { 1.000000, 1.000000, 1.000000}, {-1.000000, 1.000000, 1.000000}, {-1.000000, 1.000000, -1.000000} }; GLfloat cubocolor[8][3] = { {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}, {1.0, 1.0, 0.0}, {0.0, 1.0, 1.0}, {1.0, 0.0, 1.0}, }; // limpa o buffer para um novo quadro glclear(gl_color_buffer_bit); glmatrixmode(gl_modelview); // matrix de modelagem glloadidentity(); // zera qualquer transformação glulookat(eye[0], eye[1], eye[2], 0, 0, 0, 0, 1, 0); glbegin(gl_quads); glcolor3fv(cubocolor[0]); glvertex3fv(cubo[0]); glcolor3fv(cubocolor[1]); glvertex3fv(cubo[1]); glcolor3fv(cubocolor[2]); glvertex3fv(cubo[2]); glcolor3fv(cubocolor[3]);glvertex3fv(cubo[3]); glcolor3fv(cubocolor[4]); glvertex3fv(cubo[4]); glcolor3fv(cubocolor[7]); glvertex3fv(cubo[7]); glcolor3fv(cubocolor[6]); glvertex3fv(cubo[6]); glcolor3fv(cubocolor[5]); glvertex3fv(cubo[5]); glcolor3fv(cubocolor[0]); glvertex3fv(cubo[0]); glcolor3fv(cubocolor[4]); glvertex3fv(cubo[4]); glcolor3fv(cubocolor[5]); glvertex3fv(cubo[5]); glcolor3fv(cubocolor[1]); glvertex3fv(cubo[1]); glcolor3fv(cubocolor[1]); glvertex3fv(cubo[1]); glcolor3fv(cubocolor[5]); glvertex3fv(cubo[5]); glcolor3fv(cubocolor[6]); glvertex3fv(cubo[6]); glcolor3fv(cubocolor[2]); glvertex3fv(cubo[2]); glcolor3fv(cubocolor[2]); glvertex3fv(cubo[2]); glcolor3fv(cubocolor[6]); glvertex3fv(cubo[6]); glcolor3fv(cubocolor[7]); glvertex3fv(cubo[7]); glcolor3fv(cubocolor[3]); glvertex3fv(cubo[3]); glcolor3fv(cubocolor[4]); glvertex3fv(cubo[4]); glcolor3fv(cubocolor[0]); glvertex3fv(cubo[0]); glcolor3fv(cubocolor[3]); glvertex3fv(cubo[3]); glcolor3fv(cubocolor[7]); glvertex3fv(cubo[7]); glend(); glflush(); } 45
GL Miscelâneas glcolor* especifica a cor corrente glclearcolor cor de fundo do buffer glclear: GL_COLOR_BUFFER_BIT ou GL_DEPTH_BUFFER_BIT ou GL_ACCUM_BUFFER_BIT ou GL_STENCIL_BUFFER_BIT glflush: força a execução da pilha de comandos 46
GL Miscelâneas (2) glrasterpos* especifica a posição de raster para operações de pixel glnewlist, glgenlists, glcalllist, glendlist Comandos que podem ser chamados e executados posteriormente Úteis para a modelagem de objetos repetitivos glfrustum: matriz perspectiva 47
Display List Otimiza a criação de objetos estáticos Armazena os comandos em linguagem de hardware para futuro processamento Depois de criado não pode ser alterado Lista pode ser armazenada no buffer da placa de vídeo ou na memória Normalmente é criada na inicialização do programa Depende do tipo de aplicação (jogos, por exemplo, as utilizaria para inicializar os níveis ou fases) 48
Display List - comandos GLuint glgenlists(faixa); Reserva uma faixa de ID de listas Retorna zero no caso de erro glnewlist(id, tipo); / glendlist(); Cria uma lista estática Tipo = GL_COMPILE ou GL_COMPILE_AND_EXECUTE Permitido definição de objetos e mudanças de estado na máquina OpenGL Permite chamar outras listas também 49
Display List comandos (2) glcalllist(id); Invoca uma lista previamente criada gldeletelists(id inicial, faixa); Libera a memória de uma lista Evitar colocar informações de textura em lista Desperdício de memória Acesso ao buffer de vídeo não tem sentindo numa lista 50
Exemplo void init(void) { GLfloat cubo[8][3] = { { 1.000000, -1.000000, -1.000000}, { 1.000000, -1.000000, 1.000000}, {-1.000000, -1.000000, 1.000000}, {-1.000000, -1.000000, -1.000000}, { 1.000000, 1.000000, -1.000000}, { 1.000000, 1.000000, 1.000000}, {-1.000000, 1.000000, 1.000000}, {-1.000000, 1.000000, -1.000000} }; GLfloat cubocolor[8][3] = { {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}, {1.0, 1.0, 0.0}, {0.0, 1.0, 1.0}, {1.0, 0.0, 1.0}, }; list = glgenlists(1); if (!list) { printf("impossível alocar nova lista\n"); exit(exit_failure); } glnewlist(list, GL_COMPILE); glbegin(gl_quads); glcolor3fv(cubocolor[0]); glvertex3fv(cubo[0]); glcolor3fv(cubocolor[1]); glvertex3fv(cubo[1]); glcolor3fv(cubocolor[2]); glvertex3fv(cubo[2]); glcolor3fv(cubocolor[3]);glvertex3fv(cubo[3]); glcolor3fv(cubocolor[4]); glvertex3fv(cubo[4]); glcolor3fv(cubocolor[7]); glvertex3fv(cubo[7]); glcolor3fv(cubocolor[6]); glvertex3fv(cubo[6]); glcolor3fv(cubocolor[5]); glvertex3fv(cubo[5]); glcolor3fv(cubocolor[0]); glvertex3fv(cubo[0]); glcolor3fv(cubocolor[4]); glvertex3fv(cubo[4]); glcolor3fv(cubocolor[5]); glvertex3fv(cubo[5]); glcolor3fv(cubocolor[1]); glvertex3fv(cubo[1]); glcolor3fv(cubocolor[1]); glvertex3fv(cubo[1]); glcolor3fv(cubocolor[5]); glvertex3fv(cubo[5]); glcolor3fv(cubocolor[6]); glvertex3fv(cubo[6]); glcolor3fv(cubocolor[2]); glvertex3fv(cubo[2]); glcolor3fv(cubocolor[2]); glvertex3fv(cubo[2]); glcolor3fv(cubocolor[6]); glvertex3fv(cubo[6]); glcolor3fv(cubocolor[7]); glvertex3fv(cubo[7]); glcolor3fv(cubocolor[3]); glvertex3fv(cubo[3]); glcolor3fv(cubocolor[4]); glvertex3fv(cubo[4]); glcolor3fv(cubocolor[0]); glvertex3fv(cubo[0]); glcolor3fv(cubocolor[3]); glvertex3fv(cubo[3]); glcolor3fv(cubocolor[7]); glvertex3fv(cubo[7]); glend(); glendlist(); glclearcolor(0, 0, 0, 1.0); // cor de fundo (branco) } 51
Exemplo - Continuação void desenha(void) { // limpa o buffer para um novo quadro glclear(gl_color_buffer_bit); // todos os bit são iguais à branco glmatrixmode(gl_modelview); // matrix de modelagem glloadidentity(); // zera qualquer transformação glulookat(eye[0], eye[1], eye[2], 0, 0, 0, 0, 1, 0); // direção de visualização glcalllist(list); glflush(); } // força a visualização 52
Display list - comentários Ganho de performance? Não precisa criar o objeto toda vez que é invocado Objetos do mesmo tipo pode ser chamado várias vezes, com uma única inicialização 53
Vetor de vértices Permite a criação de lista de forma dinâmica Pode ser mudado o formato do objeto dentro do vetor previamente calculado Exemplo, uma mesh que define o oceano, em cada quadro, a mesh pode ser atualizada No OpenGL, o vetor é transferido do cliente para o servidor em lote Ganho de performance 54
Vetor de Vértices - Etapas Construir os vetores vértice, cor, coordenadas de textura, vetor normal, etc Dizer ao OpenGL onde se encontram esses vetores Dizer quais vetores a aplicação está interessada Executar a renderização do quadro 55
Vetor de Vértices - Comandos Habilitando vetores: gglenableclientstate(x); gldisableclientstate(x); X = GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_NORMAL_ARRAY, etc Note que é uma operação realizada do lado do cliente e não do servidor 56
Vetor de Vértices Comandos (2) Onde estão os dados? glvertexpointer(...); glcolorpointer(...); glnormalpointer(...); Desenhando glarrayelement(índice); Especifica o indice do vetor previamente registrado 57
Vetor de Vértices Comandos (3) Forma mais econômica: gldrawarrays(mode, first, count); Desenha o objeto (mode = GL_TRIANGLES, etc), com o índice iniciando em first e count especificando a quantidade Forma usando vetor de índices gldrawelements(mode, count, tipo, indices); Mesmo comentário anterior, onde índice é um vetor 58
Exemplo // váriaveis globais, ou estáticas na função // desenha() GLfloat cubo[24] = { 1.000000, -1.000000, -1.000000, 1.000000, -1.000000, 1.000000, -1.000000, -1.000000, 1.000000, -1.000000, -1.000000, -1.000000, 1.000000, 1.000000, -1.000000, 1.000000, 1.000000, 1.000000, -1.000000, 1.000000, 1.000000, -1.000000, 1.000000, -1.000000 }; GLfloat cubocolor[24] = { 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0 }; void init(void) { glenableclientstate(gl_vertex_array); glenableclientstate(gl_color_array); glclearcolor(0.5, 0.5, 0.5, 1.0); } void desenha(void) { // limpa o buffer para um novo quadro glclear(gl_color_buffer_bit); // cor de fundo (cinza) // todos os bit são iguais à branco glmatrixmode(gl_modelview); // matrix de modelagem glloadidentity(); // zera qualquer transformação glulookat(eye[0], eye[1], eye[2], 0, 0, 0, 0, 1, 0); // direção de // visualização glvertexpointer(3, GL_FLOAT, 0, cubo); glcolorpointer(3, GL_FLOAT, 0, cubocolor); gldrawelements(gl_quads, 24, GL_UNSIGNED_BYTE, indices); GLubyte indices[24] = { }; 0, 1, 2, 3, 4, 7, 6, 5, 0, 4, 5, 1, 1, 5, 6, 2, 2, 6, 7, 3, 4, 0, 3, 7 glflush(); } // força a visualização 59
Bibliografia Adicional http://www.opengl.org/sdk/docs/man/ http://www.opengl.org/resources/libraries/glut/sp http://www.opengl.org/resources/code/samples/gl ut_examples/examples/examples.html 60