示例#1
0
        const int SAMPLES_COUNT = 50;                                   // Number of samples used to compute the average terms

        // compute the average direction of the BRDF
        public void     ComputeAverageTerms(IBRDF _BRDF, ref float3 _tsView, float _alpha)
        {
            magnitude = 0.0;
            fresnel   = 0.0;
            Z         = float3.Zero;
            error     = 0.0;

            double weight, pdf, eval;
            float3 tsLight = float3.Zero;
            float3 H       = float3.Zero;

            for (int j = 0; j < SAMPLES_COUNT; ++j)
            {
                for (int i = 0; i < SAMPLES_COUNT; ++i)
                {
                    float U1 = (i + 0.5f) / SAMPLES_COUNT;
                    float U2 = (j + 0.5f) / SAMPLES_COUNT;

                    // sample
                    _BRDF.GetSamplingDirection(ref _tsView, _alpha, U1, U2, ref tsLight);

                    // eval
                    eval = _BRDF.Eval(ref _tsView, ref tsLight, _alpha, out pdf);
                    if (pdf == 0.0f)
                    {
                        continue;
                    }

                    H = (_tsView + tsLight).Normalized;

                    // accumulate
                    weight = eval / pdf;
                    if (double.IsNaN(weight))
                    {
                        throw new Exception("NaN!");
                    }

                    magnitude += weight;
                    fresnel   += weight * Math.Pow(1 - Math.Max(0.0f, _tsView.Dot(H)), 5.0);
                    Z         += (float)weight * tsLight;
                }
            }
            magnitude /= SAMPLES_COUNT * SAMPLES_COUNT;
            fresnel   /= SAMPLES_COUNT * SAMPLES_COUNT;

            // Finish building the average TBN orthogonal basis
            Z.y = 0.0f;                         // clear y component, which should be zero with isotropic BRDFs
            float length = Z.Length;

            if (length > 0.0f)
            {
                Z /= length;
            }
            else
            {
                Z = float3.UnitZ;
            }
            X.Set(Z.z, 0, -Z.x);
            Y = float3.UnitY;
        }
示例#2
0
                public void             Read(BinaryReader _R)
                {
                    m_index     = _R.ReadInt32();
                    m_isValid   = _R.ReadBoolean();
                    m_isNatural = _R.ReadBoolean();
                    m_isClosing = _R.ReadBoolean();
                    m_wsPosition.Set(_R.ReadSingle(), _R.ReadSingle(), _R.ReadSingle());
                    m_wsNormal.Set(_R.ReadSingle(), _R.ReadSingle(), _R.ReadSingle());
                    m_wsCenter.Set(_R.ReadSingle(), _R.ReadSingle(), _R.ReadSingle());

                    m_lines.Clear();
                    m_removedLines.Clear();

                    int linesCount = _R.ReadInt32();

                    for (int lineIndex = 0; lineIndex < linesCount; lineIndex++)
                    {
                        line_t L = new line_t(this);
                        m_lines.Add(L);
                        L.Read(_R);
                    }

                    int removedLinesCount = _R.ReadInt32();

                    for (int removedLinesIndex = 0; removedLinesIndex < removedLinesCount; removedLinesIndex++)
                    {
                        line_t L = new line_t(this);
                        m_removedLines.Add(L);
                        L.Read(_R);
                    }
                }
示例#3
0
        // Build orthonormal basis from a 3D Unit Vector Without normalization [Frisvad2012])
        void BuildOrthonormalBasis(float3 _normal, ref float3 _tangent, ref float3 _bitangent)
        {
            float a = _normal.z > -0.9999999f ? 1.0f / (1.0f + _normal.z) : 0.0f;
            float b = -_normal.x * _normal.y * a;

            _tangent.Set(1.0f - _normal.x * _normal.x * a, b, -_normal.x);
            _bitangent.Set(b, 1.0f - _normal.y * _normal.y * a, -_normal.y);
        }
示例#4
0
 public void     Load(System.IO.BinaryReader _R)
 {
     albedo.Set(_R.ReadSingle(), _R.ReadSingle(), _R.ReadSingle());
     opacity = _R.ReadSingle();
     normal.Set(_R.ReadSingle(), _R.ReadSingle(), _R.ReadSingle());
     variance            = _R.ReadSingle();
     accumulationCounter = _R.ReadInt32();
 }
示例#5
0
 public OctreeNode(System.IO.BinaryReader _R)
 {
     m_wsCornerMin.Set(_R.ReadSingle(), _R.ReadSingle(), _R.ReadSingle());
     m_size     = _R.ReadSingle();
     m_halfSize = 0.5f * m_size;
     m_level    = 0;
     Load(_R);
 }
示例#6
0
        // Sets the resolution of the grid cells by which the positions are descretized
        public void                     SetGridCellSize(float3 _cellSize)
        {
            if (_cellSize.x < 1e-6f || _cellSize.y < 1e-6f || _cellSize.z < 1e-6f)
            {
                throw new Exception("Cell size is too small!");
            }

            m_cellSize = _cellSize;
            m_invCellSize.Set(1.0f / _cellSize.x, 1.0f / _cellSize.y, 1.0f / _cellSize.z);
        }
示例#7
0
            public void             Read(BinaryReader _R)
            {
                m_wsPosition.Set(_R.ReadSingle(), _R.ReadSingle(), _R.ReadSingle());

                m_planes.Clear();
                int planesCount = _R.ReadInt32();

                for (int planeIndex = 0; planeIndex < planesCount; planeIndex++)
                {
                    plane_t P = new plane_t(this);
                    m_planes.Add(P);
                    P.Read(_R);
                }
            }
