From 8e840ece27446b7c09e90be97ee199808aa60a9e Mon Sep 17 00:00:00 2001 From: Michele Date: Fri, 15 Jan 2021 11:11:28 +0000 Subject: [PATCH] fixed shader rendering --- Sledgemapper/Content/Content.mgcb | 6 + Sledgemapper/Content/shaders/OutlineShader.fx | 10 +- .../Content/shaders/OutlineShader2.fx | 209 ++++++++++++++++++ Sledgemapper/Settings.cs | 2 +- Sledgemapper/Sledgemapper.cs | 27 ++- 5 files changed, 240 insertions(+), 14 deletions(-) create mode 100644 Sledgemapper/Content/shaders/OutlineShader2.fx diff --git a/Sledgemapper/Content/Content.mgcb b/Sledgemapper/Content/Content.mgcb index 9171191..7b86017 100644 --- a/Sledgemapper/Content/Content.mgcb +++ b/Sledgemapper/Content/Content.mgcb @@ -3027,6 +3027,12 @@ /processorParam:DebugMode=Auto /build:shaders/OutlineShader.fx +#begin shaders/OutlineShader2.fx +/importer:EffectImporter +/processor:EffectProcessor +/processorParam:DebugMode=Auto +/build:shaders/OutlineShader2.fx + #begin tiles/tile01.png /importer:TextureImporter /processor:TextureProcessor diff --git a/Sledgemapper/Content/shaders/OutlineShader.fx b/Sledgemapper/Content/shaders/OutlineShader.fx index d4b90cf..b5dac7f 100644 --- a/Sledgemapper/Content/shaders/OutlineShader.fx +++ b/Sledgemapper/Content/shaders/OutlineShader.fx @@ -119,11 +119,11 @@ float4 MainPS(VertexShaderOutput input) : COLOR // return color; -//############################################################## - - float2 pixelSize = 1/ float2((float) ImageSize.x, (float) ImageSize.y); +//############################################################## int px = (int) input.TextureCoordinates.x*ImageSize.x; int py = (int) input.TextureCoordinates.y*ImageSize.y; + +float2 pixel = input.TextureCoordinates*ImageSize; float4 color = tex2D(SpriteTextureSampler, input.TextureCoordinates); if(color.a==1) {return color;} @@ -147,8 +147,8 @@ int i, j = 0; while (j < 8) { // float2 curUV = input.TextureCoordinates + ((offsets[j] * pixelSize.x + offsets[j] *pixelSize.y)* i); - float checkpx=(float)px+0.5+(float)10*offsets[j].x; - float checkpy=(float)py+0.5+(float)10*offsets[j].y; + float checkpx=(float)px+(float)BorderSize*offsets[j].x; + float checkpy=(float)py+(float)BorderSize*offsets[j].y; float curUVx = input.TextureCoordinates.x + (float)checkpx/(float)ImageSize.x; float curUVy = input.TextureCoordinates.y + (float)checkpy/(float)ImageSize.y; diff --git a/Sledgemapper/Content/shaders/OutlineShader2.fx b/Sledgemapper/Content/shaders/OutlineShader2.fx new file mode 100644 index 0000000..9479af2 --- /dev/null +++ b/Sledgemapper/Content/shaders/OutlineShader2.fx @@ -0,0 +1,209 @@ +/* ******************************************************** + * A Simple toon shader based on the work of Petri T. Wilhelmsen + * found on his blog post XNA Shader Programming � Tutorial 7, Toon shading + * http://digitalerr0r.wordpress.com/2009/03/22/xna-shader-programming-tutorial-7-toon-shading/. + * Which in turn is based on the shader "post edgeDetect" from nVidias Shader library + * http://developer.download.nvidia.com/shaderlibrary/webpages/shader_library.html + * + * This process will use a Sobell convolution filter to determine contrast across each pixel. + * pixels that have a contrast greater than a given threshold value will be treated + * as an edge pixel and turned black. + * + * Author: John Marquiss + * Email: txg1152@gmail.com + * + * This work by John Marquiss is licensed under a + * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. + * http://creativecommons.org/licenses/by-nc-sa/3.0/ + */ + +sampler ColorMapSampler : register(s0); + +/* Screen size (really texture size) is used to + * scale the outline line thickness nicely around the + * image + */ +float2 ScreenSize; + +/* Outline line thickness scale + */ +float Thickness = 1.0f; + +/* Edge detection threshold + * Contrast values over the threshold are considered + * edges. That means smaller values for the threshold make the + * image more "edgy" higher values less so. + */ +float Threshold = 0.0f; + +/* getGray + * a simple helper function to return a grey scale + * value for a given pixel + */ +float getGray(float4 c) +{ + /* The closer a color is to a pure gray + * value the closer its dot product and gray + * will be to 0. + */ + //return float4(1,1,1,1); + // if (c.a >0) + // { + // return float4(0,0,0,1); + // } + + // return float4(1,1,1,1); + return(dot(c.rgb,((0.33333).xxx))); +} + +struct VertexShaderOutput +{ + float2 Tex : TEXCOORD0; +}; + +/* Shade each pixel turning edge pixels black + */ +float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0 +{ + // Get the source pixel color + float4 Color = tex2D(ColorMapSampler, input.Tex); + if (Color.a==0) + { + Color.rgba=0.8; + } + + /* ox is the X offset vector where the offest is based + * on the scaled edge thickness + */ + float2 ox = float2(Thickness/ScreenSize.x,0.0); + + /* oy is the Y offset vector where the offest is based + * on the scaled edge thickness + */ + float2 oy = float2(0.0,Thickness/ScreenSize.y); + + /* our current xy (uv) texture coordinate + */ + float2 uv = input.Tex.xy; + + /* Our kernel filter is a 3x3 matrix in order to process + * it we need to get the 8 neighbor pixles (top left, top, top right, + * left, right, bottom left, bottom, and bottom right) and the + * current pixel. For each of these pixels we then need to get + * its grey scale value using getGray. We will store the gray scale + * values in a 3x3 matrix g: + * g00 g01 g02 + * g10 g11 g12 + * g20 g21 g22 + */ + + /* First the bottom row pixels + * bottom left uv - oy - ox, bottom uv - oy and + * bottom right uv - oy + ox + */ + float2 PP = uv - oy; + float4 CC = tex2D(ColorMapSampler, PP-ox); float g00 = getGray(CC); + CC = tex2D(ColorMapSampler, PP); float g01 = getGray(CC); + CC = tex2D(ColorMapSampler, PP+ox); float g02 = getGray(CC); + + /* Next get the middle row pixels + * left uv - ox, current uv and right uv + ox + */ + PP = uv; + CC = tex2D(ColorMapSampler, PP-ox); float g10 = getGray(CC); + CC = tex2D(ColorMapSampler, PP); float g11 = getGray(CC); + CC = tex2D(ColorMapSampler, PP+ox); float g12 = getGray(CC); + + /* Finally get the top row pixels + * top left uv + oy - ox, top uv + oy and + * top right uv + oy + ox + */ + PP = uv + oy; + CC = tex2D(ColorMapSampler, PP-ox); float g20 = getGray(CC); + CC = tex2D(ColorMapSampler, PP); float g21 = getGray(CC); + CC = tex2D(ColorMapSampler, PP+ox); float g22 = getGray(CC); + + /* We will use a Sobell convolution filter + * -1 -2 -1 + * 0 0 0 + * 1 2 1 + */ + float K00 = -1; + float K01 = -2; + float K02 = -1; + float K10 = 0; + float K11 = 0; + float K12 = 0; + float K20 = 1; + float K21 = 2; + float K22 = 1; + + /* Calculate sx as the summation + * of g.ij * K.ij + * This will give us horizantal edge detection + */ + float sx = 0; + sx += g00 * K00; + sx += g01 * K01; + sx += g02 * K02; + sx += g10 * K10; + sx += g11 * K11; + sx += g12 * K12; + sx += g20 * K20; + sx += g21 * K21; + sx += g22 * K22; + + /* Calculate sy as the summation + * of g.ij * K.ji + * K.ji effectively rotates the kernel filter + * this will give us vertical edge detection + */ + float sy = 0; + sy += g00 * K00; + sy += g01 * K10; + sy += g02 * K20; + sy += g10 * K01; + sy += g11 * K11; + sy += g12 * K21; + sy += g20 * K02; + sy += g21 * K12; + sy += g22 * K22; + + /* Now merge the results of the horizantal + * and veritcal edge detection calculations + * together by calculating the distance of the + * vector they form. + */ + float contrast = sqrt(sx*sx + sy*sy); + + /* assume no edge (result = 1) + */ + float result = 1; + + /* If the length of s.xy has a value + * greater than the threshold then the color change (contrast) + * accoss that pixel is enough that we want to consider + * it an edge. Set result to 0 to black out that pixel. + */ + if (contrast > Threshold) + { + result = 0; + } + + /* finally return the original color multiplied + * by the result. For with contrast values over the + * threshold result will be 0 giving us a black edge. + * Make sure we do not clear out the alpha value though + * otherwise our edges will disappear if we use alpha + * blending. + */ + return Color*float4(contrast.xxx,1); +} + +technique PostOutline +{ + pass Pass0 + { + PixelShader = compile ps_2_0 PixelShaderFunction(); + } +} diff --git a/Sledgemapper/Settings.cs b/Sledgemapper/Settings.cs index 808fd10..25b39f6 100644 --- a/Sledgemapper/Settings.cs +++ b/Sledgemapper/Settings.cs @@ -19,7 +19,7 @@ namespace Sledgemapper GridColor = Color.Black; NoteColor = Color.DarkRed; OverlayTintColor = new Color(24, 118, 157); -TileDeleteDivider=8; +TileDeleteDivider=14; try { MachineName = Environment.MachineName; diff --git a/Sledgemapper/Sledgemapper.cs b/Sledgemapper/Sledgemapper.cs index 6d47a63..0dceb8f 100644 --- a/Sledgemapper/Sledgemapper.cs +++ b/Sledgemapper/Sledgemapper.cs @@ -95,13 +95,19 @@ namespace Sledgemapper base.Initialize(); } + private void ResetRenderTarget() + { + rendertarget = new RenderTarget2D(GraphicsDevice, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height, false, SurfaceFormat.Color, DepthFormat.None, 0, RenderTargetUsage.DiscardContents); + + } + private void OnClientSizeChanged(object sender, EventArgs e) { rendertarget?.Dispose(); try { - - rendertarget = new RenderTarget2D(GraphicsDevice, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height, true, SurfaceFormat.Alpha8, DepthFormat.Depth16, 0, RenderTargetUsage.DiscardContents); +ResetRenderTarget(); + // rendertarget = new RenderTarget2D(GraphicsDevice, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height, true, SurfaceFormat.Alpha8, DepthFormat.Depth16, 0, RenderTargetUsage.DiscardContents); //rendertarget = new RenderTarget2D(GraphicsDevice, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height); } @@ -135,8 +141,10 @@ namespace Sledgemapper { _spriteBatch = new SpriteBatch(GraphicsDevice); outlineShader = Content.Load("shaders/OutlineShader"); + outlineShader2 = Content.Load("shaders/OutlineShader2"); MyraEnvironment.Game = this; - rendertarget = new RenderTarget2D(GraphicsDevice, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height, true, SurfaceFormat.Alpha8, DepthFormat.Depth16, 0, RenderTargetUsage.DiscardContents); + ResetRenderTarget(); + // rendertarget = new RenderTarget2D(GraphicsDevice, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height, true, SurfaceFormat.Alpha8, DepthFormat.Depth16, 0, RenderTargetUsage.DiscardContents); _mainWidget = new MainWidget(); @@ -575,6 +583,8 @@ namespace Sledgemapper _spriteBatch.Begin(depthStencilState: DepthStencilState.None, transformMatrix: Matrix.CreateTranslation(_viewportCenter), blendState: BlendState.Opaque, + //rasterizerState:RasterizerState.CullClockwise, + samplerState:SamplerState.PointClamp, sortMode: SpriteSortMode.Deferred); @@ -607,17 +617,17 @@ namespace Sledgemapper GraphicsDevice.SetRenderTarget(null); - Vector2 texelSize = new Vector2((float)rendertarget.Width, (float)rendertarget.Height); + Vector2 texelSize = new Vector2((float)rendertarget.Width, (float)rendertarget.Height); outlineShader.Parameters["ImageSize"].SetValue(texelSize); - //outlineShader.Parameters["BorderSize"].SetValue((int)(_state.TileSize / 100f *10f)); + outlineShader.Parameters["BorderSize"].SetValue((int)(_state.TileSize / 100f *10f)); outlineShader.Parameters["R"].SetValue(_settings.OverlayTintColor.R / 255.0f); outlineShader.Parameters["G"].SetValue(_settings.OverlayTintColor.G / 255.0f); outlineShader.Parameters["B"].SetValue(_settings.OverlayTintColor.B / 255.0f); - +// outlineShader2.Parameters["ScreenSize"].SetValue(texelSize); _spriteBatch.Begin( effect: outlineShader, - blendState: BlendState.AlphaBlend, + blendState: BlendState.NonPremultiplied, sortMode: SpriteSortMode.Deferred); GraphicsDevice.Clear(_settings.BackgroundColor); _spriteBatch.Draw(rendertarget, Vector2.Zero, null, Color.White); @@ -1302,8 +1312,9 @@ namespace Sledgemapper } } Effect outlineShader; // Outline shader effect + private Effect outlineShader2; - private void DrawDelete(Room tile) + private void DrawDelete(Room tile) { var posX = tile.Start.X * _state.TileSize; var posY = tile.Start.Y * _state.TileSize;