Unity Shader -描边(后期处理)
之前的文章中我们通过两种方式分别实现了描边效果,他们各有优缺点,也比较简单,今天我们来通过后期处理这种方式来实现描边效果,相对于之前两种实现方式要稍微复杂一点。
后期处理的描边最终效果图如下:
实现大致思路:
首先我们添加一个额外的摄像机用来专门渲染需要描边的对象,通过设置摄像机的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 -描边(后期处理)相关推荐
- Unity Shader - 描边效果
原文链接:http://blog.csdn.net/puppet_master/article/details/54000951 简介 描边效果是游戏里面非常常用的一种效果,一般是为了凸显游戏中的某个 ...
- 【Unity Shader 描边效果_案例分享】
1.实现逻辑 描边效果Shader有多种实现方式,可以通过后处理和MatCap实现. 这次主要想展示的是通过两个Pass实现. 当Shader中有多个Pass时,渲染流程会安装顺序依次执行,于是后面的 ...
- Unity shader学习之屏幕后期处理效果之高斯模糊
高斯模糊,见 百度百科. 也使用卷积来实现,每个卷积元素的公式为: 其中б是标准方差,一般取值为1. x和y分别对应当前位置到卷积中心的整数距离. 由于需要对高斯核中的权重进行归一化,即使所有权重相加 ...
- Unity Shader 卡通渲染 模型描边之退化四边形
目录 前言 一.基于空间的边缘检测算法 二.退化四边形 三.Unity中的CommandBuffer和ComputeBuffer 四.构成描边的简单实例 五.模型描边的实现 前言 之前写了一篇< ...
- Unity Shader 卡通渲染 实时模型动画描边的研究
前言 卡通渲染也叫非真实感渲染(英文简写:NPR),"描边"在图形学和数字图像里都叫边缘检测.因此你可以在很多文献网站上面找到很多这类文献,但最后我发现基于图形学使用的方式基本都是 ...
- 【unity shader】unity游戏特效-遮挡显示效果 (含边缘光、描边效果版)
不知道你们有没有在玩Black Squad这个游戏啊 在被对手干掉时会有敌人高亮显示效果 (未被做掉时) (被做掉后高亮显示敌人位置) 明明敌人被不透明物体挡住却仍然可以被渲染出来 这效果要是能扔进自 ...
- Unity Shader 学习笔记(27)渲染轮廓线(描边)方法、卡通风格渲染、素描风格渲染
Unity Shader 学习笔记(27)渲染轮廓线(描边)方法.卡通风格渲染.素描风格渲染 参考书籍:<Unity Shader 入门精要> 渲染轮廓线(描边) 五种方法: 基于观察角度 ...
- Unity Shader学习笔记(5)基于摄像机深度和法线的后处理描边效果
文章目标 : 主要参考书籍为<Unity Shader入门精要>,本文主要注重于整理,方便后续直接调用. 渲染效果图: 主要相关代码: 摄像机脚本文件: using System.Coll ...
- Unity Shader入门学习(5):基础屏幕后处理
1.后处理基类 //屏幕后处理,顾名思义,通常指的是在渲染完整个场景得到屏幕图像后,再对这个图像进行一系列操作,实现各种屏幕特效. //基类的作用有二:检测平台是否支持后处理效果,及创建一个用于处理渲 ...
最新文章
- glassfish_多种监视和管理GlassFish 3的方法
- 高级软件工程2017第2次作业—— 个人项目:四则运算题目生成程序(基于控制台)...
- 华为 ICT 助力智能车,钢铁侠小鹏隔空喊话,Car OS 年终大盘点
- 【meitong】Windows系统受损切莫将就使用 如何快速修复
- 我常用的分页存储过程
- mysql 面试知识点笔记(三)联合索引的最左匹配原则
- 为antd tree组件 在onSelect时获取额外数据
- matlab 复制 模块,想把m文件在simulink 中的调用,我用的是matlab function 模块。
- 个人理财通Android手机测试,基于Android的个人理财管理系统
- 基于Gitee搭建免费图床
- 服务器解决了什么问题、状态同步和帧同步
- OpenCV裁剪图像任意区域
- AWS全球年度技术大会--上海站、广州站
- 2.MySQL索引优化
- 一些计算两台主机之间进行socket通信的延迟的小程序
- Decimal的用法简介
- 2023年全国最新会计专业技术资格精选真题及答案10
- 把普通路由器扩展为WIFI广告路由器
- git linux 文件名乱码,git 中文文件名乱码
- 实用的Dock栏快速启动工具:uDock for Mac