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,19 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/../../../include",
"${workspaceFolder}/src/include",
"${workspaceFolder}/build"
],
"defines": [],
"compilerPath": "/bin/gcc",
"cStandard": "c11",
"cppStandard": "c++14",
"intelliSenseMode": "gcc-x64",
"configurationProvider": "ms-vscode.cmake-tools"
}
],
"version": 4
}

View File

@@ -0,0 +1,95 @@
{
"files.associations": {
"ctime": "cpp",
"chrono": "cpp",
"condition_variable": "cpp",
"mutex": "cpp",
"thread": "cpp",
"cctype": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"csignal": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"array": "cpp",
"atomic": "cpp",
"hash_map": "cpp",
"strstream": "cpp",
"bit": "cpp",
"*.tcc": "cpp",
"bitset": "cpp",
"cinttypes": "cpp",
"codecvt": "cpp",
"compare": "cpp",
"complex": "cpp",
"concepts": "cpp",
"cstdint": "cpp",
"deque": "cpp",
"list": "cpp",
"map": "cpp",
"set": "cpp",
"unordered_map": "cpp",
"unordered_set": "cpp",
"vector": "cpp",
"exception": "cpp",
"algorithm": "cpp",
"functional": "cpp",
"iterator": "cpp",
"memory": "cpp",
"memory_resource": "cpp",
"numeric": "cpp",
"optional": "cpp",
"random": "cpp",
"ratio": "cpp",
"string": "cpp",
"string_view": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"fstream": "cpp",
"initializer_list": "cpp",
"iomanip": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"limits": "cpp",
"new": "cpp",
"ostream": "cpp",
"ranges": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"stop_token": "cpp",
"streambuf": "cpp",
"cfenv": "cpp",
"typeindex": "cpp",
"typeinfo": "cpp",
"valarray": "cpp",
"variant": "cpp",
"__bit_reference": "cpp",
"__config": "cpp",
"__debug": "cpp",
"__errc": "cpp",
"__functional_base": "cpp",
"__hash_table": "cpp",
"__locale": "cpp",
"__mutex_base": "cpp",
"__node_handle": "cpp",
"__nullptr": "cpp",
"__split_buffer": "cpp",
"__string": "cpp",
"__threading_support": "cpp",
"__tree": "cpp",
"__tuple": "cpp",
"ios": "cpp",
"locale": "cpp",
"queue": "cpp",
"stack": "cpp"
},
"cmake.configureOnOpen": true
}

View File

@@ -0,0 +1,45 @@
cmake_minimum_required(VERSION 3.13.4)
project("main")
set(CMAKE_CXX_STANDARD 11)
add_subdirectory("src")
target_include_directories("${PROJECT_NAME}"
PUBLIC "${CMAKE_SOURCE_DIR}/../../../include"
)
target_link_directories("${PROJECT_NAME}"
PRIVATE "${CMAKE_SOURCE_DIR}/../../../lib"
)
target_link_libraries("${PROJECT_NAME}"
camera
shader
framebuffer
glml
)
if (MSVC)
set(AssimpLibs
debug Debug/assimp-vc142-mtd optimized Release/assimp-vc142-mt
debug Debug/IrrXMLd optimized Release/IrrXML
debug Debug/zlibstaticd optimized Release/zlibstatic)
set (glfw3Lib debug Debug/glfw3d optimized Release/glfw3)
target_link_libraries("${PROJECT_NAME}"
opengl32
${AssimpLibs}
${glfw3Lib}
)
elseif (UNIX)
target_link_libraries("${PROJECT_NAME}"
glfw
dl
m
Xi
pthread
Xrandr
X11
GL
GLU
assimp
)
endif()

View File

@@ -0,0 +1,3 @@
#!/bin/bash
cmake --build build

View File

@@ -0,0 +1,3 @@
#!/bin/bash
cmake -S . -B build

View File

@@ -0,0 +1,5 @@
#!/bin/bash
cd build/src/
exec ./main
#cd ../../

View File

