傳回首頁>
跨平台移動應用開發的渲染解決方案綜述
在移動裝置上做應用/遊戲開發,實作跨平台是主流。對于應用/遊戲的邏輯功能和核心算法部分,如果是用C++進行開發的,因為iOS/Android/Windows Phone 8/Windows Store均支援Native的C++開發,是以可以輕松的移植到各個平台,應用/遊戲的Backend也有如Photon這樣的跨平台解決方案。對于一部分圖形要求很高的應用,如遊戲和一些UI定制化需求很多的應用,渲染部分往往需要花更多的精力實作移植。對于渲染部分,跨平台開發者有以下三種選擇:
1) 使用已有的一些跨平台圖形解決方案,如cocos2D-x, Unity 3D等遊戲引擎以及HTML5。
2) 将渲染部分在程式設計時獨立,針對不同的平台分别實作渲染。在Windows Phone / Windows Store應用中,DirectX和XAML可以結合使用,進而友善的與第三方SDK結合使用。
3) 将現有的渲染代碼通過工具映射到其他平台。如開源的Angle project可以将OpenGL ES自動映射到DirectX。
本文将分别對這三種選擇依次作介紹,為開發者順利完成應用/遊戲在渲染部分的移植作一個參考。因時間和能力有限,謬誤之處請不吝指教。
(1) 使用遊戲引擎/HTML5等現有的跨平台解決方案
cocos2d-x:cocos2d-x是一個開源免費、易學易用的2D跨平台遊戲引擎,支援Windows Phone, Windows 8, iOS和Android多個平台。目前是國内最流行的2D遊戲引擎。其下載下傳位址為:
http://www.cocos2d-x.org/news/143
Unity 3D: Unity 3D是一個非常強大的商用跨平台開發工具,支援Windows Store, Windows Phone, iOS, Android, Wii等多個平台。Unity 3D是移動平台上3D引擎的領頭羊,同時Unity 3D也能很好的支援2D圖形開發。下載下傳位址:
http://unity3d.com/unity/whats-new/unity-4.3
XNA:XNA可支援Windows, Xbox 360和Window Phone,以前使用XNA開發的針對Window Phone 7.x的遊戲仍然可以在Windows Phone 8上運作。但不支援建立新的目标裝置為WP8的遊戲。請參考:
http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj207003(v=vs.105).aspx
http://msdn.microsoft.com/en-us/library/bb200104.aspx
MonoGame:MonoGame旨在幫助XNA開發者在Windows Phone 8, Windows 8,iOS, Android,Mac,Linux等多個平台實作跨平台開發。官方首頁:
http://www.monogame.net/
在開源平台codeplex上的頁面:http://monogame.codeplex.com/
Marmalade:Marmalade是一個非常有特色的跨平台遊戲引擎,它支援在Windows上将應用Deploy至iOS。支援将OpenGL的程式直接轉換成DirectX11的以移植到Windows Phone平台上。請參考:
https://www.madewithmarmalade.com/
http://www.madewithmarmalade.com/windows-phone-8
HTML5: 除了遊戲引擎,還可以使用HTML5實作跨平台。對Windows Store遊戲,可使用HTML5 和 JavaScript。如果熟悉HTML5 和 JavaScript (WinJS) 的開發,同時遊戲不需要複雜的動畫效果,并且對于遊戲的實時性能沒有非常高的要求,可以考慮這種遊戲開發模式。
推薦使用的情景:充分利用HTML5 和 JavaScript(WinJS)的開發經驗。 友善頁遊的遷移,縮短開發周期
不推薦使用的情景:如果你的遊戲有大量的圖像處理,或者對性能要求很高,使用HTML5 和 JavaScript 開發模式就不太适合你的遊戲。 最好使用DirectX 和 C++ 結合。
請參考:http://msdn.microsoft.com/en-us/library/windows/apps/hh465158.aspx
開發例子:design.htmlwindowsapps/JavaScript-and-HTML5-touch-d96f6031
(2)針對不同平台分别用OpenGL / OpenGL ES或者DirectX實作渲染
在跨平台應用程式設計的時候,我們可以将渲染部分獨立,最簡單的設計是建立 Renderer類,分别針對Windows Phone, iOS和Android實作。衆所周知,OpenGL ES主要用于Android和iOS平台的開發。而WP8和Windows Store使用DirectX11 API。接下來我們重點比較OpenGL和DirectX的異同,供開發者在切換平台時參考。
OpenGL ES / OpenGL與DirectX性能比較
這是一個在OpenGL和DirectX誕生以來很多人比較熱衷于讨論的問題,是以在這裡簡要的提一下。其實一款顯示卡在設計的時候就會考慮要支援OpenGL和DirectX兩種标準的所有feature,而不管是GLSL還是HLSL的shader,在經過驅動編譯後都是在同樣的硬體中同樣的并行計算子產品上運算,紋理等resource也是存儲在同樣的顯存上。OpenGL和DirectX實作的應用程式其性能更多取決于驅動的優化程度而非OpenGL / DirectX API的優劣。OpenGL或者DirectX的API的選擇對遊戲的性能的影響主要局限于CPU部分而不是GPU。例如AMD最近釋出的Mantle API其主要優化也是集中于減少CPU的開銷,且僅适用于AMD顯示卡。而OpenGL和DirectX的API對CPU部分開銷的比較至今沒有一個定論,也即沒有一方是明顯優于另一方。OpenGL ES在設計時是參考OpenGL的,可以說是OpenGL的一個子集,其API也沒有優于DirectX的說法。
開發者如果對遊戲性能有所顧慮,可以更多的可考慮一些平台相關的特性而非API本身。例如在iOS使用pvr格式的紋理(PowerVR的有損壓縮格式),而在Windows平台使用DDS格式的紋理。在下文中有關于手機紋理的詳細說明:
手持平台紋理格式說明
硬體對OpenGL ES和DirectX的支援
在寫這篇文檔的時候(2013年10月),智能手機普遍可以支援OpenGL ES 2.0或以上了。下面的表格列出了OpenGL ES與DirectX的比較。OpenGL ES 2.0相當于DirectX 3D的feature level 9。OpenGL ES 2.0所支援的GLSL對應于DirectX的HLSL。
OpenGL ES版本清單
OpenGL ES版本号 | 對應OpenGL版本 | 對應的DX版本 | 版本特性 |
1.0 | OpenGL 1.3 | 低于DX9 | Fixed function rendering |
1.1 | OpenGL 1.5 | 低于DX9 | Fixed function rendering。雖然OpenGL 1.5中引入了ARB shader,但是OpenGL ES 1.1中仍然是不支援的。 |
2.0 | OpenGL 2.0 | DX9 | 支援GLSL |
3.0 | OpenGL 3.0 | DX10與DX9之間 | 相容OpenGL ES 2.0,但不支援DX10中才有的Geometry Shader, OpenGL自3.2版本開始支援Geometry Shader. |
OpenGL和OpenGL ES詳細資訊可參考Spec或Wiki中的介紹。可參考下面的連結:
http://www.khronos.org/opengles/
http://en.wikipedia.org/wiki/OpenGL
http://en.wikipedia.org/wiki/OpenGL_ES
DirectX 版本(忽略DirectX9以前版本,因為不論WP還是Win8的硬體最低要求都是支援DX 9.1)
DX版本 | 與OpenGL ES對應關系 | 支援的 Shader |
9.x | 功能上相當于OpenGL ES 2.0 | Vertex Shader, Pixel Shader |
10.x | 包含OpenGL ES 3.0的feature | 增加了 Geometry Shader |
11.x | 包含DX10且包含OpenGL ES 3.0 | 增加了 Hull Shader和 Domain Shader |
各應用平台對OpenGL ES、DirectX以及OpenGL(非ES)的支援
Android | iOS | Windows Phone / Windows Store |
根據下面的讨論,在2010年,已經有超過75%的Android裝置可以通過NDK支援OpenGL ES 2.0. 估計目前絕大多數Android裝置均可使用至少OpenGL ES 2.0。 https://groups.google.com/forum/#!topic/android-developers/HBddHFyxYeo 需要Android 4.3或以上才能支援OpenGL ES 3.0 | 從iPhone 3GS開始支援OpenGL ES 2.0. 從iPhone 5S開始支援OpenGL ES 3.0 | 從Windows Phone 8開始支援DirectX 11的API,其feature level是DX 9.3。開發必須使用DirectX 11的API。 Surface RT要求必須能運作DX 9.1的feature。 在Windows Store中針對x86和x64平台可使用DX10和DX11的feature。如無法支援DX9,需要在程式啟動後顯示說明。 在WP8之前的WP,可使用XNA開發,相當于DX9的feature level。 在Windows Store應用中,可使用OpenGL(非ES)開發。參考如下: http://opengl.codeplex.com/ |
OpenGL ES 2.0是目前在iOS和Android平台上通常使用的圖形解決方案,常用的遊戲引擎中的渲染部分是對OpenGL ES的封裝。OpenGL ES 2.0所對應的DirectX 版本是DirectX 9,。而WP8和Windows 8對硬體的最低硬體要求即DX9,這使得基于OpenGL或者遊戲引擎的應用向WP/Windows 8移植變成很自然的事情。
WP8和Windows 8應用商店的應用需要使用DX11的API進行程式設計,我們隻需要将DX11的Feature level設定為DX9即可(參考下面的代碼片斷)對應于OpenGL ES 2.0。對于Windows Store中的應用,我們還可以使用DX10和DX11中的feature, 實作比OpenGL ES 2.0更加強大的渲染功能和更好的性能。
D3D_FEATURE_LEVEL featureLevels[] =
{
D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_9_3,
D3D_FEATURE_LEVEL_9_2,
D3D_FEATURE_LEVEL_9_1
};
D3D_FEATURE_LEVEL APP_MIN_FEATURE_LEVEL = D3D_FEATURE_LEVEL_9_1;
如前所述,其實OpenGL ES 2.0是OpenGL 2.0的子集,對應于DirectX的Feature level 9所能夠實作的功能是相當的。是以能夠使用OpenGL實作的效果,通常也可以使用DirectX實作。Visual Studio支援兩種DirectX的模闆,一種是僅使用DirectX而不使用XAML,另外一種是将DirectX和XAML結合。我們比較推薦的是DirectX和XAML結合。因為XAML中定義的豐富的界面元素,互動的實作更加簡單。第三方的SDK如微網誌,支付相關SDK都需要XAML的支援。在微軟設計DirectX和XAML結合的時候,已經針對不同情景盡可能減少結合時對性能的影響。
XAML與DirectX結合使用的相關文檔請參考:
http://channel9.msdn.com/Events/Windows-Camp/Developing-Windows-8-Metro-style-apps-in-Cpp/Building-Apps-with-Cpp-XAML-and-DirectX
http://blogs.msdn.com/b/windowsappdev/archive/2012/03/15/combining-xaml-and-directx.aspx
http://mobile.dzone.com/articles/directx-and-xaml-windows-phone
不管是OpenGL和DirectX,渲染時都需要維護所謂的Context。在Context中儲存了一些渲染時的狀态資訊,例如是否使用了光照,是否啟用了霧效,目前使用的紋理是什麼等等。一般建立Context的過程都是由平台的模闆自動生成,開發者隻需要對Context進行适當的設定,并調用OpenGL或者DX的API進行渲染即可。OpenGL ES和DX11建立Context以渲染的過程分别如下(謹供參考,一般移動應用的程式員不需要關心細節):

最常見的渲染過程是設定vertex buffer(VB)、index buffer(IB)、紋理、shader、調用繪制函數,最後顯示緩沖中的渲染圖像。下面的表格将主要從這幾個方面對OpenGL ES和DX作比較。
OpenGL ES | DirectX 11 | |
Vertex buffer 和 Index buffer(通常稱VB和IB) 在顯存/記憶體中的存儲方式和二者沒有差別,均按順序線性存放資料。但使用VB和IB的API略不同 | VB和IB中定義的模型通過draw函數繪制。 通常使用glDrawElements函數 偶爾使用glDrawArrays函數(不需要IB) glBegin, glEnd, glVertex3f等OpenGL函數在OpenGL ES中因為效率的考慮已經移除。 | Draw通常使用DrawIndexed繪制VB/IB中的内容 也有DrawInstanced, DrawAuto等函數可供選擇 注意Instancing在DX9中已經支援,在OpenGL 3.0才支援。 在DX 10以後還可通過Geometry shader實作Instancing |
VB中頂點的屬性(Attribute) 如normal, color, texture坐标, position等等 | 使用glVertexAttribPointer函數分别指定頂點的各個屬性 與DX的比較可參考下文: 将 OpenGL ES 2.0 緩沖區、uniform 和頂點屬性與 Direct3D 進行比較 | DX的API中沒有Attribute這個概念,僅使用結構體 D3D11_INPUT_ELEMENT_DESC描述VB中每個頂點的資料格式 m_d3dDevice->CreateInputLayout |
Shader / Program | OpenGL中Shader又叫Program 支援運作時編譯,即GLSL文本在運作時編譯。 分Vertex Program和Fragment Program | 對于Windows Store和WP8需要在編譯時将HLSL編譯成生成僞彙編代碼。如Shader編譯出錯則無法生成可執行檔案。 在DX feature level 9中 分Vertext Shader和Pixel Shader分别對應于GLSL中的Vertex Program 和Fragment Program |
Shader的常數設定 | API中包含Uniform,如: glGetUniformLocation glUniform4fv | 使用Constant Buffer相關函數,如: m_d3dDevice->CreateBuffer m_d3dContext->UpdateSubresource m_d3dContext->VSSetConstantBuffers |
資源管理,如紋理和buffer | 使用glCreateShader, glBufferData, glGenBuffers, glTexImage2D, eglBindTexImage等等API管理資源 | 使用ID3D11Device管理資源。一般會有一個ID3D11Device指針,用以調資源管理的DX API ,如函數CreateTexture2D()。在Windows Store的應用可以使用一些已經封裝好的Loader類加載紋理資源。微軟的Sample中常使用BasicLoader類,程式員可在其基礎上進一步修改增強。 |
Context管理, 用于配置渲染管線 | glAttachShader, glGetUniform*等等API | 一般建立ID3D11DeviceContext類的指針,再使用context指針調用Context配置的API |
顯示緩沖區内容 | 使用SwapChain函數 | 使用Present函數 |
坐标系 X正方向為右,Y正方向為上。 詳細的異同可參考下面: Coordinate Systems (Direct3D 9) | OpenGL使用右手坐标系,是以Z的正方向指向螢幕外。 | DX使用左手坐标系。是以移植時三角形的頂點順序要反向,Z的方向也要反向。 可以使用函數 D3DXMatrixPerspectiveRH 和D3DXMatrixOrthoRH來做右手坐标系的投影映射。詳細請參考最左邊的連結 |
從OpenGL API映射到DirectX 3D的API
======================================
仍在更新的關于OpenGL到DX映射的文檔
http://msdn.microsoft.com/zh-cn/library/windows/apps/dn166866.aspx
常用的EGL API Mapping參考
http://msdn.microsoft.com/zh-cn/library/windows/apps/dn166867.aspx
最後需要指出,DirectX在Windows Phone和Windows Store的應用開發中略有差別,可參考如下:
http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj662930%28v=vs.105%29.aspx
以下是DirectX版本中渲染一個旋轉的立方體的Render函數實作,結合前面描述的OpenGL與DirectX的比較,讀者可與前面Angle Project中RotatingCube的Sample做個比較。
void Sample3DSceneRenderer::Render()
{
// Loading is asynchronous. Only draw geometry after it's loaded.
if (!m_loadingComplete)
{
return;
}
auto context = m_deviceResources->GetD3DDeviceContext();
// Set render targets to the screen.
ID3D11RenderTargetView *const targets[1] = { m_deviceResources->GetBackBufferRenderTargetView() };
context->OMSetRenderTargets(1, targets, m_deviceResources->GetDepthStencilView());
// Prepare the constant buffer to send it to the graphics device.
context->UpdateSubresource(
m_constantBuffer.Get(),
0,
NULL,
&m_constantBufferData,
0,
0
);
// Each vertex is one instance of the VertexPositionColor struct.
UINT stride = sizeof(VertexPositionColor);
UINT offset = 0;
context->IASetVertexBuffers(
0,
1,
m_vertexBuffer.GetAddressOf(),
&stride,
&offset
);
context->IASetIndexBuffer(
m_indexBuffer.Get(),
DXGI_FORMAT_R16_UINT, // Each index is one 16-bit unsigned integer (short).
0
);
context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
context->IASetInputLayout(m_inputLayout.Get());
// Attach our vertex shader.
context->VSSetShader(
m_vertexShader.Get(),
nullptr,
0
);
// Send the constant buffer to the graphics device.
context->VSSetConstantBuffers(
0,
1,
m_constantBuffer.GetAddressOf()
);
// Attach our pixel shader.
context->PSSetShader(
m_pixelShader.Get(),
nullptr,
0
);
// Draw the objects.
context->DrawIndexed(
m_indexCount,
0,
0
);
}
友善開發者使用DirectX進行開發的工具和模闆
=====================================
1. BasicLoader類:是微軟開發的一個用于加載紋理的類,可同步也可異步加載。支援各種圖像格式,也支援DDS格式的紋理。因為該類使用到Wic解碼器用于圖像解碼,而Wic解碼器僅限于PC,在WP上沒有Wic解碼器的支援,是以在WP上推薦使用DDS紋理。
2. 在Visual studio中內建了DDS紋理檢視器,可直接打開DDS檔案。也可提供一些常用的編輯功能。可以選擇不規則區域并編輯。
3. 3D遊戲中常用的FBX檔案也可以在Visual Studio中打開并編輯。
4. DirectX的Debugging在調試時可以打開debugging模式。也可使用DirectX SDK中的工具PIX抓取一段,以單步跟蹤D3D的API call。
5. Codeplex上開源的ToolKit http://directxtk.codeplex.com/wikipage?title=Samples
6. 開發者從頭開始開發的選擇。建立一個WP 8/Windows Store應用的時候,可支援多種模闆,有僅使用DX的模闆,也有用XAML與D3D混編的模闆。比較推薦的方式是使用XAML和DirectX混編的方式以充分結合兩者的強大功能。下圖是在建立一個Windows Phone應用時的模版,其中高亮的是Windows Phone Direct3D with XAML App,而Windows Store裡的模版名為DirectX App,因為Windows Store的模版不僅內建了DirectX 3D,還內建了DirectX 2D和DirectX Write。
在應用開發的架構中,已經将正常的操作完成,如Buffer Chain,重新整理,場景坐标系統設定等等。開發者需要做的是完成渲染和應用的邏輯。
對于Windows Store開發,在Shooting Game的Sample中開發者可學習一個現成的DirectX和XAML結合的遊戲架構,包括關卡設計、應用内購買、互動、渲染和音效等等技術:
http://msdn.microsoft.com/en-us/library/windows/apps/hh780560.aspx
對于Windows Phone中的遊戲開發,下面的Marble Maze這個Sample很不錯:
http://code.msdn.microsoft.com/wpapps/Marble-Maze-sample-for-c9f3706b
C++/CX
因為使用DirectX必須使用native code,是以必須使用C++/CX。這是微軟定義的一個C++ Extension,是相容标準C++的。是以移植C++代碼是非常友善的。C++/CX中有一些非常友善的新特性,掌握起來也不難,可提高使用程式設計效率。如多線程、Lamda表達示等。對于C++程式員來說,快速掌握C++/CX可參考下面的文檔:
多線程程式設計
http://channel9.msdn.com/events/BUILD/BUILD2011/PLAT-203T
C++/CX介紹及參考:
http://blogs.msdn.com/b/vcblog/archive/2012/08/29/cxxcxpart00anintroduction.aspx
3)使用AngleProject将現有的OpenGL ES代碼轉換
Angle是一個開源的項目,用于将OpenGL ES轉成DirectX以在Windows平台中使用。Angle目前是Chrome浏覽器中使用的渲染跨平台解決方案。
https://code.google.com/p/angleproject/
AngleProject編譯方法
https://code.google.com/p/angleproject/wiki/DevSetup
直接使用Angle Project移植OpenGL ES會遇到下面的問題
====================================================
1. Angle使用DirectX 11的部分是針對feature level 10的。而WP8/Surface RT僅支援到feature level 9.
2. Angle是動态在Runtime将GLSL轉成HLSL,而我們需要在編譯時即把GLSH轉成HLSL. WP8不支援Runtime的shader編譯.
Angle Project中對Windows Phone 8 / Windows 8 RT的适配
Angle Project針對Windonws Phone 8/ Windows 8 RT進行了如下适配,并在cocos2d-x中使用
1. 支援編譯時将GLSL轉成HLSL并編譯成.cso。.cso檔案是在Windows Store和Windows Phone平台上HLSL編譯後的檔案。CSO檔案應該是僞彙程式設計式,在經過驅動進一步編譯後可以在顯示卡上運作。
2.将DX10的feature去除,因為WP8隻支援到DX 9.3.
使用了Angle Project且支援WP8的cocos2D-x 2.2下載下傳位址為:
http://www.cocos2d-x.org/news/143
在Angle Project的source code tree中有一個RotatingCube的例子,開發者可參考用于OpenGL ES向WP / Windows Store的移植。
https://github.com/stammen/angleproject/tree/dev/samples/RotatingCube
Anglge project關于WP8的說明如下。簡而言之,Angle對WP8是支援的,對Windows Store 8目前支援有限制,但是如果應用是target到Windows 8.1是支援的。
https://github.com/stammen/angleproject
Angle Project (https://code.google.com/p/angleproject/) with support for Windows Store Apps (WinRT) and Windows Phone Apps (WP8). This version supports developing Windows Store Apps using Visual Studio 2013 and Windows 8.1. It is also ossible to develop a Windows Store App using Visual Studio 2012 and Windows 8.0 but this version will not be accepted in the Windows App Store.
Angle Project的RotatingCube這個Sample其 Render()函數如下。可以看到在例子中繪制使用的API是OpenGL ES的API。存儲頂點資料可以使用directxmath.h中定義的資料結構。
void CubeRenderer::Render()
{
XMFLOAT4X4 mvp;
XMStoreFloat4x4(&mvp, (XMMatrixMultiply(XMMatrixMultiply(m_modelMatrix, m_viewMatrix), m_projectionMatrix)));
glClearColor(0.098f, 0.098f, 0.439f, 1.000f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(m_colorProgram);
glUniformMatrix4fv(u_mvpColor, 1, GL_FALSE, &mvp.m[0][0]);
VertexPositionColor cubeVertices[] =
{
{XMFLOAT3(-0.5f, -0.5f, -0.5f), XMFLOAT3(0.0f, 0.0f, 0.0f)},
{XMFLOAT3(-0.5f, -0.5f, 0.5f), XMFLOAT3(0.0f, 0.0f, 1.0f)},
{XMFLOAT3(-0.5f, 0.5f, -0.5f), XMFLOAT3(0.0f, 1.0f, 0.0f)},
{XMFLOAT3(-0.5f, 0.5f, 0.5f), XMFLOAT3(0.0f, 1.0f, 1.0f)},
{XMFLOAT3( 0.5f, -0.5f, -0.5f), XMFLOAT3(1.0f, 0.0f, 0.0f)},
{XMFLOAT3( 0.5f, -0.5f, 0.5f), XMFLOAT3(1.0f, 0.0f, 1.0f)},
{XMFLOAT3( 0.5f, 0.5f, -0.5f), XMFLOAT3(1.0f, 1.0f, 0.0f)},
{XMFLOAT3( 0.5f, 0.5f, 0.5f), XMFLOAT3(1.0f, 1.0f, 1.0f)},
};
unsigned short cubeIndices[] =
{
0,2,1, // -x
1,2,3,
4,5,6, // +x
5,7,6,
0,1,5, // -y
0,5,4,
2,6,7, // +y
2,7,3,
0,4,6, // -z
0,6,2,
1,3,7, // +z
1,7,5,
};
glEnableVertexAttribArray(a_positionColor);
glEnableVertexAttribArray(a_colorColor);
glVertexAttribPointer(a_positionColor, 3, GL_FLOAT, GL_FALSE, sizeof(VertexPositionColor), cubeVertices);
glVertexAttribPointer(a_colorColor, 3, GL_FLOAT, GL_FALSE, sizeof(VertexPositionColor), reinterpret_cast(cubeVertices) + sizeof(XMFLOAT3));
glDrawElements(GL_TRIANGLES, ARRAYSIZE(cubeIndices), GL_UNSIGNED_SHORT, cubeIndices);
glDisableVertexAttribArray(a_positionColor);
glDisableVertexAttribArray(a_colorColor);
}
Android平台上OpenGL ES函數調用時,使用GLES20.來調用,OpenGL ES的函數名是不變的。是以渲染部分如使用Angle Project遷移時需要對代碼稍作調整,但并不複雜。
//sample: Android 的 Draw()函數
public void draw() {
// Add program to OpenGL ES environment
GLES20.glUseProgram(mProgram);
// get handle to vertex shader's vPosition member
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
// Enable a handle to the triangle vertices
GLES20.glEnableVertexAttribArray(mPositionHandle);
// Prepare the triangle coordinate data
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, vertexBuffer);
// get handle to fragment shader's vColor member
mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
// Set color for drawing the triangle
GLES20.glUniform4fv(mColorHandle, 1, color, 0);
// Draw the triangle
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
另兩篇文章:
- 如何在WP8上搭建cocos2d-x的遊戲開發環境
- 遊戲開發架構
傳回首頁>
跨平台移動應用開發的渲染解決方案綜述
在移動裝置上做應用/遊戲開發,實作跨平台是主流。對于應用/遊戲的邏輯功能和核心算法部分,如果是用C++進行開發的,因為iOS/Android/Windows Phone 8/Windows Store均支援Native的C++開發,是以可以輕松的移植到各個平台,應用/遊戲的Backend也有如Photon這樣的跨平台解決方案。對于一部分圖形要求很高的應用,如遊戲和一些UI定制化需求很多的應用,渲染部分往往需要花更多的精力實作移植。對于渲染部分,跨平台開發者有以下三種選擇:
1) 使用已有的一些跨平台圖形解決方案,如cocos2D-x, Unity 3D等遊戲引擎以及HTML5。
2) 将渲染部分在程式設計時獨立,針對不同的平台分别實作渲染。在Windows Phone / Windows Store應用中,DirectX和XAML可以結合使用,進而友善的與第三方SDK結合使用。
3) 将現有的渲染代碼通過工具映射到其他平台。如開源的Angle project可以将OpenGL ES自動映射到DirectX。
本文将分别對這三種選擇依次作介紹,為開發者順利完成應用/遊戲在渲染部分的移植作一個參考。因時間和能力有限,謬誤之處請不吝指教。
(1) 使用遊戲引擎/HTML5等現有的跨平台解決方案
cocos2d-x:cocos2d-x是一個開源免費、易學易用的2D跨平台遊戲引擎,支援Windows Phone, Windows 8, iOS和Android多個平台。目前是國内最流行的2D遊戲引擎。其下載下傳位址為:
http://www.cocos2d-x.org/news/143
Unity 3D: Unity 3D是一個非常強大的商用跨平台開發工具,支援Windows Store, Windows Phone, iOS, Android, Wii等多個平台。Unity 3D是移動平台上3D引擎的領頭羊,同時Unity 3D也能很好的支援2D圖形開發。下載下傳位址:
http://unity3d.com/unity/whats-new/unity-4.3
XNA:XNA可支援Windows, Xbox 360和Window Phone,以前使用XNA開發的針對Window Phone 7.x的遊戲仍然可以在Windows Phone 8上運作。但不支援建立新的目标裝置為WP8的遊戲。請參考:
http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj207003(v=vs.105).aspx
http://msdn.microsoft.com/en-us/library/bb200104.aspx
MonoGame:MonoGame旨在幫助XNA開發者在Windows Phone 8, Windows 8,iOS, Android,Mac,Linux等多個平台實作跨平台開發。官方首頁:
http://www.monogame.net/
在開源平台codeplex上的頁面:http://monogame.codeplex.com/
Marmalade:Marmalade是一個非常有特色的跨平台遊戲引擎,它支援在Windows上将應用Deploy至iOS。支援将OpenGL的程式直接轉換成DirectX11的以移植到Windows Phone平台上。請參考:
https://www.madewithmarmalade.com/
http://www.madewithmarmalade.com/windows-phone-8
HTML5: 除了遊戲引擎,還可以使用HTML5實作跨平台。對Windows Store遊戲,可使用HTML5 和 JavaScript。如果熟悉HTML5 和 JavaScript (WinJS) 的開發,同時遊戲不需要複雜的動畫效果,并且對于遊戲的實時性能沒有非常高的要求,可以考慮這種遊戲開發模式。
推薦使用的情景:充分利用HTML5 和 JavaScript(WinJS)的開發經驗。 友善頁遊的遷移,縮短開發周期
不推薦使用的情景:如果你的遊戲有大量的圖像處理,或者對性能要求很高,使用HTML5 和 JavaScript 開發模式就不太适合你的遊戲。 最好使用DirectX 和 C++ 結合。
請參考:http://msdn.microsoft.com/en-us/library/windows/apps/hh465158.aspx
開發例子:design.htmlwindowsapps/JavaScript-and-HTML5-touch-d96f6031
(2)針對不同平台分别用OpenGL / OpenGL ES或者DirectX實作渲染
在跨平台應用程式設計的時候,我們可以将渲染部分獨立,最簡單的設計是建立 Renderer類,分别針對Windows Phone, iOS和Android實作。衆所周知,OpenGL ES主要用于Android和iOS平台的開發。而WP8和Windows Store使用DirectX11 API。接下來我們重點比較OpenGL和DirectX的異同,供開發者在切換平台時參考。
OpenGL ES / OpenGL與DirectX性能比較
這是一個在OpenGL和DirectX誕生以來很多人比較熱衷于讨論的問題,是以在這裡簡要的提一下。其實一款顯示卡在設計的時候就會考慮要支援OpenGL和DirectX兩種标準的所有feature,而不管是GLSL還是HLSL的shader,在經過驅動編譯後都是在同樣的硬體中同樣的并行計算子產品上運算,紋理等resource也是存儲在同樣的顯存上。OpenGL和DirectX實作的應用程式其性能更多取決于驅動的優化程度而非OpenGL / DirectX API的優劣。OpenGL或者DirectX的API的選擇對遊戲的性能的影響主要局限于CPU部分而不是GPU。例如AMD最近釋出的Mantle API其主要優化也是集中于減少CPU的開銷,且僅适用于AMD顯示卡。而OpenGL和DirectX的API對CPU部分開銷的比較至今沒有一個定論,也即沒有一方是明顯優于另一方。OpenGL ES在設計時是參考OpenGL的,可以說是OpenGL的一個子集,其API也沒有優于DirectX的說法。
開發者如果對遊戲性能有所顧慮,可以更多的可考慮一些平台相關的特性而非API本身。例如在iOS使用pvr格式的紋理(PowerVR的有損壓縮格式),而在Windows平台使用DDS格式的紋理。在下文中有關于手機紋理的詳細說明:
手持平台紋理格式說明
硬體對OpenGL ES和DirectX的支援
在寫這篇文檔的時候(2013年10月),智能手機普遍可以支援OpenGL ES 2.0或以上了。下面的表格列出了OpenGL ES與DirectX的比較。OpenGL ES 2.0相當于DirectX 3D的feature level 9。OpenGL ES 2.0所支援的GLSL對應于DirectX的HLSL。
OpenGL ES版本清單
OpenGL ES版本号 | 對應OpenGL版本 | 對應的DX版本 | 版本特性 |
1.0 | OpenGL 1.3 | 低于DX9 | Fixed function rendering |
1.1 | OpenGL 1.5 | 低于DX9 | Fixed function rendering。雖然OpenGL 1.5中引入了ARB shader,但是OpenGL ES 1.1中仍然是不支援的。 |
2.0 | OpenGL 2.0 | DX9 | 支援GLSL |
3.0 | OpenGL 3.0 | DX10與DX9之間 | 相容OpenGL ES 2.0,但不支援DX10中才有的Geometry Shader, OpenGL自3.2版本開始支援Geometry Shader. |
OpenGL和OpenGL ES詳細資訊可參考Spec或Wiki中的介紹。可參考下面的連結:
http://www.khronos.org/opengles/
http://en.wikipedia.org/wiki/OpenGL
http://en.wikipedia.org/wiki/OpenGL_ES
DirectX 版本(忽略DirectX9以前版本,因為不論WP還是Win8的硬體最低要求都是支援DX 9.1)
DX版本 | 與OpenGL ES對應關系 | 支援的 Shader |
9.x | 功能上相當于OpenGL ES 2.0 | Vertex Shader, Pixel Shader |
10.x | 包含OpenGL ES 3.0的feature | 增加了 Geometry Shader |
11.x | 包含DX10且包含OpenGL ES 3.0 | 增加了 Hull Shader和 Domain Shader |
各應用平台對OpenGL ES、DirectX以及OpenGL(非ES)的支援
Android | iOS | Windows Phone / Windows Store |
根據下面的讨論,在2010年,已經有超過75%的Android裝置可以通過NDK支援OpenGL ES 2.0. 估計目前絕大多數Android裝置均可使用至少OpenGL ES 2.0。 https://groups.google.com/forum/#!topic/android-developers/HBddHFyxYeo 需要Android 4.3或以上才能支援OpenGL ES 3.0 | 從iPhone 3GS開始支援OpenGL ES 2.0. 從iPhone 5S開始支援OpenGL ES 3.0 | 從Windows Phone 8開始支援DirectX 11的API,其feature level是DX 9.3。開發必須使用DirectX 11的API。 Surface RT要求必須能運作DX 9.1的feature。 在Windows Store中針對x86和x64平台可使用DX10和DX11的feature。如無法支援DX9,需要在程式啟動後顯示說明。 在WP8之前的WP,可使用XNA開發,相當于DX9的feature level。 在Windows Store應用中,可使用OpenGL(非ES)開發。參考如下: http://opengl.codeplex.com/ |
OpenGL ES 2.0是目前在iOS和Android平台上通常使用的圖形解決方案,常用的遊戲引擎中的渲染部分是對OpenGL ES的封裝。OpenGL ES 2.0所對應的DirectX 版本是DirectX 9,。而WP8和Windows 8對硬體的最低硬體要求即DX9,這使得基于OpenGL或者遊戲引擎的應用向WP/Windows 8移植變成很自然的事情。
WP8和Windows 8應用商店的應用需要使用DX11的API進行程式設計,我們隻需要将DX11的Feature level設定為DX9即可(參考下面的代碼片斷)對應于OpenGL ES 2.0。對于Windows Store中的應用,我們還可以使用DX10和DX11中的feature, 實作比OpenGL ES 2.0更加強大的渲染功能和更好的性能。
D3D_FEATURE_LEVEL featureLevels[] =
{
D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_9_3,
D3D_FEATURE_LEVEL_9_2,
D3D_FEATURE_LEVEL_9_1
};
D3D_FEATURE_LEVEL APP_MIN_FEATURE_LEVEL = D3D_FEATURE_LEVEL_9_1;
如前所述,其實OpenGL ES 2.0是OpenGL 2.0的子集,對應于DirectX的Feature level 9所能夠實作的功能是相當的。是以能夠使用OpenGL實作的效果,通常也可以使用DirectX實作。Visual Studio支援兩種DirectX的模闆,一種是僅使用DirectX而不使用XAML,另外一種是将DirectX和XAML結合。我們比較推薦的是DirectX和XAML結合。因為XAML中定義的豐富的界面元素,互動的實作更加簡單。第三方的SDK如微網誌,支付相關SDK都需要XAML的支援。在微軟設計DirectX和XAML結合的時候,已經針對不同情景盡可能減少結合時對性能的影響。
XAML與DirectX結合使用的相關文檔請參考:
http://channel9.msdn.com/Events/Windows-Camp/Developing-Windows-8-Metro-style-apps-in-Cpp/Building-Apps-with-Cpp-XAML-and-DirectX
http://blogs.msdn.com/b/windowsappdev/archive/2012/03/15/combining-xaml-and-directx.aspx
http://mobile.dzone.com/articles/directx-and-xaml-windows-phone
不管是OpenGL和DirectX,渲染時都需要維護所謂的Context。在Context中儲存了一些渲染時的狀态資訊,例如是否使用了光照,是否啟用了霧效,目前使用的紋理是什麼等等。一般建立Context的過程都是由平台的模闆自動生成,開發者隻需要對Context進行适當的設定,并調用OpenGL或者DX的API進行渲染即可。OpenGL ES和DX11建立Context以渲染的過程分别如下(謹供參考,一般移動應用的程式員不需要關心細節):

