Specifically my problem is that I've created a Texture class (writing OpenGL code). The Texture class handles loading a file into memory, etc. and the constructor takes a filename as its parameter. Here's a snippet of some of the relevant code for that class.
class Texture
{
public:
unsigned char* image;
int width;
int height;
int channels;
GLuint texture_id;
Texture(const char* image_path)
:texture_id(NULL)
I then have a Pyramid class that can include a texture. It might simply be a colored pyramid with no texture though, so the texture attribute is optional.
class Pyramid :
public Shape
{
public:
std::string get_shape_type();
Pyramid(float height, float base_width, glm::vec4 color, glm::mat4 scale, glm::mat4 rotation, glm::mat4 translation);
Pyramid(float height, float base_width, const char * texture_file, glm::mat4 scale, glm::mat4 rotation, glm::mat4 translation);
private:
Texture texture;
Of course, this gives me an error that the Texture class doesn't have a default constructor. What's the general pattern to use in this sort of situation? I tried including texture(NULL) as part of the constructor initialization list for Pyramid since the texture should only be set if a filename is passed in as part of the appropriate constructor, but that didn't clear up the error.
Any suggestions?
Pointers can help you with that. They can either reference a Texture or nothing (via nullptr).
class Pyramid : public Shape
{
Texture* m_Texture;
Pyramid(Texture *tex = nullptr) m_Texture(tex) {};
};
Notes :
Pyramid may or may not be responsible for creating the texture depending on your need (meaning that the constructors could either require as parameters the Texture* or the filename)
A pointer will allow you to reuse the same Texture between many Shapes without loading them multiple times.
Related
I have an opengl batch renderer, which has a static vao, vbo, ebo etc. problem is, int the constructor of those are opengl methods. now, because they are static the opengl methods like glGenBuffers get called before opengl has been initialized.
so you can get a better picture, this is how it looks:
class renderer2d
{
private:
static vertex_array vao;
static vertex_buffer vbo;
static index_buffer ibo;
public:
static void draw();
static GLuint create_quad(glm::vec2 position, glm::vec2 size, GLfloat angle, glm::vec4 color);
}
and int the constructor of e.g. vao:
vao()
{
//some sort of opengl method, that gets called without opengl being initialized
glGenVertexArrays(1, &id);
}
btw, i dont only want to "solve" the problem while keeping the "static solution", if you have different ideas on how to do this, please tell me
One trick is to delay initialisation of the object like this:
renderer2d& get_renderer()
{
static renderer2d renderer;
return renderer;
}
This method works for any class, it does not require the renderer itself to have static data. The function can also be a static member of the class, as part of the Meyers singleton design.
It's easier for me to explain this kind of stuff in videogame terms. I'll try to be as clear as possible please bear with me...
I have a Bullet class that's made of different components, such as a Sprite component and a Transform Component... It would look something like this:
class Bullet
{
public:
Bullet( texture2D texture, Rectangle sourceRectangle, Rectangle destinationRectangle )
Bullet();
~Bullet();
// Returns a pointer to its sprite component so that I can use it wherever I want in the scene:
Sprite* const Sprite() const{ return this->sprite; }
// Setters:
void SetAngle( float new_angle ){ this->angle = new_angle; }
void SetSpeed( float new_speed ){ this->speed = new_speed; }
void SetRadius( float new_radius ){ this->radius = new_radius; }
private:
// Sprite component:
Sprite* sprite;
private:
// Regular member data:
float angle;
float speed;
float radius;
};
The sprite component is simply another class that holds a texture, source rectangle, destination rectangle, and some member functions to manipulate it (Move, Rotate, SetTexture, etc ). Nothing really special. It gets initialized within the constructor
What I need to do is to be able to copy one pointer to a bullet object entirely to another new pointer to a bullet, including the sprite component. Something like this:
// These arguments will be "fed" into the sprite component
Bullet* bullet1 = new Bullet( texture, sourceRect, destRect );
Bullet* bullet2 = new Bullet(); // Using default constructor.
*bullet2 = *bullet1;
Technically, doing it this way works. However, only the regular member data gets copied I think, but not the sprite component. It only points to the first bullet's sprite component. At least that's what I think is happening.
Hopefully I was clear explaining this issue, Thanks for taking the time.
I have a class "Object"
Object::Object(Transform transform, Mesh mesh, Shader shader)
{
this->transform = transform;
this->mesh = mesh;
this->shader = shader;
}
with 3 member variables Transform, Mesh and Shader (in case it's relevant I'm working with OpenGL- GLEW and GLFW)
The above constructor returns a "no default constructor exists for class Mesh" error.
I've defined a constructor for mesh, but my confusion here is that I'm trying to assign a passed variable object Mesh into the constructor when I instantiate an object.
Essentially I want something like
Transform transform() //has a default constructor requiring no parameters
Mesh mesh(parameters)
Shader shader()
Object myObject(transform, mesh, shader);
As a generic example.
In case the Mesh constructor is relevant:
Mesh::Mesh(Vertex* verts, unsigned int numVerts)
{
/*Vertex vertices[] = { Vertex(glm::vec3(-.5,-.5,0)),
Vertex(glm::vec3(0,.5,0)),
Vertex(glm::vec3(.5,-.5,0)) };*/
//vertices = new Vertex[numVerts]{ verts };
m_drawCount = numVerts;
glGenVertexArrays(1, &m_vertexArrayObject);
glBindVertexArray(m_vertexArrayObject);
glGenBuffers(NUM_BUFFERS, m_vertexArrayBuffers);
glBindBuffer(GL_ARRAY_BUFFER, m_vertexArrayBuffers[position_VB]);
glBufferData(GL_ARRAY_BUFFER, numVerts * sizeof(verts[0]), verts, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindVertexArray(0);
}
tl;dr I'm coming from a C# background, so maybe I've gotten confused but I'm not sure why I would need a default constructor for an object when I'm passing an object in as a parameter when that same object can be instantiated with the constructor I defined elsewhere in my code.
This:
Object::Object(Transform transform, Mesh mesh, Shader shader)
{
this->transform = transform;
this->mesh = mesh;
this->shader = shader;
}
Should be written like this instead:
Object::Object(const Transform& t, const Mesh& m, const Shader& s)
: transform(t), mesh(m), shader(s)
{
}
C++ isn't like C#, and you're going to get very confused if you assume it is.
In C++, all subobjects are constructed before you enter the body of the constructor. So the subobjects of your Object class (transform, mesh, and shader) are constructed using default constructors because you didn't specify anything else. The assignments that you coded in the body of your constructor have no effect on this.
To specify different parameters for the constructors of your subobjects, use a member initializer list, like my code above shows.
I have a code structure that has a Render with the rendering loop, a Shader class and a Model class. I am able to get my shaders to work when I implement them in the renderer, but I'm looking to assign them to a model and call render(), however I'm having an odd issue, that the shader works outside of the model, but not inside.
Shader structure:
class Shader
{
public:
unsigned int ID;
// constructor generates the shader on the fly
// ------------------------------------------------------------------------
Shader(const char* vertexPath, const char* fragmentPath, const char* geometryPath = nullptr)
{
... Generate shaders...
//Assign program ID to the public unsigned int
ID = glCreateProgram();
...attach shaders to program and link...
}
//Install program for use in rendering
void use()
{
glUseProgram(ID);
}
}
Model Structure:
class TextureModel
{
public:
TextureModel(const std::string modelPath, const std::string texturePath)
{
...Initialize model, load in mesh,texture, create a VAO with vertex and
index VBOs, set glAttribArray values...
}
Render(Shader* shader)
{
//glUseProgram(4) <---------- (3)
shader->use(); <---------- (1)
glBindVertexArray(VAO);
glBindTexture(GL_TEXTURE_2D, texture);
glDrawElements(GL_TRIANGLES, IBO->GetCount(), GL_UNSIGNED_INT, (void*)0);
glBindVertexArray(0);
}
}
Renderer structure:
Shader* texShader;
TextureModel* Reindeer;
int main()
{
texShader = new Shader("Shaders/camera.vs", "Shaders/textured.fs", "Shaders/passThrough.gs");
Reindeer = new TextureModel("Models/reindeer_v1/reindeer_v1.obj",
"Models/reindeer_v1/reindeer_diffuse.jpg");
while (!glfwWindowShouldClose(window))
{
...Update camera, project and model matrices. Update the shader uniforms...
//texShader->use() <---------- (2)
Reindeer->Render(texShader);
glfwSwapBuffers(window);
}
}
The above code does not render my object.
At point (1) my model calls the texShader->use() passed in by TextureModel::Render(Shader*). For some reason this does not work, however if I call texShader->use() from the rendering loop it works, this is at point (2).
Also in debugging I found that the program ID assigned to texShader on creation is 4. If I put glUseProgram(4) in the model::Render(Shader*) block, this also works. Point (3).
Why does the glUseProgram() function work in all cases except when passed in to my model? I'm really confused at this one.
Looks like I've fixed it.
I've summarized my problem above, but in actual fact I am using two different shaders for different objects.
The both share the same vertex shader (using their own model matrices, with a camera uniform buffer object), use different fragment shaders, and share a geometry shader.
For some reason I am only able to have one instance of the geometry shader working at a time... I need to to further investigation.
Either way I've got the above issue solved.
Thanks
Iam new to OpenGL and also new to C++ .
I created a main.cpp where i do everything .I Create an GLfloat data[] where i store my Cube's Vertices and also one GLfloat color[] for the Color. I create a VAO and a VBO and i have method, where i compile a simple Vertex and Fragment Shader.
The problem is,that my Code is very long,so i thought about creating a Cube Class,Triangle Class and so on.
My Question is now, can i use the same VAO for several Objects or do i use a new VAO for each Object?.
The other thing is, that i dont exactly know how to program this.I'am missing the structure(I used Java before).
My thoughts were :
class Cube {
public:
Cube();
Cube(GLfloat position[],GLfloat color[]);
//But i need the same Shaders for each Object , so do i initialize it here or somewhere else?
compileShader();
drawCube();
}
Note that this are only my thoughts about it..Maybe someone can help me out with this :)
VAO and VBO can be reused but for performance only should be if they aren't changing (for example, if you're keeping a 1x1x1 cube but using transformations to draw additional ones).
For a simple cube in a small application Your ideal structure would be something like
class Cube{
private static int vbo;
private static int vao;
public Cube(){
//If vbo and vao are 0 initialize them here
}
public void render(mat4* transform){
}
}
The shader would be a separate class, which can either be part of the rendering call for this object public void render (mat4* transform, shader* shader) or can be called by the main pipeline.
Now, I would recommend reading about header files in c++. In c++ headers are the right way to develop especially if you are going to be sharing your class around your program. Other classes need to only inherit the header, they don't have to care about the implementation, and that way your code only gets compiled once and you're using the same compiled assembly code throughout your class. (In c++ if you include actual code, it gets compiled, and even though modern linkers are good about merging duplicate code, it's still bad practice)
Cube.h:
class Cube{
static int vbo;
static int vao;
public:
Cube();
void render(mat4* transform);
}
cube.cpp:
Cube::Cube(){
//Initialize Here
}
Cube::render(mat4* transform){
//Render here
}
Then you'd also want a pair for shader
shader.h:
class Shader{
int ProgramID;
public:
Shader();
void activate ();
}
shader.cpp:
Shader::Shader(){
//compile shader here
}
Shader::activate(){
//make this shader program active here
}
The mat4 data for the transform that I mentioned came from http://glm.g-truc.net/0.9.6/index.html which is a great library for handling the math of 3d graphics.
If you want to refactor this further, you can define the render function of cube in an interface that all of your graphic objects will inherit, allowing you to more dynamically instantiate and configure the objects, and not care about what types they are, just that they're of the interface required.