bugyun / Android-OpenGLES

Android opengles 的使用指南

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Android-OpenGLES

Android opengles 的使用步骤

1.配置cmake

在cmakelist.txt添加如下配置

target_link_libraries( # Specifies the target library.
        native-lib
        GLESv2
        EGL
        android
        log)

2.创建 EGL

    //创建 EGL
    EGLDisplay eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    if (eglDisplay == EGL_NO_DISPLAY) {
        LOGE("eglGetDisplay 失败");
        return;
    }
    //初始化
    if (EGL_TRUE != eglInitialize(eglDisplay, 0, 0)) {
        LOGE("eglInitialize 失败");
        return;
    }

但是在配置参数的时候,需要注意,有的手机会因为attribs_24bit的参数问题,eglChooseConfig失败

    const EGLint attribs_24bit[] = {
            EGL_RENDERABLE_TYPE,
            EGL_OPENGL_ES2_BIT,  // Request opengl ES2.0
            EGL_SURFACE_TYPE,
            EGL_WINDOW_BIT,
            EGL_BLUE_SIZE, 8,
            EGL_GREEN_SIZE, 8,
            EGL_RED_SIZE, 8,
            EGL_DEPTH_SIZE, 24,
            EGL_NONE};

    //输出配置
    EGLConfig configs;
    EGLint num_configs;
    if (EGL_TRUE != eglChooseConfig(eglDisplay, attribs_24bit, &configs, 1, &num_configs)) {
        LOGE("eglChooseConfig 失败");
        return;
    }

    if (!num_configs) {
        LOGE("attribs_16bit");
        // Fall back to 16bit depth buffer
        const EGLint attribs_16bit[] = {EGL_RENDERABLE_TYPE,
                                        EGL_OPENGL_ES2_BIT,  // Request opengl ES2.0
                                        EGL_SURFACE_TYPE,
                                        EGL_WINDOW_BIT,
                                        EGL_BLUE_SIZE, 8,
                                        EGL_GREEN_SIZE, 8,
                                        EGL_RED_SIZE, 8,
                                        EGL_DEPTH_SIZE, 16,
                                        EGL_NONE};
        if (EGL_TRUE != eglChooseConfig(eglDisplay, attribs_16bit, &configs, 1, &num_configs)) {
            LOGE("eglChooseConfig 失败");
            return;
        }
    }

    if (!num_configs) {
        LOGE("Unable to retrieve EGL config");
        return;
    }
    //创建 ANativeWindow,获取原始窗口
    ANativeWindow *aNativeWindow = ANativeWindow_fromSurface(env, surface);

    //创建egl 的 surface,关联
    EGLSurface eglSurface = eglCreateWindowSurface(eglDisplay, configs, aNativeWindow, NULL);
    if (eglSurface == EGL_NO_SURFACE) {
        LOGE("eglCreateWindowSurface 失败");
        return;
    }

    //创建关联上下文,和 OpenGL 关联
    const EGLint attrib_list_context[] = {
            EGL_CONTEXT_CLIENT_VERSION,
            2,// Request opengl ES2.0
            EGL_NONE};
    EGLContext eglContext = eglCreateContext(eglDisplay, configs, NULL,
                                             attrib_list_context);
    if (eglContext == EGL_NO_CONTEXT) {
        LOGE("eglCreateContext 失败");
        return;
    }
    if (EGL_TRUE != eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext)) {
        LOGE("eglMakeCurrent 失败");
        return;
    }
    LOGE("egl 初始化成功");

这样egl就创建成功了。

