I'm creating an OpenGL project which includes ParticleFactory class to generate particles in a scene.
To achieve that I have created a class:
#ifndef PARTICLE_H
#define PARTICLE_H
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <iostream>
#include <vector>
#include "vertex.h"
#include <shader_s.h>
class ParticleFactory {
public:
Shader* shader;
std::vector<Particle> particles;
unsigned int VAO, VBO, EBO;
unsigned int nr_particles;
ParticleFactory(unsigned int nr_particles, unsigned int color){
Shader sh("shaders/particle.vs", "shaders/particle.fs");
shader = &sh;
this->nr_particles = nr_particles;
for(unsigned int i = 0; i < nr_particles; i++) {
float x = (rand()%200)/100.0 - 1;
float y = (rand()%200)/100.0 - 1;
float z = (rand()%200)/100.0 - 1;
particles.push_back(Particle(glm::vec4(x, y, z, 0.0)));
}
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(base_particle), base_particle, GL_STREAM_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(base_particle_indices), base_particle_indices, GL_STREAM_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glEnableVertexAttribArray(0);
}
void draw() {
shader->use();
shader->setMat4("model", model);
shader->setMat4("view", view);
shader->setMat4("projection", projection);
shader->setMat4("transform", transform);
for (int i=0; i<nr_particles; i++) {
shader->setVec4("offset", particles[i].offset);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 24, GL_UNSIGNED_INT, 0);
particles[i].offset += glm::vec4(0.0f, -0.001f, 0.0f, 0.0f);
if (particles[i].offset.y <= -1.0f) {
particles[i].offset.y = 1.0f;
}
}
}
};
#endif
My approach here is to first instantiate an object and then call .draw() on the main loop but it doesn't seems to work and I don't know why.
Before we even get to the OpenGL part, you're creating a LOCAL object (sh) and then assigning the address of that to the shader member. At the end of the constructor, sh will be deleted, and thus the shader member will be pointing to … ? First, you'll need to use new/delete (or better yet, use std::unique_ptr< Shader >) to make sure that object is still around when you want to use it.
Try that FIRST!
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I'm pretty new to C++ so I hope I can get some help here.
I try to port my Game Engine to C++ but C++ behaves a litle bit... "Strange".
Following Situation:
if I run test1() It all works as it should.
main.cpp
#include <iostream>
#include "../headers/base.h"
#include "../headers/DemoGame.h"
#include "../headers/TestShader.h"
using namespace std;
using namespace engine;
void run(TestShader* t, GLuint VAO, GLFWwindow* w)
{
glfwPollEvents();
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(t->progID);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
glfwSwapBuffers(w);
}
void test1()
{
Window w = Window(800, 600, "test");
TestShader t = TestShader();
GLuint VAO, VBO;
GLfloat vertices[9] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
while (!glfwWindowShouldClose(w.getWindow()))
{
run(&t, VAO, w.getWindow());
}
}
void test2()
{
DemoGame game = DemoGame();
game.start();
}
int main()
{
test1();
return 0;
}
If i'm running test2() with following involved classes:
Engine.h
#pragma once
#ifndef H_ENGINE
#define H_ENGINE
#include "base.h"
namespace engine
{
class Engine
{
private:
bool running;
public:
void start()
{
init();
process();
}
void stop()
{
this->running = false;
}
private:
void process()
{
update();
}
public:
virtual void init() = 0;
virtual void update() = 0;
virtual void render() = 0;
virtual void terminate() = 0;
};
}
#endif
DemoGame.h
#pragma once
#ifndef DEMO_DEMO_GAME
#define DEMO_DEMO_GAME
#include "base.h"
#include "Window.h"
#include "Engine.h"
#include "TestShader.h"
using namespace engine;
class DemoGame : public Engine
{
public:
Window* w;
TestShader* t;
GLuint VBO, VAO;
public:
DemoGame() : Engine() { }
public:
void init();
void update();
void render();
void terminate();
};
#endif
DemoGame.cpp
#include "../headers/DemoGame.h"
#include <iostream>
using namespace std;
void DemoGame::init()
{
cout << "ping" << endl;
Window wi = Window(800, 600, "test");
w = &wi;
TestShader te = TestShader();
t = &te;
GLfloat vertices[9] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
while (!glfwWindowShouldClose(w->getWindow()))
{
render();
}
}
void DemoGame::update()
{
}
void DemoGame::render()
{
glfwPollEvents();
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(t->progID);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
glfwSwapBuffers(w->getWindow());
}
void DemoGame::terminate()
{
}
It works aswell. But as you may see Engine.h is supposed to control the mainloop. If I change the code a little bit:
Engine.h
#pragma once
#ifndef H_ENGINE
#define H_ENGINE
#include "base.h"
namespace engine
{
class Engine
{
private:
bool running;
public:
void start()
{
init();
running = true;
while (running)
{
process();
}
}
void stop()
{
this->running = false;
}
private:
void process()
{
update();
}
public:
virtual void init() = 0;
virtual void update() = 0;
virtual void render() = 0;
virtual void terminate() = 0;
};
}
#endif
DemoGame.cpp
#include "../headers/DemoGame.h"
#include <iostream>
using namespace std;
void DemoGame::init()
{
cout << "ping" << endl;
Window wi = Window(800, 600, "test");
w = &wi;
TestShader te = TestShader();
t = &te;
GLfloat vertices[9] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void DemoGame::update()
{
render();
}
void DemoGame::render()
{
glfwPollEvents();
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(t->progID);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
glfwSwapBuffers(w->getWindow());
}
void DemoGame::terminate()
{
}
Now all of a sudden I get an "Access Violation". The question is why?
The file "base.h" just contains
#define GLEW_STATIC
#include "GL/glew.h"
#include "GLFW/glfw3.h"
and the classes Window and TestShader shouldn't matter because they work in the first two examples. As I stated before I'm pretty new to C++ and I just don't understand why that doesn't work. Can you please help me finding out at least why that doesn't work or better help me solving the problem.
This is my second attempt to get a useful answer from StackOverflow by posting a question. Please do me a favour. Please consider read the situation before you mark this question an duplicate. The last time it wasn't an duplicate the problem was by far different.
Edit
As requested the Error message(sry I'm at work so the language is german)
Ausnahme ausgelöst bei 0x0126489D in GLFWGame.exe: 0xC0000005:
Zugriffsverletzung beim Lesen an Position 0xCCCCCEA4.
Falls ein Handler für diese Ausnahme vorhanden ist, kann das Programm
möglicherweise weiterhin sicher ausgeführt werden.
And I'll try to shorten the code to the most important.
You store addresses of stack objects that get deleted. For example,
Window wi = Window(800, 600, "test");
w = &wi;
Creates a local variable wi on the stack, which gets deleted automatically when it goes out of scope (which is the case at the end of the function). After that, w will point to an address that is already freed, which will lead to big troubles when you try to access this variables later on as you do here:
glfwSwapBuffers(w->getWindow());
If you want to create the window object on the heap, you have to use the following code in DemoGame::init():
w = new Window(800, 600, "test");
Don't forget to delete this object manually by calling delete w when you don't need it anymore. The same problem also occures for the TestShader instance.
Side note: Window wi = Window(800, 600, "test"); is still a strange syntax when creating objects on the stack. The correct way would be Window wi(800, 600, "test"); Have a look at this posts for why this makes a difference: Calling constructors in c++ without new
Edit: Your first example just works because you are calling the render function inside the init function, thus the objects do not get out of scope. Storing pointers to local object is still not good practice.
Your problem is here:
Window wi = Window(800, 600, "test");
w = &wi;
TestShader te = TestShader();
t = &te;
Both, the instance of Window as well as the instance of TestShader are local variables that will get cleaned up as soon as they go out of scope (end of init) and hence remembering their addresses has no meaning. You will need to create those instances dynamically (new) or set them up within your class definition.
Currently I am trying to draw a triangle via a mesh class. I do this by first initializing the glew and the calling the Window.initializeGraphics method of my Window class, then creatubg an array of verticies and passing to my Mesh.addVerticies method. Each vertex has 3 floats, x, y, and z. Then I call the Mesh.draw method every tick of the main game loop.
initializeGraphics Method:
void Window::initializeGraphics()
{
glClearColor(0, 0, 0, 0);
glFrontFace(GL_CW);
glCullFace(GL_BACK);
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glEnable(GL_FRAMEBUFFER_SRGB);
}
Creating the Mesh:
m_Mesh = Mesh();
Vertex data[] = { Vertex(vec3(-1, -1, 0)),
Vertex(vec3(1, -1, 0)),
Vertex(vec3(0, 1, 0)) };
m_Mesh.addVerticies(data);
Mesh Header:
#include "vertex.h"
#include <GLEW\glew>
class Mesh
{
private:
GLuint m_Vbo;
int m_Size;
public:
Mesh();
void addVerticies(Vertex verticies[]);
void draw();
};
Mesh C++ File:
#include "mesh.h"
Mesh::Mesh()
{
glGenBuffers(1, &m_Vbo);
}
void Mesh::addVerticies(Vertex verticies[])
{
m_Size = (sizeof(verticies) / sizeof(*verticies));
glBindBuffer(GL_ARRAY_BUFFER, m_Vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(verticies), verticies, GL_STATIC_DRAW);
}
void Mesh::draw()
{
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, m_Vbo);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * 4, 0);
glDrawArrays(GL_TRIANGLES, 0, m_Size);
glDisableVertexAttribArray(0);
}
Vertex Header:
#include "vec3.h"
struct Vertex
{
union
{
vec3 pos;
struct
{
float x, y, z;
};
};
Vertex(vec3 pos_);
};
Vertex C++ File:
#Include "vertex.h"
Vertex::Vertex(vec3 pos_)
{
pos = pos_;
}
Render Method:
void MainComponent::render()
{
m_Window.clear();
m_Mesh.draw();
m_Window.update();
}
//m_Window.update();
void Window::update()
{
glfwSwapBuffers(m_GLFWWindow);
glfwPollEvents();
}
//m_Window.clear();
void Window::clear()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
Problem is, no triangle appears on screen. What am I doing wrong ? I am pretty much still a C++ newling, and this is my first time programming OpenGl so it could be something really really basic that I keep overlooking.
Thanks in advance for your efforts.
-Sean
Woah, hold on there! There are other bona fide errors here.
void Mesh::addVerticies(Vertex verticies[])
{
// This gives the wrong answer!
m_Size = (sizeof(verticies) / sizeof(*verticies));
That calculation for m_Size is completely wrong. This is because verticies is a pointer not an array. It looks like an array, it was declared as Vertex verticies[], but due to a quirk of C++ (the same applies to C) the parameter decays into a pointer. So it ends up being the same as this:
void Mesh::addVerticies(Vertex *verticies)
As you can see, sizeof(verticies) is always going to be 8 on a typical 64-bit system, because you are just getting the size of a pointer, not the size of an array.
We can fix this by capturing the size of the array with a template:
template <std::size_t N>
void addVertices(Vertex (&vertices)[N]) {
addVertices(vertices, N);
}
void addVertices(Vertex *vertices, std::size_t count) {
m_Size = count;
glBindBuffer(GL_ARRAY_BUFFER, m_Vbo);
glBufferData(
GL_ARRAY_BUFFER,
sizeof(*vertices) * count,
vertices,
GL_STATIC_DRAW);
}
Because we use a reference to the array, Vertex (&vertices)[N], instead of the array directly, Vertex vertices[N], the parameter does not decay into a pointer.
I feel like a complete moron... One verticie was off the screen. I think I'll call it a day :/
I'm learning openGL and I'm trying to do something very simple. I have a graphics object called Model which contains a vector of GLfloats for vertices and has a draw function. In addition to this, I have an addVertex function which takes in 3 floats and a draw function which binds the object's VAO and then unbinds it after drawing. I have no problem rendering one of these objects and adding points to it, however I can't draw more than one of these at the same time without the program crashing and visual studio's telling me "Frame not in module" which isn't helpful. Also, only the last Model object I create can be rendered, any object that comes before it will crash the program.
Here's the Model object's code:
#include "Model.h"
#include <iostream>
#include <string>
Model::Model() {
drawMode = 0;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, NULL, NULL, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, NULL, NULL, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
}
Model::~Model() {
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &EBO);
}
void Model::addVertex(GLfloat x, GLfloat y, GLfloat z) {
vertices.push_back(x);
vertices.push_back(y);
vertices.push_back(z);
update();
}
void Model::addIndex(int i, int j, int k) {
indices.push_back(i);
indices.push_back(j);
indices.push_back(k);
}
void Model::setShader(GLuint& shader) {
shaderProgram = &shader;
}
void Model::clearModel() {
vertices.clear();
indices.clear();
}
int Model::sizeOfVertices() {
return sizeof(GLfloat)*vertices.size();
}
int Model::sizeOfIndices() {
return sizeof(GLuint)*(indices.size());
}
void Model::draw() {
glUseProgram(*shaderProgram);
GLuint transformLoc = glGetUniformLocation(*shaderProgram, "model");
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(model));
glBindVertexArray(VAO);
switch (drawMode) {
case 0: glDrawArrays(GL_POINTS, 0, vertices.size() / 3);
break;
case 1: glDrawArrays(GL_LINE_STRIP, 0, vertices.size() / 3);
break;
case 2: glDrawArrays(GL_TRIANGLES, 0, vertices.size() / 3);
break;
case 3: glDrawArrays(GL_TRIANGLE_STRIP, 0, vertices.size() / 3);
break;
default: break;
}
glBindVertexArray(0);
}
void Model::setDrawMode(int type) {
drawMode = type;
}
void Model::move(glm::vec3 translation) {
model = glm::translate(model, translation);
}
void Model::rotate(float degrees,glm::vec3 axis) {
model = glm::rotate(model, degrees,axis);
}
void Model::update() {
glBindVertexArray(0);
glBindVertexArray(VAO);
glBufferData(GL_ARRAY_BUFFER, NULL, NULL, GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, NULL, NULL, GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, sizeOfVertices(), &vertices[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
}
There is an EBO included in the Model class but I'm not using it yet as I want to isolate the problem.
Model.h:
#pragma once
#include <vector>;
#include <glew.h>;
#include "glm.hpp"
#include "gtc/matrix_transform.hpp"
#include "gtc/type_ptr.hpp"
#include "gtc/constants.hpp"
class Model {
public:
int drawMode;
GLuint VAO;
GLuint VBO;
GLuint EBO;
GLuint *shaderProgram;
std::vector<GLfloat> vertices;
std::vector<GLuint> indices;
glm::mat4 model;
Model();
~Model();
void addVertex(GLfloat, GLfloat, GLfloat);
void addIndex(int, int, int);
void setShader(GLuint&);
void clearModel();
int sizeOfVertices();
int sizeOfIndices();
void draw();
void setDrawMode(int);
void move(glm::vec3);
void rotate(float, glm::vec3);
void update();
};
Main class:
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include "Callbacks.h"
#include "Shader.h"
#include "GlState.h"
#include "Model.h"
#include <glew.h>
#include <glfw3.h>
#include "glm.hpp"
#include "gtc/matrix_transform.hpp"
#include "gtc/type_ptr.hpp"
#include "gtc/constants.hpp"
Model *model;
Model *model2;
Model *model3;
void mainLoop(GLFWwindow* window) {
glfwPollEvents();
//RENDER UNDER HERE
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPointSize(5);
Callbacks::update(model3);
model3->draw();
model2->draw();
model->draw();
glfwSwapBuffers(window);
}
int main() {
GLFWwindow* window = GlState::Initialize(800,600);
GLuint shaderProgram = Shader::makeProgram("vertex.vs", "fragment1.fs");
GLuint shaderProgram2 = Shader::makeProgram("vertex.vs", "fragment2.fs");
model = new Model();
model2 = new Model();
model3 = new Model();
model->setShader(shaderProgram);
model2->setShader(shaderProgram);
model3->setShader(shaderProgram2);
while (!glfwWindowShouldClose(window))
{
mainLoop(window);
}
delete(model);
delete(model2);
delete(model3);
glfwTerminate();
return 0;
}
I'll also include the important part of Callbacks, which is called by update(Model* m)
void Callbacks::checkMouse(Model* m) {
if (leftMousePressed) {
if (tics == 0) {
m->addVertex(2*(mouseXCurrent-0.5), 2*(0.5-mouseYCurrent), 0.0f);
}
tics++;
}
}
I haven't set the camera yet so its in default orthographic view.
Since I can only add points to the last Model object initiated without crashing (model3 in this case), I assume it must be something to do with the way these models are being initiated but I can't figure out what! It's driving me nuts.
So an example of it crashing:
after the code segment in main:
model->setShader(shaderProgram);
model2->setShader(shaderProgram);
model3->setShader(shaderProgram2);
if you input
model->addVertex(0.1f,0.2f,0.0f);
or
model2->addVertex(0.1f,0.2f,0.0f);
the program will crash, however
model3->addVertex(0.1f,0.2f,0.0f);
works with no problems
The code will crash because you are accessing data outside of the buffers. In the constructor, you create buffers with size NULL:
glBufferData(GL_ARRAY_BUFFER, NULL, NULL, GL_STATIC_DRAW)
Note that the pointer type NULL is totally invalide for the size argument of that call, but that is not the issue here.
When you call the addVertex method, you append the data to your std::vector, but not to the VBO. Yo never call the update method which actually transfers the data into your buffer, so your attribute pointers still point to the 0-sized buffer, and when drawing more than 0 vertices from that, you're just in undefined-behavior land.
So I found what the problem is. Within the update method, I would bind the VAO and the problem was that I assumed this also bound the VBO for editing which apparently never happened. So when I called
glBufferData(GL_ARRAY_BUFFER, sizeOfVertices(), &vertices[0], GL_STATIC_DRAW);
I thought I was modifying the VBO within the VAO, but I was actually modifying the last VBO bound. The last time the VBO was bound was in the constructor, so this is why I was only able to modify the last Model object created, and the other ones would crash because I would bind their VAO and attempt to modify another Model's VBO.
At least I assume this was the problem as there is no error now because I'm calling
glBindBuffer(GL_ARRAY_BUFFER, VBO);
before I modify it.
My problem is the glDrawArray command stops working. I've written a few programs which I used that command. However now, I don't have any idea why it doesn't work.
But I still can draw lines to the screen with GL_LINES instead of GL_TRIANGLES.
Here is my code:
#include "Mesh.h"
#include <iostream>
Mesh::Mesh()
{
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
size = 0;
}
void Mesh::AddVertices(const Vertex vertices[], int length)
{
size = length;
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
}
void Mesh::Draw()
{
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, Vertex::SIZE * 4, 0);
glDrawArrays(GL_TRIANGLES, 0, size);
glDisableVertexAttribArray(0);
}
Draw is always called by Game class. And my Vertex class:
#include "Vertex.h"
Vertex::Vertex(glm::vec3 pos)
{
this->pos = pos;
}
Vertex::Vertex(float x, float y, float z)
{
pos = glm::vec3(x, y, z);
}
glm::vec3 Vertex::GetPos() const
{
return pos;
}
void Vertex::SetPos(glm::vec3 pos)
{
this->pos = pos;
}
sizeof(vertices) is sizeof(void*), because in C or C++ arrays in function arguments decays to pointers. You should use length provided in second argument, if it is size in bytes.
I've found the solution. When I initialize my OpenGL functions, I have accidentally written glFrontFace(GL_CW) instead of glFrontFace(GL_CCW).
in my project I want to display many objects (spheres) using vbo.
I manage to display 1 object without a problem ,but when it comes to 2 or more, all objects(vbos) are replaced by the last defined object(vbo).
CosmicBody(int x)
{
this->verticesSize=0;
//this->VaoId=x;
//this->VaoId=1;
this->VboId=x;
};
void CosmicBody::InitShape(unsigned int uiStacks, unsigned int uiSlices, float fA, float fB, float fC)
{
float tStep = (Pi) / (float)uiSlices;
float sStep = (Pi) / (float)uiStacks;
float SlicesCount=(Pi+0.0001)/tStep;
float StackCount=(2*Pi+0.0001)/sStep;
this->verticesSize=((int) (SlicesCount+1) * (int) (StackCount+1))*2;
glm::vec4 *vertices=NULL;
vertices=new glm::vec4[verticesSize];
int count=0;
for(float t = -Pi/2; t <= (Pi/2)+.0001; t += tStep)
{
for(float s = -Pi; s <= Pi+.0001; s += sStep)
{
vertices[count++]=glm::vec4(fA * cos(t) * cos(s),fB * cos(t) * sin(s),fC * sin(t),1.0f);
vertices[count++]=glm::vec4(fA * cos(t+tStep) * cos(s),fB * cos(t+tStep) * sin(s),fC * sin(t+tStep),1.0f);
}
}
glGenBuffers(1, &VboId);
glBindBuffer(GL_ARRAY_BUFFER, VboId);
glBufferData(GL_ARRAY_BUFFER, 16*verticesSize, vertices, GL_STATIC_DRAW);
glGenVertexArrays(1, &VaoId);
glBindVertexArray(VaoId);
glBindBuffer(GL_ARRAY_BUFFER, VboId);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
delete[] vertices;
}
void CosmicBody::Draw()
{
glBindBuffer(GL_ARRAY_BUFFER, this->VboId);
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLE_STRIP, 0,this->verticesSize); //when I replace this->verticesSize with number of vertices of last object ,instead of getting x different objects I get same instances of the last one.
glDisableVertexAttribArray(0);
}
When you use VAO's you should bind VAO for drawing, not the VBO buffer:
void CosmicBody::Draw()
{
glBindVertexArray( this->VaoId ); // <-- this is the difference
glDrawArrays(GL_TRIANGLE_STRIP, 0,this->verticesSize);
glBindVertexArray(0); // unbind the VAO
}
And move the glEnableVertexAttribArray(0); in the CosmicBody::InitShape after you bind VAO, no need to enable/disable it every time you draw:
...
glGenVertexArrays(1, &VaoId);
glBindVertexArray(VaoId);
glEnableVertexAttribArray(0); // <-- here
glBindBuffer(GL_ARRAY_BUFFER, VboId);
...