예제 #1
0
        /// <summary>
        /// Function to return the appropriate draw call based on the states provided.
        /// </summary>
        /// <param name="texture">The texture to display.</param>
        /// <param name="blendState">The blending state for the texture.</param>
        /// <param name="samplerState">The sampler state for the texture.</param>
        /// <param name="shader">The pixel shader to use.</param>
        /// <param name="constantBuffers">Constant buffers for the pixel shader, if required.</param>
        private void GetDrawCall(GorgonTexture2DView texture, GorgonBlendState blendState, GorgonSamplerState samplerState, GorgonPixelShader shader, GorgonConstantBuffers constantBuffers)
        {
            if ((_drawCall != null) &&
                (shader == _pixelShader) &&
                (_drawCall.PixelShader.Samplers[0] == samplerState) &&
                (_pipelineState.BlendStates[0] == blendState) &&
                (_drawCall.PixelShader.ShaderResources[0] == texture) &&
                (_drawCall.PixelShader.ConstantBuffers.DirtyEquals(constantBuffers)))
            {
                // This draw call hasn't changed, so return the previous one.
                return;
            }

            if (_pipelineState.BlendStates[0] != blendState)
            {
                _pipelineState = _pipeStateBuilder
                                 .BlendState(blendState)
                                 .Build();

                _drawCallBuilder.PipelineState(_pipelineState);
            }

            _drawCall = _drawCallBuilder.ConstantBuffers(ShaderType.Pixel, constantBuffers)
                        .SamplerState(ShaderType.Pixel, samplerState)
                        .ShaderResource(ShaderType.Pixel, texture)
                        .Build(_drawAllocator);
        }
예제 #2
0
        /// <summary>
        /// Function to load the resources for the layer.
        /// </summary>
        public override void LoadResources()
        {
            _drawCalls = new List <GorgonDrawIndexCall>();
            BuildConstantBuffers();

            for (int i = 0; i < Planets.Count; ++i)
            {
                Planet planet = Planets[i];

                for (int j = 0; j < planet.Layers.Count; ++j)
                {
                    PlanetaryLayer layer = planet.Layers[j];

                    GorgonVertexShader vertexShader = _resources.VertexShaders[layer.Mesh.Material.VertexShader];
                    GorgonPixelShader  pixelShader  = _resources.PixelShaders[layer.Mesh.Material.PixelShader];

                    // Create our vertex layout now.
                    if (_vertexLayout == null)
                    {
                        _vertexLayout = _vertexLayout = GorgonInputLayout.CreateUsingType <Vertex3D>(_graphics, vertexShader);
                    }

                    // Set up a pipeline state for the mesh.
                    GorgonPipelineState pipelineState = _stateBuilder.Clear()
                                                        .PixelShader(pixelShader)
                                                        .VertexShader(vertexShader)
                                                        .BlendState(layer.Mesh.Material.BlendState)
                                                        .PrimitiveType(PrimitiveType.TriangleList)
                                                        .Build();
                    _drawCallBuilder.Clear()
                    .PipelineState(pipelineState)
                    .IndexBuffer(layer.Mesh.IndexBuffer, 0, layer.Mesh.IndexCount)
                    .VertexBuffer(_vertexLayout, new GorgonVertexBufferBinding(layer.Mesh.VertexBuffer, Vertex3D.Size))
                    .ConstantBuffer(ShaderType.Vertex, _viewProjectionBuffer)
                    .ConstantBuffer(ShaderType.Vertex, _worldBuffer, 1)
                    .ConstantBuffer(ShaderType.Pixel, _cameraBuffer)
                    .ConstantBuffer(ShaderType.Pixel, _lightBuffer, 1)
                    .ConstantBuffer(ShaderType.Pixel, _materialBuffer, 2);

                    (int startTexture, int textureCount) = layer.Mesh.Material.Textures.GetDirtyItems();

                    for (int k = startTexture; k < startTexture + textureCount; ++k)
                    {
                        GorgonTexture2DView texture = _resources.Textures[layer.Mesh.Material.Textures[k]];
                        _drawCallBuilder.ShaderResource(ShaderType.Pixel, texture, k);
                        // We should have this in the material, but since we know what we've got here, this will be fine.
                        _drawCallBuilder.SamplerState(ShaderType.Pixel, GorgonSamplerState.Wrapping, k);
                    }

                    _drawCalls.Add(_drawCallBuilder.Build());
                }
            }

            UpdateLightTransforms();
        }
