/// <summary> /// Function to build up the render targets. /// </summary> /// <param name="width">The width of the render targets.</param> /// <param name="height">The height of the render targets.</param> /// <param name="format">The format of the buffer.</param> private void BuildRenderTargets(int width, int height, BufferFormat format) { // For the lighting effect, we use a deferred rendering technique where we have 3 render targets for diffuse, specularity, and normal mapping. // These targets are sub resources of the same texture resource (array indices). // Diffuse. _rtvInfo.Width = width; _rtvInfo.Height = height; _rtvInfo.Format = format; _rtvInfo.ArrayCount = 2; _gbufferTargets[0] = Graphics.TemporaryTargets.Rent(_rtvInfo, "Gorgon 2D GBuffer - Diffuse/Specular", false); _gbufferTargets[0].Clear(GorgonColor.Black); // Specular. _gbufferTargets[1] = _gbufferTargets[0].Texture.GetRenderTargetView(arrayIndex: 1, arrayCount: 1); _rtvInfo.Format = BufferFormat.R8G8B8A8_UNorm; _rtvInfo.ArrayCount = 1; // Normals. // We'll clear it before the pass, the default color is insufficient. _gbufferTargets[2] = Graphics.TemporaryTargets.Rent(_rtvInfo, "Gorgon 2D Buffer - Normals", false); GorgonTexture2DView normalSrv = _gbufferTargets[2].GetShaderResourceView(); if ((_pixelLitShaderState.ShaderResources[1] != normalSrv) || (_diffuseFilter != DiffuseFiltering) || (_normalFilter != NormalFiltering) || (_specularFilter != SpecularFiltering)) { _diffuseFilter = DiffuseFiltering ?? GorgonSamplerState.Default; _normalFilter = NormalFiltering ?? GorgonSamplerState.PointFiltering; _specularFilter = SpecularFiltering ?? GorgonSamplerState.Default; _pixelDeferShaderState = PixelShaderBuilder.ResetTo(_pixelDeferShaderState) .SamplerState(_diffuseFilter, 0) .SamplerState(_normalFilter, 1) .SamplerState(_specularFilter, 2) .Build(); _pixelLitShaderState = PixelShaderBuilder .ResetTo(_pixelLitShaderState) .ShaderResource(normalSrv, 1) .SamplerState(_diffuseFilter, 0) .SamplerState(_normalFilter, 1) .SamplerState(_specularFilter, 2) .Build(); _lightingState = BatchStateBuilder .ResetTo(_lightingState) .PixelShaderState(_pixelLitShaderState) .Build(); } _gbufferTexture = _gbufferTargets[0].Texture.GetShaderResourceView(); }
/// <summary> /// Function called when the effect is being initialized. /// </summary> /// <remarks> /// Use this method to set up the effect upon its creation. For example, this method could be used to create the required shaders for the effect. /// </remarks> protected override void OnInitialize() { // Compile our blur shader. _grayScaleShader = CompileShader <GorgonPixelShader>(Resources.BasicSprite, "GorgonPixelShaderGrayScale"); _grayScaleState = PixelShaderBuilder .Shader(_grayScaleShader) .Build(); _batchState = BatchStateBuilder .PixelShaderState(_grayScaleState) .Build(); }
/// <summary> /// Function to return the object. /// </summary> /// <returns>The object created or updated by this builder.</returns> public Gorgon2DShaderState <T> Build() { var shader = new Gorgon2DShaderState <T> { Shader = _workingShader.Shader }; Copy(shader.RwConstantBuffers, _workingShader.RwConstantBuffers, 0); Copy(shader.RwSrvs, _workingShader.RwSrvs, 0); Copy(shader.RwSamplers, _workingShader.RwSamplers, 0); return(shader); }
/// <summary> /// Function called to initialize the effect. /// </summary> /// <remarks>Applications must implement this method to ensure that any required resources are created, and configured for the effect.</remarks> protected override void OnInitialize() { var globalData = new GlobalEffectData { CameraPosition = DX.Vector3.Zero, FlipYNormal = 0 }; _globalData = GorgonConstantBufferView.CreateConstantBuffer(Graphics, ref globalData, "Global deferred light effect data.", ResourceUsage.Default); _lightData = GorgonConstantBufferView.CreateConstantBuffer(Graphics, new GorgonConstantBufferInfo("Deferred Lighting Light Data Buffer") { SizeInBytes = Unsafe.SizeOf <PointLightData>(), Usage = ResourceUsage.Dynamic }); Macros.Add(new GorgonShaderMacro("DEFERRED_LIGHTING")); _vertexDeferShader = CompileShader <GorgonVertexShader>(Resources.Lighting, "GorgonVertexLightingShader"); _vertexDeferShaderState = VertexShaderBuilder.Shader(_vertexDeferShader) .Build(); _pixelDeferShader = CompileShader <GorgonPixelShader>(Resources.Lighting, "GorgonPixelShaderDeferred"); _pixelDeferShaderState = PixelShaderBuilder.Shader(_pixelDeferShader) .SamplerState(_diffuseFilter, 0) .SamplerState(_normalFilter, 1) .SamplerState(_specularFilter, 2) .Build(); Macros.Clear(); Macros.Add(new GorgonShaderMacro("LIGHTS")); _vertexLitShader = CompileShader <GorgonVertexShader>(Resources.Lighting, "GorgonVertexLitShader"); _vertexLitShaderState = VertexShaderBuilder.Shader(_vertexLitShader) .Build(); _pixelLitShader = CompileShader <GorgonPixelShader>(Resources.Lighting, "GorgonPixelShaderLighting"); _pixelLitShaderState = PixelShaderBuilder.Shader(_pixelLitShader) .ConstantBuffer(_lightData, 1) .ConstantBuffer(_globalData, 2) .SamplerState(_diffuseFilter, 0) .SamplerState(_normalFilter, 1) .SamplerState(_specularFilter, 2) .Build(); // Rebuild our states for the new pixel shaders. _lightingState = BatchStateBuilder.PixelShaderState(_pixelLitShaderState) .VertexShaderState(_vertexLitShaderState) .BlendState(GorgonBlendState.Additive) .Build(); }
/// <summary> /// Function to reset the builder to the specified object state. /// </summary> /// <param name="builderObject">[Optional] The specified object state to copy.</param> /// <returns>The fluent builder interface.</returns> public Gorgon2DShaderStateBuilder <T> ResetTo(Gorgon2DShaderState <T> builderObject = null) { if (builderObject == null) { Clear(); return(this); } Copy(_workingShader.RwConstantBuffers, builderObject.RwConstantBuffers, 0); Copy(_workingShader.RwSrvs, builderObject.RwSrvs, 0); Copy(_workingShader.RwSamplers, builderObject.RwSamplers, 0); _workingShader.Shader = builderObject.Shader; return(this); }
/// <summary> /// Function to return the object. /// </summary> /// <param name="allocator">The allocator used to create an instance of the object</param> /// <returns>The object created or updated by this builder.</returns> /// <remarks> /// <para> /// Using an <paramref name="allocator" /> can provide different strategies when building objects. If omitted, the object will be created using the standard <span class="keyword">new</span> keyword. /// </para> /// <para> /// A custom allocator can be beneficial because it allows us to use a pool for allocating the objects, and thus allows for recycling of objects. This keeps the garbage collector happy by keeping objects /// around for as long as we need them, instead of creating objects that can potentially end up in the large object heap or in Gen 2. /// </para> /// </remarks> public Gorgon2DShaderState <T> Build(IGorgonAllocator <Gorgon2DShaderState <T> > allocator) { Gorgon2DShaderState <T> shader; if (allocator == null) { shader = new Gorgon2DShaderState <T>(); } else { shader = allocator.Allocate(); } Copy(shader.RwConstantBuffers, _workingShader.RwConstantBuffers, 0); Copy(shader.RwSrvs, _workingShader.RwSrvs, 0); Copy(shader.RwSamplers, _workingShader.RwSamplers, 0); shader.Shader = _workingShader.Shader; return(shader); }
/// <summary> /// Function to assign a vertex shader state to the batch state. /// </summary> /// <param name="shader">The vertex shader and resources to assign, or <b>null</b> for a default vertex shader and states.</param> /// <returns>The fluent builder interface.</returns> public Gorgon2DBatchStateBuilder VertexShaderState(Gorgon2DShaderState <GorgonVertexShader> shader) { _worker.VertexShaderState = shader; return(this); }
/// <summary> /// Function to assign a pixel shader state to the batch state. /// </summary> /// <param name="shader">The pixel shader and resources to assign, or <b>null</b> for a default pixel shader and states.</param> /// <returns>The fluent builder interface.</returns> public Gorgon2DBatchStateBuilder PixelShaderState(Gorgon2DShaderState <GorgonPixelShader> shader) { _worker.PixelShaderState = shader; return(this); }