86  const int imgWidth = img.width(), imgHeight = img.height();
 
   87  QRgb *imgPtr = 
reinterpret_cast<QRgb *
>( img.bits() );
 
   88  const QRgb *elevPtr = 
reinterpret_cast<const QRgb *
>( mElevationImage.constBits() );
 
   90  const int neighbours[] = { -1, 0, 1, 0, 0, -1, 0, 1 };
 
   91  for ( 
int i = 0; i < imgWidth; ++i )
 
   93    for ( 
int j = 0; j < imgHeight; ++j )
 
  100      for ( 
qgssize k = 0; k < 4; ++k )
 
  102        float borderFactor = 1.0f;
 
  103        int iNeighbour = std::clamp( i + distance * neighbours[2 * k], 0, imgWidth - 1 );
 
  104        int jNeighbour = std::clamp( j + distance * neighbours[2 * k + 1], 0, imgHeight - 1 );
 
  105        qgssize neighbourIndex = jNeighbour * 
static_cast<qgssize>( imgWidth ) + iNeighbour;
 
  109        if ( 
isNoData( elevPtr[ neighbourIndex ] ) )
 
  111          if ( neighbours[2 * k] != 0 )
 
  113            int corrI = iNeighbour;
 
  114            int inc = neighbours[2 * k];
 
  115            while ( corrI != i && 
isNoData( elevPtr[ neighbourIndex ] ) )
 
  118              neighbourIndex = jNeighbour * 
static_cast<qgssize>( imgWidth ) + corrI;
 
  123            borderFactor = 
static_cast<float>( distance ) / 
static_cast<float>( std::abs( i - corrI ) )   ;
 
  126          if ( neighbours[2 * k + 1] != 0 )
 
  128            int corrJ = jNeighbour;
 
  129            int inc = neighbours[2 * k + 1];
 
  130            while ( corrJ != j && 
isNoData( elevPtr[ neighbourIndex ] ) )
 
  133              neighbourIndex = corrJ * 
static_cast<qgssize>( imgWidth ) + iNeighbour;
 
  138            borderFactor = 
static_cast<float>( distance ) / 
static_cast<float>( std::abs( j - corrJ ) )   ;
 
  144        if ( neighbours[2 * k] != 0 && std::abs( iNeighbour - i ) < distance )
 
  146          if ( i > iNeighbour )
 
  147            borderFactor = 
static_cast<float>( distance ) /  
static_cast<float>( i )  ;
 
  148          else if ( i < iNeighbour )
 
  149            borderFactor = 
static_cast<float>( distance ) / 
static_cast<float>( ( imgWidth - i - 1 ) )  ;
 
  151        if ( neighbours[2 * k + 1] != 0 && std::abs( jNeighbour - j ) < distance )
 
  153          if ( j > jNeighbour )
 
  154            borderFactor = 
static_cast<float>( distance ) /  
static_cast<float>( j )  ;
 
  155          else if ( j < jNeighbour )
 
  156            borderFactor = 
static_cast<float>( distance ) / 
static_cast<float>( imgHeight - j - 1 )  ;
 
  160        factor += std::max<float>( 0, -( centerDepth - neighbourDepth ) * borderFactor );
 
  162      float shade = expf( -factor * strength / rendererScale );
 
  164      QRgb 
