rendering aaa-quality characters of project a1

94
Rendering AAA - Quality Characters of Project ‘ A1 Hyunwoo Ki Lead Graphics Programmer A1 / NEXON * Translated material in English.

Upload: ki-hyunwoo

Post on 21-Apr-2017

7.216 views

Category:

Engineering


5 download

TRANSCRIPT

Rendering AAA-Quality

Characters of Project ‘A1’

Hyunwoo KiLead Graphics Programmer

A1 / NEXON

* Translated material in English.

• Unannounced project of Nexon / New IP

In Development

By game development experts

Target Platform: High-end PC

- 60 FPS at Ultra Quality / Low-spec PCs will be okay at Medium Quality

• We first announce our project at this conference

A1

• Programming Session: Character Rendering

Including resources and implementation in development

World shown in this talk is a temporary

All content can be changed in development

A1@NDC 2016

• 04/27 15:20 Art Session by Art Director

• 04/27 17:05 Programming Session by Senior Gameplay Programmer

• Competitive, stunning visuals

Unprecedented quality in Korea

We show current results and technology at this conference

• UE4 + @@@

Use powerful rendering features of UE4

Plus, new rendering/animation/VFX features made by our team

Visual of A1

• Skin, Hair, and Metal Rendering

• Shadow Rendering

• Low Level Shader Optimization

• Run-time Rigged Physics Simulation

Agenda

Skin Rendering

• Multiple scattering

Dipole diffusion approximation

• Included in UE4

Integration of Jimenez’s implementation

We use it without any changes

SSSSS Screen Space SubSurface Scattering

Activision R&D. Property of Activision Publishing. Not Actual Gameplay

No SSSSS

• Softer lighting

• Softer shadows

• Translucent look

SSSSS

• Specular along geometry silhouettes

• Plastic-like look

Base Normal Only

• Specular along skin surface details

• More realistic

With Detail Normal

• No transmission

Ignoring irradiance from outside of visible surfaces

Lack of a screen-space approach

There’s a solution but it isn’t included in UE4

• Low frequency lighting

Can’t handle strong scattering at a short distance

Limit: UE4 SSSSS

Burley, “Extending the Disney BRDF to a BSDF with Integrated Subsurface Scattering”, SIGGRAPH 2015

• Transmission (Backlit)

• Back scattering

• Higher frequency lighting

Single ScatteringSingle Scattering Multiple Scattering (dipole)

Multiple Scattering

+ =Single + Multiple Scattering

* Single scattering is exaggerated to show different looks on the presentation screen.

ground truth Ki09

• Introduced in ShaderX7

Hyunwoo Ki, “Real-Time Subsurface Scattering using Shadow Maps”

Store translucent irradiance into multiple shadow maps (RSM/TSM style)

Approximate scattering distance by ray marching with shadow map projection

Estimate radiance using the stored irradiance and the scattering distance

• Integrated this technique into UE4 with small changes

Deferred Single Scattering

Single Scattering using Shadow Maps

• Shoot rays from the camera

Refract rays on the surfaces

• Draw stepping distance samples

Exploit Quasi Monte Carlo sampling

• Project xp onto shadow maps

To approximate incident scattering distance, Si

Review: [Ki09] Ray Marching

2 0

2

11

,, iiiiit

xs

oi

xs

otos

A π xiiiiiooiiooo

ωd sdω,xLωFeω,ωpeωFx

dAdωωnω,xLω,;xω,xSω,xL

itioto

i

N

i

M

jiit

xs

oi

xs

otos ω,xEeω,ωpeωFx itioto

0 0

,,

tos l o g

1) Deferred Shadows Pass:

Ki’s ray marching (QMC + shadow projection)

Assume that irradiance and normal are equal for all sampling steps -> Only use the shadow depth map (no additional buffers!)

Constant scattering parameters: limited by G-buffers and performance reason

Output: scalar scattering transfer instead of shadow amount (single channel)

2) Deferred Lighting Pass:

SS = intensity * (scattering transfer * SSS color) * bidirectional Fresnel transmittance * HG phase function

Output: direct lighting + single scattering

• Physically incorrect but plausible looks

Deferred Single Scattering

N

i

M

j

ss

iitoiotstoieω,xEω,ωpωF

0 0

,,

