Simulation of Iridescence and Translucency on Thin Surfaces

Simulation of Iridescence and Translucency on Thin Surfaces Simulation of Iridescence and Translucency on Thin Surfaces

14.12.2012 Views

From ShaderX 2 – Shader Programming Tips ong>andong> Tricks with DirectX 9 ong>Simulationong> ong>ofong> ong>Iridescenceong> ong>andong> ong>Translucencyong> on Thin Surfaces Introduction Natalya Tatarchuk ong>andong> Chris Brennan 3D Application Research Group ATI Research This chapter will focus on simulating the visual effect ong>ofong> translucency ong>andong> iridescence ong>ofong> thin surfaces such as butterfly wings. When creating a visual impression ong>ofong> a particular material, an important characteristic ong>ofong> that surface is the luminosity ong>ofong> the material. There are various ways a surface can be luminous. Those include sources with or without heat, from an outside source, ong>andong> from the object itself (other than a mere reflection). Luminous objects that exhibit certain combinations ong>ofong> these characteristics can be described as translucent or iridescent, depending on the way that the surface “scatters” incoming light. ong>Translucencyong> ong>ofong> a material is determined by the ability ong>ofong> that surface to allow light to pass through without full transparency. Translucent materials can only receive light ong>andong> thus can be luminous only when lit from an outside source. Although there has been ample research in the recent years in interactive simulation ong>ofong> fully translucent surfaces such as marble or wax [Jensen01], this chapter will focus on simulating translucency for thin surfaces. A good example ong>ofong> the visual effect ong>ofong> translucency ong>ofong> thin surfaces would be if you were to take a piece ong>ofong> rice paper ong>andong> hold it against a light source (for example, Chinese lanterns). You would see that the light makes the rice paper seem to glow from within, yet you cannot see the light source through the paper because the paper scatters incoming light. ong>Iridescenceong> is an effect caused by the interference ong>ofong> light waves resulting from multiple reflections ong>ofong> light ong>ofong>f ong>ofong> surfaces ong>ofong> varying thickness. This visual effect can be detected as a rainbow pattern on the surface ong>ofong> soap bubbles ong>andong> gasoline spills, ong>andong> in general, on surfaces covered with thin film diffracting different frequencies ong>ofong> incoming light in different directions. The surface ong>ofong> a soap bubble exhibits iridescence due to a layer ong>ofong> air, which varies in thickness, between the top ong>andong> bottom surfaces ong>ofong> the bubble. The reflected colors vary along with the thickness ong>ofong> the surface. Mother-ong>ofong>-pearl, compact discs ong>andong> various gem stones share that quality. Perhaps most captivating ong>ofong> all, however, is the iridescence seen on the wings ong>ofong> many beautiful butterflies, such as Blue pansy butterflies, Junonia orithya, or the Malachite butterflies, Siproeta stelenes. These wings exhibit vivid colorful iridescence (see Figure 1 for examples), the color ong>ofong> which 1

From ShaderX 2 – Shader Programming Tips <str<strong>on</strong>g>and</str<strong>on</strong>g> Tricks with DirectX 9<br />

<str<strong>on</strong>g>Simulati<strong>on</strong></str<strong>on</strong>g> <str<strong>on</strong>g>of</str<strong>on</strong>g> <str<strong>on</strong>g>Iridescence</str<strong>on</strong>g> <str<strong>on</strong>g>and</str<strong>on</strong>g><br />

<str<strong>on</strong>g>Translucency</str<strong>on</strong>g> <strong>on</strong> <strong>Thin</strong> <strong>Surfaces</strong><br />

Introducti<strong>on</strong><br />

Natalya Tatarchuk <str<strong>on</strong>g>and</str<strong>on</strong>g> Chris Brennan<br />

3D Applicati<strong>on</strong> Research Group<br />

ATI Research<br />

This chapter will focus <strong>on</strong> simulating the visual effect <str<strong>on</strong>g>of</str<strong>on</strong>g> translucency <str<strong>on</strong>g>and</str<strong>on</strong>g><br />

iridescence <str<strong>on</strong>g>of</str<strong>on</strong>g> thin surfaces such as butterfly wings. When creating a visual impressi<strong>on</strong> <str<strong>on</strong>g>of</str<strong>on</strong>g><br />

a particular material, an important characteristic <str<strong>on</strong>g>of</str<strong>on</strong>g> that surface is the luminosity <str<strong>on</strong>g>of</str<strong>on</strong>g> the<br />

material. There are various ways a surface can be luminous. Those include sources with<br />

or without heat, from an outside source, <str<strong>on</strong>g>and</str<strong>on</strong>g> from the object itself (other than a mere<br />

reflecti<strong>on</strong>). Luminous objects that exhibit certain combinati<strong>on</strong>s <str<strong>on</strong>g>of</str<strong>on</strong>g> these characteristics<br />

can be described as translucent or iridescent, depending <strong>on</strong> the way that the surface<br />

“scatters” incoming light.<br />

<str<strong>on</strong>g>Translucency</str<strong>on</strong>g> <str<strong>on</strong>g>of</str<strong>on</strong>g> a material is determined by the ability <str<strong>on</strong>g>of</str<strong>on</strong>g> that surface to allow<br />

light to pass through without full transparency. Translucent materials can <strong>on</strong>ly receive<br />

light <str<strong>on</strong>g>and</str<strong>on</strong>g> thus can be luminous <strong>on</strong>ly when lit from an outside source. Although there has<br />

been ample research in the recent years in interactive simulati<strong>on</strong> <str<strong>on</strong>g>of</str<strong>on</strong>g> fully translucent<br />

surfaces such as marble or wax [Jensen01], this chapter will focus <strong>on</strong> simulating<br />

translucency for thin surfaces. A good example <str<strong>on</strong>g>of</str<strong>on</strong>g> the visual effect <str<strong>on</strong>g>of</str<strong>on</strong>g> translucency <str<strong>on</strong>g>of</str<strong>on</strong>g> thin<br />

surfaces would be if you were to take a piece <str<strong>on</strong>g>of</str<strong>on</strong>g> rice paper <str<strong>on</strong>g>and</str<strong>on</strong>g> hold it against a light<br />

source (for example, Chinese lanterns). You would see that the light makes the rice paper<br />

seem to glow from within, yet you cannot see the light source through the paper because<br />

the paper scatters incoming light.<br />

<str<strong>on</strong>g>Iridescence</str<strong>on</strong>g> is an effect caused by the interference <str<strong>on</strong>g>of</str<strong>on</strong>g> light waves resulting from<br />

multiple reflecti<strong>on</strong>s <str<strong>on</strong>g>of</str<strong>on</strong>g> light <str<strong>on</strong>g>of</str<strong>on</strong>g>f <str<strong>on</strong>g>of</str<strong>on</strong>g> surfaces <str<strong>on</strong>g>of</str<strong>on</strong>g> varying thickness. This visual effect can be<br />

detected as a rainbow pattern <strong>on</strong> the surface <str<strong>on</strong>g>of</str<strong>on</strong>g> soap bubbles <str<strong>on</strong>g>and</str<strong>on</strong>g> gasoline spills, <str<strong>on</strong>g>and</str<strong>on</strong>g> in<br />

general, <strong>on</strong> surfaces covered with thin film diffracting different frequencies <str<strong>on</strong>g>of</str<strong>on</strong>g> incoming<br />

light in different directi<strong>on</strong>s. The surface <str<strong>on</strong>g>of</str<strong>on</strong>g> a soap bubble exhibits iridescence due to a<br />

layer <str<strong>on</strong>g>of</str<strong>on</strong>g> air, which varies in thickness, between the top <str<strong>on</strong>g>and</str<strong>on</strong>g> bottom surfaces <str<strong>on</strong>g>of</str<strong>on</strong>g> the bubble.<br />

The reflected colors vary al<strong>on</strong>g with the thickness <str<strong>on</strong>g>of</str<strong>on</strong>g> the surface. Mother-<str<strong>on</strong>g>of</str<strong>on</strong>g>-pearl,<br />

compact discs <str<strong>on</strong>g>and</str<strong>on</strong>g> various gem st<strong>on</strong>es share that quality. Perhaps most captivating <str<strong>on</strong>g>of</str<strong>on</strong>g> all,<br />

