2013-04-05 13:47:09 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2013 Google Inc.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "SkDither.h"
|
|
|
|
#include "SkPerlinNoiseShader.h"
|
2013-11-06 10:08:38 +00:00
|
|
|
#include "SkColorFilter.h"
|
2014-01-30 18:58:24 +00:00
|
|
|
#include "SkReadBuffer.h"
|
|
|
|
#include "SkWriteBuffer.h"
|
2013-04-05 13:47:09 +00:00
|
|
|
#include "SkShader.h"
|
|
|
|
#include "SkUnPreMultiply.h"
|
|
|
|
#include "SkString.h"
|
|
|
|
|
|
|
|
#if SK_SUPPORT_GPU
|
|
|
|
#include "GrContext.h"
|
2013-10-02 13:04:56 +00:00
|
|
|
#include "GrCoordTransform.h"
|
2014-09-23 16:50:21 +00:00
|
|
|
#include "gl/GrGLProcessor.h"
|
2014-08-22 03:18:45 +00:00
|
|
|
#include "gl/builders/GrGLProgramBuilder.h"
|
2014-09-23 16:50:21 +00:00
|
|
|
#include "GrTBackendProcessorFactory.h"
|
2013-04-05 13:47:09 +00:00
|
|
|
#include "SkGr.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static const int kBlockSize = 256;
|
|
|
|
static const int kBlockMask = kBlockSize - 1;
|
|
|
|
static const int kPerlinNoise = 4096;
|
|
|
|
static const int kRandMaximum = SK_MaxS32; // 2**31 - 1
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
// noiseValue is the color component's value (or color)
|
|
|
|
// limitValue is the maximum perlin noise array index value allowed
|
|
|
|
// newValue is the current noise dimension (either width or height)
|
|
|
|
inline int checkNoise(int noiseValue, int limitValue, int newValue) {
|
|
|
|
// If the noise value would bring us out of bounds of the current noise array while we are
|
|
|
|
// stiching noise tiles together, wrap the noise around the current dimension of the noise to
|
|
|
|
// stay within the array bounds in a continuous fashion (so that tiling lines are not visible)
|
|
|
|
if (noiseValue >= limitValue) {
|
|
|
|
noiseValue -= newValue;
|
|
|
|
}
|
|
|
|
return noiseValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline SkScalar smoothCurve(SkScalar t) {
|
2013-11-25 19:44:07 +00:00
|
|
|
static const SkScalar SK_Scalar3 = 3.0f;
|
2013-04-05 13:47:09 +00:00
|
|
|
|
|
|
|
// returns t * t * (3 - 2 * t)
|
|
|
|
return SkScalarMul(SkScalarSquare(t), SK_Scalar3 - 2 * t);
|
|
|
|
}
|
|
|
|
|
2013-11-25 21:46:31 +00:00
|
|
|
bool perlin_noise_type_is_valid(SkPerlinNoiseShader::Type type) {
|
|
|
|
return (SkPerlinNoiseShader::kFractalNoise_Type == type) ||
|
|
|
|
(SkPerlinNoiseShader::kTurbulence_Type == type);
|
|
|
|
}
|
|
|
|
|
2013-04-05 13:47:09 +00:00
|
|
|
} // end namespace
|
|
|
|
|
|
|
|
struct SkPerlinNoiseShader::StitchData {
|
|
|
|
StitchData()
|
|
|
|
: fWidth(0)
|
|
|
|
, fWrapX(0)
|
|
|
|
, fHeight(0)
|
|
|
|
, fWrapY(0)
|
|
|
|
{}
|
|
|
|
|
|
|
|
bool operator==(const StitchData& other) const {
|
|
|
|
return fWidth == other.fWidth &&
|
|
|
|
fWrapX == other.fWrapX &&
|
|
|
|
fHeight == other.fHeight &&
|
|
|
|
fWrapY == other.fWrapY;
|
|
|
|
}
|
|
|
|
|
|
|
|
int fWidth; // How much to subtract to wrap for stitching.
|
|
|
|
int fWrapX; // Minimum value to wrap.
|
|
|
|
int fHeight;
|
|
|
|
int fWrapY;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct SkPerlinNoiseShader::PaintingData {
|
2014-03-06 15:13:53 +00:00
|
|
|
PaintingData(const SkISize& tileSize, SkScalar seed,
|
2014-06-27 20:35:52 +00:00
|
|
|
SkScalar baseFrequencyX, SkScalar baseFrequencyY,
|
|
|
|
const SkMatrix& matrix)
|
2013-04-05 13:47:09 +00:00
|
|
|
{
|
2014-06-27 20:35:52 +00:00
|
|
|
SkVector wavelength = SkVector::Make(SkScalarInvert(baseFrequencyX),
|
|
|
|
SkScalarInvert(baseFrequencyY));
|
|
|
|
matrix.mapVectors(&wavelength, 1);
|
|
|
|
fBaseFrequency.fX = SkScalarInvert(wavelength.fX);
|
|
|
|
fBaseFrequency.fY = SkScalarInvert(wavelength.fY);
|
|
|
|
SkVector sizeVec = SkVector::Make(SkIntToScalar(tileSize.fWidth),
|
|
|
|
SkIntToScalar(tileSize.fHeight));
|
|
|
|
matrix.mapVectors(&sizeVec, 1);
|
|
|
|
fTileSize.fWidth = SkScalarRoundToInt(sizeVec.fX);
|
|
|
|
fTileSize.fHeight = SkScalarRoundToInt(sizeVec.fY);
|
2014-03-06 15:13:53 +00:00
|
|
|
this->init(seed);
|
|
|
|
if (!fTileSize.isEmpty()) {
|
|
|
|
this->stitch();
|
|
|
|
}
|
|
|
|
|
2014-06-16 17:49:58 +00:00
|
|
|
#if SK_SUPPORT_GPU
|
2014-05-30 13:26:10 +00:00
|
|
|
fPermutationsBitmap.setInfo(SkImageInfo::MakeA8(kBlockSize, 1));
|
2014-03-06 15:13:53 +00:00
|
|
|
fPermutationsBitmap.setPixels(fLatticeSelector);
|
|
|
|
|
2014-05-30 13:26:10 +00:00
|
|
|
fNoiseBitmap.setInfo(SkImageInfo::MakeN32Premul(kBlockSize, 4));
|
2014-03-06 15:13:53 +00:00
|
|
|
fNoiseBitmap.setPixels(fNoise[0][0]);
|
|
|
|
#endif
|
2013-04-05 13:47:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int fSeed;
|
|
|
|
uint8_t fLatticeSelector[kBlockSize];
|
|
|
|
uint16_t fNoise[4][kBlockSize][2];
|
|
|
|
SkPoint fGradient[4][kBlockSize];
|
|
|
|
SkISize fTileSize;
|
|
|
|
SkVector fBaseFrequency;
|
|
|
|
StitchData fStitchDataInit;
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
2014-06-16 17:49:58 +00:00
|
|
|
#if SK_SUPPORT_GPU
|
2014-03-06 15:13:53 +00:00
|
|
|
SkBitmap fPermutationsBitmap;
|
|
|
|
SkBitmap fNoiseBitmap;
|
|
|
|
#endif
|
2013-04-05 13:47:09 +00:00
|
|
|
|
|
|
|
inline int random() {
|
|
|
|
static const int gRandAmplitude = 16807; // 7**5; primitive root of m
|
|
|
|
static const int gRandQ = 127773; // m / a
|
|
|
|
static const int gRandR = 2836; // m % a
|
|
|
|
|
|
|
|
int result = gRandAmplitude * (fSeed % gRandQ) - gRandR * (fSeed / gRandQ);
|
|
|
|
if (result <= 0)
|
|
|
|
result += kRandMaximum;
|
|
|
|
fSeed = result;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2014-03-06 15:13:53 +00:00
|
|
|
// Only called once. Could be part of the constructor.
|
2013-04-05 13:47:09 +00:00
|
|
|
void init(SkScalar seed)
|
|
|
|
{
|
|
|
|
static const SkScalar gInvBlockSizef = SkScalarInvert(SkIntToScalar(kBlockSize));
|
|
|
|
|
2014-01-09 17:41:42 +00:00
|
|
|
// According to the SVG spec, we must truncate (not round) the seed value.
|
|
|
|
fSeed = SkScalarTruncToInt(seed);
|
2013-04-05 13:47:09 +00:00
|
|
|
// The seed value clamp to the range [1, kRandMaximum - 1].
|
|
|
|
if (fSeed <= 0) {
|
|
|
|
fSeed = -(fSeed % (kRandMaximum - 1)) + 1;
|
|
|
|
}
|
|
|
|
if (fSeed > kRandMaximum - 1) {
|
|
|
|
fSeed = kRandMaximum - 1;
|
|
|
|
}
|
|
|
|
for (int channel = 0; channel < 4; ++channel) {
|
|
|
|
for (int i = 0; i < kBlockSize; ++i) {
|
|
|
|
fLatticeSelector[i] = i;
|
|
|
|
fNoise[channel][i][0] = (random() % (2 * kBlockSize));
|
|
|
|
fNoise[channel][i][1] = (random() % (2 * kBlockSize));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (int i = kBlockSize - 1; i > 0; --i) {
|
|
|
|
int k = fLatticeSelector[i];
|
|
|
|
int j = random() % kBlockSize;
|
|
|
|
SkASSERT(j >= 0);
|
|
|
|
SkASSERT(j < kBlockSize);
|
|
|
|
fLatticeSelector[i] = fLatticeSelector[j];
|
|
|
|
fLatticeSelector[j] = k;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Perform the permutations now
|
|
|
|
{
|
|
|
|
// Copy noise data
|
|
|
|
uint16_t noise[4][kBlockSize][2];
|
|
|
|
for (int i = 0; i < kBlockSize; ++i) {
|
|
|
|
for (int channel = 0; channel < 4; ++channel) {
|
|
|
|
for (int j = 0; j < 2; ++j) {
|
|
|
|
noise[channel][i][j] = fNoise[channel][i][j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Do permutations on noise data
|
|
|
|
for (int i = 0; i < kBlockSize; ++i) {
|
|
|
|
for (int channel = 0; channel < 4; ++channel) {
|
|
|
|
for (int j = 0; j < 2; ++j) {
|
|
|
|
fNoise[channel][i][j] = noise[channel][fLatticeSelector[i]][j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Half of the largest possible value for 16 bit unsigned int
|
2013-11-25 19:44:07 +00:00
|
|
|
static const SkScalar gHalfMax16bits = 32767.5f;
|
2013-04-05 13:47:09 +00:00
|
|
|
|
|
|
|
// Compute gradients from permutated noise data
|
|
|
|
for (int channel = 0; channel < 4; ++channel) {
|
|
|
|
for (int i = 0; i < kBlockSize; ++i) {
|
|
|
|
fGradient[channel][i] = SkPoint::Make(
|
|
|
|
SkScalarMul(SkIntToScalar(fNoise[channel][i][0] - kBlockSize),
|
|
|
|
gInvBlockSizef),
|
2013-04-06 07:01:10 +00:00
|
|
|
SkScalarMul(SkIntToScalar(fNoise[channel][i][1] - kBlockSize),
|
2013-04-05 13:47:09 +00:00
|
|
|
gInvBlockSizef));
|
|
|
|
fGradient[channel][i].normalize();
|
|
|
|
// Put the normalized gradient back into the noise data
|
|
|
|
fNoise[channel][i][0] = SkScalarRoundToInt(SkScalarMul(
|
2013-06-10 13:59:25 +00:00
|
|
|
fGradient[channel][i].fX + SK_Scalar1, gHalfMax16bits));
|
2013-04-05 13:47:09 +00:00
|
|
|
fNoise[channel][i][1] = SkScalarRoundToInt(SkScalarMul(
|
2013-06-10 13:59:25 +00:00
|
|
|
fGradient[channel][i].fY + SK_Scalar1, gHalfMax16bits));
|
2013-04-05 13:47:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-06 15:13:53 +00:00
|
|
|
// Only called once. Could be part of the constructor.
|
2013-04-05 13:47:09 +00:00
|
|
|
void stitch() {
|
|
|
|
SkScalar tileWidth = SkIntToScalar(fTileSize.width());
|
|
|
|
SkScalar tileHeight = SkIntToScalar(fTileSize.height());
|
|
|
|
SkASSERT(tileWidth > 0 && tileHeight > 0);
|
|
|
|
// When stitching tiled turbulence, the frequencies must be adjusted
|
|
|
|
// so that the tile borders will be continuous.
|
|
|
|
if (fBaseFrequency.fX) {
|
2013-12-18 15:49:32 +00:00
|
|
|
SkScalar lowFrequencx =
|
|
|
|
SkScalarFloorToScalar(tileWidth * fBaseFrequency.fX) / tileWidth;
|
|
|
|
SkScalar highFrequencx =
|
|
|
|
SkScalarCeilToScalar(tileWidth * fBaseFrequency.fX) / tileWidth;
|
2013-04-05 13:47:09 +00:00
|
|
|
// BaseFrequency should be non-negative according to the standard.
|
2013-04-06 07:01:10 +00:00
|
|
|
if (SkScalarDiv(fBaseFrequency.fX, lowFrequencx) <
|
2013-04-05 13:47:09 +00:00
|
|
|
SkScalarDiv(highFrequencx, fBaseFrequency.fX)) {
|
|
|
|
fBaseFrequency.fX = lowFrequencx;
|
|
|
|
} else {
|
|
|
|
fBaseFrequency.fX = highFrequencx;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (fBaseFrequency.fY) {
|
2013-12-18 15:49:32 +00:00
|
|
|
SkScalar lowFrequency =
|
|
|
|
SkScalarFloorToScalar(tileHeight * fBaseFrequency.fY) / tileHeight;
|
|
|
|
SkScalar highFrequency =
|
|
|
|
SkScalarCeilToScalar(tileHeight * fBaseFrequency.fY) / tileHeight;
|
2013-04-06 07:01:10 +00:00
|
|
|
if (SkScalarDiv(fBaseFrequency.fY, lowFrequency) <
|
2013-04-05 13:47:09 +00:00
|
|
|
SkScalarDiv(highFrequency, fBaseFrequency.fY)) {
|
|
|
|
fBaseFrequency.fY = lowFrequency;
|
|
|
|
} else {
|
|
|
|
fBaseFrequency.fY = highFrequency;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Set up TurbulenceInitial stitch values.
|
|
|
|
fStitchDataInit.fWidth =
|
2013-12-18 15:49:32 +00:00
|
|
|
SkScalarRoundToInt(tileWidth * fBaseFrequency.fX);
|
2013-04-05 13:47:09 +00:00
|
|
|
fStitchDataInit.fWrapX = kPerlinNoise + fStitchDataInit.fWidth;
|
|
|
|
fStitchDataInit.fHeight =
|
2013-12-18 15:49:32 +00:00
|
|
|
SkScalarRoundToInt(tileHeight * fBaseFrequency.fY);
|
2013-04-05 13:47:09 +00:00
|
|
|
fStitchDataInit.fWrapY = kPerlinNoise + fStitchDataInit.fHeight;
|
|
|
|
}
|
|
|
|
|
2014-03-06 15:13:53 +00:00
|
|
|
public:
|
2013-04-05 13:47:09 +00:00
|
|
|
|
2014-06-16 17:49:58 +00:00
|
|
|
#if SK_SUPPORT_GPU
|
2014-03-06 15:13:53 +00:00
|
|
|
const SkBitmap& getPermutationsBitmap() const { return fPermutationsBitmap; }
|
|
|
|
|
|
|
|
const SkBitmap& getNoiseBitmap() const { return fNoiseBitmap; }
|
|
|
|
#endif
|
2013-04-05 13:47:09 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
SkShader* SkPerlinNoiseShader::CreateFractalNoise(SkScalar baseFrequencyX, SkScalar baseFrequencyY,
|
|
|
|
int numOctaves, SkScalar seed,
|
|
|
|
const SkISize* tileSize) {
|
|
|
|
return SkNEW_ARGS(SkPerlinNoiseShader, (kFractalNoise_Type, baseFrequencyX, baseFrequencyY,
|
|
|
|
numOctaves, seed, tileSize));
|
|
|
|
}
|
|
|
|
|
2014-04-01 16:09:37 +00:00
|
|
|
SkShader* SkPerlinNoiseShader::CreateTurbulence(SkScalar baseFrequencyX, SkScalar baseFrequencyY,
|
2013-04-05 13:47:09 +00:00
|
|
|
int numOctaves, SkScalar seed,
|
|
|
|
const SkISize* tileSize) {
|
|
|
|
return SkNEW_ARGS(SkPerlinNoiseShader, (kTurbulence_Type, baseFrequencyX, baseFrequencyY,
|
|
|
|
numOctaves, seed, tileSize));
|
|
|
|
}
|
|
|
|
|
|
|
|
SkPerlinNoiseShader::SkPerlinNoiseShader(SkPerlinNoiseShader::Type type,
|
|
|
|
SkScalar baseFrequencyX,
|
|
|
|
SkScalar baseFrequencyY,
|
|
|
|
int numOctaves,
|
|
|
|
SkScalar seed,
|
|
|
|
const SkISize* tileSize)
|
|
|
|
: fType(type)
|
|
|
|
, fBaseFrequencyX(baseFrequencyX)
|
|
|
|
, fBaseFrequencyY(baseFrequencyY)
|
2013-11-25 21:46:31 +00:00
|
|
|
, fNumOctaves(numOctaves > 255 ? 255 : numOctaves/*[0,255] octaves allowed*/)
|
2013-04-05 13:47:09 +00:00
|
|
|
, fSeed(seed)
|
2014-03-06 15:13:53 +00:00
|
|
|
, fTileSize(NULL == tileSize ? SkISize::Make(0, 0) : *tileSize)
|
|
|
|
, fStitchTiles(!fTileSize.isEmpty())
|
2013-04-05 13:47:09 +00:00
|
|
|
{
|
|
|
|
SkASSERT(numOctaves >= 0 && numOctaves < 256);
|
|
|
|
}
|
|
|
|
|
2014-08-21 14:59:51 +00:00
|
|
|
#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
|
|
|
|
SkPerlinNoiseShader::SkPerlinNoiseShader(SkReadBuffer& buffer) : INHERITED(buffer) {
|
2013-04-05 13:47:09 +00:00
|
|
|
fType = (SkPerlinNoiseShader::Type) buffer.readInt();
|
|
|
|
fBaseFrequencyX = buffer.readScalar();
|
|
|
|
fBaseFrequencyY = buffer.readScalar();
|
|
|
|
fNumOctaves = buffer.readInt();
|
|
|
|
fSeed = buffer.readScalar();
|
|
|
|
fStitchTiles = buffer.readBool();
|
|
|
|
fTileSize.fWidth = buffer.readInt();
|
|
|
|
fTileSize.fHeight = buffer.readInt();
|
2013-11-25 21:46:31 +00:00
|
|
|
buffer.validate(perlin_noise_type_is_valid(fType) &&
|
2014-03-06 15:13:53 +00:00
|
|
|
(fNumOctaves >= 0) && (fNumOctaves <= 255) &&
|
|
|
|
(fStitchTiles != fTileSize.isEmpty()));
|
2013-04-05 13:47:09 +00:00
|
|
|
}
|
2014-08-21 14:59:51 +00:00
|
|
|
#endif
|
2013-04-05 13:47:09 +00:00
|
|
|
|
|
|
|
SkPerlinNoiseShader::~SkPerlinNoiseShader() {
|
|
|
|
}
|
|
|
|
|
2014-08-21 14:59:51 +00:00
|
|
|
SkFlattenable* SkPerlinNoiseShader::CreateProc(SkReadBuffer& buffer) {
|
|
|
|
Type type = (Type)buffer.readInt();
|
|
|
|
SkScalar freqX = buffer.readScalar();
|
|
|
|
SkScalar freqY = buffer.readScalar();
|
|
|
|
int octaves = buffer.readInt();
|
|
|
|
SkScalar seed = buffer.readScalar();
|
|
|
|
SkISize tileSize;
|
|
|
|
tileSize.fWidth = buffer.readInt();
|
|
|
|
tileSize.fHeight = buffer.readInt();
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case kFractalNoise_Type:
|
|
|
|
return SkPerlinNoiseShader::CreateFractalNoise(freqX, freqY, octaves, seed, &tileSize);
|
|
|
|
case kTurbulence_Type:
|
|
|
|
return SkPerlinNoiseShader::CreateTubulence(freqX, freqY, octaves, seed, &tileSize);
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-30 18:58:24 +00:00
|
|
|
void SkPerlinNoiseShader::flatten(SkWriteBuffer& buffer) const {
|
2013-04-05 13:47:09 +00:00
|
|
|
buffer.writeInt((int) fType);
|
|
|
|
buffer.writeScalar(fBaseFrequencyX);
|
|
|
|
buffer.writeScalar(fBaseFrequencyY);
|
|
|
|
buffer.writeInt(fNumOctaves);
|
|
|
|
buffer.writeScalar(fSeed);
|
|
|
|
buffer.writeInt(fTileSize.fWidth);
|
|
|
|
buffer.writeInt(fTileSize.fHeight);
|
|
|
|
}
|
|
|
|
|
Revert of Revert of Extract most of the mutable state of SkShader into a separate Context object. (https://codereview.chromium.org/249643002/)
Reason for revert:
Chromium side change landed along side DEPS roll that includes r14323.
Original issue's description:
> Revert of Extract most of the mutable state of SkShader into a separate Context object. (https://codereview.chromium.org/207683004/)
>
> Reason for revert:
> This is blocking the DEPS roll into Chromium. Failures can be seen here:
>
> http://build.chromium.org/p/tryserver.chromium/builders/android_dbg/builds/174333
>
> Original issue's description:
> > Extract most of the mutable state of SkShader into a separate Context object.
> >
> > SkShader currently stores some state during draw calls via setContext(...).
> > Move that mutable state into a separate SkShader::Context class that is
> > constructed on demand for the duration of the draw.
> >
> > Calls to setContext() are replaced with createContext() which returns a context
> > corresponding to the shader object or NULL if the parameters to createContext
> > are invalid.
> >
> > TEST=out/Debug/dm
> > BUG=skia:1976
> >
> > Committed: http://code.google.com/p/skia/source/detail?r=14216
> >
> > Committed: http://code.google.com/p/skia/source/detail?r=14323
>
> TBR=scroggo@google.com,skyostil@chromium.org,tomhudson@chromium.org,senorblanco@chromium.org,reed@google.com,bungeman@google.com,dominikg@chromium.org
> NOTREECHECKS=true
> NOTRY=true
> BUG=skia:1976
>
> Committed: http://code.google.com/p/skia/source/detail?r=14326
R=scroggo@google.com, skyostil@chromium.org, tomhudson@chromium.org, senorblanco@chromium.org, reed@google.com, bungeman@google.com, dominikg@chromium.org
TBR=bungeman@google.com, dominikg@chromium.org, reed@google.com, scroggo@google.com, senorblanco@chromium.org, skyostil@chromium.org, tomhudson@chromium.org
NOTREECHECKS=true
NOTRY=true
BUG=skia:1976
Author: bsalomon@google.com
Review URL: https://codereview.chromium.org/246403013
git-svn-id: http://skia.googlecode.com/svn/trunk@14328 2bbb7eff-a529-9590-31e7-b0007b416f81
2014-04-23 19:10:51 +00:00
|
|
|
SkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::noise2D(
|
2014-06-27 20:35:52 +00:00
|
|
|
int channel, const StitchData& stitchData, const SkPoint& noiseVector) const {
|
2013-04-05 13:47:09 +00:00
|
|
|
struct Noise {
|
|
|
|
int noisePositionIntegerValue;
|
Fix tiled perlin noise.
It turns out that the perlin implementation we inherited from WebKit
does not actually generate tileable noise (see Chromium bug
http://crbug.com/383495).
The main problem is that when generating coordinates for gradient
interpolation, it was attempting to wrap both x and (x + 1)
simultaneously at the tile boundary (that is, either both or neither
are wrapped). This obviously won't work, since along the tile seams,
(x + 1) should be wrapped, but x should not. The same is true in y.
This patch fixes both the CPU and GPU paths, renames some variables to
more closely match the spec, and modifies the perlin noise GM to
actually test tiling. (Note that the clipping the GM was doing was
removed, since it's superfluous: it used to be necessary for image
filters, but isn't anymore, and this isn't an image filter GM anyway.)
R=sugoi@google.com, sugoi
TBR=senorblanco
Author: senorblanco@chromium.org
Review URL: https://codereview.chromium.org/332523006
2014-06-12 18:24:19 +00:00
|
|
|
int nextNoisePositionIntegerValue;
|
2013-04-05 13:47:09 +00:00
|
|
|
SkScalar noisePositionFractionValue;
|
|
|
|
Noise(SkScalar component)
|
|
|
|
{
|
|
|
|
SkScalar position = component + kPerlinNoise;
|
|
|
|
noisePositionIntegerValue = SkScalarFloorToInt(position);
|
|
|
|
noisePositionFractionValue = position - SkIntToScalar(noisePositionIntegerValue);
|
Fix tiled perlin noise.
It turns out that the perlin implementation we inherited from WebKit
does not actually generate tileable noise (see Chromium bug
http://crbug.com/383495).
The main problem is that when generating coordinates for gradient
interpolation, it was attempting to wrap both x and (x + 1)
simultaneously at the tile boundary (that is, either both or neither
are wrapped). This obviously won't work, since along the tile seams,
(x + 1) should be wrapped, but x should not. The same is true in y.
This patch fixes both the CPU and GPU paths, renames some variables to
more closely match the spec, and modifies the perlin noise GM to
actually test tiling. (Note that the clipping the GM was doing was
removed, since it's superfluous: it used to be necessary for image
filters, but isn't anymore, and this isn't an image filter GM anyway.)
R=sugoi@google.com, sugoi
TBR=senorblanco
Author: senorblanco@chromium.org
Review URL: https://codereview.chromium.org/332523006
2014-06-12 18:24:19 +00:00
|
|
|
nextNoisePositionIntegerValue = noisePositionIntegerValue + 1;
|
2013-04-05 13:47:09 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
Noise noiseX(noiseVector.x());
|
|
|
|
Noise noiseY(noiseVector.y());
|
|
|
|
SkScalar u, v;
|
Revert of Revert of Extract most of the mutable state of SkShader into a separate Context object. (https://codereview.chromium.org/249643002/)
Reason for revert:
Chromium side change landed along side DEPS roll that includes r14323.
Original issue's description:
> Revert of Extract most of the mutable state of SkShader into a separate Context object. (https://codereview.chromium.org/207683004/)
>
> Reason for revert:
> This is blocking the DEPS roll into Chromium. Failures can be seen here:
>
> http://build.chromium.org/p/tryserver.chromium/builders/android_dbg/builds/174333
>
> Original issue's description:
> > Extract most of the mutable state of SkShader into a separate Context object.
> >
> > SkShader currently stores some state during draw calls via setContext(...).
> > Move that mutable state into a separate SkShader::Context class that is
> > constructed on demand for the duration of the draw.
> >
> > Calls to setContext() are replaced with createContext() which returns a context
> > corresponding to the shader object or NULL if the parameters to createContext
> > are invalid.
> >
> > TEST=out/Debug/dm
> > BUG=skia:1976
> >
> > Committed: http://code.google.com/p/skia/source/detail?r=14216
> >
> > Committed: http://code.google.com/p/skia/source/detail?r=14323
>
> TBR=scroggo@google.com,skyostil@chromium.org,tomhudson@chromium.org,senorblanco@chromium.org,reed@google.com,bungeman@google.com,dominikg@chromium.org
> NOTREECHECKS=true
> NOTRY=true
> BUG=skia:1976
>
> Committed: http://code.google.com/p/skia/source/detail?r=14326
R=scroggo@google.com, skyostil@chromium.org, tomhudson@chromium.org, senorblanco@chromium.org, reed@google.com, bungeman@google.com, dominikg@chromium.org
TBR=bungeman@google.com, dominikg@chromium.org, reed@google.com, scroggo@google.com, senorblanco@chromium.org, skyostil@chromium.org, tomhudson@chromium.org
NOTREECHECKS=true
NOTRY=true
BUG=skia:1976
Author: bsalomon@google.com
Review URL: https://codereview.chromium.org/246403013
git-svn-id: http://skia.googlecode.com/svn/trunk@14328 2bbb7eff-a529-9590-31e7-b0007b416f81
2014-04-23 19:10:51 +00:00
|
|
|
const SkPerlinNoiseShader& perlinNoiseShader = static_cast<const SkPerlinNoiseShader&>(fShader);
|
2013-04-05 13:47:09 +00:00
|
|
|
// If stitching, adjust lattice points accordingly.
|
Revert of Revert of Extract most of the mutable state of SkShader into a separate Context object. (https://codereview.chromium.org/249643002/)
Reason for revert:
Chromium side change landed along side DEPS roll that includes r14323.
Original issue's description:
> Revert of Extract most of the mutable state of SkShader into a separate Context object. (https://codereview.chromium.org/207683004/)
>
> Reason for revert:
> This is blocking the DEPS roll into Chromium. Failures can be seen here:
>
> http://build.chromium.org/p/tryserver.chromium/builders/android_dbg/builds/174333
>
> Original issue's description:
> > Extract most of the mutable state of SkShader into a separate Context object.
> >
> > SkShader currently stores some state during draw calls via setContext(...).
> > Move that mutable state into a separate SkShader::Context class that is
> > constructed on demand for the duration of the draw.
> >
> > Calls to setContext() are replaced with createContext() which returns a context
> > corresponding to the shader object or NULL if the parameters to createContext
> > are invalid.
> >
> > TEST=out/Debug/dm
> > BUG=skia:1976
> >
> > Committed: http://code.google.com/p/skia/source/detail?r=14216
> >
> > Committed: http://code.google.com/p/skia/source/detail?r=14323
>
> TBR=scroggo@google.com,skyostil@chromium.org,tomhudson@chromium.org,senorblanco@chromium.org,reed@google.com,bungeman@google.com,dominikg@chromium.org
> NOTREECHECKS=true
> NOTRY=true
> BUG=skia:1976
>
> Committed: http://code.google.com/p/skia/source/detail?r=14326
R=scroggo@google.com, skyostil@chromium.org, tomhudson@chromium.org, senorblanco@chromium.org, reed@google.com, bungeman@google.com, dominikg@chromium.org
TBR=bungeman@google.com, dominikg@chromium.org, reed@google.com, scroggo@google.com, senorblanco@chromium.org, skyostil@chromium.org, tomhudson@chromium.org
NOTREECHECKS=true
NOTRY=true
BUG=skia:1976
Author: bsalomon@google.com
Review URL: https://codereview.chromium.org/246403013
git-svn-id: http://skia.googlecode.com/svn/trunk@14328 2bbb7eff-a529-9590-31e7-b0007b416f81
2014-04-23 19:10:51 +00:00
|
|
|
if (perlinNoiseShader.fStitchTiles) {
|
2013-04-05 13:47:09 +00:00
|
|
|
noiseX.noisePositionIntegerValue =
|
|
|
|
checkNoise(noiseX.noisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth);
|
|
|
|
noiseY.noisePositionIntegerValue =
|
|
|
|
checkNoise(noiseY.noisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight);
|
Fix tiled perlin noise.
It turns out that the perlin implementation we inherited from WebKit
does not actually generate tileable noise (see Chromium bug
http://crbug.com/383495).
The main problem is that when generating coordinates for gradient
interpolation, it was attempting to wrap both x and (x + 1)
simultaneously at the tile boundary (that is, either both or neither
are wrapped). This obviously won't work, since along the tile seams,
(x + 1) should be wrapped, but x should not. The same is true in y.
This patch fixes both the CPU and GPU paths, renames some variables to
more closely match the spec, and modifies the perlin noise GM to
actually test tiling. (Note that the clipping the GM was doing was
removed, since it's superfluous: it used to be necessary for image
filters, but isn't anymore, and this isn't an image filter GM anyway.)
R=sugoi@google.com, sugoi
TBR=senorblanco
Author: senorblanco@chromium.org
Review URL: https://codereview.chromium.org/332523006
2014-06-12 18:24:19 +00:00
|
|
|
noiseX.nextNoisePositionIntegerValue =
|
|
|
|
checkNoise(noiseX.nextNoisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth);
|
|
|
|
noiseY.nextNoisePositionIntegerValue =
|
|
|
|
checkNoise(noiseY.nextNoisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight);
|
2013-04-05 13:47:09 +00:00
|
|
|
}
|
|
|
|
noiseX.noisePositionIntegerValue &= kBlockMask;
|
|
|
|
noiseY.noisePositionIntegerValue &= kBlockMask;
|
Fix tiled perlin noise.
It turns out that the perlin implementation we inherited from WebKit
does not actually generate tileable noise (see Chromium bug
http://crbug.com/383495).
The main problem is that when generating coordinates for gradient
interpolation, it was attempting to wrap both x and (x + 1)
simultaneously at the tile boundary (that is, either both or neither
are wrapped). This obviously won't work, since along the tile seams,
(x + 1) should be wrapped, but x should not. The same is true in y.
This patch fixes both the CPU and GPU paths, renames some variables to
more closely match the spec, and modifies the perlin noise GM to
actually test tiling. (Note that the clipping the GM was doing was
removed, since it's superfluous: it used to be necessary for image
filters, but isn't anymore, and this isn't an image filter GM anyway.)
R=sugoi@google.com, sugoi
TBR=senorblanco
Author: senorblanco@chromium.org
Review URL: https://codereview.chromium.org/332523006
2014-06-12 18:24:19 +00:00
|
|
|
noiseX.nextNoisePositionIntegerValue &= kBlockMask;
|
|
|
|
noiseY.nextNoisePositionIntegerValue &= kBlockMask;
|
|
|
|
int i =
|
2014-06-27 20:35:52 +00:00
|
|
|
fPaintingData->fLatticeSelector[noiseX.noisePositionIntegerValue];
|
Fix tiled perlin noise.
It turns out that the perlin implementation we inherited from WebKit
does not actually generate tileable noise (see Chromium bug
http://crbug.com/383495).
The main problem is that when generating coordinates for gradient
interpolation, it was attempting to wrap both x and (x + 1)
simultaneously at the tile boundary (that is, either both or neither
are wrapped). This obviously won't work, since along the tile seams,
(x + 1) should be wrapped, but x should not. The same is true in y.
This patch fixes both the CPU and GPU paths, renames some variables to
more closely match the spec, and modifies the perlin noise GM to
actually test tiling. (Note that the clipping the GM was doing was
removed, since it's superfluous: it used to be necessary for image
filters, but isn't anymore, and this isn't an image filter GM anyway.)
R=sugoi@google.com, sugoi
TBR=senorblanco
Author: senorblanco@chromium.org
Review URL: https://codereview.chromium.org/332523006
2014-06-12 18:24:19 +00:00
|
|
|
int j =
|
2014-06-27 20:35:52 +00:00
|
|
|
fPaintingData->fLatticeSelector[noiseX.nextNoisePositionIntegerValue];
|
Fix tiled perlin noise.
It turns out that the perlin implementation we inherited from WebKit
does not actually generate tileable noise (see Chromium bug
http://crbug.com/383495).
The main problem is that when generating coordinates for gradient
interpolation, it was attempting to wrap both x and (x + 1)
simultaneously at the tile boundary (that is, either both or neither
are wrapped). This obviously won't work, since along the tile seams,
(x + 1) should be wrapped, but x should not. The same is true in y.
This patch fixes both the CPU and GPU paths, renames some variables to
more closely match the spec, and modifies the perlin noise GM to
actually test tiling. (Note that the clipping the GM was doing was
removed, since it's superfluous: it used to be necessary for image
filters, but isn't anymore, and this isn't an image filter GM anyway.)
R=sugoi@google.com, sugoi
TBR=senorblanco
Author: senorblanco@chromium.org
Review URL: https://codereview.chromium.org/332523006
2014-06-12 18:24:19 +00:00
|
|
|
int b00 = (i + noiseY.noisePositionIntegerValue) & kBlockMask;
|
|
|
|
int b10 = (j + noiseY.noisePositionIntegerValue) & kBlockMask;
|
|
|
|
int b01 = (i + noiseY.nextNoisePositionIntegerValue) & kBlockMask;
|
|
|
|
int b11 = (j + noiseY.nextNoisePositionIntegerValue) & kBlockMask;
|
2013-04-05 13:47:09 +00:00
|
|
|
SkScalar sx = smoothCurve(noiseX.noisePositionFractionValue);
|
|
|
|
SkScalar sy = smoothCurve(noiseY.noisePositionFractionValue);
|
|
|
|
// This is taken 1:1 from SVG spec: http://www.w3.org/TR/SVG11/filters.html#feTurbulenceElement
|
|
|
|
SkPoint fractionValue = SkPoint::Make(noiseX.noisePositionFractionValue,
|
|
|
|
noiseY.noisePositionFractionValue); // Offset (0,0)
|
2014-06-27 20:35:52 +00:00
|
|
|
u = fPaintingData->fGradient[channel][b00].dot(fractionValue);
|
2013-04-05 13:47:09 +00:00
|
|
|
fractionValue.fX -= SK_Scalar1; // Offset (-1,0)
|
2014-06-27 20:35:52 +00:00
|
|
|
v = fPaintingData->fGradient[channel][b10].dot(fractionValue);
|
2013-04-05 13:47:09 +00:00
|
|
|
SkScalar a = SkScalarInterp(u, v, sx);
|
|
|
|
fractionValue.fY -= SK_Scalar1; // Offset (-1,-1)
|
2014-06-27 20:35:52 +00:00
|
|
|
v = fPaintingData->fGradient[channel][b11].dot(fractionValue);
|
2013-04-05 13:47:09 +00:00
|
|
|
fractionValue.fX = noiseX.noisePositionFractionValue; // Offset (0,-1)
|
2014-06-27 20:35:52 +00:00
|
|
|
u = fPaintingData->fGradient[channel][b01].dot(fractionValue);
|
2013-04-05 13:47:09 +00:00
|
|
|
SkScalar b = SkScalarInterp(u, v, sx);
|
|
|
|
return SkScalarInterp(a, b, sy);
|
|
|
|
}
|
|
|
|
|
Revert of Revert of Extract most of the mutable state of SkShader into a separate Context object. (https://codereview.chromium.org/249643002/)
Reason for revert:
Chromium side change landed along side DEPS roll that includes r14323.
Original issue's description:
> Revert of Extract most of the mutable state of SkShader into a separate Context object. (https://codereview.chromium.org/207683004/)
>
> Reason for revert:
> This is blocking the DEPS roll into Chromium. Failures can be seen here:
>
> http://build.chromium.org/p/tryserver.chromium/builders/android_dbg/builds/174333
>
> Original issue's description:
> > Extract most of the mutable state of SkShader into a separate Context object.
> >
> > SkShader currently stores some state during draw calls via setContext(...).
> > Move that mutable state into a separate SkShader::Context class that is
> > constructed on demand for the duration of the draw.
> >
> > Calls to setContext() are replaced with createContext() which returns a context
> > corresponding to the shader object or NULL if the parameters to createContext
> > are invalid.
> >
> > TEST=out/Debug/dm
> > BUG=skia:1976
> >
> > Committed: http://code.google.com/p/skia/source/detail?r=14216
> >
> > Committed: http://code.google.com/p/skia/source/detail?r=14323
>
> TBR=scroggo@google.com,skyostil@chromium.org,tomhudson@chromium.org,senorblanco@chromium.org,reed@google.com,bungeman@google.com,dominikg@chromium.org
> NOTREECHECKS=true
> NOTRY=true
> BUG=skia:1976
>
> Committed: http://code.google.com/p/skia/source/detail?r=14326
R=scroggo@google.com, skyostil@chromium.org, tomhudson@chromium.org, senorblanco@chromium.org, reed@google.com, bungeman@google.com, dominikg@chromium.org
TBR=bungeman@google.com, dominikg@chromium.org, reed@google.com, scroggo@google.com, senorblanco@chromium.org, skyostil@chromium.org, tomhudson@chromium.org
NOTREECHECKS=true
NOTRY=true
BUG=skia:1976
Author: bsalomon@google.com
Review URL: https://codereview.chromium.org/246403013
git-svn-id: http://skia.googlecode.com/svn/trunk@14328 2bbb7eff-a529-9590-31e7-b0007b416f81
2014-04-23 19:10:51 +00:00
|
|
|
SkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::calculateTurbulenceValueForPoint(
|
2014-06-27 20:35:52 +00:00
|
|
|
int channel, StitchData& stitchData, const SkPoint& point) const {
|
Revert of Revert of Extract most of the mutable state of SkShader into a separate Context object. (https://codereview.chromium.org/249643002/)
Reason for revert:
Chromium side change landed along side DEPS roll that includes r14323.
Original issue's description:
> Revert of Extract most of the mutable state of SkShader into a separate Context object. (https://codereview.chromium.org/207683004/)
>
> Reason for revert:
> This is blocking the DEPS roll into Chromium. Failures can be seen here:
>
> http://build.chromium.org/p/tryserver.chromium/builders/android_dbg/builds/174333
>
> Original issue's description:
> > Extract most of the mutable state of SkShader into a separate Context object.
> >
> > SkShader currently stores some state during draw calls via setContext(...).
> > Move that mutable state into a separate SkShader::Context class that is
> > constructed on demand for the duration of the draw.
> >
> > Calls to setContext() are replaced with createContext() which returns a context
> > corresponding to the shader object or NULL if the parameters to createContext
> > are invalid.
> >
> > TEST=out/Debug/dm
> > BUG=skia:1976
> >
> > Committed: http://code.google.com/p/skia/source/detail?r=14216
> >
> > Committed: http://code.google.com/p/skia/source/detail?r=14323
>
> TBR=scroggo@google.com,skyostil@chromium.org,tomhudson@chromium.org,senorblanco@chromium.org,reed@google.com,bungeman@google.com,dominikg@chromium.org
> NOTREECHECKS=true
> NOTRY=true
> BUG=skia:1976
>
> Committed: http://code.google.com/p/skia/source/detail?r=14326
R=scroggo@google.com, skyostil@chromium.org, tomhudson@chromium.org, senorblanco@chromium.org, reed@google.com, bungeman@google.com, dominikg@chromium.org
TBR=bungeman@google.com, dominikg@chromium.org, reed@google.com, scroggo@google.com, senorblanco@chromium.org, skyostil@chromium.org, tomhudson@chromium.org
NOTREECHECKS=true
NOTRY=true
BUG=skia:1976
Author: bsalomon@google.com
Review URL: https://codereview.chromium.org/246403013
git-svn-id: http://skia.googlecode.com/svn/trunk@14328 2bbb7eff-a529-9590-31e7-b0007b416f81
2014-04-23 19:10:51 +00:00
|
|
|
const SkPerlinNoiseShader& perlinNoiseShader = static_cast<const SkPerlinNoiseShader&>(fShader);
|
|
|
|
if (perlinNoiseShader.fStitchTiles) {
|
2013-04-05 13:47:09 +00:00
|
|
|
// Set up TurbulenceInitial stitch values.
|
2014-06-27 20:35:52 +00:00
|
|
|
stitchData = fPaintingData->fStitchDataInit;
|
2013-04-05 13:47:09 +00:00
|
|
|
}
|
|
|
|
SkScalar turbulenceFunctionResult = 0;
|
2014-06-27 20:35:52 +00:00
|
|
|
SkPoint noiseVector(SkPoint::Make(SkScalarMul(point.x(), fPaintingData->fBaseFrequency.fX),
|
|
|
|
SkScalarMul(point.y(), fPaintingData->fBaseFrequency.fY)));
|
2013-04-05 13:47:09 +00:00
|
|
|
SkScalar ratio = SK_Scalar1;
|
Revert of Revert of Extract most of the mutable state of SkShader into a separate Context object. (https://codereview.chromium.org/249643002/)
Reason for revert:
Chromium side change landed along side DEPS roll that includes r14323.
Original issue's description:
> Revert of Extract most of the mutable state of SkShader into a separate Context object. (https://codereview.chromium.org/207683004/)
>
> Reason for revert:
> This is blocking the DEPS roll into Chromium. Failures can be seen here:
>
> http://build.chromium.org/p/tryserver.chromium/builders/android_dbg/builds/174333
>
> Original issue's description:
> > Extract most of the mutable state of SkShader into a separate Context object.
> >
> > SkShader currently stores some state during draw calls via setContext(...).
> > Move that mutable state into a separate SkShader::Context class that is
> > constructed on demand for the duration of the draw.
> >
> > Calls to setContext() are replaced with createContext() which returns a context
> > corresponding to the shader object or NULL if the parameters to createContext
> > are invalid.
> >
> > TEST=out/Debug/dm
> > BUG=skia:1976
> >
> > Committed: http://code.google.com/p/skia/source/detail?r=14216
> >
> > Committed: http://code.google.com/p/skia/source/detail?r=14323
>
> TBR=scroggo@google.com,skyostil@chromium.org,tomhudson@chromium.org,senorblanco@chromium.org,reed@google.com,bungeman@google.com,dominikg@chromium.org
> NOTREECHECKS=true
> NOTRY=true
> BUG=skia:1976
>
> Committed: http://code.google.com/p/skia/source/detail?r=14326
R=scroggo@google.com, skyostil@chromium.org, tomhudson@chromium.org, senorblanco@chromium.org, reed@google.com, bungeman@google.com, dominikg@chromium.org
TBR=bungeman@google.com, dominikg@chromium.org, reed@google.com, scroggo@google.com, senorblanco@chromium.org, skyostil@chromium.org, tomhudson@chromium.org
NOTREECHECKS=true
NOTRY=true
BUG=skia:1976
Author: bsalomon@google.com
Review URL: https://codereview.chromium.org/246403013
git-svn-id: http://skia.googlecode.com/svn/trunk@14328 2bbb7eff-a529-9590-31e7-b0007b416f81
2014-04-23 19:10:51 +00:00
|
|
|
for (int octave = 0; octave < perlinNoiseShader.fNumOctaves; ++octave) {
|
2014-06-27 20:35:52 +00:00
|
|
|
SkScalar noise = noise2D(channel, stitchData, noiseVector);
|
2013-04-05 13:47:09 +00:00
|
|
|
turbulenceFunctionResult += SkScalarDiv(
|
Revert of Revert of Extract most of the mutable state of SkShader into a separate Context object. (https://codereview.chromium.org/249643002/)
Reason for revert:
Chromium side change landed along side DEPS roll that includes r14323.
Original issue's description:
> Revert of Extract most of the mutable state of SkShader into a separate Context object. (https://codereview.chromium.org/207683004/)
>
> Reason for revert:
> This is blocking the DEPS roll into Chromium. Failures can be seen here:
>
> http://build.chromium.org/p/tryserver.chromium/builders/android_dbg/builds/174333
>
> Original issue's description:
> > Extract most of the mutable state of SkShader into a separate Context object.
> >
> > SkShader currently stores some state during draw calls via setContext(...).
> > Move that mutable state into a separate SkShader::Context class that is
> > constructed on demand for the duration of the draw.
> >
> > Calls to setContext() are replaced with createContext() which returns a context
> > corresponding to the shader object or NULL if the parameters to createContext
> > are invalid.
> >
> > TEST=out/Debug/dm
> > BUG=skia:1976
> >
> > Committed: http://code.google.com/p/skia/source/detail?r=14216
> >
> > Committed: http://code.google.com/p/skia/source/detail?r=14323
>
> TBR=scroggo@google.com,skyostil@chromium.org,tomhudson@chromium.org,senorblanco@chromium.org,reed@google.com,bungeman@google.com,dominikg@chromium.org
> NOTREECHECKS=true
> NOTRY=true
> BUG=skia:1976
>
> Committed: http://code.google.com/p/skia/source/detail?r=14326
R=scroggo@google.com, skyostil@chromium.org, tomhudson@chromium.org, senorblanco@chromium.org, reed@google.com, bungeman@google.com, dominikg@chromium.org
TBR=bungeman@google.com, dominikg@chromium.org, reed@google.com, scroggo@google.com, senorblanco@chromium.org, skyostil@chromium.org, tomhudson@chromium.org
NOTREECHECKS=true
NOTRY=true
BUG=skia:1976
Author: bsalomon@google.com
Review URL: https://codereview.chromium.org/246403013
git-svn-id: http://skia.googlecode.com/svn/trunk@14328 2bbb7eff-a529-9590-31e7-b0007b416f81
2014-04-23 19:10:51 +00:00
|
|
|
(perlinNoiseShader.fType == kFractalNoise_Type) ? noise : SkScalarAbs(noise), ratio);
|
2013-04-05 13:47:09 +00:00
|
|
|
noiseVector.fX *= 2;
|
|
|
|
noiseVector.fY *= 2;
|
|
|
|
ratio *= 2;
|
Revert of Revert of Extract most of the mutable state of SkShader into a separate Context object. (https://codereview.chromium.org/249643002/)
Reason for revert:
Chromium side change landed along side DEPS roll that includes r14323.
Original issue's description:
> Revert of Extract most of the mutable state of SkShader into a separate Context object. (https://codereview.chromium.org/207683004/)
>
> Reason for revert:
> This is blocking the DEPS roll into Chromium. Failures can be seen here:
>
> http://build.chromium.org/p/tryserver.chromium/builders/android_dbg/builds/174333
>
> Original issue's description:
> > Extract most of the mutable state of SkShader into a separate Context object.
> >
> > SkShader currently stores some state during draw calls via setContext(...).
> > Move that mutable state into a separate SkShader::Context class that is
> > constructed on demand for the duration of the draw.
> >
> > Calls to setContext() are replaced with createContext() which returns a context
> > corresponding to the shader object or NULL if the parameters to createContext
> > are invalid.
> >
> > TEST=out/Debug/dm
> > BUG=skia:1976
> >
> > Committed: http://code.google.com/p/skia/source/detail?r=14216
> >
> > Committed: http://code.google.com/p/skia/source/detail?r=14323
>
> TBR=scroggo@google.com,skyostil@chromium.org,tomhudson@chromium.org,senorblanco@chromium.org,reed@google.com,bungeman@google.com,dominikg@chromium.org
> NOTREECHECKS=true
> NOTRY=true
> BUG=skia:1976
>
> Committed: http://code.google.com/p/skia/source/detail?r=14326
R=scroggo@google.com, skyostil@chromium.org, tomhudson@chromium.org, senorblanco@chromium.org, reed@google.com, bungeman@google.com, dominikg@chromium.org
TBR=bungeman@google.com, dominikg@chromium.org, reed@google.com, scroggo@google.com, senorblanco@chromium.org, skyostil@chromium.org, tomhudson@chromium.org
NOTREECHECKS=true
NOTRY=true
BUG=skia:1976
Author: bsalomon@google.com
Review URL: https://codereview.chromium.org/246403013
git-svn-id: http://skia.googlecode.com/svn/trunk@14328 2bbb7eff-a529-9590-31e7-b0007b416f81
2014-04-23 19:10:51 +00:00
|
|
|
if (perlinNoiseShader.fStitchTiles) {
|
2013-04-05 13:47:09 +00:00
|
|
|
// Update stitch values
|
|
|
|
stitchData.fWidth *= 2;
|
|
|
|
stitchData.fWrapX = stitchData.fWidth + kPerlinNoise;
|
|
|
|
stitchData.fHeight *= 2;
|
|
|
|
stitchData.fWrapY = stitchData.fHeight + kPerlinNoise;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
|
|
|
|
// by fractalNoise and (turbulenceFunctionResult) by turbulence.
|
Revert of Revert of Extract most of the mutable state of SkShader into a separate Context object. (https://codereview.chromium.org/249643002/)
Reason for revert:
Chromium side change landed along side DEPS roll that includes r14323.
Original issue's description:
> Revert of Extract most of the mutable state of SkShader into a separate Context object. (https://codereview.chromium.org/207683004/)
>
> Reason for revert:
> This is blocking the DEPS roll into Chromium. Failures can be seen here:
>
> http://build.chromium.org/p/tryserver.chromium/builders/android_dbg/builds/174333
>
> Original issue's description:
> > Extract most of the mutable state of SkShader into a separate Context object.
> >
> > SkShader currently stores some state during draw calls via setContext(...).
> > Move that mutable state into a separate SkShader::Context class that is
> > constructed on demand for the duration of the draw.
> >
> > Calls to setContext() are replaced with createContext() which returns a context
> > corresponding to the shader object or NULL if the parameters to createContext
> > are invalid.
> >
> > TEST=out/Debug/dm
> > BUG=skia:1976
> >
> > Committed: http://code.google.com/p/skia/source/detail?r=14216
> >
> > Committed: http://code.google.com/p/skia/source/detail?r=14323
>
> TBR=scroggo@google.com,skyostil@chromium.org,tomhudson@chromium.org,senorblanco@chromium.org,reed@google.com,bungeman@google.com,dominikg@chromium.org
> NOTREECHECKS=true
> NOTRY=true
> BUG=skia:1976
>
> Committed: http://code.google.com/p/skia/source/detail?r=14326
R=scroggo@google.com, skyostil@chromium.org, tomhudson@chromium.org, senorblanco@chromium.org, reed@google.com, bungeman@google.com, dominikg@chromium.org
TBR=bungeman@google.com, dominikg@chromium.org, reed@google.com, scroggo@google.com, senorblanco@chromium.org, skyostil@chromium.org, tomhudson@chromium.org
NOTREECHECKS=true
NOTRY=true
BUG=skia:1976
Author: bsalomon@google.com
Review URL: https://codereview.chromium.org/246403013
git-svn-id: http://skia.googlecode.com/svn/trunk@14328 2bbb7eff-a529-9590-31e7-b0007b416f81
2014-04-23 19:10:51 +00:00
|
|
|
if (perlinNoiseShader.fType == kFractalNoise_Type) {
|
2013-04-05 13:47:09 +00:00
|
|
|
turbulenceFunctionResult =
|
|
|
|
SkScalarMul(turbulenceFunctionResult, SK_ScalarHalf) + SK_ScalarHalf;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (channel == 3) { // Scale alpha by paint value
|
|
|
|
turbulenceFunctionResult = SkScalarMul(turbulenceFunctionResult,
|
|
|
|
SkScalarDiv(SkIntToScalar(getPaintAlpha()), SkIntToScalar(255)));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Clamp result
|
|
|
|
return SkScalarPin(turbulenceFunctionResult, 0, SK_Scalar1);
|
|
|
|
}
|
|
|
|
|
Revert of Revert of Extract most of the mutable state of SkShader into a separate Context object. (https://codereview.chromium.org/249643002/)
Reason for revert:
Chromium side change landed along side DEPS roll that includes r14323.
Original issue's description:
> Revert of Extract most of the mutable state of SkShader into a separate Context object. (https://codereview.chromium.org/207683004/)
>
> Reason for revert:
> This is blocking the DEPS roll into Chromium. Failures can be seen here:
>
> http://build.chromium.org/p/tryserver.chromium/builders/android_dbg/builds/174333
>
> Original issue's description:
> > Extract most of the mutable state of SkShader into a separate Context object.
> >
> > SkShader currently stores some state during draw calls via setContext(...).
> > Move that mutable state into a separate SkShader::Context class that is
> > constructed on demand for the duration of the draw.
> >
> > Calls to setContext() are replaced with createContext() which returns a context
> > corresponding to the shader object or NULL if the parameters to createContext
> > are invalid.
> >
> > TEST=out/Debug/dm
> > BUG=skia:1976
> >
> > Committed: http://code.google.com/p/skia/source/detail?r=14216
> >
> > Committed: http://code.google.com/p/skia/source/detail?r=14323
>
> TBR=scroggo@google.com,skyostil@chromium.org,tomhudson@chromium.org,senorblanco@chromium.org,reed@google.com,bungeman@google.com,dominikg@chromium.org
> NOTREECHECKS=true
> NOTRY=true
> BUG=skia:1976
>
> Committed: http://code.google.com/p/skia/source/detail?r=14326
R=scroggo@google.com, skyostil@chromium.org, tomhudson@chromium.org, senorblanco@chromium.org, reed@google.com, bungeman@google.com, dominikg@chromium.org
TBR=bungeman@google.com, dominikg@chromium.org, reed@google.com, scroggo@google.com, senorblanco@chromium.org, skyostil@chromium.org, tomhudson@chromium.org
NOTREECHECKS=true
NOTRY=true
BUG=skia:1976
Author: bsalomon@google.com
Review URL: https://codereview.chromium.org/246403013
git-svn-id: http://skia.googlecode.com/svn/trunk@14328 2bbb7eff-a529-9590-31e7-b0007b416f81
2014-04-23 19:10:51 +00:00
|
|
|
SkPMColor SkPerlinNoiseShader::PerlinNoiseShaderContext::shade(
|
|
|
|
const SkPoint& point, StitchData& stitchData) const {
|
2013-04-05 13:47:09 +00:00
|
|
|
SkPoint newPoint;
|
2014-04-04 14:46:10 +00:00
|
|
|
fMatrix.mapPoints(&newPoint, &point, 1);
|
2013-04-05 13:47:09 +00:00
|
|
|
newPoint.fX = SkScalarRoundToScalar(newPoint.fX);
|
|
|
|
newPoint.fY = SkScalarRoundToScalar(newPoint.fY);
|
|
|
|
|
|
|
|
U8CPU rgba[4];
|
|
|
|
for (int channel = 3; channel >= 0; --channel) {
|
|
|
|
rgba[channel] = SkScalarFloorToInt(255 *
|
2014-06-27 20:35:52 +00:00
|
|
|
calculateTurbulenceValueForPoint(channel, stitchData, newPoint));
|
2013-04-05 13:47:09 +00:00
|
|
|
}
|
|
|
|
return SkPreMultiplyARGB(rgba[3], rgba[0], rgba[1], rgba[2]);
|
|
|
|
}
|
|
|
|
|
2014-05-05 18:39:18 +00:00
|
|
|
SkShader::Context* SkPerlinNoiseShader::onCreateContext(const ContextRec& rec,
|
|
|
|
void* storage) const {
|
2014-05-01 19:31:31 +00:00
|
|
|
return SkNEW_PLACEMENT_ARGS(storage, PerlinNoiseShaderContext, (*this, rec));
|
Revert of Revert of Extract most of the mutable state of SkShader into a separate Context object. (https://codereview.chromium.org/249643002/)
Reason for revert:
Chromium side change landed along side DEPS roll that includes r14323.
Original issue's description:
> Revert of Extract most of the mutable state of SkShader into a separate Context object. (https://codereview.chromium.org/207683004/)
>
> Reason for revert:
> This is blocking the DEPS roll into Chromium. Failures can be seen here:
>
> http://build.chromium.org/p/tryserver.chromium/builders/android_dbg/builds/174333
>
> Original issue's description:
> > Extract most of the mutable state of SkShader into a separate Context object.
> >
> > SkShader currently stores some state during draw calls via setContext(...).
> > Move that mutable state into a separate SkShader::Context class that is
> > constructed on demand for the duration of the draw.
> >
> > Calls to setContext() are replaced with createContext() which returns a context
> > corresponding to the shader object or NULL if the parameters to createContext
> > are invalid.
> >
> > TEST=out/Debug/dm
> > BUG=skia:1976
> >
> > Committed: http://code.google.com/p/skia/source/detail?r=14216
> >
> > Committed: http://code.google.com/p/skia/source/detail?r=14323
>
> TBR=scroggo@google.com,skyostil@chromium.org,tomhudson@chromium.org,senorblanco@chromium.org,reed@google.com,bungeman@google.com,dominikg@chromium.org
> NOTREECHECKS=true
> NOTRY=true
> BUG=skia:1976
>
> Committed: http://code.google.com/p/skia/source/detail?r=14326
R=scroggo@google.com, skyostil@chromium.org, tomhudson@chromium.org, senorblanco@chromium.org, reed@google.com, bungeman@google.com, dominikg@chromium.org
TBR=bungeman@google.com, dominikg@chromium.org, reed@google.com, scroggo@google.com, senorblanco@chromium.org, skyostil@chromium.org, tomhudson@chromium.org
NOTREECHECKS=true
NOTRY=true
BUG=skia:1976
Author: bsalomon@google.com
Review URL: https://codereview.chromium.org/246403013
git-svn-id: http://skia.googlecode.com/svn/trunk@14328 2bbb7eff-a529-9590-31e7-b0007b416f81
2014-04-23 19:10:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
size_t SkPerlinNoiseShader::contextSize() const {
|
|
|
|
return sizeof(PerlinNoiseShaderContext);
|
|
|
|
}
|
|
|
|
|
|
|
|
SkPerlinNoiseShader::PerlinNoiseShaderContext::PerlinNoiseShaderContext(
|
2014-05-01 19:31:31 +00:00
|
|
|
const SkPerlinNoiseShader& shader, const ContextRec& rec)
|
|
|
|
: INHERITED(shader, rec)
|
Revert of Revert of Extract most of the mutable state of SkShader into a separate Context object. (https://codereview.chromium.org/249643002/)
Reason for revert:
Chromium side change landed along side DEPS roll that includes r14323.
Original issue's description:
> Revert of Extract most of the mutable state of SkShader into a separate Context object. (https://codereview.chromium.org/207683004/)
>
> Reason for revert:
> This is blocking the DEPS roll into Chromium. Failures can be seen here:
>
> http://build.chromium.org/p/tryserver.chromium/builders/android_dbg/builds/174333
>
> Original issue's description:
> > Extract most of the mutable state of SkShader into a separate Context object.
> >
> > SkShader currently stores some state during draw calls via setContext(...).
> > Move that mutable state into a separate SkShader::Context class that is
> > constructed on demand for the duration of the draw.
> >
> > Calls to setContext() are replaced with createContext() which returns a context
> > corresponding to the shader object or NULL if the parameters to createContext
> > are invalid.
> >
> > TEST=out/Debug/dm
> > BUG=skia:1976
> >
> > Committed: http://code.google.com/p/skia/source/detail?r=14216
> >
> > Committed: http://code.google.com/p/skia/source/detail?r=14323
>
> TBR=scroggo@google.com,skyostil@chromium.org,tomhudson@chromium.org,senorblanco@chromium.org,reed@google.com,bungeman@google.com,dominikg@chromium.org
> NOTREECHECKS=true
> NOTRY=true
> BUG=skia:1976
>
> Committed: http://code.google.com/p/skia/source/detail?r=14326
R=scroggo@google.com, skyostil@chromium.org, tomhudson@chromium.org, senorblanco@chromium.org, reed@google.com, bungeman@google.com, dominikg@chromium.org
TBR=bungeman@google.com, dominikg@chromium.org, reed@google.com, scroggo@google.com, senorblanco@chromium.org, skyostil@chromium.org, tomhudson@chromium.org
NOTREECHECKS=true
NOTRY=true
BUG=skia:1976
Author: bsalomon@google.com
Review URL: https://codereview.chromium.org/246403013
git-svn-id: http://skia.googlecode.com/svn/trunk@14328 2bbb7eff-a529-9590-31e7-b0007b416f81
2014-04-23 19:10:51 +00:00
|
|
|
{
|
2014-05-01 19:31:31 +00:00
|
|
|
SkMatrix newMatrix = *rec.fMatrix;
|
2014-05-12 18:12:24 +00:00
|
|
|
newMatrix.preConcat(shader.getLocalMatrix());
|
|
|
|
if (rec.fLocalMatrix) {
|
|
|
|
newMatrix.preConcat(*rec.fLocalMatrix);
|
|
|
|
}
|
2014-04-04 14:46:10 +00:00
|
|
|
// This (1,1) translation is due to WebKit's 1 based coordinates for the noise
|
|
|
|
// (as opposed to 0 based, usually). The same adjustment is in the setData() function.
|
2014-06-27 20:35:52 +00:00
|
|
|
fMatrix.setTranslate(-newMatrix.getTranslateX() + SK_Scalar1, -newMatrix.getTranslateY() + SK_Scalar1);
|
|
|
|
fPaintingData = SkNEW_ARGS(PaintingData, (shader.fTileSize, shader.fSeed, shader.fBaseFrequencyX, shader.fBaseFrequencyY, newMatrix));
|
|
|
|
}
|
|
|
|
|
|
|
|
SkPerlinNoiseShader::PerlinNoiseShaderContext::~PerlinNoiseShaderContext() {
|
|
|
|
SkDELETE(fPaintingData);
|
2013-04-05 13:47:09 +00:00
|
|
|
}
|
|
|
|
|
Revert of Revert of Extract most of the mutable state of SkShader into a separate Context object. (https://codereview.chromium.org/249643002/)
Reason for revert:
Chromium side change landed along side DEPS roll that includes r14323.
Original issue's description:
> Revert of Extract most of the mutable state of SkShader into a separate Context object. (https://codereview.chromium.org/207683004/)
>
> Reason for revert:
> This is blocking the DEPS roll into Chromium. Failures can be seen here:
>
> http://build.chromium.org/p/tryserver.chromium/builders/android_dbg/builds/174333
>
> Original issue's description:
> > Extract most of the mutable state of SkShader into a separate Context object.
> >
> > SkShader currently stores some state during draw calls via setContext(...).
> > Move that mutable state into a separate SkShader::Context class that is
> > constructed on demand for the duration of the draw.
> >
> > Calls to setContext() are replaced with createContext() which returns a context
> > corresponding to the shader object or NULL if the parameters to createContext
> > are invalid.
> >
> > TEST=out/Debug/dm
> > BUG=skia:1976
> >
> > Committed: http://code.google.com/p/skia/source/detail?r=14216
> >
> > Committed: http://code.google.com/p/skia/source/detail?r=14323
>
> TBR=scroggo@google.com,skyostil@chromium.org,tomhudson@chromium.org,senorblanco@chromium.org,reed@google.com,bungeman@google.com,dominikg@chromium.org
> NOTREECHECKS=true
> NOTRY=true
> BUG=skia:1976
>
> Committed: http://code.google.com/p/skia/source/detail?r=14326
R=scroggo@google.com, skyostil@chromium.org, tomhudson@chromium.org, senorblanco@chromium.org, reed@google.com, bungeman@google.com, dominikg@chromium.org
TBR=bungeman@google.com, dominikg@chromium.org, reed@google.com, scroggo@google.com, senorblanco@chromium.org, skyostil@chromium.org, tomhudson@chromium.org
NOTREECHECKS=true
NOTRY=true
BUG=skia:1976
Author: bsalomon@google.com
Review URL: https://codereview.chromium.org/246403013
git-svn-id: http://skia.googlecode.com/svn/trunk@14328 2bbb7eff-a529-9590-31e7-b0007b416f81
2014-04-23 19:10:51 +00:00
|
|
|
void SkPerlinNoiseShader::PerlinNoiseShaderContext::shadeSpan(
|
|
|
|
int x, int y, SkPMColor result[], int count) {
|
2013-04-05 13:47:09 +00:00
|
|
|
SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y));
|
|
|
|
StitchData stitchData;
|
|
|
|
for (int i = 0; i < count; ++i) {
|
|
|
|
result[i] = shade(point, stitchData);
|
|
|
|
point.fX += SK_Scalar1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Revert of Revert of Extract most of the mutable state of SkShader into a separate Context object. (https://codereview.chromium.org/249643002/)
Reason for revert:
Chromium side change landed along side DEPS roll that includes r14323.
Original issue's description:
> Revert of Extract most of the mutable state of SkShader into a separate Context object. (https://codereview.chromium.org/207683004/)
>
> Reason for revert:
> This is blocking the DEPS roll into Chromium. Failures can be seen here:
>
> http://build.chromium.org/p/tryserver.chromium/builders/android_dbg/builds/174333
>
> Original issue's description:
> > Extract most of the mutable state of SkShader into a separate Context object.
> >
> > SkShader currently stores some state during draw calls via setContext(...).
> > Move that mutable state into a separate SkShader::Context class that is
> > constructed on demand for the duration of the draw.
> >
> > Calls to setContext() are replaced with createContext() which returns a context
> > corresponding to the shader object or NULL if the parameters to createContext
> > are invalid.
> >
> > TEST=out/Debug/dm
> > BUG=skia:1976
> >
> > Committed: http://code.google.com/p/skia/source/detail?r=14216
> >
> > Committed: http://code.google.com/p/skia/source/detail?r=14323
>
> TBR=scroggo@google.com,skyostil@chromium.org,tomhudson@chromium.org,senorblanco@chromium.org,reed@google.com,bungeman@google.com,dominikg@chromium.org
> NOTREECHECKS=true
> NOTRY=true
> BUG=skia:1976
>
> Committed: http://code.google.com/p/skia/source/detail?r=14326
R=scroggo@google.com, skyostil@chromium.org, tomhudson@chromium.org, senorblanco@chromium.org, reed@google.com, bungeman@google.com, dominikg@chromium.org
TBR=bungeman@google.com, dominikg@chromium.org, reed@google.com, scroggo@google.com, senorblanco@chromium.org, skyostil@chromium.org, tomhudson@chromium.org
NOTREECHECKS=true
NOTRY=true
BUG=skia:1976
Author: bsalomon@google.com
Review URL: https://codereview.chromium.org/246403013
git-svn-id: http://skia.googlecode.com/svn/trunk@14328 2bbb7eff-a529-9590-31e7-b0007b416f81
2014-04-23 19:10:51 +00:00
|
|
|
void SkPerlinNoiseShader::PerlinNoiseShaderContext::shadeSpan16(
|
|
|
|
int x, int y, uint16_t result[], int count) {
|
2013-04-05 13:47:09 +00:00
|
|
|
SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y));
|
|
|
|
StitchData stitchData;
|
|
|
|
DITHER_565_SCAN(y);
|
|
|
|
for (int i = 0; i < count; ++i) {
|
|
|
|
unsigned dither = DITHER_VALUE(x);
|
|
|
|
result[i] = SkDitherRGB32To565(shade(point, stitchData), dither);
|
|
|
|
DITHER_INC_X(x);
|
|
|
|
point.fX += SK_Scalar1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
|
*** Perlin noise GM needs to be rebaselined ***
Enabling Perlin Noise on Android
I enabled the Perlin Noise shader on Android after doing some minor modifications to the shader, specifically for Android (and #ifdefed for Android, to make sure none of this affects other platforms).
For Tegra devices (Nexus 7, Xoom), a precision issue related to the color values read from textures caused the noise to read the wrong indices and produce bad noise. I fixed this by adding a founding of the values read by simply doing the equivalent of "colorValue = floor(colorValue * 255.0) / 255.0" to make sure we retrieve the colors that were written in the texture originally.
For non-Tegra devices (Nexus 10), dealing with values in the order of 4096.0 was problematic without using the "highp" precision setting. To solve this, a few variables were given the high precision setting.
Since both fixes don't seem to do considerable harm to the platforms that are not being targetted, I left both fixes on all android devices for now.
I also reduced the Perlin noise gm so that it takes less time to test it on the Xoom (Original time was about 20 seconds, this shold take less than 10, hopefully)
BUG=
R=senorblanco@google.com, bsalomon@google.com, sugoi@google.com, senorblanco@chromium.org
Author: sugoi@chromium.org
Review URL: https://chromiumcodereview.appspot.com/16818013
git-svn-id: http://skia.googlecode.com/svn/trunk@9637 2bbb7eff-a529-9590-31e7-b0007b416f81
2013-06-17 14:19:01 +00:00
|
|
|
#if SK_SUPPORT_GPU
|
2013-04-05 13:47:09 +00:00
|
|
|
|
2014-09-23 16:50:21 +00:00
|
|
|
#include "GrTBackendProcessorFactory.h"
|
2013-04-05 13:47:09 +00:00
|
|
|
|
2014-09-23 16:50:21 +00:00
|
|
|
class GrGLPerlinNoise : public GrGLFragmentProcessor {
|
2013-04-17 13:46:56 +00:00
|
|
|
public:
|
2014-09-23 16:50:21 +00:00
|
|
|
GrGLPerlinNoise(const GrBackendProcessorFactory&,
|
|
|
|
const GrProcessor&);
|
2013-04-17 13:46:56 +00:00
|
|
|
virtual ~GrGLPerlinNoise() {}
|
2013-04-05 13:47:09 +00:00
|
|
|
|
2014-10-09 22:04:05 +00:00
|
|
|
virtual void emitCode(GrGLFPBuilder*,
|
2014-09-23 16:50:21 +00:00
|
|
|
const GrFragmentProcessor&,
|
|
|
|
const GrProcessorKey&,
|
2013-04-05 13:47:09 +00:00
|
|
|
const char* outputColor,
|
|
|
|
const char* inputColor,
|
2013-10-02 13:04:56 +00:00
|
|
|
const TransformedCoordsArray&,
|
2013-04-05 13:47:09 +00:00
|
|
|
const TextureSamplerArray&) SK_OVERRIDE;
|
|
|
|
|
2014-09-23 16:50:21 +00:00
|
|
|
virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE;
|
2013-04-17 13:46:56 +00:00
|
|
|
|
2014-09-23 16:50:21 +00:00
|
|
|
static inline void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder* b);
|
2013-04-17 13:46:56 +00:00
|
|
|
|
2014-06-16 17:49:58 +00:00
|
|
|
private:
|
2013-04-05 13:47:09 +00:00
|
|
|
|
2014-07-30 07:04:16 +00:00
|
|
|
GrGLProgramDataManager::UniformHandle fStitchDataUni;
|
|
|
|
SkPerlinNoiseShader::Type fType;
|
|
|
|
bool fStitchTiles;
|
|
|
|
int fNumOctaves;
|
|
|
|
GrGLProgramDataManager::UniformHandle fBaseFrequencyUni;
|
|
|
|
GrGLProgramDataManager::UniformHandle fAlphaUni;
|
2013-04-05 13:47:09 +00:00
|
|
|
|
|
|
|
private:
|
2014-09-23 16:50:21 +00:00
|
|
|
typedef GrGLFragmentProcessor INHERITED;
|
2013-04-05 13:47:09 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
|
2014-09-23 16:50:21 +00:00
|
|
|
class GrPerlinNoiseEffect : public GrFragmentProcessor {
|
2013-04-05 13:47:09 +00:00
|
|
|
public:
|
2014-09-23 16:50:21 +00:00
|
|
|
static GrFragmentProcessor* Create(SkPerlinNoiseShader::Type type,
|
|
|
|
int numOctaves, bool stitchTiles,
|
|
|
|
SkPerlinNoiseShader::PaintingData* paintingData,
|
|
|
|
GrTexture* permutationsTexture, GrTexture* noiseTexture,
|
|
|
|
const SkMatrix& matrix, uint8_t alpha) {
|
2014-07-08 14:34:20 +00:00
|
|
|
return SkNEW_ARGS(GrPerlinNoiseEffect, (type, numOctaves, stitchTiles, paintingData,
|
|
|
|
permutationsTexture, noiseTexture, matrix, alpha));
|
2013-04-05 13:47:09 +00:00
|
|
|
}
|
|
|
|
|
2014-06-27 20:35:52 +00:00
|
|
|
virtual ~GrPerlinNoiseEffect() {
|
|
|
|
SkDELETE(fPaintingData);
|
|
|
|
}
|
2013-04-05 13:47:09 +00:00
|
|
|
|
|
|
|
static const char* Name() { return "PerlinNoise"; }
|
2014-09-23 16:50:21 +00:00
|
|
|
virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERRIDE {
|
|
|
|
return GrTBackendFragmentProcessorFactory<GrPerlinNoiseEffect>::getInstance();
|
2013-04-05 13:47:09 +00:00
|
|
|
}
|
2014-06-27 20:35:52 +00:00
|
|
|
const SkPerlinNoiseShader::StitchData& stitchData() const { return fPaintingData->fStitchDataInit; }
|
2013-04-05 13:47:09 +00:00
|
|
|
|
2014-06-16 17:49:58 +00:00
|
|
|
SkPerlinNoiseShader::Type type() const { return fType; }
|
|
|
|
bool stitchTiles() const { return fStitchTiles; }
|
2014-06-27 20:35:52 +00:00
|
|
|
const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency; }
|
2014-06-16 17:49:58 +00:00
|
|
|
int numOctaves() const { return fNumOctaves; }
|
|
|
|
const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); }
|
|
|
|
uint8_t alpha() const { return fAlpha; }
|
|
|
|
|
2014-09-23 16:50:21 +00:00
|
|
|
typedef GrGLPerlinNoise GLProcessor;
|
2013-04-05 13:47:09 +00:00
|
|
|
|
|
|
|
private:
|
2014-10-15 15:19:04 +00:00
|
|
|
virtual bool onIsEqual(const GrFragmentProcessor& sBase) const SK_OVERRIDE {
|
2014-09-16 15:21:41 +00:00
|
|
|
const GrPerlinNoiseEffect& s = sBase.cast<GrPerlinNoiseEffect>();
|
2014-06-16 17:49:58 +00:00
|
|
|
return fType == s.fType &&
|
2014-06-27 20:35:52 +00:00
|
|
|
fPaintingData->fBaseFrequency == s.fPaintingData->fBaseFrequency &&
|
2014-06-16 17:49:58 +00:00
|
|
|
fNumOctaves == s.fNumOctaves &&
|
|
|
|
fStitchTiles == s.fStitchTiles &&
|
|
|
|
fAlpha == s.fAlpha &&
|
2014-06-27 20:35:52 +00:00
|
|
|
fPaintingData->fStitchDataInit == s.fPaintingData->fStitchDataInit;
|
2013-04-05 13:47:09 +00:00
|
|
|
}
|
|
|
|
|
2014-10-03 13:24:12 +00:00
|
|
|
void onComputeInvariantOutput(InvariantOutput* inout) const SK_OVERRIDE {
|
2014-10-15 20:49:02 +00:00
|
|
|
inout->setToUnknown(InvariantOutput::kWillNot_ReadInput);
|
2014-10-03 13:24:12 +00:00
|
|
|
}
|
|
|
|
|
2014-06-27 20:35:52 +00:00
|
|
|
GrPerlinNoiseEffect(SkPerlinNoiseShader::Type type,
|
2013-04-05 13:47:09 +00:00
|
|
|
int numOctaves, bool stitchTiles,
|
2014-06-27 20:35:52 +00:00
|
|
|
SkPerlinNoiseShader::PaintingData* paintingData,
|
2013-04-05 13:47:09 +00:00
|
|
|
GrTexture* permutationsTexture, GrTexture* noiseTexture,
|
|
|
|
const SkMatrix& matrix, uint8_t alpha)
|
2014-06-16 17:49:58 +00:00
|
|
|
: fType(type)
|
|
|
|
, fNumOctaves(numOctaves)
|
|
|
|
, fStitchTiles(stitchTiles)
|
|
|
|
, fAlpha(alpha)
|
2013-04-17 13:46:56 +00:00
|
|
|
, fPermutationsAccess(permutationsTexture)
|
2013-04-05 13:47:09 +00:00
|
|
|
, fNoiseAccess(noiseTexture)
|
2014-06-27 20:35:52 +00:00
|
|
|
, fPaintingData(paintingData) {
|
2013-04-05 13:47:09 +00:00
|
|
|
this->addTextureAccess(&fPermutationsAccess);
|
|
|
|
this->addTextureAccess(&fNoiseAccess);
|
2014-06-27 20:35:52 +00:00
|
|
|
fCoordTransform.reset(kLocal_GrCoordSet, matrix);
|
2014-06-16 17:49:58 +00:00
|
|
|
this->addCoordTransform(&fCoordTransform);
|
2013-04-05 13:47:09 +00:00
|
|
|
}
|
|
|
|
|
2014-09-23 16:50:21 +00:00
|
|
|
GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
|
2013-04-05 13:47:09 +00:00
|
|
|
|
2014-06-16 17:49:58 +00:00
|
|
|
SkPerlinNoiseShader::Type fType;
|
|
|
|
GrCoordTransform fCoordTransform;
|
|
|
|
int fNumOctaves;
|
|
|
|
bool fStitchTiles;
|
|
|
|
uint8_t fAlpha;
|
2013-04-05 13:47:09 +00:00
|
|
|
GrTextureAccess fPermutationsAccess;
|
|
|
|
GrTextureAccess fNoiseAccess;
|
2014-06-27 20:35:52 +00:00
|
|
|
SkPerlinNoiseShader::PaintingData *fPaintingData;
|
2013-04-05 13:47:09 +00:00
|
|
|
|
2013-04-17 13:46:56 +00:00
|
|
|
private:
|
2014-09-23 16:50:21 +00:00
|
|
|
typedef GrFragmentProcessor INHERITED;
|
2013-04-05 13:47:09 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
2014-09-23 16:50:21 +00:00
|
|
|
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrPerlinNoiseEffect);
|
2013-04-05 13:47:09 +00:00
|
|
|
|
2014-09-23 16:50:21 +00:00
|
|
|
GrFragmentProcessor* GrPerlinNoiseEffect::TestCreate(SkRandom* random,
|
|
|
|
GrContext* context,
|
|
|
|
const GrDrawTargetCaps&,
|
|
|
|
GrTexture**) {
|
2013-04-18 14:04:57 +00:00
|
|
|
int numOctaves = random->nextRangeU(2, 10);
|
2013-04-05 13:47:09 +00:00
|
|
|
bool stitchTiles = random->nextBool();
|
|
|
|
SkScalar seed = SkIntToScalar(random->nextU());
|
|
|
|
SkISize tileSize = SkISize::Make(random->nextRangeU(4, 4096), random->nextRangeU(4, 4096));
|
2013-11-25 19:44:07 +00:00
|
|
|
SkScalar baseFrequencyX = random->nextRangeScalar(0.01f,
|
|
|
|
0.99f);
|
|
|
|
SkScalar baseFrequencyY = random->nextRangeScalar(0.01f,
|
|
|
|
0.99f);
|
2013-04-05 13:47:09 +00:00
|
|
|
|
|
|
|
SkShader* shader = random->nextBool() ?
|
|
|
|
SkPerlinNoiseShader::CreateFractalNoise(baseFrequencyX, baseFrequencyY, numOctaves, seed,
|
|
|
|
stitchTiles ? &tileSize : NULL) :
|
2014-04-01 16:09:37 +00:00
|
|
|
SkPerlinNoiseShader::CreateTurbulence(baseFrequencyX, baseFrequencyY, numOctaves, seed,
|
2013-04-05 13:47:09 +00:00
|
|
|
stitchTiles ? &tileSize : NULL);
|
|
|
|
|
|
|
|
SkPaint paint;
|
2014-07-08 16:56:10 +00:00
|
|
|
GrColor paintColor;
|
2014-09-23 16:50:21 +00:00
|
|
|
GrFragmentProcessor* effect;
|
|
|
|
SkAssertResult(shader->asFragmentProcessor(context, paint, NULL, &paintColor, &effect));
|
2013-04-05 13:47:09 +00:00
|
|
|
|
|
|
|
SkDELETE(shader);
|
|
|
|
|
|
|
|
return effect;
|
|
|
|
}
|
2013-04-17 13:46:56 +00:00
|
|
|
|
2014-09-23 16:50:21 +00:00
|
|
|
GrGLPerlinNoise::GrGLPerlinNoise(const GrBackendProcessorFactory& factory,
|
|
|
|
const GrProcessor& processor)
|
2014-06-16 17:49:58 +00:00
|
|
|
: INHERITED (factory)
|
2014-09-23 16:50:21 +00:00
|
|
|
, fType(processor.cast<GrPerlinNoiseEffect>().type())
|
|
|
|
, fStitchTiles(processor.cast<GrPerlinNoiseEffect>().stitchTiles())
|
|
|
|
, fNumOctaves(processor.cast<GrPerlinNoiseEffect>().numOctaves()) {
|
2013-04-17 13:46:56 +00:00
|
|
|
}
|
|
|
|
|
2014-10-09 22:04:05 +00:00
|
|
|
void GrGLPerlinNoise::emitCode(GrGLFPBuilder* builder,
|
2014-09-23 16:50:21 +00:00
|
|
|
const GrFragmentProcessor&,
|
|
|
|
const GrProcessorKey& key,
|
2013-04-05 13:47:09 +00:00
|
|
|
const char* outputColor,
|
|
|
|
const char* inputColor,
|
2013-10-02 13:04:56 +00:00
|
|
|
const TransformedCoordsArray& coords,
|
2013-04-05 13:47:09 +00:00
|
|
|
const TextureSamplerArray& samplers) {
|
|
|
|
sk_ignore_unused_variable(inputColor);
|
|
|
|
|
2014-10-09 22:04:05 +00:00
|
|
|
GrGLFPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
|
2014-08-22 03:18:45 +00:00
|
|
|
SkString vCoords = fsBuilder->ensureFSCoords2D(coords, 0);
|
2013-04-05 13:47:09 +00:00
|
|
|
|
2014-08-22 03:18:45 +00:00
|
|
|
fBaseFrequencyUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
|
2013-04-05 13:47:09 +00:00
|
|
|
kVec2f_GrSLType, "baseFrequency");
|
|
|
|
const char* baseFrequencyUni = builder->getUniformCStr(fBaseFrequencyUni);
|
2014-08-22 03:18:45 +00:00
|
|
|
fAlphaUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
|
2013-04-05 13:47:09 +00:00
|
|
|
kFloat_GrSLType, "alpha");
|
|
|
|
const char* alphaUni = builder->getUniformCStr(fAlphaUni);
|
|
|
|
|
|
|
|
const char* stitchDataUni = NULL;
|
|
|
|
if (fStitchTiles) {
|
2014-08-22 03:18:45 +00:00
|
|
|
fStitchDataUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
|
2013-07-04 18:13:05 +00:00
|
|
|
kVec2f_GrSLType, "stitchData");
|
2013-04-05 13:47:09 +00:00
|
|
|
stitchDataUni = builder->getUniformCStr(fStitchDataUni);
|
|
|
|
}
|
|
|
|
|
2013-06-10 13:59:25 +00:00
|
|
|
// There are 4 lines, so the center of each line is 1/8, 3/8, 5/8 and 7/8
|
|
|
|
const char* chanCoordR = "0.125";
|
|
|
|
const char* chanCoordG = "0.375";
|
|
|
|
const char* chanCoordB = "0.625";
|
|
|
|
const char* chanCoordA = "0.875";
|
|
|
|
const char* chanCoord = "chanCoord";
|
2013-04-05 13:47:09 +00:00
|
|
|
const char* stitchData = "stitchData";
|
|
|
|
const char* ratio = "ratio";
|
|
|
|
const char* noiseVec = "noiseVec";
|
|
|
|
const char* noiseSmooth = "noiseSmooth";
|
Fix tiled perlin noise.
It turns out that the perlin implementation we inherited from WebKit
does not actually generate tileable noise (see Chromium bug
http://crbug.com/383495).
The main problem is that when generating coordinates for gradient
interpolation, it was attempting to wrap both x and (x + 1)
simultaneously at the tile boundary (that is, either both or neither
are wrapped). This obviously won't work, since along the tile seams,
(x + 1) should be wrapped, but x should not. The same is true in y.
This patch fixes both the CPU and GPU paths, renames some variables to
more closely match the spec, and modifies the perlin noise GM to
actually test tiling. (Note that the clipping the GM was doing was
removed, since it's superfluous: it used to be necessary for image
filters, but isn't anymore, and this isn't an image filter GM anyway.)
R=sugoi@google.com, sugoi
TBR=senorblanco
Author: senorblanco@chromium.org
Review URL: https://codereview.chromium.org/332523006
2014-06-12 18:24:19 +00:00
|
|
|
const char* floorVal = "floorVal";
|
2013-04-05 13:47:09 +00:00
|
|
|
const char* fractVal = "fractVal";
|
|
|
|
const char* uv = "uv";
|
|
|
|
const char* ab = "ab";
|
|
|
|
const char* latticeIdx = "latticeIdx";
|
Fix tiled perlin noise.
It turns out that the perlin implementation we inherited from WebKit
does not actually generate tileable noise (see Chromium bug
http://crbug.com/383495).
The main problem is that when generating coordinates for gradient
interpolation, it was attempting to wrap both x and (x + 1)
simultaneously at the tile boundary (that is, either both or neither
are wrapped). This obviously won't work, since along the tile seams,
(x + 1) should be wrapped, but x should not. The same is true in y.
This patch fixes both the CPU and GPU paths, renames some variables to
more closely match the spec, and modifies the perlin noise GM to
actually test tiling. (Note that the clipping the GM was doing was
removed, since it's superfluous: it used to be necessary for image
filters, but isn't anymore, and this isn't an image filter GM anyway.)
R=sugoi@google.com, sugoi
TBR=senorblanco
Author: senorblanco@chromium.org
Review URL: https://codereview.chromium.org/332523006
2014-06-12 18:24:19 +00:00
|
|
|
const char* bcoords = "bcoords";
|
2013-04-05 13:47:09 +00:00
|
|
|
const char* lattice = "lattice";
|
|
|
|
const char* inc8bit = "0.00390625"; // 1.0 / 256.0
|
|
|
|
// This is the math to convert the two 16bit integer packed into rgba 8 bit input into a
|
|
|
|
// [-1,1] vector and perform a dot product between that vector and the provided vector.
|
|
|
|
const char* dotLattice = "dot(((%s.ga + %s.rb * vec2(%s)) * vec2(2.0) - vec2(1.0)), %s);";
|
|
|
|
|
2013-06-10 13:59:25 +00:00
|
|
|
// Add noise function
|
|
|
|
static const GrGLShaderVar gPerlinNoiseArgs[] = {
|
|
|
|
GrGLShaderVar(chanCoord, kFloat_GrSLType),
|
2013-07-04 18:13:05 +00:00
|
|
|
GrGLShaderVar(noiseVec, kVec2f_GrSLType)
|
2013-06-10 13:59:25 +00:00
|
|
|
};
|
2013-04-05 13:47:09 +00:00
|
|
|
|
2013-06-10 13:59:25 +00:00
|
|
|
static const GrGLShaderVar gPerlinNoiseStitchArgs[] = {
|
|
|
|
GrGLShaderVar(chanCoord, kFloat_GrSLType),
|
2013-07-04 18:13:05 +00:00
|
|
|
GrGLShaderVar(noiseVec, kVec2f_GrSLType),
|
|
|
|
GrGLShaderVar(stitchData, kVec2f_GrSLType)
|
2013-06-10 13:59:25 +00:00
|
|
|
};
|
2013-04-05 13:47:09 +00:00
|
|
|
|
2013-06-10 13:59:25 +00:00
|
|
|
SkString noiseCode;
|
2013-04-05 13:47:09 +00:00
|
|
|
|
Fix tiled perlin noise.
It turns out that the perlin implementation we inherited from WebKit
does not actually generate tileable noise (see Chromium bug
http://crbug.com/383495).
The main problem is that when generating coordinates for gradient
interpolation, it was attempting to wrap both x and (x + 1)
simultaneously at the tile boundary (that is, either both or neither
are wrapped). This obviously won't work, since along the tile seams,
(x + 1) should be wrapped, but x should not. The same is true in y.
This patch fixes both the CPU and GPU paths, renames some variables to
more closely match the spec, and modifies the perlin noise GM to
actually test tiling. (Note that the clipping the GM was doing was
removed, since it's superfluous: it used to be necessary for image
filters, but isn't anymore, and this isn't an image filter GM anyway.)
R=sugoi@google.com, sugoi
TBR=senorblanco
Author: senorblanco@chromium.org
Review URL: https://codereview.chromium.org/332523006
2014-06-12 18:24:19 +00:00
|
|
|
noiseCode.appendf("\tvec4 %s;\n", floorVal);
|
|
|
|
noiseCode.appendf("\t%s.xy = floor(%s);\n", floorVal, noiseVec);
|
|
|
|
noiseCode.appendf("\t%s.zw = %s.xy + vec2(1.0);\n", floorVal, floorVal);
|
|
|
|
noiseCode.appendf("\tvec2 %s = fract(%s);\n", fractVal, noiseVec);
|
2013-04-05 13:47:09 +00:00
|
|
|
|
|
|
|
// smooth curve : t * t * (3 - 2 * t)
|
Fix tiled perlin noise.
It turns out that the perlin implementation we inherited from WebKit
does not actually generate tileable noise (see Chromium bug
http://crbug.com/383495).
The main problem is that when generating coordinates for gradient
interpolation, it was attempting to wrap both x and (x + 1)
simultaneously at the tile boundary (that is, either both or neither
are wrapped). This obviously won't work, since along the tile seams,
(x + 1) should be wrapped, but x should not. The same is true in y.
This patch fixes both the CPU and GPU paths, renames some variables to
more closely match the spec, and modifies the perlin noise GM to
actually test tiling. (Note that the clipping the GM was doing was
removed, since it's superfluous: it used to be necessary for image
filters, but isn't anymore, and this isn't an image filter GM anyway.)
R=sugoi@google.com, sugoi
TBR=senorblanco
Author: senorblanco@chromium.org
Review URL: https://codereview.chromium.org/332523006
2014-06-12 18:24:19 +00:00
|
|
|
noiseCode.appendf("\n\tvec2 %s = %s * %s * (vec2(3.0) - vec2(2.0) * %s);",
|
|
|
|
noiseSmooth, fractVal, fractVal, fractVal);
|
2013-04-05 13:47:09 +00:00
|
|
|
|
|
|
|
// Adjust frequencies if we're stitching tiles
|
|
|
|
if (fStitchTiles) {
|
2013-07-04 18:13:05 +00:00
|
|
|
noiseCode.appendf("\n\tif(%s.x >= %s.x) { %s.x -= %s.x; }",
|
Fix tiled perlin noise.
It turns out that the perlin implementation we inherited from WebKit
does not actually generate tileable noise (see Chromium bug
http://crbug.com/383495).
The main problem is that when generating coordinates for gradient
interpolation, it was attempting to wrap both x and (x + 1)
simultaneously at the tile boundary (that is, either both or neither
are wrapped). This obviously won't work, since along the tile seams,
(x + 1) should be wrapped, but x should not. The same is true in y.
This patch fixes both the CPU and GPU paths, renames some variables to
more closely match the spec, and modifies the perlin noise GM to
actually test tiling. (Note that the clipping the GM was doing was
removed, since it's superfluous: it used to be necessary for image
filters, but isn't anymore, and this isn't an image filter GM anyway.)
R=sugoi@google.com, sugoi
TBR=senorblanco
Author: senorblanco@chromium.org
Review URL: https://codereview.chromium.org/332523006
2014-06-12 18:24:19 +00:00
|
|
|
floorVal, stitchData, floorVal, stitchData);
|
2013-07-04 18:13:05 +00:00
|
|
|
noiseCode.appendf("\n\tif(%s.y >= %s.y) { %s.y -= %s.y; }",
|
Fix tiled perlin noise.
It turns out that the perlin implementation we inherited from WebKit
does not actually generate tileable noise (see Chromium bug
http://crbug.com/383495).
The main problem is that when generating coordinates for gradient
interpolation, it was attempting to wrap both x and (x + 1)
simultaneously at the tile boundary (that is, either both or neither
are wrapped). This obviously won't work, since along the tile seams,
(x + 1) should be wrapped, but x should not. The same is true in y.
This patch fixes both the CPU and GPU paths, renames some variables to
more closely match the spec, and modifies the perlin noise GM to
actually test tiling. (Note that the clipping the GM was doing was
removed, since it's superfluous: it used to be necessary for image
filters, but isn't anymore, and this isn't an image filter GM anyway.)
R=sugoi@google.com, sugoi
TBR=senorblanco
Author: senorblanco@chromium.org
Review URL: https://codereview.chromium.org/332523006
2014-06-12 18:24:19 +00:00
|
|
|
floorVal, stitchData, floorVal, stitchData);
|
|
|
|
noiseCode.appendf("\n\tif(%s.z >= %s.x) { %s.z -= %s.x; }",
|
|
|
|
floorVal, stitchData, floorVal, stitchData);
|
|
|
|
noiseCode.appendf("\n\tif(%s.w >= %s.y) { %s.w -= %s.y; }",
|
|
|
|
floorVal, stitchData, floorVal, stitchData);
|
2013-04-05 13:47:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Get texture coordinates and normalize
|
Fix tiled perlin noise.
It turns out that the perlin implementation we inherited from WebKit
does not actually generate tileable noise (see Chromium bug
http://crbug.com/383495).
The main problem is that when generating coordinates for gradient
interpolation, it was attempting to wrap both x and (x + 1)
simultaneously at the tile boundary (that is, either both or neither
are wrapped). This obviously won't work, since along the tile seams,
(x + 1) should be wrapped, but x should not. The same is true in y.
This patch fixes both the CPU and GPU paths, renames some variables to
more closely match the spec, and modifies the perlin noise GM to
actually test tiling. (Note that the clipping the GM was doing was
removed, since it's superfluous: it used to be necessary for image
filters, but isn't anymore, and this isn't an image filter GM anyway.)
R=sugoi@google.com, sugoi
TBR=senorblanco
Author: senorblanco@chromium.org
Review URL: https://codereview.chromium.org/332523006
2014-06-12 18:24:19 +00:00
|
|
|
noiseCode.appendf("\n\t%s = fract(floor(mod(%s, 256.0)) / vec4(256.0));\n",
|
|
|
|
floorVal, floorVal);
|
2013-04-05 13:47:09 +00:00
|
|
|
|
|
|
|
// Get permutation for x
|
|
|
|
{
|
|
|
|
SkString xCoords("");
|
Fix tiled perlin noise.
It turns out that the perlin implementation we inherited from WebKit
does not actually generate tileable noise (see Chromium bug
http://crbug.com/383495).
The main problem is that when generating coordinates for gradient
interpolation, it was attempting to wrap both x and (x + 1)
simultaneously at the tile boundary (that is, either both or neither
are wrapped). This obviously won't work, since along the tile seams,
(x + 1) should be wrapped, but x should not. The same is true in y.
This patch fixes both the CPU and GPU paths, renames some variables to
more closely match the spec, and modifies the perlin noise GM to
actually test tiling. (Note that the clipping the GM was doing was
removed, since it's superfluous: it used to be necessary for image
filters, but isn't anymore, and this isn't an image filter GM anyway.)
R=sugoi@google.com, sugoi
TBR=senorblanco
Author: senorblanco@chromium.org
Review URL: https://codereview.chromium.org/332523006
2014-06-12 18:24:19 +00:00
|
|
|
xCoords.appendf("vec2(%s.x, 0.5)", floorVal);
|
2013-04-05 13:47:09 +00:00
|
|
|
|
2013-06-10 13:59:25 +00:00
|
|
|
noiseCode.appendf("\n\tvec2 %s;\n\t%s.x = ", latticeIdx, latticeIdx);
|
2014-08-22 03:18:45 +00:00
|
|
|
fsBuilder->appendTextureLookup(&noiseCode, samplers[0], xCoords.c_str(), kVec2f_GrSLType);
|
2013-06-10 13:59:25 +00:00
|
|
|
noiseCode.append(".r;");
|
2013-04-05 13:47:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Get permutation for x + 1
|
|
|
|
{
|
|
|
|
SkString xCoords("");
|
Fix tiled perlin noise.
It turns out that the perlin implementation we inherited from WebKit
does not actually generate tileable noise (see Chromium bug
http://crbug.com/383495).
The main problem is that when generating coordinates for gradient
interpolation, it was attempting to wrap both x and (x + 1)
simultaneously at the tile boundary (that is, either both or neither
are wrapped). This obviously won't work, since along the tile seams,
(x + 1) should be wrapped, but x should not. The same is true in y.
This patch fixes both the CPU and GPU paths, renames some variables to
more closely match the spec, and modifies the perlin noise GM to
actually test tiling. (Note that the clipping the GM was doing was
removed, since it's superfluous: it used to be necessary for image
filters, but isn't anymore, and this isn't an image filter GM anyway.)
R=sugoi@google.com, sugoi
TBR=senorblanco
Author: senorblanco@chromium.org
Review URL: https://codereview.chromium.org/332523006
2014-06-12 18:24:19 +00:00
|
|
|
xCoords.appendf("vec2(%s.z, 0.5)", floorVal);
|
2013-04-05 13:47:09 +00:00
|
|
|
|
2013-06-10 13:59:25 +00:00
|
|
|
noiseCode.appendf("\n\t%s.y = ", latticeIdx);
|
2014-08-22 03:18:45 +00:00
|
|
|
fsBuilder->appendTextureLookup(&noiseCode, samplers[0], xCoords.c_str(), kVec2f_GrSLType);
|
2013-06-10 13:59:25 +00:00
|
|
|
noiseCode.append(".r;");
|
2013-04-05 13:47:09 +00:00
|
|
|
}
|
|
|
|
|
*** Perlin noise GM needs to be rebaselined ***
Enabling Perlin Noise on Android
I enabled the Perlin Noise shader on Android after doing some minor modifications to the shader, specifically for Android (and #ifdefed for Android, to make sure none of this affects other platforms).
For Tegra devices (Nexus 7, Xoom), a precision issue related to the color values read from textures caused the noise to read the wrong indices and produce bad noise. I fixed this by adding a founding of the values read by simply doing the equivalent of "colorValue = floor(colorValue * 255.0) / 255.0" to make sure we retrieve the colors that were written in the texture originally.
For non-Tegra devices (Nexus 10), dealing with values in the order of 4096.0 was problematic without using the "highp" precision setting. To solve this, a few variables were given the high precision setting.
Since both fixes don't seem to do considerable harm to the platforms that are not being targetted, I left both fixes on all android devices for now.
I also reduced the Perlin noise gm so that it takes less time to test it on the Xoom (Original time was about 20 seconds, this shold take less than 10, hopefully)
BUG=
R=senorblanco@google.com, bsalomon@google.com, sugoi@google.com, senorblanco@chromium.org
Author: sugoi@chromium.org
Review URL: https://chromiumcodereview.appspot.com/16818013
git-svn-id: http://skia.googlecode.com/svn/trunk@9637 2bbb7eff-a529-9590-31e7-b0007b416f81
2013-06-17 14:19:01 +00:00
|
|
|
#if defined(SK_BUILD_FOR_ANDROID)
|
|
|
|
// Android rounding for Tegra devices, like, for example: Xoom (Tegra 2), Nexus 7 (Tegra 3).
|
|
|
|
// The issue is that colors aren't accurate enough on Tegra devices. For example, if an 8 bit
|
|
|
|
// value of 124 (or 0.486275 here) is entered, we can get a texture value of 123.513725
|
|
|
|
// (or 0.484368 here). The following rounding operation prevents these precision issues from
|
|
|
|
// affecting the result of the noise by making sure that we only have multiples of 1/255.
|
|
|
|
// (Note that 1/255 is about 0.003921569, which is the value used here).
|
|
|
|
noiseCode.appendf("\n\t%s = floor(%s * vec2(255.0) + vec2(0.5)) * vec2(0.003921569);",
|
|
|
|
latticeIdx, latticeIdx);
|
|
|
|
#endif
|
|
|
|
|
2013-04-05 13:47:09 +00:00
|
|
|
// Get (x,y) coordinates with the permutated x
|
Fix tiled perlin noise.
It turns out that the perlin implementation we inherited from WebKit
does not actually generate tileable noise (see Chromium bug
http://crbug.com/383495).
The main problem is that when generating coordinates for gradient
interpolation, it was attempting to wrap both x and (x + 1)
simultaneously at the tile boundary (that is, either both or neither
are wrapped). This obviously won't work, since along the tile seams,
(x + 1) should be wrapped, but x should not. The same is true in y.
This patch fixes both the CPU and GPU paths, renames some variables to
more closely match the spec, and modifies the perlin noise GM to
actually test tiling. (Note that the clipping the GM was doing was
removed, since it's superfluous: it used to be necessary for image
filters, but isn't anymore, and this isn't an image filter GM anyway.)
R=sugoi@google.com, sugoi
TBR=senorblanco
Author: senorblanco@chromium.org
Review URL: https://codereview.chromium.org/332523006
2014-06-12 18:24:19 +00:00
|
|
|
noiseCode.appendf("\n\tvec4 %s = fract(%s.xyxy + %s.yyww);", bcoords, latticeIdx, floorVal);
|
2013-04-05 13:47:09 +00:00
|
|
|
|
2013-06-10 13:59:25 +00:00
|
|
|
noiseCode.appendf("\n\n\tvec2 %s;", uv);
|
2013-04-05 13:47:09 +00:00
|
|
|
// Compute u, at offset (0,0)
|
|
|
|
{
|
|
|
|
SkString latticeCoords("");
|
Fix tiled perlin noise.
It turns out that the perlin implementation we inherited from WebKit
does not actually generate tileable noise (see Chromium bug
http://crbug.com/383495).
The main problem is that when generating coordinates for gradient
interpolation, it was attempting to wrap both x and (x + 1)
simultaneously at the tile boundary (that is, either both or neither
are wrapped). This obviously won't work, since along the tile seams,
(x + 1) should be wrapped, but x should not. The same is true in y.
This patch fixes both the CPU and GPU paths, renames some variables to
more closely match the spec, and modifies the perlin noise GM to
actually test tiling. (Note that the clipping the GM was doing was
removed, since it's superfluous: it used to be necessary for image
filters, but isn't anymore, and this isn't an image filter GM anyway.)
R=sugoi@google.com, sugoi
TBR=senorblanco
Author: senorblanco@chromium.org
Review URL: https://codereview.chromium.org/332523006
2014-06-12 18:24:19 +00:00
|
|
|
latticeCoords.appendf("vec2(%s.x, %s)", bcoords, chanCoord);
|
2013-06-10 13:59:25 +00:00
|
|
|
noiseCode.appendf("\n\tvec4 %s = ", lattice);
|
2014-08-22 03:18:45 +00:00
|
|
|
fsBuilder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(),
|
2013-06-10 13:59:25 +00:00
|
|
|
kVec2f_GrSLType);
|
|
|
|
noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
|
|
|
|
noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
|
2013-04-05 13:47:09 +00:00
|
|
|
}
|
|
|
|
|
2013-06-10 13:59:25 +00:00
|
|
|
noiseCode.appendf("\n\t%s.x -= 1.0;", fractVal);
|
2013-04-05 13:47:09 +00:00
|
|
|
// Compute v, at offset (-1,0)
|
|
|
|
{
|
|
|
|
SkString latticeCoords("");
|
Fix tiled perlin noise.
It turns out that the perlin implementation we inherited from WebKit
does not actually generate tileable noise (see Chromium bug
http://crbug.com/383495).
The main problem is that when generating coordinates for gradient
interpolation, it was attempting to wrap both x and (x + 1)
simultaneously at the tile boundary (that is, either both or neither
are wrapped). This obviously won't work, since along the tile seams,
(x + 1) should be wrapped, but x should not. The same is true in y.
This patch fixes both the CPU and GPU paths, renames some variables to
more closely match the spec, and modifies the perlin noise GM to
actually test tiling. (Note that the clipping the GM was doing was
removed, since it's superfluous: it used to be necessary for image
filters, but isn't anymore, and this isn't an image filter GM anyway.)
R=sugoi@google.com, sugoi
TBR=senorblanco
Author: senorblanco@chromium.org
Review URL: https://codereview.chromium.org/332523006
2014-06-12 18:24:19 +00:00
|
|
|
latticeCoords.appendf("vec2(%s.y, %s)", bcoords, chanCoord);
|
*** Perlin noise GM needs to be rebaselined ***
Enabling Perlin Noise on Android
I enabled the Perlin Noise shader on Android after doing some minor modifications to the shader, specifically for Android (and #ifdefed for Android, to make sure none of this affects other platforms).
For Tegra devices (Nexus 7, Xoom), a precision issue related to the color values read from textures caused the noise to read the wrong indices and produce bad noise. I fixed this by adding a founding of the values read by simply doing the equivalent of "colorValue = floor(colorValue * 255.0) / 255.0" to make sure we retrieve the colors that were written in the texture originally.
For non-Tegra devices (Nexus 10), dealing with values in the order of 4096.0 was problematic without using the "highp" precision setting. To solve this, a few variables were given the high precision setting.
Since both fixes don't seem to do considerable harm to the platforms that are not being targetted, I left both fixes on all android devices for now.
I also reduced the Perlin noise gm so that it takes less time to test it on the Xoom (Original time was about 20 seconds, this shold take less than 10, hopefully)
BUG=
R=senorblanco@google.com, bsalomon@google.com, sugoi@google.com, senorblanco@chromium.org
Author: sugoi@chromium.org
Review URL: https://chromiumcodereview.appspot.com/16818013
git-svn-id: http://skia.googlecode.com/svn/trunk@9637 2bbb7eff-a529-9590-31e7-b0007b416f81
2013-06-17 14:19:01 +00:00
|
|
|
noiseCode.append("\n\tlattice = ");
|
2014-08-22 03:18:45 +00:00
|
|
|
fsBuilder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(),
|
2013-06-10 13:59:25 +00:00
|
|
|
kVec2f_GrSLType);
|
|
|
|
noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
|
|
|
|
noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
|
2013-04-05 13:47:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Compute 'a' as a linear interpolation of 'u' and 'v'
|
2013-06-10 13:59:25 +00:00
|
|
|
noiseCode.appendf("\n\tvec2 %s;", ab);
|
|
|
|
noiseCode.appendf("\n\t%s.x = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
|
2013-04-05 13:47:09 +00:00
|
|
|
|
2013-06-10 13:59:25 +00:00
|
|
|
noiseCode.appendf("\n\t%s.y -= 1.0;", fractVal);
|
2013-04-05 13:47:09 +00:00
|
|
|
// Compute v, at offset (-1,-1)
|
|
|
|
{
|
|
|
|
SkString latticeCoords("");
|
Fix tiled perlin noise.
It turns out that the perlin implementation we inherited from WebKit
does not actually generate tileable noise (see Chromium bug
http://crbug.com/383495).
The main problem is that when generating coordinates for gradient
interpolation, it was attempting to wrap both x and (x + 1)
simultaneously at the tile boundary (that is, either both or neither
are wrapped). This obviously won't work, since along the tile seams,
(x + 1) should be wrapped, but x should not. The same is true in y.
This patch fixes both the CPU and GPU paths, renames some variables to
more closely match the spec, and modifies the perlin noise GM to
actually test tiling. (Note that the clipping the GM was doing was
removed, since it's superfluous: it used to be necessary for image
filters, but isn't anymore, and this isn't an image filter GM anyway.)
R=sugoi@google.com, sugoi
TBR=senorblanco
Author: senorblanco@chromium.org
Review URL: https://codereview.chromium.org/332523006
2014-06-12 18:24:19 +00:00
|
|
|
latticeCoords.appendf("vec2(%s.w, %s)", bcoords, chanCoord);
|
*** Perlin noise GM needs to be rebaselined ***
Enabling Perlin Noise on Android
I enabled the Perlin Noise shader on Android after doing some minor modifications to the shader, specifically for Android (and #ifdefed for Android, to make sure none of this affects other platforms).
For Tegra devices (Nexus 7, Xoom), a precision issue related to the color values read from textures caused the noise to read the wrong indices and produce bad noise. I fixed this by adding a founding of the values read by simply doing the equivalent of "colorValue = floor(colorValue * 255.0) / 255.0" to make sure we retrieve the colors that were written in the texture originally.
For non-Tegra devices (Nexus 10), dealing with values in the order of 4096.0 was problematic without using the "highp" precision setting. To solve this, a few variables were given the high precision setting.
Since both fixes don't seem to do considerable harm to the platforms that are not being targetted, I left both fixes on all android devices for now.
I also reduced the Perlin noise gm so that it takes less time to test it on the Xoom (Original time was about 20 seconds, this shold take less than 10, hopefully)
BUG=
R=senorblanco@google.com, bsalomon@google.com, sugoi@google.com, senorblanco@chromium.org
Author: sugoi@chromium.org
Review URL: https://chromiumcodereview.appspot.com/16818013
git-svn-id: http://skia.googlecode.com/svn/trunk@9637 2bbb7eff-a529-9590-31e7-b0007b416f81
2013-06-17 14:19:01 +00:00
|
|
|
noiseCode.append("\n\tlattice = ");
|
2014-08-22 03:18:45 +00:00
|
|
|
fsBuilder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(),
|
2013-06-10 13:59:25 +00:00
|
|
|
kVec2f_GrSLType);
|
|
|
|
noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
|
|
|
|
noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
|
2013-04-05 13:47:09 +00:00
|
|
|
}
|
|
|
|
|
2013-06-10 13:59:25 +00:00
|
|
|
noiseCode.appendf("\n\t%s.x += 1.0;", fractVal);
|
2013-04-05 13:47:09 +00:00
|
|
|
// Compute u, at offset (0,-1)
|
|
|
|
{
|
|
|
|
SkString latticeCoords("");
|
Fix tiled perlin noise.
It turns out that the perlin implementation we inherited from WebKit
does not actually generate tileable noise (see Chromium bug
http://crbug.com/383495).
The main problem is that when generating coordinates for gradient
interpolation, it was attempting to wrap both x and (x + 1)
simultaneously at the tile boundary (that is, either both or neither
are wrapped). This obviously won't work, since along the tile seams,
(x + 1) should be wrapped, but x should not. The same is true in y.
This patch fixes both the CPU and GPU paths, renames some variables to
more closely match the spec, and modifies the perlin noise GM to
actually test tiling. (Note that the clipping the GM was doing was
removed, since it's superfluous: it used to be necessary for image
filters, but isn't anymore, and this isn't an image filter GM anyway.)
R=sugoi@google.com, sugoi
TBR=senorblanco
Author: senorblanco@chromium.org
Review URL: https://codereview.chromium.org/332523006
2014-06-12 18:24:19 +00:00
|
|
|
latticeCoords.appendf("vec2(%s.z, %s)", bcoords, chanCoord);
|
*** Perlin noise GM needs to be rebaselined ***
Enabling Perlin Noise on Android
I enabled the Perlin Noise shader on Android after doing some minor modifications to the shader, specifically for Android (and #ifdefed for Android, to make sure none of this affects other platforms).
For Tegra devices (Nexus 7, Xoom), a precision issue related to the color values read from textures caused the noise to read the wrong indices and produce bad noise. I fixed this by adding a founding of the values read by simply doing the equivalent of "colorValue = floor(colorValue * 255.0) / 255.0" to make sure we retrieve the colors that were written in the texture originally.
For non-Tegra devices (Nexus 10), dealing with values in the order of 4096.0 was problematic without using the "highp" precision setting. To solve this, a few variables were given the high precision setting.
Since both fixes don't seem to do considerable harm to the platforms that are not being targetted, I left both fixes on all android devices for now.
I also reduced the Perlin noise gm so that it takes less time to test it on the Xoom (Original time was about 20 seconds, this shold take less than 10, hopefully)
BUG=
R=senorblanco@google.com, bsalomon@google.com, sugoi@google.com, senorblanco@chromium.org
Author: sugoi@chromium.org
Review URL: https://chromiumcodereview.appspot.com/16818013
git-svn-id: http://skia.googlecode.com/svn/trunk@9637 2bbb7eff-a529-9590-31e7-b0007b416f81
2013-06-17 14:19:01 +00:00
|
|
|
noiseCode.append("\n\tlattice = ");
|
2014-08-22 03:18:45 +00:00
|
|
|
fsBuilder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(),
|
2013-06-10 13:59:25 +00:00
|
|
|
kVec2f_GrSLType);
|
|
|
|
noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
|
|
|
|
noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
|
2013-04-05 13:47:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Compute 'b' as a linear interpolation of 'u' and 'v'
|
2013-06-10 13:59:25 +00:00
|
|
|
noiseCode.appendf("\n\t%s.y = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
|
2013-04-05 13:47:09 +00:00
|
|
|
// Compute the noise as a linear interpolation of 'a' and 'b'
|
2013-06-10 13:59:25 +00:00
|
|
|
noiseCode.appendf("\n\treturn mix(%s.x, %s.y, %s.y);\n", ab, ab, noiseSmooth);
|
|
|
|
|
|
|
|
SkString noiseFuncName;
|
|
|
|
if (fStitchTiles) {
|
2014-08-22 03:18:45 +00:00
|
|
|
fsBuilder->emitFunction(kFloat_GrSLType,
|
2013-08-30 19:43:59 +00:00
|
|
|
"perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseStitchArgs),
|
|
|
|
gPerlinNoiseStitchArgs, noiseCode.c_str(), &noiseFuncName);
|
2013-06-10 13:59:25 +00:00
|
|
|
} else {
|
2014-08-22 03:18:45 +00:00
|
|
|
fsBuilder->emitFunction(kFloat_GrSLType,
|
2013-08-30 19:43:59 +00:00
|
|
|
"perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseArgs),
|
|
|
|
gPerlinNoiseArgs, noiseCode.c_str(), &noiseFuncName);
|
2013-06-10 13:59:25 +00:00
|
|
|
}
|
2013-04-05 13:47:09 +00:00
|
|
|
|
2013-06-10 13:59:25 +00:00
|
|
|
// There are rounding errors if the floor operation is not performed here
|
2014-08-22 03:18:45 +00:00
|
|
|
fsBuilder->codeAppendf("\n\t\tvec2 %s = floor(%s.xy) * %s;",
|
2014-06-27 20:35:52 +00:00
|
|
|
noiseVec, vCoords.c_str(), baseFrequencyUni);
|
2013-04-05 13:47:09 +00:00
|
|
|
|
2013-06-10 13:59:25 +00:00
|
|
|
// Clear the color accumulator
|
2014-08-22 03:18:45 +00:00
|
|
|
fsBuilder->codeAppendf("\n\t\t%s = vec4(0.0);", outputColor);
|
2013-04-05 13:47:09 +00:00
|
|
|
|
|
|
|
if (fStitchTiles) {
|
2013-06-10 13:59:25 +00:00
|
|
|
// Set up TurbulenceInitial stitch values.
|
2014-08-22 03:18:45 +00:00
|
|
|
fsBuilder->codeAppendf("\n\t\tvec2 %s = %s;", stitchData, stitchDataUni);
|
2013-04-05 13:47:09 +00:00
|
|
|
}
|
|
|
|
|
2014-08-22 03:18:45 +00:00
|
|
|
fsBuilder->codeAppendf("\n\t\tfloat %s = 1.0;", ratio);
|
2013-06-10 13:59:25 +00:00
|
|
|
|
|
|
|
// Loop over all octaves
|
2014-08-22 03:18:45 +00:00
|
|
|
fsBuilder->codeAppendf("\n\t\tfor (int octave = 0; octave < %d; ++octave) {", fNumOctaves);
|
2013-06-10 13:59:25 +00:00
|
|
|
|
2014-08-22 03:18:45 +00:00
|
|
|
fsBuilder->codeAppendf("\n\t\t\t%s += ", outputColor);
|
2013-06-10 13:59:25 +00:00
|
|
|
if (fType != SkPerlinNoiseShader::kFractalNoise_Type) {
|
2014-08-22 03:18:45 +00:00
|
|
|
fsBuilder->codeAppend("abs(");
|
2013-06-10 13:59:25 +00:00
|
|
|
}
|
|
|
|
if (fStitchTiles) {
|
2014-08-22 03:18:45 +00:00
|
|
|
fsBuilder->codeAppendf(
|
2013-06-10 13:59:25 +00:00
|
|
|
"vec4(\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s),"
|
|
|
|
"\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s))",
|
|
|
|
noiseFuncName.c_str(), chanCoordR, noiseVec, stitchData,
|
|
|
|
noiseFuncName.c_str(), chanCoordG, noiseVec, stitchData,
|
|
|
|
noiseFuncName.c_str(), chanCoordB, noiseVec, stitchData,
|
|
|
|
noiseFuncName.c_str(), chanCoordA, noiseVec, stitchData);
|
|
|
|
} else {
|
2014-08-22 03:18:45 +00:00
|
|
|
fsBuilder->codeAppendf(
|
2013-06-10 13:59:25 +00:00
|
|
|
"vec4(\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s),"
|
|
|
|
"\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s))",
|
|
|
|
noiseFuncName.c_str(), chanCoordR, noiseVec,
|
|
|
|
noiseFuncName.c_str(), chanCoordG, noiseVec,
|
|
|
|
noiseFuncName.c_str(), chanCoordB, noiseVec,
|
|
|
|
noiseFuncName.c_str(), chanCoordA, noiseVec);
|
|
|
|
}
|
|
|
|
if (fType != SkPerlinNoiseShader::kFractalNoise_Type) {
|
2014-08-22 03:18:45 +00:00
|
|
|
fsBuilder->codeAppendf(")"); // end of "abs("
|
2013-06-10 13:59:25 +00:00
|
|
|
}
|
2014-08-22 03:18:45 +00:00
|
|
|
fsBuilder->codeAppendf(" * %s;", ratio);
|
2013-06-10 13:59:25 +00:00
|
|
|
|
2014-08-22 03:18:45 +00:00
|
|
|
fsBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", noiseVec);
|
|
|
|
fsBuilder->codeAppendf("\n\t\t\t%s *= 0.5;", ratio);
|
2013-06-10 13:59:25 +00:00
|
|
|
|
|
|
|
if (fStitchTiles) {
|
2014-08-22 03:18:45 +00:00
|
|
|
fsBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", stitchData);
|
2013-06-10 13:59:25 +00:00
|
|
|
}
|
2014-08-22 03:18:45 +00:00
|
|
|
fsBuilder->codeAppend("\n\t\t}"); // end of the for loop on octaves
|
2013-04-05 13:47:09 +00:00
|
|
|
|
|
|
|
if (fType == SkPerlinNoiseShader::kFractalNoise_Type) {
|
|
|
|
// The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
|
|
|
|
// by fractalNoise and (turbulenceFunctionResult) by turbulence.
|
2014-08-22 03:18:45 +00:00
|
|
|
fsBuilder->codeAppendf("\n\t\t%s = %s * vec4(0.5) + vec4(0.5);", outputColor, outputColor);
|
2013-04-05 13:47:09 +00:00
|
|
|
}
|
|
|
|
|
2014-08-22 03:18:45 +00:00
|
|
|
fsBuilder->codeAppendf("\n\t\t%s.a *= %s;", outputColor, alphaUni);
|
2013-04-05 13:47:09 +00:00
|
|
|
|
|
|
|
// Clamp values
|
2014-08-22 03:18:45 +00:00
|
|
|
fsBuilder->codeAppendf("\n\t\t%s = clamp(%s, 0.0, 1.0);", outputColor, outputColor);
|
2013-04-05 13:47:09 +00:00
|
|
|
|
|
|
|
// Pre-multiply the result
|
2014-08-22 03:18:45 +00:00
|
|
|
fsBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n",
|
2013-04-05 13:47:09 +00:00
|
|
|
outputColor, outputColor, outputColor, outputColor);
|
|
|
|
}
|
|
|
|
|
2014-09-23 16:50:21 +00:00
|
|
|
void GrGLPerlinNoise::GenKey(const GrProcessor& processor, const GrGLCaps&,
|
|
|
|
GrProcessorKeyBuilder* b) {
|
|
|
|
const GrPerlinNoiseEffect& turbulence = processor.cast<GrPerlinNoiseEffect>();
|
2013-04-05 13:47:09 +00:00
|
|
|
|
2014-07-21 15:03:14 +00:00
|
|
|
uint32_t key = turbulence.numOctaves();
|
2013-04-05 13:47:09 +00:00
|
|
|
|
|
|
|
key = key << 3; // Make room for next 3 bits
|
|
|
|
|
|
|
|
switch (turbulence.type()) {
|
|
|
|
case SkPerlinNoiseShader::kFractalNoise_Type:
|
|
|
|
key |= 0x1;
|
|
|
|
break;
|
|
|
|
case SkPerlinNoiseShader::kTurbulence_Type:
|
|
|
|
key |= 0x2;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
// leave key at 0
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (turbulence.stitchTiles()) {
|
|
|
|
key |= 0x4; // Flip the 3rd bit if tile stitching is on
|
|
|
|
}
|
|
|
|
|
2014-07-21 15:03:14 +00:00
|
|
|
b->add32(key);
|
2013-04-05 13:47:09 +00:00
|
|
|
}
|
|
|
|
|
2014-09-23 16:50:21 +00:00
|
|
|
void GrGLPerlinNoise::setData(const GrGLProgramDataManager& pdman, const GrProcessor& processor) {
|
|
|
|
INHERITED::setData(pdman, processor);
|
2014-06-16 17:49:58 +00:00
|
|
|
|
2014-09-23 16:50:21 +00:00
|
|
|
const GrPerlinNoiseEffect& turbulence = processor.cast<GrPerlinNoiseEffect>();
|
2013-04-05 13:47:09 +00:00
|
|
|
|
|
|
|
const SkVector& baseFrequency = turbulence.baseFrequency();
|
2014-07-30 07:04:16 +00:00
|
|
|
pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY);
|
|
|
|
pdman.set1f(fAlphaUni, SkScalarDiv(SkIntToScalar(turbulence.alpha()), SkIntToScalar(255)));
|
2013-04-05 13:47:09 +00:00
|
|
|
|
2013-04-17 13:46:56 +00:00
|
|
|
if (turbulence.stitchTiles()) {
|
|
|
|
const SkPerlinNoiseShader::StitchData& stitchData = turbulence.stitchData();
|
2014-07-30 07:04:16 +00:00
|
|
|
pdman.set2f(fStitchDataUni, SkIntToScalar(stitchData.fWidth),
|
2013-07-04 18:13:05 +00:00
|
|
|
SkIntToScalar(stitchData.fHeight));
|
2013-04-17 13:46:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-05 13:47:09 +00:00
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
|
2014-09-23 16:50:21 +00:00
|
|
|
bool SkPerlinNoiseShader::asFragmentProcessor(GrContext* context, const SkPaint& paint,
|
|
|
|
const SkMatrix* externalLocalMatrix,
|
|
|
|
GrColor* paintColor, GrFragmentProcessor** fp) const {
|
2014-09-05 20:34:00 +00:00
|
|
|
SkASSERT(context);
|
2014-06-10 21:38:28 +00:00
|
|
|
|
2014-07-08 16:56:10 +00:00
|
|
|
*paintColor = SkColor2GrColorJustAlpha(paint.getColor());
|
2014-06-27 20:35:52 +00:00
|
|
|
|
2014-05-09 20:28:11 +00:00
|
|
|
SkMatrix localMatrix = this->getLocalMatrix();
|
|
|
|
if (externalLocalMatrix) {
|
|
|
|
localMatrix.preConcat(*externalLocalMatrix);
|
|
|
|
}
|
|
|
|
|
2014-06-27 20:35:52 +00:00
|
|
|
SkMatrix matrix = context->getMatrix();
|
|
|
|
matrix.preConcat(localMatrix);
|
|
|
|
|
2013-11-06 10:08:38 +00:00
|
|
|
if (0 == fNumOctaves) {
|
|
|
|
SkColor clearColor = 0;
|
|
|
|
if (kFractalNoise_Type == fType) {
|
|
|
|
clearColor = SkColorSetARGB(paint.getAlpha() / 2, 127, 127, 127);
|
|
|
|
}
|
|
|
|
SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(
|
|
|
|
clearColor, SkXfermode::kSrc_Mode));
|
2014-09-23 16:50:21 +00:00
|
|
|
*fp = cf->asFragmentProcessor(context);
|
2014-06-10 21:38:28 +00:00
|
|
|
return true;
|
2013-11-06 10:08:38 +00:00
|
|
|
}
|
|
|
|
|
2013-04-05 13:47:09 +00:00
|
|
|
// Either we don't stitch tiles, either we have a valid tile size
|
|
|
|
SkASSERT(!fStitchTiles || !fTileSize.isEmpty());
|
|
|
|
|
2014-09-23 16:50:21 +00:00
|
|
|
SkPerlinNoiseShader::PaintingData* paintingData =
|
|
|
|
SkNEW_ARGS(PaintingData, (fTileSize, fSeed, fBaseFrequencyX, fBaseFrequencyY, matrix));
|
2014-10-08 15:40:09 +00:00
|
|
|
SkAutoTUnref<GrTexture> permutationsTexture(
|
|
|
|
GrRefCachedBitmapTexture(context, paintingData->getPermutationsBitmap(), NULL));
|
|
|
|
SkAutoTUnref<GrTexture> noiseTexture(
|
|
|
|
GrRefCachedBitmapTexture(context, paintingData->getNoiseBitmap(), NULL));
|
2014-06-27 20:35:52 +00:00
|
|
|
|
|
|
|
SkMatrix m = context->getMatrix();
|
|
|
|
m.setTranslateX(-localMatrix.getTranslateX() + SK_Scalar1);
|
|
|
|
m.setTranslateY(-localMatrix.getTranslateY() + SK_Scalar1);
|
2014-09-05 20:34:00 +00:00
|
|
|
if ((permutationsTexture) && (noiseTexture)) {
|
2014-09-23 16:50:21 +00:00
|
|
|
*fp = GrPerlinNoiseEffect::Create(fType,
|
|
|
|
fNumOctaves,
|
|
|
|
fStitchTiles,
|
|
|
|
paintingData,
|
|
|
|
permutationsTexture, noiseTexture,
|
|
|
|
m, paint.getAlpha());
|
2014-06-27 20:35:52 +00:00
|
|
|
} else {
|
|
|
|
SkDELETE(paintingData);
|
2014-09-23 16:50:21 +00:00
|
|
|
*fp = NULL;
|
2014-06-27 20:35:52 +00:00
|
|
|
}
|
2014-06-10 21:38:28 +00:00
|
|
|
return true;
|
2013-04-05 13:47:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
2014-09-23 16:50:21 +00:00
|
|
|
bool SkPerlinNoiseShader::asFragmentProcessor(GrContext*, const SkPaint&, const SkMatrix*, GrColor*,
|
|
|
|
GrFragmentProcessor**) const {
|
2013-04-05 13:47:09 +00:00
|
|
|
SkDEBUGFAIL("Should not call in GPU-less build");
|
2014-06-10 21:38:28 +00:00
|
|
|
return false;
|
2013-04-05 13:47:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2014-03-13 18:02:17 +00:00
|
|
|
#ifndef SK_IGNORE_TO_STRING
|
2013-04-05 13:47:09 +00:00
|
|
|
void SkPerlinNoiseShader::toString(SkString* str) const {
|
|
|
|
str->append("SkPerlinNoiseShader: (");
|
|
|
|
|
|
|
|
str->append("type: ");
|
|
|
|
switch (fType) {
|
|
|
|
case kFractalNoise_Type:
|
|
|
|
str->append("\"fractal noise\"");
|
|
|
|
break;
|
|
|
|
case kTurbulence_Type:
|
|
|
|
str->append("\"turbulence\"");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
str->append("\"unknown\"");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
str->append(" base frequency: (");
|
|
|
|
str->appendScalar(fBaseFrequencyX);
|
|
|
|
str->append(", ");
|
|
|
|
str->appendScalar(fBaseFrequencyY);
|
|
|
|
str->append(") number of octaves: ");
|
|
|
|
str->appendS32(fNumOctaves);
|
|
|
|
str->append(" seed: ");
|
|
|
|
str->appendScalar(fSeed);
|
|
|
|
str->append(" stitch tiles: ");
|
|
|
|
str->append(fStitchTiles ? "true " : "false ");
|
|
|
|
|
|
|
|
this->INHERITED::toString(str);
|
|
|
|
|
|
|
|
str->append(")");
|
|
|
|
}
|
|
|
|
#endif
|