2) Lighting Pass 1) Shadowing Pass

float ComputeSingleScatteringUsingShadowMap(FGBufferData GBuffer, FShadowMapSamplerSettings Settings, float3 V, float3 L, float3 WorldPosition){

const int NumSamples = SHADOW_QUALITY * 3;

const float Eta = 1.3;const float EtaInverse = 1.0 / Eta;const float ExtinctionCoefficient = 2.55;const float MeanFreePath = 1.0 / ExtinctionCoefficient;

const float3 OutgoingDirection = -refract(V, -GBuffer.WorldNormal, EtaInverse.x);

const float InverseNumSamples = 1.0f / (float) NumSamples;const float Sample = InverseNumSamples * 0.5;

float SingleScattering = 0;

for (int i = 0; i < NumSamples; ++i){

float RefractedOutgoingDistance = -log(Sample) * MeanFreePath;float3 ScatteringPoint = (OutgoingDirection * RefractedOutgoingDistance) + WorldPosition;float4 ScatteringPointInShadowSpace = mul(float4(ScatteringPoint, 1.0f), WorldToShadowMatrix);ScatteringPointInShadowSpace.xy /= ScatteringPointInShadowSpace.w;

float ShadowmapDepthAtScatteringPoint = Texture2DSampleLevel(Settings.ShadowDepthTexture, Settings.ShadowDepthTextureSampler, ScatteringPointInShadowSpace.xy, 0).r;float IncidentDistance = max(0, abs((ShadowmapDepthAtScatteringPoint + Settings.ProjectionDepthBiasParameters.x) - ScatteringPointInShadowSpace.z)) * ProjectionDepthBiasParameters.y;float TravelPathLength = IncidentDistance + RefractedOutgoingDistance * DISTANCE_SCALE;float LightContribution = exp(-ExtinctionCoefficient * TravelPathLength);

float Weight = exp(-ExtinctionCoefficient * RefractedOutgoingDistance);SingleScattering += LightContribution / Weight;Sample += InverseNumSamples;

}

return SingleScattering / (float) NumSamples * SINGLESCATTERING_INTENSITY;}

Appendix) Ray marching code

• Transmission on thin body parts

Backlit effects

• Brighter skin surfaces

With texture masking / artistic choice

• Added approx. 1 ms per light

At a closeup view (worst case)

Rendering Results

* Single scattering is exaggerated to show different looks on the presentation screen.

• Using dithered, temporal sampling

Like volumetric lighting: Killzone: Shadow Fall, Loads of Fallen, INSIDE, etc.

Temporal reprojection

• Replace shadow rendering for skin

Currently we use conventional PCF (UE4 default)

But we expect that volumetric attenuation by SS can represent shadowing

Future Work: Single Scattering

Hair Rendering

• Layered card mesh with alpha texture

• + Hair strands mesh

• Optional textures:

Color, normal, roughness, AO, specular noise, etc.

• Similar to Destiny and The Order: 1886

Modeling and Texturing

• Transparency

Alpha blending: per-pixel drawing order

Lighting: deferred lighting? (incompatible)

Shadowing: deferred shadowing? (incompatible)

• Physically based shading model

Not fit to GGX

Problem

Alpha Test : Alpha Blend

Order of Alpha Blending

• Need per-pixel, sorted alpha blending

• Choice: K-Buffer style

Per-Pixel Linked List (PPLL)

DX11 Unordered Access View (UAV)

Based on an AMD TressFX 2.0 sample

We integrated this into UE4

Order Independent Transparency (OIT)

• Head UAV: RWTexture2D<uint>

Head indices for each linked list of pixels on the screen

• PPLL UAV: RWStructuredBuffer<FOitLinkedListDataElement>

Container to store all fragments being shaded

An element is added when each fragment is drawn

Review: PPLL OIT

uint PixelCount = OitLinkedListPPLLDataUAV.IncrementCounter();

int2 UAVTargetIndex = int2(SVPosition.xy);uint OldStartOffset;InterlockedExchange(OitLinkedListHeadAddrUAV[UAVTargetIndex], PixelCount, OldStartOffset);

OitLinkedListPPLLDataUAV[PixelCount] = NewElement;

• K-Buffer

Do manual alpha blending for the front-most K fragments: sorted

