static void Main(string[] args)
        {
            VertexBuffer     vertexBuffer     = null;
            IndexBuffer      indexBuffer      = null;
            Material         material         = null;
            MaterialInstance materialInstance = null;
            Texture          splatTexture     = null;
            int    renderable   = -1;
            int    cameraEntity = -1;
            Camera camera       = null;
            Skybox skybox       = null;

            var app = new Application(
                new WindowConfig()
            {
                Title = "point_sprites",
            },
                new ApplicationConfig()
                );

            app.Setup = (engine, view, scene) => {
                splatTexture = CreateSplatTexture(engine);

                Vertex[] kVertices   = new Vertex[NUM_POINTS];
                float[]  kPointSizes = new float[NUM_POINTS];
                ushort[] kIndices    = new ushort[NUM_POINTS];

                var dtheta = MathF.PI * 2 / NUM_POINTS;
                var dsize  = MAX_POINT_SIZE / NUM_POINTS;
                var dcolor = 256.0f / NUM_POINTS;

                byte[]       vbo       = new byte[NUM_POINTS * (8 + 4)];
                MemoryStream vboStream = new MemoryStream(vbo);
                BinaryWriter vboWriter = new BinaryWriter(vboStream);

                for (int i = 0; i < NUM_POINTS; i++)
                {
                    float theta = dtheta * i;
                    uint  c     = (uint)(dcolor * i);
                    kVertices[i].Position.X = MathF.Cos(theta);
                    kVertices[i].Position.Y = MathF.Sin(theta);
                    kVertices[i].Color      = 0xff000000u | c | (c << 8) | (c << 16);
                    kPointSizes[i]          = MIN_POINT_SIZE + dsize * i;
                    kIndices[i]             = (ushort)i;

                    vboWriter.Write(kVertices[i].Position.X);
                    vboWriter.Write(kVertices[i].Position.Y);
                    vboWriter.Write(kVertices[i].Color);
                }

                vertexBuffer = VertexBufferBuilder.Create()
                               .WithVertexCount(NUM_POINTS)
                               .WithBufferCount(2)
                               .WithAttribute(VertexAttribute.Position, 0, ElementType.Float2, 0, Marshal.SizeOf <Vertex>())
                               .WithAttribute(VertexAttribute.Color, 0, ElementType.UByte4, Marshal.SizeOf <Vector2>(), Marshal.SizeOf <Vertex>())
                               .WithNormalized(VertexAttribute.Color)
                               .WithAttribute(VertexAttribute.Custom0, 1, ElementType.Float, 0, Marshal.SizeOf <float>())
                               .Build(engine);
                vertexBuffer.SetBufferAt(engine, 0, vbo);
                vertexBuffer.SetBufferAt(engine, 1, kPointSizes);

                indexBuffer = IndexBufferBuilder.Create()
                              .WithIndexCount(NUM_POINTS)
                              .WithBufferType(IndexType.UShort)
                              .Build(engine);
                indexBuffer.SetBuffer(engine, kIndices);

                var sampleData = new SampleDataLoader();

                material = MaterialBuilder.Create()
                           .WithPackage(sampleData.LoadPointSprites())
                           .Build(engine);

                renderable = EntityManager.Create();

                materialInstance = material.CreateInstance();
                materialInstance.SetParameter("fade", splatTexture, new TextureSampler(SamplerMinFilter.Linear, SamplerMagFilter.Linear));

                RenderableBuilder.Create()
                .WithBoundingBox(
                    new Box(
                        new Vector3(-1, -1, -1),
                        new Vector3(1, 1, 1)
                        )
                    )
                .WithMaterial(0, materialInstance)
                .WithGeometry(0, PrimitiveType.Points, vertexBuffer, indexBuffer, 0, NUM_POINTS)
                .WithCulling(false)
                .WithReceiveShadows(false)
                .WithCastShadows(false)
                .Build(engine, renderable);

                scene.AddEntity(renderable);
                cameraEntity = EntityManager.Create();
                camera       = engine.CreateCamera(cameraEntity);

                view.Camera = camera;

                skybox = SkyboxBuilder.Create()
                         .WithColor(new Color(0.1f, 0.125f, 0.25f, 1.0f))
                         .Build(engine);
                scene.Skybox = skybox;
            };

            app.Animate = (engine, view, now) => {
                var zoom   = 1.5f;
                var width  = view.Viewport.Width;
                var height = view.Viewport.Height;
                var aspect = (float)width / height;

                camera.SetProjection(Projection.Ortho, -aspect * zoom, aspect * zoom, -zoom, zoom, 0, 1);

                var tcm = engine.TransformManager;
                tcm.SetTransform(tcm.GetInstance(renderable), Matrix4x4.CreateFromAxisAngle(Vector3.UnitZ, now));
            };

            app.Cleanup = (engine, view, scene) => {
                engine.Destroy(skybox);
                engine.Destroy(renderable);
                engine.Destroy(materialInstance);
                engine.Destroy(material);
                engine.Destroy(vertexBuffer);
                engine.Destroy(indexBuffer);

                engine.DestroyCameraComponent(cameraEntity);
                EntityManager.Destroy(cameraEntity);
            };

            app.Run();
        }
        static void Main(string[] args)
        {
            Texture          texture          = null;
            Skybox           skybox           = null;
            VertexBuffer     vertexBuffer     = null;
            IndexBuffer      indexBuffer      = null;
            Material         material         = null;
            MaterialInstance materialInstance = null;
            Camera           camera           = null;
            int cameraEntity = -1;
            int renderable   = -1;

            var app = new Application(
                new WindowConfig()
            {
                Title = "texturedquad"
            },
                new ApplicationConfig()
                );

            app.Setup = (engine, view, scene) => {
                var path = Path.Combine(app.RootAssetPath, "textures/Moss_01/Moss_01_Color.png");

                if (!File.Exists(path))
                {
                    Console.WriteLine("The texture {0} does not exist", path);
                    Environment.Exit(1);
                }

                using (var stream = File.OpenRead(path)) {
                    var imageResult = ImageResult.FromStream(stream, ColorComponents.RedGreenBlueAlpha);
                    Console.WriteLine("Loaded texture: {0}x{1}", imageResult.Width, imageResult.Height);

                    var pixelBuffer = new PixelBufferDescriptor(imageResult.Data, PixelDataFormat.Rgba, PixelDataType.UByte);

                    texture = TextureBuilder.Create()
                              .WithWidth(imageResult.Width)
                              .WithHeight(imageResult.Height)
                              .WithLevels(1)
                              .WithSampler(TextureSamplerType.Texture2d)
                              .WithFormat(TextureFormat.Rgba8)
                              .Build(engine);
                    texture.SetImage(engine, 0, pixelBuffer);
                }

                // Set up view
                skybox = SkyboxBuilder.Create()
                         .WithColor(new Color(0.1f, 0.125f, 0.25f, 1.0f))
                         .Build(engine);

                scene.Skybox = skybox;
                cameraEntity = EntityManager.Create();
                camera       = engine.CreateCamera(cameraEntity);

                view.PostProcessingEnabled = false;
                view.Camera = camera;

                // Create quad renderable
                var vbo = new VertexBufferObject();
                vbo.Write(new Vector2(-1, -1));
                vbo.Write(new Vector2(0, 0));
                vbo.Write(new Vector2(1, -1));
                vbo.Write(new Vector2(1, 0));
                vbo.Write(new Vector2(-1, 1));
                vbo.Write(new Vector2(0, 1));
                vbo.Write(new Vector2(1, 1));
                vbo.Write(new Vector2(1, 1));

                vertexBuffer = VertexBufferBuilder.Create()
                               .WithVertexCount(4)
                               .WithBufferCount(1)
                               .WithAttribute(VertexAttribute.Position, 0, ElementType.Float2, 0, 16)
                               .WithAttribute(VertexAttribute.Uv0, 0, ElementType.Float2, 8, 16)
                               .Build(engine);
                vertexBuffer.SetBufferAt(engine, 0, vbo);

                var sampleData = new SampleDataLoader();

                indexBuffer = IndexBufferBuilder.Create()
                              .WithIndexCount(6)
                              .WithBufferType(IndexType.UShort)
                              .Build(engine);
                indexBuffer.SetBuffer(engine, QUAD_INDICES);

                material = MaterialBuilder.Create()
                           .WithPackage(sampleData.LoadBakedTexture())
                           .Build(engine);

                var sampler = new TextureSampler(SamplerMinFilter.Linear, SamplerMagFilter.Linear);

                materialInstance = material.CreateInstance();
                materialInstance.SetParameter("albedo", texture, sampler);

                renderable = EntityManager.Create();

                RenderableBuilder.Create()
                .WithBoundingBox(
                    new Box(
                        new Vector3(-1, -1, -1),
                        new Vector3(1, 1, 1)
                        )
                    )
                .WithMaterial(0, materialInstance)
                .WithGeometry(0, PrimitiveType.Triangles, vertexBuffer, indexBuffer, 0, 6)
                .WithCulling(false)
                .WithReceiveShadows(false)
                .WithCastShadows(false)
                .Build(engine, renderable);

                scene.AddEntity(renderable);
            };

            app.Cleanup = (engine, view, scene) => {
                engine.Destroy(skybox);
                engine.Destroy(renderable);
                engine.Destroy(materialInstance);
                engine.Destroy(material);
                engine.Destroy(texture);
                engine.Destroy(vertexBuffer);
                engine.Destroy(indexBuffer);

                engine.DestroyCameraComponent(cameraEntity);
                EntityManager.Destroy(cameraEntity);
            };

            app.Animate = (engine, view, now) => {
                var zoom   = 2.0f + 2.0f * MathF.Sin(now);
                var width  = view.Viewport.Width;
                var height = view.Viewport.Height;
                var aspect = (float)width / (float)height;

                camera.SetProjection(Projection.Ortho,
                                     -aspect * zoom, aspect * zoom,
                                     -zoom, zoom,
                                     -1, 1
                                     );
            };

            app.Run();
        }
        static void Main(string[] args)
        {
            Skybox       skybox       = null;
            VertexBuffer vertexBuffer = null;
            IndexBuffer  indexBuffer  = null;
            Material     material     = null;
            int          renderable   = -1;
            Camera       camera       = null;
            int          cameraEntity = -1;

            var vbo = new VertexBufferObject();

            vbo.Write(new Vector2(1, 0));
            vbo.Write(0xffff0000u);
            vbo.Write(new Vector2(MathF.Cos(MathF.PI * 2 / 3), MathF.Sin(MathF.PI * 2 / 3)));
            vbo.Write(0xff00ff00u);
            vbo.Write(new Vector2(MathF.Cos(MathF.PI * 4 / 3), MathF.Sin(MathF.PI * 4 / 3)));
            vbo.Write(0xff0000ffu);

            var app = new Application(
                new WindowConfig()
            {
                Title = "hellotriangle",
            },
                new ApplicationConfig()
                );

            app.Setup = (engine, view, scene) => {
                skybox = SkyboxBuilder.Create()
                         .WithColor(new Color(0.1f, 0.125f, 0.25f, 1.0f))
                         .Build(engine);

                scene.Skybox = skybox;
                view.PostProcessingEnabled = false;

                vertexBuffer = VertexBufferBuilder.Create()
                               .WithVertexCount(3)
                               .WithBufferCount(1)
                               .WithAttribute(VertexAttribute.Position, 0, ElementType.Float2, 0, 12)
                               .WithAttribute(VertexAttribute.Color, 0, ElementType.UByte4, 8, 12)
                               .WithNormalized(VertexAttribute.Color)
                               .Build(engine);
                vertexBuffer.SetBufferAt(engine, 0, vbo);

                indexBuffer = IndexBufferBuilder.Create()
                              .WithIndexCount(3)
                              .WithBufferType(IndexType.UShort)
                              .Build(engine);
                indexBuffer.SetBuffer(engine, TRIANGLE_INDICES);

                var sampleData = new SampleDataLoader();

                material = MaterialBuilder.Create()
                           .WithPackage(sampleData.LoadBakedColor())
                           .Build(engine);

                renderable = EntityManager.Create();

                RenderableBuilder.Create()
                .WithBoundingBox(
                    new Box(
                        new Vector3(-1, -1, -1),
                        new Vector3(1, 1, 1)
                        )
                    )
                .WithMaterial(0, material.DefaultInstance)
                .WithGeometry(0, PrimitiveType.Triangles, vertexBuffer, indexBuffer, 0, 3)
                .WithCulling(false)
                .WithReceiveShadows(false)
                .WithCastShadows(false)
                .Build(engine, renderable);

                scene.AddEntity(renderable);

                cameraEntity = EntityManager.Create();
                camera       = engine.CreateCamera(cameraEntity);
                view.Camera  = camera;
            };

            app.Cleanup = (engine, view, scene) => {
                engine.Destroy(skybox);
                engine.Destroy(renderable);
                engine.Destroy(material);
                engine.Destroy(vertexBuffer);
                engine.Destroy(indexBuffer);
                engine.DestroyCameraComponent(cameraEntity);

                EntityManager.Destroy(cameraEntity);
            };

            app.Animate = (engine, view, now) => {
                var ZOOM = 1.5f;
                var w    = view.Viewport.Width;
                var h    = view.Viewport.Height;
                ;
                var aspect = (float)w / h;

                camera.SetProjection(Projection.Ortho, -aspect * ZOOM, aspect * ZOOM, -ZOOM, ZOOM, 0, 1);

                var tcm = engine.TransformManager;
                tcm.SetTransform(tcm.GetInstance(renderable), Matrix4x4.CreateFromAxisAngle(Vector3.UnitZ, now));
            };

            app.Run();
        }
        static void Main(string[] args)
        {
            Texture offscreenColorTexture = null;
            Texture offscreenDepthTexture = null;

            Filament.RenderTarget offscreenRenderTarget = null;
            View   offscreenView   = null;
            Scene  offscreenScene  = null;
            Camera offscreenCamera = null;

            int              lightEntity     = -1;
            Material         meshMaterial    = null;
            MaterialInstance meshMatInstance = null;
            Mesh             monkeyMesh      = null;
            int              reflectedMonkey = -1;
            Matrix4x4        transform       = Matrix4x4.Identity;

            int              quadEntity      = -1;
            Vector3          quadCenter      = Vector3.Zero;
            Vector3          quadNormal      = Vector3.Zero;
            VertexBuffer     quadVb          = null;
            IndexBuffer      quadIb          = null;
            Material         quadMaterial    = null;
            MaterialInstance quadMatInstance = null;
            ReflectionMode   mode            = ReflectionMode.Camera;

            var app = new Application(
                new WindowConfig()
            {
                Title = "rendertarget",
            },
                new ApplicationConfig()
                );

            app.Setup = (engine, view, scene) => {
                var tcm = engine.TransformManager;
                var rcm = engine.RenderableManager;
                var vp  = view.Viewport;

                var resourceData = new SampleDataLoader();
                var monkeyData   = new MonkeyDataLoader();

                // Instantiate offscreen render target.
                offscreenScene = engine.CreateScene();

                offscreenView       = engine.CreateView();
                offscreenView.Scene = offscreenScene;
                offscreenView.PostProcessingEnabled = false;

                offscreenColorTexture = TextureBuilder.Create()
                                        .WithWidth(vp.Width)
                                        .WithHeight(vp.Height)
                                        .WithLevels(1)
                                        .WithUsage(TextureUsage.ColorAttachment | TextureUsage.Sampleable)
                                        .WithFormat(TextureFormat.Rgba8)
                                        .Build(engine);

                offscreenDepthTexture = TextureBuilder.Create()
                                        .WithWidth(vp.Width)
                                        .WithHeight(vp.Height)
                                        .WithLevels(1)
                                        .WithUsage(TextureUsage.DepthAttachment)
                                        .WithFormat(TextureFormat.Depth24)
                                        .Build(engine);

                offscreenRenderTarget = RenderTargetBuilder.Create()
                                        .WithTexture(AttachmentPoint.Color, offscreenColorTexture)
                                        .WithTexture(AttachmentPoint.Depth, offscreenDepthTexture)
                                        .Build(engine);

                offscreenView.RenderTarget = offscreenRenderTarget;
                offscreenView.Viewport     = new Viewport(0, 0, vp.Width, vp.Height);

                offscreenCamera      = engine.CreateCamera(EntityManager.Create());
                offscreenView.Camera = offscreenCamera;

                app.AddOffscreenView(offscreenView);

                // Position and orient the mirror in an interesting way.
                var c = quadCenter = new Vector3(-2, 0, -5);
                var n = quadNormal = Vector3.Normalize(new Vector3(1, 0, 2));
                var u = Vector3.Normalize(Vector3.Cross(quadNormal, new Vector3(0, 1, 0)));
                var v = Vector3.Cross(n, u);
                u = 1.5f * u;
                v = 1.5f * v;

                Vertex[] kQuadVertices =
                {
                    new() { Position = c - u - v, Uv = new Vector2(1, 0) },
                    new() { Position = c + u - v, Uv = new Vector2(0, 0) },
                    new() { Position = c - u + v, Uv = new Vector2(1, 1) },
                    new() { Position = c + u + v, Uv = new Vector2(0, 1) },
                };

                var vbo = new byte[20 * 4];

                MemoryStream vboStream = new MemoryStream(vbo);
                BinaryWriter vboWriter = new BinaryWriter(vboStream);
                vboWriter.Write(kQuadVertices[0].Position.X);
                vboWriter.Write(kQuadVertices[0].Position.Y);
                vboWriter.Write(kQuadVertices[0].Position.Z);
                vboWriter.Write(kQuadVertices[0].Uv.X);
                vboWriter.Write(kQuadVertices[0].Uv.Y);
                vboWriter.Write(kQuadVertices[1].Position.X);
                vboWriter.Write(kQuadVertices[1].Position.Y);
                vboWriter.Write(kQuadVertices[1].Position.Z);
                vboWriter.Write(kQuadVertices[1].Uv.X);
                vboWriter.Write(kQuadVertices[1].Uv.Y);
                vboWriter.Write(kQuadVertices[2].Position.X);
                vboWriter.Write(kQuadVertices[2].Position.Y);
                vboWriter.Write(kQuadVertices[2].Position.Z);
                vboWriter.Write(kQuadVertices[2].Uv.X);
                vboWriter.Write(kQuadVertices[2].Uv.Y);
                vboWriter.Write(kQuadVertices[3].Position.X);
                vboWriter.Write(kQuadVertices[3].Position.Y);
                vboWriter.Write(kQuadVertices[3].Position.Z);
                vboWriter.Write(kQuadVertices[3].Uv.X);
                vboWriter.Write(kQuadVertices[3].Uv.Y);

                // Create quad vertex buffer.
                quadVb = VertexBufferBuilder.Create()
                         .WithVertexCount(4)
                         .WithBufferCount(1)
                         .WithAttribute(VertexAttribute.Position, 0, ElementType.Float3, 0, 20)
                         .WithAttribute(VertexAttribute.Uv0, 0, ElementType.Float2, 12, 20)
                         .Build(engine);
                quadVb.SetBufferAt(engine, 0, vbo);

                // Create quad index buffer.
                var kQuadIndices = new ushort[] { 0, 1, 2, 3, 2, 1 };

                quadIb = IndexBufferBuilder.Create()
                         .WithIndexCount(6)
                         .WithBufferType(IndexType.UShort)
                         .Build(engine);
                quadIb.SetBuffer(engine, kQuadIndices);

                // Create quad material and renderable.
                quadMaterial = MaterialBuilder.Create()
                               .WithPackage(resourceData.LoadMirror())
                               .Build(engine);
                quadMatInstance = quadMaterial.CreateInstance();

                var sampler = new TextureSampler(SamplerMinFilter.Linear, SamplerMagFilter.Linear);

                quadMatInstance.SetParameter("albedo", offscreenColorTexture, sampler);
                quadEntity = EntityManager.Create();

                RenderableBuilder.Create()
                .WithBoundingBox(
                    new Box(
                        new Vector3(-1, -1, -1),
                        new Vector3(1, 1, 1)
                        )
                    )
                .WithMaterial(0, quadMatInstance)
                .WithGeometry(0, PrimitiveType.Triangles, quadVb, quadIb, 0, 6)
                .WithCulling(false)
                .WithReceiveShadows(false)
                .WithCastShadows(false)
                .Build(engine, quadEntity);

                scene.AddEntity(quadEntity);

                // Instantiate mesh material.
                meshMaterial = MaterialBuilder.Create()
                               .WithPackage(resourceData.LoadAiDefaultMat())
                               .Build(engine);

                var mi = meshMatInstance = meshMaterial.CreateInstance();
                mi.SetParameter("baseColor", RgbType.Linear, new Color(0.8f, 1.0f, 1.0f));
                mi.SetParameter("metallic", 0.0f);
                mi.SetParameter("roughness", 0.4f);
                mi.SetParameter("reflectance", 0.5f);

                // Add monkey into the scene.
                monkeyMesh = MeshReader.LoadFromBuffer(engine, monkeyData.LoadSuzanne(), mi);

                var ti = tcm.GetInstance(monkeyMesh.Renderable);

                transform = Matrix4x4.CreateTranslation(0, 0, -4) * tcm.GetWorldTransform(ti);
                rcm.SetCastShadows(rcm.GetInstance(monkeyMesh.Renderable), false);
                scene.AddEntity(monkeyMesh.Renderable);

                // Create a reflected monkey, which is used only for ReflectionMode::RENDERABLES.
                reflectedMonkey = EntityManager.Create();

                RenderableBuilder.Create()
                .WithBoundingBox(
                    new Box(
                        new Vector3(-2, -2, -2),
                        new Vector3(2, 2, 2)
                        )
                    )
                .WithMaterial(0, mi)
                .WithGeometry(0, PrimitiveType.Triangles, monkeyMesh.VertexBuffer, monkeyMesh.IndexBuffer)
                .WithReceiveShadows(true)
                .WithCastShadows(false)
                .Build(engine, reflectedMonkey);
                mode = SetReflectionMode(offscreenScene, offscreenView, reflectedMonkey, monkeyMesh, ReflectionMode.Camera);

                // Add light source to both scenes.
                // NOTE: this is slightly wrong when the reflection mode is RENDERABLES.
                lightEntity = EntityManager.Create();

                LightBuilder.Create(LightType.Sun)
                .WithColor(Color.ToLinearAccurate(new sRGBColor(0.98f, 0.92f, 0.89f)))
                .WithIntensity(110000)
                .WithDirection(new Vector3(0.7f, -1, -0.8f))
                .WithSunAngularRadius(1.9f)
                .WithCastShadows(false)
                .Build(engine, lightEntity);

                scene.AddEntity(lightEntity);
                offscreenScene.AddEntity(lightEntity);
            };