Unity Shader模板测试描边效果,常用于 rpg 项目中主角被遮挡的情况,将被遮挡的部分的轮廓描边绘制出来,这样可以在任何情况都能知道主角在哪里。(还有另外一种就是使用X光效果,但这种效果不需要用到模板测试,所以这里用 描边效果 举例子)

 
效果如下:
 
思路
 
实现这种效果需要两个pass
1、正常绘制,即深度测试 LEqual,正常遮挡,同时往 模板缓冲区 写入一个 参考值 Ref=1(即使深度测试失败的值也要写入,保证 角色所有像素在模板缓冲区的值 都是 参考值 Ref=1)
 
2、只绘制被遮挡部分的描边
  • 先把模型的 顶点 往 法线方向 偏移一个值(这个就是描边的宽度值,可以理解为将模型放大了),可以在观察空间 或者 世界空间、模型空间 偏移,只要和 法线 在同一空间下。
  • 对比 模板缓冲区 的参考值 Ref=1,因为第一个 pass 写入的参考值是 1,所以这个pass中就要不等1才让它通过,这样就能得到一个 差值区域,即描边的区域。
  • 深度测试,让被遮挡部分才让它通过,即 ZTest Greater,done!
 
shader代码:
Shader "Custom/Unlit-Texture-Outline" {
Properties{
_MainTex("Base (RGB)", 2D) = "white" {}
_OutlineColor("Outline Color", Color) = (1,1,0,1) //描边颜色
_Outline("Outline width", Range(0.0, 0.5)) = 0.03 // 描边宽度

CGINCLUDE
#include "UnityCG.cginc"
struct appdata_t {
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
float3 normal : NORMAL;
};
struct v2f {
float4 vertex : SV_POSITION;
half2 texcoord : TEXCOORD0;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float _Outline;
float4 _OutlineColor;
v2f vert(appdata_t v)

v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
return o;

v2f vert_outline(appdata_t v)

v2f o;
// 方式一,观察空间 下往法线偏移顶点
float4 viewPos = mul(UNITY_MATRIX_MV, v.vertex);
//float3 viewNorm = mul((float3x3)UNITY_MATRIX_IT_MV, v.normal);
float3 viewNorm = mul(v.normal, (float3x3)UNITY_MATRIX_T_MV);
float3 offset = normalize(viewNorm) * _Outline;
viewPos.xyz += offset;
o.vertex = mul(UNITY_MATRIX_P, viewPos);
//方式二,世界空间 下往法线偏移顶点
//float4 worldPos = mul(unity_ObjectToWorld, v.vertex);
//float3 worldNormal = UnityObjectToWorldNormal(v.normal);
//float3 offset = normalize(worldNormal) * _Outline;
//worldPos.xyz += offset;
//o.vertex = mul(UNITY_MATRIX_VP, worldPos);
return o;

ENDCG
SubShader{
Tags{ "Queue" = "Transparent" "RenderType" = "Opaque" }
Pass{ // 正常绘制
Stencil

Ref 1
Comp Always
Pass Replace
ZFail Replace

ZTest LEqual
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
fixed4 frag(v2f i) : SV_Target

fixed4 col = tex2D(_MainTex, i.texcoord);
return col;

ENDCG

Pass{ // 遮挡部分绘制描边
ZTest Greater
ZWrite Off
//Blend DstAlpha OneMinusDstAlpha
Stencil{
Ref 1
Comp NotEqual

CGPROGRAM
#pragma vertex vert_outline
#pragma fragment frag
half4 frag(v2f i) :COLOR

return _OutlineColor;

ENDCG


 
使用 剔除Cull 的方式 描边
 
这种方式的描边不适合做遮挡部分描边,且不遮挡部分的效果也没有 模板测试 那种方式好,他的原理也是使用两个pass,一个pass正常渲染,剔除背面 (Cull Back),另外一个pass 也需要顶点外拉,然后 剔除正面(Cull Front),偏移深度。这种方式会在人体内也有描边,不像 模板测试 那种方式在人体完全没有描边。
 
效果
 
shader代码
// 这种方式的描边不适合做遮挡部分描边,且不遮挡部分的效果也没有 模板测试 那种方式好
Shader "ITS/test/testOutline_cull" {
Properties{
_MainTex("Base (RGB)", 2D) = "white" {}
_OutlineColor("Outline Color", Color) = (1,1,0,1)
_Outline("Outline width", Range(0.0, 0.5)) = 0.03

CGINCLUDE
#include "UnityCG.cginc"
struct appdata_t {
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
float3 normal : NORMAL;
};
struct v2f {
float4 vertex : SV_POSITION;
half2 texcoord : TEXCOORD0;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float _Outline;
float4 _OutlineColor;
v2f vert(appdata_t v)

v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
return o;

v2f vert_outline(appdata_t v)

v2f o;
// 方式一,观察空间 下往法线偏移顶点
float4 viewPos = mul(UNITY_MATRIX_MV, v.vertex);
//float3 viewNorm = mul((float3x3)UNITY_MATRIX_IT_MV, v.normal);
float3 viewNorm = mul(v.normal, (float3x3)UNITY_MATRIX_T_MV);
float3 offset = normalize(viewNorm) * _Outline;
viewPos.xyz += offset;
o.vertex = mul(UNITY_MATRIX_P, viewPos);
//方式二,世界空间 下往法线偏移顶点
//float4 worldPos = mul(unity_ObjectToWorld, v.vertex);
//float3 worldNormal = UnityObjectToWorldNormal(v.normal);
//float3 offset = normalize(worldNormal) * _Outline;
//worldPos.xyz += offset;
//o.vertex = mul(UNITY_MATRIX_VP, worldPos);
return o;

ENDCG
SubShader{
Tags{ "Queue" = "Transparent" "RenderType" = "Opaque" }
Pass{
ZTest LEqual
Cull Back
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
fixed4 frag(v2f i) : SV_Target

fixed4 col = tex2D(_MainTex, i.texcoord);
return col;

ENDCG

Pass{
// ZTest Greater
ZWrite Off
Cull Front
Offset 100,0
CGPROGRAM
#pragma vertex vert_outline
#pragma fragment frag
half4 frag(v2f i) : COLOR

return _OutlineColor;

ENDCG


 
ps: 还有其他描边处理的方式,比如 后处理
来自:https://blog.csdn.net/yangxuan0261/article/details/79686192

Unity Shader模板测试-描边的更多相关文章

  1. Unity Shader入门精要读书笔记(二)UnityShader概述

    第三章<UnityShader概述>的读书笔记: 1.Unity Shader模板提供了几种选择: 标准光照模型(新添加的基于物理的渲染方法) 不含光照的基本的顶点.片元着色器 屏幕后处理 ...

  2. Unity Shader概述

    一.概述 在Unity中需要配合使用材质和Unity Shader才能达到需要的效果.常见的流程:(1)创建一个材质:(2)创建一个Unity Shader,并把它赋给创建的材质:(3)把材质赋给要渲 ...

  3. Unity Shader之模板测试

    Unity Shader之模板测试 一沙一世界,一花一天堂 一.Stencil testing 渲染管线     当片段着色器处理完一个片段之后,模板测试(Stencil Test)会开始执行,和深度 ...

  4. Unity Shader实现描边效果

    http://gad.qq.com/article/detail/28346 描边效果是游戏里面非常常用的一种效果,一般是为了凸显游戏中的某个对象,会给对象增加一个描边效果.本篇文章和大家介绍下利用S ...

  5. Shader 模板缓冲和模板测试

    http://blog.sina.com.cn/s/blog_6e159df70102xa67.html 模板缓冲的概念 Unity官方的Shader文档根本没有提到这个玩意,这个概念也是看到了UGU ...

  6. 关于Unity中的模型描边与Shader切换(专题二)

    模型描边 1: LOL里面的模型描边效果,点击防御塔会有描边的效果,被攻击的时候模型也要描边凸显一下2: 网上可以找到模型描边的Shader,可以直接下载使用,一组第三方的Shader, 帮我们解决了 ...

  7. Unity Shader 卡通渲染 基于退化四边形的实时描边

    从csdn转移过来,顺便把写过的文章改写一下转过来. 一.边缘检测算法 3D模型描边有两种方式,一种是基于图像,即在所有3D模型渲染完成一张图片后,对这张图片进行边缘检测,最后得出描边效果.一种是基于 ...

  8. Unity Shader 知识点总结(一)

    在学习了一段时间的Unity Shader后,打算写一些知识总结,便于今后的查找.如有错误,希望大家指出更改. 本文参照的unity入门精要一书,做一个知识归纳,如有兴趣可以看看其开源的部分,是一本比 ...

  9. 【转】《Unity Shader入门精要》冯乐乐著 书中彩图

    为方便个人手机学习时候查阅,从网上转来这些彩图. 如属过当行为,联系本人删除. 勘错表 http://candycat1992.github.io/unity_shaders_book/unity_s ...

  10. Unity Shader入门精要读书笔记(一)序章

    本系列的博文是笔者读<Unity Shader入门精要>的读书笔记,这本书的章节框架是: 第一章:着手准备. 第二章:GPU流水线. 第三章:Shader基本语法. 第四章:Shader数 ...

随机推荐

  1. 学Shiro完结版-2

    第四章 INI配置--<跟我学Shiro> 之前章节我们已经接触过一些INI配置规则了,如果大家使用过如Spring之类的IoC/DI容器的话,Shiro提供的INI配置也是非常类似的,即 ...

  2. 利用JavaScript自定义事件完成组件间的数据通信

    我们知道,在JavaScript中,原生DOM事件在开发中是很有用的(与用户交互的重要方式),但是操作原生DOM事件其实有两大缺点:性能低.依赖于浏览器(NodeJs.小程序等不可用).那么这个时候, ...

  3. centos7关闭不必要的服务和端口

    云服务器开启很多不必要的端口,造成安全隐患 TCP 25端口:邮件服务 systemctl stop postfix 53端口 :域名解析服务 systemctl stop rhel-domainna ...

  4. 支付宝 v3 自签名如何实现

    今天在看文档的时候,发现支付宝新出了一个 v3 版本的接口调用方式,感觉有点意思,花了点时间研究了下这个版本要怎么实现自签名,大家有兴趣可以看看. 什么是支付宝 API v3 版本? 官网上给的解释是 ...

  5. 深度学习:测试是否含有gpu的环境

    在我们跑深度学习的时候,绕不开的一定是gpu显卡,但是如何检测是否使用gpu那?下面我讲提供一段代码,可以检测自己是否开启了gpu或含有gpu. import torch # 检查是否支持 CUDA( ...

  6. mysql中,让自动增长字段值复位/重新计数

    在使用mysql时,常常要设置一个id值,并设置为自动增长 如果想要复位重新计数的话,那么应该使用以下语句 ALTER TABLE `表名` AUTO_INCREMENT = 1; 但需要注意的是,除 ...

  7. Java8 stream sorted排序时包括null

    开发过程中对象集合根据某个属性排序是常常遇到的情况,但有时排序会遇到对应属性值为null的情况,会报空指针异常. 查找stream.sorted源码看到有Comparator.nullsFirst和C ...

  8. 收集 Spring Boot 相关的学习资料

    收集 Spring Boot 相关的学习资料,Spring Cloud点这里 重点推荐:Spring Boot 中文索引 推荐博客 纯洁的微笑-Spring Boot系列文章 林祥纤-从零开始学Spr ...

  9. 图片的 rgb信息 byte[] 直接转换为bmp文件

    方法1: /// <summary> /// rgb像素值转换为bmp文件 /// </summary> /// <param name="buffer&quo ...

  10. C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)

    前言 自从 DeepSeek 大模型火了以来,网络上出现了许多关于本地部署的教程和方法.然而,要真正深入了解其功能和应用,还是需要自己动手进行一次本地部署. DeepSeek 作为一个高效的自然语言处 ...