Spotlights
A spotlight is a combination of a directional light and point light. There is a coordinate position in the world space, but the light shines only in a particular direction. In addition, spotlight, like Point Light, is also attenuated by distance, but spotlight also decays around the original direction of light. You can think of spotlight as a virtual flashlight, forming a focus beam (focused beam) decays as the light is farther away from the center of the light.
Simulating a spotlight requires a coordinate position, direction, radiation radius, color and intensity, and floating-point values that describe the inner and outer angles of the focus beam radiation range. The elements are described in Figure 7.4.
Figure 7.4 An illustration of a spotlight.
Listing 7.3 lists a simple spotlight effect code. As before, copy the code into the nvidia FX composer. The code will be explained in detail next.
List 7.3 spotlight.fx
#include "include\\common.fxh"/************* resources *************/cbuffer cbufferperframe {float4 Ambientcolor:
Ambient < string uiname = "Ambient Light";
String uiwidget = "Color";
> = {1.0f, 1.0f, 1.0f, 0.0f};
FLOAT4 Lightcolor:color < string Object = "LightColor0";
String uiname = "Spot Light Color";
String uiwidget = "Color";
> = {1.0f, 1.0f, 1.0f, 1.0f};
FLOAT3 Lightposition:position < string Object = "SpotLightPosition0";
String uiname = "Spot Light Position";
String space = "the World";
> = {0.0f, 0.0f, 0.0f};
FLOAT3 Lightlookat:direction < string Object = "SpotLightDirection0";
String uiname = "Spot Light Direction";
String space = "the World";
> = {0.0f, 0.0f, -1.0f};
Float Lightradius < String uiname = "Spot Light Radius";
String uiwidget = "Slider";
float uimin = 0.0;
float Uimax = 100.0;
float Uistep = 1.0;
> = {10.0f}; Float Spotlightinnerangle < String uiname = "Spot Light InnEr Angle ";
String uiwidget = "Slider";
float uimin = 0.5;
float Uimax = 1.0;
float uistep = 0.01;
> = {0.75f};
Float Spotlightouterangle < String uiname = "Spot Light Outer Angle";
String uiwidget = "Slider";
float uimin = 0.0;
float Uimax = 0.5;
float uistep = 0.01;
> = {0.25f}; FLOAT3 Cameraposition:cameraposition < string uiwidget= "None";
>;
} cbuffer cbufferperobject {float4x4 worldviewprojection:worldviewprojection < string uiwidget= ' None '; >; float4x4 World:world < string uiwidget= "None";
>;
FLOAT4 Specularcolor:specular < string uiname = "Specular Color";
String uiwidget = "Color";
> = {1.0f, 1.0f, 1.0f, 1.0f};
Float Specularpower:specularpower < String uiname = "specular power";
String uiwidget = "Slider";
float Uimin = 1.0;
float Uimax = 255.0;
float Uistep = 1.0;
> = {25.0f};
} texture2d colortexture < string resourcename = "Default_color.dds"; String uiname = "Color TExture ";
String resourcetype = "2D";
>;
Samplerstate Colorsampler {Filter = min_mag_mip_linear;
Addressu = WRAP;
ADDRESSV = WRAP;
};
Rasterizerstate disableculling {cullmode = NONE;
/************* Data Structures *************/struct Vs_input {float4 objectposition:position;
FLOAT2 Texturecoordinate:texcoord;
FLOAT3 Normal:normal;
};
struct Vs_output {float4 position:sv_position;
FLOAT3 Normal:normal;
FLOAT2 texturecoordinate:texcoord0;
FLOAT3 Worldposition:texcoord1;
float Attenuation:texcoord2;
FLOAT3 Lightlookat:texcoord3;
};
/************* Vertex Shader *************/vs_output vertex_shader (vs_input in) {vs_output out = (vs_output) 0; Out. Position = Mul (in.
Objectposition, worldviewprojection); Out. Worldposition = Mul (in.
Objectposition, World). XYZ; Out. Texturecoordinate = Get_corrected_texture_coordinate (in.
Texturecoordinate); Out. Normal = Normalize (Mul (FLOAT4) (in.
Normal, 0), world). xyz); FLOAT3 lightdirection = LightpoSition-out.
Worldposition; Out.
Attenuation = Saturate (1.0f-length (lightdirection)/Lightradius); Out.
Lightlookat =-lightlookat;
return out;
/************* Pixel Shader *************/float4 pixel_shader (vs_output in): sv_target {float4 out = (float4) 0; FLOAT3 lightdirection = Normalize (lightposition-in.
Worldposition); FLOAT3 viewdirection = Normalize (cameraposition-in.
Worldposition); FLOAT3 normal = normalize (in.
Normal);
float n_dot_l = dot (normal, lightdirection);
FLOAT3 Halfvector = normalize (lightdirection + viewdirection);
float N_dot_h = dot (normal, halfvector); FLOAT3 Lightlookat = Normalize (in.
Lightlookat); FLOAT4 color = colortexture.sample (Colorsampler, in.
Texturecoordinate);
Float4 lightcoefficients = Lit (n_dot_l, n_dot_h, specularpower);
FLOAT3 ambient = get_vector_color_contribution (Ambientcolor, COLOR.RGB); FLOAT3 diffuse = get_vector_color_contribution (Lightcolor, LIGHTCOEFFICIENTS.Y * color.rgb) * in.
attenuation; FLOAT3 SPEcular = Get_scalar_color_contribution (Specularcolor, Min (lightcoefficients.z, COLOR.W)) * in.
attenuation;
float spotfactor = 0.0f;
float Lightangle = dot (Lightlookat, lightdirection);
if (Lightangle > 0.0f) {spotfactor = Smoothstep (Spotlightouterangle, Spotlightinnerangle, Lightangle);
} Out.rgb = ambient + (Spotfactor * (diffuse + specular));
OUT.A = 1.0f;
return out; }/************* Techniques *************/technique10 Main10 {pass P0 {SetVertexShader (Compileshader, Vs_4_0
Ex_shader ()));
Setgeometryshader (NULL);
SetPixelShader (Compileshader (Ps_4_0, Pixel_shader ()));
Setrasterizerstate (disableculling);
}
}