@@ -0,0 +1,34 @@
add_library(camera Camera.cpp include/Camera.h)
add_library(shader Shader.cpp include/Shader.h)
add_library(glml Model.cpp include/Model.h Mesh.cpp include/Mesh.h)
add_library(framebuffer Framebuffer.cpp include/Framebuffer.h)
set(REPO_ROOT "${CMAKE_SOURCE_DIR}/../../..")
set(PROJECT_DIR "${CMAKE_SOURCE_DIR}")
set(SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
set(BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}")
include_directories(
"${CMAKE_CURRENT_BINARY_DIR}"
"${REPO_ROOT}/include"
"${SOURCE_DIR}/include"
)
configure_file(config.h.in config.h @ONLY)
file(GLOB SHADERS
"shaders/*.frag"
"shaders/*.vert"
"shaders/*.geom"
)
add_executable("${PROJECT_NAME}"
main.cpp
"${REPO_ROOT}/glad.c"
"${REPO_ROOT}/stb_image.cpp"
"${REPO_ROOT}/stb_image_write.cpp"
include/DebugColors.h
"${BINARY_DIR}/config.h"
"${SHADERS}"
)
source_group(TREE ${SOURCE_DIR} PREFIX "" FILES ${SHADERS})

View File

@@ -0,0 +1,83 @@
#include "Camera.h"
#include <glm/gtc/matrix_transform.hpp>
Camera::Camera(glm::vec3 position, glm::vec3 worldUp, glm::vec3 worldFront, float yaw, float pitch) : Front(glm::vec3(0.0f, 0.0f, -1.0f)), MovementSpeed(2.5f), MouseSensitivity(0.1f), FOV(45.0f), Mode(CAM_FLOAT)
{
this->Position = position;
this->WorldUp = worldUp;
this->Yaw = yaw;
this->Pitch = pitch;
this->WorldFront = worldFront;
this->WorldRight = glm::normalize(glm::cross(this->WorldFront, this->WorldUp));
updateCameraVectors();
}
void Camera::updateCameraVectors()
{
glm::vec3 front;
front.x = cos(glm::radians(Yaw)) * cos(glm::radians(Pitch));
front.y = sin(glm::radians(Pitch));
front.z = sin(glm::radians(Yaw)) * cos(glm::radians(Pitch));
Front = glm::normalize(front);
Right = glm::normalize(glm::cross(Front, WorldUp));
Up = glm::normalize(glm::cross(Right, Front));
}
glm::mat4 Camera::getViewMatrix()
{
return glm::lookAt(Position, Position + Front, WorldUp);
}
void Camera::ProccessKeyboard(camera_movement direction, float deltaTime)
{
switch (direction)
{
case CAM_FORWARD:
Position += deltaTime * MovementSpeed * Front;
break;
case CAM_BACKWARD:
Position -= deltaTime * MovementSpeed * Front;
break;
case CAM_LEFT:
Position -= deltaTime * MovementSpeed * Right;
break;
case CAM_RIGHT:
Position += deltaTime * MovementSpeed * Right;
break;
case CAM_UP:
Position += deltaTime * MovementSpeed * WorldUp;
break;
case CAM_DOWN:
Position -= deltaTime * MovementSpeed * WorldUp;
break;
}
}
void Camera::ProccessMouse(float xoffset, float yoffset, bool constrainPitch)
{
xoffset *= MouseSensitivity;
yoffset *= MouseSensitivity;
Yaw = fmodf(Yaw + xoffset, 360.0f);
Pitch += yoffset;
if (constrainPitch)
{
if (Pitch > 89.0f)
Pitch = 89.0f;
else if (Pitch < -89.0f)
Pitch = -89.0f;
}
updateCameraVectors();
}
void Camera::ProccessScroll(float yoffset)
{
FOV -= yoffset;
if (FOV < 1.0f)
FOV = 1.0f;
else if (FOV > 45.0f)
FOV = 45.0f;
}
void Camera::SetCameraMode(camera_mode mode)
{
Mode = mode;
}

View File

@@ -0,0 +1,409 @@
#include "Framebuffer.h"
#include <glad/glad.h>
#include <iostream>
#include <vector>
#include "DebugColors.h"
#include <stb_image_write.h>
#include <ctime>
int checkFramebufferStatus()
{
int status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
switch (status)
{
case GL_FRAMEBUFFER_COMPLETE:
return 0;
break;
default:
fprintf(stderr, "Framebuffer.h: " DC_ERROR " code: %#04x\n", (int)status);
return -1;
break;
}
}
Framebuffer::Framebuffer(const int& width, const int& height)
{
glGenFramebuffers(1, &ID);
glBindFramebuffer(GL_FRAMEBUFFER, ID);
glGenTextures(1, &ColorBuffer);
glBindTexture(GL_TEXTURE_2D, ColorBuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ColorBuffer, 0);
glGenRenderbuffers(1, &DepthStencilBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, DepthStencilBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, DepthStencilBuffer);
if (checkFramebufferStatus() != 0)
{
glDeleteRenderbuffers(1, &DepthStencilBuffer);
glDeleteTextures(1, &ColorBuffer);
glDeleteFramebuffers(1, &ID);
std::cerr << "Framebuffer.h: " DC_ERROR " Could not create framebuffer object." << std::endl;
ID = 0;
return;
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
this->width = width;
this->height = height;
}
Framebuffer::~Framebuffer()
{
destroy();
}
void Framebuffer::destroy()
{
glDeleteRenderbuffers(1, &DepthStencilBuffer);
glDeleteTextures(1, &ColorBuffer);
glDeleteFramebuffers(1, &ID);
}
void Framebuffer::UpdateSize(const unsigned int& newWidth, const unsigned int& newHeight)
{
if (!checkBind())
glBindFramebuffer(GL_FRAMEBUFFER, ID);
glBindTexture(GL_TEXTURE_2D, ColorBuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, newWidth, newHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_2D, 0);
glDeleteRenderbuffers(1, &DepthStencilBuffer);
glGenRenderbuffers(1, &DepthStencilBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, DepthStencilBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, newWidth, newHeight);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, DepthStencilBuffer);
}
void Framebuffer::Use()
{
glBindFramebuffer(GL_FRAMEBUFFER, ID);
}
void Framebuffer::UseDefault()
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
void Framebuffer::clearBuffers(float r, float g, float b, float a)
{
if (!checkBind())
glBindFramebuffer(GL_FRAMEBUFFER, ID);
glClearColor(r, g, b, a);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
}
void Framebuffer::clearColorBuffer(float r, float g, float b, float a)
{
if (!checkBind())
glBindFramebuffer(GL_FRAMEBUFFER, ID);
glClearColor(r, g, b, a);
glClear(GL_COLOR_BUFFER_BIT);
}
void Framebuffer::clearDepthBuffer()
{
if (!checkBind())
glBindFramebuffer(GL_FRAMEBUFFER, ID);
glClear(GL_DEPTH_BUFFER_BIT);
}
void Framebuffer::clearStencilBuffer()
{
if (!checkBind())
glBindFramebuffer(GL_FRAMEBUFFER, ID);
glClear(GL_STENCIL_BUFFER_BIT);
}
void Framebuffer::clearDepthStencilBuffer()
{
if (!checkBind())
glBindFramebuffer(GL_FRAMEBUFFER, ID);
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
}
unsigned int Framebuffer::getWidth()
{
return width;
}
unsigned int Framebuffer::getHeight()
{
return height;
}
bool Framebuffer::checkBind()
{
int id = 0;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &id);
if ((unsigned int)id == ID)
return true;
return false;
}
unsigned int Framebuffer::getColorBuffer()
{
return ColorBuffer;
}
unsigned int Framebuffer::getDepthSnectilBuffer()
{
return DepthStencilBuffer;
}
std::string Framebuffer::screenshot(std::string path)
{
int id = 0;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &id);
unsigned char *data = new unsigned char[(int)width * (int)height * 4];
this->Use();
glReadBuffer(GL_COLOR_ATTACHMENT0);
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
stbi_flip_vertically_on_write(1);
std::string scr_name = path + "/" + getScreenshotName();
stbi_write_png(scr_name.c_str(), width, height, 4, data, 4 * width);
delete data;
glBindFramebuffer(GL_FRAMEBUFFER, (unsigned int)id);
return scr_name;
}
MSFramebuffer::MSFramebuffer(const int& width, const int& height, const unsigned int samples)
: Nsamples(samples), intermediateFBO(NULL)
{
glGenFramebuffers(1, &ID);
glBindFramebuffer(GL_FRAMEBUFFER, ID);
glGenTextures(1, &ColorBuffer);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, ColorBuffer);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGB, width, height, GL_TRUE);
glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, ColorBuffer, 0);
glGenRenderbuffers(1, &DepthStencilBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, DepthStencilBuffer);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GL_DEPTH24_STENCIL8, width, height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, DepthStencilBuffer);
if (checkFramebufferStatus() != 0)
{
glDeleteRenderbuffers(1, &DepthStencilBuffer);
glDeleteTextures(1, &ColorBuffer);
glDeleteFramebuffers(1, &ID);
std::cerr << "Framebuffer.h: " DC_ERROR " Could not create multisampled framebuffer object." << std::endl;
ID = 0;
return;
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
this->width = width;
this->height = height;
intermediateFBO = new Framebuffer(width, height);
}
MSFramebuffer::~MSFramebuffer()
{
destroy();
delete intermediateFBO;
}
std::string MSFramebuffer::screenshot(std::string path)
{
int id = 0;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &id);
unsigned char *data = new unsigned char[width * height * 4];
getColorBuffer();
intermediateFBO->Use();
glReadBuffer(GL_COLOR_ATTACHMENT0);
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
stbi_flip_vertically_on_write(1);
std::string scr_name = path + "/" + getScreenshotName();
stbi_write_png(scr_name.c_str(), width, height, 4, data, 4 * width);
delete data;
glBindFramebuffer(GL_FRAMEBUFFER, (unsigned int)id);
return scr_name;
}
void MSFramebuffer::UpdateSize(const unsigned int& newWidth, const unsigned int& newHeight)
{
if (!checkBind())
glBindFramebuffer(GL_FRAMEBUFFER, ID);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, ColorBuffer);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, Nsamples, GL_RGBA, newWidth, newHeight, GL_TRUE);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
glDeleteRenderbuffers(1, &DepthStencilBuffer);
glGenRenderbuffers(1, &DepthStencilBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, DepthStencilBuffer);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, Nsamples, GL_DEPTH24_STENCIL8, newWidth, newHeight);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, DepthStencilBuffer);
}
unsigned int MSFramebuffer::getColorBuffer()
{
glBindFramebuffer(GL_READ_FRAMEBUFFER, ID);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, intermediateFBO->ID);
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
return intermediateFBO->getColorBuffer();
}
unsigned int MSFramebuffer::getDepthSnectilBuffer()
{
glBindFramebuffer(GL_READ_FRAMEBUFFER, ID);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, intermediateFBO->ID);
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
return intermediateFBO->getDepthSnectilBuffer();
}
unsigned int MSFramebuffer::getColorBufferMS()
{
return ColorBuffer;
}
/* Static functions */
void Framebuffer::clearAllBuffers(float r, float g, float b, float a)
{
glClearColor(r, g, b, a);
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
std::string Framebuffer::getScreenshotName()
{
time_t tim = time(NULL);
struct tm *ltm = localtime(&tim);
char buf[50];
snprintf(buf, sizeof(buf), "screenshot_%i%02i%02i_%02i%02i%02i.png",
ltm->tm_year + 1900, ltm->tm_mon + 1, ltm->tm_mday, ltm->tm_hour, ltm->tm_min, ltm->tm_sec);
return std::string(buf);
}
std::string Framebuffer::screenshot_defaultFBO(unsigned int width, unsigned int height, std::string path)
{
int id = 0;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &id);
uint8_t *data = new uint8_t[width * height * 4];
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
stbi_flip_vertically_on_write(1);
std::string scr_name = path + "/" + getScreenshotName();
stbi_write_png(scr_name.c_str(), width, height, 4, data, 4 * width);
delete[] data;
glBindFramebuffer(GL_FRAMEBUFFER, (unsigned int)id);
return scr_name;
}
/* Depthmap Framebuffer */
DepthmapFramebuffer::DepthmapFramebuffer(const Resolution& resolution) : resolution(resolution), depth_texture(0), ID(0)
{
glGenFramebuffers(1, &ID);
glGenTextures(1, &depth_texture);
glBindTexture(GL_TEXTURE_2D, depth_texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, resolution.Width, resolution.Height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
float borderColor[]{ 1.0f, 1.0f, 1.0f, 1.0f };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebuffer(GL_FRAMEBUFFER, ID);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_texture, 0);
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
if (checkFramebufferStatus() != 0)
{
glDeleteFramebuffers(1, &ID);
glDeleteTextures(1, &depth_texture);
std::cerr << "Framebuffer.h " << DC_ERROR << " Could not create Depthmap Framebuffer object.\n";
ID = 0;
return;
}
}
DepthmapFramebuffer::DepthmapFramebuffer(const unsigned int& width, const unsigned int& height) :
DepthmapFramebuffer(Resolution{width, height})
{}
DepthmapFramebuffer::~DepthmapFramebuffer()
{
glDeleteFramebuffers(1, &ID);
glDeleteTextures(1, &depth_texture);
}
void DepthmapFramebuffer::Use() const
{
glBindFramebuffer(GL_FRAMEBUFFER, ID);
}
void DepthmapFramebuffer::Use(GLenum target) const
{
glBindFramebuffer(target, ID);
}
unsigned int DepthmapFramebuffer::GetDepthTexture() const
{
return depth_texture;
}
void DepthmapFramebuffer::ClearDepthBuffer() const
{
Use();
glClear(GL_DEPTH_BUFFER_BIT);
}
/* DepthCubemap Framebuffer */
DepthCubeFramebuffer::DepthCubeFramebuffer(int width, int height) : Width(width), Height(height)
{
init();
}
DepthCubeFramebuffer::~DepthCubeFramebuffer()
{
glDeleteFramebuffers(1, &ID);
glDeleteTextures(1, &depthCubemap);
}
void DepthCubeFramebuffer::init()
{
glGenTextures(1, &depthCubemap);
glBindTexture(GL_TEXTURE_CUBE_MAP, depthCubemap);
for (unsigned int i = 0; i < 6; i++)
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_DEPTH_COMPONENT, Width, Height, 0,
GL_DEPTH_COMPONENT, GL_FLOAT, 0);
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);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
glGenFramebuffers(1, &ID);
glBindFramebuffer(GL_FRAMEBUFFER, ID);
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthCubemap, 0);
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
if (checkFramebufferStatus() != 0)
{
ID = 0;
}
}
unsigned int DepthCubeFramebuffer::getDepthCubemap() const
{
return depthCubemap;
}
void DepthCubeFramebuffer::clearDepth() const
{
glClear(GL_DEPTH_BUFFER_BIT);
}
void DepthCubeFramebuffer::Use() const
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

