Unity에서 주야간주기를 위해 2 개의 라이트 맵을 어떻게 블렌딩합니까? 프로세스 집약적이지

다른 말을하기 전에 : 듀얼 라이트 맵을 사용하고 있습니다. 이는 근거리와 원거리를 혼합해야한다는 의미입니다.

그래서 나는 이것을 잠시 동안 노력해 왔으며, 렌더러와 조명을 위해 하루 종일주기를 설정했으며 모든 것이 잘 작동하고 프로세스 집약적이지 않습니다.

내가 가지고있는 유일한 문제는 두 개의 라이트 맵을 어떻게 혼합 할 수 있는지 파악하는 것입니다. 라이트 맵을 전환하는 방법을 알아 냈지만 문제는 갑작스럽게 보이고 경험을 방해한다는 것입니다.

나는 이것에 대해 몇 시간 동안 연구를 해 왔으며 모든 종류의 쉐이더, 픽셀 단위 블렌딩 및 그 밖의 모든 것을 시도해 보았습니다. C #의 픽셀 단위 블렌딩은 원하는대로 약간의 프로세스 집약적 인 것으로 판명되었지만 여전히 깨끗하게 정리하고 더 원활하게 실행하고 있습니다. 셰이더는 유망 해 보였지만 두 개의 라이트 맵을 올바르게 혼합 할 수있는 셰이더를 찾을 수 없었습니다.

누구든지 내가 이것을 달성 할 수있는 방법에 대한 리드가 있습니까? 낮과 밤의 라이트 맵 사이에 부드러운 전환이 필요합니다. 아마도 두 텍스처를 오버레이하고 알파 채널을 사용할 수 있습니까? 아니면 그런가요?



답변

그래서 나는 최근에 이것에 손을 대어 너희들과 같은 많은 문제에 부딪쳤다. 렌더 텍스처 솔루션은 약간의 청어입니다. 별도의 스레드에서 멀티 스레딩 픽셀 조작을 사용하여 해결할 수있었습니다.

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

따라서 일반적으로 graphics.blit()렌더 텍스쳐를 사용하여 필요한 곳으로 전달하지만 라이트 맵 데이터는 텍스쳐를 지원하지 않으므로 texture2ds가 필요합니다. 다음 논리적 단계는 데이터를 texture2d에 복사 한 다음 라이트 맵 데이터에 공급하는 것입니다. 이 기술은 데이터에 대한 참조가 아니라 CPU에 데이터를 전송하기 위해 GPU를 정지시키기 때문에 프레임 속도를 떨어 뜨립니다.

해결책은 GPU를 사용하지 않는 것입니다.

라이트 맵 전환은 오랜 시간 동안 발생하므로 프레임마다 라이트 맵을 업데이트해야하는 것은 아닙니다. 사실, 플레이어는 게임 시간에 20-40 분마다 라이트 맵이 업데이트되었는지 알지 못할 것입니다.

그래서 당신이하는 일은 각 라이트 맵에 대해 별도의 스레드에서 CPU로 작업을 발행하는 것입니다.

일반적으로 Unity는 멀티 스레딩을 지원하지 않습니다. 그러나 괜찮습니다, C #은 그렇습니다. 이 사람은 Unity에서 멀티 스레딩을 설명하는 경이로운 작업을 수행하므로, 들어 본 적이 없거나 Unity에서 멀티 스레딩하는 방법을 모르는 경우 비디오입니다.

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

컬러 배열에서 라이트 맵 픽셀 데이터의 복사본을 변경하는 작업자 스레드 클래스를 만든 다음 블렌드 함수를 만들기 만하면됩니다.

한 색상에서 다음 색상으로 간단한 뛰기.

그런 다음 스레드를 만들고 시작한 다음 모든 라이트 맵이 별도의 스레드에서 완료되면 픽셀 데이터를 다시 라이트 맵 데이터 texture2d에 복사 할 수 있습니다.

아래에 예제 코드를 게시했습니다. 완전히 구현 된 버전은 아니지만 클래스 만들기, 스레드 만들기 및 라이트 데이터 설정의 주요 개념을 보여줍니다.

당신이해야 할 다른 일은 라이트 맵 업데이트를 트리거하기 위해 너무 자주 함수를 호출하는 것입니다. 또한 시작하거나 컴파일 할 때 모든 픽셀 데이터를 작업자 클래스로 복사해야합니다. 이것을 찾는 사람에게 행운을 빕니다. 나는 작전이 그들의 삶과 함께 움직 였다고 생각하지만 비슷한 문제를 가진 다른 사람들이 이것에 걸려 넘어 질 수 있다는 것을 알고 있습니다.

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

답변

두 세트의 스카이 박스 텍스처를 혼합하는 스카이 박스 셰이더가 있습니다. 낮과 밤의주기를 생각하십시오!

스크립트에서 스카이 박스를 만들거나 애니메이션으로 만들려면을 사용 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
}

답변

전환하는 방법을 알고 있다면 백그라운드 스레드에서 여러 전환 라이트 맵을 만든 다음 라이트 맵이 준비되면 전환을 활성화하지 않겠습니까?

AssetStore에서 흥미로운 자산을 살펴볼 수도 있습니다 :
https://www.assetstore.unity3d.com/en/#!/content/5674

어떻게 해야할지 모르겠지만 라이트 맵 블렌딩이 포함되어 있다고 생각합니다.