• 阅读《计算机图形学编程(使用OpenGL和C++)》2


    OpenGL可以绘制点、线、三角形,这些简单的东西叫做图元,多数3D模型通常是由许多三角形的图元构成。图元由顶点组成。顶点可以从文件读取并由C++/OpenGL应用载入缓冲区或直接在C++文件中硬编码字符串或直接在GLSL代码中。在加载顶点之前,C++/OpenGL应用必须编译并链接合适的GLSL顶点着色器和片段着色器程序,之后将它们载入管线。

    C++/OpenGL应用同时负责通知OpenGL构建三角形,通过调用函数glDrawArrays(),管线中的GLSL代码开始执行。所有的顶点都会被传入顶点着色器。着色器对每个顶点执行一次,这些执行过程通常是并行的。

    glDrawArrays (GLenum mode, GLint first, GLsizei count);

    mode参数是图元的类型——对于三角形用GL_TRIANGLES。First参数表示从哪个顶点开始绘制(通常是顶点0,即第一个顶点),count是要绘制的顶点总数。

    将GLSL程序载入着色器
    1、 使用C++获取GLSL着色器代码,从文件或字符串中读取
    2、 创建OpenGL着色器对象并将GLSL着色器代码加载进着色器对象
    3、 用OpenGL命令编译并连接着色器对象,并将其安装进GPU

    OpenGL中点的默认大小为1像素。

    窗口中央有一个蓝色的点的代码如下。

    main.cpp

    (#include列表与之前同)
    
    #define numVAOs 1
    
    GLuint renderingProgram;
    GLuint vao[numVAOs];
    
    GLuint createShaderProgram()
    {
        const char* vshaderSource = 
            "#version 460 \n"
            "void main(void) \n"
            "{ gl_Position = vec4(0.0, 0.0, 0.0, 1.0); }";
    
        const char* fshaderSource =
            "#version 460 \n"
            "out vec4 color; \n"
            "void main(void) \n"
            "{ color = vec4(0.0, 0.0, 1.0, 1.0); }";
    
        GLuint vShader = glCreateShader(GL_VERTEX_SHADER); // 创建类型 GL_VERTEX_SHADER 的着色器,返回引用它的序号
        GLuint fShader = glCreateShader(GL_FRAGMENT_SHADER); // 创建类型 GL_FRAGMENT_SHADER 的着色器,返回引用它的序号
    
        glShaderSource(vShader, 1, &vshaderSource, NULL); // 将GLSL代码从字符串载入空着色器对象中 
        glShaderSource(fShader, 1, &fshaderSource, NULL);
        glCompileShader(vShader); // 编译各着色器
        glCompileShader(fShader);
    
        GLuint vfProgram = glCreateProgram(); // 创建程序对象,并储存指向它的整数ID
        glAttachShader(vfProgram, vShader); // 将着色器加入程序对象
        glAttachShader(vfProgram, fShader);
        glLinkProgram(vfProgram); // 让GLSL编译器确保它们的兼容性
    
        return vfProgram;
    }
    
    void init(GLFWwindow* window){
        renderingProgram = createShaderProgram();
        glGenVertexArrays(numVAOs, vao);
        glBindVertexArray(vao[0]);
    }
    
    void display(GLFWwindow* window, double currentTime)
    {
        glUseProgram(renderingProgram); // 将含有两个已编译着色器的程序载入OpenGL管线阶段(在GPU上),没有运行着色器,只是将着色器加载进硬件
        glDrawArrays(GL_POINTS, 0, 1); // 启动管线处理过程
    }
    (main函数与之前同)

    字符串 vshaderSource 是顶点着色器中硬编码了一个顶点。顶点着色器的主要目标是将顶点发送给管线。内置变量  gl_Position 用来设置顶点在3D空间的坐标位置,并发送至下一个管线阶段。GLSL数据类型 vec4 用来存储4元组。

    顶点接下来将沿着管线移动到光栅着色器,它们在这里被转换成像素位置。最终这些像素到达片段着色器 fshaderSource 。片段着色器的目的是给将要展示的像素赋予RGB颜色。本例中是蓝色。"out" 标签表明 color 变量是输出变量。在顶点着色器中 gl_Position 是预定义的输出变量,所以并不是必须给它指定 "out" 标签。

    当准备将数据集发送给管线时是以缓冲区形式发送的,这些缓冲区最后都会被存入顶点数组对象(Vertex Array Object, VAO)中,即使应用程序没有用到任何缓冲区,OpenGL仍然需要在使用着色器的时候至少有一个创建好的 VAO,所以 init() 后两行用来创建OpenGL要求的 VAO。

    glShaderSource()有4个参数:

    1、着色器对象;2、着色器源代码中的字符串数量;3、包含源代码的字符串指针;4、指定一个长度数组,其中包括给定着色器程序中每行代码的字符串的整数长度。如果设为NULL,OpenGL将会自动从以 NULL 结尾的字符串中构建这个数组。

    glShaderSource(GLuint shader, GLsizei count, const GLchar *const* string, const GLint* length);

    结果如下:

     在display()中加入下面代码,放在 glDrawArrays() 前面

    glPointSize(30.0f);

    当光栅化阶段从顶点着色器收到顶点时,它会为一个大小是30像素的点设置像素颜色值。

    结果如下:

  • 相关阅读:
    webpack打包注意事项
    打印内存, 打印16进制
    c++ 字符集转换
    RegSvr32 加载失败,找不到指定的模块
    错误码设计
    mfc 移动绘制的图形
    获取、设置光标
    c++ 函数中定义函数
    python linux 自动补全 tab.py
    3.4.5节 完整神经网络样例程序
  • 原文地址:https://www.cnblogs.com/lely/p/15852991.html
Copyright © 2020-2023  润新知