咳咳,有段时间没有更新了,最近有点懒!把不少精力都放在C++身上了。闲言少叙,今天要讲的可和之前的几篇有所不同了,这次是一个次综合应用.这篇内容中与之前不同主要体现在下面几点上.

  1.之前我们写的都是只用一个Shader来实现某些效果,而这次我们要使用多个Shader结合起来发挥作用。

  2.之前我们只是写的都是纯Shader代码,没有涉及到客户端的C#脚本(你爱用JS也可).而这次也要使用到。

  3.这篇教程涉及到的代码量也是之前是之前的几倍了.

  4.总的来说之前的都是比较简单的,而这篇就有了些难度了。

  不过不要怕,我们先讲解实现的原理,因为这个教程内容比较多,所以只能抽出一篇来单独讲原理了,建议看这篇教程的同学,最好能有基本的UnityShader基础,不妨去看看我的前几篇教程,在后面讲解代码中我不会事无巨细的都讲到,直跳比较重点的地方进行说明。

  好了进入正题,什么是遮挡描边呢?直接上图吧。

  如上图, 在很多游戏中,特别是3D游戏中,当我们的角色被一些墙体或者其它物体挡着的时候,为了让玩家清楚的看到角色当前身处的位置,就需要把角色被遮挡部分的外轮廓描出来(上图中的绿色边框)。这就是我们要实现的"遮挡描边"。大家可以联想一下自己玩过的游戏看看有没有这种情况。


重要概念


  在讲解具体原理之前,我们要先了解几个比较重要的概念:

  1.后期处理:有点类似于影音方面后期处理的意思,在这里指的就是,当摄像机把当前帧渲染完毕之后,我们不是直接把图像映射到屏幕上,而是利用我们的代码来对原图像进行处理,把处理后的显示在屏幕上。游戏中非常多的效果都通过后期处理实现的,比如Bloom效果,运动模糊效果等等。我们这篇说的"遮挡描边"也算作是后期处理。

  2.深度缓冲:对于一款3D游戏,要将三维世界里摄像机看到的部分展示到二维的屏幕上,除了要展示物体本身的颜色,还要处理物体的前后关系。而在我们的显存里有两个缓冲区(和具体显卡架构有关,这里只是举个例子)来分别用来保存游戏的画面和物体的前后关系。我们把它们分别称作颜色缓冲区和深度缓冲区。颜色缓冲区你可以理解为他是一个二维数组,里面的一个元素对应着屏幕的一个像素点的颜色(还会附带一些其他信息)。深度缓冲区也可以理解为一个二维数组,里面存放着屏幕像素上每一个点所对应场景中物体上的点距离相机的距离。在渲染流程中深度缓冲非常重要的,如果没有它,也就没有了物体间的前后关系,我们在屏幕上看到的可能是杂乱的图像了。

  3.深度图:深度图适合深度缓冲相关联的一个概念,深度缓冲是由操作系统通过显卡API来控制的,而我们使用引擎的时候也只能通过引擎提供的有限的API来读写利用深度缓冲来实现一些效果。那当我们需要利用深度缓冲来做一些特殊效果的时候就要抓狂了,别急我们可以通过制定一个相机,让它把渲染的图像不是显示到屏幕上,而是显示到一张我们设定好的二维图片上,我们在通过我们写的Shader来让它把这个相机所拍摄到物体的深度信息保存到这个二维图片(它现在就是深度图了)上,而不是颜色信息。这样在接下来的处理用我们就可以利用这个深度图来做一下事情了。


原理


  有了上面的一些概念我们就来了解一下实现的原理(当然了,实现遮挡描边的方法很多,而每一款游戏需要的效果也不尽相同,这里的方法仅供参考):

  大体上可以分四个大步骤:(下面的两张图片,在游戏中玩家是看不到的,开发人员也是看不到的,全部都是在代码中处理的,这里显示出来只是为了让大家能更好的理解一下)

  1.获得一共只包含我们要进行遮挡描边处理的物体(在我们的例子中,就是上图的那个士兵)深度信息的深度图。对于我们的例子,这一步的结果如下图,粗看起来是一片红,但是大家细看右边你会看到那个士兵的.至于为什么图像这么偏红,大家可以想想,我在下篇中会说明。

  

  2.通过比较判断主摄像机(就是你在Game窗口看到的图像所用到的摄像机)的深度信息和我们第一步中获得到的深度图信息,来界定出我们要处理的物体的哪些部分被挡住了。并对被遮挡全部涂上描边颜色。如下图

  

  3.把被遮挡部分分别进行一次左右,上下方向的拉伸一像素.这个就不用图了基本和上面的图一样,只是上下左右都多了一个像素,所以看起来不明显。

  4.最后把除了我们在第三步中额外绘制的一像素外轮廓以外,对角色的被遮挡部分还使用原来的颜色(就是墙本身的颜色)。效果就是本文一开始放的那个图片了。


涉及到的一些API


  这样我们就实现了遮挡描边,不过上面只是比较笼统的概括,有很多细节需要注意。具体的代码实现我会在下次的教程中进行具体讲解,这里我先把需要设计到的一些Unity知识列出来,很多内容都可以通过Unity的官方API文档查到,大家可以自己先了解一下然后试着实现一下遮挡描边。这样看下一次教程的时候会效果更好:

  1.在Unity进行后处理需要涉及到的一些API,有 OnRenderImage(...),RenderTexture.GetTemporary,RenderTexture.ReleaseTemporary,Graphics.Blit,RenderWithShader.

  2.在C#脚本中对Shader进行传值设计到的一些API,如Shader.SetGlobalXXX(),Shader.Find,Material.SetXXX().

  3.相机的深度模式,和Unity提供给我们的一个默认深度图.Camera.depthTextureMode,_CameraDepthTexture等.

  好了关于遮挡描边的原理篇基本就讲完了,怎么样是不是和之前几篇的内容有很多不同,这篇内容也只是做了一个抛砖引玉,只是希望大家能了解一下渲染中的几个重要概念,然后自己去做一些扩展,比如说深度缓冲和深度图,他们两个能够实现的效果远远不只是"遮挡描边"。更多神奇的功能还等待大家自己一起去探索。另外我会在近期完成"实现篇"的,这段时间大家不妨自己动手试着写写看,没准在我发下一篇之前,聪明的你啊已经搞定了呢!!!

  尊重他人智慧成果,欢迎转载,请注明作者esfog,原文地址 http://www.cnblogs.com/Esfog/p/CoverOutline_Shader.html

Esfog_UnityShader教程_遮挡描边(原理篇)的更多相关文章

  1. Esfog_UnityShader教程_遮挡描边(实现篇)

     在上一篇中,我们基本上说明了遮挡描边实现的一种基本原理.这一篇中我们将了解一下基于这种原理的具体实现代码.本篇中的内容和前几篇教程相比,相对比较难一些,建议先有一些基本的Unity的C#脚本编程经验 ...

  2. Esfog_UnityShader教程_镜面反射SpecularReflection

    系列教程第四篇,本来打算昨天写的,有些小偷懒就今天写了,这一期我们来讨论一下关于镜面反射的基本原理和具体代码.这一篇是承接着上一篇<Esfog_UnityShader教程_漫反射DiffuseR ...

  3. Esfog_UnityShader教程_前言

    很多人在学习Unity的时候对Shader都是一知半解,作为刚入职半年的新人接触Shader的时间也并不长,正因为是新人才能体会到学习Shader时候所遇到的困难和迷茫,无奈于资料不好找,网上难得的几 ...

  4. Esfog_UnityShader教程_漫反射DiffuseReflection

    这篇是系列教程的第三篇,最近工作比较紧,所以这个周六周日就自觉去加了刚回来就打开电脑补上这篇,这个系列的教程我会尽量至少保证一周写一篇的.如果大家看过我的上一篇教程<Esfog_UnitySha ...

  5. Esfog_UnityShader教程_逐帧动画

    有段日子没出这个系列的新文章了,今天就拿一个比较常见也比较基础的利用改变Shader来改变不断调整UV实现播放逐帧动画的小功能.很久没写了就当练练手了.在新版本的Unity中早就已经集成了Sprite ...

  6. Esfog_UnityShader教程_溶解效果Dissolve

    溶解效果在游戏中是很常见的,比如在一些神话或者魔法世界中,一些NPC角色在剧情需要时候会身体会渐渐的消失掉.甚至有一些更炫的,比如用火焰喷射器把目标燃尽.这些都可以用到溶解效果.这篇文章主要是讲解一下 ...

  7. Spring_MVC_教程_快速入门_深入分析

    Spring MVC 教程,快速入门,深入分析 博客分类: SPRING Spring MVC 教程快速入门  资源下载: Spring_MVC_教程_快速入门_深入分析V1.1.pdf Spring ...

  8. Hadoop安装教程_单机/伪分布式配置_Hadoop2.6.0/Ubuntu14.04

    摘自: http://www.cnblogs.com/kinglau/p/3796164.html http://www.powerxing.com/install-hadoop/ 当开始着手实践 H ...

  9. UnityShader实现物体被遮挡描边

    之前在网上看到物体遮挡描边的功能,自己也拿来实现了一番.算作第一篇博客的开篇. 先贴出几张效果图,也是个人思路和方案的改进路线吧. ////////////////////////////////// ...

