L’eau dans les maps Source : bien la mettre en place et corriger les bugs
L’eau dans les maps Source et GMod : structure du brush d’eau, eau coûteuse ou économique, water_lod_control, cubemaps et correctifs des bugs de rendu.
Dans le Source Engine, l’eau est un world brush dont la face supérieure porte un matériau d’eau, tandis que tous les autres côtés reçoivent tools/toolsnodraw. Il lui faut aussi un water_lod_control, une enveloppe étanche de brushes solides et des entités env_cubemap pour le chemin de rendu économique. Quand l’eau s’affiche mal, c’est en général pour l’une de ces quatre raisons : le brush est lié à une entité, la map a un leak, deux surfaces d’eau à des hauteurs différentes sont visibles depuis le même endroit, ou les cubemaps manquent.
Comment se construit un brush d’eau
- Crée un brush qui remplit tout le volume d’eau, du fond jusqu’à la surface.
- Applique
tools/toolsnodrawsur tout le brush. - Ne donne un matériau d’eau qu’à la face supérieure, par exemple
nature/water_canals_water2. - Laisse le brush en world brush. Ne le lie ni à
func_detailni à aucune autre entité. - Entoure le bassin de world brushes solides et place un
water_lod_controldans la map.
Ces règles découlent d’un mécanisme. Les matériaux d’eau portent le paramètre %compilewater 1. VBSP découpe alors les visleafs le long de la surface de l’eau et enregistre exactement une hauteur pour chaque volume d’eau. C’est pourquoi la face supérieure doit être horizontale, et pourquoi cela ne fonctionne qu’avec des world brushes : avec un brush d’eau lié à func_detail, le VBSP de GMod n’a écrit absolument aucun volume d’eau dans le BSP lors d’un test (leafwaterdata 0).
L’eau n’est pas non plus solide. Si un brush d’eau remplace un mur extérieur, VBSP signale **** leaked ****. L’article corriger l’erreur de leak d’une map explique comment trouver l’ouverture.
Les côtés restent en nodraw, car sinon ils sont compilés comme des faces. Avec un matériau d’eau sur les six côtés, le test a produit 60 faces au lieu de 40. VBSP crée lui-même la vue de dessous, à partir du paramètre $bottommaterial du matériau.
Eau coûteuse et eau économique
La même eau peut être dessinée de trois façons :
| Rendu | Reflet | Vue sous la surface | Passes de rendu supplémentaires |
|---|---|---|---|
| Coûteux | Temps réel | Réfraction | Deux, pour le reflet et la réfraction |
| Moyen | Cubemap | Réfraction | Une |
| Économique | Cubemap | Pas de réfraction | Aucune |
Le moteur décide à chaque image quelle variante s’applique. Le wiki de la Valve Developer Community (VDC) ne distingue que coûteux et économique ; « moyen » est notre nom pour l’état intermédiaire. L’ordre suivant provient du code client publié du Source SDK 2013. GMod utilise sa propre branche du moteur, des détails peuvent donc différer.
- Si le matériau définit
$forcecheap 1, l’eau est toujours économique.nature/water_canals_cheap001en est un exemple. - Un reflet en temps réel exige une
$reflecttexturedans le matériau et, en plus, soit$forceexpensive 1, soit le réglage du joueurr_waterforceexpensive 1. La plupart des matériaux d’eau fournis avec HL2 définissent$forceexpensive 1, y comprisnature/water_canals_water2. - Sans reflet en temps réel, c’est la distance qui décide. À partir de la distance de fin du
water_lod_control, l’eau est dessinée en économique, en dessous avec réfraction et cubemap.
Tu fixes donc le rendu surtout par ton choix de matériau. Le reflet par cubemap doit malgré tout fonctionner en permanence, car l’eau moyenne et l’eau économique se rabattent dessus. L’eau coûteuse dessine de grandes parties de la scène jusqu’à trois fois. L’article optimiser les performances d’une map GMod montre comment mesurer ce genre de coûts.
Bien utiliser water_lod_control
Cette entité règle, pour toute l’eau de la map, la distance à la caméra à partir de laquelle le moteur passe à l’eau économique.
| Keyvalue | Nom dans Hammer | Valeur par défaut |
|---|---|---|
cheapwaterstartdistance | Start Transition to Cheap Water | 1000 |
cheapwaterenddistance | End Transition to Cheap Water | 2000 |
Les deux valeurs sont en unités. Entre le début et la fin, le matériau effectue un fondu progressif, à condition de contenir le proxy WaterLOD, comme c’est le cas des matériaux d’eau fournis d’origine.
Si l’entité manque, la compilation ne s’arrête pas. VBSP en crée une avec les valeurs par défaut et écrit :
Water found with no water_lod_control entity, creating a default one.
Places-en une toi-même malgré tout, pour adapter les distances à ta map. N’en attends pas trop pour autant : d’après le code du SDK et le VDC, la distance ne s’applique pas aux matériaux avec reflet en temps réel.
L’eau à des hauteurs différentes
Le VDC énonce la règle : avec de l’eau coûteuse, il ne peut y avoir qu’une seule hauteur d’eau dans un PVS, l’ensemble des zones visibles depuis un endroit. Le code du SDK montre pourquoi : à chaque image, le client détermine un seul volume d’eau visible et rend le reflet et la réfraction pour cette hauteur précise. Une deuxième surface à une autre hauteur reçoit alors des images calculées pour le mauvais plan. Nous n’avons pas testé en jeu à quoi cela ressemble exactement. Il n’y a aucun avertissement : une map de test avec deux bassins à des hauteurs différentes a compilé sans le moindre message.
- Une hauteur par zone visible. Sépare les bassins de hauteurs différentes par des world brushes, de sorte qu’ils ne se retrouvent jamais dans le même PVS.
- Utilise la même hauteur. La règle ne concerne que les hauteurs différentes. Plusieurs bassins à la même hauteur partagent le plan de réflexion.
- Ne mélange pas les types. D’après le VDC, l’eau coûteuse et l’eau économique ne doivent pas non plus partager un PVS. Si deux hauteurs doivent rester visibles ensemble, donne à toute cette eau un matériau avec
$forcecheap 1. Elle reflète par sa cubemap.
Cubemaps, skybox 3D et displacements
Cubemaps. Les matériaux d’eau contiennent $envmap env_cubemap. L’eau moyenne et l’eau économique s’en servent pour refléter l’env_cubemap le plus proche. Places-en au moins un dans chaque zone contenant de l’eau et lance buildcubemaps après la compilation finale. Jusque-là, le BSP ne contient qu’un substitut tiré de la texture de la skybox. La marche à suivre est décrite dans corriger les reflets des cubemaps, et les bases du HDR se trouvent dans le guide de l’éclairage du Source Engine.
Skybox 3D. D’après le code du SDK, la skybox 3D est dessinée en une seule passe, sans reflet ni réfraction propres. Dans la skybox, utilise un matériau avec $forcecheap 1. D’après le VDC, de l’eau économique dans la skybox fonctionne à côté d’eau coûteuse dans la map. La hauteur découle de l’échelle, car la sky_camera représente l’origine de la map principale : si l’eau s’y trouve à Z = 128 et que la sky_camera a une échelle de 16, la surface dans la skybox doit se trouver 8 unités au-dessus de la sky_camera. À l’inverse, d’après le code du SDK et le VDC, le reflet en temps réel dans la map principale montre la skybox 2D et non la skybox 3D. Le VDC mentionne, pour CS:GO et Garry’s Mod, un paramètre de matériau $reflect3dskybox censé changer cela. Nous ne l’avons pas testé. Plus de détails dans le guide de la skybox 3D.
Displacements. Une rive faite de displacements ne rend pas plus la map étanche que l’eau elle-même. Prolonge le brush d’eau sous le terrain et place un world brush solide sous les deux. N’utilise le nodraw que là où le terrain le cache : le VDC met en garde contre un effet de traînée quand c’est du nodraw qui ferme l’eau. Plus de détails dans les displacements dans Hammer.
Erreurs typiques et leur cause
| Symptôme | Cause | Solution |
|---|---|---|
| Eau invisible ou mal rendue | Leak dans la map, ou brush d’eau lié à une entité | Fermer le leak, ramener le brush avec Tools → Move to World |
| Eau opaque ou avec un reflet cassé | Deuxième hauteur d’eau dans le même PVS, ou un func_viscluster ou un areaportal traverse la surface de l’eau | Séparer les hauteurs, tenir func_viscluster et les areaportals à l’écart de la surface |
| Reflet noir, en damier violet et noir, ou beaucoup trop clair | Les cubemaps manquent ou n’ont pas été générées pour le mode actif | Placer des env_cubemap, lancer buildcubemaps pour LDR et HDR |
| L’eau change soudain d’aspect au loin | L’eau sans reflet en temps réel passe en économique à partir de la distance de fin | Augmenter les distances dans water_lod_control, générer les cubemaps |
**** leaked ****, la ligne traverse l’eau | Eau utilisée comme limite extérieure | World brushes solides autour du bassin |
Si l’eau disparaît complètement à distance, il n’existe pas de cause unique documentée. Vérifie d’abord si une deuxième hauteur d’eau entre dans le champ de vision. Tu peux aussi coller le compile log dans le Map Scanner. Il repère les causes premières, les erreurs en cascade et les correctifs adaptés dans les logs de VBSP, VVIS et VRAD.
Questions fréquentes
Le niveau de l’eau peut-il monter ou descendre ?
Oui, avec func_water_analog. L’entité déplace un brush d’eau via les inputs Open, Close et SetPosition. Le shader d’eau normal n’y fonctionne pas, car il a besoin de visleafs fixes. Utilise un matériau comme nature/water_movingplane. Il ne reflète que par la cubemap.
L’eau reflète-t-elle aussi les joueurs et les props ?
Seulement si le matériau définit $reflectentities 1 ou si le joueur a activé r_waterforcereflectentities 1. Sinon, le reflet en temps réel ne contient que le monde et le ciel.
De quoi a besoin un matériau d’eau custom ?
Au minimum %compilewater 1, $abovewater, $fogcolor, $bottommaterial et $envmap env_cubemap. Si $abovewater ou $fogcolor manque, le shader avertit dans la console. Si $bottommaterial manque, c’est VBSP qui avertit. Pour la transition douce à distance, ajoute le proxy WaterLOD.