qt opengl

着色器:

//#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);
}
main.cpp三角形

 

#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
shader着色器

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);
}

 

 

四边形

 

 

 

更多属性:

  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 }
widget.cpp

 

#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();
//}
View Code

 

#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
View Code
posted @ 2019-12-18 17:51  狂奔~  阅读(641)  评论(0编辑  收藏  举报