Attempting to pass a VBO vertex and color-data from a std::vector<float4> where the float4 is similar to a CUDA float4 (object with x,y,z,w).
int createVertexArrayObject(std::vector<float4> vertex_buffer_data,
std::vector<unsigned int> index_buffer_data,
std::vector<float4> color_buffer_data){
float* vertex_data = reinterpret_cast<float*>(&vertex_buffer_data[0]);
unsigned int vertexArrayID;
glGenVertexArrays(1, &vertexArrayID);
glBindVertexArray(vertexArrayID);
unsigned int vertexBufferID;
glGenBuffers(1, &vertexBufferID);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID);
glBufferData(
GL_ARRAY_BUFFER,
vertex_buffer_data.size()*sizeof(float4),
vertex_data,
GL_STATIC_DRAW
);
(...)
}
This is what I am working with in terms of passing the data to the VBO. However, nothing renders.
Am I calculating the size correctly, and am I providing the correct reference to the first element in the structure?
Related
I'm learning OpenGL and ran into an "obstacle".
I drew some houses (blocks and pyramids) using an indexbuffer.
This works fine when loading all the vertices (from all houses) into the vertexbuffer and using 1 big indexbuffer. Now I want to animate the objects and load them in the vertexbuffer one by one so I can execute transformation on the objects one by one. The code is not much different from one big buffer, but when I do this I just see some random shapes shooting around on the screen. My code is as follows:
I have a world class which holds the list of 3D objects, has one big list of all vertices (for trial purposes), one big list of indices (also trial) and a method to add an Object3D object to the world.
class World
{
public:
World();
~World();
vector<Object3D> objects;
vector<glm::vec3> Vertices;
vector<GLushort> Indices;
void AddObject(Object3D &object);
};
Object3D class:
class Object3D
{
public:
Object3D();
~Object3D();
glm::vec3 Position;
vector<glm::vec3> Vertices;
vector<unsigned int> Indices;
};
World AddObject method, simply adds the object to the "objects" list and adds the vertices and indices to the "Vertices" and "Indices" lists to create one big buffer:
void World::AddObject(Object3D &object) {
int oldVerticesSize = Vertices.size();
objects.push_back(object);
Vertices.insert(Vertices.end(), object.Vertices.begin(), object.Vertices.end());
for each (GLushort index in object.Indices)
{
Indices.push_back(index + oldVerticesSize);
}
}
When I render the big buffer with all the vertices and indices (as shown below) it works fine.
void WorldRenderer::Render()
{
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArray(Vao); //use vao
glDrawElements(GL_TRIANGLES, World.Indices.size(), GL_UNSIGNED_SHORT, 0);
//glDrawArrays(GL_TRIANGLES, 0, World.Vertices.size());
glBindVertexArray(0); //release vao
//Model = glm::rotate(Model, 0.01f, glm::vec3(0.0f, 1.0f, 0.0f));
Mvp = Projection * View * Model;
glUniformMatrix4fv(UniformMvp, 1, GL_FALSE, glm::value_ptr(Mvp));
glutSwapBuffers();
//glutPostRedisplay();
}
When I loop through the objects and load the vertices of the objects in the buffer one-object-at-a-time (as shown below) it shows some random "shapes" which keep "shooting around" or rapidly changing. What am I doing wrong here?
Thanks in advance for any advice.
void WorldRenderer::Render()
{
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
int index = 0;
for each (Object3D mesh in World.objects)
{
Mvp = Projection * View * Model;
UpdateBuffer(mesh.Vertices, mesh.Indices);
glBindVertexArray(Vao); //use vao
glDrawElements(GL_TRIANGLES, mesh.Indices.size() , GL_UNSIGNED_SHORT, 0);
glBindVertexArray(0); //release vao
glUniformMatrix4fv(UniformMvp, 1, GL_FALSE, glm::value_ptr(Mvp));
index++;
}
glutSwapBuffers();
}
UpdateBuffers method:
void WorldRenderer::UpdateBuffer(vector<glm::vec3> vertices, vector<unsigned int> indices) {
//fill Vbo
glBindBuffer(GL_ARRAY_BUFFER, Vbo);
glBufferData(GL_ARRAY_BUFFER, vertices.size(), vertices.data(), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
//fill ibo
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, Ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), indices.data(), GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(Vao);
glBindBuffer(GL_ARRAY_BUFFER, Vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, Ibo);
}
For the first Render method (without the loop) the buffers are created once in the init method which looks like this:
void WorldRenderer::Init(int argc, char ** argv) {
InitGlutGlew(argc, argv);
InitMatrices();
glDisable(GL_CULL_FACE);
//-------------- init buffers --------------
// vbo vertices
glGenBuffers(1, &Vbo);
glBindBuffer(GL_ARRAY_BUFFER, Vbo);
glBufferData(GL_ARRAY_BUFFER, World.Vertices.size() * sizeof(glm::vec3),
&World.Vertices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
//ibo
glGenBuffers(1, &Ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, Ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, World.Indices.size() * sizeof(unsigned int),
&World.Indices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
// VAO setup
glGenVertexArrays(1, &Vao);
glBindVertexArray(Vao);
// Bind vertices to vao
glBindBuffer(GL_ARRAY_BUFFER, Vbo);
//Bind elements
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, Ibo);
//------ init shaders -----------
InitShader();
}
As soon as I see your UpdateBuffer function, I feel that the glBufferData for vbo is not loaded properly.
The second parameter vertices.size() returns just number of elements in vector but not the actual size of object.
So the second parameter should be vertices.size() * sizeof(glm::vec3)
And the third parameter is ok as it returns pointer to the underlying array. If not working ....directly pass the address of first element as shown below.
Overall it should be something like as shown below.
glBufferData(
GL_ARRAY_BUFFER,
vertices.size() * sizeof(glm::vec3),
&vertices[0],
GL_STATIC_DRAW
);
Check if it works.
Why you are seeing differences?
First render:
Your buffer contain all the world's data for vertices continuosly, when the glDrawElements is called.
So here the mesh1 last vertex is continued with mesh 2 fist vertex.... So you see a kind of closed shape.
Second render:
your buffer contains only one mesh data at a time, when the glDrawElements is called.
so your shape ends for each mesh after calling glDrawElements.
To obtain the same result as first render, you have to first update a single vertex buffer for all meshes ( use glBufferSubData).
Then call glDrawElements once. Then you will see same result.
I want to create multiple vertex buffers in objects (one by object). the constructor is:
VertexBuffer::VertexBuffer(const GLvoid *data,
GLsizeiptr size,
GLenum mode,
GLsizei count,
GLsizei stride,
ShaderInterface *shaderInterface,
GLvoid *positionOffset,
GLvoid *normalOffset)
: _mode(mode),
_count(count),
_stride(stride),
_shaderInterface(shaderInterface),
_positionOffset(positionOffset),
_normalOffset(normalOffset)
{
glGenBuffers(1, &_vertexBufferID);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferID);
glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);
//
GLuint vao = 0;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glEnableVertexAttribArray(0); //??????
glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferID);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
//
}
If I create 1 object VertexBuffer, this works ok. But if I create another object (I won't use it) and I draw the first object again the result is not correct (for example, the object showed is in other place). Why?
You don't seem to store the vao anywhere, but you should. Before drawing each object you shall glBindVertexArray its vao (but not _vertexBufferID) before you call any of glDraw*.
See also this answer to see what state VAOs contain.
I'm not very experience with the OpenGL library so I'm having trouble understanding why when I move some initialization code to a class or a function, GL stops drawing onto the screen. Some research indicates that the library is "global" or state-based rather than object based?
Anyway, here is some code that works
GLuint vertexArrayBuffer;
glGenVertexArrays(1, &vertexArrayBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexArrayBuffer);
// VBO is ready to accept vertex data
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindVertexArray(0);
while(!screen.isClosed()) {
// Give the screen a background color
screen.paint(0.0f, 0.0f, 0.5f, 1.0f);
glBindBuffer(GL_ARRAY_BUFFER, vertexArrayBuffer);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);
// Switch to display buffer after drawing all of the above
screen.swapBuffers();
This is all enclosed in the main function, with not much programming structure. The output is a nice white triangle onto a blueish background.
This is the issue here, taking the exact code prior to the event loop and wrapping it into a function:
GLuint initVertexArray(vertex vertices[]) {
// Create file descriptor for the VBO for use as reference to gl vertex functions
GLuint vertexArrayBuffer;
glGenVertexArrays(1, &vertexArrayBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexArrayBuffer);
// VBO is ready to accept vertex data
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindVertexArray(0);
return vertexArrayBuffer;
}
and calling it GLuint vertexArrayBuffer = initVertexArray(vertices); in the main function, produces no output of any kind, no errors either, just the same blueish background.
Have you checked what sizeof(vertices) is returning. In this case vertices[] will decay into a pointer so I would imagine that sizeof(vertices) is sizeof(vertex*).
Try passing the size of the array alongside it like so:
GLuint initVertexArray(vertex vertices[], const unsigned int size);
Then you would use it like so:
glBufferData(GL_ARRAY_BUFFER, size, vertices, GL_STATIC_DRAW);
instead of:
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
You would then call it in the same scope as you declared your vertices array:
vertex vertices[100];
// sizeof(vertices) here will give the actual size of the vertices array
// eg: sizeof(vertex) * 100 instead of just giving sizeof(vertex*)
GLuint vertexArrayBuffer = initVertexArray(vertices, sizeof(vertices));
I'm having trouble using vertex buffer objects without using a vertex array object.
My understanding was that VAOs are just encapsulating the state around VBOs. But shouldn't the VBOs be usable without a VAO?
Here's a mini-example. With use_vao=true this works correctly (renders orange rect). With use_vao=false this renders nothing and generates a GL_INVALID_OPERATION error upon glDrawElements.
// make sure the modern opengl headers are included before any others
#include <OpenGL/gl3.h>
#define __gl_h_
#include <GLUT/glut.h>
#include <string>
#include <cassert>
// For rendering a full-viewport quad, set tex-coord from position
std::string tex_v_shader = R"(
#version 330 core
in vec3 position;
void main()
{
gl_Position = vec4(position,1.);
}
)";
// Render directly from color or depth texture
std::string tex_f_shader = R"(
#version 330 core
out vec4 color;
void main()
{
color = vec4(0.8,0.4,0.0,0.75);
}
)";
// shader id, vertex array object
GLuint tex_p_id;
int w=1440,h=480;
const GLfloat V[] = {-0.5,-0.5,0,0.5,-0.5,0,0.5,0.5,0,-0.5,0.5,0};
const GLuint F[] ={0,1,2, 0,2,3};
int main(int argc, char * argv[])
{
// Init glut and create window + OpenGL context
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_3_2_CORE_PROFILE|GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH);
glutInitWindowSize(w,h);
glutCreateWindow("test");
// Compile shaders
const auto & compile = [](const char * src,const GLenum type)->GLuint
{
GLuint s = glCreateShader(type);
glShaderSource(s, 1, &src, NULL);
glCompileShader(s);
return s;
};
tex_p_id = glCreateProgram();
glAttachShader(tex_p_id,compile(tex_v_shader.c_str(), GL_VERTEX_SHADER));
glAttachShader(tex_p_id,compile(tex_f_shader.c_str(), GL_FRAGMENT_SHADER));
glLinkProgram(tex_p_id);
glutDisplayFunc(
[]()
{
glViewport(0,0,w,h);
glUseProgram(tex_p_id);
glClearColor(0.0,0.4,0.7,0.);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
const bool use_vao = true;
GLuint VAO;
if(use_vao)
{
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
}
GLuint VBO, EBO;
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(V), V, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(F), F, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
if(use_vao)
{
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
assert(glGetError() == GL_NO_ERROR);
glDrawElements(GL_TRIANGLES,sizeof(F)/sizeof(GLuint),GL_UNSIGNED_INT, 0);
assert(glGetError() == GL_NO_ERROR);
glutSwapBuffers();
}
);
glutReshapeFunc( [](int w,int h){::h=h, ::w=w;});
glutMainLoop();
}
On my machine glGetString(GL_VERSION) produces 4.1 INTEL-10.6.20.
Using VAOs is required in the core profile. From the OpenGL 3.3 spec, page 342, in the section E.2.2 "Removed Features":
The default vertex array object (the name zero) is also deprecated.
This means that you can't set up vertex attributes without creating and binding your own VAO.
No with a core 3.3+ profile you need a VAO to render.
You can however just create and bind a VAO and forget about it (keep it bound).
Besides that glEnableVertexAttribArray(0); must still be called even when using compatibility profile and not using a VAO.
A few other remarks is that you regenerate all buffers and VAOs every frame but don't clean it up. You should do that once during initialization and then rebind when drawing:
if(!use_vao){
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
}
else
{
glBindVertexArray(VAO);
}
I am having trouble getting Eigen::Vector3f and Opengl ES 2.0 VBO to work together.
My initial attempt was glVertexAttribPointer(VERTEX, 3, GL_FLOAT , sizeof(Vertex), 0 ).
While this draws nothing if I start to play with the stride values I can see a broken mesh.
This is my current code which leads to crash. In my old code I was using simple vector3 class made from 3 floats which was working fine.
struct Vertex {
Eigen::Vector3f pos ;
Eigen::Vector3f normal;
};
std::vector<Vertex> Vertices;
std::vector<ushort16> Indices;
...
GLuint vao;
uint32 vboID, vboID2;
glGenVertexArraysOES(1, &vao);
glBindVertexArrayOES(vao);
glGenBuffers(1, &vboID);
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glBufferData(GL_ARRAY_BUFFER, GL_STATIC_DRAW , sizeof(Vertex) * Vertices.size(), &Vertices[0]);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGenBuffers(1, &vboID2);
glBindBuffer(GL_ARRAY_BUFFER, vboID2);
glBufferData(GL_ARRAY_BUFFER, GL_STATIC_DRAW , sizeof(ushort16) * m_vIndices.size(), &Indices[0]);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glEnableVertexAttribArray(VERTEX);
glVertexAttribPointer(VERTEX, 3, GL_FLOAT , sizeof(Vertex), &Vertices[0].pos );
glEnableVertexAttribArray(NORMAL);
glVertexAttribPointer(NORMAL, 3, GL_FLOAT , sizeof(Vertex), &Vertices[0].normal );
glBindBuffer(GL_ARRAY_BUFFER, vboID2);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArrayOES(0);
...
that solved my problem:
I removed the:
glBufferData(GL_ARRAY_BUFFER, GL_STATIC_DRAW , sizeof(Vertex) * Vertices.size(), &Vertices[0]);
And I changed these lines to
glVertexAttribPointer(VERTEX, 3, GL_FLOAT , sizeof(Vertex), Vertices[0].pos.data() );
....
glVertexAttribPointer(NORMAL, 3, GL_FLOAT , sizeof(Vertex), Vertices[0].normal.data() );