1背景
上一篇分析到了gl渲染的drawFrame,这一篇继续后续的。
2步骤
2.1 drawYUV
void HGLWidget::drawYUV(HFrame* pFrame) {
assert(pFrame->type == PIX_FMT_IYUV || pFrame->type == PIX_FMT_YV12);
int w = pFrame->w;
int h = pFrame->h;
int y_size = w*h;
GLubyte* y = (GLubyte*)pFrame->buf.base;
GLubyte* u = y + y_size;
GLubyte* v = u + (y_size>>2);
if (pFrame->type == PIX_FMT_YV12) {
GLubyte* tmp = u;
u = v;
v = tmp;
}
glUseProgram(prog_yuv);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex_yuv[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, y);
glUniform1i(texUniformY, 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, tex_yuv[1]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, w/2, h/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, u);
glUniform1i(texUniformU, 1);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, tex_yuv[2]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, w/2, h/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, v);
glUniform1i(texUniformV, 2);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glUseProgram(0);
}
因为上面是OpenGL的语法,从初始化开始分析
2.2 HGLWidget的初始化
void HGLWidget::initializeGL() {
if (!s_glew_init.test_and_set()) {
if (glewInit() != 0) {
s_glew_init.clear();
qFatal("glewInit failed");
return;
}
}
initVAO();
loadYUVShader();
initYUV();
}
2.3 先看initVAO
void HGLWidget::initVAO() {
glVertexAttribPointer(VER_ATTR_VER, 2, GL_FLOAT, GL_FALSE, 0, vertices);
glEnableVertexAttribArray(VER_ATTR_VER);
glVertexAttribPointer(VER_ATTR_TEX, 2, GL_FLOAT, GL_FALSE, 0, textures);
glEnableVertexAttribArray(VER_ATTR_TEX);
}
顶点位置属性配置和纹理坐标属性配置。 查文档可以查到如下 registry.khronos.org/OpenGL-Refp…
glVertexAttribPointer
Parameters
index
Specifies the index of the generic vertex attribute to be modified.
size
Specifies the number of components per generic vertex attribute. Must be 1, 2, 3, or 4. The initial value is 4.
type
Specifies the data type of each component in the array. Symbolic constants GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, GL_UNSIGNED_INT, GL_FLOAT, or GL_DOUBLE are accepted. The initial value is GL_FLOAT.
normalized
Specifies whether fixed-point data values should be normalized (GL_TRUE) or converted directly as fixed-point values (GL_FALSE) when they are accessed.
stride
Specifies the byte offset between consecutive generic vertex attributes. If stride is 0, the generic vertex attributes are understood to be tightly packed in the array. The initial value is 0.
pointer
Specifies a pointer to the first component of the first generic vertex attribute in the array. The initial value is 0.
glEnableVertexAttribArray
Name
glEnableVertexAttribArray — Enable or disable a generic vertex attribute array
C Specification
void glEnableVertexAttribArray( GLuint index);
void glDisableVertexAttribArray( GLuint index);
Parameters
index
Specifies the index of the generic vertex attribute to be enabled or disabled
2.4 loadYUVShader
void HGLWidget::loadYUVShader() {
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
char szVS[] = " \
attribute vec4 verIn; \
attribute vec2 texIn; \
varying vec2 texOut; \
\
void main(){ \
gl_Position = verIn; \
texOut = texIn; \
} \
";
const GLchar* pszVS = szVS;
GLint len = strlen(szVS);
glShaderSource(vs, 1, (const GLchar**)&pszVS, &len);
char szFS[] = " \
varying vec2 texOut; \
uniform sampler2D tex_y; \
uniform sampler2D tex_u; \
uniform sampler2D tex_v; \
\
void main(){ \
vec3 yuv; \
vec3 rgb; \
yuv.x = texture2D(tex_y, texOut).r; \
yuv.y = texture2D(tex_u, texOut).r - 0.5; \
yuv.z = texture2D(tex_v, texOut).r - 0.5; \
rgb = mat3( 1, 1, 1, \
0, -0.39465, 2.03211, \
1.13983, -0.58060, 0) * yuv; \
gl_FragColor = vec4(rgb, 1); \
} \
";
const GLchar* pszFS = szFS;
len = strlen(szFS);
glShaderSource(fs, 1, (const GLchar**)&pszFS, &len);
glCompileShader(vs);
glCompileShader(fs);
//#ifdef _DEBUG
GLint iRet = 0;
glGetShaderiv(vs, GL_COMPILE_STATUS, &iRet);
qDebug("vs::GL_COMPILE_STATUS=%d", iRet);
glGetShaderiv(fs, GL_COMPILE_STATUS, &iRet);
qDebug("fs::GL_COMPILE_STATUS=%d", iRet);
//#endif
prog_yuv = glCreateProgram();
glAttachShader(prog_yuv, vs);
glAttachShader(prog_yuv, fs);
glBindAttribLocation(prog_yuv, VER_ATTR_VER, "verIn");
glBindAttribLocation(prog_yuv, VER_ATTR_TEX, "texIn");
glLinkProgram(prog_yuv);
//#ifdef _DEBUG
glGetProgramiv(prog_yuv, GL_LINK_STATUS, &iRet);
qDebug("prog_yuv=%d GL_LINK_STATUS=%d", prog_yuv, iRet);
//#endif
glValidateProgram(prog_yuv);
texUniformY = glGetUniformLocation(prog_yuv, "tex_y");
texUniformU = glGetUniformLocation(prog_yuv, "tex_u");
texUniformV = glGetUniformLocation(prog_yuv, "tex_v");
qDebug("loadYUVShader ok");
}
创建显卡可执行程序步骤
- glCreateProgram
- glAttachShader vs
- glAttachShader fs
- glLinkProgram
- glUseProgram
其中glAttachShader又可以分为如下步骤
- glCreateShader
- glShaderSource
- glCompileShader
上面处理这些,还绑定了两个顶点变量,以及uniform中的三个变量。
2.5 initYUV
void HGLWidget::initYUV() {
glGenTextures(3, tex_yuv);
for (int i = 0; i < 3; ++i) {
glBindTexture(GL_TEXTURE_2D, tex_yuv[i]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
}
大概是获取三个没使用的材质名,然后分别绑定材质,并设置材质参数
- 纹理放大或者缩小的过滤方式 线性插值
- 纹理坐标超出边缘的处理方式 s为水平方向 t为垂直方向
Name
glGenTextures — generate texture names
C Specification
void glGenTextures( GLsizei n,
GLuint * textures);
Parameters
n
Specifies the number of texture names to be generated.
textures
Specifies an array in which the generated texture names are stored.
Description
glGenTextures returns n texture names in textures. There is no guarantee that the names form a contiguous set of integers; however, it is guaranteed that none of the returned names was in use immediately before the call to glGenTextures.
The generated textures have no dimensionality; they assume the dimensionality of the texture target to which they are first bound (see glBindTexture).
Texture names returned by a call to glGenTextures are not returned by subsequent calls, unless they are first deleted with glDeleteTextures.
2.6 最开始的drawYUV
- 绑定纹理并上传
- 绘制四边形:通过 4 个顶点的三角形带绘制全屏四边形。
- 状态清理:解除着色器程序的绑定。