/// <summary> /// Function to build or rebuild the depth buffer. /// </summary> /// <param name="width">The width of the depth buffer.</param> /// <param name="height">The height of the depth buffer.</param> private static void BuildDepthBuffer(int width, int height) { _depthBuffer?.Dispose(); _depthBuffer = GorgonDepthStencil2DView.CreateDepthStencil(_graphics, new GorgonTexture2DInfo { Usage = ResourceUsage.Default, Width = width, Height = height, Format = BufferFormat.D24_UNorm_S8_UInt, Binding = TextureBinding.DepthStencil }); }
/// <summary> /// Function to build or rebuild the depth buffer. /// </summary> /// <param name="width">The width of the depth buffer.</param> /// <param name="height">The height of the depth buffer.</param> private static void BuildDepthBuffer(int width, int height) { _graphics.SetDepthStencil(null); _depthBuffer?.Dispose(); _depthBuffer = GorgonDepthStencil2DView.CreateDepthStencil(_graphics, new GorgonTexture2DInfo("Depth Buffer") { Usage = ResourceUsage.Default, Width = width, Height = height, Format = _depthFormat }); }
/// <summary> /// Handles the AfterSwapChainResized event of the Swap control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="AfterSwapChainResizedEventArgs"/> instance containing the event data.</param> private static void Swap_AfterSwapChainResized(object sender, AfterSwapChainResizedEventArgs e) { // We need to recreate the depth/stencil here to match the updated size of the render target (the depth/stencil and render targets must be the same size). _depthStencil = GorgonDepthStencil2DView.CreateDepthStencil(_graphics, new GorgonTexture2DInfo { Format = BufferFormat.D24_UNorm_S8_UInt, Binding = TextureBinding.DepthStencil, Usage = ResourceUsage.Default, Width = _swap.Width, Height = _swap.Height }); _graphics.SetDepthStencil(_depthStencil); // When we resize, the projection matrix will go out of date, so we need to update our constant buffer with an updated projection. DX.Matrix.PerspectiveFovLH((65.0f).ToRadians(), (float)_swap.Width / _swap.Height, 0.125f, 1000.0f, out _projection); _vsConstants.Buffer.SetData(ref _projection); }
/// <summary> /// Function used to initialize the application. /// </summary> private static void Initialize() { GorgonExample.ResourceBaseDirectory = new DirectoryInfo(Settings.Default.ResourceLocation); // Build the form so we can actually show something. _mainForm = GorgonExample.Initialize(new DX.Size2(1280, 800), "Geometry Shaders"); try { // Now we create and enumerate the list of video devices installed in the computer. // We must do this in order to tell Gorgon which video device we intend to use. Note that this method may be quite slow (particularly when running DEBUG versions of // Direct 3D). To counter this, this object and its Enumerate method are thread safe so this can be run in the background while keeping the main UI responsive. // // If no suitable device was found (no Direct 3D 11.4 support) in the computer, this method will return an empty list. However, if it succeeds, then the devices list // will be populated with an IGorgonVideoDeviceInfo for each suitable video device in the system. // // Using this method, we could also enumerate the WARP software rasterizer, and/of the D3D Reference device (only if the DEBUG functionality provided by the Windows // SDK is installed). These devices are typically used to determine if there's a driver error, and can be terribly slow to render (reference moreso than WARP). It is // recommended that these only be used in diagnostic scenarios only. IReadOnlyList <IGorgonVideoAdapterInfo> devices = GorgonGraphics.EnumerateAdapters(log: GorgonApplication.Log); if (devices.Count == 0) { GorgonDialogs.ErrorBox(_mainForm, "This example requires a video adapter that supports Direct3D 11.4 or better."); GorgonApplication.Quit(); return; } // Now we create the main graphics interface with the first applicable video device. _graphics = new GorgonGraphics(devices[0], log: GorgonApplication.Log); // Check to ensure that we can support the format required for our swap chain. // If a video device can't support this format, then the odds are good it won't render anything. Since we're asking for a very common display format, this will // succeed nearly 100% of the time. Regardless, it's good form to the check for a working display format prior to setting up the swap chain. // // This is also used to determine if a format can be used for other objects (e.g. a texture, render target, etc...) And like the swap chain format, it is also best // practice to check if the object you're creating supports the desired format. if (!_graphics.FormatSupport[BufferFormat.R8G8B8A8_UNorm].IsDisplayFormat) { // We should never see this unless you've got some very esoteric hardware. GorgonDialogs.ErrorBox(_mainForm, "We should not see this error."); return; } // Finally, create a swap chain to display our output. // In this case we're setting up our swap chain to bind with our main window, and we use its client size to determine the width/height of the swap chain back buffers. // This width/height does not need to be the same size as the window, but, except for some scenarios, that would produce undesirable image quality. _swap = new GorgonSwapChain(_graphics, _mainForm, new GorgonSwapChainInfo("Main Swap Chain") { Format = BufferFormat.R8G8B8A8_UNorm, Width = _mainForm.ClientSize.Width, Height = _mainForm.ClientSize.Height }); // Assign events so we can update our projection with our window size. _swap.BeforeSwapChainResized += Swap_BeforeSwapChainResized; _swap.AfterSwapChainResized += Swap_AfterSwapChainResized; // We'll need a depth buffer for this example, or else our pyramid will look weird when rotating as back faces will appear through front faces. // So, first we should check for support of a proper depth/stencil format. That said, if we don't have this format, then we're likely not running hardware from the last decade or more. if (!_graphics.FormatSupport[BufferFormat.D24_UNorm_S8_UInt].IsDepthBufferFormat) { GorgonDialogs.ErrorBox(_mainForm, "A 24 bit depth buffer is required for this example."); return; } _depthStencil = GorgonDepthStencil2DView.CreateDepthStencil(_graphics, new GorgonTexture2DInfo { Format = BufferFormat.D24_UNorm_S8_UInt, Binding = TextureBinding.DepthStencil, Usage = ResourceUsage.Default, Width = _swap.Width, Height = _swap.Height }); // Load the shaders from a file on disc. LoadShaders(); // Load the texture. _texture = GorgonTexture2DView.FromFile(_graphics, Path.Combine(GorgonExample.GetResourcePath(@"Textures\GeometryShader\").FullName, "GSTexture.png"), new GorgonCodecPng()); // Create our builders so we can compose a draw call and pipeline state. _drawCallBuilder = new GorgonDrawCallBuilder(); _pipeStateBuilder = new GorgonPipelineStateBuilder(_graphics); // Create a constant buffer so we can adjust the positioning of the data. DX.Matrix.PerspectiveFovLH((65.0f).ToRadians(), (float)_swap.Width / _swap.Height, 0.125f, 1000.0f, out _projection); _vsConstants = GorgonConstantBufferView.CreateConstantBuffer(_graphics, new GorgonConstantBufferInfo("WorldProjection CBuffer") { SizeInBytes = (DX.Matrix.SizeInBytes * 2) + DX.Vector4.SizeInBytes }); _vsConstants.Buffer.SetData(ref _projection, copyMode: CopyMode.Discard); _vsConstants.Buffer.SetData(ref _worldMatrix, 64, CopyMode.NoOverwrite); // Create a draw call so we actually have something we can draw. _drawCall = _drawCallBuilder.VertexRange(0, 3) .PipelineState(_pipeStateBuilder.PixelShader(_pixelShader) .VertexShader(_bufferless) .GeometryShader(_geometryShader) .DepthStencilState(GorgonDepthStencilState.DepthEnabled)) .ShaderResource(ShaderType.Pixel, _texture) .ConstantBuffer(ShaderType.Vertex, _vsConstants) .ConstantBuffer(ShaderType.Geometry, _vsConstants) .Build(); // Finally set our swap chain as the active rendering target and the depth/stencil buffer. _graphics.SetRenderTarget(_swap.RenderTargetView, _depthStencil); GorgonExample.LoadResources(_graphics); } finally { GorgonExample.EndInit(); } }
/// <summary> /// Function to initialize the application. /// </summary> /// <returns>The main window for the application.</returns> private static FormMain Initialize() { GorgonExample.ResourceBaseDirectory = new DirectoryInfo(Settings.Default.ResourceLocation); GorgonExample.PlugInLocationDirectory = new DirectoryInfo(Settings.Default.PlugInLocation); FormMain window = GorgonExample.Initialize(new DX.Size2(Settings.Default.Resolution.Width, Settings.Default.Resolution.Height), "Depth"); try { IReadOnlyList <IGorgonVideoAdapterInfo> videoDevices = GorgonGraphics.EnumerateAdapters(log: GorgonApplication.Log); if (videoDevices.Count == 0) { throw new GorgonException(GorgonResult.CannotCreate, "Gorgon requires at least a Direct3D 11.4 capable video device.\nThere is no suitable device installed on the system."); } // Find the best video device. _graphics = new GorgonGraphics(videoDevices.OrderByDescending(item => item.FeatureSet).First()); _screen = new GorgonSwapChain(_graphics, window, new GorgonSwapChainInfo("Gorgon2D Depth Buffer Example") { Width = Settings.Default.Resolution.Width, Height = Settings.Default.Resolution.Height, Format = BufferFormat.R8G8B8A8_UNorm }); _depthBuffer = GorgonDepthStencil2DView.CreateDepthStencil(_graphics, new GorgonTexture2DInfo(_screen.RenderTargetView) { Binding = TextureBinding.DepthStencil, Format = BufferFormat.D24_UNorm_S8_UInt }); // Tell the graphics API that we want to render to the "screen" swap chain. _graphics.SetRenderTarget(_screen.RenderTargetView, _depthBuffer); // Initialize the renderer so that we are able to draw stuff. _renderer = new Gorgon2D(_graphics); GorgonExample.LoadResources(_graphics); // Load our packed file system plug in. _assemblyCache = new GorgonMefPlugInCache(GorgonApplication.Log); _assemblyCache.LoadPlugInAssemblies(GorgonExample.GetPlugInPath().FullName, "Gorgon.FileSystem.GorPack.dll"); IGorgonPlugInService plugIns = new GorgonMefPlugInService(_assemblyCache); // Load the file system containing our application data (sprites, images, etc...) IGorgonFileSystemProviderFactory providerFactory = new GorgonFileSystemProviderFactory(plugIns, GorgonApplication.Log); IGorgonFileSystemProvider provider = providerFactory.CreateProvider("Gorgon.IO.GorPack.GorPackProvider"); IGorgonFileSystem fileSystem = new GorgonFileSystem(provider, GorgonApplication.Log); // We can load the editor file system directly. // This is handy for switching a production environment where your data may be stored // as a compressed file, and a development environment where your data consists of loose // files. // fileSystem.Mount(@"D:\unpak\scratch\DeepAsAPuddle.gorPack\fs\"); // For now though, we'll load the packed file. fileSystem.Mount(Path.Combine(GorgonExample.GetResourcePath(@"FileSystems").FullName, "Depth.gorPack")); // Get our sprites. These make up the frames of animation for our Guy. // If and when there's an animation editor, we'll only need to create a single sprite and load the animation. IGorgonVirtualFile[] spriteFiles = fileSystem.FindFiles("/Sprites/", "*", true).ToArray(); // Load our sprite data (any associated textures will be loaded as well). Dictionary <string, GorgonSprite> sprites = new Dictionary <string, GorgonSprite>(StringComparer.OrdinalIgnoreCase); for (int i = 0; i < spriteFiles.Length; i++) { IGorgonVirtualFile file = spriteFiles[i]; (GorgonSprite sprite, GorgonTexture2D texture) = fileSystem.LoadSprite(_renderer, file.FullPath); // The LoadSprite extension method will automatically find and load your associated texture if you're using // a Gorgon editor file system. So it's important that you leep track of your textures, disposing of just // the associated GorgonTexture2DView won't cut it here, so you'll need to dispose the actual texture resource // when you're done with it. if (!_textures.Contains(texture)) { _textures.Add(texture); } // At super duper resolution, the example graphics would be really hard to see, so we'll scale them up. sprite.Scale = new DX.Vector2((_screen.Width / (_screen.Height / 2)) * 2.0f); sprites[file.Name] = sprite; } _snowTile = sprites["Snow"]; _snowTile.Depth = 0.5f; _icicle = sprites["Icicle"]; _icicle.Depth = 0.2f; _guySprite = sprites["Guy_Up_0"]; _guySprite.Depth = 0.1f; _guyPosition = new DX.Vector2(_screen.Width / 2 + _guySprite.ScaledSize.Width * 1.25f, _screen.Height / 2 + _guySprite.ScaledSize.Height); BuildAnimations(sprites); } finally { GorgonExample.EndInit(); } return(window); }