Unity Shader 高亮重叠
Unity Shader highlighting overlaps
我正在尝试编写一个统一着色器,以突出显示重叠的网格片段。它应该适用于一个对象重叠自身以及多个对象。
结果应该类似于附加图片。
首先,我尝试通过碰撞检测来实现这一点,但我认为最好的方法是编写着色器。
我对着色器不是很熟悉,所以如果有人能帮助我,我将不胜感激。
我认为可以像这里一样使用模板着色器来完成 http://docs.unity3d.com/Manual/SL-Stencil.html
但是这个着色器只渲染两个对象的交集而不渲染整个对象。
我还找到了基于深度的着色器 (https://chrismflynn.wordpress.com/2012/09/06/fun-with-shaders-and-the-depth-buffer/),但这也适用于两个对象,不适用于一个自身重叠的网格
关于@Zze 关于两个通道的评论我现在有两个着色器。当一个有一个着色器而另一个有第二个着色器时,它适用于两个对象。
也许任何人都可以帮助我如何将它组合成一个着色器,该着色器也可以在自身重叠的对象中工作?
ShaderOne
Shader "Custom/ShaderOne"
{
SubShader {
Tags { "RenderType"="Opaque" "Queue"="Geometry"}
Pass {
Stencil {
Ref 2
Comp always
Pass keep
Fail decrWrap
ZFail keep
}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
struct appdata {
float4 vertex : POSITION;
};
struct v2f {
float4 pos : SV_POSITION;
};
v2f vert(appdata v) {
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
return o;
}
half4 frag(v2f i) : SV_Target {
return half4(0,1,0,1);
}
ENDCG
}
Pass {
Stencil {
Ref 2
Comp equal
}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
struct appdata {
float4 vertex : POSITION;
};
struct v2f {
float4 pos : SV_POSITION;
};
v2f vert(appdata v) {
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
return o;
}
half4 frag(v2f i) : SV_Target {
return half4(0,0,1,1);
}
ENDCG
}
}
}
ShaderTwo
Shader "Custom/ShaderTwo"
{
SubShader {
Tags { "RenderType"="Opaque" "Queue"="Geometry"}
Pass {
Stencil {
Ref 2
Comp always
Pass replace
ZFail keep
}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
struct appdata {
float4 vertex : POSITION;
};
struct v2f {
float4 pos : SV_POSITION;
};
v2f vert(appdata v) {
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
return o;
}
half4 frag(v2f i) : SV_Target {
return half4(1,0,0,1);
}
ENDCG
}
}
}
结果看起来像附加图片
这个问题可以借助 Stencil 缓冲区和一个、两个通道的着色器来解决。
思路如下:
- 第一遍将模板缓冲区中的值与 0 进行比较。在这两种情况下 (pass/fail) 增加缓冲区中的值。
- 第二遍将模板缓冲区中的值与 1 进行比较。如果参考值 1 小于 1,则我们通过并突出显示重叠像素。
您可能想要添加更多与第二个相同但具有不同参考值的通道,以突出显示重叠两次、三次等的区域。
在Unity的shaderlab符号中,应该是这样的:
Pass
{
Stencil {
Ref 0
Comp Equal
Pass IncrSat
Fail IncrSat
}
// Shader for not overlapping regions goes here.
}
Pass
{
Stencil {
Ref 1
Comp Less
}
// Shader for one-time overlapping regions goes here.
}
Pass
{
Stencil {
Ref 2
Comp Less
}
// Shader for two-time overlapping regions goes here.
}
示例:
着色器:
Shader "Unlit/Stencil"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
Stencil {
Ref 0
Comp Equal
Pass IncrSat
Fail IncrSat
}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
};
struct v2f
{
float4 vertex : SV_POSITION;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = fixed4(0.0, 0.0, 1.0, 1.0);
return col;
}
ENDCG
}
Pass
{
Stencil {
Ref 1
Comp Less
}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
};
struct v2f
{
float4 vertex : SV_POSITION;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = fixed4(1.0, 1.0, 0.0, 1.0);
return col;
}
ENDCG
}
Pass
{
Stencil {
Ref 2
Comp Less
}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
};
struct v2f
{
float4 vertex : SV_POSITION;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = fixed4(1.0, 0.0, 0.0, 1.0);
return col;
}
ENDCG
}
}
}
我正在尝试编写一个统一着色器,以突出显示重叠的网格片段。它应该适用于一个对象重叠自身以及多个对象。
结果应该类似于附加图片。
首先,我尝试通过碰撞检测来实现这一点,但我认为最好的方法是编写着色器。
我对着色器不是很熟悉,所以如果有人能帮助我,我将不胜感激。
我认为可以像这里一样使用模板着色器来完成 http://docs.unity3d.com/Manual/SL-Stencil.html 但是这个着色器只渲染两个对象的交集而不渲染整个对象。
我还找到了基于深度的着色器 (https://chrismflynn.wordpress.com/2012/09/06/fun-with-shaders-and-the-depth-buffer/),但这也适用于两个对象,不适用于一个自身重叠的网格
关于@Zze 关于两个通道的评论我现在有两个着色器。当一个有一个着色器而另一个有第二个着色器时,它适用于两个对象。
也许任何人都可以帮助我如何将它组合成一个着色器,该着色器也可以在自身重叠的对象中工作?
ShaderOne
Shader "Custom/ShaderOne"
{
SubShader {
Tags { "RenderType"="Opaque" "Queue"="Geometry"}
Pass {
Stencil {
Ref 2
Comp always
Pass keep
Fail decrWrap
ZFail keep
}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
struct appdata {
float4 vertex : POSITION;
};
struct v2f {
float4 pos : SV_POSITION;
};
v2f vert(appdata v) {
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
return o;
}
half4 frag(v2f i) : SV_Target {
return half4(0,1,0,1);
}
ENDCG
}
Pass {
Stencil {
Ref 2
Comp equal
}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
struct appdata {
float4 vertex : POSITION;
};
struct v2f {
float4 pos : SV_POSITION;
};
v2f vert(appdata v) {
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
return o;
}
half4 frag(v2f i) : SV_Target {
return half4(0,0,1,1);
}
ENDCG
}
}
}
ShaderTwo
Shader "Custom/ShaderTwo"
{
SubShader {
Tags { "RenderType"="Opaque" "Queue"="Geometry"}
Pass {
Stencil {
Ref 2
Comp always
Pass replace
ZFail keep
}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
struct appdata {
float4 vertex : POSITION;
};
struct v2f {
float4 pos : SV_POSITION;
};
v2f vert(appdata v) {
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
return o;
}
half4 frag(v2f i) : SV_Target {
return half4(1,0,0,1);
}
ENDCG
}
}
}
结果看起来像附加图片
这个问题可以借助 Stencil 缓冲区和一个、两个通道的着色器来解决。 思路如下:
- 第一遍将模板缓冲区中的值与 0 进行比较。在这两种情况下 (pass/fail) 增加缓冲区中的值。
- 第二遍将模板缓冲区中的值与 1 进行比较。如果参考值 1 小于 1,则我们通过并突出显示重叠像素。
您可能想要添加更多与第二个相同但具有不同参考值的通道,以突出显示重叠两次、三次等的区域。
在Unity的shaderlab符号中,应该是这样的:
Pass
{
Stencil {
Ref 0
Comp Equal
Pass IncrSat
Fail IncrSat
}
// Shader for not overlapping regions goes here.
}
Pass
{
Stencil {
Ref 1
Comp Less
}
// Shader for one-time overlapping regions goes here.
}
Pass
{
Stencil {
Ref 2
Comp Less
}
// Shader for two-time overlapping regions goes here.
}
示例:
着色器:
Shader "Unlit/Stencil"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
Stencil {
Ref 0
Comp Equal
Pass IncrSat
Fail IncrSat
}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
};
struct v2f
{
float4 vertex : SV_POSITION;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = fixed4(0.0, 0.0, 1.0, 1.0);
return col;
}
ENDCG
}
Pass
{
Stencil {
Ref 1
Comp Less
}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
};
struct v2f
{
float4 vertex : SV_POSITION;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = fixed4(1.0, 1.0, 0.0, 1.0);
return col;
}
ENDCG
}
Pass
{
Stencil {
Ref 2
Comp Less
}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
};
struct v2f
{
float4 vertex : SV_POSITION;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = fixed4(1.0, 0.0, 0.0, 1.0);
return col;
}
ENDCG
}
}
}