1.先来一段单张纹理贴图的shader示例代码:

 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

 Shader "Custom/MyShader"{
Properties{
//外部可调属性
_MainTex ("Main Tex", 2D) = "white" {}
}
SubShader
{
//设置使用本Subshader所需要满足的渲染路径等参数,如果满足,即使用本shader
Tags {"Queue"="Transparent""RenderType"="Transparent"}
Pass
{
//设置该pass 的渲染状态和标签
Tags { "LightMode"="ForwardBase" }
//开始cg代码片段
CGPROGRAM
//该代码的编译指令,
#pragma vertex vert//设置顶点着色器的函数名称
#pragma fragment frag//设置片段着色器的函数名称
#include "Lighting.cginc"//包含库文件 struct a2v {
float4 vertex : POSITION;//当前要渲染的顶点坐标
float4 texcoord : TEXCOORD0;//当前要渲染的顶点的第一套纹理坐标
}; struct v2f {
float4 pos : SV_POSITION;//
float2 uv : TEXCOORD0;
};
sampler2D _MainTex;
float4 _MainTex_ST; v2f vert(a2v v)
{
v2f o;
o.pos=UnityObjectToClipPos(v.vertex);//将顶点坐标变换到裁剪空间中
o.uv = TRANSFORM_TEX(v.texcoord,_MainTex);//变换uv坐标
return o;
} fixed4 frag(v2f i):SV_Target
{
fixed4 c = tex2D (_MainTex, i.uv);//对纹理坐标进行采样
return c;
}
ENDCG
}
//SubShader
//{
// //如果不满足第一个subshader所需要的条件,那么再来检测是否满足第二subshader 的条件。
//}
}
FallBack "Diffuse"
}

MyShader.shader

SubShader

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

一个Shader有多个SubShader。一个SubShader可理解为一个Shader的一个渲染方案。即SubShader是为了针对不同的渲染情况而编写的。每个Shader至少1个SubShader、理论可以无限多个,但往往两三个就足够。
一个时刻只会选取一个SubShader进行渲染,具体SubShader的选取规则包括:

  • 从上到下选取
  • SubShader的标签、Pass的标签
    • 是否符合当前的“Unity渲染路径”
    • 是否符合当前的ReplacementTag
  • SubShader是否和当前的GPU兼容

按此规则第一个被选取的SubShader将会用于渲染,未被选取的SubShader在这次渲染将被忽略。

SubShader的Tag

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

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

  • "RenderType"标签。Unity可以运行时替换符合特定RenderType的所有Shader。Camera.RenderWithShaderCamera.SetReplacementShader配合使用。Unity内置的RenderType包括:

    • "Opaque":绝大部分不透明的物体都使用这个;
    • "Transparent":绝大部分透明的物体、包括粒子特效都使用这个;
    • "Background":天空盒都使用这个;
    • "Overlay":GUI、镜头光晕都使用这个;
    • 用户也可以定义任意自己的RenderType这个标签所取的值。
    • 应注意,Camera.RenderWithShaderCamera.SetReplacementShader不要求标签只能是RenderTypeRenderType只是Unity内部用于Replace的一个标签而已,你也可以自定义自己全新的标签用于Replace。
      比如,你为自己的ShaderA.SubShaderA1(会被Unity选取到的SubShader,常为Shader文件中的第一个SubShader)增加Tag为"Distort"="On",然后将"Distort"作为参数replacementTag传给函数。此时,作为replacementShader实参的ShaderB.SubShaderB1中若有也有一模一样的"Distort"="On",则此SubShaderB1将代替SubShaderA1用于本次渲染。
    • 具体可参考Rendering with Replaced Shaders
  • "Queue"标签。定义渲染顺序。预制的值为
    • "Background"。值为1000。比如用于天空盒。
    • "Geometry"。值为2000。大部分物体在这个队列。不透明的物体也在这里。这个队列内部的物体的渲染顺序会有进一步的优化(应该是从近到远,early-z test可以剔除不需经过FS处理的片元)。其他队列的物体都是按空间位置的从远到近进行渲染。
    • "AlphaTest"。值为2450。已进行AlphaTest的物体在这个队列。
    • "Transparent"。值为3000。透明物体。
    • "Overlay"。值为4000。比如镜头光晕。
    • 用户可以定义任意值,比如"Queue"="Geometry+10"
  • "ForceNoShadowCasting",值为"true"时,表示不接受阴影。
  • "IgnoreProjector",值为"true"时,表示不接受Projector组件的投影。

