Unity——ShaderLab实现玻璃和镜子效果
在这一篇中会实现会介绍折射和反射,以及菲尼尔反射;并且实现镜子和玻璃效果;
这里和之前不同的地方在于取样的是一张CubeMap;
demo里的cubemap使用的一样,相机所在位置拍出来的周围环境图;
生成CubeMap的工具脚本:
public class RenderCubemapWizard : ScriptableWizard { public Transform renderFromPosition; public Cubemap cubemap; void OnWizardUpdate () { helpString = "Select transform to render from and cubemap to render into"; isValid = (renderFromPosition != null) && (cubemap != null); } void OnWizardCreate () { // create temporary camera for rendering GameObject go = new GameObject( "CubemapCamera"); go.AddComponent<Camera>(); // place it on the object go.transform.position = renderFromPosition.position; // render into cubemap go.GetComponent<Camera>().RenderToCubemap(cubemap); // destroy temporary camera DestroyImmediate( go ); } [MenuItem("GameObject/Render into Cubemap")] static void RenderCubemap () { ScriptableWizard.DisplayWizard<RenderCubemapWizard>( "Render cubemap", "Render!"); } }
1.反射
用反射方向在CubeMap上取样,_ReflectAmount控制反射程度,_ReflectColor反射颜色;
v2f vert (appdata v){ //计算反射向量 o.worldReflect = reflect(-o.worldViewDir,o.worldNormal); ... } fixed4 frag (v2f i) : SV_Target{ //根据反射向量从cubemap纹理上取样 fixed3 reflection = texCUBE(_Cubemap,i.worldReflect).rgb * _ReflectColor.rgb; //混合反射和漫反射 return fixed4(ambient + lerp(diffuse,reflection,_ReflectAmount)*atten, 1.0); }
2.折射
和反射几乎相同,将反射改成折射,计算公式改成折射计算公式;
v2f vert (appdata v){ //计算反射向量 o.worldRefract = refract(-normalize(o.worldViewDir),normalize(o.worldNormal),_RefractRatio); ... } fixed4 frag (v2f i) : SV_Target{ //根据反射向量从cubemap纹理上取样 fixed3 refraction = texCUBE(_Cubemap,i.worldRefract).rgb * _RefractColor.rgb; //混合反射和漫反射 return fixed4(ambient + lerp(diffuse,refraction,_RefractAmount)*atten, 1.0); }
成像是倒的;透过茶壶可以看到对面;
3.菲尼尔
反射光的强度与视线方向和法线方向的夹角有关,夹角越大反射光越强;最高90度,也就是边缘光最强;
Schlick菲尼尔公式:Fschlick(v,n) = F0 + (1-F0)(1- dot(v,n)) ^ 5;F0控制菲尼尔强度;
fixed4 frag (v2f i) : SV_Target{ ... //Schlick Fresnel——边缘光 fixed3 reflection = texCUBE(_Cubemap,i.worldRefl).rgb; fixed3 fresnel = _FresnelScale + (1 - _FresnelScale) * pow(1 - dot(worldViewDir,worldNormal), 5); //菲尼尔系数控制反射强度 return fixed4(ambient + lerp(diffuse,reflection,saturate(fresnel)) * atten, 1.0); }
4.玻璃效果
通过GrabPass{"_RefractionTex"} 抓取当前屏幕内容渲染到_RefractionTex贴图上
RefractionTex贴图用来取样折射纹理;_Distortion参数模拟法线扰动的程度;
GrabPass{"_RefractionTex"} ... //GrabPass纹理 sampler2D _RefractionTex; //纹素大小 float4 _RefractionTex_TexelSize; fixed4 frag (v2f i) : SV_Target { //法线偏移扰动-模拟折射 fixed3 bump = UnpackNormal(tex2D(_BumpMap,i.uv.zw)); float2 offset = bump.xy*_Distortion*_RefractionTex_TexelSize.xy; //折射计算-屏幕坐标偏移后透视除法取样折射纹理 i.screenPos.xy = offset + i.screenPos.xy; fixed3 refractColor = tex2D(_RefractionTex,i.screenPos.xy/i.screenPos.w).rgb; //矩阵计算世界法线 bump = normalize(half3(dot(i.TtoW0.xyz,bump),dot(i.TtoW1.xyz,bump),dot(i.TtoW2.xyz,bump))); //反射计算 fixed3 reflectDir = reflect(-worldViewDir,bump); fixed4 texColor = tex2D(_MainTex,i.uv.xy); fixed3 reflectColor = texCUBE(_Cubemap,reflectDir).rgb * texColor.rgb; //混合反射和折射_RefractAmount return fixed4(reflectColor*(1-_RefractAmount)+refractColor*_RefractAmount, 1.0); }
5.镜子
tex2Dproj(_ReflectionTex,UNITY_PROJ_COORD(i.refl));
UNITY_PROJ_COORD:given a 4-component vector, return a texture coordinate suitable for projected texture reads. On most platforms this returns the given value directly.
传入Vector4,返回一张用来投影取样的纹理,大部分平台直接返回给定值;
镜子直接传入屏幕顶点坐标获得投影纹理,再通过投影取样获得颜色,和最终结果混合;
但是上面效果和局限性都比较大,所以找了个大佬写的镜子效果;
使用相机和RenderTexture,底层原理差不多,效果要好了很多;
- Unity实现镜子效果
- unity实现玻璃效果
- unity实现玻璃效果
- unity实现玻璃效果
- unity中实现镜子效果
- Unity无需Shader实现镜子效果
- unity实现浇水倒水效果
- Unity 屏幕震动效果实现
- unity,荧光效果(bloom)实现过程
- Unity实现卷纸浏览效果
- Unity Shaders and Effects Cookbook (2-1) 修改 UV 坐标实现纹理贴图的滚动 模拟水流效果
- win7下 窗体玻璃效果的实现和WindowStyle None模式下的移动 wpf
- 如何在Unity中实现文字的渐隐效果?
- unity用shader实现物体的忽隐忽现效果
- 崩坏学园3里离摄像机近距离的头发透明效果在unity里的实现方法
- vc实现毛玻璃效果
- unity 使用shader加rendertexture实现刮刮乐效果
- iOS实现毛玻璃效果(无需要第三方)
- GDI+图片毛玻璃效果的实现
- Unity如何实现磁铁效果?(比如跑酷游戏中,获得磁铁道具后,自动吸附附近金币的效果。)