{"id":91922,"date":"2021-07-20T19:27:21","date_gmt":"2021-07-20T19:27:21","guid":{"rendered":"https:\/\/www.red-gate.com\/simple-talk\/?p=91922"},"modified":"2021-07-29T19:44:00","modified_gmt":"2021-07-29T19:44:00","slug":"post-processing-effects-unity","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/development\/dotnet-development\/post-processing-effects-unity\/","title":{"rendered":"Using post-processing effects in Unity"},"content":{"rendered":"<p>You may have heard the term \u201cpost-processing\u201d before, but what does that mean? In the context of images and video, it is the application of various visual effects to improve the visual elements of an image. This usually includes effects like giving lights a soft glow or tinting the image a certain color. Typically, when people think of post-processing, they think of it as a static item or something that cannot be changed once applied. In the video game space, this is rarely the case. While an app can certainly have its post-processing effects set in advance, there&#8217;s also the option to change them during runtime using C# code. This allows the developer to achieve effects such as applying a vignette under certain conditions or changing the type of film grain used. In this article, I&#8217;ll show you how to use post-processing effects in Unity.<\/p>\n<p>To help you learn how to use this, a project will be created that lets the user change the app&#8217;s post-processing properties by manipulating various user interface (UI) elements. Before that, a brief description will be given of the post-processing effects used to explain what is being demonstrated. Then, the project will be created with a UI set up before getting into the code that will make the project function. By the end, you will be able to use the UI to adjust the properties of several post-processing effects, seeing the changes in real-time as you do so.<\/p>\n<h2>Post-processing effects<\/h2>\n<p>Before diving too deep into the project, it&#8217;s helpful to understand the various effects. While the project will focus on only a single property per effect, many post-processing effects have multiple properties that can all be changed in code. Here is a list of all the post-processing effects being used in this project and what they do.<\/p>\n<p><strong>Bloom: <\/strong>The bloom effect is what gives bright objects a soft glow, making your brighter areas stand out as a result. This is most clearly visible with light sources and is a popular effect for making an environment appear brighter and more lively.<\/p>\n<p><strong>Chromatic Aberration: <\/strong>Chromatic aberration disperses colors along the dark and light areas of an image. This may remind you of wearing the 3D glasses with the red and blue lenses.<\/p>\n<p><strong>Vignette: <\/strong>The vignette property creates a dark edge that goes all around the screen. The intensity of this effect changes how much of the edges darken.<\/p>\n<p><strong>Film Grain: <\/strong>Almost exactly as the name of the effect implies, this places an old-school-styled film grain over the image. You can adjust the thickness and intensity of the grains to get the exact look you&#8217;re going for.<\/p>\n<p><strong>Lens Distortion: <\/strong>This effect simulates real-world distortion caused by an actual camera lens. Depending on the values given, you can achieve a wider field of view. This can also be handy for creating a scene from the perspective of a fish.<\/p>\n<p><strong>Color Adjustment: <\/strong>This effect will be separated into three sliders that represent the red, green, and blue values. Changing any of these will tint the image color based on the values given.<\/p>\n<h2>Setting up the Unity project<\/h2>\n<p>Now that you\u2019re familiar with some post-processing effects, it&#8217;s time to create a project that puts them to use. Start by creating a new project within the Unity Hub.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-91923\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/07\/word-image-2.jpeg\" alt=\"Image of unity projects\" width=\"964\" height=\"561\" \/><\/p>\n<p><strong>Figure 1: Creating a new project.<\/strong><\/p>\n<p>The <em>Universal Render Pipeline <\/em>template will be used this time because it already has a scene created and everything needed for implementing post-processing effects. Give the project a name and set a location for it, then create the project.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-91924\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/07\/word-image-3.jpeg\" alt=\"Universal render pipeline\" width=\"894\" height=\"452\" \/><\/p>\n<p><strong>Figure 2: Using the <em>Universal Render Pipeline <\/em>template<\/strong><\/p>\n<p>As mentioned before, this project template comes with a post-processing volume already created for you. A post-processing volume is an object that determines the area in which post-processing effects are applied. In this project&#8217;s case, the volume has already been set to <em>Global<\/em>, meaning it will affect the entire scene regardless of your current location. Select the <em>Post-process Volume<\/em> in the <em>Hierarchy<\/em>, and look at the <em>Inspector<\/em>. There&#8217;s a button for adding an override, which means you can add to the list of post-processing effects that you control and not leave it up to the app. It already has the bloom and vignette effects added, so use this button to add <em>Chromatic<\/em> <em>Aberration<\/em>, <em>Film<\/em> <em>Grain<\/em>, <em>Lens<\/em> <em>Distortion<\/em>, and <em>Color Adjustments<\/em>. Click <em>Post-processing<\/em> to see the list.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-91925\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/07\/word-image-4.jpeg\" alt=\"Adding post-processing overrides\" width=\"591\" height=\"365\" \/><\/p>\n<p><strong>Figure 3: Adding post-processing overrides.<\/strong><\/p>\n<p>It&#8217;s not enough that you add these effects to the volume, however. You also have to enable the properties you want to change. Expand each effect using the arrow icons, then enable the following:<\/p>\n<ul>\n<li>Bloom \u2013 Intensity<\/li>\n<li>Vignette \u2013 Rounded<\/li>\n<li>Chromatic Aberration \u2013 Intensity<\/li>\n<li>Film Grain \u2013 Type and Intensity<\/li>\n<li>Lens Distortion \u2013 Intensity<\/li>\n<li>Color Adjustments \u2013 Color Filter<\/li>\n<\/ul>\n<p>If, after project completion, you decide you want to modify other values in code, make sure the corresponding properties are enabled first. Also, go ahead and set the intensity for <em>Bloom<\/em> to zero, and the intensity for <em>Film Grain<\/em> to 1.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-91926\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/07\/word-image-5.jpeg\" alt=\"All default values for the post-processing volume.\" width=\"591\" height=\"788\" \/><\/p>\n<p><strong>Figure 4: All default values for the post-processing volume<\/strong><\/p>\n<p>Now comes the process of creating the user interface that will allow manipulating the post-processing values in real-time. This has a lot of parts to it, so one object&#8217;s creation will be described in detail, with the remaining objects listed out in a table complete with the object type and its coordinates.<\/p>\n<p>For this example object, create a slider for controlling the post-processing volume\u2019s bloom value. First, in the <em>Hierarchy <\/em>window, click the <em>Create <\/em>button and choose <em>UI-&gt;Slider<\/em>. Name the object <em>BloomSlider<\/em>.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-91927\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/07\/word-image-6.jpeg\" alt=\"create a new slider\" width=\"427\" height=\"451\" \/><\/p>\n<p><strong>Figure 5: Creating a new slider.<\/strong><\/p>\n<p>If it\u2019s not already set, change the view to 2D to more easily view and edit the UI. Then zoom out with your mouse wheel.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-91928\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/07\/word-image-7.jpeg\" alt=\"change to 2d view\" width=\"248\" height=\"100\" \/><\/p>\n<p><strong>Figure 6: Changing to 2D view<\/strong><\/p>\n<p>Make sure the <em>BloomSlider <\/em>object is selected, then navigate to the <em>Inspector. <\/em>There will be a <em>Rect Transform <\/em>component listed, which controls the object\u2019s location and size. Change the values seen in figure 7. Note: these values may differ based on the size of your <em>Game <\/em>window and screen resolution.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-91929\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/07\/word-image-8.jpeg\" alt=\"setting Rect Transform values of bloomslider\" width=\"593\" height=\"254\" \/><\/p>\n<p><strong>Figure 7: Setting <em>Rect Transform <\/em>values.<\/strong><\/p>\n<p>All the objects listed in Table 1 follow the same creation process listed above. The <em>Text, Toggle, Dropdown, <\/em>and <em>Button <\/em>objects are all found in the same <em>UI <\/em>menu when creating an object.<\/p>\n<table>\n<tbody>\n<tr>\n<td>\n<p><strong>Object Name<\/strong><\/p>\n<\/td>\n<td>\n<p><strong>Object Type<\/strong><\/p>\n<\/td>\n<td>\n<p><strong>Pos X<\/strong><\/p>\n<\/td>\n<td>\n<p><strong>Pos Y<\/strong><\/p>\n<\/td>\n<td>\n<p><strong>Width<\/strong><\/p>\n<\/td>\n<td>\n<p><strong>Height<\/strong><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>BloomText<\/p>\n<\/td>\n<td>\n<p>Text<\/p>\n<\/td>\n<td>\n<p>750<\/p>\n<\/td>\n<td>\n<p>310<\/p>\n<\/td>\n<td>\n<p>160<\/p>\n<\/td>\n<td>\n<p>30<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>BloomSlider<\/p>\n<\/td>\n<td>\n<p>Slider<\/p>\n<\/td>\n<td>\n<p>750<\/p>\n<\/td>\n<td>\n<p>280<\/p>\n<\/td>\n<td>\n<p>160<\/p>\n<\/td>\n<td>\n<p>20<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>ChromaticAberationText<\/p>\n<\/td>\n<td>\n<p>Text<\/p>\n<\/td>\n<td>\n<p>750<\/p>\n<\/td>\n<td>\n<p>240<\/p>\n<\/td>\n<td>\n<p>160<\/p>\n<\/td>\n<td>\n<p>30<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>ChromaticAberationSlider<\/p>\n<\/td>\n<td>\n<p>Slider<\/p>\n<\/td>\n<td>\n<p>750<\/p>\n<\/td>\n<td>\n<p>210<\/p>\n<\/td>\n<td>\n<p>160<\/p>\n<\/td>\n<td>\n<p>20<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>VignetteText<\/p>\n<\/td>\n<td>\n<p>Text<\/p>\n<\/td>\n<td>\n<p>750<\/p>\n<\/td>\n<td>\n<p>170<\/p>\n<\/td>\n<td>\n<p>160<\/p>\n<\/td>\n<td>\n<p>30<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>VignetteToggle<\/p>\n<\/td>\n<td>\n<p>Toggle<\/p>\n<\/td>\n<td>\n<p>750<\/p>\n<\/td>\n<td>\n<p>130<\/p>\n<\/td>\n<td>\n<p>160<\/p>\n<\/td>\n<td>\n<p>30<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>FilmGrainText<\/p>\n<\/td>\n<td>\n<p>Text<\/p>\n<\/td>\n<td>\n<p>750<\/p>\n<\/td>\n<td>\n<p>80<\/p>\n<\/td>\n<td>\n<p>160<\/p>\n<\/td>\n<td>\n<p>30<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>FilmGrainDropdown<\/p>\n<\/td>\n<td>\n<p>Dropdown<\/p>\n<\/td>\n<td>\n<p>750<\/p>\n<\/td>\n<td>\n<p>50<\/p>\n<\/td>\n<td>\n<p>160<\/p>\n<\/td>\n<td>\n<p>30<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>LensDistortionText<\/p>\n<\/td>\n<td>\n<p>Text<\/p>\n<\/td>\n<td>\n<p>750<\/p>\n<\/td>\n<td>\n<p>10<\/p>\n<\/td>\n<td>\n<p>160<\/p>\n<\/td>\n<td>\n<p>30<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>LensDistortionSlider<\/p>\n<\/td>\n<td>\n<p>Slider<\/p>\n<\/td>\n<td>\n<p>750<\/p>\n<\/td>\n<td>\n<p>-20<\/p>\n<\/td>\n<td>\n<p>160<\/p>\n<\/td>\n<td>\n<p>20<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>ColorAdjustmentText<\/p>\n<\/td>\n<td>\n<p>Text<\/p>\n<\/td>\n<td>\n<p>750<\/p>\n<\/td>\n<td>\n<p>-80<\/p>\n<\/td>\n<td>\n<p>160<\/p>\n<\/td>\n<td>\n<p>30<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>RedText<\/p>\n<\/td>\n<td>\n<p>Text<\/p>\n<\/td>\n<td>\n<p>665<\/p>\n<\/td>\n<td>\n<p>-120<\/p>\n<\/td>\n<td>\n<p>60<\/p>\n<\/td>\n<td>\n<p>30<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>RedSlider<\/p>\n<\/td>\n<td>\n<p>Slider<\/p>\n<\/td>\n<td>\n<p>780<\/p>\n<\/td>\n<td>\n<p>-120<\/p>\n<\/td>\n<td>\n<p>160<\/p>\n<\/td>\n<td>\n<p>20<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>GreenText<\/p>\n<\/td>\n<td>\n<p>Text<\/p>\n<\/td>\n<td>\n<p>665<\/p>\n<\/td>\n<td>\n<p>-150<\/p>\n<\/td>\n<td>\n<p>60<\/p>\n<\/td>\n<td>\n<p>30<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>GreenSlider<\/p>\n<\/td>\n<td>\n<p>Slider<\/p>\n<\/td>\n<td>\n<p>780<\/p>\n<\/td>\n<td>\n<p>-150<\/p>\n<\/td>\n<td>\n<p>160<\/p>\n<\/td>\n<td>\n<p>20<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>BlueText<\/p>\n<\/td>\n<td>\n<p>Text<\/p>\n<\/td>\n<td>\n<p>665<\/p>\n<\/td>\n<td>\n<p>-170<\/p>\n<\/td>\n<td>\n<p>60<\/p>\n<\/td>\n<td>\n<p>30<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>BlueSlider<\/p>\n<\/td>\n<td>\n<p>Slider<\/p>\n<\/td>\n<td>\n<p>780<\/p>\n<\/td>\n<td>\n<p>-170<\/p>\n<\/td>\n<td>\n<p>160<\/p>\n<\/td>\n<td>\n<p>20<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>ResetButton<\/p>\n<\/td>\n<td>\n<p>Button<\/p>\n<\/td>\n<td>\n<p>750<\/p>\n<\/td>\n<td>\n<p>-250<\/p>\n<\/td>\n<td>\n<p>160<\/p>\n<\/td>\n<td>\n<p>30<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><strong>Table 1: All UI objects with positions and size.<\/strong><\/p>\n<p>A few of these objects will need their default properties changed before creating code. You can get through this part faster by selecting all text objects at once and changing any properties to a value all objects will have. Press the Ctrl key before clicking your additional objects to modify all of them at the same time. First, in order to increase the text readability, it is advised you change the colors to black (by default they\u2019re a grey color) and change their font size and style. This is done by selecting the text object, navigating to the <em>Inspector<\/em>, finding the <em>Text <\/em>component, and changing the various properties from there.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-91930\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/07\/word-image-9.jpeg\" alt=\"change font and color properties\" width=\"593\" height=\"546\" \/><\/p>\n<p><strong>Figure 8: Setting the UI text.<\/strong><\/p>\n<p><strong>T<\/strong>he <em>VignetteToggle has a separate child <\/em>object for its text label. To edit it, you\u2019ll need to show VignetteToggle\u2019s child objects by expanding it in the Hierarchy. Find <em>Label<\/em>, and change the text, font style, and color from there.<\/p>\n<p>Next, some sliders, the toggle, and the drop-down menu will need their defaults adjusted. The <em>LensDistortionSlider <\/em>object must have a minimum value of -1, a maximum value of 1, and a default value of 0. Set the maximum value for the BloomSlider object to 10, and the default value for the red, green, and blue sliders to 1. The VignetteToggle only needs one change; make sure the IsOn property is set to false, and the toggle will be ready.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-91931\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/07\/word-image-10.jpeg\" alt=\"LensDistortionSlider default values\" width=\"593\" height=\"277\" \/><\/p>\n<p><strong>Figure 9: <em>LensDistortionSlider <\/em>default values.<\/strong><\/p>\n<p>Finally, you\u2019ll need to add and edit all needed options in the drop-down menu, as seen in figure 10. Use the + button to add as many options as needed. Be sure to also change the names of those options as well to match the list available in the Film Grain override.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-91932\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/07\/word-image-11.jpeg\" alt=\"Full list of options for Film Grain\" width=\"593\" height=\"469\" \/><\/p>\n<p><strong>Figure 10: Full list of options for Film Grain.<\/strong><\/p>\n<p>The UI is finally finished and ready for use. Of course, a script will be needed in order for the UI to do anything. Navigate to the <em>Assets <\/em>window and right-click it. Choose <em>Create-&gt;C# Script<\/em>, then give it a name such as <em>PostProcessRuntimeEffects<\/em>. Double click the new script to open the script in Visual Studio.<\/p>\n<h2>PostProcessRuntimeEffects<\/h2>\n<p>To get started, making sure you\u2019re using the following namespaces:<\/p>\n<pre class=\"lang:c# theme:vs2012\">using UnityEngine;\r\nusing UnityEngine.Rendering;\r\nusing UnityEngine.Rendering.Universal;\r\nusing UnityEngine.UI;<\/pre>\n<p>The critical items are <code>UnityEngine.UI<\/code> and the two <code>Rendering<\/code> namespaces, with the latter helping you change post-processing effects. Next, add the following to the class:<\/p>\n<pre class=\"lang:c# theme:vs2012\">public Volume vol;\r\npublic Slider bloomSlider;\r\npublic Slider chromaticAberrationSlider;\r\npublic Toggle vignetteToggle;\r\npublic Dropdown filmGrainDropdown;\r\npublic Slider lensDistortionSlider;\r\npublic Slider redSlider;\r\npublic Slider greenSlider;\r\npublic Slider blueSlider;\r\nBloom bloom;\r\nChromaticAberration chromaticAberration;\r\nVignette vignette;\r\nFilmGrain filmGrain;\r\nLensDistortion lensDistortion;\r\nColorAdjustments colorAdjustment;<\/pre>\n<p>I\u2019ll break this down a bit. First, <em>vol <\/em>is what will allow you to override the current post-processing effects with that of the user\u2019s selection. From there, you\u2019ll have all the different UI elements that the user can manipulate. Finally, each post-processing class object will be used to store the user\u2019s values and then transfer that data over to the post-processing stack.<\/p>\n<p>The <code>Update<\/code> method that was created automatically can be deleted, as it will not be used here. Moving on to the <code>Start<\/code> method, you\u2019ll need to initially populate those objects with the information currently stored in the post-processing volume. Unity will acquire the volume\u2019s profile, and then more specifically the effect you wish to get and place the found information in the corresponding object that you\u2019ll specify.<\/p>\n<pre class=\"lang:c# theme:vs2012\">vol.profile.TryGet&lt;Bloom&gt;(out bloom);\r\nvol.profile.TryGet&lt;ChromaticAberration&gt;(out chromaticAberration);\r\nvol.profile.TryGet&lt;Vignette&gt;(out vignette);\r\nvol.profile.TryGet&lt;FilmGrain&gt;(out filmGrain);\r\nvol.profile.TryGet&lt;LensDistortion&gt;(out lensDistortion);\r\nvol.profile.TryGet&lt;ColorAdjustments&gt;(out colorAdjustment);<\/pre>\n<p>Once you\u2019ve obtained that information, you\u2019ll need to set up a listener for when the user adjusts any of the values presented to them in the UI. This is done by first calling each UI element\u2019s <code>onValueChanged<\/code> function and then adding the listener from there. For the sake of simplicity, the same method will be used for all UI listeners. The method in question, <code>PostProcessValueChange()<\/code>, will be created momentarily.<\/p>\n<pre class=\"lang:c# theme:vs2012\">bloomSlider.onValueChanged.AddListener(delegate { PostProcessValueChange(); });\r\nchromaticAberrationSlider.onValueChanged.AddListener(delegate { PostProcessValueChange(); });\r\nvignetteToggle.onValueChanged.AddListener(delegate { PostProcessValueChange(); });\r\nfilmGrainDropdown.onValueChanged.AddListener(delegate { PostProcessValueChange(); });\r\nlensDistortionSlider.onValueChanged.AddListener(delegate { PostProcessValueChange(); });\r\nredSlider.onValueChanged.AddListener(delegate { PostProcessValueChange(); });\r\ngreenSlider.onValueChanged.AddListener(delegate { PostProcessValueChange(); });\r\nblueSlider.onValueChanged.AddListener(delegate { PostProcessValueChange(); });<\/pre>\n<p>This concludes the <code>Start<\/code> method, leaving the <code>PostProcessValueChanged<\/code> method mentioned earlier and a method assigned to the <em>ResetButton\u2019s <\/em><code>onClick<\/code> event. Since <code>PostProcessValueChanged<\/code> is where the app takes the user\u2019s input and changes the post-processing settings, this will be a good function to take care of next.<\/p>\n<pre class=\"lang:c# theme:vs2012\">void PostProcessValueChange()\r\n{\r\nbloom.intensity.value = bloomSlider.value;\r\nchromaticAberration.intensity.value = chromaticAberrationSlider.value;\r\nlensDistortion.intensity.value = lensDistortionSlider.value;\r\nvignette.rounded.value = vignetteToggle.isOn;\r\nFilmGrainLookupParameter filmGrainParam = new\r\n   FilmGrainLookupParameter((FilmGrainLookup)filmGrainDropdown.value);\r\n    \tfilmGrain.type.Override((FilmGrainLookup)filmGrainParam);\r\nColor newColor = new Color(redSlider.value, greenSlider.value,\r\n   blueSlider.value);\r\ncolorAdjustment.colorFilter.Override(newColor);\r\n}<\/pre>\n<p>In a nutshell, whenever the user changes any post-processing values, this function is called to update the values within the post-processing stack. For some effects, it\u2019s as simple as calling the parameter in question and setting its value to the user\u2019s selection. However, in this example, two of the effects being changed are a little more involved. Both the film grain and color adjustments require the <code>Override<\/code> function to, as the name implies, override the current value. Before you can do that, though, you must first create objects of the correct type, enter the data they need, and then use that as the argument for the <em>Override <\/em>function. Those with a basic familiarity with Unity development will recognize the <em>Color <\/em>class and how it constructs a new color using red, green, and blue values between zero and one. The more uncommon <code>FilmGrainLookupParameter<\/code> class is used by Unity to identify which film grain type to use from its list. All it needs is the drop-down menu\u2019s value to search with, and then <em>Override <\/em>will handle the rest.<\/p>\n<p>Now, as fun as it will be to move all the sliders around and create some wild effects, at some point a user may want to go back to the default look and start from scratch. This is where the <code>ResetButton<\/code> object comes in. Click this button, and every value will be set to its defaults.<\/p>\n<pre class=\"lang:c# theme:vs2012\">public void ResetSettings()\r\n{\r\n    \tbloomSlider.value = 0;\r\n    \tchromaticAberrationSlider.value = 0;\r\n    \tlensDistortionSlider.value = 0;\r\n    \tvignetteToggle.isOn = false;\r\n    \tfilmGrainDropdown.value = 0;\r\n    \tredSlider.value = 1;\r\n    \tgreenSlider.value = 1;\r\n    \tblueSlider.value = 1;\r\n}<\/pre>\n<p>Notice that you\u2019re just changing the values in each UI element and not the post-processing volume directly. Remember that the <code>PostProcessValueChanged<\/code> method is called anytime a UI element\u2019s value is changed. Not only are you still updating the post-processing volume with new data, but you\u2019re also setting the UI elements back to how they were when the app started.<\/p>\n<p>That takes care of everything on the coding side. All that remains is to tell Unity where all the UI elements and post-processing volume are, finishing the single button setup, and then the project should be ready to run. Save the code, close up Visual Studio, and head back to your Unity project.<\/p>\n<h2>Finishing Touches<\/h2>\n<p>Select the <em>Main Camera <\/em>object and attach the now finished <em>PostProcessingRuntimeEffects <\/em>script to it by clicking and dragging the script into the <em>Inspector <\/em>window. You may want to lock the Inspector window by clicking the padlock icon at the top right.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-91933\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/07\/word-image-12.jpeg\" alt=\"Attaching a script component\" width=\"893\" height=\"900\" \/><\/p>\n<p><strong>Figure 11: Attaching a script component<\/strong><\/p>\n<p>All the empty fields you see on the newly attached script component will need to be filled in. The <em>Vol <\/em>field is for the post-processing volume, so click and drag that object into this field.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-91934\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/07\/word-image-13.jpeg\" alt=\"Adding Post-process Volume to Vol field\" width=\"878\" height=\"708\" \/><\/p>\n<p><strong>Figure 12: Adding <em>Post-process Volume <\/em>to <em>Vol <\/em>field<\/strong><\/p>\n<p>The previous step also applies to all the UI elements. Just click and drag all UI objects into their corresponding fields. The <em>ResetButton <\/em>and the text objects are exceptions, as the script does not work with those directly.<\/p>\n<p>Once all fields are set, select the <em>ResetButton <\/em>object. Remember the <em>ResetSettings <\/em>function in the script? This function will need to be added to the button\u2019s <em>On Click <\/em>event list. To do this, start by clicking the + button in the <em>On Click <\/em>event list. This is what will allow the button to perform your code on click.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-91935\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/07\/graphical-user-interface-application-teams-desc.jpeg\" alt=\"Adding a new On Click event.\" width=\"574\" height=\"172\" \/><\/p>\n<p><strong>Figure 13: Adding a new <em>On Click <\/em>event.<\/strong><\/p>\n<p>Next, drag the <em>Main Camera <\/em>into the object field. This is for pointing the event in the direction of the object with the correct script component attached.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-91936\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/07\/word-image-14.jpeg\" alt=\"Setting the Main Camera as the object to find the script component from\" width=\"590\" height=\"488\" \/><\/p>\n<p><strong>Figure 14: Setting the <em>Main Camera <\/em>as the object to find the script component from<\/strong><\/p>\n<p>Next, click on the <em>No Function <\/em>drop-down. Then choose <em>PostProcessRuntimeEffects-&gt;ResetSettings<\/em>. Once you have that selected, the button will know which function to perform.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-91937\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/07\/word-image-15.jpeg\" alt=\"Setting On Click event to perform ResetSettings\" width=\"652\" height=\"499\" \/><\/p>\n<p><strong>Figure 15: Setting <em>On Click <\/em>event to perform <em>ResetSettings<\/em><\/strong><\/p>\n<p>That\u2019s everything! Now you can run the project using the play button at the top of the editor, then adjust the post-processing volume to your liking. The project template that is being used also comes with basic camera controls while running the app. You can move around the scene using the W, A, S, and D keys and rotate the camera by right-clicking your mouse and dragging. You can also go up or down using the Q and E keys.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-91938\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/07\/word-image-16.jpeg\" alt=\"post processing effects shown in running app\" width=\"1913\" height=\"993\" \/><\/p>\n<p><strong>Figure 16: The app in action.<\/strong><\/p>\n<h2>Post-processing effects in Unity<\/h2>\n<p>Users enjoy having options and being allowed to tweak aspects of an app to their liking. This can extend all the way to the visual elements of the application. By allowing customization, the user can make the app feel like \u201ctheirs\u201d and can aid in creating a unique experience for the user. While the project demonstrated this application in a gaming context, the concept can be applied to various other kinds of apps. The changes allowed don\u2019t have to be for purely visual appeal either. Designed correctly, changing these visual effects can have practical benefits as well, such as making certain colored objects more visible under a different color scheme. Either way, the ability to tweak settings to a user\u2019s liking is something anyone can appreciate.<\/p>\n<p><em>If you liked this article, you might also like\u00a0<a href=\"https:\/\/www.red-gate.com\/simple-talk\/dotnet\/c-programming\/how-to-create-a-settings-menu-in-unity\/\">How to Create a Settings Menu in Unity.<\/a><\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Changing the UI in games makes the games more fun to play. Lance Talbert demonstrates how to use post-processing effects in Unity to change the game.&hellip;<\/p>\n","protected":false},"author":317499,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143538,53],"tags":[145426,5134,145425],"coauthors":[52549],"class_list":["post-91922","post","type-post","status-publish","format-standard","hentry","category-dotnet-development","category-featured","tag-post-processing-effects-unity","tag-sql-prompt","tag-visual-effects-unity"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/91922","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/317499"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=91922"}],"version-history":[{"count":6,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/91922\/revisions"}],"predecessor-version":[{"id":91954,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/91922\/revisions\/91954"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=91922"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=91922"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=91922"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=91922"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}