however, is the iridescence seen <strong>on</strong> the wings <str<strong>on</strong>g>of</str<strong>on</strong>g> many beautiful butterflies, such as Blue<br />

pansy butterflies, Jun<strong>on</strong>ia orithya, or the Malachite butterflies, Siproeta stelenes. These<br />

wings exhibit vivid colorful iridescence (see Figure 1 for examples), the color <str<strong>on</strong>g>of</str<strong>on</strong>g> which<br />

1


<str<strong>on</strong>g>Simulati<strong>on</strong></str<strong>on</strong>g> <str<strong>on</strong>g>of</str<strong>on</strong>g> <str<strong>on</strong>g>Iridescence</str<strong>on</strong>g> <str<strong>on</strong>g>and</str<strong>on</strong>g> <str<strong>on</strong>g>Translucency</str<strong>on</strong>g> <strong>on</strong> <strong>Thin</strong> <strong>Surfaces</strong><br />

has been shown to be independent <str<strong>on</strong>g>of</str<strong>on</strong>g> pigmentati<strong>on</strong> <str<strong>on</strong>g>of</str<strong>on</strong>g> the wings, <str<strong>on</strong>g>and</str<strong>on</strong>g> is attributed to the<br />

microstructure <str<strong>on</strong>g>of</str<strong>on</strong>g> the scales located <strong>on</strong> <str<strong>on</strong>g>and</str<strong>on</strong>g> within butterfly wings.<br />

Blue pansy butterfly<br />

Jun<strong>on</strong>ia orithya<br />

Malachite butterflies<br />

Siproeta stelenes<br />

Figure 1 - Butterflies in nature<br />

The effect described in this chapter simulates translucency <str<strong>on</strong>g>and</str<strong>on</strong>g> iridescence<br />

patterns <str<strong>on</strong>g>of</str<strong>on</strong>g> delicate butterfly wings. To generate iridescence we have merged the<br />

approaches described in “Bubble Shader” [Isidoro02] <str<strong>on</strong>g>and</str<strong>on</strong>g> in “Textures as Lookup Tables<br />

for Per-Pixel Lighting Computati<strong>on</strong>s” [Vlachos02].<br />

Algorithm<br />

Inputs<br />

This effect uses a geometric model with a positi<strong>on</strong>, a normal, a set <str<strong>on</strong>g>of</str<strong>on</strong>g> texture<br />

coordinates, a tangent <str<strong>on</strong>g>and</str<strong>on</strong>g> a binormal vector. All <str<strong>on</strong>g>of</str<strong>on</strong>g> these comp<strong>on</strong>ents are supplied to the<br />

vertex shader. At the pixel level, we combine gloss, opacity, <str<strong>on</strong>g>and</str<strong>on</strong>g> normal maps for a<br />

multi-layered final look. The gloss map is used to c<strong>on</strong>tribute to satiny highlights <strong>on</strong> the<br />

butterfly wings. The opacity map allows the wings to have variable transparency <str<strong>on</strong>g>and</str<strong>on</strong>g> the<br />

normal map is used to give wings a bump-mapped look to allow for more surface<br />

thickness variati<strong>on</strong>s. The input texture coordinates are used to sample all texture maps.<br />

Sample RenderM<strong>on</strong>key TM Workspace<br />

The CD that comes with this book c<strong>on</strong>tains a build <str<strong>on</strong>g>of</str<strong>on</strong>g> the RenderM<strong>on</strong>key IDE<br />

which is an envir<strong>on</strong>ment for shader development. Al<strong>on</strong>g with the applicati<strong>on</strong> itself, the<br />

RenderM<strong>on</strong>key installer installs a series <str<strong>on</strong>g>of</str<strong>on</strong>g> workspaces including <strong>on</strong>e called HLSL<br />

Iridescent Butterfly.xml. This workspace c<strong>on</strong>tains the effect we are describing in this<br />

chapter. Feel free to modify any <str<strong>on</strong>g>of</str<strong>on</strong>g> the parameters to the shaders to explore their effect <strong>on</strong><br />

the final visual result. Of course, you can also modify the actual shaders to underst<str<strong>on</strong>g>and</str<strong>on</strong>g><br />

their algorithms in greater depth.<br />

2


Vertex Shader<br />

From ShaderX 2 – Shader Programming Tips <str<strong>on</strong>g>and</str<strong>on</strong>g> Tricks with DirectX 9<br />

The vertex shader for this effect computes vectors that will be used by the pixel<br />

shader to compute the illuminati<strong>on</strong> result. At the pixel level, the view vector <str<strong>on</strong>g>and</str<strong>on</strong>g> the light<br />

vector will be used for calculating diffuse illuminati<strong>on</strong> <str<strong>on</strong>g>and</str<strong>on</strong>g> scattered illuminati<strong>on</strong> <str<strong>on</strong>g>of</str<strong>on</strong>g>f <str<strong>on</strong>g>of</str<strong>on</strong>g><br />

the surface <str<strong>on</strong>g>of</str<strong>on</strong>g> the wings, which c<strong>on</strong>tributes to the translucency effect. The halfway vector<br />

will be used for generati<strong>on</strong> <str<strong>on</strong>g>of</str<strong>on</strong>g> glossy highlights <strong>on</strong> the wings’ surface. In the vertex<br />

shader, however, these vectors will simply be transformed to tangent space.<br />

struct VS_OUTPUT<br />

{<br />

float4 Pos : POSITION;<br />

float2 Tex : TEXCOORD0;<br />

float3 View : TEXCOORD1;<br />

float3 Light : TEXCOORD2;<br />

float3 Half : TEXCOORD3;<br />

};<br />

VS_OUTPUT main( float4 Pos : POSITION,<br />

float4 Normal : NORMAL0,<br />

float2 Tex : TEXCOORD0,<br />

float3 Tangent : TANGENT0,<br />

float3 Binormal : BINORMAL0 )<br />

{<br />

VS_OUTPUT Out = (VS_OUTPUT) 0;<br />

}<br />

// Output transformed vertex positi<strong>on</strong>:<br />

Out.Pos = mul( view_proj_matrix, Pos );<br />

// Propagate input texture coordinates:<br />

Out.Tex = Tex;<br />

// Compute the light vector (object space):<br />

float3 vLight = normalize( mul( inv_view_matrix, lightPos ) - Pos );<br />

// Define tangent space matrix:<br />

float3x3 mTangentSpace;<br />

mTangentSpace[0] = Tangent;<br />

mTangentSpace[1] = Binormal;<br />

mTangentSpace[2] = Normal;<br />

// Output light vector in tangent space:<br />

Out.Light = mul( mTangentSpace, vLight );<br />

// Compute the view vector (object space):<br />

float3 vView = normalize( view_positi<strong>on</strong> - Pos );<br />

// Output view vector in tangent space:<br />

Out.View = mul( mTangentSpace, vView );<br />

// Compute the half angle vector (in tangent space):<br />

Out.Half = mul( mTangentSpace, normalize( vView + vLight ) );<br />

return Out;<br />

3


Pixel Shader<br />

<str<strong>on</strong>g>Simulati<strong>on</strong></str<strong>on</strong>g> <str<strong>on</strong>g>of</str<strong>on</strong>g> <str<strong>on</strong>g>Iridescence</str<strong>on</strong>g> <str<strong>on</strong>g>and</str<strong>on</strong>g> <str<strong>on</strong>g>Translucency</str<strong>on</strong>g> <strong>on</strong> <strong>Thin</strong> <strong>Surfaces</strong><br />

The pixel shader computes the illuminati<strong>on</strong> value for a particular pixel <strong>on</strong> the<br />

surface <str<strong>on</strong>g>of</str<strong>on</strong>g> the butterfly wings taking into account the light propagated through the surface<br />

<str<strong>on</strong>g>of</str<strong>on</strong>g> the wings due to the translucency effect <str<strong>on</strong>g>and</str<strong>on</strong>g> light emitted due to the iridescence <str<strong>on</strong>g>of</str<strong>on</strong>g> the<br />

wings.<br />

First, we load the color value from a base texture map. For efficiency reas<strong>on</strong>s, we<br />

have stored the opacity in the alpha channel <str<strong>on</strong>g>of</str<strong>on</strong>g> the base texture map. We also load a<br />

normal vector (in tangent space) from precomputed normal map <str<strong>on</strong>g>and</str<strong>on</strong>g> a gloss value which<br />

