Get an 20% OFF using the RELEASE code on your book purchase. For a limited time.

Introduction to the shader programming language

3.0.6. Texture Properties

This post is also available in…

These properties allow us to implement textures within our shader. 

If we want to place a texture on our object (e.g. a 3D character), then we would have to create a 2D property for its texture and then pass it through a function called “tex2D” which will ask us for two parameters: the texture and the UV coordinates of our object.

A property that we will use frequently in our video games is the “Cube” which itself refers to a “Cubemap”. This type of texture is quite useful for generating reflection maps, e.g., reflections in our character’s armour or to metallic elements in general.

Other types of textures that we can find are those of the 3D type. They are used less frequently than the previous ones since they are volumetric and have an additional coordinate for their spatial calculation.

The following syntax declares textures in our shader

// name (“display name”, 2D) = “defaultColorTexture”
// name (“display name”, Cube) = “defaultColorTexture”
// name (“display name”, 3D) = “defaultColorTexture”

Shader “InspectorPath / shaderName”
{
    Properties 
    {
        _MainTex (“Texture”, 2D) = “white” {}
        _Reflection (“Reflection”, Cube) = “black” {}
        _3DTexture (“3D Texture”, 3D) = “white” {}
    } 
}

When declaring a property it is very important to consider that it will be written in ShaderLab declarative language while our program will be written in either Cg or HLSL language. As they are two different languages we have to create “connection variables”.

These variables are declared globally using the word “uniform”, however, this step can be skipped because the program recognizes them as global variables. So, to add a property to a “.shader” we must first declare the property in ShaderLab, then the global variable using the same name in Cg or HLSL, and then we can finally use it.

Shader “InspectorPath / shaderName”
{
    Properties 
    {
    // declare properties
    _MainTex (“Texture”, 2D) = “white” {}    
    _Color (“Color”, Color) = (1, 1, 1, 1)    
    } 
    SubShader
    {
        Pass
        {
            CGPROGRAM
            ...
            // add connection variables
            sampler2D _Maintex;        
            float4 _Color;            
            ...
            half4 frag (v2f i) : SV_Target
            {
                // use
                half4 col = tex2D(_MainTex, i.uv);    
                return col * _Color;                
            }
            ENDCG
        }
    }
}

In the previous example, we declared two properties: _MainTex and _Color. Then we created two connection variables within our CGPROGRAM, these correspond to “sampler2D _MainTex” and “float4 _Color”. Both the properties and the connection variables must have the same name so that the program can recognize them.

In section 2.3.5 we will detail the operation of a 2D sampler when we talk about data types.

Follow us to stay informed about all the latest news, updates, and more.

Join the group to share your experiences with other developers.

Subscribe to our channel and keep learning game dev!

jettelly-logo

Jettelly Team

We are a team of indie developers with more than 9 years of experience in video games. As an independent studio, we have developed Nom Noms in which we published with Hyperbeard in 2019. We are currently developing The Unity Shader Bible.

Follow us on our social networks.