Vuo  2.3.2
VuoShaderShaders.h
Go to the documentation of this file.
1 
14  \n#include "VuoGlslProjection.glsl"
15 
16  // Inputs provided by VuoSceneRenderer
17  uniform mat4 modelviewMatrix;
18  attribute vec3 position;
19  attribute vec3 normal;
20  attribute vec2 textureCoordinate;
21  attribute vec4 vertexColor;
22  uniform bool hasVertexColors;
23 
24  // Outputs to geometry shader
25  varying vec3 geometryPosition;
26  varying vec3 geometryNormal;
27  varying vec2 geometryTextureCoordinate;
28  varying vec4 geometryVertexColor;
29 
30  void main()
31  {
32  geometryPosition = (cameraMatrixInverse * modelviewMatrix * vec4(position, 1.)).xyz;
33  geometryNormal = (cameraMatrixInverse * modelviewMatrix * vec4(normal, 0.)).xyz;
34  geometryTextureCoordinate = textureCoordinate;
35  geometryVertexColor = hasVertexColors ? vertexColor : vec4(1.);
36  gl_Position = VuoGlsl_projectPosition(modelviewMatrix * vec4(position, 1.));
37  }
38 );
39 
44 {
45  const char *pointGeometryShaderSource = VUOSHADER_GLSL_SOURCE(120, \n#include "trianglePoint.glsl");
46  const char *lineGeometryShaderSource = VUOSHADER_GLSL_SOURCE(120, \n#include "triangleLine.glsl");
47 
48  const char *fragmentShaderSource = VUOSHADER_GLSL_SOURCE(120,
49  // Inputs
50  varying vec2 fragmentTextureCoordinate;
51  uniform vec4 blah;
52 
53  void main()
54  {
55  // Work around ATI Radeon HD 5770 bug.
56  // It seems that the rest of the shader isn't executed unless we initialize the output with a uniform.
57  // https://b33p.net/kosada/node/11256
58  gl_FragColor = blah;
59 
60  // Based on the Gritz/Baldwin antialiased checkerboard shader.
61 
62  vec3 color0 = vec3(1 -fragmentTextureCoordinate.x, fragmentTextureCoordinate.y, 1 ) * (gl_FrontFacing ? 1 : .25);
63  vec3 color1 = vec3(0.75-fragmentTextureCoordinate.x, fragmentTextureCoordinate.y-0.25, 0.75) * (gl_FrontFacing ? 1 : .25);
64  float frequency = 8;
65  vec2 filterWidth = fwidth(fragmentTextureCoordinate) * frequency;
66 
67  vec2 checkPos = fract(fragmentTextureCoordinate * frequency);
68  vec2 p = smoothstep(vec2(0.5), filterWidth + vec2(0.5), checkPos) +
69  (1 - smoothstep(vec2(0), filterWidth, checkPos));
70 
71  gl_FragColor = vec4(mix(color0, color1, p.x*p.y + (1-p.x)*(1-p.y)), 1);
72  }
73  );
74 
75  const char *fragmentShaderSourceForGeometry = VUOSHADER_GLSL_SOURCE(120,
76  // Inputs
77  varying vec3 fragmentPosition;
78  varying vec3 fragmentNormal;
79  varying vec2 fragmentTextureCoordinate;
80  varying vec4 fragmentVertexColor;
81  uniform vec4 blah;
82 
83  void main()
84  {
85  // Work around ATI Radeon HD 5770 bug.
86  // It seems that the rest of the shader isn't executed unless we initialize the output with a uniform.
87  // https://b33p.net/kosada/node/11256
88  gl_FragColor = blah;
89 
90  fragmentPosition;
91  fragmentNormal;
92  fragmentTextureCoordinate;
93  fragmentVertexColor;
94 
95  // Based on the Gritz/Baldwin antialiased checkerboard shader.
96 
97  vec3 color0 = vec3(1 -fragmentTextureCoordinate.x, fragmentTextureCoordinate.y, 1);
98  vec3 color1 = vec3(0.75-fragmentTextureCoordinate.x, fragmentTextureCoordinate.y-0.25, 0.75);
99  float frequency = 8;
100  vec2 filterWidth = fwidth(fragmentTextureCoordinate) * frequency;
101 
102  vec2 checkPos = fract(fragmentTextureCoordinate * frequency);
103  // Add 0.00001 so that smoothstep() doesn't return NaN on ATI Radeon HD 5770.
104  // https://b33p.net/kosada/node/10467
105  vec2 p = smoothstep(vec2(0.5), filterWidth + vec2(0.5), checkPos) +
106  (1 - smoothstep(vec2(0), filterWidth, checkPos+0.00001));
107 
108  gl_FragColor = vec4(mix(color0, color1, p.x*p.y + (1-p.x)*(1-p.y)), 1);
109  }
110  );
111 
112  VuoShader shader = VuoShader_make("Default Shader (Checkerboard)");
113 
114  VuoShader_addSource (shader, VuoMesh_Points, defaultVertexShaderSourceForGeometryShader, pointGeometryShaderSource, fragmentShaderSourceForGeometry);
116 
117  VuoShader_addSource (shader, VuoMesh_IndividualLines, defaultVertexShaderSourceForGeometryShader, lineGeometryShaderSource, fragmentShaderSourceForGeometry);
119 
120  VuoShader_addSource (shader, VuoMesh_IndividualTriangles, NULL, NULL, fragmentShaderSource);
121 
122  VuoShader_setUniform_VuoColor(shader, "blah", VuoColor_makeWithRGBA(42,42,42,42));
123 
124  return shader;
125 }
126 
135 {
136  static dispatch_once_t once = 0;
137  static VuoShader defaultShader;
138  dispatch_once(&once, ^{
139  defaultShader = VuoShader_makeDefaultShaderInternal();
140  VuoRegisterSingleton(defaultShader);
141  VuoRegisterSingleton(defaultShader->name);
142  VuoRegisterSingleton(defaultShader->pointProgram.vertexSource);
143  VuoRegisterSingleton(defaultShader->pointProgram.geometrySource);
144  VuoRegisterSingleton(defaultShader->pointProgram.fragmentSource);
145  VuoRegisterSingleton(defaultShader->lineProgram.vertexSource);
146  VuoRegisterSingleton(defaultShader->lineProgram.geometrySource);
147  VuoRegisterSingleton(defaultShader->lineProgram.fragmentSource);
148  VuoRegisterSingleton(defaultShader->triangleProgram.vertexSource);
149  VuoRegisterSingleton(defaultShader->triangleProgram.fragmentSource);
150  VuoRegisterSingleton(defaultShader->uniforms[0].name);
151  VuoRegisterSingleton(defaultShader->uniforms[0].type);
152  });
153  return defaultShader;
154 }
155 
164 {
165  const char *pointGeometryShaderSource = VUOSHADER_GLSL_SOURCE(120, \n#include "trianglePoint.glsl");
166  const char *lineGeometryShaderSource = VUOSHADER_GLSL_SOURCE(120, \n#include "triangleLine.glsl");
167 
168  const char *fragmentShaderSource = VUOSHADER_GLSL_SOURCE(120,
169  \n#include "VuoGlslAlpha.glsl"
170 
171  // Inputs from ports
172  uniform sampler2D texture;
173  uniform float alpha;
174  uniform vec4 blah;
175 
176  // Inputs from vertex/geometry shader
177  varying vec2 fragmentTextureCoordinate;
178  varying vec4 fragmentVertexColor;
179 
180  void main()
181  {
182  // Work around ATI Radeon HD 5770 bug.
183  // It seems that the rest of the shader isn't executed unless we initialize the output with a uniform.
184  // https://b33p.net/kosada/node/11256
185  gl_FragColor = blah;
186 
187  vec4 color = VuoGlsl_sample(texture, fragmentTextureCoordinate) * fragmentVertexColor;
188  color *= alpha;
189  VuoGlsl_discardInvisible(color.a);
190  gl_FragColor = color;
191  }
192  );
193 
194  const char *fragmentShaderSourceForGeometry = VUOSHADER_GLSL_SOURCE(120,
195  \n#include "VuoGlslAlpha.glsl"
196 
197  // Inputs from ports
198  uniform sampler2D texture;
199  uniform float alpha;
200  uniform vec4 blah;
201 
202  // Inputs from vertex/geometry shader
203  varying vec3 fragmentPosition;
204  varying vec2 fragmentTextureCoordinate;
205  varying vec4 fragmentVertexColor;
206 
207  void main()
208  {
209  // Work around ATI Radeon HD 5770 bug.
210  // It seems that the rest of the shader isn't executed unless we initialize the output with a uniform.
211  // https://b33p.net/kosada/node/11256
212  gl_FragColor = blah;
213 
214  fragmentPosition;
215 
216  vec4 color = VuoGlsl_sample(texture, fragmentTextureCoordinate) * fragmentVertexColor;
217  color *= alpha;
218  VuoGlsl_discardInvisible(color.a);
219  gl_FragColor = color;
220  }
221  );
222 
223  VuoShader shader = VuoShader_make("Image Shader (Unlit)");
224 
225  VuoShader_addSource (shader, VuoMesh_Points, defaultVertexShaderSourceForGeometryShader, pointGeometryShaderSource, fragmentShaderSourceForGeometry);
227 
228  VuoShader_addSource (shader, VuoMesh_IndividualLines, defaultVertexShaderSourceForGeometryShader, lineGeometryShaderSource, fragmentShaderSourceForGeometry);
230 
231  VuoShader_addSource (shader, VuoMesh_IndividualTriangles, NULL, NULL, fragmentShaderSource);
232 
233  VuoShader_setUniform_VuoImage(shader, "texture", image);
234  VuoShader_setUniform_VuoReal (shader, "alpha", alpha);
235  VuoShader_setUniform_VuoColor(shader, "blah", VuoColor_makeWithRGBA(42,42,42,42));
236 
237  return shader;
238 }
239 
251 {
252  const char *fragmentShaderSource = VUOSHADER_GLSL_SOURCE(120,
253  \n#include "VuoGlslAlpha.glsl"
254 
255  // Inputs from ports
256  uniform sampler2D texture;
257 
258  // Inputs from vertex/geometry shader
259  varying vec2 fragmentTextureCoordinate;
260 
261  void main()
262  {
263  vec4 color = VuoGlsl_sample(texture, fragmentTextureCoordinate);
264  VuoGlsl_discardInvisible(color.a);
265  gl_FragColor = color;
266  }
267  );
268 
269  const char *fragmentShaderSourceFlipped = VUOSHADER_GLSL_SOURCE(120,
270  \n#include "VuoGlslAlpha.glsl"
271 
272  // Inputs from ports
273  uniform sampler2D texture;
274 
275  // Inputs from vertex/geometry shader
276  varying vec2 fragmentTextureCoordinate;
277 
278  void main()
279  {
280  vec4 color = VuoGlsl_sample(texture, vec2(fragmentTextureCoordinate.x, 1. - fragmentTextureCoordinate.y));
281  VuoGlsl_discardInvisible(color.a);
282  gl_FragColor = color;
283  }
284  );
285 
286  VuoShader shader = VuoShader_make("Image Shader (Unlit, AlphaPassthru)");
287  if (flipped)
288  VuoShader_addSource(shader, VuoMesh_IndividualTriangles, NULL, NULL, fragmentShaderSourceFlipped);
289  else
290  VuoShader_addSource(shader, VuoMesh_IndividualTriangles, NULL, NULL, fragmentShaderSource);
291  VuoShader_setUniform_VuoImage(shader, "texture", image);
292  return shader;
293 }
294 
303 {
304  if (!image)
305  return NULL;
306 
307  const char *fragmentShaderSource = VUOSHADER_GLSL_SOURCE(120,
308  \n#include "VuoGlslAlpha.glsl"
309 
310  // Inputs
311  uniform sampler2DRect texture;
312  uniform vec2 textureSize;
313  uniform float alpha;
314  varying vec2 fragmentTextureCoordinate;
315 
316  void main()
317  {
318  vec4 color = VuoGlsl_sampleRect(texture, fragmentTextureCoordinate*textureSize);
319  color *= alpha;
320  VuoGlsl_discardInvisible(color.a);
321  gl_FragColor = color;
322  }
323  );
324 
325  VuoShader shader = VuoShader_make("Image Shader (GL_TEXTURE_RECTANGLE)");
326  VuoShader_addSource(shader, VuoMesh_IndividualTriangles, NULL, NULL, fragmentShaderSource);
327  VuoShader_setUniform_VuoImage (shader, "texture", image);
328  VuoShader_setUniform_VuoReal (shader, "alpha", alpha);
329  VuoShader_setUniform_VuoPoint2d(shader, "textureSize", VuoPoint2d_make(image->pixelsWide, image->pixelsHigh));
330  return shader;
331 }
332 
344 {
345  if (!image)
346  return NULL;
347 
348  const char *fragmentShaderSource = VUOSHADER_GLSL_SOURCE(120,
349  \n#include "VuoGlslAlpha.glsl"
350 
351  // Inputs
352  uniform sampler2DRect texture;
353  uniform vec2 textureSize;
354  varying vec2 fragmentTextureCoordinate;
355 
356  void main()
357  {
358  vec4 color = VuoGlsl_sampleRect(texture, fragmentTextureCoordinate*textureSize);
359  VuoGlsl_discardInvisible(color.a);
360  gl_FragColor = color;
361  }
362  );
363 
364  const char *fragmentShaderSourceFlipped = VUOSHADER_GLSL_SOURCE(120,
365  \n#include "VuoGlslAlpha.glsl"
366 
367  // Inputs
368  uniform sampler2DRect texture;
369  uniform vec2 textureSize;
370  varying vec2 fragmentTextureCoordinate;
371 
372  void main()
373  {
374  vec4 color = VuoGlsl_sampleRect(texture, vec2(fragmentTextureCoordinate.x, 1. - fragmentTextureCoordinate.y) * textureSize);
375  VuoGlsl_discardInvisible(color.a);
376  gl_FragColor = color;
377  }
378  );
379 
380  VuoShader shader = VuoShader_make("Image Shader (GL_TEXTURE_RECTANGLE, AlphaPassthru)");
381  if (flipped)
382  VuoShader_addSource(shader, VuoMesh_IndividualTriangles, NULL, NULL, fragmentShaderSourceFlipped);
383  else
384  VuoShader_addSource(shader, VuoMesh_IndividualTriangles, NULL, NULL, fragmentShaderSource);
385  VuoShader_setUniform_VuoImage (shader, "texture", image);
386  VuoShader_setUniform_VuoPoint2d(shader, "textureSize", VuoPoint2d_make(image->pixelsWide, image->pixelsHigh));
387  return shader;
388 }
389 
396 {
397  const char *vertexShaderSource = VUOSHADER_GLSL_SOURCE(120,
398  \n#include "VuoGlslProjection.glsl"
399 
400  // Inputs from VuoSceneRenderer
401  uniform mat4 modelviewMatrix;
402  attribute vec3 position;
403  attribute vec4 vertexColor;
404  uniform bool hasVertexColors;
405 
406  // Outputs to fragment shader
407  varying vec3 fragmentPosition;
408  varying vec3 fragmentNormal;
409  varying vec2 fragmentTextureCoordinate;
410  varying vec4 fragmentVertexColor;
411 
412  void main()
413  {
414  gl_Position = VuoGlsl_projectPosition(modelviewMatrix * vec4(position, 1.));
415  fragmentVertexColor = hasVertexColors ? vertexColor : vec4(1.);
416  }
417  );
418 
419  const char *pointGeometryShaderSource = VUOSHADER_GLSL_SOURCE(120, \n#include "trianglePoint.glsl");
420  const char *lineGeometryShaderSource = VUOSHADER_GLSL_SOURCE(120, \n#include "triangleLine.glsl");
421 
422  const char *fragmentShaderSource = VUOSHADER_GLSL_SOURCE(120,
423  // Inputs from ports
424  uniform vec4 color;
425 
426  // Inputs from vertex/geometry shader
427  varying vec4 fragmentVertexColor;
428 
429  void main()
430  {
431  gl_FragColor = color * fragmentVertexColor;
432  }
433  );
434 
435  const char *fragmentShaderSourceForGeometry = VUOSHADER_GLSL_SOURCE(120,
436  // Inputs from ports
437  uniform vec4 color;
438 
439  // Inputs from vertex/geometry shader
440  varying vec3 fragmentPosition;
441  varying vec3 fragmentNormal;
442  varying vec2 fragmentTextureCoordinate;
443  varying vec4 fragmentVertexColor;
444 
445  void main()
446  {
447  fragmentPosition;
448  fragmentNormal;
449  fragmentTextureCoordinate;
450 
451  gl_FragColor = color * fragmentVertexColor;
452  }
453  );
454 
455  VuoShader shader = VuoShader_make("Color Shader (Unlit)");
456 
457  VuoShader_addSource (shader, VuoMesh_Points, defaultVertexShaderSourceForGeometryShader, pointGeometryShaderSource, fragmentShaderSourceForGeometry);
459 
460  VuoShader_addSource (shader, VuoMesh_IndividualLines, defaultVertexShaderSourceForGeometryShader, lineGeometryShaderSource, fragmentShaderSourceForGeometry);
462 
463  VuoShader_addSource (shader, VuoMesh_IndividualTriangles, vertexShaderSource, NULL, fragmentShaderSource);
464 
465  VuoShader_setUniform_VuoColor(shader, "color", color);
466 
467  return shader;
468 }
469 
481 {
482  const char *pointGeometryShaderSource = VUOSHADER_GLSL_SOURCE(120, \n#include "trianglePoint.glsl");
483  const char *lineGeometryShaderSource = VUOSHADER_GLSL_SOURCE(120, \n#include "triangleLine.glsl");
484 
485  const char *fragmentShaderSource = VUOSHADER_GLSL_SOURCE(120,
486  uniform vec4 color;
487  uniform float sharpness;
488  varying vec2 fragmentTextureCoordinate;
489 
490  void main(void)
491  {
492  float dist = distance(fragmentTextureCoordinate, vec2(0.5,0.5));
493  float delta = fwidth(dist);
494  gl_FragColor = mix(color, vec4(0.), smoothstep(sharpness/2 - delta, 1 - sharpness/2 + delta, dist*2));
495  }
496  );
497 
498  VuoShader shader = VuoShader_make("Circle Shader");
499  shader->objectScale = 0.5;
500 
501  VuoShader_addSource (shader, VuoMesh_Points, defaultVertexShaderSourceForGeometryShader, pointGeometryShaderSource, fragmentShaderSource);
503 
504  VuoShader_addSource (shader, VuoMesh_IndividualLines, defaultVertexShaderSourceForGeometryShader, lineGeometryShaderSource, fragmentShaderSource);
506 
507  VuoShader_addSource (shader, VuoMesh_IndividualTriangles, NULL, NULL, fragmentShaderSource);
508 
509  VuoShader_setUniform_VuoColor(shader, "color", color);
510  VuoShader_setUniform_VuoReal (shader, "sharpness", VuoReal_clamp(sharpness, 0, 1));
511  return shader;
512 }
513 
521 {
522  // The VUOSHADER_GLSL_SOURCE macro gets hung up on the const vec2 (); declaration.
523  const char *fragmentShaderSource = "#version 120 \n\
524 varying vec2 fragmentTextureCoordinate;\
525 uniform vec4 color;\
526 uniform vec4 lineColor;\
527 uniform float thickness;\
528 const int CHECK_VERTICES = 6;\
529 const vec2 CHECK[CHECK_VERTICES] = vec2[] (\
530  vec2(.0, .47),\
531  vec2(.175, .66),\
532  vec2(.37, .46),\
533  vec2(.82, .9),\
534  vec2(1, .72),\
535  vec2(.37, .1)\
536 );\
537 \
538 bool doLineSegmentsIntersect(vec2 p0, vec2 p1, vec2 p2, vec2 p3)\
539 {\
540  vec2 s1 = p1 - p0;\
541  vec2 s2 = p3 - p2;\
542  float s, t;\
543  s = (-s1.y * (p0.x - p2.x) + s1.x * (p0.y - p2.y)) / (-s2.x * s1.y + s1.x * s2.y);\
544  t = ( s2.x * (p0.y - p2.y) - s2.y * (p0.x - p2.x)) / (-s2.x * s1.y + s1.x * s2.y);\
545 \
546  return (s >= 0 && s <= 1 && t >= 0 && t <= 1);\
547 }\
548 \
549 float drawLine(vec2 p1, vec2 p2)\
550 {\
551  vec2 uv = fragmentTextureCoordinate;\
552  float a = abs(distance(p1, uv));\
553  float b = abs(distance(p2, uv));\
554  float c = abs(distance(p1, p2));\
555  if( a >= c || b >= c) return 0.;\
556  float p = (a + b + c) * .5;\
557  float h = 2. / c * sqrt(p * (p-a) * (p-b) * (p-c));\
558  return mix(1, 0, smoothstep(0.5 * thickness, 1.5 * thickness, h));\
559 }\
560 \
561 bool isPointInPolygon(vec2 point)\
562 {\
563  vec2 rayStart = vec2(0, .5);\
564  bool inPoly = false;\
565 \
566  for(int i = 0; i < CHECK_VERTICES; i += 1)\
567  {\
568  if(doLineSegmentsIntersect(rayStart, point, CHECK[i], CHECK[i == (CHECK_VERTICES-1) ? 0 : i+1]) )\
569  inPoly = !inPoly;\
570  }\
571 \
572  return inPoly;\
573 }\
574 \
575 void main(void)\
576 {\
577  float line = 0;\
578  for(int i = 0; i < CHECK_VERTICES; i++)\
579  line = max(drawLine(CHECK[i], CHECK[i < CHECK_VERTICES-1 ? i+1 : 0]), line);\
580  gl_FragColor = mix(isPointInPolygon(fragmentTextureCoordinate) ? color : vec4(0), lineColor, line);\
581 }\
582 ";
583 
584  VuoShader shader = VuoShader_make("Checkmark Shader");
585  shader->objectScale = 1;
586  VuoShader_addSource(shader, VuoMesh_IndividualTriangles, NULL, NULL, fragmentShaderSource);
587  VuoShader_setUniform_VuoColor(shader, "color", color);
588  VuoShader_setUniform_VuoColor(shader, "lineColor", outline);
589  VuoShader_setUniform_VuoReal(shader, "thickness", thickness);
590  return shader;
591 }
592 
606 {
607  const char *fragmentShaderSource = VUOSHADER_GLSL_SOURCE(120,
608  uniform vec4 color;
609  uniform float sharpness;
610  uniform float roundness;
611  uniform float aspect;
612  varying vec2 fragmentTextureCoordinate;
613 
614  void main(void)
615  {
616  float roundness2 = max(1. - sharpness, roundness);
617  roundness2 = min(aspect, roundness2);
618  float diameter = roundness2 / 2.;
619  diameter = max(diameter, 0.001);
620  float radius = diameter / 2.;
621  vec2 r = vec2(radius/aspect, radius);
622 
623  vec2 cornerCircleCenter = vec2(0.,0.);
624  if (fragmentTextureCoordinate.x > 0.75 - r.x)
625  {
626  if (fragmentTextureCoordinate.y > 0.75 - r.y)
627  // Top right corner
628  cornerCircleCenter = vec2(0.75, 0.75) + vec2(-r.x, -r.y);
629  else if (fragmentTextureCoordinate.y < 0.25 + r.y)
630  // Bottom right corner
631  cornerCircleCenter = vec2(0.75, 0.25) + vec2(-r.x, r.y);
632  }
633  else if (fragmentTextureCoordinate.x < 0.25 + r.x)
634  {
635  if (fragmentTextureCoordinate.y > 0.75 - r.y)
636  // Top left corner
637  cornerCircleCenter = vec2(0.25, 0.75) + vec2( r.x, -r.y);
638  else if (fragmentTextureCoordinate.y < 0.25 + radius)
639  // Bottom left corner
640  cornerCircleCenter = vec2(0.25, 0.25) + vec2( r.x, r.y);
641  }
642 
643  float dist = 0.;
644  if (cornerCircleCenter.x > 0.)
645  dist = distance((fragmentTextureCoordinate - cornerCircleCenter) * vec2(aspect, 1.) + cornerCircleCenter, cornerCircleCenter) / diameter;
646  else
647  {
648  float f = 1. - (1. - sharpness) * (1. - sharpness);
649  if (aspect < 1.)
650  f = 1./f;
651  float n = (fragmentTextureCoordinate.x - 0.5) * f;
652 
653  if (fragmentTextureCoordinate.y < 0.5 + n)
654  {
655  if (fragmentTextureCoordinate.y > 0.5 - n)
656  // Right edge
657  dist = (fragmentTextureCoordinate.x - (0.75 - r.x)) * aspect;
658  else
659  // Bottom edge
660  dist = (0.25 + r.y) - fragmentTextureCoordinate.y;
661  }
662  else
663  {
664  if (fragmentTextureCoordinate.y > 0.5 - n)
665  // Top edge
666  dist = fragmentTextureCoordinate.y - (0.75 - r.y);
667  else
668  // Left edge
669  dist = ((0.25 + r.x) - fragmentTextureCoordinate.x) * aspect;
670  }
671 
672  dist /= diameter;
673  }
674 
675 // float delta = min(fwidth(fragmentTextureCoordinate.x), fwidth(fragmentTextureCoordinate.y));
676  float delta = fwidth(fragmentTextureCoordinate.y);
677  delta /= diameter;
678  delta /= 2.;
679 
680  gl_FragColor = mix(color, vec4(0.), smoothstep(sharpness / 2. - delta, 1. - sharpness / 2. + delta, dist));
681  }
682  );
683 
684  VuoShader shader = VuoShader_make("Rounded Rectangle Shader");
685  shader->objectScale = 0.5;
686  VuoShader_addSource(shader, VuoMesh_IndividualTriangles, NULL, NULL, fragmentShaderSource);
687  VuoShader_setUniform_VuoColor(shader, "color", color);
688  VuoShader_setUniform_VuoReal (shader, "sharpness", VuoReal_clamp(sharpness, 0, 1));
689  VuoShader_setUniform_VuoReal (shader, "roundness", VuoReal_clamp(roundness, 0, 1));
690  VuoShader_setUniform_VuoReal (shader, "aspect", aspect);
691  return shader;
692 }
693 
708  VuoColor backgroundColor,
709  VuoColor activeColor,
710  VuoReal sharpness,
711  VuoReal roundness,
712  VuoReal aspect,
713  VuoBoolean isHorizontal,
714  VuoReal value)
715 {
716  const char *fragmentShaderSource = VUOSHADER_GLSL_SOURCE(120,
717  uniform vec4 backgroundColor;
718  uniform vec4 activeColor;
719  uniform float sharpness;
720  uniform float roundness;
721  uniform float aspect;
722  uniform float progress;
723  uniform bool isHorizontal;
724  varying vec2 fragmentTextureCoordinate;
725 
726  void main(void)
727  {
728  float roundness2 = max(1. - sharpness, roundness);
729  roundness2 = min(aspect, roundness2);
730  float diameter = roundness2 / 2.;
731  diameter = max(diameter, 0.001);
732  float radius = diameter / 2.;
733  vec2 r = vec2(radius/aspect, radius);
734 
735  vec2 cornerCircleCenter = vec2(0.,0.);
736  if (fragmentTextureCoordinate.x > 0.75 - r.x)
737  {
738  if (fragmentTextureCoordinate.y > 0.75 - r.y)
739  // Top right corner
740  cornerCircleCenter = vec2(0.75, 0.75) + vec2(-r.x, -r.y);
741  else if (fragmentTextureCoordinate.y < 0.25 + r.y)
742  // Bottom right corner
743  cornerCircleCenter = vec2(0.75, 0.25) + vec2(-r.x, r.y);
744  }
745  else if (fragmentTextureCoordinate.x < 0.25 + r.x)
746  {
747  if (fragmentTextureCoordinate.y > 0.75 - r.y)
748  // Top left corner
749  cornerCircleCenter = vec2(0.25, 0.75) + vec2( r.x, -r.y);
750  else if (fragmentTextureCoordinate.y < 0.25 + radius)
751  // Bottom left corner
752  cornerCircleCenter = vec2(0.25, 0.25) + vec2( r.x, r.y);
753  }
754 
755  float dist = 0.;
756  if (cornerCircleCenter.x > 0.)
757  dist = distance((fragmentTextureCoordinate - cornerCircleCenter) * vec2(aspect, 1.) + cornerCircleCenter, cornerCircleCenter) / diameter;
758  else
759  {
760  float f = 1. - (1. - sharpness) * (1. - sharpness);
761  if (aspect < 1.)
762  f = 1./f;
763  float n = (fragmentTextureCoordinate.x - 0.5) * f;
764 
765  if (fragmentTextureCoordinate.y < 0.5 + n)
766  {
767  if (fragmentTextureCoordinate.y > 0.5 - n)
768  // Right edge
769  dist = (fragmentTextureCoordinate.x - (0.75 - r.x)) * aspect;
770  else
771  // Bottom edge
772  dist = (0.25 + r.y) - fragmentTextureCoordinate.y;
773  }
774  else
775  {
776  if (fragmentTextureCoordinate.y > 0.5 - n)
777  // Top edge
778  dist = fragmentTextureCoordinate.y - (0.75 - r.y);
779  else
780  // Left edge
781  dist = ((0.25 + r.x) - fragmentTextureCoordinate.x) * aspect;
782  }
783 
784  dist /= diameter;
785  }
786 
787  float delta = fwidth(dist) / 2.;
788 
789  // fwidth() seems to sometimes output invalid results; this hides most of it.
790  if (delta > 0.1)
791  delta = 0.;
792 
793  float val = (isHorizontal ? fragmentTextureCoordinate.x : fragmentTextureCoordinate.y);
794  val = (clamp(val, .25, .75) - .25) / .5;
795  vec4 color = val < progress ? activeColor : backgroundColor;
796  gl_FragColor = mix(color, vec4(0.), smoothstep(sharpness / 2. - delta, 1. - sharpness / 2. + delta, dist));
797  }
798  );
799 
800  VuoShader shader = VuoShader_make("Rounded Rectangle Track Shader");
801  shader->objectScale = 0.5;
802  VuoShader_addSource(shader, VuoMesh_IndividualTriangles, NULL, NULL, fragmentShaderSource);
803  VuoShader_setUniform_VuoColor(shader, "backgroundColor", backgroundColor);
804  VuoShader_setUniform_VuoColor(shader, "activeColor", activeColor);
805  VuoShader_setUniform_VuoReal (shader, "sharpness", VuoReal_clamp(sharpness, 0, 1));
806  VuoShader_setUniform_VuoReal (shader, "roundness", VuoReal_clamp(roundness, 0, 1));
807  VuoShader_setUniform_VuoReal (shader, "aspect", aspect);
808  VuoShader_setUniform_VuoBoolean (shader, "isHorizontal", isHorizontal);
809  VuoShader_setUniform_VuoReal (shader, "progress", value);
810  return shader;
811 }
812 
822 VuoShader VuoShader_makeLitColorShader(VuoColor diffuseColor, VuoColor highlightColor, VuoReal shininess)
823 {
824  const char *vertexShaderSource = VUOSHADER_GLSL_SOURCE(120,
825  \n#include "VuoGlslProjection.glsl"
826 
827  // Inputs provided by VuoSceneRenderer
828  uniform mat4 modelviewMatrix;
829  attribute vec3 position;
830  attribute vec3 normal;
831  attribute vec4 vertexColor;
832  uniform bool hasVertexColors;
833 
834  // Outputs to fragment shader
835  varying vec3 fragmentPosition;
836  varying vec3 fragmentNormal;
837  varying vec2 fragmentTextureCoordinate;
838  varying vec4 fragmentVertexColor;
839 
840  void main()
841  {
842  fragmentTextureCoordinate;
843 
844  fragmentPosition = (modelviewMatrix * vec4(position, 1.)).xyz;
845  fragmentNormal = (modelviewMatrix * vec4(normal, 0.)).xyz;
846  fragmentVertexColor = hasVertexColors ? vertexColor : vec4(1.);
847  gl_Position = VuoGlsl_projectPosition(fragmentPosition);
848  }
849  );
850 
851  const char *pointGeometryShaderSource = VUOSHADER_GLSL_SOURCE(120, \n#include "trianglePoint.glsl");
852  const char *lineGeometryShaderSource = VUOSHADER_GLSL_SOURCE(120, \n#include "triangleLine.glsl");
853 
854  const char *fragmentShaderSource = VUOSHADER_GLSL_SOURCE(120,
855  \n#include "lighting.glsl"
856 
857  // Inputs from ports
858  uniform vec4 diffuseColor;
859  uniform vec4 specularColor;
860  uniform float specularPower;
861 
862  // Inputs from vertex/geometry shader
863  varying vec3 fragmentNormal;
864  varying vec2 fragmentTextureCoordinate;
865  varying vec4 fragmentVertexColor;
866 
867  void main()
868  {
869  // Work around ATI Radeon HD 5770 bug.
870  // It seems that the rest of the shader isn't executed unless we initialize the output with a uniform.
871  // https://b33p.net/kosada/node/11256
872  gl_FragColor = diffuseColor;
873 
874  fragmentTextureCoordinate;
875 
876  vec3 ambientContribution = vec3(0.);
877  vec3 diffuseContribution = vec3(0.);
878  vec3 specularContribution = vec3(0.);
879 
880  calculateLighting(specularPower, fragmentNormal, ambientContribution, diffuseContribution, specularContribution);
881 
882  ambientContribution *= diffuseColor.rgb * fragmentVertexColor.rgb;
883  diffuseContribution *= diffuseColor.rgb * fragmentVertexColor.rgb;
884  specularContribution *= specularColor.rgb * specularColor.a;
885  gl_FragColor = vec4(ambientContribution + diffuseContribution + specularContribution, diffuseColor.a * fragmentVertexColor.a);
886  }
887  );
888 
889  VuoShader shader = VuoShader_make("Color Shader (Lit)");
890 
891  VuoShader_addSource (shader, VuoMesh_Points, defaultVertexShaderSourceForGeometryShader, pointGeometryShaderSource, fragmentShaderSource);
893 
894  VuoShader_addSource (shader, VuoMesh_IndividualLines, defaultVertexShaderSourceForGeometryShader, lineGeometryShaderSource, fragmentShaderSource);
896 
897  VuoShader_addSource (shader, VuoMesh_IndividualTriangles, vertexShaderSource, NULL, fragmentShaderSource);
898 
899  VuoShader_setUniform_VuoColor(shader, "diffuseColor", diffuseColor);
900  VuoShader_setUniform_VuoColor(shader, "specularColor", highlightColor);
901  VuoShader_setUniform_VuoReal (shader, "specularPower", 1./(1.0001-shininess));
902  return shader;
903 }
904 
909  \n#include "VuoGlslProjection.glsl"
910 
911  // Inputs provided by VuoSceneRenderer
912  uniform mat4 modelviewMatrix;
913  attribute vec3 position;
914  attribute vec3 normal;
915  attribute vec2 textureCoordinate;
916  attribute vec4 vertexColor;
917  uniform bool hasVertexColors;
918 
919  // Outputs to fragment shader
920  varying vec3 fragmentPosition;
921  varying vec3 fragmentNormal;
922  varying vec2 fragmentTextureCoordinate;
923  varying vec4 fragmentVertexColor;
924 
925  void main()
926  {
927  fragmentPosition = (modelviewMatrix * vec4(position, 1.)).xyz;
928  fragmentNormal = normalize(vec3(modelviewMatrix * vec4(normal, 0.)));
929  fragmentTextureCoordinate = textureCoordinate;
930  fragmentVertexColor = hasVertexColors ? vertexColor : vec4(1.);
931  gl_Position = VuoGlsl_projectPosition(fragmentPosition);
932  }
933 );
934 
939  \n#include "VuoGlslProjection.glsl"
940 
941  // Inputs provided by VuoSceneRenderer
942  uniform mat4 modelviewMatrix;
943  attribute vec3 position;
944  attribute vec3 normal;
945  attribute vec2 textureCoordinate;
946  attribute vec4 vertexColor;
947  uniform bool hasVertexColors;
948 
949  // Outputs to geometry shader
950  varying vec3 geometryPosition;
951  varying vec3 geometryNormal;
952  varying vec2 geometryTextureCoordinate;
953  varying vec4 geometryVertexColor;
954 
955  void main()
956  {
957  geometryPosition = (modelviewMatrix * vec4(position, 1.)).xyz;
958  geometryNormal = normalize((modelviewMatrix * vec4(normal, 0.)).xyz);
959  geometryTextureCoordinate = textureCoordinate;
960  geometryVertexColor = hasVertexColors ? vertexColor : vec4(1.);
961  gl_Position = VuoGlsl_projectPosition(geometryPosition);
962  }
963 );
964 
975 VuoShader VuoShader_makeLitImageShader(VuoImage image, VuoReal alpha, VuoColor highlightColor, VuoReal shininess)
976 {
977  if (!image)
978  return NULL;
979 
980  const char *pointGeometryShaderSource = VUOSHADER_GLSL_SOURCE(120, \n#include "trianglePoint.glsl");
981  const char *lineGeometryShaderSource = VUOSHADER_GLSL_SOURCE(120, \n#include "triangleLine.glsl");
982 
983  const char *fragmentShaderSource = VUOSHADER_GLSL_SOURCE(120,
984  \n#include "VuoGlslAlpha.glsl"
985  \n#include "lighting.glsl"
986 
987  // Inputs from vertex shader
988  varying vec3 fragmentNormal;
989  varying vec2 fragmentTextureCoordinate;
990  varying vec4 fragmentVertexColor;
991 
992  // Inputs from ports
993  uniform sampler2D texture;
994  uniform float alpha;
995  uniform vec4 specularColor;
996  uniform float specularPower;
997 
998  void main()
999  {
1000  // Work around ATI Radeon HD 5770 bug.
1001  // It seems that the rest of the shader isn't executed unless we initialize the output with a uniform.
1002  // https://b33p.net/kosada/node/11256
1003  gl_FragColor = specularColor;
1004 
1005  vec4 color = VuoGlsl_sample(texture, fragmentTextureCoordinate) * fragmentVertexColor;
1006  color *= alpha;
1007  VuoGlsl_discardInvisible(color.a);
1008 
1009  vec3 ambientContribution = vec3(0.);
1010  vec3 diffuseContribution = vec3(0.);
1011  vec3 specularContribution = vec3(0.);
1012 
1013  calculateLighting(specularPower, fragmentNormal, ambientContribution, diffuseContribution, specularContribution);
1014 
1015  ambientContribution *= color.rgb;
1016  diffuseContribution *= color.rgb;
1017  specularContribution *= specularColor.rgb * specularColor.a;
1018  gl_FragColor = vec4(ambientContribution + diffuseContribution + specularContribution, color.a);
1019  }
1020  );
1021 
1022  VuoShader shader = VuoShader_make("Image Shader (Lit)");
1023 
1024  VuoShader_addSource (shader, VuoMesh_Points, lightingVertexShaderSourceForGeometry, pointGeometryShaderSource, fragmentShaderSource);
1026 
1027  VuoShader_addSource (shader, VuoMesh_IndividualLines, lightingVertexShaderSourceForGeometry, lineGeometryShaderSource, fragmentShaderSource);
1029 
1030  VuoShader_addSource (shader, VuoMesh_IndividualTriangles, lightingVertexShaderSource, NULL, fragmentShaderSource);
1031 
1032  VuoShader_setUniform_VuoImage(shader, "texture", image);
1033  VuoShader_setUniform_VuoReal (shader, "alpha", alpha);
1034  VuoShader_setUniform_VuoColor(shader, "specularColor", highlightColor);
1035  VuoShader_setUniform_VuoReal (shader, "specularPower", 1./(1.0001-shininess));
1036 
1037  return shader;
1038 }
1039 
1051 {
1052  if (!image || !specularImage || !normalImage)
1053  return NULL;
1054 
1055  const char *pointGeometryShaderSource = VUOSHADER_GLSL_SOURCE(120, \n#include "trianglePoint.glsl");
1056  const char *lineGeometryShaderSource = VUOSHADER_GLSL_SOURCE(120, \n#include "triangleLine.glsl");
1057 
1058  static const char *triangleGeometryShaderSource = VUOSHADER_GLSL_SOURCE(120,
1059  \n#include "VuoGlslTangent.glsl"
1060 
1061  uniform mat4 modelviewMatrix;
1062 
1063  // Inputs
1064  varying in vec3 geometryPosition[3];
1065  varying in vec3 geometryNormal[3];
1066  varying in vec2 geometryTextureCoordinate[3];
1067  varying in vec4 geometryVertexColor[3];
1068 
1069  // Outputs
1070  varying out vec3 fragmentPosition;
1071  varying out vec2 fragmentTextureCoordinate;
1072  varying out vec4 fragmentVertexColor;
1073  varying out mat3 vertexPlaneToWorld;
1074 
1075  void main()
1076  {
1077  VuoGlslTangent_In ti;
1078  for (int i = 0; i < 3; ++i)
1079  {
1080  ti.position[i] = geometryPosition[i];
1081  ti.normal[i] = geometryNormal[i];
1082  ti.textureCoordinate[i] = geometryTextureCoordinate[i];
1083  }
1084  VuoGlslTangent_Out to;
1085  VuoGlsl_calculateTangent(ti, to);
1086 
1087  for (int i = 0; i < 3; ++i)
1088  {
1089  gl_Position = gl_PositionIn[i];
1090  fragmentPosition = geometryPosition[i];
1091  fragmentTextureCoordinate = geometryTextureCoordinate[i];
1092  fragmentVertexColor = geometryVertexColor[i];
1093 
1094  vertexPlaneToWorld[0] = normalize(vec3(modelviewMatrix * vec4(to.tangent[i], 0.)));
1095  vertexPlaneToWorld[1] = normalize(vec3(modelviewMatrix * -vec4(to.bitangent[i], 0.)));
1096  vertexPlaneToWorld[2] = normalize(vec3(modelviewMatrix * vec4(geometryNormal[i], 0.)));
1097 
1098  EmitVertex();
1099  }
1100  EndPrimitive();
1101  }
1102  );
1103 
1104  const char *fragmentShaderSource = VUOSHADER_GLSL_SOURCE(120,
1105  \n#include "VuoGlslAlpha.glsl"
1106  \n#include "lighting.glsl"
1107 
1108  // Inputs from vertex shader
1109  varying vec2 fragmentTextureCoordinate;
1110  varying vec4 fragmentVertexColor;
1111  varying mat3 vertexPlaneToWorld;
1112 
1113  // Inputs from ports
1114  uniform sampler2D texture;
1115  uniform float alpha;
1116  uniform sampler2D specularImage;
1117  uniform sampler2D normalImage;
1118  uniform vec4 blah;
1119 
1120  void main()
1121  {
1122  // Work around ATI Radeon HD 5770 bug.
1123  // It seems that the rest of the shader isn't executed unless we initialize the output with a uniform.
1124  // https://b33p.net/kosada/node/11256
1125  gl_FragColor = blah;
1126 
1127  vec4 color = VuoGlsl_sample(texture, fragmentTextureCoordinate);
1128  color *= alpha;
1129  VuoGlsl_discardInvisible(color.a);
1130 
1131  vec3 ambientContribution = vec3(0.);
1132  vec3 diffuseContribution = vec3(0.);
1133  vec3 specularContribution = vec3(0.);
1134 
1135  vec4 specularColor = texture2D(specularImage, fragmentTextureCoordinate);
1136  float specularPower = 1./(1.0001-specularColor.a);
1137 
1138  vec4 normalColor = texture2D(normalImage, fragmentTextureCoordinate);
1139  vec3 normal = normalize(vec3(
1140  2. * normalColor.r - 1.,
1141  2. * normalColor.g - 1.,
1142  normalColor.b // Leave the blue channel as-is; the normal should never point inward.
1143  ));
1144 
1145  vec3 normalDirection = vertexPlaneToWorld * normal;
1146 
1147  calculateLighting(specularPower, normalDirection, ambientContribution, diffuseContribution, specularContribution);
1148 
1149  ambientContribution *= color.rgb * fragmentVertexColor.rgb;
1150  diffuseContribution *= color.rgb * fragmentVertexColor.rgb;
1151  specularContribution *= specularColor.rgb * specularColor.a;
1152  gl_FragColor = vec4(ambientContribution + diffuseContribution + specularContribution, color.a * fragmentVertexColor.a);
1153  }
1154  );
1155 
1156  VuoShader shader = VuoShader_make("Image Details Shader (Lit)");
1157 
1158  VuoShader_addSource (shader, VuoMesh_Points, lightingVertexShaderSourceForGeometry, pointGeometryShaderSource, fragmentShaderSource);
1160 
1161  VuoShader_addSource (shader, VuoMesh_IndividualLines, lightingVertexShaderSourceForGeometry, lineGeometryShaderSource, fragmentShaderSource);
1163 
1164  VuoShader_addSource (shader, VuoMesh_IndividualTriangles, lightingVertexShaderSourceForGeometry, triangleGeometryShaderSource, fragmentShaderSource);
1165 
1166  VuoShader_setUniform_VuoImage(shader, "texture", image);
1167  VuoShader_setUniform_VuoReal (shader, "alpha", alpha);
1168  VuoShader_setUniform_VuoImage(shader, "specularImage", specularImage);
1169  VuoShader_setUniform_VuoImage(shader, "normalImage", normalImage);
1170  VuoShader_setUniform_VuoColor(shader, "blah", VuoColor_makeWithRGBA(42,42,42,42));
1171 
1172  return shader;
1173 }
1174 
1181 {
1182  const char *fragmentShaderSource = VUOSHADER_GLSL_SOURCE(120,
1183  \n#include "VuoGlslAlpha.glsl"
1184  \n#include "VuoGlslRandom.glsl"
1185 
1186  uniform float inputColorCount;
1187  uniform float stripColorCount;
1188  uniform sampler2D gradientStrip;
1189  uniform vec2 start;
1190  uniform vec2 end;
1191  uniform float aspect;
1192  uniform float noiseAmount;
1193 
1194  varying vec2 fragmentTextureCoordinate;
1195 
1196  float distSqr(vec2 a, vec2 b)
1197  {
1198  return (b.x-a.x)*(b.x-a.x) + (b.y-a.y)*(b.y-a.y);
1199  }
1200 
1201  // https://stackoverflow.com/questions/849211/shortest-distance-between-a-point-and-a-line-segment
1202  // ...minus the segment part, of course.
1203  vec2 nearest_point_on_line(vec2 v, vec2 w, vec2 p)
1204  {
1205  // Return minimum distance between line segment vw and point p
1206  float l2 = distSqr(v, w); // i.e. |w-v|^2 - avoid a sqrt
1207  if (l2 == 0.0) return p;
1208  // Consider the line extending the segment, parameterized as v + t (w - v).
1209  // We find projection of point p onto the line.
1210  // It falls where t = [(p-v) . (w-v)] / |w-v|^2
1211  float t = dot(p - v, w - v) / l2;
1212  vec2 projection = v + t * (w - v);
1213  return projection;
1214  }
1215 
1216  void main(void)
1217  {
1218  vec2 tcAspect = fragmentTextureCoordinate;
1219  tcAspect.y -= .5;
1220  tcAspect.y *= aspect;
1221  tcAspect.y += .5;
1222 
1223  vec2 pol = nearest_point_on_line(start, end, tcAspect);
1224  float x = dot(pol-start, end-start) > 0 ? distance(start, pol)/ distance(start, end) : 0;
1225 
1226  // Give x a smooth second-derivative, to reduce the ridges between colors.
1227  x *= inputColorCount - 1.;
1228  x = floor(x) + smoothstep(0.,1.,fract(x));
1229  x /= inputColorCount - 1.;
1230 
1231  float gradientWidth = (1./stripColorCount)/2.;
1232  x = x * (1-gradientWidth*2) + gradientWidth; // scale to account for the gradient/2 offsets
1233 
1234  vec4 color = VuoGlsl_sample(gradientStrip, vec2(clamp(x , gradientWidth, 1.-gradientWidth), .5));
1235  VuoGlsl_discardInvisible(color.a);
1236 
1237  color.rgb += (VuoGlsl_random2D3D(fragmentTextureCoordinate) - 0.5) * noiseAmount;
1238 
1239  gl_FragColor = color;
1240  }
1241  );
1242 
1243  VuoShader shader = VuoShader_make("Linear Gradient Shader");
1244  VuoShader_addSource(shader, VuoMesh_IndividualTriangles, NULL, NULL, fragmentShaderSource);
1245  return shader;
1246 }
1247 
1252 {
1253  // https://b33p.net/kosada/node/12582
1254  // Instead of creating an image with only one pixel per color stop,
1255  // create `gradientExpansion` pixels per stop, to compensate for GPUs
1256  // that have limited ability to interpolate between pixels.
1257  // E.g., the Intel HD Graphics 3000 GPU limits interpolation to 64 steps.
1258  // On Intel 3000, gradientExpansion=4 would result in 256 steps (64*4);
1259  // go beyond that to provide some extra detail when rendering to 16bpc textures.
1260  int gradientExpansion = 16;
1261 
1262  GLenum format = GL_BGRA;
1263  int bpp = 4;
1264  if (VuoColor_areAllOpaque(colors))
1265  {
1266  format = GL_BGR;
1267  bpp = 3;
1268  }
1269 
1270  int inputColorCount = VuoListGetCount_VuoColor(colors);
1271  int stripColorCount = (inputColorCount - 1) * gradientExpansion + 1;
1272 
1273  unsigned char *pixels = (unsigned char*)malloc(stripColorCount * bpp);
1274  int inputColor = 1;
1275  int step = 0;
1276  for (int i = 0; i < stripColorCount; ++i)
1277  {
1278  VuoColor col1 = VuoListGetValue_VuoColor(colors, inputColor);
1279  VuoColor col2 = VuoListGetValue_VuoColor(colors, inputColor+1);
1280 
1281  VuoColor col = VuoColor_lerp(col1, col2, (float)step / gradientExpansion);
1282 
1283  pixels[i * bpp ] = VuoInteger_clamp(col.a * col.b * 255, 0, 255);
1284  pixels[i * bpp + 1 ] = VuoInteger_clamp(col.a * col.g * 255, 0, 255);
1285  pixels[i * bpp + 2 ] = VuoInteger_clamp(col.a * col.r * 255, 0, 255);
1286  if (bpp == 4)
1287  pixels[i * bpp + 3] = VuoInteger_clamp(col.a * 255, 0, 255);
1288 
1289  ++step;
1290  if (step >= gradientExpansion)
1291  {
1292  step = 0;
1293  ++inputColor;
1294  }
1295  }
1296 
1297  VuoImage gradientStrip = VuoImage_makeFromBuffer(pixels, format, stripColorCount, 1, VuoImageColorDepth_8, ^(void *buffer){ free(buffer); });
1298 
1299  VuoShader_setUniform_VuoImage (shader, "gradientStrip", gradientStrip);
1300  VuoShader_setUniform_VuoReal (shader, "inputColorCount", inputColorCount);
1301  VuoShader_setUniform_VuoReal (shader, "stripColorCount", stripColorCount);
1302 }
1303 
1308 void VuoShader_setLinearGradientShaderValues(VuoShader shader, VuoList_VuoColor colors, VuoPoint2d start, VuoPoint2d end, VuoReal aspect, VuoReal noiseAmount)
1309 {
1310  VuoShader_setGradientStrip(shader, colors);
1311  VuoShader_setUniform_VuoPoint2d(shader, "start", VuoPoint2d_make((start.x+1)/2, (start.y+1)/2));
1312  VuoShader_setUniform_VuoPoint2d(shader, "end", VuoPoint2d_make((end.x+1)/2, (end.y+1)/2));
1313  VuoShader_setUniform_VuoReal (shader, "aspect", 1./aspect);
1314  VuoShader_setUniform_VuoReal (shader, "noiseAmount", MAX(0.,noiseAmount/10.));
1315 }
1316 
1323 {
1324  const char *fragmentShaderSource = VUOSHADER_GLSL_SOURCE(120,
1325  \n#include "VuoGlslAlpha.glsl"
1326  \n#include "VuoGlslRandom.glsl"
1327 
1328  uniform float inputColorCount;
1329  uniform float stripColorCount;
1330  uniform sampler2D gradientStrip;
1331  uniform vec2 center;
1332  uniform vec2 scale; // if image is not square, multiply texCoord by this to account for stretch
1333  uniform float radius;
1334  uniform float noiseAmount;
1335 
1336  varying vec2 fragmentTextureCoordinate;
1337 
1338  void main(void)
1339  {
1340  vec2 scaledTexCoord = fragmentTextureCoordinate*scale;
1341  float x = distance(center*scale, scaledTexCoord)/radius;
1342 
1343  // Give x a smooth second-derivative, to reduce the ridges between colors.
1344  x *= inputColorCount - 1.;
1345  x = floor(x) + smoothstep(0.,1.,fract(x));
1346  x /= inputColorCount - 1.;
1347 
1348  float gradientWidth = (1./stripColorCount)/2.;
1349  x = x * (1-gradientWidth*2) + gradientWidth;
1350 
1351  vec4 color = VuoGlsl_sample(gradientStrip, vec2(clamp(x , gradientWidth, 1.-gradientWidth), .5));
1352  VuoGlsl_discardInvisible(color.a);
1353 
1354  color.rgb += (VuoGlsl_random2D3D(fragmentTextureCoordinate) - 0.5) * noiseAmount;
1355 
1356  gl_FragColor = color;
1357  }
1358  );
1359 
1360  VuoShader shader = VuoShader_make("Radial Gradient Shader");
1361  VuoShader_addSource(shader, VuoMesh_IndividualTriangles, NULL, NULL, fragmentShaderSource);
1362  return shader;
1363 }
1364 
1370 void VuoShader_setRadialGradientShaderValues(VuoShader shader, VuoList_VuoColor colors, VuoPoint2d center, VuoReal radius, VuoReal width, VuoReal height, VuoReal noiseAmount)
1371 {
1372  // VuoPoint2d scale = width < height ? VuoPoint2d_make(1., height/(float)width) : VuoPoint2d_make(width/(float)height, 1.);
1373  VuoPoint2d scale = VuoPoint2d_make(1., height/(float)width);
1374 
1375  VuoShader_setGradientStrip(shader, colors);
1376  VuoShader_setUniform_VuoPoint2d(shader, "center", VuoPoint2d_make((center.x+1)/2, (center.y+1)/2));
1377  VuoShader_setUniform_VuoReal (shader, "radius", radius > 0. ? radius/2. : 0);
1378  VuoShader_setUniform_VuoPoint2d(shader, "scale", VuoPoint2d_make(scale.x, scale.y));
1379  VuoShader_setUniform_VuoReal (shader, "noiseAmount", MAX(0.,noiseAmount/10.));
1380 }
1381 
1386 {
1387  const char *vertexShaderSourceForGeometry = VUOSHADER_GLSL_SOURCE(120,
1388  \n#include "VuoGlslProjection.glsl"
1389 
1390  // Inputs provided by VuoSceneRenderer
1391  uniform mat4 modelviewMatrix;
1392  attribute vec3 position;
1393  attribute vec3 normal;
1394  attribute vec2 textureCoordinate;
1395  attribute vec4 vertexColor;
1396  uniform bool hasVertexColors;
1397 
1398  // Outputs to geometry shader
1399  varying vec3 geometryPosition;
1400  varying vec3 geometryNormal;
1401  varying vec2 geometryTextureCoordinate;
1402  varying vec4 geometryVertexColor;
1403 
1404  void main()
1405  {
1406  geometryPosition = (modelviewMatrix * vec4(position, 1.)).xyz;
1407  geometryNormal = (modelviewMatrix * vec4(normal, 0.)).xyz;
1408  geometryTextureCoordinate = textureCoordinate;
1409  geometryVertexColor = hasVertexColors ? vertexColor : vec4(1.);
1410  gl_Position = VuoGlsl_projectPosition(geometryPosition);
1411  }
1412  );
1413 
1414  const char *pointGeometryShaderSource = VUOSHADER_GLSL_SOURCE(120, \n#include "trianglePoint.glsl");
1415  const char *lineGeometryShaderSource = VUOSHADER_GLSL_SOURCE(120, \n#include "triangleLine.glsl");
1416 
1417  const char *fragmentShaderSource = VUOSHADER_GLSL_SOURCE(120,
1418  \n#include "VuoGlslAlpha.glsl"
1419  \n#include "noise3D.glsl"
1420 
1421  // Inputs provided by VuoSceneRenderer
1422  uniform sampler2D colorBuffer;
1423  uniform vec2 viewportSize;
1424 
1425  // Inputs from ports
1426  uniform vec4 color;
1427  uniform float aspectRatio;
1428  uniform vec2 noisePosition;
1429  uniform float noiseTime;
1430  uniform float noiseAmount;
1431  uniform float noiseScale;
1432  uniform float chromaticAberration;
1433  uniform int iterations;
1434  uniform int levels;
1435  uniform float roughness;
1436  uniform float spacing;
1437 
1438  // Inputs from vertex shader
1439  varying vec2 fragmentTextureCoordinate;
1440  varying vec4 fragmentVertexColor;
1441 
1442  void main()
1443  {
1444  vec2 viewportTextureCoordinate = gl_FragCoord.xy/viewportSize;
1445 
1446  vec4 accumulatedColor = vec4(0.);
1447  for (int i = 0; i < iterations; ++i)
1448  {
1449  // 3D noise, since we want a continuous 2D texture that moves continuously through time.
1450  // The iteration index needn't be continuous.
1451  vec3 noiseCoordinate = vec3(fragmentTextureCoordinate.x - .5 - noisePosition.x + float(i), (fragmentTextureCoordinate.y - .5 - noisePosition.y) / aspectRatio, noiseTime);
1452  noiseCoordinate.xy *= noiseScale;
1453  vec2 noiseOffset = snoise3D2DFractal(noiseCoordinate, levels, roughness, spacing);
1454 
1455  // Red
1456  accumulatedColor += VuoGlsl_sample(colorBuffer, viewportTextureCoordinate + noiseOffset * noiseAmount * (1. - chromaticAberration/3.)) * vec4(1.,0.,0.,1./3.);
1457 
1458  // Green
1459  accumulatedColor += VuoGlsl_sample(colorBuffer, viewportTextureCoordinate + noiseOffset * noiseAmount) * vec4(0.,1.,0.,1./3.);
1460 
1461  // Blue
1462  accumulatedColor += VuoGlsl_sample(colorBuffer, viewportTextureCoordinate + noiseOffset * noiseAmount * (1. + chromaticAberration/3.)) * vec4(0.,0.,1.,1./3.);
1463  }
1464 
1465  vec4 c = accumulatedColor / float(iterations);
1466  c.rgb /= c.a;
1467  c *= color * fragmentVertexColor;
1468  c.rgb = clamp(c.rgb, 0., 1.);
1469  c.rgb *= c.a;
1470  gl_FragColor = c;
1471  }
1472  );
1473 
1474  const char *fragmentShaderSourceForGeometry = VUOSHADER_GLSL_SOURCE(120,
1475  \n#include "VuoGlslAlpha.glsl"
1476  \n#include "noise3D.glsl"
1477 
1478  // Inputs provided by VuoSceneRenderer
1479  uniform sampler2D colorBuffer;
1480  uniform vec2 viewportSize;
1481 
1482  // Inputs from ports
1483  uniform vec4 color;
1484  uniform float aspectRatio;
1485  uniform vec2 noisePosition;
1486  uniform float noiseTime;
1487  uniform float noiseAmount;
1488  uniform float noiseScale;
1489  uniform float chromaticAberration;
1490  uniform int iterations;
1491  uniform int levels;
1492  uniform float roughness;
1493  uniform float spacing;
1494 
1495  // Inputs from geometry shader
1496  varying vec3 fragmentPosition;
1497  varying vec2 fragmentTextureCoordinate;
1498 
1499  void main()
1500  {
1501  // Work around ATI Radeon HD 5770 bug.
1502  // It seems that the rest of the shader isn't executed unless we initialize the output with a uniform.
1503  // https://b33p.net/kosada/node/11256
1504  gl_FragColor = color;
1505 
1506  fragmentPosition;
1507 
1508  vec2 viewportTextureCoordinate = gl_FragCoord.xy/viewportSize;
1509 
1510  vec4 accumulatedColor = vec4(0.);
1511  for (int i = 0; i < iterations; ++i)
1512  {
1513  // 3D noise, since we want a continuous 2D texture that moves continuously through time.
1514  // The iteration index needn't be continuous.
1515  vec3 noiseCoordinate = vec3(fragmentTextureCoordinate.x - .5 - noisePosition.x + float(i), (fragmentTextureCoordinate.y - .5 - noisePosition.y) / aspectRatio, noiseTime);
1516  noiseCoordinate.xy *= noiseScale;
1517  vec2 noiseOffset = snoise3D2DFractal(noiseCoordinate, levels, roughness, spacing);
1518 
1519  // Red
1520  accumulatedColor += VuoGlsl_sample(colorBuffer, viewportTextureCoordinate + noiseOffset * noiseAmount * (1. - chromaticAberration/3.)) * vec4(1.,0.,0.,1./3.);
1521 
1522  // Green
1523  accumulatedColor += VuoGlsl_sample(colorBuffer, viewportTextureCoordinate + noiseOffset * noiseAmount) * vec4(0.,1.,0.,1./3.);
1524 
1525  // Blue
1526  accumulatedColor += VuoGlsl_sample(colorBuffer, viewportTextureCoordinate + noiseOffset * noiseAmount * (1. + chromaticAberration/3.)) * vec4(0.,0.,1.,1./3.);
1527  }
1528 
1529  vec4 c = accumulatedColor / float(iterations);
1530  c.rgb /= c.a;
1531  c *= color;
1532  c.rgb = clamp(c.rgb, 0., 1.);
1533  c.rgb *= c.a;
1534  gl_FragColor = c;
1535  }
1536  );
1537 
1538  VuoShader s = VuoShader_make("Frosted Glass Shader");
1539  s->isTransparent = true;
1540 
1541  VuoShader_addSource (s, VuoMesh_Points, vertexShaderSourceForGeometry, pointGeometryShaderSource, fragmentShaderSourceForGeometry);
1543 
1544  VuoShader_addSource (s, VuoMesh_IndividualLines, vertexShaderSourceForGeometry, lineGeometryShaderSource, fragmentShaderSourceForGeometry);
1546 
1547  VuoShader_addSource (s, VuoMesh_IndividualTriangles, NULL, NULL, fragmentShaderSource);
1548 
1549  return s;
1550 }
1551 
1557 void VuoShader_setFrostedGlassShaderValues(VuoShader shader, VuoColor color, VuoReal brightness, VuoPoint2d noisePosition, VuoReal noiseTime, VuoReal noiseAmount, VuoReal noiseScale, VuoReal chromaticAberration, VuoInteger levels, VuoReal roughness, VuoReal spacing, VuoInteger iterations, float aspectRatio)
1558 {
1559  VuoShader_setUniform_VuoPoint4d(shader, "color", VuoPoint4d_make(color.r*brightness, color.g*brightness, color.b*brightness, color.a));
1560  VuoShader_setUniform_VuoPoint2d(shader, "noisePosition", (VuoPoint2d){(noisePosition.x+1)/2,
1561  (noisePosition.y+1)/2 * aspectRatio});
1562  VuoShader_setUniform_VuoReal (shader, "noiseTime", noiseTime);
1563  VuoShader_setUniform_VuoReal (shader, "noiseAmount", MAX(0.,noiseAmount/10.));
1564  VuoShader_setUniform_VuoReal (shader, "noiseScale", 1./VuoReal_makeNonzero(noiseScale));
1565  VuoShader_setUniform_VuoReal (shader, "chromaticAberration", VuoReal_clamp(chromaticAberration, 0, 2));
1566  VuoShader_setUniform_VuoInteger(shader, "iterations", MAX(1, iterations));
1567  VuoShader_setUniform_VuoInteger(shader, "levels", MAX(1, levels));
1568  VuoShader_setUniform_VuoReal (shader, "roughness", roughness);
1569  VuoShader_setUniform_VuoReal (shader, "spacing", spacing);
1570 }