使用射线投射算法进行体绘制(使用glsl) [英] volume rendering (using glsl) with ray casting algorithm

查看:176
本文介绍了使用射线投射算法进行体绘制(使用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,volume texture一个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

推荐答案

问题已解决. 顶点着色器

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之间只有一点点差异.将演示转换为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光线投射教程中的demo.main.cpp函数中更改的关键段:

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天全站免登陆