GPWiki.org
GPWiki.org
It is currently Sat May 25, 2013 11:53 pm

All times are UTC




Post new topic Reply to topic  [ 6 posts ] 
Author Message
PostPosted: Tue Apr 10, 2012 7:55 pm 
Gamer Geek
User avatar

Joined: Sat Feb 25, 2012 7:07 pm
Posts: 29
Location: California
Hi,
So I have been trying to improve the speed of the rendering system that I wrote several years ago, and beleave that it is as fast as its going to get, at least with the way I am going about it presently, a per-triangle basis ( each triangle has its own texture pointer, vertices, draw method ect.). After some digging through the opengl api documentation, I came across glDrawElements(), which would speed up drawing a group of triangles, and as such improve the speed of my renderer greatly. But I am flummoxed as how to use it with my highly individualized triangle objects. My class for the triangles and vertices and normals are as follows:

Code:
class POINT
{
    public:
        float x;
        float y;
        float z;
       
        // constructors and methods
};

class VECTOR : public POINT
{
    public:
   
        // constructors and methods
};

class COLOR
{
    public:
        float r, g, b, a;
       
        // constructors and methods
};

class VERTEX : public POGEL::POINT
{
    public:
        COLOR color; // this vertexes color
        VECTOR normal; // this vertexes normal direction for lighting
        int boneIDs[3]; // other bone ids for smother animation
        float u; // texture coordinate
        float v; // texture coordinate
        int boneID; // bone index for animation
        unsigned char weights[3]; // bone weights for animation
        bool usable; // is the vertex usable?
       
        // constructors and methods
};

class BOUNDING
{
    private:
        unsigned long numpoints; // number of points used to create bounding box
        bool isactual; // not important
    public:
        float maxdistance; // maximum radius of bounding box
        POINT min; // minimum
        POINT max; // maximum
        COLOR color; // color used for drawing bounding box

        // constructors and methods
};

class TRIANGLE
{
    public:
        VERTEX vertex[3];      // the 3 verticies of the triangle
        VECTOR vertnormals[3]; // pre-transformed normals per-vertex for animation
        BOUNDING bounding;     // triangles bounding box
        VECTOR normal;         // the whole triangles normal vector
    private:
        POINT trimid;          // the middle of the triangle, for speed, pre-calculated
    public:
        int ivertex[3];               // indexes to 3 verticies used for animation
        unsigned int ivertlength;     // number of things in the list of verticies
        VERTEX * pvertex;      // pointer to the list of verticies used for animation
        IMAGE * texture;       // a pointer to the image to use as the texture
    private:
        unsigned int properties;      // the mushed options, for lighting coloring ect.
        bool usetrimid;               // pre-calculated center is accurate
    public:

       // constructors and methods
};



in retrospect horrible classes, but I do not want to rewrite 10,000 lines to integrate new classes.

My question is this: How in the h**l would I be able to use glDrawElements() with such non-standard classes?

thanks in advance.

TarpeyD12

_________________
It's not truly yours, until you void the warranty.
Most of my problems: "I can fix that! ... oops".


Top
 Profile  
 
PostPosted: Tue Apr 10, 2012 11:10 pm 
Harmlessness does no harm
User avatar

Joined: Tue Sep 14, 2004 8:37 pm
Posts: 3810
Location: Ferriday, LA, US
glDrawElements() uses vertex arrays -- something that is apparently not a factor in your code (as far as I can tell).

glDrawElements() basically takes a vertex array (which is set with glVertexPointer()) and iterates over it, given the 'mode' const you feed to the function (i.e. GL_TRIANGLE_STRIP or GL_TRIANGLE_FAN or whatever) and the indices of the vertex array you specify.

Of course, it should also be noted that immediate mode OpenGL (i.e. where you use functions such as glBegin() and so on) is deprecated (not to mention highly inefficient). If you are willing to require your users have a graphics adapter capable of OpenGL 2.0 or greater (pretty much every graphics adapter made in the past several years... though drivers can be an issue with Intel integrated devices), and can grit your teeth in order to learn shader programming, then you may want to look into it.

_________________
What most people don't understand about "enlightenment" is that it is not an end-goal; but where you find yourself just before taking a new "first step."


Top
 Profile  
 
PostPosted: Tue Apr 10, 2012 11:28 pm 
Gamer Geek
User avatar

Joined: Sat Feb 25, 2012 7:07 pm
Posts: 29
Location: California
Quote:
Of course, it should also be noted that immediate mode OpenGL (i.e. where you use functions such as glBegin() and so on) is deprecated (not to mention highly inefficient).


