天天看點

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

繼續閱讀