mirror of
https://github.com/JoeyDeVries/LearnOpenGL.git
synced 2026-01-30 20:13:22 +08:00
Code re-format: lighting.
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
#version 330 core
|
||||
out vec4 color;
|
||||
out vec4 fragColor;
|
||||
|
||||
uniform vec3 objectColor;
|
||||
uniform vec3 lightColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = vec4(lightColor * objectColor, 1.0f);
|
||||
fragColor = vec4(lightColor * objectColor, 1.0f);
|
||||
}
|
||||
11
src/2.lighting/1.colors/1.colors.vs
Normal file
11
src/2.lighting/1.colors/1.colors.vs
Normal file
@@ -0,0 +1,11 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 aPos;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projection * view * model * vec4(aPos, 1.0f);
|
||||
}
|
||||
7
src/2.lighting/1.colors/1.lamp.fs
Normal file
7
src/2.lighting/1.colors/1.lamp.fs
Normal file
@@ -0,0 +1,7 @@
|
||||
#version 330 core
|
||||
out vec4 fragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
fragColor = vec4(1.0f); // set alle 4 vector values to 1.0f
|
||||
}
|
||||
11
src/2.lighting/1.colors/1.lamp.vs
Normal file
11
src/2.lighting/1.colors/1.lamp.vs
Normal file
@@ -0,0 +1,11 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 aPos;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projection * view * model * vec4(aPos, 1.0f);
|
||||
}
|
||||
270
src/2.lighting/1.colors/colors.cpp
Normal file
270
src/2.lighting/1.colors/colors.cpp
Normal file
@@ -0,0 +1,270 @@
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <stb_image.h>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
#include <learnopengl/filesystem.h>
|
||||
#include <learnopengl/shader_m.h>
|
||||
#include <learnopengl/camera.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
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);
|
||||
|
||||
// camera
|
||||
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
|
||||
float lastX = 800.0f / 2.0;
|
||||
float lastY = 600.0 / 2.0;
|
||||
bool firstMouse = true;
|
||||
|
||||
float deltaTime = 0.0f; // time between current frame and last frame
|
||||
float lastFrame = 0.0f;
|
||||
|
||||
// lighting
|
||||
glm::vec3 lightPos(1.2f, 1.0f, 2.0f);
|
||||
|
||||
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);
|
||||
//glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X
|
||||
|
||||
// glfw window creation
|
||||
// --------------------
|
||||
GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL);
|
||||
glfwMakeContextCurrent(window);
|
||||
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);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// configure global opengl state
|
||||
// -----------------------------
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
// build and compile our shader zprogram
|
||||
// ------------------------------------
|
||||
Shader lightingShader("1.colors.vs", "1.colors.fs");
|
||||
Shader lampShader("1.lamp.vs", "1.lamp.fs");
|
||||
|
||||
// set up vertex data (and buffer(s)) and configure vertex attributes
|
||||
// ------------------------------------------------------------------
|
||||
float vertices[] = {
|
||||
-0.5f, -0.5f, -0.5f,
|
||||
0.5f, -0.5f, -0.5f,
|
||||
0.5f, 0.5f, -0.5f,
|
||||
0.5f, 0.5f, -0.5f,
|
||||
-0.5f, 0.5f, -0.5f,
|
||||
-0.5f, -0.5f, -0.5f,
|
||||
|
||||
-0.5f, -0.5f, 0.5f,
|
||||
0.5f, -0.5f, 0.5f,
|
||||
0.5f, 0.5f, 0.5f,
|
||||
0.5f, 0.5f, 0.5f,
|
||||
-0.5f, 0.5f, 0.5f,
|
||||
-0.5f, -0.5f, 0.5f,
|
||||
|
||||
-0.5f, 0.5f, 0.5f,
|
||||
-0.5f, 0.5f, -0.5f,
|
||||
-0.5f, -0.5f, -0.5f,
|
||||
-0.5f, -0.5f, -0.5f,
|
||||
-0.5f, -0.5f, 0.5f,
|
||||
-0.5f, 0.5f, 0.5f,
|
||||
|
||||
0.5f, 0.5f, 0.5f,
|
||||
0.5f, 0.5f, -0.5f,
|
||||
0.5f, -0.5f, -0.5f,
|
||||
0.5f, -0.5f, -0.5f,
|
||||
0.5f, -0.5f, 0.5f,
|
||||
0.5f, 0.5f, 0.5f,
|
||||
|
||||
-0.5f, -0.5f, -0.5f,
|
||||
0.5f, -0.5f, -0.5f,
|
||||
0.5f, -0.5f, 0.5f,
|
||||
0.5f, -0.5f, 0.5f,
|
||||
-0.5f, -0.5f, 0.5f,
|
||||
-0.5f, -0.5f, -0.5f,
|
||||
|
||||
-0.5f, 0.5f, -0.5f,
|
||||
0.5f, 0.5f, -0.5f,
|
||||
0.5f, 0.5f, 0.5f,
|
||||
0.5f, 0.5f, 0.5f,
|
||||
-0.5f, 0.5f, 0.5f,
|
||||
-0.5f, 0.5f, -0.5f,
|
||||
};
|
||||
// first, configure the cube's VAO (and VBO)
|
||||
unsigned int VBO, cubeVAO;
|
||||
glGenVertexArrays(1, &cubeVAO);
|
||||
glGenBuffers(1, &VBO);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||
|
||||
glBindVertexArray(cubeVAO);
|
||||
|
||||
// position attribute
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
// 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 lightVAO;
|
||||
glGenVertexArrays(1, &lightVAO);
|
||||
glBindVertexArray(lightVAO);
|
||||
|
||||
// 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, 3 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
|
||||
// render loop
|
||||
// -----------
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
// per-frame time logic
|
||||
// --------------------
|
||||
float currentFrame = glfwGetTime();
|
||||
deltaTime = currentFrame - lastFrame;
|
||||
lastFrame = currentFrame;
|
||||
|
||||
// input
|
||||
// -----
|
||||
processInput(window);
|
||||
|
||||
// render
|
||||
// ------
|
||||
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// be sure to activate shader when setting uniforms/drawing objects
|
||||
lightingShader.use();
|
||||
lightingShader.setVec3("objectColor", 1.0f, 0.5f, 0.31f);
|
||||
lightingShader.setVec3("lightColor", 1.0f, 1.0f, 1.0f);
|
||||
|
||||
// view/projection transformations
|
||||
glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), 800.0f / 600.0f, 0.1f, 100.0f);
|
||||
glm::mat4 view = camera.GetViewMatrix();
|
||||
lightingShader.setMat4("projection", projection);
|
||||
lightingShader.setMat4("view", view);
|
||||
|
||||
// world transformation
|
||||
glm::mat4 model;
|
||||
lightingShader.setMat4("model", model);
|
||||
|
||||
// render the cube
|
||||
glBindVertexArray(cubeVAO);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
|
||||
|
||||
// also draw the lamp object
|
||||
lampShader.use();
|
||||
lampShader.setMat4("projection", projection);
|
||||
lampShader.setMat4("view", view);
|
||||
model = glm::mat4();
|
||||
model = glm::translate(model, lightPos);
|
||||
model = glm::scale(model, glm::vec3(0.2f)); // a smaller cube
|
||||
lampShader.setMat4("model", model);
|
||||
|
||||
glBindVertexArray(lightVAO);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
|
||||
|
||||
// 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, &lightVAO);
|
||||
glDeleteBuffers(1, &VBO);
|
||||
|
||||
// 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);
|
||||
|
||||
float cameraSpeed = 2.5 * deltaTime;
|
||||
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 xpos, double ypos)
|
||||
{
|
||||
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(yoffset);
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 position;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projection * view * model * vec4(position, 1.0f);
|
||||
}
|
||||
@@ -1,272 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
|
||||
// GLEW
|
||||
#define GLEW_STATIC
|
||||
#include <GL/glew.h>
|
||||
|
||||
// GLFW
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
// Other Libs
|
||||
#include <SOIL.h>
|
||||
// GLM Mathematics
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
// Other includes
|
||||
#include <learnopengl/shader.h>
|
||||
#include <learnopengl/camera.h>
|
||||
|
||||
|
||||
// Function prototypes
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
|
||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
|
||||
void do_movement();
|
||||
|
||||
// Window dimensions
|
||||
const GLuint WIDTH = 800, HEIGHT = 600;
|
||||
|
||||
// Camera
|
||||
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
|
||||
GLfloat lastX = WIDTH / 2.0;
|
||||
GLfloat lastY = HEIGHT / 2.0;
|
||||
bool keys[1024];
|
||||
|
||||
// Light attributes
|
||||
glm::vec3 lightPos(1.2f, 1.0f, 2.0f);
|
||||
|
||||
// Deltatime
|
||||
GLfloat deltaTime = 0.0f; // Time between current frame and last frame
|
||||
GLfloat lastFrame = 0.0f; // Time of last frame
|
||||
|
||||
// The MAIN function, from here we start the application and run the game loop
|
||||
int main()
|
||||
{
|
||||
// Init GLFW
|
||||
glfwInit();
|
||||
// Set all the required options for GLFW
|
||||
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);
|
||||
|
||||
// Create a GLFWwindow object that we can use for GLFW's functions
|
||||
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr);
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
// Set the required callback functions
|
||||
glfwSetKeyCallback(window, key_callback);
|
||||
glfwSetCursorPosCallback(window, mouse_callback);
|
||||
glfwSetScrollCallback(window, scroll_callback);
|
||||
|
||||
// GLFW Options
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
|
||||
// Set this to true so GLEW knows to use a modern approach to retrieving function pointers and extensions
|
||||
glewExperimental = GL_TRUE;
|
||||
// Initialize GLEW to setup the OpenGL Function pointers
|
||||
glewInit();
|
||||
|
||||
// Define the viewport dimensions
|
||||
glViewport(0, 0, WIDTH, HEIGHT);
|
||||
|
||||
// OpenGL options
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
|
||||
// Build and compile our shader program
|
||||
Shader lightingShader("colors.vs", "colors.frag");
|
||||
Shader lampShader("lamp.vs", "lamp.frag");
|
||||
|
||||
// Set up vertex data (and buffer(s)) and attribute pointers
|
||||
GLfloat vertices[] = {
|
||||
-0.5f, -0.5f, -0.5f,
|
||||
0.5f, -0.5f, -0.5f,
|
||||
0.5f, 0.5f, -0.5f,
|
||||
0.5f, 0.5f, -0.5f,
|
||||
-0.5f, 0.5f, -0.5f,
|
||||
-0.5f, -0.5f, -0.5f,
|
||||
|
||||
-0.5f, -0.5f, 0.5f,
|
||||
0.5f, -0.5f, 0.5f,
|
||||
0.5f, 0.5f, 0.5f,
|
||||
0.5f, 0.5f, 0.5f,
|
||||
-0.5f, 0.5f, 0.5f,
|
||||
-0.5f, -0.5f, 0.5f,
|
||||
|
||||
-0.5f, 0.5f, 0.5f,
|
||||
-0.5f, 0.5f, -0.5f,
|
||||
-0.5f, -0.5f, -0.5f,
|
||||
-0.5f, -0.5f, -0.5f,
|
||||
-0.5f, -0.5f, 0.5f,
|
||||
-0.5f, 0.5f, 0.5f,
|
||||
|
||||
0.5f, 0.5f, 0.5f,
|
||||
0.5f, 0.5f, -0.5f,
|
||||
0.5f, -0.5f, -0.5f,
|
||||
0.5f, -0.5f, -0.5f,
|
||||
0.5f, -0.5f, 0.5f,
|
||||
0.5f, 0.5f, 0.5f,
|
||||
|
||||
-0.5f, -0.5f, -0.5f,
|
||||
0.5f, -0.5f, -0.5f,
|
||||
0.5f, -0.5f, 0.5f,
|
||||
0.5f, -0.5f, 0.5f,
|
||||
-0.5f, -0.5f, 0.5f,
|
||||
-0.5f, -0.5f, -0.5f,
|
||||
|
||||
-0.5f, 0.5f, -0.5f,
|
||||
0.5f, 0.5f, -0.5f,
|
||||
0.5f, 0.5f, 0.5f,
|
||||
0.5f, 0.5f, 0.5f,
|
||||
-0.5f, 0.5f, 0.5f,
|
||||
-0.5f, 0.5f, -0.5f
|
||||
};
|
||||
// First, set the container's VAO (and VBO)
|
||||
GLuint VBO, containerVAO;
|
||||
glGenVertexArrays(1, &containerVAO);
|
||||
glGenBuffers(1, &VBO);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||
|
||||
glBindVertexArray(containerVAO);
|
||||
// Position attribute
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
glBindVertexArray(0);
|
||||
|
||||
// Then, we set the light's VAO (VBO stays the same. After all, the vertices are the same for the light object (also a 3D cube))
|
||||
GLuint lightVAO;
|
||||
glGenVertexArrays(1, &lightVAO);
|
||||
glBindVertexArray(lightVAO);
|
||||
// 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.
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
// Set the vertex attributes (only position data for the lamp))
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
glBindVertexArray(0);
|
||||
|
||||
|
||||
// Game loop
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
// Calculate deltatime of current frame
|
||||
GLfloat currentFrame = glfwGetTime();
|
||||
deltaTime = currentFrame - lastFrame;
|
||||
lastFrame = currentFrame;
|
||||
|
||||
// Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functions
|
||||
glfwPollEvents();
|
||||
do_movement();
|
||||
|
||||
// Clear the colorbuffer
|
||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// Use cooresponding shader when setting uniforms/drawing objects
|
||||
lightingShader.Use();
|
||||
GLint objectColorLoc = glGetUniformLocation(lightingShader.Program, "objectColor");
|
||||
GLint lightColorLoc = glGetUniformLocation(lightingShader.Program, "lightColor");
|
||||
glUniform3f(objectColorLoc, 1.0f, 0.5f, 0.31f);
|
||||
glUniform3f(lightColorLoc, 1.0f, 0.5f, 1.0f);
|
||||
|
||||
// Create camera transformations
|
||||
glm::mat4 view;
|
||||
view = camera.GetViewMatrix();
|
||||
glm::mat4 projection = glm::perspective(camera.Zoom, (GLfloat)WIDTH / (GLfloat)HEIGHT, 0.1f, 100.0f);
|
||||
// Get the uniform locations
|
||||
GLint modelLoc = glGetUniformLocation(lightingShader.Program, "model");
|
||||
GLint viewLoc = glGetUniformLocation(lightingShader.Program, "view");
|
||||
GLint projLoc = glGetUniformLocation(lightingShader.Program, "projection");
|
||||
// Pass the matrices to the shader
|
||||
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
|
||||
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
|
||||
|
||||
// Draw the container (using container's vertex attributes)
|
||||
glBindVertexArray(containerVAO);
|
||||
glm::mat4 model;
|
||||
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
glBindVertexArray(0);
|
||||
|
||||
// Also draw the lamp object, again binding the appropriate shader
|
||||
lampShader.Use();
|
||||
// Get location objects for the matrices on the lamp shader (these could be different on a different shader)
|
||||
modelLoc = glGetUniformLocation(lampShader.Program, "model");
|
||||
viewLoc = glGetUniformLocation(lampShader.Program, "view");
|
||||
projLoc = glGetUniformLocation(lampShader.Program, "projection");
|
||||
// Set matrices
|
||||
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
|
||||
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
|
||||
model = glm::mat4();
|
||||
model = glm::translate(model, lightPos);
|
||||
model = glm::scale(model, glm::vec3(0.2f)); // Make it a smaller cube
|
||||
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
|
||||
// Draw the light object (using light's vertex attributes)
|
||||
glBindVertexArray(lightVAO);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
glBindVertexArray(0);
|
||||
|
||||
// Swap the screen buffers
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
|
||||
// Terminate GLFW, clearing any resources allocated by GLFW.
|
||||
glfwTerminate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Is called whenever a key is pressed/released via GLFW
|
||||
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 (key >= 0 && key < 1024)
|
||||
{
|
||||
if (action == GLFW_PRESS)
|
||||
keys[key] = true;
|
||||
else if (action == GLFW_RELEASE)
|
||||
keys[key] = false;
|
||||
}
|
||||
}
|
||||
|
||||
void do_movement()
|
||||
{
|
||||
// Camera controls
|
||||
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);
|
||||
}
|
||||
|
||||
bool firstMouse = true;
|
||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
|
||||
{
|
||||
if (firstMouse)
|
||||
{
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
firstMouse = false;
|
||||
}
|
||||
|
||||
GLfloat xoffset = xpos - lastX;
|
||||
GLfloat yoffset = lastY - ypos; // Reversed since y-coordinates go from bottom to left
|
||||
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
|
||||
camera.ProcessMouseMovement(xoffset, yoffset);
|
||||
}
|
||||
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
|
||||
{
|
||||
camera.ProcessMouseScroll(yoffset);
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
#version 330 core
|
||||
out vec4 color;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = vec4(1.0f); // Set alle 4 vector values to 1.0f
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 position;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projection * view * model * vec4(position, 1.0f);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#version 330 core
|
||||
out vec4 fragColor;
|
||||
|
||||
in vec3 Normal;
|
||||
in vec3 FragPos;
|
||||
|
||||
uniform vec3 lightPos;
|
||||
uniform vec3 lightColor;
|
||||
uniform vec3 objectColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
// ambient
|
||||
float ambientStrength = 0.1f;
|
||||
vec3 ambient = ambientStrength * lightColor;
|
||||
|
||||
// diffuse
|
||||
vec3 norm = normalize(Normal);
|
||||
vec3 lightDir = normalize(lightPos - FragPos);
|
||||
float diff = max(dot(norm, lightDir), 0.0f);
|
||||
vec3 diffuse = diff * lightColor;
|
||||
|
||||
vec3 result = (ambient + diffuse) * objectColor;
|
||||
fragColor = vec4(result, 1.0f);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 aPos;
|
||||
layout (location = 1) in vec3 aNormal;
|
||||
|
||||
out vec3 FragPos;
|
||||
out vec3 Normal;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
|
||||
void main()
|
||||
{
|
||||
FragPos = vec3(model * vec4(aPos, 1.0f));
|
||||
Normal = aNormal;
|
||||
|
||||
gl_Position = projection * view * vec4(FragPos, 1.0f);
|
||||
}
|
||||
@@ -0,0 +1,274 @@
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <stb_image.h>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
#include <learnopengl/filesystem.h>
|
||||
#include <learnopengl/shader_m.h>
|
||||
#include <learnopengl/camera.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
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);
|
||||
|
||||
// camera
|
||||
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
|
||||
float lastX = 800.0f / 2.0;
|
||||
float lastY = 600.0 / 2.0;
|
||||
bool firstMouse = true;
|
||||
|
||||
float deltaTime = 0.0f; // time between current frame and last frame
|
||||
float lastFrame = 0.0f;
|
||||
|
||||
// lighting
|
||||
glm::vec3 lightPos(1.2f, 1.0f, 2.0f);
|
||||
|
||||
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);
|
||||
//glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X
|
||||
|
||||
// glfw window creation
|
||||
// --------------------
|
||||
GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL);
|
||||
glfwMakeContextCurrent(window);
|
||||
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);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// configure global opengl state
|
||||
// -----------------------------
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
// build and compile our shader zprogram
|
||||
// ------------------------------------
|
||||
Shader lightingShader("2.1.basic_lighting.vs", "2.1.basic_lighting.fs");
|
||||
Shader lampShader("1.lamp.vs", "1.lamp.fs");
|
||||
|
||||
// set up vertex data (and buffer(s)) and configure vertex attributes
|
||||
// ------------------------------------------------------------------
|
||||
float vertices[] = {
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
|
||||
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
|
||||
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
|
||||
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
|
||||
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f
|
||||
};
|
||||
// first, configure the cube's VAO (and VBO)
|
||||
unsigned int VBO, cubeVAO;
|
||||
glGenVertexArrays(1, &cubeVAO);
|
||||
glGenBuffers(1, &VBO);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||
|
||||
glBindVertexArray(cubeVAO);
|
||||
|
||||
// position attribute
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
// normal attribute
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
|
||||
glEnableVertexAttribArray(1);
|
||||
|
||||
|
||||
// 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 lightVAO;
|
||||
glGenVertexArrays(1, &lightVAO);
|
||||
glBindVertexArray(lightVAO);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
// note that we update the lamp's position attribute's stride to reflect the updated buffer data
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
|
||||
// render loop
|
||||
// -----------
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
// per-frame time logic
|
||||
// --------------------
|
||||
float currentFrame = glfwGetTime();
|
||||
deltaTime = currentFrame - lastFrame;
|
||||
lastFrame = currentFrame;
|
||||
|
||||
// input
|
||||
// -----
|
||||
processInput(window);
|
||||
|
||||
// render
|
||||
// ------
|
||||
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// be sure to activate shader when setting uniforms/drawing objects
|
||||
lightingShader.use();
|
||||
lightingShader.setVec3("objectColor", 1.0f, 0.5f, 0.31f);
|
||||
lightingShader.setVec3("lightColor", 1.0f, 1.0f, 1.0f);
|
||||
lightingShader.setVec3("lightPos", lightPos);
|
||||
|
||||
// view/projection transformations
|
||||
glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), 800.0f / 600.0f, 0.1f, 100.0f);
|
||||
glm::mat4 view = camera.GetViewMatrix();
|
||||
lightingShader.setMat4("projection", projection);
|
||||
lightingShader.setMat4("view", view);
|
||||
|
||||
// world transformation
|
||||
glm::mat4 model;
|
||||
lightingShader.setMat4("model", model);
|
||||
|
||||
// render the cube
|
||||
glBindVertexArray(cubeVAO);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
|
||||
|
||||
// also draw the lamp object
|
||||
lampShader.use();
|
||||
lampShader.setMat4("projection", projection);
|
||||
lampShader.setMat4("view", view);
|
||||
model = glm::mat4();
|
||||
model = glm::translate(model, lightPos);
|
||||
model = glm::scale(model, glm::vec3(0.2f)); // a smaller cube
|
||||
lampShader.setMat4("model", model);
|
||||
|
||||
glBindVertexArray(lightVAO);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
|
||||
|
||||
// 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, &lightVAO);
|
||||
glDeleteBuffers(1, &VBO);
|
||||
|
||||
// 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);
|
||||
|
||||
float cameraSpeed = 2.5 * deltaTime;
|
||||
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 xpos, double ypos)
|
||||
{
|
||||
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(yoffset);
|
||||
}
|
||||
@@ -1,27 +1,27 @@
|
||||
#version 330 core
|
||||
out vec4 color;
|
||||
out vec4 fragColor;
|
||||
|
||||
in vec3 FragPos;
|
||||
in vec3 Normal;
|
||||
in vec3 FragPos;
|
||||
|
||||
uniform vec3 lightPos;
|
||||
uniform vec3 viewPos;
|
||||
uniform vec3 viewPos;
|
||||
uniform vec3 lightColor;
|
||||
uniform vec3 objectColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
// Ambient
|
||||
// ambient
|
||||
float ambientStrength = 0.1f;
|
||||
vec3 ambient = ambientStrength * lightColor;
|
||||
|
||||
// Diffuse
|
||||
// diffuse
|
||||
vec3 norm = normalize(Normal);
|
||||
vec3 lightDir = normalize(lightPos - FragPos);
|
||||
float diff = max(dot(norm, lightDir), 0.0);
|
||||
float diff = max(dot(norm, lightDir), 0.0f);
|
||||
vec3 diffuse = diff * lightColor;
|
||||
|
||||
// Specular
|
||||
// specular
|
||||
float specularStrength = 0.5f;
|
||||
vec3 viewDir = normalize(viewPos - FragPos);
|
||||
vec3 reflectDir = reflect(-lightDir, norm);
|
||||
@@ -29,5 +29,5 @@ void main()
|
||||
vec3 specular = specularStrength * spec * lightColor;
|
||||
|
||||
vec3 result = (ambient + diffuse + specular) * objectColor;
|
||||
color = vec4(result, 1.0f);
|
||||
fragColor = vec4(result, 1.0f);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 aPos;
|
||||
layout (location = 1) in vec3 aNormal;
|
||||
|
||||
out vec3 FragPos;
|
||||
out vec3 Normal;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
|
||||
void main()
|
||||
{
|
||||
FragPos = vec3(model * vec4(aPos, 1.0f));
|
||||
Normal = mat3(transpose(inverse(model))) * aNormal;
|
||||
|
||||
gl_Position = projection * view * vec4(FragPos, 1.0f);
|
||||
}
|
||||
@@ -0,0 +1,275 @@
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <stb_image.h>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
#include <learnopengl/filesystem.h>
|
||||
#include <learnopengl/shader_m.h>
|
||||
#include <learnopengl/camera.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
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);
|
||||
|
||||
// camera
|
||||
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
|
||||
float lastX = 800.0f / 2.0;
|
||||
float lastY = 600.0 / 2.0;
|
||||
bool firstMouse = true;
|
||||
|
||||
float deltaTime = 0.0f; // time between current frame and last frame
|
||||
float lastFrame = 0.0f;
|
||||
|
||||
// lighting
|
||||
glm::vec3 lightPos(1.2f, 1.0f, 2.0f);
|
||||
|
||||
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);
|
||||
//glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X
|
||||
|
||||
// glfw window creation
|
||||
// --------------------
|
||||
GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL);
|
||||
glfwMakeContextCurrent(window);
|
||||
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);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// configure global opengl state
|
||||
// -----------------------------
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
// build and compile our shader zprogram
|
||||
// ------------------------------------
|
||||
Shader lightingShader("2.2.basic_lighting.vs", "2.2.basic_lighting.fs");
|
||||
Shader lampShader("1.lamp.vs", "1.lamp.fs");
|
||||
|
||||
// set up vertex data (and buffer(s)) and configure vertex attributes
|
||||
// ------------------------------------------------------------------
|
||||
float vertices[] = {
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
|
||||
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
|
||||
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
|
||||
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
|
||||
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f
|
||||
};
|
||||
// first, configure the cube's VAO (and VBO)
|
||||
unsigned int VBO, cubeVAO;
|
||||
glGenVertexArrays(1, &cubeVAO);
|
||||
glGenBuffers(1, &VBO);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||
|
||||
glBindVertexArray(cubeVAO);
|
||||
|
||||
// position attribute
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
// normal attribute
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
|
||||
glEnableVertexAttribArray(1);
|
||||
|
||||
|
||||
// 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 lightVAO;
|
||||
glGenVertexArrays(1, &lightVAO);
|
||||
glBindVertexArray(lightVAO);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
// note that we update the lamp's position attribute's stride to reflect the updated buffer data
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
|
||||
// render loop
|
||||
// -----------
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
// per-frame time logic
|
||||
// --------------------
|
||||
float currentFrame = glfwGetTime();
|
||||
deltaTime = currentFrame - lastFrame;
|
||||
lastFrame = currentFrame;
|
||||
|
||||
// input
|
||||
// -----
|
||||
processInput(window);
|
||||
|
||||
// render
|
||||
// ------
|
||||
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// be sure to activate shader when setting uniforms/drawing objects
|
||||
lightingShader.use();
|
||||
lightingShader.setVec3("objectColor", 1.0f, 0.5f, 0.31f);
|
||||
lightingShader.setVec3("lightColor", 1.0f, 1.0f, 1.0f);
|
||||
lightingShader.setVec3("lightPos", lightPos);
|
||||
lightingShader.setVec3("viewPos", camera.Position);
|
||||
|
||||
// view/projection transformations
|
||||
glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), 800.0f / 600.0f, 0.1f, 100.0f);
|
||||
glm::mat4 view = camera.GetViewMatrix();
|
||||
lightingShader.setMat4("projection", projection);
|
||||
lightingShader.setMat4("view", view);
|
||||
|
||||
// world transformation
|
||||
glm::mat4 model;
|
||||
lightingShader.setMat4("model", model);
|
||||
|
||||
// render the cube
|
||||
glBindVertexArray(cubeVAO);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
|
||||
|
||||
// also draw the lamp object
|
||||
lampShader.use();
|
||||
lampShader.setMat4("projection", projection);
|
||||
lampShader.setMat4("view", view);
|
||||
model = glm::mat4();
|
||||
model = glm::translate(model, lightPos);
|
||||
model = glm::scale(model, glm::vec3(0.2f)); // a smaller cube
|
||||
lampShader.setMat4("model", model);
|
||||
|
||||
glBindVertexArray(lightVAO);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
|
||||
|
||||
// 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, &lightVAO);
|
||||
glDeleteBuffers(1, &VBO);
|
||||
|
||||
// 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);
|
||||
|
||||
float cameraSpeed = 2.5 * deltaTime;
|
||||
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 xpos, double ypos)
|
||||
{
|
||||
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(yoffset);
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 position;
|
||||
layout (location = 1) in vec3 normal;
|
||||
|
||||
out vec3 Normal;
|
||||
out vec3 FragPos;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projection * view * model * vec4(position, 1.0f);
|
||||
FragPos = vec3(model * vec4(position, 1.0f));
|
||||
Normal = mat3(transpose(inverse(model))) * normal;
|
||||
}
|
||||
@@ -1,281 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
|
||||
// GLEW
|
||||
#define GLEW_STATIC
|
||||
#include <GL/glew.h>
|
||||
|
||||
// GLFW
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
// Other Libs
|
||||
#include <SOIL.h>
|
||||
// GLM Mathematics
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
// Other includes
|
||||
#include <learnopengl/shader.h>
|
||||
#include <learnopengl/camera.h>
|
||||
|
||||
|
||||
// Function prototypes
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
|
||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
|
||||
void do_movement();
|
||||
|
||||
// Window dimensions
|
||||
const GLuint WIDTH = 800, HEIGHT = 600;
|
||||
|
||||
// Camera
|
||||
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
|
||||
GLfloat lastX = WIDTH / 2.0;
|
||||
GLfloat lastY = HEIGHT / 2.0;
|
||||
bool keys[1024];
|
||||
|
||||
// Light attributes
|
||||
glm::vec3 lightPos(1.2f, 1.0f, 2.0f);
|
||||
|
||||
// Deltatime
|
||||
GLfloat deltaTime = 0.0f; // Time between current frame and last frame
|
||||
GLfloat lastFrame = 0.0f; // Time of last frame
|
||||
|
||||
// The MAIN function, from here we start the application and run the game loop
|
||||
int main()
|
||||
{
|
||||
// Init GLFW
|
||||
glfwInit();
|
||||
// Set all the required options for GLFW
|
||||
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);
|
||||
|
||||
// Create a GLFWwindow object that we can use for GLFW's functions
|
||||
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr);
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
// Set the required callback functions
|
||||
glfwSetKeyCallback(window, key_callback);
|
||||
glfwSetCursorPosCallback(window, mouse_callback);
|
||||
glfwSetScrollCallback(window, scroll_callback);
|
||||
|
||||
// GLFW Options
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
|
||||
// Set this to true so GLEW knows to use a modern approach to retrieving function pointers and extensions
|
||||
glewExperimental = GL_TRUE;
|
||||
// Initialize GLEW to setup the OpenGL Function pointers
|
||||
glewInit();
|
||||
|
||||
// Define the viewport dimensions
|
||||
glViewport(0, 0, WIDTH, HEIGHT);
|
||||
|
||||
// OpenGL options
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
|
||||
// Build and compile our shader program
|
||||
Shader lightingShader("basic_lighting.vs", "basic_lighting.frag");
|
||||
Shader lampShader("lamp.vs", "lamp.frag");
|
||||
|
||||
// Set up vertex data (and buffer(s)) and attribute pointers
|
||||
GLfloat vertices[] = {
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
|
||||
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
|
||||
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
|
||||
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
|
||||
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f
|
||||
};
|
||||
// First, set the container's VAO (and VBO)
|
||||
GLuint VBO, containerVAO;
|
||||
glGenVertexArrays(1, &containerVAO);
|
||||
glGenBuffers(1, &VBO);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||
|
||||
glBindVertexArray(containerVAO);
|
||||
// Position attribute
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
// Normal attribute
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
|
||||
glEnableVertexAttribArray(1);
|
||||
glBindVertexArray(0);
|
||||
|
||||
// Then, we set the light's VAO (VBO stays the same. After all, the vertices are the same for the light object (also a 3D cube))
|
||||
GLuint lightVAO;
|
||||
glGenVertexArrays(1, &lightVAO);
|
||||
glBindVertexArray(lightVAO);
|
||||
// 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.
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
// Set the vertex attributes (only position data for the lamp))
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0); // Note that we skip over the normal vectors
|
||||
glEnableVertexAttribArray(0);
|
||||
glBindVertexArray(0);
|
||||
|
||||
|
||||
// Game loop
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
// Calculate deltatime of current frame
|
||||
GLfloat currentFrame = glfwGetTime();
|
||||
deltaTime = currentFrame - lastFrame;
|
||||
lastFrame = currentFrame;
|
||||
|
||||
// Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functions
|
||||
glfwPollEvents();
|
||||
do_movement();
|
||||
|
||||
// Clear the colorbuffer
|
||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// Use cooresponding shader when setting uniforms/drawing objects
|
||||
lightingShader.Use();
|
||||
GLint objectColorLoc = glGetUniformLocation(lightingShader.Program, "objectColor");
|
||||
GLint lightColorLoc = glGetUniformLocation(lightingShader.Program, "lightColor");
|
||||
GLint lightPosLoc = glGetUniformLocation(lightingShader.Program, "lightPos");
|
||||
GLint viewPosLoc = glGetUniformLocation(lightingShader.Program, "viewPos");
|
||||
glUniform3f(objectColorLoc, 1.0f, 0.5f, 0.31f);
|
||||
glUniform3f(lightColorLoc, 1.0f, 1.0f, 1.0f);
|
||||
glUniform3f(lightPosLoc, lightPos.x, lightPos.y, lightPos.z);
|
||||
glUniform3f(viewPosLoc, camera.Position.x, camera.Position.y, camera.Position.z);
|
||||
|
||||
|
||||
|
||||
// Create camera transformations
|
||||
glm::mat4 view;
|
||||
view = camera.GetViewMatrix();
|
||||
glm::mat4 projection = glm::perspective(camera.Zoom, (GLfloat)WIDTH / (GLfloat)HEIGHT, 0.1f, 100.0f);
|
||||
// Get the uniform locations
|
||||
GLint modelLoc = glGetUniformLocation(lightingShader.Program, "model");
|
||||
GLint viewLoc = glGetUniformLocation(lightingShader.Program, "view");
|
||||
GLint projLoc = glGetUniformLocation(lightingShader.Program, "projection");
|
||||
// Pass the matrices to the shader
|
||||
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
|
||||
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
|
||||
|
||||
// Draw the container (using container's vertex attributes)
|
||||
glBindVertexArray(containerVAO);
|
||||
glm::mat4 model;
|
||||
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
glBindVertexArray(0);
|
||||
|
||||
// Also draw the lamp object, again binding the appropriate shader
|
||||
lampShader.Use();
|
||||
// Get location objects for the matrices on the lamp shader (these could be different on a different shader)
|
||||
modelLoc = glGetUniformLocation(lampShader.Program, "model");
|
||||
viewLoc = glGetUniformLocation(lampShader.Program, "view");
|
||||
projLoc = glGetUniformLocation(lampShader.Program, "projection");
|
||||
// Set matrices
|
||||
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
|
||||
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
|
||||
model = glm::mat4();
|
||||
model = glm::translate(model, lightPos);
|
||||
model = glm::scale(model, glm::vec3(0.2f)); // Make it a smaller cube
|
||||
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
|
||||
// Draw the light object (using light's vertex attributes)
|
||||
glBindVertexArray(lightVAO);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
glBindVertexArray(0);
|
||||
|
||||
// Swap the screen buffers
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
|
||||
// Terminate GLFW, clearing any resources allocated by GLFW.
|
||||
glfwTerminate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Is called whenever a key is pressed/released via GLFW
|
||||
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 (key >= 0 && key < 1024)
|
||||
{
|
||||
if (action == GLFW_PRESS)
|
||||
keys[key] = true;
|
||||
else if (action == GLFW_RELEASE)
|
||||
keys[key] = false;
|
||||
}
|
||||
}
|
||||
|
||||
void do_movement()
|
||||
{
|
||||
// Camera controls
|
||||
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);
|
||||
}
|
||||
|
||||
bool firstMouse = true;
|
||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
|
||||
{
|
||||
if (firstMouse)
|
||||
{
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
firstMouse = false;
|
||||
}
|
||||
|
||||
GLfloat xoffset = xpos - lastX;
|
||||
GLfloat yoffset = lastY - ypos; // Reversed since y-coordinates go from bottom to left
|
||||
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
|
||||
camera.ProcessMouseMovement(xoffset, yoffset);
|
||||
}
|
||||
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
|
||||
{
|
||||
camera.ProcessMouseScroll(yoffset);
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
#version 330 core
|
||||
out vec4 color;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = vec4(1.0f); // Set alle 4 vector values to 1.0f
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 position;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projection * view * model * vec4(position, 1.0f);
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
#version 330 core
|
||||
out vec4 fragColor;
|
||||
|
||||
struct Material {
|
||||
vec3 ambient;
|
||||
vec3 diffuse;
|
||||
@@ -17,29 +19,27 @@ struct Light {
|
||||
in vec3 FragPos;
|
||||
in vec3 Normal;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
uniform vec3 viewPos;
|
||||
uniform Material material;
|
||||
uniform Light light;
|
||||
|
||||
void main()
|
||||
{
|
||||
// Ambient
|
||||
// ambient
|
||||
vec3 ambient = light.ambient * material.ambient;
|
||||
|
||||
// Diffuse
|
||||
// diffuse
|
||||
vec3 norm = normalize(Normal);
|
||||
vec3 lightDir = normalize(light.position - FragPos);
|
||||
float diff = max(dot(norm, lightDir), 0.0);
|
||||
vec3 diffuse = light.diffuse * (diff * material.diffuse);
|
||||
|
||||
// Specular
|
||||
// specular
|
||||
vec3 viewDir = normalize(viewPos - FragPos);
|
||||
vec3 reflectDir = reflect(-lightDir, norm);
|
||||
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
|
||||
vec3 specular = light.specular * (spec * material.specular);
|
||||
|
||||
vec3 result = ambient + diffuse + specular;
|
||||
color = vec4(result, 1.0f);
|
||||
fragColor = vec4(result, 1.0f);
|
||||
}
|
||||
18
src/2.lighting/3.1.materials/3.1.materials.vs
Normal file
18
src/2.lighting/3.1.materials/3.1.materials.vs
Normal file
@@ -0,0 +1,18 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 aPos;
|
||||
layout (location = 1) in vec3 aNormal;
|
||||
|
||||
out vec3 FragPos;
|
||||
out vec3 Normal;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
|
||||
void main()
|
||||
{
|
||||
FragPos = vec3(model * vec4(aPos, 1.0f));
|
||||
Normal = mat3(transpose(inverse(model))) * aNormal;
|
||||
|
||||
gl_Position = projection * view * vec4(FragPos, 1.0f);
|
||||
}
|
||||
290
src/2.lighting/3.1.materials/materials.cpp
Normal file
290
src/2.lighting/3.1.materials/materials.cpp
Normal file
@@ -0,0 +1,290 @@
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <stb_image.h>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
#include <learnopengl/filesystem.h>
|
||||
#include <learnopengl/shader_m.h>
|
||||
#include <learnopengl/camera.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
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);
|
||||
|
||||
// camera
|
||||
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
|
||||
float lastX = 800.0f / 2.0;
|
||||
float lastY = 600.0 / 2.0;
|
||||
bool firstMouse = true;
|
||||
|
||||
float deltaTime = 0.0f; // time between current frame and last frame
|
||||
float lastFrame = 0.0f;
|
||||
|
||||
// lighting
|
||||
glm::vec3 lightPos(1.2f, 1.0f, 2.0f);
|
||||
|
||||
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);
|
||||
//glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X
|
||||
|
||||
// glfw window creation
|
||||
// --------------------
|
||||
GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL);
|
||||
glfwMakeContextCurrent(window);
|
||||
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);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// configure global opengl state
|
||||
// -----------------------------
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
// build and compile our shader zprogram
|
||||
// ------------------------------------
|
||||
Shader lightingShader("3.1.materials.vs", "3.1.materials.fs");
|
||||
Shader lampShader("1.lamp.vs", "1.lamp.fs");
|
||||
|
||||
// set up vertex data (and buffer(s)) and configure vertex attributes
|
||||
// ------------------------------------------------------------------
|
||||
float vertices[] = {
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
|
||||
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
|
||||
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
|
||||
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
|
||||
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f
|
||||
};
|
||||
// first, configure the cube's VAO (and VBO)
|
||||
unsigned int VBO, cubeVAO;
|
||||
glGenVertexArrays(1, &cubeVAO);
|
||||
glGenBuffers(1, &VBO);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||
|
||||
glBindVertexArray(cubeVAO);
|
||||
|
||||
// position attribute
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
// normal attribute
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
|
||||
glEnableVertexAttribArray(1);
|
||||
|
||||
|
||||
// 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 lightVAO;
|
||||
glGenVertexArrays(1, &lightVAO);
|
||||
glBindVertexArray(lightVAO);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
// note that we update the lamp's position attribute's stride to reflect the updated buffer data
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
|
||||
// render loop
|
||||
// -----------
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
// per-frame time logic
|
||||
// --------------------
|
||||
float currentFrame = glfwGetTime();
|
||||
deltaTime = currentFrame - lastFrame;
|
||||
lastFrame = currentFrame;
|
||||
|
||||
// input
|
||||
// -----
|
||||
processInput(window);
|
||||
|
||||
// render
|
||||
// ------
|
||||
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// be sure to activate shader when setting uniforms/drawing objects
|
||||
lightingShader.use();
|
||||
lightingShader.setVec3("light.position", lightPos);
|
||||
lightingShader.setVec3("viewPos", camera.Position);
|
||||
|
||||
// light properties
|
||||
glm::vec3 lightColor;
|
||||
lightColor.x = sin(glfwGetTime() * 2.0f);
|
||||
lightColor.y = sin(glfwGetTime() * 0.7f);
|
||||
lightColor.z = sin(glfwGetTime() * 1.3f);
|
||||
glm::vec3 diffuseColor = lightColor * glm::vec3(0.5f); // decrease the influence
|
||||
glm::vec3 ambientColor = diffuseColor * glm::vec3(0.2f); // low influence
|
||||
lightingShader.setVec3("light.ambient", ambientColor);
|
||||
lightingShader.setVec3("light.diffuse", diffuseColor);
|
||||
lightingShader.setVec3("light.specular", 1.0f, 1.0f, 1.0f);
|
||||
|
||||
// material properties
|
||||
lightingShader.setVec3("material.ambient", 1.0f, 0.5f, 0.31f);
|
||||
lightingShader.setVec3("material.diffuse", 1.0f, 0.5f, 0.31f);
|
||||
lightingShader.setVec3("material.specular", 0.5f, 0.5f, 0.5f); // specular lighting doesn't have full effect on this object's material
|
||||
lightingShader.setFloat("material.shininess", 32.0f);
|
||||
|
||||
// view/projection transformations
|
||||
glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), 800.0f / 600.0f, 0.1f, 100.0f);
|
||||
glm::mat4 view = camera.GetViewMatrix();
|
||||
lightingShader.setMat4("projection", projection);
|
||||
lightingShader.setMat4("view", view);
|
||||
|
||||
// world transformation
|
||||
glm::mat4 model;
|
||||
lightingShader.setMat4("model", model);
|
||||
|
||||
// render the cube
|
||||
glBindVertexArray(cubeVAO);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
|
||||
|
||||
// also draw the lamp object
|
||||
lampShader.use();
|
||||
lampShader.setMat4("projection", projection);
|
||||
lampShader.setMat4("view", view);
|
||||
model = glm::mat4();
|
||||
model = glm::translate(model, lightPos);
|
||||
model = glm::scale(model, glm::vec3(0.2f)); // a smaller cube
|
||||
lampShader.setMat4("model", model);
|
||||
|
||||
glBindVertexArray(lightVAO);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
|
||||
|
||||
// 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, &lightVAO);
|
||||
glDeleteBuffers(1, &VBO);
|
||||
|
||||
// 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);
|
||||
|
||||
float cameraSpeed = 2.5 * deltaTime;
|
||||
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 xpos, double ypos)
|
||||
{
|
||||
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(yoffset);
|
||||
}
|
||||
284
src/2.lighting/3.2.materials_exercise1/materials_exercise1.cpp
Normal file
284
src/2.lighting/3.2.materials_exercise1/materials_exercise1.cpp
Normal file
@@ -0,0 +1,284 @@
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <stb_image.h>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
#include <learnopengl/filesystem.h>
|
||||
#include <learnopengl/shader_m.h>
|
||||
#include <learnopengl/camera.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
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);
|
||||
|
||||
// camera
|
||||
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
|
||||
float lastX = 800.0f / 2.0;
|
||||
float lastY = 600.0 / 2.0;
|
||||
bool firstMouse = true;
|
||||
|
||||
float deltaTime = 0.0f; // time between current frame and last frame
|
||||
float lastFrame = 0.0f;
|
||||
|
||||
// lighting
|
||||
glm::vec3 lightPos(1.2f, 1.0f, 2.0f);
|
||||
|
||||
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);
|
||||
//glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X
|
||||
|
||||
// glfw window creation
|
||||
// --------------------
|
||||
GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL);
|
||||
glfwMakeContextCurrent(window);
|
||||
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);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// configure global opengl state
|
||||
// -----------------------------
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
// build and compile our shader zprogram
|
||||
// ------------------------------------
|
||||
Shader lightingShader("3.1.materials.vs", "3.1.materials.fs");
|
||||
Shader lampShader("1.lamp.vs", "1.lamp.fs");
|
||||
|
||||
// set up vertex data (and buffer(s)) and configure vertex attributes
|
||||
// ------------------------------------------------------------------
|
||||
float vertices[] = {
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
|
||||
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
|
||||
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
|
||||
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
|
||||
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f
|
||||
};
|
||||
// first, configure the cube's VAO (and VBO)
|
||||
unsigned int VBO, cubeVAO;
|
||||
glGenVertexArrays(1, &cubeVAO);
|
||||
glGenBuffers(1, &VBO);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||
|
||||
glBindVertexArray(cubeVAO);
|
||||
|
||||
// position attribute
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
// normal attribute
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
|
||||
glEnableVertexAttribArray(1);
|
||||
|
||||
|
||||
// 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 lightVAO;
|
||||
glGenVertexArrays(1, &lightVAO);
|
||||
glBindVertexArray(lightVAO);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
// note that we update the lamp's position attribute's stride to reflect the updated buffer data
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
|
||||
// render loop
|
||||
// -----------
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
// per-frame time logic
|
||||
// --------------------
|
||||
float currentFrame = glfwGetTime();
|
||||
deltaTime = currentFrame - lastFrame;
|
||||
lastFrame = currentFrame;
|
||||
|
||||
// input
|
||||
// -----
|
||||
processInput(window);
|
||||
|
||||
// render
|
||||
// ------
|
||||
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// be sure to activate shader when setting uniforms/drawing objects
|
||||
lightingShader.use();
|
||||
lightingShader.setVec3("light.position", lightPos);
|
||||
lightingShader.setVec3("viewPos", camera.Position);
|
||||
|
||||
// light properties
|
||||
lightingShader.setVec3("light.ambient", 1.0f, 1.0f, 1.0f); // note that all light colors are set at full intensity
|
||||
lightingShader.setVec3("light.diffuse", 1.0f, 1.0f, 1.0f);
|
||||
lightingShader.setVec3("light.specular", 1.0f, 1.0f, 1.0f);
|
||||
|
||||
// material properties
|
||||
lightingShader.setVec3("material.ambient", 0.0f, 0.1f, 0.06f);
|
||||
lightingShader.setVec3("material.diffuse", 0.0f, 0.50980392f, 0.50980392f);
|
||||
lightingShader.setVec3("material.specular", 0.50196078f, 0.50196078f, 0.50196078f);
|
||||
lightingShader.setFloat("material.shininess", 32.0f);
|
||||
|
||||
// view/projection transformations
|
||||
glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), 800.0f / 600.0f, 0.1f, 100.0f);
|
||||
glm::mat4 view = camera.GetViewMatrix();
|
||||
lightingShader.setMat4("projection", projection);
|
||||
lightingShader.setMat4("view", view);
|
||||
|
||||
// world transformation
|
||||
glm::mat4 model;
|
||||
lightingShader.setMat4("model", model);
|
||||
|
||||
// render the cube
|
||||
glBindVertexArray(cubeVAO);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
|
||||
|
||||
// also draw the lamp object
|
||||
lampShader.use();
|
||||
lampShader.setMat4("projection", projection);
|
||||
lampShader.setMat4("view", view);
|
||||
model = glm::mat4();
|
||||
model = glm::translate(model, lightPos);
|
||||
model = glm::scale(model, glm::vec3(0.2f)); // a smaller cube
|
||||
lampShader.setMat4("model", model);
|
||||
|
||||
glBindVertexArray(lightVAO);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
|
||||
|
||||
// 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, &lightVAO);
|
||||
glDeleteBuffers(1, &VBO);
|
||||
|
||||
// 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);
|
||||
|
||||
float cameraSpeed = 2.5 * deltaTime;
|
||||
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 xpos, double ypos)
|
||||
{
|
||||
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(yoffset);
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
#version 330 core
|
||||
out vec4 color;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = vec4(1.0f); // Set alle 4 vector values to 1.0f
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 position;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projection * view * model * vec4(position, 1.0f);
|
||||
}
|
||||
@@ -1,291 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
|
||||
// GLEW
|
||||
#define GLEW_STATIC
|
||||
#include <GL/glew.h>
|
||||
|
||||
// GLFW
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
// Other Libs
|
||||
#include <SOIL.h>
|
||||
// GLM Mathematics
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
// Other includes
|
||||
#include <learnopengl/shader.h>
|
||||
#include <learnopengl/camera.h>
|
||||
|
||||
|
||||
// Function prototypes
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
|
||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
|
||||
void do_movement();
|
||||
|
||||
// Window dimensions
|
||||
const GLuint WIDTH = 800, HEIGHT = 600;
|
||||
|
||||
// Camera
|
||||
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
|
||||
GLfloat lastX = WIDTH / 2.0;
|
||||
GLfloat lastY = HEIGHT / 2.0;
|
||||
bool keys[1024];
|
||||
|
||||
// Light attributes
|
||||
glm::vec3 lightPos(1.2f, 1.0f, 2.0f);
|
||||
|
||||
// Deltatime
|
||||
GLfloat deltaTime = 0.0f; // Time between current frame and last frame
|
||||
GLfloat lastFrame = 0.0f; // Time of last frame
|
||||
|
||||
// The MAIN function, from here we start the application and run the game loop
|
||||
int main()
|
||||
{
|
||||
// Init GLFW
|
||||
glfwInit();
|
||||
// Set all the required options for GLFW
|
||||
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);
|
||||
|
||||
// Create a GLFWwindow object that we can use for GLFW's functions
|
||||
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr);
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
// Set the required callback functions
|
||||
glfwSetKeyCallback(window, key_callback);
|
||||
glfwSetCursorPosCallback(window, mouse_callback);
|
||||
glfwSetScrollCallback(window, scroll_callback);
|
||||
|
||||
// GLFW Options
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
|
||||
// Set this to true so GLEW knows to use a modern approach to retrieving function pointers and extensions
|
||||
glewExperimental = GL_TRUE;
|
||||
// Initialize GLEW to setup the OpenGL Function pointers
|
||||
glewInit();
|
||||
|
||||
// Define the viewport dimensions
|
||||
glViewport(0, 0, WIDTH, HEIGHT);
|
||||
|
||||
// OpenGL options
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
|
||||
// Build and compile our shader program
|
||||
Shader lightingShader("materials.vs", "materials.frag");
|
||||
Shader lampShader("lamp.vs", "lamp.frag");
|
||||
|
||||
// Set up vertex data (and buffer(s)) and attribute pointers
|
||||
GLfloat vertices[] = {
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
|
||||
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
|
||||
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
|
||||
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
|
||||
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f
|
||||
};
|
||||
// First, set the container's VAO (and VBO)
|
||||
GLuint VBO, containerVAO;
|
||||
glGenVertexArrays(1, &containerVAO);
|
||||
glGenBuffers(1, &VBO);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||
|
||||
glBindVertexArray(containerVAO);
|
||||
// Position attribute
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
// Normal attribute
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
|
||||
glEnableVertexAttribArray(1);
|
||||
glBindVertexArray(0);
|
||||
|
||||
// Then, we set the light's VAO (VBO stays the same. After all, the vertices are the same for the light object (also a 3D cube))
|
||||
GLuint lightVAO;
|
||||
glGenVertexArrays(1, &lightVAO);
|
||||
glBindVertexArray(lightVAO);
|
||||
// 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.
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
// Set the vertex attributes (only position data for the lamp))
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0); // Note that we skip over the normal vectors
|
||||
glEnableVertexAttribArray(0);
|
||||
glBindVertexArray(0);
|
||||
|
||||
|
||||
// Game loop
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
// Calculate deltatime of current frame
|
||||
GLfloat currentFrame = glfwGetTime();
|
||||
deltaTime = currentFrame - lastFrame;
|
||||
lastFrame = currentFrame;
|
||||
|
||||
// Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functions
|
||||
glfwPollEvents();
|
||||
do_movement();
|
||||
|
||||
// Clear the colorbuffer
|
||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
|
||||
// Use cooresponding shader when setting uniforms/drawing objects
|
||||
lightingShader.Use();
|
||||
GLint lightPosLoc = glGetUniformLocation(lightingShader.Program, "light.position");
|
||||
GLint viewPosLoc = glGetUniformLocation(lightingShader.Program, "viewPos");
|
||||
glUniform3f(lightPosLoc, lightPos.x, lightPos.y, lightPos.z);
|
||||
glUniform3f(viewPosLoc, camera.Position.x, camera.Position.y, camera.Position.z);
|
||||
// Set lights properties
|
||||
glm::vec3 lightColor;
|
||||
lightColor.x = sin(glfwGetTime() * 2.0f);
|
||||
lightColor.y = sin(glfwGetTime() * 0.7f);
|
||||
lightColor.z = sin(glfwGetTime() * 1.3f);
|
||||
glm::vec3 diffuseColor = lightColor * glm::vec3(0.5f); // Decrease the influence
|
||||
glm::vec3 ambientColor = diffuseColor * glm::vec3(0.2f); // Low influence
|
||||
glUniform3f(glGetUniformLocation(lightingShader.Program, "light.ambient"), ambientColor.x, ambientColor.y, ambientColor.z);
|
||||
glUniform3f(glGetUniformLocation(lightingShader.Program, "light.diffuse"), diffuseColor.x, diffuseColor.y, diffuseColor.z);
|
||||
glUniform3f(glGetUniformLocation(lightingShader.Program, "light.specular"), 1.0f, 1.0f, 1.0f);
|
||||
// Set material properties
|
||||
glUniform3f(glGetUniformLocation(lightingShader.Program, "material.ambient"), 1.0f, 0.5f, 0.31f);
|
||||
glUniform3f(glGetUniformLocation(lightingShader.Program, "material.diffuse"), 1.0f, 0.5f, 0.31f);
|
||||
glUniform3f(glGetUniformLocation(lightingShader.Program, "material.specular"), 0.5f, 0.5f, 0.5f); // Specular doesn't have full effect on this object's material
|
||||
glUniform1f(glGetUniformLocation(lightingShader.Program, "material.shininess"), 32.0f);
|
||||
|
||||
// Create camera transformations
|
||||
glm::mat4 view;
|
||||
view = camera.GetViewMatrix();
|
||||
glm::mat4 projection = glm::perspective(camera.Zoom, (GLfloat)WIDTH / (GLfloat)HEIGHT, 0.1f, 100.0f);
|
||||
// Get the uniform locations
|
||||
GLint modelLoc = glGetUniformLocation(lightingShader.Program, "model");
|
||||
GLint viewLoc = glGetUniformLocation(lightingShader.Program, "view");
|
||||
GLint projLoc = glGetUniformLocation(lightingShader.Program, "projection");
|
||||
// Pass the matrices to the shader
|
||||
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
|
||||
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
|
||||
|
||||
// Draw the container (using container's vertex attributes)
|
||||
glBindVertexArray(containerVAO);
|
||||
glm::mat4 model;
|
||||
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
glBindVertexArray(0);
|
||||
|
||||
// Also draw the lamp object, again binding the appropriate shader
|
||||
lampShader.Use();
|
||||
// Get location objects for the matrices on the lamp shader (these could be different on a different shader)
|
||||
modelLoc = glGetUniformLocation(lampShader.Program, "model");
|
||||
viewLoc = glGetUniformLocation(lampShader.Program, "view");
|
||||
projLoc = glGetUniformLocation(lampShader.Program, "projection");
|
||||
// Set matrices
|
||||
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
|
||||
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
|
||||
model = glm::mat4();
|
||||
model = glm::translate(model, lightPos);
|
||||
model = glm::scale(model, glm::vec3(0.2f)); // Make it a smaller cube
|
||||
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
|
||||
// Draw the light object (using light's vertex attributes)
|
||||
glBindVertexArray(lightVAO);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
glBindVertexArray(0);
|
||||
|
||||
// Swap the screen buffers
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
|
||||
// Terminate GLFW, clearing any resources allocated by GLFW.
|
||||
glfwTerminate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Is called whenever a key is pressed/released via GLFW
|
||||
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 (key >= 0 && key < 1024)
|
||||
{
|
||||
if (action == GLFW_PRESS)
|
||||
keys[key] = true;
|
||||
else if (action == GLFW_RELEASE)
|
||||
keys[key] = false;
|
||||
}
|
||||
}
|
||||
|
||||
void do_movement()
|
||||
{
|
||||
// Camera controls
|
||||
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);
|
||||
}
|
||||
|
||||
bool firstMouse = true;
|
||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
|
||||
{
|
||||
if (firstMouse)
|
||||
{
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
firstMouse = false;
|
||||
}
|
||||
|
||||
GLfloat xoffset = xpos - lastX;
|
||||
GLfloat yoffset = lastY - ypos; // Reversed since y-coordinates go from bottom to left
|
||||
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
|
||||
camera.ProcessMouseMovement(xoffset, yoffset);
|
||||
}
|
||||
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
|
||||
{
|
||||
camera.ProcessMouseScroll(yoffset);
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 position;
|
||||
layout (location = 1) in vec3 normal;
|
||||
|
||||
out vec3 Normal;
|
||||
out vec3 FragPos;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projection * view * model * vec4(position, 1.0f);
|
||||
FragPos = vec3(model * vec4(position, 1.0f));
|
||||
Normal = mat3(transpose(inverse(model))) * normal;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
#version 330 core
|
||||
out vec4 color;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = vec4(1.0f); // Set alle 4 vector values to 1.0f
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 position;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projection * view * model * vec4(position, 1.0f);
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
#version 330 core
|
||||
struct Material {
|
||||
sampler2D diffuse;
|
||||
sampler2D specular;
|
||||
float shininess;
|
||||
};
|
||||
|
||||
struct Light {
|
||||
vec3 position;
|
||||
|
||||
vec3 ambient;
|
||||
vec3 diffuse;
|
||||
vec3 specular;
|
||||
};
|
||||
|
||||
in vec3 FragPos;
|
||||
in vec3 Normal;
|
||||
in vec2 TexCoords;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
uniform vec3 viewPos;
|
||||
uniform Material material;
|
||||
uniform Light light;
|
||||
|
||||
void main()
|
||||
{
|
||||
// Ambient
|
||||
vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));
|
||||
|
||||
// Diffuse
|
||||
vec3 norm = normalize(Normal);
|
||||
vec3 lightDir = normalize(light.position - FragPos);
|
||||
float diff = max(dot(norm, lightDir), 0.0);
|
||||
vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));
|
||||
|
||||
// Specular
|
||||
vec3 viewDir = normalize(viewPos - FragPos);
|
||||
vec3 reflectDir = reflect(-lightDir, norm);
|
||||
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
|
||||
vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));
|
||||
|
||||
color = vec4(ambient + diffuse + specular, 1.0f);
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 position;
|
||||
layout (location = 1) in vec3 normal;
|
||||
layout (location = 2) in vec2 texCoords;
|
||||
|
||||
out vec3 Normal;
|
||||
out vec3 FragPos;
|
||||
out vec2 TexCoords;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projection * view * model * vec4(position, 1.0f);
|
||||
FragPos = vec3(model * vec4(position, 1.0f));
|
||||
Normal = mat3(transpose(inverse(model))) * normal;
|
||||
TexCoords = texCoords;
|
||||
}
|
||||
@@ -1,325 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
|
||||
// GLEW
|
||||
#define GLEW_STATIC
|
||||
#include <GL/glew.h>
|
||||
|
||||
// GLFW
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
// Other Libs
|
||||
#include <SOIL.h>
|
||||
// GLM Mathematics
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
// Other includes
|
||||
#include <learnopengl/shader.h>
|
||||
#include <learnopengl/camera.h>
|
||||
#include <learnopengl/filesystem.h>
|
||||
|
||||
// Function prototypes
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
|
||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
|
||||
void do_movement();
|
||||
|
||||
// Window dimensions
|
||||
const GLuint WIDTH = 800, HEIGHT = 600;
|
||||
|
||||
// Camera
|
||||
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
|
||||
GLfloat lastX = WIDTH / 2.0;
|
||||
GLfloat lastY = HEIGHT / 2.0;
|
||||
bool keys[1024];
|
||||
|
||||
// Light attributes
|
||||
glm::vec3 lightPos(1.2f, 1.0f, 2.0f);
|
||||
|
||||
// Deltatime
|
||||
GLfloat deltaTime = 0.0f; // Time between current frame and last frame
|
||||
GLfloat lastFrame = 0.0f; // Time of last frame
|
||||
|
||||
// The MAIN function, from here we start the application and run the game loop
|
||||
int main()
|
||||
{
|
||||
// Init GLFW
|
||||
glfwInit();
|
||||
// Set all the required options for GLFW
|
||||
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);
|
||||
|
||||
// Create a GLFWwindow object that we can use for GLFW's functions
|
||||
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr);
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
// Set the required callback functions
|
||||
glfwSetKeyCallback(window, key_callback);
|
||||
glfwSetCursorPosCallback(window, mouse_callback);
|
||||
glfwSetScrollCallback(window, scroll_callback);
|
||||
|
||||
// GLFW Options
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
|
||||
// Set this to true so GLEW knows to use a modern approach to retrieving function pointers and extensions
|
||||
glewExperimental = GL_TRUE;
|
||||
// Initialize GLEW to setup the OpenGL Function pointers
|
||||
glewInit();
|
||||
|
||||
// Define the viewport dimensions
|
||||
glViewport(0, 0, WIDTH, HEIGHT);
|
||||
|
||||
// OpenGL options
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
|
||||
// Build and compile our shader program
|
||||
Shader lightingShader("lighting_maps.vs", "lighting_maps.frag");
|
||||
Shader lampShader("lamp.vs", "lamp.frag");
|
||||
|
||||
// Set up vertex data (and buffer(s)) and attribute pointers
|
||||
GLfloat 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
|
||||
};
|
||||
// First, set the container's VAO (and VBO)
|
||||
GLuint VBO, containerVAO;
|
||||
glGenVertexArrays(1, &containerVAO);
|
||||
glGenBuffers(1, &VBO);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||
|
||||
glBindVertexArray(containerVAO);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
|
||||
glEnableVertexAttribArray(2);
|
||||
glBindVertexArray(0);
|
||||
|
||||
// Then, we set the light's VAO (VBO stays the same. After all, the vertices are the same for the light object (also a 3D cube))
|
||||
GLuint lightVAO;
|
||||
glGenVertexArrays(1, &lightVAO);
|
||||
glBindVertexArray(lightVAO);
|
||||
// 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.
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
// Set the vertex attributes (only position data for the lamp))
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0); // Note that we skip over the other data in our buffer object (we don't need the normals/textures, only positions).
|
||||
glEnableVertexAttribArray(0);
|
||||
glBindVertexArray(0);
|
||||
|
||||
|
||||
// Load textures
|
||||
GLuint diffuseMap, specularMap;
|
||||
glGenTextures(1, &diffuseMap);
|
||||
glGenTextures(1, &specularMap);
|
||||
int width, height;
|
||||
unsigned char* image;
|
||||
// Diffuse map
|
||||
image = SOIL_load_image(FileSystem::getPath("resources/textures/container2.png").c_str(), &width, &height, 0, SOIL_LOAD_RGB);
|
||||
glBindTexture(GL_TEXTURE_2D, diffuseMap);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
SOIL_free_image_data(image);
|
||||
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_NEAREST_MIPMAP_NEAREST);
|
||||
// Specular map
|
||||
image = SOIL_load_image(FileSystem::getPath("resources/textures/container2_specular.png").c_str(), &width, &height, 0, SOIL_LOAD_RGB);
|
||||
glBindTexture(GL_TEXTURE_2D, specularMap);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
SOIL_free_image_data(image);
|
||||
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_NEAREST_MIPMAP_NEAREST);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
|
||||
// Set texture units
|
||||
lightingShader.Use();
|
||||
glUniform1i(glGetUniformLocation(lightingShader.Program, "material.diffuse"), 0);
|
||||
glUniform1i(glGetUniformLocation(lightingShader.Program, "material.specular"), 1);
|
||||
|
||||
|
||||
// Game loop
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
// Calculate deltatime of current frame
|
||||
GLfloat currentFrame = glfwGetTime();
|
||||
deltaTime = currentFrame - lastFrame;
|
||||
lastFrame = currentFrame;
|
||||
|
||||
// Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functions
|
||||
glfwPollEvents();
|
||||
do_movement();
|
||||
|
||||
// Clear the colorbuffer
|
||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
|
||||
// Use cooresponding shader when setting uniforms/drawing objects
|
||||
lightingShader.Use();
|
||||
GLint lightPosLoc = glGetUniformLocation(lightingShader.Program, "light.position");
|
||||
GLint viewPosLoc = glGetUniformLocation(lightingShader.Program, "viewPos");
|
||||
glUniform3f(lightPosLoc, lightPos.x, lightPos.y, lightPos.z);
|
||||
glUniform3f(viewPosLoc, camera.Position.x, camera.Position.y, camera.Position.z);
|
||||
// Set lights properties
|
||||
glUniform3f(glGetUniformLocation(lightingShader.Program, "light.ambient"), 0.2f, 0.2f, 0.2f);
|
||||
glUniform3f(glGetUniformLocation(lightingShader.Program, "light.diffuse"), 0.5f, 0.5f, 0.5f);
|
||||
glUniform3f(glGetUniformLocation(lightingShader.Program, "light.specular"), 1.0f, 1.0f, 1.0f);
|
||||
// Set material properties
|
||||
glUniform1f(glGetUniformLocation(lightingShader.Program, "material.shininess"), 32.0f);
|
||||
|
||||
// Create camera transformations
|
||||
glm::mat4 view;
|
||||
view = camera.GetViewMatrix();
|
||||
glm::mat4 projection = glm::perspective(camera.Zoom, (GLfloat)WIDTH / (GLfloat)HEIGHT, 0.1f, 100.0f);
|
||||
// Get the uniform locations
|
||||
GLint modelLoc = glGetUniformLocation(lightingShader.Program, "model");
|
||||
GLint viewLoc = glGetUniformLocation(lightingShader.Program, "view");
|
||||
GLint projLoc = glGetUniformLocation(lightingShader.Program, "projection");
|
||||
// Pass the matrices to the shader
|
||||
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
|
||||
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
|
||||
|
||||
// Bind diffuse map
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, diffuseMap);
|
||||
// Bind specular map
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, specularMap);
|
||||
|
||||
// Draw the container (using container's vertex attributes)
|
||||
glBindVertexArray(containerVAO);
|
||||
glm::mat4 model;
|
||||
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
glBindVertexArray(0);
|
||||
|
||||
// Also draw the lamp object, again binding the appropriate shader
|
||||
lampShader.Use();
|
||||
// Get location objects for the matrices on the lamp shader (these could be different on a different shader)
|
||||
modelLoc = glGetUniformLocation(lampShader.Program, "model");
|
||||
viewLoc = glGetUniformLocation(lampShader.Program, "view");
|
||||
projLoc = glGetUniformLocation(lampShader.Program, "projection");
|
||||
// Set matrices
|
||||
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
|
||||
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
|
||||
model = glm::mat4();
|
||||
model = glm::translate(model, lightPos);
|
||||
model = glm::scale(model, glm::vec3(0.2f)); // Make it a smaller cube
|
||||
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
|
||||
// Draw the light object (using light's vertex attributes)
|
||||
glBindVertexArray(lightVAO);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
glBindVertexArray(0);
|
||||
|
||||
// Swap the screen buffers
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
|
||||
// Terminate GLFW, clearing any resources allocated by GLFW.
|
||||
glfwTerminate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Is called whenever a key is pressed/released via GLFW
|
||||
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 (key >= 0 && key < 1024)
|
||||
{
|
||||
if (action == GLFW_PRESS)
|
||||
keys[key] = true;
|
||||
else if (action == GLFW_RELEASE)
|
||||
keys[key] = false;
|
||||
}
|
||||
}
|
||||
|
||||
void do_movement()
|
||||
{
|
||||
// Camera controls
|
||||
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);
|
||||
}
|
||||
|
||||
bool firstMouse = true;
|
||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
|
||||
{
|
||||
if (firstMouse)
|
||||
{
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
firstMouse = false;
|
||||
}
|
||||
|
||||
GLfloat xoffset = xpos - lastX;
|
||||
GLfloat yoffset = lastY - ypos; // Reversed since y-coordinates go from bottom to left
|
||||
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
|
||||
camera.ProcessMouseMovement(xoffset, yoffset);
|
||||
}
|
||||
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
|
||||
{
|
||||
camera.ProcessMouseScroll(yoffset);
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
#version 330 core
|
||||
out vec4 color;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = vec4(1.0f); // Set alle 4 vector values to 1.0f
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 position;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projection * view * model * vec4(position, 1.0f);
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
#version 330 core
|
||||
struct Material {
|
||||
sampler2D diffuse;
|
||||
sampler2D specular;
|
||||
float shininess;
|
||||
};
|
||||
|
||||
struct Light {
|
||||
vec3 position;
|
||||
vec3 direction;
|
||||
float cutOff;
|
||||
float outerCutOff;
|
||||
|
||||
float constant;
|
||||
float linear;
|
||||
float quadratic;
|
||||
|
||||
vec3 ambient;
|
||||
vec3 diffuse;
|
||||
vec3 specular;
|
||||
};
|
||||
|
||||
in vec3 FragPos;
|
||||
in vec3 Normal;
|
||||
in vec2 TexCoords;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
uniform vec3 viewPos;
|
||||
uniform Material material;
|
||||
uniform Light light;
|
||||
|
||||
void main()
|
||||
{
|
||||
// Ambient
|
||||
vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));
|
||||
|
||||
// Diffuse
|
||||
vec3 norm = normalize(Normal);
|
||||
vec3 lightDir = normalize(light.position - FragPos);
|
||||
float diff = max(dot(norm, lightDir), 0.0);
|
||||
vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));
|
||||
|
||||
// Specular
|
||||
vec3 viewDir = normalize(viewPos - FragPos);
|
||||
vec3 reflectDir = reflect(-lightDir, norm);
|
||||
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
|
||||
vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));
|
||||
|
||||
// Spotlight (soft edges)
|
||||
float theta = dot(lightDir, normalize(-light.direction));
|
||||
float epsilon = (light.cutOff - light.outerCutOff);
|
||||
float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0);
|
||||
diffuse *= intensity;
|
||||
specular *= intensity;
|
||||
|
||||
// Attenuation
|
||||
float distance = length(light.position - FragPos);
|
||||
float attenuation = 1.0f / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
|
||||
ambient *= attenuation;
|
||||
diffuse *= attenuation;
|
||||
specular *= attenuation;
|
||||
|
||||
color = vec4(ambient + diffuse + specular, 1.0f);
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 position;
|
||||
layout (location = 1) in vec3 normal;
|
||||
layout (location = 2) in vec2 texCoords;
|
||||
|
||||
out vec3 Normal;
|
||||
out vec3 FragPos;
|
||||
out vec2 TexCoords;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projection * view * model * vec4(position, 1.0f);
|
||||
FragPos = vec3(model * vec4(position, 1.0f));
|
||||
Normal = mat3(transpose(inverse(model))) * normal;
|
||||
TexCoords = texCoords;
|
||||
}
|
||||
@@ -1,368 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
|
||||
// GLEW
|
||||
#define GLEW_STATIC
|
||||
#include <GL/glew.h>
|
||||
|
||||
// GLFW
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
// Other Libs
|
||||
#include <SOIL.h>
|
||||
// GLM Mathematics
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
// Other includes
|
||||
#include <learnopengl/shader.h>
|
||||
#include <learnopengl/camera.h>
|
||||
#include <learnopengl/filesystem.h>
|
||||
|
||||
// Function prototypes
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
|
||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
|
||||
void do_movement();
|
||||
|
||||
// Window dimensions
|
||||
const GLuint WIDTH = 800, HEIGHT = 600;
|
||||
|
||||
// Camera
|
||||
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
|
||||
GLfloat lastX = WIDTH / 2.0;
|
||||
GLfloat lastY = HEIGHT / 2.0;
|
||||
bool keys[1024];
|
||||
|
||||
// Light attributes
|
||||
glm::vec3 lightPos(1.2f, 1.0f, 2.0f);
|
||||
|
||||
// Deltatime
|
||||
GLfloat deltaTime = 0.0f; // Time between current frame and last frame
|
||||
GLfloat lastFrame = 0.0f; // Time of last frame
|
||||
|
||||
// The MAIN function, from here we start the application and run the game loop
|
||||
int main()
|
||||
{
|
||||
// Init GLFW
|
||||
glfwInit();
|
||||
// Set all the required options for GLFW
|
||||
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);
|
||||
|
||||
// Create a GLFWwindow object that we can use for GLFW's functions
|
||||
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr);
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
// Set the required callback functions
|
||||
glfwSetKeyCallback(window, key_callback);
|
||||
glfwSetCursorPosCallback(window, mouse_callback);
|
||||
glfwSetScrollCallback(window, scroll_callback);
|
||||
|
||||
// GLFW Options
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
|
||||
// Set this to true so GLEW knows to use a modern approach to retrieving function pointers and extensions
|
||||
glewExperimental = GL_TRUE;
|
||||
// Initialize GLEW to setup the OpenGL Function pointers
|
||||
glewInit();
|
||||
|
||||
// Define the viewport dimensions
|
||||
glViewport(0, 0, WIDTH, HEIGHT);
|
||||
|
||||
// OpenGL options
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
|
||||
// Build and compile our shader program
|
||||
Shader lightingShader("light_casters.vs", "light_casters.frag");
|
||||
Shader lampShader("lamp.vs", "lamp.frag");
|
||||
|
||||
// Set up vertex data (and buffer(s)) and attribute pointers
|
||||
GLfloat 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
|
||||
};
|
||||
// Positions all containers
|
||||
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)
|
||||
};
|
||||
// First, set the container's VAO (and VBO)
|
||||
GLuint VBO, containerVAO;
|
||||
glGenVertexArrays(1, &containerVAO);
|
||||
glGenBuffers(1, &VBO);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||
|
||||
glBindVertexArray(containerVAO);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
|
||||
glEnableVertexAttribArray(2);
|
||||
glBindVertexArray(0);
|
||||
|
||||
// Then, we set the light's VAO (VBO stays the same. After all, the vertices are the same for the light object (also a 3D cube))
|
||||
GLuint lightVAO;
|
||||
glGenVertexArrays(1, &lightVAO);
|
||||
glBindVertexArray(lightVAO);
|
||||
// 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.
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
// Set the vertex attributes (only position data for the lamp))
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0); // Note that we skip over the other data in our buffer object (we don't need the normals/textures, only positions).
|
||||
glEnableVertexAttribArray(0);
|
||||
glBindVertexArray(0);
|
||||
|
||||
|
||||
// Load textures
|
||||
GLuint diffuseMap, specularMap, emissionMap;
|
||||
glGenTextures(1, &diffuseMap);
|
||||
glGenTextures(1, &specularMap);
|
||||
glGenTextures(1, &emissionMap);
|
||||
int width, height;
|
||||
unsigned char* image;
|
||||
// Diffuse map
|
||||
image = SOIL_load_image(FileSystem::getPath("resources/textures/container2.png").c_str(), &width, &height, 0, SOIL_LOAD_RGB);
|
||||
glBindTexture(GL_TEXTURE_2D, diffuseMap);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
SOIL_free_image_data(image);
|
||||
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_NEAREST_MIPMAP_NEAREST);
|
||||
// Specular map
|
||||
image = SOIL_load_image(FileSystem::getPath("resources/textures/container2_specular.png").c_str(), &width, &height, 0, SOIL_LOAD_RGB);
|
||||
glBindTexture(GL_TEXTURE_2D, specularMap);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
SOIL_free_image_data(image);
|
||||
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_NEAREST_MIPMAP_NEAREST);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
|
||||
// Set texture units
|
||||
lightingShader.Use();
|
||||
glUniform1i(glGetUniformLocation(lightingShader.Program, "material.diffuse"), 0);
|
||||
glUniform1i(glGetUniformLocation(lightingShader.Program, "material.specular"), 1);
|
||||
|
||||
|
||||
// Game loop
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
// Calculate deltatime of current frame
|
||||
GLfloat currentFrame = glfwGetTime();
|
||||
deltaTime = currentFrame - lastFrame;
|
||||
lastFrame = currentFrame;
|
||||
|
||||
// Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functions
|
||||
glfwPollEvents();
|
||||
do_movement();
|
||||
|
||||
// Clear the colorbuffer
|
||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
|
||||
// Use cooresponding shader when setting uniforms/drawing objects
|
||||
lightingShader.Use();
|
||||
GLint lightPosLoc = glGetUniformLocation(lightingShader.Program, "light.position");
|
||||
GLint lightSpotdirLoc = glGetUniformLocation(lightingShader.Program, "light.direction");
|
||||
GLint lightSpotCutOffLoc = glGetUniformLocation(lightingShader.Program, "light.cutOff");
|
||||
GLint lightSpotOuterCutOffLoc = glGetUniformLocation(lightingShader.Program, "light.outerCutOff");
|
||||
GLint viewPosLoc = glGetUniformLocation(lightingShader.Program, "viewPos");
|
||||
glUniform3f(lightPosLoc, camera.Position.x, camera.Position.y, camera.Position.z);
|
||||
glUniform3f(lightSpotdirLoc, camera.Front.x, camera.Front.y, camera.Front.z);
|
||||
glUniform1f(lightSpotCutOffLoc, glm::cos(glm::radians(12.5f)));
|
||||
glUniform1f(lightSpotOuterCutOffLoc, glm::cos(glm::radians(17.5f)));
|
||||
glUniform3f(viewPosLoc, camera.Position.x, camera.Position.y, camera.Position.z);
|
||||
// Set lights properties
|
||||
glUniform3f(glGetUniformLocation(lightingShader.Program, "light.ambient"), 0.1f, 0.1f, 0.1f);
|
||||
// We set the diffuse intensity a bit higher; note that the right lighting conditions differ with each lighting method and environment.
|
||||
// Each environment and lighting type requires some tweaking of these variables to get the best out of your environment.
|
||||
glUniform3f(glGetUniformLocation(lightingShader.Program, "light.diffuse"), 0.8f, 0.8f, 0.8f);
|
||||
glUniform3f(glGetUniformLocation(lightingShader.Program, "light.specular"), 1.0f, 1.0f, 1.0f);
|
||||
glUniform1f(glGetUniformLocation(lightingShader.Program, "light.constant"), 1.0f);
|
||||
glUniform1f(glGetUniformLocation(lightingShader.Program, "light.linear"), 0.09);
|
||||
glUniform1f(glGetUniformLocation(lightingShader.Program, "light.quadratic"), 0.032);
|
||||
// Set material properties
|
||||
glUniform1f(glGetUniformLocation(lightingShader.Program, "material.shininess"), 32.0f);
|
||||
|
||||
// Create camera transformations
|
||||
glm::mat4 view;
|
||||
view = camera.GetViewMatrix();
|
||||
glm::mat4 projection = glm::perspective(camera.Zoom, (GLfloat)WIDTH / (GLfloat)HEIGHT, 0.1f, 100.0f);
|
||||
// Get the uniform locations
|
||||
GLint modelLoc = glGetUniformLocation(lightingShader.Program, "model");
|
||||
GLint viewLoc = glGetUniformLocation(lightingShader.Program, "view");
|
||||
GLint projLoc = glGetUniformLocation(lightingShader.Program, "projection");
|
||||
// Pass the matrices to the shader
|
||||
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
|
||||
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
|
||||
|
||||
// Bind diffuse map
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, diffuseMap);
|
||||
// Bind specular map
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, specularMap);
|
||||
|
||||
// Draw the container (using container's vertex attributes)
|
||||
/*glBindVertexArray(containerVAO);
|
||||
glm::mat4 model;
|
||||
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
glBindVertexArray(0);*/
|
||||
|
||||
// Draw 10 containers with the same VAO and VBO information; only their world space coordinates differ
|
||||
glm::mat4 model;
|
||||
glBindVertexArray(containerVAO);
|
||||
for (GLuint i = 0; i < 10; i++)
|
||||
{
|
||||
model = glm::mat4();
|
||||
model = glm::translate(model, cubePositions[i]);
|
||||
GLfloat angle = 20.0f * i;
|
||||
model = glm::rotate(model, angle, glm::vec3(1.0f, 0.3f, 0.5f));
|
||||
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
}
|
||||
glBindVertexArray(0);
|
||||
|
||||
|
||||
// Again, no need to draw the lamp object
|
||||
// Also draw the lamp object, again binding the appropriate shader
|
||||
//lampShader.Use();
|
||||
//// Get location objects for the matrices on the lamp shader (these could be different on a different shader)
|
||||
//modelLoc = glGetUniformLocation(lampShader.Program, "model");
|
||||
//viewLoc = glGetUniformLocation(lampShader.Program, "view");
|
||||
//projLoc = glGetUniformLocation(lampShader.Program, "projection");
|
||||
//// Set matrices
|
||||
//glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
|
||||
//glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
|
||||
//model = glm::mat4();
|
||||
//model = glm::translate(model, lightPos);
|
||||
//model = glm::scale(model, glm::vec3(0.2f)); // Make it a smaller cube
|
||||
//glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
|
||||
//// Draw the light object (using light's vertex attributes)
|
||||
//glBindVertexArray(lightVAO);
|
||||
//glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
//glBindVertexArray(0);
|
||||
|
||||
|
||||
// Swap the screen buffers
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
|
||||
// Terminate GLFW, clearing any resources allocated by GLFW.
|
||||
glfwTerminate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Is called whenever a key is pressed/released via GLFW
|
||||
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 (key >= 0 && key < 1024)
|
||||
{
|
||||
if (action == GLFW_PRESS)
|
||||
keys[key] = true;
|
||||
else if (action == GLFW_RELEASE)
|
||||
keys[key] = false;
|
||||
}
|
||||
}
|
||||
|
||||
void do_movement()
|
||||
{
|
||||
// Camera controls
|
||||
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);
|
||||
}
|
||||
|
||||
bool firstMouse = true;
|
||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
|
||||
{
|
||||
if (firstMouse)
|
||||
{
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
firstMouse = false;
|
||||
}
|
||||
|
||||
GLfloat xoffset = xpos - lastX;
|
||||
GLfloat yoffset = lastY - ypos; // Reversed since y-coordinates go from bottom to left
|
||||
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
|
||||
camera.ProcessMouseMovement(xoffset, yoffset);
|
||||
}
|
||||
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
|
||||
{
|
||||
camera.ProcessMouseScroll(yoffset);
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
#version 330 core
|
||||
out vec4 color;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = vec4(1.0f); // Set alle 4 vector values to 1.0f
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 position;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projection * view * model * vec4(position, 1.0f);
|
||||
}
|
||||
@@ -1,408 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
|
||||
// GLEW
|
||||
#define GLEW_STATIC
|
||||
#include <GL/glew.h>
|
||||
|
||||
// GLFW
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
// Other Libs
|
||||
#include <SOIL.h>
|
||||
// GLM Mathematics
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
// Other includes
|
||||
#include <learnopengl/shader.h>
|
||||
#include <learnopengl/camera.h>
|
||||
#include <learnopengl/filesystem.h>
|
||||
|
||||
// Function prototypes
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
|
||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
|
||||
void do_movement();
|
||||
|
||||
// Window dimensions
|
||||
const GLuint WIDTH = 800, HEIGHT = 600;
|
||||
|
||||
// Camera
|
||||
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
|
||||
GLfloat lastX = WIDTH / 2.0;
|
||||
GLfloat lastY = HEIGHT / 2.0;
|
||||
bool keys[1024];
|
||||
|
||||
// Light attributes
|
||||
glm::vec3 lightPos(1.2f, 1.0f, 2.0f);
|
||||
|
||||
// Deltatime
|
||||
GLfloat deltaTime = 0.0f; // Time between current frame and last frame
|
||||
GLfloat lastFrame = 0.0f; // Time of last frame
|
||||
|
||||
// The MAIN function, from here we start the application and run the game loop
|
||||
int main()
|
||||
{
|
||||
// Init GLFW
|
||||
glfwInit();
|
||||
// Set all the required options for GLFW
|
||||
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);
|
||||
|
||||
// Create a GLFWwindow object that we can use for GLFW's functions
|
||||
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr);
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
// Set the required callback functions
|
||||
glfwSetKeyCallback(window, key_callback);
|
||||
glfwSetCursorPosCallback(window, mouse_callback);
|
||||
glfwSetScrollCallback(window, scroll_callback);
|
||||
|
||||
// GLFW Options
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
|
||||
// Set this to true so GLEW knows to use a modern approach to retrieving function pointers and extensions
|
||||
glewExperimental = GL_TRUE;
|
||||
// Initialize GLEW to setup the OpenGL Function pointers
|
||||
glewInit();
|
||||
|
||||
// Define the viewport dimensions
|
||||
glViewport(0, 0, WIDTH, HEIGHT);
|
||||
|
||||
// OpenGL options
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
|
||||
// Build and compile our shader program
|
||||
Shader lightingShader("multiple_lights.vs", "multiple_lights.frag");
|
||||
Shader lampShader("lamp.vs", "lamp.frag");
|
||||
|
||||
// Set up vertex data (and buffer(s)) and attribute pointers
|
||||
GLfloat 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
|
||||
};
|
||||
// Positions all containers
|
||||
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)
|
||||
};
|
||||
// Positions of the point lights
|
||||
glm::vec3 pointLightPositions[] = {
|
||||
glm::vec3( 0.7f, 0.2f, 2.0f),
|
||||
glm::vec3( 2.3f, -3.3f, -4.0f),
|
||||
glm::vec3(-4.0f, 2.0f, -12.0f),
|
||||
glm::vec3( 0.0f, 0.0f, -3.0f)
|
||||
};
|
||||
// First, set the container's VAO (and VBO)
|
||||
GLuint VBO, containerVAO;
|
||||
glGenVertexArrays(1, &containerVAO);
|
||||
glGenBuffers(1, &VBO);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||
|
||||
glBindVertexArray(containerVAO);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
|
||||
glEnableVertexAttribArray(2);
|
||||
glBindVertexArray(0);
|
||||
|
||||
// Then, we set the light's VAO (VBO stays the same. After all, the vertices are the same for the light object (also a 3D cube))
|
||||
GLuint lightVAO;
|
||||
glGenVertexArrays(1, &lightVAO);
|
||||
glBindVertexArray(lightVAO);
|
||||
// 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.
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
// Set the vertex attributes (only position data for the lamp))
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0); // Note that we skip over the other data in our buffer object (we don't need the normals/textures, only positions).
|
||||
glEnableVertexAttribArray(0);
|
||||
glBindVertexArray(0);
|
||||
|
||||
|
||||
// Load textures
|
||||
GLuint diffuseMap, specularMap, emissionMap;
|
||||
glGenTextures(1, &diffuseMap);
|
||||
glGenTextures(1, &specularMap);
|
||||
glGenTextures(1, &emissionMap);
|
||||
int width, height;
|
||||
unsigned char* image;
|
||||
// Diffuse map
|
||||
image = SOIL_load_image(FileSystem::getPath("resources/textures/container2.png").c_str(), &width, &height, 0, SOIL_LOAD_RGB);
|
||||
glBindTexture(GL_TEXTURE_2D, diffuseMap);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
SOIL_free_image_data(image);
|
||||
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_NEAREST_MIPMAP_NEAREST);
|
||||
// Specular map
|
||||
image = SOIL_load_image(FileSystem::getPath("resources/textures/container2_specular.png").c_str(), &width, &height, 0, SOIL_LOAD_RGB);
|
||||
glBindTexture(GL_TEXTURE_2D, specularMap);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
SOIL_free_image_data(image);
|
||||
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_NEAREST_MIPMAP_NEAREST);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
|
||||
// Set texture units
|
||||
lightingShader.Use();
|
||||
glUniform1i(glGetUniformLocation(lightingShader.Program, "material.diffuse"), 0);
|
||||
glUniform1i(glGetUniformLocation(lightingShader.Program, "material.specular"), 1);
|
||||
|
||||
|
||||
// Game loop
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
// Calculate deltatime of current frame
|
||||
GLfloat currentFrame = glfwGetTime();
|
||||
deltaTime = currentFrame - lastFrame;
|
||||
lastFrame = currentFrame;
|
||||
|
||||
// Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functions
|
||||
glfwPollEvents();
|
||||
do_movement();
|
||||
|
||||
// Clear the colorbuffer
|
||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
|
||||
// Use cooresponding shader when setting uniforms/drawing objects
|
||||
lightingShader.Use();
|
||||
GLint viewPosLoc = glGetUniformLocation(lightingShader.Program, "viewPos");
|
||||
glUniform3f(viewPosLoc, camera.Position.x, camera.Position.y, camera.Position.z);
|
||||
// Set material properties
|
||||
glUniform1f(glGetUniformLocation(lightingShader.Program, "material.shininess"), 32.0f);
|
||||
// == ==========================
|
||||
// Here we set all the uniforms for the 5/6 types of lights we have. We have to set them manually and index
|
||||
// the proper PointLight struct in the array to set each uniform variable. This can be done more code-friendly
|
||||
// by defining light types as classes and set their values in there, or by using a more efficient uniform approach
|
||||
// by using 'Uniform buffer objects', but that is something we discuss in the 'Advanced GLSL' tutorial.
|
||||
// == ==========================
|
||||
// Directional light
|
||||
glUniform3f(glGetUniformLocation(lightingShader.Program, "dirLight.direction"), -0.2f, -1.0f, -0.3f);
|
||||
glUniform3f(glGetUniformLocation(lightingShader.Program, "dirLight.ambient"), 0.05f, 0.05f, 0.05f);
|
||||
glUniform3f(glGetUniformLocation(lightingShader.Program, "dirLight.diffuse"), 0.4f, 0.4f, 0.4f);
|
||||
glUniform3f(glGetUniformLocation(lightingShader.Program, "dirLight.specular"), 0.5f, 0.5f, 0.5f);
|
||||
// Point light 1
|
||||
glUniform3f(glGetUniformLocation(lightingShader.Program, "pointLights[0].position"), pointLightPositions[0].x, pointLightPositions[0].y, pointLightPositions[0].z);
|
||||
glUniform3f(glGetUniformLocation(lightingShader.Program, "pointLights[0].ambient"), 0.05f, 0.05f, 0.05f);
|
||||
glUniform3f(glGetUniformLocation(lightingShader.Program, "pointLights[0].diffuse"), 0.8f, 0.8f, 0.8f);
|
||||
glUniform3f(glGetUniformLocation(lightingShader.Program, "pointLights[0].specular"), 1.0f, 1.0f, 1.0f);
|
||||
glUniform1f(glGetUniformLocation(lightingShader.Program, "pointLights[0].constant"), 1.0f);
|
||||
glUniform1f(glGetUniformLocation(lightingShader.Program, "pointLights[0].linear"), 0.09);
|
||||
glUniform1f(glGetUniformLocation(lightingShader.Program, "pointLights[0].quadratic"), 0.032);
|
||||
// Point light 2
|
||||
glUniform3f(glGetUniformLocation(lightingShader.Program, "pointLights[1].position"), pointLightPositions[1].x, pointLightPositions[1].y, pointLightPositions[1].z);
|
||||
glUniform3f(glGetUniformLocation(lightingShader.Program, "pointLights[1].ambient"), 0.05f, 0.05f, 0.05f);
|
||||
glUniform3f(glGetUniformLocation(lightingShader.Program, "pointLights[1].diffuse"), 0.8f, 0.8f, 0.8f);
|
||||
glUniform3f(glGetUniformLocation(lightingShader.Program, "pointLights[1].specular"), 1.0f, 1.0f, 1.0f);
|
||||
glUniform1f(glGetUniformLocation(lightingShader.Program, "pointLights[1].constant"), 1.0f);
|
||||
glUniform1f(glGetUniformLocation(lightingShader.Program, "pointLights[1].linear"), 0.09);
|
||||
glUniform1f(glGetUniformLocation(lightingShader.Program, "pointLights[1].quadratic"), 0.032);
|
||||
// Point light 3
|
||||
glUniform3f(glGetUniformLocation(lightingShader.Program, "pointLights[2].position"), pointLightPositions[2].x, pointLightPositions[2].y, pointLightPositions[2].z);
|
||||
glUniform3f(glGetUniformLocation(lightingShader.Program, "pointLights[2].ambient"), 0.05f, 0.05f, 0.05f);
|
||||
glUniform3f(glGetUniformLocation(lightingShader.Program, "pointLights[2].diffuse"), 0.8f, 0.8f, 0.8f);
|
||||
glUniform3f(glGetUniformLocation(lightingShader.Program, "pointLights[2].specular"), 1.0f, 1.0f, 1.0f);
|
||||
glUniform1f(glGetUniformLocation(lightingShader.Program, "pointLights[2].constant"), 1.0f);
|
||||
glUniform1f(glGetUniformLocation(lightingShader.Program, "pointLights[2].linear"), 0.09);
|
||||
glUniform1f(glGetUniformLocation(lightingShader.Program, "pointLights[2].quadratic"), 0.032);
|
||||
// Point light 4
|
||||
glUniform3f(glGetUniformLocation(lightingShader.Program, "pointLights[3].position"), pointLightPositions[3].x, pointLightPositions[3].y, pointLightPositions[3].z);
|
||||
glUniform3f(glGetUniformLocation(lightingShader.Program, "pointLights[3].ambient"), 0.05f, 0.05f, 0.05f);
|
||||
glUniform3f(glGetUniformLocation(lightingShader.Program, "pointLights[3].diffuse"), 0.8f, 0.8f, 0.8f);
|
||||
glUniform3f(glGetUniformLocation(lightingShader.Program, "pointLights[3].specular"), 1.0f, 1.0f, 1.0f);
|
||||
glUniform1f(glGetUniformLocation(lightingShader.Program, "pointLights[3].constant"), 1.0f);
|
||||
glUniform1f(glGetUniformLocation(lightingShader.Program, "pointLights[3].linear"), 0.09);
|
||||
glUniform1f(glGetUniformLocation(lightingShader.Program, "pointLights[3].quadratic"), 0.032);
|
||||
// SpotLight
|
||||
glUniform3f(glGetUniformLocation(lightingShader.Program, "spotLight.position"), camera.Position.x, camera.Position.y, camera.Position.z);
|
||||
glUniform3f(glGetUniformLocation(lightingShader.Program, "spotLight.direction"), camera.Front.x, camera.Front.y, camera.Front.z);
|
||||
glUniform3f(glGetUniformLocation(lightingShader.Program, "spotLight.ambient"), 0.0f, 0.0f, 0.0f);
|
||||
glUniform3f(glGetUniformLocation(lightingShader.Program, "spotLight.diffuse"), 1.0f, 1.0f, 1.0f);
|
||||
glUniform3f(glGetUniformLocation(lightingShader.Program, "spotLight.specular"), 1.0f, 1.0f, 1.0f);
|
||||
glUniform1f(glGetUniformLocation(lightingShader.Program, "spotLight.constant"), 1.0f);
|
||||
glUniform1f(glGetUniformLocation(lightingShader.Program, "spotLight.linear"), 0.09);
|
||||
glUniform1f(glGetUniformLocation(lightingShader.Program, "spotLight.quadratic"), 0.032);
|
||||
glUniform1f(glGetUniformLocation(lightingShader.Program, "spotLight.cutOff"), glm::cos(glm::radians(12.5f)));
|
||||
glUniform1f(glGetUniformLocation(lightingShader.Program, "spotLight.outerCutOff"), glm::cos(glm::radians(15.0f)));
|
||||
|
||||
// Create camera transformations
|
||||
glm::mat4 view;
|
||||
view = camera.GetViewMatrix();
|
||||
glm::mat4 projection = glm::perspective(camera.Zoom, (GLfloat)WIDTH / (GLfloat)HEIGHT, 0.1f, 100.0f);
|
||||
// Get the uniform locations
|
||||
GLint modelLoc = glGetUniformLocation(lightingShader.Program, "model");
|
||||
GLint viewLoc = glGetUniformLocation(lightingShader.Program, "view");
|
||||
GLint projLoc = glGetUniformLocation(lightingShader.Program, "projection");
|
||||
// Pass the matrices to the shader
|
||||
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
|
||||
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
|
||||
|
||||
// Bind diffuse map
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, diffuseMap);
|
||||
// Bind specular map
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, specularMap);
|
||||
|
||||
// Draw 10 containers with the same VAO and VBO information; only their world space coordinates differ
|
||||
glm::mat4 model;
|
||||
glBindVertexArray(containerVAO);
|
||||
for (GLuint i = 0; i < 10; i++)
|
||||
{
|
||||
model = glm::mat4();
|
||||
model = glm::translate(model, cubePositions[i]);
|
||||
GLfloat angle = 20.0f * i;
|
||||
model = glm::rotate(model, angle, glm::vec3(1.0f, 0.3f, 0.5f));
|
||||
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
}
|
||||
glBindVertexArray(0);
|
||||
|
||||
|
||||
// Also draw the lamp object, again binding the appropriate shader
|
||||
lampShader.Use();
|
||||
// Get location objects for the matrices on the lamp shader (these could be different on a different shader)
|
||||
modelLoc = glGetUniformLocation(lampShader.Program, "model");
|
||||
viewLoc = glGetUniformLocation(lampShader.Program, "view");
|
||||
projLoc = glGetUniformLocation(lampShader.Program, "projection");
|
||||
// Set matrices
|
||||
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
|
||||
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
|
||||
|
||||
// We now draw as many light bulbs as we have point lights.
|
||||
glBindVertexArray(lightVAO);
|
||||
for (GLuint i = 0; i < 4; i++)
|
||||
{
|
||||
model = glm::mat4();
|
||||
model = glm::translate(model, pointLightPositions[i]);
|
||||
model = glm::scale(model, glm::vec3(0.2f)); // Make it a smaller cube
|
||||
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
}
|
||||
glBindVertexArray(0);
|
||||
|
||||
|
||||
// Swap the screen buffers
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
|
||||
// Terminate GLFW, clearing any resources allocated by GLFW.
|
||||
glfwTerminate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Is called whenever a key is pressed/released via GLFW
|
||||
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 (key >= 0 && key < 1024)
|
||||
{
|
||||
if (action == GLFW_PRESS)
|
||||
keys[key] = true;
|
||||
else if (action == GLFW_RELEASE)
|
||||
keys[key] = false;
|
||||
}
|
||||
}
|
||||
|
||||
void do_movement()
|
||||
{
|
||||
// Camera controls
|
||||
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);
|
||||
}
|
||||
|
||||
bool firstMouse = true;
|
||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
|
||||
{
|
||||
if (firstMouse)
|
||||
{
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
firstMouse = false;
|
||||
}
|
||||
|
||||
GLfloat xoffset = xpos - lastX;
|
||||
GLfloat yoffset = lastY - ypos; // Reversed since y-coordinates go from bottom to left
|
||||
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
|
||||
camera.ProcessMouseMovement(xoffset, yoffset);
|
||||
}
|
||||
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
|
||||
{
|
||||
camera.ProcessMouseScroll(yoffset);
|
||||
}
|
||||
@@ -1,147 +0,0 @@
|
||||
#version 330 core
|
||||
struct Material {
|
||||
sampler2D diffuse;
|
||||
sampler2D specular;
|
||||
float shininess;
|
||||
};
|
||||
|
||||
struct DirLight {
|
||||
vec3 direction;
|
||||
|
||||
vec3 ambient;
|
||||
vec3 diffuse;
|
||||
vec3 specular;
|
||||
};
|
||||
|
||||
struct PointLight {
|
||||
vec3 position;
|
||||
|
||||
float constant;
|
||||
float linear;
|
||||
float quadratic;
|
||||
|
||||
vec3 ambient;
|
||||
vec3 diffuse;
|
||||
vec3 specular;
|
||||
};
|
||||
|
||||
struct SpotLight {
|
||||
vec3 position;
|
||||
vec3 direction;
|
||||
float cutOff;
|
||||
float outerCutOff;
|
||||
|
||||
float constant;
|
||||
float linear;
|
||||
float quadratic;
|
||||
|
||||
vec3 ambient;
|
||||
vec3 diffuse;
|
||||
vec3 specular;
|
||||
};
|
||||
|
||||
#define NR_POINT_LIGHTS 4
|
||||
|
||||
in vec3 FragPos;
|
||||
in vec3 Normal;
|
||||
in vec2 TexCoords;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
uniform vec3 viewPos;
|
||||
uniform DirLight dirLight;
|
||||
uniform PointLight pointLights[NR_POINT_LIGHTS];
|
||||
uniform SpotLight spotLight;
|
||||
uniform Material material;
|
||||
|
||||
// Function prototypes
|
||||
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir);
|
||||
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir);
|
||||
vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir);
|
||||
|
||||
void main()
|
||||
{
|
||||
// Properties
|
||||
vec3 norm = normalize(Normal);
|
||||
vec3 viewDir = normalize(viewPos - FragPos);
|
||||
|
||||
// == ======================================
|
||||
// Our lighting is set up in 3 phases: directional, point lights and an optional flashlight
|
||||
// For each phase, a calculate function is defined that calculates the corresponding color
|
||||
// per lamp. In the main() function we take all the calculated colors and sum them up for
|
||||
// this fragment's final color.
|
||||
// == ======================================
|
||||
// Phase 1: Directional lighting
|
||||
vec3 result = CalcDirLight(dirLight, norm, viewDir);
|
||||
// Phase 2: Point lights
|
||||
for(int i = 0; i < NR_POINT_LIGHTS; i++)
|
||||
result += CalcPointLight(pointLights[i], norm, FragPos, viewDir);
|
||||
// Phase 3: Spot light
|
||||
result += CalcSpotLight(spotLight, norm, FragPos, viewDir);
|
||||
|
||||
color = vec4(result, 1.0);
|
||||
}
|
||||
|
||||
// Calculates the color when using a directional light.
|
||||
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir)
|
||||
{
|
||||
vec3 lightDir = normalize(-light.direction);
|
||||
// Diffuse shading
|
||||
float diff = max(dot(normal, lightDir), 0.0);
|
||||
// Specular shading
|
||||
vec3 reflectDir = reflect(-lightDir, normal);
|
||||
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
|
||||
// Combine results
|
||||
vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));
|
||||
vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));
|
||||
vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));
|
||||
return (ambient + diffuse + specular);
|
||||
}
|
||||
|
||||
// Calculates the color when using a point light.
|
||||
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
|
||||
{
|
||||
vec3 lightDir = normalize(light.position - fragPos);
|
||||
// Diffuse shading
|
||||
float diff = max(dot(normal, lightDir), 0.0);
|
||||
// Specular shading
|
||||
vec3 reflectDir = reflect(-lightDir, normal);
|
||||
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
|
||||
// Attenuation
|
||||
float distance = length(light.position - fragPos);
|
||||
float attenuation = 1.0f / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
|
||||
// Combine results
|
||||
vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));
|
||||
vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));
|
||||
vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));
|
||||
ambient *= attenuation;
|
||||
diffuse *= attenuation;
|
||||
specular *= attenuation;
|
||||
return (ambient + diffuse + specular);
|
||||
}
|
||||
|
||||
// Calculates the color when using a spot light.
|
||||
vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
|
||||
{
|
||||
vec3 lightDir = normalize(light.position - fragPos);
|
||||
// Diffuse shading
|
||||
float diff = max(dot(normal, lightDir), 0.0);
|
||||
// Specular shading
|
||||
vec3 reflectDir = reflect(-lightDir, normal);
|
||||
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
|
||||
// Attenuation
|
||||
float distance = length(light.position - fragPos);
|
||||
float attenuation = 1.0f / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
|
||||
// Spotlight intensity
|
||||
float theta = dot(lightDir, normalize(-light.direction));
|
||||
float epsilon = light.cutOff - light.outerCutOff;
|
||||
float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0);
|
||||
// Combine results
|
||||
vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));
|
||||
vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));
|
||||
vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));
|
||||
ambient *= attenuation * intensity;
|
||||
diffuse *= attenuation * intensity;
|
||||
specular *= attenuation * intensity;
|
||||
return (ambient + diffuse + specular);
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 position;
|
||||
layout (location = 1) in vec3 normal;
|
||||
layout (location = 2) in vec2 texCoords;
|
||||
|
||||
out vec3 Normal;
|
||||
out vec3 FragPos;
|
||||
out vec2 TexCoords;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projection * view * model * vec4(position, 1.0f);
|
||||
FragPos = vec3(model * vec4(position, 1.0f));
|
||||
Normal = mat3(transpose(inverse(model))) * normal;
|
||||
TexCoords = texCoords;
|
||||
}
|
||||
Reference in New Issue
Block a user