Visão Geral Técnica
Last updated
Last updated
O Needle Engine consiste grosso modo em três partes:
um número de components e ferramentas que lhe permitem configurar cenas para o Needle Engine a partir, por exemplo, do Unity Editor.
um exporter que transforma dados de cena e component em glTF.
um runtime web que carrega e executa os ficheiros glTF produzidos e as suas extensions.
O runtime web usa three.js para rendering, adiciona um sistema de component sobre o scene graph do three e liga loaders de extension para as nossas glTF extensions personalizadas.
Efetivamente, isto transforma ferramentas como o Unity ou Blender em centros de excelência para desenvolvimento web espacial – adicionando glTF assets ao fluxo de trabalho típico de HTML, CSS, JavaScript e bundling.
Modelos, textures, animations, lights, cameras e mais são armazenados como no Needle Engine. Dados personalizados são armazenados em . Estas abrangem tudo, desde interactive components a physics, sequencing e lightmaps.
Um glTF de produção típico criado pelo Needle Engine usa as seguintes extensions:
Outras extensions suportadas:
Material extensions suportadas:
Nota: Materials que usam estas extensions podem ser exportados do Unity via o material
PBRGraph
do UnityGLTF.
Nota: Audio e variants já são suportados no Needle Engine através de
NEEDLE_components
eNEEDLE_persistent_assets
, mas existem algumas opções para um maior alinhamento com propostas existentes comoKHR_audio
eKHR_materials_variants
.
O Needle Engine armazena dados personalizados em ficheiros glTF através das nossas vendor extensions. Estas extensions foram concebidas para serem flexíveis e permitir que dados relativamente arbitrários sejam colocados nelas. De notar, nenhum código é armazenado nestes ficheiros. Interactive components são restaurados a partir dos dados no runtime. Isto tem algumas semelhanças com a forma como os AssetBundles funcionam no Unity – o lado recetor de um asset precisa de ter código correspondente para components armazenados no ficheiro.
Atualmente, não estamos a fornecer schemas para estas extensions, pois ainda estão em desenvolvimento. Os snippets JSON abaixo demonstram o uso de extensions por exemplo e incluem notas sobre escolhas arquitetónicas e o que podemos mudar em futuras versões.
As referências entre partes de dados são atualmente construídas através de uma mistura de índices para outras partes do ficheiro glTF e JSON pointers. Podemos consolidar estas abordagens numa futura versão. Também estamos a armazenar GUIDs baseados em string para casos em que a ordenação é difícil de resolver (por exemplo, dois components referenciando-se mutuamente) que podemos remover no futuro.
Esta extension contém dados de component por node. Os nomes dos component mapeiam para nomes de tipo tanto no lado JavaScript como no lado C#. Múltiplos components com o mesmo nome podem ser adicionados ao mesmo node.
Nota: Armazenar apenas o nome do tipo de component significa que os nomes de tipo precisam atualmente de ser únicos por projeto. Estamos a planear incluir nomes de pacote numa futura versão para aliviar esta restrição para nomes de tipo de component únicos por pacote, em vez de globalmente.
Nota: Atualmente não existe informação de versioning na extension (a qual pacote npm pertence um component, contra qual versão desse pacote foi exportado). Estamos a planear incluir informação de versioning numa futura versão.
Nota: Atualmente todos os components estão no array
builtin_components
. Poderemos renomear isto para apenascomponents
numa futura versão.
Esta é uma root extension que define propriedades de iluminação ambiente per ficheiro glTF.
Nota: Esta extension pode ter de ser definida por scene em vez de por ficheiro.
Esta é uma root extension que define um conjunto de lightmaps para o ficheiro glTF.
Nota: De momento, esta extension também contém referências a environment texture. Estamos a planear mudar isso numa futura versão.
Lightmap
0
Environment Map
1
Reflection Map
2
Nota: Poderemos mudar isso numa futura versão e mover dados relacionados com lightmap para uma entrada de extension
NEEDLE_lightmap
por node.
Components em NEEDLE_components
podem referenciar dados via JSON Pointers. Os dados em NEEDLE_persistent_assets
são frequentemente referenciados múltiplas vezes por diferentes components e são assim armazenados separadamente numa root extension. Por design, são sempre referenciados por outra coisa (ou têm referências entre si), e portanto não armazenam informação de tipo de todo: são simplesmente peças de dados JSON e os components que os referenciam precisam atualmente de saber o que esperam.
Exemplos de assets/dados armazenados aqui são:
AnimatorControllers, as suas layers e estados
PlayableAssets (timelines), as suas tracks e embedded clips
SignalAssets
...
Dados em persistent_assets
podem referenciar outros persistent_assets
via JSON Pointer, mas por design não podem referenciar NEEDLE_components
. Isto é semelhante à separação entre "Scene data" e "AssetDatabase content" no Unity.
Nota: Poderemos incluir mais informação de tipo e versioning no futuro.
Nota: Atualmente, vertex e fragment shaders estão sempre embutidos como URI; planeamos mover esses dados para bufferViews mais razoáveis no futuro.
Nota: Existem algumas propriedades redundantes aqui que planeamos limpar.
🏗️ Em Construção
🏗️ Em Construção
Embora o processo de compilação do Unity de C# para IL para C++ (via IL2CPP) para WASM (via emscripten) seja engenhoso, também é relativamente lento. Construir até um projeto simples para WASM leva muitos minutos, e esse processo é praticamente repetido a cada alteração de código. Parte disso pode ser evitada através de caching inteligente e garantindo que as dev builds não tentem retirar tanto código, mas ainda assim continua lento.
Temos um protótipo para alguma tradução WASM, mas está longe de estar completo e a velocidade de iteração continua lenta, pelo que não estamos a investigar ativamente este caminho neste momento.
Ao analisar workflows web modernos, descobrimos que os tempos de reload de código durante o desenvolvimento são desprezáveis, geralmente na ordem dos sub-segundos. Isto, claro, troca alguma performance (interpretação de JavaScript on the fly em vez de otimização do compilador em tempo de build) por flexibilidade, mas os browsers tornaram-se muito bons a tirar o máximo partido de JavaScript.
Acreditamos que, para iteração e workflows de teste rigorosos, é benéfico poder testar no dispositivo e na plataforma alvo (o browser, neste caso) o mais rápido e frequentemente possível - razão pela qual estamos a saltar todo o play mode do Unity, correndo efetivamente sempre no browser.
Nota: Um efeito secundário muito positivo é evitar todo o passo lento de "domain reload" que geralmente custa 15-60 segundos cada vez que entra no Play Mode. Está simplesmente "ao vivo" no browser no momento em que carrega em Play.
Página traduzida automaticamente usando IA
Mais extensions e extensions personalizadas podem ser adicionadas usando os export callbacks do UnityGLTF (ainda não documentado) e as do three.js.
Para produção, comprimimos glTF assets com . Textures usam etc1s
, uastc
, webp
ou nenhuma compression, dependendo do tipo de texture. Meshes usam draco
por defeito, mas podem ser configurados para usar meshtopt
(per ficheiro glTF). Custom extensions são passadas de forma opaca.
Veja a página para mais informações
Os dados em NEEDLE_components
podem ser animados via a extension , atualmente não ratificada.
Esta extension contém dados adicionais por node relacionados com estado, layers e tags. Layers são usadas tanto para rendering como para physics, de forma semelhante à forma como e as tratam.
Nota: Poderemos ter de explicar melhor por que razão esta não é outra entrada em .
A forma como os lightmaps são aplicados é definida no component MeshRenderer
dentro da extension por node:
Esta extension baseia-se na extension arquivada e estende-a em alguns pontos cruciais. Enquanto a extension original foi especificada para WebGL 1.0, estamos a usá-la com WebGL 2.0 aqui e adicionámos um número de uniform types.