实验2.1——彩色三角形的显示

序 

查这段代码的时候:

无意中看到了一个这个链接:

(31条消息) 现代OpenGL学习笔记三:深入理解着色器_不想不努力的菜菜的博客-CSDN博客

里面讲了如何绘制一个彩色的三角形,还演示了index=0,1两种情况下,VBO与shader怎么呼应的,绘制有颜色的图形,很常用,值得学习。

链接的学习

这部分内容,来自上面那个链接。

float vertices[] = {
    // 位置              // 颜色
     0.5f, -0.5f, 0.0f,  1.0f, 0.0f, 0.0f,   // 右下
    -0.5f, -0.5f, 0.0f,  0.0f, 1.0f, 0.0f,   // 左下
     0.0f,  0.5f, 0.0f,  0.0f, 0.0f, 1.0f    // 顶部
};
#version 330 core
layout (location = 0) in vec3 aPos;   // 位置变量的属性位置值为 0 
layout (location = 1) in vec3 aColor; // 颜色变量的属性位置值为 1
 
out vec3 ourColor; // 向片段着色器输出一个颜色
 
void main()
{
    gl_Position = vec4(aPos, 1.0);
    ourColor = aColor; // 将ourColor设置为我们从顶点数据那里得到的输入颜色
}

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

 图画的挺漂亮的:

// 位置属性
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// 颜色属性
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3* sizeof(float)));
glEnableVertexAttribArray(1);

明白了,去尝试自己写吧。 

尝试

作为一个小白,报错是常态,所以,不要有心理负担。

之前做到了这样:

第一次运行,是这样:

 

 改,在这一行里,少了个vec3,少了个;

 

坏消息是依旧报错,好消息是错少了

 这个const float,和这个有关系吗?

 实测,没关系……

经过重写对比,发现少了个“,”

这可能不是调试代码,这是比谁的眼更敏感……对我这种小白来说,太难搞了。。

正常了,这个就已经开始有点实用价值了

能正常运行出结果的完整代码

/***
 * 例程  绘制三角形 (MAKE后运行时可删除ALL_BUILD,也可以将Task-triangle设为默认启动工程)
 * 步骤:
 * 1-初始化:   GLFW窗口,GLAD。
 * 2-数据处理: 给定顶点数据,生成并绑定VAO&VBO(准备在GPU中进行处理),设置顶点属性指针(本质上就是告诉OpenGL如何处理数据)。
 * 3-着色器:   给出顶点和片段着色器,然后链接为着色器程序,渲染时使用着色器程序。
 * 4-渲染:     清空缓冲,绑定纹理,使用着色器程序,绘制三角形,交换缓冲区检查触发事件后释放资源
 */

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

 // 三角形的顶点数据
//const float triangle[] = {
//    //     ---- 位置 ----    
//         -0.5f, -0.5f, 0.0f,   // 左下
//          0.5f, -0.5f, 0.0f,   // 右下
//          0.0f,  0.5f, 0.0f    // 正上
//};
//
//const float triangle2[] = {
//    //     ---- 位置 ----    
//         0.6f, -0.5f, 0.0f,   // 左下
//          0.8f, -0.5f, 0.0f,   // 右下
//          0.7f,  0.5f, 0.0f    // 正上
//};

const float triangle[] = {
    // 位置              // 颜色
     0.5f, -0.5f, 0.0f,  1.0f, 0.0f, 0.0f,   // 右下
    -0.5f, -0.5f, 0.0f,  0.0f, 1.0f, 0.0f,   // 左下
     0.0f,  0.5f, 0.0f,  0.0f, 0.0f, 1.0f    // 顶部
};

const float triangle2[] = {
    // 位置              // 颜色
     0.6f, -0.5f, 0.0f,  1.0f, 0.0f, 0.0f,   // 右下
    0.8f, -0.5f, 0.0f,  0.0f, 1.0f, 0.0f,   // 左下
     0.7f,  0.5f, 0.0f,  0.0f, 0.0f, 1.0f    // 顶部
};

// 屏幕宽,高
int screen_width = 1280;
int screen_height = 720;

