Unity3D学习笔记3——Unity Shader的初步使用
文章目录
- 1. 概述
- 2. 详论
- 2.1. 创建材质
- 2.2. 着色器
- 2.2.1. 名称
- 2.2.2. 属性
- 2.2.3. SubShader
- 2.2.3.1. 标签(Tags)
- 2.2.3.2. 渲染状态(RenderSetup)
- 2.2.3.3. 通道(Pass)
- 2.2.4. 回退(FallBack)
- 2.3. 渲染管线
1. 概述
在上一篇文章《Unity3D学习笔记2——绘制一个带纹理的面》中介绍了如何绘制一个带纹理材质的面,并且通过调整光照,使得材质生效(变亮)。不过,上篇文章隐藏了一个很重要的细节——Unity Shader。Shader(着色器)是渲染管线中可被用户编程的阶段,依靠着色器可以控制渲染管线的细节。现代图像渲染技术,都把Shader封装成与Material(材质)相关的组件。所以这篇文章,我们就初步学习下在Unity中使用Shader。
2. 详论
2.1. 创建材质
在上一章中,材质、以及材质相关的资源是在Unity3D编辑器中创建,在C#脚本中直接引用的。这里为了学习使用Shader,我们使用自定义的Shader,可以在C#脚本中创建材质。修改上一章代码的材质部分:
Shader shader = Shader.Find("Custom/MainShader");
Material material = new Material(shader);Texture2D texture = Resources.Load<Texture2D>("ImageDemo");
material.mainTexture = texture;MeshRenderer meshRenderer = newGameObject.AddComponent<MeshRenderer>();
meshRenderer.material = material;
可以看到,要创建一个Material,首先得创建一个Shader。我们在Project视图中右键菜单->Create->Standard Surface Shader,创建一个标准表面着色器MainShader:
双击打开这个Shader,可以看到这个Shader的具体内容。标准着色器很复杂,我们清空里面的内容,填入我们这个更简单的着色器示例:
Shader "Custom/MainShader"
{Properties{ _MainTex ("Texture", 2D) = "white" {} }SubShader{Tags{"Queue" = "Geometry"}Cull BackPass{CGPROGRAM#pragma vertex vert #pragma fragment fragsampler2D _MainTex;//顶点着色器输入struct a2v{float4 position : POSITION;float3 normal: NORMAL;float2 texcoord : TEXCOORD0; };//顶点着色器输出struct v2f{float4 position: SV_POSITION;float2 texcoord: TEXCOORD0;};v2f vert(a2v v){v2f o; o.position = mul(UNITY_MATRIX_MVP, v.position); o.texcoord = v.texcoord;return o;}fixed4 frag(v2f i) : SV_Target {return tex2D(_MainTex, i.texcoord); }ENDCG}}FallBack "Diffuse"
}
2.2. 着色器
Unity使用的着色器语言叫做ShaderLab,它是图形渲染中Shader(例如GLSL,HLSL以及CG)的更高级更抽象一级的封装。ShaderLab是个非常简单的说明性描述语言,通过嵌套在花括号中的语义来描述Unity Shader文件。
2.2.1. 名称
通过Shader语义指定Unity Shader的名称:
Shader "Custom/MainShader"
{}
这个名称非常重要,在Unity编辑器中需要通过这个名字来引用Shader。
2.2.2. 属性
Shader语义块的第一个语义块是Properties语义块,它连接着材质和Unity3d编辑器,设置了这个属性就能够通过材质面板调整材质,调整材质的本质就是调整Shader。Properties的定义通常描述如下:
Properties {Name ("display name",PropertyType) = DefaultValue
}
Name指的是在Shader中使用的名称,display name指的是显示在材质面板的名称。PropertyType则有点容易混淆,它指的是显示在材质面板中的属性类型,借用一下《Unity Shader入门精要》的图表:
2.2.3. SubShader
每个Unity Shader都至少包含一个SubShader语义块,Unity会优先选择第一个能够在当前平台下运行的SubShader作为最终渲染效果的Shader。
这个语义块下面又会包含三个语义块:
2.2.3.1. 标签(Tags)
SubShader的标签用于用于标识何时以何种方式被渲染到渲染引擎,它由一系列键值对组成。Queue是最常用的标签,用于标识渲染物体在渲染队列中的位置:
我们这里,把这个渲染物体放到Geometry队列中,这个位置通常放置不透明物体的渲染:
Tags{"Queue" = "Geometry"}
2.2.3.2. 渲染状态(RenderSetup)
渲染状态用于设置图形硬件的各种状态,例如是否应开启 Alpha 混合或是否应使用深度测试等。在像OpenGL这样的图形接口中,通常是以函数的形式进行调用的,Unity3d将其放在Shader里面,也有一定的道理。
这里的渲染状态设置成将背面裁剪掉:
Cull Back
2.2.3.3. 通道(Pass)
在Pass语义块中,才是像OpenGL/DirectX中使用的Shader。OpenGL使用的着色器语言叫做GLSL,DirectX使用的着色器语言叫做HLSL,Unity3D则推荐使用Cg语言,这是一种类C语言,与HLSL非常相似。Cg语言代码段在Pass语义块中被包裹在CGPROGRAM和ENDCG之间:
CGPROGRAM
//...
ENDCG
2.2.4. 回退(FallBack)
FallBack定义了一种退化策略,由于不同机器支持的性能特性不同,如果之前的子着色器都不生效,那么就使用这个着色器,通常这个着色器是内置的:
FallBack "Diffuse"
2.3. 渲染管线
图形渲染引擎的渲染管线其实是个内涵非常丰富的概念,再次借用《Unity Shader入门精要》的插图,渲染管线的描述大致如下:
当然只看这个图是不够的,但是我们可以直接从代码层面去了解它。镶嵌在CGPROGRAM和ENDCG之间的CG代码,体现的正是渲染管线的思维。
首先,通过编译指令,分别指定顶点着色器程序和片元着色器程序:
#pragma vertex vert
#pragma fragment frag
vert就是顶点着色器的函数,在这个着色器程序中指定了计算了顶点坐标和纹理坐标:
v2f vert(a2v v)
{v2f o; o.position = mul(UNITY_MATRIX_MVP, v.position); o.texcoord = v.texcoord;return o;
}
传入参数是一个结构体,POSITION,NORMAL,TEXCOORD0是Unity Shader中固定的语义,分别代表这位置、法向量以及纹理坐标,他们也被称为顶点属性。还记得在上一篇文章《Unity3D学习笔记2——绘制一个带纹理的面》中创建Mesh时给Mesh创建的成员变量vertices、uv和normals吧?给他们传入的数据正是在这里用到了。
//顶点着色器输入
struct a2v
{float4 position : POSITION;float3 normal: NORMAL;float2 texcoord : TEXCOORD0;
};
传出参数则是另外一个结构体:
//顶点着色器输出
struct v2f
{float4 position: SV_POSITION;float2 texcoord: TEXCOORD0;
};
SV_POSITION表示的是裁剪空间坐标,也就是在顶点着色器中计算的顶点值。这个计算内容的内涵也挺丰富的,简单来说,创建Mesh时的顶点坐标,经过一个模型变换(Model)、视图变换(View)、投影变换(Projection),最终变成了裁剪空间坐标系中的坐标,体现在着色器中,就是内置的MVP矩阵UNITY_MATRIX_MVP。
剩下的就是片元着色器函数的部分了。在这个着色器中,_MainTex也就是我们先前创建的,并且传递到材质中的纹理,通过将顶点着色器中传递过来的纹理坐标进行采样,得到具体的片元颜色:
sampler2D _MainTex;fixed4 frag(v2f i) : SV_Target
{return tex2D(_MainTex, i.texcoord);
}
最终显示的效果如下:
可以看到这里显示的就是图片本身的颜色,这是因为在着色器中只是采样了图片的颜色,并没有光照计算的参与。也就是在图形引擎中,任何效果的设置只是表象,任何效果的实现都会归结到着色器中。
Unity3D学习笔记3——Unity Shader的初步使用相关推荐
- Unity3D学习笔记6——GPU实例化(1)
文章目录 1. 概述 2. 详论 3. 参考 1. 概述 在之前的文章中说到,一种材质对应一次绘制调用的指令.即使是这种情况,两个三维物体使用同一种材质,但它们使用的材质参数不一样,那么最终仍然会造成 ...
- Unity3D学习笔记8——GPU实例化(3)
文章目录 1. 概述 2. 详论 2.1. 自动实例化 2.2. MaterialPropertyBlock 3. 参考 1. 概述 在前两篇文章<Unity3D学习笔记6--GPU实例化(1) ...
- Unity3D学习笔记12——渲染纹理
文章目录 1. 概述 2. 详论 3. 问题 1. 概述 在文章<Unity3D学习笔记11--后处理>中论述了后处理是帧缓存(Framebuffer)技术实现之一:而另外一个帧缓存技术实 ...
- Unity3D 学习笔记3——了解U3D引擎的操作面板和各种工具
Unity3D 学习笔记3--了解U3D引擎的操作面板和各种工具 在完成了Unity的安装破解之后,我们接下来要做的当前是启动这个引擎,然后学会如何去使用它为我们提供的各种工具,这也是上手任何一个软件 ...
- Unity3D 学习笔记4 —— UGUI+uLua游戏框架
Unity3D 学习笔记4 -- UGUI+uLua游戏框架 使用到的资料下载地址以及基础知识 框架讲解 拓展热更过程 在这里我们使用的是uLua/cstolua技术空间所以提供的UGUI+uLua的 ...
- unity3d 学习笔记四 skybox(天空盒) light(光源) halo(光晕)
Unity3D学习笔记(四)天空.光晕和迷雾 六年前第一次接触<魔兽世界>的时候,被其绚丽的画面所折服,一个叫做贫瘠之地的地方,深深印在我的脑海里.当时在艾泽拉斯大陆还不能使用飞行坐骑,试 ...
- 【HLSL学习笔记】WPF Shader Effect Library算法解读之[DirectionalBlur]
原文:[HLSL学习笔记]WPF Shader Effect Library算法解读之[DirectionalBlur] 方位模糊是一个按照指定角度循环位移并叠加纹理,最后平均颜色值并输出的一种特效. ...
- 【Unity学习笔记】[Unity中文课堂教程] C#中级编程代码
[Unity学习笔记][Unity中文课堂教程] C#中级编程代码 最近想补一补C#基础,Unity官方的C#中级编程教程质量很高,于是开个帖子把跟着敲+记录了部分价讲解和我自己的理解的代码存在这 原 ...
- Unity学习笔记:Unity 3D 飞机大战
Unity学习笔记:Unity 3D 飞机大战 1.打开unity软件后,首先新建Quad作为背景,导入飞机模型,并为其添加刚体 然后创建C#脚本,挂载到飞机上. 2.给飞机创建子弹,让子弹成为预制体 ...
最新文章
- 起源,机制与趋势,如何理解和定义城市大脑
- linux根分区扩容(LVM动态卷)
- tvOS模拟器遥控的快捷键
- L1-048. 矩阵A乘以B
- python writerow参数_csv文件的输出结果TypeError writerow()接受2个位置参数,但给出了5个...
- JDBC+Servlet+JSP整合开发之26.JSP内建对象
- ryujinx模拟器linux安装教学,switch模拟器Ryujinx
- 论文常用出图软件(Matlab,XMind,Viso,ppt)以及格式选择(eps,svg,tif,png)
- 09 自动发表博客评论
- 装完linux无法进入windows,安装Ubuntu后无法启动Windows,如何解决?
- (GIS可视化)热力图
- PTA:运算符重载(最简分数,c++)
- exsi rh2288hv5 驱动_华为RH2288H服务器引导ServiceCD安装Windows Server操作系统
- 英语口语234之每日十句口语
- 美拉德不做鬼佬BBQ,只做中国餐饮文化
- Android黑科技 自动点击
- 一个命令禁用baloo_file及baloo_file_extractor
- Linux之命令scp远程拷贝文件
- 电脑重装系统后安全中心有个黄色感叹号如何处理
- 在线重装Win11系统详细教程
热门文章
- mybatis的2种缓存机制(1)
- 经典面试题:var 和 let 的区别
- 【Codeforces Round #523 (Div. 2) D.TV Shows】 贪心+二分
- Maven搭建Springmvc+Spring+Hibernate+html
- Python调用腾讯API进行人像动漫化
- LocalDateTime、LocalDate与Date互转
- JFreeChart画3D二维图
- 淘宝小游戏了解一下?技术引擎让你喜提2000条锦鲤
- Jmeter命令测试执行
- 【蓝桥杯回力篇】蓝桥模拟赛【摆烂day1】