Introduction
In the preceding, we have described the use of the parallel light source, the point light source, in addition to these two, there is a light source named Spotlight type. The spotlight, of course, is the light that gathers light in a certain range. Imagine the big stars on the stage in a much-anticipated venue. At the moment when he appeared, all the spotlights were focused on it ... Look at how big the spotlight is. Let's explain how to simulate spotlights.
Spotlight
In fact, the spotlight simulation is very simple, it is actually a range of point light. That is to say, we will be on the basis of the previous blog, the light equation of the point light source, increase the focus on the range of spotlight properties, to simulate the spotlight. So, the simulation of the spotlight is how to simulate the focus range.
To figure out how to simulate the focus range, we need to understand how the spotlight is focused.
First, the spotlight, like a point light source, should have a position pos, and here, unlike the point light, it should have a direction dir, which does not illuminate the light in all directions like a point light source. With the position, and the direction of irradiation, we can use the incident light of the vertex vector, and the spotlight on the direction of the point of the product operation, so as to find the angle between them, if the angle is within the scope of our specified focus, the irradiation.
Readers, may feel that this passage is very familiar. If you've seen a few of my previous blogs, you'll know how to simulate the focus area here. Yes, it is using the Cos cosine, and the exponential operation to simulate.
The following is the final formula for the irradiation equation:
The reader can find that this formula is just a little more than the previous part, and the latter part is exactly the same as the point light formula I described in my previous blog post. That is, we simulate the focus capability of the spotlight by using the formula in the previous section. where l refers to the light vector of the vertex, D is the direction of the spotlight, and S is the exponential variable of the control range, which is explained in the blog that tells reflected Light.
Instance parsing
Well, the theory is over. Below, we use the spotlight to make a simple demo.
Similarly, we use a teapot prototype to do it. We draw a teapot on the x-z plane so that when the spotlight gathers in a certain part, it can be seen clearly. Here is the code that draws a teapot:
void Cubedemo::d raw () {//set the vertex declaration HR (m_pdevice->setvertexdeclaration (VERTEXPN::_VERTEXDECL));
Set the Technique HR (M_peffect->settechnique (M_htechnique));
Set the gpower static float power = 128.0f;
HR (M_peffect->setvalue (m_gpower,&power,sizeof (float)));
Set the Gmaterial HR (M_peffect->setvector (M_gmaterial,&d3dxvector4 (0.0, 0.0, 1.0, 1.0)));
Set the Glightcolor HR (M_peffect->setvector (M_glightcolor, &d3dxvector4 (0.8, 0.8, 0.8, 1.0)));
Set the Glightpos HR (M_peffect->setvector (M_glightpos, &m_lightpos)); Set the Gspecularlightcolor HR (M_peffect->setvalue (M_gspecularlightcolor, &d3dxcolor (1.0,1.0,1.0,1.0),
sizeof (D3DXCOLOR)); Set the Gspecularmaterial HR (M_peffect->setvalue (m_gspecularmaterial, &d3dxcolor (1.0,1.0,1.0,1.0), sizeof (
(D3dxcolor))); Set the Gambientlightcolor HR (M_peffect->setvalue (M_gambientlightcolor, &d3dxcolor (0.1,0.0,0.1,0.0),
sizeof (D3DXCOLOR)); Set the Gambientmaterial HR (M_peffect->setvalue (m_gambientmaterial, &d3dxcolor (1.0,1.0,1.0,0.0), sizeof (
(D3dxcolor)));
Set the gA0 HR (M_peffect->setfloat (m_ga0, 0.0f));
Set the GA1 HR (M_peffect->setfloat (M_GA1, 0.0f));
Set the GA2 HR (M_peffect->setfloat (M_GA2, 0.005));
Set the Glightdir HR (M_peffect->setvalue (M_glightdir, &d3dxvector4 (0,-1, 0, 0), sizeof (D3DXVECTOR4)));
Set the Gspotrangepower HR (M_peffect->setfloat (M_gspotrangepower, 10.0f));
Begin Pass UINT _pass = 0;
HR (M_peffect->begin (&_pass, 0));
HR (M_peffect->beginpass (0));
Draw the Primitive Drawcube ();
End Pass HR (M_peffect->endpass ());
HR (M_peffect->end ()); }
void Cubedemo::d rawcube ()
{for
(int j = 0; J <; J + +)
{for
(int i = 0; i <; i + +)
{
//create the world matrix
d3dxmatrix _WORLDM;
D3DXMatrixIdentity (&_WORLDM);
D3DXMatrixTranslation (&_worldm,-20 + 4 * j,0,-20 + i * 4);
Set the GWVP matrix
d3dxhandle _HWVP = m_peffect->getparameterbyname (0, "GWVP");
HR (M_peffect->setmatrix (_HWVP, & (_worldm* m_viewmatrix* M_projmatrix));
Set the Gworld matrix
HR (M_peffect->setmatrix (M_gworld, &_WORLDM));
Set the Ginversetranspose
d3dxmatrixinverse (&_worldm,null, &_WORLDM);
D3dxmatrixtranspose (&_WORLDM, &_WORLDM);
HR (M_peffect->setmatrix (M_ginversetranspose, &_WORLDM));
HR (M_peffect->commitchanges ());
Draw the Teapot
HR (m_teaportmesh->drawsubset (0));
} End for
}//end for
}
Here is the shader file for this program:
---------------------------------------------------------------------------//Declaration:copyright (c), by XJ, 2014.
All right reserved.
Brief:this file would define the SpotLight shader. DATE:2014/5///----------------------------------------------------------------------------uniform float4x4 g WVP; This variable will save the world transform Matrix * Camera Transform Matrix * Perspective projection Matrix Product//Use this matrix, convert points into clipping space to uniform float4x4 ginversetranspose; This variable will save the inverse matrix of the world transformation matrix * Transpose matrix, used to transform the normal vector uniform float4 gmaterial; This variable is used to preserve the material properties of the vertex, in this demo, the same//material uniform FLOAT4 Glightcolor is used for all vertices; This variable will be used to save the color of a spotlight light uniform float3 glightpos; This variable is used to preserve the position of the spotlight light source uniform float4x4 gworld; This variable saves the world transformation, which is used to transform the coordinate of the model, thus calculating the uniform float4 Glightdir of the visual vector. This variable will save the spotlight's illumination direction uniform float gspotrangepower; This variable will save the size of the spotlight range uniform FLOAT3 Geye; This variable holds the position of the viewpoint, i.e. the position of the camera uniform float gpower; This variable will control the attenuation speed of the reflected light uniform float4 gspecularlightcolor; Reflected light color uniform float4 gspecularmateriAl The material property of object to reflected light is uniform float4 gambientlightcolor; Ambient light color uniform float4 gambientmaterial; object to ambient light material properties uniform float gA0; Decay parameter a0 uniform float gA1; Decay parameter A1 uniform float gA2;
Decay parameter a2//defines the input structure of vertex shading struct Outputvs {float4 posh:position0;
FLOAT4 color:color0;
};
Outputvs Spotvs (float3 posl:position0, Float3 normall:normal0) {//emptying Outputvs Outputvs Outputvs = (Outputvs) 0;
Transform the normal vector of the vertex normall = normalize (Normall);
FLOAT3 NORMALW = Mul (Float4 (Normall, 0.0f), ginversetranspose). xyz;
NORMALW = normalize (NORMALW);
Because it is a spotlight light, the light vectors for each vertex are different and need to be recalculated: float3 PosW = Mul (Float4 (POSL, 1.0), Gworld). xyz;
FLOAT3 Lightvec = GLIGHTPOS.XYZ-POSW;
Lightvec = normalize (Lightvec);
According to the diffuse reflection formula://Color = max (L * Normal, 0) * (lightcolor*material) Float s = max (dot (LIGHTVEC,NORMALW), 0);
FLOAT3 diffuse = s* (gmaterial*glightcolor). RGB; According to ambient light formula://Color = Ambientcolor * ambientmaterial float3 ambient = (gAmbientlightcolor * gambientmaterial). RGB;
According to the reflected light formula://Color = POW ((Max (dot (r,v), 0), p) * (specularlightcolor*specularmaterial) FLOAT3 view = GEYE-POSW;
View = normalize (view);
FLOAT3 ref = Reflect (-lightvec, NORMALW);
float t = POW (max (dot (Ref,view), 0), gpower);
FLOAT3 specular = t * (Gspecularlightcolor * gspecularmaterial). RGB; Calculates the decay value of the spotlight, according to the following formula://attenuation = POW ((Max (dot (dir, Lightvec), 0), spotpower) Float spot_attenuation = POW (max (dot (GL
Ightdir,-lightvec), 0), gspotrangepower);
The formula for calculating the decay value of diffuse and reflected light is as follows://attenuation = a0 + a1*d + a2*d*d Float dist = distance (Glightpos, PosW);
float attenuation = gA0 + ga1*dist + gA2 * dist * DIST;
Calculate the final color OutputVS.color.rgb = spot_attenuation * ((diffuse + specular)/attenuation + ambient);
OUTPUTVS.COLOR.A = GMATERIAL.A;
Use GWVP to convert world coordinates to clipping coordinates outputvs.posh = Mul (Float4 (POSL, 1.0f), GWVP);
Returns the result return Outputvs; }//End for Vertex Shader float4 Spotps (float4 c:color0): COLOR {return C;} End for PixEl Shader technique Spottech {pass P0 {vertexshader = compile vs_2_0 Spotvs ();
PixelShader = Compile ps_2_0 Spotps (); }
}
Finally, a screenshot of the program, run the program, you can press I, or K key to control the height of the spotlight, press A or D to control the position of the spotlight on the x-axis, use the mouse to control the scene magnification and zoom:
Well, it's over again today. The program instance has been uploaded and can be downloaded by itself.