示例#8
0
                    public void             Read(BinaryReader _R)
                    {
                        m_wsPosition.Set(_R.ReadSingle(), _R.ReadSingle(), _R.ReadSingle());
                        m_wsDirection.Set(_R.ReadSingle(), _R.ReadSingle(), _R.ReadSingle());
                        m_wsOrthoDirection.Set(_R.ReadSingle(), _R.ReadSingle(), _R.ReadSingle());

                        m_vertices[0].Read(_R);
                        m_vertices[1].Read(_R);

                        m_planeIndices[0] = _R.ReadUInt32();
                        m_planeIndices[1] = _R.ReadUInt32();

                        m_clipperPlaneIndex = _R.ReadUInt32();
                    }
示例#9
0
        void    LoadNormalMap(System.IO.FileInfo _normalMapFileName)
        {
            try {
                ImageFile tempImageNormal = new ImageFile(_normalMapFileName);

                // Make sure we accept the image
                double isPOT = Math.Log(tempImageNormal.Width) / Math.Log(2.0);
                if (tempImageNormal.Width != tempImageNormal.Height ||
                    (int)isPOT != isPOT)
                {
                    throw new Exception("The converter only supports square power-of-two textures!\r\nThis image is " + tempImageNormal.Width + "x" + tempImageNormal.Height);
                }

                // Replace existing
                if (m_imageNormal != null)
                {
                    m_imageNormal.Dispose();
                    m_imageNormal = null;
                }
                m_imageNormal = tempImageNormal;

                imagePanelNormal.Bitmap = m_imageNormal.AsBitmap;

                // Read normals
                m_size = m_imageNormal.Width;
                nx     = new Complex[m_size, m_size];
                ny     = new Complex[m_size, m_size];

                const float pipo = 1.0f;                        // Amplification test => no real change!

                float3 normal = float3.Zero;
                m_imageNormal.ReadPixels((uint X, uint Y, ref float4 _color) => {
                    normal.Set(pipo * (2.0f * _color.x - 1.0f), pipo * (2.0f * _color.y - 1.0f), 2.0f * _color.z - 1.0f);
                    normal.Normalize();

                    double fact = normal.z != 0.0 ? 1.0 / normal.z : 0.0;
                    nx[X, Y].Set(fact * normal.x, 0);
                    ny[X, Y].Set(fact * normal.y, 0);
                });

                // Enable conversion
                buttonConvert.Enabled         = true;
                buttonConvertOneSided.Enabled = true;
            } catch (Exception _e) {
                MessageBox("An error occurred while loading the normal map:\r\n\r\n" + _e.Message, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
示例#10
0
        public Line3DCollider(float3 v1, float3 v2, ColliderInfo info) : this()
        {
            _header.Init(info, ColliderType.Line3D);

            var vLine = math.normalize(v2 - v1);

            // Axis of rotation to make 3D cylinder a cylinder along the z-axis
            var transAxis = new float3(vLine.y, -vLine.x, 0.0f);

            var l = math.lengthsq(transAxis);

            // line already points in z axis?
            if (l <= 1e-6f)
            {
                // choose arbitrary rotation vector
                transAxis.Set(1, 0f, 0f);
            }
            else
            {
                transAxis /= math.sqrt(l);
            }

            // Angle to rotate the line into the z-axis
            var dot = vLine.z;

            _matrix = new float3x3();
            _matrix.RotationAroundAxis(transAxis, -math.sqrt(1 - dot * dot), dot);

            var trans1  = math.mul(_matrix, v1);
            var trans2Z = math.mul(_matrix, v2).z;

            // set up HitLineZ parameters
            _xy.x  = trans1.x;
            _xy.y  = trans1.y;
            _zLow  = math.min(trans1.z, trans2Z);
            _zHigh = math.max(trans1.z, trans2Z);

            Bounds = new ColliderBounds(_header.Entity, _header.Id, new Aabb(
                                            math.min(v1.x, v2.x),
                                            math.max(v1.x, v2.x),
                                            math.min(v1.y, v2.y),
                                            math.max(v1.y, v2.y),
                                            math.min(v1.z, v2.z),
                                            math.max(v1.z, v2.z)
                                            ));
        }
示例#11
0
        /// <summary>
        /// Should always return something close to 1
        /// </summary>
        /// <returns></returns>
        public double   TestNormalization()
        {
            double sum    = 0;
            float  dtheta = 0.005f;
            float  dphi   = 0.025f;
            float3 L      = new float3();

            for (float theta = 0.0f; theta <= Mathf.PI; theta += dtheta)
            {
                for (float phi = 0.0f; phi <= Mathf.PI; phi += dphi)
                {
                    L.Set(Mathf.Sin(theta) * Mathf.Cos(phi), Mathf.Sin(theta) * Mathf.Sin(phi), Mathf.Cos(theta));
                    sum += Mathf.Sin(theta) * Eval(ref L);
                }
            }
            sum *= dtheta * 2 * dphi;
            return(sum);
        }
示例#12
0
        /// <summary>
        /// Initializes the array of data we need to fit with the lobe model
        /// Computes the Center of Mass of the lobe
        /// </summary>
        /// <param name="_texHistogram_CPU"></param>
        /// <param name="_scatteringOrder"></param>
        public void             InitTargetData(double[,] _histogramData)
        {
            m_histogramData = _histogramData;
            W = m_histogramData.GetLength(0);
            H = m_histogramData.GetLength(1);

            // Compute center of mass from which we'll measure distances
            m_centerOfMass = float3.Zero;
            float3 wsOutgoingDirection = float3.Zero;

            for (int Y = 0; Y < H; Y++)
            {
                // Y = theta bin index = 2.0 * LOBES_COUNT_THETA * pow2( sin( 0.5 * theta ) )
                // We need theta:
                double theta    = 2.0 * Math.Asin(Math.Sqrt(0.5 * Y / H));
                double cosTheta = Math.Cos(theta);
                double sinTheta = Math.Sin(theta);

                for (int X = 0; X < W; X++)
                {
                    // X = phi bin index = LOBES_COUNT_PHI * X / (2PI)
                    // We need phi:
                    double phi    = 2.0 * Math.PI * X / W;
                    double cosPhi = Math.Cos(phi);
                    double sinPhi = Math.Sin(phi);

                    // Build simulated microfacet reflection direction in macro-surface space
                    double outgoingIntensity = m_histogramData[X, Y];
                    wsOutgoingDirection.Set((float)(outgoingIntensity * cosPhi * sinTheta), (float)(outgoingIntensity * sinPhi * sinTheta), (float)(outgoingIntensity * cosTheta));

                    // Accumulate lobe position
                    m_centerOfMass += wsOutgoingDirection;
                }
            }
            m_centerOfMass /= W * H;
        }
示例#13
0
        /// <summary>
        /// This code tests the determinant of the transform matrices that rectify a
        /// </summary>
        void    CheckMatrix()
        {
            const int COUNT_RADIUS = 10;
            const int COUNT_X      = 10;
            const int COUNT_Y      = 10;
            const int COUNT_Z      = 10;

            const float Xmax = 10.0f;
            const float Ymax = 10.0f;
            const float Zmax = 4.0f;
            const float Rb   = 2.0f;

            float3 P0 = float3.Zero;
            float3 T  = new float3(1, 0, 0);
            float3 B  = new float3(0, 1, 0);
            float3 N  = new float3(0, 0, 1);

//			float3	Nt, Nb, Tn, Bn, Dtn, Dbn;

//			float4		P  = float4.UnitW, Pt;
//			float4x4	M = new float4x4();

            float3   P, Pt;
            float3x3 M     = new float3x3();
            float3x3 M2    = new float3x3();
            float3x3 invM  = new float3x3();
            float3x3 invM2 = new float3x3();

            float det, illuminance;
//			float	depth;

            List <float[, , ]> determinantss = new List <float[, , ]>(COUNT_RADIUS);

//			for ( int radiusIndex=0; radiusIndex < COUNT_RADIUS; radiusIndex++ )
            int radiusIndex = 10;
            {
                float[,,]       determinants = new float[COUNT_Z, 1 + 2 * COUNT_Y, 1 + 2 * COUNT_X];
                determinantss.Add(determinants);

                float radiusFactor = Mathf.Max(0.01f, 2.0f * radiusIndex / 100);
                float Rt           = radiusFactor * Rb;

                T.Set(Rt, 0, 0);
                B.Set(0, Rb, 0);

                for (int Z = COUNT_Z; Z > 0; Z--)
                {
                    P0.z = Zmax * Z / COUNT_Z;
                    for (int Y = -COUNT_Y; Y <= COUNT_Y; Y++)
                    {
                        P0.y = Ymax * Y / COUNT_Y;
                        for (int X = -COUNT_X; X <= COUNT_X; X++)
                        {
                            P0.x = Xmax * X / COUNT_X;

#if true
                            // Matrix is a simple slanted parallelogram
                            M.r0 = (T - (P0.Dot(T) / P0.Dot(N)) * N) / (Rt * Rt);
                            M.r1 = (B - (P0.Dot(B) / P0.Dot(N)) * N) / (Rb * Rb);
                            M.r2 = N / P0.Dot(N);

                            invM = M.Inverse;

                            det = M.Determinant;

                            // Construct inverse directly
                            invM2.r0.Set(T.x, B.x, P0.x);
                            invM2.r1.Set(T.y, B.y, P0.y);
                            invM2.r2.Set(T.z, B.z, P0.z);

                            M2 = invM2.Inverse;

                            // Test matrix is working
                            P  = P0;
                            Pt = M * P;
                            P  = T;
                            Pt = M * P;
                            P  = -T;
                            Pt = M * P;
                            P  = B;
                            Pt = M * P;
                            P  = -B;
                            Pt = M * P;
                            P  = float3.Lerp(0.5f * T - 0.25f * B, 0.5f * T - 0.25f * B + P0, 0.666f);
                            Pt = M * P;

//                          invM *= M;
//                          invM2 *= M2;

                            // Test lighting computation

                            // Build rectangular area light corners in local space
                            float3   lsAreaLightPosition = P0;
                            float3[] lsLightCorners      = new float3[4];
                            lsLightCorners[0] = lsAreaLightPosition + T + B;
                            lsLightCorners[1] = lsAreaLightPosition + T - B;
                            lsLightCorners[2] = lsAreaLightPosition - T - B;
                            lsLightCorners[3] = lsAreaLightPosition - T + B;

                            float3x3 world2TangentSpace = float3x3.Identity;                                    // Assume we're already in tangent space

                            // Transform them into tangent-space
                            float3[] tsLightCorners = new float3[4];
                            tsLightCorners[0] = lsLightCorners[0] * world2TangentSpace;
                            tsLightCorners[1] = lsLightCorners[1] * world2TangentSpace;
                            tsLightCorners[2] = lsLightCorners[2] * world2TangentSpace;
                            tsLightCorners[3] = lsLightCorners[3] * world2TangentSpace;

                            // Compute diffuse disk
                            illuminance = DiskIrradiance(tsLightCorners);
#else
// Stupid version where I still thought we needed a perspective projection matrix!
                            depth = P0.Dot(N);                                  // Altitude from plane
                            Nt    = P0.Dot(T) * N;
                            Nb    = P0.Dot(B) * N;
                            Tn    = P0.Dot(N) * T;                              // = depth * T
                            Bn    = P0.Dot(N) * B;                              // = depth * B

#if true
                            M.r0.Set((Tn - Nt) / Rt, 0);
                            M.r1.Set((Bn - Nb) / Rb, 0);
                            M.r2.Set(0, 0, 1, 0);
                            M.r3.Set(-N, depth);
#else
                            Dtn = (Nt - Tn) / Rt;
                            Dbn = (Nb - Bn) / Rb;

                            M.r0.Set(Dtn, -P0.Dot(Dtn));
                            M.r1.Set(Dbn, -P0.Dot(Dbn));
                            M.r2.Set(N / depth, 0.0f);                                          // Will normalize Z to 1 if P is at same altitude as P0
                            M.r3.Set(N, -P0.Dot(N));                                            // Here, use "depth"
#endif
                            det = M.Determinant;

                            determinants[Z - 1, COUNT_Y + Y, COUNT_X + X] = det;

                            // Test matrix is working
                            P.Set(P0, 1);
                            Pt = M * P;
//							Pt /= Pt.w;	// This will NaN because W=0 in this particular case
                            P.Set(Rt * T, 1);
                            Pt  = M * P;
                            Pt /= Pt.w;
                            P.Set(-Rt * T, 1);
                            Pt  = M * P;
                            Pt /= Pt.w;
                            P.Set(Rb * B, 1);
                            Pt  = M * P;
                            Pt /= Pt.w;
                            P.Set(-Rb * B, 1);
                            Pt  = M * P;
                            Pt /= Pt.w;
                            P.Set(float3.Lerp(0.5f * Rt * T - 0.25f * Rb * B, P0, 0.666f), 1);
                            Pt  = M * P;
                            Pt /= Pt.w;
#endif
                        }
                    }
                }
            }
        }
示例#14
0
文件: Form1.cs 项目: vr3d/GodComplex
        private void buttonShootPhotons_Click(object sender, EventArgs e)
        {
            //////////////////////////////////////////////////////////////////////////
            // 1] Build initial photon positions and directions
            float3 SunDirection = new float3(0, 1, 0).Normalized;

            uint InitialDirection = PackPhotonDirection(-SunDirection);
            uint InitialColor     = EncodeRGBE(new float3(1.0f, 1.0f, 1.0f));

            int   PhotonsPerSize     = (int)Math.Floor(Math.Sqrt(PHOTONS_COUNT));
            float PhotonCoverageSize = CLOUDSCAPE_SIZE / PhotonsPerSize;

            for (int PhotonIndex = 0; PhotonIndex < PHOTONS_COUNT; PhotonIndex++)
            {
                int Z = PhotonIndex / PhotonsPerSize;
                int X = PhotonIndex - Z * PhotonsPerSize;

                float x = ((X + (float)SimpleRNG.GetUniform()) / PhotonsPerSize - 0.5f) * CLOUDSCAPE_SIZE;
                float z = ((Z + (float)SimpleRNG.GetUniform()) / PhotonsPerSize - 0.5f) * CLOUDSCAPE_SIZE;

                m_SB_Photons.m[PhotonIndex].Position.Set(x, z);
                m_SB_Photons.m[PhotonIndex].Direction = InitialDirection;
                m_SB_Photons.m[PhotonIndex].RGBE      = InitialColor;

#if DEBUG_INFOS
                m_SB_Photons.m[PhotonIndex].Infos.Set(0, 0, 0, 0);                      // Will store scattering events counter, marched length, steps count, etc.
#endif
            }
            m_SB_Photons.Write();


            //////////////////////////////////////////////////////////////////////////
            // 2] Initialize layers & textures

            // 2.1) Fill source bucket with all photons
            for (int PhotonIndex = 0; PhotonIndex < PHOTONS_COUNT; PhotonIndex++)
            {
                m_SB_PhotonLayerIndices.m[PhotonIndex] = 0U;                    // Starting from top layer, direction is down
            }
            m_SB_PhotonLayerIndices.Write();

            // 2.2) Clear photon splatting texture
            m_Device.Clear(m_Tex_PhotonLayers_Flux, new float4(0, 0, 0, 0));
            m_Device.Clear(m_Tex_PhotonLayers_Direction, new float4(0, 0, 0, 0));


            //////////////////////////////////////////////////////////////////////////
            // 3] Prepare buffers & states

            m_CloudScapeSize.Set(CLOUDSCAPE_SIZE, floatTrackbarControlCloudscapeThickness.Value, CLOUDSCAPE_SIZE);

            // 3.1) Prepare density field
            m_Tex_DensityField.SetCS(2);

            // 3.2) Constant buffer for photon shooting
            m_CB_PhotonShooterInput.m.LayersCount     = LAYERS_COUNT;
            m_CB_PhotonShooterInput.m.MaxScattering   = 30;
            m_CB_PhotonShooterInput.m.LayerThickness  = m_CloudScapeSize.y / LAYERS_COUNT;
            m_CB_PhotonShooterInput.m.SigmaScattering = floatTrackbarControlSigmaScattering.Value;              // 0.04523893421169302263386206471922f;	// re=6µm Gamma=2 N0=4e8   Sigma_t = N0 * PI * re²
            m_CB_PhotonShooterInput.m.CloudScapeSize  = m_CloudScapeSize;

            // 3.3) Prepare photon splatting buffer & states
            m_CB_SplatPhoton.m.CloudScapeSize = m_CloudScapeSize;
            m_CB_SplatPhoton.m.SplatSize      = 1.0f * (2.0f / m_Tex_PhotonLayers_Flux.Width);
            m_CB_SplatPhoton.m.SplatIntensity = 1.0f;                                                                // 1000.0f / PHOTONS_COUNT;

            m_Device.SetRenderStates(RASTERIZER_STATE.CULL_NONE, DEPTHSTENCIL_STATE.DISABLED, BLEND_STATE.ADDITIVE); // Splatting is additive
            m_Tex_PhotonLayers_Flux.RemoveFromLastAssignedSlots();
            m_Tex_PhotonLayers_Direction.RemoveFromLastAssignedSlots();


            //////////////////////////////////////////////////////////////////////////
            // 4] Splat initial photons to the top layer
            m_PS_PhotonSplatter.Use();

            m_SB_Photons.SetInput(0);                           // RO version for splatting
            m_SB_PhotonLayerIndices.SetInput(1);                // RO version for splatting

            m_CB_SplatPhoton.m.LayerIndex = 0U;
            m_CB_SplatPhoton.UpdateData();

            m_Device.SetRenderTargets(m_Tex_PhotonLayers_Flux.Width, m_Tex_PhotonLayers_Flux.Height,
                                      new View3D[] {
                m_Tex_PhotonLayers_Flux.GetView(0, 0, 0, 1),
                m_Tex_PhotonLayers_Direction.GetView(0, 0, 0, 1)
            }, null);
            m_Prim_Point.RenderInstanced(m_PS_PhotonSplatter, PHOTONS_COUNT);


            //////////////////////////////////////////////////////////////////////////
            // 5] Render loop
            int BatchesCount = PHOTONS_COUNT / PHOTON_BATCH_SIZE;

            m_SB_ProcessedPhotonsCounter.SetOutput(2);

            for (int BounceIndex = 0; BounceIndex < BOUNCES_COUNT; BounceIndex++)
            {
                // 5.1] Process every layers from top to bottom
                m_SB_ProcessedPhotonsCounter.m[0] = 0;
                m_SB_ProcessedPhotonsCounter.Write();                   // Reset processed photons counter

                for (int LayerIndex = 0; LayerIndex < LAYERS_COUNT; LayerIndex++)
                {
                    // 5.1.1) Shoot a bunch of photons from layer "LayerIndex" to layer "LayerIndex+1"
                    m_CS_PhotonShooter.Use();

                    m_CB_PhotonShooterInput.m.LayerIndex = (uint)LayerIndex;

                    m_SB_Photons.RemoveFromLastAssignedSlots();
                    m_SB_PhotonLayerIndices.RemoveFromLastAssignedSlots();

                    m_SB_Photons.SetOutput(0);
                    m_SB_PhotonLayerIndices.SetOutput(1);

                    m_SB_Random.SetInput(0);
                    m_SB_PhaseQuantile.SetInput(1);

                    for (int BatchIndex = 0; BatchIndex < BatchesCount; BatchIndex++)
                    {
                        m_CB_PhotonShooterInput.m.BatchIndex = (uint)BatchIndex;
                        m_CB_PhotonShooterInput.UpdateData();

                        m_CS_PhotonShooter.Dispatch(1, 1, 1);

                        m_Device.Present(true);

                        // Notify of progress
                        progressBar1.Value = progressBar1.Maximum * (1 + BatchIndex + BatchesCount * (LayerIndex + LAYERS_COUNT * BounceIndex)) / (BOUNCES_COUNT * LAYERS_COUNT * BatchesCount);
                        Application.DoEvents();
                    }

#if DEBUG_INFOS
//DEBUG Read back photons buffer
                    m_SB_Photons.Read();
// m_SB_PhotonLayerIndices.Read();
// Verify photons have the same energy and were indeed transported to the next layer unaffected (this test is only valid if the density field is filled with 0s)
// for ( int PhotonIndex=0; PhotonIndex < PHOTONS_COUNT; PhotonIndex++ )
// {
//  if ( m_SB_Photons.m[PhotonIndex].RGBE != 0x80FFFFFF )
//      throw new Exception( "Intensity changed!" );
//  if ( m_SB_PhotonLayerIndices.m[PhotonIndex] != LayerIndex+1 )
//      throw new Exception( "Unexpected layer index!" );
// }
//DEBUG
#endif

                    // 5.1.2) Splat the photons that got through to the 2D texture array
                    m_PS_PhotonSplatter.Use();

                    m_SB_Photons.SetInput(0);                                   // RO version for splatting
                    m_SB_PhotonLayerIndices.SetInput(1);                        // RO version for splatting

                    m_CB_SplatPhoton.m.LayerIndex = (uint)(LayerIndex + 1);
                    m_CB_SplatPhoton.UpdateData();

                    m_Device.SetRenderTargets(m_Tex_PhotonLayers_Flux.Width, m_Tex_PhotonLayers_Flux.Height,
                                              new View3D[] {
                        m_Tex_PhotonLayers_Flux.GetView(0, 0, LayerIndex + 1, 1),
                        m_Tex_PhotonLayers_Direction.GetView(0, 0, LayerIndex + 1, 1)
                    }, null);
                    m_Prim_Point.RenderInstanced(m_PS_PhotonSplatter, PHOTONS_COUNT);
                }

                m_SB_ProcessedPhotonsCounter.Read();
                if (m_SB_ProcessedPhotonsCounter.m[0] < LOW_PHOTONS_COUNT_RATIO * PHOTONS_COUNT)
                {
                    break;                      // We didn't shoot a significant number of photons to go on...
                }
                // ================================================================================
                // 5.2] Process every layers from bottom to top
                BounceIndex++;
                if (BounceIndex >= BOUNCES_COUNT)
                {
                    break;
                }

                m_SB_ProcessedPhotonsCounter.m[0] = 0;
                m_SB_ProcessedPhotonsCounter.Write();                   // Reset processed photons counter

                for (int LayerIndex = LAYERS_COUNT; LayerIndex > 0; LayerIndex--)
                {
                    // 5.2.1) Shoot a bunch of photons from layer "LayerIndex" to layer "LayerIndex-1"
                    m_CS_PhotonShooter.Use();

                    m_CB_PhotonShooterInput.m.LayerIndex = (uint)LayerIndex | 0x80000000U;                      // <= MSB indicates photons are going up

                    m_SB_Photons.RemoveFromLastAssignedSlots();
                    m_SB_PhotonLayerIndices.RemoveFromLastAssignedSlots();

                    m_SB_Photons.SetOutput(0);
                    m_SB_PhotonLayerIndices.SetOutput(1);

                    m_SB_Random.SetInput(0);
                    m_SB_PhaseQuantile.SetInput(1);

                    for (int BatchIndex = 0; BatchIndex < BatchesCount; BatchIndex++)
                    {
                        m_CB_PhotonShooterInput.m.BatchIndex = (uint)BatchIndex;
                        m_CB_PhotonShooterInput.UpdateData();

                        m_CS_PhotonShooter.Dispatch(1, 1, 1);

                        m_Device.Present(true);

                        // Notify of progress
                        progressBar1.Value = progressBar1.Maximum * (1 + BatchIndex + BatchesCount * (LayerIndex + LAYERS_COUNT * BounceIndex)) / (BOUNCES_COUNT * LAYERS_COUNT * BatchesCount);
                        Application.DoEvents();
                    }

                    // 5.2.2) Splat the photons that got through to the 2D texture array
                    m_PS_PhotonSplatter.Use();

                    m_SB_Photons.SetInput(0);                                             // RO version for splatting
                    m_SB_PhotonLayerIndices.SetInput(1);                                  // RO version for splatting

                    m_CB_SplatPhoton.m.LayerIndex = (uint)(LayerIndex - 1) | 0x80000000U; // <= MSB indicates photons are going up
                    m_CB_SplatPhoton.UpdateData();

                    m_Device.SetRenderTargets(m_Tex_PhotonLayers_Flux.Width, m_Tex_PhotonLayers_Flux.Height,
                                              new View3D[] {
                        m_Tex_PhotonLayers_Flux.GetView(0, 0, LayerIndex - 1, 0),
                        m_Tex_PhotonLayers_Direction.GetView(0, 0, LayerIndex - 1, 0)
                    }, null);
                    m_Prim_Point.RenderInstanced(m_PS_PhotonSplatter, PHOTONS_COUNT);
                }

                m_SB_ProcessedPhotonsCounter.Read();
                if (m_SB_ProcessedPhotonsCounter.m[0] < LOW_PHOTONS_COUNT_RATIO * PHOTONS_COUNT)
                {
                    break;                      // We didn't shoot a significant number of photons to go on...
                }
            }

            m_Tex_PhotonLayers_Flux.RemoveFromLastAssignedSlots();
            m_Tex_PhotonLayers_Direction.RemoveFromLastAssignedSlots();

            Render();
        }
示例#15
0
            public Surface(Model _Owner, BinaryReader _R)
            {
                m_Owner = _Owner;

                m_Material = Material.Find(m_Owner.ReadString(_R));
                int MaterialIndex = (int)m_Owner.ReadBig32(_R);                                 // Don't use that

                // Prepare triangles
                uint VerticesCount = _R.ReadUInt32();
                uint IndicesCount  = _R.ReadUInt32();

                m_Vertices = new Vertex[VerticesCount];
                m_Indices  = new ushort[IndicesCount];

                // Read vertex declaration
                int VertexElementsCount = (int)_R.ReadByte();

                m_VertexElements = new VertexElement[VertexElementsCount];
                for (int elementIndex = 0; elementIndex < VertexElementsCount; elementIndex++)
                {
                    m_VertexElements[elementIndex].Read(_R);
                }

                // Read vertex scale & bias
                float3 XYZScale = new float3(_R.ReadSingle(), _R.ReadSingle(), _R.ReadSingle());
                float3 XYZBias  = new float3(_R.ReadSingle(), _R.ReadSingle(), _R.ReadSingle());
                float2 UVScale  = new float2(_R.ReadSingle(), _R.ReadSingle());
                float2 UVBias   = new float2(_R.ReadSingle(), _R.ReadSingle());

                // Read vertices
                for (int i = 0; i < m_Vertices.Length; i++)
                {
                    Vertex V = new Vertex();
                    m_Vertices[i] = V;
                    foreach (VertexElement E in m_VertexElements)
                    {
                        E.ReadElement(_R, V);
                    }
                }

                // Read indices
                for (int i = 0; i < m_Indices.Length; i++)
                {
                    m_Indices[i] = _R.ReadUInt16();
                    if (m_Indices[i] >= m_Vertices.Length)
                    {
                        throw new Exception("Vertex index out of range!");
                    }
                }

                // Read bounds & stuff
                m_BoundsMin.Set(_R.ReadSingle(), _R.ReadSingle(), _R.ReadSingle());
                m_BoundsMax.Set(_R.ReadSingle(), _R.ReadSingle(), _R.ReadSingle());

                int detailOffset = _R.ReadInt32();

                // End
                uint TrailingMagic = m_Owner.ReadBig32(_R);

                if ((TrailingMagic & 0x00FFFFFFU) != 0x004C4D42)
                {
                    throw new Exception("Bad trailing magic!");
                }
            }
示例#16
0
        public double Eval(double[] _newParameters)
        {
            double lobeTheta         = _newParameters[0];
            double lobeRoughness     = _newParameters[1];
            double lobeGlobalScale   = _newParameters[2];
            double lobeFlatten       = _newParameters[3];
            double maskingImportance = _newParameters[4];


            // Flattening is not linear when using the anisotropic lobe model!
            if (m_lobeType == LOBE_TYPE.MODIFIED_PHONG_ANISOTROPIC)
            {
                lobeFlatten = Math.Pow(2.0, 4.0 * (lobeFlatten - 1.0));                         // in [2e-4, 2e4], log space
            }
            double invLobeFlatten = 1.0 / lobeFlatten;

            // Compute constant masking term due to incoming direction
            double maskingIncoming = Masking(m_direction.z, lobeRoughness);                             // Masking( incoming )

            // Compute lobe's reflection vector and tangent space using new parameters
            double cosTheta = Math.Cos(lobeTheta);
            double sinTheta = Math.Sin(lobeTheta);

            float3 lobe_normal    = new float3((float)(sinTheta * m_incomingDirection_CosPhi), (float)(sinTheta * m_incomingDirection_SinPhi), (float)cosTheta);
            float3 lobe_tangent   = new float3((float)-m_incomingDirection_SinPhi, (float)m_incomingDirection_CosPhi, 0.0f);                    // Always lying in the X^Y plane
            float3 lobe_biTangent = lobe_normal.Cross(lobe_tangent);

            // Compute sum
            double phi, theta, cosPhi, sinPhi;
            double outgoingIntensity_Simulated, length;
            double outgoingIntensity_Analytical, lobeIntensity;
            double difference;
            float3 wsOutgoingDirection  = float3.Zero;
            float3 wsOutgoingDirection2 = float3.Zero;
            float3 lsOutgoingDirection  = float3.Zero;
            double maskingOutGoing      = 0.0;
            double maskingShadowing;

            double sum              = 0.0;
            double sum_Simulated    = 0.0;
            double sum_Analytical   = 0.0;
            double sqSum_Simulated  = 0.0;
            double sqSum_Analytical = 0.0;

            for (int Y = 0; Y < H; Y++)
            {
// Formerly used wrong stuff!
//              // Y = theta bin index = 2.0 * LOBES_COUNT_THETA * pow2( sin( 0.5 * theta ) )
//              // We need theta:
//				theta = 2.0 * Math.Asin( Math.Sqrt( 0.5 * Y / H ) );

                // Y = theta bin index = LOBES_COUNT_THETA * (1 - cos( theta ) )
//              // We need theta:
                theta    = Math.Acos(1.0 - (float)Y / H);
                cosTheta = Math.Cos(theta);
                sinTheta = Math.Sin(theta);

                for (int X = 0; X < W; X++)
                {
                    // X = phi bin index = LOBES_COUNT_PHI * X / (2PI)
                    // We need phi:
                    phi    = 2.0 * Math.PI * X / W;
                    cosPhi = Math.Cos(phi);
                    sinPhi = Math.Sin(phi);

                    // Build simulated microfacet reflection direction in macro-surface space
                    outgoingIntensity_Simulated = m_histogramData[X, Y];
                    wsOutgoingDirection.Set((float)(cosPhi * sinTheta), (float)(sinPhi * sinTheta), (float)cosTheta);

                    // Compute maksing term due to outgoing direction
                    maskingOutGoing = Masking(wsOutgoingDirection.z, lobeRoughness);                                    // Masking( outgoing )

                    // Compute projection of world space direction onto reflected direction
                    float Vx = wsOutgoingDirection.Dot(lobe_tangent);
                    float Vy = wsOutgoingDirection.Dot(lobe_biTangent);
                    float Vz = wsOutgoingDirection.Dot(lobe_normal);

//Vz = Math.Min( 0.99f, Vz );

                    float cosTheta_M = Math.Max(1e-6f, Vz);

                    // Compute the lobe intensity in local space
                    lobeIntensity = NDF(cosTheta_M, lobeRoughness);

                    maskingShadowing = 1.0 + maskingImportance * (maskingIncoming * maskingOutGoing - 1.0); // = 1 when importance = 0, = masking when importance = 1
                    lobeIntensity   *= maskingShadowing;                                                    // * Masking terms

                    lobeIntensity *= lobeGlobalScale;

                    // Apply additional lobe scaling/flattening
                    length = m_flatteningEval(Vx, Vy, Vz, lobeFlatten, invLobeFlatten);

                    outgoingIntensity_Analytical = lobeIntensity * length;                      // Lobe intensity was estimated in lobe space, account for scaling when converting back in world space

                    // Sum the difference between simulated intensity and lobe intensity
                    outgoingIntensity_Analytical *= m_oversizeFactor;                           // Apply tolerance factor so we're always a bit smaller than the simulated lobe


                    if (m_fitUsingCenterOfMass)
                    {
                        double difference0 = outgoingIntensity_Simulated - outgoingIntensity_Analytical;

                        float3 wsLobePosition_Simulated  = (float)outgoingIntensity_Simulated * wsOutgoingDirection;
                        float3 wsLobePosition_Analytical = (float)outgoingIntensity_Analytical * wsOutgoingDirection;
                        // Subtract center of mass
                        wsLobePosition_Simulated  -= m_centerOfMass;
                        wsLobePosition_Analytical -= m_centerOfMass;
                        // Compute new intensities, relative to center of mass
                        outgoingIntensity_Simulated  = wsLobePosition_Simulated.Length;
                        outgoingIntensity_Analytical = wsLobePosition_Analytical.Length;

                        double difference1 = outgoingIntensity_Simulated - outgoingIntensity_Analytical;

                        difference = 0.5 * difference0 + 0.5 * difference1;

//						difference *= (wsLobePosition_Simulated - wsLobePosition_Analytical).Length;
//						difference += (wsLobePosition_Simulated - wsLobePosition_Analytical).Length;	// We also add the distance between lobe positions so it goes to the best of the 2 minima!
                    }
                    else
                    {
                        difference = outgoingIntensity_Simulated - outgoingIntensity_Analytical;
//						difference = outgoingIntensity_Simulated / Math.Max( 1e-6, outgoingIntensity_Analytical ) - 1.0;
//						difference = outgoingIntensity_Analytical / Math.Max( 1e-6, outgoingIntensity_Simulated ) - 1.0;
                    }


                    sum += difference * difference;

                    sum_Simulated    += outgoingIntensity_Simulated;
                    sum_Analytical   += outgoingIntensity_Analytical;
                    sqSum_Simulated  += outgoingIntensity_Simulated * outgoingIntensity_Simulated;
                    sqSum_Analytical += outgoingIntensity_Analytical * outgoingIntensity_Analytical;
                }
            }
            sum /= W * H;               // Not very useful since BFGS won't care but I'm doing it anyway to have some sort of normalized sum, better for us humans

            return(sum);
        }
示例#17
0
        private void    CubeMapSamplerSH(Probe.Pixel _Pixel, out byte _R, out byte _G, out byte _B)
        {
            float3 Dir = _Pixel.View;

            // Dot the SH together
            float3 Color = float3.Zero;

            if (m_IsolateSet)
            {
                float Factor = 1.0f;
                if (m_bShowSHDynamic)
                {
                    for (int i = 0; i < 9; i++)
                    {
                        Color += (float)_Pixel.SHCoeffs[i] * m_Probe.m_Sets[m_IsolatedSetIndex].SH[i];
                    }

                    Factor = m_bNormalizeSH ? 2.0f * m_Probe.m_Sets[m_IsolatedSetIndex].SH[0].Max() : 1.0f;
                }

                if (m_bShowSHEmissive)
                {
                    int EmissiveSetIndex = Math.Min(m_IsolatedSetIndex, m_Probe.m_EmissiveSets.Length - 1);
                    if (EmissiveSetIndex >= 0)
                    {
                        for (int i = 0; i < 9; i++)
                        {
                            Color += (float)_Pixel.SHCoeffs[i] * m_Probe.m_EmissiveSets[EmissiveSetIndex].SH[i];
                        }
                    }

                    Factor = m_bNormalizeSH ? 2.0f * m_Probe.m_EmissiveSets[EmissiveSetIndex].SH[0].Max() : 1.0f;
                }

//				Color *= 100.0f;
                Color *= 1.0f / Factor;
            }
            else
            {
                float Factor = 0.0f;
                if (m_bShowSHStatic)
                {
                    for (int i = 0; i < 9; i++)
                    {
                        Color += (float)_Pixel.SHCoeffs[i] * m_SHStatic[i];
                    }
                    Factor = Math.Max(Factor, m_SHStatic[0].Max());
                }
                if (m_bShowSHDynamic)
                {
                    for (int i = 0; i < 9; i++)
                    {
                        Color += (float)_Pixel.SHCoeffs[i] * m_SHDynamic[i];
                    }
                    Factor = Math.Max(Factor, m_SHDynamic[0].Max());
                }
                if (m_bShowSHEmissive)
                {
                    for (int i = 0; i < 9; i++)
                    {
                        Color += (float)_Pixel.SHCoeffs[i] * m_SHEmissive[i];
                    }
                    Factor = Math.Max(Factor, m_SHEmissive[0].Max());
                }
                if (m_bShowSHOcclusion)
                {
                    for (int i = 0; i < 9; i++)
                    {
                        Color += (float)_Pixel.SHCoeffs[i] * m_SHOcclusion[i] * float3.One;
                    }
                    Factor = Math.Max(Factor, m_SHOcclusion[0]);
                }

//				Color *= 50.0f;

                Color *= m_bNormalizeSH ? 1.0f / Factor : 1.0f;
            }

            if (Color.x < 0.0f || Color.y < 0.0f || Color.z < 0.0f)
            {
                Color.Set(1, 0, 1);
            }

            _R = (byte)Math.Min(255, 255 * Color.x);
            _G = (byte)Math.Min(255, 255 * Color.y);
            _B = (byte)Math.Min(255, 255 * Color.z);
        }
示例#18
0
        public void             SampleCubeMap(float3 _View, CubeMapSampler _Sampler, out byte _R, out byte _G, out byte _B)
        {
            AbsView.Set(Math.Abs(_View.x), Math.Abs(_View.y), Math.Abs(_View.z));
            float MaxComponent = Math.Max(Math.Max(AbsView.x, AbsView.y), AbsView.z);

            fXYZ.Set(_View.x / MaxComponent, _View.y / MaxComponent, _View.z / MaxComponent);
            int FaceIndex = 0;

            if (Math.Abs(fXYZ.x) > 1.0 - 1e-6)
            {                   // +X or -X
                if (_View.x > 0.0)
                {
                    FaceIndex = 0;
                    fXY.Set(-fXYZ.z, fXYZ.y);
                }
                else
                {
                    FaceIndex = 1;
                    fXY.Set(fXYZ.z, fXYZ.y);
                }
            }
            else if (Math.Abs(fXYZ.y) > 1.0 - 1e-6)
            {                   // +Y or -Y
                if (_View.y > 0.0)
                {
                    FaceIndex = 2;
                    fXY.Set(fXYZ.x, -fXYZ.z);
                }
                else
                {
                    FaceIndex = 3;
                    fXY.Set(fXYZ.x, fXYZ.z);
                }
            }
            else             // if ( Math.Abs( fXYZ.z ) > 1.0-1e-6 )
            {                // +Z or -Z
                if (_View.z > 0.0)
                {
                    FaceIndex = 4;
                    fXY.Set(fXYZ.x, fXYZ.y);
                }
                else
                {
                    FaceIndex = 5;
                    fXY.Set(-fXYZ.x, fXYZ.y);
                }
            }

            fXY.y = -fXY.y;

            int X = (int)(Probe.CUBE_MAP_SIZE * 0.5 * (1.0 + fXY.x));
            int Y = (int)(Probe.CUBE_MAP_SIZE * 0.5 * (1.0 + fXY.y));

//          if ( X < 0 || X > Probe.CUBE_MAP_SIZE-1 )
//              throw new Exception();
//          if ( Y < 0 || Y > Probe.CUBE_MAP_SIZE-1 )
//              throw new Exception();

            X = Math.Min(Probe.CUBE_MAP_SIZE - 1, X);
            Y = Math.Min(Probe.CUBE_MAP_SIZE - 1, Y);

            Probe.Pixel[,]  CubeMapFace = m_Probe.m_CubeMap[FaceIndex];

            _Sampler(CubeMapFace[X, Y], out _R, out _G, out _B);
        }