【问题标题】:Using webgl to render high bit-depth textures to the screen使用 webgl 将高位深度的纹理渲染到屏幕上
【发布时间】:2020-06-09 15:15:41
【问题描述】:

我们的项目使用位深高于 8 位(通常为 10 位)的图像。这些以 16 位 PNG 格式存储,具有 P3 颜色空间(因此每个通道有 1024 种颜色)。

我正在尝试在使用 WebGL2 的浏览器中显示这些图像。到目前为止没有运气。我知道 Chrome 可以做到这一点,因为我有一些测试图像在我的 Macbook 的视网膜屏幕上显示了扩展的颜色范围(但不是在 8 位外接显示器上)。

这是测试图片:https://webkit.org/blog-files/color-gamut/Webkit-logo-P3.png(来源:https://webkit.org/blog/6682/improving-color-on-the-web/

如果您使用的是 8 位屏幕和硬件,测试图像将看起来完全是红色的。如果您有一个高位深度监视器,您会看到一个微弱的 webkit 徽标。尽管我的高位深度监视器在 Chrome 中显示了徽标细节,但应用此纹理的 WebGL 四边形看起来是纯红色的。

我的研究表明,WebGL/OpenGL 确实提供了对浮点纹理和高位深度的支持,至少在绘制到渲染目标时是如此。

我想要实现的很简单,在 WebGL 中使用高位深度纹理,应用于屏幕四边形。这是我加载纹理的方式:

var texture = gl.createTexture();
gl.activeTexture(gl.TEXTURE0 + 0);
gl.bindTexture(gl.TEXTURE_2D, texture);

// Store as a 16 bit float
var texInternalFormat = gl.RGBA16F;
var texFormat = gl.RGBA16F;
var texType = gl.FLOAT;

var image = new Image();
image.src = "10bitTest.png";
image.addEventListener('load', function() {
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.texImage2D(
    gl.TEXTURE_2D,
    0,
    texInternalFormat,
    texFormat,
    texType,
    image
    );
    gl.generateMipmap(gl.TEXTURE_2D);
});

这失败了

 WebGL: INVALID_ENUM: texImage2D: invalid format

如果我将 texFormat 更改为 gl.RBGA,它会渲染四边形,但是是纯红色,没有扩展颜色。

我想知道它是否可能,虽然 Chrome 可以做到,所以我仍然抱有希望。

【问题讨论】:

  • 除非RENDERBUFFER_INTERNAL_FORMAT 每种颜色的位数超过 8 位(请参阅thisthis),否则不可能实现此功能。
  • RGBA16F 不是有效格式。 RGBA16F 的内部格式的正确格式是 RGBA(正如您已经注意到的)。格式仅指定传入数据(image),与纹理的存储或渲染方式无关。
  • @Ivella 不是用于渲染纹理的 RENDERBUFFER_INTERNAL_FORMAT 吗?我只是想渲染到屏幕上
  • 注意:“扩展颜色”(如您所写)与更高位无关(更高位我们倾向于扩展颜色,但我们使用了多年 DCI-P3 或 Adob​​eRGB“8位数据”屏幕(硬件校准,因此面板可以做更多,就像现代好的 10 位屏幕具有 14 或 16 位功能);所以这些是正交的东西)。所以我不确定你是否正在寻找问题的正确部分。
  • @sipi 您找到解决方法了吗?顺便说一下,这里是纹理内部格式、格式和类型的可能组合的官方列表:khronos.org/registry/webgl/specs/latest/2.0/…

标签: colors webgl color-space webgl2


【解决方案1】:

阿法伊克

  1. 您不能(截至 2020 年 6 月)在任何浏览器中创建每个通道超过 8 位的画布。有提案但没有发货

  2. 您无法通过imgImageBitmap 将> 8 位/通道图像加载到WebGL。没有tests 数据> 8bits 进入纹理。

如果您在 JavaScript 中自己解析和加载图像,则可以将每通道 8 位以上的图像加载到纹理中,但随后又回到问题 #1,即除了将其绘制成每通道 8 位之外,您无法显示它帆布。您可以将数据拉回 JavaScript,生成一个 16 位图像 blob,获取该 blob 的 URL,使用该 URL 添加一个 img 标记,并祈祷浏览器支持以每个通道 > 8 位进行绘制。

【讨论】:

  • 您说“如果您自己在 JavaScript 中解析和加载图像,您可以将每通道大于 8 位的图像加载到纹理中”...您知道如何对帧执行此操作吗?视频流?
  • 另外,关于将高深度图像加载到 WebGL 中,这不是这个 Chromium 问题(在 2019 年修复)应该支持的吗? bugs.chromium.org/p/chromium/issues/detail?id=624436#c76
  • 他们在 AFAIK 中破解了它。它不是规范的一部分。有 tests 和 AFAIK 他们不测试 16 位图像。浏览器支持什么格式取决于浏览器。例如 Safari 不支持 webm 或 webp (9/2020)。其次,如果没有一致性测试,您可以指望它不起作用。一致性测试测试例如 8 位 png 的二进制数据使其完美地变成纹理,即使默认情况下浏览器可能颜色正确。其他格式未针对二进制相等性进行 AFAIK 测试。
  • 因此,虽然您可以上传任何图像并要求 FLOAT 数据,但您不能确定数据不是从 8 位升级而来的并且有损。除非他们添加了需要它的一致性测试。你能做的最好的就是测试。制作一个 1 到 4 像素的浮动图像,将其作为 FLOAT 上传到纹理。以您可以判断数据是否丢失的方式呈现和读取结果。与 16 位图像相同。
  • 感谢您的澄清。 CG 并不是我真正的专业领域,所以我正在努力从热像仪中读取温度,热像仪以 16 位图像流式传输帧。随着当今高深度设备的普及,令人惊讶地发现浏览器仍然停留在每通道 8 位。
【解决方案2】:

郑重声明,目前这是不可能的。最近的活动看起来很有希望:

https://bugs.chromium.org/p/chromium/issues/detail?id=1083693&can=2&q=component%3ABlink%3ECanvas%20colorspace

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-11
    • 1970-01-01
    • 1970-01-01
    • 2011-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多