Compare commits
39 Commits
Prerelease
...
Prerelease
Author | SHA1 | Date | |
---|---|---|---|
7bf30f6f39 | |||
2a70981bf0 | |||
0147245325 | |||
15dcb79479 | |||
50895153f5 | |||
9688854533 | |||
0005c036b4 | |||
af42d8fd25 | |||
ff4d014739 | |||
9dda4bebc5 | |||
a5bfb4972a | |||
4348f2708a | |||
32dd2b54ca | |||
e8b601aa25 | |||
d5fd3e1a49 | |||
f593a0beac | |||
0b7af6fd31 | |||
eca4309e85 | |||
4be97f52d9 | |||
613a13618c | |||
4150c93c85 | |||
9dee59fd45 | |||
b6b2ca1bfe | |||
4eca3311c8 | |||
54711355c4 | |||
8bddf3e0a7 | |||
26d17dae38 | |||
4ff8d8ff07 | |||
162732e4b7 | |||
289157ab8a | |||
3a658b1096 | |||
480502f89e | |||
d28f680cd0 | |||
2d1e42c23b | |||
abd691b648 | |||
e261b610c2 | |||
8625c52ee9 | |||
74a4705e44 | |||
ae327b96a5 |
@@ -17,8 +17,6 @@ jobs:
|
|||||||
- run: echo "The ${{ gitea.repository }} repository has been cloned to the runner."
|
- run: echo "The ${{ gitea.repository }} repository has been cloned to the runner."
|
||||||
- run: echo "The workflow is now ready to run your tests on the runner."
|
- run: echo "The workflow is now ready to run your tests on the runner."
|
||||||
- run: echo "Install toolchain and run ReCI build test"
|
- run: echo "Install toolchain and run ReCI build test"
|
||||||
- run: apt-get update && apt-get install -y git && git clone $RECI_GIT $RECI
|
- run: apt-get update && apt-get install -y lua5.3 git && git clone $RECI_GIT $RECI
|
||||||
- run: bash $RECI/scripts/setup_build_tools.sh
|
- run: lua $RECI/reci.lua -f $RECI/scripts/buildtools.reci -f reci/scripts/builddeps.reci -f $RECI/scripts/buildtest.reci
|
||||||
- run: bash reci/scripts/install_build_dependencies.sh
|
|
||||||
- run: bash $RECI/scripts/run_buildtest.sh ${{ gitea.repository }}
|
|
||||||
- run: echo "This job's status is ${{ job.status }}."
|
- run: echo "This job's status is ${{ job.status }}."
|
||||||
|
@@ -14,6 +14,12 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
|||||||
# Enable Package Managers
|
# Enable Package Managers
|
||||||
include(cmake/CPM.cmake)
|
include(cmake/CPM.cmake)
|
||||||
|
|
||||||
|
|
||||||
|
CPMAddPackage(
|
||||||
|
NAME mcolor
|
||||||
|
URL https://git.redacted.cc/maxine/mcolor/archive/Prerelease-3.zip
|
||||||
|
)
|
||||||
|
|
||||||
CPMAddPackage(
|
CPMAddPackage(
|
||||||
NAME J3ML
|
NAME J3ML
|
||||||
URL https://git.redacted.cc/josh/j3ml/archive/Release-2.2.zip
|
URL https://git.redacted.cc/josh/j3ml/archive/Release-2.2.zip
|
||||||
@@ -21,7 +27,7 @@ CPMAddPackage(
|
|||||||
|
|
||||||
CPMAddPackage(
|
CPMAddPackage(
|
||||||
NAME ReWindow
|
NAME ReWindow
|
||||||
URL https://git.redacted.cc/Redacted/ReWindow/archive/Prerelease-3.zip
|
URL https://git.redacted.cc/Redacted/ReWindow/archive/Prerelease-9.zip
|
||||||
)
|
)
|
||||||
|
|
||||||
CPMAddPackage(
|
CPMAddPackage(
|
||||||
@@ -38,6 +44,12 @@ CPMAddPackage(
|
|||||||
NAME Event
|
NAME Event
|
||||||
URL https://git.redacted.cc/josh/Event/archive/Release-6.zip
|
URL https://git.redacted.cc/josh/Event/archive/Release-6.zip
|
||||||
)
|
)
|
||||||
|
|
||||||
|
CPMAddPackage(
|
||||||
|
NAME ReTexture
|
||||||
|
URL https://git.redacted.cc/Redacted/ReTexture/archive/Release-1.2.zip
|
||||||
|
)
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
#CPMAddPackage(
|
#CPMAddPackage(
|
||||||
#NAME harfbuzz
|
#NAME harfbuzz
|
||||||
@@ -68,9 +80,13 @@ endif()
|
|||||||
|
|
||||||
set_target_properties(JGL PROPERTIES LINKER_LANGUAGE CXX)
|
set_target_properties(JGL PROPERTIES LINKER_LANGUAGE CXX)
|
||||||
|
|
||||||
|
#Don't expose this one because it's only to be used in the demo program.
|
||||||
|
include_directories(${ReTexture_SOURCE_DIR}/include)
|
||||||
|
|
||||||
target_include_directories(JGL PUBLIC
|
target_include_directories(JGL PUBLIC
|
||||||
${PROJECT_SOURCE_DIR}/include
|
${PROJECT_SOURCE_DIR}/include
|
||||||
${OPENGL_INCLUDE_DIRS}
|
${OPENGL_INCLUDE_DIRS}
|
||||||
|
${mcolor_SOURCE_DIR}/include
|
||||||
${J3ML_SOURCE_DIR}/include
|
${J3ML_SOURCE_DIR}/include
|
||||||
${Event_SOURCE_DIR}/include
|
${Event_SOURCE_DIR}/include
|
||||||
${ReWindow_SOURCE_DIR}/include
|
${ReWindow_SOURCE_DIR}/include
|
||||||
@@ -84,13 +100,13 @@ add_executable(JGL_Demo main.cpp)
|
|||||||
if (UNIX AND NOT APPLE)
|
if (UNIX AND NOT APPLE)
|
||||||
target_include_directories(JGL PRIVATE ${FREETYPE_INCLUDE_DIRS})
|
target_include_directories(JGL PRIVATE ${FREETYPE_INCLUDE_DIRS})
|
||||||
target_link_libraries(JGL PRIVATE ${FREETYPE_LIBRARIES})
|
target_link_libraries(JGL PRIVATE ${FREETYPE_LIBRARIES})
|
||||||
target_link_libraries(JGL PUBLIC ${OPENGL_LIBRARIES} J3ML ReWindowLibrary glad jlog Event)
|
target_link_libraries(JGL PUBLIC ${OPENGL_LIBRARIES} mcolor J3ML ReWindowLibrary glad jlog Event ReTexture)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
target_include_directories(JGL PRIVATE ${freetype_SOURCE_DIR}/include)
|
target_include_directories(JGL PRIVATE ${freetype_SOURCE_DIR}/include)
|
||||||
target_link_libraries(JGL PRIVATE freetype)
|
target_link_libraries(JGL PRIVATE freetype)
|
||||||
target_link_libraries(JGL PUBLIC ${OPENGL_LIBRARIES} J3ML ReWindowLibrary glad jlog Event)
|
target_link_libraries(JGL PUBLIC ${OPENGL_LIBRARIES} mcolor J3ML ReWindowLibrary glad jlog Event ReTexture)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_link_libraries(JGL_Demo PUBLIC JGL)
|
target_link_libraries(JGL_Demo PUBLIC JGL)
|
40
README.md
40
README.md
@@ -4,23 +4,39 @@ Yet Another C++ Rendering Toolkit
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
## 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
|
|
||||||
* Full Rendering Engine
|
|
||||||
* OpenGL/Vulkan Wrapper
|
|
||||||
* Asset Loading & Management
|
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
* Modern C++ (20)
|
* Modern C++ (20)
|
||||||
* Little-to-no overhead
|
* Provides single-function-calls to render various graphics primitives in 2D and 3D.
|
||||||
* No hand-holding
|
* Integrates directly with our other toolkits (ReWindow, J3ML)
|
||||||
* No-frills, straight up just renders shapes and text.
|
* Quick Rendering of Debug Text, Geometric Widgets, Textures, and so forth.
|
||||||
|
* Little-to-no overhead.
|
||||||
* Integrates right into an existing OpenGL rendering system.
|
* Integrates right into an existing OpenGL rendering system.
|
||||||
|
* High-performance text rendering.
|
||||||
|
|
||||||
|
## API Overview
|
||||||
|
|
||||||
|
### J2D
|
||||||
|
* DrawPoint
|
||||||
|
* DrawLine / DrawGradientLine
|
||||||
|
* DrawSprite
|
||||||
|
* OutlineRect / FillRect / FillGradientRect / FillRoundedRect
|
||||||
|
* OutlineCircle / FillCircle
|
||||||
|
* OutlineTriangle / FillTriangle
|
||||||
|
* DrawString
|
||||||
|
### J3D
|
||||||
|
* DrawLine
|
||||||
|
* DrawString
|
||||||
|
* DrawMatrixGizmo (WIP)
|
||||||
|
* DrawAxisAngleGizmo (WIP)
|
||||||
|
* DrawQuaternionGizmo (WIP)
|
||||||
|
|
||||||
|
### Types
|
||||||
|
* Font
|
||||||
|
* Sprite
|
||||||
|
* Color4/Color3
|
||||||
|
* Gradient
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
BIN
assets/sprites/Re3D.png
Normal file
BIN
assets/sprites/Re3D.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.0 KiB |
@@ -1,24 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <J3ML/J3ML.h>
|
|
||||||
|
|
||||||
namespace JGL
|
|
||||||
{
|
|
||||||
using namespace J3ML;
|
|
||||||
struct Color3 {
|
|
||||||
u8 r;
|
|
||||||
u8 g;
|
|
||||||
u8 b;
|
|
||||||
Color3 Lerp(const Color3& rhs, float alpha) const;
|
|
||||||
Color3(u8 R, u8 G, u8 B) : r(R), g(G), b(B) {}
|
|
||||||
|
|
||||||
u8 RedChannel () const { return r; }
|
|
||||||
u8 GreenChannel() const { return g; }
|
|
||||||
u8 BlueChannel () const { return b; }
|
|
||||||
float RedChannelNormalized () const { return static_cast<float>(r) / 255.f;}
|
|
||||||
float BlueChannelNormalized() const { return static_cast<float>(b) / 255.f;}
|
|
||||||
float GreenChannelNormalized() const { return static_cast<float>(g) / 255.f;}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@@ -1,17 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <JGL/Color3.h>
|
|
||||||
|
|
||||||
namespace JGL
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
int a;
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,178 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
|
|
||||||
#include <JGL/Color3.h>
|
|
||||||
|
|
||||||
namespace JGL
|
|
||||||
{
|
|
||||||
namespace Colors {
|
|
||||||
namespace Primary {
|
|
||||||
static const Color3 Red{255, 0, 0};
|
|
||||||
static const Color3 Green{0, 255, 0};
|
|
||||||
static const Color3 Blue{0, 0, 255};
|
|
||||||
static const Color3 White{255, 255, 255};
|
|
||||||
static const Color3 Black{0, 0, 0};
|
|
||||||
static const Color3 Gray{128, 128, 128};
|
|
||||||
static const Color3 DarkGray{192, 192, 192};
|
|
||||||
static const Color3 LightGray{64, 64, 64};
|
|
||||||
static const Color3 Yellow{255, 255, 0};
|
|
||||||
}
|
|
||||||
using namespace Primary;
|
|
||||||
namespace Reds {
|
|
||||||
static const Color3 Fuchsia {255, 0, 255};
|
|
||||||
static const Color3 LightSalmon{255, 160, 122};
|
|
||||||
static const Color3 Salmon{250, 128, 114};
|
|
||||||
static const Color3 DarkSalmon{233, 150, 122};
|
|
||||||
static const Color3 LightCoral{240, 128, 128};
|
|
||||||
static const Color3 IndianRed{205, 92, 92};
|
|
||||||
static const Color3 Crimson{220, 20, 60};
|
|
||||||
static const Color3 Firebrick{178, 34, 34};
|
|
||||||
static const Color3 DarkRed{139, 0, 0};
|
|
||||||
}
|
|
||||||
namespace Oranges {
|
|
||||||
static const Color3 Coral{255, 127, 80};
|
|
||||||
static const Color3 Tomato{255, 99, 71};
|
|
||||||
static const Color3 OrangeRed{255, 69, 0};
|
|
||||||
static const Color3 Gold{255, 215, 0};
|
|
||||||
static const Color3 Orange{255, 165, 0};
|
|
||||||
static const Color3 DarkOrange{255, 140, 0};
|
|
||||||
}
|
|
||||||
namespace Yellows {
|
|
||||||
static const Color3 LightYellow{255, 255, 224};
|
|
||||||
static const Color3 LemonChiffon{255, 250, 205};
|
|
||||||
static const Color3 LightGoldenrodYellow{250, 250, 210};
|
|
||||||
static const Color3 PapayaWhip{255, 239, 213};
|
|
||||||
static const Color3 Moccasin{255, 228, 181};
|
|
||||||
static const Color3 PeachPuff{255, 218, 185};
|
|
||||||
static const Color3 PaleGoldenrod{238, 232, 170};
|
|
||||||
static const Color3 Khaki{240, 230, 140};
|
|
||||||
static const Color3 DarkKhaki{189, 183, 107};
|
|
||||||
}
|
|
||||||
namespace Greens {
|
|
||||||
static const Color3 LawnGreen{124, 252, 0};
|
|
||||||
static const Color3 Chartreuse{127, 255, 0};
|
|
||||||
static const Color3 LimeGreen{50, 205, 50};
|
|
||||||
static const Color3 ForestGreen{34, 139, 34};
|
|
||||||
static const Color3 DarkGreen{0, 100, 0};
|
|
||||||
static const Color3 GreenYellow{173, 255, 47};
|
|
||||||
static const Color3 YellowGreen{154, 205, 50};
|
|
||||||
static const Color3 SpringGreen{0, 255, 127};
|
|
||||||
static const Color3 MediumSpringGreen{0, 250, 154};
|
|
||||||
static const Color3 LightGreen{144, 238, 144};
|
|
||||||
static const Color3 PaleGreen{152, 251, 152};
|
|
||||||
static const Color3 DarkSeaGreen{143, 188, 143};
|
|
||||||
static const Color3 MediumSeaGreen{60, 179, 113};
|
|
||||||
static const Color3 SeaGreen{46, 139, 87};
|
|
||||||
static const Color3 DarkOliveGreen{85, 107, 47};
|
|
||||||
static const Color3 OliveDrab{107, 142, 35};
|
|
||||||
static const Color3 Lime{0, 255, 0};
|
|
||||||
static const Color3 Olive{128, 128, 0};
|
|
||||||
}
|
|
||||||
namespace Cyans {
|
|
||||||
static const Color3 LightCyan{224, 255, 255};
|
|
||||||
static const Color3 Cyan{0, 255, 255};
|
|
||||||
static const Color3 Aqua{0, 255, 255};
|
|
||||||
static const Color3 Aquamarine{127, 255, 212};
|
|
||||||
static const Color3 MediumAquamarine{102, 205, 170};
|
|
||||||
static const Color3 PaleTurquoise{175, 238, 238};
|
|
||||||
static const Color3 Turquoise{64, 224, 208};
|
|
||||||
static const Color3 MediumTurquoise{72, 209, 204};
|
|
||||||
static const Color3 DarkTurquoise{0, 206, 209};
|
|
||||||
static const Color3 LightSeaGreen{32, 178, 170};
|
|
||||||
static const Color3 CadetBlue{95, 158, 160};
|
|
||||||
static const Color3 DarkCyan{0, 139, 139};
|
|
||||||
static const Color3 Teal{0, 128, 128};
|
|
||||||
}
|
|
||||||
namespace Blues {
|
|
||||||
static const Color3 PowderBlue{176, 224, 230};
|
|
||||||
static const Color3 LightBlue{173, 216, 230};
|
|
||||||
static const Color3 LightSkyBlue{135, 206, 250};
|
|
||||||
static const Color3 SkyBlue{135, 206, 235};
|
|
||||||
static const Color3 DeepSkyBlue{0, 191, 255};
|
|
||||||
static const Color3 LightSteelBlue{176, 196, 222};
|
|
||||||
static const Color3 DodgerBlue{30, 144, 255};
|
|
||||||
static const Color3 CornflowerBlue{100, 149, 237};
|
|
||||||
static const Color3 SteelBlue{70, 130, 180};
|
|
||||||
static const Color3 RoyalBlue{65, 105, 225};
|
|
||||||
static const Color3 MediumBlue{0, 0, 205};
|
|
||||||
static const Color3 DarkBlue{0, 0, 139};
|
|
||||||
static const Color3 Navy{0, 0, 128};
|
|
||||||
static const Color3 MidnightBlue{25, 25, 112};
|
|
||||||
static const Color3 MediumSlateBlue{123, 104, 238};
|
|
||||||
static const Color3 SlateBlue{106, 90, 205};
|
|
||||||
static const Color3 DarkSlateBlue{72, 61, 139};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
namespace Purples {
|
|
||||||
static const Color3 Lavender{230, 230, 250};
|
|
||||||
static const Color3 Thistle{216, 191, 216};
|
|
||||||
static const Color3 Plum{221, 160, 221};
|
|
||||||
static const Color3 Violet{238, 160, 221};
|
|
||||||
static const Color3 Orchid{218, 112, 214};
|
|
||||||
static const Color3 Fuchsia{255, 0, 255};
|
|
||||||
static const Color3 Magenta{255, 0, 255};
|
|
||||||
static const Color3 MediumOrchid{186, 85, 211};
|
|
||||||
static const Color3 MediumPurple{147, 112, 219};
|
|
||||||
static const Color3 BlueViolet{138, 43, 226};
|
|
||||||
static const Color3 DarkViolet{148, 0, 211};
|
|
||||||
static const Color3 DarkOrchid{153, 50, 204};
|
|
||||||
static const Color3 DarkMagenta{139, 0, 128};
|
|
||||||
static const Color3 Purple{128, 0, 128};
|
|
||||||
static const Color3 Indigo{75, 0, 130};
|
|
||||||
}
|
|
||||||
namespace Pinks {
|
|
||||||
static const Color3 Pink{255, 129, 203};
|
|
||||||
static const Color3 LightPink{255, 182, 193};
|
|
||||||
static const Color3 HotPink{255, 105, 180};
|
|
||||||
static const Color3 DeepPink{255, 20, 147};
|
|
||||||
static const Color3 PaleVioletRed{219, 112, 147};
|
|
||||||
static const Color3 MediumVioletRed{199, 21, 133};
|
|
||||||
}
|
|
||||||
namespace Whites {
|
|
||||||
static const Color3 Snow{255, 250, 250};
|
|
||||||
static const Color3 Honeydew{240, 255, 240};
|
|
||||||
static const Color3 MintCream{245, 255, 250};
|
|
||||||
static const Color3 Azure{240, 255, 255};
|
|
||||||
static const Color3 AliceBlue{240, 248, 255};
|
|
||||||
static const Color3 GhostWhite{248, 248, 255};
|
|
||||||
static const Color3 WhiteSmoke{245, 245, 245};
|
|
||||||
static const Color3 SeaShell{255, 245, 238};
|
|
||||||
static const Color3 Beige{245, 245, 220};
|
|
||||||
static const Color3 OldLace{253, 245, 230};
|
|
||||||
static const Color3 FloralWhite{255, 250, 240};
|
|
||||||
static const Color3 Ivory{255, 255, 240};
|
|
||||||
static const Color3 AntiqueWhite{250, 240, 215};
|
|
||||||
static const Color3 Linen{250, 240, 230};
|
|
||||||
static const Color3 LavenderBlush{255, 240, 245};
|
|
||||||
static const Color3 MistyRose{255, 228, 255};
|
|
||||||
}
|
|
||||||
namespace Grays {
|
|
||||||
static const Color3 Gainsboro{220, 220, 220};
|
|
||||||
static const Color3 LightGray{211, 211, 211};
|
|
||||||
static const Color3 Silver{192, 192, 192};
|
|
||||||
static const Color3 DimGray{105, 105, 105};
|
|
||||||
static const Color3 LightSlateGray{119, 136, 153};
|
|
||||||
static const Color3 SlateGray{112, 128, 144};
|
|
||||||
static const Color3 DarkSlateGray{47, 79, 79};
|
|
||||||
}
|
|
||||||
namespace Browns {
|
|
||||||
static const Color3 CornSilk{255, 248, 220};
|
|
||||||
static const Color3 BlanchedAlmond{255, 235, 205};
|
|
||||||
static const Color3 Bisque{255, 228, 196};
|
|
||||||
static const Color3 NavajoWhite{255, 222, 173};
|
|
||||||
static const Color3 Wheat{254, 222, 179};
|
|
||||||
static const Color3 BurlyWood{222, 184, 135};
|
|
||||||
static const Color3 Tan{210, 180, 140};
|
|
||||||
static const Color3 RosyBrown{188, 143, 143};
|
|
||||||
static const Color3 SandyBrown{244, 164, 96};
|
|
||||||
static const Color3 GoldenRod{218, 165, 32};
|
|
||||||
static const Color3 Peru{205, 133, 63};
|
|
||||||
static const Color3 Chocolate{210, 105, 30};
|
|
||||||
static const Color3 SaddleBrown{139, 69, 19};
|
|
||||||
static const Color3 Sienna{160, 82, 45};
|
|
||||||
static const Color3 Brown{164, 42, 42};
|
|
||||||
static const Color3 Maroon{128, 0, 0};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
40
include/JGL/Font.h
Normal file
40
include/JGL/Font.h
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <J3ML/LinearAlgebra.h>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
|
/// Defines external C references to FreeType Data Structures
|
||||||
|
extern "C" typedef struct FT_FaceRec_* FT_Face;
|
||||||
|
extern "C" typedef struct FT_LibraryRec_* FT_Library;
|
||||||
|
|
||||||
|
namespace JGL
|
||||||
|
{
|
||||||
|
|
||||||
|
/// Initializes FreeType engine. Remember to call this during program initialization.
|
||||||
|
bool InitTextEngine();
|
||||||
|
|
||||||
|
/// A Font class implementation.
|
||||||
|
/// Wraps the font's FreeType asset handle and provides helper functions.
|
||||||
|
class Font {
|
||||||
|
public:
|
||||||
|
/// Default constructor does not initialize any members
|
||||||
|
Font() = default;
|
||||||
|
Font(const std::filesystem::path& path);
|
||||||
|
/// Destructor handles freeing of the underlying asset handle.
|
||||||
|
~Font();
|
||||||
|
static Font LoadTTF(const std::filesystem::path& filepath);
|
||||||
|
static std::vector<Font> GetLoadedFonts();
|
||||||
|
/// Returns the bounding-box the given string would occupy at the given point-size, assuming normal (1) scaling.
|
||||||
|
/// @param text The string to measure.
|
||||||
|
/// @param ptSize The font size at which to measure.
|
||||||
|
/// @return The size-in-pixels that would contain the entire text.
|
||||||
|
Vector2 MeasureString(const std::string& text, unsigned int ptSize);
|
||||||
|
public:
|
||||||
|
int index = 0;
|
||||||
|
FT_Face face;
|
||||||
|
};
|
||||||
|
}
|
@@ -1,53 +1,67 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
|
|
||||||
|
|
||||||
|
/// TODO: FontCache mechanism works amazing, but makes no fucking sense
|
||||||
|
/// Let's document and reorganize it to be a little nicer on the mental :)
|
||||||
|
|
||||||
namespace JGL {
|
namespace JGL {
|
||||||
class CachedGlyph;
|
class CachedGlyph;
|
||||||
class CachedFont;
|
class CachedFont;
|
||||||
class FontCache;
|
class FontCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Represents a single font-character "glyph", that has been cached in-memory for fast retrieval.
|
||||||
class JGL::CachedGlyph {
|
class JGL::CachedGlyph {
|
||||||
private:
|
private:
|
||||||
GLuint texture = 0;
|
|
||||||
char character;
|
char character;
|
||||||
|
std::array<GLfloat, 12> texcoords;
|
||||||
public:
|
public:
|
||||||
int x2offset = 0, y2offset = 0, w = 0, h = 0;
|
int x2offset = 0, y2offset = 0, w = 0, h = 0;
|
||||||
float advanceX = 0, advanceY = 0;
|
float advanceX = 0, advanceY = 0;
|
||||||
|
|
||||||
//CachedGlyph(GLuint texture_id, char c);
|
//CachedGlyph(GLuint texture_id, char c);
|
||||||
CachedGlyph(GLuint texture_id, char c, float x2o, float y2o, float w, float h, float advX, float advY);
|
CachedGlyph(char c, std::array<GLfloat, 12> texcoords, float x2o, float y2o, float w, float h, float advX, float advY);
|
||||||
char getCharacter();
|
char getCharacter();
|
||||||
const GLuint* getTexture();
|
const std::array<GLfloat, 12> getTexCoords() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Represents a Font object as it exists in the font-cache.
|
||||||
class JGL::CachedFont {
|
class JGL::CachedFont {
|
||||||
private:
|
private:
|
||||||
std::vector<CachedGlyph*> glyphs{};
|
std::map<char, CachedGlyph*> glyphs;
|
||||||
|
GLuint texture = 0;
|
||||||
|
GLsizei texture_width = 0, texture_height = 0;
|
||||||
unsigned int font_size = 0;
|
unsigned int font_size = 0;
|
||||||
unsigned int font_index = 0;
|
unsigned int font_index = 0;
|
||||||
public:
|
public:
|
||||||
void appendGlyph(CachedGlyph* glyph);
|
void appendGlyph(CachedGlyph* glyph);
|
||||||
void eraseGlyph(CachedGlyph* glyph);
|
|
||||||
void eraseGlyph(char c);
|
|
||||||
void eraseGlyph(GLuint texture_id);
|
|
||||||
unsigned int getFontSize();
|
unsigned int getFontSize();
|
||||||
unsigned int getFontIndex();
|
unsigned int getFontIndex();
|
||||||
CachedGlyph* getGlyph(char c);
|
CachedGlyph* getGlyph(char c);
|
||||||
std::vector<CachedGlyph*>* getGlyphs();
|
std::map<char, CachedGlyph*> getGlyphs();
|
||||||
CachedFont(unsigned int font_size, unsigned int font_index);
|
const GLuint* getTexture();
|
||||||
|
GLsizei getTextureWidth() const;
|
||||||
|
GLsizei getTextureHeight() const;
|
||||||
|
CachedFont(GLuint texture_id, GLsizei texture_width, GLsizei texture_height, unsigned int font_size, unsigned int font_index);
|
||||||
};
|
};
|
||||||
|
|
||||||
class JGL::FontCache {
|
class JGL::FontCache {
|
||||||
private:
|
private:
|
||||||
std::vector<CachedFont*> cachedFonts = {};
|
std::vector<CachedFont*> cachedFonts = {};
|
||||||
public:
|
public:
|
||||||
std::vector<CachedFont*>* getFonts();
|
std::vector<CachedFont*> getFonts();
|
||||||
CachedFont* getFont(unsigned int font_size, unsigned int font_index);
|
CachedFont* getFont(unsigned int font_size, unsigned int font_index);
|
||||||
void appendFont(CachedFont* font);
|
void appendFont(CachedFont* font);
|
||||||
void newFont(unsigned int font_size, unsigned int font_index);
|
void newFont(GLuint texture_id, GLsizei texture_width, GLsizei texture_height, unsigned int font_size, unsigned int font_index);
|
||||||
void eraseFont(CachedFont* font);
|
void eraseFont(CachedFont* font);
|
||||||
void purgeCache();
|
void purgeCache();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace JGL {
|
||||||
|
inline FontCache fontCache;
|
||||||
|
}
|
||||||
|
@@ -1,12 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <J3ML/J3ML.h>
|
|
||||||
|
|
||||||
namespace JGL {
|
|
||||||
enum class Gradient : u8 {
|
|
||||||
Vertical = 0,
|
|
||||||
Horizontal = 1,
|
|
||||||
DiagonalTopLeft = 2,
|
|
||||||
DiagonalBottomLeft = 3
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,13 +1,26 @@
|
|||||||
//
|
/// Josh's Graphics Library
|
||||||
// Created by dawsh on 1/17/24.
|
/// A C++20 Library for rendering 2D and 3D primitives in an OpenGL context.
|
||||||
//
|
/// Developed and Maintained by Josh O'Leary @ Redacted Software.
|
||||||
|
/// Special Thanks to William Tomasine II and Maxine Hayes.
|
||||||
|
/// (c) 2024 Redacted Software
|
||||||
|
/// This work is dedicated to the public domain.
|
||||||
|
|
||||||
|
/// @file JGL.h
|
||||||
|
/// @desc All JGL usable functions are defined here. This is the public API.
|
||||||
|
/// @edit 2024-07-16
|
||||||
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <JGL/Color4.h>
|
#include <Color3.hpp>
|
||||||
#include <JGL/Gradient.h>
|
#include <Color4.hpp>
|
||||||
|
#include <Colors.hpp>
|
||||||
|
#include <JGL/Texture.h>
|
||||||
|
#include <JGL/enums.h>
|
||||||
#include <JGL/FontCache.h>
|
#include <JGL/FontCache.h>
|
||||||
|
#include <JGL/Font.h>
|
||||||
#include <J3ML/LinearAlgebra.h>
|
#include <J3ML/LinearAlgebra.h>
|
||||||
#include <J3ML/LinearAlgebra/Vector2.h>
|
#include <J3ML/LinearAlgebra/Vector2.h>
|
||||||
#include <J3ML/LinearAlgebra/Vector3.h>
|
#include <J3ML/LinearAlgebra/Vector3.h>
|
||||||
@@ -15,28 +28,21 @@
|
|||||||
#include <J3ML/Geometry/Capsule.h>
|
#include <J3ML/Geometry/Capsule.h>
|
||||||
#include <J3ML/Geometry/TriangleMesh.h>
|
#include <J3ML/Geometry/TriangleMesh.h>
|
||||||
|
|
||||||
// OpenGL Wrapper for rendering 2D graphics primitives in both a 2D and 3D context
|
|
||||||
|
/// OpenGL Wrapper for rendering 2D graphics primitives in both a 2D and 3D context
|
||||||
namespace JGL {
|
namespace JGL {
|
||||||
|
|
||||||
using J3ML::LinearAlgebra::Vector2;
|
using namespace J3ML::LinearAlgebra;
|
||||||
using J3ML::LinearAlgebra::Vector3;
|
using namespace J3ML::Geometry;
|
||||||
using J3ML::LinearAlgebra::Matrix3x3;
|
|
||||||
using J3ML::LinearAlgebra::Matrix4x4;
|
|
||||||
using J3ML::LinearAlgebra::AxisAngle;
|
|
||||||
using J3ML::LinearAlgebra::Quaternion;
|
|
||||||
|
|
||||||
using J3ML::Geometry::Sphere;
|
|
||||||
using J3ML::Geometry::OBB;
|
|
||||||
using J3ML::Geometry::Capsule;
|
|
||||||
using J3ML::Geometry::TriangleMesh;
|
|
||||||
using J3ML::Geometry::Plane;
|
|
||||||
|
|
||||||
|
/// TODO: Implement HSV and other color representation conversions
|
||||||
struct HSV {
|
struct HSV {
|
||||||
float hue;
|
float hue;
|
||||||
float saturation;
|
float saturation;
|
||||||
float value;
|
float value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// TODO: Migrate to using J3ML's definition once finished (hint hint)
|
||||||
struct Triangle2D
|
struct Triangle2D
|
||||||
{
|
{
|
||||||
Vector2 A;
|
Vector2 A;
|
||||||
@@ -44,19 +50,14 @@ namespace JGL {
|
|||||||
Vector2 C;
|
Vector2 C;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Triangle3D
|
void Update(const Vector2& window_size);
|
||||||
{
|
void PurgeFontCache();
|
||||||
Vector3 A;
|
|
||||||
Vector3 B;
|
|
||||||
Vector3 C;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool Update(const Vector2& window_size);
|
// TODO: Implement
|
||||||
bool InitTextEngine();
|
void SetActiveFont(const Font& font);
|
||||||
int LoadFont(const std::string& font_path);
|
|
||||||
|
// TODO: Overrides specifically for Color3 are not **strictly** necessary, Color3 and Color4 should implicitly convert back and forth.
|
||||||
|
|
||||||
void UnloadFont(int font_index);
|
|
||||||
// TODO: implement correct coloring
|
|
||||||
|
|
||||||
/// Drawing functions for primitive 2D Shapes.
|
/// Drawing functions for primitive 2D Shapes.
|
||||||
/// Each function is overloaded with Color3 and Color4 for optional transparency.
|
/// Each function is overloaded with Color3 and Color4 for optional transparency.
|
||||||
@@ -72,12 +73,12 @@ namespace JGL {
|
|||||||
void End();
|
void End();
|
||||||
|
|
||||||
/// Plots a single pixel on the screen.
|
/// Plots a single pixel on the screen.
|
||||||
/// @param color A 3-or-4 channel color value. @see classes Color3, Color4
|
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
|
||||||
/// @param coordinates The pixel-point on-screen at which to plot the pixel.
|
/// @param coordinates The pixel-point on-screen at which to plot the pixel.
|
||||||
void DrawPixel(const Color3& color, const Vector2& coordinates);
|
void DrawPoint(const Color3& color, const Vector2& coordinates, float radius = 1.f);
|
||||||
void DrawPixel(const Color3& color, float x, float y);
|
void DrawPoint(const Color3& color, float x, float y, float radius = 1.f);
|
||||||
void DrawPixel(const Color4& color, const Vector2& coordinates);
|
void DrawPoint(const Color4& color, const Vector2& coordinates, float radius = 1.f);
|
||||||
void DrawPixel(const Color4& color, float x, float y);
|
void DrawPoint(const Color4& color, float x, float y, float radius = 1.f);
|
||||||
|
|
||||||
/// Plots a line (segment) on the screen.
|
/// Plots a line (segment) on the screen.
|
||||||
/// @param color A 3-or-4 channel color value. @see classes Color3, Color4.
|
/// @param color A 3-or-4 channel color value. @see classes Color3, Color4.
|
||||||
@@ -85,7 +86,7 @@ namespace JGL {
|
|||||||
/// @param B The end point of the line segment.
|
/// @param B The end point of the line segment.
|
||||||
/// @param thickness The width at which to render the line.
|
/// @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, 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 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, 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);
|
void DrawLine(const Color4& color, float x1, float y1, float x2, float y2, float thickness = 1);
|
||||||
|
|
||||||
@@ -99,6 +100,38 @@ namespace JGL {
|
|||||||
void OutlineRect(const Color4& color, const Vector2& pos, const Vector2& size, float thickness = 1);
|
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);
|
void OutlineRect(const Color3& color, const Vector2& pos, const Vector2& size, float thickness = 1);
|
||||||
|
|
||||||
|
/// Draws a sprite to the screen by passing a GLuint that represents a handle to a loaded texture.
|
||||||
|
/// @param texture
|
||||||
|
/// @param position
|
||||||
|
/// @param origin The center point around which the image should have all transformations applied to it.
|
||||||
|
/// @param scale The scale transformation for the image. X and Y axis are independently-scalable.
|
||||||
|
/// @param color A 32-bit RGBA value represented as four unsigned 8-bit integers.
|
||||||
|
/// @param inversion
|
||||||
|
/// @see class Texture
|
||||||
|
void DrawSprite(const Texture& texture,
|
||||||
|
const Vector2& position,
|
||||||
|
const Vector2& origin = Vector2(0,0),
|
||||||
|
const Vector2& scale = Vector2(1,1),
|
||||||
|
const Color4& color = Colors::White,
|
||||||
|
Inversion inversion = Inversion::None);
|
||||||
|
void DrawSprite(const Texture& texture,
|
||||||
|
float positionX, float positionY,
|
||||||
|
float originX = 0, float originY = 0,
|
||||||
|
float scaleX = 1, float scaleY = 1,
|
||||||
|
const Color4& color = Colors::White,
|
||||||
|
Inversion inversion = Inversion::None);
|
||||||
|
|
||||||
|
|
||||||
|
/// Draws a non axis-aligned fill rect to the screen.
|
||||||
|
/// The order of the vertices must be such that if you were to connect them you'd never go diagonally across the quad.
|
||||||
|
void FillQuad(const Color4& color, const Vector2& v1, const Vector2& v2, const Vector2& v3, const Vector2& v4);
|
||||||
|
void FillQuad(const Color3& color, const Vector2& v1, const Vector2& v2, const Vector2& v3, const Vector2& v4);
|
||||||
|
|
||||||
|
/// Draws a non axis-aligned outline rect to the screen.
|
||||||
|
/// The order of the vertices must be such that if you were to connect them you'd never go diagonally across the quad.
|
||||||
|
void OutlineQuad(const Color4& color, const Vector2& v1, const Vector2& v2, const Vector2& v3, const Vector2& v4, float thickness = 1);
|
||||||
|
void OutlineQuad(const Color3& color, const Vector2& v1, const Vector2& v2, const Vector2& v3, const Vector2& v4, float thickness = 1);
|
||||||
|
|
||||||
/// Draws a filled rectangle on the screen.
|
/// Draws a filled rectangle on the screen.
|
||||||
void FillRect(const Color4& color, const Vector2& pos, const Vector2& size);
|
void FillRect(const Color4& color, const Vector2& pos, const Vector2& size);
|
||||||
void FillRect(const Color3& color, const Vector2& pos, const Vector2& size);
|
void FillRect(const Color3& color, const Vector2& pos, const Vector2& size);
|
||||||
@@ -108,7 +141,7 @@ namespace JGL {
|
|||||||
void FillGradientRect(const Color3& color1, const Color3& 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.
|
/// 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 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);
|
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.
|
/// Draws an outline of a circle on the screen.
|
||||||
@@ -120,22 +153,37 @@ namespace JGL {
|
|||||||
void FillCircle(const Color3& 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.
|
/// Draws an outline of a triangle on the screen.
|
||||||
|
/// @param color
|
||||||
|
/// @param tri
|
||||||
|
/// @param thickness
|
||||||
void OutlineTriangle(const Color4& color, const Triangle2D& tri, float thickness = 1);
|
void OutlineTriangle(const Color4& color, const Triangle2D& tri, float thickness = 1);
|
||||||
void OutlineTriangle(const Color3& color, const Triangle2D& tri, float thickness = 1);
|
void OutlineTriangle(const Color3& color, const Triangle2D& tri, float thickness = 1);
|
||||||
// TODO: Implement an overload that simply takes 3 Vector3's
|
void OutlineTriangle(const Color4& color,
|
||||||
|
const Vector2& triA, const Vector2& triB, const Vector2& triC,
|
||||||
|
float thickness = 1);
|
||||||
|
void OutlineTriangle(const Color3& color,
|
||||||
|
const Vector2& triA, const Vector2& triB, const Vector2& triC,
|
||||||
|
float thickness = 1);
|
||||||
|
// TODO: Take more Focalin
|
||||||
|
|
||||||
/// Draws a filled triangle on the screen.
|
/// Draws a filled triangle on the screen.
|
||||||
void FillTriangle(const Color4& color, const Triangle2D &tri);
|
void FillTriangle(const Color4& color, const Triangle2D& tri);
|
||||||
|
void FIllTriangle(const Color4& color, const Vector2& triA, const Vector2& triB, const Vector2& triC);
|
||||||
void FillTriangle(const Color3& color, const Triangle2D& tri);
|
void FillTriangle(const Color3& color, const Triangle2D& tri);
|
||||||
|
|
||||||
|
/// Draws a triangle where each corner is defined by a given color, Smoothly transitioning between them.
|
||||||
|
void FillGradientTriangle(const Color4& a_color, const Color4& b_color, const Color4& c_color, const Triangle2D& tri);
|
||||||
|
void FillGradientTriangle(const Color3& a_color, const Color3& b_color, const Color3& c_color, const Triangle2D& tri);
|
||||||
// TODO: Implement an overload that simply takes 3 Vector3's
|
// TODO: Implement an overload that simply takes 3 Vector3's
|
||||||
|
|
||||||
|
|
||||||
/// Draws a text string on the screen with a given point-size and font.
|
/// 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);
|
void DrawString(const Color4& color, const std::string& text, float x, float y, float scale, u32 size, const Font& font);
|
||||||
|
void DrawString(const Color3& color, const std::string& text, float x, float y, float scale, u32 size, const Font& font);
|
||||||
|
|
||||||
// TODO: Implement the following:
|
// TODO: Implement the following:
|
||||||
void FillTexturedTriangle();
|
void FillTexturedTriangle();
|
||||||
void FillTexturedPolygon();
|
void FillTexturedPolygon();
|
||||||
void DrawSprite();
|
|
||||||
void DrawPartialSprite();
|
void DrawPartialSprite();
|
||||||
void DrawCubicBezierCurve();
|
void DrawCubicBezierCurve();
|
||||||
void OutlinePolygon (const Color4& color, std::vector<Vector2> points);
|
void OutlinePolygon (const Color4& color, std::vector<Vector2> points);
|
||||||
@@ -143,6 +191,7 @@ namespace JGL {
|
|||||||
void OutlineRoundedRect(const Color4& color, const Vector2& pos, const Vector2& size, float radius = 5, float thickness = 1);
|
void OutlineRoundedRect(const Color4& color, const Vector2& pos, const Vector2& size, float radius = 5, float thickness = 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Drawing functions for primitive 3D Shapes.
|
||||||
namespace J3D {
|
namespace J3D {
|
||||||
void Begin();
|
void Begin();
|
||||||
void End();
|
void End();
|
||||||
@@ -157,7 +206,7 @@ namespace JGL {
|
|||||||
void WireframeCapsule(const Color3& color, const Capsule& cap, float thickness = 1);
|
void WireframeCapsule(const Color3& color, const Capsule& cap, float thickness = 1);
|
||||||
void FillTriangleMesh(const Color3& color, const TriangleMesh& mesh);
|
void FillTriangleMesh(const Color3& color, const TriangleMesh& mesh);
|
||||||
void WireframeTriangleMesh(const Color3& color, const TriangleMesh& mesh, float thickness = 1);
|
void WireframeTriangleMesh(const Color3& color, const TriangleMesh& mesh, float thickness = 1);
|
||||||
void DrawString(const Color3& color, const std::string& text, const Vector3& pos, const Vector3& angle, float scale, u32 size, unsigned int font_index);
|
void DrawString(const Color4& color, const std::string& text, const Vector3& pos, const Vector3& angle, float scale, u32 size, const Font& font);
|
||||||
|
|
||||||
void DrawMatrixGizmo (const Matrix3x3&, const Vector3&);
|
void DrawMatrixGizmo (const Matrix3x3&, const Vector3&);
|
||||||
void DrawMatrixGizmo (const Matrix4x4&);
|
void DrawMatrixGizmo (const Matrix4x4&);
|
||||||
|
52
include/JGL/Texture.h
Normal file
52
include/JGL/Texture.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <ReTexture/Texture.h>
|
||||||
|
#include <J3ML/LinearAlgebra.h>
|
||||||
|
#include <Color3.hpp>
|
||||||
|
#include <Color4.hpp>
|
||||||
|
#include <glad/glad.h>
|
||||||
|
|
||||||
|
namespace JGL {
|
||||||
|
using namespace ReTexture;
|
||||||
|
enum class TextureFilteringMode : 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 TextureWrappingMode : u8 {
|
||||||
|
REPEAT = 0,
|
||||||
|
MIRRORED_REPEAT = 1,
|
||||||
|
CLAMP_TO_EDGE = 2,
|
||||||
|
CLAMP_TO_BORDER = 3 //Effectively the same as clamp_to_edge
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Represents texture data loaded on the GPU. Contains a handle that can be passed to OpenGL draw calls.
|
||||||
|
class Texture {
|
||||||
|
private:
|
||||||
|
GLuint texture_handle = 0;
|
||||||
|
Vector2 texture_size = {0, 0};
|
||||||
|
ReTexture::TextureFlag texture_flags;
|
||||||
|
ReTexture::TextureFormat texture_format;
|
||||||
|
TextureFilteringMode texture_filtering_mode;
|
||||||
|
TextureWrappingMode texture_wrapping_mode;
|
||||||
|
void load(SoftwareTexture* software_texture, const Vector2& size, const TextureFormat& format, TextureFilteringMode filtering_mode, TextureWrappingMode wrapping_mode);
|
||||||
|
public:
|
||||||
|
explicit Texture(const std::string& file, TextureFilteringMode filtering_mode = TextureFilteringMode::BILINEAR, TextureWrappingMode wrapping_mode = TextureWrappingMode::CLAMP_TO_EDGE);
|
||||||
|
Texture(const std::string& file, const TextureFlag& flags, TextureFilteringMode filtering_mode = TextureFilteringMode::BILINEAR, TextureWrappingMode wrapping_mode = TextureWrappingMode::CLAMP_TO_EDGE);
|
||||||
|
Texture(SoftwareTexture* software_texture, TextureFilteringMode filtering_mode, TextureWrappingMode wrapping_mode);
|
||||||
|
public:
|
||||||
|
[[nodiscard]] GLuint GetGLTextureHandle() const;
|
||||||
|
[[nodiscard]] Vector2 GetDimensions() const;
|
||||||
|
[[nodiscard]] TextureFilteringMode GetFilteringMode() const;
|
||||||
|
[[nodiscard]] TextureWrappingMode GetWrappingMode() const;
|
||||||
|
[[nodiscard]] TextureFlag GetFlags() const;
|
||||||
|
[[nodiscard]] TextureFormat GetFormat() const;
|
||||||
|
[[nodiscard]] std::vector<Color4> GetPixelData() const;
|
||||||
|
SoftwareTexture GetSoftwareTexture() const;
|
||||||
|
void Erase();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
33
include/JGL/enums.h
Normal file
33
include/JGL/enums.h
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace JGL {
|
||||||
|
enum class Inversion : u8 {
|
||||||
|
None = 0,
|
||||||
|
Vertical = 1,
|
||||||
|
Horizontal = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
inline Inversion operator|(Inversion a, Inversion b) {
|
||||||
|
return static_cast<Inversion>(static_cast<int>(a) | static_cast<int>(b));
|
||||||
|
}
|
||||||
|
inline bool operator&(Inversion a, Inversion b) {
|
||||||
|
return (u8)a & (u8)b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace JGL {
|
||||||
|
enum class Gradient : u8 {
|
||||||
|
Vertical = 0,
|
||||||
|
Horizontal = 1,
|
||||||
|
DiagonalTopLeft = 2,
|
||||||
|
DiagonalBottomLeft = 4
|
||||||
|
};
|
||||||
|
|
||||||
|
inline Gradient operator|(Gradient a, Gradient b) {
|
||||||
|
return static_cast<Gradient>(static_cast<int>(a) | static_cast<int>(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator&(Gradient a, Gradient b) {
|
||||||
|
return (u8)a & (u8)b;
|
||||||
|
}
|
||||||
|
}
|
71
main.cpp
71
main.cpp
@@ -1,12 +1,18 @@
|
|||||||
#include <glad/glad.h>
|
|
||||||
#include <JGL/JGL.h>
|
#include <JGL/JGL.h>
|
||||||
#include <rewindow/types/window.h>
|
#include <rewindow/types/window.h>
|
||||||
#include <JGL/Colors.h>
|
#include <Colors.hpp>
|
||||||
#include <J3ML/LinearAlgebra/Vector2.h>
|
#include <J3ML/LinearAlgebra/Vector2.h>
|
||||||
|
#include <JGL/Font.h>
|
||||||
|
#include <jlog/jlog.hpp>
|
||||||
|
#include <ReTexture/Texture.h>
|
||||||
|
|
||||||
using J3ML::LinearAlgebra::Vector2;
|
using J3ML::LinearAlgebra::Vector2;
|
||||||
using namespace JGL;
|
using namespace JGL;
|
||||||
|
|
||||||
|
Texture* image;
|
||||||
|
Texture* reloaded_image;
|
||||||
|
|
||||||
//The Re3D style base projection.
|
//The Re3D style base projection.
|
||||||
std::vector<GLfloat> perspective(float fov, float aspect, float nearPlane, float farPlane) {
|
std::vector<GLfloat> perspective(float fov, float aspect, float nearPlane, float farPlane) {
|
||||||
std::vector<float> result(16);
|
std::vector<float> result(16);
|
||||||
@@ -24,13 +30,13 @@ public:
|
|||||||
Vector3 position = {0,0,0};
|
Vector3 position = {0,0,0};
|
||||||
Vector3 angle = {0,0,0};
|
Vector3 angle = {0,0,0};
|
||||||
|
|
||||||
std::array<GLfloat, 16> lookAt(const Vector3& eye, const Vector3& center, const Vector3& up) {
|
std::vector<GLfloat> lookAt(const Vector3& eye, const Vector3& center, const Vector3& up) {
|
||||||
Vector3 f = Vector3::Normalized((center - eye));
|
Vector3 f = Vector3::Normalized((center - eye));
|
||||||
Vector3 upN = Vector3::Normalized(up);
|
Vector3 upN = Vector3::Normalized(up);
|
||||||
Vector3 s = Vector3::Normalized(f.Cross(upN));
|
Vector3 s = Vector3::Normalized(f.Cross(upN));
|
||||||
Vector3 u = Vector3::Normalized(s.Cross(f));
|
Vector3 u = Vector3::Normalized(s.Cross(f));
|
||||||
|
|
||||||
std::array<GLfloat, 16> result = {
|
std::vector<GLfloat> result = {
|
||||||
s.x, u.x, -f.x, 0.0f,
|
s.x, u.x, -f.x, 0.0f,
|
||||||
s.y, u.y, -f.y, 0.0f,
|
s.y, u.y, -f.y, 0.0f,
|
||||||
s.z, u.z, -f.z, 0.0f,
|
s.z, u.z, -f.z, 0.0f,
|
||||||
@@ -57,8 +63,8 @@ struct point {
|
|||||||
GLfloat t;
|
GLfloat t;
|
||||||
};
|
};
|
||||||
|
|
||||||
int FreeSans;
|
JGL::Font FreeSans;
|
||||||
int Jupiteroid;
|
JGL::Font Jupiteroid;
|
||||||
|
|
||||||
class JGLDemoWindow : public ReWindow::RWindow
|
class JGLDemoWindow : public ReWindow::RWindow
|
||||||
{
|
{
|
||||||
@@ -69,11 +75,11 @@ public:
|
|||||||
auto aspect = (float) window_size[0] / (float) window_size[1];
|
auto aspect = (float) window_size[0] / (float) window_size[1];
|
||||||
|
|
||||||
gladLoadGL();
|
gladLoadGL();
|
||||||
|
JGL::InitTextEngine();
|
||||||
JGL::Update(getSize());
|
JGL::Update(getSize());
|
||||||
FreeSans = JGL::LoadFont("assets/fonts/FreeSans.ttf");
|
FreeSans = JGL::Font("assets/fonts/FreeSans.ttf");
|
||||||
Jupiteroid = JGL::LoadFont("assets/fonts/Jupiteroid.ttf");
|
Jupiteroid = JGL::Font("assets/fonts/Jupiteroid.ttf");
|
||||||
|
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
glMatrixMode(GL_PROJECTION);
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
glMultMatrixf(perspective(75, aspect, 0.001, 100).data());
|
glMultMatrixf(perspective(75, aspect, 0.001, 100).data());
|
||||||
@@ -84,10 +90,16 @@ public:
|
|||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
glDepthFunc(GL_LESS);
|
glDepthFunc(GL_LESS);
|
||||||
glDepthMask(GL_TRUE);
|
glDepthMask(GL_TRUE);
|
||||||
|
image = new Texture("assets/sprites/Re3D.png", TextureFilteringMode::BILINEAR);
|
||||||
|
|
||||||
|
auto* software_texture = new SoftwareTexture(image->GetSoftwareTexture());
|
||||||
|
reloaded_image = new Texture(software_texture, TextureFilteringMode::BILINEAR, TextureWrappingMode::CLAMP_TO_EDGE);
|
||||||
|
delete software_texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 textAngle = {0,0,0};
|
Vector3 textAngle = {0,0,0};
|
||||||
void display() {
|
void display() {
|
||||||
|
JGL::Update(getSize());
|
||||||
textAngle.y += 2.0f;
|
textAngle.y += 2.0f;
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
@@ -96,40 +108,47 @@ public:
|
|||||||
camera->render();
|
camera->render();
|
||||||
|
|
||||||
///All 3D elements of the scene and JGL elements *must* be rendered before the 2d stuff.
|
///All 3D elements of the scene and JGL elements *must* be rendered before the 2d stuff.
|
||||||
|
|
||||||
J3D::Begin();
|
J3D::Begin();
|
||||||
J3D::DrawLine(JGL::Colors::Red, {-0.33,-0.125,1}, {-1,-0.125,1});
|
J3D::DrawLine(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::DrawLine(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(Colors::Red, "JGL Sample Text", {-0.33, -0.1, 1.0f},textAngle, 1.f, 32, FreeSans);
|
||||||
J3D::End();
|
J3D::End();
|
||||||
|
|
||||||
J2D::Begin();
|
J2D::Begin();
|
||||||
|
J2D::FillQuad(Color4(Colors::Red), {500, 52}, {500, 152}, {600, 152}, {600, 52});
|
||||||
J2D::FillRect(Colors::Blue, {0,52}, {100,100});
|
J2D::FillRect(Colors::Blue, {0,52}, {100,100});
|
||||||
J2D::FillRect(Color4::FromColor3(Colors::Pinks::HotPink), {68, 120}, {32, 32});
|
J2D::DrawSprite(*reloaded_image, {200, 252}, {0.5, 0.5}, {2, 1});
|
||||||
|
J2D::FillRect(Colors::Pinks::HotPink, {68, 120}, {32, 32});
|
||||||
J2D::FillGradientRect(Colors::Red, Colors::Blue, Gradient::DiagonalBottomLeft, {100,52}, {100,100});
|
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(Colors::Red, {200, 52}, {100, 100}, 8, 8);
|
||||||
J2D::FillRoundedRect(JGL::Colors::Purples::BlueViolet, {300, 52}, {100, 100}, 8, 4);
|
J2D::FillRoundedRect(Colors::Purples::BlueViolet, {300, 52}, {100, 100}, 8, 4);
|
||||||
|
|
||||||
J2D::FillCircle(JGL::Colors::White, {52, 204}, 50, 24);
|
J2D::FillCircle(Colors::White, {52, 204}, 50, 24);
|
||||||
J2D::OutlineCircle(JGL::Colors::White, {153, 204}, 50, 24);
|
J2D::OutlineCircle(Colors::White, {153, 204}, 50, 24);
|
||||||
|
|
||||||
J2D::FillTriangle(Colors::Red, {{0, 275}, {0, 375}, {100, 375}});
|
//J2D::FillTriangle(Colors::Red, {{0, 275}, {0, 375}, {100, 375}});
|
||||||
|
J2D::FillGradientTriangle(Color4(Colors::Red), Color4(Colors::Green), Color4(Colors::Blue), {{0, 275}, {0, 375}, {100, 375}});
|
||||||
J2D::OutlineTriangle(Colors::Blue, {{100, 275}, {0, 275}, {100, 375}});
|
J2D::OutlineTriangle(Colors::Blue, {{100, 275}, {0, 275}, {100, 375}});
|
||||||
J2D::DrawGradientLine(JGL::Colors::Red, JGL::Colors::Blue, {105, 375}, {200, 275}, 2);
|
J2D::DrawGradientLine(Colors::Red, Colors::Blue, {105, 375}, {200, 275}, 2);
|
||||||
|
auto result = Jupiteroid.MeasureString("Jupiteroid Font", 16);
|
||||||
|
|
||||||
J2D::DrawString(JGL::Colors::Green, "Jupteroid Font", 0.f, 16, 1.f, 16, Jupiteroid);
|
J2D::FillRect(Colors::Gray, {0, 0}, result);
|
||||||
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(Colors::Green, "Jupteroid Font", 0.f, 0, 1.f, 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::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::End();
|
J2D::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnRefresh(float elapsed) override {
|
void OnRefresh(float elapsed) override {
|
||||||
display();
|
display();
|
||||||
if (glGetError() != GL_NO_ERROR)
|
int glError = glGetError();
|
||||||
exit(1);
|
if (glError != GL_NO_ERROR)
|
||||||
|
std::cout << glError << std::endl;
|
||||||
glSwapBuffers();
|
glSwapBuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OnResizeRequest(const ReWindow::WindowResizeRequestEvent& e) override {return true;}
|
bool OnResizeRequest(const ReWindow::WindowResizeRequestEvent& e) override {/* glViewport(0, 0, e.Size.x, e.Size.y); std::cout << e.Size.x;*/ return true;}
|
||||||
JGLDemoWindow() : ReWindow::RWindow() {}
|
JGLDemoWindow() : ReWindow::RWindow() {}
|
||||||
JGLDemoWindow(const std::string& title, int width, int height) : ReWindow::RWindow(title, width, height){}
|
JGLDemoWindow(const std::string& title, int width, int height) : ReWindow::RWindow(title, width, height){}
|
||||||
};
|
};
|
||||||
@@ -139,7 +158,7 @@ int main(int argc, char** argv) {
|
|||||||
window->setRenderer(RenderingAPI::OPENGL);
|
window->setRenderer(RenderingAPI::OPENGL);
|
||||||
window->Open();
|
window->Open();
|
||||||
window->initGL();
|
window->initGL();
|
||||||
window->setResizable(false);
|
window->setResizable(true);
|
||||||
|
|
||||||
while (window->isAlive()) {
|
while (window->isAlive()) {
|
||||||
window->pollEvents();
|
window->pollEvents();
|
||||||
|
1
reci/scripts/builddeps.reci
Normal file
1
reci/scripts/builddeps.reci
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Main:new("Install build dependencies", "apt-get install -yq libgl1-mesa-dev libfreetype-dev")
|
@@ -6,12 +6,11 @@ char CachedGlyph::getCharacter() {
|
|||||||
return character;
|
return character;
|
||||||
}
|
}
|
||||||
|
|
||||||
const GLuint* CachedGlyph::getTexture() {
|
const std::array<GLfloat, 12> CachedGlyph::getTexCoords() const {
|
||||||
return &texture;
|
return texcoords;
|
||||||
}
|
}
|
||||||
|
|
||||||
CachedGlyph::CachedGlyph(GLuint texture_id, char c, float x2offset, float y2offset, float w, float h, float advanceX, float advanceY) {
|
CachedGlyph::CachedGlyph(char c, std::array<GLfloat, 12> texcoords, float x2offset, float y2offset, float w, float h, float advanceX, float advanceY) {
|
||||||
texture = texture_id;
|
|
||||||
character = c;
|
character = c;
|
||||||
this->x2offset = x2offset;
|
this->x2offset = x2offset;
|
||||||
this->y2offset = y2offset;
|
this->y2offset = y2offset;
|
||||||
@@ -19,10 +18,14 @@ CachedGlyph::CachedGlyph(GLuint texture_id, char c, float x2offset, float y2offs
|
|||||||
this->h = h;
|
this->h = h;
|
||||||
this->advanceX = advanceX;
|
this->advanceX = advanceX;
|
||||||
this->advanceY = advanceY;
|
this->advanceY = advanceY;
|
||||||
|
this->texcoords = texcoords;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO
|
||||||
|
//Because most things shown would be english characters. We can cut down on the iteration time significantly
|
||||||
|
//by putting each english character at the beginning of the list in order of how often they usually occur in text.
|
||||||
void JGL::CachedFont::appendGlyph(JGL::CachedGlyph* glyph) {
|
void JGL::CachedFont::appendGlyph(JGL::CachedGlyph* glyph) {
|
||||||
glyphs.push_back(glyph);
|
glyphs.emplace(glyph->getCharacter(), glyph);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int JGL::CachedFont::getFontSize() {
|
unsigned int JGL::CachedFont::getFontSize() {
|
||||||
@@ -33,64 +36,50 @@ unsigned int JGL::CachedFont::getFontIndex() {
|
|||||||
return font_index;
|
return font_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO make this code go faster.
|
||||||
CachedGlyph* JGL::CachedFont::getGlyph(char c) {
|
CachedGlyph* JGL::CachedFont::getGlyph(char c) {
|
||||||
for (const auto& g : glyphs)
|
auto it = glyphs.find(c);
|
||||||
if (c == g->getCharacter())
|
if (it != glyphs.end())
|
||||||
return g;
|
return it->second;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
CachedFont::CachedFont(unsigned int font_size, unsigned int font_index) {
|
CachedFont::CachedFont(GLuint texture_id, GLsizei texture_width, GLsizei texture_height, unsigned int font_size, unsigned int font_index) {
|
||||||
|
this->texture = texture_id;
|
||||||
|
this->texture_width = texture_width;
|
||||||
|
this->texture_height = texture_height;
|
||||||
this->font_size = font_size;
|
this->font_size = font_size;
|
||||||
this->font_index = font_index;
|
this->font_index = font_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CachedFont::eraseGlyph(CachedGlyph* glyph) {
|
std::map<char, CachedGlyph*> CachedFont::getGlyphs() {
|
||||||
if (glyph == nullptr)
|
return glyphs;
|
||||||
return;
|
|
||||||
|
|
||||||
for (int i = 0; i < glyphs.size(); i++)
|
|
||||||
if (glyphs[i] == glyph)
|
|
||||||
glDeleteTextures(1, glyphs[i]->getTexture()),
|
|
||||||
delete glyphs[i],
|
|
||||||
glyphs.erase(glyphs.begin() + i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CachedFont::eraseGlyph(char c) {
|
const GLuint* CachedFont::getTexture() {
|
||||||
for (int i = 0; i < glyphs.size(); i++)
|
return &texture;
|
||||||
if (glyphs[i]->getCharacter() == c)
|
|
||||||
glDeleteTextures(1, glyphs[i]->getTexture()),
|
|
||||||
delete glyphs[i],
|
|
||||||
glyphs.erase(glyphs.begin() + i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CachedFont::eraseGlyph(GLuint texture_id) {
|
GLsizei CachedFont::getTextureWidth() const {
|
||||||
for (int i = 0; i < glyphs.size(); i++)
|
return texture_width;
|
||||||
if (glyphs[i]->getTexture() == &texture_id)
|
|
||||||
glDeleteTextures(1, glyphs[i]->getTexture()),
|
|
||||||
delete glyphs[i],
|
|
||||||
glyphs.erase(glyphs.begin() + i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CachedGlyph*>* CachedFont::getGlyphs() {
|
GLsizei CachedFont::getTextureHeight() const {
|
||||||
return &glyphs;
|
return texture_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FontCache::appendFont(CachedFont* font) {
|
void FontCache::appendFont(CachedFont* font) {
|
||||||
cachedFonts.push_back(font);
|
cachedFonts.push_back(font);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FontCache::newFont(unsigned int font_size, unsigned int font_index) {
|
void FontCache::newFont(GLuint texture_id, GLsizei texture_width, GLsizei texture_height, unsigned int font_size, unsigned int font_index) {
|
||||||
auto* font = new CachedFont(font_size, font_index);
|
auto* font = new CachedFont(texture_id, texture_width, texture_height, font_size, font_index);
|
||||||
cachedFonts.push_back(font);
|
cachedFonts.push_back(font);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FontCache::eraseFont(CachedFont* font) {
|
void FontCache::eraseFont(CachedFont* font) {
|
||||||
for (int i = 0; i < cachedFonts.size(); i++) {
|
for (int i = 0; i < cachedFonts.size(); i++) {
|
||||||
if (cachedFonts[i] == font) {
|
if (cachedFonts[i] == font) {
|
||||||
for (auto& g: *cachedFonts[i]->getGlyphs())
|
|
||||||
cachedFonts[i]->eraseGlyph(g);
|
|
||||||
|
|
||||||
delete cachedFonts[i];
|
delete cachedFonts[i];
|
||||||
cachedFonts.erase(cachedFonts.begin() + i);
|
cachedFonts.erase(cachedFonts.begin() + i);
|
||||||
}
|
}
|
||||||
@@ -101,11 +90,10 @@ void FontCache::purgeCache() {
|
|||||||
//Remove every font from the cache.
|
//Remove every font from the cache.
|
||||||
for (const auto& font : cachedFonts)
|
for (const auto& font : cachedFonts)
|
||||||
eraseFont(font);
|
eraseFont(font);
|
||||||
cachedFonts = {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CachedFont*>* FontCache::getFonts() {
|
std::vector<CachedFont*> FontCache::getFonts() {
|
||||||
return &cachedFonts;
|
return cachedFonts;
|
||||||
}
|
}
|
||||||
|
|
||||||
CachedFont* FontCache::getFont(unsigned int font_size, unsigned int font_index) {
|
CachedFont* FontCache::getFont(unsigned int font_size, unsigned int font_index) {
|
||||||
|
236
src/JGL.cpp
236
src/JGL.cpp
@@ -4,10 +4,11 @@
|
|||||||
|
|
||||||
#include <JGL/JGL.h>
|
#include <JGL/JGL.h>
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
#include <JGL/Color3.h>
|
#include <Color3.hpp>
|
||||||
#include <jlog/jlog.hpp>
|
#include <jlog/jlog.hpp>
|
||||||
|
|
||||||
GLfloat oldColor[4] = {0, 0, 0, 255};
|
GLfloat oldColor[4] = {0, 0, 0, 1};
|
||||||
|
GLfloat baseColor[4] = {1, 1, 1, 1};
|
||||||
bool inJ2D = false;
|
bool inJ2D = false;
|
||||||
bool inJ3D = false;
|
bool inJ3D = false;
|
||||||
bool wasTexture2DEnabled = false;
|
bool wasTexture2DEnabled = false;
|
||||||
@@ -17,25 +18,35 @@ bool wasVertexArraysEnabled = false;
|
|||||||
bool wasCullFaceEnabled = false;
|
bool wasCullFaceEnabled = false;
|
||||||
bool wasBlendEnabled = false;
|
bool wasBlendEnabled = false;
|
||||||
bool wasColorArrayEnabled = false;
|
bool wasColorArrayEnabled = false;
|
||||||
|
GLint activeTextureUnit = 0;
|
||||||
|
|
||||||
namespace JGL {
|
namespace JGL {
|
||||||
using namespace J3ML;
|
using namespace J3ML;
|
||||||
Vector2 wS;
|
Vector2 wS;
|
||||||
|
|
||||||
bool Update(const Vector2& window_size) {
|
void Update(const Vector2& window_size) {
|
||||||
wS = window_size;
|
wS = window_size;
|
||||||
return JGL::InitTextEngine();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void J2D::Begin() {
|
void J2D::Begin() {
|
||||||
|
glViewport(0, 0, wS.x, wS.y);
|
||||||
glMatrixMode(GL_PROJECTION);
|
glMatrixMode(GL_PROJECTION);
|
||||||
glPushMatrix();
|
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
glOrtho(0, wS.x, wS.y, 0, -1, 1);
|
glOrtho(0, wS.x, wS.y, 0, -1, 1);
|
||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
glPushMatrix();
|
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
|
|
||||||
|
|
||||||
|
//Get what the draw color was before we did anything.
|
||||||
|
glGetFloatv(GL_CURRENT_COLOR, oldColor);
|
||||||
|
glColor4f(baseColor[0], baseColor[1], baseColor[2], baseColor[3]);
|
||||||
|
|
||||||
|
glGetIntegerv(GL_ACTIVE_TEXTURE,& activeTextureUnit);
|
||||||
|
activeTextureUnit = activeTextureUnit - GL_TEXTURE0;
|
||||||
|
if (activeTextureUnit != 0)
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
|
||||||
wasDepthTestEnabled = false;
|
wasDepthTestEnabled = false;
|
||||||
if (glIsEnabled(GL_DEPTH_TEST))
|
if (glIsEnabled(GL_DEPTH_TEST))
|
||||||
wasDepthTestEnabled = true,
|
wasDepthTestEnabled = true,
|
||||||
@@ -44,7 +55,7 @@ namespace JGL {
|
|||||||
wasVertexArraysEnabled = true;
|
wasVertexArraysEnabled = true;
|
||||||
if (!glIsEnabled(GL_VERTEX_ARRAY))
|
if (!glIsEnabled(GL_VERTEX_ARRAY))
|
||||||
wasVertexArraysEnabled = false,
|
wasVertexArraysEnabled = false,
|
||||||
glEnable(GL_VERTEX_ARRAY);
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
|
|
||||||
wasCullFaceEnabled = true;
|
wasCullFaceEnabled = true;
|
||||||
if (!glIsEnabled(GL_CULL_FACE))
|
if (!glIsEnabled(GL_CULL_FACE))
|
||||||
@@ -66,12 +77,12 @@ namespace JGL {
|
|||||||
wasTextureCoordArrayEnabled = true;
|
wasTextureCoordArrayEnabled = true;
|
||||||
if (!glIsEnabled(GL_TEXTURE_COORD_ARRAY))
|
if (!glIsEnabled(GL_TEXTURE_COORD_ARRAY))
|
||||||
wasTextureCoordArrayEnabled = false,
|
wasTextureCoordArrayEnabled = false,
|
||||||
glEnable(GL_TEXTURE_COORD_ARRAY);
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
|
||||||
wasColorArrayEnabled = false;
|
wasColorArrayEnabled = false;
|
||||||
if (glIsEnabled(GL_COLOR_ARRAY))
|
if (glIsEnabled(GL_COLOR_ARRAY))
|
||||||
wasColorArrayEnabled = true,
|
wasColorArrayEnabled = true,
|
||||||
glDisable(GL_COLOR_ARRAY);
|
glDisableClientState(GL_COLOR_ARRAY);
|
||||||
|
|
||||||
if (!inJ3D)
|
if (!inJ3D)
|
||||||
inJ2D = true;
|
inJ2D = true;
|
||||||
@@ -80,7 +91,6 @@ namespace JGL {
|
|||||||
|
|
||||||
void J2D::End() {
|
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();
|
glPopMatrix();
|
||||||
glMatrixMode(GL_PROJECTION);
|
glMatrixMode(GL_PROJECTION);
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
@@ -89,7 +99,7 @@ namespace JGL {
|
|||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
if (!wasVertexArraysEnabled)
|
if (!wasVertexArraysEnabled)
|
||||||
glDisable(GL_VERTEX_ARRAY);
|
glDisableClientState(GL_VERTEX_ARRAY);
|
||||||
|
|
||||||
if (!wasCullFaceEnabled)
|
if (!wasCullFaceEnabled)
|
||||||
glDisable(GL_CULL_FACE);
|
glDisable(GL_CULL_FACE);
|
||||||
@@ -101,10 +111,13 @@ namespace JGL {
|
|||||||
glDisable(GL_TEXTURE_2D);
|
glDisable(GL_TEXTURE_2D);
|
||||||
|
|
||||||
if (!wasTextureCoordArrayEnabled)
|
if (!wasTextureCoordArrayEnabled)
|
||||||
glDisable(GL_TEXTURE_COORD_ARRAY);
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
|
||||||
if (wasColorArrayEnabled)
|
if (wasColorArrayEnabled)
|
||||||
glEnable(GL_COLOR_ARRAY);
|
glEnableClientState(GL_COLOR_ARRAY);
|
||||||
|
|
||||||
|
//Select whatever texture_handle unit was selected before.
|
||||||
|
glActiveTexture(GL_TEXTURE0 + activeTextureUnit);
|
||||||
|
|
||||||
//Put the draw color back how it was before.
|
//Put the draw color back how it was before.
|
||||||
glColor4f(oldColor[0], oldColor[1], oldColor[2], oldColor[3]);
|
glColor4f(oldColor[0], oldColor[1], oldColor[2], oldColor[3]);
|
||||||
@@ -112,14 +125,109 @@ namespace JGL {
|
|||||||
inJ2D = false;
|
inJ2D = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void J2D::DrawSprite(const Texture& texture, const Vector2& pos, const Vector2& origin, const Vector2& scale, const Color4& color, Inversion inversion) {
|
||||||
|
if (!inJ2D)
|
||||||
|
ERROR("Attempt to Render J2D element before J2D begin.")
|
||||||
|
|
||||||
|
|
||||||
|
const Vector2 size = texture.GetDimensions();
|
||||||
|
|
||||||
|
std::array<Vector2, 4> textureCoordinates = {Vector2(0, 0), Vector2(0, 1), Vector2(1, 1), Vector2(1, 0)};
|
||||||
|
|
||||||
|
// TODO: Kind of a mess, refactor to be more sensible later.
|
||||||
|
// Factors in scaling and origin correctly.
|
||||||
|
// i.e. to render at 2x size, from the center, at coords XY, use {2, 2} scale, and {0.5, 0.5} offset.
|
||||||
|
const Vector2 offset = origin * size;
|
||||||
|
|
||||||
|
Vector2 pos2 = pos - offset*scale;
|
||||||
|
Vector2 scaled_size = scale * size;
|
||||||
|
Vector2 size2 = scaled_size;
|
||||||
|
|
||||||
|
const Vector2 vertices[] = {
|
||||||
|
pos2, // Top-left vertex
|
||||||
|
{pos2.x, pos2.y + size2.y}, // Bottom-left
|
||||||
|
{pos2.x + size2.x, pos2.y + size2.y}, // Bottom-right
|
||||||
|
{pos2.x + size2.x, pos2.y} // Top-right
|
||||||
|
};
|
||||||
|
|
||||||
|
if (inversion& Inversion::Vertical)
|
||||||
|
textureCoordinates = {Vector2(0, 1), Vector2(0, 0), Vector2(1, 0), Vector2(1, 1)};
|
||||||
|
if (inversion& Inversion::Horizontal)
|
||||||
|
textureCoordinates = {Vector2(1, 0), Vector2(1, 1), Vector2(0, 1), Vector2(0, 0)};
|
||||||
|
if ((inversion& Inversion::Horizontal) && (inversion& Inversion::Vertical))
|
||||||
|
textureCoordinates = {Vector2(1, 1), Vector2(1, 0), Vector2(0, 0), Vector2(0, 1)};
|
||||||
|
|
||||||
|
glColor4ubv(color.ptr());
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture.GetGLTextureHandle());
|
||||||
|
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
|
||||||
|
glTexCoordPointer(2, GL_FLOAT, sizeof(Vector2), textureCoordinates.data());
|
||||||
|
glDrawArrays(GL_QUADS, 0, 4);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
glColor4f(baseColor[0], baseColor[1], baseColor[2], baseColor[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void J2D::DrawSprite(const Texture& texture, float positionX, float positionY, float originX, float originY, float scaleX, float scaleY, const Color4& color, Inversion inversion)
|
||||||
|
{
|
||||||
|
DrawSprite(texture,
|
||||||
|
{positionX, positionX},
|
||||||
|
{originX, originY},
|
||||||
|
{scaleX, scaleY},
|
||||||
|
color,
|
||||||
|
inversion);
|
||||||
|
}
|
||||||
|
|
||||||
|
void J2D::FillQuad(const Color4& color, const Vector2& v1, const Vector2& v2, const Vector2& v3, const Vector2& v4) {
|
||||||
|
if (!inJ2D)
|
||||||
|
ERROR("Attempt to Render J2D element before J2D begin.")
|
||||||
|
|
||||||
|
Vector2 vertices[] = {v1, v2, v3, v4};
|
||||||
|
glColor4f(color.RedChannelNormalized(),
|
||||||
|
color.GreenChannelNormalized(),
|
||||||
|
color.BlueChannelNormalized(),
|
||||||
|
color.AlphaChannelNormalized());
|
||||||
|
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
|
||||||
|
glDrawArrays(GL_QUADS, 0, 4);
|
||||||
|
glColor4f(baseColor[0], baseColor[1], baseColor[2], baseColor[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void J2D::FillQuad(const Color3& color, const Vector2& v1, const Vector2& v2, const Vector2& v3, const Vector2& v4) {
|
||||||
|
J2D::FillQuad(Color4(color), v1, v2, v3, v4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void J2D::OutlineQuad(const Color4& color, const Vector2& v1, const Vector2& v2, const Vector2& v3, const Vector2& v4, float thickness) {
|
||||||
|
if (!inJ2D)
|
||||||
|
ERROR("Attempt to Render J2D element before J2D begin.")
|
||||||
|
|
||||||
|
Vector2 vertices[] = {v1, v2, v3, v4};
|
||||||
|
glLineWidth(thickness);
|
||||||
|
glColor4f(color.RedChannelNormalized(),
|
||||||
|
color.GreenChannelNormalized(),
|
||||||
|
color.BlueChannelNormalized(),
|
||||||
|
color.AlphaChannelNormalized());
|
||||||
|
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
|
||||||
|
glDrawArrays(GL_LINE_LOOP, 0, 4);
|
||||||
|
glColor4f(baseColor[0], baseColor[1], baseColor[2], baseColor[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void J2D::OutlineQuad(const Color3& color, const Vector2& v1, const Vector2& v2, const Vector2& v3, const Vector2& v4, float thickness) {
|
||||||
|
J2D::OutlineQuad(Color4(color), v1, v2, v3, v4);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void J2D::FillRect(const Color4& color, const Vector2& pos, const Vector2& size) {
|
void J2D::FillRect(const Color4& color, const Vector2& pos, const Vector2& size) {
|
||||||
if (!inJ2D)
|
if (!inJ2D)
|
||||||
ERROR("Attempt to Render J2D element before J2D begin.")
|
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}};
|
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);
|
glColor4f(color.RedChannelNormalized(),
|
||||||
|
color.GreenChannelNormalized(),
|
||||||
|
color.BlueChannelNormalized(),
|
||||||
|
color.AlphaChannelNormalized());
|
||||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
|
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
|
||||||
glDrawArrays(GL_QUADS, 0, 4);
|
glDrawArrays(GL_QUADS, 0, 4);
|
||||||
|
glColor4f(baseColor[0], baseColor[1], baseColor[2], baseColor[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void J2D::FillRect(const Color3& color, const Vector2& pos, const Vector2& size) {
|
void J2D::FillRect(const Color3& color, const Vector2& pos, const Vector2& size) {
|
||||||
@@ -151,18 +259,19 @@ namespace JGL {
|
|||||||
(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.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};
|
(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);
|
glEnableClientState(GL_COLOR_ARRAY);
|
||||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
|
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
|
||||||
glColorPointer(4, GL_FLOAT, 0, colors.data());
|
glColorPointer(4, GL_FLOAT, 0, colors.data());
|
||||||
glDrawArrays(GL_QUADS, 0, 4);
|
glDrawArrays(GL_QUADS, 0, 4);
|
||||||
glDisable(GL_COLOR_ARRAY);
|
glDisableClientState(GL_COLOR_ARRAY);
|
||||||
|
glColor4f(baseColor[0], baseColor[1], baseColor[2], baseColor[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void J2D::FillGradientRect(const Color3& color1, const Color3& color2, const Gradient& gradient, const Vector2& pos, const Vector2& size) {
|
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);
|
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) {
|
void J2D::FillRoundedRect(const Color4& color, const Vector2& pos, const Vector2& size, float radius, unsigned int subdivisions) {
|
||||||
if (!inJ2D)
|
if (!inJ2D)
|
||||||
ERROR("Attempt to Render J2D element before J2D begin.")
|
ERROR("Attempt to Render J2D element before J2D begin.")
|
||||||
|
|
||||||
@@ -175,7 +284,7 @@ namespace JGL {
|
|||||||
J2D::FillCircle(color, {pos.x + size.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) {
|
void J2D::FillRoundedRect(const 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);
|
J2D::FillRoundedRect({color.r, color.g, color.b, 255}, pos, size, radius, subdivisions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,9 +295,13 @@ namespace JGL {
|
|||||||
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}};
|
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);
|
glLineWidth(thickness);
|
||||||
glColor4f(color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f);
|
glColor4f(color.RedChannelNormalized(),
|
||||||
|
color.GreenChannelNormalized(),
|
||||||
|
color.BlueChannelNormalized(),
|
||||||
|
color.AlphaChannelNormalized());
|
||||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
|
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
|
||||||
glDrawArrays(GL_LINE_LOOP, 0, 4);
|
glDrawArrays(GL_LINE_LOOP, 0, 4);
|
||||||
|
glColor4f(baseColor[0], baseColor[1], baseColor[2], baseColor[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void J2D::OutlineRect(const Color3& color, const Vector2& pos, const Vector2& size, float thickness) {
|
void J2D::OutlineRect(const Color3& color, const Vector2& pos, const Vector2& size, float thickness) {
|
||||||
@@ -202,9 +315,13 @@ namespace JGL {
|
|||||||
Vector2 vertices[] = {A, B};
|
Vector2 vertices[] = {A, B};
|
||||||
|
|
||||||
glLineWidth(thickness);
|
glLineWidth(thickness);
|
||||||
glColor4f(color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f);
|
glColor4f(color.RedChannelNormalized(),
|
||||||
|
color.GreenChannelNormalized(),
|
||||||
|
color.BlueChannelNormalized(),
|
||||||
|
color.AlphaChannelNormalized());
|
||||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
|
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
|
||||||
glDrawArrays(GL_LINES, 0, 2);
|
glDrawArrays(GL_LINES, 0, 2);
|
||||||
|
glColor4f(baseColor[0], baseColor[1], baseColor[2], baseColor[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void J2D::DrawLine(const Color3& color, const Vector2& A, const Vector2& B, float thickness) {
|
void J2D::DrawLine(const Color3& color, const Vector2& A, const Vector2& B, float thickness) {
|
||||||
@@ -227,12 +344,13 @@ namespace JGL {
|
|||||||
GLfloat colors[8] = {color1.r / 255.f, color1.g / 255.f, color1.b / 255.f, color1.a / 255.f,
|
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};
|
color2.r / 255.f, color2.g / 255.f, color2.b / 255.f, color2.a / 255.f};
|
||||||
|
|
||||||
glEnable(GL_COLOR_ARRAY);
|
glEnableClientState(GL_COLOR_ARRAY);
|
||||||
glLineWidth(thickness);
|
glLineWidth(thickness);
|
||||||
glColorPointer(4,GL_FLOAT,sizeof(GL_FLOAT) * 4, colors);
|
glColorPointer(4,GL_FLOAT,sizeof(GL_FLOAT) * 4, colors);
|
||||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
|
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
|
||||||
glDrawArrays(GL_LINES, 0, 2);
|
glDrawArrays(GL_LINES, 0, 2);
|
||||||
glDisable(GL_COLOR_ARRAY);
|
glDisableClientState(GL_COLOR_ARRAY);
|
||||||
|
glColor4f(baseColor[0], baseColor[1], baseColor[2], baseColor[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void J2D::DrawGradientLine(const Color3& color1, const Color3& color2, const Vector2& A, const Vector2& B, float thickness) {
|
void J2D::DrawGradientLine(const Color3& color1, const Color3& color2, const Vector2& A, const Vector2& B, float thickness) {
|
||||||
@@ -246,27 +364,32 @@ namespace JGL {
|
|||||||
J2D::DrawGradientLine({color1.r, color1.g, color1.b, 255}, {color2.r, color2.g, color2.b, 255}, {x, y}, {w, h}, 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) {
|
void J2D::DrawPoint(const Color4& color, const Vector2& coordinates, float radius) {
|
||||||
if (!inJ2D)
|
if (!inJ2D)
|
||||||
ERROR("Attempt to Render J2D element before J2D begin.");
|
ERROR("Attempt to Render J2D element before J2D begin.");
|
||||||
|
|
||||||
Vector2 vertices[] = {coordinates};
|
Vector2 vertices[] = {coordinates};
|
||||||
|
|
||||||
glColor4f(color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f);
|
glPointSize(radius);
|
||||||
|
glColor4f(color.RedChannelNormalized(),
|
||||||
|
color.GreenChannelNormalized(),
|
||||||
|
color.BlueChannelNormalized(),
|
||||||
|
color.AlphaChannelNormalized());
|
||||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
|
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
|
||||||
glDrawArrays(GL_LINES, 0, 1);
|
glDrawArrays(GL_POINTS, 0, 1);
|
||||||
|
glColor4f(baseColor[0], baseColor[1], baseColor[2], baseColor[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void J2D::DrawPixel(const Color3& color, const Vector2& coordinates) {
|
void J2D::DrawPoint(const Color3& color, const Vector2& coordinates, float radius) {
|
||||||
J2D::DrawPixel({color.r, color.g, color.b, 255}, coordinates);
|
J2D::DrawPoint({color.r, color.g, color.b, 255}, coordinates);
|
||||||
}
|
}
|
||||||
|
|
||||||
void J2D::DrawPixel(const Color4& color, float x, float y) {
|
void J2D::DrawPoint(const Color4& color, float x, float y, float radius) {
|
||||||
DrawPixel(color, {x, y});
|
DrawPoint(color, {x, y});
|
||||||
}
|
}
|
||||||
|
|
||||||
void J2D::DrawPixel(const Color3& color, float x, float y) {
|
void J2D::DrawPoint(const Color3& color, float x, float y, float radius) {
|
||||||
DrawPixel({color.r, color.g, color.b, 255}, {x, y});
|
DrawPoint({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) {
|
void J2D::OutlineCircle(const Color4& color, const Vector2& center, float radius, unsigned int subdivisions, float thickness) {
|
||||||
@@ -284,9 +407,13 @@ namespace JGL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
glLineWidth(thickness);
|
glLineWidth(thickness);
|
||||||
glColor4f(color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f);
|
glColor4f(color.RedChannelNormalized(),
|
||||||
|
color.GreenChannelNormalized(),
|
||||||
|
color.BlueChannelNormalized(),
|
||||||
|
color.AlphaChannelNormalized());
|
||||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
|
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
|
||||||
glDrawArrays(GL_LINE_LOOP, 0, vertices.size());
|
glDrawArrays(GL_LINE_LOOP, 0, vertices.size());
|
||||||
|
glColor4f(baseColor[0], baseColor[1], baseColor[2], baseColor[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void J2D::OutlineCircle(const Color3& color, const Vector2& center, float radius, unsigned int subdivisions, float thickness) {
|
void J2D::OutlineCircle(const Color3& color, const Vector2& center, float radius, unsigned int subdivisions, float thickness) {
|
||||||
@@ -306,9 +433,10 @@ namespace JGL {
|
|||||||
y = radius * cos(angle) + center.y,
|
y = radius * cos(angle) + center.y,
|
||||||
vertices.push_back({x, y});
|
vertices.push_back({x, y});
|
||||||
|
|
||||||
glColor4f(color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f);
|
glColor4ubv(color.ptr());
|
||||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
|
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
|
||||||
glDrawArrays(GL_TRIANGLE_FAN, 0, vertices.size());
|
glDrawArrays(GL_TRIANGLE_FAN, 0, vertices.size());
|
||||||
|
glColor4f(baseColor[0], baseColor[1], baseColor[2], baseColor[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void J2D::FillCircle(const Color3& color, const Vector2& center, float radius, unsigned int subdivisions) {
|
void J2D::FillCircle(const Color3& color, const Vector2& center, float radius, unsigned int subdivisions) {
|
||||||
@@ -325,13 +453,14 @@ namespace JGL {
|
|||||||
glColor4f(color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 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);
|
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
|
||||||
glDrawArrays(GL_LINE_LOOP, 0, 3);
|
glDrawArrays(GL_LINE_LOOP, 0, 3);
|
||||||
|
glColor4f(baseColor[0], baseColor[1], baseColor[2], baseColor[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void J2D::OutlineTriangle(const Color3& color, const Triangle2D& tri, float thickness) {
|
void J2D::OutlineTriangle(const Color3& color, const Triangle2D& tri, float thickness) {
|
||||||
J2D::OutlineTriangle({color.r, color.g, color.b, 255}, tri, thickness);
|
J2D::OutlineTriangle({color.r, color.g, color.b, 255}, tri, thickness);
|
||||||
}
|
}
|
||||||
|
|
||||||
void J2D::FillTriangle(const Color4& color, const Triangle2D &tri) {
|
void J2D::FillTriangle(const Color4& color, const Triangle2D& tri) {
|
||||||
if (!inJ2D)
|
if (!inJ2D)
|
||||||
ERROR("Attempt to Render J2D element before J2D begin.")
|
ERROR("Attempt to Render J2D element before J2D begin.")
|
||||||
|
|
||||||
@@ -340,9 +469,32 @@ namespace JGL {
|
|||||||
glColor4f(color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 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);
|
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
|
||||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||||
|
glColor4f(baseColor[0], baseColor[1], baseColor[2], baseColor[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void J2D::FillTriangle(const Color3& color, const Triangle2D &tri) {
|
void J2D::FillGradientTriangle(const Color4& a_color, const Color4& b_color, const Color4& c_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}};
|
||||||
|
GLfloat colors[] = {a_color.r / 255.f, a_color.g / 255.f, a_color.b / 255.f, a_color.a / 255.f,b_color.r / 255.f,
|
||||||
|
b_color.g / 255.f, b_color.b / 255.f, b_color.a / 255.f,c_color.r / 255.f, c_color.g / 255.f, c_color.b / 255.f,
|
||||||
|
c_color.a / 255.f };
|
||||||
|
|
||||||
|
glEnableClientState(GL_COLOR_ARRAY);
|
||||||
|
glColorPointer(4, GL_FLOAT, sizeof(Color4), colors);
|
||||||
|
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||||
|
glDisableClientState(GL_COLOR_ARRAY);
|
||||||
|
glColor4f(baseColor[0], baseColor[1], baseColor[2], baseColor[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void J2D::FillGradientTriangle(const Color3& a_color, const Color3& b_color, const Color3& c_color, const Triangle2D& tri) {
|
||||||
|
J2D::FillGradientTriangle(Color4(a_color), Color4(b_color), Color4(c_color), tri);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void J2D::FillTriangle(const Color3& color, const Triangle2D& tri) {
|
||||||
J2D::FillTriangle({color.r, color.g, color.b, 255}, tri);
|
J2D::FillTriangle({color.r, color.g, color.b, 255}, tri);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -350,6 +502,7 @@ namespace JGL {
|
|||||||
|
|
||||||
//Get what the draw color was before we did anything.
|
//Get what the draw color was before we did anything.
|
||||||
glGetFloatv(GL_CURRENT_COLOR, oldColor);
|
glGetFloatv(GL_CURRENT_COLOR, oldColor);
|
||||||
|
glColor4f(baseColor[0], baseColor[1], baseColor[2], baseColor[3]);
|
||||||
|
|
||||||
wasDepthTestEnabled = false;
|
wasDepthTestEnabled = false;
|
||||||
if (glIsEnabled(GL_DEPTH_TEST))
|
if (glIsEnabled(GL_DEPTH_TEST))
|
||||||
@@ -359,14 +512,14 @@ namespace JGL {
|
|||||||
wasVertexArraysEnabled = false;
|
wasVertexArraysEnabled = false;
|
||||||
if (!glIsEnabled(GL_VERTEX_ARRAY))
|
if (!glIsEnabled(GL_VERTEX_ARRAY))
|
||||||
wasVertexArraysEnabled = false,
|
wasVertexArraysEnabled = false,
|
||||||
glEnable(GL_VERTEX_ARRAY);
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
|
|
||||||
wasTexture2DEnabled = true;
|
wasTexture2DEnabled = true;
|
||||||
if (!glIsEnabled(GL_TEXTURE_2D))
|
if (!glIsEnabled(GL_TEXTURE_2D))
|
||||||
wasTexture2DEnabled = false,
|
wasTexture2DEnabled = false,
|
||||||
glEnable(GL_TEXTURE_2D);
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
|
||||||
//TODO We won't always want this but for now we do.
|
// TODO: implement bool drawBackface as DrawString parameter.
|
||||||
wasCullFaceEnabled = false;
|
wasCullFaceEnabled = false;
|
||||||
if (glIsEnabled(GL_CULL_FACE))
|
if (glIsEnabled(GL_CULL_FACE))
|
||||||
wasCullFaceEnabled = true,
|
wasCullFaceEnabled = true,
|
||||||
@@ -382,22 +535,20 @@ namespace JGL {
|
|||||||
|
|
||||||
if (!inJ2D)
|
if (!inJ2D)
|
||||||
inJ3D = true;
|
inJ3D = true;
|
||||||
else { ERROR("Attempt to Begin J3D inside of J2D context.") }
|
else { ERROR("Attempt to Begin J3D inside of J2D context.")}
|
||||||
}
|
}
|
||||||
|
|
||||||
void J3D::End() {
|
void J3D::End() {
|
||||||
glDisable(GL_TEXTURE_2D);
|
|
||||||
|
|
||||||
if (wasDepthTestEnabled)
|
if (wasDepthTestEnabled)
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
if (!wasVertexArraysEnabled)
|
if (!wasVertexArraysEnabled)
|
||||||
glDisable(GL_VERTEX_ARRAY);
|
glDisableClientState(GL_VERTEX_ARRAY);
|
||||||
|
|
||||||
if (wasTexture2DEnabled)
|
if (wasTexture2DEnabled)
|
||||||
glDisable(GL_TEXTURE_2D);
|
glDisable(GL_TEXTURE_2D);
|
||||||
|
|
||||||
if (wasBlendEnabled)
|
if (!wasBlendEnabled)
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
|
|
||||||
if (wasCullFaceEnabled)
|
if (wasCullFaceEnabled)
|
||||||
@@ -419,6 +570,7 @@ namespace JGL {
|
|||||||
glColor4f(color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 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);
|
glVertexPointer(3, GL_FLOAT, sizeof(Vector3), vertices);
|
||||||
glDrawArrays(GL_LINES, 0, 2);
|
glDrawArrays(GL_LINES, 0, 2);
|
||||||
|
glColor4f(baseColor[0], baseColor[1], baseColor[2], baseColor[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void J3D::DrawLine(const Color3& color, const Vector3& A, const Vector3& B, float thickness) {
|
void J3D::DrawLine(const Color3& color, const Vector3& A, const Vector3& B, float thickness) {
|
||||||
|
155
src/JGL/Font.cpp
Normal file
155
src/JGL/Font.cpp
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
#include <glad/glad.h>
|
||||||
|
|
||||||
|
#if __linux__
|
||||||
|
#include <freetype2/ft2build.h>
|
||||||
|
#include FT_FREETYPE_H
|
||||||
|
#include FT_OUTLINE_H
|
||||||
|
#include <JGL/FontCache.h>
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if _WIN32
|
||||||
|
#include <ft2build.h>
|
||||||
|
#include FT_FREETYPE_H
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <JGL/Font.h>
|
||||||
|
|
||||||
|
namespace JGL::Detail
|
||||||
|
{
|
||||||
|
FT_Library ft;
|
||||||
|
|
||||||
|
std::vector<Font> fonts;
|
||||||
|
|
||||||
|
bool InitTextEngine() {
|
||||||
|
|
||||||
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // NOTE: This MUST be called for text rendering to work properly!!!
|
||||||
|
// Keep note of this, might cause problems later?
|
||||||
|
|
||||||
|
if (ft != nullptr)
|
||||||
|
throw std::runtime_error("Error::FREETYPE: FT_Library was initialized but is already initialized.");
|
||||||
|
|
||||||
|
if (FT_Init_FreeType(&ft))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnloadFont(int font_index) {
|
||||||
|
|
||||||
|
auto iter = fonts.begin();
|
||||||
|
while (iter != fonts.end())
|
||||||
|
{
|
||||||
|
if (iter->index == font_index){
|
||||||
|
FT_Done_Face(iter->face);
|
||||||
|
iter = fonts.erase(iter);
|
||||||
|
} else ++iter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace JGL
|
||||||
|
{
|
||||||
|
|
||||||
|
bool InitTextEngine()
|
||||||
|
{
|
||||||
|
return Detail::InitTextEngine();
|
||||||
|
}
|
||||||
|
|
||||||
|
Font::Font(const std::filesystem::path& path)
|
||||||
|
{
|
||||||
|
if (Detail::ft == nullptr)
|
||||||
|
throw new std::runtime_error("Error::FREETYPE: FT_Library was not initialized before attempting to load a font!");
|
||||||
|
|
||||||
|
Font font;
|
||||||
|
if (FT_New_Face(Detail::ft, path.c_str(), 0, &face)) {
|
||||||
|
std::cout << "Error::FREETYPE: Failed to load font!" << std::endl;
|
||||||
|
throw new std::runtime_error("Error::FREETYPE: Failed to load font!");
|
||||||
|
//return -1;
|
||||||
|
}
|
||||||
|
unsigned int newIndex = 0;
|
||||||
|
for (const auto& f : Detail::fonts)
|
||||||
|
if (f.index >= newIndex)
|
||||||
|
newIndex = f.index + 1;
|
||||||
|
|
||||||
|
index = newIndex;
|
||||||
|
Detail::fonts.push_back(font);
|
||||||
|
std::cout << "Loaded font from " << path << " with index " << newIndex << std::endl;
|
||||||
|
//return newIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
Font::~Font()
|
||||||
|
{
|
||||||
|
//Detail::UnloadFont(this->index);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<Font> Font::GetLoadedFonts() {
|
||||||
|
return Detail::fonts;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Font Font::LoadTTF(const std::filesystem::path& path)
|
||||||
|
{
|
||||||
|
return Font(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2 Font::MeasureString(const std::string &text, unsigned int ptSize) {
|
||||||
|
Vector2 extents = Vector2(0,0);
|
||||||
|
bool font_of_size_in_cache = false;
|
||||||
|
|
||||||
|
for(const auto& f : fontCache.getFonts()) {
|
||||||
|
if (f->getFontSize() == ptSize) {
|
||||||
|
font_of_size_in_cache = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (font_of_size_in_cache) {
|
||||||
|
CachedFont* font;
|
||||||
|
|
||||||
|
for (auto* f: fontCache.getFonts())
|
||||||
|
if (f->getFontSize() == ptSize)
|
||||||
|
font = f;
|
||||||
|
|
||||||
|
for (const char& c : text)
|
||||||
|
extents.x += font->getGlyph(c)->advanceX;
|
||||||
|
|
||||||
|
extents.y = ptSize;
|
||||||
|
return extents;
|
||||||
|
}
|
||||||
|
|
||||||
|
FT_Set_Pixel_Sizes(this->face, ptSize, ptSize);
|
||||||
|
|
||||||
|
for (const char& c : text) {
|
||||||
|
FT_GlyphSlot slot = face->glyph;
|
||||||
|
auto glyph_index = FT_Get_Char_Index(this->face, c);
|
||||||
|
|
||||||
|
auto error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
|
||||||
|
Vector2 advance = {static_cast<float>(slot->advance.x >> 6),
|
||||||
|
static_cast<float>(slot->advance.y >> 6)};
|
||||||
|
|
||||||
|
|
||||||
|
extents += advance;
|
||||||
|
|
||||||
|
// Gives smaller results than we'd want.
|
||||||
|
if (extents.y < slot->metrics.height / 64)
|
||||||
|
extents.y = slot->metrics.height / 64;
|
||||||
|
|
||||||
|
// Just fucking hardcode it, we know the glyph height is roughly always the ptSize anyway.
|
||||||
|
if (extents.y < ptSize)
|
||||||
|
extents.y = ptSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return extents;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@@ -1,139 +1,166 @@
|
|||||||
#include <JGL/JGL.h>
|
#include <JGL/JGL.h>
|
||||||
|
|
||||||
|
|
||||||
#if __linux__
|
#if __linux__
|
||||||
#include <freetype2/ft2build.h>
|
#include <freetype2/ft2build.h>
|
||||||
#include FT_FREETYPE_H
|
#include FT_FREETYPE_H
|
||||||
|
#include FT_OUTLINE_H
|
||||||
|
#include "jlog/jlog.hpp"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
#include <ft2build.h>
|
#include <ft2build.h>
|
||||||
#include FT_FREETYPE_H
|
#include FT_FREETYPE_H
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <JGL/Font.h>
|
||||||
|
#include <JGL/FontCache.h>
|
||||||
|
|
||||||
namespace JGL {
|
namespace JGL {
|
||||||
FT_Library ft;
|
|
||||||
|
|
||||||
struct Font {
|
void PurgeFontCache() {
|
||||||
int index = 0;
|
fontCache.purgeCache();
|
||||||
FT_Face face;
|
|
||||||
};
|
|
||||||
std::vector<Font> faces;
|
|
||||||
|
|
||||||
int LoadFont(const std::string &font_path) {
|
|
||||||
if (ft == nullptr)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
Font font;
|
|
||||||
if (FT_New_Face(ft, font_path.c_str(), 0, &font.face)) {
|
|
||||||
std::cout << "Error::FREETYPE: Failed to load font!" << std::endl;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
unsigned int newIndex = 0;
|
|
||||||
for (const auto& f : faces)
|
|
||||||
if (f.index >= newIndex)
|
|
||||||
newIndex = f.index + 1;
|
|
||||||
|
|
||||||
font.index = newIndex;
|
|
||||||
faces.push_back(font);
|
|
||||||
std::cout << "Loaded font from " << font_path << " with index " << newIndex << std::endl;
|
|
||||||
return newIndex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InitTextEngine() {
|
void J2D::DrawString(const Color4& color, const std::string& text, float x, float y, float scale, u32 size, const Font& font) {
|
||||||
if (FT_Init_FreeType(&ft))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UnloadFont(int font_index) {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
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.
|
glUseProgram(0); // Fixed-function pipeline.
|
||||||
|
|
||||||
Font font{};
|
// Offset by height to render at "correct" location.
|
||||||
CachedFont* cachedFont = fontCache.getFont(size, font_index);
|
y += size;
|
||||||
|
|
||||||
//If the font doesn't exist in the cache yet.
|
CachedFont* cachedFont = fontCache.getFont(size, font.index);
|
||||||
if (!cachedFont) {
|
|
||||||
fontCache.newFont(size, font_index);
|
|
||||||
cachedFont = fontCache.getFont(size, font_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Set up the regular font.
|
//Set up the regular font.
|
||||||
for (const auto& f : faces)
|
//for (const auto &f : Font::GetLoadedFonts())
|
||||||
if (f.index == font_index)
|
// if (f.index == font.index)
|
||||||
font = f;
|
// font = f;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (font.face == nullptr)
|
if (font.face == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
glColor4f(color.r / 255.f, color.g / 255.f, color.b / 255.f, 1.0f);
|
|
||||||
|
|
||||||
FT_Set_Pixel_Sizes(font.face, 0, size);
|
FT_Set_Pixel_Sizes(font.face, 0, size);
|
||||||
|
|
||||||
std::vector<GLuint> textures(text.length());
|
//If the font doesn't exist in the cache yet.
|
||||||
|
if (!cachedFont) {
|
||||||
|
DEBUG("Caching font data...");
|
||||||
|
GLuint texture_id;
|
||||||
|
glGenTextures(1, &texture_id);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture_id);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
|
||||||
|
|
||||||
//For each character
|
GLsizei width = 0;
|
||||||
for (int i = 0; i < text.length(); i++) {
|
GLsizei max_height = 0;
|
||||||
float x2, y2, w, h;
|
|
||||||
//If the font is in the cache already.
|
|
||||||
if (cachedFont->getGlyph(text.c_str()[i])) {
|
|
||||||
CachedGlyph* glyph = cachedFont->getGlyph(text.c_str()[i]);
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, *glyph->getTexture());
|
FT_ULong charcode;
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
FT_UInt gindex;
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
|
|
||||||
|
|
||||||
x2 = x + glyph->x2offset * scale;
|
//We have to loop over the available glyphs twice as we need the
|
||||||
y2 = y - glyph->y2offset * scale; // Adjust y-coordinate
|
//final width and height of the texture_handle before we can construct it
|
||||||
w = glyph->w * scale;
|
//and subsequently upload the glyph data.
|
||||||
h = glyph->h * scale;
|
|
||||||
x += glyph->advanceX * scale;
|
|
||||||
y += glyph->advanceY * scale;
|
|
||||||
|
|
||||||
} else {
|
charcode = FT_Get_First_Char(font.face, &gindex);
|
||||||
if (FT_Load_Char(font.face, text.c_str()[i], FT_LOAD_RENDER))
|
//Strings are char-based so we only handle charcodes within the extended ASCII range.
|
||||||
continue;
|
while (gindex != 0 && charcode < 255) {
|
||||||
|
if (FT_Load_Char(font.face, charcode, FT_LOAD_RENDER))
|
||||||
|
std::cout << "Error::FREETYPE: Failed to load charcode: " << charcode << std::endl;
|
||||||
|
|
||||||
FT_GlyphSlot g = font.face->glyph;
|
FT_GlyphSlot g = font.face->glyph;
|
||||||
glGenTextures(1, &textures.at(i));
|
width += g->bitmap.width;
|
||||||
glBindTexture(GL_TEXTURE_2D, textures[i]);
|
max_height = std::max(max_height, (GLsizei)g->bitmap.rows);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
charcode = FT_Get_Next_Char(font.face, charcode, &gindex);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, g->bitmap.width, g->bitmap.rows, 0, GL_ALPHA, GL_UNSIGNED_BYTE, g->bitmap.buffer);
|
|
||||||
|
|
||||||
x2 = x + g->bitmap_left * scale;
|
|
||||||
y2 = -y - g->bitmap_top * scale; // Adjust y-coordinate
|
|
||||||
w = g->bitmap.width * scale;
|
|
||||||
h = g->bitmap.rows * scale;
|
|
||||||
x += (g->advance.x >> 6) * scale;
|
|
||||||
y += (g->advance.y >> 6) * scale;
|
|
||||||
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)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GLfloat vertices[12] = {x2, y2, x2, y2 + h, x2 + w, y2 + h,x2, y2, x2 + w, y2 + h, x2 + w, y2};
|
fontCache.newFont(texture_id, width, max_height, size, font.index);
|
||||||
|
cachedFont = fontCache.getFont(size, font.index);
|
||||||
|
|
||||||
GLfloat textureCoordinates[12] = {0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0};
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, max_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, nullptr);
|
||||||
glTexCoordPointer(2, GL_FLOAT, sizeof(GL_FLOAT) * 2, &textureCoordinates);
|
|
||||||
glVertexPointer(2, GL_FLOAT, sizeof(GL_FLOAT) * 2, &vertices);
|
GLsizei xoffset = 0;
|
||||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
|
||||||
|
charcode = FT_Get_First_Char(font.face, &gindex);
|
||||||
|
while (gindex != 0 && charcode < 255) {
|
||||||
|
if (FT_Load_Char(font.face, charcode, FT_LOAD_RENDER))
|
||||||
|
std::cout << "Error::FREETYPE: Failed to load charcode: " << charcode << std::endl;
|
||||||
|
|
||||||
|
FT_GlyphSlot g = font.face->glyph;
|
||||||
|
glTexSubImage2D(GL_TEXTURE_2D, 0, xoffset, 0, g->bitmap.width, g->bitmap.rows, GL_ALPHA, GL_UNSIGNED_BYTE, g->bitmap.buffer);
|
||||||
|
|
||||||
|
GLfloat u0 = (GLfloat)xoffset / cachedFont->getTextureWidth();
|
||||||
|
GLfloat u1 = u0 + (GLfloat)g->bitmap.width / cachedFont->getTextureWidth();
|
||||||
|
|
||||||
|
GLfloat v0 = 0.0f;
|
||||||
|
GLfloat v1 = (GLfloat)g->bitmap.rows / cachedFont->getTextureHeight();
|
||||||
|
|
||||||
|
std::array<GLfloat, 12> texcoords = {
|
||||||
|
u0, v0,
|
||||||
|
u0, v1,
|
||||||
|
u1, v1,
|
||||||
|
u0, v0,
|
||||||
|
u1, v1,
|
||||||
|
u1, v0
|
||||||
|
};
|
||||||
|
|
||||||
|
cachedFont->appendGlyph(new CachedGlyph((char)charcode, texcoords, g->bitmap_left, g->bitmap_top, g->bitmap.width, g->bitmap.rows, (g->advance.x >> 6), (g->advance.y >> 6)));
|
||||||
|
|
||||||
|
xoffset += g->bitmap.width;
|
||||||
|
charcode = FT_Get_Next_Char(font.face, charcode, &gindex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
glBindTexture(GL_TEXTURE_2D, 0); // Unbind texture
|
|
||||||
|
glColor4f(color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f);
|
||||||
|
|
||||||
|
//Texture parameters are restored when the texture_handle is bound
|
||||||
|
glBindTexture(GL_TEXTURE_2D, *cachedFont->getTexture());
|
||||||
|
|
||||||
|
std::vector<std::array<GLfloat, 12>> vertices(text.size());
|
||||||
|
std::vector<std::array<GLfloat, 12>> texcoords(text.size());
|
||||||
|
|
||||||
|
for (int i = 0; i < text.length(); i++) {
|
||||||
|
float x2, y2, w, h;
|
||||||
|
CachedGlyph *glyph = cachedFont->getGlyph(text.c_str()[i]);
|
||||||
|
if (glyph == nullptr) continue;
|
||||||
|
|
||||||
|
x2 = x + glyph->x2offset * scale;
|
||||||
|
y2 = y - glyph->y2offset * scale; // Adjust y-coordinate
|
||||||
|
w = glyph->w * scale;
|
||||||
|
h = glyph->h * scale;
|
||||||
|
x += glyph->advanceX * scale;
|
||||||
|
y += glyph->advanceY * scale;
|
||||||
|
|
||||||
|
std::array<GLfloat, 12> glyph_vertices = {
|
||||||
|
x2, y2,
|
||||||
|
x2, y2 + h,
|
||||||
|
x2 + w, y2 + h,
|
||||||
|
x2, y2,
|
||||||
|
x2 + w, y2 + h,
|
||||||
|
x2 + w, y2
|
||||||
|
};
|
||||||
|
auto glyph_texcoords = glyph->getTexCoords();
|
||||||
|
vertices[i] = glyph_vertices;
|
||||||
|
texcoords[i] = glyph_texcoords;
|
||||||
|
}
|
||||||
|
|
||||||
|
glVertexPointer(2, GL_FLOAT, sizeof(GLfloat) * 2, vertices.data());
|
||||||
|
glTexCoordPointer(2, GL_FLOAT, sizeof(GLfloat) * 2, texcoords.data());
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, vertices.size() * 6);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
glColor4f(1, 1, 1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
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 J2D::DrawString(const Color3& color, const std::string& text, float x, float y, float scale, u32 size, const Font& font) {
|
||||||
|
J2D::DrawString(Color4::FromColor3(color, 255), text, x, y, scale, size, font);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void J3D::DrawString(const Color4& color, const std::string& text, const Vector3& pos, const Vector3& angle, float scale, u32 size, const Font& font) {
|
||||||
//TODO figure out what the scale should actually be mathematically.
|
//TODO figure out what the scale should actually be mathematically.
|
||||||
scale = scale * 0.002f;
|
scale = scale * 0.002f;
|
||||||
scale = -scale;
|
scale = -scale;
|
||||||
@@ -141,14 +168,14 @@ namespace JGL {
|
|||||||
float x = pos.x;
|
float x = pos.x;
|
||||||
float y = pos.y;
|
float y = pos.y;
|
||||||
float z = pos.z;
|
float z = pos.z;
|
||||||
std::vector<GLuint> textures(text.length());;
|
std::vector<GLuint> textures(text.length());
|
||||||
glUseProgram(0); // Fixed-function pipeline.
|
glUseProgram(0); // Fixed-function pipeline.
|
||||||
glColor4f(color.r, color.g, color.b, 1.0f);
|
glColor4ubv(color.ptr());
|
||||||
|
|
||||||
Font font;
|
//Font font;
|
||||||
for (auto& f : faces)
|
//for (auto& f : Font::GetLoadedFonts())
|
||||||
if (f.index == font_index)
|
//if (f.index == font.index)
|
||||||
font = f;
|
//font = f;
|
||||||
if (font.face == NULL) {
|
if (font.face == NULL) {
|
||||||
std::cout << "null font" << std::endl;
|
std::cout << "null font" << std::endl;
|
||||||
return;
|
return;
|
||||||
@@ -216,8 +243,8 @@ namespace JGL {
|
|||||||
for (unsigned int& texture : textures)
|
for (unsigned int& texture : textures)
|
||||||
glDeleteTextures(1, &texture);
|
glDeleteTextures(1, &texture);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0); // Unbind texture
|
glBindTexture(GL_TEXTURE_2D, 0); // Unbind texture_handle
|
||||||
|
glColor4f(1, 1, 1, 1);
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
177
src/JGL/Texture.cpp
Normal file
177
src/JGL/Texture.cpp
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
#include <JGL/Texture.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace ReTexture;
|
||||||
|
|
||||||
|
namespace JGL
|
||||||
|
{
|
||||||
|
Texture::Texture(const std::string& file, const ReTexture::TextureFlag& flags, TextureFilteringMode filtering_mode, TextureWrappingMode wrapping_mode)
|
||||||
|
{
|
||||||
|
auto *t = new ReTexture::SoftwareTexture(file, flags);
|
||||||
|
|
||||||
|
|
||||||
|
load(t, {(float) t->getWidth(), (float) t->getHeight()}, t->getTextureFormat(), filtering_mode,
|
||||||
|
wrapping_mode);
|
||||||
|
texture_flags = flags;
|
||||||
|
|
||||||
|
delete t;
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture::Texture(const std::string& file, TextureFilteringMode filtering_mode, TextureWrappingMode wrapping_mode) {
|
||||||
|
auto *t = new SoftwareTexture(file);
|
||||||
|
|
||||||
|
load(t, {(float) t->getWidth(), (float) t->getHeight()}, t->getTextureFormat(), filtering_mode,
|
||||||
|
wrapping_mode);
|
||||||
|
texture_flags = TextureFlag::NONE;
|
||||||
|
|
||||||
|
delete t;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Texture::load(SoftwareTexture *software_texture, const Vector2& size, const TextureFormat& format,
|
||||||
|
TextureFilteringMode filtering_mode, TextureWrappingMode wrapping_mode) {
|
||||||
|
glGenTextures(1,& texture_handle);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture_handle);
|
||||||
|
|
||||||
|
if (format == TextureFormat::RGBA)
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (int) size.x, (int) size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||||
|
software_texture->pixelData.data());
|
||||||
|
|
||||||
|
else if (format == TextureFormat::RGB)
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, (int) size.x, (int) size.y, 0, GL_RGB, GL_UNSIGNED_BYTE,
|
||||||
|
software_texture->pixelData.data());
|
||||||
|
|
||||||
|
if (wrapping_mode == TextureWrappingMode::CLAMP_TO_EDGE)
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE),
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
|
else if (wrapping_mode == TextureWrappingMode::REPEAT)
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT),
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
|
|
||||||
|
else if (wrapping_mode == TextureWrappingMode::MIRRORED_REPEAT)
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT),
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
|
||||||
|
|
||||||
|
else if (wrapping_mode == TextureWrappingMode::CLAMP_TO_BORDER)
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER),
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
||||||
|
if (filtering_mode == TextureFilteringMode::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 == TextureFilteringMode::BILINEAR)
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR),
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
|
else if (filtering_mode == TextureFilteringMode::MIPMAP_NEAREST ||
|
||||||
|
filtering_mode == TextureFilteringMode::MIPMAP_BILINEAR ||
|
||||||
|
filtering_mode == TextureFilteringMode::MIPMAP_TRILINEAR) {
|
||||||
|
//3 mipmap levels.
|
||||||
|
auto *m1 = new SoftwareTexture(software_texture->downscale(2));
|
||||||
|
auto *m2 = new SoftwareTexture(software_texture->downscale(4));
|
||||||
|
auto *m3 = new SoftwareTexture(software_texture->downscale(8));
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 3);
|
||||||
|
|
||||||
|
if (format == TextureFormat::RGBA) {
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, m1->getWidth(), m1->getHeight(), 0, GL_RGBA,
|
||||||
|
GL_UNSIGNED_BYTE, m1->pixelData.data());
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, m2->getWidth(), m2->getHeight(), 0, GL_RGBA,
|
||||||
|
GL_UNSIGNED_BYTE, m2->pixelData.data());
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA, m3->getWidth(), m3->getHeight(), 0, GL_RGBA,
|
||||||
|
GL_UNSIGNED_BYTE, m3->pixelData.data());
|
||||||
|
} else if (format == TextureFormat::RGB) {
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB, m1->getWidth(), m1->getHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE,
|
||||||
|
m1->pixelData.data());
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 2, GL_RGB, m2->getWidth(), m2->getHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE,
|
||||||
|
m2->pixelData.data());
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 3, GL_RGB, m3->getWidth(), m3->getHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE,
|
||||||
|
m3->pixelData.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filtering_mode == TextureFilteringMode::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 == TextureFilteringMode::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 == TextureFilteringMode::MIPMAP_TRILINEAR)
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR),
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
|
delete m1;
|
||||||
|
delete m2;
|
||||||
|
delete m3;
|
||||||
|
}
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
texture_size = size;
|
||||||
|
texture_format = format;
|
||||||
|
texture_filtering_mode = filtering_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Color4> JGL::Texture::GetPixelData() const {
|
||||||
|
std::vector<Color4> result((size_t) (texture_size.x * texture_size.y));
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture_handle);
|
||||||
|
|
||||||
|
if (texture_format == TextureFormat::RGBA) {
|
||||||
|
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, result.data());
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
//if RGB
|
||||||
|
std::vector<Color3> color3((size_t) (texture_size.x * texture_size.y));
|
||||||
|
|
||||||
|
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, color3.data());
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
for (const auto& c: color3)
|
||||||
|
result.emplace_back(c);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Texture::Erase() {
|
||||||
|
if (texture_handle != 0)
|
||||||
|
glDeleteTextures(1,& texture_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint Texture::GetGLTextureHandle() const {
|
||||||
|
return texture_handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2 Texture::GetDimensions() const {
|
||||||
|
return texture_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureFlag Texture::GetFlags() const {
|
||||||
|
return texture_flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureFormat Texture::GetFormat() const {
|
||||||
|
return texture_format;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureFilteringMode Texture::GetFilteringMode() const {
|
||||||
|
return texture_filtering_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureWrappingMode Texture::GetWrappingMode() const {
|
||||||
|
return texture_wrapping_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
SoftwareTexture Texture::GetSoftwareTexture() const {
|
||||||
|
std::vector<unsigned char> software_pixel_data((GetDimensions().x * GetDimensions().y) * 4);
|
||||||
|
|
||||||
|
memcpy(software_pixel_data.data(), GetPixelData().data(), (GetDimensions().x * GetDimensions().y) * 4);
|
||||||
|
return {software_pixel_data, TextureFormat::RGBA, static_cast<unsigned int>(GetDimensions().x), static_cast<unsigned int>(GetDimensions().y)};
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture::Texture(SoftwareTexture* software_texture, TextureFilteringMode filtering_mode, TextureWrappingMode wrapping_mode) {
|
||||||
|
load(software_texture, {static_cast<float>(software_texture->getWidth()), static_cast<float>(software_texture->getHeight())}, software_texture->getTextureFormat(), filtering_mode, wrapping_mode);
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user