当前位置:   article > 正文

OpenGL/OpenGL ES入门:渲染YUV数据实践_opengl es 渲染yuv数据

opengl es 渲染yuv数据

纹理:GPU中的一块数据结构,YUV数据先经过采样,转成rgb显示。

着色器代码,先通过compile编译成GPU能识别的机器语言,再交由GPU进行显示。

shader着色器,texture纹理,Utility通用工具,context,surface,

vertex shader顶点着色器,fragment shader片元着色器,

实践

1.yuv的字节数

现有宽为w高为h的一个视频,现在定义了一个data[] bytes变量并存储了这个视频的一帧数据。

  • bytes数组中,先连续存储每个像素的灰度信息,y通道占w*h个字节;
  • 然后顺序存储颜色数据,u和v分别占一个字节,每个颜色数据共占2个字节,所以uv通道占(w/2)(h/2)2=w*h/2个字。

2.纹理

2.1 纹理的组成

  • y通道的数据生成一个opengl纹理;
  • uv通道的数据生成一个opengl纹理;
  • 两个纹理作为渲染时的输入,在渲染过程中由GPU组装还原出来视频画面

yv12是三个纹理是y一个,u一个,v一个;nv12是y一个,uv一个。

2.2 纹理格式

 GL_LUMINANCE 和 GL_LUMINANCE_ALPHA 格式的纹理。

  • GL_LUMINANCE 纹理用来加载 NV21 Y Plane 的数据;
  • GL_LUMINANCE_ALPHA 纹理用来加载 UV Plane 的数据。
基本内部格式所提取的颜色
GL_ALPHA(0,0,0,A)
GL_LUMINANCE(L,L,L,1)--->亮度
GL_LUMINANCE_ALPHA(L,L,L,A)--->透明度
GL_INTENSITY(I,I,I,I)
GL_RGB(R,G,B,1)
GL_RGBA(R,G,B,A)

3. YUV渲染步骤

  • 第一步:初始化上下文
  • 第二步:初始化着色器程序(编译链接着色器程序,生成2个纹理-->确定纹理坐标及对应的顶点坐标-->加载纹理坐标和顶点坐标数据到着色器程序);
  • 第三步:初始化buffer;
  • 第四步:初始化纹理(分别加载NV21的两个Plane数据到2个纹理);
  • 第五步:绘制。

4.代码案例

在OpenGL中,片元着色器最后输出的都是rgba的数据,所以使用OpenGL来渲染YUV数据的关键还是将YUV数据传递给着色器,并在着色器中将YUV转化为RGB。

OpenGL ES 系列教程_hongge372的博客-CSDN博客_opengles教程

第一步:初始化上下文

  1. void initContextGL(const char* hWindow)
  2. {
  3. // double dpr = emscripten_get_device_pixel_ratio();
  4. // emscripten_set_element_css_size(hWindow, nWmdWidth / dpr, nWndHeight / dpr);
  5. // emscripten_set_canvas_element_size(hWindow, nWmdWidth, nWndHeight);
  6. // printf("create size success\n");
  7. EmscriptenWebGLContextAttributes attrs;
  8. emscripten_webgl_init_context_attributes(&attrs);
  9. attrs.alpha = 0;
  10. #if MAX_WEBGL_VERSION >= 2
  11. attrs.majorVersion = 2;
  12. #endif
  13. EMSCRIPTEN_WEBGL_CONTEXT_HANDLE glContext = emscripten_webgl_create_context(hWindow, &attrs);
  14. assert(glContext);
  15. EMSCRIPTEN_RESULT res=emscripten_webgl_make_context_current(glContext);
  16. assert(res == EMSCRIPTEN_RESULT_SUCCESS);
  17. assert(emscripten_webgl_get_current_context() == glContext);
  18. printf("create context success 1730\n");
  19. }

