OpenGl第二章着色器与更多属性以及创建shader类来管理着色器

#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include<iostream>
using namespace std;
void processInput(GLFWwindow* window)
{
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);
    //这里我们检查用户是否按下了返回键(Esc)
}


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开始! 
    0, 1, 3, // 第一个三角形
    1, 2, 3  // 第二个三角形
};

const char* vertexShaderSource =
"#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"// 位置变量的属性位置值为0
"out vec4 vertexColor;\n"// 为片段着色器指定一个颜色输出

"void main()\n"
"{\n"
"   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"   vertexColor = vec4(0.5, 0.0, 0.0, 1.0); \n"// 把输出变量设置为暗红色
"}\0";

const char* fragmentShaderSource =
"#version 330 core\n"
"out vec4 FragColor;\n"

"uniform vec4 ourColor;\n" //使用uniform关键字创建创建一个全局变量  Uniform是一种从CPU中的应用向GPU中的着色器发送数据的方式
"void main()\n"
"{\n"
"    FragColor = ourColor;\n"//把输出的颜色设为 uniform变量的颜色
"}\n";

//const char* fragmentShaderSource =
//"#version 330 core\n"
//"out vec4 FragColor;\n"
//"in  vec4 vertexColor;\n" // 从顶点着色器传来的输入变量(名称相同、类型相同)
//"void main()\n"
//"{\n"
//"    FragColor = vertexColor;\n"
//"}\n";


int main(void)
{
    //必须先初始化该库,然后才能使用大多数GLFW函数。成功初始化后,GLFW_TRUE将返回。如果发生错误,GLFW_FALSE则返回。
    if (!glfwInit())
        return -1;

    //创建窗口(OpenGL上下文似乎也一并创建了)
    GLFWwindow* window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
    //glfwCreateWindow函数需要窗口的宽和高作为它的前两个参数。第三个参数表示这个窗口的名称(标题

    if (!window)
    {
        glfwTerminate();
        return -1;
    }

    /* Make the window's context current */
    glfwMakeContextCurrent(window);

    //使用GLAD来加载OpenGL的函数地址 GLAD是用来管理OpenGL的函数指针的,所以在调用任何OpenGL的函数之前我们需要初始化GLAD。
    //我们给GLAD传入了用来加载系统相关的OpenGL函数指针地址的函数。GLFW给我们的是glfwGetProcAddress,它根据我们编译的系统定义了正确的函数。
    gladLoadGL();
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }
    unsigned int vertexShader;//创建一个对象vertexShader 以ID来索引所以使用 unsigned int型
    vertexShader = glCreateShader(GL_VERTEX_SHADER);//glCreateShader来创建shader 以参数形式告诉函数GL_VERTEX_SHADER 顶点做色器
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);//下一步我们把这个着色器源码附加到着色器对象上,然后编译它:
    glCompileShader(vertexShader);
    /*
    glShaderSource函数把要编译的着色器对象作为第一个参数。第二参数指定了传递的源码字符串数量,
    这里只有一个。第三个参数是顶点着色器真正的源码,第四个参数我们先设置为NULL。
    */
    unsigned int fragmentShader;
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
    glCompileShader(fragmentShader);
    /*
   这个片段着色器和定点着色器一样
   */


   //将源码编译之后需要把两个源码链接到一个程序里面
    unsigned int shaderProgram;
    shaderProgram = glCreateProgram();//使用这个glCreateProgram创建一个程序 返回ID的索引
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader); //把两个源码附加到程序上
    glLinkProgram(shaderProgram);

    glDeleteShader(vertexShader); //调用完成之后删除对象释放内存
    glDeleteShader(fragmentShader);


    /*
    VBO顶点缓冲对象 作用为管理内存 用来管理在GPU上创建内存用于储存我们的顶点数据的内存
    定义一个VBO变量  把变量传入glGenBuffers缓冲生成函数里面产生一个缓冲和一个ID
    然后把这个缓冲对象用来管理GL_ARRAY_BUFFER
    */

    //如果要绘制两个三角形就需要使用索引缓存对象来告诉GPU使用哪些顶点
    unsigned int VAO, VBO;
    unsigned int EBO;
    glGenBuffers(1, &EBO);//glGenBuffers创建索引对象
    glGenVertexArrays(1, &VAO);//glGenVertexArrays来创建顶点数组
    glGenBuffers(1, &VBO);//glGenBuffers来创建缓存

    glBindVertexArray(VAO);//为下面的属性绑定VAO

    glBindBuffer(GL_ARRAY_BUFFER, VBO); //OpenGL有很多缓冲对象类型,顶点缓冲对象的缓冲类型是GL_ARRAY_BUFFER。
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);//绑定顶点并把顶点发送给GPU 第三个参数就是我们希望发送的实际数据。

    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);//GPU有了顶点之后使用这个函数来链接顶点属性glVertexAttribPointer函数告诉OpenGL该如何解析顶点数据
    glEnableVertexAttribArray(0);

    glBindBuffer(GL_ARRAY_BUFFER, 0);//解绑V
    glBindVertexArray(0);//使用完成之后解绑就行了为下面的属性绑定VAO


    //循环直到用户关闭窗口 渲染循环(Render Loop),它能在我们让GLFW退出前一直保持运行
    while (!glfwWindowShouldClose(window))
    {
        processInput(window);//使用按键

        //清理屏幕所用的颜色:
        glClearColor(0.4f, 0.5f, 0.6f, 1.0f);

        //清理屏幕  它接受一个缓冲位(Buffer Bit)来指定要清空的缓冲,
        //可能的缓冲位有GL_COLOR_BUFFER_BIT,GL_DEPTH_BUFFER_BIT和GL_STENCIL_BUFFER_BIT。由于现在我们只关心颜色值,所以我们只清空颜色缓冲。
        glClear(GL_COLOR_BUFFER_BIT);

        // glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);//使用glPolygonMode设置绘制模式这里是绘制线框
        glUseProgram(shaderProgram);//使用这个程序

        // 更新uniform颜色
        float timeValue = glfwGetTime(); //首先我们通过glfwGetTime()获取运行的秒数。
        float greenValue = sin(timeValue) / 2.0f + 0.5f;//然后我们使用sin函数让颜色在0.0到1.0之间改变,最后将结果储存到greenValue里。
        int vertexColorLocation = glGetUniformLocation(shaderProgram, "ourColor");//查询函数提供着色器程序和uniform的名字(这是我们希望获得的位置值的来源)如果glGetUniformLocation返回-1就代表没有找到这个位置值。
        glUniform4f(vertexColorLocation, 0.0f, greenValue, 0.0f, 0.5f);//第一个参数Location 后面依次是RGB颜色 RED GREEN BLUE 

        //绘制三角形
        glBindVertexArray(VAO);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
        //glDrawArrays(GL_TRIANGLES, 0, 3);

        //交换前后缓冲
        glfwSwapBuffers(window);

        //轮询并处理事件
        glfwPollEvents();
    }
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteProgram(shaderProgram);



    //使用GLFW完成操作后,通常是在应用程序退出之前,需要终止GLFW 释放/删除之前的分配的所有资源
    glfwTerminate();

    return 0;
}