另,关于渲染队列和Batch的非官方经验总结是,一帧的渲染队列的生成,依次决定于每个渲染物体的:

  • Shader的RenderType tag,
  • Renderer.SortingLayerID,
  • Renderer.SortingOrder,
  • Material.renderQueue(默认值为Shader里的"Queue"),
  • Transform.z(ViewSpace)(默认为按z值从前到后,但当Queue是“Transparent”的时候,按z值从后到前)。

这个渲染队列决定了之后(可能有dirty flag的机制?)渲染器再依次遍历这个渲染队列,“同一种”材质的渲染物体合到一个Batch里。

Pass

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

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

Pass的Tag

Shader "ShaderLab Tutorials/TestShader" {
SubShader {
Pass
{
Tags{ "LightMode"="ForwardBase" }
//...
}
}
}
shader有自己专属的Tag类似,Pass也有Pass专属的Tag。

其中最重要Tag是 "LightMode",指定Pass和Unity的哪一种渲染路径(“Rendering Path”)搭配使用。除最重要的ForwardBaseForwardAdd外,这里需额外提醒的Tag取值可包括:

  • Always,永远都渲染,但不处理光照
  • ShadowCaster,用于渲染产生阴影的物体
  • ShadowCollector,用于收集物体阴影到屏幕坐标Buff里。

其他渲染路径相关的Tag详见下面章节“Unity渲染路径种类”。
具体所有Tag取值,可参考ShaderLab syntax: Pass Tags

FallBack

Shader "ShaderLab Tutorials/TestShader"{
SubShader { Pass {} } FallBack "Diffuse" // "Diffuse"即Unity预制的固有Shader
// FallBack Off //将关闭FallBack
}

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

Properties

 Shader "ShaderLab Tutorials/TestShader"
{
Properties {
_Range ("My Range", Range (0.02,0.15)) = 0.07 // sliders
_Color ("My Color", Color) = (., ., ., ) // color
_2D ("My Texture 2D", 2D) = "" {} // textures
_Rect("My Rectangle", Rect) = "name" { }
_Cube ("My Cubemap", Cube) = "name" { }
_Float ("My Float", Float) =
_Vector ("My Vector", Vector) = (,,,) // Display as a toggle.
[Toggle] _Invert ("Invert color?", Float) =
// Blend mode values
[Enum(UnityEngine.Rendering.BlendMode)] _Blend ("Blend mode", Float) =
//setup corresponding shader keywords.
[KeywordEnum(Off, On)] _UseSpecular ("Use Specular", Float) =
} // Shader
SubShader{
Pass{
//...
uniform float4 _Color;
//...
float4 frag() : COLOR{ return fixed4(_Color); }
//...
#pragma multi_compile __ _USESPECULAR_ON
}
} //fixed pipeline
SubShader {
Pass{
Color[_Color]
}
}
}
  • Shader在Unity编辑器暴露给美术的参数,通过Properties来实现。
  • 所有可能的参数如上所示。主要也就Float、Vector和Texture这3类。
  • 除了通过编辑器编辑Properties,脚本也可以通过Material的接口(比如SetFloatSetTexture编辑)
  • 之后在Shader程序通过[name](固定管线)或直接name(可编程Shader)访问这些属性。
  • 在每一个Property前面也能类似C#那样添加Attribute,以达到额外UI面板功能。详见MaterialPropertyDrawer.html

