Спасибо за добавление более подробной информации, чтобы уточнить ваш вопрос.Мои комментарии становятся слишком длинными, поэтому я собираюсь ответить.Перемещая комментарии сюда, чтобы сохранить их вместе:
Извините, что медлительный, но я пытаюсь понять проблему и цель.В вашем примере GLSL я не вижу генерируемой матрицы.Я вижу, что один vec3 генерируется путем суммирования случайного (изменяющегося во времени) ячеек из текстуры 15х15 (матрицы).И это vec3 пересчитывается для каждого пикселя.Тогда vec3 используется в качестве цвета пикселя.
Так что мне не ясно, действительно ли вы хотите создать матрицу или просто хотите вычислить значение для каждого пикселя.Последний в некотором смысле является «матрицей», но вычисление простого случайного значения для 200 x 200 пикселей не будет напрягать ваш графический драйвер.Также вы сказали, что хотите использовать матрицу.Поэтому я не думаю, что это то, что вы имеете в виду.
Я пытаюсь понять, зачем вам матрица - чтобы сохранить согласованную случайную основу для всех пикселей?Если это так, вы можете либо предварительно вычислить случайную текстуру, либо использовать непротиворечивую псевдослучайную функцию, как в rand (), но не использовать время.Вы четко знаете об этом, так что, думаю, я до сих пор не понимаю цели.Почему вы суммируете случайный выбор ячеек из текстуры для каждого пикселя?
Я полагаю, что причина сбоя вашего шейдера в том, что ваша функция main()
превышает ограничение по времени - либо для одного пикселя,или для всего набора пикселей.Вызов rand()
40000 раз на пиксель (во вложенном цикле 200 * 200), безусловно, может объяснить это!Если у вас было 200 x 200 пикселей, и вы вызываете sin () по 40 000 раз для каждого, это 160 000 000 вызовов на кадр.Плохой графический процессор!
Я надеюсь, что если мы лучше поймем цель, мы сможем порекомендовать более эффективный способ получить желаемый эффект.
Обновление.
(Удалил эту часть, так как она была ошибочной. Даже если многие ячейки в исходной матрице могут вносить в результат меньше, чем визуально определяемое количество цвета, общее количество ячеек может внести вкладвизуально определяемое количество цвета.)
Новое обновление на основе обновленного вопроса.
ОК, (подумав вслух), чтобы вы могли проверить,правильное понимание ...) Так как каждое из случайных значений NxM нужно только один раз, нет необходимости хранить их в матрице;значения могут быть просто вычислены по требованию и затем выброшены.Вот почему приведенный выше пример кода на самом деле не генерирует матрицу.
Это означает, что мы не можем избежать генерации (NxM) ^ 2 случайных значений на кадр, то есть NxM случайных значений на пиксель и NxMпиксели.Таким образом, для N = M = 200 это 160 миллионов случайных значений на кадр.
Однако , мы все же можем оптимизировать некоторые вещи.
- Во-первых, так как вашслучайные значения должны иметь только один бит (вам нужен только логический ответ, чтобы решить, включать ли каждую ячейку из исходной текстуры в микс), вы, вероятно, можете использовать более дешевый генератор псевдослучайных чисел.Тот, который вы используете, выдает гораздо больше случайных данных за вызов, чем один бит.Например, вы можете вызвать ту же функцию PRNG, что и сейчас, но сохранить значение и извлечь из него 32 случайных бита.Или, по крайней мере, несколько, в зависимости от того, сколько достаточно случайно.Кроме того, вместо использования функции sin (), если у вас есть расширение GL_EXT_gpu_shader4 (для побитовых операторов), вы можете использовать что-то вроде этого :
.
int LFSR_Rand_Gen(in int n)
{
// <<, ^ and & require GL_EXT_gpu_shader4.
n = (n << 13) ^ n;
return (n * (n*n*15731+789221) + 1376312589) & 0x7fffffff;
}
- Во-вторых, вы в настоящее время выполняете одну операцию деления для каждой включенной ячейки (
/2.0
), что, вероятно, относительно дорого, если только компилятор и графический процессор не могут оптимизировать его до сдвига битов (возможно ли это для плавающей запятой?) , Это также не даст арифметического среднего значения входных значений, как обсуждалось выше ... это придаст гораздо больший вес более поздним значениям и очень мало - более ранним. В качестве решения следует вести подсчет количества включаемых значений и разделить его на один раз после завершения цикла.
Достаточно ли этих оптимизаций для того, чтобы драйвер GPU мог обрабатывать 200x200 * 200x200 пикселей на кадр, я не знаю. Они определенно должны позволить вам существенно увеличить разрешение.
Это идеи, которые приходят мне в голову. Я далеко не эксперт по GPU. Было бы замечательно, если бы кто-то более квалифицированный мог присоединиться к предложениям.
P.S. В своем комментарии вы в шутку (?) Упомянули возможность предварительного вычисления N * M NxM случайных матриц. Может быть, это не плохая идея? 40,000x40,000 - это большая текстура (не менее 40 МБ), но если вы сохраняете 32 бита случайных данных на ячейку, то получается 1250 x 40000 ячеек. Жаль, что ванильный GLSL не поможет вам с побитовыми операторами извлекать данные, но даже если у вас нет расширения GL_EXT_gpu_shader4, вы все равно можете его подделать. (Может быть, вам также понадобится специальное расширение для неквадратных текстур?)