最后效果随时间变换而变化
在这里插入图片描述
在这里插入图片描述

更多属性


//多属性的使用
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include<iostream>
using namespace std;

void processInput(GLFWwindow* window)
{
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);
    //这里我们检查用户是否按下了返回键(Esc)
}


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    // 顶部
};

//根据索引直来绘制图形
unsigned int indices[] = { // 注意索引从0开始! 
    0, 1, 3, // 第一个三角形
    1, 2, 3  // 第二个三角形
};

const char* vertexShaderSource =
"#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"// 把输出变量设置为暗红色
"}\0";

const char* fragmentShaderSource =
"#version 330 core\n"
"out vec4 FragColor;\n"
"in  vec3 ourColor;\n"

"void main()\n"
"{\n"
"    FragColor = vec4(ourColor,1.0);\n"//把输出的颜色设为 uniform变量的颜色
"}\n";

int main(void)
{
    //必须先初始化该库,然后才能使用大多数GLFW函数。成功初始化后,GLFW_TRUE将返回。如果发生错误,GLFW_FALSE则返回。
    if (!glfwInit())
        return -1;

    //创建窗口(OpenGL上下文似乎也一并创建了)
    GLFWwindow* window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
    //glfwCreateWindow函数需要窗口的宽和高作为它的前两个参数。第三个参数表示这个窗口的名称(标题

    if (!window)
    {
        glfwTerminate();
        return -1;
    }

    /* Make the window's context current */
    glfwMakeContextCurrent(window);

    //使用GLAD来加载OpenGL的函数地址 GLAD是用来管理OpenGL的函数指针的,所以在调用任何OpenGL的函数之前我们需要初始化GLAD。
    //我们给GLAD传入了用来加载系统相关的OpenGL函数指针地址的函数。GLFW给我们的是glfwGetProcAddress,它根据我们编译的系统定义了正确的函数。
    gladLoadGL();
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }
    unsigned int vertexShader;//创建一个对象vertexShader 以ID来索引所以使用 unsigned int型
    vertexShader = glCreateShader(GL_VERTEX_SHADER);//glCreateShader来创建shader 以参数形式告诉函数GL_VERTEX_SHADER 顶点做色器
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);//下一步我们把这个着色器源码附加到着色器对象上,然后编译它:
    glCompileShader(vertexShader);
    /*
    glShaderSource函数把要编译的着色器对象作为第一个参数。第二参数指定了传递的源码字符串数量,
    这里只有一个。第三个参数是顶点着色器真正的源码,第四个参数我们先设置为NULL。
    */
    unsigned int fragmentShader;
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
    glCompileShader(fragmentShader);
    /*
   这个片段着色器和定点着色器一样
   */


   //将源码编译之后需要把两个源码链接到一个程序里面
    unsigned int shaderProgram;
    shaderProgram = glCreateProgram();//使用这个glCreateProgram创建一个程序 返回ID的索引
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader); //把两个源码附加到程序上
    glLinkProgram(shaderProgram);

    glDeleteShader(vertexShader); //调用完成之后删除对象释放内存
    glDeleteShader(fragmentShader);


    /*
    VBO顶点缓冲对象 作用为管理内存 用来管理在GPU上创建内存用于储存我们的顶点数据的内存
    定义一个VBO变量  把变量传入glGenBuffers缓冲生成函数里面产生一个缓冲和一个ID
    然后把这个缓冲对象用来管理GL_ARRAY_BUFFER
    */

    //如果要绘制两个三角形就需要使用索引缓存对象来告诉GPU使用哪些顶点
    unsigned int VAO, VBO;
    unsigned int EBO;
    glGenBuffers(1, &EBO);//glGenBuffers创建索引对象
    glGenVertexArrays(1, &VAO);//glGenVertexArrays来创建顶点数组
    glGenBuffers(1, &VBO);//glGenBuffers来创建缓存

    glBindVertexArray(VAO);//为下面的属性绑定VAO

    glBindBuffer(GL_ARRAY_BUFFER, VBO); //OpenGL有很多缓冲对象类型,顶点缓冲对象的缓冲类型是GL_ARRAY_BUFFER。
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);//绑定顶点并把顶点发送给GPU 第三个参数就是我们希望发送的实际数据。

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);//绑定EBO
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);//如何使用索引

    //这里配置的是属性位置为0的顶点属性
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6* sizeof(float), (void*)0);//GPU有了顶点之后使用这个函数来链接顶点属性glVertexAttribPointer函数告诉OpenGL该如何解析顶点数据
    glEnableVertexAttribArray(0);

    //这里配置的是属性位置为1的顶点属性
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3*sizeof(float)));
    glEnableVertexAttribArray(1);

    /*
    * 步长:
    由于我们现在有了两个顶点属性,我们不得不重新计算步长值。
    为获得数据队列中下一个属性值(比如位置向量的下个x分量)我们必须向右移动6个float,其中3个是位置值,另外3个是颜色值。
    这使我们的步长值为6乘以float的字节数(=24字节)。

    偏移量:
    同样,这次我们必须指定一个偏移量。对于每个顶点来说,位置顶点属性在前,所以它的偏移量是0。
    颜色属性紧随位置数据之后,所以偏移量就是3 * sizeof(float),用字节来计算就是12字节。
    */

    glBindBuffer(GL_ARRAY_BUFFER, 0);//解绑V
    glBindVertexArray(0);//使用完成之后解绑就行了为下面的属性绑定VAO


    //循环直到用户关闭窗口 渲染循环(Render Loop),它能在我们让GLFW退出前一直保持运行
    while (!glfwWindowShouldClose(window))
    {
        processInput(window);//使用按键

        //清理屏幕所用的颜色:
        glClearColor(0.4f, 0.5f, 0.6f, 1.0f);

        //清理屏幕  它接受一个缓冲位(Buffer Bit)来指定要清空的缓冲,
        //可能的缓冲位有GL_COLOR_BUFFER_BIT,GL_DEPTH_BUFFER_BIT和GL_STENCIL_BUFFER_BIT。由于现在我们只关心颜色值,所以我们只清空颜色缓冲。
        glClear(GL_COLOR_BUFFER_BIT);

        // glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);//使用glPolygonMode设置绘制模式这里是绘制线框
        glUseProgram(shaderProgram);//使用这个程序

        // 更新uniform颜色
        float timeValue = glfwGetTime(); //首先我们通过glfwGetTime()获取运行的秒数。
        float greenValue = sin(timeValue) / 2.0f + 0.5f;//然后我们使用sin函数让颜色在0.0到1.0之间改变,最后将结果储存到greenValue里。
        int vertexColorLocation = glGetUniformLocation(shaderProgram, "ourColor");//查询函数提供着色器程序和uniform的名字(这是我们希望获得的位置值的来源)如果glGetUniformLocation返回-1就代表没有找到这个位置值。
        glUniform4f(vertexColorLocation, 0.0f, greenValue, 0.0f, 0.5f);//第一个参数Location 后面依次是RGB颜色 RED GREEN BLUE 

        //绘制三角形
        glBindVertexArray(VAO);
        //glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); 
        //第二个参数是我们打算绘制顶点的个数,这里填6,也就是说我们一共需要绘制6个顶点。

        glDrawArrays(GL_TRIANGLES, 0, 3);

        //交换前后缓冲
        glfwSwapBuffers(window);

        //轮询并处理事件
        glfwPollEvents();
    }
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteProgram(shaderProgram);



    //使用GLFW完成操作后,通常是在应用程序退出之前,需要终止GLFW 释放/删除之前的分配的所有资源
    glfwTerminate();

    return 0;
}


