Exemplo n.º 1
0
        static void RunGame()
        {
            TimeStopwatch = Stopwatch.StartNew();
            InitConsole();

            Engine.VFS = new VirtualFileSystem(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
            Engine.VFS.Mount("/content/", "./content");
            Engine.VFS.Mount("/materials/", "C:/Program Files (x86)/Steam/steamapps/common/GarrysMod/garrysmod/addons/quake_3_gmod_160207505/materials");

            string[] SourceGameDirs = Engine.SourceGameDirs.Value.Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries).Where(Pth => Directory.Exists(Pth)).ToArray();

            if (SourceGameDirs.Length > 0)
            {
                foreach (var GameDir in SourceGameDirs)
                {
                    Engine.VFS.GetSourceProvider().AddRoot(GameDir);
                }
            }

            if (Directory.Exists(Path.Combine(Engine.GamePath, "content")))
            {
                Engine.VFS.Mount("/content/", Path.Combine(Engine.GamePath, "content"));
            }

            List <string> ZipResources = new List <string>();

            ZipResources.AddRange(Engine.VFS.GetFiles("/content/").Where(P => Path.GetExtension(P) == ".pk3" || Path.GetExtension(P) == ".zip"));

            foreach (var ZipResource in ZipResources)
            {
                Engine.VFS.MountArchive("/content/", ZipResource);
            }

            FileWatcher.Init("content");
            Importers.RegisterAll(Reflect.GetExeAssembly());

            Engine.GUI = new NuklearGUI();

            Engine.Window              = new RenderWindow(Engine.WindowWidth, Engine.WindowHeight, "libTech", Engine.WindowResizable);
            Engine.Window.OnMouseMove += Engine.GUI.OnMouseMove;
            Engine.Window.OnKey       += OnKey;
            Engine.Window.OnChar      += Engine.GUI.OnChar;

            RenderDoc.Init();

            GConsole.Init();
            GConsole.WriteLine("Running {0}", RenderAPI.Renderer, RenderAPI.Version);

            string ExtensionsFile = "extensions.txt";

            if (File.Exists(ExtensionsFile))
            {
                File.Delete(ExtensionsFile);
            }

            File.WriteAllLines(ExtensionsFile, RenderAPI.Extensions);
            EngineRenderer.Init();

            Engine.GUI.Init(Engine.Window, new ShaderProgram(new ShaderStage(ShaderType.VertexShader, "content/shaders/gui.vert"), new ShaderStage(ShaderType.FragmentShader, "content/shaders/gui.frag")));
            Engine.UI = new libGUI(Engine.Window);

            DbgDraw.Init();
            Lua.Init();

            GConsole.Color = Color.Orange;
            foreach (var DllName in FailedToLoadDLLs)
            {
                GConsole.WriteLine("Failed to load '{0}'", DllName);
            }
            GConsole.Color = Color.White;

            // Graphics init
            Gfx.ShadersDirectory = "content/shaders";
            //Gfx.Line3D = DefaultShaders.Line3D;
            //Gfx.Point3D = DefaultShaders.Point3D;
            //Gfx.Default3D = DefaultShaders.DefaultColor3D;

            // Camera init
            Engine.Camera2D = new Camera();
            Engine.Camera2D.SetOrthogonal(0, 0, Engine.Window.WindowWidth, Engine.Window.WindowHeight);

            Engine.Camera3D = new Camera();
            Engine.Camera3D.SetPerspective(Engine.Window.WindowWidth, Engine.Window.WindowHeight, FarPlane: 16000);

            LoadGameDll(Engine.GamePath);

            Stopwatch SWatch = Stopwatch.StartNew();

            int MaxFPS = Engine.MaxFPS;

            if (MaxFPS <= 0)
            {
                MaxFPS = 900;
            }

            float FrameCap = 1.0f / MaxFPS;
            float Dt       = 1.0f / 60.0f;

            while (!Engine.Window.ShouldClose)
            {
                Engine.FrameTime.Push(Dt);

                Update(Dt);
                EngineRenderer.Draw(Dt);

                // TODO: Move frame cap somewhere else
                while ((SWatch.ElapsedMilliseconds / 1000.0f) < FrameCap)
                {
                    Thread.Sleep(0);
                }

                Dt = SWatch.ElapsedMilliseconds / 1000.0f;
                SWatch.Restart();
            }
        }
