Двойная буферизация не работает на ноутбуке, на рабочем столе

Недавно я столкнулся со странной проблемой. Я написал класс приложения, который использует очень простое средство рендеринга для рисования некоторых моделей на экране. Камера подвижная.

Я запустил программу на своем ноутбуке. Сначала я заметил, что на экране ничего не рисуется (однако экран очищается правильным цветом). Затем я заметил, что экран обновится сам, если я нажму на рамку украшения и переместлю окно: таким образом, модели станут видимыми, но не будут двигаться, пока я не нажму и не переместлю рамку украшения снова.

Я проверил свою программу на настольном компьютере, и все работало нормально; камера двигалась плавно.

В конце концов, я получил программу для работы на моем ноутбуке, но я должен установить SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 0 ); и отключить замену буфера.

Ниже приведен основной класс приложения. В цикле выполнения я вызываю стек состояний приложений для цикла & render (состояние приложения на самом деле принадлежит рендереру).

В случае, если это имеет какое-либо значение, мой ноутбук имеет графику Intel HD 4000, а настольный компьютер имеет GTX 670.

App::App() : _running( false ),
_deltaTime( 0u ),
_elapsedTime( 0u ),
_mainWindow( nullptr ),
_glContext(),
_stack() {
//ctor
}

App::~App() {
SDL_GL_DeleteContext( _glContext );
SDL_DestroyWindow( _mainWindow );
SDL_Quit();
}

void App::execute() {
_initialize();

static const float millisecondsPerFrame = 17;

while ( _running ) {
//get the delta time & update elapsed time
uint32_t oldTime = _elapsedTime;
_elapsedTime = SDL_GetTicks();
_deltaTime = _elapsedTime - oldTime;

_processEvents();

_loop( _deltaTime / 1000.0f );
_render();

//apply possible state changes made to the stack
_stack.applyPendingChanges();

int usedTime = SDL_GetTicks() - int ( _elapsedTime );

//sleep the remainder of the cycle if we didn't use the entire update cycle
if ( millisecondsPerFrame - usedTime > 0 ) {
SDL_Delay( uint32_t ( millisecondsPerFrame - usedTime ) );
}
}
}

void App::_initialize() {

//initialize random number generator
nge::srand();

_running = true;

_initializeSDL();
_initializeOpenGL();

SDL_GL_MakeCurrent( _mainWindow, _glContext );

//attempt to set late swap tearing
int res = SDL_GL_SetSwapInterval( -1 );
//returns 0 on success
//returns -1 if swap interval is not supported
if ( res == -1 ) {
std::cout << "App::_initializeSDL> " << SDL_GetError() << "\n\n";
SDL_GL_SetSwapInterval( 1 );
}

_stack.registerState<GameState>( AppStateID::Game );
_stack.pushState( AppStateID::Game );
_stack.applyPendingChanges();
}

void App::_initializeSDL() {
SDL_Init( SDL_INIT_VIDEO );
SDL_Init( SDL_INIT_TIMER );

SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 3 );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 3 );

SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK,
SDL_GL_CONTEXT_PROFILE_CORE );

SDL_GL_SetAttribute( SDL_GL_ACCELERATED_VISUAL, 1 );

/**
For some reason, on my Samsung Series 9, double buffering does not
work.
*/
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 0 );
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE, 8 );
//anti-aliasing
SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, 1 );
SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, 4 );

_mainWindow =  SDL_CreateWindow( "window",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
800,
600,
SDL_WINDOW_OPENGL |
SDL_WINDOW_RESIZABLE |
SDL_WINDOW_MAXIMIZED |
SDL_WINDOW_SHOWN );

_glContext = SDL_GL_CreateContext( _mainWindow );
}

void App::_initializeOpenGL() {
//initialize GLEW
glewExperimental = GL_TRUE;

if ( glewInit() != GLEW_OK ) {
std::cerr << "glewInit failed." << std::endl;
std::exit( EXIT_FAILURE );
}

glEnable( GL_DEPTH_TEST );
//enable culling
glEnable( GL_CULL_FACE );
glCullFace( GL_BACK );

glDepthFunc( GL_LEQUAL );
glEnable( GL_TEXTURE_CUBE_MAP_SEAMLESS );

std::cout << "OpenGL version: " << glGetString( GL_VERSION ) << std::endl;
std::cout << "GLSL version: " << glGetString( GL_SHADING_LANGUAGE_VERSION ) << std::endl;
std::cout << "Vendor: " << glGetString( GL_VENDOR ) << std::endl;
std::cout << "Renderer: " << glGetString( GL_RENDERER ) << std::endl << std::endl;

//make sure OpenGL 3.3 is available
ASSERT( GLEW_VERSION_3_3, "OpenGL 3.3 API is not available" );
}

void App::_processEvents() {
SDL_Event event;
while ( SDL_PollEvent( &event ) ) {

if ( event.type == SDL_QUIT ) {
_running = false;
}
}
}

void App::_loop( float delta ) {
_stack.loop( delta );
}

void App::_render() {
_stack.render();
//SDL_GL_SwapWindow( _mainWindow );
}

2

Решение

Первое, что я хотел бы проверить, это драйверы графического процессора на ноутбуке. Убедитесь, что версия драйверов соответствует версии драйверов на рабочем столе.

Второе — добавить ошибку печати. От Вот :

window = SDL_CreateWindow("OpenGL Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_OPENGL);
if (!window) {
fprintf(stderr, "Couldn't create window: %s\n", SDL_GetError());
return;
}

context = SDL_GL_CreateContext(window);
if (!context) {
fprintf(stderr, "Couldn't create context: %s\n", SDL_GetError());
return;
}

Третье, что нужно проверить — это запрошенные буферы. Возможно, графический процессор или драйверы не поддерживают двойную буферизацию, размер глубины 16 бит или какой-либо другой параметр, который вы запросили. Итак, поиграйте с параметрами в initializeSDL() и найдите тот, который работает на вашем ноутбуке.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]