Shader第八讲 Reflection Mapping



转载自风宇冲Unity3D教程学

链接:http://blog.sina.com.cn/s/blog_471132920101ntl3.html


简介


Reflection Mapping,又叫Environment Mapping。 对应TexGen的SphereMap和CubeReflect。是最快的reflect周围环境的算法


最早出现的是 Sphere Mapping,之后被 Cube Mapping取代。Reflection Mapping比射线追踪(Ray Tracing)高效得多


Reflection Mapping的前提是2个假设


(1)入射线来自无限距离


(2)物体是凸的,没有自身的相互反射




Sphere Mapping


已经过时的技术,


优点:


1效率高


2也可以用普通贴图


缺点:


1.只有用鱼眼贴图,并处于正交相机的视点时才是最佳效果。


其他情况如使用普通贴图,处于其他位置时效果一般。


2 浪费贴图的4个边角, 圆形区域之外的纹理值不会对结果产生影响。


原理:


在一幅平面纹理图像中对各个方向的颜色进行编码就相当于把一个擦得锃亮的完美球体放在环境的中央,然后在极远处用长焦镜头对它进行拍照。需要编码的区域就是覆盖整个纹理图像的一个圆形区域,它与纹理图像的顶、底、左、右边缘相切。这个圆形区域之外的纹理值不会对结果产生影响,因为它们不会在环境纹理中使用。


贴图: 把一个擦得锃亮的完美球体放在环境的中央,用鱼眼镜头的相机拍照,将球体沿着 顶、底、左、右边缘切出来一张照片,那么就是贴图了。


有了贴图后,在摄像机坐标系下,根据I,N得出R. 再由R得出UV.即使没有鱼眼贴图,用普通贴图也有一定的类似效果。




贴图


鱼眼 贴图                                        普通贴图


【风宇冲】Unity3D教程宝典之Shader篇:第二十四讲Reflection <wbr>Mapping          【风宇冲】Unity3D教程宝典之Shader篇:第二十四讲Reflection <wbr>Mapping

效果
【风宇冲】Unity3D教程宝典之Shader篇:第二十四讲Reflection <wbr>Mapping    【风宇冲】Unity3D教程宝典之Shader篇:第二十四讲Reflection <wbr>Mapping


计算方法:
1 在摄像机坐标系中根据 I : 入射向量  和  N : 法线向量   计算出  R : 反射向量
R = I - 2 * N * dot(N,I)
2 再根据固定算法 由R计算出 uv
float2 R_To_UV(float3 r) 
            { 
                float interim = 2.0 * sqrt(r.x * r.x + r.y * r.y + (r.z + 1.0) * (r.z + 1.0));  
                return float2(r.x/interim+0.5,r.y/interim+0.5); 
            } 

Fixed and Fragment Shader代码

Shader "Custom/Texgen_SphereMap_FragMine" { 
   Properties { 
           _Reflectivity ("Reflectivity", Range (0,1)) = 0.5 
        _MainTex("Base", 2D) = "white" 
        _Environment ("Environment", 2D) = "white" 
    } 
    SubShader { 
        Pass { 
            CGPROGRAM 
            #pragma vertex vert 
            #pragma fragment frag 
            #include "UnityCG.cginc" 
            sampler2D _MainTex; 
            sampler2D _Environment; 
            float4 _MainTex_ST; 
            float _Reflectivity; 
            struct v2f { 
                float4  pos : SV_POSITION; 
                float2  uv : TEXCOORD0; 
                float2  uv2:TEXCOORD1; 
            } ; 
             
            //I:入射向量 N:法线向量  R:反射向量 
            float3 reflect(float3 I,float3 N) 
            { 
                return I - 2.0*N *dot(N,I); 
            } 
            // 
            float2 R_To_UV(float3 r) 
            { 
                float interim = 2.0 * sqrt(r.x * r.x + r.y * r.y + (r.z + 1.0) * (r.z + 1.0));  
                return float2(r.x/interim+0.5,r.y/interim+0.5); 
            } 
             
            v2f vert (appdata_base v) 
            { 
                v2f o; 
                o.pos = mul(UNITY_MATRIX_MVP,v.vertex); 
                o.uv = TRANSFORM_TEX(v.texcoord,_MainTex); 
                 
                float3 posEyeSpace = mul(UNITY_MATRIX_MV,v.vertex).xyz; 
                float3 I = posEyeSpace - float3(0,0,0); 
                float3 N = mul((float3x3)UNITY_MATRIX_MV,v.normal); 
                N = normalize(N); 
                float3 R = reflect(I,N); 
                o.uv2 = R_To_UV(R); 
                return o; 
            } 
            float4 frag (v2f i) : COLOR 
            { 
                float4 reflectiveColor = tex2D(_Environment,i.uv2); 
                float4 decalColor = tex2D(_MainTex,i.uv); 
                float4 outp = lerp(decalColor,reflectiveColor,_Reflectivity); 
                return outp; 
            } 
            ENDCG 
        } 
    } 
 
} 


Cube Mapping


主流技术
优点:真正的反映环境,不受位置角度限制。
缺点:效率比起Sphere Mapping低不少
原理及 计算方法:
1 在世界坐标系中根据 I : 入射向量  和  N : 法线向量   计算出  R : 反射向量
R = I - 2 * N * dot(N,I)
2 再由R 使用 texCUBE进行纹理映射得到颜色
texCUBE ( _Environment , i . R );

Fixed and Fragment Shader代码
Shader "Custom/Texgen_CubeR_FragMine" { 
   Properties { 
           _Reflectivity ("Reflectivity", Range (0,1)) = 0.5 
        _MainTex("Base", 2D) = "white" 
        _Environment ("Environment", Cube) = "white" 
    } 
    SubShader { 
        Pass { 
            CGPROGRAM 
            #pragma vertex vert 
            #pragma fragment frag 
            #include "UnityCG.cginc" 
            sampler2D _MainTex; 
            samplerCUBE _Environment; 
            float4 _MainTex_ST; 
            float _Reflectivity; 
            struct v2f { 
                float4  pos : SV_POSITION; 
                float2  uv : TEXCOORD0; 
                float3  R:TEXCOORD1; 
            } ; 
            float3 reflect(float3 I,float3 N) 
            { 
                return I - 2.0*N *dot(N,I); 
            } 
            v2f vert (appdata_base v) 
            { 
                v2f o; 
                o.pos = mul(UNITY_MATRIX_MVP,v.vertex); 
                o.uv = TRANSFORM_TEX(v.texcoord,_MainTex); 
                 
                float3 posW = mul(_Object2World,v.vertex).xyz; 
                float3 I = posW -_WorldSpaceCameraPos.xyz; 
                float3 N = mul((float3x3)_Object2World,v.normal); 
                N = normalize(N); 
                o.R = reflect(I,N); 
                return o; 
            } 
            float4 frag (v2f i) : COLOR 
            { 
                float4 reflectiveColor = texCUBE(_Environment,i.R); 
                float4 decalColor = tex2D(_MainTex,i.uv); 
                float4 outp = lerp(decalColor,reflectiveColor,_Reflectivity); 
                return outp; 
            } 
            ENDCG 
        } 
    } 
 
} 






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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值