Unity镜头光晕模拟开源库

【博物纳新】是UWA旨在为开发者推荐新颖、易用、有趣的开源项目,帮助你们在项目研发之余发现世界上的热门项目、前沿技术或者使人惊叹的视觉效果,并探索将其应用到本身项目的可行性。不少时候,咱们并不知道本身想要什么,直到某一天咱们遇到了它。html

更多精彩内容请关注:lab.uwa4d.com性能


此开源库的镜头光晕效果是由Pseudo Lens Flare简化修改的Unity版本。本文主要分析了Lens Flare开源库的大体实现过程及部分代码解读。spa

效果展现

开源库连接:https://lab.uwa4d.com/lab/5b564072d7f10a201fd8d451code


效果实现

以示例项目为例,下图展现了光晕效果的主要产生过程,通过了下采样、Ghost、半径扭曲、散射重影和两次虚化效果,最后叠加原始图像获得最终效果。
orm

一、Downsampling/Thresholdhtm

第一步,将原始图像作一次下采样,同时经过参数_Sub控制只保留画面中亮的部分,经过参数_Mul调节保留亮度(默认参数_Mul=0.5)。blog

fixed4 frag (v2f i) : SV_Target
{
    fixed4 col = tex2D(_MainTex, i.uv);
    col = max(col-_Sub, 0);
    col *= _Mul;
    return col;
}

相似于原Blog中的第一步效果:
图片

二、Ghosts开发

这一步模拟光晕效果中的斑点,经过三个参数能够控制斑点的个数、扩散和衰减。如下为参数调节的效果图及Shader部分代码。
rem

fixed4 frag(v2f i) : SV_Target
{
    fixed4 col = tex2D(_MainTex, i.uv);
    float2 uv = i.uv - float2(0.5, 0.5);
    for (int k = 3; k < _NumGhost + 3; k++) {
        if (k & 1) {
            col += tex2D(_MainTex, _Displace * -uv / (k >> 1) + float2(0.5, 0.5));
        }
        else {
            col += tex2D(_MainTex, uv / (k >> 1) + float2(0.5, 0.5));
            }
    }
    col *= pow(1 - length(uv) / .707, _Falloff);
    return col;
}

三、RadialWarp

这一步是用于模拟一个外部的光环,首先根据须要的光环半径HaloWidth计算获得一个半径扭曲的图像,再添加光环的衰减效果。便可获得一个根据原图像移动的光环效果。

fixed4 frag(v2f i) : SV_Target
{
    fixed4 col = fixed4(0,0,0,0);
    
    float2 ghostVec = i.uv - .5;
    //归一化后减光环半径获得光环顶点位置
    float2 haloVec = normalize(ghostVec)*-_HaloWidth;
    //根据光环位置获得每一个像素的权重,为一个白色的圆环
    float weight = length(float2(0.5, 0.5) - (i.uv + haloVec)) / .707;
    //添加衰减效果
    weight = pow(1.0 - weight, _HaloFalloff);
    col += tex2D(_MainTex, i.uv + haloVec) * weight;
    col = max(0, col - _HaloSub);
    return col;
}

四、Aberration

将第2步和第3步的图像叠加,便可获得一个初步成型的光晕效果图(下图左)。这一步要模拟出光线的失真效果(下图右)。

以下,为计算色彩失真的Shader核心计算代码,其中_ChromaticAberration_Spectrum是一个1x3的三像素RGB图像。

fixed4 frag (v2f i) : SV_Target
{
    //计算失真位置
    float2 coords = 2.0 * i.uv - 1.0;
    float2 end = i.uv - coords * _ChromaticAberration_Amount;
    
    //uv差值
    float2 diff = end - i.uv;
    //失真采样像素数
    int samples = clamp(int(length(_MainTex_TexelSize.zw * diff / 2.0)), 3, 16);
    //每一个像素的uv差
    float2 delta = diff / samples;
    float2 pos = i.uv;
    half3 sum = (0.0).xxx, filterSum = (0.0).xxx;


    //循环采样计算失真像素点的uv和色值
    for (int i = 0; i < samples; i++)
    {
        half t = (i + 0.5) / samples;
        half3 s = tex2Dlod(_MainTex, float4(pos, 0, 0)).rgb;
        half3 filter = tex2Dlod(_ChromaticAberration_Spectrum, float4(t, 0, 0, 0)).rgb;


        sum += s * filter;
        filterSum += filter;
        pos += delta;
    }


    return float4(sum / filterSum, 1);
}

最后将获得的图像作两次Blur效果,再与原图像混合后便可获得镜头光晕的模拟效果。


小结

本文主要分析了Lens Flare开源库的大体实现过程及部分代码解读。因为目前的版本效果运用了大量的后处理,渲染开销较高,在移动端性能较差,并不建议直接在移动端使用。但其模拟的镜头光晕效果逼真,建议有须要的朋友能够一试。


快用UWA Lab合辑Mark好项目!

请输入图片描述

今天的推荐就到这儿啦,或者它可直接使用,或者它须要您的润色,或者它启发了您的思路......

请不要吝啬您的点赞和转发,让咱们知道咱们在作对的事。固然若是您能够留言给出宝贵的意见,咱们会越作越好。

相关文章
相关标签/搜索