/// <summary> /// Sets up stored and derived parameters from an atmosphere model /// </summary> /// <remarks> /// The inner radius is diminished by a constant amount, because otherwise, the quantised /// view directions hit the inner sphere and cause a blue band to appear when the actual /// view direction approaches it. /// </remarks> private void SetupModelAndParameters( AtmosphereBuildParameters parameters, AtmosphereBuildModel model ) { m_RayleighCoefficients = ( float[] )model.RayleighCoefficients.Clone( ); m_MieCoefficients = ( float[] )model.MieCoefficients.Clone( ); m_InnerRadius = model.InnerRadiusMetres; m_OuterRadius = model.InnerRadiusMetres + model.AtmosphereThicknessMetres; m_InnerSphere = new Sphere3( Point3.Origin, m_InnerRadius * model.GroundRadiusMultiplier ); // NOTE: AP: See remarks m_OuterSphere = new Sphere3( Point3.Origin, m_OuterRadius ); m_AttenuationSamples = parameters.AttenuationSamples; float heightRange = ( m_OuterRadius - m_InnerRadius ); m_InvRH0 = -1.0f / ( heightRange * model.RayleighDensityScaleHeightFraction ); m_InvMH0 = -1.0f / ( heightRange * model.MieDensityScaleHeightFraction ); m_InscatterDistanceFudgeFactor = model.InscatterDistanceFudgeFactor; m_OutscatterDistanceFudgeFactor = model.OutscatterDistanceFudgeFactor; m_MieFudge = model.MieFudgeFactor; m_RayleighFudge = model.RayleighFudgeFactor; m_OutscatterFudge = model.OutscatterFudgeFactor; }
/// <summary> /// Setup constructor /// </summary> public WorkItem( BackgroundWorker worker, AtmosphereBuildModel model, AtmosphereBuildParameters parameters ) { m_Worker = worker; m_AtmosphereModel = model; m_AtmosphereBuildParameters = parameters; }
// // Discrepancies in atmospheric modelling papers: // - HG: // - Neilsen: HG(t,g) = (1-g2)/(4pi(1 + g2 - 2cos(t))^1.5) // - Wolfram: HG(t,g) = (1-g2)/(1 + g2 - 2.g.cos(t))^1.5 // - O'Neil (adapted HG): HG(t,g) = 3(1-g2)/2(2+g2) . (1+t2)/(1+g2 - 2gt)^1.5 // - O'Neil and Wolfram work well. Neilsen doesn't (denominator can evalute to < 0 before raising to 3/2 power) // - Scattering coefficients: (# is wavelength) // - Neilsen Rayleigh coefficient: 8pi^2(n2-1)^2/3N#^4 // - Neilsen Mie coefficient: 0.434c.pi.4pi^2/#^2K // - K=non-wavelength dependent fudge factor for Bm: ~0.67 // - c=concentration factor(0.6544T-0.6510).10e-16 (T=turbidity. ~555nm) // // // // // Realtime rendering of atmospheric scattering for flight simulators: // http://www2.imm.dtu.dk/pubdb/views/edoc_download.php/2554/pdf/imm2554.pdf // // Display of The Earth Taking into Account Atmospheric Scattering: (Nishita) // http://nis-lab.is.s.u-tokyo.ac.jp/~nis/abs_sig.html#sig93 // // Implementation of Nishita's paper: // http://www.gamedev.net/reference/articles/article2093.asp // // A practical analytical model of daylight: // http://www.cs.utah.edu/vissim/papers/sunsky/sunsky.pdf // // Discussion about atmospheric shaders: // http://www.gamedev.net/community/forums/topic.asp?topic_id=335023 // // Paper that this model is based on: // http://www.vis.uni-stuttgart.de/~schafhts/HomePage/pubs/wscg07-schafhitzel.pdf // // Heyney-Greenstein on Mathworld: // http://scienceworld.wolfram.com/physics/Heyney-GreensteinPhaseFunction.html // /// <summary> /// Builds a 3D lookup texture /// </summary> /// <param name="model">The atmosphere model</param> /// <param name="parameters">Parameters for the build process</param> /// <param name="progress">Optional progress object</param> /// <returns>Returns a 3d texture data. Returns null if cancel was flagged in the progress object</returns> public unsafe AtmosphereBuildOutputs Build( AtmosphereBuildModel model, AtmosphereBuildParameters parameters, AtmosphereBuildProgress progress ) { Texture2dData opticalDepthTexture = new Texture2dData( ); Texture3dData scatteringTexture = new Texture3dData( ); scatteringTexture.Create( parameters.ViewAngleSamples, parameters.SunAngleSamples, parameters.HeightSamples, TextureFormat.R8G8B8A8 ); SetupModelAndParameters( parameters, model ); progress = progress ?? new AtmosphereBuildProgress( ); fixed ( byte* voxels = scatteringTexture.Bytes ) { if ( !BuildScatteringTexture( parameters, voxels, progress ) ) { return null; } } if ( progress.Cancel ) { return null; } opticalDepthTexture.Create( parameters.OpticalDepthResolution, parameters.OpticalDepthResolution, TextureFormat.R8G8B8 ); fixed ( byte* pixels = opticalDepthTexture.Bytes ) { if ( !BuildOpticalDepthTexture( parameters, pixels, progress ) ) { return null; } } return new AtmosphereBuildOutputs( scatteringTexture, opticalDepthTexture ); }