4template<size_t colorCount>
 
    5GradientMaterial<colorCount>::GradientMaterial(RGBColor* rgbColors, float gradientPeriod, bool isRadial, bool isStepped) {
 
    6    this->gradientPeriod = gradientPeriod;
 
    7    this->isRadial = isRadial;
 
    8    this->isStepped = isStepped;
 
    9    this->baseRGBColors = rgbColors;
 
   11    UpdateGradient(rgbColors);
 
   14template<size_t colorCount>
 
   15void GradientMaterial<colorCount>::UpdateGradient(RGBColor* rgbColors) {
 
   16    for (uint8_t i = 0; i < colorCount; i++) {
 
   17        this->rgbColors[i] = rgbColors[i];
 
   21template<size_t colorCount>
 
   22void GradientMaterial<colorCount>::SetPositionOffset(Vector2D positionOffset) {
 
   23    this->positionOffset = positionOffset;
 
   26template<size_t colorCount>
 
   27void GradientMaterial<colorCount>::SetRotationOffset(Vector2D rotationOffset) {
 
   28    this->rotationOffset = rotationOffset;
 
   31template<size_t colorCount>
 
   32void GradientMaterial<colorCount>::SetRotationAngle(float rotationAngle) {
 
   33    this->rotationAngle = rotationAngle;
 
   36template<size_t colorCount>
 
   37void GradientMaterial<colorCount>::SetGradientPeriod(float gradientPeriod) {
 
   38    this->gradientPeriod = gradientPeriod;
 
   41template<size_t colorCount>
 
   42void GradientMaterial<colorCount>::GradientShift(float ratio) {
 
   43    this->gradientShift = ratio;
 
   46template<size_t colorCount>
 
   47void GradientMaterial<colorCount>::HueShift(float hueDeg) {
 
   48    for (uint8_t i = 0; i < colorCount; i++) {
 
   49        rgbColors[i] = baseRGBColors[i].HueShift(hueDeg);
 
   53template<size_t colorCount>
 
   54void GradientMaterial<colorCount>::UpdateRGB() {
 
   55    for (uint8_t i = 0; i < colorCount; i++) {
 
   56        rgbColors[i] = baseRGBColors[i];
 
   60template<size_t colorCount>
 
   61RGBColor GradientMaterial<colorCount>::GetRGB(const Vector3D& position, const Vector3D& normal, const Vector3D& uvw) {
 
   62    Vector3D positionL = position;
 
   64    if (rotationAngle != 0) {
 
   65        Quaternion temp = Rotation(EulerAngles(Vector3D(0, 0, rotationAngle), EulerConstants::EulerOrderXYZS)).GetQuaternion();
 
   67        positionL = temp.RotateVector(positionL);
 
   71    positionL = positionL - Vector3D(positionOffset.X, positionOffset.Y, 0);
 
   72    positionL = positionL + Vector3D(gradientShift * gradientPeriod, 0, 0);
 
   75        pos = sqrtf(positionL.X * positionL.X + positionL.Y * positionL.Y);
 
   76        pos = fabs(fmodf(pos, gradientPeriod));
 
   79        // from x position, fit into bucket ratio
 
   80        pos = fabs(fmodf(positionL.X, gradientPeriod));
 
   83    // map from modulo'd x value to color count minimum
 
   84    float ratio = Mathematics::Map(pos, 0.0f, gradientPeriod, 0.0f, float(colorCount));
 
   85    uint8_t startBox = floor(ratio);
 
   86    uint8_t endBox = startBox + 1 >= (uint8_t)colorCount ? 0 : startBox + 1;
 
   91        rgb = rgbColors[startBox];
 
   94        float mu = Mathematics::Map(ratio, float(startBox), float(startBox + 1), 0.0f, 1.0f); // calculate mu between boxes
 
   96        rgb = RGBColor::InterpolateColors(rgbColors[startBox], rgbColors[endBox], mu);