PICCANTE  0.4
The hottest HDR imaging library!
stroke.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_UTIL_GL_STROKE_HPP
19 #define PIC_UTIL_GL_STROKE_HPP
20 
21 #include "../../util/rasterizer.hpp"
22 #include "../../gl/image.hpp"
23 #include "../../util/gl/quad.hpp"
24 #include "../../util/gl/technique.hpp"
25 
26 namespace pic {
27 
28 //TODO: removing immediate mode
29 
33 class StrokeGL
34 {
35 protected:
38  float size, rSize;
39  float color[4];
40  float tmpColor[3];
41 
43 
44  std::vector<float> positions;
45 
48 
49 public:
50  float annotation;
51 
59  StrokeGL(int width, int height, int brushSize, float *color);
60 
61  ~StrokeGL();
62 
66  void initShaders();
67 
71  void Resample();
72 
76  void Reset();
77 
83  void Insert2DPoint(int x, int y);
84 
88  void RenderGL();
89 
93  void RenderAnnotationGL();
94 
100  void RenderBrushGL(int x, int y);
101 
106  unsigned int Size()
107  {
108  return (unsigned int)(positions.size());
109  }
110 
115  void bindCol(float val)
116  {
117  memcpy(tmpColor, color, 3 * sizeof(float));
118  color[0] = color[1] = color[2] = val;
119  }
120 
124  void unBindCol()
125  {
126  memcpy(color, tmpColor, 3 * sizeof(float));
127  }
128 
132  void Straightner()
133  {
134  if(positions.size() > 3) {
135  float x0 = positions[0];
136  float y0 = positions[1];
137 
138  int n = int(positions.size()) - 2;
139  float x1 = positions[n];
140  float y1 = positions[n + 1];
141 
142  positions.clear();
143  positions.push_back(x0);
144  positions.push_back(y0);
145  positions.push_back(x1);
146  positions.push_back(y1);
147  }
148  }
149 };
150 
151 PIC_INLINE StrokeGL::StrokeGL(int width, int height, int brushSize = 128,
152  float *color = NULL)
153 {
154  annotation = 1.0f;
155 
156 
157  this->width = width;
158  this->height = height;
159 
160  if(brushSize > 1) {
161  this->brushSize = brushSize;
162  } else {
163  this->brushSize = 2;
164  }
165 
166  int halfBrushSize = this->brushSize >> 1;
167 
168  float halfBrushSizeXf = float(halfBrushSize) / float(width);
169  float halfBrushSizeYf = float(halfBrushSize) / float(height);
170 
171  #ifdef PIC_DEBUG
172  printf("%f %f\n", halfBrushSizeXf, halfBrushSizeYf);
173  #endif
174 
175  this->quad = new QuadGL(true, halfBrushSizeXf, halfBrushSizeYf);
176 
177  size = 4.0f;
178  rSize = size / float(MAX(width, height));
179 
180  shape = new ImageGL(1, this->brushSize, this->brushSize, 1, IMG_CPU, GL_TEXTURE_2D);
182  shape->generateTextureGL(GL_TEXTURE_2D, false);
183 
184  if(color != NULL) {
185  for(int i = 0; i < 3; i++) {
186  this->color[i] = color[i];
187  }
188  } else {
189  this->color[0] = this->color[1] = this->color[2] = 1.0f;
190  }
191 
192  initShaders();
193 }
194 
196 {
197  if(shape != NULL) {
198  delete shape;
199  }
200 
201  shape = NULL;
202 }
203 
205 {
206  //common vertex program
207  std::string vertex_source = MAKE_STRING
208  (
209  in vec2 a_position;
210  in vec2 a_tex_coord;
211  uniform vec2 shift_position;
212  out vec2 v_tex_coord;
213 
214  void main(void) {
215  v_tex_coord = a_tex_coord;
216  gl_Position = vec4(a_position + shift_position, 0.0, 1.0);
217  }
218  );
219 
220  //render
221  std::string fragment_source_brush = MAKE_STRING
222  (
223  uniform sampler2D u_tex;
224  uniform vec4 current_color;
225  in vec2 v_tex_coord;
226  out vec4 f_color;
227 
228  void main(void) {
229  float shape = texture2D(u_tex, v_tex_coord).x;
230  f_color = vec4(current_color * shape);
231  }
232  );
233 
234  brushProgram.init("330", vertex_source, fragment_source_brush);
235  brushProgram.printLog("Brush - StrokeGL");
236 
237  brushProgram.bind();
238  brushProgram.setAttributeIndex("a_position", 0);
239  brushProgram.setAttributeIndex("a_tex_coord", 1);
241  brushProgram.link();
243 
244  brushProgram.bind();
245  brushProgram.setUniform1i("u_tex", 0);
246  brushProgram.setUniform2f("shift_position", 0.0f, 0.0f);
247  brushProgram.setUniform4f("current_color", 1.0f, 1.0f, 1.0f, 1.0f);
249 
250  //annotation
251  std::string fragment_source_annotation = MAKE_STRING
252  (
253  uniform sampler2D u_tex;
254  uniform float annotation;
255  in vec2 v_tex_coord;
256  out vec4 f_color;
257 
258  void main(void) {
259  float shape = texture2D(u_tex, v_tex_coord).x;
260  float shapeVal = shape * annotation;
261  f_color = vec4(shapeVal, shapeVal, shapeVal, shape);
262  }
263  );
264 
265  annotationProgram.init("330", vertex_source, fragment_source_annotation);
266  annotationProgram.printLog("Brush (Annotation) - StrokeGL");
267 
269  annotationProgram.setAttributeIndex("a_position", 0);
270  annotationProgram.setAttributeIndex("a_tex_coord", 1);
274 
276  annotationProgram.setUniform1i("u_tex", 0);
277  annotationProgram.setUniform2f("shift_position", 0.0f, 0.0f);
280 }
281 
283 {
284  if(positions.size() <= 0) {
285  return;
286  }
287 
288  bool *sampleGrid = Mask::assign(NULL, height * width, false);
289 
290  //calculate length of the path
291  float len = 0.0f;
292  float tmpLen;
293  const int n = int(positions.size()) - 2;
294  float x, y;
295  std::vector<float> lengths;
296 
297  for(int i = 0; i < n; i += 2) {
298  x = positions[i + 2] - positions[i];
299  y = positions[i + 3] - positions[i + 1];
300  tmpLen = sqrtf(x * x + y * y);
301  lengths.push_back(tmpLen);
302  len += tmpLen;
303  }
304 
305  //resample
306  std::vector<float> resampledPos;
307  resampledPos.push_back(positions[0]);
308  resampledPos.push_back(positions[1]);
309 
310  float workLen = 0.0f;
311  int nSamples = int(len / (rSize * 0.25f));
312  float deltaL = len / float(nSamples);
313 
314 #ifdef PIC_DEBUG
315  printf("Len: %f Samples: %d DeltaL: %f\n", len, nSamples, deltaL);
316 #endif
317 
318  for(int i = 1; i < nSamples; i++) {
319  workLen += deltaL;
320  unsigned int j;
321  bool test = false;
322  float tmpWork = 0.0f;
323 
324  for(j = 0; j < lengths.size(); j++) {
325  if(workLen >= tmpWork && workLen < (tmpWork + lengths[j])) {
326  test = true;
327  break;
328  }
329 
330  tmpWork += lengths[j];
331  }
332 
333  if(!test) {
334  break;
335  }
336 
337  int ind = j << 1;
338 
339  float x0 = positions[ind];
340  float y0 = positions[ind + 1];
341 
342  float x1 = positions[ind + 2];
343  float y1 = positions[ind + 3];
344 
345  float shift = (deltaL - (tmpWork - workLen)) / lengths[j];
346 
347  x = shift * (x1 - x0) + x0;
348  y = shift * (y1 - y0) + y0;
349 
350  int tmpX = CLAMP(int((x / 2.0f + 0.5f) * width), width);
351  int tmpY = CLAMP(int((y / 2.0f + 0.5f) * height), height);
352  int indSG = tmpY * width + tmpX;
353  bool tmpSampleGrid = sampleGrid[indSG];
354 
355 // float *val = ((*sampleGrid)(x/2.0f+0.5,y/2.0f+0.5f));
356 
357  if(tmpSampleGrid == false) {
358  resampledPos.push_back(x);
359  resampledPos.push_back(y);
360  sampleGrid[indSG] = true;
361  }
362 
363  //printf("%f %f %d %f\n",x,y,j,workLen);
364  workLen += deltaL;
365 
366  if(workLen > len) {
367  break;
368  }
369  }
370 
371  positions.clear();
372  positions.insert(positions.begin(), resampledPos.begin(), resampledPos.end());
373 
374  if(sampleGrid != NULL) {
375  delete[] sampleGrid;
376  }
377 }
378 
380 {
381  /*
382  float xf = -(x/float(width) -0.5f)*2.0f;
383  float yf = (y/float(height)-0.5f)*2.0f;
384  */
385  float xf = (x / float(width) - 0.5f) * 2.0f;
386  float yf = (y / float(height) - 0.5f) * 2.0f;
387 
388  positions.push_back(xf);
389  positions.push_back(yf);
390 }
391 
393 {
394  positions.clear();
395 }
396 
398 {
399  float xf = (x / float(width) - 0.5f) * 2.0f;
400  float yf = (y / float(height) - 0.5f) * 2.0f;
401 
402  glEnable(GL_BLEND);
403  glBlendFunc(GL_ONE, GL_ONE);
404 
405  glEnable(GL_TEXTURE_2D);
406 
407  glActiveTexture(GL_TEXTURE0);
408  shape->bindTexture();
409 
410 
411  brushProgram.bind();
412  if(annotation < 0.0f) {
413  brushProgram.setUniform4f("current_color", 1.0f - color[0], 1.0f - color[1], 1.0f - color[2], 1.0f);
414  } else {
415  brushProgram.setUniform4f("current_color", color[0], color[1], color[2], 0.5f);
416  }
417 
418  brushProgram.setUniform2f("shift_position", xf, yf);
419 
420  quad->Render();
421 
423 
424  shape->unBindTexture();
425 
426  glDisable(GL_BLEND);
427  glDisable(GL_TEXTURE_2D);
428 }
429 
431 {
432  glEnable(GL_BLEND);
433  glBlendFunc(GL_ONE, GL_ONE);
434  glEnable(GL_TEXTURE_2D);
435 
436  glActiveTexture(GL_TEXTURE0);
437  shape->bindTexture();
438 
439  glBindTexture(GL_TEXTURE_2D, shape->getTexture());
440 
441  brushProgram.bind();
442 
443  brushProgram.setUniform4f("current_color", color[0], color[1], color[2], 1.0f);
444  const int n = int(positions.size());
445 
446  for(int i = 0; i < n; i += 2) {
447  brushProgram.setUniform2f("shift_position", positions[i], positions[i + 1]);
448  quad->Render();
449  }
450 
452 
453  shape->unBindTexture();
454 
455  glDisable(GL_BLEND);
456  glDisable(GL_TEXTURE_2D);
457 }
458 
460 {
461  glEnable(GL_BLEND);
462  glBlendFunc(GL_ONE, GL_ONE);
463 
465 
466 #ifdef PIC_DEBUG
467  printf("Annotation value: %f\n", annotation);
468 #endif
469 
471 
472  glEnable(GL_TEXTURE_2D);
473  glActiveTexture(GL_TEXTURE0);
474  shape->bindTexture();
475 
476  const int n = int(positions.size());
477 
478  for(int i = 0; i < n; i += 2) {
479  annotationProgram.setUniform2f("shift_position", positions[i], positions[i + 1]);
480  quad->Render();
481  }
482 
483  glBindTexture(GL_TEXTURE_2D, 0);
484  glDisable(GL_TEXTURE_2D);
485 
487  glDisable(GL_BLEND);
488 }
489 
490 } // end namespace pic
491 
492 #endif /* PIC_UTIL_GL_STROKE_HPP */
StrokeGL(int width, int height, int brushSize, float *color)
StrokeGL.
Definition: stroke.hpp:151
void bindCol(float val)
bindCol
Definition: stroke.hpp:115
float rSize
Definition: stroke.hpp:38
void Straightner()
Straightner.
Definition: stroke.hpp:132
TechniqueGL brushProgram
Definition: stroke.hpp:47
void setOutputFragmentShaderIndex(const char *fragment_output_color_name, unsigned int index)
setOutputFragmentShaderIndex
Definition: technique.hpp:215
float size
Definition: stroke.hpp:38
void bindTexture()
bindTexture
QuadGL * quad
Definition: stroke.hpp:42
GLuint generateTextureGL(GLenum target, GLenum format_type, bool mipmap)
generateTextureGL
void setUniform1f(const char *name_uniform, float value0)
SetUniform1f.
Definition: technique.hpp:247
void unbind()
unbind
Definition: technique.hpp:197
float tmpColor[3]
Definition: stroke.hpp:40
void link()
link
Definition: technique.hpp:205
void setUniform2f(const char *name_uniform, float value0, float value1)
setUniform
Definition: technique.hpp:259
#define MAKE_STRING(input_string)
Definition: image.hpp:37
bool init(std::string version_number, std::string vertex_shader_source, std::string fragment_shader_source)
Definition: technique.hpp:67
TechniqueGL annotationProgram
Definition: stroke.hpp:46
The ImageGL class.
Definition: image.hpp:42
static bool * assign(bool *buffer, int n, bool value)
assign assigns value to buffer
Definition: filter_radial_basis_function.hpp:45
The TechniqueGL class.
Definition: technique.hpp:31
int brushSize
Definition: stroke.hpp:36
The QuadGL class.
Definition: quad.hpp:30
void unBindCol()
unBindCol
Definition: stroke.hpp:124
void RenderBrushGL(int x, int y)
RenderBrushGL.
Definition: stroke.hpp:397
float color[4]
Definition: stroke.hpp:39
void printLog(std::string name)
printLog
Definition: technique.hpp:176
void unBindTexture()
unBindTexture
int width
Definition: stroke.hpp:36
#define PIC_INLINE
Definition: base.hpp:33
~StrokeGL()
Definition: stroke.hpp:195
std::vector< float > positions
Definition: stroke.hpp:44
void RenderAnnotationGL()
RenderAnnotationGL.
Definition: stroke.hpp:459
void setAttributeIndex(const char *attribute_name, unsigned int index)
setAttributeIndex
Definition: technique.hpp:225
void Render()
Render draws a quad on screen.
Definition: quad.hpp:140
float annotation
Definition: stroke.hpp:50
void setUniform4f(const char *name_uniform, float value0, float value1, float value2, float value3)
setUniform4f
Definition: technique.hpp:289
void Insert2DPoint(int x, int y)
Insert2DPoint.
Definition: stroke.hpp:379
void Resample()
Resample.
Definition: stroke.hpp:282
GLuint getTexture() const
getTexture
Definition: image.hpp:369
Definition: bilateral_separation.hpp:25
#define CLAMP(x, a)
Definition: math.hpp:77
void initShaders()
initShaders
Definition: stroke.hpp:204
#define MAX(a, b)
Definition: math.hpp:73
The StrokeGL class.
Definition: stroke.hpp:33
int height
Definition: stroke.hpp:36
PIC_INLINE void evaluateSolid(Image *img)
evaluateSolid renders a centred circle.
Definition: rasterizer.hpp:238
ImageGL * shape
Definition: stroke.hpp:37
void RenderGL()
RenderGL.
Definition: stroke.hpp:430
void Reset()
Reset.
Definition: stroke.hpp:392
void setUniform1i(const char *name_uniform, int value0)
SetUniform.
Definition: technique.hpp:236
void bind()
bind
Definition: technique.hpp:189
unsigned int Size()
Size.
Definition: stroke.hpp:106