Shader基础

1. Shader其实就是专门用来渲染图形的一种技术,通过shader,我们可以自定义显卡渲染画面的算法,使画面达到我们想要的效果。

2. Shader编程语言:

  • 基于OpenGL的OpenGL Shading Language,简称GLSL。
  • 基于DirectX的High Level Shading Language,简称HLSL。
  • 还有NVIDIA公司的C for Graphic,简称Cg语言。

3. GLSL与HLSL分别是基于OpenGL和Direct3D的接口,两者不能混用。而Cg语言是用于图形的C语言,这其实说明了当时设计人员的一个初衷,就是让基于图形硬件的编程变得和C语言编程一样方便,自由。正如C++和 Java的语法是基于C的,Cg语言本身也是基于C语言的。Cg语言极力保留了C语言的大部分语义,力图让开发人员从硬件细节中解脱出来,Cg同时拥有高级语言的好处,如代码的易重用性,可读性高等

4. 在Unity中编写的Shader最终会根据不同的平台来编绎成不同的着色器语言,官方的建议是用Cg/HLSL来编写,当然也可以使用GLSL,主要是因为Cg/HLSL有更好的跨平台性,更倾向于使用Cg/HLSL来编写Shader程序。

5. Unity Shader严格来说并不是传统上的Shader,而是Unity自身封装后的一种便于书写的Shader,又称为ShaderLab。

6. 在Unity中有3种Shader:

  • Surface Shaders 表面着色器。
  • Vertex/Fragment Shaders 顶点/片断着色器。
  • Fixed Function Shaders 固定管线着色器。

(1) Surface Shader其实就是Unity对Vertex/Fragment Shader的又一层包装,以使Shader的制作方式更符合人类的思维模式,同时可以以极少的代码来完成不同的光照模型与不同平台下需要考虑的事情

(2) Surface Shader也有它的局限性,就是Vertex/Fragment Shader能实现的效果,Surface Shader不一定能实现,反过来则成立,Surface Shader能实现的Vertex/Fragment Shader则一定可以实现

创建Shader

Unity中Shader种类

1. Standard Surface Shader

  • 标准表面着色器,是一种基于物理的着色系统(使用了Physically Based Rendering(简称PBR)技术,即基于物理的渲染技术),以模拟现实真实的方式来模拟材质与灯光之间的关系,可以很轻易的表现出各种金属反光效果,同时此种Shader的书写逻辑也更符合人类的思维模式。

2. Unlit Shader

  • Vertex/Fragment Shader,也就是最基本的顶点片断着色器,不受光照影响的Shader,多用于特效、UI上的效果制作

3. Image Effect Shader

  • 也是顶点片段着色器,只不过是针对后处理而定制的模板。

4. ComputeShader

  • Compute Shader是运行在图形显卡上的一段程序,独立于常规渲染管线之外的,它可以直接将GPU作为并行处理器加以利用,从而使GPU不仅具有3D渲染能力,还具有其他的运算能力

5. Shader Variant Collection

  • Shader变体收集器,它不是制作Shader的模版,而只是对Shader变体进行打包用的容器

注:以上的Standard Surface Shader、Unlit Shader、Image Effect Shader仅仅只是Unity为了方便我们书写而内置的几个模版,完全可以建一个Unlit Shader,然后将其改成Surface Shader,同样也可以将一个Standard Surface Shader改成顶点片断着色器,所以这一点一定要明白,它们只是内容格式不一样的模版本而已,我们完全可以自由修改成任意我们想要的一种着色器类型,当然我们也可以通过一些手段来定制出我们自己的模版。

材质和Shader的关系

1. 在Project视图中创建一个材质和一个Shder,直接在Project视图中将Shader拖动到材质上,即可对材质关联对应的Shader

2. Shader与材质的关系:

  • 一个Shader可以与无数个材质关联
  • 一个材质同一时刻只能关联于一个Shader,但是可以通过代码去动态改变材质所关联的Shader
  • 材质可以赋与模型,但是Shader不行。
  • 材质就像是Shader的实例,每个材质都可以参数不一样呈现不同的效果,但是当Shader改变时,关联它的所有材质都会相应的改变

