24
SYSTÈME D’INSTANCING

[Paris Unity3D meetup] - Système d’instancing dans endless legend reskin

  • Upload
    bemyapp

  • View
    202

  • Download
    0

Embed Size (px)

Citation preview

Page 1: [Paris Unity3D meetup] - Système d’instancing dans endless legend reskin

SYSTÈME D’INSTANCING

Page 2: [Paris Unity3D meetup] - Système d’instancing dans endless legend reskin

TIMOTHÉE RAULIN

Page 3: [Paris Unity3D meetup] - Système d’instancing dans endless legend reskin

PLAN

PROBLÈME SOLUTION RÉSULTATS PLUS LOIN

Page 4: [Paris Unity3D meetup] - Système d’instancing dans endless legend reskin

PROBLÈME

Page 5: [Paris Unity3D meetup] - Système d’instancing dans endless legend reskin

Situation Nombre d’objets à l’écran

Nombre d’objets dans le monde

Temps de « fabrication » du contenu d’une zone

Mémoire nécessaire pour stocker le contenu d’une zone

Objectifs Performance CPU/GPU

Mémoire CPU/GPU

Temps réel

PROBLÈME

Page 6: [Paris Unity3D meetup] - Système d’instancing dans endless legend reskin

En moyenne 10 000 draw call dès qu’on dezoom

Batching dynamique …

Mauvais frame rate (CPU bound) mais régulier

Éditeur friendly

UNITY. DE BASE

Page 7: [Paris Unity3D meetup] - Système d’instancing dans endless legend reskin

Lent

Mémoire gigantesque

Très lent en fait!

Bon frame rate mais grosse saccade + out of memory

Pas éditeur friendly

UNITY.COMBINEMESH

Page 8: [Paris Unity3D meetup] - Système d’instancing dans endless legend reskin

PLAN

PROBLÈME SOLUTION RÉSULTATS PLUS LOIN

Page 9: [Paris Unity3D meetup] - Système d’instancing dans endless legend reskin

Encodage dans une texture

Décodage au vertex-shader

Implémentation

Performance

Mémoire

SOLUTION UTILISÉE

Page 10: [Paris Unity3D meetup] - Système d’instancing dans endless legend reskin

1 pixel = 4 * 8 bits ou 2 * 16 bits

2 * 8 bits = 16 bits => 65536 • 1 => 255 (8 bits) ou 65535 (16 bits)

Encodage d’un objet avec 3 pixels: • 3 * 16 bits => x, y, z ( 1 + ½ pixels) • 2 * 16 bits => Orientation + scale 2d (xz ) (1 pixel) • 1 * 16 bits => scale Y (½ pixel )

D’autres encodages possibles (plus de pixels & bits)

ENCODAGE | DÉCODAGE

Page 11: [Paris Unity3D meetup] - Système d’instancing dans endless legend reskin

int valueIn0_1_8bit = System.Math.Max(0, System.Math.Min(255, (int)(valueIn01 * 255.0f)));

UnityEngine.Color32 color = new UnityEngine.Color32((byte)valueIn0_1_8bit, …, … ,… );

int valueIn0_1_16bit = (int)System.Math.Max(0, System.Math.Min(65535, (int)(valueIn01 * 65535.0f)));

int lowBits = 255;

int highBits = 255 << 8;

