Example #1
0
        public void Run()
        {
            CreateAndActivateDefaultMaterial();

            // Use Grasshopper's procedural tools to create a cube mesh
            var mesh = CubeBuilder.New
                .Size(0.25f)
                .ToMesh("cube", v => new Vertex(v.Position, v.Color));

            // A mesh buffer manager allows us to pack multiple meshes
            // into a vertex buffer and accompanying index buffer, and
            // keep track of the offset locations of each mesh in each
            // buffer. In our case we're only storing one mesh.
            var meshBuffer = _meshBufferManager.Create("default", mesh);
            meshBuffer.Activate();
            var cubeData = meshBuffer["cube"];

            // Create a set of cube instance data with different sizes
            // and rotation values for each cube instance
            var rand = new Random();
            const int instanceCount = 100000;
            var instances = Enumerable.Range(0, instanceCount)
                .Select(i =>
                {
                    // rotation on each axis
                    var rotX = rand.Next(200) - 100.0f;
                    var rotY = rand.Next(200) - 100.0f;
                    var rotZ = rand.Next(200) - 100.0f;
                    // rotation speed
                    var rotS = (rand.Next(190) + 10) / 100.0f;
                    // cube offset from the origin
                    var posX = (rand.Next(10000) - 5000) / 100.0f;
                    var posY = (rand.Next(10000) - 5000) / 100.0f;
                    var posZ = (rand.Next(10000) - 5000) / 100.0f;
                    // cube size variation
                    var scale = (rand.Next(8) == 0 ? (rand.Next(800) + 100.0f) : rand.Next(200) + 50.0f) / 100.0f;
                    return new CubeInstance
                    {
                        Position = new Vector4(posX, posY, posZ, 0),
                        Rotation = new Vector4(rotX, rotY, rotZ, rotS),
                        Scale = new Vector4(scale, scale, scale, 1)
                    };
                });

            // Create an instance buffer and write the instance data to
            // it, then active the buffer in slot 1, so that its values
            // will be included for each vertex in the vertex shader
            var instanceBuffer = _instanceBufferManager.Create("default");
            using(var writer = instanceBuffer.BeginWrite(instanceCount))
                writer.Write(instances.ToArray());
            instanceBuffer.Activate(1);

            // Create our initial view and projection matrices that
            // will represent the camera view, location and orientation
            var view = Matrix4x4.CreateLookAt(new Vector3(0, 1.25f, -75f), new Vector3(0, 0, 0), Vector3.UnitY);

            // Create and activate our constant buffer which will hold
            // the world-view-projection data and time siagnture for
            // use by the vertex shader
            var constantBuffer = _constantBufferManager.Create("cube");
            constantBuffer.Activate(0);

            // The aspect ratio changes when the window is resized, so
            // we need to reculate the projection matrix, or our cube
            // will look squashed
            var hasWindowSizeChanged = true;
            _renderTarget.Window.SizeChanged += win => hasWindowSizeChanged = true;

            // Define the data that will go into the constant buffer
            var sceneData = new SceneData { View = Matrix4x4.Transpose(view) };
            constantBuffer.Update(ref sceneData);

            // Let the looping begin!
            _app.Run(_renderTarget, context =>
            {
                // This is always true the first time, so our
                // projection matrix is created here. Each iteration of
                // the render loop we'll update the constant buffer
                // with the current number of elapsed seconds, and the
                // current view and projection matrices
                if(hasWindowSizeChanged)
                {
                    hasWindowSizeChanged = false;
                    sceneData.Projection = Matrix4x4.Transpose(CreateProjectionMatrix(context.Window));
                }
                sceneData.SecondsElapsed = _app.ElapsedSeconds;
                constantBuffer.Update(ref sceneData);

                context.Clear(Color.CornflowerBlue);
                context.SetDrawType(cubeData.DrawType);
                context.DrawIndexedInstanced(cubeData.IndexCount, instanceCount, cubeData.IndexBufferOffset, cubeData.VertexBufferOffset, 0);
                context.Present();
            });
        }
Example #2
0
        public void Run()
        {
            CreateAndActivateDefaultMaterial();

            // Use Grasshopper's procedural tools to create a cube mesh
            var mesh = CubeBuilder.New
                       .Size(0.25f)
                       .ToMesh("cube", v => new Vertex(v.Position, v.Color));

            // A mesh buffer manager allows us to pack multiple meshes into a vertex buffer and accompanying index
            // buffer, and keep track of the offset locations of each mesh in each buffer. In our case we're only
            // storing one mesh.
            var meshBuffer = _meshBufferManager.Create("default", mesh);

            meshBuffer.Activate();
            var cubeData = meshBuffer["cube"];

            // Create a set of cube instance data with different sizes and rotation values for each cube instance
            var       rand          = new Random();
            const int instanceCount = 100000;
            var       instances     = Enumerable.Range(0, instanceCount)
                                      .Select(i =>
            {
                // rotation on each axis
                var rotX = rand.Next(200) - 100.0f;
                var rotY = rand.Next(200) - 100.0f;
                var rotZ = rand.Next(200) - 100.0f;
                // rotation speed
                var rotS = (rand.Next(190) + 10) / 100.0f;
                // cube offset from the origin
                var posX = (rand.Next(10000) - 5000) / 100.0f;
                var posY = (rand.Next(10000) - 5000) / 100.0f;
                var posZ = (rand.Next(10000) - 5000) / 100.0f;
                // cube size variation
                var scale = (rand.Next(8) == 0 ? (rand.Next(800) + 100.0f) : rand.Next(200) + 50.0f) / 100.0f;
                return(new CubeInstance
                {
                    Position = new Vector4(posX, posY, posZ, 0),
                    Rotation = new Vector4(rotX, rotY, rotZ, rotS),
                    Scale = new Vector4(scale, scale, scale, 1)
                });
            });

            // Create an instance buffer and write the instance data to it, then active the buffer in slot 1, so
            // that its values will be included for each vertex in the vertex shader
            var instanceBuffer = _instanceBufferManager.Create("default");

            using (var writer = instanceBuffer.BeginWrite(instanceCount))
                writer.Write(instances.ToArray());
            instanceBuffer.Activate(1);

            // Create our initial view and projection matrices that will represent the camera
            var view = Matrix4x4.CreateLookAt(new Vector3(0, 1.25f, -75f), new Vector3(0, 0, 0), Vector3.UnitY);

            // Create and activate our constant buffer which will hold the world-view-projection data and time
            // signature for use by the vertex shader
            var constantBuffer = _constantBufferManager.Create("cube");

            constantBuffer.Activate(0);

            // The aspect ratio changes when the window is resized, so we need to reculate the projection matrix,
            // or our cube will look squashed
            var hasWindowSizeChanged = true;

            _renderTarget.Window.SizeChanged += win => hasWindowSizeChanged = true;

            // Define the data that will go into the constant buffer
            var sceneData = new SceneData {
                View = Matrix4x4.Transpose(view)
            };

            constantBuffer.Update(ref sceneData);

            // Let the looping begin!
            _app.Run(_renderTarget, (frame, context) =>
            {
                // This is always true the first time, so our projection matrix is created here. Each iteration of
                // the render loop we'll update the constant buffer with the current number of elapsed seconds,
                // and the current view and projection matrices
                if (hasWindowSizeChanged)
                {
                    hasWindowSizeChanged = false;
                    sceneData.Projection = Matrix4x4.Transpose(CreateProjectionMatrix(context.Window));
                }
                sceneData.SecondsElapsed = _app.ElapsedSeconds;
                constantBuffer.Update(ref sceneData);

                context.Clear(Color.CornflowerBlue);
                context.SetDrawType(cubeData.DrawType);
                context.DrawIndexedInstanced(cubeData.IndexCount, instanceCount, cubeData.IndexBufferOffset, cubeData.VertexBufferOffset, 0);
                context.Present();
            });
        }