王者荣耀孙尚香被ⅹ漫画|王者荣耀兰陵王秒人连招
開啟輔助訪問

QQ登錄

注冊 找回密碼
深夜
查看: 2307
回復: 51
打印 上一主題 下一主題

地圖編輯 【開放大世界】地圖生成,地平線:黎明時分GPU程序化生成環境的秘密

 

TA的畫板

16萬

元素幣

22萬

活躍度

411

貢獻值

界王神

亞人

Rank: 8Rank: 8Rank: 8Rank: 8Rank: 8Rank: 8Rank: 8Rank: 8

積分
476309

元素銅幣元素銀幣元素金幣元素秘幣神界之石裁決滿天星【元素晶石】不死鳥羽翼風暴符文至尊皇鉆擴散者水晶礦宇宙魔方吃雞頭盔振金項鏈英雄盾紅龍戰甲

主題
124
精華
11
擴散
55
首發
1
土豪金
3161
神石
2560
在線時間
1214 小時
跳轉到指定樓層
樓主-元素創造者
發表于 2019-5-6 02:14:33

馬上注冊成為元素者,獲取海量元素資源,結識各路大神級人物

您需要 登錄 才可以下載或查看,沒有帳號?注冊

x
地平線:黎明時分開放大世界地圖生成,GPU程序化生成環境的秘密
元素獨家發布:轉載請說明出處

先來看看開場背景介紹,下方視頻的內容程序化生成的場景和原來的裸地形場景


相關文檔,視頻,PPT下載鏈接:
價格:10元素幣 銷售總額:970元素幣 購買人數:97

尊敬的游客 ,本內容需要支付 10元素幣 來下載,您可以充值或者發帖分享。也可使用擴散 懸賞 任務獲取元素幣,來下載。



技術分享
  • 程序化地圖生成是近幾年主機平臺3A大作的核心技術點,能夠熟練操作這種技術的游戲廠商在世界范圍內也是屈指可數
  • 微元素將在這個技術領域盡可能分享,翻譯更多,更有技術含量的文章
  • 中英文對照,滿足學習專業術語人群,地圖編輯,技術美術,藝術指導等多個工種的需求
  • 本文的分享來自 Guerrilla 公司的技術總監
  • 為大家展示了一個豐富度,精度極高的開發大世界的環境創建思路
  • 游戲【地平線】中的渲染技術,地圖編輯技術有超過10余年的沉淀
  • 前幾年PS3游戲【殺戮地帶】和小島修復最新力作【死亡擱淺】都是出自這個引擎技術團隊
  • 游戲【地平線】是自研引擎,所以用這個引擎開發的游戲極少,相關資料在整個網絡也是不可能存在
  • 但是他們的地圖制作思路,技術手段是可以影響整個游戲行業



精彩技術學習點
  • 物種分配清單與資源占比,在性能、豐富度、精度、密度找到平衡點
  • 地形數據生成,houdini生成資源
  • 離散算法,規則化配比生成,隨機生成,放置到區域
  • 基于節點生成的地編數據,多通道混合計算植物生態分布
  • 道路通道編輯,非線性流程影響植被分布
  • 類似unity的map magic 工作流
  • GPU筆刷繪制區域植被,快速種植片區
  • 優化與數據結構,移動中分區塊加載




PPT正文:


Before we made Horizon, Guerrilla was known fortheir Killzone Franchise.
In our Killzone games, each square meter of alevel was manually polished. Guerrilla Games has always had high qualitystandards when it comes to our environment art.
Environment artists are experts in dressing upenvironments to look interesting and believable, using light, composition andcolor.
The open world of Horizon Zero Dawn led us toinvestigate how to create and dress a large open game world using proceduralsystems, while trying to stay true to that quality standard.
Historically, procedural systems have oftenlooked monotonous, bland and robotic, but they do allow for QUICK ITERATIONSand at the end of the day, a reduced time investment per square kilometer makeslarger world scales feasible.
Our goal was to create a system, in which anartist can describe a LARGE VARIETY of interesting and BELIEVABLE environments,which can be applied anywhere in the world.
But we had some restrictions. Both the systemand the resulting content should be highly ART DIRECTABLE and seamlesslyintegrate with manually placed art.
On top of this, our art director wanted to beable to freely move mountains, rivers and gameplay without the need to continuallyredress the world.
That means that the system should be fully datadriven, deterministic and locally stable.

在我們制作《地平線》之前,Guerrilla公司以殺戮地帶系列而聞名。在我們的殺戮地帶游戲中,每一關的每平方米都是手工打磨的。游擊戰游戲在我們的環境藝術中一直有著高質量的標準。環境藝術家擅長運用光線、構圖和色彩來裝扮環境,使其看起來有趣而可信。《零點黎明》的開放世界讓我們研究如何使用程序系統創造并裝扮一個大型的開放游戲世界,同時努力保持游戲的質量標準。從歷史上看,程序系統常常看起來單調、乏味和機器人化,但它們確實允許快速迭代,而且在一天結束時,每平方公里的時間投資減少使更大的世界規模成為可能。我們的目標是創建一個系統,在這個系統中,藝術家可以描述大量有趣和可信的環境,這些環境可以應用于世界上的任何地方。但是我們有一些限制。系統和生成的內容都應該是高度藝術可直接訪問的,并與手工放置的藝術無縫集成。最重要的是,我們的美術總監希望能夠自由移動山脈、河流和游戲玩法,而不需要不斷糾正世界。這意味著系統應該完全由數據驅動,具有確定性和局部穩定性。

We started off with the more traditionalprocedural workflow of using procedural definitions and off-line bakes placeour hand-authored assets from our procedural definitions.
We had already experimented a bit with thisidea during Shadowfall, but the bake times were a big problem and iteration wasslow.
Looking for a solution, we tried moving ourprocedural placement OVER TO GPU, in an effort to reduce bake times.
When we were looking at the placement speed ofour first GPU prototype, we quickly realized that this was the way to go.
In fact, the results were looking so good, thatwe decided to try to make the system fully REALTIME, as this would not onlyremove bakes altogether, but it would also help reduce the amount of data wewould have to store, and stream from disk.
This would mean, that we would be activelygenerating the environment from procedural logic, and update the world whilethe player moves through it.
In order to accomplish this on the GPU whilestill being deterministic and locally stable, we have chosen to go with DENSITYBASED SYSTEM, which means that our procedural logic does not directly placeobjects. Instead the procedural system generates 2D density maps, which arethen discretized into a point cloud of objects.

