shader基础

来源:互联网 发布:c语言函数写法 编辑:程序博客网 时间:2024/04/29 22:35

shader基本语法

1.
Shader名字

"ShaderLab Tutorials/TestShader"{    // ...}

2014-0720-1707-17-42.png
Shader的名字会直接决定shader在material里出现的路径

2.
SubShader(渲染方案)
一个Shader有多个SubShader一个SubShader可理解为一个Shader的一个渲染方案。即SubShader是为了针对不同的显卡而编写的。每个Shader至少1个SubShader、理论可以无限多个,但往往两三个就足够。
SubShader和显卡的兼容性判断,和SubShader的标签、Pass的标签和显卡支持的“Unity渲染路径”有关。这些都会在下面逐一提到。

3.
SubShader的Tag

Shader "ShaderLab Tutorials/TestShader" {    SubShader    {        Tags { "Queue"="Geometry+10" "RenderType"="Opaque" }        //...    }}

SubShader内部可以有标签(Tags)的定义。Tag指定了这个SubShader的渲染顺序(时机),以及其他的一些设置。

(1)Queue:决定渲染顺序,(在同一Z深度下比较,优先比较z深度),越小越早渲染。
1、background 1000,,背景如天空盒子,
2,geometry2000,大部分不透明物体,
3,alphatest 2450,进行透明测试的队列
4,transpare,3000,透明物体,
5,overlay,4000,最后被渲染的,

(2)RenderType,(估计是使用此subshader的条件)
Unity可以运行时替换符合特定RenderType的所有Shader。Camera.RenderWithShader或者Camera.SetReplacementShader配合使用
1,Opaque 大部分不透明物体。
2,Transpa大部分透明物体。
3,backgroudn
4,overlay,

(3)”ForceNoShadowCasting“,值为”true”时,表示不接受阴影。

(4)”IgnoreProjector“,值为”true”时,表示不接受Projector组件的投影。

4.
Pass(越多要求性能越高,从上到下一个执行到另一个)

Shader "ShaderLab Tutorials/TestShader" {    SubShader {        Pass        {            //...        }    }}

一个SubShader(渲染方案)是由一个个Pass块来执行的。每个Pass都会消耗对应的一个DrawCall。在满足渲染效果的情况下尽可能地减少Pass的数量。

每个通道的定义可以是1个regular Pass, 或 Use Pass 或 Grab Pass.

5.
pass中的Tag

Shader "ShaderLab Tutorials/TestShader" {    SubShader {        Pass        {            Tags{ "LightMode"="ForwardBase" }            //...        }    }}

和SubShader有自己专属的Tag类似,Pass也有Pass专属的Tag。
其中最重要Tag是 “LightMode“,指定Pass和Unity的哪一种渲染路径(“Rendering Path”)搭配使用。这里需要描述的Tag取值可包括:

Always: Always rendered; no lighting is applied.

ForwardBase: Used in Forward rendering, ambient, main directional light, vertex/SH lights and lightmaps are applied.

ForwardAdd: Used in Forward rendering; additive per-pixel lights are applied, one pass per light.

Deferred: Used in Deferred Shading; renders g-buffer.

ShadowCaster: Renders object depth into the shadowmap or a depth texture.

PrepassBase: Used in legacy Deferred Lighting, renders normals and specular exponent.

PrepassFinal: Used in legacy Deferred Lighting, renders final color by combining textures, lighting and emission.

Vertex: Used in legacy Vertex Lit rendering when object is not lightmapped; all vertex lights are applied.

VertexLMRGBM: Used in legacy Vertex Lit rendering when object is lightmapped; on platforms where lightmap is RGBM encoded (PC & console).

VertexLM: Used in legacy Vertex Lit rendering when object is lightmapped; on platforms where lightmap is double-LDR encoded (mobile platforms).

6.
FallBack
当本Shader的所有SubShader都不支持当前显卡,就会使用FallBack语句指定的另一个Shader。FallBack最好指定Unity自己预制的Shader实现,因其一般能够在当前所有显卡运行。

7.
Property

Shader "ShaderLab Tutorials/TestShader"{    Properties {    _Range ("My Range", Range (0.02,0.15)) = 0.07 // sliders    _Color ("My Color", Color) = (.34, .85, .92, 1) // color    _2D ("My Texture 2D", 2D) = "" {} // textures    _Rect("My Rectangle", Rect) = "name" { }    _Cube ("My Cubemap", Cube) = "name" { }    _Float ("My Float", Float) = 1    _Vector ("My Vector", Vector) = (1,2,3,4)    }    // Shader    SubShader{        Pass{          //...          uniform float4 _Color;          //...          float4 frag() : COLOR{ return fixed4(_Color); }          //...          }    }    //fixed pipeline    SubShader    {        Pass{            Color[_Color]        }    }}

Shader在Unity编辑器暴露给美术的参数,通过Properties来实现。
所有可能的参数如上所示。主要也就Float、Vector和Texture这3类。
除了通过编辑器编辑Properties,脚本也可以通过Material的接口(比如SetFloat、SetTexture编辑
之后在Shader程序通过[name](固定管线)或直接name(可编程Shader)访问这些属性。

8
**数据类型
float,half,fix**
Shader中的数据类型
有3种基本数值类型:float、half和fixed。
这3种基本数值类型可以再组成vector和matrix,比如half3是由3个half组成、float4x4是由16个float组成。

float:32位高精度浮点数。
half:16位中精度浮点数。范围是[-6万, +6万],能精确到十进制的小数点后3.3位。
fixed:11位低精度浮点数。范围是[-2, 2],精度是1/256。
数据类型影响性能
精度够用就好。
颜色和单位向量,使用fixed
其他情况,尽量使用half(即范围在[-6万, +6万]内、精确到小数点后3.3位);否则才使用float。
不要将低精度fixed类型转换为更高的精度,否则会产生性能问题。
低精度fixed不要使用“swizzle”(即形如myFixed4.xyzw、myFixed2.xyxy,中文不知咋译,“搅和
访问”?),否则会产生性能问题。
作者donaldwu说:swizzle在编写Shader里是经常用到的,但到底怎样才算swizzle?myFixed4.x算不算?myFixed4.xyzw算不算?myFixed4.xyxy算不算?还是都算?
这个目前没有找到权威的定义,所以为了不要影响效率,建议fixed尽量不要出现上面任意一种形式。

9。
shader形态:
(1),固定管线,
(2),vfshader。
(3),surfaceShader

VFshader
**Shader “ShaderLab Tutorials/TestShader”
{
Properties {}
SubShader
{
Pass
{
// … the usual pass state setup …
CGPROGRAM
// compilation directives for this snippet, e.g.:**
#pragma vertex vert
#pragma fragment frag

      // the Cg/HLSL code itself      float4 vert(float4 v:POSITION) : SV_POSITION{          return mul(UNITY_MATRIX_MVP, v);      }      float4 frag() : COLOR{          return fixed4(1.0, 0.0, 0.0, 1.0);      }      ENDCG      // ... the rest of pass setup ...      }}

}

#pragma vertex name#pragma fragment name

替换name,来指定Vertex Shader函数、Fragment Shader函数。

#pragma only_renderers name name ...#pragma exclude_renderers name name...  #pragma only_renderers gles gles3,#pragma exclude_renderers d3d9 d3d11 opengl,

只为指定渲染平台(render platform)编译

引用库:
#include “UnityCG.cginc”

**语义
(看视频是的时候说其实寄存器)
POSITION,
COLOR
TEXCOORD0**

10.
渲染路径:Rendering Path
渲染光照的质量
开发者可以在Unity工程的PlayerSettings设置对渲染路径进行3选1

Deferred Lighting,延迟光照路径。3者中最高质量地还原光照阴影。光照性能只与最终像素数目有关,光源数量再多都不会影响性能。
Forward Rendering,顺序渲染路径。能发挥出Shader全部特性的渲染路径,当然也就支持像素级光照。最常用、功能最自由,性能与光源数目*受光照物体数目有关,具体性能视乎其具体使用到的Shader的复杂度。
Vertex Lit,顶点光照路径。顶点级光照。性能最高、兼容性最强、支持特性最少、品质最差。

每个渲染路径的内部会再分为几个阶段。
然后,Shader里的每个Pass,都可以指定为不同的LightMode。而LightMode实际就是说:“我希望这个Pass在这个XXX渲染路径的这个YYY子阶段被执行”。

渲染路径的内部阶段和Pass的LightMode标签
每个渲染路径的内部会再分为几个阶段。
然后,Shader里的每个Pass,都可以指定为不同的LightMode。而LightMode实际就是说:“我希望这个Pass在这个XXX渲染路径的这个YYY子阶段被执行”。

Deferred Ligting
渲染路径内部子阶段 对应的LightMode 描述
Base Pass “PrepassBase” 渲染物体信息。即把法向量、高光度到一张ARGB32的物体信息纹理上,把深度信息保存在Z-Buff上。
Lighting Pass 无对应可编程Pass 根据Base Pass得出的物体信息,在屏幕坐标系下,使用BlinnPhong光照模式,把光照信息渲染到ARGB32的光照信息纹理上(RGB表示diffuse颜色值、A表示高光度)
Final Pass “PrepassFinal” 根据光照信息纹理,物体再渲染一次,将光照信息、纹理信息和自发光信息最终混合。LightMap也在这个Pass进行。

Forward Rendering
渲染路径内部子阶段 对应的LightMode 描述
Base Pass “ForwardBase” 渲染:最亮一个的方向光光源(像素级)和对应的阴影、所有顶点级光源、LightMap、所有LightProbe的SH光源(Sphere Harmonic,球谐函数,效率超高的低频光)、环境光、自发光。
Additional Passes “ForwardAdd” 其他需要像素级渲染的的光源
注意到的是,在Forward Rendering中,光源可能是像素级光源、顶点级光源或SH光源。其判断标准是:

配制成“Not Important”的光源都是顶点级光源和SH光源
最亮的方向光永远都是像素级光源
配置成“Important”的都是像素级光源
上面2种情况加起来的像素级光源数目小于“Quality Settings”里面的“Pixel Light Count”的话,会把第1种情况的光源补为额外的像素级光源。

Vertex Lit
渲染路径内部子阶段 对应的LightMode 描述
Vertex “Vertex” 渲染无LightMap物体
VertexLMRGBM “VertexLMRGBM” 渲染有RGBM编码的LightMap物体
VertexLM “VertexLM” 渲染有双LDR编码的LightMap物体

不同LightMode的Pass的被选择
一个工程的渲染路径是唯一的,但一个工程里的Shader是允许配有不同LightMode的Pass的。
在Unity,策略是“从工程配置的渲染路径模式开始,按Deferred、Forward、VertxLit的顺序,搜索最匹配的LightMode的一个Pass”。
比如,在配置成Deferred路径时,优先选有Deferred相关LightMode的Pass;找不到才会选Forward相关的Pass;还找不到,才会选VertexLit相关的Pass。
再比如,在配置成Forward路径时,优先选Forward相关的Pass;找不到才会选VertexLit相关的Pass。

RenderPath的三种Deffered,forwad,vertexLIt是由unity工程设定的,而LightMode是一种策略,类似一种条件限制,选择之类的,lightMode设定为deffer的时候就会被Deffered(RenderPath)先找到。

11. 内置类型

float: 32 bit浮点类型half:  16 bit浮点int:   32 bit 整形fixd:  12 bit定点bool:  布尔值sampler*: 纹理对象的句柄string:  不是每个都支持

12.支持类型
数组
float a[10]; float4 b[10]; int length = a.length; //获取长度,上面两个返回都是10

float b[2][3] = { { }, { } };int length1 = b.length; // length1 = 2;int length2 = b[0].length; // length = 3;

结构
以struct开始,紧跟名字,内容用{};包住。不要忘记最后的分号。
结构中可以带function,是C++中的用法。
结构不支持继承。

13、特定关键字
in , out , inout,
uniform (被修饰的变量从外部传入), const ,

14、输入语义关键字
Vertex Shader的输入:

POSITION, NORMAL,BLENDINDICES, BLENDWEIGHT, TANGENT,  PSIZE,  TEXCOORD0 ~ TEXCOORD7

Vertex Shader的输出, 也就是Pixel Shader的输入

POSITION, PSIZE, FOG,COLOR0 ~ COLOR1, TEXCOORD1 ~ TEXCOORD7

Pixel Shader的输出:

COLOR

15、内置函数库

reflect 求发射向量
refract 求折射向量
mul 矩阵相乘
normalize 归一化

16渲染过程
这里写图片描述

1.vertex2.culling    depth Test,3.fog4.fragment5.alpha test6.blending

17.Culling

    back    front    off

18
Zwirte on |off

19
ZTest Less | Greater | LEqual | GEqual | Equal | NotEqual | Always

20
Offset Factor , Units 深度偏移

21
setTexture

SetTexture [TexturePropertyName] { Texture Block }
Assigns a texture. TextureName must be defined as a texture property. How to apply the texture is defined inside the TextureBlock.
指派一个纹理,TextureName 必须是被当做纹理的属性来定义。在TextureBlock中设置如何定义这个纹理。
The texture block controls how the texture is applied. Inside the texture block can be up to three commands: combine, matrix and constantColor.

TextureBlock控制了如何设置这些纹理。在这个块中可以使用3个命令:combine, matrix , constantColor.

Texture block combine command
combine 命令

combine src1 * src2 Multiplies src1 and src2 together. The result will be darker than either input. src1和src2相乘,结果纹理将比输入纹理更暗。 combine src1 + src2 Adds src1 and src2 together. The result will be lighter than either input. src1和src2相加,结果纹理将比输入纹理更明亮。 combine src1 - src2 Subtracts src2 from src1. src1和src2相减 combine src1 +- src2 Adds src1 to src2, then subtracts 0.5 (a signed add). src1和src2相加,然后减去0.5(有符号相加)combine src1 lerp (src2) src3 Interpolates between src3 and src1, using the alpha of src2. Note that the interpolation is opposite direction: src1 is used when alpha is one, and src3 is used when alpha is zero. 在src3和src1之间做插值,使用src2的alpha值。请注意插值是相反的方向,当alpha为1时候src1使用,当alpha为0时候src3使用。combine src1 * src2 + src3 Multiplies src1 with the alpha component of src2, then adds src3. src1与src2的alpha值混合,然后添加src3.combine src1 * src2 +- src3 Multiplies src1 with the alpha component of src2, then does a signed add with src3. src1与src2的alpha值混合,然后和有符号的src3相加. combine src1 * src2 - src3 Multiplies src1 with the alpha component of src2, then subtracts src3. src1和src2的alpha值相乘,然后和src3相减。All the src properties can be either one of previous, constant, primary or texture. 所有的src属性可以是previous, constant, primary 或texturePrevious is the the result of the previous SetTexture. 在使用SetTexture命令之前的纹理 Primary is the color from the lighting calculation or the vertex color if it is bound.  从光照计算或者受限的顶点颜色中得到的颜色 Texture is the color of the texture specified by [_TextureName] in the SetTexture (see above). 从SetTexture [_TextureName]中指定的纹理颜色 Constant is the color specified in ConstantColor. 常量颜色从ConstantColor设置中得到Modifiers: 修正:The formulas specified above can optionally be followed by the keywords Double or Quad to make the resulting color 2x or 4x as bright. 上述所有的公式可以选择设置关键词Double或者Quad使结果的颜色2倍或者4倍明亮。 

All the src properties, except lerp argument, can optionally be preceded by one - to make the resulting color negated.
所有的src属性,除lerp外,可以使用符号-来使最终颜色反相。

All the src properties can be followed by alpha to take only the alpha channel.
所有的src属性后面可以有且仅有1个alpha.
Texture block constantColor command 常量颜色命令
ConstantColor color
Defines a constant color that can be used in the combine command.
定义1个常量颜色,在combina命令中使用
Texture block matrix command
matrix [MatrixPropertyName]
Transforms texture coordinates used in this command with the given matrix.
利用此命令使用指定的矩阵转换纹理坐标

1.privious,
2,priamary
3,texture
4.constantColor,

Alpha Controlled Self-illumination alpha控制的自发光
This shader uses the alpha component of the _MainTex to decide where to apply lighting. It does this by applying the texture to two stages; In the first stage, the alpha value of the texture is used to blend between the vertex color and solid white. In the second stage, the RGB values of the texture are multiplied in.

这个shader使用的的_MainTex的alpha分量去决定在哪应用照明。它分两个阶段来实现这个效果。在第一阶段,纹理的alpha值用于混合顶点颜色和白色固体。在第二阶段中,再乘以纹理的RGB值。

Shader "Examples/Self-Illumination" {    Properties {        _MainTex ("Base (RGB) Self-Illumination (A)", 2D) = "white" {}    }    SubShader {        Pass {            // Set up basic white vertex lighting            Material {                Diffuse (1,1,1,1)                Ambient (1,1,1,1)            }            Lighting On            // Use texture alpha to blend up to white (= full illumination)使用纹理alpha和白色混合            SetTexture [_MainTex] {                constantColor (1,1,1,1)                combine constant lerp(texture) previous            }            // Multiply in texture            SetTexture [_MainTex] {                combine previous * texture            }        }    }} We can do something else for free here, though; instead of blending to solid white, we can add a self-illumination color and blend to that. Note the use of ConstantColor to get a _SolidColor from the properties into the texture blending. 这里我们就可以发挥想象了。我们可以在属性中设置自发光的颜色,代码如下。Shader "Examples/Self-Illumination 2" {    Properties {        _IlluminCol ("Self-Illumination color (RGB)", Color) = (1,1,1,1)        _MainTex ("Base (RGB) Self-Illumination (A)", 2D) = "white" {}    }    SubShader {        Pass {            // Set up basic white vertex lighting            Material {                Diffuse (1,1,1,1)                Ambient (1,1,1,1)            }            Lighting On            // Use texture alpha to blend up to white (= full illumination)            SetTexture [_MainTex] {                // Pull the color property into this blender                constantColor [_IlluminCol]                // And use the texture's alpha to blend between it and                // vertex color                combine constant lerp(texture) previous            }            // Multiply in texture            SetTexture [_MainTex] {                combine previous * texture            }        }    }} And finally, we take all the lighting properties of the vertexlit shader and pull that in: 最后我们可以设置顶点光照着色器的光照属性,修改成下面这样:Shader "Examples/Self-Illumination 3" {    Properties {        _IlluminCol ("Self-Illumination color (RGB)", Color) = (1,1,1,1)        _Color ("Main Color", Color) = (1,1,1,0)        _SpecColor ("Spec Color", Color) = (1,1,1,1)        _Emission ("Emmisive Color", Color) = (0,0,0,0)        _Shininess ("Shininess", Range (0.01, 1)) = 0.7        _MainTex ("Base (RGB)", 2D) = "white" {}    }    SubShader {        Pass {            // Set up basic vertex lighting            Material {                Diffuse [_Color]                Ambient [_Color]                Shininess [_Shininess]                Specular [_SpecColor]                Emission [_Emission]            }            Lighting On            // Use texture alpha to blend up to white (= full illumination)            SetTexture [_MainTex] {                constantColor [_IlluminCol]                combine constant lerp(texture) previous            }            // Multiply in texture            SetTexture [_MainTex] {                combine previous * texture            }        }    }}  

22,FOG
Fog { Fog Commands }
1.Mode,
Mode Off | Global | Linear | Exp | Exp2

2,Color,
Color ColorValue

3,Density,
Density FloatValue

4,Range,
Range FloatValue , FloatValue

23.AlphaTest
alpha测试是最后一个机会,拒绝将一个像素写到屏幕上。(可以理解为在将画面显示到屏幕上的最后1次修改,这次修改只能让该像素显示或不显示)
在最后的输出颜色被计算之后,这个颜色可以选择是否让自己的alpha值和一个固定值做比较。如果测试失败,这个像素将不在屏幕上显示。

语法,
AlphaTest Off
AlphaTest comparison AlphaValue
比较命令式下面中的1个
要输出的alpha与AhphaValue比较

Greater Only render pixels whose alpha is greater than AlphaValue. 只渲染alpha值比AlphaValue大的像素
GEqual Only render pixels whose alpha is greater than or equal to AlphaValue. 只渲染alpha值>=AlphaValue的像素
Less Only render pixels whose alpha value is less than AlphaValue. 只渲染alpha值

0 0