Bienvenue, Invité. Merci de vous connecter ou de vous inscrire.
Avez-vous perdu votre e-mail d'activation ?

Auteur Sujet: [OpenGL] bug lorsque deux carrés superposés  (Lu 2444 fois)

0 Membres et 1 Invité sur ce sujet

Samuel Proulx

  • Full Member
  • ***
  • Messages: 118
    • Voir le profil
[OpenGL] bug lorsque deux carrés superposés
« le: Novembre 19, 2012, 02:49:30 am »
Bonjour à tous et à toutes :)

Lorsque deux carrés sont superposés (x,y,z identique) les FPS chute rapidement. Y a-t-il une raison à cela ?

Je peux dessiner 100 000 carrés (200 000 triangles) à des endroits différents et je vais tourner à 100 FPS. Si je met aucun offset à aucun carré, là je tourne à 3 FPS...

Merci et bonne journée ! :)

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : [OpenGL] bug lorsque deux carrés superposés
« Réponse #1 le: Novembre 19, 2012, 08:11:08 am »
C'est assez bizarre.

Est-ce que tu peux nous montrer un code complet minimal qui permet de reproduire le problème ?
Laurent Gomila - SFML developer

Samuel Proulx

  • Full Member
  • ***
  • Messages: 118
    • Voir le profil
Re : [OpenGL] bug lorsque deux carrés superposés
« Réponse #2 le: Novembre 19, 2012, 10:57:49 pm »
Petite précision : le problème vient tout simplement lorsque plein de surfaces sont superposées (même sans le depth test).

Voici un code utilisant glew :

10 000 carrés (20 000 triangles)
Vertex Buffer : oui
Indices Buffer : oui
Texture : non
Shader : non

#include <iostream>
#include <sstream>
#include <GL/glew.h>
#include <SFML/Graphics.hpp>
#include <SFML/OpenGL.hpp>
#include <random>

#define NB_POLY 10000

using namespace std;
using namespace sf;

int main()
{
    RenderWindow app(VideoMode(800,600),"OpenGL");
    glewInit();
    float* vertexData = new float[12*NB_POLY];
    for(int i=0;i<NB_POLY;i++)
    {
        vertexData[0+i*12] = -0.05f;
        vertexData[1+i*12] = 0.05f;
        vertexData[2+i*12] = -1.0f;

        vertexData[3+i*12] = 0.05f;
        vertexData[4+i*12] = 0.05f;
        vertexData[5+i*12] = -1.0f;

        vertexData[6+i*12] = 0.05f;
        vertexData[7+i*12] = -0.05f;
        vertexData[8+i*12] = -1.0f;

        vertexData[9+i*12] = -0.05f;
        vertexData[10+i*12] = -0.05f;
        vertexData[11+i*12] = -1.0f;
    }
    short* indiceData = new short[6*NB_POLY];
    for(int i=0;i<NB_POLY;i++)
    {
        indiceData[0+i*6] = 0+i*4;
        indiceData[1+i*6] = 1+i*4;
        indiceData[2+i*6] = 2+i*4;

        indiceData[3+i*6] = 0+i*4;
        indiceData[4+i*6] = 2+i*4;
        indiceData[5+i*6] = 3+i*4;
    }
    //Buffer Object
    GLuint vertexBufferObject;

    glGenBuffers(1,&vertexBufferObject);
        glBindBuffer(GL_ARRAY_BUFFER,vertexBufferObject);
        glBufferData(GL_ARRAY_BUFFER,sizeof(float)*12*NB_POLY,vertexData,GL_STATIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER,0);

        GLuint indiceBufferObject;
        glGenBuffers(1,&indiceBufferObject);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,indiceBufferObject);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(short)*6*NB_POLY,indiceData,GL_STATIC_DRAW);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);

    Clock time;
    int nbFPS = 0;
    while(app.isOpen())
    {
        if(time.getElapsedTime().asMilliseconds() >= 1000)
        {
            ostringstream ss;
            ss << nbFPS;
            nbFPS = 0;
            app.setTitle(ss.str());
            time.restart();
        }
        else
            nbFPS++;
        Event event;
        while(app.pollEvent(event))
        {
            if(event.type == Event::Closed)
                app.close();
        }
        glClear(GL_COLOR_BUFFER_BIT);

        glEnableVertexAttribArray(0);
        glBindBuffer(GL_ARRAY_BUFFER,vertexBufferObject);
        glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,0);
        glBindBuffer(GL_ARRAY_BUFFER,0);

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,indiceBufferObject);
        glDrawElements(GL_TRIANGLES, 6*NB_POLY, GL_UNSIGNED_SHORT, 0);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);

        glDisableVertexAttribArray(0);

        app.display();
    }
    glDeleteBuffers(1,&vertexBufferObject);
    glDeleteBuffers(1,&indiceBufferObject);
    return 0;
}
 

Avec 20 000 triangles, j'obtiens ~60 FPS.... C'est pas très optimal...

Selon ce que j'ai compris, il s'agit d'overdraw : tous les triangles sont dessinés. Cela signifie donc remplir environ 100x100x10 000 pixels à chaque frame. 100 M de pixels par frame, je crois que c'est très coûteux en ressources...

Maintenant, si je met des Z aléatoires, je tourne à 180 FPS avec 10 000 carrés :
    default_random_engine generator;
    uniform_real_distribution<float> distribution(-1,1);
    RenderWindow app(VideoMode(800,600),"OpenGL");
    glewInit();
    float* vertexData = new float[12*NB_POLY];
    for(int i=0;i<NB_POLY;i++)
    {
        float rand = distribution(generator);
        vertexData[0+i*12] = -0.05f;
        vertexData[1+i*12] = 0.05f;
        vertexData[2+i*12] = -1.0f+rand;

        vertexData[3+i*12] = 0.05f;
        vertexData[4+i*12] = 0.05f;
        vertexData[5+i*12] = -1.0f+rand;

        vertexData[6+i*12] = 0.05f;
        vertexData[7+i*12] = -0.05f;
        vertexData[8+i*12] = -1.0f+rand;

        vertexData[9+i*12] = -0.05f;
        vertexData[10+i*12] = -0.05f;
        vertexData[11+i*12] = -1.0f+rand;
    }
 

Remarque aussi que si l'on dessine 10 000 shape :
ConvexShape shape;
    shape.setPointCount(4);
    shape.setPoint(0,Vector2f(0,0));
    shape.setPoint(1,Vector2f(100,0));
    shape.setPoint(2,Vector2f(100,100));
    shape.setPoint(3,Vector2f(0,100));


    for(int i=0;i<10000;i++)
        app.draw(shape);
 

Ça tourne à 8 FPS. Sauf qu'il me semble que chaque draw(shape) est un appel à glDraw*(). Ce qui est tout à fait normal que ça coûte cher si on appelle 10 000 fois le driver par frame...

Comment faire pour gérer cela plus efficacement ?

Merci et bonne journée ! :)