Compare commits
33 Commits
some_other
...
master
Author | SHA1 | Date | |
---|---|---|---|
9f9191a9db | |||
2d536cd611 | |||
40412a300a | |||
819539247e | |||
ee90e7f95b | |||
ad3b451659 | |||
74ab9d25db | |||
a5424eb370 | |||
6f99689add | |||
7ea4b8696e | |||
6d37cd93e3 | |||
7875b777e5 | |||
ede11131fe | |||
347b9cb278 | |||
1a2f7627d3 | |||
b3fb28be38 | |||
d2497d64a2 | |||
f7eff123be | |||
a1ca7ace77 | |||
02370c6bfa | |||
2f13be9dd8 | |||
4c798ea76a | |||
af31b41782 | |||
4374b83464 | |||
147123b202 | |||
2a2410e9bf | |||
fdabbe866f | |||
dac830fc7c | |||
019b4aa5ae | |||
3a293a2e0c | |||
73de143ec5 | |||
5068b4660e | |||
fd656cd543 |
@@ -17,7 +17,7 @@ include(cmake/CPM.cmake)
|
||||
|
||||
CPMAddPackage(
|
||||
NAME mcolor
|
||||
URL https://git.redacted.cc/maxine/mcolor/archive/Prerelease-5.zip
|
||||
URL https://git.redacted.cc/maxine/mcolor/archive/Release-1.zip
|
||||
)
|
||||
|
||||
CPMAddPackage(
|
||||
@@ -27,17 +27,17 @@ CPMAddPackage(
|
||||
|
||||
CPMAddPackage(
|
||||
NAME ReWindow
|
||||
URL https://git.redacted.cc/Redacted/ReWindow/archive/Prerelease-32.zip
|
||||
URL https://git.redacted.cc/Redacted/ReWindow/archive/Prerelease-34.zip
|
||||
)
|
||||
|
||||
CPMAddPackage(
|
||||
NAME GLAD
|
||||
URL https://git.redacted.cc/Redacted/glad/archive/v2.1ext_fbo_depthtexture_shadow_anisotropic.zip
|
||||
URL https://git.redacted.cc/Redacted/glad/archive/v2.1ext_fbo_depthtexture_shadow_anisotropic_instanced.zip
|
||||
)
|
||||
|
||||
CPMAddPackage(
|
||||
NAME jlog
|
||||
URL https://git.redacted.cc/josh/jlog/Prerelease-17.zip
|
||||
URL https://git.redacted.cc/josh/jlog/Prerelease-19.zip
|
||||
)
|
||||
|
||||
if (WIN32)
|
||||
@@ -47,7 +47,7 @@ if (WIN32)
|
||||
)
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_FLAGS "-O3 -Wall -Wextra")
|
||||
#set(CMAKE_CXX_FLAGS "-O3 -Wall -Wextra")
|
||||
|
||||
file(COPY "assets" DESTINATION "${PROJECT_BINARY_DIR}")
|
||||
file(GLOB_RECURSE ASSETS "assets/*")
|
||||
|
30
assets/shader_programs/shared.glsl
Normal file
30
assets/shader_programs/shared.glsl
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef include_shared
|
||||
#define include_shared
|
||||
#version 120
|
||||
|
||||
vec3 rgb2hsb( in vec3 c ){
|
||||
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
|
||||
vec4 p = mix(vec4(c.bg, K.wz),
|
||||
vec4(c.gb, K.xy),
|
||||
step(c.b, c.g));
|
||||
vec4 q = mix(vec4(p.xyw, c.r),
|
||||
vec4(c.r, p.yzx),
|
||||
step(p.x, c.r));
|
||||
float d = q.x - min(q.w, q.y);
|
||||
float e = 1.0e-10;
|
||||
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)),
|
||||
d / (q.x + e),
|
||||
q.x);
|
||||
}
|
||||
|
||||
// Function from Iñigo Quiles
|
||||
// https://www.shadertoy.com/view/MsS3Wc
|
||||
vec3 hsb2rgb( in vec3 c ){
|
||||
vec3 rgb = clamp(abs(mod(c.x*6.0+vec3(0.0,4.0,2.0),
|
||||
6.0)-3.0)-1.0,
|
||||
0.0,
|
||||
1.0 );
|
||||
rgb = rgb*rgb*(3.0-2.0*rgb);
|
||||
return c.z * mix(vec3(1.0), rgb, c.y);
|
||||
}
|
||||
#endif
|
@@ -1,5 +1,154 @@
|
||||
#version 120
|
||||
|
||||
#define J2D_DrawPoint 1
|
||||
#define J2D_DrawPoints 2
|
||||
#define J2D_DrawLine 3
|
||||
#define J2D_DrawLines 4
|
||||
#define J2D_DrawDottedLine 5
|
||||
#define J2D_DrawDashedLine 6
|
||||
#define J2D_DrawGradientLine 7
|
||||
#define J2D_OutlineRect 8
|
||||
#define J2D_OutlineRoundedRect 9
|
||||
#define J2D_OutlineChamferRect 10
|
||||
#define J2D_FillRect 11
|
||||
#define J2D_FillGradientRect 12
|
||||
#define J2D_FillRoundedRect 13
|
||||
#define J2D_FillChamferRect 14
|
||||
#define J2D_DrawRenderTarget 15
|
||||
#define J2D_DrawPartialRenderTarget 16
|
||||
#define J2D_DrawSprite 17
|
||||
#define J2D_DrawAlphaMaskSprite 18
|
||||
#define J2D_DrawPartialSprite 19
|
||||
#define J2D_DrawMirrorSprite 20
|
||||
#define J2D_OutlineCircle 21
|
||||
#define J2D_FillCircle 22
|
||||
#define J2D_OutlineTriangle 23
|
||||
#define J2D_FillTriangle 24
|
||||
#define J2D_FillGradientTriangle 25
|
||||
#define J2D_DrawCubicBezierCurve 26
|
||||
#define J2D_OutlinePolygon 27
|
||||
#define J2D_DrawString 28
|
||||
#define J2D_DrawArc 29
|
||||
|
||||
|
||||
uniform int JGL_RENDERING_ROUTINE;
|
||||
uniform bool JGL_INSTANCED_RENDERING;
|
||||
|
||||
// The number of texture units that have been set.
|
||||
uniform int TEXTURE_UNIT_SET_COUNT;
|
||||
|
||||
// The color manually set with glColor4f, glColor4ubv etc.
|
||||
varying vec4 v_color;
|
||||
|
||||
// Texture unit 0 - 7 (8 - 31 will come later).
|
||||
uniform sampler2D GL_TEXTURE0;
|
||||
uniform sampler2D GL_TEXTURE1;
|
||||
uniform sampler2D GL_TEXTURE2;
|
||||
uniform sampler2D GL_TEXTURE3;
|
||||
uniform sampler2D GL_TEXTURE4;
|
||||
uniform sampler2D GL_TEXTURE5;
|
||||
uniform sampler2D GL_TEXTURE6;
|
||||
uniform sampler2D GL_TEXTURE7;
|
||||
|
||||
// Texture coordinates.
|
||||
varying vec2 GL_TEXTURE0_COORD;
|
||||
varying vec2 GL_TEXTURE1_COORD;
|
||||
varying vec2 GL_TEXTURE2_COORD;
|
||||
varying vec2 GL_TEXTURE3_COORD;
|
||||
varying vec2 GL_TEXTURE4_COORD;
|
||||
varying vec2 GL_TEXTURE5_COORD;
|
||||
varying vec2 GL_TEXTURE6_COORD;
|
||||
varying vec2 GL_TEXTURE7_COORD;
|
||||
|
||||
void DrawColorOnly() {
|
||||
gl_FragColor = v_color;
|
||||
}
|
||||
|
||||
void SampleTextureUnits() {
|
||||
if (JGL_RENDERING_ROUTINE == J2D_DrawString)
|
||||
gl_FragColor = vec4(v_color.rgb, v_color.a * texture2D(GL_TEXTURE0, GL_TEXTURE0_COORD).a);
|
||||
|
||||
// Draw sprite, partial sprite, mirror sprite, render target, partial render target.
|
||||
else if (TEXTURE_UNIT_SET_COUNT == 1)
|
||||
gl_FragColor = v_color * texture2D(GL_TEXTURE0, GL_TEXTURE0_COORD);
|
||||
|
||||
// Draw alpha masked sprite.
|
||||
else if (TEXTURE_UNIT_SET_COUNT == 2) {
|
||||
vec4 color_texture = texture2D(GL_TEXTURE0, GL_TEXTURE0_COORD);
|
||||
float alpha_mask = texture2D(GL_TEXTURE1, GL_TEXTURE1_COORD).a;
|
||||
gl_FragColor = vec4(v_color.rgb * color_texture.rgb, v_color.a * alpha_mask);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Default() {
|
||||
if (TEXTURE_UNIT_SET_COUNT == 0) {
|
||||
DrawColorOnly(); return;
|
||||
}
|
||||
SampleTextureUnits();
|
||||
}
|
||||
|
||||
void main() {
|
||||
gl_FragColor = vec4(1, 1, 1, 1);
|
||||
/* If you want behavior per JGL draw function, Or for specific ones. The order here matters because some JGL functions call others.
|
||||
if (JGL_RENDERING_ROUTINE == J2D_DrawRenderTarget)
|
||||
Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_DrawPartialRenderTarget)
|
||||
Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_DrawAlphaMaskSprite)
|
||||
Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_DrawMirrorSprite)
|
||||
Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_DrawSprite)
|
||||
Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_DrawPartialSprite)
|
||||
Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_DrawPartialSprite)
|
||||
Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_DrawString)
|
||||
Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_DrawPoint)
|
||||
Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_DrawPoints)
|
||||
Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_DrawCubicBezierCurve)
|
||||
Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_DrawLine)
|
||||
Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_DrawLines)
|
||||
Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_DrawDottedLine)
|
||||
Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_DrawDashedLine)
|
||||
Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_DrawGradientLine)
|
||||
Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_OutlineRoundedRect)
|
||||
Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_FillChamferRect)
|
||||
Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_FillRoundedRect)
|
||||
Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_FillGradientRect)
|
||||
Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_OutlineRect)
|
||||
Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_FillRect)
|
||||
Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_OutlineCircle)
|
||||
Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_FillCircle)
|
||||
Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_OutlineTriangle)
|
||||
Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_FillTriangle)
|
||||
Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_FillGradientTriangle)
|
||||
Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_OutlinePolygon)
|
||||
Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_DrawArc)
|
||||
Default();
|
||||
else { Default(); }
|
||||
*/
|
||||
Default();
|
||||
}
|
@@ -1,7 +1,155 @@
|
||||
#version 120
|
||||
// TODO this will fail if we don't have the extension.
|
||||
#extension GL_ARB_instanced_arrays : enable
|
||||
|
||||
attribute vec2 position;
|
||||
#define J2D_DrawPoint 1
|
||||
#define J2D_DrawPoints 2
|
||||
#define J2D_DrawLine 3
|
||||
#define J2D_DrawLines 4
|
||||
#define J2D_DrawDottedLine 5
|
||||
#define J2D_DrawDashedLine 6
|
||||
#define J2D_DrawGradientLine 7
|
||||
#define J2D_OutlineRect 8
|
||||
#define J2D_OutlineRoundedRect 9
|
||||
#define J2D_OutlineChamferRect 10
|
||||
#define J2D_FillRect 11
|
||||
#define J2D_FillGradientRect 12
|
||||
#define J2D_FillRoundedRect 13
|
||||
#define J2D_FillChamferRect 14
|
||||
#define J2D_DrawRenderTarget 15
|
||||
#define J2D_DrawPartialRenderTarget 16
|
||||
#define J2D_DrawSprite 17
|
||||
#define J2D_DrawAlphaMaskSprite 18
|
||||
#define J2D_DrawPartialSprite 19
|
||||
#define J2D_DrawMirrorSprite 20
|
||||
#define J2D_OutlineCircle 21
|
||||
#define J2D_FillCircle 22
|
||||
#define J2D_OutlineTriangle 23
|
||||
#define J2D_FillTriangle 24
|
||||
#define J2D_FillGradientTriangle 25
|
||||
#define J2D_DrawCubicBezierCurve 26
|
||||
#define J2D_OutlinePolygon 27
|
||||
#define J2D_DrawString 28
|
||||
#define J2D_DrawArc 29
|
||||
|
||||
uniform int JGL_RENDERING_ROUTINE;
|
||||
uniform bool JGL_INSTANCED_RENDERING;
|
||||
|
||||
// The color manually set with glColor4f, glColor4ubv etc etc.
|
||||
varying vec4 v_color;
|
||||
|
||||
// Local space vertices for instanced rendering.
|
||||
attribute vec2 a_vertex_position; // 0
|
||||
|
||||
// The position at which to render the instance.
|
||||
attribute vec2 a_instance_position; // 1
|
||||
|
||||
// The scale of the instance.
|
||||
attribute vec2 a_instance_size; // 2
|
||||
|
||||
// The color of the instance.
|
||||
attribute vec4 a_instance_color; // 3
|
||||
|
||||
// The texture coordinates in each texture unit.
|
||||
varying vec2 GL_TEXTURE0_COORD;
|
||||
varying vec2 GL_TEXTURE1_COORD;
|
||||
varying vec2 GL_TEXTURE2_COORD;
|
||||
varying vec2 GL_TEXTURE3_COORD;
|
||||
varying vec2 GL_TEXTURE4_COORD;
|
||||
varying vec2 GL_TEXTURE5_COORD;
|
||||
varying vec2 GL_TEXTURE6_COORD;
|
||||
varying vec2 GL_TEXTURE7_COORD;
|
||||
|
||||
vec4 Default() {
|
||||
v_color = gl_Color;
|
||||
return gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||
}
|
||||
|
||||
vec4 DefaultInstanced() {
|
||||
v_color = a_instance_color;
|
||||
vec2 scaled = a_vertex_position * a_instance_size;
|
||||
vec2 world_pos = scaled + a_instance_position;
|
||||
return gl_ModelViewProjectionMatrix * vec4(world_pos, 0.0, 1.0);
|
||||
}
|
||||
|
||||
#include "shared.glsl"
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(position.x, position.y, 1.0, 1.0);
|
||||
GL_TEXTURE0_COORD = gl_MultiTexCoord0.xy;
|
||||
GL_TEXTURE1_COORD = gl_MultiTexCoord1.xy;
|
||||
GL_TEXTURE2_COORD = gl_MultiTexCoord2.xy;
|
||||
GL_TEXTURE3_COORD = gl_MultiTexCoord3.xy;
|
||||
GL_TEXTURE4_COORD = gl_MultiTexCoord4.xy;
|
||||
GL_TEXTURE5_COORD = gl_MultiTexCoord5.xy;
|
||||
GL_TEXTURE6_COORD = gl_MultiTexCoord6.xy;
|
||||
GL_TEXTURE7_COORD = gl_MultiTexCoord7.xy;
|
||||
|
||||
|
||||
|
||||
/* If you want behavior per JGL draw function, Or for specific ones. The order here matters because some JGL functions call others.
|
||||
if (JGL_RENDERING_ROUTINE == J2D_DrawRenderTarget)
|
||||
gl_Position = Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_DrawPartialRenderTarget)
|
||||
gl_Position = Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_DrawAlphaMaskSprite)
|
||||
gl_Position = Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_DrawMirrorSprite)
|
||||
gl_Position = Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_DrawSprite)
|
||||
gl_Position = Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_DrawPartialSprite)
|
||||
gl_Position = Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_DrawPartialSprite)
|
||||
gl_Position = Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_DrawString)
|
||||
gl_Position = Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_DrawPoint)
|
||||
gl_Position = Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_DrawPoints)
|
||||
gl_Position = Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_DrawCubicBezierCurve)
|
||||
gl_Position = Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_DrawLine)
|
||||
gl_Position = Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_DrawLines)
|
||||
gl_Position = Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_DrawDottedLine)
|
||||
gl_Position = Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_DrawDashedLine)
|
||||
gl_Position = Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_DrawGradientLine)
|
||||
gl_Position = Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_OutlineRoundedRect)
|
||||
gl_Position = Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_FillChamferRect)
|
||||
gl_Position = Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_FillRoundedRect)
|
||||
gl_Position = Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_FillGradientRect)
|
||||
gl_Position = Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_OutlineRect)
|
||||
gl_Position = Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_FillRect)
|
||||
gl_Position = Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_OutlineCircle)
|
||||
gl_Position = Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_FillCircle)
|
||||
gl_Position = Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_OutlineTriangle)
|
||||
gl_Position = Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_FillTriangle)
|
||||
gl_Position = Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_FillGradientTriangle)
|
||||
gl_Position = Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_OutlinePolygon)
|
||||
gl_Position = Default();
|
||||
else if (JGL_RENDERING_ROUTINE == J2D_DrawArc)
|
||||
gl_Position = Default();
|
||||
else { gl_Position = Default(); }
|
||||
*/
|
||||
|
||||
if (JGL_INSTANCED_RENDERING)
|
||||
gl_Position = DefaultInstanced();
|
||||
else
|
||||
gl_Position = Default();
|
||||
}
|
||||
|
@@ -16,6 +16,7 @@
|
||||
#include <Color4.hpp>
|
||||
#include <JGL/types/Texture.h>
|
||||
#include <JGL/types/Enums.h>
|
||||
#include <JGL/types/Instance.h>
|
||||
#include <JGL/types/FontCache.h>
|
||||
#include <JGL/types/Font.h>
|
||||
#include <JGL/types/RenderTarget.h>
|
||||
@@ -30,6 +31,7 @@
|
||||
#include <JGL/types/VRamList.h>
|
||||
#include <JGL/types/VertexArray.h>
|
||||
#include <JGL/types/TextureAtlas.h>
|
||||
#include <JGL/types/Shader.h>
|
||||
|
||||
// Fonts that are included by default.
|
||||
namespace JGL::Fonts {
|
||||
@@ -46,6 +48,8 @@ namespace JGL::ShapeCache {
|
||||
// Facing straight out.
|
||||
inline VRamList* j2d_default_normal_data = nullptr;
|
||||
inline VRamList* square_origin_topleft_vertex_data = nullptr;
|
||||
inline VRamList* draw_points_positions = nullptr;
|
||||
inline VRamList* draw_points_colors = nullptr;
|
||||
void Init();
|
||||
}
|
||||
|
||||
@@ -56,6 +60,8 @@ namespace JGL {
|
||||
|
||||
[[nodiscard]] bool Init(const Vector2i& window_size, float fovY, float far_plane);
|
||||
void Update(const Vector2i& window_size);
|
||||
/// Clear the default framebuffer for the OpenGL context (0).
|
||||
void ClearScreen(const Color4& clear_color);
|
||||
inline void PurgeFontCache() { JGL::fontCache.purgeCache(); }
|
||||
|
||||
|
||||
@@ -73,7 +79,7 @@ namespace JGL::J2D {
|
||||
/// This keeps our code from, say, clobbering the OpenGL rendering context driving 3D content in between our calls.
|
||||
/// @param render_target
|
||||
/// @param clear_buffers
|
||||
void Begin(RenderTarget* render_target = nullptr, bool clear_buffers = false);
|
||||
void Begin(RenderTarget* render_target = nullptr, Shader* shader = nullptr, bool clear_buffers = false);
|
||||
|
||||
/// Closes a 2-D rendering context with the underlying graphics system (In this case& by default OpenGL).
|
||||
/// @see Begin().
|
||||
@@ -95,7 +101,14 @@ namespace JGL::J2D {
|
||||
|
||||
/// Plots a series of pixel-points on the screen, in a batch.
|
||||
/// @note This is more performant for multiple points than plotting them individually.
|
||||
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
|
||||
/// @param colors A set of 4 channel color values. @see class Color4.
|
||||
/// @param points A set of x,y points to render.
|
||||
/// @param radius The size of the point to plot. By default, a single pixel.
|
||||
void DrawPoints(const Color4* color, const Vector2* points, int point_count, float radius = 1.f);
|
||||
|
||||
/// Plots a series of pixel-points on the screen, in a batch.
|
||||
/// @note This is more performant for multiple points than plotting them individually.
|
||||
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
|
||||
/// @param points A set of x,y points to render.
|
||||
/// @param radius The size of the point to plot. By default, a single pixel.
|
||||
void DrawPoints(const Color4& color, const Vector2* points, int point_count, float radius = 1.f);
|
||||
@@ -152,6 +165,8 @@ namespace JGL::J2D {
|
||||
/// @param thickness The width at which to render the lines.
|
||||
void OutlineRect(const Color4& color, const Vector2& pos, const Vector2& size, float thickness = 1);
|
||||
|
||||
void BatchOutlineRect(const Instance2D* instances, float thickness, const size_t& instance_count);
|
||||
|
||||
/// Draws an outline of a rectangle with rounded corners onto the screen.
|
||||
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
|
||||
/// @param pos The top-left corner of the rectangle.
|
||||
@@ -176,12 +191,13 @@ namespace JGL::J2D {
|
||||
void FillRect(const Color4& color, const Vector2& pos, const Vector2& size);
|
||||
|
||||
/// Draws a filled rectangle where the color transitions across it.
|
||||
/// @param color1 A 3-or-4 channel color value. @see class Color3, class Color4
|
||||
/// @param color2 A 3-or-4 channel color value. @see class Color3, class Color4
|
||||
/// @param gradient See enum Direction
|
||||
/// @param top_left_color A 3-or-4 channel color value. @see class Color3, class Color4
|
||||
/// @param bottom_left_color A 3-or-4 channel color value. @see class Color3, class Color4
|
||||
/// @param bottom_right_color A 3-or-4 channel color value. @see class Color3, class Color4
|
||||
/// @param top_right_color A 3-or-4 channel color value. @see class Color3, class Color4
|
||||
/// @param pos The top-left corner of the rectangle.
|
||||
/// @param size The width and height of the rectangle.
|
||||
void FillGradientRect(const Color4& color1, const Color4& color2, const Direction& gradient, const Vector2& pos, const Vector2& size);
|
||||
void FillGradientRect(const Color4& top_left_color, const Color4& bottom_left_color, const Color4& bottom_right_color, const Color4& top_right_color, const Vector2& pos, const Vector2& size);
|
||||
|
||||
/// Draws a filled rectangle with rounded corners on the screen.
|
||||
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
|
||||
@@ -191,6 +207,8 @@ namespace JGL::J2D {
|
||||
/// @param subdivisions The amount of sub-divisions (and calculations) to be performed per-arc rounding corner.
|
||||
void FillRoundedRect(const Color4& color, const Vector2& pos, const Vector2& size, float radius = 5, unsigned int subdivisions = 8);
|
||||
|
||||
void BatchFillRoundedRect(const Color4* colors, const Vector2* positions, const Vector2* sizes, float radius, unsigned int subdivisions, const size_t& count);
|
||||
|
||||
/// Draws a filled rectangle with chamfered (beveled) corners on the screen.
|
||||
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
|
||||
/// @param pos The top-left corner of the rectangle.
|
||||
@@ -367,8 +385,9 @@ namespace JGL::J2D {
|
||||
/// @param scale The value (in both axes) to scale the text by. Defaults to {1,1}.
|
||||
/// @param size The point-size at which to render the font out. Re-using the same point-size allows efficient glyph caching.
|
||||
/// @param font The font to use for rendering. @see Font.
|
||||
void DrawString(const Color4& color, const std::string& text, float x, float y, float scale, u32 size, const Font& font = Fonts::Jupiteroid);
|
||||
void DrawString(const Color4& color, const std::string& text, float x, float y, u32 size, float scale = 1.f, const Font& font = Fonts::Jupiteroid);
|
||||
|
||||
void DrawString(const Color4& color, const std::string& text, const Vector2& pos, u32 size, float scale = 1.f, const Font& font = Fonts::Jupiteroid);
|
||||
|
||||
/// Draws an Arc (section of a circle) to the screen.
|
||||
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
|
||||
@@ -387,9 +406,8 @@ namespace JGL::J2D {
|
||||
void OutlineEllipse(const Color4& color, const Vector2& position, float radius_x, float radius_y, float thickness = 1, int subdivisions = 8);
|
||||
void FillEllipse(const Color4& color, const Vector2& position, float radius_x, float radius_y, int subdivisions = 8);
|
||||
|
||||
void BatchFillRect(const Color4* colors, const Vector2* positions, const Vector2* sizes, const size_t& rect_count);
|
||||
|
||||
void BatchFillCircle(const Color4 *colors, const Vector2* positions, float* radii, unsigned int subdivisions, const size_t& circle_count);
|
||||
void BatchFillRect(const Instance2D* instances, const size_t& instance_count);
|
||||
void BatchFillCircle(const Instance2D* instances, float subdivisions, const size_t& instance_count);
|
||||
}
|
||||
|
||||
/// Drawing functions for 3D objects.
|
||||
@@ -633,12 +651,21 @@ namespace JGL::J3D {
|
||||
/// @param box_count The number of AABBs to draw.
|
||||
void BatchFillAABB(const Color4& color, const AABB* boxes, const size_t& box_count);
|
||||
|
||||
/// Draws an outline of an oriented bounding box in 3D space.
|
||||
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
|
||||
/// @param position The point in 3D space that is the center of the AABB.
|
||||
/// @param radii The radii along x,y,z axes to size the bounding box.
|
||||
/// @param orientation The rotation in 3D space of the OBB.
|
||||
/// @param thickness The line-width to draw the OBB outline with.
|
||||
void WireframeOBB(const Color4& color, const Vector3& position, const Vector3& radii, const Matrix3x3& orientation, float thickness = 1.f);
|
||||
|
||||
/// Draws an outline of an oriented bounding box in 3D space.
|
||||
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
|
||||
/// @param obb The OBB object to visualize.
|
||||
/// @param thickness The line-width to draw the OBB outline with.
|
||||
void WireframeOBB(const Color4& color, const Vector3& center, const Vector3& radii, const Matrix3x3& rotation_matrix, float thickness = 1.f);
|
||||
void WireframeOBB(const Color4& color, const OBB& obb, float thickness = 1.f);
|
||||
|
||||
void BatchWireframeOBB(const Color4& color, const OBB* boxes, const size_t& box_count, float thickness = 1.f);
|
||||
|
||||
/// Draws a solid oriented bounding box in 3D space.
|
||||
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
|
||||
|
@@ -22,11 +22,11 @@ private:
|
||||
std::array<GLfloat, 12> texcoords;
|
||||
public:
|
||||
int x2offset = 0, y2offset = 0, w = 0, h = 0;
|
||||
float advanceX = 0, advanceY = 0;
|
||||
float advanceX = 0, advanceY = 0, ascent = 0, descent = 0;
|
||||
|
||||
//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() const;
|
||||
CachedGlyph(char c, std::array<GLfloat, 12> texcoords, float x2o, float y2o, float w, float h, float advX, float advY, float asc, float desc);
|
||||
[[nodiscard]] char getCharacter() const;
|
||||
[[nodiscard]] std::array<GLfloat, 12> getTexCoords() const;
|
||||
};
|
||||
|
||||
|
49
include/JGL/types/Instance.h
Normal file
49
include/JGL/types/Instance.h
Normal file
@@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
|
||||
#include <Colors.hpp>
|
||||
#include <J3ML/LinearAlgebra/Vector2.hpp>
|
||||
#include <J3ML/LinearAlgebra/Matrix4x4.hpp>
|
||||
|
||||
namespace JGL {
|
||||
struct Instance2D;
|
||||
struct Instance3D;
|
||||
}
|
||||
|
||||
/// Information provided to JGL for each instance of an object you're rendering in a batch.
|
||||
/// @note This is non-negotiable. This information is interleaved in *the same buffer* in v-ram for performance reasons - Redacted.
|
||||
struct JGL::Instance2D {
|
||||
public:
|
||||
Color4 color;
|
||||
Vector2 position;
|
||||
Vector2 size;
|
||||
Vector2 scale;
|
||||
float rotation;
|
||||
public:
|
||||
/// @param position The position of the instance in world space.
|
||||
/// @param size The size of the instance.
|
||||
/// @param scale A multiplier to be applied to the size.
|
||||
/// @param rotation The rotation in radians.
|
||||
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4.
|
||||
/// @note If the thing you're drawing is textured you probably want Colors::White
|
||||
Instance2D(const Color4& color, const Vector2& position, const Vector2& size, const Vector2& scale = Vector2::One, float rotation = 0.0f) :
|
||||
color(color), position(position), size(size), scale(scale), rotation(rotation) {};
|
||||
Instance2D() = default;
|
||||
~Instance2D() = default;
|
||||
};
|
||||
|
||||
struct JGL::Instance3D {
|
||||
public:
|
||||
Matrix4x4 instance_matrix;
|
||||
Color4 color;
|
||||
public:
|
||||
/// @param instance_matrix A matrix containing rotation matrix, position, and scale.
|
||||
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4.
|
||||
/// @note If the thing you're drawing is textured you probably want Colors::White
|
||||
Instance3D(const Matrix4x4& instance_matrix, const Color4& color) : instance_matrix(instance_matrix), color(color) {};
|
||||
Instance3D() = default;
|
||||
~Instance3D() = default;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
@@ -1,58 +0,0 @@
|
||||
#pragma once
|
||||
#include <J3ML/LinearAlgebra/Vector4.hpp>
|
||||
#include <Colors.hpp>
|
||||
namespace JGL::J2D {
|
||||
class Light;
|
||||
class PointLight;
|
||||
}
|
||||
|
||||
// TODO Static member function to transform to RenderTarget space.
|
||||
// For ex, If the render target would be positioned at 10, 10 and the light is at 0, 0. Then fix it such that for the Render Target the light is at -10, -10.
|
||||
/// Only works if we know where the Render Target will be on screen beforehand. But that's the only scenario you'd need to be able to do this anyways - Redacted.
|
||||
class JGL::J2D::Light {
|
||||
protected:
|
||||
Vector4 light_pos = Vector4::Zero;
|
||||
Color4 ambient = Colors::White;
|
||||
Color4 diffuse = Colors::White;
|
||||
float constant_attenuation = 1;
|
||||
float linear_attenuation = 0;
|
||||
float quadratic_attenuation = 0;
|
||||
public:
|
||||
/// @returns The position of this light in screen-world 2D space.
|
||||
[[nodiscard]] Vector2 Position() const;
|
||||
/// @returns The ambient light color.
|
||||
[[nodiscard]] Color4 Ambient() const;
|
||||
/// @returns The diffuse light color.
|
||||
[[nodiscard]] Color4 Diffuse() const;
|
||||
/// @returns The constant attenuation value
|
||||
[[nodiscard]] float Constant() const;
|
||||
/// @returns The linear attenuation value.
|
||||
[[nodiscard]] float Linear() const;
|
||||
/// @returns The quadratic attenuation value.
|
||||
[[nodiscard]] float Quadratic() const;
|
||||
public:
|
||||
/// Set the position of this light in screen-world 2D space.
|
||||
void Position(const Vector2& new_position);
|
||||
/// Set the ambient light color.
|
||||
void Ambient(const Color4& new_ambient);
|
||||
/// Set the diffuse light color.
|
||||
void Diffuse(const Color4& new_diffuse);
|
||||
/// Set the constant attenuation value (0 - 1).
|
||||
void Constant(float new_constant_attenuation);
|
||||
/// Set the linear attenuation value (0 -1).
|
||||
void Linear(float new_linear_attenuation);
|
||||
/// Set the quadratic attenuation value (0 - 1).
|
||||
void Quadratic(float new_quadratic_attenuation);
|
||||
public:
|
||||
/// @returns float (0 - 1) representing how much this light impacts a given position in 2D space.
|
||||
[[nodiscard]] virtual float MeasureIntensityAtPosition(const Vector2& position) const = 0;
|
||||
};
|
||||
|
||||
class JGL::J2D::PointLight : public Light {
|
||||
public:
|
||||
[[nodiscard]] float MeasureIntensityAtPosition(const Vector2& position) const override;
|
||||
public:
|
||||
PointLight(const Vector2& position, const Color4& ambient, const Color4& diffuse,
|
||||
float constant_attenuation = 1, float linear_attenuation = 0, float quadratic_attenuation = 0);
|
||||
};
|
||||
|
121
include/JGL/types/Shader.h
Normal file
121
include/JGL/types/Shader.h
Normal file
@@ -0,0 +1,121 @@
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
#include <J3ML/LinearAlgebra.hpp>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include "glad/glad.h"
|
||||
#include <Event.h>
|
||||
|
||||
// LearnOpenGL::Shader
|
||||
// OpenGL Shader Class Wrapper
|
||||
// Updated by dawsh
|
||||
// https://learnopengl.com/code_viewer_gh.php?code=includes/learnopengl/shader.h
|
||||
|
||||
namespace JGL {
|
||||
using namespace J3ML::LinearAlgebra;
|
||||
|
||||
class Shader;
|
||||
}
|
||||
|
||||
/// TODO: Eventually support Hot-reloading shaders like in shadertoy. Should help tremendously with debugging.
|
||||
|
||||
class JGL::Shader {
|
||||
public:
|
||||
static inline Event<std::string, std::string> OnCompilationErrorMessage;
|
||||
|
||||
static bool HasFile(const std::filesystem::path& path)
|
||||
{
|
||||
return std::filesystem::exists(path);
|
||||
}
|
||||
|
||||
static std::string ReadFile(const std::filesystem::path& path);
|
||||
|
||||
/// The default constructor does not initialize any member values.
|
||||
Shader() = default;
|
||||
|
||||
/// Creates a shader by compiling a vertex and fragment program from the sources in the respective filesystem paths.
|
||||
Shader(const std::filesystem::path& vertex_source_path, const std::filesystem::path& fragment_source_path, const std::vector<std::pair<std::string, GLint>>& attribute_bindings = {});
|
||||
|
||||
/// Creates a shader by compiling a vertex and fragment program from the respective GLSL source-strings.
|
||||
Shader(const std::string& vertex_code, const std::string& fragment_code, const std::vector<std::pair<std::string, GLint>>& attribute_bindings = {});
|
||||
|
||||
/// @return True if the shader program successfully loaded and compiled.
|
||||
[[nodiscard]] bool Loaded() const;
|
||||
/// @return The integer handle that OpenGL links to this shader program.
|
||||
[[nodiscard]] unsigned int Handle() const;
|
||||
/// Enable this shader. All rendering performed thereafter will be affected by this shader code.
|
||||
/// @see UseDefault.
|
||||
|
||||
// TODO: Implement for hot-reloading.
|
||||
void Reload();
|
||||
// TODO: Implement for hot-reloading.
|
||||
void Unload();
|
||||
|
||||
/// @return The Uniform variable linked to the specified name.
|
||||
/// A Uniform is global a variable that is unique per shader program object, and can be accessed from any shader at any stage in the shader program.
|
||||
GLint Uniform(const std::string& name) const;
|
||||
|
||||
/// @return The Attribute variable linked to the specified name.
|
||||
/// Attributes differ from Uniforms in that their value is different for each instance of the shader-program as it is running.
|
||||
[[nodiscard]] GLint Attribute(const std::string& name) const;
|
||||
|
||||
/// Sets a `uniform bool name = value` in the shader program.
|
||||
void SetBool (const std::string& name, bool value) const;
|
||||
/// Sets a `uniform int name = value` in the shader program.
|
||||
void SetInt (const std::string& name, int value) const;
|
||||
/// Sets a `uniform float name = value` in the shader program.
|
||||
void SetFloat(const std::string& name, float value) const;
|
||||
/// Sets a `uniform vec2 name = value` in the shader program.
|
||||
/// @note GLSL has builtin vec2, while we implement a Vector2 type. Please be aware there may be differences in implementation between them!
|
||||
/// @see class J3ML::LinearAlgebra::Vector2.
|
||||
void SetVector2(const std::string& name, const Vector2& value) const;
|
||||
/// Sets a `uniform vec2 name = value` in the shader program.
|
||||
/// @note GLSL has builtin vec2, while we implement a Vector2 type. Please be aware there may be differences in implementation between them!
|
||||
/// @see class J3ML::LinearAlgebra::Vector2.
|
||||
void SetVector2(const std::string& name, float x, float y) const;
|
||||
/// Sets a `uniform vec3 name = value` in the shader program.
|
||||
/// @note GLSL has builtin vec3, while we implement a Vector3 type. Please be aware there may be differences in implementation between them!
|
||||
/// @see class J3ML::LinearAlgebra::Vector3.
|
||||
void SetVector3(const std::string& name, const Vector3& value) const;
|
||||
/// Sets a `uniform vec3 name = value` in the shader program.
|
||||
/// @note GLSL has builtin vec3, while we implement a Vector3 type. Please be aware there may be differences in implementation between them!
|
||||
/// @see class J3ML::LinearAlgebra::Vector3.
|
||||
void SetVector3(const std::string& name, float x, float y, float z) const;
|
||||
/// Sets a `uniform vec4 name = value` in the shader program.
|
||||
/// @note GLSL has builtin vec4, while we implement aVector4 type. Please be aware there may be differences in implementation between them!
|
||||
/// @see class J3ML::LinearAlgebra::Vector4.
|
||||
void SetVector4(const std::string& name, const Vector4& value) const;
|
||||
/// Sets a `uniform vec4 name = value` in the shader program.
|
||||
/// @note GLSL has builtin vec4, while we implement a Vector4 type. Please be aware there may be differences in implementation between them!
|
||||
/// @see class J3ML::LinearAlgebra::Vector4.
|
||||
void SetVector4(const std::string& name, float x, float y, float z, float w) const;
|
||||
|
||||
/// Sets a `uniform mat2 name = value` in the shader program.
|
||||
/// @note GLSL has builtin mat2, while we implement a Matrix2x2 type. Please be aware there may be differences in implementation between them!
|
||||
/// @see class J3ML::LinearAlgebra::Matrix2x2
|
||||
void SetMatrix2x2(const std::string& name, const Matrix2x2& value) const;
|
||||
|
||||
/// Sets a `uniform mat3 name = value` in the shader program.
|
||||
/// @note GLSL has builtin mat3, while we implement a Matrix3x3 type. Please be aware there may be differences in implementation between them!
|
||||
/// @see class J3ML::LinearAlgebra::Matrix3x3
|
||||
void SetMatrix3x3(const std::string& name, const Matrix3x3& value) const;
|
||||
|
||||
/// Sets a `uniform mat4 name = value` in the shader program.
|
||||
/// @note GLSL has builtin mat4, while we implement a Matrix4x4 type. Please be aware there may be differences in implementation between them!
|
||||
/// @see class J3ML::LinearAlgebra::Matrix4x4
|
||||
void SetMatrix4x4(const std::string& name, const Matrix4x4& value) const;
|
||||
|
||||
|
||||
// TODO: Implement Uniform-Setters for GLSL types that do not have a J3ML corollary (dmat3x4, dvec4, etc).
|
||||
|
||||
protected:
|
||||
private:
|
||||
unsigned int id = 0;
|
||||
std::string vertexPath;
|
||||
std::string vertexSource;
|
||||
std::string fragmentSource;
|
||||
std::string fragmentPath;
|
||||
mutable std::unordered_map<std::string, GLint> uniform_location_cache;
|
||||
static void checkCompileErrors(GLuint shader, const std::string& type);
|
||||
};
|
@@ -5,52 +5,68 @@
|
||||
#include <J3ML/LinearAlgebra/Vector2i.hpp>
|
||||
#include <J3ML/LinearAlgebra/Vector3.hpp>
|
||||
#include <J3ML/LinearAlgebra/Vector4.hpp>
|
||||
#include <Color4.hpp>
|
||||
|
||||
namespace JGL {
|
||||
class VRamList;
|
||||
/// A hint for OpenGL on how the VBO is to be used.
|
||||
enum VRamUsageHint : GLenum {
|
||||
// Never updated after creation.
|
||||
Fixed = GL_STATIC_DRAW,
|
||||
// Modified occasionally.
|
||||
Dynamic = GL_DYNAMIC_DRAW,
|
||||
// Constantly modified and used one or a few times.
|
||||
Stream = GL_STREAM_DRAW
|
||||
};
|
||||
}
|
||||
|
||||
/// A wrapped for "Vertex Buffer Object" In OpenGL, Store things in VRam.
|
||||
/// A wrapped for "Vertex Buffer Object" In OpenGL, Store things in V-ram.
|
||||
class JGL::VRamList {
|
||||
private:
|
||||
VRamUsageHint usage_hint = Fixed;
|
||||
GLuint list_handle = 0;
|
||||
long num_elements = 0;
|
||||
long byte_count = 0;
|
||||
bool element_array_buffer = false;
|
||||
/// "Spin Locking" fix for multi-threading.
|
||||
bool spin_lock = false;
|
||||
// TODO mutex lock.
|
||||
void load(const GLfloat* data, const long& size);
|
||||
void load(const GLuint* data, const long& size);
|
||||
void SetData(void* data, const long& count);
|
||||
void UpdateData(void* data, const long& offset, const long& count);
|
||||
void Erase();
|
||||
public:
|
||||
VRamList(const GLuint* data, const long& count);
|
||||
VRamList(const GLfloat* data, const long& count);
|
||||
VRamList(const Vector2* data, const long& count);
|
||||
VRamList(const Vector3* data, const long& count);
|
||||
VRamList(const Vector4* data, const long& count);
|
||||
VRamList(const GLuint* data, const long& count, VRamUsageHint hint = Fixed);
|
||||
VRamList(const GLfloat* data, const long& count, VRamUsageHint hint = Fixed);
|
||||
VRamList(const Vector2* data, const long& count, VRamUsageHint hint = Fixed);
|
||||
VRamList(const Vector3* data, const long& count, VRamUsageHint hint = Fixed);
|
||||
VRamList(const Vector4* data, const long& count, VRamUsageHint hint = Fixed);
|
||||
VRamList(const Color4* data, const long& count, VRamUsageHint hint = Fixed);
|
||||
/// Allocate an empty VBO
|
||||
/// @param byte_count the size of the buffer in bytes.
|
||||
/// @param element_array_buffer if applicable, whether the buffer is to be used for GLuint indices.
|
||||
/// @param hint A hint to the graphics driver for what the buffer is to be used for.
|
||||
VRamList(const size_t& byte_count, bool element_array_buffer, VRamUsageHint hint = Fixed);
|
||||
|
||||
~VRamList();
|
||||
/** Copying around the VBO data to a new VBO like this is slow.
|
||||
* Pass to function by const reference or pointer always. */
|
||||
VRamList(const VRamList& rhs);
|
||||
VRamList() : list_handle(0), num_elements(0), element_array_buffer(false), spin_lock(false) {}
|
||||
VRamList() : list_handle(0), byte_count(0), element_array_buffer(false) {}
|
||||
public:
|
||||
[[nodiscard]] GLuint GetHandle() const;
|
||||
[[nodiscard]] GLuint Handle() const;
|
||||
/// Returns the number of elements in the list.
|
||||
[[nodiscard]] long GetLength() const;
|
||||
[[nodiscard]] long Length() const;
|
||||
/// Returns the size of the data in bytes.
|
||||
[[nodiscard]] size_t GetDataSize() const;
|
||||
[[nodiscard]] size_t Size() const;
|
||||
/** Get VBO data back from the GPU. This is *bad* because the CPU is going to wait
|
||||
* for the transfer to finish. Has limited use other than testing. */
|
||||
[[nodiscard]] std::vector<GLfloat> GetDataF() const;
|
||||
[[nodiscard]] std::vector<GLuint> GetDataUI() const;
|
||||
[[nodiscard]] bool IsFloatArray() const;
|
||||
/** Replace the data of an existing VBO in it's entirety. Must be same type. */
|
||||
void SetData(const GLfloat* data, const long& count);
|
||||
void SetData(const Vector2* data, const long& count);
|
||||
void SetData(const Vector3* data, const long& count);
|
||||
void SetData(const Vector4* data, const long& count);
|
||||
void SetData(const Color4* data, const long& count);
|
||||
|
||||
void SetData(const GLuint* data, const long& count);
|
||||
void SetData(const Vector2i* data, const long& count);
|
||||
@@ -58,11 +74,17 @@ public:
|
||||
/** Update only a portion of the data in a VBO. Must be same type.
|
||||
* "offset" refers the number of Typename T into the buffer the data you want to change is.
|
||||
* For ex, offset 0 and length of 1 overwrites the first value. Offset 1 the second etc */
|
||||
|
||||
// TODO provide a bool to specify whether the current buffer should be orphaned.
|
||||
void UpdateData(const GLfloat* data, const long& offset, const long& count);
|
||||
void UpdateData(const Vector2* data, const long& offset, const long& count);
|
||||
void UpdateData(const Vector3* data, const long& offset, const long& count);
|
||||
void UpdateData(const Vector4* data, const long& offset, const long& count);
|
||||
|
||||
void UpdateData(const Color4* data, const long& offset, const long& count);
|
||||
void UpdateData(const GLuint* data, const long& offset, const long& count);
|
||||
void UpdateData(const Vector2i* data, const long& offset, const long& count);
|
||||
|
||||
// Update only a portion of the data in a VBO using bytes.
|
||||
// TODO This version of the function has no protection for out of bounds writes.
|
||||
void UpdateData(const uint8_t* data, const long& offset, const long& count);
|
||||
};
|
62
main.cpp
62
main.cpp
@@ -7,6 +7,7 @@
|
||||
#include <J3ML/Geometry/AABB.hpp>
|
||||
#include <ReWindow/Logger.h>
|
||||
#include <JGL/types/VertexArray.h>
|
||||
#include <JGL/types/Shader.h>
|
||||
|
||||
using J3ML::LinearAlgebra::Vector2;
|
||||
using namespace JGL::Fonts;
|
||||
@@ -14,7 +15,7 @@ using namespace JGL;
|
||||
using JGL::Font;
|
||||
|
||||
float fps = 0.0f;
|
||||
|
||||
std::vector<Instance2D> rect_instances;
|
||||
/// A draggable 2D point that highlights when moused over and when clicked.
|
||||
class Gizmo
|
||||
{
|
||||
@@ -111,6 +112,8 @@ JGL::Font FreeSans;
|
||||
Texture* image;
|
||||
Texture* image_mask;
|
||||
RenderTarget* j2d_render_target;
|
||||
Shader* shader;
|
||||
Vector2 result;
|
||||
|
||||
class JGLDemoWindow : public ReWindow::OpenGLWindow
|
||||
{
|
||||
@@ -128,12 +131,19 @@ public:
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LESS);
|
||||
glDepthMask(GL_TRUE);
|
||||
image = new Texture("assets/sprites/Re3D.png", FilteringMode::MIPMAP_NEAREST, JGL::SampleRate::X16);
|
||||
image = new Texture("assets/sprites/Re3D.png", FilteringMode::MIPMAP_NEAREST);
|
||||
image_mask = new Texture("assets/sprites/alpha_mask_2.png");
|
||||
j2d_render_target = new RenderTarget({540, 500}, {0,0,0,0}, false,
|
||||
SampleRate::NONE, FilteringMode::MIPMAP_TRILINEAR);
|
||||
SampleRate::NONE, FilteringMode::MIPMAP_NEAREST);
|
||||
|
||||
//Texture::MultiplyByAlphaMask(*image, *image_mask);
|
||||
|
||||
shader = new Shader(std::filesystem::path("assets/shader_programs/test_vertex.glsl"), std::filesystem::path("assets/shader_programs/test_fragment.glsl"),
|
||||
{{"a_vertex_position", 0}, {"a_instance_position", 1}, {"a_instance_size", 2}, {"a_instance_color", 3}});
|
||||
|
||||
result = Jupiteroid.MeasureString("The quick black fox jumps over the lazy dog.", 16);
|
||||
for (unsigned int i = 0; i < 100; i++)
|
||||
rect_instances.emplace_back(Colors::Red, Vector2(420, 420), Vector2(20, 20));
|
||||
}
|
||||
|
||||
EulerAngleXYZ textAngle = {0,0,0};
|
||||
@@ -141,9 +151,9 @@ public:
|
||||
float pulse = 0;
|
||||
float sprite_radians = 0;
|
||||
bool fov_increasing = true;
|
||||
int blit_pos = 0;
|
||||
|
||||
void display() {
|
||||
|
||||
pulse += 20 * delta_time;
|
||||
float dt = GetDeltaTime();
|
||||
|
||||
@@ -166,12 +176,15 @@ public:
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
|
||||
|
||||
camera->render();
|
||||
// All 3D elements of the scene and JGL elements *must* be rendered before the 2D stuff
|
||||
/* if rendering to screen space directly. */
|
||||
auto test_light = PointLight({2,1,2}, {0, 0, 0, 255}, {pulse, pulse, pulse, 255}, {0,0,0}, 0, 0.1, 0.01);
|
||||
auto test_light = PointLight({2,1,2}, {(u8) pulse,(u8) pulse,(u8) pulse, 255}, {(u8) pulse, (u8) pulse, (u8) pulse, 255}, {0,0,0}, 1, 0.1, 0.01);
|
||||
// If a 3D object has transparency. The things you'd like to see through it must be drawn before.
|
||||
|
||||
|
||||
J3D::Begin();
|
||||
J3D::DrawLine(Colors::Red, {-0.33,-0.125,1}, {-1,-0.125,1});
|
||||
J3D::DrawLine(Colors::Red, {-0.33,-0.125,1}, {-0.33,0.25,1});
|
||||
@@ -179,25 +192,24 @@ public:
|
||||
//J3D::WireframeSphere(Colors::Green, {0,0,0.5f}, 0.25f, 1, 128, 128);
|
||||
Sphere sphere = {{1,0, 0.5f}, 0.2125};
|
||||
J3D::BatchWireframeRevoSphere(Colors::Green, &sphere, 1, 1, 8, 8, true);
|
||||
J3D::RequiredLight(&test_light);glEnable(GL_NORMALIZE);
|
||||
|
||||
J3D::FillAABB(Colors::Whites::AliceBlue, {0,0,0.5f}, {0.05f, 0.05f, 0.05f});
|
||||
J3D::RequiredLight(&test_light);
|
||||
J3D::FillAABB(Colors::Whites::AliceBlue, {0,0,0.5f}, {0.05f, 0.05f, 0.05f});
|
||||
J3D::WireframeAABB(Colors::Yellow, {0.5, 0, 0.5}, {0.125, 0.125, 0.125}, 1);
|
||||
Matrix3x3 cube_rotation = Matrix3x3(Quaternion(EulerAngleXYZ(0, 20, 0)));
|
||||
J3D::WireframeOBB(Colors::Red, {0.25, 0 , 0.5}, {0.125, 0.125, 0.125}, cube_rotation, 1);
|
||||
J3D::End();
|
||||
|
||||
J2D::Begin(j2d_render_target, true);
|
||||
//JGL::ClearScreen(Colors::Red);
|
||||
J2D::Begin(j2d_render_target, shader, true);
|
||||
J2D::FillRect(Colors::Blue, {0,52}, {100,100});
|
||||
J2D::BatchFillRect(rect_instances.data(), rect_instances.size());
|
||||
J2D::DrawSprite(image, {300, 400}, sprite_radians * 0.10f, {0.5,0.5}, {1, 1}, Colors::White);
|
||||
J2D::DrawMirrorSprite(image, {400, 300}, Direction::Horizontal | Direction::Vertical, sprite_radians, {0.5,0.5}, {1, 1}, Colors::White);
|
||||
J2D::DrawPartialSprite(image, Vector2(225, 300), Vector2(image->GetDimensions()) * 0.25, Vector2(image->GetDimensions()) * 0.75, sprite_radians, {0.5, 0.5}, {1,1}, Colors::White);
|
||||
J2D::FillRect(Colors::Pinks::HotPink, {68, 120}, {32, 32});
|
||||
J2D::FillGradientRect(Colors::Red, Colors::Blue, Direction::Diagonal_SWNE, {100,52}, {100,100});
|
||||
J2D::FillGradientRect(Colors::Red, Colors::Green, Colors::Blue, Colors::White, {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);
|
||||
auto box = JGL::Fonts::Jupiteroid.MeasureString("Hello g", 16);
|
||||
|
||||
J2D::FillChamferRect(Colors::Reds::LightSalmon, {150, 400}, {64, 64}, 5);
|
||||
J2D::OutlineRoundedRect(Colors::Reds::LightCoral, {250, 350}, {128, 128}, 10, 2);
|
||||
@@ -205,12 +217,13 @@ public:
|
||||
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);
|
||||
auto result = Jupiteroid.MeasureString("Jupiteroid Font", 16);
|
||||
J2D::DrawString(Colors::Green, "The quick black fox jumps over the lazy dog.", 0, 20, 1, 16);
|
||||
J2D::OutlineRect(Colors::Red, {0, 20}, result, 1);
|
||||
|
||||
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::DrawString(Colors::Green, "Jupteroid Font", 0.f, 0, 1.f, 16, Jupiteroid);
|
||||
//J2D::DrawString(Colors::White, "Position: " + std::to_string(camera->position.x) + " " + std::to_string(camera->position.y) + " " + std::to_string(camera->position.z), 0, 16, 1,16, Jupiteroid);
|
||||
//J2D::DrawString(Colors::White, "ViewAngle: " + std::to_string(camera->angle.x) + " " + std::to_string(camera->angle.y) + " " + std::to_string(camera->angle.z), 0, 33, 1,16, Jupiteroid);
|
||||
//J2D::DrawString(Colors::White, "Framerate: " + std::to_string((int) fps), 0, 48, 1, 16, Jupiteroid);
|
||||
std::array<Vector2, 5> polygon = {Vector2(200, 400), {220, 420}, {220, 430}, {230, 410}, {200, 400}};
|
||||
J2D::OutlinePolygon(Colors::White, polygon.data(), polygon.size());
|
||||
J2D::DrawCubicBezierCurve(Colors::Blues::CornflowerBlue,
|
||||
@@ -224,17 +237,17 @@ public:
|
||||
b.Draw();
|
||||
c.Draw();
|
||||
d.Draw();
|
||||
|
||||
J2D::End();
|
||||
|
||||
J2D::Begin();
|
||||
|
||||
J2D::Begin(nullptr, nullptr, true);
|
||||
J2D::DrawRenderTarget(j2d_render_target, {0, 0});
|
||||
J2D::DrawSprite(image, image_mask, {0, 0}, 0.25, {0.5, 0.5}, {1,1});
|
||||
//J2D::DrawSprite(image, image_mask, {0, 0}, 0.25, {0.5, 0.5}, {1,1});
|
||||
J2D::End();
|
||||
|
||||
}
|
||||
|
||||
void OnRefresh(float elapsed) override {
|
||||
|
||||
fps = GetRefreshRate();
|
||||
|
||||
if (IsKeyDown(Keys::RightArrow))
|
||||
@@ -297,6 +310,7 @@ public:
|
||||
};
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
auto* window = new JGLDemoWindow("JGL Demo Window", 1280, 720);
|
||||
if (!window->Open())
|
||||
exit(-1);
|
||||
@@ -308,6 +322,10 @@ int main(int argc, char** argv) {
|
||||
if (!file.is_open())
|
||||
return -1;
|
||||
|
||||
Shader::OnCompilationErrorMessage += [] (std::string type, std::string info) {
|
||||
std::cout << type << ", " << info << std::endl;
|
||||
};
|
||||
|
||||
/*
|
||||
std::stringstream buffer;
|
||||
buffer << file.rdbuf();
|
||||
|
@@ -43,6 +43,10 @@ namespace JGL {
|
||||
return false;
|
||||
if (!GLAD_GL_ARB_shadow)
|
||||
return false;
|
||||
if (!GLAD_GL_ARB_draw_instanced)
|
||||
supports_instanced = false;
|
||||
if (!GLAD_GL_ARB_instanced_arrays)
|
||||
supports_instanced = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@@ -1,58 +1,68 @@
|
||||
#include <JGL/JGL.h>
|
||||
|
||||
static std::array<Vector3, 8> cube_v {
|
||||
Vector3(1.0f, 1.0f, -1.0f),
|
||||
Vector3(1.0f, -1.0f, -1.0f),
|
||||
Vector3(1.0f, 1.0f, 1.0f),
|
||||
Vector3(1.0f, -1.0f, 1.0f),
|
||||
Vector3(-1.0f, 1.0f, -1.0f),
|
||||
Vector3(-1.0f, -1.0f, -1.0f),
|
||||
Vector3(-1.0f, 1.0f, 1.0f),
|
||||
Vector3(-1.0f, -1.0f, 1.0f)
|
||||
};
|
||||
|
||||
std::array<unsigned int, 36> cube_ind {
|
||||
4, 2, 0,
|
||||
2, 7, 3,
|
||||
6, 5, 7,
|
||||
1, 7, 5,
|
||||
0, 3, 1,
|
||||
4, 1, 5,
|
||||
4, 6, 2,
|
||||
2, 6, 7,
|
||||
6, 4, 5,
|
||||
1, 3, 7,
|
||||
0, 2, 3,
|
||||
4, 0, 1
|
||||
};
|
||||
|
||||
std::array<Vector3, 8> cube_vn {
|
||||
Vector3( 0.816f, 0.408f, -0.408f),
|
||||
Vector3( 0.333f, -0.667f, -0.667f),
|
||||
Vector3( 0.333f, 0.667f, 0.667f),
|
||||
Vector3( 0.816f, -0.408f, 0.408f),
|
||||
Vector3(-0.333f, 0.667f, -0.667f),
|
||||
Vector3(-0.816f, -0.408f, -0.408f),
|
||||
Vector3(-0.816f, 0.408f, 0.408f),
|
||||
Vector3(-0.333f, -0.667f, 0.667f)
|
||||
};
|
||||
|
||||
std::array<Vector2, 4> square_v { Vector2(0, 0), {1, 0}, {1, -1}, {0, -1} };
|
||||
std::array<GLfloat, 3> square_vn {0, 0, 1};
|
||||
|
||||
void JGL::ShapeCache::Init() {
|
||||
std::array<Vector3, 8> vertices = {
|
||||
Vector3(1.0f, 1.0f, -1.0f),
|
||||
Vector3(1.0f, -1.0f, -1.0f),
|
||||
Vector3(1.0f, 1.0f, 1.0f),
|
||||
Vector3(1.0f, -1.0f, 1.0f),
|
||||
Vector3(-1.0f, 1.0f, -1.0f),
|
||||
Vector3(-1.0f, -1.0f, -1.0f),
|
||||
Vector3(-1.0f, 1.0f, 1.0f),
|
||||
Vector3(-1.0f, -1.0f, 1.0f)
|
||||
};
|
||||
std::array<unsigned int, 36> indices = {
|
||||
4, 2, 0,
|
||||
2, 7, 3,
|
||||
6, 5, 7,
|
||||
1, 7, 5,
|
||||
0, 3, 1,
|
||||
4, 1, 5,
|
||||
4, 6, 2,
|
||||
2, 6, 7,
|
||||
6, 4, 5,
|
||||
1, 3, 7,
|
||||
0, 2, 3,
|
||||
4, 0, 1
|
||||
};
|
||||
|
||||
std::array<Vector3, 8> vertex_normals = {
|
||||
Vector3( 0.816f, 0.408f, -0.408f),
|
||||
Vector3( 0.333f, -0.667f, -0.667f),
|
||||
Vector3( 0.333f, 0.667f, 0.667f),
|
||||
Vector3( 0.816f, -0.408f, 0.408f),
|
||||
Vector3(-0.333f, 0.667f, -0.667f),
|
||||
Vector3(-0.816f, -0.408f, -0.408f),
|
||||
Vector3(-0.816f, 0.408f, 0.408f),
|
||||
Vector3(-0.333f, -0.667f, 0.667f)
|
||||
};
|
||||
|
||||
if (!cube_vertex_data)
|
||||
cube_vertex_data = new VRamList(cube_v.data(), cube_v.size());
|
||||
cube_vertex_data = new VRamList(vertices.data(), vertices.size());
|
||||
|
||||
if (!cube_index_data)
|
||||
cube_index_data = new VRamList(cube_ind.data(), cube_ind.size());
|
||||
cube_index_data = new VRamList(indices.data(), indices.size());
|
||||
|
||||
if (!cube_normal_data)
|
||||
cube_normal_data = new VRamList(cube_vn.data(), cube_vn.size());
|
||||
cube_normal_data = new VRamList(vertex_normals.data(), vertex_normals.size());
|
||||
|
||||
if (!square_origin_topleft_vertex_data)
|
||||
square_origin_topleft_vertex_data = new VRamList(square_v.data(), square_v.size());
|
||||
if (!square_origin_topleft_vertex_data) {
|
||||
//std::array<Vector2, 4> square_vertices = { Vector2(0, 0), {1, 0}, {1, -1}, {0, -1} };
|
||||
std::array<Vector2, 4> square_vertices = { Vector2(0, 0), {0, 1}, {1, 1}, {1, 0} };
|
||||
square_origin_topleft_vertex_data = new VRamList(square_vertices.data(), square_vertices.size());
|
||||
}
|
||||
if (!j2d_default_normal_data) {
|
||||
std::array<GLfloat, 3> normal {0, 0, 1};
|
||||
j2d_default_normal_data = new VRamList(normal.data(), normal.size());
|
||||
}
|
||||
|
||||
if (!j2d_default_normal_data)
|
||||
j2d_default_normal_data = new VRamList(square_vn.data(), square_vn.size());
|
||||
if (!draw_points_colors) {
|
||||
std::array<Color4, 1> color = { Colors::Transparent };
|
||||
draw_points_colors = new VRamList(color.data(), color.size(), Stream);
|
||||
}
|
||||
|
||||
if (!draw_points_positions) {
|
||||
std::array<Vector2, 1> position = { Vector2::Zero };
|
||||
draw_points_positions = new VRamList(position.data(), position.size(), Stream);
|
||||
}
|
||||
}
|
@@ -1,12 +1,48 @@
|
||||
#include <JGL/JGL.h>
|
||||
#include <JGL/logger/logger.h>
|
||||
#include <JGL/types/Instance.h>
|
||||
#include <J3ML/Algorithm/Bezier.hpp>
|
||||
#include "internals/internals.h"
|
||||
|
||||
|
||||
void J2D::Begin(RenderTarget* render_target, bool clear_buffers) {
|
||||
void JGL::ClearScreen(const Color4& clear_color) {
|
||||
GLuint current_framebuffer = 0;
|
||||
GLint current_viewport[4] = {0, 0, 0, 0};
|
||||
GLfloat current_clear_color[4];
|
||||
|
||||
glGetIntegerv(GL_VIEWPORT, current_viewport);
|
||||
glGetFloatv(GL_COLOR_CLEAR_VALUE, current_clear_color);
|
||||
|
||||
current_framebuffer = RenderTarget::GetActiveGLFramebufferHandle();
|
||||
if (current_framebuffer)
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
bool changed_viewport = false;
|
||||
if (current_viewport[2] != window_size.x || current_viewport[3] != window_size.y)
|
||||
glViewport(0, 0, window_size.x, window_size.y),
|
||||
changed_viewport = true;
|
||||
|
||||
GLint has_depth = 0;
|
||||
glGetIntegerv(GL_DEPTH_BITS, &has_depth);
|
||||
glClearColor(clear_color.RN(), clear_color.GN(), clear_color.BN(), clear_color.AN());
|
||||
|
||||
if (has_depth)
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
else
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glClearColor(current_clear_color[0], current_clear_color[1], current_clear_color[2], current_clear_color[3]);
|
||||
|
||||
if (current_framebuffer)
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, current_framebuffer);
|
||||
|
||||
if (changed_viewport)
|
||||
glViewport(current_viewport[0], current_viewport[1], current_viewport[2], current_viewport[3]);
|
||||
}
|
||||
|
||||
void J2D::Begin(RenderTarget* render_target, Shader* shader, bool clear_buffers) {
|
||||
State new_state = default_state;
|
||||
state_stack.Push(State::SaveState());
|
||||
state_stack.Push(State::SaveState(current_state));
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
@@ -31,13 +67,17 @@ void J2D::Begin(RenderTarget* render_target, bool clear_buffers) {
|
||||
new_state.viewport[3] = window_size.y;
|
||||
}
|
||||
|
||||
if (shader) {
|
||||
new_state.current_shader = shader;
|
||||
new_state.current_shader_handle = shader->Handle();
|
||||
}
|
||||
|
||||
State::RestoreState(new_state);
|
||||
current_state = new_state;
|
||||
|
||||
if (current_state.current_render_target)
|
||||
RenderTarget::SetActiveGLRenderTarget(*current_state.current_render_target);
|
||||
|
||||
|
||||
if (render_target != nullptr && clear_buffers) {
|
||||
glClearColor(render_target->GetClearColor().RedChannelNormalized(), render_target->GetClearColor().GreenChannelNormalized(), render_target->GetClearColor().BlueChannelNormalized(), render_target->GetClearColor().AlphaChannelNormalized());
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
@@ -86,7 +126,15 @@ void J2D::DrawPoint(const Color4& color, const Vector2& coordinates, float radiu
|
||||
glPointSize(radius);
|
||||
glColor4ubv(color.ptr());
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), coordinates.ptr());
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", RENDERING_ROUTINE_ID::J2D_DrawPoint);
|
||||
|
||||
glDrawArrays(GL_POINTS, 0, 1);
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", 0);
|
||||
|
||||
glColor4fv(default_state.draw_color);
|
||||
}
|
||||
|
||||
@@ -102,7 +150,15 @@ void J2D::DrawLine(const Color4& color, const Vector2& A, const Vector2& B, floa
|
||||
glLineWidth(thickness);
|
||||
glColor4ubv(color.ptr());
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", RENDERING_ROUTINE_ID::J2D_DrawLine);
|
||||
|
||||
glDrawArrays(GL_LINES, 0, 2);
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", 0);
|
||||
|
||||
glColor4fv(default_state.draw_color);
|
||||
}
|
||||
|
||||
@@ -117,7 +173,15 @@ void J2D::DrawLines(const Color4& color, const Vector2* points, const size_t& po
|
||||
glLineWidth(thickness);
|
||||
glColor3ubv(color.ptr());
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), points);
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", RENDERING_ROUTINE_ID::J2D_DrawLines);
|
||||
|
||||
glDrawArrays(GL_LINE_STRIP, 0, point_count);
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", 0);
|
||||
|
||||
glColor4fv(default_state.draw_color);
|
||||
}
|
||||
|
||||
@@ -134,7 +198,13 @@ void J2D::DrawDottedLine(const Color4& color, const Vector2& A, const Vector2& B
|
||||
for (unsigned int i = 0; i < point_count; ++i)
|
||||
points[i] = A + direction * (i * spacing);
|
||||
|
||||
return J2D::DrawPoints(color, points.data(), points.size(), thickness);
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", RENDERING_ROUTINE_ID::J2D_DrawDottedLine);
|
||||
|
||||
J2D::DrawPoints(color, points.data(), points.size(), thickness);
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", 0);
|
||||
}
|
||||
|
||||
void J2D::DrawDottedLine(const Color4& color, float x1, float y1, float x2, float y2, float spacing, float thickness) {
|
||||
@@ -151,6 +221,10 @@ void J2D::DrawDashedLine(const Color4& color, const Vector2& A, const Vector2& B
|
||||
Logger::Error("Drawing a dashed line that would have no dashes?");
|
||||
|
||||
Vector2 A_current, B_current;
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", RENDERING_ROUTINE_ID::J2D_DrawDashedLine);
|
||||
|
||||
for (unsigned int i = 0; i < dash_count; i++) {
|
||||
A_current = A + direction * (i * length_of_dash_and_gap);
|
||||
B_current = A_current + (direction * dash_length);
|
||||
@@ -164,6 +238,9 @@ void J2D::DrawDashedLine(const Color4& color, const Vector2& A, const Vector2& B
|
||||
B_current = A_current + direction * std::min(dash_length, distance_left);
|
||||
J2D::DrawLine(color, A_current, B_current, thickness);
|
||||
}
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", 0);
|
||||
}
|
||||
|
||||
void J2D::DrawDashedLine(const Color4& color, float x1, float y1, float x2, float y2, float spacing, float dash_length, float thickness) {
|
||||
@@ -182,7 +259,15 @@ void J2D::DrawGradientLine(const Color4& color1, const Color4& color2, const Vec
|
||||
glLineWidth(thickness);
|
||||
glColorPointer(4,GL_FLOAT,sizeof(Color4), colors);
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", RENDERING_ROUTINE_ID::J2D_DrawGradientLine);
|
||||
|
||||
glDrawArrays(GL_LINES, 0, 2);
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", 0);
|
||||
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
glColor4fv(default_state.draw_color);
|
||||
}
|
||||
@@ -192,90 +277,204 @@ void DrawGradientLine(const Color4& color1, const Color4& color2, float x, float
|
||||
}
|
||||
|
||||
void J2D::OutlineRect(const Color4& color, const Vector2& pos, const Vector2& size, float thickness) {
|
||||
Instance2D rect(color, pos, size);
|
||||
J2D::BatchOutlineRect(&rect, thickness, 1);
|
||||
}
|
||||
|
||||
void J2D::BatchOutlineRect(const Instance2D* instances, float thickness, const size_t& instance_count) {
|
||||
if (!state_stack.Size())
|
||||
Logger::Error("Drawing J2D element before J2D begin.");
|
||||
|
||||
Vector2 vertices[] = {{pos.x, pos.y}, {pos.x, pos.y + size.y}, {pos.x + size.x, pos.y + size.y}, {pos.x + size.x, pos.y}};
|
||||
if (instance_count <= 0)
|
||||
return;
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", RENDERING_ROUTINE_ID::J2D_OutlineRect);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, ShapeCache::square_origin_topleft_vertex_data->Handle());
|
||||
glLineWidth(thickness);
|
||||
glColor4ubv(color.ptr());
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
|
||||
glDrawArrays(GL_LINE_LOOP, 0, 4);
|
||||
|
||||
if (instance_count == 1 || !supports_instanced || !current_state.current_shader) {
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), nullptr);
|
||||
|
||||
for (size_t i = 0; i < instance_count; i++) {
|
||||
glPushMatrix();
|
||||
glColor4ubv(instances[i].color.ptr());
|
||||
glTranslatef(instances[i].position.x, instances[i].position.y, 0);
|
||||
glScalef(instances[i].size.x, instances[i].size.y, 1);
|
||||
glDrawArrays(GL_LINE_LOOP, 0, 4);
|
||||
glPopMatrix();
|
||||
}
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
else {
|
||||
current_state.current_shader->SetBool("JGL_INSTANCED_RENDERING", true);
|
||||
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), nullptr);
|
||||
glVertexAttribDivisorARB(0, 0);
|
||||
|
||||
VRamList instance_buffer((GLfloat*) instances, instance_count * (sizeof(Instance2D) / sizeof(GLfloat)), Stream);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, instance_buffer.Handle());
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Instance2D), (GLvoid*) offsetof(Instance2D, position));
|
||||
glVertexAttribDivisorARB(1, 1);
|
||||
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Instance2D), (GLvoid*) offsetof(Instance2D, size));
|
||||
glVertexAttribDivisorARB(2, 1);
|
||||
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Instance2D), (GLvoid*) offsetof(Instance2D, color));
|
||||
glVertexAttribDivisorARB(3, 1);
|
||||
|
||||
glDrawArraysInstancedARB(GL_LINE_LOOP, 0, 4, instance_count);
|
||||
|
||||
glDisableVertexAttribArray(0);
|
||||
glDisableVertexAttribArray(1);
|
||||
glDisableVertexAttribArray(2);
|
||||
glDisableVertexAttribArray(3);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
current_state.current_shader->SetBool("JGL_INSTANCED_RENDERING", false);
|
||||
}
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", 0);
|
||||
|
||||
glColor4fv(default_state.draw_color);
|
||||
}
|
||||
|
||||
void J2D::FillRect(const Color4& color, const Vector2& pos, const Vector2& size) {
|
||||
BatchFillRect(&color, &pos, &size, 1);
|
||||
Instance2D rect(color, pos, size);
|
||||
BatchFillRect(&rect, 1);
|
||||
}
|
||||
|
||||
void J2D::BatchFillRect(const Color4* colors, const Vector2* positions, const Vector2* sizes, const size_t& rect_count) {
|
||||
void J2D::BatchFillRect(const Instance2D* instances, const size_t& instance_count) {
|
||||
if (!state_stack.Size())
|
||||
Logger::Error("Drawing J2D element before J2D begin.");
|
||||
|
||||
if (rect_count <= 0)
|
||||
if (instance_count <= 0)
|
||||
return;
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, ShapeCache::square_origin_topleft_vertex_data->GetHandle());
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), nullptr);
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", RENDERING_ROUTINE_ID::J2D_FillRect);
|
||||
|
||||
for (size_t i = 0; i < rect_count; i++) {
|
||||
glPushMatrix();
|
||||
glColor4ubv(colors[i].ptr());
|
||||
glTranslatef(positions[i].x, positions[i].y + sizes[i].y, 0);
|
||||
glScalef(sizes[i].x, sizes[i].y, 1);
|
||||
glDrawArrays(GL_QUADS, 0, 4);
|
||||
glPopMatrix();
|
||||
glBindBuffer(GL_ARRAY_BUFFER, ShapeCache::square_origin_topleft_vertex_data->Handle());
|
||||
|
||||
if (instance_count == 1 || !supports_instanced || !current_state.current_shader) {
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), nullptr);
|
||||
|
||||
for (size_t i = 0; i < instance_count; i++) {
|
||||
glPushMatrix();
|
||||
glColor4ubv(instances[i].color.ptr());
|
||||
glTranslatef(instances[i].position.x, instances[i].position.y, 0);
|
||||
glScalef(instances[i].size.x, instances[i].size.y, 1);
|
||||
glDrawArrays(GL_QUADS, 0, 4);
|
||||
glPopMatrix();
|
||||
}
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
else {
|
||||
current_state.current_shader->SetBool("JGL_INSTANCED_RENDERING", true);
|
||||
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), nullptr);
|
||||
glVertexAttribDivisorARB(0, 0);
|
||||
|
||||
VRamList instance_buffer((GLfloat*) instances, instance_count * (sizeof(Instance2D) / sizeof(GLfloat)), Stream);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, instance_buffer.Handle());
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Instance2D), (GLvoid*) offsetof(Instance2D, position));
|
||||
glVertexAttribDivisorARB(1, 1);
|
||||
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Instance2D), (GLvoid*) offsetof(Instance2D, size));
|
||||
glVertexAttribDivisorARB(2, 1);
|
||||
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Instance2D), (GLvoid*) offsetof(Instance2D, color));
|
||||
glVertexAttribDivisorARB(3, 1);
|
||||
|
||||
glDrawArraysInstancedARB(GL_QUADS, 0, 4, instance_count);
|
||||
|
||||
glDisableVertexAttribArray(0);
|
||||
glDisableVertexAttribArray(1);
|
||||
glDisableVertexAttribArray(2);
|
||||
glDisableVertexAttribArray(3);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
current_state.current_shader->SetBool("JGL_INSTANCED_RENDERING", false);
|
||||
}
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", 0);
|
||||
|
||||
glColor4fv(default_state.draw_color);
|
||||
}
|
||||
|
||||
void J2D::FillGradientRect(const Color4& color1, const Color4& color2, const Direction& gradient, const Vector2& pos, const Vector2& size) {
|
||||
void J2D::FillGradientRect(const Color4& top_left_color, const Color4& bottom_left_color, const Color4& bottom_right_color, const Color4& top_right_color, const Vector2& pos, const Vector2& size) {
|
||||
if (!state_stack.Size())
|
||||
Logger::Error("Drawing J2D element before J2D begin.");
|
||||
|
||||
Vector2 vertices[] = {{pos.x, pos.y}, {pos.x, pos.y + size.y}, {pos.x + size.x, pos.y + size.y}, {pos.x + size.x, pos.y}};
|
||||
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};
|
||||
std::vector<GLfloat> colors {
|
||||
top_left_color.RN(), top_left_color.GN(), top_left_color.BN(), top_left_color.AN(),
|
||||
bottom_left_color.RN(), bottom_left_color.GN(), bottom_left_color.BN(), bottom_left_color.AN(),
|
||||
bottom_right_color.RN(), bottom_right_color.GN(), bottom_right_color.BN(), bottom_right_color.AN(),
|
||||
top_right_color.RN(), top_right_color.GN(), top_right_color.BN(), top_right_color.AN()
|
||||
};
|
||||
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
|
||||
glColorPointer(4, GL_FLOAT, 0, colors.data());
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", RENDERING_ROUTINE_ID::J2D_FillGradientRect);
|
||||
|
||||
glDrawArrays(GL_QUADS, 0, 4);
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", 0);
|
||||
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
glColor4fv(default_state.draw_color);
|
||||
}
|
||||
|
||||
void J2D::FillRoundedRect(const Color4& color, const Vector2& pos, const Vector2& size, float radius, unsigned int subdivisions) {
|
||||
std::array<Color4, 4> colors = { color, color, color, color };
|
||||
std::array<Vector2, 2> rect_positions = { Vector2(pos.x + radius, pos.y), {pos.x, pos.y + radius} };
|
||||
std::array<Vector2, 2> rect_sizes = { Vector2(size.x - 2 * radius, size.y), {size.x, size.y - 2 * radius} };
|
||||
std::array<float, 4> circle_radii = { radius, radius, radius, radius };
|
||||
std::array<Vector2, 4> circle_positions
|
||||
{
|
||||
Vector2(pos.x + radius, pos.y + radius), {pos.x + size.x - radius, pos.y + radius},
|
||||
{pos.x + radius, pos.y + size.y - radius}, {pos.x + size.x - radius, pos.y + size.y - radius}
|
||||
};
|
||||
void J2D::BatchFillRoundedRect(const Color4* colors, const Vector2* positions, const Vector2* sizes, float radius, unsigned int subdivisions, const size_t& count) {
|
||||
std::vector<Instance2D> rect_instances(count * 2);
|
||||
std::vector<Instance2D> circle_instances(count * 4);
|
||||
|
||||
J2D::BatchFillRect(colors.data(), rect_positions.data(), rect_sizes.data(), 2);
|
||||
J2D::BatchFillCircle(colors.data(), circle_positions.data(), circle_radii.data(), subdivisions, 4);
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", RENDERING_ROUTINE_ID::J2D_FillRoundedRect);
|
||||
|
||||
for (unsigned int i = 0; i < count; i++) {
|
||||
unsigned int rect_i = i * 2;
|
||||
unsigned int circle_i = i * 4;
|
||||
|
||||
rect_instances[rect_i] = Instance2D(colors[i], Vector2(positions[i].x + radius, positions[i].y), Vector2(sizes[i].x - 2 * radius, sizes[i].y));
|
||||
rect_instances[rect_i + 1] = Instance2D(colors[i], Vector2(positions[i].x, positions[i].y + radius), Vector2(sizes[i].x, sizes[i].y - 2 * radius));
|
||||
|
||||
circle_instances[circle_i] = Instance2D(colors[i], Vector2(positions[i].x + radius, positions[i].y + radius), Vector2::One, Vector2(radius, radius));
|
||||
circle_instances[circle_i + 1] = Instance2D(colors[i], Vector2(positions[i].x + sizes[i].x - radius, positions[i].y + radius), Vector2::One, Vector2(radius, radius));
|
||||
circle_instances[circle_i + 2] = Instance2D(colors[i], Vector2(positions[i].x + radius, positions[i].y + sizes[i].y - radius), Vector2::One, Vector2(radius, radius));
|
||||
circle_instances[circle_i + 3] = Instance2D(colors[i], Vector2(positions[i].x + sizes[i].x - radius, positions[i].y + sizes[i].y - radius), Vector2::One, Vector2(radius, radius));
|
||||
}
|
||||
|
||||
J2D::BatchFillRect(rect_instances.data(), rect_instances.size());
|
||||
J2D::BatchFillCircle(circle_instances.data(), subdivisions, circle_instances.size());
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", 0);
|
||||
}
|
||||
|
||||
void J2D::FillRoundedRect(const Color4& color, const Vector2& pos, const Vector2& size, float radius, unsigned int subdivisions) {
|
||||
J2D::BatchFillRoundedRect(&color, &pos, &size, radius, subdivisions, 1);
|
||||
}
|
||||
|
||||
void J2D::DrawSprite(const Texture* texture, float positionX, float positionY, float rad_rotation,
|
||||
@@ -347,8 +546,15 @@ void J2D::DrawSprite(const RenderTarget& rt, const Vector2& position, float rad_
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
auto r_position = Vector2(Math::Floor(position.x), Math::Floor(position.y));
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", RENDERING_ROUTINE_ID::J2D_DrawRenderTarget);
|
||||
|
||||
J2D::DrawPartialSprite(*rt.GetTexture(), r_position, {0, 0}, Vector2(rt.GetDimensions()), rad_rotation, origin, scale, color, d);
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", 0);
|
||||
|
||||
if (rt.OwnsTexture())
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
@@ -423,9 +629,23 @@ void J2D::DrawSprite(const Texture& texture, const Texture& alpha_mask, const Ve
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(Vector2), textureCoordinates.data());
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("TEXTURE_UNIT_SET_COUNT", 2),
|
||||
current_state.current_shader->SetInt("GL_TEXTURE1", 1);
|
||||
|
||||
// Draw.
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", RENDERING_ROUTINE_ID::J2D_DrawAlphaMaskSprite);
|
||||
|
||||
glDrawArrays(GL_QUADS, 0, 4);
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", 0);
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("TEXTURE_UNIT_SET_COUNT", 0),
|
||||
current_state.current_shader->SetInt("GL_TEXTURE1", 0);
|
||||
|
||||
// Reset Texture 1.
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
@@ -482,8 +702,14 @@ void J2D::DrawPartialRenderTarget(const RenderTarget& rt, const Vector2& positio
|
||||
auto r_position = Vector2(Math::Floor(position.x), Math::Floor(position.y));
|
||||
auto r_sub_texture_position = Vector2(Math::Floor(sub_texture_position.x), Math::Floor(sub_texture_position.y));
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", RENDERING_ROUTINE_ID::J2D_DrawPartialRenderTarget);
|
||||
|
||||
J2D::DrawPartialSprite(*rt.GetTexture(), r_position, r_sub_texture_position, sub_texture_size, rad_rotation, origin, scale, color, d);
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", 0);
|
||||
|
||||
if (rt.OwnsTexture())
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
@@ -507,9 +733,6 @@ void J2D::DrawSprite(const Texture& texture, const Vector2& pos, float rad_rotat
|
||||
else
|
||||
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;
|
||||
@@ -547,7 +770,17 @@ void J2D::DrawSprite(const Texture& texture, const Vector2& pos, float rad_rotat
|
||||
glBindTexture(GL_TEXTURE_2D, texture.GetHandle());
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(Vector2), textureCoordinates.data());
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", RENDERING_ROUTINE_ID::J2D_DrawSprite),
|
||||
current_state.current_shader->SetInt("TEXTURE_UNIT_SET_COUNT", 1);
|
||||
|
||||
glDrawArrays(GL_QUADS, 0, 4);
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", 0),
|
||||
current_state.current_shader->SetInt("TEXTURE_UNIT_SET_COUNT", 0);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glColor4fv(default_state.draw_color);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
@@ -636,7 +869,17 @@ void J2D::DrawPartialSprite(const Texture& texture, const Vector2& position, con
|
||||
glBindTexture(GL_TEXTURE_2D, texture.GetHandle());
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, textureCoordinates.data());
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", RENDERING_ROUTINE_ID::J2D_DrawPartialSprite),
|
||||
current_state.current_shader->SetInt("TEXTURE_UNIT_SET_COUNT", 1);
|
||||
|
||||
glDrawArrays(GL_QUADS, 0, 4);
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", 0),
|
||||
current_state.current_shader->SetInt("TEXTURE_UNIT_SET_COUNT", 0);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glColor4fv(default_state.draw_color);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
@@ -718,8 +961,17 @@ void J2D::DrawMirrorSprite(const Texture& texture, const Vector2& position, Dire
|
||||
glColor4ubv(color.ptr());
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(Vector2), textureCoordinates.data());
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", RENDERING_ROUTINE_ID::J2D_DrawMirrorSprite),
|
||||
current_state.current_shader->SetInt("TEXTURE_UNIT_SET_COUNT", 1);
|
||||
|
||||
glDrawArrays(GL_QUADS, 0, 4);
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", 0),
|
||||
current_state.current_shader->SetInt("TEXTURE_UNIT_SET_COUNT", 0);
|
||||
|
||||
//Reset the wrapping mode.
|
||||
if (texture.GetWrappingMode() == WrappingMode::CLAMP_TO_EDGE)
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE),
|
||||
@@ -760,19 +1012,28 @@ void J2D::OutlineCircle(const Color4& color, const Vector2& center, float radius
|
||||
glLineWidth(thickness);
|
||||
glColor4ubv(color.ptr());
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", RENDERING_ROUTINE_ID::J2D_OutlineCircle);
|
||||
|
||||
glDrawArrays(GL_LINE_LOOP, 0, (int) vertices.size());
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", 0);
|
||||
|
||||
glColor4fv(default_state.draw_color);
|
||||
}
|
||||
|
||||
void J2D::FillCircle(const Color4& color, const Vector2& center, float radius, unsigned int subdivisions) {
|
||||
BatchFillCircle(&color, ¢er, &radius, subdivisions, 1);
|
||||
Instance2D circle(color, center, Vector2(1, 1), Vector2(radius, radius));
|
||||
BatchFillCircle(&circle, subdivisions, 1);
|
||||
}
|
||||
|
||||
void J2D::BatchFillCircle(const Color4* colors, const Vector2* positions, float* radii, unsigned int subdivisions, const size_t& circle_count) {
|
||||
void J2D::BatchFillCircle(const JGL::Instance2D* instances, float subdivisions, const size_t &instance_count) {
|
||||
if (!state_stack.Size())
|
||||
Logger::Error("Drawing J2D element before J2D begin.");
|
||||
|
||||
if (circle_count <= 0)
|
||||
if (instance_count <= 0)
|
||||
return;
|
||||
|
||||
GLfloat angle, x, y;
|
||||
@@ -793,15 +1054,64 @@ void J2D::BatchFillCircle(const Color4* colors, const Vector2* positions, float*
|
||||
i++;
|
||||
}
|
||||
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
|
||||
for (size_t j = 0; j < circle_count; j++) {
|
||||
glPushMatrix();
|
||||
glColor4ubv(colors[j].ptr());
|
||||
glTranslatef(positions[j].x, positions[j].y, 0);
|
||||
glScalef(radii[j], radii[j], 0);
|
||||
auto vertex_buffer = VRamList(vertices.data(), vertices.size(), Stream);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer.Handle());
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", RENDERING_ROUTINE_ID::J2D_FillCircle);
|
||||
|
||||
if (instance_count == 1 || !supports_instanced || !current_state.current_shader) {
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), nullptr);
|
||||
|
||||
for (size_t j = 0; j < instance_count; j++) {
|
||||
glPushMatrix();
|
||||
glColor4ubv(instances[j].color.ptr());
|
||||
glTranslatef(instances[j].position.x, instances[j].position.y, 0);
|
||||
glScalef(instances[j].scale.x, instances[j].scale.y, 0);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, (int) vertices.size());
|
||||
glPopMatrix();
|
||||
glPopMatrix();
|
||||
}
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
else {
|
||||
current_state.current_shader->SetBool("JGL_INSTANCED_RENDERING", true);
|
||||
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), nullptr);
|
||||
glVertexAttribDivisorARB(0, 0);
|
||||
|
||||
VRamList instance_buffer((GLfloat*) instances, instance_count * (sizeof(Instance2D) / sizeof(GLfloat)), Stream);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, instance_buffer.Handle());
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Instance2D), (GLvoid*) offsetof(Instance2D, position));
|
||||
glVertexAttribDivisorARB(1, 1);
|
||||
|
||||
glEnableVertexAttribArray(2);
|
||||
// Swapped scale with size in this path because we always render a unit circle scaled up to the given size.
|
||||
// TODO implement scaling attribute in vertex shader.
|
||||
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Instance2D), (GLvoid*) offsetof(Instance2D, scale));
|
||||
glVertexAttribDivisorARB(2, 1);
|
||||
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Instance2D), (GLvoid*) offsetof(Instance2D, color));
|
||||
glVertexAttribDivisorARB(3, 1);
|
||||
|
||||
glDrawArraysInstancedARB(GL_TRIANGLE_FAN, 0, vertices.size(), instance_count);
|
||||
|
||||
glDisableVertexAttribArray(0);
|
||||
glDisableVertexAttribArray(1);
|
||||
glDisableVertexAttribArray(2);
|
||||
glDisableVertexAttribArray(3);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
current_state.current_shader->SetBool("JGL_INSTANCED_RENDERING", false);
|
||||
}
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", 0);
|
||||
|
||||
glColor4fv(default_state.draw_color);
|
||||
}
|
||||
|
||||
@@ -814,7 +1124,15 @@ void J2D::OutlineTriangle(const Color4& color, const Triangle2D& tri, float thic
|
||||
glLineWidth(thickness);
|
||||
glColor4ubv(color.ptr());
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", RENDERING_ROUTINE_ID::J2D_OutlineTriangle);
|
||||
|
||||
glDrawArrays(GL_LINE_LOOP, 0, 3);
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", 0);
|
||||
|
||||
glColor4fv(default_state.draw_color);
|
||||
}
|
||||
|
||||
@@ -826,7 +1144,15 @@ void J2D::FillTriangle(const Color4& color, const Triangle2D& tri) {
|
||||
|
||||
glColor4ubv(color.ptr());
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", RENDERING_ROUTINE_ID::J2D_FillTriangle);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", 0);
|
||||
|
||||
glColor4fv(default_state.draw_color);
|
||||
}
|
||||
|
||||
@@ -842,7 +1168,15 @@ void J2D::FillGradientTriangle(const Color4& a_color, const Color4& b_color, con
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glColorPointer(4, GL_FLOAT, sizeof(Color4), colors);
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", RENDERING_ROUTINE_ID::J2D_FillGradientTriangle);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", 0);
|
||||
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
glColor4fv(default_state.draw_color);
|
||||
}
|
||||
@@ -864,7 +1198,14 @@ void J2D::DrawCubicBezierCurve(const Color4& color, const Vector2& controlA, con
|
||||
}
|
||||
vertices[2 * subdivisions] = last;
|
||||
vertices[2 * subdivisions + 1] = first;
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", RENDERING_ROUTINE_ID::J2D_DrawCubicBezierCurve);
|
||||
|
||||
DrawLines(color, vertices.data(), vertices.size(), thickness);
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", 0);
|
||||
}
|
||||
|
||||
void J2D::OutlinePolygon(const Color4& color, const Vector2* points, int points_size, float thickness) {
|
||||
@@ -877,7 +1218,15 @@ void J2D::OutlinePolygon(const Color4& color, const Vector2* points, int points_
|
||||
glLineWidth(thickness);
|
||||
glColor4ubv(color.ptr());
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), points);
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", RENDERING_ROUTINE_ID::J2D_OutlinePolygon);
|
||||
|
||||
glDrawArrays(GL_LINE_LOOP, 0, points_size);
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", 0);
|
||||
|
||||
glColor4fv(default_state.draw_color);
|
||||
}
|
||||
|
||||
@@ -915,7 +1264,15 @@ void J2D::DrawArc(const Color4& color, const Vector2& center, float radius, floa
|
||||
glLineWidth(thickness);
|
||||
glColor4ubv(color.ptr());
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", RENDERING_ROUTINE_ID::J2D_DrawArc);
|
||||
|
||||
glDrawArrays(GL_LINE_STRIP, 0, (int) vertices.size());
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", 0);
|
||||
|
||||
glColor4fv(default_state.draw_color);
|
||||
}
|
||||
|
||||
@@ -969,6 +1326,9 @@ void J2D::OutlineRoundedRect(const Color4& color, const Vector2& pos, const Vect
|
||||
|
||||
unsigned int subdivisions = 9;
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", RENDERING_ROUTINE_ID::J2D_OutlineRoundedRect);
|
||||
|
||||
J2D::DrawArc(color, anchor_tl, radius, Math::Pi, 3.01f*Math::Pi/2.f, subdivisions, thickness);
|
||||
J2D::DrawLine(color, anchor_topleft_top, anchor_topright_top, thickness);
|
||||
J2D::DrawArc(color, anchor_tr, radius, 3.f*Math::Pi/2.f, 2.02*Math::Pi, subdivisions, thickness);
|
||||
@@ -977,13 +1337,22 @@ void J2D::OutlineRoundedRect(const Color4& color, const Vector2& pos, const Vect
|
||||
J2D::DrawLine(color, anchor_bottomright_bottom, anchor_bottomleft_bottom, thickness);
|
||||
J2D::DrawArc(color, anchor_bl, radius, Math::Pi/2, Math::Pi*1.01f, subdivisions, thickness);
|
||||
J2D::DrawLine(color, anchor_bottomleft_left, anchor_topleft_left, thickness);
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", 0);
|
||||
//J2D::End();
|
||||
|
||||
|
||||
}
|
||||
|
||||
void J2D::FillChamferRect(const Color4& color, const Vector2& pos, const Vector2& size, float radius) {
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", RENDERING_ROUTINE_ID::J2D_FillChamferRect);
|
||||
|
||||
FillRoundedRect(color, pos, size, radius, 4);
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", 0);
|
||||
}
|
||||
|
||||
void J2D::OutlineChamferRect(const Color4& color, const Vector2& pos, const Vector2& size, float radius, float thickness) {
|
||||
@@ -1000,15 +1369,59 @@ void J2D::OutlineChamferRect(const Color4& color, const Vector2& pos, const Vect
|
||||
glLineWidth(thickness);
|
||||
glColor4ubv(color.ptr());
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", RENDERING_ROUTINE_ID::J2D_OutlineChamferRect);
|
||||
|
||||
glDrawArrays(GL_LINE_LOOP, 0, 8);
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", 0);
|
||||
|
||||
glColor4fv(default_state.draw_color);
|
||||
}
|
||||
|
||||
void J2D::DrawPoints(const Color4& color, const Vector2* points, int num_points, float radius) {
|
||||
void J2D::DrawPoints(const Color4* colors, const Vector2* points, int point_count, float radius) {
|
||||
ShapeCache::draw_points_colors->SetData(colors, point_count);
|
||||
ShapeCache::draw_points_positions->SetData(points, point_count);
|
||||
|
||||
glPointSize(radius);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, ShapeCache::draw_points_colors->Handle());
|
||||
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Color4), nullptr);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, ShapeCache::draw_points_positions->Handle());
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), nullptr);
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", RENDERING_ROUTINE_ID::J2D_DrawPoints);
|
||||
|
||||
glDrawArrays(GL_POINTS, 0, point_count);
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", 0);
|
||||
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glColor4fv(default_state.draw_color);
|
||||
}
|
||||
|
||||
void J2D::DrawPoints(const Color4& color, const Vector2* points, int point_count, float radius) {
|
||||
ShapeCache::draw_points_positions->SetData(points, point_count);
|
||||
glPointSize(radius);
|
||||
glColor4ubv(color.ptr());
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), points);
|
||||
glDrawArrays(GL_POINTS, 0, num_points);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, ShapeCache::draw_points_positions->Handle());
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), nullptr);
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", RENDERING_ROUTINE_ID::J2D_DrawPoints);
|
||||
|
||||
glDrawArrays(GL_POINTS, 0, point_count);
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", 0);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glColor4fv(default_state.draw_color);
|
||||
}
|
||||
|
||||
@@ -1044,7 +1457,19 @@ void J2D::OutlineEllipse(const Color4& color, const Vector2& position, float rad
|
||||
glLineWidth(thickness);
|
||||
glColor4ubv(color.ptr());
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
|
||||
|
||||
/*
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", RENDERING_ROUTINE_ID::J2D_OutlineElipse);
|
||||
*/
|
||||
|
||||
glDrawArrays(GL_LINE_LOOP, 0, (int) vertices.size());
|
||||
|
||||
/*
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", 0);
|
||||
*/
|
||||
|
||||
glColor4fv(default_state.draw_color);
|
||||
}
|
||||
|
||||
@@ -1072,7 +1497,18 @@ void J2D::FillEllipse(const Color4& color, const Vector2& position, float radius
|
||||
|
||||
glColor4ubv(color.ptr());
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
|
||||
|
||||
/*
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", RENDERING_ROUTINE_ID::J2D_OutlineElipse);
|
||||
*/
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, (int) vertices.size());
|
||||
|
||||
/*
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", 0);
|
||||
*/
|
||||
glColor4fv(default_state.draw_color);
|
||||
}
|
||||
|
||||
@@ -1083,3 +1519,8 @@ void J2D::DrawSprite(const TextureAtlas* texture_atlas, const AtlasRegion& atlas
|
||||
void J2D::DrawSprite(const TextureAtlas& texture_atlas, const AtlasRegion& atlas_region, const Vector2& position, float rad_rotation, const Vector2& origin, const Vector2& scale, const Color4& color) {
|
||||
J2D::DrawSprite(&texture_atlas, atlas_region, position, rad_rotation, origin, scale, color);
|
||||
}
|
||||
|
||||
void J2D::DrawString(const Color4 &color, const std::string &text, const Vector2 &pos, u32 size, float scale,
|
||||
const Font &font) {
|
||||
DrawString(color, text, pos.x, pos.y, size, scale, font);
|
||||
}
|
||||
|
@@ -18,15 +18,15 @@ std::array<GLfloat, 16> JGL::OpenGLPerspectiveProjectionRH(float fovY, float asp
|
||||
return result;
|
||||
}
|
||||
|
||||
void J3D::ChangeFOV(float fov) {
|
||||
J3D::fov = fov;
|
||||
void JGL::J3D::ChangeFOV(float fov) {
|
||||
JGL::J3D::fov = fov;
|
||||
}
|
||||
|
||||
void J3D::ChangeFarPlane(float far_plane) {
|
||||
J3D::far_plane = far_plane;
|
||||
void JGL::J3D::ChangeFarPlane(float far_plane) {
|
||||
JGL::J3D::far_plane = far_plane;
|
||||
}
|
||||
|
||||
void J3D::RequiredLight(const LightBase* light) {
|
||||
void JGL::J3D::RequiredLight(const JGL::LightBase* light) {
|
||||
bool success = false;
|
||||
for (auto& i : current_state.required_lights)
|
||||
if (i == nullptr) {
|
||||
@@ -39,12 +39,12 @@ void J3D::RequiredLight(const LightBase* light) {
|
||||
Logger::Error("You cannot specify more than 8 required lights.");
|
||||
}
|
||||
|
||||
void J3D::OptionalLights(const LightBase** lights, const size_t& light_count) {
|
||||
void JGL::J3D::OptionalLights(const JGL::LightBase** lights, const size_t& light_count) {
|
||||
for (size_t i = 0; i < light_count; i++)
|
||||
current_state.optional_lights.push_back(lights[i]);
|
||||
}
|
||||
|
||||
void J3D::Begin(bool two_pass) {
|
||||
void JGL::J3D::Begin(bool two_pass) {
|
||||
auto aspect = (float) window_size.x / (float) window_size.y;
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
@@ -97,7 +97,7 @@ void J3D::Begin(bool two_pass) {
|
||||
glDisable(GL_LIGHTING);
|
||||
}
|
||||
|
||||
void J3D::End() {
|
||||
void JGL::J3D::End() {
|
||||
if (!current_state.depth_test)
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
@@ -138,7 +138,7 @@ void J3D::End() {
|
||||
glColor4fv(current_state.draw_color);
|
||||
}
|
||||
|
||||
void J3D::DrawLine(const Color4& color, const Vector3& A, const Vector3& B, float thickness) {
|
||||
void JGL::J3D::DrawLine(const Color4& color, const Vector3& A, const Vector3& B, float thickness) {
|
||||
Vector3 vertices[] = {A, B};
|
||||
|
||||
glLineWidth(thickness);
|
||||
@@ -148,16 +148,16 @@ void J3D::DrawLine(const Color4& color, const Vector3& A, const Vector3& B, floa
|
||||
glColor4fv(current_state.draw_color);
|
||||
}
|
||||
|
||||
void J3D::WireframeSphere(const Color4& color, const Vector3& position, float radius, float thickness, unsigned int sectors, unsigned int stacks) {
|
||||
void JGL::J3D::WireframeSphere(const Color4& color, const Vector3& position, float radius, float thickness, unsigned int sectors, unsigned int stacks) {
|
||||
Sphere sphere = {position, radius};
|
||||
BatchWireframeSphere(color,& sphere, 1, thickness, sectors, stacks);
|
||||
}
|
||||
|
||||
void J3D::WireframeSphere(const Color4& color, const Sphere& sphere, float thickness, unsigned int sectors, unsigned int stacks) {
|
||||
void JGL::J3D::WireframeSphere(const Color4& color, const Sphere& sphere, float thickness, unsigned int sectors, unsigned int stacks) {
|
||||
BatchWireframeSphere(color,& sphere, 1, thickness, sectors, stacks);
|
||||
}
|
||||
|
||||
void J3D::BatchWireframeSphere(const Color4& color, const Sphere* spheres, const size_t& sphere_count, float thickness, unsigned int sectors, unsigned int stacks) {
|
||||
void JGL::J3D::BatchWireframeSphere(const Color4& color, const Sphere* spheres, const size_t& sphere_count, float thickness, unsigned int sectors, unsigned int stacks) {
|
||||
// Create one sphere with a radius of 1 about 0, 0.
|
||||
float r = 1;
|
||||
std::vector<Vector3> vertices((sectors + 1) * (stacks + 1));
|
||||
@@ -196,16 +196,16 @@ void J3D::BatchWireframeSphere(const Color4& color, const Sphere* spheres, const
|
||||
glColor4fv(current_state.draw_color);
|
||||
}
|
||||
|
||||
void J3D::WireframeRevoSphere(const Color4& color, const Vector3& position, float radius, float thickness, unsigned int sectors, unsigned int revolutions, bool draw_stacks) {
|
||||
void JGL::J3D::WireframeRevoSphere(const Color4& color, const Vector3& position, float radius, float thickness, unsigned int sectors, unsigned int revolutions, bool draw_stacks) {
|
||||
Sphere sphere = {position, radius};
|
||||
BatchWireframeRevoSphere(color,& sphere, 1, thickness, sectors, revolutions, draw_stacks);
|
||||
}
|
||||
|
||||
void J3D::WireframeRevoSphere(const Color4& color, const Sphere& sphere, float thickness, unsigned int sectors, unsigned int revolutions, bool draw_stacks) {
|
||||
void JGL::J3D::WireframeRevoSphere(const Color4& color, const Sphere& sphere, float thickness, unsigned int sectors, unsigned int revolutions, bool draw_stacks) {
|
||||
BatchWireframeRevoSphere(color,& sphere, 1, thickness, sectors, revolutions, draw_stacks);
|
||||
}
|
||||
|
||||
void J3D::BatchWireframeRevoSphere(const Color4& color, const Sphere* spheres, const size_t& sphere_count, float thickness, unsigned int sectors, unsigned int revolutions, bool draw_stacks) {
|
||||
void JGL::J3D::BatchWireframeRevoSphere(const Color4& color, const Sphere* spheres, const size_t& sphere_count, float thickness, unsigned int sectors, unsigned int revolutions, bool draw_stacks) {
|
||||
float r = 1;
|
||||
std::vector<Vector3> vertices;
|
||||
vertices.reserve((sectors + 1) * (revolutions + 1));
|
||||
@@ -236,8 +236,9 @@ void J3D::BatchWireframeRevoSphere(const Color4& color, const Sphere* spheres, c
|
||||
glLineWidth(thickness);
|
||||
glColor4ubv(color.ptr());
|
||||
|
||||
// TODO allocate once.
|
||||
VRamList vertex_data(vertices.data(), vertices.size());
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vertex_data.GetHandle());
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vertex_data.Handle());
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(Vector3), nullptr);
|
||||
|
||||
// Render each sphere in the batch at their given position and radius.
|
||||
@@ -245,17 +246,17 @@ void J3D::BatchWireframeRevoSphere(const Color4& color, const Sphere* spheres, c
|
||||
glPushMatrix();
|
||||
glTranslatef(spheres[i].Position.x, spheres[i].Position.y, spheres[i].Position.z);
|
||||
glScalef(spheres[i].Radius, spheres[i].Radius, spheres[i].Radius);
|
||||
glDrawArrays(GL_LINE_LOOP, 0, vertex_data.GetLength());
|
||||
glDrawArrays(GL_LINE_LOOP, 0, vertex_data.Length());
|
||||
if (draw_stacks)
|
||||
glRotatef(90, 0, 1, 0),
|
||||
glDrawArrays(GL_LINE_LOOP, 0, vertex_data.GetLength());
|
||||
glDrawArrays(GL_LINE_LOOP, 0, vertex_data.Length());
|
||||
glPopMatrix();
|
||||
}
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glColor4fv(current_state.draw_color);
|
||||
}
|
||||
|
||||
void J3D::WireframeIcosphere(const Color4& color, const Vector3& position, float radius, float thickness, unsigned int subdivisions) {
|
||||
void JGL::J3D::WireframeIcosphere(const Color4& color, const Vector3& position, float radius, float thickness, unsigned int subdivisions) {
|
||||
|
||||
// NOTE2SELF: Code i'm borrowing this from uses float-packed-arrays rather than discrete Vectors
|
||||
// working on translating that correctly...
|
||||
@@ -325,7 +326,7 @@ void J3D::WireframeIcosphere(const Color4& color, const Vector3& position, float
|
||||
}
|
||||
}
|
||||
|
||||
void J3D::WireframeIcosahedron(const Color4& color, const Vector3& position, float radius, float thickness) {
|
||||
void JGL::J3D::WireframeIcosahedron(const Color4& color, const Vector3& position, float radius, float thickness) {
|
||||
// TODO: Revise this once J3ML::Geometry::Icosahedron is implemented.
|
||||
const float h_angle = J3ML::Math::Pi / 180.f * 72.f; // 72 degree = 360 / 5;
|
||||
const float v_angle = J3ML::Math::Atan(1.0f / 2.f); // elevation = 26.565;
|
||||
@@ -367,13 +368,13 @@ void J3D::WireframeIcosahedron(const Color4& color, const Vector3& position, flo
|
||||
glColor4fv(current_state.draw_color);
|
||||
}
|
||||
|
||||
void J3D::BatchWireframeAABB(const Color4& color, const AABB* boxes, const size_t& box_count, float thickness) {
|
||||
void JGL::J3D::BatchWireframeAABB(const Color4& color, const AABB* boxes, const size_t& box_count, float thickness) {
|
||||
glColor4ubv(color.ptr());
|
||||
glLineWidth(thickness);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, ShapeCache::cube_vertex_data->GetHandle());
|
||||
glBindBuffer(GL_ARRAY_BUFFER, ShapeCache::cube_vertex_data->Handle());
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(Vector3), nullptr);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ShapeCache::cube_index_data->GetHandle());
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ShapeCache::cube_index_data->Handle());
|
||||
|
||||
for (size_t i = 0; i < box_count; i++) {
|
||||
Vector3 delta = (boxes[i].maxPoint - boxes[i].minPoint) / 2;
|
||||
@@ -381,45 +382,24 @@ void J3D::BatchWireframeAABB(const Color4& color, const AABB* boxes, const size_
|
||||
glPushMatrix();
|
||||
glTranslatef(center.x, center.y, center.z);
|
||||
glScalef(delta.x, delta.y, delta.z);
|
||||
glDrawElements(GL_LINE_LOOP, ShapeCache::cube_index_data->GetLength(), GL_UNSIGNED_INT, nullptr);
|
||||
glDrawElements(GL_LINE_LOOP, ShapeCache::cube_index_data->Length(), GL_UNSIGNED_INT, nullptr);
|
||||
glPopMatrix();
|
||||
}
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glColor4fv(current_state.draw_color);
|
||||
}
|
||||
|
||||
void J3D::WireframeOBB(const Color4& color, const Vector3& center, const Vector3& radii, const Matrix3x3& rotation_matrix, float thickness) {
|
||||
glColor4ubv(color.ptr());
|
||||
glLineWidth(thickness);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, ShapeCache::cube_vertex_data->GetHandle());
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(Vector3), nullptr);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ShapeCache::cube_index_data->GetHandle());
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(center.x, center.y, center.z);
|
||||
// TODO AxisAngle directly from rotation matrix.
|
||||
AxisAngle rotate_part = AxisAngle(Quaternion(rotation_matrix));
|
||||
glRotatef(rotate_part.angle, rotate_part.axis.x, rotate_part.axis.y, rotate_part.axis.z);
|
||||
glScalef(radii.x, radii.y, radii.z);
|
||||
glDrawElements(GL_LINE_LOOP, ShapeCache::cube_index_data->GetLength(), GL_UNSIGNED_INT, nullptr);
|
||||
glPopMatrix();
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glColor4fv(current_state.draw_color);
|
||||
}
|
||||
|
||||
void J3D::WireframeAABB(const Color4& color, const Vector3& pos, const Vector3& radii, float thickness) {
|
||||
void JGL::J3D::WireframeAABB(const Color4& color, const Vector3& pos, const Vector3& radii, float thickness) {
|
||||
AABB aabb = {Vector3(pos.x - radii.x, pos.y - radii.y, pos.z - radii.z), Vector3(pos.x + radii.x, pos.y + radii.y, pos.z + radii.z)};
|
||||
BatchWireframeAABB(color, &aabb, 1, thickness);
|
||||
}
|
||||
|
||||
void J3D::BatchFillAABB(const Color4& color, const AABB* boxes, const size_t& box_count) {
|
||||
void JGL::J3D::BatchFillAABB(const Color4& color, const AABB* boxes, const size_t& box_count) {
|
||||
glColor4ubv(color.ptr());
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, ShapeCache::cube_vertex_data->GetHandle());
|
||||
glBindBuffer(GL_ARRAY_BUFFER, ShapeCache::cube_vertex_data->Handle());
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(Vector3), nullptr);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ShapeCache::cube_index_data->GetHandle());
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ShapeCache::cube_index_data->Handle());
|
||||
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
@@ -428,7 +408,7 @@ void J3D::BatchFillAABB(const Color4& color, const AABB* boxes, const size_t& bo
|
||||
if (UsingLighting()) {
|
||||
using_lights = true;
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, ShapeCache::cube_normal_data->GetHandle());
|
||||
glBindBuffer(GL_ARRAY_BUFFER, ShapeCache::cube_normal_data->Handle());
|
||||
glNormalPointer(GL_FLOAT, sizeof(float), nullptr);
|
||||
}
|
||||
|
||||
@@ -451,20 +431,20 @@ void J3D::BatchFillAABB(const Color4& color, const AABB* boxes, const size_t& bo
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
glDisable(GL_CULL_FACE);
|
||||
}
|
||||
void J3D::FillAABB(const Color4& color, const Vector3& pos, const Vector3& radii) {
|
||||
void JGL::J3D::FillAABB(const Color4& color, const Vector3& pos, const Vector3& radii) {
|
||||
AABB box = {pos - radii, pos + radii};
|
||||
BatchFillAABB(color, &box, 1);
|
||||
}
|
||||
|
||||
void J3D::FillAABB(const Color4& color, const AABB& aabb) {
|
||||
void JGL::J3D::FillAABB(const Color4& color, const AABB& aabb) {
|
||||
BatchFillAABB(color, &aabb, 1);
|
||||
}
|
||||
|
||||
void J3D::FillSphere(const Color4& color, const Sphere& sphere, unsigned int sectors, unsigned int stacks) {
|
||||
void JGL::J3D::FillSphere(const Color4& color, const Sphere& sphere, unsigned int sectors, unsigned int stacks) {
|
||||
BatchFillSphere(color, &sphere, 1, sectors, stacks);
|
||||
}
|
||||
|
||||
void J3D::BatchFillSphere(const Color4& color, const Sphere* spheres, const size_t& sphere_count, unsigned int sectors, unsigned int stacks) {
|
||||
void JGL::J3D::BatchFillSphere(const Color4& color, const Sphere* spheres, const size_t& sphere_count, unsigned int sectors, unsigned int stacks) {
|
||||
float r = 1;
|
||||
std::vector<Vector3> vertices((sectors + 1) * (stacks + 1));
|
||||
std::vector<unsigned int> indices; indices.reserve(sectors * stacks * 6);
|
||||
@@ -507,8 +487,8 @@ void J3D::BatchFillSphere(const Color4& color, const Sphere* spheres, const size
|
||||
VRamList index_data(indices.data(), indices.size());
|
||||
|
||||
glColor4ubv(color.ptr());
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vertex_data.GetHandle());
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_data.GetHandle());
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vertex_data.Handle());
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_data.Handle());
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(Vector3), nullptr);
|
||||
|
||||
for (size_t i = 0; i < sphere_count; i++) {
|
||||
@@ -516,7 +496,7 @@ void J3D::BatchFillSphere(const Color4& color, const Sphere* spheres, const size
|
||||
glPushMatrix();
|
||||
glTranslatef(position.x, position.y, position.z);
|
||||
glScalef(spheres[i].Radius, spheres[i].Radius, spheres[i].Radius);
|
||||
glDrawElements(GL_TRIANGLES, index_data.GetLength(), GL_UNSIGNED_INT, nullptr);
|
||||
glDrawElements(GL_TRIANGLES, index_data.Length(), GL_UNSIGNED_INT, nullptr);
|
||||
glPopMatrix();
|
||||
}
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
@@ -524,16 +504,50 @@ void J3D::BatchFillSphere(const Color4& color, const Sphere* spheres, const size
|
||||
glColor4fv(current_state.draw_color);
|
||||
}
|
||||
|
||||
void J3D::FillSphere(const Color4& color, const Vector3& position, float radius, unsigned int sectors, unsigned int stacks) {
|
||||
void JGL::J3D::FillSphere(const Color4& color, const Vector3& position, float radius, unsigned int sectors, unsigned int stacks) {
|
||||
Sphere sphere = {position, radius};
|
||||
BatchFillSphere(color, &sphere, 1, sectors, stacks);
|
||||
}
|
||||
|
||||
void J3D::WireframeAABB(const Color4& color, const AABB& aabb, float thickness) {
|
||||
void JGL::J3D::WireframeAABB(const Color4& color, const AABB& aabb, float thickness) {
|
||||
BatchWireframeAABB(color, &aabb, 1, thickness);
|
||||
}
|
||||
|
||||
void J3D::DrawCubicBezierCurve(const Color4& color, const Vector3& controlA, const Vector3& pointA,
|
||||
// TODO Make it work the same as AABB batching. I couldn't get rotation to do anything more than twitch in place :(.
|
||||
void JGL::J3D::BatchWireframeOBB(const Color4& color, const OBB* boxes, const size_t& box_count, float thickness) {
|
||||
std::array<Vector3, 8> corner_points;
|
||||
std::array<GLuint, 24> indices =
|
||||
{
|
||||
0, 1, 1, 2, 2, 3, 3, 0,
|
||||
4, 5, 5, 6, 6, 7, 7, 4,
|
||||
0, 4, 1, 5, 2, 6, 3, 7
|
||||
};
|
||||
|
||||
glLineWidth(thickness);
|
||||
glColor4ubv(color.ptr());
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(Vector3), corner_points.data());
|
||||
|
||||
for (size_t i = 0; i < box_count; i++) {
|
||||
boxes[i].GetCornerPoints(corner_points.data());
|
||||
glPushMatrix();
|
||||
glTranslatef(boxes[i].pos.x, boxes[i].pos.y, boxes[i].pos.z);
|
||||
glDrawElements(GL_LINES, indices.size(), GL_UNSIGNED_INT, indices.data());
|
||||
glPopMatrix();
|
||||
}
|
||||
glColor4fv(current_state.draw_color);
|
||||
}
|
||||
|
||||
void JGL::J3D::WireframeOBB(const Color4& color, const OBB& obb, float thickness) {
|
||||
BatchWireframeOBB(color, &obb, 1, thickness);
|
||||
}
|
||||
|
||||
/*
|
||||
void JGL::J3D::WireframeOBB(const Color4& color, const Vector3& position, const Vector3& radii, const Matrix3x3& orientation, float thickness) {
|
||||
WireframeOBB(color, OBB(position, radii, orientation. * Vector3::UnitX, rotation * Vector3::UnitY, rotation * Vector3::UnitZ), thickness);
|
||||
}
|
||||
*/
|
||||
|
||||
void JGL::J3D::DrawCubicBezierCurve(const Color4& color, const Vector3& controlA, const Vector3& pointA,
|
||||
const Vector3& pointB, const Vector3& controlB, int subdivisions, float thickness) {
|
||||
Vector3 last = controlA;
|
||||
const Vector3& first = controlB;
|
||||
@@ -549,17 +563,17 @@ void J3D::DrawCubicBezierCurve(const Color4& color, const Vector3& controlA, con
|
||||
DrawLine(color, last, first, thickness);
|
||||
}
|
||||
|
||||
void J3D::DrawVertexArray(const Color4& color, const VertexArray& vertex_array, const Vector3& position) {
|
||||
void JGL::J3D::DrawVertexArray(const Color4& color, const VertexArray& vertex_array, const Vector3& position) {
|
||||
glColor4ubv(color.ptr());
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vertex_array.GetVertices()->GetHandle());
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vertex_array.GetVertices()->Handle());
|
||||
glVertexPointer(3, GL_FLOAT, 0, nullptr);
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(position.x, position.y, position.z);
|
||||
//glScalef(1,1,1);
|
||||
glDrawArrays(GL_TRIANGLES, 0, vertex_array.GetVertices()->GetLength());
|
||||
glDrawArrays(GL_TRIANGLES, 0, vertex_array.GetVertices()->Length());
|
||||
glPopMatrix();
|
||||
|
||||
//glDrawElements(GL_LINES, vertex_array.GetIndices()->GetLength(), GL_UNSIGNED_INT, nullptr);
|
||||
@@ -567,4 +581,5 @@ void J3D::DrawVertexArray(const Color4& color, const VertexArray& vertex_array,
|
||||
glColor4fv(current_state.draw_color);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
|
||||
}
|
@@ -86,7 +86,10 @@ namespace JGL {
|
||||
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)));
|
||||
float ascent = font.face->size->metrics.ascender / 64.0f;
|
||||
float descent = -font.face->size->metrics.descender / 64.0f;
|
||||
|
||||
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), ascent, descent));
|
||||
|
||||
xoffset += g->bitmap.width;
|
||||
charcode = FT_Get_Next_Char(font.face, charcode, &gindex);
|
||||
@@ -95,7 +98,7 @@ namespace JGL {
|
||||
return cachedFont;
|
||||
}
|
||||
|
||||
void J2D::DrawString(const Color4& color, const std::string& text, float x, float y, float scale, u32 size, const Font& font) {
|
||||
void J2D::DrawString(const Color4& color, const std::string& text, float x, float y, u32 size, float scale, const Font& font) {
|
||||
// Offset by height to render at "correct" location.
|
||||
y += size;
|
||||
|
||||
@@ -134,7 +137,7 @@ namespace JGL {
|
||||
continue;
|
||||
|
||||
x2 = x + glyph->x2offset * scale;
|
||||
y2 = y - glyph->y2offset * scale; // Adjust y-coordinate
|
||||
y2 = y - glyph->y2offset * scale;
|
||||
w = glyph->w * scale;
|
||||
h = glyph->h * scale;
|
||||
x += glyph->advanceX * scale;
|
||||
@@ -156,7 +159,17 @@ namespace JGL {
|
||||
}
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(Vector2), texcoords.data());
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("TEXTURE_UNIT_SET_COUNT", 1),
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", RENDERING_ROUTINE_ID::J2D_DrawString);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, (int) vertices.size() * 6);
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("TEXTURE_UNIT_SET_COUNT", 0),
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", 0);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glColor4fv(default_state.draw_color);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
@@ -238,8 +251,18 @@ namespace JGL {
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
|
||||
/*
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", RENDERING_ROUTINE_ID::J2D_DrawString);
|
||||
*/
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, (int) vertices.size() * 6);
|
||||
|
||||
/*
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", 0);
|
||||
*/
|
||||
|
||||
if (!draw_back_face)
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
|
@@ -133,7 +133,7 @@ JGL::State* JGL::StateStack::PreviousState() {
|
||||
return &states.back();
|
||||
}
|
||||
|
||||
JGL::State JGL::State::SaveState() {
|
||||
JGL::State JGL::State::SaveState(const State& state) {
|
||||
State result;
|
||||
|
||||
result.depth_test = glIsEnabled(GL_DEPTH_TEST);
|
||||
@@ -152,6 +152,8 @@ JGL::State JGL::State::SaveState() {
|
||||
glGetFloatv(GL_CURRENT_COLOR, result.draw_color);
|
||||
glGetIntegerv(GL_VIEWPORT, result.viewport);
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*)&result.current_fbo);
|
||||
glGetIntegerv(GL_CURRENT_PROGRAM, &result.current_shader_handle);
|
||||
result.current_shader = state.current_shader;
|
||||
glGetIntegerv(GL_BLEND_SRC, &result.blend_func[0]);
|
||||
glGetIntegerv(GL_BLEND_DST, &result.blend_func[1]);
|
||||
|
||||
@@ -184,7 +186,6 @@ void JGL::State::RestoreState(const State& state) {
|
||||
else
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
|
||||
glActiveTexture(GL_TEXTURE0 + state.selected_texture_unit);
|
||||
glClientActiveTexture(GL_TEXTURE0 + state.selected_texture_unit);
|
||||
|
||||
@@ -203,10 +204,14 @@ void JGL::State::RestoreState(const State& state) {
|
||||
else
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
if (state.current_shader)
|
||||
glUseProgram(state.current_shader->Handle());
|
||||
else
|
||||
glUseProgram(0);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, state.current_fbo);
|
||||
glViewport(state.viewport[0], state.viewport[1], state.viewport[2], state.viewport[3]);
|
||||
glClearColor(state.clear_color[0], state.clear_color[1], state.clear_color[2], state.clear_color[3]);
|
||||
glColor4f(state.draw_color[0], state.draw_color[1], state.draw_color[2], state.draw_color[3]);
|
||||
glBlendFunc(state.blend_func[0], state.blend_func[1]);
|
||||
|
||||
}
|
||||
|
@@ -6,21 +6,59 @@
|
||||
#include <J3ML/LinearAlgebra/Vector2.hpp>
|
||||
#include <JGL/types/RenderTarget.h>
|
||||
#include <JGL/types/Light.h>
|
||||
#include <JGL/types/Shader.h>
|
||||
#include <JGL/logger/logger.h>
|
||||
|
||||
namespace JGL {
|
||||
class State;
|
||||
class StateStack;
|
||||
enum RENDERING_ROUTINE_ID : int32_t;
|
||||
}
|
||||
|
||||
enum JGL::RENDERING_ROUTINE_ID : int32_t {
|
||||
J2D_DrawPoint = 1,
|
||||
J2D_DrawPoints = 2,
|
||||
J2D_DrawLine = 3,
|
||||
J2D_DrawLines = 4,
|
||||
J2D_DrawDottedLine = 5,
|
||||
J2D_DrawDashedLine = 6,
|
||||
J2D_DrawGradientLine = 7,
|
||||
J2D_OutlineRect = 8,
|
||||
J2D_OutlineRoundedRect = 9,
|
||||
J2D_OutlineChamferRect = 10,
|
||||
J2D_FillRect = 11,
|
||||
J2D_FillGradientRect = 12,
|
||||
J2D_FillRoundedRect = 13,
|
||||
J2D_FillChamferRect = 14,
|
||||
J2D_DrawRenderTarget = 15,
|
||||
J2D_DrawPartialRenderTarget = 16,
|
||||
J2D_DrawSprite = 17,
|
||||
J2D_DrawAlphaMaskSprite = 18,
|
||||
J2D_DrawPartialSprite = 19,
|
||||
J2D_DrawMirrorSprite = 20,
|
||||
J2D_OutlineCircle = 21,
|
||||
J2D_FillCircle = 22,
|
||||
J2D_OutlineTriangle = 23,
|
||||
J2D_FillTriangle = 24,
|
||||
J2D_FillGradientTriangle = 25,
|
||||
J2D_DrawCubicBezierCurve = 26,
|
||||
J2D_OutlinePolygon = 27,
|
||||
J2D_DrawString = 28,
|
||||
J2D_DrawArc = 29,
|
||||
};
|
||||
|
||||
class JGL::State {
|
||||
public:
|
||||
|
||||
//Matrix4x4 transformation = Matrix4x4::Identity;
|
||||
GLfloat clear_color[4] = {0, 0, 0, 1};
|
||||
GLfloat draw_color[4] = {1, 1, 1, 1};
|
||||
GLint viewport[4] = {0, 0, 0, 0};
|
||||
GLint blend_func[2];
|
||||
GLuint current_fbo = 0;
|
||||
RenderTarget* current_render_target = nullptr;
|
||||
GLint current_shader_handle = 0;
|
||||
Shader* current_shader = nullptr;
|
||||
|
||||
bool texture_2D = false;
|
||||
bool texture_coordinate_array = false;
|
||||
@@ -36,7 +74,7 @@ public:
|
||||
// List of all lights in the scene.
|
||||
std::vector<const LightBase*> optional_lights{};
|
||||
public:
|
||||
static State SaveState();
|
||||
static State SaveState(const State& state);
|
||||
static void RestoreState(const State& state);
|
||||
};
|
||||
|
||||
@@ -58,6 +96,7 @@ namespace JGL {
|
||||
std::vector<Vector3> TriangleMeshVertexNormals(const Vector3* vertices, const size_t& vertex_count, const unsigned int* indices, const size_t& index_count);
|
||||
inline StateStack state_stack;
|
||||
inline Vector2i window_size;
|
||||
inline bool supports_instanced = true;
|
||||
}
|
||||
|
||||
namespace JGL::J2D {
|
||||
@@ -68,7 +107,7 @@ namespace JGL::J2D {
|
||||
{1, 1, 1, 1},
|
||||
{0, 0, 0, 0},
|
||||
{GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA},
|
||||
0, nullptr, false, false,
|
||||
0, nullptr, 0, nullptr, false, false,
|
||||
false, false, true, true,
|
||||
true, false, 0,
|
||||
{}, {}
|
||||
|
@@ -108,61 +108,36 @@ namespace JGL {
|
||||
return Font(path);
|
||||
}
|
||||
|
||||
Vector2 Font::MeasureString(const std::string &text, unsigned int ptSize) {
|
||||
Vector2 extents = Vector2(0,0);
|
||||
bool font_of_size_in_cache = false;
|
||||
Vector2 Font::MeasureString(const std::string& text, unsigned int ptSize) {
|
||||
Vector2 extents = Vector2::Zero;
|
||||
|
||||
for(const auto& f : fontCache.getFonts()) {
|
||||
if (f->getFontSize() == ptSize) {
|
||||
font_of_size_in_cache = true;
|
||||
break;
|
||||
for(auto& f : fontCache.getFonts()) {
|
||||
// This edit technically "works" by solving the immediate problem of text-bounds returning incorrectly,
|
||||
// But I am **sure** this is not how it should be implemented, I will leave that to Will to fix.
|
||||
|
||||
if (f->getFontIndex() == this->index && f->getFontSize() == ptSize) {
|
||||
|
||||
for (const char &c: text) {
|
||||
auto glyph = f->getGlyph(c);
|
||||
extents.x += glyph->advanceX;
|
||||
extents.y = glyph->ascent + glyph->descent;
|
||||
}
|
||||
return extents;
|
||||
}
|
||||
}
|
||||
|
||||
if (font_of_size_in_cache) {
|
||||
CachedFont* font;
|
||||
|
||||
for (auto* f: fontCache.getFonts())
|
||||
if (f->getFontSize() == ptSize)
|
||||
font = f;
|
||||
|
||||
for (const char& c : text)
|
||||
extents.x += font->getGlyph(c)->advanceX;
|
||||
|
||||
extents.y = ptSize;
|
||||
return extents;
|
||||
}
|
||||
|
||||
jlog::Warning("Measuring a font size that is not cached, Defaulting to Jupiteroid.");
|
||||
FT_Set_Pixel_Sizes(Fonts::Jupiteroid.face, ptSize, ptSize);
|
||||
|
||||
// No cache
|
||||
FT_Set_Pixel_Sizes(this->face, ptSize, ptSize);
|
||||
for (const char& c : text) {
|
||||
// TODO: Fix segfault
|
||||
//FT_GlyphSlot slot = Fonts::Jupiteroid.face->glyph;
|
||||
//auto glyph_index = FT_Get_Char_Index(Fonts::Jupiteroid.face, c);
|
||||
FT_GlyphSlot slot = face->glyph;
|
||||
auto glyph_index = FT_Get_Char_Index(this->face, c);
|
||||
|
||||
//auto error = FT_Load_Glyph(Fonts::Jupiteroid.face, glyph_index, FT_LOAD_DEFAULT);
|
||||
auto error = FT_Load_Glyph(this->face, glyph_index, FT_LOAD_DEFAULT);
|
||||
|
||||
if (error)
|
||||
continue;
|
||||
|
||||
|
||||
Vector2 advance = {static_cast<float>(slot->advance.x >> 6),
|
||||
static_cast<float>(slot->advance.y >> 6)};
|
||||
|
||||
|
||||
extents += advance;
|
||||
|
||||
// Gives smaller results than we'd want.
|
||||
if (extents.y < slot->metrics.height / 64)
|
||||
extents.y = slot->metrics.height / 64;
|
||||
|
||||
// Just fucking hardcode it, we know the glyph height is roughly always the ptSize anyway.
|
||||
if (extents.y < ptSize)
|
||||
extents.y = ptSize;
|
||||
extents.x += static_cast<float>(slot->advance.x >> 6);
|
||||
extents.y = (face->size->metrics.ascender / 64.0f) + (-face->size->metrics.descender / 64.0f);
|
||||
}
|
||||
return extents;
|
||||
}
|
||||
|
@@ -10,7 +10,7 @@ std::array<GLfloat, 12> CachedGlyph::getTexCoords() const {
|
||||
return texcoords;
|
||||
}
|
||||
|
||||
CachedGlyph::CachedGlyph(char c, std::array<GLfloat, 12> texcoords, float x2offset, float y2offset, float w, float h, float advanceX, float advanceY) {
|
||||
CachedGlyph::CachedGlyph(char c, std::array<GLfloat, 12> texcoords, float x2offset, float y2offset, float w, float h, float advanceX, float advanceY, float asc, float desc) {
|
||||
character = c;
|
||||
this->x2offset = x2offset;
|
||||
this->y2offset = y2offset;
|
||||
@@ -19,6 +19,8 @@ CachedGlyph::CachedGlyph(char c, std::array<GLfloat, 12> texcoords, float x2offs
|
||||
this->advanceX = advanceX;
|
||||
this->advanceY = advanceY;
|
||||
this->texcoords = texcoords;
|
||||
this->ascent = asc;
|
||||
this->descent = desc;
|
||||
}
|
||||
|
||||
void JGL::CachedFont::appendGlyph(JGL::CachedGlyph* glyph) {
|
||||
|
@@ -1,71 +0,0 @@
|
||||
#include <JGL/types/Light2D.h>
|
||||
#include <J3ML/LinearAlgebra/Vector2.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
JGL::J2D::PointLight::PointLight(const Vector2& position, const Color4& ambient, const Color4& diffuse, float constant_attenuation, float linear_attenuation, float quadratic_attenuation) {
|
||||
light_pos = Vector4(position.x, position.y, 1, 1);
|
||||
this->ambient = ambient;
|
||||
this->diffuse = diffuse;
|
||||
this->constant_attenuation = constant_attenuation;
|
||||
this->linear_attenuation = linear_attenuation;
|
||||
this->quadratic_attenuation = quadratic_attenuation;
|
||||
}
|
||||
|
||||
float JGL::J2D::PointLight::MeasureIntensityAtPosition(const Vector2& position) const {
|
||||
float d = Vector2::Distance( Vector2(light_pos.x, light_pos.y), position);
|
||||
|
||||
// Fix possible divide by zero if the position we're measuring happens to be directly on-top of the light.
|
||||
if (d == 0)
|
||||
d = 0.00001;
|
||||
|
||||
return 1.f / (constant_attenuation + linear_attenuation * d + quadratic_attenuation * d * d);
|
||||
}
|
||||
|
||||
Vector2 JGL::J2D::Light::Position() const {
|
||||
return { light_pos.x, light_pos.y };
|
||||
}
|
||||
|
||||
Color4 JGL::J2D::Light::Ambient() const {
|
||||
return ambient;
|
||||
}
|
||||
|
||||
Color4 JGL::J2D::Light::Diffuse() const {
|
||||
return diffuse;
|
||||
}
|
||||
|
||||
float JGL::J2D::Light::Constant() const {
|
||||
return constant_attenuation;
|
||||
}
|
||||
|
||||
float JGL::J2D::Light::Linear() const {
|
||||
return linear_attenuation;
|
||||
}
|
||||
|
||||
float JGL::J2D::Light::Quadratic() const {
|
||||
return quadratic_attenuation;
|
||||
}
|
||||
|
||||
void JGL::J2D::Light::Position(const Vector2& new_position) {
|
||||
light_pos.x = new_position.x;
|
||||
light_pos.y = new_position.y;
|
||||
}
|
||||
|
||||
void JGL::J2D::Light::Ambient(const Color4& new_ambient) {
|
||||
ambient = new_ambient;
|
||||
}
|
||||
|
||||
void JGL::J2D::Light::Diffuse(const Color4& new_diffuse) {
|
||||
diffuse = new_diffuse;
|
||||
}
|
||||
|
||||
void JGL::J2D::Light::Constant(float new_constant_attenuation) {
|
||||
constant_attenuation = std::clamp(new_constant_attenuation, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
void JGL::J2D::Light::Linear(float new_linear_attenuation) {
|
||||
linear_attenuation = std::clamp(new_linear_attenuation, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
void JGL::J2D::Light::Quadratic(float new_quadratic_attenuation) {
|
||||
quadratic_attenuation = std::clamp(new_quadratic_attenuation, 0.0f, 1.0f);
|
||||
}
|
269
src/types/Shader.cpp
Normal file
269
src/types/Shader.cpp
Normal file
@@ -0,0 +1,269 @@
|
||||
#include <JGL/types/Shader.h>
|
||||
|
||||
#include <glad/glad.h>
|
||||
|
||||
namespace JGL {
|
||||
|
||||
class ShaderPreprocessor {
|
||||
public:
|
||||
std::string include_keyword = "#include";
|
||||
ShaderPreprocessor() {}
|
||||
std::string LoadShaderFile(const std::filesystem::path& filepath)
|
||||
{
|
||||
// if size is 0, it indicates, that we are at the top of the recursive load stack
|
||||
bool stack_top = (already_included.size() == 0);
|
||||
|
||||
if (stack_top) {
|
||||
already_included.emplace_back(filepath.string());
|
||||
}
|
||||
|
||||
std::string ret_data = "";
|
||||
std::ifstream file(filepath);
|
||||
|
||||
if (!file.good())
|
||||
{
|
||||
std::cout << "ERROR [ ShaderLoader::load_shader ]: Failed to start fstream, check if '" << filepath << "' exists\n";
|
||||
return ret_data;
|
||||
}
|
||||
|
||||
if (file.is_open()) {
|
||||
std::string line;
|
||||
while (getline(file, line)) {
|
||||
if (line.find(include_keyword) == 0)
|
||||
{
|
||||
// Get path between double quotes
|
||||
std::string rel_include_path = extract_first_between(line.substr(include_keyword.length()), '"', '"');
|
||||
|
||||
// Modify path according to os
|
||||
// TODO: Use std::filesystem dummy...
|
||||
// later, let me get this stolen code to work first.
|
||||
#ifdef _WIN32
|
||||
std::replace(rel_include_path.begin(), rel_include_path.end(), '/', '\\');
|
||||
#elif __linux__
|
||||
std::replace(rel_include_path.begin(), rel_include_path.end(), '\\', '/');
|
||||
#endif
|
||||
std::string full_include_path = extract_path(filepath.string()) + rel_include_path;
|
||||
|
||||
// Avoid including self
|
||||
if (filepath == full_include_path) {
|
||||
std::cout << "WARNING [ ShaderLoader::load_shader ]: '"<< filepath <<"' tried to include itself\n";
|
||||
continue;
|
||||
} else {
|
||||
bool include_flag = true;
|
||||
// check if the current file is already included
|
||||
for (const auto& file_to_check : already_included) {
|
||||
// Avoid duplicate includes
|
||||
if (file_to_check == full_include_path) {
|
||||
include_flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If not yet included, push path to include vector and replace line with file contents
|
||||
if (include_flag) {
|
||||
already_included.push_back(full_include_path);
|
||||
// Repeat recursively.
|
||||
ret_data += LoadShaderFile(full_include_path) + '\n';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ret_data += line + "\n";
|
||||
}
|
||||
}
|
||||
file.close();
|
||||
} else {
|
||||
std::cout << "ERROR [ ShaderLoader::load_shader ]: Unable to open file '" << filepath << "'\n";
|
||||
}
|
||||
|
||||
// We are back to the first call
|
||||
if (stack_top) {
|
||||
already_included.clear();
|
||||
}
|
||||
return ret_data;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
std::string PreprocessShaderSource(const std::string& source);
|
||||
private:
|
||||
std::vector<std::string> already_included;
|
||||
/// Helper function that strips filename from a path, basically getting the path to the directory containing the file.
|
||||
std::string extract_path(const std::string& path)
|
||||
{
|
||||
// find the position of the last directory separator.
|
||||
std::size_t pos = path.find_last_of("\\/");
|
||||
|
||||
// strip fname from path
|
||||
if (pos != std::string::npos) {
|
||||
return path.substr(0, pos+1);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
std::string extract_first_between(const std::string& input, char start_symbol, char end_symbol)
|
||||
{
|
||||
size_t start_index = input.find(start_symbol);
|
||||
size_t end_index = input.find(end_symbol, start_index+1);
|
||||
|
||||
std::string extracted = "";
|
||||
if (start_index != std::string::npos && end_index != std::string::npos) {
|
||||
extracted = input.substr(start_index + 1, end_index - start_index - 1);
|
||||
} else {
|
||||
std::cout << "ERROR [ ShaderLoader::extract_first_between ]: Start '" << start_symbol << "' or end symbol '" << end_symbol << "' not found" << std::endl;
|
||||
}
|
||||
return extracted;
|
||||
}
|
||||
};
|
||||
|
||||
Shader::Shader(const std::filesystem::path& vertex_source_path, const std::filesystem::path& fragment_source_path, const std::vector<std::pair<std::string, GLint>>& attribute_bindings) :
|
||||
Shader(ReadFile(vertex_source_path), ReadFile(fragment_source_path), attribute_bindings) {
|
||||
vertexPath = vertex_source_path.string();
|
||||
fragmentPath = fragment_source_path.string();
|
||||
}
|
||||
|
||||
void Shader::checkCompileErrors(GLuint shader, const std::string& type) {
|
||||
GLint success;
|
||||
GLchar infoLog[1024];
|
||||
|
||||
if (type != "PROGRAM") {
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
|
||||
if (!success) {
|
||||
glGetShaderInfoLog(shader, 1024, nullptr, infoLog);
|
||||
OnCompilationErrorMessage.Invoke( std::format("COMPILATION_ERROR: {}", type), infoLog);
|
||||
}
|
||||
} else {
|
||||
glGetProgramiv(shader, GL_LINK_STATUS, &success);
|
||||
if (!success) {
|
||||
glGetProgramInfoLog(shader, 1024, nullptr, infoLog);
|
||||
OnCompilationErrorMessage.Invoke(std::format("COMPILATION_ERROR: {}", type), infoLog);
|
||||
}
|
||||
}
|
||||
|
||||
if (success)
|
||||
std::cout << "Shader compiled successfully" << std::endl;
|
||||
}
|
||||
|
||||
GLint Shader::Uniform(const std::string &name) const {
|
||||
auto it = uniform_location_cache.find(name);
|
||||
if (it == uniform_location_cache.end()) {
|
||||
auto location = glGetUniformLocation(id, name.c_str());
|
||||
uniform_location_cache[name] = location;
|
||||
return location;
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
GLint Shader::Attribute(const std::string &name) const {
|
||||
return glGetAttribLocation(id, name.c_str());
|
||||
}
|
||||
|
||||
Shader::Shader(const std::string &vertex_code, const std::string &fragment_code, const std::vector<std::pair<std::string, GLint>>& attribute_bindings) {
|
||||
vertexSource = vertex_code;
|
||||
fragmentSource = fragment_code;
|
||||
|
||||
const char* vShaderCode = vertex_code.c_str();
|
||||
const char* fShaderCode = fragment_code.c_str();
|
||||
|
||||
// 2. Compile shaders.
|
||||
unsigned int vertex, fragment;
|
||||
|
||||
// vertex shader.
|
||||
vertex = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(vertex, 1, &vShaderCode, nullptr);
|
||||
glCompileShader(vertex);
|
||||
checkCompileErrors(vertex, "VERTEX");
|
||||
|
||||
// fragment shader
|
||||
fragment = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(fragment, 1, &fShaderCode, nullptr);
|
||||
glCompileShader(fragment);
|
||||
checkCompileErrors(fragment, "FRAGMENT");
|
||||
|
||||
// shader Program
|
||||
id = glCreateProgram();
|
||||
|
||||
// bind attribute locations.
|
||||
for (auto& a: attribute_bindings)
|
||||
glBindAttribLocation(id, a.second, a.first.c_str());
|
||||
|
||||
glAttachShader(id, vertex);
|
||||
glAttachShader(id, fragment);
|
||||
glLinkProgram(id);
|
||||
checkCompileErrors(id, "PROGRAM");
|
||||
|
||||
// delete the shaders as they're linked into our program now and are no longer necessary
|
||||
glDeleteShader(vertex);
|
||||
glDeleteShader(fragment);
|
||||
}
|
||||
|
||||
bool Shader::Loaded() const { return id != 0; }
|
||||
|
||||
unsigned int Shader::Handle() const { return id;}
|
||||
|
||||
void Shader::SetBool(const std::string &name, bool value) const { glUniform1i(Uniform(name), (int)value); }
|
||||
|
||||
void Shader::SetInt(const std::string &name, int value) const { glUniform1i(Uniform(name), value); }
|
||||
|
||||
void Shader::SetFloat(const std::string &name, float value) const { glUniform1f(Uniform(name), value); }
|
||||
|
||||
void Shader::SetVector2(const std::string &name, const Vector2 &value) const { glUniform2f(Uniform(name), value.x, value.y); }
|
||||
|
||||
void Shader::SetVector2(const std::string &name, float x, float y) const { glUniform2f(Uniform(name), x, y); }
|
||||
|
||||
void Shader::SetVector3(const std::string &name, const Vector3 &value) const { glUniform3f(Uniform(name), value.x, value.y, value.z); }
|
||||
|
||||
void Shader::SetVector3(const std::string &name, float x, float y, float z) const { glUniform3f(Uniform(name), x, y, z); }
|
||||
|
||||
void Shader::SetVector4(const std::string &name, const Vector4 &value) const { glUniform4f(Uniform(name), value.x, value.y, value.z, value.w); }
|
||||
|
||||
void Shader::SetVector4(const std::string &name, float x, float y, float z, float w) const { glUniform4f(Uniform(name), x, y, z, w); }
|
||||
|
||||
void Shader::SetMatrix2x2(const std::string &name, const Matrix2x2 &value) const {
|
||||
/// TODO: Verify if glsl expects row-major or col-major!!
|
||||
bool transpose = false;
|
||||
glUniformMatrix2fv(Uniform(name), 4, transpose, value.ptr());
|
||||
}
|
||||
|
||||
void Shader::SetMatrix3x3(const std::string &name, const Matrix3x3 &value) const {
|
||||
/// TODO: Verify if glsl expects row-major or col-major!!
|
||||
bool transpose = false;
|
||||
glUniformMatrix3fv(Uniform(name), 9, transpose, value.ptr());
|
||||
}
|
||||
|
||||
void Shader::SetMatrix4x4(const std::string &name, const Matrix4x4 &value) const {
|
||||
/// TODO: Verify if glsl expects row-major or col-major!!
|
||||
bool transpose = false;
|
||||
glUniformMatrix4fv(Uniform(name), 16, transpose, value.ptr());
|
||||
}
|
||||
|
||||
std::string Shader::ReadFile(const std::filesystem::path &path) {
|
||||
/*std::string contents;
|
||||
|
||||
std::ifstream file;
|
||||
|
||||
file.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
||||
|
||||
try {
|
||||
// Open Files
|
||||
file.open(path);
|
||||
std::stringstream stream;
|
||||
|
||||
// Read file's buffer contents into streams
|
||||
stream << file.rdbuf();
|
||||
|
||||
// close file handlers
|
||||
file.close();
|
||||
|
||||
// convert stream into string
|
||||
contents = stream.str();
|
||||
|
||||
return contents;
|
||||
} catch (std::ifstream::failure& e) {
|
||||
std::cout << "ERROR::FILE_READ_FAILURE: " << e.what() << std::endl;
|
||||
return "";
|
||||
}*/
|
||||
|
||||
ShaderPreprocessor processor;
|
||||
return processor.LoadShaderFile(path);
|
||||
}
|
||||
}
|
@@ -2,44 +2,39 @@
|
||||
#include <JGL/logger/logger.h>
|
||||
#include <cstring>
|
||||
|
||||
// TODO combine the two load functions.
|
||||
|
||||
void JGL::VRamList::load(const GLfloat* data, const long& size) {
|
||||
while (spin_lock) {}
|
||||
spin_lock = true;
|
||||
|
||||
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);
|
||||
glBufferData(GL_ARRAY_BUFFER, size, data, usage_hint);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, current_array_buffer);
|
||||
element_array_buffer = false;
|
||||
num_elements = size / sizeof(GLfloat);
|
||||
byte_count = size;
|
||||
|
||||
spin_lock = false;
|
||||
}
|
||||
|
||||
|
||||
void JGL::VRamList::load(const GLuint* data, const long& size) {
|
||||
while (spin_lock) {}
|
||||
spin_lock = true;
|
||||
|
||||
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);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, data, usage_hint);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, current_element_array_buffer);
|
||||
element_array_buffer = true;
|
||||
num_elements = size / sizeof(GLuint);
|
||||
byte_count = size;
|
||||
|
||||
spin_lock = false;
|
||||
}
|
||||
|
||||
void JGL::VRamList::Erase() {
|
||||
if (list_handle == 0)
|
||||
return;
|
||||
|
||||
while (spin_lock) {}
|
||||
spin_lock = true;
|
||||
|
||||
GLint current_element_array_buffer = 0;
|
||||
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, ¤t_element_array_buffer);
|
||||
@@ -55,36 +50,27 @@ void JGL::VRamList::Erase() {
|
||||
glDeleteBuffers(1, &list_handle);
|
||||
list_handle = 0;
|
||||
|
||||
spin_lock = false;
|
||||
}
|
||||
|
||||
GLuint JGL::VRamList::GetHandle() const {
|
||||
GLuint JGL::VRamList::Handle() const {
|
||||
return list_handle;
|
||||
}
|
||||
|
||||
bool JGL::VRamList::IsFloatArray() const {
|
||||
return !element_array_buffer;
|
||||
long JGL::VRamList::Length() const {
|
||||
// sizeof(GLfloat) & sizeof(GLuint) are both 4 - Redacted.
|
||||
return byte_count / 4;
|
||||
}
|
||||
|
||||
long JGL::VRamList::GetLength() const {
|
||||
return num_elements;
|
||||
}
|
||||
|
||||
size_t JGL::VRamList::GetDataSize() const {
|
||||
if (element_array_buffer)
|
||||
return sizeof(GLuint) * num_elements;
|
||||
return sizeof(GLfloat) * num_elements;
|
||||
size_t JGL::VRamList::Size() const {
|
||||
return byte_count;
|
||||
}
|
||||
|
||||
void JGL::VRamList::SetData(void* data, const long& length) {
|
||||
while (spin_lock) {}
|
||||
spin_lock = true;
|
||||
|
||||
bool should_resize = (this->num_elements != length);
|
||||
bool should_resize = (this->byte_count != length * 4);
|
||||
if (should_resize) {
|
||||
glDeleteBuffers(1, &list_handle);
|
||||
list_handle = 0;
|
||||
spin_lock = false;
|
||||
element_array_buffer ? load((GLuint*) data, sizeof(GLuint) * length) : load((GLfloat*) data, sizeof(GLfloat) * length);
|
||||
return;
|
||||
}
|
||||
@@ -100,33 +86,22 @@ void JGL::VRamList::SetData(void* data, const long& length) {
|
||||
glGetIntegerv(buffer_binding, ¤t_buffer);
|
||||
glBindBuffer(buffer_type, list_handle);
|
||||
|
||||
void* vram = glMapBuffer(buffer_type, GL_WRITE_ONLY);
|
||||
if (!vram)
|
||||
JGL::Logger::Fatal("Mapping in a VBO that doesn't exist?");
|
||||
|
||||
memcpy(vram, data, (element_array_buffer ? sizeof(GLuint) : sizeof(GLfloat)) * length);
|
||||
|
||||
if (!glUnmapBuffer(buffer_type))
|
||||
JGL::Logger::Fatal("We couldn't unmap the buffer?");
|
||||
size_t element_size = element_array_buffer ? sizeof(GLuint) : sizeof(GLfloat);
|
||||
|
||||
glBufferSubData(buffer_type, 0, length * element_size, data);
|
||||
glBindBuffer(buffer_type, current_buffer);
|
||||
|
||||
spin_lock = false;
|
||||
}
|
||||
|
||||
void JGL::VRamList::UpdateData(void* data, const long& offset, const long& length) {
|
||||
while (spin_lock) {}
|
||||
spin_lock = true;
|
||||
|
||||
if (offset + length > num_elements) {
|
||||
JGL::Logger::Warning("Using UpdateData to out-of-bounds write the VRamList? I'll resize it for you, But this is slow.");
|
||||
unsigned long oob_delta = (offset + length) - num_elements;
|
||||
if (offset + length > Length()) {
|
||||
unsigned long oob_delta = (offset + length) - Length();
|
||||
|
||||
if (element_array_buffer) {
|
||||
auto list_data = GetDataUI();
|
||||
list_data.resize(list_data.size() + oob_delta);
|
||||
memcpy(list_data.data() + (offset * sizeof(GLuint)), data, length * sizeof(GLuint));
|
||||
spin_lock = false; // This is going unlock and relock really fast, But this code fixes something considered wrong anyway - Redacted.
|
||||
// This is going unlock and relock really fast, But this code fixes something considered wrong anyway - Redacted.
|
||||
return SetData(list_data.data(), list_data.size());
|
||||
}
|
||||
|
||||
@@ -134,7 +109,6 @@ void JGL::VRamList::UpdateData(void* data, const long& offset, const long& lengt
|
||||
auto list_data = GetDataF();
|
||||
list_data.resize(list_data.size() + oob_delta);
|
||||
memcpy(list_data.data() + (offset * sizeof(GLfloat)), data, length * sizeof(GLfloat));
|
||||
spin_lock = false;
|
||||
return SetData(list_data.data(), list_data.size());
|
||||
}
|
||||
|
||||
@@ -149,23 +123,13 @@ void JGL::VRamList::UpdateData(void* data, const long& offset, const long& lengt
|
||||
glGetIntegerv(buffer_binding, ¤t_buffer);
|
||||
glBindBuffer(buffer_type, list_handle);
|
||||
|
||||
void* vram = glMapBuffer(buffer_type, GL_WRITE_ONLY);
|
||||
if (!vram)
|
||||
JGL::Logger::Fatal("Mapping in a VBO that doesn't exist?");
|
||||
|
||||
size_t element_size = element_array_buffer ? sizeof(GLuint) : sizeof(GLfloat);
|
||||
memcpy(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(vram) + (offset * element_size)), data, length * element_size);
|
||||
|
||||
if (!glUnmapBuffer(buffer_type))
|
||||
JGL::Logger::Fatal("We couldn't unmap the buffer?");
|
||||
|
||||
glBufferSubData(buffer_type, offset * element_size, length * element_size, data);
|
||||
glBindBuffer(buffer_type, current_buffer);
|
||||
|
||||
spin_lock = false;
|
||||
}
|
||||
|
||||
std::vector<GLfloat> JGL::VRamList::GetDataF() const {
|
||||
while (spin_lock) {}
|
||||
|
||||
if (element_array_buffer)
|
||||
JGL::Logger::Warning("Getting data as GLfloat but the buffer data is GLuint?");
|
||||
@@ -178,12 +142,12 @@ std::vector<GLfloat> JGL::VRamList::GetDataF() const {
|
||||
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, ¤t_buffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, list_handle);
|
||||
|
||||
std::vector<GLfloat> data(num_elements);
|
||||
std::vector<GLfloat> data(byte_count / 4);
|
||||
void* vram = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
|
||||
if (vram == nullptr)
|
||||
JGL::Logger::Fatal("Mapping in a VBO that doesn't exist?");
|
||||
|
||||
memcpy(data.data(), vram, num_elements * sizeof(GLfloat));
|
||||
memcpy(data.data(), vram, (byte_count / 4) * sizeof(GLfloat));
|
||||
|
||||
glUnmapBuffer(GL_ARRAY_BUFFER);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, current_buffer);
|
||||
@@ -194,7 +158,6 @@ std::vector<GLfloat> JGL::VRamList::GetDataF() const {
|
||||
}
|
||||
|
||||
std::vector<GLuint> JGL::VRamList::GetDataUI() const {
|
||||
while (spin_lock) {}
|
||||
|
||||
if (!element_array_buffer)
|
||||
JGL::Logger::Warning("Getting data as GLuint but the buffer data is GLfloat?");
|
||||
@@ -203,13 +166,13 @@ std::vector<GLuint> JGL::VRamList::GetDataUI() const {
|
||||
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, ¤t_buffer);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, list_handle);
|
||||
std::vector<GLuint> data(num_elements);
|
||||
std::vector<GLuint> data(byte_count / 4);
|
||||
|
||||
void* vram = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_READ_ONLY);
|
||||
if (vram == nullptr)
|
||||
JGL::Logger::Fatal("Mapping in a VBO that doesn't exist?");
|
||||
|
||||
memcpy(data.data(), vram, num_elements * sizeof(GLuint));
|
||||
memcpy(data.data(), vram, (byte_count / 4) * sizeof(GLuint));
|
||||
|
||||
glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, current_buffer);
|
||||
@@ -217,26 +180,35 @@ std::vector<GLuint> JGL::VRamList::GetDataUI() const {
|
||||
return data;
|
||||
}
|
||||
|
||||
JGL::VRamList::VRamList(const GLfloat* data, const long& length) {
|
||||
JGL::VRamList::VRamList(const GLfloat* data, const long& length, VRamUsageHint hint) {
|
||||
usage_hint = hint;
|
||||
load(data, (long) sizeof(GLfloat) * length);
|
||||
}
|
||||
|
||||
JGL::VRamList::VRamList(const GLuint* data, const long& length) {
|
||||
JGL::VRamList::VRamList(const GLuint* data, const long& length, VRamUsageHint hint) {
|
||||
usage_hint = hint;
|
||||
load(data, (long) sizeof(GLuint) * length);
|
||||
}
|
||||
|
||||
JGL::VRamList::VRamList(const Vector2* data, const long& length) {
|
||||
JGL::VRamList::VRamList(const Vector2* data, const long& length, VRamUsageHint hint) {
|
||||
usage_hint = hint;
|
||||
load(reinterpret_cast<const GLfloat*>(data), (long) sizeof(Vector2) * length);
|
||||
}
|
||||
|
||||
JGL::VRamList::VRamList(const Vector3* data, const long& length) {
|
||||
JGL::VRamList::VRamList(const Vector3* data, const long& length, VRamUsageHint hint) {
|
||||
usage_hint = hint;
|
||||
load(reinterpret_cast<const GLfloat*>(data), (long) sizeof(Vector3) * length);
|
||||
}
|
||||
|
||||
JGL::VRamList::VRamList(const Vector4* data, const long& length) {
|
||||
JGL::VRamList::VRamList(const Vector4* data, const long& length, VRamUsageHint hint) {
|
||||
usage_hint = hint;
|
||||
load(reinterpret_cast<const GLfloat*>(data), (long) sizeof(Vector4) * length);
|
||||
}
|
||||
|
||||
JGL::VRamList::VRamList(const Color4* data, const long& count, VRamUsageHint hint) {
|
||||
usage_hint = hint;
|
||||
load(reinterpret_cast<const GLfloat *>(data), (long) sizeof(GLuint) * count);
|
||||
}
|
||||
void JGL::VRamList::SetData(const GLfloat* data, const long& length) {
|
||||
SetData((void*) data, length);
|
||||
}
|
||||
@@ -261,6 +233,10 @@ void JGL::VRamList::SetData(const Vector2i* data, const long& length) {
|
||||
SetData((void*) data, length * 2);
|
||||
}
|
||||
|
||||
void JGL::VRamList::SetData(const Color4* data, const long& count) {
|
||||
SetData((void*) data, count);
|
||||
}
|
||||
|
||||
void JGL::VRamList::UpdateData(const GLfloat* data, const long& offset, const long& length) {
|
||||
UpdateData((void*) data, offset, length);
|
||||
}
|
||||
@@ -285,13 +261,15 @@ void JGL::VRamList::UpdateData(const Vector2i* data, const long& offset, const l
|
||||
UpdateData((void*) data, offset, length * 2);
|
||||
}
|
||||
|
||||
void JGL::VRamList::UpdateData(const Color4* data, const long &offset, const long &count) {
|
||||
UpdateData((void*) data, offset, count);
|
||||
}
|
||||
|
||||
JGL::VRamList::~VRamList() {
|
||||
Erase();
|
||||
}
|
||||
|
||||
JGL::VRamList::VRamList(const JGL::VRamList& rhs) {
|
||||
while (rhs.spin_lock) {}
|
||||
|
||||
if (rhs.element_array_buffer) {
|
||||
auto data_array = rhs.GetDataUI();
|
||||
this->load(data_array.data(), data_array.size());
|
||||
@@ -300,3 +278,32 @@ JGL::VRamList::VRamList(const JGL::VRamList& rhs) {
|
||||
auto data_array = rhs.GetDataF();
|
||||
this->load(data_array.data(), data_array.size());
|
||||
}
|
||||
|
||||
JGL::VRamList::VRamList(const size_t& byte_count, bool element_array_buffer, VRamUsageHint hint) {
|
||||
this->element_array_buffer = element_array_buffer;
|
||||
this->byte_count = byte_count;
|
||||
|
||||
GLint current_buffer = 0;
|
||||
GLenum buffer = element_array_buffer ? GL_ELEMENT_ARRAY_BUFFER : GL_ARRAY_BUFFER;
|
||||
GLenum buffer_binding = element_array_buffer ? GL_ELEMENT_ARRAY_BUFFER_BINDING : GL_ARRAY_BUFFER_BINDING;
|
||||
|
||||
glGetIntegerv(buffer_binding, ¤t_buffer);
|
||||
glGenBuffers(1, &list_handle);
|
||||
glBindBuffer(buffer, list_handle);
|
||||
glBufferData(buffer, byte_count, nullptr, hint);
|
||||
|
||||
glBindBuffer(buffer, current_buffer);
|
||||
}
|
||||
|
||||
void JGL::VRamList::UpdateData(const uint8_t* data, const long& offset, const long& count) {
|
||||
GLint current_buffer = 0;
|
||||
GLenum buffer_type = element_array_buffer ? GL_ELEMENT_ARRAY_BUFFER : GL_ARRAY_BUFFER;
|
||||
GLenum buffer_binding = element_array_buffer ? GL_ELEMENT_ARRAY_BUFFER_BINDING : GL_ARRAY_BUFFER_BINDING;
|
||||
|
||||
glGetIntegerv(buffer_binding, ¤t_buffer);
|
||||
glBindBuffer(buffer_type, list_handle);
|
||||
|
||||
glBufferSubData(buffer_type, offset, count, data);
|
||||
|
||||
glBindBuffer(buffer_type, current_buffer);
|
||||
}
|
||||
|
Reference in New Issue
Block a user