图片产生深度效果的6种方式

一、2D全景图采样

这个 Shader 的核心是将输入的 HDR 环境图像通过反射方向进行采样,并且允许对反射方向进行旋转和调整 MIP 级别。

PS:这里可以将2D图改成CubeMap方式去采样;

Shader "Custom/HDRToCubemapRotateAndMip"
{
    Properties
    {
        _MainTex ("HDR Texture", 2D) = "white" {} // 输入HDR单图
        _ReflectColor ("Reflection Color", Color) = (1, 1, 1, 1) // 反射颜色
        _RotationAngle ("Rotation Angle", Range(0, 360)) = 0 // 旋转角度
        _MipLevel ("Mip Level", Range(0, 10)) = 0 // MIP级别
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

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

            struct appdata
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
            };

            struct v2f
            {
                float3 worldPos : TEXCOORD0;
                float3 normal : TEXCOORD1;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _ReflectColor;
            float _RotationAngle;
            float _MipLevel; // 新增 MIP 控制参数

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
                o.normal = mul((float3x3)unity_ObjectToWorld, v.normal);
                return o;
            }

            // 从方向向量计算Cubemap UV
            float2 DirectionToCubemapUV(float3 dir)
            {
                float u = atan2(dir.z, dir.x) / (2.0 * UNITY_PI) + 0.5;
                float v = asin(dir.y) / UNITY_PI + 0.5;
                return float2(u, v);
            }

            float4 frag (v2f i) : SV_Target
            {
                // 计算视图方向
                float3 viewDir = normalize(i.worldPos - _WorldSpaceCameraPos);
                float3 reflectDir = reflect(viewDir, normalize(i.normal));

                // 将旋转角度从度数转换为弧度
                float radians = _RotationAngle * UNITY_PI / 180.0;

                // 计算旋转矩阵
                float3x3 rotationMatrix = float3x3(
                    cos(radians), 0, sin(radians),
                    0, 1, 0,
                    -sin(radians), 0, cos(radians)
                );

                // 应用旋转矩阵到反射方向
                reflectDir = mul(rotationMatrix, reflectDir);

                // 将反射方向转换为UV坐标
                float2 uv = DirectionToCubemapUV(reflectDir);

                // 使用 LOD 采样纹理,指定 MIP 级别
                float4 hdrColor = tex2Dlod(_MainTex, float4(uv, 0, _MipLevel));

                // 结合反射颜色
                return hdrColor * _ReflectColor;
            }
            ENDCG
        }
    }
}

第二种、2D图轴向挤压

基于盒体投影技术来计算物体反射的逻辑。它通过计算射线与盒子在 3D 空间中的相交点,并基于这个相交点从纹理中采样颜色,沿视线方向挤压。

PS:里面有Cube图的采样方式,可以用作替代;

Shader "Unlit/BoxProjection"
{
    Properties
    {
        // _Cube ("Reflection Cubemap", Cube) = "_Skybox" {}
        _MainTex("_MainTex",2D) = "white"{}
        _EnvBoxStart ("Env Box Start", Vector) = (0, 0, 0)
        _EnvBoxSize ("Env Box Size", Vector) = (1, 1, 1,1)
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            
            #include "UnityCG.cginc"
            
            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };
            
            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                float3 viewDir:TEXCOORD1;
                float3 objectPos:TEXCOORD2;
            };

            sampler2D _MainTex;
            samplerCUBE _Cube;
            float4 _Cube_ST;
            float4 _EnvBoxStart;
            float4 _EnvBoxSize;
            
            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                float3 worldPos=mul(unity_ObjectToWorld,v.vertex).xyz;
                float3 worldViewDir=UnityWorldSpaceViewDir(worldPos);
                o.viewDir=-mul(unity_WorldToObject,float4(worldViewDir,0));
                o.objectPos=v.vertex.xyz;
                return o;
            }
            
            fixed4 frag (v2f i) : SV_Target
            {
                float3 viewDir=i.viewDir;
                float3 objectPos=i.objectPos+half3(0.5,0.5,0);

                float3 rbmax=(_EnvBoxStart+_EnvBoxSize-objectPos)/viewDir;
                float3 rbmin=(_EnvBoxStart-objectPos)/viewDir;

                float3 t2=max(rbmin,rbmax);
				
				//远相交点
                float fa=min(min(t2.x,t2.y),t2.z);
                float3 posNobox=objectPos+viewDir*fa;

                fixed4 col = tex2D(_MainTex, posNobox);
                return col;

                //反射方向
                float3 reflectDir=posNobox-(_EnvBoxStart+_EnvBoxSize/2);

                //fixed4 col = texCUBE(_Cube,reflectDir);
                return float4(posNobox,1);
            }
            ENDCG
        }
    }
}

