Unity Shader学习笔记

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

目录

前言

一、ShaderLab

二、Unity Shader结构

三、GPU流水线

四、着色器

五、坐标空间

六、编写及实现

总结



前言

Unity shader是计算机图形渲染管线的一部分,是一小段应用程序,是GPU渲染流水线的

一些可高度编程的阶段,而编译出来的最终代码是会在GPU上运行的。Unity Shader告诉计算机在场景中怎样对物体渲染和着色,这个过程包括计算颜色和光照,并将其赋予对象,使其按照我们的想法显示在屏幕上。

在unity中需要配合材质才能达到需要的效果。常见流程是1.创建一个材质,2.创建一个Unity Shader,并把它赋给上步创建的材质,3.把材质赋给要渲染的对象,4.在材质面板中调整Unity Shader的属性得到满意的结果。


一、ShaderLab

ShaderLab作为一种专门为Unity Shader服务的语言。即我们可以编写ShaderLab来生成Unity Shader。Cg(C for Graphic)/ HLSL(High Level Shading Language)/ GLSL(OnpenGL Shading Language)都是着色语言,作为中间语言,即交给GPU可以理解的语言。

因为Microsoft和NVIDIA合作,所以Cg/HLSL实际上是同一种语言。而ShaderLab内部可以嵌套Cg/HLSL语言编写着色代码,需要嵌套在命令CGPROGRAM和ENDCG之间。这里的Cg/HLSL是Unity经封装后提供的,有些原生的函数和用法Unity并没有提供支持。

也可以用GLSL来编写,但是目标平台只有Masc OS X、OpenGL ES 2.0、Linux。代码嵌套在GLSLPROGRAM和ENDGLSL之间。

二、Unity Shader结构

名字:Shader “MyShader”{}

属性:Properties{

Name {“display name”, PropertyType} = DefaultValue

}//材质和Unity Shader交互

重要成员:SubShader{//不少于一个

[Tags]//标签设置,告诉渲染引擎希望怎样以及何时渲染这个对象,可选

[RenderSetup]//状态设置,设置显卡的各种状态,如是否开启深度测试等,可选

Pass{

[Name]//通过这个名称,可以使用UsePass命令直接使用其他Unity Shader的Pass

[Tags]

[RenderSetup]

//other code

//一次完整的渲染流程,如果Pass数目过多,往往会导致渲染性能下降。

//状态和标签同样可以在Pass中声明,不同的是,SubShader中的一些标签设置是 //特定的,如果在SubShader进行了这些设置,将会用于所有的Pass。

}

//Other Passes

}

后路:Fallback ”name”//如果上面所有的SubShader在这块显卡中都不能运行,就用这个最低级的Shader

三、GPU流水线

顶点数据->顶点着色器->装配图元->光栅化->片段着色器->测试和混合->帧缓存

GPU获取到CPU传递的顶点数据之后,流水线开始运作,在顶点着色器中,顶点坐标从模型空间变换到裁切空间,并可以通过shader程序对顶点进行处理,以实现一些特殊的效果。

装配图元阶段将顶点着色器输出的顶点数据装配成指定的几何图元,基本图元包括点线面。光栅化阶段将几何图元转变为片段,确定屏幕坐标中的哪些整形栅格区域被基本图元占用,再分配颜色值和深度值到各个区域。片段在经过视锥体裁切之后被传递到片元着色器,在这个阶段,片元着色器会计算光照、阴影、纹理等所有颜色数据,最终计算出像素的颜色。确定了像素的颜色之后会进入测试和混合阶段,在这个阶段会检测所有像素的深度值,将当前片段的深度值与深度缓存中的数值进行比较,从而判断这个像素前面是否有物体对它进行遮挡,进而决定这个像素是否应该被丢弃,通过测试的像素会与已经绘制好的图像进行混合,从而得到最终的颜色。帧缓存是流水线的最后一站,用于存储将要渲染到屏幕上的像素,等待下一步输出到屏幕上。

四、着色器

Shader一般有顶点/片元着色器、表面着色器、固定管线着色器(正在被淘汰)

顶点/片元着色器:用顶点着色器进行坐标变换、逐顶点光照以及传递数据(模型空间->齐次裁剪空间->计算顶点颜色),用片元着色器进行逐像素的渲染(输入上一阶段对顶点信息的插值,输出颜色值),一般都是同时出现。Cg代码写在Pass语义块中,定义在CGPROGRAM和ENDCG之间。复杂但灵活性更高。通过#pragma vertex vert #pragma fragment frag编译Cg代码片段。

