如何利用Shader来渲染游戏中的3D角色

杨航最近在学Unity3D

本文主要介绍一下如何利用Shader来渲染游戏中的3D角色,以及如何利用Unity提供的Surface Shader来书写自定义Shader。

一、从Shader开始

1、通过Assets->Create->Shader来创建一个默认的Shader,并取名“MyShader”。

Unity3D教程:3D角色的渲染

Unity3D教程:3D角色的渲染

2、将MyShader打开即可看见Unity默认的Shader代码

   
01
Shader "Custom/MyShader" {
02
Properties {
03
_MainTex ("Base (RGB)", 2D) = "white" {}
04
}
05
SubShader {
06
Tags { "RenderType"="Opaque" }
07
LOD 200
08
CGPROGRAM
09
#pragma surface surf Lambert
10
sampler2D _MainTex;
11
struct Input {
12
float2 uv_MainTex;
13
};
14
void surf (Input IN, inout SurfaceOutput o) {
15
half4 c = tex2D (_MainTex, IN.uv_MainTex);
16
o.Albedo = c.rgb;
17
o.Alpha = c.a;
18
}
19
ENDCG
20
}
21
FallBack "Diffuse"
22
}

3、将该Shader赋给一个角色,就可以看到该Shader所能表达出的Diffuse渲染效果。

Unity3D教程:3D角色的渲染

Unity3D教程:3D角色的渲染

4、接来我们将以此默认Shader作为蓝本,编写出自定义的Shader。另外,该Shader所用到的参数,我们将在下一章节进行说明。

二、实现多种自定义渲染效果

1、 BumpMap效果

如果想实现Bump Map效果,可对上述的Shader做如下修改:

1.1 在属性Properties中加入:

   
1
Properties {
2
_MainTex ("Base (RGB)", 2D) = "white" {}
3
_BumpMap("Bumpmap", 2D) = "bump" {}
4
}

1.2 在SubShader的变量中也进行相应修改:

   
1
sampler2D _MainTex;
2
sampler2D _BumpMap;
3
struct Input {
4
float2 uv_MainTex;
5
float2 uv_BumpMap;
6
};

1.3 最后修改surf函数,加入对Normal分量的计算:

   
1
void surf (Input IN, inout SurfaceOutput o) {
2
"white-space: pre;"> half4 c = tex2D (_MainTex, IN.uv_MainTex);
3
o.Albedo = c.rgb;
4
o.Alpha = c.a;
5
o.Normal = UnpackNormal (tex2D (_BumpMap, IN.uv_BumpMap));
6
}

这样,角色的材质部分即可变为如下形式(暂定BumpMap的Shader名为“MyShader1”):

Unity3D教程:3D角色的渲染

Unity3D教程:3D角色的渲染

然后,根据Base图来创建其Normal Map图,并拖入到BumpMap中即可。BumpMap的效果显示如下:

Unity3D教程:3D角色的渲染

Unity3D教程:3D角色的渲染

说明:

(1)首先是title的解释

   
1
Shader "Custom/MyShader1"

这种表示表明了该Shader在编辑器中的显示位置,例如我们可在如下地方找到该Shader。

Unity3D教程:3D角色的渲染

Unity3D教程:3D角色的渲染

(2)其次是Properties

   
1
Properties {
2
_MainTex ("Base (RGB)", 2D) = "white" {}
3
_BumpMap("Bumpmap", 2D) = "bump" {}
4
}

Properties可通过如下语义进行声明:

name ("displayname", property type) = default value

“name” 是与Shader脚本中对应的名字

“display name”是在材质视图中所显示的名字

“propertytype”是指该property的类型,一般可有如下几种类型:Range,Color,2D,Rect,Cube,Float和Vector

“defaultvalue”是指该property的默认值

这里需要注意的是,如果你在Properties中加入了新的属性,那么你需要在CGPROGRAM中的SubShader中加入同样名字的参数。

(3)接下来是“LOD”语义词的解释。

这里的“LOD”主要是指Shader的LOD程度,即对于超出该范围的物体将不再通过该Shader进行渲染,具体的Shader LOD说明可以参见:Unity3D翻译——Shader Level of Detail

(4)我们在SubShader中还加入了

   
1
sampler2D _BumpMap;
2
float2 uv_BumpMap;

其中,_BumpMap是为了关联Properties中的_BumpMap属性。

而uv_BumpMap,是为了获取BumpMap图中的uv坐标。

(5)最后,我们在surf函数中获取每个顶点的纹理信息以及法线信息,这些信息将被应用于接下来的Vertex Fragment和Pixel Fragment。

   
1
void surf (Input IN, inout SurfaceOutput o) {
2
half4 c = tex2D (_MainTex, IN.uv_MainTex);
3
o.Albedo = c.rgb;
4
o.Alpha = c.a;
5
o.Normal = UnpackNormal (tex2D (_BumpMap, IN.uv_BumpMap));
6
}

其中,tex2D函数可以读取纹理_MainTex中的IN.uv_MainTex坐标位置的像素颜色值。

Albedo和Alpha分别获取该像素的RGB值和Alpha值,其中“Albedo”是一个漫反射参数,它表示一个表面的漫反射能力,即一个表面上出射光强与入射光强的比值。具体介绍可见:http://en.wikipedia.org/wiki/Albedo。

2、  Blinn-Phong效果

如果想实现Blinn-Phong效果,可对上述的Shader做如下修改:

2.1  在属性Properties中加入:

   
1
_AmbientColor ("Ambient Color", Color) = (0.1, 0.1, 0.1, 1.0)
2
_SpecularColor ("Specular Color", Color) = (0.12, 0.31, 0.47, 1.0)
3
_Glossiness ("Gloss", Range(1.0,512.0)) = 80.0

2.2  在SubShader的变量中也加入相应修改:

   
1
fixed4 _AmbientColor;
2
fixed4 _SpecularColor;
3
half _Glossiness;

2.3  最后修改surf函数,进行如下修改:

   
1
fixed4 c = tex2D (_MainTex, IN.uv_MainTex);

这里将原有的half4替换为fixed4,这样做是为了提高渲染的性能,因为fixed的精度较之half要低,更高的精度意味着更大的计算量,而这里fixed的精度已经足够,所以使用fixed替代half4,从而来降低计算消耗,增加渲染性能。

2.4  将“#pragma surface surf Lamber”改成“#pragma surfacesurf CustomBlinnPhong”,同时加入与其对应的LightingCustomBlinnPhong函数来计算顶点光照。

   
01
inline fixed4 LightingCustomBlinnPhong (SurfaceOutput s, fixed3 lightDir, fixed3 viewDir, fixed atten) 
02
{
03
fixed3 ambient = s.Albedo * _AmbientColor.rgb;
04
 
05
fixed NdotL = saturate(dot (s.Normal, lightDir)); 
06
fixed3 diffuse = s.Albedo * _LightColor0.rgb * NdotL;
07
 
08
fixed3 h = normalize (lightDir + viewDir); 
09
float nh = saturate(dot (s.Normal, h)); 
10
float specPower = pow (nh, _Glossiness);
11
fixed3 specular = _LightColor0.rgb * specPower * _SpecularColor.rgb;
12
 
13
fixed4 c;
14
c.rgb = (ambient + diffuse + specular) * (atten * 2);
15
c.a = s.Alpha + (_LightColor0.a * _SpecularColor.a * specPower * atten);
16
return c;
17
}

该函数的名称为什么不是“CustomBlinnPhong”呢?这是因为该函数虽然是由“#pragma surface surf CustomBlinnPhong”来调用,但是为了让该函数可以正常工作,我们需要在其名称前加入“Lighting”关键字,这样Unity才能识别出这是一个自定义的光照函数。

通过以上设置,角色的材质部分即可变为如下形式(暂定该Shader名为“MyShader2”):

Unity3D教程:3D角色的渲染

Unity3D教程:3D角色的渲染

其显示效果如下:

Unity3D教程:3D角色的渲染

Unity3D教程:3D角色的渲染

3、  边缘光照(Rim Light)和卡通渲染(Toon Shading)

可以通过对上述Shader做以下改进,来达到这种效果:

3.1  在属性Properties中加入:

   
1
_RimColor ("Rim Color", Color) = (0.12, 0.31, 0.47, 1.0) 
2
_RimPower ("Rim Power", Range(0.5, 8.0)) = 3.0 
3
_Ramp ("Shading Ramp", 2D) = "gray" {}

3.2  在SubShader的变量中也加入相应修改:

   
01
sampler2D _MainTex;
02
sampler2D _BumpMap;
03
sampler2D _Ramp;
04
 
05
fixed4 _AmbientColor;
06
fixed4 _SpecularColor;
07
half _Glossiness;
08
 
09
fixed4 _RimColor;
10
half _RimPower;
11
 
12
struct Input {
13
float2 uv_MainTex;
14
float2 uv_BumpMap;
15
half3 viewDir; 
16
};

3.3  修改surf函数,进行如下修改:

   
1
void surf (Input IN, inout SurfaceOutput o) {
2
fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
3
o.Albedo = c.rgb;
4
o.Alpha = c.a;
5
o.Normal = UnpackNormal (tex2D (_BumpMap, IN.uv_BumpMap));
6
fixed rim = 1.0 - saturate (dot (normalize(IN.viewDir), o.Normal));
7
o.Emission = (_RimColor.rgb * pow (rim, _RimPower));
8
}

这里主要是用来计算边缘光照的,首先通过视线与法线的夹角来找到模型的边缘,然后再根据距离的远近来控制发射光的强度。

3.4  将“#pragma surface surf CustomBlinnPhong”改成“#pragma surfacesurf CustomBlinnPhong exclude_path:prepass”,同时在LightingCustomBlinnPhong函数来修改漫反射光的计算,来达到卡通渲染的效果。

   
1
fixed NdotL = saturate(dot (s.Normal, lightDir)); 
2
fixed diff = NdotL * 0.5 + 0.5;
3
fixed3 ramp = tex2D (_Ramp, float2(diff, diff)).rgb;
4
fixed diffuse = s.Albedo * LightColor0.rgb * ramp;

通过以上设置,角色的材质部分即可变为如下形式(暂定该Shader名为“MyShader3”):

Unity3D教程:3D角色的渲染

Unity3D教程:3D角色的渲染

其显示效果如下:

Unity3D教程:3D角色的渲染

Unity3D教程:3D角色的渲染

可以看出边缘光照的效果,同时还可以看出明显的明暗变化的卡通渲染效果。

三、       小结

综上所述,本文已经给出了人物的几种基本渲染方法及其Shader实现,在这里我并没有去分析每种渲染效果的原理,而仅是从实际出发,直接给出对应的简单实现方法。如果想要对光照模型进行深入理解,可以Google搜索其原理进行了解。最后,给出各种渲染方法的对比图,显示如下:

Unity3D教程:3D角色的渲染

Unity3D教程:3D角色的渲染

本系列文章由 Unity公司开发支持工程师Amazonzx 编写,



本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/388225.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Css单位

尺寸 颜色 转载于:https://www.cnblogs.com/jsunny/p/9866679.html

ai驱动数据安全治理_JupyterLab中的AI驱动的代码完成

ai驱动数据安全治理As a data scientist, you almost surely use a form of Jupyter Notebooks. Hopefully, you have moved over to the goodness of JupyterLab with its integrated sidebar, tabs, and more. When it first launched in 2018, JupyterLab was great but fel…

【Android】Retrofit 2.0 的使用

一、概述 Retrofit是Square公司开发的一个类型安全的Java和Android 的REST客户端库。来自官网的介绍: A type-safe HTTP client for Android and JavaRest API是一种软件设计风格,服务器作为资源存放地。客户端去请求GET,PUT, POST,DELETE资源。并且是无…

Mysql常用命令(二)

对数据库的操作 增 create database db1 charset utf8; 查 # 查看当前创建的数据库 show create database db1; # 查看所有的数据库 show databases; 改 alter database db1 charset gbk; 删 drop database db1; 对表的操作 use db1; #切换文件夹select database(); #查看当前所…

python中定义数据结构_Python中的数据结构—简介

python中定义数据结构You have multiples algorithms, the steps of which require fetching the smallest value in a collection at any given point of time. Values are assigned to variables but are constantly modified, making it impossible for you to remember all…

Unity3D 场景与C# Control进行结合

杨航最近在自学Unity3D,打算使用这个时髦、流行、强大的游戏引擎开发一个三维业务展示系统,不过发现游戏的UI和业务系统的UI还是有一定的差别,很多的用户还是比较习惯WinForm或者WPF中的UI形式,于是在网上搜了一下WinForm和Unity3…

数据质量提升_合作提高数据质量

