BatchFillCircle Instanced Rendering.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 2m51s
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 2m51s
Added JGL::ClearScreen as-well to clear fbo 0 at any time.
This commit is contained in:
@@ -146,7 +146,7 @@ void main() {
|
||||
else { gl_Position = Default(); }
|
||||
*/
|
||||
|
||||
if (JGL_RENDERING_ROUTINE == J2D_FillRect && JGL_INSTANCED_RENDERING)
|
||||
if (JGL_INSTANCED_RENDERING)
|
||||
gl_Position = DefaultInstanced();
|
||||
else
|
||||
gl_Position = Default();
|
||||
|
@@ -60,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(); }
|
||||
|
||||
|
||||
@@ -400,7 +402,7 @@ namespace JGL::J2D {
|
||||
void FillEllipse(const Color4& color, const Vector2& position, float radius_x, float radius_y, int subdivisions = 8);
|
||||
|
||||
void BatchFillRect(const Instance2D* instances, const size_t& instance_count);
|
||||
void BatchFillCircle(const Color4 *colors, const Vector2* positions, float* radii, unsigned int subdivisions, const size_t& circle_count);
|
||||
void BatchFillCircle(const Instance2D* instances, float subdivisions, const size_t& instance_count);
|
||||
}
|
||||
|
||||
/// Drawing functions for 3D objects.
|
||||
|
6
main.cpp
6
main.cpp
@@ -130,7 +130,7 @@ 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_NEAREST);
|
||||
@@ -194,7 +194,7 @@ public:
|
||||
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);
|
||||
J3D::End();
|
||||
|
||||
//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());
|
||||
@@ -237,7 +237,7 @@ public:
|
||||
J2D::End();
|
||||
|
||||
|
||||
J2D::Begin(nullptr, shader, true);
|
||||
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::End();
|
||||
|
@@ -5,6 +5,41 @@
|
||||
#include "internals/internals.h"
|
||||
|
||||
|
||||
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(current_state));
|
||||
@@ -266,6 +301,7 @@ void J2D::FillRect(const Color4& color, const Vector2& pos, const Vector2& size)
|
||||
Instance2D rect(color, pos, size);
|
||||
BatchFillRect(&rect, 1);
|
||||
}
|
||||
|
||||
void J2D::BatchFillRect(const Instance2D* instances, const size_t& instance_count) {
|
||||
if (!state_stack.Size())
|
||||
Logger::Error("Drawing J2D element before J2D begin.");
|
||||
@@ -361,20 +397,25 @@ void J2D::FillGradientRect(const Color4& top_left_color, const Color4& bottom_le
|
||||
}
|
||||
|
||||
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<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}
|
||||
};
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", RENDERING_ROUTINE_ID::J2D_FillRoundedRect);
|
||||
|
||||
std::array<Instance2D, 2> rect_instances { Instance2D(color,Vector2(pos.x + radius, pos.y), Vector2(size.x - 2 * radius, size.y)), Instance2D(color, Vector2(pos.x, pos.y + radius), Vector2(size.x, size.y - 2 * radius)) };
|
||||
std::array<Instance2D, 4> circle_instances
|
||||
{
|
||||
Instance2D(color, Vector2(pos.x + radius, pos.y + radius), Vector2::One, Vector2(radius, radius)),
|
||||
Instance2D(color, Vector2(pos.x + size.x - radius, pos.y + radius), Vector2::One, Vector2(radius, radius)),
|
||||
Instance2D(color, Vector2(pos.x + radius, pos.y + size.y - radius), Vector2::One, Vector2(radius, radius)),
|
||||
Instance2D(color, Vector2(pos.x + size.x - radius, pos.y + size.y - radius), Vector2::One, Vector2(radius, radius))
|
||||
};
|
||||
|
||||
std::array<Instance2D, 2> rect_instances
|
||||
{
|
||||
Instance2D(color,Vector2(pos.x + radius, pos.y), Vector2(size.x - 2 * radius, size.y)),
|
||||
Instance2D(color, Vector2(pos.x, pos.y + radius), Vector2(size.x, size.y - 2 * radius))
|
||||
};
|
||||
|
||||
J2D::BatchFillRect(rect_instances.data(), rect_instances.size());
|
||||
J2D::BatchFillCircle(colors.data(), circle_positions.data(), circle_radii.data(), subdivisions, 4);
|
||||
J2D::BatchFillCircle(circle_instances.data(), subdivisions, circle_instances.size());
|
||||
|
||||
if (current_state.current_shader)
|
||||
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", 0);
|
||||
@@ -928,14 +969,15 @@ void J2D::OutlineCircle(const Color4& color, const Vector2& center, float radius
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -956,18 +998,59 @@ void J2D::BatchFillCircle(const Color4* colors, const Vector2* positions, float*
|
||||
i++;
|
||||
}
|
||||
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
|
||||
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);
|
||||
|
||||
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);
|
||||
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)
|
||||
|
Reference in New Issue
Block a user