为了方便使用着色器,我自己封装了一个着色器类
1. ShaderAdmin.h
#ifndef ShaderAdmin_hpp
#define ShaderAdmin_hpp
#include <stdio.h>
#include <fstream>
#include <sstream>
#include <iostream>
#include <GL/glew.h>
using namespace std;
class ShaderAdmin
{
public:
GLuint m_program;
ShaderAdmin(const GLchar *vertexPath,const GLchar *fragmentPath);
~ShaderAdmin();
void Use();
private:
void compileShader(const GLchar *vShaderCode,const GLchar *fShaderCode);
void getCompileShaderErrorLog(GLuint shader);
void getLinkShaderProgramErrorLog(GLuint shaderProgram);
};
#endif /* ShaderAdmin_hpp */
2. ShaderAdmin.cpp
#include "ShaderAdmin.hpp"
ShaderAdmin::ShaderAdmin(const GLchar *vertexPath,const GLchar *fragmentPath)
{
string vertexCode;
string fragmentCode;
ifstream vShaderFile;
ifstream fShaderFile;
vShaderFile.exceptions(ifstream::badbit);
fShaderFile.exceptions(ifstream::badbit);
try
{
vShaderFile.open(vertexPath);
fShaderFile.open(fragmentPath);
if (!vShaderFile.is_open()||!fShaderFile.is_open())
{
cout << "无法打开文件!" << endl;
return;
}
stringstream vShaderStream,fShaderStream;
vShaderStream << vShaderFile.rdbuf();
fShaderStream << fShaderFile.rdbuf();
vShaderFile.close();
fShaderFile.close();
vertexCode = vShaderStream.str();
fragmentCode = fShaderStream.str();
}
catch (ifstream::failure e)
{
cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << endl;
}
const GLchar *vShaderCode = vertexCode.c_str();
const GLchar *fShaderCode = fragmentCode.c_str();
compileShader(vShaderCode, fShaderCode);
}
ShaderAdmin::~ShaderAdmin()
{
}
void ShaderAdmin::Use()
{
glUseProgram(this->m_program);
}
void ShaderAdmin::compileShader(const GLchar *vShaderCode, const GLchar *fShaderCode)
{
GLuint vShader,fShader;
vShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vShader,1,&vShaderCode,NULL);
glCompileShader(vShader);
getCompileShaderErrorLog(vShader);
fShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fShader,1,&fShaderCode,NULL);
glCompileShader(fShader);
getCompileShaderErrorLog(fShader);
m_program = glCreateProgram();
glAttachShader(m_program,vShader);
glAttachShader(m_program,fShader);
glLinkProgram(m_program);
getLinkShaderProgramErrorLog(m_program);
glDeleteShader(vShader);
glDeleteShader(fShader);
}
void ShaderAdmin::getCompileShaderErrorLog(GLuint shader)
{
GLint sucess;
GLchar infoLog[512];
glGetShaderiv(shader,GL_COMPILE_STATUS,&sucess);
if (!sucess)
{
glGetShaderInfoLog(shader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
}
void ShaderAdmin::getLinkShaderProgramErrorLog(GLuint shaderProgram)
{
GLint success;
GLchar infoLog[512];
glGetProgramiv(shaderProgram,GL_LINK_STATUS,&success);
if (!success)
{
glGetShaderInfoLog(shaderProgram,512,NULL,infoLog);
}
}
3. main.cpp
#include <iostream>
#include <stdlib.h>
#include <math.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "ShaderAdmin.hpp"
#define WIDTH 800
#define HEIGHT 600
#define TITLE "OpenGL"
void initGL();
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
GLuint VAO,VBO,EBO;
int main(int argc, const char * argv[]) {
initGL();
GLFWwindow *win = glfwCreateWindow(WIDTH, HEIGHT, TITLE, nullptr,nullptr);
if (win == nullptr)
{
cout << "Failed to create GLFW window!"<<endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(win);
glfwSetKeyCallback(win, key_callback);
glewExperimental = GL_TRUE;
if(glewInit() != GLEW_OK)
{
cout << "Failed to initialize GLEW" << endl;
}
int width,height;
glfwGetFramebufferSize(win, &width, &height);
glViewport(0, 0, width, height);
ShaderAdmin shader("shader/vShader.vert","shader/fShader.frag");
while (!glfwWindowShouldClose(win))
{
glfwPollEvents();
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
shader.Use();
GLfloat offset = 0.0f;
glUniform1f(glGetUniformLocation(shader.m_program,"offset"),offset);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
glfwSwapBuffers(win);
}
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &EBO);
glfwTerminate();
return 0;
}
void initGL()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
}
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{
if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
}
void renderTriangle()
{
GLfloat vertices[] = {
0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f
};
glGenVertexArrays(1,&VAO);
glGenBuffers(1,&VBO);
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(GLfloat),(GLvoid *)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,6 * sizeof(GLfloat),(GLvoid *)(3*sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER,0);
glBindVertexArray(0);
}