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)