static int Main(string[] args) { if (args.Length != 2) { Console.WriteLine($"ImageTint <image-path> <out>: Tints the image at <image-path> and saves it to <out>."); return(1); } string inPath = args[0]; string outPath = args[1]; // This demo uses WindowState.Hidden to avoid popping up an unnecessary window to the user. VeldridStartup.CreateWindowAndGraphicsDevice( new WindowCreateInfo { WindowInitialState = WindowState.Hidden, }, new GraphicsDeviceOptions() { ResourceBindingModel = ResourceBindingModel.Improved }, out Sdl2Window window, out GraphicsDevice gd); DisposeCollectorResourceFactory factory = new DisposeCollectorResourceFactory(gd.ResourceFactory); ImageSharpTexture inputImage = new ImageSharpTexture(inPath, false); Texture inputTexture = inputImage.CreateDeviceTexture(gd, factory); TextureView view = factory.CreateTextureView(inputTexture); Texture output = factory.CreateTexture(TextureDescription.Texture2D( inputImage.Width, inputImage.Height, 1, 1, PixelFormat.R8_G8_B8_A8_UNorm, TextureUsage.RenderTarget)); Framebuffer framebuffer = factory.CreateFramebuffer(new FramebufferDescription(null, output)); DeviceBuffer vertexBuffer = factory.CreateBuffer(new BufferDescription(64, BufferUsage.VertexBuffer)); Vector4[] quadVerts = { new Vector4(-1, 1, 0, 0), new Vector4(1, 1, 1, 0), new Vector4(-1, -1, 0, 1), new Vector4(1, -1, 1, 1), }; gd.UpdateBuffer(vertexBuffer, 0, quadVerts); ShaderSetDescription shaderSet = new ShaderSetDescription( new[] { new VertexLayoutDescription( new VertexElementDescription("Position", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float2), new VertexElementDescription("TextureCoordinates", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float2)) }, factory.CreateFromSpirv( new ShaderDescription(ShaderStages.Vertex, ReadEmbeddedAssetBytes("TintShader-vertex.glsl"), "main"), new ShaderDescription(ShaderStages.Fragment, ReadEmbeddedAssetBytes("TintShader-fragment.glsl"), "main"))); ResourceLayout layout = factory.CreateResourceLayout(new ResourceLayoutDescription( new ResourceLayoutElementDescription("Input", ResourceKind.TextureReadOnly, ShaderStages.Fragment), new ResourceLayoutElementDescription("Sampler", ResourceKind.Sampler, ShaderStages.Fragment), new ResourceLayoutElementDescription("Tint", ResourceKind.UniformBuffer, ShaderStages.Fragment))); Pipeline pipeline = factory.CreateGraphicsPipeline(new GraphicsPipelineDescription( BlendStateDescription.SingleOverrideBlend, DepthStencilStateDescription.Disabled, RasterizerStateDescription.Default, PrimitiveTopology.TriangleStrip, shaderSet, layout, framebuffer.OutputDescription)); DeviceBuffer tintInfoBuffer = factory.CreateBuffer(new BufferDescription(16, BufferUsage.UniformBuffer)); gd.UpdateBuffer( tintInfoBuffer, 0, new TintInfo( new Vector3(1f, 0.2f, 0.1f), // Change this to modify the tint color. 0.25f)); ResourceSet resourceSet = factory.CreateResourceSet( new ResourceSetDescription(layout, view, gd.PointSampler, tintInfoBuffer)); // RenderTarget textures are not CPU-visible, so to get our tinted image back, we need to first copy it into // a "staging Texture", which is a Texture that is CPU-visible (it can be Mapped). Texture stage = factory.CreateTexture(TextureDescription.Texture2D( inputImage.Width, inputImage.Height, 1, 1, PixelFormat.R8_G8_B8_A8_UNorm, TextureUsage.Staging)); CommandList cl = factory.CreateCommandList(); cl.Begin(); cl.SetFramebuffer(framebuffer); cl.SetFullViewports(); cl.SetVertexBuffer(0, vertexBuffer); cl.SetPipeline(pipeline); cl.SetGraphicsResourceSet(0, resourceSet); cl.Draw(4, 1, 0, 0); cl.CopyTexture( output, 0, 0, 0, 0, 0, stage, 0, 0, 0, 0, 0, stage.Width, stage.Height, 1, 1); cl.End(); gd.SubmitCommands(cl); gd.WaitForIdle(); // When a texture is mapped into a CPU-visible region, it is often not laid out linearly. // Instead, it is laid out as a series of rows, which are all spaced out evenly by a "row pitch". // This spacing is provided in MappedResource.RowPitch. // It is also possible to obtain a "structured view" of a mapped data region, which is what is done below. // With a structured view, you can read individual elements from the region. // The code below simply iterates over the two-dimensional region and places each texel into a linear buffer. // ImageSharp requires the pixel data be contained in a linear buffer. MappedResourceView <Rgba32> map = gd.Map <Rgba32>(stage, MapMode.Read); // Rgba32 is synonymous with PixelFormat.R8_G8_B8_A8_UNorm. Rgba32[] pixelData = new Rgba32[stage.Width * stage.Height]; for (int y = 0; y < stage.Height; y++) { for (int x = 0; x < stage.Width; x++) { int index = (int)(y * stage.Width + x); pixelData[index] = map[x, y]; } } gd.Unmap(stage); // Resources should be Unmapped when the region is no longer used. Image <Rgba32> outputImage = Image.LoadPixelData(pixelData, (int)stage.Width, (int)stage.Height); outputImage.Save(outPath); factory.DisposeCollector.DisposeAll(); gd.Dispose(); window.Close(); return(0); }
private void CreateResources() { _factory = new DisposeCollectorResourceFactory(_gd.ResourceFactory); _cl = _factory.CreateCommandList(); _cl.Begin(); _projectionBuffer = _factory.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer)); _viewBuffer = _factory.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer)); _modelBuffer = _factory.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer)); _projectionBufferForShadowShader = _factory.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer)); _viewBufferShadow = _factory.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer)); _modelBufferShadow = _factory.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer)); // TODO: no idea why this buffer requires 48 bytes instead of 32 bytes, padding? //_directionLightBuffer = _factory.CreateBuffer(new BufferDescription(48, BufferUsage.UniformBuffer)); // addition of shadowmatrix, now requires (48+64=) 112 bytes _directionLightBuffer = _factory.CreateBuffer(new BufferDescription(112, BufferUsage.UniformBuffer)); _cl.End(); _gd.SubmitCommands(_cl); _gd.WaitForIdle(); ShaderSetDescription shaderSet = new ShaderSetDescription( new[] { new VertexLayoutDescription( new VertexElementDescription("Position", VertexElementSemantic.Position, VertexElementFormat.Float3), new VertexElementDescription("Color", VertexElementSemantic.Color, VertexElementFormat.Float3), new VertexElementDescription("Normal", VertexElementSemantic.Normal, VertexElementFormat.Float3)) }, new[] { LoadShader(_factory, "ColorShader", ShaderStages.Vertex, "VS"), LoadShader(_factory, "ColorShader", ShaderStages.Fragment, "FS") }); ShaderSetDescription shaderSetShadow = new ShaderSetDescription( new[] { new VertexLayoutDescription( new VertexElementDescription("Position", VertexElementSemantic.Position, VertexElementFormat.Float3), new VertexElementDescription("Color", VertexElementSemantic.Color, VertexElementFormat.Float3), new VertexElementDescription("Normal", VertexElementSemantic.Normal, VertexElementFormat.Float3)) }, new[] { LoadShader(_factory, "ShadowShader", ShaderStages.Vertex, "VS"), LoadShader(_factory, "ShadowShader", ShaderStages.Fragment, "FS") }); ResourceLayout projectionViewMatricesLightLayout = _factory.CreateResourceLayout( new ResourceLayoutDescription( new ResourceLayoutElementDescription("Projection", ResourceKind.UniformBuffer, ShaderStages.Vertex), new ResourceLayoutElementDescription("View", ResourceKind.UniformBuffer, ShaderStages.Vertex), new ResourceLayoutElementDescription("DirectionalLight", ResourceKind.UniformBuffer, ShaderStages.Vertex | ShaderStages.Fragment), new ResourceLayoutElementDescription("ShadowMap", ResourceKind.TextureReadOnly, ShaderStages.Fragment), new ResourceLayoutElementDescription("ShadowMapSampler", ResourceKind.Sampler, ShaderStages.Fragment) )); ResourceLayout perObjectLayout = _factory.CreateResourceLayout( new ResourceLayoutDescription( new ResourceLayoutElementDescription("Model", ResourceKind.UniformBuffer, ShaderStages.Vertex) )); ResourceLayout projectionViewMatricesLayoutShadow = _factory.CreateResourceLayout( new ResourceLayoutDescription( new ResourceLayoutElementDescription("Projection", ResourceKind.UniformBuffer, ShaderStages.Vertex), new ResourceLayoutElementDescription("View", ResourceKind.UniformBuffer, ShaderStages.Vertex) )); ResourceLayout modelLayoutShadow = _factory.CreateResourceLayout( new ResourceLayoutDescription( new ResourceLayoutElementDescription("Model", ResourceKind.UniformBuffer, ShaderStages.Vertex) )); _pipeline = _factory.CreateGraphicsPipeline(new GraphicsPipelineDescription( BlendStateDescription.SingleOverrideBlend, DepthStencilStateDescription.DepthOnlyLessEqual, RasterizerStateDescription.Default, PrimitiveTopology.TriangleList, shaderSet, new[] { projectionViewMatricesLightLayout, perObjectLayout }, _gd.SwapchainFramebuffer.OutputDescription)); TextureDescription desc = TextureDescription.Texture2D(2048, 2048, 1, 1, PixelFormat.D32_Float_S8_UInt, TextureUsage.DepthStencil | TextureUsage.Sampled); _shadowMap = _factory.CreateTexture(desc); _shadowMap.Name = "Shadow Map"; _shadowMapView = _factory.CreateTextureView(_shadowMap); _shadowMapFramebuffer = _factory.CreateFramebuffer(new FramebufferDescription( new FramebufferAttachmentDescription(_shadowMap, 0), Array.Empty <FramebufferAttachmentDescription>())); _pipelineShadow = _factory.CreateGraphicsPipeline(new GraphicsPipelineDescription( BlendStateDescription.Empty, DepthStencilStateDescription.DepthOnlyLessEqual, RasterizerStateDescription.Default, PrimitiveTopology.TriangleList, shaderSetShadow, new[] { projectionViewMatricesLayoutShadow, modelLayoutShadow }, _shadowMapFramebuffer.OutputDescription)); _projectionViewMatricesLightSet = _factory.CreateResourceSet(new ResourceSetDescription( projectionViewMatricesLightLayout, _projectionBuffer, _viewBuffer, _directionLightBuffer, _shadowMapView, _gd.PointSampler)); _perObjectSet = _factory.CreateResourceSet(new ResourceSetDescription( perObjectLayout, _modelBuffer)); _projectionViewMatricesSetShadow = _factory.CreateResourceSet(new ResourceSetDescription( projectionViewMatricesLayoutShadow, _projectionBufferForShadowShader, _viewBufferShadow)); _modelMatrixSetShadow = _factory.CreateResourceSet(new ResourceSetDescription( modelLayoutShadow, _modelBufferShadow)); }
public Framebuffer CreateFramebuffer(FramebufferDescription framebufferDescription) => _factory.CreateFramebuffer(framebufferDescription);