Рендеринг в расширенном динамическом диапазоне в XNA. Часть 3.

Добавление свечения к сцене карты тона:

Последний шаг для применения эффекта рендеринга в расширенном динамическом диапазоне – объединение эффекта свечения и карты тона, даже если шаг с применением эффекта тона пропущен:

Код для суммирования RGB каналов двух текстур:

texture2D SourceTexture1; 
texture2D SourceTexture2; 
sampler2D SourceTexture1Sampler = sampler_state 
{ 
 Texture = <SourceTexture1>; 
 MinFilter = LINEAR; 
 MagFilter = LINEAR; 
 MipFilter = LINEAR; 
 MaxAnisotropy = 1; 
 AddressU = CLAMP; 
 AddressV = CLAMP; 
}; 
sampler2D SourceTexture2Sampler = sampler_state 
{ 
 Texture = <SourceTexture2>; 
 MinFilter = LINEAR; 
 MagFilter = LINEAR; 
 MipFilter = LINEAR; 
 MaxAnisotropy = 1; 
 AddressU = CLAMP; 
 AddressV = CLAMP; 
}; 
struct VS_OUTPUT 
{ 
 float4 Position : POSITION; 
 float2 TexCoord : TEXCOORD0; 
}; 
VS_OUTPUT Common_VS(float4 Position : POSITION, 
 float2 TexCoord : TEXCOORD0) 
{ 
 VS_OUTPUT OUT; 
 OUT.Position = Position; 
 OUT.TexCoord = TexCoord; 
 return OUT; 
} 
float4 AddRGB_PS(float2 texCoord : TEXCOORD0) : COLOR0 
{ 
 float4 color = tex2D(SourceTexture1Sampler, texCoord); 
 color.rgb += tex2D(SourceTexture2Sampler, texCoord).rgb; 
 return color; 
} 
technique AddRGB 
{ 
 pass p0 
 { 
 VertexShader = compile vs_1_1 Common_VS(); 
 PixelShader = compile ps_2_0 AddRGB_PS(); 
 } 
}
public sealed class AddRGB : PostProcessEffect 
{ 
 private Effect _Effect = null; 
 private EffectParameter Parameter_SourceTexture = null; 
 private EffectParameter Parameter_OtherTexture = null; 
 public AddRGB(GraphicsDevice graphicsDevice, ContentManager content) 
 : base(graphicsDevice) 
 { 
 _Effect = content.Load<Effect>("Effects/AddRGB"); 
 Parameter_SourceTexture = _Effect.Parameters["SourceTexture1"]; 
 Parameter_OtherTexture = _Effect.Parameters["SourceTexture2"]; 
 } 
 public Texture2D OtherTexture 
 { 
 get 
 { 
 return Parameter_OtherTexture.GetValueTexture2D(); 
 } 
 set 
 { 
 Parameter_OtherTexture.SetValue(value); 
 } 
 } 
 public override void PostProcess(Texture2D sourceTexture, 
 RenderTarget2D result) 
 { 
 Parameter_SourceTexture.SetValue(sourceTexture); 
 _GraphicsDevice.SetRenderTarget(0, result); 
 _GraphicsDevice.Clear(Color.Black); 
 DrawQuad(_Effect); 
 _GraphicsDevice.SetRenderTarget(0, null); 
 } 
}

Соединение всего кода:

