Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
HLSL Development Cookbook

You're reading from   HLSL Development Cookbook Implement stunning 3D rendering techniques using the power of HLSL and DirectX 11

Arrow left icon
Product type Paperback
Published in Jun 2013
Publisher Packt
ISBN-13 9781849694209
Length 224 pages
Edition 1st Edition
Tools
Arrow right icon
Author (1):
Arrow left icon
Doron Feinstein Doron Feinstein
Author Profile Icon Doron Feinstein
Doron Feinstein
Arrow right icon
View More author details
Toc

Spot light


Spot light is a light source that emits light from a given position in a cone shape that is rounded at its base. The following screenshot shows a spot light pointed at the bunny's head:

The cone shape of the spot light is perfect for representing flash lights, vehicle's front lights, and other lights that are focused in a specific direction.

Getting ready

In addition to all the values needed for point light sources, a spot light has a direction and two angles to represent its cone. The two cone angles split the cone into an inner cone, where light intensity is even, and an outer cone, where light attenuates if it gets closer to the cone's border. The following screenshot shows the spot light direction as D, the inner to outer cone angle as α, and the outer cone angle as θ:

Unlike the point light, where light intensity attenuates only over distance, spot lights intensity also attenuates across the angle α. When a light ray angle from the center is inside the range of α, the light gets dimmer; the dimmer the light, the closer the angle is to θ.

How to do it...

For the spot light calculation, we will need all the values used for point light sources plus the additional three values mentioned in the previous section. The following deceleration contains the previous and new values:

cbuffer SpotLightConstants : register( b0 )
{
  float3 SpotLightPos      : packoffset( c0 );
  float SpotLightRangeRcp  : packoffset( c0.w );
  float3 SpotLightDir      : packoffset( c1 );
  float SpotCosOuterCone   : packoffset( c1.w );
  float SpotInnerConeRcp   : packoffset( c2 );
}

Like the directional light's direction, the spot light's direction has to be normalized and inverted, so it would point to the light (just pass it to the shader, minus the light direction). The inverted direction is stored in the shader constant SpotLightDir.

Reciprocal range is stored in the shader constant SpotLightRangeRcp.

When picking the inner and outer cone angles, always make sure that the outer angle is bigger than the outer to inner angle. During the spot light calculation, we will be using the cosine of the inner and outer angles. Calculating the cosine values over and over for every lit pixel in the pixel shader is bad for performance. We avoid this overhead by calculating the cosine values on the CPU and passing them to the GPU. The two angle cosine values are stored in the shader constants SpotCosOuterCone and SpotCosInnerCone.

The code to calculate the spot light is very similar to the point light code:

float3 CalcSpot(float3 position, Material material)
{
   float3 ToLight = SpotLightPos - position;
   float3 ToEye = EyePosition.xyz - position;
   float DistToLight = length(ToLight);
   
   // Phong diffuse
   ToLight /= DistToLight; // Normalize
   float NDotL = saturate(dot(ToLight, material.normal));
   float3 finalColor = SpotColor.rgb * NDotL;
   
   // Blinn specular
   ToEye = normalize(ToEye);
   float3 HalfWay = normalize(ToEye + ToLight);
   float NDotH = saturate(dot(HalfWay, material.normal));
   finalColor += SpotColor.rgb * pow(NDotH, material.specExp) * material.specIntensity;
   
   // Cone attenuation
   float conAtt = saturate((cosAng - SpotCosOuterCone) * SpotCosInnerConeRcp);
   conAtt *= conAtt;
   
   // Attenuation
   float DistToLightNorm = 1.0 - saturate(DistToLight * SpotLightRangeRcp);
   float Attn = DistToLightNorm * DistToLightNorm;
   finalColor *= material.diffuseColor * Attn * conAtt;
   
   return finalColor;
}

As with the previous two light functions, this function takes the pixel's world position and material values, and outputs the pixel's lit color value.

How it works…

As with the previous light sources, the spot light is using the Blinn-Phong model. The only difference in the code is the cone attenuation, which gets combined with the distance attenuation. To account for the cone shape, we first have to find the angle between the pixel to light vector and the light vector. For that calculation we use the dot product and get the cosine of that angle. We then subtract the cosine of the outer cone angle from that value and end up with one of the three optional results:

  • If the result is higher than the cosine of the inner cone, we will get a value of 1 and the light affect will be fully on

  • If the result is lower than the cosine of the inner cone but higher than zero, the pixel is inside the attenuation range and the light will get dimmer based on the size of the angle

  • If the result is lower than zero, the pixel was outside the range of the outer cone and the light will not affect the pixel

You have been reading a chapter from
HLSL Development Cookbook
Published in: Jun 2013
Publisher: Packt
ISBN-13: 9781849694209
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime
Banner background image