我們從使用過程定義的更傳統的過程工作流開始,離線烘焙將手工創建的資產從過程定義中放置。我們已經在Shadowfall中嘗試了這個想法,但是烘焙時間是一個大問題,迭代很慢。為了尋找解決方案,我們嘗試將過程性布局轉移到GPU,以減少烘焙時間。當我們觀察第一個GPU原型的放置速度時,我們很快意識到這是我們要做的事情。事實上,結果看起來很好,我們決定讓系統完全實時,因為這不僅可以完全消除烘焙,而且還可以幫助減少我們必須存儲的數據量和磁盤流。這意味著,我們將從過程邏輯中積極地生成環境,并在玩家移動時更新世界。為了在GPU上實現這一點,同時保持確定性和局部穩定性,我們選擇了基于密度的系統,這意味著我們的過程邏輯不會直接放置對象。相反,程序系統生成2D密度圖,然后將其離散為一個點云對象。


Our prototype started small, but we keptgetting requests about expanding the system from our sound, effects and evengameplay teams.
During the development of Horizon, it grew intoa rather versatile system.
You see the game running behind me, and you canreally see the difference the placement system makes to the game, especiallywhen you turn it off.
As you can see, almost the entirety of thevegetation of Horizon zero dawn is procedurally placed.

我們的原型開始很小,但是我們不斷收到來自聲音、效果甚至游戲團隊關于擴展系統的請求。在地平發育的過程中,它發展成為一個相當多用途的系統。你看到游戲在我身后運行,你真的可以看到放置系統對游戲的影響,特別是當你關閉它的時候。如你所見,幾乎所有地平線零黎明的植被都是按程序放置的。

We ended up with the procedural placementmanaging around 500 types of objects at any given time. During normal gameplay,the dedicated rendering back-end is managing around 100.000 placement meshesaround the player when the player explores the world.
This is a lot more than what we had originallyscoped for the system; we ended up placing not only vegetation and rock meshes,but also effects, gameplay elements (like pickups) and wildlife.
To support all of this, we were continuallytinkering with our GPU placement pipeline and its dedicated rendering pipelineto keep things in budget, which averages around 250 per frame when the playeris moving through the world。

最后,我們在任何給定的時間對大約500種對象進行了程序化的放置管理。在正常的游戲中,當玩家探索世界時,專用的渲染后端在玩家周圍管理大約100000個放置網格。這比我們最初為這個系統確定的范圍要大得多;我們最終不僅放置了植被和巖石網格,還放置了效果、游戲元素(如拾音器)和野生動物。為了支持所有這些,我們不斷地修補我們的GPU放置管道及其專用的渲染管道,以保持預算,當玩家在世界各地移動時,平均每幀250個。

As I said earlier, one of our goals was to havea large amount of variety within the world of horizon.
To accomplish this, we broke the world downinto different unique environment types that we could then design and buildindependently. In the real world; classification of natural environments isdone through the concept of ECOTOPES.
We decided to adopt this concept, and westarted by defining our version of an ecotope.
An ecotope defines the biodiversity andgeographical characteristics of a particular area.
In practice this includes what type of ASSETSneed to be placed and HOW. In drives the COLORIZATION of rocks and vegetation,determines WEATHER patterns, EFFECTS, SOUND and WILDLIFE.
It follows that each ecotope will need to haveits own procedural design, and so this is where we start our proceduralauthoring.
就像我之前說的,我們的目標之一是在視野范圍內擁有大量的多樣性。為了實現這一點,我們將世界分解為不同的獨特環境類型,然后我們可以獨立地設計和構建它們。在現實世界中;通過生態位的概念對自然環境進行分類。我們決定采用這個概念,從定義我們的生態小區開始。生態小區定義了特定區域的生物多樣性和地理特征。在實踐中,這包括需要放置什么類型的資產以及如何放置。在驅動巖石和植被的顏色,決定了天氣模式,影響,聲音和野生動物。因此,每個生態區都需要有自己的過程設計,這就是我們開始程序創作的地方。

Our goal was to populate the world in anatural, Believable and interesting manner as a good environment artist wouldmanually accomplish.
To get as close to this goal as possible, weneeded to create a system that captures our artists logic, expertise and skill.
Therefore, the system was designed in such away that our artists could have full control on not only the INPUT DATA butalso the system’s PROCEDURAL LOGIC. And of course we will still be using handauthored individual ASSETS.
我們的目標是用一種自然、可信和有趣的方式來填充這個世界,就像一個優秀的環境藝術家手工完成的那樣。為了盡可能接近這個目標,我們需要創建一個系統來捕獲我們的設計師的邏輯、專業知識和技能。因此,系統的設計使我們的設計師不僅可以完全控制輸入數據,而且可以控制系統的過程邏輯。當然,我們仍將使用手工創建的單個資源。

So what data do we need to create convincing,natural looking ecotopes.
Well, we didn’t know either […]so we just started building, adding data as we needed and keeping a tightmemory budget. In the end we had a large amount of data that described theworld to not only the placement system, but all other game systems as well.
We call this our WorldData, which is aCOLLECTION OF 2D MAPS that we can access across our gameplay systems, and whichare also used as the base inputs of our procedural system. These maps arecontinuously STREAMED IN SECTIONS around the player and fed into the ecotope’s placement logic.
Most maps are initially seeded using variousBAKE PROCESSES such as WorldMachine and tools like Houdini. We have additionalpaintable layers on top of these base maps, so artists can EDIT THE MAPS withour in-game editor through brushes or other tools.
The Procedural Placement System USES ABOUT4MB/km2 worth of this maps exclusively. This comes down to a data footprint ofabout 32 bits per square meter.
Lets give you an idea about what kind of datawe ended up with in our game
那么,我們需要什么樣的數據來創建令人信服的、看起來自然的生態系統呢?嗯,我們也不知道[…],所以我們只是開始構建,根據需要添加數據,并保持嚴格的內存預算。最后我們獲得了大量的數據,這些數據不僅向安置系統描述了這個世界,也向所有其他游戲系統描述了這個世界。我們將其稱為WorldData,這是一組2D地圖,我們可以通過游戲系統訪問它們,它們也被用作程序系統的基本輸入。這些地圖不斷地在玩家周圍流動,并被輸入到生態墻面的布局邏輯中。大多數地圖最初都是使用各種烘焙過程進行播種的,比如WorldMachine和Houdini這樣的工具。我們在這些基礎地圖上添加了額外的可繪制圖層,因此藝術家可以通過畫筆或其他工具使用游戲內編輯器編輯地圖。程序布局系統僅使用了大約4MB/km2的這種地圖。這歸結為每平方米大約32位的數據占用。讓我們來給你一個關于我們在游戲中最終得到的數據類型的概念。

