Unity渲染(一):Shader着色器基础入门之纯色Shader

本文介绍UnityShader基础知识,包括Shader语法、CG语义、GPU渲染流水线等内容,并演示如何实现纯色渲染效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Unity渲染(一):纯色Shader

通过这里,你可以学习到UnityShader基本语法,CG语义,GPU渲染流水线等编写着色器的基础知识

开发环境:Unity5.0或者更高


在这里插入图片描述

最终效果

概述

1. Unity shader 基本语法
2. 顶点着色器与片元着色器参数传递
3. 基本shader语义
4. GPU渲染流水线

1.1 开始

  • 创建场景并取名为SolidColor并在场景中添加CameraCube

在这里插入图片描述

Hierachy
  • 创建MaterialShader

在这里插入图片描述

  • 删除Shader中所有代码后,写入如下代码, 这是shader的基本结构
Shader "Toturial/SolidColor"
{
	SubShader
    {
        Pass
        {
            CGPROGRAM
            
            ENDCG
        }
    }
}

此时Console出现了两条警告信息,第一条表示该Shader代码中的所有SubShader都不支持,第二条表示需要该Shader对GPU顶点着色器和片元着色器进行编程,在

Shader warning in 'Toturial/SolidColor': Toturial/SolidColor shader is not supported on this GPU (none of subshaders/fallbacks are suitable)
Shader warning in 'Toturial/SolidColor': Both vertex and fragment programs must be present in a shader snippet. Excluding it from compilation

代码说明
  1. Shader "xx/xx"表示在Unity材质面板的路径
    d
  2. SubShader{ ... } 中编写着色代码,可以写多个,GPU会选择一个最合适的来进行渲染
  3. Pass{ ... } 写在SubShader中 ,渲染逻辑和渲染配置写在这里面,可以写多个,有几个就会渲染几次
  4. CGPROGRAM ... ENDCG CG代码,渲染逻辑写在这里面

1.2 简化的GPU渲染管线

在这里插入图片描述

简化的GPU渲染管线

管线说明(重要!!!)
  1. Unity将顶点数据、顶点颜色等属性传入Shader ,进入GPU顶点着色器处理,之后进入裁剪阶段,裁剪完成后数据将进入片元着色器,最后输出到屏幕
  2. 其中顶点着色器和片元着色器是可编程的(表示可以在Shader中写代码进行控制)
  3. 裁剪阶段是可配置的(表示可以在Shader中使用一些特定的语法进行设置 例如 Cut off)

1.3 顶点着色器和片元着色器

在我们对顶点着色器(Vertex Shader)以及片元着色器(Fragment Shader)进行编程之前,需要先从获取对象的属性,例如图片的顶点位置和颜色,模型的顶点位置、法线方向、颜色等。

我们通过语义绑定来获取模型数据或者图片的位置和颜色

语义说明
  1. 类型 变量名 :POSITION; 获取输入的顶点 (例如:float4 vertex : POSITION)
  2. 类型 变量名 : COLOR 获取输入的颜色,SpriteRenderer 和Image组件上的Color
  3. :SV_POSITION 顶点着色器输出的顶点位置,SV表示System Value的缩写
  4. :SV_TARGET 片元着色器输出的值

了解了语义之后,我们需要定义函数为顶点着色器和片元着色器进行编程控制。

宏定义

#pragma vertex vert 定义顶点着色器,vert为函数名 可以改成其他的
#pragma fragment frag 定义片元着色器 ,frag为函数名 可以改成其他的

之后我们在CGPROGRAM … ENDCG中写入如下代码:

Shader "Toturial/SolidColor"
{
	SubShader
    {
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag 
            
            float4 vert(float4 vertex : POSITION): SV_POSITION
            {
                return UnityObjectToClipPos(vertex);
            }

            fixed4 frag() : SV_TARGET
            {
                return fixed4(0,0,1,1);
            }
            ENDCG
        }
    }
}

其中UnityObjectToClipPos(vertex)表示将顶点位置从对象空间转换到裁剪空间,这一步是为了将3D的场景最终输出到一张2D的屏幕上。参考Unity官方文档 https://docs.unity3d.com/cn/current/Manual/SL-BuiltinFunctions.html

