protected static void BRDFMappingGlobalFunctionGradientEval( double[] _Coefficients, double[] _Gradients, object _Params )
{
BRDFFitEvaluationContext Context = _Params as BRDFFitEvaluationContext;
double Normalizer = 1.0 / ms_BRDFSamples.Length;
// Compute derivatives for each coefficient
_Gradients[0] = 0.0;
for ( int DerivativeIndex=1; DerivativeIndex < _Coefficients.Length; DerivativeIndex++ )
{
// Copy coefficients and add a tiny delta for derivative estimate
_Coefficients.CopyTo( ms_TempCoefficientsGlobal, 0 );
ms_TempCoefficientsGlobal[DerivativeIndex] += DERIVATIVE_OFFSET; // Add a tiny delta for derivative estimate
// Copy current coefficients into the current cosine lobes
for ( int LobeIndex=0; LobeIndex < Context.m_Lobes.Length; LobeIndex++ )
{
CosineLobe Lobe = Context.m_Lobes[LobeIndex];
int CoeffOffset = 1+4*LobeIndex; // Remember those stupid coefficients are indexed from 1!
Lobe.C.Set( ms_TempCoefficientsGlobal[CoeffOffset+0], ms_TempCoefficientsGlobal[CoeffOffset+1], ms_TempCoefficientsGlobal[CoeffOffset+2] );
Lobe.N = Math.Max( EPS, ms_TempCoefficientsGlobal[CoeffOffset+3] ); // Exponents are constrained to be strictly positive!
}
// Sum differences between current ZH estimates and current SH goal estimates
double SumSquareDifference = ComputeSummedDifferences( ms_BRDFSamples, Normalizer, Context.m_BRDF, Context.m_Lobes );
// Compute delta with fixed central square difference
_Gradients[DerivativeIndex] = (SumSquareDifference - Context.m_SumSquareDifference) / DERIVATIVE_OFFSET;
}
}