目录:Unity Shader - 知识点目录(先占位,后续持续更新)
原文:Writing Surface Shaders
版本:2019.1
编写表面着色器
编写与光照有交互的shader是复杂的。有许多不同的光源类型,不同的阴影选项,不同的rendering paths(渲染路径)(forward(正向渲染)和deferred rendering(延迟渲染)),以至于这种shader是很复杂的。
Unity中的Surface Shaders(表面着色器)是一种代码生成方法,用此方式编写光照着色器比使用相对低级的vertex/pixel shader programs(顶点/像素着色器程序)容易得多。注意,Surface Shaders并没有自定义语言,魔术或忍术的神奇之术;它仅仅是生成一些你得手写的代码。
一些例子,可看看Surface Shader Examples(表面着色器的例子)和Surface Shader Custom Lighting Examples(表面着色器自定义器光照例子)。
如何工作的
您定义了一个"surface function"(surface函数),它接受您需要的任何uv或数据作为输入,并填充输出结构SurfaceOutput。SurfaceOutput是surface的基础描述数据(有Albedo颜色,法线,自发光,高光,等等)。你可以使用HLSL编写这些代码。
Surface Shader编译器会根据你哪些所输入的,哪些所填充到输出的,等等来生成精准需要的vertex&pixel shaders,以及生成需要的forward和deferred rendering需要的pass。
Surface shader的标准Output数据结构如下:
struct SurfaceOutput
{
fixed3 Albedo; // diffuse color - 漫反射颜色
fixed3 Normal; // tangent space normal, if written - 切线空间的法线
fixed3 Emission; // 自发光颜色
half Specular; // specular power in 0..1 range - 高光的强度,数值范围:0~1
fixed Gloss; // specular intensity - 也是控制高光的数值
fixed Alpha; // alpha for transparencies - 透明度的alpha值
};
在Unity Surface shaders中你可以使用PBR。内置的Standard和StandardSpecular的光照模型(查看下面)分别使用了不一样的输出数据结构:
struct SurfaceOutputStandard
{
fixed3 Albedo; // base (diffuse or specular) color - 基础色(漫反射或高光色)
fixed3 Normal; // tangent space normal, if written - 切线空间的法线
half3 Emission; // 自发光
half Metallic; // 0=non-metal, 1=metal - 金属性,0:完全没有,1:高金属性
half Smoothness; // 0=rough, 1=smooth - 光滑度,0:粗糙的,1:光滑的
half Occlusion; // occlusion (default 1) - AO(Ambient Occlusion) 的基础系数
fixed Alpha; // alpha for transparencies - 透明度
};
struct SurfaceOutputStandardSpecular
{
fixed3 Albedo; // diffuse color - 漫反射颜色
fixed3 Specular; // specular color - 高光色
fixed3 Normal; // tangent space normal, if written - 切线空间的法线
half3 Emission; // 自发光
half Smoothness; // 0=rough, 1=smooth - 光滑度,0:粗糙的,1:光滑的
half Occlusion; // occlusion (default 1) - AO(Ambient Occlusion) 的基础系数
fixed Alpha; // alpha for transparencies - 透明度
};
例子
查看Surface Shader Examples, Surface Shader Custom Lighting Examples和Surface Shader Tessellation页面。
表面着色器的编译指令
Surface shader代码放在CGPROGRAM…ENDCG块之间,和其他的Shader一样。但不同的有:
#pragma surface指令:
#pragma surface surfaceFunction lightModel [optionalparams]
必要的参数
可选参数
Transparency and alpha testing(透明的与alpha测试的) 有alpha和alphatest指令控制。透明效果一种两种:传统的alpha混合(用于淡出的对象)或是像物理的"premultiplied blending"(预乘混合)(允许半透明保留适当的高光反射)。启用半透明将会让surface shader生成的代码包含blending指令;但请用alpha cutout(alpha剔除)将会在pixel shader生成处理fragment discard(片段禁用/剔除)的代码。剔除alpha是需要指定数值的:
Custom modifier functions(自定义的修改器函数) 可用于修改或计算传入的顶点数据,或修改fragment片段最终计算的颜色。
Shadows and Tessellation(阴影与曲面细化) - 该额外的指令能用于控制阴影也曲面细化如何处理。
Code generation options(代码生成选项) - 默认的Surface shader生成的代码都尽可能的处理lighting(光照)/shadowing(阴影)/lightmap(光源映射)场景。但某些情况你是不需要部分功能的,这就可以调整生成代码选项来跳过不需要的功能。减少功能还可以让shader变得更小,载入更快。
其他选项
要查看上面使用不同选项的不同之处,可以在Shadaer Inspector中使用"Show Generated Code"按钮查看帮助。
Surface Shader 输入数据的结构体
输入数据结构体Input通常都会有一些纹理坐标。纹理坐标必须命名开头为"uv",后跟纹理名称(或者以"uv2"开始使用第二个纹理坐标)。(如:我有的Property _MainTex纹理,那么Input 中与此Property的名对应使用,就得命名uv名称为:uv_MainTex)
Input结构体可以放的数值:
Surface Shader与DirectX 11 HLSL 的语法
当前Surface Shader的一部分编译管线没有遵守DirectX 11-specific HLSL的语法,所以,如果你使用了HLSL的一些功能特性,如:StructuredBuffers,RWTextures等等 非DX9语法,您不得不将其封装到只有DX1的预处理器宏中。
查看 Platform Specific Differences和Shading Language页面了解更多详情。