c++ OpenGL显示YUV数据

#include 
#include 
#include 
#include "openglNative.h"
#include 
#include 

#define LOG_TAG "OPENGL"
#define LOGI(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,__VA_ARGS__)

GLuint program;
GLuint vertexShader;
GLuint pixelShader;
GLint _positionHandle = -1, _coordHandle = -1;

int _width = 0;
int _height = 0;

const GLchar *VERTEX_SHADER = "attribute vec4 vPosition;\n"
        "attribute vec2 a_texCoord;\n"
        "varying vec2 tc;\n"
        "void main() {\n"
        "gl_Position = vPosition;\n"
        "tc = a_texCoord;\n"
        "}\n";

const GLchar *FRAGMENT_SHADER = "precision mediump float;\n"
        "uniform sampler2D tex_y;\n"
        "uniform sampler2D tex_u;\n"
        "uniform sampler2D tex_v;\n"
        "varying vec2 tc;\n"
        "void main() {\n"
        "vec4 c = vec4((texture2D(tex_y, tc).r - 16./255.) * 1.164);\n"
        "vec4 U = vec4(texture2D(tex_u, tc).r - 128./255.);\n"
        "vec4 V = vec4(texture2D(tex_v, tc).r - 128./255.);\n"
        "c += V * vec4(1.596, -0.813, 0, 0);\n"
        "c += U * vec4(0, -0.392, 2.017, 0);\n"
        "c.a = 1.0;\n"
        "gl_FragColor = c;\n"
        "}\n";

GLuint _frameBuffer;
GLuint _renderBuffer;

GLenum _textureI = GL_TEXTURE0;
GLenum _textureII = GL_TEXTURE1;
GLenum _textureIII = GL_TEXTURE2;
GLenum _tIindex = 0;
GLenum _tIIindex = 1;
GLenum _tIIIindex = 2;

GLint _yhandle = -1, _uhandle = -1, _vhandle = -1;
GLuint _ytid = 0, _utid = 0, _vtid = 0;

typedef struct {

    float position[3];
    float color[4];
    float texture[2];
} LLVertex;

const LLVertex Vertex[] = {
        {{-1, -1, 0}, {0, 0, 0, 1}, {0.0, 0.0}},
        {{-1, 1,  0}, {0, 0, 1, 1}, {0.0, 1.0}},
        {{1,  1,  0}, {0, 1, 0, 1}, {1.0, 1.0}},
        {{1,  -1, 0}, {1, 0, 0, 1}, {1.0, 0.0}}
};

const GLubyte LLIndices[] = {
        0, 1, 2,
        2, 3, 0
};

void checkGlError(const char *op) {
    GLint error;
    for (error = glGetError(); error; error = glGetError()) {
        LOGI("error::after %s() glError (0x%x)\n", op, error);
    }
}

GLuint test::createProgram() {
    GLuint vertexShader = loadShader(GL_VERTEX_SHADER, VERTEX_SHADER);
    GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, FRAGMENT_SHADER);
    program = glCreateProgram();
    if (program) {
        glAttachShader(program, vertexShader);
        checkGlError("vertexShader");
        glAttachShader(program, pixelShader);
        checkGlError("pixelShader");
        glLinkProgram(program);
        checkGlError("glLinkProgram");
        GLint linkStatus = 0;
        glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
        checkGlError("glGetProgramiv");
        if (!linkStatus) {
            glDeleteProgram(program);
            program = 0;
        }
    }

    GLuint vertexBuffer;
    glGenBuffers(1, &vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex), Vertex, GL_STATIC_DRAW);

    GLuint indexBuffer;
    glGenBuffers(1, &indexBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(LLIndices), LLIndices, GL_STATIC_DRAW);

    return program;
}

GLuint test::loadShader(GLenum shaderType, const GLchar *source) {
    GLuint shader = glCreateShader(shaderType);
    if (shader) {
        int len = strlen(source);
        glShaderSource(shader, 1, &source, &len);
        checkGlError("glShaderSource");
        glCompileShader(shader);
        checkGlError("glCompileShader");
        GLint complied = 0;
        glGetShaderiv(shader, GL_COMPILE_STATUS, &complied);
        checkGlError("glGetShaderiv");
        if (complied == GL_FALSE) {
            glDeleteShader(shader);
            shader = 0;
        }
    }
    return shader;
}

