Example #1
0
        public void Update(List <BasicEntity> entities, GraphicsDevice graphics, DistanceFieldRenderModule distanceFieldRenderModule, FullScreenTriangle fullScreenTriangle, ref List <SignedDistanceField> sdfDefinitionsOut)
        {
            //First let's check which entities need building, if at all!
            sdfDefinitions.Clear();

            //This should preferably be a list of meshes that are in the scene, instead of a list of entities
            for (var index0 = 0; index0 < entities.Count; index0++)
            {
                BasicEntity entity = entities[index0];


                if (!entity.SignedDistanceField.IsUsed)
                {
                    continue;
                }

                if (entity.SignedDistanceField.NeedsToBeGenerated)
                {
                    GenerateDistanceFields(entity, graphics, distanceFieldRenderModule, fullScreenTriangle);
                }

                bool found = false;
                //Compile a list of all mbbs used right now
                for (var i = 0; i < sdfDefinitions.Count; i++)
                {
                    if (entity.SignedDistanceField == sdfDefinitions[i])
                    {
                        found = true;
                        break;
                    }
                }
                if (!found)
                {
                    sdfDefinitions.Add(entity.SignedDistanceField);
                }
            }

            //Now for the model definitions
            for (var i = 0; i < sdfDefinitions.Count; i++)
            {
                if (GameSettings.sdf_regenerate)
                {
                    sdfDefinitions[i].NeedsToBeGenerated = true;
                }
            }

            GameSettings.sdf_regenerate = false;

            sdfDefinitionsOut = sdfDefinitions;
        }
Example #2
0
        public void GenerateDistanceFields(BasicEntity entity, GraphicsDevice graphics, DistanceFieldRenderModule distanceFieldRenderModule, FullScreenTriangle fullScreenTriangle)
        {
            SignedDistanceField uncomputedSignedDistanceField = entity.SignedDistanceField;
            Model unprocessedModel = entity.Model;

            //Set to false so it won't get covered in future
            uncomputedSignedDistanceField.NeedsToBeGenerated = false;
            uncomputedSignedDistanceField.IsLoaded           = false;
            uncomputedSignedDistanceField.SdfTexture?.Dispose();

            //First generate tris
            Triangle[] triangles;
            GenerateTriangles(unprocessedModel, out triangles);

            int xsteps = (int)uncomputedSignedDistanceField.TextureResolution.X;
            int ysteps = (int)uncomputedSignedDistanceField.TextureResolution.Y;
            int zsteps = (int)uncomputedSignedDistanceField.TextureResolution.Z;

            Texture2D output;

            if (!GameSettings.sdf_cpu)
            {
                Stopwatch stopwatch = Stopwatch.StartNew();

                int maxwidth     = 4096; //16384
                int requiredData = triangles.Length * 3;

                int x = maxwidth;//Math.Min(requiredData, maxwidth);
                int y = requiredData / x + 1;

                Vector4[] data = new Vector4[x * y];

                int index = 0;
                for (int i = 0; i < triangles.Length; i++, index += 3)
                {
                    data[index]     = new Vector4(triangles[i].a, 0);
                    data[index + 1] = new Vector4(triangles[i].b, 0);
                    data[index + 2] = new Vector4(triangles[i].c, 0);
                }

                //16k

                Texture2D triangleData = new Texture2D(graphics, x, y, false, SurfaceFormat.Vector4);

                triangleData.SetData(data);

                output = distanceFieldRenderModule.CreateSDFTexture(graphics, triangleData, xsteps, ysteps,
                                                                    zsteps, uncomputedSignedDistanceField, fullScreenTriangle, triangles.Length);

                stopwatch.Stop();

                Debug.Write("\nSDF generated in " + stopwatch.ElapsedMilliseconds + "ms on GPU");

                float[] texData = new float[xsteps * ysteps * zsteps];

                output.GetData(texData);

                string path = uncomputedSignedDistanceField.TexturePath;
                DataStream.SaveImageData(texData, xsteps, ysteps, zsteps, path);
                uncomputedSignedDistanceField.TextureResolution = new Vector4(xsteps, ysteps, zsteps, 0);
                uncomputedSignedDistanceField.SdfTexture        = output;
                uncomputedSignedDistanceField.IsLoaded          = true;
            }
            else
            {
                generateTask = Task.Factory.StartNew(() =>
                {
                    output = new Texture2D(graphics, xsteps * zsteps, ysteps, false, SurfaceFormat.Single);

                    float[] data = new float[xsteps * ysteps * zsteps];

                    Stopwatch stopwatch = Stopwatch.StartNew();

                    int numberOfThreads = GameSettings.sdf_threads;

                    if (numberOfThreads > 1)
                    {
                        Task[] threads = new Task[numberOfThreads - 1];

                        //Make local datas

                        float[][] dataArray = new float[numberOfThreads][];

                        for (int index = 0; index < threads.Length; index++)
                        {
                            int i = index;
                            dataArray[index + 1] = new float[xsteps * ysteps * zsteps];
                            threads[i]           = Task.Factory.StartNew(() =>
                            {
                                GenerateData(xsteps, ysteps, zsteps, uncomputedSignedDistanceField,
                                             ref dataArray[i + 1], i + 1,
                                             numberOfThreads, triangles);
                            });
                        }

                        dataArray[0] = data;
                        GenerateData(xsteps, ysteps, zsteps, uncomputedSignedDistanceField, ref dataArray[0], 0,
                                     numberOfThreads, triangles);

                        Task.WaitAll(threads);

                        //Something broke?
                        for (int i = 0; i < data.Length; i++)
                        {
                            //data[i] = dataArray[i % numberOfThreads][i];
                            for (int j = 0; j < numberOfThreads; j++)
                            {
                                if (dataArray[j][i] != 0)
                                {
                                    data[i] = dataArray[j][i];
                                    break;
                                }
                            }
                        }

                        for (var index2 = 0; index2 < threads.Length; index2++)
                        {
                            threads[index2].Dispose();
                        }
                    }
                    else
                    {
                        GenerateData(xsteps, ysteps, zsteps, uncomputedSignedDistanceField, ref data, 0,
                                     numberOfThreads, triangles);
                    }

                    stopwatch.Stop();

                    Debug.Write("\nSDF generated in " + stopwatch.ElapsedMilliseconds + "ms with " +
                                GameSettings.sdf_threads + " thread(s)");

                    string path = uncomputedSignedDistanceField.TexturePath;
                    DataStream.SaveImageData(data, xsteps, ysteps, zsteps, path);
                    output.SetData(data);
                    uncomputedSignedDistanceField.TextureResolution = new Vector4(xsteps, ysteps, zsteps, 0);
                    uncomputedSignedDistanceField.SdfTexture        = output;
                    uncomputedSignedDistanceField.IsLoaded          = true;
                });
            }
        }