Estoy trabajando en la configuración de un esquema activo en mi motor 3D, un efecto de resaltado para personajes 3D seleccionados o paisajes en la pantalla. Después de trabajar con el búfer de la plantilla y obtener algunos resultados insatisfactorios (problemas con las formas cóncavas, el grosor del contorno debido a la distancia de la cámara y las inconsistencias entre mi computadora de escritorio y la computadora portátil), cambié a la detección de bordes y al muestreo del búfer de cuadro y obtuve un esquema. bastante satisfecho con
Sin embargo, no puedo ocultar el contorno cuando la malla seleccionada está detrás de otra malla. Esto tiene sentido dado mi proceso, ya que simplemente renderizo el contorno del sombreador 2D desde un búfer de cuadros después de renderizar el resto de la escena.
Dos capturas de pantalla de mis resultados están a continuación. El primero es un esquema "bueno", el segundo es donde se ve el esquema sobre una malla que bloquea la fuente del esquema.
El proceso de renderizado se ejecuta así: 1) Dibuje solo el alfa de la malla resaltada, capturando una silueta negra en un búfer de cuadro (framebuffer1).
2) Pase la textura de framebuffer1 a un segundo sombreador que realice la detección de bordes. Capture el borde en framebuffer2.
3) Renderiza toda la escena.
4) Renderiza la textura de framebuffer2 en la parte superior de la escena.
Tengo algunas ideas sobre cómo lograrlo y espero recibir comentarios sobre su validez, o sobre métodos más simples o mejores.
Primero, he pensado en representar toda la escena en un búfer de cuadro y almacenar la silueta visible de la malla resaltada en el canal alfa (todo blanco excepto donde la malla resaltada es visible). Luego realizaría la detección de bordes en el canal alfa, renderizaría el búfer de cuadro de escena y luego renderizaría el borde en la parte superior. Resultando en algo como esto:
Para lograr esto, pensé en establecer una definición solo durante el paso de renderizado del objeto resaltado que dibujaría todo negro en el alfa para cualquier píxel visible.
Mi segunda idea es utilizar el proceso de renderizado actual descrito anteriormente, pero también almacenar las coordenadas X, Y y Z en los canales R, G y B de framebuffer1 cuando renderice la silueta de la malla seleccionada. Las detecciones de bordes se realizarían y almacenarían en framebuffer2, pero pasaría los valores RGB / XYZ desde los bordes del alfa a la silueta. Luego, al renderizar la escena, probaría si la coordenada está dentro del borde almacenado en framebuffer2. Si es así, probaría la profundidad del fragmento actual para determinar si está delante o detrás de las coordenadas extraídas de los canales RGB (convertidos en espacio de cámara). Si el fragmento está delante de las coordenadas de profundidad, el fragmento se representará normalmente. Si el fragmento está detrás, se representará como el color del contorno sólido.
Estoy usando LibGDX para este proyecto y me gustaría admitir WebGL y OpenGL ES, por lo que ninguna de las soluciones que involucran sombreadores de geometría o funciones GLSL más nuevas están disponibles para mí. Si alguien pudiera comentar sobre mis enfoques propuestos o proponer algo mejor, realmente lo agradecería.
Respuestas:
Procesaría toda la escena en un búfer de plantilla con el objeto delineado deseado para establecer un bit y para cualquier otra cosa descartar / eliminar el bit.
Luego, elimine la detección de bordes, no lo necesita, en su lugar puede escalar un poco el búfer. Entonces cada objeto solo crece ligeramente.
A partir de ahí, el búfer de la plantilla puede tener el contorno que necesita. Se trata de asegurarse de que los otros objetos que está renderizando estén apagando los bits en su búfer de plantilla.
fuente
1) en un objeto frame buffer, puede ejecutar un sombreador laplaciano en la GPU para obtener el contorno.
2) tiene que usar el búfer de profundidad final cuando dibuje su objeto en el FBO, de esa manera dibujará solo la parte visible de su objeto en el FBO, y el laplaciano contorneará solo la parte visible.
fuente
Espero poder aclarar esto, pero básicamente necesita hacer una plantilla de ambos objetos como si ambos estuvieran seleccionados, luego solo mantenga las áreas en el cuadro delimitador del elemento que realmente desea resaltar.
Entonces, básicamente, haces un búfer de plantilla de ambos objetos seleccionados (o de todos los objetos que ocluyen el objeto, en realidad ... pero no me preocuparía por esos casos a menos que realmente surja mucho, si es que las personas ocluidas no van a esperar esta mucha ayuda), y luego con una plantilla del cuadro delimitador para su objeto.
Eso debería tener el efecto que estás buscando.
Alternativamente, puede dejar el resultado 'malo' y no creo que a la mayoría de la gente le importe demasiado, aunque esto depende de sus datos / juego y especialmente del tamaño de los objetos.
fuente