第三种、2图体积渲染

基于光线步进,模拟体积渲染,我这里层数故意设置高了,实际可以不用这么多;

Shader "Unlit/ParallaxMapping" 
{
	Properties {
		_Color("颜色",Color) = (1,1,1,1)
		_MainTex("深度图",2D) = "white"{}
		[NoScaleOffset]_BaseTex("颜色图",2D)="white"{}
		_Height("位移高度",range(0,1)) = 0.15
		_HeightAmount("基准高度",range(0,2)) = 1
		_MaxStep("最大迭代步长", Range(4, 256)) = 16
	}
	SubShader 
	{
        Tags 
		{
            "IgnoreProjector"="True"
            "Queue"="Opaque"
            "RenderType"="Opaque"
        }

		Pass
		{
		    Name "FORWARD"
			Cull Off

			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma multi_compile_fwdbase

			#include "UnityCG.cginc"

			sampler2D _MainTex;
			float4 _MainTex_ST;
			float4 _MainTex_TexelSize;

			sampler2D _BaseTex;
			half _Height;
			half _HeightAmount;
			half4 _Color;
			int _MaxStep;

			struct v2f 
			{
				float4 pos : SV_POSITION;
				float2 uv : TEXCOORD0;
				float3 viewDir : TEXCOORD2;
			};

			v2f vert (appdata_full v) 
			{
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);
				o.uv = TRANSFORM_TEX(v.texcoord,_MainTex);
				TANGENT_SPACE_ROTATION;
				o.viewDir = mul(rotation, ObjSpaceViewDir(v.vertex));
				return o;
			}

			float4 frag(v2f i) : SV_Target
			{
				float3 viewRay=normalize(i.viewDir*-1);
				viewRay.z=abs(viewRay.z) + 0.2;
				viewRay.xy *= _Height;

				float3 shadeP = float3(i.uv,0);
				float h2 = _HeightAmount;
				
				float3 lioffset = viewRay / viewRay.z;
				float2 pixels = lioffset.xy * _MainTex_TexelSize.zw;
				float pixel = max(max(abs(pixels.x), abs(pixels.y)), 1);
				float linearStep = min(_MaxStep, floor(pixel));
				lioffset /= linearStep;

				float d = 1.0 - tex2Dlod(_MainTex, float4(shadeP.xy,0,0)).b * h2	;
				float3 prev_d = d;
				float3 prev_shadeP = shadeP;
				while(d > shadeP.z)
				{
					prev_shadeP = shadeP;
					shadeP += lioffset;
					prev_d = d;
					d = 1.0 - tex2Dlod(_MainTex, float4(shadeP.xy,0,0)).b * h2;
				}
				float d1 = d - shadeP.z;
				float d2 = prev_d - prev_shadeP.z;
				float w = d1 / (d1 - d2);
				shadeP = lerp(shadeP, prev_shadeP, w);

				half4 c = tex2D(_BaseTex, shadeP.xy) * _Color;
				return c;
			}
			ENDCG
		}
	}
}

第四种、2D图盒体投影

这段代码的核心功能是实现盒体投影的反射效果,主要通过计算光线与盒子相交的点,并通过反射方向从立方体贴图(Cubemap)中采样颜色,模拟物体表面的环境反射。

