Как мне смешать 2 карты освещения для дневного / ночного цикла в Unity?

16

Прежде чем я скажу что-нибудь еще: я использую двойные карты освещения, что означает, что мне нужно смешать как ближний, так и дальний.

Так что я уже некоторое время работаю над этим, у меня настроен целый день / ночь для рендеров и освещения, и все работает нормально и не требует интенсивного процесса.

Единственная проблема, которая у меня возникла, - это выяснить, как я мог бы смешать два световых карты, я выяснил, как переключать световые карты, но проблема в том, что это выглядит довольно неожиданно и прерывает процесс.

Я провел много исследований по этому вопросу, пробовал все виды шейдеров, попиксельное смешивание и все остальное безрезультатно. Попиксельное смешение в C # оказалось мне немного трудоемким для меня, хотя я все еще работаю над его очисткой и обеспечением более плавной работы. Шейдеры выглядели многообещающе, но я не мог найти шейдер, который мог бы правильно смешать две карты освещения.

У кого-нибудь есть указания на то, как я могу это сделать? Мне просто нужен какой-то плавный переход между дневной и ночной картой освещения. Возможно, я мог бы наложить две текстуры и использовать альфа-канал? Или что-то типа того?

Тимоти Уильямс
источник
Если у вас есть Pro, может быть, вы можете визуализировать две текстуры карты освещения в третью, а затем использовать эту третью текстуру в качестве карты освещения? Это должно быть как смешение пикселей, но значительно быстрее.
Nevermind
У меня есть Pro. Как бы я пошел о рендеринг двух текстур карты света вместе? Это было мое основное руководство, но я пытался выяснить код / ​​процесс для его достижения.
Тимоти Уильямс
Хм, создать материал, который смешивает две текстуры, использовать Graphics.Blit()для его рендеринга? Я никогда не делал этого, но, глядя в руководстве, это должно работать.
Nevermind
Итак, создайте новый материал, который может смешать две текстуры для вывода, применить Afar-1 и Bfar-1, а затем использовать исходящую текстуру для переменной lightmap?
Тимоти Уильямс
Да, что-то в этом роде. Я бы проверил это, но у меня нет доступа к Pro версии на данный момент.
Nevermind

Ответы:

3

Поэтому я недавно попробовал свои силы в этом и столкнулся с множеством тех же проблем, что и у вас, ребята. Решение для рендеринга текстуры - это немного красной сельди. Я смог решить эту проблему, используя многопоточную обработку пикселей в отдельном потоке.

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

Поэтому обычно можно использовать graphics.blit()и передавать текстуру рендеринга куда угодно, но данные карты освещения не поддерживают текстуры, им требуются texture2ds. Следующий логический шаг - скопировать данные в texture2d, а затем передать их в данные карты освещения. Этот метод разрушает частоту кадров, потому что он останавливает GPU для отправки данных в CPU, а не просто для ссылки на данные.

Решение состоит в том, чтобы не использовать графический процессор.

Переходы карты освещения происходят в течение длительного периода времени, поэтому необязательно обновлять карту освещения каждый кадр. На самом деле, игроки, вероятно, не заметят, если световые карты будут обновляться каждые 20-40 минут во время игры.

Итак, что вы делаете, вы запускаете задачу в ЦП в отдельных потоках для каждой карты освещения.

Обычно Unity не поддерживает многопоточность. Но это нормально, C # делает. Этот парень делает феноменальную работу по объяснению многопоточности в Unity, поэтому, если вы никогда не слышали об этом или никогда не знали, как многопоточность в Unity, это видео:

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

Все, что вам нужно сделать, это создать класс рабочего потока, который изменяет копии данных пикселей карты освещения в цветовых массивах, а затем создать функцию наложения.

Подойдет простой переход от одного цвета к другому.

Затем создайте поток, запустите его, и когда все световые карты будут закончены в отдельных потоках, вы сможете скопировать данные пикселей обратно в данные карты освещения texture2d.

Я разместил пример кода ниже. Это, конечно, не полностью реализованная версия, но она показывает вам основные концепции создания класса, создания потока, а затем установки lightdata.

Другие вещи, которые вам нужно будет делать, это вызывать функцию время от времени, чтобы вызвать обновление световых карт. Также вы должны скопировать все данные пикселей в рабочий класс при запуске или во время компиляции. Удачи всем, кто найдет это. Я полагаю, что работа продолжалась с их жизнью, но я знаю, что другие люди с подобными проблемами могут наткнуться на это.

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

Существует шейдер скайбокса, который смешивается между двумя наборами текстур скайбокса. Подумайте день и ночь цикла!

Если вы хотите создать или анимировать скайбокс из скрипта, используйте 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
}
JA Corbal
источник
2
Вопрос задан по поводу лайтмапов, а не скайбоксов. Спасибо за ссылку, похоже, это будет полезно для меня.
Джоккинг
0

Если вы знаете, как переключаться, почему бы не приступить к созданию ряда переходных световых карт в фоновом потоке, а затем включить переходы, когда световые карты будут готовы?

Вы также можете взглянуть на интересный ресурс в AssetStore: https://www.assetstore.unity3d.com/en/#!/content/5674

Я предполагаю, что это включает смешивание световых карт, хотя я не знаю, как это сделать.

tomekkie
источник