大家好,我是秦培,欢迎关注我的博客,我的博客地址blog.csdn.net/qinyuanpei

在上一篇文章中,我们通过自己定义着色器实现了一个简单的在3D游戏中选取、显示物体轮廓的实例。

在文章最后,博主给大家留下了一个问题,就是我们的这样的方法存在一定的问题,无法运用到复杂的模型上。

原因是什么呢?这要从这样的方法的原理上来说。事实上这样的方法相似于摄像机的视角方向上对物体进行了一个投影。这样的话,假设模型被其他物体遮挡的话,就会出现渲染不全然的问题。如图所看到的,有一位朋友在评论中提出了这个问题。那么,怎么解决问题呢?对于遮挡的问题,我们一般採取的方法是拉近摄像机,因此,我们这里依旧採取这样的方法,即假设被渲染的物体前面有遮挡物体,则将摄像机拉近,这样就能够解决问题了。

那么攻克了上一篇文章中的问题后,我们就来開始学习今天的内容——《Unity3D游戏开发复杂模型的选取与轮廓高亮显示》。首先,我们今天的内容是基于边缘光(RimLight)的方法来实现的,在Unity3D的官方演示样例中。我们能够找到这个算法。其核心算法是:

half rim = 1.0 - saturate(dot (normalize(IN.viewDir), IN.worldNormal));
o.Emission = _RimColor.rgb * pow (rim, _RimPower);

当中。IN.viewDir是当前视角向量,IN.worldNormal是物体的法线。dot是计算视角和法线的点积,等于视角和法线夹角的cos值,例如以下图:

因为Cos的值域是1到0。所以1-cos就成了0到1,在夹角90度时达到最大值。正好用来模拟側光的强度(与视角成90度的部分光线最强,就是边缘光了),把这个值的变化率用一个pow函数(rim的_rimPower次方)进行放大,就能强化边缘发亮的效果。

可是当物体表面比較平直时(比如立方体),因为各个面上的法向量都是一个方向上的,因此无法体现出变化和轮廓。此外,这样的方法在描绘凹的几何体时,凹的部分(包含法线贴图造成的凹凸)的边缘也都会被画出来,并非真正意义上的边缘轮廓。就是一种側光效果。

这一部分。博主并非非常懂。因为博主并没有系统的学习过计算机图形学的东西,假设大家想了解很多其他的内容。能够參考这里:

tid=3592">http://game.ceeger.com/forum/read.php?tid=3592

好了,以下我们開始详细地来讲通过这样的方法来实现物体轮廓高光显示。首先编写Shader:

Shader "Custom/Outline" {
Properties {
_Color ("Main Color", Color) = (1,1,1,1)
_SpecColor ("Specular Color", Color) = (0.5, 0.5, 0.5, 1)
_Shininess ("Shininess", Range (0.03, 1)) = 1
_MainTex ("Base (RGB) Gloss (A)", 2D) = "black" {}
_BumpMap ("Normalmap", 2D) = "bump" {}
//边缘光颜色
_RimColor ("Rim Color", Color) = (0,0,0,0.0)
//放大倍数
_RimPower ("Rim Power", Range(0.5,8.0)) = 2.0
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 400 CGPROGRAM
#pragma surface surf BlinnPhong
#pragma target 3.0 sampler2D _MainTex;
sampler2D _BumpMap;
fixed4 _Color;
half _Shininess;
float4 _RimColor;
float _RimPower; struct Input {
float2 uv_MainTex;
float2 uv_BumpMap;
float3 viewDir;
}; void surf (Input IN, inout SurfaceOutput o) { fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
o.Albedo = tex.rgb * _Color.rgb;
o.Gloss = tex.a;
o.Alpha = tex.a * _Color.a;
o.Specular = _Shininess;
o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
//核心算法
half rim = 1 - saturate(dot (normalize(IN.viewDir), o.Normal));
o.Emission = _RimColor.rgb * pow (rim, _RimPower);
}
ENDCG } FallBack "Specular"
}

在这个着色器脚本中。最重要的一个属性是_RimColor,这个值将决定我们终于渲染的效果。

在上一篇文章中,我们是通过一个使用了自己定义着色器的材质来实现轮廓显示的。今天我们换一种方法,怎么做呢?我们这里通过Shader来实现,在Material中有一个Shader属性。一旦改变了该属性的值,那么全部材质都将依照新的渲染方式进行渲染。我们在上一篇文章中的脚本的基础上。扩展得到以下的脚本:

using UnityEngine;
using System.Collections; public class ShowBoundry : MonoBehaviour { //使用显示轮廓的简单材质
public Material mSimpleMat;
//默认材质
public Material mDefaultMat; //我们今天使用Shader来直接改变模型的渲染效果。这样能够避免使用一个材质
public Shader RimLightShader;
public Color RimColor = new Color(0.2F,0.8F,10.6F,1);
//定义私有变量以存储模型的原始信息
private SkinnedMeshRenderer mSkin;
private Color mColor;
private Shader mShader; void Start ()
{
//获取模型的SkinnedMeshRenderer
mSkin=GameObject.Find("Person").
GetComponentInChildren<SkinnedMeshRenderer>();
//获取默认颜色
mColor=mSkin.material.color;
//获取默认Shader
mShader=mSkin.material.shader; } void Update ()
{
//获取鼠标位置
Vector3 mPos=Input.mousePosition;
//向物体发射射线
Ray mRay=Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit mHit;
//射线检验
if(Physics.Raycast(mRay,out mHit))
{
//Cube
if(mHit.collider.gameObject.tag=="Cube")
{
//将当前选中的对象材质换成带轮廓线的材质
mHit.collider.gameObject.renderer.material=mSimpleMat;
//将未选中的对象材质换成默认材质
GameObject.Find("Sphere").renderer.material=mDefaultMat;
//将模型恢复到初始状态
mSkin.material.shader=mShader;
mSkin.material.SetColor("_RimColor",mColor);
//设置提示信息
GameObject.Find("GUIText").guiText.text="当前选择的对象是:Cube";
}
//Sphere
if(mHit.collider.gameObject.tag=="Sphere")
{
//将当前选中的对象材质换成带轮廓线的材质
mHit.collider.gameObject.renderer.material=mSimpleMat;
//将未选中的对象材质换成默认材质
GameObject.Find("Cube").renderer.material=mDefaultMat;
//将模型恢复到初始状态
mSkin.material.shader=mShader;
mSkin.material.SetColor("_RimColor",mColor);
//设置提示信息
GameObject.Find("GUIText").guiText.text="当前选择的对象是:Sphere";
}
//Person
if(mHit.collider.gameObject.tag=="Person")
{
//更换Shader
mSkin.material.shader=RimLightShader;
mSkin.material.SetColor("_RimColor",RimColor);
//将未选中的对象材质换成默认材质
GameObject.Find("Cube").renderer.material=mDefaultMat;
GameObject.Find("Sphere").renderer.material=mDefaultMat;
//设置提示信息
GameObject.Find("GUIText").guiText.text="当前选择的对象是:Person";
}
} }
}

在今天的脚本中,我们添加了一个RimLightShader和RimColor,它们的作用是指定着色器和边缘光的颜色,我们能够通过外部来引用我们刚才定义好的自己定义Shader,同一时候,为了保存模型的原始状态,我们定义了两个私有变量mShader和mColor,以便我们能够在适当的时候将模型的状态还原到原始状态。好了,我们来执行下今天的程序,效果例如以下:

能够注意到。当角色被选中时,角色以高亮显示的形式被渲染出来,博主这里使用的是金黄色的边缘光,所以得到了这样的结果。感觉效果还不错啊。博主在做今天的内容的时候,常常出现着色器无效的情况,后来发现是着色器定义的名称和文件名不符的缘故,所以大家在编写着色器的时候一定要注意啊。

好了。今天的内容就是这样了。希望大家喜欢啊。呵呵。

每日箴言:以前以为生命中最糟糕的事,就是孤独终老。事实上不是。

最糟糕的是与那些让你感到孤独的人一起终老。

喜欢我的博客请记住我的名字:秦元培,我的博客地址是blog.csdn.net/qinyuanpei

转载请注明出处。本文作者:秦元培。本文出处:http://blog.csdn.net/qinyuanpei/article/details/26862743

.

版权声明:本文博客原创文章,博客,未经同意,不得转载。转载请注明出处和作者,谢谢!

[Unity3D]Unity3D游戏开发3D选择场景中的对象,并显示轮廓效果强化版的更多相关文章

  1. 关于《Unity3D/2D游戏开发从0到1》书籍再版说明

    关于<Unity3D/2D游戏开发从0到1>第一版本在2015年7月1日全国发行,累计得到不少国内高校教师.培训机构的好评.但是由于Unity官方对于技术不断的升级与版本的快速迭代,基于U ...

  2. 《Unity3D/2D游戏开发从0到1(第二版本)》 书稿完结总结

    前几天,个人著作<Unity3D/2D游戏开发从0到1(第二版)>经过七八个月的技术准备以及近3个月的日夜编写,在十一长假后终于完稿.今天抽出一点时间来,给广大热心小伙伴们汇报一下书籍概况 ...

  3. Unity3D手机游戏开发

    <Unity3D手机游戏开发> 基本信息 作者: 金玺曾 出版社:清华大学出版社 ISBN:9787302325550 上架时间:2013-8-7 出版日期:2013 年8月 开本:16开 ...

  4. 《Unity3D/2D游戏开发从0到1》正式出版发行

    <Unity3D/2D游戏开发从0到1>正式出版发行 去年个人编写的Unity书籍正式在2015年7月正式发行,现在补充介绍一下个人著作.书籍信息:      书籍的名称: <Uni ...

  5. Unity3D 入门 游戏开发 Unity3D portal game development

    Unity3D 入门 游戏开发 Unity3D portal game development 作者:韩梦飞沙 Author:han_meng_fei_sha 邮箱:313134555@qq.com ...

  6. 3D UI场景中,把XY平面的尺寸映射为屏幕像素的数学模型推导

    概述及目录(版权所有,请勿转载,欢迎读者提出错误) 之前用kanzi的3D UI引擎和cocos-2d的时候都有遇到过这个问题,就如何把3D场景中的XY平面的尺寸映射为与屏幕像素一一对应的,即XY平面 ...

  7. 【转载】【游戏开发】在Lua中实现面向对象特性——模拟类、继承、多态

    [游戏开发]在Lua中实现面向对象特性——模拟类.继承.多态   阅读目录 一.简介 二.前提知识 三.Lua中实现类.继承.多态 四.总结 回到顶部 一.简介 Lua是一门非常强大.非常灵活的脚本语 ...

  8. Unity 游戏开发技巧集锦之使用忍者飞镖创建粒子效果

    Unity 游戏开发技巧集锦之使用忍者飞镖创建粒子效果 使用忍者飞镖创建粒子效果 游戏中,诸如烟.火.水滴.落叶等粒子效果,都可以使用粒子系统(particle system)来实现.例如,<明 ...

  9. [Unity3D]Unity3D游戏开发之在3D场景中选择物体并显示轮廓效果

    大家好,我是秦元培,欢迎大家关注我的博客,我的博客地址是blog.csdn.net/qinyuanpei. 在<仙剑奇侠传>.<古剑奇谭>等游戏中,常常须要玩家在一个3D场景中 ...

随机推荐

  1. css样式hover图片闪烁问题

    主要是ie8及ie8以下版本浏览器会出现此问题, 问题核心是因为hover选择器没有缓存即将要替换的图片, 所以导致替换期间有一个极其短暂的空白期. 解决方案: 采用 background-posit ...

  2. pygame系列_小球完全弹性碰撞游戏

    之前做了一个基于python的tkinter的小球完全碰撞游戏: 今天利用业余时间,写了一个功能要强大一些的小球完全碰撞游戏: 游戏名称: 小球完全弹性碰撞游戏规则: 1.游戏初始化的时候,有5个不同 ...

  3. 解决set /p yn= 接受键盘输入导致ECHO 处于关闭状态的问题

    今天写了一个自动更新程序的批处理脚本,但是有个变量一直赋值有问题.弄了一个下午终于找到原因及解决方法: ----转载要说明来自:博客园--邦邦酱好 哦 有问题的代码如下: @echo off echo ...

  4. 训练赛 Grouping(强连通分量缩点 + DAG求最长路)

    http://acm.sdut.edu.cn:8080/vjudge/contest/view.action?cid=158#problem/F 大致题意:给出n个人和m种关系(ti,si),表示ti ...

  5. MySQL先进的技术-存储引擎

    MySQL功能被分成两部分,主要有成品的外部client连接和可行性研究SQL函数语句,内侧部分被称为存储引擎,它负责接收外部操作指令数据,实际数据是完整的,文件输入和输出操作的工作 版权声明:本文博 ...

  6. 23设计模式(3):Abstract Factory模式

    定义:要创建一组相关或依赖对象提供一个接口,而你并不需要指定其具体类别. 类型:创建一个类模型 类图: 抽象工厂模式与工厂方法模式的差别 抽象工厂模式是工厂方法模式的升级版本号,他用来创建一组相关或者 ...

  7. oracle 包,函数,过程,块的创建和执行及在java中执行(转)

    SQL> create or replace procedure sp_guocheng1 is--如果有这个名字就替换  2  begin--执行部分  3  insert into guoc ...

  8. JAVA程序生成XML标准化的文件格式,缩进,美化。

    //他开始Document映射到文件 TransformerFactory transFactory = TransformerFactory.newInstance(); Transformer t ...

  9. Eclipse+Maven命令创建webapp项目<三>

    1.使用maven命令:mvn archetype:create -DgroupId=xxxxx -DartifactId=web-sample -DarchetypeArtifactId=maven ...

  10. UVA 674 (入门DP, 14.07.09)

     Coin Change  Suppose there are 5 types of coins: 50-cent, 25-cent, 10-cent, 5-cent, and 1-cent. We ...