Do manual alpha blending for the remainder fragments: unsorted

• See references in detail

Review: PPLL OIT

float4 BlendTransparency(float4 FragmentColor, float4 FinalColor){

float4 OutColor;OutColor.xyz = mad(-FinalColor.xyz, FragmentColor.w, FinalColor.xyz) + FragmentColor.xyz * FragmentColor.w;OutColor.w = mad(-FinalColor.w, FragmentColor.w, FinalColor.w);return OutColor;

}

• Store radiance computed by forward lighting into PPLL / Force early-Z

• Sort and blend in the following pass

• PPLL layout: DX11 StructuredBuffer

Pack HDR radiance from half4 to uint: for memory, bandwidth, and cache alignment (128 bit)

UE4 Integration

struct FOitLinkedListDataElement{

half4 Radiance;uint NormalAndOpacity;uint Depth;uint Next;

};

struct FOitLinkedListDataElement{

uint RadianceRGY32;uint NormalAndOpacity;uint Depth;uint Next;

};

float3 UnpackRGY32(uint PackedColor){

const float ONE_OVER_255 = 1.0f / 255.0f;float3 RGB;RGB.r = (PackedColor & 0xff000000) >> 24;RGB.g = (PackedColor & 0x00ff0000) >> 16;RGB.b = 255.0f - (RGB.r + RGB.g);float Luminance = f16tof32(PackedColor);return RGB * Luminance * ONE_OVER_255;

}

uint PackRGY32(float3 Color){

float Luminance = (Color.r + Color.g + Color.b);Color.rg /= Luminance;

uint PackedValue = uint(Color.r * 255.0f + 0.5f) << 24 | uint(Color.g * 255.0f + 0.5f) << 16;

PackedValue |= f32tof16(Luminance);return PackedValue;

}

Rendering Results

• Serious pixel over draws due to layered geometry

• Optimization: single pass Opacity Thresholding using UAV

Observation: Alpha blending of hair is not for transparency but for rendering thin strands with clean silhouettes, and hair textures has almost opaque texels (especially inner layers) excepts hair tips

Goal: Reduce drawing invisible pixels occluded by almost opaque pixels from the same geometry

Unordered Opacity Thresholding

Reducing Pixel Over Draws

• Set the opacity threshold for each hair material: ex) 0.95

• Do manual Z test with an additional UAV Z buffer RWTexture2D<uint> in PS

Try to write Z if opacity of a fragment is higher than the opacity threshold

Always do Z test with the UAV Z buffer

const uint DepthAsUint = asuint(SVPosition.w);

const uint DepthToWrite = (Opacity > OpacityThreshold) ? DepthAsUint : INVALID_UINT;

uint OldMinDepthAsUint;

InterlockedMin(OitOpacityThresholdingDepthUAV[int2(SVPosition.xy)], DepthToWrite, OldMinDepthAsUint);

if (DepthAsUint > OldMinDepthAsUint)

{

discard;

}

Unordered Opacity Thresholding

• Added costs to read and write the UAV but reduced the total rendering cost

• +5~10% rendering speed and -15% memory usage

Reduced heavy lighting costs

Reduced PPLL size

No additional draw calls

Unpredictable performance gainby the rasterization order

Rendering Results

• More efficient unordered opacity thresholding

Exploit the order of triangle indices and locality?

Multiple meshes: adding per-geometry draw calls but reducing per-pixel over draws

• Use ROV for DX12

Future Work: OIT

• Per-pixel lighting for transparent materials

• Based on an experimental feature of UE4

• Limited usage

For hair / For glass and others in the future

• Supports approximated shadows

Transparent Deferred Shadows

Forward+ Lighting

• 16x16 tiled culling

• Forward light data

Constant buffer: faster than Structured Buffer (NV)

128 bit stride: cache efficiency, under 64KB

SOA? AOS?

Forward+ Lighting

Forward+ Lighting

Forward+ Lighting + Shadowing + Scattering

• Problem of forward shadowing

Adding complex nested dynamic branch / GPR pressure

Increasing forward light data (CB): shadow matrix and other parameters

Using many VRAM simultaneously (CSM and cube shadow maps)

• Transparent shadow approximation:

Volumetric attenuation on the front-most transparent pixels

Integrated with the deferred shadow pass

