mirror of
https://github.com/JoeyDeVries/LearnOpenGL.git
synced 2026-01-30 20:13:22 +08:00
Initial commit, all code samples with working CMake script for VS/Windows.
This commit is contained in:
80
src/1.getting_started/1.hello_window/hellowindow2.cpp
Normal file
80
src/1.getting_started/1.hello_window/hellowindow2.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
#include <iostream>
|
||||
|
||||
// GLEW
|
||||
#define GLEW_STATIC
|
||||
#include <GL/glew.h>
|
||||
|
||||
// GLFW
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
|
||||
// Function prototypes
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
|
||||
|
||||
// Window dimensions
|
||||
const GLuint WIDTH = 800, HEIGHT = 600;
|
||||
|
||||
// The MAIN function, from here we start the application and run the game loop
|
||||
int main()
|
||||
{
|
||||
std::cout << "Starting GLFW context, OpenGL 3.3" << std::endl;
|
||||
// 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);
|
||||
if (window == NULL)
|
||||
{
|
||||
std::cout << "Failed to create GLFW window" << std::endl;
|
||||
glfwTerminate();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Set the required callback functions
|
||||
glfwSetKeyCallback(window, key_callback);
|
||||
|
||||
// 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
|
||||
if (glewInit() != GLEW_OK)
|
||||
{
|
||||
std::cout << "Failed to initialize GLEW" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Define the viewport dimensions
|
||||
glViewport(0, 0, WIDTH, HEIGHT);
|
||||
|
||||
// Game loop
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
// Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functions
|
||||
glfwPollEvents();
|
||||
|
||||
// Render
|
||||
// Clear the colorbuffer
|
||||
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
// 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)
|
||||
{
|
||||
std::cout << key << std::endl;
|
||||
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
|
||||
glfwSetWindowShouldClose(window, GL_TRUE);
|
||||
}
|
||||
1
src/1.getting_started/1.hello_window/shader.frag
Normal file
1
src/1.getting_started/1.hello_window/shader.frag
Normal file
@@ -0,0 +1 @@
|
||||
swag_frag
|
||||
1
src/1.getting_started/1.hello_window/shader.vs
Normal file
1
src/1.getting_started/1.hello_window/shader.vs
Normal file
@@ -0,0 +1 @@
|
||||
swag
|
||||
179
src/1.getting_started/2.hello_triangle/hellotriangle2.cpp
Normal file
179
src/1.getting_started/2.hello_triangle/hellotriangle2.cpp
Normal file
@@ -0,0 +1,179 @@
|
||||
#include <iostream>
|
||||
|
||||
// GLEW
|
||||
#define GLEW_STATIC
|
||||
#include <GL/glew.h>
|
||||
|
||||
// GLFW
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
|
||||
// Function prototypes
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
|
||||
|
||||
// Window dimensions
|
||||
const GLuint WIDTH = 800, HEIGHT = 600;
|
||||
|
||||
// Shaders
|
||||
const GLchar* vertexShaderSource = "#version 330 core\n"
|
||||
"layout (location = 0) in vec3 position;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
"gl_Position = vec4(position.x, position.y, position.z, 1.0);\n"
|
||||
"}\0";
|
||||
const GLchar* fragmentShaderSource = "#version 330 core\n"
|
||||
"out vec4 color;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
"color = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
|
||||
"}\n\0";
|
||||
|
||||
// The MAIN function, from here we start the application and run the game loop
|
||||
int main()
|
||||
{
|
||||
std::cout << "Starting GLFW context, OpenGL 3.3" << std::endl;
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
|
||||
// Build and compile our shader program
|
||||
// Vertex shader
|
||||
GLint vertexShader = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
|
||||
glCompileShader(vertexShader);
|
||||
// Check for compile time errors
|
||||
GLint success;
|
||||
GLchar infoLog[512];
|
||||
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
|
||||
if (!success)
|
||||
{
|
||||
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
|
||||
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
|
||||
}
|
||||
// Fragment shader
|
||||
GLint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
|
||||
glCompileShader(fragmentShader);
|
||||
// Check for compile time errors
|
||||
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
|
||||
if (!success)
|
||||
{
|
||||
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
|
||||
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
|
||||
}
|
||||
// Link shaders
|
||||
GLint shaderProgram = glCreateProgram();
|
||||
glAttachShader(shaderProgram, vertexShader);
|
||||
glAttachShader(shaderProgram, fragmentShader);
|
||||
glLinkProgram(shaderProgram);
|
||||
// Check for linking errors
|
||||
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
|
||||
if (!success) {
|
||||
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
|
||||
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
|
||||
}
|
||||
glDeleteShader(vertexShader);
|
||||
glDeleteShader(fragmentShader);
|
||||
|
||||
|
||||
// Set up vertex data (and buffer(s)) and attribute pointers
|
||||
//GLfloat vertices[] = {
|
||||
// // First triangle
|
||||
// 0.5f, 0.5f, // Top Right
|
||||
// 0.5f, -0.5f, // Bottom Right
|
||||
// -0.5f, 0.5f, // Top Left
|
||||
// // Second triangle
|
||||
// 0.5f, -0.5f, // Bottom Right
|
||||
// -0.5f, -0.5f, // Bottom Left
|
||||
// -0.5f, 0.5f // Top Left
|
||||
//};
|
||||
GLfloat vertices[] = {
|
||||
0.5f, 0.5f, 0.0f, // Top Right
|
||||
0.5f, -0.5f, 0.0f, // Bottom Right
|
||||
-0.5f, -0.5f, 0.0f, // Bottom Left
|
||||
-0.5f, 0.5f, 0.0f // Top Left
|
||||
};
|
||||
GLuint indices[] = { // Note that we start from 0!
|
||||
0, 1, 3, // First Triangle
|
||||
1, 2, 3 // Second Triangle
|
||||
};
|
||||
GLuint VBO, VAO, EBO;
|
||||
glGenVertexArrays(1, &VAO);
|
||||
glGenBuffers(1, &VBO);
|
||||
glGenBuffers(1, &EBO);
|
||||
// Bind the Vertex Array Object first, then bind and set vertex buffer(s) and attribute pointer(s).
|
||||
glBindVertexArray(VAO);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
|
||||
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0); // Note that this is allowed, the call to glVertexAttribPointer registered VBO as the currently bound vertex buffer object so afterwards we can safely unbind
|
||||
|
||||
glBindVertexArray(0); // Unbind VAO (it's always a good thing to unbind any buffer/array to prevent strange bugs), remember: do NOT unbind the EBO, keep it bound to this VAO
|
||||
|
||||
|
||||
// Uncommenting this call will result in wireframe polygons.
|
||||
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
|
||||
// Game loop
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
// Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functions
|
||||
glfwPollEvents();
|
||||
|
||||
// Render
|
||||
// Clear the colorbuffer
|
||||
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
// Draw our first triangle
|
||||
glUseProgram(shaderProgram);
|
||||
glBindVertexArray(VAO);
|
||||
//glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
|
||||
glBindVertexArray(0);
|
||||
|
||||
// Swap the screen buffers
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
// Properly de-allocate all resources once they've outlived their purpose
|
||||
glDeleteVertexArrays(1, &VAO);
|
||||
glDeleteBuffers(1, &VBO);
|
||||
glDeleteBuffers(1, &EBO);
|
||||
// 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);
|
||||
}
|
||||
9
src/1.getting_started/3.shaders/basic.frag
Normal file
9
src/1.getting_started/3.shaders/basic.frag
Normal file
@@ -0,0 +1,9 @@
|
||||
#version 330 core
|
||||
in vec3 ourColor;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = vec4(ourColor, 1.0f);
|
||||
}
|
||||
11
src/1.getting_started/3.shaders/basic.vs
Normal file
11
src/1.getting_started/3.shaders/basic.vs
Normal file
@@ -0,0 +1,11 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 position;
|
||||
layout (location = 1) in vec3 color;
|
||||
|
||||
out vec3 ourColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(position, 1.0f);
|
||||
ourColor = color;
|
||||
}
|
||||
110
src/1.getting_started/3.shaders/shaders-using-object.cpp
Normal file
110
src/1.getting_started/3.shaders/shaders-using-object.cpp
Normal file
@@ -0,0 +1,110 @@
|
||||
#include <iostream>
|
||||
|
||||
// GLEW
|
||||
#define GLEW_STATIC
|
||||
#include <GL/glew.h>
|
||||
|
||||
// GLFW
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
// Other includes
|
||||
#include <learnopengl/shader.h>
|
||||
|
||||
|
||||
// Function prototypes
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
|
||||
|
||||
// Window dimensions
|
||||
const GLuint WIDTH = 800, HEIGHT = 600;
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
|
||||
// Build and compile our shader program
|
||||
Shader ourShader("basic.vs", "basic.frag");
|
||||
|
||||
|
||||
// Set up vertex data (and buffer(s)) and attribute pointers
|
||||
GLfloat vertices[] = {
|
||||
// Positions // Colors
|
||||
0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, // Bottom Right
|
||||
-0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, // Bottom Left
|
||||
0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f // Top
|
||||
};
|
||||
GLuint VBO, VAO;
|
||||
glGenVertexArrays(1, &VAO);
|
||||
glGenBuffers(1, &VBO);
|
||||
// Bind the Vertex Array Object first, then bind and set vertex buffer(s) and attribute pointer(s).
|
||||
glBindVertexArray(VAO);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||
|
||||
// Position attribute
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
// Color attribute
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
|
||||
glEnableVertexAttribArray(1);
|
||||
|
||||
glBindVertexArray(0); // Unbind VAO
|
||||
|
||||
|
||||
// Game loop
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
// Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functions
|
||||
glfwPollEvents();
|
||||
|
||||
// Render
|
||||
// Clear the colorbuffer
|
||||
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
// Draw the triangle
|
||||
ourShader.Use();
|
||||
glBindVertexArray(VAO);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
glBindVertexArray(0);
|
||||
|
||||
// Swap the screen buffers
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
// Properly de-allocate all resources once they've outlived their purpose
|
||||
glDeleteVertexArrays(1, &VAO);
|
||||
glDeleteBuffers(1, &VBO);
|
||||
// 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);
|
||||
}
|
||||
15
src/1.getting_started/4.textures/texture.frag
Normal file
15
src/1.getting_started/4.textures/texture.frag
Normal file
@@ -0,0 +1,15 @@
|
||||
#version 330 core
|
||||
in vec3 ourColor;
|
||||
in vec2 TexCoord;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
// Texture samplers
|
||||
uniform sampler2D ourTexture1;
|
||||
uniform sampler2D ourTexture2;
|
||||
|
||||
void main()
|
||||
{
|
||||
// Linearly interpolate between both textures (second texture is only slightly combined)
|
||||
color = mix(texture(ourTexture1, TexCoord), texture(ourTexture2, TexCoord), 0.2);
|
||||
}
|
||||
16
src/1.getting_started/4.textures/texture.vs
Normal file
16
src/1.getting_started/4.textures/texture.vs
Normal file
@@ -0,0 +1,16 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 position;
|
||||
layout (location = 1) in vec3 color;
|
||||
layout (location = 2) in vec2 texCoord;
|
||||
|
||||
out vec3 ourColor;
|
||||
out vec2 TexCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(position, 1.0f);
|
||||
ourColor = color;
|
||||
// We swap the y-axis by substracing our coordinates from 1. This is done because most images have the top y-axis inversed with OpenGL's top y-axis.
|
||||
// TexCoord = texCoord;
|
||||
TexCoord = vec2(texCoord.x, 1.0 - texCoord.y);
|
||||
}
|
||||
177
src/1.getting_started/4.textures/textures_combined.cpp
Normal file
177
src/1.getting_started/4.textures/textures_combined.cpp
Normal file
@@ -0,0 +1,177 @@
|
||||
#include <iostream>
|
||||
|
||||
// GLEW
|
||||
#define GLEW_STATIC
|
||||
#include <GL/glew.h>
|
||||
|
||||
// GLFW
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
// Other Libs
|
||||
#include <SOIL.h>
|
||||
|
||||
// Other includes
|
||||
#include <learnopengl/shader.h>
|
||||
|
||||
|
||||
// Function prototypes
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
|
||||
|
||||
// Window dimensions
|
||||
const GLuint WIDTH = 800, HEIGHT = 600;
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
|
||||
// Build and compile our shader program
|
||||
Shader ourShader("texture.vs", "texture.frag");
|
||||
|
||||
|
||||
// Set up vertex data (and buffer(s)) and attribute pointers
|
||||
GLfloat vertices[] = {
|
||||
// Positions // Colors // Texture Coords
|
||||
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // Top Right
|
||||
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // Bottom Right
|
||||
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // Bottom Left
|
||||
-0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // Top Left
|
||||
};
|
||||
GLuint indices[] = { // Note that we start from 0!
|
||||
0, 1, 3, // First Triangle
|
||||
1, 2, 3 // Second Triangle
|
||||
};
|
||||
GLuint VBO, VAO, EBO;
|
||||
glGenVertexArrays(1, &VAO);
|
||||
glGenBuffers(1, &VBO);
|
||||
glGenBuffers(1, &EBO);
|
||||
|
||||
glBindVertexArray(VAO);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
|
||||
|
||||
// Position attribute
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
// Color attribute
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
|
||||
glEnableVertexAttribArray(1);
|
||||
// TexCoord attribute
|
||||
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
|
||||
glEnableVertexAttribArray(2);
|
||||
|
||||
glBindVertexArray(0); // Unbind VAO
|
||||
|
||||
|
||||
// Load and create a texture
|
||||
GLuint texture1;
|
||||
GLuint texture2;
|
||||
// ====================
|
||||
// Texture 1
|
||||
// ====================
|
||||
glGenTextures(1, &texture1);
|
||||
glBindTexture(GL_TEXTURE_2D, texture1); // All upcoming GL_TEXTURE_2D operations now have effect on our texture object
|
||||
// Set our texture parameters
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Set texture wrapping to GL_REPEAT
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
// Set texture filtering
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
// Load, create texture and generate mipmaps
|
||||
int width, height;
|
||||
unsigned char* image = SOIL_load_image("../../../resources/textures/container.jpg", &width, &height, 0, SOIL_LOAD_RGB);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
SOIL_free_image_data(image);
|
||||
glBindTexture(GL_TEXTURE_2D, 0); // Unbind texture when done, so we won't accidentily mess up our texture.
|
||||
// ===================
|
||||
// Texture 2
|
||||
// ===================
|
||||
glGenTextures(1, &texture2);
|
||||
glBindTexture(GL_TEXTURE_2D, texture2);
|
||||
// Set our texture parameters
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
// Set texture filtering
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
// Load, create texture and generate mipmaps
|
||||
image = SOIL_load_image("../../../resources/textures/awesomeface.png", &width, &height, 0, SOIL_LOAD_RGB);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
SOIL_free_image_data(image);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
|
||||
// Game loop
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
// Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functions
|
||||
glfwPollEvents();
|
||||
|
||||
// Render
|
||||
// Clear the colorbuffer
|
||||
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
|
||||
// Bind Textures using texture units
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, texture1);
|
||||
glUniform1i(glGetUniformLocation(ourShader.Program, "ourTexture1"), 0);
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, texture2);
|
||||
glUniform1i(glGetUniformLocation(ourShader.Program, "ourTexture2"), 1);
|
||||
|
||||
// Activate shader
|
||||
ourShader.Use();
|
||||
|
||||
// Draw container
|
||||
glBindVertexArray(VAO);
|
||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
|
||||
glBindVertexArray(0);
|
||||
|
||||
// Swap the screen buffers
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
// Properly de-allocate all resources once they've outlived their purpose
|
||||
glDeleteVertexArrays(1, &VAO);
|
||||
glDeleteBuffers(1, &VBO);
|
||||
glDeleteBuffers(1, &EBO);
|
||||
// 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);
|
||||
}
|
||||
12
src/1.getting_started/5.transformations/transform.frag
Normal file
12
src/1.getting_started/5.transformations/transform.frag
Normal file
@@ -0,0 +1,12 @@
|
||||
#version 330 core
|
||||
in vec2 TexCoord;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
uniform sampler2D ourTexture1;
|
||||
uniform sampler2D ourTexture2;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = mix(texture(ourTexture1, TexCoord), texture(ourTexture2, TexCoord), 0.2);
|
||||
}
|
||||
13
src/1.getting_started/5.transformations/transform.vs
Normal file
13
src/1.getting_started/5.transformations/transform.vs
Normal file
@@ -0,0 +1,13 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 position;
|
||||
layout (location = 2) in vec2 texCoord;
|
||||
|
||||
out vec2 TexCoord;
|
||||
|
||||
uniform mat4 transform;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = transform * vec4(position, 1.0f);
|
||||
TexCoord = vec2(texCoord.x, 1.0 - texCoord.y);
|
||||
}
|
||||
190
src/1.getting_started/5.transformations/transformations.cpp
Normal file
190
src/1.getting_started/5.transformations/transformations.cpp
Normal file
@@ -0,0 +1,190 @@
|
||||
#include <iostream>
|
||||
|
||||
// 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>
|
||||
|
||||
|
||||
// Function prototypes
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
|
||||
|
||||
// Window dimensions
|
||||
const GLuint WIDTH = 800, HEIGHT = 600;
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
|
||||
// Build and compile our shader program
|
||||
Shader ourShader("transform.vs", "transform.frag");
|
||||
|
||||
|
||||
// Set up vertex data (and buffer(s)) and attribute pointers
|
||||
GLfloat vertices[] = {
|
||||
// Positions // Colors // Texture Coords
|
||||
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // Top Right
|
||||
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // Bottom Right
|
||||
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // Bottom Left
|
||||
-0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // Top Left
|
||||
};
|
||||
GLuint indices[] = { // Note that we start from 0!
|
||||
0, 1, 3, // First Triangle
|
||||
1, 2, 3 // Second Triangle
|
||||
};
|
||||
GLuint VBO, VAO, EBO;
|
||||
glGenVertexArrays(1, &VAO);
|
||||
glGenBuffers(1, &VBO);
|
||||
glGenBuffers(1, &EBO);
|
||||
|
||||
glBindVertexArray(VAO);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
|
||||
|
||||
// Position attribute
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
// Color attribute
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
|
||||
glEnableVertexAttribArray(1);
|
||||
// TexCoord attribute
|
||||
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
|
||||
glEnableVertexAttribArray(2);
|
||||
|
||||
glBindVertexArray(0); // Unbind VAO
|
||||
|
||||
|
||||
// Load and create a texture
|
||||
GLuint texture1;
|
||||
GLuint texture2;
|
||||
// ====================
|
||||
// Texture 1
|
||||
// ====================
|
||||
glGenTextures(1, &texture1);
|
||||
glBindTexture(GL_TEXTURE_2D, texture1); // All upcoming GL_TEXTURE_2D operations now have effect on our texture object
|
||||
// Set our texture parameters
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Set texture wrapping to GL_REPEAT
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
// Set texture filtering
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
// Load, create texture and generate mipmaps
|
||||
int width, height;
|
||||
unsigned char* image = SOIL_load_image("../../../resources/textures/container.jpg", &width, &height, 0, SOIL_LOAD_RGB);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
SOIL_free_image_data(image);
|
||||
glBindTexture(GL_TEXTURE_2D, 0); // Unbind texture when done, so we won't accidentily mess up our texture.
|
||||
// ===================
|
||||
// Texture 2
|
||||
// ===================
|
||||
glGenTextures(1, &texture2);
|
||||
glBindTexture(GL_TEXTURE_2D, texture2);
|
||||
// Set our texture parameters
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
// Set texture filtering
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
// Load, create texture and generate mipmaps
|
||||
image = SOIL_load_image("../../../resources/textures/awesomeface.png", &width, &height, 0, SOIL_LOAD_RGB);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
SOIL_free_image_data(image);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
|
||||
// Game loop
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
// Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functions
|
||||
glfwPollEvents();
|
||||
|
||||
// Render
|
||||
// Clear the colorbuffer
|
||||
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
|
||||
// Bind Textures using texture units
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, texture1);
|
||||
glUniform1i(glGetUniformLocation(ourShader.Program, "ourTexture1"), 0);
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, texture2);
|
||||
glUniform1i(glGetUniformLocation(ourShader.Program, "ourTexture2"), 1);
|
||||
|
||||
// Activate shader
|
||||
ourShader.Use();
|
||||
|
||||
// Create transformations
|
||||
glm::mat4 transform;
|
||||
transform = glm::translate(transform, glm::vec3(0.5f, -0.5f, 0.0f));
|
||||
transform = glm::rotate(transform, (GLfloat)glfwGetTime() * 50.0f, glm::vec3(0.0f, 0.0f, 1.0f));
|
||||
|
||||
// Get matrix's uniform location and set matrix
|
||||
GLint transformLoc = glGetUniformLocation(ourShader.Program, "transform");
|
||||
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(transform));
|
||||
|
||||
// Draw container
|
||||
glBindVertexArray(VAO);
|
||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
|
||||
glBindVertexArray(0);
|
||||
|
||||
// Swap the screen buffers
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
// Properly de-allocate all resources once they've outlived their purpose
|
||||
glDeleteVertexArrays(1, &VAO);
|
||||
glDeleteBuffers(1, &VBO);
|
||||
glDeleteBuffers(1, &EBO);
|
||||
// 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);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#version 330 core
|
||||
in vec2 TexCoord;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
uniform sampler2D ourTexture1;
|
||||
uniform sampler2D ourTexture2;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = mix(texture(ourTexture1, TexCoord), texture(ourTexture2, TexCoord), 0.2);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 position;
|
||||
layout (location = 2) in vec2 texCoord;
|
||||
|
||||
out vec2 TexCoord;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projection * view * model * vec4(position, 1.0f);
|
||||
TexCoord = vec2(texCoord.x, 1.0 - texCoord.y);
|
||||
}
|
||||
@@ -0,0 +1,244 @@
|
||||
#include <iostream>
|
||||
|
||||
// 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>
|
||||
|
||||
|
||||
// Function prototypes
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
|
||||
|
||||
// Window dimensions
|
||||
const GLuint WIDTH = 800, HEIGHT = 600;
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
// Setup OpenGL options
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
|
||||
// Build and compile our shader program
|
||||
Shader ourShader("coordinate_systems.vs", "coordinate_systems.frag");
|
||||
|
||||
|
||||
// Set up vertex data (and buffer(s)) and attribute pointers
|
||||
GLfloat vertices[] = {
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
|
||||
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
|
||||
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f
|
||||
};
|
||||
// World space positions of our cubes
|
||||
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)
|
||||
};
|
||||
GLuint VBO, VAO;
|
||||
glGenVertexArrays(1, &VAO);
|
||||
glGenBuffers(1, &VBO);
|
||||
|
||||
glBindVertexArray(VAO);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||
|
||||
// Position attribute
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
// TexCoord attribute
|
||||
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
|
||||
glEnableVertexAttribArray(2);
|
||||
|
||||
glBindVertexArray(0); // Unbind VAO
|
||||
|
||||
|
||||
// Load and create a texture
|
||||
GLuint texture1;
|
||||
GLuint texture2;
|
||||
// ====================
|
||||
// Texture 1
|
||||
// ====================
|
||||
glGenTextures(1, &texture1);
|
||||
glBindTexture(GL_TEXTURE_2D, texture1); // All upcoming GL_TEXTURE_2D operations now have effect on our texture object
|
||||
// Set our texture parameters
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Set texture wrapping to GL_REPEAT
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
// Set texture filtering
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
// Load, create texture and generate mipmaps
|
||||
int width, height;
|
||||
unsigned char* image = SOIL_load_image("../../../resources/textures/container.jpg", &width, &height, 0, SOIL_LOAD_RGB);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
SOIL_free_image_data(image);
|
||||
glBindTexture(GL_TEXTURE_2D, 0); // Unbind texture when done, so we won't accidentily mess up our texture.
|
||||
// ===================
|
||||
// Texture 2
|
||||
// ===================
|
||||
glGenTextures(1, &texture2);
|
||||
glBindTexture(GL_TEXTURE_2D, texture2);
|
||||
// Set our texture parameters
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
// Set texture filtering
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
// Load, create texture and generate mipmaps
|
||||
image = SOIL_load_image("../../../resources/textures/awesomeface.png", &width, &height, 0, SOIL_LOAD_RGB);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
SOIL_free_image_data(image);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
|
||||
// Game loop
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
// Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functions
|
||||
glfwPollEvents();
|
||||
|
||||
// Render
|
||||
// Clear the colorbuffer
|
||||
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
|
||||
// Bind Textures using texture units
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, texture1);
|
||||
glUniform1i(glGetUniformLocation(ourShader.Program, "ourTexture1"), 0);
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, texture2);
|
||||
glUniform1i(glGetUniformLocation(ourShader.Program, "ourTexture2"), 1);
|
||||
|
||||
// Activate shader
|
||||
ourShader.Use();
|
||||
|
||||
// Create transformations
|
||||
glm::mat4 view;
|
||||
glm::mat4 projection;
|
||||
view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f));
|
||||
projection = glm::perspective(45.0f, (GLfloat)WIDTH / (GLfloat)HEIGHT, 0.1f, 100.0f);
|
||||
// Get their uniform location
|
||||
GLint modelLoc = glGetUniformLocation(ourShader.Program, "model");
|
||||
GLint viewLoc = glGetUniformLocation(ourShader.Program, "view");
|
||||
GLint projLoc = glGetUniformLocation(ourShader.Program, "projection");
|
||||
// Pass the matrices to the shader
|
||||
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
|
||||
// Note: currently we set the projection matrix each frame, but since the projection matrix rarely changes it's often best practice to set it outside the main loop only once.
|
||||
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
|
||||
|
||||
glBindVertexArray(VAO);
|
||||
for (GLuint i = 0; i < 10; i++)
|
||||
{
|
||||
// Calculate the model matrix for each object and pass it to shader before drawing
|
||||
glm::mat4 model;
|
||||
model = glm::translate(model, cubePositions[i]);
|
||||
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);
|
||||
|
||||
// Swap the screen buffers
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
// Properly de-allocate all resources once they've outlived their purpose
|
||||
glDeleteVertexArrays(1, &VAO);
|
||||
glDeleteBuffers(1, &VBO);
|
||||
// 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);
|
||||
}
|
||||
298
src/1.getting_started/7.camera/camera_with_class.cpp
Normal file
298
src/1.getting_started/7.camera/camera_with_class.cpp
Normal file
@@ -0,0 +1,298 @@
|
||||
// Std. Includes
|
||||
#include <string>
|
||||
|
||||
// GLEW
|
||||
#define GLEW_STATIC
|
||||
#include <GL/glew.h>
|
||||
|
||||
// GLFW
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
// GL includes
|
||||
#include <learnopengl/shader.h>
|
||||
#include <learnopengl/camera.h>
|
||||
|
||||
// GLM Mathemtics
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
// Other Libs
|
||||
#include <SOIL.h>
|
||||
|
||||
// Properties
|
||||
GLuint screenWidth = 800, screenHeight = 600;
|
||||
|
||||
// Function prototypes
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
|
||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
|
||||
void Do_Movement();
|
||||
|
||||
// Camera
|
||||
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
|
||||
bool keys[1024];
|
||||
GLfloat lastX = 400, lastY = 300;
|
||||
bool firstMouse = true;
|
||||
|
||||
GLfloat deltaTime = 0.0f;
|
||||
GLfloat lastFrame = 0.0f;
|
||||
|
||||
// The MAIN function, from here we start our application and run our Game loop
|
||||
int main()
|
||||
{
|
||||
// Init GLFW
|
||||
glfwInit();
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
|
||||
glfwWindowHint(GLFW_SAMPLES, 4);
|
||||
|
||||
GLFWwindow* window = glfwCreateWindow(screenWidth, screenHeight, "LearnOpenGL", nullptr, nullptr); // Windowed
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
// Set the required callback functions
|
||||
glfwSetKeyCallback(window, key_callback);
|
||||
glfwSetCursorPosCallback(window, mouse_callback);
|
||||
glfwSetScrollCallback(window, scroll_callback);
|
||||
|
||||
// Options
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
|
||||
// Initialize GLEW to setup the OpenGL Function pointers
|
||||
glewExperimental = GL_TRUE;
|
||||
glewInit();
|
||||
|
||||
// Define the viewport dimensions
|
||||
glViewport(0, 0, screenWidth, screenHeight);
|
||||
|
||||
// Setup some OpenGL options
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
// Setup and compile our shaders
|
||||
Shader ourShader("coordinate_systems.vs", "coordinate_systems.frag");
|
||||
|
||||
// Set up our vertex data (and buffer(s)) and attribute pointers
|
||||
GLfloat vertices[] = {
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
|
||||
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
|
||||
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f
|
||||
};
|
||||
glm::vec3 cubePositions[] = {
|
||||
glm::vec3(0.0f, 0.0f, 0.0f),
|
||||
glm::vec3(2.0f, 5.0f, -15.0f),
|
||||
glm::vec3(-1.5f, -2.2f, -2.5f),
|
||||
glm::vec3(-3.8f, -2.0f, -12.3f),
|
||||
glm::vec3(2.4f, -0.4f, -3.5f),
|
||||
glm::vec3(-1.7f, 3.0f, -7.5f),
|
||||
glm::vec3(1.3f, -2.0f, -2.5f),
|
||||
glm::vec3(1.5f, 2.0f, -2.5f),
|
||||
glm::vec3(1.5f, 0.2f, -1.5f),
|
||||
glm::vec3(-1.3f, 1.0f, -1.5f)
|
||||
};
|
||||
|
||||
GLuint VBO, VAO;
|
||||
glGenVertexArrays(1, &VAO);
|
||||
glGenBuffers(1, &VBO);
|
||||
// Bind our Vertex Array Object first, then bind and set our buffers and pointers.
|
||||
glBindVertexArray(VAO);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||
|
||||
// Position attribute
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
// TexCoord attribute
|
||||
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
|
||||
glEnableVertexAttribArray(2);
|
||||
|
||||
glBindVertexArray(0); // Unbind VAO
|
||||
|
||||
// Load and create a texture
|
||||
GLuint texture1;
|
||||
GLuint texture2;
|
||||
// --== TEXTURE 1 == --
|
||||
glGenTextures(1, &texture1);
|
||||
glBindTexture(GL_TEXTURE_2D, texture1); // All upcoming GL_TEXTURE_2D operations now have effect on our texture object
|
||||
// Set our texture parameters
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
// Set texture filtering
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
// Load, create texture and generate mipmaps
|
||||
int width, height;
|
||||
unsigned char* image = SOIL_load_image("../../../resources/textures/container.jpg", &width, &height, 0, SOIL_LOAD_RGB);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
SOIL_free_image_data(image);
|
||||
glBindTexture(GL_TEXTURE_2D, 0); // Unbind texture when done, so we won't accidentily mess up our texture.
|
||||
// --== TEXTURE 2 == --
|
||||
glGenTextures(1, &texture2);
|
||||
glBindTexture(GL_TEXTURE_2D, texture2);
|
||||
// Set our texture parameters
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
// Set texture filtering
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
// Load, create texture and generate mipmaps
|
||||
image = SOIL_load_image("../../../resources/textures/awesomeface.png", &width, &height, 0, SOIL_LOAD_RGB);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
SOIL_free_image_data(image);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
// Game loop
|
||||
while(!glfwWindowShouldClose(window))
|
||||
{
|
||||
// Set frame time
|
||||
GLfloat currentFrame = glfwGetTime();
|
||||
deltaTime = currentFrame - lastFrame;
|
||||
lastFrame = currentFrame;
|
||||
|
||||
// Check and call events
|
||||
glfwPollEvents();
|
||||
Do_Movement();
|
||||
|
||||
// Clear the colorbuffer
|
||||
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// Draw our first triangle
|
||||
ourShader.Use();
|
||||
|
||||
// Bind Textures using texture units
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, texture1);
|
||||
glUniform1i(glGetUniformLocation(ourShader.Program, "ourTexture1"), 0);
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, texture2);
|
||||
glUniform1i(glGetUniformLocation(ourShader.Program, "ourTexture2"), 1);
|
||||
|
||||
// Create camera transformation
|
||||
glm::mat4 view;
|
||||
view = camera.GetViewMatrix();
|
||||
glm::mat4 projection;
|
||||
projection = glm::perspective(camera.Zoom, (float)screenWidth/(float)screenHeight, 0.1f, 1000.0f);
|
||||
// Get the uniform locations
|
||||
GLint modelLoc = glGetUniformLocation(ourShader.Program, "model");
|
||||
GLint viewLoc = glGetUniformLocation(ourShader.Program, "view");
|
||||
GLint projLoc = glGetUniformLocation(ourShader.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));
|
||||
|
||||
glBindVertexArray(VAO);
|
||||
for(GLuint i = 0; i < 10; i++)
|
||||
{
|
||||
// Calculate the model matrix for each object and pass it to shader before drawing
|
||||
glm::mat4 model;
|
||||
model = glm::translate(model, cubePositions[i]);
|
||||
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);
|
||||
// Swap the buffers
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
// Properly de-allocate all resources once they've outlived their purpose
|
||||
glDeleteVertexArrays(1, &VAO);
|
||||
glDeleteBuffers(1, &VBO);
|
||||
glfwTerminate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Moves/alters the camera positions based on user input
|
||||
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);
|
||||
}
|
||||
|
||||
// Is called whenever a key is pressed/released via GLFW
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
|
||||
{
|
||||
//cout << key << endl;
|
||||
if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
|
||||
glfwSetWindowShouldClose(window, GL_TRUE);
|
||||
|
||||
if(action == GLFW_PRESS)
|
||||
keys[key] = true;
|
||||
else if(action == GLFW_RELEASE)
|
||||
keys[key] = false;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
12
src/1.getting_started/7.camera/coordinate_systems.frag
Normal file
12
src/1.getting_started/7.camera/coordinate_systems.frag
Normal file
@@ -0,0 +1,12 @@
|
||||
#version 330 core
|
||||
in vec2 TexCoord;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
uniform sampler2D ourTexture1;
|
||||
uniform sampler2D ourTexture2;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = mix(texture(ourTexture1, TexCoord), texture(ourTexture2, TexCoord), 0.2);
|
||||
}
|
||||
15
src/1.getting_started/7.camera/coordinate_systems.vs
Normal file
15
src/1.getting_started/7.camera/coordinate_systems.vs
Normal file
@@ -0,0 +1,15 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 position;
|
||||
layout (location = 2) in vec2 texCoord;
|
||||
|
||||
out vec2 TexCoord;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projection * view * model * vec4(position, 1.0f);
|
||||
TexCoord = vec2(texCoord.x, 1.0 - texCoord.y);
|
||||
}
|
||||
10
src/2.lighting/1.colors/colors.frag
Normal file
10
src/2.lighting/1.colors/colors.frag
Normal file
@@ -0,0 +1,10 @@
|
||||
#version 330 core
|
||||
out vec4 color;
|
||||
|
||||
uniform vec3 objectColor;
|
||||
uniform vec3 lightColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = vec4(lightColor * objectColor, 1.0f);
|
||||
}
|
||||
11
src/2.lighting/1.colors/colors.vs
Normal file
11
src/2.lighting/1.colors/colors.vs
Normal file
@@ -0,0 +1,11 @@
|
||||
#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);
|
||||
}
|
||||
272
src/2.lighting/1.colors/colors_scene.cpp
Normal file
272
src/2.lighting/1.colors/colors_scene.cpp
Normal file
@@ -0,0 +1,272 @@
|
||||
#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);
|
||||
}
|
||||
7
src/2.lighting/1.colors/lamp.frag
Normal file
7
src/2.lighting/1.colors/lamp.frag
Normal file
@@ -0,0 +1,7 @@
|
||||
#version 330 core
|
||||
out vec4 color;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = vec4(1.0f); // Set alle 4 vector values to 1.0f
|
||||
}
|
||||
11
src/2.lighting/1.colors/lamp.vs
Normal file
11
src/2.lighting/1.colors/lamp.vs
Normal file
@@ -0,0 +1,11 @@
|
||||
#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);
|
||||
}
|
||||
33
src/2.lighting/2.basic_lighting/basic_lighting.frag
Normal file
33
src/2.lighting/2.basic_lighting/basic_lighting.frag
Normal file
@@ -0,0 +1,33 @@
|
||||
#version 330 core
|
||||
out vec4 color;
|
||||
|
||||
in vec3 FragPos;
|
||||
in vec3 Normal;
|
||||
|
||||
uniform vec3 lightPos;
|
||||
uniform vec3 viewPos;
|
||||
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.0);
|
||||
vec3 diffuse = diff * lightColor;
|
||||
|
||||
// Specular
|
||||
float specularStrength = 0.5f;
|
||||
vec3 viewDir = normalize(viewPos - FragPos);
|
||||
vec3 reflectDir = reflect(-lightDir, norm);
|
||||
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);
|
||||
vec3 specular = specularStrength * spec * lightColor;
|
||||
|
||||
vec3 result = (ambient + diffuse + specular) * objectColor;
|
||||
color = vec4(result, 1.0f);
|
||||
}
|
||||
17
src/2.lighting/2.basic_lighting/basic_lighting.vs
Normal file
17
src/2.lighting/2.basic_lighting/basic_lighting.vs
Normal file
@@ -0,0 +1,17 @@
|
||||
#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;
|
||||
}
|
||||
281
src/2.lighting/2.basic_lighting/basic_lighting_specular.cpp
Normal file
281
src/2.lighting/2.basic_lighting/basic_lighting_specular.cpp
Normal file
@@ -0,0 +1,281 @@
|
||||
#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);
|
||||
}
|
||||
7
src/2.lighting/2.basic_lighting/lamp.frag
Normal file
7
src/2.lighting/2.basic_lighting/lamp.frag
Normal file
@@ -0,0 +1,7 @@
|
||||
#version 330 core
|
||||
out vec4 color;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = vec4(1.0f); // Set alle 4 vector values to 1.0f
|
||||
}
|
||||
11
src/2.lighting/2.basic_lighting/lamp.vs
Normal file
11
src/2.lighting/2.basic_lighting/lamp.vs
Normal file
@@ -0,0 +1,11 @@
|
||||
#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);
|
||||
}
|
||||
7
src/2.lighting/3.materials/lamp.frag
Normal file
7
src/2.lighting/3.materials/lamp.frag
Normal file
@@ -0,0 +1,7 @@
|
||||
#version 330 core
|
||||
out vec4 color;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = vec4(1.0f); // Set alle 4 vector values to 1.0f
|
||||
}
|
||||
11
src/2.lighting/3.materials/lamp.vs
Normal file
11
src/2.lighting/3.materials/lamp.vs
Normal file
@@ -0,0 +1,11 @@
|
||||
#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);
|
||||
}
|
||||
291
src/2.lighting/3.materials/materials.cpp
Normal file
291
src/2.lighting/3.materials/materials.cpp
Normal file
@@ -0,0 +1,291 @@
|
||||
#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);
|
||||
}
|
||||
45
src/2.lighting/3.materials/materials.frag
Normal file
45
src/2.lighting/3.materials/materials.frag
Normal file
@@ -0,0 +1,45 @@
|
||||
#version 330 core
|
||||
struct Material {
|
||||
vec3 ambient;
|
||||
vec3 diffuse;
|
||||
vec3 specular;
|
||||
float shininess;
|
||||
};
|
||||
|
||||
struct Light {
|
||||
vec3 position;
|
||||
|
||||
vec3 ambient;
|
||||
vec3 diffuse;
|
||||
vec3 specular;
|
||||
};
|
||||
|
||||
in vec3 FragPos;
|
||||
in vec3 Normal;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
uniform vec3 viewPos;
|
||||
uniform Material material;
|
||||
uniform Light light;
|
||||
|
||||
void main()
|
||||
{
|
||||
// Ambient
|
||||
vec3 ambient = light.ambient * material.ambient;
|
||||
|
||||
// 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
|
||||
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);
|
||||
}
|
||||
17
src/2.lighting/3.materials/materials.vs
Normal file
17
src/2.lighting/3.materials/materials.vs
Normal file
@@ -0,0 +1,17 @@
|
||||
#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;
|
||||
}
|
||||
7
src/2.lighting/4.lighting_maps/lamp.frag
Normal file
7
src/2.lighting/4.lighting_maps/lamp.frag
Normal file
@@ -0,0 +1,7 @@
|
||||
#version 330 core
|
||||
out vec4 color;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = vec4(1.0f); // Set alle 4 vector values to 1.0f
|
||||
}
|
||||
11
src/2.lighting/4.lighting_maps/lamp.vs
Normal file
11
src/2.lighting/4.lighting_maps/lamp.vs
Normal file
@@ -0,0 +1,11 @@
|
||||
#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);
|
||||
}
|
||||
44
src/2.lighting/4.lighting_maps/lighting_maps.frag
Normal file
44
src/2.lighting/4.lighting_maps/lighting_maps.frag
Normal file
@@ -0,0 +1,44 @@
|
||||
#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);
|
||||
}
|
||||
20
src/2.lighting/4.lighting_maps/lighting_maps.vs
Normal file
20
src/2.lighting/4.lighting_maps/lighting_maps.vs
Normal file
@@ -0,0 +1,20 @@
|
||||
#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;
|
||||
}
|
||||
326
src/2.lighting/4.lighting_maps/lighting_maps_specular.cpp
Normal file
326
src/2.lighting/4.lighting_maps/lighting_maps_specular.cpp
Normal file
@@ -0,0 +1,326 @@
|
||||
#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("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, emissionMap;
|
||||
glGenTextures(1, &diffuseMap);
|
||||
glGenTextures(1, &specularMap);
|
||||
glGenTextures(1, &emissionMap);
|
||||
int width, height;
|
||||
unsigned char* image;
|
||||
// Diffuse map
|
||||
image = SOIL_load_image("../../../resources/textures/container2.png", &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("../../../resources/textures/container2_specular.png", &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);
|
||||
}
|
||||
7
src/2.lighting/5.light_casters/lamp.frag
Normal file
7
src/2.lighting/5.light_casters/lamp.frag
Normal file
@@ -0,0 +1,7 @@
|
||||
#version 330 core
|
||||
out vec4 color;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = vec4(1.0f); // Set alle 4 vector values to 1.0f
|
||||
}
|
||||
11
src/2.lighting/5.light_casters/lamp.vs
Normal file
11
src/2.lighting/5.light_casters/lamp.vs
Normal file
@@ -0,0 +1,11 @@
|
||||
#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);
|
||||
}
|
||||
65
src/2.lighting/5.light_casters/light_casters.frag
Normal file
65
src/2.lighting/5.light_casters/light_casters.frag
Normal file
@@ -0,0 +1,65 @@
|
||||
#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);
|
||||
}
|
||||
20
src/2.lighting/5.light_casters/light_casters.vs
Normal file
20
src/2.lighting/5.light_casters/light_casters.vs
Normal file
@@ -0,0 +1,20 @@
|
||||
#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;
|
||||
}
|
||||
368
src/2.lighting/5.light_casters/light_casters_spotlight_soft.cpp
Normal file
368
src/2.lighting/5.light_casters/light_casters_spotlight_soft.cpp
Normal file
@@ -0,0 +1,368 @@
|
||||
#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("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("../../../resources/textures/container2.png", &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("../../../resources/textures/container2_specular.png", &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);
|
||||
}
|
||||
7
src/2.lighting/6.multiple_lights/lamp.frag
Normal file
7
src/2.lighting/6.multiple_lights/lamp.frag
Normal file
@@ -0,0 +1,7 @@
|
||||
#version 330 core
|
||||
out vec4 color;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = vec4(1.0f); // Set alle 4 vector values to 1.0f
|
||||
}
|
||||
11
src/2.lighting/6.multiple_lights/lamp.vs
Normal file
11
src/2.lighting/6.multiple_lights/lamp.vs
Normal file
@@ -0,0 +1,11 @@
|
||||
#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);
|
||||
}
|
||||
408
src/2.lighting/6.multiple_lights/multiple_lights.cpp
Normal file
408
src/2.lighting/6.multiple_lights/multiple_lights.cpp
Normal file
@@ -0,0 +1,408 @@
|
||||
#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("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("../../../resources/textures/container2.png", &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("../../../resources/textures/container2_specular.png", &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);
|
||||
}
|
||||
147
src/2.lighting/6.multiple_lights/multiple_lights.frag
Normal file
147
src/2.lighting/6.multiple_lights/multiple_lights.frag
Normal file
@@ -0,0 +1,147 @@
|
||||
#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);
|
||||
}
|
||||
20
src/2.lighting/6.multiple_lights/multiple_lights.vs
Normal file
20
src/2.lighting/6.multiple_lights/multiple_lights.vs
Normal file
@@ -0,0 +1,20 @@
|
||||
#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;
|
||||
}
|
||||
171
src/3.model_loading/1.model_loading/model_rendered.cpp
Normal file
171
src/3.model_loading/1.model_loading/model_rendered.cpp
Normal file
@@ -0,0 +1,171 @@
|
||||
// Std. Includes
|
||||
#include <string>
|
||||
|
||||
// GLEW
|
||||
#define GLEW_STATIC
|
||||
#include <GL/glew.h>
|
||||
|
||||
// GLFW
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
// GL includes
|
||||
#include <learnopengl/shader.h>
|
||||
#include <learnopengl/camera.h>
|
||||
#include <learnopengl/model.h>
|
||||
|
||||
// GLM Mathemtics
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
// Other Libs
|
||||
#include <SOIL.h>
|
||||
|
||||
// Properties
|
||||
GLuint screenWidth = 800, screenHeight = 600;
|
||||
|
||||
// Function prototypes
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
|
||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
|
||||
void Do_Movement();
|
||||
|
||||
// Camera
|
||||
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
|
||||
bool keys[1024];
|
||||
GLfloat lastX = 400, lastY = 300;
|
||||
bool firstMouse = true;
|
||||
|
||||
GLfloat deltaTime = 0.0f;
|
||||
GLfloat lastFrame = 0.0f;
|
||||
|
||||
// The MAIN function, from here we start our application and run our Game loop
|
||||
int main()
|
||||
{
|
||||
// Init GLFW
|
||||
glfwInit();
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
|
||||
|
||||
GLFWwindow* window = glfwCreateWindow(screenWidth, screenHeight, "LearnOpenGL", nullptr, nullptr); // Windowed
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
// Set the required callback functions
|
||||
glfwSetKeyCallback(window, key_callback);
|
||||
glfwSetCursorPosCallback(window, mouse_callback);
|
||||
glfwSetScrollCallback(window, scroll_callback);
|
||||
|
||||
// Options
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
|
||||
// Initialize GLEW to setup the OpenGL Function pointers
|
||||
glewExperimental = GL_TRUE;
|
||||
glewInit();
|
||||
|
||||
// Define the viewport dimensions
|
||||
glViewport(0, 0, screenWidth, screenHeight);
|
||||
|
||||
// Setup some OpenGL options
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
// Setup and compile our shaders
|
||||
Shader shader("shader.vs", "shader.frag");
|
||||
|
||||
// Load models
|
||||
Model ourModel("../../../resources/objects/nanosuit/nanosuit.obj");
|
||||
|
||||
// Draw in wireframe
|
||||
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
|
||||
// Game loop
|
||||
while(!glfwWindowShouldClose(window))
|
||||
{
|
||||
// Set frame time
|
||||
GLfloat currentFrame = glfwGetTime();
|
||||
deltaTime = currentFrame - lastFrame;
|
||||
lastFrame = currentFrame;
|
||||
|
||||
// Check and call events
|
||||
glfwPollEvents();
|
||||
Do_Movement();
|
||||
|
||||
// Clear the colorbuffer
|
||||
glClearColor(0.05f, 0.05f, 0.05f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
shader.Use(); // <-- Don't forget this one!
|
||||
// Transformation matrices
|
||||
glm::mat4 projection = glm::perspective(camera.Zoom, (float)screenWidth/(float)screenHeight, 0.1f, 100.0f);
|
||||
glm::mat4 view = camera.GetViewMatrix();
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view));
|
||||
|
||||
// Draw the loaded model
|
||||
glm::mat4 model;
|
||||
model = glm::translate(model, glm::vec3(0.0f, -1.75f, 0.0f)); // Translate it down a bit so it's at the center of the scene
|
||||
model = glm::scale(model, glm::vec3(0.2f, 0.2f, 0.2f)); // It's a bit too big for our scene, so scale it down
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||
ourModel.Draw(shader);
|
||||
|
||||
// Swap the buffers
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
|
||||
glfwTerminate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#pragma region "User input"
|
||||
|
||||
// Moves/alters the camera positions based on user input
|
||||
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);
|
||||
}
|
||||
|
||||
// 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(action == GLFW_PRESS)
|
||||
keys[key] = true;
|
||||
else if(action == GLFW_RELEASE)
|
||||
keys[key] = false;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
|
||||
camera.ProcessMouseMovement(xoffset, yoffset);
|
||||
}
|
||||
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
|
||||
{
|
||||
camera.ProcessMouseScroll(yoffset);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
10
src/3.model_loading/1.model_loading/shader.frag
Normal file
10
src/3.model_loading/1.model_loading/shader.frag
Normal file
@@ -0,0 +1,10 @@
|
||||
#version 330 core
|
||||
in vec2 TexCoords;
|
||||
out vec4 color;
|
||||
|
||||
uniform sampler2D texture_diffuse1;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = texture(texture_diffuse1, TexCoords);
|
||||
}
|
||||
16
src/3.model_loading/1.model_loading/shader.vs
Normal file
16
src/3.model_loading/1.model_loading/shader.vs
Normal file
@@ -0,0 +1,16 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 position;
|
||||
// layout (location = 1) in vec3 normal;
|
||||
layout (location = 2) in vec2 texCoords;
|
||||
|
||||
out vec2 TexCoords;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projection * view * model * vec4(position, 1.0f);
|
||||
TexCoords = texCoords;
|
||||
}
|
||||
16
src/4.advanced_opengl/1.depth_testing/depth_testing.frag
Normal file
16
src/4.advanced_opengl/1.depth_testing/depth_testing.frag
Normal file
@@ -0,0 +1,16 @@
|
||||
#version 330 core
|
||||
out vec4 color;
|
||||
|
||||
float LinearizeDepth(float depth) // Note that this ranges from [0,1] instead of up to 'far plane distance' since we divide by 'far'
|
||||
{
|
||||
float near = 0.1;
|
||||
float far = 100.0;
|
||||
float z = depth * 2.0 - 1.0; // Back to NDC
|
||||
return (2.0 * near) / (far + near - z * (far - near));
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
float depth = LinearizeDepth(gl_FragCoord.z);
|
||||
color = vec4(vec3(depth), 1.0f);
|
||||
}
|
||||
15
src/4.advanced_opengl/1.depth_testing/depth_testing.vs
Normal file
15
src/4.advanced_opengl/1.depth_testing/depth_testing.vs
Normal file
@@ -0,0 +1,15 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 position;
|
||||
layout (location = 1) in vec2 texCoords;
|
||||
|
||||
out vec2 TexCoords;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projection * view * model * vec4(position, 1.0f);
|
||||
TexCoords = texCoords;
|
||||
}
|
||||
290
src/4.advanced_opengl/1.depth_testing/depth_testing_func.cpp
Normal file
290
src/4.advanced_opengl/1.depth_testing/depth_testing_func.cpp
Normal file
@@ -0,0 +1,290 @@
|
||||
// Std. Includes
|
||||
#include <string>
|
||||
|
||||
// GLEW
|
||||
#define GLEW_STATIC
|
||||
#include <GL/glew.h>
|
||||
|
||||
// GLFW
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
// GL includes
|
||||
#include <learnopengl/shader.h>
|
||||
#include <learnopengl/camera.h>
|
||||
|
||||
// GLM Mathemtics
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
// Other Libs
|
||||
#include <SOIL.h>
|
||||
|
||||
// Properties
|
||||
GLuint screenWidth = 800, screenHeight = 600;
|
||||
|
||||
// Function prototypes
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
|
||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
|
||||
void Do_Movement();
|
||||
GLuint loadTexture(GLchar* path);
|
||||
|
||||
// Camera
|
||||
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
|
||||
bool keys[1024];
|
||||
GLfloat lastX = 400, lastY = 300;
|
||||
bool firstMouse = true;
|
||||
|
||||
GLfloat deltaTime = 0.0f;
|
||||
GLfloat lastFrame = 0.0f;
|
||||
|
||||
// The MAIN function, from here we start our application and run our Game loop
|
||||
int main()
|
||||
{
|
||||
// Init GLFW
|
||||
glfwInit();
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
|
||||
|
||||
GLFWwindow* window = glfwCreateWindow(screenWidth, screenHeight, "LearnOpenGL", nullptr, nullptr); // Windowed
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
// Set the required callback functions
|
||||
glfwSetKeyCallback(window, key_callback);
|
||||
glfwSetCursorPosCallback(window, mouse_callback);
|
||||
glfwSetScrollCallback(window, scroll_callback);
|
||||
|
||||
// Options
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
|
||||
// Initialize GLEW to setup the OpenGL Function pointers
|
||||
glewExperimental = GL_TRUE;
|
||||
glewInit();
|
||||
|
||||
// Define the viewport dimensions
|
||||
glViewport(0, 0, screenWidth, screenHeight);
|
||||
|
||||
// Setup some OpenGL options
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
// glDepthFunc(GL_ALWAYS); // Set to always pass the depth test (same effect as glDisable(GL_DEPTH_TEST))
|
||||
|
||||
// Setup and compile our shaders
|
||||
Shader shader("depth_testing.vs", "depth_testing.frag");
|
||||
|
||||
#pragma region "object_initialization"
|
||||
// Set the object data (buffers, vertex attributes)
|
||||
GLfloat cubeVertices[] = {
|
||||
// Positions // Texture Coords
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
|
||||
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
|
||||
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f
|
||||
};
|
||||
GLfloat planeVertices[] = {
|
||||
// Positions // Texture Coords (note we set these higher than 1 that together with GL_REPEAT as texture wrapping mode will cause the floor texture to repeat)
|
||||
5.0f, -0.5f, 5.0f, 2.0f, 0.0f,
|
||||
-5.0f, -0.5f, 5.0f, 0.0f, 0.0f,
|
||||
-5.0f, -0.5f, -5.0f, 0.0f, 2.0f,
|
||||
|
||||
5.0f, -0.5f, 5.0f, 2.0f, 0.0f,
|
||||
-5.0f, -0.5f, -5.0f, 0.0f, 2.0f,
|
||||
5.0f, -0.5f, -5.0f, 2.0f, 2.0f
|
||||
};
|
||||
// Setup cube VAO
|
||||
GLuint cubeVAO, cubeVBO;
|
||||
glGenVertexArrays(1, &cubeVAO);
|
||||
glGenBuffers(1, &cubeVBO);
|
||||
glBindVertexArray(cubeVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), &cubeVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
|
||||
glBindVertexArray(0);
|
||||
// Setup plane VAO
|
||||
GLuint planeVAO, planeVBO;
|
||||
glGenVertexArrays(1, &planeVAO);
|
||||
glGenBuffers(1, &planeVBO);
|
||||
glBindVertexArray(planeVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, planeVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(planeVertices), &planeVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
|
||||
glBindVertexArray(0);
|
||||
|
||||
// Load textures
|
||||
GLuint cubeTexture = loadTexture("../../../resources/textures/marble.jpg");
|
||||
GLuint floorTexture = loadTexture("../../../resources/textures/metal.png");
|
||||
#pragma endregion
|
||||
|
||||
// Game loop
|
||||
while(!glfwWindowShouldClose(window))
|
||||
{
|
||||
// Set frame time
|
||||
GLfloat currentFrame = glfwGetTime();
|
||||
deltaTime = currentFrame - lastFrame;
|
||||
lastFrame = currentFrame;
|
||||
|
||||
// Check and call events
|
||||
glfwPollEvents();
|
||||
Do_Movement();
|
||||
|
||||
// Clear the colorbuffer
|
||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// Draw objects
|
||||
shader.Use();
|
||||
glm::mat4 model;
|
||||
glm::mat4 view = camera.GetViewMatrix();
|
||||
glm::mat4 projection = glm::perspective(camera.Zoom, (float)screenWidth/(float)screenHeight, 0.1f, 100.0f);
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
|
||||
// Cubes
|
||||
glBindVertexArray(cubeVAO);
|
||||
glBindTexture(GL_TEXTURE_2D, cubeTexture); // We omit the glActiveTexture part since TEXTURE0 is already the default active texture unit. (sampler used in fragment is set to 0 as well as default)
|
||||
model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
model = glm::mat4();
|
||||
model = glm::translate(model, glm::vec3(2.0f, 0.0f, 0.0f));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
// Floor
|
||||
glBindVertexArray(planeVAO);
|
||||
glBindTexture(GL_TEXTURE_2D, floorTexture);
|
||||
model = glm::mat4();
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
glBindVertexArray(0);
|
||||
|
||||
|
||||
// Swap the buffers
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
|
||||
glfwTerminate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This function loads a texture from file. Note: texture loading functions like these are usually
|
||||
// managed by a 'Resource Manager' that manages all resources (like textures, models, audio).
|
||||
// For learning purposes we'll just define it as a utility function.
|
||||
GLuint loadTexture(GLchar* path)
|
||||
{
|
||||
//Generate texture ID and load texture data
|
||||
GLuint textureID;
|
||||
glGenTextures(1, &textureID);
|
||||
int width,height;
|
||||
unsigned char* image = SOIL_load_image(path, &width, &height, 0, SOIL_LOAD_RGB);
|
||||
// Assign texture to ID
|
||||
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
// Parameters
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
SOIL_free_image_data(image);
|
||||
return textureID;
|
||||
|
||||
}
|
||||
|
||||
#pragma region "User input"
|
||||
|
||||
// Moves/alters the camera positions based on user input
|
||||
void Do_Movement()
|
||||
{
|
||||
// Camera controls
|
||||
if(keys[GLFW_KEY_W])
|
||||
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);
|
||||
}
|
||||
|
||||
// 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(action == GLFW_PRESS)
|
||||
keys[key] = true;
|
||||
else if(action == GLFW_RELEASE)
|
||||
keys[key] = false;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
|
||||
camera.ProcessMouseMovement(xoffset, yoffset);
|
||||
}
|
||||
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
|
||||
{
|
||||
camera.ProcessMouseScroll(yoffset);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
10
src/4.advanced_opengl/10.instancing/instanced_asteroids.frag
Normal file
10
src/4.advanced_opengl/10.instancing/instanced_asteroids.frag
Normal file
@@ -0,0 +1,10 @@
|
||||
#version 330 core
|
||||
in vec2 TexCoords;
|
||||
out vec4 color;
|
||||
|
||||
uniform sampler2D texture_diffuse1;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = texture(texture_diffuse1, TexCoords);
|
||||
}
|
||||
15
src/4.advanced_opengl/10.instancing/instanced_asteroids.vs
Normal file
15
src/4.advanced_opengl/10.instancing/instanced_asteroids.vs
Normal file
@@ -0,0 +1,15 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 position;
|
||||
layout (location = 2) in vec2 texCoords;
|
||||
layout (location = 3) in mat4 instanceMatrix;
|
||||
|
||||
out vec2 TexCoords;
|
||||
|
||||
uniform mat4 projection;
|
||||
uniform mat4 view;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projection * view * instanceMatrix * vec4(position, 1.0f);
|
||||
TexCoords = texCoords;
|
||||
}
|
||||
@@ -0,0 +1,238 @@
|
||||
// GLEW
|
||||
#define GLEW_STATIC
|
||||
#include <GL/glew.h>
|
||||
|
||||
// GLFW
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
// GL includes
|
||||
#include <learnopengl/shader.h>
|
||||
#include <learnopengl/camera.h>
|
||||
#include <learnopengl/model.h>
|
||||
|
||||
// GLM Mathemtics
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
// Properties
|
||||
GLuint screenWidth = 800, screenHeight = 600;
|
||||
|
||||
// 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 Do_Movement();
|
||||
|
||||
// Camera
|
||||
Camera camera(glm::vec3(0.0f, 0.0f, 155.0f));
|
||||
bool keys[1024];
|
||||
GLfloat lastX = 400, lastY = 300;
|
||||
bool firstMouse = true;
|
||||
|
||||
GLfloat deltaTime = 0.0f;
|
||||
GLfloat lastFrame = 0.0f;
|
||||
|
||||
// The MAIN function, from here we start our application and run our Game loop
|
||||
int main()
|
||||
{
|
||||
// Init GLFW
|
||||
glfwInit();
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
|
||||
|
||||
GLFWwindow* window = glfwCreateWindow(screenWidth, screenHeight, "LearnOpenGL", nullptr, nullptr); // Windowed
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
// Set the required callback functions
|
||||
glfwSetKeyCallback(window, key_callback);
|
||||
glfwSetCursorPosCallback(window, mouse_callback);
|
||||
|
||||
// Options
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
|
||||
// Initialize GLEW to setup the OpenGL Function pointers
|
||||
glewExperimental = GL_TRUE;
|
||||
glewInit();
|
||||
|
||||
// Define the viewport dimensions
|
||||
glViewport(0, 0, screenWidth, screenHeight);
|
||||
|
||||
// Setup OpenGL options
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
// Setup and compile our shaders
|
||||
Shader planetShader("planet.vs", "planet.frag");
|
||||
Shader instanceShader("instanced_asteroids.vs", "instanced_asteroids.frag");
|
||||
|
||||
// Load models
|
||||
Model rock("../../../resources/objects/rock/rock.obj");
|
||||
Model planet("../../../resources/objects/planet/planet.obj");
|
||||
|
||||
// Set projection matrix
|
||||
glm::mat4 projection = glm::perspective(45.0f, (GLfloat)screenWidth/(GLfloat)screenHeight, 1.0f, 10000.0f);
|
||||
planetShader.Use();
|
||||
glUniformMatrix4fv(glGetUniformLocation(planetShader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
|
||||
// Also of instance shader
|
||||
instanceShader.Use();
|
||||
glUniformMatrix4fv(glGetUniformLocation(instanceShader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
|
||||
|
||||
// Generate a large list of semi-random model transformation matrices
|
||||
GLuint amount = 100000;
|
||||
glm::mat4* modelMatrices;
|
||||
modelMatrices = new glm::mat4[amount];
|
||||
srand(glfwGetTime()); // initialize random seed
|
||||
GLfloat radius = 150.0f;
|
||||
GLfloat offset = 25.0f;
|
||||
for(GLuint i = 0; i < amount; i++)
|
||||
{
|
||||
glm::mat4 model;
|
||||
// 1. Translation: Randomly displace along circle with radius 'radius' in range [-offset, offset]
|
||||
GLfloat angle = (GLfloat)i / (GLfloat)amount * 360.0f;
|
||||
GLfloat displacement = (rand() % (GLint)(2 * offset * 100)) / 100.0f - offset;
|
||||
GLfloat x = sin(angle) * radius + displacement;
|
||||
displacement = (rand() % (GLint)(2 * offset * 100)) / 100.0f - offset;
|
||||
GLfloat y = -2.5f + displacement * 0.4f; // Keep height of asteroid field smaller compared to width of x and z
|
||||
displacement = (rand() % (GLint)(2 * offset * 100)) / 100.0f - offset;
|
||||
GLfloat z = cos(angle) * radius + displacement;
|
||||
model = glm::translate(model, glm::vec3(x, y, z));
|
||||
|
||||
// 2. Scale: Scale between 0.05 and 0.25f
|
||||
GLfloat scale = (rand() % 20) / 100.0f + 0.05;
|
||||
model = glm::scale(model, glm::vec3(scale));
|
||||
|
||||
// 3. Rotation: add random rotation around a (semi)randomly picked rotation axis vector
|
||||
GLfloat rotAngle = (rand() % 360);
|
||||
model = glm::rotate(model, rotAngle, glm::vec3(0.4f, 0.6f, 0.8f));
|
||||
|
||||
// 4. Now add to list of matrices
|
||||
modelMatrices[i] = model;
|
||||
}
|
||||
|
||||
// Set transformation matrices as an instance vertex attribute (with divisor 1)
|
||||
// NOTE: We're cheating a little by taking the, now publicly declared, VAO of the model's mesh(es) and adding new vertexAttribPointers
|
||||
// Normally you'd want to do this in a more organized fashion, but for learning purposes this will do.
|
||||
for(GLuint i = 0; i < rock.meshes.size(); i++)
|
||||
{
|
||||
GLuint VAO = rock.meshes[i].VAO;
|
||||
GLuint buffer;
|
||||
glBindVertexArray(VAO);
|
||||
glGenBuffers(1, &buffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, amount * sizeof(glm::mat4), &modelMatrices[0], GL_STATIC_DRAW);
|
||||
// Set attribute pointers for matrix (4 times vec4)
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (GLvoid*)0);
|
||||
glEnableVertexAttribArray(4);
|
||||
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (GLvoid*)(sizeof(glm::vec4)));
|
||||
glEnableVertexAttribArray(5);
|
||||
glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (GLvoid*)(2 * sizeof(glm::vec4)));
|
||||
glEnableVertexAttribArray(6);
|
||||
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (GLvoid*)(3 * sizeof(glm::vec4)));
|
||||
|
||||
glVertexAttribDivisor(3, 1);
|
||||
glVertexAttribDivisor(4, 1);
|
||||
glVertexAttribDivisor(5, 1);
|
||||
glVertexAttribDivisor(6, 1);
|
||||
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
// Game loop
|
||||
while(!glfwWindowShouldClose(window))
|
||||
{
|
||||
// Set frame time
|
||||
GLfloat currentFrame = glfwGetTime();
|
||||
deltaTime = currentFrame - lastFrame;
|
||||
lastFrame = currentFrame;
|
||||
|
||||
// Check and call events
|
||||
glfwPollEvents();
|
||||
Do_Movement();
|
||||
|
||||
// Clear buffers
|
||||
glClearColor(0.03f, 0.03f, 0.03f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// Add transformation matrices
|
||||
planetShader.Use();
|
||||
glUniformMatrix4fv(glGetUniformLocation(planetShader.Program, "view"), 1, GL_FALSE, glm::value_ptr(camera.GetViewMatrix()));
|
||||
instanceShader.Use();
|
||||
glUniformMatrix4fv(glGetUniformLocation(instanceShader.Program, "view"), 1, GL_FALSE, glm::value_ptr(camera.GetViewMatrix()));
|
||||
|
||||
// Draw Planet
|
||||
planetShader.Use();
|
||||
glm::mat4 model;
|
||||
model = glm::translate(model, glm::vec3(0.0f, -5.0f, 0.0f));
|
||||
model = glm::scale(model, glm::vec3(4.0f, 4.0f, 4.0f));
|
||||
glUniformMatrix4fv(glGetUniformLocation(planetShader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||
planet.Draw(planetShader);
|
||||
|
||||
// Draw meteorites
|
||||
instanceShader.Use();
|
||||
glBindTexture(GL_TEXTURE_2D, rock.textures_loaded[0].id); // Note we also made the textures_loaded vector public (instead of private) from the model class.
|
||||
for(GLuint i = 0; i < rock.meshes.size(); i++)
|
||||
{
|
||||
glBindVertexArray(rock.meshes[i].VAO);
|
||||
glDrawElementsInstanced(GL_TRIANGLES, rock.meshes[i].vertices.size(), GL_UNSIGNED_INT, 0, amount);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
// Swap the buffers
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
|
||||
delete[] modelMatrices;
|
||||
|
||||
glfwTerminate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#pragma region "User input"
|
||||
|
||||
// Moves/alters the camera positions based on user input
|
||||
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);
|
||||
}
|
||||
|
||||
// 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(action == GLFW_PRESS)
|
||||
keys[key] = true;
|
||||
else if(action == GLFW_RELEASE)
|
||||
keys[key] = false;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
|
||||
camera.ProcessMouseMovement(xoffset, yoffset);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
10
src/4.advanced_opengl/10.instancing/planet.frag
Normal file
10
src/4.advanced_opengl/10.instancing/planet.frag
Normal file
@@ -0,0 +1,10 @@
|
||||
#version 330 core
|
||||
in vec2 TexCoords;
|
||||
out vec4 color;
|
||||
|
||||
uniform sampler2D texture_diffuse1;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = texture(texture_diffuse1, TexCoords);
|
||||
}
|
||||
15
src/4.advanced_opengl/10.instancing/planet.vs
Normal file
15
src/4.advanced_opengl/10.instancing/planet.vs
Normal file
@@ -0,0 +1,15 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 position;
|
||||
layout (location = 2) in vec2 texCoords;
|
||||
|
||||
out vec2 TexCoords;
|
||||
|
||||
uniform mat4 projection;
|
||||
uniform mat4 view;
|
||||
uniform mat4 model;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projection * view * model * vec4(position, 1.0f);
|
||||
TexCoords = texCoords;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#version 330 core
|
||||
out vec4 color;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = vec4(0.0, 1.0, 0.0, 1.0);
|
||||
}
|
||||
11
src/4.advanced_opengl/11.anti_aliasing/anti_aliasing.vs
Normal file
11
src/4.advanced_opengl/11.anti_aliasing/anti_aliasing.vs
Normal file
@@ -0,0 +1,11 @@
|
||||
#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,255 @@
|
||||
// GLEW
|
||||
#define GLEW_STATIC
|
||||
#include <GL/glew.h>
|
||||
|
||||
// GLFW
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
// GL includes
|
||||
#include <learnopengl/shader.h>
|
||||
#include <learnopengl/camera.h>
|
||||
|
||||
// GLM Mathemtics
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
// Properties
|
||||
GLuint screenWidth = 800, screenHeight = 600;
|
||||
|
||||
// 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();
|
||||
GLuint generateMultiSampleTexture(GLuint samples);
|
||||
|
||||
// Camera
|
||||
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
|
||||
bool keys[1024];
|
||||
GLfloat lastX = 400, lastY = 300;
|
||||
bool firstMouse = true;
|
||||
|
||||
GLfloat deltaTime = 0.0f;
|
||||
GLfloat lastFrame = 0.0f;
|
||||
|
||||
// The MAIN function, from here we start our application and run our Game loop
|
||||
int main()
|
||||
{
|
||||
// Init GLFW
|
||||
glfwInit();
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
|
||||
|
||||
GLFWwindow* window = glfwCreateWindow(screenWidth, screenHeight, "LearnOpenGL", nullptr, nullptr); // Windowed
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
// Set the required callback functions
|
||||
glfwSetKeyCallback(window, key_callback);
|
||||
glfwSetCursorPosCallback(window, mouse_callback);
|
||||
glfwSetScrollCallback(window, scroll_callback);
|
||||
|
||||
// Options
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
|
||||
// Initialize GLEW to setup the OpenGL Function pointers
|
||||
glewExperimental = GL_TRUE;
|
||||
glewInit();
|
||||
|
||||
// Define the viewport dimensions
|
||||
glViewport(0, 0, screenWidth, screenHeight);
|
||||
|
||||
// Setup OpenGL options
|
||||
glEnable(GL_MULTISAMPLE); // Enabled by default on some drivers, but not all so always enable to make sure
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
// Setup and compile our shaders
|
||||
Shader shader("anti_aliasing.vs", "anti_aliasing.frag");
|
||||
|
||||
#pragma region "object_initialization"
|
||||
// Set the object data (buffers, vertex attributes)
|
||||
GLfloat cubeVertices[] = {
|
||||
// Positions
|
||||
-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
|
||||
};
|
||||
// Setup cube VAO
|
||||
GLuint cubeVAO, cubeVBO;
|
||||
glGenVertexArrays(1, &cubeVAO);
|
||||
glGenBuffers(1, &cubeVBO);
|
||||
glBindVertexArray(cubeVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), &cubeVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glBindVertexArray(0);
|
||||
#pragma endregion
|
||||
|
||||
|
||||
// Framebuffers
|
||||
GLuint framebuffer;
|
||||
glGenFramebuffers(1, &framebuffer);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
|
||||
// Create a multisampled color attachment texture
|
||||
GLuint textureColorBufferMultiSampled = generateMultiSampleTexture(4);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, textureColorBufferMultiSampled, 0);
|
||||
// Create a renderbuffer object for depth and stencil attachments
|
||||
GLuint rbo;
|
||||
glGenRenderbuffers(1, &rbo);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
|
||||
glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, screenWidth, screenHeight);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
|
||||
|
||||
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||
std::cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << std::endl;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
|
||||
// Game loop
|
||||
while(!glfwWindowShouldClose(window))
|
||||
{
|
||||
// Set frame time
|
||||
GLfloat currentFrame = glfwGetTime();
|
||||
deltaTime = currentFrame - lastFrame;
|
||||
lastFrame = currentFrame;
|
||||
|
||||
// Check and call events
|
||||
glfwPollEvents();
|
||||
Do_Movement();
|
||||
|
||||
// 1. Draw scene as normal in multisampled buffers
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
|
||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// Set transformation matrices
|
||||
shader.Use();
|
||||
glm::mat4 projection = glm::perspective(camera.Zoom, (GLfloat)screenWidth/(GLfloat)screenHeight, 0.1f, 1000.0f);
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "view"), 1, GL_FALSE, glm::value_ptr(camera.GetViewMatrix()));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(glm::mat4()));
|
||||
|
||||
glBindVertexArray(cubeVAO);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
glBindVertexArray(0);
|
||||
|
||||
// 2. Now blit multisampled buffer(s) to default framebuffers
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
glBlitFramebuffer(0, 0, screenWidth, screenHeight, 0, 0, screenWidth, screenHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
|
||||
// Swap the buffers
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
|
||||
|
||||
glfwTerminate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
GLuint generateMultiSampleTexture(GLuint samples)
|
||||
{
|
||||
GLuint texture;
|
||||
glGenTextures(1, &texture);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture);
|
||||
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGB, screenWidth, screenHeight, GL_TRUE);
|
||||
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
#pragma region "User input"
|
||||
|
||||
// Moves/alters the camera positions based on user input
|
||||
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);
|
||||
}
|
||||
|
||||
// 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(action == GLFW_PRESS)
|
||||
keys[key] = true;
|
||||
else if(action == GLFW_RELEASE)
|
||||
keys[key] = false;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
|
||||
camera.ProcessMouseMovement(xoffset, yoffset);
|
||||
}
|
||||
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
|
||||
{
|
||||
camera.ProcessMouseScroll(yoffset);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
@@ -0,0 +1,7 @@
|
||||
#version 330 core
|
||||
out vec4 outColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
outColor = vec4(0.04, 0.28, 0.26, 1.0);
|
||||
}
|
||||
337
src/4.advanced_opengl/2.stencil_testing/stencil_testing.cpp
Normal file
337
src/4.advanced_opengl/2.stencil_testing/stencil_testing.cpp
Normal file
@@ -0,0 +1,337 @@
|
||||
// Std. Includes
|
||||
#include <string>
|
||||
|
||||
// GLEW
|
||||
#define GLEW_STATIC
|
||||
#include <GL/glew.h>
|
||||
|
||||
// GLFW
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
// GL includes
|
||||
#include <learnopengl/shader.h>
|
||||
#include <learnopengl/camera.h>
|
||||
|
||||
// GLM Mathemtics
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
// Other Libs
|
||||
#include <SOIL.h>
|
||||
|
||||
// Properties
|
||||
GLuint screenWidth = 800, screenHeight = 600;
|
||||
|
||||
// Function prototypes
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
|
||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
|
||||
void Do_Movement();
|
||||
GLuint loadTexture(GLchar* path);
|
||||
|
||||
// Camera
|
||||
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
|
||||
bool keys[1024];
|
||||
GLfloat lastX = 400, lastY = 300;
|
||||
bool firstMouse = true;
|
||||
|
||||
GLfloat deltaTime = 0.0f;
|
||||
GLfloat lastFrame = 0.0f;
|
||||
|
||||
// The MAIN function, from here we start our application and run our Game loop
|
||||
int main()
|
||||
{
|
||||
// Init GLFW
|
||||
glfwInit();
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
|
||||
|
||||
GLFWwindow* window = glfwCreateWindow(screenWidth, screenHeight, "LearnOpenGL", nullptr, nullptr); // Windowed
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
// Set the required callback functions
|
||||
glfwSetKeyCallback(window, key_callback);
|
||||
glfwSetCursorPosCallback(window, mouse_callback);
|
||||
glfwSetScrollCallback(window, scroll_callback);
|
||||
|
||||
// Options
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
|
||||
// Initialize GLEW to setup the OpenGL Function pointers
|
||||
glewExperimental = GL_TRUE;
|
||||
glewInit();
|
||||
|
||||
// Define the viewport dimensions
|
||||
glViewport(0, 0, screenWidth, screenHeight);
|
||||
|
||||
// Setup some OpenGL options
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LESS);
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
||||
|
||||
// Setup and compile our shaders
|
||||
Shader shader("stencil_testing.vs", "stencil_testing.frag");
|
||||
Shader shaderSingleColor("stencil_testing.vs", "stencil_single_color.frag");
|
||||
|
||||
#pragma region "object_initialization"
|
||||
// Set the object data (buffers, vertex attributes)
|
||||
GLfloat cubeVertices[] = {
|
||||
// Positions // Texture Coords
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
|
||||
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
|
||||
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f
|
||||
};
|
||||
GLfloat planeVertices[] = {
|
||||
// Positions // Texture Coords (note we set these higher than 1 that together with GL_REPEAT (as texture wrapping mode) will cause the floor texture to repeat)
|
||||
5.0f, -0.5f, 5.0f, 2.0f, 0.0f,
|
||||
-5.0f, -0.5f, 5.0f, 0.0f, 0.0f,
|
||||
-5.0f, -0.5f, -5.0f, 0.0f, 2.0f,
|
||||
|
||||
5.0f, -0.5f, 5.0f, 2.0f, 0.0f,
|
||||
-5.0f, -0.5f, -5.0f, 0.0f, 2.0f,
|
||||
5.0f, -0.5f, -5.0f, 2.0f, 2.0f
|
||||
};
|
||||
// Setup cube VAO
|
||||
GLuint cubeVAO, cubeVBO;
|
||||
glGenVertexArrays(1, &cubeVAO);
|
||||
glGenBuffers(1, &cubeVBO);
|
||||
glBindVertexArray(cubeVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), &cubeVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
|
||||
glBindVertexArray(0);
|
||||
// Setup plane VAO
|
||||
GLuint planeVAO, planeVBO;
|
||||
glGenVertexArrays(1, &planeVAO);
|
||||
glGenBuffers(1, &planeVBO);
|
||||
glBindVertexArray(planeVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, planeVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(planeVertices), &planeVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
|
||||
glBindVertexArray(0);
|
||||
|
||||
// Load textures
|
||||
GLuint cubeTexture = loadTexture("../../../resources/textures/marble.jpg");
|
||||
GLuint floorTexture = loadTexture("../../../resources/textures/metal.png");
|
||||
#pragma endregion
|
||||
|
||||
// Game loop
|
||||
while(!glfwWindowShouldClose(window))
|
||||
{
|
||||
// Set frame time
|
||||
GLfloat currentFrame = glfwGetTime();
|
||||
deltaTime = currentFrame - lastFrame;
|
||||
lastFrame = currentFrame;
|
||||
|
||||
// Check and call events
|
||||
glfwPollEvents();
|
||||
Do_Movement();
|
||||
|
||||
// Clear the colorbuffer
|
||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
// Set uniforms
|
||||
shaderSingleColor.Use();
|
||||
glm::mat4 model;
|
||||
glm::mat4 view = camera.GetViewMatrix();
|
||||
glm::mat4 projection = glm::perspective(camera.Zoom, (float)screenWidth/(float)screenHeight, 0.1f, 100.0f);
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderSingleColor.Program, "view"), 1, GL_FALSE, glm::value_ptr(view));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderSingleColor.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
|
||||
shader.Use();
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
|
||||
|
||||
|
||||
// Draw floor as normal, we only care about the containers. The floor should NOT fill the stencil buffer so we set its mask to 0x00
|
||||
glStencilMask(0x00);
|
||||
// Floor
|
||||
glBindVertexArray(planeVAO);
|
||||
glBindTexture(GL_TEXTURE_2D, floorTexture);
|
||||
model = glm::mat4();
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
glBindVertexArray(0);
|
||||
|
||||
// == =============
|
||||
// 1st. Render pass, draw objects as normal, filling the stencil buffer
|
||||
glStencilFunc(GL_ALWAYS, 1, 0xFF);
|
||||
glStencilMask(0xFF);
|
||||
// Cubes
|
||||
glBindVertexArray(cubeVAO);
|
||||
glBindTexture(GL_TEXTURE_2D, cubeTexture);
|
||||
model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
model = glm::mat4();
|
||||
model = glm::translate(model, glm::vec3(2.0f, 0.0f, 0.0f));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
glBindVertexArray(0);
|
||||
|
||||
// == =============
|
||||
// 2nd. Render pass, now draw slightly scaled versions of the objects, this time disabling stencil writing.
|
||||
// Because stencil buffer is now filled with several 1s. The parts of the buffer that are 1 are now not drawn, thus only drawing
|
||||
// the objects' size differences, making it look like borders.
|
||||
glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
|
||||
glStencilMask(0x00);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
shaderSingleColor.Use();
|
||||
GLfloat scale = 1.1;
|
||||
// Cubes
|
||||
glBindVertexArray(cubeVAO);
|
||||
glBindTexture(GL_TEXTURE_2D, cubeTexture);
|
||||
model = glm::mat4();
|
||||
model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f));
|
||||
model = glm::scale(model, glm::vec3(scale, scale, scale));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderSingleColor.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
model = glm::mat4();
|
||||
model = glm::translate(model, glm::vec3(2.0f, 0.0f, 0.0f));
|
||||
model = glm::scale(model, glm::vec3(scale, scale, scale));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderSingleColor.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
glBindVertexArray(0);
|
||||
glStencilMask(0xFF);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
// Swap the buffers
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
|
||||
glfwTerminate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DrawScene()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// This function loads a texture from file. Note: texture loading functions like these are usually
|
||||
// managed by a 'Resource Manager' that manages all resources (like textures, models, audio).
|
||||
// For learning purposes we'll just define it as a utility function.
|
||||
GLuint loadTexture(GLchar* path)
|
||||
{
|
||||
//Generate texture ID and load texture data
|
||||
GLuint textureID;
|
||||
glGenTextures(1, &textureID);
|
||||
int width,height;
|
||||
unsigned char* image = SOIL_load_image(path, &width, &height, 0, SOIL_LOAD_RGB);
|
||||
// Assign texture to ID
|
||||
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
// Parameters
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
SOIL_free_image_data(image);
|
||||
return textureID;
|
||||
|
||||
}
|
||||
|
||||
#pragma region "User input"
|
||||
|
||||
// Moves/alters the camera positions based on user input
|
||||
void Do_Movement()
|
||||
{
|
||||
// Camera controls
|
||||
if(keys[GLFW_KEY_W])
|
||||
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);
|
||||
}
|
||||
|
||||
// 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(action == GLFW_PRESS)
|
||||
keys[key] = true;
|
||||
else if(action == GLFW_RELEASE)
|
||||
keys[key] = false;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
|
||||
camera.ProcessMouseMovement(xoffset, yoffset);
|
||||
}
|
||||
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
|
||||
{
|
||||
camera.ProcessMouseScroll(yoffset);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
11
src/4.advanced_opengl/2.stencil_testing/stencil_testing.frag
Normal file
11
src/4.advanced_opengl/2.stencil_testing/stencil_testing.frag
Normal file
@@ -0,0 +1,11 @@
|
||||
#version 330 core
|
||||
in vec2 TexCoords;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
uniform sampler2D texture1;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = texture(texture1, TexCoords);
|
||||
}
|
||||
15
src/4.advanced_opengl/2.stencil_testing/stencil_testing.vs
Normal file
15
src/4.advanced_opengl/2.stencil_testing/stencil_testing.vs
Normal file
@@ -0,0 +1,15 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 position;
|
||||
layout (location = 1) in vec2 texCoords;
|
||||
|
||||
out vec2 TexCoords;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projection * view * model * vec4(position, 1.0f);
|
||||
TexCoords = texCoords;
|
||||
}
|
||||
331
src/4.advanced_opengl/3.1.blending_discard/blending_discard.cpp
Normal file
331
src/4.advanced_opengl/3.1.blending_discard/blending_discard.cpp
Normal file
@@ -0,0 +1,331 @@
|
||||
// Std. Includes
|
||||
#include <string>
|
||||
|
||||
// GLEW
|
||||
#define GLEW_STATIC
|
||||
#include <GL/glew.h>
|
||||
|
||||
// GLFW
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
// GL includes
|
||||
#include <learnopengl/shader.h>
|
||||
#include <learnopengl/camera.h>
|
||||
|
||||
// GLM Mathemtics
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
// Other Libs
|
||||
#include <SOIL.h>
|
||||
|
||||
// Properties
|
||||
GLuint screenWidth = 800, screenHeight = 600;
|
||||
|
||||
// Function prototypes
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
|
||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
|
||||
void Do_Movement();
|
||||
GLuint loadTexture(GLchar* path, GLboolean alpha = false);
|
||||
|
||||
// Camera
|
||||
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
|
||||
bool keys[1024];
|
||||
GLfloat lastX = 400, lastY = 300;
|
||||
bool firstMouse = true;
|
||||
|
||||
GLfloat deltaTime = 0.0f;
|
||||
GLfloat lastFrame = 0.0f;
|
||||
|
||||
// The MAIN function, from here we start our application and run our Game loop
|
||||
int main()
|
||||
{
|
||||
// Init GLFW
|
||||
glfwInit();
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
|
||||
|
||||
GLFWwindow* window = glfwCreateWindow(screenWidth, screenHeight, "LearnOpenGL", nullptr, nullptr); // Windowed
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
// Set the required callback functions
|
||||
glfwSetKeyCallback(window, key_callback);
|
||||
glfwSetCursorPosCallback(window, mouse_callback);
|
||||
glfwSetScrollCallback(window, scroll_callback);
|
||||
|
||||
// Options
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
|
||||
// Initialize GLEW to setup the OpenGL Function pointers
|
||||
glewExperimental = GL_TRUE;
|
||||
glewInit();
|
||||
|
||||
// Define the viewport dimensions
|
||||
glViewport(0, 0, screenWidth, screenHeight);
|
||||
|
||||
// Setup some OpenGL options
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
// Setup and compile our shaders
|
||||
Shader shader("blending_discard.vs", "blending_discard.frag");
|
||||
|
||||
#pragma region "object_initialization"
|
||||
// Set the object data (buffers, vertex attributes)
|
||||
GLfloat cubeVertices[] = {
|
||||
// Positions // Texture Coords
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
|
||||
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
|
||||
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f
|
||||
};
|
||||
GLfloat planeVertices[] = {
|
||||
// Positions // Texture Coords (note we set these higher than 1 that together with GL_REPEAT as texture wrapping mode will cause the floor texture to repeat)
|
||||
5.0f, -0.5f, 5.0f, 2.0f, 0.0f,
|
||||
-5.0f, -0.5f, 5.0f, 0.0f, 0.0f,
|
||||
-5.0f, -0.5f, -5.0f, 0.0f, 2.0f,
|
||||
|
||||
5.0f, -0.5f, 5.0f, 2.0f, 0.0f,
|
||||
-5.0f, -0.5f, -5.0f, 0.0f, 2.0f,
|
||||
5.0f, -0.5f, -5.0f, 2.0f, 2.0f
|
||||
};
|
||||
GLfloat transparentVertices[] = {
|
||||
// Positions // Texture Coords (swapped y coordinates because texture is flipped upside down)
|
||||
0.0f, 0.5f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, -0.5f, 0.0f, 0.0f, 1.0f,
|
||||
1.0f, -0.5f, 0.0f, 1.0f, 1.0f,
|
||||
|
||||
0.0f, 0.5f, 0.0f, 0.0f, 0.0f,
|
||||
1.0f, -0.5f, 0.0f, 1.0f, 1.0f,
|
||||
1.0f, 0.5f, 0.0f, 1.0f, 0.0f
|
||||
};
|
||||
// Setup cube VAO
|
||||
GLuint cubeVAO, cubeVBO;
|
||||
glGenVertexArrays(1, &cubeVAO);
|
||||
glGenBuffers(1, &cubeVBO);
|
||||
glBindVertexArray(cubeVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), &cubeVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
|
||||
glBindVertexArray(0);
|
||||
// Setup plane VAO
|
||||
GLuint planeVAO, planeVBO;
|
||||
glGenVertexArrays(1, &planeVAO);
|
||||
glGenBuffers(1, &planeVBO);
|
||||
glBindVertexArray(planeVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, planeVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(planeVertices), &planeVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
|
||||
glBindVertexArray(0);
|
||||
// Setup transparent plane VAO
|
||||
GLuint transparentVAO, transparentVBO;
|
||||
glGenVertexArrays(1, &transparentVAO);
|
||||
glGenBuffers(1, &transparentVBO);
|
||||
glBindVertexArray(transparentVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, transparentVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(transparentVertices), transparentVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
|
||||
glBindVertexArray(0);
|
||||
|
||||
// Load textures
|
||||
GLuint cubeTexture = loadTexture("../../../resources/textures/marble.jpg");
|
||||
GLuint floorTexture = loadTexture("../../../resources/textures/metal.png");
|
||||
GLuint transparentTexture = loadTexture("../../../resources/textures/grass.png", true);
|
||||
#pragma endregion
|
||||
|
||||
std::vector<glm::vec3> vegetation;
|
||||
vegetation.push_back(glm::vec3(-1.5f, 0.0f, -0.48f));
|
||||
vegetation.push_back(glm::vec3( 1.5f, 0.0f, 0.51f));
|
||||
vegetation.push_back(glm::vec3( 0.0f, 0.0f, 0.7f));
|
||||
vegetation.push_back(glm::vec3(-0.3f, 0.0f, -2.3f));
|
||||
vegetation.push_back(glm::vec3( 0.5f, 0.0f, -0.6f));
|
||||
|
||||
// Game loop
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
// Set frame time
|
||||
GLfloat currentFrame = glfwGetTime();
|
||||
deltaTime = currentFrame - lastFrame;
|
||||
lastFrame = currentFrame;
|
||||
|
||||
// Check and call events
|
||||
glfwPollEvents();
|
||||
Do_Movement();
|
||||
|
||||
// Clear the colorbuffer
|
||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// Draw objects
|
||||
shader.Use();
|
||||
glm::mat4 model;
|
||||
glm::mat4 view = camera.GetViewMatrix();
|
||||
glm::mat4 projection = glm::perspective(camera.Zoom, (float)screenWidth / (float)screenHeight, 0.1f, 100.0f);
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
|
||||
// Cubes
|
||||
glBindVertexArray(cubeVAO);
|
||||
glBindTexture(GL_TEXTURE_2D, cubeTexture); // We omit the glActiveTexture part since TEXTURE0 is already the default active texture unit. (a single sampler used in fragment is set to 0 as well by default)
|
||||
model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
model = glm::mat4();
|
||||
model = glm::translate(model, glm::vec3(2.0f, 0.0f, 0.0f));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
// Floor
|
||||
glBindVertexArray(planeVAO);
|
||||
glBindTexture(GL_TEXTURE_2D, floorTexture);
|
||||
model = glm::mat4();
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
// Vegetation
|
||||
glBindVertexArray(transparentVAO);
|
||||
glBindTexture(GL_TEXTURE_2D, transparentTexture);
|
||||
for (GLuint i = 0; i < vegetation.size(); i++)
|
||||
{
|
||||
model = glm::mat4();
|
||||
model = glm::translate(model, vegetation[i]);
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
}
|
||||
glBindVertexArray(0);
|
||||
|
||||
|
||||
// Swap the buffers
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
|
||||
glfwTerminate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This function loads a texture from file. Note: texture loading functions like these are usually
|
||||
// managed by a 'Resource Manager' that manages all resources (like textures, models, audio).
|
||||
// For learning purposes we'll just define it as a utility function.
|
||||
GLuint loadTexture(GLchar* path, GLboolean alpha)
|
||||
{
|
||||
//Generate texture ID and load texture data
|
||||
GLuint textureID;
|
||||
glGenTextures(1, &textureID);
|
||||
int width,height;
|
||||
unsigned char* image = SOIL_load_image(path, &width, &height, 0, alpha ? SOIL_LOAD_RGBA : SOIL_LOAD_RGB);
|
||||
// Assign texture to ID
|
||||
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, alpha ? GL_RGBA : GL_RGB, width, height, 0, alpha ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, image);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
// Parameters
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, alpha ? GL_CLAMP_TO_EDGE : GL_REPEAT ); // Use GL_CLAMP_TO_EDGE to prevent semi-transparent borders. Due to interpolation it takes value from next repeat
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, alpha ? GL_CLAMP_TO_EDGE : GL_REPEAT );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
SOIL_free_image_data(image);
|
||||
return textureID;
|
||||
}
|
||||
|
||||
#pragma region "User input"
|
||||
|
||||
// Moves/alters the camera positions based on user input
|
||||
void Do_Movement()
|
||||
{
|
||||
// Camera controls
|
||||
if (keys[GLFW_KEY_W])
|
||||
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);
|
||||
}
|
||||
|
||||
// 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 mouse_callback(GLFWwindow* window, double xpos, double ypos)
|
||||
{
|
||||
if (firstMouse)
|
||||
{
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
firstMouse = false;
|
||||
}
|
||||
|
||||
GLfloat xoffset = xpos - lastX;
|
||||
GLfloat yoffset = lastY - ypos;
|
||||
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
|
||||
camera.ProcessMouseMovement(xoffset, yoffset);
|
||||
}
|
||||
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
|
||||
{
|
||||
camera.ProcessMouseScroll(yoffset);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
@@ -0,0 +1,14 @@
|
||||
#version 330 core
|
||||
in vec2 TexCoords;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
uniform sampler2D texture1;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 texColor = texture(texture1, TexCoords);
|
||||
if(texColor.a < 0.1)
|
||||
discard;
|
||||
color = texColor;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 position;
|
||||
layout (location = 1) in vec2 texCoords;
|
||||
|
||||
out vec2 TexCoords;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projection * view * model * vec4(position, 1.0f);
|
||||
TexCoords = texCoords;
|
||||
}
|
||||
343
src/4.advanced_opengl/3.2.blending_sort/blending_sorted.cpp
Normal file
343
src/4.advanced_opengl/3.2.blending_sort/blending_sorted.cpp
Normal file
@@ -0,0 +1,343 @@
|
||||
// Std. Includes
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
// GLEW
|
||||
#define GLEW_STATIC
|
||||
#include <GL/glew.h>
|
||||
|
||||
// GLFW
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
// GL includes
|
||||
#include <learnopengl/shader.h>
|
||||
#include <learnopengl/camera.h>
|
||||
|
||||
// GLM Mathemtics
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
// Other Libs
|
||||
#include <SOIL.h>
|
||||
|
||||
// Properties
|
||||
GLuint screenWidth = 800, screenHeight = 600;
|
||||
|
||||
// Function prototypes
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
|
||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
|
||||
void Do_Movement();
|
||||
GLuint loadTexture(GLchar* path, GLboolean alpha = false);
|
||||
|
||||
// Camera
|
||||
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
|
||||
bool keys[1024];
|
||||
GLfloat lastX = 400, lastY = 300;
|
||||
bool firstMouse = true;
|
||||
|
||||
GLfloat deltaTime = 0.0f;
|
||||
GLfloat lastFrame = 0.0f;
|
||||
|
||||
// The MAIN function, from here we start our application and run our Game loop
|
||||
int main()
|
||||
{
|
||||
// Init GLFW
|
||||
glfwInit();
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
|
||||
|
||||
GLFWwindow* window = glfwCreateWindow(screenWidth, screenHeight, "LearnOpenGL", nullptr, nullptr); // Windowed
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
// Set the required callback functions
|
||||
glfwSetKeyCallback(window, key_callback);
|
||||
glfwSetCursorPosCallback(window, mouse_callback);
|
||||
glfwSetScrollCallback(window, scroll_callback);
|
||||
|
||||
// Options
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
|
||||
// Initialize GLEW to setup the OpenGL Function pointers
|
||||
glewExperimental = GL_TRUE;
|
||||
glewInit();
|
||||
|
||||
// Define the viewport dimensions
|
||||
glViewport(0, 0, screenWidth, screenHeight);
|
||||
|
||||
// Setup some OpenGL options
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
// Setup and compile our shaders
|
||||
Shader shader("blending_sorted.vs", "blending_sorted.frag");
|
||||
|
||||
#pragma region "object_initialization"
|
||||
// Set the object data (buffers, vertex attributes)
|
||||
GLfloat cubeVertices[] = {
|
||||
// Positions // Texture Coords
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
|
||||
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
|
||||
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f
|
||||
};
|
||||
GLfloat planeVertices[] = {
|
||||
// Positions // Texture Coords (note we set these higher than 1 that together with GL_REPEAT as texture wrapping mode will cause the floor texture to repeat)
|
||||
5.0f, -0.5f, 5.0f, 2.0f, 0.0f,
|
||||
-5.0f, -0.5f, 5.0f, 0.0f, 0.0f,
|
||||
-5.0f, -0.5f, -5.0f, 0.0f, 2.0f,
|
||||
|
||||
5.0f, -0.5f, 5.0f, 2.0f, 0.0f,
|
||||
-5.0f, -0.5f, -5.0f, 0.0f, 2.0f,
|
||||
5.0f, -0.5f, -5.0f, 2.0f, 2.0f
|
||||
};
|
||||
GLfloat transparentVertices[] = {
|
||||
// Positions // Texture Coords (swapped y coordinates because texture is flipped upside down)
|
||||
0.0f, 0.5f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, -0.5f, 0.0f, 0.0f, 1.0f,
|
||||
1.0f, -0.5f, 0.0f, 1.0f, 1.0f,
|
||||
|
||||
0.0f, 0.5f, 0.0f, 0.0f, 0.0f,
|
||||
1.0f, -0.5f, 0.0f, 1.0f, 1.0f,
|
||||
1.0f, 0.5f, 0.0f, 1.0f, 0.0f
|
||||
};
|
||||
// Setup cube VAO
|
||||
GLuint cubeVAO, cubeVBO;
|
||||
glGenVertexArrays(1, &cubeVAO);
|
||||
glGenBuffers(1, &cubeVBO);
|
||||
glBindVertexArray(cubeVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), &cubeVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
|
||||
glBindVertexArray(0);
|
||||
// Setup plane VAO
|
||||
GLuint planeVAO, planeVBO;
|
||||
glGenVertexArrays(1, &planeVAO);
|
||||
glGenBuffers(1, &planeVBO);
|
||||
glBindVertexArray(planeVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, planeVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(planeVertices), &planeVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
|
||||
glBindVertexArray(0);
|
||||
// Setup transparent plane VAO
|
||||
GLuint transparentVAO, transparentVBO;
|
||||
glGenVertexArrays(1, &transparentVAO);
|
||||
glGenBuffers(1, &transparentVBO);
|
||||
glBindVertexArray(transparentVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, transparentVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(transparentVertices), transparentVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
|
||||
glBindVertexArray(0);
|
||||
|
||||
// Load textures
|
||||
GLuint cubeTexture = loadTexture("../../../resources/textures/marble.jpg");
|
||||
GLuint floorTexture = loadTexture("../../../resources/textures/metal.png");
|
||||
GLuint transparentTexture = loadTexture("../../../resources/textures/window.png", true);
|
||||
#pragma endregion
|
||||
|
||||
std::vector<glm::vec3> windows;
|
||||
windows.push_back(glm::vec3(-1.5f, 0.0f, -0.48f));
|
||||
windows.push_back(glm::vec3( 1.5f, 0.0f, 0.51f));
|
||||
windows.push_back(glm::vec3( 0.0f, 0.0f, 0.7f));
|
||||
windows.push_back(glm::vec3(-0.3f, 0.0f, -2.3f));
|
||||
windows.push_back(glm::vec3( 0.5f, 0.0f, -0.6f));
|
||||
|
||||
// Game loop
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
// Set frame time
|
||||
GLfloat currentFrame = glfwGetTime();
|
||||
deltaTime = currentFrame - lastFrame;
|
||||
lastFrame = currentFrame;
|
||||
|
||||
// Check and call events
|
||||
glfwPollEvents();
|
||||
Do_Movement();
|
||||
|
||||
// Clear the colorbuffer
|
||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// Sort windows
|
||||
std::map<GLfloat, glm::vec3> sorted;
|
||||
for (GLuint i = 0; i < windows.size(); i++)
|
||||
{
|
||||
GLfloat distance = glm::length(camera.Position - windows[i]);
|
||||
sorted[distance] = windows[i];
|
||||
}
|
||||
|
||||
// Draw objects
|
||||
shader.Use();
|
||||
glm::mat4 model;
|
||||
glm::mat4 view = camera.GetViewMatrix();
|
||||
glm::mat4 projection = glm::perspective(camera.Zoom, (float)screenWidth / (float)screenHeight, 0.1f, 100.0f);
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
|
||||
// Cubes
|
||||
glBindVertexArray(cubeVAO);
|
||||
glBindTexture(GL_TEXTURE_2D, cubeTexture); // We omit the glActiveTexture part since TEXTURE0 is already the default active texture unit. (a single sampler used in fragment is set to 0 as well by default)
|
||||
model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
model = glm::mat4();
|
||||
model = glm::translate(model, glm::vec3(2.0f, 0.0f, 0.0f));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
// Floor
|
||||
glBindVertexArray(planeVAO);
|
||||
glBindTexture(GL_TEXTURE_2D, floorTexture);
|
||||
model = glm::mat4();
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
// Render windows (from furthest to nearest)
|
||||
glBindVertexArray(transparentVAO);
|
||||
glBindTexture(GL_TEXTURE_2D, transparentTexture);
|
||||
for (std::map<float, glm::vec3>::reverse_iterator it = sorted.rbegin(); it != sorted.rend(); ++it)
|
||||
{
|
||||
model = glm::mat4();
|
||||
model = glm::translate(model, it->second);
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
}
|
||||
glBindVertexArray(0);
|
||||
|
||||
|
||||
// Swap the buffers
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
|
||||
glfwTerminate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This function loads a texture from file. Note: texture loading functions like these are usually
|
||||
// managed by a 'Resource Manager' that manages all resources (like textures, models, audio).
|
||||
// For learning purposes we'll just define it as a utility function.
|
||||
GLuint loadTexture(GLchar* path, GLboolean alpha)
|
||||
{
|
||||
//Generate texture ID and load texture data
|
||||
GLuint textureID;
|
||||
glGenTextures(1, &textureID);
|
||||
int width,height;
|
||||
unsigned char* image = SOIL_load_image(path, &width, &height, 0, alpha ? SOIL_LOAD_RGBA : SOIL_LOAD_RGB);
|
||||
// Assign texture to ID
|
||||
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, alpha ? GL_RGBA : GL_RGB, width, height, 0, alpha ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, image);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
// Parameters
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, alpha ? GL_CLAMP_TO_EDGE : GL_REPEAT ); // Use GL_CLAMP_TO_EDGE to prevent semi-transparent borders. Due to interpolation it takes value from next repeat
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, alpha ? GL_CLAMP_TO_EDGE : GL_REPEAT );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
SOIL_free_image_data(image);
|
||||
return textureID;
|
||||
|
||||
}
|
||||
|
||||
#pragma region "User input"
|
||||
|
||||
// Moves/alters the camera positions based on user input
|
||||
void Do_Movement()
|
||||
{
|
||||
// Camera controls
|
||||
if (keys[GLFW_KEY_W])
|
||||
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);
|
||||
}
|
||||
|
||||
// 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 mouse_callback(GLFWwindow* window, double xpos, double ypos)
|
||||
{
|
||||
if (firstMouse)
|
||||
{
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
firstMouse = false;
|
||||
}
|
||||
|
||||
GLfloat xoffset = xpos - lastX;
|
||||
GLfloat yoffset = lastY - ypos;
|
||||
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
|
||||
camera.ProcessMouseMovement(xoffset, yoffset);
|
||||
}
|
||||
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
|
||||
{
|
||||
camera.ProcessMouseScroll(yoffset);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
11
src/4.advanced_opengl/3.2.blending_sort/blending_sorted.frag
Normal file
11
src/4.advanced_opengl/3.2.blending_sort/blending_sorted.frag
Normal file
@@ -0,0 +1,11 @@
|
||||
#version 330 core
|
||||
in vec2 TexCoords;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
uniform sampler2D texture1;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = texture(texture1, TexCoords);
|
||||
}
|
||||
15
src/4.advanced_opengl/3.2.blending_sort/blending_sorted.vs
Normal file
15
src/4.advanced_opengl/3.2.blending_sort/blending_sorted.vs
Normal file
@@ -0,0 +1,15 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 position;
|
||||
layout (location = 1) in vec2 texCoords;
|
||||
|
||||
out vec2 TexCoords;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projection * view * model * vec4(position, 1.0f);
|
||||
TexCoords = texCoords;
|
||||
}
|
||||
11
src/4.advanced_opengl/5.framebuffers/framebuffers.frag
Normal file
11
src/4.advanced_opengl/5.framebuffers/framebuffers.frag
Normal file
@@ -0,0 +1,11 @@
|
||||
#version 330 core
|
||||
in vec2 TexCoords;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
uniform sampler2D texture1;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = texture(texture1, TexCoords);
|
||||
}
|
||||
15
src/4.advanced_opengl/5.framebuffers/framebuffers.vs
Normal file
15
src/4.advanced_opengl/5.framebuffers/framebuffers.vs
Normal file
@@ -0,0 +1,15 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 position;
|
||||
layout (location = 1) in vec2 texCoords;
|
||||
|
||||
out vec2 TexCoords;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projection * view * model * vec4(position, 1.0f);
|
||||
TexCoords = texCoords;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
#version 330 core
|
||||
in vec2 TexCoords;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
uniform sampler2D screenTexture;
|
||||
|
||||
const float offset = 1.0 / 300;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 offsets[9] = vec2[](
|
||||
vec2(-offset, offset), // top-left
|
||||
vec2(0.0f, offset), // top-center
|
||||
vec2(offset, offset), // top-right
|
||||
vec2(-offset, 0.0f), // center-left
|
||||
vec2(0.0f, 0.0f), // center-center
|
||||
vec2(offset, 0.0f), // center-right
|
||||
vec2(-offset, -offset), // bottom-left
|
||||
vec2(0.0f, -offset), // bottom-center
|
||||
vec2(offset, -offset) // bottom-right
|
||||
);
|
||||
|
||||
float kernel[9] = float[](
|
||||
-1, -1, -1,
|
||||
-1, 9, -1,
|
||||
-1, -1, -1
|
||||
);
|
||||
|
||||
vec3 sample[9];
|
||||
for(int i = 0; i < 9; i++)
|
||||
{
|
||||
sample[i] = vec3(texture(screenTexture, TexCoords.st + offsets[i]));
|
||||
}
|
||||
vec3 col;
|
||||
for(int i = 0; i < 9; i++)
|
||||
col += sample[i] * kernel[i];
|
||||
|
||||
color = vec4(col, 1.0);
|
||||
}
|
||||
11
src/4.advanced_opengl/5.framebuffers/framebuffers_screen.vs
Normal file
11
src/4.advanced_opengl/5.framebuffers/framebuffers_screen.vs
Normal file
@@ -0,0 +1,11 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec2 position;
|
||||
layout (location = 1) in vec2 texCoords;
|
||||
|
||||
out vec2 TexCoords;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(position.x, position.y, 0.0f, 1.0f);
|
||||
TexCoords = texCoords;
|
||||
}
|
||||
@@ -0,0 +1,394 @@
|
||||
// Std. Includes
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
using namespace std;
|
||||
|
||||
// GLEW
|
||||
#define GLEW_STATIC
|
||||
#include <GL/glew.h>
|
||||
|
||||
// GLFW
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
// GL includes
|
||||
#include <learnopengl/shader.h>
|
||||
#include <learnopengl/camera.h>
|
||||
|
||||
// GLM Mathemtics
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
// Other Libs
|
||||
#include <SOIL.h>
|
||||
|
||||
// Properties
|
||||
GLuint screenWidth = 800, screenHeight = 600;
|
||||
|
||||
// Function prototypes
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
|
||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
|
||||
void Do_Movement();
|
||||
GLuint loadTexture(GLchar* path, GLboolean alpha = false);
|
||||
GLuint generateAttachmentTexture(GLboolean depth, GLboolean stencil);
|
||||
|
||||
// Camera
|
||||
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
|
||||
bool keys[1024];
|
||||
GLfloat lastX = 400, lastY = 300;
|
||||
bool firstMouse = true;
|
||||
|
||||
GLfloat deltaTime = 0.0f;
|
||||
GLfloat lastFrame = 0.0f;
|
||||
|
||||
// The MAIN function, from here we start our application and run our Game loop
|
||||
int main()
|
||||
{
|
||||
// Init GLFW
|
||||
glfwInit();
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
|
||||
|
||||
GLFWwindow* window = glfwCreateWindow(screenWidth, screenHeight, "LearnOpenGL", nullptr, nullptr); // Windowed
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
// Set the required callback functions
|
||||
glfwSetKeyCallback(window, key_callback);
|
||||
glfwSetCursorPosCallback(window, mouse_callback);
|
||||
glfwSetScrollCallback(window, scroll_callback);
|
||||
|
||||
// Options
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
|
||||
// Initialize GLEW to setup the OpenGL Function pointers
|
||||
glewExperimental = GL_TRUE;
|
||||
glewInit();
|
||||
|
||||
// Define the viewport dimensions
|
||||
glViewport(0, 0, screenWidth, screenHeight);
|
||||
|
||||
// Setup some OpenGL options
|
||||
glDepthFunc(GL_LESS);
|
||||
|
||||
// Setup and compile our shaders
|
||||
Shader shader("framebuffers.vs", "framebuffers.frag");
|
||||
Shader screenShader("framebuffers_screen.vs", "framebuffers_screen.frag");
|
||||
|
||||
#pragma region "object_initialization"
|
||||
// Set the object data (buffers, vertex attributes)
|
||||
GLfloat cubeVertices[] = {
|
||||
// Positions // Texture Coords
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
|
||||
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
|
||||
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f
|
||||
};
|
||||
GLfloat floorVertices[] = {
|
||||
// Positions // Texture Coords (note we set these higher than 1 that together with GL_REPEAT as texture wrapping mode will cause the floor texture to repeat)
|
||||
5.0f, -0.5f, 5.0f, 2.0f, 0.0f,
|
||||
-5.0f, -0.5f, 5.0f, 0.0f, 0.0f,
|
||||
-5.0f, -0.5f, -5.0f, 0.0f, 2.0f,
|
||||
|
||||
5.0f, -0.5f, 5.0f, 2.0f, 0.0f,
|
||||
-5.0f, -0.5f, -5.0f, 0.0f, 2.0f,
|
||||
5.0f, -0.5f, -5.0f, 2.0f, 2.0f
|
||||
};
|
||||
GLfloat quadVertices[] = { // Vertex attributes for a quad that fills the entire screen in Normalized Device Coordinates.
|
||||
// Positions // TexCoords
|
||||
-1.0f, 1.0f, 0.0f, 1.0f,
|
||||
-1.0f, -1.0f, 0.0f, 0.0f,
|
||||
1.0f, -1.0f, 1.0f, 0.0f,
|
||||
|
||||
-1.0f, 1.0f, 0.0f, 1.0f,
|
||||
1.0f, -1.0f, 1.0f, 0.0f,
|
||||
1.0f, 1.0f, 1.0f, 1.0f
|
||||
};
|
||||
|
||||
// Setup cube VAO
|
||||
GLuint cubeVAO, cubeVBO;
|
||||
glGenVertexArrays(1, &cubeVAO);
|
||||
glGenBuffers(1, &cubeVBO);
|
||||
glBindVertexArray(cubeVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), &cubeVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
|
||||
glBindVertexArray(0);
|
||||
// Setup plane VAO
|
||||
GLuint floorVAO, floorVBO;
|
||||
glGenVertexArrays(1, &floorVAO);
|
||||
glGenBuffers(1, &floorVBO);
|
||||
glBindVertexArray(floorVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, floorVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(floorVertices), &floorVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
|
||||
glBindVertexArray(0);
|
||||
// Setup screen VAO
|
||||
GLuint quadVAO, quadVBO;
|
||||
glGenVertexArrays(1, &quadVAO);
|
||||
glGenBuffers(1, &quadVBO);
|
||||
glBindVertexArray(quadVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (GLvoid*)(2 * sizeof(GLfloat)));
|
||||
glBindVertexArray(0);
|
||||
|
||||
// Load textures
|
||||
GLuint cubeTexture = loadTexture("../../../resources/textures/container.jpg");
|
||||
GLuint floorTexture = loadTexture("../../../resources/textures/metal.png");
|
||||
#pragma endregion
|
||||
|
||||
// Framebuffers
|
||||
GLuint framebuffer;
|
||||
glGenFramebuffers(1, &framebuffer);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
|
||||
// Create a color attachment texture
|
||||
GLuint textureColorbuffer = generateAttachmentTexture(false, false);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureColorbuffer, 0);
|
||||
// Create a renderbuffer object for depth and stencil attachment (we won't be sampling these)
|
||||
GLuint rbo;
|
||||
glGenRenderbuffers(1, &rbo);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, screenWidth, screenHeight); // Use a single renderbuffer object for both a depth AND stencil buffer.
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo); // Now actually attach it
|
||||
// Now that we actually created the framebuffer and added all attachments we want to check if it is actually complete now
|
||||
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||
cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << endl;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
|
||||
// Draw as wireframe
|
||||
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
|
||||
// Game loop
|
||||
while(!glfwWindowShouldClose(window))
|
||||
{
|
||||
// Set frame time
|
||||
GLfloat currentFrame = glfwGetTime();
|
||||
deltaTime = currentFrame - lastFrame;
|
||||
lastFrame = currentFrame;
|
||||
|
||||
// Check and call events
|
||||
glfwPollEvents();
|
||||
Do_Movement();
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Bind to framebuffer and draw to color texture
|
||||
// as we normally would.
|
||||
// //////////////////////////////////////////////////
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
|
||||
// Clear all attached buffers
|
||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // We're not using stencil buffer so why bother with clearing?
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
// Set uniforms
|
||||
shader.Use();
|
||||
glm::mat4 model;
|
||||
glm::mat4 view = camera.GetViewMatrix();
|
||||
glm::mat4 projection = glm::perspective(camera.Zoom, (float)screenWidth/(float)screenHeight, 0.1f, 100.0f);
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
|
||||
|
||||
// Floor
|
||||
glBindVertexArray(floorVAO);
|
||||
glBindTexture(GL_TEXTURE_2D, floorTexture);
|
||||
model = glm::mat4();
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
glBindVertexArray(0);
|
||||
// Cubes
|
||||
glBindVertexArray(cubeVAO);
|
||||
glBindTexture(GL_TEXTURE_2D, cubeTexture);
|
||||
model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
model = glm::mat4();
|
||||
model = glm::translate(model, glm::vec3(2.0f, 0.0f, 0.0f));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
glBindVertexArray(0);
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Bind to default framebuffer again and draw the
|
||||
// quad plane with attched screen texture.
|
||||
// //////////////////////////////////////////////////
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
// Clear all relevant buffers
|
||||
glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // Set clear color to white (not really necessery actually, since we won't be able to see behind the quad anyways)
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glDisable(GL_DEPTH_TEST); // We don't care about depth information when rendering a single quad
|
||||
|
||||
// Draw Screen
|
||||
screenShader.Use();
|
||||
glBindVertexArray(quadVAO);
|
||||
glBindTexture(GL_TEXTURE_2D, textureColorbuffer); // Use the color attachment texture as the texture of the quad plane
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
glBindVertexArray(0);
|
||||
|
||||
|
||||
// Swap the buffers
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
glDeleteFramebuffers(1, &framebuffer);
|
||||
|
||||
glfwTerminate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This function loads a texture from file. Note: texture loading functions like these are usually
|
||||
// managed by a 'Resource Manager' that manages all resources (like textures, models, audio).
|
||||
// For learning purposes we'll just define it as a utility function.
|
||||
GLuint loadTexture(GLchar* path, GLboolean alpha)
|
||||
{
|
||||
//Generate texture ID and load texture data
|
||||
GLuint textureID;
|
||||
glGenTextures(1, &textureID);
|
||||
int width,height;
|
||||
unsigned char* image = SOIL_load_image(path, &width, &height, 0, alpha ? SOIL_LOAD_RGBA : SOIL_LOAD_RGB);
|
||||
// Assign texture to ID
|
||||
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, alpha ? GL_RGBA : GL_RGB, width, height, 0, alpha ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, image);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
// Parameters
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, alpha ? GL_CLAMP_TO_EDGE : GL_REPEAT ); // Use GL_MIRRORED_REPEAT to prevent white borders. Due to interpolation it takes value from next repeat
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, alpha ? GL_CLAMP_TO_EDGE : GL_REPEAT );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
SOIL_free_image_data(image);
|
||||
return textureID;
|
||||
}
|
||||
|
||||
// Generates a texture that is suited for attachments to a framebuffer
|
||||
GLuint generateAttachmentTexture(GLboolean depth, GLboolean stencil)
|
||||
{
|
||||
// What enum to use?
|
||||
GLenum attachment_type;
|
||||
if(!depth && !stencil)
|
||||
attachment_type = GL_RGB;
|
||||
else if(depth && !stencil)
|
||||
attachment_type = GL_DEPTH_COMPONENT;
|
||||
else if(!depth && stencil)
|
||||
attachment_type = GL_STENCIL_INDEX;
|
||||
|
||||
//Generate texture ID and load texture data
|
||||
GLuint textureID;
|
||||
glGenTextures(1, &textureID);
|
||||
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||
if(!depth && !stencil)
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, attachment_type, screenWidth, screenHeight, 0, attachment_type, GL_UNSIGNED_BYTE, NULL);
|
||||
else // Using both a stencil and depth test, needs special format arguments
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, screenWidth, screenHeight, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
return textureID;
|
||||
}
|
||||
|
||||
#pragma region "User input"
|
||||
|
||||
// Moves/alters the camera positions based on user input
|
||||
void Do_Movement()
|
||||
{
|
||||
// Camera controls
|
||||
if(keys[GLFW_KEY_W])
|
||||
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);
|
||||
}
|
||||
|
||||
// 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(action == GLFW_PRESS)
|
||||
keys[key] = true;
|
||||
else if(action == GLFW_RELEASE)
|
||||
keys[key] = false;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
|
||||
camera.ProcessMouseMovement(xoffset, yoffset);
|
||||
}
|
||||
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
|
||||
{
|
||||
camera.ProcessMouseScroll(yoffset);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
14
src/4.advanced_opengl/6.cubemaps/cubemaps.frag
Normal file
14
src/4.advanced_opengl/6.cubemaps/cubemaps.frag
Normal file
@@ -0,0 +1,14 @@
|
||||
#version 330 core
|
||||
in vec3 Normal;
|
||||
in vec3 Position;
|
||||
out vec4 color;
|
||||
|
||||
uniform vec3 cameraPos;
|
||||
uniform samplerCube skybox;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 I = normalize(Position - cameraPos);
|
||||
vec3 R = reflect(I, normalize(Normal));
|
||||
color = texture(skybox, R);
|
||||
}
|
||||
17
src/4.advanced_opengl/6.cubemaps/cubemaps.vs
Normal file
17
src/4.advanced_opengl/6.cubemaps/cubemaps.vs
Normal file
@@ -0,0 +1,17 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 position;
|
||||
layout (location = 1) in vec3 normal;
|
||||
|
||||
out vec3 Normal;
|
||||
out vec3 Position;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projection * view * model * vec4(position, 1.0f);
|
||||
Normal = mat3(transpose(inverse(model))) * normal;
|
||||
Position = vec3(model * vec4(position, 1.0f));
|
||||
}
|
||||
376
src/4.advanced_opengl/6.cubemaps/cubemaps_skybox_optimized.cpp
Normal file
376
src/4.advanced_opengl/6.cubemaps/cubemaps_skybox_optimized.cpp
Normal file
@@ -0,0 +1,376 @@
|
||||
// Std. Includes
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
using namespace std;
|
||||
|
||||
// GLEW
|
||||
#define GLEW_STATIC
|
||||
#include <GL/glew.h>
|
||||
|
||||
// GLFW
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
// GL includes
|
||||
#include <learnopengl/shader.h>
|
||||
#include <learnopengl/camera.h>
|
||||
|
||||
// GLM Mathemtics
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
// Other Libs
|
||||
#include <SOIL.h>
|
||||
|
||||
// Properties
|
||||
GLuint screenWidth = 800, screenHeight = 600;
|
||||
|
||||
// Function prototypes
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
|
||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
|
||||
void Do_Movement();
|
||||
GLuint loadTexture(GLchar* path);
|
||||
GLuint loadCubemap(std::vector<const GLchar*> faces);
|
||||
|
||||
// Camera
|
||||
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
|
||||
bool keys[1024];
|
||||
GLfloat lastX = 400, lastY = 300;
|
||||
bool firstMouse = true;
|
||||
|
||||
GLfloat deltaTime = 0.0f;
|
||||
GLfloat lastFrame = 0.0f;
|
||||
|
||||
|
||||
|
||||
// The MAIN function, from here we start our application and run our Game loop
|
||||
int main()
|
||||
{
|
||||
// Init GLFW
|
||||
glfwInit();
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
|
||||
|
||||
GLFWwindow* window = glfwCreateWindow(screenWidth, screenHeight, "LearnOpenGL", nullptr, nullptr); // Windowed
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
// Set the required callback functions
|
||||
glfwSetKeyCallback(window, key_callback);
|
||||
glfwSetCursorPosCallback(window, mouse_callback);
|
||||
glfwSetScrollCallback(window, scroll_callback);
|
||||
|
||||
// Options
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
|
||||
// Initialize GLEW to setup the OpenGL Function pointers
|
||||
glewExperimental = GL_TRUE;
|
||||
glewInit();
|
||||
|
||||
// Define the viewport dimensions
|
||||
glViewport(0, 0, screenWidth, screenHeight);
|
||||
|
||||
// Setup some OpenGL options
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LESS);
|
||||
|
||||
// Setup and compile our shaders
|
||||
Shader shader("cubemaps.vs", "cubemaps.frag");
|
||||
Shader skyboxShader("skybox.vs", "skybox.frag");
|
||||
|
||||
#pragma region "object_initialization"
|
||||
// Set the object data (buffers, vertex attributes)
|
||||
GLfloat cubeVertices[] = {
|
||||
// Positions // Normals
|
||||
-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
|
||||
};
|
||||
GLfloat skyboxVertices[] = {
|
||||
// Positions
|
||||
-1.0f, 1.0f, -1.0f,
|
||||
-1.0f, -1.0f, -1.0f,
|
||||
1.0f, -1.0f, -1.0f,
|
||||
1.0f, -1.0f, -1.0f,
|
||||
1.0f, 1.0f, -1.0f,
|
||||
-1.0f, 1.0f, -1.0f,
|
||||
|
||||
-1.0f, -1.0f, 1.0f,
|
||||
-1.0f, -1.0f, -1.0f,
|
||||
-1.0f, 1.0f, -1.0f,
|
||||
-1.0f, 1.0f, -1.0f,
|
||||
-1.0f, 1.0f, 1.0f,
|
||||
-1.0f, -1.0f, 1.0f,
|
||||
|
||||
1.0f, -1.0f, -1.0f,
|
||||
1.0f, -1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, -1.0f,
|
||||
1.0f, -1.0f, -1.0f,
|
||||
|
||||
-1.0f, -1.0f, 1.0f,
|
||||
-1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f,
|
||||
1.0f, -1.0f, 1.0f,
|
||||
-1.0f, -1.0f, 1.0f,
|
||||
|
||||
-1.0f, 1.0f, -1.0f,
|
||||
1.0f, 1.0f, -1.0f,
|
||||
1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f,
|
||||
-1.0f, 1.0f, 1.0f,
|
||||
-1.0f, 1.0f, -1.0f,
|
||||
|
||||
-1.0f, -1.0f, -1.0f,
|
||||
-1.0f, -1.0f, 1.0f,
|
||||
1.0f, -1.0f, -1.0f,
|
||||
1.0f, -1.0f, -1.0f,
|
||||
-1.0f, -1.0f, 1.0f,
|
||||
1.0f, -1.0f, 1.0f
|
||||
};
|
||||
|
||||
// Setup cube VAO
|
||||
GLuint cubeVAO, cubeVBO;
|
||||
glGenVertexArrays(1, &cubeVAO);
|
||||
glGenBuffers(1, &cubeVBO);
|
||||
glBindVertexArray(cubeVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), &cubeVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
|
||||
glBindVertexArray(0);
|
||||
// Setup skybox VAO
|
||||
GLuint skyboxVAO, skyboxVBO;
|
||||
glGenVertexArrays(1, &skyboxVAO);
|
||||
glGenBuffers(1, &skyboxVBO);
|
||||
glBindVertexArray(skyboxVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, skyboxVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glBindVertexArray(0);
|
||||
|
||||
#pragma endregion
|
||||
|
||||
// Cubemap (Skybox)
|
||||
std::vector<const GLchar*> faces;
|
||||
faces.push_back("../../../resources/textures/skybox/right.jpg");
|
||||
faces.push_back("../../../resources/textures/skybox/left.jpg");
|
||||
faces.push_back("../../../resources/textures/skybox/top.jpg");
|
||||
faces.push_back("../../../resources/textures/skybox/bottom.jpg");
|
||||
faces.push_back("../../../resources/textures/skybox/back.jpg");
|
||||
faces.push_back("../../../resources/textures/skybox/front.jpg");
|
||||
GLuint skyboxTexture = loadCubemap(faces);
|
||||
|
||||
// Draw as wireframe
|
||||
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
|
||||
// Game loop
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
// Set frame time
|
||||
GLfloat currentFrame = glfwGetTime();
|
||||
deltaTime = currentFrame - lastFrame;
|
||||
lastFrame = currentFrame;
|
||||
|
||||
// Check and call events
|
||||
glfwPollEvents();
|
||||
Do_Movement();
|
||||
|
||||
// Clear buffers
|
||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
|
||||
// Draw scene as normal
|
||||
shader.Use();
|
||||
glm::mat4 model;
|
||||
glm::mat4 view = camera.GetViewMatrix();
|
||||
glm::mat4 projection = glm::perspective(camera.Zoom, (float)screenWidth / (float)screenHeight, 0.1f, 100.0f);
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
|
||||
glUniform3f(glGetUniformLocation(shader.Program, "cameraPos"), camera.Position.x, camera.Position.y, camera.Position.z);
|
||||
// Cubes
|
||||
glBindVertexArray(cubeVAO);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, skyboxTexture);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
glBindVertexArray(0);
|
||||
|
||||
// Draw skybox as last
|
||||
glDepthFunc(GL_LEQUAL); // Change depth function so depth test passes when values are equal to depth buffer's content
|
||||
skyboxShader.Use();
|
||||
view = glm::mat4(glm::mat3(camera.GetViewMatrix())); // Remove any translation component of the view matrix
|
||||
glUniformMatrix4fv(glGetUniformLocation(skyboxShader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view));
|
||||
glUniformMatrix4fv(glGetUniformLocation(skyboxShader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
|
||||
// skybox cube
|
||||
glBindVertexArray(skyboxVAO);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, skyboxTexture);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
glBindVertexArray(0);
|
||||
glDepthFunc(GL_LESS); // Set depth function back to default
|
||||
|
||||
|
||||
// Swap the buffers
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
|
||||
glfwTerminate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Loads a cubemap texture from 6 individual texture faces
|
||||
// Order should be:
|
||||
// +X (right)
|
||||
// -X (left)
|
||||
// +Y (top)
|
||||
// -Y (bottom)
|
||||
// +Z (front)? (CHECK THIS)
|
||||
// -Z (back)?
|
||||
GLuint loadCubemap(std::vector<const GLchar*> faces)
|
||||
{
|
||||
GLuint textureID;
|
||||
glGenTextures(1, &textureID);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
int width, height;
|
||||
unsigned char* image;
|
||||
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, textureID);
|
||||
for (GLuint i = 0; i < faces.size(); i++)
|
||||
{
|
||||
image = SOIL_load_image(faces[i], &width, &height, 0, SOIL_LOAD_RGB);
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
|
||||
}
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
|
||||
|
||||
return textureID;
|
||||
}
|
||||
|
||||
|
||||
// This function loads a texture from file. Note: texture loading functions like these are usually
|
||||
// managed by a 'Resource Manager' that manages all resources (like textures, models, audio).
|
||||
// For learning purposes we'll just define it as a utility function.
|
||||
GLuint loadTexture(GLchar* path)
|
||||
{
|
||||
//Generate texture ID and load texture data
|
||||
GLuint textureID;
|
||||
glGenTextures(1, &textureID);
|
||||
int width, height;
|
||||
unsigned char* image = SOIL_load_image(path, &width, &height, 0, SOIL_LOAD_RGB);
|
||||
// Assign texture to ID
|
||||
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
// Parameters
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
SOIL_free_image_data(image);
|
||||
return textureID;
|
||||
}
|
||||
|
||||
#pragma region "User input"
|
||||
|
||||
// Moves/alters the camera positions based on user input
|
||||
void Do_Movement()
|
||||
{
|
||||
// Camera controls
|
||||
if (keys[GLFW_KEY_W])
|
||||
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);
|
||||
}
|
||||
|
||||
// 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 (action == GLFW_PRESS)
|
||||
keys[key] = true;
|
||||
else if (action == GLFW_RELEASE)
|
||||
keys[key] = false;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
|
||||
camera.ProcessMouseMovement(xoffset, yoffset);
|
||||
}
|
||||
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
|
||||
{
|
||||
camera.ProcessMouseScroll(yoffset);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
10
src/4.advanced_opengl/6.cubemaps/skybox.frag
Normal file
10
src/4.advanced_opengl/6.cubemaps/skybox.frag
Normal file
@@ -0,0 +1,10 @@
|
||||
#version 330 core
|
||||
in vec3 TexCoords;
|
||||
out vec4 color;
|
||||
|
||||
uniform samplerCube skybox;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = texture(skybox, TexCoords);
|
||||
}
|
||||
14
src/4.advanced_opengl/6.cubemaps/skybox.vs
Normal file
14
src/4.advanced_opengl/6.cubemaps/skybox.vs
Normal file
@@ -0,0 +1,14 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 position;
|
||||
out vec3 TexCoords;
|
||||
|
||||
uniform mat4 projection;
|
||||
uniform mat4 view;
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 pos = projection * view * vec4(position, 1.0);
|
||||
gl_Position = pos.xyww;
|
||||
TexCoords = position;
|
||||
}
|
||||
@@ -0,0 +1,262 @@
|
||||
// GLEW
|
||||
#define GLEW_STATIC
|
||||
#include <GL/glew.h>
|
||||
|
||||
// GLFW
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
// GL includes
|
||||
#include <learnopengl/shader.h>
|
||||
#include <learnopengl/camera.h>
|
||||
|
||||
// GLM Mathemtics
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
// Other Libs
|
||||
#include <SOIL.h>
|
||||
|
||||
// Properties
|
||||
GLuint screenWidth = 800, screenHeight = 600;
|
||||
|
||||
// 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 Do_Movement();
|
||||
|
||||
// Camera
|
||||
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
|
||||
bool keys[1024];
|
||||
GLfloat lastX = 400, lastY = 300;
|
||||
bool firstMouse = true;
|
||||
|
||||
GLfloat deltaTime = 0.0f;
|
||||
GLfloat lastFrame = 0.0f;
|
||||
|
||||
// The MAIN function, from here we start our application and run our Game loop
|
||||
int main()
|
||||
{
|
||||
// Init GLFW
|
||||
glfwInit();
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
|
||||
|
||||
GLFWwindow* window = glfwCreateWindow(screenWidth, screenHeight, "LearnOpenGL", nullptr, nullptr); // Windowed
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
// Set the required callback functions
|
||||
glfwSetKeyCallback(window, key_callback);
|
||||
glfwSetCursorPosCallback(window, mouse_callback);
|
||||
|
||||
// Options
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
|
||||
// Initialize GLEW to setup the OpenGL Function pointers
|
||||
glewExperimental = GL_TRUE;
|
||||
glewInit();
|
||||
|
||||
// Define the viewport dimensions
|
||||
glViewport(0, 0, screenWidth, screenHeight);
|
||||
|
||||
// Setup some OpenGL options
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
// Setup and compile our shaders
|
||||
Shader shaderRed("uniform_buffers.vs", "red.frag");
|
||||
Shader shaderGreen("uniform_buffers.vs", "green.frag");
|
||||
Shader shaderBlue("uniform_buffers.vs", "blue.frag");
|
||||
Shader shaderYellow("uniform_buffers.vs", "yellow.frag");
|
||||
|
||||
#pragma region "object_initialization"
|
||||
|
||||
GLfloat cubeVertices[] = {
|
||||
-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
|
||||
};
|
||||
|
||||
// Setup cube VAO
|
||||
GLuint cubeVAO, cubeVBO;
|
||||
glGenVertexArrays(1, &cubeVAO);
|
||||
glGenBuffers(1, &cubeVBO);
|
||||
glBindVertexArray(cubeVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), &cubeVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glBindVertexArray(0);
|
||||
|
||||
#pragma endregion
|
||||
|
||||
// Create a uniform buffer object
|
||||
// First. We get the relevant block indices
|
||||
GLuint uniformBlockIndexRed = glGetUniformBlockIndex(shaderRed.Program, "Matrices");
|
||||
GLuint uniformBlockIndexGreen = glGetUniformBlockIndex(shaderGreen.Program, "Matrices");
|
||||
GLuint uniformBlockIndexBlue = glGetUniformBlockIndex(shaderBlue.Program, "Matrices");
|
||||
GLuint uniformBlockIndexYellow = glGetUniformBlockIndex(shaderYellow.Program, "Matrices");
|
||||
// Then we link each shader's uniform block to this uniform binding point
|
||||
glUniformBlockBinding(shaderRed.Program, uniformBlockIndexRed, 0);
|
||||
glUniformBlockBinding(shaderGreen.Program, uniformBlockIndexGreen, 0);
|
||||
glUniformBlockBinding(shaderBlue.Program, uniformBlockIndexBlue, 0);
|
||||
glUniformBlockBinding(shaderYellow.Program, uniformBlockIndexYellow, 0);
|
||||
// Now actually create the buffer
|
||||
GLuint uboMatrices;
|
||||
glGenBuffers(1, &uboMatrices);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, uboMatrices);
|
||||
glBufferData(GL_UNIFORM_BUFFER, 2 * sizeof(glm::mat4), NULL, GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||
// Define the range of the buffer that links to a uniform binding point
|
||||
glBindBufferRange(GL_UNIFORM_BUFFER, 0, uboMatrices, 0, 2 * sizeof(glm::mat4));
|
||||
|
||||
// Store the projection matrix (we only have to do this once) (note: we're not using zoom anymore by changing the FoV. We only create the projection matrix once now)
|
||||
glm::mat4 projection = glm::perspective(45.0f, (float)screenWidth/(float)screenHeight, 0.1f, 100.0f);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, uboMatrices);
|
||||
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(glm::mat4), glm::value_ptr(projection));
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||
|
||||
|
||||
// Game loop
|
||||
while(!glfwWindowShouldClose(window))
|
||||
{
|
||||
// Set frame time
|
||||
GLfloat currentFrame = glfwGetTime();
|
||||
deltaTime = currentFrame - lastFrame;
|
||||
lastFrame = currentFrame;
|
||||
|
||||
// Check and call events
|
||||
glfwPollEvents();
|
||||
Do_Movement();
|
||||
|
||||
// Clear buffers
|
||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// Set the view and projection matrix in the uniform block - we only have to do this once per loop iteration.
|
||||
glm::mat4 view = camera.GetViewMatrix();
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, uboMatrices);
|
||||
glBufferSubData(GL_UNIFORM_BUFFER, sizeof(glm::mat4), sizeof(glm::mat4), glm::value_ptr(view));
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||
|
||||
// Draw 4 cubes
|
||||
// RED
|
||||
glBindVertexArray(cubeVAO);
|
||||
shaderRed.Use();
|
||||
glm::mat4 model;
|
||||
model = glm::translate(model, glm::vec3(-0.75f, 0.75f, 0.0f)); // Move top-left
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderRed.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
// GREEN
|
||||
shaderGreen.Use();
|
||||
model = glm::mat4();
|
||||
model = glm::translate(model, glm::vec3(0.75f, 0.75f, 0.0f)); // Move top-right
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderGreen.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
// BLUE
|
||||
shaderBlue.Use();
|
||||
model = glm::mat4();
|
||||
model = glm::translate(model, glm::vec3(-0.75f, -0.75f, 0.0f)); // Move bottom-left
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderBlue.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
// YELLOW
|
||||
shaderYellow.Use();
|
||||
model = glm::mat4();
|
||||
model = glm::translate(model, glm::vec3(0.75f, -0.75f, 0.0f)); // Move bottom-right
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderYellow.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
glBindVertexArray(0);
|
||||
|
||||
// Swap the buffers
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
|
||||
glfwTerminate();
|
||||
return 0;
|
||||
}
|
||||
#pragma region "User input"
|
||||
|
||||
// Moves/alters the camera positions based on user input
|
||||
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);
|
||||
}
|
||||
|
||||
// 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(action == GLFW_PRESS)
|
||||
keys[key] = true;
|
||||
else if(action == GLFW_RELEASE)
|
||||
keys[key] = false;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
|
||||
camera.ProcessMouseMovement(xoffset, yoffset);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
7
src/4.advanced_opengl/8.advanced_glsl/blue.frag
Normal file
7
src/4.advanced_opengl/8.advanced_glsl/blue.frag
Normal file
@@ -0,0 +1,7 @@
|
||||
#version 330 core
|
||||
out vec4 color;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = vec4(0.0, 0.0, 1.0, 1.0);
|
||||
}
|
||||
7
src/4.advanced_opengl/8.advanced_glsl/green.frag
Normal file
7
src/4.advanced_opengl/8.advanced_glsl/green.frag
Normal file
@@ -0,0 +1,7 @@
|
||||
#version 330 core
|
||||
out vec4 color;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = vec4(0.0, 1.0, 0.0, 1.0);
|
||||
}
|
||||
7
src/4.advanced_opengl/8.advanced_glsl/red.frag
Normal file
7
src/4.advanced_opengl/8.advanced_glsl/red.frag
Normal file
@@ -0,0 +1,7 @@
|
||||
#version 330 core
|
||||
out vec4 color;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
14
src/4.advanced_opengl/8.advanced_glsl/uniform_buffers.vs
Normal file
14
src/4.advanced_opengl/8.advanced_glsl/uniform_buffers.vs
Normal file
@@ -0,0 +1,14 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 position;
|
||||
|
||||
layout (std140) uniform Matrices
|
||||
{
|
||||
mat4 projection;
|
||||
mat4 view;
|
||||
};
|
||||
uniform mat4 model;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projection * view * model * vec4(position, 1.0);
|
||||
}
|
||||
7
src/4.advanced_opengl/8.advanced_glsl/yellow.frag
Normal file
7
src/4.advanced_opengl/8.advanced_glsl/yellow.frag
Normal file
@@ -0,0 +1,7 @@
|
||||
#version 330 core
|
||||
out vec4 color;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = vec4(1.0, 1.0, 0.0, 1.0);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#version 330 core
|
||||
in vec3 fColor;
|
||||
out vec4 color;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = vec4(fColor, 1.0f);
|
||||
}
|
||||
30
src/4.advanced_opengl/9.geometry_shader/geometry_shader.gs
Normal file
30
src/4.advanced_opengl/9.geometry_shader/geometry_shader.gs
Normal file
@@ -0,0 +1,30 @@
|
||||
#version 330 core
|
||||
layout (points) in;
|
||||
layout (triangle_strip, max_vertices = 5) out;
|
||||
|
||||
in VS_OUT {
|
||||
vec3 color;
|
||||
} gs_in[];
|
||||
|
||||
out vec3 fColor;
|
||||
|
||||
void build_house(vec4 position)
|
||||
{
|
||||
fColor = gs_in[0].color; // gs_in[0] since there's only one input vertex
|
||||
gl_Position = position + vec4(-0.2f, -0.2f, 0.0f, 0.0f); // 1:bottom-left
|
||||
EmitVertex();
|
||||
gl_Position = position + vec4( 0.2f, -0.2f, 0.0f, 0.0f); // 2:bottom-right
|
||||
EmitVertex();
|
||||
gl_Position = position + vec4(-0.2f, 0.2f, 0.0f, 0.0f); // 3:top-left
|
||||
EmitVertex();
|
||||
gl_Position = position + vec4( 0.2f, 0.2f, 0.0f, 0.0f); // 4:top-right
|
||||
EmitVertex();
|
||||
gl_Position = position + vec4( 0.0f, 0.4f, 0.0f, 0.0f); // 5:top
|
||||
fColor = vec3(1.0f, 1.0f, 1.0f);
|
||||
EmitVertex();
|
||||
EndPrimitive();
|
||||
}
|
||||
|
||||
void main() {
|
||||
build_house(gl_in[0].gl_Position);
|
||||
}
|
||||
13
src/4.advanced_opengl/9.geometry_shader/geometry_shader.vs
Normal file
13
src/4.advanced_opengl/9.geometry_shader/geometry_shader.vs
Normal file
@@ -0,0 +1,13 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec2 position;
|
||||
layout (location = 1) in vec3 color;
|
||||
|
||||
out VS_OUT {
|
||||
vec3 color;
|
||||
} vs_out;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(position.x, position.y, 0.0f, 1.0f);
|
||||
vs_out.color = color;
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
// GLEW
|
||||
#define GLEW_STATIC
|
||||
#include <GL/glew.h>
|
||||
|
||||
// GLFW
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
// GL includes
|
||||
#include <learnopengl/shader.h>
|
||||
|
||||
// Properties
|
||||
GLuint screenWidth = 800, screenHeight = 600;
|
||||
|
||||
// The MAIN function, from here we start our application and run our Game loop
|
||||
int main()
|
||||
{
|
||||
// Init GLFW
|
||||
glfwInit();
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
|
||||
|
||||
GLFWwindow* window = glfwCreateWindow(screenWidth, screenHeight, "LearnOpenGL", nullptr, nullptr); // Windowed
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
// Options
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
|
||||
// Initialize GLEW to setup the OpenGL Function pointers
|
||||
glewExperimental = GL_TRUE;
|
||||
glewInit();
|
||||
|
||||
// Define the viewport dimensions
|
||||
glViewport(0, 0, screenWidth, screenHeight);
|
||||
|
||||
// Setup and compile our shaders
|
||||
Shader shader("geometry_shader.vs", "geometry_shader.frag", "geometry_shader.gs");
|
||||
|
||||
// Vertex data
|
||||
GLfloat points[] = {
|
||||
-0.5f, 0.5f, 1.0f, 0.0f, 0.0f, // Top-left
|
||||
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, // Top-right
|
||||
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, // Bottom-right
|
||||
-0.5f, -0.5f, 1.0f, 1.0f, 0.0f // Bottom-left
|
||||
};
|
||||
GLuint VBO, VAO;
|
||||
glGenBuffers(1, &VBO);
|
||||
glGenVertexArrays(1, &VAO);
|
||||
glBindVertexArray(VAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(points), &points, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), 0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(2 * sizeof(GLfloat)));
|
||||
glBindVertexArray(0);
|
||||
|
||||
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
|
||||
// Game loop
|
||||
while(!glfwWindowShouldClose(window))
|
||||
{
|
||||
// Check and call events
|
||||
glfwPollEvents();
|
||||
|
||||
// Clear buffers
|
||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
// Draw points
|
||||
shader.Use();
|
||||
glBindVertexArray(VAO);
|
||||
glDrawArrays(GL_POINTS, 0, 4);
|
||||
glBindVertexArray(0);
|
||||
|
||||
// Swap the buffers
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
|
||||
glfwTerminate();
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user