2

さて、私が取り組んでいるプロジェクトに関して、非常に奇妙な問題に遭遇しました。このプロジェクトは 3D エンジンです (それぞれ入力処理とグラフィックスに SDL と openGL を使用)。過去数か月間、Linux (Ubuntu 10.10) でこのプロジェクトに取り組んできましたが、最近、コードを Windows 7 環境に移植することにしました。私が SDL を選んだ主な理由の 1 つは、オペレーティング システムに依存せずにウィンドウの作成を処理するためです。コンパイルやリンクに問題はありません。明らかに理由もなく、まったく同じコードが 2 つのまったく異なる方法で実行されていることが問題です。

まず、違いの視覚的な例:

http://i.stack.imgur.com/RNcCs.jpg

このように見えるべきではありません。まず、左下にある紫色の revtangler はテキストであるはずです。よく見ると、いくつかのポイントがレンダリングされているのがわかります。私はジオメトリ、頂点、およびピクセル シェーダーを使用しています。

http://i.stack.imgur.com/1Y9km.jpg

Linux の場合と同様に、このように見えるはずです。私が話していたポイントは、これらの草です。

http://i.stack.imgur.com/Hzmuy.jpg

http://i.stack.imgur.com/HYCMh.jpg

Linux でも 600+ FPS で動作し、シェーダーは正常に動作し、すべてが問題なく動作します。Windows で FPS をチェックするコードを追加し (ボタンが押されたときに現在の fps をログ ファイルに送信)、シェーダーを無効にして 20 ~ 30 FPS で実行していました。

私が使用しているコードは実際に異なるものではないため、これには非常に混乱しています。唯一の違いは、openGL の使用方法にあります。Windows では GLEW を使用して拡張機能を処理し、Linux では #define GL_GLEXT_PROTOTYPES を使用します。私が使用しているコードは、Linux と Windows の両方で動作する必要があるように見えますが、Windows でプログラムを実行するたびに、これらの非常に奇妙な効果が発生します。

問題は次のとおりです。

  • ビューが正射投影でスタックしているようです (遠近法に設定されている場合)
  • シェーダー、ブレンディング、フレームバッファー/VBO、テクスチャーが機能していません。
  • 極端な遅延。

私が何か間違ったことをしている可能性があると思う唯一の場所は、 Initializing SDL/OpenGL/GLEW です。

私が最初にリンクしていたライブラリが私に問題を与えていたので、私はGLEWを直接使用しています。

//SAE_GL.h
/**Header Guard**/
#ifndef __SAE_OPENGL__
#define __SAE_OPENGL__

/**Include**/
///gl extensions
#ifdef __WIN32
    #define GLEW_STATIC
    #include "GL/glew.h"
#else
    #define GL_GLEXT_PROTOTYPES
#endif

///opengl
#include "GL/gl.h"
#include "GL/glu.h"

///SAE Dependencies
#include "SAE_Core.h"

ウィンドウマネージャ (WM.h は単に宣言を持ち、SAE_GL.h、SAE_SDL.h、および SAE_Core.h を含みます)

#include "SAE_WM.h"