View File

@@ -0,0 +1,67 @@
#include <glad/glad.h>
#include "Mesh.h"
using namespace glml;
Mesh::Mesh(const std::vector<Vertex>& vertices,
const std::vector<unsigned int>& indices,
const std::vector<Texture>& textures) : vertices(vertices), indices(indices), textures(textures)
{
setupMesh();
}
void Mesh::setupMesh()
{
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const void*)offsetof(Vertex, Position));
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const void*)offsetof(Vertex, Normal));
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const void*)offsetof(Vertex, TexCoord));
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const void*)offsetof(Vertex, Tangent));
glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const void*)offsetof(Vertex, Bitangent));
for (int i = 0; i < 5; i++)
glEnableVertexAttribArray(i);
glBindVertexArray(0);
}
void Mesh::Draw(const Shader& shader) const
{
unsigned int diffNr = 0;
unsigned int specNr = 0;
unsigned int normNr = 0;
unsigned int heigNr = 0;
for (int i = 0; i < textures.size(); i++)
{
std::string name = TextureTypeStrings[static_cast<size_t>(textures[i].type)];
if (textures[i].type == TextureType::diffuse)
name += std::to_string(diffNr++);
else if (textures[i].type == TextureType::specular)
name += std::to_string(specNr++);
else if (textures[i].type == TextureType::normal)
name += std::to_string(normNr++);
else if (textures[i].type == TextureType::height)
name += std::to_string(heigNr++);
glActiveTexture(GL_TEXTURE0 + i);
shader.setInt("material." + name, i);
glBindTexture(GL_TEXTURE_2D, textures[i].id);
}
glActiveTexture(GL_TEXTURE0);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
}

