Métodos para Rendering de Superfície
Transcrição
Métodos para Rendering de Superfície
Métodos para Rendering de Superfície Métodos para Rendering de Superfície SCC0250 - Computação Gráca Prof. Fernando V. Paulovich http://www.icmc.usp.br/~paulovic [email protected] Instituto de Ciências Matemáticas e de Computação (ICMC) Universidade de São Paulo (USP) 16 de maio de 2011 1 / 50 Métodos para Rendering de Superfície Introdução Sumário 1 Introdução 2 Programação OpenGL (Rendering) 3 OpenGL Shading Language Programação OpenGL 2 / 50 Métodos para Rendering de Superfície Introdução Sumário 1 Introdução 2 Programação OpenGL (Rendering) 3 OpenGL Shading Language Programação OpenGL 3 / 50 Métodos para Rendering de Superfície Introdução Introdução Baseado no modelo de iluminação, um método de rendering de superfície é usado para determinar a cor dos pixels O modelo de iluminação pode ser usado de formas diferentes para denir a cor de uma superfície Ray-tracing: executado em cada pixel projetado (realismo) Scan-line: executado em alguns pixels e interpolado no restante (tempo real) 4 / 50 Métodos para Rendering de Superfície Introdução Métodos de Rendering de Superfície Maioria das APIs grácas reduz o processamento usando algoritmos de scan-line As intensidades são calculadas nos vértices e interpoladas nas posições restantes dos polígonos 5 / 50 Métodos para Rendering de Superfície Introdução Rendering de Superfície de Intensidade Constante O método mais simples para renderizar uma superfície é usar a mesma cor para todos seus pontos (at surface rendering) Emprega-se o modelo de iluminação para determinar a intensidade das 3 componentes RGB em uma única posição da superfície Vértice ou centróide do polígono 6 / 50 Métodos para Rendering de Superfície Introdução Rendering de Superfície de Intensidade Constante O at surface rendering normalmente dene resultados precisos se O polígono é uma face de um poliedro e não uma seção de uma superfície curva Todas as fontes de luz estão distantes o suciente da superfície de forma que N · L e a função de atenuação são constantes A posição visão é distante o suciente do polígono de forma que V·R I (ou N · H) = ka Ia + é constante Pn l=1 Il [kd (N · L) + ks (N · H)ns ] Mesmo se alguma dessas condições for falsa, uma boa aproximação pode ser conseguida se os polígonos empregados forem pequenos 7 / 50 Métodos para Rendering de Superfície Introdução Rendering de Superfície de Gouraud O esquema de Gouraud surface rendering interpola linearmente as intensidades nos vértices por toda face do polígono de um objeto iluminado Desenvolvido para aproximar superfícies curvas, amenizando as transições de intensidades entre polígonos adjacentes Elimina as descontinuidades de intensidades do at surface rendering 8 / 50 Métodos para Rendering de Superfície Introdução Rendering de Superfície de Gouraud Cada polígono de uma superfície é processado usando o seguinte procedimento 1 Determina o vetor unitário normal médio em cada vértice do polígono 2 Aplica o modelo de iluminação em cada vértice para obter as intensidades 3 Interpola linearmente as intensidades dos vértices sobre a área projetada do polígono 9 / 50 Métodos para Rendering de Superfície Introdução Rendering de Superfície de Gouraud O vetor normal médio em um vértice é obtido fazendo a média das normais de todos os polígonos que compartilham esse vértice Pn Nk NV = Pk=1 n | k=1 Nk | Usando essas normais o modelo de iluminação é então executado para calcular as intensidades em cada vértice 10 / 50 Métodos para Rendering de Superfície Introdução Rendering de Superfície de Gouraud Esses valores de intensidade são então interpolados para se obter as intensidades ao longo de scan-lines que intersectam a área projetada do polígono As intensidades das intersecções das scan-lines com as arestas dos polígonos são calculadas interpolando linearmente as intensidades dos pontos nais das arestas 11 / 50 Métodos para Rendering de Superfície Introdução Rendering de Superfície de Gouraud Por exemplo, a intensidade em 4 pode ser calculada considerando somente o deslocamento vertical da scan-line y1 − y4 y4 − y2 I1 + I2 I4 = y1 − y2 y1 − y2 A intensidade em 5 pode ser obtida da mesma forma interpolando verticalmente as intensidades em 2 e 3 12 / 50 Métodos para Rendering de Superfície Introdução Rendering de Superfície de Gouraud Considerando as intensidades obtidas em 4 e 5, as intensidades em qualquer ponto p da scan-line são obtidas interpolando na horizontal x5 − xp xp − x4 Ip = I4 + I5 x5 − x4 x5 − x4 Esse método é conhecido como interpolação bilinear e é executado para os 3 componentes RGB separadamente 13 / 50 Métodos para Rendering de Superfície Introdução Rendering de Superfície de Gouraud Essa interpolação de intensidades elimina descontinuidades mas tem alguns problemas Brilhos na superfície podem apresentar formatos estranhos mach Intensidades claras ou escuras podem parecer riscadas ( bands) 14 / 50 Métodos para Rendering de Superfície Introdução Rendering de Superfície de Gouraud Efeito de mach bands consiste em faixas claras ou escuras que são percebidas próximo das fronteiras entre duas regiões de diferentes gradientes de luz 15 / 50 Métodos para Rendering de Superfície Introdução Rendering de Superfície de Phong Um método mais preciso de interpolação é conhecido como Phong surface rendering Ao invés de interpolar valores de intensidades, normais são interpoladas Cálculos mais precisos de intensidades Brilhos mais realísticos nas superfícies Redução do efeito mach-band Computacionalmente mais caro que o método de Gouraud 16 / 50 Métodos para Rendering de Superfície Introdução Rendering de Superfície de Phong Cada polígono é processado usando o seguinte procedimento 1 Determina o vetor unitário normal médio em cada vértice do polígono 2 Interpola linearmente as normais dos vértices sobre a área projetada do polígono 3 Aplica o modelo de iluminação nas posições ao longo da scan-line para calcular as intensidades dos pixels usando as normais interpoladas 17 / 50 Métodos para Rendering de Superfície Introdução Rendering de Superfície de Phong O procedimento de interpolação das normais é o mesmo da interpolação das intensidades do método de Gouraud Por exemplo, o vetor normal N é verticalmente interpolado a partir das normais nos vértices 1 e 2 fazendo y − y2 y1 − y N= N1 + N2 y1 − y2 y1 − y2 18 / 50 Métodos para Rendering de Superfície Programação OpenGL (Rendering) Sumário 1 Introdução 2 Programação OpenGL (Rendering) 3 OpenGL Shading Language Programação OpenGL 19 / 50 Métodos para Rendering de Superfície Programação OpenGL (Rendering) Funções de Rendering de Superfície Podemos usar dois métodos de rendering da superfície: (1) de intensidade constante (at); (2) e o modelo de Gouraud (smoothing) Não existe suporte para o modelo de Phong Para denir o método de rendering usamos 1 gl.glShadeModel(rendering_method); Onde rendering_method pode ser GL.GL_FLAT e GL.GL_SMOOTH 20 / 50 Métodos para Rendering de Superfície Programação OpenGL (Rendering) Funções de Rendering de Superfície Para se denir a normal usamos 1 gl.glNormal3*(Nx, Ny, Nz); Com o suxo dependendo do tipo de parâmetro b, s, i, f e d, ou com a adição de v caso o parâmetro seja um vetor Valores byte, short e integer são convertidos para valores de ponto utuante na faixa de −1.0 a 1.0 A normal é um valor de estado da OpenGL e tem valor padrão igual a (0.0, 0.0, 1.0) 21 / 50 Métodos para Rendering de Superfície Programação OpenGL (Rendering) Funções de Rendering de Superfície Para rendering de intensidade constante denimos apenas uma normal para cada polígono 1 2 3 4 5 6 7 gl.glNormal3fv(normal_vector); gl.glBegin(GL.GL_TRIANGLES); gl.glVertex3fv(vertex1); gl.glVertex3fv(vertex2); gl.glVertex3fv(vertex3); gl.glEnd(); 22 / 50 Métodos para Rendering de Superfície Programação OpenGL (Rendering) Funções de Rendering de Superfície Para o rendering de Gouraud uma normal deve ser denida para cada vértice 1 2 3 4 5 6 7 8 9 10 gl.glBegin(GL_TRIANGLES); gl.glNormal3fv(normal_vector1); gl.glVertex3fv(vertex1); gl.glNormal3fv(normal_vector2); gl.glVertex3fv(vertex2); gl.glNormal3fv(normal_vector3); gl.glVertex3fv(vertex3); gl.glEnd(); 23 / 50 Métodos para Rendering de Superfície Programação OpenGL (Rendering) Funções de Rendering de Superfície Apesar dos vetores normais não precisarem ser especicados com tamanho unitário, fazendo isso reduzimos o custo computacional É possível solicitar a OpenGL normalizar qualquer vetor normal que não seja unitário chamando 1 gl.glEnable(GL.GL_NORMALIZE); Esse comando renormaliza todas as normais às superfícies incluindo as que foram modicadas por transformações geométricas de escala e cisalhamento 24 / 50 Métodos para Rendering de Superfície Programação OpenGL (Rendering) Rendering de Superfície 1 public class Rendering implements GLEventListener { 2 /** calcula o produto vetorial. */ 3 private Point3D crossproduct(Point3D a, Point3D b) { Point3D prod = new Point3D(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - b.x * a.y); return prod; } 4 5 6 7 8 9 10 /** normaliza um vetor de entrada. */ 11 private Point3D normalize(Point3D p) { float norm = (float) Math.sqrt(p.x * p.x + p.y * p.y + p.z * p.z); return new Point3D(p.x / norm, p.y / norm, p.z / norm); } 12 13 14 15 16 /** Representa uma Célula com posição 3D e uma normal. */ 17 class Cell { public Point3D point; public Point3D normal; } 18 19 20 21 22 /** Representa um ponto ou vetor 3D (x,y,z). */ 23 24 25 26 27 28 29 30 31 32 } class Point3D { public Point3D(float x, float y, float z) { this.x = x; this.y = y; this.z = z; } public float x; public float y; public float z; } 25 / 50 Métodos para Rendering de Superfície Programação OpenGL (Rendering) Rendering de Superfície 1 2 public class Rendering implements GLEventListener { ... 3 /** cria uma matriz formando uma gaussiana. As primeiras e últimas linhas e colunas são criadas apenas como forma para facilitar o cálculo das normais em cada ponto. Essas não devem ser usadas para o desenho da gaussiana. */ 4 5 6 7 private Cell[][] createMatrix(int size) { Cell[][] matrix = new Cell[size + 2][size + 2]; 8 9 10 for (int i = 0; i < size + 2; i++) { for (int j = 0; j < size + 2; j++) { matrix[i][j] = new Cell(); float x = (4.0f * j) / ((float) size + 2) - 2.0f; float z = (4.0f * i) / ((float) size + 2) - 2.0f; float y = (float) (Math.exp(-x * x) * Math.exp(-z * z)); matrix[i][j].point = new Point3D(x, y, z); } } 11 12 13 14 15 16 17 18 19 20 21 22 23 } } return matrix; 26 / 50 Métodos para Rendering de Superfície Programação OpenGL (Rendering) Rendering de Superfície 1 2 public class Rendering implements GLEventListener { ... 3 /** calcula as normais em cada ponto. As primeiras e últimas linhas e colunas são ignoradas. Seja V1 o ponto para o qual será calculada a normal, V2 o ponto na mesma linha e próxima coluna e V3 o ponto na próxima linha e mesma coluna. A normal é computada como o produto vetorial do vetores de V1 para V2 e de V3 para V1. */ 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 } private void calculateNormal(Cell[][] matrix) { for (int i = 1; i < matrix.length - 1; i++) { for (int j = 1; j < matrix[0].length - 1; j++) { Point3D v1 = matrix[i][j].point; Point3D v2 = matrix[i][j + 1].point; Point3D v3 = matrix[i + 1][j].point; Point3D vec1 = new Point3D(v2.x-v1.x, v2.y-v1.y, v2.z-v1.z); Point3D vec2 = new Point3D(v1.x-v3.x, v1.y-v3.y, v1.z-v3.z); matrix[i][j].normal = normalize(crossproduct(vec1, vec2)); } } } 27 / 50 Métodos para Rendering de Superfície Programação OpenGL (Rendering) Rendering de Superfície 1 2 public class Rendering implements GLEventListener { ... 3 public static void main(String[] args) { 4 //cria o painel e adiciona um ouvinte GL 5 Rendering pp = new Rendering(); GLJPanel panel = new GLJPanel(); panel.addGLEventListener(pp); 6 7 8 9 //cria uma janela e adiciona o painel 10 11 12 13 14 15 16 } 17 18 19 20 } JFrame frame = new JFrame("Aplicacao JOGL Simples"); frame.add(panel); frame.setSize(800, 800); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLocationRelativeTo(null); frame.setVisible(true); ... 28 / 50 Métodos para Rendering de Superfície Programação OpenGL (Rendering) Rendering de Superfície 1 2 public class Rendering implements GLEventListener { ... 3 public void init(GLAutoDrawable drawable) { GL gl = drawable.getGL(); GLU glu = new GLU(); 4 5 6 7 gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); //dene a cor de fundo gl.glEnable(GL.GL_DEPTH_TEST); //habilita o teste de profundidade 8 9 10 gl.glMatrixMode(GL.GL_MODELVIEW); //dene que a matrix gl.glLoadIdentity(); //carrega a matrix de identidade glu.gluLookAt(1.5, 0.75, 1.0, //posição da câmera 0.0, 0.0, 0.0, //para onde a câmera aponta 0.0, 1.0, 0.0); //vetor view−up 11 12 13 14 15 16 gl.glMatrixMode(GL.GL_PROJECTION); //dene que a matrix gl.glLoadIdentity(); //carrega a matrix de identidade gl.glOrtho(-2.5, 2.5, -2.5, 2.5, -4.5, 4.5); 17 18 19 20 21 22 23 é a model view } } lighting(drawable); é a de projeção //deninido os parâmetros de iluminação 29 / 50 Métodos para Rendering de Superfície Programação OpenGL (Rendering) Rendering de Superfície 1 2 public class Rendering implements GLEventListener { ... 3 private void lighting(GLAutoDrawable drawable) { GL gl = drawable.getGL(); 4 5 6 //dene a posição e parâmetros da luz 0 7 float position[] = {1.0f, 1.5f, -0.5f, 1.0f}; float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; float black[] = {0.0f, 0.0f, 0.0f, 1.0f}; gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, position, 0); gl.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, black, 0); gl.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, white, 0); gl.glLightfv(GL.GL_LIGHT0, GL.GL_SPECULAR, white, 0); 8 9 10 11 12 13 14 15 //ativa a iluminação 16 gl.glEnable(GL.GL_LIGHTING); gl.glEnable(GL.GL_LIGHT0); 17 18 19 //dene as propriedades de reexção da superfície 20 21 22 23 24 25 26 27 28 } } float diffuse[] = {0.5f, 0.5f, 0.8f, 1.0f}; float specular[] = {1.0f, 1.0f, 1.0f, 1.0f}; float shininess = 100.0f; gl.glMaterialfv(GL.GL_FRONT, GL.GL_DIFFUSE, diffuse, 0); gl.glMaterialfv(GL.GL_FRONT, GL.GL_SPECULAR, specular, 0); gl.glMaterialf(GL.GL_FRONT, GL.GL_SHININESS, shininess); 30 / 50 Métodos para Rendering de Superfície Programação OpenGL (Rendering) Rendering de Superfície 1 2 public class Rendering implements GLEventListener { ... 3 public void display(GLAutoDrawable drawable) { GL gl = drawable.getGL(); gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); 4 5 6 7 //cria matrix com as células para desenho 8 Cell[][] m = createMatrix(40); calculateNormal(m); 9 10 11 //desenha a superfície 12 for (int i = 1; i < m.length - 1; i++) { for (int j = 1; j < m.length - 1; j++) { gl.glNormal3f(m[i][j].n.x, m[i][j].n.y, m[i][j].n.z); 13 14 15 16 17 18 19 20 21 22 23 } 24 25 26 27 28 } } } gl.glBegin(GL.GL_TRIANGLE_STRIP); gl.glVertex3f(m[i+1][j].p.x, m[i+1][j].p.y, m[i+1][j].p.z); gl.glVertex3f(m[i+1][j+1].p.x, m[i+1][j+1].p.y, m[i+1][j+1].p.z); gl.glVertex3f(m[i][j].p.x, m[i][j].p.y, m[i][j].p.z); gl.glVertex3f(m[i][j+1].p.x, m[i][j+1].p.y, m[i][j+1].p.z); gl.glEnd(); gl.glFlush(); //força o desenho das primitivas 31 / 50 Métodos para Rendering de Superfície Programação OpenGL (Rendering) Rendering de Superfície Uma normal por face: a tonalização da face é constante 32 / 50 Métodos para Rendering de Superfície Programação OpenGL (Rendering) Rendering de Superfície 1 2 3 4 5 6 7 8 9 10 11 public class Rendering implements GLEventListener { ... public void display(GLAutoDrawable drawable) { ... for (int i = 1; i < m.length - 1; i++) { for (int j = 1; j < m.length - 1; j++) { gl.glBegin(GL.GL_TRIANGLE_STRIP); if (m[i+1][j].n != null) { gl.glNormal3f(m[i+1][j].n.x, m[i+1][j].n.y, m[i+1][j].n.z); } gl.glVertex3f(m[i+1][j].p.x, m[i+1][j].p.y, m[i+1][j].p.z); 12 if (m[i+1][j+1].n != null) { gl.glNormal3f(m[i+1][j+1].n.x, m[i+1][j+1].n.y, m[i+1][j+1].n.z); } gl.glVertex3f(m[i+1][j+1].p.x, m[i+1][j+1].p.y, m[i+1][j+1].p.z); 13 14 15 16 17 if (m[i][j].n != null) { gl.glNormal3f(m[i][j].n.x, m[i][j].n.y, m[i][j].n.z); } gl.glVertex3f(m[i][j].p.x, m[i][j].p.y, m[i][j].p.z); 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 } } } } ... if (m[i][j+1].n != null) { gl.glNormal3f(m[i][j+1].n.x, m[i][j+1].n.y, m[i][j+1].n.z); } gl.glVertex3f(m[i][j+1].p.x, m[i][j+1].p.y, m[i][j+1].p.z); gl.glEnd(); 33 / 50 Métodos para Rendering de Superfície Programação OpenGL (Rendering) Rendering de Superfície 1 2 3 4 public class Rendering implements GLEventListener { ... private void lighting(GLAutoDrawable drawable) { GL gl = drawable.getGL(); 5 //dene a posição e parâmetros da luz 0 6 float position[] = {1.0f, 1.5f, -0.5f, 1.0f}; float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; float black[] = {0.0f, 0.0f, 0.0f, 1.0f}; 7 8 9 10 gl.glLightfv(GL.GL_LIGHT0, gl.glLightfv(GL.GL_LIGHT0, gl.glLightfv(GL.GL_LIGHT0, gl.glLightfv(GL.GL_LIGHT0, 11 12 13 14 15 //ativa a iluminação 16 gl.glEnable(GL.GL_LIGHTING); gl.glEnable(GL.GL_LIGHT0); 17 18 19 //dene as propriedades de reexção da superfície 20 float diffuse[] = {0.5f, 0.5f, 0.8f, 1.0f}; float specular[] = {1.0f, 1.0f, 1.0f, 1.0f}; float shininess = 100.0f; 21 22 23 24 gl.glMaterialfv(GL.GL_FRONT, GL.GL_DIFFUSE, diffuse, 0); gl.glMaterialfv(GL.GL_FRONT, GL.GL_SPECULAR, specular, 0); gl.glMaterialf(GL.GL_FRONT, GL.GL_SHININESS, shininess); 25 26 27 28 //ativa rendering 'smooth' 29 30 31 32 GL.GL_POSITION, position, 0); GL.GL_AMBIENT, black, 0); GL.GL_DIFFUSE, white, 0); GL.GL_SPECULAR, white, 0); } } gl.glShadeModel(GL.GL_SMOOTH); //ou GL.GL_FLAT para 'at'; 34 / 50 Métodos para Rendering de Superfície Programação OpenGL (Rendering) Rendering de Superfície Normal por vértice: a tonalização da face é contínua Matriz com 40 × 40 faces: a reexão especular é ruim 35 / 50 Métodos para Rendering de Superfície Programação OpenGL (Rendering) Rendering de Superfície Melhorando a reexão especular: matriz com 400 × 400 faces Nunca fazer isso: usar GLSL e implementar Phong 36 / 50 Métodos para Rendering de Superfície OpenGL Shading Language Sumário 1 Introdução 2 Programação OpenGL (Rendering) 3 OpenGL Shading Language Programação OpenGL 37 / 50 Métodos para Rendering de Superfície OpenGL Shading Language OpenGL Shading Language OpenGL Shading Language (GLSL) é uma linguagem de alto nível que permite aos desenvolvedores maior controle sobre o pipeline gráco sem precisar se preocupar com aspectos especícos de hardware Incluída na versão 2.0 de OpenGL Similar a linguagem C, suportando laços, comandos de decisão, etc. Alguns benefícios são Compatibilidade entre diferentes plataformas, incluindo linux, Mac OS e Windows Possibilidade de escrever shaders que podem ser usados em sistemas grácos que suportam GLSL 38 / 50 Métodos para Rendering de Superfície OpenGL Shading Language OpenGL Shading Language GLSL shaders são conjuntos de strings que são passados para a placa gráca para compilação diretamente de dentro de uma aplicação OpenGL Podem ser criados on the y de dentro de uma aplicação ou lidos a partir de arquivos texto Cada placa gráca inclui um compilador GLSL em seu driver código pode ser otimizado para utilizar as particularidades da placa 39 / 50 Métodos para Rendering de Superfície OpenGL Shading Language OpenGL Shading Language Um exemplo bem simples de GLSL que transforma um vértice da mesma forma do pipeline original 1 2 3 4 void main(void) { gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex; } E colore os fragmentos de verde 1 2 3 4 void main(void) { gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); } 40 / 50 Métodos para Rendering de Superfície OpenGL Shading Language Vertex Shader (Phong Shading) Usando a GLSL é possível usar o modelo de rendering de Phong É preciso criar um vertex shader para transferir os dados dos vértices para o fragment shader A posição e a normal são passadas para o fragment shader, e são automaticamente interpoladas 1 2 3 4 5 6 7 8 9 10 11 /* vertex shader for per−fragment Phong shading */ varying vec3 normal; varying vec4 position; void main(void) { normal = gl_NormalMatrix * gl_Normal; position = gl_ModelViewMatrix * gl_Vertex; gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; } //ou = ftransform(); gl_NormalMatrix deve ser usada no lugar da gl_ModelViewMatrix para garantir que as normais não sejam afetadas por escalas não uniformes 41 / 50 Métodos para Rendering de Superfície OpenGL Shading Language Fragment Shader (Phong Shading) 1 2 3 4 5 6 7 8 9 10 11 12 /* fragment shader for per−fragment Phong shading */ varying vec3 normal; varying vec4 position; void main() { vec3 normv = normalize(normal); //normal vec3 lightv = normalize(gl_LightSource[0].position.xyz - position.xyz); vec3 viewv = normalize(-position.xyz); //direção de visão vec3 halfv = normalize(lightv + viewv); //vetor médio //calculando a componente ambiente 13 vec4 ambient = gl_FrontMaterial.ambient * gl_LightSource[0].ambient; 14 15 //calculando a componente difusa 16 float diff = max(0.0, dot(lightv, normv)); vec4 diffuse = diff * gl_FrontMaterial.diffuse * gl_LightSource[0].diffuse; 17 18 19 //calculando a componente especular 20 float spec = max(0.0, pow(dot(halfv, normv), gl_FrontMaterial.shininess)); vec4 specular = spec * gl_FrontMaterial.specular * gl_LightSource[0].specular; 21 22 23 //calculando a cor nal 24 25 26 //luz } gl_FragColor = ambient + diffuse + specular; 42 / 50 Métodos para Rendering de Superfície OpenGL Shading Language OpenGL Shading Language Figura: Diferença de fazer o shading considerando os vértices (a esquerda) e considerando os fragmentos (a direita). Para maiores informações consulte http://www.opengl.org/documentation/glsl/ 43 / 50 Métodos para Rendering de Superfície OpenGL Shading Language Programação OpenGL Sumário 1 Introdução 2 Programação OpenGL (Rendering) 3 OpenGL Shading Language Programação OpenGL 44 / 50 Métodos para Rendering de Superfície OpenGL Shading Language Programação OpenGL Usando Shaders 1 2 public class RenderingSmoothGLSL implements GLEventListener { ... 3 public void init(GLAutoDrawable drawable) { 4 //ativa modo debug da jogl 5 drawable.setGL(new DebugGL(drawable.getGL())); 6 7 GL gl = drawable.getGL(); GLU glu = new GLU(); 8 9 10 gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); //dene a cor de fundo gl.glEnable(GL.GL_DEPTH_TEST); //habilita o teste de profundidade 11 12 13 gl.glMatrixMode(GL.GL_MODELVIEW); //dene que a matrix gl.glLoadIdentity(); //carrega a matrix de identidade glu.gluLookAt(1.5, 0.75, 1.0, //posição da câmera 0.0, 0.0, 0.0, //para onde a câmera aponta 0.0, 1.0, 0.0); //vetor view−up 14 15 16 17 18 19 gl.glMatrixMode(GL.GL_PROJECTION); //dene que a matrix gl.glLoadIdentity(); //carrega a matrix de identidade gl.glOrtho(-2.5, 2.5, -2.5, 2.5, -4.5, 4.5); 20 21 22 23 24 25 26 27 é a model view } } lighting(drawable); //deninido os parâmetros shader(drawable); //ativando o shader é a de projeção de iluminação 45 / 50 Métodos para Rendering de Superfície OpenGL Shading Language Programação OpenGL Carregando Shaders 1 2 public class RenderingSmoothGLSL implements GLEventListener { ... 3 private void shader(GLAutoDrawable drawable) { GL gl = drawable.getGL(); 4 5 6 //cria o fragment e vertex shaders 7 int v = gl.glCreateShader(GL.GL_VERTEX_SHADER); int f = gl.glCreateShader(GL.GL_FRAGMENT_SHADER); 8 9 10 //carrega e compila o vertex shader 11 String[] vsrc = readShader("/shaders/phong_vertex_shader.txt"); gl.glShaderSource(v, 1, vsrc, null, 0); gl.glCompileShader(v); 12 13 14 15 //carrega e compila o fragment shader 16 String[] fsrc = readShader("/shaders/phong_fragment_shader.txt"); gl.glShaderSource(f, 1, fsrc, null, 0); gl.glCompileShader(f); 17 18 19 20 //anexa, valida e usa os shaders 21 22 23 24 25 26 27 28 29 } } int shaderprogram = gl.glCreateProgram(); gl.glAttachShader(shaderprogram, v); gl.glAttachShader(shaderprogram, f); gl.glLinkProgram(shaderprogram); gl.glValidateProgram(shaderprogram); gl.glUseProgram(shaderprogram); 46 / 50 Métodos para Rendering de Superfície OpenGL Shading Language Programação OpenGL Lendo Arquivo de Shading 1 2 public class RenderingSmoothGLSL implements GLEventListener { ... 3 /** Lê um arquivo de shader no formato texto. */ 4 private String[] readShader(String shadername) { try { InputStream isv = getClass().getResourceAsStream(shadername); BufferedReader brv = new BufferedReader(new InputStreamReader(isv)); StringBuilder buffer = new StringBuilder(); String line; while ((line = brv.readLine()) != null) { buffer.append(line).append("\r\n"); } brv.close(); isv.close(); return new String[]{buffer.toString()}; } catch (IOException ex) { Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, ex); } 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 } } return null; 47 / 50 Métodos para Rendering de Superfície OpenGL Shading Language Programação OpenGL Phong Shader GLSL Melhorando a reexão especular usando GLSL 48 / 50 Métodos para Rendering de Superfície OpenGL Shading Language Programação OpenGL Shaders Exemplo de um shader simples: a cor do pixel é dada pelo posição de um vértice 1 2 3 /* vertex shader */ varying vec3 vertex_color; 8 void main(void) { gl_Position = ftransform(); vertex_color = gl_Vertex.xyz; } 1 /* fragment shader */ 4 5 6 7 2 3 4 5 6 7 //cor será a posição do vértice varying vec3 vertex_color; void main(void) { gl_FragColor = vec4(vertex_color, 1.0); } 49 / 50 Métodos para Rendering de Superfície OpenGL Shading Language Programação OpenGL Resultado Isso também mostra que vertex_color é interpolado quando passado do vertex shader para o fragment shader 50 / 50
Documentos relacionados
Título do Projeto - Pós-Graduação em Ciência da Computação
5.10 Visualização com o mapa de profundidade filtrado . . . . . . . . . . . . . . . . 100 5.11 Ativação do método fluxo óptico . . . . . . . . . . . . . . . . . . . . . . . . . 100 5.12 Posição da ...
Leia mais