DX9 Update中的HDRLighting Sample分析 (2) (轉)
DX9 Update中的HDRLighting Sample分析 (2) (轉)[@more@] DX9 Update中的HDRLighting Sample分析 (2)
上一篇我們分析到得出了場景的平均亮度值。下面如果我們不打算做Star和Bloom效果的話,我們可以直接使用這個亮度值來進行我們最後的調整,獲得最後的畫面。但是如果HDR缺少了Star和Bloom或類似的效果的話,就如同太陽失去了光芒一樣。不過在進行我們的Star和Bloom效果處理之前還有一個問題需要解決,這個問題和這些效果沒什麼關係。我們知道我們的眼睛當遇到強光的時候,並不是一下子就能適應,而是有個漸進的過程。如果我們的沒有這個處理的話,將會失色很多。也就是說兩個亮度值之間需要有個過渡的變化。我們如何做到這一點呢?
fNewAdaptation = fAdaptedLum + (fCurrentLum - fAdaptedLum) * ( 1 - pow( 0.98f, 30 * g_fElapsedTime ) );
上面的就是我們計算過渡亮度值的公式,fCurrentLum是我們的目標的亮度值,fAdaptedLum是上一楨的亮度值,我們在每次計算的時候,一般是保持fCurrentLum,上一次計算的fNewAdaptation作為這次計算的fAdaptedLum,這樣我們就能做到逐步的接近我們的最終結果fCurrentLum。而我們把每楨計算得出的fNewAdaptation作為我們調整顏色用的亮度值。
讓我們來具體的看看程式碼
if( m_bAdaptationInvalid )
{
// Clear the update flag
m_bAdaptationInvalid = false;
// Calculate the current luminance adaptation level
CalculateAdaptation();
}
這裡的if( m_bAdaptationInvalid )並不起作用,因為在FrameMove()內都m_bAdaptationInvalid設定成了true.也就是說每楨都CalculateAdaptation();我們來看看著個函式是如何實現上面說得那樣的計算:
HRESULT CMyD3DApplication::CalculateAdaptation()
{
HRESULT hr = S_OK;
UINT uiPass, uiPasunt;
// S current & last luminance
PDIRECT3DTEXTURE9 pTexSwap = m_pTexAdaptedLuminanceLast;
m_pTexAdaptedLuminanceLast = m_pTexAdaptedLuminanceCur;
m_pTexAdaptedLuminanceCur = pTexSwap;
這裡可以看到每楨都了Cur和Last,將上楨的結果作為這一楨的輸入引數
m_pEffect->SetTechnique("CalculateAdaptedLum");
m_pEffect->SetFloat("g_fElapsedTime", m_fElapsedTime);
m_pd3dDevice->SetRenderTarget(0, pSurfAdaptedLum);
m_pd3dDevice->SetTexture(0, m_pTexAdaptedLuminanceLast);
m_pd3dDevice->SetTexture(1, m_apTexToneMap[0]);
m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT );
m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT );
m_pd3dDevice->SetSamplerState( 1, D3DSAMP_MAGFILTER, D3DTEXF_POINT );
m_pd3dDevice->SetSamplerState( 1, D3DSAMP_MINFILTER, D3DTEXF_POINT );
這裡m_apTexToneMap(0)就是我們的最終的目標亮度值,這裡用到的shader的程式碼如下
float4 CalculateAdaptedLum(in float2 vScreenPosition : TEXCOORD0) : COLOR
{
float fAdaptedLum = tex2D(s0, float2(0.5f, 0.5f));
float fCurrentLum = tex2D(s1, float2(0.5f, 0.5f));
// The user's adapted luminance level is simulated by closing the gap between
// adapted luminance and current luminance by 2% every frame, based on a
// 30 fps rate. This is not an accurate model of human adaptation, which can
// take longer than half an hour.
float fNewAdaptation = fAdaptedLum + (fCurrentLum - fAdaptedLum) *
( 1 - pow( 0.98f, 30 * g_fElapsedTime ) );
return float4(fNewAdaptation, fNewAdaptation, fNewAdaptation, 1.0f);
}
這裡就是使用上面說到的公式來計算我們當前的亮度值
}
透過上面的計算,我們在最後使用的亮度值儲存在了m_pTexAdaptedLuminanceCur裡面。
接下來我們就準備開始獲得Star和Bloom效果了.首先我們需要將場景中特別亮的畫素給提取出來。
SceneScaled_To_BrightPass();
這個函式就是獲得我們Star和Bloom所需要的來源貼圖.我們來看看著個函式的內部實現
HRESULT CMyD3DApplication::SceneScaled_To_BrightPass()
{
....
m_pEffect->SetTechnique("BrightPasilter");
m_pd3dDevice->SetRenderTarget( 0, pSurfBrightPass );
m_pd3dDevice->SetTexture( 0, m_pTexSceneScaled );
m_pd3dDevice->SetTexture( 1, m_pTexAdaptedLuminanceCur );
m_pd3dDevice->SetRenderState( D3DRS_SCISSORTESTENABLE, TRUE );
m_pd3dDevice->SetScissorRect( &rectDest );
m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT );
m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT );
m_pd3dDevice->SetSamplerState( 1, D3DSAMP_MINFILTER, D3DTEXF_POINT );
m_pd3dDevice->SetSamplerState( 1, D3DSAMP_MAGFILTER, D3DTEXF_POINT );
我們使用剛剛計算得出的m_pTexAdaptedLuminanceCur(如果跳過模擬過渡的階段,這裡應該使用m_apTexToneMap(0))和m_pTexSceneScaled作為我們的引數,計算後的只剩下我們需要的亮度資訊儲存pSurfBrightPass,我們來看看這裡用到的shader的操作
float4 BrightPassFilter(in float2 vScreenPosition : TEXCOORD0) : COLOR
{
float4 vSample = tex2D( s0, vScreenPosition );
float fAdaptedLum = tex2D( s1, float2(0.5f, 0.5f) );
// Detene what the pixel's value will be after tone-map occurs
vSample.rgb *= g_fMiddleGray/(fAdaptedLum + 0.001f);
// Subtract out dark pixels
vSample.rgb -= BRIGHT_PASS_THRESHOLD;
// Clamp to 0
vSample = max(vSample, 0.0f);
// Map the resulting value into the 0 to 1 range. Higher values for
// BRIGHT_PASS_OFFSET will isolate lights from illuminated scene
// s.
vSample.rgb /= (BRIGHT_PASS_OFFSET+vSample);
return vSample;
}
這裡透過-BRIGHT_PASS_THRESHOLD和Clamp to 0我們就得到了只剩下我們需要的畫素亮度值得Texture了
}
上一篇我們分析到得出了場景的平均亮度值。下面如果我們不打算做Star和Bloom效果的話,我們可以直接使用這個亮度值來進行我們最後的調整,獲得最後的畫面。但是如果HDR缺少了Star和Bloom或類似的效果的話,就如同太陽失去了光芒一樣。不過在進行我們的Star和Bloom效果處理之前還有一個問題需要解決,這個問題和這些效果沒什麼關係。我們知道我們的眼睛當遇到強光的時候,並不是一下子就能適應,而是有個漸進的過程。如果我們的沒有這個處理的話,將會失色很多。也就是說兩個亮度值之間需要有個過渡的變化。我們如何做到這一點呢?
fNewAdaptation = fAdaptedLum + (fCurrentLum - fAdaptedLum) * ( 1 - pow( 0.98f, 30 * g_fElapsedTime ) );
上面的就是我們計算過渡亮度值的公式,fCurrentLum是我們的目標的亮度值,fAdaptedLum是上一楨的亮度值,我們在每次計算的時候,一般是保持fCurrentLum,上一次計算的fNewAdaptation作為這次計算的fAdaptedLum,這樣我們就能做到逐步的接近我們的最終結果fCurrentLum。而我們把每楨計算得出的fNewAdaptation作為我們調整顏色用的亮度值。
讓我們來具體的看看程式碼
if( m_bAdaptationInvalid )
{
// Clear the update flag
m_bAdaptationInvalid = false;
// Calculate the current luminance adaptation level
CalculateAdaptation();
}
這裡的if( m_bAdaptationInvalid )並不起作用,因為在FrameMove()內都m_bAdaptationInvalid設定成了true.也就是說每楨都CalculateAdaptation();我們來看看著個函式是如何實現上面說得那樣的計算:
HRESULT CMyD3DApplication::CalculateAdaptation()
{
HRESULT hr = S_OK;
UINT uiPass, uiPasunt;
// S current & last luminance
PDIRECT3DTEXTURE9 pTexSwap = m_pTexAdaptedLuminanceLast;
m_pTexAdaptedLuminanceLast = m_pTexAdaptedLuminanceCur;
m_pTexAdaptedLuminanceCur = pTexSwap;
這裡可以看到每楨都了Cur和Last,將上楨的結果作為這一楨的輸入引數
m_pEffect->SetTechnique("CalculateAdaptedLum");
m_pEffect->SetFloat("g_fElapsedTime", m_fElapsedTime);
m_pd3dDevice->SetRenderTarget(0, pSurfAdaptedLum);
m_pd3dDevice->SetTexture(0, m_pTexAdaptedLuminanceLast);
m_pd3dDevice->SetTexture(1, m_apTexToneMap[0]);
m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT );
m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT );
m_pd3dDevice->SetSamplerState( 1, D3DSAMP_MAGFILTER, D3DTEXF_POINT );
m_pd3dDevice->SetSamplerState( 1, D3DSAMP_MINFILTER, D3DTEXF_POINT );
這裡m_apTexToneMap(0)就是我們的最終的目標亮度值,這裡用到的shader的程式碼如下
float4 CalculateAdaptedLum(in float2 vScreenPosition : TEXCOORD0) : COLOR
{
float fAdaptedLum = tex2D(s0, float2(0.5f, 0.5f));
float fCurrentLum = tex2D(s1, float2(0.5f, 0.5f));
// The user's adapted luminance level is simulated by closing the gap between
// adapted luminance and current luminance by 2% every frame, based on a
// 30 fps rate. This is not an accurate model of human adaptation, which can
// take longer than half an hour.
float fNewAdaptation = fAdaptedLum + (fCurrentLum - fAdaptedLum) *
( 1 - pow( 0.98f, 30 * g_fElapsedTime ) );
return float4(fNewAdaptation, fNewAdaptation, fNewAdaptation, 1.0f);
}
這裡就是使用上面說到的公式來計算我們當前的亮度值
}
透過上面的計算,我們在最後使用的亮度值儲存在了m_pTexAdaptedLuminanceCur裡面。
接下來我們就準備開始獲得Star和Bloom效果了.首先我們需要將場景中特別亮的畫素給提取出來。
SceneScaled_To_BrightPass();
這個函式就是獲得我們Star和Bloom所需要的來源貼圖.我們來看看著個函式的內部實現
HRESULT CMyD3DApplication::SceneScaled_To_BrightPass()
{
....
m_pEffect->SetTechnique("BrightPasilter");
m_pd3dDevice->SetRenderTarget( 0, pSurfBrightPass );
m_pd3dDevice->SetTexture( 0, m_pTexSceneScaled );
m_pd3dDevice->SetTexture( 1, m_pTexAdaptedLuminanceCur );
m_pd3dDevice->SetRenderState( D3DRS_SCISSORTESTENABLE, TRUE );
m_pd3dDevice->SetScissorRect( &rectDest );
m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT );
m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT );
m_pd3dDevice->SetSamplerState( 1, D3DSAMP_MINFILTER, D3DTEXF_POINT );
m_pd3dDevice->SetSamplerState( 1, D3DSAMP_MAGFILTER, D3DTEXF_POINT );
我們使用剛剛計算得出的m_pTexAdaptedLuminanceCur(如果跳過模擬過渡的階段,這裡應該使用m_apTexToneMap(0))和m_pTexSceneScaled作為我們的引數,計算後的只剩下我們需要的亮度資訊儲存pSurfBrightPass,我們來看看這裡用到的shader的操作
float4 BrightPassFilter(in float2 vScreenPosition : TEXCOORD0) : COLOR
{
float4 vSample = tex2D( s0, vScreenPosition );
float fAdaptedLum = tex2D( s1, float2(0.5f, 0.5f) );
// Detene what the pixel's value will be after tone-map occurs
vSample.rgb *= g_fMiddleGray/(fAdaptedLum + 0.001f);
// Subtract out dark pixels
vSample.rgb -= BRIGHT_PASS_THRESHOLD;
// Clamp to 0
vSample = max(vSample, 0.0f);
// Map the resulting value into the 0 to 1 range. Higher values for
// BRIGHT_PASS_OFFSET will isolate lights from illuminated scene
// s.
vSample.rgb /= (BRIGHT_PASS_OFFSET+vSample);
return vSample;
}
這裡透過-BRIGHT_PASS_THRESHOLD和Clamp to 0我們就得到了只剩下我們需要的畫素亮度值得Texture了
}
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-963732/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- A Simple Sample for Expression Tree (轉)Express
- 專案財務分析中的陷阱(2)(轉)
- Oracle中的for update 和 for update nowaitOracleAI
- For Update 加鎖分析
- DB2中安裝sample資料庫和TOLLSDB資料庫DB2資料庫
- Oracle 12CR2 Install the Sample SchemasOracle
- 專案管理過程中的問題分析方法2(轉)專案管理
- MybatisPlus中的update操作MyBatis
- oracle中update的細節Oracle
- 徹底玩轉你的Windows Update(轉)Windows
- Javacc sampleJava
- (轉)資料庫oracle for update of和for update區別資料庫Oracle
- Oracle中select ... for update的用法Oracle
- SPAM/SAINT update(轉載)AI
- sample a texture as a rendertarget
- netty sampleNetty
- oracle 11g中auto_sample_size是如何工作的Oracle
- Update時間過慢效能分析
- sample, choices: 從list中隨機選擇無重複的元素隨機
- MySQL update一個詭異現象的分析--個人未分析出MySql
- table type usage sample:
- MySQL中UPDATE語句裡SET後使用AND的執行過程和結果分析MySql
- 關於unity中的update、Lateupdate和FixedUpdateUnity
- SVG中的動畫技術(2) (轉)SVG動畫
- 貪吃蛇的演算法分析(2) (轉)演算法
- GreatSQL執行Update失敗案例分析SQL
- 更新、插入資料庫所使用的UPDATE() (轉)資料庫
- UPDATE注射(mysql+php)的兩個模式(轉)MySqlPHP模式
- 我眼中的 Nginx(二):HTTP/2 dynamic table size updateNginxHTTP
- ArrayList分析2 :Itr、ListIterator以及SubList中的坑
- Oracle 自己帶的Sample Sechemas 介紹Oracle
- Error in Memento Sample Code?Error
- For Update操作分析——不同Oracle版本之間的差異研究Oracle
- 財務分析中的五力分析法(轉載)
- 企業中的專案管理2(轉)專案管理
- JavaScript中的正規表示式(2) (轉)JavaScript
- ORACLE UPDATE 語句語法與效能分析Oracle
- 專案財務分析中的陷阱(1)(轉)