经过这几天的的开发和调试,KlayGE的所有例子都在NVIDIA的OpenGL ES模拟器上顺利运行了。除了没有GI、distance mapping退化成normal mapping、以及由于缺少float texture而不能实现高精度DoF之外,其他效果都和D3D11和OpenGL一致。

Tegra 2模拟器的问题

NVIDIA的OpenGL ES模拟器的模拟对象是Tegra 2,但支持的扩展不如真的Tegra 2。Tegra 2真机支持的OpenGL ES扩展有(来自Xoom):

GL_ARB_draw_buffers
GL_EXT_bgra
GL_EXT_Cg_shader
GL_EXT_packed_float
GL_EXT_texture_array
GL_EXT_texture_compression_dxt1
GL_EXT_texture_compression_latc
GL_EXT_texture_compression_s3tc
GL_EXT_texture_filter_anisotropic
GL_EXT_texture_format_BGRA8888
GL_EXT_unpack_subimage
GL_NV_coverage_sample
GL_NV_depth_nonlinear
GL_NV_draw_path
GL_NV_fbo_color_attachments
GL_NV_framebuffer_vertex_attrib_array
GL_NV_get_tex_image
GL_NV_platform_binary
GL_NV_read_buffer
GL_NV_shader_framebuffer_fetch
GL_NV_texture_npot_2D_mipmap
GL_OES_byte_coordinates
GL_OES_compressed_ETC1_RGB8_texture
GL_OES_compressed_paletted_texture
GL_OES_draw_texture
GL_OES_EGL_image
GL_OES_EGL_image_external
GL_OES_EGL_sync
GL_OES_extended_matrix_palette
GL_OES_fbo_render_mipmap
GL_OES_fixed_point
GL_OES_framebuffer_object
GL_OES_mapbuffer
GL_OES_matrix_get
GL_OES_matrix_palette
GL_OES_point_size_array
GL_OES_point_sprite
GL_OES_query_matrix
GL_OES_read_format
GL_OES_rgb8_rgba8
GL_OES_single_precision
GL_OES_stencil8
GL_OES_texture_cube_map
GL_OES_texture_float
GL_OES_texture_half_float
GL_OES_vertex_half_float

但模拟器支持的就少多了,只有:

GL_EXT_texture_compression_dxt1
GL_EXT_texture_compression_s3tc
GL_NV_log_textures
GL_OES_compressed_paletted_texture
GL_OES_element_index_uint
GL_OES_framebuffer_object
GL_OES_mapbuffer
GL_OES_rgb8_rgba8
GL_OES_shader_source
GL_OES_stencil8
GL_OES_texture_half_float

在移植各个例子的过程中,遇到的主要问题有:

不支持3D texture

模拟器和真机都没有GL_OES_texture_3D,所以所有需要用到3D texture的地方都无效了。Distance mapping退化成normal mapping,color grading被跳过。所以我在载入纹理的地方加了一段把3D展平成2D长纹理的代码,并在shader里计算纹理坐标。对于较小的纹理没啥问题,但大一点的纹理就可能超过2D纹理的最大限制。

不支持depth texture

在《KlayGE 4.0中Deferred Rendering的改进》中,我提到了用depth texture来省去G-Buffer的一个通道。但在Tegra 2、甚至Tegra 3上,都不支持depth texture。而且Tegra 2也不支持GL_NV_read_depth,所以无法用glReadPixels把depth读回CPU。所以我只能在建立G-Buffer之前,先加一个Pre-Depth pass,从PS输出depth。通过这种方法,才避免了depth texture。

下一步

在模拟器上通过是一回事,在真机上可能很不相同,所以还需做进一步测试。另外,由于硬件的不同,在Tegra 2模拟器上通过了,在其他的模拟器和硬件,比如PowerVR和Mali上也需要单独调试。