Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 8 of 8

Thread: Performance Problem

  1. #1
    Junior Member Newbie
    Join Date
    Jan 2002
    Location
    Germany
    Posts
    24

    Performance Problem

    Hello,
    i am working on a little CAD-system. my scene has only one object at this time. this object is a geosphere with 5120 triangles and 2562 vertices for testing the performance.

    the vertices and mesh-description for the geosphere are precalculated, so that they would not be calculated while rendering. access-members for complex classes in my structure like cobject, cvertex, cmeshface, will always return references for faster access.

    i am using visual c++ in release-mode and no vertical synchronization for my gfx-card and monitor.

    when i render in imidiate mode, i get only 7 fps. using a displaylist for the geosphere speeds up rendering to 50 fps. i think this is not very fast, because popular games render more triangles in less times.

    here is the render-method :


    void C3DViewGL::RenderScene()
    {
    CExp3DDoc *pDoc = (CExp3DDoc *) GetDocument();
    if (!pDoc) return;

    CScene *pScene = pDoc->GetScene();
    if (!pScene) return;

    wglMakeCurrent(m_hDC,m_hRC);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();

    RenderGrid();

    glRotatef(m_rotAngleX,1.0,0.0,0.0);
    glRotatef(m_rotAngleY,0.0,1.0,0.0);
    glRotatef(m_rotAngleZ,0.0,0.0,1.0);
    glTranslatef(m_trans[1],m_trans[2],m_trans[3]);

    glBegin(GL_TRIANGLES);
    for (long i=0; i < pScene->Get3DObjectCount(); i++)
    {
    C3DObject *pObject = pScene->Get3DObjectAt(i);
    if (pObject)
    {
    if (pObject->GetMemObj())
    //Execute displaylist
    pObject->GetMemObj()->Execute();

    else
    //Render in imidiate-mode
    RenderObject(pObject);
    }
    }
    glEnd();

    RenderCoorSys();

    SwapBuffers(m_hDC);
    glPopMatrix();
    }


    void C3DViewGL::RenderObject(C3DObject *pObject)
    {
    CScene *pScene = pObject->GetScene();
    if (!pScene) return;

    if (pScene->GetColorMode() == CM_OBJECT)
    glColor3f(pObject->GetRed()/255.0, pObject->GetGreen()/255.0, pObject->GetBlue()/255.0);
    for (long j=0; j < pObject->GetMeshFaceCount(); j++)
    {
    CMeshFace *pMesh = pObject->GetMeshFaceAt(j);
    if (pMesh)
    {
    CVertex *pA, *pB, *pC;
    pA = pObject->GetVertexAt(pMesh->GetIndexA());
    pB = pObject->GetVertexAt(pMesh->GetIndexB());
    pC = pObject->GetVertexAt(pMesh->GetIndexC());
    if (pA && pB && pC)
    {
    if (pScene->GetShadingModel() == SM_FLAT)
    glNormal3f(pMesh->GetNormal()[1], pMesh->GetNormal()[2], pMesh->GetNormal()[3]);

    if (pScene->GetShadingModel() == SM_SMOOTH)
    glNormal3f(pA->GetNormal()[1], pA->GetNormal()[2], pA->GetNormal()[3]);
    if (pScene->GetColorMode() == CM_VERTEX)
    glColor3f(pA->GetRed()/255.0, pA->GetGreen()/255.0, pA->GetBlue()/255.0);
    glVertex3f(pA->GetVertex()[1], pA->GetVertex()[2], pA->GetVertex()[3]);

    if (pScene->GetShadingModel() == SM_SMOOTH)
    glNormal3f(pB->GetNormal()[1], pB->GetNormal()[2], pB->GetNormal()[3]);
    if (pScene->GetColorMode() == CM_VERTEX)
    glColor3f(pB->GetRed()/255.0, pB->GetGreen()/255.0, pB->GetBlue()/255.0);
    glVertex3f(pB->GetVertex()[1], pB->GetVertex()[2], pB->GetVertex()[3]);

    if (pScene->GetShadingModel() == SM_SMOOTH)
    glNormal3f(pC->GetNormal()[1], pC->GetNormal()[2], pC->GetNormal()[3]);
    if (pScene->GetColorMode() == CM_VERTEX)
    glColor3f(pC->GetRed()/255.0, pC->GetGreen()/255.0, pC->GetBlue()/255.0);
    glVertex3f(pC->GetVertex()[1], pC->GetVertex()[2], pC->GetVertex()[3]);
    }
    }
    }
    }

    maybe someone can give me a hint to speed this up !


    best regards

    tabor25

  2. #2
    Advanced Member Frequent Contributor
    Join Date
    Sep 2000
    Location
    SWEDEN
    Posts
    718

    Re: Performance Problem

    You're doing a bunch of conditional logic and unneccesary checks in the rendering function which slows you way down. That's why it speeds up so much when using a display list. Read this document on performance in OpenGL. To get better performance, abstract at a higher level, having a class called CVertex and sending this class one instance at a time to OpenGL is going to kill performance. You're also doing lots of logic per CMeshFace which seems to be a triangle. don't do that, it's slow. Batch stuff up in larger groups, abstract at a higher level/larger granularity and hoist your logic out of the loops. Use vertex arrays and index arrays and render the large batches with glDrawRangeElements and you'l see a large speed improvement. If you wan't more information on performance try searching these boards or looking here .

    [This message has been edited by harsman (edited 03-05-2002).]

  3. #3
    Senior Member OpenGL Pro
    Join Date
    May 2000
    Location
    Hannover, Germany
    Posts
    1,258

    Re: Performance Problem

    Also, try to unnest if/else constructs out of for-loops if possible.
    - Michael Steinberg

  4. #4
    Junior Member Newbie
    Join Date
    Jan 2002
    Location
    Germany
    Posts
    24

    Re: Performance Problem

    Thank you very much harsman and Michael Steinberg !!!

  5. #5
    Senior Member OpenGL Guru knackered's Avatar
    Join Date
    Aug 2001
    Location
    UK
    Posts
    3,032

    Re: Performance Problem

    God, that code is going to run very slow.
    Aside from what everyone else has said, look at all the divisions you're doing! Just to get your colours from 0-255 down to 0.0f-1.0f ??? Do this as a preprocessing step (ie. not for every vertex-every frame during runtime)
    Also, you seem to not be aware that opengl can deal with indexed vertex arrays well, in fact far better than explicitly repeating vertex definitions. I say this, because of these lines
    [CODE]
    CVertex *pA, *pB, *pC;
    pA = pObject->GetVertexAt(pMesh->GetIndexA());
    pB = pObject->GetVertexAt(pMesh->GetIndexB());
    pC = pObject->GetVertexAt(pMesh->GetIndexC());
    [\code]

    You can just give opengl the address of the first vertex in your vertex array, then give it the address of the first index in your index array - it will do the dereferencing for you!
    Knackered

  6. #6
    Junior Member Newbie
    Join Date
    Jan 2002
    Location
    Germany
    Posts
    24

    Re: Performance Problem

    Originally posted by knackered:
    Also, you seem to not be aware that opengl can deal with indexed vertex arrays well, in fact far better than explicitly repeating vertex definitions. I say this, because of these lines
    [CODE]
    CVertex *pA, *pB, *pC;
    pA = pObject->GetVertexAt(pMesh->GetIndexA());
    pB = pObject->GetVertexAt(pMesh->GetIndexB());
    pC = pObject->GetVertexAt(pMesh->GetIndexC());
    [\code]

    You can just give opengl the address of the first vertex in your vertex array, then give it the address of the first index in your index array - it will do the dereferencing for you!
    thank you very much for this tip knackered. After i got the messages of michael steinberg and harseman, i am now going to store vertex-,normal,- and index-data in float arrays which will be dynamically allocated when creating objects like sphere, cone, torus, etc.! My object-class contains now pointers to float-arrays, one for the vertices, another for the vertex-normals and a third one for the indices describing the mesh.
    Do you think that this is the right way to define the data-structure in refer to performance. Yesterday i bought the red-book and now i will read, what functions are available to handle the float-arrays.

    Best regards
    tabor25

  7. #7
    Advanced Member Frequent Contributor
    Join Date
    Sep 2000
    Location
    SWEDEN
    Posts
    718

    Re: Performance Problem

    Yes, this is a good way to store your data. It's flexible and efficient. I hope you're not using float for indices though It might be wise to factor out the handling of this data in a separate vertex buffer class. That'll probably help if you want to use more advanced geometry management in the future.

  8. #8
    Junior Member Newbie
    Join Date
    Jan 2002
    Location
    Germany
    Posts
    24

    Re: Performance Problem

    Originally posted by harsman:
    Yes, this is a good way to store your data. It's flexible and efficient. I hope you're not using float for indices though It might be wise to factor out the handling of this data in a separate vertex buffer class. That'll probably help if you want to use more advanced geometry management in the future.
    Hello harsman,

    now i am going to store vertex-,normal-,face- and color-data in arrays (pointers to arrays) in my object-class. the data will be calculated only once and then all is rendered by calling glDrawElements like follows:

    void C3DViewGL::RenderObject(C3DObject *pObject)
    {
    CScene *pScene = pObject->GetScene();
    if (!pScene) return;

    long faceCount;
    const GLfloat *pVertList = pObject->GetVertList();
    const GLfloat *pVertNormList = pObject->GetVertNormList();
    const GLfloat *pVertColList = pObject->GetVertColList();
    const GLuint *pFaceList = pObject->GetFaceList(faceCount);
    const GLfloat *pFaceNormList = pObject->GetFaceNormList();

    if (pScene->GetColorMode() == CM_OBJECT)
    {
    glDisableClientState(GL_COLOR_ARRAY);
    glColor3f(pObject->GetRed(), pObject->GetGreen(), pObject->GetBlue());
    }
    else
    {
    glEnableClientState(GL_COLOR_ARRAY);
    const GLfloat *pVertColList = pObject->GetVertColList();
    glColorPointer(3,GL_FLOAT,0,pVertColList);
    }

    if (pScene->GetShadingModel() == SM_FLAT)
    {
    glShadeModel(GL_FLAT);
    glNormalPointer(GL_FLOAT,0,pFaceNormList);
    }
    else
    {
    glShadeModel(GL_SMOOTH);
    glNormalPointer(GL_FLOAT,0,pVertNormList);
    }

    glVertexPointer(3,GL_FLOAT,0,pVertList);

    glDrawElements(GL_TRIANGLES,faceCount,GL_UNSIGNED_ INT,pFaceList);
    }


    Now my test-object contains 45000 polygons and will be rendered at 30 FPS per second :-). What do you think, is this a good rate or goes it also faster ?
    Using vertex-arrays i have a problem when i want to use flat-shading: in the code below, i force opengl to use the face-normal-array for shading when flat-shading is enabled. but it seems that the normals of the face-normal-array will not be used or in a wrong way, because the object looks not shaded correctly. Maybe you have an idea ?

    Best regards

    tabor25

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •