如何扩大光绽的半径?

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

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

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

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 的解释似乎是模拟这种情况的合理方法。无论如何,这不是我想要实现的目标。我想独立于大小/强度等来控制绽放的“梯度”部分的半径。的来源。我希望能够在屏幕中心设置一个白色(最大值)像素,并让花朵按照我想要的方式生长,到达屏幕边缘或超出我的感觉.

javascript algorithm graphics effects
3个回答
0
投票

为了获得良好的光晕效果,您应该使用高动态范围渲染。不然你的白色会不够亮。

其原因是像素亮度通常用 [0,1] 范围表示。因此,最大亮度被限制为 1。然而,在现实世界中,并没有真正的最大值。尽管真正明亮的光都被感知为“1”,但像绽放这样的视觉副作用并不相同。

所以你要做的就是允许真正明亮的区域超过最大亮度,至少对于光晕卷积来说是这样。然后,当您进行渲染时,根据需要限制值。

完成此操作后,您应该能够通过增加卷积中使用的艾里斑的大小来增加光晕半径。


0
投票

tskuzzy 的答案的简单总结是:使用浮点缓冲区来存储预绽放图像,然后卷积到第二个浮点缓冲区(此时您将像素饱和回整数格式)或动态饱和到在将每个输出像素直接存储到整数输出缓冲区之前,将其转换回整数。

Airy 卷积必须在余量下完成(即以定点或浮点形式进行,而如今前者通常不值得为如此常见的快速 FPU 所麻烦),以便图像中较亮的点会相应地渗色更多超过他们的邻近地区。

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


0
投票

创建任意半径的光绽放效果确实是可能的,但需要仔细考虑和实施。您可以探索以下一些技术来实现这一目标:

Multi-pass Blur: Implement a multi-pass Gaussian blur algorithm. Start with a small blur radius and gradually increase it in subsequent passes until you reach the desired bloom radius. Each pass of the blur operation will contribute to the overall bloom effect, allowing you to control the size dynamically.

Variable Kernel Size: Instead of using a fixed-size kernel for Gaussian blur, you can create a variable-sized kernel based on the desired bloom radius. By dynamically adjusting the kernel size, you can achieve bloom effects of different sizes.

Downsampling and Upsampling: Apply downsampling (reducing the resolution of the image) before the blur operation to speed up the process. After blurring, upsample the image to its original resolution. This technique can help achieve larger bloom radii with better performance.
© www.soinside.com 2019 - 2024. All rights reserved.