【问题标题】:Prevent ColorMask obscuring parts of an object's mesh防止 ColorMask 遮挡对象网格的某些部分
【发布时间】:2018-07-19 12:05:51
【问题描述】:

我正在尝试使用着色器来防止对象在离开特定区域时被渲染。但是,当使用表面着色器执行此操作时,要解决绘图问题,我必须使用深度缓冲区。目前我正在这样做

Pass {
    ColorMask 0
}

但是,这会导致不渲染颜色蒙版的绘制部分后面的网格部分的效果。

为了解决这个问题,我试图只完成传递但丢弃片段,但这会导致面部以错误的顺序呈现。这可能是由于下面的着色器脚本中的Cull Off 造成的,但这不是我的程序处理内部渲染的正常方式,它只是在没有大量代码的情况下提供合理结果的快速方法。 Cull BackCull Off 也会发生这种情况。

我怎样才能做到这一点,以便ColorMask 0 不会掩盖其背后的内容,或者在丢弃所有片段时可以使用什么 CG 程序来防止人脸渲染顺序错误的问题?

着色器代码 - Lit.shader

Shader "Culling/Lit" {
    Properties {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0

        //Properties normally assigned by script but can be done manually
        _SHOWCULL("Show Cull", Int) = 0

        _RADIUS("Radius", Float) = 0

        _STARTX("Start X", Float) = 0
        _STARTY("Start Y", Float) = 0
        _STARTZ("Start Z", Float) = 0

        _CENTREX("Centre X", Float) = 0
        _CENTREY("Centre Y", Float) = 0
        _CENTREZ("Centre Z", Float) = 0

        _ENDX("End X", Float) = 0
        _ENDY("End Y", Float) = 0
        _ENDZ("End Z", Float) = 0

        _MODE("Mode", Int) = 0
    }
    SubShader {
        Tags{ "Queue" = "Transparent" "RenderType" = "Transparent" "IgnoreProjector" = "True" }
        LOD 200
        Blend SrcAlpha OneMinusSrcAlpha
        ZWrite On

        Pass {
            //Renders faces in wrong order
            /*CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag

                fixed4 _Color;

                struct appdata {
                    float4 vertex : POSITION;
                };

                struct v2f {
                    float4 vertex : POSITION;
                };

                v2f vert (appdata v) {
                    v2f o;
                    o.vertex = UnityObjectToClipPos(v.vertex);
                    return o;
                }

                fixed4 frag (v2f i) : COLOR {
                    discard;
                    return _Color;
                }
            ENDCG*/
            ColorMask 0
        }

        Cull Off //Not normally used as provides incorrect light but way to fix is not needed for this and it is here to show example inside

        CGPROGRAM
        #pragma surface surf Standard fullforwardshadows alpha
        #pragma target 3.0

        sampler2D _MainTex;

        struct Input {
            float2 uv_MainTex;
            float3 worldPos;
        };

        half _Glossiness;
        half _Metallic;
        fixed4 _Color;

        UNITY_INSTANCING_CBUFFER_START(Props)
        UNITY_INSTANCING_CBUFFER_END

        int _SHOWCULL;

        float _RADIUS;

        float _STARTX;
        float _STARTY;
        float _STARTZ;

        float _CENTREX;
        float _CENTREY;
        float _CENTREZ;

        float _ENDX;
        float _ENDY;
        float _ENDZ;

        int _MODE;

        void surf (Input IN, inout SurfaceOutputStandard o) {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
            o.Albedo = c.rgb;
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Alpha = c.a;

            if (_MODE == 0) {
                //For Cylinder
                if (sqrt(((IN.worldPos.x - _CENTREX) * (IN.worldPos.x - _CENTREX)) +
                    ((IN.worldPos.z - _CENTREZ) * (IN.worldPos.z - _CENTREZ))) < _RADIUS
                    && IN.worldPos.y > _STARTY && IN.worldPos.y < _ENDY) {
                }
                else
                {
                    discard; //ignores that pixel - doesnt render it
                }
            }
            else if (_MODE == 1) {
                //For Sphere
                if (sqrt(((IN.worldPos.x - _CENTREX) * (IN.worldPos.x - _CENTREX)) +
                    ((IN.worldPos.y - _CENTREY) * (IN.worldPos.y - _CENTREY)) +
                    ((IN.worldPos.z - _CENTREZ) * (IN.worldPos.z - _CENTREZ))) < _RADIUS) {
                }
                else
                {
                    discard; //ignores that pixel - doesnt render it
                }
            }
            else if (_MODE == 2) {
                // For Cuboid
                if (IN.worldPos.x > _STARTX && IN.worldPos.x < _ENDX
                    && IN.worldPos.y > _STARTY && IN.worldPos.y < _ENDY
                    && IN.worldPos.z > _STARTZ && IN.worldPos.z < _ENDZ) {
                }
                else
                {
                    discard; //ignores that pixel - doesnt render it
                }
            }
        }

        ENDCG
    }
    FallBack "Diffuse"
}

