#include <iostream> // GLEW #define GLEW_STATIC #include <GL/glew.h> // GLFW #include <GLFW/glfw3.h> #pragma comment(lib,"opengl32.lib") #pragma comment(lib,"glu32.lib") using namespace std; // 窗口大小 const GLuint WIDTH = 800, HEIGHT = 600; // 着色器 GLSL const GLchar* vertexShaderSource = "#version 330 core\n" "uniform vec3 change;\n" "layout (location = 0) in vec3 position;\n" "layout (location = 1) in vec3 color;\n" "out vec3 ourColor;\n" "void main()\n" "{\n" "gl_Position = vec4(position, 1.0f);\n" "if(color.x > 0.0f) ourColor = change.xyz;\n" "if(color.y > 0.0f) ourColor = change.yzx;\n" "if(color.z > 0.0f) ourColor = change.zxy;\n" "}\0"; const GLchar* fragmentShaderSource = "#version 330 core\n" "in vec3 ourColor;\n" "out vec4 color;\n" "void main()\n" "{\n" "color = vec4(ourColor, 1.0f);\n" "}\n\0"; int main(void) { // 初始化 GLFW glfwInit(); // glfwWindowHint() // 配置 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); // Mac OS 使用 // glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // 创建一个窗口 GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "ColorChange", nullptr, nullptr); glfwMakeContextCurrent(window); // 初始化 GLEW glewExperimental = GL_TRUE; glewInit(); // 设置窗口大小 int width, height; glfwGetFramebufferSize(window, &width, &height); glViewport(0, 0, width, height); // 配置着色器 // 创建一个着色器对象(GL_VERTEX_SHADER:顶点着色器) GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); // 把着色器源码附加到着色器对象上,然后编译它 glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); glCompileShader(vertexShader); // 检测编译时错误,输出错误信息 GLint success; GLchar infoLog[512]; glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(vertexShader, 512, NULL, infoLog); std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl; } // 创建一个着色器对象(GL_FRAGMENT_SHADER:片段着色器) GLuint 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; } // 创建一个着色器程序对象 GLuint shaderProgram; shaderProgram = glCreateProgram(); // 链接着色器程序 glAttachShader(shaderProgram, vertexShader); glAttachShader(shaderProgram, fragmentShader); glLinkProgram(shaderProgram); // 激活对象 glUseProgram(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); // 输入顶点数据(这是一个平面的三角形,z 坐标表示深度) /*GLfloat vertices[] = { -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f, }; */ GLfloat 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 // 顶部 }; // 生成一个 VBO 对象 GLuint VBO; glGenBuffers(1, &VBO); // 把新创建的缓冲绑定到 GL_ARRAY_BUFFER 目标上 glBindBuffer(GL_ARRAY_BUFFER, VBO); // 把之前定义的顶点数据复制到缓冲的内存中(静态图形方式) // glBufferData() // 复制数据到当前绑定缓冲(缓冲类型,数据大小,数据,显存数据的管理方式) glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // 创建一个 VAO GLuint VAO; glGenVertexArrays(1, &VAO); // 把新创建的缓冲绑定到 GL_ARRAY_BUFFER 目标上 glBindBuffer(GL_ARRAY_BUFFER, VAO); glBindVertexArray(VAO); // glVertexAttribPointer() // 解析顶点数据(1.顶点属性[对应前面的 layout (location = 0)],2.顶点属性的大小[3分量向量], // 3.数据类型[浮点数],4.是否标准化为(-1,1)范围内,5.单位步长,6.从起始位置的偏移量) /*glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0); glEnableVertexAttribArray(0);*/ // 位置属性 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0); glEnableVertexAttribArray(0); // 颜色属性 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); glEnableVertexAttribArray(1); // 解绑 glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); // 创建游戏循环 while (!glfwWindowShouldClose(window)) { // 事件处理 glfwPollEvents(); // 指定背景色(深蓝色) glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); // 实时改变三角形的颜色 glUseProgram(shaderProgram); GLfloat timeValue = glfwGetTime(); float speedDown = 5; timeValue = timeValue / speedDown; GLint intValue = timeValue; GLfloat xValue = (timeValue - intValue)*3; GLint vertexColorLocation = glGetUniformLocation(shaderProgram, "change"); GLfloat redValue = xValue < 1.0f ? 1.0f - xValue : (xValue >= 2.0f ? xValue - 2.0f : 0.0f); GLfloat greenValue = xValue < 2.0f && xValue >= 1.0f ? 2.0f - xValue : (xValue < 1.0f ? xValue : 0.0f); GLfloat blueValue = xValue >= 2.0f ? 3.0f - xValue : (xValue < 2.0f && xValue >= 1.0f ? xValue - 1.0f : 0.0f); glUniform3f(vertexColorLocation, redValue, greenValue, blueValue); // 使用着色器程序, glDrawArrays():绘制图元函数 glUseProgram(shaderProgram); glBindVertexArray(VAO); glDrawArrays(GL_TRIANGLES, 0, 3); glBindVertexArray(0); // 交换缓冲 glfwSwapBuffers(window); } // 删除 VAO 和 VBO,释放空间 glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); // 释放 GLFW 内存 glfwTerminate(); return 0; }