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
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

最新文章

  1. [原]CentOS7 部署GeoServer2.92
  2. 可在广域网部署运行的QQ高仿版 -- GG叽叽V1.8(源码)
  3. ios面试(2015.10.30)
  4. CodeForces 483C Diverse Permutation
  5. @Secured(), @PreAuthorize()
  6. gdalwarp:变形工具
  7. MYSQL - php 使用 localhost 无法连接数据库
  8. ural 1356. Something Easier(数论,哥德巴赫猜想)
  9. JWebFileTrans(JDownload): 一款可以从网络上下载文件的小程序(三),多线程断点下载
  10. struts2.1.6教程五、拦截器
  11. snmp4j 之 ArgumentParser
  12. iOS项目的命名规范
  13. 使用wrk进行性能测试
  14. 五种基于RGB色彩空间统计的皮肤检测算法
  15. 错误代码: 1449 The user specified as a definer ('root'@'%') does not exist
  16. HDR拍照
  17. jcifs windows 域账户单点登录(转)
  18. 20175314 《Java程序设计》第九周学习总结
  19. Git学习(一)
  20. 剑指offer(60)把二叉树打印成多行

热门文章

  1. SQL Server Profiler和数据库引擎优化顾问
  2. 初识交替最小二乘ALS
  3. Java 并发工具包 java.util.concurrent 用户指南(转)
  4. 设计模式之适配器模式(php实现)
  5. perl一次读取多行文本的策略
  6. ISP模块之RAW DATA去噪(一)
  7. 2017.3.31 spring mvc教程(六)转发、重定向、ajax请求
  8. AForge.NET Framework-2.2.5
  9. Node.js node主文件找不到时报出的Error:Cannot find module异常
  10. DNS 取得授权