View File

@@ -0,0 +1,200 @@
#include <glad/glad.h>
#include <assimp/Importer.hpp>
#include <assimp/postprocess.h>
#include <iostream>
#include <stb_image.h>
#include "Model.h"
#include "DebugColors.h"
using namespace glml;
Model::Model(const std::string path, bool flip_textures, bool sRGB_diffuse) :
sRGB_diffuse(sRGB_diffuse), flip_textures(flip_textures)
{
loadModel(path);
}
void Model::Draw(const Shader& shader) const
{
for (int i = 0; i < meshes.size(); i++)
meshes[i].Draw(shader);
}
void Model::loadModel(const std::string path)
{
Assimp::Importer importer;
const aiScene* scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_CalcTangentSpace);
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode)
{
std::cerr << DC_ERROR "[ASSIMP] Model '" << path << "' not loaded.\n" << importer.GetErrorString() << std::endl;
return;
}
directory = path.substr(0, path.find_last_of('/'));
processNode(scene->mRootNode, scene);
}
void Model::processNode(aiNode* node, const aiScene* scene)
{
unsigned int i;
for (i = 0; i < node->mNumMeshes; i++)
{
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
meshes.push_back(processMesh(mesh, scene));
}
for (i = 0; i < node->mNumChildren; i++)
processNode(node->mChildren[i], scene);
}
Mesh Model::processMesh(aiMesh* mesh, const aiScene* scene)
{
std::vector<Vertex> vertices;
std::vector<unsigned int> indices;
std::vector<Texture> textures;
unsigned int i;
for (i = 0; i < mesh->mNumVertices; i++)
{
Vertex vertex;
glm::vec3 v;
v.x = mesh->mVertices[i].x;
v.y = mesh->mVertices[i].y;
v.z = mesh->mVertices[i].z;
vertex.Position = v;
if (mesh->mNormals != NULL)
{
v.x = mesh->mNormals[i].x;
v.y = mesh->mNormals[i].y;
v.z = mesh->mNormals[i].z;
vertex.Normal = v;
}
if (mesh->mTangents != NULL)
{
v.x = mesh->mTangents[i].x;
v.y = mesh->mTangents[i].y;
v.z = mesh->mTangents[i].z;
vertex.Tangent = v;
}
if (mesh->mBitangents != NULL)
{
v.x = mesh->mBitangents[i].x;
v.y = mesh->mBitangents[i].y;
v.z = mesh->mBitangents[i].z;
vertex.Bitangent = v;
}
if (mesh->mTextureCoords[0]) { // does the mesh contains texture coordinates?
glm::vec2 vec;
vec.x = mesh->mTextureCoords[0][i].x;
vec.y = mesh->mTextureCoords[0][i].y;
vertex.TexCoord = vec;
}
else {
vertex.TexCoord = glm::vec2(0.0f);
}
vertices.push_back(vertex);
}
for (i = 0; i < mesh->mNumFaces; i++)
{
aiFace face = mesh->mFaces[i];
for (unsigned int j = 0; j < face.mNumIndices; j++)
indices.push_back(face.mIndices[j]);
}
if (mesh->mMaterialIndex >= 0)
{
aiMaterial* mat = scene->mMaterials[mesh->mMaterialIndex];
std::vector<Texture> diffuseMaps = loadMaterialTextures(mat, aiTextureType_DIFFUSE, TextureType::diffuse);
textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end());
std::vector<Texture> specularMaps = loadMaterialTextures(mat, aiTextureType_SPECULAR, TextureType::specular);
textures.insert(textures.end(), specularMaps.begin(), specularMaps.end());
std::vector<Texture> normalMaps = loadMaterialTextures(mat, aiTextureType_NORMALS, TextureType::normal);
textures.insert(textures.end(), normalMaps.begin(), normalMaps.end());
std::vector<Texture> heightMaps = loadMaterialTextures(mat, aiTextureType_HEIGHT, TextureType::height);
textures.insert(textures.end(), heightMaps.begin(), heightMaps.end());
}
return Mesh(vertices, indices, textures);
}
std::vector<Texture> Model::loadMaterialTextures(aiMaterial* mat, aiTextureType type, TextureType glmlType)
{
std::vector<Texture> textures;
bool sRGB = false;
if (sRGB_diffuse && glmlType == TextureType::diffuse)
sRGB = true;
for (unsigned int i = 0; i < mat->GetTextureCount(type); i++)
{
aiString str;
mat->GetTexture(type, i, &str);
bool loaded = false;
for (int j = 0; j < textures_loaded.size(); j++)
{
if (std::strcmp(textures_loaded[j].path.data(), str.C_Str()) == 0)
{
textures.push_back(textures_loaded[j]);
loaded = true;
break;
}
}
if (!loaded)
{
Texture texture;
texture.id = load_texture(directory + '/' + str.C_Str(), flip_textures, sRGB);
texture.type = glmlType;
texture.path = str.C_Str();
textures.push_back(texture);
textures_loaded.push_back(texture);
}
}
return textures;
}
static unsigned int glml::load_texture(std::string path, bool flip, bool sRGB, GLint wrapS, GLint wrapT)
{
return glml::load_texture(path.c_str(), flip, sRGB, wrapS, wrapT);
}
static unsigned int glml::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 {
std::cerr << DC_WARNING " Could not load texture '" << path << "'\n";
}
stbi_image_free(data);
glBindTexture(GL_TEXTURE_2D, 0);
return texture;
}