Shader中的数据类型

有3种基本数值类型:floathalffixed
这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

ShaderLab中的Matrix

当提到“Row-Major”、“Column-Major”,根据不同的场合,它们可能指不同的意思:

  • 数学上的,主要是指矢量V是Row Vector、还是Column Vector。引用自[Game Engine Architecture 2nd Edition, 183]。留意到V和M的乘法,当是Row Vector的时候,数学上写作VM,Matrix在右边,Matrix的最下面一行表示Translate;当是Column Vector的时候,数学上写作MtVt,Matrix在左边并且需要转置,Matrix最右面一列表示Translate。
  • 访问接口上的:Row-Major即MyMatrix[Row][Column]、Column-Major即MyMatrix[Column][Row]。HLSL/CG的访问接口都是Row-Major,比如MyMatrix[3]返回的是第3行;GLSL的访问接口是Column-Major,比如MyMatrix[3]返回的是第3列。
  • 寄存器存储上的:每个元素是按行存储在寄存器中、还是按列存储在寄存器中。需要关注它的一般情况举例是,float2x3的MyMatrix,到底是占用2个寄存器(Row-Major)、还是3个寄存器(Column-Major)。在HLSL里,可以通过#pragmapack_matrix设定row_major或者column_major。

上述情况,互不相干。
然后,ShaderLab中,数学上是Column Vector、访问接口上是Row-Major、存储上是(尚未查明)。

ShaderLab中各个Space的坐标系

一般情况下,从Vertex Buff输入顶点到Vertex Shader,

  • 该顶点为左手坐标系Model Space中的顶点vInModel
    其用w=1的Homogenous Cooridniates(故等效于Cartesian Coordinates)表达vInModel = float4(xm, ym, zm, 1)
  • vInWrold = mul(_Object2World , vInModel)后,得出左手坐标系World Space中的vInWorld,其为w=1的Homogenous Cooridniates(故等效于Cartesian Coordinates)vInWorld = float4(xw, yw, zw, 1)
  • vInView = mul(UNITY_MATRIX_V , vInWrold)后,得出右手坐标系View Space中的vInView,其为w=1的Homogenous Cooridniates(故等效于Cartesian Coordinates)vInWorld = float4(xv, yv, zv, 1)
  • vInClip = mul(UNITY_MATRIX_P , vInView)后,得出左手坐标系Clip Space中的vInClip,其为w往往不等于1的Homogenous Cooridniates(故往往不等效于Cartesian Coordinates)vInClip = float4(xc, yc, zc, wc)
    设r、l、t、b、n、f的长度绝对值如下图:

     

    注意View Space中摄像机前方的z值为负数、-z为正数。则GL/DX/Metal的Clip Space坐标为:

    • GL:

      • xc=(2nx+rz+lz)/(r-l);
      • yc=(2ny+tz+bz)/(t-b);
      • zc=(-fz-nz-2nf)/(f-n);
      • wc=-z;
    • DX/Metal:
      • xc=(2nx+rz+lz)/(r-l);
      • yc=(2ny+tz+bz)/(t-b);
      • zc=(-fz-nf)/(f-n);
      • wc=-z;
  • vInNDC = vInClip / vInClip.w后,得出左手坐标系Normalized Device Coordinates中的vInNDC,其为w=1的Homogenous Cooridniates(故等效于Cartesian Coordinates)vInNDC = float4(xn, yn, zn, 1)
    xnyn的取值范围为[-1,1]。
    • GL: zn=zc/wc=(fz+nz+2nf)/((f-n)z);
    • DX/Metal: zn=zc/wc=(fz+nf)/((f-n)z);
    • 在Unity中,zn的取值范围可以这样决定:
      • 如果UNITY_REVERSED_Z已定义,zn的取值范围是[UNITY_NEAR_CLIP_VALUE, 0],即[1,0]
      • 如果UNITY_REVERSED_Z未定义,zn的取值范围是[UNITY_NEAR_CLIP_VALUE, 1]
        • 如果SHADER_API_D3D9/SHADER_API_D3D11_9X定义了,即[0,1]
        • 否则,即OpenGL情况,即[-1,1]
 v2f vert (appdata v)
{
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
// 1 、2、3是等价的,和4是不等价的
// 因为是M在左、V在右,所以是Column Vector
// 因为是HLSL/CG语言,所以是访问方式是Row-Major
o.rootInView = mul(UNITY_MATRIX_MV, float4(, , , )); //
o.rootInView = float4(UNITY_MATRIX_MV[].w, UNITY_MATRIX_MV[].w, UNITY_MATRIX_MV[].w, ); // 2
o.rootInView = UNITY_MATRIX_MV._m03_m13_m23_m33; // 3
//o.rootInView = UNITY_MATRIX_MV[3]; // return o;
} fixed4 frag (v2f i) : SV_Target
{
// 因为是ViewSpace是右手坐标系,所以当root在view前面的时候,z是负数,所以需要-z才能正确显示颜色
fixed4 col = fixed4(i.rootInView.x, i.rootInView.y, -i.rootInView.z, );
return col;
} struct appdata
{
float4 vertex : POSITION;
};
struct v2f
{
float4 rootInView : TEXCOORD0;
float4 vertex : SV_POSITION;
};

