GLESv2 #添加本地库 android
${log_lib} )
至此,对于 OpenGL 的开发需要用到的头文件以及库文件就引入完毕了,下面再来看看如何使用 EGL 搭建出 OpenGL 的上下文环境以及渲染视频数据。
-
- 使用 EGL 首先必须创建,建立本地窗口系统和 OpenGL ES 的连接
//1.获取原始窗口 nativeWindow = ANativeWindow_fromSurface(env, surface); //获取Display display = eglGetDisplay(EGL_DEFAULT_DISPLAY); if (display == EGL_NO_DISPLAY) { LOGD(“egl display failed”); showMessage(env, “egl display failed”, false); return; }
//初始化egl,后两个参数为主次版本号 if (EGL_TRUE != eglInitialize(display, 0, 0)) { LOGD(“eglInitialize failed”); showMessage(env, “eglInitialize failed”, false); return; }
//surface 配置,可以理解为窗口 EGLConfig eglConfig; EGLint configNum; EGLint configSpec[] = { EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_NONE };
if (EGL_TRUE != eglChooseConfig(display, configSpec, &eglConfig, 1, &configNum)) { LOGD(“eglChooseConfig failed”); showMessage(env, “eglChooseConfig failed”, false); return; }
//创建surface(egl和NativeWindow进行关联。最后一个参数为属性信息,0表示默认版本) winSurface = eglCreateWindowSurface(display, eglConfig, nativeWindow, 0); if (winSurface == EGL_NO_SURFACE) { LOGD(“eglCreateWindowSurface failed”); showMessage(env, “eglCreateWindowSurface failed”, false); return; }
//4 创建关联上下文 const EGLint ctxAttr[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; //EGL_NO_CONTEXT表示不需要多个设备共享上下文 context = eglCreateContext(display, eglConfig, EGL_NO_CONTEXT, ctxAttr); if (context == EGL_NO_CONTEXT) { LOGD(“eglCreateContext failed”); showMessage(env, “eglCreateContext failed”, false); return; }
-
- 指定某个 EGLContext 为当前上下文, 关联起来
//将egl和opengl关联 //两个surface一个读一个写。第二个一般用来离线渲染 if (EGL_TRUE != eglMakeCurrent(display, winSurface, winSurface, context)) { LOGD(“eglMakeCurrent failed”); showMessage(env, “eglMakeCurrent failed”, false); return; }
GLint vsh = initShader(vertexShader, GL_VERTEX_SHADER); GLint fsh = initShader(fragYUV420P, GL_FRAGMENT_SHADER);
//创建渲染程序 GLint program = glCreateProgram(); if (program == 0) { LOGD(“glCreateProgram failed”); showMessage(env, “glCreateProgram failed”, false); return; }
//向渲染程序中加入着色器 glAttachShader(program, vsh); glAttachShader(program, fsh);
//链接程序 glLinkProgram(program); GLint status = 0; glGetProgramiv(program, GL_LINK_STATUS, &status); if (status == 0) { LOGD(“glLinkProgram failed”); showMessage(env, “glLinkProgram failed”, false); return; } LOGD(“glLinkProgram success”); //激活渲染程序 glUseProgram(program);
//加入三维顶点数据 static float ver[] = { 1.0f, -1.0f, 0.0f, -1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f, -1.0f, 1.0f, 0.0f };
GLuint apos = static_cast(glGetAttribLocation(program, “aPosition”)); glEnableVertexAttribArray(apos); glVertexAttribPointer(apos, 3, GL_FLOAT, GL_FALSE, 0, ver);
//加入纹理坐标数据 static float fragment[] = { 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f }; GLuint aTex = static_cast(glGetAttribLocation(program, “aTextCoord”)); glEnableVertexAttribArray(aTex); glVertexAttribPointer(aTex, 2, GL_FLOAT, GL_FALSE, 0, fragment);
//纹理初始化 //设置纹理层对应的对应采样器?
/**
- //获取一致变量的存储位置
GLint textureUniformY = glGetUniformLocation(program, “SamplerY”); GLint textureUniformU = glGetUniformLocation(program, “SamplerU”); GLint textureUniformV = glGetUniformLocation(program, “SamplerV”); //对几个纹理采样器变量进行设置 glUniform1i(textureUniformY, 0); glUniform1i(textureUniformU, 1); glUniform1i(textureUniformV, 2); */ //对sampler变量,使用函数glUniform1i和glUniform1iv进行设置 glUniform1i(glGetUniformLocation(program, “yTexture”), 0); glUniform1i(glGetUniformLocation(program, “uTexture”), 1); glUniform1i(glGetUniformLocation(program, “vTexture”), 2); //纹理ID GLuint texts[3] = {0}; //创建若干个纹理对象,并且得到纹理ID glGenTextures(3, texts);
//绑定纹理。后面的的设置和加载全部作用于当前绑定的纹理对象 //GL_TEXTURE0、GL_TEXTURE1、GL_TEXTURE2 的就是纹理单元,GL_TEXTURE_1D、GL_TEXTURE_2D、CUBE_MAP为纹理目标 //通过 glBindTexture 函数将纹理目标和纹理绑定后,对纹理目标所进行的操作都反映到对纹理上 glBindTexture(GL_TEXTURE_2D, texts[0]); //缩小的过滤器 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //放大的过滤器 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //设置纹理的格式和大小 // 加载纹理到 OpenGL,读入 buffer 定义的位图数据,并把它复制到当前绑定的纹理对象 // 当前绑定的纹理对象就会被附加上纹理图像。 //width,height表示每几个像素公用一个yuv元素?比如width / 2表示横向每两个像素使用一个元素? glTexImage2D(GL_TEXTURE_2D, 0,//细节基本 默认0 GL_LUMINANCE,//gpu内部格式 亮度,灰度图(这里就是只取一个亮度的颜色通道的意思) width,//加载的纹理宽度。最好为2的次幂(这里对y分量数据当做指定尺寸算,但显示尺寸会拉伸到全屏?) height,//加载的纹理高度。最好为2的次幂 0,//纹理边框 GL_LUMINANCE,//数据的像素格式 亮度,灰度图 GL_UNSIGNED_BYTE,//像素点存储的数据类型 NULL //纹理的数据(先不传) );
//绑定纹理 glBindTexture(GL_TEXTURE_2D, texts[1]); //缩小的过滤器 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //设置纹理的格式和大小 glTexImage2D(GL_TEXTURE_2D, 0,//细节基本 默认0 GL_LUMINANCE,//gpu内部格式 亮度,灰度图(这里就是只取一个颜色通道的意思) width / 2,//u数据数量为屏幕的4分之1 height / 2, 0,//边框 GL_LUMINANCE,//数据的像素格式 亮度,灰度图 GL_UNSIGNED_BYTE,//像素点存储的数据类型 NULL //纹理的数据(先不传) );
//绑定纹理 glBindTexture(GL_TEXTURE_2D, texts[2]); //缩小的过滤器 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //设置纹理的格式和大小 glTexImage2D(GL_TEXTURE_2D, 0,//细节基本 默认0 GL_LUMINANCE,//gpu内部格式 亮度,灰度图(这里就是只取一个颜色通道的意思) width / 2, height / 2,//v数据数量为屏幕的4分之1 0,//边框 GL_LUMINANCE,//数据的像素格式 亮度,灰度图 GL_UNSIGNED_BYTE,//像素点存储的数据类型 NULL //纹理的数据(先不传) );
unsigned char *buf[3] = {0}; buf[0] = new unsigned char[width * height];//y buf[1] = new unsigned char[width * height / 4];//u buf[2] = new unsigned char[width * height / 4];//v
showMessage(env, “onSucceed”, true);
FILE *fp = fopen(data_source, “rb”); if (!fp) { LOGD(“oepn file %s fail”, data_source); return; }
while (!feof(fp)) { //解决异常退出,终止读取数据 if (!isPlay) return; fread(buf[0], 1, width * height, fp); fread(buf[1], 1, width * height / 4, fp); fread(buf[2], 1, width * height / 4, fp);
//激活第一层纹理,绑定到创建的纹理 //下面的width,height主要是显示尺寸? glActiveTexture(GL_TEXTURE0); //绑定y对应的纹理 glBindTexture(GL_TEXTURE_2D, texts[0]); //替换纹理,比重新使用glTexImage2D性能高多 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,//相对原来的纹理的offset width, height,//加载的纹理宽度、高度。最好为2的次幂 GL_LUMINANCE, GL_UNSIGNED_BYTE, buf[0]);
//激活第二层纹理,绑定到创建的纹理 glActiveTexture(GL_TEXTURE1); //绑定u对应的纹理 glBindTexture(GL_TEXTURE_2D, texts[1]); //替换纹理,比重新使用glTexImage2D性能高 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width / 2, height / 2, GL_LUMINANCE, GL_UNSIGNED_BYTE, buf[1]);
//激活第三层纹理,绑定到创建的纹理 glActiveTexture(GL_TEXTURE2); //绑定v对应的纹理 glBindTexture(GL_TEXTURE_2D, texts[2]); //替换纹理,比重新使用glTexImage2D性能高 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width / 2, height / 2, GL_LUMINANCE, GL_UNSIGNED_BYTE, buf[2]);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); //8. 窗口显示,交换双缓冲区 eglSwapBuffers(display, winSurface); }
-
- 交换 EGL 的 Surface 的内部缓冲和 EGL 创建的和平台无关的窗口 diaplay
//窗口显示,交换双缓冲区 eglSwapBuffers(display, winSurface); 复制代码
/**
- 销毁数据
*/ void Gles_play::release() { if (display || winSurface || context) { //销毁显示设备 eglDestroySurface(display, winSurface); //销毁上下文 eglDestroyContext(display, context); //释放窗口 ANativeWindow_release(nativeWindow); //释放线程 eglReleaseThread(); //停止 eglTerminate(display); eglMakeCurrent(display, winSurface, EGL_NO_SURFACE, context); context = EGL_NO_CONTEXT; display = EGL_NO_SURFACE; winSurface = nullptr; Surface(display, winSurface); //销毁上下文 eglDestroyContext(display, context); //释放窗口 ANativeWindow_release(nativeWindow); //释放线程 eglReleaseThread(); //停止 eglTerminate(display); eglMakeCurrent(display, winSurface, EGL_NO_SURFACE, context); context = EGL_NO_CONTEXT; display = EGL_NO_SURFACE; winSurface = nullptr;
|