View File

@@ -0,0 +1,179 @@
#include "Shader.h"
#include <iostream>
#include <fstream>
#include <sstream>
#include <glad/glad.h>
#include <glm/gtc/type_ptr.hpp>
#include "DebugColors.h"
Shader::Shader(const char* vertexShaderSourcePath, const char* fragmentShaderSourcePath, const char* geometryShaderSourcePath, bool directSource)
{
const char* vertexSource;
const char* fragmentSource;
const char* geometrySource;
std::string v, f, g;
if (!directSource)
{
v = readFile(vertexShaderSourcePath);
f = readFile(fragmentShaderSourcePath);
if (v == "" || f == "") {
this->Program = 0;
return;
}
vertexSource = v.c_str();
fragmentSource = f.c_str();
if (geometryShaderSourcePath != NULL)
{
g = readFile(geometryShaderSourcePath);
if (g == "") {
this->Program = 0;
return;
}
geometrySource = g.c_str();
}
else
geometrySource = NULL;
}
else
{
vertexSource = vertexShaderSourcePath;
fragmentSource = fragmentShaderSourcePath;
geometrySource = geometryShaderSourcePath;
}
int success;
char infoLog[512];
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexSource, NULL);
glCompileShader(vertexShader);
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
std::cerr << "Shader.h: " DC_WARNING " Vertex shader compilation failed!\n";
std::cerr << "shader.h: " DC_WARNING " Path: " << vertexShaderSourcePath << '\n' << infoLog << std::endl;
this->Program = 0;
return;
}
unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentSource, NULL);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
std::cerr << "Shader.h: " DC_WARNING " Fragment shader compilation failed!\n";
std::cerr << "shader.h: " DC_WARNING " Path: " << fragmentShaderSourcePath << '\n' << infoLog << std::endl;
this->Program = 0;
return;
}
unsigned int geometryShader;
if (geometrySource)
{
geometryShader = glCreateShader(GL_GEOMETRY_SHADER);
glShaderSource(geometryShader, 1, &geometrySource, NULL);
glCompileShader(geometryShader);
glGetShaderiv(geometryShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(geometryShader, 512, NULL, infoLog);
std::cerr << "Shader.h: " DC_WARNING " Geometry shader compilation failed!\n";
std::cerr << "Shader.h: " DC_WARNING " Path: " << geometryShaderSourcePath;
std::cerr << std::endl << infoLog << std::endl;
this->Program = 0;
return;
}
}
Program = glCreateProgram();
glAttachShader(Program, vertexShader);
glAttachShader(Program, fragmentShader);
if (geometrySource)
glAttachShader(Program, geometryShader);
glLinkProgram(Program);
glGetProgramiv(Program, GL_LINK_STATUS, &success);
if (!success)
{
glGetProgramInfoLog(Program, 512, NULL, infoLog);
std::cerr << "shader.h: " DC_ERROR " Program linking failed\n" << infoLog << std::endl;
this->Program = 0;
return;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
}
Shader::Shader(std::string vertexShaderSourcePath,
std::string fragmentShaderSourcePath,
std::string geometryShaderSource,
bool directSource) : Shader(vertexShaderSourcePath.c_str(), fragmentShaderSourcePath.c_str(), geometryShaderSource.c_str(), directSource)
{
}
Shader::~Shader()
{
glDeleteProgram(Program);
}
std::string Shader::readFile(const char* path)
{
std::ifstream ifs(path); // input file stream
if (ifs.fail())
{
std::cout << "shader.h: " DC_ERROR " Could not open file '" << path << "'\n";
return "";
}
std::stringstream buffer;
buffer << ifs.rdbuf();
std::string out = buffer.str();
ifs.close();
return out;
}
void Shader::Use() const
{
glUseProgram(Program);
}
void Shader::setBool(const std::string name, bool value) const
{
glUniform1i(glGetUniformLocation(Program, name.c_str()), value ? 1 : 0);
}
void Shader::setFloat(const std::string name, float value) const
{
glUniform1f(glGetUniformLocation(Program, name.c_str()), value);
}
void Shader::setInt(const std::string name, int value) const
{
glUniform1i(glGetUniformLocation(Program, name.c_str()), value);
}
void Shader::setMat4(const std::string name, glm::mat4 value) const
{
glUniformMatrix4fv(glGetUniformLocation(Program, name.c_str()), 1, GL_FALSE, glm::value_ptr(value));
}
void Shader::setVec3(const std::string name, glm::vec3 value) const
{
setVec3(name, value.x, value.y, value.z);
}
void Shader::setVec3(const std::string name, float v0, float v1, float v2) const
{
glUniform3f(glGetUniformLocation(Program, name.c_str()), v0, v1, v2);
}
void Shader::setMat3(const std::string name, glm::mat3 value) const
{
glUniformMatrix3fv(glGetUniformLocation(Program, name.c_str()), 1, GL_FALSE, glm::value_ptr(value));
}
void Shader::setVec2(const std::string name, float v0, float v1) const
{
glUniform2f(glGetUniformLocation(Program, name.c_str()), v0, v1);
}
void Shader::setVec2(const std::string name, glm::vec2 v) const
{
setVec2(name, v.x, v.y);
}