Inaccurate but acceptable looks

Transparent Deferred Shadows

1) Transparent Z Pre Pass

Using depth rendering material proxy if needed

The buffer is used for post processing as well

2) Shadow Depth and Deferred Shadows Passes

Shadow Depth Pass: Also using depth rendering material proxy

Deferred Shadows Pass: Compute volume lighting attenuation if transparent Z is less than opaque Z

Resolve the deferred shadowing buffer into a texture array for each light

3) Forward+ Lighting Pass

Fetching shadow amount from the texture array and weighting according to opacity

Transparent Deferred Shadows

float DeferredShadow = DeferredShadowsTextureArray.SampleLevel(PointSampler, float3(ScreenUV, LightIndex), 0).x;DeferredShadow = lerp(1, DeferredShadow, Opacity);

Deferred Shadows : Transparent Deferred Shadows

Final Rendering

* =

• Many lights and various materials for forward+ lighting

• Faster reading forward light data

• Better shadowing for inner layers

Attenuation by screen Z?

• Solve conflict of storage for transparent shadows and single scattering

Currently single scattering is ignored when hair strands are on the skin

Future Work: Lighting and Shadowing

• Marschner’s: hair strand = cylinder

• Three components of specular

Primary reflection: R

Secondary reflection: TRT

Transmission: TT

• + fake light scattering

Physically Based Shading Model

Hair Lighting

R: Primary Reflection

TRT: Secondary Reflection

TT: Transmission

• Longitudinal Scattering

Using ALU

Gaussian function instead of lookup table

• Azimuthal Scattering

Very complex math

2D function -> lookup table with constant material properties

Texture 2D Array: CosPhi, CosTheta, HairProfileID

ALU : Lookup Table

float3 ComputeLongitudinalScattering(float3 Theta, float Roughness){

const float bR = DecodeHairLongitudinalWidth(Roughness);const float3 Beta3 = float3(bR, bR * 0.5, bR * 2);return exp(-0.5 * Square(Theta) / Square(Beta3) ) / (sqrt(2.0 * PI) * Beta3);

}

U V Index

• Define per-hair properties

Create a lookup table for azimuthal scattering according to this asset

G buffer-free

Reusable

• Lookup table

Scalar light transfer for TRT and TT / performance reason

R: R, G: TRT, B: TT, A: Unused

Hair Profile Asset

• To give scalar TRT/TT spectral color

• Physically, volumetric attenuation by transmission

Angle: light, camera and tangent

Thickness: 1 - opacity (to brighten hair tips)

Travel distance of light: 2 * TT = TRT

Color Shift

const float Thickness = (1.0 - Opacity);const float ColorTintFactor = saturate(CosThetaD) + Square(Thickness) + 1e-4;const float2 BaseColorTintPower = float2(0.6, 1.2) / ColorTintFactor;float3 TTColorTint = pow(BaseColor, BaseColorTintPower.x);float3 TRTColorTint = pow(BaseColor, BaseColorTintPower.y);

• Fake Scattering: similar to UE 4.11

Volumetric attenuation and color shift using transparent deferred shadows

Phase function with camera and light vectors: from forward to backward scattering

Per-light scattering effect

Scattering: Direct Lighting

float3 ScatteringLighting = 0;if (bShadowed){

float HGPhaseFunc = HGPhaseFunctionSchlick(VoL, ScatteringAnisotropy);float3 ScatteringColor = GBuffer.BaseColor * Shadow;float3 ScatterAttenuation = saturate(pow(ScatteringColor / Luminance(ScatteringColor), 1.0 - Shadow));ScatteringLighting = ScatteringColor * ScatterAttenuation * HGPhaseFunc * ScatteringIntensity;

}

Fake Scattering

• Screen Space Volume Photon Mapping

Use OIT PPLL as the volume photon map: radiance, normal and depth

Gather nearest photons on the front-most pixels after sorting

3 x 3 Gaussian kernel

Isotropic phase function: hard to handle per-material properties

Can’t filter radiance from other geometry but it will be attenuated

Flickering due to UAV writing -> reduced by TAA

Scattering: Indirect Lighting

