OpenGL Pixel Shader: как сгенерировать случайную матрицу нулей и единиц (для каждого пикселя)?

Так что мне нужно просто: каждый раз, когда мы выполняем наш шейдер (то есть для каждого пикселя), мне нужно вычислять случайную матрицу 1s и 0s с resolution == originalImageResolution. Как это сделать?

На данный момент я создал один для shadertoy, разрешение случайной матрицы здесь установлено как 15 на 15. потому что графический процессор заставляет хром часто падать, когда я пробую такие вещи, как 200 на 200, хотя мне действительно нужен размер полного разрешения изображения

#ifdef GL_ES
precision highp float;
#endif

uniform vec2 resolution;
uniform float time;
uniform sampler2D tex0;

float rand(vec2 co){
    return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * (43758.5453+ time));
}
vec3 getOne(){
    vec2 p =  gl_FragCoord.xy / resolution.xy;
    vec3 one;
    for(int i=0;i<15;i++){
        for(int j=0;j<15;j++){
            if(rand(p)<=0.5)
                one = (one.xyz + texture2D(tex0,vec2(j,i)).xyz)/2.0;
        }
    }
    return one;
}

void main(void)
{
    gl_FragColor = vec4(getOne(),1.0);
}

И еще один для Adobe Pixel Bender:

<languageVersion: 1.0;> 

kernel random
<   namespace : "Random";
    vendor : "Kabumbus";
    version : 3;
    description : "not as random as needed, not as fast as needed"; >
{

    input image4 src;
    output float4 outputColor;

float rand(float2 co, float2 co2){
    return fract(sin(dot(co.xy ,float2(12.9898,78.233))) * (43758.5453 + (co2.x + co2.y )));
}

float4 getOne(){
    float4 one;
    float2 r = outCoord();
    for(int i=0;i<200;i++){
        for(int j=0;j<200;j++){
            if(rand(r, float2(i,j))>=1.0)
                one = (one + sampleLinear(src,float2(j,i)))/2.0;
        }
    }
    return one;
}
void
evaluatePixel()
{
    float4 oc = getOne();
    outputColor = oc;
}
}

Итак, моя настоящая проблема в том, что мои шейдеры приводят к падению моего графического процессора. Как использовать GLSL для той же цели, что и я, но без сбоев и, если возможно, быстрее?

Обновление: то, что я хочу создать, называется однопиксельным Камера (google Compressive Imaging или Compressive Sensing), я хочу создать программную реализацию на основе графического процессора.

Идея проста:

  • у нас есть изображение - NxM.
  • for each pixel in image we want GPU to performe the next operations:
    • to generate NxMmatrix of random values - 0s and 1s.
    • вычислить среднее арифметическое всех пикселей исходного изображения, координаты которых соответствуют координатам 1s в нашем случайном NxM матрица
    • вывести результат среднего арифметического в виде цвета пикселя.

В своих шейдерах я пытался имитировать этот осторожный процесс.

Что на самом деле глупо пытаться сделать это на gpu:

  • Compressive Sensing не требует от нас вычислять NxM матрицу таких средних арифметических значений, он требует лишь небольшого количества этого (например, 1/3). Так что я оказываю давление на GPU, которое мне не нужно. Однако тестирование большего количества данных - не всегда плохая идея.

person Rella    schedule 07.06.2011    source источник
comment
возможный дубликат функций случайного / шума для GLSL   -  person genpfault    schedule 07.06.2011
comment
Вам нужна действительно случайная функция, т.е. разная каждый раз, когда вы ее вызываете, или она должна быть предсказуемой, как шум Перлина?   -  person LarsH    schedule 08.06.2011
comment
Вы хотите сказать, что хотите рассчитывать новую матрицу для каждого пикселя ?? или просто случайное значение для каждого пикселя (которое будет накапливаться в матрицу случайных значений)?   -  person LarsH    schedule 08.06.2011
comment
@all: Я предоставил образцы, которые, надеюсь, объясняют, почему мне нужно создать матрицу с полностью случайным разрешением и как я хочу ее использовать.   -  person Rella    schedule 08.06.2011
comment
Под originalImageResolution вы имеете в виду разрешение входной текстуры (tex0), а не разрешение выходного изображения? P.S. +1 за Shader Toy!   -  person LarsH    schedule 08.06.2011
comment
@genpfault, это не дубликат 4200224. OP уже использует функцию шума, поэтому он не ищет реализацию функции шума.   -  person LarsH    schedule 08.06.2011
comment
Извините, если я туплю, но я просто хочу подтвердить: нужна ли вам другая случайная матрица NxM для использования с каждым пикселем, или можно предварительно вычислить эту матрицу один раз на кадр и передать это к шейдеру?   -  person LarsH    schedule 09.06.2011
comment
@LarsH: да - другая случайная матрица NxM для использования с каждым пикселем ... или мы можем предварительно вычислить случайные матрицы NxM ... =)   -  person Rella    schedule 10.06.2011
comment
@Kabumbus - Я обновил свой ответ в ответ.   -  person LarsH    schedule 10.06.2011


Ответы (1)


Спасибо, что добавили более подробную информацию, чтобы прояснить ваш вопрос. Мои комментарии становятся слишком длинными, поэтому я собираюсь ответить. Перемещение комментариев сюда, чтобы держать их вместе:

