PDA

View Full Version : Instancing Doesn't Display



therealcain
01-16-2018, 11:59 PM
hello, i followed this tutorial (https://learnopengl.com/#!Advanced-OpenGL/Instancing) 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...

Dark Photon
01-17-2018, 04:54 AM
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.

john_connor
01-17-2018, 05:44 AM
and what is "cubeData" ? a pointer ? you may want to upload more than 4 (32bit) or 8 (64bit) byte into the vertexbuffer ...

therealcain
01-17-2018, 08:37 AM
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 ?

OceanJeff40
01-18-2018, 04:56 PM
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

Dark Photon
01-18-2018, 05:52 PM
is it possible that all the instanced cubes are rendering at the same position ?

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.

therealcain
01-19-2018, 12:36 AM
What's SIZE set to?

#define SIZE 5


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.
I did what you said, but the result is the same as the beginning, only one cube is being rendered.

Dark Photon
01-19-2018, 04:46 AM
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.

john_connor
01-19-2018, 06:15 AM
i'd start it this way:
1. draw 1 point at (0, 0, 0)

glDrawArrays(GL_POINTS, 0, 1);

2. 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);

3. 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

therealcain
01-19-2018, 12:00 PM
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.

OceanJeff40
01-19-2018, 07:12 PM
Are you sure that translations.size() (used in the draw call) is giving you a number greater than one?

Jeff

therealcain
01-20-2018, 03:07 AM
Are you sure that translations.size() (used in the draw call) is giving you a number greater than one?

Jeff

yep, i checked the numbers inside the vector.

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

OceanJeff40
01-21-2018, 01:35 PM
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