*** RENDER ENGINE ***

Post Reply
ezee
Intrepid Venturer
Intrepid Venturer
Posts: 703
Joined: Tue Feb 11, 2014 12:47 am
Location: FRANCE
Contact:

*** RENDER ENGINE ***

Post by ezee »

yeah , me again !
:lol:

I was reading the source code , following that curious /*GFXDRVAPI*/ ...
Then i remembered the 0.5.2 toDO :
[OPEN] (klauss) put gfxlib into a class, or at the _very_least_ a namespace
--> http://wiki.vega-strike.org/Development ... .6.0#0.5.2

GREAT IDEA !
I go into that direction me too , as i try to separate the gameEngine in subSystems .
So this thread is dedicated to the actual RENDER SYSTEM .

I will report my analyze later , and see what could be done .
If we can isolate the rendering into a c++ namespace , we can probably make a class .
A Abstract class could be great ! you guess why ?
An abstract class is a class that is designed to be specifically used as a base class. An abstract class contains at least one pure virtual function. You declare a pure virtual function by using a pure specifier (= 0) in the declaration of a virtual member function in the class declaration.
So the name is gfx for "Graphics Effects" ?
mmm ... i try to "create" a rendersystem .
The advantages are multiples :
Image

So now imagine something like VS::RenderSystem .
:wink:

I will study that possibility .
More to come .

Edit ; Let simulate a port of the ogre3d render system , and use their level of engineering:
( I pop Ogre and push VS to simulate this port explained by their doc )
original doc is here http://www.ogre3d.org/docs/api/1.9/clas ... ml#details
Remarks
The RenderSystem class provides a base interface which abstracts the general functionality of the 3D API e.g. Direct3D or OpenGL. Whilst a few of the general methods have implementations, most of this class is abstract, requiring a subclass based on a specific API to be constructed to provide the full functionality. Note there are 2 levels to the interface - one which will be used often by the caller of the VS library, and one which is at a lower level and will be used by the other classes provided by VS. These lower level methods are prefixed with '_' to differentiate them. The advanced user of the library may use these lower level methods to access the 3D API at a more fundamental level (dealing direct with render states and rendering primitives), but still benefiting from VS's abstraction of exactly which 3D API is in use.
cool preview , no ?

Check the source code of OgreRenderSystem.h if you wanna have a global idea here :
http://www.ogre3d.org/docs/api/1.9/Ogre ... ource.html

In that system , we can host the actual gfxlib ( SDL/Opengl) as subclass , and create new ones . Should be portable .

Code: Select all

 if (!track.HasWeapons())
            {
                // So what are you going to threaten me with? Exhaustion gas?
                return ThreatLevel::None;
            }
Vegastrike evolved
DEV YOUTUBE CHANNEL
Vegastrike evolved wiki
ezee
Intrepid Venturer
Intrepid Venturer
Posts: 703
Joined: Tue Feb 11, 2014 12:47 am
Location: FRANCE
Contact:

Re: *** RENDER ENGINE ***

Post by ezee »

I have started to create a new class , GFXRenderer .
Based upon gfxlib.h functions , GFXRenderer will be the centralized interface for rendering
stuff .

I'm not happy with the actual design/architecture of the gameEngine ( even if it is working
good , and i feel a lot of respect for that ! ) because some stuffs are linked each other
where they shouldn't ( in my point of view ) .

Example of bad design is Universe class that deal with rendering ( why ? ) :
/**
* Class Universe Deals with universal constants. It is a global,
* accessed from anywhere as _Universe-> Universe may be queried for
* Relationships, the current star system rendering is taking place in
* etc. It acts as a wrapper to the active Star System.
* Additionally it handles beginning and ending the main loop.
* And starting and ending graphics. (incl the task of wiping temp lights)
* Deprecated: loaded dynamic gldrv module
*/
The answer is because of the main loop ! ( single thread for gamelogic,physic,inputs,audio,render )
I wonder if it's possible in a single threaded app to separate the Gamelogic and the rendering system . ( a loop for the game logic-input-audio- an other for rendering ops.)
Look now what this mean today :

Code: Select all

void GameUniverse::Loop( void main_loop() )
{
    GFXLoop( main_loop );
}
The render stage is looped inside the gameLogic .
It is also initialised in the gameLogic :

Code: Select all

