Unity引擎制作假室內效果
??大家好,我是阿趙。
??這次來介紹一種使用CubeMap做假室內效果的方式。這種技術名叫InteriorCubeMap,是UE引擎自帶的節點效果。我這里是在Unity引擎里面的實現。
一、效果展示
這個假室內效果,要動態看才能看出效果,各位可以看看上面的視頻
??簡單來說,從不同的角度看這個面片,看到的里面的內容會隨著視角的變化而變化,感覺好像從窗外觀看室內的效果。
二、原理分析
實際上,并沒有什么室內效果,那些都是一個一個的面片來的。
??面片所顯示的內容,其實是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));
}
??通過調節Depth參數,可以模擬不同深度的室內效果。
??通過調節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 100Pass{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}}}