Upload
-
View
758
Download
3
Embed Size (px)
Citation preview
8.1 Postprocessing Effects
in Design
http://ohyecloudy.com
http://cafe.naver.com/shader.cafe
2009.02.23
ShaderX5
Introduction
• 사용하는 Post-processing Effect가 증가.
– Color correction, depth-of-field, motion blur, night vision, HDR tone mapping…
• 확장이 쉽고 다양한 요구 사항에 유연하게 적응 가능한 framework를 제시.
The Goals
• Stability – 믿을 수 있고 일관된 결과.
• Robustness – 다른 시나리오와 이펙트에서 stability 보장.
• Extensibility – 이펙트 추가가 손쉬움.
• Performance – 가능한 최적, 효율적으로 동작.
• Flexibility – 풍부한 제어가 가능.
• Scalability – 지원하는 플랫폼에서 잠재적인 제한이 있더라도 잘 동작한다. – 예) 비디오 카드에 따라 다른 구성
The Design
Effect
Phase
Step
Step
Phase
구현이 필요한 파이프라인의 함수. 예) SetRenderTarget
Step의 그룹핑
HDR
Downsample scene texture
Set RenderTarget
Calculate luminance
Generate bright-pass
Bloom bright-pass
Tone-map and final composite
Draw Overlay
Set RenderTarget
Draw Overlay
Set RenderTarget
Draw Overlay
Set RenderTarget
Draw Overlay
Set RenderTarget
Draw Overlay
Set RenderTarget
Draw Overlay
Set RenderTarget
Draw Overlay
A Short Test Drive
<Effect Name="SepiaTone" Requirements="DX9“ Description="Output a Sepia-toned image."> <Phase Description=""> <Step Type="SetRenderTarget" Target="*CompositeOut" /> <Step Type="Overlay" ShaderTechnique="RenderSepiaTone"> <Texture Name="*CompositeIn" Alias="g_Texture"/> <Texture Name="Media/sepiatone.tga" Alias="g_DependantReadTexture" Type="File"/> <Param Name="Amout" Alias="g_fBlendAmout" Function="FadeIn"/> </Step> <Step Type="SetRenderTarget" Target="*Framebuffer"/> </Phase> </Effect>
A Short Test Drive
<Effect Name = "Output" Requirements = "DX9" Description = "Output the final results to the screen."> <Phase Description = ""> <Step Type = "SetRenderTarget" Target ="*Framebuffer" /> <Step Type = "Overlay" ShaderTechnique = "RenderScreenQuad"> <Texture Name = "*CompositeIn" Alias = "g_Texture" /> </Step> </Phase> </Effect>
Implementation Issue
A B
A
Night Vision
Sepia HDR Output
B B
B A
A
INPUT
OUTPUT
Disable Wrong!
Implementation Details
• Effect 활성 유무에 따라서 다음 Effect의 RenderTarget을 변경해주는 코드만 리뷰
– class CPostProcessTextureIoGroup
– void Enable( bool bEnable )
– void FixupTexturePointers()
– CRTTexture* FindRenderTarget( const char *strName )
class CPostProcessEffect { protected: // The list of effects phases. vector< CPostProcessEffectPhase * > m_Phases; // The list of user created render targets. vector< CRTTexture * > m_UserRenderTargets; // The effect file name. char *m_strFileName; // The effect name. char *m_strEffectName; // The next effect in the linked-list. CPostProcessEffect *m_pNext; // Whether this effect is enabled or not. bool m_bIsEnabled; // The current texture input/output group. CPostProcessTextureIoGroup *m_pCurIoGroup; // The original texture input/output group. CPostProcessTextureIoGroup m_OrigIoGroup; };
void CPostProcessEffect::Enable( bool bEnable ) // If we're disabling the effect. if ( !bEnable ) { CPostProcessEffect *pCurEffect = GetNext(); CPostProcessTextureIoGroup *pCurIoGroup = NULL; CPostProcessTextureIoGroup *pPrevIoGroup = GetCurIoGroup(); // For every active effect after this effect, // move the io groups forward to maintain // the proper texture io group mappings. for ( ; pCurEffect; pCurEffect = pCurEffect->GetNext() ) { if ( !pCurEffect->GetIsEnabled() ) { continue; } // Get the current io group. pCurIoGroup = pCurEffect->GetCurIoGroup(); // Set the current io group and fixup texture pointers. pCurEffect->SetCurIoGroup( pPrevIoGroup ); pCurEffect->FixupTexturePointers(); // Update the previous io group. pPrevIoGroup = pCurIoGroup; } }
void CPostProcessEffect::Enable( bool bEnable )
if ( bEnable ) { CPostProcessEffect *pCurEffect = CPostProcessEffectsSystem::m_pInstance->GetEffectsHead(); CPostProcessEffect *pNxtActiveEffectHead = pCurEffect; CPostProcessEffect *pNxtActiveEffect = NULL; // To enable the effect we need to traverse the entire effect list twice, // once moving forward through each original io groups, and second finding // the next active effect that we can give that io group to. for ( ; pCurEffect; pCurEffect = pCurEffect->GetNext() ) { // Where there are no more active effects we're done. if ( !pNxtActiveEffect ) { break; }
// Set the next active effects pNxtActiveEffect->SetCurIoGroup( (CPostProcessTextureIoGroup *)&pCurEffect->GetOrigIoGroup() ); pNxtActiveEffect->FixupTexturePointers(); } } // if ( bEnable )
// Fixup texture pointers. void CPPFXStep_Overlay::FixupTexturePointers() { if ( m_bIsLoadedFromFile ) return; CRTTexture *pRT = m_pParentStep->GetParentEffect()->FindRenderTarget( GetRefName() ); SetTexture( pRT ); }
// Fixup texture pointers. void CPPFXStep_SetRenderTarget::FixupTexturePointers() { CRTTexture *pRT = m_pParentEffect->FindRenderTarget( m_pRTRef->GetRefName() ); m_pRTRef->SetTexture( pRT ); }
CRTTexture *CPostProcessEffect::FindRenderTarget( const char *strName ) { if ( strcmp( strName, "*CompositeIn" ) == 0 ) { return m_pCurIoGroup->GetInput(); } else if ( strcmp( strName, "*CompositeOut" ) == 0 ) { return m_pCurIoGroup->GetOutput(); } vector< CRTTexture * >::iterator iterRT = m_UserRenderTargets.begin(); for ( ; iterRT != m_UserRenderTargets.end(); ++iterRT ) { if ( strcmp( (*iterRT)->GetName(), strName ) == 0 ) { return (*iterRT); } } return NULL; }
Conclusion
• Post processing effects는 텍스쳐를 바꾸어 가며 SetRenderTarget을 한다.
– 이 짓의 연속.
• 이 섹션에서 제시하는 Framework에서 확장성있고 변화에 유연한 Post processing effect 엔진 구현에 대한 힌트를 얻을 수 있다.