1
\$\begingroup\$

So I'm creating a game engine with many features, last time I focused on textures.

When I finished implementing some new code (Made by myself) I created new Entity with texture, and it was working really nice.

But If I create 2 or more textured objects game starts lagging..

  • 1 Cube without texture = > 60 FPS
  • 1 Cube with texture = > 60 FPS
  • 2 Cubes without texture = > 60 FPS
  • 2 Cubes with texture = 40-50 FPS
  • 10 Cubes without texture = > 60 FPS
  • 10 Cubes with texture = 20 FPS
  • 100 Cubes without Texture = > 60 FPS
  • 100 Cubes with Texture = < 1 FPS
  • 10000 Cubes without Texture = > 60 FPS

I'm using GLSL sampler2D, texture UV from VBO, here is my renderer code:

bool textured = false;

if(entity->hasComponent("MaterialComponent"))
{
    MaterialComponent *materialComponent = (MaterialComponent*) entity->getComponent("MaterialComponent");

    if(materialComponent->material != NULL && materialComponent->material->texture != NULL) textured = true;
}

if(component->cullFaces)
{
    glEnable(GL_CULL_FACE);
    glCullFace(GL_BACK);
}

if(textured) glEnable(GL_TEXTURE_2D);

glBindVertexArray(component->model->vaoID);
glEnableVertexAttribArray(0);
if(textured) glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);

//glDrawElements(GL_TRIANGLES, component->model->getVertexCount(), GL_UNSIGNED_INT, 0);

if(textured)
{
    MaterialComponent *materialComponent = (MaterialComponent*) entity->getComponent("MaterialComponent");

    if(materialComponent->material->texture->textureID == 0) glGenTextures(1, &materialComponent->material->texture->textureID);

    glBindTexture(GL_TEXTURE_2D, materialComponent->material->texture->textureID);

    SDL_Surface *surface = IMG_Load(materialComponent->material->texture->textureFile->getPath().c_str());

    if(!surface) Error::throwError("Cannot load texture file!");

    S32 colorMode = GL_RGB;

    if(surface->format->BytesPerPixel == 4) colorMode = GL_RGBA;

    glTexImage2D(GL_TEXTURE_2D, 0, colorMode, surface->w, surface->h, 0, colorMode, GL_UNSIGNED_BYTE, surface->pixels);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);


    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
   // glGenerateMipmap(GL_TEXTURE_2D);

    glActiveTexture(GL_TEXTURE0);

    glUniform1i(baseShader->loc_sampler, 0);

    SDL_FreeSurface(surface);
}

glDrawElements(GL_TRIANGLES, component->model->getVertexCount(), GL_UNSIGNED_INT, 0);

if(textured)
{
    //glBindTexture(GL_TEXTURE_2D, 0);
    glDisable(GL_TEXTURE_2D);
}

glDisableVertexAttribArray(0);
if(textured) glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
glBindVertexArray(0);

if(textured) glDisable(GL_TEXTURE_2D);

if(component->cullFaces)
{
    glDisable(GL_CULL_FACE);
}

So I can create new TextureAsset for each cube or I can use one TextureAsset for each cube, it makes no difference about FPS.

I'm creating new TextureAsset like this:

TextureAsset *textureAsset = new TextureAsset(new FilePath("PATH_TO_TEXTURE"));

Then putting it inside Entity' MaterialComponent:

MaterialComponent *materialC = (MaterialComponent*) cube1->getComponent("MaterialComponent");

materialC->materialAsset->texture = textureAsset;

I think there is something bad inside my renderer method, it happens only if there is more than 1 textured object. Maybe I have to clean-up texture in different way?

I'm using SDL2, SDL2_image and GLEW.

If you need more code - just tell me.

\$\endgroup\$
3
  • \$\begingroup\$ Do you bind the texture for every entity separately, or yoi bind the texture, and render every object with that texture? \$\endgroup\$
    – Bálint
    Feb 3, 2016 at 9:38
  • \$\begingroup\$ Shader and texture binding have enough overhead that sometimes developers sort their draw calls to reduce this as much as possible. Also, creating and freeing the texture/surface every time you draw would probably make it significantly slower. \$\endgroup\$
    – Ben
    Feb 3, 2016 at 9:40
  • \$\begingroup\$ @Bálint Each object has its own texture, but I generate texture only once for each object and store ID inside its MaterialComponent->Material->TextureAsset->TextureID. As you can see:if(materialComponent->material->texture->textureID == 0) glGenTextures(1, &materialComponent->material->texture->textureID); Edit: But obviously I create new SDL_Surface each drawcall. \$\endgroup\$
    – skprime
    Feb 3, 2016 at 9:54

1 Answer 1

3
\$\begingroup\$

I know it's stupid to answer my own question but...

With very, very big thanks to @Ben I fixed this problem by creating SDL_Surface and load image to it once for each TextureAsset and store it inside TextureAsset instead of creating new SDL_Surface for same texture and free it each draw call.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .