Learn_OpenGL_002_你好,长方形

本代码中为中文版注释,基本每行代码都会注释其功能,这里注释的功能为学习记录的过程,而非正常程序所需要的必要的精简的注释。

#include <glad/glad.h>
#include <GLFW/glfw3.h>

#include <iostream>

// 顶点数组对象:Vertex Array Object,VAO
// 顶点缓冲对象:Vertex Buffer Object,VBO
// 索引缓冲对象:Element Buffer Object, EBO; 或者Index Buffer Object, IBO

// Pipeline管线化: 顶点着色器-> 图元装配-> 几何着色器 -> (先裁切)光栅化-> 片段着色器 -> 测试混合 ,三个着色器是可定义的,其他OpenGL处理
// 通常只需要自定义的: 顶点,片段着色器.

// 顶点数据: 点的集合; 
// 一个顶点: 是3D坐标(3D位置和颜色值)的集合.

// 自适应窗口函数的声明
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
// 自定义输入控制函数的声明
void processInput(GLFWwindow *window);

// 顶点着色语言源代码.GLSL(OpenGL Shading Language)
// 输入一个3分量变量
const char *vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
"   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
// 片段着色器语言源代码,RGBA.
// 输出一个4分量变量
const char *fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
"   FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";

// 屏幕宽高
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;

int main()
{
    // 初始化GLFW窗口
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);  //主版本号
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);  //次版本号
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);  //核心模式
    // 创建窗口对象(宽,高,名,忽略,忽略)
    GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
    // 创建失败则提示,结束GLFW,返回-1.
    if (window == NULL)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }
    // 设置窗口线程的当前上下文
    glfwMakeContextCurrent(window);
    // 将可变窗口函数注册到GLFW
    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
    // GLAD 加载管理OpenGL的函数指针,初始化GLAD,将GLFW函数指针地址传给GLAD
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }

    // 建造,编译着色程序
    
    // 着色器创建: 类型为顶点着色器
    int vertexShader = glCreateShader(GL_VERTEX_SHADER);    // 创建着色器,并指定id到vertexShader
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); // 将源码传给着色器,(对象名,字符串数量,字符地址,NULL)
    glCompileShader(vertexShader);  // 编译着色器
    // 顶点着色编译检查
    int success;
    char infoLog[512];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if (!success)   //成功为0,取反为1,
    {
        glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
    }
    // 片段着色器
    int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
    glCompileShader(fragmentShader);
    // 片段着色器编译检查
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
    }
    // 链接着色器到一个着色器程序对象
    int shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);
    // 链接检查
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
    if (!success) {
        glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
    }
    // 着色器对象加入到程序对象之后, 直接使用程序对象,不再需要着色器对象,可以删除.
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    // 顶点数据,缓冲,属性的设置
    // 标准化设备坐标范围xyz坐标局限于(-1,1)中, 右手坐标, 
    // z值设为0,无深度.
    float vertices[] = {
        // 所需要的所有顶点集合
        0.5f,  0.5f, 0.0f,  // 右上
        0.5f, -0.5f, 0.0f,  // 右下
        -0.5f, -0.5f, 0.0f,  // 左下
        -0.5f,  0.5f, 0.0f   // 左上 
    };
    // 索引数据, 需要的点的组合
    unsigned int indices[] = {
        0, 1, 3,  // 第一个三角
        1, 2, 3   // 第二个三角
    };

    // VBO对象将顶点从内存接受并在显存中管理
    unsigned int VBO, VAO, EBO;
    glGenVertexArrays(1, &VAO); // 生成顶点数组对象VAO
    glGenBuffers(1, &VBO);  //  根据int类型的VBO这个ID生成一个VBO对象
    glGenBuffers(1, &EBO);
    // 绑定顶点数组对象VAO
    glBindVertexArray(VAO);
    // 绑定顶点缓冲对象VBO
    glBindBuffer(GL_ARRAY_BUFFER, VBO); //  绑定VBO到某个缓冲类型
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);  // 初始化缓存后,将数据拷贝,此步骤后, 数据被复制到在显存中
    // 绑定元素缓冲对象EBO
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); // 绑定EBO到某个缓冲类型
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
    // 顶点属性指针(位置值,几个分量值,类型,是否标准化,步长,偏移量)
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);   // 启动定点属性
    // 调用glVertexAttribPointer函数,注册VBO为定点属性的绑定VBO,之后就可以安全解除绑定.
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    // VAO处于活动状态下啊不要解绑EBO
    //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    // 你可以解绑VAO这样就不能改变VAO(这样的用法很少见),修改其他VAO需要glBindVertexArray,所以一般不解绑VAO,VBO,除非明确需求.
    glBindVertexArray(0);
    // 填充模式(默认)
    //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    // 线框模式(只绘制线)
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

    // 循环渲染,要求退出则为1,取反为0,循环终止.
    while (!glfwWindowShouldClose(window))
    {
        // 自定义的输入控制
        processInput(window);
        // 渲染背景,设置,清空
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);
        // 渲染三角形
        glUseProgram(shaderProgram);
        glBindVertexArray(VAO); //绑定VAO时自动保存EBO的绑定
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);    //顶点数,EBO偏移量.
        // 双缓冲,后台渲染完后一次性与前台交换,力求一次呈现.
        glfwSwapBuffers(window);
        // 触发事件
        glfwPollEvents();
    }
    // 释放资源
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteBuffers(1, &EBO);
    // 结束GLFW
    glfwTerminate();
    return 0;
}

// 自定义的输入控制
void processInput(GLFWwindow *window)
{
    // ESC键按下则窗口关闭
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);
}

// 可视界面随窗口变化
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
    // Viewport可视界面,左下角坐标,x,y,宽,高
    glViewport(0, 0, width, height);
}

转载于:https://www.cnblogs.com/FireCuckoo/p/7838304.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值