Como lidar com a renderização em vários monitores com taxas de atualização diferentes?

8

Qual é a melhor maneira de lidar com uma situação que pode surgir, em que um usuário tem dois ou mais monitores com resoluções diferentes e intervalos de sincronização verticais?

Isso se aplicaria quando um jogo tivesse um timestap fixo e estivesse sendo executado no modo de janela: se um monitor tiver uma taxa de quadros de 60.056 e o ​​outro tiver uma taxa de quadros de 59.94, a sincronização vertical acabará falhando em seu trabalho, se o A janela do jogo é movida da tela principal para outra.

O aliasing temporal também ocorrerá, pois o timestep não está adequadamente sintonizado com a outra taxa de sincronização. Como os jogos geralmente lidam com esse problema, se é que existem?

NmdMystery
fonte
O que é exatamente o que você está tentando fazer?
Panda Pyjama
@PandaPajama Estou tentando permitir que o jogador mova a janela do jogo entre as telas sem problemas, para que A) não rasgue em nenhum momento e B) nenhum quadro seja repetido em nenhum momento. Eu acho que a lógica é independente disso, então reduzirei o escopo da minha pergunta para apenas renderização.
NmdMystery
Você só obterá quadros repetidos se a lógica do jogo for mais lenta que o código de renderização. A 60 fps lógicos, em 60.056 gráficos fps, em média, você obtém um quadro repetido a cada 18 segundos. Isso leva 0,017 segundos e provavelmente será imperceptível. Se você DEFINITIVAMENTE NÃO DEVE ter quadros repetidos, poderá ter sua lógica de jogo em uma taxa de quadros muito mais rápida. Diga 200fps. Você desperdiçará muito processamento e obterá muitos quadros perdidos, mas não obterá quadros repetidos, o que parece ser seu objetivo.
Panda Pyjama
É claro que isso é válido para um mundo com etapas de tempo discretas, que abrangem a grande maioria do código do jogo. Se você puder calcular consistentemente o estado do seu mundo de jogo por um tempo arbitrário nem menos do que O(n)complexidade (idealmente O(1)), nada do que eu disse será aplicável. Simulações interativas não tendem a funcionar assim.
Panda Pyjama

Respostas:

5

As etapas da lógica do jogo não precisam ser sincronizadas com a lógica de exibição, mesmo se você estiver usando um passo fixo no tempo.

Considere um gameloop como:

var time_per_step = 1 / 60 -- for 60 -logic- steps per second
var prev_time = get_time() -- in seconds

while true do
    var curr_time = get_time()
    while prev_time < curr_time do
        do_step()
        prev_time = prev_time + time_per_step
        // optional: curr_time = get_time()
    end
    draw()
end

Realmente não importa quanto tempo suas draw()chamadas demoram. Contanto que você do_step()leve menos que time_per_step, sua lógica de jogo não ficará para trás.

Panda Pajama
fonte
Que tal rasgar? A solução para diferentes taxas de atualização é do fornecedor ou existe uma maneira eficiente de renderizar no momento correto nas duas telas sem experimentar o aliasing temporal em uma delas?
N
Esta solução é compatível com o vSync. Usei 60 etapas de quadro lógico por segundo, mas você pode aumentar ou diminuir o quanto quiser.
Panda Pyjama
O que quero dizer é que, com esse gameloop, sua lógica de jogo estará sempre atualizada com o relógio em tempo real. Assim, se sua lógica de desenho não estiver exatamente sincronizada com a lógica do jogo, esse algoritmo repetirá ou eliminará os quadros conforme necessário para acompanhar o relógio em tempo real. Se isto é aceitável ou não é com você decidir
Panda Pajama
Então eu tenho que escolher entre quadros repetidos e lacrimejamento, essencialmente? Não há outras alternativas?
NmdMystery
Bem, mas isso é por definição. Se você deseja Xquadros lógicos por segundo em Yquadros gráficos por segundo, por exemplo X != Y, você precisará fazer a lógica manter os gráficos (quadros repetidos e descartados) ou os gráficos manter a lógica (rasgar). A outra alternativa é forçar a lógica a ser executada na velocidade gráfica, o que levará ao aliasing temporal. Nenhuma ciência de foguetes aqui.
Panda Pyjama