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 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 v2 v0 v1 v3 s0 s1 s2 s3 sf sb eye
Ponto de saída: menor dos t i > 0 Cálculo do Ponto de Saída v2 v1 v3 f2f3 f1
Cálculo do Ponto de Saída Projeção ortográfica –View direction é constante –Parâmetros t i variam linearmente ao longo dos fragmentos da face –t i podem ser calculados para os vértices da face frontal no vertex program –Rasterizador interpola os t i para cada fragmento –Teste dos t i feito no fragment program. Projeção perspectiva –Cálculo dos t i 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 v0 v1 v3 s0 s1 s2 s3
Renderização de isosuperfícies via Cell Projection v2 v0 v1 v3 s0 s1 s2 s3 sfsb eye Teste codificado em uma textura 2d
Renderização de isosuperfícies via Cell Projection s iso3 s iso2 s iso1 s iso2 s iso3 sf sb
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; // Vertice no espaco de clipping 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; };
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; // 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; } 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);
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 = ; // inicializa com valor alto float ti; float3 aux1; float aux2; float3 dir_n; // direcao normalizada dir_n = 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 17x17x tetraedros Janela 320x240 AMD Athlon XP GHz 256 MB de RAM NVIDIA GeForce FX 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)