Shader形态

Shader形态之1:固定管线

固定管线是为了兼容老式显卡。都是顶点光照。之后固定管线可能是被Unity抛弃的功能,所以最好不学它、当它不存在。特征是里面出现了形如下面Material块、没有CGPROGRAMENDCG块。

 Shader "ShaderLab Tutorials/TestShader"
{
Properties {
_Color ("My Color", Color) = (., ., ., ) // color
} // Fixed Pipeline
SubShader
{
Pass
{
Material{
Diffuse [_Color]
Ambient [_Color]
} Lighting On
}
}
}

Shader形态之2:可编程Shader

 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 ...
}
}
}
  • 功能最强大、最自由的形态。
  • 特征是在Pass里出现CGPROGRAMENDCG
  • 编译指令#pragma。详见官网Cg snippets。其中重要的包括:
编译指令 示例/含义
#pragma vertex name
#pragma fragment name
替换name,来指定Vertex Shader函数、Fragment Shader函数。
#pragma target name 替换name(为2.03.0等)。设置编译目标shader model的版本。
#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"引入指定的库。常用的就是UnityCG.cginc了。其他库详见官网Built-in shader include files
  • ShaderLab内置值。Unity给Shader程序提供了便捷的、常用的值,比如下面例子中的UNITY_MATRIX_MVP就代表了这个时刻的MVP矩阵。详见官网ShaderLab built-in values
  • Shader输入输出参数语义(Semantics)。在管线流程中每个阶段之间(比如Vertex Shader阶段和FragmentShader阶段之间)的输入输出参数,通过语义字符串,来指定参数的含义。常用的语义包括:COLORSV_PositionTEXCOORD[n]。完整的参数语义可见HLSL Semantic(由于是HLSL的连接,所以可能不完全在Unity里可以使用)。
  • 特别地,因为Vertex Shader的的输入往往是管线的最开始,Unity为此内置了常用的数据结构:
数据结构 含义
appdata_base vertex shader input with position, normal, one texture coordinate.
appdata_tan vertex shader input with position, normal, tangent, one texture coordinate.
appdata_full vertex shader input with position, normal, tangent, vertex color and two texture coordinates.
appdata_img vertex shader input with position and one texture coordinate.

