HarmonyOS 自适应 VRS OpenGL ES 版
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 // native&arkts交互
│ │ │── render // 渲染
│ │ │── shader // 渲染shader
│ ├── ets
│ │ ├── entryability
│ │ │ └── EntryAbility.ts // 程序入口类
│ │ ├── pages
│ │ │ └── index.ets // 主界面展示类
│ ├── resources // 资源文件目录
│ │ ├── base
│ │ │ ├── media
│ │ │ └── icon.png // 图片资源
│ │ ├── rawfile/model/Sponza
│ │ │ └── sponza.obj // 模型资源
第一步:引入头文件
#include <cstring>
#include <cstdlib>
#include <xengine/xeg_gles_extension.h>
#include <xengine/xeg_gles_adaptive_vrs.h>
这些头文件的作用:
cstring、cstdlib:C++ 标准库xeg_gles_extension.h:XEngine 的 OpenGL ES 扩展接口xeg_gles_adaptive_vrs.h:自适应 VRS 的核心接口
第二步:配置 CMakeLists.txt
find_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 三个库。
第三步:查询设备是否支持
const char* extensions = (const char*)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_t renderWidth = 800;
uint32_t renderHeight = 600;
GLsizei inputSize[2] = {static_cast<GLsizei>(renderWidth), static_cast<GLsizei>(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 sensitivity = 0.15;
HMS_XEG_AdaptiveVRSParameter(XEG_ADAPTIVE_VRS_ERROR_SENSITIVITY, &sensitivity);
设置误差敏感度阈值,取值范围 [0, 1]。值越小,越倾向于高精度渲染;值越大,越倾向于低精度渲染。0.15 是一个比较保守的值,画质影响很小。
设置翻转选项
GLboolean flip = false;
HMS_XEG_AdaptiveVRSParameter(XEG_ADAPTIVE_VRS_FLIP, &flip);
设置是否翻转图像。false 表示不翻转。
第五步:生成着色率纹理
GLuint inputColorImage;
GLuint inputDepthImage;
GLuint outputShadingRateImage;
float *reprojectionMatrix = nullptr;
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 参数配置的决策流程:
OpenGL ES 版和 Vulkan 版的区别
对比一下两个版本:
| 方面 | OpenGL ES 版 | Vulkan 版 |
|---|---|---|
| 查询扩展 | HMS_XEG_GetString | HMS_XEG_EnumerateDeviceExtensionProperties |
| 设置参数 | HMS_XEG_AdaptiveVRSParameter | 通过创建结构体 |
| 生成着色率 | HMS_XEG_DispatchAdaptiveVRS | HMS_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 版本。
更多推荐


所有评论(0)