Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
I have this code :
Upp::Vector<float> verticesTriangle{
1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, -0.5f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, -0.5f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f,
};
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
//Setting up the VAO Attribute format
glVertexArrayAttribFormat(VAO, 0, 3, GL_FLOAT, GL_FALSE, 0); //Will be colors (R G B in float)
glVertexArrayAttribFormat(VAO, 1, 2, GL_FLOAT, GL_FALSE, 3); //Will be texture coordinates
glVertexArrayAttribFormat(VAO, 2, 3, GL_FLOAT, GL_FALSE, 5); //Normals
glVertexArrayAttribFormat(VAO, 3, 3, GL_FLOAT, GL_FALSE, 8); //Will be my position
glEnableVertexArrayAttrib(VAO, 0);
glEnableVertexArrayAttrib(VAO, 1);
glEnableVertexArrayAttrib(VAO, 2);
glEnableVertexArrayAttrib(VAO, 3);
//Generating a VBO
glGenBuffers(1, &VBOCarre);
glBindBuffer(GL_ARRAY_BUFFER, VBOCarre);
glBufferStorage(GL_ARRAY_BUFFER, sizeof(float) * verticesTriangle.GetCount(), verticesTriangle, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
//Binding the VBO to be read by VAO
glVertexArrayVertexBuffer(VAO, 0, VBOCarre, 0 * sizeof(float), 11 * sizeof(float));
glVertexArrayVertexBuffer(VAO, 1, VBOCarre, 3 * sizeof(float), 11 * sizeof(float));
glVertexArrayVertexBuffer(VAO, 2, VBOCarre, 5 * sizeof(float), 11 * sizeof(float));
glVertexArrayVertexBuffer(VAO, 3, VBOCarre, 8 * sizeof(float), 11 * sizeof(float));
//Bind VAO
glBindVertexArray(VAO);
I have no problem retrieving the first attribute in my shader however, when I trying to retrieve others, It dont work. To test it, I have setup an float array and a simple shader program and I try to retrieve my position to draw a triangle.
Here is how my datas are ordered :
Here is my vertex shader :
#version 400
layout (location = 0) in vec3 colors;
layout (location = 1) in vec2 textCoords;
layout (location = 2) in vec3 normals;
layout (location = 3) in vec3 positions;
out vec3 fs_colors;
void main()
{
gl_Position = vec4(positions.x, positions.y, positions.z, 1.0);
// gl_Position = vec4(colors.x, colors.y, colors.z, 1.0); //This line work, proofing my
// first attribute is sended well to my shader
fs_colors = colors;
}
The problem is, except the first attribute, all others seems to not be sent to the shader. What am I missing ?!
You're putting stuff in the wrong place.
glVertexArrayAttribFormat(VAO, 1, 2, GL_FLOAT, GL_FALSE, 3); //Will be texture coordinates
The "3" here is being passed as a byte offset from the start of a vertex in the array to the particular data for that vertex in the attribute. Obviously, your texture coordinate is not 3 bytes from the start of your vertex; it's 3 * sizeof(float) bytes from the start of the vertex.
Similarly:
glVertexArrayVertexBuffer(VAO, 1, VBOCarre, 3 * sizeof(float), 11 * sizeof(float));
This makes no sense either. You're only using a single buffer, and all four attributes read from the same binding. So you should only bind a single buffer.
The offset ought to be 0, because that's where a vertex in the buffer starts. And the stride should be what you wrote.
You also never directly set the association between the attributes and the binding index with glVertexArrayAttribBinding. You probably got things to work by relying on the default, but you shouldn't be using the default here.
The correct code would be:
//Generating a VBO
glCreateBuffers(1, &VBOCarre);
//No need to call glBindBuffer(GL_ARRAY_BUFFER, VBOCarre);, since we're doing DSA.
glNamedBufferStorage(VBOCarre, sizeof(float) * verticesTriangle.GetCount(), verticesTriangle, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
glCreateVertexArrays(1, &VAO);
//No need to glBindVertexArray(VAO);, since we're using DSA.
//Setting up the VAO Attribute format
glEnableVertexArrayAttrib(VAO, 0);
glVertexArrayAttribFormat(VAO, 0, 3, GL_FLOAT, GL_FALSE, 0); //Will be colors (R G B in float)
glEnableVertexArrayAttrib(VAO, 1);
glVertexArrayAttribFormat(VAO, 1, 2, GL_FLOAT, GL_FALSE, 3 * sizeof(float)); //Will be texture coordinates
glEnableVertexArrayAttrib(VAO, 2);
glVertexArrayAttribFormat(VAO, 2, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float)); //Normals
glEnableVertexArrayAttrib(VAO, 3);
glVertexArrayAttribFormat(VAO, 3, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float)); //Will be my position
//One buffer, one binding.
glVertexArrayVertexBuffer(VAO, 0, VBOCarre, 0, 11 * sizeof(float));
//Make all attributes read from the same buffer.
glVertexArrayAttribBinding(VAO, 0, 0);
glVertexArrayAttribBinding(VAO, 1, 0);
glVertexArrayAttribBinding(VAO, 2, 0);
glVertexArrayAttribBinding(VAO, 3, 0);
//We can glBindVertexArray(VAO); when we're about to use it, not just because we finished setting it up.
I'm learning OpenGL and I'm trying to implement some particles in my application.
To do so, I followed some courses.
But when I try to render my particles, nothing happen, it doesn't even enter the shader (I tried to put some infinite loop in it and nothing happened). I tried a lot of thing, maybe there is something I did not understand..
I created a class Particle, with a constructor, an update and a draw method, I followed every step of the course, and adapted it to my class (the course is doing everything in the main loop).
My particles class got some private members:
private:
size_t maxSize_;
std::vector<float> quadData_;
unsigned int dataVbo_;
std::vector<float> posData_;
unsigned int posVbo_;
std::vector<float> colorData_;
unsigned int colorVbo_;
std::list<Particle> allParticles_;
and here is the initialization of Particles:
Particles::Particles(size_t maxSize)
: maxSize_(maxSize), quadData_({-0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f, -0.5f, 0.5f, 0.0f, 0.5f, 0.5f, 0.0f})
{
posData_.resize(maxSize_*4);
colorData_.resize(maxSize_*4);
glGenBuffers(1, &dataVbo_);
glBindBuffer(GL_ARRAY_BUFFER, dataVbo_);
glBufferData(GL_ARRAY_BUFFER, quadData_.size() * sizeof(float), quadData_.data(), GL_STATIC_DRAW);
// The VBO containing the positions and sizes of the particles
glGenBuffers(1, &posVbo_);
glBindBuffer(GL_ARRAY_BUFFER, posVbo_);
// Initialize with empty (NULL) buffer : it will be updated later, each frame.
glBufferData(GL_ARRAY_BUFFER, maxSize_ * 4 * sizeof(float), NULL, GL_STREAM_DRAW);
// The VBO containing the colors of the particles
glGenBuffers(1, &colorVbo_);
glBindBuffer(GL_ARRAY_BUFFER, colorVbo_);
// Initialize with empty (NULL) buffer : it will be updated later, each frame.
glBufferData(GL_ARRAY_BUFFER, maxSize_ * 4 * sizeof(float), NULL, GL_STREAM_DRAW);
}
and the draw:
void Particles::draw(){
size_t count(posData_.size());
glBindBuffer(GL_ARRAY_BUFFER, posVbo_);
glBufferData(GL_ARRAY_BUFFER, maxSize_ * 4 * sizeof(float), NULL, GL_STREAM_DRAW); // Buffer orphaning, a common way to improve streaming perf. See above link for details.
glBufferSubData(GL_ARRAY_BUFFER, 0, count * sizeof(float), posData_.data());
glBindBuffer(GL_ARRAY_BUFFER, colorVbo_);
glBufferData(GL_ARRAY_BUFFER, maxSize_ * 4 * sizeof(float), NULL, GL_STREAM_DRAW); // Buffer orphaning, a common way to improve streaming perf. See above link for details.
glBufferSubData(GL_ARRAY_BUFFER, 0, count * sizeof(float) * 4, colorData_.data());
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, dataVbo_);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0);
// 2nd attribute buffer : positions of particles' centers
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, posVbo_);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (void*) 0);
// 3rd attribute buffer : particles' colors
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, colorVbo_);
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 0, (void*) 0);
glVertexAttribDivisor(0, 0); // particles vertices : always reuse the same 4 vertices -> 0
glVertexAttribDivisor(1, 1); // positions : one per quad (its center) -> 1
glVertexAttribDivisor(2, 1); // color : one per quad -> 1
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, count);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
}
And in my main loop I'm doing this:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
myParticules.update(elapsedTime);
glDisable(GL_DEPTH_TEST);
glUseProgram(_particleShad);
myParticles.draw();
I'm also sending some uniform vec and mat, but nothing important.
In my shader I only try to do this:
Vertex :
gl_Position = vec4(squareVertices.xyz, 1);
//squareVertices contain the vertices of my square for my particles
Fragment :
color = vec4(1, 1, 1, 1);
I don't find anything wrong, I really need some help, I'm totally lost.
You must create a VAO (Vertex Array Object):
class Particles {
private:
// add:
GLuint vao;
...
Initialization:
Particles::Particles(size_t maxSize)
: maxSize_(maxSize), quadData_({-0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f, -0.5f, 0.5f, 0.0f, 0.5f, 0.5f, 0.0f})
{
posData_.resize(maxSize_*4);
colorData_.resize(maxSize_*4);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &dataVbo_);
glBindBuffer(GL_ARRAY_BUFFER, dataVbo_);
glBufferData(GL_ARRAY_BUFFER, quadData_.size() * sizeof(float), quadData_.data(), GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0);
// The VBO containing the positions and sizes of the particles
glGenBuffers(1, &posVbo_);
glBindBuffer(GL_ARRAY_BUFFER, posVbo_);
// Initialize with empty (NULL) buffer : it will be updated later, each frame.
glBufferData(GL_ARRAY_BUFFER, maxSize_ * 4 * sizeof(float), NULL, GL_STREAM_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (void*) 0);
// The VBO containing the colors of the particles
glGenBuffers(1, &colorVbo_);
glBindBuffer(GL_ARRAY_BUFFER, colorVbo_);
// Initialize with empty (NULL) buffer : it will be updated later, each frame.
glBufferData(GL_ARRAY_BUFFER, maxSize_ * 4 * sizeof(float), NULL, GL_STREAM_DRAW);
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 0, (void*) 0);
glVertexAttribDivisor(0, 0); // particles vertices : always reuse the same 4 vertices -> 0
glVertexAttribDivisor(1, 1); // positions : one per quad (its center) -> 1
glVertexAttribDivisor(2, 1); // color : one per quad -> 1
}
Drawing code:
void Particles::draw(){
size_t count(posData_.size());
glBindBuffer(GL_ARRAY_BUFFER, posVbo_);
glBufferSubData(GL_ARRAY_BUFFER, 0, count * sizeof(float), posData_.data());
glBindBuffer(GL_ARRAY_BUFFER, colorVbo_);
glBufferSubData(GL_ARRAY_BUFFER, 0, count * sizeof(float) * 4, colorData_.data());
glBindVertexArray(vao);
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, count);
}
Notice how you don't need to update your VAO state during the draw() call, only during the initialization.
actually Im a bit confused about using glBufferSubData and glMapBuffer. In my program I'm loading a mesh of Triangles so i created a Struct of Vertex and initialized my VertexBuffer with the data of whole mesh. I implemented ray-casting and ray-triangle intersection. What im trying to do is, if my cursor intersects with the mesh, the intersected triangle changes his color as long its get intersected. Its working at the moment but when I try to load a bigger mesh with 50.000+ Vertices it doesnt work anymore. I am updating my whole VBO with glBufferData because I dont understand how I can update only Color of Triangles with glBufferSubData. Can someone explain me how I can update only the specific part (e.g. Color) of my VBO ?
struct Vertex
{
glm::vec3 Pos;
glm::vec3 Normal;
glm::vec3 Color;
};
VertexBuffer(void* vertices, size_t size)
{
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, size, vertices, GL_DYNAMIC_DRAW);
glBindVertexArray(0);
}
void Render()
{
glBindVertexArray(vertexBuffer->VAO);
glUseProgram(Fill->program);
glUniformMatrix4fv(glGetUniformLocation(Fill->program, "model"), 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(glGetUniformLocation(Fill->program, "view"), 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(glGetUniformLocation(Fill->program, "projection"), 1, GL_FALSE, glm::value_ptr(proj));
for (int j = 0; j < numVertices; j += 3){
if (intersectPlane(this->Vertices[j], this->Vertices[j + 1], this->Vertices[j + 2], ray, orig)){
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer->buffer);
this->Vertices[j].Color = glm::vec3(1.0, 0.0, 0.0);
this->Vertices[j + 1].Color = glm::vec3(1.0, 0.0, 0.0);
this->Vertices[j + 2].Color = glm::vec3(1.0, 0.0, 0.0);
glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(Vertex), Vertices, GL_DYNAMIC_DRAW);
}
else{
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer->buffer);
this->Vertices[j].Color = glm::vec3(0.695f, 0.695f, 0.695f);
this->Vertices[j + 1].Color = glm::vec3(0.695f, 0.695f, 0.695f);
this->Vertices[j + 2].Color = glm::vec3(0.695f, 0.695f, 0.695f);
glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(Vertex), Vertices, GL_DYNAMIC_DRAW);
}
}
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer->buffer);
GLuint posLoc = glGetAttribLocation(Fill->program, "Position");
GLuint norm = glGetAttribLocation(Fill->program, "Normal");
GLuint colo = glGetAttribLocation(Fill->program, "Color");
glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, Pos));
glVertexAttribPointer(norm, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, Normal));
glVertexAttribPointer(colo, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, Color));
glEnableVertexAttribArray(posLoc);
glEnableVertexAttribArray(norm);
glEnableVertexAttribArray(colo);
glDrawArrays(GL_TRIANGLES, 0, numVertices);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glUseProgram(0);
}
glBufferSubData updates part (or the whole) of the buffer without the need to recreate it.
In your case you can do some calculus to know the position in bytes inside the buffer (so called "offset") of the edge currently selected, and update the buffer just for that pair of vertices.
glMapBuffer gives you a (virtual) pointer to the buffer. You can read or write to that address directly using your C/C++ functions. Be aware to "unmap" when done.
Now, your buffer layout is Pos,Normal,Color and repeat. So: PxPyPzNxNyNzCrCgCbPxPyPzNxNyNzCrCgCbPxPyPzNxNyNzCrCgCb... "interleaved data". You must be carefull with the positions (bytes) you update.
I am trying to implement picking via following an opengl tutorial, I have a mesh with 6000 vertices and I wish to pick particular ones; I have chosen to do by redering uniquely coloured boxes at each vertex point, read the pixel on my mouse click at that point and that should return to me the ID of the closest vertex. The background is rendered as white so if I miss I get nothing.
However I have a problem, it only works most of the time; there are certain areas that if I click there I get white returned even though its clearly a vertex, and when rendering the colorized scene clearly has a redish box at the point I clicked.
Then there are white areas near the mesh, to the bottom left and at some random point away from it, returns me a hit.
I do not understand at all why this is happening, it should work.
void Display() {
Controls->setVector(indexed_vertices);
if (Controls->getPicking()) {
// Clear the screen in white
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
for ( int i=0; i< indexed_vertices.size(); i++) {
// use shaders
glUseProgram(pickingProgramID);
// Get a handle for our "MVP" uniform
GLuint PickingMatrixID = glGetUniformLocation(pickingProgramID, "MVP");
glm::mat4 RotationMatrix = glm::toMat4(orientations);
glm::mat4 btTranslationMatrix = glm::translate(glm::mat4(1.0f), indexed_vertices[i]);
glm::mat4 myModelMatrix = ModelMatrix * Controls->getTranslationMatrix() * Controls->getRotationMatrix() * btTranslationMatrix;
MVP = ProjectionMatrix * ViewMatrix * myModelMatrix;
Controls->setCntrlsViewMatrix(ViewMatrix);
Controls->setCntrlsProjectionMatrix(ProjectionMatrix);
glUniformMatrix4fv(PickingMatrixID, 1, GL_FALSE, &MVP[0][0]);
// Convert "i", the integer mesh ID, into an RGB color
int r = (i & 0x000000FF) >> 0;
int g = (i & 0x0000FF00) >> 8;
int b = (i & 0x00FF0000) >> 16;
// OpenGL expects colors to be in [0,1], so divide by 255.
glUniform4f(pickingColorID, r/255.0f, g/255.0f, b/255.0f, 1.0f);
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, gvertexbuffer);
glVertexAttribPointer(
0, // attribute. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// Index buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
// Draw the triangles !
glDrawElements(
GL_TRIANGLES, // mode
indices.size(), // count
GL_UNSIGNED_SHORT, // type
(void*)0 // element array buffer offset
);
// OpenGL expects colors to be in [0,1], so divide by 255.
}
glDisableVertexAttribArray(0);
glFlush();
glFinish();
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// Read the pixel at the center of the screen.
// You can also use glfwGetMousePos().
// Ultra-mega-over slow too, even for 1 pixel,
// because the framebuffer is on the GPU.
unsigned char data[4];
glReadPixels(Controls->get_mx_cur(), Controls->get_my_cur(),1,1, GL_RGBA, GL_UNSIGNED_BYTE, data);
std::cout << "MX: " << Controls->get_mx_cur() << " MY: " << Controls->get_my_cur() << std::endl;
// Convert the color back to an integer ID
int pickedID =
data[0] +
data[1] * 256 +
data[2] * 256*256;
//std::cout << std::hex << pickedID << std::dec<<std::endl;
if (pickedID == 0x00ffffff) { // Full white, must be the background !
printf("Miss\n");
}
else {
std::cout << "mesh " << pickedID << std::endl;
}
// Uncomment these lines to see the picking shader in effect
glutSwapBuffers();
skip = true;
Controls->setPicking(false);
}
if (!skip) {
// White background
glClearColor(0.2f, 0.25f, 0.5f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
//glEnable(GL_CULL_FACE);
glUseProgram(ShaderIDs[0]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, Texture);
glUniform1i(TextureID, 0);
glm::mat4 myModelMatrix = ModelMatrix * Controls->getTranslationMatrix() * Controls->getRotationMatrix();
MVP = ProjectionMatrix * ViewMatrix * myModelMatrix;
// The inverse transpose of the View Model Matrix will re-normalize the normals if there's
// been any scaling. Otherwise you don't need it.
glm::mat3 NormalMatrix = glm::mat3( glm::transpose(glm::inverse(ViewMatrix * myModelMatrix)));
Controls->setCntrlsViewMatrix(ViewMatrix);
Controls->setCntrlsProjectionMatrix(ProjectionMatrix);
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
glUniformMatrix4fv(ViewMatrixID, 1, GL_FALSE, &ViewMatrix[0][0]);
glUniformMatrix4fv(ModelMatrixID, 1, GL_FALSE, &myModelMatrix[0][0]);
// Notice we're passing a 3 by 3 matrix here.
glUniformMatrix3fv(NormalMatrixID, 1, GL_FALSE, &NormalMatrix[0][0]);
glUniform3f(CameraID, cameraLoc.x, cameraLoc.y, cameraLoc.z);
glUniform3f(LightPosID, lightPosition.x, lightPosition.y, lightPosition.z);
// VBO buffer: vertices
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// 2nd attribute buffer : UVs
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glVertexAttribPointer(
1, // attribute
2, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// 2rd attribute buffer : normals
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
glVertexAttribPointer(
2, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// Index buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
if ( Controls->getRenderingMode() == 0 ) {
glDisable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
//glDisable(GL_POLYGON_OFFSET_FILL);
}
else if (Controls->getRenderingMode() == 1 ) {
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glDisable(GL_CULL_FACE);
//glDisable(GL_POLYGON_OFFSET_FILL);
glUseProgram(ShaderIDs[1]);
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
glUniformMatrix4fv(ViewMatrixID, 1, GL_FALSE, &ViewMatrix[0][0]);
glUniformMatrix4fv(ModelMatrixID, 1, GL_FALSE, &myModelMatrix[0][0]);
// Notice we're passing a 3 by 3 matrix here.
glUniformMatrix3fv(NormalMatrixID, 1, GL_FALSE, &NormalMatrix[0][0]);
glUniform3f(CameraID, cameraLoc.x, cameraLoc.y, cameraLoc.z);
glUniform3f(LightPosID, lightPosition.x, lightPosition.y, lightPosition.z);
}
else if (Controls->getRenderingMode() == 2 ) {
glUseProgram(ShaderIDs[1]);
//
glm::mat4 MyOffsetMatrix = glm::scale(glm::mat4(1.0f), glm::vec3(1.025,1.025,1.025));
MyOffsetMatrix = glm::mat4(1.0f);
glm::mat4 myModelMatrix2 = ModelMatrix * Controls->getTranslationMatrix() *
Controls->getRotationMatrix()*MyOffsetMatrix;
glm::mat3 NormalMatrix2 = glm::mat3( glm::transpose(glm::inverse(ViewMatrix *
myModelMatrix2)));
glm::mat4 MVP2 = ProjectionMatrix * ViewMatrix * myModelMatrix2;
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP2[0][0]);
glUniformMatrix4fv(ViewMatrixID, 1, GL_FALSE, &ViewMatrix[0][0]);
glUniformMatrix4fv(ModelMatrixID, 1, GL_FALSE, &myModelMatrix2[0][0]);
// Notice we're passing a 3 by 3 matrix here.
glUniformMatrix3fv(NormalMatrixID, 1, GL_FALSE, &NormalMatrix2[0][0]);
glUniform3f(CameraID, cameraLoc.x, cameraLoc.y, cameraLoc.z);
glUniform3f(LightPosID, lightPosition.x, lightPosition.y, lightPosition.z);
// The rest is exactly the same as the first object
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
// 2nd attribute buffer : UVs
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
// 3rd attribute buffer : normals
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
// Index buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glDisable(GL_CULL_FACE);
glEnable(GL_POLYGON_OFFSET_FILL);
// Draw the triangles !
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_SHORT, (void*)0);
glEnable(GL_POLYGON_OFFSET_FILL);
glDisable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glPolygonOffset(2.0f, 2.0f);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
//glDisable(GL_POLYGON_OFFSET_FILL);
glUseProgram(ShaderIDs[0]);
}
//glUseProgram(ShaderIDs[1]);
// Draw the triangles !
glDrawElements(
GL_TRIANGLES, // mode
indices.size(), // count
GL_UNSIGNED_SHORT, // type
(void*)0 // element array buffer offset
);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
glutSwapBuffers();
}
}
The problem was two-fold: Crazy numbers returned is a result of improper multisampling enabled when I wanted specific colour values (how to have my cake and eat it might need a bit of work but right now I don't care), and secondly because glReadPixels() inverts the Y axis and needed to do Height - Current_Mouse_Position for the Y value.
Perhaps glPoints would be faster means of doing what I'm doing, I'll need to look into it.
I have changed 3 GLFloat arrays (aka GLfloat[]) into vectors (aka vector) and my triangles stopped working! Here is my init function:
void initialize(GLuint &vao) {
// Use a Vertex Array Object
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
Projection = perspective(45.0f, 16.0f / 9.0f, 0.1f, 100.0f);
//ortho(-4.0f/3.0f, 4.0f/3.0f, -1.0f, 1.0f, -1.0f, 1.0f);
Model = translate(Model, vec3(0.f, 0.f, 0.f));
Model = rotate(Model, 45.0f, vec3(0.0f, 0.0f, 1.0f));
//pos + textures array
GLuint vboId;
glGenBuffers(1, &vboId);
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, (vertices_position.size() + texture_coord.size() ) * sizeof(GLfloat), NULL, GL_DYNAMIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, vertices_position.size() * sizeof(GLfloat), &vertices_position[0]);
glBufferSubData(GL_ARRAY_BUFFER, vertices_position.size() * sizeof(GLfloat), texture_coord.size() * sizeof(GLfloat), &texture_coord[0]);
//Indices
GLuint eabId;
glGenBuffers(1, &eabId);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, eabId);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLfloat), &indices[0], GL_DYNAMIC_DRAW);
//Textures
GLuint textureId;
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
load_image("../squirrel.jpg");
shaderProgram = create_program("../shaders/vert.shader", "../shaders/frag.shader");
//Position attribute
positionAttrId = glGetAttribLocation(shaderProgram, "position");
glVertexAttribPointer(positionAttrId, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(positionAttrId);
//Texture attribute
textureCoordId = glGetAttribLocation(shaderProgram, "texture_coord");
glVertexAttribPointer(textureCoordId, 2, GL_FLOAT, GL_FALSE, 0, (GLvoid *)(vertices_position.size() * sizeof(GLfloat)));
glEnableVertexAttribArray(textureCoordId);
modelId = glGetUniformLocation(shaderProgram, "Model");
cameraId = glGetUniformLocation(shaderProgram, "Camera");
}
And below is my render function:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shaderProgram);
glUniformMatrix4fv(modelId, 1, GL_FALSE, glm::value_ptr(Model));
glUniformMatrix4fv(cameraId, 1, GL_FALSE, glm::value_ptr(cam.matrix()));
//VAO
glBindVertexArray(vao);
//glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glUseProgram(0);
You are using floating-point elements in your Index Buffer Object, that is not a valid data type.
OpenGL requires either GLubyte (not hardware accelerated on most desktop GPUs), GLushort or GLuint indices.
For best performance, you should use an array of GLushort and pass GL_UNSIGNED_SHORT as the element type in your call to glDrawElements (...).