namespace SAE{

bool SDL_Application::SAE_QUIT_BOOL_DEFAULT = false;
bool SDL_Application::SAE_MENU_BOOL_DEFAULT = false;
bool SDL_Application::SAE_VERBOSE_FLAG = false;

///Constructor
SDL_Application::SDL_Application(){

    ///Video Info
    screen      = (SDL_Surface*)NULL;
    videoInfo   = (SDL_VideoInfo*)NULL;

    VIEW_MODE               = SAE_PERSPECTIVE;
    VIEW_DIM                = SAE_3D;

    defaultScreenInfo = SAE_DEFAULT_SCREENINFO_HOLDER;
    currentScreenInfo = SAE_DEFAULT_SCREENINFO_HOLDER;

    numResolutions = 0;

    ///Set up our video flags
    videoFlags  = SDL_OPENGL;          ///OpenGL
    videoFlags |= SDL_GL_DOUBLEBUFFER; ///Double Buffering
    videoFlags |= SDL_HWPALETTE;       ///Harware Palette
    videoFlags |= SDL_RESIZABLE;       ///Window Resizing



    ///Callback setup
    setResizeFunction       ( SDL_DResize );
    setRunFunction          ( SDL_DRun    );
    setEventFunction        ( SDL_DEvent  );
    setCleanupFunction      ( SDL_DClean  );
    setMenuManagerFunction  ( SDL_DMenu   );

    SAE_QUIT_FLAG           = &SAE_QUIT_BOOL_DEFAULT;
    SAE_MENU_FLAG           = &SAE_MENU_BOOL_DEFAULT;


/////////////////////////////////////////////////

    ///FPS Handler setup
    time        = 0;
    frames      = 0;




/////////////////////////////////////////////////


/////////////////////////////////////////////////

/////////////////////////////////////////////////
/////////////////////////////////////////////////
}

void SDL_Application::init(int argc, char** argv){
    ///Redirect output to log
    FILE* tempb;
    tempb = freopen( "logfile.dat", "a+", stderr );

    fprintf(stderr,"\n===================================================================================================\n");
    fprintf(stderr,"\n***Initializing program essentials***\n");

    bool create_fonts = false;

    for(int i = 0; i < argc; i++){
        if(strncmp(argv[i], "-v",10)==0) SAE_VERBOSE_FLAG = true;
        if(strncmp(argv[i], "--genfonts",20)==0){
            videoFlags |= SDL_NOFRAME;
            create_fonts = true;
        }
    }

    ///Initialize Everything in SDL
    if(be_verbose)fprintf(stderr,"----SDL        : ");
    if ( SDL_Init( SDL_INIT_EVERYTHING ) < 0 ){
        if(be_verbose){
            fprintf( stderr, "Failed\n");
            fprintf( stderr, "--------Critical Error: SDL init failed: %s\n", SDL_GetError( ) );
        }
        fprintf( stderr, "****The program encountered a critical error - exiting...****");
        exit( 0 );
    }else{
        if(be_verbose)fprintf( stderr, "Success :)\n" );
    }

    ///Get Video Info
    videoInfo = ( SDL_VideoInfo* )SDL_GetVideoInfo( );
    if(be_verbose)fprintf(stderr,"----Video Info : ");

    if( !videoInfo ){
        if(be_verbose){
            fprintf( stderr, "Failed\n");
            fprintf( stderr, "--------Critical Error: Can't query video info: %s\n", SDL_GetError() );
        }
        fprintf( stderr, "\n****The program encountered a critical error - exiting...****");
        exit( 0 );
    } else {
        ///Setup our default width and height
        defaultScreenInfo.Width  = videoInfo->current_w;
        defaultScreenInfo.Height = videoInfo->current_h;
        if(be_verbose)fprintf( stderr, "Success :)\n");
    }

//////////////////////////////////////////////////////////////////////////////////////////////////

    ///Sets up what type of surface we're using
    if(be_verbose) fprintf(stderr,"----FrameBuffer: ");
    if( videoInfo -> hw_available ){
        videoFlags |= SDL_HWSURFACE;
    }
    else{
        videoFlags |= SDL_SWSURFACE;
    }

/////////

    ///Sets up hardware blitting
    if( videoInfo -> blit_hw ){
        videoFlags |= SDL_HWACCEL;
    }

/////////

    ///Enable Double Buffering
    SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
    SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE,   16);
    ///Startup the screen

    if(create_fonts){
        screen = SDL_SetVideoMode( SAE_DEFAULT_TEXTURE_WIDTH,
                                   SAE_DEFAULT_TEXTURE_HEIGHT,
                                   SAE_DEFAULT_SCREEN_BYTES_PER_PIXEL,
                                   videoFlags );
    }else{
        screen = SDL_SetVideoMode( SAE_DEFAULT_SCREEN_WIDTH,
                                   SAE_DEFAULT_SCREEN_HEIGHT,
                                   SAE_DEFAULT_SCREEN_BYTES_PER_PIXEL,
                                   videoFlags );
        }

    if ( !screen ){
        if(be_verbose)fprintf( stderr, "Critical Error: Video mode not supported: %s\n", SDL_GetError());
        fprintf( stderr, "\n****The program encountered a critical error - exiting...****");
        exit(0);
    } else {
        if(be_verbose) fprintf( stderr, "Success :)\n");
    }

//////////////////////////////////////////////////////////////////////////////////////////////////

