#include "glad.h"
#include <GLFW/glfw3.h>
#include <array>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <ctime>
#include <execution>
#include <iostream>
#include <optional>
#include <span>
#include <utility>
constexpr auto lerp(
float a,
float b,
float f) ->
float
{
return a * (1.0F - f) + b * f;
}
};
void GLAPIENTRY
GLenum type,
GLuint id [[maybe_unused]],
GLenum severity,
GLsizei length [[maybe_unused]],
const GLchar* message,
const void* userParam [[maybe_unused]])
{
if (type == GL_DEBUG_TYPE_OTHER || type == GL_DEBUG_TYPE_PERFORMANCE)
return;
fprintf(stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x,\nmessage = %s\n",
(type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : ""),
type, severity, message);
}
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
GLFWwindow* window = glfwCreateWindow(
SCR_WIDTH,
SCR_HEIGHT,
"Batched Rendering",
nullptr,
nullptr);
if (window == nullptr) {
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
if (gladLoadGLLoader(reinterpret_cast<GLADloadproc>(glfwGetProcAddress)) == 0) {
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
glEnable(GL_DEBUG_OUTPUT);
glEnable(GL_MULTISAMPLE);
const std::array<const float, 12> vertices {
0.001F, 0.001F, 0.0F,
0.001F, -0.001F, 0.0F,
-0.001F, -0.001F, 0.0F,
-0.001F, 0.001F, 0.0F,
};
const std::array<const unsigned int, 6> indices {
0, 1, 3,
1, 2, 3
};
{ u_type::vec3, "aPos" }
};
{ u_type::vec3, "instancePos" }
};
VBO.set_layout(layout);
{ shader_array_type::float32_arr, "u_color", 4 }
};
std::array<float, 4> color {};
const float START = -0.95F;
const float END = 0.95F;
const float Z_START = 0.01F;
const float Z_END = 1.00F;
std::srand(static_cast<unsigned int>(std::time(nullptr)));
constexpr int32_t NUM_INSTANCES = 65535;
for (int i = 0; i < NUM_INSTANCES; i++) {
std::array<float, 3> offset = {
static_cast<float>(rand()) / static_cast<float>(RAND_MAX)),
static_cast<float>(rand()) / static_cast<float>(RAND_MAX)),
static_cast<float>(rand()) / static_cast<float>(RAND_MAX))
};
}
while (glfwWindowShouldClose(window) == 0) {
glClearColor(0.2F, 0.3F, 0.3F, 1.0F);
glClear(GL_COLOR_BUFFER_BIT);
auto timeNow = static_cast<float>(glfwGetTime());
for (float& col : color) {
col = std::sin(timeNow) / 2.0F + 0.5F;
}
color[3] = 1.0F;
for (int i = 0; i < 4; ++i) {
UBO_block.set_attribute_data(std::span { &color[i], 1 }, "u_color", i);
}
#pragma pack(push, 1)
};
#pragma pack(pop)
static_assert(
sizeof(
vec3) == 3 *
sizeof(
float));
[](std::span<vec3> data) {
std::for_each(std::execution::par_unseq, data.begin(), data.end(),
const float speed = ((static_cast<float>(std::rand()) / static_cast<float>(RAND_MAX)) - 0.5F) / 1000.0F;
v.x += speed;
});
});
glDrawElementsInstanced(GL_TRIANGLES, VAO.
index_data().count(), GL_UNSIGNED_INT,
nullptr,
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
glfwSetWindowShouldClose(window, 1);
}
}
{
glViewport(0, 0, width, height);
}
void processInput(GLFWwindow *window)
void framebuffer_size_callback(GLFWwindow *window, int width, int height)
void GLAPIENTRY MessageCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam)
constexpr auto lerp(float a, float b, float f) -> float
Element Buffer Object (EBO) wrapper.
void bind() const
Bind the shader program.
Vertex Array Object (VAO) wrapper.
constexpr auto instanced_data() -> std::optional< vertex_buffer_inst > &
Get the instance buffer object.
void bind() const
Bind the vertex array object.
void set_index_buffer(index_buffer &&ibo)
Set the index buffer object.
void set_instance_buffer(vertex_buffer_inst &&vbo)
Set the instance buffer object.
constexpr auto index_data() -> index_buffer &
Get the index buffer object.
auto add_vertex_buffer(vertex_buffer &&vbo) -> vertex_array::iterator_t
Add a vertex buffer to the vertex array object.
A vertex buffer object for instanced rendering.
Vertex Buffer Object (VBO) wrapper.
void set_layout(const vertex_buffer_layout &layout)
Set the layout object.
StapleGL, a C++20 wrapper for OpenGL.