Я пытаюсь нарисовать набор Мандельброта. Я создал алгоритм на CPU, но теперь я хочу воспроизвести его на GPU, но код ведет себя по-другому.
В программе CPU, в какой-то момент, я беру std :: abs ( z), где z - комплексное число, и запишите значение в зеленый канал на экране.
В графическом процессоре я беру тот же z и вызываю следующую функцию (Vulkan, GLSL):
double module(dvec2 z) {
return sqrt(z.x * z.x + z.y * z.y);
}
double color(z) {
return module(z);
}
Когда я записываю цвет (z) в зеленый канал, я получаю ту же самую картинку, что и для программы ЦП, поэтому код работает точно так же, по крайней мере, до этого момента.
Затем я изменил код процессора, взяв вместо него std::log(std::abs(z)) / 20
и поместив его в зеленый канал. Это изображение, которое я получаю (номера в наборе Мандельброта окрашены в белый цвет): ![enter image description here](https://i.stack.imgur.com/NjM1g.png)
Вы можете видеть, что зеленый цвет никогда не обрезается, поэтому результат для каждого pixel находится где-то в диапазоне (0, 1).
Затем я изменил код графического процессора следующим образом:
double module(dvec2 z) {
return sqrt(z.x * z.x + z.y * z.y);
}
double color(z) {
return log(module(z));
}
Я написал color(z) / 20
в зеленый канал. Это результирующее изображение: ![enter image description here](https://i.stack.imgur.com/craoY.png)
Как видите, значение color(z) / 20
должно быть <= 0. Я попытался изменить функцию <code>color на это:
double color(z) {
return -log(module(z));
}
Чтобы увидеть, было ли значение 0 или отрицательным. Я все еще получил то же изображение, поэтому значение должно быть 0. Чтобы подтвердить это, я снова изменяю код, теперь на этот:
double color(z) {
return log(module(z)) + 0.5;
}
и записал color(z)
в зеленый канал (отбрасывая деление на 20). Я ожидал, что результат будет среднего зеленого цвета.
К моему удивлению, изображение не изменилось, пиксели все еще были черными.
Озадаченный, я вернул изменение к оригиналу:
double color(z) {
return log(module(z));
}
но я написал color(z) + 0.5
в зеленый канал и получил это: ![enter image description here](https://i.stack.imgur.com/dBN85.png)
Подводя итог, кажется, что log(module(z))
возвращая какое-то неопределенное значение. Если вы отрицаете это или пытаетесь добавить что-либо к нему, оно остается неопределенным. Когда это значение возвращается из функции, которая имеет double
в качестве возвращаемого типа, возвращаемое значение равно 0, которое теперь можно добавить к.
Почему это происходит? Функция module(z)
гарантированно возвращает положительное число, поэтому функция журнала должна возвращать действительный результат. Определения std::log
и GLSL log
являются натуральным логарифмом аргумента, поэтому значение должно быть точно таким же (игнорируя ошибку точности).
Как заставить GLSL log
вести себя правильно?