Question

J'apprends le rendu de volume en utilisant un algorithme de coulée de rayons. J'ai trouvé une bonne démo et tuturial dans ici. Mais le problème est que j'ai une carte graphique ATI au lieu de NVIDIA qui ne peut pas utiliser le shader CG dans la démo, donc je veux changer le shader CG en Shader GLSL. J'ai parcouru le livre rouge (7 édition) d'OpenGL, mais je ne connais pas GLSL et CG. Quelqu'un peut-il m'aider à changer le shader CG dans la démo en GLSL? Ou y a-t-il des matériaux à la démo la plus simple du rendu de volume en utilisant la coulée de rayons (bien sûr dans GLSL). ici est le shader CG de la démo. Et cela peut fonctionner sur la carte graphique Nvidia de mon ami. Ce qui me confondait le plus, c'est que je ne sais pas comment traduire la partie d'entrée de CG en GLSL, par exemple:

struct vertex_fragment
 {
   float4 Position    : POSITION; // For the rasterizer
   float4 TexCoord    : TEXCOORD0; 
   float4 Color       : TEXCOORD1;
   float4 Pos         : TEXCOORD2;
 };

De plus, je peux écrire un objet de texture Bind 2 de programme avec 2 unité de texture au shader à condition que j'attribue deux TexCoord lors de l'écran, par exemple

glMultiTexCoord2f(GL_TEXTURE0, 1.0, 0.0);

glMultiTexCoord2f(GL_TEXTURE1, 1.0, 0.0);

Dans la démo, le programme se liera à deux textures (un 2d pour backface_buffer un 3d pour volume texture), mais avec une seule unité de texture comme glMultiTexCoord3f(GL_TEXTURE1, x, y, z); Je pense que le GL_TEXTURE1 L'unité est pour la texture volumique, mais laquelle (unité texure) est pour le backface_buffer? Pour autant que je sache, pour lier la texture obj dans un shader, je dois obtenir une unité de texture pour se lier par exemple:

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);

Le programme est bien compilé et lié OK. Mais je n'ai obtenu que -1 des trois emplacements (Texloc, Volume_Texloc et Stepsizeloc). Je sais que cela peut être optimisé. Quelqu'un peut m'aider à traduire le shader CG en shader GLSL?

Éditer: Si vous vous intéressez à l'implémentation de l'API OpenGL moderne (code source C ++) avec GLSL:Volume_redering_using_glsl

Était-ce utile?

La solution

Problème résolu. la Version GLSL de la démo:

vertex shadder

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;
}

shader de fragment

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;
}

Si vous avez vu l'original shadmeder de CG, il n'y a qu'une petite différence entre CG et GLSL. La partie la plus difficile pour traduire la démo en version GLSL est que la fonction CG dans l'OpenGL tel que:

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

encapsuler le processus d'activation de l'unité de texture et de l'activation multiditexture (en utilisant glActiveTexture) et la désactivation, qui est très importante dans cette démo car elle a utilisé le pipeline fixe ainsi que le pipeline programmable. Voici le segment clé changé dans la fonction void raycasting_pass() de main.cpp de la démo dans le tutoriel GPU GPU Raycasting:

fonction 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);
}

C'est ça.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top