在UnrealEngine中用Custom节点实现描边效果
在《Real Time Rendering, third edition》一书中,作者把描边算法分成了5种类型。
1、基于观察角度与表面法线的轮廓渲染。缺点很明显。
2、过程式几何轮廓渲染。即先渲染背面,通过顶点压平等手段,渲染轮廓线,之后渲染正面。优点:快速有效,适合大多数模型,缺点:不合适和立方体之类的平整模型。
3、基于图像处理的轮廓线渲染。通过边缘监测来判断轮廓。
4、基于轮廓检测的轮廓线渲染。同时监测相邻的2个面法线值得正负是否相反。
5、以上方法结合。
除此之外还有:
6、沿法线方向放大模型(vs)并用描边色渲染(ps)正常渲染模型
7、直接模糊模板
其中2、4、6在材质编辑器中是做不到,接下来本人将会分享剩下几种方法的代码。方法2在材质编辑器里无法实现因为TwoSideSign无法用于世界位移(通过摄像机向量与法向量点乘判断的方式也被不行)
其实是可以做到的,不过比较蛋疼,那就是复制一个模型,设Mask为0,同时沿着法线方向放大。从而得到放大的模板。具体做法不再复述,如果不会做,可以留言问我。
4.15版本的项目设置中多了这个,应该可以解决边缘抖动的问题,所以推荐使用4.15版本

然后Epic的程序员竟然忘记给Custom Stencil加这个功能,这就导致了我的部分效果会出现抖动的问题,我能说MDZZ么?
首先是方法3。边缘检测有以下几种检测算子(摘自UntiyShader入门精要),不过查了网上的资料,感觉还是Sobel比较好,所以别的2种不搞了。

当然还有别的,在此就不深入了。
虚幻4案例里就是用这个方法以及检测算子Prewitt(www.tomlooman.com里的案例),通过边缘检测深度的方式来。以下是我转化的HLSL代码:
//input SceneTexSize
//input UV
//input NotUse
//input OutLineSize
//input MaxZ
//input Alpha
//input OutLineColor
float Depth=;
float2 Sampler[]={float2(-,-),float2(-,),float2(-,),
float2(,-),float2(,),
float2(,-),float2(,),float2(,)}; for(int i=;i< ;i++)
{
Depth+=SceneTextureLookup(UV+Sampler[i]*SceneTexSize*OutLineSize,,false).x;
}
//Normalize Depth to 0.0-1.0 Range,规整化
Depth=MaxZ/(clamp(Depth,,MaxZ)+MaxZ);
//自定义深度物体的遮罩
float Mask=MaxZ/(SceneTextureLookup(UV,,false).x+MaxZ);
//减去自定义深度物体部分,也就是得到轮廓,0.2是因子,可以设置变量来 调节
Depth+=-MaxZ/(SceneTextureLookup(UV,,false).x+MaxZ)+0.2; //深度部分到此为止,以下物体透视部分
//被物体遮挡了
float Check=SceneTextureLookup(UV,,false).x-SceneTextureLookup(UV,,false).x;
float KeepOut=floor(Mask*);
if(Check>)
{
Check=clamp(KeepOut,,);
}else
{
Check=;
}
KeepOut*=Alpha*Check;
Depth=clamp(-Depth+KeepOut,,); return lerp(SceneTextureLookup(UV,,false),OutLineColor,Depth);

