1.贴图
(1)漫反射贴图
(2)镜面光贴图
贴图的区分只是为了使其呈现出不同的渲染效果,实际操作与纹理相同,对贴图区分相当于对物体不同的部分使用不同的纹理单元
2.练习
(1)基础代码
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <learnopengl/shader_m.h>
#include <learnopengl/camera.h>
#include <iostream>
#include <stb_image.h>
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
void processInput(GLFWwindow* window);
// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
// camera
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
float lastX = SCR_WIDTH / 2.0f;
float lastY = SCR_HEIGHT / 2.0f;
bool firstMouse = true;
// timing
float deltaTime = 0.0f;
float lastFrame = 0.0f;
// lighting
glm::vec3 lightPos(2.2f, 1.0f, 2.0f);
//GLSL(OpenGL Shader Language)
const char* colorV =
"#version 330 core\n" //OpenGL版本与模式设置
"layout (location = 0) in vec3 aPos;\n" //定义顶点属性的位置值
"layout (location = 1) in vec3 aNormal;\n" //定义顶点属性的法线值
"layout (location = 2) in vec2 aTexCoords;\n"
"out vec3 Normal;\n"
"out vec3 FragPos;\n"
"out vec2 TexCoords;\n"
"uniform mat4 model;\n"
"uniform mat4 view;\n"
"uniform mat4 projection;\n"
"void main()\n"
"{\n"
"FragPos = vec3(model* vec4(aPos,1.0));\n"
"gl_Position = projection * view * vec4(FragPos, 1.0);\n" //进行顶点变换后设置位置
"Normal = mat3(transpose(inverse(model))) * aNormal;\n" //逆矩阵转置,防止缩放操作对法线造成影响
"TexCoords = aTexCoords;\n"
"}\0";
//Fragment GLSL
const char* colorF =
"#version 330 core\n"
"out vec4 FragColor;\n"
"struct Material{\n"
" sampler2D diffuse;\n"
" sampler2D specular;\n"
" float shininess;\n"
"};\n"
"struct Light {\n"
" vec3 position;\n"
" vec3 ambient;\n"
" vec3 diffuse;\n"
" vec3 specular;\n"
"};\n"
"in vec3 FragPos;\n"
"in vec3 Normal;\n"
"in vec2 TexCoords;\n"
"uniform vec3 viewPos;\n"
"uniform Material material;\n"
"uniform Light light;\n"
"void main()\n"
"{\n"
//ambient
//" vec3 ambient = light.ambient * material.ambient;\n"
" vec3 ambient = light.ambient * texture(material.diffuse, TexCoords).rgb;\n"
//diffuse
" vec3 norm = normalize(Normal);\n"
" vec3 lightDir = normalize(light.position - FragPos);\n"
" float diff = max(dot(norm, lightDir), 0.0);\n"
" vec3 diffuse = light.diffuse * diff * texture(material.diffuse, TexCoords).rgb;\n"
//specular
" vec3 viewDir = normalize(viewPos - FragPos);\n"
" vec3 reflectDir = reflect(-lightDir, norm);\n"
" float spec = pow(max(dot(viewDir,reflectDir), 0.0), material.shininess);\n"
" vec3 specular = light.specular * spec * texture(material.specular, TexCoords).rgb;\n"
//
" vec3 result = ambient + diffuse + specular;\n"
" FragColor = vec4(result, 1.0);\n"
"}\n";
//GLSL(OpenGL Shader Language)
const char* lightV =
"#version 330 core\n" //OpenGL版本与模式设置
"layout (location = 0) in vec3 aPos;\n" //定义顶点属性的位置值
"uniform mat4 model;\n"
"uniform mat4 view;\n"
"uniform mat4 projection;\n"
"void main()\n"
"{\n"
" gl_Position = projection * view * model * vec4(aPos, 1.0);\n" //进行顶点变换后设置位置
"}\0";
//Fragment GLSL
const char* lightF =
"#version 330 core\n"
"out vec4 FragColor;\n"//传出的颜色值
"void main()\n"
"{\n"
" FragColor = vec4(1.0f);\n"
"}\0";
int main()
{
// glfw: initialize and configure
// ------------------------------
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
// glfw window creation
// --------------------
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL12", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
glfwSetCursorPosCallback(window, mouse_callback);
glfwSetScrollCallback(window, scroll_callback);
// tell GLFW to capture our mouse
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
// glad: load all OpenGL function pointers
// ---------------------------------------
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
//shader program
// ---------------------------
//vertex shader
unsigned int vertexShader1 = glCreateShader(GL_VERTEX_SHADER);//顶点着色器对象创建
glShaderSource(vertexShader1, 1, &colorV, NULL);//GLSL设置
glCompileShader(vertexShader1);//
//编译检测
int success1;
char infolog1[512];
glGetShaderiv(vertexShader1, GL_COMPILE_STATUS, &success1);//success存储编译结果
if (!success1) {
glGetShaderInfoLog(vertexShader1, 512, NULL, infolog1);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infolog1 << std::endl;
}
// fragment shader
unsigned int fragmentShader1 = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader1, 1, &colorF, NULL);
glCompileShader(fragmentShader1);
//编译检测
glGetShaderiv(fragmentShader1, GL_COMPILE_STATUS, &success1);
if (!success1)
{
glGetShaderInfoLog(fragmentShader1, 512, NULL, infolog1);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infolog1 << std::endl;
}
//着色器链接
unsigned int shaderProgram1 = glCreateProgram();
glAttachShader(shaderProgram1, vertexShader1);
glAttachShader(shaderProgram1, fragmentShader1);
glLinkProgram(shaderProgram1);
//编译检测
glGetProgramiv(shaderProgram1, GL_LINK_STATUS, &success1);
if (!success1) {
glGetProgramInfoLog(shaderProgram1, 512, NULL, infolog1);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infolog1 << std::endl;
}
//delete shader
glDeleteShader(vertexShader1);
glDeleteShader(fragmentShader1);
unsigned int vertexShader2 = glCreateShader(GL_VERTEX_SHADER);//顶点着色器对象创建
glShaderSource(vertexShader2, 1, &lightV, NULL);//GLSL设置
glCompileShader(vertexShader2);//
//编译检测
int success;
char infolog[512];
glGetShaderiv(vertexShader2, GL_COMPILE_STATUS, &success);//success存储编译结果
if (!success) {
glGetShaderInfoLog(vertexShader2, 512, NULL, infolog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infolog << std::endl;
}
// fragment shader
unsigned int fragmentShader2 = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader2, 1, &lightF, NULL);
glCompileShader(fragmentShader2);
//编译检测
glGetShaderiv(fragmentShader2, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentShader2, 512, NULL, infolog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infolog << std::endl;
}
//着色器链接
unsigned int shaderProgram2 = glCreateProgram();
glAttachShader(shaderProgram2, vertexShader2);
glAttachShader(shaderProgram2, fragmentShader2);
glLinkProgram(shaderProgram2);
//编译检测
glGetProgramiv(shaderProgram2, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shaderProgram2, 512, NULL, infolog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infolog << std::endl;
}
//delete shader
glDeleteShader(vertexShader2);
glDeleteShader(fragmentShader2);
// set up vertex data (and buffer(s)) and configure vertex attributes
// ------------------------------------------------------------------
float vertices[] = {
// positions // normals // texture coords
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f
};
unsigned int VBO, CubeVAO; //EBO;
glGenVertexArrays(1, &CubeVAO);
glGenBuffers(1, &VBO);
//glGenBuffers(1, &EBO);
glBindVertexArray(CubeVAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
//glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
// position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// normal attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// TexCoords attribute
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(2);
// second, configure the light's VAO (VBO stays the same; the vertices are the same for the light object which is also a 3D cube)
unsigned int lightCubeVAO;
glGenVertexArrays(1, &lightCubeVAO);
glBindVertexArray(lightCubeVAO);
// we only need to bind to the VBO (to link it with glVertexAttribPointer), no need to fill it; the VBO's data already contains all we need (it's already bound, but we do it again for educational purposes)
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// load and create a texture
// -------------------------
unsigned int diffuseMap;
// texture 1
// ---------
glGenTextures(1, &diffuseMap);
glBindTexture(GL_TEXTURE_2D, diffuseMap);
// 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);
// load image, create texture and generate mipmaps
int width, height, nrChannels;
stbi_set_flip_vertically_on_load(true);
// The FileSystem::getPath(...) is part of the GitHub repository so we can find files on any IDE/platform; replace it with your own image path.
const std::string filename = "F:/DeskTop/container2.jpg";
unsigned char* data = stbi_load(filename.c_str(), &width, &height, &nrChannels, 0);
if (data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 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);
// texture 2
// ---------
unsigned int specularMap;
glGenTextures(1, &specularMap);
glBindTexture(GL_TEXTURE_2D, specularMap);
// 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);
// load image, create texture and generate mipmaps
stbi_set_flip_vertically_on_load(true);
// The FileSystem::getPath(...) is part of the GitHub repository so we can find files on any IDE/platform; replace it with your own image path.
const std::string filename2 = "F:/DeskTop/container2_specular.png";
unsigned char* data2 = stbi_load(filename2.c_str(), &width, &height, &nrChannels, 0);
if (data2)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data2);
//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(data2);
glUseProgram(shaderProgram1);
glUniform1i(glGetUniformLocation(shaderProgram1, "material.diffuse"),0);
glUniform1i(glGetUniformLocation(shaderProgram1, "material.specular"), 1);
// render loop
// -----------
while (!glfwWindowShouldClose(window))
{
// per-frame time logic
// --------------------
float currentFrame = static_cast<float>(glfwGetTime());
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
// input
// -----
processInput(window);
// render
// ------
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//开启深度缓冲
glEnable(GL_DEPTH_TEST);
//光源位置移动
//lightPos.x = 1.0f + sin(glfwGetTime()) * 2.0f;
//lightPos.y = sin(glfwGetTime() / 2.0f) * 1.0f;
// activate shader
glUseProgram(shaderProgram1);
//uniform setting
glUniform3fv(glGetUniformLocation(shaderProgram1, "light.position"), 1, glm::value_ptr(lightPos));
glUniform3fv(glGetUniformLocation(shaderProgram1, "viewPos"), 1, glm::value_ptr(camera.Position));//以摄像头位置作为视野方向起点
//light properities
//glm::vec3 lightColor;
//lightColor.x = static_cast<float>(sin(glfwGetTime() * 2.0));
//lightColor.y = static_cast<float>(sin(glfwGetTime() * 0.7));
//lightColor.z = static_cast<float>(sin(glfwGetTime() * 1.3));
//glm::vec3 diffuseColor = lightColor * glm::vec3(0.5f);
//glm::vec3 ambientColor = lightColor * glm::vec3(0.2f);
glUniform3fv(glGetUniformLocation(shaderProgram1, "light.ambient"), 1, glm::value_ptr(glm::vec3(0.2, 0.2, 0.2)));
glUniform3fv(glGetUniformLocation(shaderProgram1, "light.diffuse"), 1, glm::value_ptr(glm::vec3(0.5, 0.5, 0.5)));
//glUniform3fv(glGetUniformLocation(shaderProgram1, "light.ambient"), 1, glm::value_ptr(glm::vec3(1.0f, 1.0f, 1.0f)));
//glUniform3fv(glGetUniformLocation(shaderProgram1, "light.diffuse"), 1, glm::value_ptr(glm::vec3(1.0f, 1.0f, 1.0f)));
glUniform3fv(glGetUniformLocation(shaderProgram1, "light.specular"), 1, glm::value_ptr(glm::vec3(1.0f, 1.0f, 1.0f)));
//material properties
//glUniform3fv(glGetUniformLocation(shaderProgram1, "material.specular"), 1, glm::value_ptr(glm::vec3(0.5, 0.5, 0.5)));
//glUniform3fv(glGetUniformLocation(shaderProgram1, "material.ambient"), 1, glm::value_ptr(glm::vec3(0.0, 0.1, 0.06)));
//glUniform3fv(glGetUniformLocation(shaderProgram1, "material.diffuse"), 1, glm::value_ptr(glm::vec3(0.0, 0.50980392, 0.50980392)));
//glUniform3fv(glGetUniformLocation(shaderProgram1, "material.specular"), 1, glm::value_ptr(glm::vec3(0.50196078, 0.50196078, 0.50196078)));
glUniform1f(glGetUniformLocation(shaderProgram1, "material.shininess"), 64.0);
// view/projection transformations
glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
glm::mat4 view = camera.GetViewMatrix();//以摄像机位置设置观察位置
glUniformMatrix4fv(glGetUniformLocation(shaderProgram1, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
glUniformMatrix4fv(glGetUniformLocation(shaderProgram1, "view"), 1, GL_FALSE, glm::value_ptr(view));
// world transformation
glm::mat4 model = glm::mat4(1.0f);
glUniformMatrix4fv(glGetUniformLocation(shaderProgram1, "model"), 1, GL_FALSE, glm::value_ptr(model));
//texture
glActiveTexture(GL_TEXTURE0);//激活纹理
glBindTexture(GL_TEXTURE_2D, diffuseMap);//绑定纹理
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, specularMap);
// render the cube
glBindVertexArray(CubeVAO);
glDrawArrays(GL_TRIANGLES, 0, 36);
// also draw the lamp object
glUseProgram(shaderProgram2);
glUniformMatrix4fv(glGetUniformLocation(shaderProgram2, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
glUniformMatrix4fv(glGetUniformLocation(shaderProgram2, "view"), 1, GL_FALSE, glm::value_ptr(view));
model = glm::mat4(1.0f);
model = glm::translate(model, lightPos);
model = glm::scale(model, glm::vec3(0.2f)); // a smaller cube
glUniformMatrix4fv(glGetUniformLocation(shaderProgram2, "model"), 1, GL_FALSE, glm::value_ptr(model));
//glUniform4fv(glGetUniformLocation(shaderProgram2, "fragColor"), 1, glm::value_ptr(fragColor));
glBindVertexArray(lightCubeVAO);
glDrawArrays(GL_TRIANGLES, 0, 36);
glfwSwapBuffers(window);
glfwPollEvents();
}
// optional: de-allocate all resources once they've outlived their purpose:
// ------------------------------------------------------------------------
glDeleteVertexArrays(1, &CubeVAO);
glDeleteVertexArrays(1, &lightCubeVAO);
glDeleteBuffers(1, &VBO);
//glDeleteBuffers(1, &EBO);
// glfw: terminate, clearing all previously allocated GLFW resources.
// ------------------------------------------------------------------
glfwTerminate();
return 0;
}
// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
// ---------------------------------------------------------------------------------------------------------
void processInput(GLFWwindow* window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
camera.ProcessKeyboard(FORWARD, deltaTime);
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
camera.ProcessKeyboard(BACKWARD, deltaTime);
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
camera.ProcessKeyboard(LEFT, deltaTime);
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
camera.ProcessKeyboard(RIGHT, deltaTime);
}
// glfw: whenever the window size changed (by OS or user resize) this callback function executes
// ---------------------------------------------------------------------------------------------
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);
}
// glfw: whenever the mouse moves, this callback is called
// -------------------------------------------------------
void mouse_callback(GLFWwindow* window, double xposIn, double yposIn)
{
float xpos = static_cast<float>(xposIn);
float ypos = static_cast<float>(yposIn);
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.ProcessMouseMovement(xoffset, yoffset);
}
// glfw: whenever the mouse scroll wheel scrolls, this callback is called
// ----------------------------------------------------------------------
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
camera.ProcessMouseScroll(static_cast<float>(yoffset));
}
(2)运行结果