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