void GameUniverse::Init( int argc, char **argv, const char *galaxy )
{
    current_cockpit = 0;
    //Select drivers
#if defined (__APPLE__)
    //get the current working directory so when glut trashes it we can restore.
    char pwd[MAXPATHLEN];
    getcwd( pwd, MAXPATHLEN );
#endif
    GFXInit( argc, argv );
#if defined (__APPLE__)
    //Restore it
    chdir( pwd );
#endif
    StartGFX();
    InitInput();

    hud_camera = Camera();
...
...
AND GFX is only Opengl stuff :

Code: Select all

void GFXInit( int argc, char **argv )
{
    char vsname[12] = "Vega Strike";
    char vsicon[9] = "vega.ico";
    winsys_init (&argc,argv,&vsname[0],&vsicon[0]);
    /* Ingore key-repeat messages */
    winsys_enable_key_repeat( false );

    glViewport( 0, 0, g_game.x_resolution, g_game.y_resolution );
    float clearcol[4];
    gl_options.wireframe = game_options.use_wireframe;
    gl_options.max_texture_dimension = game_options.max_texture_dimension;
    gl_options.max_movie_dimension   = game_options.max_movie_dimension;
    bool textsupported = (vsExtensionSupported( "GL_ARB_texture_non_power_of_two" ) ||  vsExtensionSupported( "GL_ARB_texture_rectangle" ) || vsExtensionSupported( "GL_NV_texture_rectangle" )) ? "true" : "false" ;

    gl_options.rect_textures    = game_options.rect_textures ? true : textsupported;

    if (gl_options.rect_textures) {
        VSFileSystem::vs_dprintf(3, "RECT textures supported\n");
        
        // Fetch max rect textue dimension
        GLint max_rect_dimension = 65535;
        glGetIntegerv(
            GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, 
            &max_rect_dimension);
        
        gl_options.max_rect_dimension = max_rect_dimension;
        VSFileSystem::vs_dprintf(3, "RECT max texture dimension: %d\n", max_rect_dimension);
    }
        
    bool vidsupported = (   gl_options.rect_textures || (   vsExtensionSupported( "GL_ARB_texture_non_power_of_two" ) && vsVendorMatch("nvidia"))); 

    gl_options.pot_video_textures    = game_options.pot_video_textures ? true : vidsupported;

    if (!gl_options.pot_video_textures && gl_options.rect_textures) {
        // Enforce max rect texture for movies, which use them
        if (gl_options.max_movie_dimension > gl_options.max_rect_dimension)
            gl_options.max_movie_dimension = gl_options.max_rect_dimension;
    }
    
    if (gl_options.pot_video_textures)
        VSFileSystem::vs_dprintf(1, "Forcing POT video textures\n");
    else
        VSFileSystem::vs_dprintf(3, "Using NPOT video textures\n");
    // Removing gl_options soon
    gl_options.smooth_shade        = game_options.SmoothShade;
    gl_options.mipmap 		   = game_options.mipmapdetail;
    gl_options.compression         = game_options.texture_compression;
    gl_options.Multitexture        = game_options.reflection;
    gl_options.smooth_lines        = game_options.smooth_lines;
    gl_options.smooth_points       = game_options.smooth_points;

    gl_options.display_lists       = game_options.displaylists;
    gl_options.s3tc 		   = game_options.s3tc;
    gl_options.ext_clamp_to_edge   = game_options.ext_clamp_to_edge;
    gl_options.ext_clamp_to_border = game_options.ext_clamp_to_border;

    vs_config->getColor( "space_background", clearcol );
    glClearColor( clearcol[0], clearcol[1], clearcol[2], clearcol[3] );
    winsys_set_reshape_func( Reshape );
    initfov();
    glShadeModel( GL_SMOOTH );
    glEnable( GL_CULL_FACE );
    glCullFace( GL_BACK );
    glShadeModel( GL_SMOOTH );
    glEnable( GL_DEPTH_TEST );
    glDepthFunc( GL_LESS );
    if (gl_options.wireframe)
        glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
    if (gl_options.smooth_shade == 0)
        glShadeModel( GL_FLAT );
    glEnable( GL_ALPHA_TEST );
    glAlphaFunc( GL_GREATER, 0.0 );

    init_opengl_extensions();
    GFXInitTextureManager();
    if (gl_options.Multitexture)
        GFXActiveTexture( 0 );
    glEnable( GL_TEXTURE_2D );          //use two-dimensional texturing
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );

#if defined (IRIX)
    glEnable( GL_SHARED_TEXTURE_PALETTE_EXT );
#endif
    if ( vsExtensionSupported( "GL_EXT_color_table" ) || vsExtensionSupported( "GL_EXT_shared_texture_palette" ) ) {
        gl_options.PaletteExt = 1;
        VSFileSystem::vs_dprintf(3, "OpenGL::EXTColorTable supported\n");
    } else {
        gl_options.PaletteExt = 0;
        VSFileSystem::vs_dprintf( 2, "OpenGL::EXTColorTable unsupported\n" );
    }
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
    glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
    if (gl_options.Multitexture) {
        for (int i = 1; i < 4; ++i) {
            GFXActiveTexture( i );
            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
            GFXTextureEnv( i, GFXADDTEXTURE );
            glPixelStorei( GL_UNPACK_SKIP_ROWS, 0 );
            glPixelStorei( GL_UNPACK_SKIP_PIXELS, 0 );
            glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
            glPixelStorei( GL_UNPACK_SWAP_BYTES, 0 );
            // Choose cubemap or spheremap coordinates. 
            if (i == 1) {
#ifdef NV_CUBE_MAP
                GFXToggleTexture( true, 1, CUBEMAP );
                GFXTextureCoordGenMode( 1, CUBE_MAP_GEN, NULL, NULL );
#else
                const float tempo[4] = {1, 0, 0, 0};
                GFXToggleTexture( true, 1, TEXTURE2D );
                GFXTextureCoordGenMode( 1, SPHERE_MAP_GEN, tempo, tempo );
#endif
            }
        }
    }
    GFXActiveTexture( 0 );
    glClearDepth( 1 );
    glEnable( GL_BLEND );
    glDisable( GL_ALPHA_TEST );
    GFXBlendMode( ONE, ZERO );

    glColor3f( 0, 0, 0 );
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
    glMatrixMode( GL_TEXTURE );
    glLoadIdentity();     //set all matricies to identity
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();

    glEnable( GL_LIGHTING );

    glDisable( GL_NORMALIZE );

    glDisable( GL_LINE_SMOOTH );
    glDisable( GL_POINT_SMOOTH );

    int con;
    GFXCreateLightContext( con );
    //glutSetCursor(GLUT_CURSOR_NONE);
    /* Avoid scrambled screen on startup - Twice, for triple buffering */
    if ( game_options.ClearOnStartup ) {
        glClear( GL_COLOR_BUFFER_BIT );
        winsys_swap_buffers();
        glClear( GL_COLOR_BUFFER_BIT );
        winsys_swap_buffers();
    }
    glEnable( GL_TEXTURE_CUBE_MAP_SEAMLESS );
    winsys_show_cursor( false );
}

