cgv
Loading...
Searching...
No Matches
volume_renderer.cxx
1#include "volume_renderer.h"
2#include <random>
3#include <cgv/math/ftransform.h>
4#include <cgv_gl/gl/gl.h>
5#include <cgv_gl/gl/gl_tools.h>
6
7namespace cgv {
8 namespace render {
9 volume_renderer& ref_volume_renderer(context& ctx, int ref_count_change)
10 {
11 static int ref_count = 0;
12 static volume_renderer r;
13 r.manage_singleton(ctx, "volume_renderer", ref_count, ref_count_change);
14 return r;
15 }
16
18 {
21
22 unsigned size = 64;
23 std::vector<uint8_t> noise_data(size*size);
24
25 std::default_random_engine rng(42);
26 std::uniform_int_distribution<unsigned> dist(0u, 255u);
27
28 for(size_t i = 0; i < noise_data.size(); ++i)
29 noise_data[i] = static_cast<uint8_t>(dist(rng));
30
32 noise_texture.create(ctx, dv, 0);
33 }
34
36 {
37 // validate set attributes
38 const volume_render_style& vrs = get_style<volume_render_style>();
39 bool res = renderer::validate_attributes(ctx);
40 res = res && (volume_texture != nullptr);
41 return res;
42 }
44 {
45 const volume_render_style& vrs = get_style<volume_render_style>();
46
47 options.define_macro_if_not_default("NUM_STEPS", vrs.integration_quality, VolumeIntegrationQuality::k128);
49 options.define_macro_if_true(vrs.enable_noise_offset, "ENABLE_NOISE_OFFSET");
50 options.define_macro_if_true(vrs.enable_lighting, "ENABLE_LIGHTING");
51 options.define_macro_if_true(vrs.use_gradient_texture, "USE_GRADIENT_TEXTURE");
52 options.define_macro_if_true(vrs.enable_gradient_modulation, "ENABLE_GRADIENT_MODULATION");
53 options.define_macro_if_true(vrs.enable_depth_test, "ENABLE_DEPTH_TEST");
54
55 options.define_macro_if_not_default("ISOSURFACE_MODE", vrs.isosurface_mode, VolumeIsosurfaceMode::kNone);
56 options.define_macro_if_not_default("ISOSURFACE_COLOR_MODE", vrs.isosurface_color_from_transfer_function, false);
57
58 options.define_macro_if_not_default("SLICE_MODE", vrs.slice_mode, VolumeSliceMode::kNone);
59
60 options.define_macro_if_not_default("COMPOSITING_MODE", vrs.compositing_mode, VolumeCompositingMode::kBlend);
62 options.define_macro_if_not_default("TRANSFER_FUNCTION_SAMPLER_DIMENSIONS", transfer_function_texture->get_nr_dimensions(), 1u);
63 }
65 {
66 bool res = renderer::init(ctx);
67 res = res && position_aam.init(ctx);
68 enable_attribute_array_manager(ctx, position_aam);
69
70 // use a single optimized triangle strip to define a cube
71 std::vector<vec3> positions = {
72 { -0.5f, +0.5f, -0.5f },
73 { +0.5f, +0.5f, -0.5f },
74 { -0.5f, -0.5f, -0.5f },
75 { +0.5f, -0.5f, -0.5f },
76 { +0.5f, -0.5f, +0.5f },
77 { +0.5f, +0.5f, -0.5f },
78 { +0.5f, +0.5f, +0.5f },
79 { -0.5f, +0.5f, -0.5f },
80 { -0.5f, +0.5f, +0.5f },
81 { -0.5f, -0.5f, -0.5f },
82 { -0.5f, -0.5f, +0.5f },
83 { +0.5f, -0.5f, +0.5f },
84 { -0.5f, +0.5f, +0.5f },
85 { +0.5f, +0.5f, +0.5 }
86 };
87 set_position_array(ctx, positions);
88
91
92 return res;
93 }
94 void volume_renderer::clear (const context& ctx) {
95 disable_attribute_array_manager(ctx, position_aam);
96 position_aam.destruct(ctx);
98 renderer::clear(ctx); // perform upstream actions
99 }
100
102 if(!tex || tex->get_nr_dimensions() != 3)
103 return false;
104 volume_texture = tex;
105 return true;
106 }
107
109 if(!tex || tex->get_nr_dimensions() > 2)
110 return false;
112 return true;
113 }
114
116 if(!tex || tex->get_nr_dimensions() != 3)
117 return false;
118 gradient_texture = tex;
119 return true;
120 }
121
123 if(!tex || tex->get_nr_dimensions() != 2)
124 return false;
125 depth_texture = tex;
126 return true;
127 }
128
129 void volume_renderer::set_bounding_box(const box3& bbox)
130 {
131 bounding_box = bbox;
132 }
133
134 void volume_renderer::transform_to_bounding_box(bool flag)
135 {
137 }
138
139 void volume_renderer::set_noise_offset(const vec2& offset)
140 {
141 noise_offset = offset;
142 }
143
145 const volume_render_style& vrs = get_style<volume_render_style>();
146 if(!renderer::enable(ctx))
147 return false;
148 int vp[4];
149 glGetIntegerv(GL_VIEWPORT, vp);
150 ref_prog().set_uniform(ctx, "viewport_dims", vec2(float(vp[2] - vp[0]), float(vp[3] - vp[1])));
151 ref_prog().set_uniform(ctx, "noise_offset", noise_offset);
152
153 ref_prog().set_uniform(ctx, "picking_opacity_threshold", vrs.picking_opacity_threshold);
154 ref_prog().set_uniform(ctx, "scale_adjustment_factor", vrs.scale_adjustment_factor);
155
156 ref_prog().set_uniform(ctx, "light_local_to_eye", vrs.light_local_to_eye);
157 ref_prog().set_uniform(ctx, "light_direction", normalize(vrs.light_direction));
158 float specular_exponent = cgv::math::lerp(128.0f, 1.0f, cgv::math::clamp(vrs.roughness, 0.0f, 1.0f));
159 ref_prog().set_uniform(ctx, "ambient_strength", vrs.ambient_strength);
160 ref_prog().set_uniform(ctx, "diffuse_strength", vrs.diffuse_strength);
161 ref_prog().set_uniform(ctx, "specular_strength", vrs.specular_strength);
162 ref_prog().set_uniform(ctx, "specular_exponent", specular_exponent);
163 ref_prog().set_uniform(ctx, "specular_color_mix", vrs.specular_color_mix);
164
165 ref_prog().set_uniform(ctx, "gradient_lambda", std::max(vrs.gradient_lambda, 0.001f));
166
167 ref_prog().set_uniform(ctx, "isovalue", vrs.isovalue);
168 ref_prog().set_uniform(ctx, "isosurface_color", vrs.isosurface_color);
169
170 ref_prog().set_uniform(ctx, "slice_axis", vrs.slice_axis);
171 ref_prog().set_uniform(ctx, "slice_coordinate", vrs.slice_coordinate);
172 ref_prog().set_uniform(ctx, "slice_opacity", vrs.slice_opacity);
173
174 ref_prog().set_uniform(ctx, "clip_box_min", vrs.clip_box.get_min_pnt());
175
176 ref_prog().set_uniform(ctx, "clip_box_max", vrs.clip_box.get_max_pnt());
177
179 ctx.set_depth_func(CF_ALWAYS);
180 ctx.push_blend_state();
181 ctx.enable_blending();
183 ctx.push_cull_state();
184 ctx.set_cull_state(CM_FRONTFACE);
185
188 noise_texture.enable(ctx, 2);
191 return true;
192 }
209 void volume_renderer::draw(context& ctx, size_t start, size_t count, bool use_strips, bool use_adjacency, uint32_t strip_restart_index)
210 {
212
214 const volume_render_style& vrs = get_style<volume_render_style>();
215 cgv::box3 clipped_box(
218 );
219 ctx.mul_modelview_matrix(cgv::math::translate4(clipped_box.get_center()));
220 ctx.mul_modelview_matrix(cgv::math::scale4(clipped_box.get_extent()));
221 }
222
223 glDrawArrays(GL_TRIANGLE_STRIP, 0, (GLsizei)14);
224
226 }
227 }
228}
229
230#include <cgv/gui/provider.h>
231
232namespace cgv {
233 namespace gui {
234
237 bool create(provider* p, const std::string& label,
238 void* value_ptr, const std::string& value_type,
239 const std::string& gui_type, const std::string& options, bool*) {
241 return false;
242 cgv::render::volume_render_style* vrs_ptr = reinterpret_cast<cgv::render::volume_render_style*>(value_ptr);
243 cgv::base::base* b = dynamic_cast<cgv::base::base*>(p);
244
245 p->add_member_control(b, "Quality", vrs_ptr->integration_quality, "dropdown", "w=114;enums='8=8,16=16,32=32,64=64,128=128,256=256,512=512,1024=1024,2048=2048,4096=4096'", " ");
246 p->add_member_control(b, "Use Noise", vrs_ptr->enable_noise_offset, "check", "w=74");
247 p->add_member_control(b, "Interpolation", vrs_ptr->interpolation_mode, "dropdown", "enums=Nearest,Smoothed,Linear,Cubic");
248
249 p->add_member_control(b, "Depth Test", vrs_ptr->enable_depth_test, "check");
250 p->add_member_control(b, "Opacity Threshold", vrs_ptr->picking_opacity_threshold, "value_slider", "min=0.0;max=1.0;step=0.001;tooltip='Opacity threshold used for focus picking'");
251
252 p->add_member_control(b, "Compositing Mode", vrs_ptr->compositing_mode, "dropdown", "enums='Maximum Intensity Projection, Average, Blend'");
253
254 p->add_member_control(b, "Scale Adjustment", vrs_ptr->scale_adjustment_factor, "value_slider", "min=0.0;step=0.001;max=1000.0;log=true;ticks=true");
255
256 if(p->begin_tree_node("Lighting", vrs_ptr->enable_lighting, false)) {
257 p->align("/a");
258 p->add_member_control(b, "Enable", vrs_ptr->enable_lighting, "check", "w=88", " ");
259 p->add_member_control(b, "Local to Eye", vrs_ptr->light_local_to_eye, "check", "w=100");
260 p->add_member_control(b, "Normals from Gradient Texture", vrs_ptr->use_gradient_texture, "check");
261 p->add_member_control(b, "Direction", vrs_ptr->light_direction[0], "value", "w=58;min=-1;max=1", " ");
262 p->add_member_control(b, "", vrs_ptr->light_direction[1], "value", "w=58;min=-1;max=1", " ");
263 p->add_member_control(b, "", vrs_ptr->light_direction[2], "value", "w=58;min=-1;max=1");
264 p->add_member_control(b, "", vrs_ptr->light_direction[0], "slider", "w=58;min=-1;max=1;step=0.0001;ticks=true", " ");
265 p->add_member_control(b, "", vrs_ptr->light_direction[1], "slider", "w=58;min=-1;max=1;step=0.0001;ticks=true", " ");
266 p->add_member_control(b, "", vrs_ptr->light_direction[2], "slider", "w=58;min=-1;max=1;step=0.0001;ticks=true");
267
268 p->add_decorator("Light Parameters", "heading", "level=3");
269 p->add_member_control(b, "Ambient", vrs_ptr->ambient_strength, "value_slider", "min=0;max=1;step=0.001;ticks=true");
270 p->add_member_control(b, "Diffuse", vrs_ptr->diffuse_strength, "value_slider", "min=0;max=1;step=0.001;ticks=true");
271 p->add_member_control(b, "Specular", vrs_ptr->specular_strength, "value_slider", "min=0;max=1;step=0.001;ticks=true");
272 p->add_member_control(b, "Roughness", vrs_ptr->roughness, "value_slider", "min=0;max=1;step=0.001;ticks=true");
273 p->add_member_control(b, "Specular Color", vrs_ptr->specular_color_mix, "value_slider", "min=0;max=1;step=0.001;ticks=true");
274 p->align("/b");
275 p->end_tree_node(vrs_ptr->enable_lighting);
276 }
277
278 if(p->begin_tree_node("Gradient Modulation", vrs_ptr->enable_gradient_modulation, false)) {
279 p->align("\a");
280 p->add_member_control(b, "Enable", vrs_ptr->enable_gradient_modulation, "check");
281 p->add_member_control(b, "Lambda", vrs_ptr->gradient_lambda, "value_slider", "min=0.001;max=10;step=0.001;ticks=true;log=true");
282 p->align("\b");
284 }
285 if (p->begin_tree_node("Orthogonal Slicing", vrs_ptr->slice_mode, false)) {
286 p->align("\a");
287 p->add_member_control(b, "Mode", vrs_ptr->slice_mode, "dropdown", "enums='Disabled,Opaque,Transparent'");
288 p->add_member_control(b, "Axis", vrs_ptr->slice_axis, "value_slider", "min=0;max=2;ticks=true");
289 p->add_member_control(b, "Coordinate", vrs_ptr->slice_coordinate, "value_slider", "min=0;max=1;ticks=true");
290 p->add_member_control(b, "Opacity", vrs_ptr->slice_opacity, "value_slider", "min=0;max=1;ticks=true");
291 p->align("\b");
292 p->end_tree_node(vrs_ptr->slice_mode);
293 }
294
295 if(p->begin_tree_node("Isosurface (Blend only)", vrs_ptr->isosurface_mode, false)) {
296 p->align("\a");
297 p->add_member_control(b, "", vrs_ptr->isosurface_mode, "dropdown", "enums='Disabled,Isovalue,Alpha Threshold'");
298
299 p->add_member_control(b, "Value", vrs_ptr->isovalue, "value_slider", "min=0.0;max=1.0;step=0.001;ticks=true");
300 p->add_member_control(b, "Color", vrs_ptr->isosurface_color, "", "w=42", " ");
301 p->add_member_control(b, "From Transfer Function", vrs_ptr->isosurface_color_from_transfer_function, "check", "w=146");
302 p->align("\b");
303 p->end_tree_node(vrs_ptr->isosurface_mode);
304 }
305
306 if(p->begin_tree_node("Clip Box", vrs_ptr->clip_box, false)) {
307 p->align("\a");
308 p->add_gui("Clipping Box", vrs_ptr->clip_box, "",
309 "options='w=100;min=0;max=1;step=0.01;ticks=true;align=\"BL\"';align_col=' '");
310 p->align("\b");
311 p->end_tree_node(vrs_ptr->clip_box);
312 }
313
314 return true;
315 }
316 };
317
318#include "gl/lib_begin.h"
319
320 CGV_API cgv::gui::gui_creator_registration<volume_render_style_gui_creator> volume_rs_gc_reg("volume_render_style_gui_creator");
321
322 }
323}
base class for all classes that can be registered with support for dynamic properties (see also secti...
Definition base.h:75
A data_format describes a multidimensional data block of data entries.
Definition data_format.h:17
unsigned get_nr_dimensions() const
return the number of dimensions of the data set
the data view gives access to a data array of one, two, three or four dimensions.
Definition data_view.h:153
helper template for registration of gui creators
Definition gui_creator.h:32
derive from this class to provide a gui to the current viewer
Definition provider.h:64
bool add_gui(const std::string &label, T &value, const std::string &gui_type="", const std::string &options="")
Add a composed gui of the given gui_type for the given value.
Definition provider.h:247
cgv::base::base_ptr add_decorator(const std::string &label, const std::string &decorator_type, const std::string &options="", const std::string &align="\n")
add a newly created decorator to the group
Definition provider.cxx:168
void align(const std::string &_align)
send pure alignment information
Definition provider.cxx:36
bool begin_tree_node(const std::string &label, const T &value, bool initial_visibility=false, const std::string &options="", gui_group_ptr ggp=gui_group_ptr())
Begin a sub tree of a tree structured gui.
Definition provider.h:212
data::ref_ptr< control< T > > add_member_control(cgv::base::base *base_ptr, const std::string &label, T &value, const std::string &gui_type="", const std::string &options="", const std::string &align="\n")
add control with callback to cgv::base::on_set method on cgv::gui::control::value_change
Definition provider.h:137
void end_tree_node(const T &value)
template specialization that allows to specify value reference plus node_instance by using the result...
Definition provider.h:222
fpnt_type get_center() const
return the center of the box
fvec_type get_extent() const
return a vector with the extents in the different dimensions
const fpnt_type & get_max_pnt() const
return a const reference to corner 7
const fpnt_type & get_min_pnt() const
return a const reference to corner 0
base class for all drawables, which is independent of the used rendering API.
Definition context.h:627
void set_blend_func_back_to_front()
set the default blend function for back to front blending
Definition context.cxx:1771
virtual void mul_modelview_matrix(const dmat4 &MV)
multiply given matrix from right to current modelview matrix
Definition context.cxx:1827
void push_depth_test_state()
push a copy of the current depth test state onto the stack saved attributes: depth test enablement,...
Definition context.cxx:1688
void push_blend_state()
push a copy of the current blend state onto the stack saved attributes: blend enablement,...
Definition context.cxx:1735
void pop_blend_state()
pop the top of the current culling state from the stack
Definition context.cxx:1739
void pop_depth_test_state()
pop the top of the current depth test state from the stack
Definition context.cxx:1692
void push_cull_state()
push a copy of the current culling state onto the stack saved attributes: cull face enablement,...
Definition context.cxx:1718
virtual void set_cull_state(CullingMode culling_mode)
set the culling state
Definition context.cxx:1731
virtual void set_depth_func(CompareFunction func)
set the depth test function
Definition context.cxx:1705
virtual void enable_blending()
enable blending
Definition context.cxx:1775
void pop_cull_state()
pop the top of the current culling state from the stack
Definition context.cxx:1722
void pop_modelview_matrix()
see push_V for an explanation
Definition context.cxx:1833
void push_modelview_matrix()
push the current viewing matrix onto a matrix stack for viewing matrices.
Definition context.cxx:1821
virtual bool is_created() const
return whether component has been created
Definition context.cxx:2065
void manage_singleton(context &ctx, const std::string &renderer_name, int &ref_count, int ref_count_change)
used by derived classes to manage singletons
Definition renderer.cxx:10
virtual bool enable(context &ctx)
enables renderer
Definition renderer.cxx:198
virtual bool init(context &ctx)
call init() once before using renderer
Definition renderer.cxx:167
shader_program & ref_prog()
derived renderer classes have access to shader program
Definition renderer.h:79
virtual void enable_attribute_array_manager(const context &ctx, attribute_array_manager &aam)
call this before setting attribute arrays to manage attribute array in given manager
Definition renderer.cxx:48
virtual void clear(const context &ctx)
the clear function destructs the shader program
Definition renderer.cxx:344
virtual void disable_attribute_array_manager(const context &ctx, attribute_array_manager &aam)
call this after last render/draw call to ensure that no other users of renderer change attribute arra...
Definition renderer.cxx:57
void set_position_array(const context &ctx, const std::vector< T > &positions)
templated method to set the position attribute from a vector of positions of type T
Definition renderer.h:181
virtual bool validate_attributes(const context &ctx) const
call to validate, whether essential position attribute is defined
Definition renderer.cxx:124
virtual bool disable(context &ctx)
disable renderer
Definition renderer.cxx:224
Stores preprocessor options used for conditionally compiling shader programs.
Definition shader_code.h:73
void define_macro_if_true(bool predicate, const std::string &identifier)
Conditionally define identifier as a macro with replacement text 1.
void define_macro_if_not_default(const std::string &identifier, const T &value, const T &default_value)
Conditionally define identifier as a macro with value as replacement text.
bool set_uniform(const context &ctx, const std::string &name, const T &value, bool generate_error=false)
Set the value of a uniform by name, where the type can be any of int, unsigned, float,...
the texture class encapsulates all functionality independent of the rendering api.
Definition texture.h:15
bool create(const context &ctx, TextureType _tt=TT_UNDEF, unsigned width=-1, unsigned height=-1, unsigned depth=-1)
create the texture of dimension and resolution specified in the data format base class.
Definition texture.cxx:213
bool disable(const context &ctx)
disable texture and restore state from before last enable call
Definition texture.cxx:774
bool enable(const context &ctx, int tex_unit=-1)
enable this texture in the given texture unit, -1 corresponds to the current unit.
Definition texture.cxx:763
bool destruct(const context &ctx)
destruct the texture and free texture memory and handle
Definition texture.cxx:748
renderer that supports point splatting
texture * gradient_texture
the 3D texture containing vector gradients used for lighting normal calculation
bool validate_attributes(const context &ctx) const override
call to validate, whether essential position attribute is defined
bool set_gradient_texture(texture *tex)
sets the gradient texture used for lighting
void clear(const context &ctx) override
clean up
bool init(context &ctx) override
construct shader programs and return whether this was successful, call inside of init method of drawa...
texture * depth_texture
a 2D texture from a frame buffer depth buffer used to combine volume rendering with opaque geometry
texture * transfer_function_texture
the 2D transfer function texture used for classification of the volume values
void init_noise_texture(context &ctx)
initializes the noise texture with random values
bool enable(context &ctx) override
enables renderer
void draw(context &ctx, size_t start, size_t count, bool use_strips=false, bool use_adjacency=false, uint32_t strip_restart_index=-1) override
Draw a range of vertices or indexed elements.
bool apply_bounding_box_transformation
whether to translate and scale the volume to the given bounding box during rendering
bool set_transfer_function_texture(texture *tex)
sets the transfer function used for classification; must be 1D or 2D (as loaded from an image)
vec2 noise_offset
offset applied to the noise texture (can be used in conjunction with temporal anti aliasing)
bool set_volume_texture(texture *tex)
sets the 3D volume texture containing scalar values (density or other measured quantities)
bool set_depth_texture(texture *tex)
sets the depth texture needed for rendering with additional opaque geometry
texture * volume_texture
the 3D texture used for rendering
texture noise_texture
a 2D texture containing random noise used to offset ray start positions in order to reduce ring artif...
box3 bounding_box
the bounding box of the volume in scene units
void update_shader_program_options(shader_compile_options &options) const override
update shader program compile options based on render style
bool disable(context &ctx) override
disable renderer
@ CF_R
undefinded format with no component
@ kLinear
modification of the built-in trilinear interpolation to prevent triangular artifacts (results look bl...
volume_renderer & ref_volume_renderer(context &ctx, int ref_count_change)
reference to a singleton volume renderer that is shared among drawables
@ TI_UINT8
signed integer stored in 64 bits
Definition type_id.h:23
the cgv namespace
Definition print.h:11
cgv::math::fvec< float, 2 > vec2
declare type of 2d single precision floating point vectors
Definition fvec.h:668
interface for gui creators
Definition gui_creator.h:14
bool create(provider *p, const std::string &label, void *value_ptr, const std::string &value_type, const std::string &gui_type, const std::string &options, bool *)
attempt to create a gui and return whether this was successful
bool light_local_to_eye
whether the light is local to the eye position (moves with the eye) or is static to the scene
bool enable_noise_offset
whether to use the noise texture to offset ray start positions in order to reduce sampling artifacts
bool enable_lighting
whether to enable lighting
float specular_strength
material specular component strength
float ambient_strength
light ambient component strength
VolumeIsosurfaceMode isosurface_mode
mode of a single supported isosurface
rgb isosurface_color
the default constant isosurface color
bool enable_depth_test
whether to enable depth testing by reading depth from a texture to allow geometry intersecting the vo...
float isovalue
the value used to check for an isosurface
float gradient_lambda
influence scale for gradient-based opacity modulation
VolumeSliceMode slice_mode
mode of slice rendering
bool isosurface_color_from_transfer_function
whether to color the isosurface based on the transfer function
float scale_adjustment_factor
the coefficient used to adjust sample opacity based on volume scaling (useful range between 50 and 50...
VolumeInterpolationMode interpolation_mode
the interpolation method used (supplied volume texture should be set to GL_LINEAR)
float slice_opacity
in case of transparent mode, slice opacity
VolumeIntegrationQuality integration_quality
quality measure for the number of steps used during ray marching
float specular_color_mix
material specular color mix factor (0 = color from transfer function, 1 = pure white)
vec3 light_direction
the direction of the directional light
float roughness
material roughness (inversely proportional to specular shininess)
bool use_gradient_texture
whether to use a supplied gradient texture or compute gradients on the fly via central differences (d...
VolumeCompositingMode compositing_mode
the compositing mode used
int slice_axis
coordinate axis orthogonal to which slice is rendered
float diffuse_strength
material diffuse component strength
bool enable_gradient_modulation
whether to enable modulating the volume opacity by the gradient magnitude
box3 clip_box
a bounding box used to define a subspace of the volume to be visualized
float slice_coordinate
coordinate value along axis defining slice in range [0,1]
traits class with a static function get_name() of type const char* that returns the type name of the ...
Definition type_name.h:54