Shader "Unlit/BoxProjection"
{
    Properties
    {
        _Cube ("Reflection Cubemap", Cube) = "_Skybox" {}
        _EnvBoxStart ("Env Box Start", Vector) = (0, 0, 0)
        _EnvBoxSize ("Env Box Size", Vector) = (1, 1, 1,1)
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            
            #include "UnityCG.cginc"
            
            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };
            
            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                float3 viewDir:TEXCOORD1;
                float3 objectPos:TEXCOORD2;
            };


            samplerCUBE _Cube;
            float4 _Cube_ST;
            float4 _EnvBoxStart;
            float4 _EnvBoxSize;
            
            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                float3 worldPos=mul(unity_ObjectToWorld,v.vertex).xyz;
                float3 worldViewDir=UnityWorldSpaceViewDir(worldPos);
                o.viewDir=-mul(unity_WorldToObject,float4(worldViewDir,0));
                o.objectPos=v.vertex.xyz;
                return o;
            }
            
            fixed4 frag (v2f i) : SV_Target
            {
                float3 viewDir=i.viewDir;
                float3 objectPos=i.objectPos+half3(0.5,0.5,0);

                float3 rbmax=(_EnvBoxStart+_EnvBoxSize-objectPos)/viewDir;
                float3 rbmin=(_EnvBoxStart-objectPos)/viewDir;

                float3 t2=max(rbmin,rbmax);

                float fa=min(min(t2.x,t2.y),t2.z);
                float3 posNobox=objectPos+viewDir*fa;
                float3 reflectDir=posNobox-(_EnvBoxStart+_EnvBoxSize/2);

                fixed4 col = texCUBE(_Cube,reflectDir);
                return col;
            }
            ENDCG
        }
    }
}

第五种、2D图蒙版剔除

这个需要分开来做,球状图单独一个mesh,另外一个面片用来做蒙版剔除显示画面;

SKY:

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
 
Shader "Common/Men_Stencil" {
Properties {
	_DepthValue("远近",Range(0,1)) =1
	[Enum(Off, 0, On, 1)]_ZWriteMode ("ZWriteMode", float) = 0
	[Enum(UnityEngine.Rendering.CompareFunction)]_ZTestMode ("ZTestMode", Float) = 4
	_Tint ("Tint Color", Color) = (.5, .5, .5, .5)
	[Gamma] _Exposure ("Exposure", Range(0, 8)) = 1.0
	_Rotation ("Rotation", Range(0, 360)) = 0
	_RotSpeed ("Rotation Speed", Range(0, 360)) = 0
	[NoScaleOffset] _Tex ("Cubemap   (HDR)", Cube) = "grey" {}
	_DitherStrength("Dither Strength", int) = 16
	[IntRange] _StencilRef("Stencil Reference Value", Range(0, 255)) = 0
}
 
SubShader {
	Tags { "RenderPipeline"="UniversalPipeline" "RenderType" = "Transparent"  "Queue" = "Transparent" "PreviewType"="Skybox" }
	Cull Off
	ZWrite Off
	Blend SrcAlpha OneMinusSrcAlpha
	ZWrite [_ZWriteMode]
    ZTest [_ZTestMode]

	Stencil{
			Ref[_StencilRef]
				Comp Equal
			}
 
	Pass {
		
		HLSLPROGRAM
		#pragma vertex vert
		#pragma fragment frag
 
        #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
        #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
		
		struct appdata_t {
			float4 vertex 			: POSITION;
		};
 
		struct v2f {
			float4 vertex 			: SV_POSITION;
			float3 texcoord 		: TEXCOORD0;
			float3 positionWS       : TEXCOORD1;
		};
 
            TEXTURECUBE(_Tex);
            SAMPLER(sampler_Tex);
 
            CBUFFER_START(UnityPerMaterial)
			//CBUFFER_START(UnityPerMaterialCB)
            half4 _Tex_HDR;
            float4 _Tint;
			half _Exposure , _DepthValue;
			float _Rotation, _RotSpeed; half _DitherStrength;
            CBUFFER_END
 
			#ifdef UNITY_COLORSPACE_GAMMA
			#define unity_ColorSpaceDouble half4(2.0, 2.0, 2.0, 2.0)
			
			#else // Linear values
			#define unity_ColorSpaceDouble half4(4.59479380, 4.59479380, 4.59479380, 2.0)
			#endif
 
		float4 RotateAroundYInDegrees (float4 vertex, float degrees)
		{
			float alpha = degrees * PI / 180.0;
			float sina, cosa;
			sincos(alpha, sina, cosa);
			float2x2 m = float2x2(cosa, -sina, sina, cosa);
			return float4(mul(m, vertex.xz), vertex.yw).xzyw;
		}

		v2f vert (appdata_t v)
		{
			v2f o;
			o.vertex = TransformObjectToHClip(RotateAroundYInDegrees(v.vertex, _Rotation + (_Time * _RotSpeed)));
			// o.texcoord = TransformObjectToWorld(v.vertex.xyz);
			o.texcoord = v.vertex.xyz;
			o.positionWS  = TransformObjectToWorld(v.vertex.xyz);
			return o;
		}
 
		half4 frag (v2f i) : SV_Target
		{	
			//视角修正
			half3 V = SafeNormalize(_WorldSpaceCameraPos - i.positionWS);
			half4 tex = SAMPLE_TEXTURECUBE(_Tex,sampler_Tex,float3(i.texcoord.xy,i.texcoord.z*_DepthValue));
			
			half3 c = DecodeHDREnvironment (tex, _Tex_HDR);
			c = c * _Tint.rgb * unity_ColorSpaceDouble.rgb;
			//c = c * _Tint.rgb * 2.2;
			c *= _Exposure;
			
			return float4(c,1);
		}
		ENDHLSL
	}
} 	
 
 
FallBack "Packages/com.unity.render-pipelines.universal/FallbackError"
 
}

