2012-02-28 9 views
17

Uczę się renderowania objętości za pomocą algorytmu odlewania promieni. Znalazłem dobre demo i tuturial w here. ale problem polega na tym, że mam kartę graficzną ATI zamiast nVidii, co uniemożliwia mi używanie shadera cg w demie, więc chcę zmienić shadera cg na shader glsl. Przeszedłem przez czerwoną książkę (7 edycji) OpenGL, ale nie znałem glsl i cg. czy ktoś może mi pomóc zmienić shader cg w wersji demonstracyjnej na glsl? lub czy istnieją materiały do ​​najprostszej wersji renderowania wolumenu za pomocą ray castingu (oczywiście w języku glsl). here jest shaderem cg demonstracji. i może działać na karcie graficznej nVidii mojego przyjaciela. co najbardziej mnie mylące jest to, że nie wiem jak przetłumaczyć część wejścia cg do GLSL, na przykład:renderowanie objętości (przy użyciu glsl) z algorytmem odlewania promieni

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 tekstury obiekt z jednostką 2 teksturę shader pod warunkiem, że przypisanie dwóch texcoord podczas rysowania na ekranie, na przykład

glMultiTexCoord2f(GL_TEXTURE0, 1.0, 0.0);

glMultiTexCoord2f(GL_TEXTURE1, 1.0, 0.0);

W demo program będzie wiązać się z dwóch tekstury (jeden 2D dla backface_buffer jeden 3D dla volume texture), ale z tylko jedną jednostką teksturową, taką jak glMultiTexCoord3f(GL_TEXTURE1, x, y, z);, myślę, że jednostka GL_TEXTURE1 jest dla tekstury objętości, ale która z nich (jednostka Texure) jest dla backface_buffer? o ile wiem, w celu związania tekstury OBJ w cieniującego, muszę dostać jednostkę tekstury wią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 kompilowany w porządku i połączone ok. ale mam tylko -1 ze wszystkich trzech lokalizacji (texloc, volume_texloc i stepsizeloc). Wiem, że to może być zoptymalizowane. ktoś może mi pomóc przetłumaczyć shadera cg na shader glsl?

Edit: Jeśli zainteresowanie w nowoczesny implementacji OpenGL API (C++ kod źródłowy) z GLSL: Volume_Rendering_Using_GLSL

+0

Cg shadery działają równie dobrze na ATi/AMD, jak na NVidii (co jest dość względne, ponieważ środowisko wykonawcze Cg ma * wiele błędów * dotyczących błędów w kodekach). – ssube

+0

Przypomnienie: kompilator Cg może emitować kod GLSL. Z kartami AMD/ATI można również używać Cg. Tylko kilka rzeczy specyficznych dla NVidii nie zadziała, a wydajność będzie nieznacznie ograniczona. – datenwolf

+0

@ datenwolf naprawdę? Spróbuję. Zastanawiam się, jak wyemitować kod GLSL? – toolchainX

Odpowiedz

14

Problem rozwiązany. glsl version 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ł oryginału shader CG jest tylko mała różnica pomiędzy CG i GLSL . najtrudniejsze do przetłumaczenia demo do wersji GLSL jest to, że funkcja CG w OpenGL, takie jak:

param = cgGetNamedParameter(program, par); 
cgGLSetTextureParameter(param, tex); 
cgGLEnableTextureParameter(param); 

hermetyzacji procesu jednostki tekstury i aktywacji multitekstur (używając glActiveTexture) i dezaktywacji, co jest bardzo ważne w to demo, ponieważ używało stałego potoku, a także programowalnego potoku. tutaj jest kluczowy segment zmieniony w funkcji void raycasting_pass() głównej.CPP demo w Peter Trier tutorialu ray casting GPU:

funkcja 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.

Powiązane problemy