找回密码
 立即注册
查看: 6903|回复: 91

[基础] Unity3D游戏制作之如何渲染3D角色

  [复制链接]
发表于 2013-4-1 22:07 | 显示全部楼层 |阅读模式
资源信息 Tutorial Information
教程名称: Unity3D游戏制作之如何渲染3D角色(发帖教程)
适用引擎:   (适用引擎,为空默认为Unity)
教程语种: 中文
教程等级: 1
教程格式: 图文(请用IE9以上浏览器访问本版块)
教程作者: 转载自互联网 (如有问题请短消息联系作者或发表回复)
下载地址: (兑换积分)
点击查看原图
美丽分割线

本系列文章由 Amazonzx 编写,欢迎转载,转载请注明出处。

http://blog.csdn.net/amazonzx/article/details/7935341


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


一、       从Shader开始

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


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

[csharp] view plaincopy

  • Shader "Custom/MyShader" {  
  •     Properties {  
  •         _MainTex ("Base (RGB)", 2D) = "white" {}  
  •     }  
  •     SubShader {  
  •         Tags { "RenderType"="Opaque" }  
  •         LOD 200  
  •          
  •         CGPROGRAM  
  •         #pragma surface surf Lambert  
  •   
  •         sampler2D _MainTex;  
  •   
  •         struct Input {  
  •             float2 uv_MainTex;  
  •         };  
  •   
  •         void surf (Input IN, inout SurfaceOutput o) {  
  •             half4 c = tex2D (_MainTex, IN.uv_MainTex);  
  •             o.Albedo = c.rgb;  
  •             o.Alpha = c.a;  
  •         }  
  •         ENDCG  
  •     }   
  •     FallBack "Diffuse"  
  • }  


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



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


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

1、  BumpMap效果

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

1.1  在属性Properties中加入:

[csharp] view plaincopy

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


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

[csharp] view plaincopy

  • sampler2D _MainTex;  
  • sampler2D _BumpMap;  
  •   
  • struct Input {  
  •     float2 uv_MainTex;  
  •     float2 uv_BumpMap;   
  • };  


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

[csharp] view plaincopy

  • void surf (Input IN, inout SurfaceOutput o) {  
  • <span style="white-space:pre">  </span>half4 c = tex2D (_MainTex, IN.uv_MainTex);  
  •     o.Albedo = c.rgb;  
  •     o.Alpha = c.a;  
  •     o.Normal = UnpackNormal (tex2D (_BumpMap, IN.uv_BumpMap));  
  • }  


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


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

说明:

(1)首先是title的解释

[csharp] view plaincopy

  • Shader "Custom/MyShader1"   

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


(2)其次是Properties

[csharp] view plaincopy

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

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

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

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

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

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

l  “defaultvalue”是指该property的默认值

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


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

这里的“LOD”主要是指Shader的LOD程度,即对于超出该范围的物体将不再通过该Shader进行渲染,具体的Shader LOD说明可以参见:http://blog.csdn.net/amazonzx/article/details/7614399


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

[csharp] view plaincopy

  • sampler2D _BumpMap;  
  • float2 uv_BumpMap;  
  •               

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

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


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

[csharp] view plaincopy

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


其中,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中加入:

[csharp] view plaincopy

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


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

[csharp] view plaincopy

  • fixed4 _AmbientColor;  
  • fixed4 _SpecularColor;  
  • half _Glossiness;  


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

[csharp] view plaincopy

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

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


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

[csharp] view plaincopy

  • inline fixed4 LightingCustomBlinnPhong (SurfaceOutput s, fixed3 lightDir, fixed3 viewDir, fixed atten)   
  • {  
  •     fixed3 ambient = s.Albedo * _AmbientColor.rgb;  
  •   
  •     fixed NdotL = saturate(dot (s.Normal, lightDir));   
  •     fixed3 diffuse = s.Albedo * _LightColor0.rgb * NdotL;  
  •               
  •     fixed3 h = normalize (lightDir + viewDir);   
  •     float nh = saturate(dot (s.Normal, h));   
  •     float specPower = pow (nh, _Glossiness);  
  •     fixed3 specular = _LightColor0.rgb * specPower * _SpecularColor.rgb;  
  •   
  •     fixed4 c;  
  •     c.rgb = (ambient + diffuse + specular) * (atten * 2);  
  •     c.a = s.Alpha + (_LightColor0.a * _SpecularColor.a * specPower * atten);  
  •     return c;  
  • }  


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


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


其显示效果如下:



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

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

3.1  在属性Properties中加入:

[csharp] view plaincopy

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

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

[csharp] view plaincopy

  • sampler2D _MainTex;  
  • sampler2D _BumpMap;  
  • sampler2D _Ramp;  
  •          
  • fixed4 _AmbientColor;  
  • fixed4 _SpecularColor;  
  • half _Glossiness;  
  •   
  • fixed4 _RimColor;  
  • half _RimPower;  
  •   
  • struct Input {  
  •     float2 uv_MainTex;  
  •     float2 uv_BumpMap;  
  •     half3 viewDir;   
  • };  

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

[csharp] view plaincopy

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

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

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

[csharp] view plaincopy

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

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


其显示效果如下:


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


三、       小结

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




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×

评分

参与人数 2鲜花 +2 +1 收起 理由
橘子xs + 1 赞一个!
gostgy + 1 + 1 很给力!

查看全部评分

发表于 2013-4-6 17:59 | 显示全部楼层

不错 不错 不错{:soso__3922851084632044791_6:}
发表于 2013-4-24 18:08 | 显示全部楼层

不错 不错 不错{:soso__3922851084632044791_6:}
发表于 2013-5-6 05:44 | 显示全部楼层

膜拜中。。。。{:soso__7524161091986203637_5:}
发表于 2013-5-6 11:45 | 显示全部楼层
{:5_435:}学习了
发表于 2013-5-6 13:31 | 显示全部楼层
支持- -{:5_404:}
发表于 2013-5-9 20:53 | 显示全部楼层

不错 不错 不错{:soso__3922851084632044791_6:}
发表于 2013-6-5 08:54 | 显示全部楼层

膜拜中。。。。{:soso__7524161091986203637_5:}
发表于 2013-6-7 15:46 | 显示全部楼层
不错,受教了
发表于 2013-7-13 04:16 | 显示全部楼层

不错 不错 不错{:soso__3922851084632044791_6:}
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-24 12:19 , Processed in 0.113300 second(s), 32 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表