first commit
This commit is contained in:
commit
8d2af1dbda
14
.gitignore
vendored
Normal file
14
.gitignore
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
.vscode/.browse.c_cpp.db*
|
||||||
|
.vscode/c_cpp_properties.json
|
||||||
|
.vscode/launch.json
|
||||||
|
.vscode/ipch
|
||||||
|
.vscode
|
||||||
|
lib
|
||||||
|
include
|
||||||
|
test
|
||||||
|
packages
|
||||||
|
.vs
|
||||||
|
bin
|
||||||
|
obj
|
||||||
|
build
|
||||||
|
makeP.bat
|
137
CMakeLists.txt
Normal file
137
CMakeLists.txt
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
|
||||||
|
# So library linking is more sane.
|
||||||
|
cmake_policy(SET CMP0003 NEW)
|
||||||
|
|
||||||
|
# So syntax problems are errors.
|
||||||
|
cmake_policy(SET CMP0010 NEW)
|
||||||
|
|
||||||
|
# Input directories must have CMakeLists.txt
|
||||||
|
cmake_policy(SET CMP0014 NEW)
|
||||||
|
|
||||||
|
# Compile definitions.
|
||||||
|
cmake_policy(SET CMP0043 NEW)
|
||||||
|
|
||||||
|
# Use ROOT variables in find_package.
|
||||||
|
cmake_policy(SET CMP0074 NEW)
|
||||||
|
|
||||||
|
# Convert relative paths to absolute in target_sources()
|
||||||
|
cmake_policy(SET CMP0076 NEW)
|
||||||
|
|
||||||
|
# Copy files from source directory to destination directory, substituting any
|
||||||
|
# variables. Create destination directory if it does not exist.
|
||||||
|
|
||||||
|
macro(configure_files srcDir destDir)
|
||||||
|
message(STATUS "Configuring directory ${destDir}")
|
||||||
|
make_directory(${destDir})
|
||||||
|
|
||||||
|
file(GLOB templateFiles RELATIVE ${srcDir} ${srcDir}/*)
|
||||||
|
foreach(templateFile ${templateFiles})
|
||||||
|
set(srcTemplatePath ${srcDir}/${templateFile})
|
||||||
|
if(NOT IS_DIRECTORY ${srcTemplatePath})
|
||||||
|
message(STATUS "Configuring file ${templateFile}")
|
||||||
|
configure_file(
|
||||||
|
${srcTemplatePath}
|
||||||
|
${destDir}/${templateFile}
|
||||||
|
@ONLY)
|
||||||
|
endif(NOT IS_DIRECTORY ${srcTemplatePath})
|
||||||
|
endforeach(templateFile)
|
||||||
|
endmacro(configure_files)
|
||||||
|
|
||||||
|
# Initialize project
|
||||||
|
project(ComputeEngine)
|
||||||
|
|
||||||
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
|
||||||
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
|
||||||
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
||||||
|
set(default_build_type "Release")
|
||||||
|
|
||||||
|
# Add binary
|
||||||
|
add_library(${PROJECT_NAME} STATIC)
|
||||||
|
|
||||||
|
# Find GLFW
|
||||||
|
|
||||||
|
set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)
|
||||||
|
set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
|
||||||
|
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
|
||||||
|
|
||||||
|
find_path(GLFW_INCLUDE_DIR GLFW/glfw3.h
|
||||||
|
HINTS
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/lib
|
||||||
|
${GLFW_ROOT}
|
||||||
|
${GLFW_ROOT}/include)
|
||||||
|
|
||||||
|
if(GLFW_INCLUDE_DIR)
|
||||||
|
message(STATUS "GLFW_INCLUDE_DIR: ${GLFW_INCLUDE_DIR}")
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "glfw3.h not found")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_path(GLFW_LIB_DIR glfw3.lib
|
||||||
|
HINTS
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/lib
|
||||||
|
${GLFW_ROOT}/lib
|
||||||
|
${GLFW_ROOT}/lib-vc2019
|
||||||
|
${GLFW_ROOT}/lib-vc2017
|
||||||
|
${GLFW_ROOT}/lib-vc2015)
|
||||||
|
|
||||||
|
if(GLFW_LIB_DIR)
|
||||||
|
message(STATUS "GLFW_LIB_DIR: ${GLFW_LIB_DIR}")
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "glfw3.lib not found")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Find GLEW
|
||||||
|
find_package(GLEW REQUIRED)
|
||||||
|
|
||||||
|
if(GLEW_FOUND)
|
||||||
|
set(GLEW_INCLUDE_DIR ${GLEW_INCLUDE_DIRS})
|
||||||
|
get_filename_component(GLEW_LIBRARIES ${GLEW_LIBRARIES} DIRECTORY)
|
||||||
|
message(STATUS "GLEW_INCLUDE_DIR: ${GLEW_INCLUDE_DIR}")
|
||||||
|
message(STATUS "GLEW_LIBRARIES: ${GLEW_LIBRARIES}")
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "GLEW not found")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Find OpenGL
|
||||||
|
if(NOT WIN32)
|
||||||
|
find_package(OpenGL REQUIRED)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Find stb_image
|
||||||
|
find_path(stb_image_INCLUDE_DIR stb_image.h
|
||||||
|
HINTS
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/include/stb
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/lib
|
||||||
|
${stb_image_ROOT})
|
||||||
|
|
||||||
|
if(stb_image_INCLUDE_DIR)
|
||||||
|
message(STATUS "stb_image_INCLUDE_DIR: ${stb_image_INCLUDE_DIR}")
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "stb_image not found")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Add source
|
||||||
|
add_subdirectory(src)
|
||||||
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||||
|
${GLFW_INCLUDE_DIR}
|
||||||
|
${OPENGL_INCLUDE_DIR}
|
||||||
|
${stb_image_INCLUDE_DIR}
|
||||||
|
${GLEW_INCLUDE_DIR})
|
||||||
|
target_link_directories(${PROJECT_NAME} PUBLIC ${GLFW_LIB_DIR} ${GLEW_LIBRARIES})
|
||||||
|
target_link_libraries(${PROJECT_NAME} "glfw3.lib" "opengl32.lib" "glew32s.lib")
|
||||||
|
|
||||||
|
# Header files
|
||||||
|
file(COPY src/ComputeEngine.h DESTINATION ${CMAKE_BINARY_DIR}/include)
|
||||||
|
file(COPY src/Timer.h DESTINATION ${CMAKE_BINARY_DIR}/include)
|
||||||
|
file(COPY src/Texture.h DESTINATION ${CMAKE_BINARY_DIR}/include)
|
||||||
|
file(COPY src/UBO.h DESTINATION ${CMAKE_BINARY_DIR}/include)
|
||||||
|
file(COPY src/SSBO.h DESTINATION ${CMAKE_BINARY_DIR}/include)
|
||||||
|
file(COPY src/Shader.h DESTINATION ${CMAKE_BINARY_DIR}/include)
|
||||||
|
file(COPY src/Program.h DESTINATION ${CMAKE_BINARY_DIR}/include)
|
||||||
|
file(COPY src/GLUtils.h DESTINATION ${CMAKE_BINARY_DIR}/include)
|
||||||
|
#file(COPY src/Scene.h DESTINATION ${CMAKE_BINARY_DIR}/include)
|
||||||
|
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2021 Dawid Pietrykowski
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
79
README.md
Normal file
79
README.md
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
# GPU Ray Tracer
|
||||||
|
GPU Ray Tracing application based on my OpenGL Compute Engine.
|
||||||
|
<p align="center">
|
||||||
|
<img src="screenshots/fox2.png">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
* OpenGL
|
||||||
|
* GLFW
|
||||||
|
* GLEW
|
||||||
|
* [stb_image](https://github.com/nothings/stb)
|
||||||
|
* [OpenGL Compute Engine](https://github.com/DawidPietrykowski/ComputeEngine)
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
Specify these root directories for dependencies in [make.bat](make.bat) script:
|
||||||
|
* GLFW_ROOT
|
||||||
|
* GLEW_ROOT
|
||||||
|
* stb_image_ROOT
|
||||||
|
* ComputeEngine_ROOT
|
||||||
|
|
||||||
|
Run [make.bat](make.bat) script.
|
||||||
|
|
||||||
|
## Config files
|
||||||
|
|
||||||
|
Each scene/configuration is described in a config file.
|
||||||
|
|
||||||
|
Example scenes are located in [/configs](configs) directory.
|
||||||
|
|
||||||
|
All available parameters are specified in [config_template.txt](config_template.txt).
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Pass chosen config file to the generated executable as an argument in command line.
|
||||||
|
|
||||||
|
If no argument given, *config.txt* is picked.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
* Wavefront (.obj) file import
|
||||||
|
* PNG, JPG, HDR texture import
|
||||||
|
* Object can be an imported triangle mesh, sphere or infinite plane
|
||||||
|
* Each scene is saved in a separate file
|
||||||
|
* Specular and diffuse reflections
|
||||||
|
* Physics based refractions
|
||||||
|
* Camera movement
|
||||||
|
* Screenshot saving
|
||||||
|
|
||||||
|
## Example images
|
||||||
|
Mesh | Refraction
|
||||||
|
:-------------------------:|:-------------------------:
|
||||||
|
![](screenshots/fox2.png) | ![](screenshots/refraction1.png)
|
||||||
|
Multiple meshes 1 | Multiple meshes 2
|
||||||
|
![](screenshots/objects1.png) | ![](screenshots/objects4.jpg)
|
||||||
|
Solar system 1 | Solar system 2
|
||||||
|
![](screenshots/solar_system1.png) | ![](screenshots/solar_system2.png)
|
||||||
|
|
||||||
|
## Keys
|
||||||
|
Camera
|
||||||
|
|
||||||
|
* UP - SPACE
|
||||||
|
* DOWN - CTRL
|
||||||
|
* LEFT - A
|
||||||
|
* RIGHT - D
|
||||||
|
* FORWARD - W
|
||||||
|
* BACKWARD - S
|
||||||
|
|
||||||
|
Window
|
||||||
|
|
||||||
|
* Screenshot - L
|
||||||
|
* Disable input to window - P
|
||||||
|
* Close application - ESC
|
||||||
|
|
||||||
|
## License and copyright
|
||||||
|
|
||||||
|
© Dawid Pietrykowski
|
||||||
|
|
||||||
|
Licensed under the [MIT LICENSE](LICENSE)
|
8
make.bat
Normal file
8
make.bat
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
set GLFW_ROOT=
|
||||||
|
set GLEW_ROOT=
|
||||||
|
set stb_image_ROOT=
|
||||||
|
|
||||||
|
cmake -B build -S . -DGLFW_ROOT=%GLFW_ROOT% -DGLEW_ROOT=%GLEW_ROOT% -Dstb_image_ROOT=%stb_image_ROOT%
|
||||||
|
cmake --build build --config Release
|
2
remake.bat
Normal file
2
remake.bat
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
rmdir /s /q build
|
||||||
|
make.bat
|
21
src/CMakeLists.txt
Normal file
21
src/CMakeLists.txt
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
target_sources(${PROJECT_NAME}
|
||||||
|
PUBLIC
|
||||||
|
GLUtils.cpp
|
||||||
|
GLUtils.h
|
||||||
|
ComputeEngine.cpp
|
||||||
|
ComputeEngine.h
|
||||||
|
Program.cpp
|
||||||
|
Program.h
|
||||||
|
#Scene.cpp
|
||||||
|
#Scene.h
|
||||||
|
Shader.cpp
|
||||||
|
Shader.h
|
||||||
|
SSBO.cpp
|
||||||
|
SSBO.h
|
||||||
|
UBO.cpp
|
||||||
|
UBO.h
|
||||||
|
Texture.cpp
|
||||||
|
Texture.h
|
||||||
|
Timer.cpp
|
||||||
|
Timer.h
|
||||||
|
)
|
379
src/ComputeEngine.cpp
Normal file
379
src/ComputeEngine.cpp
Normal file
@ -0,0 +1,379 @@
|
|||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
#include "ComputeEngine.h"
|
||||||
|
|
||||||
|
#define STBI_MSC_SECURE_CRT
|
||||||
|
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||||
|
#pragma warning(disable : 4996)
|
||||||
|
#include <stb_image_write.h>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <chrono>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <iostream>
|
||||||
|
#include <math.h>
|
||||||
|
#include <array>
|
||||||
|
#include <cmath>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <fileapi.h>
|
||||||
|
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
#include "Texture.h"
|
||||||
|
#include "Program.h"
|
||||||
|
#include "Shader.h"
|
||||||
|
#include "Timer.h"
|
||||||
|
|
||||||
|
ComputeEngine* m_instance;
|
||||||
|
|
||||||
|
ComputeEngine::~ComputeEngine() {
|
||||||
|
m_TextureDisplay.~Program();
|
||||||
|
m_instance = nullptr;
|
||||||
|
glfwTerminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
ComputeEngine::ComputeEngine(int w, int h, std::string name, bool focus, bool tonemapping)
|
||||||
|
{
|
||||||
|
m_instance = this;
|
||||||
|
|
||||||
|
m_width = w;
|
||||||
|
m_height = h;
|
||||||
|
|
||||||
|
m_window = InitWindow(m_width, m_height, name, focus);
|
||||||
|
LOG("GLFW initiated");
|
||||||
|
|
||||||
|
GLCall(glEnable(GL_DEBUG_OUTPUT));
|
||||||
|
glewExperimental = GL_FALSE;
|
||||||
|
|
||||||
|
glfwGetCursorPos(m_window, &m_xpos, &m_ypos);
|
||||||
|
|
||||||
|
Shader vertexShadrer(GL_VERTEX_SHADER);
|
||||||
|
Shader fragmentShader(GL_FRAGMENT_SHADER, tonemapping);
|
||||||
|
|
||||||
|
m_TextureDisplay = InitQuad(vertexShadrer, fragmentShader);
|
||||||
|
LOG("Texture display shader created");
|
||||||
|
|
||||||
|
for(int i = 0; i < 348; i++)
|
||||||
|
m_keys[i] = GLFW_RELEASE;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWwindow* ComputeEngine::InitWindow(int width, int height, std::string name, bool focus) {
|
||||||
|
|
||||||
|
GLFWwindow* window;
|
||||||
|
|
||||||
|
if (!glfwInit())
|
||||||
|
LOG("Failed to initialize glfw");
|
||||||
|
|
||||||
|
window = glfwCreateWindow(width, height, name.c_str(), NULL, NULL);
|
||||||
|
if (!window)
|
||||||
|
{
|
||||||
|
glfwTerminate();
|
||||||
|
LOG("Failed to initialize window");
|
||||||
|
}
|
||||||
|
|
||||||
|
glfwMakeContextCurrent(window);
|
||||||
|
glfwSetKeyCallback(window, this->KeyCallback);
|
||||||
|
glfwSetMouseButtonCallback(window, this->MouseButtonCallback);
|
||||||
|
glfwSetFramebufferSizeCallback(window, this->FramebufferSizeCallback);
|
||||||
|
if (focus) {
|
||||||
|
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||||
|
}
|
||||||
|
glfwSetWindowSizeLimits(window, 200, 200, m_fullscreen_width, m_fullscreen_height);
|
||||||
|
|
||||||
|
m_input = focus;
|
||||||
|
|
||||||
|
GLenum err = glewInit();
|
||||||
|
if (GLEW_OK != err)
|
||||||
|
{
|
||||||
|
/* Problem: glewInit failed, something is seriously wrong. */
|
||||||
|
LOG("Error: " << glewGetErrorString(err));
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG("Using GL " << glGetString(GL_VERSION));
|
||||||
|
LOG("Using GLEW " << glewGetString(GLEW_VERSION));
|
||||||
|
|
||||||
|
GLFWmonitor* primary = glfwGetPrimaryMonitor();
|
||||||
|
const GLFWvidmode* mode = glfwGetVideoMode(primary);
|
||||||
|
m_fullscreen_width = mode->width;
|
||||||
|
m_fullscreen_height = mode->height;
|
||||||
|
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
|
||||||
|
Program ComputeEngine::InitQuad(Shader& vertShader, Shader& fragShader) {
|
||||||
|
|
||||||
|
unsigned int buffer;
|
||||||
|
GLCall(glGenBuffers(1, &buffer));
|
||||||
|
GLCall(glBindBuffer(GL_ARRAY_BUFFER, buffer));
|
||||||
|
float quad_vao[] = {
|
||||||
|
-1.0f, -1.0f, 0.0f, 0.0f, // bottom left corner
|
||||||
|
-1.0f, 1.0f, 0.0f, 1.0f, // top left corner
|
||||||
|
1.0f, -1.0f, 1.0f, 0.0f, // bottom right corner
|
||||||
|
1.0f, 1.0f, 1.0f, 1.0f // top right corner
|
||||||
|
};
|
||||||
|
GLCall(glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 16, quad_vao, GL_STATIC_DRAW));
|
||||||
|
GLuint vao = 0;
|
||||||
|
GLCall(glGenVertexArrays(1, &vao));
|
||||||
|
GLCall(glBindVertexArray(vao));
|
||||||
|
GLCall(glBindBuffer(GL_ARRAY_BUFFER, buffer));
|
||||||
|
GLCall(glEnableVertexAttribArray(0));
|
||||||
|
GLCall(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, (void*)0));
|
||||||
|
GLCall(glEnableVertexAttribArray(1));
|
||||||
|
GLCall(glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, (void*)(sizeof(float) * 2)));
|
||||||
|
|
||||||
|
Program quad_program(vertShader, fragShader);
|
||||||
|
return quad_program;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLAPIENTRY MessageCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam)
|
||||||
|
{
|
||||||
|
std::string sev = "";
|
||||||
|
if (severity == GL_DEBUG_SEVERITY_LOW)
|
||||||
|
sev = "low";
|
||||||
|
else if (severity == GL_DEBUG_SEVERITY_HIGH)
|
||||||
|
sev = "high";
|
||||||
|
else if (severity == GL_DEBUG_SEVERITY_NOTIFICATION)
|
||||||
|
return;
|
||||||
|
else if (severity == GL_DEBUG_SEVERITY_MEDIUM)
|
||||||
|
sev = "medium";
|
||||||
|
|
||||||
|
fprintf(stderr, "GL CALLBACK: %s type = %x, severity = %s, message = %s\n",
|
||||||
|
(type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : ""),
|
||||||
|
type, sev.c_str(), message);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ComputeEngine::FramebufferSizeCallback(GLFWwindow* window, int w, int h) {
|
||||||
|
if(w != 0 && h != 0)
|
||||||
|
(*m_instance).UpdateSize(w, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ComputeEngine::KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) {
|
||||||
|
(*m_instance).m_keys[key] = action;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ComputeEngine::MouseButtonCallback(GLFWwindow* window, int button, int action, int mods)
|
||||||
|
{
|
||||||
|
(*m_instance).m_mouse_buttons[button] = action;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ComputeEngine::PollEvents() {
|
||||||
|
ResetKeys();
|
||||||
|
|
||||||
|
glfwPollEvents();
|
||||||
|
|
||||||
|
for (int i = 0; i < 348; i++) {
|
||||||
|
m_keys[i] = (m_keys[i] == GLFW_PRESS && m_prev_keys[i] == GLFW_PRESS) ? GLFW_REPEAT : m_keys[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
m_mouse_buttons[i] = (m_mouse_buttons[i] == GLFW_PRESS && m_prev_mouse_buttons[i] == GLFW_PRESS) ? GLFW_REPEAT : m_mouse_buttons[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
double x_p, y_p;
|
||||||
|
glfwGetCursorPos(m_window, &x_p, &y_p);
|
||||||
|
|
||||||
|
m_dx = (float)(m_xpos - x_p) * m_input;
|
||||||
|
m_dy = (float)(m_ypos - y_p) * m_input;
|
||||||
|
m_xpos = x_p;
|
||||||
|
m_ypos = y_p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ComputeEngine::ResetKeys() {
|
||||||
|
memcpy(m_prev_keys, m_keys, sizeof(int) * 348);
|
||||||
|
memcpy(m_prev_mouse_buttons, m_mouse_buttons, sizeof(int) * 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ComputeEngine::SetFullscreen(bool fullscreen) {
|
||||||
|
m_fullscreen = fullscreen;
|
||||||
|
|
||||||
|
if (!m_fullscreen) {
|
||||||
|
m_width = m_windowed_width;
|
||||||
|
m_height = m_windowed_height;
|
||||||
|
|
||||||
|
glfwSetWindowMonitor(m_window, NULL, 200, 200, m_width, m_height, GLFW_DONT_CARE);
|
||||||
|
|
||||||
|
glViewport(0, 0, m_width, m_height);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_windowed_width = m_width;
|
||||||
|
m_windowed_height = m_height;
|
||||||
|
|
||||||
|
m_width = m_fullscreen_width;
|
||||||
|
m_height = m_fullscreen_height;
|
||||||
|
|
||||||
|
glfwSetWindowMonitor(m_window, NULL, 0, 0, m_width, m_height, GLFW_DONT_CARE);
|
||||||
|
|
||||||
|
glViewport(0, 0, m_width, m_height);
|
||||||
|
|
||||||
|
m_dx = 0;
|
||||||
|
m_dy = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ComputeEngine::SwitchFullScreen() {
|
||||||
|
SetFullscreen(!IsFullscreen());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ComputeEngine::GetWindowSize(int& width, int& height) {
|
||||||
|
width = m_width;
|
||||||
|
height = m_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ComputeEngine::IsFullscreen() {
|
||||||
|
return m_fullscreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ComputeEngine::SetInput(bool mode) {
|
||||||
|
m_input = mode;
|
||||||
|
if(!mode)
|
||||||
|
glfwSetInputMode(m_window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||||
|
else
|
||||||
|
glfwSetInputMode(m_window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ComputeEngine::UpdateSize(int width, int height) {
|
||||||
|
m_width = width;
|
||||||
|
m_height = height;
|
||||||
|
|
||||||
|
glViewport(0, 0, m_width, m_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ComputeEngine::ShouldClose() {
|
||||||
|
return glfwWindowShouldClose(m_window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ComputeEngine::CloseWindow() {
|
||||||
|
glfwSetWindowShouldClose(m_window, GLFW_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ComputeEngine::SwitchInput() {
|
||||||
|
SetInput(!m_input);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ComputeEngine::DrawTexture(Texture &texture){
|
||||||
|
m_TextureDisplay.Use();
|
||||||
|
|
||||||
|
GLCall(glMemoryBarrier(GL_ALL_BARRIER_BITS));
|
||||||
|
|
||||||
|
|
||||||
|
GLCall(glActiveTexture(GL_TEXTURE0));
|
||||||
|
GLuint boundTexture = 0;
|
||||||
|
GLCall(glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*)&boundTexture));
|
||||||
|
GLCall(glBindTexture(GL_TEXTURE_2D, texture.GetId()));
|
||||||
|
|
||||||
|
GLCall(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
||||||
|
|
||||||
|
GLCall(glBindTexture(GL_TEXTURE_2D, boundTexture));
|
||||||
|
GLCall(glfwSwapBuffers(m_window));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ComputeEngine::UpdateFrametime() {
|
||||||
|
double ms = m_timer.GetMilis();
|
||||||
|
m_frametime = m_framecount > 0 ? ms : 1;
|
||||||
|
m_time_sum += m_frametime;
|
||||||
|
|
||||||
|
m_framecount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ComputeEngine::SaveScreen(std::string name) {
|
||||||
|
bool found = true;
|
||||||
|
int i = 0;
|
||||||
|
while (found) {
|
||||||
|
i++;
|
||||||
|
std::string full_name_png = "screenshots\\" + name + std::to_string(i) + ".png";
|
||||||
|
std::string full_name_jpg = "screenshots\\" + name + std::to_string(i) + ".jpg";
|
||||||
|
found = FileExists(full_name_png) || FileExists(full_name_jpg);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* path = "screenshots";
|
||||||
|
CreateDirectoryA(path, NULL);
|
||||||
|
|
||||||
|
name = name + std::to_string(i) + ".png";
|
||||||
|
|
||||||
|
int img_size = 4 * m_width * m_height;
|
||||||
|
|
||||||
|
unsigned char* pixels = new unsigned char[img_size];
|
||||||
|
|
||||||
|
LOG("Saving screenshot: " + name);
|
||||||
|
|
||||||
|
GLCall(glReadBuffer(GL_FRONT));
|
||||||
|
GLCall(glReadPixels(0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
|
||||||
|
|
||||||
|
stbi__flip_vertically_on_write = true;
|
||||||
|
|
||||||
|
stbi_write_png(("screenshots\\" + name).c_str(), m_width, m_height, 4, pixels, m_width * 4);
|
||||||
|
|
||||||
|
delete[] pixels;
|
||||||
|
};
|
||||||
|
|
||||||
|
void ComputeEngine::Finish() {
|
||||||
|
GLCall(glFinish());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ComputeEngine::IsKeyPressed(int key) {
|
||||||
|
int state = m_keys[key];
|
||||||
|
return state == GLFW_PRESS || state == GLFW_REPEAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ComputeEngine::IsKeyClicked(int key) {
|
||||||
|
return m_keys[key] == GLFW_PRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ComputeEngine::IsMouseButtonPressed(int button) {
|
||||||
|
int state = m_mouse_buttons[button];
|
||||||
|
return state == GLFW_PRESS || state == GLFW_REPEAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ComputeEngine::IsMouseButtonClicked(int button) {
|
||||||
|
return m_prev_mouse_buttons[button] == GLFW_PRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ComputeEngine::GetMousePos(double& xpos, double& ypos) {
|
||||||
|
xpos = m_xpos;
|
||||||
|
ypos = m_ypos;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ComputeEngine::GetMouseDelta(double& dx, double& dy) {
|
||||||
|
dx = m_dx;
|
||||||
|
dy = m_dy;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ComputeEngine::GetInput() {
|
||||||
|
return m_input;
|
||||||
|
}
|
||||||
|
|
||||||
|
double ComputeEngine::GetFrametime() {
|
||||||
|
return m_frametime;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ComputeEngine::GetFramecount() {
|
||||||
|
return m_framecount;
|
||||||
|
}
|
||||||
|
|
||||||
|
double ComputeEngine::GetAverageFrametime() {
|
||||||
|
return m_time_sum / m_framecount;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ComputeEngine::GetWidth() {
|
||||||
|
return m_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ComputeEngine::GetHeight() {
|
||||||
|
return m_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
float ComputeEngine::GetRand() {
|
||||||
|
return (float)((double)rand() / (RAND_MAX));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ComputeEngine::FileExists(const std::string& name) {
|
||||||
|
struct stat buffer;
|
||||||
|
return (stat(name.c_str(), &buffer) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWwindow* ComputeEngine::GetWindow() {
|
||||||
|
return m_window;
|
||||||
|
}
|
89
src/ComputeEngine.h
Normal file
89
src/ComputeEngine.h
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
#pragma once
|
||||||
|
#define GLEW_STATIC
|
||||||
|
|
||||||
|
#include "UBO.h"
|
||||||
|
#include "GLUtils.h"
|
||||||
|
#include "SSBO.h"
|
||||||
|
#include "Texture.h"
|
||||||
|
#include "Program.h"
|
||||||
|
#include "Scene.h"
|
||||||
|
#include "Shader.h"
|
||||||
|
#include "Timer.h"
|
||||||
|
|
||||||
|
class ComputeEngine {
|
||||||
|
public:
|
||||||
|
ComputeEngine(int w, int h, std::string name, bool focus = true, bool tonemapping = false);
|
||||||
|
~ComputeEngine();
|
||||||
|
|
||||||
|
GLFWwindow* InitWindow(int width, int height, std::string name, bool focus);
|
||||||
|
|
||||||
|
void UpdateFrametime();
|
||||||
|
void CloseWindow();
|
||||||
|
void SwitchInput();
|
||||||
|
void SetInput(bool mode);
|
||||||
|
void PollEvents();
|
||||||
|
void GetMousePos(double& xpos, double& ypos);
|
||||||
|
void GetMouseDelta(double& dx, double& dy);
|
||||||
|
void SaveScreen(std::string name);
|
||||||
|
void ResetKeys();
|
||||||
|
void SetFullscreen(bool fullscreen);
|
||||||
|
void SwitchFullScreen();
|
||||||
|
void GetWindowSize(int& width, int& height);
|
||||||
|
void DrawTexture(Texture& texture);
|
||||||
|
void Finish();
|
||||||
|
|
||||||
|
bool IsFullscreen();
|
||||||
|
bool GetInput();
|
||||||
|
bool ShouldClose();
|
||||||
|
bool IsKeyPressed(int key);
|
||||||
|
bool IsKeyClicked(int key);
|
||||||
|
bool IsMouseButtonPressed(int button);
|
||||||
|
bool IsMouseButtonClicked(int button);
|
||||||
|
bool FileExists(const std::string& name);
|
||||||
|
|
||||||
|
double GetFrametime();
|
||||||
|
double GetAverageFrametime();
|
||||||
|
|
||||||
|
int GetWidth();
|
||||||
|
int GetHeight();
|
||||||
|
int GetFramecount();
|
||||||
|
|
||||||
|
float GetRand();
|
||||||
|
|
||||||
|
GLFWwindow* GetWindow();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Program m_TextureDisplay;
|
||||||
|
Timer m_timer;
|
||||||
|
GLFWwindow* m_window;
|
||||||
|
|
||||||
|
|
||||||
|
Program InitQuad(Shader& vertShader, Shader& fragShader);
|
||||||
|
|
||||||
|
double m_frametime = 0;
|
||||||
|
double m_time_sum = 0;
|
||||||
|
|
||||||
|
int m_keys[348];
|
||||||
|
int m_prev_keys[348];
|
||||||
|
int m_mouse_buttons[8];
|
||||||
|
int m_prev_mouse_buttons[8];
|
||||||
|
|
||||||
|
bool m_fullscreen = false;
|
||||||
|
|
||||||
|
bool m_input = false;
|
||||||
|
|
||||||
|
int m_framecount = 0;
|
||||||
|
int m_width, m_height;
|
||||||
|
int m_windowed_width, m_windowed_height;
|
||||||
|
|
||||||
|
double m_xpos = 0, m_ypos = 0;
|
||||||
|
float m_dx = 0, m_dy = 0;
|
||||||
|
|
||||||
|
int m_fullscreen_width = 1920;
|
||||||
|
int m_fullscreen_height = 1080;
|
||||||
|
|
||||||
|
static void FramebufferSizeCallback(GLFWwindow* window, int width, int height);
|
||||||
|
static void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
|
||||||
|
static void MouseButtonCallback(GLFWwindow* window, int button, int action, int mods);
|
||||||
|
void UpdateSize(int w, int h);
|
||||||
|
};
|
75
src/GLUtils.cpp
Normal file
75
src/GLUtils.cpp
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "GLUtils.h"
|
||||||
|
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
using std::cout;
|
||||||
|
using std::endl;
|
||||||
|
|
||||||
|
bool glErrorCheck() {
|
||||||
|
bool no_err = true;
|
||||||
|
|
||||||
|
GLenum error = glGetError();
|
||||||
|
while (error) {
|
||||||
|
std::string err_str;
|
||||||
|
switch (error) {
|
||||||
|
case GL_NO_ERROR:
|
||||||
|
err_str = "GL_NO_ERROR";
|
||||||
|
break;
|
||||||
|
case GL_INVALID_ENUM:
|
||||||
|
err_str = "GL_INVALID_ENUM";
|
||||||
|
break;
|
||||||
|
case GL_INVALID_VALUE:
|
||||||
|
err_str = "GL_INVALID_VALUE";
|
||||||
|
break;
|
||||||
|
case GL_INVALID_OPERATION:
|
||||||
|
err_str = "GL_INVALID_OPERATION";
|
||||||
|
break;
|
||||||
|
case GL_INVALID_FRAMEBUFFER_OPERATION:
|
||||||
|
err_str = "GL_INVALID_FRAMEBUFFER_OPERATION";
|
||||||
|
break;
|
||||||
|
case GL_OUT_OF_MEMORY:
|
||||||
|
err_str = "GL_OUT_OF_MEMORY";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
err_str = "GL_UNKNOWN_ERROR";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cout << err_str << endl;
|
||||||
|
|
||||||
|
error = glGetError();
|
||||||
|
|
||||||
|
no_err = false;
|
||||||
|
return no_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return no_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
void glClearError() {
|
||||||
|
while (glGetError() != GL_NO_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintSizeLimits() {
|
||||||
|
GLint size;
|
||||||
|
GLint size2;
|
||||||
|
|
||||||
|
glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &size);
|
||||||
|
std::cout << "GL_MAX_TEXTURE_BUFFER_SIZE is " << ((float)size * 32.0f / 1073741824.0f) << " GB" << endl;
|
||||||
|
glGetIntegerv(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, &size);
|
||||||
|
std::cout << "GL_MAX_SHADER_STORAGE_BLOCK_SIZE is " << ((float)size / 1073741824.0f) << " GB" << endl;
|
||||||
|
glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &size);
|
||||||
|
std::cout << "GL_MAX_UNIFORM_BLOCK_SIZE is " << ((float)size / 1024.0f) << " KB" << endl;
|
||||||
|
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &size);
|
||||||
|
std::cout << "GL_MAX_TEXTURE_SIZE is " << ((float)size / 1024.0f) << " MB" << endl;
|
||||||
|
glGetIntegerv(GL_MAX_IMAGE_UNITS, &size);
|
||||||
|
std::cout << "GL_MAX_IMAGE_UNITS is " << size << endl;
|
||||||
|
glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 0, &size);
|
||||||
|
glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 1, &size2);
|
||||||
|
std::cout << "GL_MAX_COMPUTE_WORK_GROUP_SIZE is " << size << ", " << size2 << endl;
|
||||||
|
}
|
29
src/GLUtils.h
Normal file
29
src/GLUtils.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define __FILENAME__ (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)
|
||||||
|
|
||||||
|
#define ASSERT(x) if(!(x)){ std::cout << "[ERROR] " << #x << '\n';\
|
||||||
|
__debugbreak();}
|
||||||
|
|
||||||
|
#define GLCall(x) \
|
||||||
|
glClearError();\
|
||||||
|
x;\
|
||||||
|
if(!(glErrorCheck())){ std::cout << "[ERROR] " << #x << '\n';\
|
||||||
|
__debugbreak();}
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
#define LOG(msg) \
|
||||||
|
std::cout << '[' << __TIME__ << "] Renderer: " << msg << std::endl
|
||||||
|
#else
|
||||||
|
#define LOG(msg) \
|
||||||
|
std::cout << __FILENAME__ << "(" << __LINE__ << "): " << msg << std::endl
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void PrintSizeLimits();
|
||||||
|
bool glErrorCheck();
|
||||||
|
void glClearError();
|
428
src/Program.cpp
Normal file
428
src/Program.cpp
Normal file
@ -0,0 +1,428 @@
|
|||||||
|
#include "Program.h"
|
||||||
|
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
#include "GLUtils.h"
|
||||||
|
#include "Texture.h"
|
||||||
|
#include "Shader.h"
|
||||||
|
|
||||||
|
Program::Program() :
|
||||||
|
m_id(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Program::Program(unsigned int _id) :
|
||||||
|
m_id(_id)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Program::Program(Shader& vertShader, Shader& fragShader) {
|
||||||
|
unsigned int program;
|
||||||
|
GLCall(program = glCreateProgram());
|
||||||
|
|
||||||
|
GLCall(glAttachShader(program, vertShader.GetId()));
|
||||||
|
GLCall(glAttachShader(program, fragShader.GetId()));
|
||||||
|
GLCall(glLinkProgram(program));
|
||||||
|
GLCall(glValidateProgram(program));
|
||||||
|
|
||||||
|
m_id = program;
|
||||||
|
}
|
||||||
|
|
||||||
|
Program::~Program() {
|
||||||
|
Delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Program::Program(Program&& other) :
|
||||||
|
m_id(other.m_id)
|
||||||
|
{
|
||||||
|
other.m_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Program& Program::operator=(Program&& other)
|
||||||
|
{
|
||||||
|
if (this != &other)
|
||||||
|
{
|
||||||
|
Delete();
|
||||||
|
std::swap(m_id, other.m_id);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Program::Program(Shader& computeShader) {
|
||||||
|
unsigned int program;
|
||||||
|
GLCall(program = glCreateProgram());
|
||||||
|
|
||||||
|
GLCall(glAttachShader(program, computeShader.GetId()));
|
||||||
|
GLCall(glLinkProgram(program));
|
||||||
|
GLCall(glValidateProgram(program));
|
||||||
|
|
||||||
|
m_id = program;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Program::Delete() {
|
||||||
|
if (m_id != 0) {
|
||||||
|
GLCall(glDeleteProgram(m_id));
|
||||||
|
}
|
||||||
|
m_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Program::DispatchCompute(int width, int height) {
|
||||||
|
Use();
|
||||||
|
|
||||||
|
int up_w = int(ceil((float)width / 8.0f));
|
||||||
|
int up_h = int(ceil((float)height / 8.0f));
|
||||||
|
GLCall(glDispatchCompute(up_w, up_h, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Program::DispatchCompute(int x) {
|
||||||
|
Use();
|
||||||
|
|
||||||
|
GLCall(glDispatchCompute(x, 1, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Program::Use() {
|
||||||
|
GLCall(glUseProgram(m_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Program::BindTexture(Texture& texture, int slot) {
|
||||||
|
Use();
|
||||||
|
|
||||||
|
int location;
|
||||||
|
GLCall(location = glGetUniformLocation(m_id, texture.GetName().c_str()));
|
||||||
|
|
||||||
|
ASSERT(location != -1);
|
||||||
|
|
||||||
|
Use();
|
||||||
|
GLCall(glUniform1i(location, slot));
|
||||||
|
texture.Bind(slot);
|
||||||
|
}
|
||||||
|
void Program::BindTexture(Texture* texture, int slot) {
|
||||||
|
Use();
|
||||||
|
|
||||||
|
int location;
|
||||||
|
GLCall(location = glGetUniformLocation(m_id, texture->GetName().c_str()));
|
||||||
|
|
||||||
|
ASSERT(location != -1);
|
||||||
|
|
||||||
|
Use();
|
||||||
|
GLCall(glUniform1i(location, slot));
|
||||||
|
texture->Bind(slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Program::BindTexture(Texture& texture, int slot, std::string name) {
|
||||||
|
Use();
|
||||||
|
|
||||||
|
int location;
|
||||||
|
GLCall(location = glGetUniformLocation(m_id, name.c_str()));
|
||||||
|
|
||||||
|
ASSERT(location != -1);
|
||||||
|
|
||||||
|
GLCall(glUniform1i(location, slot));
|
||||||
|
texture.Bind(slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Program::BindTextureImage(Texture& texture, int slot) {
|
||||||
|
Use();
|
||||||
|
|
||||||
|
int location;
|
||||||
|
GLCall(location = glGetUniformLocation(m_id, texture.GetName().c_str()));
|
||||||
|
|
||||||
|
ASSERT(location != -1);
|
||||||
|
|
||||||
|
GLCall(glUniform1i(location, slot));
|
||||||
|
texture.BindImage(slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int Program::GetId() {
|
||||||
|
return m_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Program::SetUniform1f(std::string name, float u) {
|
||||||
|
Use();
|
||||||
|
|
||||||
|
int location;
|
||||||
|
|
||||||
|
GLCall(location = glGetUniformLocation(m_id, name.c_str()));
|
||||||
|
|
||||||
|
ASSERT(location != -1);
|
||||||
|
|
||||||
|
GLCall(glUniform1f(location, u));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Program::SetUniform2f(std::string name, float u1, float u2) {
|
||||||
|
Use();
|
||||||
|
|
||||||
|
int location;
|
||||||
|
|
||||||
|
GLCall(location = glGetUniformLocation(m_id, name.c_str()));
|
||||||
|
|
||||||
|
ASSERT(location != -1);
|
||||||
|
|
||||||
|
GLCall(glUniform2f(location, u1, u2));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Program::SetUniform3f(std::string name, float u1, float u2, float u3) {
|
||||||
|
Use();
|
||||||
|
|
||||||
|
int location;
|
||||||
|
|
||||||
|
GLCall(location = glGetUniformLocation(m_id, name.c_str()));
|
||||||
|
|
||||||
|
ASSERT(location != -1);
|
||||||
|
|
||||||
|
GLCall(glUniform3f(location, u1, u2, u3));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Program::SetUniform4f(std::string name, float u1, float u2, float u3, float u4) {
|
||||||
|
Use();
|
||||||
|
|
||||||
|
int location;
|
||||||
|
|
||||||
|
GLCall(location = glGetUniformLocation(m_id, name.c_str()));
|
||||||
|
|
||||||
|
ASSERT(location != -1);
|
||||||
|
|
||||||
|
GLCall(glUniform4f(location, u1, u2, u3, u4));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Program::SetUniform1i(std::string name, int u) {
|
||||||
|
Use();
|
||||||
|
|
||||||
|
int location;
|
||||||
|
|
||||||
|
GLCall(location = glGetUniformLocation(m_id, name.c_str()));
|
||||||
|
|
||||||
|
ASSERT(location != -1);
|
||||||
|
|
||||||
|
GLCall(glUniform1i(location, u));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Program::SetUniform2i(std::string name, int u1, int u2) {
|
||||||
|
Use();
|
||||||
|
|
||||||
|
int location;
|
||||||
|
|
||||||
|
GLCall(location = glGetUniformLocation(m_id, name.c_str()));
|
||||||
|
|
||||||
|
ASSERT(location != -1);
|
||||||
|
|
||||||
|
GLCall(glUniform2i(location, u1, u2));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Program::SetUniform3i(std::string name, int u1, int u2, int u3) {
|
||||||
|
Use();
|
||||||
|
|
||||||
|
int location;
|
||||||
|
|
||||||
|
GLCall(location = glGetUniformLocation(m_id, name.c_str()));
|
||||||
|
|
||||||
|
ASSERT(location != -1);
|
||||||
|
|
||||||
|
GLCall(glUniform3i(location, u1, u2, u3));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Program::SetUniform4i(std::string name, int u1, int u2, int u3, int u4) {
|
||||||
|
Use();
|
||||||
|
|
||||||
|
int location;
|
||||||
|
|
||||||
|
GLCall(location = glGetUniformLocation(m_id, name.c_str()));
|
||||||
|
|
||||||
|
ASSERT(location != -1);
|
||||||
|
|
||||||
|
GLCall(glUniform4i(location, u1, u2, u3, u4));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Program::SetUniform1ui(std::string name, unsigned int u) {
|
||||||
|
Use();
|
||||||
|
|
||||||
|
int location;
|
||||||
|
|
||||||
|
GLCall(location = glGetUniformLocation(m_id, name.c_str()));
|
||||||
|
|
||||||
|
ASSERT(location != -1);
|
||||||
|
|
||||||
|
GLCall(glUniform1ui(location, u));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Program::SetUniform2ui(std::string name, unsigned int u1, unsigned int u2) {
|
||||||
|
Use();
|
||||||
|
|
||||||
|
int location;
|
||||||
|
|
||||||
|
GLCall(location = glGetUniformLocation(m_id, name.c_str()));
|
||||||
|
|
||||||
|
ASSERT(location != -1);
|
||||||
|
|
||||||
|
GLCall(glUniform2ui(location, u1, u2));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Program::SetUniform3ui(std::string name, unsigned int u1, unsigned int u2, unsigned int u3) {
|
||||||
|
Use();
|
||||||
|
|
||||||
|
int location;
|
||||||
|
|
||||||
|
GLCall(location = glGetUniformLocation(m_id, name.c_str()));
|
||||||
|
|
||||||
|
ASSERT(location != -1);
|
||||||
|
|
||||||
|
GLCall(glUniform3ui(location, u1, u2, u3));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Program::SetUniform4ui(std::string name, unsigned int u1, unsigned int u2, unsigned int u3, unsigned int u4) {
|
||||||
|
Use();
|
||||||
|
|
||||||
|
int location;
|
||||||
|
|
||||||
|
GLCall(location = glGetUniformLocation(m_id, name.c_str()));
|
||||||
|
|
||||||
|
ASSERT(location != -1);
|
||||||
|
|
||||||
|
GLCall(glUniform4ui(location, u1, u2, u3, u4));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Program::SetUniform1fv(std::string name, int count, float* u) {
|
||||||
|
Use();
|
||||||
|
|
||||||
|
int location;
|
||||||
|
|
||||||
|
GLCall(location = glGetUniformLocation(m_id, name.c_str()));
|
||||||
|
|
||||||
|
ASSERT(location != -1);
|
||||||
|
|
||||||
|
GLCall(glUniform1fv(location, count, u));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Program::SetUniform2fv(std::string name, int count, float* u) {
|
||||||
|
Use();
|
||||||
|
|
||||||
|
int location;
|
||||||
|
|
||||||
|
GLCall(location = glGetUniformLocation(m_id, name.c_str()));
|
||||||
|
|
||||||
|
ASSERT(location != -1);
|
||||||
|
|
||||||
|
GLCall(glUniform2fv(location, count, u));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Program::SetUniform3fv(std::string name, int count, float* u) {
|
||||||
|
Use();
|
||||||
|
|
||||||
|
int location;
|
||||||
|
|
||||||
|
GLCall(location = glGetUniformLocation(m_id, name.c_str()));
|
||||||
|
|
||||||
|
ASSERT(location != -1);
|
||||||
|
|
||||||
|
GLCall(glUniform3fv(location, count, u));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Program::SetUniform4fv(std::string name, int count, float* u) {
|
||||||
|
Use();
|
||||||
|
|
||||||
|
int location;
|
||||||
|
|
||||||
|
GLCall(location = glGetUniformLocation(m_id, name.c_str()));
|
||||||
|
|
||||||
|
ASSERT(location != -1);
|
||||||
|
|
||||||
|
GLCall(glUniform4fv(location, count, u));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Program::SetUniform1iv(std::string name, int count, int* u) {
|
||||||
|
Use();
|
||||||
|
|
||||||
|
int location;
|
||||||
|
|
||||||
|
GLCall(location = glGetUniformLocation(m_id, name.c_str()));
|
||||||
|
|
||||||
|
ASSERT(location != -1);
|
||||||
|
|
||||||
|
GLCall(glUniform1iv(location, count, u));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Program::SetUniform2iv(std::string name, int count, int* u) {
|
||||||
|
Use();
|
||||||
|
|
||||||
|
int location;
|
||||||
|
|
||||||
|
GLCall(location = glGetUniformLocation(m_id, name.c_str()));
|
||||||
|
|
||||||
|
ASSERT(location != -1);
|
||||||
|
|
||||||
|
GLCall(glUniform2iv(location, count, u));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Program::SetUniform3iv(std::string name, int count, int* u) {
|
||||||
|
Use();
|
||||||
|
|
||||||
|
int location;
|
||||||
|
|
||||||
|
GLCall(location = glGetUniformLocation(m_id, name.c_str()));
|
||||||
|
|
||||||
|
ASSERT(location != -1);
|
||||||
|
|
||||||
|
GLCall(glUniform3iv(location, count, u));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Program::SetUniform4iv(std::string name, int count, int* u) {
|
||||||
|
Use();
|
||||||
|
|
||||||
|
int location;
|
||||||
|
|
||||||
|
GLCall(location = glGetUniformLocation(m_id, name.c_str()));
|
||||||
|
|
||||||
|
ASSERT(location != -1);
|
||||||
|
|
||||||
|
GLCall(glUniform4iv(location, count, u));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Program::SetUniform1uiv(std::string name, int count, unsigned int* u) {
|
||||||
|
Use();
|
||||||
|
|
||||||
|
int location;
|
||||||
|
|
||||||
|
GLCall(location = glGetUniformLocation(m_id, name.c_str()));
|
||||||
|
|
||||||
|
ASSERT(location != -1);
|
||||||
|
|
||||||
|
GLCall(glUniform1uiv(location, count, u));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Program::SetUniform2uiv(std::string name, int count, unsigned int* u) {
|
||||||
|
Use();
|
||||||
|
|
||||||
|
int location;
|
||||||
|
|
||||||
|
GLCall(location = glGetUniformLocation(m_id, name.c_str()));
|
||||||
|
|
||||||
|
ASSERT(location != -1);
|
||||||
|
|
||||||
|
GLCall(glUniform2uiv(location, count, u));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Program::SetUniform3uiv(std::string name, int count, unsigned int* u) {
|
||||||
|
Use();
|
||||||
|
|
||||||
|
int location;
|
||||||
|
|
||||||
|
GLCall(location = glGetUniformLocation(m_id, name.c_str()));
|
||||||
|
|
||||||
|
ASSERT(location != -1);
|
||||||
|
|
||||||
|
GLCall(glUniform3uiv(location, count, u));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Program::SetUniform4uiv(std::string name, int count, unsigned int* u) {
|
||||||
|
Use();
|
||||||
|
|
||||||
|
int location;
|
||||||
|
|
||||||
|
GLCall(location = glGetUniformLocation(m_id, name.c_str()));
|
||||||
|
|
||||||
|
ASSERT(location != -1);
|
||||||
|
|
||||||
|
GLCall(glUniform4uiv(location, count, u));
|
||||||
|
}
|
61
src/Program.h
Normal file
61
src/Program.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Shader.h"
|
||||||
|
#include "Texture.h"
|
||||||
|
|
||||||
|
class Program {
|
||||||
|
private:
|
||||||
|
unsigned int m_id = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Program();
|
||||||
|
~Program();
|
||||||
|
Program(unsigned int id);
|
||||||
|
Program(Shader& vertShader, Shader& fragShader);
|
||||||
|
Program(Shader& computeShader);
|
||||||
|
|
||||||
|
Program& operator=(Program&& other);
|
||||||
|
Program(Program&& other);
|
||||||
|
Program(const Program&) = delete;
|
||||||
|
Program& operator=(const Program&) = delete;
|
||||||
|
|
||||||
|
void Delete();
|
||||||
|
|
||||||
|
void Use();
|
||||||
|
void DispatchCompute(int width, int height);
|
||||||
|
void DispatchCompute(int x);
|
||||||
|
void BindTexture(Texture& texture, int slot);
|
||||||
|
void BindTexture(Texture* texture, int slot);
|
||||||
|
void BindTexture(Texture& texture, int slot, std::string name);
|
||||||
|
void BindTextureImage(Texture& texture, int slot);
|
||||||
|
unsigned int GetId();
|
||||||
|
|
||||||
|
void SetUniform1f(std::string name, float u);
|
||||||
|
void SetUniform2f(std::string name, float u1, float u2);
|
||||||
|
void SetUniform3f(std::string name, float u1, float u2, float u3);
|
||||||
|
void SetUniform4f(std::string name, float u1, float u2, float u3, float u4);
|
||||||
|
|
||||||
|
void SetUniform1i(std::string name, int u);
|
||||||
|
void SetUniform2i(std::string name, int u1, int u2);
|
||||||
|
void SetUniform3i(std::string name, int u1, int u2, int u3);
|
||||||
|
void SetUniform4i(std::string name, int u1, int u2, int u3, int u4);
|
||||||
|
|
||||||
|
void SetUniform1ui(std::string name, unsigned int u);
|
||||||
|
void SetUniform2ui(std::string name, unsigned int u1, unsigned int u2);
|
||||||
|
void SetUniform3ui(std::string name, unsigned int u1, unsigned int u2, unsigned int u3);
|
||||||
|
void SetUniform4ui(std::string name, unsigned int u1, unsigned int u2, unsigned int u3, unsigned int u4);
|
||||||
|
|
||||||
|
void SetUniform1fv(std::string name, int count, float* u);
|
||||||
|
void SetUniform2fv(std::string name, int count, float* u);
|
||||||
|
void SetUniform3fv(std::string name, int count, float* u);
|
||||||
|
void SetUniform4fv(std::string name, int count, float* u);
|
||||||
|
|
||||||
|
void SetUniform1iv(std::string name, int count, int* u);
|
||||||
|
void SetUniform2iv(std::string name, int count, int* u);
|
||||||
|
void SetUniform3iv(std::string name, int count, int* u);
|
||||||
|
void SetUniform4iv(std::string name, int count, int* u);
|
||||||
|
|
||||||
|
void SetUniform1uiv(std::string name, int count, unsigned int* u);
|
||||||
|
void SetUniform2uiv(std::string name, int count, unsigned int* u);
|
||||||
|
void SetUniform3uiv(std::string name, int count, unsigned int* u);
|
||||||
|
void SetUniform4uiv(std::string name, int count, unsigned int* u);
|
||||||
|
};
|
58
src/SSBO.cpp
Normal file
58
src/SSBO.cpp
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#include "SSBO.h"
|
||||||
|
#include "GLUtils.h"
|
||||||
|
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
SSBO::SSBO(int bind) :
|
||||||
|
m_id(0), m_binding(bind), m_last_size(0)
|
||||||
|
{
|
||||||
|
GLCall(glGenBuffers(1, &m_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
SSBO::SSBO() :
|
||||||
|
m_id(0), m_binding(0), m_last_size(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SSBO::SSBO(unsigned int i, int bind) :
|
||||||
|
m_id(i), m_binding(bind), m_last_size(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
SSBO::~SSBO() {
|
||||||
|
Delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
int SSBO::GetId()
|
||||||
|
{
|
||||||
|
return m_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
SSBO::SSBO(SSBO&& other) :
|
||||||
|
m_id(other.m_id), m_binding(other.m_binding), m_last_size(other.m_last_size)
|
||||||
|
{
|
||||||
|
other.m_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SSBO& SSBO::operator=(SSBO&& other)
|
||||||
|
{
|
||||||
|
if (this != &other)
|
||||||
|
{
|
||||||
|
Delete();
|
||||||
|
std::swap(m_id, other.m_id);
|
||||||
|
m_binding = other.m_binding;
|
||||||
|
m_last_size = other.m_last_size;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSBO::Delete() {
|
||||||
|
if (m_id != 0) {
|
||||||
|
GLCall(glDeleteBuffers(1, &m_id));
|
||||||
|
}
|
||||||
|
m_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSBO::Bind() {
|
||||||
|
GLCall(glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_id));
|
||||||
|
}
|
76
src/SSBO.h
Normal file
76
src/SSBO.h
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <vector>
|
||||||
|
#include "GLUtils.h"
|
||||||
|
|
||||||
|
class SSBO {
|
||||||
|
private:
|
||||||
|
unsigned int m_id;
|
||||||
|
int m_binding;
|
||||||
|
int m_last_size;
|
||||||
|
public:
|
||||||
|
|
||||||
|
SSBO(int bind);
|
||||||
|
SSBO();
|
||||||
|
SSBO(unsigned int i, int bind);
|
||||||
|
SSBO& operator=(SSBO&& other);
|
||||||
|
SSBO(SSBO&& other);
|
||||||
|
SSBO(const SSBO&) = delete;
|
||||||
|
SSBO& operator=(const SSBO&) = delete;
|
||||||
|
~SSBO();
|
||||||
|
int GetId();
|
||||||
|
void Delete();
|
||||||
|
void Bind();
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void Set(T shader_data) {
|
||||||
|
int size = sizeof(shader_data);
|
||||||
|
|
||||||
|
m_last_size = size;
|
||||||
|
|
||||||
|
Bind();
|
||||||
|
GLCall(glBufferData(GL_SHADER_STORAGE_BUFFER, size, size > 0 ? &shader_data : nullptr, GL_DYNAMIC_DRAW));
|
||||||
|
|
||||||
|
GLCall(glBindBufferBase(GL_SHADER_STORAGE_BUFFER, m_binding, m_id));
|
||||||
|
}
|
||||||
|
template<typename T>
|
||||||
|
void Set(std::vector<T>* shader_data) {
|
||||||
|
int size = sizeof(T) * (int)shader_data->size();
|
||||||
|
|
||||||
|
m_last_size = size;
|
||||||
|
|
||||||
|
Bind();
|
||||||
|
GLCall(glBufferData(GL_SHADER_STORAGE_BUFFER, size, size > 0 ? shader_data->data() : nullptr, GL_DYNAMIC_DRAW));
|
||||||
|
|
||||||
|
GLCall(glBindBufferBase(GL_SHADER_STORAGE_BUFFER, m_binding, m_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void Update(T shader_data) {
|
||||||
|
int size = sizeof(shader_data);
|
||||||
|
|
||||||
|
Bind();
|
||||||
|
if (size == m_last_size) {
|
||||||
|
GLCall(glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, size, &shader_data));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_last_size = size;
|
||||||
|
GLCall(glBufferData(GL_SHADER_STORAGE_BUFFER, size, &shader_data, GL_DYNAMIC_DRAW));
|
||||||
|
GLCall(glBindBufferBase(GL_SHADER_STORAGE_BUFFER, m_binding, m_id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template<typename T>
|
||||||
|
void Update(std::vector<T>* shader_data) {
|
||||||
|
int size = sizeof(T) * shader_data->size();
|
||||||
|
|
||||||
|
Bind();
|
||||||
|
if (size == m_last_size) {
|
||||||
|
GLCall(glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, size, size > 0 ? shader_data->data() : nullptr));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_last_size = size;
|
||||||
|
GLCall(glBufferData(GL_SHADER_STORAGE_BUFFER, size, size > 0 ? shader_data->data() : nullptr, GL_DYNAMIC_DRAW));
|
||||||
|
GLCall(glBindBufferBase(GL_SHADER_STORAGE_BUFFER, m_binding, m_id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
311
src/Scene.cpp
Normal file
311
src/Scene.cpp
Normal file
@ -0,0 +1,311 @@
|
|||||||
|
#include "Scene.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
void IndexArray::AddVertex(int x, int y, int z) {
|
||||||
|
m_array.push_back(x - 1);
|
||||||
|
m_array.push_back(y - 1);
|
||||||
|
m_array.push_back(z - 1);
|
||||||
|
m_array.push_back(0);
|
||||||
|
m_array.push_back(0);
|
||||||
|
m_array.push_back(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IndexArray::AddVertex(int x, int y, int z, int tx, int ty, int tz) {
|
||||||
|
m_array.push_back(x - 1);
|
||||||
|
m_array.push_back(y - 1);
|
||||||
|
m_array.push_back(z - 1);
|
||||||
|
m_array.push_back(tx - 1);
|
||||||
|
m_array.push_back(ty - 1);
|
||||||
|
m_array.push_back(tz - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int IndexArray::GetSize() {
|
||||||
|
return (int)m_array.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
int IndexArray::GetByteSize() {
|
||||||
|
return (int)m_array.size() * (int)sizeof(int);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<int>* IndexArray::GetPointer() {
|
||||||
|
return &m_array;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<int> IndexArray::GetVector() {
|
||||||
|
return m_array;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IndexArray::MoveIndices(int offset) {
|
||||||
|
int size = (int)m_array.size();
|
||||||
|
const int block_size = 6;
|
||||||
|
for (int i = 0; i < size / block_size; i++) {
|
||||||
|
m_array[block_size *i] += offset;
|
||||||
|
m_array[block_size *i + 1] += offset;
|
||||||
|
m_array[block_size *i + 2] += offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IndexArray::MoveTextureIndices(int offset){
|
||||||
|
int size = (int)m_array.size();
|
||||||
|
const int block_size = 6;
|
||||||
|
for (int i = 0; i < size / block_size; i++) {
|
||||||
|
m_array[block_size * i + 3] += offset;
|
||||||
|
m_array[block_size * i + 4] += offset;
|
||||||
|
m_array[block_size * i + 5] += offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VertexArray::AddVertex(float x, float y, float z) {
|
||||||
|
m_array.push_back(x);
|
||||||
|
m_array.push_back(y);
|
||||||
|
m_array.push_back(z);
|
||||||
|
}
|
||||||
|
|
||||||
|
int VertexArray::GetSize() {
|
||||||
|
return (int)m_array.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
int VertexArray::GetByteSize() {
|
||||||
|
return (int)m_array.size() * (int)sizeof(float);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<float>* VertexArray::GetPointer() {
|
||||||
|
return &m_array;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<float> VertexArray::GetVector() {
|
||||||
|
return m_array;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextureVertexArray::AddVertex(float u, float v) {
|
||||||
|
m_array.push_back(u);
|
||||||
|
m_array.push_back(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
int TextureVertexArray::GetSize() {
|
||||||
|
return (int)m_array.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
int TextureVertexArray::GetByteSize() {
|
||||||
|
return (int)m_array.size() * (int)sizeof(float);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<float>* TextureVertexArray::GetPointer() {
|
||||||
|
return &m_array;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<float> TextureVertexArray::GetVector() {
|
||||||
|
return m_array;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneVertices::AddModel(Model3D* model) {
|
||||||
|
int size = model->GetIndexArrayPtr()->GetSize() / 6;
|
||||||
|
m_offsets.push_back(size + m_index_count);
|
||||||
|
|
||||||
|
m_models.push_back(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneVertices::FillBuffers() {
|
||||||
|
int size = (int)m_models.size();
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
m_models[i]->GetIndexArrayPtr()->MoveIndices(m_vertex_count);
|
||||||
|
m_models[i]->GetIndexArrayPtr()->MoveTextureIndices(m_texture_vertex_count);
|
||||||
|
m_models[i]->SetIndexOffset(m_index_count);
|
||||||
|
|
||||||
|
m_vertex_buffer.insert(m_vertex_buffer.end(),
|
||||||
|
m_models[i]->GetVertexArrayPtr()->GetPointer()->begin(),
|
||||||
|
m_models[i]->GetVertexArrayPtr()->GetPointer()->end());
|
||||||
|
|
||||||
|
m_texture_buffer.insert(m_texture_buffer.end(),
|
||||||
|
m_models[i]->GetTextureArrayPtr()->GetPointer()->begin(),
|
||||||
|
m_models[i]->GetTextureArrayPtr()->GetPointer()->end());
|
||||||
|
|
||||||
|
m_index_buffer.insert(m_index_buffer.end(),
|
||||||
|
m_models[i]->GetIndexArrayPtr()->GetPointer()->begin(),
|
||||||
|
m_models[i]->GetIndexArrayPtr()->GetPointer()->end());
|
||||||
|
|
||||||
|
m_vertex_count += m_models[i]->GetVertexArrayPtr()->GetSize() / 3;
|
||||||
|
m_texture_vertex_count += m_models[i]->GetTextureArrayPtr()->GetSize() / 2;
|
||||||
|
m_index_count += m_models[i]->GetIndexArrayPtr()->GetSize() / 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<float>* SceneVertices::GetVertexBuffer() {
|
||||||
|
return &m_vertex_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<float>* SceneVertices::GetTextureBuffer() {
|
||||||
|
return &m_texture_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<int>* SceneVertices::GetIndexBuffer() {
|
||||||
|
return &m_index_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SceneVertices::GetFaceCount() {
|
||||||
|
return m_index_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SceneVertices::GetTextureVertsCount() {
|
||||||
|
return m_texture_vertex_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SceneVertices::GetVertexCount() {
|
||||||
|
return m_vertex_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Model3D::Load(std::string path) {
|
||||||
|
std::fstream file(path);
|
||||||
|
|
||||||
|
std::string line;
|
||||||
|
std::stringstream str;
|
||||||
|
|
||||||
|
std::string prefix;
|
||||||
|
|
||||||
|
int vertex_id = 0;
|
||||||
|
|
||||||
|
float x, y, z;
|
||||||
|
while (std::getline(file, line)) {
|
||||||
|
str.clear();
|
||||||
|
str.str(line);
|
||||||
|
str >> prefix;
|
||||||
|
if (prefix == "v") {
|
||||||
|
str >> x >> y >> z;
|
||||||
|
|
||||||
|
if (m_vertex_arr.GetSize() == 0)
|
||||||
|
m_lowest_point = y;
|
||||||
|
else
|
||||||
|
m_lowest_point = std::min(m_lowest_point, y);
|
||||||
|
|
||||||
|
m_vertex_arr.AddVertex(x, y, z);
|
||||||
|
}
|
||||||
|
else if (prefix == "vt") {
|
||||||
|
str >> x >> y;
|
||||||
|
|
||||||
|
m_texture_arr.AddVertex(x, y);
|
||||||
|
}
|
||||||
|
else if (prefix == "f") {
|
||||||
|
int f;
|
||||||
|
int v1 = 0;
|
||||||
|
int v2 = 0;
|
||||||
|
int v3 = 0;
|
||||||
|
int v4 = 0;
|
||||||
|
|
||||||
|
int vt1 = 0;
|
||||||
|
int vt2 = 0;
|
||||||
|
int vt3 = 0;
|
||||||
|
int vt4 = 0;
|
||||||
|
|
||||||
|
int type_counter = 0;
|
||||||
|
int id_counter = 0;
|
||||||
|
|
||||||
|
while (str >> f) {
|
||||||
|
|
||||||
|
|
||||||
|
if (type_counter == 0) {
|
||||||
|
if (id_counter == 0) {
|
||||||
|
v1 = f;
|
||||||
|
}
|
||||||
|
else if (id_counter == 1) {
|
||||||
|
v2 = f;
|
||||||
|
}
|
||||||
|
else if (id_counter == 2) {
|
||||||
|
v3 = f;
|
||||||
|
}
|
||||||
|
else if (id_counter == 3) {
|
||||||
|
v4 = f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type_counter == 1) {
|
||||||
|
if (id_counter == 0) {
|
||||||
|
vt1 = f;
|
||||||
|
}
|
||||||
|
else if (id_counter == 1) {
|
||||||
|
vt2 = f;
|
||||||
|
}
|
||||||
|
else if (id_counter == 2) {
|
||||||
|
vt3 = f;
|
||||||
|
}
|
||||||
|
else if (id_counter == 3) {
|
||||||
|
vt4 = f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (str.peek() == '/') {
|
||||||
|
type_counter++;
|
||||||
|
type_counter %= 3;
|
||||||
|
str.ignore(1, '/');
|
||||||
|
}
|
||||||
|
while (str.peek() == ' ') {
|
||||||
|
id_counter++;
|
||||||
|
type_counter = 0;
|
||||||
|
str.ignore(1, ' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id_counter == 2)
|
||||||
|
m_index_arr.AddVertex(v1, v2, v3, vt1, vt2, vt3);
|
||||||
|
else {
|
||||||
|
m_index_arr.AddVertex(v1, v2, v3, vt1, vt2, vt3);
|
||||||
|
m_index_arr.AddVertex(v1, v3, v4, vt1, vt3, vt4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// shift vertices to level the vertices to ground
|
||||||
|
const int block_size = 3;
|
||||||
|
for (int i = 0; i < m_vertex_arr.GetSize()/ block_size; i++)
|
||||||
|
(*m_vertex_arr.GetPointer())[block_size * i + 1] -= (m_lowest_point - 0.001f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Model3D::SetId(int id) {
|
||||||
|
m_id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Model3D::SetIndexOffset(int offset) {
|
||||||
|
m_index_offset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Model3D::GetIndexOffset() {
|
||||||
|
return m_index_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Model3D::GetFaceCount() {
|
||||||
|
return m_index_arr.GetSize() / 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Model3D::GetId() {
|
||||||
|
return m_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Model3D::GetLowestPoint() {
|
||||||
|
return m_lowest_point;
|
||||||
|
}
|
||||||
|
|
||||||
|
VertexArray Model3D::GetVertexArray() {
|
||||||
|
return m_vertex_arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
IndexArray Model3D::GetIndexArray() {
|
||||||
|
return m_index_arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureVertexArray Model3D::GetTextureArray() {
|
||||||
|
return m_texture_arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
VertexArray* Model3D::GetVertexArrayPtr() {
|
||||||
|
return &m_vertex_arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
IndexArray* Model3D::GetIndexArrayPtr() {
|
||||||
|
return &m_index_arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureVertexArray* Model3D::GetTextureArrayPtr() {
|
||||||
|
return &m_texture_arr;
|
||||||
|
}
|
93
src/Scene.h
Normal file
93
src/Scene.h
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "Texture.h"
|
||||||
|
|
||||||
|
class IndexArray {
|
||||||
|
public:
|
||||||
|
void AddVertex(int x, int y, int z, int tx, int ty, int tz);
|
||||||
|
void AddVertex(int x, int y, int z);
|
||||||
|
int GetSize();
|
||||||
|
int GetByteSize();
|
||||||
|
std::vector<int>* GetPointer();
|
||||||
|
std::vector<int> GetVector();
|
||||||
|
void MoveIndices(int offset);
|
||||||
|
void MoveTextureIndices(int offset);
|
||||||
|
private:
|
||||||
|
std::vector<int> m_array;
|
||||||
|
};
|
||||||
|
|
||||||
|
class VertexArray {
|
||||||
|
public:
|
||||||
|
void AddVertex(float x, float y, float z);
|
||||||
|
int GetSize();
|
||||||
|
int GetByteSize();
|
||||||
|
std::vector<float>* GetPointer();
|
||||||
|
std::vector<float> GetVector();
|
||||||
|
private:
|
||||||
|
std::vector<float> m_array;
|
||||||
|
};
|
||||||
|
|
||||||
|
class TextureVertexArray {
|
||||||
|
public:
|
||||||
|
void AddVertex(float u, float v);
|
||||||
|
int GetSize();
|
||||||
|
int GetByteSize();
|
||||||
|
std::vector<float>* GetPointer();
|
||||||
|
std::vector<float> GetVector();
|
||||||
|
private:
|
||||||
|
std::vector<float> m_array;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Model3D {
|
||||||
|
public:
|
||||||
|
void Load(std::string path);
|
||||||
|
void SetId(int id);
|
||||||
|
void SetIndexOffset(int offset);
|
||||||
|
int GetIndexOffset();
|
||||||
|
int GetFaceCount();
|
||||||
|
float GetLowestPoint();
|
||||||
|
int GetId();
|
||||||
|
VertexArray GetVertexArray();
|
||||||
|
IndexArray GetIndexArray();
|
||||||
|
TextureVertexArray GetTextureArray();
|
||||||
|
VertexArray* GetVertexArrayPtr();
|
||||||
|
IndexArray* GetIndexArrayPtr();
|
||||||
|
TextureVertexArray* GetTextureArrayPtr();
|
||||||
|
private:
|
||||||
|
VertexArray m_vertex_arr;
|
||||||
|
IndexArray m_index_arr;
|
||||||
|
TextureVertexArray m_texture_arr;
|
||||||
|
|
||||||
|
int m_id = -1;
|
||||||
|
int m_index_offset = 0;
|
||||||
|
|
||||||
|
float m_lowest_point = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SceneVertices {
|
||||||
|
public:
|
||||||
|
void AddModel(Model3D* model);
|
||||||
|
void FillBuffers();
|
||||||
|
std::vector<float>* GetVertexBuffer();
|
||||||
|
std::vector<float>* GetTextureBuffer();
|
||||||
|
std::vector<int>* GetIndexBuffer();
|
||||||
|
int GetFaceCount();
|
||||||
|
int GetTextureVertsCount();
|
||||||
|
int GetVertexCount();
|
||||||
|
private:
|
||||||
|
std::vector<Model3D*> m_models;
|
||||||
|
int m_index_count = 0;
|
||||||
|
int m_vertex_count = 0;
|
||||||
|
int m_texture_vertex_count = 0;
|
||||||
|
std::vector<int> m_offsets;
|
||||||
|
|
||||||
|
std::vector<float> m_vertex_buffer;
|
||||||
|
std::vector<float> m_texture_buffer;
|
||||||
|
std::vector<int> m_index_buffer;
|
||||||
|
};
|
169
src/Shader.cpp
Normal file
169
src/Shader.cpp
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
#include "Shader.h"
|
||||||
|
#include "GLUtils.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
std::string vert_source =
|
||||||
|
"#version 330 core\n"
|
||||||
|
"layout(location = 0) in vec4 position;\n"
|
||||||
|
"layout(location = 1) in vec2 aTexCoord;\n"
|
||||||
|
"out vec2 TexCoord;\n"
|
||||||
|
"void main(){\n"
|
||||||
|
"gl_Position = position;\n"
|
||||||
|
"TexCoord = aTexCoord;\n"
|
||||||
|
"}";
|
||||||
|
|
||||||
|
std::string frag_source_tonemapped =
|
||||||
|
"#version 330 core\n"
|
||||||
|
"layout(location = 0) out vec4 color;\n"
|
||||||
|
"in vec2 TexCoord;\n"
|
||||||
|
"uniform sampler2D img_output;\n"
|
||||||
|
"void main(){\n"
|
||||||
|
"const float gamma = 2.2;\n"
|
||||||
|
"vec3 hdrColor = texture(img_output, TexCoord).xyz;\n"
|
||||||
|
"vec3 mapped = vec3(1.0) - exp(-hdrColor * 1.0);\n"
|
||||||
|
"mapped = pow(mapped, vec3(1.0 / gamma));\n"
|
||||||
|
"color = vec4(mapped, 1.0);\n"
|
||||||
|
"}";
|
||||||
|
|
||||||
|
std::string frag_source =
|
||||||
|
"#version 330 core\n"
|
||||||
|
"layout(location = 0) out vec4 color;\n"
|
||||||
|
"in vec2 TexCoord;\n"
|
||||||
|
"uniform sampler2D img_output;\n"
|
||||||
|
"void main(){\n"
|
||||||
|
"color = texture(img_output, TexCoord);\n"
|
||||||
|
"}";
|
||||||
|
|
||||||
|
Shader::Shader(std::string path, unsigned int type) {
|
||||||
|
std::string source;
|
||||||
|
|
||||||
|
LoadShader(path, source);
|
||||||
|
|
||||||
|
m_id = CompileShader(source, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
Shader::Shader(std::string path, unsigned int type, bool tonemapping)
|
||||||
|
{
|
||||||
|
std::string source;
|
||||||
|
|
||||||
|
LoadShader(path, source);
|
||||||
|
|
||||||
|
m_id = CompileShader(source, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
Shader::Shader(std::string path) {
|
||||||
|
std::string source;
|
||||||
|
|
||||||
|
LoadShader(path, source);
|
||||||
|
|
||||||
|
m_id = CompileShader(source, GL_COMPUTE_SHADER);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Shader::Shader(unsigned int type) {
|
||||||
|
// switch (type) {
|
||||||
|
// case GL_VERTEX_SHADER:
|
||||||
|
// m_id = CompileShader(vert_source, type);
|
||||||
|
// break;
|
||||||
|
// case GL_FRAGMENT_SHADER:
|
||||||
|
// m_id = CompileShader(frag_source, type);
|
||||||
|
// break;
|
||||||
|
// default:
|
||||||
|
// __debugbreak();
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
Shader::Shader(unsigned int type, bool tonemapped) {
|
||||||
|
switch (type) {
|
||||||
|
case GL_VERTEX_SHADER:
|
||||||
|
m_id = CompileShader(vert_source, type);
|
||||||
|
break;
|
||||||
|
case GL_FRAGMENT_SHADER:
|
||||||
|
if(!tonemapped)
|
||||||
|
m_id = CompileShader(frag_source, type);
|
||||||
|
else
|
||||||
|
m_id = CompileShader(frag_source_tonemapped, type);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
__debugbreak();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Shader::~Shader() {
|
||||||
|
Delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
Shader::Shader(Shader&& other) :
|
||||||
|
m_id(other.m_id)
|
||||||
|
{
|
||||||
|
other.m_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Shader& Shader::operator=(Shader&& other)
|
||||||
|
{
|
||||||
|
if (this != &other)
|
||||||
|
{
|
||||||
|
Delete();
|
||||||
|
std::swap(m_id, other.m_id);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shader::Delete() {
|
||||||
|
if (m_id != 0) {
|
||||||
|
GLCall(glDeleteShader(m_id));
|
||||||
|
}
|
||||||
|
m_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Shader::CompileShader(std::string _source, unsigned int type){
|
||||||
|
unsigned int id = glCreateShader(type);
|
||||||
|
const char* src = _source.c_str();
|
||||||
|
GLCall(glShaderSource(id, 1, &src, nullptr));
|
||||||
|
m_source = _source;
|
||||||
|
GLCall(glCompileShader(id));
|
||||||
|
|
||||||
|
int result;
|
||||||
|
GLCall(glGetShaderiv(id, GL_COMPILE_STATUS, &result));
|
||||||
|
if (result == GL_FALSE) {
|
||||||
|
m_compilation_success = false;
|
||||||
|
int length;
|
||||||
|
GLCall(glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length));
|
||||||
|
char* message = (char*)alloca(length * sizeof(char));
|
||||||
|
GLCall(glGetShaderInfoLog(id, length, &length, message));
|
||||||
|
if (type == GL_COMPUTE_SHADER) {
|
||||||
|
LOG("Compilation failed of compute shader");
|
||||||
|
LOG(message);
|
||||||
|
}
|
||||||
|
GLCall(glDeleteShader(id));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_compilation_success = true;
|
||||||
|
if (type == GL_COMPUTE_SHADER)
|
||||||
|
LOG("Compilation successfull of compute shader");
|
||||||
|
}
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shader::LoadShader(std::string name, std::string& Shader){
|
||||||
|
std::ifstream v(name);
|
||||||
|
std::stringstream buffer;
|
||||||
|
buffer << v.rdbuf();
|
||||||
|
Shader = buffer.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
int Shader::GetId() {
|
||||||
|
return m_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Shader::Compiled()
|
||||||
|
{
|
||||||
|
return m_compilation_success;
|
||||||
|
}
|
28
src/Shader.h
Normal file
28
src/Shader.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
#define _USE_MATH_DEFINES
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class Shader {
|
||||||
|
public:
|
||||||
|
Shader(std::string path);
|
||||||
|
Shader(std::string path, unsigned int type);
|
||||||
|
Shader(std::string path, unsigned int type, bool tonemapping);
|
||||||
|
Shader(unsigned int type, bool tonemapped = false);
|
||||||
|
~Shader();
|
||||||
|
|
||||||
|
Shader& operator=(Shader&& other);
|
||||||
|
Shader(Shader&& other);
|
||||||
|
Shader(const Shader&) = delete;
|
||||||
|
Shader& operator=(const Shader&) = delete;
|
||||||
|
|
||||||
|
void Delete();
|
||||||
|
int CompileShader(std::string _source, unsigned int type);
|
||||||
|
void LoadShader(std::string name, std::string& Shader);
|
||||||
|
int GetId();
|
||||||
|
bool Compiled();
|
||||||
|
private:
|
||||||
|
bool m_compilation_success = false;
|
||||||
|
unsigned int m_id = 0;
|
||||||
|
std::string m_source;
|
||||||
|
};
|
146
src/Texture.cpp
Normal file
146
src/Texture.cpp
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
#include "Texture.h"
|
||||||
|
#include "GLUtils.h"
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
|
#include <stb_image.h>
|
||||||
|
|
||||||
|
|
||||||
|
Texture::Texture(std::string name, std::string path) :
|
||||||
|
m_width(0), m_height(0), m_name(name), m_image(false),
|
||||||
|
m_bpp(0), m_id(0), m_buffer(nullptr)
|
||||||
|
{
|
||||||
|
GLCall(glGenTextures(1, &m_id));
|
||||||
|
|
||||||
|
GLCall(glBindTexture(GL_TEXTURE_2D, m_id));
|
||||||
|
GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT));
|
||||||
|
GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT));
|
||||||
|
GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
|
||||||
|
GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
|
||||||
|
|
||||||
|
Load(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture::Texture(std::string name, int width, int height) :
|
||||||
|
m_width(width), m_height(height), m_name(name), m_image(true),
|
||||||
|
m_bpp(0), m_id(0), m_buffer(nullptr)
|
||||||
|
{
|
||||||
|
GLCall(glGenTextures(1, &m_id));
|
||||||
|
|
||||||
|
GLCall(glBindTexture(GL_TEXTURE_2D, m_id));
|
||||||
|
GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT));
|
||||||
|
GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT));
|
||||||
|
GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
|
||||||
|
GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
|
||||||
|
|
||||||
|
GLCall(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, m_width, m_height, 0, GL_RGBA, GL_FLOAT, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Texture::Resize(int width, int height) {
|
||||||
|
m_width = width;
|
||||||
|
m_height = height;
|
||||||
|
|
||||||
|
|
||||||
|
GLuint boundTexture = 0;
|
||||||
|
GLCall(glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*)&boundTexture));
|
||||||
|
Bind();
|
||||||
|
|
||||||
|
GLCall(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, m_width, m_height, 0, GL_RGBA, GL_FLOAT, NULL));
|
||||||
|
|
||||||
|
GLCall(glBindTexture(GL_TEXTURE_2D, boundTexture));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Texture::Load(std::string path) {
|
||||||
|
stbi_set_flip_vertically_on_load(1);
|
||||||
|
std::string extension = path.substr(path.length() - 3, 3);
|
||||||
|
if (extension != "hdr") {
|
||||||
|
m_buffer = stbi_load(path.c_str(), &m_width, &m_height, &m_bpp, 4);
|
||||||
|
|
||||||
|
GLCall(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_buffer));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_buffer = (unsigned char*)stbi_loadf(path.c_str(), &m_width, &m_height, &m_bpp, 4);
|
||||||
|
|
||||||
|
GLCall(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, m_width, m_height, 0, GL_RGBA, GL_FLOAT, m_buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_buffer)
|
||||||
|
delete[] m_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Texture::Bind(unsigned int slot) {
|
||||||
|
GLCall(glActiveTexture(GL_TEXTURE0 + slot));
|
||||||
|
GLCall(glBindTexture(GL_TEXTURE_2D, m_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Texture::BindImage(unsigned int slot) {
|
||||||
|
GLCall(glBindImageTexture(slot, m_id, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Texture::IsImg() {
|
||||||
|
return m_image;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Texture::GetName()
|
||||||
|
{
|
||||||
|
return m_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture::Texture() :
|
||||||
|
m_width(0), m_height(0), m_name(""), m_image(false),
|
||||||
|
m_bpp(0), m_id(0), m_buffer(nullptr) {}
|
||||||
|
|
||||||
|
Texture::~Texture() {
|
||||||
|
Delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture::Texture(Texture&& other) :
|
||||||
|
m_width(other.m_width), m_height(other.m_height), m_name(other.m_name), m_image(other.m_image),
|
||||||
|
m_bpp(other.m_bpp), m_id(other.m_id), m_buffer(other.m_buffer)
|
||||||
|
{
|
||||||
|
other.m_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture& Texture::operator=(Texture&& other)
|
||||||
|
{
|
||||||
|
if (this != &other)
|
||||||
|
{
|
||||||
|
Delete();
|
||||||
|
std::swap(m_id, other.m_id);
|
||||||
|
std::swap(m_width, other.m_width);
|
||||||
|
std::swap(m_height, other.m_height);
|
||||||
|
std::swap(m_name, other.m_name);
|
||||||
|
std::swap(m_image, other.m_image);
|
||||||
|
std::swap(m_bpp, other.m_bpp);
|
||||||
|
std::swap(m_buffer, other.m_buffer);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Texture::Delete() {
|
||||||
|
if (m_id != 0) {
|
||||||
|
Unbind();
|
||||||
|
GLCall(glDeleteTextures(1, &m_id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Texture::Bind() {
|
||||||
|
GLCall(glBindTexture(GL_TEXTURE_2D, m_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Texture::Unbind() {
|
||||||
|
GLCall(glBindTexture(GL_TEXTURE_2D, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int Texture::GetId() {
|
||||||
|
return m_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Texture::GetWidth() {
|
||||||
|
return m_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Texture::GetHeight() {
|
||||||
|
return m_height;
|
||||||
|
}
|
39
src/Texture.h
Normal file
39
src/Texture.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#pragma once
|
||||||
|
#define _USE_MATH_DEFINES
|
||||||
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
class Texture {
|
||||||
|
private:
|
||||||
|
unsigned int m_id;
|
||||||
|
std::string m_name;
|
||||||
|
bool m_image;
|
||||||
|
unsigned char* m_buffer;
|
||||||
|
int m_width;
|
||||||
|
int m_height;
|
||||||
|
int m_bpp;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Texture(std::string name, std::string path);
|
||||||
|
Texture(std::string name, int width, int height);
|
||||||
|
void Resize(int width, int height);
|
||||||
|
Texture();
|
||||||
|
~Texture();
|
||||||
|
Texture& operator=(Texture&& other);
|
||||||
|
Texture(Texture&& other);
|
||||||
|
Texture(const Texture&) = delete;
|
||||||
|
Texture& operator=(const Texture&) = delete;
|
||||||
|
void Load(std::string path);
|
||||||
|
void Bind(unsigned int slot);
|
||||||
|
void BindImage(unsigned int slot);
|
||||||
|
void Bind();
|
||||||
|
void Unbind();
|
||||||
|
void Delete();
|
||||||
|
unsigned int GetId();
|
||||||
|
int GetWidth();
|
||||||
|
int GetHeight();
|
||||||
|
bool IsImg();
|
||||||
|
std::string GetName();
|
||||||
|
};
|
37
src/Timer.cpp
Normal file
37
src/Timer.cpp
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#include "Timer.h"
|
||||||
|
|
||||||
|
Timer::Timer() {
|
||||||
|
m_start = std::chrono::high_resolution_clock::now();
|
||||||
|
m_s = std::chrono::microseconds(0);
|
||||||
|
m_e = std::chrono::microseconds(0);
|
||||||
|
m_duration = std::chrono::microseconds(0);
|
||||||
|
}
|
||||||
|
void Timer::Start() {
|
||||||
|
m_start = std::chrono::high_resolution_clock::now();
|
||||||
|
}
|
||||||
|
void Timer::Stop() {
|
||||||
|
m_end = std::chrono::high_resolution_clock::now();
|
||||||
|
}
|
||||||
|
double Timer::TimeSinceLast() {
|
||||||
|
m_end = std::chrono::high_resolution_clock::now();
|
||||||
|
m_s = std::chrono::time_point_cast<std::chrono::microseconds>(m_start).time_since_epoch();
|
||||||
|
m_e = std::chrono::time_point_cast<std::chrono::microseconds>(m_end).time_since_epoch();
|
||||||
|
m_start = std::chrono::high_resolution_clock::now();
|
||||||
|
m_duration = m_e - m_s;
|
||||||
|
return (double)m_duration.count();
|
||||||
|
}
|
||||||
|
double Timer::GetMicro() {
|
||||||
|
return Timer::TimeSinceLast();
|
||||||
|
}
|
||||||
|
double Timer::GetMilis() {
|
||||||
|
return Timer::TimeSinceLast() * 0.001;
|
||||||
|
}
|
||||||
|
double Timer::GetSec() {
|
||||||
|
return Timer::TimeSinceLast() * 0.000001;
|
||||||
|
}
|
||||||
|
double Timer::TimeAfterStop() {
|
||||||
|
m_s = std::chrono::time_point_cast<std::chrono::microseconds>(m_start).time_since_epoch();
|
||||||
|
m_e = std::chrono::time_point_cast<std::chrono::microseconds>(m_end).time_since_epoch();
|
||||||
|
m_duration = m_e - m_s;
|
||||||
|
return m_duration.count() * 0.001;
|
||||||
|
}
|
24
src/Timer.h
Normal file
24
src/Timer.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
#define _USE_MATH_DEFINES
|
||||||
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
class Timer {
|
||||||
|
public:
|
||||||
|
Timer();
|
||||||
|
|
||||||
|
void Stop();
|
||||||
|
void Start();
|
||||||
|
double TimeSinceLast();
|
||||||
|
double TimeAfterStop();
|
||||||
|
double GetMicro();
|
||||||
|
double GetMilis();
|
||||||
|
double GetSec();
|
||||||
|
private:
|
||||||
|
std::chrono::time_point<std::chrono::high_resolution_clock> m_start, m_end;
|
||||||
|
std::chrono::microseconds m_s, m_e;
|
||||||
|
std::chrono::microseconds m_duration;
|
||||||
|
};
|
56
src/UBO.cpp
Normal file
56
src/UBO.cpp
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#include "UBO.h"
|
||||||
|
#include "GLUtils.h"
|
||||||
|
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
UBO::UBO(int bind) :
|
||||||
|
m_id(0), m_binding(bind), m_last_size(0)
|
||||||
|
{
|
||||||
|
GLCall(glGenBuffers(1, &m_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
UBO::UBO() :
|
||||||
|
m_id(0), m_binding(0), m_last_size(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
UBO::~UBO() {
|
||||||
|
Delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
int UBO::GetId()
|
||||||
|
{
|
||||||
|
return m_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
UBO::UBO(UBO&& other) :
|
||||||
|
m_id(other.m_id), m_binding(other.m_binding), m_last_size(other.m_last_size)
|
||||||
|
{
|
||||||
|
other.m_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
UBO& UBO::operator=(UBO&& other)
|
||||||
|
{
|
||||||
|
if (this != &other)
|
||||||
|
{
|
||||||
|
Delete();
|
||||||
|
std::swap(m_id,other.m_id);
|
||||||
|
m_binding = other.m_binding;
|
||||||
|
m_last_size = other.m_last_size;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UBO::Delete() {
|
||||||
|
if (m_id != 0) {
|
||||||
|
GLCall(glDeleteBuffers(1, &m_id));
|
||||||
|
}
|
||||||
|
m_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UBO::Bind() {
|
||||||
|
GLCall(glBindBuffer(GL_UNIFORM_BUFFER, m_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
76
src/UBO.h
Normal file
76
src/UBO.h
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "GLUtils.h"
|
||||||
|
|
||||||
|
class UBO {
|
||||||
|
private:
|
||||||
|
unsigned int m_id = 0;
|
||||||
|
int m_binding = 0;
|
||||||
|
size_t m_last_size = 0;
|
||||||
|
public:
|
||||||
|
|
||||||
|
UBO(int bind);
|
||||||
|
UBO();
|
||||||
|
UBO& operator=(UBO&& other);
|
||||||
|
UBO(UBO&& other);
|
||||||
|
UBO(const UBO&) = delete;
|
||||||
|
UBO& operator=(const UBO&) = delete;
|
||||||
|
~UBO();
|
||||||
|
int GetId();
|
||||||
|
void Delete();
|
||||||
|
void Bind();
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void Set(T* shader_data) {
|
||||||
|
size_t size = sizeof(*shader_data);
|
||||||
|
|
||||||
|
m_last_size = size;
|
||||||
|
|
||||||
|
Bind();
|
||||||
|
GLCall(glBufferData(GL_UNIFORM_BUFFER, size, size > 0 ? shader_data : nullptr, GL_DYNAMIC_DRAW));
|
||||||
|
|
||||||
|
GLCall(glBindBufferBase(GL_UNIFORM_BUFFER, m_binding, m_id));
|
||||||
|
}
|
||||||
|
template<typename T>
|
||||||
|
void Set(std::vector<T>* shader_data) {
|
||||||
|
size_t size = sizeof(T) * shader_data->size();
|
||||||
|
|
||||||
|
m_last_size = size;
|
||||||
|
|
||||||
|
Bind();
|
||||||
|
GLCall(glBufferData(GL_UNIFORM_BUFFER, size, size > 0 ? shader_data->data() : nullptr, GL_DYNAMIC_DRAW));
|
||||||
|
|
||||||
|
GLCall(glBindBufferBase(GL_UNIFORM_BUFFER, m_binding, m_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void Update(T* shader_data) {
|
||||||
|
size_t size = sizeof(*shader_data);
|
||||||
|
|
||||||
|
Bind();
|
||||||
|
if (size == m_last_size) {
|
||||||
|
GLCall(glBufferSubData(GL_UNIFORM_BUFFER, 0, size, shader_data));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_last_size = size;
|
||||||
|
GLCall(glBufferData(GL_UNIFORM_BUFFER, size, shader_data, GL_DYNAMIC_DRAW));
|
||||||
|
GLCall(glBindBufferBase(GL_UNIFORM_BUFFER, m_binding, m_id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template<typename T>
|
||||||
|
void Update(std::vector<T>* shader_data) {
|
||||||
|
size_t size = sizeof(T) * shader_data->size();
|
||||||
|
|
||||||
|
Bind();
|
||||||
|
if (size == m_last_size) {
|
||||||
|
GLCall(glBufferSubData(GL_UNIFORM_BUFFER, 0, size, size > 0 ? shader_data->data() : nullptr));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_last_size = size;
|
||||||
|
GLCall(glBufferData(GL_UNIFORM_BUFFER, size, size > 0 ? shader_data->data() : nullptr, GL_DYNAMIC_DRAW));
|
||||||
|
GLCall(glBindBufferBase(GL_UNIFORM_BUFFER, m_binding, m_id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user