211 lines
6.5 KiB
C++
211 lines
6.5 KiB
C++
#pragma once
|
|
|
|
#include <iostream>
|
|
#include <JGL/logger/logger.h>
|
|
#include <ReWindow/types/Window.h>
|
|
#include <JUI/Widgets/Scene.hpp>
|
|
#include <JUI/Widgets/Slider.hpp>
|
|
#include <JUI/Widgets/Window.hpp>
|
|
#include "JUI/Widgets/CommandLine.hpp"
|
|
#include "JGL/types/Shader.h"
|
|
#include <ReWindow/Logger.h>
|
|
#include <Color4.hpp>
|
|
#include "JUI/Widgets/UtilityBar.hpp"
|
|
#include <JUI/Widgets/ColorPicker.hpp>
|
|
|
|
#include "JUI/Widgets/Image.hpp"
|
|
#include "JUI/Widgets/ImageRect.hpp"
|
|
|
|
#include <misc.hpp>
|
|
|
|
#pragma region OpenGL Introspection
|
|
|
|
inline std::string GetGLVendor() { return {(const char*)glGetString(GL_VENDOR)}; }
|
|
inline std::string GetGLRenderer() { return {(const char*)glGetString(GL_RENDERER)}; }
|
|
inline std::string GetGLVersion() { return {(const char*)glGetString(GL_VERSION)}; }
|
|
inline std::string GetGLSLVersion() { return {(const char*)glGetString(GL_SHADING_LANGUAGE_VERSION)}; }
|
|
inline std::string GetGLExtensions() { return {(const char*)glGetString(GL_EXTENSIONS)}; }
|
|
inline std::vector<std::string> GetGLExtensionList() { return misc::string_expand({(const char*)glGetString(GL_EXTENSIONS)}); }
|
|
|
|
#pragma endregion
|
|
|
|
using namespace JUI::UDimLiterals;
|
|
|
|
enum class Fractal {
|
|
MandelbrotSet, JuliaSet
|
|
};
|
|
|
|
|
|
template <typename T>
|
|
struct Lerped {
|
|
|
|
T current;
|
|
T goal;
|
|
float rate = 1.f;
|
|
void Update(float elapsed);
|
|
};
|
|
|
|
template <>
|
|
inline void Lerped<float>::Update(float elapsed) { current = Math::Lerp(current, goal, elapsed*rate); }
|
|
|
|
template <>
|
|
inline void Lerped<Vector2>::Update(float elapsed) { current = Vector2::Lerp(current, goal, elapsed*rate); }
|
|
|
|
|
|
|
|
/// This class represents the FractalApp program state.
|
|
class FractalInspectorApp : public ReWindow::OpenGLWindow {
|
|
protected:
|
|
JUI::Scene *scene;
|
|
JUI::UtilityBar* toolbar;
|
|
JUI::CommandLine *console;
|
|
JUI::Window* info_dialog;
|
|
JUI::TextRect* fps_label;
|
|
|
|
JUI::Window* mandelbrotset_dialog;
|
|
JUI::Window* juliaset_dialog;
|
|
JUI::Window* colorpicker_window;
|
|
|
|
JGL::Shader mandelbrot_shader;
|
|
JGL::Shader julia_shader;
|
|
JGL::RenderTarget *canvas;
|
|
|
|
JUI::Slider* julia_x_slider;
|
|
JUI::Slider* julia_y_slider;
|
|
JUI::Text* julia_x_label;
|
|
JUI::Text* julia_y_label;
|
|
|
|
float u_time;
|
|
float u_scale = 2.f;
|
|
float u_scale_goal = 2.f;
|
|
Vector2 u_translation {0.4f, 0.f};
|
|
Vector2 u_translation_goal {0.4f, 0.f};
|
|
Color4 u_rgb_1 = Colors::Greens::Chartreuse;
|
|
Color4 u_rgb_2 = Colors::Reds::LightCoral;
|
|
Color4 u_rgb_3 = Colors::Yellow;
|
|
Color4 u_rgb_4 = Colors::Green;
|
|
Vector2 u_julia_set {0,0};
|
|
Vector2 u_julia_value {0,0};
|
|
bool panning = false;
|
|
|
|
Fractal current_fractal = Fractal::MandelbrotSet;
|
|
|
|
void OnShaderLoadFail(const std::string&, const std::string&);
|
|
public:
|
|
FractalInspectorApp(int width, int height);
|
|
|
|
/// Returns a full-path file name for a GLSL vertex shader, from a given prefix name.
|
|
static std::filesystem::path VertexShaderFilepathFromPrefixName(const std::string &name);
|
|
|
|
/// Returns a full-path file name for a GLSL fragment shader, from a given prefix name.
|
|
static std::filesystem::path FragmentShaderFilepathFromPrefixName(const std::string &name);
|
|
|
|
void LoadShaders();
|
|
|
|
void ReloadShader();
|
|
|
|
using CmdArgs = std::vector<std::string>;
|
|
void PositionCmd(const CmdArgs& args);
|
|
|
|
void ZoomCmd(const CmdArgs &args);
|
|
|
|
void ParseCmdLineMessage(const std::string& message);
|
|
|
|
/// Loads the Julia set program -- consists of a shader program and special widget for parameters.
|
|
void LoadJulia();
|
|
|
|
/// Unloads the Julia set program.
|
|
/// @see LoadJulia
|
|
void UnloadJulia();
|
|
|
|
/// Creates and returns the "Info" dialog for the program. Think of it like a watermark.
|
|
JUI::Window* CreateAppInfoDialogWindow(JUI::Widget* parent);
|
|
|
|
/// Creates and styles the program's GUI.
|
|
void CreateMenu();
|
|
|
|
/// Initializes the ReWindow and sets up program state, GUI widgets, etc.
|
|
bool Open() override;
|
|
|
|
/// Passes the current window size to subordinate objects, such as the JUI scene.
|
|
void PropagateWindowSize();
|
|
|
|
Vector2 FractalSpaceToScreenSpace(const Vector2& pos) {
|
|
Vector2 R(GetWidth(), GetHeight());
|
|
Vector2 translation(u_translation.x, -u_translation.y);
|
|
|
|
return ((pos + u_translation) * R.y + R + Vector2(1.f, 1.f)) / u_scale;
|
|
}
|
|
|
|
Vector2 ScreenSpaceToFractalSpace(const Vector2& pos) {
|
|
Vector2 tpos = -pos;
|
|
Vector2 R(GetWidth(), GetHeight());
|
|
Vector2 scaled = pos * u_scale;
|
|
Vector2 translation(u_translation.x, -u_translation.y);
|
|
|
|
Vector2 uv = ((scaled - R - Vector2(1.f, 1.f)) / R.y) - u_translation;
|
|
return uv;
|
|
}
|
|
|
|
void ZoomIn(float rate);
|
|
|
|
void ZoomInTowards(const Vector2 &dir, float rate);
|
|
|
|
void ZoomOutTowards(const Vector2 &dir, float rate);
|
|
|
|
void ZoomOut(float rate);
|
|
|
|
/// Performs a logic update.
|
|
void Update(float elapsed);
|
|
|
|
float ReadableScale();
|
|
|
|
/// Pushes updated shader paramters to the OpenGL shader program.
|
|
void UpdateShaderUniforms(float elapsed);
|
|
|
|
/// Renders the program.
|
|
void Draw();
|
|
|
|
/// Called by the ReWindow base, updates and then re-draws the program.
|
|
void OnRefresh(float elapsed) override;
|
|
|
|
/// Called by the ReWindow base when the user presses a mouse button.
|
|
void OnMouseButtonDown(const ReWindow::MouseButtonDownEvent &e) override;
|
|
|
|
/// Called by the ReWindow base when the user releases a mouse button.
|
|
void OnMouseButtonUp(const ReWindow::MouseButtonUpEvent &e) override;
|
|
/// Called by the ReWindow base when the user moves the mouse / pointer device.
|
|
void OnMouseMove(const ReWindow::MouseMoveEvent &e) override;
|
|
/// Called by the ReWindow base when the user presses a key.
|
|
void OnKeyDown(const ReWindow::KeyDownEvent &e) override;
|
|
/// Called by the ReWindow base when the user presses a key.
|
|
void OnKeyUp(const ReWindow::KeyUpEvent &e) override;
|
|
|
|
void OnMouseWheel(const ReWindow::MouseWheelEvent &e) override {
|
|
|
|
// Test of zooming in toward the mouse.
|
|
|
|
auto mouse_pos_ipair = GetMouseCoordinates();
|
|
auto resolution_ipair = GetSize();
|
|
auto mouse_pos = Vector2(mouse_pos_ipair.x, mouse_pos_ipair.y);
|
|
auto resolution = Vector2(resolution_ipair.x, resolution_ipair.y);
|
|
|
|
auto mp_norm = mouse_pos / resolution;
|
|
mp_norm -= {.5f, .5f};
|
|
mp_norm *= 2.f;
|
|
mp_norm = {-mp_norm.x, mp_norm.y};
|
|
|
|
if (e.WheelMovement > 0) {
|
|
ZoomOutTowards(mp_norm, 0.1f);
|
|
}
|
|
if (e.WheelMovement < 0) {
|
|
ZoomInTowards(mp_norm, 0.1f);
|
|
}
|
|
}
|
|
|
|
void TakeScreenshot();
|
|
protected:
|
|
private:
|
|
};
|
|
|