c = imgPtr[ index ];
 
  165      imgPtr[ index ] = qRgba( 
static_cast<int>( 
static_cast<float>( qRed( 
c ) ) * shade ),
 
  166                               static_cast<int>( 
static_cast<float>( qGreen( 
c ) )  * shade ),
 
  167                               static_cast<int>( 
static_cast<float>( qBlue( 
c ) ) * shade )
 
 
  176  double altRad = altitude * M_PI / 180.0;
 
  177  double cos_altRadian = std::cos( altRad );
 
  178  double sin_altRadian = std::sin( altRad );
 
  179  double cos_alt_mul_z = cos_altRadian * zFactor ;
 
  180  double azimuthRad = -1 * azimuth * M_PI / 180.0;
 
  181  double cos_az_mul_cos_alt_mul_z = std::cos( azimuthRad ) * cos_alt_mul_z;
 
  182  double sin_az_mul_cos_alt_mul_z = std::sin( azimuthRad ) * cos_alt_mul_z;
 
  187  double cos225_az_mul_cos_alt_mul_z_mul_0_5 = -32.87001872802012 * cos_alt_mul_z / 255;
 
  188  double square_z =  zFactor * zFactor;
 
  190  QRgb *imgPtr = 
reinterpret_cast<QRgb *
>( img.bits() );
 
  191  const QRgb *elevPtr = 
reinterpret_cast<const QRgb *
>( mElevationImage.constBits() );
 
  193  const int imgWidth = img.width(), imgHeight = img.height();
 
  195  auto colRowToIndex = [&]( 
int c, 
int r )->
qgssize 
  197    return  static_cast<qgssize>( r ) * imgWidth + 
c ;
 
  206  float pixelValues[9];
 
  208  for ( 
int rowC = 0; rowC < imgHeight ; ++rowC )
 
  210    int rowU = std::max( 0, rowC - 1 );
 
  211    int rowD = std::min( imgHeight - 1, rowC + 1 );
 
  222    for ( 
int colC = 0; colC < imgWidth  ; ++colC )
 
  224      qgssize centerIndex = colRowToIndex( colC, rowC );
 
  225      int colR = std::min( imgWidth - 1, colC + 1 );
 
  227      pixelValues[0] = pixelValues[1];
 
  228      pixelValues[3] = pixelValues[4];
 
  229      pixelValues[6] = pixelValues[7];
 
  231      pixelValues[1] = pixelValues[2];
 
  232      pixelValues[4] = pixelValues[5];
 
  233      pixelValues[7] = pixelValues[8];
 
  235      pixelValues[2] = 
decodeElevation( elevPtr[colRowToIndex( colR, rowU )] );
 
  236      pixelValues[5] = 
decodeElevation( elevPtr[colRowToIndex( colR, rowC )] );
 
  237      pixelValues[8] = 
decodeElevation( elevPtr[colRowToIndex( colR, rowD )] );
 
  239      if ( elevPtr[centerIndex] != 0 )
 
  242        const float x22 = pixelValues[4];
 
  246        const float x11 = ( pixelValues[0] == noData ) ? x22 : pixelValues[0];
 
  247        const float x21 = ( pixelValues[3] == noData ) ? x22 : pixelValues[3];
 
  248        const float x31 = ( pixelValues[6] == noData ) ? x22 : pixelValues[6];
 
  250        const float x12 = ( pixelValues[1] == noData ) ? x22 : pixelValues[1];
 
  251        const float x32 = ( pixelValues[7] == noData ) ? x22 : pixelValues[7];
 
  253        const float x13 = ( pixelValues[2] == noData ) ? x22 : pixelValues[2];
 
  254        const float x23 = ( pixelValues[5] == noData ) ? x22 : pixelValues[5];
 
  255        const float x33 = ( pixelValues[8] == noData ) ? x22 : pixelValues[8];
 
  257        const double derX = 
static_cast<double>( ( x13 + x23 + x23 + x33 ) - ( x11 + x21 + x21 + x31 ) ) / ( 8 * cellSizeX );
 
  258        const double derY = 
static_cast<double>( ( x31 + x32 + x32 + x33 ) - ( x11 + x12 + x12 + x13 ) ) / ( 8 * -cellSizeY );
 
  261        if ( !multiDirectional )
 
  264          shade = std::clamp( ( sin_altRadian -
 
  265                                ( derY * cos_az_mul_cos_alt_mul_z -
 
  266                                  derX * sin_az_mul_cos_alt_mul_z ) ) /
 
  267                              std::sqrt( 1 + square_z * ( derX * derX + derY * derY ) ),
 
  274          const double xx = derX * derX;
 
  275          const double yy = derY * derY;
 
  276          const double xx_plus_yy = xx + yy;
 
  278          if ( xx_plus_yy == 0.0 )
 
  280            shade = std::clamp( sin_altRadian, 0.0, 1.0 );
 
  285            double val225_mul_0_5 = sin_altRadian * 0.5 +
 
  286                                    ( derX - derY ) * cos225_az_mul_cos_alt_mul_z_mul_0_5;
 
  287            val225_mul_0_5 = ( val225_mul_0_5 <= 0.0 ) ? 0.0 : val225_mul_0_5;
 
  288            double val270_mul_0_5 = sin_altRadian * 0.5 -
 
  289                                    derX * cos_alt_mul_z * 0.5;
 
  290            val270_mul_0_5 = ( val270_mul_0_5 <= 0.0 ) ? 0.0 : val270_mul_0_5;
 
  291            double val315_mul_0_5 = sin_altRadian * 0.5 +
 
  292                                    ( derX + derY ) * cos225_az_mul_cos_alt_mul_z_mul_0_5;
 
  293            val315_mul_0_5 = ( val315_mul_0_5 <= 0.0 ) ? 0.0 : val315_mul_0_5;
 
  294            double val360_mul_0_5 = sin_altRadian * 0.5 -
 
  295                                    derY * cos_alt_mul_z * 0.5;
 
  296            val360_mul_0_5 = ( val360_mul_0_5 <= 0.0 ) ? 0.0 : val360_mul_0_5;
 
  299            const double weight_225 = 0.5 * xx_plus_yy - derX * derY;
 
  300            const double weight_270 = xx;
 
  301            const double weight_315 = xx_plus_yy - weight_225;
 
  302            const double weight_360 = yy;
 
  303            const double cang_mul_127 = (
 
  304                                          ( weight_225 * val225_mul_0_5 +
 
  305                                            weight_270 * val270_mul_0_5 +
 
  306                                            weight_315 * val315_mul_0_5 +
 
  307                                            weight_360 * val360_mul_0_5 ) / xx_plus_yy ) /
 
  308                                        ( 1 + square_z * xx_plus_yy );
 
  310            shade = std::clamp( cang_mul_127, 0.0, 1.0 );
 
  314        QRgb 
c = imgPtr[ centerIndex ];
 
  315        imgPtr[ centerIndex ] = qRgba( 
static_cast<int>( 
static_cast<float>( qRed( 
c ) ) * shade ),
 
  316                                       static_cast<int>( 
static_cast<float>( qGreen( 
c ) )  * shade ),
 
  317                                       static_cast<int>( 
static_cast<float>( qBlue( 
c ) ) * shade )