CP13:

全部合并成头文件,实现进一步抽象简洁
一个摄像机GLFWCamera.h
一个读取材质LoadShader.h
一个FrameWindow

#ifndef WINDOW_H
#define WINDOW_H
#undef GLFW_DLL
#include <GLFW/glfw3.h>
#define GLEW_STATIC
#include <GL/glew.h>
class FrameWindow
{
public:
FrameWindow(int width,int height,const char*title="OpenGL");
virtual ~FrameWindow();
GLFWwindow *getWindow();
private:
GLFWwindow *window;
int w;
int h;
};
FrameWindow::FrameWindow(int width,int height,const char*title){
w = width;
h = height;
glfwInit();
window = glfwCreateWindow(width,height,title,NULL,NULL);
glfwMakeContextCurrent(window);
glewInit();
}
FrameWindow::~FrameWindow(){
glfwDestroyWindow(window);
glfwTerminate();
}
GLFWwindow * FrameWindow::getWindow(){
return window;
}
#endif // WINDOW_H

#ifndef LOADSHADER_H
#define LOADSHADER_H
#include <GL/glew.h>
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
using namespace std;
struct LoadShader
{
LoadShader()=default;
LoadShader(const char*vertPath, const char* fragPath){
load(vertPath,fragPath);
}
string _readFile(const char *path){
ifstream stream;
stringstream ss;
stream.exceptions(ifstream::badbit);
try
{
stream.open(path); // open file
ss << stream.rdbuf(); // get strings from file
} catch (ifstream::failure e)
{
cout << "ERROR::OPEN FILE:" << path << endl;
}
// close file handle
stream.close();
// get str() from stringstream
string shaderCode = ss.str();
return shaderCode;
}
void _loadVertexShader(const char *path){
// read shader code
auto handle = _readFile(path);
const char * shaderCode = handle.c_str();
// Vertex shader
vertexShader = glCreateShader( GL_VERTEX_SHADER );
glShaderSource( vertexShader, 1, &shaderCode, NULL );
glCompileShader( vertexShader );
GLint success;
GLchar infoLog[512];
glGetShaderiv( vertexShader, GL_COMPILE_STATUS, &success );
if ( !success )
{
glGetShaderInfoLog( vertexShader, 512, NULL, infoLog );
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
}
void _loadFragmentShader(const char *path){
// read shader code
auto handle = _readFile(path);
const char * shaderCode = handle.c_str();
// Vertex shader
fragmentShader = glCreateShader( GL_FRAGMENT_SHADER );
glShaderSource( fragmentShader, 1, &shaderCode, NULL );
glCompileShader( fragmentShader );
GLint success;
GLchar infoLog[512];
glGetShaderiv( fragmentShader, GL_COMPILE_STATUS, &success ); // Get Compile status
if ( !success )
{
glGetShaderInfoLog( fragmentShader, 512, NULL, infoLog );
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
}
void load(const char* vertShaderPath, const char* fragShaderPath){
_loadVertexShader(vertShaderPath);
_loadFragmentShader(fragShaderPath);
// create shader program and check it
GLint success;
GLchar infoLog[512];
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram,vertexShader);
glAttachShader(shaderProgram,fragmentShader);
glLinkProgram(shaderProgram );
glGetProgramiv( shaderProgram, GL_LINK_STATUS, &success ); // Get Link Status
if (!success)
{
glGetProgramInfoLog( shaderProgram, 512, NULL, infoLog );
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
}
// Delete the shaders as they're linked into our program now and no longer necessery
glDeleteShader( vertexShader );
glDeleteShader( fragmentShader );
}
void use(){
glUseProgram(shaderProgram);
}
void setBool(const char *name, bool value) const
{
glUniform1i(glGetUniformLocation(shaderProgram, name), (int)value);
}
void setInt(const char *name, int value) const
{
glUniform1i(glGetUniformLocation(shaderProgram,name), value);
}
// ------------------------------------------------------------------------
void setFloat(const char *name, float value) const
{
glUniform1f(glGetUniformLocation(shaderProgram, name), value);
}
// ------------------------------------------------------------------------
void setVec2(const char *name, const glm::vec2 &value) const
{
glUniform2fv(glGetUniformLocation(shaderProgram,name), 1, &value[0]);
}
void setVec2(const char *name, float x, float y) const
{
glUniform2f(glGetUniformLocation(shaderProgram,name), x, y);
}
// ------------------------------------------------------------------------
void setVec3(const char *name, const glm::vec3 &value) const
{
glUniform3fv(glGetUniformLocation(shaderProgram,name), 1, &value[0]);
}
void setVec3(const char *name, float x, float y, float z) const
{
glUniform3f(glGetUniformLocation(shaderProgram,name), x, y, z);
}
// ------------------------------------------------------------------------
void setVec4(const char *name, const glm::vec4 &value) const
{
glUniform4fv(glGetUniformLocation(shaderProgram,name), 1, &value[0]);
}
void setVec4(const char *name, float x, float y, float z, float w)
{
glUniform4f(glGetUniformLocation(shaderProgram,name), x, y, z, w);
}
void setMat2(const char*name, const glm::mat2 &mat) const
{
glUniformMatrix2fv(glGetUniformLocation(shaderProgram, name), 1, GL_FALSE,glm::value_ptr(mat));
}
void setMat3(const char*name, const glm::mat3 &mat){
GLuint location = glGetUniformLocation(shaderProgram, name);
glUniformMatrix3fv(location,1, GL_FALSE, &mat[0][0]);
}
void setMat4(const char *name , const glm::mat4 &mat){
GLuint location = glGetUniformLocation(shaderProgram, name);
glUniformMatrix4fv(location,1, GL_FALSE, glm::value_ptr(mat));
}
GLuint shaderProgram;
GLuint vertexShader;
GLuint fragmentShader;
};
#endif // LOADSHADER_H

#ifndef GLFWCAMERA_H
#define GLFWCAMERA_H
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
class GLFWCamera{
public:
GLFWCamera();
~GLFWCamera(){}
enum CAMERA_MOVEMENT{
FORWARD, // Camera move to front -> key:W
BACKWARD, // Camera move to back -> key:S
LEFT, // Camera move to left -> key:A
RIGHT // Camera move to right -> key:D
};
public:
glm::vec3 pos;
glm::vec3 front;
glm::vec3 up;
// Euler Angles
float yaw;
float pitch;
// Camera options
float movementSpeed;
float mouseSensitivity;
float fov;
void processFov(float yoffset){
if(fov >= 1.0f && fov <= 45.0f){
fov -= yoffset;
}
if(fov <=1.0f){
fov = 1.0f;
}
if(fov >= 45.0f){
fov = 45.0f;
}
}
// build the matrix for lookAt
glm::mat4 GetViewMatrix(){
return glm::lookAt(pos , pos + front , up);
}
// process -Rotate the view-
void processMouseMove(float xoffset, float yoffset);
// process -W S A D-
void processKeyboardMove(float delta, CAMERA_MOVEMENT moveDir);
void updateFront(){
glm::vec3 tempfront;
tempfront.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));
tempfront.y = sin(glm::radians(pitch));
tempfront.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch));
this->front = glm::normalize(tempfront);
}
};
GLFWCamera::GLFWCamera(){
pos = glm::vec3(0.0f,0.0f,3.0f);
up = glm::vec3(0.0f,1.0f,0.0f);
front = glm::vec3(0.0f,0.0f,-1.0f);
yaw = -90.0f;
pitch = 0.0f;
fov = 45.0f;
movementSpeed = 2.5f;
mouseSensitivity = 0.1f;
}
void GLFWCamera::processMouseMove(float xoffset, float yoffset)
{
xoffset *= mouseSensitivity;
yoffset *= mouseSensitivity;
yaw += xoffset;
pitch += yoffset;
// make sure that when pitch is out of bounds, screen doesn't get flipped
if (pitch > 89.0f)
pitch = 89.0f;
if (pitch < -89.0f)
pitch = -89.0f;
this->updateFront();
}
void GLFWCamera::processKeyboardMove(float delta, CAMERA_MOVEMENT moveDir)
{
float vel = movementSpeed * delta;
switch (moveDir)
{
case FORWARD:
{
pos += vel * front;
break;
}
case BACKWARD:
{
pos -= vel * front;
break;
}
case LEFT:
{
pos -= glm::normalize(glm::cross(front, up)) * vel;
break;
}
case RIGHT:
{
pos += glm::normalize(glm::cross(front, up)) * vel;
}
default:
break;
}
}
#endif // GLFWCAMERA_H

