Я встановив деякий FPS-вимірювальний код у WebGL (на основі цієї відповіді ТА ) і виявив деякі диваки з виконанням мого фрагмента шейдера. Код просто видає один квадратик (а точніше два трикутники) на полотні розміром 1024x1024, тому вся магія відбувається в шейдері фрагмента.
Розглянемо цей простий шейдер (GLSL; вершина шейдера - лише прохідний):
// some definitions
void main() {
float seed = uSeed;
float x = vPos.x;
float y = vPos.y;
float value = 1.0;
// Nothing to see here...
gl_FragColor = vec4(value, value, value, 1.0);
}
Тож це просто робить біле полотно. На моїй машині він складає в середньому близько 30 кадрів в секунду.
Тепер давайте збільшимо число хрускоту і обчислимо кожен фрагмент на основі декількох октав шуму, що залежить від положення:
void main() {
float seed = uSeed;
float x = vPos.x;
float y = vPos.y;
float value = 1.0;
float noise;
for ( int j=0; j<10; ++j)
{
noise = 0.0;
for ( int i=4; i>0; i-- )
{
float oct = pow(2.0,float(i));
noise += snoise(vec2(mod(seed,13.0)+x*oct,mod(seed*seed,11.0)+y*oct))/oct*4.0;
}
}
value = noise/2.0+0.5;
gl_FragColor = vec4(value, value, value, 1.0);
}
Якщо ви хочете запустити вищевказаний код, я використовував цю реалізаціюsnoise
.
Це зводить fps до чогось типу 7. Це має сенс.
Тепер дивна частина ... давайте обчислимо лише один з кожні 16 фрагментів як шум, а інші залишимо білими, обернувши обчислення шуму в такі умови:
if (int(mod(x*512.0,4.0)) == 0 && int(mod(y*512.0,4.0)) == 0)) {
// same noise computation
}
Ви б очікували, що це буде набагато швидше, але це все ще лише 7 кадрів в секунду.
Для ще одного тесту давайте замість цього фільтрувати пікселі за наступними умовними:
if (x > 0.5 && y > 0.5) {
// same noise computation
}
Це дає точно таку ж кількість шумових пікселів, як і раніше, але зараз ми набрали майже 30 кадрів в секунду.
Що тут відбувається? Чи не повинні два способи відфільтрувати 16-ту пікселів дають стільки ж циклів? І чому повільніша така ж повільна, як і всі пікселі, як шум?
Питання про бонус: Що я можу зробити з цього приводу? Чи є спосіб , щоб працювати навколо жахливої продуктивності , якщо я на самому ділі дійсно хочу спекл мого полотна з допомогою всього кілька дорогих фрагментів?
(Просто для впевненості, я підтвердив, що фактичні обчислення модуля взагалі не впливають на частоту кадрів, рендерінг кожного 16-го пікселя замість білого.)