/// <summary> /// Internal constructor to create RT for backbuffer. /// </summary> /// <param name="device"></param> /// <param name="backbufColor"></param> internal RenderTarget2D(GraphicsDevice device, D3D.Texture2D backbufColor, RenderTargetViewDescription?desc = null) : base(device) { Log.Debug("RenderTarget2D: from backbuffer."); if (backbufColor.Description.Format != DXGI.Format.R8G8B8A8_UNorm) { Log.Warning("R8G8B8A8_UNorm"); } Width = backbufColor.Description.Width; Height = backbufColor.Description.Height; Format = ColorFormat.Rgba8; MipCount = 1; SampleCount = backbufColor.Description.SampleDescription.Count; SRV = null; tex2D = backbufColor; surfaces = new RenderTargetSurface[1]; if (desc.HasValue) { surfaces[0] = new RenderTargetSurface(new RenderTargetView(device.Device, backbufColor, desc.Value), null, tex2D, 0, Format, Width, Height, SampleCount); } else { surfaces[0] = new RenderTargetSurface(new RenderTargetView(device.Device, backbufColor), null, tex2D, 0, Format, Width, Height, SampleCount); } }
/// <summary> /// SetCSRWBuffer & SetCSRWTexture share same registers. /// </summary> /// <param name="register"></param> /// <param name="buffer"></param> /// <param name="initialCount">An array of append and consume buffer offsets. /// A value of -1 indicates to keep the current offset. /// Any other values set the hidden counter for that appendable and consumable UAV. </param> public void SetCSRWTexture(int register, RenderTargetSurface surface) { if (register > 8) { throw new GraphicsException("Could not bind RW texture at register " + register.ToString() + " (max 8)"); } lock (deviceContext) { DeviceContext.ComputeShader.SetUnorderedAccessView(register, surface == null?null:surface.UAV, -1); } }
/// <summary> /// /// </summary> /// <param name="source"></param> /// <param name="destination"></param> public void Resolve(RenderTargetSurface source, RenderTargetSurface destination) { if (source.Width != destination.Width || source.Height != destination.Height) { throw new GraphicsException("Could not resolve: source and destination are not the same size"); } if (source.SampleCount <= 1) { throw new GraphicsException("Could not resolve: source surface is not multisampled"); } if (destination.SampleCount > 1) { throw new GraphicsException("Could not resolve: destination surface is multisampled"); } lock (deviceContext) { deviceContext.ResolveSubresource(source.Resource, source.Subresource, destination.Resource, destination.Subresource, Converter.Convert(source.Format)); } }
/// <summary> /// SetPSRWBuffer & SetPSRWTexture share same registers. /// </summary> /// <param name="register"></param> /// <param name="buffer"></param> /// <param name="initialCount">An array of append and consume buffer offsets. /// A value of -1 indicates to keep the current offset. /// Any other values set the hidden counter for that appendable and consumable UAV. </param> public void SetPSRWTexture ( int register, RenderTargetSurface surface ) { if (register>8) { throw new GraphicsException("Could not bind RW texture at register " + register.ToString() + " (max 8)"); } lock (deviceContext) { DeviceContext.OutputMerger.SetUnorderedAccessView ( register, surface==null?null:surface.UAV, -1 ); } }
/// <summary> /// Draws sprite laters and all sublayers. /// </summary> /// <param name="gameTime"></param> /// <param name="stereoEye"></param> public void DrawSprites ( GameTime gameTime, StereoEye stereoEye, RenderTargetSurface surface, IEnumerable<SpriteLayer> layers ) { device.ResetStates(); //device.RestoreBackbuffer(); device.SetTargets( null, surface ); DrawSpritesRecursive( gameTime, stereoEye, surface, layers, Matrix.Identity, new Color4(1f,1f,1f,1f) ); }
/// <summary> /// /// </summary> /// <param name="dst">target to copy to</param> /// <param name="src">target to copy from</param> public void OverlayAdditive( RenderTargetSurface dst, ShaderResource src ) { SetDefaultRenderStates(); using( new PixEvent("OverlayAdditive") ) { if(dst == null) { rs.RestoreBackbuffer(); } else { rs.SetTargets( null, dst ); } rs.PipelineState = factory[ (int)ShaderFlags.OVERLAY_ADDITIVE ]; rs.PixelShaderResources[0] = src; rs.Draw( 3, 0 ); } rs.ResetStates(); }
/// <summary> /// /// </summary> /// <param name="dst">target to copy to</param> /// <param name="src">target to copy from</param> public void Copy( RenderTargetSurface dst, ShaderResource src ) { SetDefaultRenderStates(); using( new PixEvent("Copy") ) { if(dst == null) { rs.RestoreBackbuffer(); } else { SetViewport(dst); rs.SetTargets( null, dst ); } rs.PipelineState = factory[ (int)ShaderFlags.COPY ]; rs.PixelShaderResources[0] = src; rs.Draw( 3, 0 ); } rs.ResetStates(); }
public void LinearizeDepth( RenderTargetSurface dst, ShaderResource src ) { throw new NotImplementedException(); #if false Debug.Assert( Game.IsServiceExist<Camera>() ); var camera = Game.GetService<Camera>(); bufLinearizeDepth.Data.linearizeDepthA = 1.0f / camera.FrustumZFar - 1.0f / camera.FrustumZNear; bufLinearizeDepth.Data.linearizeDepthB = 1.0f / camera.FrustumZNear; bufLinearizeDepth.UpdateCBuffer(); var isDepthMSAA = ( src.SampleCount > 1 ); var depthShader = (int)( isDepthMSAA ? ShaderFlags.RESOLVE_AND_LINEARIZE_DEPTH_MSAA : ShaderFlags.LINEARIZE_DEPTH ); string signature; SetDefaultRenderStates(); using( new PixEvent() ) { bufLinearizeDepth.SetCBufferPS( 0 ); shaders.SetPixelShader( depthShader ); shaders.SetVertexShader( depthShader ); dst.SetViewport(); rs.SetRenderTargets( dst ); src.SetPS( 0 ); rs.Draw( Primitive.TriangleList, 3, 0 ); } rs.ResetStates(); #endif }
/// <summary> /// Creates render target /// </summary> /// <param name="?"></param> /// <param name="format"></param> /// <param name="width"></param> /// <param name="height"></param> /// <param name="samples"></param> /// <param name="mips"></param> /// <param name="debugName"></param> void Create(ColorFormat format, int size, int samples, bool mips, string debugName) { bool msaa = samples > 1; CheckSamplesCount(samples); if (mips && samples > 1) { throw new ArgumentException("Render target should be multisampler either mipmapped"); } SampleCount = samples; Format = format; SampleCount = samples; Width = size; Height = size; Depth = 1; MipCount = mips ? ShaderResource.CalculateMipLevels(Width, Height) : 1; var texDesc = new Texture2DDescription(); texDesc.Width = Width; texDesc.Height = Height; texDesc.ArraySize = 6; texDesc.BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource; texDesc.CpuAccessFlags = CpuAccessFlags.None; texDesc.Format = Converter.Convert(format); texDesc.MipLevels = mips ? MipCount : 1; texDesc.OptionFlags = ResourceOptionFlags.TextureCube | (mips ? ResourceOptionFlags.GenerateMipMaps : ResourceOptionFlags.None); texDesc.SampleDescription = new DXGI.SampleDescription(samples, 0); texDesc.Usage = ResourceUsage.Default; texCube = new D3D.Texture2D(device.Device, texDesc); SRV = new ShaderResourceView(device.Device, texCube); texDesc.BindFlags = BindFlags.None; texDesc.CpuAccessFlags = CpuAccessFlags.Write | CpuAccessFlags.Read; texDesc.Usage = ResourceUsage.Staging; texDesc.OptionFlags = ResourceOptionFlags.TextureCube; staging = new D3D.Texture2D(device.Device, texDesc); // // Top mipmap level : // cubeMipShaderResources = new ShaderResource[MipCount]; for (int mip = 0; mip < MipCount; mip++) { var srvDesc = new ShaderResourceViewDescription(); srvDesc.TextureCube.MipLevels = 1; srvDesc.TextureCube.MostDetailedMip = mip; srvDesc.Format = Converter.Convert(format); srvDesc.Dimension = ShaderResourceViewDimension.TextureCube; cubeMipShaderResources[mip] = new ShaderResource(device, new ShaderResourceView(device.Device, texCube, srvDesc), size >> mip, size >> mip, 1); } // // Create surfaces : // surfaces = new RenderTargetSurface[MipCount, 6]; for (int mip = 0; mip < MipCount; mip++) { int width = GetMipSize(Width, mip); int height = GetMipSize(Height, mip); for (int face = 0; face < 6; face++) { var rtvDesc = new RenderTargetViewDescription(); rtvDesc.Texture2DArray.MipSlice = mip; rtvDesc.Texture2DArray.FirstArraySlice = face; rtvDesc.Texture2DArray.ArraySize = 1; rtvDesc.Dimension = msaa ? RenderTargetViewDimension.Texture2DMultisampledArray : RenderTargetViewDimension.Texture2DArray; rtvDesc.Format = Converter.Convert(format); var rtv = new RenderTargetView(device.Device, texCube, rtvDesc); int subResId = Resource.CalculateSubResourceIndex(mip, face, MipCount); surfaces[mip, face] = new RenderTargetSurface(rtv, null, texCube, subResId, format, Width, Height, samples); GraphicsDevice.Clear(surfaces[mip, face], Color4.Zero); } } }
/// <summary> /// Performs luminance measurement, tonemapping, applies bloom. /// </summary> /// <param name="target">LDR target.</param> /// <param name="hdrImage">HDR source image.</param> public void Render ( GameTime gameTime, RenderTargetSurface target, ShaderResource hdrImage, RenderWorld viewLayer ) { var device = Game.GraphicsDevice; var filter = Game.RenderSystem.Filter; var settings = viewLayer.HdrSettings; // // Rough downsampling of source HDR-image : // filter.StretchRect( averageLum.Surface, hdrImage, SamplerState.PointClamp ); averageLum.BuildMipmaps(); // // Make bloom : // filter.StretchRect( viewLayer.Bloom0.Surface, hdrImage, SamplerState.LinearClamp ); viewLayer.Bloom0.BuildMipmaps(); filter.GaussBlur( viewLayer.Bloom0, viewLayer.Bloom1, settings.GaussBlurSigma, 0 ); filter.GaussBlur( viewLayer.Bloom0, viewLayer.Bloom1, settings.GaussBlurSigma, 1 ); filter.GaussBlur( viewLayer.Bloom0, viewLayer.Bloom1, settings.GaussBlurSigma, 2 ); filter.GaussBlur( viewLayer.Bloom0, viewLayer.Bloom1, settings.GaussBlurSigma, 3 ); // // Setup parameters : // var paramsData = new Params(); paramsData.AdaptationRate = 1 - (float)Math.Pow( 0.5f, gameTime.ElapsedSec / settings.AdaptationHalfLife ); paramsData.LuminanceLowBound = settings.LuminanceLowBound; paramsData.LuminanceHighBound = settings.LuminanceHighBound; paramsData.KeyValue = settings.KeyValue; paramsData.BloomAmount = settings.BloomAmount; paramsData.DirtMaskLerpFactor = settings.DirtMaskLerpFactor; paramsData.DirtAmount = settings.DirtAmount; paramsCB.SetData( paramsData ); device.PixelShaderConstants[0] = paramsCB; // // Measure and adapt : // device.SetTargets( null, viewLayer.MeasuredNew ); device.PixelShaderResources[0] = averageLum; device.PixelShaderResources[1] = viewLayer.MeasuredOld; device.PipelineState = factory[ (int)(Flags.MEASURE_ADAPT) ]; device.Draw( 3, 0 ); // // Tonemap and compose : // device.SetTargets( null, target ); device.PixelShaderResources[0] = hdrImage;// averageLum; device.PixelShaderResources[1] = viewLayer.MeasuredNew;// averageLum; device.PixelShaderResources[2] = viewLayer.Bloom0;// averageLum; device.PixelShaderResources[3] = settings.DirtMask1==null ? whiteTex.Srv : settings.DirtMask1.Srv; device.PixelShaderResources[4] = settings.DirtMask2==null ? whiteTex.Srv : settings.DirtMask2.Srv; device.PixelShaderSamplers[0] = SamplerState.LinearClamp; Flags op = Flags.LINEAR; if (settings.TonemappingOperator==TonemappingOperator.Filmic) { op = Flags.FILMIC; } if (settings.TonemappingOperator==TonemappingOperator.Linear) { op = Flags.LINEAR; } if (settings.TonemappingOperator==TonemappingOperator.Reinhard) { op = Flags.REINHARD; } device.PipelineState = factory[ (int)(Flags.TONEMAPPING|op) ]; device.Draw( 3, 0 ); device.ResetStates(); // swap luminanice buffers : Misc.Swap( ref viewLayer.MeasuredNew, ref viewLayer.MeasuredOld ); }
/// <summary> /// /// </summary> public void Render ( RenderTargetSurface colorBuffer, Camera camera ) { DrawTracers(); if (!vertexDataAccum.Any()) { return; } var dev = Game.GraphicsDevice; dev.ResetStates(); dev.SetTargets( null, colorBuffer ); constData.Transform = camera.GetViewMatrix(StereoEye.Mono) * camera.GetProjectionMatrix(StereoEye.Mono); constBuffer.SetData(constData); dev.SetupVertexInput( vertexBuffer, null ); dev.VertexShaderConstants[0] = constBuffer ; dev.PipelineState = factory[0]; int numDPs = MathUtil.IntDivUp(vertexDataAccum.Count, vertexBufferSize); for (int i = 0; i < numDPs; i++) { int numVerts = i < numDPs - 1 ? vertexBufferSize : vertexDataAccum.Count % vertexBufferSize; if (numVerts == 0) { break; } vertexDataAccum.CopyTo(i * vertexBufferSize, vertexArray, 0, numVerts); vertexBuffer.SetData(vertexArray, 0, numVerts); dev.Draw( numVerts, 0); } vertexDataAccum.Clear(); }
/// <summary> /// Creates render target /// </summary> /// <param name="?"></param> /// <param name="format"></param> /// <param name="width"></param> /// <param name="height"></param> /// <param name="samples"></param> /// <param name="mips"></param> /// <param name="debugName"></param> void Create ( ColorFormat format, int size, int samples, bool mips, string debugName ) { bool msaa = samples > 1; CheckSamplesCount( samples ); if (mips && samples>1) { throw new ArgumentException("Render target should be multisampler either mipmapped"); } SampleCount = samples; Format = format; SampleCount = samples; Width = size; Height = size; Depth = 1; MipCount = mips ? ShaderResource.CalculateMipLevels( Width, Height ) : 1; var texDesc = new Texture2DDescription(); texDesc.Width = Width; texDesc.Height = Height; texDesc.ArraySize = 6; texDesc.BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource; texDesc.CpuAccessFlags = CpuAccessFlags.None; texDesc.Format = Converter.Convert( format ); texDesc.MipLevels = mips ? MipCount : 1; texDesc.OptionFlags = ResourceOptionFlags.TextureCube | (mips ? ResourceOptionFlags.GenerateMipMaps : ResourceOptionFlags.None); texDesc.SampleDescription = new DXGI.SampleDescription(samples, 0); texDesc.Usage = ResourceUsage.Default; texCube = new D3D.Texture2D( device.Device, texDesc ); SRV = new ShaderResourceView( device.Device, texCube ); // // Top mipmap level : // cubeMipShaderResources = new ShaderResource[MipCount]; for (int mip=0; mip<MipCount; mip++) { var srvDesc = new ShaderResourceViewDescription(); srvDesc.TextureCube.MipLevels = 1; srvDesc.TextureCube.MostDetailedMip = mip; srvDesc.Format = Converter.Convert( format ); srvDesc.Dimension = ShaderResourceViewDimension.TextureCube; cubeMipShaderResources[mip] = new ShaderResource( device, new ShaderResourceView(device.Device, texCube, srvDesc), size>>mip, size>>mip, 1 ); } // // Create surfaces : // surfaces = new RenderTargetSurface[ MipCount, 6 ]; for ( int mip=0; mip<MipCount; mip++ ) { int width = GetMipSize( Width, mip ); int height = GetMipSize( Height, mip ); for ( int face=0; face<6; face++) { var rtvDesc = new RenderTargetViewDescription(); rtvDesc.Texture2DArray.MipSlice = mip; rtvDesc.Texture2DArray.FirstArraySlice = face; rtvDesc.Texture2DArray.ArraySize = 1; rtvDesc.Dimension = msaa ? RenderTargetViewDimension.Texture2DMultisampledArray : RenderTargetViewDimension.Texture2DArray; rtvDesc.Format = Converter.Convert( format ); var rtv = new RenderTargetView( device.Device, texCube, rtvDesc ); int subResId = Resource.CalculateSubResourceIndex( mip, face, MipCount ); surfaces[mip,face] = new RenderTargetSurface( rtv, null, texCube, subResId, format, Width, Height, samples ); GraphicsDevice.Clear( surfaces[mip,face], Color4.Zero ); } } }
/// <summary> /// Clears render target using given color /// </summary> /// <param name="surface"></param> /// <param name="color"></param> public void Clear(RenderTargetSurface surface, Color4 color) { lock (deviceContext) { deviceContext.ClearRenderTargetView(surface.RTV, SharpDXHelper.Convert(color)); } }
/// <summary> /// Creates render target /// </summary> /// <param name="rs"></param> /// <param name="width"></param> /// <param name="height"></param> /// <param name="format"></param> public FeedbackBuffer(GraphicsDevice device, int width, int height) : base(device) { Log.Debug("FeedbackBuffer: w:{0} h:{1}", width, height); feedbackData = new VTAddress[width * height]; feedbackDataRaw = new int[width * height]; linearSize = width * height; Width = width; Height = height; Depth = 1; // // Create Texture2D : // var texDesc = new Texture2DDescription(); texDesc.Width = width; texDesc.Height = height; texDesc.ArraySize = 1; texDesc.BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource; texDesc.CpuAccessFlags = CpuAccessFlags.None; texDesc.Format = DXGI.Format.R10G10B10A2_UNorm; texDesc.MipLevels = 1; texDesc.OptionFlags = ResourceOptionFlags.None; texDesc.SampleDescription = new DXGI.SampleDescription(1, 0); texDesc.Usage = ResourceUsage.Default; tex2D = new D3D.Texture2D(device.Device, texDesc); // // Create staging Texture2D : // var texDescStaging = new Texture2DDescription(); texDescStaging.Width = width; texDescStaging.Height = height; texDescStaging.ArraySize = 1; texDescStaging.BindFlags = BindFlags.None; texDescStaging.CpuAccessFlags = CpuAccessFlags.Read; texDescStaging.Format = DXGI.Format.R10G10B10A2_UNorm; texDescStaging.MipLevels = 1; texDescStaging.OptionFlags = ResourceOptionFlags.None; texDescStaging.SampleDescription = new DXGI.SampleDescription(1, 0); texDescStaging.Usage = ResourceUsage.Staging; tex2Dstaging = new D3D.Texture2D(device.Device, texDescStaging); tex2Dstaging1 = new D3D.Texture2D(device.Device, texDescStaging); tex2Dstaging2 = new D3D.Texture2D(device.Device, texDescStaging); // // Create SRV : // var srvDesc = new ShaderResourceViewDescription(); srvDesc.Texture2D.MipLevels = 1; srvDesc.Texture2D.MostDetailedMip = 0; srvDesc.Dimension = ShaderResourceViewDimension.Texture2D; srvDesc.Format = DXGI.Format.R10G10B10A2_UNorm; SRV = new ShaderResourceView(device.Device, tex2D, srvDesc); // // Create RTV : // width = Width; height = Height; var rtvDesc = new RenderTargetViewDescription(); rtvDesc.Texture2D.MipSlice = 0; rtvDesc.Dimension = RenderTargetViewDimension.Texture2D; rtvDesc.Format = DXGI.Format.R10G10B10A2_UNorm; var rtv = new RenderTargetView(device.Device, tex2D, rtvDesc); surface = new RenderTargetSurface(rtv, null, tex2D, 0, ColorFormat.Unknown, width, height, 1); }
/// <summary> /// Draw sprite layers /// </summary> /// <param name="gameTime"></param> /// <param name="stereoEye"></param> /// <param name="layers"></param> void DrawSpritesRecursive ( GameTime gameTime, StereoEye stereoEye, RenderTargetSurface surface, IEnumerable<SpriteLayer> layers, Matrix parentTransform, Color4 parentColor ) { int w = surface.Width; int h = surface.Height; var ofs = 0f; var projection = Matrix.OrthoOffCenterRH(ofs, w + ofs, h + ofs, ofs, -9999, 9999); var orderedLayers = layers.Where( layer0 => layer0!=null ).OrderBy( layer1 => layer1.Order ); foreach ( var layer in orderedLayers ) { if (!layer.Visible) { continue; } using ( new PixEvent("SpriteLayer") ) { Matrix absTransform = parentTransform * layer.Transform; Color4 absColor = parentColor * layer.Color.ToColor4(); constData.Transform = absTransform * projection; constData.ClipRectangle = new Vector4(0,0,0,0); constData.MasterColor = absColor; constBuffer.SetData( constData ); device.VertexShaderConstants[0] = constBuffer; device.PixelShaderConstants[0] = constBuffer; PipelineState ps = null; SamplerState ss = null; switch ( layer.FilterMode ) { case SpriteFilterMode.PointClamp : ss = SamplerState.PointClamp; break; case SpriteFilterMode.PointWrap : ss = SamplerState.PointWrap; break; case SpriteFilterMode.LinearClamp : ss = SamplerState.LinearClamp; break; case SpriteFilterMode.LinearWrap : ss = SamplerState.LinearWrap; break; case SpriteFilterMode.AnisotropicClamp : ss = SamplerState.AnisotropicClamp; break; case SpriteFilterMode.AnisotropicWrap : ss = SamplerState.AnisotropicWrap; break; } switch ( layer.BlendMode ) { case SpriteBlendMode.Opaque : ps = factory[(int)Flags.OPAQUE ]; break; case SpriteBlendMode.AlphaBlend : ps = factory[(int)Flags.ALPHA_BLEND ]; break; case SpriteBlendMode.AlphaBlendPremul : ps = factory[(int)Flags.ALPHA_BLEND_PREMUL]; break; case SpriteBlendMode.Additive : ps = factory[(int)Flags.ADDITIVE ]; break; case SpriteBlendMode.Screen : ps = factory[(int)Flags.SCREEN ]; break; case SpriteBlendMode.Multiply : ps = factory[(int)Flags.MULTIPLY ]; break; case SpriteBlendMode.NegMultiply : ps = factory[(int)Flags.NEG_MULTIPLY ]; break; case SpriteBlendMode.AlphaOnly : ps = factory[(int)Flags.ALPHA_ONLY ]; break; } device.PipelineState = ps; device.PixelShaderSamplers[0] = ss; layer.Draw( gameTime, stereoEye ); DrawSpritesRecursive( gameTime, stereoEye, surface, layer.Layers, absTransform, absColor ); } } }
/// <summary> /// Creates render target /// </summary> /// <param name="?"></param> /// <param name="format"></param> /// <param name="width"></param> /// <param name="height"></param> /// <param name="samples"></param> /// <param name="mips"></param> /// <param name="debugName"></param> void Create(ColorFormat format, int width, int height, int samples, int mips, bool enableRWBuffer) { //Log.Debug("RenderTarget2D: f:{0} w:{1} h:{2} s:{3}{4}{5}", format, width, height, samples, mips?" mips":"", enableRWBuffer?" uav":"" ); bool msaa = samples > 1; CheckSamplesCount(samples); if (mips != 1 && samples > 1) { throw new ArgumentException("Render target should be multisampler either mipmapped"); } SampleCount = samples; Format = format; SampleCount = samples; Width = width; Height = height; Depth = 1; MipCount = mips == 0 ? ShaderResource.CalculateMipLevels(width, height) : mips; var texDesc = new Texture2DDescription(); texDesc.Width = width; texDesc.Height = height; texDesc.ArraySize = 1; texDesc.BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource; texDesc.CpuAccessFlags = CpuAccessFlags.None; texDesc.Format = Converter.Convert(format); texDesc.MipLevels = MipCount; texDesc.OptionFlags = (mips != 1) ? ResourceOptionFlags.GenerateMipMaps : ResourceOptionFlags.None; texDesc.SampleDescription = new DXGI.SampleDescription(samples, 0); texDesc.Usage = ResourceUsage.Default; if (enableRWBuffer) { texDesc.BindFlags |= BindFlags.UnorderedAccess; } tex2D = new D3D.Texture2D(device.Device, texDesc); SRV = new ShaderResourceView(device.Device, tex2D); // // Create surfaces : // surfaces = new RenderTargetSurface[MipCount]; for (int i = 0; i < MipCount; i++) { width = GetMipSize(Width, i); height = GetMipSize(Height, i); var rtvDesc = new RenderTargetViewDescription(); rtvDesc.Texture2D.MipSlice = i; rtvDesc.Dimension = msaa ? RenderTargetViewDimension.Texture2DMultisampled : RenderTargetViewDimension.Texture2D; rtvDesc.Format = Converter.Convert(format); var rtv = new RenderTargetView(device.Device, tex2D, rtvDesc); UnorderedAccessView uav = null; if (enableRWBuffer) { var uavDesc = new UnorderedAccessViewDescription(); uavDesc.Buffer.ElementCount = width * height; uavDesc.Buffer.FirstElement = 0; uavDesc.Buffer.Flags = UnorderedAccessViewBufferFlags.None; uavDesc.Dimension = UnorderedAccessViewDimension.Texture2D; uavDesc.Format = Converter.Convert(format); uavDesc.Texture2D.MipSlice = i; uav = new UnorderedAccessView(device.Device, tex2D, uavDesc); } surfaces[i] = new RenderTargetSurface(rtv, uav, tex2D, i, format, width, height, samples); } }
/// <summary> /// /// </summary> /// <param name="gameTime"></param> /// <param name="stereoEye"></param> /// <param name="viewport"></param> /// <param name="targetSurface"></param> protected void RenderGIS ( GameTime gameTime, StereoEye stereoEye, Viewport viewport, RenderTargetSurface targetSurface ) { if (GisLayers.Any()) { if (GlobeDepthStencil == null) { GlobeDepthStencil = new DepthStencil2D(Game.GraphicsDevice, DepthFormat.D24S8, targetSurface.Width, targetSurface.Height, targetSurface.SampleCount); } else if (GlobeDepthStencil.Width != targetSurface.Width || GlobeDepthStencil.Height != targetSurface.Height) { GlobeDepthStencil.Dispose(); GlobeDepthStencil = new DepthStencil2D(Game.GraphicsDevice, DepthFormat.D24S8, targetSurface.Width, targetSurface.Height, targetSurface.SampleCount); } rs.Device.Clear(GlobeDepthStencil.Surface); Game.GraphicsDevice.SetTargets(GlobeDepthStencil.Surface, targetSurface); GlobeCamera.Viewport = viewport; GlobeCamera.Update(gameTime); rs.Gis.Camera = GlobeCamera; rs.Gis.Draw(gameTime, stereoEye, GisLayers); } }
/// <summary> /// /// </summary> void RenderGeneric ( string passName, GameTime gameTime, Camera camera, Viewport viewport, Matrix view, Matrix projection, RenderTargetSurface colorTarget, DepthStencilSurface depthTarget, ShaderResource depthValues, Flags flags ) { var device = Game.GraphicsDevice; if (rs.SkipParticles) { return; } using ( new PixEvent(passName) ) { device.ResetStates(); // // Setup images : // if (Images!=null && !Images.IsDisposed) { imagesCB.SetData( Images.GetNormalizedRectangles( MaxImages ) ); } SetupGPUParameters( 0, renderWorld, view, projection, flags ); device.ComputeShaderConstants[0] = paramsCB ; // // Render // using (new PixEvent("Drawing")) { device.ResetStates(); // target and viewport : device.SetTargets( depthTarget, colorTarget ); device.SetViewport( viewport ); // params CB : device.ComputeShaderConstants[0] = paramsCB ; device.VertexShaderConstants[0] = paramsCB ; device.GeometryShaderConstants[0] = paramsCB ; device.PixelShaderConstants[0] = paramsCB ; // atlas CB : device.VertexShaderConstants[1] = imagesCB ; device.GeometryShaderConstants[1] = imagesCB ; device.PixelShaderConstants[1] = imagesCB ; // sampler & textures : device.PixelShaderSamplers[0] = SamplerState.LinearClamp4Mips ; device.PixelShaderResources[0] = Images==null? rs.WhiteTexture.Srv : Images.Texture.Srv; device.PixelShaderResources[5] = depthValues; device.GeometryShaderResources[1] = simulationBuffer ; device.GeometryShaderResources[2] = simulationBuffer ; device.GeometryShaderResources[3] = sortParticlesBuffer; device.GeometryShaderResources[4] = particleLighting; // setup PS : device.PipelineState = factory[ (int)flags ]; // GPU time : 0.81 ms -> 0.91 ms device.Draw( MaxSimulatedParticles, 0 ); } } }
/// <summary> /// Performs good-old StretchRect to destination buffer with blending. /// </summary> /// <param name="dst"></param> /// <param name="src"></param> /// <param name="filter"></param> /// <param name="rect"></param> public void RenderSsao ( RenderTargetSurface ssaoDst, StereoEye stereoEye, Camera camera, DepthStencil2D depthSource, RenderTarget2D normalsSource ) { SetDefaultRenderStates(); using( new PixEvent("SSAO") ) { var ssaoParams = new SsaoParams(); ssaoParams.View = camera.GetViewMatrix( stereoEye ); ssaoParams.Projection = camera.GetProjectionMatrix( stereoEye ); ssaoParams.InverseProjection = Matrix.Invert( ssaoParams.Projection ); paramsCB.SetData( ssaoParams ); SetViewport( ssaoDst ); device.SetTargets( null, ssaoDst ); device.PipelineState = factory[ (int)(ShaderFlags.SSAO) ]; device.VertexShaderResources[0] = depthSource; device.PixelShaderResources[0] = depthSource; device.PixelShaderSamplers[0] = SamplerState.PointClamp; device.PixelShaderConstants[0] = paramsCB; device.PixelShaderConstants[1] = randomDirsCB; device.Draw( 3, 0 ); } device.ResetStates(); }
/// <summary> /// /// </summary> /// <param name="gameTime"></param> internal void RenderShadow ( GameTime gameTime, Viewport viewport, Matrix view, Matrix projection, RenderTargetSurface particleShadow, DepthStencilSurface depthBuffer ) { var colorTarget = particleShadow; var depthTarget = depthBuffer; RenderGeneric( "Particles Shadow", gameTime, null, viewport, view, projection, colorTarget, depthTarget, null, Flags.DRAW_SHADOW ); }
public void StretchRect4x4( RenderTargetSurface dst, RenderTarget2D src, SamplerState filter = null, bool flipToCubeFace = false ) { SetDefaultRenderStates(); using( new PixEvent("StretchRect4x4") ) { rs.SetTargets( null, dst ); SetViewport(dst); if (flipToCubeFace) { rs.PipelineState = factory[ (int)(ShaderFlags.DOWNSAMPLE_2_4x4|ShaderFlags.TO_CUBE_FACE) ]; } else { rs.PipelineState = factory[ (int)ShaderFlags.DOWNSAMPLE_2_4x4 ]; } rs.VertexShaderResources[0] = src; rs.PixelShaderResources[0] = src; rs.PixelShaderSamplers[0] = filter ?? SamplerState.LinearPointClamp; rs.Draw( 3, 0 ); } rs.ResetStates(); }
/// <summary> /// /// </summary> /// <param name="depthStencil"></param> /// <param name="renderTargets"></param> public void GetTargets ( out DepthStencilSurface depthStencil, out RenderTargetSurface[] renderTargets ) { depthStencil = depthStencilSurface; renderTargets = renderTargetSurfaces.ToArray(); }
void SetViewport ( RenderTargetSurface dst ) { rs.SetViewport( 0,0, dst.Width, dst.Height ); }
/// <summary> /// Clears render target using given color /// </summary> /// <param name="surface"></param> /// <param name="color"></param> public void Clear ( RenderTargetSurface surface, Color4 color ) { lock (deviceContext) { deviceContext.ClearRenderTargetView( surface.RTV, SharpDXHelper.Convert( color ) ); } }
/// <summary> /// /// </summary> /// <param name="dst">target to copy to</param> /// <param name="src">target to copy from</param> public void FillAlphaOne( RenderTargetSurface dst ) { SetDefaultRenderStates(); using( new PixEvent("FillAlphaOne") ) { if(dst == null) { rs.RestoreBackbuffer(); } else { SetViewport(dst); rs.SetTargets( null, dst ); } rs.PipelineState = factory[ (int)ShaderFlags.FILL_ALPHA_ONE ]; rs.Draw( 3, 0 ); } rs.ResetStates(); }
/// <summary> /// /// </summary> /// <param name="source"></param> /// <param name="destination"></param> public void Resolve ( RenderTargetSurface source, RenderTargetSurface destination ) { if ( source.Width != destination.Width || source.Height != destination.Height ) { throw new GraphicsException( "Could not resolve: source and destination are not the same size"); } if ( source.SampleCount <= 1 ) { throw new GraphicsException( "Could not resolve: source surface is not multisampled"); } if ( destination.SampleCount > 1 ) { throw new GraphicsException( "Could not resolve: destination surface is multisampled"); } lock (deviceContext) { deviceContext.ResolveSubresource( source.Resource, source.Subresource, destination.Resource, destination.Subresource, Converter.Convert( source.Format ) ); } }
/// <summary> /// Performs FXAA antialiasing. /// </summary> /// <param name="dst">Target buffer to render FXAA to</param> /// <param name="src">Source image with luminance in alpha</param> public void Fxaa( RenderTargetSurface dst, ShaderResource src ) { SetDefaultRenderStates(); using( new PixEvent("Fxaa") ) { if(dst == null) { rs.RestoreBackbuffer(); } else { SetViewport( dst ); rs.SetTargets( null, dst ); } rs.PipelineState = factory[ (int)ShaderFlags.FXAA ]; rs.VertexShaderResources[0] = src; rs.PixelShaderResources[0] = src; rs.PixelShaderSamplers[0] = SamplerState.LinearPointClamp; rs.Draw( 3, 0 ); } rs.ResetStates(); }
/// <summary> /// /// </summary> /// <param name="gameTime"></param> /// <param name="stereoEye"></param> void RenderHdrScene ( GameTime gameTime, StereoEye stereoEye, Viewport viewport, RenderTargetSurface targetSurface ) { // clear g-buffer and hdr-buffers: ClearBuffers( viewHdrFrame ); // single pass for stereo rendering : if (stereoEye!=StereoEye.Right) { // simulate particles BEFORE lighting // to make particle lit (position is required) and // get simulated particles for shadows. ParticleSystem.Simulate( gameTime, Camera ); // render shadows : rs.LightRenderer.RenderShadows( this, this.LightSet ); } // render g-buffer : rs.SceneRenderer.RenderGBuffer( stereoEye, Camera, viewHdrFrame, this ); // render ssao : rs.SsaoFilter.Render( stereoEye, Camera, viewHdrFrame.DepthBuffer, viewHdrFrame.NormalMapBuffer ); switch (rs.ShowGBuffer) { case 1 : rs.Filter.Copy( targetSurface, viewHdrFrame.DiffuseBuffer ); return; case 2 : rs.Filter.Copy( targetSurface, viewHdrFrame.SpecularBuffer ); return; case 3 : rs.Filter.Copy( targetSurface, viewHdrFrame.NormalMapBuffer ); return; case 4 : rs.Filter.Copy( targetSurface, viewHdrFrame.ScatteringBuffer ); return; case 5 : rs.Filter.Copy( targetSurface, rs.SsaoFilter.OcclusionMap ); return; case 6 : rs.Filter.StretchRect( targetSurface, rs.LightRenderer.CascadedShadowMap.ParticleShadow ); return; case 7 : rs.Filter.StretchRect( targetSurface, rs.LightRenderer.CascadedShadowMap.ColorBuffer ); return; } // render sky : rs.Sky.Render( Camera, stereoEye, viewHdrFrame, SkySettings ); rs.Sky.RenderFogTable( SkySettings ); // render lights : rs.LightRenderer.RenderLighting( stereoEye, Camera, viewHdrFrame, this, Radiance ); // render "solid" DOF : rs.DofFilter.Render( gameTime, viewHdrFrame.LightAccumulator, viewHdrFrame.HdrBuffer, viewHdrFrame.DepthBuffer, this ); // render and simulate particles : ParticleSystem.Render( gameTime, Camera, stereoEye, viewHdrFrame ); // apply tonemapping and bloom : rs.HdrFilter.Render( gameTime, TempFXBuffer.Surface, viewHdrFrame.HdrBuffer, this ); // apply FXAA if (rs.UseFXAA) { rs.Filter.Fxaa( targetSurface, TempFXBuffer ); } else { rs.Filter.Copy( targetSurface, TempFXBuffer ); } // draw debug lines : Debug.Render( targetSurface, Camera ); }