shader和Material的基本关系

Shader(着色器)实际上就是一小段程序,它负责将输入的Mesh(网格)以指定的方式和输入的贴图或者颜色等组合作用,然后输出。绘图单元可以依据这个输出来将图像绘制到屏幕上。输入的贴图或者颜色等,加上对应的Shader,以及对Shader的特定的参数设置,将这些内容(Shader及输入参数)打包存储在一起,得到的就是一个Material(材质)。之后,我们便可以将材质赋予合适的renderer(渲染器)来进行渲染(输出)了。

所以说Shader并没有什么特别神奇的,它只是一段规定好输入(颜色,贴图等)和输出(渲染器能够读懂的点和颜色的对应关系)的程序。而Shader开发者要做的就是根据输入,进行计算变换,产生输出而已。

Unity中Shader的三种基本类型

按照渲染管线的分类,可以把Sharder分成3个类别:

固定功能着色器(Fixed Function Shader)

固定功能着色器为固定功能渲染管线的具体表现。

表面着色器

存在于Unity3D中由U3D发扬光大的一门技术。Untiy3D为我们把Shader的复杂性包装起来,降低shader的书写门槛。

顶点着色器和片段着色器

GPU上含有两个组件:可编程顶点处理器和可编程片段处理器,顶点和片段处理器被分离成可编程单元,可编程顶点处理器是一个硬件单元,可以运行顶点程序,而可编程片段处理器则是一个可以运行片段程序的单元。

顶点着色器

顶点着色程序从GPU前端(寄存器)中提取图元信息(顶点位置、法向量、纹理坐标),并完成顶点坐标空间变换、法向量空间转换、光照计算等操作,最后将计算数据传送到指定寄存器中。

片段着色器

片段程序从上述寄存器中获取需要的数据:纹理坐标与光照信息等,并根据这些信息以及从应用程序传递的纹理信息进行每个片段的颜色计算(纹理查询),最后将处理后的数据传送光栅操作模块。

三种着色器的共同点:

  • 都必须从唯一一个根Shader开始
  • Prooerties参数部分,作用以及语法完全相同。
  • 具体功能都在SubShader里。
  • 都可以打标签
  • 都可以Fallback
  • 都可以处理基本的功能,例如光照漫反射以及镜面反射。但如uv计算效果等高级功能,固定功能着色器无法完成。

三种着色器的不同点

  • 表面着色器没有通道pass{},加了会报错,该着色器已经把具体内容打包在光照模型中了。
  • 固定渲染管线每句代码之后都没有“;”
  • 核心结构不同:
固定渲染管线的核心是:

Material{}以及SetTexture[_MainTex]{}

顶点与片段着色器的核心是:

CGPROGRAM

#pragma vertex vert

#pragma fragment frag

#include "UnityCG.cginc"

ENDCG

表面着色器的核心是:

1.表面着色器使用Unity3D自带光照模型Lambert,也不做顶点处理,只需要一个表面处理函数surf即可。

CGPROGRAM

#Pragma surface surf Lambert

ENDCF

2.这套表示使用的是自己写的光照模型lsyLightModel,并且使用了顶点处理函数vert

CGPROGRAM

#pragma surface surf lsyLightModel vertex:vert

ENDCG

在Unity中如何区分以上三种着色器

  • 没有嵌套CG语言,即代码中没有CGPROGARAM和ENDCG关键字的,就是固定功能着色器。
  • 嵌套CG语言,代码中有surf函数的为表面着色器
  • 嵌套了CG语言,代码中有#pragma vertex name和 #pragma fragment frag声明的,就是顶点着色器&片段着色器。

Unity中Shader的基本框架

Unity中Shader整体的框架写法可以用如下的形式来概括:

Shader "name" { [Properties] SubShaders[Fallback] }

Unity中所有着色器都由关键字shader开始,随后的字符表示着色器的名字,这个名字会显示在Inspector检视面板中,所有的代码都应该放在{}里面。

name

该名字不需要和shader文件名同名,它应该是简单的描述性词语,在name后面加上/能够中Inspector面板中创造出二级菜单(多个/创建多级菜单)。

shader整体框架

如上面的整体框架,我们可以画出下面这图:

从这幅图可以看到,Unity中的shader可以分为以下三个模块:

属性Properties

Properties一般定义中着色器的起始部分。属性模块可以定义一些属性,用来指定那个这段代码有哪些输入。在使用shader的时候可以直接中材质面板里编辑这些属性。Properties块内的语法都是单行的。属性的定义格式如下所示:

属性可以划分为以下几类:

数字与滑动条

name ("display name", Range (min, max)) = number //滑动条调节