Here is a section of one of the most widelyused world data maps, called Placement_Trees. It was originally baked from worldmachine, but later extensively HAND PAINTED to fit art direction and gameplayrequirements.
Artists always want to pack as much data inthese kinds of maps as possible.
To that end, they designed some sharedPROCEDURAL LOGIC to encode additional information out of these maps.
This particular map, Placement_Trees , acts asour main tree placement map.
It can be used as a density map, but ecotopesoften encode additional meaning to it.
[picture, gradient, soft brush]
Within an ecotope they can then hook in Lush “Edge trees” on values near zero and high branchless Inner Trees on values nearone.
[picture, graph]
This is an example where artist control overboth the data and the placement logic really helps to create a more naturallook. Even better, it also solves a visibility requirement from design withoutthe need of programmer support.
這是一個最廣泛使用的世界數據地圖之一Placement_Trees的一部分。它最初是從世界機器上烘焙出來的,但后來廣泛地手繪以適應設計指導和游戲要求。設計師總是希望在這類地圖中包含盡可能多的數據。為此,他們設計了一些共享的過程邏輯來從這些映射中編碼額外的信息。這個特殊的映射Placement_Trees用來充當我們的主樹位置映射。它可以用作密度圖,但是生態系統通常會為它編碼額外的含義。[圖片,漸變,軟筆刷]。在一個生態系統中,它們可以在接近零的值上鉤住茂盛的“邊緣樹”,在接近1的值上鉤住高的無枝內部樹。[圖片,圖表]。在這個例子中,設計師對數據和布局邏輯的控制確實有助于創建更自然的外觀。更好的是,它還解決了設計中的可視性需求,而不需要程序員的支持。

There are many other types of world data. Mostof them are BC7 compressed.
Resolution varies across different types,ranging from 1m to 4m resolution.
Lets quickly look at a few more maps before wemove on.
還有許多其他類型的世界數據。其中大部分是BC7壓縮的。分辨率因不同類型而異,從1m到4m不等。在我們繼續之前,讓我們快速地看一下更多的地圖。

Here we see the road data, which is painted bythe road tool, and the object data, which is generated from non-proceduralobjects within the game.
Because the procedural system is map based,world data maps like these are the main way it can read the the rest of thenon-procedural content.
You can imagine, that when an artist designsthe procedural logic for an ecotope, artists have to make sure that the ecotopereacts naturally to things like roads, rocks and rivers.
And big part of ecotope logic revolves aroundreading these kinds of maps and defining areas such as “side of the road”, “next to a rock”or as we just saw “edge of a forest”.
These structures can get rather complex,luckily these definitions can be made once and then shared between ecotopes.
在這里,我們看到了道路數據(由道路工具繪制)和對象數據(由游戲中的非程序對象生成)。因為程序系統是基于地圖的,所以像這樣的世界數據地圖是它讀取其他非程序內容的主要方式。你可以想象,當設計師為生態區設計程序邏輯時,設計師必須確保生態區對道路、巖石和河流等自然反應。生態系統邏輯的很大一部分是圍繞著閱讀這些地圖和定義諸如“路邊”、“石頭旁邊”或我們剛才看到的“森林邊緣”等區域。這些結構可能會變得相當復雜,幸運的是,這些定義可以只定義一次,然后在生態園之間共享。



Our height maps are also part of the worlddata, and these maps are used in logic graphs and as a placement height for ourprocedural objects.
We have several layers of heightmaps, so we canplace things not only on the ground, but also on top of objects, and the watersurface.
我們的高度映射也是世界數據的一部分,這些映射用于邏輯圖中,并作為程序對象的放置高度。我們有好幾層高度圖,所以我們不僅可以把東西放在地面上,還可以把東西放在物體和水面上。

Finally some generated maps; these come out ofworld machine and are almost never painted by artists. We use these kind ofnatural maps to create realistic variations and environmental reactions withinour ecotopes.
I think you all get the idea; lets move on。
最后一些生成的地圖;這些來自世界機器,幾乎從未被藝術家繪制過。我們使用這些自然地圖來創造現實的變化和生態系統內的環境反應。我想你們都明白了,我們繼續。

So I hope this gives you an idea of our inputdata, and how artists can bake and paint into them.
So we’ve seen how artists can setup andmanipulate world data; now lets take a look at the logic side of things.
In short, we use logic networks; similar tonuke, substance or any other shader builder tool out there.
We’ve already seen some hints at sharinglogic, and using tools such as curves, these are all aspects of the densitynetworks that artists can click together.
The purpose of a logic network is to generate asingle density map, which can be linked to assets, or sets of assets, usingworld data is its input. Those density maps are then discretized into a cloudto actually instance the linked assets in the world.
Lets see how we can combine world data mapsinto a density map.
所以我希望這能讓你了解我們的輸入數據,以及設計師如何在數據中烘焙和繪畫。我們已經看到了設計師如何設置和操作世界數據;現在讓我們看看事物的邏輯方面。簡言之,我們使用邏輯網絡;類似于核、物質或任何其他著色生成器工具。我們已經看到了一些關于共享邏輯的提示,使用曲線等工具,這些都是設計師可以點擊在一起的密度網絡的各個方面。邏輯網絡的目的是生成一個單一的密度圖,使用世界數據作為輸入,該密度圖可以鏈接到資產或資產集。然后將這些密度圖離散為一個云,以實際來舉例世界上的鏈接資產。讓我們看看如何將世界數據地圖合并成一個密度地圖。

