mirror of
https://github.com/JoeyDeVries/LearnOpenGL.git
synced 2026-01-02 04:37:54 +08:00
Start code re-work Advanced OpenGL chapter.
This commit is contained in:
@@ -110,16 +110,22 @@ set(3.model_loading
|
||||
)
|
||||
|
||||
set(4.advanced_opengl
|
||||
1.depth_testing
|
||||
1.1.depth_testing
|
||||
1.2.depth_testing_view
|
||||
2.stencil_testing
|
||||
3.1.blending_discard
|
||||
3.2.blending_sort
|
||||
5.framebuffers
|
||||
6.cubemaps
|
||||
8.advanced_glsl
|
||||
9.geometry_shader
|
||||
10.instancing
|
||||
11.anti_aliasing
|
||||
5.1.framebuffers
|
||||
5.2.framebuffers_exercise1
|
||||
6.1.cubemaps_skybox
|
||||
6.2.cubemaps_environment_mapping
|
||||
8.advanced_glsl_ubo
|
||||
9.1.geometry_shader_houses
|
||||
9.2.geometry_shader_exploding
|
||||
9.3.geometry_shader_normal_visualization
|
||||
10.1.instancing_quads
|
||||
10.2.instancing_asteroids
|
||||
11.anti_aliasing_offscreen
|
||||
)
|
||||
|
||||
set(5.advanced_lighting
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#version 330 core
|
||||
in vec2 TexCoords;
|
||||
out vec4 FragColor;
|
||||
|
||||
out vec4 color;
|
||||
in vec2 TexCoords;
|
||||
|
||||
uniform sampler2D texture1;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = texture(texture1, TexCoords);
|
||||
{
|
||||
FragColor = texture(texture1, TexCoords);
|
||||
}
|
||||
15
src/4.advanced_opengl/1.1.depth_testing/1.1.depth_testing.vs
Normal file
15
src/4.advanced_opengl/1.1.depth_testing/1.1.depth_testing.vs
Normal file
@@ -0,0 +1,15 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 aPos;
|
||||
layout (location = 1) in vec2 aTexCoords;
|
||||
|
||||
out vec2 TexCoords;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
|
||||
void main()
|
||||
{
|
||||
TexCoords = aTexCoords;
|
||||
gl_Position = projection * view * model * vec4(aPos, 1.0f);
|
||||
}
|
||||
322
src/4.advanced_opengl/1.1.depth_testing/depth_testing.cpp
Normal file
322
src/4.advanced_opengl/1.1.depth_testing/depth_testing.cpp
Normal file
@@ -0,0 +1,322 @@
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <stb_image.h>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
#include <learnopengl/filesystem.h>
|
||||
#include <learnopengl/shader_m.h>
|
||||
#include <learnopengl/camera.h>
|
||||
#include <learnopengl/model.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
|
||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
|
||||
void processInput(GLFWwindow *window);
|
||||
unsigned int loadTexture(const char *path);
|
||||
|
||||
// settings
|
||||
const unsigned int SCR_WIDTH = 1280;
|
||||
const unsigned int SCR_HEIGHT = 720;
|
||||
|
||||
// camera
|
||||
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
|
||||
float lastX = (float)SCR_WIDTH / 2.0;
|
||||
float lastY = (float)SCR_HEIGHT / 2.0;
|
||||
bool firstMouse = true;
|
||||
|
||||
// timing
|
||||
float deltaTime = 0.0f;
|
||||
float lastFrame = 0.0f;
|
||||
|
||||
int main()
|
||||
{
|
||||
// glfw: initialize and configure
|
||||
// ------------------------------
|
||||
glfwInit();
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
|
||||
// glfw window creation
|
||||
// --------------------
|
||||
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
|
||||
glfwMakeContextCurrent(window);
|
||||
if (window == NULL)
|
||||
{
|
||||
std::cout << "Failed to create GLFW window" << std::endl;
|
||||
glfwTerminate();
|
||||
return -1;
|
||||
}
|
||||
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
|
||||
glfwSetCursorPosCallback(window, mouse_callback);
|
||||
glfwSetScrollCallback(window, scroll_callback);
|
||||
|
||||
// tell GLFW to capture our mouse
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
|
||||
// glad: load all OpenGL function pointers
|
||||
// ---------------------------------------
|
||||
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
|
||||
{
|
||||
std::cout << "Failed to initialize GLAD" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// configure global opengl state
|
||||
// -----------------------------
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_ALWAYS); // always pass the depth test (same effect as glDisable(GL_DEPTH_TEST))
|
||||
|
||||
// build and compile shaders
|
||||
// -------------------------
|
||||
Shader shader("1.1.depth_testing.vs", "1.1.depth_testing.fs");
|
||||
|
||||
// set up vertex data (and buffer(s)) and configure vertex attributes
|
||||
// ------------------------------------------------------------------
|
||||
float cubeVertices[] = {
|
||||
// positions // texture Coords
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
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
|
||||
};
|
||||
float planeVertices[] = {
|
||||
// positions // texture Coords (note we set these higher than 1 (together with GL_REPEAT as texture wrapping mode). this will cause the floor texture to repeat)
|
||||
5.0f, -0.5f, 5.0f, 2.0f, 0.0f,
|
||||
-5.0f, -0.5f, 5.0f, 0.0f, 0.0f,
|
||||
-5.0f, -0.5f, -5.0f, 0.0f, 2.0f,
|
||||
|
||||
5.0f, -0.5f, 5.0f, 2.0f, 0.0f,
|
||||
-5.0f, -0.5f, -5.0f, 0.0f, 2.0f,
|
||||
5.0f, -0.5f, -5.0f, 2.0f, 2.0f
|
||||
};
|
||||
// cube VAO
|
||||
unsigned int cubeVAO, cubeVBO;
|
||||
glGenVertexArrays(1, &cubeVAO);
|
||||
glGenBuffers(1, &cubeVBO);
|
||||
glBindVertexArray(cubeVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), &cubeVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
|
||||
glBindVertexArray(0);
|
||||
// plane VAO
|
||||
unsigned int planeVAO, planeVBO;
|
||||
glGenVertexArrays(1, &planeVAO);
|
||||
glGenBuffers(1, &planeVBO);
|
||||
glBindVertexArray(planeVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, planeVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(planeVertices), &planeVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
|
||||
glBindVertexArray(0);
|
||||
|
||||
// load textures
|
||||
// -------------
|
||||
unsigned int cubeTexture = loadTexture(FileSystem::getPath("resources/textures/marble.jpg").c_str());
|
||||
unsigned int floorTexture = loadTexture(FileSystem::getPath("resources/textures/metal.png").c_str());
|
||||
|
||||
// shader configuration
|
||||
// --------------------
|
||||
shader.use();
|
||||
shader.setInt("ourTexture", 0);
|
||||
|
||||
// render loop
|
||||
// -----------
|
||||
while(!glfwWindowShouldClose(window))
|
||||
{
|
||||
// per-frame time logic
|
||||
// --------------------
|
||||
float currentFrame = glfwGetTime();
|
||||
deltaTime = currentFrame - lastFrame;
|
||||
lastFrame = currentFrame;
|
||||
|
||||
// input
|
||||
// -----
|
||||
processInput(window);
|
||||
|
||||
// render
|
||||
// ------
|
||||
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
shader.use();
|
||||
glm::mat4 model;
|
||||
glm::mat4 view = camera.GetViewMatrix();
|
||||
glm::mat4 projection = glm::perspective(camera.Zoom, (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
|
||||
shader.setMat4("view", view);
|
||||
shader.setMat4("projection", projection);
|
||||
// cubes
|
||||
glBindVertexArray(cubeVAO);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, cubeTexture);
|
||||
model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f));
|
||||
shader.setMat4("model", model);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
model = glm::mat4();
|
||||
model = glm::translate(model, glm::vec3(2.0f, 0.0f, 0.0f));
|
||||
shader.setMat4("model", model);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
// floor
|
||||
glBindVertexArray(planeVAO);
|
||||
glBindTexture(GL_TEXTURE_2D, floorTexture);
|
||||
shader.setMat4("model", glm::mat4());
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
glBindVertexArray(0);
|
||||
|
||||
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
|
||||
// -------------------------------------------------------------------------------
|
||||
glfwSwapBuffers(window);
|
||||
glfwPollEvents();
|
||||
}
|
||||
|
||||
// optional: de-allocate all resources once they've outlived their purpose:
|
||||
// ------------------------------------------------------------------------
|
||||
glDeleteVertexArrays(1, &cubeVAO);
|
||||
glDeleteVertexArrays(1, &planeVAO);
|
||||
glDeleteBuffers(1, &cubeVBO);
|
||||
glDeleteBuffers(1, &planeVBO);
|
||||
|
||||
glfwTerminate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
|
||||
// ---------------------------------------------------------------------------------------------------------
|
||||
void processInput(GLFWwindow *window)
|
||||
{
|
||||
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
|
||||
glfwSetWindowShouldClose(window, true);
|
||||
|
||||
float cameraSpeed = 2.5 * deltaTime;
|
||||
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
|
||||
camera.ProcessKeyboard(FORWARD, deltaTime);
|
||||
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
|
||||
camera.ProcessKeyboard(BACKWARD, deltaTime);
|
||||
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
|
||||
camera.ProcessKeyboard(LEFT, deltaTime);
|
||||
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
|
||||
camera.ProcessKeyboard(RIGHT, deltaTime);
|
||||
}
|
||||
|
||||
// glfw: whenever the window size changed (by OS or user resize) this callback function executes
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
|
||||
{
|
||||
// make sure the viewport matches the new window dimensions; note that width and
|
||||
// height will be significantly larger than specified on retina displays.
|
||||
glViewport(0, 0, width, height);
|
||||
}
|
||||
|
||||
|
||||
// glfw: whenever the mouse moves, this callback is called
|
||||
// -------------------------------------------------------
|
||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
|
||||
{
|
||||
if (firstMouse)
|
||||
{
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
firstMouse = false;
|
||||
}
|
||||
|
||||
float xoffset = xpos - lastX;
|
||||
float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top
|
||||
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
|
||||
camera.ProcessMouseMovement(xoffset, yoffset);
|
||||
}
|
||||
|
||||
// glfw: whenever the mouse scroll wheel scrolls, this callback is called
|
||||
// ----------------------------------------------------------------------
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
|
||||
{
|
||||
camera.ProcessMouseScroll(yoffset);
|
||||
}
|
||||
|
||||
// utility function for loading a 2D texture from file
|
||||
// ---------------------------------------------------
|
||||
unsigned int loadTexture(char const * path)
|
||||
{
|
||||
unsigned int textureID;
|
||||
glGenTextures(1, &textureID);
|
||||
|
||||
int width, height, nrComponents;
|
||||
unsigned char *data = stbi_load(path, &width, &height, &nrComponents, 0);
|
||||
if (data)
|
||||
{
|
||||
GLenum format;
|
||||
if (nrComponents == 1)
|
||||
format = GL_RED;
|
||||
else if (nrComponents == 3)
|
||||
format = GL_RGB;
|
||||
else if (nrComponents == 4)
|
||||
format = GL_RGBA;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
stbi_image_free(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Texture failed to load at path: " << path << std::endl;
|
||||
stbi_image_free(data);
|
||||
}
|
||||
|
||||
return textureID;
|
||||
}
|
||||
@@ -1,16 +1,16 @@
|
||||
#version 330 core
|
||||
out vec4 color;
|
||||
out vec4 FragColor;
|
||||
|
||||
float near = 1.0;
|
||||
float near = 0.1;
|
||||
float far = 100.0;
|
||||
float LinearizeDepth(float depth)
|
||||
{
|
||||
float z = depth * 2.0 - 1.0; // Back to NDC
|
||||
float z = depth * 2.0 - 1.0; // back to NDC
|
||||
return (2.0 * near * far) / (far + near - z * (far - near));
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
float depth = LinearizeDepth(gl_FragCoord.z) / far; // divide by far to get depth in range [0,1] for visualization purposes.
|
||||
color = vec4(vec3(depth), 1.0f);
|
||||
float depth = LinearizeDepth(gl_FragCoord.z) / far; // divide by far to get depth in range [0,1] for visualization purposes
|
||||
FragColor = vec4(vec3(depth), 1.0);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 aPos;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projection * view * model * vec4(aPos, 1.0f);
|
||||
}
|
||||
@@ -0,0 +1,322 @@
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <stb_image.h>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
#include <learnopengl/filesystem.h>
|
||||
#include <learnopengl/shader_m.h>
|
||||
#include <learnopengl/camera.h>
|
||||
#include <learnopengl/model.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
|
||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
|
||||
void processInput(GLFWwindow *window);
|
||||
unsigned int loadTexture(const char *path);
|
||||
|
||||
// settings
|
||||
const unsigned int SCR_WIDTH = 1280;
|
||||
const unsigned int SCR_HEIGHT = 720;
|
||||
|
||||
// camera
|
||||
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
|
||||
float lastX = (float)SCR_WIDTH / 2.0;
|
||||
float lastY = (float)SCR_HEIGHT / 2.0;
|
||||
bool firstMouse = true;
|
||||
|
||||
// timing
|
||||
float deltaTime = 0.0f;
|
||||
float lastFrame = 0.0f;
|
||||
|
||||
int main()
|
||||
{
|
||||
// glfw: initialize and configure
|
||||
// ------------------------------
|
||||
glfwInit();
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
|
||||
// glfw window creation
|
||||
// --------------------
|
||||
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
|
||||
glfwMakeContextCurrent(window);
|
||||
if (window == NULL)
|
||||
{
|
||||
std::cout << "Failed to create GLFW window" << std::endl;
|
||||
glfwTerminate();
|
||||
return -1;
|
||||
}
|
||||
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
|
||||
glfwSetCursorPosCallback(window, mouse_callback);
|
||||
glfwSetScrollCallback(window, scroll_callback);
|
||||
|
||||
// tell GLFW to capture our mouse
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
|
||||
// glad: load all OpenGL function pointers
|
||||
// ---------------------------------------
|
||||
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
|
||||
{
|
||||
std::cout << "Failed to initialize GLAD" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// configure global opengl state
|
||||
// -----------------------------
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LESS);
|
||||
|
||||
// build and compile shaders
|
||||
// -------------------------
|
||||
Shader shader("1.2.depth_testing.vs", "1.2.depth_testing.fs");
|
||||
|
||||
// set up vertex data (and buffer(s)) and configure vertex attributes
|
||||
// ------------------------------------------------------------------
|
||||
float cubeVertices[] = {
|
||||
// positions // texture Coords
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
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
|
||||
};
|
||||
float planeVertices[] = {
|
||||
// positions // texture Coords (note we set these higher than 1 (together with GL_REPEAT as texture wrapping mode). this will cause the floor texture to repeat)
|
||||
5.0f, -0.5f, 5.0f, 2.0f, 0.0f,
|
||||
-5.0f, -0.5f, 5.0f, 0.0f, 0.0f,
|
||||
-5.0f, -0.5f, -5.0f, 0.0f, 2.0f,
|
||||
|
||||
5.0f, -0.5f, 5.0f, 2.0f, 0.0f,
|
||||
-5.0f, -0.5f, -5.0f, 0.0f, 2.0f,
|
||||
5.0f, -0.5f, -5.0f, 2.0f, 2.0f
|
||||
};
|
||||
// cube VAO
|
||||
unsigned int cubeVAO, cubeVBO;
|
||||
glGenVertexArrays(1, &cubeVAO);
|
||||
glGenBuffers(1, &cubeVBO);
|
||||
glBindVertexArray(cubeVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), &cubeVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
|
||||
glBindVertexArray(0);
|
||||
// plane VAO
|
||||
unsigned int planeVAO, planeVBO;
|
||||
glGenVertexArrays(1, &planeVAO);
|
||||
glGenBuffers(1, &planeVBO);
|
||||
glBindVertexArray(planeVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, planeVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(planeVertices), &planeVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
|
||||
glBindVertexArray(0);
|
||||
|
||||
// load textures
|
||||
// -------------
|
||||
unsigned int cubeTexture = loadTexture(FileSystem::getPath("resources/textures/marble.jpg").c_str());
|
||||
unsigned int floorTexture = loadTexture(FileSystem::getPath("resources/textures/metal.png").c_str());
|
||||
|
||||
// shader configuration
|
||||
// --------------------
|
||||
shader.use();
|
||||
shader.setInt("ourTexture", 0);
|
||||
|
||||
// render loop
|
||||
// -----------
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
// per-frame time logic
|
||||
// --------------------
|
||||
float currentFrame = glfwGetTime();
|
||||
deltaTime = currentFrame - lastFrame;
|
||||
lastFrame = currentFrame;
|
||||
|
||||
// input
|
||||
// -----
|
||||
processInput(window);
|
||||
|
||||
// render
|
||||
// ------
|
||||
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
shader.use();
|
||||
glm::mat4 model;
|
||||
glm::mat4 view = camera.GetViewMatrix();
|
||||
glm::mat4 projection = glm::perspective(camera.Zoom, (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
|
||||
shader.setMat4("view", view);
|
||||
shader.setMat4("projection", projection);
|
||||
// cubes
|
||||
glBindVertexArray(cubeVAO);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, cubeTexture);
|
||||
model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f));
|
||||
shader.setMat4("model", model);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
model = glm::mat4();
|
||||
model = glm::translate(model, glm::vec3(2.0f, 0.0f, 0.0f));
|
||||
shader.setMat4("model", model);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
// floor
|
||||
glBindVertexArray(planeVAO);
|
||||
glBindTexture(GL_TEXTURE_2D, floorTexture);
|
||||
shader.setMat4("model", glm::mat4());
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
glBindVertexArray(0);
|
||||
|
||||
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
|
||||
// -------------------------------------------------------------------------------
|
||||
glfwSwapBuffers(window);
|
||||
glfwPollEvents();
|
||||
}
|
||||
|
||||
// optional: de-allocate all resources once they've outlived their purpose:
|
||||
// ------------------------------------------------------------------------
|
||||
glDeleteVertexArrays(1, &cubeVAO);
|
||||
glDeleteVertexArrays(1, &planeVAO);
|
||||
glDeleteBuffers(1, &cubeVBO);
|
||||
glDeleteBuffers(1, &planeVBO);
|
||||
|
||||
glfwTerminate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
|
||||
// ---------------------------------------------------------------------------------------------------------
|
||||
void processInput(GLFWwindow *window)
|
||||
{
|
||||
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
|
||||
glfwSetWindowShouldClose(window, true);
|
||||
|
||||
float cameraSpeed = 2.5 * deltaTime;
|
||||
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
|
||||
camera.ProcessKeyboard(FORWARD, deltaTime);
|
||||
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
|
||||
camera.ProcessKeyboard(BACKWARD, deltaTime);
|
||||
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
|
||||
camera.ProcessKeyboard(LEFT, deltaTime);
|
||||
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
|
||||
camera.ProcessKeyboard(RIGHT, deltaTime);
|
||||
}
|
||||
|
||||
// glfw: whenever the window size changed (by OS or user resize) this callback function executes
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
|
||||
{
|
||||
// make sure the viewport matches the new window dimensions; note that width and
|
||||
// height will be significantly larger than specified on retina displays.
|
||||
glViewport(0, 0, width, height);
|
||||
}
|
||||
|
||||
|
||||
// glfw: whenever the mouse moves, this callback is called
|
||||
// -------------------------------------------------------
|
||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
|
||||
{
|
||||
if (firstMouse)
|
||||
{
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
firstMouse = false;
|
||||
}
|
||||
|
||||
float xoffset = xpos - lastX;
|
||||
float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top
|
||||
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
|
||||
camera.ProcessMouseMovement(xoffset, yoffset);
|
||||
}
|
||||
|
||||
// glfw: whenever the mouse scroll wheel scrolls, this callback is called
|
||||
// ----------------------------------------------------------------------
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
|
||||
{
|
||||
camera.ProcessMouseScroll(yoffset);
|
||||
}
|
||||
|
||||
// utility function for loading a 2D texture from file
|
||||
// ---------------------------------------------------
|
||||
unsigned int loadTexture(char const * path)
|
||||
{
|
||||
unsigned int textureID;
|
||||
glGenTextures(1, &textureID);
|
||||
|
||||
int width, height, nrComponents;
|
||||
unsigned char *data = stbi_load(path, &width, &height, &nrComponents, 0);
|
||||
if (data)
|
||||
{
|
||||
GLenum format;
|
||||
if (nrComponents == 1)
|
||||
format = GL_RED;
|
||||
else if (nrComponents == 3)
|
||||
format = GL_RGB;
|
||||
else if (nrComponents == 4)
|
||||
format = GL_RGBA;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
stbi_image_free(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Texture failed to load at path: " << path << std::endl;
|
||||
stbi_image_free(data);
|
||||
}
|
||||
|
||||
return textureID;
|
||||
}
|
||||
@@ -1,15 +1,15 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 position;
|
||||
layout (location = 1) in vec2 texCoords;
|
||||
layout (location = 2) in vec2 texCoords;
|
||||
layout (location = 3) in mat4 instanceMatrix;
|
||||
|
||||
out vec2 TexCoords;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
uniform mat4 view;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projection * view * model * vec4(position, 1.0f);
|
||||
gl_Position = projection * view * instanceMatrix * vec4(position, 1.0f);
|
||||
TexCoords = texCoords;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#version 330 core
|
||||
in vec2 TexCoords;
|
||||
out vec4 color;
|
||||
|
||||
uniform sampler2D texture_diffuse1;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = texture(texture_diffuse1, TexCoords);
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
// 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>
|
||||
|
||||
#include <learnopengl/filesystem.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, 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(FileSystem::getPath("resources/objects/rock/rock.obj").c_str());
|
||||
Model planet(FileSystem::getPath("resources/objects/planet/planet.obj").c_str());
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// forward declare the buffer
|
||||
GLuint buffer;
|
||||
glGenBuffers(1, &buffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, amount * sizeof(glm::mat4), &modelMatrices[0], GL_STATIC_DRAW);
|
||||
|
||||
// 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;
|
||||
glBindVertexArray(VAO);
|
||||
// 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();
|
||||
// NB: This could all be implemented as a method within the Model class, perhaps "DrawInstanced(const GLuint amount)"
|
||||
glActiveTexture(GL_TEXTURE0); // Activate proper texture unit before binding
|
||||
glUniform1i(glGetUniformLocation(instanceShader.Program, "texture_diffuse1"), 0); // Now set the sampler to the correct texture unit
|
||||
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].indices.size(), GL_UNSIGNED_INT, 0, amount);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
// reset our texture binding
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, 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
|
||||
@@ -0,0 +1,7 @@
|
||||
#version 330 core
|
||||
out vec4 FragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor = vec4(0.04, 0.28, 0.26, 1.0);
|
||||
}
|
||||
11
src/4.advanced_opengl/2.stencil_testing/2.stencil_testing.fs
Normal file
11
src/4.advanced_opengl/2.stencil_testing/2.stencil_testing.fs
Normal file
@@ -0,0 +1,11 @@
|
||||
#version 330 core
|
||||
out vec4 FragColor;
|
||||
|
||||
in vec2 TexCoords;
|
||||
|
||||
uniform sampler2D texture1;
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor = texture(texture1, TexCoords);
|
||||
}
|
||||
15
src/4.advanced_opengl/2.stencil_testing/2.stencil_testing.vs
Normal file
15
src/4.advanced_opengl/2.stencil_testing/2.stencil_testing.vs
Normal file
@@ -0,0 +1,15 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 aPos;
|
||||
layout (location = 1) in vec2 aTexCoords;
|
||||
|
||||
out vec2 TexCoords;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
|
||||
void main()
|
||||
{
|
||||
TexCoords = aTexCoords;
|
||||
gl_Position = projection * view * model * vec4(aPos, 1.0f);
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
#version 330 core
|
||||
out vec4 outColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
outColor = vec4(0.04, 0.28, 0.26, 1.0);
|
||||
}
|
||||
@@ -1,88 +1,89 @@
|
||||
// Std. Includes
|
||||
#include <string>
|
||||
|
||||
// GLEW
|
||||
#define GLEW_STATIC
|
||||
#include <GL/glew.h>
|
||||
|
||||
// GLFW
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <stb_image.h>
|
||||
|
||||
// GL includes
|
||||
#include <learnopengl/shader.h>
|
||||
#include <learnopengl/camera.h>
|
||||
|
||||
// GLM Mathemtics
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
// Other Libs
|
||||
#include <SOIL.h>
|
||||
#include <learnopengl/filesystem.h>
|
||||
#include <learnopengl/shader_m.h>
|
||||
#include <learnopengl/camera.h>
|
||||
#include <learnopengl/model.h>
|
||||
|
||||
// Properties
|
||||
GLuint screenWidth = 800, screenHeight = 600;
|
||||
#include <iostream>
|
||||
|
||||
// Function prototypes
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
|
||||
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
|
||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
|
||||
void Do_Movement();
|
||||
GLuint loadTexture(GLchar const * path);
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
|
||||
void processInput(GLFWwindow *window);
|
||||
unsigned int loadTexture(const char *path);
|
||||
|
||||
// Camera
|
||||
// settings
|
||||
const unsigned int SCR_WIDTH = 1280;
|
||||
const unsigned int SCR_HEIGHT = 720;
|
||||
|
||||
// camera
|
||||
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
|
||||
bool keys[1024];
|
||||
GLfloat lastX = 400, lastY = 300;
|
||||
float lastX = (float)SCR_WIDTH / 2.0;
|
||||
float lastY = (float)SCR_HEIGHT / 2.0;
|
||||
bool firstMouse = true;
|
||||
|
||||
GLfloat deltaTime = 0.0f;
|
||||
GLfloat lastFrame = 0.0f;
|
||||
// timing
|
||||
float deltaTime = 0.0f;
|
||||
float lastFrame = 0.0f;
|
||||
|
||||
// The MAIN function, from here we start our application and run our Game loop
|
||||
int main()
|
||||
{
|
||||
// Init GLFW
|
||||
// glfw: initialize and configure
|
||||
// ------------------------------
|
||||
glfwInit();
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
|
||||
|
||||
GLFWwindow* window = glfwCreateWindow(screenWidth, screenHeight, "LearnOpenGL", nullptr, nullptr); // Windowed
|
||||
// glfw window creation
|
||||
// --------------------
|
||||
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
// Set the required callback functions
|
||||
glfwSetKeyCallback(window, key_callback);
|
||||
if (window == NULL)
|
||||
{
|
||||
std::cout << "Failed to create GLFW window" << std::endl;
|
||||
glfwTerminate();
|
||||
return -1;
|
||||
}
|
||||
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
|
||||
glfwSetCursorPosCallback(window, mouse_callback);
|
||||
glfwSetScrollCallback(window, scroll_callback);
|
||||
|
||||
// Options
|
||||
// tell GLFW to capture our mouse
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
|
||||
// Initialize GLEW to setup the OpenGL Function pointers
|
||||
glewExperimental = GL_TRUE;
|
||||
glewInit();
|
||||
// glad: load all OpenGL function pointers
|
||||
// ---------------------------------------
|
||||
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
|
||||
{
|
||||
std::cout << "Failed to initialize GLAD" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Define the viewport dimensions
|
||||
glViewport(0, 0, screenWidth, screenHeight);
|
||||
|
||||
// Setup some OpenGL options
|
||||
// configure global opengl state
|
||||
// -----------------------------
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LESS);
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
||||
|
||||
// Setup and compile our shaders
|
||||
Shader shader("stencil_testing.vs", "stencil_testing.frag");
|
||||
Shader shaderSingleColor("stencil_testing.vs", "stencil_single_color.frag");
|
||||
// build and compile shaders
|
||||
// -------------------------
|
||||
Shader shader("2.stencil_testing.vs", "2.stencil_testing.fs");
|
||||
Shader shaderSingleColor("2.stencil_testing.vs", "2.stencil_single_color.fs");
|
||||
|
||||
#pragma region "object_initialization"
|
||||
// Set the object data (buffers, vertex attributes)
|
||||
GLfloat cubeVertices[] = {
|
||||
// Positions // Texture Coords
|
||||
// set up vertex data (and buffer(s)) and configure vertex attributes
|
||||
// ------------------------------------------------------------------
|
||||
float cubeVertices[] = {
|
||||
// positions // texture Coords
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
@@ -125,214 +126,240 @@ int main()
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f
|
||||
};
|
||||
GLfloat planeVertices[] = {
|
||||
// Positions // Texture Coords (note we set these higher than 1 that together with GL_REPEAT (as texture wrapping mode) will cause the floor texture to repeat)
|
||||
5.0f, -0.5f, 5.0f, 2.0f, 0.0f,
|
||||
float planeVertices[] = {
|
||||
// positions // texture Coords (note we set these higher than 1 (together with GL_REPEAT as texture wrapping mode). this will cause the floor texture to repeat)
|
||||
5.0f, -0.5f, 5.0f, 2.0f, 0.0f,
|
||||
-5.0f, -0.5f, 5.0f, 0.0f, 0.0f,
|
||||
-5.0f, -0.5f, -5.0f, 0.0f, 2.0f,
|
||||
|
||||
5.0f, -0.5f, 5.0f, 2.0f, 0.0f,
|
||||
5.0f, -0.5f, 5.0f, 2.0f, 0.0f,
|
||||
-5.0f, -0.5f, -5.0f, 0.0f, 2.0f,
|
||||
5.0f, -0.5f, -5.0f, 2.0f, 2.0f
|
||||
5.0f, -0.5f, -5.0f, 2.0f, 2.0f
|
||||
};
|
||||
// Setup cube VAO
|
||||
GLuint cubeVAO, cubeVBO;
|
||||
// cube VAO
|
||||
unsigned int cubeVAO, cubeVBO;
|
||||
glGenVertexArrays(1, &cubeVAO);
|
||||
glGenBuffers(1, &cubeVBO);
|
||||
glBindVertexArray(cubeVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), &cubeVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
|
||||
glBindVertexArray(0);
|
||||
// Setup plane VAO
|
||||
GLuint planeVAO, planeVBO;
|
||||
// plane VAO
|
||||
unsigned int planeVAO, planeVBO;
|
||||
glGenVertexArrays(1, &planeVAO);
|
||||
glGenBuffers(1, &planeVBO);
|
||||
glBindVertexArray(planeVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, planeVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(planeVertices), &planeVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
|
||||
glBindVertexArray(0);
|
||||
|
||||
// Load textures
|
||||
GLuint cubeTexture = loadTexture(FileSystem::getPath("resources/textures/marble.jpg").c_str());
|
||||
GLuint floorTexture = loadTexture(FileSystem::getPath("resources/textures/metal.png").c_str());
|
||||
#pragma endregion
|
||||
// load textures
|
||||
// -------------
|
||||
unsigned int cubeTexture = loadTexture(FileSystem::getPath("resources/textures/marble.jpg").c_str());
|
||||
unsigned int floorTexture = loadTexture(FileSystem::getPath("resources/textures/metal.png").c_str());
|
||||
|
||||
// Game loop
|
||||
while(!glfwWindowShouldClose(window))
|
||||
// shader configuration
|
||||
// --------------------
|
||||
shader.use();
|
||||
shader.setInt("ourTexture", 0);
|
||||
|
||||
// render loop
|
||||
// -----------
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
// Set frame time
|
||||
GLfloat currentFrame = glfwGetTime();
|
||||
// per-frame time logic
|
||||
// --------------------
|
||||
float currentFrame = glfwGetTime();
|
||||
deltaTime = currentFrame - lastFrame;
|
||||
lastFrame = currentFrame;
|
||||
|
||||
// Check and call events
|
||||
glfwPollEvents();
|
||||
Do_Movement();
|
||||
// input
|
||||
// -----
|
||||
processInput(window);
|
||||
|
||||
// Clear the colorbuffer
|
||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
// render
|
||||
// ------
|
||||
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // don't forget to clear the stencil buffer!
|
||||
|
||||
// Set uniforms
|
||||
shaderSingleColor.Use();
|
||||
// set uniforms
|
||||
shaderSingleColor.use();
|
||||
glm::mat4 model;
|
||||
glm::mat4 view = camera.GetViewMatrix();
|
||||
glm::mat4 projection = glm::perspective(camera.Zoom, (float)screenWidth/(float)screenHeight, 0.1f, 100.0f);
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderSingleColor.Program, "view"), 1, GL_FALSE, glm::value_ptr(view));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderSingleColor.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
|
||||
shader.Use();
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
|
||||
glm::mat4 projection = glm::perspective(camera.Zoom, (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
|
||||
shader.setMat4("view", view);
|
||||
shader.setMat4("projection", projection);
|
||||
|
||||
shader.use();
|
||||
shader.setMat4("view", view);
|
||||
shader.setMat4("projection", projection);
|
||||
|
||||
// Draw floor as normal, we only care about the containers. The floor should NOT fill the stencil buffer so we set its mask to 0x00
|
||||
// draw floor as normal, but don't write the floor to the stencil buffer, we only care about the containers. We set its mask to 0x00 to not write to the stencil buffer.
|
||||
glStencilMask(0x00);
|
||||
// Floor
|
||||
// floor
|
||||
glBindVertexArray(planeVAO);
|
||||
glBindTexture(GL_TEXTURE_2D, floorTexture);
|
||||
model = glm::mat4();
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
glBindVertexArray(0);
|
||||
shader.setMat4("model", glm::mat4());
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
glBindVertexArray(0);
|
||||
|
||||
// == =============
|
||||
// 1st. Render pass, draw objects as normal, filling the stencil buffer
|
||||
// 1st. render pass, draw objects as normal, writing to the stencil buffer
|
||||
// --------------------------------------------------------------------
|
||||
glStencilFunc(GL_ALWAYS, 1, 0xFF);
|
||||
glStencilMask(0xFF);
|
||||
// Cubes
|
||||
glStencilMask(0xFF);
|
||||
// cubes
|
||||
glBindVertexArray(cubeVAO);
|
||||
glBindTexture(GL_TEXTURE_2D, cubeTexture);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, cubeTexture);
|
||||
model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||
shader.setMat4("model", model);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
model = glm::mat4();
|
||||
model = glm::translate(model, glm::vec3(2.0f, 0.0f, 0.0f));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||
shader.setMat4("model", model);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
glBindVertexArray(0);
|
||||
|
||||
// == =============
|
||||
// 2nd. Render pass, now draw slightly scaled versions of the objects, this time disabling stencil writing.
|
||||
// Because stencil buffer is now filled with several 1s. The parts of the buffer that are 1 are now not drawn, thus only drawing
|
||||
// 2nd. render pass: now draw slightly scaled versions of the objects, this time disabling stencil writing.
|
||||
// Because the stencil buffer is now filled with several 1s. The parts of the buffer that are 1 are not drawn, thus only drawing
|
||||
// the objects' size differences, making it look like borders.
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
|
||||
glStencilMask(0x00);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
shaderSingleColor.Use();
|
||||
GLfloat scale = 1.1;
|
||||
// Cubes
|
||||
shaderSingleColor.use();
|
||||
float scale = 1.1;
|
||||
// cubes
|
||||
glBindVertexArray(cubeVAO);
|
||||
glBindTexture(GL_TEXTURE_2D, cubeTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, cubeTexture);
|
||||
model = glm::mat4();
|
||||
model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f));
|
||||
model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f));
|
||||
model = glm::scale(model, glm::vec3(scale, scale, scale));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderSingleColor.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||
shader.setMat4("model", model);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
model = glm::mat4();
|
||||
model = glm::translate(model, glm::vec3(2.0f, 0.0f, 0.0f));
|
||||
model = glm::mat4();
|
||||
model = glm::translate(model, glm::vec3(2.0f, 0.0f, 0.0f));
|
||||
model = glm::scale(model, glm::vec3(scale, scale, scale));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderSingleColor.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||
shader.setMat4("model", model);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
glBindVertexArray(0);
|
||||
glBindVertexArray(0);
|
||||
glStencilMask(0xFF);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
// Swap the buffers
|
||||
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
|
||||
// -------------------------------------------------------------------------------
|
||||
glfwSwapBuffers(window);
|
||||
glfwPollEvents();
|
||||
}
|
||||
|
||||
// optional: de-allocate all resources once they've outlived their purpose:
|
||||
// ------------------------------------------------------------------------
|
||||
glDeleteVertexArrays(1, &cubeVAO);
|
||||
glDeleteVertexArrays(1, &planeVAO);
|
||||
glDeleteBuffers(1, &cubeVBO);
|
||||
glDeleteBuffers(1, &planeVBO);
|
||||
|
||||
glfwTerminate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DrawScene()
|
||||
// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
|
||||
// ---------------------------------------------------------------------------------------------------------
|
||||
void processInput(GLFWwindow *window)
|
||||
{
|
||||
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
|
||||
glfwSetWindowShouldClose(window, true);
|
||||
|
||||
}
|
||||
|
||||
// This function loads a texture from file. Note: texture loading functions like these are usually
|
||||
// managed by a 'Resource Manager' that manages all resources (like textures, models, audio).
|
||||
// For learning purposes we'll just define it as a utility function.
|
||||
GLuint loadTexture(GLchar const * path)
|
||||
{
|
||||
//Generate texture ID and load texture data
|
||||
GLuint textureID;
|
||||
glGenTextures(1, &textureID);
|
||||
int width,height;
|
||||
unsigned char* image = SOIL_load_image(path, &width, &height, 0, SOIL_LOAD_RGB);
|
||||
// Assign texture to ID
|
||||
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
// Parameters
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
SOIL_free_image_data(image);
|
||||
return textureID;
|
||||
|
||||
}
|
||||
|
||||
#pragma region "User input"
|
||||
|
||||
// Moves/alters the camera positions based on user input
|
||||
void Do_Movement()
|
||||
{
|
||||
// Camera controls
|
||||
if(keys[GLFW_KEY_W])
|
||||
float cameraSpeed = 2.5 * deltaTime;
|
||||
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
|
||||
camera.ProcessKeyboard(FORWARD, deltaTime);
|
||||
if(keys[GLFW_KEY_S])
|
||||
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
|
||||
camera.ProcessKeyboard(BACKWARD, deltaTime);
|
||||
if(keys[GLFW_KEY_A])
|
||||
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
|
||||
camera.ProcessKeyboard(LEFT, deltaTime);
|
||||
if(keys[GLFW_KEY_D])
|
||||
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
|
||||
camera.ProcessKeyboard(RIGHT, deltaTime);
|
||||
}
|
||||
|
||||
// Is called whenever a key is pressed/released via GLFW
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
|
||||
// glfw: whenever the window size changed (by OS or user resize) this callback function executes
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
|
||||
{
|
||||
if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
|
||||
glfwSetWindowShouldClose(window, GL_TRUE);
|
||||
|
||||
if(action == GLFW_PRESS)
|
||||
keys[key] = true;
|
||||
else if(action == GLFW_RELEASE)
|
||||
keys[key] = false;
|
||||
// make sure the viewport matches the new window dimensions; note that width and
|
||||
// height will be significantly larger than specified on retina displays.
|
||||
glViewport(0, 0, width, height);
|
||||
}
|
||||
|
||||
|
||||
// glfw: whenever the mouse moves, this callback is called
|
||||
// -------------------------------------------------------
|
||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
|
||||
{
|
||||
if(firstMouse)
|
||||
if (firstMouse)
|
||||
{
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
firstMouse = false;
|
||||
}
|
||||
|
||||
GLfloat xoffset = xpos - lastX;
|
||||
GLfloat yoffset = lastY - ypos;
|
||||
|
||||
float xoffset = xpos - lastX;
|
||||
float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top
|
||||
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
|
||||
camera.ProcessMouseMovement(xoffset, yoffset);
|
||||
}
|
||||
}
|
||||
|
||||
// glfw: whenever the mouse scroll wheel scrolls, this callback is called
|
||||
// ----------------------------------------------------------------------
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
|
||||
{
|
||||
camera.ProcessMouseScroll(yoffset);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
// utility function for loading a 2D texture from file
|
||||
// ---------------------------------------------------
|
||||
unsigned int loadTexture(char const * path)
|
||||
{
|
||||
unsigned int textureID;
|
||||
glGenTextures(1, &textureID);
|
||||
|
||||
int width, height, nrComponents;
|
||||
unsigned char *data = stbi_load(path, &width, &height, &nrComponents, 0);
|
||||
if (data)
|
||||
{
|
||||
GLenum format;
|
||||
if (nrComponents == 1)
|
||||
format = GL_RED;
|
||||
else if (nrComponents == 3)
|
||||
format = GL_RGB;
|
||||
else if (nrComponents == 4)
|
||||
format = GL_RGBA;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
stbi_image_free(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Texture failed to load at path: " << path << std::endl;
|
||||
stbi_image_free(data);
|
||||
}
|
||||
|
||||
return textureID;
|
||||
}
|
||||
@@ -1,311 +1,240 @@
|
||||
// Std. Includes
|
||||
#include <string>
|
||||
|
||||
// GLEW
|
||||
#define GLEW_STATIC
|
||||
#include <GL/glew.h>
|
||||
|
||||
// GLFW
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <stb_image.h>
|
||||
|
||||
// GL includes
|
||||
#include <learnopengl/shader.h>
|
||||
#include <learnopengl/camera.h>
|
||||
|
||||
// GLM Mathemtics
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
// Other Libs
|
||||
#include <SOIL.h>
|
||||
#include <learnopengl/filesystem.h>
|
||||
#include <learnopengl/shader_m.h>
|
||||
#include <learnopengl/camera.h>
|
||||
#include <learnopengl/model.h>
|
||||
|
||||
// Properties
|
||||
GLuint screenWidth = 800, screenHeight = 600;
|
||||
#include <iostream>
|
||||
|
||||
// Function prototypes
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
|
||||
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
|
||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
|
||||
void Do_Movement();
|
||||
GLuint loadTexture(GLchar const * path, GLboolean alpha = false);
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
|
||||
void processInput(GLFWwindow *window);
|
||||
unsigned int loadTexture(const char *path);
|
||||
|
||||
// Camera
|
||||
// settings
|
||||
const unsigned int SCR_WIDTH = 1280;
|
||||
const unsigned int SCR_HEIGHT = 720;
|
||||
|
||||
// camera
|
||||
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
|
||||
bool keys[1024];
|
||||
GLfloat lastX = 400, lastY = 300;
|
||||
float lastX = (float)SCR_WIDTH / 2.0;
|
||||
float lastY = (float)SCR_HEIGHT / 2.0;
|
||||
bool firstMouse = true;
|
||||
|
||||
GLfloat deltaTime = 0.0f;
|
||||
GLfloat lastFrame = 0.0f;
|
||||
// timing
|
||||
float deltaTime = 0.0f;
|
||||
float lastFrame = 0.0f;
|
||||
|
||||
// The MAIN function, from here we start our application and run our Game loop
|
||||
int main()
|
||||
{
|
||||
// Init GLFW
|
||||
// glfw: initialize and configure
|
||||
// ------------------------------
|
||||
glfwInit();
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
|
||||
|
||||
GLFWwindow* window = glfwCreateWindow(screenWidth, screenHeight, "LearnOpenGL", nullptr, nullptr); // Windowed
|
||||
// glfw window creation
|
||||
// --------------------
|
||||
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
// Set the required callback functions
|
||||
glfwSetKeyCallback(window, key_callback);
|
||||
if (window == NULL)
|
||||
{
|
||||
std::cout << "Failed to create GLFW window" << std::endl;
|
||||
glfwTerminate();
|
||||
return -1;
|
||||
}
|
||||
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
|
||||
glfwSetCursorPosCallback(window, mouse_callback);
|
||||
glfwSetScrollCallback(window, scroll_callback);
|
||||
|
||||
// Options
|
||||
// tell GLFW to capture our mouse
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
|
||||
// Initialize GLEW to setup the OpenGL Function pointers
|
||||
glewExperimental = GL_TRUE;
|
||||
glewInit();
|
||||
// glad: load all OpenGL function pointers
|
||||
// ---------------------------------------
|
||||
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
|
||||
{
|
||||
std::cout << "Failed to initialize GLAD" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Define the viewport dimensions
|
||||
glViewport(0, 0, screenWidth, screenHeight);
|
||||
|
||||
// Setup some OpenGL options
|
||||
// configure global opengl state
|
||||
// -----------------------------
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_ALWAYS); // always pass the depth test (same effect as glDisable(GL_DEPTH_TEST))
|
||||
|
||||
// Setup and compile our shaders
|
||||
Shader shader("blending_discard.vs", "blending_discard.frag");
|
||||
// build and compile shaders
|
||||
// -------------------------
|
||||
Shader shader("1.1.depth_testing.vs", "1.1.depth_testing.fs");
|
||||
|
||||
#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,
|
||||
// set up vertex data (and buffer(s)) and configure vertex attributes
|
||||
// ------------------------------------------------------------------
|
||||
float cubeVertices[] = {
|
||||
// positions // texture Coords
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
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, 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, 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,
|
||||
|
||||
-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,
|
||||
float planeVertices[] = {
|
||||
// positions // texture Coords (note we set these higher than 1 (together with GL_REPEAT as texture wrapping mode). this will cause the floor texture to repeat)
|
||||
5.0f, -0.5f, 5.0f, 2.0f, 0.0f,
|
||||
-5.0f, -0.5f, 5.0f, 0.0f, 0.0f,
|
||||
-5.0f, -0.5f, -5.0f, 0.0f, 2.0f,
|
||||
|
||||
5.0f, -0.5f, 5.0f, 2.0f, 0.0f,
|
||||
-5.0f, -0.5f, -5.0f, 0.0f, 2.0f,
|
||||
5.0f, -0.5f, -5.0f, 2.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;
|
||||
// cube VAO
|
||||
unsigned int cubeVAO, cubeVBO;
|
||||
glGenVertexArrays(1, &cubeVAO);
|
||||
glGenBuffers(1, &cubeVBO);
|
||||
glBindVertexArray(cubeVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), &cubeVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
|
||||
glBindVertexArray(0);
|
||||
// Setup plane VAO
|
||||
GLuint planeVAO, planeVBO;
|
||||
// plane VAO
|
||||
unsigned int planeVAO, planeVBO;
|
||||
glGenVertexArrays(1, &planeVAO);
|
||||
glGenBuffers(1, &planeVBO);
|
||||
glBindVertexArray(planeVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, planeVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(planeVertices), &planeVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
|
||||
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)));
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
|
||||
glBindVertexArray(0);
|
||||
|
||||
// Load textures
|
||||
GLuint cubeTexture = loadTexture(FileSystem::getPath("resources/textures/marble.jpg").c_str());
|
||||
GLuint floorTexture = loadTexture(FileSystem::getPath("resources/textures/metal.png").c_str());
|
||||
GLuint transparentTexture = loadTexture(FileSystem::getPath("resources/textures/grass.png").c_str(), true);
|
||||
#pragma endregion
|
||||
// load textures
|
||||
// -------------
|
||||
unsigned int cubeTexture = loadTexture(FileSystem::getPath("resources/textures/marble.jpg").c_str());
|
||||
unsigned int floorTexture = loadTexture(FileSystem::getPath("resources/textures/metal.png").c_str());
|
||||
|
||||
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));
|
||||
// shader configuration
|
||||
// --------------------
|
||||
shader.use();
|
||||
shader.setInt("ourTexture", 0);
|
||||
|
||||
// Game loop
|
||||
// render loop
|
||||
// -----------
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
// Set frame time
|
||||
GLfloat currentFrame = glfwGetTime();
|
||||
// per-frame time logic
|
||||
// --------------------
|
||||
float currentFrame = glfwGetTime();
|
||||
deltaTime = currentFrame - lastFrame;
|
||||
lastFrame = currentFrame;
|
||||
|
||||
// Check and call events
|
||||
glfwPollEvents();
|
||||
Do_Movement();
|
||||
// input
|
||||
// -----
|
||||
processInput(window);
|
||||
|
||||
// Clear the colorbuffer
|
||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
||||
// render
|
||||
// ------
|
||||
glClearColor(0.2f, 0.3f, 0.3f, 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
|
||||
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
|
||||
// -------------------------------------------------------------------------------
|
||||
glfwSwapBuffers(window);
|
||||
glfwPollEvents();
|
||||
}
|
||||
|
||||
// optional: de-allocate all resources once they've outlived their purpose:
|
||||
// ------------------------------------------------------------------------
|
||||
glDeleteVertexArrays(1, &cubeVAO);
|
||||
glDeleteVertexArrays(1, &planeVAO);
|
||||
glDeleteBuffers(1, &cubeVBO);
|
||||
glDeleteBuffers(1, &planeVBO);
|
||||
|
||||
glfwTerminate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This function loads a texture from file. Note: texture loading functions like these are usually
|
||||
// managed by a 'Resource Manager' that manages all resources (like textures, models, audio).
|
||||
// For learning purposes we'll just define it as a utility function.
|
||||
GLuint loadTexture(GLchar const * path, GLboolean alpha)
|
||||
// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
|
||||
// ---------------------------------------------------------------------------------------------------------
|
||||
void processInput(GLFWwindow *window)
|
||||
{
|
||||
//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);
|
||||
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
|
||||
glfwSetWindowShouldClose(window, true);
|
||||
|
||||
// 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])
|
||||
float cameraSpeed = 2.5 * deltaTime;
|
||||
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
|
||||
camera.ProcessKeyboard(FORWARD, deltaTime);
|
||||
if (keys[GLFW_KEY_S])
|
||||
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
|
||||
camera.ProcessKeyboard(BACKWARD, deltaTime);
|
||||
if (keys[GLFW_KEY_A])
|
||||
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
|
||||
camera.ProcessKeyboard(LEFT, deltaTime);
|
||||
if (keys[GLFW_KEY_D])
|
||||
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
|
||||
camera.ProcessKeyboard(RIGHT, deltaTime);
|
||||
}
|
||||
|
||||
// Is called whenever a key is pressed/released via GLFW
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
|
||||
// glfw: whenever the window size changed (by OS or user resize) this callback function executes
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
|
||||
{
|
||||
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
|
||||
glfwSetWindowShouldClose(window, GL_TRUE);
|
||||
if (key >= 0 && key < 1024)
|
||||
{
|
||||
if (action == GLFW_PRESS)
|
||||
keys[key] = true;
|
||||
else if (action == GLFW_RELEASE)
|
||||
keys[key] = false;
|
||||
}
|
||||
// make sure the viewport matches the new window dimensions; note that width and
|
||||
// height will be significantly larger than specified on retina displays.
|
||||
glViewport(0, 0, width, height);
|
||||
}
|
||||
|
||||
|
||||
// glfw: whenever the mouse moves, this callback is called
|
||||
// -------------------------------------------------------
|
||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
|
||||
{
|
||||
if (firstMouse)
|
||||
@@ -315,8 +244,8 @@ void mouse_callback(GLFWwindow* window, double xpos, double ypos)
|
||||
firstMouse = false;
|
||||
}
|
||||
|
||||
GLfloat xoffset = xpos - lastX;
|
||||
GLfloat yoffset = lastY - ypos;
|
||||
float xoffset = xpos - lastX;
|
||||
float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top
|
||||
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
@@ -324,9 +253,48 @@ void mouse_callback(GLFWwindow* window, double xpos, double ypos)
|
||||
camera.ProcessMouseMovement(xoffset, yoffset);
|
||||
}
|
||||
|
||||
// glfw: whenever the mouse scroll wheel scrolls, this callback is called
|
||||
// ----------------------------------------------------------------------
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
|
||||
{
|
||||
camera.ProcessMouseScroll(yoffset);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
// utility function for loading a 2D texture from file
|
||||
// ---------------------------------------------------
|
||||
unsigned int loadTexture(char const * path)
|
||||
{
|
||||
unsigned int textureID;
|
||||
glGenTextures(1, &textureID);
|
||||
|
||||
int width, height, nrComponents;
|
||||
unsigned char *data = stbi_load(path, &width, &height, &nrComponents, 0);
|
||||
if (data)
|
||||
{
|
||||
GLenum format;
|
||||
if (nrComponents == 1)
|
||||
format = GL_RED;
|
||||
else if (nrComponents == 3)
|
||||
format = GL_RGB;
|
||||
else if (nrComponents == 4)
|
||||
format = GL_RGBA;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
stbi_image_free(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Texture failed to load at path: " << path << std::endl;
|
||||
stbi_image_free(data);
|
||||
}
|
||||
|
||||
return textureID;
|
||||
}
|
||||
@@ -1,323 +1,240 @@
|
||||
// Std. Includes
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
// GLEW
|
||||
#define GLEW_STATIC
|
||||
#include <GL/glew.h>
|
||||
|
||||
// GLFW
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <stb_image.h>
|
||||
|
||||
// GL includes
|
||||
#include <learnopengl/shader.h>
|
||||
#include <learnopengl/camera.h>
|
||||
|
||||
// GLM Mathemtics
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
// Other Libs
|
||||
#include <SOIL.h>
|
||||
#include <learnopengl/filesystem.h>
|
||||
#include <learnopengl/shader_m.h>
|
||||
#include <learnopengl/camera.h>
|
||||
#include <learnopengl/model.h>
|
||||
|
||||
// Properties
|
||||
GLuint screenWidth = 800, screenHeight = 600;
|
||||
#include <iostream>
|
||||
|
||||
// Function prototypes
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
|
||||
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
|
||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
|
||||
void Do_Movement();
|
||||
GLuint loadTexture(GLchar const * path, GLboolean alpha = false);
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
|
||||
void processInput(GLFWwindow *window);
|
||||
unsigned int loadTexture(const char *path);
|
||||
|
||||
// Camera
|
||||
// settings
|
||||
const unsigned int SCR_WIDTH = 1280;
|
||||
const unsigned int SCR_HEIGHT = 720;
|
||||
|
||||
// camera
|
||||
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
|
||||
bool keys[1024];
|
||||
GLfloat lastX = 400, lastY = 300;
|
||||
float lastX = (float)SCR_WIDTH / 2.0;
|
||||
float lastY = (float)SCR_HEIGHT / 2.0;
|
||||
bool firstMouse = true;
|
||||
|
||||
GLfloat deltaTime = 0.0f;
|
||||
GLfloat lastFrame = 0.0f;
|
||||
// timing
|
||||
float deltaTime = 0.0f;
|
||||
float lastFrame = 0.0f;
|
||||
|
||||
// The MAIN function, from here we start our application and run our Game loop
|
||||
int main()
|
||||
{
|
||||
// Init GLFW
|
||||
// glfw: initialize and configure
|
||||
// ------------------------------
|
||||
glfwInit();
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
|
||||
|
||||
GLFWwindow* window = glfwCreateWindow(screenWidth, screenHeight, "LearnOpenGL", nullptr, nullptr); // Windowed
|
||||
// glfw window creation
|
||||
// --------------------
|
||||
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
// Set the required callback functions
|
||||
glfwSetKeyCallback(window, key_callback);
|
||||
if (window == NULL)
|
||||
{
|
||||
std::cout << "Failed to create GLFW window" << std::endl;
|
||||
glfwTerminate();
|
||||
return -1;
|
||||
}
|
||||
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
|
||||
glfwSetCursorPosCallback(window, mouse_callback);
|
||||
glfwSetScrollCallback(window, scroll_callback);
|
||||
|
||||
// Options
|
||||
// tell GLFW to capture our mouse
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
|
||||
// Initialize GLEW to setup the OpenGL Function pointers
|
||||
glewExperimental = GL_TRUE;
|
||||
glewInit();
|
||||
// glad: load all OpenGL function pointers
|
||||
// ---------------------------------------
|
||||
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
|
||||
{
|
||||
std::cout << "Failed to initialize GLAD" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Define the viewport dimensions
|
||||
glViewport(0, 0, screenWidth, screenHeight);
|
||||
|
||||
// Setup some OpenGL options
|
||||
// configure global opengl state
|
||||
// -----------------------------
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDepthFunc(GL_ALWAYS); // always pass the depth test (same effect as glDisable(GL_DEPTH_TEST))
|
||||
|
||||
// Setup and compile our shaders
|
||||
Shader shader("blending_sorted.vs", "blending_sorted.frag");
|
||||
// build and compile shaders
|
||||
// -------------------------
|
||||
Shader shader("1.1.depth_testing.vs", "1.1.depth_testing.fs");
|
||||
|
||||
#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,
|
||||
// set up vertex data (and buffer(s)) and configure vertex attributes
|
||||
// ------------------------------------------------------------------
|
||||
float cubeVertices[] = {
|
||||
// positions // texture Coords
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
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, 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, 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,
|
||||
|
||||
-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,
|
||||
float planeVertices[] = {
|
||||
// positions // texture Coords (note we set these higher than 1 (together with GL_REPEAT as texture wrapping mode). this will cause the floor texture to repeat)
|
||||
5.0f, -0.5f, 5.0f, 2.0f, 0.0f,
|
||||
-5.0f, -0.5f, 5.0f, 0.0f, 0.0f,
|
||||
-5.0f, -0.5f, -5.0f, 0.0f, 2.0f,
|
||||
|
||||
5.0f, -0.5f, 5.0f, 2.0f, 0.0f,
|
||||
-5.0f, -0.5f, -5.0f, 0.0f, 2.0f,
|
||||
5.0f, -0.5f, -5.0f, 2.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;
|
||||
// cube VAO
|
||||
unsigned int cubeVAO, cubeVBO;
|
||||
glGenVertexArrays(1, &cubeVAO);
|
||||
glGenBuffers(1, &cubeVBO);
|
||||
glBindVertexArray(cubeVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), &cubeVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
|
||||
glBindVertexArray(0);
|
||||
// Setup plane VAO
|
||||
GLuint planeVAO, planeVBO;
|
||||
// plane VAO
|
||||
unsigned int planeVAO, planeVBO;
|
||||
glGenVertexArrays(1, &planeVAO);
|
||||
glGenBuffers(1, &planeVBO);
|
||||
glBindVertexArray(planeVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, planeVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(planeVertices), &planeVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
|
||||
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)));
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
|
||||
glBindVertexArray(0);
|
||||
|
||||
// Load textures
|
||||
GLuint cubeTexture = loadTexture(FileSystem::getPath("resources/textures/marble.jpg").c_str());
|
||||
GLuint floorTexture = loadTexture(FileSystem::getPath("resources/textures/metal.png").c_str());
|
||||
GLuint transparentTexture = loadTexture(FileSystem::getPath("resources/textures/window.png").c_str(), true);
|
||||
#pragma endregion
|
||||
// load textures
|
||||
// -------------
|
||||
unsigned int cubeTexture = loadTexture(FileSystem::getPath("resources/textures/marble.jpg").c_str());
|
||||
unsigned int floorTexture = loadTexture(FileSystem::getPath("resources/textures/metal.png").c_str());
|
||||
|
||||
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));
|
||||
// shader configuration
|
||||
// --------------------
|
||||
shader.use();
|
||||
shader.setInt("ourTexture", 0);
|
||||
|
||||
// Game loop
|
||||
// render loop
|
||||
// -----------
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
// Set frame time
|
||||
GLfloat currentFrame = glfwGetTime();
|
||||
// per-frame time logic
|
||||
// --------------------
|
||||
float currentFrame = glfwGetTime();
|
||||
deltaTime = currentFrame - lastFrame;
|
||||
lastFrame = currentFrame;
|
||||
|
||||
// Check and call events
|
||||
glfwPollEvents();
|
||||
Do_Movement();
|
||||
// input
|
||||
// -----
|
||||
processInput(window);
|
||||
|
||||
// Clear the colorbuffer
|
||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
||||
// render
|
||||
// ------
|
||||
glClearColor(0.2f, 0.3f, 0.3f, 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
|
||||
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
|
||||
// -------------------------------------------------------------------------------
|
||||
glfwSwapBuffers(window);
|
||||
glfwPollEvents();
|
||||
}
|
||||
|
||||
// optional: de-allocate all resources once they've outlived their purpose:
|
||||
// ------------------------------------------------------------------------
|
||||
glDeleteVertexArrays(1, &cubeVAO);
|
||||
glDeleteVertexArrays(1, &planeVAO);
|
||||
glDeleteBuffers(1, &cubeVBO);
|
||||
glDeleteBuffers(1, &planeVBO);
|
||||
|
||||
glfwTerminate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This function loads a texture from file. Note: texture loading functions like these are usually
|
||||
// managed by a 'Resource Manager' that manages all resources (like textures, models, audio).
|
||||
// For learning purposes we'll just define it as a utility function.
|
||||
GLuint loadTexture(GLchar const * path, GLboolean alpha)
|
||||
// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
|
||||
// ---------------------------------------------------------------------------------------------------------
|
||||
void processInput(GLFWwindow *window)
|
||||
{
|
||||
//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);
|
||||
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
|
||||
glfwSetWindowShouldClose(window, true);
|
||||
|
||||
// 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])
|
||||
float cameraSpeed = 2.5 * deltaTime;
|
||||
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
|
||||
camera.ProcessKeyboard(FORWARD, deltaTime);
|
||||
if (keys[GLFW_KEY_S])
|
||||
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
|
||||
camera.ProcessKeyboard(BACKWARD, deltaTime);
|
||||
if (keys[GLFW_KEY_A])
|
||||
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
|
||||
camera.ProcessKeyboard(LEFT, deltaTime);
|
||||
if (keys[GLFW_KEY_D])
|
||||
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
|
||||
camera.ProcessKeyboard(RIGHT, deltaTime);
|
||||
}
|
||||
|
||||
// Is called whenever a key is pressed/released via GLFW
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
|
||||
// glfw: whenever the window size changed (by OS or user resize) this callback function executes
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
|
||||
{
|
||||
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
|
||||
glfwSetWindowShouldClose(window, GL_TRUE);
|
||||
if (key >= 0 && key < 1024)
|
||||
{
|
||||
if (action == GLFW_PRESS)
|
||||
keys[key] = true;
|
||||
else if (action == GLFW_RELEASE)
|
||||
keys[key] = false;
|
||||
}
|
||||
// make sure the viewport matches the new window dimensions; note that width and
|
||||
// height will be significantly larger than specified on retina displays.
|
||||
glViewport(0, 0, width, height);
|
||||
}
|
||||
|
||||
|
||||
// glfw: whenever the mouse moves, this callback is called
|
||||
// -------------------------------------------------------
|
||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
|
||||
{
|
||||
if (firstMouse)
|
||||
@@ -327,8 +244,8 @@ void mouse_callback(GLFWwindow* window, double xpos, double ypos)
|
||||
firstMouse = false;
|
||||
}
|
||||
|
||||
GLfloat xoffset = xpos - lastX;
|
||||
GLfloat yoffset = lastY - ypos;
|
||||
float xoffset = xpos - lastX;
|
||||
float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top
|
||||
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
@@ -336,9 +253,48 @@ void mouse_callback(GLFWwindow* window, double xpos, double ypos)
|
||||
camera.ProcessMouseMovement(xoffset, yoffset);
|
||||
}
|
||||
|
||||
// glfw: whenever the mouse scroll wheel scrolls, this callback is called
|
||||
// ----------------------------------------------------------------------
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
|
||||
{
|
||||
camera.ProcessMouseScroll(yoffset);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
// utility function for loading a 2D texture from file
|
||||
// ---------------------------------------------------
|
||||
unsigned int loadTexture(char const * path)
|
||||
{
|
||||
unsigned int textureID;
|
||||
glGenTextures(1, &textureID);
|
||||
|
||||
int width, height, nrComponents;
|
||||
unsigned char *data = stbi_load(path, &width, &height, &nrComponents, 0);
|
||||
if (data)
|
||||
{
|
||||
GLenum format;
|
||||
if (nrComponents == 1)
|
||||
format = GL_RED;
|
||||
else if (nrComponents == 3)
|
||||
format = GL_RGB;
|
||||
else if (nrComponents == 4)
|
||||
format = GL_RGBA;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
stbi_image_free(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Texture failed to load at path: " << path << std::endl;
|
||||
stbi_image_free(data);
|
||||
}
|
||||
|
||||
return textureID;
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
// Std. Includes
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
using namespace std;
|
||||
|
||||
// GLEW
|
||||
#define GLEW_STATIC
|
||||
@@ -29,7 +31,8 @@ void key_callback(GLFWwindow* window, int key, int scancode, int action, int mod
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
|
||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
|
||||
void Do_Movement();
|
||||
GLuint loadTexture(GLchar const * path);
|
||||
GLuint loadTexture(GLchar const * path, GLboolean alpha = false);
|
||||
GLuint generateAttachmentTexture(GLboolean depth, GLboolean stencil);
|
||||
|
||||
// Camera
|
||||
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
|
||||
@@ -59,7 +62,7 @@ int main()
|
||||
glfwSetScrollCallback(window, scroll_callback);
|
||||
|
||||
// Options
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
|
||||
// Initialize GLEW to setup the OpenGL Function pointers
|
||||
glewExperimental = GL_TRUE;
|
||||
@@ -69,11 +72,11 @@ int main()
|
||||
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))
|
||||
|
||||
glDepthFunc(GL_LESS);
|
||||
|
||||
// Setup and compile our shaders
|
||||
Shader shader("depth_testing.vs", "depth_testing.frag");
|
||||
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)
|
||||
@@ -121,8 +124,8 @@ int main()
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f
|
||||
};
|
||||
GLfloat planeVertices[] = {
|
||||
// Positions // Texture Coords (note we set these higher than 1 that together with GL_REPEAT as texture wrapping mode will cause the floor texture to repeat)
|
||||
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,
|
||||
@@ -131,6 +134,17 @@ int main()
|
||||
-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);
|
||||
@@ -144,23 +158,58 @@ int main()
|
||||
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);
|
||||
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(FileSystem::getPath("resources/textures/marble.jpg").c_str());
|
||||
GLuint cubeTexture = loadTexture(FileSystem::getPath("resources/textures/container.jpg").c_str());
|
||||
GLuint floorTexture = loadTexture(FileSystem::getPath("resources/textures/metal.png").c_str());
|
||||
#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))
|
||||
{
|
||||
@@ -173,20 +222,35 @@ int main()
|
||||
glfwPollEvents();
|
||||
Do_Movement();
|
||||
|
||||
// Clear the colorbuffer
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// 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);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // We're not using stencil buffer so why bother with clearing?
|
||||
|
||||
// Draw objects
|
||||
shader.Use();
|
||||
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); // 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)
|
||||
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);
|
||||
@@ -194,19 +258,33 @@ int main()
|
||||
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));
|
||||
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);
|
||||
glBindVertexArray(0);
|
||||
|
||||
|
||||
// Swap the buffers
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
glDeleteFramebuffers(1, &framebuffer);
|
||||
|
||||
glfwTerminate();
|
||||
return 0;
|
||||
}
|
||||
@@ -214,27 +292,53 @@ int main()
|
||||
// This function loads a texture from file. Note: texture loading functions like these are usually
|
||||
// managed by a 'Resource Manager' that manages all resources (like textures, models, audio).
|
||||
// For learning purposes we'll just define it as a utility function.
|
||||
GLuint loadTexture(GLchar const * path)
|
||||
GLuint loadTexture(GLchar const * 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, SOIL_LOAD_RGB);
|
||||
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, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
|
||||
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, GL_REPEAT );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
|
||||
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"
|
||||
@@ -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);
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 position;
|
||||
layout (location = 1) in vec2 texCoords;
|
||||
layout (location = 1) in vec3 normal;
|
||||
|
||||
out vec2 TexCoords;
|
||||
out vec3 Normal;
|
||||
out vec3 Position;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
@@ -11,5 +12,6 @@ uniform mat4 projection;
|
||||
void main()
|
||||
{
|
||||
gl_Position = projection * view * model * vec4(position, 1.0f);
|
||||
TexCoords = texCoords;
|
||||
}
|
||||
Normal = mat3(transpose(inverse(model))) * normal;
|
||||
Position = vec3(model * vec4(position, 1.0f));
|
||||
}
|
||||
@@ -0,0 +1,377 @@
|
||||
// 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>
|
||||
#include <learnopengl/filesystem.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 const * path);
|
||||
GLuint loadCubemap(std::vector<std::string> 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<std::string> faces;
|
||||
faces.push_back(FileSystem::getPath("resources/textures/skybox/right.jpg"));
|
||||
faces.push_back(FileSystem::getPath("resources/textures/skybox/left.jpg"));
|
||||
faces.push_back(FileSystem::getPath("resources/textures/skybox/top.jpg"));
|
||||
faces.push_back(FileSystem::getPath("resources/textures/skybox/bottom.jpg"));
|
||||
faces.push_back(FileSystem::getPath("resources/textures/skybox/back.jpg"));
|
||||
faces.push_back(FileSystem::getPath("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<std::string> 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].c_str(), &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 const * path)
|
||||
{
|
||||
//Generate texture ID and load texture data
|
||||
GLuint textureID;
|
||||
glGenTextures(1, &textureID);
|
||||
int width, height;
|
||||
unsigned char* image = SOIL_load_image(path, &width, &height, 0, SOIL_LOAD_RGB);
|
||||
// Assign texture to ID
|
||||
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
// Parameters
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
SOIL_free_image_data(image);
|
||||
return textureID;
|
||||
}
|
||||
|
||||
#pragma region "User input"
|
||||
|
||||
// Moves/alters the camera positions based on user input
|
||||
void Do_Movement()
|
||||
{
|
||||
// Camera controls
|
||||
if (keys[GLFW_KEY_W])
|
||||
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,8 @@
|
||||
#version 330 core
|
||||
in vec3 fColor;
|
||||
out vec4 color;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = vec4(fColor, 1.0f);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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,101 @@
|
||||
// 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;
|
||||
|
||||
bool keys[1024];
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
|
||||
|
||||
// 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);
|
||||
|
||||
// Set the required callback functions
|
||||
glfwSetKeyCallback(window, key_callback);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#version 330 core
|
||||
in vec3 fColor;
|
||||
out vec4 color;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = vec4(fColor, 1.0f);
|
||||
}
|
||||
@@ -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,8 @@
|
||||
#version 330 core
|
||||
in vec3 fColor;
|
||||
out vec4 color;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = vec4(fColor, 1.0f);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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,101 @@
|
||||
// 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;
|
||||
|
||||
bool keys[1024];
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
|
||||
|
||||
// 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);
|
||||
|
||||
// Set the required callback functions
|
||||
glfwSetKeyCallback(window, key_callback);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
Reference in New Issue
Block a user