Unity之Shader学习基础篇《一》

最近在学习Shader,将学习的一些心得和案例以及基础知识罗列了一下。这一篇是unity之Shader的基础篇之基础,更多的是一些概念。该篇将分以下几个部分:

1、什么是Shader?

2、GPU和Cg语言

3、Unity中使用Cg语言如何编写Shader?

1、什么是Shader?

1.1、Shder的概念:Shader即着色器,是一款运行在GPU上的程序,用以对三维物体进行着色处理,光与影的计算,纹理颜色的呈现等,从而将游戏引擎中一个个作为抽象的几何数据存在的模型、场景和特效,以和真实世界类似的光与影的形式呈现于人们眼中。

1.2、Shader和Material的关系:Shader负责将输入的Mesh(网格)以指定的方式和输入的贴图或者颜色等组合起来输出,绘图单元可以依据这个输出来讲图像绘制到屏幕上。输入的贴图或者颜色,加上对应的Shader以及Shader的特定的参数设置,将这些打包存储在一起就得到了一个Material。

姑且可以这么认为Shader就相当于高级语言里面的一个类,当我们需要对某一具体物体使用此Shader是,我们就需要先实例化次shader,从而得到一个它的对象,其实Mataerial就相当于Shader的一个对象。这样我们就能理解在Unity中同样的材质球在被修改后,其他物体挂载了此材质球也会被修改。而如果是使用相同Shader新建的别名材质球,就不会受影响。

2、GPU和Cg语言

2.1、Gpu图形绘制管线分为三个主要阶段:

  1. 应用程序阶段:使用高级编程语言(C、C++、Java等)进行开发,主要和CPU进行打交道,诸如碰撞检测、场景图建立、空间八叉树更新、视锥裁剪等景等经典算法在此阶段执行
  2. 几何阶段:主要负责顶点坐标变换、光照、裁剪、投影以及屏幕映射,该阶段基于GPU进行运算,在该阶段之后得到了经过变化和投影之后的顶点坐标、颜色以及纹理坐标——《实时计算机图像学》
  3. 光栅阶段:基于几何阶段的输出数据,为像素正确配色,以便绘制完整的图形,该阶段进行的都是单个像素的操作,每个像素的信息存储在颜色缓冲器(Color buffer或者Frame buffer)中,光栅化得到的屏幕坐标值通常都是浮点型的而像素都是整数表示,通常最后绘制到屏幕上的都是这两个整数点之间进行插值得到线段上某些点上。

(光栅化:将几何图元变为二维图像的过程)

2.2、GPU上的两个组件:Vertex Program和Fragment Program

  1. Vertex Program:从GPU中提取图元信息(顶点位置、法向量、纹理坐标等)完成顶点坐标空间转换,法线向量空间转换光照计算等操作。

  2. Fragment Program:将Vertex Program的输出作为输入对每个片段的颜色进行计算,最后将处理后的数据送光栅操作模块进行光栅化。
  3. 什么是片段,它和像素有什么不一样?:片段其实就是所有的三维顶点在光栅化之后得到的数据集合,这些数据没有经过深度值的比较,而在屏幕上显示的像素都是经过深度值比较的。

(Fragment Program还有一个突出的特点就是拥有检索纹理的能力,纹理其实就是数组)

2.3、坐标空间

屏幕是二维的,GPU所需要的就是将三维的数据绘制到二维的屏幕上,这样就有坐标空间的转换。根据顶点坐标变换的先后顺序,主要有如下几个坐标空间

  1. Object Space,模型坐标空间:这个过程才有真正意义上的投影,投影主要有两种方法:正投影(也称为平行投影)和透视投影。而裁剪是一个较大的概念,为了减少需要绘制的顶点个数,而识别指定区域内或区域外的图形部分的算法都称之为裁剪,裁剪算法包括:视域剔除、背面剔除、遮挡剔除和视口裁剪。
  2. World Space,世界坐标空间:顶点法向量的计算在此过程
  3. Eye Space,观察坐标空间,在Unity中即为虚拟摄像机坐标空间:以虚拟摄像机为原点,由视线方向、视角和远近平面共同组成一个梯形的三维空间
  4. Clip and Project Space,屏幕坐标空间

并非是先裁剪再投影,因为在不规则的物体中进行裁剪并非容易的事情,裁剪被单独安排在一个单位立方体中进行,这个立方体被称为CVV,CVV的近平面的X,Y坐标对应屏幕像素坐标,Z坐标则代表画面像素深度。视点坐标到屏幕坐标由三部分组成:用透视变换矩阵把顶点从视锥体中变换到裁剪空间的CVV中、在CVV进行图元裁剪、屏幕映射。

2.3、Cg语言

2.3.1、Cg支持7中数据类型:

  1. float,32位浮点数据
  2. half,16位浮点数据
  3. int,32位整形数据
  4. fixed,12位定点数
  5. bool,布尔数据
  6. sampler*,纹理对象的句柄:sampler、sampler1D,sampler2D,sampler3D,samplerCUBE,samplerRECT
  7. string,字符类型

2.3.2、内置的向量类型是基于上述数据类型

  1. float4为float类型的4元向量,bool3为bool类型的三元向量,向量最长不能超过4元
  2. Cg中向量、矩阵与数据是完全不同的、向量和矩阵是内置的数据类型,而数据是一种数据结构,在其他高级语言中数组,向量和矩阵都是一种数据结构

2.3.3、Cg表达式与控制语句:关系操作符、逻辑操作符、数学操作符、位移操作符以及Swizzle操作符:

float4(a, b, c, d).xyz 等价于 float3(a, b, c)

float4(a, b, c, d).xyy 等价于 float3(a, b, b)

float4(a, b, c, d).wzyx 等价于 float4(d, c, b, a)

float4(a, b, c, d).w 等价于 float d

中float a 和float1 a是基本等价的,两者可以进行类

型转换;float、bool、half等基本类型声明的变量也可以使用swizzle操作符。例

如:

float a = 1.0;

float4 b = a.xxxx;

2.3.4、Cg语言的其他一些特性

  1. 数组形参:Cg中不存在指针机制,数组作为函数形参传递的是数组的完全拷贝注意:形参数组不必指定长度,如果指定了长度在调用函数是实参数组的长度和形参数组的长度必须一致,最好不要指定长度。
  2. CG函数重载方式和C++基本一致
  3. 由于着色程序分为定点程序很片段程序,两者对应着图形流水线上的不同阶段,所以两个程序各有且只有一个入口函数,当程序今夕编译时必须要指定入口函数,除非入口函数为main.
  4. 如何确定定点和片段程序的入口函数?顶点程序:接收应用程序传递的顶点数据(通常位于模型坐标空间)进行坐标空间转换和光照处理,输出投影坐标和计算得到的光照颜色片段程序:接收从顶点程序输出的数据并进行像素颜色计算。
  5. 所以通常通过观察程序的输入输出语义绑定就可以区分函数对应的是顶点程序还是片段程序

2.3.5、齐次坐标的重要性

齐次坐标的本质是什么?

1、两条平行线是否可以相交一点?

在欧氏几何空间,同一平面的两条平行线不能相交,这是我们都熟悉的一种场景。

然而,在透视空间里面,两条平行线可以相交,例如:火车轨道随着我们的视线越来越窄,最后两条平行线在无穷远处交于一点。

2、为什么叫齐次坐标?

简而言之,齐次坐标就是用N+1维来代表N维坐标

3、齐次坐标的本质是什么?

我们可以在一个2D笛卡尔坐标末尾加上一个额外的变量w来形成2D齐次坐标,因此,一个点(X,Y)在齐次坐标里面变成了(x,y,w),并且有

X = x/w

Y = y/w

例如,笛卡尔坐标系下(1,2)的齐次坐标可以表示为(1,2,1),如果点(1,2)移动到无限远处,在笛卡尔坐标下它变为(∞,∞),然后它的齐次坐标表示为(1,2,0),因为(1/0, 2/0) = (∞,∞),我们可以不用”∞"来表示一个无穷远处的点了

证明两条直线可以相交:

3、Unity中如何使用Cg编写Shader

3.1、Shader程序的基本结构:首先是一些属性定义,用来指定这段代码将有哪些输入。接下来是一个或者多个的子着色器,在实际运行中,哪一个子着色器被使用是由运行的平台所决定的。子着色器是代码的主体,每一个子着色器中包含一个或者多个的Pass。在计算着色时,平台先选择最优先可以使用的着色器,然后依次运行其中的Pass,然后得到输出的结果。最后指定一个回滚,用来处理所有Subshader都不能运行的情况(比如目标设备实在太老,所有Subshader中都有其不支持的特性)。

3.2,Shader的程序:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

Shader"Cg
basic shader"

{
//
定义Shader的名字

    SubShader{//
Unity会选择最适合GPU的subshader块

        Pass{//
一个shader会有多个Pass块

            CGPROGRAM//
开始Unity的shader

#pragma
vertex vert //定义一个顶点程序,名为vert

#pragma
fragment frag//定义一个片段程序,名为frag

    float4
vert(float4 vertexPos : POSITION) : SV_POSITION

    {

                returnmul(UNITY_MATRIX_MVP,
vertexPos);

//这行代码的作用是使用Unity内置的矩阵UNITY_MATRIX_MVP将顶点输入参数vertexPos进行转换,并将转换后的值作为返回顶点程序的输出参数,片段程序的输入参数

    }

    float4
frag(
void)
: COLOR
//
f片段程序

    {

        returnfloat4(1.0,
0.0, 0.0, 1.0);)

    //该片段程序返回一个片段输出参加(也即语义COLOR),该代码的意思是设置一个不透明的红色((red
= 1, green = 0, blue = 0, alpha = 1))

    }

ENDCG//
here ends the part in Cg

}

    }

}

时间: 2024-07-30 13:44:45

Unity之Shader学习基础篇《一》的相关文章

