1.02k likes | 1.19k Views
Programação em GPUs (OpenGL/GLSL CUDA). Yalmar Ponce. Roteiro. Introdução Tipos de dados, Estruturas, Funções Shaders Exemplos Luz (Direcional, Pontual, Spot) Efeitos (Parede de Tijolos, Madeira, Desenho animado) Modificando Geometria Textura e Multitextura Shader de Geometria Exemplos
E N D
Programação em GPUs(OpenGL/GLSLCUDA) Yalmar Ponce
Roteiro • Introdução • Tipos de dados, Estruturas, Funções • Shaders • Exemplos • Luz (Direcional, Pontual, Spot) • Efeitos (Parede de Tijolos, Madeira, Desenho animado) • Modificando Geometria • Textura e Multitextura • Shader de Geometria • Exemplos • FBO • CUDA • Projeto Final • Mapeamento de Sombra (Shadow mapping) 15 de setembro de 2014
Introdução • Aplicações • Renderização em tempo real • Efeitos • Jogos 15 de setembro de 2014
Introdução • GPUs são rápidas... • 3.0 GHz Intel Core Extreme • 96 GFLOPS – pico • Memory Bandwidth: 13 GB/s • Preço: 800~ dólares • NVIDIA GeForce GTX 280: • 930 GFLOPS • Memory Bandwidth: 141 GB/s • Preço: 499 dólares 15 de setembro de 2014
Introdução • Versão simplificada da pipeline CPU GPU Graphics State Xformed, Lit Vertices (2D) Screenspace triangles (2D) Fragments (pre-pixels) Final Pixels (Color, Depth) Application Transform& Light AssemblePrimitives Rasterize Shade Vertices (3D) VideoMemory(Textures) Render-to-texture 15 de setembro de 2014
Introdução • Processador de Vértices Programável CPU GPU Graphics State VertexProcessor FragmentProcessor Xformed, Lit Vertices (2D) Screenspace triangles (2D) Fragments (pre-pixels) Final Pixels (Color, Depth) Application Transform& Light AssemblePrimitives Rasterize Shade Vertices (3D) VideoMemory(Textures) Render-to-texture • Processador de fragmentos Programável 15 de setembro de 2014
Introdução • Geração de geometria programável CPU GPU Graphics State GeometryProcessor Xformed, Lit Vertices (2D) Screenspace triangles (2D) Fragments (pre-pixels) Final Pixels (Color, Depth) Application VertexProcessor AssemblePrimitives Rasterize FragmentProcessor Vertices (3D) VideoMemory(Textures) Render-to-texture • Acesso a memória mais flexível 15 de setembro de 2014
Shaders • Shaders são programas que executam em determinadas etapas do pipeline • Não são aplicações stand-alone • Necessitam deuma aplicação que utilize um API (OpenGL ou Direct3D) 15 de setembro de 2014
Shaders • No caso: • Vertex shader – Vertex Processor • Fragment shader – Fragment Processor • Geometry shader – Geometry Processor 15 de setembro de 2014
Shaders • Vertex Processor • Transforma do espaço de mundo para o espaço de tela • Calcula iluminação per-vertex 15 de setembro de 2014
Shaders • Geometry Processor • Como os vértices se conectam para formar a geometria • Operações por primitiva 15 de setembro de 2014
Shaders • Fragment Processor • Calcula a cor de cada pixel • Obtém cores de texturas 15 de setembro de 2014
Shaders • Hoje 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 15 de setembro de 2014
Shaders • Temos algumas ferramentas que servem tanto para criação e edição de shaders: • NVIDIA FX Composer 2.5 • RenderMonkey ATI 15 de setembro de 2014
Shaders 15 de setembro de 2014
Shaders 15 de setembro de 2014
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 15 de setembro de 2014
Tipos de dados • Texturas • Sampler1D, Sampler2D, Sampler3D - texturas 1D, 2D e 3D • SamplerCube – Cube map textures • Sampler1Dshadow, Sampler2DShadow – mapa de profundidade 1D e 2D 15 de setembro de 2014
Input/Output • Existem 3 tipos de input em um shader: • Uniforms • Varyings • Attributes 15 de setembro de 2014
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 • Usado para passar dados do vertex shader para o fragment shader ou geometry shader 15 de setembro de 2014
Input/Output • Varyings • São read-only no fragment e geometry shader mas read/write no vertex shader • Deve-se declarar a mesma varying em todos os programas • Attributes • Estão presentes apenas nos Vertex shaders • São valores (possivelmente diferentes) associados a cada vértice 15 de setembro de 2014
Input/Output • Attributes • Ex: Posição do vértice ou normais • São apenas read-only 15 de setembro de 2014
Input/Output • Exemplos de Attributes 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 15 de setembro de 2014
Input/Output • Exemplos de Uniforms • gl_ModelViewMatrix • gl_ModelViewProjectionMatrix • gl_NormalMatrix 15 de setembro de 2014
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 15 de setembro de 2014
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 15 de setembro de 2014
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; 15 de setembro de 2014
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; 15 de setembro de 2014
Funções e Estruturas de Controle • Similar a linguagem C • Suporta estruturas de repetição e decisão • If/else • For • Do/while • Break • Continue 15 de setembro de 2014
Funções e Estruturas de Controle • Possui funções como: • Seno (sin) • Cosseno (cos) • Tangente (tan) • Potencia (pow) • Logaritmo (log) • Logaritmo (log2) • Raiz (sqrt) 15 de setembro de 2014
GLSL-Setup • Antes de criar os shaders é necessário implementar uma função (no caso do GLSL) para ler e enviar os shaders para o hardware 15 de setembro de 2014
GLSL-Setup void setShaders(){ char *vs = NULL,*fs = NULL,*fs2 = NULL; 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); free(vs);free(fs); glCompileShader(v); glCompileShader(f); p = glCreateProgram(); glAttachShader(p,v); glAttachShader(p,f); glLinkProgram(p); glUseProgram(p); } 15 de setembro de 2014
Hello World • O código shader mais simples • Vertex Shader void main() { gl_Position = ftransform(); } • Fragment Shader void main(){ gl_FragColor = vec4(0.4,0.4,0.8,1.0); } 15 de setembro de 2014
Modificando a geometria • 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; } 15 de setembro de 2014
Modificando a geometria II void main(void){ vec4 v = vec4(gl_Vertex); v.z = sin(5.0*v.x )*0.25; gl_Position = gl_ModelViewProjectionMatrix * v; } 15 de setembro de 2014
Animação • É necessário manter a passagem do tempo nos frames • No vertex shader não é possível guardar valores • a variável é definida na aplicação OpenGL 15 de setembro de 2014
O shader recebe o valor time numa 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; } A função de render: void renderScene(void){ ... glUniform1fARB(loc, time); glutSolidTeapot(1); time+=0.01; glutSwapBuffers(); } Animação 15 de setembro de 2014
Manipulação de Texturas • GLSL permite 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_MultiTexCoord[0..8] 15 de setembro de 2014
Manipulação de Texturas • Precisa calcular a coordenada de textura • Armazenar numa variável varying gl_TexCoord[i] onde i é a unidade de textura utilizada • gl_TexCoord[0] = gl_MultiTexCoord0; • 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(); } 15 de setembro de 2014
Manipulação de Texturas • 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; 15 de setembro de 2014
Manipulação de Texturas • 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) 15 de setembro de 2014
Manipulação de Texturas • Vertex Shader void main(){ gl_TexCoord[0] = gl_MultiTexCoord0; gl_Position = ftransform(); } • Fragment shader uniform sampler2D tex; void main() { vec4 color = texture2D(tex,gl_TexCoord[0].st); gl_FragColor = color; } 15 de setembro de 2014
Múltiplas Texturas • Definir as texturas 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); • Na aplicação OpenGL, é necessário habilitar as texturas que serão usadas. glActivateTexture(GL_TEXTUREi) onde i = 0..8 15 de setembro de 2014
Múltiplas Texturas • Multi Texturing glEnable (GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texid0); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, texid1); ... glBegin(GLenum Mode); . . . glEnd(); glDisable (GL_TEXTURE_2D); 15 de setembro de 2014
GLSL e Multi-Textura • Cada textura que será usada no programa GLSL deve ser associada a uma textura na aplicação OpenGL. • Vertex/Fragment Shader uniform sampler2D textureName1, textureName2; • Programa OpenGL (inicialiazação) GLuint tex1, tex2; GLint texLoc1, texLoc2; texLoc1 = glGetUniformLocation(programObj, "textureName1"); texLoc2 = glGetUniformLocation(programObj, "textureName2"); glUniform1i(texLoc1, 0); // a primeira deve ser 0 glUniform1i(texLoc2, 1); • Programa OpenGL ( ativar multitextura) glEnable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0); // habilita para uso tex1 glActiveTexture(GL_TEXTURE1); // habilita para uso tex2 drawQuad(); • Note que a textura atribuída com a função glUniform1i(texLoc1, i) i = 0, 1, ... deve ser ativada com glActiveTexture(GL_TEXTUREi) antes de usar um programa GLSL 15 de setembro de 2014
Textura 3D glGenTextures(1, &TexName);glBindTexture(GL_TEXTURE_3D, TexName); glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_REPEAT); glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, TexSize, TexSize, TexSize, 0, GL_RGBA,GL_UNSIGNED_BYTE, data); 15 de setembro de 2014
Efeito tijolo • Vertex Shader • http://www.3dshaders.com/shaders2ndEd/CH06-brick.vert.txt • Fragment Shader • http://www.3dshaders.com/shaders2ndEd/CH06-brick.frag.txt 15 de setembro de 2014
Effeito madeira • Vertex Shader • http://www.3dshaders.com/shaders2ndEd/CH15-wood.vert.txt • Fragment Shader • http://www.3dshaders.com/shaders2ndEd/CH15-wood.frag.txt 15 de setembro de 2014