Add light in the scene-use HLSL to define the spotlight

Source: Internet
Author: User
Problem

The Point Light Source defined in the previous tutorial emits light in all directions from a point. You want to define a spotlight, which is very similar to a point light source, but the light only illuminates a cone area, 6-10.

Figure 6-10 define a spotlight variable

Solution

In pixel shader, determine whether the current pixel is in the Light cone. This can be done by performing dot multiplication in the light direction and the cone direction.

Working Principle

The initial code is the same as that in the previous tutorial. Because the spotlight has more things to set than the point light source, you need to add the following XNA-to-HLSL variables to the. fx file:

float xLightStrength; float3 xConeDirection; float xConeAngle; float xConeDecay; 

The first variable allows you to increase/decrease the illumination intensity. This variable is also useful for other types of light. It is also required when there are multiple light sources in the scenario (see tutorial 6-10 ). Then define the center line direction and width of the Light cone. Finally, it defines the attenuation of illumination.

In addition, you need to extend pixel shader. Basically, this is the same as the pixel-by-pixel light source (see tutorial 6-7). It only adds a step to check whether the pixel is in the cone:

SLPixelToFrame SLPixelShader(SLVertexToPixel PSIn) : COLOR0 {    SLPixelToFrame Output = (SLPixelToFrame)0;         float4 baseColor = float4(0,0,1,1);     float3 normal = normalize(PSIn.Normal);     float3 lightDirection = normalize(PSIn.LightDirection);     float coneDot = dot(lightDirection, normalize(xConeDirection));         float shading = 0;     if (coneDot > xConeAngle)     {        float coneAttenuation = pow(coneDot, xConeDecay);         shading = dot(normal, -lightDirection);         shading *= xLightStrength;         shading *= coneAttenuation;     }    Output.Color = baseColor*(shading+xAmbient);         return Output; }

After normalization of the normal and light direction, you need to check whether the current pixel is within the light cone. This can detect the angle between the two directions:

  • Current pixel to Light Source Direction
  • Direction of the center line of the optical cone

The first direction is lightDirection, and the second direction is defined by the xConeDirection variable. Pixels are illuminated only when the angle between the two directions is smaller than a critical value.

A quick method for detection is to calculate the point multiplication in these two directions. The result is close to 1, indicating that the angle between the two is very small. The smaller the result, the larger the angle.

To determine whether the angle is too large, you need to check whether the result of the dot multiplication is smaller than a critical value, which is stored in the ConeAngle variable. If the pixel is in the Light cone, the light factor is calculated. To reduce the illumination close to the edge of the cone, You need to calculate the xConeDecay power of the variable coneDot. As a result, for pixels that are far away from the center line of the optical cone, when the coneDot variable is less than or equal to 1, the power result will be smaller (see the right figure of Figure 6-11 ).

The pixel illumination value outside the light cone is 0, and the light has no effect on these pixels.

Code

The complete pixel shader code already exists.

In the Draw method of XNA code, enable effect, set parameters, and Draw the scenario:

effect.CurrentTechnique = effect.Techniques["SpotLight"]; effect.Parameters["xWorld"].SetValue(Matrix.Identity); effect.Parameters["xView"].SetValue(fpsCam.ViewMatrix); effect.Parameters["xProjection"].SetValue(fpsCam.ProjectionMatrix); effect.Parameters["xAmbient"].SetValue(0.2f); effect.Parameters["xLightPosition"].SetValue(new Vector3(5.0f, 2.0f, -15.0f+variation)); effect.Parameters["xConeDirection"].SetValue(new Vector3(0,-1,0)); effect.Parameters["xConeAngle"].SetValue(0.5f); effect.Parameters["xConeDecay"].SetValue(2.0f); effect.Parameters["xLightStrength"].SetValue(0.7f); effect.Begin(); foreach (EffectPass pass in effect.CurrentTechnique.Passes) {    pass.Begin();     device.VertexDeclaration = myVertexDeclaration;     device.DrawUserPrimitives<VertexPositionNormalTexture>(PrimitiveType.TriangleStrip,vertices, 0, 6);     pass.End(); }effect.End(); 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.