首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >不同的GL着色器来自不同的平台/hw(YUV到RGB)

不同的GL着色器来自不同的平台/hw(YUV到RGB)
EN

Stack Overflow用户
提问于 2017-09-15 08:53:01
回答 1查看 489关注 0票数 0

我编写了一个WebGL着色器,它通过3个不同的纹理单元呈现yuv420p图片(因此它也可以处理平面422,444 .)。您可以在浏览器这里上运行它。这里是我转换yuv文件的原始图像。

我用以下内容创建了YUV文件:

代码语言:javascript
运行
AI代码解释
复制
ffmpeg -i color-test.jpg -pix_fmt yuvj420p -f rawvideo color-test.yuv

我显式地使用yuvj420p而不是yuv420p来获得完整的范围值(0-255)。因此,如果我要在生产中使用这个代码,我会添加一些制服来调整颜色范围。

顶点着色器

代码语言:javascript
运行
AI代码解释
复制
attribute vec3 a_pos;
attribute vec2 a_uv;

uniform mat4 u_mvp;

varying vec2 v_uv;


void main () {
  gl_Position = u_mvp * vec4(a_pos, 1.0);
  v_uv = a_uv;
}

片段着色器

代码语言:javascript
运行
AI代码解释
复制
precision mediump float;

uniform sampler2D u_texY;
uniform sampler2D u_texU;
uniform sampler2D u_texV;
uniform vec4 u_diffuse;

varying vec2 v_uv;

// YUV to RGB coefficient matrix.
const mat3 coeff = mat3(
  1.0, 1.0, 1.0,
  0.0, -0.21482, 2.12798,
  1.28033, -0.38059, 0.0
);


void main () {
  vec3 yuv = vec3(texture2D(u_texY, v_uv).a, texture2D(u_texU, v_uv).a, texture2D(u_texV, v_uv).a) * 2.0 - 1.0;
  vec3 colour = (coeff * yuv + 1.0) / 2.0;

  gl_FragColor = u_diffuse * vec4(colour, 1.0);
}

系数矩阵为BT.709 rec(这个wiki页面)的系数矩阵。u_diffuse通常是vec4(1.0, 1.0, 1.0, 1.0),除非您想用特定的颜色来分散图片。

纹理上传

纹理上传如下(第233行):

代码语言:javascript
运行
AI代码解释
复制
  gl.activeTexture(gl.TEXTURE0);
  gl.bindTexture(gl.TEXTURE_2D, tex.y);
  gl.texImage2D(gl.TEXTURE_2D, 0, gl.ALPHA, rp.yuv.meta.width, rp.yuv.meta.height, 0, gl.ALPHA, gl.UNSIGNED_BYTE, picture.y);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);

CLAMP_TO_EDGE用于处理图像的任何维度(任何可被2整除的维度)。请注意,纹理在每次抽签回调时都会更新。这是故意的,因为通常情况下,我们必须更新纹理,每次从视频解码器移交图片。

问题

最明显的问题是,呈现的图像明显不同于图像查看器应用程序(即web浏览器)的呈现。这些程序可能是用CPU将图像从YUV扩展到RGB。我想这是最准确的转换方式。在我的节目里到底是什么原因造成的?我已经做了我的研究,但我无法得到一个明确的解释。浮点精度?

这一问题进一步扩大。不同设备的颜色不同。例如,这个女人在我的android手机上和我的电脑上看起来有点不同。同样的情况也发生在Linux和Windows浏览器上。当我测量右下角黑匣子的颜色时,我在站台/hw上得到了“不同的黑色”。

  • Linux上的Chrome:#060106
  • Linux上的Firefox:#010001
  • 安卓上的Chrome:#060006
  • Windows上的Chrome/Firefox/Oprea:#060106

有什么办法缓解这种情况吗?为什么我不能得到“真正的”黑色(#000000)?

额外位

我不只是担心这一点,因为有些人确实注意到了这种差异。有一天,当我在我的办公室工作时,这位客户坚持我的视频播放器的颜色与另一家公司的程序不同。没有人知道为什么(没有其他程序的源代码)。但似乎其他程序在RGB表面上呈现,而我的程序则在YUV DirectX表面上呈现。所以他们必须从CPU进行转换,如果是这样的话。它看起来不同的原因可能有很多。可能是颜色范围一些吉米用的坏系数..。名单可能会继续下去。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-09-18 04:54:22

你在假设你的色度样本位置在哪里,它并不总是紫外线纹理的中间位置。

你是线性插值的YUV样本,仍然是在非线性伽马。

YUV的色域大于RGB的色域(您将得到0到1 RGB范围之外的值),因此您需要剪辑或重新映射颜色值。

并不是所有的图形堆栈都正确地处理RGB输出伽马,所以您可能会发现GPU发射的伽马和显示器如何解释它之间的不匹配。

另外,你确定你得到了一个BT.709输入吗?其他格式的色度常数不同,即使内存中的像素填充格式是相同的(无论是恢复RGB,还是使用窄或宽的色域)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46244345

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档