第二步:初始化着色器程序

  1. /*顶点着色器代码*/
  2. static const char g_pGLVS[] = ///<普通纹理渲染顶点着色器
  3. {
  4. "precision mediump float;"
  5. "attribute vec4 position; "
  6. "attribute vec4 texCoord; "
  7. "varying vec4 pp; "
  8. "void main() "
  9. "{ "
  10. " gl_Position = position; "
  11. " pp = texCoord; "
  12. "} "
  13. };
  14. /*像素着色器代码*/
  15. const char* g_pGLFS = ///<YV12片段着色器
  16. {
  17. "precision mediump float;"
  18. "varying vec4 pp; "
  19. "uniform sampler2D Ytexture; "
  20. "uniform sampler2D Utexture; "
  21. "uniform sampler2D Vtexture; "
  22. "void main() "
  23. "{ "
  24. " float r,g,b,y,u,v; "
  25. " y=texture2D(Ytexture, pp.st).r; "
  26. " u=texture2D(Utexture, pp.st).r; "
  27. " v=texture2D(Vtexture, pp.st).r; "
  28. " y=1.1643*(y-0.0625); "
  29. " u=u-0.5; "
  30. " v=v-0.5; "
  31. " r=y+1.5958*v; "
  32. " g=y-0.39173*u-0.81290*v; "
  33. " b=y+2.017*u; "
  34. " gl_FragColor=vec4(r,g,b,1.0); "
  35. "} "
  36. };
  37. GLuint initShaderProgram()
  38. {
  39. ///< 顶点着色器相关操作
  40. GLuint nVertexShader = glCreateShader(GL_VERTEX_SHADER);
  41. const GLchar* pVS = g_pGLVS;
  42. GLint nVSLen = static_cast<GLint>(strlen(g_pGLVS));
  43. glShaderSource(nVertexShader, 1, (const GLchar**)&pVS, &nVSLen);
  44. GLint nCompileRet;
  45. glCompileShader(nVertexShader);
  46. glGetShaderiv(nVertexShader, GL_COMPILE_STATUS, &nCompileRet);
  47. if(0 == nCompileRet)
  48. {
  49. return SR_FAIL;
  50. }
  51. ///< 片段着色器相关操作
  52. GLuint nFragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
  53. const GLchar* pFS = g_pGLFS;
  54. GLint nFSLen = static_cast<GLint>(strlen(g_pGLFS));
  55. glShaderSource(nFragmentShader, 1, (const GLchar**)&pFS, &nFSLen);
  56. glCompileShader(nFragmentShader);
  57. glGetShaderiv(nFragmentShader, GL_COMPILE_STATUS, &nCompileRet);
  58. if(0 == nCompileRet)
  59. {
  60. return SR_FAIL;
  61. }
  62. ///<program相关
  63. GLuint nShaderProgram = glCreateProgram();
  64. glAttachShader(nShaderProgram, nVertexShader);
  65. glAttachShader(nShaderProgram, nFragmentShader);
  66. glLinkProgram(nShaderProgram);
  67. GLint nLinkRet;
  68. glGetProgramiv(nShaderProgram, GL_LINK_STATUS, &nLinkRet);
  69. if(0 == nLinkRet)
  70. {
  71. return SR_FAIL;
  72. }
  73. glDeleteShader(nVertexShader);
  74. glDeleteShader(nFragmentShader);
  75. return nShaderProgram;
  76. }

功能描述:loadShader 方法通过 glCreateShader 方法创建了一个着色器;如果着色器创建成功则加载着色器源代码,并编译着色器。编译完成后检查编译情况。若编译成功则返回着色器的 ID,反之删除着色器并且打印错误信息。

GLenum type为着色器的类型,分为:GL_VERTEX_SHADER顶点着色器,GL_FRAGMENT_SHADER片段着色器。

功能描述:createProgram 方法通过调用 loadShader 方法分别加载顶点着色器与片元着色器的源代码进 GPU,并分别进行编译。

第三步:初始化buffer

  1. GLuint g_vertexPosBuffer;
  2. GLuint g_vertexPosBuffer;
  3. GLuint g_texturePosBuffer;
  4. const GLfloat g_Vertices[] = {
  5. -1.0f, 1.0f,
  6. -1.0f, -1.0f,
  7. 1.0f, 1.0f,
  8. 1.0f, 1.0f,
  9. -1.0f, -1.0f,
  10. 1.0f, -1.0f,
  11. };
  12. const GLfloat g_TexCoord[] = {
  13. 0.0f, 0.0f,
  14. 0.0f, 1.0f,
  15. 1.0f, 0.0f,
  16. 1.0f, 0.0f,
  17. 0.0f, 1.0f,
  18. 1.0f, 1.0f,
  19. };
  20. void initBuffers()
  21. {
  22. GLuint vertexPosBuffer;
  23. glGenBuffers(1, &vertexPosBuffer);//创建缓冲区对象
  24. glBindBuffer(GL_ARRAY_BUFFER, vertexPosBuffer);//将该缓冲区对象绑定到管线上
  25. glBufferData(GL_ARRAY_BUFFER, sizeof(g_Vertices), g_Vertices, GL_STATIC_DRAW);
  26. glBindBuffer(GL_ARRAY_BUFFER, NULL);
  27. g_vertexPosBuffer=vertexPosBuffer;
  28. GLuint texturePosBuffer;
  29. glGenBuffers(1, &texturePosBuffer);
  30. glBindBuffer(GL_ARRAY_BUFFER, texturePosBuffer);
  31. glBufferData(GL_ARRAY_BUFFER, sizeof(g_TexCoord), g_TexCoord, GL_STATIC_DRAW);
  32. glBindBuffer(GL_ARRAY_BUFFER, NULL);
  33. g_texturePosBuffer=texturePosBuffer;
  34. }

第四步:初始化纹理

  1. GLuint g_ShaderProgram;
  2. GLuint g_Texture2D[3];
  3. #define Y 0
  4. #define U 1
  5. #define V 2
  6. void initTexture()
  7. {
  8. glUseProgram(g_ShaderProgram);
  9. GLuint nTexture2D[3]; ///<< YUV三层纹理数组
  10. glGenTextures(3, nTexture2D);
  11. for(int i = 0; i < 3; ++i)
  12. {
  13. glBindTexture(GL_TEXTURE_2D, nTexture2D[i]);
  14. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  15. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  16. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  17. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  18. glBindTexture(GL_TEXTURE_2D, NULL);
  19. }
  20. GLuint nTextureUniform[3];
  21. nTextureUniform[Y] = glGetUniformLocation(g_ShaderProgram, "Ytexture");
  22. nTextureUniform[U] = glGetUniformLocation(g_ShaderProgram, "Utexture");
  23. nTextureUniform[V] = glGetUniformLocation(g_ShaderProgram, "Vtexture");
  24. glUniform1i(nTextureUniform[Y], 0);
  25. glUniform1i(nTextureUniform[U], 1);
  26. glUniform1i(nTextureUniform[V], 2);
  27. g_Texture2D[0]=nTexture2D[0];
  28. g_Texture2D[1]=nTexture2D[1];
  29. g_Texture2D[2]=nTexture2D[2];
  30. glUseProgram(NULL);
  31. }

功能描述:将纹理图象空间映射到帧缓冲图象空间(把纹理像素映射成像素)

  1. //纹理过滤函数glTexParameteri()
  2. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  3. param1: GL_TEXTURE_2D: 操作2D纹理.
  4. param2: GL_TEXTURE_WRAP_S: S方向上的贴图模式.
  5. param3: GL_CLAMP: 将纹理坐标限制在0.0,1.0的范围之内.如果超出了会如何呢.不会错误,只是会边缘拉伸填充.
  6. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  7. param2:这里同上,只是它是T方向
  8. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  9. param2:GL_TEXTURE_MAG_FILTER: 放大过滤
  10. param3:GL_LINEAR: 线性过滤, 使用距离当前渲染像素中心最近的4个纹素加权平均值.
  11. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
  12. param2:GL_TEXTURE_MIN_FILTER: 缩小过滤
  13. param2:GL_LINEAR_MIPMAP_NEAREST: 使用GL_NEAREST对最接近当前多边形的解析度的两个层级贴图进行采样,然后用这两个值进行线性插值.

第四步 渲染YUV到纹理

  1. int RenderFrame( unsigned char* pFrameData, int nFrameWidth, int nFrameHeight)
  2. {
  3. if(pFrameData==NULL||nFrameWidth<=0||nFrameHeight<=0)
  4. {
  5. return -1;
  6. }
  7. glClearColor(0.8f,0.8f,1.0f,1.0);
  8. glClear(GL_COLOR_BUFFER_BIT);
  9. glActiveTexture(GL_TEXTURE0);
  10. glBindTexture(GL_TEXTURE_2D, g_Texture2D[Y]);
  11. glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, nFrameWidth, nFrameHeight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, pFrameData);
  12. glActiveTexture(GL_TEXTURE1);
  13. glBindTexture(GL_TEXTURE_2D,g_Texture2D[U] );
  14. glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, nFrameWidth / 2, nFrameHeight / 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, pFrameData + nFrameWidth * nFrameHeight * 5 / 4);
  15. glActiveTexture(GL_TEXTURE2);
  16. glBindTexture(GL_TEXTURE_2D, g_Texture2D[V]);
  17. glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, nFrameWidth / 2, nFrameHeight / 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, pFrameData + nFrameWidth * nFrameHeight);
  18. glUseProgram(g_ShaderProgram);
  19. //将所有顶点数据上传至顶点着色器的顶点缓存
  20. #ifdef DRAW_FROM_CLIENT_MEMORY
  21. glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 20, pos_and_color);
  22. glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 20, (void*)(pos_and_color+2));
  23. GLint nPosLoc = glGetAttribLocation(g_ShaderProgram, "position");
  24. glVertexAttribPointer(nPosLoc, 2, GL_FLOAT, GL_FALSE, 0, g_Vertices);
  25. GLint nTexcoordLoc = glGetAttribLocation(g_ShaderProgram, "texCoord");
  26. glVertexAttribPointer(nTexcoordLoc, 2, GL_FLOAT, GL_FALSE, 0, g_TexCoord);
  27. #else
  28. glBindBuffer(GL_ARRAY_BUFFER, g_vertexPosBuffer);
  29. GLint nPosLoc = glGetAttribLocation(g_ShaderProgram, "position");
  30. glEnableVertexAttribArray(nPosLoc);
  31. glVertexAttribPointer(nPosLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
  32. glBindBuffer(GL_ARRAY_BUFFER, NULL);
  33. glBindBuffer(GL_ARRAY_BUFFER, g_texturePosBuffer);
  34. GLint nTexcoordLoc = glGetAttribLocation(g_ShaderProgram, "texCoord");
  35. glEnableVertexAttribArray(nTexcoordLoc);
  36. glVertexAttribPointer(nTexcoordLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
  37. glBindBuffer(GL_ARRAY_BUFFER, NULL);
  38. #endif
  39. glDrawArrays(GL_TRIANGLES, 0, 6);
  40. glDisableVertexAttribArray(nPosLoc);
  41. glDisableVertexAttribArray(nTexcoordLoc);
  42. #ifdef EXPLICIT_SWAP
  43. emscripten_webgl_commit_frame();
  44. #endif
  45. #ifdef REPORT_RESULT
  46. REPORT_RESULT(0);
  47. #endif
  48. glUseProgram(NULL);
  49. return SR_OK;
  50. }
  1. void glTexImage2D(
  2. int target, // 目标纹理,此处必须为GL_TEXTURE_2D
  3. int level, // 执行细节级别,0是最基本的图像级别,n表示第N级贴图细化级别
  4. int internalformat, // 指定纹理中的颜色组件
  5. int width, // 指定纹理图像的宽度,
  6. int height, // 指定纹理图像的高度,
  7. int border, // 指定边框的宽度。必须为0
  8. int format, // 像素数据的颜色格式
  9. int type, // 指定像素数据的数据类型
  10. java.nio.Buffer pixels // 指定内存中指向图像数据的指针
  11. );

internalformat这个参数指定纹理中的颜色组件,可选的值如下:

  • 通常使用GL_RGBA这种颜色组件,它会单独保存R,G,B,A四个数据;
  • 在渲染YUV数据的时候,使用GL_LUMINANCE和GL_LUMINANCE_ALPHA。使用GL_LUMINANCE时,可以将Y分量存储到像素的各个通道内,这样在着色器中,我们可以通过R,G,B任意一个分量来获取到Y值。U,V分量同理
  • 使用GL_LUMINANCE_ALPHA的时候,首先存储亮度,然后是alpha值,利用这一点可以将U值存储到像素的A通道,V值存储到R,G,B通道

完整代码:

  1. #include <GLES2/gl2.h>
  2. // #include <EGL/egl.h>
  3. // #include <EGL/eglext.h>
  4. #include <emscripten.h>
  5. // #include <emscripten/bind.h>
  6. // #include <emscripten/val.h>
  7. #include <emscripten/html5.h>
  8. // #include <X11/Xlib.h>
  9. // #include <X11/Xatom.h>
  10. // #include <X11/Xutil.h>
  11. #include <string.h>
  12. #include <stdio.h>
  13. #include <iostream>
  14. #include <assert.h>
  15. #define SR_OK 0;
  16. #define SR_FAIL 1;
  17. #define Y 0
  18. #define U 1
  19. #define V 2
  20. /// esCreateWindow flag - RGB color buffer
  21. #define ES_WINDOW_RGB 0
  22. /// esCreateWindow flag - ALPHA color buffer
  23. #define ES_WINDOW_ALPHA 1
  24. /// esCreateWindow flag - depth buffer
  25. #define ES_WINDOW_DEPTH 2
  26. /// esCreateWindow flag - stencil buffer
  27. #define ES_WINDOW_STENCIL 4
  28. /// esCreateWindow flat - multi-sample buffer
  29. #define ES_WINDOW_MULTISAMPLE 8
  30. GLuint flags=ES_WINDOW_RGB;
  31. GLuint g_ShaderProgram;
  32. GLuint g_Texture2D[3];
  33. GLuint g_vertexPosBuffer;
  34. GLuint g_texturePosBuffer;
  35. /*顶点着色器代码*/
  36. static const char g_pGLVS[] = ///<普通纹理渲染顶点着色器
  37. {
  38. "precision mediump float;"
  39. "attribute vec4 position; "
  40. "attribute vec4 texCoord; "
  41. "varying vec4 pp; "
  42. "void main() "
  43. "{ "
  44. " gl_Position = position; "
  45. " pp = texCoord; "
  46. "} "
  47. };
  48. /*像素着色器代码*/
  49. const char* g_pGLFS = ///<YV12片段着色器
  50. {
  51. "precision mediump float;"
  52. "varying vec4 pp; "
  53. "uniform sampler2D Ytexture; "
  54. "uniform sampler2D Utexture; "
  55. "uniform sampler2D Vtexture; "
  56. "void main() "
  57. "{ "
  58. " float r,g,b,y,u,v; "
  59. " y=texture2D(Ytexture, pp.st).r; "
  60. " u=texture2D(Utexture, pp.st).r; "
  61. " v=texture2D(Vtexture, pp.st).r; "
  62. " y=1.1643*(y-0.0625); "
  63. " u=u-0.5; "
  64. " v=v-0.5; "
  65. " r=y+1.5958*v; "
  66. " g=y-0.39173*u-0.81290*v; "
  67. " b=y+2.017*u; "
  68. " gl_FragColor=vec4(r,g,b,1.0); "
  69. "} "
  70. };
  71. const GLfloat g_Vertices[] = {
  72. -1.0f, 1.0f,
  73. -1.0f, -1.0f,
  74. 1.0f, 1.0f,
  75. 1.0f, 1.0f,
  76. -1.0f, -1.0f,
  77. 1.0f, -1.0f,
  78. };
  79. const GLfloat g_TexCoord[] = {
  80. 0.0f, 0.0f,
  81. 0.0f, 1.0f,
  82. 1.0f, 0.0f,
  83. 1.0f, 0.0f,
  84. 0.0f, 1.0f,
  85. 1.0f, 1.0f,
  86. };
  87. #ifdef __cplusplus
  88. extern "C" {
  89. #endif
  90. EMSCRIPTEN_KEEPALIVE
  91. void initBuffers()
  92. {
  93. GLuint vertexPosBuffer;
  94. glGenBuffers(1, &vertexPosBuffer);//创建缓冲区对象
  95. glBindBuffer(GL_ARRAY_BUFFER, vertexPosBuffer);//将该缓冲区对象绑定到管线上
  96. glBufferData(GL_ARRAY_BUFFER, sizeof(g_Vertices), g_Vertices, GL_STATIC_DRAW);
  97. glBindBuffer(GL_ARRAY_BUFFER, NULL);
  98. g_vertexPosBuffer=vertexPosBuffer;
  99. GLuint texturePosBuffer;
  100. glGenBuffers(1, &texturePosBuffer);
  101. glBindBuffer(GL_ARRAY_BUFFER, texturePosBuffer);
  102. glBufferData(GL_ARRAY_BUFFER, sizeof(g_TexCoord), g_TexCoord, GL_STATIC_DRAW);
  103. glBindBuffer(GL_ARRAY_BUFFER, NULL);
  104. g_texturePosBuffer=texturePosBuffer;
  105. }
  106. EMSCRIPTEN_KEEPALIVE
  107. void initTexture()
  108. {
  109. glUseProgram(g_ShaderProgram);
  110. GLuint nTexture2D[3]; ///<< YUV三层纹理数组
  111. glGenTextures(3, nTexture2D);
  112. for(int i = 0; i < 3; ++i)
  113. {
  114. glBindTexture(GL_TEXTURE_2D, nTexture2D[i]);
  115. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  116. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  117. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  118. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  119. glBindTexture(GL_TEXTURE_2D, NULL);
  120. }
  121. GLuint nTextureUniform[3];
  122. nTextureUniform[Y] = glGetUniformLocation(g_ShaderProgram, "Ytexture");
  123. nTextureUniform[U] = glGetUniformLocation(g_ShaderProgram, "Utexture");
  124. nTextureUniform[V] = glGetUniformLocation(g_ShaderProgram, "Vtexture");
  125. glUniform1i(nTextureUniform[Y], 0);
  126. glUniform1i(nTextureUniform[U], 1);
  127. glUniform1i(nTextureUniform[V], 2);
  128. g_Texture2D[0]=nTexture2D[0];
  129. g_Texture2D[1]=nTexture2D[1];
  130. g_Texture2D[2]=nTexture2D[2];
  131. glUseProgram(NULL);
  132. }
  133. EMSCRIPTEN_KEEPALIVE
  134. GLuint initShaderProgram()
  135. {
  136. ///< 顶点着色器相关操作
  137. GLuint nVertexShader = glCreateShader(GL_VERTEX_SHADER);
  138. const GLchar* pVS = g_pGLVS;
  139. GLint nVSLen = static_cast<GLint>(strlen(g_pGLVS));
  140. glShaderSource(nVertexShader, 1, (const GLchar**)&pVS, &nVSLen);
  141. GLint nCompileRet;
  142. glCompileShader(nVertexShader);
  143. glGetShaderiv(nVertexShader, GL_COMPILE_STATUS, &nCompileRet);
  144. if(0 == nCompileRet)
  145. {
  146. return SR_FAIL;
  147. }
  148. ///< 片段着色器相关操作
  149. GLuint nFragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
  150. const GLchar* pFS = g_pGLFS;
  151. GLint nFSLen = static_cast<GLint>(strlen(g_pGLFS));
  152. glShaderSource(nFragmentShader, 1, (const GLchar**)&pFS, &nFSLen);
  153. glCompileShader(nFragmentShader);
  154. glGetShaderiv(nFragmentShader, GL_COMPILE_STATUS, &nCompileRet);
  155. if(0 == nCompileRet)
  156. {
  157. return SR_FAIL;
  158. }
  159. ///<program相关
  160. GLuint nShaderProgram = glCreateProgram();
  161. glAttachShader(nShaderProgram, nVertexShader);
  162. glAttachShader(nShaderProgram, nFragmentShader);
  163. glLinkProgram(nShaderProgram);
  164. GLint nLinkRet;
  165. glGetProgramiv(nShaderProgram, GL_LINK_STATUS, &nLinkRet);
  166. if(0 == nLinkRet)
  167. {
  168. return SR_FAIL;
  169. }
  170. glDeleteShader(nVertexShader);
  171. glDeleteShader(nFragmentShader);
  172. return nShaderProgram;
  173. }
  174. EMSCRIPTEN_KEEPALIVE
  175. void initContextGL(const char* hWindow)
  176. {
  177. // double dpr = emscripten_get_device_pixel_ratio();
  178. // emscripten_set_element_css_size(hWindow, nWmdWidth / dpr, nWndHeight / dpr);
  179. // emscripten_set_canvas_element_size(hWindow, nWmdWidth, nWndHeight);
  180. // printf("create size success\n");
  181. EmscriptenWebGLContextAttributes attrs;
  182. emscripten_webgl_init_context_attributes(&attrs);
  183. attrs.alpha = 0;
  184. #if MAX_WEBGL_VERSION >= 2
  185. attrs.majorVersion = 2;
  186. #endif
  187. EMSCRIPTEN_WEBGL_CONTEXT_HANDLE glContext = emscripten_webgl_create_context(hWindow, &attrs);
  188. assert(glContext);
  189. EMSCRIPTEN_RESULT res=emscripten_webgl_make_context_current(glContext);
  190. assert(res == EMSCRIPTEN_RESULT_SUCCESS);
  191. assert(emscripten_webgl_get_current_context() == glContext);
  192. printf("create context success 1730\n");
  193. }
  194. EMSCRIPTEN_KEEPALIVE
  195. int init(const char* hWindow)
  196. {
  197. //初始化Context
  198. initContextGL(hWindow);
  199. //初始化着色器程序
  200. g_ShaderProgram=initShaderProgram();
  201. //初始化buffer
  202. initBuffers();
  203. //初始化纹理
  204. initTexture();
  205. return 1;
  206. }
  207. EMSCRIPTEN_KEEPALIVE
  208. int RenderFrame( unsigned char* pFrameData, int nFrameWidth, int nFrameHeight)
  209. {
  210. if(pFrameData==NULL||nFrameWidth<=0||nFrameHeight<=0)
  211. {
  212. return -1;
  213. }
  214. glClearColor(0.8f,0.8f,1.0f,1.0);
  215. glClear(GL_COLOR_BUFFER_BIT);
  216. glActiveTexture(GL_TEXTURE0);
  217. glBindTexture(GL_TEXTURE_2D, g_Texture2D[Y]);
  218. glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, nFrameWidth, nFrameHeight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, pFrameData);
  219. glActiveTexture(GL_TEXTURE1);
  220. glBindTexture(GL_TEXTURE_2D,g_Texture2D[U] );
  221. glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, nFrameWidth / 2, nFrameHeight / 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, pFrameData + nFrameWidth * nFrameHeight * 5 / 4);
  222. glActiveTexture(GL_TEXTURE2);
  223. glBindTexture(GL_TEXTURE_2D, g_Texture2D[V]);
  224. glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, nFrameWidth / 2, nFrameHeight / 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, pFrameData + nFrameWidth * nFrameHeight);
  225. glUseProgram(g_ShaderProgram);
  226. //将所有顶点数据上传至顶点着色器的顶点缓存
  227. #ifdef DRAW_FROM_CLIENT_MEMORY
  228. glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 20, pos_and_color);
  229. glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 20, (void*)(pos_and_color+2));
  230. GLint nPosLoc = glGetAttribLocation(g_ShaderProgram, "position");
  231. glVertexAttribPointer(nPosLoc, 2, GL_FLOAT, GL_FALSE, 0, g_Vertices);
  232. GLint nTexcoordLoc = glGetAttribLocation(g_ShaderProgram, "texCoord");
  233. glVertexAttribPointer(nTexcoordLoc, 2, GL_FLOAT, GL_FALSE, 0, g_TexCoord);
  234. #else
  235. glBindBuffer(GL_ARRAY_BUFFER, g_vertexPosBuffer);
  236. GLint nPosLoc = glGetAttribLocation(g_ShaderProgram, "position");
  237. glEnableVertexAttribArray(nPosLoc);
  238. glVertexAttribPointer(nPosLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
  239. glBindBuffer(GL_ARRAY_BUFFER, NULL);
  240. glBindBuffer(GL_ARRAY_BUFFER, g_texturePosBuffer);
  241. GLint nTexcoordLoc = glGetAttribLocation(g_ShaderProgram, "texCoord");
  242. glEnableVertexAttribArray(nTexcoordLoc);
  243. glVertexAttribPointer(nTexcoordLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
  244. glBindBuffer(GL_ARRAY_BUFFER, NULL);
  245. #endif
  246. glDrawArrays(GL_TRIANGLES, 0, 6);
  247. glDisableVertexAttribArray(nPosLoc);
  248. glDisableVertexAttribArray(nTexcoordLoc);
  249. #ifdef EXPLICIT_SWAP
  250. emscripten_webgl_commit_frame();
  251. #endif
  252. #ifdef REPORT_RESULT
  253. REPORT_RESULT(0);
  254. #endif
  255. glUseProgram(NULL);
  256. return SR_OK;
  257. }
  258. #ifdef __cplusplus
  259. }
  260. #endif

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/46066?site
推荐阅读
相关标签
  

闽ICP备14008679号