天天看點

XNA學習筆記3-2D紋理

對于2D紋理的繪制,XNA架構使用了一個特殊的類-SpriteBatch來處理,其中Draw方法的不同重載版本有不同的功能,可以實作旋轉、縮放、鏡像和設定層深度的功能,以及通過Begin方法的參數實作透明繪制的功能。

[b]旋轉[/b]。使用rotation 參數你可以旋轉一個圖像。你需要使用弧度制指定這個旋轉角度,是以如果你想讓圖像順時針旋轉20度,你可以使用MathHelper.ToRadians(20),它可以幫你完成這個轉換。注意:2*PI弧度對應360角度,PI弧度對應180角度。是以如果你想旋轉20度,你也可以使用MathHelper.Pi/180.0f*20.0f作為參數。

[b]縮放[/b]。如果你想放大/縮小圖像,可以設定參數scale。因為這個參數是一個Vector2,你可以對圖像的水準方向和豎直方向施加不同的縮放值。例如,設定為(0.5f, 2.0f)将會使寬度變為原始寬度的一半,高度變為原始高度的2倍。

[b]鏡像[/b]。參數effects讓你可以水準或豎直翻轉圖像。通過flags,你可以使用SpriteEffects.FlipHorizontally|SpriteEffects.FlipVertically同時進行這兩個操作,這和将圖像旋轉180度的效果是相同的。

[b]層深度[/b].最後一個參數讓你可以指定圖像位于哪個層,當你想将多個圖像在各自的頂部時層的概念是很有用的。

public void Draw (Texture2D texture,Vector2 position,
   Nullable<Rectangle> sourceRectangle,Color color,float rotation,
   Vector2 origin,Vector2 scale,SpriteEffects effects,float layerDepth)
           

[b]透明[/b]。如果你想讓XNA處理圖像的透明,需要使用SpriteBatch.Begin()方法開啟alpha混合。當然,對那些沒有透明資訊的圖像,你可以指定一個顔色作為透明色。這可以通過設定圖像屬性中的color key實作(在IDE的圖形界面設定)。

[b]性能優化[/b]

性能優化是SpriteBatch的一個重要議題。在螢幕上繪制一張2D圖像是通過繪制兩個三角形并将它們填充為從一張紋理采樣的顔色實作的。顯示卡喜歡一次性地繪制大量的三角形不要被打攪。但是當你需要改變紋理時,你就打攪了顯示卡。換句話說,從同一張紋理繪制100張圖像比從100張紋理繪制100張圖像快得多。是以,盡可能少地改變目前紋理可以改進性能。

有了這個概念,下面你可以學習可以作為SpriteBatch . Begin方法的一個參數指定的sprite排序模式了:

Deferred:這是預設的SpriteSortMode。雖然你幾乎從不會用到它,因為它沒有排序。 隻要通過SpriteBatch . Draw方法将一個sprite添加到batch,這個sprite隻是簡單地添加到堆棧的頂部。當調用SpriteBatch . End方法時,堆棧中所有的sprite會根據進入堆棧的順序進行繪制。

Texture:通常基于性能優化和易用性考慮,你會使用這個模式。當調用SpriteBatch . End方法時,在XNA實際要求顯示卡繪制圖像前,堆棧中的所有圖像據紋理進行排序。通過這種方式,顯示卡可以在一個輪次中使用同一張紋理繪制許多三角形,你可以減少幹擾顯示卡改變紋理的次數。但是,當使用alpha透明時這個模式會遇到麻煩,你需要用到下面幾個模式中的一個。

BackToFront:當使用alpha混合時,你想讓距離最遠的物體最先繪制。添加圖像到SpriteBatch 類的SpriteBatch . Draw方法有一個重載方法可以接受layerDepth為參數。使用這個float參數,你可以指定圖像在哪個層,1.0f表示最遠的層,0.0f表示最近層。你可以指定兩者之間的任何值。當使用BackToFront模式時,隻要調用SpriteBatch . End方法,在SpriteBatch中的圖像就會進行排序讓最遠層最先被繪制。

FrontToBack:這個模式正好與前一個模式相反,是以最近層的圖像最先被繪制。因為螢幕上所有被繪制的像素永遠不會被覆寫(因為所有接下來的圖像都在這個之後),這會導緻最好的性能。但是,使用alpha混合無法工作,并且隻有在所有圖像使用相同的紋理的情況下才會獲得最好的性能!如果繪制最近層需要交換10次紋理,性能相比使用Texture模式會有更大的下降。

Immediate:相對于其他模式,在這個模式中XNA不會等待調用SpriteBatch . End方法繪制所有圖像。隻要你調用SpriteBatch. Draw方法将使用相同紋理的圖像添加到SpriteBatch,SpriteBatch就會将它們推入堆棧中。當你使用另一個紋理繪制一個sprite時,目前堆棧中的sprite會立即被繪制。

使用前四個模式,隻有在調用SpriteBatch . End方法時,sprite才會被排序,渲染狀态被設定,三角形和紋理被傳送到顯示卡。這讓你可以使用多個SpriteBatch 類對象,以随機順序添加新sprite,甚至是使用相同渲染狀态的3D對象。但在使用Immediate模式時,渲染狀态會在調用SpriteBatch. Begin方法時調用,sprite會在調用SpriteBatch . Draw方法之後被繪制。這意味着你可以在兩個方法間改變渲染狀态!通過這種方式,你可以通路更多的alpha混合模式或使用一個自定義的pixel shader 繪制sprite!但是使用Immediate模式繪制圖像時,你無法在繪制其他東西,例如一個3D對象,因為這時你可能會改變渲染狀态。當你想用SpriteBatch繼續繪制sprite時,渲染狀态還沒有複位,是以你将使用3D物體的渲染狀态和pixel shader 繪制sprite。

SpriteBatch同時用于繪制文字。

SpriteFont myFont = Content.Load<SpriteFont>("ourFont")
spriteBatch.Begin();
string myString = "Elapsed seconds: " + gameTime.TotalGameTime.Seconds.ToString(); 
spriteBatch.DrawString(myFont, myString, new Vector2(50, 20), Color.Tomato); 
spriteBatch.End();
           

首先需要建立一個SpriteFont檔案。右擊XNA項目的Content檔案夾并選擇Add→New item。從對話框中選擇SpriteFont,起一個名稱(比如ourFont),然後點選Add。現在看到一個XML頁面。最重要的一行是設定FontName屬性,可以将這個屬性改成你想要繪制的字型。接下去一行可以設定字型大小,你也可以在以後縮放字型大小。 注意:你可以使用任何安裝在你的計算機上的TrueType字型。要看到已經安裝的字型,可以打開C:\WINDOWS\FONTS目錄(例如點選Start按鈕,選擇Run,并輸入這個檔案夾位址)。FontName列顯示了可以指定的所有字型。例如,如果字型名稱為Times New Roman (TrueType),你指定Times New Roman作為FontName 屬性。 當在另一台電腦上編譯代碼時,那台電腦上也必須裝有這個字型,否則會報錯。