Compare commits
9 Commits
Prerelease
...
Prerelease
Author | SHA1 | Date | |
---|---|---|---|
7498390180 | |||
4ac28a2c10 | |||
61c1c3245c | |||
cb9fe4e5c9 | |||
c7e7aa6fb5 | |||
1261321992 | |||
6d1ddad428 | |||
eae3c794fa | |||
db7a37d647 |
11
README.md
11
README.md
@@ -19,12 +19,17 @@ Yet Another C++ Rendering Toolkit
|
||||
|
||||
### J2D
|
||||
* DrawPoint
|
||||
* DrawLine / DrawGradientLine
|
||||
* DrawLine / DrawGradientLine / DrawDottedLine / DrawDashedLine / DrawLines
|
||||
* DrawSprite / DrawPartialSprite
|
||||
* OutlineRect / FillRect / FillGradientRect / FillRoundedRect
|
||||
* DrawRenderTarget / DrawPartialRenderTarget
|
||||
* OutlineRect / OutlineRoundedRect / OutlineChamferRect
|
||||
* FillRect / FillGradientRect / FillRoundedRect / FillChamferRect
|
||||
* OutlineCircle / FillCircle
|
||||
* OutlineTriangle / FillTriangle
|
||||
* OutlineTriangle / FillTriangle / FillGradientTriangle
|
||||
* DrawString
|
||||
* DrawCubicBezierCurve
|
||||
* DrawArc
|
||||
* OutlineEllipse / FillEllipse
|
||||
|
||||
### J3D
|
||||
* DrawLine
|
||||
|
@@ -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(); }
|
||||
|
||||
|
||||
@@ -381,6 +381,10 @@ namespace JGL::J2D {
|
||||
void FillPolygon(const Color4& color, const std::vector<Vector2>& points);
|
||||
void OutlineEllipse(const Color4& color, const Vector2& position, float radius_x, float radius_y, float thickness = 1, int subdivisions = 8);
|
||||
void FillEllipse(const Color4& color, const Vector2& position, float radius_x, float radius_y, int subdivisions = 8);
|
||||
|
||||
void BatchFillRect(const Color4* colors, const Vector2* positions, const Vector2* sizes, const size_t& rect_count);
|
||||
|
||||
void BatchFillCircle(const Color4 *colors, const Vector2* positions, float* radii, unsigned int subdivisions, const size_t& circle_count);
|
||||
}
|
||||
|
||||
/// Drawing functions for 3D objects.
|
||||
|
@@ -41,6 +41,24 @@ namespace JGL {
|
||||
MSAA_8X = 3
|
||||
};
|
||||
|
||||
enum class FilteringMode : u8 {
|
||||
NEAREST = 0, // Fastest for 2D, Sometimes causes graphical issues.
|
||||
BILINEAR = 1, // Fast and pretty, The best for 2D.
|
||||
|
||||
MIPMAP_NEAREST = 2, // Nearest with mipmaps. The fastest for 3D, Sometimes causes graphical issues. Uses more vram.
|
||||
MIPMAP_BILINEAR = 3, // Bilinear with mipmaps, Fast and pretty. Uses more vram.
|
||||
MIPMAP_TRILINEAR = 4 // The prettiest. Still decent speed. Uses more vram.
|
||||
};
|
||||
|
||||
enum class WrappingMode : u8 {
|
||||
REPEAT = 0,
|
||||
MIRRORED_REPEAT = 1,
|
||||
CLAMP_TO_EDGE = 2,
|
||||
CLAMP_TO_BORDER = 3 // Effectively the same as clamp_to_edge
|
||||
};
|
||||
|
||||
enum class ColorFormat : bool { RGB = false, RGBA = true };
|
||||
|
||||
static std::string to_string(const JGL::MSAA_SAMPLE_RATE& sample_rate) {
|
||||
switch (sample_rate) {
|
||||
case MSAA_SAMPLE_RATE::MSAA_NONE:
|
||||
|
@@ -47,6 +47,7 @@ public:
|
||||
/// If you're using MSAA and not using J2D || J3D Begin & End you must do this.
|
||||
void MSAABlit() const;
|
||||
|
||||
void RegenerateMipMaps();
|
||||
/// Copy one Render Target onto another. Will break if they're not the same size.
|
||||
// TODO support different sizes. If the destination is too small fix it for them but log a warning.
|
||||
static void Blit(const RenderTarget& source, RenderTarget* destination, const Vector2i& position = {0, 0});
|
||||
@@ -91,10 +92,11 @@ public:
|
||||
/// @returns The color that should be used to clear this Render Target.
|
||||
[[nodiscard]] Color4 GetClearColor() const;
|
||||
|
||||
|
||||
/// @returns The color information for this Render Target.
|
||||
/// @note Both the CPU & GPU cannot do anything while this takes place. It's very slow.
|
||||
/// @note The CPU thread this is called from & the GPU cannot do anything while this takes place. It's very slow.
|
||||
[[nodiscard]] std::vector<GLfloat> GetPixels() const;
|
||||
|
||||
[[nodiscard]] static Vector2i MaximumSize();
|
||||
public:
|
||||
/// Create a Render Target from a Render Target that already exists.
|
||||
/** @note Render Targets that are copies of another will copy the Texture.
|
||||
@@ -113,7 +115,8 @@ public:
|
||||
/// @param clear_color The color to be used if you want to clear the Render Target.
|
||||
/// @param use_depth Whether or not this Render Target will have depth information.
|
||||
/// @param sample_rate The MSAA sample rate this Render Target will use.
|
||||
explicit RenderTarget(const Vector2i& size, const Color4& clear_color = Colors::Transparent, bool use_depth = false, MSAA_SAMPLE_RATE sample_rate = MSAA_SAMPLE_RATE::MSAA_NONE);
|
||||
explicit RenderTarget(const Vector2i& size, const Color4& clear_color = Colors::Transparent, bool use_depth = false,
|
||||
MSAA_SAMPLE_RATE sample_rate = MSAA_SAMPLE_RATE::MSAA_NONE, FilteringMode filteirng_mode = FilteringMode::NEAREST);
|
||||
|
||||
/// Deletes this Render Target.
|
||||
/** @note If this Render Target was made with a Texture that already existed
|
||||
|
@@ -4,30 +4,13 @@
|
||||
#include <J3ML/LinearAlgebra/Vector2i.hpp>
|
||||
#include <Color3.hpp>
|
||||
#include <Color4.hpp>
|
||||
#include <JGL/types/Enums.h>
|
||||
|
||||
namespace JGL {
|
||||
using J3ML::LinearAlgebra::Vector2i;
|
||||
|
||||
enum class FilteringMode : u8 {
|
||||
NEAREST = 0, // Fastest for 2D, Sometimes causes graphical issues.
|
||||
BILINEAR = 1, // Fast and pretty, The best for 2D.
|
||||
|
||||
MIPMAP_NEAREST = 2, // Nearest with mipmaps. The fastest for 3D, Sometimes causes graphical issues. Uses more vram.
|
||||
MIPMAP_BILINEAR = 3, // Bilinear with mipmaps, Fast and pretty. Uses more vram.
|
||||
MIPMAP_TRILINEAR = 4 // The prettiest. Still decent speed. Uses more vram.
|
||||
};
|
||||
|
||||
enum class WrappingMode : u8 {
|
||||
REPEAT = 0,
|
||||
MIRRORED_REPEAT = 1,
|
||||
CLAMP_TO_EDGE = 2,
|
||||
CLAMP_TO_BORDER = 3 // Effectively the same as clamp_to_edge
|
||||
};
|
||||
enum class ColorFormat : bool { RGB = false, RGBA = true };
|
||||
class Texture;
|
||||
}
|
||||
|
||||
/// TODO handle the case of a texture being loaded that exceeds the max texture size.
|
||||
/// Represents texture data loaded on the GPU. Contains a handle that can be passed to OpenGL draw calls.
|
||||
class JGL::Texture {
|
||||
protected:
|
||||
@@ -40,6 +23,7 @@ protected:
|
||||
void load(const unsigned char* pixels);
|
||||
std::vector<unsigned char> png(const std::filesystem::path& file);
|
||||
std::vector<unsigned char> bmp(const std::filesystem::path& file);
|
||||
[[nodiscard]] bool SizeExceedsMaximum(const Vector2i& size);
|
||||
public:
|
||||
/// @returns A handle used to identify this texture.
|
||||
[[nodiscard]] unsigned int GetHandle() const;
|
||||
@@ -56,6 +40,9 @@ public:
|
||||
/// @returns The raw pixels this texture is made up of.
|
||||
/// @note This will read-back from the GPU. Slow.
|
||||
[[nodiscard]] std::vector<Color4> GetPixelData() const;
|
||||
/// @returns The biggest size for a texture on this system.
|
||||
/// @note on modern systems this is *usually* ridiculous.
|
||||
[[nodiscard]] static Vector2i MaximumSize();
|
||||
public:
|
||||
/// Load a texture from a file,
|
||||
explicit Texture(const std::filesystem::path& file, FilteringMode filtering_mode = FilteringMode::BILINEAR, WrappingMode wrapping_mode = WrappingMode::CLAMP_TO_EDGE, bool invert_y = true);
|
||||
@@ -68,7 +55,7 @@ public:
|
||||
Texture(const Texture* textures, const size_t& texture_count);
|
||||
/// Initialize a texture filled with trash data.
|
||||
/// @see RenderTarget
|
||||
explicit Texture(const Vector2i& size);
|
||||
explicit Texture(const Vector2i& size, FilteringMode filtering_mode = FilteringMode::NEAREST);
|
||||
|
||||
Texture(const Texture& rhs);
|
||||
~Texture();
|
||||
|
16
main.cpp
16
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.
|
||||
@@ -130,7 +130,8 @@ public:
|
||||
glDepthMask(GL_TRUE);
|
||||
image = new Texture("assets/sprites/Re3D.png", FilteringMode::BILINEAR);
|
||||
image_mask = new Texture("assets/sprites/alpha_mask_2.png");
|
||||
j2d_render_target = new RenderTarget({540, 500}, {0,0,0,0}, false, MSAA_SAMPLE_RATE::MSAA_NONE);
|
||||
j2d_render_target = new RenderTarget({540, 500}, {0,0,0,0}, false,
|
||||
MSAA_SAMPLE_RATE::MSAA_8X, FilteringMode::MIPMAP_TRILINEAR);
|
||||
|
||||
//Texture::MultiplyByAlphaMask(*image, *image_mask);
|
||||
}
|
||||
@@ -146,7 +147,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 +185,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 +207,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<Vector2, 5> 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 +225,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();
|
||||
|
||||
}
|
||||
|
13
src/JGL.cpp
13
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() {
|
||||
|
@@ -3,182 +3,99 @@
|
||||
#include <J3ML/Algorithm/Bezier.hpp>
|
||||
#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())
|
||||
void J2D::Begin(RenderTarget* render_target, bool clear_buffers) {
|
||||
State new_state = default_state;
|
||||
state_stack.Push(State::SaveState());
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
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.");
|
||||
|
||||
new_state.current_fbo = render_target->GetGLFramebufferObjectHandle();
|
||||
new_state.viewport[2] = render_target->GetDimensions().x;
|
||||
new_state.viewport[3] = render_target->GetDimensions().y;
|
||||
|
||||
new_state.clear_color[0] = render_target->GetClearColor().RN();
|
||||
new_state.clear_color[1] = render_target->GetClearColor().GN();
|
||||
new_state.clear_color[2] = render_target->GetClearColor().BN();
|
||||
new_state.clear_color[3] = render_target->GetClearColor().AN();
|
||||
new_state.current_render_target = render_target;
|
||||
}
|
||||
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);
|
||||
|
||||
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);
|
||||
else {
|
||||
new_state.viewport[2] = window_size.x;
|
||||
new_state.viewport[3] = window_size.y;
|
||||
}
|
||||
|
||||
if (glIsEnabled(GL_DEPTH_TEST))
|
||||
OpenGLState::wasDepthTestEnabled = true,
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
else
|
||||
OpenGLState::wasDepthTestEnabled = false;
|
||||
State::RestoreState(new_state);
|
||||
current_state = new_state;
|
||||
|
||||
if (!glIsEnabled(GL_VERTEX_ARRAY))
|
||||
OpenGLState::wasVertexArraysEnabled = false,
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
else
|
||||
OpenGLState::wasVertexArraysEnabled = true;
|
||||
if (current_state.current_render_target)
|
||||
JGL::RenderTarget::SetActiveGLRenderTarget(*current_state.current_render_target);
|
||||
|
||||
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());
|
||||
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);
|
||||
glClearColor(old_clear_color[0], old_clear_color[1], old_clear_color[2], old_clear_color[3]);
|
||||
}
|
||||
|
||||
glOrtho(0, new_state.viewport[2], new_state.viewport[3], 0, -1, 1);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
}
|
||||
|
||||
void JGL::J2D::End() {
|
||||
//Change back to the previous projection (The 3D one in Re3D's case.)
|
||||
void J2D::End() {
|
||||
if (current_state.current_render_target) {
|
||||
current_state.current_render_target->MSAABlit();
|
||||
FilteringMode filtering_mode = current_state.current_render_target->GetTexture()->GetFilteringMode();
|
||||
|
||||
if (filtering_mode == FilteringMode::MIPMAP_NEAREST ||
|
||||
filtering_mode == FilteringMode::MIPMAP_BILINEAR ||
|
||||
filtering_mode == FilteringMode::MIPMAP_TRILINEAR)
|
||||
current_state.current_render_target->RegenerateMipMaps();
|
||||
}
|
||||
|
||||
//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);
|
||||
State::RestoreState(*previous_state);
|
||||
if (previous_state->current_render_target)
|
||||
JGL::RenderTarget::SetActiveGLRenderTarget(*current_state.current_render_target);
|
||||
|
||||
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;
|
||||
current_state = *previous_state;
|
||||
state_stack.Pop();
|
||||
}
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
void JGL::J2D::DrawPoint(const Color4& color, const Vector2& coordinates, float radius) {
|
||||
if (!inJ2D)
|
||||
void J2D::DrawPoint(const Color4& color, const Vector2& coordinates, float radius) {
|
||||
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) {
|
||||
void J2D::DrawPoint(const Color4& color, float x, float y, float radius) {
|
||||
DrawPoint(color, {x, y}, radius);
|
||||
}
|
||||
|
||||
void JGL::J2D::DrawLine(const Color4& color, const Vector2& A, const Vector2& B, float thickness) {
|
||||
if (!inJ2D)
|
||||
void J2D::DrawLine(const Color4& color, const Vector2& A, const Vector2& B, float thickness) {
|
||||
if (!state_stack.Size())
|
||||
Logger::Error("Drawing J2D element before J2D begin.");
|
||||
Vector2 vertices[] = {A, B};
|
||||
|
||||
@@ -186,25 +103,25 @@ 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) {
|
||||
JGL::J2D::DrawLine(color, {x, y}, {w, h}, thickness);
|
||||
void J2D::DrawLine(const Color4& color, float x, float y, float w, float h, float thickness) {
|
||||
J2D::DrawLine(color, {x, y}, {w, h}, thickness);
|
||||
}
|
||||
|
||||
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) {
|
||||
void J2D::DrawDottedLine(const Color4& color, const Vector2& A, const Vector2& B, float spacing, float thickness) {
|
||||
float distance = Vector2::Distance(A, B);
|
||||
Vector2 direction = (B - A).Normalized();
|
||||
|
||||
@@ -217,14 +134,14 @@ void JGL::J2D::DrawDottedLine(const Color4& color, const Vector2& A, const Vecto
|
||||
for (unsigned int i = 0; i < point_count; ++i)
|
||||
points[i] = A + direction * (i * spacing);
|
||||
|
||||
return JGL::J2D::DrawPoints(color, points.data(), points.size(), thickness);
|
||||
return J2D::DrawPoints(color, points.data(), points.size(), thickness);
|
||||
}
|
||||
|
||||
void JGL::J2D::DrawDottedLine(const Color4& color, float x1, float y1, float x2, float y2, float spacing, float thickness) {
|
||||
return JGL::J2D::DrawDottedLine(color, {x1, y1}, {x2, y2}, spacing, thickness);
|
||||
void J2D::DrawDottedLine(const Color4& color, float x1, float y1, float x2, float y2, float spacing, float thickness) {
|
||||
return J2D::DrawDottedLine(color, {x1, y1}, {x2, y2}, spacing, thickness);
|
||||
}
|
||||
|
||||
void JGL::J2D::DrawDashedLine(const Color4& color, const Vector2& A, const Vector2& B, float spacing, float dash_length, float thickness) {
|
||||
void J2D::DrawDashedLine(const Color4& color, const Vector2& A, const Vector2& B, float spacing, float dash_length, float thickness) {
|
||||
float distance = Vector2::Distance(A, B);
|
||||
Vector2 direction = (B - A).Normalized();
|
||||
float length_of_dash_and_gap = dash_length + spacing;
|
||||
@@ -237,7 +154,7 @@ void JGL::J2D::DrawDashedLine(const Color4& color, const Vector2& A, const Vecto
|
||||
for (unsigned int i = 0; i < dash_count; i++) {
|
||||
A_current = A + direction * (i * length_of_dash_and_gap);
|
||||
B_current = A_current + (direction * dash_length);
|
||||
JGL::J2D::DrawLine(color, A_current, B_current, thickness);
|
||||
J2D::DrawLine(color, A_current, B_current, thickness);
|
||||
}
|
||||
|
||||
// For the little piece at the end.
|
||||
@@ -245,16 +162,16 @@ void JGL::J2D::DrawDashedLine(const Color4& color, const Vector2& A, const Vecto
|
||||
if (distance_left > 0) {
|
||||
A_current = A + direction * (dash_count * length_of_dash_and_gap);
|
||||
B_current = A_current + direction * std::min(dash_length, distance_left);
|
||||
JGL::J2D::DrawLine(color, A_current, B_current, thickness);
|
||||
J2D::DrawLine(color, A_current, B_current, thickness);
|
||||
}
|
||||
}
|
||||
|
||||
void JGL::J2D::DrawDashedLine(const Color4& color, float x1, float y1, float x2, float y2, float spacing, float dash_length, float thickness) {
|
||||
return JGL::J2D::DrawDashedLine(color, {x1, y1}, {x2, y2}, spacing, dash_length, thickness);
|
||||
void J2D::DrawDashedLine(const Color4& color, float x1, float y1, float x2, float y2, float spacing, float dash_length, float thickness) {
|
||||
return J2D::DrawDashedLine(color, {x1, y1}, {x2, y2}, spacing, dash_length, thickness);
|
||||
}
|
||||
|
||||
void JGL::J2D::DrawGradientLine(const Color4& color1, const Color4& color2, const Vector2& A, const Vector2& B, float thickness) {
|
||||
if (!inJ2D)
|
||||
void J2D::DrawGradientLine(const Color4& color1, const Color4& color2, const Vector2& A, const Vector2& B, float thickness) {
|
||||
if (!state_stack.Size())
|
||||
Logger::Error("Drawing J2D element before J2D begin.");
|
||||
|
||||
Vector2 vertices[] = {A, B};
|
||||
@@ -267,15 +184,15 @@ 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) {
|
||||
JGL::J2D::DrawGradientLine(color1, color2, {x, y}, {w, h}, thickness);
|
||||
J2D::DrawGradientLine(color1, color2, {x, y}, {w, h}, thickness);
|
||||
}
|
||||
|
||||
void JGL::J2D::OutlineRect(const Color4& color, const Vector2& pos, const Vector2& size, float thickness) {
|
||||
if (!inJ2D)
|
||||
void J2D::OutlineRect(const Color4& color, const Vector2& pos, const Vector2& size, float thickness) {
|
||||
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,28 +201,37 @@ 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)
|
||||
void J2D::FillRect(const Color4& color, const Vector2& pos, const Vector2& size) {
|
||||
BatchFillRect(&color, &pos, &size, 1);
|
||||
}
|
||||
|
||||
void J2D::BatchFillRect(const Color4* colors, const Vector2* positions, const Vector2* sizes, const size_t& rect_count) {
|
||||
if (!state_stack.Size())
|
||||
Logger::Error("Drawing J2D element before J2D begin.");
|
||||
|
||||
glColor4ubv(color.ptr());
|
||||
if (rect_count <= 0)
|
||||
return;
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, ShapeCache::square_origin_topleft_vertex_data->GetHandle());
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), nullptr);
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(pos.x, pos.y + size.y, 0);
|
||||
glScalef(size.x, size.y, 1);
|
||||
glDrawArrays(GL_QUADS, 0, 4);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glPopMatrix();
|
||||
glColor4fv(OpenGLState::baseColor);
|
||||
for (size_t i = 0; i < rect_count; i++) {
|
||||
glPushMatrix();
|
||||
glColor4ubv(colors[i].ptr());
|
||||
glTranslatef(positions[i].x, positions[i].y + sizes[i].y, 0);
|
||||
glScalef(sizes[i].x, sizes[i].y, 1);
|
||||
glDrawArrays(GL_QUADS, 0, 4);
|
||||
glPopMatrix();
|
||||
}
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
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)
|
||||
void J2D::FillGradientRect(const Color4& color1, const Color4& color2, const Direction& gradient, const Vector2& pos, const Vector2& size) {
|
||||
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,41 +260,43 @@ 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)
|
||||
Logger::Error("Drawing J2D element before J2D begin.");
|
||||
void J2D::FillRoundedRect(const Color4& color, const Vector2& pos, const Vector2& size, float radius, unsigned int subdivisions) {
|
||||
std::array<Color4, 4> colors = { color, color, color, color };
|
||||
std::array<Vector2, 2> rect_positions = { Vector2(pos.x + radius, pos.y), {pos.x, pos.y + radius} };
|
||||
std::array<Vector2, 2> rect_sizes = { Vector2(size.x - 2 * radius, size.y), {size.x, size.y - 2 * radius} };
|
||||
std::array<float, 4> circle_radii = { radius, radius, radius, radius };
|
||||
std::array<Vector2, 4> circle_positions
|
||||
{
|
||||
Vector2(pos.x + radius, pos.y + radius), {pos.x + size.x - radius, pos.y + radius},
|
||||
{pos.x + radius, pos.y + size.y - radius}, {pos.x + size.x - radius, pos.y + size.y - radius}
|
||||
};
|
||||
|
||||
JGL::J2D::FillRect(color, {pos.x + radius, pos.y}, {size.x - 2 * radius, size.y});
|
||||
JGL::J2D::FillRect(color, {pos.x, pos.y + radius}, {size.x, size.y - 2 * radius});
|
||||
|
||||
JGL::J2D::FillCircle(color, {pos.x + radius, pos.y + radius}, radius, subdivisions);
|
||||
JGL::J2D::FillCircle(color, {pos.x + size.x - radius, pos.y + radius}, radius, subdivisions);
|
||||
JGL::J2D::FillCircle(color, {pos.x + radius, pos.y + size.y - radius}, radius, subdivisions);
|
||||
JGL::J2D::FillCircle(color, {pos.x + size.x - radius, pos.y + size.y - radius}, radius, subdivisions);
|
||||
J2D::BatchFillRect(colors.data(), rect_positions.data(), rect_sizes.data(), 2);
|
||||
J2D::BatchFillCircle(colors.data(), circle_positions.data(), circle_radii.data(), subdivisions, 4);
|
||||
}
|
||||
|
||||
void JGL::J2D::DrawSprite(const Texture* texture, float positionX, float positionY, float rad_rotation,
|
||||
void J2D::DrawSprite(const Texture* texture, float positionX, float positionY, float rad_rotation,
|
||||
float originX, float originY,float scaleX, float scaleY,
|
||||
const Color4& color, Direction inversion) {
|
||||
DrawSprite(*texture, {positionX, positionY}, rad_rotation, {originX, originY}, {scaleX, scaleY}, color, inversion);
|
||||
}
|
||||
void JGL::J2D::DrawSprite(const Texture* texture, const Vector2& position, float rad_rotation, const Vector2& origin,
|
||||
void J2D::DrawSprite(const Texture* texture, const Vector2& position, float rad_rotation, const Vector2& origin,
|
||||
const Vector2& scale, const Color4& color, Direction inversion) {
|
||||
|
||||
DrawSprite(*texture, position, rad_rotation, origin, scale, color, inversion);
|
||||
}
|
||||
|
||||
void JGL::J2D::DrawPartialSprite(const Texture* texture, const Vector2& position, const Vector2& sub_texture_position,
|
||||
void 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) {
|
||||
DrawPartialSprite(*texture, position, sub_texture_position, sub_texture_size, rad_rotation, origin, scale, color, inversion);
|
||||
|
||||
}
|
||||
|
||||
void JGL::J2D::DrawPartialSprite(const Texture* texture, float positionX, float positionY, float sub_texture_positionX,
|
||||
void J2D::DrawPartialSprite(const Texture* texture, float positionX, float positionY, float sub_texture_positionX,
|
||||
float sub_texture_positionY, unsigned int sub_texture_sizeX,
|
||||
unsigned int sub_texture_sizeY, float rad_rotation, float originX, float originY,
|
||||
float scaleX, float scaleY, const Color4& color, Direction inversion) {
|
||||
@@ -376,27 +304,27 @@ void JGL::J2D::DrawPartialSprite(const Texture* texture, float positionX, float
|
||||
rad_rotation, {originX, originY}, {scaleX, scaleY}, color, inversion);
|
||||
}
|
||||
|
||||
void JGL::J2D::DrawMirrorSprite(const Texture* texture, const Vector2& position, Direction mirror_axis, float rad_rotation,
|
||||
void J2D::DrawMirrorSprite(const Texture* texture, const Vector2& position, Direction mirror_axis, float rad_rotation,
|
||||
const Vector2& origin, const Vector2& scale, const Color4& color) {
|
||||
DrawMirrorSprite(*texture, position, mirror_axis, rad_rotation, origin, scale, color);
|
||||
}
|
||||
|
||||
void JGL::J2D::DrawSprite(const RenderTarget* render_target, const Vector2& position, float rad_rotation,
|
||||
void J2D::DrawSprite(const RenderTarget* render_target, const Vector2& position, float rad_rotation,
|
||||
const Vector2& origin, const Vector2& scale, const Color4& color, Direction inversion) {
|
||||
DrawSprite(*render_target, position, rad_rotation, origin, scale, color, inversion);
|
||||
}
|
||||
|
||||
void JGL::J2D::DrawRenderTarget(const RenderTarget* render_target, const Vector2& position, float rad_rotation,
|
||||
void J2D::DrawRenderTarget(const RenderTarget* render_target, const Vector2& position, float rad_rotation,
|
||||
const Vector2& origin, const Vector2& scale, const Color4& color, Direction inversion) {
|
||||
DrawSprite(*render_target, position, rad_rotation, origin, scale, color, inversion);
|
||||
}
|
||||
|
||||
void JGL::J2D::DrawRenderTarget(const RenderTarget& render_target, const Vector2& position, float rad_rotation,
|
||||
void J2D::DrawRenderTarget(const RenderTarget& render_target, const Vector2& position, float rad_rotation,
|
||||
const Vector2& origin, const Vector2& scale, const Color4& color, Direction inversion) {
|
||||
DrawSprite(render_target, position, rad_rotation, origin, scale, color, inversion);
|
||||
}
|
||||
|
||||
void JGL::J2D::DrawSprite(const JGL::RenderTarget& rt, const Vector2& position, float rad_rotation, const Vector2& origin,
|
||||
void J2D::DrawSprite(const RenderTarget& rt, const Vector2& position, float rad_rotation, const Vector2& origin,
|
||||
const Vector2& scale, const Color4& color, Direction inversion) {
|
||||
|
||||
//Correct for the render-target being upside-down.
|
||||
@@ -419,15 +347,15 @@ void JGL::J2D::DrawSprite(const JGL::RenderTarget& rt, const Vector2& position,
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
auto r_position = Vector2(Math::Floor(position.x), Math::Floor(position.y));
|
||||
JGL::J2D::DrawPartialSprite(*rt.GetTexture(), r_position, {0, 0}, Vector2(rt.GetDimensions()), rad_rotation, origin, scale, color, d);
|
||||
J2D::DrawPartialSprite(*rt.GetTexture(), r_position, {0, 0}, Vector2(rt.GetDimensions()), rad_rotation, origin, scale, color, d);
|
||||
|
||||
if (rt.OwnsTexture())
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
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)
|
||||
void J2D::DrawSprite(const Texture& texture, const Texture& alpha_mask, const Vector2& position, float rad_rotation,
|
||||
const Vector2& origin, const Vector2& scale,const Color4& color, Direction inversion) {
|
||||
if (!state_stack.Size())
|
||||
Logger::Error("Drawing J2D element before J2D begin.");
|
||||
|
||||
if (texture.GetDimensions() != alpha_mask.GetDimensions())
|
||||
@@ -510,26 +438,26 @@ 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,
|
||||
void J2D::DrawSprite(const Texture* texture, const Texture* alpha_mask, const Vector2& position, float rad_rotation,
|
||||
const Vector2& origin, const Vector2& scale,const Color4& color, Direction inversion) {
|
||||
DrawSprite(*texture, *alpha_mask, position, rad_rotation, origin, scale, color, inversion);
|
||||
}
|
||||
|
||||
void JGL::J2D::DrawSprite(const Texture& texture, const Texture& alpha_mask, float positionX, float positionY, float rad_rotation,
|
||||
void J2D::DrawSprite(const Texture& texture, const Texture& alpha_mask, float positionX, float positionY, float rad_rotation,
|
||||
float originX, float originY,float scaleX, float scaleY,const Color4& color, Direction inversion) {
|
||||
DrawSprite(texture, alpha_mask, {positionX, positionY}, rad_rotation, {originX, originY}, {scaleX, scaleY}, color, inversion);
|
||||
}
|
||||
|
||||
void JGL::J2D::DrawSprite(const Texture* texture, const Texture* alpha_mask, float positionX, float positionY, float rad_rotation,
|
||||
void J2D::DrawSprite(const Texture* texture, const Texture* alpha_mask, float positionX, float positionY, float rad_rotation,
|
||||
float originX, float originY,float scaleX, float scaleY,const Color4& color, Direction inversion) {
|
||||
DrawSprite(*texture, *alpha_mask, {positionX, positionY}, rad_rotation, {originX, originY}, {scaleX, scaleY}, color, inversion);
|
||||
}
|
||||
|
||||
void JGL::J2D::DrawPartialRenderTarget(const JGL::RenderTarget& rt, 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, JGL::Direction inversion) {
|
||||
void J2D::DrawPartialRenderTarget(const RenderTarget& rt, 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) {
|
||||
|
||||
//Correct for the render-target being upside-down.
|
||||
Direction d{};
|
||||
@@ -554,20 +482,20 @@ void JGL::J2D::DrawPartialRenderTarget(const JGL::RenderTarget& rt, const Vector
|
||||
auto r_position = Vector2(Math::Floor(position.x), Math::Floor(position.y));
|
||||
auto r_sub_texture_position = Vector2(Math::Floor(sub_texture_position.x), Math::Floor(sub_texture_position.y));
|
||||
|
||||
JGL::J2D::DrawPartialSprite(*rt.GetTexture(), r_position, r_sub_texture_position, sub_texture_size, rad_rotation, origin, scale, color, d);
|
||||
J2D::DrawPartialSprite(*rt.GetTexture(), r_position, r_sub_texture_position, sub_texture_size, rad_rotation, origin, scale, color, d);
|
||||
|
||||
if (rt.OwnsTexture())
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
void JGL::J2D::DrawPartialRenderTarget(const JGL::RenderTarget* rt, const Vector2& position,const Vector2& sub_texture_position,const Vector2& sub_texture_size, float rad_rotation,
|
||||
void J2D::DrawPartialRenderTarget(const RenderTarget* rt, 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) {
|
||||
DrawPartialRenderTarget(*rt, position, sub_texture_position, sub_texture_size, rad_rotation, origin, scale, color, inversion);
|
||||
}
|
||||
|
||||
void JGL::J2D::DrawSprite(const Texture& texture, const Vector2& pos, float rad_rotation, const Vector2& origin,
|
||||
void 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,13 +549,13 @@ 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);
|
||||
}
|
||||
|
||||
|
||||
void JGL::J2D::DrawSprite(const Texture& texture, float positionX, float positionY, float rad_rotation, float originX,
|
||||
void J2D::DrawSprite(const Texture& texture, float positionX, float positionY, float rad_rotation, float originX,
|
||||
float originY, float scaleX, float scaleY, const Color4& color, Direction inversion) {
|
||||
DrawSprite(texture,
|
||||
{positionX, positionY},
|
||||
@@ -637,10 +565,10 @@ void JGL::J2D::DrawSprite(const Texture& texture, float positionX, float positio
|
||||
color, inversion);
|
||||
}
|
||||
|
||||
void JGL::J2D::DrawPartialSprite(const Texture& texture, const Vector2& position, const Vector2& sub_texture_position,
|
||||
void 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,27 +638,27 @@ 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);
|
||||
}
|
||||
|
||||
void JGL::J2D::DrawPartialSprite(const JGL::Texture& texture, float positionX, float positionY, float sub_texture_positionX,
|
||||
void J2D::DrawPartialSprite(const Texture& texture, float positionX, float positionY, float sub_texture_positionX,
|
||||
float sub_texture_positionY, unsigned int sub_texture_sizeX,
|
||||
unsigned int sub_texture_sizeY, float originX, float originY, float rad_rotation,
|
||||
float scaleX, float scaleY, const Color4& color, JGL::Direction inversion) {
|
||||
float scaleX, float scaleY, const Color4& color, Direction inversion) {
|
||||
|
||||
JGL::J2D::DrawPartialSprite(texture, {positionX, positionY}, {sub_texture_positionX, sub_texture_positionY},
|
||||
J2D::DrawPartialSprite(texture, {positionX, positionY}, {sub_texture_positionX, sub_texture_positionY},
|
||||
{(float) sub_texture_sizeX, (float) sub_texture_sizeY}, rad_rotation, {originX, originY},
|
||||
{scaleX, scaleY}, color, inversion);
|
||||
}
|
||||
|
||||
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)
|
||||
void J2D::DrawMirrorSprite(const Texture& texture, const Vector2& position, Direction mirror_axis, float rad_rotation, const Vector2& origin, const Vector2& scale, const Color4& color) {
|
||||
if (!state_stack.Size())
|
||||
Logger::Error("Drawing J2D element before J2D begin.");
|
||||
|
||||
if (mirror_axis == Direction::None)
|
||||
Logger::Warning("Drawing non-mirrored sprite with JGL::J2D::DrawMirrorSprite?");
|
||||
Logger::Warning("Drawing non-mirrored sprite with J2D::DrawMirrorSprite?");
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture.GetHandle());
|
||||
Vector2 size = Vector2(texture.GetDimensions());
|
||||
@@ -804,13 +732,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)
|
||||
void J2D::OutlineCircle(const Color4& color, const Vector2& center, float radius, unsigned int subdivisions, float thickness) {
|
||||
if (!state_stack.Size())
|
||||
Logger::Error("Drawing J2D element before J2D begin.");
|
||||
|
||||
float step = (2.f * Math::Pi) / (float) subdivisions;
|
||||
@@ -833,13 +761,20 @@ 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)
|
||||
void J2D::FillCircle(const Color4& color, const Vector2& center, float radius, unsigned int subdivisions) {
|
||||
BatchFillCircle(&color, ¢er, &radius, subdivisions, 1);
|
||||
}
|
||||
|
||||
void J2D::BatchFillCircle(const Color4* colors, const Vector2* positions, float* radii, unsigned int subdivisions, const size_t& circle_count) {
|
||||
if (!state_stack.Size())
|
||||
Logger::Error("Drawing J2D element before J2D begin.");
|
||||
|
||||
if (circle_count <= 0)
|
||||
return;
|
||||
|
||||
GLfloat angle, x, y;
|
||||
float step = (2.f * Math::Pi) / (float) subdivisions;
|
||||
std::vector<Vector2> vertices(subdivisions);
|
||||
@@ -849,8 +784,8 @@ void JGL::J2D::FillCircle(const Color4& color, const Vector2& center, float radi
|
||||
* wait around for the container to resize. This gets rid of it for what we can guarantee. */
|
||||
int i = 0;
|
||||
for (angle = 0.0f; angle < (2.f * Math::Pi); angle += step) {
|
||||
x = radius * std::sin(angle) + center.x;
|
||||
y = radius * std::cos(angle) + center.y;
|
||||
x = std::sin(angle);
|
||||
y = std::cos(angle);
|
||||
if (i < subdivisions)
|
||||
vertices[i] = {x, y};
|
||||
else
|
||||
@@ -858,14 +793,20 @@ void JGL::J2D::FillCircle(const Color4& color, const Vector2& center, float radi
|
||||
i++;
|
||||
}
|
||||
|
||||
glColor4ubv(color.ptr());
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, (int) vertices.size());
|
||||
glColor4fv(OpenGLState::baseColor);
|
||||
for (size_t j = 0; j < circle_count; j++) {
|
||||
glPushMatrix();
|
||||
glColor4ubv(colors[j].ptr());
|
||||
glTranslatef(positions[j].x, positions[j].y, 0);
|
||||
glScalef(radii[j], radii[j], 0);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, (int) vertices.size());
|
||||
glPopMatrix();
|
||||
}
|
||||
glColor4fv(default_state.draw_color);
|
||||
}
|
||||
|
||||
void JGL::J2D::OutlineTriangle(const Color4& color, const Triangle2D& tri, float thickness) {
|
||||
if (!inJ2D)
|
||||
void J2D::OutlineTriangle(const Color4& color, const Triangle2D& tri, float thickness) {
|
||||
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 +815,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)
|
||||
void J2D::FillTriangle(const Color4& color, const Triangle2D& tri) {
|
||||
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 +827,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)
|
||||
void J2D::FillGradientTriangle(const Color4& a_color, const Color4& b_color, const Color4& c_color, const Triangle2D& tri) {
|
||||
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,50 +844,51 @@ 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.
|
||||
void JGL::J2D::DrawCubicBezierCurve(const Color4& color, const Vector2& controlA, const Vector2& pointA, const Vector2& pointB, const Vector2& controlB,
|
||||
void J2D::DrawCubicBezierCurve(const Color4& color, const Vector2& controlA, const Vector2& pointA, const Vector2& pointB, const Vector2& controlB,
|
||||
int subdivisions, float thickness) {
|
||||
|
||||
|
||||
Vector2 last = controlA;
|
||||
const Vector2& first = controlB;
|
||||
for (int i = 0; i < subdivisions; ++i)
|
||||
{
|
||||
|
||||
std::vector<Vector2> vertices(2 * subdivisions + 2);
|
||||
for (int i = 0; i < subdivisions; ++i) {
|
||||
float alpha = (float) i / (float) subdivisions;
|
||||
Vector2 step = J3ML::Algorithm::Bezier(alpha, controlA, pointA, pointB, controlB);
|
||||
DrawLine(color, last, step, thickness);
|
||||
vertices[2 * i] = last;
|
||||
vertices[2 * i + 1] = step;
|
||||
last = step;
|
||||
}
|
||||
|
||||
// Have to manually draw the last segment of the curve.
|
||||
DrawLine(color, last, first, thickness);
|
||||
vertices[2 * subdivisions] = last;
|
||||
vertices[2 * subdivisions + 1] = first;
|
||||
DrawLines(color, vertices.data(), vertices.size(), thickness);
|
||||
}
|
||||
|
||||
void JGL::J2D::OutlinePolygon(const Color4& color, const Vector2* points, int points_size, float thickness) {
|
||||
if (!inJ2D)
|
||||
void J2D::OutlinePolygon(const Color4& color, const Vector2* points, int points_size, float thickness) {
|
||||
if (!state_stack.Size())
|
||||
Logger::Error("Drawing J2D element before J2D begin.");
|
||||
|
||||
if (points[0] != points[points_size -1])
|
||||
throw std::runtime_error("JGL::J2D::OutlinePolygon: The first point and the last point must connect.");
|
||||
throw std::runtime_error("J2D::OutlinePolygon: The first point and the last point must connect.");
|
||||
|
||||
glLineWidth(thickness);
|
||||
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,
|
||||
void J2D::DrawGradientLine(const Color4& color_a, const Color4& color_b, float x, float y, float w, float h,
|
||||
float thickness) {
|
||||
DrawGradientLine(color_a, color_b, {x, y}, {w, h}, thickness);
|
||||
}
|
||||
|
||||
void JGL::J2D::DrawArc(const Color4& color, const Vector2& center, float radius, float arc_begin, float arc_end, unsigned int subdivisions, float thickness)
|
||||
void 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,10 +916,10 @@ 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)
|
||||
void J2D::OutlineRoundedRect(const Color4& color, const Vector2& pos, const Vector2& size, float radius, float thickness)
|
||||
{
|
||||
// A rounded rectangle of size 2a x 2b with rounding radius r is given by
|
||||
// f(x; a, r) + f(y; b, r) = 1
|
||||
@@ -992,7 +934,6 @@ void JGL::J2D::OutlineRoundedRect(const Color4& color, const Vector2& pos, const
|
||||
|
||||
// TODO: Calculate vertices for top-left quarter-circle.
|
||||
|
||||
Vector2 tl = pos;
|
||||
Vector2 tr = pos + Vector2(size.x, 0);
|
||||
Vector2 br = pos + size;
|
||||
Vector2 bl = pos + Vector2(0, size.y);
|
||||
@@ -1003,10 +944,10 @@ void JGL::J2D::OutlineRoundedRect(const Color4& color, const Vector2& pos, const
|
||||
Vector2 anchor_br = pos + size - Vector2(radius, radius);
|
||||
Vector2 anchor_bl = pos + Vector2(radius, size.y - radius);
|
||||
|
||||
//JGL::J2D::Begin();
|
||||
//JGL::J2D::DrawPoints(Colors::Red, {tl, tr, br, bl}, 2);
|
||||
//JGL::J2D::DrawPoints(Colors::Blue, {anchor_tl, anchor_tr, anchor_br, anchor_bl}, 2);
|
||||
//JGL::J2D::End();
|
||||
//J2D::Begin();
|
||||
//J2D::DrawPoints(Colors::Red, {tl, tr, br, bl}, 2);
|
||||
//J2D::DrawPoints(Colors::Blue, {anchor_tl, anchor_tr, anchor_br, anchor_bl}, 2);
|
||||
//J2D::End();
|
||||
|
||||
Vector2 anchor_topleft_top = pos + Vector2(radius, 0);
|
||||
Vector2 anchor_topright_top = pos + Vector2(size.x - radius, 0);
|
||||
@@ -1020,7 +961,7 @@ void JGL::J2D::OutlineRoundedRect(const Color4& color, const Vector2& pos, const
|
||||
Vector2 anchor_bottomleft_left = pos + Vector2(0, size.y - radius);
|
||||
Vector2 anchor_topleft_left = pos + Vector2(0, radius);
|
||||
|
||||
//JGL::J2D::Begin();
|
||||
//J2D::Begin();
|
||||
|
||||
// The 3.01f, etc is a tiny-bit of overshoot to compensate for the fact that
|
||||
// this is not being plotted as a continuous line-loop.
|
||||
@@ -1028,25 +969,24 @@ void JGL::J2D::OutlineRoundedRect(const Color4& color, const Vector2& pos, const
|
||||
|
||||
unsigned int subdivisions = 9;
|
||||
|
||||
JGL::J2D::DrawArc(color, anchor_tl, radius, Math::Pi, 3.01f*Math::Pi/2.f, subdivisions, thickness);
|
||||
JGL::J2D::DrawLine(color, anchor_topleft_top, anchor_topright_top, thickness);
|
||||
JGL::J2D::DrawArc(color, anchor_tr, radius, 3.f*Math::Pi/2.f, 2.02*Math::Pi, subdivisions, thickness);
|
||||
JGL::J2D::DrawLine(color, anchor_topright_right, anchor_bottomright_right, thickness);
|
||||
JGL::J2D::DrawArc(color, anchor_br, radius, 0.0f, 1.01f*Math::Pi/2, subdivisions, thickness);
|
||||
JGL::J2D::DrawLine(color, anchor_bottomright_bottom, anchor_bottomleft_bottom, thickness);
|
||||
JGL::J2D::DrawArc(color, anchor_bl, radius, Math::Pi/2, Math::Pi*1.01f, subdivisions, thickness);
|
||||
JGL::J2D::DrawLine(color, anchor_bottomleft_left, anchor_topleft_left, thickness);
|
||||
//JGL::J2D::End();
|
||||
J2D::DrawArc(color, anchor_tl, radius, Math::Pi, 3.01f*Math::Pi/2.f, subdivisions, thickness);
|
||||
J2D::DrawLine(color, anchor_topleft_top, anchor_topright_top, thickness);
|
||||
J2D::DrawArc(color, anchor_tr, radius, 3.f*Math::Pi/2.f, 2.02*Math::Pi, subdivisions, thickness);
|
||||
J2D::DrawLine(color, anchor_topright_right, anchor_bottomright_right, thickness);
|
||||
J2D::DrawArc(color, anchor_br, radius, 0.0f, 1.01f*Math::Pi/2, subdivisions, thickness);
|
||||
J2D::DrawLine(color, anchor_bottomright_bottom, anchor_bottomleft_bottom, thickness);
|
||||
J2D::DrawArc(color, anchor_bl, radius, Math::Pi/2, Math::Pi*1.01f, subdivisions, thickness);
|
||||
J2D::DrawLine(color, anchor_bottomleft_left, anchor_topleft_left, thickness);
|
||||
//J2D::End();
|
||||
|
||||
|
||||
}
|
||||
|
||||
void JGL::J2D::FillChamferRect(const Color4& color, const Vector2& pos, const Vector2& size, float radius) {
|
||||
void J2D::FillChamferRect(const Color4& color, const Vector2& pos, const Vector2& size, float radius) {
|
||||
FillRoundedRect(color, pos, size, radius, 4);
|
||||
}
|
||||
|
||||
void JGL::J2D::OutlineChamferRect(const Color4& color, const Vector2& pos, const Vector2& size, float radius,
|
||||
float thickness) {
|
||||
void J2D::OutlineChamferRect(const Color4& color, const Vector2& pos, const Vector2& size, float radius, float thickness) {
|
||||
Vector2 anchor_topleft_top = pos + Vector2(radius, 0);
|
||||
Vector2 anchor_topright_top = pos + Vector2(size.x - radius, 0);
|
||||
Vector2 anchor_topright_right = pos + Vector2(size.x, radius);
|
||||
@@ -1061,29 +1001,29 @@ 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) {
|
||||
void J2D::DrawPoints(const Color4& color, const Vector2* points, int num_points, float radius) {
|
||||
glPointSize(radius);
|
||||
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) {
|
||||
void J2D::FIllTriangle(const Color4& color, const Vector2& triA, const Vector2& triB, const Vector2& triC) {
|
||||
FillTriangle(color, {triA, triB, triC});
|
||||
}
|
||||
|
||||
void JGL::J2D::FillGradientTriangle(const Color4& a_color, const Color4& b_color, const Color4& c_color, const Vector2& tri_a,
|
||||
void J2D::FillGradientTriangle(const Color4& a_color, const Color4& b_color, const Color4& c_color, const Vector2& tri_a,
|
||||
const Vector2& tri_b, const Vector2& tri_c) {
|
||||
FillGradientTriangle(a_color, b_color, c_color, {tri_a, tri_b, tri_c});
|
||||
}
|
||||
|
||||
void JGL::J2D::OutlineEllipse(const Color4& color, const Vector2& position, float radius_x, float radius_y, float thickness,
|
||||
void 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 +1045,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)
|
||||
void J2D::FillEllipse(const Color4& color, const Vector2& position, float radius_x, float radius_y, int subdivisions) {
|
||||
if (!state_stack.Size())
|
||||
Logger::Error("Drawing J2D element before J2D begin.");
|
||||
|
||||
GLfloat angle, x, y;
|
||||
@@ -1133,5 +1073,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);
|
||||
}
|
||||
|
@@ -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<Vector3> 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<Vector3> vertices((sectors + 1) * (stacks + 1));
|
||||
std::vector<unsigned int> 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);
|
||||
|
||||
|
@@ -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();
|
||||
|
@@ -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<const LightBase*, 8> result = required_lights;
|
||||
std::array<const LightBase*, 8> 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<std::pair<float, const LightBase*>> 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<Vector3> 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]);
|
||||
}
|
||||
|
@@ -9,44 +9,75 @@
|
||||
#include <JGL/logger/logger.h>
|
||||
|
||||
namespace JGL {
|
||||
inline constexpr std::array<const LightBase*, 8> empty_light_array = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
|
||||
inline bool inJ2D = false;
|
||||
inline bool inJ3D = false;
|
||||
std::vector<Vector3> 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;
|
||||
RenderTarget* current_render_target = nullptr;
|
||||
|
||||
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<const LightBase*, 8> required_lights{};
|
||||
// List of all lights in the scene.
|
||||
std::vector<const LightBase*> 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<State> 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<const LightBase*, 8> empty_light_array = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
|
||||
std::vector<Vector3> 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;
|
||||
}
|
||||
|
||||
namespace JGL::J2D {
|
||||
inline std::array<const LightBase*, 8> required_lights;
|
||||
inline std::vector<const LightBase*> 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, nullptr, false, false,
|
||||
false, false, true, true,
|
||||
true, false, 0,
|
||||
{}, {}
|
||||
};
|
||||
|
||||
inline State current_state;
|
||||
}
|
||||
|
||||
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<const LightBase*, 8> required_lights;
|
||||
// List of all lights in the scene.
|
||||
inline std::vector<const LightBase*> optional_lights;
|
||||
inline State current_state;
|
||||
inline float far_plane = 0;
|
||||
inline float fov = 0;
|
||||
// Enables lighting and selects the correct lights to use.
|
||||
|
@@ -76,7 +76,7 @@ JGL::RenderTarget::RenderTarget(const JGL::Texture* texture, const Color4& clear
|
||||
texture_created_by_us = false;
|
||||
}
|
||||
|
||||
JGL::RenderTarget::RenderTarget(const Vector2i& size, const Color4& clear_color, bool use_depth, MSAA_SAMPLE_RATE sample_rate) {
|
||||
JGL::RenderTarget::RenderTarget(const Vector2i& size, const Color4& clear_color, bool use_depth, MSAA_SAMPLE_RATE sample_rate, FilteringMode filtering_mode) {
|
||||
if (size.x < 1 || size.y < 1)
|
||||
Logger::Fatal("Creating a render target where the color attachment is empty?");
|
||||
|
||||
@@ -85,7 +85,7 @@ JGL::RenderTarget::RenderTarget(const Vector2i& size, const Color4& clear_color,
|
||||
glGetIntegerv(GL_VIEWPORT, viewport);
|
||||
//Textures behave strangely if they're not square aaaaaaaaaaaaa.
|
||||
|
||||
texture = new Texture(size);
|
||||
texture = new Texture(size, filtering_mode);
|
||||
glGenFramebuffers(1, &framebuffer_object);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_object);
|
||||
glViewport(0,0, size.x, size.y);
|
||||
@@ -140,30 +140,10 @@ void JGL::RenderTarget::Resize(const Vector2i& new_size) {
|
||||
glGetIntegerv(GL_VIEWPORT, old_viewport);
|
||||
glGetFloatv(GL_COLOR_CLEAR_VALUE, old_clear_color);
|
||||
|
||||
/* If what was previously not part of the renderable area is big enough
|
||||
* to just set the new size. */
|
||||
if (new_size.x <= texture->GetDimensions().x && new_size.y <= texture->GetDimensions().y) {
|
||||
size = new_size;
|
||||
|
||||
// Clear.
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_object);
|
||||
auto cc = GetClearColor();
|
||||
glClearColor(cc.RedChannelNormalized(), cc.GreenChannelNormalized(), cc.BlueChannelNormalized(), cc.AlphaChannelNormalized());
|
||||
glViewport(0,0, size.x, size.y);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
if (using_depth)
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, current_fbo);
|
||||
glClearColor(old_clear_color[0], old_clear_color[1], old_clear_color[2], old_clear_color[3]);
|
||||
glViewport(old_viewport[0], old_viewport[1], old_viewport[2], old_viewport[3]);
|
||||
return;
|
||||
}
|
||||
|
||||
//If we have to remake the texture.
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_object);
|
||||
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
|
||||
|
||||
// Erase it.
|
||||
delete texture;
|
||||
|
||||
@@ -240,20 +220,19 @@ bool JGL::RenderTarget::SetMSAAEnabled(JGL::MSAA_SAMPLE_RATE sample_rate) {
|
||||
glGetIntegerv(GL_RENDERBUFFER_BINDING, ¤t_renderbuffer);
|
||||
glGenRenderbuffers(1, &msaa_render_buffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, msaa_render_buffer);
|
||||
glRenderbufferStorageMultisample(GL_RENDERBUFFER, JGL::to_int(sample_rate), GL_RGBA, size.x, size.y);
|
||||
glRenderbufferStorageMultisample(GL_RENDERBUFFER, to_int(sample_rate), GL_RGBA, size.x, size.y);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, msaa_render_buffer);
|
||||
|
||||
if (using_depth) {
|
||||
glGenRenderbuffers(1, &msaa_depth_buffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, msaa_depth_buffer);
|
||||
glRenderbufferStorageMultisample(GL_RENDERBUFFER, JGL::to_int(sample_rate), GL_DEPTH_COMPONENT, size.x, size.y);
|
||||
glRenderbufferStorageMultisample(GL_RENDERBUFFER, to_int(sample_rate), GL_DEPTH_COMPONENT, size.x, size.y);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, msaa_depth_buffer);
|
||||
}
|
||||
|
||||
bool failure = false;
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||
failure = true,
|
||||
Logger::Fatal("A new MSAA " + std::to_string(to_int(sample_rate)) + "x framebuffer couldn't be allocated.");
|
||||
failure = true, Logger::Fatal("A new " + to_string(sample_rate) + " framebuffer couldn't be allocated.");
|
||||
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, current_renderbuffer);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, current_fbo);
|
||||
@@ -283,19 +262,6 @@ void JGL::RenderTarget::MSAABlit() const {
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, current_draw_fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, current_fbo);
|
||||
}
|
||||
|
||||
// Fixes using render targets on a texture that has mipmaps.
|
||||
if (GetTexture()->GetFilteringMode() == FilteringMode::MIPMAP_NEAREST
|
||||
|| GetTexture()->GetFilteringMode() == FilteringMode::MIPMAP_BILINEAR ||
|
||||
GetTexture()->GetFilteringMode() == FilteringMode::MIPMAP_TRILINEAR) {
|
||||
GLint current_texture = 0;
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, ¤t_texture);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, GetTexture()->GetHandle());
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, current_texture);
|
||||
}
|
||||
}
|
||||
|
||||
void JGL::RenderTarget::Blit(const JGL::RenderTarget& source, JGL::RenderTarget* destination, const Vector2i& position) {
|
||||
@@ -381,3 +347,22 @@ JGL::RenderTarget::RenderTarget(const JGL::RenderTarget& rhs) {
|
||||
|
||||
operator delete(this_render_target);
|
||||
}
|
||||
|
||||
Vector2i JGL::RenderTarget::MaximumSize() {
|
||||
return Texture::MaximumSize();
|
||||
}
|
||||
|
||||
void JGL::RenderTarget::RegenerateMipMaps() {
|
||||
// Fixes using render targets on a texture that has mipmaps.
|
||||
if (GetTexture()->GetFilteringMode() == FilteringMode::MIPMAP_NEAREST
|
||||
|| GetTexture()->GetFilteringMode() == FilteringMode::MIPMAP_BILINEAR ||
|
||||
GetTexture()->GetFilteringMode() == FilteringMode::MIPMAP_TRILINEAR) {
|
||||
GLint current_texture = 0;
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, ¤t_texture);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, GetTexture()->GetHandle());
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, current_texture);
|
||||
}
|
||||
}
|
||||
|
@@ -98,7 +98,9 @@ std::vector<unsigned char> Texture::bmp(const std::filesystem::path& file) {
|
||||
return result;
|
||||
}
|
||||
|
||||
Texture::Texture(const Vector2i& size) : invert_y(true), format(ColorFormat::RGBA), size(size), filtering_mode(FilteringMode::NEAREST), wrapping_mode(WrappingMode::CLAMP_TO_EDGE) {
|
||||
Texture::Texture(const Vector2i& size, FilteringMode filtering_mode) : invert_y(true), format(ColorFormat::RGBA), size(size), filtering_mode(filtering_mode), wrapping_mode(WrappingMode::CLAMP_TO_EDGE) {
|
||||
if (SizeExceedsMaximum(size))
|
||||
Logger::Error("Creating a texture where the size is bigger than the maximum for this system.");
|
||||
GLuint previous_texture;
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*) &previous_texture);
|
||||
|
||||
@@ -107,6 +109,27 @@ Texture::Texture(const Vector2i& size) : invert_y(true), format(ColorFormat::RGB
|
||||
//NEAREST
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
if (filtering_mode == FilteringMode::NEAREST)
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST),
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
else if (filtering_mode == FilteringMode::BILINEAR)
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR),
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
if (filtering_mode == FilteringMode::MIPMAP_NEAREST)
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST),
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
else if (filtering_mode == FilteringMode::MIPMAP_BILINEAR)
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST),
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
else if (filtering_mode == FilteringMode::MIPMAP_TRILINEAR)
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR),
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
//Clamp
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
@@ -114,8 +137,10 @@ Texture::Texture(const Vector2i& size) : invert_y(true), format(ColorFormat::RGB
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.x, size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
glBindTexture(GL_TEXTURE_2D, previous_texture);
|
||||
}
|
||||
|
||||
void Texture::load(const unsigned char* pixels) {
|
||||
if (SizeExceedsMaximum(size))
|
||||
Logger::Error("Creating a texture where the size is bigger than the maximum for this system.");
|
||||
|
||||
GLuint previous_texture;
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*) &previous_texture);
|
||||
|
||||
@@ -272,3 +297,16 @@ Texture::Texture(const Texture* textures, const size_t& texture_count) {
|
||||
next_x += textures[i].GetDimensions().x;
|
||||
}
|
||||
}
|
||||
|
||||
bool Texture::SizeExceedsMaximum(const Vector2i& s) {
|
||||
|
||||
auto max_size = Texture::MaximumSize();
|
||||
return s.x > max_size.x || s.y > max_size.y;
|
||||
}
|
||||
|
||||
Vector2i Texture::MaximumSize() {
|
||||
GLint max_size;
|
||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_size);
|
||||
|
||||
return { max_size, max_size };
|
||||
}
|
||||
|
Reference in New Issue
Block a user