Search icon CANCEL
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Unity 5.x Shaders and Effects Cookbook

You're reading from   Unity 5.x Shaders and Effects Cookbook Master the art of Shader programming to bring life to your Unity projects

Arrow left icon
Product type Paperback
Published in Feb 2016
Publisher
ISBN-13 9781785285240
Length 240 pages
Edition 1st Edition
Languages
Tools
Concepts
Arrow right icon
Author (1):
Arrow left icon
Alan Zucconi Alan Zucconi
Author Profile Icon Alan Zucconi
Alan Zucconi
Arrow right icon
View More author details
Toc

Table of Contents (12) Chapters Close

Preface 1. Creating Your First Shader 2. Surface Shaders and Texture Mapping FREE CHAPTER 3. Understanding Lighting Models 4. Physically Based Rendering in Unity 5 5. Vertex Functions 6. Fragment Shaders and Grab Passes 7. Mobile Shader Adjustment 8. Screen Effects with Unity Render Textures 9. Gameplay and Screen Effects 10. Advanced Shading Techniques Index

Using properties in a Surface Shader

Now that we have created some properties, let's actually hook them up to the shader so that we can use them as tweaks to our shader and make the material process much more interactive.

We can use the properties' values from the material's Inspector tab because we have attached a variable name to the property itself, but in the shader code, you have to set up a couple of things before you can start calling the value by its variable name.

How to do it…

The following steps show you how to use the properties in a Surface Shader:

  1. To begin, let's remove the following lines of code, as we deleted the property called _MainTex in the Creating a basic Standard Shader recipe of this chapter:
    _MainTex ("Albedo (RGB)", 2D) = "white" {}
    sampler2D _MainTex;
    fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
  2. Next, add the following lines of code to the shader, below the CGPROGRAM line:
    float4 _AmbientColor;
    float _MySliderValue;
  3. With step 2 complete, we can now use the values from the properties in our shader. Let's do this by adding the value from the _Color property to the _AmbientColor property and giving the result of this to the o.Albedo line of code. So, let's add the following code to the shader in the surf() function:
    void surf (Input IN, inout SurfaceOutputStandard o) {
      fixed4 c = pow((_Color + _AmbientColor), _MySliderValue);
      o.Albedo = c.rgb;
      o.Metallic = _Metallic;
      o.Smoothness = _Glossiness;
      o.Alpha = c.a;
    }
  4. Finally, your shader should look like the following shader code. If you save your shader in MonoDevelop and re-enter Unity, your shader will compile. If there were no errors, you will now have the ability to change the ambient and emissive colors of the material as well as increase the saturation of the final color using the slider value. Pretty neat, huh!
    Shader "CookbookShaders/StandardDiffuse3" {
      // We define Properties in the properties block
      Properties {
        _Color ("Color", Color) = (1,1,1,1)
        _AmbientColor("Ambient Color", Color) = (1,1,1,1)
        _MySliderValue("This is a Slider", Range(0,10)) = 2.5
      }
      SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 200
        
        // We need to declare the properties variable type inside of the
        // CGPROGRAM so we can access its value from the properties block.
        CGPROGRAM
        #pragma surface surf Standard fullforwardshadows
        #pragma target 3.0
    
        struct Input {
          float2 uv_MainTex;
        };
    
    
        fixed4 _Color;
        float4 _AmbientColor;
        float _MySliderValue;
    
        void surf (Input IN, inout SurfaceOutputStandard o) {
          // We can then use the properties values in our shader 
          fixed4 c = pow((_Color + _AmbientColor), _MySliderValue);
          o.Albedo = c.rgb;
          o.Alpha = c.a;
        }
        ENDCG
      } 
      FallBack "Diffuse"
    }

Tip

Downloading the example code

You can download the example code files for all Packt books you have purchased from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.

Note

The pow(arg1, arg2) function is a built-in function that will perform the equivalent math function of power. So, argument 1 is the value that we want to raise to a power and argument 2 is the power that we want to raise it to.

To find out more about the pow() function, look at the Cg tutorial. It is a great free resource that you can use to learn more about shading and get a glossary of all the functions available to you in the Cg shading language:

http://http.developer.nvidia.com/CgTutorial/cg_tutorial_appendix_e.html

The following screenshot demonstrates the result obtained using our properties to control our material's colors and saturation from within the material's Inspector tab:

How to do it…

How it works…

When you declare a new property in the Properties block, you are providing a way for the shader to retrieve the tweaked value from the material's Inspector tab. This value is stored in the variable name portion of the property. In this case, _AmbientColor, _Color, and _MySliderValue are the variables in which we are storing the tweaked values. In order for you to be able to use the value in the SubShader{} block, you need to create three new variables with the same names as the property's variable name. This automatically sets up a link between these two so that they know they have to work with the same data. Additionally, it declares the type of data that we want to store in our subshader variables, which will come in handy when we look at optimizing shaders in a later chapter.

Once you have created the subshader variables, you can then use the values in the surf() function. In this case, we want to add the _Color and _AmbientColor variables together and take it to a power of whatever the _MySliderValue variable is equal to in the material's Inspector tab.

The vast majority of shaders start out as Standard Shaders and get modified until they match the desired look. We have now created the foundation for any Surface Shader you will create that requires a diffuse component.

Note

Materials are assets. This means that any change made to them while your game is running in the editor are permanent. If you have changed the value of a property by mistake, you can undo it using Ctrl + Z.

There's more…

Like any other programming language, Cg does not allow mistakes. As such, your shader will not work if you have a typo in your code. When this happens, your materials are rendered in unshaded magenta:

There's more…

When a script does not compile, Unity prevents your game from being exported or even executed. Conversely, errors in shaders do not stop your game from being executed.

If one of your shaders appears as magenta, it is time to investigate where the problem is. If you select the incriminated shader, you will see a list of errors displayed in its Inspector tab:

There's more…

Despite showing the line that raised the error, it rarely means that this is the line that has to be fixed. The error message shown in the previous image is generated by deleting the sampler2D _MainTex variable from the SubShader{} block. However, the error is raised by the first line that tries to access such a variable.

Finding and fixing what's wrong with code is a process called debugging. The most common mistakes that you should check for are as follows:

  • A missing bracket. If you forgot to add a curly bracket to close a section, the compiler is likely to raise errors at the end of the document, at the beginning, or a new section.
  • A missing semicolon. One of the most common mistakes but luckily one of the easiest to spot and fix. Errors are often raised by the following line.
  • A property that has been defined in the Properties section but has not been coupled with a variable in the SubShader{} block.
  • Conversely to what you might be used to in C# scripts, floating point values in Cg do not need to the followed by an f: it's 1.0, not 1.0f.

The error messages raised by shaders can be very misleading, especially due to their strict syntactic constraints. If you are in doubt about their meaning, it's best to search the Internet. Unity forums are filled with other developers who are likely to have encountered (and fixed) your problem before.

See also

More information on how to master Surface Shaders and their properties can be found in Chapter 2, Surface Shaders and Texture Mapping. If you are curious to see what shaders can actually do when used at their full potential, have a look at Chapter 10, Advanced Shading Techniques, for some of the most advanced techniques covered in this book.

lock icon The rest of the chapter is locked
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime