带有光线投射算法的体积渲染(使用 glsl) [英] volume rendering (using glsl) with ray casting algorithm

查看:37
本文介绍了带有光线投射算法的体积渲染(使用 glsl)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习使用光线投射算法的体绘制.我在这里找到了一个很好的演示和教程.但问题是我有一个 ATI 显卡而不是 nVidia,这使我无法在演示中使用 cg 着色器,所以我想将 cg 着色器更改为 glsl 着色器.OpenGL的红皮书(7版)看过,但是对glsl和cg不熟悉.有谁可以帮我将演示中的 cg 着色器更改为 glsl?或者是否有使用光线投射(当然在 glsl 中)的最简单的体积渲染演示的任何材料.这里是演示的 cg 着色器.它可以在我朋友的 nVidia 显卡上运行.最让我困惑的是,我不知道如何将cg的入口部分翻译成glsl,例如:

I am learning volume rendering using ray casting algorithm. I have found a good demo and tuturial in here. but the problem is that I have a ATI graphic card instead of nVidia which make me can't using the cg shader in the demo, so I want to change the cg shader to glsl shader. I have gone through the red book (7 edition) of OpenGL, but not familiar with glsl and cg. does anyone can help me change the cg shader in the demo to glsl? or is there any materials to the simplest demo of volume rendering using ray casting (of course in glsl). here is the cg shader of the demo. and it can work on my friend's nVidia graphic card. what most confusing me is that I don't know how to translate the entry part of cg to glsl, for example:

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

更重要的是,如果我在绘制屏幕时分配两个texcoord,我可以编写一个程序将2个纹理对象与2个纹理单元绑定到着色器,例如

what's more, I can write a program bind 2 texture object with 2 texture unit to the shader provided that I assign two texcoord when draw the screen, for example

glMultiTexCoord2f(GL_TEXTURE0, 1.0, 0.0);

glMultiTexCoord2f(GL_TEXTURE1, 1.0, 0.0);

在演示中,程序将绑定到两个纹理(backface_buffer 一个 2D,体积纹理 一个 3D),但只有一个纹理单元,如 glMultiTexCoord3f(GL_TEXTURE1, x, y, z); 我认为 GL_TEXTURE1 单元是用于体积纹理的,但哪个(纹理单元)用于 backface_buffer?据我所知,为了在着色器中绑定纹理 obj,我必须获得一个纹理单元来绑定,例如:

In the demo the program will bind to two texture (one 2D for backface_buffer one 3D for volume texture), but with only one texture unit like glMultiTexCoord3f(GL_TEXTURE1, x, y, z); I think the GL_TEXTURE1 unit is for the volume texture, but which one (texure unit) is for the backface_buffer? as far as I know in order to bind texture obj in a shader, I must get a texture unit to bind for example:

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

程序编译正常,链接正常.但我只得到了所有三个位置(texloc、volume_texloc 和 stepsizeloc)中的 -1.我知道它可能会被优化掉.谁能帮我将 cg 着色器转换为 glsl 着色器?

the program is compiled fine and linked ok. but I only got -1 of all three location(texloc, volume_texloc and stepsizeloc). I know it may be optimized out. anyone can help me translate the cg shader to glsl shader?

如果您对使用 glsl 的现代 OpenGL API 实现(C++ 源代码)感兴趣:Volume_Rendering_Using_GLSL

If you are interest in modern OpenGL API implementation(C++ source code) with glsl:Volume_Rendering_Using_GLSL

推荐答案

问题已解决.glsl 版本98">演示:

Problem solved. the glsl version of the demo:

顶点着色器

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

片段着色器

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

如果你看过cg的原始shader,cg和glsl之间只有一点点区别.将demo翻译成glsl版本最难的部分是opengl中的cg函数如:

if you seen the original shader of cg there is only a little difference between cg and glsl. the most difficult part to translate the demo to glsl version is that the cg function in the opengl such as:

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

封装了纹理单元和多纹理激活(使用glActiveTexture)和去激活的过程,这在这个演示中非常重要,因为它使用了固定管线和可编程管线.这是 Peter Triers GPU raycasting 教程中演示的 main.cpp 函数 void raycasting_pass() 中更改的关键部分:

encapsulate the process of texture unit and multitexture activation (using glActiveTexture) and deactivation, which is very important in this demo as it used the fixed pipeline as well as programmable pipeline. here is the key segment changed in the function void raycasting_pass() of main.cpp of the demo in Peter Triers GPU raycasting tutorial:

函数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);
}

就是这样.

这篇关于带有光线投射算法的体积渲染(使用 glsl)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