爱问知识人 爱问教育 医院库

OpenGL ES渲染YUV纹理

首页

OpenGL ES渲染YUV纹理


        

提交回答
好评回答
  • 2023-12-14 19:30:03

    OpenGL中是不能直接渲染YUV数据的,但是我们可以用3个纹理来

    分别获得Y、U和V的值,然后按照公式:

    r = y + 1.403 * v;

    g = y - 0.344 * u - 0.714 * v;

    b = y + 1.770 * u;

    转为rgb颜色格式显示出来。这个转化过程是在GPU中完成的万能播放器java版,计算

    效率比在CPU中计算高很多倍!

    vertex_shader.glsl

    attribute ve av_Position;attribute vec2 af_Position;varying vec2 v_texPosition;void main() { v_texPosition = af_Position; gl_Position = av_Position;}

    注: attribute 只能在vertex中使用

    varying 用于vertex和fragment之间传递值

    fragment_shader.glsl

    precision mediump float;varying vec2 v_texPosition;uniform sampler2D sampler_y;uniform sampler2D sampler_u;uniform sampler2D sampler_v;void main() { float y,u,v; y = texture2D(sampler_y,v_texPosition).r; u = texture2D(sampler_u,v_texPosition).r- 0.5; v = texture2D(sampler_v,v_texPosition).r- 0.5; vec3 rgb; rgb.r = y + 1.403 * v; rgb.g = y - 0.344 * u - 0.714 * v; rgb.b = y + 1.770 * u; gl_FragColor = ve(rgb,1);}

    注: uniform 用于在application中向vertex和fragment中释放值。

    实现OpenGL ES的工具类-JfShaderUtil.java

    package com.example.myplayer.opengl;import android.content.Context;import android.opengl.GLES20;import com.example.myplayer.log.JfLog;import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;public class JfShaderUtil { public static String readRawTxt(Context context, int rawId) { InputStream inputStream = context.getResources().openRawResource(rawId); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); StringBuffer sb = new StringBuffer(); String line; try { while((line = reader.readLine()) != null) { sb.append(line).append("\n"); } reader.close(); } catch (Exception e) { e.printStackTrace(); } return sb.toString(); } public static int loadShader(int shaderType, String source) { int shader = GLES20.glCreateShader(shaderType); if(shader != 0) { GLES20.glShaderSource(shader, source); GLES20.glCompileShader(shader); int[] compile = new int[1]; GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compile, 0); if(compile[0] != GLES20.GL_TRUE) { JfLog.e("shader compile error"); GLES20.glDeleteShader(shader); shader = 0; } } return shader; } public static int createProgram(String vertexSource, String fragmentSource) { int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource); if(vertexShader == 0) { return 0; } int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource); if(fragmentShader == 0) { return 0; } int program = GLES20.glCreateProgram(); if(program != 0) { GLES20.glAttachShader(program, vertexShader); GLES20.glAttachShader(program, fragmentShader); GLES20.glLinkProgram(program); int[] linsStatus = new int[1]; GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linsStatus, 0); if(linsStatus[0] != GLES20.GL_TRUE) { JfLog.e( "link program error"); GLES20.glDeleteProgram(program); program = 0; } } return program; }}

    实现JfRender

    package com.example.myplayer.opengl;import android.content.Context;import android.opengl.GLES20;import android.opengl.GLSurfaceView;import com.example.myplayer.R;import com.example.myplayer.log.JfLog;import java.nio.ByteBuffer;import java.nio.ByteOrder;import java.nio.FloatBuffer;import javax.microedition.khronos.egl.EGLConfig;import javax.microedition.khronos.opengles.GL10;public class JfRender implements GLSurfaceView.Renderer { private Context context; private final float[] vertexData ={//顶点坐标 -1f, -1f, 1f, -1f, -1f, 1f, 1f, 1f }; private final float[] textureData ={//纹理坐标 0f,1f, 1f, 1f, 0f, 0f, 1f, 0f }; private FloatBuffer vertexBuffer; private FloatBuffer textureBuffer; private int program_yuv; private int avPosition_yuv; private int afPosition_yuv; private int sampler_y; private int sampler_u; private int sampler_v; private int[] textureId_yuv; //渲染用 private int width_yuv; private int height_yuv; private ByteBuffer y; private ByteBuffer u; private ByteBuffer v; public JfRender(Context context){ this.context = context; //存储顶点坐标数据 vertexBuffer = ByteBuffer.allocateDirect(vertexData.length * 4) .order(ByteOrder.nativeOrder()) .asFloatBuffer() .put(vertexData); vertexBuffer.position(0); //存储纹理坐标 textureBuffer = ByteBuffer.allocateDirect(textureData.length * 4) .order(ByteOrder.nativeOrder()) .asFloatBuffer() .put(textureData); textureBuffer.position(0); } @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { initRenderYUV(); } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { GLES20.glViewport(0, 0, width, height); } @Override public void onDrawFrame(GL10 gl) { //用黑色清屏 GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); renderYUV(); } /** * 初始化 */ private void initRenderYUV(){ String vertexSource = JfShaderUtil.readRawTxt(context, R.raw.vertex_shader); String fragmentSource = JfShaderUtil.readRawTxt(context,R.raw.fragment_shader); //创建一个渲染程序 program_yuv = JfShaderUtil.createProgram(vertexSource,fragmentSource); //得到着色器中的属性 avPosition_yuv = GLES20.glGetAttribLocation(program_yuv,"av_Position"); afPosition_yuv = GLES20.glGetAttribLocation(program_yuv,"af_Position"); sampler_y = GLES20.glGetUniformLocation(program_yuv, "sampler_y"); sampler_u = GLES20.glGetUniformLocation(program_yuv, "sampler_u"); sampler_v = GLES20.glGetUniformLocation(program_yuv, "sampler_v"); //创建纹理 textureId_yuv = new int[3]; GLES20.glGenTextures(3, textureId_yuv, 0); for(int i = 0; i < 3; i++) { //绑定纹理 GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId_yuv[i]); //设置环绕和过滤方式 GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); } JfLog.d("initRenderYUV"); } public void setYUVRenderData(int width, int height, byte[] y, byte[] u, byte[] v) { this.width_yuv = width; this.height_yuv = height; this.y = ByteBuffer.wrap(y); this.u = ByteBuffer.wrap(u); this.v = ByteBuffer.wrap(v); } /** * 渲染 */ private void renderYUV(){ JfLog.d("渲染中"); if(width_yuv > 0 && height_yuv > 0 && y != null && u != null && v != null){ GLES20.glUseProgram(program_yuv);//使用源程序 GLES20.glEnableVertexAttribArray(avPosition_yuv);//使顶点属性数组有效 GLES20.glVertexAttribPointer(avPosition_yuv, 2, GLES20.GL_FLOAT, false, 8, vertexBuffer);//为顶点属性赋值 GLES20.glEnableVertexAttribArray(afPosition_yuv); GLES20.glVertexAttribPointer(afPosition_yuv, 2, GLES20.GL_FLOAT, false, 8, textureBuffer); GLES20.glActiveTexture(GLES20.GL_TEXTURE0);//激活纹理 GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId_yuv[0]);//绑定纹理 GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE, width_yuv, height_yuv, 0, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE, y);// GLES20.glActiveTexture(GLES20.GL_TEXTURE1); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId_yuv[1]); GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE, width_yuv / 2, height_yuv / 2, 0, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE, u); GLES20.glActiveTexture(GLES20.GL_TEXTURE2); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId_yuv[2]); GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE, width_yuv / 2, height_yuv / 2, 0, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE, v); GLES20.glUniform1i(sampler_y, 0); GLES20.glUniform1i(sampler_u, 1); GLES20.glUniform1i(sampler_v, 2); y.clear(); u.clear(); v.clear(); y = null; u = null; v = null; GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); } }}

    劈***

    2023-12-14 19:30:03

相关推荐

正在加载...
最新问答 推荐信息 热门专题 热点推荐
  • 1-20
  • 21-40
  • 41-60
  • 61-80
  • 81-100
  • 101-120
  • 121-140
  • 141-160
  • 161-180
  • 181-200
  • 1-20
  • 21-40
  • 41-60
  • 61-80
  • 81-100
  • 101-120
  • 121-140
  • 141-160
  • 161-180
  • 181-200
  • 1-20
  • 21-40
  • 41-60
  • 61-80
  • 81-100
  • 101-120
  • 121-140
  • 141-160
  • 161-180
  • 181-200
  • 1-20
  • 21-40
  • 41-60
  • 61-80
  • 81-100
  • 101-120
  • 121-140
  • 141-160
  • 161-180
  • 181-200

热点检索

  • 1-20
  • 21-40
  • 41-60
  • 61-80
  • 81-100
  • 101-120
  • 121-140
  • 141-160
  • 161-180
  • 181-200
返回
顶部
帮助 意见
反馈

确定举报此问题

举报原因(必选):