public sealed class HighDynamicRange : PostProcessEffect, 
 IDisposable 
{ 
 private DownSample4x4 _DownSample4x4 = null; 
 private ToneMapping _ToneMapping = null; 
 private BrightPass _BrightPass = null; 
 private GaussianBlur9x9 _GaussianBlur = null; 
 private AddRGB _AddRGB = null; 
 private Luminance _Luminance = null; 
 private RenderTarget2D currentFrameLuminance = null; 
 private RenderTarget2D glowEffect = null; 
 private RenderTarget2D addRgb = null; 
 public float Exposure 
 { 
 get 
 { 
 return _ToneMapping.Exposure; 
 } 
 set 
 { 
 _BrightPass.Exposure = value; 
 _ToneMapping.Exposure = value; 
 } 
 } 
 public float BrightnessThreshold 
 { 
 get 
 { 
 return _BrightPass.Threshold; 
 } 
 set 
 { 
 _BrightPass.Threshold = value; 
 } 
 } 
 public GaussianBlur9x9 GaussianBlur 
 { 
 get { return _GaussianBlur; } 
 } 
 public HighDynamicRange(GraphicsDevice graphicsDevice, 
 ContentManager content, int width, int height) 
 : base(graphicsDevice) 
 { 
 currentFrameLuminance = new RenderTarget2D(graphicsDevice, 
 1, 1, 1, SurfaceFormat.HalfVector2, 
 RenderTargetUsage.DiscardContents); 
 _DownSample4x4 = new DownSample4x4(graphicsDevice, content); 
 _GaussianBlur = new GaussianBlur9x9(graphicsDevice, content); 
 _BrightPass = new BrightPass(graphicsDevice, content); 
 _ToneMapping = new ToneMapping(graphicsDevice, content); 
 _AddRGB = new AddRGB(graphicsDevice, content); 
 _Luminance = new Luminance(graphicsDevice, 
 content, width, height); 
 } 
 public override void PostProcess(Texture2D sourceTexture, 
 RenderTarget2D result) 
 { 
 EnsureHelperRenderTargets(sourceTexture); 
 _Luminance.PostProcess(sourceTexture, currentFrameLuminance); 
 _BrightPass.LuminanceTexture = currentFrameLuminance.GetTexture(); 
 _ToneMapping.LuminanceTexture = currentFrameLuminance.GetTexture(); 
 _BrightPass.PostProcess(sourceTexture, glowEffect); 
 _GaussianBlur.Horizontal = true; 
 _GaussianBlur.PostProcess(glowEffect.GetTexture(), glowEffect); 
 _GaussianBlur.Horizontal = false; 
 _GaussianBlur.PostProcess(glowEffect.GetTexture(), glowEffect); 
 glowEffect.ApplyEffect(_DownSample4x4); 
 _ToneMapping.PostProcess(sourceTexture, addRgb); 
 _AddRGB.OtherTexture = glowEffect.GetTexture(); 
 _AddRGB.PostProcess(addRgb.GetTexture(), result); 
 } 
 private void EnsureHelperRenderTargets(Texture2D sourceTexture) 
 { 
 if (glowEffect == null) 
 { 
 glowEffect = new RenderTarget2D(_GraphicsDevice, 
 sourceTexture.Width / 4, sourceTexture.Height / 4, 
 1, SurfaceFormat.HalfVector4); 
 } 
 else 
 { 
 if (glowEffect.Width != sourceTexture.Width / 4 || 
 glowEffect.Height != sourceTexture.Height / 4) 
 { 
 glowEffect.Dispose(); 
 glowEffect = null; 
 glowEffect = new RenderTarget2D(_GraphicsDevice, 
 sourceTexture.Width / 4, sourceTexture.Height / 4, 
 1, SurfaceFormat.HalfVector4); 
 } 
 } 
 if (addRgb == null) 
 { 
 addRgb = new RenderTarget2D(_GraphicsDevice, 
 sourceTexture.Width, sourceTexture.Height, 
 1, SurfaceFormat.HalfVector4); 
 } 
 else 
 { 
 if (addRgb.Width != sourceTexture.Width || 
 addRgb.Height != sourceTexture.Height) 
 { 
 addRgb.Dispose(); 
 addRgb = null; 
 addRgb = new RenderTarget2D(_GraphicsDevice, 
 sourceTexture.Width, sourceTexture.Height, 
 1, SurfaceFormat.HalfVector4); 
 } 
 } 
 } 
 public void Dispose() 
 { 
 IDisposable luminance = _Luminance; 
 luminance.Dispose(); 
 luminance = null; 
 _Luminance = null; 
 } 
}

Заключение:

В этой статье вы увидели, как рендеринг в расширенном динамическом диапазоне действительно работает в ваших играх. Все исходные коды сделаны для Microsoft Visual Studio 2008 и Microsoft XNA 3.0.

В дальнейшем может быть осуществлено добавление автоматической регулировки яркости сцены, сохраняя значения яркости с предыдущего кадра и адаптируя его в текущем кадре. Другим эффектом улучшения изображения может быть освещение, основанное на изображении.

Справочная информация:

Green, S., & Cebenoyan, C. (2004).

High Dynamic Range Rendering (on the GeForce 6800).
Hoxley, J. (Novamber 2005).

High Dynamic Range Rendering Demonstration.
Anirudh, S. High Dynamic Range Rendering.

Ссылки:

Исходные коды: http://www.ziggyware.com/readarticle.php?forum_id=18&thread_id=13501&getfile=44825

Оригинал статьи (англ.):

http://www.ziggyware.com/readarticle.php?article_id=226

Реклама
Запись опубликована в рубрике Uncategorized. Добавьте в закладки постоянную ссылку.

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s