Оптимизация видимости

From Valve Developer Community
Revision as of 20:38, 2 August 2015 by Alvagor (talk | contribs) (Листья)
Jump to: navigation, search
English Español

Без "видимости", карта прорисовывает все предметы независимо от того, видит их игрок или нет. Очевидно, какие-то объекты нужно исключить из обработки, но как? Проверка каждого объекта на степень загрузки видео займет много времени.

Движок игры должен создавать компромисс; Source - это модель Binary Space Partition, основанная John Carmack, реализованная в Quake. Данная страница объясняет, как это работает и как этим манипулировать.

Листья

Листья в коридоре.

Интерьер (т.е. не занятое брашами world brush) пространство карта BSP разделяет на листья visleaves. Видимость в этом 3-х мерном объеме рассчитывается во время компиляции карты, и встраивается в файл карты для использования движком. Как и браши, листья всегда выпуклые.

Рисунок слева показывает, как листья создаются в изгибах коридоров (промежутки между ними добавлены для ясности). Тут нет прямой видимости между листами 1 и 3, поэтому, когда камера находится в одном коридоре, содержимое другого не прорисовывается. Насколько это облегчает движок, видно по графику видимости, включенном в карту.

Но есть проблема с листом 2. Содержимое "всех трех" листов прорисовывается, когда камера находится внутри, усекая картинку конусообразно, даже если левая стена полностью закрывает вид. У нас есть инструменты для преодоления этого, и мы их скоро рассмотрим, но имейте в виду, что решить проблему будет труднее (expensive), нежели просто оптимально нарисовать сцену.

Постоянно имейте в виду, что displacement'ы, энтити point и brush (включая detail brushes), а также браши с поверхностями $translucent не влияют на листья. Создание браша world brush с текстурой nodraw 'основано' на этой проблеме: это типично для дисплейсментов, созданных как деталь, покрывающая каркас обычных брашей.

Warning.png Предупреждение: Листья не будут создаваться, если на карте имеется утечка.
Tip.png Совет: Листья режутся каждые 1024 единицы в плоскости XY независимо от геометрии, таким образом разделяя большие пространства. Сетка Хаммера помогает вам учитывать это.
Note.png Примечание: Листья работают как по вертикали, так и по горизонтали. Тянутся с неба, проходят по улицам и опускаются в комнаты.

Сокращение времени компиляции VIS

VVIS - это инструмент, который рассчитывает видимость между листьями (в то время, как VBSP создает их). Расчет не занимает и нескольких минут даже для сложных карт, но если время затянулось, то проделайте следующие шаги.

  • Используйте detail brushes.
  • Размещайте world brush строго по сетке. Размер сетки лучше всего выставить на два.
  • Используйте простые браши. Не вырезайте (carve), если не уверены в результате.
  • Располагайте func_viscluster:ru (in all games since <Half-Life 2: Episode Two><Half-Life 2: Episode Two>) на больших площадях с не загороженным видом. Листья в нем будут видеть друг друга.
  • Не создавайте больших открытых пространств, которые игрок изначально не видит, если в этом нет необходимости. Используйте 3D Skybox, чтобы уменьшить размер неба и создайте скелет брашей под дисплейсментами.

Помните, что время компиляции VIS и производительность в игре - две очень разные вещи. Вполне может быть, что длительная компиляция стоит своего результата.

Inspecting leaves

The Orange Box version of Hammer has a new function to view the current map's leaves in the 3D view: Map > Load Portal File. This displays leaf edges that touch other edges as thick blue lines. It's a fantastic learning tool, as if you compile your map without VIS or RAD (then reload its portal file to refresh the display) you can see your changes' effects very quickly.

Episode One users must rely on the glview application.

Tip.png Tip: For even more clarity use auto visgroups to remove objects from your map that don't block visibility – i.e. everything but "World Geometry".

For in-game inspections, there is a console variable called "mat_leafvis". mat_leafvis 3 will outline all the visleaves in the PVS, while mat_leafvis 1 will just outline the leaf that the camera is currently in. (This variable is a cheat.)

You can also inspect the geometry itself through using the mat_wireframe console variable. mat_wireframe 1 will display how polygons are drawn in the current PVS. (This variable is a cheat as well.)

Hints

tools\toolshint
All leaves draw at the same time until we hint.

Unfortunately, leaves don't always work out so well as they did in our first example. Consider the alternative layout on the left (in practice things would be configured as per the first image, but put that aside for a moment): in this example the leaves can all see each other, leading to the whole area being drawn at once for no good reason. This is where Hints come in.