Exemplo n.º 2
0
        public static void Draw(float Dt, bool AmbientLighting = true, bool PointLighting = true)
        {
            RenderDoc.StartFrame();
            Engine.GetTexture("skybox").BindTextureUnit(10);

            DbgDraw.Enabled = Engine.DebugDraw;
            ShaderUniforms.Current.Resolution = Engine.Window.WindowSize;

            // Deferred opaque pass
            RenderAPI.DbgPushGroup("Deferred opaque pass");
            Engine.GBuffer.Push();

            {
                RenderState RS = Gfx.PeekRenderState();
                RS.EnableBlend = false;
                Gfx.PushRenderState(RS);
                Gfx.Clear(Color.Transparent);

                ShaderUniforms.Current.Camera = Engine.Camera3D;

                Engine.Map?.DrawOpaque();
                Engine.Game.DrawOpaque();

                Gfx.PopRenderState();
            }
            Engine.GBuffer.Pop();
            RenderAPI.DbgPopGroup();

            // Lighting/transparency pass
            RenderAPI.DbgPushGroup("Lighting/transparency pass");
            Engine.ScreenRT.Push();
            {
                // Clear canvas, copy depth buffer, draw skybox
                RenderAPI.DbgMessage("Lighting/transparency pass");

                Gfx.Clear(Color.Black);
                Engine.GBuffer.Framebuffer.Blit(false, true, false, Destination: Engine.ScreenRT.Framebuffer);
                Engine.Map?.DrawSkybox();

                Engine.GBuffer.Color.BindTextureUnit(0);
                Engine.GBuffer.Position.BindTextureUnit(1);
                Engine.GBuffer.Normal.BindTextureUnit(2);
                Engine.GBuffer.DepthStencil.BindTextureUnit(3);

                {
                    RenderState State = Gfx.PeekRenderState();
                    State.FrontFace       = FrontFace.CounterClockwise;
                    State.EnableBlend     = true;
                    State.BlendFunc_Src   = BlendFactor.SrcAlpha;
                    State.BlendFunc_Dst   = BlendFactor.One;
                    State.EnableDepthTest = false;

                    Gfx.PushRenderState(State);
                    ShaderUniforms.Current.Camera = Engine.Camera2D;

                    if (AmbientLighting)
                    {
                        RenderAPI.DbgPushGroup("Deferred ambient");
                        // Ambient lighting
                        ShaderProgram AmbientShader = Engine.GetShader("deferred_ambient");
                        AmbientShader.Bind(ShaderUniforms.Current);
                        Engine.ScreenQuad.Draw();
                        AmbientShader.Unbind();
                        RenderAPI.DbgPopGroup();
                    }

                    // Point lighting
                    Gfx.PopRenderState();
                    State.FrontFace         = FrontFace.CounterClockwise;
                    State.EnableDepthMask   = false;
                    State.EnableDepthTest   = true;
                    State.EnableStencilTest = true;
                    Gfx.PushRenderState(State);
                    ShaderUniforms.Current.Camera = Engine.Camera3D;

                    if (Engine.Map != null && PointLighting)
                    {
                        DynamicLight[] Lights = Engine.Map.GetLights();
                        RenderAPI.DbgPushGroup("Point lighting");

                        for (int i = 0; i < Lights.Length; i++)
                        {
                            DbgDraw.DrawCross(Lights[i].Position);

                            State.SetColorMask(false);
                            State.EnableBlend     = false;
                            State.EnableDepthTest = true;
                            State.EnableCullFace  = false;

                            State.StencilFunc(StencilFunction.Always, 0, 0);
                            State.StencilOpSeparate(StencilFace.Front, StencilOperation.Keep, StencilOperation.IncrWrap, StencilOperation.Keep);
                            State.StencilOpSeparate(StencilFace.Back, StencilOperation.Keep, StencilOperation.DecrWrap, StencilOperation.Keep);

                            State.DepthFunc = DepthFunc.LessOrEqual;

                            Gfx.PushRenderState(State);
                            Gfx.ClearStencil();

                            DrawPointLightMask(Lights[i]);
                            DrawPointLightShadow(Lights[i]);

                            Gfx.PopRenderState();

                            State.EnableBlend = true;
                            State.SetColorMask(true);
                            State.EnableDepthTest = false;
                            State.EnableCullFace  = true;
                            State.StencilFunc(StencilFunction.Equal, 1, 0xFF);
                            State.StencilOp(StencilOperation.Keep, StencilOperation.Keep, StencilOperation.Keep);
                            Gfx.PushRenderState(State);

                            ShadePointLight(Lights[i]);

                            Gfx.PopRenderState();
                        }

                        RenderAPI.DbgPopGroup();
                    }

                    Gfx.PopRenderState();
                }
                Engine.GBuffer.DepthStencil.UnbindTextureUnit(3);
                Engine.GBuffer.Normal.UnbindTextureUnit(2);
                Engine.GBuffer.Position.UnbindTextureUnit(1);
                Engine.GBuffer.Color.UnbindTextureUnit(0);

                // Draw transparent items
                RenderAPI.DbgPushGroup("Transparent items");
                Engine.Map?.DrawTransparent();
                Engine.Game.DrawTransparent();
                RenderAPI.DbgPopGroup();

                // Draw debug lines
                DbgDraw.FinalizeDraw((long)(Engine.Time * 1000));
            }
            Engine.ScreenRT.Pop();
            RenderAPI.DbgPopGroup();

            RenderAPI.DbgPushGroup("2D pass");
            {
                RenderState State = Gfx.PeekRenderState();
                State.EnableDepthTest = false;
                Gfx.PushRenderState(State);
                {
                    Gfx.Clear();
                    ShaderUniforms.Current.Camera           = Engine.Camera2D;
                    ShaderUniforms.Current.TextureSize      = Engine.ScreenRT.Color.Size;
                    ShaderUniforms.Current.MultisampleCount = Engine.ScreenRT.Color.Multisamples;
                    Gfx.TexturedRectangle(0, 0, Engine.Window.WindowWidth, Engine.Window.WindowHeight, Texture: Engine.ScreenRT.Color, Shader: Engine.GetShader("framebuffer"));

                    Engine.GUI.Draw(() => {
                        float FT           = Engine.FrameTime.Average();
                        float FPS          = 1.0f / FT;
                        string DebugString = string.Format("{0} ms\n{1} FPS\n{2} Lights", FT, FPS, Engine.Map.GetLights().Length);
                        int Lines          = 3;

                        Gfx.DrawText(Engine.UI.DebugFont, new Vector2(2, Engine.WindowHeight - Engine.UI.DebugFont.ScaledLineHeight * Lines - 2), DebugString, Color.White);

                        Engine.UI.Draw();
                        Engine.Game.DrawGUI(Dt);
                    });
                }
                Gfx.PopRenderState();
            }
            RenderAPI.DbgPopGroup();
            Engine.Window.SwapBuffers();

            RenderDoc.EndFrame();
        }