• OpenGL学习——自定义Shader工具类


    从文件读取Vertex Shader 和 Fragment Shader的工具类。

    代码如下:

    Shader.h

    #ifndef Shader_h
    #define Shader_h
    
    // GLEW
    #define GLEW_STATIC
    #include <GL/glew.h>
    // GLFW
    #include <GLFW/glfw3.h>
    #include <iostream>
    #include <sstream>
    #include <fstream>
    #include <string>
    
    class Shader
    {
    public:
        Shader();
    
        Shader(const GLchar* vsPath, const GLchar* fragPath);
    
        ~Shader();
    
    public:
        void init(const GLchar* vsPath, const GLchar* fragPath);
    
        void useProgram();
    
        GLint getUniformLocation(const GLchar* uniformName);
    
    private:
        //create vertex shader
        void createVertexShader(const GLchar* vsPath);
    
        //create fragment shader
        void createFragmentShader(const GLchar* fragPath);
    
        //create shader program
        void createShaderProgram();
    
        //load string from file
        std::string loadFile(const GLchar* filePath);
    
    private:
        GLuint _vertexShader;
        GLuint _fragmentShader;
        GLuint _shaderProgram;
    
    };
    
    
    #endif //Shader_h

    Shader.cpp

    #include "Shader.h"
    
    Shader::Shader(){
    }
    
    Shader::Shader(const GLchar* vsPath, const GLchar* fragPath){
        init(vsPath, fragPath);
    }
    
    Shader::~Shader(){
    }
    
    void Shader::init(const GLchar* vsPath, const GLchar* fragPath){
        this->createVertexShader(vsPath);
        this->createFragmentShader(fragPath);
        this->createShaderProgram();
    }
    
    void Shader::useProgram(){
        glUseProgram(this->_shaderProgram);
    }
    
    GLint Shader::getUniformLocation(const GLchar* uniformName){
        GLint uniLocation = glGetUniformLocation(_shaderProgram, uniformName);
        return uniLocation;
    }
    
    
    void Shader::createVertexShader(const GLchar* vsPath){
        //compile vertex shader source
        std::string vertexShaderStr = this->loadFile(vsPath);
        const char *vertexShaderSrc = vertexShaderStr.c_str();
        std::cout << "vertexShaderSrc:
    " << vertexShaderSrc;
        //GLuint vertexShader;                                     // shader object
        _vertexShader = glCreateShader(GL_VERTEX_SHADER);         // create vertex shader object
        glShaderSource(_vertexShader, 1, &vertexShaderSrc, NULL); // shader source attach to shader object
        glCompileShader(_vertexShader);                           // compile shader
        //compile result check
        GLint success;
        GLchar infoLog[512];
        glGetShaderiv(_vertexShader, GL_COMPILE_STATUS, &success);
        if (!success){
            glGetShaderInfoLog(_vertexShader, 512, NULL, infoLog);
            std::cout << "vertex shader source compile failed...
    " << infoLog << std::endl;
            std::cout << vertexShaderSrc;
        }
    }
    
    
    void Shader::createFragmentShader(const GLchar* fragPath){
        //compile fragment shader source
        std::string fragmentShaderStr = this->loadFile(fragPath);
        const char *fragmentShaderSrc = fragmentShaderStr.c_str();
        std::cout << "
    
    fragmentShaderSrc:
    " << fragmentShaderSrc;
        //GLuint fragmentShader;
        _fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
        glShaderSource(_fragmentShader, 1, &fragmentShaderSrc, NULL);
        glCompileShader(_fragmentShader);
    }
    
    
    void Shader::createShaderProgram(){
        if (_vertexShader == NULL || _fragmentShader == NULL){
            return;
        }
        //shader program, link vertex shader object and fragment shader object
        //GLuint shaderProgram;
        _shaderProgram = glCreateProgram();               // create shader program
        glAttachShader(_shaderProgram, _vertexShader);     // attach vertex shader
        glAttachShader(_shaderProgram, _fragmentShader);   // attach fragment shader
        glLinkProgram(_shaderProgram);                    // linking
        //check link result
        GLint success;
        GLchar infoLog[512];
        glGetProgramiv(_shaderProgram, GL_LINK_STATUS, &success);
        if (!success){
            glGetProgramInfoLog(_shaderProgram, 512, NULL, infoLog);
            std::cout << "shader program linking failed...
    " << infoLog << std::endl;
            return;
        }
        //delete vertex shader object and fragment shader object
        glDeleteShader(_vertexShader);
        glDeleteShader(_fragmentShader);
    }
    
    
    //load string from file
    std::string Shader::loadFile(const GLchar* filePath){
        std::ifstream fileStream;
        fileStream.exceptions(std::ifstream::badbit);
        try{
            fileStream.open(filePath);
            std::stringstream ss;
            ss << fileStream.rdbuf();
            fileStream.close();
            return ss.str();
        }
        catch (std::ifstream::failure e){
            std::cout << "read file failed, filePath = " << filePath <<std::endl;
        }
        return NULL;
    }

    使用方法:

    const GLchar* vsPath = "D:\code\OpenGL\opengl-learn\hi-opengl\003-shader\triangles.vs";
    const GLchar* fragPath = "D:\code\OpenGL\opengl-learn\hi-opengl\003-shader\triangles.frag";
    Shader shader(vsPath, fragPath);

    while (...)
    {
    shader.useProgram();
    drawSomthing();
    }


    使用实例:
    TrianglesFile.h

    #ifndef  TrianglesFile_h
    #define  TrianglesFile_h
    
    #include "Shader.h"
    
    class TrianglesFile
    {
    public:
        TrianglesFile();
    
        ~TrianglesFile();
    
    public:
        virtual void init();
    
        virtual void draw();
    
    private:
        Shader* _shader;
    
    };
    
    #endif // TrianglesFile_h

    TrianglesFile.cpp

    #include "TrianglesFile.h"
    
    TrianglesFile::TrianglesFile(){
    }
    
    TrianglesFile::~TrianglesFile(){
        delete _shader;
    }
    
    
    void TrianglesFile::init(){
        // x,y,z  opengl coordinates, the vertex data, three 3d point in normalized device coordinates
        GLfloat vertexs[] = {
            -0.6f, 0.9f, 0.0f, 0.0f, 0.0f, 1.0f,    // top
            -0.3f, 0.2f, 0.0f, 0.0f, 1.0f, 0.0f,    // left down
            -0.9f, 0.2f, 0.0f, 1.0f, 0.0f, 0.0f,    // right down
        };
        //define VAO, vertex array object
        //GLuint VAO;
        glGenVertexArrays(1, &VAO);
        glBindVertexArray(VAO); // bind vertex array object
        //define VBO, vertex buffer object
        GLuint VBO;
        glGenBuffers(1, &VBO);                                                   // gen buffer object
        glBindBuffer(GL_ARRAY_BUFFER, VBO);                                      // bind buffer to the target
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertexs), vertexs, GL_STATIC_DRAW); // copy vertex data to VBO
        //set vertex attribute point, position
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
        glEnableVertexAttribArray(0);
        //set vertex attribute point, color
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(sizeof(GLfloat)* 3));
        glEnableVertexAttribArray(1);
        glBindVertexArray(0);//unbind vertex array object
    
        //create shader program
        const GLchar* vsPath = "D:\code\OpenGL\opengl-learn\hi-opengl\003-shader\triangles.vs";
        const GLchar* fragPath = "D:\code\OpenGL\opengl-learn\hi-opengl\003-shader\triangles.frag";
        this->_shader = new Shader(vsPath, fragPath);
    }
    
    void TrianglesFile::draw(){
        //use shader programs
        this->_shader->useProgram();
    
        //set uniform value
        GLfloat currentTime = glfwGetTime();                          // current time
        GLfloat redColor = (sin(6 * currentTime) + 1.0f) / 2.0f;   // sin value, like [0.0f, 1.0f]
        GLfloat blueColor = (cos(6 * currentTime) + 1.0f) / 2.0f;
        GLfloat alphaValue = (sin(6 * currentTime) + 1.0f) / 2.0f;
        GLint uniColorLocation = this->_shader->getUniformLocation("uniColor");
        glUniform4f(uniColorLocation, redColor, 0.0f, blueColor, 1.0f);    // reset uniform color
    
        //draw the triangles
        glBindVertexArray(VAO);
        glDrawArrays(GL_TRIANGLES, 0, 3);
        glBindVertexArray(0);
    }

    triangles.vs

    #version 330 core
    layout (location = 0) in vec3 pos;
    layout (location = 1) in vec3 color;
    out vec4 vertexColor;
    
    void main () {
      gl_Position = vec4(pos, 1.0);
      //vertexColor = vec4(0.99f, 0.5f, 0.2f, 1.0f);
      vertexColor = vec4(color, 1.0f);
    }

    triangles.frag

    #version 330 core
    in  vec4 vertexColor;
    out vec4 color;
    uniform  vec4 uniColor;    // define uniform color
    
    void main () {
      //color = vertexColor;     // set out color as vertex color
      //color = uniColor;        // set out color as unifrom color
      color = vertexColor + uniColor / 10;
    }

    运行结果:

  • 相关阅读:
    关于Linux联网的问题
    MapD的数据导出与扩容(利用现有的表)
    系统重启后,MapD报错Thrift的连接被拒绝
    关于Linux系统只读(Ubuntu16.4.1)
    javaBean的依赖注入中构造注入和依赖注入的区别
    Struts2开发中遇到的坑。。。
    通过配置文件设置定时任务,以及时间的选择
    微信小程序开发的movable开发的坑
    spring基础概念
    Hibernate的三种查询方式
  • 原文地址:https://www.cnblogs.com/xingchong/p/12070600.html
Copyright © 2020-2023  润新知