/// <summary> /// Creates a new instance of <see cref="RenderFrame"/> from the specified parameters. /// </summary> /// <param name="graphicsDevice">The graphics device.</param> /// <param name="frameDescriptor">The frame descriptor.</param> /// <param name="referenceFrame">The reference frame, when using relative mode for <see cref="RenderFrameDescriptor.Mode"/>.</param> /// <returns>A new instance of <see cref="RenderFrame"/>.</returns> /// <exception cref="System.ArgumentNullException"> /// graphicsDevice /// or /// frameDescriptor /// </exception> public static RenderFrame New(GraphicsDevice graphicsDevice, RenderFrameDescriptor frameDescriptor, RenderFrame referenceFrame = null) { // Just return null if no render frame is defined if (frameDescriptor.DepthFormat == RenderFrameDepthFormat.None && frameDescriptor.Format == RenderFrameFormat.None) { return(null); } var renderFrame = new RenderFrame(); renderFrame.InitializeFrom(graphicsDevice, frameDescriptor, referenceFrame); return(renderFrame); }
// TODO: Should we move this to Graphics instead? /// <summary> /// Initializes a new instance of the <see cref="RenderFrame" /> class. /// </summary> /// <param name="descriptor">The descriptor.</param> /// <param name="renderTargets">The render target.</param> /// <param name="depthStencil">The depth stencil.</param> /// <param name="ownsResources">if set to <c>true</c> this instance is owning the rendertargets and depth stencil buffer.</param> private void InitializeFrom(RenderFrameDescriptor descriptor, Texture[] renderTargets, Texture depthStencil, bool ownsResources) { Descriptor = descriptor; RenderTargets = renderTargets; DepthStencil = depthStencil; isOwner = ownsResources; if (renderTargets != null) { foreach (var renderTarget in renderTargets) { if (renderTarget != null) { ReferenceTexture = renderTarget; break; } } } if (ReferenceTexture == null && depthStencil != null) { ReferenceTexture = depthStencil; } }
internal void InitializeFrom(GraphicsDevice device, RenderFrameDescriptor description, RenderFrame referenceFrame = null) { if (device == null) { throw new ArgumentNullException("device"); } if (description.DepthFormat == RenderFrameDepthFormat.None && description.Format == RenderFrameFormat.None) { return; } var referenceTexture = referenceFrame != null ? referenceFrame.ReferenceTexture : device.BackBuffer; int width = description.Width; int height = description.Height; if (description.Mode == RenderFrameSizeMode.Relative) { width = (width * referenceTexture.Width) / 100; height = (height * referenceTexture.Height) / 100; } var pixelFormat = PixelFormat.None; if (description.Format == RenderFrameFormat.LDR) { pixelFormat = device.ColorSpace == ColorSpace.Linear ? PixelFormat.R8G8B8A8_UNorm_SRgb : PixelFormat.R8G8B8A8_UNorm; } else if (description.Format == RenderFrameFormat.HDR) { pixelFormat = PixelFormat.R16G16B16A16_Float; } var depthFormat = PixelFormat.None; switch (description.DepthFormat) { case RenderFrameDepthFormat.Depth: depthFormat = PixelFormat.D32_Float; break; case RenderFrameDepthFormat.DepthAndStencil: depthFormat = PixelFormat.D24_UNorm_S8_UInt; break; } // Create the render target Texture renderTarget = null; if (pixelFormat != PixelFormat.None) { renderTarget = Texture.New2D(device, width, height, 1, pixelFormat, TextureFlags.RenderTarget | TextureFlags.ShaderResource); } // Create the depth stencil buffer Texture depthStencil = null; // TODO: Better handle the case where shared cannot be used. Should we throw an exception? if (description.DepthFormat == RenderFrameDepthFormat.Shared && referenceFrame != null && referenceFrame.DepthStencil != null && referenceFrame.DepthStencil.Width == width && referenceFrame.DepthStencil.Height == height) { depthStencil = referenceFrame.DepthStencil; } else if (description.DepthFormat == RenderFrameDepthFormat.Depth || description.DepthFormat == RenderFrameDepthFormat.DepthAndStencil) { var depthStencilExtraFlag = device.Features.Profile >= GraphicsProfile.Level_10_0 ? TextureFlags.ShaderResource : TextureFlags.None; depthStencil = Texture.New2D(device, width, height, 1, depthFormat, TextureFlags.DepthStencil | depthStencilExtraFlag); } InitializeFrom(description, renderTarget != null ? new[] { renderTarget } : null, depthStencil, true); }
/// <summary> /// Creates a fake instance of <see cref="RenderFrame"/> for serialization. /// </summary> /// <param name="frameDescriptor">The frame descriptor.</param> /// <returns>A new instance of <see cref="RenderFrame"/>.</returns> public static RenderFrame NewFake(RenderFrameDescriptor frameDescriptor) { return(new RenderFrame { Descriptor = frameDescriptor }); }
/// <summary> /// Recover a <see cref="RenderFrame" /> from a texture that has been created for a render frame. /// </summary> /// <param name="renderTextures">The texture.</param> /// <param name="depthStencilTexture">The depth stencil texture.</param> /// <returns>The instance of RenderFrame or null if no render frame was used to create this texture.</returns> /// <exception cref="System.InvalidOperationException">The texture must be a render target</exception> public static RenderFrame FromTexture(Texture[] renderTextures, Texture depthStencilTexture = null) { Texture referenceTexture = null; if (renderTextures != null) { foreach (var renderTexture in renderTextures) { if (renderTexture != null && !renderTexture.IsRenderTarget) { throw new ArgumentException("The texture must be a render target", "renderTextures"); } if (referenceTexture == null && renderTexture != null) { referenceTexture = renderTexture; } else if (renderTexture != null) { if (referenceTexture.Width != renderTexture.Width || referenceTexture.Height != renderTexture.Height) { throw new ArgumentException("Invalid textures. The textures must have the same width/height", "renderTextures"); } } } } if (depthStencilTexture != null && !depthStencilTexture.IsDepthStencil) { throw new ArgumentException("The texture must be a depth stencil texture", "depthStencilTexture"); } if (referenceTexture == null && depthStencilTexture != null) { referenceTexture = depthStencilTexture; } else if (depthStencilTexture != null) { if (referenceTexture.Width != depthStencilTexture.Width || referenceTexture.Height != depthStencilTexture.Height) { throw new ArgumentException("Invalid textures/depthstencil. The textures must have the same width/height", "depthStencilTexture"); } } // If no relevant textures, than return null if (referenceTexture == null) { return(null); } var descriptor = RenderFrameDescriptor.Default(); // TODO: Check for formats? var renderFrameFormat = RenderFrameFormat.LDR; if (referenceTexture.Format == PixelFormat.R16G16B16A16_Float) { renderFrameFormat = RenderFrameFormat.HDR; } var depthFrameFormat = RenderFrameDepthFormat.None; if (depthStencilTexture != null) { depthFrameFormat = depthStencilTexture.HasStencil ? RenderFrameDepthFormat.DepthAndStencil : RenderFrameDepthFormat.Depth; } descriptor.Format = renderFrameFormat; descriptor.DepthFormat = depthFrameFormat; descriptor.Mode = RenderFrameSizeMode.Fixed; descriptor.Width = referenceTexture.Width; descriptor.Height = referenceTexture.Height; var renderFrame = new RenderFrame(); renderFrame.InitializeFrom(descriptor, renderTextures, depthStencilTexture, false); return(renderFrame); }