由于这里的人提供了一些提示,我现在有了一个不错的发光着色器。粒子的定义

很多时候,如果粒子移动很多,它看起来就像一张彩色纸。下图放大了,因此您可以看到更多的清晰度,但是缩小并实时地看起来就像是一张纸。


#2粒子看起来不就像它们是霓虹灯一样

我的意思是我不希望效果如此巨大,但是当它们组合在一起时,我希望它们在辉光中具有白色突出显示。
像这样:

当粒子组合在一起时,它看起来应该更像这样(这只是一个以更大的对比度混合它的添加副本的样机)[但是奇异粒子不应该具有白色亮点]:


这是我当前的渲染过程:

我有几个带有纹理附件的FBO:


并条机:永不清除,为了抗锯齿目的而进行了放大
较小的机架:清除了每帧,屏幕的精确分辨率,在其上绘制了最暗的部分绘制了并条机
水平模糊:清除e每个帧,进行水平模糊处理(分辨率低于屏幕)
垂直模糊:清除每帧,垂直模糊水平模糊处理(分辨率低于屏幕)
前缓冲区:绘制较小的帧和垂直缓冲区因此,一个典型的渲染可能看起来像这样(我为未对齐和裁剪表示歉意,Xcode框架调试器允许您窥视FBO,但不导出纹理在其中必须使用屏幕截图)对于这两次模糊,我正在使用这样的代码,其中很多都是预先计算的,但是为了便于阅读,我写了我的计算方式。

gl_FragColor = vec4(clamp(texture2D(s_texture, v_texcoord).xyz, 0.,
1.) + (clamp(texture2D(s_texture2, v_texcoord).xyz, 0., 1.) * 1.5),
1.0);


现在,虽然问题可能出在我如何计算模糊并将其结合在一起,但我认为问题更可能在于我渲染粒子的方式。基本上,每个粒子的每个帧都用一个圆形和一个矩形渲染。点标记位置,矩形将其连接到上一帧。

这里是一个过程图,每个新的色相组代表一个新的帧,对不起颜色的幼稚外观。



我使用两个绘制调用来执行此操作,一个绘制矩形(带有索引的GL_TRIANGLES),另一个绘制圆(外部alpha设为0的GL_POINTS)。 br />
虽然这使我可以快速模拟累积缓冲区,但它也有一些缺点,如果可以在不影响速度的情况下进行处理,那么更改它们将是不错的选择。


没有实际的深度排序,尽管粒子很容易具有z值,但它是徒劳的,因为如果不清除每个帧的深度缓冲区,则opengles 2.0会变黑,因此它不能真正与累积缓冲区一起使用。
没有附加绘图


因为有两个单独的绘制调用,即使在该设置上没有设置似乎也无法在同一绘制ca中进行附加绘制ll
即使我做圆和矩形相遇的区域也会特别明亮,这是不希望的。



我尝试的加法模式是

float Gaussian(float x, float deviation)
{
    return (1.0 / sqrt(2.0 * 3.141592 * deviation)) * exp(-((x * x) / (2.0 * deviation)));
}
vec3 blurS15()

{
    vec3 blr = vec3(0.0);

    float scalart =  (1 / screenResolution.x) * (1.0 / 7.0) * 14.0;
    float deviationScale = 1.2;
    float finalScalar = 1.1;

    blr += texture2D(s_texture, (v_texcoord + vec2(7.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(7.0, 7.0 * deviationScale) ;
    blr += texture2D(s_texture, (v_texcoord + vec2(6.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(6.0, 7.0 * deviationScale) ;
    blr += texture2D(s_texture, (v_texcoord + vec2(5.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(5.0, 7.0 * deviationScale) ;
    blr += texture2D(s_texture, (v_texcoord + vec2(4.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(4.0, 7.0 * deviationScale) ;
    blr += texture2D(s_texture, (v_texcoord + vec2(3.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(3.0, 7.0 * deviationScale) ;
    blr += texture2D(s_texture, (v_texcoord + vec2(2.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(2.0, 7.0 * deviationScale) ;
    blr += texture2D(s_texture, (v_texcoord + vec2(1.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(1.0, 7.0 * deviationScale) ;


    blr += texture2D(s_texture, (v_texcoord + vec2(0.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(0.0, 7.0 * deviationScale) ;


    blr += texture2D(s_texture, (v_texcoord + vec2(-1.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(-1.0, 7.0 * deviationScale) ;
    blr += texture2D(s_texture, (v_texcoord + vec2(-2.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(-2.0, 7.0 * deviationScale) ;
    blr += texture2D(s_texture, (v_texcoord + vec2(-3.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(-3.0, 7.0 * deviationScale) ;
    blr += texture2D(s_texture, (v_texcoord + vec2(-4.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(-4.0, 7.0 * deviationScale) ;
    blr += texture2D(s_texture, (v_texcoord + vec2(-5.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(-5.0, 7.0 * deviationScale) ;
    blr += texture2D(s_texture, (v_texcoord + vec2(-6.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(-6.0, 7.0 * deviationScale) ;
    blr += texture2D(s_texture, (v_texcoord + vec2(-7.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(-7.0, 7.0 * deviationScale) ;

    return blr; //This gets put into gl_FragColor
}


具体来说,当我说它不起作用时,我尝试在淡入淡出之前将其禁用,然后在之后启用它。这几乎使一切看上去都怪异,好像没有任何踪迹。而且似乎没有相交的亮点。但是,如果我一直启用它,那么它看起来确实像是添加剂混合。只有前一帧永不褪色,因为您无法在添加混合模式下绘制黑色。更好,请让我知道。

我很好奇是否还有一种方法可以使用累积缓冲区进行深度排序/不必清除深度缓冲区。

#1 楼

为了使堆积的粒子达到“白色”发光效果,您可能应该切换到HDR渲染,并使色调映射运算符使“过亮”像素去饱和。因此,您将需要一个更高精度的浮点渲染目标(例如RGBA1010102或RGBA16F)以及一个后处理步骤,以将其降低到LDR系统的后台缓冲区。然后只要确保碰撞的粒子加起来就足够高的颜色值(即超过1.0),并且色调映射器就可以解决问题。

使用ping-渲染目标的乒乓图案:


将帧0渲染到FBOA。
将帧1渲染到FBO B,以FBO A作为历史(即迄今为止的累积)输入。
将第2帧渲染到FBO A,以FBO B作为历史输入。
从第2点开始重复。粒子会留下类似的痕迹。查看Brian Karis关于虚幻引擎4的时间超采样的演示-幻灯片15-17描述了基于移动平均的混合加权。

评论


$ \ begingroup $
对于您的最后评论,您是说应该将移动平均值用于模拟累积缓冲区吗?您是否错过了绘制全屏黑色四边形以“擦除”缓冲区以免缓冲区爆裂成白色的步骤?
$ \ endgroup $
–user3412
16年7月15日在6:16

$ \ begingroup $
实际上,应该通过移动平均线来解决。如果新像素的值为:gl_FragColor =权重*当前+(1.0-权重)*历史记录然后注意,通过减小权重的原理,随着时间的推移,对特定帧最终图像的贡献将随时间简单地接近零,从而逐渐消失。无需清除RT,然后只需用每个乒乓球将其覆盖即可。
$ \ endgroup $
–引文
16年7月15日在8:03



$ \ begingroup $
这与Alpha混合不一样吗?
$ \ endgroup $
–PaulHK
16年7月22日在6:38

$ \ begingroup $
只要您不需要积累Alpha,它的确如此,因为您可以在Alpha通道中添加权重。
$ \ endgroup $
–引文
16年7月22日在12:30