我目前正在使用OpenGL(更具体地说是通过VisPy绑定)来进行一些科学数据可视化。我有一个体积数据集,我想想象一下它内部存在的一些等值面。我使用Python的skimage.measure
库中的内置行进立方体算法生成等值面。
所以,我有一组顶点,我有一组索引,它们定义网格的三角剖分作为skimage.measure.marching_cubes
的输出。这些可以直接转换为VertexBuffer
和IndexBuffer
个对象进行渲染。但是将纹理应用于等值面的正确方法是什么?我不需要做任何花哨的事情,基本上只是一些颜色,所以它可以更清晰地显示。
基本上,这是我的困惑点。顶点坐标在方框[0,2] x [0,2] x [0, 1]
上定义,因为我的x
和y
中的音量是z
中的两倍。如果我的理解是正确的,纹理坐标总是在[0,1] x [0,1] x [0, 1]
立方体上定义。我一直试图生成一个简单的体积纹理,通过将x
和y
分量除以2将顶点坐标转换为纹理坐标,然后使用体积纹理中的那些坐标作为{ {1}}。但这不起作用(请参见附图)。这是一些代码:
顶点着色器:
texcoord
Fragment Shader:
uniform mat4 u_model;
uniform mat4 u_view;
uniform mat4 u_projection;
attribute vec3 a_position;
attribute vec3 a_texcoord;
varying vec3 v_texcoord;
void main() {
gl_Position = u_projection * u_view * u_model * vec4(a_position, 1.0);
v_texcoord = a_texcoord;
}
3D纹理当前设置如下。请注意,这种纹理不应该意味着那么多;我只是试图在各个方向上放置一个渐变并使用设置来玩,所以我可以看到输出的差异。更改此纹理对我看到的内容没有影响。
uniform sampler3D u_texture;
varying vec3 v_texcoord;
void main() {
float r = texture3D(u_texture, v_texcoord).r;
float g = texture3D(u_texture, v_texcoord).g;
float b = texture3D(u_texture, v_texcoord).b;
gl_FragColor = vec4(r, g, b, 1);
}
D, H, W = 64, 128, 128
texture_arr = np.ones((W, H, D, 4)).astype(np.float32)
texture_arr[...] *= np.linspace(0, 1, W)[:, np.newaxis, np.newaxis, np.newaxis]
texture_arr[...] *= np.linspace(0, 1, H)[np.newaxis, :, np.newaxis, np.newaxis]
texture_arr[...] *= np.linspace(0, 1, D)[np.newaxis, np.newaxis, :, np.newaxis]
和VertexBuffer
完全是行进多维数据集算法的输出。如上所述,IndexBuffer
只是顶点坐标,texcoord
和x
坐标除以2。
这是我看到的截图,它具有正确的等值面形状,但纹理可怕的错误。
答案 0 :(得分:0)
自OpenGL 3.0以来,gl_FragColor已被弃用,您使用的是旧版本还是较新版本的OpenGL?也许你可以尝试这个片段着色器。
uniform sampler3D u_texture;
varying vec3 v_texcoord;
out vec4 FragColor;
void main()
{
FragColor = vec4(texture(u_texture, v_texcoord), 1);
}