Этот пост является продолжением серии постов о WebGL. Первый начался с основ. и предыдущий был о 3D камерах. Если вы не читали их, пожалуйста, просмотрите их сначала.
Как мы анимируем что-то в WebGL?
На самом деле это не специфично для WebGL, но вообще, если вы хотите анимировать что-то в JavaScript, вам нужно изменить что-то со временем и нарисовать снова.
Мы можем взять один из наших предыдущих примеров и анимировать его следующим образом.
*var fieldOfViewRadians = degToRad(60);
*var rotationSpeed = 1.2;
*requestAnimationFrame(drawScene);
// Рисуем сцену.
function drawScene() {
* // Каждый кадр увеличиваем вращение немного.
* rotation[1] += rotationSpeed / 60.0;
...
* // Вызываем drawScene снова в следующем кадре
* requestAnimationFrame(drawScene);
}
И вот это
Есть тонкая проблема, однако. Код выше имеет
rotationSpeed / 60.0
. Мы разделили на 60.0, потому что предположили, что браузер
будет отвечать на requestAnimationFrame 60 раз в секунду, что довольно распространено.
Это на самом деле не валидное предположение, однако. Может быть, пользователь на маломощном устройстве, как старый смартфон. Или может быть, пользователь запускает какую-то тяжелую программу в фоне. Есть все виды причин, по которым браузер может не отображать кадры со скоростью 60 кадров в секунду. Может быть, это 2020 год, и все машины работают на 240 кадрах в секунду сейчас. Может быть, пользователь - геймер и имеет CRT монитор, работающий на 90 кадрах в секунду.
Вы можете увидеть проблему в этом примере
В примере выше мы хотим вращать все ‘F’ с одинаковой скоростью. ‘F’ в середине работает на полной скорости и не зависит от частоты кадров. Тот, что слева и справа, симулируют, если бы браузер работал только на 1/8 максимальной скорости для текущей машины. Тот, что слева, НЕ зависит от частоты кадров. Тот, что справа, ЗАВИСИТ от частоты кадров.
Обратите внимание, что поскольку тот, что слева, не учитывает, что частота кадров может быть медленной, он не поспевает. Тот, что справа, однако, даже though он работает на 1/8 частоты кадров, он поспевает за тем, что в середине, работающим на полной скорости.
Способ сделать анимацию независимой от частоты кадров - это вычислить, сколько времени потребовалось между кадрами, и использовать это для вычисления, сколько анимировать в этом кадре.
Сначала нам нужно получить время. К счастью, requestAnimationFrame
передает
нам время с момента загрузки страницы, когда он вызывает нас.
Я нахожу это легче всего, если мы получаем время в секундах, но поскольку requestAnimationFrame
передает нам время в миллисекундах (тысячных долях секунды), нам нужно умножить на 0.001,
чтобы получить секунды.
Итак, мы можем затем вычислить дельта-время так
*var then = 0;
requestAnimationFrame(drawScene);
// Рисуем сцену.
*function drawScene(now) {
* // Преобразуем время в секунды
* now *= 0.001;
* // Вычитаем предыдущее время из текущего времени
* var deltaTime = now - then;
* // Запоминаем текущее время для следующего кадра.
* then = now;
...
Как только у нас есть deltaTime
в секундах, тогда все наши вычисления могут быть в том, сколько
единиц в секунду мы хотим, чтобы что-то происходило. В этом случае
rotationSpeed
равен 1.2, что означает, что мы хотим вращать 1.2 радиана в секунду.
Это примерно 1/5 оборота, или другими словами, потребуется около 5 секунд, чтобы
обернуться полностью, независимо от частоты кадров.
* rotation[1] += rotationSpeed * deltaTime;
Вот это работает.
Вы вряд ли увидите разницу с тем, что вверху этой страницы, если вы не на медленной машине, но если вы не делаете ваши анимации независимыми от частоты кадров, у вас, вероятно, будут некоторые пользователи, которые получают очень другой опыт, чем вы планировали.
Далее как применять текстуры.