伪内部空间映射的相关文档
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}