Se a cena não couber totalmente na memória, você estará inserindo o campo de renderização fora do núcleo. Existem basicamente duas abordagens aqui: a) Gere sua cena sob demanda b) Carregue sua cena sob demanda
A abordagem anterior se alinha bem à maioria dos fluxos de trabalho de animação, onde os modelos são fortemente subdivididos usando, por exemplo, Catmull-Clark e podem se tornar muito intensivos em memória, mas as malhas básicas se encaixam facilmente na memória. A Pixar tem alguns artigos sobre isso (por exemplo, Diferenciais de Ray e Cache de Geometria Multiresolução para Rastreamento de Raios de Distribuição em Cenas Complexas ), mas a essência disso é que os modelos são subdivididos apenas quando são atingidos por um raio, e apenas subdivididos tanto quanto possível. razoável para esse raio (por exemplo, a inter-reflexão difusa precisa de menos precisão do que os reflexos no espelho). O restante é tratado por um cache de geometria, que mantém os modelos subdivididos na memória e, com sorte, torna o processo eficiente por uma boa estratégia de remoção.
Desde que todas as malhas básicas se encaixem confortavelmente na memória, você pode facilmente sair do núcleo e renderizar malhas em níveis de subdivisão que nunca se encaixariam na memória. O cache da geometria também se adapta bem à quantidade de memória que você possui, permitindo pesar a RAM versus o tempo de renderização. Isso também foi usado em carros , acredito.
A segunda abordagem é mais geral e não depende do uso pesado de subdivisão. Em vez disso, depende do fato de que sua cena foi provavelmente feita por um artista e já é particionada em objetos razoavelmente pequenos que cabem na memória individualmente. A ideia é manter duas hierarquias (árvore kD ou hierarquia de volume delimitadora): uma hierarquia de nível superior que armazena apenas caixas delimitadoras dos objetos em sua cena e uma hierarquia de baixo nível que armazena a geometria real. Existe uma hierarquia de baixo nível para cada objeto.
Nessa abordagem, você idealmente já armazena uma caixa delimitadora junto com cada objeto no disco. À medida que a cena é carregada, você constrói apenas inicialmente a hierarquia de nível superior, o que significa que você só precisa observar as caixas delimitadoras e não a geometria. Você começa a rastrear raios e os percorre pela hierarquia. Sempre que um raio atinge um nó folha na hierarquia de nível superior (ou seja, atinge a caixa delimitadora de um objeto), esse objeto é carregado na memória e sua hierarquia de baixo nível é criada. O raio continua a traçar esse objeto. Combinado com um cache de objeto que mantém o máximo possível da hierarquia de baixo nível na memória, isso pode ter um desempenho razoável.
O primeiro benefício dessa abordagem é que objetos que nunca são atingidos nunca são carregados, o que significa que ele se adapta automaticamente à visibilidade em sua cena. O segundo benefício é que, se você estiver rastreando muitos raios, não precisará carregar um objeto imediatamente, pois é atingido por um raio; em vez disso, você pode manter esse raio e esperar até que raios suficientes atinjam esse objeto, amortizando a carga sobre vários acertos de raio.
Você também pode combinar essa abordagem com um algoritmo de classificação de raios, como Sombreamento diferido classificado para rastreamento de caminho de produção, para evitar trituração devido a raios incoerentes. O artigo mencionado descreve a arquitetura do renderizador Hyperion da Disney, usado para o Big Hero 6, acredito, para que ele possa lidar com cenas em escala de produção.
Se você organizar sua cena em uma estrutura espacial (a maneira usual é uma Hierarquia de Volume Limite ), poderá usar um tipo de cena virtual (eu estou criando esse termo, em referência a texturas virtuais ).
Um gerenciador de memória manteria apenas um número limitado de caixas delimitadoras carregadas por vez e abstraia a operação que consiste em recuperar uma.
Dessa forma, uma caixa seria carregada apenas quando necessário: quando um raio atinge uma caixa delimitadora, a caixa é carregada para resolver a colisão. Mais tarde, quando outra caixa precisar ser carregada, a não utilizada será excluída para abrir espaço para a nova.
Com todas essas caixas sendo carregadas e excluídas, a coerência dos raios seria um fator importante na velocidade. Suponho que uma melhoria adicional poderia ser adiar o carregamento, reordenando os raios para tratar primeiro as caixas que já estão carregadas.
fonte
O que você faz é carregar triângulos na memória do disco com base no que foi atingido anteriormente. Você pode começar com triângulos muito próximos primeiro. O raciocínio é que em uma área os raios provavelmente atingem os mesmos triângulos repetidamente. E, eventualmente, você será um pouco eficiente. (Por esse motivo, é uma boa idéia armazenar em cache o último triângulo de acerto no rastreamento de oclusão que não se importa com a ordem)
Segundo, você armazena os triângulos em uma árvore espacial que permite pesquisar rapidamente a partir do disco, para renovar as partes que você está tendo na memória por proximidade. Portanto, carregue apenas ramos que estarão no caminho do raio. Se for algum tipo de árvore voxel, como uma octree, você pode até classificar os raios secundários e resolvê-los por coerência. Uma árvore BSP também é um pouco boa em áreas de poda.
Há casos em que isso falha, mas é razoavelmente eficiente na maioria dos baldes de cena, se você não estiver produzindo ruído ...
fonte