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

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