在这里插入图片描述

创建shader类来管理着色器

shader.h头文件


#include <glad/glad.h>
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>

class Shader
{
public:
    unsigned int ID;
    // constructor generates the shader on the fly
    // ------------------------------------------------------------------------
    Shader(const char* vertexPath, const char* fragmentPath)
    {
        // 1. retrieve the vertex/fragment source code from filePath
        std::string vertexCode;
        std::string fragmentCode;
        std::ifstream vShaderFile;
        std::ifstream fShaderFile;
        // ensure ifstream objects can throw exceptions:
        vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
        fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
        try
        {
            // 打开文件
            vShaderFile.open(vertexPath);
            fShaderFile.open(fragmentPath);
            std::stringstream vShaderStream, fShaderStream;
            // 读取文件的缓冲内容到数据流中
            vShaderStream << vShaderFile.rdbuf();
            fShaderStream << fShaderFile.rdbuf();
            // 关闭文件处理器
            vShaderFile.close();
            fShaderFile.close();
            // 转换数据流到string
            vertexCode = vShaderStream.str();
            fragmentCode = fShaderStream.str();
        }
        catch (std::ifstream::failure& e)
        {
            std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ: " << e.what() << std::endl;
        }
        const char* vShaderCode = vertexCode.c_str();
        const char* fShaderCode = fragmentCode.c_str();
        // 2. compile shaders
        unsigned int vertex, fragment;

        // vertex shader
        vertex = glCreateShader(GL_VERTEX_SHADER);
        glShaderSource(vertex, 1, &vShaderCode, NULL);
        glCompileShader(vertex);
        checkCompileErrors(vertex, "VERTEX");

        // fragment Shader
        fragment = glCreateShader(GL_FRAGMENT_SHADER);
        glShaderSource(fragment, 1, &fShaderCode, NULL);
        glCompileShader(fragment);
        checkCompileErrors(fragment, "FRAGMENT");
        // shader Program
        ID = glCreateProgram();
        glAttachShader(ID, vertex);
        glAttachShader(ID, fragment);
        glLinkProgram(ID);
        checkCompileErrors(ID, "PROGRAM");
        // delete the shaders as they're linked into our program now and no longer necessary
        glDeleteShader(vertex);
        glDeleteShader(fragment);
    }
    // activate the shader
    // ------------------------------------------------------------------------
    void use()
    {
        glUseProgram(ID);
    }
    // utility uniform functions
    // ------------------------------------------------------------------------
    void setBool(const std::string& name, bool value) const
    {
        glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value);
    }
    // ------------------------------------------------------------------------
    void setInt(const std::string& name, int value) const
    {
        glUniform1i(glGetUniformLocation(ID, name.c_str()), value);
    }
    // ------------------------------------------------------------------------
    void setFloat(const std::string& name, float value) const
    {
        glUniform1f(glGetUniformLocation(ID, name.c_str()), value);
    }

