Unity引擎使用InteriorCubeMap采样制作假室内效果

Unity引擎制作假室内效果

  大家好,我是阿赵。
  这次来介绍一种使用CubeMap做假室内效果的方式。这种技术名叫InteriorCubeMap,是UE引擎自带的节点效果。我这里是在Unity引擎里面的实现。

一、效果展示

这个假室内效果,要动态看才能看出效果,各位可以看看上面的视频

Unity引擎使用InteriorCubeMap采样制作假室内效果_第1张图片
Unity引擎使用InteriorCubeMap采样制作假室内效果_第2张图片

Unity引擎使用InteriorCubeMap采样制作假室内效果_第3张图片

  简单来说,从不同的角度看这个面片,看到的里面的内容会随着视角的变化而变化,感觉好像从窗外观看室内的效果。

二、原理分析

Unity引擎使用InteriorCubeMap采样制作假室内效果_第4张图片

实际上,并没有什么室内效果,那些都是一个一个的面片来的。
Unity引擎使用InteriorCubeMap采样制作假室内效果_第5张图片

  面片所显示的内容,其实是CubeMap贴图。
  CubeMap贴图的用法之前在写天空盒变化的文章里面介绍过,各位可以去看看:
  https://blog.csdn.net/liweizhao/article/details/129603219
  当时的CubeMap采样时通过计算世界空间的ViewDir和世界空间的法线方向来做的

float3 worldViewDir = UnityWorldSpaceViewDir(i.worldPos);
worldViewDir = normalize(worldViewDir);
float3 worldReflect = reflect(worldViewDir,i.worldNormal);
float4 col = texCUBE(_SkyTex1, worldReflect);

  所以如果使用在一个面片上面,也能做到里面的内容跟随这视角变化而变化,但由于面片的法线方向都是朝着同一个方向的,所以显示在上面的CubeMap是一个平面的效果。
但这个InteriorCubeMap的计算采样CubeMap的UV的方式比较特别,它会模拟成一个方形来采样CubeMap。
  我把这个InteriorCubeMap节点的代码模拟成一个方法,求出一个采样的UV:

float3 InteriorCubeMap(float3 worldPosition,  float3 worldTangent,float3 worldNormal,float3 worldBitangent,float2 uv)
{
	float3 tanToWorld0 = float3(worldTangent.x, worldBitangent.x, worldNormal.x);
	float3 tanToWorld1 = float3(worldTangent.y, worldBitangent.y, worldNormal.y);
	float3 tanToWorld2 = float3(worldTangent.z, worldBitangent.z, worldNormal.z);
	float3 worldViewDir = UnityWorldSpaceViewDir(worldPosition);
	worldViewDir = normalize(worldViewDir);
	float3 tanViewDir = tanToWorld0 * worldViewDir.x + tanToWorld1 * worldViewDir.y + tanToWorld2 * worldViewDir.z;
	tanViewDir = Unity_SafeNormalize(tanViewDir);
	float3 step1Val = (float3(-1, -1, 1) * tanViewDir);
	float3 step2Val = (1.0 / step1Val);
	float3 step3Val = (float3(((frac(((uv * float2(1, -1)) * (_Tilling).xx)) * float2(2, -2)) - float2(1, -1)), -1.0*_Depth));
	float3 step4Val = (abs(step2Val) - (step2Val * step3Val));
	float3 step5Val = ((min(min(step4Val.x, step4Val.y), step4Val.z) * step1Val) + step3Val);
	return (float3(step5Val.z, step5Val.x, step5Val.y));
}

Unity引擎使用InteriorCubeMap采样制作假室内效果_第6张图片

  通过调节Depth参数,可以模拟不同深度的室内效果。
Unity引擎使用InteriorCubeMap采样制作假室内效果_第7张图片

  通过调节Tilling平铺次数,可以模拟多个相同的房间放在一起的效果。

三、代码

Shader "azhao/InteriorCubeMapTest"
{
	Properties
	{
		_Tilling("Tilling", Vector) = (1,1,1,1)
		_CubeTex("Texture Sample 0", CUBE) = "white" {}
		_Depth("Depth",Range(0,5)) = 1
	}

	SubShader
	{


		Tags { "RenderType" = "Opaque" }
		LOD 100

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

			struct appdata
			{
				float4 vertex : POSITION;
				float4 color : COLOR;
				float4 tangent : TANGENT;
				float3 normal : NORMAL;
				float2 uv : TEXCOORD0;
			};

			struct v2f
			{
				float4 vertex : SV_POSITION;
				float2 uv : TEXCOORD0;
				float3 worldPos : TEXCOORD1;
				float3 worldTangent : TEXCOORD2;
				float3 worldNormal : TEXCOORD3;
				float3 worldBitangent : TEXCOORD4;

			};

			samplerCUBE _CubeTex;
			float2 _Tilling;
			float _Depth;
			float3 InteriorCubeMap(float3 worldPosition,  float3 worldTangent,float3 worldNormal,float3 worldBitangent,float2 uv)
			{
				float3 tanToWorld0 = float3(worldTangent.x, worldBitangent.x, worldNormal.x);
				float3 tanToWorld1 = float3(worldTangent.y, worldBitangent.y, worldNormal.y);
				float3 tanToWorld2 = float3(worldTangent.z, worldBitangent.z, worldNormal.z);
				float3 worldViewDir = UnityWorldSpaceViewDir(worldPosition);
				worldViewDir = normalize(worldViewDir);
				float3 tanViewDir = tanToWorld0 * worldViewDir.x + tanToWorld1 * worldViewDir.y + tanToWorld2 * worldViewDir.z;
				tanViewDir = Unity_SafeNormalize(tanViewDir);
				float3 step1Val = (float3(-1, -1, 1) * tanViewDir);
				float3 step2Val = (1.0 / step1Val);
				float3 step3Val = (float3(((frac(((uv * float2(1, -1)) * (_Tilling).xy)) * float2(2, -2)) - float2(1, -1)), -1.0*_Depth));
				float3 step4Val = (abs(step2Val) - (step2Val * step3Val));
				float3 step5Val = ((min(min(step4Val.x, step4Val.y), step4Val.z) * step1Val) + step3Val);
				return (float3(step5Val.z, step5Val.x, step5Val.y));
			}

			v2f vert(appdata v)
			{
				v2f o;

				o.worldTangent = UnityObjectToWorldDir(v.tangent);
				o.worldNormal = UnityObjectToWorldNormal(v.normal);
				float vertexTangentSign = v.tangent.w * unity_WorldTransformParams.w;
				float3 worldBitangent = cross(o.worldNormal, o.worldTangent) * vertexTangentSign;
				o.worldBitangent.xyz = worldBitangent;
				o.uv = v.uv;
				o.vertex = UnityObjectToClipPos(v.vertex);
				o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;

				return o;
			}

			half4 frag(v2f i) : SV_Target		{

				float3 cubeUV = InteriorCubeMap(i.worldPos,i.worldTangent, i.worldNormal, i.worldBitangent, i.uv);
				half4 finalColor = texCUBE(_CubeTex, cubeUV);
				return finalColor;
			}
			ENDCG
		}
	}


}

你可能感兴趣的:(Unity引擎Shader效果,unity,游戏引擎,InteriorCubeMap,假室内效果)