unity 自定义天空球模型防止被裁剪

在unity中,有时候不想使用内置的天空球去渲染,那么,我们就会使用一个球体去渲染天空球。为了保证游戏场景模型都放置在天空球内。球体就会放大的很大,那么问题就来了,这样会导致球体超出了相机的可视范围,导致天空球无法渲染,调整相机的裁减远面,会影响性能,还影响渲染效果。
这里有个解决方案,就是我们可以在材质里面去修改球体的顶点着色器输出的裁减坐标,将它的值限制在-w到w的范围内,来解决无法被渲染的问题。
UNITY_REVERSED_Z 这个属性则是为了判断是否翻转z 深度,像D3D平台,Metal平台,远裁剪面都是接近于0,他们都设置了UNITY_REVERSED_Z 值为1
而Opengl平台则 远裁剪面的值为w,但是没有设置UNITY_REVERSED_Z 的值。
所以,我们可以通过宏进行一下判断,如果UNITY_REVERSED_Z 有值positionCS.w * 0.0001f,
如果UNITY_REVERSED_Z 没有值,我们设置一下positionCS.w * 0.9999f,让模型裁剪空间位置无限接近于远裁剪面,就实现了当前的这个功能。

这是一个基于unlit修改的防止被裁剪的天空球shader

Shader "Unlit/SkyBox"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" { }
    }
    SubShader
    {
        Tags { "RenderType" = "Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM

            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            v2f vert(appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                //将输出位置的z坐标限制在-1到1的范围内,这样可以防止自定义的天空球被裁剪掉
                #if UNITY_REVERSED_Z //这个宏是用来判断平台的,有个平台最远裁剪值是w,有的是-w
                    o.vertex.z = o.vertex.w * 0.000001f;
                #else
                    o.vertex.z = o.vertex.w * 0.999999f;
                #endif
                return o;
            }

            half4 frag(v2f i) : SV_Target
            {
                // sample the texture
                half4 col = tex2D(_MainTex, i.uv);
                return col;
            }
            ENDCG

        }
    }
}

个人发现,在urp管线里面,精度没有那么高,需要这样写:

Shader "Unlit/SkyBox"
{
    Properties
    {
        _BaseMap ("Texture", 2D) = "white" { }
        _BaseColor ("Color", Color) = (1, 1, 1, 1)
    }
    SubShader
    {
        Tags { "RenderType" = "Background" "IgnoreProjector" = "True" "RenderPipeline" = "UniversalPipeline" "ShaderModel" = "4.5" }
        LOD 100

        ZWrite On

        Pass
        {
            HLSLPROGRAM

            #pragma vertex vert
            #pragma fragment frag

            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/SurfaceInput.hlsl"
			#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
            

            CBUFFER_START(UnityPerMaterial)
            float4 _BaseMap_ST;
            float4 _BaseMap_HDR;
            half4 _BaseColor;
            CBUFFER_END

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 positionCS : SV_POSITION;
            };

            v2f vert(appdata v)
            {
                v2f o;
                o.positionCS = TransformObjectToHClip(v.vertex.xyz);
                o.uv = TRANSFORM_TEX(v.uv, _BaseMap);
                #if UNITY_REVERSED_Z //这个宏是用来判断平台的,有个平台最远裁剪值是1,有的是-1
                    o.positionCS.z = o.positionCS.w * 0.0001f;
                #else
                    o.positionCS.z = o.positionCS.w * 0.9999f;
                #endif  
                return o;
            }

            half4 frag(v2f i) : SV_Target
            {
                half4 col = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, i.uv);
                col.rgb = DecodeHDREnvironment(col, _BaseMap_HDR) * _BaseColor.rgb;
                return col;
            }
            ENDHLSL

        }
    }
}

降低一下精度

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值