EGLContext context;

void test::buildProgram() {
    context = eglGetCurrentContext();

    if (program <= 0) {
        program = createProgram();
    }

    const GLchar *vp = "vPosition";
    _positionHandle = glGetAttribLocation(program, vp);
    checkGlError("glGetAttribLocation vPosition");
    if (_positionHandle == -1) {
        LOGI("Could not get attribute location for vPosition");
    }
    const GLchar *at = "a_texCoord";
    _coordHandle = glGetAttribLocation(program, at);
    checkGlError("glGetAttribLocation a_texCoord");
    if (_coordHandle == -1) {
        LOGI("Could not get attribute location for a_texCoord");
    }

    _yhandle = glGetUniformLocation(program, "tex_y");
    checkGlError("glGetUniformLocation tex_y");
    if (_yhandle == -1) {
        LOGI("_yhandle -1");
    }

    _uhandle = glGetUniformLocation(program, "tex_u");
    checkGlError("glGetUniformLocation tex_u");
    if (_uhandle == -1) {
        LOGI("_uhandle -1");
    }

    _vhandle = glGetUniformLocation(program, "tex_v");
    checkGlError("glGetUniformLocation tex_v");
    if (_vhandle == -1) {
        LOGI("_vhandle -1");
    }
}

void
test::buildTexture(unsigned char *y, unsigned char *u, unsigned char *v, int width, int height) {
    if (_ytid == 0) {
        GLuint y_textures = 0;
        glGenTextures(1, &y_textures);
        checkGlError("glGenTextures");
        _ytid = y_textures;
    }
    glBindTexture(GL_TEXTURE_2D, (GLuint) _ytid);
    checkGlError("glBindTexture");
    glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, GL_LUMINANCE,
                 GL_UNSIGNED_BYTE, y);
    checkGlError("glTexImage2D");
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    if (_utid == 0) {
        GLuint u_textures = 0;
        glGenTextures(1, &u_textures);
        checkGlError("glGenTextures");
        _utid = u_textures;
    }
    glBindTexture(GL_TEXTURE_2D, (GLuint) _utid);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width / 2, height / 2, 0,
                 GL_LUMINANCE,
                 GL_UNSIGNED_BYTE, u);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    GLuint v_textures = 0;
    if (_vtid == 0) {
        glGenTextures(1, &v_textures);
        checkGlError("glGenTextures");
        _vtid = v_textures;
    }
    glBindTexture(GL_TEXTURE_2D, (GLuint) _vtid);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width / 2, height / 2, 0,
                 GL_LUMINANCE,
                 GL_UNSIGNED_BYTE, v);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}

void test::draw() {
    glViewport(0, 0, _width, _height);
    glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glUseProgram(program);

    glVertexAttribPointer(_positionHandle, 3, GL_FLOAT, GL_FALSE, sizeof(LLVertex), 0);
    glEnableVertexAttribArray(_positionHandle);

    glVertexAttribPointer(_coordHandle, 2, GL_FLOAT, GL_FALSE, sizeof(LLVertex),
                          (GLvoid *) (sizeof(float) * 7));
    glEnableVertexAttribArray(_coordHandle);

    glActiveTexture(_textureI);
    glBindTexture(GL_TEXTURE_2D, (GLuint) _ytid);
    glUniform1i(_yhandle, _tIindex);
    checkGlError("_yhandle");

    glActiveTexture(_textureII);
    glBindTexture(GL_TEXTURE_2D, (GLuint) _utid);
    glUniform1i(_uhandle, _tIIindex);
    checkGlError("_uhandle");

    glActiveTexture(_textureIII);
    glBindTexture(GL_TEXTURE_2D, (GLuint) _vtid);
    glUniform1i(_vhandle, _tIIIindex);
    checkGlError("_vhandle");

    glEnableVertexAttribArray(_positionHandle);
    glEnableVertexAttribArray(_coordHandle);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0);
}

你可能感兴趣的:(多媒体)