Main
#define GLEW_STATIC
#include<GL/glew.h>
#include<GLFW/glfw3.h>
#include<iostream>
#include "Shader.h"
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#include <glm.hpp>
#include <gtc/matrix_transform.hpp>
#include <gtc/type_ptr.hpp>
#include "Camera.h"
Camera* camera = new Camera(glm::vec3(0, 0, 3.0f), glm::radians(5.0f), glm::radians(200.0f), glm::vec3(0, 1.0f, 0));
void mous_callback(GLFWwindow* window, double xpos, double ypos);
/// <summary>
/// 键盘事件
/// </summary>
void processInput(GLFWwindow* window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
{
glfwSetWindowShouldClose(window, true);
}
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
{
camera->MoveZ =1.0f;
}
else if(glfwGetKey(window,GLFW_KEY_S)==GLFW_PRESS)
{
camera->MoveZ = -1.0f;
}
else
{
camera->MoveZ = 0;
}
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
{
camera->MoveX = 1;
}
else if(glfwGetKey(window,GLFW_KEY_D))
{
camera->MoveX = -1;
}
else
{
camera->MoveX = 0;
}
}
float lastX;
float lastY;
bool fistMouse=true;
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
};
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)
};
unsigned int indices[] = {
0, 1, 3, // 第一个三角形
1, 2, 3 // 第二个三角形
};
int main()
{
#pragma region 初始化GLFW和创建窗口
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
//创建window窗口
GLFWwindow* window = glfwCreateWindow(800, 800, "My OpenGl", NULL, NULL);
if (window == NULL)
{
printf("打开引擎失败");
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
#pragma endregion
#pragma region 初始化GLEW
glewExperimental = true;
if (glewInit() != GLEW_OK)
{
printf("初始化失败");
glfwTerminate();
return -1;
}
#pragma endregion
glEnable(GL_DEPTH_TEST);
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
glfwSetCursorPosCallback(window, mous_callback);
Shader* shaderSouce = new Shader("VertexSource.txt", "FragmentSource.txt");
#pragma region 贴图: 创建-设置-导入
//创建贴图
unsigned int textBufferA;
glGenTextures(1, &textBufferA);
glBindTexture(GL_TEXTURE_2D, textBufferA);
//设置uv采样
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// set texture filtering parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//加载贴图
int width, heigth, nrChannels;
unsigned char *data = stbi_load("wood.jpg", &width, &heigth, &nrChannels, 0);
if (data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, heigth, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
std::cout << "文件加载失败" << std::endl;
}
stbi_image_free(data);
//创建贴图
unsigned int textureBufferB;
glGenTextures(1, &textureBufferB);
glBindTexture(GL_TEXTURE_2D, textureBufferB);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// set texture filtering parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
stbi_set_flip_vertically_on_load(true);
unsigned char *data2 = stbi_load("face.png", &width, &heigth, &nrChannels, 0);
if (data2)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, heigth, 0, GL_RGBA, GL_UNSIGNED_BYTE, data2);
glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
std::cout << "文件加载失败" << std::endl;
}
stbi_image_free(data2);
shaderSouce->Use();
glUniform1i(glGetUniformLocation(shaderSouce->ID, "ourTexture"), 0);
glUniform1i(glGetUniformLocation(shaderSouce->ID, "ourFace"), 2);
#pragma endregion
#pragma region 创建VAO、VBO、EBO和数据绑定
unsigned int VAO;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
//创建一个 顶点缓冲对象:VBO
unsigned int VBO;
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);//绑定VBO
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); //将顶点数据复制到当前绑定缓冲
unsigned int EBO;
glGenBuffers(1, &EBO);//创建EBO
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);//传递GL_ELEMENT_ARRAY_BUFFER当作缓冲目标
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); //调用glBufferData函数把之前定义的顶点数据复制到缓冲的内存中
//顶点位置
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
//颜色
/*glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3*sizeof(float)));
glEnableVertexAttribArray(1);*/
//vu信息
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(2);
#pragma endregion
glm::mat4 trans;
//设置显示窗口大小
glViewport(0, 0, 800, 800);
//Camera *camera=new Camera(glm::vec3(0, 0, 3.0f), glm::vec3(0, -1.0f, 0), glm::vec3(0, 1.0f, 0));
//旋转位移缩放
//trans = glm::translate(trans, glm::vec3(-0.01f, 0, 0));
//trans = glm::rotate(trans, glm::radians(45.0f), glm::vec3(1.0f, 0, 0));
//trans = glm::scale(trans, glm::vec3(1.02f, 1.02f, 1.02f));
//空间矩阵
glm::mat4 viewMat;
// = glm::translate(viewMat, glm::vec3(0, 0, -3));
//投影矩阵
glm::mat4 projection;
projection = glm::perspective(glm::radians(45.0f), 800.0f / 800.0f, 0.1f, 100.0f);
/*glm::mat4 modelMat;
modelMat = glm::rotate(modelMat, glm::radians(50.0f), glm::vec3(0, 1.0f, 0.0f));*/
while (!glfwWindowShouldClose(window))
{
processInput(window);
//渲染
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);
viewMat = camera->GetViewMatrix();
for (int i = 0; i < 10; i++)
{
glm::mat4 modelMat2;
modelMat2 = glm::translate(modelMat2, cubePositions[i]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textBufferA);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, textureBufferB);
//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBindVertexArray(VAO);
shaderSouce->Use();
//glUniformMatrix4fv(glGetUniformLocation(shaderSouce->ID, "transform"), 1, GL_FALSE, glm::value_ptr(trans));
glUniformMatrix4fv(glGetUniformLocation(shaderSouce->ID, "modelMat"), 1, GL_FALSE, glm::value_ptr(modelMat2));
glUniformMatrix4fv(glGetUniformLocation(shaderSouce->ID, "viewMat"), 1, GL_FALSE, glm::value_ptr(viewMat));
glUniformMatrix4fv(glGetUniformLocation(shaderSouce->ID, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
//glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glDrawArrays(GL_TRIANGLES, 0, 36);
}
//绑定贴图
//切换渲染数据
glfwSwapBuffers(window);
//其他事件
glfwPollEvents();
camera->UpdateMoveCamera();
}
glfwTerminate();
return 0;
}
void mous_callback(GLFWwindow* window, double xpos, double ypos)
{
if (fistMouse == true)
{
lastX = xpos;
lastY = ypos;
fistMouse = false;
}
float xoffset = lastX-xpos;
float yoffset = lastY - ypos ;
lastX = xpos;
lastY = ypos;
camera->ProcessInput(xoffset,yoffset);
}
Camera 类
#include "Camera.h"
#include <glm.hpp>
#include <gtc/matrix_transform.hpp>
Camera::Camera(glm::vec3 position, glm::vec3 target, glm::vec3 worldUp)
{
Position = position;
WorldUp = worldUp;
Forword = glm::normalize(target - position);
Right = glm::normalize(glm::cross(worldUp, Forword));
Up = glm::normalize(glm::cross(Forword, Right));
}
//初始化
Camera::Camera(glm::vec3 position, float pitch, float yaw, glm::vec3 worldUp)
{
Position = position;
WorldUp = worldUp;
Forword.x = glm::cos(pitch) * glm::sin(yaw);
Forword.y = glm::sin(pitch);
Forword.z = glm::cos(pitch) * glm::cos(yaw);
Right = glm::normalize(glm::cross(WorldUp, Forword));
Up = glm::normalize(glm::cross(Forword, Right));
Yaw = yaw;
Pitch = pitch;
}
glm::mat4 Camera::GetViewMatrix()
{
//创建一个观察矩阵
return glm::lookAt(Position,Position+Forword,WorldUp);
}
//输入角度的偏移量
void Camera::ProcessInput(float xoffset, float yoffset)
{
Pitch+= yoffset * 0.0001f;
Yaw += xoffset * 0.0001f;
UpdateCameraVectors();
}
// Camera 位移 W A S D
void Camera::UpdateMoveCamera()
{
Position += Forword * MoveZ*0.1f; //前进或后退
Position += glm::normalize(glm::cross(Forword, Up)) * MoveX * 0.1f; //左或右
}
//Camera角度计算
void Camera::UpdateCameraVectors()
{
Forword.x = glm::cos(Pitch) * glm::sin(Yaw);
Forword.y = glm::sin(Pitch);
Forword.z = glm::cos(Pitch) * glm::cos(Yaw);
Right = glm::normalize(glm::cross( Forword, WorldUp));
Up = glm::normalize(glm::cross(Forword, Right));
}
Camera.h
#pragma once
#include <glm.hpp>
#include <gtc/matrix_transform.hpp>
class Camera
{
public:
glm::vec3 Position;
glm::vec3 Forword;
glm::vec3 Right;
glm::vec3 WorldUp;
glm::vec3 Up;
float Pitch;
float Yaw;
float MoveZ=0;
float MoveX = 0;
Camera(glm::vec3 position, glm::vec3 target, glm::vec3 worldUp);
Camera(glm::vec3 position, float pitch, float yaw, glm::vec3 worldUp);
glm::mat4 GetViewMatrix();
void ProcessInput(float xoffset, float yoffset);
void UpdateMoveCamera();
private:
void UpdateCameraVectors();
};
Shader 类
#include "Shader.h"
#include<string>
#include<iostream>
#include<fstream>
#include <sstream>
#define GLEW_STATIC
#include<GL/glew.h>
#include<GLFW/glfw3.h>
Shader::Shader(const char* vertexPath, const char* fragmentPath)
{
// 1. 从文件路径中获取顶点/片段着色器
std::ifstream vertexFile;
std::ifstream fragmentFile;
std::stringstream vertexSstring;
std::stringstream fragmentSstring;
std::string vertexCode;
std::string fragmentCode;
// 保证ifstream对象可以抛出异常:
vertexFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
fragmentFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
try
{
// 打开文件
vertexFile.open(vertexPath);
fragmentFile.open(fragmentPath);
// 读取文件的缓冲内容到数据流中
vertexSstring << vertexFile.rdbuf();
fragmentSstring << fragmentFile.rdbuf();
// 关闭文件处理器
vertexFile.close();
fragmentFile.close();
// 转换数据流到string
vertexCode = vertexSstring.str();
fragmentCode = fragmentSstring.str();
}
catch (const std::exception& ex)
{
printf("Open Failed");
}
// string转换char
const char* vShaderCode = vertexCode.c_str();
const char* fShaderCode = fragmentCode.c_str();
unsigned int vertex, fragment;
// 顶点着色器
vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &vShaderCode, NULL);
glCompileShader(vertex);
checkComplieError(ID, "VERTEX");
// 片段着色器
fragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment, 1, &fShaderCode, NULL);
glCompileShader(fragment);
checkComplieError(ID, "FRAGMENT");
// 着色器程序
ID = glCreateProgram();
glAttachShader(ID, vertex);
glAttachShader(ID, fragment);
glLinkProgram(ID);
checkComplieError(ID, "PROGAM");
glDeleteShader(vertex);
glDeleteShader(fragment);
}
void Shader::Use()
{
glUseProgram(ID);
}
/// <summary>
/// 检测编译错误
/// </summary>
void Shader::checkComplieError(unsigned int ID, std::string type)
{
int success;
char infoLog[512];
if (type != "PROGAM")
{
//获取编译状态
glGetShaderiv(ID, GL_COMPILE_STATUS, &success);
if (!success)
{
//返回错误类型
glGetShaderInfoLog(ID, 512, NULL, infoLog);
std::cout << "编译错误" << infoLog << std::endl;
}
}
else
{
glGetProgramiv(ID, GL_LINK_STATUS, &success);
if (!success)
{
glGetProgramInfoLog(ID, 512, NULL, infoLog);
std::cout << "编译错误" << infoLog << std::endl;
}
}
}
Shader.h
#pragma once
#include "Shader.h"
#include<string>
#include<iostream>
#include<fstream>
class Shader
{
public :
Shader(const char* vertexPath, const char* fragmentPath);
unsigned int ID;
void Use();
private:
void checkComplieError(unsigned int ID,std::string type);
};
VertexSource.txt
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;
out vec4 vertexColor;
out vec2 TextCoord;
//uniform mat4 transform;
uniform mat4 modelMat;
uniform mat4 viewMat;
uniform mat4 projection;
void main()
{
gl_Position =projection *viewMat* modelMat * vec4(aPos.x, aPos.y, aPos.z, 1.0);
vertexColor=vec4(aColor.x,aColor.y,aColor.z,1.0);
TextCoord=aTexCoord;
}
FragmentSource.txt
#version 330 core
out vec4 FragColor;
in vec4 vertexColor;
in vec2 TextCoord;
uniform sampler2D ourTexture;
uniform sampler2D ourFace;
void main()
{
FragColor =mix(texture(ourTexture,TextCoord),texture(ourFace,TextCoord),0.3);
}