美文网首页
OpenGL-ES 学习(4)---- Shader对象和程序对

OpenGL-ES 学习(4)---- Shader对象和程序对

作者: 特立独行的佩奇 | 来源:发表于2022-02-02 14:19 被阅读0次
    本节概述

    在本节中,我们提供创建Shader,并且编译链接到一个程序对象的完整流程,主要内容如下:

    • Shader 和程序对象概述
    • 创建和编译Shader
    • 创建和链接程序对象
    • 设置和获取统一变量
    • 获取和设置属性
    • Shader 编译器和程序二进制代码

    想要用Shader 进行渲染,必须创建两个基本的对象:Shader 对象和程序对象;它们之间的关系类似于C语言链接程序和编译器

    1. C语言对象将一段源代码生成目标对象
    2. C链接程序将对象文件链接为最后的文件

    Shader 对象是包含多个Shader 的对象,源代码提供给Shader 对象,Shader 对象被编译为一个目标形式(类似于 obj 文件),编译之后,Shader 对象可以连接到一个程序对象,一个程序对象可以连接多个 Shader 对象,在 OpenGL-ES 中,每个程序对象必须连接到一个Vertex Shader 对象和Fragment Shader.

    之后使用Shader 进行渲染,步骤如下:


    shader渲染.png
    创建和编译Shader

    创建和编译Shader使用的 API如下:
    glCreateShader (GLenum type)
    glDeleteShader(GLuint shader)
    说明:创建/删除 vertex shader or fragment shader ,返回新 shader 的handle

    glShaderSource (GLuint shader, GLsizei count, const GLchar conststring, const GLint *length)
    说明:指定Shader 的src_code 源代码

    glCompileShader (GLuint shader)
    说明:编译Shader

    glGetShaderiv(GLuint shader,GLenum pname,GLint * params)
    说明:检查Shader 是否编译成功

    glGetShaderInfoLog(GLuint shader,GLsizei maxLength,GLsizei *length,GLchar *infoLog)
    说明:获取编译Shader 的log 信息

    链接程序对象

    链接程序对象使用的 API 如下:

    API 说明
    glCreateProgram() 创建程序对象
    glDeleteProgram() 删除程序对象
    glAttachShader() Shader 对象连接到程序对象
    glDetachShader() Shader 对象从程序对象分离
    glLinkPrigram() 链接程序对象
    glGetProgramiv 查询Shader 链接信息
    glGetProgramInfoLog 获取程序信息日志
    绘制一个最简单的三角形

    绘制一个基本三角形,示例输入顶点坐标和颜色坐标如下:

        //R G B A
        GLfloat color[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
        // 3 vertices, with (x,y,z) per-vertex
        GLfloat vertexPos[3 * 3] =
        {
            1.0f,  0.0f, 0.0f, // v0
            0.0f, 1.0f, 0.0f, // v1
            0.0f, 0.0f, 1.0f  // v2
        };
    

    vertexPos数组表示的是三个顶点的三维坐标,OpenGL-ES 中使用的坐标系如下图所示:


    Vertex 坐标.png openGL-坐标.png

    最终显示效果:


    最终效果png.png
    示例代码
    #include "esUtil.h"
    
    typedef struct
    {
        GLuint programObject;
    } UserData;
    
    static int Init(ESContext *esContext)
    {
        UserData *userData = esContext->userData;
        const char vShaderStr[] =
            "#version 300 es                            \n"
            "layout(location = 0) in vec4 a_position;   \n"
            "layout(location = 1) in vec4 a_color;      \n"
            "out vec4 v_color;                          \n"
            "void main()                                \n"
            "{                                          \n"
            "    v_color = a_color;                     \n"
            "    gl_Position = a_position;              \n"
            "}";
    
        const char fShaderStr[] =
            "#version 300 es            \n"
            "precision mediump float;   \n"
            "in vec4 v_color;           \n"
            "out vec4 o_fragColor;      \n"
            "void main()                \n"
            "{                          \n"
            "    o_fragColor = v_color; \n"
            "}";
    
        GLuint programObject;
    
        // Create the program object
        programObject = esLoadProgram(vShaderStr, fShaderStr);
    
        if (programObject == 0) {
            return GL_FALSE;
        }
    
        // Store the program object
        userData->programObject = programObject;
    
        // R G B A
        glClearColor(1.0f, 1.0f, 1.0f, 0.5f);
        return GL_TRUE;
    }
    
    static void Shutdown(ESContext *esContext)
    {
        UserData *userData = esContext->userData;
        glDeleteProgram(userData->programObject);
    }
    
    
    static void Draw(ESContext *esContext)
    {
        UserData *userData = esContext->userData;
        //R G B A
        GLfloat color[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
        // 3 vertices, with (x,y,z) per-vertex
        GLfloat vertexPos[3 * 3] =
        {
            1.0f,  0.0f, 0.0f, // v0
            0.0f, 1.0f, 0.0f, // v1
            0.0f, 0.0f, 1.0f  // v2
        };
    
        glViewport(0, 0, esContext->width, esContext->height);
    
        glClear(GL_COLOR_BUFFER_BIT);
        glUseProgram(userData->programObject);
    
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertexPos);
        glEnableVertexAttribArray(0);
        glVertexAttrib4fv(1, color);
    
        glDrawArrays(GL_TRIANGLES, 0, 3);
        glDisableVertexAttribArray(0);
    }
    
    // 必须 注册 draw 函数和 shutdown 函数
    int esMain(ESContext *esContext)
    {
        esContext->userData = malloc(sizeof(UserData));
    
        esCreateWindow(esContext, "gl_basic demo", 320, 240, ES_WINDOW_RGB);
        if (!Init(esContext))
        {
            return GL_FALSE;
        }
    
        esRegisterShutdownFunc(esContext, Shutdown);
        esRegisterDrawFunc(esContext, Draw);
    
        return GL_TRUE;
    }
    

    相关文章

      网友评论

          本文标题:OpenGL-ES 学习(4)---- Shader对象和程序对

          本文链接:https://www.haomeiwen.com/subject/avcrkrtx.html