如何扩大光照的半径?

时间:2012-07-12 02:42:38

标签: javascript algorithm graphics effects

我正在编写一个软件过滤器对象并试图实现一个光照效果。我使用简单的双通道卷积方法,除了效果半径很小,我似乎无法控制半径外,效果很好。我使用较大的盒式滤镜并调整了各种像素的重量,但似乎没有任何效果。效果似乎具有最大尺寸(不是很大),然后对参数的所有更改都会使其变小。

我希望能够创建一个任意半径的光照绽放。经过大量的实验和在线搜索后,我开始怀疑这是否无法完成。我一直在考虑替代方法 - 等离子体,渐变和各种播种方案 - 但我想首先将这条路径追到地面。有没有人知道如何创建一个任意大小的光绽放(在软件中)?

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;
}

也许我在原始问题中遗漏的重要一点是要解释我并不是要模拟任何真实或特定的现象(而且它可能并没有帮助我称之为&#34 ;光&#34;绽放)。可能是,当处理真实光现象时,为了获得具有任意半径的半影,您需要具有任意半径的源(即,#34;完全饱和的区域&#34;)。如果这实际上是一个真正的光绽放表现的方式,那么吉姆和tskuzzy的解释似乎是模拟它的合理方法。无论如何,这不是我想要完成的事情。我想控制&#34;渐变的半径&#34;绽放的一部分与大小/强度/等无关。来源。我希望能够在屏幕中央设置一个单一的白色(最大值)像素,并根据我的需要将花朵扩展到屏幕的边缘,如果我觉得喜欢它。

2 个答案:

答案 0 :(得分:0)

为了获得良好的绽放效果,您应该使用high-dynamic range rendering。否则,你的白人就不够亮了。

其原因是像素亮度通常由范围[0,1]表示。因此,最大亮度被钳制为1.然而,在现实世界中,实际上并非最大亮度。虽然真正明亮的灯光都被视为&#34; 1&#34;但像绽放的视觉副作用却不尽相同。

所以你需要做的是让真正明亮的区域超过最大亮度,至少对于绽放卷积。然后,当您进行渲染时,根据需要钳制值。

完成后,您应该能够通过增加卷积中使用的Airy disk的大小来增加布隆半径。

答案 1 :(得分:0)

tskuzzy的答案的简单总结是:使用浮点缓冲区存储预绽放图像,并卷入第二个浮点缓冲区(从而使像素饱和成整数格式)或者直接将每个输出像素转换回整数,然后将其直接存储在整数输出缓冲区中。

Airy卷积必须使用净空(即固定点或浮点数,现在前者通常不值得用快速FPU这么常见的麻烦),以便图像中的亮点将在邻近地区相应地流血。

注意:颜色的动态饱和度并不像单独剪切通道一样简单 - 如果这样做,最终可能会出现色调失真以及剪辑点周围的轮廓。