这段代码还包含了透视效果,如果只需要描边可以自己编辑。感觉和传统边缘检测不一样。
官方的风格化渲染用的是Roberts检测算子,以下是对应HLSL代码(因为Sphere
Mask不是HLSL中的原生函数,所以去掉了,而且感觉不太好理解,就没有深入),略有修改:
//input SceneTexSize
//input UV
//input NotUse
//input OutLineSize
//input OutLineColor
//input PostProcessBlendWeight
float4 Depth=;
float2 Sampler[]={float2(-,),float2(,-),
float2(,),float2(,)}; for(int i=;i< ;i++)
{
Depth+=SceneTextureLookup(UV,,false)-SceneTextureLookup(UV+Sampler[i]*SceneTexSize*OutLineSize,,false);
}
Depth=clamp((-clamp(Depth/-,,))*,,); Depth=(-Depth).x*lerp(clamp(-SceneTextureLookup(UV,,false).x/,0.25,),clamp(-SceneTextureLookup(UV,,false).x/,,),PostProcessBlendWeight);
return lerp(SceneTextureLookup(UV,,false),OutLineColor,Depth);
不过需要注意的是最后的轮廓往往是半透明的,所以需要在倒数第二行增加:
if(Depth>OutLineDepth)
{
Depth=;
}
通过判断深度的方式强行让Depth=1,从而实现让轮廓变实。(OutLineDepth为自己设置的变量)

Sobel检测算子HLSL代码,基于亮度检测:
//input SceneTexSize
//input UV
//input NotUse
//input OutLineSize
//input MaxZ
//input OutLineColor
float3 w=float3(0.2125,0.7154,0.0721);
float2 Sampler[]={float2(-,-),float2(-,),float2(-,),
float2(,-),float2(,),float2(,),
float2(,-),float2(,),float2(,)};
float2 UVOffset[]={float2(-,-),float2(,-),float2(,-),
float2(-,),float2(,),float2(,),
float2(-,),float2(,),float2(,),};
float2 Edge=;
for(int i=;i< ;i++)
{
Edge+=Sampler[i]*dot(SceneTextureLookup(UV+UVOffset[i]*SceneTexSize*OutLineSize,,false).xyz,w);
}
//最后的length可以改成1-abs(Edge.x)-abs(Edge.y),这样可以减少运算量
return lerp(
SceneTextureLookup(UV,,false),OutLineColor,length(Edge));

方法5法线与深度相配合的边缘检测:因为用SceneTextureLookup(UV,8,false);会有Bug,所以暂时空着,直接用节点写。


方法7代码(模糊用的是之前写的代码,我懒得改了,这个模糊其实有点问题):
int UVOfferset[]={-,-,-,,,,};
float Weights[]=
{
,,,,,,,
,,,,,,,
,,,,,,,
,,,,,,,
,,,,,,,
,,,,,,,
,,,,,,
};
float3 OutColor={0.0,0.0,0.0};
for(int i=;i<=;i++)
{
for(int j=;j<=;j++)
{
OutColor+=Weights[i*+j]*SceneTextureLookup(UV+float2(UVOfferset[j]*SceneTexSize.x*OutLineSize,UVOfferset[i]*SceneTexSize.y*OutLineSize),,false);
}
}
float Alpha=(float4(OutColor,1.0f)/-SceneTextureLookup(UV,,false)).x;
Alpha=smoothstep(,Max,Alpha);
return lerp(SceneTextureLookup(UV,,false).xyz,OutLineColor,Alpha);


