Instancing Doesn't Display

hello, i followed this tutorial for project i’m working on, but somehow only one cube is being drawed.
here is the class source:

class MainWindow
{
  private:
	GLFWwindow *window;

	unsigned int VertexArrayID; // Objects
	unsigned int VBO;			// Vertex Buffer Object
	unsigned int InstanceVBO;   //Instance Vertex Buffer Object
	unsigned int ProgramID;		// Program

	std::vector<glm::vec3> translations; // Instance Positions

	unsigned int MatrixID; // Handler
	glm::mat4 MVP;		   // Projection * View * Model

	// Setting up
	void Setup()
	{
		// GLFW Initialization
		if (glfwInit() == false)
			throw std::runtime_error("Failed to initialize GLFW!");

		glfwWindowHint(GLFW_SAMPLES, 4);			   // Anti-Aliasing
		glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // OpenGL Version
		glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
		glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // Old OpenGL De-Support

		// Window Creation
		window = glfwCreateWindow(800, 800, "Wave Cube", nullptr, nullptr);
		// Window Checking
		if (window == nullptr)
			throw std::runtime_error("GLFW Window could not be Created!");

		glfwMakeContextCurrent(window); // OpenGL Context

		// OpenGL Initialization
		glewExperimental = true;
		if (glewInit() != GLEW_OK)
			throw std::runtime_error("Failed to initialize GLEW!");

		glfwSetInputMode(window, GLFW_STICKY_KEYS, true); // Enable Keyboard
		glEnable(GL_DEPTH_TEST);

		// Setting Up Positions
		for (int y = 0; y < SIZE; y += 1)
		{
			for (int x = 0; x < SIZE; x += 1)
			{
				for (int z = 0; z < SIZE; z += 1)
					translations.push_back(glm::vec3(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z)));
			}
		}
	}

	void Creation()
	{
		glGenBuffers(1, &InstanceVBO);
		glBindBuffer(GL_ARRAY_BUFFER, InstanceVBO);
		glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * translations.size(), &translations[0], GL_STATIC_DRAW);
		glBindBuffer(GL_ARRAY_BUFFER, 0);

		// VAO Setting Up
		glGenVertexArrays(1, &VertexArrayID);
		glBindVertexArray(VertexArrayID);

		// Vertex Buffer Object
		glGenBuffers(1, &VBO); // Generate Buffer
		glBindBuffer(GL_ARRAY_BUFFER, VBO);
		glBufferData(GL_ARRAY_BUFFER, sizeof(cubeData), cubeData, GL_STATIC_DRAW); // Set Vertices
		glEnableVertexAttribArray(0);											   // Vertices Attribute
		glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, nullptr);
		glEnableVertexAttribArray(1);
		glBindBuffer(GL_ARRAY_BUFFER, InstanceVBO);
		glVertexAttribPointer(1, 3, GL_FLOAT, false, 0, nullptr);
		glBindBuffer(GL_ARRAY_BUFFER, 0);

		glVertexAttribDivisor(1, 1);

		ProgramID = LoadShaders("cube.vert", "cube.frag"); // Program Shaders
	}

	void Projection()
	{
		MatrixID = glGetUniformLocation(ProgramID, "MVP");									 // Get MVP
		glm::mat4 Projection = glm::perspective(glm::radians(90.f), 4.f / 3.f, 0.1f, 100.f); // Projection Matrix
		glm::mat4 View = glm::lookAt(glm::vec3(4, 5, 3),									 // View Matrix
									 glm::vec3(0, 0, 0),
									 glm::vec3(0, 1, 0));
		glm::mat4 Model = glm::scale(glm::mat4(1.f), glm::vec3(0.1f));
		MVP = Projection * View * Model;
	}

	void Loop()
	{
		glClearColor(1.f, 0.f, 0.f, 1.f);

		while (glfwGetKey(window, GLFW_KEY_ESCAPE) != true && glfwWindowShouldClose(window) == 0)
		{
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Buffer

			glUseProgram(ProgramID);
			glUniformMatrix4fv(MatrixID, 1, false, &MVP[0][0]); // Send Transformation
			glBindVertexArray(VertexArrayID);
			glDrawArraysInstanced(GL_TRIANGLES, 0, 12 * 3, translations.size());
			glBindVertexArray(0);

			glfwSwapBuffers(window);
			glfwPollEvents();
		}
	}

  public:
	void run()
	{
		Setup();
		Creation();
		Projection();
		Loop();
	}

	~MainWindow()
	{
		// Cleanup
		glDeleteBuffers(1, &VBO);
		glDeleteProgram(ProgramID);
		glDeleteVertexArrays(1, &VertexArrayID);

		// Close Window
		glfwTerminate();
	}
};