name ("display name", Float) = number//数字调节

name ("display name", Int) = number//数字调节

颜色与向量(注意是四元数)

name ("display name", Color) = (number,number,number,number)

name ("display name", Vector) = (number,number,number,number)

贴图

name ("display name", 2D) = "defaulttexture" {}

name ("display name", Cube) = "defaulttexture" {}//立方体贴图

name ("display name", 3D) = "defaulttexture" {}

细节

  1. Range与float的属性只能是单精度值。
  2. 在后面的着色器程序中,属性值通过[name]来访问。而display name将显示在材质检视器中。
  3. 可以使用在属性定义加上等号为每个属性提供缺省值。
  4. 对于纹理(2D, Rect, Cube) 缺省值既可以是一个空字符串也可以是某个内置的缺省纹理:"white", "black", "gray" or"bump"

使用示例


// properties for a water shader
Properties
{
_WaveScale ("Wave scale", Range (0.02,0.15)) = 0.07 // sliders
_ReflDistort ("Reflection distort", Range (0,1.5)) = 0.5
_RefrDistort ("Refraction distort", Range (0,1.5)) = 0.4
_RefrColor ("Refraction color", Color) = (.34, .85, .92, 1) // color
_ReflectionTex ("Environment Reflection", 2D) = "" {} // textures
_RefractionTex ("Environment Refraction", 2D) = "" {}
_Fresnel ("Fresnel (A) ", 2D) = "" {}
_BumpMap ("Bumpmap (RGB) ", 2D) = "" {}
}

子着色器SubShader

可以有一个或者有多个子着色器SubShader(至少有一个),子着色器SubShader中含有一个或者多个通道Pass(也是至少要有一个)。

在Pass中一般可以写以下的代码

Color Color 设定对象的纯颜色,可以是括号中的四个值,也可以是被方框包围的颜色属性名称

Material{Material Block} 材质被用于定义对象的材质属性,关于材质块的内容可以看下面的介绍

Lighting On/Off 定义上述材质块的定义是否有效,On时材质块效果有效,Off时颜色通过Color命令直接给出

SeparateSpecular On/Off 开启独立镜面反射,这个命令会添加高光光照到着色器通道的末尾,因此贴图对高光没有影响。只在光照开启时有效。

ColorMaterial AmbientAndDiffuse | Emission

使用每顶点的颜色替代材质中的颜色集。AmbientAndDiffuse 替代材质的阴影光和漫反射值;Emission 替代 材质中的光发射值。

Pash中材质块Material{}代码写法

上面已经说了,在Pass中可以书写材质块代码用于定义对象的材质属性,如下的代码可以写在材质块中:

Diffuse Color(R,G,B,A);对象基本颜色,漫反射

Ambient Color(R,G,B,A);环境光,当对象被RenderSettings.中设定的环境色所照射时对象所表现的颜色。

Specular Color(R,G,B,A);对象反射高光的颜色

Emission Color 对象自发光

Shininess Number 取值在0-1之间表示加亮时的光泽度

对象完整光照的最终颜色是:

FinalColor=Ambient * RenderSettings ambientsetting + (Light Color * Diffuse + Light Color *Specular) + Emission

即:

最终颜色=环境光反射颜色* 渲染设置环境设置 (灯光颜色漫反射颜色+灯光颜色*镜面反射颜色)+自发光

示例代码:


