1. 程式人生 > >IOS opengl es2.0顯示YUV RGB

IOS opengl es2.0顯示YUV RGB

簡介

opengl es (OpenGL for Embedded Systems)是OpenGL針對嵌入式系統的圖形API. Android, IOS, 以及PC, 都支援這個規範.
opengl es 2.0 API文件
https://www.khronos.org/registry/OpenGL-Refpages/es2.0/
opengl es 2.0 規範
https://www.khronos.org/registry/OpenGL/specs/es/2.0/es_full_spec_2.0.pdf
The OpenGL ES Shading Language
https://www.khronos.org/files/opengles_shading_language.pdf


這是我寫的一個簡單的Shadinge Language教程
https://blog.csdn.net/wzj_whut/article/details/85225179

opengl es能做什麼? 使用硬體來進行3D圖形處理.
3D圖形的表現形式, 應該在一些科幻電影裡都見過, 在三個維座標系統中, 用一堆三角形, 來表達一個立體物體, 再給每個三角形貼上貼圖, 就可以表現出具有細節的事物.

在進行視訊開發時, 主要用於yuv資料的顯示, 因為H.264解碼後的資料是yuv.

#編寫shader

static const char gVertexShader[] = {
    "attribute vec4 vertexIn;    \n"
    "attribute vec2 textureIn;   \n"
    "varying vec2 textureOut;    \n"
    "void main(void)             \n"
    "{                           \n"
    "    gl_Position = vertexIn; \n"
    "    textureOut = textureIn; \n"
    "}                           \n"
};


static const char gFragmentShader[] = {
    "#ifdef GL_ES\n"
    "precision mediump int;\n"
    "precision mediump float;\n"
    "#endif\n"
    "varying vec2 textureOut;\n"
    "uniform sampler2D tex_y;\n"
    "uniform sampler2D tex_u;\n"
    "uniform sampler2D tex_v;\n"
    "void main(void) {\n"
    "    vec3 yuv;\n"
    "    vec3 rgb;\n"
    "    yuv.x = texture2D(tex_y, textureOut).r;\n"
    "    yuv.y = texture2D(tex_u, textureOut).r - 0.5;\n"
    "    yuv.z = texture2D(tex_v, textureOut).r - 0.5;\n"
    "    rgb = mat3( 1,       1,         1,\n"
    "                0,       -0.39465,  2.03211,\n"
    "                1.13983, -0.58060,  0) * yuv;\n"
    "    		gl_FragColor = vec4(rgb, 1.0);\n"
    "}\n"
};

上面這個yuv轉rgb的演算法, 我也不知道當初從哪來拷過來的, 看起來很詭異, 但是能正常工作, 也沒有出現偏色, 我估摸著應該是求的近似解. 正常的寫法應該是這樣的

static const char gFragmentShader[] = {
    "#ifdef GL_ES\n"
    "precision mediump int;\n"
    "precision mediump float;\n"
    "#endif\n"
    "varying vec2 textureOut;\n"
    "uniform sampler2D tex_y;\n"
    "uniform sampler2D tex_u;\n"
    "uniform sampler2D tex_v;\n"
    "void main(void) {\n"
    "    float y,u,v,r,g,b;\n"
    "    y = texture2D(tex_y, textureOut).r;\n"
    "    u = texture2D(tex_u, textureOut).r - 0.5;\n"
    "    v = texture2D(tex_v, textureOut).r - 0.5;\n"
    "    y=1.1643*(y-0.0625);\n"
    "    r=y+1.5958*v;\n"
    "    g=y-0.39173*u-0.81290*v;\n"
    "    b=y+2.017*u;\n"
    "  gl_FragColor=vec4(r,g,b,1.0);\n"
"}\n"
};

遵循的公式為

Y  =      (0.257 * R) + (0.504 * G) + (0.098 * B) + 16
Cb = U = -(0.148 * R) - (0.291 * G) + (0.439 * B) + 128
Cr = V =  (0.439 * R) - (0.368 * G) - (0.071 * B) + 128

R = 1.164*(Y - 16) + 1.596*(V - 128)
B = 1.164*(Y - 16)  + 2.018*(U - 128)
G = 1.164*(Y - 16) - 0.813*(V - 128) - 0.391*(U - 128)

在這裡插入圖片描述

完整示例
https://github.com/wzjwhut/ios-opengles