You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

125 lines
3.1KB

  1. #pragma once
  2. #include "nanovg.h"
  3. /**
  4. * Renders animated noise image sing nanogl
  5. */
  6. // 0 = random pixel grey level
  7. // 1 = random white, bk, transparent.
  8. const int method = 0;
  9. class NoiseDrawer
  10. {
  11. public:
  12. NoiseDrawer(NVGcontext *vg, float width, float height)
  13. : _width(width), _height(height)
  14. {
  15. makeImage(vg);
  16. _vg = vg;
  17. }
  18. ~NoiseDrawer()
  19. {
  20. nvgDeleteImage(_vg, _image);
  21. _image = 0;
  22. }
  23. void draw(NVGcontext *vg, float colorX, float colorY, float colorWidth, float colorHeight);
  24. private:
  25. /**
  26. * Holds an image (gl texture) in memory for
  27. * the lifetime of the plugin instance.
  28. */
  29. int _image = 0;
  30. NVGcontext* _vg = nullptr;
  31. const int _width, _height;
  32. int frameCount = 0;
  33. float randomX = 0;
  34. float randomY = 0;
  35. void makeImage(NVGcontext *vg);
  36. };
  37. inline void NoiseDrawer::makeImage(NVGcontext *vg)
  38. {
  39. // let's synthesize some white noise
  40. const int memSize = _width * _height * 4;
  41. unsigned char * memImage = new unsigned char[memSize];
  42. for (int row = 0; row < _height; ++row) {
  43. for (int col = 0; col < _width; ++col) {
  44. unsigned char * pix = memImage + (4 * (row*_width + col));
  45. if (method == 0) {
  46. int value = int((255.f * rand()) / float(RAND_MAX));
  47. pix[0] = value;
  48. pix[1] = value;
  49. pix[2] = value;
  50. pix[3] = 255; // opaque, for now
  51. } else if (method == 1) {
  52. //generate 0 .. 100
  53. int rnd = int((100.f * rand()) / float(RAND_MAX));
  54. int value, alpha;
  55. if (rnd > 75) {
  56. value = 0;
  57. alpha = 255;
  58. } else if (rnd > 75) {
  59. value = 255;
  60. alpha = 255;
  61. } else {
  62. value = 128;
  63. alpha = 0;
  64. }
  65. pix[0] = value;
  66. pix[1] = value;
  67. pix[2] = value;
  68. pix[3] = alpha;
  69. }
  70. }
  71. }
  72. _image = nvgCreateImageRGBA(vg,
  73. _width,
  74. _height,
  75. NVG_IMAGE_REPEATX | NVG_IMAGE_REPEATY,
  76. memImage);
  77. assert(_image != 0);
  78. delete[] memImage;
  79. }
  80. inline void NoiseDrawer::draw(NVGcontext *vg,
  81. float drawX,
  82. float drawY,
  83. float drawWidth,
  84. float drawHeight)
  85. {
  86. assert(_image);
  87. // noise looks slightly better with anti-alias off?
  88. nvgShapeAntiAlias(vg, false);
  89. // Don't update the noise position every frame. Old TV is only
  90. // 30 fps, and this looks better even slower.
  91. if (frameCount++ > 3) {
  92. randomX = (float) rand() * _width / float(RAND_MAX);
  93. randomY = (float) rand() * _height / float(RAND_MAX);
  94. frameCount = 0;
  95. }
  96. // Clever trick. We don't draw new noise every time, we just
  97. // draw the same noise image from a random offset.
  98. NVGpaint paint = nvgImagePattern(vg,
  99. randomX, randomY,
  100. _width, _height,
  101. 0, _image, 0.15f);
  102. nvgBeginPath(vg);
  103. nvgRect(vg, drawX, drawY, drawWidth, drawHeight);
  104. nvgFillPaint(vg, paint);
  105. nvgFill(vg);
  106. }