GLSL日志返回一个未定义的结果

问题描述 投票:0回答:1

我试图绘制曼德尔布罗特集。我已经在CPU上创建了算法,但现在我想在GPU上重现它,但代码表现不同。

在CPU程序中,有一点,我取std::abs(z),其中z是一个复数,并将其值写在屏幕上的绿色通道中。

在GPU上,我取相同的z并调用以下函数(Vulkan,GLSL)。

double module(dvec2 z) {
    return sqrt(z.x * z.x + z.y * z.y);
}

double color(z) {
    return module(z);
}

当我把color(z)写进绿色通道时,我得到的画面和CPU程序得到的画面是一样的,所以代码的工作原理完全一样,至少在这一点上是一样的。

接下来,我把CPU代码改成了以 std::log(std::abs(z)) / 20 并把它放在绿色通道中。这就是我得到的图像(在曼德尔布罗特集合中的nubmers被染成白色)。enter image description here

你可以看到绿色从来没有被剪切过 所以每个像素的结果都是在某个范围内(0,1)。

然后我把GPU代码改成这样。

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

正如你所看到的 color(z) / 20 必须是<=0。我试着把 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

综上所述,似乎... log(module(z)) 正在返回一些未定义的值。如果你否定它或试图在它上面添加任何东西,它仍然是未定义的。当这个值从一个有类似于 double 作为返回类型,返回的值是0,现在可以加到。

为什么会出现这种情况呢?函数 module(z) 是保证返回一个正数,所以log函数应该返回一个有效的结果。这两个函数的定义是 std::logGLSL log 是参数的自然对数,所以值应该是完全一样的(忽略精度误差)。

我如何使 GLSL log 乖不乖?

c++ glsl vulkan
1个回答
1
投票

原来GPU并不太喜欢你让它计算一个很大的数字的log。据我所知,log(实际上是ln)是以taylor系列的形式实现的。这是不幸的,因为它包含了n个成员的n次幂的多项式。

然而,如果你有一个数字表示为 x = mantissa * 2^exp,你可以得到 ln(x) 由以下公式得出。

ln(x) = exp * ln(2) + ln(mantissa)

不管x是什么,mantissa应该明显小一些。这是一个片段着色器的函数。

float ln(float z) {
    int integerValue = floatBitsToInt(z);
    int exp = ((integerValue >> mantissaBits) & (1 << expBits) - 1)
              - ((1 << (expBits - 1)) - 1);

    integerValue |= ((1 << expBits) - 1) << mantissaBits;
    integerValue &= ~(1 << (mantissaBits + expBits - 1));

    return exp * log2 + log(intBitsToFloat(integerValue));
}

请注意,在GLSL中,这个技巧只适用于floats--没有64位的积分类型,因此也没有doubleBitsToLong,反之亦然。

© www.soinside.com 2019 - 2024. All rights reserved.