float2 PhotonScreenUV = InScreenUV + float2(SEARCH_RADIUS * dx, SEARCH_RADIUS * dy);int2 PhotonAddress = int2(PhotonScreenUV * View.ViewSizeAndInvSize.xy + View.ViewSizeAndInvSize.zw);uint PhotonListIndex = OitLinkedListHeadAddressSRV[PhotonAddress];if (PhotonListIndex == INVALID_UINT){

continue;}

FOitLinkedListDataElement Photon = OitLinkedListDataSRV[PhotonListIndex];float3 PhotonRadiance = UnpackRGY32(Photon.RadianceRGY32);

float3 PhotonNormal = GetNormalFromPack(Photon.NormalAndOpacity);float CosTheta = dot(FrontmostNormal, PhotonNormal);

float3 PhotonPositionWS = ConstructWorldPosition(PhotonScreenUV, asfloat(Photon.Depth));float R3 = distance(FrontmostPositionWS, PhotonPositionWS) * PHOTON_DISTANCE_SCALE;

float3 PhotonContribution = 3.0 * PhotonRadiance;PhotonContribution /= R3;PhotonContribution *= HGPhaseFunctionSchlick(CosTheta, MATERIAL_ANISOTROPY); // isotropicGaussPhotonScattering += PhotonContribution * GaussianWeights[GaussianWeightIndex];

Screen Space Volume Photon Mapping

Diffuse Lighting

• Tangent Lambertian

DiffuseLighting = max(0, sqrt(1 – SinThetaI * SinTetaI))

* EnergeConservingWrappedDiffuse(N, L, 1)

* DiffuseIntensity

Final Rendering

• Specular parameters

Noise: fuzzy highlight

Roughness: width and strength of highlight

Shift: position of highlight peek

+ binding a hair profile asset

• Diffuse, fake scattering and textures

• Other hair parameters

-> To create various styled hairs

Hair Material

• Better scattering

• Material LOD

• Finding the best method for a certain hair style

Future Work: Hair Shading

Metal Rendering

• Experimental

• Anisotropic GGX

• Far Cry 4 style

• To all lighting components

Direct lighting, sky lighting, reflection environment, SSR, etc.

Using tangent irradiance map?

Anisotropic Specular

Shadow Rendering

• For a character viewer and a lobby

EVSM: Exponential Variance Shadow Maps

• For the game scene

Sun: PCSS

Other types of lights: PCF / No changes from UE4

Additional shadows: Screen Space Inner Shadows (new feature)

Scene-Specific Shadows

• Experimental

• Pre-filtered shadows

No changes from the original algorithm

Nice look but light leaks and low performance

• Optimization

CSM split limits: maximum 2

Scissor test: larger than screen space shadow bounds

EVSM

• For Sun in the game scene

• One of an effect of time of lighting changes

Day and night cycle in the game play

Different blur size by time: sharp at noon, soft at sunrise and sunset

Different blur size by distance between occluders and receivers

• Optimization

CSM split limits: maximum 2

• Temporal reprojection

Reduce flickering due to moving Sun, and sampling artifacts

Lerp according to difference between prev and current frame

PCSS

float2 Attenuation = Texture2DSample(SunLightAttenuationTexture, TextureSamplerPoint, PrevScreenUV).xy;float2 ShadowAndSSSTransmission = float2(Shadow, SSSTransmission);const float2 TAAFactor = Square(1.0 - abs(ShadowAndSSSTransmission - Attenuation));ShadowAndSSSTransmission = lerp(ShadowAndSSSTransmission, Attenuation, 0.5 * TAAFactor);

• Shadows in shadows:

Darker shadows on environment occluded by characters

Better looks when a character is on the shadowed surfaces

Directionality: difference from AO

• Using scene depth

No preprocessing or asset settings

Comparison> Capsule based: The Order: 1886 or UE 4.11

Screen Space Inner Shadows

• G-buffer changes: add caster and receiver bit masks

1) Stencil Masking Pass

Write stencil at shadowed pixels by Sun

Ignore unlit pixels

2) Shadow Rendering Pass: SSR styled ray marching

Shoot rays to the half vector between Sun and Sky

Limit max tracing distance: artistic choice and performance win

Temporal reprojection to the previous frame’s buffer

Screen Space Inner Shadows

L Sky

H

Sun ShadowInner Shadow

• ½ resolution buffer

• Separable Gaussian blur

