Shaders
Bruno José Dembogurski
Instituto de Computação - UFF
Agenda
Introdução
Shaders
Tipos de dados
Input/Output
Funções e Estruturas de controle
Exemplos e Códigos
Conclusões
Introdução
Poder da computação gráfica hoje
GPGPU
Por que?
Introdução
Crescimento absurdo no poder de
processamento
O hardware é relativamente barato
Flexibilidade
Como?
Introdução
JOGOS !
Industria exige cada vez mais poder
de processamento
Gera bilhões de dólares por ano
Incentiva cada vez mais o
desenvolvimento do hardware
E acaba por baixar o custo
Introdução
Desde 2000 o poder aplicado ao
processamento de vértices e
fragmentos tem crescido a uma taxa
absurda
Introdução
GPUs são rápidas...
3.0 GHz Intel Core2 Duo (WoodCrest
Xeon 5160)
Poder: 48 GFLOPS – pico
Memory Bandwidth: 21GB/s – pico
Preço: 874 dólares
NVIDIA GeForce 8800GTX:
Poder: 330 GFLOPS
Memory Bandwidth: 55.2 GB/s
Preço: 599 dólares
Introdução
“NVIDIA Tesla Computing Solutions
now with the world's first teraflop
parallel processor “
Introdução
Introdução
Graphics State
GPU
Shade
Final Pixels (Color, Depth)
Rasterize
Fragments (pre-pixels)
Assemble
Primitives
Screenspace triangles (2D)
Transform
& Light
Xformed, Lit Vertices (2D)
CPU
Vertices (3D)
Application
Video
Memory
(Textures)
Render-to-texture
Versão simplificada da pipeline
Introdução
Graphics State
Processador de
Vértices
Programável
GPU
Fragment
Shade
Processor
Final Pixels (Color, Depth)
CPU
Rasterize
Fragments (pre-pixels)
Assemble
Primitives
Screenspace triangles (2D)
Vertex
Transform
Processor
& Light
Xformed, Lit Vertices (2D)
Vertices (3D)
Application
Video
Memory
(Textures)
Render-to-texture
Processador de
fragmentos
Programável
Introdução
Graphics State
GPU
Fragment
Processor
Final Pixels (Color, Depth)
Geração de
geometria
programável
Rasterize
Fragments (pre-pixels)
CPU
Geometry
Assemble
Processor
Primitives
Screenspace triangles (2D)
Vertex
Processor
Xformed, Lit Vertices (2D)
Vertices (3D)
Application
Video
Memory
(Textures)
Render-to-texture
Acesso a
memória mais
flexivel
Shaders
Shaders são programas que
executam em determinadas etapas
da pipeline
Não são aplicações stand-alone
Necessitam de uma aplicação que
utilize um API (OpenGL ou Direct3D)
Shaders
No caso:
Vertex shader – Vertex Processor
Fragment shader – Fragment Processor
Geometry shader – Geometry Processor
Shaders
Vertex Processor
Transforma do espaço de mundo para o
espaço de tela
Calcula iluminação per-vertex
Shaders
Geometry Processor
Como os vértices se conectam para
formar a geometria
Operações por primitiva
Shaders
Fragment Processor
Calcula a cor de cada pixel
Obtém cores de texturas
Shaders
Hoje temos que a programação de
shaders é feita em linguagens de alto
nível
No estilo de c/c++
As principais que temos hoje:
GLSL – OpenGL Shader Language
HLSL – High Level Shader Language
Cg – C for Graphics
Shaders
Temos algumas ferramentas que
servem tanto para criação e edição de
shaders:
NVIDIA FX Composer 2.5
RenderMonkey ATI
Shaders
Shaders
Shaders
Tipos de dados
Estruturas bem intuitivas
Vetores:
vec2, vec3 e vec4 – floating point
ivec2, ivec3 e ivec4 – interger
bvec2, bvec3 e bvec4 – boolean
Matrizes
mat2, mat3 e mat4 – floating point
Tipos de dados
Texturas
Sampler1D, Sampler2D, Sampler3D texturas 1D, 2D e 3D
SamplerCube – Cube map textures
Sampler1Dshadow, Sampler2DShadow –
mapa de profundidade 1D e 2D
Input/Output
Existem 3 tipos de input em um
shader:
Uniforms
Varyings
Attributes
Input/Output
Uniforms
Não mudam durante o rendering
Ex: Posição da luz ou cor da luz
Esta presente em todos os tipos de
shader
Varyings
Usando para passar dados do vertex
shader para o fragment shader ou
geometry shader
Input/Output
Varyings
São read-only no fragment e geometry
shader mas read/write no vertex shader
Para usar deve-se declarar a mesma
varying em todos os programas
Attributes
Estão presentes apenas nos Vertex
shaders
São valores de input mudam em cada
vertice
Input/Output
Attributes
Ex: Posição do vértice ou normais
São apenas read-only
Input/Output
Exemplos de Input Attibutes no
vertex shader
gl_Vertex – vetor 4D, posição do vértice
gl_Normal – vetor 3D, Normal do vértice
gl_Color – vetor 4D, cor do vértice
gl_MultiTexCoordX – vetor 4D,
coordenada de textura na unit X
Existem vários outros atributos
Input/Output
Exemplos de Uniforms
gl_ModelViewMatrix
gl_ModelViewProjectionMatrix
gl_NormalMatrix
Input/Output
Exemplos de Varyings
gl_FrontColor - vetor 4D com a cor
frontal das primitivas
gl_BackColor – vetor 4D com a cor de
trás das primitivas
gl_TexCoord[N] – vetor 4D
representando a n-ésima coordenada de
textura
Input/Output
Exemplos de output:
gl_Position – vetor 4D representando a
posição final do vértice
gl_FragColor – vetor 4D representando a
cor final que será escrita no frame buffer
gl_FragDepth – float representando o
depth que será escrito do depth buffer
Input/Output
Também é possível definir attributes,
Uniforms e varyings
Ex: Passar um vetor tangente 3D por
todos os vértices da sua aplicação
É possível especificar o atributo
“tangente”
attribute vec3 tangente;
Input/Output
Alguns outros exemplos:
uniform sampler2D my_color_texture;
varying vec3 vertex_to_light_vector;
varying vec3 vertex_to_eye_vector;
attribute vec3 binormal;
Funções e Estruturas de Controle
Similar a linguagem C
Suporta estruturas de loop e decisão
If/else
For
Do/while
Break
Continue
Funções e Estruturas de Controle
Possui funções como:
Seno (sin)
Cosseno (cos)
Tangente (tan)
Potencia (pow)
Logaritmo (log)
Logaritmo (log2)
Raiz (sqrt)
Exemplos e Códigos
Antes de criar os shaders mesmo
temo que definir uma função (no caso
de GLSL) para carregar e enviar os
shaders para o hardware
Esta função já é bem difundida e fácil
de encontrar e manipular
Exemplos e Códigos
void setShaders()
free(vs);free(fs);
char *vs = NULL,*fs = NULL,*fs2 = NULL;
glCompileShader(v);
glCompileShader(f);
v = glCreateShader(GL_VERTEX_SHADER);
f = glCreateShader(GL_FRAGMENT_SHADER);
vs = textFileRead("minimal.vert");
fs = textFileRead("minimal.frag");
const char * vv = vs;
const char * ff = fs;
glShaderSource(v, 1, &vv,NULL);
glShaderSource(f, 1, &ff,NULL);
p = glCreateProgram();
glAttachShader(p,v);
glAttachShader(p,f);
glLinkProgram(p);
glUseProgram(p);
Exemplos e Códigos
O código shader mais simples (Estilo
Hello World)
Vertex Shader
void main()
{
gl_Position = ftransform();
}
Exemplos e Códigos
O código shader mais simples (Estilo
Hello World)
Fragment Shader
void main()
{
gl_FragColor = vec4(0.4,0.4,0.8,1.0);
}
Exemplos e Códigos
Resultado:
Exemplos e Códigos
Toon shading
Vertex shader
varying vec3 normal;
void main()
{
normal = gl_Normal; gl_Position = ftransform();
}
Exemplos e Códigos
Toon shading
Fragment shader
uniform vec3 lightDir;
varying vec3 normal;
void main()
{
float intensity;
vec4 color; intensity = dot(lightDir,normalize(normal));
if (intensity > 0.95)
color = vec4(1.0,0.5,0.5,1.0);
else if (intensity > 0.5)
color = vec4(0.6,0.3,0.3,1.0);
else if (intensity > 0.25)
color = vec4(0.4,0.2,0.2,1.0);
else
color = vec4(0.2,0.1,0.1,1.0);
}
gl_FragColor = color;
Exemplos e Códigos
Toon shading
Exemplos e Códigos
Mexendo na geometria
Shader achatar o modelo 3D, ou seja,
z=0
void main(void)
{
vec4 v = vec4(gl_Vertex);
v.z = 0.0;
gl_Position =
gl_ModelViewProjectionMatrix * v;
}
Exemplos e Códigos
Resultados
Exemplos e Códigos
Distorcendo ainda mais a geometria
void main(void)
{
vec4 v = vec4(gl_Vertex);
v.z = sin(5.0*v.x )*0.25;
gl_Position =
gl_ModelViewProjectionMatrix * v;
}
Exemplos e Códigos
Resultados
Exemplos e Códigos
É possível fazer uma animação com
os vértices
Para isso precisamos de uma variável
que mantenha a passagem do tempo
ou dos frames
Não temos como fazer isso no vertex
shader, logo temos que definir essa
variável na aplicação OpenGL
Exemplos e Códigos
E passar para o shader na forma de
uma variável Uniform
uniform float time;
void main(void)
{
vec4 v = vec4(gl_Vertex);
v.z = sin(5.0*v.x + time*0.01)*0.25;
gl_Position = gl_ModelViewProjectionMatrix * v;
}
Exemplos e Códigos
No caso a função de render ficaria:
void renderScene(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(0.0,0.0,5.0, 0.0,0.0,0.0, 0.0f,1.0f,0.0f);
glUniform1fARB(loc, time);
glutSolidTeapot(1);
time+=0.01;
}
glutSwapBuffers();
Exemplos e Códigos
Vídeo
Exemplos e Códigos
Texturing
GLSL tem que ter acesso as coordenadas
de textura por vértice
GLSL provê variáveis do tipo Attribute,
para cada unidade de textura (max 8)
attribute vec4 gl_MultiTexCoord0..8
Exemplos e Códigos
Texturing
Precisa calcular a coordenada de textura
Armazenar em uma variável varying
gl_TexCoord[i] onde i é a unidade de
textura utilizada
gl_TexCoord[0] = gl_MultiTexCoord0;
Exemplos e Códigos
Texturing
Um simples código para definir
coordenadas de textura para uma
textura utilizando a unit 0
Vertex Shader
void main()
{
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = ftransform();
}
Exemplos e Códigos
Texturing
gl_TexCoord é uma variável varying
Será utilizada no fragment shader para
acessar as coordenadas de textura
interpoladas
Para acessar os valores de textura temos
que declarar uma variável do tipo
uniform no fragment shader
Para uma textura 2D temos:
uniform sampler2D tex;
Exemplos e Códigos
Texturing
A função que nos retorna um textel é a
texture2D
Os valores retornados levam em
consideração todos as definições de
textura feitos no OpenGL (filtering,
mipmap, clamp, etc)
Exemplos e Códigos
Texturing
O fragment shader ficaria assim:
uniform sampler2D tex;
Void main()
{
vec4 color =
texture2D(tex,gl_TexCoord[0].st);
gl_FragColor = color;
}
Exemplos e Códigos
Texturing
São necessárias algumas inicializações na aplicação
para que o shader possa utilizar a textura
glActivateTexture(GL_TEXTUREi) onde i = 0..8
glGenTextures(1, &Textura);
glBindTexture(GL_TEXTURE_2D, Textura);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, level, format, Width, Height, 0,
GL_RGB,GL_UNSIGNED_BYTE, TexureInfo);
Exemplos e Códigos
Texturing
glEnable (GL_TEXTURE_2D);
glBegin(GLenum Mode);
.
.
.
glEnd();
glDisable (GL_TEXTURE_2D);
Exemplos e Códigos
Bump Mapping
Segue as mesmas idéias vistas
Vertex shader
uniform
uniform
uniform
uniform
uniform
mat4 view_matrix;
mat4 inv_view_matrix;
vec4 view_position;
vec4 light_position;
vec4 lightDir;
attribute vec3 rm_Tangent;
attribute vec3 rm_Binormal;
varying
varying
varying
varying
vec2
vec3
vec3
vec3
vTexCoord;
vLightVector;
vHalfAngle;
vNormal;
Exemplos e Códigos
Bump Mapping
void main( void )
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
vec4 eye_position = gl_ModelViewMatrix * gl_Vertex;
//**---------------------------------------------//** Passa as coordenadas de textura
//**---------------------------------------------vTexCoord = vec2(gl_MultiTexCoord0);
Exemplos e Códigos
Bump Mapping
//**---------------------------------------------//** Espaço tangente
//**---------------------------------------------vec3 tangent = vec3( rm_Tangent.x, rm_Tangent.y,
rm_Tangent.z);
vec3 normal = vec3( gl_Normal.x, gl_Normal.y,
gl_Normal.z);
vec3 binormal = vec3(rm_Binormal.x, rm_Binormal.y,
rm_Binormal.z);
Exemplos e Códigos
Bump Mapping
//**-------------------------------------------//** Calcula o vetor de iluminação no espaço de câmera,
//** transforma para o espaço tangente.
//**-------------------------------------------vec3 temp_light_position = vec3( vec4(light_position.x,
light_position.y, -light_position.z, light_position.w) *
inv_view_matrix);
vec3 temp_light_vector
gl_Vertex.xyz;
= temp_light_position.xyz -
vLightVector.x = dot( temp_light_vector, tangent );
vLightVector.y = dot( temp_light_vector, binormal );
vLightVector.z = dot( temp_light_vector, normal );
Exemplos e Códigos
Bump Mapping
//**------------------------------------------//**Mesma coisa para o view vector
//**------------------------------------------vec4 oglEyePos = eye_position;
oglEyePos.z = -oglEyePos.z;
vec3 temp_eye_position = vec3( oglEyePos * inv_view_matrix) ;
vec3 temp_view_vector = temp_eye_position - gl_Vertex.xyz;
vec3 temp_view_vector2;
temp_view_vector2.x = dot( temp_view_vector, tangent );
temp_view_vector2.y = dot( temp_view_vector, binormal );
temp_view_vector2.z = dot( temp_view_vector, normal );
Exemplos e Códigos
Bump Mapping
Fragment Shader
uniform float Kd;
uniform float Ka;
uniform vec4 diffuse;
uniform vec4 ambient;
uniform float Ks;
uniform vec4 specular;
uniform float
specular_power;
uniform float reflectance;
uniform float bumpiness;
uniform mat4 view_matrix;
uniform samplerCube
environment_map;
uniform sampler2D bump_map;
uniform sampler2D base_map;
varying vec2 vTexCoord;
varying vec3 vLightVector;
varying vec3 vHalfAngle;
Exemplos e Códigos
Bump Mapping
void main(void)
{
//**-----------------------------------------------------//** Pega os componente de cor e bump das texturas
//** baseadas nas coordenadas passadas
//**-----------------------------------------------------vec3 base = texture2D( base_map, vTexCoord ).xyz;
vec3 bump = texture2D( bump_map, vTexCoord ).xyz;
Exemplos e Códigos
Bump Mapping
//**---------------------------------------------------//** Normaliza os vetores passados pelo vertex shader
//**---------------------------------------------------vec3 normalized_light_vector = normalize( vLightVector );
vec3 normalized_half_angle = normalize( vHalfAngle );
//**---------------------------------------------------//** Suaviza os niveis de bump
//**---------------------------------------------------vec3 smooth = vec3(0.5, 0.5, 1.0);
bump = mix( smooth, bump, bumpiness );
bump = normalize( ( bump * 2.0 ) - 1.0 );
Exemplos e Códigos
Bump Mapping
//**-------------------------------------------------------//** Modelo de iluminação
//** NxL – Normal x vetor da luz
//** NxH – Normal x Half Vector
//**-------------------------------------------------------vec3 n_dot_l = vec3(dot( bump, normalized_light_vector ));
vec3 n_dot_h = vec3(dot( bump, normalized_half_angle ));
Exemplos e Códigos
Bump Mapping
//**-------------------------------------//** Calcula a cor resultante,
//** baseado no modelo de iluminação.
//** Ambient + Diffuse + Specular
//**-------------------------------------vec3 color0 = ( base * ambient.xyz * Ka ) +
( base * diffuse.xyz * Kd * max( vec3(0.0), n_dot_l ) ) +
( specular.xyz * Ks * pow( max( vec3(0.0), n_dot_h ),
vec3(specular_power) ));
Exemplos e Códigos
Bump Mapping
float color0_a = 1.0; //** Define o alfa
gl_FragColor = vec4(color0.xyz, color0_a); //** retorna a cor
Exemplos e Códigos
Bump Mapping
Conclusões
Apenas um introdução
Existem muitas outras utilidades para
os shaders
Muitos outros efeitos que podem ser
criados
Conclusões
Conclusões
Conclusões
Conclusões
Conclusões
Conclusões
Gears of War Video
GRID Video
Referencias
GLSL Quick Guide
NeHe Produtions
Wiki GLSL
LightHouse