Shader形态之3:SurfaceShader

 Shader "ShaderLab Tutorials/TestShader"
{
Properties { } // Surface Shader
SubShader {
Tags { "RenderType" = "Opaque" }
CGPROGRAM
#pragma surface surf Lambert
struct Input {
float4 color : COLOR;
};
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = ;
}
ENDCG
}
FallBack "Diffuse"
}
  • SurfaceShader可以认为是一个光照Shader的语法糖、一个光照VS/FS的生成器。减少了开发者写重复代码的需要。
  • 在手游,由于对性能要求比较高,所以不建议使用SurfaceShader。因为SurfaceShader是一个比较“通用”的功能,而通用往往导致性能不高。
  • 特征是在SubShader里出现CGPROGRAMENDCG块。(而不是出现在Pass里。因为SurfaceShader自己会编译成多个Pass。)
  • 编译指令是:
    #pragma surface surfaceFunction lightModel [optionalparams]
    • surfaceFunction:surfaceShader函数,形如void surf (Input IN, inout SurfaceOutput o)
    • lightModel:使用的光照模式。包括Lambert(漫反射)和BlinnPhong(镜面反射)。
      • 也可以自己定义光照函数。比如编译指令为#pragma surface surf MyCalc

  • 你定义输入数据结构(比如上面的Input)、编写自己的Surface函数处理输入、最终输出修改过后的SurfaceOutput。SurfaceOutput的定义为
    struct SurfaceOutput {
    half3 Albedo; // 纹理颜色值(r, g, b)
    half3 Normal; // 法向量(x, y, z)
    half3 Emission; // 自发光颜色值(r, g, b)
    half Specular; // 镜面反射度
    half Gloss; // 光泽度
    half Alpha; // 不透明度
    };

Shader形态之4:Compiled Shader

点击a.shader文件的“Compile and show code”,可以看到该文件的“编译”过后的ShaderLab shader文件,文件名形如Compiled-a.shader
其依然是ShaderLab文件,其包含最终提交给GPU的shader代码字符串。
先就其结构进行简述如下,会发现和上述的编译前ShaderLab结构很相似。

 // Compiled shader for iPhone, iPod Touch and iPad, uncompressed size: 36.5KB
// Skipping shader variants that would not be included into build of current scene.
Shader "ShaderLab Tutorials/TestShader"
{
Properties {...}
SubShader {
// Stats for Vertex shader:
// gles : 14 avg math (11..19), 1 avg texture (1..2)
// metal : 14 avg math (11..17)
// Stats for Fragment shader:
// metal : 14 avg math (11..19), 1 avg texture (1..2)
Pass {
Program "vp" // vertex program
{
SubProgram "gles" {
// Stats: 11 math, 1 textures
Keywords{...} // keywords for shader variants ("uber shader") //shader codes in string
"
#ifdef VERTEX
vertex shader codes
#endif // Note, on gles, fragment shader stays here inside Program "vp"
#ifdef FRAGMENT
fragment shader codes
#endif
"
} SubProgram "metal" {
some setup
Keywords{...} //vertex shader codes in string
"..."
}
} Program "fp" // fragment program
{
SubProgram "gles" {
Keywords{...}
"// shader disassembly not supported on gles" //(because gles fragment shader codes are in Program "vp")
} SubProgram "metal" {
common setup
Keywords{...} //fragment shader codes in string
"..."
}
}
}
} ...
}

Unity渲染路径(Rendering Path)种类

概述

开发者可以在Unity工程的PlayerSettings设置对渲染路径进行3选1:

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

渲染路径的内部阶段和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种情况的光源补为额外的像素级光源。

另外,配置成“Auto”的光源有更复杂的判断标注,截图如下:

2014-0720-1607-31-40.png

具体可参考Forward Rendering Path Details

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。

移动设备GPU架构简述

《The Mali GPU: An Abstract Machine》系列以Arm Mali GPU为例子给出了全面的讨论,现简述如下:

  • Part 1 - Frame Pipelining

    • Application/Geometry/Fragment三阶段组成,三者中最大才是瓶颈
    • OpenGL的同步API是个“illusion”,事实上是CommandQueue(直到遇到Fence会被强制同步),以减少CPU/GPU之间的互相等待
    • Pipeline Throttle,为了更低的延迟,当GPU累积了多帧(往往是3帧,以eglSwapBuffers()Present()来区分帧)的Command时,OS会通过eglSwapBuffers()Present()来阻塞CPU让其进入idle,从而防止更多后续Command的提交
  • Part 2 - Tile-based Rendering
    • tile-based deferred rendering (WikiPowerVR/Mali/Adreno)是重要的概念。其将Fragment一帧处理多个比如16x16的单元,并为Shader集成一个小但快的cache,从而大幅避免Shader和主内存之间带宽消耗(电量消耗)
  • Part 3 - The Midgard Shader Core
    • GPU包含数个(当前常见为4-8个)Unified Shading Core,可动态分配用于Vertex Shader、Fragment Shader或Compute Kernel
    • 每个Unified Shader Core包含数个(当前常见为2个)用于SIMD计算的运算器Arithmetic Pipeline(A-pipe),1个用于纹理采样的Texutre Pipeline(T-pipe),1个用于非纹理类的内存读写的Load/Store Pipeline(LS-pipe)比如顶点属性写读、变量访问等
    • 会进行Early-ZS测试尝试减少Overdraw(依赖于渲染物体提交顺序由前至后)
    • Arm的Forward Pixel Kill和PowerVR的Hidden Surface Removal做到像素级别的Overdraw减少(不用依赖于渲染物体提交顺序由前至后)
    • 当Shader使用discardclip、在Fragment Shader里修改深度值、半透明,将不能进行Early-ZS,只好使用传统的Late-ZS
  • Part 4 - The Bifrost Shader Core
    • 2016年的新型号,对架构作出了优化

参考资源

  • Youtube:https://www.youtube.com/watch?v=hDJQXzajiPg (包括part1-6)。视频是最佳的入门方式没有之一,所以墙裂建议就算不看下文的所有内容,都要去看一下part1。
  • 书籍:《Unity 3D ShaderLab开发实战详解》
  • Unity各种官方文档

作者:DonaldW
链接:http://www.jianshu.com/p/7b9498e58659
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