I’ve been sitting on it for a whole day with no success, i don’t know what am i doing wrong…

You might post your shaders too. It’s obvious you’re doing something a bit different than the tutorial. Most importantly, we want to verify that the vertex attribute bindings are correct.

and what is “cubeData” ? a pointer ? you may want to upload more than 4 (32bit) or 8 (64bit) byte into the vertexbuffer …

here is my fragment shader:

#version 330 core
 
out vec3 color;
 
void main()
{
    color = vec3(0, 0, 0);
}

vertex shader:

#version 330 core
 
layout(location = 0) in vec3 modelPosition;
layout(location = 1) in vec3 offest;
uniform mat4 MVP;
 
void main()
{
    gl_Position = MVP * vec4(modelPosition + offest, 1);
}

Cube Data is just bunch of vertices.

static const float cubeData[] = {
    -1.0f, -1.0f, -1.0f,
    -1.0f, -1.0f, 1.0f,
    -1.0f, 1.0f, 1.0f,
    1.0f, 1.0f, -1.0f,
    -1.0f, -1.0f, -1.0f,
    -1.0f, 1.0f, -1.0f,
    1.0f, -1.0f, 1.0f,
    -1.0f, -1.0f, -1.0f,
    1.0f, -1.0f, -1.0f,
    1.0f, 1.0f, -1.0f,
    1.0f, -1.0f, -1.0f,
    -1.0f, -1.0f, -1.0f,
    -1.0f, -1.0f, -1.0f,
    -1.0f, 1.0f, 1.0f,
    -1.0f, 1.0f, -1.0f,
    1.0f, -1.0f, 1.0f,
    -1.0f, -1.0f, 1.0f,
    -1.0f, -1.0f, -1.0f,
    -1.0f, 1.0f, 1.0f,
    -1.0f, -1.0f, 1.0f,
    1.0f, -1.0f, 1.0f,
    1.0f, 1.0f, 1.0f,
    1.0f, -1.0f, -1.0f,
    1.0f, 1.0f, -1.0f,
    1.0f, -1.0f, -1.0f,
    1.0f, 1.0f, 1.0f,
    1.0f, -1.0f, 1.0f,
    1.0f, 1.0f, 1.0f,
    1.0f, 1.0f, -1.0f,
    -1.0f, 1.0f, -1.0f,
    1.0f, 1.0f, 1.0f,
    -1.0f, 1.0f, -1.0f,
    -1.0f, 1.0f, 1.0f,
    1.0f, 1.0f, 1.0f,
    -1.0f, 1.0f, 1.0f,
    1.0f, -1.0f, 1.0f};

is it possible that all the instanced cubes are rendering at the same position ?

I have actually made some videos that follow this exact tutorial, I hope they help you (there are four parts):

Part 1 https://www.youtube.com/watch?v=BxkPiID_M9g

Part 2 https://www.youtube.com/watch?v=Hw1ySlrlbVk&t=36s

Part 3 https://www.youtube.com/watch?v=PuZsUJetbng&t=2s

Part 4 https://www.youtube.com/watch?v=iXegHQ7s9Hw

Thanks,

Jeff

Yes. It’s also possible that you’re rendering all but one of the instances off-screen. Another possibility is you’re rendering all of them except 1 transparent.

A few random thoughts:

