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(); }
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(); }