Compare commits

...

6 Commits

Author SHA1 Message Date
eb3e037c96 Gradient FillRect + GradientLine
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 1m31s
2024-07-10 20:00:49 -04:00
672a363c53 Fluff the README a little.
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 1m30s
2024-07-10 15:17:37 -04:00
6a16c3f87e Update main.cpp
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 1m31s
2024-07-10 15:05:21 -04:00
23d3d1f378 Implement stub documentation & small refactors on J2D namespace
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Has been cancelled
2024-07-10 15:05:46 -04:00
523806f9ef Rounded Fill Rect
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 1m49s
2024-07-10 14:49:37 -04:00
d118ae2f8e Accept Color3 & Color4
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 6m0s
2024-07-09 15:10:26 -04:00
9 changed files with 442 additions and 123 deletions

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.25)
cmake_minimum_required(VERSION 3.18)
project(JGL
VERSION 1.0
LANGUAGES CXX
@@ -31,7 +31,7 @@ CPMAddPackage(
CPMAddPackage(
NAME jlog
URL https://git.redacted.cc/josh/jlog/Prerelease-9.zip
URL https://git.redacted.cc/josh/jlog/Prerelease-12.zip
)
CPMAddPackage(

View File

@@ -1,12 +1,43 @@
# Josh Graphics Library
# Goals
Yet Another C++ Rendering Toolkit
![Static Badge](https://img.shields.io/badge/Lit-Based-%20)
## Goals
* Provide single-function-calls to render various graphics primitives in 2D and 3D.
* Integrated directly with our other toolkits (ReWindow, J3ML)
* Quick Rendering of Debug Text, Geometric Widgets, Textures, and so forth.
# Non-Goals
## Non-Goals
* Full Rendering Engine
* OpenGL/Vulkan Wrapper
* Asset Loading & Management
## Features
* Modern C++ (20)
* Little-to-no overhead
* No hand-holding
* No-frills, straight up just renders shapes and text.
* Integrates right into an existing OpenGL rendering system.
## Usage
Install instructions and code samples coming soon :tm: !
## Documentation
Documentation is (sic: will be) automatically generated from latest commit and is hosted at https://doc.redacted.cc/jgl .
## Contributing
Contributions to JGL are welcome! If you find a bug, have a feature request, or would like to contribute code, please submit an issue or pull request to our repository!
## License
JGL is licensed under the Public Domain. See the LICENSE file for details.
## Acknowledgements
JGL is developed and maintained by Josh O'Leary @ Co from Redacted Software and contributors. Special thanks to Redacted.

View File

@@ -1,6 +1,5 @@
#pragma once
#include <JGL/Color4.h>
#include <J3ML/J3ML.h>
namespace JGL
@@ -10,16 +9,9 @@ namespace JGL
u8 r;
u8 g;
u8 b;
Color3 Lerp(const Color3& rhs, float alpha) const;
Color4 WithAlphaChannel(float alpha = 1) const;
Color3(u8 R, u8 G, u8 B) : r(R), g(G), b(B) {}
Color3(const Color4& c)
{
this->r = c.r;
this->g = c.g;
this->b = c.b;
}
u8 RedChannel () const { return r; }
u8 GreenChannel() const { return g; }
u8 BlueChannel () const { return b; }

View File

@@ -1,8 +1,14 @@
#pragma once
#include <JGL/Color3.h>
namespace JGL
{
struct Color4{
class Color4 {
public:
explicit Color4(const Color3& color3, unsigned int alpha) {r = color3.r; g = color3.g; b = color3.b; a = alpha;}
Color4(int red, int green, int blue, int alpha = 127) : r(red), g(green), b(blue), a(alpha) {}
static Color4 FromColor3(const Color3& color3, unsigned int alpha = 127) {return Color4(color3, alpha);}
int r;
int g;
int b;

12
include/JGL/Gradient.h Normal file
View File

@@ -0,0 +1,12 @@
#pragma once
#include <J3ML/J3ML.h>
namespace JGL {
enum class Gradient : u8 {
Vertical = 0,
Horizontal = 1,
DiagonalTopLeft = 2,
DiagonalBottomLeft = 3
};
}

View File

@@ -5,7 +5,8 @@
#include <string>
#include <iostream>
#include <JGL/Color3.h>
#include <JGL/Color4.h>
#include <JGL/Gradient.h>
#include <JGL/FontCache.h>
#include <J3ML/LinearAlgebra.h>
#include <J3ML/LinearAlgebra/Vector2.h>
@@ -13,6 +14,7 @@
#include <J3ML/Geometry/Sphere.h>
#include <J3ML/Geometry/Capsule.h>
#include <J3ML/Geometry/TriangleMesh.h>
// OpenGL Wrapper for rendering 2D graphics primitives in both a 2D and 3D context
namespace JGL {
@@ -56,35 +58,96 @@ namespace JGL {
void UnloadFont(int font_index);
// TODO: implement correct coloring
/// Drawing functions for primitive 2D Shapes.
/// Each function is overloaded with Color3 and Color4 for optional transparency.
namespace J2D {
/// Open a 2-D rendering context with the underlying graphics system (In this case & by default OpenGL).
/// @note This call may not strictly be necessary on some setups, but is provided to keep the API constant.
/// It is recommended to always open a JGL 2D context to render your content, then close when completed.
/// This keeps our code from, say, clobbering the OpenGL rendering context driving 3D content in between our calls.
void Begin();
/// Closes a 2-D rendering context with the underlying graphics system (In this case & by default OpenGL).
/// @see Begin().
void End();
/// Plots a single pixel on the screen.
/// @param color A 3-or-4 channel color value. @see classes Color3, Color4
/// @param coordinates The pixel-point on-screen at which to plot the pixel.
void DrawPixel(const Color3& color, const Vector2& coordinates);
void DrawPixel(const Color3& color, float x, float y);
void DrawPixel(const Color4& color, const Vector2& coordinates);
void DrawPixel(const Color4& color, float x, float y);
/// Plots a line (segment) on the screen.
/// @param color A 3-or-4 channel color value. @see classes Color3, Color4.
/// @param A The starting point of the line segment.
/// @param B The end point of the line segment.
/// @param thickness The width at which to render the line.
void DrawLine(const Color3& color, const Vector2& A, const Vector2& B, float thickness = 1);
void DrawLine(const Color3& color, float x, float y, float w, float h, float thickness = 1);
void DrawCubicBezierCurve();
void OutlineCircle(const Color3& color, const Vector2& center, float radius, int subdivisions, float thickness = 1);
void FillCircle(const Color3& color, const Vector2& center, float radius, int subdivisions);
void DrawLine(const Color3 &color, float x, float y, float w, float h, float thickness = 1);
void DrawLine(const Color4& color, const Vector2& A, const Vector2& B, float thickness = 1);
void DrawLine(const Color4& color, float x1, float y1, float x2, float y2, float thickness = 1);
///Draws a line with a gradient that transitions across it.
void DrawGradientLine(const Color4& color1, const Color4& color2, const Vector2& A, const Vector2& B, float thickness = 1);
void DrawGradientLine(const Color3& color1, const Color3& color2, const Vector2& A, const Vector2& B, float thickness = 1);
void DrawGradientLine(const Color4& color1, const Color4& color2, float x, float y, float w, float h, float thickness = 1);
void DrawGradientLine(const Color3& color1, const Color3& color2, float x, float y, float w, float h, float thickness = 1);
/// Draws an outline of a rectangle on the screen.
void OutlineRect(const Color4& color, const Vector2& pos, const Vector2& size, float thickness = 1);
void OutlineRect(const Color3& color, const Vector2& pos, const Vector2& size, float thickness = 1);
/// Draws a filled rectangle on the screen.
void FillRect(const Color4& color, const Vector2& pos, const Vector2& size);
void FillRect(const Color3& color, const Vector2& pos, const Vector2& size);
/// Draws a filled rectangle where the color transitions across it.
void FillGradientRect(const Color4& color1, const Color4& color2, const Gradient& gradient, const Vector2& pos, const Vector2& size);
void FillGradientRect(const Color3& color1, const Color3& color2, const Gradient& gradient, const Vector2& pos, const Vector2& size);
/// Draws a filled rectangle with rounded corners on the screen.
void FillRoundedRect(const Color4 &color, const Vector2 &pos, const Vector2 &size, float radius = 5, unsigned int subdivisions = 8);
void FillRoundedRect(const Color3& color, const Vector2& pos, const Vector2& size, float radius = 5, unsigned int subdivisions = 8);
/// Draws an outline of a circle on the screen.
void OutlineCircle(const Color4& color, const Vector2& center, float radius, unsigned int subdivisions = 16, float thickness = 1);
void OutlineCircle(const Color3& color, const Vector2& center, float radius, unsigned int subdivisions = 16, float thickness = 1);
/// Draws a filled circle on the screen.
void FillCircle(const Color4& color, const Vector2& center, float radius, unsigned int subdivisions = 8);
void FillCircle(const Color3& color, const Vector2& center, float radius, unsigned int subdivisions = 8);
/// Draws an outline of a triangle on the screen.
void OutlineTriangle(const Color4& color, const Triangle2D& tri, float thickness = 1);
void OutlineTriangle(const Color3& color, const Triangle2D& tri, float thickness = 1);
void FillTriangle(const Color3& color, const Triangle2D &tri);
// TODO: Implement an overload that simply takes 3 Vector3's
/// Draws a filled triangle on the screen.
void FillTriangle(const Color4& color, const Triangle2D &tri);
void FillTriangle(const Color3& color, const Triangle2D& tri);
// TODO: Implement an overload that simply takes 3 Vector3's
/// Draws a text string on the screen with a given point-size and font.
void DrawString(const Color3& color, std::string text, float x, float y, float scale, u32 size, unsigned int font_index);
// TODO: Implement the following:
void FillTexturedTriangle();
void FillTexturedPolygon();
void DrawSprite();
void DrawPartialSprite();
void DrawString(const Color3& color, std::string text, float x, float y, float scale, u32 size, unsigned int font_index);
void FillRect(const Color3 &color, const Vector2& pos, const Vector2& size);
void OutlineRect ( const Color3& color, const Vector2& pos, const Vector2& size, float thickness = 1);
void FillRoundedRect (const Color3& color, const Vector2& pos, const Vector2& size, float radius);
void OutlineRoundedRect(const Color3& color, const Vector2& pos, const Vector2& size, float radius, float thickness = 1);
void OutlinePolygon (const Color3& color, std::vector<Vector2> points);
void FillPolygon (const Color3& color, std::vector<Vector2> points, float thickness = 1);
void GradientFillRect ();
void DrawCubicBezierCurve();
void OutlinePolygon (const Color4& color, std::vector<Vector2> points);
void FillPolygon (const Color4& color, std::vector<Vector2> points, float thickness = 1);
void OutlineRoundedRect(const Color4& color, const Vector2& pos, const Vector2& size, float radius = 5, float thickness = 1);
}
namespace J3D {
void Begin();
void End();
void SetMatrix(const std::vector<GLfloat>& matrix, const Vector2& window_size);
void DrawLine(const Color4& color, const Vector3& A, const Vector3& B, float thickness = 1);
void DrawLine(const Color3& color, const Vector3& A, const Vector3& B, float thickness = 1);
void FillSphere(const Color3& color, const Sphere& sphere);
void WireframeSphere(const Color3& color, const Sphere& sphere, float thickness = 1);

View File

@@ -88,27 +88,37 @@ public:
Vector3 textAngle = {0,0,0};
void display() {
textAngle.y += 1.0f;
textAngle.y += 2.0f;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//camera->angle.y += 1;
camera->render();
///All 3D elements of the scene and JGL elements *must* be rendered before the 2d stuff.
J3D::Begin();
J3D::DrawLine(JGL::Colors::Red, {-0.33,-0.125,1}, {-1,-0.125,1});
J3D::DrawLine(JGL::Colors::Red, {-0.33,-0.125,1}, {-0.33,0.25,1});
J3D::DrawString(JGL::Colors::Red, "JGL Sample Text", {-0.33, -0.1, 1.0f},textAngle , 1.f, 32, FreeSans);
J3D::DrawString(JGL::Colors::Red, "JGL Sample Text", {-0.33, -0.1, 1.0f},textAngle, 1.f, 32, FreeSans);
J3D::End();
J2D::Begin();
J2D::OutlineRect(JGL::Colors::Blue, {32, 32}, {100.5, 100.5});
J2D::OutlineTriangle(JGL::Colors::Yellow, {{140, 200},{135, 100},{105, 100}}, 1);
J2D::FillCircle(JGL::Colors::White, {120, 200}, 20, 16);
J2D::DrawLine(JGL::Colors::Green, {10, 10}, {200, 300}, 1);
J2D::DrawString(JGL::Colors::Green, "Jupteroid Font", 0.f, -48.f, 1.f, 16, Jupiteroid);
J2D::DrawString(JGL::Colors::White, "Position: " + std::to_string(camera->position.x) + " " + std::to_string(camera->position.y) + " " + std::to_string(camera->position.z), 0, -65, 1,16, Jupiteroid);
J2D::DrawString(JGL::Colors::White, "ViewAngle: " + std::to_string(camera->angle.x) + " " + std::to_string(camera->angle.y) + " " + std::to_string(camera->angle.z), 0, -82, 1,16, Jupiteroid);
J2D::FillRect(Colors::Blue, {0,52}, {100,100});
J2D::FillRect(Color4::FromColor3(Colors::Pinks::HotPink), {68, 120}, {32, 32});
J2D::FillGradientRect(Colors::Red, Colors::Blue, Gradient::DiagonalBottomLeft, {100,52}, {100,100});
J2D::FillRoundedRect(JGL::Colors::Red, {200, 52}, {100, 100}, 8, 8);
J2D::FillRoundedRect(JGL::Colors::Purples::BlueViolet, {300, 52}, {100, 100}, 8, 4);
J2D::FillCircle(JGL::Colors::White, {52, 204}, 50, 24);
J2D::OutlineCircle(JGL::Colors::White, {153, 204}, 50, 24);
J2D::FillTriangle(Colors::Red, {{0, 275}, {0, 375}, {100, 375}});
J2D::OutlineTriangle(Colors::Blue, {{100, 275}, {0, 275}, {100, 375}});
J2D::DrawGradientLine(JGL::Colors::Red, JGL::Colors::Blue, {105, 375}, {200, 275}, 2);
J2D::DrawString(JGL::Colors::Green, "Jupteroid Font", 0.f, 16, 1.f, 16, Jupiteroid);
J2D::DrawString(JGL::Colors::White, "Position: " + std::to_string(camera->position.x) + " " + std::to_string(camera->position.y) + " " + std::to_string(camera->position.z), 0, 33, 1,16, Jupiteroid);
J2D::DrawString(JGL::Colors::White, "ViewAngle: " + std::to_string(camera->angle.x) + " " + std::to_string(camera->angle.y) + " " + std::to_string(camera->angle.z), 0, 50, 1,16, Jupiteroid);
J2D::End();
}

View File

@@ -5,9 +5,18 @@
#include <JGL/JGL.h>
#include <glad/glad.h>
#include <JGL/Color3.h>
#include <jlog/jlog.hpp>
GLfloat oldColor[4] = {0, 0, 0, 255};
bool inJ2D = false;
bool inJ3D = false;
bool wasTexture2DEnabled = false;
bool wasTextureCoordArrayEnabled = false;
bool wasDepthTestEnabled = false;
bool wasVertexArraysEnabled = false;
bool wasCullFaceEnabled = false;
bool wasBlendEnabled = false;
bool wasColorArrayEnabled = false;
namespace JGL {
using namespace J3ML;
@@ -16,13 +25,9 @@ namespace JGL {
bool Update(const Vector2& window_size) {
wS = window_size;
return JGL::InitTextEngine();
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
void J2D::Begin() {
glEnable(GL_TEXTURE_2D);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
@@ -36,14 +41,45 @@ namespace JGL {
wasDepthTestEnabled = true,
glDisable(GL_DEPTH_TEST);
wasVertexArraysEnabled = false;
wasVertexArraysEnabled = true;
if (!glIsEnabled(GL_VERTEX_ARRAY))
wasVertexArraysEnabled = false,
glEnable(GL_VERTEX_ARRAY);
wasCullFaceEnabled = true;
if (!glIsEnabled(GL_CULL_FACE))
wasCullFaceEnabled = false,
glEnable(GL_CULL_FACE),
glCullFace(GL_BACK);
wasBlendEnabled = true;
if (!glIsEnabled(GL_BLEND))
wasBlendEnabled = false,
glEnable(GL_BLEND),
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
wasTexture2DEnabled = true;
if (!glIsEnabled(GL_TEXTURE_2D))
wasTexture2DEnabled = false,
glEnable(GL_TEXTURE_2D);
wasTextureCoordArrayEnabled = true;
if (!glIsEnabled(GL_TEXTURE_COORD_ARRAY))
wasTextureCoordArrayEnabled = false,
glEnable(GL_TEXTURE_COORD_ARRAY);
wasColorArrayEnabled = false;
if (glIsEnabled(GL_COLOR_ARRAY))
wasColorArrayEnabled = true,
glDisable(GL_COLOR_ARRAY);
if (!inJ3D)
inJ2D = true;
else { ERROR("Attempt to Begin J2D inside of J3D context.") }
}
void J2D::End() {
//Change back to the previous projection (The 3D one in Re3D's case.
//Change back to the previous projection (The 3D one in Re3D's case.)
glDisable(GL_TEXTURE_2D);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
@@ -55,52 +91,188 @@ namespace JGL {
if (!wasVertexArraysEnabled)
glDisable(GL_VERTEX_ARRAY);
//std::cout << (int) glIsEnabled(GL_VERTEX_ARRAY) << std::endl;
if (!wasCullFaceEnabled)
glDisable(GL_CULL_FACE);
if (!wasBlendEnabled)
glDisable(GL_BLEND);
if (!wasTexture2DEnabled)
glDisable(GL_TEXTURE_2D);
if (!wasTextureCoordArrayEnabled)
glDisable(GL_TEXTURE_COORD_ARRAY);
if (wasColorArrayEnabled)
glEnable(GL_COLOR_ARRAY);
//Put the draw color back how it was before.
glColor4f(oldColor[0], oldColor[1], oldColor[2], oldColor[3]);
inJ2D = false;
}
void J2D::FillRect(const Color3& color, const Vector2& pos, const Vector2& size) {
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}};
void J2D::FillRect(const Color4& color, const Vector2& pos, const Vector2& size) {
if (!inJ2D)
ERROR("Attempt to Render J2D element before J2D begin.")
glColor3f(color.r / 255.f, color.g / 255.f, color.b / 255.f);
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}};
glColor4f(color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f);
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
glDrawArrays(GL_QUADS, 0, 4);
}
void J2D::OutlineRect(const Color3& color, const Vector2& pos, const Vector2& size, float thickness) {
void J2D::FillRect(const Color3& color, const Vector2& pos, const Vector2& size) {
J2D::FillRect({color.r, color.g, color.b, 255}, pos, size);
}
void J2D::FillGradientRect(const Color4& color1, const Color4& color2, const Gradient& gradient, const Vector2& pos, const Vector2& size) {
if (!inJ2D)
ERROR("Attempt to Render 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}};
std::vector<GLfloat> colors = {};
if (gradient == Gradient::Horizontal)
colors = {color1.r / 255.f, color1.g / 255.f, color1.b / 255.f, color1.a / 255.f, color1.r / 255.f, color1.g / 255.f, color1.b / 255.f, color1.a / 255.f,
color2.r / 255.f, color2.g / 255.f, color2.b / 255.f, color2.a / 255.f, color2.r / 255.f, color2.g / 255.f, color2.b / 255.f, color2.a / 255.f};
else if (gradient == Gradient::Vertical)
colors = {color1.r / 255.f, color1.g / 255.f, color1.b / 255.f, color1.a / 255.f, color2.r / 255.f, color2.g / 255.f, color2.b / 255.f, color2.a / 255.f,
color2.r / 255.f, color2.g / 255.f, color2.b / 255.f, color2.a / 255.f, color1.r / 255.f, color1.g / 255.f, color1.b / 255.f, color1.a / 255.f};
else if (gradient == Gradient::DiagonalBottomLeft)
colors = {(color1.r + color2.r) / 2.f / 255.f, (color1.g + color2.g) / 2.f / 255.f, (color1.b + color2.b) / 2.f / 255.f, (color1.a + color2.a) / 2.f / 255.f,
color1.r / 255.f, color1.g / 255.f, color1.b / 255.f, color1.a / 255.f,(color1.r + color2.r) / 2.f / 255.f, (color1.g + color2.g) / 2.f / 255.f,
(color1.b + color2.b) / 2.f / 255.f, (color1.a + color2.a) / 2.f / 255.f, color2.r / 255.f, color2.g / 255.f, color2.b / 255.f, color2.a / 255.f};
else if (gradient == Gradient::DiagonalTopLeft)
colors = {color1.r / 255.f, color1.g / 255.f, color1.b / 255.f, color1.a / 255.f,(color1.r + color2.r) / 2.f / 255.f, (color1.g + color2.g) / 2.f / 255.f,
(color1.b + color2.b) / 2.f / 255.f, (color1.a + color2.a) / 2.f / 255.f,color2.r / 255.f, color2.g / 255.f, color2.b / 255.f, color2.a / 255.f,
(color1.r + color2.r) / 2.f / 255.f, (color1.g + color2.g) / 2.f / 255.f, (color1.b + color2.b) / 2.f / 255.f,(color1.a + color2.a) / 2.f / 255.f};
glEnable(GL_COLOR_ARRAY);
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
glColorPointer(4, GL_FLOAT, 0, colors.data());
glDrawArrays(GL_QUADS, 0, 4);
glDisable(GL_COLOR_ARRAY);
}
void J2D::FillGradientRect(const Color3& color1, const Color3& color2, const Gradient& gradient, const Vector2& pos, const Vector2& size) {
J2D::FillGradientRect({color1.r, color1.g, color1.b, 255}, {color2.r, color2.g, color2.b, 255}, gradient, pos, size);
}
void J2D::FillRoundedRect(const Color4 &color, const Vector2 &pos, const Vector2 &size, float radius, unsigned int subdivisions) {
if (!inJ2D)
ERROR("Attempt to Render J2D element before J2D begin.")
J2D::FillRect(color, {pos.x + radius, pos.y}, {size.x - 2 * radius, size.y});
J2D::FillRect(color, {pos.x, pos.y + radius}, {size.x, size.y - 2 * radius});
J2D::FillCircle(color, {pos.x + radius, pos.y + radius}, radius, subdivisions);
J2D::FillCircle(color, {pos.x + size.x - radius, pos.y + radius}, radius, subdivisions);
J2D::FillCircle(color, {pos.x + radius, pos.y + size.y - radius}, radius, subdivisions);
J2D::FillCircle(color, {pos.x + size.x - radius, pos.y + size.y - radius}, radius, subdivisions);
}
void J2D::FillRoundedRect(const JGL::Color3& color, const J3ML::LinearAlgebra::Vector2& pos, const J3ML::LinearAlgebra::Vector2& size, float radius, unsigned int subdivisions) {
J2D::FillRoundedRect({color.r, color.g, color.b, 255}, pos, size, radius, subdivisions);
}
void J2D::OutlineRect(const Color4& color, const Vector2& pos, const Vector2& size, float thickness) {
if (!inJ2D)
ERROR("Attempt to Render 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}};
glLineWidth(thickness);
glColor3f(color.r, color.g, color.b);
glColor4f(color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f);
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
glDrawArrays(GL_LINE_LOOP, 0, 4);
}
void J2D::DrawLine(const Color3& color, const Vector2& A, const Vector2& B, float thickness) {
void J2D::OutlineRect(const Color3& color, const Vector2& pos, const Vector2& size, float thickness) {
J2D::OutlineRect({color.r, color.g, color.b, 255}, pos, size, thickness);
}
void J2D::DrawLine(const Color4& color, const Vector2& A, const Vector2& B, float thickness) {
if (!inJ2D)
ERROR("Attempt to Render J2D element before J2D begin.");
Vector2 vertices[] = {A, B};
glLineWidth(thickness);
glColor3f(color.r / 255.f, color.g / 255.f, color.b / 255.f);
glColor4f(color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f);
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
glDrawArrays(GL_LINES, 0, 2);
}
void J2D::DrawLine(const Color3& color, float x, float y, float w, float h, float thickness) {
DrawLine(color, {x, y}, {w, h}, thickness);
void J2D::DrawLine(const Color3& color, const Vector2& A, const Vector2& B, float thickness) {
J2D::DrawLine({color.r, color.g, color.b, 255}, A, B, thickness);
}
void J2D::DrawPixel(const Color3& color, const Vector2& coordinates) {
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::DrawLine(const Color3& color, float x, float y, float w, float h, float thickness) {
J2D::DrawLine({color.r, color.g, color.b, 255}, x, y, w, h, thickness);
}
void J2D::DrawGradientLine(const Color4& color1, const Color4& color2, const Vector2& A, const Vector2& B, float thickness) {
if (!inJ2D)
ERROR("Attempt to Render J2D element before J2D begin.");
Vector2 vertices[] = {A, B};
GLfloat colors[8] = {color1.r / 255.f, color1.g / 255.f, color1.b / 255.f, color1.a / 255.f,
color2.r / 255.f, color2.g / 255.f, color2.b / 255.f, color2.a / 255.f};
glEnable(GL_COLOR_ARRAY);
glLineWidth(thickness);
glColorPointer(4,GL_FLOAT,sizeof(GL_FLOAT) * 4, colors);
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
glDrawArrays(GL_LINES, 0, 2);
glDisable(GL_COLOR_ARRAY);
}
void J2D::DrawGradientLine(const Color3& color1, const Color3& color2, const Vector2& A, const Vector2& B, float thickness) {
J2D::DrawGradientLine({color1.r, color1.g, color1.b, 255}, {color2.r, color2.g, color2.b, 255}, A, B, thickness);
}
void DrawGradientLine(const Color4& color1, const Color4& color2, float x, float y, float w, float h, float thickness) {
J2D::DrawGradientLine(color1, color2, {x, y}, {w, h}, thickness);
}
void DrawGradientLine(const Color3& color1, const Color3& color2, float x, float y, float w, float h, float thickness) {
J2D::DrawGradientLine({color1.r, color1.g, color1.b, 255}, {color2.r, color2.g, color2.b, 255}, {x, y}, {w, h}, thickness);
}
void J2D::DrawPixel(const Color4& color, const Vector2& coordinates) {
if (!inJ2D)
ERROR("Attempt to Render J2D element before J2D begin.");
Vector2 vertices[] = {coordinates};
glColor3f(color.r / 255.f, color.g / 255.f, color.b / 255.f);
glColor4f(color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f);
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
glDrawArrays(GL_LINES, 0, 1);
}
void J2D::DrawPixel(const Color3& color, float x, float y) {
void J2D::DrawPixel(const Color3& color, const Vector2& coordinates) {
J2D::DrawPixel({color.r, color.g, color.b, 255}, coordinates);
}
void J2D::DrawPixel(const Color4& color, float x, float y) {
DrawPixel(color, {x, y});
}
void J2D::OutlineCircle(const Color3& color, const Vector2& center, float radius, int subdivisions, float thickness) {
void J2D::DrawPixel(const Color3& color, float x, float y) {
DrawPixel({color.r, color.g, color.b, 255}, {x, y});
}
void J2D::OutlineCircle(const Color4& color, const Vector2& center, float radius, unsigned int subdivisions, float thickness) {
if (!inJ2D)
ERROR("Attempt to Render J2D element before J2D begin.")
float step = (2.f * M_PI) / (float) subdivisions;
std::vector<Vector2> vertices{};
GLfloat angle, x, y;
@@ -112,46 +284,72 @@ namespace JGL {
}
glLineWidth(thickness);
glColor3f(color.r / 255.f, color.g / 255.f, color.b / 255.f);
glColor4f(color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f);
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
glDrawArrays(GL_LINE_LOOP, 0, vertices.size());
}
void J2D::FillCircle(const Color3& color, const Vector2& center, float radius, int subdivisions) {
float step = (2.f * M_PI) / (float) subdivisions;
void J2D::OutlineCircle(const Color3& color, const Vector2& center, float radius, unsigned int subdivisions, float thickness) {
J2D::OutlineCircle({color.r, color.g, color.b, 255}, center, radius, subdivisions, thickness);
}
void J2D::FillCircle(const Color4& color, const Vector2& center, float radius, unsigned int subdivisions) {
if (!inJ2D)
ERROR("Attempt to Render J2D element before J2D begin.")
float step = (2.f * M_PI) / (float) subdivisions;;
std::vector<Vector2> vertices{};
GLfloat angle, x, y;
for (angle = 0.0f; angle < (2.f * M_PI); angle += step) {
x = radius * sin(angle) + center.x;
y = radius * cos(angle) + center.y;
vertices.push_back({x, y});
}
for (angle = 0.0f; angle < (2.f * M_PI); angle += step)
x = radius * sin(angle) + center.x,
y = radius * cos(angle) + center.y,
vertices.push_back({x, y});
glColor3f(color.r / 255.f, color.g / 255.f, color.b / 255.f);
glColor4f(color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f);
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
glDrawArrays(GL_POLYGON, 0, vertices.size());
glDrawArrays(GL_TRIANGLE_FAN, 0, vertices.size());
}
void J2D::OutlineTriangle(const Color3& color, const Triangle2D& tri, float thickness) {
void J2D::FillCircle(const Color3& color, const Vector2& center, float radius, unsigned int subdivisions) {
J2D::FillCircle({color.r, color.g, color.b, 255}, center, radius, subdivisions);
}
void J2D::OutlineTriangle(const Color4& color, const Triangle2D& tri, float thickness) {
if (!inJ2D)
ERROR("Attempt to Render 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}};
glLineWidth(thickness);
glColor3f(color.r / 255.f, color.g / 255.f, color.b / 255.f);
glColor4f(color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f);
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
glDrawArrays(GL_LINE_LOOP, 0, 3);
}
void J2D::FillTriangle(const Color3& color, const Triangle2D &tri) {
void J2D::OutlineTriangle(const Color3& color, const Triangle2D& tri, float thickness) {
J2D::OutlineTriangle({color.r, color.g, color.b, 255}, tri, thickness);
}
void J2D::FillTriangle(const Color4& color, const Triangle2D &tri) {
if (!inJ2D)
ERROR("Attempt to Render 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}};
glColor3f(color.r / 255.f, color.g / 255.f, color.b / 255.f);
glColor4f(color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f);
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
void J2D::FillTriangle(const Color3& color, const Triangle2D &tri) {
J2D::FillTriangle({color.r, color.g, color.b, 255}, tri);
}
void J3D::Begin() {
glEnable(GL_TEXTURE_2D);
//Get what the draw color was before we did anything.
glGetFloatv(GL_CURRENT_COLOR, oldColor);
wasDepthTestEnabled = false;
if (glIsEnabled(GL_DEPTH_TEST))
@@ -162,6 +360,29 @@ namespace JGL {
if (!glIsEnabled(GL_VERTEX_ARRAY))
wasVertexArraysEnabled = false,
glEnable(GL_VERTEX_ARRAY);
wasTexture2DEnabled = true;
if (!glIsEnabled(GL_TEXTURE_2D))
wasTexture2DEnabled = false,
glEnable(GL_TEXTURE_2D);
//TODO We won't always want this but for now we do.
wasCullFaceEnabled = false;
if (glIsEnabled(GL_CULL_FACE))
wasCullFaceEnabled = true,
glDisable(GL_CULL_FACE);
wasBlendEnabled = true;
if (!glIsEnabled(GL_BLEND))
wasBlendEnabled = false,
glEnable(GL_BLEND),
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
if (!inJ2D)
inJ3D = true;
else { ERROR("Attempt to Begin J3D inside of J2D context.") }
}
void J3D::End() {
@@ -172,13 +393,35 @@ namespace JGL {
if (!wasVertexArraysEnabled)
glDisable(GL_VERTEX_ARRAY);
if (wasTexture2DEnabled)
glDisable(GL_TEXTURE_2D);
if (wasBlendEnabled)
glDisable(GL_BLEND);
if (wasCullFaceEnabled)
glEnable(GL_CULL_FACE);
//Put the draw color back how it was before.
glColor4f(oldColor[0], oldColor[1], oldColor[2], oldColor[3]);
inJ3D = false;
}
void J3D::DrawLine(const Color3& color, const Vector3& A, const Vector3& B, float thickness) {
void J3D::DrawLine(const Color4& color, const Vector3& A, const Vector3& B, float thickness) {
if (!inJ3D)
ERROR("Attempt to Render J3D element before J3D begin.")
Vector3 vertices[] = {A, B};
glLineWidth(thickness);
glColor3f(color.r / 255.f, color.g / 255.f, color.b / 255.f);
glColor4f(color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f);
glVertexPointer(3, GL_FLOAT, sizeof(Vector3), vertices);
glDrawArrays(GL_LINES, 0, 2);
}
void J3D::DrawLine(const Color3& color, const Vector3& A, const Vector3& B, float thickness) {
J3D::DrawLine({color.r, color.g, color.b, 255}, A, B, thickness);
}
}

View File

@@ -48,10 +48,10 @@ namespace JGL {
for (int i = 0; i < faces.size(); i++)
if (faces[i].index == font_index)
FT_Done_Face(faces[i].face),
faces.erase(faces.begin() + i);
faces.erase(faces.begin() + i);
}
FontCache fontCache;
void J2D::DrawString(const Color3& color, std::string text, float x, float y, float scale, u32 size, unsigned int font_index) {
glUseProgram(0); // Fixed-function pipeline.
@@ -71,19 +71,12 @@ namespace JGL {
if (font.face == nullptr)
return;
GLfloat currentColor[4];
glGetFloatv(GL_CURRENT_COLOR, currentColor);
glColor4f(color.r / 255.f, color.g / 255.f, color.b / 255.f, 1.0f);
FT_Set_Pixel_Sizes(font.face, 0, size);
std::vector<GLuint> textures(text.length());
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_TEXTURE_2D);
//For each character
for (int i = 0; i < text.length(); i++) {
float x2, y2, w, h;
@@ -100,7 +93,7 @@ namespace JGL {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
x2 = x + glyph->x2offset * scale;
y2 = -y - glyph->y2offset * scale; // Adjust y-coordinate
y2 = y - glyph->y2offset * scale; // Adjust y-coordinate
w = glyph->w * scale;
h = glyph->h * scale;
x += glyph->advanceX * scale;
@@ -130,49 +123,25 @@ namespace JGL {
cachedFont->appendGlyph(new CachedGlyph(textures.at(i), text.c_str()[i], g->bitmap_left, g->bitmap_top, g->bitmap.width, g->bitmap.rows, (g->advance.x >> 6), (g->advance.y >> 6)));
}
glBegin(GL_TRIANGLES);
GLfloat vertices[12] = {x2, y2, x2, y2 + h, x2 + w, y2 + h,x2, y2, x2 + w, y2 + h, x2 + w, y2};
glTexCoord2f(0, 0);
glVertex2f(x2, y2);
glTexCoord2f(0, 1);
glVertex2f(x2, y2 + h);
glTexCoord2f(1, 1);
glVertex2f(x2 + w, y2 + h);
glTexCoord2f(0, 0);
glVertex2f(x2, y2);
glTexCoord2f(1, 1);
glVertex2f(x2 + w, y2 + h);
glTexCoord2f(1, 0);
glVertex2f(x2 + w, y2);
glEnd();
GLfloat textureCoordinates[12] = {0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0};
glTexCoordPointer(2, GL_FLOAT, sizeof(GL_FLOAT) * 2, &textureCoordinates);
glVertexPointer(2, GL_FLOAT, sizeof(GL_FLOAT) * 2, &vertices);
glDrawArrays(GL_TRIANGLES, 0, 6);
}
//for (unsigned int& texture : textures)
//glDeleteTextures(1, &texture);
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
glBindTexture(GL_TEXTURE_2D, 0); // Unbind texture
glColor4f(currentColor[0], currentColor[1], currentColor[2], currentColor[3]); //Set draw color back to whatever it was before.
}
void J3D::DrawString(const Color3& color, const std::string& text, const Vector3& pos, const Vector3& angle, float scale, u32 size, unsigned int font_index)
{
void J3D::DrawString(const Color3& color, const std::string& text, const Vector3& pos, const Vector3& angle, float scale, u32 size, unsigned int font_index) {
//TODO figure out what the scale should actually be mathematically.
scale = scale * 0.002f;
scale = -scale;
float x = pos.x;
float y = pos.y;
float z = pos.z;
GLfloat currentColor[4];
std::vector<GLuint> textures(text.length());;
glGetFloatv(GL_CURRENT_COLOR, currentColor);
glUseProgram(0); // Fixed-function pipeline.
glColor4f(color.r, color.g, color.b, 1.0f);
@@ -202,10 +171,6 @@ namespace JGL {
continue;
FT_GlyphSlot g = font.face->glyph;
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &textures.at(i));
glBindTexture(GL_TEXTURE_2D, textures[i]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@@ -251,10 +216,7 @@ namespace JGL {
for (unsigned int& texture : textures)
glDeleteTextures(1, &texture);
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
glBindTexture(GL_TEXTURE_2D, 0); // Unbind texture
glColor4f(currentColor[0], currentColor[1], currentColor[2], currentColor[3]); //Set draw color back to whatever it was before.
glPopMatrix();
}