OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkPerlinNoiseShader.h" | 8 #include "SkPerlinNoiseShader.h" |
9 #include "SkColorFilter.h" | 9 #include "SkColorFilter.h" |
10 #include "SkReadBuffer.h" | 10 #include "SkReadBuffer.h" |
(...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
465 point.fX += SK_Scalar1; | 465 point.fX += SK_Scalar1; |
466 } | 466 } |
467 } | 467 } |
468 | 468 |
469 ///////////////////////////////////////////////////////////////////// | 469 ///////////////////////////////////////////////////////////////////// |
470 | 470 |
471 #if SK_SUPPORT_GPU | 471 #if SK_SUPPORT_GPU |
472 | 472 |
473 class GrGLPerlinNoise : public GrGLSLFragmentProcessor { | 473 class GrGLPerlinNoise : public GrGLSLFragmentProcessor { |
474 public: | 474 public: |
475 GrGLPerlinNoise(const GrProcessor&); | |
476 | |
477 void emitCode(EmitArgs&) override; | 475 void emitCode(EmitArgs&) override; |
478 | 476 |
479 static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessor
KeyBuilder* b); | 477 static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessor
KeyBuilder*); |
480 | 478 |
481 protected: | 479 protected: |
482 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override
; | 480 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override
; |
483 | 481 |
484 private: | 482 private: |
485 | |
486 GrGLSLProgramDataManager::UniformHandle fStitchDataUni; | 483 GrGLSLProgramDataManager::UniformHandle fStitchDataUni; |
487 SkPerlinNoiseShader::Type fType; | |
488 bool fStitchTiles; | |
489 int fNumOctaves; | |
490 GrGLSLProgramDataManager::UniformHandle fBaseFrequencyUni; | 484 GrGLSLProgramDataManager::UniformHandle fBaseFrequencyUni; |
491 | 485 |
492 typedef GrGLSLFragmentProcessor INHERITED; | 486 typedef GrGLSLFragmentProcessor INHERITED; |
493 }; | 487 }; |
494 | 488 |
495 ///////////////////////////////////////////////////////////////////// | 489 ///////////////////////////////////////////////////////////////////// |
496 | 490 |
497 class GrPerlinNoiseEffect : public GrFragmentProcessor { | 491 class GrPerlinNoiseEffect : public GrFragmentProcessor { |
498 public: | 492 public: |
499 static GrFragmentProcessor* Create(SkPerlinNoiseShader::Type type, | 493 static GrFragmentProcessor* Create(SkPerlinNoiseShader::Type type, |
(...skipping 12 matching lines...) Expand all Loading... |
512 const SkPerlinNoiseShader::StitchData& stitchData() const { return fPainting
Data->fStitchDataInit; } | 506 const SkPerlinNoiseShader::StitchData& stitchData() const { return fPainting
Data->fStitchDataInit; } |
513 | 507 |
514 SkPerlinNoiseShader::Type type() const { return fType; } | 508 SkPerlinNoiseShader::Type type() const { return fType; } |
515 bool stitchTiles() const { return fStitchTiles; } | 509 bool stitchTiles() const { return fStitchTiles; } |
516 const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency
; } | 510 const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency
; } |
517 int numOctaves() const { return fNumOctaves; } | 511 int numOctaves() const { return fNumOctaves; } |
518 const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); } | 512 const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); } |
519 | 513 |
520 private: | 514 private: |
521 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { | 515 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { |
522 return new GrGLPerlinNoise(*this); | 516 return new GrGLPerlinNoise; |
523 } | 517 } |
524 | 518 |
525 virtual void onGetGLSLProcessorKey(const GrGLSLCaps& caps, | 519 virtual void onGetGLSLProcessorKey(const GrGLSLCaps& caps, |
526 GrProcessorKeyBuilder* b) const override
{ | 520 GrProcessorKeyBuilder* b) const override
{ |
527 GrGLPerlinNoise::GenKey(*this, caps, b); | 521 GrGLPerlinNoise::GenKey(*this, caps, b); |
528 } | 522 } |
529 | 523 |
530 bool onIsEqual(const GrFragmentProcessor& sBase) const override { | 524 bool onIsEqual(const GrFragmentProcessor& sBase) const override { |
531 const GrPerlinNoiseEffect& s = sBase.cast<GrPerlinNoiseEffect>(); | 525 const GrPerlinNoiseEffect& s = sBase.cast<GrPerlinNoiseEffect>(); |
532 return fType == s.fType && | 526 return fType == s.fType && |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
590 SkPerlinNoiseShader::CreateFractalNoise(baseFrequencyX, baseFrequencyY,
numOctaves, seed, | 584 SkPerlinNoiseShader::CreateFractalNoise(baseFrequencyX, baseFrequencyY,
numOctaves, seed, |
591 stitchTiles ? &tileSize : nullpt
r) : | 585 stitchTiles ? &tileSize : nullpt
r) : |
592 SkPerlinNoiseShader::CreateTurbulence(baseFrequencyX, baseFrequencyY, nu
mOctaves, seed, | 586 SkPerlinNoiseShader::CreateTurbulence(baseFrequencyX, baseFrequencyY, nu
mOctaves, seed, |
593 stitchTiles ? &tileSize : nullptr))
; | 587 stitchTiles ? &tileSize : nullptr))
; |
594 | 588 |
595 return shader->asFragmentProcessor(d->fContext, | 589 return shader->asFragmentProcessor(d->fContext, |
596 GrTest::TestMatrix(d->fRandom), nullptr, | 590 GrTest::TestMatrix(d->fRandom), nullptr, |
597 kNone_SkFilterQuality); | 591 kNone_SkFilterQuality); |
598 } | 592 } |
599 | 593 |
600 GrGLPerlinNoise::GrGLPerlinNoise(const GrProcessor& processor) | 594 void GrGLPerlinNoise::emitCode(EmitArgs& args) { |
601 : fType(processor.cast<GrPerlinNoiseEffect>().type()) | 595 const GrPerlinNoiseEffect& pne = args.fFp.cast<GrPerlinNoiseEffect>(); |
602 , fStitchTiles(processor.cast<GrPerlinNoiseEffect>().stitchTiles()) | |
603 , fNumOctaves(processor.cast<GrPerlinNoiseEffect>().numOctaves()) { | |
604 } | |
605 | 596 |
606 void GrGLPerlinNoise::emitCode(EmitArgs& args) { | |
607 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder; | 597 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder; |
608 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; | 598 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; |
609 SkString vCoords = fragBuilder->ensureFSCoords2D(args.fCoords, 0); | 599 SkString vCoords = fragBuilder->ensureFSCoords2D(args.fCoords, 0); |
610 | 600 |
611 fBaseFrequencyUni = uniformHandler->addUniform(GrGLSLUniformHandler::kFragme
nt_Visibility, | 601 fBaseFrequencyUni = uniformHandler->addUniform(GrGLSLUniformHandler::kFragme
nt_Visibility, |
612 kVec2f_GrSLType, kDefault_GrS
LPrecision, | 602 kVec2f_GrSLType, kDefault_GrS
LPrecision, |
613 "baseFrequency"); | 603 "baseFrequency"); |
614 const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequency
Uni); | 604 const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequency
Uni); |
615 | 605 |
616 const char* stitchDataUni = nullptr; | 606 const char* stitchDataUni = nullptr; |
617 if (fStitchTiles) { | 607 if (pne.stitchTiles()) { |
618 fStitchDataUni = uniformHandler->addUniform(GrGLSLUniformHandler::kFragm
ent_Visibility, | 608 fStitchDataUni = uniformHandler->addUniform(GrGLSLUniformHandler::kFragm
ent_Visibility, |
619 kVec2f_GrSLType, kDefault_Gr
SLPrecision, | 609 kVec2f_GrSLType, kDefault_Gr
SLPrecision, |
620 "stitchData"); | 610 "stitchData"); |
621 stitchDataUni = uniformHandler->getUniformCStr(fStitchDataUni); | 611 stitchDataUni = uniformHandler->getUniformCStr(fStitchDataUni); |
622 } | 612 } |
623 | 613 |
624 // There are 4 lines, so the center of each line is 1/8, 3/8, 5/8 and 7/8 | 614 // There are 4 lines, so the center of each line is 1/8, 3/8, 5/8 and 7/8 |
625 const char* chanCoordR = "0.125"; | 615 const char* chanCoordR = "0.125"; |
626 const char* chanCoordG = "0.375"; | 616 const char* chanCoordG = "0.375"; |
627 const char* chanCoordB = "0.625"; | 617 const char* chanCoordB = "0.625"; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
660 noiseCode.appendf("\tvec4 %s;\n", floorVal); | 650 noiseCode.appendf("\tvec4 %s;\n", floorVal); |
661 noiseCode.appendf("\t%s.xy = floor(%s);\n", floorVal, noiseVec); | 651 noiseCode.appendf("\t%s.xy = floor(%s);\n", floorVal, noiseVec); |
662 noiseCode.appendf("\t%s.zw = %s.xy + vec2(1.0);\n", floorVal, floorVal); | 652 noiseCode.appendf("\t%s.zw = %s.xy + vec2(1.0);\n", floorVal, floorVal); |
663 noiseCode.appendf("\tvec2 %s = fract(%s);\n", fractVal, noiseVec); | 653 noiseCode.appendf("\tvec2 %s = fract(%s);\n", fractVal, noiseVec); |
664 | 654 |
665 // smooth curve : t * t * (3 - 2 * t) | 655 // smooth curve : t * t * (3 - 2 * t) |
666 noiseCode.appendf("\n\tvec2 %s = %s * %s * (vec2(3.0) - vec2(2.0) * %s);", | 656 noiseCode.appendf("\n\tvec2 %s = %s * %s * (vec2(3.0) - vec2(2.0) * %s);", |
667 noiseSmooth, fractVal, fractVal, fractVal); | 657 noiseSmooth, fractVal, fractVal, fractVal); |
668 | 658 |
669 // Adjust frequencies if we're stitching tiles | 659 // Adjust frequencies if we're stitching tiles |
670 if (fStitchTiles) { | 660 if (pne.stitchTiles()) { |
671 noiseCode.appendf("\n\tif(%s.x >= %s.x) { %s.x -= %s.x; }", | 661 noiseCode.appendf("\n\tif(%s.x >= %s.x) { %s.x -= %s.x; }", |
672 floorVal, stitchData, floorVal, stitchData); | 662 floorVal, stitchData, floorVal, stitchData); |
673 noiseCode.appendf("\n\tif(%s.y >= %s.y) { %s.y -= %s.y; }", | 663 noiseCode.appendf("\n\tif(%s.y >= %s.y) { %s.y -= %s.y; }", |
674 floorVal, stitchData, floorVal, stitchData); | 664 floorVal, stitchData, floorVal, stitchData); |
675 noiseCode.appendf("\n\tif(%s.z >= %s.x) { %s.z -= %s.x; }", | 665 noiseCode.appendf("\n\tif(%s.z >= %s.x) { %s.z -= %s.x; }", |
676 floorVal, stitchData, floorVal, stitchData); | 666 floorVal, stitchData, floorVal, stitchData); |
677 noiseCode.appendf("\n\tif(%s.w >= %s.y) { %s.w -= %s.y; }", | 667 noiseCode.appendf("\n\tif(%s.w >= %s.y) { %s.w -= %s.y; }", |
678 floorVal, stitchData, floorVal, stitchData); | 668 floorVal, stitchData, floorVal, stitchData); |
679 } | 669 } |
680 | 670 |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
769 noiseCode.appendf(".bgra;\n\t%s.x = ", uv); | 759 noiseCode.appendf(".bgra;\n\t%s.x = ", uv); |
770 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal); | 760 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal); |
771 } | 761 } |
772 | 762 |
773 // Compute 'b' as a linear interpolation of 'u' and 'v' | 763 // Compute 'b' as a linear interpolation of 'u' and 'v' |
774 noiseCode.appendf("\n\t%s.y = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmoo
th); | 764 noiseCode.appendf("\n\t%s.y = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmoo
th); |
775 // Compute the noise as a linear interpolation of 'a' and 'b' | 765 // Compute the noise as a linear interpolation of 'a' and 'b' |
776 noiseCode.appendf("\n\treturn mix(%s.x, %s.y, %s.y);\n", ab, ab, noiseSmooth
); | 766 noiseCode.appendf("\n\treturn mix(%s.x, %s.y, %s.y);\n", ab, ab, noiseSmooth
); |
777 | 767 |
778 SkString noiseFuncName; | 768 SkString noiseFuncName; |
779 if (fStitchTiles) { | 769 if (pne.stitchTiles()) { |
780 fragBuilder->emitFunction(kFloat_GrSLType, | 770 fragBuilder->emitFunction(kFloat_GrSLType, |
781 "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseStit
chArgs), | 771 "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseStit
chArgs), |
782 gPerlinNoiseStitchArgs, noiseCode.c_str(), &no
iseFuncName); | 772 gPerlinNoiseStitchArgs, noiseCode.c_str(), &no
iseFuncName); |
783 } else { | 773 } else { |
784 fragBuilder->emitFunction(kFloat_GrSLType, | 774 fragBuilder->emitFunction(kFloat_GrSLType, |
785 "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseArgs
), | 775 "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseArgs
), |
786 gPerlinNoiseArgs, noiseCode.c_str(), &noiseFun
cName); | 776 gPerlinNoiseArgs, noiseCode.c_str(), &noiseFun
cName); |
787 } | 777 } |
788 | 778 |
789 // There are rounding errors if the floor operation is not performed here | 779 // There are rounding errors if the floor operation is not performed here |
790 fragBuilder->codeAppendf("\n\t\tvec2 %s = floor(%s.xy) * %s;", | 780 fragBuilder->codeAppendf("\n\t\tvec2 %s = floor(%s.xy) * %s;", |
791 noiseVec, vCoords.c_str(), baseFrequencyUni); | 781 noiseVec, vCoords.c_str(), baseFrequencyUni); |
792 | 782 |
793 // Clear the color accumulator | 783 // Clear the color accumulator |
794 fragBuilder->codeAppendf("\n\t\t%s = vec4(0.0);", args.fOutputColor); | 784 fragBuilder->codeAppendf("\n\t\t%s = vec4(0.0);", args.fOutputColor); |
795 | 785 |
796 if (fStitchTiles) { | 786 if (pne.stitchTiles()) { |
797 // Set up TurbulenceInitial stitch values. | 787 // Set up TurbulenceInitial stitch values. |
798 fragBuilder->codeAppendf("\n\t\tvec2 %s = %s;", stitchData, stitchDataUn
i); | 788 fragBuilder->codeAppendf("vec2 %s = %s;", stitchData, stitchDataUni); |
799 } | 789 } |
800 | 790 |
801 fragBuilder->codeAppendf("\n\t\tfloat %s = 1.0;", ratio); | 791 fragBuilder->codeAppendf("float %s = 1.0;", ratio); |
802 | 792 |
803 // Loop over all octaves | 793 // Loop over all octaves |
804 fragBuilder->codeAppendf("\n\t\tfor (int octave = 0; octave < %d; ++octave)
{", fNumOctaves); | 794 fragBuilder->codeAppendf("for (int octave = 0; octave < %d; ++octave) {", pn
e.numOctaves()); |
805 | 795 |
806 fragBuilder->codeAppendf("\n\t\t\t%s += ", args.fOutputColor); | 796 fragBuilder->codeAppendf("%s += ", args.fOutputColor); |
807 if (fType != SkPerlinNoiseShader::kFractalNoise_Type) { | 797 if (pne.type() != SkPerlinNoiseShader::kFractalNoise_Type) { |
808 fragBuilder->codeAppend("abs("); | 798 fragBuilder->codeAppend("abs("); |
809 } | 799 } |
810 if (fStitchTiles) { | 800 if (pne.stitchTiles()) { |
811 fragBuilder->codeAppendf( | 801 fragBuilder->codeAppendf( |
812 "vec4(\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s)," | 802 "vec4(\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s)," |
813 "\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s))", | 803 "\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s))", |
814 noiseFuncName.c_str(), chanCoordR, noiseVec, stitchData, | 804 noiseFuncName.c_str(), chanCoordR, noiseVec, stitchData, |
815 noiseFuncName.c_str(), chanCoordG, noiseVec, stitchData, | 805 noiseFuncName.c_str(), chanCoordG, noiseVec, stitchData, |
816 noiseFuncName.c_str(), chanCoordB, noiseVec, stitchData, | 806 noiseFuncName.c_str(), chanCoordB, noiseVec, stitchData, |
817 noiseFuncName.c_str(), chanCoordA, noiseVec, stitchData); | 807 noiseFuncName.c_str(), chanCoordA, noiseVec, stitchData); |
818 } else { | 808 } else { |
819 fragBuilder->codeAppendf( | 809 fragBuilder->codeAppendf( |
820 "vec4(\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s)," | 810 "vec4(\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s)," |
821 "\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s))", | 811 "\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s))", |
822 noiseFuncName.c_str(), chanCoordR, noiseVec, | 812 noiseFuncName.c_str(), chanCoordR, noiseVec, |
823 noiseFuncName.c_str(), chanCoordG, noiseVec, | 813 noiseFuncName.c_str(), chanCoordG, noiseVec, |
824 noiseFuncName.c_str(), chanCoordB, noiseVec, | 814 noiseFuncName.c_str(), chanCoordB, noiseVec, |
825 noiseFuncName.c_str(), chanCoordA, noiseVec); | 815 noiseFuncName.c_str(), chanCoordA, noiseVec); |
826 } | 816 } |
827 if (fType != SkPerlinNoiseShader::kFractalNoise_Type) { | 817 if (pne.type() != SkPerlinNoiseShader::kFractalNoise_Type) { |
828 fragBuilder->codeAppendf(")"); // end of "abs(" | 818 fragBuilder->codeAppendf(")"); // end of "abs(" |
829 } | 819 } |
830 fragBuilder->codeAppendf(" * %s;", ratio); | 820 fragBuilder->codeAppendf(" * %s;", ratio); |
831 | 821 |
832 fragBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", noiseVec); | 822 fragBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", noiseVec); |
833 fragBuilder->codeAppendf("\n\t\t\t%s *= 0.5;", ratio); | 823 fragBuilder->codeAppendf("\n\t\t\t%s *= 0.5;", ratio); |
834 | 824 |
835 if (fStitchTiles) { | 825 if (pne.stitchTiles()) { |
836 fragBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", stitchData); | 826 fragBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", stitchData); |
837 } | 827 } |
838 fragBuilder->codeAppend("\n\t\t}"); // end of the for loop on octaves | 828 fragBuilder->codeAppend("\n\t\t}"); // end of the for loop on octaves |
839 | 829 |
840 if (fType == SkPerlinNoiseShader::kFractalNoise_Type) { | 830 if (pne.type() == SkPerlinNoiseShader::kFractalNoise_Type) { |
841 // The value of turbulenceFunctionResult comes from ((turbulenceFunction
Result) + 1) / 2 | 831 // The value of turbulenceFunctionResult comes from ((turbulenceFunction
Result) + 1) / 2 |
842 // by fractalNoise and (turbulenceFunctionResult) by turbulence. | 832 // by fractalNoise and (turbulenceFunctionResult) by turbulence. |
843 fragBuilder->codeAppendf("\n\t\t%s = %s * vec4(0.5) + vec4(0.5);", | 833 fragBuilder->codeAppendf("\n\t\t%s = %s * vec4(0.5) + vec4(0.5);", |
844 args.fOutputColor,args.fOutputColor); | 834 args.fOutputColor,args.fOutputColor); |
845 } | 835 } |
846 | 836 |
847 // Clamp values | 837 // Clamp values |
848 fragBuilder->codeAppendf("\n\t\t%s = clamp(%s, 0.0, 1.0);", args.fOutputColo
r, args.fOutputColor); | 838 fragBuilder->codeAppendf("\n\t\t%s = clamp(%s, 0.0, 1.0);", args.fOutputColo
r, args.fOutputColor); |
849 | 839 |
850 // Pre-multiply the result | 840 // Pre-multiply the result |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
980 str->append(" seed: "); | 970 str->append(" seed: "); |
981 str->appendScalar(fSeed); | 971 str->appendScalar(fSeed); |
982 str->append(" stitch tiles: "); | 972 str->append(" stitch tiles: "); |
983 str->append(fStitchTiles ? "true " : "false "); | 973 str->append(fStitchTiles ? "true " : "false "); |
984 | 974 |
985 this->INHERITED::toString(str); | 975 this->INHERITED::toString(str); |
986 | 976 |
987 str->append(")"); | 977 str->append(")"); |
988 } | 978 } |
989 #endif | 979 #endif |
OLD | NEW |