Compare commits
11 Commits
Prerelease
...
Prerelease
Author | SHA1 | Date | |
---|---|---|---|
b86377a092 | |||
5fc4914180 | |||
58e432b9c3 | |||
41fa634da1 | |||
9d6d256e80 | |||
0e22bc721a | |||
881d031f3c | |||
9e3e0c949f | |||
1526a101c3 | |||
f6e8875eb9 | |||
9903fc19c9 |
@@ -27,12 +27,12 @@ CPMAddPackage(
|
||||
|
||||
CPMAddPackage(
|
||||
NAME ReWindow
|
||||
URL https://git.redacted.cc/Redacted/ReWindow/archive/Prerelease-13.zip
|
||||
URL https://git.redacted.cc/Redacted/ReWindow/archive/Prerelease-15.zip
|
||||
)
|
||||
|
||||
CPMAddPackage(
|
||||
NAME GLAD
|
||||
URL https://git.redacted.cc/Redacted/glad/archive/v2.1ext_mt.zip
|
||||
URL https://git.redacted.cc/Redacted/glad/archive/v2.1ext_fbo.zip
|
||||
)
|
||||
|
||||
CPMAddPackage(
|
||||
@@ -80,16 +80,16 @@ endif()
|
||||
|
||||
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)
|
||||
#Don't expose these ones.
|
||||
include_directories(${ReWindow_SOURCE_DIR}/include)
|
||||
|
||||
target_include_directories(JGL PUBLIC
|
||||
${PROJECT_SOURCE_DIR}/include
|
||||
${OPENGL_INCLUDE_DIRS}
|
||||
${ReTexture_SOURCE_DIR}/include
|
||||
${mcolor_SOURCE_DIR}/include
|
||||
${J3ML_SOURCE_DIR}/include
|
||||
${Event_SOURCE_DIR}/include
|
||||
${ReWindow_SOURCE_DIR}/include
|
||||
${glad_SOURCE_DIR}/include
|
||||
${jlog_SOURCE_DIR}/include
|
||||
)
|
||||
@@ -100,13 +100,13 @@ add_executable(JGL_Demo main.cpp)
|
||||
if (UNIX AND NOT APPLE)
|
||||
target_include_directories(JGL PRIVATE ${FREETYPE_INCLUDE_DIRS})
|
||||
target_link_libraries(JGL PRIVATE ${FREETYPE_LIBRARIES})
|
||||
target_link_libraries(JGL PUBLIC ${OPENGL_LIBRARIES} mcolor J3ML ReWindowLibrary glad jlog Event ReTexture)
|
||||
target_link_libraries(JGL PUBLIC ${OPENGL_LIBRARIES} mcolor J3ML glad jlog Event ReTexture)
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
target_include_directories(JGL PRIVATE ${freetype_SOURCE_DIR}/include)
|
||||
target_link_libraries(JGL PRIVATE freetype)
|
||||
target_link_libraries(JGL PUBLIC ${OPENGL_LIBRARIES} mcolor J3ML ReWindowLibrary glad jlog Event ReTexture)
|
||||
target_link_libraries(JGL PUBLIC ${OPENGL_LIBRARIES} mcolor J3ML glad jlog Event ReTexture)
|
||||
endif()
|
||||
|
||||
target_link_libraries(JGL_Demo PUBLIC JGL)
|
||||
target_link_libraries(JGL_Demo PUBLIC JGL ReWindowLibrary)
|
||||
|
@@ -13,61 +13,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <Color3.hpp>
|
||||
#include <Color4.hpp>
|
||||
#include <Colors.hpp>
|
||||
#include <JGL/types/Texture.h>
|
||||
#include <JGL/types/enums.h>
|
||||
#include <JGL/types/Enums.h>
|
||||
#include <JGL/types/FontCache.h>
|
||||
#include <JGL/types/Font.h>
|
||||
#include <JGL/types/RenderTarget.h>
|
||||
#include <J3ML/LinearAlgebra.hpp>
|
||||
#include <J3ML/LinearAlgebra/Vector2.hpp>
|
||||
#include <J3ML/LinearAlgebra/Vector3.hpp>
|
||||
#include <J3ML/Geometry/Sphere.hpp>
|
||||
#include <J3ML/Geometry/Capsule.hpp>
|
||||
#include <J3ML/Geometry/TriangleMesh.hpp>
|
||||
#include <JGL/Logger.h>
|
||||
#include <J3ML/Geometry/Triangle2D.hpp>
|
||||
|
||||
|
||||
/// OpenGL Wrapper for rendering 2D graphics primitives in both a 2D and 3D context
|
||||
/// OpenGL Wrapper for rendering 2D & 3D graphics in both a 2D and 3D context.
|
||||
namespace JGL {
|
||||
using namespace J3ML::LinearAlgebra;
|
||||
using namespace J3ML::Geometry;
|
||||
|
||||
/// TODO: Implement HSV and other color representation conversions
|
||||
struct HSV {
|
||||
float hue;
|
||||
float saturation;
|
||||
float value;
|
||||
};
|
||||
|
||||
/// TODO: Migrate to using J3ML's definition once finished (hint hint)
|
||||
struct Triangle2D
|
||||
{
|
||||
Vector2 A;
|
||||
Vector2 B;
|
||||
Vector2 C;
|
||||
};
|
||||
|
||||
void Update(const Vector2& window_size);
|
||||
void PurgeFontCache();
|
||||
|
||||
// TODO: Implement
|
||||
void SetActiveFont(const Font& font);
|
||||
|
||||
// TODO: Overrides specifically for Color3 are not **strictly** necessary, Color3 and Color4 should implicitly convert back and forth.
|
||||
|
||||
inline void PurgeFontCache() { fontCache.purgeCache(); }
|
||||
std::vector<GLfloat> OpenGLPerspectiveProjectionRH(float fovY, float aspect, float z_near, float z_far);
|
||||
|
||||
/// Drawing functions for primitive 2D Shapes.
|
||||
/// Each function is overloaded with Color3 and Color4 for optional transparency.
|
||||
namespace J2D {
|
||||
/// Open a 2-D rendering context with the underlying graphics system (In this case & by default OpenGL).
|
||||
/// Open a 2-D rendering context with the underlying graphics system (In this case& by default OpenGL).
|
||||
/// @note This call may not strictly be necessary on some setups, but is provided to keep the API constant.
|
||||
/// It is recommended to always open a JGL 2D context to render your content, then close when completed.
|
||||
/// This keeps our code from, say, clobbering the OpenGL rendering context driving 3D content in between our calls.
|
||||
void Begin();
|
||||
/// Closes a 2-D rendering context with the underlying graphics system (In this case & by default OpenGL).
|
||||
void Begin(RenderTarget* render_target = nullptr, bool clear_buffers = false);
|
||||
/// Closes a 2-D rendering context with the underlying graphics system (In this case& by default OpenGL).
|
||||
/// @see Begin().
|
||||
void End();
|
||||
|
||||
@@ -86,12 +61,23 @@ namespace JGL {
|
||||
void DrawLine(const Color4& color, float x1, float y1, float x2, float y2, float thickness = 1);
|
||||
|
||||
///Draws a line with a gradient that transitions across it.
|
||||
void DrawGradientLine(const Color4& color1, const Color4& color2, const Vector2& A, const Vector2& B, float thickness = 1);
|
||||
void DrawGradientLine(const Color4& color1, const Color4& color2, float x, float y, float w, float h, float thickness = 1);
|
||||
void DrawGradientLine(const Color4& color_a, const Color4& color_b, const Vector2& A, const Vector2& B, float thickness = 1);
|
||||
void DrawGradientLine(const Color4& color_a, const Color4& color_b, float x, float y, float w, float h, float thickness = 1);
|
||||
|
||||
/// Draws an outline of a rectangle on the screen.
|
||||
void OutlineRect(const Color4& color, const Vector2& pos, const Vector2& size, float thickness = 1);
|
||||
|
||||
/// Draws a filled rectangle on the screen.
|
||||
void FillRect(const Color4& color, const Vector2& pos, const Vector2& size);
|
||||
|
||||
/// Draws a filled rectangle where the color transitions across it.
|
||||
void FillGradientRect(const Color4& color1, const Color4& color2, const Direction& gradient, const Vector2& pos, const Vector2& size);
|
||||
|
||||
/// Draws a filled rectangle with rounded corners on the screen.
|
||||
void FillRoundedRect(const Color4& color, const Vector2& pos, const Vector2& size, float radius = 5, unsigned int subdivisions = 8);
|
||||
|
||||
void DrawRenderTargetAsSprite(const RenderTarget& render_target, const Vector2& position, float rad_rotation = 0, const Vector2& origin = Vector2(0 , 0),
|
||||
const Vector2& scale = Vector2(1, 1), const Color4& color = Colors::White, Direction inversion = Direction::None);
|
||||
/// Draws a sprite to the screen by passing a G̶L̶u̶i̶n̶t̶ JGL Texture that represents a handle to a loaded texture.
|
||||
/// @param texture
|
||||
/// @param position
|
||||
@@ -102,14 +88,14 @@ namespace JGL {
|
||||
/// @param inversion inverts the texture only.
|
||||
/// @see class Texture
|
||||
void DrawSprite(const Texture& texture, const Vector2& position, float rad_rotation = 0, const Vector2& origin = Vector2(0,0),
|
||||
const Vector2& scale = Vector2(1,1), const Color4& color = Colors::White, Inversion inversion = Inversion::None);
|
||||
const Vector2& scale = Vector2(1,1), const Color4& color = Colors::White, Direction inversion = Direction::None);
|
||||
void DrawSprite(const Texture& texture,
|
||||
float positionX, float positionY,
|
||||
float rad_rotation = 0,
|
||||
float originX = 0, float originY = 0,
|
||||
float scaleX = 1, float scaleY = 1,
|
||||
const Color4& color = Colors::White,
|
||||
Inversion inversion = Inversion::None);
|
||||
Direction inversion = Direction::None);
|
||||
|
||||
/// Draws a piece of a sprite to the screen, similar to DrawSprite.
|
||||
/// @param texture
|
||||
@@ -121,36 +107,20 @@ namespace JGL {
|
||||
/// @param color
|
||||
/// @param inversion
|
||||
void DrawPartialSprite(const Texture& texture, const Vector2& position, const Vector2& sub_texture_position, const Vector2& sub_texture_size, float rad_rotation = 0,
|
||||
const Vector2& origin = Vector2(0,0), const Vector2& scale = Vector2(1, 1), const Color4& color = Colors::White, Inversion inversion = Inversion::None);
|
||||
const Vector2& origin = Vector2(0,0), const Vector2& scale = Vector2(1, 1), const Color4& color = Colors::White, Direction inversion = Direction::None);
|
||||
void DrawPartialSprite(const Texture& texture, float positionX, float positionY, float sub_texture_positionX, float sub_texture_positionY, unsigned int sub_texture_sizeX, unsigned int sub_texture_sizeY,
|
||||
float rad_rotation = 0, float originX = 0, float originY = 0, float scaleX = 1, float scaleY = 1, const Color4& color = Colors::White, Inversion inversion = Inversion::None);
|
||||
float rad_rotation = 0, float originX = 0, float originY = 0, float scaleX = 1, float scaleY = 1, const Color4& color = Colors::White, Direction inversion = Direction::None);
|
||||
|
||||
|
||||
/// Draws a non axis-aligned fill rect to the screen.
|
||||
/// To save v-ram, Use if a sprite would be identical if mirrored horizontally, vertically, or both. For example, a circle.
|
||||
/// Assumes the input texture is the top left quadrant. You can use "SoftwareTexture" to invert it correctly so that's the case.
|
||||
/// @param texture
|
||||
/// @param position
|
||||
/// @param mirror_axis The axes to mirror across, Vertical and Horizontal or both only.
|
||||
/// @param rad_rotation The rotation of the final result.
|
||||
/// @param origin The point at which transformations are done about.
|
||||
/// @param scale
|
||||
/// @param color
|
||||
/// @param v1 top-left vertex.
|
||||
/// @param v2 bottom-left vertex.
|
||||
/// @param v3 bottom-right vertex.
|
||||
/// @param v4 top-right vertex.
|
||||
void FillQuad(const Color4& color, const Vector2& v1, const Vector2& v2, const Vector2& v3, const Vector2& v4);
|
||||
|
||||
/// Draws a non axis-aligned outline rect to the screen.
|
||||
/// @param color
|
||||
/// @param v1 top-left vertex.
|
||||
/// @param v2 bottom-left vertex.
|
||||
/// @param v3 bottom-right vertex.
|
||||
/// @param v4 top-right vertex.
|
||||
/// @param thickness the thickness of the GL_LINES to be connected together.
|
||||
void OutlineQuad(const Color4& color, const Vector2& v1, const Vector2& v2, const Vector2& v3, const Vector2& v4, float thickness = 1);
|
||||
|
||||
/// Draws a filled rectangle on the screen.
|
||||
void FillRect(const Color4& color, const Vector2& pos, const Vector2& size);
|
||||
|
||||
/// Draws a filled rectangle where the color transitions across it.
|
||||
void FillGradientRect(const Color4& color1, const Color4& color2, const Gradient& gradient, const Vector2& pos, const Vector2& size);
|
||||
|
||||
/// 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 DrawMirrorSprite(const Texture& texture, const Vector2& position, Direction mirror_axis = Direction::Horizontal | Direction::Vertical, float rad_rotation = 0, const Vector2& origin = Vector2(0,0), const Vector2& scale = Vector2(1,1), const Color4& color = Colors::White);
|
||||
|
||||
/// Draws an outline of a circle on the screen.
|
||||
void OutlineCircle(const Color4& color, const Vector2& center, float radius, unsigned int subdivisions = 16, float thickness = 1);
|
||||
@@ -172,16 +142,15 @@ namespace JGL {
|
||||
/// 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);
|
||||
|
||||
|
||||
/// Draws a text string on the screen with a given point-size and font.
|
||||
void DrawString(const Color4& color, const std::string& text, float x, float y, float scale, u32 size, const Font& font);
|
||||
|
||||
void DrawCubicBezierCurve(const Color4& color, const Vector2& controlA, const Vector2& pointA, const Vector2& pointB, const Vector2& controlB,
|
||||
int subdivisions = 10, float thickness = 1);
|
||||
|
||||
/// Draws a series of points where the last point always connects to the first point.
|
||||
void OutlinePolygon(const Color4& color, const std::vector<Vector2>& points, float thickness = 1);
|
||||
|
||||
/// Draws a text string on the screen with a given point-size and font.
|
||||
void DrawString(const Color4& color, const std::string& text, float x, float y, float scale, u32 size, const Font& font);
|
||||
|
||||
/// TODO Implement the following. These ones are going to be extremely annoying.
|
||||
void FillPolygon(const Color4& color, const std::vector<Vector2>& points);
|
||||
void FillTexturedPolygon();
|
||||
|
@@ -8,4 +8,5 @@ namespace JGL::Logger {
|
||||
extern GenericLogger Fatal;
|
||||
extern GenericLogger Debug;
|
||||
extern GenericLogger Error;
|
||||
|
||||
}
|
36
include/JGL/types/Enums.h
Normal file
36
include/JGL/types/Enums.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
namespace JGL {
|
||||
enum class Direction : u8 {
|
||||
None = 0,
|
||||
Vertical = 1,
|
||||
Horizontal = 2,
|
||||
Diagonal_NWSE = 3, // North West -> South East.
|
||||
Diagonal_SWNE = 4 // South West -> North East.
|
||||
};
|
||||
|
||||
inline Direction operator|(Direction a, Direction b) {
|
||||
return static_cast<Direction>(static_cast<int>(a) | static_cast<int>(b));
|
||||
}
|
||||
|
||||
inline bool operator&(Direction a, Direction b) {
|
||||
return (u8)a & (u8)b;
|
||||
}
|
||||
|
||||
static std::string to_string(JGL::Direction direction) {
|
||||
switch (direction) {
|
||||
case JGL::Direction::None:
|
||||
return "None";
|
||||
case JGL::Direction::Vertical:
|
||||
return "Vertical";
|
||||
case JGL::Direction::Horizontal:
|
||||
return "Horizontal";
|
||||
case JGL::Direction::Diagonal_NWSE:
|
||||
return "Diagonal_NWSE";
|
||||
case JGL::Direction::Diagonal_SWNE:
|
||||
return "Diagonal_SWNE";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,9 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <glad/glad.h>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <unordered_map>
|
||||
|
||||
|
||||
/// TODO: FontCache mechanism works amazing, but makes no fucking sense
|
||||
@@ -27,13 +27,13 @@ public:
|
||||
//CachedGlyph(GLuint texture_id, char c);
|
||||
CachedGlyph(char c, std::array<GLfloat, 12> texcoords, float x2o, float y2o, float w, float h, float advX, float advY);
|
||||
char getCharacter();
|
||||
[[nodiscard]] const std::array<GLfloat, 12> getTexCoords() const;
|
||||
[[nodiscard]] std::array<GLfloat, 12> getTexCoords() const;
|
||||
};
|
||||
|
||||
/// Represents a Font object as it exists in the font-cache.
|
||||
class JGL::CachedFont {
|
||||
private:
|
||||
std::map<char, CachedGlyph*> glyphs;
|
||||
std::unordered_map<char, CachedGlyph*> glyphs;
|
||||
GLuint texture = 0;
|
||||
GLsizei texture_width = 0, texture_height = 0;
|
||||
unsigned int font_size = 0;
|
||||
@@ -43,7 +43,7 @@ public:
|
||||
unsigned int getFontSize();
|
||||
unsigned int getFontIndex();
|
||||
CachedGlyph* getGlyph(char c);
|
||||
std::map<char, CachedGlyph*> getGlyphs();
|
||||
std::unordered_map<char, CachedGlyph*> getGlyphs();
|
||||
const GLuint* getTexture();
|
||||
[[nodiscard]] GLsizei getTextureWidth() const;
|
||||
[[nodiscard]] GLsizei getTextureHeight() const;
|
||||
|
37
include/JGL/types/RenderTarget.h
Normal file
37
include/JGL/types/RenderTarget.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
#include <glad/glad.h>
|
||||
#include <JGL/types/Texture.h>
|
||||
#include <Color4.hpp>
|
||||
#include <Colors.hpp>
|
||||
|
||||
namespace JGL {
|
||||
class RenderTarget;
|
||||
}
|
||||
|
||||
class JGL::RenderTarget {
|
||||
private:
|
||||
Color4 clear_color{0,0,0,0};
|
||||
/// "Size" in this sense is the "Renderable Area" because OpenGL textures behave strangely if they're not square.
|
||||
Vector2 size{0, 0};
|
||||
bool using_depth = false;
|
||||
GLuint framebuffer_object = 0;
|
||||
GLuint depth_buffer = 0;
|
||||
Texture* texture = nullptr;
|
||||
public:
|
||||
static GLuint GetActiveGLFramebufferHandle();
|
||||
static void SetActiveGLRenderTarget(const RenderTarget& render_target);
|
||||
public:
|
||||
[[nodiscard]] Vector2 GetDimensions() const;
|
||||
[[nodiscard]] Texture* GetJGLTexture() const;
|
||||
[[nodiscard]] GLuint GetGLTextureHandle() const;
|
||||
[[nodiscard]] GLuint GetGLFramebufferObjectHandle() const;
|
||||
[[nodiscard]] GLuint GetGLDepthBufferHandle() const;
|
||||
[[nodiscard]] Color4 GetClearColor() const;
|
||||
public:
|
||||
/// Create a render target for a texture that already exists. For decals.
|
||||
explicit RenderTarget(const Texture& texture, const Color4& clear_color = Colors::Black, bool use_depth = false);
|
||||
/// Create a Render Target with a brand new texture. Want to render JGL elements onto a texture and display it as a sprite?
|
||||
explicit RenderTarget(const Vector2& size, const Color4& clear_color = Colors::Black, bool use_depth = false);
|
||||
|
||||
void Erase();
|
||||
};
|
@@ -32,18 +32,23 @@ namespace JGL {
|
||||
ReTexture::TextureFormat texture_format;
|
||||
TextureFilteringMode texture_filtering_mode;
|
||||
TextureWrappingMode texture_wrapping_mode;
|
||||
virtual void load(SoftwareTexture* software_texture, const Vector2& size, const TextureFormat& format, TextureFilteringMode filtering_mode, TextureWrappingMode wrapping_mode);
|
||||
void load(SoftwareTexture* software_texture, const Vector2& size, const TextureFormat& format, TextureFilteringMode filtering_mode, TextureWrappingMode wrapping_mode);
|
||||
public:
|
||||
///Load a texture from a file,
|
||||
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);
|
||||
/* Initialize a texture filled with trash data
|
||||
this is primarily for the RenderTarget */
|
||||
explicit Texture(const Vector2& size);
|
||||
Texture() = default;
|
||||
public:
|
||||
GLuint GetGLTextureHandle() const;
|
||||
Vector2 GetDimensions() const;
|
||||
TextureFilteringMode GetFilteringMode() const;
|
||||
TextureFlag GetFlags() const;
|
||||
TextureFormat GetFormat() const;
|
||||
std::vector<Color4> GetPixelData() const;
|
||||
[[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;
|
||||
|
||||
void SetTextureHandle(GLuint handle);
|
||||
void Erase();
|
||||
|
68
include/JGL/types/VRamList.h
Normal file
68
include/JGL/types/VRamList.h
Normal file
@@ -0,0 +1,68 @@
|
||||
#pragma once
|
||||
#include <glad/glad.h>
|
||||
#include <J3ML/LinearAlgebra/Vector2.hpp>
|
||||
#include <J3ML/LinearAlgebra/Vector3.hpp>
|
||||
#include <J3ML/LinearAlgebra/Vector4.hpp>
|
||||
#include <JGL/logger/logger.h>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
namespace JGL {
|
||||
class VRamList;
|
||||
}
|
||||
|
||||
/// A wrapper for VBO, Storing texture coordinates or vertices or indices in vram.
|
||||
class JGL::VRamList {
|
||||
private:
|
||||
GLuint list_handle = 0;
|
||||
long size = 0;
|
||||
bool element_array_buffer = false;
|
||||
|
||||
void load(const GLfloat* data, const long& size);
|
||||
void load(const GLuint* data, const long& size);
|
||||
public:
|
||||
VRamList() = default;
|
||||
VRamList(const GLfloat* data, const long& size);
|
||||
VRamList(Vector2* data, const long& size);
|
||||
VRamList(Vector3* data, const long& size);
|
||||
VRamList(Vector4* data, const long& size);
|
||||
VRamList(const GLuint* data, const long& size);
|
||||
public:
|
||||
[[nodiscard]] GLuint GetHandle() const;
|
||||
/// Returns the number of GLfloat or GLuint in the list.
|
||||
[[nodiscard]] long GetSize() const;
|
||||
/// Returns the size of the data in bytes.
|
||||
[[nodiscard]] long GetDataSize() const;
|
||||
[[nodiscard]] bool IsIntegerArray() const;
|
||||
[[nodiscard]] bool IsFloatArray() const;
|
||||
void Erase();
|
||||
|
||||
/// Get list data back from the GPU. This is *very* slow.
|
||||
/// It's not recommended you use this in your normal rendering routines.
|
||||
template <typename T>
|
||||
[[nodiscard]] std::vector<T> GetListData() const {
|
||||
GLenum buffer_type;
|
||||
GLint current_buffer = 0;
|
||||
|
||||
if constexpr (std::is_same<T, GLfloat>::value)
|
||||
buffer_type = GL_ARRAY_BUFFER,
|
||||
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, ¤t_buffer);
|
||||
else if constexpr (std::is_same<T, GLuint>::value)
|
||||
buffer_type = GL_ELEMENT_ARRAY_BUFFER,
|
||||
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, ¤t_buffer);
|
||||
else {
|
||||
Logger::Fatal("Typename T must be either GLfloat or GLuint.");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
glBindBuffer(buffer_type, list_handle);
|
||||
std::vector<T> data(size);
|
||||
memcpy(data.data(), (T*) glMapBuffer(buffer_type, GL_READ_ONLY), size * sizeof(T));
|
||||
glUnmapBuffer(buffer_type);
|
||||
glBindBuffer(buffer_type, current_buffer);
|
||||
|
||||
return data;
|
||||
}
|
||||
};
|
@@ -1,33 +0,0 @@
|
||||
#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;
|
||||
}
|
||||
}
|
89
main.cpp
89
main.cpp
@@ -4,9 +4,6 @@
|
||||
#include <Colors.hpp>
|
||||
#include <chrono>
|
||||
#include <J3ML/LinearAlgebra/Vector2.hpp>
|
||||
#include <JGL/types/Font.h>
|
||||
#include <JGL/Logger.h>
|
||||
#include <ReTexture/Texture.h>
|
||||
|
||||
using J3ML::LinearAlgebra::Vector2;
|
||||
using namespace JGL;
|
||||
@@ -26,53 +23,31 @@ public:
|
||||
|
||||
void Grab() {
|
||||
if (hovered)
|
||||
{
|
||||
dragging = true;
|
||||
}
|
||||
}
|
||||
void Release() {
|
||||
dragging = false;
|
||||
}
|
||||
|
||||
void Update(const Vector2& mouse)
|
||||
{
|
||||
void Update(const Vector2& mouse) {
|
||||
if (dragging)
|
||||
{
|
||||
position = position.Lerp(mouse, 0.25f);
|
||||
}
|
||||
|
||||
if (mouse.Distance(position) < range)
|
||||
{
|
||||
hovered = true;
|
||||
} else
|
||||
{
|
||||
hovered = false;
|
||||
}
|
||||
|
||||
hovered = mouse.Distance(position) < range;
|
||||
}
|
||||
|
||||
void Draw()
|
||||
{
|
||||
void Draw() {
|
||||
if (dragging)
|
||||
{
|
||||
J2D::DrawPoint(Colors::White, position, 4.f);
|
||||
} else if (hovered)
|
||||
{
|
||||
else if (hovered)
|
||||
J2D::DrawPoint(Colors::Reds::Crimson, position, 6.f);
|
||||
} else
|
||||
{
|
||||
else
|
||||
J2D::DrawPoint(Colors::Reds::Salmon, position, 3.f);
|
||||
}
|
||||
|
||||
J2D::DrawString(Colors::White, std::format("{:.1f},{:.1f}", position.x, position.y), position.x, position.y, 1.f, 10, FreeSans);
|
||||
}
|
||||
protected:
|
||||
private:
|
||||
};
|
||||
|
||||
|
||||
Texture* image;
|
||||
|
||||
class Camera {
|
||||
public:
|
||||
Vector3 position = {0,0,0};
|
||||
@@ -111,13 +86,14 @@ struct point {
|
||||
GLfloat t;
|
||||
};
|
||||
|
||||
|
||||
|
||||
Gizmo a({250, 150});
|
||||
Gizmo b({200, 250});
|
||||
Gizmo c({350, 300});
|
||||
Gizmo d({450, 250});
|
||||
|
||||
Texture* image;
|
||||
RenderTarget* j2d_render_target;
|
||||
|
||||
class JGLDemoWindow : public ReWindow::RWindow
|
||||
{
|
||||
public:
|
||||
@@ -136,20 +112,18 @@ public:
|
||||
glDepthFunc(GL_LESS);
|
||||
glDepthMask(GL_TRUE);
|
||||
image = new Texture("assets/sprites/Re3D.png", TextureFilteringMode::BILINEAR);
|
||||
j2d_render_target = new RenderTarget({500, 500}, {255,0,0,0});
|
||||
}
|
||||
|
||||
Vector3 textAngle = {0,0,0};
|
||||
float fov = 90;
|
||||
float sprite_radians = 0;
|
||||
bool fov_increasing = true;
|
||||
unsigned long long frames = 0;
|
||||
bool framerate_measurement = false;
|
||||
std::chrono::system_clock::time_point start;
|
||||
float elapsed = 0.0f;
|
||||
std::chrono::high_resolution_clock::time_point start;
|
||||
float fps = 0.0f;
|
||||
|
||||
void display() {
|
||||
if (framerate_measurement)
|
||||
start = std::chrono::high_resolution_clock::now();
|
||||
start = std::chrono::high_resolution_clock::now();
|
||||
|
||||
JGL::Update(getSize());
|
||||
if (fov_increasing)
|
||||
@@ -170,7 +144,8 @@ public:
|
||||
glLoadIdentity();
|
||||
|
||||
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
|
||||
/* if rendering to screen space directly. */
|
||||
|
||||
J3D::Begin();
|
||||
J3D::DrawLine(Colors::Red, {-0.33,-0.125,1}, {-1,-0.125,1});
|
||||
@@ -178,20 +153,20 @@ public:
|
||||
J3D::DrawString(Colors::Red, "JGL Sample Text", {-0.33, -0.1, 1.0f}, 1.f, 32, FreeSans, textAngle, true);
|
||||
J3D::End();
|
||||
|
||||
|
||||
J2D::Begin();
|
||||
J2D::FillQuad(Color4(Colors::Red), {500, 52}, {500, 152}, {600, 152}, {600, 52});
|
||||
J2D::FillRect(Colors::Blue, {0,52}, {100,100});
|
||||
J2D::DrawSprite(*image, {252, 252}, sprite_radians, {0.5, 0.5});
|
||||
J2D::DrawPartialSprite(*image, {200, 252}, image->GetDimensions() * 0.25, image->GetDimensions() * 0.75, sprite_radians, {0.5, 0.5});
|
||||
J2D::DrawSprite(*image, {300, 300}, 0, {0,0}, {1, 1}, Colors::White, Direction::Vertical | Direction::Horizontal);
|
||||
J2D::DrawMirrorSprite(*image, {400, 300}, Direction::Horizontal | Direction::Vertical, sprite_radians, {0.5,0.5}, {1, 1}, Colors::White);
|
||||
J2D::DrawPartialSprite(*image, {225, 300}, image->GetDimensions() * 0.25, image->GetDimensions() * 0.75, sprite_radians, {0.5, 0.5});
|
||||
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, Direction::Diagonal_SWNE, {100,52}, {100,100});
|
||||
J2D::FillRoundedRect(Colors::Red, {200, 52}, {100, 100}, 8, 8);
|
||||
J2D::FillRoundedRect(Colors::Purples::BlueViolet, {300, 52}, {100, 100}, 8, 4);
|
||||
|
||||
J2D::FillCircle(Colors::White, {52, 204}, 50, 24);
|
||||
J2D::OutlineCircle(Colors::White, {153, 204}, 50, 24);
|
||||
|
||||
//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::DrawGradientLine(Colors::Red, Colors::Blue, {105, 375}, {200, 275}, 2);
|
||||
@@ -201,6 +176,7 @@ public:
|
||||
J2D::DrawString(Colors::Green, "Jupteroid Font", 0.f, 0, 1.f, 16, Jupiteroid);
|
||||
J2D::DrawString(Colors::White, "Position: " + std::to_string(camera->position.x) + " " + std::to_string(camera->position.y) + " " + std::to_string(camera->position.z), 0, 16, 1,16, Jupiteroid);
|
||||
J2D::DrawString(Colors::White, "ViewAngle: " + std::to_string(camera->angle.x) + " " + std::to_string(camera->angle.y) + " " + std::to_string(camera->angle.z), 0, 33, 1,16, Jupiteroid);
|
||||
J2D::DrawString(Colors::White, "Framerate: " + std::to_string((int) fps), 0, 48, 1, 16, Jupiteroid);
|
||||
J2D::OutlinePolygon(Colors::White, {{200, 400}, {220, 420}, {220, 430}, {230, 410}, {200, 400}});
|
||||
//J2D::FillPolygon(Colors::White, {{200, 400}, {220, 420}, {220, 430}, {230, 410}, {200, 400}});
|
||||
J2D::DrawCubicBezierCurve(Colors::Blues::CornflowerBlue,
|
||||
@@ -216,21 +192,16 @@ public:
|
||||
d.Draw();
|
||||
J2D::End();
|
||||
|
||||
if (framerate_measurement) {
|
||||
frames++;
|
||||
std::chrono::system_clock::time_point stop = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<float> frame_time = stop - start;
|
||||
elapsed += frame_time.count();
|
||||
if (elapsed >= 1)
|
||||
std::cout << "Framerate: " << frames << std::endl,
|
||||
frames = 0,
|
||||
elapsed = 0,
|
||||
framerate_measurement = false,
|
||||
setVsyncEnabled(true);
|
||||
} else if (isKeyDown(Keys::One))
|
||||
framerate_measurement = true,
|
||||
frames = 0,
|
||||
setVsyncEnabled(false);
|
||||
//Draw the Render Target that we just drew all that stuff onto.
|
||||
/*
|
||||
J2D::Begin();
|
||||
J2D::DrawRenderTargetAsSprite(*j2d_render_target, {0, 0}, 0, {0.5, 0.5}, {1,1}, Colors::White);
|
||||
J2D::End();
|
||||
*/
|
||||
|
||||
std::chrono::high_resolution_clock::time_point stop = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<float> frame_time = stop - start;
|
||||
fps = 1.0f / frame_time.count();
|
||||
}
|
||||
|
||||
void OnRefresh(float elapsed) override {
|
||||
|
609
src/JGL.cpp
609
src/JGL.cpp
@@ -4,12 +4,16 @@
|
||||
|
||||
#include <JGL/JGL.h>
|
||||
#include <glad/glad.h>
|
||||
#include <Color3.hpp>
|
||||
#include <jlog/Logger.hpp>
|
||||
#include <J3ML/Algorithm/Bezier.hpp>
|
||||
#include <JGL/logger/logger.h>
|
||||
|
||||
JGL::RenderTarget* render_target = nullptr;
|
||||
GLfloat oldColor[4] = {0, 0, 0, 1};
|
||||
GLfloat baseColor[4] = {1, 1, 1, 1};
|
||||
|
||||
GLuint current_fbo = 0;
|
||||
GLint viewport[4] = {0, 0, 0, 0};
|
||||
|
||||
bool inJ2D = false;
|
||||
bool inJ3D = false;
|
||||
bool wasTexture2DEnabled = false;
|
||||
@@ -30,12 +34,26 @@ namespace JGL {
|
||||
glViewport(0, 0, (int) wS.x, (int) wS.y);
|
||||
}
|
||||
|
||||
void J2D::Begin() {
|
||||
#pragma region J2D
|
||||
void J2D::Begin(RenderTarget* rt, bool clear_buffers) {
|
||||
GLfloat old_clear_color[4];
|
||||
if (rt != nullptr) {
|
||||
render_target = rt;
|
||||
glGetFloatv(GL_COLOR_CLEAR_VALUE, old_clear_color);
|
||||
glGetIntegerv(GL_VIEWPORT, viewport);
|
||||
current_fbo = JGL::RenderTarget::GetActiveGLFramebufferHandle();
|
||||
JGL::RenderTarget::SetActiveGLRenderTarget(*rt);
|
||||
}
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glViewport(0, 0, (int) wS.x, (int) wS.y);
|
||||
glOrtho(0, wS.x, wS.y, 0, -1, 1);
|
||||
|
||||
if (rt == nullptr)
|
||||
glViewport(0, 0, (int) wS.x, (int) wS.y),
|
||||
glOrtho(0, wS.x, wS.y, 0, -1, 1);
|
||||
else
|
||||
glOrtho(0, rt->GetDimensions().x, rt->GetDimensions().y, 0, -1, 1);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
@@ -44,7 +62,7 @@ namespace JGL {
|
||||
glGetFloatv(GL_CURRENT_COLOR, oldColor);
|
||||
glColor4fv(baseColor);
|
||||
|
||||
glGetIntegerv(GL_ACTIVE_TEXTURE,& activeTextureUnit);
|
||||
glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTextureUnit);
|
||||
activeTextureUnit = activeTextureUnit - GL_TEXTURE0;
|
||||
|
||||
if (activeTextureUnit != 0)
|
||||
@@ -96,7 +114,13 @@ namespace JGL {
|
||||
|
||||
if (!inJ3D)
|
||||
inJ2D = true;
|
||||
else { jlog::Error("Attempt to Begin J2D inside of J3D context."); }
|
||||
else { Logger::Error("Attempt to Begin J2D inside of J3D context."); }
|
||||
|
||||
if (rt != nullptr && clear_buffers) {
|
||||
glClearColor(rt->GetClearColor().R(), rt->GetClearColor().G(), rt->GetClearColor().B(), rt->GetClearColor().A());
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glClearColor(old_clear_color[0], old_clear_color[1], old_clear_color[2], old_clear_color[3]);
|
||||
}
|
||||
}
|
||||
|
||||
void J2D::End() {
|
||||
@@ -132,228 +156,34 @@ namespace JGL {
|
||||
//Put the draw color back how it was before.
|
||||
glColor4fv(oldColor);
|
||||
|
||||
if (render_target != nullptr) {
|
||||
render_target = nullptr;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, current_fbo);
|
||||
glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
|
||||
}
|
||||
inJ2D = false;
|
||||
}
|
||||
|
||||
void J2D::DrawSprite(const Texture& texture, const Vector2& pos, float rad_rotation, const Vector2& origin, const Vector2& scale, const Color4& color, Inversion inversion) {
|
||||
void J2D::DrawPoint(const Color4& color, const Vector2& coordinates, float radius) {
|
||||
if (!inJ2D)
|
||||
jlog::Error("Drawing J2D element before J2D begin.");
|
||||
Logger::Error("Drawing J2D element before J2D begin.");
|
||||
|
||||
Vector2 vertices[] = {coordinates};
|
||||
|
||||
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;
|
||||
float cos_theta = std::cos(rad_rotation);
|
||||
float sin_theta = std::sin(rad_rotation);
|
||||
|
||||
std::array<Vector2, 4> 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
|
||||
};
|
||||
|
||||
//Rotate the vertices about the origin by float rad_rotation.
|
||||
if (rad_rotation != 0)
|
||||
for (auto& v : vertices)
|
||||
v = { (v.x - pos2.x - offset.x * scale.x) * cos_theta - (v.y - pos2.y - offset.y * scale.y) * sin_theta + pos2.x + offset.x * scale.x, (v.x - pos2.x - offset.x * scale.x) * sin_theta + (v.y - pos2.y - offset.y * scale.y) * cos_theta + pos2.y + offset.y * scale.y};
|
||||
|
||||
|
||||
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.data());
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(Vector2), textureCoordinates.data());
|
||||
glDrawArrays(GL_QUADS, 0, 4);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glColor4fv(baseColor);
|
||||
}
|
||||
|
||||
|
||||
void J2D::DrawSprite(const Texture& texture, float positionX, float positionY, float rad_rotation, float originX, float originY, float scaleX, float scaleY, const Color4& color, Inversion inversion)
|
||||
{
|
||||
DrawSprite(texture,
|
||||
{positionX, positionY},
|
||||
rad_rotation,
|
||||
{originX, originY},
|
||||
{scaleX, scaleY},
|
||||
color, inversion);
|
||||
}
|
||||
|
||||
void J2D::DrawPartialSprite(const Texture& texture, const Vector2& position, const Vector2& sub_texture_position, const Vector2& sub_texture_size, float rad_rotation, const Vector2& origin, const Vector2& scale, const Color4& color, Inversion inversion) {
|
||||
if (!inJ2D)
|
||||
jlog::Error("Drawing J2D element before J2D begin.");
|
||||
|
||||
const Vector2 textureSize = texture.GetDimensions();
|
||||
|
||||
// Calculate texture coordinates (relative to the whole texture)
|
||||
std::array<GLfloat, 8> textureCoordinates = {
|
||||
sub_texture_position.x / textureSize.x,
|
||||
sub_texture_position.y / textureSize.y,
|
||||
sub_texture_position.x / textureSize.x,
|
||||
(sub_texture_position.y + sub_texture_size.y) / textureSize.y,
|
||||
(sub_texture_position.x + sub_texture_size.x) / textureSize.x,
|
||||
(sub_texture_position.y + sub_texture_size.y) / textureSize.y,
|
||||
(sub_texture_position.x + sub_texture_size.x) / textureSize.x,
|
||||
sub_texture_position.y / textureSize.y
|
||||
};
|
||||
|
||||
if (inversion & Inversion::Vertical)
|
||||
std::swap(textureCoordinates[1], textureCoordinates[3]),
|
||||
std::swap(textureCoordinates[5], textureCoordinates[7]);
|
||||
|
||||
if (inversion & Inversion::Horizontal)
|
||||
std::swap(textureCoordinates[0], textureCoordinates[6]),
|
||||
std::swap(textureCoordinates[2], textureCoordinates[4]);
|
||||
|
||||
const Vector2 offset = origin * sub_texture_size;
|
||||
Vector2 pos2 = position - offset * scale;
|
||||
Vector2 scaled_size = scale * sub_texture_size;
|
||||
Vector2 size2 = scaled_size;
|
||||
float cos_theta = std::cos(rad_rotation);
|
||||
float sin_theta = std::sin(rad_rotation);
|
||||
|
||||
std::array<Vector2, 4> vertices =
|
||||
{
|
||||
pos2, // Top-left
|
||||
{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
|
||||
};
|
||||
|
||||
//Rotate the vertices about the origin by float rad_rotation.
|
||||
if (rad_rotation != 0)
|
||||
for (auto& v : vertices)
|
||||
v = { (v.x - pos2.x - offset.x * scale.x) * cos_theta - (v.y - pos2.y - offset.y * scale.y) * sin_theta + pos2.x + offset.x * scale.x, (v.x - pos2.x - offset.x * scale.x) * sin_theta + (v.y - pos2.y - offset.y * scale.y) * cos_theta + pos2.y + offset.y * scale.y};
|
||||
|
||||
glColor4ubv(color.ptr());
|
||||
glBindTexture(GL_TEXTURE_2D, texture.GetGLTextureHandle());
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, textureCoordinates.data());
|
||||
glDrawArrays(GL_QUADS, 0, 4);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glColor4fv(baseColor);
|
||||
}
|
||||
|
||||
void J2D::DrawPartialSprite(const JGL::Texture& texture, float positionX, float positionY, float sub_texture_positionX, float sub_texture_positionY, unsigned int sub_texture_sizeX,
|
||||
unsigned int sub_texture_sizeY, float originX,float originY, float rad_rotation, float scaleX, float scaleY, const Color4& color,JGL::Inversion inversion) {
|
||||
|
||||
J2D::DrawPartialSprite(texture, {positionX, positionY}, {sub_texture_positionX, sub_texture_positionY},
|
||||
{(float) sub_texture_sizeX, (float) sub_texture_sizeY}, rad_rotation, {originX, originY}, {scaleX, scaleY}, color, inversion);
|
||||
}
|
||||
|
||||
void J2D::FillQuad(const Color4& color, const Vector2& v1, const Vector2& v2, const Vector2& v3, const Vector2& v4) {
|
||||
if (!inJ2D)
|
||||
jlog::Error("Drawing J2D element before J2D begin.");
|
||||
|
||||
Vector2 vertices[4] = {v1, v2, v3, v4};
|
||||
|
||||
glPointSize(radius);
|
||||
glColor4ubv(color.ptr());
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
|
||||
glDrawArrays(GL_QUADS, 0, 4);
|
||||
glDrawArrays(GL_POINTS, 0, 1);
|
||||
glColor4fv(baseColor);
|
||||
}
|
||||
|
||||
void J2D::OutlineQuad(const Color4& color, const Vector2& v1, const Vector2& v2, const Vector2& v3, const Vector2& v4, float thickness) {
|
||||
if (!inJ2D)
|
||||
jlog::Error("Drawing J2D element before J2D begin.");
|
||||
|
||||
Vector2 vertices[] = {v1, v2, v3, v4};
|
||||
glLineWidth(thickness);
|
||||
glColor4ubv(color.ptr());
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
|
||||
glDrawArrays(GL_LINE_LOOP, 0, 4);
|
||||
glColor4fv(baseColor);
|
||||
}
|
||||
|
||||
void J2D::FillRect(const Color4& color, const Vector2& pos, const Vector2& size) {
|
||||
if (!inJ2D)
|
||||
jlog::Error("Drawing J2D element before J2D begin.");
|
||||
|
||||
Vector2 vertices[] = {{pos.x, pos.y}, {pos.x, pos.y + size.y}, {pos.x + size.x, pos.y + size.y}, {pos.x + size.x, pos.y}};
|
||||
glColor4ubv(color.ptr());
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
|
||||
glDrawArrays(GL_QUADS, 0, 4);
|
||||
glColor4fv(baseColor);
|
||||
}
|
||||
|
||||
void J2D::FillGradientRect(const Color4& color1, const Color4& color2, const Gradient& gradient, const Vector2& pos, const Vector2& size) {
|
||||
if (!inJ2D)
|
||||
jlog::Error("Drawing J2D element before J2D begin.");
|
||||
|
||||
Vector2 vertices[] = {{pos.x, pos.y}, {pos.x, pos.y + size.y}, {pos.x + size.x, pos.y + size.y}, {pos.x + size.x, pos.y}};
|
||||
std::vector<GLfloat> colors{};
|
||||
|
||||
if (gradient == Gradient::Horizontal)
|
||||
colors = {color1.RedChannelNormalized(), color1.GreenChannelNormalized(), color1.BlueChannelNormalized(), color1.AlphaChannelNormalized(), color1.RedChannelNormalized(), color1.GreenChannelNormalized(), color1.BlueChannelNormalized(), color1.AlphaChannelNormalized(),
|
||||
color2.RedChannelNormalized(), color2.GreenChannelNormalized(), color2.BlueChannelNormalized(), color2.AlphaChannelNormalized(), color2.RedChannelNormalized(), color2.GreenChannelNormalized(), color2.BlueChannelNormalized(), color2.AlphaChannelNormalized()};
|
||||
|
||||
else if (gradient == Gradient::Vertical)
|
||||
colors = {color1.RedChannelNormalized(), color1.GreenChannelNormalized(), color1.BlueChannelNormalized(), color1.AlphaChannelNormalized(), color2.RedChannelNormalized(), color2.GreenChannelNormalized(), color2.BlueChannelNormalized(), color2.AlphaChannelNormalized(),
|
||||
color2.RedChannelNormalized(), color2.GreenChannelNormalized(), color2.BlueChannelNormalized(), color2.AlphaChannelNormalized(), color1.RedChannelNormalized(), color1.GreenChannelNormalized(), color1.BlueChannelNormalized(), color1.AlphaChannelNormalized()};
|
||||
|
||||
else if (gradient == Gradient::DiagonalBottomLeft)
|
||||
colors = {(color1.RedChannelNormalized() + color2.RedChannelNormalized()) / 2.f, (color1.GreenChannelNormalized() + color2.GreenChannelNormalized()) / 2.f, (color1.BlueChannelNormalized() + color2.BlueChannelNormalized()) / 2.f, (color1.AlphaChannelNormalized() + color2.AlphaChannelNormalized()) / 2.f,
|
||||
color1.RedChannelNormalized(), color1.GreenChannelNormalized(), color1.BlueChannelNormalized(), color1.AlphaChannelNormalized(), (color1.RedChannelNormalized() + color2.RedChannelNormalized()) / 2.f, (color1.GreenChannelNormalized() + color2.GreenChannelNormalized()) / 2.f,
|
||||
(color1.BlueChannelNormalized() + color2.BlueChannelNormalized()) / 2.f, (color1.AlphaChannelNormalized() + color2.AlphaChannelNormalized()) / 2.f, color2.RedChannelNormalized(), color2.GreenChannelNormalized(), color2.BlueChannelNormalized(), color2.AlphaChannelNormalized()};
|
||||
|
||||
else if (gradient == Gradient::DiagonalTopLeft)
|
||||
colors = {color1.RedChannelNormalized(), color1.GreenChannelNormalized(), color1.BlueChannelNormalized(), color1.AlphaChannelNormalized(),(color1.RedChannelNormalized() + color2.RedChannelNormalized()) / 2.f, (color1.GreenChannelNormalized() + color2.GreenChannelNormalized()) / 2.f,
|
||||
(color1.BlueChannelNormalized() + color2.BlueChannelNormalized()) / 2.f, (color1.AlphaChannelNormalized() + color2.AlphaChannelNormalized()) / 2.f, color2.RedChannelNormalized(), color2.GreenChannelNormalized(), color2.BlueChannelNormalized(), color2.AlphaChannelNormalized(),
|
||||
(color1.RedChannelNormalized() + color2.RedChannelNormalized()) / 2.f, (color1.GreenChannelNormalized() + color2.GreenChannelNormalized()) / 2.f, (color1.BlueChannelNormalized() + color2.BlueChannelNormalized()) / 2.f,(color1.AlphaChannelNormalized() + color2.AlphaChannelNormalized()) / 2.f};
|
||||
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
|
||||
glColorPointer(4, GL_FLOAT, 0, colors.data());
|
||||
glDrawArrays(GL_QUADS, 0, 4);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
glColor4fv(baseColor);
|
||||
}
|
||||
|
||||
void J2D::FillRoundedRect(const Color4& color, const Vector2& pos, const Vector2& size, float radius, unsigned int subdivisions) {
|
||||
if (!inJ2D)
|
||||
jlog::Error("Drawing J2D element before J2D begin.");
|
||||
|
||||
J2D::FillRect(color, {pos.x + radius, pos.y}, {size.x - 2 * radius, size.y});
|
||||
J2D::FillRect(color, {pos.x, pos.y + radius}, {size.x, size.y - 2 * radius});
|
||||
|
||||
J2D::FillCircle(color, {pos.x + radius, pos.y + radius}, radius, subdivisions);
|
||||
J2D::FillCircle(color, {pos.x + size.x - radius, pos.y + radius}, radius, subdivisions);
|
||||
J2D::FillCircle(color, {pos.x + radius, pos.y + size.y - radius}, radius, subdivisions);
|
||||
J2D::FillCircle(color, {pos.x + size.x - radius, pos.y + size.y - radius}, radius, subdivisions);
|
||||
}
|
||||
|
||||
void J2D::OutlineRect(const Color4& color, const Vector2& pos, const Vector2& size, float thickness) {
|
||||
if (!inJ2D)
|
||||
jlog::Error("Drawing J2D element before J2D begin.");
|
||||
|
||||
Vector2 vertices[] = {{pos.x, pos.y}, {pos.x, pos.y + size.y}, {pos.x + size.x, pos.y + size.y}, {pos.x + size.x, pos.y}};
|
||||
|
||||
glLineWidth(thickness);
|
||||
glColor4ubv(color.ptr());
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
|
||||
glDrawArrays(GL_LINE_LOOP, 0, 4);
|
||||
glColor4fv(baseColor);
|
||||
void J2D::DrawPoint(const Color4& color, float x, float y, float radius) {
|
||||
DrawPoint(color, {x, y}, radius);
|
||||
}
|
||||
|
||||
void J2D::DrawLine(const Color4& color, const Vector2& A, const Vector2& B, float thickness) {
|
||||
if (!inJ2D)
|
||||
jlog::Error("Drawing J2D element before J2D begin.");
|
||||
Logger::Error("Drawing J2D element before J2D begin.");
|
||||
Vector2 vertices[] = {A, B};
|
||||
|
||||
glLineWidth(thickness);
|
||||
@@ -369,7 +199,7 @@ namespace JGL {
|
||||
|
||||
void J2D::DrawGradientLine(const Color4& color1, const Color4& color2, const Vector2& A, const Vector2& B, float thickness) {
|
||||
if (!inJ2D)
|
||||
jlog::Error("Drawing J2D element before J2D begin.");
|
||||
Logger::Error("Drawing J2D element before J2D begin.");
|
||||
|
||||
Vector2 vertices[] = {A, B};
|
||||
GLfloat colors[8] = {color1.RedChannelNormalized(), color1.GreenChannelNormalized(), color1.BlueChannelNormalized(), color1.AlphaChannelNormalized(),
|
||||
@@ -388,40 +218,299 @@ namespace JGL {
|
||||
J2D::DrawGradientLine(color1, color2, {x, y}, {w, h}, thickness);
|
||||
}
|
||||
|
||||
void J2D::OutlinePolygon(const Color4 &color, const std::vector<Vector2>& points, float thickness) {
|
||||
void J2D::OutlineRect(const Color4& color, const Vector2& pos, const Vector2& size, float thickness) {
|
||||
if (!inJ2D)
|
||||
jlog::Error("Drawing J2D element before J2D begin.");
|
||||
Logger::Error("Drawing J2D element before J2D begin.");
|
||||
|
||||
if (points.front() != points.back())
|
||||
throw std::runtime_error("J2D::OutlinePolygon: The first point and the last point must connect.");
|
||||
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);
|
||||
glColor4ubv(color.ptr());
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), points.data());
|
||||
glDrawArrays(GL_LINE_LOOP, 0, (int) points.size());
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
|
||||
glDrawArrays(GL_LINE_LOOP, 0, 4);
|
||||
glColor4fv(baseColor);
|
||||
}
|
||||
|
||||
void J2D::DrawPoint(const Color4& color, const Vector2& coordinates, float radius) {
|
||||
void J2D::FillRect(const Color4& color, const Vector2& pos, const Vector2& size) {
|
||||
if (!inJ2D)
|
||||
jlog::Error("Drawing J2D element before J2D begin.");
|
||||
Logger::Error("Drawing J2D element before J2D begin.");
|
||||
|
||||
Vector2 vertices[] = {coordinates};
|
||||
|
||||
glPointSize(radius);
|
||||
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}};
|
||||
glColor4ubv(color.ptr());
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
|
||||
glDrawArrays(GL_POINTS, 0, 1);
|
||||
glDrawArrays(GL_QUADS, 0, 4);
|
||||
glColor4fv(baseColor);
|
||||
}
|
||||
|
||||
void J2D::DrawPoint(const Color4& color, float x, float y, float radius) {
|
||||
DrawPoint(color, {x, y}, radius);
|
||||
void J2D::FillGradientRect(const Color4& color1, const Color4& color2, const Direction& gradient, const Vector2& pos, const Vector2& size) {
|
||||
if (!inJ2D)
|
||||
Logger::Error("Drawing J2D element before J2D begin.");
|
||||
|
||||
Vector2 vertices[] = {{pos.x, pos.y}, {pos.x, pos.y + size.y}, {pos.x + size.x, pos.y + size.y}, {pos.x + size.x, pos.y}};
|
||||
std::vector<GLfloat> colors{};
|
||||
|
||||
if (gradient == Direction::Horizontal)
|
||||
colors = {color1.RedChannelNormalized(), color1.GreenChannelNormalized(), color1.BlueChannelNormalized(), color1.AlphaChannelNormalized(), color1.RedChannelNormalized(), color1.GreenChannelNormalized(), color1.BlueChannelNormalized(), color1.AlphaChannelNormalized(),
|
||||
color2.RedChannelNormalized(), color2.GreenChannelNormalized(), color2.BlueChannelNormalized(), color2.AlphaChannelNormalized(), color2.RedChannelNormalized(), color2.GreenChannelNormalized(), color2.BlueChannelNormalized(), color2.AlphaChannelNormalized()};
|
||||
|
||||
else if (gradient == Direction::Vertical)
|
||||
colors = {color1.RedChannelNormalized(), color1.GreenChannelNormalized(), color1.BlueChannelNormalized(), color1.AlphaChannelNormalized(), color2.RedChannelNormalized(), color2.GreenChannelNormalized(), color2.BlueChannelNormalized(), color2.AlphaChannelNormalized(),
|
||||
color2.RedChannelNormalized(), color2.GreenChannelNormalized(), color2.BlueChannelNormalized(), color2.AlphaChannelNormalized(), color1.RedChannelNormalized(), color1.GreenChannelNormalized(), color1.BlueChannelNormalized(), color1.AlphaChannelNormalized()};
|
||||
|
||||
else if (gradient == Direction::Diagonal_SWNE)
|
||||
colors = {(color1.RedChannelNormalized() + color2.RedChannelNormalized()) / 2.f, (color1.GreenChannelNormalized() + color2.GreenChannelNormalized()) / 2.f, (color1.BlueChannelNormalized() + color2.BlueChannelNormalized()) / 2.f, (color1.AlphaChannelNormalized() + color2.AlphaChannelNormalized()) / 2.f,
|
||||
color1.RedChannelNormalized(), color1.GreenChannelNormalized(), color1.BlueChannelNormalized(), color1.AlphaChannelNormalized(), (color1.RedChannelNormalized() + color2.RedChannelNormalized()) / 2.f, (color1.GreenChannelNormalized() + color2.GreenChannelNormalized()) / 2.f,
|
||||
(color1.BlueChannelNormalized() + color2.BlueChannelNormalized()) / 2.f, (color1.AlphaChannelNormalized() + color2.AlphaChannelNormalized()) / 2.f, color2.RedChannelNormalized(), color2.GreenChannelNormalized(), color2.BlueChannelNormalized(), color2.AlphaChannelNormalized()};
|
||||
|
||||
else if (gradient == Direction::Diagonal_NWSE)
|
||||
colors = {color1.RedChannelNormalized(), color1.GreenChannelNormalized(), color1.BlueChannelNormalized(), color1.AlphaChannelNormalized(),(color1.RedChannelNormalized() + color2.RedChannelNormalized()) / 2.f, (color1.GreenChannelNormalized() + color2.GreenChannelNormalized()) / 2.f,
|
||||
(color1.BlueChannelNormalized() + color2.BlueChannelNormalized()) / 2.f, (color1.AlphaChannelNormalized() + color2.AlphaChannelNormalized()) / 2.f, color2.RedChannelNormalized(), color2.GreenChannelNormalized(), color2.BlueChannelNormalized(), color2.AlphaChannelNormalized(),
|
||||
(color1.RedChannelNormalized() + color2.RedChannelNormalized()) / 2.f, (color1.GreenChannelNormalized() + color2.GreenChannelNormalized()) / 2.f, (color1.BlueChannelNormalized() + color2.BlueChannelNormalized()) / 2.f,(color1.AlphaChannelNormalized() + color2.AlphaChannelNormalized()) / 2.f};
|
||||
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
|
||||
glColorPointer(4, GL_FLOAT, 0, colors.data());
|
||||
glDrawArrays(GL_QUADS, 0, 4);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
glColor4fv(baseColor);
|
||||
}
|
||||
|
||||
void J2D::FillRoundedRect(const Color4& color, const Vector2& pos, const Vector2& size, float radius, unsigned int subdivisions) {
|
||||
if (!inJ2D)
|
||||
Logger::Error("Drawing J2D element before J2D begin.");
|
||||
|
||||
J2D::FillRect(color, {pos.x + radius, pos.y}, {size.x - 2 * radius, size.y});
|
||||
J2D::FillRect(color, {pos.x, pos.y + radius}, {size.x, size.y - 2 * radius});
|
||||
|
||||
J2D::FillCircle(color, {pos.x + radius, pos.y + radius}, radius, subdivisions);
|
||||
J2D::FillCircle(color, {pos.x + size.x - radius, pos.y + radius}, radius, subdivisions);
|
||||
J2D::FillCircle(color, {pos.x + radius, pos.y + size.y - radius}, radius, subdivisions);
|
||||
J2D::FillCircle(color, {pos.x + size.x - radius, pos.y + size.y - radius}, radius, subdivisions);
|
||||
}
|
||||
|
||||
void
|
||||
J2D::DrawRenderTargetAsSprite(const JGL::RenderTarget& rt, const Vector2& position, float rad_rotation, const Vector2& origin,
|
||||
const Vector2& scale, const Color4& color, Direction inversion) {
|
||||
|
||||
//Correct for the render-target being upside-down.
|
||||
Direction d{};
|
||||
if (inversion == Direction::None)
|
||||
d = Direction::Vertical;
|
||||
else if (inversion == Direction::Horizontal)
|
||||
d = Direction::Horizontal | Direction::Vertical;
|
||||
else if (inversion& Direction::Horizontal && inversion& Direction::Vertical)
|
||||
d = Direction::Horizontal;
|
||||
|
||||
//Change the blending mode such that the alpha doesn't get multiplied again.
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
//J2D::DrawSprite(*rt.GetJGLTexture(), position, rad_rotation, origin, scale, color, d);
|
||||
J2D::DrawPartialSprite(*rt.GetJGLTexture(), position, {0, 0}, rt.GetDimensions(), rad_rotation, origin, scale, color, d);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
void J2D::DrawSprite(const Texture& texture, const Vector2& pos, float rad_rotation, const Vector2& origin,
|
||||
const Vector2& scale, const Color4& color, Direction inversion) {
|
||||
if (!inJ2D)
|
||||
Logger::Error("Drawing 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;
|
||||
Vector2 scaled_size = scale * size;
|
||||
Vector2 size2 = scaled_size;
|
||||
float cos_theta = std::cos(rad_rotation);
|
||||
float sin_theta = std::sin(rad_rotation);
|
||||
|
||||
std::array<Vector2, 4> 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
|
||||
};
|
||||
|
||||
//Rotate the vertices about the origin by float rad_rotation.
|
||||
if (rad_rotation != 0)
|
||||
for (auto& v: vertices)
|
||||
v = {(v.x - pos2.x - offset.x * scale.x) * cos_theta - (v.y - pos2.y - offset.y * scale.y) * sin_theta +
|
||||
pos2.x + offset.x * scale.x,
|
||||
(v.x - pos2.x - offset.x * scale.x) * sin_theta + (v.y - pos2.y - offset.y * scale.y) * cos_theta +
|
||||
pos2.y + offset.y * scale.y
|
||||
};
|
||||
|
||||
|
||||
if (inversion& Direction::Vertical)
|
||||
textureCoordinates = {Vector2(0, 1), Vector2(0, 0), Vector2(1, 0), Vector2(1, 1)};
|
||||
if (inversion& Direction::Horizontal)
|
||||
textureCoordinates = {Vector2(1, 0), Vector2(1, 1), Vector2(0, 1), Vector2(0, 0)};
|
||||
if ((inversion& Direction::Horizontal) && (inversion& Direction::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.data());
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(Vector2), textureCoordinates.data());
|
||||
glDrawArrays(GL_QUADS, 0, 4);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glColor4fv(baseColor);
|
||||
}
|
||||
|
||||
|
||||
void J2D::DrawSprite(const Texture& texture, float positionX, float positionY, float rad_rotation, float originX,
|
||||
float originY, float scaleX, float scaleY, const Color4& color, Direction inversion) {
|
||||
DrawSprite(texture,
|
||||
{positionX, positionY},
|
||||
rad_rotation,
|
||||
{originX, originY},
|
||||
{scaleX, scaleY},
|
||||
color, inversion);
|
||||
}
|
||||
|
||||
void J2D::DrawPartialSprite(const Texture& texture, const Vector2 &position, const Vector2& sub_texture_position,
|
||||
const Vector2& sub_texture_size, float rad_rotation, const Vector2& origin,
|
||||
const Vector2& scale, const Color4& color, Direction inversion) {
|
||||
if (!inJ2D)
|
||||
Logger::Error("Drawing J2D element before J2D begin.");
|
||||
|
||||
const Vector2 textureSize = texture.GetDimensions();
|
||||
|
||||
// Calculate texture coordinates (relative to the whole texture)
|
||||
std::array<GLfloat, 8> textureCoordinates = {
|
||||
sub_texture_position.x / textureSize.x,
|
||||
sub_texture_position.y / textureSize.y,
|
||||
sub_texture_position.x / textureSize.x,
|
||||
(sub_texture_position.y + sub_texture_size.y) / textureSize.y,
|
||||
(sub_texture_position.x + sub_texture_size.x) / textureSize.x,
|
||||
(sub_texture_position.y + sub_texture_size.y) / textureSize.y,
|
||||
(sub_texture_position.x + sub_texture_size.x) / textureSize.x,
|
||||
sub_texture_position.y / textureSize.y
|
||||
};
|
||||
|
||||
if (inversion& Direction::Vertical)
|
||||
std::swap(textureCoordinates[1], textureCoordinates[3]),
|
||||
std::swap(textureCoordinates[5], textureCoordinates[7]);
|
||||
|
||||
if (inversion& Direction::Horizontal)
|
||||
std::swap(textureCoordinates[0], textureCoordinates[6]),
|
||||
std::swap(textureCoordinates[2], textureCoordinates[4]);
|
||||
|
||||
const Vector2 offset = origin * sub_texture_size;
|
||||
Vector2 pos2 = position;
|
||||
Vector2 scaled_size = scale * sub_texture_size;
|
||||
Vector2 size2 = scaled_size;
|
||||
float cos_theta = std::cos(rad_rotation);
|
||||
float sin_theta = std::sin(rad_rotation);
|
||||
|
||||
std::array<Vector2, 4> vertices =
|
||||
{
|
||||
pos2, // Top-left
|
||||
{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
|
||||
};
|
||||
|
||||
//Rotate the vertices about the origin by float rad_rotation.
|
||||
if (rad_rotation != 0)
|
||||
for (auto& v: vertices)
|
||||
v = {(v.x - pos2.x - offset.x * scale.x) * cos_theta - (v.y - pos2.y - offset.y * scale.y) * sin_theta +
|
||||
pos2.x + offset.x * scale.x,
|
||||
(v.x - pos2.x - offset.x * scale.x) * sin_theta + (v.y - pos2.y - offset.y * scale.y) * cos_theta +
|
||||
pos2.y + offset.y * scale.y};
|
||||
|
||||
glColor4ubv(color.ptr());
|
||||
glBindTexture(GL_TEXTURE_2D, texture.GetGLTextureHandle());
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, textureCoordinates.data());
|
||||
glDrawArrays(GL_QUADS, 0, 4);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glColor4fv(baseColor);
|
||||
}
|
||||
|
||||
void
|
||||
J2D::DrawPartialSprite(const JGL::Texture& texture, float positionX, float positionY, float sub_texture_positionX,
|
||||
float sub_texture_positionY, unsigned int sub_texture_sizeX,
|
||||
unsigned int sub_texture_sizeY, float originX, float originY, float rad_rotation,
|
||||
float scaleX, float scaleY, const Color4& color, JGL::Direction inversion) {
|
||||
|
||||
J2D::DrawPartialSprite(texture, {positionX, positionY}, {sub_texture_positionX, sub_texture_positionY},
|
||||
{(float) sub_texture_sizeX, (float) sub_texture_sizeY}, rad_rotation, {originX, originY},
|
||||
{scaleX, scaleY}, color, inversion);
|
||||
}
|
||||
|
||||
void J2D::DrawMirrorSprite(const Texture& texture, const Vector2& position, Direction mirror_axis, float rad_rotation, const Vector2& origin, const Vector2& scale, const Color4& color) {
|
||||
if (!inJ2D)
|
||||
Logger::Error("Drawing J2D element before J2D begin.");
|
||||
|
||||
if (mirror_axis == Direction::None)
|
||||
Logger::Warning("Drawing non-mirrored sprite with J2D::DrawMirrorSprite?");
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture.GetGLTextureHandle());
|
||||
Vector2 size = texture.GetDimensions();
|
||||
std::array<Vector2, 4> textureCoordinates = {Vector2(0, 0), Vector2(0, 1), Vector2(1, 1), Vector2(1, 0)};
|
||||
|
||||
if (mirror_axis& Direction::Horizontal)
|
||||
size.x *= 2,
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT),
|
||||
textureCoordinates = {Vector2(0, 0), Vector2(0, 1), Vector2(2, 1), Vector2(2, 0)};
|
||||
|
||||
if (mirror_axis& Direction::Vertical)
|
||||
size.y *= 2,
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT),
|
||||
textureCoordinates = {Vector2(0, 0), Vector2(0, 2), Vector2(1, 2), Vector2(1, 0)};
|
||||
|
||||
if ((mirror_axis& Direction::Horizontal) && (mirror_axis& Direction::Vertical))
|
||||
textureCoordinates = {Vector2(0, 0), Vector2(0, 2), Vector2(2, 2), Vector2(2, 0)};
|
||||
|
||||
const Vector2 offset = origin * size;
|
||||
Vector2 pos2 = position;
|
||||
Vector2 size2 = scale * size;
|
||||
float cos_theta = std::cos(rad_rotation);
|
||||
float sin_theta = std::sin(rad_rotation);
|
||||
|
||||
std::array<Vector2, 4> vertices =
|
||||
{
|
||||
pos2,
|
||||
{pos2.x, pos2.y + size2.y},
|
||||
{pos2.x + size2.x, pos2.y + size2.y},
|
||||
{pos2.x + size2.x, pos2.y}
|
||||
};
|
||||
|
||||
if (rad_rotation != 0)
|
||||
for (auto& v : vertices)
|
||||
v = {
|
||||
(v.x - pos2.x - offset.x * scale.x) * cos_theta - (v.y - pos2.y - offset.y * scale.y) * sin_theta + pos2.x + offset.x * scale.x,
|
||||
(v.x - pos2.x - offset.x * scale.x) * sin_theta + (v.y - pos2.y - offset.y * scale.y) * cos_theta + pos2.y + offset.y * scale.y
|
||||
};
|
||||
|
||||
glColor4ubv(color.ptr());
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(Vector2), textureCoordinates.data());
|
||||
glDrawArrays(GL_QUADS, 0, 4);
|
||||
|
||||
//Reset the wrapping mode.
|
||||
if (texture.GetWrappingMode() == 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 (texture.GetWrappingMode() == TextureWrappingMode::REPEAT)
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT),
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
else if (texture.GetWrappingMode() == 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);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glColor4fv(baseColor);
|
||||
}
|
||||
|
||||
void J2D::OutlineCircle(const Color4& color, const Vector2& center, float radius, unsigned int subdivisions, float thickness) {
|
||||
if (!inJ2D)
|
||||
jlog::Error("Drawing J2D element before J2D begin.");
|
||||
Logger::Error("Drawing J2D element before J2D begin.");
|
||||
|
||||
float step = (2.f * Math::Pi) / (float) subdivisions;
|
||||
std::vector<Vector2> vertices{};
|
||||
@@ -442,17 +531,15 @@ namespace JGL {
|
||||
|
||||
void J2D::FillCircle(const Color4& color, const Vector2& center, float radius, unsigned int subdivisions) {
|
||||
if (!inJ2D)
|
||||
jlog::Error("Drawing J2D element before J2D begin.");
|
||||
Logger::Error("Drawing J2D element before J2D begin.");
|
||||
|
||||
GLfloat angle, x, y;
|
||||
float step = (2.f * Math::Pi) / (float) subdivisions;
|
||||
std::vector<Vector2> vertices{};
|
||||
|
||||
for (angle = 0.0f; angle < (2.f * Math::Pi); angle += step)
|
||||
x = radius * std::sin(angle) + center.x,
|
||||
y = radius * std::cos(angle) + center.y,
|
||||
vertices.emplace_back(x, y);
|
||||
|
||||
glColor4ubv(color.ptr());
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, (int) vertices.size());
|
||||
@@ -461,7 +548,7 @@ namespace JGL {
|
||||
|
||||
void J2D::OutlineTriangle(const Color4& color, const Triangle2D& tri, float thickness) {
|
||||
if (!inJ2D)
|
||||
jlog::Error("Drawing J2D element before J2D begin.");
|
||||
Logger::Error("Drawing J2D element before J2D begin.");
|
||||
|
||||
Vector2 vertices[] = {{tri.A.x, tri.A.y}, {tri.B.x, tri.B.y}, {tri.C.x, tri.C.y}};
|
||||
|
||||
@@ -474,7 +561,7 @@ namespace JGL {
|
||||
|
||||
void J2D::FillTriangle(const Color4& color, const Triangle2D& tri) {
|
||||
if (!inJ2D)
|
||||
jlog::Error("Drawing J2D element before J2D begin.");
|
||||
Logger::Error("Drawing J2D element before J2D begin.");
|
||||
|
||||
Vector2 vertices[] = {{tri.A.x, tri.A.y}, {tri.B.x, tri.B.y}, {tri.C.x, tri.C.y}};
|
||||
|
||||
@@ -486,7 +573,7 @@ namespace JGL {
|
||||
|
||||
void J2D::FillGradientTriangle(const Color4& a_color, const Color4& b_color, const Color4& c_color, const Triangle2D& tri) {
|
||||
if (!inJ2D)
|
||||
jlog::Error("Drawing J2D element before J2D begin.");
|
||||
Logger::Error("Drawing J2D element before J2D begin.");
|
||||
|
||||
Vector2 vertices[] = {{tri.A.x, tri.A.y}, {tri.B.x, tri.B.y}, {tri.C.x, tri.C.y}};
|
||||
GLfloat colors[] = {a_color.RedChannelNormalized(), a_color.GreenChannelNormalized(), a_color.BlueChannelNormalized(), a_color.AlphaChannelNormalized(),
|
||||
@@ -519,15 +606,31 @@ namespace JGL {
|
||||
DrawLine(color, last, first, thickness);
|
||||
}
|
||||
|
||||
//The 3D projection.
|
||||
std::vector<GLfloat> perspective(float fov, float aspect, float nearPlane, float farPlane) {
|
||||
std::vector<float> result(16);
|
||||
float f = 1.0f / std::tan(fov * 0.5f * Math::Pi / 180.0f);
|
||||
void J2D::OutlinePolygon(const Color4 &color, const std::vector<Vector2>& points, float thickness) {
|
||||
if (!inJ2D)
|
||||
Logger::Error("Drawing J2D element before J2D begin.");
|
||||
|
||||
if (points.front() != points.back())
|
||||
throw std::runtime_error("J2D::OutlinePolygon: The first point and the last point must connect.");
|
||||
|
||||
glLineWidth(thickness);
|
||||
glColor4ubv(color.ptr());
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), points.data());
|
||||
glDrawArrays(GL_LINE_LOOP, 0, (int) points.size());
|
||||
glColor4fv(baseColor);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region J3D
|
||||
std::vector<GLfloat> OpenGLPerspectiveProjectionRH(float fovY, float aspect, float z_near, float z_far) {
|
||||
std::vector<GLfloat> result(16);
|
||||
GLfloat f = 1.0f / std::tan(fovY * 0.5f * Math::Pi / 180.0f);
|
||||
result[0] = f / aspect;
|
||||
result[5] = f;
|
||||
result[10] = (farPlane + nearPlane) / (nearPlane - farPlane);
|
||||
result[10] = (z_far + z_near) / (z_near - z_far);
|
||||
result[11] = -1.0f;
|
||||
result[14] = (2.0f * farPlane * nearPlane) / (nearPlane - farPlane);
|
||||
result[14] = (2.0f * z_far * z_near) / (z_near - z_far);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -557,7 +660,7 @@ namespace JGL {
|
||||
auto aspect = (float) wS.x / (float) wS.y;
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glMultMatrixf(perspective(j3d_fov, aspect, 0.001, j3d_far_plane).data());
|
||||
glMultMatrixf(OpenGLPerspectiveProjectionRH(j3d_fov, aspect, 0.001, j3d_far_plane).data());
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
|
||||
//Get what the draw color was before we did anything.
|
||||
@@ -574,6 +677,13 @@ namespace JGL {
|
||||
wasVertexArraysEnabled = false,
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
if (!glIsEnabled(GL_TEXTURE_COORD_ARRAY))
|
||||
wasTextureCoordArrayEnabled = false,
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
else
|
||||
wasTextureCoordArrayEnabled = true;
|
||||
|
||||
|
||||
wasTexture2DEnabled = true;
|
||||
if (!glIsEnabled(GL_TEXTURE_2D))
|
||||
wasTexture2DEnabled = false,
|
||||
@@ -584,18 +694,17 @@ namespace JGL {
|
||||
wasCullFaceEnabled = true,
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
wasBlendEnabled = true;
|
||||
if (!glIsEnabled(GL_BLEND))
|
||||
wasBlendEnabled = false,
|
||||
glEnable(GL_BLEND),
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
|
||||
else
|
||||
wasBlendEnabled = true;
|
||||
|
||||
if (!inJ2D)
|
||||
inJ3D = true;
|
||||
else
|
||||
jlog::Error("Can't begin J3D context inside J2D context.");
|
||||
Logger::Error("Can't begin J3D context inside J2D context.");
|
||||
}
|
||||
|
||||
void J3D::End() {
|
||||
@@ -614,6 +723,9 @@ namespace JGL {
|
||||
if (wasCullFaceEnabled)
|
||||
glEnable(GL_CULL_FACE);
|
||||
|
||||
if (!wasTextureCoordArrayEnabled)
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
//Put the draw color back how it was before.
|
||||
glColor4fv(oldColor);
|
||||
inJ3D = false;
|
||||
@@ -621,7 +733,7 @@ namespace JGL {
|
||||
|
||||
void J3D::DrawLine(const Color4& color, const Vector3& A, const Vector3& B, float thickness) {
|
||||
if (!inJ3D)
|
||||
jlog::Error("Attempt to Render J3D element before J3D begin.");
|
||||
Logger::Error("Attempt to Render J3D element before J3D begin.");
|
||||
|
||||
Vector3 vertices[] = {A, B};
|
||||
|
||||
@@ -631,4 +743,5 @@ namespace JGL {
|
||||
glDrawArrays(GL_LINES, 0, 2);
|
||||
glColor4fv(baseColor);
|
||||
}
|
||||
#pragma endregion
|
||||
}
|
||||
|
@@ -15,101 +15,96 @@
|
||||
|
||||
#include <JGL/types/Font.h>
|
||||
#include <JGL/types/FontCache.h>
|
||||
#include <JGL/Logger.h>
|
||||
#include "JGL/logger/logger.h"
|
||||
|
||||
namespace JGL {
|
||||
CachedFont* CacheFont(const Font& font, u32 size) {
|
||||
CachedFont* cachedFont;
|
||||
FT_Set_Pixel_Sizes(font.face, 0, size);
|
||||
jlog::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);
|
||||
|
||||
void PurgeFontCache() {
|
||||
fontCache.purgeCache();
|
||||
GLsizei width = 0;
|
||||
GLsizei max_height = 0;
|
||||
FT_ULong charcode;
|
||||
FT_UInt gindex;
|
||||
|
||||
//We have to loop over the available glyphs twice as we need the
|
||||
//final width and height of the texture_handle before we can construct it
|
||||
//and subsequently upload the glyph data.
|
||||
charcode = FT_Get_First_Char(font.face, &gindex);
|
||||
//Strings are char-based so we only handle charcodes within the extended ASCII range.
|
||||
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;
|
||||
width += g->bitmap.width;
|
||||
max_height = std::max(max_height, (GLsizei) g->bitmap.rows);
|
||||
charcode = FT_Get_Next_Char(font.face, charcode, &gindex);
|
||||
}
|
||||
|
||||
fontCache.newFont(texture_id, width, max_height, size, font.index);
|
||||
cachedFont = fontCache.getFont(size, font.index);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, max_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, nullptr);
|
||||
|
||||
GLsizei xoffset = 0;
|
||||
|
||||
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);
|
||||
}
|
||||
return cachedFont;
|
||||
}
|
||||
|
||||
void J2D::DrawString(const Color4& color, const std::string& text, float x, float y, float scale, u32 size, const Font& font) {
|
||||
glUseProgram(0); // Fixed-function pipeline.
|
||||
|
||||
// Offset by height to render at "correct" location.
|
||||
y += size;
|
||||
|
||||
CachedFont* cachedFont = fontCache.getFont(size, font.index);
|
||||
|
||||
if (font.face == nullptr)
|
||||
return;
|
||||
|
||||
FT_Set_Pixel_Sizes(font.face, 0, size);
|
||||
jlog::Fatal("Drawing a string with an uninitialized font?");
|
||||
|
||||
//If the font doesn't exist in the cache yet.
|
||||
if (!cachedFont) {
|
||||
jlog::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);
|
||||
|
||||
GLsizei width = 0;
|
||||
GLsizei max_height = 0;
|
||||
|
||||
FT_ULong charcode;
|
||||
FT_UInt gindex;
|
||||
|
||||
//We have to loop over the available glyphs twice as we need the
|
||||
//final width and height of the texture_handle before we can construct it
|
||||
//and subsequently upload the glyph data.
|
||||
|
||||
charcode = FT_Get_First_Char(font.face, &gindex);
|
||||
//Strings are char-based so we only handle charcodes within the extended ASCII range.
|
||||
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;
|
||||
width += g->bitmap.width;
|
||||
max_height = std::max(max_height, (GLsizei) g->bitmap.rows);
|
||||
charcode = FT_Get_Next_Char(font.face, charcode, &gindex);
|
||||
}
|
||||
|
||||
fontCache.newFont(texture_id, width, max_height, size, font.index);
|
||||
cachedFont = fontCache.getFont(size, font.index);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, max_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, nullptr);
|
||||
|
||||
GLsizei xoffset = 0;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
if (!cachedFont)
|
||||
cachedFont = CacheFont(font, size);
|
||||
|
||||
glColor4ubv(color.ptr());
|
||||
|
||||
//Texture parameters are restored when the texture_handle is bound
|
||||
glBindTexture(GL_TEXTURE_2D, *cachedFont->getTexture());
|
||||
|
||||
@@ -129,7 +124,8 @@ namespace JGL {
|
||||
x += glyph->advanceX * scale;
|
||||
y += glyph->advanceY * scale;
|
||||
|
||||
std::array<GLfloat, 12> glyph_vertices = {
|
||||
std::array<GLfloat, 12> glyph_vertices
|
||||
{
|
||||
x2, y2,
|
||||
x2, y2 + h,
|
||||
x2 + w, y2 + h,
|
||||
@@ -137,34 +133,38 @@ namespace JGL {
|
||||
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());
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(Vector2), texcoords.data());
|
||||
glDrawArrays(GL_TRIANGLES, 0, (int) vertices.size() * 6);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glColor4f(1, 1, 1, 1);
|
||||
}
|
||||
|
||||
void J3D::DrawString(const Color4& color, const std::string& text, const Vector3& pos, float scale, u32 size, const Font& font, const EulerAngle& angle, bool draw_back_face) {
|
||||
//TODO figure out what the scale should actually be mathematically.
|
||||
// TODO: Determine the proper scale factor mathematically
|
||||
scale = scale * 0.002f;
|
||||
scale = -scale;
|
||||
|
||||
float x = pos.x;
|
||||
float y = pos.y;
|
||||
float z = pos.z;
|
||||
std::vector<GLuint> textures(text.length());
|
||||
glUseProgram(0); // Fixed-function pipeline.
|
||||
glColor4ubv(color.ptr());
|
||||
|
||||
CachedFont* cachedFont = fontCache.getFont(size, font.index);
|
||||
if (font.face == nullptr)
|
||||
throw std::runtime_error("FreeType font face is null.");
|
||||
jlog::Fatal("Drawing a string with an uninitialized font?");
|
||||
|
||||
FT_Set_Pixel_Sizes(font.face, 0, size);
|
||||
if (!cachedFont)
|
||||
cachedFont = CacheFont(font, size);
|
||||
|
||||
glColor4ubv(color.ptr());
|
||||
glBindTexture(GL_TEXTURE_2D, *cachedFont->getTexture());
|
||||
|
||||
std::vector<std::array<GLfloat, 18>> vertices(text.size());
|
||||
std::vector<std::array<GLfloat, 12>> texcoords(text.size());
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(x, y, z);
|
||||
@@ -173,66 +173,43 @@ namespace JGL {
|
||||
glRotatef(angle.roll, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
x = y = z = 0;
|
||||
for (int i = 0; i < text.length(); i++) {
|
||||
CachedGlyph* glyph = cachedFont->getGlyph(text[i]);
|
||||
|
||||
for (int i = 0; i < text.length(); i++)
|
||||
{
|
||||
if (FT_Load_Char(font.face, text.c_str()[i], FT_LOAD_RENDER))
|
||||
continue;
|
||||
float x2 = x + glyph->x2offset * scale;
|
||||
float y2 = y - glyph->y2offset * scale;
|
||||
float w = glyph->w * scale;
|
||||
float h = glyph->h * scale;
|
||||
|
||||
FT_GlyphSlot g = font.face->glyph;
|
||||
glGenTextures(1, &textures.at(i));
|
||||
glBindTexture(GL_TEXTURE_2D, textures[i]);
|
||||
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);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, g->bitmap.width, g->bitmap.rows, 0, GL_ALPHA, GL_UNSIGNED_BYTE, g->bitmap.buffer);
|
||||
std::array<GLfloat, 18> glyph_vertices
|
||||
{
|
||||
x2, y2, z,
|
||||
x2, y2 + h, z,
|
||||
x2 + w, y2 + h, z,
|
||||
x2, y2, z,
|
||||
x2 + w, y2 + h, z,
|
||||
x2 + w, y2, z
|
||||
};
|
||||
|
||||
float x2 = x + g->bitmap_left * scale;
|
||||
float y2 = y - g->bitmap_top * scale; // Adjust y-coordinate
|
||||
float z2 = z;
|
||||
float w = g->bitmap.width * scale;
|
||||
float h = g->bitmap.rows * scale;
|
||||
|
||||
if (!draw_back_face)
|
||||
glEnable(GL_CULL_FACE),
|
||||
glCullFace(GL_BACK);
|
||||
|
||||
glBegin(GL_TRIANGLES);
|
||||
|
||||
glTexCoord2f(0, 0);
|
||||
glVertex3f(x2, y2, z2);
|
||||
|
||||
glTexCoord2f(0, 1);
|
||||
glVertex3f(x2, y2 + h, z2);
|
||||
|
||||
glTexCoord2f(1, 1);
|
||||
glVertex3f(x2 + w, y2 + h, z2);
|
||||
|
||||
glTexCoord2f(0, 0);
|
||||
glVertex3f(x2, y2, z2);
|
||||
|
||||
glTexCoord2f(1, 1);
|
||||
glVertex3f(x2 + w, y2 + h, z2);
|
||||
|
||||
glTexCoord2f(1, 0);
|
||||
glVertex3f(x2 + w, y2, z2);
|
||||
|
||||
glEnd();
|
||||
|
||||
if (!draw_back_face)
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
x += (g->advance.x >> 6) * scale;
|
||||
y += (g->advance.y >> 6) * scale;
|
||||
vertices[i] = glyph_vertices;
|
||||
texcoords[i] = glyph->getTexCoords();
|
||||
x += glyph->advanceX * scale;
|
||||
y += glyph->advanceY * scale;
|
||||
}
|
||||
|
||||
for (unsigned int& texture : textures)
|
||||
glDeleteTextures(1, &texture);
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(Vector3), vertices.data());
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(Vector2), texcoords.data());
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0); // Unbind texture_handle
|
||||
if (!draw_back_face)
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, (int) vertices.size() * 6);
|
||||
|
||||
if (!draw_back_face)
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glColor4f(1, 1, 1, 1);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
9
src/logger/logger.cpp
Normal file
9
src/logger/logger.cpp
Normal file
@@ -0,0 +1,9 @@
|
||||
#include <JGL/logger/logger.h>
|
||||
|
||||
namespace JGL::Logger {
|
||||
using namespace jlog;
|
||||
|
||||
GenericLogger Fatal {"JGL::fatal", GlobalLogFile, Colors::Reds::Crimson, Colors::Gray, Colors::Gray, Colors::Reds::Crimson, Colors::White};
|
||||
GenericLogger Debug {"JGL::debug", GlobalLogFile, Colors::Purples::Purple, Colors::Gray, Colors::Gray, Colors::Purples::Purple, Colors::White};
|
||||
GenericLogger Error {"JGL::error", GlobalLogFile, Colors::Red, Colors::Gray, Colors::Gray, Colors::Red, Colors::White};
|
||||
}
|
@@ -3,6 +3,7 @@
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <glad/glad.h>
|
||||
#include <jlog/Logger.hpp>
|
||||
|
||||
#if __linux__
|
||||
#include <freetype2/ft2build.h>
|
||||
@@ -122,6 +123,7 @@ namespace JGL
|
||||
return extents;
|
||||
}
|
||||
|
||||
jlog::Warning("Measuring a font size that is not cached, This is *super* slow.");
|
||||
FT_Set_Pixel_Sizes(this->face, ptSize, ptSize);
|
||||
|
||||
for (const char& c : text) {
|
||||
|
@@ -6,7 +6,7 @@ char CachedGlyph::getCharacter() {
|
||||
return character;
|
||||
}
|
||||
|
||||
const std::array<GLfloat, 12> CachedGlyph::getTexCoords() const {
|
||||
std::array<GLfloat, 12> CachedGlyph::getTexCoords() const {
|
||||
return texcoords;
|
||||
}
|
||||
|
||||
@@ -21,9 +21,6 @@ CachedGlyph::CachedGlyph(char c, std::array<GLfloat, 12> texcoords, float x2offs
|
||||
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) {
|
||||
glyphs.emplace(glyph->getCharacter(), glyph);
|
||||
}
|
||||
@@ -36,7 +33,6 @@ unsigned int JGL::CachedFont::getFontIndex() {
|
||||
return font_index;
|
||||
}
|
||||
|
||||
//TODO make this code go faster.
|
||||
CachedGlyph* JGL::CachedFont::getGlyph(char c) {
|
||||
auto it = glyphs.find(c);
|
||||
if (it != glyphs.end())
|
||||
@@ -52,7 +48,7 @@ CachedFont::CachedFont(GLuint texture_id, GLsizei texture_width, GLsizei texture
|
||||
this->font_index = font_index;
|
||||
}
|
||||
|
||||
std::map<char, CachedGlyph*> CachedFont::getGlyphs() {
|
||||
std::unordered_map<char, CachedGlyph*> CachedFont::getGlyphs() {
|
||||
return glyphs;
|
||||
}
|
||||
|
||||
|
93
src/types/RenderTarget.cpp
Normal file
93
src/types/RenderTarget.cpp
Normal file
@@ -0,0 +1,93 @@
|
||||
#include <JGL/types/RenderTarget.h>
|
||||
#include <jlog/Logger.hpp>
|
||||
#include <stdexcept>
|
||||
|
||||
JGL::Texture* JGL::RenderTarget::GetJGLTexture() const {
|
||||
return texture;
|
||||
}
|
||||
|
||||
GLuint JGL::RenderTarget::GetGLTextureHandle() const {
|
||||
return texture->GetGLTextureHandle();
|
||||
}
|
||||
|
||||
GLuint JGL::RenderTarget::GetGLFramebufferObjectHandle() const {
|
||||
return framebuffer_object;
|
||||
}
|
||||
|
||||
GLuint JGL::RenderTarget::GetGLDepthBufferHandle() const {
|
||||
return depth_buffer;
|
||||
}
|
||||
|
||||
GLuint JGL::RenderTarget::GetActiveGLFramebufferHandle() {
|
||||
GLuint fbo;
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &fbo);
|
||||
return fbo;
|
||||
}
|
||||
|
||||
void JGL::RenderTarget::SetActiveGLRenderTarget(const RenderTarget& render_target) {
|
||||
RenderTarget rt = render_target;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, rt.GetGLFramebufferObjectHandle());
|
||||
glViewport(0,0, rt.GetDimensions().x, rt.GetDimensions().y);
|
||||
}
|
||||
|
||||
Vector2 JGL::RenderTarget::GetDimensions() const {
|
||||
return size;
|
||||
}
|
||||
|
||||
void JGL::RenderTarget::Erase() {
|
||||
if (GetActiveGLFramebufferHandle() == framebuffer_object)
|
||||
jlog::Warning("Deleting the framebuffer that's currently in use?");
|
||||
|
||||
texture->Erase();
|
||||
|
||||
if (using_depth)
|
||||
glDeleteRenderbuffers(1, &depth_buffer);
|
||||
|
||||
glDeleteFramebuffers(1, &framebuffer_object);
|
||||
}
|
||||
|
||||
Color4 JGL::RenderTarget::GetClearColor() const {
|
||||
return clear_color;
|
||||
}
|
||||
|
||||
JGL::RenderTarget::RenderTarget(const Vector2& size, const Color4& clear_color, bool use_depth) {
|
||||
GLuint current_fbo = GetActiveGLFramebufferHandle();
|
||||
GLint viewport[4] = {0, 0, 0, 0};
|
||||
glGetIntegerv(GL_VIEWPORT, viewport);
|
||||
|
||||
unsigned int biggest;
|
||||
if (size.x >= size.y)
|
||||
biggest = size.x;
|
||||
else biggest = size.y;
|
||||
|
||||
texture = new Texture(Vector2(biggest, biggest));
|
||||
glGenFramebuffers(1, &framebuffer_object);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_object);
|
||||
glViewport(0,0, size.x, size.y);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture->GetGLTextureHandle(), 0);
|
||||
|
||||
if (use_depth) {
|
||||
GLuint depthBuffer;
|
||||
glGenRenderbuffers(1, &depthBuffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, biggest, biggest);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer);
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
using_depth = true;
|
||||
}
|
||||
|
||||
GLfloat old_clear_color[4];
|
||||
glGetFloatv(GL_COLOR_CLEAR_VALUE, old_clear_color);
|
||||
glClearColor(clear_color.RedChannelNormalized(), clear_color.GreenChannelNormalized(), clear_color.BlueChannelNormalized(), clear_color.AlphaChannelNormalized());
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glClearColor(old_clear_color[0], old_clear_color[1], old_clear_color[2], old_clear_color[3]);
|
||||
|
||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE)
|
||||
throw std::runtime_error("Error " + std::to_string(status) + "while generating framebuffer");
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, current_fbo);
|
||||
glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
|
||||
this->clear_color = clear_color;
|
||||
this->size = size;
|
||||
}
|
@@ -5,29 +5,59 @@ using namespace ReTexture;
|
||||
|
||||
namespace JGL
|
||||
{
|
||||
Texture::Texture(const std::string &file, const ReTexture::TextureFlag &flags, TextureFilteringMode filtering_mode, TextureWrappingMode wrapping_mode)
|
||||
Texture::Texture(const std::string& file, const ReTexture::TextureFlag& flags, TextureFilteringMode filtering_mode, TextureWrappingMode wrapping_mode)
|
||||
{
|
||||
auto *t = new ReTexture::SoftwareTexture(file, flags);
|
||||
|
||||
GLuint previous_texture;
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*) &previous_texture);
|
||||
|
||||
load(t, {(float) t->getWidth(), (float) t->getHeight()}, t->getTextureFormat(), filtering_mode,
|
||||
wrapping_mode);
|
||||
load(t, {(float) t->getWidth(), (float) t->getHeight()}, t->getTextureFormat(), filtering_mode, wrapping_mode);
|
||||
texture_flags = flags;
|
||||
|
||||
delete t;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, previous_texture);
|
||||
}
|
||||
|
||||
Texture::Texture(const std::string &file, TextureFilteringMode filtering_mode, TextureWrappingMode wrapping_mode) {
|
||||
auto *t = new SoftwareTexture(file);
|
||||
Texture::Texture(const std::string& file, TextureFilteringMode filtering_mode, TextureWrappingMode wrapping_mode) {
|
||||
GLuint previous_texture;
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*) &previous_texture);
|
||||
|
||||
load(t, {(float) t->getWidth(), (float) t->getHeight()}, t->getTextureFormat(), filtering_mode,
|
||||
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;
|
||||
glBindTexture(GL_TEXTURE_2D, previous_texture);
|
||||
}
|
||||
|
||||
void Texture::load(SoftwareTexture *software_texture, const Vector2 &size, const TextureFormat &format,
|
||||
Texture::Texture(const Vector2& size) {
|
||||
GLuint previous_texture;
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*) &previous_texture);
|
||||
|
||||
glGenTextures(1, &texture_handle);
|
||||
glBindTexture(GL_TEXTURE_2D, texture_handle);
|
||||
//NEAREST
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
//Clamp
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (int) size.x, (int) size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
|
||||
texture_format = TextureFormat::RGBA;
|
||||
texture_size = size;
|
||||
texture_filtering_mode = TextureFilteringMode::NEAREST;
|
||||
texture_wrapping_mode = TextureWrappingMode::CLAMP_TO_EDGE;
|
||||
texture_flags = TextureFlag::NONE;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, previous_texture);
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -92,22 +122,20 @@ namespace JGL
|
||||
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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;
|
||||
@@ -160,4 +188,8 @@ namespace JGL
|
||||
void Texture::SetTextureHandle(GLuint handle) {
|
||||
texture_handle = handle;
|
||||
}
|
||||
|
||||
TextureWrappingMode Texture::GetWrappingMode() const {
|
||||
return texture_wrapping_mode;
|
||||
}
|
||||
}
|
85
src/types/VRamList.cpp
Normal file
85
src/types/VRamList.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
#include <JGL/types/VRamList.h>
|
||||
#include <jlog/Logger.hpp>
|
||||
#include <cstring>
|
||||
|
||||
void JGL::VRamList::load(const GLfloat* data, const long& s) {
|
||||
GLint current_array_buffer = 0;
|
||||
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, ¤t_array_buffer);
|
||||
glGenBuffers(1, &list_handle);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, list_handle);
|
||||
glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, current_array_buffer);
|
||||
size = s;
|
||||
}
|
||||
|
||||
void JGL::VRamList::load(const GLuint* data, const long& s) {
|
||||
GLint current_element_array_buffer = 0;
|
||||
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, ¤t_element_array_buffer);
|
||||
glGenBuffers(1, &list_handle);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, list_handle);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, current_element_array_buffer);
|
||||
element_array_buffer = true;
|
||||
size = s;
|
||||
}
|
||||
|
||||
JGL::VRamList::VRamList(const GLfloat* data, const long& size) {
|
||||
long data_size = (long) sizeof(GLfloat) * size;
|
||||
load(data, data_size);
|
||||
}
|
||||
|
||||
JGL::VRamList::VRamList(const GLuint* data, const long& size) {
|
||||
load(data, (long) sizeof(GLuint) * size);
|
||||
}
|
||||
|
||||
JGL::VRamList::VRamList(Vector2* data, const long& size) {
|
||||
load(reinterpret_cast<GLfloat*>(data), (long) sizeof(Vector2) * size);
|
||||
}
|
||||
|
||||
JGL::VRamList::VRamList(Vector3* data, const long& size) {
|
||||
load(reinterpret_cast<GLfloat*>(data), (long) sizeof(Vector3) * size);
|
||||
}
|
||||
|
||||
JGL::VRamList::VRamList(Vector4* data, const long& size) {
|
||||
load(reinterpret_cast<GLfloat*>(data), (long) sizeof(Vector4) * size);
|
||||
}
|
||||
|
||||
void JGL::VRamList::Erase() {
|
||||
if (list_handle == 0)
|
||||
jlog::Warning("Erasing an uninitialized array buffer?");
|
||||
|
||||
GLint current_element_array_buffer = 0;
|
||||
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, ¤t_element_array_buffer);
|
||||
GLint current_array_buffer = 0;
|
||||
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, ¤t_array_buffer);
|
||||
|
||||
if (element_array_buffer && current_element_array_buffer == list_handle)
|
||||
jlog::Warning("Erasing an element array buffer while it's in use?");
|
||||
|
||||
else if (!element_array_buffer && current_array_buffer == list_handle)
|
||||
jlog::Warning("Erasing an array buffer while it's in use?");
|
||||
|
||||
glDeleteBuffers(1, &list_handle);
|
||||
}
|
||||
|
||||
GLuint JGL::VRamList::GetHandle() const {
|
||||
return list_handle;
|
||||
}
|
||||
|
||||
bool JGL::VRamList::IsIntegerArray() const {
|
||||
return element_array_buffer;
|
||||
}
|
||||
|
||||
bool JGL::VRamList::IsFloatArray() const {
|
||||
return !element_array_buffer;
|
||||
}
|
||||
|
||||
long JGL::VRamList::GetSize() const {
|
||||
return size;
|
||||
}
|
||||
|
||||
long JGL::VRamList::GetDataSize() const {
|
||||
if (element_array_buffer)
|
||||
return (long) sizeof(GLuint) * size;
|
||||
return (long) sizeof(GLfloat) * size;
|
||||
}
|
Reference in New Issue
Block a user