/// <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() { // Initialize the default look up table. using (IGorgonImage image = new GorgonImage(new GorgonImageInfo(ImageType.Image1D, BufferFormat.R8G8B8A8_UNorm) { Width = 3 })) { image.ImageData.ReadAs <int>(0) = GorgonColor.RedPure.ToABGR(); image.ImageData.ReadAs <int>(4) = GorgonColor.BluePure.ToABGR(); image.ImageData.ReadAs <int>(8) = GorgonColor.GreenPure.ToABGR(); _defaultLut = GorgonTexture1DView.CreateTexture(Graphics, new GorgonTexture1DInfo("Default Spectral LUT") { Binding = TextureBinding.ShaderResource, Usage = ResourceUsage.Immutable, Width = 3 }, image); } _chromeAbShader = GorgonShaderFactory.Compile <GorgonPixelShader>(Graphics, Resources.ChromaticAberration, "ChromaticAberration", GorgonGraphics.IsDebugEnabled); _simpleChromeAbShader = GorgonShaderFactory.Compile <GorgonPixelShader>(Graphics, Resources.ChromaticAberration, "ChromaticAberrationSimple", GorgonGraphics.IsDebugEnabled); _settings = GorgonConstantBufferView.CreateConstantBuffer(Graphics, new GorgonConstantBufferInfo("Chromatic Aberration Settings Buffer") { SizeInBytes = DX.Vector4.SizeInBytes, Usage = ResourceUsage.Default }); }
/// <summary> /// Initializes a new instance of the <see cref="CameraController"/> class. /// </summary> /// <param name="graphics">The graphics interface used for the camera buffer data.</param> public CameraController(GorgonGraphics graphics) { Graphics = graphics; _cameraBuffer = GorgonConstantBufferView.CreateConstantBuffer(graphics, ref _viewProjectionMatrix, "Gorgon 2D Camera Constant Buffer", ResourceUsage.Dynamic); }
/// <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 create a new constant buffer so we can upload data to the shaders on the GPU. /// </summary> /// <param name="window">The application window.</param> private static void CreateConstantBuffer(Form window) { // Our projection matrix. // Build our projection matrix using a 65 degree field of view and an aspect ratio that matches our current window aspect ratio. // Note that we depth a depth range from 0.001f up to 1000.0f. This provides a near and far plane for clipping. // These clipping values must have the world transformed vertex data inside of it or else it will not render. Note that the near/far plane is not a // linear range and Z accuracy can get worse the further from the near plane that you get (particularly with depth buffers). DX.Matrix.PerspectiveFovLH(65.0f.ToRadians(), window.ClientSize.Width / (float)window.ClientSize.Height, 0.125f, 1000f, out DX.Matrix projectionMatrix); // Create our constant buffer. // // The data we pass into here will apply the projection transformation to our vertex data so we can transform from 3D space into 2D space. _constantBuffer = GorgonConstantBufferView.CreateConstantBuffer(_graphics, ref projectionMatrix, "MiniTri WVP Constant Buffer"); }
/// <summary> /// Function to build up the constant buffer data for our shaders. /// </summary> private void BuildConstantBuffers() { var worldMatrix = DX.Matrix.Identity; DX.Vector3 cameraPos = _viewMatrix.TranslationVector; var emptyMaterial = new Material { Albedo = GorgonColor.White, SpecularPower = 1.0f, UVOffset = DX.Vector2.Zero }; _viewProjectionBuffer = GorgonConstantBufferView.CreateConstantBuffer(_graphics, ref _viewProjection, "Projection/View Buffer", ResourceUsage.Dynamic); _cameraBuffer = GorgonConstantBufferView.CreateConstantBuffer(_graphics, ref cameraPos, "CameraBuffer", ResourceUsage.Dynamic); _worldBuffer = GorgonConstantBufferView.CreateConstantBuffer(_graphics, ref worldMatrix, "WorldBuffer", ResourceUsage.Dynamic); _materialBuffer = GorgonConstantBufferView.CreateConstantBuffer(_graphics, ref emptyMaterial, "MaterialBuffer", ResourceUsage.Dynamic); _lightBuffer = GorgonConstantBufferView.CreateConstantBuffer(_graphics, new GorgonConstantBufferInfo("LightDataBuffer") { Usage = ResourceUsage.Default, SizeInBytes = Unsafe.SizeOf <LightData>() * MaxLights }); }
/// <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 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); } }
/// <summary> /// Function to initialize the GPU resource objects. /// </summary> private static void InitializeGpuResources() { _graphics = CreateGraphicsInterface(); // If we couldn't create the graphics interface, then leave. if (_graphics == null) { return; } // Create a 1280x800 window with a depth buffer. // We can modify the resolution in the config file for the application, but like other Gorgon examples, the default is 1280x800. _swap = new GorgonSwapChain(_graphics, _mainForm, new GorgonSwapChainInfo("Main") { // Set up for 32 bit RGBA normalized display. Format = BufferFormat.R8G8B8A8_UNorm, Width = Settings.Default.Resolution.Width, Height = Settings.Default.Resolution.Height }); // Build the depth buffer for our swap chain. BuildDepthBuffer(_swap.Width, _swap.Height); if (!Settings.Default.IsWindowed) { // Get the output for the main window. var currentScreen = Screen.FromControl(_mainForm); IGorgonVideoOutputInfo output = _graphics.VideoAdapter.Outputs[currentScreen.DeviceName]; // If we've asked for full screen mode, then locate the correct video mode and set us up. _selectedVideoMode = new GorgonVideoMode(Settings.Default.Resolution.Width, Settings.Default.Resolution.Height, BufferFormat.R8G8B8A8_UNorm); _swap.EnterFullScreen(in _selectedVideoMode, output); } // Handle resizing because the projection matrix and depth buffer needs to be updated to reflect the new view size. _swap.BeforeSwapChainResized += Swap_BeforeResized; _swap.AfterSwapChainResized += Swap_AfterResized; // Set the current render target output so we can see something. _graphics.SetRenderTarget(_swap.RenderTargetView, _depthBuffer); // Create our shaders. // Our vertex shader. This is a simple shader, it just processes a vertex by multiplying it against // the world/view/projection matrix and spits it back out. _vertexShader = GorgonShaderFactory.Compile <GorgonVertexShader>(_graphics, Resources.Shader, "BoingerVS"); // Our main pixel shader. This is a very simple shader, it just reads a texture and spits it back out. Has no // diffuse capability. _pixelShader = GorgonShaderFactory.Compile <GorgonPixelShader>(_graphics, Resources.Shader, "BoingerPS"); // Create the vertex input layout. // We need to create a layout for our vertex type because the shader won't know how to interpret the data we're sending it otherwise. // This is why we need a vertex shader before we even create the layout. _inputLayout = GorgonInputLayout.CreateUsingType <BoingerVertex>(_graphics, _vertexShader); // Resources are stored as System.Drawing.Bitmap files, so we need to convert into an IGorgonImage so we can upload it to a texture. // We also will generate mip-map levels for this image so that scaling the texture will look better. using (IGorgonImage image = Resources.Texture.ToGorgonImage()) { _texture = image.ToTexture2D(_graphics, new GorgonTexture2DLoadOptions { Usage = ResourceUsage.Immutable, Name = "Texture" }) .GetShaderResourceView(); } // Create our constant buffer. // Our constant buffers are how we send data to our shaders. This one in particular will be responsible for sending our world/view/projection matrix // to the vertex shader. _wvpBuffer = GorgonConstantBufferView.CreateConstantBuffer(_graphics, new GorgonConstantBufferInfo("WVPBuffer") { Usage = ResourceUsage.Dynamic, SizeInBytes = DX.Matrix.SizeInBytes }); // This one will hold our material information. _materialBuffer = GorgonConstantBufferView.CreateConstantBuffer(_graphics, new GorgonConstantBufferInfo("MaterialBuffer") { Usage = ResourceUsage.Dynamic, SizeInBytes = Unsafe.SizeOf <GorgonColor>() }); GorgonColor defaultMaterialColor = GorgonColor.White; _materialBuffer.Buffer.SetData(ref defaultMaterialColor); GorgonExample.LoadResources(_graphics); }