will be used to modulate highlights <strong>on</strong> the surface <str<strong>on</strong>g>of</str<strong>on</strong>g> the wings. The scalar gloss map is<br />

stored in the alpha channel <str<strong>on</strong>g>of</str<strong>on</strong>g> the normal map. Combining three-channel texture maps<br />

with a single-channel grayscale value maps allows us to load two values with a single<br />

texture fetch.<br />

float3 vNormal, baseColor;<br />

float fGloss, fTransparency;<br />

// Load normal <str<strong>on</strong>g>and</str<strong>on</strong>g> gloss map:<br />

float4( vNormal, fGloss ) = tex2D( bump_glossMap, Tex );<br />

// Load base <str<strong>on</strong>g>and</str<strong>on</strong>g> opacity map:<br />

float4 (baseColor, fTransparency) = tex2D( base_opacityMap, Tex );<br />

D<strong>on</strong>’t forget to scale <str<strong>on</strong>g>and</str<strong>on</strong>g> bias the fetched normal map into the [-1.0, 1.0] range:<br />

// Signed scale the normal:<br />

vNormal = vNormal * 2 - 1;<br />

4


From ShaderX 2 – Shader Programming Tips <str<strong>on</strong>g>and</str<strong>on</strong>g> Tricks with DirectX 9<br />

Figure 2 displays the c<strong>on</strong>tents <str<strong>on</strong>g>of</str<strong>on</strong>g> the texture maps used for this effect:<br />

Base texture map for wings texture<br />

Normal map for bump mapping<br />

Figure 2 - Input Texture Maps<br />

Opacity texture map<br />

Gloss map<br />

The texture address mode should be set to CLAMP in u <str<strong>on</strong>g>and</str<strong>on</strong>g> v for both <str<strong>on</strong>g>of</str<strong>on</strong>g> these<br />

texture maps. Also they should be trilinearly filtered (MAGFILTER = linear,<br />

MINFILTER = linear, <str<strong>on</strong>g>and</str<strong>on</strong>g> MIPFILTER = anisotropic).<br />

<str<strong>on</strong>g>Translucency</str<strong>on</strong>g><br />

Next we will compute the translucency effect. The amount <str<strong>on</strong>g>of</str<strong>on</strong>g> light scattered<br />

through a thin surface is proporti<strong>on</strong>al to the incident angle <str<strong>on</strong>g>of</str<strong>on</strong>g> the light <strong>on</strong> the back side.<br />

So, similar to a Lambertian diffuse calculati<strong>on</strong>, we dot the light vector but with the<br />

negative <str<strong>on</strong>g>of</str<strong>on</strong>g> the normal vector. We also use a pre-specified translucency coefficient in<br />

additi<strong>on</strong> to the fetched opacity value to c<strong>on</strong>trol the amount <str<strong>on</strong>g>of</str<strong>on</strong>g> scattered light:<br />

float3 scatteredIlluminati<strong>on</strong> = saturate(dot(-vNormal, Light)) *<br />

fTransparency * translucencyCoeff;<br />

5


<str<strong>on</strong>g>Simulati<strong>on</strong></str<strong>on</strong>g> <str<strong>on</strong>g>of</str<strong>on</strong>g> <str<strong>on</strong>g>Iridescence</str<strong>on</strong>g> <str<strong>on</strong>g>and</str<strong>on</strong>g> <str<strong>on</strong>g>Translucency</str<strong>on</strong>g> <strong>on</strong> <strong>Thin</strong> <strong>Surfaces</strong><br />

As described above, the scattered light c<strong>on</strong>tributi<strong>on</strong> is dependent <strong>on</strong> both the<br />

directi<strong>on</strong> <str<strong>on</strong>g>of</str<strong>on</strong>g> incident light as well as the surface normal for the pixel locati<strong>on</strong>. This<br />

c<strong>on</strong>tributi<strong>on</strong> to diffuse illuminati<strong>on</strong> <str<strong>on</strong>g>of</str<strong>on</strong>g> the wings surface is what accounts for their subtle<br />

glow. Figure 3 illustrates the c<strong>on</strong>tributi<strong>on</strong> <str<strong>on</strong>g>of</str<strong>on</strong>g> scattered reflected light <strong>on</strong> the surface <str<strong>on</strong>g>of</str<strong>on</strong>g> the<br />

