top of page
metal_ball.webp

HLSL Shaders

Alright, shader nerds (or soon-to-be shader nerds), welcome to my little corner of the internet where we make sense of HLSL in Unity! Whether you're just dipping your toes into the shader pool or trying to level up your VFX game, this is where I spill all the tea—breakdowns, hacks, and random discoveries included. Let’s make some pixels shine! ✨🎨

What We’ll Cover

  • Understanding the basics of a shader

  • Creating a simple unlit shader from scratch

  • Walking through shader structure, properties, and rendering passes

  • Explaining vertex and fragment shaders in the simplest way possible

  • A little sprinkle of shader math magic ✨

Setting Up Your First Shader

To start, open Unity and create a simple plane. Now, let’s make our first shader:

  1. Navigate to your Assets folder.

  2. Right-click → Create → Shader → Unlit Shader.

  3. Rename it to something like MyFirstShader.

  4. Apply this shader to a new material and assign it to the plane.

​

If you see a magenta color—don’t panic! It just means there’s a shader issue (which we’ll fix in a sec). 🎨

Breaking Down the Shader Code

A Unity shader is made up of different parts. Let’s go over them:

​​​​​1. Properties

​

Think of properties as variables that let you tweak your shader from the Unity Inspector. Here’s how we define a simple color property:

Properties
{
    _Color("Test Color", Color) = (1,1,1,1) // White by default
}

This means our shader will have a color picker in the Material settings. The (1,1,1,1) stands for RGBA (Red, Green, Blue, Alpha).

2. SubShaders and Tags

​

This is where most of the shader logic lives. Tags tell Unity how to render the shader:

SubShader
{
    Tags { "RenderType"="Opaque" }
    LOD 100
}

  • Opaque means this shader doesn’t support transparency.

  • LOD 100 is for setting different shader complexity levels for different devices (like an iPhone 7 vs. iPhone 15).

3. The Shader Pass

​

Each Pass tells Unity how to render the object.ader:

Pass
{
    CGPROGRAM
    #pragma vertex vert // Runs on every vertex
    #pragma fragment frag // Runs on every pixel

Here, we’re defining two key functions:

  • vert (Vertex Shader): Runs on each vertex of the model and transforms it into the correct screen position.

  • frag (Fragment Shader): Runs on each pixel and decides the final color.

4. Writing the Vertex Shader

​

The vertex shader processes positions of 3D objects.

struct appdata
{
    float4 vertex : POSITION; // Position of each vertex
};

  • This appdata structure stores mesh data (like vertex positions).

  • UnityObjectToClipPos(v.vertex); transforms our object from local space to screen space.

5. The Fragment Shader

​

This is where we set the color of each pixel.

fixed4 frag(v2f i) : SV_Target
{
    fixed4 col = fixed4(1,1,1,1); // Default to white
    return col;
}

Want to change the color? Just modify the RGBA values:

  • (1,0,0,1) = Red

  • (1,1,0,1) = Yellow

  • (0,0,1,1) = Blue

6. Connecting the Color Property

​

Let’s use the _Color property in our shader!

fixed4 frag(v2f i) : SV_Target
{
    return _Color; // Use the user-defined color
}

Now, we can change the material color dynamically in Unity’s Inspector. 🎨🔥

Wrapping Up

​And that’s it!

We just built our first Unity shader from scratch. 🚀

​

Key takeaways:

✔ Vertex shaders handle object positions.
✔ Fragment shaders decide the color of each pixel.
✔ Properties let us modify shader values easily from Unity’s Inspector.
✔ Unity’s CGINC files provide handy shader functions we can reuse.

 

This is just the beginning! Let’s keep making some shader magic together. ✨ :))

bottom of page