3.创建着色器

    //初始化
    //顶点着色器
    GLuint vsh = InitShader(vertexShader, GL_VERTEX_SHADER);
    //片元着色器
    GLuint fsh = InitShader(fragYUV420P, GL_FRAGMENT_SHADER);

    //创建渲染程序
    GLuint program = glCreateProgram();
    if (program == 0) {
        LOGE("glCreateProgram 失败");
        return;
    }
    //加入着色器
    glAttachShader(program, vsh);
    glAttachShader(program, fsh);

    //链接程序
    glLinkProgram(program);

    //获取运行状态
    GLint status;
    glGetProgramiv(program, GL_LINK_STATUS, &status);
    if (status != GL_TRUE) {
        LOGE("glGetProgramiv 运行失败");
        return;
    }

    //激活渲染程序
    glUseProgram(program);
    LOGE("glUseProgram 运行成功");


    //加入三维顶点数据 两个三角形组成正方形
    static float vers[] = {
            1.0f, -1.0f, 0.0f,
            -1.0f, -1.0f, 0.0f,
            1.0f, 1.0f, 0.0f,
            -1.0f, 1.0f, 0.0f,
    };
    GLuint apos = (GLuint) glGetAttribLocation(program, "aPosition");
    glEnableVertexAttribArray(apos);
    //传递顶点
    glVertexAttribPointer(apos, 3, GL_FLOAT, GL_FALSE, 12, vers);

    //加入材质坐标数据
    static float txts[] = {
            1.0f, 0.0f, //右下
            0.0f, 0.0f,
            1.0f, 1.0f,
            0.0, 1.0
    };
    GLuint atex = (GLuint) glGetAttribLocation(program, "aTexCoord");
    glEnableVertexAttribArray(atex);
    glVertexAttribPointer(atex, 2, GL_FLOAT, GL_FALSE, 8, txts);


    //352x288
    int width = 352;
    int height = 288;

    //材质纹理初始化
    //设置纹理层
    glUniform1i(glGetUniformLocation(program, "yTexture"), 0); //对于纹理第1层
    glUniform1i(glGetUniformLocation(program, "uTexture"), 1); //对于纹理第2层
    glUniform1i(glGetUniformLocation(program, "vTexture"), 2); //对于纹理第3层

    //创建opengl纹理
    GLuint texts[3] = {0};
    //创建三个纹理
    glGenTextures(3, texts);

    //设置纹理属性
    glBindTexture(GL_TEXTURE_2D, texts[0]);
    //缩小的过滤器
    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默认
                 GL_LUMINANCE,//gpu内部格式 亮度,灰度图
                 width, height, //拉升到全屏
                 0,             //边框
                 GL_LUMINANCE,//数据的像素格式 亮度,灰度图 要与上面一致
                 GL_UNSIGNED_BYTE, //像素的数据类型
                 NULL                    //纹理的数据
    );

    //设置纹理属性
    glBindTexture(GL_TEXTURE_2D, texts[1]);
    //缩小的过滤器
    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默认
                 GL_LUMINANCE,//gpu内部格式 亮度,灰度图
                 width / 2, height / 2, //拉升到全屏
                 0,             //边框
                 GL_LUMINANCE,//数据的像素格式 亮度,灰度图 要与上面一致
                 GL_UNSIGNED_BYTE, //像素的数据类型
                 NULL                    //纹理的数据
    );

    //设置纹理属性
    glBindTexture(GL_TEXTURE_2D, texts[2]);
    //缩小的过滤器
    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默认
                 GL_LUMINANCE,//gpu内部格式 亮度,灰度图
                 width / 2, height / 2, //拉升到全屏
                 0,             //边框
                 GL_LUMINANCE,//数据的像素格式 亮度,灰度图 要与上面一致
                 GL_UNSIGNED_BYTE, //像素的数据类型
                 NULL                    //纹理的数据
    );

4.在屏幕上显示

    unsigned char *buf[3] = {0};
    buf[0] = new unsigned char[width * height];
    buf[1] = new unsigned char[width * height / 4];
    buf[2] = new unsigned char[width * height / 4];


    for (int i = 0; i < 100000; i++) {
        //420p   yyyyyyyy uu vv
        if (feof(fp) == 0) {
            //yyyyyyyy
            fread(buf[0], 1, static_cast<size_t>(width * height), fp);
            fread(buf[1], 1, static_cast<size_t>(width * height / 4), fp);
            fread(buf[2], 1, static_cast<size_t>(width * height / 4), fp);
        }

        //激活第1层纹理,绑定到创建的opengl纹理
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, texts[0]);
        //替换纹理内容
        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE,
                        buf[0]);



        //激活第2层纹理,绑定到创建的opengl纹理
        glActiveTexture(GL_TEXTURE0 + 1);
        glBindTexture(GL_TEXTURE_2D, texts[1]);
        //替换纹理内容
        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width / 2, height / 2, GL_LUMINANCE,
                        GL_UNSIGNED_BYTE, buf[1]);


        //激活第2层纹理,绑定到创建的opengl纹理
        glActiveTexture(GL_TEXTURE0 + 2);
        glBindTexture(GL_TEXTURE_2D, texts[2]);
        //替换纹理内容
        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width / 2, height / 2, GL_LUMINANCE,
                        GL_UNSIGNED_BYTE, buf[2]);

        //三维绘制
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
        //窗口显示
        eglSwapBuffers(eglDisplay, eglSurface);
    }

5.其他

具体代码可以参考native-lib.cpp

展示的视频文件在video目录下

About

Android opengles 的使用指南


Languages

Language:C++ 79.5%Language:Java 18.7%Language:CMake 1.8%