int main() {
    // 第一部分,初始化GLFW和GLAD,分为4个步骤进行/

    // 初始化GLFW
    glfwInit();                                                     // 初始化GLFW
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);                  // OpenGL版本为3.3,主次版本号均设为3
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);  // 使用核心模式(无需向后兼容性)
    //glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);            // 如果使用的是Mac OS X系统,需加上这行
    glfwWindowHint(GLFW_RESIZABLE, false);						    // 不可改变窗口大小

    // 创建窗口(宽、高、窗口名称)
    auto window = glfwCreateWindow(screen_width, screen_height, "Triangle", nullptr, nullptr);
    if (window == nullptr) {                                        // 如果窗口创建失败,输出Failed to Create OpenGL Context
        std::cout << "Failed to Create OpenGL Context" << std::endl;
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);                                 // 将窗口的上下文设置为当前线程的主上下文

    // 初始化GLAD,加载OpenGL函数指针地址的函数
    // 在调用任何OpenGL函数之前
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }

    // 指定当前视口尺寸(前两个参数为左下角位置,后两个参数是渲染窗口宽、高)
    glViewport(0, 0, screen_width, screen_height);



    // 第二部分,数据处理,通过VAO,VBO,把顶点数据发送到显卡GPU上,并设置属性指针,告诉GPU如何解释这些数据/

    // 生成并绑定VAO和VBO
    GLuint vertex_array_object; // == VAO   核心模式要求必须使用VAO
    glGenVertexArrays(1, &vertex_array_object);//先生成
    glBindVertexArray(vertex_array_object);//再绑定

    GLuint vertex_buffer_object[2]; // == VBO
    glGenBuffers(2, &vertex_buffer_object[0]);//先生成,相当于C里声明的指针

    glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_object[0]);//绑定, 相当于声明指针指向的变量类型,同时设置一下状态机的状态(火车轨道变轨,变完了后面的车都得按变了的轨道走)
    glBufferData(GL_ARRAY_BUFFER, sizeof(triangle), triangle, GL_STATIC_DRAW);    // 将顶点数据绑定至当前默认的缓冲中
    //glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);    // 设置顶点属性指针——告知OpenGL,如何解释这些数据
    //glEnableVertexAttribArray(0);

    glBindBuffer(GL_ARRAY_BUFFER, 0);//解绑

    glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_object[1]);//再绑定
    glBufferData(GL_ARRAY_BUFFER, sizeof(triangle2), triangle2, GL_STATIC_DRAW);    // 将顶点数据绑定至当前默认的缓冲中,可能是传数据到GPU吧
    //glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);    // 设置顶点属性指针——告知OpenGL,如何解释这些数据
    //glEnableVertexAttribArray(0);

    glBindBuffer(GL_ARRAY_BUFFER, 0);//再绑定

    // 解绑VAO和VBO    为了代码更规范
    glBindVertexArray(0);


    // 第三部分,着色器,用来处理GPU里的数据//

    // 顶点着色器和片段着色器源码【GLSL】
    const char* vertex_shader_source =
        "#version 330 core\n"
        "layout (location = 0) in vec3 aPos;\n"           // 位置变量的属性位置值为0
        "layout (location = 1) in vec3 aColor; \n "          颜色变量的属性位置值为 1
        "out vec3 ourColor; \n"// 向片段着色器输出一个颜色
        "void main()\n"
        "{\n"
        "gl_Position = vec4(aPos, 1.0);\n" //内建变量
        "ourColor=aColor;\n"
        "}\n\0";
    const char* fragment_shader_source =
        "#version 330 core\n"
        "in vec3 ourColor;\n"
        "out vec4 FragColor;\n"                           // 输出的颜色向量
        "void main()\n"
        "{\n"
        "FragColor = vec4(ourColor, 1.0f);\n"
        "}\n\0";

    // 生成并编译着色器
        // 顶点着色器
    int vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertex_shader, 1, &vertex_shader_source, NULL);
    glCompileShader(vertex_shader);
    int success;
    char info_log[512];
    // 检查着色器是否成功编译,如果编译失败,打印错误信息
    glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(vertex_shader, 512, NULL, info_log);
        std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << info_log << std::endl;
    }
    // 片段着色器
    int fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragment_shader, 1, &fragment_shader_source, NULL);
    glCompileShader(fragment_shader);
    // 检查着色器是否成功编译,如果编译失败,打印错误信息
    glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(fragment_shader, 512, NULL, info_log);
        std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << info_log << std::endl;
    }

    // 链接顶点和片段着色器至一个着色器程序
    int shader_program = glCreateProgram();
    glAttachShader(shader_program, vertex_shader);
    glAttachShader(shader_program, fragment_shader);
    glLinkProgram(shader_program);
    // 检查着色器是否成功链接,如果链接失败,打印错误信息
    glGetProgramiv(shader_program, GL_LINK_STATUS, &success);
    if (!success) {
        glGetProgramInfoLog(shader_program, 512, NULL, info_log);
        std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << info_log << std::endl;
    }

    // 删除着色器    需要的着色器程序已经拿到了,这个没用了,就删除了
    glDeleteShader(vertex_shader);
    glDeleteShader(fragment_shader);

    // 线框模式
    //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

    // 第4部分,渲染//

    // 渲染循环
    while (!glfwWindowShouldClose(window)) {

        // 清空颜色缓冲
        glClearColor(0.0f, 0.34f, 0.57f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);
        // 使用着色器程序  【之前链接好的那个】
        glUseProgram(shader_program);

        // 绘制三角形
        glBindVertexArray(vertex_array_object);                                    // 绑定VAO

        glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_object[0]);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);    // 设置指针位置,以便后续从此处读取数据进行渲染
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3*sizeof(float)));    // 设置指针位置,以便后续从此处读取数据进行渲染
        glEnableVertexAttribArray(1);
        glDrawArrays(GL_TRIANGLES, 0, 3);                                          // 绘制三角形

        glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_object[1]);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);    // 【渲染时告诉OpenGL如何解释这些数据】
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));    // 【渲染时告诉OpenGL如何解释这些数据】
        glEnableVertexAttribArray(1);
        glDrawArrays(GL_TRIANGLES, 0, 3);                                          // 绘制三角形


        glBindVertexArray(0);                                                      // 解除绑定

        // 交换缓冲并且检查是否有触发事件(比如键盘输入、鼠标移动等)
        glfwSwapBuffers(window);//双缓冲
        glfwPollEvents();
    }

    // 第五部分,善后工作

    // 删除VAO和VBO
    glDeleteVertexArrays(1, &vertex_array_object);
    glDeleteBuffers(1, &vertex_buffer_object[0]);

    // 清理所有的资源并正确退出程序
    glfwTerminate();
    return 0;
}

后记

那末,如果这个顶点数据,是可变的,应该咋写?

和STATIC_DRAW有关吗?

有关,但是没有想象里的关联那么大

 引用:

(31条消息) STATIC_DRAW, DYNAMIC_DRAW, STREAM_DRAW的区别_me_badman的博客-CSDN博客

 

以后再说吧,暂时用不到。

小白而已,不能一次要求的太多…… 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值