cgv
Loading...
Searching...
No Matches
gl_transparent_renderer.cxx
1#include "gl_transparent_renderer.h"
2#include "gl_tools.h"
3#include <cgv_gl/gl/gl.h>
4
5namespace cgv {
6 namespace render {
7 namespace gl {
8
9
11gl_transparent_renderer::gl_transparent_renderer(bool front_to_back, float _depth_bias)
12 : gl_depth_peeler(front_to_back, _depth_bias),
13 layer_tex("uint8[R,G,B,A]",TF_NEAREST,TF_NEAREST),
14 color_tex("uint8[R,G,B,A]",TF_NEAREST,TF_NEAREST),
15 depth_buffer("[D]", TF_NEAREST, TF_NEAREST)
16{
17}
18
21{
22 if (!gl_depth_peeler::init(ctx))
23 return false;
24 if (!GLEW_EXT_framebuffer_object) {
25 last_error = "gl_transparent_renderer::init -> framebuffer objects not supported";
26 return false;
27 }
28 return true;
29}
30
33{
34 if (tex.is_created() && tex.get_width() == w && tex.get_height() == h)
35 return;
36
37 // depth buffer
38 if (tex.is_created())
39 tex.destruct(ctx);
40 tex.set_width(w);
41 tex.set_height(h);
42 tex.create(ctx);
43
44 fb.attach(ctx,tex,0,i);
45}
46
47
48
51{
52 // init the peeler for the frame
53 GLint vp[4];
54 glGetIntegerv(GL_VIEWPORT, vp);
55 // query size of view
56 int w = vp[2];
57 int h = vp[3];
58
59 // ensure that frame buffer and depth texture are created and have correct dimensions
60 if (!fb.is_created() || fb.get_width() != w || fb.get_height() != h) {
61 // frame buffer
62 if (fb.is_created())
63 fb.destruct(ctx);
64 fb.create(ctx,w,h);
65 }
66 create_and_attach_texture(ctx, depth_buffer, w, h);
67 create_and_attach_texture(ctx, layer_tex, w, h, 0);
68 if (is_front_to_back())
70 else
72 if (!fb.is_complete(ctx)) {
73 std::cerr << "gl_transparent_renderer::init_frame -> framebuffer not complete" << std::endl;
74 abort();
75 }
77}
78
81{
82 // blend layer over global frame buffer
83 glPushAttrib(GL_TEXTURE_BIT|GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
84 tex.enable(ctx);
85
86 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
87
88 glEnable(GL_BLEND);
89 if (front_to_back)
90 glBlendFuncSeparate(GL_DST_ALPHA, GL_ONE, GL_DST_ALPHA, GL_ZERO);
91 else
92 glBlendFuncSeparate(GL_ONE, GL_SRC_ALPHA, GL_DST_ALPHA, GL_ZERO);
93
94 glDisable(GL_DEPTH_TEST);
95 glDepthMask(GL_FALSE);
96
97 mat4 inv_PV = inverse(ctx.get_projection_matrix()*ctx.get_modelview_matrix());
98 vec4 p_lb = inv_PV * vec4(-1,-1, 0, 1);
99 vec4 p_rb = inv_PV * vec4( 1,-1, 0, 1);
100 vec4 p_rt = inv_PV * vec4( 1, 1, 0, 1);
101 vec4 p_lt = inv_PV * vec4(-1, 1, 0, 1);
102
103 glBegin(GL_QUADS);
104 glTexCoord2f(0,0);
105 glVertex4fv(p_lb.data());
106 glTexCoord2f(1,0);
107 glVertex4fv(p_rb.data());
108 glTexCoord2f(1,1);
109 glVertex4fv(p_rt.data());
110 glTexCoord2f(0,1);
111 glVertex4fv(p_lt.data());
112 glEnd();
113
114 tex.disable(ctx);
115 glPopAttrib();
116}
117
119int gl_transparent_renderer::render_transparent(context& ctx, int max_nr_layers, int tex_unit)
120{
121 glPushAttrib(GL_DEPTH_BUFFER_BIT|GL_ENABLE_BIT|GL_SCISSOR_BIT);
122 glDisable(GL_SCISSOR_TEST);
123
124 int nr_fragments, nr_layers = 0;
125 GLint vp[4];
126 glGetIntegerv(GL_VIEWPORT, vp);
127 GLint vp_off[4] = { 0,0, vp[2], vp[3] };
128 if (front_to_back) {
129 glDepthFunc(GL_LESS);
130 glClearDepth(1);
131 // use current depth buffer to initialize depth buffer of fbo
132 depth_buffer.replace_from_buffer(ctx,0,0,vp[0],vp[1],vp[2],vp[3],0);
133 // render first layer to layer texture
134 glClearColor(0, 0, 0, 1);
135 fb.enable(ctx, 0);
136 // render without a shadow test
137 glClear(GL_COLOR_BUFFER_BIT);
138 render_callback(ctx);
139 fb.disable(ctx);
140
141// layer_tex.write_to_file(ctx, "S:/temp/debug/layer_ 0.bmp");
142// depth_buffer.write_to_file(ctx, "S:/temp/debug/depth_buffer_ 0.bmp", -1, 2.0f);
143
144 // iterate layers
145 do {
146 fb.enable(ctx,1);
147 if (nr_layers == 0)
148 glClear(GL_COLOR_BUFFER_BIT);
149 blend_texture_over_viewport(ctx, layer_tex);
150 fb.disable(ctx);
151// color_tex.write_to_file(ctx, "S:/temp/debug/color_" + cgv::utils::to_string(nr_layers, 2) + ".bmp");
152
153 // check for termination
154 if (++nr_layers > max_nr_layers)
155 break;
156
157 // enable frame buffer object
158 fb.enable(ctx, 0);
160 fb.disable(ctx);
161 depth_buffer.replace_from_buffer(ctx,0,0,vp[0],vp[1],vp[2],vp[3],0);
162
163 fb.enable(ctx, 0);
164 // draw and use first layer (no depth peeling necessary)
165 glClear(GL_COLOR_BUFFER_BIT);
166 // create occlusion query, that counts the number of rendered fragments
167 glGenQueriesARB(1, &query);
168 glBeginQueryARB(GL_SAMPLES_PASSED_ARB, query);
169
170 render_callback_2(ctx, depth_texture);
171 glEndQueryARB(GL_SAMPLES_PASSED_ARB);
172 // evaluation of occlusion query
173 GLuint nr_drawn_fragments;
174 glGetQueryObjectuivARB(query, GL_QUERY_RESULT_ARB, &nr_drawn_fragments);
175 glDeleteQueriesARB(1, &query);
176 query = -1;
177 nr_fragments = nr_drawn_fragments;
178
179 fb.disable(ctx);
180// layer_tex.write_to_file(ctx, "S:/temp/debug/layer_"+cgv::utils::to_string(nr_layers,2)+".bmp");
181// depth_buffer.write_to_file(ctx, "S:/temp/debug/depth_buffer_" + cgv::utils::to_string(nr_layers,2) + ".bmp", -1, 2.0f);
182// std::cout << "layer " << nr_layers << " : " << nr_fragments << std::endl;
183 } while (nr_fragments > 0);
184
185 front_to_back = false;
187 front_to_back = true;
188
189 }
190 else {
191 glDepthFunc(GL_GREATER);
192 glClearDepth(0);
193 // init shadow depth map to current depth buffer
195 fb.enable(ctx, 0);
196 // render with shadow test
197 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
198 begin_layer(ctx);
199 render_callback(ctx);
200 end_layer(ctx);
201 fb.disable(ctx);
202
203 // iterate layers
204 do {
205 blend_texture_over_viewport(ctx, layer_tex);
206
207 // check for termination
208 if (++nr_layers > max_nr_layers)
209 break;
210
211 // enable frame buffer object
212 fb.enable(ctx, 0);
214 // draw and use first layer (no depth peeling necessary)
215 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
216 begin_layer(ctx);
217 render_callback(ctx);
218 nr_fragments = end_layer(ctx);
219 fb.disable(ctx);
220 } while (nr_fragments > 0);
221 }
222
223 glPopAttrib();
224 return nr_layers;
225}
226
229{
231 fb.destruct(ctx);
232 layer_tex.destruct(ctx);
233 color_tex.destruct(ctx);
234 depth_buffer.destruct(ctx);
235}
236
237 }
238 }
239}
void set_height(size_t _height)
set the resolution in the second dimension, add dimensions if necessary
void set_width(size_t _width)
set the resolution in the first dimension, add dimensions if necessary
size_t get_width() const
return the resolution in the first dimension, or 1 if not defined
size_t get_height() const
return the resolution in the second dimension, or 1 if not defined
T * data()
return a pointer to the underlying array serving as component storage
Definition fvec.h:160
base class for all drawables, which is independent of the used rendering API.
Definition context.h:672
virtual dmat4 get_projection_matrix() const =0
return homogeneous 4x4 projection matrix, which transforms from eye to clip space
virtual dmat4 get_modelview_matrix() const =0
return homogeneous 4x4 viewing matrix, which transforms from world to eye space
bool create(const context &ctx, int _width=-1, int _height=-1)
create framebuffer if extension is supported, otherwise return false.
bool is_complete(const context &ctx) const
check for completeness, if not complete, get the reason in last_error
int get_width() const
return the width
void destruct(const context &ctx)
destruct the framebuffer objext
bool attach(const context &ctx, const render_buffer &rb, int i=0)
attach render buffer to depth buffer if it is a depth buffer, to stencil if it is a stencil buffer or...
bool enable(context &ctx, int i0=-1, int i1=-1, int i2=-1, int i3=-1, int i4=-1, int i5=-1, int i6=-1, int i7=-1, int i8=-1, int i9=-1, int i10=-1, int i11=-1, int i12=-1, int i13=-1, int i14=-1, int i15=-1)
enable the framebuffer either with all color attachments if no arguments are given or if arguments ar...
bool disable(context &ctx)
disable the framebuffer object
int get_height() const
return the height
OpenGL helper class to simplify depth peeling.
void copy_depth_buffer(context &ctx)
copies the current depth buffer to the second depth buffer, what is typically done before peeling a l...
bool is_front_to_back() const
return whether the mode is front to back
void begin_layer(context &ctx, int tex_unit=-1)
start to extract the next layer. Within begin_layer and end_layer the following OpenGL features are u...
virtual bool init(context &ctx)
checks for extensions and init depth peeler, return success
unsigned int end_layer(context &ctx)
finish the layer and return the number of drawn fragments in the layer. All OpenGL settings are resto...
virtual void destruct(context &ctx)
destruct the depth peeler
virtual void init_frame(context &ctx)
call this after the viewport has been set and before the first call to copy_depth_buffer or begin_lay...
cgv::signal::signal< context &, texture & > render_callback_2
signal called to render the transparent content for second and further layers with additional depth t...
int render_transparent(context &ctx, int max_nr_layers, int tex_unit=-1)
perform transparent rendering by considering a maximum of the specified number of depth layers
void init_frame(context &ctx)
configure frame buffer and textures
void blend_texture_over_viewport(context &ctx, texture &tex)
renders the given texture over the current viewport
cgv::signal::signal< context & > render_callback
signal called to render the transparent content for first layer without additional depth test
bool init(context &ctx)
checks for extensions and init depth peeler, return success
void create_and_attach_texture(context &ctx, texture &tex, int w, int h, int i=-1)
ensure that texture has the correct dimensions and is created
gl_transparent_renderer(bool front_to_back=true, float _depth_bias=0.001)
construct uninitialized depth peeler
texture color_tex
texture used as color buffer in front to back mode to blend together all transparent layers before bl...
void destruct(context &ctx)
destruct the transparent renderer
std::string last_error
a string that contains the last error, which is only set by the init method
virtual bool is_created() const
return whether component has been created
Definition context.cxx:2188
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 replace_from_buffer(const context &ctx, int x, int y, int x_buffer, int y_buffer, int width, int height, int level=-1)
replace a block within a 2d texture from the current read buffer.
Definition texture.cxx:672
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
the cgv namespace
Definition print.h:11
cgv::math::fvec< float, 4 > vec4
declare type of 4d single precision floating point vectors (used for homogeneous coordinates)
Definition fvec.h:663