mirror of
https://github.com/JoeyDeVries/LearnOpenGL.git
synced 2026-01-30 20:13:22 +08:00
Start code re-work Advanced OpenGL chapter.
This commit is contained in:
@@ -1,88 +1,89 @@
|
||||
// Std. Includes
|
||||
#include <string>
|
||||
|
||||
// GLEW
|
||||
#define GLEW_STATIC
|
||||
#include <GL/glew.h>
|
||||
|
||||
// GLFW
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <stb_image.h>
|
||||
|
||||
// GL includes
|
||||
#include <learnopengl/shader.h>
|
||||
#include <learnopengl/camera.h>
|
||||
|
||||
// GLM Mathemtics
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
// Other Libs
|
||||
#include <SOIL.h>
|
||||
#include <learnopengl/filesystem.h>
|
||||
#include <learnopengl/shader_m.h>
|
||||
#include <learnopengl/camera.h>
|
||||
#include <learnopengl/model.h>
|
||||
|
||||
// Properties
|
||||
GLuint screenWidth = 800, screenHeight = 600;
|
||||
#include <iostream>
|
||||
|
||||
// Function prototypes
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
|
||||
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
|
||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
|
||||
void Do_Movement();
|
||||
GLuint loadTexture(GLchar const * path);
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
|
||||
void processInput(GLFWwindow *window);
|
||||
unsigned int loadTexture(const char *path);
|
||||
|
||||
// Camera
|
||||
// settings
|
||||
const unsigned int SCR_WIDTH = 1280;
|
||||
const unsigned int SCR_HEIGHT = 720;
|
||||
|
||||
// camera
|
||||
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
|
||||
bool keys[1024];
|
||||
GLfloat lastX = 400, lastY = 300;
|
||||
float lastX = (float)SCR_WIDTH / 2.0;
|
||||
float lastY = (float)SCR_HEIGHT / 2.0;
|
||||
bool firstMouse = true;
|
||||
|
||||
GLfloat deltaTime = 0.0f;
|
||||
GLfloat lastFrame = 0.0f;
|
||||
// timing
|
||||
float deltaTime = 0.0f;
|
||||
float lastFrame = 0.0f;
|
||||
|
||||
// The MAIN function, from here we start our application and run our Game loop
|
||||
int main()
|
||||
{
|
||||
// Init GLFW
|
||||
// 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);
|
||||
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
|
||||
|
||||
GLFWwindow* window = glfwCreateWindow(screenWidth, screenHeight, "LearnOpenGL", nullptr, nullptr); // Windowed
|
||||
// glfw window creation
|
||||
// --------------------
|
||||
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
// Set the required callback functions
|
||||
glfwSetKeyCallback(window, key_callback);
|
||||
if (window == NULL)
|
||||
{
|
||||
std::cout << "Failed to create GLFW window" << std::endl;
|
||||
glfwTerminate();
|
||||
return -1;
|
||||
}
|
||||
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
|
||||
glfwSetCursorPosCallback(window, mouse_callback);
|
||||
glfwSetScrollCallback(window, scroll_callback);
|
||||
|
||||
// Options
|
||||
// tell GLFW to capture our mouse
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
|
||||
// Initialize GLEW to setup the OpenGL Function pointers
|
||||
glewExperimental = GL_TRUE;
|
||||
glewInit();
|
||||
// glad: load all OpenGL function pointers
|
||||
// ---------------------------------------
|
||||
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
|
||||
{
|
||||
std::cout << "Failed to initialize GLAD" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Define the viewport dimensions
|
||||
glViewport(0, 0, screenWidth, screenHeight);
|
||||
|
||||
// Setup some OpenGL options
|
||||
// configure global opengl state
|
||||
// -----------------------------
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LESS);
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
||||
|
||||
// Setup and compile our shaders
|
||||
Shader shader("stencil_testing.vs", "stencil_testing.frag");
|
||||
Shader shaderSingleColor("stencil_testing.vs", "stencil_single_color.frag");
|
||||
// build and compile shaders
|
||||
// -------------------------
|
||||
Shader shader("2.stencil_testing.vs", "2.stencil_testing.fs");
|
||||
Shader shaderSingleColor("2.stencil_testing.vs", "2.stencil_single_color.fs");
|
||||
|
||||
#pragma region "object_initialization"
|
||||
// Set the object data (buffers, vertex attributes)
|
||||
GLfloat cubeVertices[] = {
|
||||
// Positions // Texture Coords
|
||||
// set up vertex data (and buffer(s)) and configure vertex attributes
|
||||
// ------------------------------------------------------------------
|
||||
float cubeVertices[] = {
|
||||
// positions // texture Coords
|
||||
-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,
|
||||
@@ -125,214 +126,240 @@ int main()
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f
|
||||
};
|
||||
GLfloat planeVertices[] = {
|
||||
// Positions // Texture Coords (note we set these higher than 1 that together with GL_REPEAT (as texture wrapping mode) will cause the floor texture to repeat)
|
||||
5.0f, -0.5f, 5.0f, 2.0f, 0.0f,
|
||||
float planeVertices[] = {
|
||||
// positions // texture Coords (note we set these higher than 1 (together with GL_REPEAT as texture wrapping mode). this will cause the floor texture to repeat)
|
||||
5.0f, -0.5f, 5.0f, 2.0f, 0.0f,
|
||||
-5.0f, -0.5f, 5.0f, 0.0f, 0.0f,
|
||||
-5.0f, -0.5f, -5.0f, 0.0f, 2.0f,
|
||||
|
||||
5.0f, -0.5f, 5.0f, 2.0f, 0.0f,
|
||||
5.0f, -0.5f, 5.0f, 2.0f, 0.0f,
|
||||
-5.0f, -0.5f, -5.0f, 0.0f, 2.0f,
|
||||
5.0f, -0.5f, -5.0f, 2.0f, 2.0f
|
||||
5.0f, -0.5f, -5.0f, 2.0f, 2.0f
|
||||
};
|
||||
// Setup cube VAO
|
||||
GLuint cubeVAO, cubeVBO;
|
||||
// cube VAO
|
||||
unsigned int cubeVAO, cubeVBO;
|
||||
glGenVertexArrays(1, &cubeVAO);
|
||||
glGenBuffers(1, &cubeVBO);
|
||||
glBindVertexArray(cubeVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), &cubeVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
|
||||
glBindVertexArray(0);
|
||||
// Setup plane VAO
|
||||
GLuint planeVAO, planeVBO;
|
||||
// plane VAO
|
||||
unsigned int planeVAO, planeVBO;
|
||||
glGenVertexArrays(1, &planeVAO);
|
||||
glGenBuffers(1, &planeVBO);
|
||||
glBindVertexArray(planeVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, planeVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(planeVertices), &planeVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
|
||||
glBindVertexArray(0);
|
||||
|
||||
// Load textures
|
||||
GLuint cubeTexture = loadTexture(FileSystem::getPath("resources/textures/marble.jpg").c_str());
|
||||
GLuint floorTexture = loadTexture(FileSystem::getPath("resources/textures/metal.png").c_str());
|
||||
#pragma endregion
|
||||
// load textures
|
||||
// -------------
|
||||
unsigned int cubeTexture = loadTexture(FileSystem::getPath("resources/textures/marble.jpg").c_str());
|
||||
unsigned int floorTexture = loadTexture(FileSystem::getPath("resources/textures/metal.png").c_str());
|
||||
|
||||
// Game loop
|
||||
while(!glfwWindowShouldClose(window))
|
||||
// shader configuration
|
||||
// --------------------
|
||||
shader.use();
|
||||
shader.setInt("ourTexture", 0);
|
||||
|
||||
// render loop
|
||||
// -----------
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
// Set frame time
|
||||
GLfloat currentFrame = glfwGetTime();
|
||||
// per-frame time logic
|
||||
// --------------------
|
||||
float currentFrame = glfwGetTime();
|
||||
deltaTime = currentFrame - lastFrame;
|
||||
lastFrame = currentFrame;
|
||||
|
||||
// Check and call events
|
||||
glfwPollEvents();
|
||||
Do_Movement();
|
||||
// input
|
||||
// -----
|
||||
processInput(window);
|
||||
|
||||
// Clear the colorbuffer
|
||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
// render
|
||||
// ------
|
||||
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // don't forget to clear the stencil buffer!
|
||||
|
||||
// Set uniforms
|
||||
shaderSingleColor.Use();
|
||||
// set uniforms
|
||||
shaderSingleColor.use();
|
||||
glm::mat4 model;
|
||||
glm::mat4 view = camera.GetViewMatrix();
|
||||
glm::mat4 projection = glm::perspective(camera.Zoom, (float)screenWidth/(float)screenHeight, 0.1f, 100.0f);
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderSingleColor.Program, "view"), 1, GL_FALSE, glm::value_ptr(view));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderSingleColor.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
|
||||
shader.Use();
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
|
||||
glm::mat4 projection = glm::perspective(camera.Zoom, (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
|
||||
shader.setMat4("view", view);
|
||||
shader.setMat4("projection", projection);
|
||||
|
||||
shader.use();
|
||||
shader.setMat4("view", view);
|
||||
shader.setMat4("projection", projection);
|
||||
|
||||
// Draw floor as normal, we only care about the containers. The floor should NOT fill the stencil buffer so we set its mask to 0x00
|
||||
// draw floor as normal, but don't write the floor to the stencil buffer, we only care about the containers. We set its mask to 0x00 to not write to the stencil buffer.
|
||||
glStencilMask(0x00);
|
||||
// Floor
|
||||
// floor
|
||||
glBindVertexArray(planeVAO);
|
||||
glBindTexture(GL_TEXTURE_2D, floorTexture);
|
||||
model = glm::mat4();
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
glBindVertexArray(0);
|
||||
shader.setMat4("model", glm::mat4());
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
glBindVertexArray(0);
|
||||
|
||||
// == =============
|
||||
// 1st. Render pass, draw objects as normal, filling the stencil buffer
|
||||
// 1st. render pass, draw objects as normal, writing to the stencil buffer
|
||||
// --------------------------------------------------------------------
|
||||
glStencilFunc(GL_ALWAYS, 1, 0xFF);
|
||||
glStencilMask(0xFF);
|
||||
// Cubes
|
||||
glStencilMask(0xFF);
|
||||
// cubes
|
||||
glBindVertexArray(cubeVAO);
|
||||
glBindTexture(GL_TEXTURE_2D, cubeTexture);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, cubeTexture);
|
||||
model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||
shader.setMat4("model", model);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
model = glm::mat4();
|
||||
model = glm::translate(model, glm::vec3(2.0f, 0.0f, 0.0f));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||
shader.setMat4("model", model);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
glBindVertexArray(0);
|
||||
|
||||
// == =============
|
||||
// 2nd. Render pass, now draw slightly scaled versions of the objects, this time disabling stencil writing.
|
||||
// Because stencil buffer is now filled with several 1s. The parts of the buffer that are 1 are now not drawn, thus only drawing
|
||||
// 2nd. render pass: now draw slightly scaled versions of the objects, this time disabling stencil writing.
|
||||
// Because the stencil buffer is now filled with several 1s. The parts of the buffer that are 1 are not drawn, thus only drawing
|
||||
// the objects' size differences, making it look like borders.
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
|
||||
glStencilMask(0x00);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
shaderSingleColor.Use();
|
||||
GLfloat scale = 1.1;
|
||||
// Cubes
|
||||
shaderSingleColor.use();
|
||||
float scale = 1.1;
|
||||
// cubes
|
||||
glBindVertexArray(cubeVAO);
|
||||
glBindTexture(GL_TEXTURE_2D, cubeTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, cubeTexture);
|
||||
model = glm::mat4();
|
||||
model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f));
|
||||
model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f));
|
||||
model = glm::scale(model, glm::vec3(scale, scale, scale));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderSingleColor.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||
shader.setMat4("model", model);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
model = glm::mat4();
|
||||
model = glm::translate(model, glm::vec3(2.0f, 0.0f, 0.0f));
|
||||
model = glm::mat4();
|
||||
model = glm::translate(model, glm::vec3(2.0f, 0.0f, 0.0f));
|
||||
model = glm::scale(model, glm::vec3(scale, scale, scale));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderSingleColor.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||
shader.setMat4("model", model);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
glBindVertexArray(0);
|
||||
glBindVertexArray(0);
|
||||
glStencilMask(0xFF);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
// Swap the buffers
|
||||
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
|
||||
// -------------------------------------------------------------------------------
|
||||
glfwSwapBuffers(window);
|
||||
glfwPollEvents();
|
||||
}
|
||||
|
||||
// optional: de-allocate all resources once they've outlived their purpose:
|
||||
// ------------------------------------------------------------------------
|
||||
glDeleteVertexArrays(1, &cubeVAO);
|
||||
glDeleteVertexArrays(1, &planeVAO);
|
||||
glDeleteBuffers(1, &cubeVBO);
|
||||
glDeleteBuffers(1, &planeVBO);
|
||||
|
||||
glfwTerminate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DrawScene()
|
||||
// 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);
|
||||
|
||||
}
|
||||
|
||||
// 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 const * path)
|
||||
{
|
||||
//Generate texture ID and load texture data
|
||||
GLuint textureID;
|
||||
glGenTextures(1, &textureID);
|
||||
int width,height;
|
||||
unsigned char* image = SOIL_load_image(path, &width, &height, 0, SOIL_LOAD_RGB);
|
||||
// Assign texture to ID
|
||||
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
// Parameters
|
||||
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_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
SOIL_free_image_data(image);
|
||||
return textureID;
|
||||
|
||||
}
|
||||
|
||||
#pragma region "User input"
|
||||
|
||||
// Moves/alters the camera positions based on user input
|
||||
void Do_Movement()
|
||||
{
|
||||
// Camera controls
|
||||
if(keys[GLFW_KEY_W])
|
||||
float cameraSpeed = 2.5 * deltaTime;
|
||||
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
|
||||
camera.ProcessKeyboard(FORWARD, deltaTime);
|
||||
if(keys[GLFW_KEY_S])
|
||||
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
|
||||
camera.ProcessKeyboard(BACKWARD, deltaTime);
|
||||
if(keys[GLFW_KEY_A])
|
||||
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
|
||||
camera.ProcessKeyboard(LEFT, deltaTime);
|
||||
if(keys[GLFW_KEY_D])
|
||||
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
|
||||
camera.ProcessKeyboard(RIGHT, deltaTime);
|
||||
}
|
||||
|
||||
// Is called whenever a key is pressed/released via GLFW
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
|
||||
// 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)
|
||||
{
|
||||
if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
|
||||
glfwSetWindowShouldClose(window, GL_TRUE);
|
||||
|
||||
if(action == GLFW_PRESS)
|
||||
keys[key] = true;
|
||||
else if(action == GLFW_RELEASE)
|
||||
keys[key] = false;
|
||||
// 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 xpos, double ypos)
|
||||
{
|
||||
if(firstMouse)
|
||||
if (firstMouse)
|
||||
{
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
firstMouse = false;
|
||||
}
|
||||
|
||||
GLfloat xoffset = xpos - lastX;
|
||||
GLfloat yoffset = lastY - ypos;
|
||||
|
||||
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(yoffset);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
// utility function for loading a 2D texture from file
|
||||
// ---------------------------------------------------
|
||||
unsigned int loadTexture(char const * path)
|
||||
{
|
||||
unsigned int textureID;
|
||||
glGenTextures(1, &textureID);
|
||||
|
||||
int width, height, nrComponents;
|
||||
unsigned char *data = stbi_load(path, &width, &height, &nrComponents, 0);
|
||||
if (data)
|
||||
{
|
||||
GLenum format;
|
||||
if (nrComponents == 1)
|
||||
format = GL_RED;
|
||||
else if (nrComponents == 3)
|
||||
format = GL_RGB;
|
||||
else if (nrComponents == 4)
|
||||
format = GL_RGBA;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
|
||||
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_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
stbi_image_free(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Texture failed to load at path: " << path << std::endl;
|
||||
stbi_image_free(data);
|
||||
}
|
||||
|
||||
return textureID;
|
||||
}
|
||||
Reference in New Issue
Block a user