diff --git a/include/JGL/JGL.h b/include/JGL/JGL.h index 8c35642..06b9cdf 100644 --- a/include/JGL/JGL.h +++ b/include/JGL/JGL.h @@ -53,8 +53,8 @@ namespace JGL { using namespace J3ML::LinearAlgebra; using namespace J3ML::Geometry; - [[nodiscard]] bool Init(const Vector2& window_size, float fovY, float far_plane); - void Update(const Vector2& window_size); + [[nodiscard]] bool Init(const Vector2i& window_size, float fovY, float far_plane); + void Update(const Vector2i& window_size); inline void PurgeFontCache() { JGL::fontCache.purgeCache(); } diff --git a/main.cpp b/main.cpp index 49d28ec..3d8ae7a 100644 --- a/main.cpp +++ b/main.cpp @@ -118,7 +118,7 @@ public: void initGL() { camera = new Camera; - if (!JGL::Init({(float) GetSize().x, (float) GetSize().y}, 75, 100)) + if (!JGL::Init({ GetSize().x, GetSize().y}, 75, 100)) Logger::Fatal("Initialization failed."); // Load a custom font. @@ -146,7 +146,7 @@ public: pulse++; float dt = GetDeltaTime(); - JGL::Update({(float) GetSize().x, (float) GetSize().y}); + JGL::Update({ GetSize().x, GetSize().y }); if (fov_increasing) fov += 0.025; @@ -184,7 +184,6 @@ public: AABB boxes[1] = {{Vector3(-0.2125, -0.2125,0.28750), Vector3(0.2125,0.2125,0.7125)}}; J3D::BatchWireframeAABB(Colors::Yellow, boxes, 1, 1); - J3D::End(); J2D::Begin(j2d_render_target, true); @@ -207,14 +206,12 @@ public: J2D::DrawGradientLine(Colors::Red, Colors::Blue, {105, 375}, {200, 275}, 2); auto result = Jupiteroid.MeasureString("Jupiteroid Font", 16); - //J2D::FillRect(Colors::Gray, {0, 0}, result); 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::FillPolygon(Colors::White, {{200, 400}, {220, 420}, {220, 430}, {230, 410}, {200, 400}}); J2D::DrawCubicBezierCurve(Colors::Blues::CornflowerBlue, a.position, b.position, @@ -227,16 +224,10 @@ public: c.Draw(); d.Draw(); J2D::End(); - RenderTarget::Blit(Colors::Red, {0, 0}, j2d_render_target); - - //Draw the Render Target that we just drew all that stuff onto. J2D::Begin(); J2D::DrawRenderTarget(j2d_render_target, {0, 0}); J2D::DrawSprite(image, image_mask, {0, 0}, 0.25, {0.5, 0.5}, {1,1}); - //J2D::DrawSprite(, {0, 0}, 0, {0.5, 0.5}, {1,1}, Colors::White); - - //J2D::DrawSprite( {0, 0}, 0, {0.5, 0.5}, {1,1}, Colors::White); J2D::End(); } diff --git a/src/JGL.cpp b/src/JGL.cpp index 3709863..6f2939e 100644 --- a/src/JGL.cpp +++ b/src/JGL.cpp @@ -10,7 +10,7 @@ namespace JGL { using namespace J3ML; - bool Init(const Vector2& window_size, float fovY, float far_plane) { + bool Init(const Vector2i& ws, float fovY, float far_plane) { gladLoadGL(); if (!MeetsRequirements()) { Logger::Fatal("The graphics driver does not meet the minimum requirements to run this program."); @@ -20,15 +20,18 @@ namespace JGL { InitTextEngine(); Fonts::Init(); ShapeCache::Init(); - OpenGLState::window_size = window_size; + JGL::window_size = ws; J3D::fov = fovY; J3D::far_plane = far_plane; return true; } - void Update(const Vector2& window_size) { - OpenGLState::window_size = window_size; - glViewport(0, 0, (int) window_size.x, (int) window_size.y); + void Update(const Vector2i& ws) { + if (state_stack.Size()) + Logger::Error("You shouldn't be running JGL::Update while inside a J2D or J3D context."); + + JGL::window_size = ws; + glViewport(0, 0, window_size.x, window_size.y); } bool MeetsRequirements() { diff --git a/src/renderer/OpenGL/J2D.cpp b/src/renderer/OpenGL/J2D.cpp index 9f0bcc6..ed6329d 100644 --- a/src/renderer/OpenGL/J2D.cpp +++ b/src/renderer/OpenGL/J2D.cpp @@ -3,174 +3,70 @@ #include #include "internals/internals.h" -void JGL::J2D::Begin(RenderTarget* rt, bool clear_buffers) { - GLfloat old_clear_color[4]; - if (rt != nullptr) { - OpenGLState::render_target = rt; - glGetFloatv(GL_COLOR_CLEAR_VALUE, old_clear_color); - glGetIntegerv(GL_VIEWPORT, OpenGLState::viewport); - OpenGLState::current_fbo = JGL::RenderTarget::GetActiveGLFramebufferHandle(); - JGL::RenderTarget::SetActiveGLRenderTarget(*rt); - if (!rt->GetTexture()->Inverted()) - Logger::Warning("You're rendering onto a texture that is upside-down. Your draw commands won't work how you'd expect."); - } +void JGL::J2D::Begin(RenderTarget* render_target, bool clear_buffers) { + State current_state = default_state; + state_stack.Push(State::SaveState()); + glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); - if (rt == nullptr) - glViewport(0, 0, (int) OpenGLState::window_size.x, (int) OpenGLState::window_size.y), - glOrtho(0, OpenGLState::window_size.x, OpenGLState::window_size.y, 0, -1, 1); - else - glOrtho(0, rt->GetDimensions().x, rt->GetDimensions().y, 0, -1, 1); + if (render_target) { + if (!render_target->GetTexture()->Inverted()) + Logger::Warning("You're rendering onto a texture that is upside-down. Your draw commands won't work how you'd expect."); + + current_state.current_fbo = render_target->GetGLFramebufferObjectHandle(); + current_state.viewport[2] = render_target->GetDimensions().x; + current_state.viewport[3] = render_target->GetDimensions().y; + + current_state.clear_color[0] = render_target->GetClearColor().RN(); + current_state.clear_color[1] = render_target->GetClearColor().GN(); + current_state.clear_color[2] = render_target->GetClearColor().BN(); + current_state.clear_color[3] = render_target->GetClearColor().AN(); + } + else { + current_state.viewport[2] = window_size.x; + current_state.viewport[3] = window_size.y; + } + + State::RestoreState(current_state); + if (render_target != nullptr && clear_buffers) { + glClearColor(render_target->GetClearColor().RedChannelNormalized(), render_target->GetClearColor().GreenChannelNormalized(), render_target->GetClearColor().BlueChannelNormalized(), render_target->GetClearColor().AlphaChannelNormalized()); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + } + + glOrtho(0, current_state.viewport[2], current_state.viewport[3], 0, -1, 1); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); - - //Get what the draw color was before we did anything. - glGetFloatv(GL_CURRENT_COLOR, OpenGLState::oldColor); - glColor4fv(OpenGLState::baseColor); - - glGetIntegerv(GL_ACTIVE_TEXTURE, &OpenGLState::activeTextureUnit); - OpenGLState::activeTextureUnit = OpenGLState::activeTextureUnit - GL_TEXTURE0; - - if (OpenGLState::activeTextureUnit != 0) { - glActiveTexture(GL_TEXTURE0); - glClientActiveTexture(GL_TEXTURE0); - } - - if (glIsEnabled(GL_DEPTH_TEST)) - OpenGLState::wasDepthTestEnabled = true, - glDisable(GL_DEPTH_TEST); - else - OpenGLState::wasDepthTestEnabled = false; - - if (!glIsEnabled(GL_VERTEX_ARRAY)) - OpenGLState::wasVertexArraysEnabled = false, - glEnableClientState(GL_VERTEX_ARRAY); - else - OpenGLState::wasVertexArraysEnabled = true; - - if (glIsEnabled(GL_NORMAL_ARRAY)) - OpenGLState::wasNormalArrayEnabled = true, - glDisableClientState(GL_NORMAL_ARRAY); - else - OpenGLState::wasNormalArrayEnabled = false; - - if (!glIsEnabled(GL_CULL_FACE)) - OpenGLState::wasCullFaceEnabled = false, - glEnable(GL_CULL_FACE), - glCullFace(GL_BACK); - else - OpenGLState::wasCullFaceEnabled = true; - - if (!glIsEnabled(GL_BLEND)) - OpenGLState::wasBlendEnabled = false, - glEnable(GL_BLEND), - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - else - OpenGLState::wasBlendEnabled = true; - - if (glIsEnabled(GL_TEXTURE_2D)) - OpenGLState::wasTexture2DEnabled = true, - glDisable(GL_TEXTURE_2D); - - if (glIsEnabled(GL_TEXTURE_COORD_ARRAY)) - OpenGLState::wasTextureCoordArrayEnabled = true; - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - - if (glIsEnabled(GL_COLOR_ARRAY)) - OpenGLState::wasColorArrayEnabled = true, - glDisableClientState(GL_COLOR_ARRAY); - else - OpenGLState::wasColorArrayEnabled = false; - - if (!inJ3D) - inJ2D = true; - else { Logger::Error("Beginning J2D context inside of J3D context?"); } - - if (rt != nullptr && clear_buffers) { - glClearColor(rt->GetClearColor().RedChannelNormalized(), rt->GetClearColor().GreenChannelNormalized(), rt->GetClearColor().BlueChannelNormalized(), rt->GetClearColor().AlphaChannelNormalized()); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glClearColor(old_clear_color[0], old_clear_color[1], old_clear_color[2], old_clear_color[3]); - } } void JGL::J2D::End() { - //Change back to the previous projection (The 3D one in Re3D's case.) + //Change back to the previous projection. glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); - if (OpenGLState::wasDepthTestEnabled) - glEnable(GL_DEPTH_TEST); - if (!OpenGLState::wasVertexArraysEnabled) - glDisableClientState(GL_VERTEX_ARRAY); + auto previous_state = state_stack.PreviousState(); + if (!previous_state) + Logger::Fatal("Calling J2D::End before J2D::Begin."); - if (!OpenGLState::wasCullFaceEnabled) - glDisable(GL_CULL_FACE); - - if (!OpenGLState::wasBlendEnabled) - glDisable(GL_BLEND); - - // Select whatever texture mapper was selected before. - glActiveTexture(GL_TEXTURE0 + OpenGLState::activeTextureUnit); - glClientActiveTexture(GL_TEXTURE0 + OpenGLState::activeTextureUnit); - - if (OpenGLState::wasTexture2DEnabled) - glEnable(GL_TEXTURE_2D); - - if (OpenGLState::wasTextureCoordArrayEnabled) - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - - if (OpenGLState::wasNormalArrayEnabled) - glEnableClientState(GL_NORMAL_ARRAY); - - if (OpenGLState::wasColorArrayEnabled) - glEnableClientState(GL_COLOR_ARRAY); - - //Put the draw color back how it was before. - glColor4fv(OpenGLState::oldColor); - - if (OpenGLState::render_target != nullptr) { - OpenGLState::render_target->MSAABlit(); - OpenGLState::render_target = nullptr; - glBindFramebuffer(GL_FRAMEBUFFER, OpenGLState::current_fbo); - glViewport(OpenGLState::viewport[0], OpenGLState::viewport[1], OpenGLState::viewport[2], OpenGLState::viewport[3]); - } - inJ2D = false; -} - -void JGL::J2D::RequiredLight(const JGL::LightBase* light) { - bool success = false; - for (auto& item : required_lights) - if (item == nullptr) { - item = light; - success = true; - break; - } - - if (!success) - Logger::Error("You cannot specify more than 8 required lights."); -} - -void JGL::J2D::OptionalLights(const LightBase** lights, const size_t& light_count) { - for (size_t i = 0; i < light_count; i++) - light_array.push_back(lights[i]); + State::RestoreState(*previous_state); + state_stack.Pop(); } void JGL::J2D::DrawPoint(const Color4& color, const Vector2& coordinates, float radius) { - if (!inJ2D) + if (!state_stack.Size()) Logger::Error("Drawing J2D element before J2D begin."); glPointSize(radius); glColor4ubv(color.ptr()); glVertexPointer(2, GL_FLOAT, sizeof(Vector2), coordinates.ptr()); glDrawArrays(GL_POINTS, 0, 1); - glColor4fv(OpenGLState::baseColor); + glColor4fv(default_state.draw_color); } void JGL::J2D::DrawPoint(const Color4& color, float x, float y, float radius) { @@ -178,7 +74,7 @@ void JGL::J2D::DrawPoint(const Color4& color, float x, float y, float radius) { } void JGL::J2D::DrawLine(const Color4& color, const Vector2& A, const Vector2& B, float thickness) { - if (!inJ2D) + if (!state_stack.Size()) Logger::Error("Drawing J2D element before J2D begin."); Vector2 vertices[] = {A, B}; @@ -186,7 +82,7 @@ void JGL::J2D::DrawLine(const Color4& color, const Vector2& A, const Vector2& B, glColor4ubv(color.ptr()); glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices); glDrawArrays(GL_LINES, 0, 2); - glColor4fv(OpenGLState::baseColor); + glColor4fv(default_state.draw_color); } void JGL::J2D::DrawLine(const Color4& color, float x, float y, float w, float h, float thickness) { @@ -194,14 +90,14 @@ void JGL::J2D::DrawLine(const Color4& color, float x, float y, float w, float h, } void J2D::DrawLines(const Color4& color, const Vector2* points, const size_t& point_count, float thickness) { - if (!inJ2D) + if (!state_stack.Size()) Logger::Error("Drawing J2D element before J2D begin."); glLineWidth(thickness); glColor3ubv(color.ptr()); glVertexPointer(2, GL_FLOAT, sizeof(Vector2), points); glDrawArrays(GL_LINE_STRIP, 0, point_count); - glColor4fv(OpenGLState::baseColor); + glColor4fv(default_state.draw_color); } void JGL::J2D::DrawDottedLine(const Color4& color, const Vector2& A, const Vector2& B, float spacing, float thickness) { @@ -254,7 +150,7 @@ void JGL::J2D::DrawDashedLine(const Color4& color, float x1, float y1, float x2, } void JGL::J2D::DrawGradientLine(const Color4& color1, const Color4& color2, const Vector2& A, const Vector2& B, float thickness) { - if (!inJ2D) + if (!state_stack.Size()) Logger::Error("Drawing J2D element before J2D begin."); Vector2 vertices[] = {A, B}; @@ -267,7 +163,7 @@ void JGL::J2D::DrawGradientLine(const Color4& color1, const Color4& color2, cons glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices); glDrawArrays(GL_LINES, 0, 2); glDisableClientState(GL_COLOR_ARRAY); - glColor4fv(OpenGLState::baseColor); + glColor4fv(default_state.draw_color); } void DrawGradientLine(const Color4& color1, const Color4& color2, float x, float y, float w, float h, float thickness) { @@ -275,7 +171,7 @@ void DrawGradientLine(const Color4& color1, const Color4& color2, float x, float } void JGL::J2D::OutlineRect(const Color4& color, const Vector2& pos, const Vector2& size, float thickness) { - if (!inJ2D) + if (!state_stack.Size()) Logger::Error("Drawing J2D element before J2D begin."); Vector2 vertices[] = {{pos.x, pos.y}, {pos.x, pos.y + size.y}, {pos.x + size.x, pos.y + size.y}, {pos.x + size.x, pos.y}}; @@ -284,11 +180,11 @@ void JGL::J2D::OutlineRect(const Color4& color, const Vector2& pos, const Vector glColor4ubv(color.ptr()); glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices); glDrawArrays(GL_LINE_LOOP, 0, 4); - glColor4fv(OpenGLState::baseColor); + glColor4fv(default_state.draw_color); } void JGL::J2D::FillRect(const Color4& color, const Vector2& pos, const Vector2& size) { - if (!inJ2D) + if (!state_stack.Size()) Logger::Error("Drawing J2D element before J2D begin."); glColor4ubv(color.ptr()); @@ -301,11 +197,11 @@ void JGL::J2D::FillRect(const Color4& color, const Vector2& pos, const Vector2& glDrawArrays(GL_QUADS, 0, 4); glBindBuffer(GL_ARRAY_BUFFER, 0); glPopMatrix(); - glColor4fv(OpenGLState::baseColor); + glColor4fv(default_state.draw_color); } void JGL::J2D::FillGradientRect(const Color4& color1, const Color4& color2, const Direction& gradient, const Vector2& pos, const Vector2& size) { - if (!inJ2D) + if (!state_stack.Size()) Logger::Error("Drawing J2D element before J2D begin."); Vector2 vertices[] = {{pos.x, pos.y}, {pos.x, pos.y + size.y}, {pos.x + size.x, pos.y + size.y}, {pos.x + size.x, pos.y}}; @@ -334,11 +230,11 @@ void JGL::J2D::FillGradientRect(const Color4& color1, const Color4& color2, cons glColorPointer(4, GL_FLOAT, 0, colors.data()); glDrawArrays(GL_QUADS, 0, 4); glDisableClientState(GL_COLOR_ARRAY); - glColor4fv(OpenGLState::baseColor); + glColor4fv(default_state.draw_color); } void JGL::J2D::FillRoundedRect(const Color4& color, const Vector2& pos, const Vector2& size, float radius, unsigned int subdivisions) { - if (!inJ2D) + if (!state_stack.Size()) Logger::Error("Drawing J2D element before J2D begin."); JGL::J2D::FillRect(color, {pos.x + radius, pos.y}, {size.x - 2 * radius, size.y}); @@ -427,7 +323,7 @@ void JGL::J2D::DrawSprite(const JGL::RenderTarget& rt, const Vector2& position, void JGL::J2D::DrawSprite(const Texture& texture, const Texture& alpha_mask, const Vector2& position, float rad_rotation, const Vector2& origin, const Vector2& scale,const Color4& color, JGL::Direction inversion) { - if (!inJ2D) + if (!state_stack.Size()) Logger::Error("Drawing J2D element before J2D begin."); if (texture.GetDimensions() != alpha_mask.GetDimensions()) @@ -510,7 +406,7 @@ void JGL::J2D::DrawSprite(const Texture& texture, const Texture& alpha_mask, con glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisable(GL_TEXTURE_2D); - glColor4fv(OpenGLState::baseColor); + glColor4fv(default_state.draw_color); } void JGL::J2D::DrawSprite(const Texture* texture, const Texture* alpha_mask, const Vector2& position, float rad_rotation, @@ -567,7 +463,7 @@ void JGL::J2D::DrawPartialRenderTarget(const JGL::RenderTarget* rt, const Vector void JGL::J2D::DrawSprite(const Texture& texture, const Vector2& pos, float rad_rotation, const Vector2& origin, const Vector2& scale, const Color4& color, Direction inversion) { - if (!inJ2D) + if (!state_stack.Size()) Logger::Error("Drawing J2D element before J2D begin."); @@ -621,7 +517,7 @@ void JGL::J2D::DrawSprite(const Texture& texture, const Vector2& pos, float rad_ glTexCoordPointer(2, GL_FLOAT, sizeof(Vector2), textureCoordinates.data()); glDrawArrays(GL_QUADS, 0, 4); glBindTexture(GL_TEXTURE_2D, 0); - glColor4fv(OpenGLState::baseColor); + glColor4fv(default_state.draw_color); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisable(GL_TEXTURE_2D); } @@ -640,7 +536,7 @@ void JGL::J2D::DrawSprite(const Texture& texture, float positionX, float positio void JGL::J2D::DrawPartialSprite(const Texture& texture, const Vector2& position, const Vector2& sub_texture_position, const Vector2& sub_texture_size, float rad_rotation, const Vector2& origin, const Vector2& scale, const Color4& color, Direction inversion) { - if (!inJ2D) + if (!state_stack.Size()) Logger::Error("Drawing J2D element before J2D begin."); const Vector2 textureSize = Vector2(texture.GetDimensions()); @@ -710,7 +606,7 @@ void JGL::J2D::DrawPartialSprite(const Texture& texture, const Vector2& position glTexCoordPointer(2, GL_FLOAT, 0, textureCoordinates.data()); glDrawArrays(GL_QUADS, 0, 4); glBindTexture(GL_TEXTURE_2D, 0); - glColor4fv(OpenGLState::baseColor); + glColor4fv(default_state.draw_color); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisable(GL_TEXTURE_2D); } @@ -726,7 +622,7 @@ void JGL::J2D::DrawPartialSprite(const JGL::Texture& texture, float positionX, f } void JGL::J2D::DrawMirrorSprite(const Texture& texture, const Vector2& position, Direction mirror_axis, float rad_rotation, const Vector2& origin, const Vector2& scale, const Color4& color) { - if (!inJ2D) + if (!state_stack.Size()) Logger::Error("Drawing J2D element before J2D begin."); if (mirror_axis == Direction::None) @@ -804,13 +700,13 @@ void JGL::J2D::DrawMirrorSprite(const Texture& texture, const Vector2& position, glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); glBindTexture(GL_TEXTURE_2D, 0); - glColor4fv(OpenGLState::baseColor); + glColor4fv(default_state.draw_color); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisable(GL_TEXTURE_2D); } void JGL::J2D::OutlineCircle(const Color4& color, const Vector2& center, float radius, unsigned int subdivisions, float thickness) { - if (!inJ2D) + if (!state_stack.Size()) Logger::Error("Drawing J2D element before J2D begin."); float step = (2.f * Math::Pi) / (float) subdivisions; @@ -833,11 +729,11 @@ void JGL::J2D::OutlineCircle(const Color4& color, const Vector2& center, float r glColor4ubv(color.ptr()); glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data()); glDrawArrays(GL_LINE_LOOP, 0, (int) vertices.size()); - glColor4fv(OpenGLState::baseColor); + glColor4fv(default_state.draw_color); } void JGL::J2D::FillCircle(const Color4& color, const Vector2& center, float radius, unsigned int subdivisions) { - if (!inJ2D) + if (!state_stack.Size()) Logger::Error("Drawing J2D element before J2D begin."); GLfloat angle, x, y; @@ -861,11 +757,11 @@ void JGL::J2D::FillCircle(const Color4& color, const Vector2& center, float radi glColor4ubv(color.ptr()); glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data()); glDrawArrays(GL_TRIANGLE_FAN, 0, (int) vertices.size()); - glColor4fv(OpenGLState::baseColor); + glColor4fv(default_state.draw_color); } void JGL::J2D::OutlineTriangle(const Color4& color, const Triangle2D& tri, float thickness) { - if (!inJ2D) + if (!state_stack.Size()) Logger::Error("Drawing J2D element before J2D begin."); Vector2 vertices[] = {{tri.A.x, tri.A.y}, {tri.B.x, tri.B.y}, {tri.C.x, tri.C.y}}; @@ -874,11 +770,11 @@ void JGL::J2D::OutlineTriangle(const Color4& color, const Triangle2D& tri, float glColor4ubv(color.ptr()); glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices); glDrawArrays(GL_LINE_LOOP, 0, 3); - glColor4fv(OpenGLState::baseColor); + glColor4fv(default_state.draw_color); } void JGL::J2D::FillTriangle(const Color4& color, const Triangle2D& tri) { - if (!inJ2D) + if (!state_stack.Size()) Logger::Error("Drawing J2D element before J2D begin."); Vector2 vertices[] = {{tri.A.x, tri.A.y}, {tri.B.x, tri.B.y}, {tri.C.x, tri.C.y}}; @@ -886,11 +782,11 @@ void JGL::J2D::FillTriangle(const Color4& color, const Triangle2D& tri) { glColor4ubv(color.ptr()); glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices); glDrawArrays(GL_TRIANGLES, 0, 3); - glColor4fv(OpenGLState::baseColor); + glColor4fv(default_state.draw_color); } void JGL::J2D::FillGradientTriangle(const Color4& a_color, const Color4& b_color, const Color4& c_color, const Triangle2D& tri) { - if (!inJ2D) + if (!state_stack.Size()) Logger::Error("Drawing J2D element before J2D begin."); Vector2 vertices[] = {{tri.A.x, tri.A.y}, {tri.B.x, tri.B.y}, {tri.C.x, tri.C.y}}; @@ -903,7 +799,7 @@ void JGL::J2D::FillGradientTriangle(const Color4& a_color, const Color4& b_color glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices); glDrawArrays(GL_TRIANGLES, 0, 3); glDisableClientState(GL_COLOR_ARRAY); - glColor4fv(OpenGLState::baseColor); + glColor4fv(default_state.draw_color); } //TODO render all in once pass with GL_LINE_LOOP instead of separate lines. @@ -926,7 +822,7 @@ void JGL::J2D::DrawCubicBezierCurve(const Color4& color, const Vector2& controlA } void JGL::J2D::OutlinePolygon(const Color4& color, const Vector2* points, int points_size, float thickness) { - if (!inJ2D) + if (!state_stack.Size()) Logger::Error("Drawing J2D element before J2D begin."); if (points[0] != points[points_size -1]) @@ -936,7 +832,7 @@ void JGL::J2D::OutlinePolygon(const Color4& color, const Vector2* points, int po glColor4ubv(color.ptr()); glVertexPointer(2, GL_FLOAT, sizeof(Vector2), points); glDrawArrays(GL_LINE_LOOP, 0, points_size); - glColor4fv(OpenGLState::baseColor); + glColor4fv(default_state.draw_color); } void JGL::J2D::DrawGradientLine(const Color4& color_a, const Color4& color_b, float x, float y, float w, float h, @@ -946,7 +842,7 @@ void JGL::J2D::DrawGradientLine(const Color4& color_a, const Color4& color_b, fl void JGL::J2D::DrawArc(const Color4& color, const Vector2& center, float radius, float arc_begin, float arc_end, unsigned int subdivisions, float thickness) { - if (!inJ2D) + if (!state_stack.Size()) Logger::Error("Drawing J2D element before J2D begin."); if (arc_begin == arc_end) @@ -974,7 +870,7 @@ void JGL::J2D::DrawArc(const Color4& color, const Vector2& center, float radius, glColor4ubv(color.ptr()); glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data()); glDrawArrays(GL_LINE_STRIP, 0, (int) vertices.size()); - glColor4fv(OpenGLState::baseColor); + glColor4fv(default_state.draw_color); } void JGL::J2D::OutlineRoundedRect(const Color4& color, const Vector2& pos, const Vector2& size, float radius, float thickness) @@ -1061,7 +957,7 @@ void JGL::J2D::OutlineChamferRect(const Color4& color, const Vector2& pos, const glColor4ubv(color.ptr()); glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices); glDrawArrays(GL_LINE_LOOP, 0, 8); - glColor4fv(OpenGLState::baseColor); + glColor4fv(default_state.draw_color); } void JGL::J2D::DrawPoints(const Color4& color, const Vector2* points, int num_points, float radius) { @@ -1069,7 +965,7 @@ void JGL::J2D::DrawPoints(const Color4& color, const Vector2* points, int num_po glColor4ubv(color.ptr()); glVertexPointer(2, GL_FLOAT, sizeof(Vector2), points); glDrawArrays(GL_POINTS, 0, num_points); - glColor4fv(OpenGLState::baseColor); + glColor4fv(default_state.draw_color); } void JGL::J2D::FIllTriangle(const Color4& color, const Vector2& triA, const Vector2& triB, const Vector2& triC) { @@ -1083,7 +979,7 @@ void JGL::J2D::FillGradientTriangle(const Color4& a_color, const Color4& b_color void JGL::J2D::OutlineEllipse(const Color4& color, const Vector2& position, float radius_x, float radius_y, float thickness, int subdivisions) { - if (!inJ2D) + if (!state_stack.Size()) Logger::Error("Drawing J2D element before J2D begin."); float step = (2.f * Math::Pi) / (float) subdivisions; @@ -1105,11 +1001,11 @@ void JGL::J2D::OutlineEllipse(const Color4& color, const Vector2& position, floa glColor4ubv(color.ptr()); glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data()); glDrawArrays(GL_LINE_LOOP, 0, (int) vertices.size()); - glColor4fv(OpenGLState::baseColor); + glColor4fv(default_state.draw_color); } void JGL::J2D::FillEllipse(const Color4& color, const Vector2& position, float radius_x, float radius_y, int subdivisions) { - if (!inJ2D) + if (!state_stack.Size()) Logger::Error("Drawing J2D element before J2D begin."); GLfloat angle, x, y; @@ -1133,5 +1029,5 @@ void JGL::J2D::FillEllipse(const Color4& color, const Vector2& position, float r glColor4ubv(color.ptr()); glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data()); glDrawArrays(GL_TRIANGLE_FAN, 0, (int) vertices.size()); - glColor4fv(OpenGLState::baseColor); + glColor4fv(default_state.draw_color); } diff --git a/src/renderer/OpenGL/J3D.cpp b/src/renderer/OpenGL/J3D.cpp index ff8ee38..579ba8c 100644 --- a/src/renderer/OpenGL/J3D.cpp +++ b/src/renderer/OpenGL/J3D.cpp @@ -28,7 +28,7 @@ void JGL::J3D::ChangeFarPlane(float far_plane) { void JGL::J3D::RequiredLight(const JGL::LightBase* light) { bool success = false; - for (auto& i : required_lights) + for (auto& i : current_state.required_lights) if (i == nullptr) { i = light; success = true; @@ -41,86 +41,82 @@ void JGL::J3D::RequiredLight(const JGL::LightBase* light) { void JGL::J3D::OptionalLights(const JGL::LightBase** lights, const size_t& light_count) { for (size_t i = 0; i < light_count; i++) - optional_lights.push_back(lights[i]); + current_state.optional_lights.push_back(lights[i]); } void JGL::J3D::Begin(bool two_pass) { - auto aspect = (float) OpenGLState::window_size.x / (float) OpenGLState::window_size.y; + auto aspect = (float) window_size.x / (float) window_size.y; glMatrixMode(GL_PROJECTION); glLoadIdentity(); glMultMatrixf(OpenGLPerspectiveProjectionRH(fov, aspect, 0.001, far_plane).data()); glMatrixMode(GL_MODELVIEW); //Get what the draw color was before we did anything. - glGetFloatv(GL_CURRENT_COLOR, OpenGLState::oldColor); - glColor4fv(OpenGLState::baseColor); + glGetFloatv(GL_CURRENT_COLOR, current_state.draw_color); + glColor4fv(current_state.draw_color); if (!glIsEnabled(GL_DEPTH_TEST)) - OpenGLState::wasDepthTestEnabled = false, + current_state.depth_test = false, glEnable(GL_DEPTH_TEST); else - OpenGLState::wasDepthTestEnabled = true; + current_state.depth_test = true; - OpenGLState::wasVertexArraysEnabled = false; + current_state.vertex_array = false; if (!glIsEnabled(GL_VERTEX_ARRAY)) - OpenGLState::wasVertexArraysEnabled = false, + current_state.vertex_array = false, glEnableClientState(GL_VERTEX_ARRAY); if (glIsEnabled(GL_NORMAL_ARRAY)) - OpenGLState::wasNormalArrayEnabled = true, + current_state.normal_array = true, glDisableClientState(GL_NORMAL_ARRAY); if (glIsEnabled(GL_TEXTURE_COORD_ARRAY)) - OpenGLState::wasTextureCoordArrayEnabled = true, + current_state.texture_coordinate_array = true, glDisableClientState(GL_TEXTURE_COORD_ARRAY); if (glIsEnabled(GL_TEXTURE_2D)) - OpenGLState::wasTexture2DEnabled = true, + current_state.texture_2D = true, glDisable(GL_TEXTURE_2D); - OpenGLState::wasCullFaceEnabled = false; + current_state.cull_face = false; if (glIsEnabled(GL_CULL_FACE)) - OpenGLState::wasCullFaceEnabled = true, + current_state.cull_face = true, glDisable(GL_CULL_FACE); if (!glIsEnabled(GL_BLEND)) - OpenGLState::wasBlendEnabled = false, + current_state.blend = false, glEnable(GL_BLEND), glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); else - OpenGLState::wasBlendEnabled = true; + current_state.blend = true; // Reset the lights. - required_lights = empty_light_array; - optional_lights = {}; + current_state.required_lights = empty_light_array; + current_state.optional_lights = {}; glDisable(GL_LIGHTING); - if (!inJ2D) - inJ3D = true; - else - Logger::Error("Beginning J3D context inside of J2D context?"); } void JGL::J3D::End() { - if (!OpenGLState::wasDepthTestEnabled) + if (!current_state.depth_test) glDisable(GL_DEPTH_TEST); - if (!OpenGLState::wasVertexArraysEnabled) + if (!current_state.vertex_array) glDisableClientState(GL_VERTEX_ARRAY); - if (OpenGLState::wasTexture2DEnabled) + if (current_state.texture_2D) glEnable(GL_TEXTURE_2D); - if (!OpenGLState::wasBlendEnabled) + if (!current_state.blend) glDisable(GL_BLEND); - if (OpenGLState::wasCullFaceEnabled) + if (current_state.cull_face) glEnable(GL_CULL_FACE); - if (OpenGLState::wasNormalArrayEnabled) + if (current_state.normal_array) glEnableClientState(GL_NORMAL_ARRAY); - if (OpenGLState::wasTextureCoordArrayEnabled) + if (current_state.texture_coordinate_array) glEnableClientState(GL_TEXTURE_COORD_ARRAY); if (glIsEnabled(GL_LIGHTING)) { @@ -135,25 +131,21 @@ void JGL::J3D::End() { glDisable(GL_LIGHT7); } - required_lights = empty_light_array; - optional_lights = {}; + current_state.required_lights = empty_light_array; + current_state.optional_lights = {}; //Put the draw color back how it was before. - glColor4fv(OpenGLState::oldColor); - inJ3D = false; + glColor4fv(current_state.draw_color); } void JGL::J3D::DrawLine(const Color4& color, const Vector3& A, const Vector3& B, float thickness) { - if (!inJ3D) - Logger::Error("Drawing J3D element before J3D begin."); - Vector3 vertices[] = {A, B}; glLineWidth(thickness); glColor4ubv(color.ptr()); glVertexPointer(3, GL_FLOAT, sizeof(Vector3), vertices); glDrawArrays(GL_LINES, 0, 2); - glColor4fv(OpenGLState::baseColor); + glColor4fv(current_state.draw_color); } void JGL::J3D::WireframeSphere(const Color4& color, const Vector3& position, float radius, float thickness, unsigned int sectors, unsigned int stacks) { @@ -166,9 +158,6 @@ void JGL::J3D::WireframeSphere(const Color4& color, const Sphere& sphere, float } void JGL::J3D::BatchWireframeSphere(const Color4& color, const Sphere* spheres, const size_t& sphere_count, float thickness, unsigned int sectors, unsigned int stacks) { - if (!inJ3D) - Logger::Error("Drawing J3D element before J3D begin."); - // Create one sphere with a radius of 1 about 0, 0. float r = 1; std::vector vertices((sectors + 1) * (stacks + 1)); @@ -204,7 +193,7 @@ void JGL::J3D::BatchWireframeSphere(const Color4& color, const Sphere* spheres, glDrawArrays(GL_LINE_LOOP, 0, vertices.size()); glPopMatrix(); } - glColor4fv(OpenGLState::baseColor); + glColor4fv(current_state.draw_color); } void JGL::J3D::WireframeRevoSphere(const Color4& color, const Vector3& position, float radius, float thickness, unsigned int sectors, unsigned int revolutions, bool draw_stacks) { @@ -263,14 +252,10 @@ void JGL::J3D::BatchWireframeRevoSphere(const Color4& color, const Sphere* spher glPopMatrix(); } glBindBuffer(GL_ARRAY_BUFFER, 0); - glColor4fv(OpenGLState::baseColor); + glColor4fv(current_state.draw_color); } -void JGL::J3D::WireframeIcosphere(const Color4& color, const Vector3& position, float radius, float thickness, - unsigned int subdivisions) { - - if (!inJ3D) - Logger::Error("Drawing J3D element before J3D begin."); +void JGL::J3D::WireframeIcosphere(const Color4& color, const Vector3& position, float radius, float thickness, unsigned int subdivisions) { // NOTE2SELF: Code i'm borrowing this from uses float-packed-arrays rather than discrete Vectors // working on translating that correctly... @@ -341,9 +326,6 @@ void JGL::J3D::WireframeIcosphere(const Color4& color, const Vector3& position, } void JGL::J3D::WireframeIcosahedron(const Color4& color, const Vector3& position, float radius, float thickness) { - if (!inJ3D) - Logger::Error("Drawing J3D element before J3D begin."); - // TODO: Revise this once J3ML::Geometry::Icosahedron is implemented. const float h_angle = J3ML::Math::Pi / 180.f * 72.f; // 72 degree = 360 / 5; const float v_angle = J3ML::Math::Atan(1.0f / 2.f); // elevation = 26.565; @@ -382,7 +364,7 @@ void JGL::J3D::WireframeIcosahedron(const Color4& color, const Vector3& position //glBindBuffer(GL_ARRAY_BUFFER, vertices.size()); glVertexPointer(3, GL_FLOAT, sizeof(Vector3), vertices.data()); glDrawArrays(GL_TRIANGLE_STRIP, 0, vertices.size()); - glColor4fv(OpenGLState::baseColor); + glColor4fv(current_state.draw_color); } void JGL::J3D::BatchWireframeAABB(const Color4& color, const AABB* boxes, const size_t& box_count, float thickness) { @@ -402,7 +384,7 @@ void JGL::J3D::BatchWireframeAABB(const Color4& color, const AABB* boxes, const glPopMatrix(); } glBindBuffer(GL_ARRAY_BUFFER, 0); - glColor4fv(OpenGLState::baseColor); + glColor4fv(current_state.draw_color); } void JGL::J3D::WireframeAABB(const Color4& color, const Vector3& pos, const Vector3& radii, float thickness) { @@ -411,9 +393,6 @@ void JGL::J3D::WireframeAABB(const Color4& color, const Vector3& pos, const Vect } void JGL::J3D::BatchFillAABB(const Color4& color, const AABB* boxes, const size_t& box_count) { - if (!inJ3D) - Logger::Error("Drawing J3D element before J3D begin."); - glColor4ubv(color.ptr()); glBindBuffer(GL_ARRAY_BUFFER, ShapeCache::cube_vertex_data->GetHandle()); @@ -445,7 +424,7 @@ void JGL::J3D::BatchFillAABB(const Color4& color, const AABB* boxes, const size_ glPopMatrix(); } - glColor4fv(OpenGLState::oldColor); + glColor4fv(current_state.draw_color); if (using_lights) glDisableClientState(GL_NORMAL_ARRAY); glDisable(GL_CULL_FACE); @@ -464,9 +443,6 @@ void JGL::J3D::FillSphere(const Color4& color, const Sphere& sphere, unsigned in } void JGL::J3D::BatchFillSphere(const Color4& color, const Sphere* spheres, const size_t& sphere_count, unsigned int sectors, unsigned int stacks) { - if (!inJ3D) - Logger::Error("Drawing J3D element before J3D begin."); - float r = 1; std::vector vertices((sectors + 1) * (stacks + 1)); std::vector indices; indices.reserve(sectors * stacks * 6); @@ -523,7 +499,7 @@ void JGL::J3D::BatchFillSphere(const Color4& color, const Sphere* spheres, const } glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glColor4fv(OpenGLState::oldColor); + glColor4fv(current_state.draw_color); } void JGL::J3D::FillSphere(const Color4& color, const Vector3& position, float radius, unsigned int sectors, unsigned int stacks) { @@ -556,7 +532,7 @@ void JGL::J3D::BatchWireframeOBB(const Color4& color, const OBB* boxes, const si glDrawElements(GL_LINES, indices.size(), GL_UNSIGNED_INT, indices.data()); glPopMatrix(); } - glColor4fv(OpenGLState::oldColor); + glColor4fv(current_state.draw_color); } void JGL::J3D::WireframeOBB(const Color4& color, const OBB& obb, float thickness) { @@ -586,8 +562,6 @@ void JGL::J3D::DrawCubicBezierCurve(const Color4& color, const Vector3& controlA } void JGL::J3D::DrawVertexArray(const Color4& color, const VertexArray& vertex_array, const Vector3& position) { - if (!inJ3D) - Logger::Error("Drawing J3D element before J3D begin."); glColor4ubv(color.ptr()); glEnableClientState(GL_VERTEX_ARRAY); @@ -602,7 +576,7 @@ void JGL::J3D::DrawVertexArray(const Color4& color, const VertexArray& vertex_ar //glDrawElements(GL_LINES, vertex_array.GetIndices()->GetLength(), GL_UNSIGNED_INT, nullptr); //std::cout << vertex_array.GetVertices()->GetLength() << std::endl; - glColor4fv(OpenGLState::oldColor); + glColor4fv(current_state.draw_color); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); diff --git a/src/renderer/OpenGL/TextRendering.cpp b/src/renderer/OpenGL/TextRendering.cpp index 7daf4b9..4db8b27 100644 --- a/src/renderer/OpenGL/TextRendering.cpp +++ b/src/renderer/OpenGL/TextRendering.cpp @@ -158,7 +158,7 @@ namespace JGL { glTexCoordPointer(2, GL_FLOAT, sizeof(Vector2), texcoords.data()); glDrawArrays(GL_TRIANGLES, 0, (int) vertices.size() * 6); glBindTexture(GL_TEXTURE_2D, 0); - glColor4fv(OpenGLState::oldColor); + glColor4fv(default_state.draw_color); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisable(GL_TEXTURE_2D); } @@ -244,7 +244,7 @@ namespace JGL { glDisable(GL_CULL_FACE); glBindTexture(GL_TEXTURE_2D, 0); - glColor4fv(OpenGLState::oldColor); + glColor4fv(current_state.draw_color); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisable(GL_TEXTURE_2D); glPopMatrix(); diff --git a/src/renderer/OpenGL/internals/internals.cpp b/src/renderer/OpenGL/internals/internals.cpp index 513a6c1..a5a44e8 100644 --- a/src/renderer/OpenGL/internals/internals.cpp +++ b/src/renderer/OpenGL/internals/internals.cpp @@ -4,19 +4,19 @@ // TODO handle the case that a required light is in the list of optional lights. void JGL::J3D::SelectLights(const Vector3& position) { - std::array result = required_lights; + std::array result = current_state.required_lights; unsigned int required_light_count = 0; for (const auto& i : result) if (i) required_light_count++; // If there is optional lights. - if (!optional_lights.empty()) { + if (!current_state.optional_lights.empty()) { // The number of lights we need to solve for unsigned int remaining_lights = 8 - required_light_count; std::vector> light_influence; - for (const auto* light: optional_lights) + for (const auto* light: current_state.optional_lights) light_influence.emplace_back(light->GetAttenuationAtPosition(position), light); // Sort by biggest influence. @@ -82,11 +82,11 @@ void JGL::J3D::ResetLights() { } bool JGL::J3D::UsingLighting() { - if (!optional_lights.empty()) + if (!current_state.optional_lights.empty()) return true; - for (unsigned int i = 0; i < required_lights.size(); i++) - if (required_lights[i]) + for (unsigned int i = 0; i < current_state.required_lights.size(); i++) + if (current_state.required_lights[i]) return true; return false; } @@ -117,3 +117,94 @@ std::vector JGL::TriangleMeshVertexNormals(const Vector3* vertices, con return normals; } + +void JGL::StateStack::Push(const JGL::State& state) { + states.push_back(state); +} + +void JGL::StateStack::Pop() { + states.pop_back(); +} + +JGL::State* JGL::StateStack::PreviousState() { + if (states.empty()) + return nullptr; + + return &states.back(); +} + +JGL::State JGL::State::SaveState() { + State result; + + result.depth_test = glIsEnabled(GL_DEPTH_TEST); + result.vertex_array = glIsEnabled(GL_VERTEX_ARRAY); + result.normal_array = glIsEnabled(GL_NORMAL_ARRAY); + result.cull_face = glIsEnabled(GL_CULL_FACE); + result.blend = glIsEnabled(GL_BLEND); + result.texture_2D = glIsEnabled(GL_TEXTURE_2D); + result.texture_coordinate_array = glIsEnabled(GL_TEXTURE_COORD_ARRAY); + result.color_array = glIsEnabled(GL_COLOR_ARRAY); + + glGetIntegerv(GL_ACTIVE_TEXTURE, &result.selected_texture_unit); + result.selected_texture_unit -= GL_TEXTURE0; + + glGetFloatv(GL_COLOR_CLEAR_VALUE, result.clear_color); + glGetFloatv(GL_CURRENT_COLOR, result.draw_color); + glGetIntegerv(GL_VIEWPORT, result.viewport); + glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*)&result.current_fbo); + glGetIntegerv(GL_BLEND_SRC, &result.blend_func[0]); + glGetIntegerv(GL_BLEND_DST, &result.blend_func[1]); + + return result; +} + +void JGL::State::RestoreState(const State& state) { + if (state.depth_test) + glEnable(GL_DEPTH_TEST); + else + glDisable(GL_DEPTH_TEST); + + if (state.vertex_array) + glEnableClientState(GL_VERTEX_ARRAY); + else + glDisableClientState(GL_VERTEX_ARRAY); + + if (state.normal_array) + glEnableClientState(GL_NORMAL_ARRAY); + else + glDisableClientState(GL_NORMAL_ARRAY); + + if (state.cull_face) + glEnable(GL_CULL_FACE); + else + glDisable(GL_CULL_FACE); + + if (state.blend) + glEnable(GL_BLEND); + else + glDisable(GL_BLEND); + + glActiveTexture(GL_TEXTURE0 + state.selected_texture_unit); + glClientActiveTexture(GL_TEXTURE0 + state.selected_texture_unit); + + if (state.texture_2D) + glEnable(GL_TEXTURE_2D); + else + glDisable(GL_TEXTURE_2D); + + if (state.texture_coordinate_array) + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + else + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + + if (state.color_array) + glEnable(GL_COLOR_ARRAY); + else + glDisable(GL_COLOR_ARRAY); + + glBindFramebuffer(GL_FRAMEBUFFER, state.current_fbo); + glViewport(state.viewport[0], state.viewport[1], state.viewport[2], state.viewport[3]); + glClearColor(state.clear_color[0], state.clear_color[1], state.clear_color[2], state.clear_color[3]); + glColor4f(state.draw_color[0], state.draw_color[1], state.draw_color[2], state.draw_color[3]); + glBlendFunc(state.blend_func[0], state.blend_func[1]); +} diff --git a/src/renderer/OpenGL/internals/internals.h b/src/renderer/OpenGL/internals/internals.h index 68fbb7f..45a554b 100644 --- a/src/renderer/OpenGL/internals/internals.h +++ b/src/renderer/OpenGL/internals/internals.h @@ -9,44 +9,73 @@ #include namespace JGL { - inline constexpr std::array empty_light_array = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }; - inline bool inJ2D = false; - inline bool inJ3D = false; - std::vector TriangleMeshVertexNormals(const Vector3* vertices, const size_t& vertex_count, const unsigned int* indices, const size_t& index_count); + class State; + class StateStack; } -namespace JGL::OpenGLState { - inline JGL::RenderTarget* render_target = nullptr; - inline Vector2 window_size; +class JGL::State { +public: + GLfloat clear_color[4] = {0, 0, 0, 1}; + GLfloat draw_color[4] = {1, 1, 1, 1}; + GLint viewport[4] = {0, 0, 0, 0}; + GLint blend_func[2]; + GLuint current_fbo = 0; - inline GLfloat oldColor[4] = {0, 0, 0, 1}; - inline GLfloat baseColor[4] = {1, 1, 1, 1}; + bool texture_2D = false; + bool texture_coordinate_array = false; + bool normal_array = false; + bool depth_test = false; + bool vertex_array = false; + bool cull_face = false; + bool blend = false; + bool color_array = false; + GLint selected_texture_unit = 0; + // List of lights required for each object in the scene. up-to 8. For example, the sun. Or a flash-light. + std::array required_lights{}; + // List of all lights in the scene. + std::vector optional_lights{}; +public: + static State SaveState(); + static void RestoreState(const State& state); +}; - inline GLuint current_fbo = 0; - inline GLint viewport[4] = {0, 0, 0, 0}; +class JGL::StateStack { +private: + std::vector states{}; +public: + size_t Size() { return states.size(); } + void Push(const State& state); + void Pop(); + State* PreviousState(); +public: + StateStack() = default; + ~StateStack() = default; +}; - inline bool wasTexture2DEnabled = false; - inline bool wasTextureCoordArrayEnabled = false; - inline bool wasNormalArrayEnabled = false; - - inline bool wasDepthTestEnabled = false; - inline bool wasVertexArraysEnabled = false; - inline bool wasCullFaceEnabled = false; - inline bool wasBlendEnabled = false; - inline bool wasColorArrayEnabled = false; - inline GLint activeTextureUnit = 0; +namespace JGL { + inline constexpr std::array empty_light_array = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }; + std::vector TriangleMeshVertexNormals(const Vector3* vertices, const size_t& vertex_count, const unsigned int* indices, const size_t& index_count); + inline StateStack state_stack; + inline Vector2i window_size; + //inline State current_state; } namespace JGL::J2D { - inline std::array required_lights; - inline std::vector light_array; + inline State default_state + { + {0, 0, 0, 1}, + {1, 1, 1, 1}, + {0, 0, 0, 0}, + {GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA}, + 0, false, false, + false, false, true, true, + true, false, 0, + {}, {} + }; } namespace JGL::J3D { - // List of lights required for each objects in the scene. up-to 8. For example, the sun. Or a flash-light. - inline std::array required_lights; - // List of all lights in the scene. - inline std::vector optional_lights; + inline State current_state; inline float far_plane = 0; inline float fov = 0; // Enables lighting and selects the correct lights to use.