最常見的渲染過程是設定vertex buffer(VB)、index buffer(IB)、紋理、shader、調用繪制函數,最後顯示緩沖中的渲染圖像。下面的表格将主要從這幾個方面對OpenGL ES和DX作比較。
OpenGL ES | DirectX 11 | |
Vertex buffer 和 Index buffer(通常稱VB和IB) 在顯存/記憶體中的存儲方式和二者沒有差別,均按順序線性存放資料。但使用VB和IB的API略不同 | VB和IB中定義的模型通過draw函數繪制。 通常使用glDrawElements函數 偶爾使用glDrawArrays函數(不需要IB) glBegin, glEnd, glVertex3f等OpenGL函數在OpenGL ES中因為效率的考慮已經移除。 | Draw通常使用DrawIndexed繪制VB/IB中的内容 也有DrawInstanced, DrawAuto等函數可供選擇 注意Instancing在DX9中已經支援,在OpenGL 3.0才支援。 在DX 10以後還可通過Geometry shader實作Instancing |
VB中頂點的屬性(Attribute) 如normal, color, texture坐标, position等等 | 使用glVertexAttribPointer函數分别指定頂點的各個屬性 與DX的比較可參考下文: 将 OpenGL ES 2.0 緩沖區、uniform 和頂點屬性與 Direct3D 進行比較 | DX的API中沒有Attribute這個概念,僅使用結構體 D3D11_INPUT_ELEMENT_DESC描述VB中每個頂點的資料格式 m_d3dDevice->CreateInputLayout |
Shader / Program | OpenGL中Shader又叫Program 支援運作時編譯,即GLSL文本在運作時編譯。 分Vertex Program和Fragment Program | 對于Windows Store和WP8需要在編譯時将HLSL編譯成生成僞彙編代碼。如Shader編譯出錯則無法生成可執行檔案。 在DX feature level 9中 分Vertext Shader和Pixel Shader分别對應于GLSL中的Vertex Program 和Fragment Program |
Shader的常數設定 | API中包含Uniform,如: glGetUniformLocation glUniform4fv | 使用Constant Buffer相關函數,如: m_d3dDevice->CreateBuffer m_d3dContext->UpdateSubresource m_d3dContext->VSSetConstantBuffers |
資源管理,如紋理和buffer | 使用glCreateShader, glBufferData, glGenBuffers, glTexImage2D, eglBindTexImage等等API管理資源 | 使用ID3D11Device管理資源。一般會有一個ID3D11Device指針,用以調資源管理的DX API ,如函數CreateTexture2D()。在Windows Store的應用可以使用一些已經封裝好的Loader類加載紋理資源。微軟的Sample中常使用BasicLoader類,程式員可在其基礎上進一步修改增強。 |
Context管理, 用于配置渲染管線 | glAttachShader, glGetUniform*等等API | 一般建立ID3D11DeviceContext類的指針,再使用context指針調用Context配置的API |
顯示緩沖區内容 | 使用SwapChain函數 | 使用Present函數 |
坐标系 X正方向為右,Y正方向為上。 詳細的異同可參考下面: Coordinate Systems (Direct3D 9) | OpenGL使用右手坐标系,是以Z的正方向指向螢幕外。 | DX使用左手坐标系。是以移植時三角形的頂點順序要反向,Z的方向也要反向。 可以使用函數 D3DXMatrixPerspectiveRH 和D3DXMatrixOrthoRH來做右手坐标系的投影映射。詳細請參考最左邊的連結 |
從OpenGL API映射到DirectX 3D的API
======================================
仍在更新的關于OpenGL到DX映射的文檔
http://msdn.microsoft.com/zh-cn/library/windows/apps/dn166866.aspx
常用的EGL API Mapping參考
http://msdn.microsoft.com/zh-cn/library/windows/apps/dn166867.aspx
最後需要指出,DirectX在Windows Phone和Windows Store的應用開發中略有差別,可參考如下:
http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj662930%28v=vs.105%29.aspx
以下是DirectX版本中渲染一個旋轉的立方體的Render函數實作,結合前面描述的OpenGL與DirectX的比較,讀者可與前面Angle Project中RotatingCube的Sample做個比較。
void Sample3DSceneRenderer::Render()
{
// Loading is asynchronous. Only draw geometry after it's loaded.
if (!m_loadingComplete)
{
return;
}
auto context = m_deviceResources->GetD3DDeviceContext();
// Set render targets to the screen.
ID3D11RenderTargetView *const targets[1] = { m_deviceResources->GetBackBufferRenderTargetView() };
context->OMSetRenderTargets(1, targets, m_deviceResources->GetDepthStencilView());
// Prepare the constant buffer to send it to the graphics device.
context->UpdateSubresource(
m_constantBuffer.Get(),
0,
NULL,
&m_constantBufferData,
0,
0
);
// Each vertex is one instance of the VertexPositionColor struct.
UINT stride = sizeof(VertexPositionColor);
UINT offset = 0;
context->IASetVertexBuffers(
0,
1,
m_vertexBuffer.GetAddressOf(),
&stride,
&offset
);
context->IASetIndexBuffer(
m_indexBuffer.Get(),
DXGI_FORMAT_R16_UINT, // Each index is one 16-bit unsigned integer (short).
0
);
context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
context->IASetInputLayout(m_inputLayout.Get());
// Attach our vertex shader.
context->VSSetShader(
m_vertexShader.Get(),
nullptr,
0
);
// Send the constant buffer to the graphics device.
context->VSSetConstantBuffers(
0,
1,
m_constantBuffer.GetAddressOf()
);
// Attach our pixel shader.
context->PSSetShader(
m_pixelShader.Get(),
nullptr,
0
);
// Draw the objects.
context->DrawIndexed(
m_indexCount,
0,
0
);
}
友善開發者使用DirectX進行開發的工具和模闆
=====================================
1. BasicLoader類:是微軟開發的一個用于加載紋理的類,可同步也可異步加載。支援各種圖像格式,也支援DDS格式的紋理。因為該類使用到Wic解碼器用于圖像解碼,而Wic解碼器僅限于PC,在WP上沒有Wic解碼器的支援,是以在WP上推薦使用DDS紋理。
2. 在Visual studio中內建了DDS紋理檢視器,可直接打開DDS檔案。也可提供一些常用的編輯功能。可以選擇不規則區域并編輯。
3. 3D遊戲中常用的FBX檔案也可以在Visual Studio中打開并編輯。
4. DirectX的Debugging在調試時可以打開debugging模式。也可使用DirectX SDK中的工具PIX抓取一段,以單步跟蹤D3D的API call。
5. Codeplex上開源的ToolKit http://directxtk.codeplex.com/wikipage?title=Samples
6. 開發者從頭開始開發的選擇。建立一個WP 8/Windows Store應用的時候,可支援多種模闆,有僅使用DX的模闆,也有用XAML與D3D混編的模闆。比較推薦的方式是使用XAML和DirectX混編的方式以充分結合兩者的強大功能。下圖是在建立一個Windows Phone應用時的模版,其中高亮的是Windows Phone Direct3D with XAML App,而Windows Store裡的模版名為DirectX App,因為Windows Store的模版不僅內建了DirectX 3D,還內建了DirectX 2D和DirectX Write。
在應用開發的架構中,已經将正常的操作完成,如Buffer Chain,重新整理,場景坐标系統設定等等。開發者需要做的是完成渲染和應用的邏輯。
對于Windows Store開發,在Shooting Game的Sample中開發者可學習一個現成的DirectX和XAML結合的遊戲架構,包括關卡設計、應用内購買、互動、渲染和音效等等技術:
http://msdn.microsoft.com/en-us/library/windows/apps/hh780560.aspx
對于Windows Phone中的遊戲開發,下面的Marble Maze這個Sample很不錯:
http://code.msdn.microsoft.com/wpapps/Marble-Maze-sample-for-c9f3706b
C++/CX
因為使用DirectX必須使用native code,是以必須使用C++/CX。這是微軟定義的一個C++ Extension,是相容标準C++的。是以移植C++代碼是非常友善的。C++/CX中有一些非常友善的新特性,掌握起來也不難,可提高使用程式設計效率。如多線程、Lamda表達示等。對于C++程式員來說,快速掌握C++/CX可參考下面的文檔:
多線程程式設計
http://channel9.msdn.com/events/BUILD/BUILD2011/PLAT-203T
C++/CX介紹及參考:
http://blogs.msdn.com/b/vcblog/archive/2012/08/29/cxxcxpart00anintroduction.aspx
3)使用AngleProject将現有的OpenGL ES代碼轉換
Angle是一個開源的項目,用于将OpenGL ES轉成DirectX以在Windows平台中使用。Angle目前是Chrome浏覽器中使用的渲染跨平台解決方案。
https://code.google.com/p/angleproject/
AngleProject編譯方法
https://code.google.com/p/angleproject/wiki/DevSetup
直接使用Angle Project移植OpenGL ES會遇到下面的問題
====================================================
1. Angle使用DirectX 11的部分是針對feature level 10的。而WP8/Surface RT僅支援到feature level 9.
2. Angle是動态在Runtime将GLSL轉成HLSL,而我們需要在編譯時即把GLSH轉成HLSL. WP8不支援Runtime的shader編譯.
Angle Project中對Windows Phone 8 / Windows 8 RT的适配
Angle Project針對Windonws Phone 8/ Windows 8 RT進行了如下适配,并在cocos2d-x中使用
1. 支援編譯時将GLSL轉成HLSL并編譯成.cso。.cso檔案是在Windows Store和Windows Phone平台上HLSL編譯後的檔案。CSO檔案應該是僞彙程式設計式,在經過驅動進一步編譯後可以在顯示卡上運作。
2.将DX10的feature去除,因為WP8隻支援到DX 9.3.
使用了Angle Project且支援WP8的cocos2D-x 2.2下載下傳位址為:
http://www.cocos2d-x.org/news/143
在Angle Project的source code tree中有一個RotatingCube的例子,開發者可參考用于OpenGL ES向WP / Windows Store的移植。
https://github.com/stammen/angleproject/tree/dev/samples/RotatingCube
Anglge project關于WP8的說明如下。簡而言之,Angle對WP8是支援的,對Windows Store 8目前支援有限制,但是如果應用是target到Windows 8.1是支援的。
https://github.com/stammen/angleproject
Angle Project (https://code.google.com/p/angleproject/) with support for Windows Store Apps (WinRT) and Windows Phone Apps (WP8). This version supports developing Windows Store Apps using Visual Studio 2013 and Windows 8.1. It is also ossible to develop a Windows Store App using Visual Studio 2012 and Windows 8.0 but this version will not be accepted in the Windows App Store.
Angle Project的RotatingCube這個Sample其 Render()函數如下。可以看到在例子中繪制使用的API是OpenGL ES的API。存儲頂點資料可以使用directxmath.h中定義的資料結構。
void CubeRenderer::Render()
{
XMFLOAT4X4 mvp;
XMStoreFloat4x4(&mvp, (XMMatrixMultiply(XMMatrixMultiply(m_modelMatrix, m_viewMatrix), m_projectionMatrix)));
glClearColor(0.098f, 0.098f, 0.439f, 1.000f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(m_colorProgram);
glUniformMatrix4fv(u_mvpColor, 1, GL_FALSE, &mvp.m[0][0]);
VertexPositionColor cubeVertices[] =
{
{XMFLOAT3(-0.5f, -0.5f, -0.5f), XMFLOAT3(0.0f, 0.0f, 0.0f)},
{XMFLOAT3(-0.5f, -0.5f, 0.5f), XMFLOAT3(0.0f, 0.0f, 1.0f)},
{XMFLOAT3(-0.5f, 0.5f, -0.5f), XMFLOAT3(0.0f, 1.0f, 0.0f)},
{XMFLOAT3(-0.5f, 0.5f, 0.5f), XMFLOAT3(0.0f, 1.0f, 1.0f)},
{XMFLOAT3( 0.5f, -0.5f, -0.5f), XMFLOAT3(1.0f, 0.0f, 0.0f)},
{XMFLOAT3( 0.5f, -0.5f, 0.5f), XMFLOAT3(1.0f, 0.0f, 1.0f)},
{XMFLOAT3( 0.5f, 0.5f, -0.5f), XMFLOAT3(1.0f, 1.0f, 0.0f)},
{XMFLOAT3( 0.5f, 0.5f, 0.5f), XMFLOAT3(1.0f, 1.0f, 1.0f)},
};
unsigned short cubeIndices[] =
{
0,2,1, // -x
1,2,3,
4,5,6, // +x
5,7,6,
0,1,5, // -y
0,5,4,
2,6,7, // +y
2,7,3,
0,4,6, // -z
0,6,2,
1,3,7, // +z
1,7,5,
};
glEnableVertexAttribArray(a_positionColor);
glEnableVertexAttribArray(a_colorColor);
glVertexAttribPointer(a_positionColor, 3, GL_FLOAT, GL_FALSE, sizeof(VertexPositionColor), cubeVertices);
glVertexAttribPointer(a_colorColor, 3, GL_FLOAT, GL_FALSE, sizeof(VertexPositionColor), reinterpret_cast(cubeVertices) + sizeof(XMFLOAT3));
glDrawElements(GL_TRIANGLES, ARRAYSIZE(cubeIndices), GL_UNSIGNED_SHORT, cubeIndices);
glDisableVertexAttribArray(a_positionColor);
glDisableVertexAttribArray(a_colorColor);
}
Android平台上OpenGL ES函數調用時,使用GLES20.來調用,OpenGL ES的函數名是不變的。是以渲染部分如使用Angle Project遷移時需要對代碼稍作調整,但并不複雜。
//sample: Android 的 Draw()函數
public void draw() {
// Add program to OpenGL ES environment
GLES20.glUseProgram(mProgram);
// get handle to vertex shader's vPosition member
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
// Enable a handle to the triangle vertices
GLES20.glEnableVertexAttribArray(mPositionHandle);
// Prepare the triangle coordinate data
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, vertexBuffer);
// get handle to fragment shader's vColor member
mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
// Set color for drawing the triangle
GLES20.glUniform4fv(mColorHandle, 1, color, 0);
// Draw the triangle
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
另兩篇文章:
- 如何在WP8上搭建cocos2d-x的遊戲開發環境
- 遊戲開發架構