YUV
YUV
是一种彩色编码模型,其中"Y"
表示的是亮度,"U"
表示的是色度,而"V"
表示的是浓度.需要注意的是YUV编码模型的图像数据一般是不能直接去显示的,需要转换为对应的RGB(或者RGBA)才能正常显示图像.
YUV图像是不能直接用于显示,所以需要转换为RGB格式,而YUV转RGB是一个逐像素处理的一个耗时操作,这样的耗时操作在CPU端进行处理无疑效率和性能都过低,所以在实际开发中都是利用GPU强大的并行处理能力才实现YUV转RGB的效果.
OpenGL ES 实现YUV渲染时需要用到的有GL_LUMINANCE
和GL_LUMINANCE_ALPHA
格式的纹理,其中GL_LUMINANCE
纹理是用来加载NV21 Y Plane
的数据,GL_LUMINANCE_ALPHA
纹理是用来加载UV Plane的数据的.
基本内部格式 | 所提取的源颜色(R, G, B, A) |
---|---|
GL_ALPHA | (0, 0, 0, A) |
GL_LUMINANCE | (L, L, L, 1) |
GL_LUMINANCE_ALPHA | (L, L, L, A) |
GL_INTENSITY | (I, I, I, I) |
GL_RGB | (R, G, B, 1) |
GL_RGBA | (R, G, B, A) |
L: 表示亮度, A: 表示透明度
YUV渲染
渲染步骤:
- 1, 生成两个纹理:y_texture和uv_texture,并编译链接着色器程序.
- 2, 确定纹理坐标和对应的顶点坐标
- 3, 分别加载两个NV21的两个Plane数据到纹理,之后加载纹理坐标和顶点坐标到着色器程序.
- 4, 完成绘制
片段着色器.fs文件
#version 300es
precision mediump float;
in vec2 v_texCoord;
layout(location = 0) out vec4 outColor;
uniform sampler2D y_texture;
uniform sampler2d uv_texture;
void main() {
vec3 yuv;
yuv.x = texture(y_texture, v_texCoord).r;
yuv.y = texture(uv_texture, v_texCoord).a-0.5;
yue.z = texture(uv_texture, v_texCorrd).r-0.5;
}
vec3 rgb = mat3(
1.0, 1.0, 1.0,
0.0, -0.344, 1.770,
1.403, -0.714, 0.0)*yuv;
outColor = vec4(rgb, 1);
VBO 和EBO
VBO: 是顶点缓冲区对象,是Vertex Buffer Object的缩写
EBO: 是图元索引缓冲区对象, 是Element Buffer Object的缩写
OpenGL中用于绘制的顶点数据是保存在CPU内存的,所以在调用glDrawArrays和glDrawElement时,需要将顶点数据从CPU内存中拷贝到显存,但是如果每次绘制都需要这要拷贝操作,无疑会造成很大程度上的开销, 所以为了解决这个问题,OpenGL ES 3.0 才引入了VBO和EBO的概念,它们的作用是在显存中提前开辟一块好的内存,用于缓存顶点数据或者图元索引数据, 目的是避免每次绘制时CPU与GPU之间来回调度产生的性能问题,从而最大限度地降低内存宽带和功耗,提高渲染性能;
GL_ARRAY_BUFFER
: 标志指定的缓存区对象是用于保存顶点数据
GL_ELEMENT_ARRAY_BUFFER
: 标志指定的缓存区对象时用于保存图元索引.
VBO和EBO的创建示例
// 1, 创建缓存区, 参数1: 创建的数量 参数2: 缓存区的地址
// glGenBuffers(<#GLsizei n#>, <#GLuint *buffers#>)
// 2, 绑定缓存区, 参数1: 缓存区指定类型的标识. 参数2: 缓存区
glBindBuffer(<#GLenum target#>, <#GLuint buffer#>)
GLuint m_Vboids;
glGenBuffers(2, &m_Vboids); // 这样就成功创建了两个缓存区, 至于是什么类型的缓存区, 在绑定的时候需要指定对应类型标识
// VBO
glBindBuffer(GL_ARRAY_BUFFER, m_Vboids[0]); // 绑定的是一个顶点数据类型, 作用是拷贝顶点数据到显存中
glBufferData(GL_ARRAY_BUFFER, sizeof(verices), verices, GL_STATIC_DRAW); // 以上就是创建一个VBO缓存区
// EBO
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, &m_Vboids[1]); // 绑定了一个EBO的缓存区
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
GL_STATIC_DRAW: 这个标志标识缓存区对象数据被修改了一次, 使用多次,用在绘制
顶点着色器和片元着色器里新增颜色属性
// 顶点着色器
#version 300 es
// 位置变量的属性位置为0
layout(location = 0) in vec4 a_position
// 颜色变量的属性位置为1
layout(location = 1) in vec3 a_color;
// 重点: 向片段着色器输出一个颜色值
out vec3 v_color; // 这个输出值的名称和类型在顶点着色器和片元着色器中的类型和名称必须一模一样.
void main() {
v_color = a_color;
gl_Position = a_position;
}
// 片段着色器
#version 300 es
precision mediump float;
// 从订单着色器传过来的输入值
in vec3 v_color;
out vec4 o_fragColor;
void main() {
o_fragColor = vec4(v_color 1.0);
}
网友评论