从文件读取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:\n" << 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...\n" << 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 << "\n\nfragmentShaderSrc:\n" << 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...\n" << 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; }
运行结果: