Unity3D Shader 入门第一天

Unity3d Shader UV移动 本文使用UV偏移,创建车道方向动画 原始素材 最终效果(带水平向移动)Unity3d纹理坐标 偏移:Offset(xo,yo),将原点偏移到(xo,yo)。 平铺:Tiling(xt,yt),以偏移后的坐标为新原点,平铺(xt,yt)范围 Unity3d在创建Material,默认Offset = (0, 0),Tiling(1, 1)。即原点不偏移,平铺方向各1次。也就是原图显示。Uni 阅读详情

刚开始接触Unity3D Shader编程时,你会发现有关shader的文档相当散,这也造成初学者对Unity3D Shader编程望而却步。该系列教程的第一篇文章(译者注:即本文,后续还有5篇文章)详细介绍了Unity3D中的表面着色器(Surface Shader)的,为学习更复杂的Shader编程打下基础。

动机

如果你是刚刚接触Shader编程的新手,你可能不知道从何开始踏出Shader编程的第一步。本教程将带你一步步完成一个表面着色器(Surface Shader)和片段着色器(Fragment Shader)。本教程也将介绍在Unity3D Shader编程中所使用的一些函数和变量,这些内容可能和你在网上看到的不一样哦!

如果你满足下面的条件,我觉得你应该看看这篇文章:

  • 如果你是shader编程的新手。
  • 你想在你的游戏中使用shader做一些很炫酷的效果,但是你在网上找不到可用的Shader(译者注:o(╯□╰)o自己动手丰衣足食)。
  • 由于缺乏对基础知识的了解,造成不能随心所欲使用Strumpy着色器编辑器(译者注:Strumpy Shader Editor,一种图形化编写shader的方式,看着很诱人!)。
  • 你想在你的shader代码中手动处理纹理(Textures)

本文是该系列教程的第一篇文章,随后我们会制作一些更复杂的shader。相比起来,第一篇文章确实很简单。

 

My reason for getting into shader programming was to build something that I needed for a world populated with an endless array of different characters.  I needed to build a combined mesh out of multiple parts so I only have one draw call per character.

通过打开和关闭角色的穿衣效果,我使用Megafiers(一个变形插件)修改了角色的基本网格(base meshes)。其中的困难在于我只有一个纹理(texture),但是我却想给每个角色的皮肤,服饰以及其他的特征使用不同的颜色。我想到一个方法----对每个角色使用不同的3个4x4纹理,并使用一个shader来给模型上色。我将在整个教程中详细描述我做的这个shader,但是现在—我想你们已经迫不及待地想看我创建的角色表演一段即兴的快闪舞(flash mob dance)(译者注:网上截的图片)。

技术分享

着色器和材质(shaders&materials)

一个shader所做的就是将一个模型的网格(mesh)渲染到屏幕上。Shader可以被定义为一系列的属性(译者注:就像一个函数里面的参数一样,你可以改变函数的不同赋值来改变函数的输出结果),你可以通过改变这些属性来改变模型渲染到屏幕上的效果。而这些属性被存放起来,放到一个叫做材质(material)的地方。

Unity3D Shader有以下几种

  • 表面着色器(surface shader)----后台自动为你做的绝大部分的工作,减少了你工作量,并且适合绝大多数需要shader的情况。
  • 片段着色器(fragment shader)----可以让你做更多的效果,但是此shader更难写。你也可以用它做一些底层的工作,比如顶点光照(Vertex lighting,即在每个顶点存储该点的光照信息)。顶点光照对于移动设备很有用(译者注:估计省内存吧)。该shader对于一些需要多通道(multiple passes)的高级渲染效果也很有效。

本文中我们将关注点放在表面着色器上。

学习Shader的资源

如果你要学习Shader编程,我向你推荐下面几个资源

  • Martin Kraus‘s fantastic Wiki Book GLSL Programming/Unity
  • Unity‘s Shader Reference
  • NVidia‘s tutorial on the CG programming language
  • CreativeTD‘s video series on writing surface shaders

Shader的流水化工作方式

(译者注:Shader的工作方式也称为shader流水线(pipeline),因为shader工作方式很类似汽车流水线,将模型上一系列顶点数据和其他各种数据作为输入,用这个shader组成的流水线加工下,出来的就成了炫酷的效果了。)

你将在shader流水线中看到不明觉厉的各种术语,我将用我自己的语言尽量降低理解的难度。

Shader的工作就是输入一些3D几何信息,经过shader处理后将其变为2D的像素呈现在屏幕上。好处是在shader处理过程中,你只需要改变少数几个属性就可以产生不同的效果。对于表面着色器,该工作流程看起来像下面这样:

