main.cpp
#define STB_IMAGE_IMPLEMENTATION
#include
#include
#include
#include
#include
#include "shader.h"
#include
#include
#include
#pragma comment (lib, "glfw3.lib")
void framebuffer_size_callback(GLFWwindow* pWnd, int width, int height);
void processInput(GLFWwindow *pWnd);
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
int main()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* pWnd = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
if (pWnd == NULL)
{
std::cout << "Failed to create GLFW pWnd" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(pWnd);
glfwSetFramebufferSizeCallback(pWnd, framebuffer_size_callback);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
glEnable(GL_DEPTH_TEST); // 开启深度测试
Shader ourShader("coordinate_systems.vs", "coordinate_systems.fs");
float vertices[] = { // 模型位置坐标3 纹理坐标3
-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 VBO, VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// position attribute -> layout 0
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// texture coord attribute -> layout 1
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// 图像1
unsigned int texture1;
glGenTextures(1, &texture1); // 创建一个空的纹理对象
glBindTexture(GL_TEXTURE_2D, texture1);// 绑定后,接下来对纹理的操作均在此ID上进行
// set the texture wrapping parameters 设置纹理环绕方式:均为重复
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);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
int width, height, nrChannels;
// 将纹理图片数据加载到内存中
//stbi_set_flip_vertically_on_load(true); // 翻转图像
unsigned char *data = stbi_load("../res/container.jpg", &width, &height, &nrChannels, 0);
if (data)
{
// 用纹理图片数据生成一个2D纹理,即将空的纹理对象填入数据
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
std::cout << "Failed to load texture" << std::endl;
}
stbi_image_free(data);
// 图像2
unsigned int texture2;
glGenTextures(1, &texture2); // 创建一个空的纹理对象
glBindTexture(GL_TEXTURE_2D, texture2);// 绑定后,接下来对纹理的操作均在此ID上进行
// set the texture wrapping parameters 设置纹理环绕方式:均为重复
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);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
data = stbi_load("../res/Sloth.jpg", &width, &height, &nrChannels, 0);
if (data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
std::cout << "Failed to load texture" << std::endl;
}
stbi_image_free(data); // 释放图片资源
// 纹理分别对应不同的采样器
ourShader.useShaderProgram();
ourShader.setInt("texture1", 0);
ourShader.setInt("texture2", 1);
while (!glfwWindowShouldClose(pWnd))
{
processInput(pWnd);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // also clear the depth buffer now!
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture1);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture2);
ourShader.useShaderProgram();
// create transformations
glm::mat4 viewMat;
glm::mat4 projectionMat;
projectionMat = glm::perspective(glm::radians(45.0f), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
viewMat = glm::translate(viewMat, glm::vec3(0.0f, 0.0f, -3.0f));
// pass transformation matrices to the shader
ourShader.setMat4("projection", projectionMat);
ourShader.setMat4("view", viewMat);
// render boxes
glBindVertexArray(VAO);
for (unsigned int i = 0; i < 10; i++)
{
// calculate the model matrix for each object and pass it to shader before drawing
// 模型变换 -> 世界坐标
// 偏移
glm::mat4 model;
model = glm::translate(model, cubePositions[i]);
// 旋转
float angle = 20.0f * i;
model = glm::rotate(model, glm::radians(angle), glm::vec3(1.0f, 0.3f, 0.5f));
ourShader.setMat4("model", model);
glDrawArrays(GL_TRIANGLES, 0, 36);
}
glfwSwapBuffers(pWnd);
glfwPollEvents();
}
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glfwTerminate();
return 0;
}
void processInput(GLFWwindow *pWnd)
{
if (glfwGetKey(pWnd, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(pWnd, true);
}
void framebuffer_size_callback(GLFWwindow* pWnd, int width, int height)
{
glViewport(0, 0, width, height);
}
shader.h
#ifndef SHADER_H
#define SHADER_H
#include ; // 包含glad来获取所有的必须OpenGL头文件
#include
#include
#include
#include
#include
#include
#include
class Shader
{
public:
// 程序ID
unsigned int m_ID;
// 构造器读取并构建着色器
Shader(const GLchar* vertexPath, const GLchar* fragmentPath);
// 使用/激活程序
void useShaderProgram();
// uniform工具函数
void setBool(const std::string &name, bool value) const;
void setInt(const std::string &name, int value) const;
void setFloat(const std::string &name, float value) const;
void setMat4(const std::string &name, glm::mat4 mat) const;
private:
void checkCompileErrors(unsigned int shader, std::string type);
};
#endif
shader.cpp
#include "shader.h"
Shader::Shader(const char* vertexPath, const char* fragmentPath)
{
// 1. retrieve the vertex/fragment source code from filePath
// 加载读取Shader文件
std::string strVertexCode;
std::string strFragmentCode;
std::ifstream vShaderFile;
std::ifstream fShaderFile;
// ensure ifstream objects can throw exceptions:
vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
try
{
// open files
vShaderFile.open(vertexPath);
fShaderFile.open(fragmentPath);
std::stringstream vShaderStream, fShaderStream;
// read file's buffer contents into streams
vShaderStream << vShaderFile.rdbuf();
fShaderStream << fShaderFile.rdbuf();
// close file handlers
vShaderFile.close();
fShaderFile.close();
// convert stream into string
strVertexCode = vShaderStream.str();
strFragmentCode = fShaderStream.str();
}
catch (std::ifstream::failure e)
{
std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl;
}
const char* vShaderCode = strVertexCode.c_str();
const char * fShaderCode = strFragmentCode.c_str();
// 2. compile shaders 编译
unsigned int nVertex, nFragment;
int nSuccess = 0;
char infoLog[512];
// vertex shader
nVertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(nVertex, 1, &vShaderCode, NULL);
glCompileShader(nVertex);
checkCompileErrors(nVertex, "VERTEX");
// fragment Shader
nFragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(nFragment, 1, &fShaderCode, NULL);
glCompileShader(nFragment);
checkCompileErrors(nFragment, "FRAGMENT");
// shader Program
m_ID = glCreateProgram();
glAttachShader(m_ID, nVertex);
glAttachShader(m_ID, nFragment);
glLinkProgram(m_ID);
checkCompileErrors(m_ID, "PROGRAM");
// delete the shaders as they're linked into our program now and no longer necessary
glDeleteShader(nVertex);
glDeleteShader(nFragment);
}
// activate the shader
// ------------------------------------------------------------------------
void Shader::useShaderProgram()
{
glUseProgram(m_ID);
}
// utility uniform functions
// ------------------------------------------------------------------------
void Shader::setBool(const std::string &name, bool value) const
{
glUniform1i(glGetUniformLocation(m_ID, name.c_str()), (int)value);
}
// ------------------------------------------------------------------------
void Shader::setInt(const std::string &name, int value) const
{
glUniform1i(glGetUniformLocation(m_ID, name.c_str()), value);
}
// ------------------------------------------------------------------------
void Shader::setFloat(const std::string &name, float value) const
{
glUniform1f(glGetUniformLocation(m_ID, name.c_str()), value);
}
void Shader::setMat4(const std::string &name, glm::mat4 mat) const
{
glUniformMatrix4fv(glGetUniformLocation(m_ID, name.c_str()), 1, GL_FALSE, &mat[0][0]);
}
// utility function for checking shader compilation/linking errors.
// ------------------------------------------------------------------------
void Shader::checkCompileErrors(unsigned int shader, std::string type)
{
int nSuccess = 0;
char infoLog[1024];
if (type != "PROGRAM")
{
glGetShaderiv(shader, GL_COMPILE_STATUS, &nSuccess);
if (!nSuccess)
{
glGetShaderInfoLog(shader, 1024, NULL, infoLog);
std::cout << "ERROR::SHADER_COMPILATION_ERROR of type: " << type << "\n" << infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
}
}
else
{
glGetProgramiv(shader, GL_LINK_STATUS, &nSuccess);
if (!nSuccess)
{
glGetProgramInfoLog(shader, 1024, NULL, infoLog);
std::cout << "ERROR::PROGRAM_LINKING_ERROR of type: " << type << "\n" << infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
}
}
}
coordinate_systems.vs
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 texturePos;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
out vec2 TexCoord;
void main()
{
// 注意乘法要从右向左读
gl_Position = projection * view * model * vec4(aPos, 1.0);
TexCoord = vec2(texturePos.x, 1.0 - texturePos.y);
}
coordinate_systems.fs
#version 330 core // 版本声明
out vec4 FragColor; // 输出绘制
in vec2 TexCoord; // 从vs中传进
uniform sampler2D texture1; // 纹理采样器
uniform sampler2D texture2; // 纹理采样器
void main()
{
// 两个纹理进行混合
FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.5);
}