14template <
typename DimX,
typename DimY,
typename DimZ, floating_point ValueType,
15 bool HasNonConstReference>
19 HasNonConstReference>
const& prop) ->
void {
21 bool menu_open =
true;
27 auto viridis_data = std::vector<vec4f>{};
28 for (std::size_t i = 0; i < v.num_samples(); ++i) {
29 viridis_data.push_back(
30 vec4f{v.
data()[i](0), v.data()[i](1), v.data()[i](2), 1});
32 viridis_tex_1d.upload_data(viridis_data, v.num_samples());
35 viridis_tex_2d.resize(v.num_samples(), 2);
36 for (std::size_t i = 0; i < v.num_samples(); ++i) {
37 viridis_data.push_back(
38 vec4f{v.
data()[i](0), v.data()[i](1), v.data()[i](2), 1});
40 viridis_tex_2d.upload_data(viridis_data, v.num_samples(), 2);
42 auto const color_scales = std::array{
43 std::tuple{
"Viridis", std::move(viridis_tex_1d),
44 std::move(viridis_tex_2d)}
48 typename decltype(color_scales)
::value_type const* current_color_scale =
49 &color_scales.front();
52 cube_data.indexbuffer().resize(36);
55 auto data = cube_data.vertexbuffer().wmap();
56 data[i++] =
vec3f{0, 0, 0};
57 data[i++] =
vec3f{1, 0, 0};
58 data[i++] =
vec3f{0, 1, 0};
59 data[i++] =
vec3f{1, 1, 0};
60 data[i++] =
vec3f{0, 0, 1};
61 data[i++] =
vec3f{1, 0, 1};
62 data[i++] =
vec3f{0, 1, 1};
63 data[i++] =
vec3f{1, 1, 1};
67 auto data = cube_data.indexbuffer().wmap();
118 screenspace_quad_data.indexbuffer().resize(6);
121 auto data = screenspace_quad_data.vertexbuffer().wmap();
122 data[i++] =
vec2f{-1, -1};
123 data[i++] =
vec2f{1, -1};
124 data[i++] =
vec2f{-1, 1};
125 data[i++] =
vec2f{1, 1};
129 auto data = screenspace_quad_data.indexbuffer().wmap();
139 position_shader_t() {
141 "#version 330 core\n"
142 "layout(location = 0) in vec3 pos;\n"
143 "out vec3 frag_pos;\n"
144 "uniform mat4 projection_matrix;\n"
145 "uniform mat4 modelview_matrix;\n"
147 "------------------------------------------------------------------\n"
149 " gl_Position = projection_matrix * modelview_matrix * vec4(pos, "
154 "#version 330 core\n"
155 "in vec3 frag_pos;\n"
156 "out vec4 frag_out;\n"
158 "------------------------------------------------------------------\n"
160 " frag_out = vec4(frag_pos, 1);\n"
164 auto set_modelview_matrix(
mat4f const& MV) ->
void {
165 set_uniform_mat4(
"modelview_matrix", MV.
data());
167 auto set_projection_matrix(
mat4f const& P) ->
void {
168 set_uniform_mat4(
"projection_matrix", P.
data());
174 "#version 330 core\n"
175 "layout(location = 0) in vec2 pos;\n"
176 "//----------------------------------------------------------------\n"
178 " gl_Position = vec4(pos, 0, 1);\n"
181 "#version 430 core\n"
182 "uniform float shininess;\n"
183 "uniform vec3 specular_color;\n"
184 "uniform mat4 model_matrix;\n"
185 "uniform mat4 modelview_matrix;\n"
186 "uniform vec3 eps;\n"
187 "uniform sampler3D volume_data;\n"
188 "uniform sampler1D color_scale;\n"
189 "uniform sampler1D alpha;\n"
190 "uniform int mode;\n"
191 "uniform float range_min;\n"
192 "uniform float range_max;\n"
193 "uniform float ray_offset;\n"
194 "layout(rgba32f, binding = 0) readonly uniform image2D front_cube;\n"
195 "layout(rgba32f, binding = 1) readonly uniform image2D back_cube;\n"
196 "out vec4 frag_out;\n"
197 "//----------------------------------------------------------------\n"
198 "vec3 phong_brdf(vec3 light_dir, vec3 view_dir,\n"
199 " vec3 normal, vec3 diffuse_color) {\n"
200 " vec3 color = diffuse_color;\n"
201 " vec3 reflect_dir = reflect(-light_dir, normal);\n"
202 " float spec_dot = abs(dot(reflect_dir, view_dir));\n"
203 " color += pow(spec_dot, shininess) * specular_color;\n"
206 "//----------------------------------------------------------------\n"
208 " vec4 front = imageLoad(front_cube, ivec2(gl_FragCoord.xy));\n"
209 " vec4 back = imageLoad(back_cube, ivec2(gl_FragCoord.xy));\n"
210 " if (front.w == 0) {\n"
211 " frag_out = vec4(1, 1, 1, 1);\n"
214 " if (mode == 0) {\n"
215 " vec3 direction = back.xyz - front.xyz;\n"
216 " float distance = length(direction);\n"
217 " direction = normalize(direction);\n"
218 " vec3 modelview_direction =\n"
219 " normalize((modelview_matrix * back).xyz -\n"
220 " (modelview_matrix * front).xyz);\n"
221 " int num_steps = int(distance / ray_offset);\n"
222 " float actual_ray_offset = distance / num_steps;\n"
223 " vec4 accumulator = vec4(0, 0, 0, 0);\n"
224 " vec3 physical_eps = vec3(\n"
225 " length((model_matrix * vec4(2 * eps.x, 0, 0, 1)).xyz),\n"
226 " length((model_matrix * vec4(0, 2 * eps.y, 0, 1)).xyz),\n"
227 " length((model_matrix * vec4(0, 0, 2 * eps.z, 1)).xyz)\n"
229 " for (int i = 0; i < num_steps; ++i) {\n"
230 " vec3 cur_pos = front.xyz + direction * i * actual_ray_offset;"
231 " float s = texture(volume_data, cur_pos).x;\n"
232 " vec3 gradient = vec3(\n"
233 " (texture(volume_data, cur_pos + vec3(eps.x, 0, 0)).x -\n"
234 " texture(volume_data, cur_pos - vec3(eps.x, 0, 0)).x),\n"
235 " (texture(volume_data, cur_pos + vec3(0, eps.y, 0)).x -\n"
236 " texture(volume_data, cur_pos - vec3(0, eps.y, 0)).x),\n"
237 " (texture(volume_data, cur_pos + vec3(0, 0, eps.z)).x -\n"
238 " texture(volume_data, cur_pos - vec3(0, 0, eps.z)).x)) / "
240 " float normalized_sample = (s-range_min) / "
241 "(range_max-range_min);\n"
242 " vec3 normal = normalize(gradient);\n"
243 " vec3 albedo = texture(color_scale, normalized_sample).rgb;\n"
244 " vec3 luminance = albedo * 0.1;\n"
245 " float illuminance = abs(dot(modelview_direction, normal));\n"
246 " luminance += phong_brdf(modelview_direction, "
247 "modelview_direction,\n"
248 " normal, albedo) * illuminance;\n"
249 " float cur_alpha = texture(alpha, normalized_sample).r;\n"
250 " accumulator.rgb += (1 - accumulator.a) * cur_alpha * "
252 " accumulator.a += (1 - accumulator.a) * cur_alpha;\n"
253 " if (accumulator.a >= 0.95) { break; }\n"
255 " frag_out.xyz = vec3(1 - accumulator.a) + accumulator.xyz * "
257 " } else if (mode == 1) {\n"
258 " frag_out = front;\n"
259 " } else if (mode == 2) {\n"
260 " frag_out = back;\n"
261 " } else if (mode == 3) {\n"
262 " float s = texture(volume_data, front.xyz).x;\n"
263 " float normalized_sample = (s-range_min) / "
264 "(range_max-range_min);\n"
265 " //vec3 color = vec3(normalized_sample);\n"
266 " vec3 color = texture(color_scale, normalized_sample).xyz;\n"
267 " frag_out = vec4(color, 1);\n"
273 auto set_shininess(
float shininess) ->
void {
274 set_uniform(
"shininess", shininess);
276 auto set_volume_data_sampler_unit(
int unit) ->
void {
277 set_uniform(
"volume_data", unit);
279 auto set_color_scale_sampler_unit(
int unit) ->
void {
280 set_uniform(
"color_scale", unit);
282 auto set_alpha_sampler_unit(
int unit) ->
void {
283 set_uniform(
"alpha", unit);
285 auto set_model_matrix(
mat4f const& M) ->
void {
286 set_uniform_mat4(
"model_matrix", M.
data());
288 auto set_modelview_matrix(
mat4f const& MV) ->
void {
289 set_uniform_mat4(
"modelview_matrix", MV.
data());
291 auto set_mode(
int mode) ->
void { set_uniform(
"mode", mode); }
292 auto set_range_min(
float range_min) ->
void {
293 set_uniform(
"range_min", range_min);
295 auto set_specular_color(
vec3f const& specular_color) ->
void {
296 set_uniform_vec3(
"specular_color", specular_color.
data());
298 auto set_eps(
vec3f const& eps) ->
void {
299 set_uniform_vec3(
"eps", eps.
data());
301 auto set_range_max(
float range_max) ->
void {
302 set_uniform(
"range_max", range_max);
304 auto set_ray_offset(
float ray_offset) ->
void {
305 set_uniform(
"ray_offset", ray_offset);
311 auto specular_color =
vec3f{0.1f, 0.1f, 0.1f};
312 float range_min = 0.0f;
313 float range_max = 1.0f;
314 float ray_offset = 0.01f;
315 float shininess = 100.0f;
316 size_t const num_alpha_samples = 100;
318 std::vector<float> handles{0.0f, 0.0f, 0.1f, 0.0f, 0.45f, 0.0f, 0.45f,
319 0.0f, 0.5f, 1.0f, 0.5f, 1.0f, 0.55f, 0.0f,
320 0.55f, 0.0f, 1.0f, 0.0f, 0.9f, 0.0f};
322 std::vector<float> alpha_data(num_alpha_samples);
323 dvr_shader.set_volume_data_sampler_unit(0);
324 dvr_shader.set_color_scale_sampler_unit(1);
325 dvr_shader.set_alpha_sampler_unit(2);
326 dvr_shader.set_range_min(range_min);
327 dvr_shader.set_range_max(range_max);
328 dvr_shader.set_shininess(shininess);
329 dvr_shader.set_specular_color(specular_color);
330 dvr_shader.set_ray_offset(ray_offset);
331 dvr_shader.set_eps(
vec3f{1.0f / prop.grid().
template size<0>(),
332 1.0f / prop.grid().template size<1>(),
333 1.0f / prop.grid().template size<2>()});
339 : front_cube_tex{f}, back_cube_tex{b} {}
340 auto on_resize(
int width,
int height) ->
void override {
341 front_cube_tex.resize(width, height);
342 back_cube_tex.resize(width, height);
344 } listener{front_cube_tex, back_cube_tex};
345 win.add_listener(listener);
347 win.render_loop([&](
auto const ) {
348 front_cube_tex.clear(1, 1, 1, 0);
349 back_cube_tex.clear(1, 1, 1, 0);
355 position_shader.bind();
358 prop.grid().template front<1>(),
359 prop.grid().template front<2>()) *
361 prop.grid().template extent<1>(),
362 prop.grid().template extent<2>());
363 auto const MV = win.camera_controller().view_matrix() * M;
364 position_shader.set_modelview_matrix(MV);
365 dvr_shader.set_model_matrix(M);
366 dvr_shader.set_modelview_matrix(MV);
367 position_shader.set_projection_matrix(
368 win.camera_controller().projection_matrix());
371 front_cube_framebuffer.
bind();
373 cube_data.draw_triangles();
376 back_cube_framebuffer.
bind();
378 cube_data.draw_triangles();
386 front_cube_tex.bind_image_texture(0);
387 back_cube_tex.bind_image_texture(1);
389 std::get<1>(*current_color_scale).bind(1);
391 for (
size_t i = 0; i < num_alpha_samples; ++i) {
392 float const pos = i / (float)(num_alpha_samples - 1);
395 alpha_tex.upload_data(alpha_data, num_alpha_samples);
397 screenspace_quad_data.draw_triangles();
400 float width = std::min<float>(400, win.width() / 2);
401 ImGui::SetNextWindowSize(ImVec2{width, float(win.height())});
402 ImGui::SetNextWindowPos(ImVec2{win.width() - width, 0});
403 ImGui::Begin(
"", &menu_open,
404 ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse |
405 ImGuiWindowFlags_NoMove);
407 if (ImGui::Button(
"Volume")) {
408 dvr_shader.set_mode(0);
411 if (ImGui::Button(
"Front")) {
412 dvr_shader.set_mode(1);
415 if (ImGui::Button(
"Back")) {
416 dvr_shader.set_mode(2);
419 if (ImGui::Button(
"Map")) {
420 dvr_shader.set_mode(3);
422 if (ImGui::DragFloat(
"Ray Offset", &ray_offset, 0.001f, 0.0001f, 0.1f)) {
423 dvr_shader.set_ray_offset(ray_offset);
425 if (ImGui::DragFloat(
"Min", &range_min, 0.001f,
426 -std::numeric_limits<float>::max(), range_max)) {
427 dvr_shader.set_range_min(range_min);
429 if (ImGui::DragFloat(
"Max", &range_max, 0.001f, range_min,
430 std::numeric_limits<float>::max())) {
431 dvr_shader.set_range_max(range_max);
433 if (ImGui::DragFloat(
"Shininess", &shininess, 5.0f)) {
434 dvr_shader.set_shininess(shininess);
436 if (ImGui::ColorEdit3(
"Specular Color", specular_color.data())) {
437 dvr_shader.set_specular_color(specular_color);
441 ImGuiStyle& style = ImGui::GetStyle();
442 float w = ImGui::CalcItemWidth();
443 float spacing = style.ItemInnerSpacing.x;
444 float button_sz = ImGui::GetFrameHeight();
445 ImVec2 combo_pos = ImGui::GetCursorScreenPos();
446 ImGui::PushItemWidth(w - spacing * 2.0f - button_sz * 2.0f);
447 if (ImGui::BeginCombo(
"##custom combo",
"")) {
449 for (
auto const& color_scale : color_scales) {
450 bool is_selected = (current_color_scale == &color_scale);
452 if (ImGui::Selectable(
"##foo", is_selected)) {
453 current_color_scale = &color_scale;
457 ImGui::Image((
void*)(intptr_t)std::get<2>(color_scale).
id(),
460 ImGui::SetCursorPosX(
461 ImGui::GetCursorPosX() + ImGui::GetColumnWidth() -
462 ImGui::CalcTextSize(std::get<0>(color_scale)).x -
463 ImGui::GetScrollX() - 2 * ImGui::GetStyle().ItemSpacing.x);
464 ImGui::TextUnformatted(std::get<0>(color_scale));
466 ImGui::SetItemDefaultFocus();
471 ImGui::PopItemWidth();
472 ImGui::SameLine(0, style.ItemInnerSpacing.x);
473 ImVec2 backup_pos = ImGui::GetCursorScreenPos();
474 ImGui::SetCursorScreenPos(
475 ImVec2(combo_pos.x + style.FramePadding.x, combo_pos.y));
476 ImGui::Image((
void*)(intptr_t)std::get<2>(*current_color_scale).id(),
478 ImGui::SetCursorScreenPos(backup_pos);
480 ImGui::SetCursorPosX(
481 ImGui::GetCursorPosX() + ImGui::GetColumnWidth() -
482 ImGui::CalcTextSize(std::get<0>(*current_color_scale)).x -
483 ImGui::GetScrollX() - 2 * ImGui::GetStyle().ItemSpacing.x);
484 ImGui::TextUnformatted(std::get<0>(*current_color_scale));
487 ImGui::SetNextWindowSize(ImVec2{50, 50});
488 ImGui::SetNextWindowPos(ImVec2{float(win.width() - 50), 0.0f});
489 ImGui::Begin(
"",
nullptr,
490 ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize |
491 ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoBackground);
492 if (ImGui::Button(
"<", ImGui::GetWindowContentRegionMax() -
493 ImGui::GetWindowContentRegionMin())) {
Definition: framebuffer.h:10
static DLL_API void unbind()
Definition: indexeddata.h:13
auto vertexbuffer() -> auto &
Definition: indexeddata.h:148
auto set_wrap_mode(wrap_mode mode) -> void
setting all wrapmodes to same mode
Definition: texture.h:747
Definition: rectilinear_grid.h:38
constexpr auto data() -> ValueType *
Definition: static_multidim_array.h:260
auto Bezier(const char *label, std::vector< float > &handles) -> int
auto BezierValue(float dt01, std::vector< float > const &handles) -> float
DLL_API auto clear_color(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) -> void
DLL_API auto set_back_face_culling() -> void
DLL_API auto set_front_face_culling() -> void
DLL_API auto enable_depth_test() -> void
DLL_API auto disable_depth_test() -> void
DLL_API auto enable_face_culling() -> void
tex2rgba< GLfloat > tex2rgba32f
Definition: texture.h:957
DLL_API auto clear_color_depth_buffer() -> void
tex1rgba< GLfloat > tex1rgba32f
Definition: texture.h:921
DLL_API auto disable_face_culling() -> void
auto upload_tex(std::vector< Tensor > const &data, integral auto const ... res)
Definition: upload.h:41
auto interactive(std::vector< line< Real, N > > const &lines)
Definition: line.h:104
auto constexpr scale_matrix(Real s)
Definition: matrices.h:26
auto constexpr translation_matrix(Real const x, Real const y, Real const z)
Definition: matrices.h:11
typename value_type_impl< T >::type value_type
Definition: type_traits.h:280
Definition: vertex_property.h:96
Definition: shadersource.h:8
Definition: window_listener.h:10
Definition: first_person_window.h:15