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

Table of Contents

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com

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)效果的实现》中提到的代码实现

Shader "Custom/FakeRoom"
{
    Properties
    {
        [NoScaleOffset]_WindowTex ("Window Texture", 2D) = "black" {}
        _RoomTex ("Room Texture", CUBE) = ""{}
        _RoomDepth ("Room Depth", Range(0.01, 1)) = 1.0
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        Cull Back

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"
            #define FLT_EPS  5.960464478e-8  // 2^-24, machine epsilon: 1 + EPS = 1 (half of the ULP for 1.0f)
            #define Max3(a, b, c) max(max(a, b), c)
            #define Min3(a, b, c) min(min(a, b), c)

            struct appdata
            {
                float4 positionOS : POSITION;
                float2 uv : TEXCOORD0;
                float3 normal : NORMAL;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 positionCS : SV_POSITION;
                float3 positionOS : TEXCOORD1;
                float3 viewDirOS : TEXCOORD2;
                float3 normalOS : TEXCOORD3;
            };

            sampler2D _WindowTex;
            samplerCUBE _RoomTex;
            float4 _RoomTex_ST;
            fixed _RoomDepth;
            
            bool IntersectRayAABB(float3 rayOrigin, float3 rayDirection,
                                  float3 boxMin,    float3 boxMax,
                                  float  tMin,       float tMax,
                              out float  tEntr,  out float tExit)
            {
                // Could be precomputed. Clamp to avoid INF. clamp() is a single ALU on GCN.
                // rcp(FLT_EPS) = 16,777,216, which is large enough for our purposes,
                // yet doesn't cause a lot of numerical issues associated with FLT_MAX.
                float3 rayDirInv = clamp(rcp(rayDirection), -rcp(FLT_EPS), rcp(FLT_EPS));
            
                // Perform ray-slab intersection (component-wise).
                float3 t0 = boxMin * rayDirInv - (rayOrigin * rayDirInv);
                float3 t1 = boxMax * rayDirInv - (rayOrigin * rayDirInv);
            
                // Find the closest/farthest distance (component-wise).
                float3 tSlabEntr = min(t0, t1);
                float3 tSlabExit = max(t0, t1);
            
                // Find the farthest entry and the nearest exit.
                tEntr = Max3(tSlabEntr.x, tSlabEntr.y, tSlabEntr.z);
                tExit = Min3(tSlabExit.x, tSlabExit.y, tSlabExit.z);
            
                // Clamp to the range.
                tEntr = max(tEntr, tMin);
                tExit = min(tExit, tMax);
            
                return tEntr < tExit;
            }
            
            v2f vert (appdata v)
            {
                v2f o;
                o.positionCS = UnityObjectToClipPos(v.positionOS);
                o.uv = v.uv;
                o.positionOS = v.positionOS;
                o.viewDirOS = ObjSpaceViewDir(v.positionOS);
                o.normalOS = v.normal;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
            
                fixed4 windowColor = tex2D(_WindowTex, i.uv);
                float3 viewDirOS = normalize(i.viewDirOS);
                float3 normalOS = i.normalOS;
                float radius = 0.5, posEntr, posExit;
                float bias = 2 * radius * (1 - _RoomDepth);
                
                float3 boxMin = (float3)(-radius) + lerp((float3)0, bias * normalOS, Max3(normalOS.x, normalOS.y, normalOS.z));
                float3 boxMax = (float3)(radius) + lerp(bias * normalOS, (float3)0, Max3(normalOS.x, normalOS.y, normalOS.z));
                
                IntersectRayAABB(i.positionOS, -viewDirOS, boxMin, boxMax, 1, 2, posEntr, posExit);
                float3 sampleDir = i.positionOS - posExit * viewDirOS;
                sampleDir -= bias * normalOS;

                fixed4 col = texCUBElod(_RoomTex, float4(sampleDir, 0));
                col.rgb += windowColor.rgb * windowColor.a;
                return col;
            }

            ENDCG
        }
    }
}

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

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "MyShaders/InteriorMapping_2D"
{
	Properties
	{
		_RoomTex("Room Atlas RGB (A - back wall fraction)", 2D) = "white" {}
		_Rooms("Room Atlas Rows&Cols (XY)", Vector) = (1,1,0,0)
		_RoomDepth("Room Depth",range(0.001,0.999)) = 0.5
	}
		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;
					float3 normal : NORMAL;
					float4 tangent : TANGENT;
				};

				struct v2f
				{
					float4 pos : SV_POSITION;
					float2 uv : TEXCOORD0;
					float3 tangentViewDir : TEXCOORD1;
				};
				sampler2D _RoomTex;
				float4 _RoomTex_ST;
				float2 _Rooms;
				float _RoomDepth;
				v2f vert(appdata v)
				{
					v2f o;
					o.pos = UnityObjectToClipPos(v.vertex);
					o.uv = TRANSFORM_TEX(v.uv, _RoomTex);

					// get tangent space camera vector
					float4 objCam = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos, 1.0));
					float3 viewDir = v.vertex.xyz - objCam.xyz;
					float tangentSign = v.tangent.w * unity_WorldTransformParams.w;
					float3 bitangent = cross(v.normal.xyz, v.tangent.xyz) * tangentSign;
					o.tangentViewDir = float3(
						dot(viewDir, v.tangent.xyz),
						dot(viewDir, bitangent),
						dot(viewDir, v.normal)
						);
					o.tangentViewDir *= _RoomTex_ST.xyx;
					return o;
				}

				// psuedo random
				float2 rand2(float co) {
					return frac(sin(co * float2(12.9898,78.233)) * 43758.5453);
				}

				fixed4 frag(v2f i) : SV_Target
				{
					// room uvs
					float2 roomUV = frac(i.uv);
					float2 roomIndexUV = floor(i.uv);

					// randomize the room
					float2 n = floor(rand2(roomIndexUV.x + roomIndexUV.y * (roomIndexUV.x + 1)) * _Rooms.xy);
					//float2 n = floor(_Rooms.xy);
					roomIndexUV += n;

					// get room depth from room atlas alpha
					// fixed farFrac = tex2D(_RoomTex, (roomIndexUV + 0.5) / _Rooms).a;

					// Specify depth manually
					fixed farFrac = _RoomDepth;

					//remap [0,1] to [+inf,0]
					//->if input _RoomDepth = 0    -> depthScale = 0      (inf depth room)
					//->if input _RoomDepth = 0.5  -> depthScale = 1
					//->if input _RoomDepth = 1    -> depthScale = +inf   (0 volume room)
					float depthScale = 1.0 / (1.0 - farFrac) - 1.0;

					// raytrace box from view dir
					// normalized box space's ray start pos is on trinagle surface, where z = -1
					float3 pos = float3(roomUV * 2 - 1, -1);
					// transform input ray dir from tangent space to normalized box space
					i.tangentViewDir.z *= -depthScale;
					
                    // 预先处理倒数  t=(1-p)/view=1/view-p/view
					float3 id = 1.0 / i.tangentViewDir;
					float3 k = abs(id) - pos * id;
					float kMin = min(min(k.x, k.y), k.z);
					pos += kMin * i.tangentViewDir;

					// remap from [-1,1] to [0,1] room depth
					float interp = pos.z * 0.5 + 0.5;

					// account for perspective in "room" textures
					// assumes camera with an fov of 53.13 degrees (atan(0.5))
					// visual result = transform nonlinear depth back to linear
					float realZ = saturate(interp) / depthScale + 1;
					interp = 1.0 - (1.0 / realZ);
					interp *= depthScale + 1.0;

					// iterpolate from wall back to near wall
					float2 interiorUV = pos.xy * lerp(1.0, farFrac, interp);
					
					interiorUV = interiorUV * 0.5 + 0.5;

					// sample room atlas texture
					fixed4 room = tex2D(_RoomTex, (roomIndexUV + interiorUV.xy) / _Rooms);
					return room;
				}
			ENDCG
		}
	}
	FallBack "Diffuse"
}
kumakoko avatar
kumakoko
pure coder
comments powered by Disqus