參照Win32下的DirectX 10代碼,實現基於DirectX 11的Windows Store App,雖然是彎路,會遇到一些額外的問題,但是感覺在解決問題的過程中,能對DirectX理解的更深一些。而且這樣做能夠避免自己直接複製代碼,不關注細節。這裏對目前爲止遇到過的問題進行總結,防止自己以後犯同樣的錯誤。水模型之前的代碼只是對VS2012模板代碼進行簡單改動,從沒遇到問題,問題都出現在實現水波紋的過程中,都是運行時出現的錯誤。
一、內存訪問衝突
錯誤提示:
出現這個錯誤的原因是在Renderer的Update方法中,沒有用條件語句
if (m_loadingComplete)
{
}
包含更新水面頂點緩衝區的代碼。
從調用堆棧可以看出問題由WaterModel的Update方法引發,而且彈出錯誤提示是在應用啓動時,也就是第一次對Update方法的調用。Update方法中需要更改緩衝區,出現此問題應該是緩衝區未初始化。檢查Renderer類的Update方法後發現問題。由於初始化資源爲異步調用,第一次執行Update方法時不能保證緩衝初始化完成,這時嘗試更新緩衝區就會出現問題。
教訓:
1、 使用資源前要保證初始化完成。
2、 異步編程一定要注意任務次序控制。
二、輸入驗證失敗
錯誤提示:
這個問題出現在Disturb方法的輸入驗證階段,從輸出提示可以看出是傳入的參數越界。因此定位到Renderer的Update方法,找到生成隨機值的代碼。
int i = 5 + rand() % 128;
int j = 5 + rand() % 128;
i和j有可能超出128。在初始化時用的代碼是
m_water.Initialize(m_d3dDevice.Get(), 128, 128, 1.0f,0.03f, 3.25f, 0.4f);
這樣就會造成Disturb方法輸入驗證失敗。
教訓:
在編程中要避免奇異數出現,方便查找錯誤。
三、圖像繪製異常
錯誤現象:
程序能正常運行,但是水面會從邊界高度無限增加,最終消失。由於這次沒有出現運行錯誤,所以只檢查更新水面高度的代碼,最終發現是循環的起止範圍有誤。使用這種算法更新水面高度時會用到當前頂點四個方向上的鄰點,而邊界頂點總會缺少一個方向的鄰點,這樣,在更新頂點高度時會引入一個無效值,得出無意義的結果,出現上面的現象。
教訓:
實現算法時要注意邊界條件。