Shader "Custom/Selected Object" {
Properties {
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Emission ("EmissionColor", Color) = (0.5, 0.5, 0.5, 1)
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
_Mode ("Blend Mode", Range(0,3)) = 0
_ZWrite ("ZWrite", Int) = 0
_SrcBlend ("SrcBlend", Int) = 0
_DstBlend ("DstBlend", Int) = 0
_Cutoff ("Alpha Cutoff", Float) = 0.05
}
SubShader{
//Behind other geometry
Pass
{
ZTest GEqual
ZWrite [_ZWrite]
Blend [_SrcBlend] [_DstBlend]
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float2 uv : TEXCOORD0;
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f
{
float4 pos : SV_POSITION;
float3 viewDir : TEXCOORD1;
float3 normal : NORMAL;
float2 uv : TEXCOORD0;
};
v2f vert(appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.normal = UnityObjectToWorldNormal(v.normal);
o.viewDir = normalize(UnityWorldSpaceViewDir(o.pos));
o.uv = v.uv;
return o;
}
sampler2D _MainTex;
fixed4 frag(v2f i) : SV_Target
{
//Note you have to normalize these again since they are being interpolated between vertices
float rim = 1 - dot(normalize(i.normal), normalize(i.viewDir));
fixed4 rimLight = lerp(half4(.95, .95, .95, 1), half4(0.65, 0.65, .95, 1), rim);
fixed4 t = tex2D(_MainTex, i.uv);
clip(t.a < 0.2);
return t * rimLight;
}
ENDCG
}
ZTest Less
ZWrite On
Blend [_SrcBlend][_DstBlend]
//Front geometry
CGPROGRAM
// Physically based Standard lighting model, and enable shadows on all light types
// And generate the shadow pass with instancing support
#pragma surface surf Standard fullforwardshadows addshadow alphatest:_Cutoff //alpha:blend //keepalpha
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0
#pragma multi_compile __ EMISSIVE_ON
sampler2D _MainTex;
fixed4 _Emission;
fixed4 _Color;
//float _Mode;
struct Input {
float2 uv_MainTex;
};
half _Glossiness;
half _Metallic;
void surf(Input IN, inout SurfaceOutputStandard o) {
// Albedo comes from a texture tinted by color
fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
#if EMISSIVE_ON //Glowing
o.Emission = _Emission;
#endif
// Metallic and smoothness come from slider variables
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Instanced/InstancedSurfaceShader"
}
此着色器应用于用户选择的对象。它添加了一个 channel 来绘制可能被遮挡的对象部分,如 X 射线效果。该着色器在运行时进行交换,如果起始着色器是 Unity 标准着色器,则该着色器将正常工作。
问题:我正在制作一个着色器来代替标准着色器,以启用 GPU 实例化。从实例化着色器进行交换时,只有在对象完全通过其遮挡物后才会绘制效果。
除非对象完全超过遮挡对象,否则 ZTest GEqual
似乎会失败。在上面的图像中,在第二个图像中看到的效果也应该在第一个图像中看到,其中对象被遮挡。
事实上,它与标准着色器配合得很好,这让我相信这个问题是我在实例着色器中遗漏的,在这里:
Shader "Custom/Instanced/InstancedSurfaceShader - Glow" {
Properties {
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Emission ("EmissionColor", Color) = (1, 1, 1, 1)
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
_Mode ("Blend Mode", Range(0,3)) = 0
_Cutoff("Alpha Cutoff", Float) = 0.05
}
SubShader {
ZTest Less
ZWrite On
CGPROGRAM
// Physically based Standard lighting model, and enable shadows on all light types
// And generate the shadow pass with instancing support
#pragma surface surf Standard fullforwardshadows addshadow alphatest:_Cutoff
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0
// Enable instancing for this shader
#pragma multi_compile_instancing
// Config maxcount. See manual page.
// #pragma instancing_options
sampler2D _MainTex;
struct Input {
float2 uv_MainTex;
};
fixed4 _Emission;
half _Glossiness;
half _Metallic;
// Declare instanced properties inside a cbuffer.
// Each instanced property is an array of by default 500(D3D)/128(GL) elements. Since D3D and GL imposes a certain limitation
// of 64KB and 16KB respectively on the size of a cubffer, the default array size thus allows two matrix arrays in one cbuffer.
// Use maxcount option on #pragma instancing_options directive to specify array size other than default (divided by 4 when used
// for GL).
// https://docs.unity3d.com/Manual/GPUInstancing.html
UNITY_INSTANCING_BUFFER_START(Props)
UNITY_DEFINE_INSTANCED_PROP(fixed4, _Color) // Make _Color an instanced property (i.e. an array)
#define _Color_arr Props
UNITY_INSTANCING_BUFFER_END(Props)
void surf (Input IN, inout SurfaceOutputStandard o) {
// Albedo comes from a texture tinted by color
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * UNITY_ACCESS_INSTANCED_PROP(_Color_arr, _Color);
o.Albedo = c.rgb;
o.Emission = _Emission;
// Metallic and smoothness come from slider variables
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Instanced/InstancedSurfaceShader"
}
这是在着色器切换时直接影响 Material /着色器的代码片段:
material.SetOverrideTag("RenderType", "");
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
material.SetInt("_ZWrite", 1);
material.DisableKeyword("_ALPHATEST_ON");
material.DisableKeyword("_ALPHABLEND_ON");
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = -1;
实例化着色器中的哪些因素可能导致 X 射线着色器的效果不同?
最佳答案
在回答这里的实际问题之前,我需要指出这一点:
If you have more than two passes for multi-pass Shaders, only the first passes can be instanced. This is because Unity forces the later passes to be rendered together for each object, forcing Material changes.
https://docs.unity3d.com/Manual/GPUInstancing.html
因此,从本质上讲,在您当前使用 Pass 实现的情况下,无论如何您都将无法使用 GPU 实例。
现在,您的着色器的问题是您的所有 channel 都是不透明的,因此无法保证网格的绘制顺序。如果遮挡物在被遮挡物之后渲染,则 Zbuffer 中不会有任何信息可供测试。解决方案只是增加 Material 的渲染顺序,因为它会在所有其他不透明(ZWrite On)像素之后绘制。
关于unity-game-engine - Shader ZTest 未按预期运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50749891/