1

我正在编写一个软件过滤器对象并尝试实现光晕效果。我正在使用一种简单的两遍卷积方法,除了效果半径很小而且我似乎无法控制半径之外,它工作得很好。我玩过更大的盒子过滤器并调整了各种像素的权重,但这些似乎都没有任何效果。效果似乎有一个最大尺寸(不是很大),然后对参数的所有更改都只是为了使其更小。

我希望能够创建一个任意半径的光晕。经过大量的实验和在线搜索,我开始怀疑这是否无法完成。我一直在考虑替代方法——等离子、梯度和各种播种方案——但我想先把这条路埋在地下。有谁知道如何创建任意大小的光晕(在软件中)?

javascript 如下(这在 HTML5 画布上运行;如果需要,我可以在代码中添加注释):

// the kernel functions are called via Array.map on this.backBuffer.data, a canvas surface color array
this.kernelFirstPass = function(val, index, array)
{
    if(index<pitch || index>=array.length-pitch || index%pitch<4 || index%pitch>pitch-5 || index%4==3)
        return;
    var c = 1,
        l1 = 1,
        l2 = 1,
        l3 = 1,
        r1 = 1,
        r2 = 1,
        r3 = 1;
    var avg =
    (
        c*this.frontBuffer.data[index]+
        l1*this.frontBuffer.data[index-4]+
        l2*this.frontBuffer.data[index-8]+
        l3*this.frontBuffer.data[index-12]+
        l1*this.frontBuffer.data[index+4]+
        l2*this.frontBuffer.data[index+8]+
        l3*this.frontBuffer.data[index+12]
    )/(c+l1+l2+l3+l1+l2+l3);
    //this.frontBuffer.data[index] = avg;
    array[index] = avg;
}
this.kernelSecondPass = function(val, index, array)
{
    if(index<pitch || index>=array.length-pitch || index%pitch<4 || index%pitch>=pitch-4 || index%4==3)
        return;
    var c = 1,
        l1 = 1,
        l2 = 1,
        l3 = 1,
        r1 = 1,
        r2 = 1,
        r3 = 1;
    var avg =
    (
        c*array[index]+
        l1*array[index-pitch]+
        l2*array[index-(pitch*2)]+
        l3*array[index-(pitch*3)]+
        l1*array[index+pitch]+
        l2*array[index+(pitch*2)]+
        l3*array[index+(pitch*3)]
    )/(c+l1+l2+l3+l1+l2+l3);
    array[index] = avg;
}

也许我在最初的问题中遗漏的一个重要点是解释我不是试图模拟任何真实或特定的现象(我称之为“光”绽放可能无济于事)。可能是,在处理真实的光现象时,为了获得具有任意半径的半影,您需要具有任意半径的光源(即“完全饱和区域”)。如果这实际上是真正的光绽放的行为方式,那么 Jim 和 tskuzzy 的解释似乎是模拟这种情况的合理方法。无论如何,这不是我想要完成的。我想独立于大小/强度/等来控制绽放的“渐变”部分的半径。的来源。我希望能够设置一个单一的,

4

2 回答 2

0

In order to achieve a good bloom effect, you should be using high-dynamic range rendering . Otherwise, your whites will not be bright enough.

The reason for this is that pixel brightnesses are typically represented from the range [0,1]. Thus the maximum brightness is clamped to 1. However in a real world situation, there isn't really a maximum. And although really bright lights are all perceived as a "1", the visual side-effects like bloom are not the same.

So what you have to do is allow for really bright areas to exceed the maximum brightness, at least for the bloom convolution. Then when you do the rendering, clamp the values as needed.

Once you have that done, you should be able to increase the bloom radius simply by increasing the size of the Airy disk used in the convolution.

于 2012-07-12T03:52:06.187 回答
0

tkuzzy 的答案的简单总结是:使用浮点缓冲区来存储预开花图像,然后卷积成第二个浮点缓冲区(从那里将像素饱和回整数格式)或动态饱和以转换每个输出像素在将其直接存储在整数输出缓冲区之前返回整数。

Airy 卷积必须使用余量来完成(即在定点或浮点中,现在前者通常不值得为如此常见的快速 FPU 带来麻烦),因此图像中较亮的点会相应地流血更多他们的邻近地区。

注意:颜色的动态饱和度并不像单独裁剪通道那么简单——如果你这样做,你可能会在裁剪的点周围出现色调失真和轮廓。

于 2012-08-14T14:12:39.130 回答