IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> opengl es2.0渲染图并局部刷新 -> 正文阅读

[游戏开发]opengl es2.0渲染图并局部刷新

??????? 最近在鼓捣OpenGL渲染,这东西确实给显示带来很大便利,网上资料也比较多,不过因为这些接口都高度封装,出问题可不太好查。我在网上看了一些资料,有很多渲染图的例子,不过貌似渲染图并刷新的比较少见,所以把我的一些经验分享一下,毕竟像我一样临时现学现搞的菜鸟应该还是比较多的。期间遇到一些坑,还好有大佬的帮忙。。。

1. 着色器脚本

??????? 这算是opengl的基本概念,就不做详细解释了

char *vertex_shader_source =
"attribute vec2 vertexCoord;"
"attribute vec2 textureCoord;"
"varying vec2 sampleCoord;"
"void main()"
"{"
"   sampleCoord = textureCoord;"
"   gl_Position = vec4(vertexCoord, 0.0, 1.0);"
"}";

char *fragment_shader_source =
"precision mediump float;"
"varying vec2 sampleCoord;"
"uniform sampler2D sampleTexture;"
"void main()"
"{"
"   gl_FragColor = texture2D(sampleTexture, sampleCoord);"
"}";

2.构建着色器程序

??????? 这个也是基本操作,八股文一样,也不再细说了

static void check_gl_error(char *gl_operation)
{
    for (GLint error = glGetError(); error; error = glGetError())
    {
        g_info("[GL] Operation %s() glError (0x%x)", gl_operation, error);
    }
}

static GLuint load_shader(GLenum shader_type, char *shader_source)
{
    GLuint shader = glCreateShader(shader_type);
    if (shader) {
        glShaderSource(shader, 1, &shader_source, NULL);
        glCompileShader(shader);
        GLint compiled = 0;
        glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
        if (!compiled) {
            GLint infoLen = 0;
            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
            if (infoLen) {
                char* buf = (char*)malloc(infoLen);
                if (buf) {
                    glGetShaderInfoLog(shader, infoLen, NULL, buf);
                    g_info("[GL] Could not compile shader %d:%s", shader_type, buf);
                    free(buf);
                }
                glDeleteShader(shader);
                shader = 0;
            }
        }
    }
    return shader;
}

static GLuint gl_render_create_program(GlRender *render, char *vertex_shader_source, char *fragment_shader_source)
{
    g_return_val_if_fail(IS_GL_RENDER(render), 0);
    GlRenderPrivate *p = render->priv;

    p->vertex_shader = load_shader(GL_VERTEX_SHADER, vertex_shader_source);
    if (!p->vertex_shader) {
        return 0;
    }
    
    p->fragment_shader = load_shader(GL_FRAGMENT_SHADER, fragment_shader_source);
    if (!p->fragment_shader) {
        return 0;
    }
    
    GLuint program = glCreateProgram();
    if (program) {
        glAttachShader(program, p->vertex_shader);
        check_gl_error("glAttachShader");
        glAttachShader(program, p->fragment_shader);
        check_gl_error("glAttachShader");
        glLinkProgram(program);
        GLint linkStatus = GL_FALSE;
        glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
        if (linkStatus != GL_TRUE) {
            GLint bufLength = 0;
            glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
            if (bufLength) {
                char* buf = (char*)malloc(bufLength);
                if (buf) {
                    glGetProgramInfoLog(program, bufLength, NULL, buf);
                    g_info("[GL] Could not link program:%s", buf);
                    free(buf);
                }
            }
            glDeleteProgram(program);
            program = 0;
        }
    }
    return program;
}

3.坐标系初始化

??????? 定点坐标及纹理坐标初始化后可以直接使用了,不需要再对每一幅图作坐标映射,因为图像是局部刷新,每次显示还是全图

static void gl_render_get_handles(GlRender *render)
{
    g_return_if_fail(IS_GL_RENDER(render));
    GlRenderPrivate *p = render->priv;

    glUseProgram(p->program);

    p->vertex_coord_handle = glGetAttribLocation(p->program, "vertexCoord");
    p->texture_coord_handle = glGetAttribLocation(p->program, "textureCoord");
    p->sample_texture_handle = glGetUniformLocation(p->program, "sampleTexture");

    g_info("[GL] vertex_coord_handle = %d", p->vertex_coord_handle);
    g_info("[GL] texture_coord_handle = %d", p->texture_coord_handle);
    g_info("[GL] sample_texture_handle = %d", p->sample_texture_handle);

    glEnableVertexAttribArray(p->vertex_coord_handle);
    glEnableVertexAttribArray(p->texture_coord_handle);
}