Mask:

Shader "Common/Men_StencilWriter"
{
    Properties
    {
		[IntRange] _StencilRef("Stencil Reference Value", Range(0,255)) = 0
    }
 
    SubShader
    {

        Pass
        {
            Tags { "Queue" = "Geometry+501" "IgnoreProjector" = "True" "RenderPipeline" = "UniversalPipeline" }

            ZWrite Off
            Blend SrcAlpha OneMinusSrcAlpha
            ColorMask 0 // Don't write to any colour channels
            Stencil
            {
                Ref[_StencilRef]
                Comp Always
                Pass Replace  
            }

            Name "Unlit"
            HLSLPROGRAM
            // Required to compile gles 2.0 with standard srp library
            #pragma prefer_hlslcc gles
            #pragma exclude_renderers d3d11_9x
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_fog
            //GPU批处理
            #pragma multi_compile_instancing 

            #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
            #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/UnityInstancing.hlsl"
 
 
            struct Attributes
            {
                float4 positionOS       : POSITION;
                float4 color : COLOR;
				UNITY_VERTEX_INPUT_INSTANCE_ID              //GPU批处理死亡三件套
            };
 
            struct Varyings
            {
                float4 positionCS       : SV_POSITION;
                float4 color            : COLOR;
                float3 texcoord         : TEXCOORD0;
				UNITY_VERTEX_INPUT_INSTANCE_ID               //GPU批处理死亡三件套
            };
 
            CBUFFER_START(UnityPerMaterial)
            CBUFFER_END
            
 
            Varyings vert(Attributes v)
            {
                Varyings o = (Varyings)0;
                UNITY_SETUP_INSTANCE_ID(v);         //GPU批处理死亡三件套
		        UNITY_TRANSFER_INSTANCE_ID(v,o);    //GPU批处理死亡三件套
                o.texcoord = v.positionOS.xyz;
                // v.positionOS.xyz = float3(v.positionOS.x,lerp(0,v.positionOS.y,_yMask),v.positionOS.z);
                o.color = v.color;
                o.positionCS = TransformObjectToHClip(v.positionOS.xyz);
 
                return o;
            }
 
            half4 frag(Varyings i) : SV_Target
            {
                UNITY_SETUP_INSTANCE_ID(i);         //GPU批处理死亡三件套
                return 0.5;
            }
            ENDHLSL
        }

    }
}

第六种、DDC软件摄像机跟踪

参考三来自B站:视差效果简易制作教程_哔哩哔哩_bilibili

其余查找资料或者GPT找思路....

你可能感兴趣的:(unity,计算机视觉,前端)