Към съдържанието
PN Scripts

Игри

Автоматично качество на графиката в игра с Three.js: първа преценка по видеокартата, измерване на началния екран и динамична резолюция

  • PN Scripts
  • 7 мин четене

3D браузърната игра няма минимални системни изисквания. Една и съща връзка се отваря на мощен настолен компютър, на служебен лаптоп с вградена графика, на Chromebook и на петгодишен телефон, а играчът решава в първите десет секунди дали играта върви добре. Меню с настройки „Ниско, Средно, Високо“ не помага, защото повечето играчи никога не го отварят. Този дневник на разработката показва как нашата игра с балон Billowpost сама избира нивото на графиката: първа преценка по името на видеокартата, кратко измерване, докато е показан началният екран, резолюция, която се нагажда по време на игра, без да замръзва, и ниво, запомнено за следващото посещение. Числата са от тестовете ни на истински хардуер.

#Какво променят трите нива

Преди да решавате автоматично, решете какво означава всяко ниво. В Billowpost големите разходи са броят на пикселите, сенките и последващата обработка, затова нивата променят точно тях:

НастройкаВисокоСредноНиско
Съотношение на пикселитедо 2до 1,25, по 0,9до 1, по 0,8
Бюджет от пикселибезограниченограничен по-ниско
Сенки от слънцетокарта 2048, прерисувана на всеки 3-ти кадъркарта 1024, на всеки 4-ти кадъризключени
Последваща обработкасияние, цветова корекция, винетка, 2x изглажданебез, само тоново картографиранебез

Две от тези идеи си струва да се вземат дори без автоматична система. Пейзажът не се движи, а балонът се мести с няколко сантиметра на кадър, така че картата на сенките не трябва да се прерисува всеки кадър: изключването на shadowMap.autoUpdate и задаването на needsUpdate през няколко кадъра махна най-големия разход на вградената графика. А на средно и ниско сцената се рисува направо на екрана с тоновото картографиране на самия рендер, което спестява три прохода през целия екран и голяма цел за рисуване с половинна точност.

#Първа преценка по името на видеокартата

WebGL може да каже на коя видеокарта работи. Играта създава временен контекст, прочита името на рендера през разширението WEBGL_debug_renderer_info и веднага освобождава контекста:

static gpuName() {
  try {
    const c = document.createElement('canvas');
    const gl = c.getContext('webgl2') ?? c.getContext('webgl');
    if (!gl) return '';
    const ext = gl.getExtension('WEBGL_debug_renderer_info');
    const name = String(ext ? gl.getParameter(ext.UNMASKED_RENDERER_WEBGL) : gl.getParameter(gl.RENDERER));
    gl.getExtension('WEBGL_lose_context')?.loseContext();
    return name.toLowerCase();
  } catch {
    return '';
  }
}

После няколко регулярни израза превръщат името в начално ниво. Софтуерните рендери като SwiftShader или llvmpipe започват на ниско; така и по-старите видеокарти на телефони и HD и UHD Graphics на Intel, чиповете в повечето служебни лаптопи и Chromebook. Iris, другите вградени и мобилни видеокарти започват на средно, а всичко останало на високо. Едно уточнение дойде от тестовете: Intel HD и UHD започват на средно, когато прозорецът е около 1366 на 768 или по-малък, защото там държат 60 кадъра в секунда, и на ниско само на по-големи екрани.

Приемайте името като подсказка, никога като истина. Някои браузъри дават общо или опростено име, за да намалят снемането на отпечатък на устройството, а празно име води до средно ниво. Каквато и да е преценката, следващата стъпка измерва.

#Измерване на началния екран

Началният екран на Billowpost е самата игра: балонът се носи над първата долина, а менюто е отгоре. Това го прави идеален тест за скорост, който играчът не забелязва. Автоматичният режим пропуска първите две секунди, докато се строи пейзажът и се компилират шейдърите, после усреднява три едносекундни измервания на кадрите. Под 50 кадъра в секунда слиза едно ниво надолу и мери отново; иначе настройката е готова и нивото се запазва заедно с името на видеокартата:

if (mode === 'title' && !titleCalDone) {
  if (++titleSec <= 2) return;            // загряване: пренебрегва се
  titleFps.push(fps);
  if (titleFps.length < 3) return;
  const avg = titleFps.reduce((a, x) => a + x, 0) / titleFps.length;
  titleFps = [];
  if (avg < AUTO_SLOW && autoQ !== 'low') {
    autoQ = autoQ === 'high' ? 'medium' : 'low';
    stage.setQuality(autoQ, w, h);
    titleSec = 0;                          // новото ниво се мери отначало
  } else {
    titleCalDone = true;
  }
  settings.autoLearned = { q: autoQ, gpu: stage.gpu };
  writeSave(data);
}

При следващото посещение играта започва направо от запомненото ниво, стига името на видеокартата да е същото. Когато името се смени, например на лаптоп, който превключва между вградена и отделна видеокарта, играта отново преценява и мери.

#По време на игра: сменя се резолюцията, не пейзажът

