Nove repo opengl-learning
This commit is contained in:
608
lessons/5. Advanced Lighting/6. Parallax Mapping/src/main.cpp
Normal file
608
lessons/5. Advanced Lighting/6. Parallax Mapping/src/main.cpp
Normal file
@@ -0,0 +1,608 @@
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <iostream>
|
||||
#include <stb_image.h>
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <stb_image_write.h>
|
||||
#include <ctime>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include "Shader.h"
|
||||
#include "Camera.h"
|
||||
#include "Framebuffer.h"
|
||||
#include "Model.h"
|
||||
#include "DebugColors.h"
|
||||
#include "config.h" // in cmake build directory (need to run configure.sh first)
|
||||
#if _WIN32
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
#define WINDOW_NAME "6. Parallax Mapping"
|
||||
#define TEXTURES_DIR REPO_ROOT "/textures/"
|
||||
#define MODELS_DIR REPO_ROOT "/models/"
|
||||
#define SHADERS_DIR SOURCE_DIR "/shaders/"
|
||||
#define _IsUnused __attribute__((__unused__)) // linux only
|
||||
|
||||
using namespace std;
|
||||
typedef unsigned int uint;
|
||||
|
||||
// Global Constants
|
||||
// ...
|
||||
// Global Variables
|
||||
GLFWwindow* window;
|
||||
int WINDOW_WIDTH = 800;
|
||||
int WINDOW_HEIGHT = 600;
|
||||
Camera myCamera(glm::vec3(0.0f, 0.0f, 3.0f));
|
||||
float deltaTime = 0.0f;
|
||||
float lastFrame = 0.0f;
|
||||
float lastX = 400;
|
||||
float lastY = 300;
|
||||
bool firstmouse = true;
|
||||
|
||||
/* pointer to Framebuffer object that is used for screenshot */
|
||||
/* if NULL default framebuffer is used */
|
||||
Framebuffer *screenshot_FBO_ptr = NULL;
|
||||
|
||||
uint8_t init(void);
|
||||
void framebuffersize_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 proccessInput(GLFWwindow* window);
|
||||
unsigned int load_texture(const char* path, bool flip = true, bool sRGB = true, GLint wrapS = GL_REPEAT, GLint wrapT = GL_REPEAT);
|
||||
unsigned int load_cubemap(vector<string> faces);
|
||||
void draw_cube(void);
|
||||
void draw_floor(void);
|
||||
void draw_quad(void);
|
||||
void draw_scene(const Shader* shader, bool lightCube);
|
||||
|
||||
Shader* shader = NULL;
|
||||
Shader* quadShader = NULL;
|
||||
Shader* basicShader = NULL;
|
||||
|
||||
glm::vec3 lightPos(0.0f);
|
||||
glm::vec3 lightColor(1.0f, 1.0f, 1.0f);
|
||||
bool cullFaces = false;
|
||||
bool normalMapping = false;
|
||||
bool parallaxMapping = false;
|
||||
GLint polygonMode = GL_FILL;
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
#if _WIN32
|
||||
SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
|
||||
#endif
|
||||
|
||||
if (init() != 0)
|
||||
return -1;
|
||||
|
||||
shader = new Shader(SHADERS_DIR "shader.vert", SHADERS_DIR "shader.frag");
|
||||
quadShader = new Shader(SHADERS_DIR "quadShader.vert", SHADERS_DIR "quadShader.frag");
|
||||
basicShader = new Shader(SHADERS_DIR "basicShader.vert", SHADERS_DIR "basicShader.frag");
|
||||
|
||||
if (!shader->Program || !quadShader->Program || !basicShader->Program)
|
||||
{
|
||||
std::cerr << DC_ERROR " Could not create shader programs!" << std::endl;
|
||||
std::cerr << DC_INFO " Exiting...\n";
|
||||
return -2;
|
||||
}
|
||||
|
||||
MSFramebuffer fbOffScreen(WINDOW_WIDTH, WINDOW_HEIGHT, 4);
|
||||
if (fbOffScreen.ID == 0)
|
||||
return -1;
|
||||
screenshot_FBO_ptr = &fbOffScreen;
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
cullFaces = false;
|
||||
//glEnable(GL_MULTISAMPLE);
|
||||
/* ------------------ MAIN loop ------------------ */
|
||||
while (!glfwWindowShouldClose(window)) {
|
||||
float currentFrame = (float)glfwGetTime();
|
||||
deltaTime = currentFrame - lastFrame; // cas jak dlouho trval posledni frame
|
||||
lastFrame = currentFrame; // cas kdy zacal tento frame
|
||||
// input ...
|
||||
proccessInput(window);
|
||||
// rendering commands here ...
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
if (cullFaces)
|
||||
glEnable(GL_CULL_FACE);
|
||||
|
||||
// 1. Render pass: render to fbOffscreen framebuffer
|
||||
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, polygonMode);
|
||||
fbOffScreen.Use();
|
||||
fbOffScreen.clearBuffers(0.006f, 0.006f, 0.006f, 1.0f);
|
||||
|
||||
shader->Use();
|
||||
draw_scene(shader, false);
|
||||
|
||||
// 2. Render pass: render quad on screen
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
quadShader->Use();
|
||||
quadShader->setInt("texture0", 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, fbOffScreen.getColorBuffer());
|
||||
draw_quad();
|
||||
|
||||
//glDisable(GL_FRAMEBUFFER_SRGB);
|
||||
|
||||
// check and calls events and swap the buffers
|
||||
glfwSwapBuffers(window);
|
||||
glfwPollEvents();
|
||||
|
||||
}
|
||||
|
||||
glfwTerminate();
|
||||
|
||||
delete(shader);
|
||||
delete(quadShader);
|
||||
delete(basicShader);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t init(void) {
|
||||
// init of glfw window
|
||||
glfwInit();
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_NAME, NULL, NULL);
|
||||
if (window == NULL) {
|
||||
cerr << DC_ERROR " Failed to create glfw window" << endl;
|
||||
glfwTerminate();
|
||||
return 1;
|
||||
}
|
||||
glfwMakeContextCurrent(window);
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
|
||||
// init of GLAD
|
||||
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
|
||||
cerr << DC_ERROR " Failed to initialize GLAD" << endl;
|
||||
}
|
||||
|
||||
glfwSetFramebufferSizeCallback(window, framebuffersize_callback);
|
||||
glfwSetCursorPosCallback(window, mouse_callback);
|
||||
glfwSetScrollCallback(window, scroll_callback);
|
||||
return 0;
|
||||
}
|
||||
void framebuffersize_callback(GLFWwindow* window, int width, int height)
|
||||
{
|
||||
glViewport(0, 0, width, height);
|
||||
WINDOW_HEIGHT = height;
|
||||
WINDOW_WIDTH = width;
|
||||
}
|
||||
void proccessInput(GLFWwindow* window)
|
||||
{
|
||||
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) // Escape
|
||||
glfwSetWindowShouldClose(window, true);
|
||||
if (glfwGetKey(window, GLFW_KEY_F1) == GLFW_PRESS) // F1
|
||||
{
|
||||
if (polygonMode != GL_FILL)
|
||||
{
|
||||
std::cout << DC_INFO << " Polygon mode: " << DC_YELLOW << "fill" << DC_DEFAULT << "\n";
|
||||
polygonMode = GL_FILL;
|
||||
}
|
||||
}
|
||||
else if (glfwGetKey(window, GLFW_KEY_F2) == GLFW_PRESS) // F2
|
||||
{
|
||||
if (polygonMode != GL_LINE)
|
||||
{
|
||||
std::cout << DC_INFO << " Polygon mode: " << DC_YELLOW << "line" << DC_DEFAULT << "\n";
|
||||
polygonMode = GL_LINE;
|
||||
}
|
||||
}
|
||||
if (glfwGetKey(window, GLFW_KEY_F3) == GLFW_PRESS) // F3
|
||||
{
|
||||
std::string path;
|
||||
if (screenshot_FBO_ptr == NULL)
|
||||
path = Framebuffer::screenshot_defaultFBO(WINDOW_WIDTH, WINDOW_HEIGHT);
|
||||
else
|
||||
path = screenshot_FBO_ptr->screenshot();
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
std::cout << DC_INFO << " Screenshot saved to '" DC_MAGNETA << path << DC_DEFAULT "'\n";
|
||||
}
|
||||
//if (glfwGetKey(window, GLFW_KEY_F4) == GLFW_PRESS); // F4
|
||||
if (glfwGetKey(window, GLFW_KEY_1) == GLFW_PRESS) // 1
|
||||
{
|
||||
if (!normalMapping) {
|
||||
std::cout << DC_INFO << " Normal mapping: " << DC_GREEN << "on" << DC_DEFAULT << "\n";
|
||||
normalMapping = true;
|
||||
}
|
||||
}
|
||||
else if (glfwGetKey(window, GLFW_KEY_2) == GLFW_PRESS) // 2
|
||||
{
|
||||
if (normalMapping) {
|
||||
std::cout << DC_INFO << " Normal mapping: " << DC_RED << "off" << DC_DEFAULT << "\n";
|
||||
normalMapping = false;
|
||||
}
|
||||
}
|
||||
if (glfwGetKey(window, GLFW_KEY_3) == GLFW_PRESS)
|
||||
{
|
||||
if (!parallaxMapping) {
|
||||
std::cout << DC_INFO << " Parallax mapping: " << DC_GREEN << "on" << DC_DEFAULT << "\n";
|
||||
parallaxMapping = true;
|
||||
}
|
||||
}
|
||||
else if (glfwGetKey(window, GLFW_KEY_4) == GLFW_PRESS)
|
||||
{
|
||||
if (parallaxMapping) {
|
||||
std::cout << DC_INFO << " Parallax mapping: " << DC_RED << "off" << DC_DEFAULT << "\n";
|
||||
parallaxMapping = false;
|
||||
}
|
||||
}
|
||||
/* -------------------- Movement -------------------- */
|
||||
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) // w
|
||||
myCamera.ProccessKeyboard(CAM_FORWARD, deltaTime);
|
||||
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) // S
|
||||
myCamera.ProccessKeyboard(CAM_BACKWARD, deltaTime);
|
||||
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) // D
|
||||
myCamera.ProccessKeyboard(CAM_RIGHT, deltaTime);
|
||||
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) // A
|
||||
myCamera.ProccessKeyboard(CAM_LEFT, deltaTime);
|
||||
if (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) // Left-shift
|
||||
myCamera.ProccessKeyboard(CAM_DOWN, deltaTime);
|
||||
if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS) // Space
|
||||
myCamera.ProccessKeyboard(CAM_UP, deltaTime);
|
||||
|
||||
}
|
||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
|
||||
{
|
||||
if (firstmouse) {
|
||||
lastX = (float)xpos;
|
||||
lastY = (float)ypos;
|
||||
firstmouse = false;
|
||||
}
|
||||
|
||||
float xoffset = (float)xpos - lastX;
|
||||
float yoffset = lastY - (float)ypos;
|
||||
lastX = (float)xpos;
|
||||
lastY = (float)ypos;
|
||||
|
||||
myCamera.ProccessMouse(xoffset, yoffset);
|
||||
}
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
|
||||
{
|
||||
myCamera.ProccessScroll((float)yoffset);
|
||||
}
|
||||
unsigned int load_texture(const char* path, bool flip, bool sRGB, GLint wrapS, GLint wrapT)
|
||||
{
|
||||
unsigned int texture = 0;
|
||||
int width, height, nrChannels, format, intFormat;
|
||||
stbi_set_flip_vertically_on_load(flip);
|
||||
unsigned char* data = stbi_load(path, &width, &height, &nrChannels, 0); // load image to the array of bytes (char = 1 byte)
|
||||
|
||||
switch (nrChannels)
|
||||
{
|
||||
case 4: format = GL_RGBA;
|
||||
if (sRGB) intFormat = GL_SRGB_ALPHA;
|
||||
else intFormat = GL_RGBA;
|
||||
break;
|
||||
case 3: format = GL_RGB;
|
||||
if (sRGB) intFormat = GL_SRGB;
|
||||
else intFormat = GL_RGB;
|
||||
break;
|
||||
case 2: format = intFormat = GL_RED; break;
|
||||
default: format = intFormat = GL_RGB; break;
|
||||
}
|
||||
|
||||
if (data) // data != NULL
|
||||
{
|
||||
glGenTextures(1, &texture);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, intFormat, width, height, 0, format, GL_UNSIGNED_BYTE, data); // generates texture
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
}
|
||||
else {
|
||||
cerr << DC_WARNING " Could not load texture '" << path << "'\n";
|
||||
}
|
||||
stbi_image_free(data);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
return texture;
|
||||
}
|
||||
unsigned int load_cubemap(vector<string> faces)
|
||||
{
|
||||
unsigned int textureID;
|
||||
glGenTextures(1, &textureID);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, textureID);
|
||||
|
||||
int width, height, nrChannels, format;
|
||||
for (size_t i = 0; i < faces.size(); i++)
|
||||
{
|
||||
unsigned char* data = stbi_load(faces[i].c_str(), &width, &height, &nrChannels, 0);
|
||||
switch (nrChannels)
|
||||
{
|
||||
case 4: format = GL_RGBA; break;
|
||||
case 3: format = GL_RGB; break;
|
||||
case 2: format = GL_RED; break;
|
||||
default: format = GL_RGB; break;
|
||||
}
|
||||
if (data)
|
||||
{
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + static_cast<int>(i), 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
|
||||
}
|
||||
else {
|
||||
std::cerr << DC_INFO " Failed to load cubemap texture at " << faces[i] << std::endl;
|
||||
}
|
||||
stbi_image_free(data);
|
||||
};
|
||||
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);
|
||||
|
||||
return textureID;
|
||||
}
|
||||
|
||||
unsigned int cubeVAO = 0, cubeVBO = 0;
|
||||
void draw_cube(void)
|
||||
{
|
||||
if (cubeVBO == 0 || cubeVAO == 0)
|
||||
{
|
||||
float cubeVertices[] = {
|
||||
// back face
|
||||
-1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, // bottom-left
|
||||
1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, // top-right
|
||||
1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, // bottom-right
|
||||
1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, // top-right
|
||||
-1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, // bottom-left
|
||||
-1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, // top-left
|
||||
// front face
|
||||
-1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom-left
|
||||
1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, // bottom-right
|
||||
1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // top-right
|
||||
1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // top-right
|
||||
-1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, // top-left
|
||||
-1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom-left
|
||||
// left face
|
||||
-1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-right
|
||||
-1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top-left
|
||||
-1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-left
|
||||
-1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-left
|
||||
-1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom-right
|
||||
-1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-right
|
||||
// right face
|
||||
1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-left
|
||||
1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-right
|
||||
1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top-right
|
||||
1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-right
|
||||
1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-left
|
||||
1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom-left
|
||||
// bottom face
|
||||
-1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, // top-right
|
||||
1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, // top-left
|
||||
1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom-left
|
||||
1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom-left
|
||||
-1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, // bottom-right
|
||||
-1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, // top-right
|
||||
// top face
|
||||
-1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // top-left
|
||||
1.0f, 1.0f , 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom-right
|
||||
1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, // top-right
|
||||
1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom-right
|
||||
-1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // top-left
|
||||
-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f // bottom-left
|
||||
};
|
||||
|
||||
glGenVertexArrays(1, &cubeVAO);
|
||||
glGenBuffers(1, &cubeVBO);
|
||||
glBindVertexArray(cubeVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), cubeVertices, GL_STATIC_DRAW);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (const void*)0);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (const void*)(6 * sizeof(float)));
|
||||
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (const void*)(3 * sizeof(float)));
|
||||
for (int i = 0; i < 3; i++)
|
||||
glEnableVertexAttribArray(i);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
glBindVertexArray(cubeVAO);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
unsigned int floorVAO = 0, floorVBO = 0;
|
||||
void draw_floor(void)
|
||||
{
|
||||
if (floorVAO == 0 || floorVBO == 0)
|
||||
{
|
||||
float floorVertices[] = {
|
||||
// positions // normals // texcoords
|
||||
25.0f, -0.5f, 25.0f, 0.0f, 1.0f, 0.0f, 25.0f, 0.0f,
|
||||
-25.0f, -0.5f, 25.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
|
||||
-25.0f, -0.5f, -25.0f, 0.0f, 1.0f, 0.0f, 0.0f, 25.0f,
|
||||
|
||||
25.0f, -0.5f, 25.0f, 0.0f, 1.0f, 0.0f, 25.0f, 0.0f,
|
||||
-25.0f, -0.5f, -25.0f, 0.0f, 1.0f, 0.0f, 0.0f, 25.0f,
|
||||
25.0f, -0.5f, -25.0f, 0.0f, 1.0f, 0.0f, 25.0f, 25.0f
|
||||
};
|
||||
|
||||
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); // aPos
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (const void*)0);
|
||||
glEnableVertexAttribArray(1); // aTexCoord
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (const void*)(6 * sizeof(float)));
|
||||
glEnableVertexAttribArray(2); // aNormal
|
||||
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (const void*)(3 * sizeof(float)));
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
glBindVertexArray(floorVAO);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
unsigned int quadVAO = 0, quadVBO = 0;
|
||||
void draw_quad(void)
|
||||
{
|
||||
if (quadVAO == 0 || quadVBO == 0)
|
||||
{
|
||||
//Tangent space calculations
|
||||
glm::vec3 pos1(-1.0f, 1.0f, 0.0f);
|
||||
glm::vec3 pos2(-1.0f, -1.0f, 0.0f);
|
||||
glm::vec3 pos3(1.0f, -1.0f, 0.0f);
|
||||
glm::vec3 pos4(1.0f, 1.0f, 0.0f);
|
||||
// texture coordinates
|
||||
glm::vec2 uv1(0.0f, 1.0f);
|
||||
glm::vec2 uv2(0.0f, 0.0f);
|
||||
glm::vec2 uv3(1.0f, 0.0f);
|
||||
glm::vec2 uv4(1.0f, 1.0f);
|
||||
// normal vector
|
||||
glm::vec3 nm(0.0f, 0.0f, 1.0f);
|
||||
|
||||
// calculate tangent/bitangent vectors of both triangles
|
||||
glm::vec3 tangent1, bitangent1;
|
||||
glm::vec3 tangent2, bitangent2;
|
||||
// triangle 1
|
||||
// ----------
|
||||
glm::vec3 edge1 = pos2 - pos1;
|
||||
glm::vec3 edge2 = pos3 - pos1;
|
||||
glm::vec2 deltaUV1 = uv2 - uv1;
|
||||
glm::vec2 deltaUV2 = uv3 - uv1;
|
||||
|
||||
float f = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV2.x * deltaUV1.y);
|
||||
|
||||
tangent1.x = f * (deltaUV2.y * edge1.x - deltaUV1.y * edge2.x);
|
||||
tangent1.y = f * (deltaUV2.y * edge1.y - deltaUV1.y * edge2.y);
|
||||
tangent1.z = f * (deltaUV2.y * edge1.z - deltaUV1.y * edge2.z);
|
||||
|
||||
bitangent1.x = f * (-deltaUV2.x * edge1.x + deltaUV1.x * edge2.x);
|
||||
bitangent1.y = f * (-deltaUV2.x * edge1.y + deltaUV1.x * edge2.y);
|
||||
bitangent1.z = f * (-deltaUV2.x * edge1.z + deltaUV1.x * edge2.z);
|
||||
|
||||
// triangle 2
|
||||
// ----------
|
||||
edge1 = pos3 - pos1;
|
||||
edge2 = pos4 - pos1;
|
||||
deltaUV1 = uv3 - uv1;
|
||||
deltaUV2 = uv4 - uv1;
|
||||
|
||||
f = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV2.x * deltaUV1.y);
|
||||
|
||||
tangent2.x = f * (deltaUV2.y * edge1.x - deltaUV1.y * edge2.x);
|
||||
tangent2.y = f * (deltaUV2.y * edge1.y - deltaUV1.y * edge2.y);
|
||||
tangent2.z = f * (deltaUV2.y * edge1.z - deltaUV1.y * edge2.z);
|
||||
|
||||
|
||||
bitangent2.x = f * (-deltaUV2.x * edge1.x + deltaUV1.x * edge2.x);
|
||||
bitangent2.y = f * (-deltaUV2.x * edge1.y + deltaUV1.x * edge2.y);
|
||||
bitangent2.z = f * (-deltaUV2.x * edge1.z + deltaUV1.x * edge2.z);
|
||||
|
||||
float quadVertices[] = {
|
||||
// positions // normal // texcoords // tangent // bitangent
|
||||
pos1.x, pos1.y, pos1.z, nm.x, nm.y, nm.z, uv1.x, uv1.y, tangent1.x, tangent1.y, tangent1.z, bitangent1.x, bitangent1.y, bitangent1.z,
|
||||
pos2.x, pos2.y, pos2.z, nm.x, nm.y, nm.z, uv2.x, uv2.y, tangent1.x, tangent1.y, tangent1.z, bitangent1.x, bitangent1.y, bitangent1.z,
|
||||
pos3.x, pos3.y, pos3.z, nm.x, nm.y, nm.z, uv3.x, uv3.y, tangent1.x, tangent1.y, tangent1.z, bitangent1.x, bitangent1.y, bitangent1.z,
|
||||
|
||||
pos1.x, pos1.y, pos1.z, nm.x, nm.y, nm.z, uv1.x, uv1.y, tangent2.x, tangent2.y, tangent2.z, bitangent2.x, bitangent2.y, bitangent2.z,
|
||||
pos3.x, pos3.y, pos3.z, nm.x, nm.y, nm.z, uv3.x, uv3.y, tangent2.x, tangent2.y, tangent2.z, bitangent2.x, bitangent2.y, bitangent2.z,
|
||||
pos4.x, pos4.y, pos4.z, nm.x, nm.y, nm.z, uv4.x, uv4.y, tangent2.x, tangent2.y, tangent2.z, bitangent2.x, bitangent2.y, bitangent2.z
|
||||
};
|
||||
// configure plane VAO
|
||||
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); // Vertex positions
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 14 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(1); // Vertex normals
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 14 * sizeof(float), (void*)(3 * sizeof(float)));
|
||||
glEnableVertexAttribArray(2); // Vertex texture coordinates
|
||||
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 14 * sizeof(float), (void*)(6 * sizeof(float)));
|
||||
glEnableVertexAttribArray(3); // Vertex tangent
|
||||
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 14 * sizeof(float), (void*)(8 * sizeof(float)));
|
||||
glEnableVertexAttribArray(4); // Vertex bitangent
|
||||
glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, 14 * sizeof(float), (void*)(11 * sizeof(float)));
|
||||
}
|
||||
glBindVertexArray(quadVAO);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
unsigned int brick_texture = 0, brick_texture_normal = 0, brick_texture_height = 0;
|
||||
void draw_scene(const Shader* shader, bool lightCube)
|
||||
{
|
||||
if (brick_texture == 0) // flipV sRGB
|
||||
brick_texture = load_texture(TEXTURES_DIR "brickwall2/brickwall2.jpg", true, true);
|
||||
if (brick_texture_normal == 0)
|
||||
brick_texture_normal = load_texture(TEXTURES_DIR "brickwall2/brickwall2_normal.jpg", true, false);
|
||||
if (brick_texture_height == 0)
|
||||
brick_texture_height = load_texture(TEXTURES_DIR "brickwall2/brickwall2_height.jpg", true, false);
|
||||
if (!brick_texture || !brick_texture_normal || !brick_texture_height)
|
||||
{
|
||||
std::cout << DC_ERROR " Could not load needed textures. Exiting..." DC_DEFAULT << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
glm::mat4 model(1.0f);
|
||||
glm::mat4 view = myCamera.getViewMatrix();
|
||||
glm::mat4 projection = glm::perspective(glm::radians(myCamera.FOV),
|
||||
WINDOW_WIDTH / (float)WINDOW_HEIGHT, 0.1f, 300.0f);
|
||||
|
||||
shader->Use();
|
||||
shader->setMat4("projection", projection);
|
||||
shader->setMat4("view", view);
|
||||
|
||||
// Lighting
|
||||
float tim = (float)glfwGetTime();
|
||||
lightPos = glm::vec3(0.0f, 0.0f, 1.5f);
|
||||
shader->setVec3("light.position", lightPos);
|
||||
shader->setVec3("viewPos", myCamera.Position);
|
||||
shader->setVec3("light.ambient", glm::vec3(0.005f));
|
||||
shader->setVec3("light.diffuse", 0.9f * lightColor);
|
||||
shader->setVec3("light.specular", 1.0f * lightColor);
|
||||
|
||||
shader->setInt("material.texture_diffuse0", 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, brick_texture);
|
||||
shader->setInt("material.texture_normal0", 1);
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, brick_texture_normal);
|
||||
shader->setInt("material.texture_height0", 2);
|
||||
glActiveTexture(GL_TEXTURE2);
|
||||
glBindTexture(GL_TEXTURE_2D, brick_texture_height);
|
||||
|
||||
if (cullFaces)
|
||||
glEnable(GL_CULL_FACE);
|
||||
|
||||
model = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -0.5f));
|
||||
model = glm::scale(model, glm::vec3(1.0f));
|
||||
//model = glm::rotate(model, tim * 0.5f, glm::vec3(0.0f, 0.0f, 1.0f));
|
||||
shader->setMat4("model", model);
|
||||
shader->setMat3("normalMatrix", glm::transpose(glm::inverse(model)));
|
||||
shader->setBool("normalMapping", normalMapping);
|
||||
shader->setBool("parallaxMapping", parallaxMapping);
|
||||
shader->setFloat("height_scale", 0.15f);
|
||||
draw_quad();
|
||||
|
||||
if (lightCube)
|
||||
{
|
||||
basicShader->Use();
|
||||
model = glm::translate(glm::mat4(1.0f), lightPos);
|
||||
model = glm::scale(model, glm::vec3(0.05f));
|
||||
basicShader->setMat4("PVM", projection * view * model);
|
||||
basicShader->setVec3("Color", lightColor);
|
||||
draw_cube();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user