{"id":2885,"date":"2024-01-21T06:00:00","date_gmt":"2024-01-21T14:00:00","guid":{"rendered":"https:\/\/rose.dev\/blog\/?p=2885"},"modified":"2024-02-07T02:37:39","modified_gmt":"2024-02-07T10:37:39","slug":"unity-shaders-intro-part-1-shader-graph-creating-player-highlight-obscuring-area-effect-mask-shader","status":"publish","type":"post","link":"https:\/\/rose.dev\/blog\/2024\/01\/21\/unity-shaders-intro-part-1-shader-graph-creating-player-highlight-obscuring-area-effect-mask-shader\/","title":{"rendered":"Unity Shaders Intro Part 1: Shader Graph | Creating Player Highlight \/ Obscuring Area Effect Mask Shader"},"content":{"rendered":"\n<p>Shaders can be a useful way to enhance the visual presentation of your project through subtle or otherwise effects. Beyond code, the engine provides a built in visual scripting tool to create shaders from version 2019 onwards. <\/p>\n\n\n\n<p>We will create an effect that allows us to highlight the player and obscure the rest of our stage. With scripting, we can also modify our exposed shader properties to adjust the intensity of the transparency effect, and transition to having no highlight. Examples will be shown later in the post.<\/p>\n\n\n\n<figure class=\"wp-block-video\"><video controls loop preload=\"auto\" src=\"https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/followmouse.mp4\" playsinline><\/video><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Prerequisites<\/h2>\n\n\n\n<p>Ensure you have the Shader Graph package installed in your version of Unity. I am using <em>2022.3.17f<\/em> for this post. <\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-style-default\"><img loading=\"lazy\" decoding=\"async\" width=\"573\" height=\"709\" sizes=\"auto, (max-width: 573px) 100vw, 573px\" src=\"https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/shadergraph.png\" alt=\"\" class=\"wp-image-2886\" style=\"aspect-ratio:1;object-fit:cover\" srcset=\"https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/shadergraph.png 573w, https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/shadergraph-242x300.png 242w\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Creating the Shader<\/h2>\n\n\n\n<p>Right click in your Unity Project and do Create &gt; Shader Graph &gt; Blank Shader Graph<\/p>\n\n\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;69ddf8fa9d354&quot;}\" data-wp-interactive=\"core\/image\" class=\"wp-block-image size-full wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"1007\" height=\"697\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" sizes=\"auto, (max-width: 1007px) 100vw, 1007px\" src=\"https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/shader-graph-right-click-menu.png\" alt=\"\" class=\"wp-image-2893\" srcset=\"https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/shader-graph-right-click-menu.png 1007w, https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/shader-graph-right-click-menu-300x208.png 300w, https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/shader-graph-right-click-menu-768x532.png 768w\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\taria-label=\"Enlarge\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on-async--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.imageButtonRight\"\n\t\t\tdata-wp-style--top=\"state.imageButtonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure>\n\n\n\n<p>Now that we have a Shader Graph file, simply open the editor by <strong>double clicking<\/strong> it.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"857\" height=\"518\" sizes=\"auto, (max-width: 857px) 100vw, 857px\" src=\"https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/shader.png\" alt=\"\" class=\"wp-image-2895\" srcset=\"https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/shader.png 857w, https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/shader-300x181.png 300w, https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/shader-768x464.png 768w\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Let&#8217;s add some basic shader properties first. Navigate to the Graph Settings and add <code>Built In<\/code> as a target. We want the ability to control the transparency of our pixels, so also add the Alpha property to our fragment.<\/p>\n\n\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;69ddf8fa9ea76&quot;}\" data-wp-interactive=\"core\/image\" class=\"wp-block-image size-full wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"934\" height=\"518\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" sizes=\"auto, (max-width: 934px) 100vw, 934px\" src=\"https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/built-in-properties.png\" alt=\"\" class=\"wp-image-2899\" srcset=\"https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/built-in-properties.png 934w, https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/built-in-properties-300x166.png 300w, https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/built-in-properties-768x426.png 768w\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\taria-label=\"Enlarge\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on-async--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.imageButtonRight\"\n\t\t\tdata-wp-style--top=\"state.imageButtonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure>\n\n\n\n<p>In order to properly utilize the Alpha property, we will need to edit the Built In settings <code>Surface Type<\/code> to <code>Transparent<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Shader Inputs<\/h2>\n\n\n\n<p>The first thing to consider is the Player&#8217;s world position. Since we want the highlight effect to follow the player, we&#8217;ll need some sort of input into the shader.<\/p>\n\n\n\n<p>In the Shader Graph editor, ensure the &#8216;Blackboard&#8217; option is checked and visible, then click the plus button on the left side of the editor to create an input variable. Make it a Vector3 category. The &#8216;Name&#8217; is for visual purposes, and the &#8216;Reference&#8217; field will allow scripts access to the property. Give that some value like &#8220;_PlayerPosition&#8221; and drag it into the stage.<\/p>\n\n\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;69ddf8fa9f31f&quot;}\" data-wp-interactive=\"core\/image\" class=\"wp-block-image size-full wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"870\" height=\"489\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" sizes=\"auto, (max-width: 870px) 100vw, 870px\" src=\"https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/PlayerPos-Property.png\" alt=\"\" class=\"wp-image-2901\" srcset=\"https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/PlayerPos-Property.png 870w, https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/PlayerPos-Property-300x169.png 300w, https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/PlayerPos-Property-768x432.png 768w\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\taria-label=\"Enlarge\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on-async--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.imageButtonRight\"\n\t\t\tdata-wp-style--top=\"state.imageButtonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure>\n\n\n\n<p>Since that&#8217;s simply a Vector, we need to translate that into something usable for our shader. We need to subtract the input player position from our world position so we can get the individual area to affect.<\/p>\n\n\n\n<p>Right click, and create a <code>Position <\/code>and <code>Subtract <\/code>node.<\/p>\n\n\n\n<p>Connect the player position and world position node to the subtract node. At this point your graph should look similar to below.<\/p>\n\n\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;69ddf8fa9fcbf&quot;}\" data-wp-interactive=\"core\/image\" class=\"wp-block-image size-full wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"989\" height=\"490\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" sizes=\"auto, (max-width: 989px) 100vw, 989px\" src=\"https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/playerposworldsubtract.png\" alt=\"\" class=\"wp-image-2903\" srcset=\"https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/playerposworldsubtract.png 989w, https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/playerposworldsubtract-300x149.png 300w, https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/playerposworldsubtract-768x381.png 768w\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\taria-label=\"Enlarge\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on-async--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.imageButtonRight\"\n\t\t\tdata-wp-style--top=\"state.imageButtonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure>\n\n\n\n<p>Next we will need a <code>Length<\/code> node to translate our position into a distance. <\/p>\n\n\n\n<p>At this point, if we connect the output of our length to our Base Color on our Fragment, we can see a strange divine light.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"482\" height=\"482\" sizes=\"auto, (max-width: 482px) 100vw, 482px\" src=\"https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/shaderprogress.png\" alt=\"\" class=\"wp-image-2906\" style=\"object-fit:cover\" srcset=\"https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/shaderprogress.png 482w, https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/shaderprogress-300x300.png 300w, https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/shaderprogress-150x150.png 150w\" \/><\/figure>\n\n\n\n<p>How can we control the actual effect size?<\/p>\n\n\n\n<p>We need a multiply node and some additional input here to control the highlight amount.<\/p>\n\n\n\n<p>Let&#8217;s create a new <code>Multiply<\/code> node, and a <code>Float <\/code>input.<\/p>\n\n\n\n<p>Name the Float input something like _EffectStrength, and feed the length output into the new multiply node. <\/p>\n\n\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;69ddf8faa08fb&quot;}\" data-wp-interactive=\"core\/image\" class=\"wp-block-image size-full wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"981\" height=\"506\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" sizes=\"auto, (max-width: 981px) 100vw, 981px\" src=\"https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/shaderwipeffectstrengthmult.png\" alt=\"\" class=\"wp-image-2910\" srcset=\"https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/shaderwipeffectstrengthmult.png 981w, https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/shaderwipeffectstrengthmult-300x155.png 300w, https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/shaderwipeffectstrengthmult-768x396.png 768w\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\taria-label=\"Enlarge\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on-async--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.imageButtonRight\"\n\t\t\tdata-wp-style--top=\"state.imageButtonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure>\n\n\n\n<p>You should have something similar to this, and the shader will go black again. This is simply because we haven&#8217;t given it an effect strength yet. <\/p>\n\n\n\n<p>Save this Shader Graph asset and assign it to an object in our scene if you haven&#8217;t already.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"445\" height=\"334\" sizes=\"auto, (max-width: 445px) 100vw, 445px\" src=\"https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/assignmaterial-edited.png\" alt=\"\" class=\"wp-image-2913\" srcset=\"https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/assignmaterial-edited.png 445w, https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/assignmaterial-edited-300x225.png 300w\" \/><\/figure>\n\n\n\n<p>Notice the warning. This refers to the fact that we aren&#8217;t rendering a sprite. This is correct, and can be safely ignored.<\/p>\n\n\n\n<p>Assuming a reference to the sprite renderer component, we can then use the material set property functions to pass along our game values in an Update function or whenever needed.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"csharp\" class=\"language-csharp\">RevealBG.material.SetVector(\"_PlayerPosition\", position);\nRevealBG.material.SetFloat(\"_EffectStrength\", highlightingPlayerAmount);\n<\/code><\/pre>\n\n\n\n<p>Set the effect to something visible like 1 for now. We can also set a default through the Shader Graph editor.<\/p>\n\n\n\n<p>All of this grey is pretty boring, so let&#8217;s add some color. The ability to edit our colors through scripting is pretty important, so let&#8217;s create two new <code>Color <\/code>variables. <\/p>\n\n\n\n<p>The shader will lerp between these two colors for the highlight effect. We could use only one color considering our goal of mixing the effect with transparency, but the additional color gives more control over the effect appearance. <\/p>\n\n\n\n<p>Create a <code>Lerp <\/code>node. Connect the output of the previous multiply node to the lerp T input, and the two new colors to the A and B inputs, respectively.<\/p>\n\n\n\n<p>I set BGColor to blue, and PlayerRevealColor to red through the graph inspector to clearly show the shader effect.<\/p>\n\n\n\n<p>If all goes well, you should have a circular gradient in the input colors you&#8217;ve specified.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"533\" height=\"295\" sizes=\"auto, (max-width: 533px) 100vw, 533px\" src=\"https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/shaderhighlighteffectlerp.png\" alt=\"\" class=\"wp-image-2923\" srcset=\"https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/shaderhighlighteffectlerp.png 533w, https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/shaderhighlighteffectlerp-300x166.png 300w\" \/><\/figure>\n\n\n\n<p>And something like this in your Shader Graph.<\/p>\n\n\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;69ddf8faa19ab&quot;}\" data-wp-interactive=\"core\/image\" class=\"wp-block-image size-full wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"1357\" height=\"536\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" sizes=\"auto, (max-width: 1357px) 100vw, 1357px\" src=\"https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/lerpcolorsshadergraph.png\" alt=\"\" class=\"wp-image-2922\" srcset=\"https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/lerpcolorsshadergraph.png 1357w, https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/lerpcolorsshadergraph-300x118.png 300w, https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/lerpcolorsshadergraph-1024x404.png 1024w, https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/lerpcolorsshadergraph-768x303.png 768w\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\taria-label=\"Enlarge\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on-async--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.imageButtonRight\"\n\t\t\tdata-wp-style--top=\"state.imageButtonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure>\n\n\n\n<p>That gradient isn&#8217;t really the look we want. Instead, we want a tight circular highlight around the player position.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"245\" height=\"245\" sizes=\"auto, (max-width: 245px) 100vw, 245px\" src=\"https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/highlight.png\" alt=\"\" class=\"wp-image-2931\" style=\"object-fit:cover\" srcset=\"https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/highlight.png 245w, https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/highlight-150x150.png 150w\" \/><\/figure>\n\n\n\n<p>To achieve this, we can add a <code>Step <\/code>node. <\/p>\n\n\n\n<p>Insert it between the multiply and lerp node at the end, and it will produce a gated circular output.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"537\" height=\"303\" sizes=\"auto, (max-width: 537px) 100vw, 537px\" src=\"https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/shader1p.png\" alt=\"\" class=\"wp-image-2933\" srcset=\"https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/shader1p.png 537w, https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/shader1p-300x169.png 300w\" \/><\/figure>\n\n\n\n<p>Adjusting the EffectStrength should make the circle appear larger. Try values from 0 -&gt; 1. Above 1 will make the highlight smaller.<\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:50%\"><div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"264\" height=\"265\" sizes=\"auto, (max-width: 264px) 100vw, 264px\" src=\"https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/shader0p5.png\" alt=\"0.5 effect setting\" class=\"wp-image-2934\" srcset=\"https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/shader0p5.png 264w, https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/shader0p5-150x150.png 150w\" \/><figcaption class=\"wp-element-caption\">EffectStrength at 0.5<\/figcaption><\/figure><\/div><\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:50%\"><div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"264\" height=\"264\" sizes=\"auto, (max-width: 264px) 100vw, 264px\" src=\"https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/shader0.png\" alt=\"\" class=\"wp-image-2938\" srcset=\"https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/shader0.png 264w, https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/shader0-150x150.png 150w\" \/><figcaption class=\"wp-element-caption\">EffectStrength at 0<\/figcaption><\/figure><\/div><\/div>\n<\/div>\n\n\n\n<p>Now we just need to connect our transparency logic.<\/p>\n\n\n\n<p>Add another <code>Multiply <\/code>node that we will use for the <code>Alpha <\/code>property on the Fragment. The input should be our previous multiply node&#8217;s output, before the <code>Step <\/code>node. This allows control over the strength of the highlight fade. I went with 1.5.<\/p>\n\n\n\n<p>You&#8217;re pretty much finished!<\/p>\n\n\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;69ddf8faa4626&quot;}\" data-wp-interactive=\"core\/image\" class=\"wp-block-image size-full wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"1461\" height=\"718\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" sizes=\"auto, (max-width: 1461px) 100vw, 1461px\" src=\"https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/multaddstage.png\" alt=\"\" class=\"wp-image-2942\" srcset=\"https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/multaddstage.png 1461w, https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/multaddstage-300x147.png 300w, https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/multaddstage-1024x503.png 1024w, https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/multaddstage-768x377.png 768w\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\taria-label=\"Enlarge\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on-async--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.imageButtonRight\"\n\t\t\tdata-wp-style--top=\"state.imageButtonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>We can adjust the colors to do screen wave effects like this that could be enhanced with particle effects.<\/p>\n\n\n\n<figure class=\"wp-block-video\"><video controls loop preload=\"auto\" src=\"https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/basicscreenwave.mp4\" playsinline><\/video><\/figure>\n\n\n\n<p>Or as a game over effect where you hide the rest of the stage and highlight the player. I added a purple background sprite behind the player to show the masking effect.<\/p>\n\n\n\n<figure class=\"wp-block-video\"><video controls loop src=\"https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/gameoversimplepurple.mp4\" playsinline><\/video><\/figure>\n\n\n\n<p>Force fields, lights for dark mazes etc all follow a similar concept. <\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p><a href=\"https:\/\/github.com\/gen3vra\/slashdot\" target=\"_blank\" rel=\"noreferrer noopener\">Source<\/a><\/p>\n<hr>\r\nIt helps me if you share this post\r\n<br\/>\r\n<br\/>\r\nPublished 2024-01-21 06:00:00 ","protected":false},"excerpt":{"rendered":"<p>Learn how to create a basic Shader Graph shader in Unity2D! 2D highlighting, obscuring shader, masking shader, 2d overlay effect.<\/p>\n","protected":false},"author":1,"featured_media":2994,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"footnotes":""},"categories":[922,832,833],"tags":[1193,1210,1207,858,1206,1214,1208,1130,1211,1209,1205,1215,1204,1212,3,1202],"class_list":["post-2885","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-release","category-software","category-technology","tag-2d","tag-area-of-effect","tag-development","tag-game","tag-graph","tag-hide-area","tag-highlight","tag-lighting","tag-masking","tag-obscure","tag-shader","tag-shader-graph","tag-shaders","tag-transparent","tag-unity","tag-unity2d"],"jetpack_featured_media_url":"https:\/\/rose.dev\/blog\/wp-content\/uploads\/2024\/01\/highlightshaderbanner.png","_links":{"self":[{"href":"https:\/\/rose.dev\/blog\/wp-json\/wp\/v2\/posts\/2885","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/rose.dev\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rose.dev\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/rose.dev\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/rose.dev\/blog\/wp-json\/wp\/v2\/comments?post=2885"}],"version-history":[{"count":108,"href":"https:\/\/rose.dev\/blog\/wp-json\/wp\/v2\/posts\/2885\/revisions"}],"predecessor-version":[{"id":3296,"href":"https:\/\/rose.dev\/blog\/wp-json\/wp\/v2\/posts\/2885\/revisions\/3296"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/rose.dev\/blog\/wp-json\/wp\/v2\/media\/2994"}],"wp:attachment":[{"href":"https:\/\/rose.dev\/blog\/wp-json\/wp\/v2\/media?parent=2885"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rose.dev\/blog\/wp-json\/wp\/v2\/categories?post=2885"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rose.dev\/blog\/wp-json\/wp\/v2\/tags?post=2885"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}