    SDL_PixelFormat format;
    SAE_ScreenInfo max;
    format.BitsPerPixel = SAE_COMPATABILITY_SCREEN_BYTES_PER_PIXEL;

////////

    ///Get supported screen resolutions
    SDL_Rect** modes = SDL_ListModes(&format, videoFlags|SDL_FULLSCREEN);

    if(be_verbose)fprintf(stderr,"----Resolutions: ");
    if (modes == (SDL_Rect**)0) {
        if(be_verbose)fprintf(stderr,"Critical Error: No resolutions available!\n");
        fprintf( stderr, "\n****The program encountered a critical error - exiting...****");
        exit(-1);
    }else{
        if(be_verbose)fprintf(stderr,"Success :)\n");
    }

    if (modes == (SDL_Rect**)-1) {
        max.Width = videoInfo->current_w;
        max.Height = videoInfo->current_h;
    }else{
        for (int i=0; modes[i]; ++i){
            max.Width = modes[i]->w;
            max.Height = modes[i]->h;
        }
    }

    for(int i = 0; i < 23; i+=2){
        if(SAE_SCREEN_RESOLUTIONS[i] <= max.Width && SAE_SCREEN_RESOLUTIONS[i+1] <= max.Height)
        {
            supportedResolutions[numResolutions].Width = SAE_SCREEN_RESOLUTIONS[i];
            supportedResolutions[numResolutions].Height = SAE_SCREEN_RESOLUTIONS[i+1];
            numResolutions++;
        }
    }

    ///Initialize openGL
    if(be_verbose)fprintf(stderr,"----OpenGL     : ");
    if(!initializeOpenGL()){
        if(be_verbose)fprintf(stderr,"Critical Error: openGL init failed, exiting\n");
        fprintf( stderr, "\n****The program encountered a critical error - exiting...****");
        exit(0);
    } else {
        if(be_verbose)fprintf(stderr,"Success :)\n\n");
    }
/////////////////////////////////////////////////
    fprintf(stderr,"***------------SUCCESS------------***\n");
////////////////////////////////////////////////

    if(be_verbose){
        fprintf(stderr,"\n***---Current Video Information---***\n");
        fprintf( stderr, "----Software Surface: %s\n", (videoFlags&SDL_SWSURFACE )?"ENABLED":"DISABLED");
        fprintf( stderr, "----Hardware Surface: %s\n", (videoFlags&SDL_HWSURFACE )?"ENABLED":"DISABLED");
        fprintf( stderr, "----Hardware Palette: %s\n", (videoFlags&SDL_HWPALETTE )?"ENABLED":"DISABLED");
        fprintf( stderr, "----Double Buffering: %s\n", (videoFlags&SDL_DOUBLEBUF )?"ENABLED":"DISABLED");
        fprintf( stderr, "----openGL Doublebuf: %s\n", (videoFlags&SDL_GL_DOUBLEBUFFER )?"ENABLED":"DISABLED");
        fprintf( stderr, "----Fullscreen      : %s\n", (videoFlags&SDL_FULLSCREEN)?"ENABLED":"DISABLED");
        fprintf( stderr, "----OpenGL          : %s\n", (videoFlags&SDL_OPENGL    )?"ENABLED":"DISABLED");
        fprintf( stderr, "----Resizable       : %s\n", (videoFlags&SDL_RESIZABLE )?"ENABLED":"DISABLED");
        fprintf( stderr, "----No Frame        : %s\n", (videoFlags&SDL_NOFRAME   )?"ENABLED":"DISABLED");
    }
    SDL_EnableKeyRepeat(500,250);
    time = SDL_GetTicks();
    resizeWindow(SAE_DEFAULT_SCREEN_WIDTH, SAE_DEFAULT_SCREEN_HEIGHT);
    time = SDL_GetTicks();
}

これは、openGL/GLEW を使用するためにセットアップしているところです。