随机推荐

  1. jsp的九大内置对象和四大作用域(转)

    定义:可以不加声明就在JSP页面脚本(Java程序片和Java表达式)中使用的成员变量 JSP共有以下9种基本内置组件(可与ASP的6种内部组件相对应): 1.request对象(作用域)  客户端的 ...

  2. Flask 的扩展

    1. Flask-Script,为Flask程序提供了一个命令行解析器: (venv) $ pip install flask-script 2. Bootstrap(http://getbootst ...

  3. centos x86_64环境下 下载chrome

    由于Cent OS内核版本过低,无法安装Chrome浏览器2.替代方案:可以使用Chromium浏览器 1.切换到root: su - 或者 sudo -i 2.下载新的软件源定义: cd /etc/ ...

  4. codeforces 733D

    明白了自己这么菜的原因多半是赛后不肯去补那些需要多花点时间思考的题目以及效率不高,但愿现在还不算晚... #include<bits/stdc++.h> #include<iostr ...

  5. 使用cordova插件barcodescanner遇到的坑

    最近接手了一个app任务,由于不懂android和ios,只想简单点写代码,所以,最终采用了基于H5的web框架:ionic + cordova(也叫phonegap)来开发.app的设计中有一个扫描 ...

  6. c :set标签的陷阱(未解决)

    三层嵌套的list,第二层解套的时候用Cset标签给设置别名,第一个对象正常使用,第二个对象开始传入内存的地址的值,但是无法获取对象属性

  7. ie 8 下post提交提交了两次

    擦你吗呀,IE8! 老子写一个登录功能,IE他妈的给我登录了两次,导致权限校验错误,什么他妈的鬼问题,调了两天....fuck,都是泪水. 解决方案:提交按钮加返回值<input type=&q ...

  8. 结对编程--基于android平台的黄金点游戏

    游戏内容: 阿超的课都是下午两点钟,这时班上不少的同学都昏昏欲睡,为了让大家兴奋起来,阿超让同学玩一个叫“黄金点”的游戏: N个同学(N通常大于10),每人写一个0~100之间的有理数 (不包括0或1 ...

  9. gui2

    事件:描述发生了什么的对象. 存在各种不同类型的事件类用来描述各种类型的用户交互. 事件源:事件的产生器. 事件处理器:接收事件.解释事件并处理用户交互的方法. 比如在Button组件上点击鼠标会产生 ...

  10. zeromq:c,c++,golang及nodejs使用

    官网:www.zeromq.org 消息队列比较:http://www.cnblogs.com/charlesblc/p/6058799.html zeromq的一些观点:http://www.cnb ...