Acho que entendo o básico do Marched Ray Fielded Distance Distance. Você modela sua cena com vários campos de distância (como estes: http://iquilezles.org/www/articles/distfunctions/distfunctions.htm ) e, em seguida, para cada pixel que você lança um raio, comece do início do raio , encontre a distância até o objeto mais próximo nesse ponto e aumente o ponto pela distância mais próxima, até atingir alguma coisa. Eu consegui criar um renderizador simples, e é aí que a maioria das descrições da técnica para.
Isso me deixa com algumas perguntas sobre como o SDF Ray Marching pode ser usado em um cenário do mundo real:
Pergunta 1: Em um jogo real, a cena é geralmente complexa e carregada na CPU, com muitos objetos dinâmicos. Entendo o descarte básico de oclusão (como octrees) e, com a renderização poligonal, eu criaria uma lista (na CPU) de itens na exibição de frustrum a ser renderizada.
Então, imagine que eu tenho uma cena muito complexa, com muitos personagens e objetos dinâmicos movendo-se na tela, controlados pela CPU. Como transmitiria os objetos que quero renderizar para a GPU em cada quadro? Todo exemplo tem a cena codificada no GLSL. Alguém pode compartilhar um exemplo do nível que está sendo transmitido para o shader dinamicamente?
Pergunta 2: Como os objetos podem ter várias cores? As funções de distância retornam apenas uma distância, mas como as implementações geralmente devolvem a cor? (por exemplo, você bate em uma esfera vermelha e não em um cubo azul.) Se essa fosse uma implementação de CPU, eu poderia chamar uma função global dentro da função distance quando for um hit para finalizar o ray marcher, e que também pode passar o objeto do hit. textura / cor. Mas como você retornaria a cor ou a textura do item no GLSL?
Obrigado.
Atualmente, estou desenvolvendo um mecanismo de jogo que utiliza campos de distância assinados como uma técnica de renderização para exibir geometria processual suave (gerada com primitivas simples como as do seu link no momento, procurando implementar os fractais Julia e IFS no futuro). Como meu mecanismo está focado na geração de procedimentos e deve definir figuras de maneira a torná-las amigáveis aos marcadores de raios, acho que estou em um bom lugar para responder a essa pergunta: P.
Em relação ao streaming, a solução simples é usar um tipo de buffer de algum tipo e jogá-lo na GPU quando você quiser fazer a marcação de raios. Cada elemento do buffer é um tipo complexo (por exemplo, uma estrutura em C / C ++), e cada tipo contém elementos que definem qual função você deve usar para representá-lo, sua posição, rotação, escala, etc. e uma cor média. O processo simplifica até:
Em relação às cores das figuras, lembre-se de que os sombreadores permitem definir tipos complexos e primitivos;). Isso permite que você jogue tudo em uma estrutura no estilo C e passe essas estruturas de volta da sua função de distância.
No meu mecanismo, cada estrutura contém uma distância, uma cor e um ID que o vincula à definição de figura correspondente no buffer de entrada. Cada ID é deduzido do contexto circundante da função de distância relevante (como minha função de mapeamento percorre o buffer de entrada para encontrar a figura mais próxima de cada raio para cada etapa, posso tratar com segurança o valor do contador de loop quando cada SDF é chamado como o ID da figura para essa função), enquanto os valores de distância são definidos usando um SDF principal arbitrário (por exemplo,
point - figure.pos
para uma esfera) e as cores são definidas a partir da cor média do elemento apropriado no buffer de figuras (por isso, é útil manter os IDs das figuras por aí) ou através de uma cor de procedimento ponderada em relação à média armazenada (um exemplo pode estar ocorrendo uma contagem de iteração para algum ponto no Mandelbulb, mapeando sua "cor média" do espaço de cores FP para o espaço de cores inteiro e, em seguida, usando a cor mapeada como uma paleta, usando XOR para a contagem de iterações).Texturas procedurais são outra abordagem, mas eu nunca as usei. O iq fez muita pesquisa nessa área e publicou algumas demonstrações interessantes em Shadertoy, de modo que essa pode ser uma maneira de reunir algumas informações extras.
Independentemente de sua cor é estático para cada figura, processualmente gerado, ou magicamente amostrados de uma textura processual, a lógica básica é a mesma: Figuras abstratas em algum tipo de tipo complexo intermediário (por exemplo, um struct), armazenar tanto distância locais e locais color em uma instância desse tipo, depois passe o tipo complexo como um valor de retorno da sua função de distância. Dependendo da sua implementação, a cor de saída pode passar diretamente para a tela ou seguir o ponto de colisão no seu código de iluminação.
Não sei se o exposto foi claro o suficiente ou não, então não se preocupe em perguntar se algo não faz sentido. Eu realmente não posso fornecer nenhum exemplo de código GLSL / pixel-shading, pois estou trabalhando com HLSL e computar sombreamento, mas estou feliz em tentar revisar qualquer coisa que não tenha escrito corretamente em primeiro lugar :).
fonte