1e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com/* 2e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com * Copyright 2013 Google Inc. 3e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com * 4e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com * Use of this source code is governed by a BSD-style license that can be 5e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com * found in the LICENSE file. 6e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com */ 7e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 8e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com#ifndef SkPerlinNoiseShader_DEFINED 9e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com#define SkPerlinNoiseShader_DEFINED 10e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 11e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com#include "SkShader.h" 12e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 13e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com/** \class SkPerlinNoiseShader 14e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 15e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkPerlinNoiseShader creates an image using the Perlin turbulence function. 16e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 17e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com It can produce tileable noise if asked to stitch tiles and provided a tile size. 18e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com In order to fill a large area with repeating noise, set the stitchTiles flag to 19e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com true, and render exactly a single tile of noise. Without this flag, the result 20e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com will contain visible seams between tiles. 21e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 22e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com The algorithm used is described here : 23e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com http://www.w3.org/TR/SVG/filters.html#feTurbulenceElement 24e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com*/ 25384f5e2a9b491c4ae814a465c167612fafdcd89fsugoi@google.comclass SK_API SkPerlinNoiseShader : public SkShader { 26e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.compublic: 27e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com struct StitchData; 28ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco struct PaintingData; 29e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 30e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com /** 31e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com * About the noise types : the difference between the 2 is just minor tweaks to the algorithm, 32e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com * they're not 2 entirely different noises. The output looks different, but once the noise is 33e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com * generated in the [1, -1] range, the output is brought back in the [0, 1] range by doing : 34e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com * kFractalNoise_Type : noise * 0.5 + 0.5 35e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com * kTurbulence_Type : abs(noise) 36e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com * Very little differences between the 2 types, although you can tell the difference visually. 37e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com */ 38e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com enum Type { 39e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com kFractalNoise_Type, 40e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com kTurbulence_Type, 41e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com kFirstType = kFractalNoise_Type, 42e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com kLastType = kTurbulence_Type 43e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com }; 44e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com /** 45e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com * This will construct Perlin noise of the given type (Fractal Noise or Turbulence). 46e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com * 47e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com * Both base frequencies (X and Y) have a usual range of (0..1). 48e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com * 49e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com * The number of octaves provided should be fairly small, although no limit is enforced. 50e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com * Each octave doubles the frequency, so 10 octaves would produce noise from 51e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com * baseFrequency * 1, * 2, * 4, ..., * 512, which quickly yields insignificantly small 52e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com * periods and resembles regular unstructured noise rather than Perlin noise. 53e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com * 54e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com * If tileSize isn't NULL or an empty size, the tileSize parameter will be used to modify 55e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com * the frequencies so that the noise will be tileable for the given tile size. If tileSize 56e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com * is NULL or an empty size, the frequencies will be used as is without modification. 57e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com */ 58e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com static SkShader* CreateFractalNoise(SkScalar baseFrequencyX, SkScalar baseFrequencyY, 59e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com int numOctaves, SkScalar seed, 60e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const SkISize* tileSize = NULL); 619fbbcca1c958e6df2cff24d3ccdb7ebd89b8486bcommit-bot@chromium.org static SkShader* CreateTurbulence(SkScalar baseFrequencyX, SkScalar baseFrequencyY, 62e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com int numOctaves, SkScalar seed, 63e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const SkISize* tileSize = NULL); 649fbbcca1c958e6df2cff24d3ccdb7ebd89b8486bcommit-bot@chromium.org /** 659fbbcca1c958e6df2cff24d3ccdb7ebd89b8486bcommit-bot@chromium.org * Create alias for CreateTurbulunce until all Skia users changed 669fbbcca1c958e6df2cff24d3ccdb7ebd89b8486bcommit-bot@chromium.org * its code to use the new naming 679fbbcca1c958e6df2cff24d3ccdb7ebd89b8486bcommit-bot@chromium.org */ 689fbbcca1c958e6df2cff24d3ccdb7ebd89b8486bcommit-bot@chromium.org static SkShader* CreateTubulence(SkScalar baseFrequencyX, SkScalar baseFrequencyY, 699fbbcca1c958e6df2cff24d3ccdb7ebd89b8486bcommit-bot@chromium.org int numOctaves, SkScalar seed, 709fbbcca1c958e6df2cff24d3ccdb7ebd89b8486bcommit-bot@chromium.org const SkISize* tileSize = NULL) { 71c282ba85bababb903d8cd43320508790195a98f9skia.committer@gmail.com return CreateTurbulence(baseFrequencyX, baseFrequencyY, numOctaves, seed, tileSize); 729fbbcca1c958e6df2cff24d3ccdb7ebd89b8486bcommit-bot@chromium.org } 739fbbcca1c958e6df2cff24d3ccdb7ebd89b8486bcommit-bot@chromium.org 74e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 758d9f2e474ac9d175c28079357b022d31408e2fe4fmalita size_t contextSize(const ContextRec&) const override; 7687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 7787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org class PerlinNoiseShaderContext : public SkShader::Context { 7887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org public: 79e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org PerlinNoiseShaderContext(const SkPerlinNoiseShader& shader, const ContextRec&); 80ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco virtual ~PerlinNoiseShaderContext(); 8187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 8236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void shadeSpan(int x, int y, SkPMColor[], int count) override; 8387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 8487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org private: 8587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkPMColor shade(const SkPoint& point, StitchData& stitchData) const; 8687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkScalar calculateTurbulenceValueForPoint( 87ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco int channel, 8887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org StitchData& stitchData, const SkPoint& point) const; 89ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco SkScalar noise2D(int channel, 9087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org const StitchData& stitchData, const SkPoint& noiseVector) const; 9187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 9287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkMatrix fMatrix; 93ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco PaintingData* fPaintingData; 9487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 9587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org typedef SkShader::Context INHERITED; 9687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org }; 97e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 98c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomon#if SK_SUPPORT_GPU 99c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomon const GrFragmentProcessor* asFragmentProcessor(GrContext* context, const SkMatrix& viewM, 1004a339529612a43871d021877e58698e067d6c4cdbsalomon const SkMatrix*, SkFilterQuality) const override; 101c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomon#endif 102e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 1030f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org SK_TO_STRING_OVERRIDE() 104e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkPerlinNoiseShader) 105e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 106e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.comprotected: 10736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void flatten(SkWriteBuffer&) const override; 10836352bf5e38f45a70ee4f4fc132a38048d38206dmtklein Context* onCreateContext(const ContextRec&, void* storage) const override; 109e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 110e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.comprivate: 111e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkPerlinNoiseShader(SkPerlinNoiseShader::Type type, SkScalar baseFrequencyX, 112e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkScalar baseFrequencyY, int numOctaves, SkScalar seed, 113fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org const SkISize* tileSize); 114e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com virtual ~SkPerlinNoiseShader(); 115e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 1163f3b3d003527861dc0bd89733857576408906431mtklein const SkPerlinNoiseShader::Type fType; 1173f3b3d003527861dc0bd89733857576408906431mtklein const SkScalar fBaseFrequencyX; 1183f3b3d003527861dc0bd89733857576408906431mtklein const SkScalar fBaseFrequencyY; 1193f3b3d003527861dc0bd89733857576408906431mtklein const int fNumOctaves; 1203f3b3d003527861dc0bd89733857576408906431mtklein const SkScalar fSeed; 1213f3b3d003527861dc0bd89733857576408906431mtklein const SkISize fTileSize; 1223f3b3d003527861dc0bd89733857576408906431mtklein const bool fStitchTiles; 123e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 124e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com typedef SkShader INHERITED; 125e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com}; 126e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 127e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com#endif 128