void gl_render_open(GlRender *render)
{
    g_return_if_fail(IS_GL_RENDER(render));
    GlRenderPrivate *p = render->priv;

    p->texture_id = 0;
    p->texture_width = 0;
    p->texture_height = 0;
    p->surface_width = 0;
    p->surface_height = 0;

    p->vertex_coord[0] = -1.0f;
    p->vertex_coord[1] = -1.0f;
    p->vertex_coord[2] = 1.0f;
    p->vertex_coord[3] = -1.0f;
    p->vertex_coord[4] = -1.0f;
    p->vertex_coord[5] = 1.0f;
    p->vertex_coord[6] = 1.0f;
    p->vertex_coord[7] = 1.0f;

    p->texture_coord[0] = 0.0f;
    p->texture_coord[1] = 1.0f;
    p->texture_coord[2] = 1.0f;
    p->texture_coord[3] = 1.0f;
    p->texture_coord[4] = 0.0f;
    p->texture_coord[5] = 0.0f;
    p->texture_coord[6] = 1.0f;
    p->texture_coord[7] = 0.0f;

    p->program = gl_render_create_program(render, vertex_shader_source, fragment_shader_source);
    if (!p->program)
    {
        g_info("[GL] init render failed");
    }

    gl_render_get_handles(render);
}

4.加载纹理到GPU

? ??????? 考虑切换分辨率的情况,当view的尺寸或纹理的尺寸出现变化时,通过设置glTexImage2D最后一个参数为NULL分配一个全图的缓存,尺寸不变的时候通过glTexSubImage2D往缓冲区写入局部的图像数据,达到局部刷新的效果

GLuint gl_render_load_texture(GlRender *render, GlContext *context,
                                void* data, int x, int y, int width, int height, int max_width, int max_height)
{
    g_return_val_if_fail(IS_GL_RENDER(render), 0);
    GlRenderPrivate *p = render->priv;

    int surface_width = 0;
    int surface_height = 0;
    gl_context_get_width_height(context, &surface_width, &surface_height);

    if (p->texture_width != max_width || p->texture_height != max_height
        || p->surface_width != surface_width || p->surface_height != surface_height)
    {
        p->texture_width = max_width;
        p->texture_height = max_height;
        p->surface_width = surface_width;
        p->surface_height = surface_height;

        glViewport(0, 0, surface_width, surface_height);
        g_info("[GL] set opengl view width %d, height %d, texture width %d, texture height %d",
                surface_width, surface_height, max_width, max_height);

        if (p->texture_id)
        {
            glDeleteTextures(1, &p->texture_id);
            p->texture_id = 0;
        }

        glGenTextures(1, &p->texture_id);
        check_gl_error("glGenTextures");

        glBindTexture(GL_TEXTURE_2D, p->texture_id);
        check_gl_error("glBindTexture");

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        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, GL_BGRA_IMG, max_width, max_height, 0, GL_BGRA_IMG, GL_UNSIGNED_BYTE, NULL);
        check_gl_error("glTexImage2D");
    }

    glBindTexture(GL_TEXTURE_2D, p->texture_id);
    glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, GL_BGRA_IMG, GL_UNSIGNED_BYTE, data);
    check_gl_error("glTexSubImage2D");

    glBindTexture(GL_TEXTURE_2D, 0);

    return p->texture_id;
}

5.绘制

void gl_render_draw(GlRender *render, GlContext *context)
{
    g_return_if_fail(IS_GL_RENDER(render));
    GlRenderPrivate *p = render->priv;

    glUseProgram(p->program);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, p->texture_id);

    glUniform1i(p->sample_texture_handle, 0);

    glVertexAttribPointer(p->vertex_coord_handle, 2, GL_FLOAT, GL_FALSE, 0, p->vertex_coord);
    glVertexAttribPointer(p->texture_coord_handle, 2, GL_FLOAT, GL_FALSE, 0, p->texture_coord);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    check_gl_error("glDrawArrays");

    gl_context_swap_buffers(context);
}

6.用完后记得释放资源

if (p->texture_id) {
    glDeleteTextures(1, &p->texture_id);
}
if (p->fragment_shader) {
    glDeleteShader(p->fragment_shader);
    glDetachShader(p->program, p->fragment_shader);
}
if (p->vertex_shader) {
    glDeleteShader(p->vertex_shader);
    glDetachShader(p->program, p->vertex_shader);
}
if (p->program) {
    glDeleteProgram(p->program);
}

7.小结

??????? 用法:先调用gl_render_load_texture加载纹理(第一次调用最好传一幅全图),然后调用gl_render_draw绘制,不断循环这个过程。关键点是顶点坐标及纹理坐标,以及图像纹理的加载方式。本人用的是gobiect,跟c++的class是类似的东西,这里的GlContext其实是另一个抽象类,里面有egl的实现,主要是创建surface还有egl的swapbuffers,这个实现网上很多,这里就不再细述了

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2021-11-26 09:10:11  更:2021-11-26 09:11:47 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/27 22:21:27-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码