How do I rotate around the instance itself instead of the rotating the entire shader? You can see what I mean by rotating the entire shader in the images below:

Here is the main.c:
#include <glad/glad.h>#include <GLFW/glfw3.h>#include <cglm/cglm.h>#include <stdio.h>#include "file.h"const unsigned int SCR_WIDTH = 1280;const unsigned int SCR_HEIGHT = 720;const char* vert_shader_path = "<path_to_project>/shaders/inst_shader.vert";const char* frag_shader_path = "<path_to_project>/shaders/inst_shader.frag";int main(){ // Initialize GLFW glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // Create window and make it the current context GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "MINIMAL INSTANCING", 0, 0); if(window == 0) { printf("Failed to create GLFW window\n"); glfwTerminate(); return -1; } glfwMakeContextCurrent(window); // Initialize Open GL via glad if(!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { printf("Failed to init GLAD\n"); glfwTerminate(); return -1; } int err; char* vert_shader_src; char* frag_shader_src; // Read in the shader file binary data err = read_file_binary(vert_shader_path, &vert_shader_src); if(err) return err; err = read_file_binary(frag_shader_path, &frag_shader_src); if(err) return err; // Create Vertex Shader unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertexShader, 1, (const char**)&vert_shader_src, 0); glCompileShader(vertexShader); int success; char infoLog[512]; glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success); if(!success) { glGetShaderInfoLog(vertexShader, 512, 0, infoLog); printf("ERROR VERTEX %s\n", infoLog); } // Create Fragment Shader unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragmentShader, 1, (const char**)&frag_shader_src, 0); glCompileShader(fragmentShader); glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success); if(!success) { glGetShaderInfoLog(fragmentShader, 512, 0, infoLog); printf("ERROR FRAGMENT %s\n", infoLog); } // Create Shader Program and Link the Vertex / Fragment shaders unsigned int shaderProgram = glCreateProgram(); glAttachShader(shaderProgram, vertexShader); glAttachShader(shaderProgram, fragmentShader); glLinkProgram(shaderProgram); glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success); if(!success) { glGetProgramInfoLog(shaderProgram, 512, 0, infoLog); printf("ERROR LINKING %s\n", infoLog); } // Delete the shaders since they are linked to the shader program glDeleteShader(vertexShader); glDeleteShader(fragmentShader); free(frag_shader_src); free(vert_shader_src); // Instance setup and memory allocation unsigned int instance_count = 264; float* instance_data; instance_data = (float*)malloc(sizeof(float) * 2 * instance_count); // Build the offests int inst_index = 0; float inst_offset = 0.1f; for(int y = -12; y < 12; y += 2) { for(int x = -22; x < 22; x += 2) { instance_data[inst_index + 0] = (float) x / 10.0f + inst_offset; instance_data[inst_index + 1] = (float) y / 10.0f + inst_offset; inst_index += 2; } } // Generate the instance buffers unsigned int instVBO; glGenBuffers(1, &instVBO); glBindBuffer(GL_ARRAY_BUFFER, instVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 2 * instance_count, &instance_data[0], GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); // Vertex positions and vertex colors float vertices[] = { 0.05f, 0.05f, /* top right */ 0.0f, 0.0f, 1.0f, // Blue 0.05f, -0.05f, /* bottom right */ 1.0f, 0.0f, 0.0f, // Red -0.05f, -0.05f, /* bottom left */ 1.0f, 1.0f, 0.0f, // Yellow -0.05f, 0.05f, /* top left */ 0.0f, 1.0f, 0.0f // Green }; // Indices for each triangle in the quad unsigned int indices[] = { 0, 1, 3, // first triangle 1, 2, 3 // second triangle }; // Generate quad arrays and buffers unsigned int quadVAO, quadVBO, quadEBO; glGenVertexArrays(1, &quadVAO); glGenBuffers(1, &quadVBO); glGenBuffers(1, &quadEBO); // Bind the Vertex Array before manipulation glBindVertexArray(quadVAO); // Bind the Array Buffer and set the data from the vertices array glBindBuffer(GL_ARRAY_BUFFER, quadVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // Bind the Element Buffer and set the data from the indices array glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quadEBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); // Setup the quad buffer layout // 0: 2 / 5 ITEMS @ 0 [X, X, -, -, -] glEnableVertexAttribArray(0); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); // 1: 3 / 5 ITEMS @ 2 [-, -, X, X, X] glEnableVertexAttribArray(1); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(2 * sizeof(float))); // Setup the instance buffer layout // 0: 2 / 2 ITEMS @ 0 [X, X] glEnableVertexAttribArray(2); glBindBuffer(GL_ARRAY_BUFFER, instVBO); glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0); glBindBuffer(GL_ARRAY_BUFFER, 0); // This tells OpenGL this is an instanced vertex attribute glVertexAttribDivisor(2, 1); glBindVertexArray(0); mat4 projection, view, rotation; vec3 eye = {0.0f, 0.0f, 3.0f}; vec3 center = {0.0f, 0.0f, 0.0f}; vec3 up = {0.0f, 1.0f, 0.0f}; vec3 pivot, axis; float angle; glm_vec3_zero(pivot); glm_vec3_zero(axis); pivot[0] = 0.0f; pivot[1] = 0.0f; axis[2] = 1.0f; angle = 45.0f; glm_mat4_identity(rotation); glm_rotate_at(rotation, pivot, glm_rad(angle), axis); while(!glfwWindowShouldClose(window)) { if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, 1); glClearColor(0.1f, 0.1f, 0.1f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glm_perspective(glm_rad(45.0f), (float)SCR_WIDTH/(float)SCR_HEIGHT, 0.1f, 1000.0f, projection); glm_lookat(eye, center, up, view); glUseProgram(shaderProgram); glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "projection"), 1, GL_FALSE, &projection[0][0]); glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "view"), 1, GL_FALSE, &view[0][0]); glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "rotation"), 1, GL_FALSE, &rotation[0][0]); glBindVertexArray(quadVAO); glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0, instance_count); glBindVertexArray(0); glfwSwapBuffers(window); glfwPollEvents(); } glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0); glDeleteVertexArrays(1, &quadVAO); glDeleteBuffers(1, &quadVBO); glDeleteProgram(shaderProgram); glfwTerminate(); return 0;}Here is the shader code:
#version 330 corelayout (location = 0) in vec2 aPos;layout (location = 1) in vec3 aColor;layout (location = 2) in vec2 aOffset;uniform mat4 projection;uniform mat4 view;uniform mat4 rotation;out vec3 fColor;void main(){ fColor = aColor; gl_Position = projection * view * rotation * vec4(aPos + aOffset, 0.0, 1.0);}Any help I can get would be greatly appreciated, I have been stuck on this for a while now.
1 Answer1
In order to apply the rotation to each instance rather than the whole scene, you need to apply the rotation to each instance's vertex position andnot apply it to the offset.
gl_Position = projection * view * ( rotation * vec4(aPos, 0.0, 1.0) + vec4(aOffset, 0.0, 0.0));- $\begingroup$Interesting, that worked for me but why does it change the spacing? With that they become much more tightly packed$\endgroup$cvolpe– cvolpe2025-11-22 19:03:29 +00:00CommentedNov 22 at 19:03
- $\begingroup$@cvolpe If you rotate squares by 45 degrees without changing the grid arrangement at all, the corners will become closer to each other, but in exchange, there will be more empty space diagonally — it becomes closer to a checkerboard pattern. If that's not what you mean, a picture will be needed, and it may be a different question.$\endgroup$Kevin Reid– Kevin Reid2025-11-23 00:19:57 +00:00CommentedNov 23 at 0:19
Explore related questions
See similar questions with these tags.