• Approximately 0.5 ms

• Shadow amount is applied for

sky lighting and GI with a receiver mask

Screen Space Inner Shadows

• Important for game visuals

Look

Day and night cycle

• How to reduce costs and flickering?

High draw calls

Moving Sun

Future Work: Shadow Rendering

Run-time Rigged Physics Simulation

• Movement of short hair

• Trembling body fat and cloth wrinkles

• To reduce work load of artists

Goal

• Define simulator assets in the editor

Currently we support spring simulation only

• Group vertices

According to vertex colors roughly painted by artists, and the simulator assets

• Sample simulator bones

In the bounds of a vertex group / according to a density setting / snap to the nearest vertex

Poisson distribution / deterministic sampling

• Rig the simulator bones

Simulator bone -> become a child of the nearest bone in a character

Vertex -> rigged with the nearest simulator bone

Distance based skinning weights

Algorithm

• Trying to rich animation with various methods

Module based animation

Procedural animation

Physics simulation

• They may be introduced by other conferences

ex) NDC 2017?

Animation Techniques of A1

Low Level Shader Optimization

• Using the GPU profiler of UE4

Checking rendering costs and doing high level shader optimization

• Using RenderDoc, Intel GPA, and AMD GPU PerfStudio

Debugging shader code and doing low level shader optimization

• Rewriting shader code by hand with optimization references

Approach

• Only critical parts of shader written by Epic Games

To upgrade a new version of the engine continously

We will check all of shader code before shipping

• Currently we focus on shader written by ours

• This talk shows examples of our optimization

Target Code

Before After

Static Branch with Preprocessor

float3 L = (LightPositionAndIsDirectional.w == 1)? -LightPositionAndIsDirectional.xyz : normalize(LightPositionAndIsDirectional.xyz

- OpaqueWorldPosition);

#if USE_FADE_PLANE // CSM case = directional lightfloat3 L = -LightPositionAndIsDirectional.xyz;

#elsefloat3 L = (LightPositionAndIsDirectional.w == 1)

? -LightPositionAndIsDirectional.xyz : normalize(LightPositionAndIsDirectional.xyz

- OpaqueWorldPosition);#endif

Before After

Vectorization and Explicit MAD

float2 LookupUV = float2(CosPhiD, CosThetaD) * 0.5 + 0.5;float Backlit = saturate(-CosThetaD * 0.5 + 0.5);

float3 LookupUVandBacklit = saturate(mad(float3(CosPhiD, CosThetaD, -CosThetaD), 0.5, 0.5));

Before After

Share Preceding Computation