wings. If you modify the pixel shader for this effect in RenderM<strong>on</strong>key workspace found<br />

<strong>on</strong> the CD in this book to output <strong>on</strong>ly the scattered light c<strong>on</strong>tributi<strong>on</strong>, you will be able to<br />

investigate how this c<strong>on</strong>tributi<strong>on</strong> changes as you rotate the model.<br />

To simulate varying thickness <str<strong>on</strong>g>of</str<strong>on</strong>g> scales <strong>on</strong> the surface <str<strong>on</strong>g>of</str<strong>on</strong>g> butterfly wings as well<br />

as within them, we use a normal map to perturb the normal vectors. The usual diffuse<br />

illuminati<strong>on</strong> is computed with a simple dot product <str<strong>on</strong>g>and</str<strong>on</strong>g> a global ambient term:<br />

float3 diffuseC<strong>on</strong>tributi<strong>on</strong> = saturate(dot(vNormal,Light)) +<br />

ambient;<br />

Figure 3 below shows the result <str<strong>on</strong>g>of</str<strong>on</strong>g> computing diffusely reflected light for the butterfly<br />

wings.<br />

Scattered light c<strong>on</strong>tributi<strong>on</strong><br />

Figure 3 - Diffuse Illuminati<strong>on</strong><br />

Diffuse term<br />

In the next step we combine the base texture map with the diffuse term <str<strong>on</strong>g>and</str<strong>on</strong>g> the<br />

scattered reflected light c<strong>on</strong>tributi<strong>on</strong> to compute final value for diffuse surface<br />

illuminati<strong>on</strong>:<br />

baseColor *= scatteredIlluminati<strong>on</strong> + diffuseC<strong>on</strong>tributi<strong>on</strong>;<br />

Figure 4 illustrates the results <str<strong>on</strong>g>of</str<strong>on</strong>g> this operati<strong>on</strong>. Now we can notice how scattered<br />

reflected light c<strong>on</strong>tributes to the translucency effect <str<strong>on</strong>g>of</str<strong>on</strong>g> the butterfly wings in the more<br />

illuminated porti<strong>on</strong>s <str<strong>on</strong>g>of</str<strong>on</strong>g> wings in the final picture in Figure 4.<br />

6


From ShaderX 2 – Shader Programming Tips <str<strong>on</strong>g>and</str<strong>on</strong>g> Tricks<br />

with DirectX 9<br />

+<br />

* =<br />

Figure 4 - Combining the base texture map with scattered reflected light <str<strong>on</strong>g>and</str<strong>on</strong>g> diffusely<br />

Since butterfly wings in nature have varying transparency, we had our artists paint<br />

in the appropriate opacity values. However, since the desired effect has transparent<br />

geometry which also has specular highlights, we must take care when doing blending to<br />

achieve transparency properly. Typically, blending transparent materials is d<strong>on</strong>e during<br />

the blending stage <str<strong>on</strong>g>of</str<strong>on</strong>g> the rendering pipeline. However, if the object that you are rendering<br />

as transparent is a specular surface, blending should be d<strong>on</strong>e before actually applying<br />

specular highlights to the surface. A brute force approach for this would be to render two<br />

separate passes: diffuse alpha-blended pass first; <str<strong>on</strong>g>and</str<strong>on</strong>g> adding specular highlights in the<br />

sec<strong>on</strong>d pass. But to speed up our effect we wanted to do to it all in <strong>on</strong>e pass. This requires<br />

some tricks with the way alpha-blending is used. Since the specular pass is additive <str<strong>on</strong>g>and</str<strong>on</strong>g><br />

diffuse is blended, we want to pre-blend the diffuse color <str<strong>on</strong>g>and</str<strong>on</strong>g> add the specular color in<br />

the shader. Then during the blending stage the source color is not modified, it’s simply<br />

added since that porti<strong>on</strong> <str<strong>on</strong>g>of</str<strong>on</strong>g> the blending equati<strong>on</strong> is already taken care <str<strong>on</strong>g>of</str<strong>on</strong>g> in the shader<br />

code. The destinati<strong>on</strong> has the same blend as it normally would with the st<str<strong>on</strong>g>and</str<strong>on</strong>g>ard two-pass<br />

