Hi, nice to meet you!

Unity Shader | 半兰伯特、高光反射、BlinnPhone

写 Shader,到底是在做什么?Shader 就像一个拥有魔法的黑箱,我们最终从它那里得到的,是像素的颜色。而得到的是什么样的像素颜色,则取决于我们丢进黑箱里的是什么东西,以及使用的魔法咒语是什么。丢进同样的东西,使用不同的魔法咒语,得到的像素颜色也是不一样的。输入顶点的坐标,光线方向,以及自定义的颜色,使用不同的计算方式,得到的像素颜色是不一样的。使用同样的计算方式,丢进一个纯色颜色值,和丢进一张纹理,得到的像素,也是不一样的。

如果把整个 Shader 比作一个函数,那么顶点位置,自定义的颜色值,纹理,灯光等这些就相当于函数的输入参数,而 Shader 中写的各种计算,用的各种算法,都是对输入的那些参数进行操作,而最终生成的,就是颜色值,也就是相当于函数的返回值。把 Shader 想的简单一点,就是输入需要的东西,进行计算,得到像素值。

这篇博客,还是关于光照模型的,接下来我们首先总结一下常用的光照模型。

Unity Shader | 半兰伯特、高光反射、BlinnPhone

Unity Shader | 光照模型和漫反射

在之前的文章中写的Shader,呈现出来的物体样子是一个平面2D的状态,即使物体是3D的,那是因为,我们还没有将灯光加入到Shader的运算中。现在,我们将介绍灯光相关的东西,最后呈现出和 Unity Diffuse Shader 一样的效果。

什么是光照模型

光照模型,简单理解就是一种运算,或者说一个公式,计算的结果,决定了一个点受到光照时,所表现出来的效果。例如,光照在木板上,和照在一面镜子上,我们所看到的效果是不一样的,照在镜子上,很大一部分光会被镜子反射,而木板,却不会反射那么多光。

Unity Shader | 光照模型和漫反射

Unity UGUI RGB通道分离抖动

今天我们要在 UGUI 上实现图片RGB通道分离抖动效果,先看最终效果图

Unity UGUI RGB通道分离抖动

Unity Shader | 使用Struct传递数据

上一篇博客 说了在 CGPROGRAM 中写代码、顶点处理函数、片元处理函数、以及在两个函数之间传递简单的数据、从 ShaderLab 属性到CG数据类型之间的联系等。这一篇博将稍详细一点说一下 Shader 的基本知识,以及在顶点和片元函数之间传递更多的数据。

Shader的基本理解

简单来说,Shader 决定了一个模型最终呈现在屏幕上的样子。一个模型由很多顶点构成,而每一个顶点,都会经过 Shader 中的顶点处理函数,这个过程,就是从应用将数据传递到顶点处理函数,顶点函数需要将顶点从模型空间转换到屏幕空间,或者说是裁剪空间,也可以简单理解为从 3 维空间转换到屏幕上的 2 维空间。在这个过程中,还可以做一些其他对顶点的操作。

顶点数据经过顶点处理函数处理后,接下来就返回,然后传给片元处理函数,到了这一步,面对的,就是像素,也就是每一个像素的颜色值。在这里,可以根据自己的需求,对每一个像素做处理,例如做高斯模糊,RGB通道分离,等等,各种各样的效果。

Unity Shader | 使用Struct传递数据

Unity Shader | 属性、顶点与片元函数

上一篇博客 介绍了Shader的基本结构,这里我们继续来说Shader的编写,也就是要在 CGPROGRAM 中写代码。首先我们把之前的Shader结构代码复制过来。

Shader "iMoeGirl/MyShader" {  // Shader 名字

// 这里定义一些属性,可以显示在UI面板上用于调节
Properties {
// 属性名("Inspector面板上显示出来的属性名", 属性类型) = 默认值
_Color("颜色类型", Color) = (1,1,1,1)
_Vector("向量类型", Vector) = (1, 2, 3, 4)
_Int("整型", Int) = 11111
_Float("浮点型", Float) = 12.11
_Range("范围类型", Range(100, 1000)) = 128
_Tex2D("贴图类型", 2D) = "white"{}
_Cube("立方体贴图类型", Cube) = "white"{}
_Tex3D("3D纹理", 3D) = "white"{}
}

// 子 Shader,可以写多个,显卡运行时,
// 从第一个SubShader开始,如果第一个里面的效果都支持,则使用第一个,
// 如果发现这个SubShader里面某些效果不支持,则自动运行下一个SubShader
SubShader {

// 至少有一个Pass,相当于一个方法
Pass {
// 在Pass块里写Shader代码

CGPROGRAM
// 使用 CG语言编写Shader
ENDCG
}
}

// 如果发现所有的SubShader都不支持,则使用Fallback,相当于后备方案
Fallback "VertexLit"
}

怎样使用 Properties 中定义的属性

Unity3D定义Shader属性所使用的语法,和CG所使用的说法是不一样的,所以我们要在一个Pass中使用Properties中定义的属性,需要在Pass中再以CG的语法再写一遍,其实就是变量名相同,而数据类型不同,在Shader在编译的时候,就会自动将两个变量关联起来。看下面的代码

Unity Shader | 属性、顶点与片元函数

Unity Shader | 基础

MeshFilter

存储一个Mesh(网格,模型的网格,模型的三角面顶点信息)

MeshRenderer

用于渲染一个物体的外观,数据来源于MeshFilter

Material

材质包含两部分,贴图和Shader

Unity Shader | 基础

使用 Unity 实现漂亮的数学曲面(下)

上一篇博客我们实现了一些简单的数学曲面,这一节我们将继续更复杂的数学曲面展示,所有资源完全承接上一篇内容。

2.5 创建一个涟漪效果

先来看一下最终要实现的效果图

我们一步一步来实现这个效果。首先,要创建一个基于到原点距离正弦波。而这个距离,我们使用毕达哥拉斯定理也就是勾股定理 $a^2 + b^2 = c^2$ 。对于这个效果来说,我们是基于XZ坐标来求Y坐标的,所以也就是 $\sqrt{x^2 + z^2}$ 。

使用 Unity 实现漂亮的数学曲面(下)

使用 Unity 实现漂亮的数学曲面(上)

这篇博客是上一篇 使用Unity3D展示Sin函数动画 的续篇,在上一篇的基础上,来实现更复杂的效果。在文章最后会有完整的 C# 代码和 Shader 代码,先来看一下最终的效果图

由于篇幅太长,所以将分为上下两部分,现在开始第一部分的内容。

使用 Unity 实现漂亮的数学曲面(上)

使用Unity3D展示Sin函数动画

今天我们要实现的东西,就是下面这个动图的效果。使用代码控制方块的坐标,来展示 Sin 函数。方块的颜色变化,是随着坐标变化而动态改变的,我们会写一个超简单的 Shader 来实现。

使用Unity3D展示Sin函数动画

制作一个会动的时钟

这是 Unity 基础系列教程的第一篇博客。我们将由浅入深,一步一步学习Unity及游戏开发相关的东西。整个系列教程所使用的Unity版本为 2018.4 及以上就可以,如果要使用特殊版本,则会在文中指出。

今天要做的是一个能够实时显示当前时间的时钟,就是下面这个东东。

p002001_Unity-001-1

制作一个会动的时钟