for (int X = 0; X < NumSamplesSqrt; ++X) {

for (int Y = 0; Y < NumSamplesSqrt; Y++){

float2 ShadowOffset = TexelSize * StepSize * float2(X, Y);

const float2 BaseTexelSize = TexelSize * StepSize;…for (int X = 0; X < NumSamplesSqrt; ++X) {

for (int Y = 0; Y < NumSamplesSqrt; Y++){

float2 ShadowOffset = BaseTexelSize * float2(X, Y);

Before After

Rearrange Scalar/Vector Operation

float3 DiffuseLighting = (TangentDiffuse * GBuffer.DiffuseColor) / PI * NoLWrapped * ShadowColor;

float3 DiffuseLighting = GBuffer.DiffuseColor * (TangentDiffuse / PI * NoLWrapped * ShadowColor);

Before After

Use Modifiers as Input

Force += -normalize(Position) * Simulation.GravityStrength; Force += normalize(-Position) * Simulation.GravityStrength;

Before After

Rearrange Code Lines

// 무언가 긴 작업…//clip(OpacityMask);

// 셰이더 메인이 시작 후 최대한 빨리…//clip(OpacityMask);

Use termination if possible

Early-Z, Stencil, and Discard

if (GBuffer.ShadingModelID != 0){

discard;}

float Attenuation = Texture2DSample(SunLightAttenuationTexture, TextureSamplerPoint, ScreenUV).x;if (Attenuation > 0.99){

discard;}

-------

[EARLYDEPTHSTENCIL]void OrderIndependentTransparencyCompositePixelMain(

float2 InScreenUV: TexCoord0, float4 InSVPosition: SV_Position, out float4 OutColor: SV_Target0){

Data packing and cache line alignment

ALU VS. lookup table

Misc.: Above Metioned

#if OIT_PACK_RADIANCEuint RadianceRGY32;

#elsehalf4 Radiance;

#endif

float3 ComputeLongitudinalScattering(float3 Theta, float Roughness){

const float bR = DecodeHairLongitudinalWidth(Roughness);const float3 Beta3 = float3(bR, bR * 0.5, bR * 2);return exp(-0.5 * Square(Theta) / Square(Beta3) ) / (sqrt(2.0 * PI) * Beta3);

}

• Continuous work

• Optimization of shader written by Epic Games

• Although aggressive and smart optimization of a shader compiler is amazing, it sometimes produces unwanted results.

• Need explicitly writing GPU friendly code and checking disassembly

Future Work: Low Level Shader Optimization

• New IP of Nexon

• AAA-Quality Graphics

• With Cutting Edge Graphics Technology

• In Development

Summary of This Talk

• Colleagues of A1

• Support Team of Epic Korea

• Authors of References

Acknowledgement

Thanks

WE ARE HIRING!

• AMD TressFX Hair http://www.amd.com/en-us/innovations/software-technologies/technologies-gaming/tressfx

• Burke, “Hair In Destiny”, SIGGRAPH 2014 http://advances.realtimerendering.com/destiny/siggraph2014/heads/

• Burley, “Extending the Disney BRDF to a BSDF with Integrated Subsurface Scattering”, SIGGRAPH 2015 http://blog.selfshadow.com/publications/s2015-shading-course/#course_content

• d‘Eon, “An Energy-Conserving Hair Reflectance Model”, ESR 2011 http://www.eugenedeon.com/

• GCN Performance Tweets http://developer.amd.com/wordpress/media/2013/05/GCNPerformanceTweets.pdf

• Wexler, “GPU-Accelerated High-Quality Hidden Surface Removal”, Graphics Hardware 2005 http://developer.amd.com/wordpress/media/2013/05/GCNPerformanceTweets.pdf

• Jensen, “A Practical Model for Subsurface Light Transport”, SIGGRAPH 2001 http://www.graphics.stanford.edu/papers/bssrdf/

• Jimenez, “Next Generation Character Rendering”, GDC 2013 http://www.iryoku.com/stare-into-the-future

• Ki, Real-Time Subsurface Scattering using Shadow Maps, ShaderX7 http://amzn.to/1TxzadP

• Marschner, “Light Scattering from Human Hair Fibers”, SIGGRAPH 2003 https://www.cs.cornell.edu/~srm/publications/SG03-hair-abstract.html

• McAuley, “Rendering the World of Far Cry 4”, GDC 2015 http://www.gdcvault.com/play/1022235/Rendering-the-World-of-Far

• Moon, Simulating multiple scattering in hair using a photon mapping approach, SIGGRAPH 2006 https://www.cs.cornell.edu/~srm/publications/SG06-hair.pdf

• More Explosions, More Chaos, and Definitely More Blowing Stuff Up: Optimizations and New DirectX Features in ‘Just Cause 3′ https://software.intel.com/sites/default/files/managed/20/d5/2016_GDC_Optimizations-and-DirectX-features-in-JC3_v0-92_X.pdf

• Nguyen, “Hair Animation and Rendering in the Nalu Demo”, GPU Gems 2 http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter23.html

• NVIDIA GameWorks Blog https://developer.nvidia.com/gameworks/blog

• Persson, Low-level Shader Optimization for Next-Gen and DX11, GDC 2014 http://www.humus.name/index.php?page=Articles

• Persson, Low-Level Thinking in High-Level Shading Languages, GDC 2013 http://www.humus.name/index.php?page=Articles

• Pettineo, “A Sampling of Shadow Techniques” https://mynameismjp.wordpress.com/2013/09/10/shadow-maps/

• Phail-Liff, “Melton and Moustaches: The Character Art and Shot Lighting Pipelines of The Order: 1886” http://www.readyatdawn.com/presentations/

• Thibieroz, Grass, Fur and all Things Hairy, GDC 2014 http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2012/10/Grass-Fur-and-All-Things-Hairy-Thibieroz-Hillesland.ppsx

• Unreal Engine 4 https://www.unrealengine.com/

References