雖說手機遊戲最終是運行在手機上,但是為了方便開發和測試,遊戲也必需能在一般的桌機上運行。這一點在現今 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,就非得用微軟版的不可。
沒有留言:
張貼留言