Actualmente estoy desarrollando un motor de juego que utiliza campos de distancia firmados como una técnica de representación para mostrar una geometría de procedimiento uniforme (generada con primitivas simples como las de su enlace por el momento, buscando implementar fractales Julia e IFS en el futuro). Dado que mi motor está enfocado en la generación de procedimientos y debe definir las figuras de una manera que los haga amigables para los que marcan rayos, creo que estoy en un buen lugar para responder esta pregunta: P.
Con respecto a la transmisión, la solución simple es usar un búfer tipeado de algún tipo y tirarlo a la GPU cuando desee hacer su marcha de rayos. Cada elemento del búfer es un tipo complejo (por ejemplo, una estructura en C / C ++), y cada tipo contiene elementos que definen qué función debe usar para representarlo, su posición, rotación, escala, etc., y un color promedio. El proceso luego se simplifica a:
- Elimine su escena en un subconjunto manejable (tenga en cuenta que el sacrificio de frustum y la eliminación de oclusiones se realizan en parte de forma automática por el algoritmo de marcha de rayos de todos modos)
- Pase el subconjunto a su búfer de entrada de renderizado
- Pase el búfer a la GPU si aún no está allí, luego renderice su escena con la marcha de rayos tradicional. Tendrá que realizar algún tipo de búsqueda por paso para evaluar qué elemento en el búfer de entrada está más cerca de cada rayo para cada iteración del rayo-marcador, y deberá aplicar transformaciones a cualquiera de los rayos (en cuyo caso necesitará invertir las rotaciones de figuras antes de que lleguen a la GPU) o las funciones de distancia (mover el origen de la función para cambios de posición, ajustar, por ejemplo, longitudes de los lados cúbicos para cambios de escala, etc.) El enfoque más simple es modificar los rayos antes los pasa a la función de distancia real del núcleo.
Con respecto a los colores de las figuras, recuerde que los sombreadores le permiten definir tipos complejos y primitivos;). Eso le permite lanzar todo en una estructura de estilo C, luego pasar esas estructuras de su función de distancia.
En mi motor, cada estructura contiene una distancia, un color y una ID que lo vincula a la definición de figura correspondiente en el búfer de entrada. Cada ID se infiere del contexto circundante de la función de distancia relevante (dado que mi función de mapeo recorre el búfer de entrada para encontrar la figura más cercana a cada rayo para cada paso, puedo tratar con seguridad el valor del contador de bucle cuando se llama a cada SDF como la ID de la figura para esa función), mientras que los valores de distancia se definen utilizando un SDF de núcleo arbitrario (por ejemplo,point - figure.pos
para una esfera), y los colores se definen a partir del color promedio del elemento apropiado en el búfer de la figura (por lo tanto, es útil mantener las ID de la figura alrededor) o mediante un color de procedimiento ponderado hacia el promedio almacenado (un ejemplo podría estar tomando un recuento de iteración para algún punto en el Mandelbulb, mapeando su "color promedio" desde el espacio de color FP al espacio de color entero, luego usando el color mapeado como una paleta XOR 'contra el recuento de iteración).
Las texturas de procedimiento son otro enfoque, pero nunca las he usado yo mismo. iq ha investigado bastante en esa área y ha publicado algunas demostraciones interesantes en Shadertoy, por lo que podría ser una forma de recopilar información adicional.
Independientemente de si su color es estático para cada figura, generado por procedimiento o muestreado mágicamente a partir de una textura de procedimiento, la lógica básica es la misma: las figuras abstractas en algún tipo de tipo complejo intermedio (por ejemplo, una estructura), almacenan tanto la distancia local como la local. color en una instancia de ese tipo, luego pase el tipo complejo como un valor de retorno de su función de distancia. Dependiendo de su implementación, el color de salida puede pasar directamente a la pantalla o seguir el punto de colisión en su código de iluminación.
No sé si lo anterior fue lo suficientemente claro o no, así que no se preocupe por preguntar si algo no tiene sentido. Realmente no puedo dar ninguna muestra de código GLSL / pixel-shading ya que estoy trabajando con HLSL y calcular el sombreado, pero estoy feliz de tratar de repasar todo lo que no escribí correctamente en primer lugar :).