私は現在、いくつかの科学的データの視覚化を行うためにOpenGL(より具体的にはVisPyバインディングを使用しています)を使用しています。私は容積測定データセットを持っており、内部に存在するいくつかの等値面を視覚化したいと思います。私は、Pythonのskimage.measure
ライブラリに組み込まれたマーチングキューブアルゴリズムを使用して等値面を生成します。マーチングキューブで生成された等値面を可視化する
私は頂点のセットを持っています。メッシュの三角形分割を出力として定義するインデックスのセットはskimage.measure.marching_cubes
です。これらはレンダリングのために直接VertexBuffer
とIndexBuffer
オブジェクトに変換することができます。しかし、isosurfaceにテクスチャを適用する適切な方法は何ですか?私は空想的な何かをする必要はありません、基本的にはちょっとした色ですので、より明瞭に視覚化することができます。
本質的に、ここに私の混乱の点があります。頂点座標はボックス[0,2] x [0,2] x [0, 1]
に定義されています。これは、ボリュームがx
とy
の2倍で、z
であるためです。私の理解が正しいならば、テクスチャ座標は常に[0,1] x [0,1] x [0, 1]
立方体で定義されます。私は、x
とy
のコンポーネントを2で割って、ボリュームテクスチャの座標をtexcoord
として使って、頂点座標をテクスチャ座標に変換する単純な体積テクスチャを生成しようとしています。しかし、これは動作しません(添付の画像を参照してください)。ここではいくつかのコードがあります:
バーテックスシェーダ:
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;
}
フラグメントシェーダ:
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);
}
3Dテクスチャは、現在、次のように設定されています。このテクスチャはそれほど意味を持たないことに注意してください。私は様々な方向のグラデーションを置いて、設定で遊んでみるので、出力の違いを見ることができます。このテクスチャを変更しても、私が見ているものには影響しません。
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
とy
の座標を2で割った頂点座標です。
ここに私が見るもののスクリーンショットがあります。これは正しいアイソサーフェスの形をしていますが、ひどく間違ったテクスチャです。