Métodos para Rendering de Superfície
Métodos para Rendering de Superfície
SCC0250 - Computação Grá�ca
Prof. Fernando V. Paulovichhttp://www.icmc.usp.br/~paulovic
Instituto de Ciências Matemáticas e de Computação (ICMC)Universidade de São Paulo (USP)
25 de abril de 2013
1 / 50
Métodos para Rendering de Superfície
Introdução
Sumário
1 Introdução
2 Programação OpenGL (Rendering)
3 OpenGL Shading LanguageProgramaçã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 LanguageProgramaçã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 desuperfície é usado para determinar a cor dos pixels
O modelo de iluminação pode ser usado de formas diferentes parade�nir 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 algoritmosde scan-line
As intensidades são calculadas nos vértices e interpoladas nasposiçõ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 amesma cor para todos seus pontos (�at surface rendering)
Emprega-se o modelo de iluminação para determinar a intensidadedas 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 de�ne resultados precisos seO polígono é uma face de um poliedro e não uma seção de umasuperfície curva
Todas as fontes de luz estão distantes o su�ciente da superfície deforma que N · L e a função de atenuação são constantes
A posição visão é distante o su�ciente do polígono de forma queV ·R (ou N ·H) é constante
I = ka Ia +∑n
l=1 Il[kd(N · L) + ks(N ·H)ns ]
Mesmo se alguma dessas condições for falsa, uma boa aproximaçãopode 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 asintensidades nos vértices por toda face do polígono de um objetoiluminado
Desenvolvido para aproximar superfícies curvas, amenizando astransiçõ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 seguinteprocedimento
1 Determina o vetor unitário normal médio em cada vértice do polígono2 Aplica o modelo de iluminação em cada vértice para obter as
intensidades3 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 dasnormais de todos os polígonos que compartilham esse vértice
NV =
∑nk=1 Nk
|∑n
k=1 Nk|
Usando essas normais o modelo de iluminação é então executadopara 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 asintensidades ao longo de scan-lines que intersectam a área projetadado polígono
As intensidades das intersecções das scan-lines com as arestas dospolígonos são calculadas interpolando linearmente as intensidadesdos 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 considerandosomente o deslocamento vertical da scan-line
I4 =y4 − y2y1 − y2
I1 +y1 − y4y1 − y2
I2
A intensidade em 5 pode ser obtida da mesma forma interpolandoverticalmente 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 emqualquer ponto p da scan-line são obtidas interpolando na horizontal
Ip =x5 − xp
x5 − x4I4 +
xp − x4
x5 − x4I5
Esse método é conhecido como interpolação bilinear e é executadopara 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 temalguns problemas
Brilhos na superfície podem apresentar formatos estranhosIntensidades claras ou escuras podem parecer �riscadas� (mach
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ãopercebidas próximo das fronteiras entre duas regiões de diferentesgradientes 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 Phongsurface rendering
Ao invés de interpolar valores de intensidades, normais sãointerpoladas
Cálculos mais precisos de intensidadesBrilhos mais realísticos nas superfíciesReduçã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 procedimento1 Determina o vetor unitário normal médio em cada vértice do polígono2 Interpola linearmente as normais dos vértices sobre a área projetada
do polígono3 Aplica o modelo de iluminação nas posições ao longo da scan-line
para calcular as intensidades dos pixels usando as normaisinterpoladas
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 dainterpolação das intensidades do método de Gouraud
Por exemplo, o vetor normal N é verticalmente interpolado a partirdas normais nos vértices 1 e 2 fazendo
N =y − y2y1 − y2
N1 +y1 − y
y1 − y2N2
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 LanguageProgramaçã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) deintensidade constante (�at); (2) e o modelo de Gouraud(smoothing)
Não existe suporte para o modelo de Phong
Para de�nir o método de rendering usamos
1 gl.glShadeModel(rendering_method);
Onde rendering_method pode ser GL.GL_FLAT eGL.GL_SMOOTH
20 / 50
Métodos para Rendering de Superfície
Programação OpenGL (Rendering)
Funções de Rendering de Superfície
Para se de�nir a normal usamos
1 gl.glNormal3*(Nx, Ny, Nz);
Com o su�xo dependendo do tipo de parâmetro b, s, i, f e d, oucom 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 iguala (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 de�nimos apenas umanormal para cada polígono
1 gl.glNormal3fv(normal_vector);2
3 gl.glBegin(GL.GL_TRIANGLES);4 gl.glVertex3fv(vertex1);5 gl.glVertex3fv(vertex2);6 gl.glVertex3fv(vertex3);7 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 de�nida paracada vértice
1 gl.glBegin(GL_TRIANGLES);2 gl.glNormal3fv(normal_vector1);3 gl.glVertex3fv(vertex1);4
5 gl.glNormal3fv(normal_vector2);6 gl.glVertex3fv(vertex2);7
8 gl.glNormal3fv(normal_vector3);9 gl.glVertex3fv(vertex3);
10 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 especi�cados comtamanho unitário, fazendo isso reduzimos o custo computacional
É possível solicitar a OpenGL normalizar qualquer vetor normal quenão seja unitário chamando
1 gl.glEnable(GL.GL_NORMALIZE);
Esse comando renormaliza todas as normais às superfícies incluindoas que foram modi�cadas por transformações geométricas de escalae 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
3 /** calcula o produto vetorial. */4 private Point3D crossproduct(Point3D a, Point3D b) {5 Point3D prod = new Point3D(a.y * b.z - a.z * b.y,6 a.z * b.x - a.x * b.z,7 a.x * b.y - b.x * a.y);8 return prod;9 }
10
11 /** normaliza um vetor de entrada. */12 private Point3D normalize(Point3D p) {13 float norm = (float) Math.sqrt(p.x * p.x + p.y * p.y + p.z * p.z);14 return new Point3D(p.x / norm, p.y / norm, p.z / norm);15 }16
17 /** Representa uma Célula com posição 3D e uma normal. */18 class Cell {19 public Point3D point;20 public Point3D normal;21 }22
23 /** Representa um ponto ou vetor 3D (x,y,z). */24 class Point3D {25 public Point3D(float x, float y, float z) {26 this.x = x; this.y = y; this.z = z;27 }28 public float x;29 public float y;30 public float z;31 }32 }
25 / 50
Métodos para Rendering de Superfície
Programação OpenGL (Rendering)
Rendering de Superfície
1 public class Rendering implements GLEventListener {2 ...3
4 /** cria uma matriz formando uma gaussiana. As primeiras e últimas5 linhas e colunas são criadas apenas como forma para facilitar6 o cálculo das normais em cada ponto. Essas não devem ser usadas7 para o desenho da gaussiana. */8 private Cell[][] createMatrix(int size) {9 Cell[][] matrix = new Cell[size + 2][size + 2];
10
11 for (int i = 0; i < size + 2; i++) {12 for (int j = 0; j < size + 2; j++) {13 matrix[i][j] = new Cell();14 float x = (4.0f * j) / ((float) size + 2) - 2.0f;15 float z = (4.0f * i) / ((float) size + 2) - 2.0f;16 float y = (float) (Math.exp(-x * x) * Math.exp(-z * z));17 matrix[i][j].point = new Point3D(x, y, z);18 }19 }20
21 return matrix;22 }23 }
26 / 50
Métodos para Rendering de Superfície
Programação OpenGL (Rendering)
Rendering de Superfície
1 public class Rendering implements GLEventListener {2 ...3
4 /** calcula as normais em cada ponto. As primeiras e últimas linhas5 e colunas são ignoradas. Seja V1 o ponto para o qual será calculada6 a normal, V2 o ponto na mesma linha e próxima coluna e V3 o ponto7 na próxima linha e mesma coluna. A normal é computada como o8 produto vetorial do vetores de V1 para V2 e de V3 para V1. */9 private void calculateNormal(Cell[][] matrix) {
10 for (int i = 1; i < matrix.length - 1; i++) {11 for (int j = 1; j < matrix[0].length - 1; j++) {12 Point3D v1 = matrix[i][j].point;13 Point3D v2 = matrix[i][j + 1].point;14 Point3D v3 = matrix[i + 1][j].point;15 Point3D vec1 = new Point3D(v2.x-v1.x, v2.y-v1.y, v2.z-v1.z);16 Point3D vec2 = new Point3D(v1.x-v3.x, v1.y-v3.y, v1.z-v3.z);17 matrix[i][j].normal = normalize(crossproduct(vec1, vec2));18 }19 }20 }21 }
27 / 50
Métodos para Rendering de Superfície
Programação OpenGL (Rendering)
Rendering de Superfície
1 public class Rendering implements GLEventListener {2 ...3
4 public static void main(String[] args) {5 //acelera o rendering6 GLCapabilities caps = new GLCapabilities();7 caps.setDoubleBuffered(true);8 caps.setHardwareAccelerated(true);9
10 //cria o painel e adiciona um ouvinte GLEventListener11 GLCanvas canvas = new GLCanvas(caps);12 canvas.addGLEventListener(new Rendering());13
14 //cria uma janela e adiciona o painel15 JFrame frame = new JFrame("Aplicação JOGL Simples");16 frame.getContentPane().add(canvas);17 frame.setSize(800, 800);18 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);19
20 //inicializa o sistema e chama display() a 60 fps21 Animator animator = new FPSAnimator(canvas, 60);22 frame.setLocationRelativeTo(null);23 frame.setVisible(true);24 animator.start();25 }26
27 ...28 }
28 / 50
Métodos para Rendering de Superfície
Programação OpenGL (Rendering)
Rendering de Superfície
1 public class Rendering implements GLEventListener {2 ...3
4 public void init(GLAutoDrawable drawable) {5 GL gl = drawable.getGL();6 GLU glu = new GLU();7
8 gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); //de�ne a cor de fundo9 gl.glEnable(GL.GL_DEPTH_TEST); //habilita o teste de profundidade
10
11 gl.glMatrixMode(GL.GL_MODELVIEW); //de�ne que a matrix é a model view12 gl.glLoadIdentity(); //carrega a matrix de identidade13 glu.gluLookAt(1.5, 0.75, 1.0, //posição da câmera14 0.0, 0.0, 0.0, //para onde a câmera aponta15 0.0, 1.0, 0.0); //vetor view−up16
17 gl.glMatrixMode(GL.GL_PROJECTION); //de�ne que a matrix é a de projeção18 gl.glLoadIdentity(); //carrega a matrix de identidade19 gl.glOrtho(-2.5, 2.5, -2.5, 2.5, -4.5, 4.5);20
21 lighting(drawable); //de�ninido os parâmetros de iluminação22 }23 }
29 / 50
Métodos para Rendering de Superfície
Programação OpenGL (Rendering)
Rendering de Superfície
1 public class Rendering implements GLEventListener {2 ...3
4 private void lighting(GLAutoDrawable drawable) {5 GL gl = drawable.getGL();6
7 //de�ne a posição e parâmetros da luz 08 float position[] = {1.0f, 1.5f, -0.5f, 1.0f};9 float white[] = {1.0f, 1.0f, 1.0f, 1.0f};
10 float black[] = {0.0f, 0.0f, 0.0f, 1.0f};11 gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, position, 0);12 gl.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, black, 0);13 gl.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, white, 0);14 gl.glLightfv(GL.GL_LIGHT0, GL.GL_SPECULAR, white, 0);15
16 //ativa a iluminação17 gl.glEnable(GL.GL_LIGHTING);18 gl.glEnable(GL.GL_LIGHT0);19 }20 }
30 / 50
Métodos para Rendering de Superfície
Programação OpenGL (Rendering)
Rendering de Superfície
1 public class Rendering implements GLEventListener {2 ...3
4 public void display(GLAutoDrawable drawable) {5 GL gl = drawable.getGL();6 gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);7
8 //de�ne as propriedades de re�exão da superfície9 float diffuse[] = {0.5f, 0.5f, 0.8f, 1.0f};
10 float specular[] = {1.0f, 1.0f, 1.0f, 1.0f};11 float shininess = 100.0f;12 gl.glMaterialfv(GL.GL_FRONT, GL.GL_DIFFUSE, diffuse, 0);13 gl.glMaterialfv(GL.GL_FRONT, GL.GL_SPECULAR, specular, 0);14 gl.glMaterialf(GL.GL_FRONT, GL.GL_SHININESS, shininess);15
16 //cria matrix com as células para desenho17 Cell[][] m = createMatrix(40);18 calculateNormal(m);19
20 //desenha a superfície21 for (int i = 1; i < m.length - 1; i++) {22 for (int j = 1; j < m.length - 1; j++) {23 gl.glNormal3f(m[i][j].n.x, m[i][j].n.y, m[i][j].n.z);24
25 gl.glBegin(GL.GL_TRIANGLE_STRIP);26 gl.glVertex3f(m[i+1][j].p.x, m[i+1][j].p.y, m[i+1][j].p.z);27 gl.glVertex3f(m[i+1][j+1].p.x, m[i+1][j+1].p.y, m[i+1][j+1].p.z);28 gl.glVertex3f(m[i][j].p.x, m[i][j].p.y, m[i][j].p.z);29 gl.glVertex3f(m[i][j+1].p.x, m[i][j+1].p.y, m[i][j+1].p.z);30 gl.glEnd();31 }32 }33
34 gl.glFlush(); //força o desenho das primitivas35 }36 }
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 public class Rendering implements GLEventListener {2 ...3 public void display(GLAutoDrawable drawable) {4 ...5 for (int i = 1; i < m.length - 1; i++) {6 for (int j = 1; j < m.length - 1; j++) {7 gl.glBegin(GL.GL_TRIANGLE_STRIP);8 if (m[i+1][j].n != null) {9 gl.glNormal3f(m[i+1][j].n.x, m[i+1][j].n.y, m[i+1][j].n.z);
10 }11 gl.glVertex3f(m[i+1][j].p.x, m[i+1][j].p.y, m[i+1][j].p.z);12
13 if (m[i+1][j+1].n != null) {14 gl.glNormal3f(m[i+1][j+1].n.x, m[i+1][j+1].n.y, m[i+1][j+1].n.z);15 }16 gl.glVertex3f(m[i+1][j+1].p.x, m[i+1][j+1].p.y, m[i+1][j+1].p.z);17
18 if (m[i][j].n != null) {19 gl.glNormal3f(m[i][j].n.x, m[i][j].n.y, m[i][j].n.z);20 }21 gl.glVertex3f(m[i][j].p.x, m[i][j].p.y, m[i][j].p.z);22
23 if (m[i][j+1].n != null) {24 gl.glNormal3f(m[i][j+1].n.x, m[i][j+1].n.y, m[i][j+1].n.z);25 }26 gl.glVertex3f(m[i][j+1].p.x, m[i][j+1].p.y, m[i][j+1].p.z);27 gl.glEnd();28 }29 }30 ...31 }32 }
33 / 50
Métodos para Rendering de Superfície
Programação OpenGL (Rendering)
Rendering de Superfície
1 public class Rendering implements GLEventListener {2 ...3 private void lighting(GLAutoDrawable drawable) {4 GL gl = drawable.getGL();5
6 //de�ne a posição e parâmetros da luz 07 float position[] = {1.0f, 1.5f, -0.5f, 1.0f};8 float white[] = {1.0f, 1.0f, 1.0f, 1.0f};9 float black[] = {0.0f, 0.0f, 0.0f, 1.0f};
10
11 gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, position, 0);12 gl.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, black, 0);13 gl.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, white, 0);14 gl.glLightfv(GL.GL_LIGHT0, GL.GL_SPECULAR, white, 0);15
16 //ativa a iluminação17 gl.glEnable(GL.GL_LIGHTING);18 gl.glEnable(GL.GL_LIGHT0);19
20 //ativa rendering 'smooth'21 gl.glShadeModel(GL.GL_SMOOTH); //ou GL.GL_FLAT para '�at';22 }23 }
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ínuaMatriz com 40× 40 faces: a re�exão especular é ruim
35 / 50
Métodos para Rendering de Superfície
Programação OpenGL (Rendering)
Rendering de Superfície
Melhorando a re�exão especular: matriz com 400× 400 facesNunca 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 LanguageProgramação OpenGL
37 / 50
Métodos para Rendering de Superfície
OpenGL Shading Language
OpenGL Shading Language
OpenGL Shading Language (GLSL) é uma linguagem de altonível que permite aos desenvolvedores maior controle sobre opipeline grá�co sem precisar se preocupar com aspectos especí�cosde hardware
Incluída na versão 2.0 de OpenGLSimilar a linguagem C, suportando laços, comandos de decisão, etc.
Alguns benefícios sãoCompatibilidade entre diferentes plataformas, incluindo linux, MacOS e WindowsPossibilidade de escrever shaders que podem ser usados em sistemasgrá�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 aplaca grá�ca para compilação diretamente de dentro de umaaplicação OpenGL
Podem ser criados �on the �y� de dentro de uma aplicação ou lidos apartir 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 damesma forma do pipeline original
1 void main(void)2 {3 gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;4 }
E colore os fragmentos de verde
1 void main(void)2 {3 gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);4 }
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érticespara o fragment shader
A posição e a normal são passadas para o fragment shader, e sãoautomaticamente interpoladas
1 /* vertex shader for per−fragment Phong shading */2
3 varying vec3 normal;4 varying vec4 position;5
6 void main(void)7 {8 normal = gl_NormalMatrix * gl_Normal;9 position = gl_ModelViewMatrix * gl_Vertex;
10 gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; //ou = ftransform();11 }
gl_NormalMatrix deve ser usada no lugar da gl_ModelViewMatrixpara garantir que as normais não sejam afetadas por escalas nãouniformes
41 / 50
Métodos para Rendering de Superfície
OpenGL Shading Language
Fragment Shader (Phong Shading)
1 /* fragment shader for per−fragment Phong shading */2
3 varying vec3 normal;4 varying vec4 position;5
6 void main()7 {8 vec3 normv = normalize(normal); //normal9 vec3 lightv = normalize(gl_LightSource[0].position.xyz - position.xyz); //luz
10 vec3 viewv = normalize(-position.xyz); //direção de visão11 vec3 halfv = normalize(lightv + viewv); //vetor médio12
13 //calculando a componente ambiente14 vec4 ambient = gl_FrontMaterial.ambient * gl_LightSource[0].ambient;15
16 //calculando a componente difusa17 float diff = max(0.0, dot(lightv, normv));18 vec4 diffuse = diff * gl_FrontMaterial.diffuse * gl_LightSource[0].diffuse;19
20 //calculando a componente especular21 float spec = max(0.0, pow(dot(halfv, normv), gl_FrontMaterial.shininess));22 vec4 specular = spec * gl_FrontMaterial.specular * gl_LightSource[0].specular;23
24 //calculando a cor �nal25 gl_FragColor = ambient + diffuse + specular;26 }
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) econsiderando os fragmentos (a direita).
Para maiores informações consultehttp://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 LanguageProgramação OpenGL
44 / 50
Métodos para Rendering de Superfície
OpenGL Shading Language
Programação OpenGL
Usando Shaders
1 public class RenderingSmoothGLSL implements GLEventListener {2 ...3
4 public void init(GLAutoDrawable drawable) {5 //ativa modo debug da jogl6 drawable.setGL(new DebugGL(drawable.getGL()));7
8 GL gl = drawable.getGL();9 GLU glu = new GLU();
10
11 gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); //de�ne a cor de fundo12 gl.glEnable(GL.GL_DEPTH_TEST); //habilita o teste de profundidade13
14 gl.glMatrixMode(GL.GL_MODELVIEW); //de�ne que a matrix é a model view15 gl.glLoadIdentity(); //carrega a matrix de identidade16 glu.gluLookAt(1.5, 0.75, 1.0, //posição da câmera17 0.0, 0.0, 0.0, //para onde a câmera aponta18 0.0, 1.0, 0.0); //vetor view−up19
20 gl.glMatrixMode(GL.GL_PROJECTION); //de�ne que a matrix é a de projeção21 gl.glLoadIdentity(); //carrega a matrix de identidade22 gl.glOrtho(-2.5, 2.5, -2.5, 2.5, -4.5, 4.5);23
24 lighting(drawable); //de�ninido os parâmetros de iluminação25 shader(drawable); //ativando o shader26 }27 }
45 / 50
Métodos para Rendering de Superfície
OpenGL Shading Language
Programação OpenGL
Carregando Shaders
1 public class RenderingSmoothGLSL implements GLEventListener {2 ...3
4 private void shader(GLAutoDrawable drawable) {5 GL gl = drawable.getGL();6
7 //cria o fragment e vertex shaders8 int v = gl.glCreateShader(GL.GL_VERTEX_SHADER);9 int f = gl.glCreateShader(GL.GL_FRAGMENT_SHADER);
10
11 //carrega e compila o vertex shader12 String[] vsrc = readShader("/shaders/phong_vertex_shader.txt");13 gl.glShaderSource(v, 1, vsrc, null, 0);14 gl.glCompileShader(v);15
16 //carrega e compila o fragment shader17 String[] fsrc = readShader("/shaders/phong_fragment_shader.txt");18 gl.glShaderSource(f, 1, fsrc, null, 0);19 gl.glCompileShader(f);20
21 //anexa, valida e usa os shaders22 int shaderprogram = gl.glCreateProgram();23 gl.glAttachShader(shaderprogram, v);24 gl.glAttachShader(shaderprogram, f);25 gl.glLinkProgram(shaderprogram);26 gl.glValidateProgram(shaderprogram);27 gl.glUseProgram(shaderprogram);28 }29 }
46 / 50
Métodos para Rendering de Superfície
OpenGL Shading Language
Programação OpenGL
Lendo Arquivo de Shading
1 public class RenderingSmoothGLSL implements GLEventListener {2 ...3
4 /** Lê um arquivo de shader no formato texto. */5 private String[] readShader(String shadername) {6 try {7 InputStream isv = getClass().getResourceAsStream(shadername);8 BufferedReader brv = new BufferedReader(new InputStreamReader(isv));9 StringBuilder buffer = new StringBuilder();
10 String line;11 while ((line = brv.readLine()) != null) {12 buffer.append(line).append("\r\n");13 }14 brv.close();15 isv.close();16 return new String[]{buffer.toString()};17 } catch (IOException ex) {18 Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, ex);19 }20
21 return null;22 }23 }
47 / 50
Métodos para Rendering de Superfície
OpenGL Shading Language
Programação OpenGL
Phong Shader GLSL
Melhorando a re�exã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çãode um vértice
1 /* vertex shader */2 varying vec3 vertex_color;3
4 void main(void)5 {6 gl_Position = ftransform();7 vertex_color = gl_Vertex.xyz; //cor será a posição do vértice8 }
1 /* fragment shader */2 varying vec3 vertex_color;3
4 void main(void)5 {6 gl_FragColor = vec4(vertex_color, 1.0);7 }
49 / 50
Métodos para Rendering de Superfície
OpenGL Shading Language
Programação OpenGL
Resultado
Isso também mostra que vertex_color é interpolado quandopassado do vertex shader para o fragment shader
50 / 50
Top Related