Nove repo opengl-learning

This commit is contained in:
TheRetikGM
2021-02-12 15:43:03 +01:00
commit 63e3c0bc8b
1046 changed files with 358397 additions and 0 deletions

View 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();
}
}