zoukankan      html  css  js  c++  java
  • QT_OPENGL-------- 4.可编程管线绘制三角形

    一、环境:qt下qmake编译
    首先在qt .pro文件中添加glew和glfw的链接
    LIBS+= -L/usr/lib64 -lGLEW
    LIBS +=-L/usr/local/lib -lglfw3 -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor -lGL -lpthread -ldl
    二、用可编程管线实现画三角形分为三步
    1.创建vertexshader和fragramshader作为gpu program,
    2.创建vertexdata上传数据到gpu
    3.调用显卡程序渲染vertexdata,也就是画三角形
    三、具体实现
    main.cpp
    #include<GL/glew.h>
    #include <GLFW/glfw3.h>
    #include<stdio.h>
    #include<glm/glm.hpp>
    #include<glm/ext.hpp>
    
    GLfloat deltaTime = 0.0f;
    GLfloat lastFrame = 0.0f;
    struct Vertex
    {
        float pos[3];
        float color[4];
    
    };
    
    char *LoadFileContent(const char*path)
    {
        FILE*pFile = fopen(path, "rb");
        if (pFile)
        {
            fseek(pFile, 0, SEEK_END);
            int nLen = ftell(pFile);
            char*buffer = new char[nLen+1];
            rewind(pFile);
            fread(buffer, nLen, 1, pFile);
            buffer[nLen]='';
            fclose(pFile);
            return buffer;
        }
        fclose(pFile);
        return nullptr;
    }
    GLint CreateGPUProgram(const char*vsShaderPath,const char*fsShaderPath)
    {
        GLuint vsShader=glCreateShader(GL_VERTEX_SHADER);
        GLuint fsShader=glCreateShader(GL_FRAGMENT_SHADER);
        const char*vsCode=LoadFileContent(vsShaderPath);
        const char*fsCode=LoadFileContent(fsShaderPath);
        glShaderSource(vsShader,1,&vsCode,nullptr);
        glShaderSource(fsShader,1,&fsCode,nullptr);
        glCompileShader(vsShader);
        glCompileShader(fsShader);
        GLuint program=glCreateProgram();
        glAttachShader(program,vsShader);
        glAttachShader(program,fsShader);
        glLinkProgram(program);
        glDetachShader(program,vsShader);
        glDetachShader(program,fsShader);
        glDeleteShader(vsShader);
        glDeleteShader(fsShader);
        return program;
    }
    void framebuffer_size_callback(GLFWwindow* window, int width, int height)
    {
        glViewport(0, 0, width, height);
    }
    int main(void)
    {
        GLFWwindow* window;
    
    
        if (!glfwInit())
            return -1;
    
        window = glfwCreateWindow(480, 320, "Hello World", NULL, NULL);
        if (!window)
        {
            glfwTerminate();
            return -1;
        }
        glfwMakeContextCurrent(window);
        glewExperimental = GL_TRUE;
        // 还需要注册这个函数,告诉GLFW我们希望每当窗口调整大小的时候调用这个函数。
        glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
    
        glewInit();//初始化glew可以使用高级opengl接口函数
        GLuint program=CreateGPUProgram("/home/jun/OpenGL/FirstTriangle/sample.vs","/home/jun/OpenGL/FirstTriangle/sample.fs");
        //在创建程序之后取得每一个变量的位置
        GLint posLocation,colorLocation,MLocation,PLocation,VLocation;//分别代表sample.vs文件中pos,color,M,P,V的位置
        //获取变量的值
        posLocation=glGetAttribLocation(program,"pos");//第一个参数是你的程序是什么,第二个参数是要获取的sample.vs变量名
        colorLocation=glGetAttribLocation(program,"color");
        MLocation=glGetUniformLocation(program,"M");
         PLocation=glGetUniformLocation(program,"P");
          VLocation=glGetUniformLocation(program,"V");
        //创建vertex data (顶点数据)
        Vertex vertex[3];
        vertex[0].pos[0] = 0;
            vertex[0].pos[1] = 0;
            vertex[0].pos[2] = -100.0f;
            vertex[0].color[0] = 1.0f;
            vertex[0].color[1] = 1.0f;
            vertex[0].color[2] = 1.0f;
            vertex[0].color[3] = 1.0f;
    
            vertex[1].pos[0] = 10;
            vertex[1].pos[1] = 0;
            vertex[1].pos[2] = -100.0f;
            vertex[1].color[0] = 1.0f;
            vertex[1].color[1] = 1.0f;
            vertex[1].color[2] = 1.0f;
            vertex[1].color[3] = 1.0f;
    
            vertex[2].pos[0] = 0;
            vertex[2].pos[1] = 10;
            vertex[2].pos[2] = -100.0f;
            vertex[2].color[0] = 1.0f;
            vertex[2].color[1] = 1.0f;
            vertex[2].color[2] = 1.0f;
            vertex[2].color[3] = 1.0f;
    
        GLuint vbo;//vertex buffer
        //object创建并绑定VBO对象
        glGenBuffers(1,&vbo);//需要声明一个vbo对象
        glBindBuffer(GL_ARRAY_BUFFER,vbo);//设置为当前操作的对象
        // 分配空间 传送数据
        glBufferData(GL_ARRAY_BUFFER,sizeof(vertex)*3,vertex,GL_STATIC_DRAW);//将内存中的数据传入显卡buffer数据包含三个顶点和4个color
        // 解除绑定
        glBindBuffer(GL_ARRAY_BUFFER,0);
        //创建一个单位矩阵
        float identity[]=
        {
            1,0,0,0,
            0,1,0,0,
            0,0,1,0,
            0,0,0,1
    
    
        };
       //创建一个投影矩阵
       glm::mat4 projection=glm::perspective(45.0f,800.0f/600.0f,0.1f,1000.0f);
    
    
       glEnable(GL_DEPTH_TEST);
       glEnable(GL_CULL_FACE);
    
        while (!glfwWindowShouldClose(window))
        {
            GLfloat currentFrame = (GLfloat)glfwGetTime();
            deltaTime = currentFrame - lastFrame;
            lastFrame = currentFrame;
            glfwPollEvents();
    
            glClearColor(1.0f, 0.04f, 0.14f, 1.0f);
    
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
            //调用显卡程序渲染数据
            glUseProgram(program);//创建一个程序,调用渲染程序
            // 在上面已经获取到了posLocation,colorLocation,MLocation,PLocation,VLocation在gpu中地址的值,这里就可以把定义的三角形的顶点的值付给地址了
            glUniformMatrix4fv(MLocation,1,GL_FALSE,identity);//第一个参数传地址,第二份是size,第三个是否转置,第四个参数是要传的数据,这里传单位矩阵
            glUniformMatrix4fv(VLocation,1,GL_FALSE,identity);//视图矩阵
            glUniformMatrix4fv(PLocation,1,GL_FALSE,glm::value_ptr(projection));//投影矩阵
    
           //给pos 和color传值
            glBindBuffer(GL_ARRAY_BUFFER,vbo);
            glEnableVertexAttribArray(posLocation);
            //指定显卡中vbo数据分别对应的是sample中的pos和color
            glVertexAttribPointer(posLocation,3,GL_FLOAT,GL_FALSE,sizeof(Vertex),nullptr);//第一个参数传位置,第二个数量,第三变量类型,第四个是否归一化,第五个间隔多少,第六感是数据开始的地方
            //color
            glEnableVertexAttribArray(colorLocation);
            glVertexAttribPointer(colorLocation,4,GL_FLOAT,GL_FALSE,sizeof(Vertex),(const GLvoid*)(3*sizeof(float)));
            //画图
            glDrawArrays(GL_TRIANGLES,0,3);//起始位置是0,画3个点
            glBindBuffer(GL_ARRAY_BUFFER,0);
    
            glUseProgram(0);//结束时重置
            glfwSwapBuffers(window);
    
    
        }
    
        glfwTerminate();
        return 0;
    }

    sample.vs

    attribute vec3 pos;
    attribute vec4 color;
    
    uniform mat4 M;
    uniform mat4 V;
    uniform mat4 P;
    
    varying vec4 V_Color;
    
    void main()
    {
        V_Color=color;
        gl_Position=P*V*M*vec4(pos,1.0);
    }

    sample.fs

    varying vec4 V_Color;
    
    void main()
    {
        gl_FragColor=V_Color;
    }

    四、结果展示


  • 相关阅读:
    我今天能懂
    SpringMVC之RequestContextHolder分析
    idea只导入部分依赖
    idea中GitPush失败问题
    SpringBoot常用配置,引入外部配置文件信息,热加载
    idea的yml文件不识别问题
    SpringBoot介绍,快速入门小例子,目录结构,不同的启动方式,SpringBoot常用注解
    Java连接Redis,存储对象获取对象()byte和json),连接池
    Nginx的反向代理
    Nginx介绍,安装,配置
  • 原文地址:https://www.cnblogs.com/fuhang/p/10032280.html
Copyright © 2011-2022 走看看