I have to deal as consequence to read/write operations to disk inside GFXRenderer
because of this implementation in Universe !
That is bad , and i will try to find an other way to do that . ( checking relationships etc..)

The renderer should be an independent module that you first setup with viewports and camera . ( and perhaps is responsible also for window creation ? ) .

All other operations should be dedicated to specialized class , used in Universe for example .
The actual render process :
step 1

Code: Select all

_Universe->Loop( main_loop );
definition of main-loop :

Code: Select all

void GameUniverse::Loop( void main_loop() )
{
    GFXLoop( main_loop );
}
step 2 ( frame level )

Code: Select all

void main_loop()
{
    //Evaluate number of loops per second each XX loops
    if (loop_count == 500) {
        last_check = cur_check;
        cur_check  = getNewTime();
        if (last_check != 1) {
            //Time to update test
            avg_loop  = ( (nb_checks-1)*avg_loop+( loop_count/(cur_check-last_check) ) )/(nb_checks);
            nb_checks = nb_checks+1;
        }
        loop_count = -1;
    }
    loop_count++;

    //Execute DJ script
    Music::MuzakCycle();

    _Universe->StartDraw();// frame level
    if (myterrain)
        myterrain->AdjustTerrain( _Universe->activeStarSystem() );
    if (Network != NULL)
        for (size_t jj = 0; jj < _Universe->numPlayers(); jj++)
            Network[jj].checkMsg( NULL );
    
#ifndef NO_GFX
    VSFileSystem::vs_dprintf(3, "Drawn %d vertices in %d batches\n", 
                             gl_vertices_this_frame, 
                             gl_batches_this_frame);
    gl_vertices_this_frame = 0;
    gl_batches_this_frame = 0;
#endif
    
    //Commit audio scene status to renderer
    if (g_game.sound_enabled)
        Audio::SceneManager::getSingleton()->commit();
}

