Je voudrais charger des maillages arbitraires et dessiner des lignes noires épaisses le long des bords pour obtenir un aspect semblable à un ombrage. J'ai réussi à dessiner une silhouette noire autour des objets en utilisant le tampon de pochoir. Vous pouvez voir le résultat ici:
Mais ce qui manque, ce sont les lignes noires dans l'objet lui-même. J'ai pensé à vérifier les discontinuités normales: vérifier si un pixel voisin a un vecteur normal différent de celui actuel. Si oui, un bord a été trouvé. Malheureusement, je ne sais pas comment je pourrais implémenter cette approche, ni dans OpenGL ni dans GLSL vertex / fragment shader.
Je serais très heureux d'avoir de l'aide concernant cette approche ou toute autre concernant la détection des bords.
Edit: je n'utilise pas de textures pour mes meshs.
Pour être plus précis, je voudrais créer une solution CAD / CAM qui ressemble autant que possible à celle-ci (tirée de Top Solid https://www.youtube.com/watch?v=-qTJZtYUDB4 ):
la source
Réponses:
Généralement, la détection des contours se résume à détecter les zones de l'image avec une valeur de gradient élevée.
Dans notre cas, nous pouvons voir grossièrement le gradient comme la dérivée de la fonction d'image, donc l'ampleur du gradient vous donne une information sur la façon dont votre image change localement (en ce qui concerne les pixels / texels voisins).
Maintenant, un bord est comme vous le dites une indication de discontinuité, alors maintenant que nous avons défini le gradient, il est clair que cette information est tout ce dont nous avons besoin. Une fois que nous trouvons le gradient d'une image, il suffit de lui appliquer un seuil pour obtenir une valeur binaire bord / non bord.
Comment trouvez-vous que ce gradient est vraiment ce que vous demandez et je n'ai pas encore répondu :)
Beaucoup de façons! Voici un couple :)
Fonctions de shader intégrées
Hlsl et glsl offrent des fonctions dérivées. Dans GLSL, vous avez dFdx et dFdy qui vous donnent respectivement des informations de gradient dans les directions x et y. En règle générale, ces fonctions sont évaluées dans un bloc de fragments 2x2.
Sauf si vous êtes intéressé par une seule direction, un bon moyen d'avoir un résultat compact qui indique la force du gradient dans la région est une largeur qui ne vous donne rien d'autre que la somme de la valeur absolue de dFdy et dFdy.
Vous êtes susceptible d'être intéressé par un bord sur l'image globale plutôt que sur un canal spécifique, vous pouvez donc vouloir transformer votre fonction d'image en luma. Dans cet esprit, en ce qui concerne la détection des contours, votre shader peut inclure quelque chose du genre:
Avec un seuil élevé, vous trouverez des bords plus grossiers et vous pourriez en manquer, à l'inverse, avec un seuil bas, vous pourriez détecter de faux bords. Vous devez expérimenter pour trouver le seuil qui correspond le mieux à vos besoins.
La raison pour laquelle ces fonctions fonctionnent mérite d'être mentionnée mais je n'ai pas le temps pour cela maintenant, je suis susceptible de mettre à jour cette réponse plus tard :)
Post-traitement de l'espace d'écran
Vous pourriez devenir plus sophistiqué que cela, maintenant le domaine de la détection des bords dans le traitement d'image est immense. Je pourrais vous citer des dizaines de bonnes façons de détecter la détection des contours en fonction de vos besoins, mais restons simples pour l'instant, si vous êtes intéressé, je peux vous citer plus d'options!
L'idée serait donc similaire à celle ci-dessus, à la différence près que vous pourriez regarder un voisinage plus large et utiliser un ensemble de poids sur les échantillons environnants si vous le souhaitez. En règle générale, vous exécutez une convolution sur votre image avec un noyau qui vous donne en conséquence une bonne information de dégradé.
Un choix très courant est le noyau Sobel
Ce qui vous donne respectivement des gradients dans les directions x et y:
Vous pouvez obtenir la valeur unique du dégradé sous la formeGradientMagnitude=(Gradientx)2+(Gradienty)2−−−−−−−−−−−−−−−−−−−−−−−√
Ensuite, vous pouvez définir le seuil de la même manière que je l'ai mentionné ci-dessus.
Ce noyau, comme vous pouvez le voir, donne plus de poids au pixel central, il calcule donc efficacement le dégradé + un peu de lissage, ce qui aide traditionnellement (souvent l'image est floue gaussienne pour éliminer les petits bords).
Ce qui précède fonctionne assez bien, mais si vous n'aimez pas le lissage, vous pouvez utiliser les noyaux Prewitt:
(Notez que je suis pressé, j'écrirai bientôt le texte formaté approprié au lieu des images!)
Vraiment, il y a beaucoup plus de noyaux et de techniques pour trouver la détection des bords d'une manière processus d'image y plutôt que des graphiques en temps réel, j'ai donc exclu des méthodes plus compliquées (jeu de mots non prévu) car probablement vous seriez très bien avec les fonctions dFdx / y .
la source
Juste au cas où quiconque elso aurait également besoin de détecter les bords: voici un bel article sur la façon d'afficher un filaire et cet article explique comment afficher uniquement les bords.
la source