使用射线投射算法进行体绘制(使用glsl) [英] volume rendering (using glsl) with ray casting algorithm
问题描述
我正在学习使用射线投射算法进行体积渲染.我在此处找到了很好的演示和教程.但是问题是我有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屋!