英吋 XNA

XNA – SpriteBatch 與 RenderState

當3D功能做到一定程度後,通常會開始加上一些文字或圖片來加入偵錯資訊
但這時候,當你使用SpriteBatch繪製之後…
3D圖像全部都掰掉了…

這個原因就是在於SpriteBatch在Begin()的時候會更動GraphicsDevice.RenderState的東西。
直接的影響到一些3D很重要的模式被改變,導致出錯。

最簡單的方式就是啟用SpriteBatch.Begin()多載裡的SaveStateMode.SaveState項目。
簡單來說就是在Begin()前紀錄,End()後恢復,即可避免!
但是儲存狀態(SaveState)的這個動作非常的浪費效能!
(這是網路上大多數人的說法,我沒實測

如果不使用SaveState的方法,那就只好在繪製3D圖像之前手動設定啦~
當然,無謂的全部紀錄或改變並不會比SaveState來得有意義。
知彼知己,乃最高兵法!
來看看SpriteBatch.Begin()會改變哪些屬性吧~

SpriteBatch.Begin Method

  GraphicsDevice.RenderState.CullMode = CullMode.CullCounterClockwiseFace;
  GraphicsDevice.RenderState.DepthBufferEnable = false;

  GraphicsDevice.RenderState.AlphaBlendEnable = true;
  GraphicsDevice.RenderState.AlphaBlendOperation = BlendFunction.Add;
  GraphicsDevice.RenderState.SourceBlend = Blend.SourceAlpha;
  GraphicsDevice.RenderState.DestinationBlend = Blend.InverseSourceAlpha;
  GraphicsDevice.RenderState.SeparateAlphaBlendEnabled = false;

  GraphicsDevice.RenderState.AlphaTestEnable = true;
  GraphicsDevice.RenderState.AlphaFunction = CompareFunction.Greater;
  GraphicsDevice.RenderState.ReferenceAlpha = 0;

  GraphicsDevice.SamplerStates[0].AddressU = TextureAddressMode.Clamp;
  GraphicsDevice.SamplerStates[0].AddressV = TextureAddressMode.Clamp;

  GraphicsDevice.SamplerStates[0].MagFilter = TextureFilter.Linear;
  GraphicsDevice.SamplerStates[0].MinFilter = TextureFilter.Linear;
  GraphicsDevice.SamplerStates[0].MipFilter = TextureFilter.Linear;

  GraphicsDevice.SamplerStates[0].MipMapLevelOfDetailBias = 0.0f;
  GraphicsDevice.SamplerStates[0].MaxMipLevel = 0;


有些屬性是2D和3D都適用的,那倒是還好。
但像是DepthBufferEnable、AlphaBlendEnable這類的屬性,卻很有差別。
通常會將這些改回來…

RenderState的部分:

  GraphicsDevice.RenderState.DepthBufferEnable = true;
  GraphicsDevice.RenderState.AlphaBlendEnable = false;
  GraphicsDevice.RenderState.AlphaTestEnable = false;
  // 像是我會開雙面貼圖,就要加上去
  GraphicsDevice.RenderState.CullMode = CullMode.None;


SamplerStates的部分:

  GraphicsDevice.SamplerStates[0].AddressU = TextureAddressMode.Wrap;
  GraphicsDevice.SamplerStates[0].AddressV = TextureAddressMode.Wrap;



大概就是這樣~

參考「SpriteBatch and renderstates

※程式碼HeightLight

–End

2則迴響

  1. 真認真耶… 我現在只能在地上認真的爬三行三進了=口= 還有可怕刺槍術!

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com 標誌

您的留言將使用 WordPress.com 帳號。 登出 /  變更 )

Google photo

您的留言將使用 Google 帳號。 登出 /  變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 /  變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 /  變更 )

連結到 %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.