使用GLSL画一个随着时间颜色渐变的三角形

使用着色器画一个随着时间颜色渐变的三角形

效果:
使用GLSL画一个随着时间颜色渐变的三角形_第1张图片
使用GLSL画一个随着时间颜色渐变的三角形_第2张图片

代码:

#include 
#include 

#include 


//窗口大小变化回调
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
//键盘事件监听
void processInput(GLFWwindow* window);  


// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;

//顶点着色器
const char* vertexShaderSource = "#version 330 core\n"  //版本声明,同时明确表示我们会使用核心模式
"layout (location = 0) in vec3 aPos;\n" //in关键字设置输入变量  ,设定了输入变量的位置值为 0 ,创建一个vec3输入变量aPos
"out vec4 myColor;"
"void main()\n"
"{\n"
"   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"   //gl_Position的值为顶点着色器的输出
"   myColor = vec4(aPos.xyz,1.0);"
"}\0";

//片元着色器
const char* fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"     //out关键字设置输出变量
"in vec4 myColor;"
"uniform float ourColor;"
"void main()\n"
"{\n"
"   FragColor = vec4(myColor.x + ourColor,myColor.y + ourColor,myColor.z + ourColor,1.0);"
"}\n\0";

int main()
{
   
    glfwInit();  //初始化GLFW
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); //上下文的客户端API版本 主版本号
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); //上下文的客户端API版本 次版本号
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);  //设置OpenGL使用的模式为核心模式 CORE_PROFILE
    //glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); //MAC OS X系统配置生效设置

    
    //创建窗口对象
    GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
    if (window == NULL)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }

    glfwMakeContextCurrent(window); //通知GLFW将我们窗口的上下文设置为当前线程的主上下文

     //初始化GLAD
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }


    //注册 framebuffer_size_callback 这个函数,当窗口调整大小时调用 函数framebuffer_size_callback 
    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

   




    //创建顶点着色器
    int vertexShader = glCreateShader(GL_VERTEX_SHADER); 
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); //把这个着色器源码附加到着色器对象上
    glCompileShader(vertexShader); //编译着色器对象

    //检查顶点着色器是否编译成功
    int success;
    char infoLog[512];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
        std::cout << "错误:顶点着色器编译失败!>>> \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 << "错误:片元着色器编译失败!>>> \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);

    //三角形顶点数组
    float vertices[] = {
        -0.5f, -0.5f, 0.0f, // 点left  
         0.5f, -0.5f, 0.0f, // 点right 
         0.0f,  0.5f, 0.0f  // 点top   
    };

    unsigned int VBO, VAO;
    glGenVertexArrays(1, &VAO); //创建顶点数组对象 VAO  ,缓冲ID为1 ,&VAO代表指向VAO变量的指针
    glGenBuffers(1, &VBO);  //创建一个VBO对象 ,缓冲ID为1
    glBindVertexArray(VAO); // 想使用VAO,要做的只是使用glBindVertexArray绑定VAO


    //把新创建的缓冲绑定到GL_ARRAY_BUFFER目标上 ,因为顶点缓冲对象VBO的缓冲类型是GL_ARRAY_BUFFER
    glBindBuffer(GL_ARRAY_BUFFER, VBO);  
    //把之前定义的顶点数据复制到缓冲的内存中,第四个参数控制是否把数据放在显卡可以告诉写入的内存部分
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); 


    //告诉OpenGL该如何解析顶点数据(应用到逐个顶点属性上)
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    //以顶点属性位置值作为参数,启用顶点属性;
    glEnableVertexAttribArray(0); 

    // 注意,这是允许的,调用glVertexAttribPointer将VBO注册为顶点属性的绑定顶点缓冲区对象,这样我们就可以安全地解除绑定
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    // 您可以在以后解除VAO的绑定,这样其他的VAO调用就不会意外地修改这个VAO,但是这种情况很少发生。修改otherVAOs需要调用glBindVertexArray,
    //所以我们通常不会在没有直接必要的时候取消绑定VAOs(或VBOs)。
    glBindVertexArray(0);


    // 使用线框模式绘制图元
    //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

    //当用户没有关闭窗口时执行循环渲染
    while (!glfwWindowShouldClose(window))
    {
        //键盘事件监听
        processInput(window);

        //清空屏幕的颜色缓冲
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);


        float timeValue = glfwGetTime();
        float greenValue = (sin(timeValue) / 2.0f) + 0.5;
        /*std::cout << "greenValue的值为: "<
        int vertexColorLocation = glGetUniformLocation(shaderProgram, "ourColor");
        glUseProgram(shaderProgram);
        glUniform1f(vertexColorLocation,  greenValue);



        
        glUseProgram(shaderProgram); //激活着色器程序对象,之后每个着色器调用和渲染调用都会使用这个着色器程序对象
        glBindVertexArray(VAO);            // 绑定VAO
        glDrawArrays(GL_TRIANGLES, 0, 3);  //绘制,使用当前激活的着色器,之前定义的顶点属性配置,和VBO的顶点数据(通过VAO间接绑定)来绘制图元
        // glBindVertexArray(0); // no need to unbind it every time 

        
        glfwSwapBuffers(window); //交换颜色缓冲
        glfwPollEvents(); //检查有没有触发什么事件(比如键盘输入、鼠标移动等)、更新窗口状态,并调用对应的回调函数
    }

    

    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);

   
    glfwTerminate(); //释放或删除之前的分配的所有资源
    return 0;
}


void processInput(GLFWwindow* window)
{
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);
}

void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
    //设置OpenGL渲染窗口(视口)的尺寸大小
    glViewport(0, 0, width, height);
}

你可能感兴趣的:(OpenGL)