“brute force” approach. If we look at the blending equati<strong>on</strong>, the two pass approach would<br />

be expressed in the following form:<br />

Pass 1: diffuseIlluminati<strong>on</strong>Color * α+ destinati<strong>on</strong> * (1 – α)<br />

Pass 2: specularColor + destinati<strong>on</strong><br />

And the single pass approach can be expressed as follows:<br />

Pass 1: (diffuseIlluminati<strong>on</strong>Color * α + specularColor ) * 1+<br />

destinati<strong>on</strong> * (1 - α)<br />

7


<str<strong>on</strong>g>Simulati<strong>on</strong></str<strong>on</strong>g> <str<strong>on</strong>g>of</str<strong>on</strong>g> <str<strong>on</strong>g>Iridescence</str<strong>on</strong>g> <str<strong>on</strong>g>and</str<strong>on</strong>g> <str<strong>on</strong>g>Translucency</str<strong>on</strong>g> <strong>on</strong> <strong>Thin</strong> <strong>Surfaces</strong><br />

Here’s the porti<strong>on</strong> <str<strong>on</strong>g>of</str<strong>on</strong>g> the shader that pre-multiplies the diffuse illuminati<strong>on</strong> result<br />

with the alpha:<br />

float fOpacity = 1 - fTransparency;<br />

// Premultiply alpha blend to avoid clamping:<br />

baseColor *= fOpacity;<br />

Figure 5 illustrates effect <str<strong>on</strong>g>of</str<strong>on</strong>g> this acti<strong>on</strong> <strong>on</strong> the diffuse illuminati<strong>on</strong> result.<br />

<str<strong>on</strong>g>Iridescence</str<strong>on</strong>g><br />

Figure 5 - Pre-multiplied alpha-blending<br />

One <str<strong>on</strong>g>of</str<strong>on</strong>g> the reas<strong>on</strong>s why butterflies are so captivating in nature is the iridescence<br />

<str<strong>on</strong>g>of</str<strong>on</strong>g> their wings. To simulate iridescent patterns <strong>on</strong> the surface <str<strong>on</strong>g>of</str<strong>on</strong>g> our simulated butterfly<br />

wings, we use an approach similar to the technique described in the “Bubble Shader”<br />

chapter in the original ShaderX book [Isidoro02]. <str<strong>on</strong>g>Iridescence</str<strong>on</strong>g> is a view dependent effect,<br />

so we will use the view vector which was computed in the vertex shader <str<strong>on</strong>g>and</str<strong>on</strong>g> interpolated<br />

across the polyg<strong>on</strong> in tangent space. We also use scale <str<strong>on</strong>g>and</str<strong>on</strong>g> bias coefficients to scale <str<strong>on</strong>g>and</str<strong>on</strong>g><br />

bias index to make iridescence change more quickly or slowly across the surface <str<strong>on</strong>g>of</str<strong>on</strong>g> the<br />

wings. You can explore the effects <str<strong>on</strong>g>of</str<strong>on</strong>g> these parameters by modifying the variables<br />

iridescence_speed_scale <str<strong>on</strong>g>and</str<strong>on</strong>g> iridescence_speed_bias in the HLSL Iridescent<br />

Butterfly.xml RenderM<strong>on</strong>key workspace.<br />

// Compute index into the iridescence gradient map,<br />

// which c<strong>on</strong>sists <str<strong>on</strong>g>of</str<strong>on</strong>g> N·V coefficients<br />

float fGradientIndex =<br />

dot( vNormal, View ) * iridescence_speed_scale +<br />

iridescence_speed_bias;<br />

// Load the iridescence value from the gradient map based <strong>on</strong> the<br />

// index we just computed above:<br />

float4 iridescence = tex1D( gradientMap, fGradientIndex );<br />

8


From ShaderX 2 – Shader Programming Tips <str<strong>on</strong>g>and</str<strong>on</strong>g> Tricks with DirectX 9<br />

This effect uses a 1D gradient texture map (Figure 6) for computing color-shifted<br />

iridescence values. This texture should have trilinear filtering enabled <str<strong>on</strong>g>and</str<strong>on</strong>g> MIRROR<br />