In this example, lets say we are designing thelogic for placing a tree within an ecotope.
As a starting point, we’ll bring up a world data nodethat links in the placement_trees map we saw earlier.
We can hook this up as the density of our treeasset directly, but then we’ll get trees placed in water, through rocks and roads.
So to remove the rocks, we multiply out theobject map, by multiplying the values together.
Then we do the same with the water map and theroad
The result looks like this, you end up with amap that defines the valid areas for trees.
This logic graph can then be referenced by notonly the trees, but also it can be linked into other logic that want to knowwhere trees might be placed.
NextSlide: our first ecotope。
在本例中,假設我們正在設計將樹放置在生態區中的邏輯。首先,我們將打開一個worlddata節點,它鏈接到我們前面看到的placement_trees映射中。為了移走石頭,我們用物體圖乘以這些值。我們可以直接把它和樹的密度聯系起來,然后我們把樹放在水中,穿過巖石和道路。你最終得到的一個定義了樹的有效區域的地圖。這個邏輯圖不僅可以被樹引用,還可以被鏈接到其他想知道樹可能放在哪里的邏輯中。下一步:我們的第一個生態圈。

Here we have our forest ecotope assetdefinition. It consists of trees and plant assets grouped in a hierarchicalstructure. The leaf nodes on the right link to actual resources, called the(placement) targets, which will be instantiated across the ecotope.
Now for each asset, we define the Footprint,which defines the effective diameter of the object within the placement system.
The discretezation algorithm will use thefootprint to space out objects and perform collision avoidance. You can seethat the large meshes such as trees are placed six meters apart, while theundergrowth meshes are only one meter apart.
Since there is no logic linked in yet, all theassets will have full density. The density maps of the individual assets willbe fully white.
Ok, let’s load it into the game。
這里有我們的森林生態資產定義。它由樹和植物資產組成,按層次結構分組。右邊的葉節點鏈接到實際資源,稱為(放置)目標,將在Ecotope中實例化。現在,對于每個資源,我們定義了足跡,它定義了放置系統中對象的有效直徑。離散化算法將使用足跡來劃分對象空間并執行碰撞避免。可以看到,像樹這樣的大網格相距6米,而灌木叢網格僅相距1米。由于還沒有邏輯關聯,所有資產都將具有完全密度。單個資產的密度圖將完全為白色。好的,讓我們把它加載到游戲中。

Before capturing this movie, I’ve had to lower the bushdensity, because the bushes were covering the ground completely, obscuring thegrass.
Other than that this is the direct proceduraloutput of the simple graph we just made, without any logic to speak of.
在拍攝這部電影之前,我不得不降低灌木的密度,因為灌木完全覆蓋了地面,模糊了草地。除此之外,這是我們剛才制作的簡單圖形的直接過程輸出,沒有任何邏輯可言。

It’s a good starting point, but let’s layer a little bit of logic into it.
First we load up a world data map and apply itdirectly to the root forest node in our placement graph; CLICK
Now that the forest node has a density maplinked to it, it will pass its density on on to its child nodes.
Lets take it one step further; Let’s define a clearing in ourforest.
We link in a new WD map, we’ll call it clearing CLICK
Now we want to remove things from clearings,not add things, so we add an inverse node. CLICK
And now we link it into the trees and bushes.CLICK
So while the forest as a whole will stilllistens to the tree map, inside the forest, we can now paint a clearing thatwill reduce the density of all bushes, and all trees.
So lets run this in-game, there won’t be any world data mapsfilled in that area, so we’ll have to paint in the treemap and the clearing map ourselves.
這是一個很好的起點,但讓我們在其中加入一點邏輯。首先,我們加載一個世界數據地圖,并將其直接應用于我們的布局圖中的根森林節點;現在單擊forest節點有一個鏈接到它的密度映射,它將把它的密度傳遞給它的子節點。讓我們更進一步;我們定義一個森林中的空地。鏈接到一個新的WD地圖,我們稱之為清除點擊,現在我們要從清除中刪除內容,而不是添加內容,所以我們添加一個反向節點,點擊。現在我們把它連接到樹和灌木叢中,點擊。因此,當森林作為一個整體仍在聆聽樹木地圖時,在森林內部,我們現在可以繪制一個空地,它將降低所有灌木和所有樹木的密度。所以讓我們在游戲中運行這個,在那個區域不會有任何世界數據地圖,所以我們必須自己在樹地圖和清除地圖中繪制。

First we have to paint in the forest map, thisstarts black, giving it a starting density of zero.
Next, lets paint in the clearing map, creatinga clearing within the forest.
This is all very basic, but it shows how easilyan artist can setup a piece of procedural logic.
In production, the ecotopes ended up being verycomplex; artists could create deep systems of asset groups and logic networks.
首先我們要在森林地圖上繪制,這開始是黑色的,給它一個初始密度為零。接下來,讓我們在清除地圖中繪制,在森林中創建一個清除。這都是非常基本的,但它顯示了設計師可以多么容易地設置一段過程邏輯。在生產過程中,生態系統變得非常復雜;設計師可以創建資產組和邏輯網絡的深層系統。

That small network we just made looks like thisin our editor framework.
CLICK
For instance, this is one of our most complexlogic networks, containing a large amount of our shared area logic, which isused across ecotopes. You make them once, and then share them between ecotopes.
Now lets load in a full fledged ecotope, andsee how it reacts to the world around it
NextSlide: movie

我們剛剛創建的小型網絡在編輯器框架中是這樣的,點擊,例如,這是我們最復雜的邏輯網絡之一,其中包含大量跨生態系統使用的共享區域邏輯。你做了一次,然后在生態系統之間分享。現在讓我們加載一個成熟的生態系統,看看它如何對周圍的世界作出反應。下一步:電影

