Renderização de Isosuperficies
Baseada em Cell Projection
Marcos Machado
10/12/2004
Introdução
• Dado volumétrico não-estruturado
• Volume rendering:
–
–
–
–
Projected Tetrahedra
Cell Projection
Ray Tracing
...
Cell Projection Baseado em
Hardware Gráfico
• M. Weiler, M. Kraus, and T. Ertl.
Hardware-Based View-Independent Cell
Projection.
In Procceedings of IEEE Symposium on Volume
Visualization 2002
• Características:
– Paralelizável
– Independência do observador
– Permite otimizações como display list ou vertex
array do OpenGL
Cell Projection
v2
s2
sf
eye
v0
s0
sb
v3
s3
v1
s1
• Campo escalar varia linearmente no tetraedro
• Rasteriza faces visíveis de cada tetraedro:
– OpenGL backface culling => independência do observador
– sf calculado pelo rasterizador
– Calcular sb e a contribuição entre os 2 pontos
• Volume rendering
• Rendering de isosuperficie
Cálculo do Ponto de Saída
v2
f1
v3
f3
f2
v1
Ponto de saída: menor dos ti > 0
Cálculo do Ponto de Saída
• Projeção ortográfica
– View direction é constante
– Parâmetros ti variam linearmente ao longo dos
fragmentos da face
– ti podem ser calculados para os vértices da face frontal
no vertex program
– Rasterizador interpola os ti para cada fragmento
– Teste dos ti feito no fragment program.
• Projeção perspectiva
– Cálculo dos ti e teste devem ser executados no fragment
program
Cálculo do Valor no Ponto de
Saída
• Campo escalar varia linearmente no tetraedro
=> gradiente constante
Cálculo do gradiente
v2
s2
v3
s3
v0
s0
v1
s1
Renderização de isosuperfícies
via Cell Projection
v2
s2
sf
eye
v0
s0
sb
v3
s3
v1
s1
Teste codificado em uma textura 2d
Renderização de isosuperfícies
via Cell Projection
siso3
siso2
sb
siso1
siso1 siso2 siso3
sf
Cg Vertex Program
struct vert_in {
float4 vertex
: POSITION;
float4 scalar
: COLOR0;
// Escalar normalizado.
float4 vertex3
: NORMAL;
// Vértice oposto à face.
float3 normal0
: TEXCOORD0;
// Normais das outras faces.
float3 normal1
: TEXCOORD1;
float3 normal2
: TEXCOORD2;
float3 gradient : TEXCOORD3;
// Gradiente do escalar no tetraedro.
};
struct vert2frag {
float4 vertexCS
: POSITION;
float4 sf
: COLOR0;
float3 normal0
: TEXCOORD0;
float3 normal1
: TEXCOORD1;
float3 normal2
: TEXCOORD2;
float3 gradient
: TEXCOORD3;
float3 dir
: TEXCOORD4;
float3 vertexOS
: TEXCOORD5; // Vertice no espaco do objeto
float3 vertex3
: TEXCOORD6;
};
// Vertice no espaco de clipping
Cg Vertex Program
vert2frag main(vert_in IN, uniform float4x4 ModelViewProj, uniform float4x4 ModelViewI,
uniform float3 EyePosVP)
{
vert2frag OUT;
OUT.vertexCS = mul(ModelViewProj, IN.vertex);
OUT.sf
= IN.scalar;
OUT.vertex3
= IN.vertex3.xyz;
OUT.normal0
= IN.normal0;
OUT.normal1
= IN.normal1;
OUT.normal2
= IN.normal2;
OUT.gradient
= IN.gradient;
cgGLSetStateMatrixParameter(cgGetNamedParameter(
_program_vp, "ModelViewProj"),
CG_GL_MODELVIEW_PROJECTION_MATRIX,
CG_GL_MATRIX_IDENTITY);
cgGLSetStateMatrixParameter(cgGetNamedParameter(
_program_vp, "ModelViewI"),
CG_GL_MODELVIEW_MATRIX,
CG_GL_MATRIX_INVERSE);
// Posição do olho no sistema do objeto
float3 EyePos = mul( ModelViewI, float4(0,0,0,1)).xyz;
OUT.dir
= IN.vertex.xyz - EyePos;
OUT.vertexOS = IN.vertex.xyz;
return OUT;
}
Cg Fragment Program
struct vert2frag {
float4 vCS
: POSITION; // Posicao do fragmento no espaco de clipping
float4 sf
: COLOR0;
float3 normal0
: TEXCOORD0;
float3 normal1
: TEXCOORD1;
float3 normal2
: TEXCOORD2;
float3 gradient : TEXCOORD3;
float3 dir
: TEXCOORD4;
float3 vOS
: TEXCOORD5; // Posicao do fragmento no espaco do objeto
float3 vertex3
: TEXCOORD6;
};
struct frag_out {
float4 color
};
: COLOR;
Cg Fragment Program
frag_out main(vert2frag IN, uniform sampler2D IsoSurfTex)
{
frag_out OUT;
float
t = 10000.0; // inicializa com valor alto
float
ti;
float3 aux1;
float
aux2;
float3 dir_n;
dir_n
// direcao normalizada
= IN.dir;
//dir_n = normalize(IN.dir);
// Acha menor t positivo dentre as interseções do raio com as outras faces do tetraedro.
// t = (V3 - V).Ni / D.Ni
aux1 = IN.vertex3 - IN.vOS; // (vértice oposto - posição de entrada do raio)
aux2 = 1.0f / dot(dir_n, IN.normal0);
ti = dot(aux1, IN.normal0) * aux2;
if (ti > 0.0f)
t = min(t,ti);
Cg Fragment Program
aux2 = 1.0f / dot(IN.dir, IN.normal1);
ti = dot(aux1, IN.normal1) * aux2;
if(ti > 0.0f)
t = min(t,ti);
aux2 = 1.0f / dot(dir_n, IN.normal2);
ti = dot(aux1, IN.normal2) * aux2;
if(ti > 0.0f)
t = min(t,ti);
// Calcula Sb = Sf + t(G.D)
// Coordenadas de textura:
//
Isosurfaces: (sb, sf)
aux1.x = IN.sf.x + t*dot(IN.gradient, dir_n);
aux1.y = IN.sf.x;
// Cor sem iluminação
OUT.color = tex2D(IsoSurfTex, aux1.yx);
return OUT;
}
Resultados
• Volume de 17x17x17
24576 tetraedros
Janela 320x240
• AMD Athlon XP 2200+
1.80 GHz
256 MB de RAM
NVIDIA GeForce FX5200
• 5.0 fps
Resultados
Campo com simetria planar
isovalores: 0.3(R), 0.5(G) e 0.9(B)
Campo com simetria esférica
isovalores: 0.3(R), 0.5(G) e 0.9(B)
Download

sf - PUC-Rio