2025年【Shader概要】了解shader 初学者必看 附有简单案例

【Shader概要】了解shader 初学者必看 附有简单案例Shader 简要概括 1 Shader 在可编程渲染流水线中 所处的位置是顶点着色器和片元着色器 这两个部分是高度可编程的 2 Unity 的 ShaderLab 是 Untiy 特有的着色器编程语言 他是对 Cg HLSL 的一层封装 是为了简化编程而诞生的 3

大家好,我是讯享网,很高兴认识大家。

Shader简要概括:

1、Shader在可编程渲染流水线中,所处的位置是顶点着色器和片元着色器,这两个部分是高度可编程的。

2、Unity的ShaderLab是Untiy特有的着色器编程语言,他是对Cg/HLSL/的一层封装,是为了简化编程而诞生的。

3、Shader脚本和Material密切相关,和Material一起作用在GameObject上。

4、Unity的着色器包括2种类型,一种是表面着色器,一种是顶点/片元着色器。其中表面着色器其实是对顶点/片元着色器的更高一层封装,它具有简单,易用性,但同时牺牲了控制的灵活性。需要注意的是顶点/片元着色器的“顶点着色器”和“片元着色器”写在同个shader文件里面,两个不连续的过程之所以可以放在一起,也是因为Unity为用户进行了封装。

5、一个Shader可以有多个SubShader,但必须至少有一个SubShader。

6、一个SubShader可以有多个Pass,多个Pass可以实现更加复杂的效果。

Shader结构:

shader结构包含了:声明,属性(Properties),SubShader,状态设置,标签(tags),Pass,Fallback。

1 声明:例如 shader "Custom/MyShader" { } 其中"Custom/"表示文件路径 "MyShader"表示这个Shader的名字

2 属性:例如 Properties{ _Int("Int", Int) = 2 } 其中 _Int是在Shader脚本里面的变量名,"Int" 是在Inspector 上显示的变量名, Int 是变量的属性,= 是给这个变量默认值。

除了Int类型外,还有Float、Range(min,max)、Color、Vector、2D、Cube、3D。需要注意的是2D、Cube、3D的属性语句是:

_2D("2D", 2D) = "white" {}, 其中"white"是系统内置的纹理,除了“white”还有“black”、“gray”、“bump”。

3 SubShader:SubShader包含了Pass模块,状态设置模块和标签模块。Shader可以包含多个SubShader,每个SubShader的渲染级别不同,渲染过程中会选择最合适的SubShader代码块来执行。

4 状态设置:是ShaderLab提供用于设置渲染状态的指令。常见的状态设置有:

Cull Back | Cull Front | Cull Off :剔除模式:剔除背面/正面/关闭剔除;

ZTest Less Greater | ZTest LEqual | ZTest GEqual | ZTest Equal | ZTest NotEqual | ZTest Always :深度测试的判断条件;

ZWrite On | ZWrite Off :开启/关闭深度测试;

Blend SrcFactor DstFactor:开启并设置混合模式;

5 标签:是一个键值对,用于描述对象的渲染方式,形式如 Tags{ “Queue” = "Transfparent" }常见的Tags有:

"Queue" = "Transparent" :控制渲染顺序;

"RenderType" = "Opaque" :对着色器进行分类,可用于着色器替换功能;

"DisableBatching" = "True" :使用模型空间下的顶点动画可能会出现问题,指定该SubShader是否可以批处理;


讯享网

"ForceNoShadowCasting" = "True" :该SubShader是否会投射阴影;

"IgnorProject" = "True" :表示物体是否不受Projector的影响,常用于半透明物体;

“CanUseSpriteAtlas” = "True" :该SubShader用于精灵时,应该设置为"False";

"PreviewType" = "Plane" :指明材质面板应该以社么形状来预览模型,一般是球形。

6 Pass:Pass可以包含命名、标签(Tags)、渲染设置。可以用UsePass命令在其他Shader里面调用该Pass。

7 FallBack:当shader里面的所有SubShader都不符合当前运行环境时,便会执行FallBack,它告诉Unity用某个特定的Shader来执行渲染,当然也可以关闭,不使用任何Shader渲染。 例如:FallBack Off / FallBack "Name"。

原文链接:Unity Shader的ShaderLab语法_PresleyGo的博客-CSDN博客


Shader分为两类 :

  1. 顶点Shader(3D图形都是由一个个三角面片组成的,顶点Shader就是计算每个三角面片上的顶点,并为最终像素渲染做准备)。
  2. 像素Shader,顾名思义,就是以像素为单位,计算光照、颜色的一系列算法。 几个不同的图形API都有各自的Shader语言,在DirectX中,顶点shader叫做 Vertex Shader ,像素Shader叫做 Pixel Shader; 在OpenGL中,顶点Shader也叫做 Vertex Shader ,但像素Shader叫做 Fragment Shader,也就是我们常说的片断Shader或者片元Shader。

说白了,Shader其实就是一段代码,这段代码的作用是告诉GPU具体怎样去绘制模型的每一个顶点的颜色以及最终每一个像素点的颜色。

Shader编程语言:

既然Shader是一段代码,那必然要用一种语言来书写它,目前主流的有三种语言:

  1. 基于OpenGL的OpenGL Shading Language,简称GLSL。
  2. 基于DirectX的High Level Shading Language,简称HLSL。
  3. 还有NVIDIA公司的C for Graphic,简称CG语言。

shader的透明通道:

//透明

Tags { "Queue" = "Transparent" "RenderType" = "Transparent" }
LOD 100

ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha

//不透明

Tags { "RenderType"="Opaque" }

LOD 100

放的位置,如下

