伪内部空间映射的相关文档

CSDN上的参考网页

Unity Shader Interior mapping 内部映射 CSDN上的案例学习——Interior Mapping 室内映射(假室内效果) CSDN上的UE5黑客帝国3d print假室内的一些使用记录 unity 跟随目标_使用Cubemap在Unity中制作虚拟室内效果

知乎上的参考网页

案例学习——Interior Mapping 室内映射(假室内效果) 一种假室内(Fake Interior)效果的实现,这种是带上了室内深度效果的,即每个室内的深度纵深是不一样的。

其他

Joost van Dongen的论文《Interior Mapping A new techique for rendering realistic buildings

下面的这份代码是《一种假室内(Fake Interior)效果的实现》中提到的代码实现

  1Shader "Custom/FakeRoom"
  2{
  3    Properties
  4    {
  5        [NoScaleOffset]_WindowTex ("Window Texture", 2D) = "black" {}
  6        _RoomTex ("Room Texture", CUBE) = ""{}
  7        _RoomDepth ("Room Depth", Range(0.01, 1)) = 1.0
  8    }
  9    SubShader
 10    {
 11        Tags { "RenderType"="Opaque" }
 12        Cull Back
 13
 14        Pass
 15        {
 16            CGPROGRAM
 17            #pragma vertex vert
 18            #pragma fragment frag
 19
 20            #include "UnityCG.cginc"
 21            #define FLT_EPS  5.960464478e-8  // 2^-24, machine epsilon: 1 + EPS = 1 (half of the ULP for 1.0f)
 22            #define Max3(a, b, c) max(max(a, b), c)
 23            #define Min3(a, b, c) min(min(a, b), c)
 24
 25            struct appdata
 26            {
 27                float4 positionOS : POSITION;
 28                float2 uv : TEXCOORD0;
 29                float3 normal : NORMAL;
 30            };
 31
 32            struct v2f
 33            {
 34                float2 uv : TEXCOORD0;
 35                float4 positionCS : SV_POSITION;
 36                float3 positionOS : TEXCOORD1;
 37                float3 viewDirOS : TEXCOORD2;
 38                float3 normalOS : TEXCOORD3;
 39            };
 40
 41            sampler2D _WindowTex;
 42            samplerCUBE _RoomTex;
 43            float4 _RoomTex_ST;
 44            fixed _RoomDepth;
 45            
 46            bool IntersectRayAABB(float3 rayOrigin, float3 rayDirection,
 47                                  float3 boxMin,    float3 boxMax,
 48                                  float  tMin,       float tMax,
 49                              out float  tEntr,  out float tExit)
 50            {
 51                // Could be precomputed. Clamp to avoid INF. clamp() is a single ALU on GCN.
 52                // rcp(FLT_EPS) = 16,777,216, which is large enough for our purposes,
 53                // yet doesn't cause a lot of numerical issues associated with FLT_MAX.
 54                float3 rayDirInv = clamp(rcp(rayDirection), -rcp(FLT_EPS), rcp(FLT_EPS));
 55            
 56                // Perform ray-slab intersection (component-wise).
 57                float3 t0 = boxMin * rayDirInv - (rayOrigin * rayDirInv);
 58                float3 t1 = boxMax * rayDirInv - (rayOrigin * rayDirInv);
 59            
 60                // Find the closest/farthest distance (component-wise).
 61                float3 tSlabEntr = min(t0, t1);
 62                float3 tSlabExit = max(t0, t1);
 63            
 64                // Find the farthest entry and the nearest exit.
 65                tEntr = Max3(tSlabEntr.x, tSlabEntr.y, tSlabEntr.z);
 66                tExit = Min3(tSlabExit.x, tSlabExit.y, tSlabExit.z);
 67            
 68                // Clamp to the range.
 69                tEntr = max(tEntr, tMin);
 70                tExit = min(tExit, tMax);
 71            
 72                return tEntr < tExit;
 73            }
 74            
 75            v2f vert (appdata v)
 76            {
 77                v2f o;
 78                o.positionCS = UnityObjectToClipPos(v.positionOS);
 79                o.uv = v.uv;
 80                o.positionOS = v.positionOS;
 81                o.viewDirOS = ObjSpaceViewDir(v.positionOS);
 82                o.normalOS = v.normal;
 83                return o;
 84            }
 85
 86            fixed4 frag (v2f i) : SV_Target
 87            {
 88            
 89                fixed4 windowColor = tex2D(_WindowTex, i.uv);
 90                float3 viewDirOS = normalize(i.viewDirOS);
 91                float3 normalOS = i.normalOS;
 92                float radius = 0.5, posEntr, posExit;
 93                float bias = 2 * radius * (1 - _RoomDepth);
 94                
 95                float3 boxMin = (float3)(-radius) + lerp((float3)0, bias * normalOS, Max3(normalOS.x, normalOS.y, normalOS.z));
 96                float3 boxMax = (float3)(radius) + lerp(bias * normalOS, (float3)0, Max3(normalOS.x, normalOS.y, normalOS.z));
 97                
 98                IntersectRayAABB(i.positionOS, -viewDirOS, boxMin, boxMax, 1, 2, posEntr, posExit);
 99                float3 sampleDir = i.positionOS - posExit * viewDirOS;
100                sampleDir -= bias * normalOS;
101
102                fixed4 col = texCUBElod(_RoomTex, float4(sampleDir, 0));
103                col.rgb += windowColor.rgb * windowColor.a;
104                return col;
105            }
106
107            ENDCG
108        }
109    }
110}

