2017年10月14日 星期六

在桌機中準備 OpenGL ES 的開發環境

大約在 2013 年中,公司的產品方針由桌機網遊轉變為手遊。由於當時還是採用自製的呈像引擎所以立刻要處理的就是把 Render API 切換為手機上通用的 OpenGL ES 2.0。

雖說手機遊戲最終是運行在手機上,但是為了方便開發和測試,遊戲也必需能在一般的桌機上運行。這一點在現今 Unity 稱霸的時代已經是很基本的需求,但對於當時一切 DIY 的我們來說還算是一項考驗。那時負責呈像的同仁拋出了兩個方案 -- 一是只在手機上使用 OpenGL ES API、桌機環境上維持使用既有的 OpenGL API;二是無論如何都使用 OpenGL ES API,桌機環境上去找 OpenGL ES Emulator 來提供 OpenGL ES 的支持。最後考慮到維護成本採取的是後者,這樣只需要統一維護 OpenGL ES 的部分即可。


當時能免費使用的 OpenGL ES Emulator 記得只有兩個選項: 其一是 Imagination Technology (設計 PowerVR GPU 的公司) 他們提供的免費 PowerVR SDK 中就帶有 OpenGL ES 的 Emualtor。另一個是 AMD 提供的 OpenGL ES SDK,但需要搭配它們家的顯卡。因為公司是統一採購 N 牌顯卡,所以其實只有一條路可走。不過後來證明 PowerVR SDK 的 OpenGL ES Emulator 也是會挑卡,我們包出來的桌機遊戲版本也只能保證在 N 牌 4xx 以後的型號上呈像正常。

直到產品都已經上線營運了,我們才找到更好的替代方案 -- 就是 Google 發展的 ANGLE 專案。它也是目前 Google Chromium、及 Google Chrome 瀏灠器中用來處理 WebGL 呈像的模組。WebGL 的初版 1.0 其實就是基於 OpenGL ES 2.0,所以 ANGLE 非常適合用為桌面環境的 OpenGL ES Emulator。事實上 Unity 也使用 ANGLE,在 Windows 版本中的 Unity Editor 可以透過命令列參數來切換它的 Render API 為 OpenGL ES,在 Unity 的安裝目錄下,於 Editor\libGLESv2.dll 這個檔案內搜尋 "GL_ANGLE",可以找到 ANGLE 實作中獨有的 Extension 名稱。

ANGLE 的運作方式很特別,它是嘗試把所有的 OpenGL ES API、以及所有以 GLSL 編寫的 Shader,都轉換為對等的 DirectX API 呼叫和 HLSL Shader (所以 ANGLE 只有在 Windows 平台有效益)。因此只要是能良好支援 DirectX 9 的顯卡,透過 ANGLE 都可以良好地支援 OpenGL ES 2.0。如果你的顯卡較新、可支援 DirectX 11,那 ANGLE 更可提供 OpenGL ES 3.0 的支援。

身為 DirectX 的原發展者,微軟也維護了一份 ANGLE 的分支,我們兩個版本都試過了,微軟的 ANGLE 版本支援較多的 Extension (請見最後的列表)。而且如果是用 Visual Studio 的環境來開發,微軟版的 ANGLE 直接就可透過 Nuget 來安裝,整合上最便捷。而 Google ANGLE 目前還沒有提供 prebuilt 好的版本可以下載,必需手動由原始碼來建構。或者偷懶一點從其它有使用 ANGLE 的軟體套件中複製出 prebuilt 好的 dll (提示: Qt 或是 Unity 都是好選擇),header 就用 Google ANGLE github 上的那份,再自己生成一下 lib 檔案就可以正常使用了。

以下是我從 Qt 5.5 中抽出的 ANGLE 所返回的 Extension 支援列表:

Using renderer: OpenGL ES 2.0 (ANGLE 2.1.99f075dade7c)
OpenGL_ES
Google Inc.
ANGLE (NVIDIA GeForce GTX 1060 6GB Direct3D11 vs_5_0 ps_5_0)
EGL_EXT_create_context_robustness
EGL_ANGLE_d3d_share_handle_client_buffer
EGL_ANGLE_surface_d3d_texture_2d_share_handle
GL_ANGLE_query_surface_pointer
EGL_ANGLE_window_fixed_size
EGL_KHR_create_context 
GL_OES_element_index_uint
GL_OES_packed_depth_stencil
GL_OES_get_program_binary
GL_OES_rgb8_rgba8
GL_EXT_texture_format_BGRA8888
GL_EXT_read_format_bgra
GL_NV_pixel_buffer_object
GL_OES_mapbuffer
GL_EXT_map_buffer_range
GL_OES_texture_half_float
GL_OES_texture_half_float_linear
GL_OES_texture_float
GL_OES_texture_float_linear
GL_EXT_texture_rg
GL_EXT_texture_compression_dxt1
GL_ANGLE_texture_compression_dxt3
GL_ANGLE_texture_compression_dxt5
GL_EXT_sRGB
GL_ANGLE_depth_texture
GL_EXT_texture_storage
GL_OES_texture_npot
GL_EXT_draw_buffers
GL_EXT_texture_filter_anisotropic
GL_EXT_occlusion_query_boolean
GL_NV_fence
GL_EXT_robustness
GL_EXT_blend_minmax
GL_ANGLE_framebuffer_blit
GL_ANGLE_framebuffer_multisample
GL_ANGLE_instanced_arrays
GL_ANGLE_pack_reverse_row_order
GL_OES_standard_derivatives
GL_EXT_shader_texture_lod
GL_EXT_frag_depth
GL_ANGLE_texture_usage
GL_ANGLE_translated_shader_source


