PICCANTE  0.4
The hottest HDR imaging library!
filter_reinhard_single_pass.hpp
Go to the documentation of this file.
1 /*
2 
3 PICCANTE
4 The hottest HDR imaging library!
5 http://vcg.isti.cnr.it/piccante
6 
7 Copyright (C) 2014
8 Visual Computing Laboratory - ISTI CNR
9 http://vcg.isti.cnr.it
10 First author: Francesco Banterle
11 
12 This Source Code Form is subject to the terms of the Mozilla Public
13 License, v. 2.0. If a copy of the MPL was not distributed with this
14 file, You can obtain one at http://mozilla.org/MPL/2.0/.
15 
16 */
17 
18 #ifndef PIC_GL_FILTERING_REINHARD_TMO_SINGLE_PASS_HPP
19 #define PIC_GL_FILTERING_REINHARD_TMO_SINGLE_PASS_HPP
20 
21 #include "../../base.hpp"
22 
23 #include "../../util/vec.hpp"
24 #include "../../util/std_util.hpp"
25 
26 #include "../../gl/filtering/filter.hpp"
27 #include "../../util/file_lister.hpp"
28 #include "../../gl/point_samplers/sampler_random_m.hpp"
29 
30 namespace pic {
31 
36 {
37 protected:
40 
41  //tmo
42  float alpha;
43 
44  //Random numbers tile
46 
47  void initShaders();
48  void FragmentShader();
49 
50 public:
51  float Lwa;
52 
59  FilterGLReinhardSinglePass(float alpha, float phi);
60 
62 
66  void releaseAux()
67  {
69  delete_s(ms);
70  }
71 
77  void update(float sigma_s, float sigma_r, float Lwa);
78 };
79 
81 {
82  this->sigma_s = -1.0f;
83  this->sigma_r = -1.0f;
84  this->alpha = alpha;
85  float epsilon = 0.05f;
86  float s_max = 8.0f;
87  float sigma_s = 1.6f;
88  float sigma_r = epsilon / 2.0f;
89 
90  this->sigmoid_constant = (powf(2.0f, phi) * alpha / (s_max * s_max)) * epsilon;
91 
92  ms = NULL;
93  imageRand = NULL;
94 
96  initShaders();
97 
98  update(sigma_s, sigma_r, 1.0f);
99 }
100 
102 {
103  release();
104 }
105 
107 {
109  (
110  uniform sampler2D u_tex;
111  uniform sampler2D u_tex_col;
112  uniform isampler2D u_poisson;
113  uniform sampler2D u_rand;
114  uniform int nSamples;
115  uniform float sigmoid_constant;
116  uniform float sigmas2;
117  uniform float sigmar2;
118  uniform int kernelSize;
119  uniform float kernelSizef;
120  uniform float a;
121  out vec4 f_color;
122 
123  void main(void) {
124  ivec2 coordsFrag = ivec2(gl_FragCoord.xy);
125 
126  float colRef = texelFetch(u_tex, coordsFrag, 0).x;
127  float Lw = colRef;
128 
129  colRef = colRef / (colRef + sigmoid_constant);
130 
131  float shifter = texture(u_rand, gl_FragCoord.xy).x;
132  float color = 0.0;
133  float weight = 0.0;
134 
135  for(int i = 0; i < nSamples; i++) {
136  //coordinates
137  ivec3 coords = texelFetch(u_poisson, ivec2(i, shifter), 0).xyz;
138 
139  //texture fetch
140  float tmpCol = texelFetch(u_tex, coordsFrag.xy + coords.xy, 0).x;
141  tmpCol = tmpCol / (tmpCol + sigmoid_constant);
142 
143  float tmpCol2 = tmpCol - colRef;
144  float dstR = tmpCol2 * tmpCol2;
145 
146  int coordsz = coords.x * coords.x + coords.y * coords.y;
147  float tmp = exp(-dstR / sigmar2 - float(coordsz) / sigmas2);
148 
149  color += tmpCol * tmp;
150  weight += tmp;
151 
152  }
153 
154  float bilateral = weight > 0.0 ? (color / weight) : colRef;
155  bilateral = (bilateral * sigmoid_constant) / (1.0 - bilateral);
156 
157  Lw = Lw < 1e-9 ? 1e-9 : Lw;
158  vec3 color_hdr = texelFetch(u_tex_col, coordsFrag, 0).xyz / Lw;
159 
160  float Ld = (Lw * a) / (bilateral * a + 1.0);
161 
162  f_color = vec4(color_hdr * Ld, 1.0);
163  }
164  );
165 
166 }
167 
169 {
170  technique.initStandard("330", vertex_source, fragment_source, "FilterGLReinhardSinglePass");
171 }
172 
173 PIC_INLINE void FilterGLReinhardSinglePass::update(float sigma_s, float sigma_r, float Lwa)
174 {
175  bool flag = false;
176 
177  if(sigma_s > 0.0f) {
178  flag = (this->sigma_s != sigma_s);
179  this->sigma_s = sigma_s;
180  }
181 
182  if(sigma_r > 0.0f) {
183  flag = flag || (this->sigma_r != sigma_r);
184  this->sigma_r = sigma_r;
185  }
186 
187  this->Lwa = Lwa > 0.0f ? Lwa : this->Lwa;
188 
189  //precomputation of the Gaussian Kernel
190  int kernelSize = PrecomputedGaussian::getKernelSize(this->sigma_s);
191  int halfKernelSize = kernelSize >> 1;
192 
193  if(imageRand == NULL) {
194  imageRand = new ImageGL(1, 128, 128, 1, IMG_CPU, GL_TEXTURE_2D);
195  imageRand->setRand(1);
197  *imageRand -= 0.5f;
198  }
199 
200  if(flag) {
201  Vec2i window = Vec2i(halfKernelSize, halfKernelSize);
202 
203  if(ms == NULL) {
204  int nSamplers = 1;
205 
206  //Poisson samples
207  #ifdef PIC_DEBUG
208  printf("Window: %d\n", halfKernelSize);
209  #endif
210  ms = new MRSamplersGL<2>(ST_BRIDSON, window, halfKernelSize, 1,
211  nSamplers);
212  ms->generateTexture();
213  } else {
214  ms->updateGL(window, halfKernelSize);
215  param.clear();
216  }
217 
218  if(param.empty()) {
219  param.push_back(imageRand);
220  param.push_back(ms->getImage());
221  }
222  }
223 
224  //shader update
225  float sigmas2 = 2.0f * this->sigma_s * this->sigma_s;
226  float sigmar2 = 2.0f * this->sigma_r * this->sigma_r;
227 
228  technique.bind();
229  technique.setUniform1i("u_tex_col", 0);
230  technique.setUniform1i("u_tex", 1);
231  technique.setUniform1i("u_rand", 2);
232  technique.setUniform1i("u_poisson", 3);
233 
234  technique.setUniform1f("sigmas2", sigmas2);
236  technique.setUniform1f("sigmoid_constant", sigmoid_constant);
237 
238  technique.setUniform1f("sigmar2", sigmar2);
239  technique.setUniform1i("kernelSize", kernelSize);
240  technique.setUniform1f("kernelSizef", float(kernelSize));
241  technique.setUniform1i("nSamples", ms->nSamples >> 1);
242  technique.unbind();
243 }
244 
245 } // end namespace pic
246 
247 #endif /* PIC_GL_FILTERING_REINHARD_TMO_SINGLE_PASS_HPP */
248 
ImageGL * imageRand
Definition: filter_reinhard_single_pass.hpp:45
TechniqueGL technique
Definition: display.hpp:45
float alpha
Definition: filter_reinhard_single_pass.hpp:42
FilterGLReinhardSinglePass(float alpha, float phi)
FilterGLReinhardSinglePass.
static int getKernelSize(float sigma)
KernelSize computes the size of a kernel in pixel give its sigma.
Definition: precomputed_gaussian.hpp:121
T * delete_s(T *data)
delete_s
Definition: std_util.hpp:123
void bind()
bind
Definition: display.hpp:189
float Lwa
Definition: filter_reinhard_single_pass.hpp:51
#define MAKE_STRING(input_string)
Definition: image.hpp:37
The ImageGL class.
Definition: image.hpp:42
Vec< 2, int > Vec2i
Vec2i.
Definition: vec.hpp:829
float sigma_s
Definition: filter_reinhard_single_pass.hpp:38
void setUniform1f(const char *name_uniform, float value0)
SetUniform1f.
Definition: display.hpp:247
void update(float sigma_s, float sigma_r, float Lwa)
update
void updateGL(Vec< N, int > window, int nSamples)
updateGL
Definition: sampler_random_m.hpp:129
The FilterGL class.
Definition: filter.hpp:35
void setRand(unsigned int seed)
setRand
Definition: filter_radial_basis_function.hpp:1392
GLuint generateTexture()
generateTexture
Definition: sampler_random_m.hpp:151
The FilterGL class.
Definition: display.hpp:35
The MRSamplersGL class.
Definition: sampler_random_m.hpp:45
#define PIC_INLINE
Definition: base.hpp:33
The ImageGL class.
Definition: display.hpp:42
The Vec class.
Definition: display.hpp:35
bool initStandard(std::string version_number, std::string vertex_shader_source, std::string fragment_shader_source, std::string name)
initStandard
Definition: display.hpp:114
ImageGLVec param
Definition: display.hpp:49
MRSamplersGL< 2 > * ms
Definition: filter_reinhard_single_pass.hpp:39
float sigma_r
Definition: filter_reinhard_single_pass.hpp:38
Definition: point_samplers.hpp:51
void unbind()
unbind
Definition: display.hpp:197
std::string vertex_source
Definition: display.hpp:57
Definition: bilateral_separation.hpp:25
The FilterGLReinhardSinglePass class.
Definition: filter_reinhard_single_pass.hpp:35
void releaseAux()
releaseAux
Definition: filter_reinhard_single_pass.hpp:66
std::string fragment_source
Definition: display.hpp:57
int nSamples
Definition: display.hpp:53
ImageGL * getImage()
getImage
Definition: display.hpp:89
float sigmoid_constant
Definition: filter_reinhard_single_pass.hpp:38
void release()
release
Definition: display.hpp:85
void setUniform1i(const char *name_uniform, int value0)
SetUniform.
Definition: display.hpp:236
void loadFromMemory()
loadFromMemory