下面这段代码则是《案例学习——Interior Mapping 室内映射(假室内效果)》中的“预投影2D贴图方法的实现”

  1// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
  2
  3Shader "MyShaders/InteriorMapping_2D"
  4{
  5	Properties
  6	{
  7		_RoomTex("Room Atlas RGB (A - back wall fraction)", 2D) = "white" {}
  8		_Rooms("Room Atlas Rows&Cols (XY)", Vector) = (1,1,0,0)
  9		_RoomDepth("Room Depth",range(0.001,0.999)) = 0.5
 10	}
 11		SubShader
 12		{
 13			Tags { "RenderType" = "Opaque" }
 14			LOD 100
 15
 16			Pass
 17			{
 18				CGPROGRAM
 19				#pragma vertex vert
 20				#pragma fragment frag
 21
 22				#include "UnityCG.cginc"
 23
 24				struct appdata
 25				{
 26					float4 vertex : POSITION;
 27					float2 uv : TEXCOORD0;
 28					float3 normal : NORMAL;
 29					float4 tangent : TANGENT;
 30				};
 31
 32				struct v2f
 33				{
 34					float4 pos : SV_POSITION;
 35					float2 uv : TEXCOORD0;
 36					float3 tangentViewDir : TEXCOORD1;
 37				};
 38				sampler2D _RoomTex;
 39				float4 _RoomTex_ST;
 40				float2 _Rooms;
 41				float _RoomDepth;
 42				v2f vert(appdata v)
 43				{
 44					v2f o;
 45					o.pos = UnityObjectToClipPos(v.vertex);
 46					o.uv = TRANSFORM_TEX(v.uv, _RoomTex);
 47
 48					// get tangent space camera vector
 49					float4 objCam = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos, 1.0));
 50					float3 viewDir = v.vertex.xyz - objCam.xyz;
 51					float tangentSign = v.tangent.w * unity_WorldTransformParams.w;
 52					float3 bitangent = cross(v.normal.xyz, v.tangent.xyz) * tangentSign;
 53					o.tangentViewDir = float3(
 54						dot(viewDir, v.tangent.xyz),
 55						dot(viewDir, bitangent),
 56						dot(viewDir, v.normal)
 57						);
 58					o.tangentViewDir *= _RoomTex_ST.xyx;
 59					return o;
 60				}
 61
 62				// psuedo random
 63				float2 rand2(float co) {
 64					return frac(sin(co * float2(12.9898,78.233)) * 43758.5453);
 65				}
 66
 67				fixed4 frag(v2f i) : SV_Target
 68				{
 69					// room uvs
 70					float2 roomUV = frac(i.uv);
 71					float2 roomIndexUV = floor(i.uv);
 72
 73					// randomize the room
 74					float2 n = floor(rand2(roomIndexUV.x + roomIndexUV.y * (roomIndexUV.x + 1)) * _Rooms.xy);
 75					//float2 n = floor(_Rooms.xy);
 76					roomIndexUV += n;
 77
 78					// get room depth from room atlas alpha
 79					// fixed farFrac = tex2D(_RoomTex, (roomIndexUV + 0.5) / _Rooms).a;
 80
 81					// Specify depth manually
 82					fixed farFrac = _RoomDepth;
 83
 84					//remap [0,1] to [+inf,0]
 85					//->if input _RoomDepth = 0    -> depthScale = 0      (inf depth room)
 86					//->if input _RoomDepth = 0.5  -> depthScale = 1
 87					//->if input _RoomDepth = 1    -> depthScale = +inf   (0 volume room)
 88					float depthScale = 1.0 / (1.0 - farFrac) - 1.0;
 89
 90					// raytrace box from view dir
 91					// normalized box space's ray start pos is on trinagle surface, where z = -1
 92					float3 pos = float3(roomUV * 2 - 1, -1);
 93					// transform input ray dir from tangent space to normalized box space
 94					i.tangentViewDir.z *= -depthScale;
 95					
 96                    // 预先处理倒数  t=(1-p)/view=1/view-p/view
 97					float3 id = 1.0 / i.tangentViewDir;
 98					float3 k = abs(id) - pos * id;
 99					float kMin = min(min(k.x, k.y), k.z);
100					pos += kMin * i.tangentViewDir;
101
102					// remap from [-1,1] to [0,1] room depth
103					float interp = pos.z * 0.5 + 0.5;
104
105					// account for perspective in "room" textures
106					// assumes camera with an fov of 53.13 degrees (atan(0.5))
107					// visual result = transform nonlinear depth back to linear
108					float realZ = saturate(interp) / depthScale + 1;
109					interp = 1.0 - (1.0 / realZ);
110					interp *= depthScale + 1.0;
111
112					// iterpolate from wall back to near wall
113					float2 interiorUV = pos.xy * lerp(1.0, farFrac, interp);
114					
115					interiorUV = interiorUV * 0.5 + 0.5;
116
117					// sample room atlas texture
118					fixed4 room = tex2D(_RoomTex, (roomIndexUV + interiorUV.xy) / _Rooms);
119					return room;
120				}
121			ENDCG
122		}
123	}
124	FallBack "Diffuse"
125}