Around the World in 80 Shaders

69

Transcript of Around the World in 80 Shaders

Page 1: Around the World in 80 Shaders
Page 2: Around the World in 80 Shaders

Around the World in 80 Shaders

Stephen McAuleyBizarre Creations

[email protected]

Page 3: Around the World in 80 Shaders

Overview

• Introduction:– The FX system

• Around the world tour:– Default– Skin– MPEG corruption– Refraction mapping– Shallow water– Aquarium

Page 4: Around the World in 80 Shaders

FX System: Problem

• After finishing PGR4 and The Club we needed a new solution to handling shaders.– Two different systems.– Extremely complicated to add new shaders.• Have to add new vertex declarations, new exporter

code and new rendering code as well.

– Not data driven.• Shaders treated as code not data.• Could never run on an SPU.

– No Maya previewing for artists.

Page 5: Around the World in 80 Shaders

FX System: Solution

• Our solution was the FX system:– Based on .fx files.– Entirely data driven.– Automatic Maya previews for artists.– All rendering code now runs on the SPUs.

Page 6: Around the World in 80 Shaders

FX System: Maya and XSI

• Compile Maya and XSI shaders alongside PC shaders.

• Annotations control how the parameters appear to the artists:

• Artists can “expose” parameters they want to be set within game.

texture2D g_tAlbedo < string SasUiLabel = “Colour”; >;

float g_fScale < string SasUiLabel = “Scale”; > = 0.0;

Page 7: Around the World in 80 Shaders

FX System: Exporting

• Scene converter:– Reads vertex input structure• With the help of annotations.

– Exports relevant vertex data in the correct format.

struct C_VertexInput{ float3 m_vPosition : POSITION; float3 m_vNormal : NORMAL; float4 m_vTexCoord : TEXCOORD0 annotation(xy(uv:0) | zw(uv:luxlightmap) | format(F16_4));};

Page 8: Around the World in 80 Shaders

FX System: Exporting

• Lua script within each shader helps build shader permutations:

• If a bumpmap is present, game will search for ShaderB.fx instead of Shader.fx.

• Make sure you have compiled that permutation!

texture2D g_tBumpmap < string SasUiLabel = “Bumpmap”; >;

#if defined(FXFILE_PARSER)if (g_tBumpmap) then append(“B”, 10) end#endif

Page 9: Around the World in 80 Shaders

FX System: In Game

• Game sets exposed and shared parameters.• Techniques are changed dynamically:• e.g. shadow mapping technique, prepass technique…

• Shader parameters can be overridden via our debugging tool:– Currently only on all instances of a shader.

Page 10: Around the World in 80 Shaders
Page 11: Around the World in 80 Shaders

Default

Athens

Page 12: Around the World in 80 Shaders

Default Shader

• This is our base material for everything in game.

• Applied when artists use the Lambert shader in Maya.– Easy to set up.– Artists just set an albedo texture.– Other textures are picked up in the exporter using

a naming convention.

Page 13: Around the World in 80 Shaders

Default Shader: Material

• The following material options are supported:– Albedo (_DIFF)– Normal (_NORM)– Specular (_IPR0)– Emissive (_NEON)

• These are all controlled by textures.

Page 14: Around the World in 80 Shaders

Default Shader: Lighting

• We support these lighting methods:– Light maps– Vertex lighting– Vertex PRT– SH lighting

• In Blood Stone, they contained the following information:– Colour, sun occlusion and ambient occlusion

Page 15: Around the World in 80 Shaders

Default Shader: Lighting

Our BRDF for sun lighting:

where is the surface albedo and is Schlick’s fresnel approximation:

Page 16: Around the World in 80 Shaders

Default Shader: Specular

We have three parameters controlling specular:

• is the specular intensity• is the specular power• is the normal specular reflectance

Page 17: Around the World in 80 Shaders

Default Shader: Specular

• These three specular properties come from our specular texture:– Red channel: Intensity ()– Green channel: Power ()

– Blue channel: Reflectance ()

Page 18: Around the World in 80 Shaders
Page 19: Around the World in 80 Shaders

Skin

Istanbul

Page 20: Around the World in 80 Shaders

Skin

• Standard diffuse lighting gives unrealistic results when applied to skin.

• It looks hard and dry compared to skin’s soft appearance.

• To achieve this look, we need to model subsurface scattering.

Page 21: Around the World in 80 Shaders

Skin

• The best approach is described by Eugene d’Eon and David Luebke in [1]:– Observed that red light scatters in skin more than

green and blue.– Simulate subsurface scattering by lighting in

texture space, then performing separate gaussian blurs for red, green and blue channels.

• This is expensive and intrusive. Are there any cheaper ways?

Page 22: Around the World in 80 Shaders

Skin: Approximations

• Standard diffuse lighting:D = N.L

• Wrapped diffuse lighting:D = N.L * w + (1 – w)• i.e. D = N.L * 0.5 + 0.5

• What if we wrap different colours by different amounts?

Page 23: Around the World in 80 Shaders

Skin: Our solution

• Coloured wrapped diffuse lighting:D = N.L * W + (1 – W)

• i.e. D = N.L * { 0.5, 0.8, 0.9 } + { 0.5, 0.2, 0.1 }

• Simulates subsurface scattering by giving skin a softer look.

• Simulates red light scattering further in skin.• Cheap and easy to implement.

Page 24: Around the World in 80 Shaders

Standard Diffuse

Page 25: Around the World in 80 Shaders

Wrapped Diffuse

Page 26: Around the World in 80 Shaders

Coloured Wrapped Diffuse

Page 27: Around the World in 80 Shaders

MPEG Corruption

Monaco

Page 28: Around the World in 80 Shaders

MPEG Corruption

• For the AR phone, we wanted an effect that simulated MPEG corruption.

• “Blocks” in the image don’t update and remain from the previous frame.

Page 29: Around the World in 80 Shaders

MPEG Corruption

• Algorithm:– For each pixel, point sample a noise texture.• Scaled so each texel is the size of a “block”.

– If sample is less than a threshold, take pixel from previous frame buffer.• Instead of the previous frame buffer, use a scaled and

offset version of the current frame.

– Else, take pixel from current frame buffer.

Page 30: Around the World in 80 Shaders

MPEG Corruption

half2 vRUV = vUV * g_vCorruptionBlockSize; vRUV += half2(g_fCorruptionAmount * 7.123h, 0.0h);

half fRand = h4tex2D(g_tNoise, vRUV).r;

if(fRand < g_fCorruptionAmount){ real2 vDUV = input.m_TexCoord * g_vCorruptionUVScale; vDUV += g_vCorruptionUVOffset;

vColour = h4tex2D(g_tBackbuffer, vDUV).rgb; vColour *= (1.0h + fRand - 0.5h * g_fCorruptionAmount);}else{ vColour = h4tex2D(g_tBackbuffer, vUV).rgb;}

Page 31: Around the World in 80 Shaders
Page 32: Around the World in 80 Shaders
Page 33: Around the World in 80 Shaders
Page 34: Around the World in 80 Shaders

Refraction Mapping

Siberia

Page 35: Around the World in 80 Shaders

Refraction Mapping

• We wanted to simulate surfaces that are coated in a layer of ice.

• Requirements:– These surfaces have two layers:• Ice layer• Base layer

– The base layer is refracted by the ice layer.

Page 36: Around the World in 80 Shaders

Refraction Mapping

• Our in-game materials use three textures:– albedo– normal– specular

• We split these textures across the two layers.

Ice layer:• normal• specular

Base layer:• albedo

uv

refracted uv

Page 37: Around the World in 80 Shaders

Refraction Mapping

• Calculate the refracted texture coordinate:

• Albedo texture uses vRefractUV.• Normal and specular maps use vUV.

half3 vRefract = refract(vTangentView, vTangentNormal, 1.0f / g_fRefractiveIndex);

float2 vUVOffset = g_fDisplacement * vRefract.xy / vRefract.z;

float2 vRefractUV = vUV + vUVOffset;

Page 38: Around the World in 80 Shaders

Default

Page 39: Around the World in 80 Shaders

Displacement

Page 40: Around the World in 80 Shaders

Refraction

Page 41: Around the World in 80 Shaders

Refraction Mapping: Extensions

• Vary the displacement across the surface:– Height map.– Vertex colours.

• Add a frost layer in between the top layer and the base layer.

Page 42: Around the World in 80 Shaders

Default

Page 43: Around the World in 80 Shaders

Refraction

Page 44: Around the World in 80 Shaders

Frost

Page 45: Around the World in 80 Shaders

Refraction Mapping: Problems

• Make sure your tangent space is correct!– Any errors will very quickly become apparent.

• Displacement breaks as you look at the surface edge on.

Page 46: Around the World in 80 Shaders

Shallow Water

Burma

Page 47: Around the World in 80 Shaders

Shallow water

Deep water

Page 48: Around the World in 80 Shaders

Shallow Water

• Why does shallow water appear more transparent than deep water?– Water molecules absorb and scatter light.– The further light travels, the higher probability it is

absorbed or scattered.– Absorption and scattering are dependent on

wavelength:• e.g. red light is absorbed more than green or blue,

giving water its characteristic colour.

Page 49: Around the World in 80 Shaders

Shallow Water

• Premoze and Ashikhmin suggested the following model for the absorption and scattering of light in water [2]:

Page 50: Around the World in 80 Shaders

Shallow Water

𝐿=𝐿𝑧𝑒−𝑐𝑅+𝐿0(1−𝑒

−𝑐𝑅𝑒−𝐾 𝑑𝐻 )R

H

LZ

L0

extinction inscattering

c and Kd are wavelength dependent absorption and scattering coefficients

Page 51: Around the World in 80 Shaders

Shallow Water

• Optimisation:– Remove the term.– Only changes the falloff of the inscattering, not

the intensity.

Page 52: Around the World in 80 Shaders

Shallow Water

• Optimisation:– Remove the term.– Only changes the falloff of the inscattering, not

the intensity.

Page 53: Around the World in 80 Shaders

Shallow Water

• Optimisation:– Remove the term.– Only changes the falloff of the inscattering, not

the intensity.• Visual artefact:– Very shallow water is slightly darker.

Page 54: Around the World in 80 Shaders

Shallow Water

• The final equation is a lerp between the water colour and the underwater colour, based on the extinction:

• Final shader code:

half3 vExtinction = exp(-g_vExtinctionCoeffs * fDistUnderwater);

half3 vDiffuse = lerp(vSceneColour, vWaterColour, vExtinction);

Page 55: Around the World in 80 Shaders

No extinction

Page 56: Around the World in 80 Shaders

Red extinction

Page 57: Around the World in 80 Shaders

Green/blue extinction

Page 58: Around the World in 80 Shaders

Aquarium

Bangkok

Page 59: Around the World in 80 Shaders

Aquarium

• Is an aquarium tank equivalent to shallow water?

R LZ

L0

Page 60: Around the World in 80 Shaders

With Extinction

Page 61: Around the World in 80 Shaders

Image courtesy Jon Rawlinsonjonrawlinson.com

Page 62: Around the World in 80 Shaders

Aquarium

• Simulate a light positioned directly above the tank.

• This is our new inscattering term.

R LZ

L0

M0

H

MZ

Page 63: Around the World in 80 Shaders

Aquarium

• Inscattering equation:

• Light colour, , should be the colour of the light as it hits the surface of the water.– i.e. light colour modulated by water colour

• Use a different attenuation coefficient to the extinction.– Allows for more interesting hue shifts.

Page 64: Around the World in 80 Shaders

Aquarium

• Shader code:

half3 vExtinction = exp(-g_vExtinctionCoeffs * fDistanceThroughWater);

half3 vInscattering = exp(-g_vInscatteringCoeffs * fDistanceUnderWater);

vInscattering *= g_vLightColour.rgb;

half3 vDiffuse = lerp(vSceneColour, vInscattering, vExtinction);

Page 65: Around the World in 80 Shaders

Aquarium

• For the final touch, add light shafts:– Project two scrolling textures in the world x-z

plane.• Sample each texture at a fixed distance behind the

glass front of the aquarium tank.

– Combine texture samples into light shaft term, .– Modify inscattering term:

Page 66: Around the World in 80 Shaders

With Light

Page 67: Around the World in 80 Shaders

With Light Shafts

Page 68: Around the World in 80 Shaders

References

• [1] Advanced Techniques for Real-Time Skin Rendering, Eugene d’Eon and David Luebke, GPU Gems 3, 2008

• [2] Rendering Natural Waters, Simon Premoze & Michael Ashikhmin, 2001

Page 69: Around the World in 80 Shaders

Credits

• For working on the technology described in this presentation:– Paul Malin– Jan van Valburg– David Hampson