UnityEngine.Color32 color = new UnityEngine.Color32((byte)(valueIn0_1_16bit & lowBits), ((byte)((valueIn0_1_16bit & highBits) >> 8), …, …)

float4 texContent = tex2Dlod(_EncodedContentTexture, texCoord);

float valueIn0_1 = texContent.x;

float valueIn0_255 = 255 * texContent.x; //on récupère exactement la valeur valueIn0_1_8bit

float4 texContent = tex2Dlod(_EncodedContentTexture, texCoord);

float valueIn0_65535 = texContent.x * 255 + texContent.y * 255 * 256; //on récupère exactement la valeur valueIn0_1_16bit

float valueIn0_1 = valueIn0_65535 / 65535;

FORMULES Encoder en 8 bits - un float entre 0 et 1

Encoder en 16 bits

Décoder en 8 bits

Décoder en 16 bits

Page 12: [Paris Unity3D meetup] - Système d’instancing dans endless legend reskin

Strip de mesh : Pour chaque mesh de chaque type de décors, on prépare un mesh qui est une répétition de copie de ce mesh. Dans le strip de mesh, on ajoute la composante couleur où l’on encode l’index de la copie dans la série

On encode l’affichage d’un groupe d’objet de même type en une bande de pixel

On transmet au vertex-shader l’endroit où il faut commencer à lire et le nombre d’objet qu’il faut décoder

tree tree4 tree0 tree1 tree2 tree3 tree4 tree5 tree6

DÉCODAGE AU VERTEX-SHADER

Page 13: [Paris Unity3D meetup] - Système d’instancing dans endless legend reskin

On utilise la version de UnityEngine.Graphics.DrawMesh avec 9 paramètres dont un MaterialPropertyBlock

MaterialPropertyBlock : contiendra ce qui change par DrawMesh : le _StartUV, le MeshCount, la bounding box, etc…

UnityEngine.Shader.SetGlobalXXX : pour ce qui ne change pas par draw, en particulier la texture de contrôle

IMPLÉMENTATION 1/2

Page 14: [Paris Unity3D meetup] - Système d’instancing dans endless legend reskin

X lo X hi Y lo Y hi Z lo Z hi Fx lo Fx hi Fz lo Fz hi Up lo Up hi X lo X hi Up lo Up hi

Instance 0 Instance 1 Instance 2 Instance 3 Instance 4

Shader parameters

_ControlTex _StartUV _ObjectCount

float instanceIndex = 255 * vertex.color.x;

int pixelCountPerInstance = 3;

float2 baseTexCoord = _StartUV.xy + float2(_ControlTex_TexelSize.x * (pixelCountPerInstance * instanceIndex), 0) + _ControlTex_TexelSize.xy * 0.5f;

float4 controlValue0 = tex2Dlod (_ControlTex, float4(baseTexCoord, 0, 0));

float4 controlValue1 = tex2Dlod (_ControlTex, float4(baseTexCoord + float2(_ControlTex_TexelSize.x, 0), 0, 0));

float4 controlValue2 = tex2Dlod (_ControlTex, float4(baseTexCoord + float2(2 * _ControlTex_TexelSize.x, 0), 0, 0));

float valueX01 = (controlValue0.x * 255 + controlValue0.y * 255 * 256) / 65535;

(…)

float3 pos = lerp(_MinBBox.xyz, _MaxBBox.xyz, float3(valueX01, valueY01, valueZ01));

(…)

float visible = step(colorIndex, _ObjectCount – 0.5);

controlValue0 controlValue1 controlValue2

_ControlTex

Zoom +

Page 15: [Paris Unity3D meetup] - Système d’instancing dans endless legend reskin

A partir d’un ensemble de groupe d’objets disparates, on fabrique un ensemble de groupe d’objets de même type

On les encode dans la texture de contrôle

On envoie les commandes de rendu avec DrawMesh

IMPLÉMENTATION 2/2

Page 16: [Paris Unity3D meetup] - Système d’instancing dans endless legend reskin

La consultation de la texture au vertex-shader est gratuite!

• Il faut être GPU bound pour le voir

• Il faut vraiment beaucoup de vertex alors que généralement le coût principal vient des pixels

• Même dans ce cas là, on a seulement quelques % de différence

Remplir une texture sans mip-map à partir d’un tableau de color32, n’est pas très cher

PERFORMANCES

Page 17: [Paris Unity3D meetup] - Système d’instancing dans endless legend reskin

Ca pique!! Chaque type d’objet est répliqué, parfois plusieurs centaines de fois

En cause certaines limitations de Unity

Ajuster la taille des strips de mesh

Optimiser le layout mémoire

• Encoder la normale dans la couleur

• Encoder la tangeante dans la normale

MÉMOIRE

Page 18: [Paris Unity3D meetup] - Système d’instancing dans endless legend reskin

Pour le debug et la mise au point, pouvoir switcher entre « Unity pur » et « instancing », le premier définissant la référence

Nécessite une autre manière de regrouper les meshs pour certains éléments

Animation : manipuler quelques pixels pour bouger un objet

DIVERS

Page 19: [Paris Unity3D meetup] - Système d’instancing dans endless legend reskin

TA TA TATATA * *AIR CONNU

Page 20: [Paris Unity3D meetup] - Système d’instancing dans endless legend reskin

PLAN

PROBLÈME SOLUTION RÉSULTATS PLUS LOIN

Page 21: [Paris Unity3D meetup] - Système d’instancing dans endless legend reskin

Nombre de draw call réduit

Temps de régénération et coût de stockage d’une zone réduit

Zéro alloc ou presque en réutilisant les buffers de stockage

Empreinte mémoire importante à t=0 mais quasi constante par la suite

Animation de certains éléments facilitée

Nécessite une certaine infrastructure et un certain investissement pour la mise au point

RÉSULTATS

Page 22: [Paris Unity3D meetup] - Système d’instancing dans endless legend reskin

PLAN

PROBLÈME SOLUTION RÉSULTATS PLUS LOIN

Page 23: [Paris Unity3D meetup] - Système d’instancing dans endless legend reskin

Travailler avec des valeurs entières permet d’avoir des indices et donc des tableaux d’objets consultables

Il n’est pas prohibitif de faire au pixel shader ce genre d’opération

On peut produire le contenu de texture d’encodage à partir d’un rendu et donc animer au GPU

PLUS LOIN

Page 24: [Paris Unity3D meetup] - Système d’instancing dans endless legend reskin

[email protected]

MERCI