Ejemplo n.º 1
0
        public unsafe void Draw()
        {
            if (game.Config.MSAASamples > 0)
            {
                if (_mwidth != Game.Width || _mheight != Game.Height)
                {
                    _mwidth  = Game.Width;
                    _mheight = Game.Height;
                    if (msaa != null)
                    {
                        msaa.Dispose();
                    }
                    msaa = new MultisampleTarget(Game.Width, Game.Height, Game.Config.MSAASamples);
                }
                msaa.Bind();
            }
            NebulaRenderer nr = CheckNebulae();             //are we in a nebula?

            bool transitioned = false;

            if (nr != null)
            {
                transitioned = nr.FogTransitioned();
            }
            rstate.DepthEnabled = true;
            //Add Nebula light
            if (GLExtensions.Features430 && ExtraLights)
            {
                //TODO: Re-add [LightSource] to the compute shader, it shouldn't regress.
                PointLight p2;
                if (nr != null && nr.DoLightning(out p2))
                {
                    pointLights.Add(p2);
                }
            }
            //Async calcs
            for (int i = 0; i < Objects.Count; i += 16)
            {
                JThreads.Instance.AddTask((o) =>
                {
                    var offset = (int)o;
                    for (int j = 0; j < 16 && ((j + offset) < Objects.Count); j++)
                    {
                        Objects[j + offset].PrepareRender(camera, nr);
                    }
                }, i);
            }
            JThreads.Instance.BeginExecute();
            if (transitioned)
            {
                //Fully in fog. Skip Starsphere
                rstate.ClearColor = nr.Nebula.FogColor;
                rstate.ClearAll();
            }
            else
            {
                rstate.DepthEnabled = false;
                if (starSystem == null)
                {
                    rstate.ClearColor = NullColor;
                }
                else
                {
                    rstate.ClearColor = starSystem.BackgroundColor;
                }
                rstate.ClearAll();
                //Starsphere
                for (int i = 0; i < StarSphereModels.Length; i++)
                {
                    Matrix4 ssworld = Matrix4.CreateTranslation(camera.Position);
                    if (StarSphereWorlds != null)
                    {
                        ssworld = StarSphereWorlds[i] * ssworld;
                    }
                    StarSphereModels[i].Draw(rstate, ssworld, Lighting.Empty);
                }
                //Render fog transition: if any
                if (nr != null)
                {
                    rstate.DepthEnabled = false;
                    nr.RenderFogTransition();
                    rstate.DepthEnabled = true;
                }
            }
            DebugRenderer.StartFrame(camera, rstate);
            Polyline.SetCamera(camera);
            commands.StartFrame();
            rstate.DepthEnabled = true;
            //Optimisation for dictionary lookups
            LightEquipRenderer.FrameStart();
            //Clear depth buffer for game objects
            rstate.ClearDepth();
            game.Billboards.Begin(camera, commands);
            JThreads.Instance.FinishExecute();             //Make sure visibility calculations are complete
            if (GLExtensions.Features430 && ExtraLights)
            {
                //Forward+ heck yeah!
                //ISSUES: Z prepass here doesn't work - gives blank texture  (investigate DepthMap.cs)
                //(WORKED AROUND) Lights being culled too aggressively - Pittsburgh planet light, intro_planet_chunks
                //Z test - cull transparent and opaque differently (opaqueLightBuffer enable)
                //Optimisation work needs to be done
                //When these are fixed this can be enabled by default
                //Copy lights into buffer
                int plc = pointLights.Count;
                using (var h = pointLightBuffer.Map()) {
                    var ptr = (PointLight *)h.Handle;
                    for (int i = 0; i < pointLights.Count; i++)
                    {
                        ptr[i] = pointLights[i];
                    }
                    //Does the rest of the buffer need to be cleared?
                }
                pointLights.Clear();
                //Setup Visible Buffers
                var tilesW = (Game.Width + (Game.Width % 16)) / 16;
                var tilesH = (Game.Height + (Game.Height % 16)) / 16;
                SystemLighting.NumberOfTilesX = tilesW;
                if (_twidth != tilesW || _theight != tilesH)
                {
                    _twidth  = tilesW;
                    _theight = tilesH;
                    //if (opaqueLightBuffer != null) opaqueLightBuffer.Dispose();
                    if (transparentLightBuffer != null)
                    {
                        transparentLightBuffer.Dispose();
                    }
                    //opaqueLightBuffer = new ShaderStorageBuffer((tilesW * tilesH) * 512 * sizeof(int));
                    transparentLightBuffer = new ShaderStorageBuffer((tilesW * tilesH) * 512 * sizeof(int));
                }
                //Depth
                if (_dwidth != Game.Width || _dheight != Game.Height)
                {
                    _dwidth  = Game.Width;
                    _dheight = Game.Height;
                    if (depthMap != null)
                    {
                        depthMap.Dispose();
                    }
                    depthMap = new DepthMap(Game.Width, game.Height);
                }
                depthMap.BindFramebuffer();
                rstate.ClearDepth();
                rstate.DepthFunction = DepthFunction.Less;
                for (int i = 0; i < Objects.Count; i++)
                {
                    if (Objects[i].Visible)
                    {
                        Objects[i].DepthPrepass(camera, rstate);
                    }
                }
                rstate.DepthFunction = DepthFunction.LessEqual;
                RenderTarget2D.ClearBinding();
                if (game.Config.MSAASamples > 0)
                {
                    msaa.Bind();
                }
                //Run compute shader
                pointLightBuffer.BindIndex(0);
                transparentLightBuffer.BindIndex(1);
                //opaqueLightBuffer.BindIndex(2);
                pointLightCull.Uniform1i("depthTexture", 7);
                depthMap.BindTo(7);
                pointLightCull.Uniform1i("numLights", plc);
                pointLightCull.Uniform1i("windowWidth", Game.Width);
                pointLightCull.Uniform1i("windowHeight", Game.Height);
                var v = camera.View;
                var p = camera.Projection;
                p.Invert();
                pointLightCull.UniformMatrix4fv("viewMatrix", ref v);
                pointLightCull.UniformMatrix4fv("invProjection", ref p);
                GL.MemoryBarrier(GL.GL_SHADER_STORAGE_BARRIER_BIT);                 //I don't think these need to be here - confirm then remove?
                pointLightCull.Dispatch((uint)tilesW, (uint)tilesH, 1);
                GL.MemoryBarrier(GL.GL_SHADER_STORAGE_BARRIER_BIT);
            }
            else
            {
                SystemLighting.NumberOfTilesX = -1;
                //Simple depth pre-pass
                rstate.DepthFunction = DepthFunction.Less;
                for (int i = 0; i < Objects.Count; i++)
                {
                    if (Objects[i].Visible)
                    {
                        Objects[i].DepthPrepass(camera, rstate);
                    }
                }
                rstate.DepthFunction = DepthFunction.LessEqual;
            }
            //Actual Drawing
            for (int i = 0; i < Objects.Count; i++)
            {
                if (Objects[i].Visible)
                {
                    Objects[i].Draw(camera, commands, SystemLighting, nr);
                }
            }
            for (int i = 0; i < AsteroidFields.Count; i++)
            {
                AsteroidFields[i].Draw(cache, SystemLighting, commands, nr);
            }
            game.Nebulae.NewFrame();
            if (nr == null)
            {
                for (int i = 0; i < Nebulae.Count; i++)
                {
                    Nebulae[i].Draw(commands);
                }
            }
            else
            {
                nr.Draw(commands);
            }
            game.Nebulae.SetData();
            game.Billboards.End();
            Polyline.FrameEnd();
            //Opaque Pass
            rstate.DepthEnabled = true;
            commands.DrawOpaque(rstate);
            //Transparent Pass
            rstate.DepthWrite = false;
            commands.DrawTransparent(rstate);
            rstate.DepthWrite = true;
            DebugRenderer.Render();
            if (Game.Config.MSAASamples > 0)
            {
                msaa.BlitToScreen();
            }
            rstate.DepthEnabled = true;
        }
