public OutputPanelHammersley( IContainer container )
        {
            container.Add( this );

            InitializeComponent();

            WMath.Hammersley	QRNG = new WMath.Hammersley();
            double[,]		Sequence = QRNG.BuildSequence( SAMPLES_COUNT, 2 );
            for ( int SampleIndex=0; SampleIndex < SAMPLES_COUNT; SampleIndex++ )
            {
                float	Angle = 2.0f * (float) Math.PI * (float) Sequence[SampleIndex,0];
                float	Radius = (float) Math.Sqrt( Sequence[SampleIndex,1] );	// Uniform
            //				float	Radius = (float) Sequence[SampleIndex,1];

                m_Samples[SampleIndex] = new WMath.Vector2D( Radius * (float) Math.Cos( Angle ), Radius * (float) Math.Sin( Angle ) );
            }

            string	Format = "const uint		SHADOW_SAMPLES_COUNT = " + SAMPLES_COUNT + ";\r\n"
                           + "const float2	SamplesOffset[SHADOW_SAMPLES_COUNT] = {\r\n";

            for ( int SampleIndex=0; SampleIndex < SAMPLES_COUNT; SampleIndex++ )
            {
                Format += "	float2( " + m_Samples[SampleIndex].x + ", " + m_Samples[SampleIndex].y + " ),\r\n";
            }

            Format += "};\r\n\r\n";

            OnSizeChanged( EventArgs.Empty );
        }
Example #2
0
        public OutputPanelHammersley(IContainer container)
        {
            container.Add(this);

            InitializeComponent();

            WMath.Hammersley QRNG = new WMath.Hammersley();
            double[,]               Sequence = QRNG.BuildSequence(SAMPLES_COUNT, 2);
            for (int SampleIndex = 0; SampleIndex < SAMPLES_COUNT; SampleIndex++)
            {
                float Angle  = 2.0f * (float)Math.PI * (float)Sequence[SampleIndex, 0];
                float Radius = (float)Math.Sqrt(Sequence[SampleIndex, 1]);                      // Uniform
//				float	Radius = (float) Sequence[SampleIndex,1];

                m_Samples[SampleIndex] = new WMath.Vector2D(Radius * (float)Math.Cos(Angle), Radius * (float)Math.Sin(Angle));
            }

            string Format = "const uint		SHADOW_SAMPLES_COUNT = "+ SAMPLES_COUNT + ";\r\n"
                            + "const float2	SamplesOffset[SHADOW_SAMPLES_COUNT] = {\r\n";

            for (int SampleIndex = 0; SampleIndex < SAMPLES_COUNT; SampleIndex++)
            {
                Format += "	float2( " + m_Samples[SampleIndex].x + ", " + m_Samples[SampleIndex].y + " ),\r\n";
            }

            Format += "};\r\n\r\n";

            OnSizeChanged(EventArgs.Empty);
        }
Example #3
0
        private void integerTrackbarControlNeighborsCount_ValueChanged(IntegerTrackbarControl _Sender, int _FormerValue)
        {
            int NeighborsCount = integerTrackbarControlNeighborsCount.Value;

            if (m_SB_Neighbors != null)
            {
                m_SB_Neighbors.Dispose();
            }
            m_SB_Neighbors = new StructuredBuffer <SB_Neighbor>(m_Device, NeighborsCount, true);

            WMath.Vector[] Directions = null;
            if (radioButtonHammersley.Checked)
            {
                double[,]               Samples = m_Hammersley.BuildSequence(NeighborsCount, 2);
                Directions = m_Hammersley.MapSequenceToSphere(Samples);
            }
            else
            {
                Random TempRNG = new Random();
                Directions = new WMath.Vector[NeighborsCount];
                for (int i = 0; i < NeighborsCount; i++)
                {
                    Directions[i] = new WMath.Vector(2.0f * (float)TempRNG.NextDouble() - 1.0f, 2.0f * (float)TempRNG.NextDouble() - 1.0f, 2.0f * (float)TempRNG.NextDouble() - 1.0f);
                    Directions[i].Normalize();
                }
            }

            Random RNG = new Random(1);

            m_NeighborPositions = new float3[NeighborsCount];
            m_NeighborColors    = new float3[NeighborsCount];
            for (int NeighborIndex = 0; NeighborIndex < NeighborsCount; NeighborIndex++)
            {
                float Radius = 2.0f;                    // Make that random!
                m_NeighborPositions[NeighborIndex] = Radius * new float3(Directions[NeighborIndex].x, Directions[NeighborIndex].y, Directions[NeighborIndex].z);

                float R = (float)RNG.NextDouble();
                float G = (float)RNG.NextDouble();
                float B = (float)RNG.NextDouble();
                m_NeighborColors[NeighborIndex] = new float3(R, G, B);

                m_SB_Neighbors.m[NeighborIndex].m_Position = m_NeighborPositions[NeighborIndex];
                m_SB_Neighbors.m[NeighborIndex].m_Color    = m_NeighborColors[NeighborIndex];
            }

            m_SB_Neighbors.Write();             // Upload
        }
Example #4
0
        private void    GenerateRays(int _RaysCount, float _MaxConeAngle, RendererManaged.StructuredBuffer <RendererManaged.float3> _Target)
        {
            _RaysCount = Math.Min(MAX_THREADS, _RaysCount);

            WMath.Hammersley hammersley = new WMath.Hammersley();
            double[,]                       sequence = hammersley.BuildSequence(_RaysCount, 2);
            WMath.Vector[] rays = hammersley.MapSequenceToSphere(sequence, 0.5f * _MaxConeAngle);
            for (int RayIndex = 0; RayIndex < _RaysCount; RayIndex++)
            {
                WMath.Vector ray = rays[RayIndex];

//              // Scale the ray so we ensure to always walk at least a texel in the texture
//              float	SinTheta = (float) Math.Sqrt( 1.0 - ray.y * ray.y );
//              float	LengthFactor = 1.0f / SinTheta;
//              ray *= LengthFactor;

                _Target.m[RayIndex].Set(ray.x, -ray.z, ray.y);
            }

            _Target.Write();
        }
Example #5
0
        /// <summary>
        /// Performs a ray-tracing of the surface
        /// Outputs resulting directions into a texture then performs a histogram
        /// 
        /// The surface is assigned a beam of photons, one for each texel of the heightfield texture
        /// At each iteration, the whole beam is offset a little using a Hammersley sequence that guarantees
        ///  we end up ray-tracing the entire surface finely (hopefully, the full surface can be traced using enough terationsi)
        /// </summary>
        /// <param name="_roughness">Surface roughness</param>
        /// <param name="_albedo">Surface albedo for diffuse or F0 for dielectrics</param>
        /// <param name="_surfaceType">Type of surface we're simulating</param>
        /// <param name="_theta">Vertical angle of incidence</param>
        /// <param name="_phi">Azimuthal angle of incidence</param>
        /// <param name="_iterationsCount">Amount of iterations of beam tracing</param>
        public void RayTraceSurface( float _roughness, float _albedoF0, SURFACE_TYPE _surfaceType, float _theta, float _phi, int _iterationsCount )
        {
            float	sinTheta = (float) Math.Sin( _theta );
            float	cosTheta = (float) Math.Cos( _theta );
            float	sinPhi = (float) Math.Sin( _phi );
            float	cosPhi = (float) Math.Cos( _phi );

            m_lastComputedDirection.Set( -sinTheta * cosPhi, -sinTheta * sinPhi, -cosTheta );	// Minus sign because we need the direction pointing TOWARD the surface (i.e. z < 0)
            m_lastComputedRoughness = _roughness;
            m_lastComputedAlbedo = _albedoF0;
            m_lastComputedIOR = Fresnel_IORFromF0( _albedoF0 );
            m_lastComputedSurfaceType = _surfaceType;

            m_lastComputedHistogramIterationsCount = _iterationsCount;

            m_CB_RayTrace.m._Direction = m_lastComputedDirection;
            m_CB_RayTrace.m._Roughness = m_lastComputedRoughness;
            m_CB_RayTrace.m._Albedo = m_lastComputedAlbedo;
            m_CB_RayTrace.m._IOR = m_lastComputedIOR;

            m_Tex_OutgoingDirections_Reflected.RemoveFromLastAssignedSlots();
            m_Tex_OutgoingDirections_Transmitted.RemoveFromLastAssignedSlots();
            m_Tex_LobeHistogram_Reflected.RemoveFromLastAssignedSlots();
            m_Tex_LobeHistogram_Transmitted.RemoveFromLastAssignedSlots();

            m_Device.Clear( m_Tex_LobeHistogram_Reflected_Decimal, float4.Zero );	// Clear counters
            m_Device.Clear( m_Tex_LobeHistogram_Reflected_Integer, float4.Zero );
            m_Device.Clear( m_Tex_LobeHistogram_Transmitted_Decimal, float4.Zero );	// Clear counters
            m_Device.Clear( m_Tex_LobeHistogram_Transmitted_Integer, float4.Zero );

            WMath.Hammersley	pRNG = new WMath.Hammersley();
            double[,]			sequence = pRNG.BuildSequence( _iterationsCount, 2 );
            for ( int iterationIndex=0; iterationIndex < _iterationsCount; iterationIndex++ ) {
                // 1] Ray-trace surface
                switch ( m_lastComputedSurfaceType ) {
                    case SURFACE_TYPE.CONDUCTOR:
                        if ( m_Shader_RayTraceSurface_Conductor.Use() ) {
                            // Update trace offset
                            m_CB_RayTrace.m._Offset.Set( (float) sequence[iterationIndex,0], (float) sequence[iterationIndex,1] );
                            m_CB_RayTrace.UpdateData();

                            m_Device.Clear( m_Tex_OutgoingDirections_Reflected, float4.Zero );	// Clear target directions and weights

                            m_Tex_Heightfield.SetCS( 0 );
                            m_Tex_Random.SetCS( 1 );
                            m_Tex_OutgoingDirections_Reflected.SetCSUAV( 0 );	// New target buffer where to accumulate

                            m_Shader_RayTraceSurface_Conductor.Dispatch( HEIGHTFIELD_SIZE >> 4, HEIGHTFIELD_SIZE >> 4, 1 );

                            m_Tex_OutgoingDirections_Reflected.RemoveFromLastAssignedSlotUAV();
                        }

                        // 2] Accumulate into target histogram
                        if ( m_Shader_AccumulateOutgoingDirections.Use() ) {
                            m_Tex_OutgoingDirections_Reflected.SetCS( 0 );
                            m_Tex_LobeHistogram_Reflected_Decimal.SetCSUAV( 0 );
                            m_Tex_LobeHistogram_Reflected_Integer.SetCSUAV( 1 );

                            m_Shader_AccumulateOutgoingDirections.Dispatch( HEIGHTFIELD_SIZE >> 4, HEIGHTFIELD_SIZE >> 4, MAX_SCATTERING_ORDER );

             							m_Tex_LobeHistogram_Reflected_Decimal.RemoveFromLastAssignedSlotUAV();
             							m_Tex_LobeHistogram_Reflected_Integer.RemoveFromLastAssignedSlotUAV();
                            m_Tex_OutgoingDirections_Reflected.RemoveFromLastAssignedSlots();
                        }
                        break;

                    case SURFACE_TYPE.DIELECTRIC:
                        if ( m_Shader_RayTraceSurface_Dielectric.Use() ) {
                            // Update trace offset
                            m_CB_RayTrace.m._Offset.Set( (float) sequence[iterationIndex,0], (float) sequence[iterationIndex,1] );
                            m_CB_RayTrace.UpdateData();

                            m_Device.Clear( m_Tex_OutgoingDirections_Reflected, float4.Zero );		// Clear target directions and weights
                            m_Device.Clear( m_Tex_OutgoingDirections_Transmitted, float4.Zero );	// Clear target directions and weights

                            m_Tex_Heightfield.SetCS( 0 );
                            m_Tex_Random.SetCS( 1 );
                            m_Tex_OutgoingDirections_Reflected.SetCSUAV( 0 );	// New target buffer where to accumulate
                            m_Tex_OutgoingDirections_Transmitted.SetCSUAV( 1 );	// New target buffer where to accumulate

                            m_Shader_RayTraceSurface_Dielectric.Dispatch( HEIGHTFIELD_SIZE >> 4, HEIGHTFIELD_SIZE >> 4, 1 );

                            m_Tex_OutgoingDirections_Reflected.RemoveFromLastAssignedSlotUAV();
                            m_Tex_OutgoingDirections_Transmitted.RemoveFromLastAssignedSlotUAV();
                        }

                        // 2] Accumulate into target histogram
                        if ( m_Shader_AccumulateOutgoingDirections.Use() ) {
                            // Accumulated reflections
                            m_Tex_OutgoingDirections_Reflected.SetCS( 0 );
                            m_Tex_LobeHistogram_Reflected_Decimal.SetCSUAV( 0 );
                            m_Tex_LobeHistogram_Reflected_Integer.SetCSUAV( 1 );

                            m_Shader_AccumulateOutgoingDirections.Dispatch( HEIGHTFIELD_SIZE >> 4, HEIGHTFIELD_SIZE >> 4, MAX_SCATTERING_ORDER );

             							m_Tex_LobeHistogram_Reflected_Decimal.RemoveFromLastAssignedSlotUAV();
             							m_Tex_LobeHistogram_Reflected_Integer.RemoveFromLastAssignedSlotUAV();
                            m_Tex_OutgoingDirections_Reflected.RemoveFromLastAssignedSlots();

                            // Accumulated transmissions
                            m_Tex_OutgoingDirections_Transmitted.SetCS( 0 );
                            m_Tex_LobeHistogram_Transmitted_Decimal.SetCSUAV( 0 );
                            m_Tex_LobeHistogram_Transmitted_Integer.SetCSUAV( 1 );

                            m_Shader_AccumulateOutgoingDirections.Dispatch( HEIGHTFIELD_SIZE >> 4, HEIGHTFIELD_SIZE >> 4, MAX_SCATTERING_ORDER );

             							m_Tex_LobeHistogram_Transmitted_Decimal.RemoveFromLastAssignedSlotUAV();
             							m_Tex_LobeHistogram_Transmitted_Integer.RemoveFromLastAssignedSlotUAV();
                            m_Tex_OutgoingDirections_Transmitted.RemoveFromLastAssignedSlots();
                        }
                        break;

                    case SURFACE_TYPE.DIFFUSE:
                        if ( m_Shader_RayTraceSurface_Diffuse.Use() ) {
                            // Update trace offset
                            m_CB_RayTrace.m._Offset.Set( (float) sequence[iterationIndex,0], (float) sequence[iterationIndex,1] );
                            m_CB_RayTrace.UpdateData();

                            m_Device.Clear( m_Tex_OutgoingDirections_Reflected, float4.Zero );	// Clear target directions and weights

                            m_Tex_Heightfield.SetCS( 0 );
                            m_Tex_Random.SetCS( 1 );
                            m_Tex_OutgoingDirections_Reflected.SetCSUAV( 0 );	// New target buffer where to accumulate

                            m_Shader_RayTraceSurface_Diffuse.Dispatch( HEIGHTFIELD_SIZE >> 4, HEIGHTFIELD_SIZE >> 4, 1 );

                            m_Tex_OutgoingDirections_Reflected.RemoveFromLastAssignedSlotUAV();
                        }

                        // 2] Accumulate into target histogram
                        if ( m_Shader_AccumulateOutgoingDirections.Use() ) {
                            m_Tex_OutgoingDirections_Reflected.SetCS( 0 );
                            m_Tex_LobeHistogram_Reflected_Decimal.SetCSUAV( 0 );
                            m_Tex_LobeHistogram_Reflected_Integer.SetCSUAV( 1 );

                            m_Shader_AccumulateOutgoingDirections.Dispatch( HEIGHTFIELD_SIZE >> 4, HEIGHTFIELD_SIZE >> 4, MAX_SCATTERING_ORDER );

             							m_Tex_LobeHistogram_Reflected_Decimal.RemoveFromLastAssignedSlotUAV();
             							m_Tex_LobeHistogram_Reflected_Integer.RemoveFromLastAssignedSlotUAV();
                            m_Tex_OutgoingDirections_Reflected.RemoveFromLastAssignedSlots();
                        }
                        break;

                    default:
                        throw new Exception( "Not implemented!" );
                }
            }

            // 3] Finalize
            if ( m_Shader_FinalizeOutgoingDirections.Use() ) {
                m_Tex_LobeHistogram_Reflected_Decimal.SetCSUAV( 0 );
             				m_Tex_LobeHistogram_Reflected_Integer.SetCSUAV( 1 );
                m_Tex_LobeHistogram_Reflected.SetCSUAV( 2 );

                m_CB_Finalize.m._IterationsCount = (uint) _iterationsCount;
                m_CB_Finalize.UpdateData();

                m_Shader_FinalizeOutgoingDirections.Dispatch( (LOBES_COUNT_PHI + 15) >> 4, (LOBES_COUNT_THETA + 15) >> 4, MAX_SCATTERING_ORDER );

             				m_Tex_LobeHistogram_Reflected_Decimal.RemoveFromLastAssignedSlotUAV();
             				m_Tex_LobeHistogram_Reflected_Integer.RemoveFromLastAssignedSlotUAV();
                m_Tex_LobeHistogram_Reflected.RemoveFromLastAssignedSlotUAV();

                if ( m_lastComputedSurfaceType == SURFACE_TYPE.DIELECTRIC ) {
                    // Finalize transmitted
                    m_Tex_LobeHistogram_Transmitted_Decimal.SetCSUAV( 0 );
             					m_Tex_LobeHistogram_Transmitted_Integer.SetCSUAV( 1 );
                    m_Tex_LobeHistogram_Transmitted.SetCSUAV( 2 );

                    m_Shader_FinalizeOutgoingDirections.Dispatch( (LOBES_COUNT_PHI + 15) >> 4, (LOBES_COUNT_THETA + 15) >> 4, MAX_SCATTERING_ORDER );

             					m_Tex_LobeHistogram_Transmitted_Decimal.RemoveFromLastAssignedSlotUAV();
             					m_Tex_LobeHistogram_Transmitted_Integer.RemoveFromLastAssignedSlotUAV();
                    m_Tex_LobeHistogram_Transmitted.RemoveFromLastAssignedSlotUAV();
                } else {
                    m_Device.Clear( m_Tex_LobeHistogram_Transmitted, float4.Zero );
                }
            }
        }