What’s SIZE set to?

Change the body of your frag shader main() to just:


gl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );

You’re applying your translations (offest in the shader) in OBJECT space. Depending on your MVP, that could easily land all instances but one off-screen. Instead, try applying it in VIEWPORT-space (pixels) like this:


gl_Position = MVP * vec4(modelPosition, 1);
gl_Position.xy += vec2( offest.x / XRES, offest.y * / YRES ) * 2 *  gl_Position.w;

Replace XRES and YRES with the width and height of your viewport (e.g. window). This gl_Position logic should space out your instances so that they are offset by 1 pixel in X and/or Y based on each offest.xy step (by the way, “offest” is spelled “offset”). Note though that this does assume the instance with translation (0,0,0) actually appears on-screen based on your MVP. If not, then you need to fix that. It probably will, given that you’re looking at the origin.

[QUOTE=Dark Photon;1290181]
What’s SIZE set to?[/QUOTE]

#define SIZE 5

[QUOTE=Dark Photon;1290181]Change the body of your frag shader main() to just:
Code glsl:

gl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );

You’re applying your translations (offest in the shader) in OBJECT space. Depending on your MVP, that could easily land all instances but one off-screen. Instead, try applying it in VIEWPORT-space (pixels) like this:

Code glsl:

gl_Position = MVP * vec4(modelPosition, 1);
gl_Position.xy += vec2( offest.x / XRES, offest.y * / YRES ) * 2 * gl_Position.w;

Replace XRES and YRES with the width and height of your viewport (e.g. window). This gl_Position logic should space out your instances so that they are offset by 1 pixel in X and/or Y based on each offest.xy step (by the way, “offest” is spelled “offset”). Note though that this does assume the instance with translation (0,0,0) actually appears on-screen based on your MVP. If not, then you need to fix that. It probably will, given that you’re looking at the origin. [/QUOTE]
I did what you said, but the result is the same as the beginning, only one cube is being rendered.

Ok. Try other things. Such as…
Change your modeling transform so you can see more/less of your scene.
Dump your translations array to make sure it’s what you think it is.
Try making changes to its contents to get a line on which instance(s) you’re seeing and why.
Make some debug change to your shader so you can determine what “offest” is in your shader for the instance that you’re seeing.
etc.

i’d start it this way:

  1. draw 1 point at (0, 0, 0)
glDrawArrays(GL_POINTS, 0, 1);
  1. draw 5 points at (0.0, 0, 0), (0.1, 0, 0), … (0.4, 0, 0) to check if you’ve correctly setup the instance buffer / attribute
glDrawArraysInstanced(GL_POINTS, 0, 1, 5);
  1. draw 5 little triangles to check your vertexbuffer
glDrawArraysInstanced(GL_TRIANGLES, 0, 3, 5);

the instanced attribute “offset” has to be set up exactly as the “position” attribute, with 1 exception:

glVertexAttribDivisor(instancedattribindex, 1);
// instancedattribindex being 1 in your shader

thank you guys, i’ll probably will add a camera that i can control with mouse to check i’m not missing anything, and will use a similar code to this to work on 2d to diagnose the issue.

Are you sure that translations.size() (used in the draw call) is giving you a number greater than one?

Jeff

[QUOTE=OceanJeff40;1290203]Are you sure that translations.size() (used in the draw call) is giving you a number greater than one?

Jeff[/QUOTE]

yep, i checked the numbers inside the vector.

anyway, i started off from scratch and managed to get instancing to work!

[QUOTE=OceanJeff40;1290203]Are you sure that translations.size() (used in the draw call) is giving you a number greater than one?

Jeff[/QUOTE]

yep, i checked the numbers inside the vector.

anyway, i started off from scratch and managed to get instancing to work!

Also, yeah, if you’re using the code from the website, make sure you have all of it, some of the code is linked with URLs hyperlinks in the source code of main.

Also, make sure if you have all the code, make sure it’s current from that particular tutorial, as past tutorials wouldn’t have all the updated code … maybe?

Jeff