1.原理

利用几何着色器,生成新的顶点,用新生成的顶点,构建描边,在用模板测试剔除原模型,如下图

灰色三角形是模型原来的一个三角面,用几何着色器,延顶点法线向外,创建出新的顶点A,B,C。已知一个面的构成需要三个顶点,依次连接顶点,总共创建了6个新的面,这六个面就构成灰色三角形的描边。再用模板测试的原理对模型进行Mask,得到描边。

2.代码

Properties{[HDR]_OutlineColor ("TintColor", Color) = (1,1,1,1)_OutlineWidth ("OutlineWidth", Range(0.001, 0.01)) = 0.001}

属性定义了描边的颜色,描边的宽度。

struct a2v {float4 vertex : POSITION;    float3 normal : NORMAL;
};

输入模型的顶点,法线。

struct v2gf {float4 g_vertex : TEXCOORD0;float3 g_normal : TEXCOORD1;float4 pos : SV_POSITION;};

输出顶点,法线,裁剪空间下的顶点。

v2gf vert(a2v v) {v2gf o;o.g_vertex = v.vertex;o.g_normal = v.normal;o.pos = UnityObjectToClipPos(v.vertex);return o;}

顶点和法线处理,直接传入模型空间下的顶点,后面在几何处理中,再进行空间变换。

v2gf Offset(v2gf o) {v2gf extruded = o;float3 vNormal = mul((float3x3)UNITY_MATRIX_IT_MV, o.g_normal.xyz);float2 vOffset = TransformViewToProjection(vNormal.xy);vOffset.xy = normalize(vOffset.xy);extruded.pos = UnityObjectToClipPos(o.g_vertex);extruded.pos.xy += vOffset.xy * extruded.pos.w * _OutlineWidth;return extruded;}

在齐次裁剪空间下对顶点延法线进行偏移,得到新的顶点坐标,顶点在齐次裁剪空间下,w的值反应了和相机的远近关系,故乘以extruded.pos.w,当相机拉远和拉近,有宽度的变化。

#define APPEND(o)\outputStream.Append(o);[maxvertexcount(18)]void geom(triangle v2gf inputTriangle[3], inout TriangleStream<v2gf> outputStream) {v2gf extrusionTriangle0 = Offset(inputTriangle[0]);v2gf extrusionTriangle1 = Offset(inputTriangle[1]);v2gf extrusionTriangle2 = Offset(inputTriangle[2]);APPEND(inputTriangle[0]);APPEND(extrusionTriangle0);APPEND(inputTriangle[1]);APPEND(extrusionTriangle0);APPEND(extrusionTriangle1);APPEND(inputTriangle[1]);APPEND(inputTriangle[1]);APPEND(extrusionTriangle1);APPEND(extrusionTriangle2);APPEND(inputTriangle[1]);APPEND(extrusionTriangle2);APPEND(inputTriangle[2]);APPEND(inputTriangle[2]);APPEND(extrusionTriangle2);APPEND(inputTriangle[0]);APPEND(extrusionTriangle2);APPEND(extrusionTriangle0);APPEND(inputTriangle[0]);}

由原理部分的图,我们需要输出新的6个面,以及6*3=18个顶点,来构成描边模型。前面先处理了新的顶点,通过输出流,写入新的顶点来构成三角面。

下面是完整代码,用了两个Pass,对模板测试进行配置。