private:
    // utility function for checking shader compilation/linking errors.
    // ------------------------------------------------------------------------
    void checkCompileErrors(unsigned int shader, std::string type)
    {
        int success;
        char infoLog[1024];
        if (type != "PROGRAM")
        {
            glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
            if (!success)
            {
                glGetShaderInfoLog(shader, 1024, NULL, infoLog);
                std::cout << "ERROR::SHADER_COMPILATION_ERROR of type: " << type << "\n" << infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
            }
        }
        else
        {
            glGetProgramiv(shader, GL_LINK_STATUS, &success);
            if (!success)
            {
                glGetProgramInfoLog(shader, 1024, NULL, infoLog);
                std::cout << "ERROR::PROGRAM_LINKING_ERROR of type: " << type << "\n" << infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
            }
        }
    }
};

shader.cpp实现

#include "Shader.h"
#include <GLFW/glfw3.h>
float 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 
};

void processInput(GLFWwindow* window)
{
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);
    //这里我们检查用户是否按下了返回键(Esc)
}
int main(void)
{

    //必须先初始化该库,然后才能使用大多数GLFW函数。成功初始化后,GLFW_TRUE将返回。如果发生错误,GLFW_FALSE则返回。
    if (!glfwInit())
        return -1;

    //创建窗口(OpenGL上下文似乎也一并创建了)
    GLFWwindow* window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
    //glfwCreateWindow函数需要窗口的宽和高作为它的前两个参数。第三个参数表示这个窗口的名称(标题

    if (!window)
    {
        glfwTerminate();
        return -1;
    }

    /* Make the window's context current */
    glfwMakeContextCurrent(window);

    //使用GLAD来加载OpenGL的函数地址 GLAD是用来管理OpenGL的函数指针的,所以在调用任何OpenGL的函数之前我们需要初始化GLAD。
    //我们给GLAD传入了用来加载系统相关的OpenGL函数指针地址的函数。GLFW给我们的是glfwGetProcAddress,它根据我们编译的系统定义了正确的函数。
    gladLoadGL();
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }

    Shader ourShader("shader.vs", "shader.fs");
   


    //如果要绘制两个三角形就需要使用索引缓存对象来告诉GPU使用哪些顶点
    unsigned int VAO, VBO;
    unsigned int EBO;
    glGenBuffers(1, &EBO);//glGenBuffers创建索引对象

    glGenVertexArrays(1, &VAO);//glGenVertexArrays来创建顶点数组
    glGenBuffers(1, &VBO);//glGenBuffers来创建缓存

    glBindVertexArray(VAO);//为下面的属性绑定VAO

    glBindBuffer(GL_ARRAY_BUFFER, VBO); //OpenGL有很多缓冲对象类型,顶点缓冲对象的缓冲类型是GL_ARRAY_BUFFER。
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);//绑定顶点并把顶点发送给GPU 第三个参数就是我们希望发送的实际数据。
    
   // 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, 6 * sizeof(float), (void*)0);//GPU有了顶点之后使用这个函数来链接顶点属性glVertexAttribPointer函数告诉OpenGL该如何解析顶点数据
    glEnableVertexAttribArray(0);

    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3* sizeof(float)));//GPU有了顶点之后使用这个函数来链接顶点属性glVertexAttribPointer函数告诉OpenGL该如何解析顶点数据
    glEnableVertexAttribArray(1);
   
    glBindBuffer(GL_ARRAY_BUFFER, 0);//解绑V
    glBindVertexArray(0);//使用完成之后解绑就行了为下面的属性绑定VAO
    
  
    //循环直到用户关闭窗口 渲染循环(Render Loop),它能在我们让GLFW退出前一直保持运行
    while (!glfwWindowShouldClose(window))
    {
        processInput(window);//使用按键

        //清理屏幕所用的颜色:
        glClearColor(0.4f, 0.5f, 0.6f, 1.0f);

        //清理屏幕  它接受一个缓冲位(Buffer Bit)来指定要清空的缓冲,
        //可能的缓冲位有GL_COLOR_BUFFER_BIT,GL_DEPTH_BUFFER_BIT和GL_STENCIL_BUFFER_BIT。由于现在我们只关心颜色值,所以我们只清空颜色缓冲。
        glClear(GL_COLOR_BUFFER_BIT);

       // glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);//使用glPolygonMode设置绘制模式这里是绘制线框
        ourShader.use();//使用这个程序
        glBindVertexArray(VAO);
        //glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
        glDrawArrays(GL_TRIANGLES, 0, 3);

        //交换前后缓冲
        glfwSwapBuffers(window);

        //轮询并处理事件
        glfwPollEvents();
    }
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);



    //使用GLFW完成操作后,通常是在应用程序退出之前,需要终止GLFW 释放/删除之前的分配的所有资源
    glfwTerminate();
    
    return 0;
}

把着色器代码放到资源文件下面
在这里插入图片描述

//片段着色器
#version 330 core
out vec4 fragColor;
in  vec3 ourColor;
void main()
{
  fragColor = vec4(ourColor,1.0);
}
//顶点着色器
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;

out vec3 ourColor;

void main()
{
    gl_Position = vec4(aPos, 1.0);
    ourColor = aColor;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值