【Unity Shader学习笔记】10.高级纹理

学习资料:《Unity Shader入门精要》第10章

源代码:Github


立方体纹理

菲涅尔反射

视线与法线夹角越大,反射越强

Schlick菲涅尔近似等式:

F s c h l i c k ( v ⃗ , n ⃗ ) = F 0 + ( 1 − F 0 ) ( 1 − v ⃗ ⋅ n ⃗ ) 5 F_{schlick}(\vec{v},\vec{n})=F_{0}+(1-F_{0})(1-\vec{v}\cdot \vec{n})^5 Fschlick(v ,n )=F0+(1F0)(1v n )5
v:视角方向,n:表面法线

渲染纹理

渲染目标纹理:把整个三维场景渲染到中间缓冲,即渲染目标纹理(Render Target Texture, RTT)

多重渲染目标(MRT):把场景同时渲染到多个渲染目标纹理中

延迟渲染

镜子效果

创建渲染纹理(Create -> Render Texture),并设置为摄像机的Target Texture,使摄像机把渲染结果更新到这个渲染纹理中。把摄像机放在适当的位置(镜子的中间),调整裁剪平面和视角等,使摄像机看到的就是镜子所照到的,只是左右相反。

使用渲染纹理作为Shader的输入属性,左右翻转后显示到物体上即可:

Mirror的Main Tex使用由渲染相机得到的渲染纹理Mirror Texture,渲染相机挂载在Mirror下面,Target Texture选择Mirror Texture。

// 左右翻转
o.uv = v.texcoord;
o.uv.x = 1 - o.uv.x;

效果展示:

在这里插入图片描述

玻璃效果

GrabPass:把当前屏幕的图像绘制在一张纹理中,供后续Pass使用,通常用于渲染透明物体

反射:CubeMap 环境映射纹理

折射:使用GrabPass获取玻璃后面的屏幕图像,使用切线空间下的法线对屏幕纹理坐标偏移后,再对屏幕图像采样得到近似的折射效果

// This pass grabs the screen behind the object into a texture.
// We can access the result in the next pass as _RefractionTex
GrabPass { "_RefractionTex" }
v2f vert (a2v v) {
	v2f o;
	o.pos = UnityObjectToClipPos(v.vertex);
	
	// 得到被抓取的屏幕图像的采样坐标
	o.scrPos = ComputeGrabScreenPos(o.pos);
	
	o.uv.xy = TRANSFORM_TEX(v.texcoord, _MainTex);
	o.uv.zw = TRANSFORM_TEX(v.texcoord, _BumpMap);
	
	float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;  
	fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);  
	fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);  
	fixed3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w; 
	
	// 切线空间变换到世界空间
	o.TtoW0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);  
	o.TtoW1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);  
	o.TtoW2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);  
	
	return o;
}

fixed4 frag (v2f i) : SV_Target {		
	float3 worldPos = float3(i.TtoW0.w, i.TtoW1.w, i.TtoW2.w);
	fixed3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos));
	
	// 采样法线纹理,得到切线空间的法线方向
	fixed3 bump = UnpackNormal(tex2D(_BumpMap, i.uv.zw));	
	
	// 计算折射的偏移
	float2 offset = bump.xy * _Distortion * _RefractionTex_TexelSize.xy;
	i.scrPos.xy = offset * i.scrPos.z + i.scrPos.xy;
	fixed3 refrCol = tex2D(_RefractionTex, i.scrPos.xy/i.scrPos.w).rgb;
	
	// 法线从切线空间变换到世界空间
	bump = normalize(half3(dot(i.TtoW0.xyz, bump), dot(i.TtoW1.xyz, bump), dot(i.TtoW2.xyz, bump)));
	fixed3 reflDir = reflect(-worldViewDir, bump);
	fixed4 texColor = tex2D(_MainTex, i.uv.xy);
	// 混合得到反射颜色
	fixed3 reflCol = texCUBE(_Cubemap, reflDir).rgb * texColor.rgb;
	
	fixed3 finalColor = reflCol * (1 - _RefractAmount) + refrCol * _RefractAmount;
	
	return fixed4(finalColor, 1);
}

效果展示:

在这里插入图片描述

渲染纹理 & GrabPass

  • GrabPass:实现简单

  • 渲染纹理:手动创建渲染纹理、额外摄像机,把渲染纹理传递给对应的shader

效率:渲染纹理好于GrabPass,渲染纹理可以自定义大小,GrabPass的分辨率和显示屏幕一致,在移动设备上GrabPass需要CPU直接读取back buffer的数据

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值