So here we have another part of the world,where a full fledged ecotope has already been applied. Let’s see how it reacts to world data.Here is me trying to use the editor
因此,我們在世界的另一個地方,一個成熟的生態系統已經被應用。讓我們看看它對世界數據的反應。這是我試著使用編輯器。
Here we are looking at the inverse; instead ofchanging the world data with our painting tools, we’re applying multiple ecotopesto the same area in the world.
在這里,我們看到的是相反的情況;我們不是用我們的繪畫工具改變世界數據,而是將多個生態位應用到世界的同一個區域。

Ok, let’s get into the technical details!
We have seen how to setup the logic, and how tolink in assets and assets groups. We’re done looking at the inputs of thesystem, now lets move on to our real-time algorithms.
Before we can do anything with our data, weneed to compile our authored content networks into a usable form. Our firststep is to flatten the graphs into more manageable units.
We iterate through all the assets within ourecotope logic, and convert them into a flat list of layers.
Each layer represents a run-time proceduralpayload, linked to a single asset. It contains all the information to calculatea density map from world data and populate an area within the world.
The logic network that is associated with it iscompiled into an INTERMEDIATE FORM. This representation can be compiled into acompute shader binary, or be fed direcly into a GPU based interpreter shaderthat we use for our debugging interfaces.
This intermediate form allows us to apply ofAUTHOR DRIVEN MERGING SEMANTICS; this merging step is necessary to reduce theamount of unique layers.
In practice it crunches down the amount oflayers around the player from several thousands, to several hundreds.
Now have our list of layers, lets see how theplacement of such a layer takes place on GPU. We start out with our originalplan of density map generation, followed by discretization.
好的,讓我們來了解一下技術細節!我們已經看到了如何設置邏輯,以及如何在資產和資產組中鏈接。我們已經完成了對系統輸入的研究,現在讓我們繼續研究我們的實時算法。在我們對數據做任何事情之前,我們需要將我們編寫的內容網絡編譯成一種可用的形式。我們的第一步是將圖展平為更易于管理的單元。我們遍歷Ecotope邏輯中的所有資產,并將它們轉換為一個簡單的層列表。每一層表示一個運行時過程負載,鏈接到一個資產。它包含了根據世界數據計算密度圖并填充世界中某個區域的所有信息。與之相關聯的邏輯網絡被編譯成一個中間形式。這個表示可以編譯成一個計算著色程序二進制文件,或者直接輸入到一個基于GPU的解釋器著色程序中,我們使用它來調試接口。這個中間形式允許我們應用作者驅動的合并語義;這個合并步驟對于減少唯一層的數量是必要的。實際上,它將玩家周圍的層數從幾千層壓縮到幾百層。現在有了我們的圖層列表,讓我們看看這樣一個圖層是如何在GPU上放置的。我們從最初的密度圖生成計劃開始,然后是離散化。

Our first part of the run-time pipelineevaluates the density graph for a SINGLE LAYER, within a given area in theworld. Under normal conditions, this is done by a precompiled compute shadercalled the densitymap shader, precompiled from the intermediate form stored inthe layer data.
Our entire placement pipeline scales up inGRANUARITY, depending on the footprint of the asset. Large objects such astrees are placed in big 128x128m blocks, while grasses are placed in 32x32blocks. Independent on the granularity, we have a fixed densitymap resolutionof 64x64 pixels per block.
我們的運行時管道的第一部分評估世界上給定區域內單層的密度圖。在正常情況下,這是由預編譯的計算著色器完成的,稱為densitymap著色器,該著色器是從存儲在層數據中的中間形式預編譯的。根據資產的足跡,我們的整個布局管道在Granuary中不斷擴大。大型物體如樹木被放置在128x128m的大區域內,而草被放置在32x32的區域內。獨立于粒度,我們有一個固定的密度圖分辨率為每塊64x64像素。

Here you can see the in-game debugginginterface, where artists can step through density calculations, and see theresulting discretization step. It’s also used to browse and inspect thehundreds of active layers.
This is the placement system running on a GPUintepreter, that could be easily halted, stepped through and debugged. The useof an intermediate representation and an interpreter turned out so versatile,we used it throughout the development of horizon.
You can see a density map being built, followedby the discretization step.
在這里,您可以看到游戲中的調試界面,在這里,藝術家可以逐步進行密度計算,并看到產生的離散化步驟。它還用于瀏覽和檢查數百個活動層。這是運行在GPU集成程序上的布局系統,可以很容易地停止、單步執行和調試。中間表示法和解釋器的使用非常廣泛,我們在horizon的整個開發過程中都使用了它。你可以看到正在構建一個密度圖,然后是離散化步驟。

After the densitmap step, we run the generatestep, which DISCRETIZES the density map into individual placements.
Our method is based on a technique calledordered dithering.
在密度圖步驟之后,我們運行生成步驟,該步驟將密度圖離散到各個位置。我們的方法基于一種稱為有序抖動的技術。

So here we have our super-realistic lookingdensity map.
Now if we downscale this, and apply ditheredfiltering, And then apply an ordered dithering on it (in photoshop), we end upwith something like this. CLICK
Now if we imagine creating an object on everywhite pixel, we have a form of discretization. CLICK
There are no objects on zero density pixels,with density increasing as the values become higher, until white has fullcoverage.
The process behind this is extremely simple:Each pixel is evaluated independently against a small repeated pattern ofthreshold values, and the result colors the pixels. Perfect for GPUs: Nodependencies, and a small dataset.
The most commonly used pattern in these kindsof dithering is a Bayer Matrix. CLICK
The numbers define the order in which thethreshold increases for a single output pixel. The pattern below shows theresulting image using a slowly incrementing input.
But lets’s be honest, it will be a bit obvious if wewould place all our assets in a pattern like this.
Luckily, we’re not tied down to pixel boundaries.
Next Slide
這就是我們的超高真實感密度圖。現在,如果我們縮小這個比例,應用抖動過濾,然后在上面應用有序抖動(在photoshop中)過濾,我們最終會得到類似這樣的效果。點擊。現在,如果我們想象在每個白色像素上創建一個對象,我們用一種離散化的形式。點擊。零密度像素上沒有對象,密度隨著值的增加而增加,直到白色完全覆蓋。這背后的過程非常簡單:每個像素都是根據一個小的重復的閾值模式獨立評估的,結果為像素著色。非常適合GPU:沒有依賴關系,數據集很小。在這種抖動中最常用的模式是Bayer矩陣。點擊。這些數字定義了單個輸出像素的閾值增加的順序。下面的模式使用緩慢遞增的輸入顯示結果圖像。但是老實說,如果我們將所有資產都放在這樣的模式中,那就有點明顯了。幸運的是,我們不受像素邊界的限制。