【问题讨论】:

    标签: unity3d shader fragment-shader vertex cg


    【解决方案1】:

    这可以通过使用与网格相同的数学来裁剪ColorMask 来解决。这样,深度缓冲区仍然存在,因此面部以正确的顺序绘制,并且不会遮挡任何东西。

    ...
    Pass {
        ColorMask 0
    
        CGPROGRAM
        #pragma vertex vert
        #pragma fragment frag
    
        #include "UnityCG.cginc"
    
        float _RADIUS;
    
        float _STARTX;
        float _STARTY;
        float _STARTZ;
    
        float _CENTREX;
        float _CENTREY;
        float _CENTREZ;
    
        float _ENDX;
        float _ENDY;
        float _ENDZ;
    
        float _MODE;
    
        sampler2D _MainTex;
        fixed4 _Color;
        // vertex shader inputs
        struct appdata
        {
            float4 vertex : POSITION; // vertex position
            float2 uv : TEXCOORD0; // texture coordinate
        };
    
        // vertex shader outputs ("vertex to fragment")
        struct v2f
        {
            float2 uv : TEXCOORD0; // texture coordinate
            float4 vertex : SV_POSITION; // clip space position
            float4 position_in_world_space : TEXCOORD1; //same as uv
        };
    
        float4 _MainTex_ST;
    
        // vertex shader
        v2f vert (appdata v)
        {
            v2f o;
            o.vertex = UnityObjectToClipPos(v.vertex);
            o.position_in_world_space = mul(unity_ObjectToWorld, v.vertex);
            o.uv = TRANSFORM_TEX(v.uv, _MainTex);
            return o;
        }
    
        fixed4 frag (v2f i) : SV_Target
        {
            fixed4 col = tex2D(_MainTex, i.uv) * _Color;
    
            if (_MODE == 0) {
                //For Cylinder
                if (sqrt(((i.position_in_world_space.x - _CENTREX) * (i.position_in_world_space.x - _CENTREX)) + 
                    ((i.position_in_world_space.z - _CENTREZ) * (i.position_in_world_space.z - _CENTREZ))) < _RADIUS
                    && i.position_in_world_space.y > _STARTY && i.position_in_world_space.y < _ENDY) {}
                else
                {
                    discard; //ignores that pixel - doesnt render it
                }
            }
            else if (_MODE == 1){
                 //For Sphere
                if (sqrt(((i.position_in_world_space.x - _CENTREX) * (i.position_in_world_space.x - _CENTREX)) + 
                    ((i.position_in_world_space.y - _CENTREY) * (i.position_in_world_space.y - _CENTREY)) +
                    ((i.position_in_world_space.z - _CENTREZ) * (i.position_in_world_space.z - _CENTREZ))) < _RADIUS) {}
                else
                {
                    discard; //ignores that pixel - doesnt render it
                }
            }
            else if (_MODE == 2){
                // For Cuboid
                if (i.position_in_world_space.x > _STARTX && i.position_in_world_space.x < _ENDX
                    && i.position_in_world_space.y > _STARTY && i.position_in_world_space.y < _ENDY
                    && i.position_in_world_space.z > _STARTZ && i.position_in_world_space.z < _ENDZ) {}
                else 
                {
                    discard; //ignores that pixel - doesnt render it
                }
            }
    
            return col;
        }
        ENDCG
    }
    ...
    

    【讨论】:

      猜你喜欢
      • 2023-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-15
      • 2017-02-27
      • 2014-02-13
      相关资源
      最近更新 更多