表面着色器:对顶点/片元着色器的更进一层封装,Unity自己创造的一种着色器代码类型,在背后做了很多工作,为我们处理了很多光照细节,使代码量有明显的降低。Cg代码写在SubShader语义块中,定义在CGPROGRAM和ENDCG之间。对细节的把控不如顶点/片元着色器。背后仍旧将其转换成对应的顶点/片元着色器,渲染代价比较大。通过#pragma surface编译Cg代码片段。

五、坐标空间

shader具有很强的封装性,在实际编写shader的过程中,除了调用必须的函数外,还需要进行坐标的转换(如:o.vertex = UnityObjectToClipPos(v.vertex)),在不同的空间中有不同的坐标系:

模型空间(Object Space):float4

定义:以模型(通常为模型的重心)为原点的空间,一般默认物体前方为z轴,右边为x轴,上方为y轴。

世界空间 WS(World Space):float4

定义:一般来说世界空间就是游戏空间,其原点放置在游戏空间的中心。

观察空间 VS(View Space):float4

定义:以相机为原点的坐标空间。(观察空间与屏幕空间不一样,观察空间是一个三维空间,屏幕空间是二维空间)。

裁剪空间 CS(Clip Space):float4

定义:与投影矩阵计算后也被称为齐次裁剪空间(HCS Homogeneous Clip Space),这个用于变换的矩阵叫做裁剪矩阵(Clip Matrix),也被称为投影矩阵(Projection Matrix)。

屏幕空间 SS(Screen Space):float2

定义:当裁剪工作完毕后,就需要进行真正的投影,也就是说需要把视锥体投影到屏幕空间(Screen Space)。经过这一步变换就会得到真正的像素位置,而不是虚拟的三维坐标。

视口空间 VP(ViewPort Space):float2

定义:屏幕空间除以屏幕分辨率得到的就是视口空间(viewport space)中的坐标。

模型空间(本地空间)经模型变换矩阵变换为世界空间

世界空间经视变换矩阵变换为摄像机空间(观察空间)

摄像机空间(观察空间)经裁切矩阵变换为裁切空间(裁切几何体)

裁切空间(裁切几何体)经投影矩阵变换为屏幕空间(得到屏幕像素坐标)

六、编写及实现

通过编写Unity shader最终实现包括但不限于:光照,阴影,纹理,透明,流光,描边,消融,液体,序列帧动画,后期处理等效果。

而在用visua studio编写Unity shader的过程中会发现,没有代码补全,没有报错提示,编写完成运行的时候,在console中报的错误也很模糊,不易找出哪里出现了bug。

ASE是一款Unity提供的付费插件,下载并导入之后,可以在此进行shader的编写,只需进行节点的创建以及设置并进行连线即可,连线完成就意味着代码生成完毕,可当做手写的shader直接赋予材质。不仅如此,ASE还可以在编写过程中,查看中间节点的运行效果。

此外,还可以在C#脚本中创建材质,并找到指定的Unity shader赋予给该材质(避免创建材质并拖动),同时,可在脚本中对材质的各个属性进行设置。


总结

以上就是要讲的内容,本文仅仅简单介绍了unity shader的简单概念,而在实际的编写及应用中还需要更深一步的学习。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,您的第一个问题是关于Unity Shader学习笔记,具体是在表面着色器中控制顶点变换。那么我可以回答您的问题。 在Unity中,表面着色器是一种用于控制物体表面外观的程序。它们可以控制颜色、纹理和光照等方面。而在表面着色器中,我们可以使用顶点变换来控制物体表面的外观。 顶点变换是一个将物体的顶点坐标从局部空间转换为世界空间或者相机空间的过程。在表面着色器中,我们可以通过在CG程序中编写代码来实现顶点变换。以下是一个简单的例子: ```CG // 定义变换矩阵 float4x4 worldMatrix; float4x4 viewMatrix; float4x4 projectionMatrix; // 定义输入结构体 struct appdata { float4 vertex : POSITION; }; // 定义输出结构体 struct v2f { float4 vertex : SV_POSITION; }; // 顶点变换函数 v2f vert (appdata v) { v2f o; o.vertex = mul(mul(mul(v.vertex, worldMatrix), viewMatrix), projectionMatrix); return o; } ``` 在这个例子中,我们定义了三个变换矩阵:世界矩阵、视图矩阵和投影矩阵。然后定义了一个输入结构体appdata,其中包含了顶点的位置信息。输出结构体v2f则只包含了顶点的位置信息,用于传递给像素着色器。 在vert函数中,我们首先将顶点从局部空间转换到世界空间,然后再从世界空间转换到相机空间,最后再从相机空间转换到屏幕空间。这个过程中使用了mul函数来进行矩阵乘法运算。 通过这样的方式,我们可以在表面着色器中控制顶点变换,从而实现对物体表面外观的控制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值