qt opengl
着色器:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//#include <iostream> //#include "Display.h" // //int main() //{ // std::string title("LearnOpenGL"); // Display window(800,600, title); // // // 渲染循环 // while (!window.IsClosed()) { // window.Clear(0.2f, 0.3f, 0.3f, 1.0f); // window.Update(); // } // return 0; //} #include <glad/glad.h> #include <GLFW/glfw3.h> #include "Shader.h" #include <iostream> 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" "void main()\n" "{\n" " gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n" "}\0"; const char* fragmentShaderSource = "#version 330 core\n" "out vec4 FragColor;\n" "uniform vec4 ourColor;\n" "void main()\n" "{\n" " //FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n" " FragColor = ourColor;\n" "}\n\0"; int main() { // glfw: initialize and configure // ------------------------------ glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); #ifdef __APPLE__ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X #endif // glfw window creation // -------------------- 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); glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); // glad: load all OpenGL function pointers // --------------------------------------- if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { std::cout << "Failed to initialize GLAD" << std::endl; return -1; } #if 0 // build and compile our shader program // ------------------------------------ // vertex shader int vertexShader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); glCompileShader(vertexShader); // check for shader compile errors int success; char 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; } // fragment shader int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL); glCompileShader(fragmentShader); // check for shader compile errors glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog); std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl; } // link shaders int shaderProgram = glCreateProgram(); glAttachShader(shaderProgram, vertexShader); glAttachShader(shaderProgram, fragmentShader); glLinkProgram(shaderProgram); // check for linking errors 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); #endif Shader ourShader("3.3.shader.vs", "3.3.shader.fs"); // you can name your shader files however you like // set up vertex data (and buffer(s)) and configure vertex attributes // ------------------------------------------------------------------ float vertices[] = { // 位置 颜色 0.5f, -0.5f, 0.0f, 1.0f,0.0f,0.0f, -0.5f, -0.5f, 0.0f, 0.0f,0.1f,0.0f, 0.0f, 0.5f, 0.0f, 0.0f,0.0f,1.0f }; unsigned int VBO, VAO; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); // bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s). glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); 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); // 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 glBindBuffer(GL_ARRAY_BUFFER, 0); // You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other // VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary. glBindVertexArray(0); // uncomment this call to draw in wireframe polygons. //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // render loop // ----------- while (!glfwWindowShouldClose(window)) { // input // ----- processInput(window); // render // ------ glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); // 更新uniform颜色 //float timeValue = glfwGetTime(); //float greenValue = sin(timeValue) / 2.0f + 0.5f; //int vertexColorLocation = glGetUniformLocation(shaderProgram, "ourColor"); //glUniform4f(vertexColorLocation, 0.0f, greenValue, 0.0f, 1.0f); // draw our first triangle //glUseProgram(shaderProgram); ourShader.use(); glBindVertexArray(VAO); // seeing as we only have a single VAO there's no need to bind it every time, but we'll do so to keep things a bit more organized glDrawArrays(GL_TRIANGLES, 0, 3); // glBindVertexArray(0); // no need to unbind it every time // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.) // ------------------------------------------------------------------------------- glfwSwapBuffers(window); glfwPollEvents(); } // optional: de-allocate all resources once they've outlived their purpose: // ------------------------------------------------------------------------ glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); // glfw: terminate, clearing all previously allocated GLFW resources. // ------------------------------------------------------------------ glfwTerminate(); return 0; } // process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly // --------------------------------------------------------------------------------------------------------- void processInput(GLFWwindow* window) { if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, true); } // glfw: whenever the window size changed (by OS or user resize) this callback function executes // --------------------------------------------------------------------------------------------- void framebuffer_size_callback(GLFWwindow* window, int width, int height) { // make sure the viewport matches the new window dimensions; note that width and // height will be significantly larger than specified on retina displays. glViewport(0, 0, width, height); }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#ifndef SHADER_H #define 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 { // open files vShaderFile.open(vertexPath); fShaderFile.open(fragmentPath); std::stringstream vShaderStream, fShaderStream; // read file's buffer contents into streams vShaderStream << vShaderFile.rdbuf(); fShaderStream << fShaderFile.rdbuf(); // close file handlers vShaderFile.close(); fShaderFile.close(); // convert stream into string vertexCode = vShaderStream.str(); fragmentCode = fShaderStream.str(); } catch (std::ifstream::failure e) { std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << 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; } } } }; #endif
vertex
#version 330 core layout (location = 0) in vec3 aPos; layout (location = 1) in vec3 aColor; layout (location = 2) in vec3 aTexCoord; out vec3 ourColor; out vec2 TexCoord; void main() { gl_Position = vec4(aPos, 1.0); ourColor = aColor; TexCoord = aTexCoord; }
fragment
#version 330 core out vec4 FragColor; in vec3 ourColor; in vec2 TexCoord; uniform sampler2D ourTexture; void main() { //FragColor = vec4(ourColor, 1.0f); FragColor = texture(ourTexture,TexCoord); }
四边形
更多属性:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include "widget.h" 2 #include "ui_widget.h" 3 #include <QDebug> 4 #include <QTime> 5 #include <math.h> 6 #include <sys/time.h> 7 #include <QTimer> 8 //#include "shader.h" 9 10 //顶点着色器源码 11 const char *vertexShaderSource = "#version 330 core\n" 12 "layout (location = 0) in vec3 aPos;\n" 13 "layout (location = 1) in vec3 aColor;\n" 14 "out vec3 ourColor;\n" 15 "void main()\n" 16 "{\n" 17 " gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n" 18 " ourColor = aColor;\n" 19 "}\0"; 20 21 //片段着色器源码 22 const char *fragmentShaderSource = "#version 330 core\n" 23 "out vec4 FragColor;\n" 24 "in vec3 ourColor;\n" 25 "//uniform vec4 ourColor;\n" 26 "void main()\n" 27 "{\n" 28 " FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n" 29 " FragColor = vec4(ourColor,1.0f);\n" 30 "}\n\0"; 31 32 Widget::Widget(QWidget *parent) : 33 QOpenGLWidget(parent), 34 ui(new Ui::Widget) 35 { 36 ui->setupUi(this); 37 38 //Shader shader(":basicVertexShader.vert","./basicFragmentShader.frag"); 39 // QTimer* timer = new QTimer(this); 40 // timer->start(1); 41 // connect(timer,&QTimer::timeout,this,&slotUpdate); 42 43 } 44 45 Widget::~Widget() 46 { 47 delete ui; 48 } 49 50 void Widget::initializeGL() 51 { 52 initializeOpenGLFunctions(); 53 54 GLuint vertexShader; // 顶点着色器 55 vertexShader = glCreateShader(GL_VERTEX_SHADER);//创建顶点着色器 56 glShaderSource(vertexShader,1,&vertexShaderSource,NULL);// 参数二为需要编译的着色器源码数量 57 glCompileShader(vertexShader); 58 createShaderError(vertexShader,GL_COMPILE_STATUS,false,"Vertex Shader compiler error"); 59 60 GLuint fragmentShader;// 片段着色器 61 fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); 62 glShaderSource(fragmentShader,1,&fragmentShaderSource,NULL); 63 glCompileShader(fragmentShader); 64 createShaderError(fragmentShader,GL_COMPILE_STATUS,false,"Fragment Shader compiler error"); 65 66 m_shaderProgram = glCreateProgram(); 67 glAttachShader(m_shaderProgram,vertexShader); 68 glAttachShader(m_shaderProgram,fragmentShader); 69 glLinkProgram(m_shaderProgram); 70 createShaderError(m_shaderProgram,GL_LINK_STATUS,true,"Program linking failed error"); 71 72 glUseProgram(m_shaderProgram);//激活程序对象 73 glDeleteShader(vertexShader); 74 glDeleteShader(fragmentShader); 75 76 int nrAttributes; 77 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS,&nrAttributes); 78 qDebug() << nrAttributes; 79 } 80 81 void Widget::resizeGL(int w, int h) 82 { 83 //视口变换 84 glViewport(0,0,(GLsizei)w,(GLsizei)h); 85 } 86 87 void Widget::paintGL() 88 { 89 90 // glEnable(GL_DEPTH_TEST); 91 drawTriangles(); 92 //drawRect(); 93 } 94 95 void Widget::createShaderError(GLuint shader, GLuint flag, bool isProgram, const QString errMessage) 96 { 97 GLint success = 0; 98 GLchar error[1024] = {0}; 99 100 if (isProgram){ 101 glGetProgramiv(shader,flag,&success); 102 } 103 else { 104 glGetShaderiv(shader,flag,&success); 105 } 106 107 if (success == GL_FALSE){ 108 if (isProgram){ 109 glGetProgramInfoLog(shader,sizeof(error),NULL,error); 110 } 111 else { 112 glGetShaderInfoLog(shader,sizeof(error),NULL,error); 113 } 114 qDebug() << errMessage << ": " << error; 115 } 116 117 } 118 119 void Widget::drawRect() 120 { 121 glClearColor(0.2f, 0.3f, 0.3f, 1.0f); 122 glClear(GL_COLOR_BUFFER_BIT); 123 124 float vertices[] = { 125 // 位置 126 0.5f, 0.5f, 0.0f, // 右上 127 0.5f, -0.5f, 0.0f, // 右下 128 -0.5f, 0.5f, 0.0f, // 左上 129 -0.5f, -0.5f, 0.0f // 左下 130 }; 131 unsigned int indices[] = { 132 0,1,2,//第一个三角形 133 1,2,3// 第二个三角形 134 }; 135 136 // float timeValue = (float)clock(); 137 // float greenValue = (sin(timeValue)/2.0f) +0.5f; 138 // qDebug() << greenValue; 139 // int vertexColorLocation = glGetUniformLocation(m_shaderProgram, "ourColor"); 140 141 unsigned int VBO, VAO; 142 glGenVertexArrays(1, &VAO); 143 glGenBuffers(1, &VBO); 144 // 1. 绑定顶点数组对象 145 glBindVertexArray(VAO); 146 // 2. 把我们的顶点数组复制到一个顶点缓冲中,供OpenGL使用 147 glBindBuffer(GL_ARRAY_BUFFER, VBO); 148 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); 149 150 // 3. 复制我们的索引数组到一个索引缓冲中,供OpenGL使用 151 unsigned int EBO; 152 glGenBuffers(1,&EBO); 153 154 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO); 155 glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(indices),indices,GL_STATIC_DRAW); 156 157 // 4,设置顶点指针属性 158 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); 159 glEnableVertexAttribArray(0); 160 161 glBindBuffer(GL_ARRAY_BUFFER, 0); 162 163 // You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other 164 // VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary. 165 glBindVertexArray(0); 166 167 glUseProgram(m_shaderProgram); 168 // glUniform4f(vertexColorLocation, 0.0f, greenValue, 0.0f, 1.0f); 169 glBindVertexArray(VAO); 170 glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,0); 171 } 172 173 void Widget::drawTriangles() 174 { 175 glClearColor(0.2f, 0.3f, 0.3f, 1.0f); 176 glClear(GL_COLOR_BUFFER_BIT); 177 178 float vertices[] = { 179 // 位置 颜色 180 0.5f, -0.5f, 0.0f, 1.0f,0.0f,0.0f, 181 -0.5f, -0.5f, 0.0f, 0.0f,0.1f,0.0f, 182 0.0f, 0.5f, 0.0f, 0.0f,0.0f,1.0f 183 }; 184 185 unsigned int VBO, VAO; 186 glGenVertexArrays(1, &VAO); 187 glGenBuffers(1, &VBO); 188 // bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s). 189 glBindVertexArray(VAO); 190 191 glBindBuffer(GL_ARRAY_BUFFER, VBO); 192 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); 193 194 /* 195 第一个参数指定我们要配置的顶点属性。还记得我们在顶点着色器中使用layout(location = 0)定义了position顶点属性的位置值(Location)吗?它可以把顶点属性的位置值设置为0。因为我们希望把数据传递到这一个顶点属性中,所以这里我们传入0。 196 第二个参数指定顶点属性的大小。顶点属性是一个vec3,它由3个值组成,所以大小是3。 197 第三个参数指定数据的类型,这里是GL_FLOAT(GLSL中vec*都是由浮点数值组成的)。 198 下个参数定义我们是否希望数据被标准化(Normalize)。如果我们设置为GL_TRUE,所有数据都会被映射到0(对于有符号型signed数据是-1)到1之间。我们把它设置为GL_FALSE。 199 第五个参数叫做步长(Stride),它告诉我们在连续的顶点属性组之间的间隔。由于下个组位置数据在3个float之后,我们把步长设置为3 * sizeof(float)。要注意的是由于我们知道这个数组是紧密排列的(在两个顶点属性之间没有空隙)我们也可以设置为0来让OpenGL决定具体步长是多少(只有当数值是紧密排列时才可用)。一旦我们有更多的顶点属性,我们就必须更小心地定义每个顶点属性之间的间隔,我们在后面会看到更多的例子(译注: 这个参数的意思简单说就是从这个属性第二次出现的地方到整个数组0位置之间有多少字节)。 200 最后一个参数的类型是void*,所以需要我们进行这个奇怪的强制类型转换。它表示位置数据在缓冲中起始位置的偏移量(Offset)。由于位置数据在数组的开头,所以这里是0。我们会在后面详细解释这个参数 201 */ 202 // 位置属性 203 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0); 204 glEnableVertexAttribArray(0); 205 // 颜色属性 206 glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE, 6 * sizeof(float), (void*)(3*sizeof(float))); 207 glEnableVertexAttribArray(1); 208 209 // 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 210 glBindBuffer(GL_ARRAY_BUFFER, 0); 211 212 // You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other 213 // VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary. 214 glBindVertexArray(0); 215 216 glUseProgram(m_shaderProgram); 217 glBindVertexArray(VAO); // seeing as we only have a single VAO there's no need to bind it every time, but we'll do so to keep things a bit more organized 218 glDrawArrays(GL_TRIANGLES, 0, 3); 219 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include "widget.h" #include "ui_widget.h" #include <QDebug> //顶点着色器源码 const char *vertexShaderSource = "#version 330 core\n" "layout (location = 0) in vec3 aPos;\n" "void main()\n" "{\n" " gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n" "}\0"; //片段着色器源码 const char *fragmentShaderSource = "#version 330 core\n" "out vec4 FragColor;\n" "void main()\n" "{\n" " FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n" "}\n\0"; Widget::Widget(QWidget *parent) : QOpenGLWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); } Widget::~Widget() { delete ui; } void Widget::initializeGL() { initializeOpenGLFunctions(); GLuint vertexShader; // 顶点着色器 vertexShader = glCreateShader(GL_VERTEX_SHADER);//创建顶点着色器 glShaderSource(vertexShader,1,&vertexShaderSource,NULL);// 参数二为需要编译的着色器源码数量 glCompileShader(vertexShader); createShaderError(vertexShader,GL_COMPILE_STATUS,false,"Vertex Shader compiler error"); GLuint fragmentShader;// 片段着色器 fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragmentShader,1,&fragmentShaderSource,NULL); glCompileShader(fragmentShader); createShaderError(fragmentShader,GL_COMPILE_STATUS,false,"Fragment Shader compiler error"); m_shaderProgram = glCreateProgram(); glAttachShader(m_shaderProgram,vertexShader); glAttachShader(m_shaderProgram,fragmentShader); glLinkProgram(m_shaderProgram); createShaderError(m_shaderProgram,GL_LINK_STATUS,true,"Program linking failed error"); glUseProgram(m_shaderProgram);//激活程序对象 glDeleteShader(vertexShader); glDeleteShader(fragmentShader); } void Widget::resizeGL(int w, int h) { //视口变换 glViewport(0,0,(GLsizei)w,(GLsizei)h); } void Widget::paintGL() { // glEnable(GL_DEPTH_TEST); //drawTriangles(); drawRect(); } void Widget::createShaderError(GLuint shader, GLuint flag, bool isProgram, const QString errMessage) { GLint success = 0; GLchar error[1024] = {0}; if (isProgram){ glGetProgramiv(shader,flag,&success); } else { glGetShaderiv(shader,flag,&success); } if (success == GL_FALSE){ if (isProgram){ glGetProgramInfoLog(shader,sizeof(error),NULL,error); } else { glGetShaderInfoLog(shader,sizeof(error),NULL,error); } } qDebug() << errMessage << ": " << error; } void Widget::drawTriangles() { glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); 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); glGenBuffers(1, &VBO); // bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s). glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); // 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 glBindBuffer(GL_ARRAY_BUFFER, 0); // You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other // VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary. glBindVertexArray(0); glUseProgram(m_shaderProgram); glBindVertexArray(VAO); // seeing as we only have a single VAO there's no need to bind it every time, but we'll do so to keep things a bit more organized glDrawArrays(GL_TRIANGLES, 0, 3); } void Widget::drawRect() { glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); 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,1,2,//第一个三角形 1,2,3// 第二个三角形 }; unsigned int VBO, VAO; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); // 1. 绑定顶点数组对象 glBindVertexArray(VAO); // 2. 把我们的顶点数组复制到一个顶点缓冲中,供OpenGL使用 glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // 3. 复制我们的索引数组到一个索引缓冲中,供OpenGL使用 unsigned int EBO; glGenBuffers(1,&EBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(indices),indices,GL_STATIC_DRAW); // 4,设置顶点指针属性 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); // You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other // VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary. glBindVertexArray(0); glUseProgram(m_shaderProgram); glBindVertexArray(VAO); glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,0); } //#include "widget.h" //#include "ui_widget.h" //Widget::Widget(QWidget *parent) : // QGLWidget(parent), // ui(new Ui::Widget) //{ // ui->setupUi(this); //} //Widget::~Widget() //{ // delete ui; //} //void Widget::initializeGL() //{ // //设置widget的坐标和尺寸 // setGeometry(300, 150, 500, 500); // //设置清除时颜色 // glClearColor(0.0, 0.0, 0.0, 0); //} //void Widget::resizeGL(int w, int h) //{ // //视口变换 // glViewport(0,0,(GLsizei)w,(GLsizei)h); // //投影变换 // glMatrixMode(GL_PROJECTION); // glLoadIdentity(); // gluPerspective(40.0,(GLdouble)w/(GLdouble)h,0.1,10000.0); // //视图变换 // glMatrixMode(GL_MODELVIEW); // glLoadIdentity(); // gluLookAt(0.0,0.0,15.0,0.0,0.0,0.0,0.0,1.0,0.0); //} //void Widget::paintGL() //{ // //清屏 // glClear(GL_COLOR_BUFFER_BIT); // //绘制七彩三角形 // glBegin(GL_TRIANGLES); // glColor3f(1.0,0.0,0.0); // glVertex3f(-2,0,0); // glColor3f(0.0,1.0,0.0); // glVertex3f(2,0,0); // glColor3f(0.0,0.0,1.0); // glVertex3f(0,4,0); // glEnd(); // glFlush(); //}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QOpenGLWidget> #include <QOpenGLFunctions_3_0> namespace Ui { class Widget; } class Widget : public QOpenGLWidget,protected QOpenGLFunctions_3_0 { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); void initializeGL(); void resizeGL(int w,int h); void paintGL(); private: void createShaderError(GLuint shader,GLuint flag,bool isProgram,const QString errMessage); void drawTriangles(); void drawRect(); private: GLuint m_shaderProgram;//着色器程序对象 private: Ui::Widget *ui; }; #endif // WIDGET_H //#ifndef WIDGET_H //#define WIDGET_H //#include <QWidget> //#include <QtOpenGL/qgl.h> //#include <GL/gl.h> //#include <GL/glu.h> //#include <QOpenGLWidget> //#include <QOpenGLFunctions_3_0> //namespace Ui { //class Widget; //} //class Widget : public QGLWidget //{ // Q_OBJECT //public: // explicit Widget(QWidget *parent = 0); // ~Widget(); // void initializeGL(); // void resizeGL(int w,int h); // void paintGL(); //private: // Ui::Widget *ui; //}; //#endif // WIDGET_H