技术分享

(译者注:简单讲解一下这个流程图,首先要渲染的物体将自己的几何信息传递到Shader中,并且系统得到了该物体的顶点信息,然后你可以选择经不经过Vertex Function来处理这些顶点信息,随后经过光栅化(将三维几何信息映射到二维屏幕上,打个不恰当的比喻,相当于把3D模型拍扁到屏幕上,然后你就可以专心处理屏幕上的像素了),每个像素经过你的shader代码将得到最终的颜色值)

注意在表面着色器(Surface Shader)中的函数退出之前,像素的颜色还没有计算出来。这意味着你可以再次之前传入顶点的法向量来影响光照的计算。

片段着色器(Fragment Shader)有着同样的工作流程,但事实上,片段着色器中必须有Vertex Function(上图中的Vertex Function部分就是可选的(Optional)),而且需要在像素处理阶段做很多的工作才能产生最终的像素。而表面着色器隐藏了这些。(译者注:给我的感觉就是片段着色器向用户提供了更多的接口进行更高级的渲染)。

下图展示了你的代码如何被调用以及代码构成

技术分享

从上图我们可以看到,当你写一个shader的时候,你可能得有一些属性值(properties),并且有一个或多个Subshaders。具体使用哪个Subshader进行处理取决于你的运行平台。你应该还要指定一个Fallback shader,当你的subshader没有一个能运行在你的目标设备上,将使用Fallback shader(译者注:有点像备胎)。

每个Subshader都至少有一个通道(pass)作为数据的输入和输出。你可以使用多个通道(passes)执行不同的操作,比如在一个Grab Pass中,你可以获取将要呈现到屏幕上的像素值(译者注:类似于glsl中的fragment buffer)。当你想制作高级的扭曲效果,这非常有用。虽然当你开始学习shader编程时,你可能并不会使用到它。另外一个使用多通道(multiple passes)的原因是在不同时刻,你可能需要写入或者禁止写入深度缓存的使用。

当你写表面着色器时,我们将直接在Subshader这个层次上写代码,系统将把我们的代码编译成若干个合适的通道(pass)。

尽管shader最终产生的是二维像素,但是其实这些像素除了保存xy坐标外,本身保存着深度值(即每个像素点上的内容在原先3D场景中离照相机的远近),这样距离照相机近的物体就会把距离照相机远的物体遮挡住,在屏幕上显示时,就是将其像素值覆盖。

你可以控制是否在你的shader中使用深度缓存(Z-buffer)产生一些特效,或者在Pass中使用一些指令决定shader是否可以写入Z-buffer:比如使用ZWrite Off时,任何你输出的东西都不会更新Z-buffer的值,即关闭的Z-Buffer的写入功能。

你可以使用Z-buffer技术在别的物体上掏出一个洞,你可以先写入需要打洞区域的深度值,但不输出打洞区域所属的像素值,然后在你模型后面的物体的深度值将无法写入(因为Z-buffer觉得你的模型已经挡住了后面的物体)(译者注:这样你打洞区域显示的就是一开始使用的背景色,会造成一个洞穿过了这些物体的效果)。

下面是一些shader代码:

技术分享

希望你能看出上面代码是由Properties,SubShader,Fallback三段代码组成的。

理解Shader代码

文章剩下的部分将讲述上面那段简单代码到底做了什么?真正的干货马上就来了,你必须好好掌握这些内容。

当你进行shader编程时,你必须使用正确的变量名和函数名来调用它们,事实上变量的名称在某些情况下能让人一眼看出它的特定含义。

创建并使用默认Shader

(译者注:在详细介绍Shader之前,我们先简单介绍下shader如何使用。)

1. 我们先打开Unity(我的版本是4.6.1),创建新工程,并在Assets文件夹下创建三个目录,如下:

技术分享

2. 我们再创建一个cube。

技术分享

可以在Inspector面板看到新创建的cube所使用的Material如下。

技术分享

3. 打开Material文件夹,我们在其中创建一个Shader和一个Material。

技术分享

此时New Material的默认Shader为Diffuse。

技术分享

我们将NewShader拖到New Material上。

技术分享

可以看到该材质所使用的Shader变成我们新建的NewShader了。当然你也可以直接点击材质编辑器中Shader下拉框,选择相应的Shader。

4. 最后将New Material拖到cube上。可以看到cube所使用的材质和Shader都变成了我们新创建的材质和Shader了。

技术分享

Properties(属性值)简介

你在shader代码中的Properties{…}部分定义Shader中的属性值(属性值就是用户传入给shader的数据,比如纹理之类的,然后shader处理这些纹理,产生特效。可以理解为属性值相当于一种全局变量,而Shader就是那个主函数,Unity的优势在于给这个全局变量赋值可以在Inspector面板进行)。注意Properties(属性值)是所有Subshader代码中的共享的,意味着所有SubShader代码中都可以使用这些属性值。

属性值(property)定义的形式:

_Name(“Displayed Name”,type) = default value[{options}]

  • _Name 属性值的名称,是在shader代码内部使用的,区别于下面的Displayed Name,后者是在Inspector 面板上显示的,作为外界(用户)的输入提示。
  • Displayed Name 呈现在材质编辑器中的属性值名称,在Inspector面板上显示。

总结:打开我们创建的NewShader。可以看到_MainTex是在代码中使用的,而Base (RGB)是在材质编辑器中使用的

技术分享

  • type 属性值的类型,包括:
    • Color – 表示纯色,使用了RGBA表示法
    • 2D – 代表尺寸为2的幂次的纹理(如2,4,8,16…256,512)
    • Rect – 代表纹理(texture),不同于上面的纹理,此处纹理的大小不一定是2的幂次。
    • Cube – 用于3d中的cube map,经常提到的天空盒就是使用了cube map。
    • Range(min, max) – 在min和max之间的一个值,在面板中可用滑动条改变其值大小。
    • Float – 任意一浮点数。
    • Vector – 4维向量值,本质就是4个浮点数组成的类型。

来张全家福:

技术分享

技术分享

  • default value 属性值的初始值,就相当于你的变量初始化的那个值。
    • Color – (red,green,blue,alpha) 使用了RGBA这种格式的颜色,alpha指的是透明度– 比如 (1,1,1,1)
    • 2D/Rect/Cube – 纹理的类型,上面已经介绍过了。初始化值可以使一个空字符串,或者"white", "black", "gray", "bump"(说明此纹理是一个凹凸纹理)
    • Float/Range – 这个没啥说的,跟浮点数初始化一样一样的
    • Vector – 4维向量,其中4个数均为浮点数 (x,y,z,w)
  • { options } 这里注意了,{options} 仅仅用于纹理类型,比如上面提到的2D,Rect,Cube,对于这些类型,如果没有options可填,至少要写一个空的{},否则编译出错。可以使用空格将多个options(选项)分开 ,可用的options(选项)如下:
    •  TexGen texgenmode:纹理坐标自动生成的方式。可以是ObjectLinear, EyeLinear, SphereMap, CubeReflect,CubeNormal其中之一,这些方式和OpenGL中的纹理坐标生成方式相对应,具体详见这篇博文。注意当你写Vertex Function时,纹理坐标产生方式将被忽略。

下面举几个属性值写法的例子:

// 定义了一个半透明(alpha=0.5)效果的红色作为默认颜色值

_MainColor(“Main Color”,Color)=(1,0,0,0.5)

// 定义了一个默认值为白色的纹理

_Texture(“Texture”,2D) =”white” {}

注意属性值的定义末尾处不需添加分号。

标签(Tags)

你的表面着色器可以用一个或多个标签(tags)进行修饰。这些标签的作用是告诉硬件何时去调用你的shader代码。

在我们的例子中,我们使用:Tags {“RenderType” = “Opaque”},这意味着当程序去渲染不透明的几何体时,将调用我们的shader,Unity定义了一系列这样的渲染过程。另一个很容易理解的标签就是Tags {“RenderType” = “Transparent”},意味着我们的shader只会输出半透明或透明的像素值。

其它一些有用的标签,比如“IgnoreProjector”=“True”,意味着你渲染的物体不会受到projectors(投影仪)的影响。

“Queue”=“xxxx”(给shader所属的对象贴上渲染队列的标签)。当渲染的对象类型是透明物体时,Queue标签能产生一些非常有趣的效果。该标签决定了物体渲染的顺序(译者注:我猜测它的工作方式是这样的,一个场景中有很多个物体,当这些物体被渲染时,必须有一个渲染的顺序,比如背景应该比其他物体先渲染出来,否则背景会将之前渲染的物体遮挡住,具体方法是将背景使用的shader中贴上一个“Queue”=“Backfround”标签,这样使用该shader的物体将被贴上Background的标签。总之当渲染整个场景时,unity会根据这些渲染队列的标签决定按什么顺序去渲染对应标签所属的物体)。

  • Background – 在所有其他物体渲染之前渲染,被用于天空盒或类似的背景效果。
  • Geometry(默认tags为geometry) – 适用于大多数物体。非透明物体使用这种渲染顺序。
  • AlphaTest – 顺利通过alpha测试的像素(alpha-test是指当前像素的alpha小于一定的值就舍弃该像素)使用该渲染顺序。单独设置该渲染顺序是因为在所有实体渲染过后,该渲染顺序将对渲染经过alpha测试的物体更有效率。
  • Transparent – 该渲染标签所属的物体将在标签为Geometry和AlphaTest之后的物体渲染,并且这些贴着Transparent的所有物体本身是从后往前依次渲染的。任何经过alpha-blended的物体都应该使用该标签(译者注:alpha-blended是指使用当前像素的alpha作为混合因子,来混合之前写入到缓存中像素值,此时注意shader是不能写入深度缓存的,因为如果不关闭写入深度缓存,那么在进行深度检测的时候,它背后的物体本来我们是可以透过它被我们看到的,但由于深度检测时,小于它的深度就被剔除了,从而我们就看不到它后面的物体了),玻璃和粒子效果比较适合该渲染标签。
  • Overlay – 该渲染标签适合覆盖效果,任何最后渲染的效果都可以使用该标签,比如透镜光晕。

有趣的是你可以给这些基本的渲染标签进行加加减减。这些预定义的值本质上是一组定义整数,Background = 1000, Geometry = 2000, AlphaTest = 2450, Transparent = 3000,最后Overlay = 4000。(译者注:从此处我们也可以一窥究竟,貌似数值大的后渲染。)这些预设值这对透明物体有很大影响,比如一个湖水的平面覆盖了你用广告牌制作的树,你可以对你的树使用“Queue”=”Transparent-102”,这样你的树就会绘制在湖水前面了。

Shader的整体结构

让我们回顾下shader代码的结构。

技术分享

#pragma surface surf Lambert 这段代码表示其中surface表示这是一个表面着色器,进行结果输出的函数名称为surf,其使用的光照模型为Lambert光照模型。

我们的CG程序使用了一种经过修饰的类C语言 —— CG语言(是Nvidia和微软共同出品的一种shader语言)。详见Nvidia的文档 —— 我在文中也会介绍一些基本的Cg使用方法。

浮点数类型(float)和向量值类型(vec)一般都会在末尾加上2,3,4这些数字(float2,float4,vec3…)表示该类型具体有几个元素组成。这种定义方式使数值操作变得更方便,你可以将其当做一个整体使用,或者单独使用其分量。

//定义一个浮点类型的二维坐标

vec2 coordinate;

//定义一个颜色变量(4个浮点值分量的颜色值)

float4 color;

//通过点乘得到3个浮点值分量的颜色值

float3 multipliedColor = color.rgb * coordinate.x;

你可以使用.xyzw或.rgba来表明你使用的变量类型具体的含义,比如.xyzw可能表示的是旋转四元数,而.xyz表示位置或法向量,.rgba表示颜色。当然,你可以仅仅使用float作为单个浮点值类型。其实对.rgba等分量访问符的使用也称作swizzle,尤其是对颜色的处理,比如颜色空间的转换可能会用到它,比如color=color.abgr;

你将会遇到half(半精度)和double(双精度)类型,half(一般16bit)即正常float(一般32bit)的一半精度,double(一般64bit)是正常float的两倍精度(此处的倍数衡量的方式不是指表示的范围,而是表示可以使用的bit位数)。使用half经常是出于性能考虑的原因。还有一种区别于浮点数的定点数fixed,精度更低。

当你想将颜色值规范到0~1之间时,你可能会想到使用saturate函数(saturate(x)的作用是如果x取值小于0,则返回值为0。如果x取值大于1,则返回值为1。若x在0到1之间,则直接返回x的值.),当然saturate也可以使用变量的swizzled版本,比如saturate(somecolor.rgb);

你可以使用length函数得到一个向量的长度,比如float size = length(someVec4.xz);

如何从表面着色器输出信息

我们的surface function(表面函数)每个像素调用一次,系统已经事先计算出当前处理的像素的输入值(准确来说应该是输入结构体,即Input IN中的Input类型)。 它是根据每个网格上的面片,并进行插值得到的结果。

来看看我们的surf函数

void surf (Input IN, inout SurfaceOutput o) {

    o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;

}

很明显我们可以看出,我们返回了o.Albeodo值 – 该值是Unity为我们定义的SurfaceOutput结构体中的某个成员。接下来让我们看看SurfaceOutput具体定义了哪些成员。该Albedo表示像素的颜色。

struct SurfaceOutput {

    half3 Albedo; //该像素的颜色值

    half3 Normal; //该像素的法向量

    half3 Emission; //该像素的辐射光,辐射光是最简单的一种光,它直接从物体发出并且不受任何光源影响

    half Specular; //该像素的镜面高光

    half Gloss; //该像素的发光强度

    half Alpha; //该像素的透明度

};

你只要将该结构体中值交给Unity,Unity会自动根据这些值产生最终效果,而不需要你关心其中的细节。

我答应你们的干货就在下面

首先看看作为我们surf函数的输入是啥?

我们定义了一个输入结构体如下:

struct Input {

    float2 uv_MainTex;

};

通过简单地创建结构体,我们告诉系统当我们每次调用surf函数时,获取MainTex在该像素的纹理坐标。如果我们有第二个纹理叫做—_OtherTexture,我们可以通过在输入结构体中添加下面代码得到它的纹理坐标

struct Input {

    float2 uv_MainTex;

    float2 uv_OtherTexture;

};

如果对于其他纹理,我们有第二套纹理坐标,我们可以这样做:

struct Input {

    float2 uv_MainTex;

    float2 uv2_OtherTexture;

};

此时对于我们所使用的所有纹理,我们的输入结构体包含一套uv坐标或者一套uv2坐标。

如果我们的shader很复杂并且需要知道像素的其他相关信息,我们就可以将以下变量包含在输入结构体中,以此来查询其他的相关变量。

  • float3 viewDir – 视图方向( view direction)值。为了计算视差效果(Parallax effects),边缘光照(rim lighting)等,需要包含视图方向(view direction)值。
  • float4  with COLOR semantic(比如float4 currentColor,即用户自定义和颜色相关的变量名称) – 每个顶点(per-vertex)颜色的插值。
  • float4 screenPos – 为了反射效果,需要包含屏幕空间中的位置信息
  • float3 worldPos – 世界空间中的位置
  • float3 worldRefl – 世界空间中的反射向量。如果表面着色器(surface shader) 不为SurfaceOutput结构中的Normal赋值,将包含这个参数。
  • float3 worldNormal – 世界空间中的法线向量(normal vector)。如果表面着色器(surface shader) 不为SurfaceOutput结构中的Normal赋值,将包含这个参数。
  • INTERNAL_DATA – 相对于上面的float3 worldRefl和float3 worldNormal,如果表面着色器为SurfaceOutput结构中的Normal赋值了,将使用该参数。为了获得基于每个顶点法线贴图( per-pixel normal map)的反射向量(reflection vector)需要使用世界反射向量(WorldReflectionVector (IN, o.Normal)),其中o.Normal表示的是切空间的法向量,而非世界坐标系下的法向量。
  • 你可能会问上面的COLOR semantic是什么意思?当你写一个正常的片段着色器时,你得告诉别人你的输入结构体每个变量代表什么意思?如果你够疯狂,你可以试试下面这样定义:float2 MyUncleFred : TEXCOORD0; 并告诉别人MyUncleFred表示该模型的uv坐标。(画外音就是这种变量命名方式很令人费解)在表面着色器中你唯一担心的就是对COLOR类型的定义。float4 currentColor : COLOR;可以看做目前已经经过插值后的像素颜色。当然你也可以不用关心这些,不过建议你命名上最好规范些,方便自己也方便别人。

该shader实际做了哪些事?

现在我们还有两行代码没有详细讨论:

Sampler2D _MainTex;

对每一个属性值,我们定义了属性值区域(Properties Section),该区域用来定义CG程序中使用的变量。在使用中,我们必须保证属性名称一致。

技术分享

注意输入结构体中的uv_MainTex是uv+对应属性值(文中为_MainTex,注意前面带下划线是CG官方推荐的写法),如果你使用uv2,那将写作uv2_MainTex。注意Sampler2D _MainTex中的_MainTex变量是一个Sampler2D(这个Sampler2D,可以理解为引用一个2D Texture),它引用了Properties中的_MainTex(译者注:注意两者同名。解释通了sampler2D是什么之后,还需要解释下为什么在这里需要一句对_MainTex的声明,之前我们不是已经在Properties里声明过它是贴图了么。答案是我们用来实例的这个shader其实是由两个相对独立的块组成的,外层的属性声明,回滚等等是Unity可以直接使用和编译的ShaderLab;而现在我们是在CGPROGRAM...ENDCG这样一个代码块中,这是一段CG程序。对于这段CG程序,要想访问在Properties中所定义的变量的话,必须使用和之前变量相同的名字进行声明。于是其实sampler2D _MainTex;做的事情就是再次声明并链接了_MainTex,使得接下来的CG程序能够使用这个变量。),他可以根据指定的uv坐标来提供对应纹理上的像素值,而此处uv_MainTex的作用就是提供纹理_MainTex的uv坐标值。

如果我们定义了一个_Color变量,我们可以定义它的属性为

float4 _Color;

我们surf函数中唯一一行代码

o.Albedo = tex2d( _MainTex, IN.uv_MainTex).rgb;

tex2d的作用是利用IN.uv_MainTex所代表的uv坐标(注意我们上面指定了uv坐标产生的方式,所以此处的IN.uv_MainTex是自动生成的)对纹理_MainTex进行采样。此处,对于o.Albedo我们只取颜色分量中的rgb三分量,其中alpha值(透明度)目前不需要,至少对于非透明物体alpha值得作用不大。

如果你要设置alpha值的话,可以像下面这样赋值

float4 texColor = tex2d( _MainTex, IN.uv_MainTex );

o.Albedo = texColor.rgb;

o.Alpha = texColor.a;

总结

你已经了解了很多的术语,但是目前我们所写的shader还相当有限,但是当学习完第二部分教程后,我们就可以做一些很酷炫的shader了,因为第二部分我们将开始使用多重纹理,法向量等等酷炫技术。

  • 在第二部分中,我们创建了一个实现积雪效果的shader,根据积雪的程度来修改模型,以呈现不同效果。
  • 在第三部分我们改进了我们的shader来混合岩石边缘的积雪。
  • 在第四部分,我们使用黑色边缘和渐变纹理来创建了具有卡通效果的shader。
  • 在第五部分,我们创建了一个顶点/片段多通道凹凸纹理着色器(vertex/fragment multipass bumped shader) – 其复杂程度远远超越表面着色器
  • 在第六部分,我们创建了一个顶点/片段着色器(vertex/fragment shader)来制作相比于我们第四部分使用表面着色器制作的卡通效果shader更好的shader。
Unity3D 双面渲染Shader实现 概述 在建模软件中可以为每个顶点设置法线,三个顶点可以组成一个三角面,三角面的法线是根据其顶点的法线插值而来,这个法线朝向就代表了这个平面的正面。 而在现代大部分引擎和游戏中,会默认只显示平面的正面,即对每个三角面进行一次面法线和摄像机出射向量的点积,判断正负,如果当前平面是背面朝向摄像机,则不渲染该面片。 Unity 的standard shader就是这样,我们只要创建一个平面就能看出这种效果。 创建一个平面,默认此平面正面朝上。 我们调整角度从下往上看,平面完全不渲染了。除了一个选中的什么都看不见( 阅读详情

相关推荐

详解Unity3D Shader之Shader Lab框架

笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,优快云社区专家,特邀编辑,畅销书作者,国家专利发明人;已出版书籍:《手把手教你架构3D游戏引擎》电子工业出版社和《Unity3D实战核心技术详解》电子工业出版社等。优快云课程视频网址:http://edu.youkuaiyun.com/lecturer/144 网上有很多关于Shader的教程,我在这里就不给读者讲解基础知识了,我们直接讲重点,我会结合着

海洋个人博客 4112

Unity3D Shader 入门

Shader的种类Unity Shader 是将传统的硬件Shader(由 Cg / HLSL编写)嵌入到独有的描述性结构中而形成的一种代码生成框架,最终会自动生成各硬件平台自己的Shader,从而实现跨平台。Unity Shader 分为 表面着色器(Surface Shader)和 顶点片段着色器(Vertex And Fragment Shader)。 表面着色器(Surface Shader

悦峰原创博客 2万+

Unity3D引擎之Shader Forge应用

笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,优快云社区专家,特邀编辑,畅销书作者,国家专利发明人;已出版书籍:《手把手教你架构3D游戏引擎》电子工业出版社和《Unity3D实战核心技术详解》电子工业出版社等。优快云视频网址:http://edu.youkuaiyun.com/lecturer/144 本篇博客给读者介绍一个材质渲染的组件-Shader Forge,在材质渲染中可以起到事半功倍的效果

海洋个人博客 5742

【Unity】Shader编程 基础总结

Shader编程一直是一个比较难入门难上手的主题,本篇对Unity Shader编程的一些基础和要点进行了总结。 包括Shader编程相关知识图谱、Shader编程相关数据类型、Shader核心结构体等(后续继续补充)。 每个部分相互独立,可以单独参考,亦可作为一个整体参考。

杜子兮@优快云 2878

[Unity3D] [Shader] 实现基于NDC的Sprite渐隐Shader

1. 准备 Unity3Dphttp://download.unity3d.com/download_unity/builtin_shaders-4.3.4.zip

ManwithRose 5167

Unity3d中Shader的一些常用方法

float4 tex2D(sampler2D samp, float2 s) 2D纹理采样,CG内置函数。 内部实现分为以下几步: 1. 用图片的宽高度乘以uv数值,得到像素坐标。widthPixel=samp.x*s.x;heightPixel=samp.y*s.y; 2. 因为取到的数值基本上都是带有小数点的,也就是说不是一个整数,这个时候,需要看图片的过滤设置了。也就是Unity

yutyliu的专栏 1万+

Shader,想说爱你不容易。

这两天开始接触shader,给我的第一感觉是容易,第二感觉是难,第三赶脚是数学不好就先学数学吧! 首先我们通过unity自己创建一个shader脚本的时候,其实shader已经给我们搭建好了编写shader基本的框架,我们要做的就是往里面写自己的shader,但是写之前总的先认识这里面有啥子东西吧。先创建一个shader瞅瞅,如下: Shader "Custom/MyShader" {

Can的专栏 1951

【Unity3D优化】优化内置shader的内存占用

在打AB包的过程中,并不会把这些Built-in的shader单独打包,并与材质球和预设体做好依赖,因此打AB包时,Unity会自行在材质球和预制体的AB包内每一个都包含进去用到的Built-in的Shader,而且运行时,由于加载的是不同的AB包,shader也是不同的实例,占用的也是多份内存。结合项目特点可以分析,由于项目里使用了大量的粒子特效,一些特殊的效果,会给特效师写定制的shader,但是这些常见的效果,特效师直接使用了Unity Built-in的shader。继续优化内存占用。

a310989583的专栏 2311

UnityShader介绍新手向,让你一看就懂的那种~

前言 做Unity很久了也不会Shdaer,最近趁着略空闲了解了以下,这里做一个引导,想要更进一步的了解请移步冯乐乐的《UnityShader入门精要》,墙裂推荐! 使用步骤 Shader "Unlit/m_UnlitShader"//一个成功的shdaer必定需要一个名字,在这里我们将其命名为:m_UnlitShader。代表这是我们自己的shader!仪式感满满 { Properties { _MainTex ("Texture", 2D) = "white" {}//图

zhangwwfz的博客 678

Unity3D眼镜Shader技术实现

笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,优快云社区专家,特邀编辑,畅销书作者,已出版书籍:《手把手教你架构3D游戏引擎》电子工业出版社和《Unity3D实战核心技术详解》电子工业出版社等。优快云视频网址:http://edu.youkuaiyun.com/lecturer/144 最近在利用Shader实现眼镜的反射,透明以及高光,法线等效果,Unity虽然为我们提供了很多的Shader,

海洋个人博客 4067

Unity3D之高级渲染-Shader Forge

笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,优快云社区专家,特邀编辑,畅销书作者,国家专利发明人;已出版书籍:《手把手教你架构3D游戏引擎》电子工业出版社和《Unity3D实战核心技术详解》电子工业出版社等。优快云视频网址:http://edu.youkuaiyun.com/lecturer/144 在前面的博客中给读者介绍了关于使用Shader Forge的应用,Shader Forge这个组件

海洋个人博客 5830

unity shader 入门之路(六)shader forge

枯燥无味的理论知识看得多了头疼,然后我就去找了关于shader的可视化编辑器。shader forge作为一个非专业初入门者,直接依靠文本编辑器来编写shader难度太大,依靠可视化编辑器则可以事半功倍。...

Testiness_Wind的博客 773

Unity3D中关于Shader的简单介绍

我们可以放心地讲,Unity对于很多人来说已经使游戏开发变得更加容易。但其中毫无疑问仍然有很长的路要走的就是Shader编程。提起Shader人们通常会觉得它很神秘,其实 Shader就是专门用于在GPU上运行的程序,它最终会绘制你3D模型中的所有三角形。如果你想给你的游戏添加特别的外观或效果,那么学习如何编写Shader程序是至关重要的。Unity也会使用Shader来做后期处理(postpro

SwordMaster8060的博客 1104

Shader基础学习 第一天

首先分享一些学习的书籍和网站吧 书籍 unity shader 入门精要(乐乐程序猿) CG语言教程官网 http://http.developer.nvidia.com/CgTutorial/cg_tutorial_frontmatter.html 一些网站 www.shadertoy.com http://blog.youkuaiyun.com/poem_qianmo?viewmode=contents ...

weixin_43333566的博客 300

单目视觉定位:深入解析PNP算法在机器人导航中的实战应用

本文深入解析了PNP算法在机器人单目视觉定位中的核心原理与实战应用。通过拆解坐标变换四步,详细阐述了如何从二维图像点反求相机三维位姿。文章结合OpenCV的solvePnP函数,提供了算法选择、参数调优及结果后处理的实用指南,并针对机器人导航中的特征匹配、尺度不确定性等挑战,给出了鲁棒性优化与实时性平衡的解决方案。

weixin_29083649的博客 419

猫都能学会的Unity3D Shader入门指南(一)

猫都能学会的Unity3D Shader入门指南(一) 原文出处:https://onevcat.com/2013/07/shader-tutorial-1/ 动机 自己使用Unity3D也有一段时间了,但是很多时候是流于表面,更多地是把这个引擎简单地用作脚本控制,而对更深入一些的层次几乎没有了解。虽然说Unity引擎设计的初衷就是创建简单的不需要开发者操心的谁都

life_demo的博客 5771

【Creo】关于Creo一换网络就报错许可证丢失问题解决方案

依照我的个人理解,Creo只要一更换网络,则其许可证里面的网卡参数和现在的网络就对不上了,所以就会出现报错,并且有可能是报错代码(-9),提示许可证激活有问题。

weixin_52002180的博客 6035

【Unity3D Shader编程】之十三 单色透明Shader & 标准镜面高光Shader

本次更新放出的Shader为透明系列的3个Shader和标准的镜面高光Shader的两个Shader。由易到难,由入门级到应用级,难度梯度合理。 依然是先放出游戏场景的exe和运行截图。 本期用的模型为妙蛙草。 【可运行的本文配套exe游戏场景请点击这里下载】 OK,直奔主题吧。 一、单色透明Shader 在上篇文章中单色透明的基础上进行改造,加入alpha混合,构成了这篇文章的第一个Shader——单色透明Shader。具体代码如下:

【浅墨的游戏编程Blog】毛星云(浅墨)的专栏 3万+

Vcenter虚拟机磁盘转换实战:如何用StarWind V2V将vmdk转为qcow2(附空间优化技巧)

本文详细介绍了如何使用StarWind V2V Converter将Vcenter中的vmdk虚拟机磁盘高效转换为qcow2格式,并提供了空间优化技巧。从准备工作、导出vmdk文件到转换过程中的性能调优,帮助管理员在迁移虚拟机时减少资源消耗,确保数据完整性和性能。

dell8的博客 202

车载 ECU 中的 Safety Linux 详解

车载 ECU 中的 Safety Linux 详解

天赐好车的博客 307

Unity3D Shader 入门学习

Unity3D Shader 入门学习 Unity3D 的所有渲染工作离不开着色器. 一些基本的概念 Shader和Material Shader 着色器其实是一小段程序,它负责将输入的 Mesh 网格. 以指定的方式和输入的贴图或者颜色等组合作用.然后输出.绘图单元可以依据这个输出来将图像绘制到屏幕上 输入的贴图或颜色等,加上对应的shader,以及对Shader的特定参数设置,将这些内容(...

【黑键】 398

深入理解JVM虚拟机第一篇:Java跨平台和字节码以及多语言混合编程

本位描述了Java的跨平台和JVM的跨平台的作用,Java语言的字节码的概念多语言混合编程应用到JVM虚拟机以及Java发展的重大事件。

七叔的博客 1万+

Unity3D Shader 入门知识

Unity3D Shader 入门知识详解

2301_76984003的博客 965

在 SAP S/4HANA Public Cloud 中做产品扩展:从 Key User 到 ABAP Cloud 与 BTP 的三轨实践指南

摘要:SAP S/4HANA Public Cloud 提供三种扩展方式(key user、developer extensibility 和 side-by-side),遵循 clean core 原则确保升级稳定。key user 扩展适合无代码轻量改良,developer extensibility 用于受控 ABAP 开发,side-by-side 则适用于云原生独立应用。文章通过销售订单优先级字段、退货审批微服务和采购校验等案例,说明不同扩展路径的适用场景与实现方法,帮助开发者在三系统景观中合理选

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 293

机器学习特征选择-t检验

在特征选择的过程中通过计算检验统计量值,比较特征之间的统计量的大小,并降序排列,选取统计值较高的特征,从而起到去除差别小的特征(此差别小的特征难以区分不同的额类别)的目的。 以t检验(Student's t test)为例: 假设检验 通过比较两类样本的随机变化,通过计算其p值决定是否拒绝零假设,也即是说:通过计算p值,若p值小于某一阈值则认为两个样本具有显著差异,两个样本是不同的,此时拒绝...

heda3的博客 6700
上一篇: 让数字变化炫酷起来,数字滚动Text组件[Unity]
下一篇: Unity中的法线贴图、漫反射及高光
慕飞
博客等级 码龄11年 43粉丝 15原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值