Compare commits

..

No commits in common. "2a0ed92cfc4a393459fe64d4223b2a06bee2ebc5" and "c2c11a6aba517880a4a97302be43cc7b59e70da6" have entirely different histories.

3 changed files with 283 additions and 317 deletions

View File

@ -1,4 +1,4 @@
.PHONY: run clean install all gl_test
.PHONY: run clean install all
.DELETE_ON_ERROR: $(BINDIR)/Getting_Started_with_GTK
.DEFAULT_GOAL: all
@ -20,15 +20,6 @@ SOURCES = $(shell find $(SRCDIR) -type f -name "*.c")
OBJECTS = $(patsubst %.c,$(BUILDDIR)/%.o,$(SOURCES))
DEPENDENCIES = $(patsubst %.c,$(BUILDDIR)/%.d,$(SOURCES))
sandbox: opengl_sandbox/main.c
$(CC) $(CFLAGS) $(LDFLAGS) $(WARNINGS) $(DEBUG)-o $@ $<
gl_run: sandbox
./$<
gl_clean:
rm sandbox
all: $(BINDIR)/gem-graph-client
-include /etc/os-release

BIN
instanced_cubes Executable file

Binary file not shown.

View File

@ -6,17 +6,15 @@
#include <gtk/gtk.h> // GTK types
// General declaration zone ---------------------------------------------------
#define N_INSTANCE 5
#define N_SPACE_SIZE 20
GtkWidget *window;
// OpenGL objects
GLuint vao, arrow_vao;
GLuint vbo, arrow_vbo, cubes_instance_vbo, arrow_instance_vbo;
GLuint ebo, arrow_ebo, edge_ebo;
GLuint vao, vbo, ebo, instance_vbo, arrow_instance_vbo;
GLuint arrow_vao, arrow_vbo, arrow_ebo;
GLuint edge_ebo;
GLuint shader_program;
unsigned int num_instances = N_INSTANCE;
mat4 instance_matrices[N_INSTANCE];
@ -36,12 +34,12 @@ static bool rotate;
// Projection and view matrices
mat4 projection, view;
// Function Prototypes zone ---------------------------------------------------
// Function Prototypes
GLuint create_shader_program ();
void setup_cubes_buffers ();
void setup_buffers ();
void setup_arrow_buffers ();
void setup_cube_instance_data ();
void setup_instance_data ();
void setup_arrow_instance_data();
static void on_realize (GtkGLArea *area);
static gboolean on_render (GtkGLArea *area, GdkGLContext *context);
@ -49,10 +47,7 @@ static void on_activate (GtkApplication *app, gpointer user_data);
static gboolean on_mouse_scroll(GtkEventControllerScroll *controller, gdouble dx, gdouble dy, gpointer user_data);
static gboolean on_mouse_move(GtkEventControllerMotion *controller, gdouble x, gdouble y, gpointer user_data);
// ----------------------------------------------------------------------------
// Vertex and fragment shader source code
// ----------------------------------------------------------------------------
const char *vertex_shader_src = "#version 460 core\n"
"layout (location = 0) in vec3 aPos;\n"
"layout (location = 2) in mat4 instanceMatrix;\n"
@ -69,10 +64,7 @@ const char *fragment_shader_src = "#version 460 core\n"
" finalColor = vec4(FragColor.rgb, 0.3); // Set alpha to 30%\n"
"}\n";
// ----------------------------------------------------------------------------
// Vertices and indices
// ----------------------------------------------------------------------------
// Cube vertices and indices
GLfloat vertices[] = {
-0.5f, -0.5f, -0.5f, // 0
0.5f, -0.5f, -0.5f, // 1
@ -132,10 +124,6 @@ GLuint arrow_indices[] = {
0, 6 // Center to Back face
};
// ----------------------------------------------------------------------------
// MOUSE MANAGEMENT ZONE
// ----------------------------------------------------------------------------
// Maps a 2D point on the screen to a 3D point on a virtual trackball (sphere)
void trackball_map(float x, float y, int width, int height, vec3 out)
{
@ -204,6 +192,7 @@ static gboolean on_mouse_move(GtkEventControllerMotion *controller, gdouble x, g
return TRUE;
}
static gboolean on_mouse_scroll(GtkEventControllerScroll *controller, gdouble dx, gdouble dy, gpointer user_data)
{
if (dy > 0)
@ -226,294 +215,7 @@ static gboolean on_mouse_scroll(GtkEventControllerScroll *controller, gdouble dx
return TRUE;
}
// ----------------------------------------------------------------------------
// OpenGL zone
// ----------------------------------------------------------------------------
// Create the shader program
GLuint create_shader_program ()
{
GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, &vertex_shader_src, NULL);
glCompileShader(vertex_shader);
GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, &fragment_shader_src, NULL);
glCompileShader(fragment_shader);
GLuint program = glCreateProgram();
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
return program;
}
// Setup OpenGL buffers (VBO, VAO, EBO for cubes and edges)
void setup_cubes_buffers ()
{
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// Vertex buffer
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// Face Index buffer (EBO for cube faces)
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
// Vertex attributes
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// Edge Index buffer (EBO for cube edges)
glGenBuffers(1, &edge_ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, edge_ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(edge_indices), edge_indices, GL_STATIC_DRAW);
glBindVertexArray(0);
}
// Setup instance data for cubes (random positions)
void setup_cube_instance_data ()
{
g_message("[%s] setting up cube instance data...",
__func__);
srand(time(NULL));
g_message("[%s] random seed initialized",
__func__);
glGenBuffers(1, &cubes_instance_vbo);
glBindBuffer(GL_ARRAY_BUFFER, cubes_instance_vbo);
g_message("[%s] cubes_instance_vbo buffer bound",
__func__);
for (unsigned int i = 0; i < num_instances; i++) {
glm_mat4_identity(instance_matrices[i]);
// Randomize positions
vec3 position = {
(float)(rand() % N_SPACE_SIZE) - 10.0f, // Random x from -10 to 10
(float)(rand() % N_SPACE_SIZE) - 10.0f, // Random y from -10 to 10
(float)(rand() % N_SPACE_SIZE) - 10.0f // Random z from -10 to 10
};
glm_translate(instance_matrices[i], position);
}
g_message("[%s] generated %d cube instances",
__func__,
num_instances);
// Pass the instance matrices to the instance VBO
glBufferData(GL_ARRAY_BUFFER, num_instances * sizeof(mat4), instance_matrices, GL_STATIC_DRAW);
g_message("[%s] instance matrices passed to VBO",
__func__);
// Setup vertex attribute for the model matrix (location = 2)
// Setup vertex attribute for the model matrix (location = 2)
glBindVertexArray(vao);
for (int i = 0; i < 4; i++) {
glVertexAttribPointer(2 + i, 4, GL_FLOAT, GL_FALSE, sizeof(mat4), (void*)(sizeof(vec4) * i));
glEnableVertexAttribArray(2 + i);
glVertexAttribDivisor(2 + i, 1); // Tell OpenGL this is per-instance data
}
glBindVertexArray(0);
g_message("[%s] finalized model matrix vertex attribute ",
__func__);
}
void setup_arrow_buffers()
{
glGenVertexArrays(1, &arrow_vao);
glBindVertexArray(arrow_vao);
// Vertex buffer for arrows
glGenBuffers(1, &arrow_vbo);
glBindBuffer(GL_ARRAY_BUFFER, arrow_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(arrow_vertices), arrow_vertices, GL_STATIC_DRAW);
// Index buffer for arrows
glGenBuffers(1, &arrow_ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, arrow_ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(arrow_indices), arrow_indices, GL_STATIC_DRAW);
// Vertex attributes
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
}
void setup_arrow_instance_data()
{
// Define indices for the arrows (lines from center to cube faces)
GLuint arrow_indices[] = {
0, 1, // Arrow pointing to right face
0, 2, // Arrow pointing upwards
0, 3, // Arrow pointing to front face
0, 4, // Arrow pointing to left face
0, 5, // Arrow pointing downwards
0, 6 // Arrow pointing to back face
};
// Generate Vertex Buffer Object for arrows
glGenBuffers(1, &arrow_vbo);
glBindBuffer(GL_ARRAY_BUFFER, arrow_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(arrow_vertices), arrow_vertices, GL_STATIC_DRAW);
// Generate Element Buffer Object for arrows
glGenBuffers(1, &arrow_ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, arrow_ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(arrow_indices), arrow_indices, GL_STATIC_DRAW);
// Define arrow vertex attributes
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// Arrow instance matrices (positions) -- same as cubes
glGenBuffers(1, &arrow_instance_vbo);
glBindBuffer(GL_ARRAY_BUFFER, arrow_instance_vbo);
glBufferData(GL_ARRAY_BUFFER, num_instances * sizeof(mat4), instance_matrices, GL_STATIC_DRAW);
// Define vertex attribute for arrow instance matrix
for (int i = 0; i < 4; i++) {
glVertexAttribPointer(2 + i, 4, GL_FLOAT, GL_FALSE, sizeof(mat4), (void*)(sizeof(vec4) * i));
glEnableVertexAttribArray(2 + i);
glVertexAttribDivisor(2 + i, 1); // Make this per-instance data
}
glBindVertexArray(0);
}
// ----------------------------------------------------------------------------
// GTK / OpenGL zone
// ----------------------------------------------------------------------------
// Called when GtkGLArea is realized (OpenGL context is created)
static void on_realize(GtkGLArea *area)
{
g_message("[%s] GLArea realization in progress...", __func__);
gtk_gl_area_make_current(GTK_GL_AREA(area));
g_message("[%s] GLArea made current", __func__);
if (gtk_gl_area_get_error(GTK_GL_AREA(area)) != NULL) return;
g_message("[%s] OpenGL context successfully created", __func__);
// Enable depth testing
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthFunc(GL_LESS);
// Initialize cglm projection and view matrices
glm_mat4_identity(projection);
glm_perspective(glm_rad(60.0f), 800.0f / 600.0f, 0.1f, 100.0f, projection);
glm_mat4_identity(view);
glm_lookat((vec3){0.0f, 0.0f, 20.0f}, (vec3){0.0f, 0.0f, 0.0f}, (vec3){0.0f, 1.0f, 0.0f}, view);
// Initialize rotation matrix
glm_mat4_identity(rotation_matrix); // Initialize to identity
// Create shader program and setup buffers
shader_program = create_shader_program();
setup_cubes_buffers();
setup_arrow_buffers();
setup_cube_instance_data();
setup_arrow_instance_data(); // Setup arrow data
// Set the background color
glClearColor(0.1f, 0.1f, 0.1f, 1.0f); // Dark gray background
glLineWidth(2.0f); // Increase the line width for cube edges
}
// Called on each frame to render the scene
static gboolean on_render(GtkGLArea *area, GdkGLContext *context)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glUseProgram(shader_program);
// Pass projection and view matrices to the shader
GLint projectionLoc = glGetUniformLocation(shader_program, "projection");
GLint viewLoc = glGetUniformLocation(shader_program, "view");
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, (const GLfloat *)projection);
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, (const GLfloat *)view);
// Update instance matrices with the accumulated rotation matrix
if (rotate) {
for (unsigned int i = 0; i < num_instances; i++) {
mat4 model;
glm_mat4_copy(rotation_matrix, model); // Copy the accumulated rotation matrix
// Combine the rotation with the instance's individual matrix
glm_mul(model, instance_matrices[i], instance_matrices[i]);
}
rotate = FALSE;
}
// Update the instance matrix buffer with the modified instance matrices
glBindBuffer(GL_ARRAY_BUFFER, cubes_instance_vbo);
glBufferSubData(GL_ARRAY_BUFFER, 0, num_instances * sizeof(mat4), instance_matrices);
// Draw the cubes with the updated instance matrices
glUniform4f(glGetUniformLocation(shader_program, "FragColor"), 0.4f, 0.6f, 0.9f, 1.0f);
glBindVertexArray(vao);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glDrawElementsInstanced(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0, num_instances);
// Draw the cube edges
glUniform4f(glGetUniformLocation(shader_program, "FragColor"), 1.0f, 1.0f, 1.0f, 1.0f);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, edge_ebo);
glDrawElementsInstanced(GL_LINES, 24, GL_UNSIGNED_INT, 0, num_instances);
glDisable(GL_DEPTH_TEST);
// Set arrow color (e.g., red) and draw arrows
glUniform4f(glGetUniformLocation(shader_program, "FragColor"), 1.0f, 0.0f, 0.0f, 1.0f); // Red, opaque
// Bind the arrow VAO and use the same transformation matrices
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, (const GLfloat *)projection);
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, (const GLfloat *)view);
// Draw the arrows
glBindVertexArray(arrow_vao);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, arrow_ebo);
glDrawElementsInstanced(GL_LINES, 12, GL_UNSIGNED_INT, 0, num_instances);
glEnable(GL_DEPTH_TEST);
glBindVertexArray(0);
// Reset the rotation matrix to prevent continuous accumulation
glm_mat4_identity(rotation_matrix);
return TRUE;
}
// ----------------------------------------------------------------------------
// GTK ZONE
// ----------------------------------------------------------------------------
// Called when GtkApplication is activated
static void on_activate (GtkApplication *app, gpointer user_data)
@ -561,6 +263,280 @@ static void on_activate (GtkApplication *app, gpointer user_data)
__func__);
}
// Called when GtkGLArea is realized (OpenGL context is created)
static void on_realize(GtkGLArea *area)
{
g_message("[%s] GLArea realization in progress...", __func__);
gtk_gl_area_make_current(GTK_GL_AREA(area));
g_message("[%s] GLArea made current", __func__);
if (gtk_gl_area_get_error(GTK_GL_AREA(area)) != NULL) return;
g_message("[%s] OpenGL context successfully created", __func__);
// Enable depth testing
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthFunc(GL_LESS);
// Initialize cglm projection and view matrices
glm_mat4_identity(projection);
glm_perspective(glm_rad(60.0f), 800.0f / 600.0f, 0.1f, 100.0f, projection);
glm_mat4_identity(view);
glm_lookat((vec3){0.0f, 0.0f, 20.0f}, (vec3){0.0f, 0.0f, 0.0f}, (vec3){0.0f, 1.0f, 0.0f}, view);
// Initialize rotation matrix
glm_mat4_identity(rotation_matrix); // Initialize to identity
// Create shader program and setup buffers
shader_program = create_shader_program();
setup_buffers();
setup_arrow_buffers();
setup_instance_data();
setup_arrow_instance_data(); // Setup arrow data
// Set the background color
glClearColor(0.1f, 0.1f, 0.1f, 1.0f); // Dark gray background
glLineWidth(2.0f); // Increase the line width for cube edges
}
// Called on each frame to render the scene
static gboolean on_render(GtkGLArea *area, GdkGLContext *context)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glUseProgram(shader_program);
// Pass projection and view matrices to the shader
GLint projectionLoc = glGetUniformLocation(shader_program, "projection");
GLint viewLoc = glGetUniformLocation(shader_program, "view");
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, (const GLfloat *)projection);
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, (const GLfloat *)view);
// Update instance matrices with the accumulated rotation matrix
if (rotate) {
for (unsigned int i = 0; i < num_instances; i++) {
mat4 model;
glm_mat4_copy(rotation_matrix, model); // Copy the accumulated rotation matrix
// Combine the rotation with the instance's individual matrix
glm_mul(model, instance_matrices[i], instance_matrices[i]);
}
rotate = FALSE;
}
// Update the instance matrix buffer with the modified instance matrices
glBindBuffer(GL_ARRAY_BUFFER, instance_vbo);
glBufferSubData(GL_ARRAY_BUFFER, 0, num_instances * sizeof(mat4), instance_matrices);
// Draw the cubes with the updated instance matrices
glUniform4f(glGetUniformLocation(shader_program, "FragColor"), 0.4f, 0.6f, 0.9f, 1.0f);
glBindVertexArray(vao);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glDrawElementsInstanced(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0, num_instances);
// Draw the cube edges
glUniform4f(glGetUniformLocation(shader_program, "FragColor"), 1.0f, 1.0f, 1.0f, 1.0f);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, edge_ebo);
glDrawElementsInstanced(GL_LINES, 24, GL_UNSIGNED_INT, 0, num_instances);
glDisable(GL_DEPTH_TEST);
// Set arrow color (e.g., red) and draw arrows
glUniform4f(glGetUniformLocation(shader_program, "FragColor"), 1.0f, 0.0f, 0.0f, 1.0f); // Red, opaque
glBindVertexArray(arrow_vao);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, arrow_ebo);
glDrawElementsInstanced(GL_LINES, 12, GL_UNSIGNED_INT, 0, num_instances);
glEnable(GL_DEPTH_TEST);
glBindVertexArray(0);
// Reset the rotation matrix to prevent continuous accumulation
glm_mat4_identity(rotation_matrix);
return TRUE;
}
// Create the shader program
GLuint create_shader_program ()
{
GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, &vertex_shader_src, NULL);
glCompileShader(vertex_shader);
GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, &fragment_shader_src, NULL);
glCompileShader(fragment_shader);
GLuint program = glCreateProgram();
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
return program;
}
// Setup OpenGL buffers (VBO, VAO, EBO for cubes and edges)
void setup_buffers ()
{
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// Vertex buffer
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// Face Index buffer (EBO for cube faces)
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
// Vertex attributes
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// Edge Index buffer (EBO for cube edges)
glGenBuffers(1, &edge_ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, edge_ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(edge_indices), edge_indices, GL_STATIC_DRAW);
glBindVertexArray(0);
}
void setup_arrow_buffers() {
glGenVertexArrays(1, &arrow_vao);
glBindVertexArray(arrow_vao);
// Vertex buffer for arrows
glGenBuffers(1, &arrow_vbo);
glBindBuffer(GL_ARRAY_BUFFER, arrow_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(arrow_vertices), arrow_vertices, GL_STATIC_DRAW);
// Index buffer for arrows
glGenBuffers(1, &arrow_ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, arrow_ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(arrow_indices), arrow_indices, GL_STATIC_DRAW);
// Vertex attributes
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
}
// Setup instance data for cubes (random positions)
void setup_instance_data ()
{
g_message("[%s] setting up cube instance data...",
__func__);
srand(time(NULL));
g_message("[%s] random seed initialized",
__func__);
glGenBuffers(1, &instance_vbo);
glBindBuffer(GL_ARRAY_BUFFER, instance_vbo);
g_message("[%s] instance_vbo buffer bound",
__func__);
for (unsigned int i = 0; i < num_instances; i++) {
glm_mat4_identity(instance_matrices[i]);
// Randomize positions
vec3 position = {
(float)(rand() % N_SPACE_SIZE) - 10.0f, // Random x from -10 to 10
(float)(rand() % N_SPACE_SIZE) - 10.0f, // Random y from -10 to 10
(float)(rand() % N_SPACE_SIZE) - 10.0f // Random z from -10 to 10
};
glm_translate(instance_matrices[i], position);
}
g_message("[%s] generated %d cube instances",
__func__,
num_instances);
// Pass the instance matrices to the instance VBO
glBufferData(GL_ARRAY_BUFFER, num_instances * sizeof(mat4), instance_matrices, GL_STATIC_DRAW);
g_message("[%s] instance matrices passed to VBO",
__func__);
// Setup vertex attribute for the model matrix (location = 2)
// Setup vertex attribute for the model matrix (location = 2)
glBindVertexArray(vao);
for (int i = 0; i < 4; i++) {
glVertexAttribPointer(2 + i, 4, GL_FLOAT, GL_FALSE, sizeof(mat4), (void*)(sizeof(vec4) * i));
glEnableVertexAttribArray(2 + i);
glVertexAttribDivisor(2 + i, 1); // Tell OpenGL this is per-instance data
}
glBindVertexArray(0);
g_message("[%s] finalized model matrix vertex attribute ",
__func__);
}
void setup_arrow_instance_data() {
// Define indices for the arrows (lines from center to cube faces)
GLuint arrow_indices[] = {
0, 1, // Arrow pointing to right face
0, 2, // Arrow pointing upwards
0, 3, // Arrow pointing to front face
0, 4, // Arrow pointing to left face
0, 5, // Arrow pointing downwards
0, 6 // Arrow pointing to back face
};
// Generate Vertex Array Object for arrows
glGenVertexArrays(1, &arrow_vao);
glBindVertexArray(arrow_vao);
// Generate Vertex Buffer Object for arrows
GLuint arrow_vbo;
glGenBuffers(1, &arrow_vbo);
glBindBuffer(GL_ARRAY_BUFFER, arrow_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(arrow_vertices), arrow_vertices, GL_STATIC_DRAW);
// Generate Element Buffer Object for arrows
GLuint arrow_ebo;
glGenBuffers(1, &arrow_ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, arrow_ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(arrow_indices), arrow_indices, GL_STATIC_DRAW);
// Define arrow vertex attributes
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// Arrow instance matrices (positions) -- same as cubes
glGenBuffers(1, &arrow_instance_vbo);
glBindBuffer(GL_ARRAY_BUFFER, arrow_instance_vbo);
glBufferData(GL_ARRAY_BUFFER, num_instances * sizeof(mat4), instance_matrices, GL_STATIC_DRAW);
// Define vertex attribute for arrow instance matrix
for (int i = 0; i < 4; i++) {
glVertexAttribPointer(2 + i, 4, GL_FLOAT, GL_FALSE, sizeof(mat4), (void*)(sizeof(vec4) * i));
glEnableVertexAttribArray(2 + i);
glVertexAttribDivisor(2 + i, 1); // Make this per-instance data
}
glBindVertexArray(0);
}
// Main Function
int main (int argc, char *argv[])
{
@ -595,4 +571,3 @@ int main (int argc, char *argv[])
return status;
}