Example #1
0
        public LiveRenderer(Fractal fractal, FractalBufferPool pool)
        {
            if (fractal == null)
            {
                throw new ArgumentNullException("fractal");
            }
            if (pool == null)
            {
                throw new ArgumentNullException("pool");
            }

            _fractal            = fractal;
            _pool               = pool;
            tileUpdatesPerFrame = 10;

            _fractal.Colorizer.Changed += Colorizer_Changed;
            _fractal.FractalChanged    += OnFractalChanged;
        }
Example #2
0
        public FractalBuffer(FractalBufferPool factory)
        {
            var desc = new RenderTextureDescriptor(factory.TileResolution, factory.TileResolution, RenderTextureFormat.ARGBFloat);

            GPUFractal            = new RenderTexture(desc);
            GPUFractal.filterMode = FilterMode.Point;
            GPUFractal.Create();

            CPUFractal            = new Texture2D(factory.TileResolution, factory.TileResolution, TextureFormat.RGBAFloat, false);
            CPUFractal.filterMode = FilterMode.Point;

            desc      = new RenderTextureDescriptor(factory.TileResolution, factory.TileResolution, RenderTextureFormat.BGRA32);
            Colorized = new RenderTexture(desc);
            Colorized.Create();

            FractalMat          = new Material(factory.FractalShader);
            BlitMat             = new Material(factory.BlitShader);
            BlitMat.mainTexture = Colorized;
        }
Example #3
0
        public static void Render(Fractal fractal, Camera cam, FractalBufferPool pool, int ssLOD)
        {
            var target = cam.targetTexture ?? cam.activeTexture;
            var w      = cam.pixelWidth;
            var h      = cam.pixelHeight;

            var oldTarget = RenderTexture.active;

            if (target != null)
            {
                RenderTexture.active = target;
            }

            var ar    = w / (float)h;
            var ortho = Matrix4x4.Ortho(-2 * ar, 2 * ar, -2, 2, -1, 1);

            //var camOrthe = cam.projectionMatrix;

            //GL.Clear(false, true, Color.blue);
            GL.PushMatrix();
            //GL.Viewport(new Rect(0, 0, 300, 300));
            //GL.Clear(false, true, Color.red);
            //GL.LoadProjectionMatrix(test == null ? cam.projectionMatrix : test.projectionMatrix);
            GL.LoadProjectionMatrix(Matrix4x4.Ortho(-2 * ar, 2 * ar, -2, 2, -1, 1));
            //GL.LoadPixelMatrix();
            // GL.LoadIdentity();
            // GL.LoadOrtho();
            //GL.LoadPrjectionMatrix(cam.projectionMatrix);
            //Help.RenderRectNow(target, new Material(Shader.Find("Hidden/BlitShader")), Matrix4x4.identity);
            //GL.PopMatrix();

            // Free cached tile resources before calling
            var tileJobChunk = Math.Max(3, pool.PreallocatedBuffersAvailable);

            // copy the colorizer
            var pubColorizer = new Colorizer(fractal.Colorizer);

            //pubColorizer.FlipVertical = true;

            RenderTextureDescriptor rtd = new RenderTextureDescriptor(1, 1, RenderTextureFormat.BGRA32);

            if (target != null)
            {
                pubColorizer.ConvertSRGB = !target.sRGB;
                rtd = target.descriptor;

                if (target.format == RenderTextureFormat.ARGB32)
                {
                    pubColorizer.SwapRedBlue = true;
                }
            }

            // Compute the grid dimensions
            int tileCols = (1 << ssLOD) * (w - 1) / pool.TileResolution + 1;
            int tileRows = (1 << ssLOD) * (h - 1) / pool.TileResolution + 1;

            // Compute the fractal window and edge length
            var cambb  = Help.GetViewBoundingBox(ortho);
            var minima = fractal.ViewCenter + new double2(cambb.min.x, cambb.min.y) * fractal.ViewScale;
            var maxima = fractal.ViewCenter + new double2(cambb.max.x, cambb.max.y) * fractal.ViewScale;
            var span   = maxima - minima;
            var edge   = span.x * pool.TileResolution / (w * (1 << ssLOD));

            // Flip the fractal over so the result is compatible with TIFF
            //var tmp = minima.y;
            //minima.y = maxima.y;
            //maxima.y = tmp;
            var edgeIncrement = new double2(edge, edge);

            // TODO: incorporate rotation

            // Allocate downsampling buffers
            RenderTexture[] downsamplers = null;
            if (ssLOD > 0)
            {
                downsamplers = new RenderTexture[ssLOD - 1];
                for (int i = 1; i < ssLOD; i++)
                {
                    var desc = rtd;
                    desc.width          = desc.height = pool.TileResolution >> i;
                    downsamplers[i - 1] = new RenderTexture(desc);
                    downsamplers[i - 1].Create();
                }
            }

            List <double2> toRender = new List <double2>();

            for (int x = 0; x < tileCols; x++)
            {
                for (int y = 0; y < tileRows; y++)
                {
                    toRender.Add(new double2(x, y));
                }
            }

            int toRenderIndex        = 0;
            var one2                 = new double2(1, 1);
            List <FractalTile> tiles = new List <FractalTile>();

            while (toRenderIndex < toRender.Count)
            {
                int nextJobChunk = Math.Min(tileJobChunk, toRender.Count - toRenderIndex);

                // Initialize tiles
                for (int i = 0; i < nextJobChunk; i++)
                {
                    var index   = toRender[i + toRenderIndex];
                    var tileMin = minima + index * edgeIncrement;
                    var tileMax = minima + (index + one2) * edgeIncrement;

                    var tile = new FractalTile(fractal, pool.Get(), tileMin, tileMax, edge < 1e-5);
                    tiles.Add(tile);
                }

                for (int i = 0; i < tiles.Count; i++)
                {
                    tiles[i].RenderFractal();
                }

                JobHandle.ScheduleBatchedJobs();

                for (int i = 0; i < tiles.Count; i++)
                {
                    tiles[i].FinishRenderFractal();
                    tiles[i].Colorize(pubColorizer);

                    // Downsample
                    Texture downSrc = tiles[i].Data.Colorized;

                    if (downsamplers != null)
                    {
                        for (int downsIndex = 0; downsIndex != downsamplers.Length; downsIndex++)
                        {
                            var downsTarget = downsamplers[downsIndex];
                            Help.BlitNow(downSrc, downsTarget);
                            //Help.Mark(downsTarget, UnityEngine.Random.ColorHSV());
                            downSrc = downsTarget;
                        }
                    }

                    // Render to target
                    tiles[i].RenderComposition(1, target, downSrc, true);
                }

                for (int i = 0; i < tiles.Count; i++)
                {
                    pool.Free(tiles[i].Data);
                }

                tiles.Clear();
                toRenderIndex += nextJobChunk;
            }

            if (target != null)
            {
                RenderTexture.active = oldTarget;
            }

            GL.PopMatrix();
        }