《塞爾達傳說 曠野之息》中的草是如何渲染的?

時間 2021-05-05 22:12:46

1樓:凱丁

主要的思路: LOD,Instancing,拉長的Quad

藍色(包括藍綠色)部分是隨風動的草,紅色是不動的草體貼片,藍綠色更接近相機

頂檢視草體mesh會根據多張TerrianInfo相關texture來生成,所以需要VTF支援,比如互動用了一張固定頻率更新的NormalMap,高度用HeightMap

由於所有草體顏色和Terrain顏色很接近,所以紅色草和藍色草之間的切換(也就是LOD切換)相當自然

根本不需要Geomerty Shader,根本沒用細分

沒有太多神奇的技術,但是有很多神奇的經驗!

其他細節就不說了,看彙編太累

但看完就覺得很多細節上就能體現:老任做遊戲,真的是完全是從使用者角度和遊戲性出發!

很多人問是用什麼工具分析的,這邊大概說一下,以後得空了在慢慢補全:

WiiU模擬器Cemu已經很完善了,有興趣可以自己截一幀看,不過Cemu渲染底層採用的是OpenGL,所以GPA是看不了的,可以用Nsight來看;不過由於是模擬器,Shader、Mesh以及Uniform Variable 都是按int儲存讀取,需要一些技巧和耐心,尤其是Shader,擷取一段各位看看

void main()

