Steel monkeys: Unity3D глазами программиста графики

34

description

Роман расскажет о разных тонкостях работы с трехмерной графикой в Unity, о работе графического конвеера, о реализации отложенного освещения в Unity3D, его преимуществах и недостатках. А также разберет все возможности работы с шейдерами и пост-эффектами в Unity.

Transcript of Steel monkeys: Unity3D глазами программиста графики

Page 1: Steel monkeys: Unity3D глазами программиста графики
Page 2: Steel monkeys: Unity3D глазами программиста графики

• Рассмотрим graphics pipeline в Unity3D .• Коснемся работы с шейдерами в Unity3D .• Поговорим об оптимизации графики.• Поговорим о image post processing.

Words to say

Page 3: Steel monkeys: Unity3D глазами программиста графики

WhoAmI()

• Программист графики.•В разное время работал с Adobe flash -> DirectX -> OpenGL -> Unity.• Работал с open-source движками: Ogre3D, Irrlicht3D, Horde3D, HGE. Контрибьютил в Irrlicht3D, Horde3D.• На данный момент работаю на мобильной разработке в Steel Monkeys (Unity 3D).

Page 4: Steel monkeys: Unity3D глазами программиста графики

• Vertex lit (hardware transform & lighting)• Forward (multi-pass forward rendering)• Deferred (light footprint deferred shading)

Graphics pipelines

Page 5: Steel monkeys: Unity3D глазами программиста графики

• Аппаратная трансформация, отсечение и освещение.

• Texture blending тоже аппаратный.

• Очень быстрый расчет освещения, буквально несколько тактов GPU.

• Реализуется через программный API.

• В Unity реализована в виде fixed-function шейдеров.

Hardware Transform & Lighting

Page 6: Steel monkeys: Unity3D глазами программиста графики

// DirectX9 codeD3DLIGHT9 light;D3DMATERIAL9 material;

ZeroMemory(&light, sizeof(light));light.Type = D3DLIGHT_POINT;light.Diffuse = D3DXCOLOR(0.5, 0.5, 0.5,

0.5);light.Position = D3DXVECTOR3(0.0f, 5.0f, 0.0

f);light.Range = 100.0f;light.Attenuation0 = 0.0f;light.Attenuation1 = 0.125f;light.Attenuation2 = 0.0f;

d3ddev->SetLight(0, &light);d3ddev->LightEnable(0, TRUE);

ZeroMemory(&material, sizeof(D3DMATERIAL9));material.Diffuse = D3DXCOLOR(1, 1, 1, 1);material.Ambient = D3DXCOLOR(1, 1, 1, 1);

d3ddev->SetMaterial(&material);

Fixed function shader

Page 7: Steel monkeys: Unity3D глазами программиста графики

Да, если Нет, если• Не требуется

попиксельного освещения.

• Вообще не требуется динамического освещения, и/или взаимодействия с лайтмапами.

• Вы работаете с очень старым железом (iphone 4, ipad 1).

• Требуется попиксельное освещение, лайтмапы, realtime-тени, любые шейдерные эффекты.

• Ваша платформа позволяет использовать что угодно другое.

Conclusion: Fixed function rendering

Page 8: Steel monkeys: Unity3D глазами программиста графики

• Per-pixel освещение накладывается во фрагментном шейдере.

• Один Forward Base проход для самого яркого Directional источника на сцене.

• N дополнительных Forward Add проходов в аддитивном блендинге для N избранных источников света.

• До четырех per-vertex источников света в вершинном шейдере.

• Легко взаимодействовать с помощью surface-шейдеров.

Per-pixel forward rendering oveview

Page 9: Steel monkeys: Unity3D глазами программиста графики

• SubShader:• Forward base

• OpenGL• Base

• KEYWORD_A• KEYWORD_B

• Vertex program• Fragment program

• Shadow caster• Shadow collector

• DX9• WP8

…• Forward add• Prepass base• Prepass final

e.g. over 100 vertex/fragment programs

Surface shader

Page 10: Steel monkeys: Unity3D глазами программиста графики

Forward Base (brightest directional light)

Stats:• 2K triangles• 4K vertices

Page 11: Steel monkeys: Unity3D глазами программиста графики

Forward Add (x1)

Stats:• 4K triangles• 8K vertices• 1X Blend “One One”

Page 12: Steel monkeys: Unity3D глазами программиста графики

Forward Add (x2)

Stats:• 6K triangles• 12K vertices• 2X Blend “One One”

Page 13: Steel monkeys: Unity3D глазами программиста графики

Forward Add (x3)

Stats:• 8K triangles• 16K vertices• 3X Blend “One One”

Page 14: Steel monkeys: Unity3D глазами программиста графики

Forward Add (x4)

Stats:• 10K triangles• 20K vertices• 4X Blend “One One”

Page 15: Steel monkeys: Unity3D глазами программиста графики

Forward Add (x5)

Stats:• 12K triangles• 24K vertices• 5X Blend “One One”

Page 16: Steel monkeys: Unity3D глазами программиста графики

Итого имеем:• 5X дополнительных циклов вершинной

трансформации, • 5X операций аддитивного блендинга.• 5X дополнительных текстурных операций.• 5X дополнительных итераций всего шейдерного

кода.• 5X overdraw по tris’ам.

Forward rendering overhead

Какой бы то ни было оптимизации в Light-manager’e Unity не предусмотрено.

Давайте ему поможем!

Page 17: Steel monkeys: Unity3D глазами программиста графики

