diff --git a/stuff/config/current.txt b/stuff/config/current.txt index bf9cb06..d94833d 100644 --- a/stuff/config/current.txt +++ b/stuff/config/current.txt @@ -1316,6 +1316,28 @@ "STD_iwa_GlareFx.noise_evolution" "Noise Evolution" "STD_iwa_GlareFx.noise_offset" "Noise Offset" + "STD_iwa_FractalNoiseFx" "Fractal Noise Iwa" + "STD_iwa_FractalNoiseFx.fractalType" "Fractal Type" + "STD_iwa_FractalNoiseFx.noiseType" "Noise Type" + "STD_iwa_FractalNoiseFx.invert" "Invert" + "STD_iwa_FractalNoiseFx.rotation" "Rotation" + "STD_iwa_FractalNoiseFx.uniformScaling" "Uniform Scaling" + "STD_iwa_FractalNoiseFx.scale" "Scale" + "STD_iwa_FractalNoiseFx.scaleW" "Scale W" + "STD_iwa_FractalNoiseFx.scaleH" "Scale H" + "STD_iwa_FractalNoiseFx.offsetTurbulence" "Offset Turbulence" + "STD_iwa_FractalNoiseFx.perspectiveOffset" "Perspective Offset" + "STD_iwa_FractalNoiseFx.complexity" "Complexity" + "STD_iwa_FractalNoiseFx.subInfluence" "Sub Influence" + "STD_iwa_FractalNoiseFx.subScaling" "Sub Scaling" + "STD_iwa_FractalNoiseFx.subRotation" "Sub Rotation" + "STD_iwa_FractalNoiseFx.subOffset" "Sub Offset" + "STD_iwa_FractalNoiseFx.evolution" "Evolution" + "STD_iwa_FractalNoiseFx.cycleEvolution" "Cycle Evolution" + "STD_iwa_FractalNoiseFx.cycleEvolutionRange" "Cycle (in Evolution)" + "STD_iwa_FractalNoiseFx.dynamicIntensity" "Dynamic Intensity" + "STD_iwa_FractalNoiseFx.alphaRendering" "Alpha Rendering" + STD_iwa_TiledParticlesFx "Tiled Particles Iwa" diff --git a/stuff/profiles/layouts/fxs/STD_iwa_FractalNoiseFx.xml b/stuff/profiles/layouts/fxs/STD_iwa_FractalNoiseFx.xml new file mode 100644 index 0000000..6ce9310 --- /dev/null +++ b/stuff/profiles/layouts/fxs/STD_iwa_FractalNoiseFx.xml @@ -0,0 +1,38 @@ + + + fractalType + noiseType + invert + + rotation + uniformScaling + + scale + + + scaleW + scaleH + + offsetTurbulence + perspectiveOffset + + complexity + + subInfluence + subScaling + subRotation + subOffset + centerSubscale + + evolution + cycleEvolution + + cycleEvolutionRange + + + + dynamicIntensity + + alphaRendering + + diff --git a/stuff/profiles/layouts/fxs/fxs.lst b/stuff/profiles/layouts/fxs/fxs.lst index 8a031ad..15e9a3a 100644 --- a/stuff/profiles/layouts/fxs/fxs.lst +++ b/stuff/profiles/layouts/fxs/fxs.lst @@ -143,6 +143,7 @@ STD_noiseFx STD_iwa_PNPerspectiveFx STD_saltpepperNoiseFx + STD_iwa_FractalNoiseFx STD_cloudsFx diff --git a/toonz/sources/stdfx/CMakeLists.txt b/toonz/sources/stdfx/CMakeLists.txt index 5c38bea..5b99c27 100644 --- a/toonz/sources/stdfx/CMakeLists.txt +++ b/toonz/sources/stdfx/CMakeLists.txt @@ -80,6 +80,7 @@ set(HEADERS iwa_spingradientfx.h iwa_lineargradientfx.h iwa_glarefx.h + iwa_fractalnoisefx.h ) set(SOURCES @@ -266,6 +267,7 @@ set(SOURCES iwa_spingradientfx.cpp iwa_lineargradientfx.cpp iwa_glarefx.cpp + iwa_fractalnoisefx.cpp ) set(OBJCSOURCES diff --git a/toonz/sources/stdfx/iwa_fractalnoisefx.cpp b/toonz/sources/stdfx/iwa_fractalnoisefx.cpp new file mode 100644 index 0000000..e3388f0 --- /dev/null +++ b/toonz/sources/stdfx/iwa_fractalnoisefx.cpp @@ -0,0 +1,474 @@ +#include "iwa_fractalnoisefx.h" +#include "iwa_noise1234.h" +#include "tparamuiconcept.h" + +namespace { +// convert sRGB color space to power space +template +inline T to_linear_color_space(T nonlinear_color, T exposure, T gamma) { + // return -std::log(T(1) - std::pow(nonlinear_color, gamma)) / exposure; + return std::pow(nonlinear_color, gamma) / exposure; +} +// convert power space to sRGB color space +template +inline T to_nonlinear_color_space(T linear_color, T exposure, T gamma) { + // return std::pow(T(1) - std::exp(-exposure * linear_color), T(1) / gamma); + return std::pow(exposure * linear_color, T(1) / gamma); +} + +inline double hardlight(const double *dn, const double *up) { + if ((*up) < 0.5) + return (*up) * (*dn) * 2.0; + else + return 1.0 - 2.0 * (1.0 - (*up)) * (1.0 - (*dn)); +} + +template +inline const T &clamp(const T &v, const T &lo, const T &hi) { + assert(!(hi < lo)); + return (v < lo) ? lo : (hi < v) ? hi : v; +} + +const double turbulentGamma = 2.2; +// magic number to offset evolution between generations +const double evolutionOffsetStep = 19.82; +} // namespace +//------------------------------------------------------------------ + +Iwa_FractalNoiseFx::Iwa_FractalNoiseFx() + : m_fractalType(new TIntEnumParam(Basic, "Basic")) + , m_noiseType(new TIntEnumParam(Block, "Block")) + , m_invert(false) + , m_rotation(0.0) + , m_uniformScaling(true) + , m_scale(100.0) + , m_scaleW(100.0) + , m_scaleH(100.0) + , m_offsetTurbulence(TPointD(0.0, 0.0)) + , m_perspectiveOffset(false) + , m_complexity(6.0) + , m_subInfluence(70.0) + , m_subScaling(56.0) + , m_subRotation(0.0) + , m_subOffset(TPointD(0.0, 0.0)) + ///, m_centerSubscale(false) + , m_evolution(0.0) + , m_cycleEvolution(false) + , m_cycleEvolutionRange(1.0) + ///, m_randomSeed(0) + , m_dynamicIntensity(1.0) + , m_alphaRendering(false) { + m_fractalType->addItem(TurbulentSmooth, "Turbulent Smooth"); + m_fractalType->addItem(TurbulentBasic, "Turbulent Basic"); + m_fractalType->addItem(TurbulentSharp, "Turbulent Sharp"); + m_fractalType->addItem(Dynamic, "Dynamic"); + m_fractalType->addItem(DynamicTwist, "Dynamic Twist"); + m_fractalType->addItem(Max, "Max"); + m_fractalType->addItem(Rocky, "Rocky"); + + m_noiseType->addItem(Smooth, "Smooth"); + m_noiseType->setValue(Smooth); + + m_rotation->setMeasureName("angle"); + m_rotation->setValueRange(-360.0, 360.0); + m_scale->setMeasureName("fxLength"); + m_scale->setValueRange(20.0, 600.0); + m_scaleW->setMeasureName("fxLength"); + m_scaleW->setValueRange(20.0, 600.0); + m_scaleH->setMeasureName("fxLength"); + m_scaleH->setValueRange(20.0, 600.0); + m_offsetTurbulence->getX()->setMeasureName("fxLength"); + m_offsetTurbulence->getY()->setMeasureName("fxLength"); + + m_complexity->setValueRange(1.0, 10.0); + m_subInfluence->setValueRange(25.0, 100.0); + m_subScaling->setValueRange(25.0, 100.0); + m_subRotation->setMeasureName("angle"); + m_subRotation->setValueRange(-360.0, 360.0); + m_subOffset->getX()->setMeasureName("fxLength"); + m_subOffset->getY()->setMeasureName("fxLength"); + + m_evolution->setValueRange(-100.0, 100.0); + m_cycleEvolutionRange->setValueRange(0.1, 30.0); + m_dynamicIntensity->setValueRange(-10.0, 10.0); + + bindParam(this, "fractalType", m_fractalType); + bindParam(this, "noiseType", m_noiseType); + bindParam(this, "invert", m_invert); + bindParam(this, "rotation", m_rotation); + bindParam(this, "uniformScaling", m_uniformScaling); + bindParam(this, "scale", m_scale); + bindParam(this, "scaleW", m_scaleW); + bindParam(this, "scaleH", m_scaleH); + bindParam(this, "offsetTurbulence", m_offsetTurbulence); + bindParam(this, "perspectiveOffset", m_perspectiveOffset); + bindParam(this, "complexity", m_complexity); + bindParam(this, "subInfluence", m_subInfluence); + bindParam(this, "subScaling", m_subScaling); + bindParam(this, "subRotation", m_subRotation); + bindParam(this, "subOffset", m_subOffset); + /// bindParam(this, "centerSubscale", m_centerSubscale); + bindParam(this, "evolution", m_evolution); + bindParam(this, "cycleEvolution", m_cycleEvolution); + bindParam(this, "cycleEvolutionRange", m_cycleEvolutionRange); + /// bindParam(this, "randomSeed", m_randomSeed); + bindParam(this, "dynamicIntensity", m_dynamicIntensity); + + bindParam(this, "alphaRendering", m_alphaRendering); +} + +//------------------------------------------------------------------ + +bool Iwa_FractalNoiseFx::doGetBBox(double frame, TRectD &bBox, + const TRenderSettings &ri) { + bBox = TConsts::infiniteRectD; + return true; +} + +//------------------------------------------------------------------ + +void Iwa_FractalNoiseFx::doCompute(TTile &tile, double frame, + const TRenderSettings &ri) { + // obtain current parameters + FNParam param; + obtainParams(param, frame, ri.m_affine); + + Noise1234 pn; + + TDimension outDim = tile.getRaster()->getSize(); + // allocate buffer for accumulating the noise patterns + TRasterGR8P out_buf_ras = TRasterGR8P(outDim.lx * sizeof(double), outDim.ly); + out_buf_ras->clear(); + out_buf_ras->lock(); + double *out_buf = (double *)out_buf_ras->getRawData(); + + // allocate buffer for storing the noise pattern of each generation + TRasterGR8P work_buf_ras = TRasterGR8P(outDim.lx * sizeof(double), outDim.ly); + work_buf_ras->lock(); + double *work_buf = (double *)work_buf_ras->getRawData(); + + // affine transformations + TAffine globalAff = TTranslation(-tile.m_pos) * ri.m_affine; + TAffine parentOffsetAff = TTranslation(param.offsetTurbulence); + TAffine parentAff = + TScale(param.scale.lx, param.scale.ly) * TRotation(-param.rotation); + TAffine subAff = TTranslation(param.subOffset) * TScale(param.subScaling) * + TRotation(-param.subRotation); + + TAffine offsetAff = + TTranslation((double)outDim.lx * 0.5, (double)outDim.ly * 0.5); + + TAffine genAff; + + // for cyclic evolution, rotate the sample position in ZW space instead of + // using the periodic noise in Z space so that it can cycle in arbitral + // period. + double evolution_z = param.evolution; + TPointD evolution_zw; + if (param.cycleEvolution) { + double theta = 2.0 * M_PI * param.evolution / param.cycleEvolutionRange; + double d = param.cycleEvolutionRange / (2.0 * M_PI); + evolution_zw.x = d * cos(theta); + evolution_zw.y = d * sin(theta); + } + + int genCount = (int)std::ceil(param.complexity); + + // accumulate base noise pattern for each generation + for (int gen = 0; gen < genCount; gen++) { + // affine transformation for the current generation + TAffine currentAff = + (globalAff * parentOffsetAff * parentAff * genAff * offsetAff).inv(); + // scale of the current pattern ( used for the Dynamic / Dynamic Twist + // offset ) + double scale = sqrt(std::abs(currentAff.det())); + + // for each pixel + double *buf_p = work_buf; + for (int y = 0; y < outDim.ly; y++) { + for (int x = 0; x < outDim.lx; x++, buf_p++) { + // obtain sampling position + // For Dynamic and Dynamic Twist patterns, the position offsets using + // gradient / rotation of the parent pattern + TPointD samplePos = + getSamplePos(x, y, outDim, out_buf, gen, scale, param); + // multiply affine transformation + samplePos = currentAff * samplePos; + // adjust postion for the block pattern + if (param.noiseType == Block) + samplePos = TPointD(std::floor(samplePos.x) + 0.5, + std::floor(samplePos.y) + 0.5); + // calculate the base noise + if (param.cycleEvolution) + *buf_p = (pn.noise(samplePos.x, samplePos.y, evolution_zw.x, + evolution_zw.y) + + 1.0) * + 0.5; + else + *buf_p = + (pn.noise(samplePos.x, samplePos.y, evolution_z) + 1.0) * 0.5; + + // convert the noise + convert(buf_p, param); + } + } + + // just copy the values for the first generation + if (gen == 0) { + memcpy(out_buf, work_buf, outDim.lx * outDim.ly * sizeof(double)); + } else { + // intensity of the last generation will take the fraction part of + // complexity + double genIntensity = std::min(1.0, param.complexity - (double)gen); + // influence of the current generation + double influence = + genIntensity * std::pow(param.subInfluence, (double)gen); + // composite the base noise pattern + buf_p = work_buf; + double *out_p = out_buf; + for (int i = 0; i < outDim.lx * outDim.ly; i++, buf_p++, out_p++) + composite(out_p, buf_p, influence, param); + } + + // update affine transformations (for the next generation loop) + genAff *= subAff; + // When the "Perspective Offset" option is ON, reduce the offset amount + // according to the sub scale + if (param.perspectiveOffset) + parentOffsetAff = TScale(param.subScaling) * + TRotation(-param.subRotation) * parentOffsetAff * + TRotation(param.subRotation) * + TScale(1 / param.subScaling); + + if (param.cycleEvolution) + evolution_zw.x += evolutionOffsetStep; + else + evolution_z += evolutionOffsetStep; + } + + work_buf_ras->unlock(); + + // finalize pattern (coverting the color space) + if (param.fractalType == TurbulentSmooth || + param.fractalType == TurbulentBasic || + param.fractalType == TurbulentSharp) { + double *out_p = out_buf; + for (int i = 0; i < outDim.lx * outDim.ly; i++, out_p++) + finalize(out_p, param); + } + + tile.getRaster()->clear(); + + // convert to RGB channel values + TRaster32P ras32 = (TRaster32P)tile.getRaster(); + TRaster64P ras64 = (TRaster64P)tile.getRaster(); + if (ras32) + outputRaster(ras32, out_buf, param); + else if (ras64) + outputRaster(ras64, out_buf, param); + + out_buf_ras->unlock(); +} + +//------------------------------------------------------------------ +// obtain current parameters +void Iwa_FractalNoiseFx::obtainParams(FNParam ¶m, const double frame, + const TAffine &aff) { + param.fractalType = (FractalType)m_fractalType->getValue(); + param.noiseType = (NoiseType)m_noiseType->getValue(); + param.invert = m_invert->getValue(); + param.rotation = m_rotation->getValue(frame); // in degree, not radian + if (m_uniformScaling->getValue()) { // uniform case + double s = m_scale->getValue(frame); + param.scale = TDimensionD(s, s); + } else { // non-uniform case + param.scale.lx = m_scaleW->getValue(frame); + param.scale.ly = m_scaleH->getValue(frame); + } + assert(param.scale.lx != 0.0 && param.scale.ly != 0.0); + if (param.scale.lx == 0.0) param.scale.lx = 1e-8; + if (param.scale.ly == 0.0) param.scale.ly = 1e-8; + + param.offsetTurbulence = m_offsetTurbulence->getValue(frame); + param.perspectiveOffset = m_perspectiveOffset->getValue(); + param.complexity = m_complexity->getValue(frame); + if (param.complexity < 1.0) + param.complexity = + 1.0; // at least the first generation is rendered in full opacity + param.subInfluence = + m_subInfluence->getValue(frame) / 100.0; // normalize to 0 - 1 + param.subScaling = + m_subScaling->getValue(frame) / 100.0; // normalize to 0 - 1 + param.subRotation = m_subRotation->getValue(frame); // in degree, not radian + param.subOffset = m_subOffset->getValue(frame); + param.evolution = m_evolution->getValue(frame); + param.cycleEvolution = m_cycleEvolution->getValue(); + param.cycleEvolutionRange = m_cycleEvolutionRange->getValue(frame); + param.dynamicIntensity = m_dynamicIntensity->getValue(frame) * 10.0; + param.alphaRendering = m_alphaRendering->getValue(); +} + +//------------------------------------------------------------------ +template +void Iwa_FractalNoiseFx::outputRaster(const RASTER outRas, double *out_buf, + const FNParam ¶m) { + TDimension dim = outRas->getSize(); + double *buf_p = out_buf; + for (int j = 0; j < dim.ly; j++) { + PIXEL *pix = outRas->pixels(j); + for (int i = 0; i < dim.lx; i++, pix++, buf_p++) { + double val = (param.invert) ? 1.0 - (*buf_p) : (*buf_p); + val = clamp(val, 0.0, 1.0); + typename PIXEL::Channel chan = static_cast( + val * (double)PIXEL::maxChannelValue); + pix->r = chan; + pix->g = chan; + pix->b = chan; + pix->m = (param.alphaRendering) ? chan : PIXEL::maxChannelValue; + } + } +} + +//------------------------------------------------------------------ + +void Iwa_FractalNoiseFx::getParamUIs(TParamUIConcept *&concepts, int &length) { + concepts = new TParamUIConcept[length = 2]; + + concepts[0].m_type = TParamUIConcept::POINT; + concepts[0].m_label = "Offset Turbulence"; + concepts[0].m_params.push_back(m_offsetTurbulence); + + concepts[1].m_type = TParamUIConcept::POINT; + concepts[1].m_label = "Sub Offset"; + concepts[1].m_params.push_back(m_subOffset); +} +//------------------------------------------------------------------ +// For Dynamic and Dynamic Twist patterns, the position offsets using gradient / +// rotation of the parent pattern +TPointD Iwa_FractalNoiseFx::getSamplePos(int x, int y, const TDimension outDim, + const double *out_buf, const int gen, + const double scale, + const FNParam ¶m) { + // the position does not offset in the first generation + if (gen == 0 || param.dynamicIntensity == 0.0 || + (param.fractalType != Dynamic && param.fractalType != DynamicTwist)) + return TPointD((double)x, (double)y); + + auto clampPos = [&](int x, int y) { + if (x < 0) + x = 0; + else if (x >= outDim.lx) + x = outDim.lx - 1; + if (y < 0) + y = 0; + else if (y >= outDim.ly) + y = outDim.ly - 1; + return TPoint(x, y); + }; + + auto val = [&](const TPoint &p) { return out_buf[p.y * outDim.lx + p.x]; }; + int range = std::max(2, (int)(0.1 / scale)); + TPoint left = clampPos(x - range, y); + TPoint right = clampPos(x + range, y); + TPoint down = clampPos(x, y - range); + TPoint up = clampPos(x, y + range); + + double dif_x = param.dynamicIntensity * (1 / scale) * + (val(left) - val(right)) / (left.x - right.x); + double dif_y = param.dynamicIntensity * (1 / scale) * (val(up) - val(down)) / + (up.y - down.y); + + if (param.fractalType == Dynamic) + return TPointD((double)x + dif_x, (double)y + dif_y); // gradient + else // Dynamic_twist + return TPointD((double)x + dif_y, (double)y - dif_x); // rotation +} + +//------------------------------------------------------------------ +// convert the noise +void Iwa_FractalNoiseFx::convert(double *buf, const FNParam ¶m) { + if (param.fractalType == Basic || param.fractalType == Dynamic || + param.fractalType == DynamicTwist) + return; + + switch (param.fractalType) { + case TurbulentSmooth: + *buf = std::pow(std::abs(*buf - 0.5), 2.0) * 3.75; + *buf = to_linear_color_space(*buf, 1.0, turbulentGamma); + break; + case TurbulentBasic: + *buf = std::pow(std::abs(*buf - 0.5), 1.62) * 4.454; + *buf = to_linear_color_space(*buf, 1.0, turbulentGamma); + break; + case TurbulentSharp: + *buf = std::pow(std::abs(*buf - 0.5), 0.725) * 1.77; + *buf = to_linear_color_space(*buf, 1.0, turbulentGamma); + break; + case Max: + *buf = std::abs(*buf - 0.5) * 1.96; + break; + case Rocky: + // convertion LUT for the range from 0.43 to 0.57, every 0.01 + static double table[15] = { + 0.25, 0.256658635, 0.275550218, 0.30569519, 0.345275591, + 0.392513494, 0.440512, 0.5, 0.555085147, 0.607486506, + 0.654724409, 0.69430481, 0.724449782, 0.743341365, 0.75}; + if (*buf <= 0.43) + *buf = 0.25; + else if (*buf >= 0.57) + *buf = 0.75; + else { + int id = (int)std::floor(*buf * 100.0) - 43; + double t = *buf * 100.0 - (double)(id + 43); + // linear interpolation the LUT values + *buf = (1 - t) * table[id] + t * table[id + 1]; + } + break; + } +} + +//------------------------------------------------------------------ +// composite the base noise pattern +void Iwa_FractalNoiseFx::composite(double *out, double *buf, + const double influence, + const FNParam ¶m) { + switch (param.fractalType) { + case Basic: + case Dynamic: + case DynamicTwist: + case Rocky: { + // hard light composition + double val = hardlight(out, buf); + *out = (1.0 - influence) * (*out) + influence * val; + break; + } + case TurbulentSmooth: + case TurbulentBasic: + case TurbulentSharp: + // add composition in the linear color space + *out += (*buf) * influence; + break; + case Max: + // max composition + *out = std::max(*out, influence * (*buf)); + break; + default: { + double val = hardlight(out, buf); + *out = (1.0 - influence) * (*out) + influence * val; + break; + } + } +} + +//------------------------------------------------------------------ +// finalize pattern (coverting the color space) +void Iwa_FractalNoiseFx::finalize(double *out, const FNParam ¶m) { + assert(param.fractalType == TurbulentSmooth || + param.fractalType == TurbulentBasic || + param.fractalType == TurbulentSharp); + + // TurbulentSmooth / TurbulentBasic / TurbulentSharp + *out = to_nonlinear_color_space(*out, 1.0, turbulentGamma); +} + +FX_PLUGIN_IDENTIFIER(Iwa_FractalNoiseFx, "iwa_FractalNoiseFx"); diff --git a/toonz/sources/stdfx/iwa_fractalnoisefx.h b/toonz/sources/stdfx/iwa_fractalnoisefx.h new file mode 100644 index 0000000..d0b2642 --- /dev/null +++ b/toonz/sources/stdfx/iwa_fractalnoisefx.h @@ -0,0 +1,142 @@ +#pragma once + +//****************************************************************** +// Iwa FractalNoise Fx +// An Fx emulating Fractal Noise effect in Adobe AfterEffect +//****************************************************************** + +#ifndef IWA_FRACTALNOISEFX_H +#define IWA_FRACTALNOISEFX_H + +#include "tfxparam.h" +#include "tparamset.h" +#include "stdfx.h" + +class Iwa_FractalNoiseFx final : public TStandardZeraryFx { + FX_PLUGIN_DECLARATION(Iwa_FractalNoiseFx) + + enum FractalType { + Basic = 0, + TurbulentSmooth, + TurbulentBasic, + TurbulentSharp, + Dynamic, + DynamicTwist, + Max, + Rocky, + FractalTypeCount + }; + + enum NoiseType { Block = 0, Smooth, NoiseTypeCount }; + + struct FNParam { + FractalType fractalType; + NoiseType noiseType; + bool invert; + double rotation; + TDimensionD scale; + TPointD offsetTurbulence; + bool perspectiveOffset; + double complexity; + double subInfluence; + double subScaling; + double subRotation; + TPointD subOffset; + double evolution; + bool cycleEvolution; + double cycleEvolutionRange; + double dynamicIntensity; + bool alphaRendering; + }; + +protected: + // Fractal Type �t���N�^���̎�� + TIntEnumParamP m_fractalType; + // Noise Type �m�C�Y�̎�� + TIntEnumParamP m_noiseType; + // Invert ���] + TBoolParamP m_invert; + /// Contrast �R���g���X�g + /// Brightness ���邳 + /// Overflow �I�[�o�[�t���[ + + //- - - Transform �g�����X�t�H�[�� - - - + // Rotation ��] + TDoubleParamP m_rotation; + // Uniform Scaling�@�c������Œ� + TBoolParamP m_uniformScaling; + // Scale �X�P�[�� + TDoubleParamP m_scale; + // Scale Width �X�P�[���̕� + TDoubleParamP m_scaleW; + // Scale Height �X�P�[���̍��� + TDoubleParamP m_scaleH; + // Offset Turbulence ���C���̃I�t�Z�b�g + TPointParamP m_offsetTurbulence; + // Perspective Offset ���߃I�t�Z�b�g + TBoolParamP m_perspectiveOffset; + + // Complexity ���G�x + TDoubleParamP m_complexity; + + //- - - Sub Settings �T�u�ݒ� - - - + // Sub Influence �T�u�e���i���j + TDoubleParamP m_subInfluence; + // Sub Scaling�@�T�u�X�P�[�� + TDoubleParamP m_subScaling; + // Sub Rotation �T�u��] + TDoubleParamP m_subRotation; + // Sub Offset �T�u�̃I�t�Z�b�g + TPointParamP m_subOffset; + // Center Subscale �T�u�X�P�[���𒆐S + /// TBoolParamP m_centerSubscale; + + // Evolution �W�J + TDoubleParamP m_evolution; + + //- - - Evolution Options �W�J�̃I�v�V���� - - - + // Cycle Evolution �T�C�N���W�J + TBoolParamP m_cycleEvolution; + // Cycle (in Evolution) �T�C�N���i�����j + TDoubleParamP m_cycleEvolutionRange; + /// Random Seed �����_���V�[�h + /// Opacity �s�����x + /// Blending Mode �`�惂�[�h + + // �_�C�i�~�b�N�̓x���� + TDoubleParamP m_dynamicIntensity; + + // - - - additional parameters - - - + TBoolParamP m_alphaRendering; + +public: + Iwa_FractalNoiseFx(); + bool canHandle(const TRenderSettings &info, double frame) override { + return true; + } + bool doGetBBox(double frame, TRectD &bBox, + const TRenderSettings &ri) override; + void doCompute(TTile &tile, double frame, const TRenderSettings &ri) override; + + void obtainParams(FNParam ¶m, const double frame, const TAffine &aff); + + template + void outputRaster(const RASTER outRas, double *out_buf, const FNParam ¶m); + + void getParamUIs(TParamUIConcept *&concepts, int &length) override; + + // For Dynamic and Dynamic Twist patterns, the position offsets using gradient + // / rotation of the parent pattern + TPointD getSamplePos(int x, int y, const TDimension outDim, + const double *out_buf, const int gen, const double scale, + const FNParam ¶m); + // convert the noise + void convert(double *buf, const FNParam ¶m); + // composite the base noise pattern + void composite(double *out, double *buf, const double influence, + const FNParam ¶m); + // finalize pattern (coverting the color space) + void finalize(double *out, const FNParam ¶m); +}; + +#endif \ No newline at end of file