以下是由 Nuget 安裝的微軟版本 ANGLE 所返回的 Extension 支援列表:

Using renderer: OpenGL ES 2.0 (ANGLE 2.1.0.badf00dbad00)
OpenGL_ES
Google Inc.
ANGLE (NVIDIA GeForce GTX 1060 6GB Direct3D11 vs_5_0 ps_5_0)
EGL_EXT_create_context_robustness
EGL_ANGLE_d3d_share_handle_client_buffer
EGL_ANGLE_d3d_texture_client_buffer
EGL_ANGLE_surface_d3d_texture_2d_share_handle
EGL_ANGLE_query_surface_pointer
EGL_ANGLE_window_fixed_size
EGL_ANGLE_keyed_mutex
EGL_ANGLE_surface_orientation
EGL_ANGLE_direct_composition
EGL_NV_post_sub_buffer
EGL_KHR_create_context
EGL_EXT_device_query
EGL_KHR_image
EGL_KHR_image_base
EGL_KHR_gl_texture_2D_image
EGL_KHR_gl_texture_cubemap_image
EGL_KHR_gl_renderbuffer_image
EGL_KHR_get_all_proc_addresses
EGL_KHR_stream
EGL_KHR_stream_consumer_gltexture
EGL_NV_stream_consumer_gltexture_yuv
EGL_ANGLE_flexible_surface_compatibility
EGL_ANGLE_stream_producer_d3d_texture_nv12
EGL_ANGLE_create_context_webgl_compatibility
EGL_CHROMIUM_create_context_bind_generates_resource 
GL_ANGLE_depth_texture
GL_ANGLE_framebuffer_blit
GL_ANGLE_framebuffer_multisample
GL_ANGLE_instanced_arrays
GL_ANGLE_lossy_etc_decode
GL_ANGLE_pack_reverse_row_order
GL_ANGLE_request_extension
GL_ANGLE_robust_client_memory
GL_ANGLE_texture_compression_dxt3
GL_ANGLE_texture_compression_dxt5
GL_ANGLE_texture_usage
GL_ANGLE_translated_shader_source
GL_CHROMIUM_bind_generates_resource
GL_CHROMIUM_bind_uniform_location
GL_CHROMIUM_copy_compressed_texture
GL_CHROMIUM_copy_texture
GL_CHROMIUM_sync_query
GL_EXT_blend_minmax
GL_EXT_color_buffer_half_float
GL_EXT_debug_marker
GL_EXT_discard_framebuffer
GL_EXT_disjoint_timer_query
GL_EXT_draw_buffers
GL_EXT_frag_depth
GL_EXT_map_buffer_range
GL_EXT_occlusion_query_boolean
GL_EXT_read_format_bgra
GL_EXT_robustness
GL_EXT_sRGB
GL_EXT_shader_texture_lod
GL_EXT_texture_compression_dxt1
GL_EXT_texture_filter_anisotropic
GL_EXT_texture_format_BGRA8888
GL_EXT_texture_rg
GL_EXT_texture_storage
GL_EXT_unpack_subimage
GL_KHR_debug
GL_NV_EGL_stream_consumer_external
GL_NV_fence
GL_NV_pack_subimage
GL_NV_pixel_buffer_object
GL_OES_EGL_image
GL_OES_EGL_image_external
GL_OES_compressed_ETC1_RGB8_texture
GL_OES_depth32
GL_OES_element_index_uint
GL_OES_get_program_binary
GL_OES_mapbuffer
GL_OES_packed_depth_stencil
GL_OES_rgb8_rgba8
GL_OES_standard_derivatives
GL_OES_texture_float
GL_OES_texture_float_linear
GL_OES_texture_half_float
GL_OES_texture_half_float_linear
GL_OES_texture_npot
GL_OES_vertex_array_object


以我們的例子來說,因為有使用到 GL_OES_vertex_array_object,就非得用微軟版的不可。

沒有留言:

張貼留言