Esempio n. 1
0
        private void CalculateAO()
        {
            Debug.Log("Precomputing AO Started...");

            int GRIDRES_AO = 128;
            int N_AO       = 2;

            var options = new ParallelOptions {
                MaxDegreeOfParallelism = 4
            };

            float[] buf = new float[GRIDRES_AO * GRIDRES_AO * GRIDRES_AO * 4];

            for (int i = 0; i < GRIDRES_AO; ++i)
            {
                for (int j = 0; j < GRIDRES_AO; ++j)
                {
                    for (int k = 0; k < GRIDRES_AO; ++k)
                    {
                        int off = i + j * GRIDRES_AO + k * GRIDRES_AO * GRIDRES_AO;

                        buf[4 * off]     = 0;
                        buf[4 * off + 1] = 0;
                        buf[4 * off + 2] = 0;
                        buf[4 * off + 3] = 0;
                    }
                }
            }

            var indices  = PreProcessMesh.GetIndices(0);
            var vertices = PreProcessMesh.vertices;

            for (int ni = 0; ni < indices.Length; ni += 3)
            {
                int a = indices[ni];
                int b = indices[ni + 1];
                int c = indices[ni + 2];

                float x1 = vertices[a].x, y1 = vertices[a].y, z1 = vertices[a].z;
                float x2 = vertices[b].x, y2 = vertices[b].y, z2 = vertices[b].z;
                float x3 = vertices[c].x, y3 = vertices[c].y, z3 = vertices[c].z;

                x1 = (x1 + 1.0f) / 2.0f;
                x2 = (x2 + 1.0f) / 2.0f;
                x3 = (x3 + 1.0f) / 2.0f;
                y1 = (y1 + 1.0f) / 2.0f;
                y2 = (y2 + 1.0f) / 2.0f;
                y3 = (y3 + 1.0f) / 2.0f;
                z1 = (z1 + 1.0f) / 2.0f;
                z2 = (z2 + 1.0f) / 2.0f;
                z3 = (z3 + 1.0f) / 2.0f;

                double l12 = Mathf.Sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1) + (z2 - z1) * (z2 - z1));
                double l23 = Mathf.Sqrt((x3 - x2) * (x3 - x2) + (y3 - y2) * (y3 - y2) + (z3 - z2) * (z3 - z2));
                double l31 = Mathf.Sqrt((x1 - x3) * (x1 - x3) + (y1 - y3) * (y1 - y3) + (z1 - z3) * (z1 - z3));

                if (l12 > l23 && l12 > l31)
                {
                    Swap(ref a, ref c);
                    Swap(ref x1, ref x3); Swap(ref y1, ref y3); Swap(ref z1, ref z3);
                    Swap(ref l12, ref l23);
                }
                else if (l31 > l12 && l31 > l23)
                {
                    Swap(ref a, ref b);
                    Swap(ref x1, ref x2); Swap(ref y1, ref y2); Swap(ref z1, ref z2);
                    Swap(ref l31, ref l23);
                }

                int n12 = (int)(Math.Ceiling(l12 * GRIDRES_AO) * 2.0);
                int n13 = (int)(Math.Ceiling(l31 * GRIDRES_AO) * 2.0);

                Parallel.For(0, n12 - 1, i =>
                {
                    var u = (double)i / n12;

                    Parallel.For(0, n13 - 1, j =>
                    {
                        var v = (double)j / n13;

                        if (u + v < 1.0)
                        {
                            var x = x1 + u * (x2 - x1) + v * (x3 - x1);
                            var y = y1 + u * (y2 - y1) + v * (y3 - y1);
                            var z = z1 + u * (z2 - z1) + v * (z3 - z1);

                            int ix = (int)(x * GRIDRES_AO);
                            int iy = (int)(y * GRIDRES_AO);
                            int iz = (int)(z * GRIDRES_AO);

                            if (ix >= 0 && ix < GRIDRES_AO && iy >= 0 && iy < GRIDRES_AO && iz >= 0 && iz < GRIDRES_AO)
                            {
                                int off = 4 * (ix + iy * GRIDRES_AO + iz * GRIDRES_AO * GRIDRES_AO);

                                buf[off]     = 255;
                                buf[off + 1] = 255;
                                buf[off + 2] = 255;
                                buf[off + 3] = 255;
                            }
                        }
                    });
                });
            }

            Debug.Log("Precomputing AO Mesh Passed...");

            double[] vocc = new double[GRIDRES_AO * GRIDRES_AO * GRIDRES_AO];

            for (int i = 0; i < GRIDRES_AO * GRIDRES_AO * GRIDRES_AO; ++i)
            {
                vocc[i] = 1.0;
            }

            double zmax = Math.Abs(Z);
            double zmin = -Math.Abs(Z);

            Parallel.For(0, N_AO - 1, options, i =>
            {
                var theta  = (i + 0.5) / N_AO * Math.PI / 2.0;
                var dtheta = 1.0 / N_AO * Math.PI / 2.0;

                Parallel.For(0, (4 * N_AO) - 1, options, j =>
                {
                    var phi  = (j + 0.5) / (4 * N_AO) * 2.0 * Math.PI;
                    var dphi = 1.0 / (4 * N_AO) * 2.0 * Math.PI;
                    var docc = Math.Cos(theta) * Math.Sin(theta) * dtheta * dphi / Math.PI;

                    if ((i * 4 * N_AO + j) % 4 == 0)
                    {
                        Debug.Log(string.Format("Precomputing AO Step {0} of {1}", i * 4 * N_AO + j, 4 * N_AO * N_AO));
                    }

                    Vector3d uz = new Vector3d(Math.Cos(phi) * Math.Sin(theta), Math.Sin(phi) * Math.Sin(theta), Math.Cos(theta));
                    Vector3d ux = uz.z.EpsilonEquals(1.0, 0.0000001) ? new Vector3d(1.0, 0.0, 0.0) : new Vector3d(-uz.y, uz.x, 0.0).Normalized();
                    Vector3d uy = uz.Cross(ux);

                    Matrix3x3d toView = new Matrix3x3d(ux.x, ux.y, ux.z, uy.x, uy.y, uy.z, uz.x, uz.y, uz.z);
                    Matrix3x3d toVol  = new Matrix3x3d(ux.x, uy.x, uz.x, ux.y, uy.y, uz.y, ux.z, uy.z, uz.z);

                    Box3d b = new Box3d();
                    b       = b.Enlarge(toView * new Vector3d(-1.0, -1.0, zmin));
                    b       = b.Enlarge(toView * new Vector3d(+1.0, -1.0, zmin));
                    b       = b.Enlarge(toView * new Vector3d(-1.0, +1.0, zmin));
                    b       = b.Enlarge(toView * new Vector3d(+1.0, +1.0, zmin));
                    b       = b.Enlarge(toView * new Vector3d(-1.0, -1.0, zmax));
                    b       = b.Enlarge(toView * new Vector3d(+1.0, -1.0, zmax));
                    b       = b.Enlarge(toView * new Vector3d(-1.0, +1.0, zmax));
                    b       = b.Enlarge(toView * new Vector3d(+1.0, +1.0, zmax));

                    int nx = (int)((b.Max.x - b.Min.x) * GRIDRES_AO / 2);
                    int ny = (int)((b.Max.y - b.Min.y) * GRIDRES_AO / 2);
                    int nz = (int)((b.Max.z - b.Min.z) * GRIDRES_AO / 2);

                    int[] occ = new int[nx * ny * nz];
                    for (int v = 0; v < nx * ny * nz; ++v)
                    {
                        occ[v] = 0;
                    }

                    for (int iz = nz - 1; iz >= 0; --iz)
                    {
                        var z = b.Min.z + (iz + 0.5) / nz * (b.Max.z - b.Min.z);

                        for (int iy = 0; iy < ny; ++iy)
                        {
                            var y = b.Min.y + (iy + 0.5) / ny * (b.Max.y - b.Min.y);

                            for (int ix = 0; ix < nx; ++ix)
                            {
                                var x = b.Min.x + (ix + 0.5) / nx * (b.Max.x - b.Min.x);

                                Vector3d p = toVol * new Vector3d(x, y, z);

                                int val = 0;
                                int vx  = (int)((p.x + 1.0) / 2.0 * GRIDRES_AO);
                                int vy  = (int)((p.y + 1.0) / 2.0 * GRIDRES_AO);
                                int vz  = (int)((p.z + 1.0) / 2.0 * GRIDRES_AO);

                                if (vx >= 0 && vx < GRIDRES_AO && vy >= 0 && vy < GRIDRES_AO && vz >= 0 && vz < GRIDRES_AO)
                                {
                                    val = buf[4 * (vx + vy * GRIDRES_AO + vz * GRIDRES_AO * GRIDRES_AO) + 3].EpsilonEquals(255.0f) ? 1 : 0;
                                }

                                occ[ix + iy * nx + iz * nx * ny] = val;

                                if (iz != nz - 1)
                                {
                                    occ[ix + iy * nx + iz * nx * ny] += occ[ix + iy * nx + (iz + 1) * nx * ny];
                                }
                            }
                        }
                    }

                    Parallel.For(0, GRIDRES_AO - 1, options, ix =>
                    {
                        var x = -1.0 + (ix + 0.5) / GRIDRES_AO * 2.0;

                        Parallel.For(0, GRIDRES_AO - 1, options, iy =>
                        {
                            var y = -1.0 + (iy + 0.5) / GRIDRES_AO * 2.0;

                            Parallel.For(0, GRIDRES_AO - 1, options, iz =>
                            {
                                var z = -1.0 + (iz + 0.5) / GRIDRES_AO * 2.0;

                                Vector3d p = toView * new Vector3d(x, y, z);

                                int vx = (int)((p.x - b.Min.x) / (b.Max.x - b.Min.x) * nx);
                                int vy = (int)((p.y - b.Min.y) / (b.Max.y - b.Min.y) * ny);
                                int vz = (int)((p.z - b.Min.z) / (b.Max.z - b.Min.z) * nz);

                                if (vx >= 0 && vx < nx && vy >= 0 && vy < ny && vz >= 0 && vz < nz)
                                {
                                    int occN = occ[vx + vy * nx + vz * nx * ny];

                                    if (occN > 6)
                                    {
                                        vocc[ix + iy * GRIDRES_AO + iz * GRIDRES_AO * GRIDRES_AO] -= docc;
                                    }
                                }
                            });
                        });
                    });
                });
            });

            for (int i = 0; i < GRIDRES_AO; ++i)
            {
                for (int j = 0; j < GRIDRES_AO; ++j)
                {
                    for (int k = 0; k < GRIDRES_AO; ++k)
                    {
                        int off = i + j * GRIDRES_AO + k * GRIDRES_AO * GRIDRES_AO;

                        if (buf[4 * off + 3].EpsilonEquals(255.0f))
                        {
                            var v = Math.Max(vocc[off], 0.0f) * 255;

                            buf[4 * off]     = (float)v;
                            buf[4 * off + 1] = (float)v;
                            buf[4 * off + 2] = (float)v;
                        }
                    }
                }
            }

            GC.Collect();

            var cb = new ComputeBuffer(GRIDRES_AO * GRIDRES_AO * GRIDRES_AO, sizeof(float) * 4);

            PreProcessAORT = RTExtensions.CreateRTexture(GRIDRES_AO, 0, RenderTextureFormat.ARGBFloat, FilterMode.Bilinear, TextureWrapMode.Clamp, GRIDRES_AO);

            CBUtility.WriteIntoRenderTexture(PreProcessAORT, CBUtility.Channels.RGBA, cb, GodManager.Instance.WriteData);
            RTUtility.SaveAs8bit(GRIDRES_AO, GRIDRES_AO * GRIDRES_AO, CBUtility.Channels.RGBA, "TreeAO", DestinationFolder, buf, 0.00392156863f);

            cb.ReleaseAndDisposeBuffer();

            Debug.Log("Precomputing AO Completed!");
        }
Esempio n. 2
0
        public void Calculate(AtmosphereParameters AP)
        {
            if (step == 0)
            {
                // computes transmittance texture T (line 1 in algorithm 4.1)
                Transmittance.SetTexture(0, "transmittanceWrite", transmittanceT);
                Transmittance.Dispatch(0, AtmosphereConstants.TRANSMITTANCE_W / NUM_THREADS, AtmosphereConstants.TRANSMITTANCE_H / NUM_THREADS, 1);
            }
            else if (step == 1)
            {
                // computes irradiance texture deltaE (line 2 in algorithm 4.1)
                Irradiance1.SetTexture(0, "transmittanceRead", transmittanceT);
                Irradiance1.SetTexture(0, "deltaEWrite", deltaET);
                Irradiance1.Dispatch(0, AtmosphereConstants.SKY_W / NUM_THREADS, AtmosphereConstants.SKY_H / NUM_THREADS, 1);
            }
            else if (step == 2)
            {
                // computes single scattering texture deltaS (line 3 in algorithm 4.1)
                // Rayleigh and Mie separated in deltaSR + deltaSM
                Inscatter1.SetTexture(0, "transmittanceRead", transmittanceT);
                Inscatter1.SetTexture(0, "deltaSRWrite", deltaSRT);
                Inscatter1.SetTexture(0, "deltaSMWrite", deltaSMT);

                //The inscatter calc's can be quite demanding for some cards so process
                //the calc's in layers instead of the whole 3D data set.
                for (int i = 0; i < AtmosphereConstants.RES_R; i++)
                {
                    Inscatter1.SetInt("layer", i);
                    Inscatter1.Dispatch(0, (AtmosphereConstants.RES_MU_S * AtmosphereConstants.RES_NU) / NUM_THREADS, AtmosphereConstants.RES_MU / NUM_THREADS, 1);
                }
            }
            else if (step == 3)
            {
                // copies deltaE into irradiance texture E (line 4 in algorithm 4.1)
                CopyIrradiance.SetFloat("k", 0.0f);
                CopyIrradiance.SetTexture(0, "deltaERead", deltaET);
                CopyIrradiance.SetTexture(0, "irradianceRead", irradianceT_Read);
                CopyIrradiance.SetTexture(0, "irradianceWrite", irradianceT_Write);
                CopyIrradiance.Dispatch(0, AtmosphereConstants.SKY_W / NUM_THREADS, AtmosphereConstants.SKY_H / NUM_THREADS, 1);

                //Swap irradianceT_Read - irradianceT_Write
                RTUtility.Swap(ref irradianceT_Read, ref irradianceT_Write);
            }
            else if (step == 4)
            {
                // copies deltaS into inscatter texture S (line 5 in algorithm 4.1)
                CopyInscatter1.SetTexture(0, "deltaSRRead", deltaSRT);
                CopyInscatter1.SetTexture(0, "deltaSMRead", deltaSMT);
                CopyInscatter1.SetTexture(0, "inscatterWrite", inscatterT_Write);

                //The inscatter calc's can be quite demanding for some cards so process
                //the calc's in layers instead of the whole 3D data set.
                for (int i = 0; i < AtmosphereConstants.RES_R; i++)
                {
                    CopyInscatter1.SetInt("layer", i);
                    CopyInscatter1.Dispatch(0, (AtmosphereConstants.RES_MU_S * AtmosphereConstants.RES_NU) / NUM_THREADS, AtmosphereConstants.RES_MU / NUM_THREADS, 1);
                }

                //Swap inscatterT_Write - inscatterT_Read
                RTUtility.Swap(ref inscatterT_Read, ref inscatterT_Write); //!!!
            }
            else if (step == 5)
            {
                //Here Nvidia GTX 430 or lower driver will crash.
                //If only ray1 or mie1 calculated - slow, but all is alright.
                //But if both - driver crash.
                //INSCATTER_SPHERICAL_INTEGRAL_SAMPLES = 8 - limit for GTX 430.

                // computes deltaJ (line 7 in algorithm 4.1)
                InscatterS.SetInt("first", (order == 2) ? 1 : 0);
                InscatterS.SetTexture(0, "transmittanceRead", transmittanceT);
                InscatterS.SetTexture(0, "deltaERead", deltaET);
                InscatterS.SetTexture(0, "deltaSRRead", deltaSRT);
                InscatterS.SetTexture(0, "deltaSMRead", deltaSMT);
                InscatterS.SetTexture(0, "deltaJWrite", deltaJT);

                //The inscatter calc's can be quite demanding for some cards so process
                //the calc's in layers instead of the whole 3D data set.
                for (int i = 0; i < AtmosphereConstants.RES_R; i++)
                {
                    InscatterS.SetInt("layer", i);
                    InscatterS.Dispatch(0, (AtmosphereConstants.RES_MU_S * AtmosphereConstants.RES_NU) / NUM_THREADS, AtmosphereConstants.RES_MU / NUM_THREADS, 1);
                }
            }
            else if (step == 6)
            {
                // computes deltaE (line 8 in algorithm 4.1)
                IrradianceN.SetInt("first", (order == 2) ? 1 : 0);
                IrradianceN.SetTexture(0, "deltaSRRead", deltaSRT);
                IrradianceN.SetTexture(0, "deltaSMRead", deltaSMT);
                IrradianceN.SetTexture(0, "deltaEWrite", deltaET);
                IrradianceN.Dispatch(0, AtmosphereConstants.SKY_W / NUM_THREADS, AtmosphereConstants.SKY_H / NUM_THREADS, 1);
            }
            else if (step == 7)
            {
                // computes deltaS (line 9 in algorithm 4.1)
                InscatterN.SetTexture(0, "transmittanceRead", transmittanceT);
                InscatterN.SetTexture(0, "deltaJRead", deltaJT);
                InscatterN.SetTexture(0, "deltaSRWrite", deltaSRT);

                //The inscatter calc's can be quite demanding for some cards so process
                //the calc's in layers instead of the whole 3D data set.
                for (int i = 0; i < AtmosphereConstants.RES_R; i++)
                {
                    InscatterN.SetInt("layer", i);
                    InscatterN.Dispatch(0, (AtmosphereConstants.RES_MU_S * AtmosphereConstants.RES_NU) / NUM_THREADS, AtmosphereConstants.RES_MU / NUM_THREADS, 1);
                }
            }
            else if (step == 8)
            {
                // adds deltaE into irradiance texture E (line 10 in algorithm 4.1)
                CopyIrradiance.SetFloat("k", 1.0f);
                CopyIrradiance.SetTexture(0, "deltaERead", deltaET);
                CopyIrradiance.SetTexture(0, "irradianceRead", irradianceT_Read);
                CopyIrradiance.SetTexture(0, "irradianceWrite", irradianceT_Write);
                CopyIrradiance.Dispatch(0, AtmosphereConstants.SKY_W / NUM_THREADS, AtmosphereConstants.SKY_H / NUM_THREADS, 1);

                //Swap irradianceT_Read - irradianceT_Write
                RTUtility.Swap(ref irradianceT_Read, ref irradianceT_Write);
            }
            else if (step == 9)
            {
                // adds deltaS into inscatter texture S (line 11 in algorithm 4.1)
                CopyInscatterN.SetTexture(0, "deltaSRead", deltaSRT);
                CopyInscatterN.SetTexture(0, "inscatterRead", inscatterT_Read);
                CopyInscatterN.SetTexture(0, "inscatterWrite", inscatterT_Write);

                //The inscatter calc's can be quite demanding for some cards so process
                //the calc's in layers instead of the whole 3D data set.
                for (int i = 0; i < AtmosphereConstants.RES_R; i++)
                {
                    CopyInscatterN.SetInt("layer", i);
                    CopyInscatterN.Dispatch(0, (AtmosphereConstants.RES_MU_S * AtmosphereConstants.RES_NU) / NUM_THREADS, AtmosphereConstants.RES_MU / NUM_THREADS, 1);
                }

                //Swap inscatterT_Read - inscatterT_Write
                RTUtility.Swap(ref inscatterT_Read, ref inscatterT_Write);

                if (order < 4)
                {
                    step   = 4;
                    order += 1;
                }
            }
            else if (step == 10)
            {
                if (BakeMode == AtmosphereBakeMode.TO_HDD || BakeMode == AtmosphereBakeMode.TO_HDD_DEBUG)
                {
                    var readDataShader = GodManager.Instance.ReadData;

                    RTUtility.SaveAsRaw(AtmosphereConstants.TRANSMITTANCE_W * AtmosphereConstants.TRANSMITTANCE_H, CBUtility.Channels.RGB, "/transmittance", DestinationFolder, transmittanceT, readDataShader);
                    RTUtility.SaveAsRaw(AtmosphereConstants.SKY_W * AtmosphereConstants.SKY_H, CBUtility.Channels.RGB, "/irradiance", DestinationFolder, irradianceT_Read, readDataShader);
                    RTUtility.SaveAsRaw((AtmosphereConstants.RES_MU_S * AtmosphereConstants.RES_NU) * AtmosphereConstants.RES_MU * AtmosphereConstants.RES_R, CBUtility.Channels.RGB, "/inscatter", DestinationFolder, inscatterT_Read, readDataShader);

                    if (BakeMode == AtmosphereBakeMode.TO_HDD_DEBUG)
                    {
                        RTUtility.SaveAs8bit(AtmosphereConstants.TRANSMITTANCE_W, AtmosphereConstants.TRANSMITTANCE_H, CBUtility.Channels.RGBA, "/transmittance_debug", DestinationFolder, transmittanceT, readDataShader);
                        RTUtility.SaveAs8bit(AtmosphereConstants.SKY_W, AtmosphereConstants.SKY_H, CBUtility.Channels.RGBA, "/irradiance_debug", DestinationFolder, irradianceT_Read, readDataShader, 10.0f);
                        RTUtility.SaveAs8bit(AtmosphereConstants.RES_MU_S * AtmosphereConstants.RES_NU, AtmosphereConstants.RES_MU * AtmosphereConstants.RES_R, CBUtility.Channels.RGBA, "/inscater_debug", DestinationFolder, inscatterT_Read, readDataShader);
                    }
                }
            }
            else if (step == 11)
            {
                finished = true;
            }

            step++;
        }