protected override void CreateResources(ResourceFactory factory)
        {
            _instanceCount = 8000u;

            _camera.Position = new Vector3(-36f, 20f, 100f);
            _camera.Pitch    = -0.3f;
            _camera.Yaw      = 0.1f;

            _cameraProjViewBuffer = factory.CreateBuffer(
                new BufferDescription((uint)(Unsafe.SizeOf <Matrix4x4>() * 2), BufferUsage.UniformBuffer | BufferUsage.Dynamic));
            _lightInfoBuffer    = factory.CreateBuffer(new BufferDescription(32, BufferUsage.UniformBuffer | BufferUsage.Dynamic));
            _rotationInfoBuffer = factory.CreateBuffer(new BufferDescription(16, BufferUsage.UniformBuffer | BufferUsage.Dynamic));
            _lightDir           = Vector3.Normalize(new Vector3(0.3f, -0.75f, -0.3f));

            VertexLayoutDescription sharedVertexLayout = new VertexLayoutDescription(
                new VertexElementDescription("Position", VertexElementSemantic.Position, VertexElementFormat.Float3),
                new VertexElementDescription("Normal", VertexElementSemantic.Normal, VertexElementFormat.Float3),
                new VertexElementDescription("TexCoord", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float2));

            bool etc2Supported = GraphicsDevice.GetPixelFormatSupport(
                PixelFormat.ETC2_R8_G8_B8_UNorm,
                TextureType.Texture2D,
                TextureUsage.Sampled);
            PixelFormat pixelFormat = etc2Supported ? PixelFormat.ETC2_R8_G8_B8_UNorm : PixelFormat.BC3_UNorm;

            byte[] rockTextureData = LoadEmbeddedAsset <byte[]>(
                etc2Supported
                    ? "texturearray_rocks_etc2_unorm.binary"
                    : "texturearray_rocks_bc3_unorm.binary");
            Texture rockTexture = KtxFile.LoadTexture(
                GraphicsDevice,
                ResourceFactory,
                rockTextureData,
                pixelFormat);
            TextureView rockTextureView = ResourceFactory.CreateTextureView(rockTexture);

            ResourceLayoutElementDescription[] resourceLayoutElementDescriptions =
            {
                new ResourceLayoutElementDescription("ProjView",     ResourceKind.UniformBuffer, ShaderStages.Vertex),
                new ResourceLayoutElementDescription("RotationInfo", ResourceKind.UniformBuffer, ShaderStages.Vertex),
                new ResourceLayoutElementDescription("LightInfo",    ResourceKind.UniformBuffer, ShaderStages.Fragment),
            };
            ResourceLayoutDescription resourceLayoutDescription = new ResourceLayoutDescription(resourceLayoutElementDescriptions);
            ResourceLayout            sharedLayout = factory.CreateResourceLayout(resourceLayoutDescription);

            ResourceLayoutElementDescription[] textureLayoutDescriptions =
            {
                new ResourceLayoutElementDescription("Tex",  ResourceKind.TextureReadOnly, ShaderStages.Fragment),
                new ResourceLayoutElementDescription("Samp", ResourceKind.Sampler,         ShaderStages.Fragment)
            };
            ResourceLayout textureLayout = factory.CreateResourceLayout(new ResourceLayoutDescription(textureLayoutDescriptions));

            BindableResource[]     bindableResources      = new BindableResource[] { _cameraProjViewBuffer, _rotationInfoBuffer, _lightInfoBuffer };
            ResourceSetDescription resourceSetDescription = new ResourceSetDescription(sharedLayout, bindableResources);

            _sharedResourceSet = factory.CreateResourceSet(resourceSetDescription);

            BindableResource[] instanceBindableResources = { rockTextureView, GraphicsDevice.LinearSampler };
            _instanceTextureSet = factory.CreateResourceSet(new ResourceSetDescription(textureLayout, instanceBindableResources));

            ProcessedModel rock = LoadEmbeddedAsset <ProcessedModel>("rock01.binary");

            _rockModel = rock.MeshParts[0].CreateDeviceResources(GraphicsDevice, ResourceFactory);

            VertexLayoutDescription vertexLayoutPerInstance = new VertexLayoutDescription(
                new VertexElementDescription("InstancePosition", VertexElementSemantic.Position, VertexElementFormat.Float3),
                new VertexElementDescription("InstanceRotation", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float3),
                new VertexElementDescription("InstanceScale", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float3),
                new VertexElementDescription("InstanceTexArrayIndex", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Int1));

            vertexLayoutPerInstance.InstanceStepRate = 1;
            _instanceVB = ResourceFactory.CreateBuffer(new BufferDescription(InstanceInfo.Size * _instanceCount, BufferUsage.VertexBuffer));
            InstanceInfo[] infos         = new InstanceInfo[_instanceCount];
            Random         r             = new Random();
            float          orbitDistance = 50f;

            for (uint i = 0; i < _instanceCount / 2; i++)
            {
                float angle = (float)(r.NextDouble() * Math.PI * 2);
                infos[i] = new InstanceInfo(
                    new Vector3(
                        ((float)Math.Cos(angle) * orbitDistance) + (float)(-10 + r.NextDouble() * 20),
                        (float)(-1.5 + r.NextDouble() * 3),
                        ((float)Math.Sin(angle) * orbitDistance) + (float)(-10 + r.NextDouble() * 20)),
                    new Vector3(
                        (float)(r.NextDouble() * Math.PI * 2),
                        (float)(r.NextDouble() * Math.PI * 2),
                        (float)(r.NextDouble() * Math.PI * 2)),
                    new Vector3((float)(0.65 + r.NextDouble() * 0.35)),
                    r.Next(0, (int)rockTexture.ArrayLayers));
            }

            orbitDistance = 100f;
            for (uint i = _instanceCount / 2; i < _instanceCount; i++)
            {
                float angle = (float)(r.NextDouble() * Math.PI * 2);
                infos[i] = new InstanceInfo(
                    new Vector3(
                        ((float)Math.Cos(angle) * orbitDistance) + (float)(-10 + r.NextDouble() * 20),
                        (float)(-1.5 + r.NextDouble() * 3),
                        ((float)Math.Sin(angle) * orbitDistance) + (float)(-10 + r.NextDouble() * 20)),
                    new Vector3(
                        (float)(r.NextDouble() * Math.PI * 2),
                        (float)(r.NextDouble() * Math.PI * 2),
                        (float)(r.NextDouble() * Math.PI * 2)),
                    new Vector3((float)(0.65 + r.NextDouble() * 0.35)),
                    r.Next(0, (int)rockTexture.ArrayLayers));
            }

            GraphicsDevice.UpdateBuffer(_instanceVB, 0, infos);

            Shader instanceVS = LoadShader(ResourceFactory, "Instance", ShaderStages.Vertex, "VS");
            Shader instanceFS = LoadShader(ResourceFactory, "Instance", ShaderStages.Fragment, "FS");

            GraphicsPipelineDescription pipelineDescription = new GraphicsPipelineDescription()
            {
                BlendState        = BlendStateDescription.SingleOverrideBlend,
                DepthStencilState = new DepthStencilStateDescription(
                    depthTestEnabled: true,
                    depthWriteEnabled: true,
                    comparisonKind: ComparisonKind.LessEqual),
                RasterizerState = new RasterizerStateDescription(
                    cullMode: FaceCullMode.Back,
                    fillMode: PolygonFillMode.Solid,
                    frontFace: FrontFace.Clockwise,
                    depthClipEnabled: true,
                    scissorTestEnabled: false
                    ),
                PrimitiveTopology = PrimitiveTopology.TriangleList,
                ResourceLayouts   = new ResourceLayout[] { sharedLayout, textureLayout },
                ShaderSet         = new ShaderSetDescription(
                    // The ordering of layouts directly impacts shader layout schemes
                    vertexLayouts: new VertexLayoutDescription[] { sharedVertexLayout, vertexLayoutPerInstance },
                    shaders: new Shader[] { instanceVS, instanceFS }
                    ),
                Outputs = MainSwapchain.Framebuffer.OutputDescription
            };

            _instancePipeline = factory.CreateGraphicsPipeline(pipelineDescription);

            // Create planet Pipeline
            // Almost everything is the same as the rock Pipeline,
            // except no instance vertex buffer is needed, and different shaders are used.
            pipelineDescription.ShaderSet = new ShaderSetDescription(
                new[] { sharedVertexLayout },
                new[]
            {
                LoadShader(ResourceFactory, "Planet", ShaderStages.Vertex, "VS"),
                LoadShader(ResourceFactory, "Planet", ShaderStages.Fragment, "FS"),
            });
            _planetPipeline = ResourceFactory.CreateGraphicsPipeline(pipelineDescription);

            ProcessedModel planet = LoadEmbeddedAsset <ProcessedModel>("sphere.binary");

            _planetModel = planet.MeshParts[0].CreateDeviceResources(GraphicsDevice, ResourceFactory);

            byte[] planetTexData = LoadEmbeddedAsset <byte[]>(
                etc2Supported
                    ? "lavaplanet_etc2_unorm.binary"
                    : "lavaplanet_bc3_unorm.binary");
            Texture     planetTexture     = KtxFile.LoadTexture(GraphicsDevice, ResourceFactory, planetTexData, pixelFormat);
            TextureView planetTextureView = ResourceFactory.CreateTextureView(planetTexture);

            _planetTextureSet = ResourceFactory.CreateResourceSet(new ResourceSetDescription(textureLayout, planetTextureView, GraphicsDevice.Aniso4xSampler));

            // Starfield resources
            ResourceLayout invCameraInfoLayout = ResourceFactory.CreateResourceLayout(new ResourceLayoutDescription(
                                                                                          new ResourceLayoutElementDescription("InvCameraInfo", ResourceKind.UniformBuffer, ShaderStages.Fragment)));

            _viewInfoBuffer = ResourceFactory.CreateBuffer(new BufferDescription((uint)Unsafe.SizeOf <InvCameraInfo>(), BufferUsage.UniformBuffer | BufferUsage.Dynamic));
            _viewInfoSet    = ResourceFactory.CreateResourceSet(new ResourceSetDescription(invCameraInfoLayout, _viewInfoBuffer));

            ShaderSetDescription starfieldShaders = new ShaderSetDescription(
                Array.Empty <VertexLayoutDescription>(),
                new[]
            {
                LoadShader(ResourceFactory, "Starfield", ShaderStages.Vertex, "VS"),
                LoadShader(ResourceFactory, "Starfield", ShaderStages.Fragment, "FS"),
            });

            _starfieldPipeline = ResourceFactory.CreateGraphicsPipeline(new GraphicsPipelineDescription(
                                                                            BlendStateDescription.SingleOverrideBlend,
                                                                            DepthStencilStateDescription.Disabled,
                                                                            RasterizerStateDescription.CullNone,
                                                                            PrimitiveTopology.TriangleList,
                                                                            starfieldShaders,
                                                                            new[] { invCameraInfoLayout },
                                                                            MainSwapchain.Framebuffer.OutputDescription));

            _commandList = factory.CreateCommandList();
        }
Exemple #2
0
        protected override void CreateResources(ResourceFactory factory)
        {
            _instanceCount = 1 << 14;

            _camera.Position = new Vector3(-36f, 20f, 100f);
            _camera.Pitch    = -0.3f;
            _camera.Yaw      = 0.1f;

            _cameraProjViewBuffer = factory.CreateBuffer(
                new BufferDescription((uint)(Unsafe.SizeOf <Matrix4x4>() * 2), BufferUsage.UniformBuffer | BufferUsage.Dynamic));
            _lightInfoBuffer    = factory.CreateBuffer(new BufferDescription(32, BufferUsage.UniformBuffer | BufferUsage.Dynamic));
            _rotationInfoBuffer = factory.CreateBuffer(new BufferDescription(16, BufferUsage.UniformBuffer | BufferUsage.Dynamic));
            _lightDir           = Vector3.Normalize(new Vector3(0.3f, -0.75f, -0.3f));

            VertexLayoutDescription sharedVertexLayout = new VertexLayoutDescription(
                new VertexElementDescription("Position", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float3),
                new VertexElementDescription("Normal", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float3),
                new VertexElementDescription("TexCoord", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float2));

            bool etc2Supported = GraphicsDevice.GetPixelFormatSupport(
                PixelFormat.ETC2_R8_G8_B8_UNorm,
                TextureType.Texture2D,
                TextureUsage.Sampled);
            PixelFormat pixelFormat = etc2Supported ? PixelFormat.ETC2_R8_G8_B8_UNorm : PixelFormat.BC3_UNorm;

            byte[] rockTextureData = LoadEmbeddedAsset <byte[]>(
                etc2Supported
                    ? "texturearray_rocks_etc2_unorm.binary"
                    : "texturearray_rocks_bc3_unorm.binary");
            Texture rockTexture = KtxFile.LoadTexture(
                GraphicsDevice,
                ResourceFactory,
                rockTextureData,
                pixelFormat);
            TextureView rockTextureView = ResourceFactory.CreateTextureView(rockTexture);

            ResourceLayoutElementDescription[] resourceLayoutElementDescriptions =
            {
                new ResourceLayoutElementDescription("LightInfo",    ResourceKind.UniformBuffer, ShaderStages.Fragment),
                new ResourceLayoutElementDescription("ProjView",     ResourceKind.UniformBuffer, ShaderStages.Vertex),
                new ResourceLayoutElementDescription("RotationInfo", ResourceKind.UniformBuffer, ShaderStages.Vertex),
            };
            ResourceLayoutDescription resourceLayoutDescription = new ResourceLayoutDescription(resourceLayoutElementDescriptions);
            ResourceLayout            sharedLayout = factory.CreateResourceLayout(resourceLayoutDescription);

            ResourceLayoutElementDescription[] textureLayoutDescriptions =
            {
                new ResourceLayoutElementDescription("Tex",  ResourceKind.TextureReadOnly, ShaderStages.Fragment),
                new ResourceLayoutElementDescription("Samp", ResourceKind.Sampler,         ShaderStages.Fragment)
            };
            ResourceLayout textureLayout = factory.CreateResourceLayout(new ResourceLayoutDescription(textureLayoutDescriptions));

            BindableResource[]     bindableResources      = new BindableResource[] { _lightInfoBuffer, _cameraProjViewBuffer, _rotationInfoBuffer };
            ResourceSetDescription resourceSetDescription = new ResourceSetDescription(sharedLayout, bindableResources);

            _sharedResourceSet = factory.CreateResourceSet(resourceSetDescription);

            BindableResource[] instanceBindableResources = { rockTextureView, GraphicsDevice.LinearSampler };
            _instanceTextureSet = factory.CreateResourceSet(new ResourceSetDescription(textureLayout, instanceBindableResources));

            ProcessedModel rock = LoadEmbeddedAsset <ProcessedModel>("sphere.binary");

            _rockModel = rock.MeshParts[0].CreateDeviceResources(GraphicsDevice, ResourceFactory);

            VertexLayoutDescription vertexLayoutPerInstancePos = new VertexLayoutDescription(
                new VertexElementDescription("InstancePosition", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float3));

            VertexLayoutDescription vertexLayoutPerInstanceScale = new VertexLayoutDescription(
                new VertexElementDescription("InstanceScale", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float3));

            VertexLayoutDescription vertexLayoutPerInstanceColor = new VertexLayoutDescription(
                new VertexElementDescription("InstanceColor", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float3));


            vertexLayoutPerInstancePos.InstanceStepRate   = 1;
            vertexLayoutPerInstanceScale.InstanceStepRate = 1;
            vertexLayoutPerInstanceColor.InstanceStepRate = 1;

            _instanceVBPos   = ResourceFactory.CreateBuffer(new BufferDescription(Vector3.Size * _instanceCount, BufferUsage.VertexBuffer));
            _instanceVBScale = ResourceFactory.CreateBuffer(new BufferDescription(Vector3.Size * _instanceCount, BufferUsage.VertexBuffer));
            _instanceVBColor = ResourceFactory.CreateBuffer(new BufferDescription(Vector3.Size * _instanceCount, BufferUsage.VertexBuffer));


            Vector3[] instancePos    = new Vector3[_instanceCount];
            Vector3[] instanceScale  = new Vector3[_instanceCount];
            Vector3[] instanceColors = new Vector3[_instanceCount];
            Random    r = new Random();

            for (uint i = 0; i < _instanceCount; i++)
            {
                instancePos[i] = new Vector3(
                    1000.0f * ((float)r.NextDouble() - 0.5f),
                    200.0f * ((float)r.NextDouble() - 0.5f),
                    1000.0f * ((float)r.NextDouble() - 0.5f));

                instanceScale[i] = new Vector3((float)(r.NextDouble() * 0.3));

                instanceColors[i] = new Vector3((float)r.NextDouble() * 0.5f + 0.5f,
                                                (float)r.NextDouble() * 0.5f + 0.5f,
                                                (float)r.NextDouble() * 0.5f + 0.5f);
            }


            GraphicsDevice.UpdateBuffer(_instanceVBPos, 0, instancePos);
            GraphicsDevice.UpdateBuffer(_instanceVBScale, 0, instanceScale);
            GraphicsDevice.UpdateBuffer(_instanceVBColor, 0, instanceColors);

            GraphicsPipelineDescription pipelineDescriptionRocks = new GraphicsPipelineDescription()
            {
                BlendState        = BlendStateDescription.SingleOverrideBlend,
                DepthStencilState = new DepthStencilStateDescription(
                    depthTestEnabled: true,
                    depthWriteEnabled: true,
                    comparisonKind: ComparisonKind.LessEqual),
                RasterizerState = new RasterizerStateDescription(
                    cullMode: FaceCullMode.Back,
                    fillMode: PolygonFillMode.Solid,
                    frontFace: FrontFace.Clockwise,
                    depthClipEnabled: true,
                    scissorTestEnabled: false
                    ),
                PrimitiveTopology = PrimitiveTopology.TriangleList,
                ResourceLayouts   = new ResourceLayout[] { sharedLayout, textureLayout },
                ShaderSet         = new ShaderSetDescription(
                    // The ordering of layouts directly impacts shader layout schemes
                    vertexLayouts: new VertexLayoutDescription[] { sharedVertexLayout, vertexLayoutPerInstancePos, vertexLayoutPerInstanceScale, vertexLayoutPerInstanceColor },
                    shaders: LoadShaders("Instance")
                    ),
                Outputs = MainSwapchain.Framebuffer.OutputDescription
            };

            _instancePipeline = factory.CreateGraphicsPipeline(pipelineDescriptionRocks);

            // Starfield resources
            ResourceLayout invCameraInfoLayout = ResourceFactory.CreateResourceLayout(new ResourceLayoutDescription(
                                                                                          new ResourceLayoutElementDescription("InvCameraInfo", ResourceKind.UniformBuffer, ShaderStages.Fragment)));

            _viewInfoBuffer = ResourceFactory.CreateBuffer(new BufferDescription((uint)Unsafe.SizeOf <MatrixPair>(), BufferUsage.UniformBuffer | BufferUsage.Dynamic));

            _commandList = factory.CreateCommandList();
        }