其基本原理很多例子上有講到。下面給出一些比較合适的連結
以上兩位都适合opengl控。
本文給出一個dx hlsl例子。并解釋了反射方向計算的數學模型。希望能給大家一定的幫助。
cube映射主要分為兩步:
一、在vs中根據法線和觀察位置計算反射方向,并且得到觀察空間中的反射方向。
反射方向有兩種計算方法。
1、在世界坐标系空間中計算,然後再将計算到的反射方向轉換到觀察空間。 這要求我們轉入觀察位置。
2、在觀察空間中進行計算,此時觀察位置已經為0,0,0,于是不需要傳入觀察位置,并且得到的向量即為所求。本文的代碼采用此種方式。
值得說明的一點是。在進行計算時,入射方向和反射方向以及法線方向并未要求一定要機關化。
二、用這個反射方向在ps中對cube紋理進行采樣。
下面是一個對反射向量計算的通用求解過程。
我們假設頂點位置為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中可見。
//vs
float4x4 matview;
float4x4 matprojection;
struct vs_input
{
float4 position : position0;
float2 texcoord : texcoord0;
float3 normal :normal;
};
struct vs_output
float3 texcoord : texcoord0;
vs_output vs_main( vs_input input )
vs_output output;
output.position = mul(input.position,matview);
float3 vn = mul(input.normal,matview);
float3 veyer = -normalize(output.position);
output.texcoord = 2 * dot( veyer, vn ) * vn - veyer;
output.position = mul(output.position,matprojection);
return( output );
}
//ps
samplercube basemap;
struct ps_input
float4 ps_main( ps_input input ) : color0
return texcube( basemap, input.texcoord );
在此對float3 veyer = -normalize(output.position);作一下解釋。
我們上面講到的 eyer的計算為eye- pos。 但是,由于n和pos已轉入攝相機空間。則此時的eye為(0,0,0)。 并且,不一定要機關化veyer
是以上面的解法可以讓你不用再傳入觀察點。
最後,我們來圍觀一下效果。
我是在rendermonkey中測試的shader,是以,上面貼出來的,即為原碼。
下面是用到的cubemap圖的樣子
ok,謝謝欣賞,歡迎交流
gmail :boyuegame
簡介:09年入行,喜歡遊戲和程式設計,對3d遊戲和引擎尤其感興趣。
版權聲明:本文版權歸作者和部落格園共有,歡迎轉載。轉載必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。
轉載:http://www.cnblogs.com/geniusalex/archive/2011/01/07/1929667.html