读书人

3DShader之立方体环境映射(cubic envi

发布时间: 2013-10-08 16:38:32 作者: rapoo

3DShader之立方体环境映射(cubic environment mapping)

前面讲了球形环境映射,然而目前采用更多的是立方体环境映射.国际惯例:上图先:

1.反射:

3DShader之立方体环境映射(cubic environment 地图ping)

2.折射

3DShader之立方体环境映射(cubic environment 地图ping)

3.fresnel(反射+折射)

3DShader之立方体环境映射(cubic environment 地图ping)

4.色散

3DShader之立方体环境映射(cubic environment 地图ping)


好了,大概讲下原理,

立方体纹理我就不多讲了,它以一个3维向量(x,y,z)为输入,然后比较x,y,z的绝对值,假设X的绝对值最大,但是X是负值,那么就找到-X那一面,用Y,Z的坐标X的绝对值得到2D纹理坐标(u,v)最后用(u,v)去-X面的图片去采样, 输出最后的颜色,

Which face to sample is determined by the sign of the coordinate having the
largest absolute value. The other two coordinates are divided by the largest coordinate
and remapped to the range [0,1] using the formulas listed in Table 7.1 to
produce 2D texture coordinates s′,t′ . These coordinates are then used to sample
the two-dimensional texture map for the corresponding face of the cube texture
map.


好了,讲下反射

3DShader之立方体环境映射(cubic environment 地图ping)

可以根据I和N算去R,然后用R去查找立方体贴图

公式为:R = I - 2N(NI)

折射

3DShader之立方体环境映射(cubic environment 地图ping)

这里是一次折射,理想情况下应该是两次折射,进去一次出来一次

3DShader之立方体环境映射(cubic environment 地图ping)

由于一次折射效果就行了而且比较简单,我们这里采用了一次折射

有个斯涅尔定律(Snell's law)对折射非常重要

3DShader之立方体环境映射(cubic environment 地图ping)

折射的推导公式为:

3DShader之立方体环境映射(cubic environment 地图ping)

公式为:

如果I不是单位化的,可以先单位化下再算,最后算出T的长度再乘以I的长度就得到最终的T

或者用书上的另一方法来推导也行

3DShader之立方体环境映射(cubic environment 地图ping)

3DShader之立方体环境映射(cubic environment 地图ping)

3DShader之立方体环境映射(cubic environment 地图ping)

3DShader之立方体环境映射(cubic environment 地图ping)


fresnel(折射+反射)

菲涅尔效应(Fresnel Effect):当光到达材质的交界面时,一部分光被反射,而另一部分将发生折射,这个现象称为Fresnel Effect.


那么这两个部分占的比重如何去确定呢?

一般来说,当入射光线与法向量重合时,这时反射应占主导,当成180度时,折射应占主导.

这里有一个近似的公式,我们不追求物理上的精确,只要效果行就OK.

3DShader之立方体环境映射(cubic environment 地图ping)

3DShader之立方体环境映射(cubic environment 地图ping)


Chromatic Dispersion(色散):


refraction depends on the
surface normal, incident angle, and ratio of indices of refraction.In addition to these factors, the amount of
refraction also depends on the wavelength of the incident light. For example, red light gets refracted more
than blue light. This phenomenon is known as chromatic dispersion, and it is what happens when white light
enters a prism and emerges as a rainbow.

色散是基于不同波长的光在介质中折射率不同而产生的,这里我们只模拟算红,绿,蓝三种不同光的折射率

3DShader之立方体环境映射(cubic environment 地图ping)


呵呵,原理大概就是这样了.


得抓紧了,多写几个shader,为自己的海洋打下坚实基础,最近我可能会写一个水面(牵涉到RRT),还有投影纹理,还有移位贴图(displacement mapping),敬请期待吧3DShader之立方体环境映射(cubic environment 地图ping)


对了,差点了贴源代码了:

/*--------------------------------------CubeEnvMapping.fx -- cubic environment mapping shader (c) Seamanj.2013/8/28--------------------------------------*///--------------------------------------------------// Global variables//--------------------------------------------------float4x4 g_mWorldViewProj;float4x4 g_mWorld;float4x4 g_mWorldInv;float3 g_eyePosition;texture g_txCubeEnvMap;float g_fEtaRatio;float g_fFresnelBias;float g_fFresnelScale;float g_fFresnelPower;float3 g_fRGBEtaRatio;//-----------------------------------------// Sampler//-----------------------------------------samplerCUBE g_samCubeEnvMap =sampler_state{    Texture = <g_txCubeEnvMap>;    MinFilter = Linear;    MagFilter = Linear;    MipFilter = Linear;};//--------------------------------------------------// Vertex shader output structure//--------------------------------------------------struct Reflection_VS_Output {  float4 position : POSITION;  float3 Reflection : TEXCOORD0;};//--------------------------------------------------// Vertex shader//--------------------------------------------------Reflection_VS_Output ReflectionVertexEntry(float4 position : POSITION,float3 normal : NORMAL){  Reflection_VS_Output OUT;  OUT.position = mul ( position, g_mWorldViewProj);  normal = mul ( normal, transpose((float3x3)g_mWorldInv));  normal = normalize(normal);  float3 positionW = mul(position, g_mWorld).xyz;  float3 I = positionW - g_eyePosition;  OUT.Reflection = reflect(I, normal);  return OUT;}struct Refraction_VS_Output {  float4 position : POSITION;  float3 Refraction : TEXCOORD0;};Refraction_VS_Output RefractionVertexEntry(float4 position : POSITION,float3 normal : NORMAL){  Refraction_VS_Output OUT;  OUT.position = mul ( position, g_mWorldViewProj);  normal = mul ( normal, transpose((float3x3)g_mWorldInv));  normal = normalize(normal);  float3 positionW = mul(position, g_mWorld).xyz;  float3 I = positionW - g_eyePosition;  OUT.Refraction = refract(I, normal, g_fEtaRatio);  return OUT;}struct Fresnel_VS_Output {  float4 position : POSITION;  float reflectionFactor : COLOR;  float3 Reflection : TEXCOORD0;  float3 Refraction : TEXCOORD1;};Fresnel_VS_Output FresnelVertexEntry(float4 position : POSITION,float3 normal : NORMAL){  Fresnel_VS_Output OUT;  OUT.position = mul ( position, g_mWorldViewProj);  normal = mul ( normal, transpose((float3x3)g_mWorldInv));  normal = normalize(normal);  float3 positionW = mul(position, g_mWorld).xyz;  float3 I = positionW - g_eyePosition;  OUT.reflectionFactor = g_fFresnelBias + g_fFresnelScale * pow(1 + dot(I, normal), g_fFresnelPower);  OUT.Reflection = reflect(I, normal);  OUT.Refraction = refract(I, normal, g_fEtaRatio);  return OUT;}struct Dispersion_VS_Output {  float4 position : POSITION;  float reflectionFactor : COLOR;  float3 Reflection : TEXCOORD0;  float3 RedRefraction : TEXCOORD1;  float3 GreenRefraction : TEXCOORD2;  float3 BlueRefraction : TEXCOORD3;};Dispersion_VS_Output DispersionVertexEntry(float4 position : POSITION,float3 normal : NORMAL){  Dispersion_VS_Output OUT;  OUT.position = mul ( position, g_mWorldViewProj);  normal = mul ( normal, transpose((float3x3)g_mWorldInv));  normal = normalize(normal);  float3 positionW = mul(position, g_mWorld).xyz;  float3 I = positionW - g_eyePosition;  OUT.reflectionFactor = g_fFresnelBias + g_fFresnelScale * pow(1 + dot(I, normal), g_fFresnelPower);  OUT.Reflection = reflect(I, normal);  OUT.RedRefraction = refract(I, normal, g_fRGBEtaRatio.x);  OUT.GreenRefraction = refract(I, normal, g_fRGBEtaRatio.y);  OUT.BlueRefraction = refract(I, normal, g_fRGBEtaRatio.z);  return OUT;}//--------------------------------------------------// Pixel shader//--------------------------------------------------float4 ReflectionPixelEntry(float3 Reflection : TEXCOORD0) : COLOR{return texCUBE(g_samCubeEnvMap, Reflection);}float4 RefractionPixelEntry(float3 Refraction : TEXCOORD0) : COLOR{return texCUBE(g_samCubeEnvMap, Refraction);}float4 FresnelPixelEntry(float reflectionFactor : COLOR,float3 Reflection : TEXCOORD0,float3 Refraction : TEXCOORD1) : COLOR{float4 reflectedColor = texCUBE(g_samCubeEnvMap, Reflection);float4 refractedColor = texCUBE(g_samCubeEnvMap, Refraction);float4 color = lerp( refractedColor, reflectedColor, reflectionFactor );return color;}float4 DispersionPixelEntry(float reflectionFactor : COLOR,float3 Reflection : TEXCOORD0,float3 RedRefraction : TEXCOORD1,float3 GreenRefraction : TEXCOORD2,float3 BlueRefraction : TEXCOORD3) : COLOR{float4 reflectedColor = texCUBE(g_samCubeEnvMap, Reflection);float4 refractedColor;refractedColor.x = texCUBE(g_samCubeEnvMap, RedRefraction).x;refractedColor.y = texCUBE(g_samCubeEnvMap, GreenRefraction).y;refractedColor.z = texCUBE(g_samCubeEnvMap, BlueRefraction).z;refractedColor.w = 1;float4 color = lerp( refractedColor, reflectedColor, reflectionFactor );return color;}//--------------------------------------------------// Renders scene to render target//--------------------------------------------------technique ReflectionTechnique{    pass P0    {                  VertexShader = compile vs_2_0 ReflectionVertexEntry();        PixelShader = compile ps_2_0 ReflectionPixelEntry();    }}technique RefractionTechnique{    pass P0    {                  VertexShader = compile vs_2_0 RefractionVertexEntry();        PixelShader = compile ps_2_0 RefractionPixelEntry();    }}technique FresnelTechnique{    pass P0    {                  VertexShader = compile vs_2_0 FresnelVertexEntry();        PixelShader = compile ps_2_0 FresnelPixelEntry();    }}technique DispersionTechnique{    pass P0    {                  VertexShader = compile vs_2_0 DispersionVertexEntry();        PixelShader = compile ps_2_0 DispersionPixelEntry();    }}


可执行程序以及相关源代码请点击这里下载

读书人网 >其他相关

热点推荐