Извините за медленную работу, но я пытаюсь понять проблему и цель. В вашем примере GLSL я не вижу генерируемой матрицы. Я вижу, что один vec3 генерируется путем суммирования случайного выбора (меняющегося во времени) ячеек из текстуры (матрицы) 15 x 15. И этот vec3 пересчитывается для каждого пикселя. Затем в качестве цвета пикселя используется vec3.

Поэтому я не понимаю, действительно ли вы хотите создать матрицу или просто хотите вычислить значение для каждого пикселя. Последний в некотором смысле является «матрицей», но вычисление простого случайного значения для 200 x 200 пикселей не вызовет нагрузку на ваш графический драйвер. Также вы сказали, что хотите использовать матрицу. Так что я не думаю, что вы имеете в виду.

Я пытаюсь понять, зачем вам матрица - чтобы сохранить последовательную случайную основу для всех пикселей? Если это так, вы можете либо предварительно вычислить случайную текстуру, либо использовать последовательную псевдослучайную функцию, как в rand (), за исключением того, что время не используется. Вы четко об этом знаете, так что, думаю, я все еще не понимаю цель. Почему вы суммируете случайный выбор ячеек текстуры для каждого пикселя?

Я считаю, что причина сбоя вашего шейдера в том, что ваша main() функция превышает свой временной лимит - либо для одного пикселя, либо для всего набора пикселей. Вызов rand() 40 000 раз на пиксель (во вложенном цикле 200 * 200), безусловно, может объяснить это! Если у вас было 200 x 200 пикселей, и вы вызываете sin () 40k раз для каждого из них, это 160 000 000 вызовов на кадр. Бедный GPU!

Я надеюсь, что если мы лучше поймем цель, мы сможем порекомендовать более эффективный способ добиться желаемого эффекта.

Обновить.

(Эта часть удалена, так как она была ошибочной. Даже несмотря на то, что каждая из многих ячеек в исходной матрице может вносить в результат меньше, чем визуально определяемое количество цвета, общее количество ячеек может вносить визуально определяемое количество цвета.)

Новое обновление на основе обновленного вопроса.

Хорошо (думая здесь "вслух", чтобы вы могли проверить, правильно ли я понимаю ...) Поскольку вам нужно каждое из случайных значений NxM только один раз, нет необходимости хранить их в матрице; значения можно просто вычислить по запросу, а затем выбросить. Вот почему приведенный выше пример кода на самом деле не генерирует матрицу.

Это означает, что мы не можем уйти от генерации (NxM) ^ 2 случайных значений на кадр, то есть NxM случайных значений на пиксель, а есть NxM пикселей. Итак, для N = M = 200 это 160 миллионов случайных значений на кадр.

Однако мы все еще можем оптимизировать некоторые вещи.

  • Во-первых, поскольку ваши случайные значения должны быть только одним битом каждое (вам нужен только логический ответ, чтобы решить, включать ли каждую ячейку из исходной текстуры в микс), вы, вероятно, можете использовать более дешевый генератор псевдослучайных чисел. Тот, который вы используете, выводит гораздо больше случайных данных за вызов, чем один бит. Например, вы можете вызвать ту же функцию ГПСЧ, которую используете сейчас, но сохранить значение и извлечь из него 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), что, вероятно, относительно дорого, если только компилятор и графический процессор не могут оптимизировать ее до битового сдвига (возможно ли это для плавающей запятой?). Это также не даст среднего арифметического входных значений, как обсуждалось выше ... это придаст гораздо больший вес более поздним значениям и очень мало более ранним. В качестве решения подсчитайте, сколько значений включается, и разделите на это количество один раз после завершения цикла.

Я не знаю, будет ли этих оптимизаций достаточно, чтобы позволить вашему драйверу графического процессора управлять 200x200 * 200x200 пикселей на кадр. Они определенно должны позволить вам существенно увеличить разрешение.

Это идеи, которые приходят мне в голову. Впрочем, я далек от того, чтобы быть экспертом по GPU. Было бы здорово, если бы кто-то более квалифицированный мог бы присоединиться к вам с предложениями.

P.S. В своем комментарии вы в шутку (?) Упомянули возможность предварительного вычисления N * M NxM случайных матриц. Может это неплохая идея ?? 40,000x40,000 - это большая текстура (не менее 40 МБ), но если вы храните 32 бита случайных данных на ячейку, это сводится к 1250 x 40,000 ячеек. Жаль, что ванильный GLSL не поможет вам с побитовыми операторами для извлечения данных, но даже если у вас нет расширения GL_EXT_gpu_shader4, вы все равно можете подделать его. (Может быть, тогда для неквадратных текстур вам также понадобится специальное расширение?)

person LarsH    schedule 08.06.2011
comment
Большое спасибо за вашу поддержку!))) Пост обновлен. Надеюсь, это прояснит то, что я пытаюсь делать. - person Rella; 09.06.2011
comment
@Kabumbus: вау, я не слышал об однопиксельных камерах / сжатии. Мне нужно будет изучить ваш обновленный вопрос и посмотреть, смогу ли я предложить какие-либо предложения. - person LarsH; 09.06.2011