Shader "我的Shader"
{
Properties
{
_MainColor ("主颜色",Color)=(0,0,0,0)
_AmbientColor("环境光颜色",Color)=(0.8,0.2,0.2,0)
_SpecularColor("放射高光颜色",Color)=(0.8,0.2,0.2,0)
_ShininessNum("光泽度",Range(0,1))= 0.5 //滑动条 }
//---------------------------------【子着色器1】----------------------------------
SubShader
{ //----------------通道---------------
Pass
{
Color(1,0,0,0) //当光照开启时无效。 //----------材质块------------
Material
{
//将漫反射和环境光反射颜色设为相同
Diffuse[_MainColor]
Ambient[_AmbientColor]
Specular[_specularColor]
Shininess[_ShinnessNum]
} //开启光照 //光照影响了颜色
Lighting On
SeparateSpecular On }
}
}

效果:

回滚FallBack

Shader基本框架的最后是指定一个回滚函数Fallback,用来处理所有的子着色器都不能运行时的情况(当目标设备太老时,所有的设备都有其不支持的特性时使用了Fallback),可以认为是一种defult。

Fallback" Diffuse "

关于纹理的载入在下一节讲解。

【unity shaders】:Unity中的Shader及其基本框架的更多相关文章

  1. 【Unity Shaders】Vertex & Fragment Shader入门

    写在前面 三个月以前,在一篇讲卡通风格的Shader的最后,我们说到在Surface Shader中实现描边效果的弊端,也就是只对表面平缓的模型有效.这是因为我们是依赖法线和视角的点乘结果来进行描边判 ...

  2. 【Unity Shaders】初探Surface Shader背后的机制

    转载请注明出处:http://blog.csdn.net/candycat1992/article/details/39994049 写在前面 一直以来,Unity Surface Shader背后的 ...

  3. 【Unity Shaders】学习笔记——渲染管线

    [Unity Shaders]学习笔记——Shader和渲染管线 转载请注明出处:http://www.cnblogs.com/-867259206/p/5595924.html 写作本系列文章时使用 ...

  4. 【Unity Shaders】Diffuse Shading——在Surface Shader中使用properties

    本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...

  5. Unity Shaders Vertex & Fragment Shader入门

    http://blog.csdn.net/candycat1992/article/details/40212735 三个月以前,在一篇讲卡通风格的Shader的最后,我们说到在Surface Sha ...

  6. 【Unity Shaders】使用CgInclude让你的Shader模块化——创建CgInclude文件存储光照模型

    本系列主要參考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同一时候会加上一点个人理解或拓展. 这里是本书全部的插图. 这里是本书所需的代码 ...

  7. 【Unity Shaders】使用CgInclude让你的Shader模块化——Unity内置的CgInclude文件

    本系列主要參考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同一时候会加上一点个人理解或拓展. 这里是本书全部的插图. 这里是本书所需的代码 ...

  8. 【Unity Shaders】使用Unity Render Textures实现画面特效——画面特效中的亮度、饱和度和对照度

    本系列主要參考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同一时候会加上一点个人理解或拓展. 这里是本书全部的插图. 这里是本书所需的代码 ...

  9. 【Unity Shaders】Mobile Shader Adjustment —— 为手机定制Shader

    本系列主要參考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同一时候会加上一点个人理解或拓展. 这里是本书全部的插图.这里是本书所需的代码和 ...

随机推荐

  1. Samsung I9103刷cm-10.1的方法

    按照官方网站的说明一步一步的做下去的时候发现在执行heimdall.exe文件的时候出现“不是win32的应用程序”的错误提示,因此决定按照其它方法安装recovery,然后再刷入CM10.1. sa ...

  2. HTML 学习笔记 JavaScript(简介)

    JavaScript 是世界上最流行的编程语言. 这门语言可用于HTML和web 更可广泛用于服务器.PC.笔记本电脑.平板电脑和智能手机等设备. JavaScript是脚本语言 JavaScript ...

  3. Vs 2015 调试ASP.NET Core修改监听端口

    如何改变监听IP地址和端口?在这里找到了答案:https://github.com/aspnet/KestrelHttpSer... 把Program.cs加一行UseUrls代码如下: using ...

  4. win2008server R2 x64 部署.net core到IIS上出现【Failed to load the dll from [C:\Program Files\dotnet\host\fxr\1.0.1\hostfxr.dll], HRESULT: 0x80070057】错误

    win2008server R2 x64 部署.net core到IIS上出现[Failed to load the dll from [C:\Program Files\dotnet\host\fx ...

  5. 两个经典的Oracle触发器示例(轉)

    [案例一] 题目:--触发器:--添加员工信息,流水号作为自动编号(通过序列生成),--并且判断如果工资小于0,则改为0;如果大于10000,则改为10000. CREATE TABLE emp2(e ...

  6. poj 3255 Roadblocks

    Roadblocks Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 13216 Accepted: 4660 Descripti ...

  7. node基础02:第一个node程序

    1.第一个web服务器 var http = require("http"); http.createServer(function(request, response){ res ...

  8. 一个用react+nodejs实现的笔记本小应用

    寒假回家产品经理一直叮嘱着要继续做学校团队的辣个项目,但是...,我到现在一点都还没做,而且还销声匿迹躲了起来藏了几天,是的我干了票大的,想把项目用一种新的架构实现了,所以这几天一直在偷偷摸摸的做一些 ...

  9. [转]Win2003打不开https的问题

    转自:http://ljl-xyf.iteye.com/blog/2269834 碰到客户做问题是能打开https://www.baidu.com 这个网页 打不开 https://sha256.al ...

  10. 转一篇Unity的相机动画控制

    最近真是忙,连研究细看的时间都没有了,原帖地址:https://alastaira.wordpress.com/2013/11/08/smooth-unity-camera-transitions-w ...