Example #6
0
		void	ComputeBRDFIntegralImportanceSampling( System.IO.FileInfo _TableFileName0, System.IO.FileInfo _TableFileName1, int _TableSize ) {

			const int		SAMPLES_COUNT = 1024;

			double[,]		Table0 = new double[_TableSize,_TableSize];
			double[,]		Table1 = new double[_TableSize,_TableSize];

			WMath.Hammersley	QRNG = new WMath.Hammersley();
			double[,]			Sequence = QRNG.BuildSequence( SAMPLES_COUNT, 2 );

			float3	View = new float3();
			float3	Light = new float3();
			float3	Half = new float3();
			for ( int Y=0; Y < _TableSize; Y++ ) {
				double	Roughness = Math.Max( 0.01f, (float) Y / (_TableSize-1) );


//Roughness = Math.Pow( 1.0 - Roughness, 4.0 );


				double	r2 = Roughness*Roughness;

				for ( int X=0; X < _TableSize; X++ ) {
					float	CosThetaView = (float) (1+X) / _TableSize;
					float	SinThetaView = (float) Math.Sqrt( 1.0f - CosThetaView*CosThetaView );
					View.x = SinThetaView;
					View.y = CosThetaView;
					View.z = 0.0f;

					double	SumA = 0.0;
					double	SumB = 0.0;
					for ( int SampleIndex=0; SampleIndex < SAMPLES_COUNT; SampleIndex++ ) {

						double	X0 = Sequence[SampleIndex,0];
						double	X1 = Sequence[SampleIndex,1];

						double	PhiH = 2.0 * Math.PI * X0;

						// WARD
						double	ThetaH = Math.Atan( -r2 * Math.Log( 1.0 - X1 ) );
						double	CosThetaH = Math.Cos( ThetaH );
						double	SinThetaH = Math.Sin( ThetaH );

// 						// GGX
// 						double	a = r2;
// 						double	CosThetaH = Math.Sqrt( (1.0 - X1) / (1.0 + (a*a - 1.0) * X1 ) );
// 						double	SinThetaH = Math.Sqrt( 1.0f - CosThetaH * CosThetaH );


						double	CosPhiH = Math.Cos( PhiH );
						double	SinPhiH = Math.Sin( PhiH );

						Half.x = (float) (SinPhiH * SinThetaH);
						Half.y = (float) CosThetaH;
						Half.z = (float) (CosPhiH * SinThetaH);

 						Light = 2.0f * View.Dot( Half ) * Half - View;	// Light is on the other size of the Half vector...


// Intuitively, we should have the same result if we sampled around the reflected view direction
// 						float3	ReflectedView = 2.0f * View.Dot( float3.UnitY ) * float3.UnitY - View;
// 						float3	OrthoY = ReflectedView.Cross( float3.UnitZ ).Normalized;
// 						float3	OrthoX = float3.UnitZ;
//  						Light = Half.x * OrthoX + Half.y * ReflectedView + Half.z * OrthoY;
// 
// 						Half = (View + Light).Normalized;


						if ( Light.y <= 0 )
							continue;

						double	HoN = Half.y;
						double	HoN2 = HoN*HoN;
						double	HoV = Half.Dot( View );
//						float	HoV = Half.x * View.x + Half.y * View.y;	// We know that Z=0 here...
						double	HoL = Half.Dot( Light );
						double	NoL = Light.y;
						double	NoV = View.y;

 						// Apply sampling weight for correct distribution
 						double	SampleWeight = 2.0 / (1.0 + View.y / Light.y);
 						double	BRDF = SampleWeight;





// Try with Unreal's GGX & Smith G term to see if we get the same thing
// 
// 	// GGX NDF
// // double	alpha = r2;
// // double	alpha2 = alpha*alpha;
// // double	D = alpha2 / (Math.PI * Math.Pow( HoN2*(alpha2 - 1.0) + 1.0, 2.0 ));
// 
// 	// Smith masking/shadowing
// double	k = (Roughness + 1)*(Roughness + 1) / 8.0;
// double	Gl = NoL / (NoL * (1-k) + k);
// double	Gv = NoV / (NoV * (1-k) + k);
// double	G = Gl * Gv;
// 
// //double	BRDF = G / (4.0 * View.y);
// //double	BRDF = G * HoV / (HoN * NoV);
// double	BRDF = NoL * GSmith( Roughness, NoV, NoL ) * 4.0f * HoV / HoN;




						// Compute Fresnel terms
						double	Schlick = 1.0 - HoV;
						double	Schlick5 = Schlick * Schlick;
								Schlick5 *= Schlick5 * Schlick;

						double	FresnelA = 1.0f - Schlick5;
						double	FresnelB = Schlick5;

//FresnelA = FresnelB = 1.0;

						SumA += FresnelA * BRDF;
						SumB += FresnelB * BRDF;
					}

// 					SumA *= 1.0 / (SAMPLES_COUNT * Math.PI * r2);
// 					SumB *= 1.0 / (SAMPLES_COUNT * Math.PI * r2);

					SumA /= SAMPLES_COUNT;
					SumB /= SAMPLES_COUNT;

					// For few samples, the sum goes over 1 because we have poor solid angle sampling resolution...
// 					SumA = Math.Min( 1.0, SumA );
// 					SumB = Math.Min( 1.0, SumB );

					Table0[X,Y] = SumA;
					Table1[X,Y] = SumB;
				}
			}

			// Write table 0
			using ( System.IO.FileStream S = _TableFileName0.Create() )
				using ( System.IO.BinaryWriter W = new System.IO.BinaryWriter( S ) )
					for ( int Y=0; Y < _TableSize; Y++ ) {
						for ( int X=0; X < _TableSize; X++ )
							W.Write( Table0[X,Y] );
						}

			// Write table 1
			using ( System.IO.FileStream S = _TableFileName1.Create() )
				using ( System.IO.BinaryWriter W = new System.IO.BinaryWriter( S ) )
					for ( int Y=0; Y < _TableSize; Y++ ) {
						for ( int X=0; X < _TableSize; X++ )
							W.Write( Table1[X,Y] );
						}
		}