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\$
  • \$\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 '16 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 '16 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 '16 at 9:54
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\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.