Excellent projet, tu penses que tu peux potentiellement commercialiser ton moteur une fois qu'il sera fini ? Ou tu fais ça pour le fun ?
Excellent projet, tu penses que tu peux potentiellement commercialiser ton moteur une fois qu'il sera fini ? Ou tu fais ça pour le fun ?
Toujours aussi balaise!
Et en ce qui concerne ton précédent projet, je crois que le plus impressionnant pour moi c'est le nombre de personnes que tu as fédéré autour! J'essaye depuis de nombreux mois de motiver mes amis/collègues sur mon projet. Mais je dois avouer sans succès.
Merci ! Ce n'est pas dans mes plans, et j'utilise quand-même de techniques déjà existantes développées par d'autres donc ça ne ferait pas vraiment sens je pense. Je fais ça principalement pour le fun, pour me mettre à jour et aussi pour mes futures projets. Sinon il sera disponible en open source.Excellent projet, tu penses que tu peux potentiellement commercialiser ton moteur une fois qu'il sera fini ? Ou tu fais ça pour le fun ?
C'est très difficile. Je pense que le projet n'a tenu que parce que mon frère et moi-même tenions le coup (et avions beaucoup de temps, ah la bonne époque des études secondaires ).Et en ce qui concerne ton précédent projet, je crois que le plus impressionnant pour moi c'est le nombre de personnes que tu as fédéré autour! J'essaye depuis de nombreux mois de motiver mes amis/collègues sur mon projet. Mais je dois avouer sans succès.
Depuis le temps que j'ai ça en tête, je me suis enfin jeté... à l'eau !
Ca va encore demander beaucoup de tweak et de tests pour arriver au résultat que je désire, mais ça commence quand-même à ressembler à quelque chose.
Le mouvement de l'eau fait ressortir les contours coupés au couteau des sprites, mais j'en ai quand même la mâchoire qui tombe :p
En fait c'est totalement normal au vu de comment je procède pour le moment: je ne gère que deux couches de rendu, une pour les objets opaques et une pour l'alpha. Mais donc l'alpha de l'anti-crénelage de la tour (par exemple) vient remplacer le fragment d'eau, ce qui donne un artefact dégeux. Je pourrais y remédier en mettant l'eau totalement opaque, mais alors ça veut dire qu'elle se prend de l'ambient occlusion... pas top ! Je pourrais ajouter des couches de rendu, c'est la solution facile, mais aussi la plus couteuse... pas top !Le mouvement de l'eau fait ressortir les contours coupés au couteau des sprites, mais j'en ai quand même la mâchoire qui tombe :p
Je dois encore réfléchir à comment procéder. Une piste serait peut-être d'essayer de développer un meilleur moyen de résoudre les conflits d'alpha que simplement le depth buffer (le plus haut gagne), en prenant par exemple un autre poids donné par la transparence et le depth buffer, à réfléchir.
Salut!
Tout d'abord un grand bravo pour les résultats que tu obtiens, il y a du boulot derrière!
Tu utilises une height map, pour le rendu de l'écume ?
Si vous ne trouvez plus rien, cherchez autre chose...
Vous trouverez ici des tutoriels OpenGL moderne.
Mon moteur 3D: Castor 3D, presque utilisable (venez participer, il y a de la place)!
Un projet qui ne sert à rien, mais qu'il est joli (des fois) : ProceduralGenerator (Génération procédurale d'images, et post-processing).
Tout le rendu de l'eau est basé sur une heightmap générée à partir de bruit de Perlin fractal et un sinus (à remplacer par des vagues de Gerstner ou équivalent), et j'en profite pour calculer les normales analytiquement. Ensuite ici l'écume est juste donnée par la hauteur (c'est pas top), en modifiant l'albedo et material map; j'ai en tête de remplacer ça par/mixer ça avec la dérivée seconde (pour mettre de l'écume dès que tu arrive à un sommet).Tu utilises une height map, pour le rendu de l'écume ?
Ensuite c'est la magie du moteur qui fait tout le reste, en utilisant notamment le raytraced parallax que j'ai implémenté juste avant en fait (l'eau n'étant en fait rendue que sur un rectangle plat ).
Je reviens sur ce qu'on m'a dit l'autre fois:
Et au passage, je voudrais expliquer un autre problème du même style que j'ai mentionné avant: l'anticrénelage des objets est contenu dans la couche de rendu alpha. Dès lors, est-ce qu'il faut l'assombrir avec l'occlusion ambiante ou non ? Si on assombrit les objets transparents, alors c'est étrange car un objet semi-transparent devient foncé à cause d'une ombre derrière lui. D'un autre côté, si on ne le fait pas, alors l'anti-crénelage ressort illuminé.Le mouvement de l'eau fait ressortir les contours coupés au couteau des sprites [...]
Voici une image pour illustrer le problème:
A gauche on n'a l'anticrénelage qui vient prendre la place des fragments d'eau car ils sont au dessus, en haut à droite ce sont les artefacts qu'on a si on dessine l'SSAO en dessous des fragments semi-transparents et en bas à droite si on dessine l'SSAO par dessus.
Si je viens en parler, c'est parce que j'ai trouvé une solution (partielle): il y a un moyen de savoir si un fragment est semi-transparent à cause de l'anticrénelage ou non et c'est... de regarder l'opacité du fragment dans la heightmap. En effet, l'eau et les objets que je dessine semi-transparents ont quand-même leur heightmap complètement opaque, alors que l'anticrénelage est donné par le logiciel de rendu 3D, qui met aussi de l'anticrénelage sur les heightmaps qu'il produit.
Alors ça, ça résoud facilement le problème de SSAO (on applique SSAO si et seulement pixel opaque ou depth transparent).
Pour l'eau, c'est un peu plus compliqué car on n'a toujours qu'un seul channel de rendu pour les pixels transparents... mais l'idée est de donner priorité aux pixels transparent ayant un depth non transparent (pour le moment là façon dont je le fais n'est pas optimale car ne donne priorité que aux objets transparents dynamique par rapport aux statiques, simplement dans la façon dont je copie le depthBuffer du buffer alpha static vers le buffer alpha dynamique).
Voici le résultat !
Alors bien sûr on perd l'AA sur la tour au dessus de l'eau, mais c'est le prix à payer, on ne peut pas faire mieux sans manger méchamment dans les perfs.
Au passage, j'ai aussi corrigé une bête erreur avec mon parallax: je partais du point le plus bas pour remonter vers la caméra et chercher la première intersection... ce qui est stupide si jamais on a plusieurs points d'intersection vu qu'alors on voit celui qui est derrières les autres ! Donc maintenant je le fais dans l'autre sens.
Gerstner waves
J'ai enfin implémenté mes vagues de type Gerstner, la difficulté a été que la fonction n'est pas présentée de façon traditionnel par y = f(x) mais par un mouvement circulaire de particules:
Source: https://en.wikipedia.org/wiki/Trochoidal_wave
En général, cette description est très pratique car on peut interpréter les sommets d'un mesh comme des particules qu'on bouge en fonction de ces mouvement circulaires... sauf que moi je veux générer une heightmap, et donc il me faut une hauteur à chaque point ! Ma solution a donc été de prendre un échantillon de N points uniformément réparti sur l’intervalle unité, ensuite je déplace chacun de ces points en fonction de mon mouvement circulaire (je regarde le mouvement de N particules d'eau si vous voulez), en m'arrangeant pour faire un tour complet entre 0 et 1 (comme ça, j'ai un seul mouvement de vague). Ensuite, il me suffit d’interpoler entre ces points, avec une interpolation linéaire ça donne ça:
Dans les fait, dans mon shader j'utilise une interpolation quadratique pour avoir un changement de normal plus lisse (linéaire). Ensuite on peut juste jouer avec la forme du mouvement circulaire, le rendant ellipsoïdale, pour avoir des vagues plus ou moins pointues.
Au passage, j'en ai profité pour rendre l'eau plus ou moins opaque en fonction de sa profondeur (puisque l'eau est rendu dans la pass d'alpha, tout ce que j'ai à faire est lire la hauteur du pixel dans le buffer de la pass de géométrie opaque et comparer).
Edge smoothing
Par ailleurs, j'ai décidé de travailler sur l'aliasing qui apparait quand on fait s'intersecter deux objets. En effet, un fragment réussit ou non le test du depthbuffer et en fonction est pris ou non, ce qui peut donner de l'aliasing assez dégueulasse quand les matériaux sont fort différents. Une solution est probablement de simplement mettre en place un shader de FXAA (Fast approXimate Anti-Aliasing), ce qui devrait rendre le rendu beaucoup plus lisse ; je ne l'ai pas encore fait mais j'envisage de le faire très prochainement (même si logiquement ça peut s'activer en dehors via le driver NVidia par exemple). Le gros avantage c'est que ça va aussi s'occuper de lisser le specular aliasing (aliasing du à grand différence d'éclairage, par exemple un objet pointu ou un bord d'un objet lisse peut réfléter beaucoup (trop ?) de lumière par rapport à son voisin). Par contre le désavantage c'est que c'est quand-même pas complètement gratuit en perfs (encore que négligeable ?) et étant juste un post-traitement de l'image il peut avoir des effets indésirables. De plus, je ne suis pas sûr qu'il va vraiment améliorer l'aliasing étrange qui apparait à cause du fait que mes heightmaps sont limitées en précisions.
Du coup, j'ai décidé de tenter une autre technique, basée sur ce que j'avais fait juste avant avec l'eau qui devient transparente en fonction de la géométrie en dessous: pendant la pass d'alpha, si j'ai un pixel opaque qui est très proche d'un autre mais juste en dessous, je viens le redessiner par dessus, avec transparence. C'est une gros approximation étant donné que des pixels qui devraient être cachés viennent se mettre par dessus... mais ça se fait à un tellement petit niveau que je pense que ça passe assez bien. Le gros avantage est que l'impacte sur les performances est quasi nul et que ça ne touche que l'endroit où deux objets s'intersectent. Voici le résultat:
Haut-gauche: sans AA, sans SSAO ; Haut-droite: sans AA, avec SSAO
Bas-gauche: avec AA, sans SSAO ; Bas-droite: avec AA, avec SSAO
En fait, le mieux, est d'activer à la fois cette technique et le FXAA (qui va au passage anticrénelé la tour qui perdait son AA quand on la mettait au dessus de l'eau).
Je ne sais pas si c'est applicable pour la 2D, mais je te conseille de te renseigner sur le SMAA, pour l'AA, parce que le FXAA est vraiment moche :
Si vous ne trouvez plus rien, cherchez autre chose...
Vous trouverez ici des tutoriels OpenGL moderne.
Mon moteur 3D: Castor 3D, presque utilisable (venez participer, il y a de la place)!
Un projet qui ne sert à rien, mais qu'il est joli (des fois) : ProceduralGenerator (Génération procédurale d'images, et post-processing).
C'est vrai que le FXAA a une sale tendance à rendre tout flou. Après, ça reste une solution assez cheap pour régler les problèmes de specular aliasing et de perte d'AA quand tu superposes avec un objet transparent.
Je n'ai pas lu en détails, mais est-ce que le SMAA n'utilise-t-il pas du multi-sampling ? A priori, c'est ça qui pourrait poser problème avec le côté 2D. Peut-être que je peux zapper juste cette partie-là et garder le reste, je regarderai ça en détails à l'occasion.
Au final, c'est surtout une méthode de specular anti-aliasing qu'il me faudrait mettre en place je pense. Et vu que tous mes objets sont prérendus je peux peut-être précalculer facilement des specular occlusions maps ou quelque chose comme ça.
Tu as plusieurs modes pour le SMAA, et le T2X que j'ai posté n'utilise pas le multisampling.
Si vous ne trouvez plus rien, cherchez autre chose...
Vous trouverez ici des tutoriels OpenGL moderne.
Mon moteur 3D: Castor 3D, presque utilisable (venez participer, il y a de la place)!
Un projet qui ne sert à rien, mais qu'il est joli (des fois) : ProceduralGenerator (Génération procédurale d'images, et post-processing).
Alors en attendant d'implémenter le SMAA T2X, voici ce sur quoi j'ai bossé:
Je vous présente mon algorithme de Screen Space Foam Rendering. L'idée ? C'est simple, en même temps que je génère mes heightmap, normalmap et co pour l'eau, je génère en plus une "velocity map" qui contient les vecteurs vitesses du mouvement de mes particules d'eau. Ensuite, au moment du rendu de l'eau, j'ai juste besoin de faire un léger raytracing pour voir si je prédicte une collision avec le décor, et en fonction de la distance je génère plus ou moins de mousse, tout simplement en changeant l'albedo et material. De plus, puisque je génère cette map à ce stade-ci, je peux directement profité de mon bruit de Perlin déjà généré sur place pour introduire de l'aléatoire dans la génération de mousse simplement en perturbant mes vecteurs vitesses.
J'ai mis du temps à obtenir des résultats qui m'allaient car au début je générais mes vecteurs vitesses basé sur le mouvement des particules dans la fonction de Gerstner. Mais du coup ça mettait de la mousse à l'avant de la vague (logique) mais rien sur le dos puisque leur velocité va vers le haut. De fait, ça ne peut pas bien donner puisque je ne gère pas une véritable simulation de la physique de l'eau. Dès lors j'ai décidé d'introduire des vecteurs vitesses "artificiels" qui pointent vers le bas, dans la direction de la vague, sur son dos. Ca me permet d'utiliser les fragments d'eau de celle-ci pour générer la mousse sensée se produire par le fracas de la vague sur le décor. Le résultat est assez sympa, je pense, et plutôt raisonnable en terme de cout de performances.
Mer du nord:
Mer des caraïbes:
Mer de heu... mercure ?
Ca rend très bien je trouve!
Par contre, le framerate n'est pas fou, c'est en debug ?
Si vous ne trouvez plus rien, cherchez autre chose...
Vous trouverez ici des tutoriels OpenGL moderne.
Mon moteur 3D: Castor 3D, presque utilisable (venez participer, il y a de la place)!
Un projet qui ne sert à rien, mais qu'il est joli (des fois) : ProceduralGenerator (Génération procédurale d'images, et post-processing).
Non mais c'est principalement le Screen Space Reflection qui bouffe la blinde de performances (de l'ordre de 7ms), ainsi que le fait de dessiner sur quasi la quasi intégralité du buffer alpha (ça fait que je dois calculer l'éclairage et SSR sur mes deux couches). Je tourne sur une 750m gt.Par contre, le framerate n'est pas fou, c'est en debug ?
Après, la mousse, ça me fait une différence de moins d'1ms. Après, si je retire l'eau et augmente le seuil de SSR (pour ne refléter que les objets avec un fort indice de réflexion, comme le métal ou l'eau), je repasse aux alentours de 60 FPS (en 1024x768 certes).
C'est normal en fait, il y a juste une petite faute de frappe dans le sujet. Il s'agit du ÇALAGEngine en fait, il touche au but !
(Toutes mes excuses, elle me démange depuis quelques jours celle-là).
Par contre je suis assez bluffé par le rendu, c'est vraiment très beau et je ne pensais pas qu'on pouvait obtenir un résultat pareil avec de la "fausse" 3D ... J'ai l'impression de voir des percées technologiques à chaque fois que je lis un nouveau post sur ce sujet ^^.
Abandonner ses rêves n'est pas à la portée de tout le monde.
Comme dirait certains : C'est de toute beauté !
C'est le running gag par chez moi aussi.C'est normal en fait, il y a juste une petite faute de frappe dans le sujet. Il s'agit du ÇALAGEngine en fait, il touche au but !
(Toutes mes excuses, elle me démange depuis quelques jours celle-là).
C'est parce que beaucoup (la plupart ?) des méthodes de rendu temps réel actuelles utilisent uniquement les informations présentent à l'écran pour des raisons de performances (d'où tous ces Screen Space algorithmes qui tournent en deferred shading) et donc s'appliquent aisément à la fausse 2.5D.Par contre je suis assez bluffé par le rendu, c'est vraiment très beau et je ne pensais pas qu'on pouvait obtenir un résultat pareil avec de la "fausse" 3D ... J'ai l'impression de voir des percées technologiques à chaque fois que je lis un nouveau post sur ce sujet ^^.
Je trouve les avancés très bien, mais il y a quelque chose qui me titille au niveau du mouvement des vagues. On dirait juste des ondulations de la hauteur et non des vagues qui se fracassent sur les objets. Ne serait-ce pas plus efficace de faire une simulation de particules ? Je doute, car vous êtes en 2D.
J'aimais bien ce qu'il y avait dans AoE 2 et AoE 3 :
Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi
Ma page sur DVP
Mon Portfolio
Qui connaît l'erreur, connaît la solution.
Ce que je fais actuellement ne laisse pas la place pour faire une simulation de la dynamique du fluide de la vague en fonction de la scène (et je ne suis pas sûr que ça soit envisageable en temps réel ?).Je trouve les avancés très bien, mais il y a quelque chose qui me titille au niveau du mouvement des vagues. On dirait juste des ondulations de la hauteur et non des vagues qui se fracassent sur les objets. Ne serait-ce pas plus efficace de faire une simulation de particules ? Je doute, car vous êtes en 2D.
Cependant, il est dans mes prochains objectifs de simuler l'écrasement de la vague, en générant de la mousse quand elle se referme sur elle-même, pour simuler une vague qui arrive sur la terre ferme (la différence de profondeur change la forme de la vague). Ce que j'ai pour le moment correspond plus avec une vague relativement loin de la côte.
Je compte aussi ajouter une déformation pour avoir des vagues courbent. Mais cela restera quelque chose de prégénéré (en gros, il faudra juste changer la fonction que je fais manger à mon générateur de texture d'eau je pense).
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager