
HarmonyOS 自适应 VRS OpenGL ES 版降低 GPU 负载的另一种选择什么是自适应 VRS上一篇我们介绍了用 Vulkan 实现自适应 VRS这篇来看看用 OpenGL ES 怎么做。功能是一样的自动分析画面对不同区域使用不同的渲染精度从而降低 GPU 负载。简单回顾一下 VRS 的原理人眼对画面中心的细节更敏感对边缘区域不太在意。VRS 就是利用这个特点重要的地方精细渲染不重要的地方粗糙渲染既保证视觉效果又提高性能。环境搭建硬件要求设备类型请参考 XEngine 开发指南的硬件要求软件要求DevEco Studio 版本DevEco Studio 6.0.0 Release 及以上HarmonyOS SDK 版本HarmonyOS 6.0.0 Release SDK 及以上搭建步骤安装 DevEco Studio去华为开发者官网下载安装配置开发环境确保网络环境正常设备调试使用真机进行调试项目结构├── entry/src/main // 代码区 │ ├── cpp │ │ ├── types │ │ │ ├── libnativerender │ │ │ └── index.d.ts // native层接口注册文件 │ │ │── napi_init.cpp // native api层接口的具体实现函数 │ │ │── CMakeLists.txt // native层编译配置 │ │ │── 3rdParty // 三方件 │ │ │── common // 通用接口 │ │ │── model // 模型 │ │ │── file // 文件管理 │ │ │── libs // 三方动态库 │ │ │── manager // nativearkts交互 │ │ │── render // 渲染 │ │ │── shader // 渲染shader │ ├── ets │ │ ├── entryability │ │ │ └── EntryAbility.ts // 程序入口类 │ │ ├── pages │ │ │ └── index.ets // 主界面展示类 │ ├── resources // 资源文件目录 │ │ ├── base │ │ │ ├── media │ │ │ └── icon.png // 图片资源 │ │ ├── rawfile/model/Sponza │ │ │ └── sponza.obj // 模型资源第一步引入头文件#includecstring#includecstdlib#includexengine/xeg_gles_extension.h#includexengine/xeg_gles_adaptive_vrs.h这些头文件的作用cstring、cstdlibC 标准库xeg_gles_extension.hXEngine 的 OpenGL ES 扩展接口xeg_gles_adaptive_vrs.h自适应 VRS 的核心接口第二步配置 CMakeLists.txtfind_library( xengine-lib xengine ) find_library( EGL-lib EGL ) find_library( GLES-lib GLESv3 ) target_link_libraries(nativerender PUBLIC ${EGL-lib} ${GLES-lib} ${xengine-lib})链接了xengine、EGL和GLESv3三个库。第三步查询设备是否支持constchar*extensions(constchar*)HMS_XEG_GetString(XEG_EXTENSIONS);if(!strstr(extensions,XEG_ADAPTIVE_VRS_EXTENSION_NAME)){exit(1);// return error}和 Vulkan 版本一样先检查设备是否支持自适应 VRS。OpenGL ES 的查询方式更简单直接调用HMS_XEG_GetString获取扩展列表字符串然后用strstr查找。第四步设置 VRS 参数这是自适应 VRS 的配置步骤需要设置多个参数设置输入尺寸uint32_trenderWidth800;uint32_trenderHeight600;GLsizei inputSize[2]{static_castGLsizei(renderWidth),static_castGLsizei(renderHeight)};HMS_XEG_AdaptiveVRSParameter(XEG_ADAPTIVE_VRS_INPUT_SIZE,inputSize);设置输入图像的尺寸就是上一帧渲染结果的大小。inputSize是一个包含宽高的数组。设置输入区域GLuint inputRegion[4]{0,0,renderWidth,renderHeight};HMS_XEG_AdaptiveVRSParameter(XEG_ADAPTIVE_VRS_INPUT_REGION,inputRegion);设置输入图像的采样区域。inputRegion是一个包含 4 个元素的数组起始坐标 (x, y) 和宽高。从 (0, 0) 开始大小等于渲染分辨率表示处理整个图像。设置分片大小GLsizei texelSizes[2]{8,8};HMS_XEG_AdaptiveVRSParameter(XEG_ADAPTIVE_VRS_TEXEL_SIZE,texelSizes);设置 VRS 的分片大小。画面会被分成很多小块每块独立决定渲染精度。当前支持两种规格[8, 8]8x8 像素一块精度高但计算量大[16, 16]16x16 像素一块精度低但性能好设置误差敏感度GLfloat sensitivity0.15;HMS_XEG_AdaptiveVRSParameter(XEG_ADAPTIVE_VRS_ERROR_SENSITIVITY,sensitivity);设置误差敏感度阈值取值范围 [0, 1]。值越小越倾向于高精度渲染值越大越倾向于低精度渲染。0.15 是一个比较保守的值画质影响很小。设置翻转选项GLboolean flipfalse;HMS_XEG_AdaptiveVRSParameter(XEG_ADAPTIVE_VRS_FLIP,flip);设置是否翻转图像。false表示不翻转。第五步生成着色率纹理GLuint inputColorImage;GLuint inputDepthImage;GLuint outputShadingRateImage;float*reprojectionMatrixnullptr;HMS_XEG_DispatchAdaptiveVRS(reprojectionMatrix,inputColorImage,inputDepthImage,outputShadingRateImage);调用HMS_XEG_DispatchAdaptiveVRS生成着色率纹理。参数说明reprojectionMatrix重投影矩阵用于处理相机运动。如果相机不动传nullptrinputColorImage上一帧的颜色纹理就是渲染出来的彩色画面inputDepthImage深度纹理记录每个像素离相机有多远outputShadingRateImage输出的着色率纹理GPU 会根据它决定每个区域的渲染精度第六步应用着色率纹理HMS_XEG_ApplyAdaptiveVRS(outputShadingRateImage);最后调用HMS_XEG_ApplyAdaptiveVRS把着色率纹理应用到渲染目标中。之后 GPU 在渲染下一帧时就会根据这个纹理来决定每个区域的渲染精度。自适应 VRS 的整体工作流程如下查询设备是否支持自适应VRS设置输入尺寸设置输入区域设置分片大小设置误差敏感度设置翻转选项调用 DispatchAdaptiveVRS分析颜色和深度信息生成着色率纹理调用 ApplyAdaptiveVRSGPU 根据着色率渲染下一帧VRS 参数配置的决策流程精度优先性能优先画质优先性能优先是否开始配置VRS参数选择分片大小8x8 像素分片16x16 像素分片设置误差敏感度较小值 如 0.15较大值 如 0.5相机是否移动?传入重投影矩阵传入 nullptr参数配置完成OpenGL ES 版和 Vulkan 版的区别对比一下两个版本方面OpenGL ES 版Vulkan 版查询扩展HMS_XEG_GetStringHMS_XEG_EnumerateDeviceExtensionProperties设置参数HMS_XEG_AdaptiveVRSParameter通过创建结构体生成着色率HMS_XEG_DispatchAdaptiveVRSHMS_XEG_CmdDispatchAdaptiveVRS应用着色率HMS_XEG_ApplyAdaptiveVRS自动应用销毁实例无需显式销毁HMS_XEG_DestroyAdaptiveVRS主要区别API 风格OpenGL ES 版用函数参数设置Vulkan 版用结构体设置资源管理OpenGL ES 版不需要显式销毁实例Vulkan 版需要命令提交Vulkan 版需要通过命令缓冲区提交OpenGL ES 版直接调用选择哪个版本取决于你的应用已经在用哪个图形 API。适用场景自适应 VRS 特别适合以下场景3D 游戏画面复杂有很多区域可以降低精度VR/AR 应用对帧率要求极高图形渲染应用需要稳定帧率的场景注意事项设备支持不是所有设备都支持自适应 VRS一定要先查询扩展分片大小8x8 精度高但性能开销大16x16 性能好但精度低要根据实际需求选择误差敏感度sensitivity要根据画面质量要求来调整重投影矩阵如果相机在移动需要传入正确的重投影矩阵总结OpenGL ES 版本的自适应 VRS 和 Vulkan 版本功能相同核心流程查询设备是否支持设置参数输入尺寸、分片大小、误差敏感度等调用HMS_XEG_DispatchAdaptiveVRS生成着色率纹理调用HMS_XEG_ApplyAdaptiveVRS应用着色率纹理如果你的应用已经在用 OpenGL ES用这个版本会更方便。如果用的是 Vulkan就用 Vulkan 版本。