最终返回了蓝色fixed4(0,0,1,1);,之后给场景中的Cube添加材质Custom_SolidColor

在这里插入图片描述

最终效果

1.4 代码结构优化

上面的代码中我们只用到了顶点位置:POSITION语义,当我们需要多个参数的时候,例如还需要颜色,法线方向等我们可以使用结构体给顶点着色器函数传参

修改 CGPROGRAM … ENDCG 中的代码,首先我们定义一个结构体名为a2v,他是application to vertex 的缩写,意思是表示数据从应用传递到顶点着色器

struct a2v
{
	float4 vertex : POSITION;
	fixed4 color : COLOR;
};

我们再定义一个结构体用于将数据从顶点着色器输出后传递到片元着色器,结构体名为v2f ,它是vertex to fragment的缩写,

struct v2f
{
	float4 pos : SV_POSITION;
	fixed4 color : COLOR;
};

之后修改顶点着色器函数返回值和参数

v2f vert(a2v v)
{
    v2f o;
    o.pos = UnityObjectToClipPos(v.vertex);
    o.color = v.color;
    return o;
}

完整代码

Shader "Toturial/SolidColor"
{
    SubShader
    {
        Pass
        {
            CGPROGRAM
            
            #pragma vertex vert
            #pragma fragment frag 

            struct a2v
            {
                float4 vertex : POSITION;
                fixed4 color : COLOR;
            };

            struct v2f
            {
                float4 pos : SV_POSITION;
                fixed4 color : COLOR;
            };

            v2f vert(a2v v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.color = v.color;
                return o;
            }

            fixed4 frag(v2f i) : SV_TARGET
            {
                return fixed4(0,0,1,1);
            }

            ENDCG
        }
    }
}

最终结果
在这里插入图片描述

最终效果

1.5 使用Properties属性

在场景中创建一个Image与2D Sprite

在这里插入图片描述
Image组件的Material设置为Custom_SolidColor
SpriteRenderer 的Material设置为Custom_SolidColor

此时出现了一个报错

Material 'Custom_SolidColor' with Shader 'Toturial/SolidColor' doesn't have a texture property '_MainTex'

这是因为图片组件会将Sprite设置给Shader中的_MainTex,所以我们在Properties中需要定义一个变量名为_MainTex类型为2D的参数,将以下代码写在SubShader上面。

Properties
{
    _MainTex("MainTex",2D) = "white"{}
}
代码说明
  1. Properties{...} 代码块定义材质属性。参阅 ShaderLab:定义材质属性
    这部分的参数会显示在材质面板上
    在这里插入图片描述
  2. _MainTex("MainTex",2D) = "white"{} _MainTex表示变量名,用于在C#访问,"MainTex"表示在材质面板上的名字,2D为参数类型,“white”{}为默认值

接下来我们给材质属性添加一个设置颜色的功能,首先在Properties属性添加Color

   Properties
    {
        _MainTex("MainTex",2D) = "white"{}
        _Color("Color",Color) = (1,1,1,1)
    }

之后我们需要在CGPROGRAM… ENDCG 中定义变量用来获取Properties里的_Color值,在 struct a2v上面定义

#pragma vertex vert
#pragma fragment frag 

fixed4 _Color;