The actual renderloop is that part of code :

Code: Select all

void GameUniverse::StartDraw()
{
#ifndef WIN32
    RESETTIME();
#endif
    GFXBeginScene();
    size_t i;
    StarSystem  *lastStarSystem = NULL;
    for (i = 0; i < cockpit.size(); ++i) {
        SetActiveCockpit( i );
        float x, y, w, h;
        CalculateCoords( i, cockpit.size(), x, y, w, h );
        AccessCamera()->SetSubwindow( x, y, w, h );
        if (cockpit.size() > 1 && AccessCockpit( i )->activeStarSystem != lastStarSystem) {
            active_star_system[0]->SwapOut();
            lastStarSystem = AccessCockpit()->activeStarSystem;
            active_star_system[0] = lastStarSystem;
            lastStarSystem->SwapIn();
        }
        AccessCockpit()->SelectProperCamera();
        if (cockpit.size() > 0)
            AccessCamera()->UpdateGFX();
        if ( !RefreshGUI() && !UniverseUtil::isSplashScreenShowing() )
            activeStarSystem()->Draw();
        AccessCamera()->SetSubwindow( 0, 0, 1, 1 );
    }
    UpdateTime();
    UpdateTimeCompressionSounds();
    _Universe->SetActiveCockpit( ( (int) ( rand01()*cockpit.size() ) )%cockpit.size() );
    for (i = 0; i < star_system.size() && i < game_options.NumRunningSystems; ++i)
        star_system[i]->Update( (i == 0) ? 1 : game_options.InactiveSystemTime/i, true );
    StarSystem::ProcessPendingJumps();
    for (i = 0; i < cockpit.size(); ++i) {
        SetActiveCockpit( i );
        pushActiveStarSystem( AccessCockpit( i )->activeStarSystem );
        ProcessInput( i );                       //input neesd to be taken care of;
        popActiveStarSystem();
    }
    if (screenshotkey) {
        KBData b;
        Screenshot( b, PRESS );
        screenshotkey = false;
    }
    GFXEndScene();
    //so we don't starve the audio thread
    micro_sleep( getmicrosleep() );

    //remove systems not recently visited?
    static int sorttime = 0;
    if (game_options.garbagecollectfrequency != 0) {
        //don't want to delete something when there is something pending to jump therexo
        if ( PendingJumpsEmpty() ) {
            if ( (++sorttime)%game_options.garbagecollectfrequency == 1 ) {
                SortStarSystems( star_system, active_star_system.back() );
                if (star_system.size() > game_options.numoldsystems && game_options.deleteoldsystems) {
                    if ( std::find( active_star_system.begin(), active_star_system.end(),
                                   star_system.back() ) == active_star_system.end() ) {
                        delete star_system.back();
                        star_system.pop_back();
                    } else {
                        VSFileSystem::vs_fprintf( stderr, "error with active star system list\n" );
                    }
                }
            }
        }
    }
}
Some reading about game engine patern and rendering :
http://gameprogrammingpatterns.com/game-loop.html
http://www.koonsolo.com/news/dewitters-gameloop/
Run, run as fast as you can

We’ve already seen the simplest possible game loop:

while (true)
{
processInput();
update();
render();
}
Today , it's like
while (true)
{
processInput();
Universe.update(render());
}
The render stage is inside the Universe update .


Well , i go back to the code ...
( the 0.5.2 vc9 solution in trunk/ is still not working .
The compilation and link are ok but the exe generated crash at first loading time .
Severe , i must kill the process , no error file write ...
The precompiled exe in the package is working
Perhaps a bad configuration in the project ?)

Code: Select all

 if (!track.HasWeapons())
            {
                // So what are you going to threaten me with? Exhaustion gas?
                return ThreatLevel::None;
            }
Vegastrike evolved
DEV YOUTUBE CHANNEL
Vegastrike evolved wiki
Post Reply