如何在Unity中为白天/夜晚循环混合2个光照贴图?


16

在我再说什么之前:我正在使用双重光照贴图,这意味着我需要混合一个近距离和一个远距离。

因此,我已经为此工作了一段时间,我为渲染器和照明设置了一个昼/夜循环,并且一切工作正常,并且不占用大量流程。

我唯一的问题是弄清楚如何将两个光照贴图混合在一起,我已经找到了如何切换光照贴图的方法,但是问题是看起来有点突然,并且中断了体验。

我已经进行了数小时的研究,尝试了各种着色器,逐像素混合以及其他所有方法,但均无济于事。依我的喜好,C#中的逐像素混合实际上是一个过程密集型过程,尽管我仍在努力清理它并使它运行更平稳。着色器看起来很有前途,但是我找不到能够正确融合两个光照贴图的着色器。

有人在我如何实现这一目标方面有什么线索吗?我只需要在白天和夜间的光照贴图之间进行某种平滑的过渡即可。也许我可以覆盖两个纹理并使用Alpha通道?或类似的东西?


如果您拥有Pro,也许可以将两个光照贴图纹理渲染为第三个纹理,然后将此第三个纹理用作光照贴图?那应该像像素融合一样,但是速度要快得多。
没关系

我有专业版。我将如何一起渲染两个光照贴图纹理?这是我的主要负责人,但是我一直在尝试找出实现它的代码/过程。
蒂莫西·威廉姆斯

嗯,创建一种混合两个纹理的材质,用于Graphics.Blit()渲染吗?我从来没有做过,但是在手册中,它应该可以工作。
没关系

因此,创建一种可以将两个纹理混合到输出的新材质,应用Afar-1和Bfar-1,然后将出站纹理用于lightmap变量吗?
蒂莫西·威廉姆斯

是的,类似的东西。我已经测试过了,但目前无法访问Pro版本。
没关系

Answers:


3

因此,我最近尝试了这一点,遇到了很多同样的问题。渲染纹理解决方案有点像鲱鱼。我能够在单独的线程上使用多线程像素操作来解决它。

https://www.youtube.com/watch?v=T_zpFk1mdCI

因此,通常人们会使用graphics.blit()渲染纹理并将其传递到需要去的任何地方,但是光照贴图数据不支持纹理,它们需要texture2ds。下一步的逻辑步骤是将数据复制到texture2d,然后将其输入到光照贴图数据。该技术破坏了帧速率,因为它使GPU无法将数据发送到CPU,而不仅仅是对数据的引用。

解决方案是不使用GPU。

光照贴图过渡时间很长,因此在每一帧更新光照贴图并不一定重要。事实上,玩家可能不会注意到光照图是否仅在游戏时间每20-40分钟更新一次。

因此,您要做的是将任务分配给每个光照贴图的单独线程上的CPU。

通常,Unity不支持多线程。但这没关系,C#可以。这个家伙在解释Unity中的多线程方面做得非常出色,因此,如果您从未听说过它,或者不知道如何在Unity中进行多线程,请看以下视频:

https://www.youtube.com/watch?v=ja63QO1Imck

您需要做的是创建一个工作线程类,以更改Color数组中的光照贴图像素数据的副本,然后创建一个blend函数。

从一种颜色到另一种颜色的简单lerp即可。

然后创建线程,启动它,并在单独的线程中完成所有光照贴图后,您可以将像素数据复制回光照贴图数据texture2d中。

我在下面发布了一些示例代码。它当然不是完全实现的版本,但是向您展示了创建类,创建线程并设置lightdata的主要概念。

您还需要做的其他事情是经常调用函数以触发更新光照贴图。另外,您还必须在启动时或编译时将所有像素数据复制到worker类中。祝发现这个的人好运。我认为操作人员的生活已经继续前进,但是我知道其他有类似问题的人可能会偶然发现这一点。

public class work
{
    Color[] fromPixels;
    Color[] toPixels;

    public float LerpValue = 0;
    public bool Finished = false;
    public Color[] mixedPixels;

    public work(Color[] FromPix, Color[] ToPix)
    {
        fromPixels= FromPix;
        toPixels= ToPix;
        Finished = false;
        mixedPixels = new Color[FromPix.Length];
    }
    public void DoWork()
    {
        for (int x = 0; x < fromPixels.Length; x++)
        {
            mixedPixels[x] = Color.Lerp(fromPixels[x], toPixels[x], LerpValue);
        }
        Finished = true;
    }
}

