BatchFillRect instanced rendering.
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Has been cancelled
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Has been cancelled
during shader creation you can now also specify your attributes.
This commit is contained in:
@@ -32,7 +32,7 @@ CPMAddPackage(
|
||||
|
||||
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(
|
||||
|
@@ -1,31 +0,0 @@
|
||||
#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;
|
@@ -1,6 +1,38 @@
|
||||
#version 120
|
||||
|
||||
#include "jgl.glsl"
|
||||
#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;
|
||||
|
@@ -1,10 +1,55 @@
|
||||
#version 120
|
||||
// TODO this will fail if we don't have the extension.
|
||||
#extension GL_ARB_instanced_arrays : enable
|
||||
|
||||
#include "jgl.glsl"
|
||||
#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;
|
||||
@@ -16,11 +61,11 @@ varying vec2 GL_TEXTURE6_COORD;
|
||||
varying vec2 GL_TEXTURE7_COORD;
|
||||
|
||||
vec4 Default() {
|
||||
v_color = gl_Color;
|
||||
return gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||
}
|
||||
|
||||
void main() {
|
||||
v_color = gl_Color;
|
||||
GL_TEXTURE0_COORD = gl_MultiTexCoord0.xy;
|
||||
GL_TEXTURE1_COORD = gl_MultiTexCoord1.xy;
|
||||
GL_TEXTURE2_COORD = gl_MultiTexCoord2.xy;
|
||||
@@ -30,6 +75,8 @@ void main() {
|
||||
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();
|
||||
@@ -92,5 +139,13 @@ void main() {
|
||||
else { gl_Position = Default(); }
|
||||
*/
|
||||
|
||||
gl_Position = Default();
|
||||
if (JGL_RENDERING_ROUTINE == J2D_FillRect) {
|
||||
if (!JGL_INSTANCED_RENDERING) { gl_Position = Default(); return; }
|
||||
|
||||
vec2 scaled = a_vertex_position * a_instance_size;
|
||||
vec2 world_pos = scaled + a_instance_position;
|
||||
gl_Position = gl_ModelViewProjectionMatrix * vec4(world_pos, 0.0, 1.0);
|
||||
v_color = a_instance_color;
|
||||
}
|
||||
else { gl_Position = Default(); }
|
||||
}
|
||||
|
@@ -35,10 +35,10 @@ public:
|
||||
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);
|
||||
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);
|
||||
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;
|
||||
|
16
main.cpp
16
main.cpp
@@ -15,7 +15,9 @@ using namespace JGL;
|
||||
using JGL::Font;
|
||||
|
||||
float fps = 0.0f;
|
||||
|
||||
std::vector<Vector2> rect_pos;
|
||||
std::vector<Vector2> rect_size;
|
||||
std::vector<Color4> rect_colors;
|
||||
/// A draggable 2D point that highlights when moused over and when clicked.
|
||||
class Gizmo
|
||||
{
|
||||
@@ -137,7 +139,14 @@ public:
|
||||
|
||||
//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"));
|
||||
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}});
|
||||
|
||||
for (unsigned int i = 0; i < 100; i++) {
|
||||
rect_pos.emplace_back(420, 420);
|
||||
rect_size.emplace_back(20, 20);
|
||||
rect_colors.emplace_back(Colors::Red);
|
||||
}
|
||||
}
|
||||
|
||||
EulerAngleXYZ textAngle = {0,0,0};
|
||||
@@ -178,6 +187,7 @@ public:
|
||||
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});
|
||||
@@ -192,6 +202,7 @@ public:
|
||||
|
||||
J2D::Begin(j2d_render_target, shader, true);
|
||||
J2D::FillRect(Colors::Blue, {0,52}, {100,100});
|
||||
J2D::BatchFillRect(rect_colors.data(), rect_pos.data(), rect_size.data(), rect_pos.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);
|
||||
@@ -235,7 +246,6 @@ public:
|
||||
J2D::DrawRenderTarget(j2d_render_target, {0, 0});
|
||||
J2D::DrawSprite(image, image_mask, {0, 0}, 0.25, {0.5, 0.5}, {1,1});
|
||||
J2D::End();
|
||||
|
||||
}
|
||||
|
||||
void OnRefresh(float elapsed) override {
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -272,25 +272,68 @@ void J2D::BatchFillRect(const Color4* colors, const Vector2* positions, const Ve
|
||||
if (rect_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->GetHandle());
|
||||
|
||||
if (rect_count == 1 || !supports_instanced || !current_state.current_shader) {
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), nullptr);
|
||||
|
||||
for (size_t i = 0; i < rect_count; i++) {
|
||||
glPushMatrix();
|
||||
glColor4ubv(colors[i].ptr());
|
||||
glTranslatef(positions[i].x, positions[i].y + sizes[i].y, 0);
|
||||
glScalef(sizes[i].x, sizes[i].y, 1);
|
||||
glDrawArrays(GL_QUADS, 0, 4);
|
||||
glPopMatrix();
|
||||
}
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
else {
|
||||
current_state.current_shader->SetBool("JGL_INSTANCED_RENDERING", true);
|
||||
|
||||
std::vector<Instance> instances;
|
||||
instances.reserve(rect_count);
|
||||
|
||||
for (size_t i = 0; i < rect_count; ++i)
|
||||
instances.emplace_back(Vector2(positions[i].x, positions[i].y + sizes[i].y), sizes[i], colors[i]);
|
||||
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), nullptr);
|
||||
glVertexAttribDivisorARB(0, 0);
|
||||
|
||||
// count * 5 because 4x float & 4x uint8_t = sizeof(float).
|
||||
VRamList instance_buffer((GLfloat*) instances.data(), instances.size() * 5, VRamUsageHint::Stream);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, instance_buffer.GetHandle());
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Instance), (GLvoid*) offsetof(Instance, position));
|
||||
glVertexAttribDivisorARB(1, 1);
|
||||
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Instance), (GLvoid*) offsetof(Instance, size));
|
||||
glVertexAttribDivisorARB(2, 1);
|
||||
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Instance), (GLvoid*) offsetof(Instance, color));
|
||||
glVertexAttribDivisorARB(3, 1);
|
||||
|
||||
glDrawArraysInstancedARB(GL_QUADS, 0, 4, rect_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);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glColor4fv(default_state.draw_color);
|
||||
}
|
||||
|
||||
|
@@ -96,6 +96,17 @@ 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;
|
||||
|
||||
struct Instance {
|
||||
public:
|
||||
Vector2 position;
|
||||
Vector2 size;
|
||||
Color4 color;
|
||||
public:
|
||||
Instance(const Vector2& position, const Vector2& size, const Color4& color) : position(position), size(size), color(color) {}
|
||||
~Instance() = default;
|
||||
};
|
||||
}
|
||||
|
||||
namespace JGL::J2D {
|
||||
|
@@ -115,8 +115,8 @@ namespace JGL {
|
||||
}
|
||||
};
|
||||
|
||||
Shader::Shader(const std::filesystem::path& vertex_source_path, const std::filesystem::path& fragment_source_path) :
|
||||
Shader(ReadFile(vertex_source_path), ReadFile(fragment_source_path)) {
|
||||
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;
|
||||
fragmentPath = fragment_source_path;
|
||||
}
|
||||
@@ -128,13 +128,13 @@ namespace JGL {
|
||||
if (type != "PROGRAM") {
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
|
||||
if (!success) {
|
||||
glGetShaderInfoLog(shader, 1024, NULL, infoLog);
|
||||
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, NULL, infoLog);
|
||||
glGetProgramInfoLog(shader, 1024, nullptr, infoLog);
|
||||
OnCompilationErrorMessage.Invoke(std::format("COMPILATION_ERROR: {}", type), infoLog);
|
||||
}
|
||||
}
|
||||
@@ -157,7 +157,7 @@ namespace JGL {
|
||||
return glGetAttribLocation(id, name.c_str());
|
||||
}
|
||||
|
||||
Shader::Shader(const std::string &vertex_code, const std::string &fragment_code) {
|
||||
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;
|
||||
|
||||
@@ -169,21 +169,25 @@ namespace JGL {
|
||||
|
||||
// vertex shader.
|
||||
vertex = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(vertex, 1, &vShaderCode, NULL);
|
||||
glShaderSource(vertex, 1, &vShaderCode, nullptr);
|
||||
glCompileShader(vertex);
|
||||
checkCompileErrors(vertex, "VERTEX");
|
||||
|
||||
// fragment shader
|
||||
fragment = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(fragment, 1, &fShaderCode, NULL);
|
||||
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");
|
||||
|
||||
|
Reference in New Issue
Block a user