Yes I am using immediate OpenGL, I know that it is ineffient, but my stupid Intel 945G device probably won't support anything new, so I am somewhat stuck, besides it gives my program "backwards compatibility". As you can probably see everything is on a per-triangle basis, and each triangle is drawn as if it were a lone entity, which it usually is not. What I am trying to do is reduce the 40 to 50 gl*() calls per triangle, down to something like about 10 gl*() calls per 1000 triangles (at best), and with my current setup that is going to be difficult to say the least. Plus I am not really understanding how all the gl*Pointer() functions work. (you can tell that I have no idea what I am doing :x ).

_________________
It's not truly yours, until you void the warranty.
Most of my problems: "I can fix that! ... oops".


Top
 Profile  
 
PostPosted: Tue Apr 10, 2012 11:44 pm 
Harmlessness does no harm
User avatar

Joined: Tue Sep 14, 2004 8:37 pm
Posts: 3810
Location: Ferriday, LA, US
I feel your pain! Intel graphics adapters are awful awful awful. x_x One of my computers has an Intel GMA somesuchorother (it's a stock ASUS Eee 901 netbook from 2008 IIRC... in either case, the graphics "accelerator" is rather pathetic), and I tried to test an OpenGL game on it (which I wrote in immediate mode), only to discover that the program would refuse to run -- the graphics driver for that card would not allow a vertex buffer with more than 1,024 vertices. Made me rather unhappy.

Check NeHe Productions' "Legacy Tutorials" section ( http://nehe.gamedev.net/ ) to get up-to-speed on the basics of immediate-mode OpenGL. They are apparently also working on updated, modern-standards-compliant equivalent tutorials (which have yet to appear...).

Of course, if that doesn't do it for you, be sure and post back about what exactly might be giving you grief.

_________________
What most people don't understand about "enlightenment" is that it is not an end-goal; but where you find yourself just before taking a new "first step."


Top
 Profile  
 
PostPosted: Tue Apr 10, 2012 11:55 pm 
Gamer Geek
User avatar

Joined: Sat Feb 25, 2012 7:07 pm
Posts: 29
Location: California
NeHe is where I "learned" how to use OpenGL, what really irks me, is that I wasn't thinking when I wrote my triangle rendering system, and now two years later I an paying for it :doh >:( :x .

anyway this is how I render my triangles:

Code:

void
TRIANGLE::drawgeometry() const
{
    // if using triangle's flat normal set it
    if ( properties & TRIANGLE_LIT && !( properties & TRIANGLE_VERTEX_NORMALS ) )
    {
        glNormal3f( normal.x, normal.y, normal.z );
    }

    if ( !properties & TRIANGLE_COLORED )
    {
        glColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
    }

    if( properties & TRIANGLE_INVERT_NORMALS )
    {
        for ( unsigned int a = 3; a > 0; --a )
        {
            unsigned int i = a % 3;
            // the triangle will not be colored if GL_LIGHTING is enabled,
            //  don't know why.
            // set the color
            if ( properties & TRIANGLE_COLORED )
            {
                glColor4f( vertex[ i ].color.r, vertex[ i ].color.g, vertex[ i ].color.b, vertex[ i ].color.a );
            }

            // light the verticies
            if ( properties & TRIANGLE_VERTEX_NORMALS )
            {
                glNormal3f( vertex[ i ].normal.x, vertex[ i ].normal.y, vertex[ i ].normal.z );
            }

            // set the verticies' texture coordanates
            glTexCoord2f( vertex[ i ].u, vertex[ i ].v );

            // set the vertex
            glVertex3f( vertex[ i ].x, vertex[ i ].y, vertex[ i ].z );
        }
    }
    else
    {
        for ( unsigned int i = 0; i < 3; ++i )
        {
            // the triangle will not be colored if GL_LIGHTING is enabled,
            //  don't know why.
            // set the color
            if ( properties & TRIANGLE_COLORED )
            {
                glColor4f( vertex[ i ].color.r, vertex[ i ].color.g, vertex[ i ].color.b, vertex[ i ].color.a );
            }

            // light the verticies
            if ( properties & TRIANGLE_VERTEX_NORMALS )
            {
                glNormal3f( vertex[ i ].normal.x, vertex[ i ].normal.y, vertex[ i ].normal.z );
            }

            // set the verticies' texture coordanates
            glTexCoord2f( vertex[ i ].u, vertex[ i ].v );

            // set the vertex
            glVertex3f( vertex[ i ].x, vertex[ i ].y, vertex[ i ].z );
        }
    }

    if ( properties & TRIANGLE_COLORED )
    {
        glColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
    }
}

void
TRIANGLE::draw() const
{
    #ifdef OPENGL

    // set up the texture to use.
    if ( texture && texture->getbase() != (unsigned int)NULL && texture->isbuilt() )
    {
        texture->set();
    }
    else
    {
        IMAGE * nullImage = getNullImage();
        if ( nullImage && nullImage->getbase() != (unsigned int)NULL && nullImage->isbuilt() )
        {
            nullImage->set();
            //texture = nullImage;
        }
        else
        {
            return;
        }
    }

    bool b_bounding   = POGEL::hasproperty( POGEL_BOUNDING );
    bool b_wireframe  = POGEL::hasproperty( POGEL_WIREFRAME );

    //updateVert();

    // draw the triangle's bounding box
    if ( b_bounding )
    {
        bounding.draw( POINT() );
    }

    bool b_lit         = this->hasproperty( TRIANGLE_LIT );
    bool b_vertnorms   = this->hasproperty( TRIANGLE_VERTEX_NORMALS );
    bool b_doublesided = this->hasproperty( TRIANGLE_DOUBLESIDED );
    bool b_transparent = this->hasproperty( TRIANGLE_TRANSPARENT );

    // enable or disable lighting
    if ( b_lit || b_vertnorms )
    {
        glEnable( GL_LIGHTING );
    }
    else
    {
        glDisable( GL_LIGHTING );
    }

    if ( !b_doublesided )
    {
        glEnable( GL_CULL_FACE );
        glCullFace( GL_BACK );
        glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
    }
    else if ( glIsEnabled( GL_CULL_FACE ) )
    {
        glDisable( GL_CULL_FACE );
        glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
    }

    // set the transparency
    bool blendEnabled = false;
    if ( b_transparent )
    {
        blendEnabled = glIsEnabled( GL_BLEND );
        glBlendFunc( GL_SRC_ALPHA, GL_ONE );
        glEnable( GL_BLEND );
    }

    // begin either a solid face or lines for wireframe
    if ( b_wireframe )
    {
        glBegin( GL_LINES );
    }
    else
    {
        glBegin( GL_TRIANGLES );
    }

    drawgeometry();

    // end GL_TRIANGLES or GL_LINES
    glEnd();

    // disable the transparency
    if ( b_transparent )
    {
        glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
        if( !blendEnabled )
        {
            glDisable( GL_BLEND );
        }
    }

    #endif
}



really inefficient, but robust as h**l, the Idea was that I could just draw a triangle anywhere and not worry about setting anything up, but it is really slow.

_________________
It's not truly yours, until you void the warranty.
Most of my problems: "I can fix that! ... oops".


Top
 Profile  
 
PostPosted: Thu Apr 12, 2012 12:43 pm 
Funky Monkey

Joined: Thu Sep 09, 2004 1:17 pm
Posts: 1553
Location: burrowed
Well, at least you figured out for bottleneck :P

Just imagine your code above versus something like

Code:
GL.UseProgram(shaderId);
GL.BindBuffer(BufferTarget.ArrayBuffer, vboId);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, indexBufferId);
GL.DrawElements(BeginMode.Triangles, indices.Length, DrawElementsType.UnsignedInt, IntPtr.Zero);
GL.UseProgram(0);


Ok, granted. The way to set up your geometry is a tad more complex than this, but this is the rendering calls per object/model in a nutshell. Basically what you want to do is keeping the calls to opengl a minimum when rendering, this is why vertexbufferobjects exists.
Indeed it is more difficult to dynamically create geometry: if you have an VBO that just holds a triangle and render that thousands of times you run into problems pretty fast.
So one way to use them is shove a bunch of static geometry in an vbo, and create a more sophisticated manager for vbo's if you need dynamic generation or manipulation of geometry, like particles. You can stream/upload data to your vbo.

Regarding your intel adapter, just try running some opengl 2.0 sample code and see if it works. Backwards compatibility is not worth it if you're talking opengl < 2. People sporting hardware like that usually aren't interested in games, or are close to nonexistant nowadays. Sure you can use that as an excuse to not get into the dirty work of upgrading your code, which can take a lot of effort, be warned, but it's well worth it.

_________________
Long pork is people!

wzl's burrow


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group