使用Render Target來拍攝場景
Render Target這個詞是在DirectX出現的,XNA同樣的也是沿用這個詞,而用途就是說,現在我們可以設定畫面的輸出位置。通常,我們所指的輸出位置,是指螢幕的部分,現在有了Render Target,我們可以自己設定輸出的位置,像是我們可以輸出到2D貼圖。
如果你有用OpenGL來做這個部分的話,那你可能會聽過一個詞Frame Buffer Object(FBO),這兩個用途是相同的。
而現在我們要做的事情,就是用Render Target將場景畫面輸出到一張2D貼圖上面。
做了這個動作以後,現在可以直接用spritbatch將他畫出來,或是直接用前面所說的VertexBuffer來建立一個平面,在將圖片貼上去顯示。
首先,我們先要將模型先放進虛擬資料夾下(在方案總管中,有一個Content的資料夾)。模型的部分,你可以自己設計,或是到XNA Creator Club上面,有些範例有提供3D模型。
要運用Render Tartget的話,我們需要宣告一個Render Target物件。接下來,我們需要Model和View、projection Matrix。
1: Model mModel;
2:
3: Matrix mView, mProjection;
4:
5: RenderTarget2D mRenderTarget;
而在Initialize的函數中,可以直接建立View和project矩陣,如下
1: mView = Matrix.CreateLookAt(new Vector3(0, 40, 80),
2: new Vector3(0,40,0), Vector3.Up);
3: mProjection = Matrix.CreatePerspectiveFieldOfView(
4: (float)(3*Math.PI / 4), graphics.GraphicsDevice.Viewport.Width /
5: graphics.GraphicsDevice.Viewport.Height, 1.0f, 10000.0f);
完成以後,需要在LoadContent的函數中,載入模型,輸入以下程式碼
mModel = Content.Load<Model>("dude");
這樣Content Pipeline就會在編譯的時候,將檔案編譯成XNB檔案,方便在runtime中執行。
讀入完成以後,接下來,需要初始化RenderTarget,如下程式碼
1: mRenderTarget = new RenderTarget2D(GraphicsDevice, GraphicsDevice.Viewport.Width,
2: GraphicsDevice.Viewport.Height, 1, SurfaceFormat.Color);
第一個參數要傳入GraphicDevice
第二個參數設定RenderTarger的寬度
第三個參數設定RenderTarget的高度
第四個參數設定為1即可
第五個參數這邊設定為Color因為我們現在拍攝的是彩色的場景,可能需要依照不同的情況,會設定不同的參數
在Draw的函數中,我們就要進行Render的部分。
首先先將結果Render到Render Target,要做這個步驟,需要將輸出的位置
GraphicsDevice.SetRenderTarget(0, mRenderTarget);
這由這樣就可以,將輸出的位置,輸出到mRenderTarget中,第一個參數設定為0
接下來,當你Rander過後,你需要將Reder Target設定為Back Buffer(有設定到Back Buffer後,會畫到螢幕上面)
設定方式
GraphicsDevice.SetRenderTarget(0, null);
現在你可以用mRenderTarget中的getTexture()來取得現在畫面中的貼圖。
你可以直接將貼圖結果,用spriteBatch將結果畫出來
1: spriteBatch.Begin(SpriteBlendMode.None, SpriteSortMode.BackToFront,
2: SaveStateMode.SaveState);
3: spriteBatch.Draw(mRenderTarget.GetTexture(), Vector2.Zero, Color.White);
4: spriteBatch.End();
結果如下:
用SpriteBatch來會出結果是其中一種表現結果的方式,另一種方式是使用前面一篇所教的VertexBuffer和index的方式來畫出來。
1. 宣告下列變數:
1: VertexBuffer mVertexBuffer;
2: VertexDeclaration mDeclaration;
3: VertexPositionColorTexture[] mVertex;
4: BasicEffect mEffect;
5: short[] mIndex;
2. 在Initialize中設定頂點相關資料,這邊需要設定貼圖座標!!
1: mVertex = new VertexPositionColorTexture[4];
2: mVertex[0].Position = new Vector3(-100, 100, 0);
3: mVertex[0].TextureCoordinate = new Vector2(0.0f, 0.0f);
4: mVertex[1].Position = new Vector3(-100, -100, 0);
5: mVertex[1].TextureCoordinate = new Vector2(0.0f, 1.0f);
6: mVertex[2].Position = new Vector3(100, -100, 0);
7: mVertex[2].TextureCoordinate = new Vector2(1.0f, 1.0f);
8: mVertex[3].Position = new Vector3(100, 100, 0);
9: mVertex[3].TextureCoordinate = new Vector2(1.0f, 0.0f);
10:
11: mDeclaration = new VertexDeclaration(GraphicsDevice,
12: VertexPositionColorTexture.VertexElements);
13: mVertexBuffer = new VertexBuffer(GraphicsDevice,
14: VertexPositionColorTexture.SizeInBytes * 4, BufferUsage.WriteOnly);
15: mVertexBuffer.SetData<VertexPositionColorTexture>(mVertex);
16:
17: mIndex = new short[4] { 0, 1, 2, 3 };
18:
19: mEffect = new BasicEffect(GraphicsDevice, null);
20: mEffect.World = Matrix.Identity;
21: mEffect.View = mView;
22: mEffect.Projection = mProjection;
這邊詳細就不再多多說明...,有需要的話可以往前面看
在Draw的函數中,使用basic effect中來做貼Texture的動作,首先,要先開啟貼圖,然後在設定貼圖,程式碼如下:
1: mEffect.TextureEnabled = true;
2: mEffect.Texture = mRenderTarget.GetTexture();
這樣就可以得到下面的結果
有興趣的話可以下載程式碼來看看,也歡迎一起討論這個部分...
Rander Target的部分,被應用在很多地方,像是你可以用來建立Multi Viewport、Deffered Buffer或是Shadow Map等的實作的部分。