View File

@@ -0,0 +1,4 @@
#cmakedefine REPO_ROOT "@REPO_ROOT@"
#cmakedefine PROJECT_DIR "@PROJECT_DIR@"
#cmakedefine SOURCE_DIR "@SOURCE_DIR@"
#cmakedefine BINARY_DIR "@BINARY_DIR@"

View File

@@ -0,0 +1,54 @@
#pragma once
#include <glm/glm.hpp>
enum camera_movement {
CAM_FORWARD,
CAM_BACKWARD,
CAM_LEFT,
CAM_RIGHT,
CAM_UP,
CAM_DOWN
};
enum camera_mode {
CAM_FLOAT,
CAM_MINECRAFT
};
class Camera
{
public:
float FOV;
float MovementSpeed;
float MouseSensitivity;
float Yaw; // vlevo vpravo
float Pitch; // nahoru dolu
camera_mode Mode;
glm::vec3 Position;
glm::vec3 Front;
glm::vec3 Right;
glm::vec3 Up;
glm::vec3 WorldUp;
glm::vec3 WorldRight;
glm::vec3 WorldFront;
Camera(glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f),
glm::vec3 worldUp = glm::vec3(0.0f, 1.0f, 0.0f),
glm::vec3 worldFront = glm::vec3(0.0f, 0.0f, -1.0),
float yaw = -90.0f, float pitch = 0);
glm::mat4 getViewMatrix();
void ProccessKeyboard(camera_movement direction, float deltaTime);
void ProccessMouse(float xoffset, float yoffset, bool constrainPitch = true);
void ProccessScroll(float yoffset);
void SetCameraMode(camera_mode mode);
private:
float lastY;
float lastX;
void updateCameraVectors();
};

View File

@@ -0,0 +1,11 @@
#pragma once
#define DC_RED "\x1b[31m"
#define DC_GREEN "\x1b[32m"
#define DC_YELLOW "\x1b[33m"
#define DC_CYAN "\x1b[36m"
#define DC_MAGNETA "\x1b[35m"
#define DC_DEFAULT "\x1b[0m"
#define DC_ERROR DC_RED "[ERROR]" DC_DEFAULT
#define DC_SUCCESS DC_GREEN "[SUCCESS]" DC_DEFAULT
#define DC_INFO DC_CYAN "[INFO]" DC_DEFAULT
#define DC_WARNING DC_YELLOW "[WARNING]" DC_DEFAULT

View File

@@ -0,0 +1,113 @@
#pragma once
#include <string>
#include <glad/glad.h>
#include "config.h"
class Framebuffer
{
public:
/* id of this framebuffer */
unsigned int ID;
Framebuffer(const int& width, const int& height);
virtual ~Framebuffer();
/* updates width and height of buffers */
virtual void UpdateSize(const unsigned int& newWidth, const unsigned int& newHeight);
/* sets opengl to use this framebuffer */
void Use();
/* sets opengl to use default buffer */
void UseDefault();
void clearBuffers(float r = 0.0f, float g = 0.0f, float b = 0.0f, float a = 1.0f);
void clearColorBuffer(float r = 0.0f, float g = 0.0f, float b = 0.0f, float a = 1.0f);
void clearDepthBuffer();
void clearStencilBuffer();
void clearDepthStencilBuffer();
virtual unsigned int getWidth();
virtual unsigned int getHeight();
virtual unsigned int getColorBuffer();
virtual unsigned int getDepthSnectilBuffer();
static std::string getScreenshotName();
/* saves image of framebuffers color buffer */
virtual std::string screenshot(std::string path = BINARY_DIR);
static void clearAllBuffers(float r = 0.0f, float g = 0.0f, float b = 0.0f, float a = 1.0f);
/* saves image of default framebuffer */
static std::string screenshot_defaultFBO(unsigned int width, unsigned int height, std::string path = BINARY_DIR);
protected:
Framebuffer() : width(0), height(0), ColorBuffer(0), ID(0), DepthStencilBuffer(0) {}
unsigned int width;
unsigned int height;
/* opengl texture2D */
unsigned int ColorBuffer;
/* renderbuffer depth 24 bits stencil 8 bits */
unsigned int DepthStencilBuffer;
virtual bool checkBind();
virtual void destroy();
};
/* Multisampled Framebuffer */
class MSFramebuffer : public Framebuffer
{
public:
/* Number of samples */
const unsigned int Nsamples;
MSFramebuffer(const int& width, const int& height, const unsigned int samples);
virtual ~MSFramebuffer();
std::string screenshot(std::string = BINARY_DIR) override;
void UpdateSize(const unsigned int& newWidth, const unsigned int& newHeight) override;
/* Returns resolved color buffer */
unsigned int getColorBuffer() override;
unsigned int getDepthSnectilBuffer() override;
/* Reurns unresolved colorbuffer. ( with multisample informations ) */
unsigned int getColorBufferMS();
protected:
MSFramebuffer() : Nsamples(0), intermediateFBO(NULL) {}
private:
Framebuffer* intermediateFBO;
};
struct Resolution
{
unsigned int Width;
unsigned int Height;
};
class DepthmapFramebuffer
{
public:
unsigned int ID;
Resolution resolution;
DepthmapFramebuffer(const Resolution& resolution);
DepthmapFramebuffer(const unsigned int& width, const unsigned int& height);
~DepthmapFramebuffer();
void Use() const;
void Use(GLenum target) const;
unsigned int GetDepthTexture() const;
void ClearDepthBuffer() const;
private:
unsigned int depth_texture;
};
class DepthCubeFramebuffer
{
unsigned int depthCubemap;
void init();
public:
unsigned int ID;
const int Width, Height;
DepthCubeFramebuffer(int width, int height);
~DepthCubeFramebuffer();
unsigned int getDepthCubemap() const;
void clearDepth() const;
void Use() const;
};