[转]Unity Shader 学习总结的更多相关文章

  1. Unity Shader 学习之旅

    Unity Shader 学习之旅 unityshader图形图像 纸上学来终觉浅,绝知此事要躬行 美丽的梦和美丽的诗一样 都是可遇而不可求的——席慕蓉 一.渲染流水线 示例图 Tips:什么是 GP ...

  2. Unity Shader 学习之旅之SurfaceShader

    Unity Shader 学习之旅之SurfaceShader unity shader 图形图像  如果大地的每个角落都充满了光明 谁还需要星星,谁还会 在夜里凝望 寻找遥远的安慰——江河 官方文档 ...

  3. 第四章 开始Unity Shader学习之旅(2)

    目录 1. 强大的援手:Unity提供的内置文件和变量 1.1 内置的包含文件 1.2 内置的变量 2. Unity提供的Cg/HLSL语义 2.1 什么是语义 2.2 Unity支持的语义 2.3 ...

  4. 第四章 开始Unity Shader学习之旅(1)

    1. 一个最简单的顶点/片元着色器 现在,我们正式开始学习如何编写Unity Shader,更准确的说是,学习如何编写顶点/片元着色器 2.顶点/片元着色器的基本结构 我们在以前已经讲过了Unity ...

  5. Unity Shader学习笔记-1

    本篇文章是对Unity Shader入门精要的学习笔记,插图大部分来自冯乐乐女神的github 如果有什么说的不正确的请批评指正 目录 渲染流水线 流程图 Shader作用 屏幕映射 三角形遍历 两大 ...

  6. 【Unity Shader学习笔记】Unity基础纹理-单张纹理

    1 单张纹理 1.1 纹理 使用纹理映射(Texture Mapping)技术,我们把一张图片逐纹素(Texel)地控制模型的颜色. 美术人员建模时,会在建模软件中利用纹理展开技术把纹理映射坐标(Te ...

  7. Unity shader学习之屏幕后期处理效果之高斯模糊

    高斯模糊,见 百度百科. 也使用卷积来实现,每个卷积元素的公式为: 其中б是标准方差,一般取值为1. x和y分别对应当前位置到卷积中心的整数距离. 由于需要对高斯核中的权重进行归一化,即使所有权重相加 ...

  8. Unity Shader入门精要学习笔记 - 第5章 开始 Unity Shader 学习之旅

    一个顶点/片元 着色器的结构大概如下: Shader "MyShaderName" { Properties { //属性 } SubShader { //针对显卡A的SubSha ...

  9. 【Unity Shader学习笔记】Unity基础纹理-渐变纹理

    纹理可以用来存储任何表面属性. 可以通过使用渐变纹理来实现插画风格的渲染效果. 这项技术是由Valve公司提出的.Valve使用它来渲染游戏中具有插画风格的角色. 我们使用半兰伯特模型计算漫反射. 因 ...

  10. 第四章 开始Unity Shader学习之旅(3)

    1. 程序员的烦恼:Debug 调试(debug),大概是所有程序员的噩梦.而不幸的是,对一个Shader进行调试更是噩梦中的噩梦.这也是造成Shader难写的原因之一--如果发现得到的效果不对,我们 ...

随机推荐

  1. PS Tips: powershell 将文件以utf8格式打开并另存

    1. powershell 将文件以utf8格式打开并另存 Get-Content .\rep_position_liquidity.csv -Encoding UTF8 | Set-Content ...

  2. windows上的docker容器内安装vim

    Reading package lists... Done Building dependency tree Reading state information... Done E: Unable t ...

  3. django book多站点学习

    多个站点 Django 的多站点系统是一种通用框架,它让你可以在同一个数据库和同一个Django项目下操作多个网站. 这是一个抽象概念,理解起来可能有点困难,因此我们从几个让它能派上用场的实际情景入手 ...

  4. log4j教程 2、安装

    Log4j的API包使用Apache软件许可证,由开源倡议认证一个完全成熟的开源许可证下发布. 最新log4j的版本,包括完整的源代码,类文件和文档可以在这里找到 http://logging.apa ...

  5. python调用jieba(结巴)分词 加入自定义词典和去停用词功能

    把语料从数据库提取出来以后就要进行分词啦,我是在linux环境下做的,先把jieba安装好,然后找到内容是build jieba PKG-INFO setup.py test的那个文件夹(我这边是ji ...

  6. 2017.7.1 ftp文件服务器安装与配置(已验证可使用)

    下载地址:http://learning.happymmall.com/ 1.点击exe文件 2.启动ftpserver 点击exe后,就出现如下画面:输入账户密码和勾选权限等. 并配置好对应的文件夹 ...

  7. 3D数学读书笔记——矩阵基础番外篇之线性变换

    本系列文章由birdlove1987编写.转载请注明出处. 文章链接:http://blog.csdn.net/zhurui_idea/article/details/25102425 前面有一篇文章 ...

  8. Database returned an invalid value in QuerySet.datetimes(). Are time zone definitions for your datab

    Database returned an invalid value in QuerySet.datetimes(). Are time zone definitions for your datab ...

  9. Android API Guides---RenderScript

    RenderScript RenderScript是在Android上的高性能执行计算密集型任务的框架. RenderScript主要面向与数据并行计算的使用.尽管串行计算密集型工作负载能够受益.该R ...

  10. PJSIP dialog inv销毁

    PJSIP的Diaglog(类型为pjsip_dialog) 可以被外部调用,同时PJSIP有自己的机制销毁用户创建的 Dialog,如PJSIP内部销毁了某个Diaglog,用户在不知情的情况下继续 ...