Me gustaría cargar mallas arbitrarias y dibujar gruesas líneas negras a lo largo de los bordes para obtener un aspecto similar al sombreado de toon. Logré dibujar una silueta negra alrededor de los objetos usando el búfer de plantilla. Puedes ver el resultado aquí:
Pero lo que falta son las líneas negras en el objeto mismo. Pensé en verificar las discontinuidades normales: verificar si un píxel vecino tiene un vector normal diferente al actual. En caso afirmativo, se ha encontrado una ventaja. Desafortunadamente, no tengo idea de cómo podría implementar este enfoque, ni en OpenGL ni en el sombreador de vértices / fragmentos GLSL.
Estaría muy feliz de recibir ayuda con respecto a este enfoque o cualquier otro con respecto a la detección de bordes.
Editar: no uso ninguna textura para mis mallas.
Para ser más preciso, me gustaría crear una solución CAD / CAM que se vea lo más posible posible (tomada de Top Solid https://www.youtube.com/watch?v=-qTJZtYUDB4 ):
fuente
Respuestas:
En general, la detección de bordes se reduce para detectar áreas de la imagen con un alto valor de gradiente.
En nuestro caso, podemos ver crudamente el gradiente como la derivada de la función de imagen, por lo tanto, la magnitud del gradiente le brinda información sobre cuánto cambia su imagen localmente (con respecto a los píxeles / texels vecinos).
Ahora, una ventaja es, como usted dice, una indicación de discontinuidad, por lo que ahora que definimos el gradiente está claro que esta información es todo lo que necesitamos. Una vez que encontramos el gradiente de una imagen, solo es cuestión de aplicarle un umbral para obtener un valor binario borde / no borde.
¿Cómo encuentras que este gradiente es realmente lo que estás preguntando y todavía tengo que responder :)
¡Muchas maneras! Aquí una pareja :)
Construido en funciones de sombreador
Tanto hlsl como glsl ofrecen funciones derivadas. En GLSL tiene dFdx y dFdy que le dan información de gradiente respectivamente en dirección x e y. Normalmente, estas funciones se evalúan en un bloque de fragmentos de 2x2.
A menos que esté interesado en una sola dirección, una buena forma de tener un resultado compacto que indique qué tan fuerte es el gradiente en la región es un ancho que no le da más que la suma del valor absoluto de dFdy y dFdy.
Es probable que esté interesado en una ventaja en la imagen general en lugar de en un canal específico, por lo que es posible que desee transformar su función de imagen en luma. Con esto en mente, cuando se trata de detección de bordes, su sombreador podría incluir algo similar a:
Con un umbral alto, encontrará bordes más gruesos y, por el contrario, puede perder algunos, a la inversa, con un umbral bajo puede detectar bordes falsos. Tienes que experimentar para encontrar el umbral que mejor se adapte a tus necesidades.
Vale la pena mencionar el motivo por el que funcionan estas funciones, pero no tengo tiempo para hacerlo ahora, es probable que actualice esta respuesta más adelante :)
Espacio de pantalla posterior al proceso
Podría ser más elegante que esto, ahora el campo de detección de bordes en el procesamiento de imágenes es inmenso. Podría citarle decenas de buenas maneras de detectar la detección de bordes de acuerdo con sus necesidades, pero hagámoslo simple por ahora, si está interesado, ¡puedo citarle más opciones!
Por lo tanto, la idea sería similar a la anterior, con la diferencia de que podría mirar un vecindario más amplio y usar un conjunto de pesos en muestras circundantes si lo desea. Por lo general, ejecuta una convolución sobre su imagen con un núcleo que le da como resultado una buena información de gradiente.
Una opción muy común es el núcleo Sobel
Que respectivamente te dan gradientes en direcciones x e y:
Entonces puede umbral como de la misma manera que mencioné anteriormente.
Este núcleo, como puede ver, le da más peso al píxel central, por lo que efectivamente calcula el gradiente + un poco de suavizado que tradicionalmente ayuda (a menudo la imagen es borrosa gaussiana para eliminar pequeños bordes).
Lo anterior funciona bastante bien, pero si no le gusta el suavizado, puede usar los núcleos Prewitt:
(Tenga en cuenta que tengo prisa, ¡pronto escribiré el texto con el formato adecuado en lugar de las imágenes!)
Realmente hay muchos más núcleos y técnicas para encontrar la detección de bordes en un proceso de imagen en lugar de gráficos en tiempo real, por lo que he excluido los métodos más complicados (juego de palabras no intencionado) ya que probablemente estaría bien con las funciones dFdx / y .
fuente
En caso de que alguien también necesite detectar bordes: Aquí hay un buen artículo sobre cómo mostrar una estructura metálica y este artículo explica cómo mostrar solo los bordes.
fuente