389 lines
11 KiB
C++
389 lines
11 KiB
C++
#include <cstdio>
|
|
#include <GL/glew.h>
|
|
#include <GLFW/glfw3.h>
|
|
|
|
#include "imgui/imgui.h"
|
|
#include "imgui/imgui_impl_glfw.h"
|
|
#include "imgui/imgui_impl_opengl3.h"
|
|
|
|
#include "MyGLWindow.h"
|
|
|
|
bool lbutton_down;
|
|
bool rbutton_down;
|
|
bool mbutton_down;
|
|
double m_lastMouseX;
|
|
double m_lastMouseY;
|
|
double cx, cy;
|
|
|
|
int g_width;
|
|
int g_height;
|
|
|
|
bool reset = false;
|
|
|
|
void window_size_callback(GLFWwindow* window, int width, int height)
|
|
{
|
|
g_width = width;
|
|
g_height = height;
|
|
}
|
|
|
|
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
|
|
{
|
|
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
|
|
glfwSetWindowShouldClose(window, GLFW_TRUE);
|
|
if (key == GLFW_KEY_R && action == GLFW_PRESS)
|
|
reset = true;
|
|
}
|
|
|
|
static void cursor_pos_callback(GLFWwindow* window, double xpos, double ypos)
|
|
{
|
|
cx = xpos;
|
|
cy = ypos;
|
|
}
|
|
|
|
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
|
|
{
|
|
if (action == GLFW_PRESS) {
|
|
double xpos, ypos;
|
|
glfwGetCursorPos(window, &xpos, &ypos);
|
|
m_lastMouseX = xpos;
|
|
m_lastMouseY = ypos;
|
|
}
|
|
|
|
if (button == GLFW_MOUSE_BUTTON_LEFT) {
|
|
if (GLFW_PRESS == action)
|
|
lbutton_down = true;
|
|
else if (GLFW_RELEASE == action)
|
|
lbutton_down = false;
|
|
}
|
|
|
|
else if (button == GLFW_MOUSE_BUTTON_RIGHT) {
|
|
if (GLFW_PRESS == action)
|
|
rbutton_down = true;
|
|
else if (GLFW_RELEASE == action)
|
|
rbutton_down = false;
|
|
}
|
|
|
|
else if (button == GLFW_MOUSE_BUTTON_MIDDLE) {
|
|
if (GLFW_PRESS == action)
|
|
mbutton_down = true;
|
|
else if (GLFW_RELEASE == action)
|
|
mbutton_down = false;
|
|
}
|
|
}
|
|
|
|
|
|
void mouseDragging(double width, double height, MyGlWindow &win)
|
|
{
|
|
ImGuiIO& io = ImGui::GetIO();
|
|
if (!io.WantCaptureMouse)
|
|
{
|
|
if (lbutton_down) {
|
|
float fractionChangeX = static_cast<float>(cx - m_lastMouseX) / static_cast<float>(width);
|
|
float fractionChangeY = static_cast<float>(m_lastMouseY - cy) / static_cast<float>(height);
|
|
win.viewer.rotate(fractionChangeX, fractionChangeY);
|
|
}
|
|
else if (mbutton_down) {
|
|
float fractionChangeX = static_cast<float>(cx - m_lastMouseX) / static_cast<float>(width);
|
|
float fractionChangeY = static_cast<float>(m_lastMouseY - cy) / static_cast<float>(height);
|
|
win.viewer.zoom(fractionChangeY);
|
|
}
|
|
else if (rbutton_down) {
|
|
float fractionChangeX = static_cast<float>(cx - m_lastMouseX) / static_cast<float>(width);
|
|
float fractionChangeY = static_cast<float>(m_lastMouseY - cy) / static_cast<float>(height);
|
|
win.viewer.translate(-fractionChangeX, -fractionChangeY, 1);
|
|
}
|
|
m_lastMouseX = cx;
|
|
m_lastMouseY = cy;
|
|
}
|
|
}
|
|
|
|
bool initGLFW()
|
|
{
|
|
if (!glfwInit())
|
|
{
|
|
// Windows error box
|
|
return false;
|
|
}
|
|
|
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
|
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4);
|
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
|
return true;
|
|
}
|
|
|
|
void initImgui(GLFWwindow **window)
|
|
{
|
|
IMGUI_CHECKVERSION();
|
|
ImGui::CreateContext();
|
|
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
|
|
|
const char* glsl_version = "#version 430";
|
|
|
|
ImGui_ImplGlfw_InitForOpenGL(*window, true);
|
|
ImGui_ImplOpenGL3_Init(glsl_version);
|
|
|
|
ImGui::StyleColorsDark();
|
|
//ImGui::StyleColorsClassic();
|
|
//ImGui::StyleColorsLight();
|
|
|
|
}
|
|
|
|
bool createWindow(GLFWwindow **window)
|
|
{
|
|
int width = 1080;
|
|
int height = 1080;
|
|
g_width = 1080;
|
|
g_height = 1080;
|
|
/* Create a windowed mode window and its OpenGL context */
|
|
(*window) = glfwCreateWindow(width, height, "OpenGL FrameWork", NULL, NULL);
|
|
if (!(*window))
|
|
{
|
|
// Windows error box
|
|
glfwTerminate();
|
|
return false;
|
|
}
|
|
|
|
initImgui(window);
|
|
|
|
glfwMakeContextCurrent((*window));
|
|
/* Make the window's context current */
|
|
glewExperimental = GL_TRUE;
|
|
GLenum err = glewInit();
|
|
if (err != GLEW_OK)
|
|
{
|
|
// Windows error box
|
|
//Problem: glewInit failed, something is seriously wrong.
|
|
return false;
|
|
}
|
|
glfwSetKeyCallback((*window), key_callback);
|
|
return true;
|
|
}
|
|
|
|
void FPSDisplay(int width)
|
|
{
|
|
static int frameCount = 0;
|
|
static int fps = 60;
|
|
static double previousTime = glfwGetTime();
|
|
double currentTime = glfwGetTime();
|
|
frameCount++;
|
|
// If a second has passed.
|
|
if (currentTime - previousTime >= 1.0)
|
|
{
|
|
fps = frameCount;
|
|
frameCount = 0;
|
|
previousTime = currentTime;
|
|
}
|
|
|
|
if (ImGui::Begin("FPSCounterOutline1", false,
|
|
ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoFocusOnAppearing))
|
|
ImGui::TextColored(ImVec4(0, 0, 0, 1), std::to_string(fps).c_str());
|
|
ImGui::End();
|
|
|
|
if (ImGui::Begin("FPSCounterOutline2", false,
|
|
ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoFocusOnAppearing))
|
|
ImGui::TextColored(ImVec4(0, 0, 0, 1), std::to_string(fps).c_str());
|
|
ImGui::End();
|
|
|
|
if (ImGui::Begin("FPSCounterOutline3", false,
|
|
ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoFocusOnAppearing))
|
|
ImGui::TextColored(ImVec4(0, 0, 0, 1), std::to_string(fps).c_str());
|
|
ImGui::End();
|
|
|
|
if (ImGui::Begin("FPSCounterOutline4", false,
|
|
ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoFocusOnAppearing))
|
|
ImGui::TextColored(ImVec4(0, 0, 0, 1), std::to_string(fps).c_str());
|
|
ImGui::End();
|
|
|
|
if (ImGui::Begin("FPSCounter", false,
|
|
ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoFocusOnAppearing))
|
|
ImGui::TextColored(ImVec4(1, 1, 1, 1), std::to_string(fps).c_str());
|
|
ImGui::End();
|
|
|
|
ImGui::SetWindowPos("FPSCounterOutline1", ImVec2(width - 49.f, 20.f), ImGuiCond_Once);
|
|
ImGui::SetWindowPos("FPSCounterOutline2", ImVec2(width - 51.f, 20.f), ImGuiCond_Once);
|
|
ImGui::SetWindowPos("FPSCounterOutline3", ImVec2(width - 50.f, 19.f), ImGuiCond_Once);
|
|
ImGui::SetWindowPos("FPSCounterOutline4", ImVec2(width - 50.f, 21.f), ImGuiCond_Once);
|
|
|
|
ImGui::SetWindowPos("FPSCounter", ImVec2(width - 50.f, 20.f), ImGuiCond_Once);
|
|
}
|
|
|
|
int loop(GLFWwindow *window)
|
|
{
|
|
std::printf("OpenGL %s, GLSL %s\n", glGetString(GL_VERSION), glGetString(GL_SHADING_LANGUAGE_VERSION));
|
|
|
|
int width;
|
|
int heigth;
|
|
|
|
glfwGetWindowSize(window, &width, &heigth);
|
|
MyGlWindow glWin(width, heigth);
|
|
|
|
glWin.scnctx.fboDisplayName = "position_buffer";
|
|
bool is_selected = false;
|
|
|
|
glWin.scnctx.renderMode = DEFERRED_LIGHT;
|
|
glWin.scnctx.firstRedraw = true;
|
|
|
|
std::vector<std::string> lights_strs;
|
|
char const **strings = nullptr;
|
|
|
|
int current_light = 0;
|
|
|
|
bool orbiting_lights = true;
|
|
float light_speed = 50.0f;
|
|
|
|
double prev_time = glfwGetTime();
|
|
double sinceLastFrame;
|
|
|
|
while (!glfwWindowShouldClose(window))
|
|
{
|
|
sinceLastFrame = glfwGetTime() - prev_time;
|
|
prev_time = glfwGetTime();
|
|
|
|
ImGui_ImplOpenGL3_NewFrame();
|
|
ImGui_ImplGlfw_NewFrame();
|
|
ImGui::NewFrame();
|
|
|
|
if (ImGui::Begin("Scene settings"))
|
|
{
|
|
if (ImGui::BeginCombo("Debug Buffer", glWin.scnctx.fboDisplayName.c_str()))
|
|
{
|
|
if (ImGui::Selectable("Position buffer", &is_selected, 0, ImVec2(120, 10)))
|
|
glWin.scnctx.fboDisplayName = "position_buffer";
|
|
if (ImGui::Selectable("Normal buffer", &is_selected, 0, ImVec2(120, 10)))
|
|
glWin.scnctx.fboDisplayName = "normal_buffer";
|
|
if (ImGui::Selectable("Color buffer", &is_selected, 0, ImVec2(120, 10)))
|
|
glWin.scnctx.fboDisplayName = "color_buffer";
|
|
|
|
ImGui::EndCombo();
|
|
}
|
|
|
|
if (ImGui::BeginCombo("Render Mode",
|
|
(glWin.scnctx.renderMode == DEFERRED_LIGHT) ? "Deferred Lights" : (
|
|
(glWin.scnctx.renderMode == FORWARD_LIGHT) ? "Forward Lights" : "Debug GBuffers")))
|
|
{
|
|
if (ImGui::Selectable("Draw Debug GBuffers", &is_selected, 0, ImVec2(120, 10)))
|
|
{
|
|
glWin.scnctx.renderMode = GBUF_DEBUG;
|
|
glWin.scnctx.firstRedraw = true;
|
|
}
|
|
if (ImGui::Selectable("Draw with Deferred Lights", &is_selected, 0, ImVec2(120, 10)))
|
|
{
|
|
glWin.scnctx.renderMode = DEFERRED_LIGHT;
|
|
glWin.scnctx.firstRedraw = true;
|
|
}
|
|
|
|
if (ImGui::Selectable("Draw with Forward Lights", &is_selected, 0, ImVec2(120, 10)))
|
|
{
|
|
glWin.scnctx.renderMode = FORWARD_LIGHT;
|
|
glWin.scnctx.firstRedraw = true;
|
|
}
|
|
|
|
ImGui::EndCombo();
|
|
}
|
|
|
|
if (ImGui::BeginCombo("Scene Choice",
|
|
(glWin.scene == MOUNTAIN) ? "Mountain" :
|
|
(glWin.scene == CUBES) ? "Cubes" : "Teapots"))
|
|
{
|
|
if (ImGui::Selectable("Mountain", &is_selected, 0, ImVec2(100, 10)))
|
|
glWin.loadScene(SceneChoice::MOUNTAIN);
|
|
if (ImGui::Selectable("Cubes", &is_selected, 0, ImVec2(100, 10)))
|
|
glWin.loadScene(SceneChoice::CUBES);
|
|
if (ImGui::Selectable("Teapots", &is_selected, 0, ImVec2(100, 10)))
|
|
glWin.loadScene(SceneChoice::TEAPOTS);
|
|
ImGui::EndCombo();
|
|
}
|
|
|
|
ImGui::SetWindowPos(ImVec2(20, 20));
|
|
}
|
|
ImGui::End();
|
|
|
|
if (reset)
|
|
{
|
|
glWin.loadScene(SceneChoice::MOUNTAIN);
|
|
reset = false;
|
|
}
|
|
|
|
if (ImGui::Begin("Light management"))
|
|
{
|
|
lights_strs.clear();
|
|
for (auto light : glWin.scnctx.lights)
|
|
lights_strs.push_back(light.toString());
|
|
|
|
std::free(strings);
|
|
strings = (char const **)std::malloc(sizeof(char *) * (lights_strs.size() + 1));
|
|
std::memset((void *)strings, 0, sizeof(char *) * (lights_strs.size() + 1));
|
|
|
|
for (int i = 0; i < lights_strs.size(); i++)
|
|
strings[i] = lights_strs[i].c_str();
|
|
|
|
ImGui::ListBox("Lights", ¤t_light, strings, lights_strs.size());
|
|
if (glWin.scnctx.lights.size() > 0)
|
|
{
|
|
if (ImGui::SliderFloat("Selected light X", &glWin.scnctx.lights[current_light].location.x, -10, 10)
|
|
&& glWin.scnctx.renderMode == DEFERRED_LIGHT)
|
|
glWin.multipassManager.recomputeDeferredLights(glWin.scnctx);
|
|
if (ImGui::SliderFloat("Selected light Y", &glWin.scnctx.lights[current_light].location.y, -10, 10)
|
|
&& glWin.scnctx.renderMode == DEFERRED_LIGHT)
|
|
glWin.multipassManager.recomputeDeferredLights(glWin.scnctx);
|
|
if (ImGui::SliderFloat("Selected light Z", &glWin.scnctx.lights[current_light].location.z, -10, 10)
|
|
&& glWin.scnctx.renderMode == DEFERRED_LIGHT)
|
|
glWin.multipassManager.recomputeDeferredLights(glWin.scnctx);
|
|
|
|
if (ImGui::SliderFloat("Selected light R", &glWin.scnctx.lights[current_light].intensity.x, 0, 1)
|
|
&& glWin.scnctx.renderMode == DEFERRED_LIGHT)
|
|
glWin.multipassManager.recomputeDeferredLights(glWin.scnctx);
|
|
if (ImGui::SliderFloat("Selected light G", &glWin.scnctx.lights[current_light].intensity.y, 0, 1)
|
|
&& glWin.scnctx.renderMode == DEFERRED_LIGHT)
|
|
glWin.multipassManager.recomputeDeferredLights(glWin.scnctx);
|
|
if (ImGui::SliderFloat("Selected light B", &glWin.scnctx.lights[current_light].intensity.z, 0, 1)
|
|
&& glWin.scnctx.renderMode == DEFERRED_LIGHT)
|
|
glWin.multipassManager.recomputeDeferredLights(glWin.scnctx);
|
|
|
|
}
|
|
ImGui::Checkbox("Orbit Lights", &orbiting_lights);
|
|
ImGui::SliderFloat("Orbit degrees / second", &light_speed, 0, 360);
|
|
}
|
|
ImGui::End();
|
|
|
|
FPSDisplay(width);
|
|
|
|
glfwSwapBuffers(window);
|
|
glWin.draw();
|
|
if (orbiting_lights)
|
|
glWin.orbitLights(sinceLastFrame, light_speed);
|
|
|
|
ImGui::Render();
|
|
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
|
|
|
glfwPollEvents();
|
|
mouseDragging(g_width, g_height, glWin);
|
|
glWin.resize(g_width, g_height);
|
|
}
|
|
|
|
ImGui_ImplOpenGL3_Shutdown();
|
|
ImGui_ImplGlfw_Shutdown();
|
|
ImGui::DestroyContext();
|
|
|
|
|
|
glfwDestroyWindow(window);
|
|
glfwTerminate();
|
|
return 0;
|
|
}
|
|
|
|
int main()
|
|
{
|
|
GLFWwindow *win;
|
|
|
|
if (!initGLFW() || !createWindow(&win))
|
|
return 1;
|
|
|
|
glfwSetWindowSizeCallback(win, window_size_callback);
|
|
glfwSetMouseButtonCallback(win, mouse_button_callback);
|
|
glfwSetCursorPosCallback(win, cursor_pos_callback);
|
|
glfwSetKeyCallback(win, key_callback);
|
|
glfwSetWindowTitle(win, "Variables d'environnement pour le DLL :,(");
|
|
return loop(win);
|
|
}
|
|
|