举个例子

CFBC684BYYEHY(1Y7D1~AQB.png

渲染:

image.png

 简单火焰Shader特效:
// 定义一个自定义的水纹Shader Shader "Custom/WaterRipple" { // 定义所需属性 Properties { _MainTex ("Texture", 2D) = "white" {} _BumpMap("Normal Map", 2D) = "bump" {} _RippleCenter("Ripple Center", Vector) = (0.5,0.5,0,0) _RippleSize("Ripple Size", Range(0,1)) = 0.05 _RippleSpeed("Ripple Speed", Range(0,1)) = 0.1 } SubShader { Tags {"Queue"="Transparent" "RenderType"="Opaque" } LOD 200 Pass { CGPROGRAM // 定义顶点着色器函数 #pragma vertex vert // 定义片元着色器函数 #pragma fragment frag // 引入UnityCG.cginc库 #include "UnityCG.cginc" // 定义输入顶点数据结构体 struct appdata { float4 vertex : POSITION; float3 normal : NORMAL; float2 uv : TEXCOORD0; }; // 定义输出顶点数据结构体 struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; float3 worldPos : TEXCOORD1; float3 worldNormal : TEXCOORD2; }; // 定义纹理采样器 sampler2D _MainTex; sampler2D _BumpMap; float4 _RippleCenter; float _RippleSize; float _RippleSpeed; // 定义顶点着色器函数 v2f vert (appdata v) { v2f o; // 位置转换为裁剪空间坐标 o.vertex = UnityObjectToClipPos(v.vertex); o.uv = v.uv; // 保存世界空间中的位置和法线信息 o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz; o.worldNormal = UnityObjectToWorldNormal(v.normal); return o; } // 定义片元着色器函数 float4 frag (v2f i) : SV_Target { float2 uv = i.uv; float4 color = tex2D(_MainTex, uv); // 采样法线图 float4 bump = tex2D(_BumpMap, uv); // 根据法线图计算出法线信息 float2 normalMap = (bump.xy 2.0 - 1.0) _RippleSize; // 计算片元到波纹中心的距离 float dist = distance(i.worldPos.xy, _RippleCenter.xy); // 根据距离计算出波纹的大小 normalMap = pow(saturate((_RippleSize - dist) / _RippleSize), 2); // 根据当前片元的位置和波纹中心的位置计算出角度 float angle = atan2(i.worldPos.y - _RippleCenter.y, i.worldPos.x - _RippleCenter.x); // 加入时间偏移量和角度因素 float timeOffset = _Time.y _RippleSpeed + angle / (2 3.); // 计算纹理坐标偏移 uv += normalMap sin(timeOffset) 0.025; // 采样新的纹理颜色 color = tex2D(_MainTex, uv); return color; } ENDCG } } // 备选Shader FallBack "Diffuse" }

讯享网
简单水波纹特效:
讯享网// 定义一个自定义的水纹Shader Shader "Custom/WaterRipple" { // 定义所需属性 Properties { _MainTex ("Texture", 2D) = "white" {} _BumpMap("Normal Map", 2D) = "bump" {} _RippleCenter("Ripple Center", Vector) = (0.5,0.5,0,0) _RippleSize("Ripple Size", Range(0,1)) = 0.05 _RippleSpeed("Ripple Speed", Range(0,1)) = 0.1 } SubShader { Tags {"Queue"="Transparent" "RenderType"="Opaque" } LOD 200 Pass { CGPROGRAM // 定义顶点着色器函数 #pragma vertex vert // 定义片元着色器函数 #pragma fragment frag // 引入UnityCG.cginc库 #include "UnityCG.cginc" // 定义输入顶点数据结构体 struct appdata { float4 vertex : POSITION; float3 normal : NORMAL; float2 uv : TEXCOORD0; }; // 定义输出顶点数据结构体 struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; float3 worldPos : TEXCOORD1; float3 worldNormal : TEXCOORD2; }; // 定义纹理采样器 sampler2D _MainTex; sampler2D _BumpMap; float4 _RippleCenter; float _RippleSize; float _RippleSpeed; // 定义顶点着色器函数 v2f vert (appdata v) { v2f o; // 位置转换为裁剪空间坐标 o.vertex = UnityObjectToClipPos(v.vertex); o.uv = v.uv; // 保存世界空间中的位置和法线信息 o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz; o.worldNormal = UnityObjectToWorldNormal(v.normal); return o; } // 定义片元着色器函数 float4 frag (v2f i) : SV_Target { float2 uv = i.uv; float4 color = tex2D(_MainTex, uv); // 采样法线图 float4 bump = tex2D(_BumpMap, uv); // 根据法线图计算出法线信息 float2 normalMap = (bump.xy 2.0 - 1.0) _RippleSize; // 计算片元到波纹中心的距离 float dist = distance(i.worldPos.xy, _RippleCenter.xy); // 根据距离计算出波纹的大小 normalMap = pow(saturate((_RippleSize - dist) / _RippleSize), 2); // 根据当前片元的位置和波纹中心的位置计算出角度 float angle = atan2(i.worldPos.y - _RippleCenter.y, i.worldPos.x - _RippleCenter.x); // 加入时间偏移量和角度因素 float timeOffset = _Time.y _RippleSpeed + angle / (2 3.); // 计算纹理坐标偏移 uv += normalMap sin(timeOffset) 0.025; // 采样新的纹理颜色 color = tex2D(_MainTex, uv); return color; } ENDCG } } // 备选Shader FallBack "Diffuse" }

小讯
上一篇 2025-03-28 17:52
下一篇 2025-03-09 08:20

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/23472.html