如何扩大光晕的半径? [英] How can I expand the radius of a light bloom?

查看:120
本文介绍了如何扩大光晕的半径?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个软件过滤器对象,并试图实现一个光晕效果.我正在使用一种简单的两遍卷积方法,除了效果半径很小而且我似乎无法控制半径之外,该方法效果很好.我玩过较大的框式滤镜,并调整了各种像素的权重,但似乎没有任何效果.效果似乎具有最大大小(不是很大),然后对参数的所有更改都只是使其变小.

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

javascript如下(在HTML5画布上运行):

I am writing a software filter object and trying to implement a light bloom effect. I''m using a simple, two pass convolution approach which works fine except that the effect radius is tiny and I can''t seem to control the radius. I''ve played with larger box filters and adjusted the weights of the various pixels, but none of that seems to have any effect. The effect seems to have a maximum size (which is not very big) and then all changes to the parameters just serve to make it smaller.

I''d like to be able to create a light bloom with an arbitrary radius. After a LOT of experimentation and searching online, I''m starting to wonder if this just can''t be done. I''ve been thinking about alternate approaches--plasmas, gradients, and various seeding schemes--but I''d like to hound this path into the ground first. Does anyone out there know how to create an arbitrarily sized light bloom (in software)?

The javascript is as follows (this operates on an HTML5 canvas):

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

推荐答案

我看不出这段代码有什么问题(拒绝测试除外-见下文).它确实在RGBA图像(按此顺序存储的组件)上实现了可分离的7x7框滤镜.

盒式滤镜具有很强的模糊效果,其大小恰好等于内核的大小,您会发现其效果随半径的增加而增加.成正比.更改系数确实可以降低模糊,但是对于非常偏斜的分布(例如接近高斯的二项式1 6 15 20 15 6 1),这将变得明显.

如果采用这种方式,则均匀滤波器的运行时间与半径成正比.对于大半径,这可能会变慢.您可以通过积分图像技巧( http://en.wikipedia.org/wiki/Summed_area_table [ ^ ]).

关于测试
我不同意这样的事实,即两次通过它们是相同的,而我在第二次通过中看到了一个问题:没有什么可以阻止index-(pitch*3)为负数.

我的解决方案是将索引转换为一对坐标((index%pitch)/4, index/pitch),并在添加偏移量后检查它们是否保持在各自的范围[0..pitch/4[[0..length/pitch[中.对于2r+1 x 2r+1过滤器,这导致以下条件:

第一遍:
I see nothing wrong with this code (except the rejection tests - see below). It does implement a separable 7x7 box filter on an RGBA image (components stored in this order).

The box filter has a strong blurring effect that has exactly the size of the kernel and you will see its effect increasing with the radius. Directly proportional. Changing the coefficients will indeed lower the blur but this will become noticeable for very skewed distributions (like the Binomial 1 6 15 20 15 6 1, which approximates a Gaussian).

The running time of the uniform filter, when implemented this way, is proportional to the radius. This can get slow for large radii. You can do better by means of the integral image trick (http://en.wikipedia.org/wiki/Summed_area_table[^]).

About the tests
I disagree with the fact that they are identical for the two passes and I see a problem in the second pass: nothing prevents index-(pitch*3) to be negative, among others.

My solution would be to convert the index to the pair of coordinates ((index%pitch)/4, index/pitch), and check if they remain in their respective range [0..pitch/4[ and [0..length/pitch[ after offsets are added. This leads to the following conditions, for the 2r+1 x 2r+1 filter:

First pass:
index%4 == 3 || (index%pitch)/4 - r < 0 || (index%pitch)/4 + r >= pitch/4



第二遍:



Second pass:

index%4 == 3 || index/pitch - r < 0 || index/pitch + r >= length/pitch


这篇关于如何扩大光晕的半径?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