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
► 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];
// Cubo unitá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]
glVertex3f(s_center[0] + factor*cube[x][1][0],s_center[1] + factor*cube[x][1][1],s_center[2]
glVertex3f(s_center[0] + factor*cube[x][2][0],s_center[1] + factor*cube[x][2][1],s_center[2]
glVertex3f(s_center[0] + factor*cube[x][3][0],s_center[1] + factor*cube[x][3][1],s_center[2]
}
}
glEnd();
+
+
+
+
factor*cube[x][0][2]);
factor*cube[x][1][2]);
factor*cube[x][2][2]);
factor*cube[x][3][2]);
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
float4 color
float4 light
float4 camera
};
►
: POSITION;
: COLOR0;
: COLOR1;
: TEXCOORD0;
A saída do Vertex Program e’ do tipo vfconn e e’ a entrada do Fragment Program.
struct vfconn
{
float4 HPos
float4 Col0
float4 o
float4 l
float4 v
};
: POSITION;
: COLOR0;
: TEXCOORD1;
: COLOR1;
: 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]
v2[0] = p->v[1].x; v2[1] = p->v[1].y; v2[2]
v3[0] = p->v[2].x; v3[1] = p->v[2].y; v3[2]
// 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();
{
= p->v[0].z;
= p->v[1].z;
= p->v[2].z;
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;
Resultados
Download

Renderizacao de cenas por tracado de raios na Placa Grafica