// cubemaps-exercise1.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "glew/glew.h"
#include "glfw/glfw3.h"
#include "SOIL.h"
#include "camera.h"
#include "filesystem.h"
#include "mesh.h"
#include "model.h"
#include "root_directory.h"
#include "shader_m.h"
#include "stb_image.h"
#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"
#include "glm/gtc/type_ptr.hpp"
#include <iostream>
#include <vector>
using namespace std;
const GLuint screenWidth = 1920;
const GLuint screenHeight = 1080;
void key_callback(GLFWwindow *window, int key, int scancode, int action, int mode);
void scroll_callback(GLFWwindow *window, double xPos, double yPos);
void mouse_callback(GLFWwindow *window, double xOffset, double yOffset);
void do_movement();
GLuint loadTexture(GLchar *path, GLboolean alpha = GL_FALSE);
GLuint loadCubemap(vector<const GLchar*> faces);
Camera camera(glm::vec3(0.0f, 8.0f, 15.0f));
GLboolean keys[1024];
GLfloat lastX = (GLfloat)screenWidth / 2.0f;
GLfloat lastY = (GLfloat)screenHeight / 2.0f;
GLboolean firstMouse = GL_FALSE;
GLfloat lastFrame = 0.0f;
GLfloat deltaTime = 0.0f;
int main()
{
GLenum glfwErr = glfwInit();
if (GLFW_FALSE == glfwErr)
{
cout << "GLFW initialization failed!" << endl;
return -1;
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
GLFWwindow *window = glfwCreateWindow(screenWidth, screenHeight, "cubemaps", nullptr, nullptr);
if (nullptr == window)
{
cout << "GLFW create window failed!" << endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetKeyCallback(window, key_callback);
glfwSetCursorPosCallback(window, mouse_callback);
glfwSetScrollCallback(window, scroll_callback);
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
glewExperimental = GL_TRUE;
GLenum glewErr = glewInit();
if (GLEW_OK != glewErr)
{
cout << "GLEW initialization failed!" << endl;
return -1;
}
const GLubyte *renderer = glGetString(GL_RENDERER);
const GLubyte *vendor = glGetString(GL_VENDOR);
const GLubyte *version = glGetString(GL_VERSION);
const GLubyte *glslVersion =
glGetString(GL_SHADING_LANGUAGE_VERSION);
GLint major, minor;
glGetIntegerv(GL_MAJOR_VERSION, &major);
glGetIntegerv(GL_MINOR_VERSION, &minor);
printf("GL Vendor : %s\n", vendor);
printf("GL Renderer : %s\n", renderer);
printf("GL Version (string) : %s\n", version);
printf("GL Version (integer) : %d.%d\n", major, minor);
printf("GLSL Version : %s\n", glslVersion);
glGetError(); // Debug GLEW bug fix
glViewport(0, 0, screenWidth, screenHeight);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
Shader shader("6.3.cubemaps.vs", "6.3.cubemaps.fs");
Shader skyboxShader("6.1.skybox.vs", "6.1.skybox.fs");
GLfloat skyboxVertices[] = {
// Positions
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f
};
GLuint skyboxVAO, skyboxVBO;
glGenVertexArrays(1, &skyboxVAO);
glGenBuffers(1, &skyboxVBO);
glBindVertexArray(skyboxVAO);
glBindBuffer(GL_ARRAY_BUFFER, skyboxVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glBindVertexArray(0);
vector<const GLchar*> faces;
faces.push_back("resources/textures/skybox/right.jpg");
faces.push_back("resources/textures/skybox/left.jpg");
faces.push_back("resources/textures/skybox/top.jpg");
faces.push_back("resources/textures/skybox/bottom.jpg");
faces.push_back("resources/textures/skybox/front.jpg");
faces.push_back("resources/textures/skybox/back.jpg");
GLuint skyboxTextures = loadCubemap(faces);
Model nanosuit("resources/objects/nanosuit/nanosuit.obj");
//绘制线框
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
while (!glfwWindowShouldClose(window))
{
GLfloat currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
glfwPollEvents();
do_movement();
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shader.use();
glm::mat4 model = glm::mat4(1.0f);
glm::mat4 view = glm::mat4(1.0f);
glm::mat4 projection = glm::mat4(1.0f);
view = camera.GetViewMatrix();
projection = glm::perspective(camera.Zoom, (GLfloat)screenWidth / (GLfloat)screenHeight, 0.0001f, 10000.0f);
shader.setMat4("model", model);
shader.setMat4("view", view);
shader.setMat4("projection", projection);
shader.setVec3("cameraPos", glm::vec3(camera.Position.x, camera.Position.y, camera.Position.z));
//我们已经有3个纹理单元处于活动状态(在该着色器中),
//因此将skybox设置为第4个纹理单元(纹理单位基于0,因此索引编号为3)
glActiveTexture(GL_TEXTURE3);
shader.setInt("skybox", 3);
// Now draw the nanosuit
glBindTexture(GL_TEXTURE_CUBE_MAP, skyboxTextures);
nanosuit.Draw(shader);
//draw skybox
glDepthFunc(GL_LEQUAL);
skyboxShader.use();
view = glm::mat4(glm::mat3(camera.GetViewMatrix()));
skyboxShader.setMat4("view", view);
skyboxShader.setMat4("projection", projection);
//skybox cube
glBindVertexArray(skyboxVAO);
glActiveTexture(GL_TEXTURE0);
skyboxShader.setInt("skybox", 0);
glBindTexture(GL_TEXTURE_CUBE_MAP, skyboxTextures);
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);
// Set depth function back to default
glDepthFunc(GL_LESS);
glfwSwapBuffers(window);
}
glDeleteVertexArrays(1, &skyboxVAO);
glDeleteBuffers(1, &skyboxVBO);
glfwTerminate();
return 0;
}
// Loads a cubemap texture from 6 individual texture faces
// Order should be:
// +X (right)
// -X (left)
// +Y (top)
// -Y (bottom)
// +Z (front)
// -Z (back)
GLuint loadCubemap(vector<const GLchar *> faces)
{
GLuint textureId;
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_CUBE_MAP, textureId);
int width, height;
unsigned char *image = nullptr;
for (GLuint i = 0; i < faces.size(); i++)
{
image = SOIL_load_image(faces[i], &width, &height, 0, SOIL_LOAD_RGB);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
SOIL_free_image_data(image);
}
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
return textureId;
}
// This function loads a texture from file. Note: texture loading functions like these are usually
// managed by a 'Resource Manager' that manages all resources (like textures, models, audio).
// For learning purposes we'll just define it as a utility function.
GLuint loadTexture(GLchar *path, GLboolean alpha /* = GL_FALSE */)
{
GLuint textureId;
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
int width, height;
unsigned char * image = SOIL_load_image(path, &width, &height, 0, SOIL_LOAD_RGB);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
SOIL_free_image_data(image);
return textureId;
}
void do_movement()
{
if (keys[GLFW_KEY_W])
{
camera.ProcessKeyboard(FORWARD, deltaTime);
}
if (keys[GLFW_KEY_S])
{
camera.ProcessKeyboard(BACKWARD, deltaTime);
}
if (keys[GLFW_KEY_A])
{
camera.ProcessKeyboard(LEFT, deltaTime);
}
if (keys[GLFW_KEY_D])
{
camera.ProcessKeyboard(RIGHT, deltaTime);
}
}
void key_callback(GLFWwindow *window, int key, int scancode, int action, int mode)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
{
glfwSetWindowShouldClose(window, GL_TRUE);
}
if (action == GLFW_PRESS)
{
keys[key] = GL_TRUE;
}
else if (action == GLFW_RELEASE)
{
keys[key] = GL_FALSE;
}
}
void mouse_callback(GLFWwindow *window, double xPos, double yPos)
{
if (!firstMouse)
{
lastX = xPos;
lastY = yPos;
firstMouse = GL_TRUE;
}
GLfloat xOffset = xPos - lastX;
GLfloat yOffset = lastY - yPos;
lastX = xPos;
lastY = yPos;
camera.ProcessMouseMovement(xOffset, yOffset);
}
void scroll_callback(GLFWwindow *window, double xPos, double yPos)
{
camera.ProcessMouseScroll(yPos);
}