1. _WorldSpaceLightPos0 – позиция первогонаправленного источника.

2. _LightColor0 – цвет этого источника

3. unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0 – позиции четырехисточников света, которые считались бы per-vertex.

4. unity_4LightAtten0 – аттенюация этих источников света

5. unity_LightColor – цвет этих источников

Accessing built-in shader constants

Page 18: Steel monkeys: Unity3D глазами программиста графики

Implementing an algorithm

Get on github: https://github.com/RChehowski/devgamm_expo

int index = 0;while (index < 4){ float4 lightPosition = float4( unity_4LightPosX0[index], unity_4LightPosY0[index], unity_4LightPosZ0[index], 1.0); // calculate direction float3 vertexToLightSource = lightPosition.xyz - input.posWorld.xyz; float3 lightDirection = normalize(vertexToLightSource); // find distance and calculate attenuation float squaredDistance = dot(vertexToLightSource, vertexToLightSource); float attenuation = 1.0 / (1.0 + unity_4LightAtten0[index] * squaredDistance); // calculate diffuse intensity float3 diffuseReflection = attenuation * unity_LightColor[index].rgb * _Color.rgb * max(0.0, dot(input.normalDir, lightDirection)); output += diffuseReflection; index++;}

Page 19: Steel monkeys: Unity3D глазами программиста графики

• 1X per-pixel directional light.

• 4X per-pixel point light.• All in one pass!

Result

Page 20: Steel monkeys: Unity3D глазами программиста графики

Да, если Нет, если• Количество

динамических источников света и освещенных объектов мало.

• Требуется поддержка динамических теней от directional лайтов.

• Требуется поддержка лайтмапов из коробки.

• Количество динамических источников велико.

• Есть возможность обойтись Hardware Transform & Lighting.

• Требуется доступ к буферу глубины или view-нормалей.

Conclusion: Forward rendering

Page 21: Steel monkeys: Unity3D глазами программиста графики

Deferred rendering overview

• Освещение рассчитывается как пост-процессинг, только для видимых фрагментов.

• Все освещение на сцене рендерится попиксельно.

• Легко получить depth и view normals для собственных манипуляций при пост-процессинге.

• Производительность сильно зависит от пропускной способности памяти видеокарты и способа реализации.

Page 22: Steel monkeys: Unity3D глазами программиста графики

Forward approach

Page 23: Steel monkeys: Unity3D глазами программиста графики

Deferred approach

Page 24: Steel monkeys: Unity3D глазами программиста графики

Thousands of dynamic per-pixel lights

FORWARD• 20 objects * 50

lights = 1000 DIP

Deferred• 20 objects + 50

lights + 3 post pass = 73 DIP

Feel the difference!

Page 25: Steel monkeys: Unity3D глазами программиста графики

Prepass: View normals & depth

Renders the scene into the RenderTexture

Page 26: Steel monkeys: Unity3D глазами программиста графики

Lighting calculation: Rendering light footprints

Uses the RT from the previous pass

Page 27: Steel monkeys: Unity3D глазами программиста графики

Final pass

Unfortunately, renders the scene one more time :(

Page 28: Steel monkeys: Unity3D глазами программиста графики

Да, если Нет, если• Количество

динамических источников очень велико.

• Используется хотя бы один пост-эффект, работающих с глубиной сцены (SSAO, DOF, soft particles, point light shafts)

• Количество динамических источников невелико.

• Слабое железо или железо без поддержки рендеринга в текстуру.

• Много transparent объектов (alpha-test не считается).

Conclusion: Deferred rendering

Page 29: Steel monkeys: Unity3D глазами программиста графики

Post processing

Попиксельная обработка отрендеренного изображения для получения необходимого эффекта:

• SSAO• Bloom• FXAA• Gamma correction• DOF• Outlines• … and many, many more!

Page 30: Steel monkeys: Unity3D глазами программиста графики

Post processingСообщения:

• OnRenderImage() – вызывается после того, как все объекты на сцене были отрисованы в рендертекстуру.

• OnPreRender() – вызывается перед тем, как начнется рендеринг.

• OnPostRender() – вызывается после того как отрендерятся все объекты в текущем кадре.

• OnWillRenderObject() – вызывается перед рендерингом каждого видимого объекта.

Методы:• Graphics.DrawMesh() – сабмитит mesh на отрисовку.• Graphics.DrawMeshNow() – рисует mesh в текущем кадре.• Graphics.Blit() – копирует данные из рендертекстуры в

рендертекстуру

Page 31: Steel monkeys: Unity3D глазами программиста графики

Post process example

Page 32: Steel monkeys: Unity3D глазами программиста графики

High price of the Depth

• Camera.depthTextureMode = DepthTextureMode.Depth;

• UNITY_TRANSFER_DEPTH(), • UNITY_OUTPUT_DEPTH()

• В forward-пайплайне стоит одного дополнительного прохода рендера

• В deferred-пайплайне просто берется из G-буфера.

Page 33: Steel monkeys: Unity3D глазами программиста графики

• К сожалению, формат данной презентации не позволяет уделить каждой реализации конвейера достаточного количество внимания.

• В погоне за универсальностью, рендер Unity нередко жертвует производительностью.

• Использование каждого из пайплайнов создает свои проблемы, но их можно устранить в рамках каждой конкретной задачи.

Conclusion

Page 34: Steel monkeys: Unity3D глазами программиста графики

Спасибо за внимание!

[email protected]

inangwish

Special thanks to: <Dmitry Minsky> http://halfbus.co/