A hint is a brush face textured with the special tools\toolshint material, which slices any leaves it intersects in two (faces of the brush that should not split leaves must be textured with tools\toolsskip). In our example, we would place a hint where the purple line indicates, so that it slices leaves 1 and 3 to the same shape that they were in our first example.

It isn't possible to merge leaves together, so after hinting there will be three separate leaves on the right-hand side. Thankfully this isn't a huge problem.

Tip.png Tip: It's a good idea to use hints to separate expensive and cheap areas of the same leaf, if doing so will reduce the amount of time that the expensive areas are drawn for.

Detail brushes

As was mentioned above, leaves are moulded around world brushes. But what if you don't want a brush to do that? If you have a brush that can be seen around at all times (e.g. a statue plinth, a small free-standing wall) there’s no point in creating lots of extra leaves around it.

In these situations you want func_detail. It's an internal entity which makes the compilers ignore the brush when calculating visibility, without otherwise affecting its behaviour. It's not uncommon for large portions of a map's brushes to be detail.

Nodraw surfaces

tools\toolsnodraw

If a player cannot see a brush face without cheating or being a spectator, it's a good idea to apply the special nodraw material to it. Nodraw removes the entire face when the map is compiled without affecting visibility, which reduces both rendering time and, since no lightmap needs to be calculated, map filesize.

You do not need to apply nodraw to faces that are touching the void (i.e. outside the map) or to brush faces touching other brush faces tied to the same entity (the world being one big entity of its own). See Brush#In-game.

Areaportals

tools\toolsareaportal
Teal lines indicate good areaportal locations.

In the image to the left all of the leaves can see each other, and this time there is very little that hint brushes can achieve.

In this situation we should create Areaportals at the mouth of selected openings. These make the engine perform the per-object line of sight testing that Carmack created the BSP/visleaf system to avoid – but with that system behind it, and with the calculations restricted to when the camera looks through the areaportal, performance can be gained if one blocks enough objects from view.

The image has areaportal locations marked over each mouth, but placing all four would likely hinder performance more than help it. Your strategy depends on the relative cost of each area - in most situations, creating the large areaportal to the right and leaving the corridors alone would be best.

(It is possible to use hints to reduce visibility in this situation, but only with a ridiculous number of them at very precise angles, which impacts performance in its own way. If you can't see across a room for hint brushes then you should be using an areaportal!)

Tip.png Tip: Areaportals are also useful because they can be closed to completely and cheaply block visibility past them. It's a good idea to attach an areaportal to every window-less door in your map, so that they can automatically perform this function.
Note.png Note: Areaportals make no account for objects in front of them.
Warning.png Warning: Areaportals can cause problems if placed incorrectly, so be sure to read about them carefully.

Occluders

tools\toolsoccluder

Sometimes you want to block visibility in a way that visleaves simply don't allow: consider a destructible free-standing wall behind which are standing several expensive character models. You don't want to draw the models if they aren't being seen, but without any connected world brushes to work with except the ground you can't do it by separating leaves.

An Occluder is the tool for the job. It's a brush that hides models (not brushes, alas) behind it when enabled in a similar manner to an areaportal hiding things that aren't behind it. For obvious reasons, it should be entirely contained inside an opaque object.

Draw distance

If you are dealing with a large open area without any cover at all then there isn't a lot you can do but remove detail or employ fog to disguise a low draw distance. Configure draw distance with Map > Properties > Far z_clip plane.

Draw distances can also be applied selectively to props, even prop_static, with the Start Fade Dist/Pixels and End Fade Dist/Pixels keyvalues. As the names suggest, these values can represent either distance in units or pixels on-screen as per the Screen Space Fade KV.

If you enter fade distances on props, it’s a good general rule to have the difference between the two numbers (start and end) be 200. It looks pretty good, and the larger that number is, the longer the model incurs an increased cost to render. Fading models do not go through the fast path and incur additional sorting cost.

func_lod is a special brush entity that can fade out. You can't use any brushes tied to it as any other entity, however!

Sample maps

  • sourcesdk_content\hl2\mapsrc\
    • sdk_func_detail.vmf
    • sdk_hints.vmf
    • sdk_occluders.vmf

<< Return to Optimization (level design)

See Also

  • Func_lod (World detail that doesn't need to be drawn far away, for performance reasons.)