180 likes | 346 Views
Renderização de cenas por traçado de raios na Placa Gráfica. Fabiano Segadaes Romeiro Sistemas Gráficos 3D IMPA. Sumário. Introdução Programação da Placa Gráfica Traçado de raios na esfera Renderização da Cena Resultados. Introdução.
E N D
Renderizaçãode cenas por traçado de raios na Placa Gráfica Fabiano Segadaes Romeiro Sistemas Gráficos 3D IMPA
Sumário • Introdução • Programação da Placa Gráfica • Traçado de raios na esfera • Renderização da Cena • Resultados
Introdução • Dada uma descrição de cena no formato apresentado na biblioteca do curso, realizar a sua renderização por traçado de raios na placa gráfica utilizando esferas como primitivas.
Introdução • Ponto fundamental: utilização da placa gráfica para realizar o traçado de raios. • Vantagens: o traçado de raios pode ser realizado de maneira bem mais rápida, sem ocupar a cpu.
Programação da Placa Gráfica • Utilização da linguagem Cg e do OpenGL juntamente com a interface CgGL para a implementação.
Programação da Placa Gráfica Localização do VP e do FP no pipeline da GPU • Vertex Program: chamado para cada vértice dos polígonos. • Fragment Program: chamado para cada pixel dos polígonos.
Programação da Placa Gráfica Localização do VP e do FP no pipeline da GPU
Traçado de raios da esfera • Estrutura de dados usada na implementação: GLfloat cube[6][4][3]; // Cubounitário centrado na origem de lado 2 // [-1,1]x[-1,1]x[-1,1] void draw_sphere(GLfloat s_center[3], GLfloat s_radius) { int x; // Set the variables on the VP and the FP cgGLSetParameter4f(center, s_center[0], s_center[1], s_center[2], 1.0f); cgGLSetParameter4f(center_fp, s_center[0], s_center[1], s_center[2], 1.0f); cgGLSetParameter4f(light, light_cg[0],light_cg[1], light_cg[2], 0.0f); // Pass a cube to the pipeline and let the VP/FP raytrace an inscribed sphere in it. float factor = s_radius; glBegin(GL_QUADS); for (x = 0; x < 6; x++) { glVertex3f(s_center[0] + factor*cube[x][0][0],s_center[1] + factor*cube[x][0][1],s_center[2] + factor*cube[x][0][2]); glVertex3f(s_center[0] + factor*cube[x][1][0],s_center[1] + factor*cube[x][1][1],s_center[2] + factor*cube[x][1][2]); glVertex3f(s_center[0] + factor*cube[x][2][0],s_center[1] + factor*cube[x][2][1],s_center[2] + factor*cube[x][2][2]); glVertex3f(s_center[0] + factor*cube[x][3][0],s_center[1] + factor*cube[x][3][1],s_center[2] + factor*cube[x][3][2]); } glEnd(); }
Traçado de raios da esfera Estruturas de dados • Parâmetros de entrada são setados no programa principal antes da renderização, através da API CgGL. struct appdata { float4 position : POSITION; float4 color : COLOR0; float4 light : COLOR1; float4 camera : TEXCOORD0; }; • A saída do Vertex Program e’ do tipo vfconn e e’ a entrada do Fragment Program. struct vfconn { float4 HPos : POSITION; float4 Col0 : COLOR0; float4 o : TEXCOORD1; float4 l : COLOR1; float4 v : TEXCOORD0; };
Traçado de raios da esfera Vertex Program vfconn vp_main(appdata IN, uniform float4x4 ModelViewProj, uniform float4 center, uniform float radius) { vfconn OUT; // Find o OUT.o.xyz = (IN.position.xyz - center.xyz); OUT.o.w = 1.0f; // Find l OUT.l.xyz = normalize(IN.light.xyz); OUT.l.w = 0.0f; // Find v OUT.v.xyz = normalize(IN.position.xyz - IN.camera.xyz); OUT.v.w = 0.0f; OUT.HPos = mul(ModelViewProj, IN.position); OUT.Col0.xyz = IN.color.xyz; return OUT; }
Traçado de raios da esfera Fragment Program void fp_main(in vfconn IN, out float4 color : COLOR0, out float depth : DEPTH, uniform float4x4 ModelViewProj, uniform float radius, uniform float4 center) { float3 norm_l = normalize(IN.l.xyz); float3 norm_v = normalize(IN.v.xyz); float oo = dot(IN.o.xyz,IN.o.xyz); float ov = dot(IN.o.xyz,norm_v); float delta = 4*(ov*ov - oo + radius*radius); if (delta <= 0.0f) { discard; } else { delta = sqrt(delta); float t = -ov - delta/2; ... float difuse = dot(normal,norm_l); float specular = dot(normal, halfvec); ... color.xyz = difuse*IN.Col0.xyz + specular*specularColor; …. (Calculo da profundidade) depth = (depto.z/depto.w); } }
Renderização da Cena • Leitura da cena no formato .scn da biblioteca s3d, suportando cenas com: • Esferas • Malhas poligonais (trilist), que são renderizadas usando esferas como primitivos: esferas são renderizadas nos vértices dos triângulos ou em toda a superfície do triangulo.
Renderização da Cena • Estruturas de dados: static Scene *s; Object *o; Poly *p; Color c; Light *l; GLfloat light_cg[3]; • Na inicializacao: s = scene_read(); .... glutDisplayFunc(Draw); .... glutMainLoop();
Renderização da Cena • Na rotina Draw: gluLookAt(s->view->center.x, s->view->center.y, s->view->center.z, s->view->center.x + s->view->normal.x, s->view->center.y + s->view->normal.y, s->view->center.z + s->view->normal.z, s->view->up.x, s->view->up.y, s->view->up.z); ........ l = s->lights; light_cg[0] = l->dir.x; light_cg[1] = l->dir.y; light_cg[2] = l->dir.z; ......... cgGLSetStateMatrixParameter(modelViewMatrix, CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY); cgGLSetStateMatrixParameter(modelViewMatrix_fp, CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY); cgGLSetParameter4f(camera_cg, s->view->center.x, s->view->center.y, s->view->center.z, 1.0f);
Renderização da Cena for (o = s->objs; o != NULL; o = o->next) { color_c = o->mat->c; color_s = o->mat->s; s_color[0] = color_c.x; s_color[1] = color_c.y; s_color[2] = color_c.z; // Set up CG color parameters cgGLSetParameter4f(color, s_color[0], s_color[1], s_color[2], 1.0f); if (o->type == V_PRIM) { Sphere sph = o->u.prim->d; c = sph->c; s_center[0] = c.x; s_center[1] = c.y; s_center[2] = c.z; sph_radius = sph->r; // Set up object type specific CG parameters cgGLSetParameter1f(radius, sph_radius); cgGLSetParameter1f(radius_fp, sph_radius); draw_sphere(s_center, sph_radius); }
Renderização da Cena else if (o->type == V_POLYLIST) { for (p = o->u.pols; p != NULL; p = p->next) { v1[0] = p->v[0].x; v1[1] = p->v[0].y; v1[2] = p->v[0].z; v2[0] = p->v[1].x; v2[1] = p->v[1].y; v2[2] = p->v[1].z; v3[0] = p->v[2].x; v3[1] = p->v[2].y; v3[2] = p->v[2].z; // Set up object type specific CG parameters cgGLSetParameter1f(radius, s_radius); cgGLSetParameter1f(radius_fp, s_radius); bilerp(v1, v2, v3, s_radius); } } } if (cg_enable) { // disable VP and FP cgGLDisableProfile(cgVertexProfile); cgGLDisableProfile(cgFragmentProfile); } glFlush (); glutSwapBuffers();
Renderização da Cena long bilerp(GLfloat v1[3], GLfloat v2[3], GLfloat v3[3], GLfloat s_radius) { long num_spheres = 0; int i,j, i_max, j_max; GLfloat s_center[3], vtemp[3]; float d_v1v2 = dist(v1,v2); float d_vtempv3; i_max = (int)floor(d_v1v2/s_radius); if (bilerp_enable == TRUE) { for (i=0;i<=i_max;i++) { vtemp[0] = v1[0] + (float)((float)i/(float)i_max)*(v2[0]-v1[0]); vtemp[1] = v1[1] + (float)((float)i/(float)i_max)*(v2[1]-v1[1]); vtemp[2] = v1[2] + (float)((float)i/(float)i_max)*(v2[2]-v1[2]); j_max = (int)floor(dist(vtemp,v3)/s_radius); d_vtempv3 = dist(vtemp, v3); num_spheres += j_max; for(j=0;j<=j_max;j++) { s_center[0] = vtemp[0] + (float)((float)j/(float)j_max)*(v3[0]-vtemp[0]); s_center[1] = vtemp[1] + (float)((float)j/(float)j_max)*(v3[1]-vtemp[1]); s_center[2] = vtemp[2] + (float)((float)j/(float)j_max)*(v3[2]-vtemp[2]); draw_sphere(s_center, s_radius); } } } else { num_spheres+=3; draw_sphere(v1, s_radius); draw_sphere(v2, s_radius); draw_sphere(v3, s_radius); } return num_spheres; }