Atualização do motor
Ei! Já faz um tempo que não postei um DevLog. Só queria postar brevemente sobre minha experiência de atualização de mecanismo para Unity.
Há muitos anos que uso o Unity 2019.4 LTS – e como planejamos lançar o jogo em consoles modernos, achei que period hora de uma grande atualização do motor.
Originalmente, eu não pretendia atualizar para o Unity 6 por causa de seu modelo de receita. No entanto, para benefício de todos (incluindo a Unity), felizmente, isso foi revertido em setembro.
Decidi modernizar totalmente o Desolus para rodar no Unity 6, então não terei que me preocupar muito com isso mais tarde, quando o jogo realmente for lançado.
No entanto, como a atualização do mecanismo durou cerca de 5 anos de alterações no código do Unity, decidi fazê-lo em um processo gradual e atualizei primeiro para 2022 LTS.
—
Unidade 2019 LTS -> Unidade 2022 LTS
Se você leu meu DevLog, sabe que o Desolus está sendo executado em um Scriptable Render Pipeline personalizado que eu mesmo escrevi. Felizmente, Catlike Coding possui uma vasta documentação sobre como escrever seu próprio pipeline, e eles também tinham um guia Unity 2019 -> 2022 para atualização.
O processo de atualização de 2022 foi praticamente indolor – apenas algumas atualizações simples de API para algumas coisas. No entanto, emblem percebi que, uma vez compilado o jogo, *todos os shaders do jogo estavam quebrados.* Não apenas estavam quebrados, mas eu estava recebendo um erro ambíguo de ‘sintaxe inválida’ no arquivo de nível superior em meus shaders.
Aparentemente, a causa foi que, em algum lugar entre o Unity 2019 e o Unity 2022, a sintaxe dos comentários mudou?
Na verdade, não havia nada de errado com meu código, exceto que COMMENT estava causando um erro de análise no compilador.
Levei cerca de duas horas batendo a cabeça contra a parede, mas finalmente consegui descobrir essa mudança obscura e fiz o Unity 2022 funcionar bem.
—
Unidade 2022 LTS -> Unidade 6
A atualização do Unity 6 foi mais desafiadora do que a atualização do Unity 2022.
Novamente, as diferenças da API C# eram bastante triviais, mas acabei tendo dificuldades por causa de uma alteração obscura de shader.
Eu uso o SpeedTree para Desolus há muitos anos. No entanto, como estou usando um SRP personalizado, tive que transferir o sombreador SpeedTree para meu próprio pipeline de renderização.
Tudo é traduzido para HLSL. No entanto, existe um arquivo de inclusão obscuro dos tempos antigos no qual eu ainda confiava, chamado SpeedTreeWind.cginc. Isso é interno ao Unity. Não sei onde existe e não está disponível publicamente no Repositório gráfico Unity.
Eu estava recebendo algum tipo de erro de compilação com este arquivo, que é interno e não pode ser editado, então tive que desenterrá-lo nas profundezas da Web e traduzi-lo do código de shader CG para HLSL.
Depois disso, consegui compilar o shader SpeedTree, mas percebi que não havia vento! Isso funcionou bem durante a atualização de 2022, então algo deve ter mudado do Unity 2022 para o Unity 6.
Lutando para consertar isso, investiguei o repositório interno do Unity para a história dos shaders SpeedTree, e fixei a mudança exata neste commit.
Ainda um pouco perplexo, mandei uma mensagem para o Desenvolvedor da Unity Applied sciences que criou essas alterações. Ele foi gentil o suficiente em responder (obrigado Volkan!) Ele descreveu como o sistema eólico mudou entre o Unity 2022 e o Unity 6.
Consegui resolver o problema através de algumas modificações adicionais em meu shader SpeedTree e, assim, a atualização do Unity 6 foi concluída!
—
Mudanças no SRP: correções de textura e otimizações de memória
Decidi, enquanto ainda estava no meio da minha base de código, que também faria algumas otimizações em meu pipeline de renderização.
Se você ainda não viu minha palestra no Desolus SRP, recomendo assistir!
Mergulhando nas mudanças que fiz em um quadro:
—
Mudança na forma como as normais são armazenadas na passagem de profundidade/normais.
Anteriormente, cometi um erro ao armazenar minhas normais do espaço mundial.
As normais do espaço mundial são um vetor que existe no intervalo (-1,-1,-1) a (1,1,1), os valores que são armazenados no canal Vermelho/Verde/Azul.
Porque eu estava armazenando os valores em um RGBAHMeia texturapresumi que os valores negativos seriam armazenados corretamente e isso period suportado pelo formato de textura.
Porém, não foi esse o caso, os valores estavam sendo limitados ao intervalo (0,0,0) a (1,1,1).
Isso causou um erro em vários shaders posteriores no pipeline que dependiam das normais do espaço mundial, já que metade dos valores estavam efetivamente ausentes e definidos como 0.
O que acabei fazendo foi criar uma função pack/unpack, que remapeia os normais do intervalo (-1,-1,-1) a (1,1,1) para o intervalo (0,0,0) a (1 ,1,1), para que os valores possam ser armazenados corretamente na textura. Quando preciso dos normais posteriormente no pipeline, o processo inverso é feito para mapear os normais de volta aos seus valores originais.
Embora se possa argumentar que há uma perda de precisão, a diferença é nominal e os valores corretos fazem uma grande diferença na correção de erros visuais.
—
Mudanças no funcionamento do Display Area Reflection
Fiz algumas otimizações em como meu A reflexão do espaço da tela funciona.
Anteriormente, eu tinha uma passagem adicional de ‘SSR de profundidade’ para objetos, que period usada para corrigir artefatos no SSR.
O que isso fez foi efetivamente definir um intervalo nos valores do buffer de profundidade, para que o SSR não chegasse ao fundo do poço e causasse enormes quantidades de artefatos gráficos.
Felizmente, consegui eliminar totalmente essa passagem corrigindo bugs na maneira como meu sombreador SSR lidava com os valores do buffer de profundidade. Efetivamente, o que fiz foi definir um intervalo máximo no qual o buffer de profundidade poderia ser avaliado.
—
Várias otimizações de textura
Anteriormente, eu não period muito preciso com os formatos de textura em meu Scriptable Render Pipeline.
A maioria dos passes period armazenada como um RGBAHalf RenderTexture(o formato de buffer de cores padrão para meu SRP), que na verdade é bastante caro.
Houve ganhos óbvios em passes como o meu ‘Portal Cross’, que desenha apenas um tom de vermelho. Usar um RGBAHalf para armazenar esses dados foi um desperdício complete, quando em vez disso eu poderia ter armazenou a textura como um R8que é apenas uma textura de 8 bits de canal único em vez de uma textura de 16 bits de quatro canais.
Mudei o formato da textura em cerca de cinco a seis passagens diferentes, e isso resultou em uma grande melhoria na VRAM usada no jogo, bem como em um ligeiro aumento na taxa de quadros em geral.
—
Conclusão
No geral, estou muito feliz com o progresso da atualização do mecanismo Unity e da refatoração do SRP. Agora estou totalmente de volta à terra do design de quebra-cabeças!
—