#ifndef TRANSITION_DITHER_H__ #define TRANSITION_DITHER_H__ #include #include "ILI9341_t3.h" #include "MathUtil.h" #include "BaseTransition.h" const float TRANSITION_DITHER_SPEED = 0.015f; class TransitionDither : public BaseTransition { public: TransitionDither() : BaseTransition() {}; void init( ILI9341_t3 tft ); void restart( ILI9341_t3 tft, uint_fast16_t color ); void perFrame( ILI9341_t3 tft, FrameParams frameParams ); boolean isComplete(); private: float _phase = 0; uint_fast16_t _color; uint_fast8_t _step; }; void TransitionDither::init( ILI9341_t3 tft ) { } void TransitionDither::restart( ILI9341_t3 tft, uint_fast16_t inColor ) { //uint_fast16_t w = tft.width(); //uint_fast16_t h = tft.height(); _phase = 0; _color = inColor; _step = 0; } void TransitionDither::perFrame( ILI9341_t3 tft, FrameParams frameParams ) { uint_fast16_t w = (uint_fast16_t)tft.width(); uint_fast16_t h = (uint_fast16_t)tft.height(); _phase += frameParams.timeMult * TRANSITION_DITHER_SPEED; // Apply some easing. Linear speed feels dull float easeOutQuad = 1.0f - (1.0f-_phase)*(1.0f-_phase); // Calculate destination float dest_f = min( easeOutQuad, 1.0f ) * 0xff; uint_fast8_t dest = floor(dest_f); // Draw dither dots until _step reaches the destination while( _step <= dest ) { // Bayer matrix. See: https://en.wikipedia.org/wiki/Ordered_dithering // Recreate Bayer matrix pattern, basically a recursive sequence of 2D moves: [ 0, 3, // 2, 1 ] uint_fast16_t start_i = 0; uint_fast16_t start_j = 0; uint_fast8_t move = (1<<3); uint_fast8_t s = _step; while( s > 0 ) { if( s&0b01 ) start_i += move; // 1 & 3: move horizontal if( (s&0b01) ^ ((s&0b10)>>1) ) start_j += move; // 1 & 2: move vertical move >>= 1; s >>= 2; } for( uint_fast16_t i=start_i; i= 1.0f; } #endif