unity修炼之路Unity3D游戏开发首页投稿(暂停使用,暂停投稿)

Unity中Shader表面着色器基础

2016-04-17  本文已影响2917人  Unity云中客

写与灯光交互的Shader是很复杂的,因为有不同的灯光类型(light Type),不同的阴影选项(Shadow Options),不同的渲染路径(renderingPath:forward,deferred rendering),所以Shader应该以某种方式来处理所有的复杂情况。

Unity中的==Surface Shaders==是一种比使用底层的顶点/像素着色器程序(vertex/pixel shader programs)写起来更为简单通用的方式。 surfaceShaders 也是用Cg/hlsl来写。

How It Works

首先你需要定义一个"Surface"函数来获取任何uv信息或者你需要的数据作为输入,最后会填充在输出结构体"SurfaceOutput"里,SurfaceOutput是对表面属性的基本描述(例如Albedo,Normal,Emission,Specular等等),你可以将这些代码写在cg/hlsl里。

然后Surface Shaders计算编译需要哪些输入数据,以及哪些输出被填充等等,然后生成原生的vertex/pixed shaders,同时渲染通道会去处理forward和deferred渲染。

标准的表面着色器输出结构:

struct SurfaceOutput
{
    fixed3 Albedo;  // diffuse color /反射颜色
    fixed3 Normal;  // tangent space normal, if written(法向量)
    fixed3 Emission;//自发光颜色
    half Specular;  // specular power in 0..1 range//镜面反射度
    fixed Gloss;    // specular intensity(光泽度)
    fixed Alpha;    // alpha for transparencies(透明度)
};

在Unity5中,SurfaceShader也可以使用光照模型的基本物理属性。内置的"Standard"和"StandardSpecular"光照模型分别使用下面的输出结构体:

(Standard和StandardSpecular光照模型对应普通没有物理的的Lambert何BlinnPhong光照模型)

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,金属度
    half Smoothness;    // 0=rough, 1=smooth,光滑度
    half Occlusion;     // occlusion (default 1),遮挡率
    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
    half Occlusion;     // occlusion (default 1)
    fixed Alpha;        // alpha for transparencies
};

对比SurfaceOutput和SurfaceOutputStandard,会发现前者的结构中Specular和Gloss被替换成在后者的结构中的Metallic,Smoothness,Occlusion三个属性。这三个属性就是Unity5里新加的物理属性。同样比较SurfaceOutputStandard和SurfaceOutputStanaedSpecular结构体,发现Metallic属性被Specular属性替换掉。

所以Unity5.x基于光照模型添加的基本物理属性应该是在Specular镜面发射上做了一些处理,添加了遮挡和粗糙度的属性以及混合Specular而形成的Metallic属性,使物体表面具有更加接近真实的物理光泽效果,从而减轻开发者自己书写相似效果的工作量。

##Surface Shader compile directives****(表面着色器编译指令)
表面着色器和其它Shader一样被放在CGPROGRAM……ENDCG块中执行,不同的是:

“#Pragma surface” 指令是:

#pragma surface surfaceFunction lightModel [optionalparams]

必要参数

****可选参数****

Transparency和Alpha testing是由alpha和alphatest指令控制。不透明度主要分为两种:传统的alpha混合(一般用于淡出物体)或更加看似物理的“premultiplied blending”(允许半透明表面保留适当的镜面反射效果)。使半透明能够使用生成的表面着色器代码包含blending指令,而能够让alpha基于已有的变量剔除被生成的pixed shader丢弃的片段。

自定义函数可以被用来改变或计算来自顶点的数据,或者改变最后计算得出的片段颜色。

Shadows and Tessellation(阴影和镶嵌花纹),可以控制如何处理阴影和镶嵌花纹的额外指令。

Code Generation(代码生成) 选项,通过默认生成的表面着色器代码试图去处理各种可能的lighting/shadowing/lightmap情况,然而有些情况下你不需要他们中的一些内容,这里你就可以调整代码生成去跳过它们。这样的结果会使你的shader更小并且被更快的加载。

其它

表面着色器输入结构

在输入结构体Input中通常会有一些shader使用需要的纹理坐标。纹理坐标必须以uv命名开头,后面街上纹理名称(或者以uv2开头,使用第二个纹理坐标)。

其它可以被放到Input结构中的值有:

现在有部分表面着色器编译管线不支持DX11上特殊的HLSL语法,所以如果你使用HLSL一些特性,比如StructuredBuffers,RWTextures和其它的DX9没有的特性,可以使用宏包裹住。

上一篇 下一篇

猜你喜欢

热点阅读