Unity Shader——Writing Surface Shaders(0)
从今天起,开始翻译Unity关于shader的官方文档。翻译水平比较一般,目的主要是通过翻译来提升对shader的见解,也让其他人更容易的了解shader。以下开始正文内容:
编写Surface Shaders
和光交互的shader写起来很复杂,有不同的光照类型、阴影选项、渲染路径(正向渲染和延迟渲染),有时shader需要考虑所有的复杂性。
Unity中的Surface Shader是一个代码生成器,用它来写光照shader(lit shader)相比于使用低阶的顶点/像素shader(vertex/pixel shader)程序,会更加容易。注意Surface Shader中并没有固定的语言和奇幻的东西(magic or ninjas involved)。它仅仅是生成原本必须由手工重复编写的代码。你也可以用Cg/HLSL来写shader代码。
这里有一些例子: Surface Shader Examples、Surface Shader Custom Lighting Examples。
它如何工作
你定义一个“surface 函数”,其输入是你所需要的任意UVs或数据,输出是SurfaceOutput数据结构。SurfaceOutput简单地描述了surface的属性(properties of the surface),如反射率颜色(albedo color)、法线(normal)、散射(emission)、镜面反射(specularity )等。
Surface Shader编译器会确定需要什么输入,有什么输出等,也会产生实际的顶点&像素shader(vertex&pixel shaders),以及渲染路径来处理正向和延迟渲染。
surface标准的输出结构如下:
struct SurfaceOutput
2 {
3 fixed3 Albedo; // 漫反射颜色
4 fixed3 Normal; // 切线空间法线,如果赋值的话
5 fixed3 Emission;
6 half Specular; // 高光强度,范围是0-1
7 fixed Gloss; // specular intensity
8 fixed Alpha; // 透明度
9 };
在Unity 5中,surface shader 也能使用物理光照模型。内建的标准和标准镜面光照模型(见下文)分别使用以下输出结构:
struct SurfaceOutputStandard
{
fixed3 Albedo; // 基础 (漫反射或镜面反射) 颜色
fixed3 Normal; // 切线空间法线,如果赋值的话
half3 Emission;
half Metallic; // 0=非金属, 1=金属
half Smoothness; // 0=粗糙, 1=光滑
half Occlusion; // 遮挡(默认1)
fixed Alpha; // 透明度
};
struct SurfaceOutputStandardSpecular
{
fixed3 Albedo; // 漫反射颜色
fixed3 Specular; // 镜面反射颜色
fixed3 Normal; // 切线空间法线,如果赋值的话
half3 Emission;
half Smoothness; // 0=粗糙, 1=光滑
half Occlusion; // 遮挡(默认1)
fixed Alpha; // 透明度
};
例子
参见:Surface Shader Examples, Surface Shader Custom Lighting Examples and Surface Shader Tessellation。
Surface Shader编译指令
Surface shader放在CGPROGRAM..ENDCG块中,就像其他任何的shader一样。不同处在于:
- 它必须放在SubShader块中,而不是Pass中。Surface shader将会自动编译进多个pass中。
- 它使用#pragma surface ...指令来指示它是Surface shader。
#pragma surface指令如下:
#pragma surface surfaceFunction lightModel [optionalparams]
必须参数
- surfaceFunction — 拥有surface shader代码的Cg函数。此函数应有这样的格式:void surf (Input IN, inout SurfaceOutput o),其中Input是你定义好的结构,它应该包含任何纹理坐标以及surface函数所需的额外的自动变量。
lightModel — 要使用的光照模型。内建的光照模型是基于物理的标准和标准镜面光照模型,以及简单的非物理Lambert(漫反射)和BlinnPhong(镜面)光照模型。参见
- 来学习如何编写。
- 标准光照模型使用SurfaceOutputStandard输出结构,并匹配Unity中的标准(金属工作流)shader。
- 标准镜面光照模型使用SurfaceOutputStandardSpecular输出结构,并匹配Unity中的标准(高光设置)shader。
- Lambert和BinnPhong光照模型是不基于物理的(来自Unity 4.x),但是使用它们的shader在低配电脑上能够渲染地更快。
可选参数
透明度和alpha测试(Transparency and alpha testing)由alpha和alphatest指令控制。通常透明度有两种类型:传统alpha混合(用于对象淡出)或更逼近物理的“混合预乘”(允许半透明的表面保持合适的镜面反射)。开启半透明度使得产生的surface shader代码包含blending指令:基于给定的变量,开启alpha裁剪将会在生成的像素shader中进行碎片丢弃。
alpha
或alpha:auto — 将会选择fade-transparency (同
alpha:fade
)作为简单的光照函数,选择premultiplied transparency (同alpha:premul
)作为物理光照函数。alpha:fade
— 允许传统的透明度渐隐。alpha:premul
— 允许预乘alpha透明度。alphatest:VariableName
— 允许alpha裁剪透明度。截断值是一个名为VariableName的float类型变量。你还可以使用addshadow指令来生成合适的投影通道。keepalpha
— 默认alpha通道中的不透明度为1.0(白色),无论输出结构中的Alpha是多少或者光照函数的返回值是多少。decal:add
— 附加的贴花shader(如terrain AddPass)。这对位于其他表面正上方和使用附加混合的对象来说是有意义的。decal:blend
— 半透明贴花shader。这对位于其他表面正上方和使用alpha混合的对象来说是有意义的。
定制修改器函数(Custom modifier functions)能够用来改变或者计算输入的顶点数据,或者改变最终计算出的片段颜色。
vertex:VertexFunction
— 定制顶点修改器函数. 此函数在生成的顶点shader的开始处被调用,可以修改或计算预顶点数据,参见 Surface Shader Examples。finalcolor:ColorFunction
— 定制的最终颜色修改器函数。参见Surface Shader Examples。
阴影和镶嵌(Shadows and Tessellation)— 附加指令,用于控制阴影和镶嵌的处理。
addshadow
— 生成一个投影通道。一般还要使用定制顶点修改器,这样投影也能获取任何程序上的顶点动画。 当shader通过fallback来使用投影时,通常不需要任何特别的阴影处理。fullforwardshadows
— 支持 Forward 渲染路径中所有的光照阴影模型。默认shader只支持正向渲染中来自单方向光产生的阴影。如果你需要用点光源或聚光光源来产生阴影,使用该指令。tessellate:TessFunction
— 使用DX11 GPU 镶嵌; 该函数计算镶嵌因子。详情参见 Surface Shader Tessellation。
代码生成选项 — 默认生成的surface shader代码会尝试去处理所有可能的光照/阴影/光照贴图场景。尽管如此,在某些情况下你并不需要其中一些,你可以调整生成的代码来跳过它们。这样就能产生更小、加载速度更快的shader。
exclude_path:deferred
,exclude_path:forward
,exclude_path:prepass
- 对于给定的渲染路径(分别是Deferred Shading, Forward 和 Legacy Deferred),不生成相应的通道。noshadow
— 在此shader中关闭所有支持阴影功能。noambient
— 不应用任何环境光或光照探测(light probes)。novertexlights
— 不在正向渲染中应用任何光照探测或预顶点光照。nolightmap
— 在此shader中关闭所有支持光照贴图功能。nodynlightmap
— 在此shader中关闭支持运行时动态全局光照(runtime dynamic global illumination)功能。nodirlightmap
- 在此shader中关闭支持方向光照贴图功能。nofog
— 关闭内建的支持所有雾效果功能。nometa
— 不产生“meta”通道(该meta用来由光照贴图和动态全局光照提取表面信息)。noforwardadd
— 关闭Forward 渲染附加通道。 这使得shader支持单方向完全光照,以及所有其他由每个顶点/SH计算的光照。同时使得shader更小。
混合选项
softvegetation
— 当柔性植被开启时,surface shader才会被渲染。interpolateview
— 在顶点shader中计算视线方向并进行插值,而不是在像素shader中进行计算。这使得像素shader更快,但会多消耗一个纹理插值器。halfasview
— 将half-direction 向量,而不是视线方向向量,传递给光照函数。Half-direction 将被逐顶点计算和单位化。这会更快,但不会完全正确。approxview
— 在Unity 5.0中被移除,请用interpolateview
替代。dualforward
- 在forward渲染路径中使用dual lightmaps 。
要了解使用上述不同选项所带来确切的变化,使用Shader Inspector中的“Show Generated Code” 按钮将会有所帮助。
Surface Shader 输入结构
输入结构 Input
通常有shader所需的任意纹理坐标。纹理坐标必须命名为“uv”+“纹理名称”(或者以“uv2”开头,来使用第二个纹理坐标集)。
输入结构中还能放入一下额外的变量:
float3 viewDir
— 将会包含视线方向,用来计算视差影响,边缘光照等。float4
withCOLOR
semantic — 将会包含每个顶点插值后的颜色。float4 screenPos
— 将会包含反射或屏幕空间影响下的屏幕空间坐标。float3 worldPos
— 将会包含世界空间坐标。float3 worldRefl
— 如果surface shader没有赋值o.Normal,将会包含世界反射向量。参见例子:Reflect-Diffuse shader。float3 worldNormal
— 如果surface shader没有赋值o.Normal,将会包含世界法向量。float3 worldRefl; INTERNAL_DATA
— 如果surface shader没有赋值o.Normal,将会包含世界法向量。为了获得逐像素法线贴图的反射向量,请使用WorldReflectionVector (IN, o.Normal)。参见例子:
Reflect-Bumped shader。float3 worldNormal; INTERNAL_DATA
— 如果surface shader没有赋值o.Normal,将会包含世界法向量。为了获得逐像素法线贴图的法向量,请使用WorldNormalVector (IN, o.Normal)。
Surface shaders 和 DirectX 11
目前,surface shader编译管道的部分内容并不能理解 DirectX 11-特定的HLSL 语法, 所以如果你在使用HLSL特性,诸如StructuredBuffers, RWTextures 和其他非DX9 语法,你必须将之包含在只针对DX11的预处理器宏中。详情参见Platform Specific Differences 。
Unity Shader——Writing Surface Shaders(0)的更多相关文章
- Unity Shader——Writing Surface Shaders(3)——Surface Shader Lighting Examples
Surface Shader 光照例子 这里有一些自定义光照模型和Surface Shaders的例子.通常的Surface Shader例子在这里. 由于延迟光照在某些自定义的逐材质光照模型中表现得 ...
- Unity Shader——Writing Surface Shaders(2)——Custom Lighting models in Surface Shaders
Surface Shader中的自定义光照模型 当你在编写 Surface Shaders 时,是在描述一个表面的属性(反射颜色.法线……),而且光的交互过程是由一个光照模型来计算的.内建的光照模型有 ...
- Unity Shader——Writing Surface Shaders(1)——Surface Shader Examples
这里有Surface Shader的一些例子.下面的这些例子关注使用内建的光照模型:关于如何使用自定义光照模型的例子参见Surface Shader Lighting Examples. 简单 我们将 ...
- Writing Surface Shaders
[Writing Surface Shaders] Writing shaders that interact with lighting is complex. There are differen ...
- [Unity Shader]Shader前述
什么是Shader Shader,也就是着色器,它的工作就是读取你的网格并渲染在屏幕上.Shader可以定义一些属性,你会用它来影响渲染模型时所显示的效果.当存储了这些属性的设置时,就是一个Mat ...
- Unity Shader 基础(3) 获取深度纹理
Unity提供了很多Image Effect效果,包含Global Fog.DOF.Boom.Blur.Edge Detection等等,这些效果里面都会使用到摄像机深度或者根据深度还原世界坐标实现各 ...
- Unity shader 官网文档全方位学习(一)
转载:https://my.oschina.net/u/138823/blog/181131 摘要: 这篇文章主要介绍Surface Shaders基础及Examples详尽解析 What?? Sha ...
- 【Unity Shader】(六) ------ 复杂的光照(上)
笔者使用的是 Unity 2018.2.0f2 + VS2017,建议读者使用与 Unity 2018 相近的版本,避免一些因为版本不一致而出现的问题. [Unity Sha ...
- unity shader 编辑器扩展类 ShaderGUI
这应该unity5才出的新功能了,今天看文档时刚巧看到了,就来尝试了一下. 效果如图: shader 的编辑器扩展分为2种方法: 是通过UnityEditor下的ShaderGUI类来实现的,形式比较 ...
随机推荐
- git github 异常
git :版本控制工具 github:项目托管 git clone failed:git是否安装正确 github commit failed:github 是否账号 / 密码是否正确(密码错误也可以 ...
- Python中类的特殊方法详解
本文和大家分享的主要是python语言中类的特殊方法相关用法,希望对大家有帮助. 构造序列 1._len_(self) 2._getitem_(self,key) 3._setitem_(self,k ...
- 如何让popWindow显示在view上方
看了bilibili的客户端搜索按钮,很喜欢大爱!自己也想做个类似的(相似度 10% 哈哈) popWin的出现退出动画也可以自己设定,用过其方法setAnimationStyle(R.style.x ...
- 导出Excel 有身份证时注意
if (this.GridView1.Rows.Count != 0) { HttpContext.Current.Response.Clear() ...
- LoarRunner11使用异常及解决方案
1:使用VuGen录制后出现“由于另一个程序正在运行中,此操作无法完成.请选择切换到来激活正在运行中的程序,并更正问题”,点击“切换到”无效果. 解决:在“运行”中输入“msconfig”,选择“启用 ...
- C/C++ 如何来自动优雅的涮别银家的贴子
被涮屏涮烦了,就分享一下如何用低调的c/c++来涮别人家的屏吧! 此处埋下三颗雷! 这不是啥新知识,也不是什么浅显的代码.下面,来淘淘这份经验,呼呼 我们要了解Web browser 这个控件,因为到 ...
- 转Global.asax文件
Global.asax 文件是什么 Global.asax 文件,有时候叫做 ASP.NET 应用程序文件,提供了一种在一个中心位置响应应用程序级或模块级事件的方法.你可以使用这个文件实现应用程序 ...
- Android开发--RadioButton的应用
1.简介 RadioButton为单选按钮,当一个按钮被选中后,点击其他按钮无法使上一个按钮变为未选中状态.RadioGroup是可以容纳多个RadioButton的容器, 通过使用RadioGrou ...
- UE3:SkeletalMesh的绘制流程
[目标] SkeletalMesh的绘制流程 [思路] 1 顶点缓冲流 静态数据流向 动态数据流向(紫红色箭头) 2 FGPUSkinVertexFactory.ShaderDataType.Bone ...
- log4net.NoSql +ElasticSearch 实现日志记录
前言: 前两天在查找如何扩展log4net的日志格式时找到一个开源项目Log4net.NoSql,它通过扩展Appender实现了把日志输出到ElasticSearch里面.顺藤摸瓜,发现涉及的项目还 ...