Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/unity3d/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jquery-ui/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unity3d 防止透明区域被投影着色器着色_Unity3d_Shader_Hlsl_Cg - Fatal编程技术网

Unity3d 防止透明区域被投影着色器着色

Unity3d 防止透明区域被投影着色器着色,unity3d,shader,hlsl,cg,Unity3d,Shader,Hlsl,Cg,我正在尝试制作一个贴花着色器,用于Unity中的投影仪。以下是我总结的内容: Shader "Custom/color_projector" { Properties { _Color ("Tint Color", Color) = (1,1,1,1) _MainTex ("Cookie", 2D) = "gray" {} } Subshader { Tags {"Queue"="Transparent"}

我正在尝试制作一个贴花着色器,用于Unity中的投影仪。以下是我总结的内容:

Shader "Custom/color_projector"
{
    Properties {
        _Color ("Tint Color", Color) = (1,1,1,1)
        _MainTex ("Cookie", 2D) = "gray" {}
    }
    Subshader {
        Tags {"Queue"="Transparent"}

        Pass {

            ZTest Less
            ColorMask RGB
            Blend One OneMinusSrcAlpha
            Offset -1, -1

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            struct v2f {
                float4 uvShadow : TEXCOORD0;
                float4 pos : SV_POSITION;
            };

            float4x4 unity_Projector;
            float4x4 unity_ProjectorClip;

            v2f vert (float4 vertex : POSITION)
            {
                v2f o;
                o.pos = UnityObjectToClipPos (vertex);
                o.uvShadow = mul (unity_Projector, vertex);
                return o;
            }

            sampler2D _MainTex;
            fixed4 _Color;

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 tex = tex2Dproj (_MainTex, UNITY_PROJ_COORD(i.uvShadow));
                return _Color * tex.a;

            }
            ENDCG
        }
    }
}
这在大多数情况下都很有效:

但是,每当它投影到透明曲面(或多个曲面)上时,似乎会为每个曲面渲染额外的时间。在这里,我使用带有透明区域的草纹理打破了草和铺路之间的界限:

我尝试了许多混合和选项,以及所有的ZTesting选项。这是我能看到的最好的了

从周围的阅读中,我收集到这可能是因为透明着色器不会写入深度缓冲区。我尝试添加
ZWrite On
,并尝试在主通行证之前进行通行证:

Pass {
   ZWrite On
   ColorMask 0
}
但两者都没有任何效果

如何修改该着色器,使其仅在最近的几何体上投影纹理一次

所需结果(photoshopped):


问题在于投影仪的工作方式。基本上,它们会第二次渲染其视野内的所有网格,除非使用不同的着色器。在您的例子中,这意味着地面和有草的平面都将渲染两次,并彼此层叠。我认为可以通过两个步骤来解决这个问题

首先,将以下内容添加到透明(草)着色器的标记中:

然后,将投影仪的渲染队列从“透明”更改为“透明+1”。这意味着首先渲染地面,然后渲染草边,最后投影仪将投影到地面上(除了显示在顶部,因为它是最后渲染的)

至于混合,我认为您需要常规alpha混合:

Blend SrcAlpha OneMinusSrcAlpha

如果使用延迟渲染,另一个选项是使用。这些都比投影仪便宜,而且通常更容易使用

非常好,谢谢。我将再次查看延迟贴花,尽管如此,我只是在Unity第一次发布它时快速查看了一下。
Blend SrcAlpha OneMinusSrcAlpha