Броят кадри се мени по време на игра: оживен град, голяма облачна маса или друга програма на заден план. Смяната на нивото посред игра би била грешният отговор, защото новото ниво преизгражда материалите, а компилирането на шейдъри замразява кадър за осезаем миг. Затова по време на игра автоматичният режим мени само резолюцията на рисуването, което става мигновено:

  • след три поредни секунди под 48 кадъра в секунда мащабът на рисуването пада с 10 процента, до 0,76 от резолюцията на нивото;
  • след осем поредни секунди на 58 или повече се качва обратно с около 6 процента, до пълна резолюция;
  • ако мащабът вече е на дъното и играта все още е бавна, по-ниско ниво се нарежда на опашка и се прилага в следващия спокоен момент: менюто за пауза, екрана с резултатите или началния екран.

Несиметрията е нарочна. Бързото слизане и бавното възстановяване пречат на резолюцията да скача нагоре-надолу на всеки няколко секунди, което разсейва повече от малко по-мека картина. Скритите раздели и ръчната настройка изключват целия механизъм.

#Какво показаха числата

Мерим със скрипт, който отваря готовата игра в браузър без прозорец на истинска видеокарта, кара балона и записва кадрите в секунда за всеки район и ниво. На Intel HD 630, типичната видеокарта на служебен лаптоп, ниското ниво държеше 59 до 60 кадъра в секунда при 1366 на 768 и 53 до 58 при 1920 на 1080. По-ранен преглед на този клас чипове показа средно ниво с 28 до 31 кадъра и ниско с 47 до 57, затова тогава тези чипове започваха на ниско.

Най-полезното откритие изобщо не беше за 3D. Профилирането показа, че информацията на екрана, рисувана върху 2D платно, се прерисуваше при всеки кадър, дори когато нищо по нея не се е променило, и на слабите лаптопи точно това се оказа истинският разход. Решението беше ключ, съставен от всичко, което тази информация показва, закръглено до това, което окото може да види; платното се прерисува само когато ключът се промени. След тази промяна HD и UHD чиповете държаха 60 кадъра в секунда на средно ниво при резолюциите на лаптопите, а началното правило по-горе беше вдигнато съответно. Мерете, преди да режете красивите неща.

#По-проста версия за по-малки игри

Не всяка игра има нужда от всичко това. Нашата арена игра Faultwarden ползва по-леко правило: брои кадрите в прозорци от четири секунди по време на игра и слиза едно ниво след два поредни бавни прозореца под 42 кадъра в секунда, никога заради едно единствено засичане. За игра с кратки рундове и малка сцена това стига. Частите, които си струва да пазите във всяка версия: определете какво променя всяко ниво, преценявайте устойчивия брой кадри, а не отделни кадри, никога не преизграждайте по време на действие, запомнете резултата и винаги оставяйте ръчна настройка за играчите, които знаят по-добре.

За основите на 3D в браузъра вижте браузърни игри с Three.js и WebGL, а за това как правилата да не зависят от броя кадри, цикъл на игра с фиксирана стъпка в JavaScript. Billowpost е безплатна и е обявена като „Очаквайте скоро“ в каталога с игри на PN Scripts.

#Често задавани въпроси

Може ли уеб страница да разбере каква видеокарта има играчът?

Обикновено да, чрез разширението WEBGL_debug_renderer_info на WebGL. Някои браузъри връщат общо или опростено име заради поверителността, затова го ползвайте като начална подсказка и мерете истинския брой кадри.

Защо нивото на графиката не се сменя по време на игра?

Новото ниво преизгражда материалите и компилира шейдъри, което замразява играта за миг. По време на игра сменяйте само резолюцията на рисуването, а новото ниво прилагайте при пауза, меню или екран с резултати.

Към колко кадъра в секунда да се цели автоматичният режим?

Ние слизаме ниво надолу под 50 кадъра в секунда на началния екран и приемаме 58 или повече за запас. Преценявайте средни стойности за няколко секунди, никога един бавен кадър.

Кое струва най-много на вградената графика?

По нашите измервания: броят на пикселите, сенките в реално време и обработката на целия екран, и, изненадващо, 2D платно за интерфейса, прерисувано при всеки кадър. Ограничете съотношението на пикселите, обновявайте сенките през няколко кадъра и прерисувайте интерфейса само когато се промени.

#Източници

Коментари

Коментари

Напишете първия коментар.

Оставете коментар

Следваща стъпка

pnscripts.com/bg/contact

Пишете на екипа

Попитайте за статия или ни разкажете за проект, който искате да изградим. Отговаряме до един работен ден.

Пишете ни

Семейството PN Scripts

Другите сайтове на PN Scripts

Хостингът, игрите и блогът имат свои сайтове, поддържани от същата компания.

  • pnscripts.com

    PN Scripts

    Софтуерно инженерство

    Уеб и мобилни приложения и API по поръчка, плюс нашите продукти и плъгини с отворен код.

  • games.pnscripts.com

    Игри

    Игри и игрови сървъри

    Домът на игрите на PN Scripts: безплатни браузърни игри, които се играят веднага, а игровите сървъри предстоят.

  • hosting.pnscripts.com

    Хостинг

    Хостинг и инфраструктура

    Споделен хостинг, KVM VPS, самостоятелни сървъри и домейни от същата компания, която изработва проекта ви.

  • blog.pnscripts.com

    Блог

    Статии и бележки

    Практични статии за разработка на софтуер, хостинг, отворен код и игри, писани от хората, които ги създават.

    Вие сте тук