之前的文章中我们通过两种方式分别实现了描边效果,他们各有优缺点,也比较简单,今天我们来通过后期处理这种方式来实现描边效果,相对于之前两种实现方式要稍微复杂一点。

后期处理的描边最终效果图如下:

实现大致思路:

首先我们添加一个额外的摄像机用来专门渲染需要描边的对象,通过设置摄像机的LayerMask即可,然后将摄像机的Render Target设置为我们设定好的一张Render Texture上,设置如下:

然后在渲染之前(可以通过Unity内置的方法OnPreRender处理),通过一个纯色shader来处理该Render Texture,使其变为纯色,如下图

关键代码如下:

然后我们通过均值模糊或者高斯模糊来处理该RenderTexture,使其模糊 膨胀,然后和模糊之前的RenderTexture相减即可得到轮廓图。如图所示:


此时得到了轮廓图之后就好办了,直接和原图叠加即可得到最终的效果图

本篇文章采用了高斯模糊(参考了《Unity Shader入门精要》书中的高斯模糊)来处理RenderTexture,
高斯模糊也可以参考这里

最终代码如下:

Shader:

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
// ---------------------------【后处理-描边】---------------------------
Shader "lcl/screenEffect/outLine"
{// ---------------------------【属性】---------------------------Properties{_MainTex ("Texture", 2D) = "white" {}}// ---------------------------【子着色器】---------------------------SubShader{CGINCLUDE#include "UnityCG.cginc"sampler2D _MainTex;half4 _MainTex_TexelSize;float _BlurSize;sampler2D _BlurTex;sampler2D _SrcTex;fixed4 _OutlineColor;// ---------------------------【高斯模糊】---------------------------struct v2f{float4 pos : SV_POSITION;half2 uv[5]: TEXCOORD0;};//垂直方向的高斯模糊v2f vertBlurVertical(appdata_img v) {v2f o;o.pos = UnityObjectToClipPos(v.vertex);half2 uv = v.texcoord;o.uv[0] = uv;o.uv[1] = uv + float2(0.0, _MainTex_TexelSize.y * 1.0) * _BlurSize;o.uv[2] = uv - float2(0.0, _MainTex_TexelSize.y * 1.0) * _BlurSize;o.uv[3] = uv + float2(0.0, _MainTex_TexelSize.y * 2.0) * _BlurSize;o.uv[4] = uv - float2(0.0, _MainTex_TexelSize.y * 2.0) * _BlurSize;return o;}//水平方向的高斯模糊v2f vertBlurHorizontal(appdata_img v) {v2f o;o.pos = UnityObjectToClipPos(v.vertex);half2 uv = v.texcoord;o.uv[0] = uv;o.uv[1] = uv + float2(_MainTex_TexelSize.x * 1.0, 0.0) * _BlurSize;o.uv[2] = uv - float2(_MainTex_TexelSize.x * 1.0, 0.0) * _BlurSize;o.uv[3] = uv + float2(_MainTex_TexelSize.x * 2.0, 0.0) * _BlurSize;o.uv[4] = uv - float2(_MainTex_TexelSize.x * 2.0, 0.0) * _BlurSize;return o;}//高斯模糊片段着色器fixed4 fragBlur(v2f i) : SV_Target {float weight[3] = {0.4026, 0.2442, 0.0545};fixed3 sum = tex2D(_MainTex, i.uv[0]).rgb * weight[0];for (int it = 1; it < 3; it++) {sum += tex2D(_MainTex, i.uv[it*2-1]).rgb * weight[it];sum += tex2D(_MainTex, i.uv[it*2]).rgb * weight[it];}return fixed4(sum, 1.0);}// ---------------------------【轮廓图】---------------------------//Blur图和原图进行相减获得轮廓struct v2f_cull{float4 pos : SV_POSITION;half2 uv: TEXCOORD0;};v2f_cull vert_cull(appdata_img v){v2f_cull o;o.pos = UnityObjectToClipPos(v.vertex);o.uv = v.texcoord.xy;//dx中纹理从左上角为初始坐标,需要反向//通过判断_MainTex_TexelSize.y是否小于0来检验是否开启了抗体锯齿#if UNITY_UV_STARTS_AT_TOPif (_MainTex_TexelSize.y < 0)o.uv.y = 1 - o.uv.y;#endif    return o;}fixed4 frag_cull(v2f_cull i) : SV_Target{//取原始场景纹理进行采样fixed4 mainColor = tex2D(_MainTex, i.uv);//对blur之前的rt进行采样fixed4 srcColor = tex2D(_SrcTex, i.uv);//对blur后的纹理进行采样fixed4 blurColor = tex2D(_BlurTex, i.uv);//相减后得到轮廓图fixed4 outline = ( srcColor - blurColor) * _OutlineColor;//输出:blur部分为0的地方返回原始图像,否则为0,然后叠加描边fixed4 final = saturate(outline) + mainColor;return final;}ENDCG// No culling or depthCull Off ZWrite Off ZTest Always//垂直高斯模糊Pass {CGPROGRAM#pragma vertex vertBlurVertical  #pragma fragment fragBlurENDCG  }//水平高斯模糊Pass {  CGPROGRAM  #pragma vertex vertBlurHorizontal  #pragma fragment fragBlurENDCG}//轮廓图Pass {  CGPROGRAM  #pragma vertex vert_cull  #pragma fragment frag_cullENDCG}}FallBack "Diffuse"}

C#: PostEffectsBase基类可以参考这里

using System.Collections;
using UnityEngine;//编辑状态下也运行
[ExecuteInEditMode]
//继承自PostEffectsbase
public class OutLine : PostEffectsBase {//主相机private Camera mainCamera = null;//渲染纹理private RenderTexture renderTexture = null;private Material _material = null;/// 辅助摄像机  public Camera outlineCamera;// 纯色shaderpublic Shader purecolorShader;//描边处理的shaderpublic Shader shader;//迭代次数[Range (0, 4)]public int iterations = 3;//模糊扩散范围[Range (0.2f, 3.0f)]public float blurSpread = 0.6f;private int downSample = 1;public Color outlineColor = new Color (1, 1, 1, 1);public Material outlineMaterial {get {_material = CheckShaderAndCreateMaterial (shader, _material);return _material;}}void Awake () {mainCamera = GetComponent<Camera> ();if (mainCamera == null)return;createPurecolorRenderTexture ();}// ---------------------------【创建一个RenderTexture】---------------------------private void createPurecolorRenderTexture () {outlineCamera.cullingMask = 1 << LayerMask.NameToLayer ("Player");int width = outlineCamera.pixelWidth >> downSample;int height = outlineCamera.pixelHeight >> downSample;renderTexture = RenderTexture.GetTemporary (width, height, 0);}// ---------------------------【渲染之前调用】---------------------------private void OnPreRender () {if (outlineCamera.enabled) {//设置创建好的RenderTextureoutlineCamera.targetTexture = renderTexture;//渲染了一张纯色RenderTextureoutlineCamera.RenderWithShader (purecolorShader, "");}}//-------------------------------------【OnRenderImage函数】------------------------------------    // 说明:此函数在当完成所有渲染图片后被调用,用来渲染图片后期效果//--------------------------------------------------------------------------------------------------------  private void OnRenderImage (RenderTexture source, RenderTexture destination) {int rtW = source.width >> downSample;int rtH = source.height >> downSample;var temp1 = RenderTexture.GetTemporary (rtW, rtH, 0);var temp2 = RenderTexture.GetTemporary (rtW, rtH, 0);// 高斯模糊处理Graphics.Blit (renderTexture, temp1);for (int i = 0; i < iterations; i++) {outlineMaterial.SetFloat ("_BlurSize", 1.0f + i * blurSpread);//垂直高斯模糊Graphics.Blit (temp1, temp2, outlineMaterial, 0);//水平高斯模糊Graphics.Blit (temp2, temp1, outlineMaterial, 1);}//用模糊图和原始图计算出轮廓图outlineMaterial.SetColor ("_OutlineColor", outlineColor);outlineMaterial.SetTexture ("_BlurTex", temp1);outlineMaterial.SetTexture ("_SrcTex", renderTexture);Graphics.Blit (source, destination, outlineMaterial, 2);}
}

参考

《Unity Shader 入门精要》
https://blog.csdn.net/puppet_master/article/details/54000951

Unity Shader -描边(后期处理)相关推荐

  1. Unity Shader - 描边效果

    原文链接:http://blog.csdn.net/puppet_master/article/details/54000951 简介 描边效果是游戏里面非常常用的一种效果,一般是为了凸显游戏中的某个 ...

  2. 【Unity Shader 描边效果_案例分享】

    1.实现逻辑 描边效果Shader有多种实现方式,可以通过后处理和MatCap实现. 这次主要想展示的是通过两个Pass实现. 当Shader中有多个Pass时,渲染流程会安装顺序依次执行,于是后面的 ...

  3. Unity shader学习之屏幕后期处理效果之高斯模糊

    高斯模糊,见 百度百科. 也使用卷积来实现,每个卷积元素的公式为: 其中б是标准方差,一般取值为1. x和y分别对应当前位置到卷积中心的整数距离. 由于需要对高斯核中的权重进行归一化,即使所有权重相加 ...

  4. Unity Shader 卡通渲染 模型描边之退化四边形

    目录 前言 一.基于空间的边缘检测算法 二.退化四边形 三.Unity中的CommandBuffer和ComputeBuffer 四.构成描边的简单实例 五.模型描边的实现 前言 之前写了一篇< ...

  5. Unity Shader 卡通渲染 实时模型动画描边的研究

    前言 卡通渲染也叫非真实感渲染(英文简写:NPR),"描边"在图形学和数字图像里都叫边缘检测.因此你可以在很多文献网站上面找到很多这类文献,但最后我发现基于图形学使用的方式基本都是 ...

  6. 【unity shader】unity游戏特效-遮挡显示效果 (含边缘光、描边效果版)

    不知道你们有没有在玩Black Squad这个游戏啊 在被对手干掉时会有敌人高亮显示效果 (未被做掉时) (被做掉后高亮显示敌人位置) 明明敌人被不透明物体挡住却仍然可以被渲染出来 这效果要是能扔进自 ...

  7. Unity Shader 学习笔记(27)渲染轮廓线(描边)方法、卡通风格渲染、素描风格渲染

    Unity Shader 学习笔记(27)渲染轮廓线(描边)方法.卡通风格渲染.素描风格渲染 参考书籍:<Unity Shader 入门精要> 渲染轮廓线(描边) 五种方法: 基于观察角度 ...

  8. Unity Shader学习笔记(5)基于摄像机深度和法线的后处理描边效果

    文章目标 : 主要参考书籍为<Unity Shader入门精要>,本文主要注重于整理,方便后续直接调用. 渲染效果图: 主要相关代码: 摄像机脚本文件: using System.Coll ...

  9. Unity Shader入门学习(5):基础屏幕后处理

    1.后处理基类 //屏幕后处理,顾名思义,通常指的是在渲染完整个场景得到屏幕图像后,再对这个图像进行一系列操作,实现各种屏幕特效. //基类的作用有二:检测平台是否支持后处理效果,及创建一个用于处理渲 ...

最新文章

  1. glassfish_多种监视和管理GlassFish 3的方法
  2. 高级软件工程2017第2次作业—— 个人项目:四则运算题目生成程序(基于控制台)...
  3. 华为 ICT 助力智能车,钢铁侠小鹏隔空喊话,Car OS 年终大盘点
  4. 【meitong】Windows系统受损切莫将就使用 如何快速修复
  5. 我常用的分页存储过程
  6. mysql 面试知识点笔记(三)联合索引的最左匹配原则
  7. 为antd tree组件 在onSelect时获取额外数据
  8. matlab 复制 模块,想把m文件在simulink 中的调用,我用的是matlab function 模块。
  9. 个人理财通Android手机测试,基于Android的个人理财管理系统
  10. 基于Gitee搭建免费图床
  11. 服务器解决了什么问题、状态同步和帧同步
  12. OpenCV裁剪图像任意区域
  13. AWS全球年度技术大会--上海站、广州站
  14. 2.MySQL索引优化
  15. 一些计算两台主机之间进行socket通信的延迟的小程序
  16. Decimal的用法简介
  17. 2023年全国最新会计专业技术资格精选真题及答案10
  18. 把普通路由器扩展为WIFI广告路由器
  19. git linux 文件名乱码,git 中文文件名乱码
  20. 实用的Dock栏快速启动工具:uDock for Mac

热门文章

  1. MatLab常见函数和运算符号
  2. HTTP如何保证安全传输
  3. 年老时最后悔但为时已晚的几件事
  4. Python——字典的遍历
  5. java中的高内聚和低耦合和接口的简单理解
  6. FPM生成Allegro封装常见问题及解决方法
  7. Hive常用函数大全
  8. ubuntu 下如何下载linux内核源码
  9. DP问题之01背包如此简单
  10. Android studio三周学习总结