We’re on GPU, and we have linear interpolationand we can define our own uv’s thankyouverymuch.
So our pattern is not a regular pixel grid, buta nicely sorted set of explicit positions, each with its own implicit thresholdvalue.
This is an old screenshot from our patterngenerator, from years ago when we were setting it up. It’s a bit hard to see, but itis basically a disk packing with some configurable randomization, point count,boundary configurations etc.
It’s not a coincidence that everybody used abayer matrix when doing ordered dithering, it’s amathematically constructed matrix that has some nice properties, which we alsoapplied to our more freestyle version.
The thresholds themselves need to be EVENLYSPREAD between 0 and 1
the points are ordered to have MAXIMIZEDDISTANCE BTWEEN two consecutive threshold values.
By scaling the pattern so the 2D distance Wequals the footprint of the layer, we can apply the pattern directly in worldspace, with the resulting point-cloud having proper spacing as defined by itslayer settings.
在GPU上,我們有線性插值,我們可以定義自己的紫外線。因此,我們的模式不是常規的像素網格,而是一組經過良好排序的顯式位置,每個位置都有自己的隱式閾值。這是我們的模式生成器的一個舊截圖,是多年前我們設置它時的截圖。這有點難看,但它基本上是一個磁盤包裝,帶有一些可配置的隨機化、點計數、邊界配置等。在進行有序抖動時,每個人都使用了Bayer矩陣,這不是巧合,它是一個數學構造的矩陣,具有一些很好的特性,我們也將其應用于更自由的版本。閾值本身需要在0和1之間均勻分布。這些點被排序為在兩個連續閾值之間具有最大距離。通過縮放模式,使2D距離W等于該層的占用空間,我們可以將該模式直接應用到世界空間中,得到的點云具有其層設置所定義的適當間距。

Trees in a forest are a good example of a verylarge footprint, combined with full coverage density. This way, we have aneven, well defined minimum distance between trees, guarantees proper navigationfor the player, as well as the enemies.
But even with a proper bayer pattern, generatestill has the annoying side-effect of creating visual patterns when densitygets high.
You can see here how the trees are lining up inthe middle there.
It took quite long for someone to notice this,but once you see it you cannot un-see it, so we added a user defined noiseoffset. We had plans for multiple stencils and Wang tiling, but in the end itwasn’t reallyneeded.
森林中的樹木就是一個很好的例子,它們的足跡非常之大,而且覆蓋范圍非常之廣。通過這種方式,我們在樹與樹之間有一個均勻的、定義良好的最小距離,這保證了玩家和敵人都能正確導航。但是,即使使用適當的Bayer模式,generate仍然有一個惱人的副作用,那就是當密度變大時創建視覺模式。你可以看到樹是如何排列在中間的。有人花了很長時間才注意到這一點,但是一旦你看到它,你就不能取消它,所以我們添加了一個用戶定義的噪聲偏移量。我們原計劃是制作多個模板,但最終并不是真的需要。

This is an overview of four threadgroups of theGENERATE shader, that discretizes a density map across a area. Here we see thetarget area in white, and four tiled patterns across the area. Each computethreadgroup runs over a single pattern, where each compute thread evaluates onesample point. This maps very nicely into the threadgroup shader structure.
Let’s step through a single compute thread.
First, we have to make sure we EARLY OUT on allthe points that lie outside of the tile;
We read the density and to do our THRESHOLDTEST.
When we pass the threshold test we have ourposition in 2D, but no height to go with it. Therefore, we sample the properHEIGHTMAP to generate the full position.
Since we’re in the texture cache neighbourhood here,we might as well construct the HEIGHT NORMAL along with it.
The threads that pass the tests appended theiroriented point to buffer in GROUP LOCAL MEMORY.
Finally, we append the data onto the outputbuffer at the end to reduce atomic contention on the output buffer.
So now we have a buffer with an oriented pointcloud, but no full world data matrices yet. We also haven’t applied any per-objectlogic yet, such as random tilting, rotation, elevation etc.
這是生成著色器的四個線程組的概述,這些線程組在一個區域內離散化密度貼圖。在這里,我們看到目標區域是白色的,區域上有四個瓷磚圖案。每個計算線程組運行在一個模式上,其中每個計算線程計算一個采樣點。這可以很好地映射到線程組著色器結構中。讓我們單步執行一個計算線程。首先,我們必須確保早點發現瓷磚外的所有點;我們讀取密度并進行閾值測試。當我們通過門檻測試時,我們的位置是二維的,但沒有高度可以與之匹配。因此,我們對適當的高度圖進行采樣,以生成完整的位置。既然我們在紋理緩存的附近,我們也可以用它來構造正常的高度。通過測試的線程將其定向點附加到組本地內存中的緩沖區。最后,我們將數據附加到輸出緩沖區的末尾,以減少輸出緩沖區上的原子爭用。現在我們有了一個帶有定向點云的緩沖區,但是還沒有完整的數據矩陣。我們還沒有應用任何對象邏輯,如隨機傾斜、旋轉、仰角等。

Here again we see some in-game screens to showthe GENERATE discretization in game.
Here we have a layer that is covering areaswith particle effects. The placement system is instructed to simply fill thedesignated areas with full coverage. The result is a tightly squished hexagonalgrid.
This shows a more natural placement, a douglasfir is placed with within a forest area.
這里我們再次看到一些游戲中的屏幕來顯示生成的離散化。在這里我們有一個覆蓋有粒子效應區域的層。放置系統被指示簡單地用完全覆蓋填充指定區域。結果是形成了一個緊密擠壓的六邊形網格。這表明一個更自然的位置,道格拉斯冷杉是放置在一個森林地區。

