/// <summary> /// Called by the automation form to change the lobe type /// </summary> /// <param name="_type"></param> public void SetLobeType( LobeModel.LOBE_TYPE _type ) { switch ( _type ) { case LobeModel.LOBE_TYPE.MODIFIED_PHONG: radioButtonAnalyticalPhong.Checked = true; break; case LobeModel.LOBE_TYPE.MODIFIED_PHONG_ANISOTROPIC: radioButtonAnalyticalPhongAnisotropic.Checked = true; break; case LobeModel.LOBE_TYPE.BECKMANN: radioButtonAnalyticalBeckmann.Checked = true; break; case LobeModel.LOBE_TYPE.GGX: radioButtonAnalyticalGGX.Checked = true; break; } }
void PerformLobeFitting( float3 _incomingDirection, float _theta, bool _computeInitialThetaUsingCenterOfMass, float _roughness, float _IOR, float _scale, float _flatteningFactor, float _MaskingImportance, float _OversizeFactor, int _scatteringOrder, bool _reflected ) { checkBoxShowAnalyticalLobe.Checked = true; // Read back histogram to CPU for fitting m_Tex_LobeHistogram_CPU.CopyFrom( _reflected ? m_Tex_LobeHistogram_Reflected : m_Tex_LobeHistogram_Transmitted ); // Initialize lobe model m_lobeModel = new LobeModel(); m_lobeModel.ParametersChanged += ( double[] _parameters ) => { UpdateLobeParameters( _parameters, _reflected ); }; double[,] histogramData = LobeModel.HistogramTexture2Array( m_Tex_LobeHistogram_CPU, _scatteringOrder ); m_lobeModel.InitTargetData( histogramData ); LobeModel.LOBE_TYPE lobeType = radioButtonAnalyticalPhong.Checked ? LobeModel.LOBE_TYPE.MODIFIED_PHONG : (radioButtonAnalyticalPhongAnisotropic.Checked ? LobeModel.LOBE_TYPE.MODIFIED_PHONG_ANISOTROPIC : (radioButtonAnalyticalBeckmann.Checked ? LobeModel.LOBE_TYPE.BECKMANN : LobeModel.LOBE_TYPE.GGX)); if ( _computeInitialThetaUsingCenterOfMass ) { // Optionally override theta to use the direction of the center of mass // (quite intuitive to start by aligning our lobe along the main simulated lobe direction!) float3 towardCenterOfMass = m_lobeModel.CenterOfMass.Normalized; _theta = (float) Math.Acos( towardCenterOfMass.z ); // _scale = 2.0 * m_centerOfMass.Length; // Also assume we should match the simulated lobe's length _flatteningFactor = lobeType == LobeModel.LOBE_TYPE.MODIFIED_PHONG ? 0.5f : 1.0f; // Start from a semi-flattened shape so it can choose either direction... _scale = 0.01f * m_lobeModel.CenterOfMass.Length; // In fact, I realized the algorithm converged much faster starting from a very small lobe!! (~20 iterations compared to 200 otherwise, because the gradient leads the algorithm in the wrong direction too fast and it takes hell of a time to get back on tracks afterwards if we start from too large a lobe!) } m_lobeModel.InitLobeData( lobeType, _incomingDirection, _theta, _roughness, _scale, _flatteningFactor, _MaskingImportance, _OversizeFactor, checkBoxUseCenterOfMassForBetterFitting.Checked ); // if ( !checkBoxUseCenterOfMassForBetterFitting.Checked ) { // m_Fitter.SuccessTolerance = 1e-4; // m_Fitter.GradientSuccessTolerance = 1e-4; // } // Peform fitting m_Fitter.Minimize( m_lobeModel ); panelOutput.Invalidate(); }