Визуализация изоповерхности, созданной марширующими кубами

В настоящее время я использую 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 на два, а затем используя эти координаты в объемной текстуре как 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, разделенными на два.

Вот скриншот того, что я вижу, он имеет правильную форму изоповерхности, но ужасно неправильную текстуру.

Изоповерхность с ужасающей текстурой.


person The Wind-Up Bird    schedule 07.11.2016    source источник


Ответы (1)


gl_FragColor устарел с OpenGL 3.0, вы используете старую или новую версию OpenGL? Может быть, вы можете попробовать этот фрагментный шейдер.

uniform sampler3D u_texture;
varying vec3 v_texcoord;
out vec4 FragColor;    
void main() 
{
    FragColor = vec4(texture(u_texture, v_texcoord), 1);
}
person Tiger Hwang    schedule 07.11.2016