Finally, the PLACEMENT shader applies all ofthe behavior parameters and generate world matrix and bounding box from thegenerated point cloud. For each input point, there is one output matrix.
So far, all operations have been deterministic,except for the output order of the GENERATE shader.
We need to pass the stencil point and tile IDalong with the position and normal, so each placement has a fully deterministicID.
[We have now completed our journey from adensity map graph to a buffer full of world matrices.]
最后,放置著色器應用所有行為參數,并從生成的點云生成世界矩陣和邊界框。對于每個輸入點,都有一個輸出矩陣。到目前為止,除了生成著色器的輸出順序之外,所有操作都是確定性的。我們需要傳遞模具點和圖塊ID以及位置和法線,因此每個位置都有一個完全確定的ID。[我們現在已經完成了從密度圖到充滿世界矩陣的緩沖區的旅程。]

This is the full overview of the the GPUcompute pipeline that is kicked of for a single layer of placement.
World data goes into the DENSITYMAP shader,which evaluates it into a 64x64 density texture. It is sampled by GENERATE intoa point cloud, expanded into world matrices by PLACEMENT and finally copied toCPU memory.
You can imagine how this all plays out acrossmultiple layers, and all these layers can be evaluated in parallel on GPUwithout much problems…oh wait
We haven’t solved collision. as it stands, you’ll just end up with lots of assets placed on top of each other sosome kind of collision avoidance has to be added.
Luckily, there are some interesting solutionsto this problem.
這是對GPU計算管道的完整概述,該管道是為單個放置層而啟動的。世界數據進入DensityMap著色器,該著色器將其評估為64x64密度紋理。它被采樣生成一個點云,通過放置擴展成世界矩陣,最后復制到CPU內存。你可以想象這一切是如何在多個層之間進行的,所有這些層都可以在GPU上并行地進行評估,沒有什么問題……哦,等等。我們還沒有解決碰撞問題。事實上,你最終會得到很多資產放在彼此之上,所以必須添加某種避免碰撞的方法。幸運的是,這個問題有一些有趣的解決方案。

The general solution for collision in thesecases is doing read-backs, this means that you would have to read back previousplacements, and either discard or re-iterate on collision.
This creates complex dependencies within yourGPU pipeline if you want to hold on to that local stability and deterministicbehavior. And GPU’s don’t really like those; no flushesplease.
However, when footprints between layers matchup, we can use a dithering technique called layered dithering, which isbasically free collision avoidance during discretization.
Readback was our backup path for colliding objectsacross different footprints. This lives somewhere in my saved changelists, itnever made it into the game proper. Instead we make extensive use of thelayered dithering technique to solve collision between placement layers withthe same footprint.
在這些情況下,沖突的一般解決方案是進行回讀,這意味著您必須回讀以前的位置,并在沖突時放棄或重新迭代。如果您希望保持本地穩定性和確定性行為,那么這將在您的GPU管道中創建復雜的依賴關系。GPU不太喜歡這些,請不要沖洗。然而,當層之間的足跡匹配時,我們可以使用一種稱為分層抖動的抖動技術,這基本上是在離散化過程中的自由碰撞避免。readback是我們的備份路徑,用于跨不同的封裝外形碰撞對象。這存在于我保存的變更列表中的某個地方,它從來沒有使它成為游戲的適當部分。相反,我們廣泛使用分層抖動技術來解決具有相同足跡的放置層之間的沖突。

Before we look into the details, lets changegears and focus on a one dimensional slice of the densitymap to make it easierto visualize.
So we grab a density map
Take a slice out of it
在我們研究細節之前,讓我們換個檔位,把注意力集中在密度圖的一個一維切片上,以便于可視化。所以我們拿一張密度圖,從里面切一片。

So in normal dithering, you have only onedensity map, with layered dithering, we’re dithering multiple layers of densitiesat once. Our starting point is still the same, a single density layer.
We then run our GENERATE shader, which samplesthe density on different points, with different thresholds. We can visualizethis as these little pins. So each pinpoint that lies below the density mapgenerates a placed object
Now what would happen if we would run anotherlayer directly afterwards, with the same footprint.
It would have an identical dithering pattern,and it would place directly on top of them.
The solution to this problem, is to simplylayer the densities together.
Now each pin-point can only lie in one range,removing any possibility of collision.
The density maps are now suddenly doublelayered (density volumes), having a minimum and maximum bound.
[each layer floats on top of the other layers]
The layers along a given sample point can nowbe seen as a propability distribution of multiple assets, where the thresholdof the sample point is the evenly distributed stochastic value that selectsone.
This whole thing also holds in 2D dithering.
所以在正常抖動中,只有一個密度圖,使用分層抖動,我們會同時抖動多個密度層。我們的出發點還是一樣的,一個密度層。然后運行GENERATE著色器,它在不同的點上以不同的閾值采樣密度。我們可以把它想象成這些小別針。因此位于密度圖下方的每個點都會生成一個放置的對象,現在,如果我們在后面直接運行另一個具有相同足跡的層,會發生什么。它將有一個相同的抖動模式,并將直接放在上面。解決這個問題的辦法,就是把密度簡單地疊加在一起。現在每個針點只能在一個范圍內,消除了任何碰撞的可能性。密度圖現在突然變成了雙層(密度體積),有一個最小和最大的界限。[每個層浮在其他層的頂部]。沿著一個給定采樣點的層現在可以看作是多個資產的一個可比性分布,其中采樣點的閾值是選擇一個均勻分布的隨機值。這整件事也適用于二維抖動。

So we solved collision, and we still end uphaving dependencies, but the dependencies only relate to the DENSITYMAP phase,and with some refactoring, you can still evaluate all layers independently onGPU using atomics, saving costly GPU flushes.
So here you can see that we run multipledensitymap shaders before we hit GENERATE.
This is actually the most common case inproduction ecotopes. We often have more than 20 layers with the same footprintthat stacked on top of each other like this and we are almost always interestedin placing only a very specific subset of layers.
Meaning that we run DENSITYMAP on layers thatwe don’t want toplace, but we need their DENSTIYMAP to reach higher up in the stack.
So our pipelines run N density maps for eachlayer that actually need to be placed. We want this number N to be as low aspossible,so we use all kind of heuristics to order the layers in such a waythat the most commonly placed layers are at the bottom of these stacks.
所以我們解決了沖突,我們仍然有依賴關系,但依賴關系只與密集映射階段有關,通過一些重構,你仍然可以獨立地評估GPU上的所有層使用原子,節省昂貴的GPU刷新。在這里,你可以看到我們在點擊Generate之前運行了多個DensityMap著色器。這實際上是生產生態環境中最常見的情況。我們通常有20多個具有相同足跡的層,像這樣彼此疊加在一起,我們幾乎總是對只放置一個非常特定的層子集感興趣。這意味著我們在不想放置的層上運行密度圖,但我們需要它們的密度圖在堆棧中更高。所以我們的管道為每一層運行N個密度圖,實際上需要放置。我們希望這個數字N盡可能的低,所以我們使用各種啟發式方法來對層進行排序,使最常見的層位于這些堆棧的底部。