Shader框架

命名

1. 如果我们把路径名称放在Hidden下面的话,比如:

Shader "Hidden/TA/MyFirstShader"
则表示在材质面板中隐藏此Shader,你将无法通过材质下拉列表中找到它。这在做一些不需暴露的Shader时很有用处,可以使Shader下拉列表更精简整洁

2. Shader文件的名称,也就是我们在Project面板中的资源文件的名称,是可以与Shader内部的路径名称不一样的,这点与C#是不同的。在定义内部路径名称时,建议统一规划下,不要Shader过多后导致很混乱,不便于美术去使用。

Properties

1. Properties可以理解为是材质与Shader的连接通道,在材质面板上需要设置的内容都必须通过Properties来实现并暴露。如果不需要属性的话也可以将整个Properties以及它的{}全部删除。

2. 语法格式:

(1) Attribute:

  • 属性标记,Unity内置的几个属性标记关键字,用于对当前这条属性进行一些特殊的处理,此标记不是必选项,可以不添加,同时一条属性上也可以有多条属性标记

(2) _Name:

  • 属性的名称,也就是变量名,在Shader的CG代码中就是通过这个名称来调用此属性内容的在外部利用脚本调用时也是这个名称,所以一定要用英文

  • 在名称前一定要加上下划线,否则会出现编绎错误。

(3) Display Name:

  • 显示在材质面板上的名称,主要起到说明解释的作用,可中文(正式项目中建议最好还是用英文)。

  • 一般使用作用与通道的组合命名,如BaseRGB。

(4) Type:属性的类型,常用的有以下几种:

  • Color颜色
  • Int整数
  • Float浮点数
  • Vector四维数
  • 2D纹理
  • 3D纹理
  • Cube立方体纹理
  • Default Value

(5) Default Value

  • 默认值,当第一次指定此Shader时,或者在材质面板上执行Reset时,属性的值会自动恢复到默认值,不同的类型具体写法也不太一样。

3. Properties举例。

注意:Shader中的浮点数值后不需要加后缀f,否则会出错零点几的值可以省略零,比如0.95可以写成.95

(1) Color颜色Type属性。前面用HDR限制后,会多出Intensity属性。

(2)数值和数值区间

(3) 开关和下拉列表

(4) 四维向量和2D纹理。其中2D纹理的默认值有以下几种:

  • white
  • black
  • gray
  • bump

如果不设置默认值,即=""{},则其实与="gray"{}相同。当设置了默认值后,Shader内部会自动调用Unity内部准备的一张小图片,white就是纯白色,black就是纯黑色,gray就是灰色图,bump就是法线图

(5) 3D纹理和立方体纹理

(6) 常用通用属性标记。

SubShaders

1. 实际上每个Shader中都可以包含多个SubShader,不可以没有,必须至少有一个,因为当前Shader的核心算法实现就是在SubShader中来实现的。

2. 在加载Shader时,Unity将遍历所有SubShader列表,并最终选择用户机器支持的第一个

3. 不同的硬件性能是不一样,游戏内通常把机器配置分为高中低三种,假如我们做了一个效果很好的Shader,但是却只能在高配机上有较好的性能表现,中低端就显的太费性能,SubShader在这时就可以派上用场了,可以在这个Shader内做三个SubShader,分别对应于高中低不同的配置。

4. 最简单的一个Shader:

(1) 在SubShader中,Pass即为走通一遍整个渲染管线。具体要怎么渲染就需要我们在Pass中添加Cg/HLSL代码片断来实现了,这段代码片断是由CGPROGRAM开始,由ENDCG结束

(2) 接着定义执行顶点着色器与片段着色器的名字,告诉Unity分别在哪里去执行它们。分别通过#pragma vertex和#pragma fragment去定义。

#pragma vertex VertexName
#pragma fragment FragmentName

(3) 接着定义类似下面代码的顶点着色器:

  • 顶点着色器函数的名称,与上面已经指定了顶点着色器的名称需要保持一致。
  • 输入参数中,仅仅定义一个或数个多维向量并不能使它拥有我们模型的顶点信息,需要为它指定一个语义,例如POSITION就是代表着模型的顶点位置信息。此时变量vertex就表示着我们模型的顶点位置。
  • 在顶色着色器中最主要的事情就是将顶点从模型坐标转换到裁剪坐标,Unity已经为我们准备好现成的命令,只需调用UnityObjectToClipPos函数即可。
  • 在后面片断着色器中需要顶点着色器中的输出结果,所以函数中需要加上return来将转换后的顶点返回。经过变换后返回的顶点位置,我们也需要利用语义来标记一下,以便片断着色器可以知道哪个是从顶点着色器输出过来的顶点位置信息,所以在函数的后面加上: SV_POSITION
  • 在顶点着色器中处理顶点时,首先需要获取到模型的顶点数据(比如顶点位置、法线信息、顶点颜色等等),这些数据都是直接存储在模型中的,我们在Shader中只需要通过标识语义就可以自动获得

(4) 经过顶点着色器的处理,已经得到了最终显示在屏幕上的顶点矩阵,内部会自动进行插值计算,以获得当前模型的所有片断像素,然后每个像素都会执行一次片断着色器,得到最终每个像素的颜色值

  • 片断着色器的函数名与#pragma fragment定义的名字一样,如果需要从顶点着色器传入额外参数,可以传入过来。
  • 在Cg/HLSL中使用Properties中的变量前还需要在Cg/HLSL中再重新声明一次,名称要求一致。float、half、fixed,这三都是浮点数的表示,只是分别对应的精度不一样,主要用此可以进行更进一步的优化。
  • SV_TARGET是系统值,表示该函数返回的是用于下一个阶段输出的颜色值,也就是我们最终输出到显示器上的值

(5) 顶点着色器与片断着色器的执行并不是1:1的,举个例子,一个三角面片,只有三个顶点,顶点着色器只需执行3次,而片断着色器由最终的像素数来决定,执行几百上千都是很正常的。所以从性能的角度来考虑,我们要尽量把计算放在顶点着色器中去执行。其次在片断着色器中也要尽量的简化算法,节省开支

Properties{_Color("CustomColor", Color) = (1, 1, 1, 1)}SubShader{Tags { "RenderType" = "Opaque" }LOD 100Pass//渲染一次模型{CGPROGRAM//Pass中开始执行#pragma vertex VertexName#pragma fragment FragmentNamefloat4 VertexName(float4 vertex : POSITION) : SV_POSITION{return UnityObjectToClipPos(vertex);}fixed4 _Color;float4 FragmentName() : SV_TARGET{return _Color;}ENDCG//Pass中结束执行}}

FallBack

1. 有的时候写的Shader难免在一些机器上会出现不支持的问题,而这个时候我们只要添加了FallBack,并且在后面的双引号内写上了其它Shader的有效路径名称,那么在碰到不支持的硬件时这个Shader就会自动切换成FallBack内的Shader,如果FallBack内的Shader也不支持呢,那就继续从FallBack内的Shader中再找FallBack。

CustomEditor

1. 自定义界面,也就是说我们可以通过这个功能来自由定义材质面板的显示结果,它可以改写Properties中定义的显示方式

举个你一定见过的例子:

Shader中变量相关问题

Cg/HLSL中的数据类型

1. 在Shader中,我们在Properties中定义的变量是为了在材质面板中显示并方便我们调节,如果要在Cg/HLSL中使用的话就必须要重新声明一次(要求命名一样)

2. 在Cg/HLSL中的几种常见数据类型:

(1) float/half/fixed(三个都是浮点数,只是精度不一样而已)

  • float高精度类型,32位,通常用于世界坐标下的位置,纹理UV,或涉及复杂函数的标量计算,如三角函数、幂运算等。
  • half中精度类型,16位,数值范围为[-60000,+60000],通常用于本地坐标下的位置、方向向量、HDR颜色等
  • fixed低精度类型,11位,数值范围为[-2,+2],通常用于常规的颜色与贴图,以及低精度间的一些运算变量等。
  • 在PC平台不管你Shader中写的是half还是fixed,统统都会被当作float来处理。half与fixed仅在一些移动设备上有效
    比较常用的一个规则是,除了位置和坐标用float以外,其余的全部用half。主要原因也是因为大部分的现代GPU只支持32位与16位,也就是说只支持float和half,不支持fixed

(2) integer(整型)

  • 整型类型,通常用于循环与数组的索引。

(3) sampler2D(2D纹理)

(4) samplerCUBE(3D纹理)

  • 默认情况下在移动平台纹理会被自动转换成低精度的纹理类型。
  • 如果需要中精度的或者高精度的需要用以下方式来声明:sampler2D_half(中精度2D纹理),sampler2D_float(高精度2D纹理),sampler3D_half(中精度3D纹理),sampler3D_float(高精度3D纹理),samplerCUBE_halft(中精度立方体纹理),samplerCUBE_float(高精度立方体纹理)

类型对应

1. Properties中的属性与Cg/HLSL中的对应关系如下:

  • Int/float/Range用浮点值表示,也就是float、half或者fixed,根据自己需要的精度来定义
  • Vector/Color用float4、half4或者fixed4表示
  • 2D类型用sampler2D表示。
  • 3D类型sampler3D表示。
  • CUBE类型用samplerCUBE表示。

2. 多Vector分量通常在颜色上用rgba,在向量上用xyzw,这样比较直观方便理解。

3. 在Shader中,矩阵是一个按照长方形阵列排列的浮点数集合。可以用floatMxN来表示,如果是4x4矩阵,就是float4x4(同样支持其它精度),不过有一点要注意,在某些平台上是不支持非方矩阵的(比如float3x2),特别是OpenGL ES 2.0平台

结构体传递多个值

1. 如果想在应用程序阶段传递多个值,除了顶点位置还想传递顶点色、UV坐标等到片元着色器中需要用到结构体。

2. 可通过在Shader中自定义函数调用来减轻把所有内容都写在片段和顶点着色器里面的问题,但是在使用之前必须要已经定义。

       Pass//渲染一次模型{CGPROGRAM//Pass中开始执行#pragma vertex VertexName#pragma fragment FragmentNamefixed4 _Color;struct SAppData{float4 vertext:POSITION;float2 uv : TEXCOORD;};struct STranslateData{float4 pos:SV_POSITION;float2 uv:TEXCOORD;};  STranslateData VertexName(SAppData InputMeshData) {STranslateData TranslateData;TranslateData.pos = UnityObjectToClipPos(InputMeshData.vertex);TranslateData.uv = InputMeshData.uv;return TranslateData;}float4 FragmentName(STranslateData InputVertexData) : SV_TARGET{return fixed4(InputVertexData.uv, 0, 1);}ENDCG//Pass中结束执行}

应用数据传递流程

应用阶段传入顶点着色器的数据

1. 当应用阶段的数据传过来时,顶点着色器怎么知道谁是模型的顶点数据谁又是模型的法线数据呢?需要一种方式来告拆计算机我们定义的变量代表着什么

struct SAppData
{float4 vertext:POSITION;float2 uv : TEXCOORD;
};

(1) 这里我们声明了一个float4类型的变量vertext,并给予了它顶点数据的语义(在变量后加冒号并跟一个语义),也就是说vertext变量将代表着模型的顶点数据被我们使用与传递。

2. 常见语义:

 struct appdata{float4 vertex : POSITION;        //顶点float4 tangent : TANGENT;       //切线float3 normal : NORMAL;         //法线float4 texcoord : TEXCOORD0;            //UV1float4 texcoord1 : TEXCOORD1;          //UV2float4 texcoord2 : TEXCOORD2;          //UV3float4 texcoord3 : TEXCOORD3;          //UV4fixed4 color : COLOR;          //顶点色};

顶点着色器到片断着色器的数据

1. 顶点着色器在处理完应用阶段传过来的数据后,会需要输出并传入片断着色器,这个时候我们同样需要定义一个结构来承载其中的数据,同样的,输出给片断着色器的值也需要语义来标识。

            struct STranslateData{float4 pos:SV_POSITION;float2 uv:TEXCOORD;};  

(1) 这里声明了float4类型的变量pos,并指定为SV_POSITION语义,表示pos就是顶点着色器输出的屏幕裁剪空间下的顶点位置这条语义是必须要有的,否则GPU无法进行接下来的光栅化处理

(2) 其实在现代GPU上对这里的语义如何定义并不关心了(除了SV_POSITION以外),主要是部分OpenGL ES2.0上面才需要特别注意而已。

2. 这里的语义除了SV_POSITION以外,我们还有另外两种选择:

(1) TEXCOORD0~N系列。例如TEXCOORD0、TEXCOORD1、TEXCOORD2...等等,主要用于高精度数据。

(2) COLOR0~N系列。例如COLOR0、COLOR1、COLOR2...等等,主要用于低精度数据。

3. 虽然这两种语义我们可以根据需要自由定义,但是,它并不是可以无限定义的,不同的GPU硬件有不同的数量限制。以下为手机平台的常见规则:

  • OpenGL ES2.0支持最多8个
  • OpenGL ES3.0支持最多16个

4. 从性能优化角度来讲,数量越少性能越好。另外,每个语义是4维向量,利用好这一点,可以大大节省总数量

5. 在片断着色器中还有些特殊的语义的可以识别,比如VFACE,如果渲染表面朝向摄像机,则Face节点输出正值1,如果远离摄像机,则输出负值-1。

完整代码如下:

fixed4 frag (v2f i,float face:VFACE) : SV_Target
{fixed4 col=1;col = face > 0 ? tex2D(_FrontTex,i.uv) : tex2D(_BackTex,i.uv);return col;
}

片断着色器输出相关语义

1. 通常情况下,片断着色器最终只需返回一个颜色值即可,也是我们最常见到的编写方式,如下:

fixed4 frag (v2f i ) : SV_TARGET

这里的SV_TARGET就是指定输出颜色到RenderTarget的语义

2. 当我们利用Struct时,就可以通过下列语义来输出多个内容:

  • SV_Target0〜N

默认SV_TARGET0,也就是SV_TARGET,还有SV_TARGET1,SV_TARGET2...这个在需要输出多个RenderTarget时很有用。

  • SV_Depth

3. 一般情况下,模型的像素深度值在光栅化时会自动插值计算得出,并不需要我们做额外的处理,但这并不代表不可以修改它,通过在片断着色器中输出SV_DEPTH语义可以更改像素的深度值。注意此功能相对会消耗性能,在没有特别需求的情况下尽量不要用。

Tags可选参数组

1. 在SubShader和Pass中都有Tags可选参数组,Tags的作用是告诉引擎如何去渲染我们的对象,语法格式如下:

Tags { "TagName1" = "Value1" "TagName2" = "Value2" }

SubShader Tags

SubShader中的Tags必须放置于SubShader中的Tags内。

Queue:

1. Queue渲染队列,指定对象什么时候渲染,每个队列其实都是利用一个整数进行索引的。整数索引值越小,越先渲染。有以下取值:

  • Background。值为1000,此队列的对象最先进行渲染。
  • Geometry。Queue的默认值,值为2000,通常用于不透明对象,比如场景中的物件与角色等
  • AlphaTest。值为2450,要么完全透明要么完全不透明,多用于利用贴图来实现边缘透明的效果,也就是美术常说的透贴。
  • Transparent。值为3000,常用于半透明对象,渲染时从后往前进行渲染,建议需要混合的对象放入此队列。
  • Overlay。值为4000,此渲染队列用于叠加效果。最后渲染的东西应该放在这里(例如镜头光晕等)。

2. 写法示例:

Tags{ "Queue" = "Geometry" }

3. 可以通过在值后加数字的形式来进行重新指定渲染队列

Tags{ "Queue" = "Geometry+1" }

4. 渲染队列直接影响性能中的重复绘制,合理的队列可极大的提升渲染效率。在Unity中,渲染队列小于2500的对象都被认为是不透明的物体,(如“Background”,“Geometry”,“AlphaTest”),这些物体是从前往后绘制的,而使用其他的队列(如“Transparent”,“Overlay”)的物体则是从后往前绘制的。这意味着,我们需要尽可能地把物体的队列设置为不透明物体的渲染队列,而尽量避免重复绘制

RenderType

1. 自带的值有以下这些:

  • Opaque
  • Transparent
  • TransparentCutout
  • Background
  • Overlay
  • TreeOpaque
  • TreeTransparentCutout
  • TreeBillboard
  • Grass
  • GrassBillboard

2. 这些名称实际上只是一种内部的约定,用来区别这个Shader要渲染的对象是属于什么类别的,可以想像成是把各种不同的物体进行分类一样。当然也可以改成自定义的名称,这样并不会影响到Shader的效果。

(1) RenderType它的作用是可以利用Camera.SetReplacementShader来更改最终的渲染效果。这是Unity的脚本API,需要在C#脚本中进行调用。其中EffectShader是我们需要渲染的Shader,Tag是用来筛选渲染对象用的。

camera.SetReplacementShader (EffectShader, Tag);

(2) 具体按以下规则执行:

  • 使用SetReplacementShader("shaderA",""),这里Tag为空,表示全部物体Shader都替换成shaderA进行渲染
  • SetReplacementShader("shaderA","RenderType"),由于这里Tag为"RenderType",所以先查看场景中的shader中是否有RenderType参数,如果有,再看RenderType中的值是否与shaderA中的RenderType值相等,相等则使用shaderA渲染,否则就不渲染(Game视图什么也没有)。
  • 关于Tag参数并不局限于RenderType,我们同样可以使用SetReplacementShader("shaderA","IgnoreProjector")或是其他任何参数如:SetReplacementShader("shaderA","ABC")等。

(3) 用法示例:实现替换材质开关功能。

其中taecg/Overdraw(此Shader实现的是类似于Overdraw的效果)这个Shader中的Tag如下:

而我们的物体(这头狼),我们给它的Shader中Tag如下:

DisableBatching tag

1. 有的时候,我们会利用Shader在模型的顶点本地坐标下做一些位移动画,当此模型有批处理时会出现效果不正确的情况,这是因为批处理会将所有几何转换为世界坐标空间,因此“本地坐标空间”将丢失

"DisableBatching" = "True"

2. 这时我们就可以利用此Tag在Shader中指定是否受批处理影响,有以下3个值可选:

  • False(默认值),不禁用批处理
  • True,始终禁用此着色器的批处理
  • LODFading,仅当LOD激活时禁用批处理

ForceNoShadowCasting tag

1. 是否强制关闭投射阴影,值可为:

  • True,强制关闭投射阴影
  • False(默认值),不关闭投射阴影
"ForceNoShadowCasting" = "True"

IgnoreProjector tag

1. 是否忽略Projector投影器的影响,Projector是Unity中内置的组件,可用于实现贴花等功能。

  • True,使对象不受Projector影响
  • False(默认值),使对象受Projector影响

CanUseSpriteAtlas tag

1. 是否可用于精灵打包图集,意思就是如果某个图片精灵被设置为打包进图集中,那么当此精灵所指定Shader中设置为

"CanUseSpriteAtlas"="False"

时就会使其无法工作,相应的UI上也会有警告提示。

PreviewType tag

1. 此Tag决定了材质面板的预览窗口如何显示模型,默认显示的是球体,当我们把值定义为以下两种情况时会进行相应的变化。此功能仅仅影响的只是材质面板的预览,对Shader本身没有什么影响

  • Plane平面预览
  • Skybox天空盒预览

Unity之Shader相关推荐

  1. Unity编写Shader内置各种矩阵和方法介绍

    返回目录 大家好,我是阿赵. 这里记录一下Unity编写Shader内置各种矩阵和方法 一.Unity内置转换矩阵 1.MVP类矩阵 UNITY_MATRIX_MVP:Current model * ...

  2. Unity初学者Shader Graph教程

    Unity初学者Shader Graph教程 了解面向非程序员的 Unity 引擎可视化着色器编程工具的来龙去脉 课程英文名:Your Ultimate Guide to Shader Graph f ...

  3. 1.Unity之Shader新手入门

    Unity Shader着色器的基本概念 如何使用Unity Shader着色器 示例:如何使用Unity Shader着色器创建复杂的效果 总结 什么是Unity中的Shader着色器? Shade ...

  4. Unity学习shader笔记[一百]简单焦散Caustic效果

    焦散是模仿光透过水底的一个投影景象 有两个版本,改版最后效果如下 这里是简单的基于物体的焦散,基于水体的焦散思路是水面物体的shader中拿到ColorBuffer,然后用水体的屏幕空间坐标取采集Co ...

  5. Unity之Shader基础探索

    Unity之Shader基础探索 一.什么是Shader? 1.Shader的开发语言 2.着色器用途 3.着色器的编辑 4.着色器性能分析工具 5.着色器编译 6.异步着色器的编译工作原理 7.内置 ...

  6. Unity使用Shader快速制作一个圆形遮罩

    Unity使用Shader快速制作一个圆形遮罩 如何用Shader来做出圆形.切倒角和边缘虚化 Unity使用Shader快速制作一个圆形遮罩 橙子前言 一.创建Shader 二.创建Material ...

  7. Unity官方Shader介绍: TRANSFORM_TEX

    Unity官方Shader介绍: TRANSFORM_TEX 文章目录 Unity官方Shader介绍: TRANSFORM_TEX 纹理(Texture) 纹理坐标(UVW, STR) 纹理映射(T ...

  8. Unity 流光shader 记录分享

    Unity 流光shader 转载自:链接 Shader "Custom/DataFlowEffect" {Properties{_MainColor("Main Col ...

  9. Unity中用shader graph制作一个简单的传送门效果

    Unity中用shader graph制作一个简单的传送门效果 一.配置渲染管线 1.通过菜单"Asset" --> "Create" --> &q ...

  10. Unity树叶shader

    Unity树叶shader 树叶贴图的RGB的G小于设定的颜色阈值的话将会被视为透明 Shader "ACP/tree" {Properties{_FrontTex("贴 ...

最新文章

  1. hdu6989 (莫队+单调栈+ST表)
  2. 用mysqldump远程备份mysql数据库
  3. 第四篇:Mysql查询-多表联合查询-及子查询
  4. Linux服务器网卡驱动安装及故障排除(转)
  5. HDFS HA模式下支持只连接其中Active的NameNode
  6. RabbitMQ常用操作命令和入门案例(一对一的简单模式)
  7. [哀悼]5.12地震后把网站改成灰色的方法
  8. 织梦html2text( me),织梦dedecms中function='Html2Text(@me)的使用方法
  9. Jfinal3.4+layui2.4.3整合
  10. python 列举图像颜色
  11. 【论文阅读】Speicher: Securing LSM-based Key-Value Stores using Shielded Execution
  12. 1946年产生的第一台电子计算机6,1946年第一台计算机在美国诞生——青夏教育精英家教网——...
  13. 光量子计算机技术突破,真正突破光刻机封锁的技术诞生了!可编程光量子计算芯片是什么?...
  14. linux下LTP工具说明
  15. Python画玫瑰花
  16. 【我想对策划说的事】-- 入职dy一年后被邀请召开的扯淡分享会讲稿
  17. 强、弱、一般、健壮等价类区别
  18. JS逆向之巨量星图sign签名
  19. css3特效(上下左右晃动效果)
  20. 目前可以放google adsense的所有免费博客

热门文章

  1. Unity 基于Terrain系统 真实弹坑的实现
  2. Web面试之 HTML与CSS
  3. 一款好用的开源家庭服务器管理工具
  4. Linux操作系统入门
  5. python计算平均数、中位数及标准差
  6. 数学建模论文怎么写(二)
  7. 第十三讲:常微分方程
  8. 硬件大熊原创合集(2022/02更新)
  9. PostgreSQL 在WAL文件中查找drop table、update、delete操作
  10. 数控CNC加工行业“做模具难还是做产品难”?