예제 #3
0
        /// <summary>
        /// Function to create a draw call based on a mesh.
        /// </summary>
        /// <param name="mesh">The mesh to evaluate.</param>
        private void AddDrawCall(Mesh mesh)
        {
            // Find out which shaders are used by the mesh and retrieve them from the cache.
            if (!ShaderCache.TryGetValue(mesh.Material.VertexShader, out GorgonShader shader))
            {
                return;
            }

            var vertexShader = (GorgonVertexShader)shader;

            if (!ShaderCache.TryGetValue(mesh.Material.PixelShader, out shader))
            {
                return;
            }

            // Not an ideal place for this, but since we don't know when a vertex shader will be added to our renderer, and we require a vertex shader for our
            // input layout, then this will have to suffice.  In a real renderer, we'd cache the vertex inputs per shader and just look it up because the type
            // of vertex may not be what we expect. In this case, we *know* that we're using Vertex3D and no other vertex type, so we're 100% safe doing it
            // here in this example.
            if ((_vertexLayout == null) && (vertexShader != null))
            {
                _vertexLayout = GorgonInputLayout.CreateUsingType <Vertex3D>(_graphics, vertexShader);
            }

            var pixelShader = (GorgonPixelShader)shader;

            GorgonPipelineState pipelineState = _stateBuilder.Clear()
                                                .DepthStencilState(mesh.IsDepthWriteEnabled
                                                                                    ? GorgonDepthStencilState.DepthEnabled
                                                                                    : GorgonDepthStencilState.DepthEnabledNoWrite)
                                                .PixelShader(pixelShader)
                                                .VertexShader(vertexShader)
                                                .BlendState(mesh.Material.BlendState)
                                                .PrimitiveType(mesh.PrimitiveType)
                                                .Build();

            _drawBuilder.Clear()
            .PipelineState(pipelineState)
            .IndexBuffer(mesh.IndexBuffer, 0, mesh.IndexCount)
            .VertexBuffer(_vertexLayout, new GorgonVertexBufferBinding(mesh.VertexBuffer, Vertex3D.Size))
            .ConstantBuffer(ShaderType.Vertex, _viewProjectionBuffer)
            .ConstantBuffer(ShaderType.Vertex, _worldBuffer, 1)
            .ConstantBuffer(ShaderType.Pixel, _cameraBuffer)
            .ConstantBuffer(ShaderType.Pixel, _lightBuffer, 1)
            .ConstantBuffer(ShaderType.Pixel, _materialBuffer, 2);

            ref readonly (int Start, int Count)textures = ref mesh.Material.Textures.GetDirtyItems();
예제 #4
0
        /// <summary>
        /// Function to initialize the blitter.
        /// </summary>
        public void Initialize()
        {
            try
            {
                // We've been initialized, so leave.
                if ((_vertexShader != null) || (Interlocked.Increment(ref _initializedFlag) > 1))
                {
                    // Trap other threads until we're done initializing and then release them.
                    while ((_vertexShader == null) && (_initializedFlag > 0))
                    {
                        var wait = new SpinWait();
                        wait.SpinOnce();
                    }

                    return;
                }


                _vertexShader = GorgonShaderFactory.Compile <GorgonVertexShader>(_graphics,
                                                                                 Resources.GraphicsShaders,
                                                                                 "GorgonBltVertexShader",
                                                                                 GorgonGraphics.IsDebugEnabled);
                _pixelShader = GorgonShaderFactory.Compile <GorgonPixelShader>(_graphics,
                                                                               Resources.GraphicsShaders,
                                                                               "GorgonBltPixelShader",
                                                                               GorgonGraphics.IsDebugEnabled);

                _inputLayout = GorgonInputLayout.CreateUsingType <BltVertex>(_graphics, _vertexShader);

                _vertexBufferBindings = new GorgonVertexBufferBindings(_inputLayout)
                {
                    [0] = GorgonVertexBufferBinding.CreateVertexBuffer <BltVertex>(_graphics,
                                                                                   4,
                                                                                   ResourceUsage.Dynamic,
                                                                                   bufferName: "Gorgon Blitter Vertex Buffer")
                };

                _wvpBuffer = GorgonConstantBufferView.CreateConstantBuffer(_graphics,
                                                                           new GorgonConstantBufferInfo("Gorgon Blitter WVP Buffer")
                {
                    Usage       = ResourceUsage.Dynamic,
                    SizeInBytes = DX.Matrix.SizeInBytes
                });

                // Finish initalizing the draw call.
                _pipelineState = _pipeStateBuilder.VertexShader(_vertexShader)
                                 .BlendState(GorgonBlendState.NoBlending)
                                 .DepthStencilState(GorgonDepthStencilState.Default)
                                 .PrimitiveType(PrimitiveType.TriangleStrip)
                                 .RasterState(GorgonRasterState.Default)
                                 .PixelShader(_pixelShader)
                                 .Build();

                _drawCallBuilder.VertexBuffers(_inputLayout, _vertexBufferBindings)
                .VertexRange(0, 4)
                .SamplerState(ShaderType.Pixel, GorgonSamplerState.Default)
                .PipelineState(_pipelineState)
                .ConstantBuffer(ShaderType.Vertex, _wvpBuffer);


                _defaultTexture = Resources.White_2x2.ToTexture2D(_graphics,
                                                                  new GorgonTexture2DLoadOptions
                {
                    Name    = "Gorgon_Default_White_Texture",
                    Usage   = ResourceUsage.Immutable,
                    Binding = TextureBinding.ShaderResource
                }).GetShaderResourceView();
            }
            finally
            {
                Interlocked.Decrement(ref _initializedFlag);
            }
        }