perlinnoise.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /*
  2. * Copyright 2013 Google Inc.
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. #include "gm/gm.h"
  8. #include "include/core/SkCanvas.h"
  9. #include "include/core/SkColor.h"
  10. #include "include/core/SkMatrix.h"
  11. #include "include/core/SkPaint.h"
  12. #include "include/core/SkRect.h"
  13. #include "include/core/SkRefCnt.h"
  14. #include "include/core/SkScalar.h"
  15. #include "include/core/SkShader.h"
  16. #include "include/core/SkSize.h"
  17. #include "include/core/SkString.h"
  18. #include "include/effects/SkPerlinNoiseShader.h"
  19. #include <utility>
  20. namespace {
  21. enum class Type {
  22. kFractalNoise,
  23. kTurbulence,
  24. };
  25. class PerlinNoiseGM : public skiagm::GM {
  26. SkISize fSize = {80, 80};
  27. void onOnceBeforeDraw() override { this->setBGColor(0xFF000000); }
  28. SkString onShortName() override { return SkString("perlinnoise"); }
  29. SkISize onISize() override { return {200, 500}; }
  30. void drawRect(SkCanvas* canvas, int x, int y, const SkPaint& paint, const SkISize& size) {
  31. canvas->save();
  32. canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
  33. SkRect r = SkRect::MakeWH(SkIntToScalar(size.width()),
  34. SkIntToScalar(size.height()));
  35. canvas->drawRect(r, paint);
  36. canvas->restore();
  37. }
  38. void test(SkCanvas* canvas, int x, int y, Type type,
  39. float baseFrequencyX, float baseFrequencyY, int numOctaves, float seed,
  40. bool stitchTiles) {
  41. SkISize tileSize = SkISize::Make(fSize.width() / 2, fSize.height() / 2);
  42. sk_sp<SkShader> shader = (type == Type::kFractalNoise) ?
  43. SkPerlinNoiseShader::MakeFractalNoise(baseFrequencyX, baseFrequencyY, numOctaves,
  44. seed, stitchTiles ? &tileSize : nullptr) :
  45. SkPerlinNoiseShader::MakeTurbulence(baseFrequencyX, baseFrequencyY, numOctaves,
  46. seed, stitchTiles ? &tileSize : nullptr);
  47. SkPaint paint;
  48. paint.setShader(std::move(shader));
  49. if (stitchTiles) {
  50. drawRect(canvas, x, y, paint, tileSize);
  51. x += tileSize.width();
  52. drawRect(canvas, x, y, paint, tileSize);
  53. y += tileSize.width();
  54. drawRect(canvas, x, y, paint, tileSize);
  55. x -= tileSize.width();
  56. drawRect(canvas, x, y, paint, tileSize);
  57. } else {
  58. drawRect(canvas, x, y, paint, fSize);
  59. }
  60. }
  61. void onDraw(SkCanvas* canvas) override {
  62. canvas->clear(SK_ColorBLACK);
  63. test(canvas, 0, 0, Type::kFractalNoise,
  64. 0.1f, 0.1f, 0, 0, false);
  65. test(canvas, 100, 0, Type::kTurbulence,
  66. 0.1f, 0.1f, 0, 0, false);
  67. test(canvas, 0, 100, Type::kFractalNoise,
  68. 0.1f, 0.1f, 2, 0, false);
  69. test(canvas, 100, 100, Type::kFractalNoise,
  70. 0.05f, 0.1f, 1, 0, true);
  71. test(canvas, 0, 200, Type::kTurbulence,
  72. 0.1f, 0.1f, 1, 0, true);
  73. test(canvas, 100, 200, Type::kTurbulence,
  74. 0.2f, 0.4f, 5, 0, false);
  75. test(canvas, 0, 300, Type::kFractalNoise,
  76. 0.1f, 0.1f, 3, 1, false);
  77. test(canvas, 100, 300, Type::kFractalNoise,
  78. 0.1f, 0.1f, 3, 4, false);
  79. canvas->scale(0.75f, 1.0f);
  80. test(canvas, 0, 400, Type::kFractalNoise,
  81. 0.1f, 0.1f, 2, 0, false);
  82. test(canvas, 100, 400, Type::kFractalNoise,
  83. 0.1f, 0.05f, 1, 0, true);
  84. }
  85. private:
  86. typedef GM INHERITED;
  87. };
  88. class PerlinNoiseGM2 : public skiagm::GM {
  89. SkISize fSize = {80, 80};
  90. SkString onShortName() override { return SkString("perlinnoise_localmatrix"); }
  91. SkISize onISize() override { return {640, 480}; }
  92. void install(SkPaint* paint, Type type,
  93. float baseFrequencyX, float baseFrequencyY, int numOctaves, float seed,
  94. bool stitchTiles) {
  95. sk_sp<SkShader> shader = (type == Type::kFractalNoise) ?
  96. SkPerlinNoiseShader::MakeFractalNoise(baseFrequencyX, baseFrequencyY, numOctaves,
  97. seed, stitchTiles ? &fSize : nullptr) :
  98. SkPerlinNoiseShader::MakeTurbulence(baseFrequencyX, baseFrequencyY, numOctaves,
  99. seed, stitchTiles ? &fSize : nullptr);
  100. paint->setShader(std::move(shader));
  101. }
  102. void onDraw(SkCanvas* canvas) override {
  103. canvas->translate(10, 10);
  104. SkPaint paint;
  105. this->install(&paint, Type::kFractalNoise, 0.1f, 0.1f, 2, 0, false);
  106. const SkScalar w = SkIntToScalar(fSize.width());
  107. const SkScalar h = SkIntToScalar(fSize.height());
  108. SkRect r = SkRect::MakeWH(w, h);
  109. canvas->drawRect(r, paint);
  110. canvas->save();
  111. canvas->translate(w * 5/4, 0);
  112. canvas->drawRect(r, paint);
  113. canvas->restore();
  114. canvas->save();
  115. canvas->translate(0, h + 10);
  116. canvas->scale(2, 2);
  117. canvas->drawRect(r, paint);
  118. canvas->restore();
  119. canvas->save();
  120. canvas->translate(w + 100, h + 10);
  121. canvas->scale(2, 2);
  122. canvas->drawRect(r, paint);
  123. canvas->restore();
  124. // The next row should draw the same as the previous, even though we are using a local
  125. // matrix instead of the canvas.
  126. canvas->translate(0, h * 2 + 10);
  127. SkMatrix lm;
  128. lm.setScale(2, 2);
  129. paint.setShader(paint.getShader()->makeWithLocalMatrix(lm));
  130. r.fRight += r.width();
  131. r.fBottom += r.height();
  132. canvas->save();
  133. canvas->translate(0, h + 10);
  134. canvas->drawRect(r, paint);
  135. canvas->restore();
  136. canvas->save();
  137. canvas->translate(w + 100, h + 10);
  138. canvas->drawRect(r, paint);
  139. canvas->restore();
  140. }
  141. };
  142. } // namespace
  143. DEF_GM( return new PerlinNoiseGM; )
  144. DEF_GM( return new PerlinNoiseGM2; )