Unity3D教程宝典之Shader篇:第二十四讲Reflection Mapping

转载自风宇冲Unity3D教程学院

简介

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.即使没有鱼眼贴图,用普通贴图也有一定的类似效果。

贴图

鱼眼贴图                                       普通贴图

    


效果
       

计算方法:

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
        }
    }
}

  

时间: 2024-10-11 03:53:41

Unity3D教程宝典之Shader篇:第二十四讲Reflection Mapping的相关文章

Unity3D教程宝典之Shader篇:第四讲制作一个美丽的地球

原创文章如需转载请注明:转载自风宇冲Unity3D教程学院 Vertex and Fragment Shader例子二,制作一个自动旋转的3D地球. 下载美丽的地球工程 原理是 2张贴图,一张地球图,一张云层分布图(1)通过uv.x即纹理坐标的横轴与时间相乘,产生球在移动的效果 (2)通过地球和云的颜色值叠加形成 层叠 的效果.注意:贴图的'Wrap Mode'属性一定要设置成Repeat                              关于Wrap Mode当Wrap Mode为Cl

Unity3D教程宝典之Shader篇:第六讲TexGen

转载自风宇冲Unity3D教程学院 介绍 TexGen全称是Texture coordinate generation,即纹理坐标生成.本来模型的纹理坐标是在做模型的时候赋予各个顶点的.但是有时模型表面非常复杂,或者要做一些特效时,就需要其他方法来生成纹理坐标. TexGen主要用于Fixed Function Shader. 有如下模式ObjectLinear, EyeLinear, SphereMap, CubeReflect, CubeNormal .  该函数直接对应OpenGL的tex

Unity3D教程宝典之Shader篇:第八讲 Why CG?

转载自风宇冲Unity3D教程学院 Shader有Fixed Function, Vertex and Fragment, Surface, 而Vertex and Fragmen里又有CG和GLSL两种.为什么选CG做重点讲解呢? Fixed Function:老式的固定管线,实现功能有限,不必多说.CG:跨平台首选,Unity3d能直接把CG编译成GLSL.GLSL:支持Mac,iOS,安卓.不支持Windows.Unity3d不能把GLSL编译成CG.不适合广泛的跨平台.Surface:属

Unity3D教程宝典之Shader篇:第十一讲剔除及深度测试

转载自风宇冲Unity3D教程学院 Culling阴影面剔除 Culling阴影面剔除是一种优化技术.所有的多边形都有正反两面,而你永远只能看见其中一面,不信的话拿张纸板或者一面镜子看看你能不能同时看到两面.通常多边形面向屏幕里面的背面,我们看不见,所以会将该面剔除. Cull Off 关闭阴影面剔除 Cull Back 剔除背面 Cull Front 剔除正面 Depth Testing深度测试 Depth Testing:深度测试,也叫深度缓冲.只有最靠近观察者的物体会被绘制.深度即Z,该值

Unity3D教程宝典之Shader篇:第七讲流程图

转载自风宇冲Unity3D教程学院 步骤如图: 图一:坐标系变换图二:流水线图形图三:Unity3D渲染流程图四:光栅操作(又名光栅化操作) 图一:坐标系变换图二:流水线图形 图三:Unity3D渲染流程 图四:光栅操作

Unity3D教程宝典之Shader篇:第十七讲Heightmap与地形

转载自风宇冲Unity3D教程学院 Heightmap Heightmap, 高度图.通常Heightmap高度图储存成Gray Scale Image也就是常说灰度图.越白该点就越高,纯黑表示最低点,纯点表示最高点. 8位灰度图有256阶.16位灰度图有65536阶.如果依然精度不够用的话(例如绘制大型场景),那么可以使用标准的RGB位图来储存高度图,那么精度就是256的3次方=16777216阶.同理还可以再升为RGBA. Heightmap可以用3D软件(Unity的地形也可以)来绘制,或

Unity3D教程宝典之光影烘焙:第四讲脚本控制

上一讲讲了用Light probes实现动态物体的非实时阴影,这一讲讲用代码实现代码实现动态物体的非实时阴影. 实现步骤:(1)新建一个场景,并建一个plane作为大地(2)创建Cube并缩放成扁平面后.复制Cube并旋转拼接搭建成一个敞篷.(3)讲上述物体设置static并烘焙.(4)创建一个player.这里用的unity自带的Character Controller包里的 3rd person controller这个prefab,拖进敞篷边.在该人物下找到Bip001 Pelvis这个节

Unity3D教程宝典之Shader篇

教程目录 基础讲:Shader学习方法基础讲:基础知识特别讲:常见问题解答特别讲:CG函数 第一讲: Shader总篇第二讲: Fixed Function Shader 第三讲: Vertex&Fragment Shader基础 第四讲: 制作一个美丽的地球第五讲:LOGO闪光效果 第六讲:TexGen第七讲:流程图第八讲:Why CG?第九讲:Render Path第十讲:雾化第十一讲:阴影面剔除及深度测试第十二讲:alpha测试第十三讲:alpha混合第十四讲:Surface Shader

Unity3D教程宝典之Shader篇:第十二讲 Alpha测试

转载自风宇冲Unity3D教程学院 引言:本讲和下一讲主要讲Alpha即透明通道有关的内容.RGBA,其中最终在屏幕上显示的只有RGB即 红绿蓝组成的颜色,Alpha并没有任何颜色显示.A只是辅助颜色运算特别是多图层运算而已.例如在单图层的情况下(1,1,1,0.8)输出的是(1,1,1)*0.8即 浅灰色(0.8,0.8,0.8),和(0.8,0.8,0.8)是等价的.但是假如不再是单图层而背景为绿色(0,1,0,1)的时候,(0.8,0.8,0.8)就不知道怎么去运算了,而(1,1,1,0.