openGL学习<四>、着色器
1 // 2 // Created by sry on 2021/7/6. 3 // 4 #include <glad/glad.h> 5 #include <GLFW/glfw3.h> 6 #include<iostream> 7 #include<cmath> 8 using namespace std; 9 10 void framebuffer_size_callback(GLFWwindow* window, int width, int height) 11 { 12 glViewport(0, 0, width, height); // opengl_frame glfw_frame new_frame,知道为啥有这么多JB帧了吧 13 } 14 /* 15 * 16 * 这里我们检查用户是否按下了返回键(Esc)(如果没有按下,glfwGetKey将会返回GLFW_RELEASE。 17 * 如果用户的确按下了返回键,我们将通过glfwSetwindowShouldClose使用把WindowShouldClose属性设置为 true的方法关闭GLFW。 18 * 19 * */ 20 void processInput(GLFWwindow *window) 21 { 22 if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) 23 glfwSetWindowShouldClose(window, true); 24 } 25 26 // glsl 渲染语言,这和C++调用Matlab差不多 27 const char *vertexShaderSource = "#version 330 core\n" 28 "layout (location = 0) in vec3 aPos;\n" 29 "void main()\n" 30 "{\n" 31 " gl_Position = vec4(aPos, 1.0);\n" 32 "}\0"; 33 34 const char *fragmentShaderSource = "#version 330 core\n" 35 "out vec4 FragColor;\n" 36 "uniform vec4 ourColor;\n" 37 "void main()\n" 38 "{\n" 39 " FragColor = ourColor;\n" 40 "}\n\0"; 41 42 int main() 43 { 44 // <1>、初始化GLFW 45 glfwInit(); 46 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // opengl3.3 47 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 48 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 只用核心通用模块 49 50 // <2>、glfw窗口创建 51 GLFWwindow* window = glfwCreateWindow(800, 600, "shiruiyu", NULL, NULL); 52 if (window == NULL) 53 { 54 cout << "fuck" << endl; 55 glfwTerminate(); // Release 56 return -1; 57 } 58 glfwMakeContextCurrent(window); // 通知GLFW将我们窗口的上下文设置为当前线程的主上下文了。 59 /* 60 * 告诉OpenGL渲染窗口的尺寸大小 61 * OpenGL坐标范围只为-1到1,因此我们事实上将(-1到1)范围内的坐标映射到(0, 800)和(0, 600)。 62 * */ 63 // 对窗口注册一个回调函数(Callback Function),它会在每次窗口大小被调整的时候被调用 64 glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); 65 /* 66 * <3>、利用glad加载所有OpenGL函数地址 67 * GLAD是用来管理OpenGL的函数指针的,所以在调用任何OpenGL的函数之前我们需要初始化GLAD 68 * */ 69 if (!gladLoadGLLoader((GLADloadproc) glfwGetProcAddress)) 70 { 71 cout << "Failed to init GLAD" << endl; 72 return -1; 73 } 74 // <4>、构建、编译shader program 75 // 创建顶点渲染器,vertex shader 76 unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER); 77 glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); 78 glCompileShader(vertexShader); 79 // 验证渲染器是否正常 80 int success = 0; 81 char infoLog[512]; 82 glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success); 83 if (!success) 84 { 85 glGetShaderInfoLog(vertexShader, 512, NULL, infoLog); 86 std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl; 87 } 88 // 创建线段渲染器,fragment shader 89 unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); 90 glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL); 91 glCompileShader(fragmentShader); 92 // 验证渲染器是否正常 93 success = 0; 94 glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success); 95 if (!success) 96 { 97 glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog); 98 std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl; 99 } 100 // 链接渲染器,link shaders 101 unsigned int shaderProgram = glCreateProgram(); 102 glAttachShader(shaderProgram, vertexShader); 103 glAttachShader(shaderProgram, fragmentShader); 104 glLinkProgram(shaderProgram); 105 // 检测链接错误 106 success = 0; 107 glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success); 108 if (!success) 109 { 110 glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog); 111 std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl; 112 } 113 glDeleteShader(vertexShader); 114 glDeleteShader(fragmentShader); 115 116 // set up vertex data (and buffer(s)) and configure vertex attributes 117 // ------------------------------------------------------------------ 118 float vertices[] = { 119 -0.5f, -0.5f, 0.0f, // left 120 0.5f, -0.5f, 0.0f, // right 121 0.0f, 0.5f, 0.0f // top 122 }; 123 unsigned int VBO, VAO; // ??? 124 glGenVertexArrays(1, &VAO); 125 glGenBuffers(1, &VBO); 126 // bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s). 127 glBindVertexArray(VAO); 128 129 glBindBuffer(GL_ARRAY_BUFFER, VBO); 130 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); 131 132 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); 133 glEnableVertexAttribArray(0); 134 135 // note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind 136 glBindBuffer(GL_ARRAY_BUFFER, 0); 137 // You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other 138 // VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary. 139 glBindVertexArray(0); 140 141 // 循环渲染 142 while(!glfwWindowShouldClose(window)) // 检查一次GLFW是否被要求退出 143 { 144 // 输入 145 processInput(window); 146 147 // 渲染指令 148 // 清除颜色缓冲 149 glClearColor(0.2f, 0.3f, 0.3f, 1.0f); 150 glClear(GL_COLOR_BUFFER_BIT); 151 // 激活着色器 152 glUseProgram(shaderProgram); 153 154 // 更新uniform颜色 155 float timeValue = glfwGetTime(); 156 float greenValue = std::sin(timeValue)/2.0f + 0.5f; 157 int vertexColorLocation = glGetUniformLocation(shaderProgram, "ourColor"); 158 glUniform4f(vertexColorLocation, 0.0f, greenValue, 0.0f, 1.0f); 159 160 161 // 画第一个三角形 162 163 glBindVertexArray(VAO); 164 glDrawArrays(GL_TRIANGLES, 0, 3);// Primitive:GL_POINTS、GL_TRIANGLES、GL_LINE_STRIP 165 166 167 168 169 170 // 检查并调用事件,交换缓冲 171 glfwPollEvents(); // 检查有没有触发什么事件(比如键盘输入、鼠标移动等)、更新窗口状态,并调用对应的回调函数(可以通过回调方法手动设置)。 172 glfwSwapBuffers(window); // 函数会交换颜色缓冲(它是一个储存着GLFW窗口每一个像素颜色值的大缓冲),它在这一迭代中被用来绘制,并且将会作为输出显示在屏幕上。 173 174 } 175 176 glDeleteVertexArrays(1, &VAO); 177 glDeleteBuffers(1, &VBO); 178 glDeleteProgram(shaderProgram); 179 180 // release 181 glfwTerminate(); 182 183 return 0; 184 }
CV&DL