View File

@@ -0,0 +1,53 @@
#pragma once
#include <glm/glm.hpp>
#include <string>
#include <vector>
#include "Shader.h"
namespace glml
{
static const std::string TextureTypeStrings[] = {
"texture_diffuse",
"texture_specular",
"texture_normal",
"texture_height"
};
enum class TextureType : size_t
{
diffuse = 0,
specular = 1,
normal = 2,
height = 3
};
struct Vertex {
glm::vec3 Position;
glm::vec3 Normal;
glm::vec2 TexCoord;
glm::vec3 Tangent;
glm::vec3 Bitangent;
};
struct Texture {
unsigned int id;
TextureType type;
std::string path;
};
class Mesh {
public:
unsigned int VAO;
std::vector<Vertex> vertices;
std::vector<unsigned int> indices;
std::vector<Texture> textures;
Mesh(const std::vector<Vertex>& vertices, const std::vector<unsigned int>& indices, const std::vector<Texture>& textures);
void Draw(const Shader& shader) const;
private:
unsigned int VBO, EBO;
void setupMesh();
};
};

View File

@@ -0,0 +1,48 @@
#pragma once
#include <string>
#include "Mesh.h"
#include <vector>
#include "Shader.h"
#include <assimp/scene.h>
/*
Vertex attributes are expected as follows:
0. Vertex position
1. Vertex normal
2. Vertex texture coordinate
3. Vertex tangent
4. Vertex bitangent
In the Fragment Shader there must be at least
struct Material
{
sampler2D texture_diffuse0;
}
uniform Material material;
*/
namespace glml
{
class Model {
public:
std::vector<Mesh> meshes;
std::vector<Texture> textures_loaded;
/* sRGB_diffuse: when true, save diffuse textures as sRGB textures*/
Model(const std::string path, bool flip_textures = false, bool sRGB_diffuse = false);
void Draw(const Shader& shader) const;
private:
// model data
std::string directory;
const bool sRGB_diffuse;
const bool flip_textures;
void loadModel(const std::string path);
void processNode(aiNode* node, const aiScene* scene);
Mesh processMesh(aiMesh* mesh, const aiScene* scene);
std::vector<Texture> loadMaterialTextures(aiMaterial* mat, aiTextureType type, TextureType glmlType);
};
static unsigned int load_texture(const char* path, bool flip = true, bool sRGB = true, GLint wrapS = GL_REPEAT, GLint wrapT = GL_REPEAT);
static unsigned int load_texture(std::string path, bool flip = true, bool sRGB = true, GLint wrapS = GL_REPEAT, GLint wrapT = GL_REPEAT);
}

View File

@@ -0,0 +1,29 @@
#pragma once
#include <string>
#include <glm/glm.hpp>
class Shader
{
public:
unsigned int Program;
Shader(const char* vertexShaderSourcePath, const char* fragmentShaderSourcePath, const char* geometryShaderSource = NULL, bool directSource = false);
Shader(std::string vertexShaderSourcePath, std::string fragmentShaderSourcePath, std::string geometryShaderSource = NULL, bool directSource = false);
~Shader();
void Use() const;
void setBool(const std::string name, bool value) const;
void setFloat(const std::string name, float value) const;
void setInt(const std::string name, int value) const;
void setMat4(const std::string name, glm::mat4 value) const;
void setVec3(const std::string name, glm::vec3 value) const;
void setVec3(const std::string name, float v0, float v1, float v2) const;
void setVec2(const std::string name, float v0, float v1) const;
void setVec2(const std::string name, glm::vec2 v) const;
void setMat3(const std::string name, glm::mat3 value) const;
static std::string readFile(const char* path);
};

View File

@@ -0,0 +1,588 @@
#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 "5. Normal 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;
//STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes);
// 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;
glml::Model* cyborg = NULL;
glm::vec3 lightPos(0.0f);
glm::vec3 lightColor(1.0f, 1.0f, 1.0f);
bool cullFaces = false;
bool normalMapping = 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 = true;
//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, true);
// 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);
delete(cyborg);
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;
}
/* -------------------- 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)
{
// positions
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);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 14 * sizeof(float), (void*)0);
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 14 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 14 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 14 * sizeof(float), (void*)(8 * sizeof(float)));
glEnableVertexAttribArray(4);
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;
void draw_scene(const Shader* shader, bool lightCube)
{
//if (brick_texture == 0) // flipV sRGB
// brick_texture = load_texture(TEXTURES_DIR "brickwall/brickwall.jpg", true, true);
//if (brick_texture_normal == 0)
// brick_texture_normal = load_texture(TEXTURES_DIR "brickwall/brickwall_normal.jpg", true, false);
if (cyborg == NULL)
cyborg = new glml::Model(MODELS_DIR "backpack/backpack.obj", true, true);
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, 0.0f);
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("texture0", 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, brick_texture);
shader->setInt("texture0_normal", 1);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, brick_texture_normal);*/
if (cullFaces)
glEnable(GL_CULL_FACE);
model = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, -1.5f, -2.0f));
model = glm::scale(model, glm::vec3(1.0f));
//model = glm::rotate(model, glm::radians(-45.0f), glm::vec3(1.0f, 0.0f, 0.0f));
shader->setMat4("model", model);
shader->setMat3("normalMatrix", glm::transpose(glm::inverse(model)));
shader->setBool("normalMapping", normalMapping);
cyborg->Draw(*shader);
if (lightCube)
{
basicShader->Use();
model = glm::translate(glm::mat4(1.0f), lightPos);
model = glm::scale(model, glm::vec3(0.1f));
basicShader->setMat4("PVM", projection * view * model);
basicShader->setVec3("Color", lightColor);
draw_cube();
}
}

