Цвета отключены в программе SDL - PullRequest
2 голосов
/ 09 июня 2011

В настоящее время я работаю над очень простой игрой, использующей чистый C-подход с SDL (и его официальными дополнительными библиотеками, такими как SDL_image) и OpenGL.Сейчас я наткнулся на камень преткновения и понятия не имею, почему он это делает: при рисовании все цвета отключены.В настоящее время я запускаю программу на Mac, но если я правильно помню, когда я запускаю ее в Windows, цвета ближе к правильности, но все же происходят некоторые странные вещи (например, рисунок белого многоугольника желтым цветом).

В настоящее время на моем Mac все изображения, загруженные в виде файлов png, имеют немного оттянутый цвет, а чисто белый многоугольник отображается как темно-зеленый.Есть также несколько изображений, которые нарисованы чисто белым.Если я правильно помню в Windows, изображения отображаются правильно, но белый многоугольник желтый, как упоминалось ранее.Теперь я выложу соответствующий код для инициализации и загрузки и тому подобное.

int main( int argc, char *argv[] ) {
//initializing various OpenGL attributes with SDL utilities
    SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
    SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 ); //needs for 3D
    SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 ); //only needed for systems other than mac osx
    SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 );
    SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8 );
    SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 8 );

    /* Set 640x480 video mode */
    screen=SDL_SetVideoMode(screen_width,screen_height, 8, videoflags );
        if (screen == NULL) {
        fprintf(stderr, "Couldn't set %dx%dx%d video mode: %s\n",
                        screen_width, screen_height,
                        video_info->vfmt->BitsPerPixel, SDL_GetError());
        exit(2);
    }

    glShadeModel( GL_SMOOTH );

    glClearColor( 0.3f, 0.3f, 0.3f, 0 );

    glViewport( 0, 0, (GLsizei)screen->w, (GLsizei)screen->h );

    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();

    gluOrtho2D( 0.0f, screen->w, 0.0f, screen->h );

    /*glEnable( GL_BLEND );
    glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );*/
    glEnable( GL_ALPHA_TEST );
    glAlphaFunc( GL_GREATER, 0.1f );

// Some basic initialization stuff goes here
// Assume infinite while loop goes here, except when esc is pressed

        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
        glMatrixMode( GL_MODELVIEW );
        glLoadIdentity();

        glEnable( GL_TEXTURE_2D );
        draw_gui();

        // Things get drawn here

        glDisable( GL_TEXTURE_2D );

        SDL_GL_SwapBuffers();
        SDL_Delay( 10 );

// End of while loop, clean up, etc.
}

Теперь я покажу код, который фактически загружает изображение в память:

Sprite *gen_sprite( char *file ) {
    SDL_Surface *buffer = IMG_Load( file );
    if( buffer == NULL ) {
        fprintf( stderr, "Could not load image '%s'\n for reason: %s\n",
                file, IMG_GetError() );
        exit( 3 );
    } 
    return gen_sprite_from( buffer );
}

Sprite *gen_sprite_from( SDL_Surface *buffer ) {
    Sprite *sprite;
    GLuint texture;

    if( buffer == NULL ) {
        fprintf( stderr, "NULL surface passed to gen_sprite_from." );
        exit( 3 );
    }    
    texture = gen_Gl_texture_from( buffer );
    if( ( sprite = malloc( sizeof( Sprite ) ) ) == NULL ) {
        fprintf( stderr, "Malloc failed to allocate space for a Sprite.\n" );
        exit( 1 );
    }
    if( ( sprite->tex = malloc( sizeof( GLuint ) ) ) == NULL ) {
        fprintf( stderr, "Malloc failed to allocate space for a GLuint.\n" );
        exit( 1 );
    }
    sprite->tex[ 0 ] = texture;
    sprite->original = buffer;
    sprite->is_animation = 0;
    sprite->cur_frame = 0;
    sprite->cur_time = 0;
    sprite->num_frames = 1;
    sprite->frame_time = NULL;

    return sprite;
}

Uint32 gen_Gl_texture_from( SDL_Surface *buffer ) {
    GLuint texture;
    SDL_Surface *temp;

    glPixelStorei( GL_UNPACK_ALIGNMENT, 4 );
    glGenTextures( 1, &texture );
    temp = SDL_CreateRGBSurface( SDL_SWSURFACE, buffer->w, buffer->h, 32,

        0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 );
    SDL_SetAlpha( buffer, 0, SDL_ALPHA_OPAQUE );
    SDL_BlitSurface( buffer, NULL, temp, NULL );
    glBindTexture( GL_TEXTURE_2D, texture );
    //glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
    //glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
    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_GENERATE_MIPMAP, GL_TRUE );
    gluBuild2DMipmaps( GL_TEXTURE_2D, 4,
                      temp->w, temp->h,
                      GL_RGBA, GL_UNSIGNED_BYTE,
                      temp->pixels );
    SDL_FreeSurface( temp );

    // This just creates white blocks instead of actually loading textures
    //glPixelStorei( GL_UNPACK_ALIGNMENT, buffer->format->BytesPerPixel );
    //glGenTextures( 1, &texture );
    //glBindTexture( GL_TEXTURE_2D, texture );
    //glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
    //glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    //glTexImage2D( GL_TEXTURE_2D, 0, mask_order, buffer->w, buffer->h, 0,
    //  mask_order, GL_UNSIGNED_BYTE, buffer->pixels );

    return texture;
}

На этомТочка, я считаю, что весь код, который имеет отношение к тому, почему цвета будут искажены, был опубликован.Код для рисования очень прост и включает в себя что-то вроде перевода или поворота, связывания текстуры, а затем простой начальный / конечный блок с текстовыми координатами и вершинами.Если кто-то может сказать мне, почему цвета отключены, и дать мне хороший способ убедиться, что цвета всегда правильные в кроссплатформенном виде (я планирую использовать все платформы, что является одной из причин, по которым я используюSDL) Я был бы очень признателен.

1 Ответ

4 голосов
/ 09 июня 2011

Ваши каналы перепутаны.

Проблема проявляется в следующих строках:

temp = SDL_CreateRGBSurface( SDL_SWSURFACE, buffer->w, buffer->h, 32,
    0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 );

и

gluBuild2DMipmaps( GL_TEXTURE_2D, 4,
                  temp->w, temp->h,
                  GL_RGBA, GL_UNSIGNED_BYTE,
                  temp->pixels );

Вы указываете 32-битную текстуру в SDL, состоящую из 32-битных блоков, а затем вы задаете текстуру OpenGL как 4 8-битных компонента. Это может дать вам правильные или неправильные результаты в зависимости от порядкового номера вашей архитектуры. Решение состоит в том, чтобы задавать текстуры OpenGL не как GL_UNSIGNED_BYTE, а как GL_UNSIGNED_INT следующим образом:

gluBuild2DMipmaps( GL_TEXTURE_2D, 4,
                  temp->w, temp->h,
                  GL_RGBA, GL_UNSIGNED_INT_8_8_8_8,
                  temp->pixels );

Или, может быть, GL_UNSIGNED_INT_8_8_8_8_REV правильно, мне лень выяснять, какой из них соответствует вашей спецификации текстуры SDL. Или вы можете изменить спецификацию текстуры SDL. Подобный формат (на самом деле GL_BGRA / GL_UNSIGNED_INT_8_8_8_8_REV, я думаю , я мог бы ошибаться) точно соответствует общепринятому внутреннему формату и будет немного быстрее загружаться в вашу графику карты, но вы не заметите, если не загрузите много текстур.

В качестве стилистического примечания, как правило, предпочтительнее указывать внутренний формат более точно, например:

gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA8, ....
...