官方论坛上还有几个案例:
https://forums.unrealengine.com/showthread.php?127151-Custom-Stencil-Radial-Silhouette-Post-Process-Materiel-(HLSL)-(PC)-(Full-code)-(4-13)&highlight=SceneTextureLookup
这个本质上还是用的是Sobel检测算子,不过读了他的HLSL本人也有些许启发,比如做上面的边缘虚化效果可以使用多次边缘检测。这样比直接用均值模糊效果好。
在UnrealEngine中用Custom节点实现描边效果的更多相关文章
- 在UnrealEngine中用Custom节点实现马赛克效果
参考这位大神的Shaderhttp://blog.csdn.net/noahzuo/article/details/51316015 //input BaseUV 屏幕UV //intput Tili ...
- 在UnrealEngine中用Custom节点实现毛玻璃的效果
本人在论坛上找到了一篇实现毛玻璃效果的文章:https://forums.unrealengine.com/showthread.php?70143-So-Blurred-glass-material ...
- 在UnrealEngine中用Custom节点实现高斯模糊
3x3高斯模糊 //input sW 分辨率宽 //input sH 分辨率高 //input NotUse 为了开启SceneTextureLookup函数而连接的节点,但是不参与逻辑 //inpu ...
- 在UnrealEngine中用Custom节点实现径向模糊
//input NotUse 为了开启SceneTextureLookup函数而连接的节点,但是不参与逻辑 //input UV 屏幕缓存的坐标坐标 //input Strength 力度 //inp ...
- UE4实现描边效果
描边效果属于常见常用的功能,现VR项目中,也需要射线选中一个物体,使物体高亮. 于是在网上找了部分资料,同时也感谢群里的一位大神的提点,总算将描边的功能实现了,这里也写一个简单的示例步骤. 1.我并不 ...
- 有关UnrealEngine材质编辑器中的Custom节点的一些小贴士
PS:本文写于2017.2.1日,使用版本为4.13.第二次更新时间为2017.3.15增加了四.一些材质编辑器中的奇怪的技巧: 一.前言在Unreal中材质编辑器提供了Custom节点,作为HLSL ...
- unity描边效果
这里总结了几种在unity实现描边效果的方法,首先准备一个模型导入在unity中,使用默认shader,上传一张原始图,以便后面实现功能效果的对比 一.边缘光,这里参照官方的一个SurfaceShad ...
- Unity Shader实现描边效果
http://gad.qq.com/article/detail/28346 描边效果是游戏里面非常常用的一种效果,一般是为了凸显游戏中的某个对象,会给对象增加一个描边效果.本篇文章和大家介绍下利用S ...
- [Flutter] 支持描边效果的Text
新版的flutter已经自带这个功能了.TextSyle 中一个shadow . 目前flutter中没找到很好的办法给Text增加描边.自己扩展了一个TextEx,可以实现简单的描边效果,能满足大部 ...
随机推荐
- windows 下命令行启动停止mysql
MySQL比较好玩一点就是它可以用多种方式启动,当然它也可以用多种方式关闭.下面我就mysql的几种启动方式简单的谈一谈,希望可以给大家提供一些参考. 第一种,用mysqld-nt来启动. 在没有进行 ...
- 开启或停止website
1.添加:Microsoft.Web.Administration 2.代码: static void Main(string[] args) { var server = new ServerMan ...
- data-key
在foreach或者each循环中给按钮赋予值 html中:data-key="@config.key" js里获取值: var key = $(this).data(" ...
- 小米8如何root
现身说法,实测有效,也踩坑很多. 0. 准备手机.数据线.windows系统的电脑.小米帐号,各一个. 手机需要装上sim卡:电脑需要能上网.最好是有wifi的环境,用来下载安装包. 注意提前备份数据 ...
- Spring MVC基础知识整理➣拦截器和自定义注解
概述 Spring MVC中通过注解来对方法或者类进行动态的说明或者标注,类似于配置标识文件的属性信息.当标注的类或者方式被使用时候,通过提取注解信息来达到对类的动态处理.在 MVC中,我们常用的注解 ...
- Codeforces 758F Geometrical Progression
Geometrical Progression n == 1的时候答案为区间长度, n == 2的时候每两个数字都可能成为答案, 我们只需要考虑 n == 3的情况, 我们可以枚举公差, 其分子分母都 ...
- GFS 安装使用
准备环境: 1.OS: Centos:7.2x86_64 2.主机 server1: 192.168.30.41 wohaoshuai1 server2: 192.168.30.42 wohaoshu ...
- windows docker常用命令
关键词 示例 作用 attach sudo docker run -itd ubuntu:14.04 /bin/bash 进入容器 exec docker exec -it mysql bash 在容 ...
- 获取Form表单数据转化成JSON对象
$.fn.serializeObject = function() { var o = {}; var a = this.serializeArray(); $.each(a, function() ...
- NOI2018Day1T1 归程 并查集 kruskal kruskal重构树 倍增表 Dijkstra
原文链接https://www.cnblogs.com/zhouzhendong/p/NOI2018Day1T1.html 题目传送门 - 洛谷P4768 题意 给定一个无向连通图,有 $n$ 个点 ...