Opengl 使用光线投射算法的体绘制(使用glsl)
我正在学习使用光线投射算法的体绘制。我发现了一个很好的演示和教程。但问题是我有一个ATI图形卡而不是nVidia,这使我无法在演示中使用cg着色器,所以我想将cg着色器更改为glsl着色器。我已经阅读了OpenGL的红皮书(7版),但不熟悉glsl和cg。 有人能帮我把演示中的cg着色器改成glsl吗?或者,是否有任何材料可用于使用光线投射的最简单的体绘制演示(当然是glsl)。 是演示的cg着色器。它可以在我朋友的nVidia图形卡上工作。最让我困惑的是,我不知道如何将cg的输入部分翻译成glsl,例如:Opengl 使用光线投射算法的体绘制(使用glsl),opengl,glsl,demo,raycasting,volume-rendering,Opengl,Glsl,Demo,Raycasting,Volume Rendering,我正在学习使用光线投射算法的体绘制。我发现了一个很好的演示和教程。但问题是我有一个ATI图形卡而不是nVidia,这使我无法在演示中使用cg着色器,所以我想将cg着色器更改为glsl着色器。我已经阅读了OpenGL的红皮书(7版),但不熟悉glsl和cg。 有人能帮我把演示中的cg着色器改成glsl吗?或者,是否有任何材料可用于使用光线投射的最简单的体绘制演示(当然是glsl)。 是演示的cg着色器。它可以在我朋友的nVidia图形卡上工作。最让我困惑的是,我不知道如何将cg的输入部分翻译成gl
struct vertex_fragment
{
float4 Position : POSITION; // For the rasterizer
float4 TexCoord : TEXCOORD0;
float4 Color : TEXCOORD1;
float4 Pos : TEXCOORD2;
};
更重要的是,我可以编写一个程序绑定2纹理对象和2个纹理单元到着色器,前提是我在绘制屏幕时指定了两个texcoord,例如
glMultiTexCoord2f(GL_TEXTURE0,1.0,0.0)代码>
glMultiTexCoord2f(GL_TEXTURE1,1.0,0.0)代码>
在演示中,程序将绑定到两个纹理(一个2D用于backface\u buffer
一个3D用于volume texture
),但只有一个纹理单元,如glMultiTexCoord3f(GL\u TEXTURE1,x,y,z)
我认为GL_纹理1
单元用于体积纹理,但是哪个(纹理单元)用于backface_缓冲区
?据我所知,为了在着色器中绑定纹理obj,我必须获得要绑定的纹理单元,例如:
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);
程序编译良好,链接正常。但我只得到了三个位置中的-1(texloc、volume_texloc和stepsizeloc)。我知道它可能被优化了。
有人能帮我把cg着色器翻译成glsl着色器吗
编辑:如果您对使用glsl实现现代OpenGL API(C++源代码)感兴趣:问题已解决。委员会成员:
顶点着色器
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;
}
片段着色器
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;
}
封装纹理单元和多纹理激活(使用glactivatetexture
)和停用的过程,这在本演示中非常重要,因为它使用固定管道和可编程管道。以下是Peter Triers GPU光线投射教程中演示的main.cpp的函数void raycasting_pass()
中更改的关键片段:
功能光线投射\u通行证
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);
}
就这样 Cg着色器在ATi/AMD上的工作与在nVidia上的工作一样好(这是相对的,因为Cg运行时在错误代码路径上有许多崩溃)。提醒一下:Cg编译器可以发出GLSL代码。Cg也可与AMD/ATI卡一起使用。只有一些特定于NVidia的东西不起作用,性能会受到轻微影响。@datenwolf真的吗?我要试一试。我想知道如何发出glsl代码?这是Cg独立编译器的一个选项。在GLSL中,它还可以发出DirectX HLSL和OpenGL vertex/fragment_程序集(在GLSL出现之前,我非常想念程序集着色器。GLSL对我来说并不合适)。@DatenWalf我尝试了cg3.1,似乎我的计算机只支持非常低级的配置文件,无法正确运行程序。