*
Shader

           

生成测试yuv数据和pcm数据命令:
ffmpeg -i test.mp4 -f si6le test.pcm ffmpeg -i 720.mp4 -pix_fmt yuv20p -s
424x240 out.yuv
具体显示yuv数据 --- 着色器语言 GLSL (运行在显卡上,不消耗cpu)

-GLSL的基本语法与C语言基本相同

-它完美支持向量和矩阵操作

-GLSL提供了大量的内置函数来提供丰富的扩展功能

-它是通过限定符操作来管理输入输出类型的

①顶点着色器:
顶点着色器被使用在传统的基于顶点的操作,例如位移矩阵、计算光照方程、产生贴图坐标。顶点着色器被应用指定,应用于客户的顶点转化是针对每个顶点执行一次,用于确定顶点位置

作用:顶点坐标输出成材质坐标

                              

②片元着色器:在片元着色器阶段只有唯一的varying 输出变量-即内建变量:gl_FragColo

是针对每个片元(可以理解为每个像素)执行一次,用于确定每个片元(像素)的颜色

作用:输出像素格式

 

                                                   

* 顶点信息 float *vertexData = new float[12]{ 1.0f, -1.0f, 0.0f, -1.0f, -1.0f,
0.0f, 1.0f, 1.0f, 0.0f, -1.0f, 1.0f, 0.0f};
 

              
// 顶点着色器 glsl代码 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; } );
* 材质坐标 float *textureVertexData = new float[8]{ 1.0f, 0.0f,//右下 0.0f,
0.0f,//左下 1.0f, 1.0f,//右上 0.0f, 1.0f//左上 };
               
//yuv420p 片元着色器,软解码和部分x86硬解码 static const char *fragYUV_420P= 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; yuv.g = texture2D(uTexture, vTexCoord).r -
0.5; yuv.b = texture2D(vTexture, vTexCoord).r - 0.5; 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); } ); //NV12 片元着色器 glsl代码 static const char *fragNV12 = GET_STR(
precision mediump float; //精度 varying vec2 vTexCoord; //顶点着色器传递的坐标 uniform
sampler2D yTexture; //输入的材质(不透明灰度,单像素) uniform sampler2D uvTexture; void main()
{ vec3 yuv; vec3 rgb; yuv.r = texture2D(yTexture, vTexCoord).r; yuv.g =
texture2D(uvTexture, vTexCoord).r - 0.5; yuv.b = texture2D(uvTexture,
vTexCoord).a - 0.5; 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); } );
* yuv转rgb // 方法一:使用转换公式 R = Y + 1.402 (Cr-128) G = Y - 0.34414 (Cb-128) -
0.71414 (Cr-128) B = Y + 1.772 (Cb-128) // 方法二: 使用转换矩阵 (1.0, 1.0, 1.0, 0.0,
-0.39465, 2.03211, 1.13983, -0.58060, 0.0)
* shader初始化代码演示 bool XShader::Init(XShaderType type) { XLOGE("Enter
XShader::Init()!"); Close(); //shader 初始化 //顶点坐标初始化 vsh =
InitShader(vertexShader, GL_VERTEX_SHADER); if (vsh == 0) { mux.unlock();
XLOGE("InitShader GL_VERTEX_SHADER failed!"); return false; }
XLOGE("@@@@@@@@@@@@@@@@ type: %d", type); //片元初始化 switch (type) { case
XSHADER_yuv420P: //片元yuv420 shader初始化 fsh = InitShader(fragYUV_420P,
GL_FRAGMENT_SHADER); break; case XSHADER_NV12: // NV12 fsh =
InitShader(fragNV12, GL_FRAGMENT_SHADER); break; case XSHADER_NV21: fsh =
InitShader(fragNV21, GL_FRAGMENT_SHADER); break; default: mux.unlock();
XLOGE("XShaderType format is error!"); break; } if (fsh == 0) { mux.unlock();
XLOGE("InitShader GL_FRAGMENT_SHADER failed!"); return false; } //创建渲染程序
program = glCreateProgram(); if (program == 0) { mux.unlock();
XLOGE("===========>>glCreateProgram failed! "); return false; } //渲染程序中加入着色器代码
glAttachShader(program, vsh); glAttachShader(program, fsh); //连接程序
glLinkProgram(program); GLint status; glGetProgramiv(program, GL_LINK_STATUS,
&status); if (status != GL_TRUE) { mux.unlock(); XLOGE("=========>>
glLinkProgram failed!"); return false; } //激活渲染程序 glUseProgram(program);
///////////////////////////////////////////////////// //加入三维顶点数据 两个三角形组成正方形
static float ver[] = { 1.0f, -1.f, 0.0f, -1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f }; GLuint apos = glGetAttribLocation(program, "aPosition");
glEnableVertexAttribArray(apos); //传递值 glVertexAttribPointer(apos, 3, GL_FLOAT,
GL_FALSE, 12, ver); //加入材质坐标 static float txts[] = { 1.0f, 0.0f, 0.0f, 0.0f,
1.0f, 1.0f, 0.0f, 1.0f }; GLuint atex = glGetAttribLocation(program,
"aTexCoord"); glEnableVertexAttribArray(atex); glVertexAttribPointer(atex, 2,
GL_FLOAT, GL_FALSE, 8, txts); //材质纹理初始化 //设置纹理层
glUniform1i(glGetUniformLocation(program, "yTexture"), 0); //纹理层第一层 switch
(type) { case XSHADER_yuv420P: glUniform1i(glGetUniformLocation(program,
"uTexture"), 1); //纹理层第二层 glUniform1i(glGetUniformLocation(program,
"vTexture"), 2); //纹理层第三层 break; case XSHADER_NV12: case XSHADER_NV21:
glUniform1i(glGetUniformLocation(program, "uvTexture"), 1); //纹理层第二层 break; }
mux.unlock(); XLOGE("InitShader success!"); return true; }
 
