OpenGL ES 如何渲染 16bit 图像(P010)?

16bit 图像(P010)

前面讨论关于 YUV 图像 NV21、YUYV 等格式的处理,都是 8 bit YUV 格式,即每个 Y、U、V 分量分别占用 8 个 bit (一个字节)。

可以类比,10bit YUV 就是每个 Y、U、V 分量分别占用 10 个 bit ,但是实际处理中,我们是以字节为单位进行存储和处理的,所以最终处理的数据是以 2 个字节来存储 10bit 的有效数据。

也就是说 10bit YUV ,每个像素( Y 分量)将占用 16bit 两个字节,但是其中 6 个 bit 是 padding ,补 0 。

OpenGL ES 如何渲染 16bit 图像(P010)?
10bit YUV 结构

为什么要了解 10bit YUV ? 最近发现越来越多的视频解码出来是 10bit YUV 的图像,毫无疑问 10bit YUV 会有更好的动态范围,能表现出更丰富的颜色信息

随着移动设备性能不断提升,这种能表现更高动态范围的图像存储格式将会逐渐成为主流,但是现在很多算法都不能直接处理 10bit 的 YUV ,都是先将其转换为 8bit YUV ,然后再进行处理,这实际上是丢弃了 10bit YUV 的图像高动态范围优势。

关于 P010 与 NV21 的转换可以参考文章 10bit YUV(P010)的存储结构和处理 。

OpenGL ES 如何渲染 16bit 图像?

最近有不少读者私信问 OpenGL ES 如何处理 16bit 图像(P010)?

然后我直接贴给他们一段在 OpenGL 环境下验证过的上传 16bit 图像数据的代码

glTexImage2D(GL_TEXTURE_2D, 0, GL_R16UI, width, height, 0, GL_RED_INTEGER, GL_UNSIGNED_SHORT, data);

看了下 OpenGL ES 实际上也是支持这一套格式,但是我之前没有在 GL ES 环境下运行验证过。

OpenGL ES 如何渲染 16bit 图像(P010)?

据读者普遍反馈,这套 16bit 的纹理格式在 ES 上无法正常使用,尽管文档是支持这套格式。

既然直接使用 16bit 的格式不行,也不能直接使用 CPU 转换成 8bit 的图像(性能过慢),又要想 GPU 直接处理 16bit 图像,我觉得可以利用 2 个通道 8bit 格式如 GL_LUMINANCE_ALPHA 或者 GL_RG8 完成加载 16bit 图像数据到纹理,然后采样的时候再将 2 个 8bit 数据转换成 16bit .

在 shader 采样之后,每一个通道的值都会被归一化,8bit 归一化之前的范围是 0~255,16bit 归一化之前的范围是 0~65535, 2 个 8bit 值进行移位求和转成 16bit 值,最后再进行归一化。

对应的片段着色器如下,这里默认 16bit 为小端序。

#version 300 es
precision highp float;
in vec2 v_texCoord;
uniform sampler2D u_texture;
out vec4 outColor;
void main() {
    vec4 col = texture(u_texture, v_texCoord);
    float val = 255.0 * col.r + col.a * 255.0 * pow(2.0, 8.0);
    outColor = vec4(vec3(val / 65535.0), 1.0);
}

加载数据到纹理:

    glBindTexture(GL_TEXTURE_2D, m_uTextureId);

    glTexImage2D ( GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, m_RenderImage.width, m_RenderImage.height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, m_RenderImage.ppPlane[0]);

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glBindTexture(GL_TEXTURE_2D, GL_NONE);

渲染效果与原图一致

OpenGL ES 如何渲染 16bit 图像(P010)?

需要源码的同学可以,可以下方扫码添加我的微信:Byte-Flow 获取。

字节流动

本文来自作者投稿,版权归原作者所有。如需转载,请注明出处:https://www.nxrte.com/zixun/40349.html

(0)

相关推荐

发表回复

登录后才能评论