OpenGL двойное переполнение - PullRequest
2 голосов
/ 06 октября 2019

У меня есть двойной 'радиус' = 2.0E-45, когда я установил его на ~ 2.0E-46, коллапс вычисления приведет к белому экрану. Кажется, проблема в переполнении. Я написал тот же алгоритм, но с использованием nubma cuda и f64 (двойной точности) 'radius'. И все работает отлично. Я использую текстурный буфер f32 для 'глубины_array' (для этого нет типа dp float64), но реализация numba прекрасно работает с f32, а реализация opengl также работает до тех пор, пока радиус не станет больше, чем ~ 2.0E-46. Почему реализация numba работает, а opengl нет? Я хочу придерживаться OpenGL. Есть ли возможность исправить это?

Я ставлю только части, которые используют «радиус». Все остальные переменные имеют двойной тип. (код грязный и просто царапина)

#version 150
#extension GL_ARB_gpu_shader_fp64 : enable

double radius = 2.0E-45;

...

dvec2 pixel = dvec2(gl_FragCoord.xy) + dvec2(-0.5+(double(x)+0.5)/double(AA),-0.5+(double(y)+0.5)/double(AA));
dvec2 c = pixel/dvec2(width, height) * dvec2(radius, radius) + dvec2(-radius/2, -radius/2);
color.rgb += sample(c);

...

vec3 sample(dvec2 dn)
    {
        vec3 color = vec3(0.0,0.0,0.0);
        dvec2 d0 = dn;

        double zn_size = 0.0;
        int i = 0;
        while (i < depth)
        {
            int x = i % depth;
            dvec2 value = dvec2(texelFetch(depth_array, x).rg);
            dn = complex_mul(dn, value + dn);
            dn = dn + d0;

            i++;
            x = i % depth;
            value = dvec2(texelFetch(depth_array, x).rg);
            dvec2 zn = value * 0.5 + dn;

            zn_size = dot(zn, zn);
            if (zn_size > r)
            {
                double fraciter = (zn_size-r)/(r2-r);
                double iter = double(i) - fraciter;
                double m = sqrt(iter)*mul*2.0;

                color = sin(vec3(.1, .15, .2)*float(m)*0.5)*.5+0.5;
                break;
            }
        }
        return color;
    }

1 Ответ

2 голосов
/ 06 октября 2019

В GLSL буквенное значение 2.0E-45 имеет тип float. Это означает, что значение будет сжато в допустимый диапазон float до того, как будет присвоено значение.

Если вы хотите, чтобы литерал был double, тогда оннеобходимо использовать правильный суффикс: 2.0E-45lf.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...