• opengl入门篇一: 第一个三角形


    话说程序员有三大浪漫,操作系统、编译原理和计算机图形学。这里称作计算机图形学,而不是图形学,是为了避免歧义。

    opengl是干什么的,可以自行google。这里仅作为一个学习里程中的记录。不作为权威指南。

    入门教程参见,https://learnopengl-cn.readthedocs.io/zh/latest/01%20Getting%20started/02%20Creating%20a%20window/

    opengl的环境配置可以见,https://zhuanlan.zhihu.com/p/23226676?utm_medium=social&utm_source=qq,谢谢大神分享。

    本是在windows10, visual studio2015的环境下运行。顺便提一句,windows10自带opengl库,即包含了opengl32.lib。下面上代码。

    shader.vs    顶点着色器代码

    #version 330 core
    layout (location = 0) in vec3 position;//in 代表输入向量, location,与下面的顶点属性描述有关。
    layout (location = 1) in vec3 color;
    
    out vec3 ourColor;//out 代表输出3维向量,作为片段着色器的输入,见下文
    
    void main()
    {
        gl_Position = vec4(position, 1.0f);
        ourColor = color;
    }

    shader.frag  片段着色器代码

    #version 330 core
    in vec3 ourColor;
    out vec4 color;
    
    void main()
    {
        color = vec4(ourColor, 1.0f);
    }

    main.cpp

    #include <iostream>
    // GLEW
    #define GLEW_STATIC
    #include <GL/glew.h>
    // GLFW
    #include <GLFW/glfw3.h>
    // Other includes
    #include "Shader.h"
    
    // Function prototypes
    void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
    
    // Window dimensions
    const GLuint WIDTH = 800, HEIGHT = 600;
    // The MAIN function, from here we start the application and run the game loop int main() { // Init GLFW glfwInit(); // Set all the required options for GLFW glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); // Create a GLFWwindow object that we can use for GLFW's functions GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr); glfwMakeContextCurrent(window); // Set the required callback functions glfwSetKeyCallback(window, key_callback); // Set this to true so GLEW knows to use a modern approach to retrieving function pointers and extensions glewExperimental = GL_TRUE; // Initialize GLEW to setup the OpenGL Function pointers glewInit(); // Define the viewport dimensions glViewport(0, 0, WIDTH, HEIGHT); //读取shader文件,并编译,见shader.h代码 Shader ourShader("C:\Users\leng\Desktop\shader.vs", "C:\Users\leng\Desktop\shader.frag"); // 一维数组,每六个代表一个顶点属性,前三个代表位置属性,后三个代表颜色属性 GLfloat vertices[] = { // Positions // Colors 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, // Bottom Right -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, // Bottom Left 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f // Top }; GLuint VBO, VAO;//声明顶点缓冲,声明顶点数组用于管理顶点数据 glGenVertexArrays(1, &VAO);//创建顶点数组,返回一个独一无二的整数,标识数组 glGenBuffers(1, &VBO);//创建顶点缓冲,返回一个独一无二的整数,标识缓冲区 glBindVertexArray(VAO);//绑定顶点数组 glBindBuffer(GL_ARRAY_BUFFER, VBO);//绑定顶点缓冲
      //指定顶点数组的数据源为vertices,第四个参数代表显卡如何管理给定的数据,GL_STATIC_DRWA代表几乎不会改变 glBufferData(GL_ARRAY_BUFFER,
    sizeof(vertices), vertices, GL_STATIC_DRAW); // 指定顶点属性的解析方式。即,如何从顶点缓冲获取相应的顶点属性和相应的颜色属性。或者说,顶点着色器中如何知道去哪个顶点属性分量重着色呢
      //对每一个顶点而言,属性有2种,一是位置属性,而是颜色属性,因此每六个浮点数决定了一个顶点的位置和颜色

      //顶点着色器中使用layout(location = 0)定义了position顶点属性的位置值(Location),因此第一个参数,代表属性分量的索引
      //参数二:顶点位置属性的维度,参数三:属性向量的数据类型,参数四:是否标准化;参数五,顶点位置属性的总字节长度,参数六:在缓冲数组中的偏移量,即起始位置 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0); glEnableVertexAttribArray(0);//启用属性0,因为默认是禁用的
    // 参数一,对应顶点着色器中的layout (location = 1) in vec3 color;参数六:说明颜色属性的偏移量在三个浮点数后,与上文vertices一致 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); glEnableVertexAttribArray(1);//启用属性1.
      //顶点数组对象(Vertex Array Object, VAO)的好处就是,当配置顶点属性指针时,你只需要将上面的代码调用执行一次,之后再绘制物体的时候只需要绑定相应的VAO就行了。如下文循环中的绑定再解绑 glBindVertexArray(
    0); // 解绑 VAO // Game loop while (!glfwWindowShouldClose(window)) { // 检查事件,调用相应的回调函数,如下文的key_callback函数 glfwPollEvents(); // Render // Clear the colorbuffer glClearColor(0.2f, 0.3f, 0.3f, 1.0f);//渲染颜色到后台缓冲 glClear(GL_COLOR_BUFFER_BIT);//清除前台缓冲 // Draw the triangle ourShader.Use();//启用着色器程序 glBindVertexArray(VAO);//每次循环都调用,绑定函数绑定VAO glDrawArrays(GL_TRIANGLES, 0, 3); glBindVertexArray(0);//解绑 // Swap the screen buffers glfwSwapBuffers(window); } // Properly de-allocate all resources once they've outlived their purpose glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); // Terminate GLFW, clearing any resources allocated by GLFW. glfwTerminate(); return 0; } // Is called whenever a key is pressed/released via GLFW void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) { if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) glfwSetWindowShouldClose(window, GL_TRUE); }

    Shader.h    从文件中读取着色器代码,并编译。

    #ifndef SHADER_H
    #define SHADER_H
    
    #include <string>
    #include <fstream>
    #include <sstream>
    #include <iostream>
    
    #include <GL/glew.h>
    
    class Shader
    {
    public:
        GLuint Program;
        // Constructor generates the shader on the fly
        Shader(const GLchar* vertexPath, const GLchar* fragmentPath)
        {
            // 1. Retrieve the vertex/fragment source code from filePath
            std::string vertexCode;
            std::string fragmentCode;
            std::ifstream vShaderFile;
            std::ifstream fShaderFile;
            // ensures ifstream objects can throw exceptions:
            vShaderFile.exceptions(std::ifstream::badbit);
            fShaderFile.exceptions(std::ifstream::badbit);
            try
            {
                // Open files
                vShaderFile.open(vertexPath);
                fShaderFile.open(fragmentPath);
                std::stringstream vShaderStream, fShaderStream;
                // Read file's buffer contents into streams
                vShaderStream << vShaderFile.rdbuf();
                fShaderStream << fShaderFile.rdbuf();
                // close file handlers
                vShaderFile.close();
                fShaderFile.close();
                // Convert stream into string
                vertexCode = vShaderStream.str();
                fragmentCode = fShaderStream.str();
            }
            catch (std::ifstream::failure e)
            {
                std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl;
            }
            const GLchar* vShaderCode = vertexCode.c_str();
            const GLchar * fShaderCode = fragmentCode.c_str();
            // 2. Compile shaders
            GLuint vertex, fragment;
            GLint success;
            GLchar infoLog[512];
            // Vertex Shader
            vertex = glCreateShader(GL_VERTEX_SHADER);//创建顶点着色器
            glShaderSource(vertex, 1, &vShaderCode, NULL);//指定源代码
            glCompileShader(vertex);//编译着色器
            // Print compile errors if any
            glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);//查看是否编译成功
            if (!success)
            {
                glGetShaderInfoLog(vertex, 512, NULL, infoLog);
                std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED
    " << infoLog << std::endl;
            }
            // Fragment Shader
            fragment = glCreateShader(GL_FRAGMENT_SHADER);//创建片段着色器
            glShaderSource(fragment, 1, &fShaderCode, NULL);
            glCompileShader(fragment);
            // Print compile errors if any
            glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
            if (!success)
            {
                glGetShaderInfoLog(fragment, 512, NULL, infoLog);
                std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED
    " << infoLog << std::endl;
            }
            // Shader Program
            this->Program = glCreateProgram();//创建着色程序
            glAttachShader(this->Program, vertex);//关联顶点着色器
            glAttachShader(this->Program, fragment);//关联片段着色器
            glLinkProgram(this->Program);//链接编译器
            // Print linking errors if any
            glGetProgramiv(this->Program, GL_LINK_STATUS, &success);
            if (!success)
            {
                glGetProgramInfoLog(this->Program, 512, NULL, infoLog);
                std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED
    " << infoLog << std::endl;
            }
            // Delete the shaders as they're linked into our program now and no longer necessery
            glDeleteShader(vertex);
            glDeleteShader(fragment);
    
        }
        // Uses the current shader
        void Use()
        {
            glUseProgram(this->Program);
        }
    };
    
    #endif

    最后附上,运行图片

  • 相关阅读:
    前端技术学习路线及技术汇总
    周末学习笔记——B/S和C/S的介绍
    前端个人笔记----------vue.js
    js中闭包来实现bind函数的一段代码的分析
    零碎总结
    最近要做的事
    递归中的返回
    近期写js库中遇到的一个判别的问题
    js中函数的写法
    关于异步回调的一段代码及相关总结
  • 原文地址:https://www.cnblogs.com/nazhizq/p/6582375.html
Copyright © 2020-2023  润新知