Unity的shader学习2

下面继续看基于surface的shader代码,基本与Vertex&Fragment shader差不多,只是不能写pass,然后只需要声明surface函数,就能处理所有的事情. 1 Shader "T1/Hero/Diffuse" { 2 Properties { 3 _MainTex ("Base (RGB)", 2D) = "white" {} 4 _Color ("Main Color", Color) =

Python学习基础篇第一篇——快速入门(适合初学者)

一.Python学习基础篇第一篇--(快速入门) 建议从Python2.7开始学习,Python2.7可以支持扩展大量的第三方类库,是目前比较成熟的版本 编写代码的软件推荐将python自带的IDLE和PyCharm集成IDE结合起来使用 1.1 Python命令行 Python命令行将以 >>> 开始,比如 >>>print 'Hello World!' 对于验证简单的命令可以在python自带的IDLE中完成  1.2 在Python自带的IDLE写一段小程序 在所

Docker虚拟化实战学习——基础篇(转)

Docker虚拟化实战学习--基础篇 2018年05月26日 02:17:24 北纬34度停留 阅读数:773更多 个人分类: Docker Docker虚拟化实战和企业案例演练 深入剖析虚拟化技术概念和应用场景 虚拟化,一是项技术--,是一种资源解决方案. 虚拟化技术是将物理资源转变为逻辑上可以管理的资源,以打破物理结构之间的壁垒,使计算元件运行在虚拟的基础上,而不是真实的物理资源上. 通过虚拟化技术,可以将物理资源转变为逻辑资源(虚拟机),应用程序服务运行在虚拟资源上,而不是真实的物理机上.

[转]C++学习–基础篇(书籍推荐及分享)

C++入门 语言技巧,性能优化 底层硬货 STL Boost 设计模式 算法篇 算起来,用C++已经有七八年时间,也有点可以分享的东西: 以下推荐的书籍大多有电子版.对于技术类书籍,电子版并不会带来一个好的阅读体验.如果喜欢,最好找纸版(图书馆是个好去处):电子版更适合作为一个参考书籍常备电脑. 我将分为基础篇.Windows篇.和Linux/Unix篇 三个部分来介绍这些经典书籍:   C++入门 <C++ Primer> 我的C++入门读物是<C++大学教程>,这本书800多页

性能测试学习基础篇--随笔3

继续做个随笔--现在开始主要讲Jmeter的基础运用知识 -Jmeter基础篇- Jmeter常用术语: 1.采样器Samplers:采样器是jmeter测试脚本的基础单元,用户可以用它来向服务器发出一个特定的请求,采样器会在超时前等待服务器的响应. 2.逻辑控制器Logic Controllers:用户通过逻辑控制器来控制jmeter测试脚本的执行顺序,以便测试能够按照用户期望的顺序和逻辑执行. 3.监听器Listeners:监听器被用来收集测试结果信息,并以用户指定的方式加以展示. 4.配置

【Unity】Shader编程 基础总结

Shader编程一直是一个比较难入门难上手的主题,本篇对Unity Shader编程的一些基础和要点进行了总结. 包括Shader编程相关知识图谱.Shader编程相关数据类型.Shader核心结构体等(后续继续补充). 每个部分相互独立,可以单独参考,亦可作为一个整体参考. 博文首发:http://blog.csdn.net/duzixi 一.Shader编程知识图谱 个人对Shader编程的理解凝在四个字:色即是光. 无论是要手写Shader程序,还是利用各类Shader制作插件(如Shad

Laravel学习基础篇之--路由

终于还是决定再多学一门重量级框架,当然首选必备还是被称为最优雅的Web开发框架--Laravel 对于框架的入门,首先了解它的路由规则是先前必备的,以下是laravel 中几种常见的基础路由规则 //基础路由//GETRoute::get('basic',function (){ return 'Im,GET'; }); //POSTRoute::post('basic2',function (){ return 'Im,Post'; }); //多请求路由(两种方式:match & any m

Bat 脚本学习 (基础篇)

[转]Bat 脚本学习 2015-01-05 14:13 115人阅读 评论(0) 收藏 举报 基础部分: ====================================================================== 一.基础语法: 1.批处理文件是一个“.bat”结尾的文本文件,这个文件的每一行都是一条DOS命令.可以使用任何文本文件编辑工具创建和修改. 2.批处理是一种简单的程序,可以用 if 和 goto 来控制流程,也可以使用 for 循环. 3.批处理的

Flume搭建及学习(基础篇)

转载请注明原文出处:http://www.cnblogs.com/lighten/p/6830439.html 1.简介 该文主要是翻译官方的相关文档,源地址点击这里.介绍一下Flume的一些基本知识和搭建方法. Apache Flume是一种分布式,可靠和可用的系统,用于高效收集,聚合和将许多不同的来源的大量日志数据移动到集中式数据存储. Apache Flume的使用不仅限于日志数据聚合. 由于数据源是可定制的,因此可以使用Flume来传输大量事件数据,包括但不限于网络流量数据,社交媒体生成