OpenGL实现Volume Rendering 大致步骤
1D TF Code
在混合volume render程序中的1D TF code
1. RGBA都为0~255,正好一个byte,unsigned int,char型。
2. 一个节点(传输函数上的关键节点)上的信息为:intensity+color[RBGA]。
3. 透明度值a用0~255存储,用的时候(float)/255.f。
4. intensity大的点在update的时候必须>=原来intensity比其小的店,比较,移动等问题,用插入排序。
绘制纹理
绘制一共需要3个纹理
1. 一个3D texture 存放体数据。
2. 3个2D texture: ray casting 起始位置纹理,ray casting 结束位置纹理(存放的是起始和技术位置的深度值),一张深度纹理,即为2张纹理的差值。
3. 1个1D texture 存放1DTF数据。244*4个byte。
GLSL过程
GLSL过程
1. 创建shader -> glCreateShader();
2. shader读入char* -> glShaderSource();
3. 编译shader -> glCompileShader();
4. 创建program -> glCreateProgram();
5. 将shader连到program上 -> glAttachShader();
6. 链接program -> glLinkProgram();
程序流程
程序流程
1. init
1. 初始化GLSL
2. 初始化texture,分配空间,glTexImage2D();
3. 将纹理都绑定到一个帧缓存对象。FBO需要opengl3.0或者使用扩展glew,或者用代替的framebufferobject.h/.cpp。
4. 根据raw数据长宽高,载入数据到char*,再绑定到3D纹理。
5. 绑定传输函数1Dtexture。
2. render
1. updateTFtexture,看看传输函数是否变化,有变化重新产生纹理。
2. 绘制起始位置纹理:绑定FBO,转换视角,glDrawBuffer绘制到绑定的纹理上,绘制一个立方体,将顶点坐标信息当做纹理坐标。
3. 绘制结束位置纹理:同上,绘制前用glDepthFunc(GL_GREATER);绘制后用glDepthFunc(GL_LESS);
4. boundingBox的片段着色器为: void main { gl_FragColor = gl_TexCoord[0];//直接将纹理坐标赋值给最终颜色。 }
5. glUseProgram(raycastingProgram);
6. glActiveTexture()激活纹理,内容始终是GL_TEXTURE0+gen出来的纹理id。
7. 穿入这些纹理。
8. 将产生的最终结果绘制到窗口大小的矩形上。
9. 使用正交投影。
10. raycasting glsl代码:
GLSL Code
#extension GL_ARB_texture_rectangle : enable
uniform sampler1D texTransfunc;
uniform sampler2DRect texStartPos;
uniform sampler2DRect texEndPos;
uniform sampler3D texVolume;
uniform float step;
void main()
{
vec3 rayStart = texture2DRect(texStartPos, gl_TexCoord[0].st).xyz;
vec3 rayEnd = texture2DRect(texEndPos, gl_TexCoord[0].st).xyz;
vec3 start2end = rayEnd - rayStart;
if (start2end.x == 0.0 && start2end.y == 0.0 && start2end.z == 0.0) {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
return;
}
vec4 color = vec4(0, 0, 0, 0);
vec3 direction = normalize(start2end);
float distance = dot(direction, start2end);
int steps = distance / step;
for(int i = 0; i < 2048; ++i) {
if(i >= steps)
break;
vec3 samplePoint = rayStart + direction * step * (i + 0.5);
float scalar = texture3D(texVolume, samplePoint).x;
vec4 sampledColor = texture1D(texTransfunc, scalar);
color = color + sampledColor * vec4(sampledColor.aaa, 1.0) * (1.0 - color.a);
if(color.a > 0.99)
break;
}
color = color + vec4(1, 1, 1, 0) * (1.0 - color.a);
color.a = 1;
gl_FragColor = color;
//gl_FragColor = texture2DRect(texStartPos, gl_TexCoord[0].st);
}
引用的文件地址:http://neversayever.com/blog/2012/01/1901/。但是估计网站没有更新,因此不能访问。