///Initialize openGL
bool SDL_Application::initializeOpenGL(){
/////////////////////////////////////////////////

    ///Initialize GLEW and load extensions
    #ifdef __WIN32
    GLenum status = glewInit();

    if( status != GLEW_OK ){
    ///Glew Initialization went wrong
        fprintf(stderr, "Error: %s\n", glewGetErrorString( status ));
        return false;
    } else {
        fprintf(stderr, "GLEW successfully initialized!\n");
    }
    #endif

/////////////////////////////////////////////////

    ///Sets clear color and clear depth
    float clearColor[]={0.0f,0.0f,0.0f,0.0f};
    glClearColor( clearColor[0], clearColor[1], clearColor[2], clearColor[3] );
    glClearDepth( 1.0f );

/////////
    ///DEPTH FUNCTION NEEDS CHECKING
    glDepthFunc ( GL_LEQUAL );
    glBlendEquation(GL_FUNC_ADD);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    glShadeModel( GL_SMOOTH );
/////////
    glEnable( GL_DEPTH_TEST );      ///Depth Testting
    glEnable( GL_CULL_FACE);        ///Face Culling
/////////////////////////////////////////////////

    return true;

/////////////////////////////////////////////////

}

また、ウィンドウのサイズ変更機能も相対的なものと見なして含めています。

void SDL_Application::resizeWindow(int width, int height){
/////////////////////////////////////////////////
        SDL_Event myEvent;
        myEvent.type = SDL_VIDEORESIZE;
        myEvent.resize.type = SDL_VIDEORESIZE;
        myEvent.resize.w = width;
        myEvent.resize.h = height;
        SDL_PushEvent(&myEvent);

    }

void SDL_Application::ResizeWindow(int width, int height){
/////////////////////////////////////////////////
    double v_min = (VIEW_DIM == SAE_2D)?1.0:  0.1 * SAE_UNIT_MEASURE;
    double v_max = (VIEW_DIM == SAE_2D)?1.0: 1000.0 * SAE_UNIT_MEASURE;
    ///Prevents divide by zero
    if( height <= 0 ) height = 1;

    ///Set aspect ratio
    double ratio = (double)width/(double)height;
    currentScreenInfo.Width = width;
    currentScreenInfo.Height = height;
/////////

    ///Load and clear our projection matrix
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();

    ///Set the entire window as our viewport
    glViewport( 0, 0, currentScreenInfo.Width, currentScreenInfo.Height );

    if(VIEW_MODE == SAE_PERSPECTIVE)
    {
        ///Set up a perspective projection
        gluPerspective( 70, ratio, v_min, v_max );
    }else{
        ///Gives us an orthographic perspective
        glOrtho( v_min, v_max, v_min, v_max, v_min, v_max);

    }



/////////

    ///Set what we're looking at, into the screen
    gluLookAt(0, 0, 0,
              0, 0, -1,
              0.0f, 1.0f, 0.0f);

/////////

    ///Do our user-set resize function and resize the screen

    SAEResize( currentScreenInfo.Width, currentScreenInfo.Height);
    screen = SDL_SetVideoMode( currentScreenInfo.Width, currentScreenInfo.Height, SAE_DEFAULT_SCREEN_BYTES_PER_PIXEL, videoFlags);
/////////////////////////////////////////////////
}

何かが欠けているに違いないか、SDL/OpenGL/GLEW が Windows でどのように機能するかについて何かわかりません。

編集: 私の質問に対する具体的な回答は得られないようです。コードを書き直して、DirectX を使用する必要があると思います。まあ、大したことではありません。

4

1 に答える 1

0

これがあなたの問題の主な理由だとは思いませんが、ウィンドウのサイズ変更ハンドラーで射影行列を設定するOPを含め、なぜそんなに多くの人がいるのですか? なんで?行列の設定はすべて表示機能に入ります。

また、射影行列は「レンズ」を設定するためにのみ使用する必要があります。射影行列でビュー位置を設定してはなりません。gluLookAt射影行列モード: 大きくて太った NoGo !

あなたはシェーダーを使用していると言いました。では、なぜ固定関数行列演算を使用しているのですか? 行列をユニフォームとして渡します。これにより、サイズ変更ハンドラーが属していない場所で何かを行うという問題もすぐに解決されます。

于 2012-10-20T09:14:45.717 に答える