数据质量提升Author Vlad Rișcuția is joined for this article by co-authors Wayne Yim and Ayyappan Balasubramanian.作者 Vlad Rișcuția 和合著者 Wayne Yim 和 Ayyappan Balasubramanian 共同撰写了这篇文章 。 为什么要数据质量? (Why data quality?) …

unity3d 人员控制代码

普通浏览复制代码private var walkSpeed : float 1.0;private var gravity 100.0;private var moveDirection : Vector3 Vector3.zero;private var charController : CharacterController;function Start(){charController GetComponent(CharacterController);animation.w…

删除wallet里面登机牌_登机牌丢失问题

删除wallet里面登机牌On a sold-out flight, 100 people line up to board the plane. The first passenger in the line has lost his boarding pass but was allowed in regardless. He takes a random seat. Each subsequent passenger takes their assigned seat if availa…

字符串操作截取后面的字符串_对字符串的5个必知的熊猫操作

字符串操作截取后面的字符串We have to represent every bit of data in numerical values to be processed and analyzed by machine learning and deep learning models. However, strings do not usually come in a nice and clean format and require preprocessing to con…

最新 Unity3D鼠标滑轮控制物体放大缩小 [

var s 1.0;function Update () {var cube GameObject.Find("Cube");if(Input.GetAxis("Mouse ScrollWheel")){s Input.GetAxis("Mouse ScrollWheel");cube.transform.localScaleVector3(1*s,1*s,1*s);}}

sublime-text3 安装 emmet 插件

下载sublime,http://www.sublimetext.com/ 安装package control :https://packagecontrol.io/ins... 这个地址需要翻墙,访问不了的可以看下图 import urllib.request,os,hashlib; h 6f4c264a24d933ce70df5dedcf1dcaee ebe013ee18cced0ef93d…

unity3d]鼠标点击地面人物自动走动(也包含按键wasdspace控制)

目录(?)[-] 一效果图二大概步骤 创建一个plane设置层为Terrain因为后面要判断是否点击的是这个层准备好人物模型并且将三个脚本拖放到人物上并且将动画文件也拖放好记得看前面提醒哦 ThirdPersonCamera相当于smoothflowThirdPersonController修改版mouseMoveContr鼠标点击人物…

Web 开发基础

一、 Web 开发简介 最早的软件都是运行在大型机上的,软件使用者登陆到大型机上去运行软件。后来随着 PC 机的兴起,软件开始主要运行在桌面上,而数据库这样的软件运行在服务器端,这种 Client/Server 模式简称 CS 架构。随着互联网的…

power bi函数_在Power BI中的行上使用聚合函数

power bi函数Aggregate functions are one of the main building blocks in Power BI. Being used explicitly in measures, or implicitly defined by Power BI, there is no single Power BI report which doesn’t use some sort of aggregate functions.聚合功能是Power BI…

广义估计方程估计方法_广义估计方程简介

广义估计方程估计方法A key assumption underpinning generalized linear models (which linear regression is a type of) is the independence of observations. In longitudinal data this will simply not hold. Observations within an individual (between time points) …

Unity3d鼠标点击屏幕来控制人物的走动

今天呢,我们来一起实现一个在RPG中游戏中十分常见的功能,通过鼠标点击屏幕来控制人物的走动。首先来说一下原理,当我们点击屏幕时,我们按照一定的方法,将屏幕上的二维坐标转化为三维坐标,然后我们从摄像机位…

Java中的ReentrantLock和synchronized两种锁定机制的对比

2019独角兽企业重金招聘Python工程师标准>>> 多线程和并发性并不是什么新内容,但是 Java 语言设计中的创新之一就是,它是第一个直接把跨平台线程模型和正规的内存模型集成到语言中的主流语言。核心类库包含一个 Thread 类,可以用它…

大数定理 中心极限定理_中心极限定理:直观的遍历

大数定理 中心极限定理One of the most beautiful concepts in statistics and probability is Central Limit Theorem,people often face difficulties in getting a clear understanding of this and the related concepts, I myself struggled understanding this during my…

探索性数据分析(EDA)-不要问如何,不要问什么

数据科学 , 机器学习 (Data Science, Machine Learning) This is part 1 in a series of articles guiding the reader through an entire data science project.这是一系列文章的第1部分 ,指导读者完成整个数据科学项目。 I am a new writer on Medium…