Ejemplo n.º 2
0
        public unsafe void Draw()
        {
            if (gconfig.MSAASamples > 0)
            {
                if (_mwidth != Game.Width || _mheight != Game.Height)
                {
                    _mwidth  = Game.Width;
                    _mheight = Game.Height;
                    if (msaa != null)
                    {
                        msaa.Dispose();
                    }
                    msaa = new MultisampleTarget(Game.Width, Game.Height, gconfig.MSAASamples);
                }
                rstate.RenderTarget = msaa;
            }
            NebulaRenderer nr = CheckNebulae();             //are we in a nebula?

            bool transitioned = false;

            if (nr != null)
            {
                transitioned = nr.FogTransitioned();
            }
            rstate.DepthEnabled = true;
            //Add Nebula light
            if (GLExtensions.Features430 && ExtraLights)
            {
                //TODO: Re-add [LightSource] to the compute shader, it shouldn't regress.
                PointLight p2;
                if (nr != null && nr.DoLightning(out p2))
                {
                    pointLights.Add(p2);
                }
            }
            //Async calcs
            objects = new List <ObjectRenderer>(250);

            /*for (int i = 0; i < World.Objects.Count; i += 16)
             *          {
             *                  JThreads.Instance.AddTask((o) =>
             *                  {
             *                          var offset = (int)o;
             *                          for (int j = 0; j < 16 && ((j + offset) < World.Objects.Count); j++) World.Objects[j + offset].PrepareRender(camera, nr, this);
             *                  }, i);
             *          }
             *          JThreads.Instance.BeginExecute();*/
            for (int i = 0; i < World.Objects.Count; i++)
            {
                World.Objects[i].PrepareRender(camera, nr, this);
            }
            if (transitioned)
            {
                //Fully in fog. Skip Starsphere
                rstate.ClearColor = nr.Nebula.FogColor;
                rstate.ClearAll();
            }
            else
            {
                rstate.DepthEnabled = false;
                if (starSystem == null)
                {
                    rstate.ClearColor = NullColor;
                }
                else
                {
                    rstate.ClearColor = starSystem.BackgroundColor;
                }
                rstate.ClearAll();
                //Starsphere
                if (camera is ThnCamera thn)
                {
                    thn.DefaultZ();
                }
                for (int i = 0; i < StarSphereModels.Length; i++)
                {
                    Matrix4x4 ssworld = Matrix4x4.CreateTranslation(camera.Position);

                    if (StarSphereWorlds != null)
                    {
                        ssworld = StarSphereWorlds[i] * ssworld;
                    }
                    var lighting = Lighting.Empty;
                    if (StarSphereLightings != null)
                    {
                        lighting = StarSphereLightings[i];
                    }
                    StarSphereModels[i].DrawImmediate(rstate, resman, ssworld, ref lighting);
                }
                if (camera is ThnCamera thn2)
                {
                    thn2.CameraZ();
                }
                //Render fog transition: if any
                if (nr != null)
                {
                    rstate.DepthEnabled = false;
                    nr.RenderFogTransition();
                    rstate.DepthEnabled = true;
                }
            }
            DebugRenderer.StartFrame(camera, rstate);
            Polyline.SetCamera(camera);
            commands.StartFrame(rstate);
            rstate.DepthEnabled = true;
            //Optimisation for dictionary lookups
            LightEquipRenderer.FrameStart();
            //Clear depth buffer for game objects
            rstate.ClearDepth();
            billboards.Begin(camera, commands);
            //JThreads.Instance.FinishExecute(); //Make sure visibility calculations are complete
            if (GLExtensions.Features430 && ExtraLights)
            {
                //Forward+ heck yeah!
                //(WORKED AROUND) Lights being culled too aggressively - Pittsburgh planet light, intro_planet_chunks
                //Z test doesn't seem to be working (commented out in shader)
                //May need optimisation
                int plc = pointLights.Count;
                using (var h = pointLightBuffer.Map()) {
                    var ptr = (PointLight *)h.Handle;
                    for (int i = 0; i < pointLights.Count; i++)
                    {
                        ptr[i] = pointLights[i];
                    }
                }
                pointLights.Clear();
                //Setup Visible Buffers
                var tilesW = (Game.Width + (Game.Width % 16)) / 16;
                var tilesH = (Game.Height + (Game.Height % 16)) / 16;
                SystemLighting.NumberOfTilesX = tilesW;
                if (_twidth != tilesW || _theight != tilesH)
                {
                    _twidth  = tilesW;
                    _theight = tilesH;
                    //if (opaqueLightBuffer != null) opaqueLightBuffer.Dispose();
                    if (transparentLightBuffer != null)
                    {
                        transparentLightBuffer.Dispose();
                    }
                    //opaqueLightBuffer = new ShaderStorageBuffer((tilesW * tilesH) * 512 * sizeof(int));
                    transparentLightBuffer = new ShaderStorageBuffer((tilesW * tilesH) * 512 * sizeof(int));
                }
                //Depth
                if (_dwidth != Game.Width || _dheight != Game.Height)
                {
                    _dwidth  = Game.Width;
                    _dheight = Game.Height;
                    if (depthMap != null)
                    {
                        depthMap.Dispose();
                    }
                    depthMap = new DepthMap(Game.Width, game.Height);
                }
                depthMap.BindFramebuffer();
                rstate.ClearDepth();
                rstate.DepthFunction = DepthFunction.Less;
                foreach (var obj in objects)
                {
                    obj.DepthPrepass(camera, rstate);
                }
                rstate.DepthFunction = DepthFunction.LessEqual;
                rstate.RenderTarget  = null;
                if (gconfig.MSAASamples > 0)
                {
                    rstate.RenderTarget = msaa;
                }
                //Run compute shader
                pointLightBuffer.BindIndex(0);
                transparentLightBuffer.BindIndex(1);
                //opaqueLightBuffer.BindIndex(2);
                pointLightCull.Uniform1i("depthTexture", 7);
                depthMap.BindTo(7);
                pointLightCull.Uniform1i("numLights", plc);
                pointLightCull.Uniform1i("windowWidth", Game.Width);
                pointLightCull.Uniform1i("windowHeight", Game.Height);
                var v = camera.View;
                var p = camera.Projection;
                Matrix4x4.Invert(p, out p);
                pointLightCull.UniformMatrix4fv("viewMatrix", ref v);
                pointLightCull.UniformMatrix4fv("invProjection", ref p);
                GL.MemoryBarrier(GL.GL_SHADER_STORAGE_BARRIER_BIT);                 //I don't think these need to be here - confirm then remove?
                pointLightCull.Dispatch((uint)tilesW, (uint)tilesH, 1);
                GL.MemoryBarrier(GL.GL_SHADER_STORAGE_BARRIER_BIT);
            }
            else
            {
                SystemLighting.NumberOfTilesX = -1;
                //Simple depth pre-pass
                rstate.ColorWrite    = false;
                rstate.DepthFunction = DepthFunction.Less;
                foreach (var obj in objects)
                {
                    obj.DepthPrepass(camera, rstate);
                }
                rstate.DepthFunction = DepthFunction.LessEqual;
                rstate.ColorWrite    = true;
            }

            //Actual Drawing
            Beams.Begin(commands, resman, camera);
            foreach (var obj in objects)
            {
                obj.Draw(camera, commands, SystemLighting, nr);
            }
            Beams.End();
            FxPool.Draw(camera, Polyline, resman, DebugRenderer);
            for (int i = 0; i < AsteroidFields.Count; i++)
            {
                AsteroidFields[i].Draw(cache, SystemLighting, commands, nr);
            }
            nebulae.NewFrame();
            if (nr == null)
            {
                for (int i = 0; i < Nebulae.Count; i++)
                {
                    Nebulae[i].Draw(commands);
                }
            }
            else
            {
                nr.Draw(commands);
            }
            nebulae.SetData();
            billboards.End();
            Polyline.FrameEnd();
            //Opaque Pass
            rstate.DepthEnabled = true;
            commands.DrawOpaque(rstate);
            //Transparent Pass
            rstate.DepthWrite = false;
            commands.DrawTransparent(rstate);
            rstate.DepthWrite = true;
            PhysicsHook?.Invoke();
            foreach (var point in debugPoints)
            {
                var lX  = point + new Vector3(5, 0, 0);
                var lmX = point + new Vector3(-5, 0, 0);
                var lY  = point + new Vector3(0, -5, 0);
                var lmY = point + new Vector3(0, 5, 0);
                var lZ  = point + new Vector3(0, 0, 5);
                var lmZ = point + new Vector3(0, 0, -5);
                DebugRenderer.DrawLine(lX, lmX);
                DebugRenderer.DrawLine(lY, lmY);
                DebugRenderer.DrawLine(lZ, lmZ);
            }
            debugPoints = new Vector3[0];
            DebugRenderer.Render();
            if (gconfig.MSAASamples > 0)
            {
                msaa.BlitToScreen();
                rstate.RenderTarget = null;
            }
            rstate.DepthEnabled = true;
        }