描边的实现方式有许多种,如sobel,法线外扩,网上都有对应大佬写的文章可以查阅。
做了个测试顺便分享下URP管线在shader graph里面不增加render feature的情况下,将该算法放入hlsl文件中,然后使用custom function节点实现该描边效果。主要是对不了解shaderlab的分享下custom function如何使用,最终效果还是有点问题不推荐使用。
如果要是实现的话可以选择使用官方推荐的方法。在URP管线中render feature实现描边的方法官方demo:URP实现outline
关于custom function两种使用方式,本文分享加载hlsl的。
先上效果吧:
网上有些文章写了如何使用,但对于萌新以及我这种连连连看都无法特别理解的菜鸡还是有点摸不着头脑。
1.unity无法直接创建.hlsl文件,所以直接创建一个.shader文件,然后将其后缀改为.hlsl即可。
2.接下来是HLSL文件的格式说明(针对不懂shader的自学党,大佬请忽略)
#ifndef SOBEL
#define SOBEL
//前面这部分#ifndef #define包括最后#endif 的意思是如果没有定义xxx(宏名称),则定义xxx(宏名称),名称是没有限制的形式的,可以随意起。包括其实连这部分都可以不要,直接放入函数都行,但是为了规范起见,就是需要了解关于定义宏的使用知识,建议用一下。可以自行测试一下,新建一个unlit shader在shader中定义一个同名称的宏就会发现会出问题了。
#include "HLSLSupport.cginc"
//引用上面这个内置文件时因为下面的SAMPLE_DEPTH_TEXTURE在HLSLSupport.cginc中有被定义了。但是用了后报了个警告,也没找到对应的文件。
接下来从使用了网上别人写的关于sobel算法描边相关的shader,取了如下核心计算部分。shader的链接找不到了,回头找到了补充上去。
sampler2D _CameraDepthTexture;
//这个_CameraDepthTexture会自动调用相机深度图,名称要对上,前提需要在setting里面开启depth texture
float SampleDepth(float2 uv )
{
return SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, uv);
}
//上面的uv指的是屏幕坐标UV,待会会在custom function节点中开放输入,名字需要跟输入的名称保持一致。
void SOBEL_float(float _Delta , float2 uv , out float Out)
//SOBEL_float这里SOBEL是函数名,待会在custom function node中需要使用,_float表示精度,还有_half,官方文档中有些这里该如何使用。链接:custom function使用
//括号中的(float _Delta , float2 uv , out float Out),都是需要跟custom function面板上开放的参数对应上。菜鸡的我没找到如果输入贴图咋整2333
{
float2 delta = float2(_Delta, _Delta);
float hr = 0;
float vt = 0;
hr += SampleDepth(uv + float2(-1.0, -1.0) * delta) * 1.0;
hr += SampleDepth(uv + float2( 1.0, -1.0) * delta) * -1.0;
hr += SampleDepth(uv + float2(-1.0, 0.0) * delta) * 2.0;
hr += SampleDepth(uv + float2( 1.0, 0.0) * delta) * -2.0;
hr += SampleDepth(uv + float2(-1.0, 1.0) * delta) * 1.0;
hr += SampleDepth(uv + float2( 1.0, 1.0) * delta) * -1.0;
vt += SampleDepth(uv + float2(-1.0, -1.0) * delta) * 1.0;
vt += SampleDepth(uv + float2( 0.0, -1.0) * delta) * 2.0;
vt += SampleDepth(uv + float2( 1.0, -1.0) * delta) * 1.0;
vt += SampleDepth(uv + float2(-1.0, 1.0) * delta) * -1.0;
vt += SampleDepth(uv + float2( 0.0, 1.0) * delta) * -2.0;
vt += SampleDepth(uv + float2( 1.0, 1.0) * delta) * -1.0;
//Out = 1 ;
Out = sqrt(hr * hr + vt * vt);
}
//以上就是sobel的核心函数,需要注意的是void没有返回值,所以最后不能使用return。所以直接Out输出
#endif
3.接下来就是在面板上面如何将第二步中的这些信息跟node上对应上了。
1是跟SOBEL_float或者SOBEL_half相关,指调用哪个精度的函数。
2inputs和outputs分别是SOBEL对应函数的输入输出
3是file形式的custom function
4这里的name要跟函数的名称对应上,后面的_float就不需要带上了
5是指.hlsl文件,直接拽上去就好了。
结果:
最终效果有问题哈哈哈哈,如果要使用这个方法实现不建议,或者后续看有没有时间找找原因。重点是分享custom function如何使用,这样就可以移植很多shaderlab的内容了!!!!以上就先这样了,自己摸索尝试的理解上应该有问题,有幸被大佬看到希望可以指出有问题的地方哈哈哈。感恩感谢~
可能连连看玩家关于sobel的理解也会有点疑问,后续我再整理一下sobel算法的。希望可以举一反三彻底理解哈哈哈