1

I'm currently using OpenGL (more specifically through the VisPy bindings) to do some scientific data visualization. I have a volumetric dataset, and I would like to visualize some isosurfaces present inside of it. I generate the isosurfaces using the built-in marching cubes algorithm in Python's skimage.measure library.

So, I have the set of vertices, and I have the set of indices which define the triangulation of the mesh as output by skimage.measure.marching_cubes. These can be directly converted to VertexBuffer and IndexBuffer objects for rendering. But what is the proper way to apply a texture to the isosurface? I don't need to do anything fancy, basically just some color so it can be visualized more clearly.

Essentially, here is my point of confusion. Vertex coordinates are defined on the box [0,2] x [0,2] x [0, 1], because my volume is twice as long in x and y as it is in z. Texture coordinates are always defined on the [0,1] x [0,1] x [0, 1] cube if my understanding is correct. I've been attempting to generate a simple volumetric texture, converting vertex coordinates to texture coordinates by dividing the x and y components by two, and then using those coordinates in the volumetric texture as the texcoord. But this doesn't work (please see attached image). Here's some code:

Vertex 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;
}

Fragment Shader:

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);
}

The 3D texture is currently set to the following. Please note that this texture isn't supposed to mean all that much; I'm just trying to put a gradient in various directions and play around with the settings so I can see a difference in the output. Changing this texture has no effect on what I see.

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]

The VertexBuffer and IndexBuffer are exactly as output by the marching cubes algorithm. As described above, texcoord is simply the vertex coordinate with x and y coordinates divided by two.

Here's a screenshot of what I see, which has the correct isosurface shape but is textured horribly wrong.

A horribly textured isosurface.

genpfault
  • 51,148
  • 11
  • 85
  • 139
The Wind-Up Bird
  • 661
  • 2
  • 8
  • 17

1 Answers1

0

gl_FragColor was deprecated since OpenGL 3.0, are you using an older or newer version of OpenGL? Maybe you can try this fragment shader.

uniform sampler3D u_texture;
varying vec3 v_texcoord;
out vec4 FragColor;    
void main() 
{
    FragColor = vec4(texture(u_texture, v_texcoord), 1);
}
Tiger Hwang
  • 300
  • 1
  • 5
  • 16