您当前的位置: 首页 > 学无止境 > 心得笔记 网站首页心得笔记
9. opengl的yuv纹理的创建和初始化~1
发布时间:2021-06-07 17:24:54编辑:雪饮阅读()
创建纹理数据需要对纹理的第一层、第二层、第三层分别进行缩小与放大的过滤、纹理格式和大小的设置。
具体实例:cpp/native-lib.cpp:
#include <jni.h>
#include <string>
#include <android/log.h>
#include <android/native_window_jni.h>
#include <EGL/egl.h>
#include <GLES2/gl2.h>
#define LOGD(...) __android_log_print(ANDROID_LOG_WARN,"testff",__VA_ARGS__)
//顶点着色器glsl ,一元运算符 # 常称为字符串化运算符,這裏用在宏定義上,則這裏的x會被展開為"x"字面量形式
#define GET_STR(x) #x
static const char *vertexShader = GET_STR(
attribute vec4 aPosition; //顶点坐标
attribute vec2 aTexCoord; //材质顶点坐标
varying vec2 vTexCoord; //输出的材质坐标
void main(){
vTexCoord = vec2(aTexCoord.x,1.0-aTexCoord.y);
gl_Position = aPosition;
}
);
//片元着色器,软解码和部分x86硬解码
static const char *fragYUV420P = GET_STR(
precision mediump float; //精度
varying vec2 vTexCoord; //顶点着色器传递的坐标
uniform sampler2D yTexture; //输入的材质(不透明灰度,单像素)
uniform sampler2D uTexture;
uniform sampler2D vTexture;
void main(){
vec3 yuv;
vec3 rgb;
yuv.r = texture2D(yTexture,vTexCoord).r;
//這裏一般減去0.5去做個四捨五入
yuv.g = texture2D(uTexture,vTexCoord).r - 0.5;
yuv.b = texture2D(vTexture,vTexCoord).r - 0.5;
//一個yuv轉rgb的公式
rgb = mat3(1.0, 1.0, 1.0,
0.0,-0.39465,2.03211,
1.13983,-0.58060,0.0)*yuv;
//输出像素颜色
gl_FragColor = vec4(rgb,1.0);
}
);
GLint InitShader(const char *code,GLint type)
{
//创建shader
GLint sh = glCreateShader(type);
if(sh == 0)
{
LOGD("glCreateShader %d failed!",type);
return 0;
}
//加载shader,最后一个参数代码长度,传0表示直接找到字符串的结尾
glShaderSource(sh,
1, //shader数量
&code, //shader代码
0); //代码长度
//编译shader
glCompileShader(sh);
//获取编译情况
GLint status;
glGetShaderiv(sh,GL_COMPILE_STATUS,&status);
if(status == 0)
{
LOGD("glCompileShader failed!");
return 0;
}
LOGD("glCompileShader success!");
return sh;
}
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_yuv_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}extern "C"
JNIEXPORT void JNICALL
Java_com_example_yuv_XPlay_Open(JNIEnv *env, jobject thiz, jstring url_, jobject surface) {
const char *url=env->GetStringUTFChars(url_,0);
LOGD("open url is %s",url);
//獲取原始窗口
ANativeWindow *nwin=ANativeWindow_fromSurface(env,surface);
//1 display創建和初始化
EGLDisplay display=eglGetDisplay(EGL_DEFAULT_DISPLAY);
if(display==EGL_NO_DISPLAY){
LOGD("eglGetDisplay failed!");
return;
}
if(EGL_TRUE!=eglInitialize(display,0,0)){
LOGD("eglInitialize failed");
return;
}
//2 surface
//2-1 surface窗口配置
//輸出配置
EGLConfig config;
EGLint configNum;
//c語言數組結束填充,這裏用EGL_NONE
EGLint configSpec[]={
EGL_RED_SIZE,8,
EGL_GREEN_SIZE,8,
EGL_BLUE_SIZE,8,
EGL_SURFACE_TYPE,EGL_WINDOW_BIT,
EGL_NONE
};
//EGL_TRUE的宏定義值為1
if(EGL_TRUE!=eglChooseConfig(display,configSpec,&config,1,&configNum)){
LOGD("eglChooseConfig failed!");
return;
}
//創建surface
EGLSurface winsurface=eglCreateWindowSurface(display,config,nwin,0);
if(winsurface==EGL_NO_SURFACE){
LOGD("eglCreateWindowSurface failed!");
return;
}
//3 context創建關聯的上下文
const EGLint ctxAttr[]={
EGL_CONTEXT_CLIENT_VERSION,2,EGL_NONE
};
//第三個參數是在多個上下文進行共享的時候用的,這裏用不到,所以就是設置為EGL_NO_CONTEXT,最後一個參數是接收一個版本信息
EGLContext context=eglCreateContext(display,config,EGL_NO_CONTEXT,ctxAttr);
if(context==EGL_NO_CONTEXT){
LOGD("eglCreateContext failed!");
}
//上下文關聯起來就可以進行數據的交換,第二和第三個函數是分別用來繪製、讀取的
if(EGL_TRUE!=eglMakeCurrent(display,winsurface,winsurface,context)){
LOGD("eglMakeCurrent failed!");
return;
}
LOGD("EGL Init Success");
//顶点和片元shader初始化
//顶点shader初始化 GL_VERTEX_SHADER表示顶点着色器
GLint vsh = InitShader(vertexShader,GL_VERTEX_SHADER);
//片元yuv420 shader初始化 GL_FRAGMENT_SHADER表示片段着色器或者片元着色器
GLint fsh = InitShader(fragYUV420P,GL_FRAGMENT_SHADER);
/////////////////////////////////////////////////////////////
//创建渲染程序
GLint program = glCreateProgram();
if(program == 0)
{
LOGD("glCreateProgram failed!");
return;
}
//渲染程序中加入着色器代码
glAttachShader(program,vsh);
glAttachShader(program,fsh);
//链接程序
glLinkProgram(program);
GLint status = 0;
glGetProgramiv(program,GL_LINK_STATUS,&status);
if(status != GL_TRUE)
{
LOGD("glLinkProgram failed!");
return;
}
//使用程序对象program作为当前渲染状态的一部分
glUseProgram(program);
LOGD("glLinkProgram success!");
/////////////////////////////////////////////////////////////
//加入三维顶点数据两个三角形组成正方形,顶点信息,参数顺序“Z”字形右下到左上
static float vers[] = {
1.0f,-1.0f,0.0f,
-1.0f,-1.0f,0.0f,
1.0f,1.0f,0.0f,
-1.0f,1.0f,0.0f,
};
//获取顶点坐标,根据可以名称,这里是aPosition,对应定义于上面的vertexShader中
GLuint apos = (GLuint)glGetAttribLocation(program,"aPosition");
//启用指定属性
glEnableVertexAttribArray(apos);
/*传递顶点
* size:一个点有多少个数据,例如一个坐标是x,y,z则size为3
* 存储格式GL_FLOAT
* 反向向量没有,则使用GL_FALSE
* stride:每个值的间隔,这里总共有3个数据,每个数据为4个字节,则总共12个字节
* */
glVertexAttribPointer(apos,3,GL_FLOAT,GL_FALSE,12,vers);
//加入材质坐标数据,同样"Z"字形,右下到左上,只是材质坐标没有z轴
static float txts[] = {
1.0f,0.0f ,
0.0f,0.0f,
1.0f,1.0f,
0.0,1.0
};
GLuint atex = (GLuint)glGetAttribLocation(program,"aTexCoord");
glEnableVertexAttribArray(atex);
glVertexAttribPointer(atex,2,GL_FLOAT,GL_FALSE,8,txts);
//yuv纹理创建及初始化
int width = 424;
int height = 240;
//材质纹理初始化
//设置纹理层,yTexture来源于上面定义的fragYUV420P
glUniform1i( glGetUniformLocation(program,"yTexture"),0); //对于纹理第1层
glUniform1i( glGetUniformLocation(program,"uTexture"),1); //对于纹理第2层
glUniform1i( glGetUniformLocation(program,"vTexture"),2); //对于纹理第3层
//创建opengl纹理
GLuint texts[3] = {0};
//创建三个纹理
glGenTextures(3,texts);
//设置纹理属性,这里先做第一层纹理
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);
//设置纹理的格式和大小
glTexImage2D(GL_TEXTURE_2D,
0, //细节级别 0默认
GL_LUMINANCE,//gpu内部格式亮度,灰度图(1个字节),如果不是灰度图,那么还有一种就是rgb,是3个字节,浪费性能
width,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,height/2, //拉升到全屏,后面这两层纹理的宽高都要除以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, //拉升到全屏
0, //边框
GL_LUMINANCE,//数据的像素格式亮度,灰度图要与上面一致
GL_UNSIGNED_BYTE, //像素的数据类型
NULL //纹理的数据
);
env->ReleaseStringUTFChars(url_,url);
}
#include <string>
#include <android/log.h>
#include <android/native_window_jni.h>
#include <EGL/egl.h>
#include <GLES2/gl2.h>
#define LOGD(...) __android_log_print(ANDROID_LOG_WARN,"testff",__VA_ARGS__)
//顶点着色器glsl ,一元运算符 # 常称为字符串化运算符,這裏用在宏定義上,則這裏的x會被展開為"x"字面量形式
#define GET_STR(x) #x
static const char *vertexShader = GET_STR(
attribute vec4 aPosition; //顶点坐标
attribute vec2 aTexCoord; //材质顶点坐标
varying vec2 vTexCoord; //输出的材质坐标
void main(){
vTexCoord = vec2(aTexCoord.x,1.0-aTexCoord.y);
gl_Position = aPosition;
}
);
//片元着色器,软解码和部分x86硬解码
static const char *fragYUV420P = GET_STR(
precision mediump float; //精度
varying vec2 vTexCoord; //顶点着色器传递的坐标
uniform sampler2D yTexture; //输入的材质(不透明灰度,单像素)
uniform sampler2D uTexture;
uniform sampler2D vTexture;
void main(){
vec3 yuv;
vec3 rgb;
yuv.r = texture2D(yTexture,vTexCoord).r;
//這裏一般減去0.5去做個四捨五入
yuv.g = texture2D(uTexture,vTexCoord).r - 0.5;
yuv.b = texture2D(vTexture,vTexCoord).r - 0.5;
//一個yuv轉rgb的公式
rgb = mat3(1.0, 1.0, 1.0,
0.0,-0.39465,2.03211,
1.13983,-0.58060,0.0)*yuv;
//输出像素颜色
gl_FragColor = vec4(rgb,1.0);
}
);
GLint InitShader(const char *code,GLint type)
{
//创建shader
GLint sh = glCreateShader(type);
if(sh == 0)
{
LOGD("glCreateShader %d failed!",type);
return 0;
}
//加载shader,最后一个参数代码长度,传0表示直接找到字符串的结尾
glShaderSource(sh,
1, //shader数量
&code, //shader代码
0); //代码长度
//编译shader
glCompileShader(sh);
//获取编译情况
GLint status;
glGetShaderiv(sh,GL_COMPILE_STATUS,&status);
if(status == 0)
{
LOGD("glCompileShader failed!");
return 0;
}
LOGD("glCompileShader success!");
return sh;
}
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_yuv_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}extern "C"
JNIEXPORT void JNICALL
Java_com_example_yuv_XPlay_Open(JNIEnv *env, jobject thiz, jstring url_, jobject surface) {
const char *url=env->GetStringUTFChars(url_,0);
LOGD("open url is %s",url);
//獲取原始窗口
ANativeWindow *nwin=ANativeWindow_fromSurface(env,surface);
//1 display創建和初始化
EGLDisplay display=eglGetDisplay(EGL_DEFAULT_DISPLAY);
if(display==EGL_NO_DISPLAY){
LOGD("eglGetDisplay failed!");
return;
}
if(EGL_TRUE!=eglInitialize(display,0,0)){
LOGD("eglInitialize failed");
return;
}
//2 surface
//2-1 surface窗口配置
//輸出配置
EGLConfig config;
EGLint configNum;
//c語言數組結束填充,這裏用EGL_NONE
EGLint configSpec[]={
EGL_RED_SIZE,8,
EGL_GREEN_SIZE,8,
EGL_BLUE_SIZE,8,
EGL_SURFACE_TYPE,EGL_WINDOW_BIT,
EGL_NONE
};
//EGL_TRUE的宏定義值為1
if(EGL_TRUE!=eglChooseConfig(display,configSpec,&config,1,&configNum)){
LOGD("eglChooseConfig failed!");
return;
}
//創建surface
EGLSurface winsurface=eglCreateWindowSurface(display,config,nwin,0);
if(winsurface==EGL_NO_SURFACE){
LOGD("eglCreateWindowSurface failed!");
return;
}
//3 context創建關聯的上下文
const EGLint ctxAttr[]={
EGL_CONTEXT_CLIENT_VERSION,2,EGL_NONE
};
//第三個參數是在多個上下文進行共享的時候用的,這裏用不到,所以就是設置為EGL_NO_CONTEXT,最後一個參數是接收一個版本信息
EGLContext context=eglCreateContext(display,config,EGL_NO_CONTEXT,ctxAttr);
if(context==EGL_NO_CONTEXT){
LOGD("eglCreateContext failed!");
}
//上下文關聯起來就可以進行數據的交換,第二和第三個函數是分別用來繪製、讀取的
if(EGL_TRUE!=eglMakeCurrent(display,winsurface,winsurface,context)){
LOGD("eglMakeCurrent failed!");
return;
}
LOGD("EGL Init Success");
//顶点和片元shader初始化
//顶点shader初始化 GL_VERTEX_SHADER表示顶点着色器
GLint vsh = InitShader(vertexShader,GL_VERTEX_SHADER);
//片元yuv420 shader初始化 GL_FRAGMENT_SHADER表示片段着色器或者片元着色器
GLint fsh = InitShader(fragYUV420P,GL_FRAGMENT_SHADER);
/////////////////////////////////////////////////////////////
//创建渲染程序
GLint program = glCreateProgram();
if(program == 0)
{
LOGD("glCreateProgram failed!");
return;
}
//渲染程序中加入着色器代码
glAttachShader(program,vsh);
glAttachShader(program,fsh);
//链接程序
glLinkProgram(program);
GLint status = 0;
glGetProgramiv(program,GL_LINK_STATUS,&status);
if(status != GL_TRUE)
{
LOGD("glLinkProgram failed!");
return;
}
//使用程序对象program作为当前渲染状态的一部分
glUseProgram(program);
LOGD("glLinkProgram success!");
/////////////////////////////////////////////////////////////
//加入三维顶点数据两个三角形组成正方形,顶点信息,参数顺序“Z”字形右下到左上
static float vers[] = {
1.0f,-1.0f,0.0f,
-1.0f,-1.0f,0.0f,
1.0f,1.0f,0.0f,
-1.0f,1.0f,0.0f,
};
//获取顶点坐标,根据可以名称,这里是aPosition,对应定义于上面的vertexShader中
GLuint apos = (GLuint)glGetAttribLocation(program,"aPosition");
//启用指定属性
glEnableVertexAttribArray(apos);
/*传递顶点
* size:一个点有多少个数据,例如一个坐标是x,y,z则size为3
* 存储格式GL_FLOAT
* 反向向量没有,则使用GL_FALSE
* stride:每个值的间隔,这里总共有3个数据,每个数据为4个字节,则总共12个字节
* */
glVertexAttribPointer(apos,3,GL_FLOAT,GL_FALSE,12,vers);
//加入材质坐标数据,同样"Z"字形,右下到左上,只是材质坐标没有z轴
static float txts[] = {
1.0f,0.0f ,
0.0f,0.0f,
1.0f,1.0f,
0.0,1.0
};
GLuint atex = (GLuint)glGetAttribLocation(program,"aTexCoord");
glEnableVertexAttribArray(atex);
glVertexAttribPointer(atex,2,GL_FLOAT,GL_FALSE,8,txts);
//yuv纹理创建及初始化
int width = 424;
int height = 240;
//材质纹理初始化
//设置纹理层,yTexture来源于上面定义的fragYUV420P
glUniform1i( glGetUniformLocation(program,"yTexture"),0); //对于纹理第1层
glUniform1i( glGetUniformLocation(program,"uTexture"),1); //对于纹理第2层
glUniform1i( glGetUniformLocation(program,"vTexture"),2); //对于纹理第3层
//创建opengl纹理
GLuint texts[3] = {0};
//创建三个纹理
glGenTextures(3,texts);
//设置纹理属性,这里先做第一层纹理
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);
//设置纹理的格式和大小
glTexImage2D(GL_TEXTURE_2D,
0, //细节级别 0默认
GL_LUMINANCE,//gpu内部格式亮度,灰度图(1个字节),如果不是灰度图,那么还有一种就是rgb,是3个字节,浪费性能
width,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,height/2, //拉升到全屏,后面这两层纹理的宽高都要除以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, //拉升到全屏
0, //边框
GL_LUMINANCE,//数据的像素格式亮度,灰度图要与上面一致
GL_UNSIGNED_BYTE, //像素的数据类型
NULL //纹理的数据
);
env->ReleaseStringUTFChars(url_,url);
}
没有报错就算是ok了
关键字词:yuv,纹理
相关文章
-
无相关信息