Shader "Custom/Unlit/CustomSilhouette"
{Properties{[HDR]_OutlineColor ("TintColor", Color) = (1,1,1,1)//_OutlineWidth ("OutlineWidth", Range(0.001, 0.01)) = 0.001}CGINCLUDE#pragma target 4.0#include "UnityCG.cginc"fixed4 _OutlineColor;float _OutlineWidth;struct a2v {float4 vertex : POSITION;float3 normal : NORMAL;};struct v2gf {float4 g_vertex : TEXCOORD0;float3 g_normal : TEXCOORD1;float4 pos : SV_POSITION;};v2gf vert(a2v v) {v2gf o;o.g_vertex = v.vertex;o.g_normal = v.normal;o.pos = UnityObjectToClipPos(v.vertex);return o;}v2gf Offset(v2gf o) {v2gf extruded = o;float3 vNormal = mul((float3x3)UNITY_MATRIX_IT_MV, o.g_normal.xyz);float2 vOffset = TransformViewToProjection(vNormal.xy);vOffset.xy = normalize(vOffset.xy);extruded.pos = UnityObjectToClipPos(o.g_vertex);extruded.pos.xy += vOffset.xy * extruded.pos.w * _OutlineWidth;return extruded;}#define APPEND(o)\outputStream.Append(o);[maxvertexcount(18)]void geom(triangle v2gf inputTriangle[3], inout TriangleStream<v2gf> outputStream) {v2gf extrusionTriangle0 = Offset(inputTriangle[0]);v2gf extrusionTriangle1 = Offset(inputTriangle[1]);v2gf extrusionTriangle2 = Offset(inputTriangle[2]);APPEND(inputTriangle[0]);APPEND(extrusionTriangle0);APPEND(inputTriangle[1]);APPEND(extrusionTriangle0);APPEND(extrusionTriangle1);APPEND(inputTriangle[1]);APPEND(inputTriangle[1]);APPEND(extrusionTriangle1);APPEND(extrusionTriangle2);APPEND(inputTriangle[1]);APPEND(extrusionTriangle2);APPEND(inputTriangle[2]);APPEND(inputTriangle[2]);APPEND(extrusionTriangle2);APPEND(inputTriangle[0]);APPEND(extrusionTriangle2);APPEND(extrusionTriangle0);APPEND(inputTriangle[0]);  }    fixed4 frag(v2gf o) : SV_Target{return _OutlineColor;}fixed4 Null(v2gf o) : SV_Target{return float4(1.0, 0.0, 1.0, 1.0);}ENDCGSubShader{Tags{ "RenderType" = "Outline"}Pass{Tags { "LightMode" = "Always" }ColorMask 0//不输出颜色Cull OffZWrite Off//不进行深度写入。Stencil//模板测试总是通过,并且写入参考值1{Ref 1Comp alwaysPass replace}CGPROGRAM#pragma vertex vert#pragma fragment NullENDCG}Pass{Tags { "LightMode" = "Always" }Cull OffZWrite OnStencil//模板测试中参考值不等于1的像素将会通过,进行外轮廓描边。{Ref 1Comp notequalPass keepFail keep}CGPROGRAM#pragma vertex vert#pragma geometry geom#pragma fragment fragENDCG}}
}

3.效果




加了Bloom效果,看着就非常高大上了,这个Shader适用于你不想修改原模型的着色效果,又想加入一个描边效果的情况,但骨骼动画就要考虑在原Shader上处理,在本例中可以把第一个Pass改成渲染模型纹理,关键代码如下:

fixed4 Null(v2gf o) : SV_Target
{     return tex2D(_MainTex, o.uv);//return float4(1.0, 0.0, 1.0, 1.0);
}
Pass
{Tags { "LightMode" = "Always" }//ColorMask 0Cull BackStencil{Ref 1Comp alwaysPass replace}CGPROGRAM#pragma vertex vert#pragma fragment NullENDCG
}

或者传入骨骼动画后的模型数据进行同步,也是可以的。

[Unity]Shader利用Geometry处理实现描边效果相关推荐

  1. unity shader利用渲染纹理实现玻璃效果

    实现方法: 通过cubemap实现反射效果 通过GrabPass获取到渲染纹理,配合上法线纹理的偏移,实现玻璃的折射效果. 实现效果: 提前准备: 求得立方体所在位置的cubemap 代码: // U ...

  2. 着色器编程_unity中的基础纹理,使用Unity Shader实现基础纹理的渲染效果

    学习通过使用Unity Shader实现基础纹理的渲染效果 目录 学习通过使用Unity Shader实现基础纹理的渲染效果 问1:详细描述一下漫反射纹理.高度纹理.法线纹理.渐变纹理和遮罩纹理? 问 ...

  3. Unity使用Shader实现3D模型外描边效果ObjectOutline.shader

    一.前言 有同学问我3D模型的外描边怎么弄,其实网上有很多文章写了实现方式,我就再写个简单的实现和操作流程吧~ 二.3D模型外描边效果 三.如何制作 将最下面的shader代码保存为ObjectOut ...

  4. Unity使用Shader实现3D模型外描边效果

    文章目录 一.前言 二.3D模型外描边效果 三.如何制作 三.shader代码 一.前言 有同学问我3D模型的外描边怎么弄,其实网上有很多文章写了实现方式,我就再写个简单的实现和操作流程吧~ 二.3D ...

  5. Unity Shader学习笔记/Urp/水墨风效果

    实现简易的水墨风效果大致分为三部分: 1.将原始的rgb贴图转化为灰度图 float4 baseMap = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, IN ...

  6. Unity Shader - 类似七龙珠的人物气焰效果

    文章目录 环境 效果 思路 passes pass - 气焰 优化后的 shader Project 关于效果落地 环境 Unity : 2018.3.11f1 Pipeline : BRP 效果 覆 ...

  7. Unity Shader深度相关知识总结与效果实现

    鸣谢:puppet_master (VIA CSDN)贡献此文 前言 前言废话依旧比较多,感觉我是个写游戏体验评测的,233.最近想起了<恶灵附身>这款游戏的几个效果: <恶灵附身& ...

  8. Unity Shader学习案例一: 流光效果

    Unity Shader Lab新手宝典简单Shader案例一:流光效果 + 相关基础知识说明 Shader "Samples/Light Flow"//shader名称 {Pro ...

  9. Unity Shader 实现简单的压扁效果

    有点累啊,一个CoverMap搞了一周多,还是太嫩了,还有好多东西等着我去学呢,今天就写个简单的东西吧--一个把模型压扁的效果,参考博客Unity Shader - 一些玩具Shader.话不多说,先 ...

最新文章

  1. 关于asp.net Session丢失问题的总结
  2. HTML5 canvas drawImage() 方法记录
  3. 推荐升级版PDF在线转Word转换器
  4. Oracle数据库之集合运算
  5. 【CodeForces - 761C】Dasha and Password (暴力可过,标解dp,字符串,有坑总结)
  6. android开机动画多长时间_Android系统开机动画的一生
  7. 洛谷 P1141 01迷宫(dfs)
  8. php der格式 证书,php读取der格式证书乱码解决方法_PHP教程
  9. 记一次设置密钥登陆centos7所遇问题
  10. Unity采用Forge Networking Remastered数据的远程传输Basic Moving Cube Example
  11. 服务器2012导出日志文件,MDT2012,client部署日志存放在服务器上
  12. 存用部首查字典如何查_存的部首,存的偏旁部首,存的拼音,存的笔画数,存的组词,存的意思...
  13. 可用在404 的几句诗词
  14. 尚医通——后台搭建——MybatisPlus自动填充和乐观锁
  15. 浏览器端可以直接运行Python了
  16. ipad怎么压缩文件?教你一招快捷压缩图片
  17. objectArx --- 实体类AcDbEntity方法
  18. 文本CSS多行溢出隐藏显示省略号
  19. 因特网、万维网和互联网
  20. 工作生活可能用得到的资源

热门文章

  1. HTML5:爱奇艺首页图片轮播效果
  2. group by 与 order by的用法
  3. java路由架构_《大型分布式网站架构设计与实践》读书笔记之 服务的路由和负载均衡...
  4. ★【STL】报表统计
  5. 另类推柿子 Crypto Lights
  6. java科学型计算器代码_用JAVA编写的科学计算器源代码
  7. latex多行公式加大括号、整体编号及多行编号及不同方法的区别
  8. 电脑无线(外网)和有线(内网)网络同时使用方法
  9. 国外网站打开非常慢,什么鬼?
  10. GAGE USB信号采集卡