IEnumerator LightMapSet()
{
    Thread workerThread = new Thread(someworker.DoWork);
    someworker.LerpValue = lerpValue;
    workerThread.Start();
    yield return new WaitUntil(() => someworker.Finished);
    mixedMap.SetPixels(someworker.mixedPixels);
    mixedMap.Apply(true);
    LightmapData someLightmapData;
    someLightmapData.lightmapColor = mixedMap;
    lightDatas = { someLightmapData};
    LightmapSettings.lightmaps = lightDatas;
}

1

有一个Skybox着色器,在两组Skybox纹理之间混合。想想白天和黑夜的循环!

如果要通过脚本构建或动画化天空盒,请使用skyboxmaterial.SetFloat("_Blend", yourBlend)更改混合;否则,请执行以下操作。也可以使用SetTexture材质功能来设置或更改纹理。

有关昼夜周期的视频教程:http : //www.youtube.com/watch?v=FTfv9JhkmIA

示例代码如下:

Shader "RenderFX/Skybox Blended" {
Properties {
    _Tint ("Tint Color", Color) = (.5, .5, .5, .5)
    _Blend ("Blend", Range(0.0,1.0)) = 0.5
    _FrontTex ("Front (+Z)", 2D) = "white" {}
    _BackTex ("Back (-Z)", 2D) = "white" {}
    _LeftTex ("Left (+X)", 2D) = "white" {}
    _RightTex ("Right (-X)", 2D) = "white" {}
    _UpTex ("Up (+Y)", 2D) = "white" {}
    _DownTex ("Down (-Y)", 2D) = "white" {}
    _FrontTex2("2 Front (+Z)", 2D) = "white" {}
    _BackTex2("2 Back (-Z)", 2D) = "white" {}
    _LeftTex2("2 Left (+X)", 2D) = "white" {}
    _RightTex2("2 Right (-X)", 2D) = "white" {}
    _UpTex2("2 Up (+Y)", 2D) = "white" {}
    _DownTex2("2 Down (-Y)", 2D) = "white" {}
}

SubShader {
    Tags { "Queue" = "Background" }
    Cull Off
    Fog { Mode Off }
    Lighting Off        
    Color [_Tint]
    Pass {
        SetTexture [_FrontTex] { combine texture }
        SetTexture [_FrontTex2] { constantColor (0,0,0,[_Blend]) combine texture lerp(constant) previous }
        SetTexture [_FrontTex2] { combine previous +- primary, previous * primary }
    }
    Pass {
        SetTexture [_BackTex] { combine texture }
        SetTexture [_BackTex2] { constantColor (0,0,0,[_Blend]) combine texture lerp(constant) previous }
        SetTexture [_BackTex2] { combine previous +- primary, previous * primary }
    }
    Pass {
        SetTexture [_LeftTex] { combine texture }
        SetTexture [_LeftTex2] { constantColor (0,0,0,[_Blend]) combine texture lerp(constant) previous }
        SetTexture [_LeftTex2] { combine previous +- primary, previous * primary }
    }
    Pass {
        SetTexture [_RightTex] { combine texture }
        SetTexture [_RightTex2] { constantColor (0,0,0,[_Blend]) combine texture lerp(constant) previous }
        SetTexture [_RightTex2] { combine previous +- primary, previous * primary }
    }
    Pass {
        SetTexture [_UpTex] { combine texture }
        SetTexture [_UpTex2] { constantColor (0,0,0,[_Blend]) combine texture lerp(constant) previous }
        SetTexture [_UpTex2] { combine previous +- primary, previous * primary }
    }
    Pass {
        SetTexture [_DownTex] { combine texture }
        SetTexture [_DownTex2] { constantColor (0,0,0,[_Blend]) combine texture lerp(constant) previous }
        SetTexture [_DownTex2] { combine previous +- primary, previous * primary }
    }
}

Fallback "RenderFX/Skybox", 1
}

2
该问题询问的是光照贴图,而不是Skybox。不过,感谢您提供的链接,这对我来说很有用。
jhocking

0

如果您知道如何切换,为什么不继续在后台线程上创建多个过渡光照贴图,然后在光照贴图准备就绪时启用过渡呢?

您还可以在AssetStore上查看有趣的资产:https ://www.assetstore.unity3d.com/zh-CN/#! / content/5674

我猜它包括了光照贴图的融合,尽管我不知道怎么做。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.