View File

@@ -0,0 +1,12 @@
#version 330 core
out vec4 FragColor;
uniform vec3 Color;
void main()
{
//FragColor = vec4(Color.rgb, 1.0);
// Gamma corrected color
FragColor = vec4(pow(Color.rgb, vec3(1.0/2.2)).rgb, 1.0);
}

View File

@@ -0,0 +1,10 @@
#version 330 core
layout (location = 0) in vec3 aPos;
uniform mat4 PVM;
void main()
{
gl_Position = PVM * vec4(aPos, 1.0);
}

View File

@@ -0,0 +1,40 @@
#version 330 core
out vec4 FragColor;
in vec2 TexCoord;
uniform sampler2D texture0;
float offset = 1.0 / 300.0;
void main()
{
vec2 offsets[9] = vec2[](
vec2(-offset, offset), // top-left
vec2(0.0, offset), // top-center
vec2(offset, offset), // top-right
vec2(-offset, 0.0), // center-right
vec2(0.0, 0.0), // center-center
vec2(offset, 0.0), // center-right
vec2(-offset, -offset), // bottom-left
vec2(0.0, -offset), // bottom-center
vec2(offset, -offset) // bottom-right
);
float kernel[9] = float[](
0, 0, 0,
0, 1, 0,
0, 0, 0
);
vec3 col = vec3(0.0);
for (int i = 0; i < 9; i++)
{
col += vec3(texture(texture0, TexCoord.st + offsets[i])) * kernel[i];
}
float gamma = 2.2;
//FragColor = vec4(pow(col, vec3(1.0 / gamma)), 1.0);
FragColor = vec4(col, 1.0f);
// vec3 col = vec3(texture(texture0, TexCoord).r);
// FragColor = vec4(pow(col, vec3(1.0 / 2.2)), 1.0);
}

View File

@@ -0,0 +1,14 @@
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;
uniform mat4 PV, model;
out vec2 TexCoord;
void main()
{
TexCoord = aTexCoord;
gl_Position = vec4(aPos, 1.0);
}

View File

@@ -0,0 +1,63 @@
#version 330 core
struct Light {
vec3 position;
vec3 diffuse, specular, ambient;
};
struct Material {
sampler2D texture_diffuse0;
sampler2D texture_height0;
sampler2D texture_specular0;
};
out vec4 FragColor;
in VS_OUT
{
vec3 Normal;
vec2 TexCoord;
vec3 TangFragPos;
vec3 TangViewPos;
vec3 TangLightPos;
} fs_in; // vertex shader in
uniform Material material;
uniform Light light;
uniform bool normalMapping;
void main()
{
vec3 color = texture(material.texture_diffuse0, fs_in.TexCoord).rgb;
//vec3 color = vec3(1.0, 0.6, 0.34);
// make light direction towards the origin vec3(0.0) <-- we want directional light
vec3 lightDir = normalize(fs_in.TangLightPos - fs_in.TangFragPos);
vec3 viewDir = normalize(fs_in.TangViewPos - fs_in.TangFragPos);
vec3 normal;
if (normalMapping) {
normal = texture(material.texture_height0, fs_in.TexCoord).rgb;
normal = normalize(normal * 2.0 - 1.0);
}
else {
normal = fs_in.Normal;
}
float fragDist = length(fs_in.TangLightPos - fs_in.TangFragPos);
float attenuation = 1.0 / (1.0 + 0.14 * fragDist + 0.07 * fragDist * fragDist);
//float attenuation = 1.0 / (fragDist * fragDist);
// ambient
vec3 ambient = light.ambient * color;
// diffuse
float diff = max(dot(lightDir, normal), 0.0);
vec3 diffuse = diff * light.diffuse * color;
// specular
vec3 halfwayDir = normalize(lightDir + viewDir);
float spec = pow(max(dot(halfwayDir, normal), 0.0), 128.0);
vec3 specular = spec * light.specular * texture(material.texture_specular0, fs_in.TexCoord).rgb;
FragColor.rgb = pow(ambient + (diffuse + specular) * attenuation, vec3(1.0 / 2.2));
FragColor.a = 1.0;
// FragColor.rgb = pow(vec3(texture(depthCubemap, vs_in.FragPos - light.position).r), vec3(1.0/2.2));
// FragColor.a = 1.0;
}

View File

@@ -0,0 +1,46 @@
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoord;
layout (location = 3) in vec3 aTangent;
layout (location = 4) in vec3 aBitangent;
struct Light {
vec3 position;
vec3 diffuse, specular, ambient;
};
out VS_OUT
{
vec3 Normal;
vec2 TexCoord;
vec3 TangFragPos;
vec3 TangViewPos;
vec3 TangLightPos;
};
uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
uniform mat3 normalMatrix;
uniform vec3 viewPos;
uniform Light light;
uniform bool normalMapping;
void main()
{
vec3 T = normalize(normalMatrix * aTangent);
vec3 B = normalize(normalMatrix * aBitangent);
vec3 N = normalize(normalMatrix * aNormal);
mat3 TBN = (normalMapping) ? transpose(mat3(T, B, N)) : mat3(1.0);
TangLightPos = TBN * light.position;
TangViewPos = TBN * viewPos;
TangFragPos = TBN * vec3(model * vec4(aPos, 1.0)); // Fragment position in world space
Normal = N;
TexCoord = aTexCoord;
gl_Position = projection * view * model * vec4(aPos, 1.0);
}