As a final step, we look at our GPU scheduling.If we would only place one layer per frame, it would extremely slow, so inorder to schedule more work, we instantiate our entire pipeline multiple times.Note that we can not schedule dependent layers across different pipelines. Sowe mostly parrelize spatialy in this step; each pipeline picks an area topopulate.
In our first prototype, pipelines would emitits shaders one at a time, but again this means that each shader uses theoutput data of the shader before it, which is not ideal because they can’t overlap on GPU.
最后一步,看一下我們的GPU調度。如果我們每幀只放置一個層,那么速度會非常慢,因此為了安排更多的工作,我們將對整個管道進行多次實例化。請注意,我們不能跨不同的管道調度依賴層。因此,在這一步中,我們主要對空間進行Parrelieze;每個管道都選擇一個區域進行填充。在我們的第一個原型中,管道將一次發射一個著色器,但這再次意味著每個著色器使用其之前的著色器輸出數據,這并不理想,因為它們不能在GPU上重疊。

So this is our final gpu load layout.
We first run DENSITYMAP across all pipelinesindependently
We keep doing this until we hit a layer thatneeds to be placed
Then we run the GENERATE shader, and a specialALLOCATION shader to dynamically allocate memory in the copy buffer
Then PLACEMENT converts the oriented points tothe copy buffer
The entire thing can be repeated until all workis done for all pipelines, but we shipped with a maximum of 4 emits to reducememory load and prevent GPU spikes.
Finally the copy buffer copies all data to CPUin one go. This saves us hundreds microseconds of syncing and copying overhead.
所以這是我們最后的GPU負載布局。我們首先在所有管道上獨立運行密度圖。我們一直這樣做直到我們碰到一個需要放置的層,然后我們運行generate shader和一個特殊的分配shader來動態地分配復制緩沖區中的內存。然后placement將定向點轉換為復制緩沖區。整個過程可以重復,直到所有管道的所有工作都完成為止,但是為了減少內存負載和防止GPU峰值,我們提供了最多4個發射器。最后,復制緩沖區將所有數據一次性復制到CPU。這為我們節省了數百微秒的同步和復制開銷。







評分

參與人數 4元素幣 +71 活躍度 +46 貢獻值 +1 收起 理由
玨銘 + 21 + 12 光看圖片就已經驚艷到我了
元素界王 + 50 + 20 + 1 【點贊】這很有大網氣質!
浮生如夢 + 8 感謝分享!!!
諾一 + 6 很喜歡樓主的帖子呢!

查看全部評分

本帖被以下畫板推薦:

還沒有設置簽名!您可以在此展示你的鏈接,或者個人主頁!

使用道具 舉報

回復 論壇版權

盤 TA

謝謝分享

使用道具 舉報

回復

盤 TA

使用道具 舉報

回復

盤 TA

素沒有出現過以下哪個培訓機構

使用道具 舉報

回復

盤 TA

謝謝分享

使用道具 舉報

回復

盤 TA

感謝樓主分享!

使用道具 舉報

回復

盤 TA

這很贊

使用道具 舉報

回復

盤 TA

這很贊

使用道具 舉報

回復

盤 TA

不錯,多謝分享

使用道具 舉報

回復

盤 TA

66666666666

使用道具 舉報

回復

盤 TA

這個帖子不錯,大家快來頂起來!

使用道具 舉報

回復

盤 TA

使用道具 舉報

回復

盤 TA

謝謝分享

使用道具 舉報

回復

盤 TA

謝謝分享

使用道具 舉報

回復

盤 TA

使用道具 舉報

回復

盤 TA

謝謝分享

使用道具 舉報

回復

盤 TA

謝謝分享

使用道具 舉報

回復

盤 TA

謝謝分享

使用道具 舉報

回復

盤 TA

很好的資源,感謝分享

使用道具 舉報

回復

盤 TA

666

使用道具 舉報

回復

盤 TA

謝謝分享

使用道具 舉報

回復

盤 TA

謝謝分享

使用道具 舉報

回復

盤 TA

謝謝分享

使用道具 舉報

回復

盤 TA

很好,很強大

使用道具 舉報

回復

盤 TA

哈友情價10個幣

使用道具 舉報

回復

盤 TA

路過看看 感謝分享

使用道具 舉報

回復

盤 TA

路過看看 感謝分享

使用道具 舉報

回復

盤 TA

路過看看 感謝分享

使用道具 舉報

回復

盤 TA

感謝分享

使用道具 舉報

回復

盤 TA

niubi

使用道具 舉報

回復

盤 TA

阿羅伊!

使用道具 舉報

回復

盤 TA

很好的資源,感謝分享

使用道具 舉報

回復

盤 TA

使用道具 舉報

回復

盤 TA


從業不識微元素,做遍項目也枉然

使用道具 舉報

回復

盤 TA

使用道具 舉報

回復

盤 TA

使用道具 舉報

回復

盤 TA

從業不識微元素,做遍項目也枉然

使用道具 舉報

回復

盤 TA

NB,   從此我要踏上屌絲之路

使用道具 舉報

回復

盤 TA

樓主我愛你

使用道具 舉報

回復

盤 TA

每天早晨第一句,賺他一億元素幣!

使用道具 舉報

回復
12下一頁
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規則

關閉

元素推薦-友情提示上一條 /1 下一條

快速回復 返回頂部 返回列表
王者荣耀孙尚香被ⅹ漫画