纹理:GPU中的一块数据结构,YUV数据先经过采样,转成rgb显示。
着色器代码,先通过compile编译成GPU能识别的机器语言,再交由GPU进行显示。
shader着色器,texture纹理,Utility通用工具,context,surface,
vertex shader顶点着色器,fragment shader片元着色器,
实践
1.yuv的字节数
现有宽为w高为h的一个视频,现在定义了一个data[] bytes变量并存储了这个视频的一帧数据。
- bytes数组中,先连续存储每个像素的灰度信息,y通道占w*h个字节;
- 然后顺序存储颜色数据,u和v分别占一个字节,每个颜色数据共占2个字节,所以uv通道占(w/2)(h/2)2=w*h/2个字。
2.纹理
2.1 纹理的组成
- y通道的数据生成一个opengl纹理;
- uv通道的数据生成一个opengl纹理;
- 两个纹理作为渲染时的输入,在渲染过程中由GPU组装还原出来视频画面。
yv12是三个纹理是y一个,u一个,v一个;nv12是y一个,uv一个。
2.2 纹理格式
GL_LUMINANCE 和 GL_LUMINANCE_ALPHA 格式的纹理。
- GL_LUMINANCE 纹理用来加载 NV21 Y Plane 的数据;
- GL_LUMINANCE_ALPHA 纹理用来加载 UV Plane 的数据。
基本内部格式 | 所提取的颜色 |
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) |
3. YUV渲染步骤
- 第一步:初始化上下文
- 第二步:初始化着色器程序(编译链接着色器程序,生成2个纹理-->确定纹理坐标及对应的顶点坐标-->加载纹理坐标和顶点坐标数据到着色器程序);
- 第三步:初始化buffer;
- 第四步:初始化纹理(分别加载NV21的两个Plane数据到2个纹理);
- 第五步:绘制。
4.代码案例
在OpenGL中,片元着色器最后输出的都是rgba的数据,所以使用OpenGL来渲染YUV数据的关键还是将YUV数据传递给着色器,并在着色器中将YUV转化为RGB。
OpenGL ES 系列教程_hongge372的博客-CSDN博客_opengles教程
第一步:初始化上下文
void initContextGL(const char* hWindow)
{
// double dpr = emscripten_get_device_pixel_ratio();
// emscripten_set_element_css_size(hWindow, nWmdWidth / dpr, nWndHeight / dpr);
// emscripten_set_canvas_element_size(hWindow, nWmdWidth, nWndHeight);
// printf("create size success\n");
EmscriptenWebGLContextAttributes attrs;
emscripten_webgl_init_context_attributes(&attrs);
attrs.alpha = 0;
#if MAX_WEBGL_VERSION >= 2
attrs.majorVersion = 2;
#endif
EMSCRIPTEN_WEBGL_CONTEXT_HANDLE glContext = emscripten_webgl_create_context(hWindow, &attrs);
assert(glContext);
EMSCRIPTEN_RESULT res=emscripten_webgl_make_context_current(glContext);
assert(res == EMSCRIPTEN_RESULT_SUCCESS);
assert(emscripten_webgl_get_current_context() == glContext);
printf("create context success 1730\n");
}
第二步:初始化着色器程序
/*顶点着色器代码*/
static const char g_pGLVS[] = ///<普通纹理渲染顶点着色器
{
"precision mediump float;"
"attribute vec4 position; "
"attribute vec4 texCoord; "
"varying vec4 pp; "
"void main() "
"{ "
" gl_Position = position; "
" pp = texCoord; "
"} "
};
/*像素着色器代码*/
const char* g_pGLFS = ///<YV12片段着色器
{
"precision mediump float;"
"varying