/** * EvaluateSubBlock * Iterates over all pixels in the specified rectangle, if the resulting pixel * isn't black, mid grey or would result in X or Y being -1 or +1 then it is * added to the average color and the number of samples count is incremented. */ void EvaluateSubBlock( int32 Left, int32 Top, int32 Width, int32 Height ) { for ( int32 Y=Top; Y != (Top+Height); Y++ ) { for ( int32 X=Left; X != (Left+Width); X++ ) { FLinearColor ColorSample = Sampler.DoSampleColor( X, Y ); // Nearly black or transparent pixels don't contribute to the calculation if (FMath::IsNearlyZero(ColorSample.A, AlphaComponentNearlyZeroThreshold) || ColorSample.IsAlmostBlack()) { continue; } // Scale and bias, if required, to get a signed vector float Vx = Sampler.ScaleAndBiasComponent( ColorSample.R ); float Vy = Sampler.ScaleAndBiasComponent( ColorSample.G ); float Vz = Sampler.ScaleAndBiasComponent( ColorSample.B ); const float Length = FMath::Sqrt(Vx * Vx + Vy * Vy + Vz * Vz); if (Length < ColorComponentNearlyZeroThreshold) { // mid-grey pixels representing (0,0,0) are also not considered as they may be used to denote unused areas continue; } // If the vector is sufficiently different in length from a unit vector, consider it invalid. if (FMath::Abs(Length - 1.0f) > NormalVectorUnitLengthDeltaThreshold) { NumSamplesRejected++; continue; } // If the vector is pointing backwards then it is an invalid sample, so consider it invalid if (Vz < 0.0f) { NumSamplesRejected++; continue; } AverageColor += ColorSample; NumSamplesTaken++; } } }
/** * EvaluateSubBlock * Iterates over all pixels in the specified rectangle, if the resulting pixel * isn't black, mid grey or would result in X or Y being -1 or +1 then it is * added to the average color and the number of samples count is incremented. */ void EvaluateSubBlock( int32 Left, int32 Top, int32 Width, int32 Height ) { for ( int32 Y=Top; Y != (Top+Height); Y++ ) { for ( int32 X=Left; X != (Left+Width); X++ ) { FLinearColor ColorSample = Sampler.DoSampleColor( X, Y ); if ( !ColorSample.IsAlmostBlack() ) { if (FMath::IsNearlyZero(ColorSample.A, AlphaComponentNearlyZeroThreshold)) { AverageColor += FLinearColor::Transparent; NumSamplesTaken++; continue; } // Scale and bias, if required, to get a signed vector float Vx = Sampler.ScaleAndBiasComponent( ColorSample.R ); float Vy = Sampler.ScaleAndBiasComponent( ColorSample.G ); float Vz = Sampler.ScaleAndBiasComponent( ColorSample.B ); // If the vector is close to zero (mid-gray) then ignore it as invalid if ( FMath::IsNearlyZero(Vx, ColorComponentNearlyZeroThreshold) && FMath::IsNearlyZero(Vy, ColorComponentNearlyZeroThreshold) && FMath::IsNearlyZero(Vz, ColorComponentNearlyZeroThreshold) ) { continue; } // Assume that if X or Y are very close to +1 or -1 then it is an invalid sample. // If this were to happen in a real normal map, it would imply an impossible gradient if ( !FMath::IsWithinInclusive( Vx, ColorComponentMinVectorThreshold, ColorComponentMaxVectorThreshold ) || !FMath::IsWithinInclusive( Vy, ColorComponentMinVectorThreshold, ColorComponentMaxVectorThreshold ) ) { continue; } AverageColor += ColorSample; NumSamplesTaken++; } } } }