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
5
6namespace cgv {
7 namespace render {
8 namespace gl {
9
10
12gl_transparent_renderer::gl_transparent_renderer(bool front_to_back, float _depth_bias)
13 : gl_depth_peeler(front_to_back, _depth_bias),
14 layer_tex("uint8[R,G,B,A]",TF_NEAREST,TF_NEAREST),
15 color_tex("uint8[R,G,B,A]",TF_NEAREST,TF_NEAREST),
16 depth_buffer("[D]", TF_NEAREST, TF_NEAREST)
17{
18}
19
22{
23 if (!gl_depth_peeler::init(ctx))
24 return false;
25 if (!GLEW_EXT_framebuffer_object) {
26 last_error = "gl_transparent_renderer::init -> framebuffer objects not supported";
27 return false;
28 }
29 return true;
30}
31
34{
35 if (tex.is_created() && tex.get_width() == w && tex.get_height() == h)
36 return;
37
38 // depth buffer
39 if (tex.is_created())
40 tex.destruct(ctx);
41 tex.set_width(w);
42 tex.set_height(h);
43 tex.create(ctx);
44
45 fb.attach(ctx,tex,0,i);
46}
47
48
49
52{
53 // init the peeler for the frame
54 GLint vp[4];
55 glGetIntegerv(GL_VIEWPORT, vp);
56 // query size of view
57 int w = vp[2];
58 int h = vp[3];
59
60 // ensure that frame buffer and depth texture are created and have correct dimensions
61 if (!fb.is_created() || fb.get_width() != w || fb.get_height() != h) {
62 // frame buffer
63 if (fb.is_created())
64 fb.destruct(ctx);
65 fb.create(ctx,w,h);
66 }
67 create_and_attach_texture(ctx, depth_buffer, w, h);
68 create_and_attach_texture(ctx, layer_tex, w, h, 0);
69 if (is_front_to_back())
71 else
73 if (!fb.is_complete(ctx)) {
74 std::cerr << "gl_transparent_renderer::init_frame -> framebuffer not complete" << std::endl;
75 abort();
76 }
78}
79
82{
83 // blend layer over global frame buffer
84 glPushAttrib(GL_TEXTURE_BIT|GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
85 tex.enable(ctx);
86
87 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
88
89 glEnable(GL_BLEND);
90 if (front_to_back)
91 glBlendFuncSeparate(GL_DST_ALPHA, GL_ONE, GL_DST_ALPHA, GL_ZERO);
92 else
93 glBlendFuncSeparate(GL_ONE, GL_SRC_ALPHA, GL_DST_ALPHA, GL_ZERO);
94
95 glDisable(GL_DEPTH_TEST);
96 glDepthMask(GL_FALSE);
97
98 mat4 inv_PV = inv(ctx.get_projection_matrix()*ctx.get_modelview_matrix());
99 vec4 p_lb = inv_PV * vec4(-1,-1, 0, 1);
100 vec4 p_rb = inv_PV * vec4( 1,-1, 0, 1);
101 vec4 p_rt = inv_PV * vec4( 1, 1, 0, 1);
102 vec4 p_lt = inv_PV * vec4(-1, 1, 0, 1);
103
104 glBegin(GL_QUADS);
105 glTexCoord2f(0,0);
106 glVertex4fv(p_lb.data());
107 glTexCoord2f(1,0);
108 glVertex4fv(p_rb.data());
109 glTexCoord2f(1,1);
110 glVertex4fv(p_rt.data());
111 glTexCoord2f(0,1);
112 glVertex4fv(p_lt.data());
113 glEnd();
114
115 tex.disable(ctx);
116 glPopAttrib();
117}
118
120int gl_transparent_renderer::render_transparent(context& ctx, int max_nr_layers, int tex_unit)
121{
122 glPushAttrib(GL_DEPTH_BUFFER_BIT|GL_ENABLE_BIT|GL_SCISSOR_BIT);
123 glDisable(GL_SCISSOR_TEST);
124
125 int nr_fragments, nr_layers = 0;
126 GLint vp[4];
127 glGetIntegerv(GL_VIEWPORT, vp);
128 GLint vp_off[4] = { 0,0, vp[2], vp[3] };
129 if (front_to_back) {
130 glDepthFunc(GL_LESS);
131 glClearDepth(1);
132 // use current depth buffer to initialize depth buffer of fbo
133 depth_buffer.replace_from_buffer(ctx,0,0,vp[0],vp[1],vp[2],vp[3],0);
134 // render first layer to layer texture
135 glClearColor(0, 0, 0, 1);
136 fb.enable(ctx, 0);
137 // render without a shadow test
138 glClear(GL_COLOR_BUFFER_BIT);
139 render_callback(ctx);
140 fb.disable(ctx);
141
142// layer_tex.write_to_file(ctx, "S:/temp/debug/layer_ 0.bmp");
143// depth_buffer.write_to_file(ctx, "S:/temp/debug/depth_buffer_ 0.bmp", -1, 2.0f);
144
145 // iterate layers
146 do {
147 fb.enable(ctx,1);
148 if (nr_layers == 0)
149 glClear(GL_COLOR_BUFFER_BIT);
150 blend_texture_over_viewport(ctx, layer_tex);
151 fb.disable(ctx);
152// color_tex.write_to_file(ctx, "S:/temp/debug/color_" + cgv::utils::to_string(nr_layers, 2) + ".bmp");
153
154 // check for termination
155 if (++nr_layers > max_nr_layers)
156 break;
157
158 // enable frame buffer object
159 fb.enable(ctx, 0);
161 fb.disable(ctx);
162 depth_buffer.replace_from_buffer(ctx,0,0,vp[0],vp[1],vp[2],vp[3],0);
163
164 fb.enable(ctx, 0);
165 // draw and use first layer (no depth peeling necessary)
166 glClear(GL_COLOR_BUFFER_BIT);
167 // create occlusion query, that counts the number of rendered fragments
168 glGenQueriesARB(1, &query);
169 glBeginQueryARB(GL_SAMPLES_PASSED_ARB, query);
170
171 render_callback_2(ctx, depth_texture);
172 glEndQueryARB(GL_SAMPLES_PASSED_ARB);
173 // evaluation of occlusion query
174 GLuint nr_drawn_fragments;
175 glGetQueryObjectuivARB(query, GL_QUERY_RESULT_ARB, &nr_drawn_fragments);
176 glDeleteQueriesARB(1, &query);
177 query = -1;
178 nr_fragments = nr_drawn_fragments;
179
180 fb.disable(ctx);
181// layer_tex.write_to_file(ctx, "S:/temp/debug/layer_"+cgv::utils::to_string(nr_layers,2)+".bmp");
182// depth_buffer.write_to_file(ctx, "S:/temp/debug/depth_buffer_" + cgv::utils::to_string(nr_layers,2) + ".bmp", -1, 2.0f);
183// std::cout << "layer " << nr_layers << " : " << nr_fragments << std::endl;
184 } while (nr_fragments > 0);
185
186 front_to_back = false;
188 front_to_back = true;
189
190 }
191 else {
192 glDepthFunc(GL_GREATER);
193 glClearDepth(0);
194 // init shadow depth map to current depth buffer
196 fb.enable(ctx, 0);
197 // render with shadow test
198 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
199 begin_layer(ctx);
200 render_callback(ctx);
201 end_layer(ctx);
202 fb.disable(ctx);
203
204 // iterate layers
205 do {
206 blend_texture_over_viewport(ctx, layer_tex);
207
208 // check for termination
209 if (++nr_layers > max_nr_layers)
210 break;
211
212 // enable frame buffer object
213 fb.enable(ctx, 0);
215 // draw and use first layer (no depth peeling necessary)
216 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
217 begin_layer(ctx);
218 render_callback(ctx);
219 nr_fragments = end_layer(ctx);
220 fb.disable(ctx);
221 } while (nr_fragments > 0);
222 }
223
224 glPopAttrib();
225 return nr_layers;
226}
227
230{
232 fb.destruct(ctx);
233 layer_tex.destruct(ctx);
234 color_tex.destruct(ctx);
235 depth_buffer.destruct(ctx);
236}
237
238 }
239 }
240}
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()
cast into array. This allows calls like glVertex<N><T>v(p.data()) instead of glVertex<N><T,...
Definition fvec.h:181
base class for all drawables, which is independent of the used rendering API.
Definition context.h:621
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:2046
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:208
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:667
bool disable(const context &ctx)
disable texture and restore state from before last enable call
Definition texture.cxx:756
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:745
bool destruct(const context &ctx)
destruct the texture and free texture memory and handle
Definition texture.cxx:730
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:671