天天看点

CubeMap视线反射方向计算详解

其基本原理很多例子上有讲到。下面给出一些比较合适的链接

以上两位都适合opengl控。

本文给出一个dx hlsl例子。并解释了反射方向计算的数学模型。希望能给大家一定的帮助。

cube映射主要分为两步:

一、在vs中根据法线和观察位置计算反射方向,并且得到观察空间中的反射方向。

反射方向有两种计算方法。

1、在世界坐标系空间中计算,然后再将计算到的反射方向转换到观察空间。 这要求我们转入观察位置。

2、在观察空间中进行计算,此时观察位置已经为0,0,0,于是不需要传入观察位置,并且得到的向量即为所求。本文的代码采用此种方式。

值得说明的一点是。在进行计算时,入射方向和反射方向以及法线方向并未要求一定要单位化。

二、用这个反射方向在ps中对cube纹理进行采样。

下面是一个对反射向量计算的通用求解过程。

CubeMap视线反射方向计算详解

我们假设顶点位置为pos 即点o,视点为eye 即点a (均为同一坐标系空间)

那么,我们的观察方向便是pos-eye, 即ao。而我们的反射方向便是oc。 法线为ob或od方向。

下面我们来看看反射方向的求法

而由上图可知,oc = ad ;

而又由oa+ad = od;od = 2*ob;可得

 oc = 2*ob-oa;

而oa = eye-pos;

可得,oc = 2*ob-(eye-pos);

那么,最后我们可以看出,只要求出ob,则可以求出oc。

而从图上我们可以看到ob即为oa在(法线)od上的投影。 由此可知, ob = dot(oa,normal);

于是可以写出如下公式。

float3 eyer = eye - pos;  float3 reflectvec = 2*dot(eyer,normal)*normal - eyer;

当然,你也可以使用高级语言中的reflect函数来求反射

在hlsl中。

ret reflect(i, n)

上面的公式中。i为入射方向,v为反射方向,n为法线。

由于eyer 为观察方向的反方向,即入射方向的反方向

所以 reflectvec = reflect(-eyer,normal)即可求得。

最后将reflectvec转换到观察空间,然后对cube纹理进行采样即可。

下面是hlsl中我使用的代码。该代码在d3d sdk的hdrcubemap.fx中可见。

CubeMap视线反射方向计算详解

//vs

CubeMap视线反射方向计算详解

float4x4 matview;

CubeMap视线反射方向计算详解

float4x4 matprojection;

CubeMap视线反射方向计算详解

struct vs_input 

CubeMap视线反射方向计算详解

{

CubeMap视线反射方向计算详解

   float4 position : position0;

CubeMap视线反射方向计算详解

   float2 texcoord : texcoord0;

CubeMap视线反射方向计算详解

   float3 normal :normal;

CubeMap视线反射方向计算详解

};

CubeMap视线反射方向计算详解
CubeMap视线反射方向计算详解

struct vs_output 

CubeMap视线反射方向计算详解
CubeMap视线反射方向计算详解
CubeMap视线反射方向计算详解

   float3 texcoord : texcoord0;

CubeMap视线反射方向计算详解
CubeMap视线反射方向计算详解
CubeMap视线反射方向计算详解

vs_output vs_main( vs_input input )

CubeMap视线反射方向计算详解
CubeMap视线反射方向计算详解

   vs_output output;

CubeMap视线反射方向计算详解

   output.position = mul(input.position,matview);

CubeMap视线反射方向计算详解
CubeMap视线反射方向计算详解

   float3 vn = mul(input.normal,matview);

CubeMap视线反射方向计算详解

   float3 veyer = -normalize(output.position);

CubeMap视线反射方向计算详解
CubeMap视线反射方向计算详解

   output.texcoord = 2 * dot( veyer, vn ) * vn - veyer;

CubeMap视线反射方向计算详解
CubeMap视线反射方向计算详解

   output.position = mul(output.position,matprojection);

CubeMap视线反射方向计算详解

   return( output );

CubeMap视线反射方向计算详解

}

CubeMap视线反射方向计算详解
CubeMap视线反射方向计算详解

//ps

CubeMap视线反射方向计算详解

samplercube basemap;

CubeMap视线反射方向计算详解
CubeMap视线反射方向计算详解

struct ps_input 

CubeMap视线反射方向计算详解
CubeMap视线反射方向计算详解
CubeMap视线反射方向计算详解
CubeMap视线反射方向计算详解
CubeMap视线反射方向计算详解
CubeMap视线反射方向计算详解

float4 ps_main( ps_input input ) : color0

CubeMap视线反射方向计算详解
CubeMap视线反射方向计算详解

   return texcube( basemap, input.texcoord );

CubeMap视线反射方向计算详解
CubeMap视线反射方向计算详解
CubeMap视线反射方向计算详解

在此对float3 veyer = -normalize(output.position);作一下解释。

我们上面讲到的 eyer的计算为eye- pos。 但是,由于n和pos已转入摄相机空间。则此时的eye为(0,0,0)。 并且,不一定要单位化veyer 

所以上面的解法可以让你不用再传入观察点。

最后,我们来围观一下效果。

CubeMap视线反射方向计算详解
CubeMap视线反射方向计算详解

我是在rendermonkey中测试的shader,所以,上面贴出来的,即为原码。

下面是用到的cubemap图的样子

CubeMap视线反射方向计算详解

ok,谢谢欣赏,欢迎交流

gmail :boyuegame

简介:09年入行,喜欢游戏和编程,对3d游戏和引擎尤其感兴趣。 

版权声明:本文版权归作者和博客园共有,欢迎转载。转载必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

转载:http://www.cnblogs.com/geniusalex/archive/2011/01/07/1929667.html

继续阅读