renderowanie woluminów (przy użyciu glsl) z algorytmem Ray castingu
Uczę się renderowania woluminów za pomocą algorytmu odlewania promieni. Znalazłem dobre demo i tuturial w tutaj . ale problem polega na tym, że mam kartę graficzną ATI zamiast Nvidii, które sprawiają, że nie mogę używać CG shader w demo, więc chcę zmienić CG shader na GLSL shader. Przejrzałem red book (wydanie 7) OpenGL, ale nie znam glsl i cg. czy ktoś może mi pomóc zmienić CG shader w demo na glsl? czy są jakieś materiały do najprostsze demo renderowania woluminów za pomocą ray castingu (oczywiście w glsl). tutaj jest CG shader demo. i może działać na karcie graficznej NVIDIA mojego przyjaciela. najbardziej mylące jest to, że nie wiem, jak przetłumaczyć część wejściową cg na glsl, na przykład:
struct vertex_fragment
{
float4 Position : POSITION; // For the rasterizer
float4 TexCoord : TEXCOORD0;
float4 Color : TEXCOORD1;
float4 Pos : TEXCOORD2;
};
Co więcej, mogę napisać program bind 2 texture object z 2 texture unit do shadera pod warunkiem, że przy rysowaniu ekranu przypiszę dwa texcoord, na przykład
glMultiTexCoord2f(GL_TEXTURE0, 1.0, 0.0);
glMultiTexCoord2f(GL_TEXTURE1, 1.0, 0.0);
W wersji demonstracyjnej program będzie wiązał się z dwiema teksturami (jedna 2D dla backface_buffer
jedna 3D dla volume texture
), ale tylko z jedną jednostką tekstury, taką jak glMultiTexCoord3f(GL_TEXTURE1, x, y, z);
myślę, że jednostka GL_TEXTURE1
jest dla tekstury woluminu, ale która (jednostka tekstury) jest dla backface_buffer
? o ile wiem, Aby powiązać teksturę obj w shaderze, muszę uzyskać jednostkę tekstury, aby powiązać na przykład:
glLinkProgram(p);
texloc = glGetUniformLocation(p, "tex");
volume_texloc = glGetUniformLocation(p, "volume_tex");
stepsizeloc = glGetUniformLocation(p, "stepsize");
glUseProgram(p);
glUniform1i(texloc, 0);
glUniform1i(volume_texloc, 1);
glUniform1f(stepsizeloc, stepsize);
//When rendering an object with this program.
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, backface_buffer);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_3D, volume_texture);
Program jest dobrze skompilowany i połączony ok. ale mam tylko -1 z wszystkich trzech lokalizacji (texloc, volume_texloc i stepsizeloc). Wiem, że może być zoptymalizowany. czy ktoś może mi pomóc przetłumaczyć CG shader na GLSL shader?
Edit: jeśli interesuje Cię nowoczesna implementacja API OpenGL (kod źródłowy C++) z glsl: Volume_Rendering_Using_GLSL
1 answers
Problem rozwiązany. wersja glsl z demo :
Vertex shader
void main()
{
gl_Position = gl_ModelViewProjectionMatrix*gl_Vertex;
//gl_FrontColor = gl_Color;
gl_TexCoord[2] = gl_Position;
gl_TexCoord[0] = gl_MultiTexCoord1;
gl_TexCoord[1] = gl_Color;
}
Fragment shader
uniform sampler2D tex;
uniform sampler3D volume_tex;
uniform float stepsize;
void main()
{
vec2 texc = ((gl_TexCoord[2].xy/gl_TexCoord[2].w) + 1) / 2;
vec4 start = gl_TexCoord[0];
vec4 back_position = texture2D(tex, texc);
vec3 dir = vec3(0.0);
dir.x = back_position.x - start.x;
dir.y = back_position.y - start.y;
dir.z = back_position.z - start.z;
float len = length(dir.xyz); // the length from front to back is calculated and used to terminate the ray
vec3 norm_dir = normalize(dir);
float delta = stepsize;
vec3 delta_dir = norm_dir * delta;
float delta_dir_len = length(delta_dir);
vec3 vect = start.xyz;
vec4 col_acc = vec4(0,0,0,0); // The dest color
float alpha_acc = 0.0; // The dest alpha for blending
float length_acc = 0.0;
vec4 color_sample; // The src color
float alpha_sample; // The src alpha
for(int i = 0; i < 450; i++)
{
color_sample = texture3D(volume_tex,vect);
// why multiply the stepsize?
alpha_sample = color_sample.a*stepsize;
// why multply 3?
col_acc += (1.0 - alpha_acc) * color_sample * alpha_sample*3 ;
alpha_acc += alpha_sample;
vect += delta_dir;
length_acc += delta_dir_len;
if(length_acc >= len || alpha_acc > 1.0)
break; // terminate if opacity > 1 or the ray is outside the volume
}
gl_FragColor = col_acc;
}
Jeśli widziałeś oryginalny shader cg, jest tylko niewielka różnica między cg a glsl. w opengl nie jest możliwe tłumaczenie wersji demonstracyjnej na wersję glsl, ponieważ funkcja cg w opengl jest taka jak:
param = cgGetNamedParameter(program, par);
cgGLSetTextureParameter(param, tex);
cgGLEnableTextureParameter(param);
Enkapsuluje proces aktywacji jednostki tekstury i wielowątkowości (za pomocą glActiveTexture
) i dezaktywacja, która jest bardzo ważna w tym demo, ponieważ używała zarówno stałego potoku, jak i programowalnego potoku. oto kluczowy segment zmieniony w funkcji void raycasting_pass()
main.procesor CPP demo w samouczku Raycastingu GPU Petera Triera:
Function raycasting_pass
void raycasting_pass()
{
// specify which texture to bind
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, final_image, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glUseProgram(p);
glUniform1f(stepsizeIndex, stepsize);
glActiveTexture(GL_TEXTURE1);
glEnable(GL_TEXTURE_3D);
glBindTexture(GL_TEXTURE_3D, volume_texture);
glUniform1i(volume_tex, 1);
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, backface_buffer);
glUniform1i(tex, 0);
glUseProgram(p);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
drawQuads(1.0,1.0, 1.0); // Draw a cube
glDisable(GL_CULL_FACE);
glUseProgram(0);
// recover to use only one texture unit as for the fixed pipeline
glActiveTexture(GL_TEXTURE1);
glDisable(GL_TEXTURE_3D);
glActiveTexture(GL_TEXTURE0);
}
To wszystko.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-26 08:41:03