头文件(Shader.h)
#ifndef SHADER_H
#define SHADER_H
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <GL/glew.h>
class Shader
{
public:
// 程序ID
GLuint Program;
// 构造器读取并构建着色器
Shader(const GLchar* vertexPath, const GLchar* fragmentPath);
// 使用程序
void Use();
};
#endif
cpp(Shader.cpp)
#include <ShaderDemo.h>
#include <SOIL2.h>
using namespace std;
Shader::Shader (const GLchar* vertexPath, const GLchar* fragmentPath) {
std::string vertexCode;
std::string fragmentCode;
std::ifstream vShaderFile;
std::ifstream fShaderFile;
vShaderFile.exceptions(std::ifstream::badbit);
fShaderFile.exceptions(std::ifstream::badbit);
cout << vertexPath << endl;
cout << fragmentPath << endl;
try {
vShaderFile.open(vertexPath);
fShaderFile.open(fragmentPath);
std::stringstream vShaderStream, fShaderStream;
//缓冲
vShaderStream << vShaderFile.rdbuf();
fShaderStream << fShaderFile.rdbuf();
vShaderFile.close();
fShaderFile.close();
vertexCode = vShaderStream.str();
fragmentCode = fShaderStream.str();
cout << vertexCode << endl;
cout << fragmentCode << endl;
}
catch (std::ifstream::failure e)
{
std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULIY_RED" << std::endl;
}
const GLchar* vShaderCode = vertexCode.c_str();
const GLchar* fShaderCode = fragmentCode.c_str();
GLuint vertex, fragment;
GLchar infoLog[512];
GLint success;
vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &vShaderCode, NULL);
glCompileShader(vertex);
glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(vertex, 512, NULL, infoLog);
cout << "error::" << infoLog << endl;
}
GLint success2;
fragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment, 1, &fShaderCode, NULL);
glCompileShader(fragment);
glGetShaderiv(fragment, GL_COMPILE_STATUS, &success2);
if (!success2) {
glGetShaderInfoLog(fragment, 512, NULL,infoLog);
cout << "error:" << infoLog << endl;
}
if (success2 && success) {
this->Program = glCreateProgram();
glAttachShader(this->Program, vertex);
glAttachShader(this->Program, fragment);
glLinkProgram(this->Program);
glGetProgramiv(this->Program,512, &success);
if (!success) {
glGetProgramInfoLog(this->Program, 512, NULL, infoLog);
cout << "error" << infoLog << endl;
}
}
glDeleteShader(vertex);
glDeleteShader(fragment);
};
void Shader::Use() {
glUseProgram(this->Program);
}
顶点着色器文件(shader.vs)
#version 330
layout(location = 0) in vec3 position;
uniform vec3 pos;
uniform float x;
out vec3 outPos;
void main(){
gl_Position = vec4(position.x + x,position.y,position.z,1.0);
outPos = vec3(position);
};
片段着色器文件(shader.frag)
#version 330
in vec3 outPos;
uniform vec4 ourColor;
out vec4 color;
void main(){
color = vec4(outPos,0.1f);
};
如何使用?
// GLEW
#define GLEW_STATIC
#include <GL/glew.h>
// GLFW
#include <GLFW/glfw3.h>
#include <iostream>
#include <string>
#include <ShaderDemo.h>
#include <SOIL2.h>
using namespace std;
int main()
{
glewExperimental = GL_TRUE;
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_TRUE);
glfwWindowHint(GLFW_CENTER_CURSOR, GL_TRUE);
GLFWmonitor* currMonitor = glfwGetPrimaryMonitor();
const GLFWvidmode *mode = glfwGetVideoMode(currMonitor);
GLFWwindow* window = glfwCreateWindow(mode->width, mode->height, "LearnOpenGL2", nullptr, nullptr);
glfwMakeContextCurrent(window);
glewInit();
if (window == nullptr)
{
//cout << "Failed to create GLFW window" << endl;
glfwTerminate();
return -1;
}
GLfloat i = 0;
//使用我们之前创建的类
Shader shader = Shader("F:/wh/Glew/FirstGlew/FirstGlew/shader/shader.vs", "F:/wh/Glew/FirstGlew/FirstGlew/shader/shader.frag");
GLfloat vertex[] = {
-0.5f,-0.5f,0.0f,
0.5f,-0.5f,0.0f,
0.0f,0.5f,0.0f,
};
GLfloat vertex2[] = {
0.5f, 0.5f, 0.0f, // 右上角
0.5f, -0.5f, 0.0f, // 右下角
-0.5f, -0.5f, 0.0f, // 左下角
-0.5f, 0.5f, 0.0f // 左上角
};
GLuint index[] = {
0,1,3,
1,2,3
};
GLfloat colours[] = {
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f,
};
GLuint VAO;//顶点数组对象
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);//后面的VBO操作会被记录到该顶点数组对象,后面能直接用
GLuint VBO;
glGenBuffers(1, &VBO);//创建顶点缓冲对象(空),创建显存空间
glBindBuffer(GL_ARRAY_BUFFER, VBO);//缓冲对象绑定到缓冲区,一个缓冲区只能有一个缓冲对象, 不然后面写入缓冲区不知道写入哪个对象,但是一个缓冲对象可以绑定多个缓冲区
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex), vertex, GL_STATIC_DRAW);//往缓冲区中的对象写入数据c
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);//设置顶点属性指针,使用的是此时绑定到GL_ARRAY_BUFFER的VBO顶点缓冲对象
glEnableVertexAttribArray(0);//启用顶点属性,参数是顶点属性的位置
glBindVertexArray(0);//后面的VBO操作会被记录到该顶点数组对象,后面能直接用
while (!glfwWindowShouldClose(window))
{
i += 0.01;
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shader.Program);
GLint vertexColorLocation = glGetUniformLocation(shader.Program, "ourColor");
GLint x = glGetUniformLocation(shader.Program, "x");
GLint pos = glGetUniformLocation(shader.Program, "pos");
if (vertexColorLocation == 1) {
cout << "ok" << endl;
}
GLfloat time = glfwGetTime();
GLfloat greenValue = (sin(time) / 2) + 0.5;
glUniform4f(vertexColorLocation, greenValue, 0.0f, 0.0f, 0.0f);
glUniform1f(x, i);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
glfwPollEvents();
glfwSwapBuffers(window);
}
glfwTerminate();
return 0;
}