struct a2v
{

修改frag函数

fixed4 frag(v2f i) : SV_TARGET
{
     return _Color;
}

修改材质界面的Color
在这里插入图片描述
完整代码:

Shader "Toturial/SolidColor"
{
    Properties
    {
        _MainTex("MainTex",2D) = "white"{}
        _Color("Color",Color) = (1,1,1,1)
    }

    SubShader
    {
        Pass
        {
            CGPROGRAM
            
            #pragma vertex vert
            #pragma fragment frag 

            fixed4 _Color;

            struct a2v
            {
                float4 vertex : POSITION;
                fixed4 color : COLOR;
            };

            struct v2f
            {
                float4 pos : SV_POSITION;
                fixed4 color : COLOR;
            };

            v2f vert(a2v v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.color = v.color;
                return o;
            }

            fixed4 frag(v2f i) : SV_TARGET
            {
                 return _Color;
            }

            ENDCG
        }
    }
}

最终看到效果

在这里插入图片描述

最终效果

接下来我们将使用Image.Color和SpriteRenderer修改材质的颜色,因为我们在a2v结构体中对color进行了:Color语义绑定,之后将a2v结构体传入顶点着色器vert,在顶点着色器中实例化了一个v2f结构体并对color进行赋值,之后将v2f传递到片元着色器中,所以我们需要把片元着色器frag中的返回值修改为i.color就可以达到效果。

fixed4 frag(v2f i) : SV_TARGET
{
     return i.color;
}

修改完后我们修改场景中的Image组件上的颜色为#FFDA00 ,将SpriteRenderer上的颜色修改为#3889F1

在这里插入图片描述

最终效果

1.6 完整代码

Shader "Toturial/SolidColor"
{
    Properties
    {
        _MainTex("MainTex",2D) = "white"{}
        _Color("Color",Color) = (1,1,1,1)
    }

    SubShader
    {
        Pass
        {
            CGPROGRAM
            
            #pragma vertex vert
            #pragma fragment frag 

            fixed4 _Color;

            struct a2v
            {
                float4 vertex : POSITION;
                fixed4 color : COLOR;
            };

            struct v2f
            {
                float4 pos : SV_POSITION;
                fixed4 color : COLOR;
            };

            v2f vert(a2v v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.color = v.color;
                return o;
            }

            fixed4 frag(v2f i) : SV_TARGET
            {
                 return i.color;
            }

            ENDCG
        }
    }
}
在本篇文章中,我们将从个简单的 Unlit Shader 开始,了解如何在 Unity 的 URP 中编写 Shader。 Unlit Shader 是最基本的 Shader,它不考虑任何光照,只对物体进行纯色渲染。这是个非常适合初学者的 Shader,因为它可以让我们更好地理解 Shader 的基本结构和语法。 首先,我们需要创建个新的 Shader,选择 URP 中的 Universal Render Pipeline/Lit Shader,并将其重命名为 Unlit。 接下来,打开 Shader 文件,我们可以看到 Shader 的基本结构如下: ``` Shader "Custom/Unlit" { Properties { // 定义 Shader 的属性 } SubShader { // 定义 SubShader 的标签和 Tags Pass { // 定义 Pass 的标签和 Tags CGPROGRAM // Shader 代码 ENDCG } } } ``` 如上所述,Shader 由多个 SubShader 组成,每个 SubShader 又由多个 Pass 组成。在这里,我们只需要关注个 SubShader个 Pass。 首先,我们需要在 Properties 中定义 Shader 的属性。这些属性可以在材质面板中进行编辑和调整。对于 Unlit Shader,我们只需要定义颜色属性即可,代码如下: ``` Properties { _Color ("Color", Color) = (1,1,1,1) } ``` 上述代码定义了个名为 _Color 的属性,类型为 Color,初始值为白色。在这里,我们使用了 UnityShaderLab 语言来定义属性。 接下来,我们需要在 SubShader 中定义标签和 Tags。标签和 Tags 是用来控制 Shader渲染和使用的,我们需要根据实际情况进行定义。 对于 Unlit Shader,我们只需要定义个名为 "RenderType" 的标签,值为 "Opaque",表示这个 Shader 用于不透明的渲染。代码如下: ``` Tags { "RenderType"="Opaque" } ``` 最后,我们需要在 Pass 中编写 Shader 代码。对于 Unlit Shader,我们只需要将颜色值直接输出即可,代码如下: ``` CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; }; struct v2f { float4 vertex : SV_POSITION; }; float4 _Color; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); return o; } fixed4 frag (v2f i) : SV_Target { return _Color; } ENDCG ``` 在上述代码中,我们定义了两个结构体 appdata 和 v2f,分别代表输入和输出数据。在 vert 函数中,我们将输入的顶点位置转换为屏幕空间的位置,并将其保存到输出中。在 frag 函数中,我们直接返回颜色值,这样就能够实现纯色渲染了。 最后,我们需要将 Shader 保存,并将其赋给个材质。在材质面板中,我们可以看到 _Color 属性,可以通过这个属性来修改材质的颜色。 这就是从个简单的 Unlit Shader 开始,在 Unity 的 URP 中编写 Shader 的全部过程。希望本文对你有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值