#include #include #include #include #include #include #include #include #include #include using J3ML::LinearAlgebra::Vector2; using namespace JGL::Fonts; using namespace JGL; using JGL::Font; float fps = 0.0f; std::vector rect_instances; /// A draggable 2D point that highlights when moused over and when clicked. class Gizmo { public: Gizmo() {} Gizmo(const Vector2& pos) : position(pos) {} bool dragging = false; bool hovered = false; Vector2 position; float range = 6.f; float base_radius = 3.f; float hover_radius = 6.f; float drag_radius = 4.f; Color4 base_color = Colors::Reds::Salmon; Color4 hover_color = Colors::Reds::Firebrick; Color4 drag_color = Colors::White; float lerp_rate = 0.25f; float text_scale = 1.f; int text_size = 12; void Grab() { if (hovered) dragging = true; } void Release() { dragging = false; } void Update(const Vector2& mouse) { if (dragging) position = position.Lerp(mouse, lerp_rate); hovered = mouse.Distance(position) < range; } void Draw() { if (dragging) J2D::DrawPoint(drag_color, position, drag_radius); else if (hovered) J2D::DrawPoint(hover_color, position, hover_radius); else J2D::DrawPoint(base_color, position, base_radius); J2D::DrawString(Colors::White, std::format("{:.1f},{:.1f}", position.x, position.y), position.x, position.y, text_scale, text_size); } }; /// A 3D Camera Controller. class Camera { public: Vector3 position = {0,0,0}; Vector3 angle = {0,0,0}; std::vector lookAt(const Vector3& eye, const Vector3& center, const Vector3& up) { Vector3 f = Vector3::Normalized((center - eye)); Vector3 upN = Vector3::Normalized(up); Vector3 s = Vector3::Normalized(f.Cross(upN)); Vector3 u = Vector3::Normalized(s.Cross(f)); std::vector result = { s.x, u.x, -f.x, 0.0f, s.y, u.y, -f.y, 0.0f, s.z, u.z, -f.z, 0.0f, -s.Dot(eye), -u.Dot(eye), f.Dot(eye), 1.0f }; return result; } void render() { glRotatef(angle.x,1.0f, 0.0f, 0.0f); glRotatef(angle.y,0.0f, 1.0f, 0.0f); glRotatef(angle.z,0.0f, 0.0f, 1.0f); glMultMatrixf(lookAt({position.x, position.y, position.z}, {position.x, position.y, 100.f + position.z}, {0,1,0}).data()); } }; Camera* camera; using J3ML::LinearAlgebra::Matrix4x4; struct point { GLfloat x; GLfloat y; GLfloat s; GLfloat t; }; Gizmo a({250, 150}); Gizmo b({200, 250}); Gizmo c({350, 300}); Gizmo d({450, 250}); JGL::Font FreeSans; Texture* image; Texture* image_mask; RenderTarget* j2d_render_target; Shader* shader; Vector2 result; class JGLDemoWindow : public ReWindow::OpenGLWindow { public: void initGL() { camera = new Camera; if (!JGL::Init({ GetSize().x, GetSize().y}, 75, 100)) Logger::Fatal("Initialization failed."); // Load a custom font. FreeSans = JGL::Font("assets/fonts/FreeSans.ttf"); glClearColor(0.f, 0.f, 0.f, 0.f); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); glDepthMask(GL_TRUE); image = new Texture("assets/sprites/Re3D.png", FilteringMode::MIPMAP_NEAREST); image_mask = new Texture("assets/sprites/alpha_mask_2.png"); j2d_render_target = new RenderTarget({540, 500}, {0,0,0,0}, false, SampleRate::NONE, FilteringMode::MIPMAP_NEAREST); //Texture::MultiplyByAlphaMask(*image, *image_mask); shader = new Shader(std::filesystem::path("assets/shader_programs/test_vertex.glsl"), std::filesystem::path("assets/shader_programs/test_fragment.glsl"), {{"a_vertex_position", 0}, {"a_instance_position", 1}, {"a_instance_size", 2}, {"a_instance_color", 3}}); result = Jupiteroid.MeasureString("The quick black fox jumps over the lazy dog.", 16); for (unsigned int i = 0; i < 100; i++) rect_instances.emplace_back(Colors::Red, Vector2(420, 420), Vector2(20, 20)); } EulerAngleXYZ textAngle = {0,0,0}; float fov = 90; float pulse = 0; float sprite_radians = 0; bool fov_increasing = true; void display() { pulse += 20 * delta_time; float dt = GetDeltaTime(); JGL::Update({ GetSize().x, GetSize().y }); if (fov_increasing) fov += 0.025; else fov -= 0.050; if (fov >= 120) fov_increasing = false; else if (fov <= 75) fov_increasing = true; //J3D::ChangeFOV(fov); sprite_radians += 0.005; textAngle.yaw += 1; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); camera->render(); // All 3D elements of the scene and JGL elements *must* be rendered before the 2D stuff /* if rendering to screen space directly. */ auto test_light = PointLight({2,1,2}, {(u8) pulse,(u8) pulse,(u8) pulse, 255}, {(u8) pulse, (u8) pulse, (u8) pulse, 255}, {0,0,0}, 1, 0.1, 0.01); // If a 3D object has transparency. The things you'd like to see through it must be drawn before. J3D::Begin(); J3D::DrawLine(Colors::Red, {-0.33,-0.125,1}, {-1,-0.125,1}); J3D::DrawLine(Colors::Red, {-0.33,-0.125,1}, {-0.33,0.25,1}); J3D::DrawString(Colors::Red, "JGL Sample Text", {-0.33, -0.1, 1.0f}, 1.f, 32, FreeSans, textAngle, true); //J3D::WireframeSphere(Colors::Green, {0,0,0.5f}, 0.25f, 1, 128, 128); Sphere sphere = {{1,0, 0.5f}, 0.2125}; J3D::BatchWireframeRevoSphere(Colors::Green, &sphere, 1, 1, 8, 8, true); J3D::RequiredLight(&test_light); J3D::FillAABB(Colors::Whites::AliceBlue, {0,0,0.5f}, {0.05f, 0.05f, 0.05f}); J3D::WireframeAABB(Colors::Yellow, {0.5, 0, 0.5}, {0.125, 0.125, 0.125}, 1); J3D::End(); //JGL::ClearScreen(Colors::Red); J2D::Begin(j2d_render_target, shader, true); J2D::FillRect(Colors::Blue, {0,52}, {100,100}); J2D::BatchFillRect(rect_instances.data(), rect_instances.size()); J2D::DrawSprite(image, {300, 400}, sprite_radians * 0.10f, {0.5,0.5}, {1, 1}, Colors::White); J2D::DrawMirrorSprite(image, {400, 300}, Direction::Horizontal | Direction::Vertical, sprite_radians, {0.5,0.5}, {1, 1}, Colors::White); J2D::DrawPartialSprite(image, Vector2(225, 300), Vector2(image->GetDimensions()) * 0.25, Vector2(image->GetDimensions()) * 0.75, sprite_radians, {0.5, 0.5}, {1,1}, Colors::White); J2D::FillRect(Colors::Pinks::HotPink, {68, 120}, {32, 32}); J2D::FillGradientRect(Colors::Red, Colors::Green, Colors::Blue, Colors::White, {100,52}, {100,100}); J2D::FillRoundedRect(Colors::Red, {200, 52}, {100, 100}, 8, 8); J2D::FillRoundedRect(Colors::Purples::BlueViolet, {300, 52}, {100, 100}, 8, 4); J2D::FillCircle(Colors::White, {52, 204}, 50, 24); J2D::OutlineCircle(Colors::White, {153, 204}, 50, 24); auto box = JGL::Fonts::Jupiteroid.MeasureString("Hello g", 16); J2D::FillChamferRect(Colors::Reds::LightSalmon, {150, 400}, {64, 64}, 5); J2D::OutlineRoundedRect(Colors::Reds::LightCoral, {250, 350}, {128, 128}, 10, 2); std::vector points = {{1,1}, {4,4}, {8,8}, {16,16}, {32,32}}; J2D::FillGradientTriangle(Color4(Colors::Red), Color4(Colors::Green), Color4(Colors::Blue), {{0, 275}, {0, 375}, {100, 375}}); J2D::OutlineTriangle(Colors::Blue, {{100, 275}, {0, 275}, {100, 375}}); J2D::DrawGradientLine(Colors::Red, Colors::Blue, {105, 375}, {200, 275}, 2); J2D::DrawString(Colors::Green, "The quick black fox jumps over the lazy dog.", 0, 20, 1, 16); J2D::OutlineRect(Colors::Red, {0, 20}, result, 1); //J2D::DrawString(Colors::Green, "Jupteroid Font", 0.f, 0, 1.f, 16, Jupiteroid); //J2D::DrawString(Colors::White, "Position: " + std::to_string(camera->position.x) + " " + std::to_string(camera->position.y) + " " + std::to_string(camera->position.z), 0, 16, 1,16, Jupiteroid); //J2D::DrawString(Colors::White, "ViewAngle: " + std::to_string(camera->angle.x) + " " + std::to_string(camera->angle.y) + " " + std::to_string(camera->angle.z), 0, 33, 1,16, Jupiteroid); //J2D::DrawString(Colors::White, "Framerate: " + std::to_string((int) fps), 0, 48, 1, 16, Jupiteroid); std::array polygon = {Vector2(200, 400), {220, 420}, {220, 430}, {230, 410}, {200, 400}}; J2D::OutlinePolygon(Colors::White, polygon.data(), polygon.size()); J2D::DrawCubicBezierCurve(Colors::Blues::CornflowerBlue, a.position, b.position, c.position, d.position , 20, 1.5f); a.Draw(); b.Draw(); c.Draw(); d.Draw(); J2D::End(); J2D::Begin(nullptr, nullptr, true); J2D::DrawRenderTarget(j2d_render_target, {0, 0}); //J2D::DrawSprite(image, image_mask, {0, 0}, 0.25, {0.5, 0.5}, {1,1}); J2D::End(); } void OnRefresh(float elapsed) override { fps = GetRefreshRate(); if (IsKeyDown(Keys::RightArrow)) camera->angle.y += 45.f * elapsed; if (IsKeyDown(Keys::LeftArrow)) camera->angle.y -= 45.f * elapsed; if (IsKeyDown(Keys::UpArrow)) camera->angle.x -= 45.f * elapsed; if (IsKeyDown(Keys::DownArrow)) camera->angle.x += 45.f * elapsed; if (IsKeyDown(Keys::Space)) camera->position.y += 1.f * elapsed; if (IsKeyDown(Keys::LeftShift)) camera->position.y -= 1.f * elapsed; //This is wrong of course. Just for testing purposes. if (IsKeyDown(Keys::W)) camera->position.z += 1.f * elapsed; if (IsKeyDown(Keys::S)) camera->position.z -= 1.f * elapsed; if (IsKeyDown(Keys::A)) camera->position.x += 1.f * elapsed; if (IsKeyDown(Keys::D)) camera->position.x -= 1.f * elapsed; auto mouse = GetMouseCoordinates(); a.Update({(float) mouse.x, (float) mouse.y}); b.Update({(float) mouse.x, (float) mouse.y}); c.Update({(float) mouse.x, (float) mouse.y}); d.Update({(float) mouse.x, (float) mouse.y}); display(); int glError = glGetError(); if (glError != GL_NO_ERROR) std::cout << glError << std::endl; SwapBuffers(); } void OnMouseButtonDown(const ReWindow::MouseButtonDownEvent & ev) override { RWindow::OnMouseButtonDown(ev); a.Grab(); b.Grab(); c.Grab(); d.Grab(); } void OnMouseButtonUp(const ReWindow::MouseButtonUpEvent & ev) override { RWindow::OnMouseButtonUp(ev); a.Release(); b.Release(); c.Release(); d.Release(); } bool OnResizeRequest(const ReWindow::WindowResizeRequestEvent& e) override {return true;} JGLDemoWindow(const std::string& title, int width, int height) : ReWindow::OpenGLWindow(title, width, height, 2, 1) {} }; int main(int argc, char** argv) { auto* window = new JGLDemoWindow("JGL Demo Window", 1280, 720); if (!window->Open()) exit(-1); window->initGL(); window->SetResizable(true); window->SetVsyncEnabled(false); std::ifstream file("assets/models/cube.amo"); if (!file.is_open()) return -1; Shader::OnCompilationErrorMessage += [] (std::string type, std::string info) { std::cout << type << ", " << info << std::endl; }; /* std::stringstream buffer; buffer << file.rdbuf(); std::string file_text = buffer.str(); file.close(); std::cout << file_text << std::endl; auto result = VertexArray::LoadAMO(file_text); */ //ReWindow::Logger::Error.EnableConsole(false); //ReWindow::Logger::Warning.EnableConsole(false); //ReWindow::Logger::Debug.EnableConsole(false); while (window->IsAlive()) window->ManagedRefresh(); return 0; }