Shader 第二十四讲Reflection Mapping(转)

简介

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

贴图

鱼眼贴图普通贴图

Shader 第二十四讲Reflection Mapping(转)_第1张图片
Shader 第二十四讲Reflection Mapping(转)_第2张图片

效果

Shader 第二十四讲Reflection Mapping(转)_第3张图片
Shader 第二十四讲Reflection Mapping(转)_第4张图片

计算方法:

1 在摄像机坐标系中根据I:入射向量和N:法线向量计算出R:反射向量

R = I - 2 * N * dot(N,I)

2 再根据固定算法 由R计算出 uv

float2R_To_UV(float3r)

{

floatinterim=2.0*sqrt(r.x*r.x+r.y*r.y+(r.z+1.0)*(r.z+1.0));

returnfloat2(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

#pragmavertexvert

#pragmafragmentfrag

#include"UnityCG.cginc"

sampler2D_MainTex;

sampler2D_Environment;

float4_MainTex_ST;

float_Reflectivity;

structv2f{

float4pos:SV_POSITION;

float2uv:TEXCOORD0;

float2uv2:TEXCOORD1;

};

//I:入射向量N:法线向量R:反射向量

float3reflect(float3I,float3N)

{

returnI-2.0*N*dot(N,I);

}

//

float2R_To_UV(float3r)

{

floatinterim=2.0*sqrt(r.x*r.x+r.y*r.y+(r.z+1.0)*(r.z+1.0));

returnfloat2(r.x/interim+0.5,r.y/interim+0.5);

}

v2fvert(appdata_basev)

{

v2fo;

o.pos=mul(UNITY_MATRIX_MVP,v.vertex);

o.uv=TRANSFORM_TEX(v.texcoord,_MainTex);

float3posEyeSpace=mul(UNITY_MATRIX_MV,v.vertex).xyz;

float3I=posEyeSpace-float3(0,0,0);

float3N=mul((float3x3)UNITY_MATRIX_MV,v.normal);

N=normalize(N);

float3R=reflect(I,N);

o.uv2=R_To_UV(R);

returno;

}

float4frag(v2fi):COLOR

{

float4reflectiveColor=tex2D(_Environment,i.uv2);

float4decalColor=tex2D(_MainTex,i.uv);

float4outp=lerp(decalColor,reflectiveColor,_Reflectivity);

returnoutp;

}

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

#pragmavertexvert

#pragmafragmentfrag

#include"UnityCG.cginc"

sampler2D_MainTex;

samplerCUBE_Environment;

float4_MainTex_ST;

float_Reflectivity;

structv2f{

float4pos:SV_POSITION;

float2uv:TEXCOORD0;

float3R:TEXCOORD1;

};

float3reflect(float3I,float3N)

{

returnI-2.0*N*dot(N,I);

}

v2fvert(appdata_basev)

{

v2fo;

o.pos=mul(UNITY_MATRIX_MVP,v.vertex);

o.uv=TRANSFORM_TEX(v.texcoord,_MainTex);

float3posW=mul(_Object2World,v.vertex).xyz;

float3I=posW-_WorldSpaceCameraPos.xyz;

float3N=mul((float3x3)_Object2World,v.normal);

N=normalize(N);

o.R=reflect(I,N);

returno;

}

float4frag(v2fi):COLOR

{

float4reflectiveColor=texCUBE(_Environment,i.R);

float4decalColor=tex2D(_MainTex,i.uv);

float4outp=lerp(decalColor,reflectiveColor,_Reflectivity);

returnoutp;

}

ENDCG

}

}

}

你可能感兴趣的:(Shader 第二十四讲Reflection Mapping(转))