//shader 初始化 static GLuint InitShader(const char *code, GLint type) { GLuint
sh = glCreateShader(type); if (sh == 0) { XLOGE("====>> InitShader failed! %d",
type); return 0; } //加载shader glShaderSource(sh, 1, //shader 数量
&code,//shader代码 //代码长度 0); //编译shader glCompileShader(sh); //获取编译情况 GLint
status; glGetShaderiv(sh, GL_COMPILE_STATUS, &status); if (status == 0) {
XLOGE("glGetShaderiv failed!"); return 0; } XLOGE("glGetShaderiv succee!");
return sh; }
* 开始绘制 代码演示 virtual void Draw(unsigned char *data[], int width, int height)
{ // XLOGE("XTexture Draw!"); // XLOGE("width %d height %d", width, height);
mux.lock(); shader.GetTexture(0, width, height, data[0]); //y if
(XSHADER_yuv420P == textureType) { shader.GetTexture(1, width / 2, height / 2,
data[1]); //u shader.GetTexture(2, width / 2, height / 2, data[2]); //v } else
{ shader.GetTexture(1, width / 2, height / 2, data[1], true); //uv }
shader.Draw(); if (xegl) { xegl->Draw(); } mux.unlock(); }
 
void XShader::GetTexture(unsigned int index, int width, int height, unsigned
char *buf, bool isa) { // XLOGE("XShader width %d height %d", width, height);
//默认灰度图GL_LUMINANCE,透明通道GL_LUMINANCE_ALPHA unsigned int format = isa ?
GL_LUMINANCE_ALPHA : GL_LUMINANCE; mux.lock(); if (texts[index] == 0) {
glGenTextures(1, &texts[index]);//创建纹理 //设置纹理属性 glBindTexture(GL_TEXTURE_2D,
texts[index]); //缩小过滤器 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默认
format,//gpu内部格式,灰度图 width, height,//尺寸是2的次方 0,//边框
format,//数据的像素格式 亮度,灰度图 要与上面一致 GL_UNSIGNED_BYTE,//像素的数据类型 NULL//纹理的数据 ); }
glActiveTexture(GL_TEXTURE0 + index);//激活第index层纹理 glBindTexture(GL_TEXTURE_2D,
texts[index]);//绑定到创建的opengl纹理 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width,
height, format, GL_UNSIGNED_BYTE, buf);//替换纹理内容 mux.unlock(); } void
XShader::Draw() { // XLOGE("XShader Draw!");dra mux.lock(); if (program == 0) {
mux.unlock(); XLOGE("Program is NUll when call Draw of Xshader!"); return; }
//三维绘制 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); mux.unlock(); }
 

 

 

 

 

 

友情链接
ioDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:ixiaoyang8@qq.com
QQ群:637538335
关注微信