{ivec4 R0i = ivec4(0);

ivec4 R1i = ivec4(0);

ivec4 R2i = ivec4(0);

ivec4 R3i = ivec4(0);

ivec4 R4i = ivec4(0);

ivec4 R5i = ivec4(0);

ivec4 R6i = ivec4(0);

ivec4 R7i = ivec4(0);

ivec4 R8i = ivec4(0);

ivec4 R9i = ivec4(0);

ivec4 R10i = ivec4(0);

ivec4 R122i = ivec4(0);

ivec4 R123i = ivec4(0);

ivec4 R124i = ivec4(0);

ivec4 R125i = ivec4(0);

ivec4 R126i = ivec4(0);

ivec4 R127i = ivec4(0);

uvec4 attrDecoder;

int backupReg0i, backupReg1i, backupReg2i, backupReg3i, backupReg4i;

ivec4 PV0i = ivec4(0), PV1i = ivec4(0);

int PS0i = 0, PS1i = 0;

ivec4 tempi = ivec4(0);

float tempResultf;

int tempResulti;

ivec4 ARi = ivec4(0);

bool predResult = true;

vec3 cubeMapSTM;

int cubeMapFaceId;

R0i = ivec4(gl_VertexID, 0, 0, gl_InstanceID);

attrDecoder.xy = floatBitsToUint(vec2(attrDataSem0.xy)/255.0);

attrDecoder.zw = uvec2(0);

R4i = ivec4(int(attrDecoder.x), int(attrDecoder.y), floatBitsToInt(0.

0), floatBitsToInt(1.0));

attrDecoder.xy = attrDataSem1.zw;

if( (attrDecoder.x&0x80) != 0 ) attrDecoder.x |= 0xFFFFFF00;

if( (attrDecoder.y&0x80) != 0 ) attrDecoder.y |= 0xFFFFFF00;

attrDecoder.x = floatBitsToUint(max(float(int(attrDecoder.x))/127.0,-1.0));

attrDecoder.y = floatBitsToUint(max(float(int(attrDecoder.y))/127.0,-1.0));

attrDecoder.zw = uvec2(0);

R3i = ivec4(int(attrDecoder.x), int(attrDecoder.y), floatBitsToInt(0.

0), floatBitsToInt(1.0));

attrDecoder.xy = floatBitsToUint(vec2(attrDataSem2.xy));

attrDecoder.zw = uvec2(0);

R1i = ivec4(int(attrDecoder.x), int(attrDecoder.y), floatBitsToInt(0.

0), floatBitsToInt(1.0));

attrDecoder.xy = floatBitsToUint(vec2(attrDataSem8.zw)/255.0);

attrDecoder.zw = uvec2(0);

R2i = ivec4(int(attrDecoder.x), int(attrDecoder.y), floatBitsToInt(0.

0), floatBitsToInt(1.0));

// 0

R127i.x = floatBitsToInt(intBitsToFloat(R2i.x) * intBitsToFloat(0x3e65a5dd));

PS0i = R127i.x;

// 1

PV1i.z = R3i.z;

PV1i.w = R5i.w;

R1i.w = 0x3f800000;

PS1i = R1i.w;

// 2

PS0i = R125i.z;

// 3

backupReg0i = R127i.x;

R126i.z = floatBitsToInt(intBitsToFloat(backupReg0i) + intBitsToFloat(PV0i.w));

PV1i.z = R126i.z;

PS1i = R5i.y;

// 4

PS0i = floatBitsToInt(-(intBitsToFloat(PV1i.y)) + intBitsToFloat(PV1i.z));

// 5

PV1i.x = floatBitsToInt(intBitsToFloat(R126i.z) + -(intBitsToFloat(R127i.x)));

PV1i.y = floatBitsToInt(-(intBitsToFloat(R127i.y)) + intBitsToFloat(PS0i));

PS1i = R0i.y;

// 6

R8i.y = floatBitsToInt(intBitsToFloat(R125i.z) * intBitsToFloat(0x439d1463));

PV0i.z = floatBitsToInt(-(intBitsToFloat(PV1i.w)) + intBitsToFloat(PV1i.x));

R0i.x = floatBitsToInt(intBitsToFloat(PV1i.y) * intBitsToFloat(0x3cb6a401));

PS0i = R0i.x;

// 7

R5i.z = floatBitsToInt(intBitsToFloat(PV0i.z) * intBitsToFloat(0x3cb6a401));

R2i.w = R3i.z;

R1i.z = R5i.w;

PS1i = R1i.z;

R9i.xyzw = floatBitsToInt(texture(textureUnitVS3, intBitsToFloat(R7i.xy)).xyzw);

R4i.xy = floatBitsToInt(texture(textureUnitVS0, intBitsToFloat(R4i.xy)).xy);

R10i.xy = floatBitsToInt(texture(textureUnitVS2, intBitsToFloat(R0i.zy)).zw);

R0i.x = floatBitsToInt(texture(textureUnitVS5, intBitsToFloat(R0i.xw)).x);

R5i.x = floatBitsToInt(texture(textureUnitVS5, intBitsToFloat(R5i.zy)).x);

R6i.xy = floatBitsToInt(texture(textureUnitVS1, intBitsToFloat(R6i.xy)).xy);

R7i.yzw = floatBitsToInt(texture(textureUnitVS4, intBitsToFloat(R7i.xy)).xyz

以上只是整個VertexShader量的1/5左右

基本上是逐條從彙編直譯成GLSL,資料都是Int<->Float互轉,有耐心和好學的同學可以一看

2樓:

首先,ns機能一點不差,基本上835gpu等效效能的硬體,還有主動散熱。最近的吃雞手遊中草的數量也證實其實並沒有那麼費,再加上instancing和lod的幫助,可能並沒有想象的那麼麻煩。另外,塞爾達的草幾乎純色,還免去了讀diffuse的頻寬。

3樓:9級鐵甲蛹

就我知道的用geometry shader能弄這個效果。建議看看這個https://

zhuanlan /p/29632347

switch上有啥優化不了解,等大佬來答

如何評價《塞爾達傳說 曠野之息》?

迍迍TAT 我只想說是神作了吧!如果你入了switch卻沒有玩過塞爾達,那一定是一生的遺憾。這麼說吧,玩的過程中,你甚至會覺得買switch和卡帶的錢都是值得的,他配! Soul 俗套的主題,配上最短的主線,寫出了最打動人心的故事。艱苦卓絕的戰鬥,潛移默化的成長,一次次意外或是驚喜,最終留下的是一場...

《塞爾達傳說 曠野之息》中塞爾達公主的角色塑造算不算失敗?

Risland 乙個角色是否塑造的成功壓根兒就不在於他是不是被喜歡,而是在於他她最後呈現出來的效果是否符合設計者的預期和他她對整個故事的情節和主題所起到的幫助和昇華。假如乙個角色很被喜歡就是好角色,那乾脆以後塑造角色就往死裡堆優點就行了 漂亮,善良,聰明 而且還一定要特別體貼,對男主角百依百順 事實...

《塞爾達傳說 曠野之息》中,玩家遊玩的動機是救公主還是探索海拉魯,兩個動機間是否存在一定的矛盾

TonyLiu 並不矛盾 在我看來,荒野之息在遊戲很早起就交代完了遊戲目標 拯救塞爾達公主,然後就立即把控制權交給玩家,讓玩家自己決定,怎麼去解救公主。在這個過程中,玩家必定需要去探索海拉魯,必定需要通過探索,來讓自己變強,強到可以挑戰boss 這兩個動力是相輔相成的 而在玩法上,荒野之息是開放世界...