#define GLEW_STATIC
// GLEW
#include <GL/glew.h>
#include <cstdlib>
#undef GLFW_DLL
// GLFW
#include <GLFW/glfw3.h>
#include <iostream>
#include "LoadShader.h"
#include "GLFWCamera.h"
#include "FrameWindow.h"
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
#include <cmath>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
const unsigned int SRC_WIDTH = 1400;
const unsigned int SRC_HEIGHT = 720;
static GLuint VAO,VBO,EBO;
static LoadShader shader;
void init();
void display();
void showFPS(GLFWwindow *);
void processInput(GLFWwindow *window);
void framebuffer_size_callback(GLFWwindow* window, int width, int height); // framezize
void mouse_callback(GLFWwindow* window, double xpos, double ypos); // Maya Alt+LeftMouse
void scroll_callback(GLFWwindow *window, double xoffset, double yoffset);
// camera
static GLFWCamera *camera;
static float lastX = float(SRC_WIDTH) / 2.0f;
static float lastY = float(SRC_HEIGHT) / 2.0f;
static bool firstMouse = true;
// timing
static float deltaTime = 0.0f; // time between current frame and last frame
static float lastFrame = 0.0f;
// world space positions of our cubes
static glm::vec3 cubePositions[] = {
glm::vec3( 0.0f, 0.0f, 0.0f),
glm::vec3( 2.0f, 5.0f, -15.0f),
glm::vec3(-1.5f, -2.2f, -2.5f),
glm::vec3(-3.8f, -2.0f, -12.3f),
glm::vec3( 2.4f, -0.4f, -3.5f),
glm::vec3(-1.7f, 3.0f, -7.5f),
glm::vec3( 1.3f, -2.0f, -2.5f),
glm::vec3( 1.5f, 2.0f, -2.5f),
glm::vec3( 1.5f, 0.2f, -1.5f),
glm::vec3(-1.3f, 1.0f, -1.5f)
};
void init(){
camera = new GLFWCamera;
float vertices[] = {
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f
};
glEnable(GL_DEPTH_TEST);
GLuint indices[6] = {
0, 1, 3, // FIRST TRIANGLE
1, 2, 3 // SECOND TRIANGLE
};
shader.load("shader.vert","shader.frag");
shader.use();
glCreateVertexArrays(1, &VAO);
glCreateBuffers(1, &VBO);
glCreateBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER,VBO);
//glNamedBufferStorage(VBO,sizeof(verticels), verticels, 0);
glBufferData(GL_ARRAY_BUFFER,sizeof(vertices), vertices, GL_STATIC_DRAW);
glCreateBuffers(1, &EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glNamedBufferStorage(EBO, sizeof(indices), indices , 0);
// VERTEX POINTS ATTRIBUTES
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); // POS at location 0
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); // ST at location 1
glEnableVertexAttribArray(1);
cout << "GEN Texture\n";
// loading one texture
GLuint textureID;
glCreateTextures(GL_TEXTURE_2D,1 , &textureID);
glBindTexture(GL_TEXTURE_2D,textureID);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
int width, height, nrChannels;
stbi_set_flip_vertically_on_load(true); // tell stb_image.h to flip loaded texture's on the y-axis.
unsigned char *data = stbi_load("wendy.png", &width, &height, &nrChannels, 0);
if (data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
}
cout << "FREE IMAGE\n";
stbi_image_free(data);
}
void display(){
// per-frame time logic
// --------------------
float currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glm::mat4 projection = glm::perspective(glm::radians(camera->fov),float(SRC_WIDTH) / float(SRC_HEIGHT),0.1f, 1000.0f);
glm::mat4 view = camera->GetViewMatrix();
// Send projection and view matrix to shader
shader.setMat4("projection", projection);
shader.setMat4("view", view);
for (unsigned int i = 0; i < 10; i++)
{
// RULE : RST
// FIRST WE ROTATION
glm::mat4 tempRot = glm::mat4(1.0f);
tempRot = glm::rotate(tempRot, float(glfwGetTime()*0.5f + float(i) ),glm::vec3(1.00f,0.0f,0.0f));
// then translate
glm::mat4 tempTrans = glm::mat4(1.0f);
tempTrans = glm::translate(tempTrans,cubePositions[i]);
// final combine one matrix
glm::mat4 model = glm::mat4(1.0f);
model = tempTrans * tempRot;
// send to opengl
shader.setMat4("model",model);
glDrawArrays(GL_TRIANGLES,0,36);
}
}
int main()
{
glfwInit();
FrameWindow FrameWindow(SRC_WIDTH,SRC_HEIGHT);
glfwSetFramebufferSizeCallback(FrameWindow.getWindow(), framebuffer_size_callback);
glfwSetCursorPosCallback(FrameWindow.getWindow(),mouse_callback);
glfwSetScrollCallback(FrameWindow.getWindow(), scroll_callback);
init();
// RENDER--------------
while(!glfwWindowShouldClose(FrameWindow.getWindow())){
processInput(FrameWindow.getWindow());
display();
glfwSwapBuffers(FrameWindow.getWindow());
glfwPollEvents();
}
delete camera;
return 0;
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
// make sure the viewport matches the new window dimensions; note that width and
// height will be significantly larger than specified on retina displays.
glViewport(0, 0, width, height);
}
void processInput(GLFWwindow *window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
camera->processKeyboardMove(deltaTime,GLFWCamera::FORWARD);
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
camera->processKeyboardMove(deltaTime,GLFWCamera::BACKWARD);
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
camera->processKeyboardMove(deltaTime,GLFWCamera::LEFT);
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
camera->processKeyboardMove(deltaTime,GLFWCamera::RIGHT);
}
// ROTATE VIEW DIR
void mouse_callback(GLFWwindow* window, double xpos, double ypos){
int mouse_state = glfwGetMouseButton(window,GLFW_MOUSE_BUTTON_LEFT);
int key_state = glfwGetKey(window,GLFW_KEY_LEFT_ALT);
if( mouse_state == GLFW_PRESS && key_state== GLFW_PRESS)
{
if (firstMouse){
lastX = xpos;
lastY = ypos;
firstMouse = false;
}
float xoffset = xpos - lastX;
float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top
lastX = xpos;
lastY = ypos;
camera->processMouseMove(xoffset,yoffset);
}
if (key_state == GLFW_RELEASE || mouse_state == GLFW_RELEASE){
firstMouse = true;
}
}
void scroll_callback(GLFWwindow *window, double xoffset, double yoffset){
camera->processFov(yoffset);
}
来源:https://www.cnblogs.com/gearslogy/p/12318092.html