texture address mode selected for both u <str<strong>on</strong>g>and</str<strong>on</strong>g> v coordinates.<br />

Figure 6 - Gradient texture map<br />

Figure 7 illustrates the resulting iridescence value.<br />

Figure 7 - <str<strong>on</strong>g>Iridescence</str<strong>on</strong>g> <str<strong>on</strong>g>of</str<strong>on</strong>g> butterfly wings<br />

To add satiny highlights to the surface <str<strong>on</strong>g>of</str<strong>on</strong>g> the wings we use a gloss map generated<br />

by the artist. We compute the gloss value based <strong>on</strong> the result fetched from the gloss map<br />

<str<strong>on</strong>g>and</str<strong>on</strong>g> N·V for determining the placement <str<strong>on</strong>g>of</str<strong>on</strong>g> specular highlights. Finally we add the gloss<br />

c<strong>on</strong>tributi<strong>on</strong> to the previously compute diffuse illuminati<strong>on</strong> result to obtain the final<br />

result:<br />

// Compute the final color using this equati<strong>on</strong>:<br />

// N*H * Gloss * <str<strong>on</strong>g>Iridescence</str<strong>on</strong>g> + Diffuse<br />

float fGlossIndex = fGloss *<br />

( saturate( dot( vNormal, Half )) *<br />

gloss_scale + gloss_bias );<br />

baseColor += fGlossIndex * iridescence;<br />

Figure 8 shows the final color for the butterfly wings.<br />

9


<str<strong>on</strong>g>Simulati<strong>on</strong></str<strong>on</strong>g> <str<strong>on</strong>g>of</str<strong>on</strong>g> <str<strong>on</strong>g>Iridescence</str<strong>on</strong>g> <str<strong>on</strong>g>and</str<strong>on</strong>g> <str<strong>on</strong>g>Translucency</str<strong>on</strong>g> <strong>on</strong> <strong>Thin</strong> <strong>Surfaces</strong><br />

Figure 8 - Assembled final color<br />

To render the final effect correctly, we output the previously-computed scalar fOpacity<br />

in the alpha channel <str<strong>on</strong>g>of</str<strong>on</strong>g> our result:<br />

return float4( baseColor, fOpacity );<br />

Because <str<strong>on</strong>g>of</str<strong>on</strong>g> the premultiplicati<strong>on</strong> menti<strong>on</strong>ed earlier, this means that our alpha<br />

blend factors should be ONE for SRCBLEND render state <str<strong>on</strong>g>and</str<strong>on</strong>g> IVRSRCALPHA for<br />

DESTBLEND.<br />

Summary<br />

In this chapter we presented a technique for simulating translucency <str<strong>on</strong>g>and</str<strong>on</strong>g><br />

iridescence <strong>on</strong> thin surfaces such as butterfly wings. Our technique combines scattered<br />

reflected light with diffusely reflected light <str<strong>on</strong>g>and</str<strong>on</strong>g> a color-shifted iridescence value for a<br />

visually interesting final result. You can see this effect in the Chimp Demo in the ATI<br />

RADEON TM 9800 demo suite <strong>on</strong> the ATI website as shown in Figure 9.<br />

10


References<br />

From ShaderX 2 – Shader Programming Tips <str<strong>on</strong>g>and</str<strong>on</strong>g> Tricks with DirectX 9<br />

Figure 9 - A snapshot from the Chimp demo<br />

1. [Demers01] [digital] Texturing <str<strong>on</strong>g>and</str<strong>on</strong>g> Painting, Owen Demers, New Riders, 2001.<br />

2. [Isidoro02] “Bubble Shader”, J. Isidoro, D. Gosselin, ShaderX, 2002.<br />

3. [Vlachos02] “Textures as Lookup Tables for Per-Pixel Lighting Computati<strong>on</strong>s”,<br />

A. Vlachos, J. Isidoro, C. Oat, Game Programming Gems III, 2002.<br />

4. [Jensen01] “A Practical Model for Subsurface Light Transport”, H.W. Jensen,<br />

S.R.Marschner, M. Levoy, P. Hanrahan, Proceedings <str<strong>on</strong>g>of</str<strong>on</strong>g> SIGGRAPH 2001.<br />

11

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!