GCC Code Coverage Report


Directory: ./
File: lib/geogram_gfx/full_screen_effects/unsharp_masking.cpp
Date: 2026-09-07 02:37:58
Exec Total Coverage
Lines: 0 113 0.0%
Functions: 0 10 0.0%
Branches: 0 50 0.0%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2000-2022 Inria
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * * Neither the name of the ALICE Project-Team nor the names of its
14 * contributors may be used to endorse or promote products derived from this
15 * software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Contact: Bruno Levy
30 *
31 * https://www.inria.fr/fr/bruno-levy
32 *
33 * Inria,
34 * Domaine de Voluceau,
35 * 78150 Le Chesnay - Rocquencourt
36 * FRANCE
37 *
38 */
39
40
41 #include <geogram_gfx/full_screen_effects/unsharp_masking.h>
42 #include <geogram_gfx/basic/GLSL.h>
43 #include <geogram/basic/logger.h>
44 #include <geogram/bibliography/bibliography.h>
45
46 // Requirements for Android compile are the same
47 // as for Emscripten.
48 // TODO: something cleaner.
49 #ifdef GEO_OS_ANDROID
50 #define GEO_OS_EMSCRIPTEN
51 #endif
52
53 namespace GEO {
54
55 UnsharpMaskingImpl::UnsharpMaskingImpl() {
56 unsharp_masking_program_ = 0;
57 blur_program_ = 0;
58 positive_shadows_ = true;
59 contrast_ = 50;
60 intensity_ = 50;
61 halos_ = true;
62 blur_width_ = 1;
63 geo_cite("DBLP:journals/tog/LuftCD06");
64 }
65
66 UnsharpMaskingImpl::~UnsharpMaskingImpl() {
67 if (unsharp_masking_program_ != 0) {
68 glDeleteProgram(unsharp_masking_program_);
69 }
70 if (blur_program_ != 0) {
71 glDeleteProgram(blur_program_);
72 }
73 }
74
75 double UnsharpMaskingImpl::required_GLSL_version() const {
76 #ifdef GEO_OS_EMSCRIPTEN
77 return 1.0;
78 #else
79 return 1.3;
80 #endif
81 }
82
83 void UnsharpMaskingImpl::initialize(index_t w, index_t h) {
84 FullScreenEffectImpl::initialize(w,h);
85 if(!OK()) {
86 return;
87 }
88
89 #if defined(GEO_OS_EMSCRIPTEN) || defined(GEO_OS_ANDROID)
90 // GL_R16F gives a different result (stripes) on Emscripten
91 // Note: does not work on Android for now.
92 # if defined(GEO_OS_EMSCRIPTEN) && !defined(GEO_WEBGL2)
93 const GLint internal_format = GL_RGBA;
94 # else
95 const GLint internal_format = GL_R32F;
96 # endif
97 #else
98 // Note: I do not know what GL_R16 corresponds to internally,
99 // it is different from GL_R16F and GL_R16I and GL_R16UI
100 // (different behavior when I use them).
101 const GLint internal_format = GL_R16;
102 #endif
103
104 if(!blur_1_.initialize(
105 width(), height(), false, internal_format
106 )
107 ) {
108 Logger::err("UnsharpM")
109 << "blur_1_ FBO is not initialized" << std::endl;
110 }
111 if(!blur_2_.initialize(
112 width(), height(), false, internal_format
113 )
114 ) {
115 Logger::err("UnsharpM")
116 << "blur_2_ FBO is not initialized" << std::endl;
117 }
118
119 // Shader sources are embedded in source code,
120 // Initial sourcecode is in:
121 // geogram_gfx/GLUP/shaders/fullscreen
122 unsharp_masking_program_ = GLSL::compile_program_with_includes_no_link(
123 this,
124 "//stage GL_VERTEX_SHADER\n"
125 "//import <fullscreen/vertex_shader.h>\n",
126 "//stage GL_FRAGMENT_SHADER\n"
127 "//import <fullscreen/unsharp_masking_fragment_shader.h>\n"
128 );
129
130
131 glBindAttribLocation(unsharp_masking_program_, 0, "vertex_in");
132 glBindAttribLocation(unsharp_masking_program_, 1, "tex_coord_in");
133
134 GLSL::link_program(unsharp_masking_program_);
135
136 GLSL::set_program_uniform_by_name(
137 unsharp_masking_program_, "blur_texture", 0
138 );
139 GLSL::set_program_uniform_by_name(
140 unsharp_masking_program_, "depth_texture", 1
141 );
142
143 // Shader sources are embedded in source code,
144 // Initial sourcecode is in:
145 // geogram_gfx/GLUP/shaders/fullscreen
146 blur_program_ = GLSL::compile_program_with_includes_no_link(
147 this,
148 "//stage GL_VERTEX_SHADER\n"
149 "//import <fullscreen/vertex_shader.h>\n",
150 "//stage GL_FRAGMENT_SHADER\n"
151 "//import <fullscreen/blur_fragment_shader.h>\n"
152 );
153
154 glBindAttribLocation(blur_program_, 0, "vertex_in");
155 glBindAttribLocation(blur_program_, 1, "tex_coord_in");
156
157 GLSL::link_program(blur_program_);
158
159 GLSL::set_program_uniform_by_name(
160 blur_program_, "source_tex", 0
161 );
162 GLSL::set_program_uniform_by_name(
163 blur_program_, "blur_width", 2.0f
164 );
165 if(ES_profile_) {
166 GLSL::set_program_uniform_by_name(
167 blur_program_, "source_tex_size",
168 float(blur_1_.width), float(blur_1_.height)
169 );
170 }
171 update();
172 }
173
174 void UnsharpMaskingImpl::pre_render(index_t w, index_t h) {
175 FullScreenEffectImpl::pre_render(w,h);
176 }
177
178 void UnsharpMaskingImpl::resize(index_t width, index_t height) {
179 blur_1_.resize(width, height);
180 blur_2_.resize(width, height);
181 if(ES_profile_) {
182 GLSL::set_program_uniform_by_name(
183 blur_program_, "source_tex_size",
184 float(width), float(height)
185 );
186 }
187 FullScreenEffectImpl::resize(width, height);
188 }
189
190 void UnsharpMaskingImpl::blur() {
191 glViewport(0, 0, GLsizei(width()), GLsizei(height()));
192
193 // Horizontal blur: ZBuffer -> blur_2_
194 draw_FBO_.bind_depth_buffer_as_texture();
195 blur_2_.bind_as_framebuffer();
196 GLSL::set_program_uniform_by_name(blur_program_, "vertical", false);
197 glUseProgram(blur_program_);
198 draw_unit_textured_quad();
199 blur_2_.unbind();
200 draw_FBO_.unbind();
201
202 // Vertical blur: blur_2_ -> blur_1_
203 blur_1_.bind_as_framebuffer();
204 blur_2_.bind_as_texture();
205 GLSL::set_program_uniform_by_name(blur_program_, "vertical", true);
206 glUseProgram(blur_program_);
207 draw_unit_textured_quad();
208 blur_1_.unbind();
209 blur_2_.unbind();
210
211 glUseProgram(0);
212 }
213
214 void UnsharpMaskingImpl::display_final_texture() {
215 glBindFramebuffer(GL_FRAMEBUFFER, main_framebuffer_id_);
216
217 glDisable(GL_DEPTH_TEST);
218 glEnable(GL_BLEND);
219 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
220 glViewport(0, 0, GLsizei(width()), GLsizei(height()));
221
222 glUseProgram(unsharp_masking_program_);
223 glActiveTexture(GL_TEXTURE1);
224 draw_FBO_.bind_depth_buffer_as_texture();
225 glActiveTexture(GL_TEXTURE0);
226 blur_1_.bind_as_texture();
227 draw_unit_textured_quad();
228 glUseProgram(0);
229 draw_FBO_.unbind();
230
231 glEnable(GL_DEPTH_TEST);
232 glDisable(GL_BLEND);
233 blur_1_.unbind();
234 }
235
236 void UnsharpMaskingImpl::post_render() {
237 // Copies the content of draw_FBO_ to the screen.
238 FullScreenEffectImpl::post_render();
239
240 // Computes effect and composites effect with
241 // previously rendered image.
242 blur();
243 display_final_texture();
244 reset_alpha();
245 }
246
247 void UnsharpMaskingImpl::update() {
248 if(!OK()) {
249 return;
250 }
251 if(unsharp_masking_program_ != 0) {
252 float fx = 1.0f - float(contrast_)/100.0f;
253 geo_clamp(fx, 0.0f, 1.0f);
254 GLSL::set_program_uniform_by_name(
255 unsharp_masking_program_,
256 "shadows_gamma", fx
257 );
258 GLSL::set_program_uniform_by_name(
259 unsharp_masking_program_,
260 "shadows_intensity", float(intensity_) / 400.0f
261 );
262 GLSL::set_program_uniform_by_name(
263 unsharp_masking_program_, "shadows_halo", halos_
264 );
265 GLSL::set_program_uniform_by_name(
266 unsharp_masking_program_, "do_positive_shadows",
267 positive_shadows_
268 );
269 }
270 if(blur_program_ != 0) {
271 GLSL::set_program_uniform_by_name(
272 blur_program_, "blur_width", float(blur_width_)
273 );
274 }
275 }
276 }
277