Spotlight.cpp
=============================================================================//Spotlight.cpp by Frank Luna (C)
2005 All rights Reserved.
Demonstrates an animated spotlight. Controls:use Mouse to orbit and zoom;
Use the ' W ' and ' S ' keys to//alter the height of the camera.
Use ' G ' and ' H ' to decrease and increase the spotlight cone,//respectively. ============================================================================= #include "d3dApp.h" #include " DirectInput.h "#include <crtdbg.h> #include" GfxStats.h "#include <list> #include" Vertex.h "class Spotlight Demo:public D3dapp {public:spotlightdemo (hinstance hinstance, std::string wincaption, D3DDEVTYPE devType, DWORD reque
STEDVP);
~spotlightdemo ();
BOOL Checkdevicecaps ();
void Onlostdevice ();
void Onresetdevice ();
void Updatescene (float dt);
void Drawscene ();
Helper methods void Buildgeobuffers ();
void Buildfx ();
void Buildviewmtx (); void BUILDPROJMTX ();
void DrawGrid ();
void Drawcylinders ();
void Drawspheres ();
Private:gfxstats* Mgfxstats;
DWORD mnumgridvertices;
DWORD Mnumgridtriangles;
id3dxmesh* Mcylinder;
id3dxmesh* Msphere;
idirect3dvertexbuffer9* MVB;
idirect3dindexbuffer9* MIB;
id3dxeffect* MFX;
D3dxhandle Mhtech;
D3dxhandle MHWVP;
D3dxhandle Mhworldinvtrans;
D3dxhandle Mhambientlight;
D3dxhandle Mhdiffuselight;
D3dxhandle Mhspeclight;
D3dxhandle MHLIGHTPOSW;
D3dxhandle MHLIGHTDIRW;
D3dxhandle mhAttenuation012;
D3dxhandle Mhspotpower;
D3dxhandle Mhambientmtrl;
D3dxhandle Mhdiffusemtrl;
D3dxhandle Mhspecmtrl;
D3dxhandle Mhspecpower;
D3dxhandle Mheyepos;
D3dxhandle Mhworld;
D3dxcolor Mambientlight;
D3dxcolor Mdiffuselight;
D3dxcolor Mspeclight;
D3dxvector3 mAttenuation012;
float Mspotpower;
Mtrl Mgridmtrl;
Mtrl Mcylindermtrl;
Mtrl Mspheremtrl;
float Mcamerarotationy;
float Mcameraradius;
float Mcameraheight; D3dxmatrix MvieW
D3dxmatrix mProj;
}; int WINAPI WinMain (hinstance hinstance, hinstance previnstance, PSTR cmdline, int showcmd) {//Enable run-time Me
Mory Check for debug builds. #if defined (DEBUG) |
Defined (_DEBUG) _crtsetdbgflag (_CRTDBG_ALLOC_MEM_DF | _crtdbg_leak_check_df);
#endif Spotlightdemo app (hinstance, "Spotlight Demo", D3ddevtype_hal, d3dcreate_hardware_vertexprocessing);
Gd3dapp = &app; DirectInput di (discl_nonexclusive| Discl_foreground, discl_nonexclusive|
Discl_foreground);
Gdinput = &di;
return Gd3dapp->run (); } spotlightdemo::spotlightdemo (HInstance hinstance, std::string wincaption, D3ddevtype devType, DWORD RequestedVP): D3D APP (HInstance, Wincaption, Devtype, REQUESTEDVP) {if (!checkdevicecaps ()) {MessageBox (0, "checkdevicecaps () Failed",
0, 0);
PostQuitMessage (0);
} mgfxstats = new Gfxstats ();
Mcameraradius = 50.0f;
Mcamerarotationy = 1.2 * D3DX_PI;
Mcameraheight = 20.0f;
Mambientlight = 0.4f*white; Mdiffuselight = white;
Mspeclight = white;
mAttenuation012 = D3dxvector3 (1.0f, 0.0f, 0.0f);
Mspotpower = 16.0f;
Mgridmtrl = Mtrl (blue, blue, white, 16.0f);
Mcylindermtrl = Mtrl (red, red, white, 8.0f);
Mspheremtrl = Mtrl (green, green, White, 8.0f);
HR (D3dxcreatecylinder (Gd3ddevice, 1.0f, 1.0f, 6.0f, &mcylinder, 0));
HR (D3dxcreatesphere (Gd3ddevice, 1.0f, &msphere, 0));
Buildgeobuffers ();
BUILDFX ();
If you are on the drawcylinders and Drawspheres functions, you see//that we draw the cylinders and spheres.
int numcylverts = mcylinder->getnumvertices () * 14;
int numsphereverts = msphere->getnumvertices () * 14;
int numcyltris = mcylinder->getnumfaces () * 14;
int numspheretris = msphere->getnumfaces () * 14;
Mgfxstats->addvertices (mnumgridvertices);
Mgfxstats->addvertices (Numcylverts);
Mgfxstats->addvertices (Numsphereverts);
Mgfxstats->addtriangles (Mnumgridtriangles); Mgfxstats->addtrianglES (Numcyltris);
Mgfxstats->addtriangles (Numspheretris);
Onresetdevice ();
Initallvertexdeclarations ();
} spotlightdemo::~spotlightdemo () {delete mgfxstats;
Releasecom (MVB);
Releasecom (MIB);
Releasecom (MFX);
Releasecom (Mcylinder);
Releasecom (Msphere);
Destroyallvertexdeclarations ();
} bool Spotlightdemo::checkdevicecaps () {D3DCAPS9 caps;
HR (Gd3ddevice->getdevicecaps (&caps));
Check for vertex shader version 2.0 support. if (Caps.
Vertexshaderversion < D3dvs_version (2, 0)) return false;
Check for pixel shader version 2.0 support. if (Caps.
Pixelshaderversion < D3dps_version (2, 0)) return false;
return true;
} void Spotlightdemo::onlostdevice () {mgfxstats->onlostdevice ();
HR (Mfx->onlostdevice ());
} void Spotlightdemo::onresetdevice () {mgfxstats->onresetdevice ();
HR (Mfx->onresetdevice ()); The aspect ratio depends on the backbuffer dimensions, which can//possibly change after a reset. So rebuild the projection Matrix.
BUILDPROJMTX ();
} void Spotlightdemo::updatescene (float dt) {mgfxstats->update (dt);
Get snapshot of input devices.
Gdinput->poll ();
Check input.
if (Gdinput->keydown (dik_w)) Mcameraheight + = 25.0f * DT;
if (Gdinput->keydown (dik_s)) Mcameraheight-= 25.0f * DT;
Divide to make mouse less sensitive.
Mcamerarotationy + = Gdinput->mousedx ()/100.0f;
Mcameraradius + = Gdinput->mousedy ()/25.0f; If we rotate over degrees, just roll back to 0 if (FABSF (mcamerarotationy) >= 2.0f * d3dx_pi) Mcamerarotati
OnY = 0.0f;
Don ' t let radius get too small.
if (Mcameraradius < 5.0f) Mcameraradius = 5.0f;
Control Spotlight Cone.
if (Gdinput->keydown (dik_g)) Mspotpower + = 25.0f * DT;
if (Gdinput->keydown (dik_h)) Mspotpower-= 25.0f * DT;
Clamp spot Power.
if (Mspotpower < 1.0f) Mspotpower = 1.0f;
if (Mspotpower > 64.0f) mspotpower = 64.0f; The camera Position/orieNtation relative to World space can//change every frame based on input, so we need to rebuild the//view matrix ever
Y frame with the latest changes.
BUILDVIEWMTX ();
} void Spotlightdemo::d rawscene () {//Clear the Backbuffer and depth buffer. HR (gd3ddevice->clear (0, 0, d3dclear_target |
D3dclear_zbuffer, 0xFFFFFFFF, 1.0f, 0));
HR (Gd3ddevice->beginscene ());
Setup the rendering FX HR (Mfx->setvalue (mhambientlight, &mambientlight, sizeof (D3DXCOLOR)));
HR (Mfx->setvalue (mhdiffuselight, &mdiffuselight, sizeof (D3DXCOLOR)));
HR (Mfx->setvalue (mhspeclight, &mspeclight, sizeof (D3DXCOLOR)));
HR (Mfx->setvalue (mhAttenuation012, &mattenuation012, sizeof (D3DXVECTOR3)));
HR (Mfx->setfloat (Mhspotpower, mspotpower));
Begin passes.
UINT numpasses = 0;
HR (Mfx->begin (&numpasses, 0));
for (UINT i = 0; i < numpasses; ++i) {HR (Mfx->beginpass (i));
DrawGrid ();
Drawcylinders ();
Drawspheres ();
HR (Mfx->endpass ()); } HR (Mfx->end ());
Mgfxstats->display ();
HR (Gd3ddevice->endscene ());
Present the Backbuffer.
HR (gd3ddevice->present (0, 0, 0, 0));
} void Spotlightdemo::buildgeobuffers () {std::vector<d3dxvector3> verts;
Std::vector<dword> indices;
Gentrigrid (1.0f, 1.0f, D3dxvector3 (0.0f, 0.0f, 0.0f), Verts, indices);
Save vertex count and triangle count for drawindexedprimitive arguments.
Mnumgridvertices = 100*100;
Mnumgridtriangles = 99*99*2;
Obtain a pointer to a new vertex buffer. HR (Gd3ddevice->createvertexbuffer (mnumgridvertices * sizeof (VERTEXPN), d3dusage_writeonly, 0, D3DPOOL_MANAGED, &
AMP;MVB, 0));
Now lock it to obtain a pointer to its internal data, and write the//grid ' s vertex data.
Vertexpn* v = 0;
HR (mvb->lock (0, 0, (void**) &v, 0));
for (DWORD i = 0; i < mnumgridvertices; ++i) {v[i].pos = verts[i];
V[i].normal = D3dxvector3 (0.0f, 1.0f, 0.0f);
} HR (Mvb->unlock ()); Obtain a pointerTo a new index buffer. HR (Gd3ddevice->createindexbuffer (mnumgridtriangles*3*sizeof (WORD), d3dusage_writeonly, D3DFMT_INDEX16, D3DPOOL
_managed, &mib, 0));
Now lock IT-obtain a pointer to its internal data, and write the//grid's index data.
word* k = 0;
HR (mib->lock (0, 0, (void**) &k, 0));
for (DWORD i = 0; i < mnumgridtriangles*3; ++i) k[i] = (WORD) indices[i];
HR (Mib->unlock ());
} void Spotlightdemo::buildfx () {//Create the FX from a. fx file.
id3dxbuffer* errors = 0;
HR (D3dxcreateeffectfromfile (Gd3ddevice, "spotlight.fx", 0, 0, d3dxshader_debug, 0, &mfx, &errors));
if (errors) MessageBox (0, (char*) errors->getbufferpointer (), 0, 0);
Obtain handles.
Mhtech = Mfx->gettechniquebyname ("Spotlighttech");
MHWVP = mfx->getparameterbyname (0, "GWVP");
Mhworldinvtrans = mfx->getparameterbyname (0, "Gworldinvtrans");
Mheyepos = mfx->getparameterbyname (0, "GEYEPOSW"); Mhworld= Mfx->getparameterbyname (0, "Gworld");
Mhambientlight = mfx->getparameterbyname (0, "gambientlight");
Mhdiffuselight = mfx->getparameterbyname (0, "gdiffuselight");
Mhspeclight = mfx->getparameterbyname (0, "gspeclight");
MHLIGHTPOSW = mfx->getparameterbyname (0, "GLIGHTPOSW");
MHLIGHTDIRW = mfx->getparameterbyname (0, "GLIGHTDIRW");
mhAttenuation012 = mfx->getparameterbyname (0, "gAttenuation012");
Mhambientmtrl = mfx->getparameterbyname (0, "Gambientmtrl");
Mhdiffusemtrl = mfx->getparameterbyname (0, "Gdiffusemtrl");
Mhspecmtrl = mfx->getparameterbyname (0, "Gspecmtrl");
Mhspecpower = mfx->getparameterbyname (0, "Gspecpower");
Mhspotpower = mfx->getparameterbyname (0, "Gspotpower");
} void Spotlightdemo::buildviewmtx () {Float x = Mcameraradius * COSF (Mcamerarotationy);
float z = Mcameraradius * Sinf (Mcamerarotationy);
D3dxvector3 POS (x, Mcameraheight, z);
D3dxvector3 Target (0.0f, 0.0f, 0.0f); D3dxvecTOR3 up (0.0f, 1.0f, 0.0f);
D3DXMATRIXLOOKATLH (&mview, &pos, &target, &up);
HR (Mfx->setvalue (Mheyepos, &pos, sizeof (D3DXVECTOR3)));
Spotlight position is the same as the camera position.
HR (Mfx->setvalue (MHLIGHTPOSW, &pos, sizeof (D3DXVECTOR3)));
Spotlight direction is the same as the camera forward direction.
D3dxvector3 lightdir = Target-pos;
D3dxvec3normalize (&lightdir, &lightdir);
HR (Mfx->setvalue (MHLIGHTDIRW, &lightdir, sizeof (D3DXVECTOR3)));
} void Spotlightdemo::buildprojmtx () {Float w = (float) md3dpp.backbufferwidth;
Float h = (float) md3dpp.backbufferheight;
D3DXMATRIXPERSPECTIVEFOVLH (&mproj, D3dx_pi * 0.25f, w/h, 1.0f, 5000.0f);
} void Spotlightdemo::d rawgrid () {HR (Gd3ddevice->setstreamsource (0, MVB, 0, sizeof (VERTEXPN)));
HR (Gd3ddevice->setindices (MIB));
HR (Gd3ddevice->setvertexdeclaration (vertexpn::D ecl));
D3dxmatrix W, WIT;
D3DXMatrixIdentity (&W); D3dxmatrixinverse (&wit, 0, &
W);
D3dxmatrixtranspose (&wit, &wit);
HR (Mfx->setmatrix (Mhworld, &w));
HR (Mfx->setmatrix (MHWVP, & (W*mview*mproj)));
HR (Mfx->setmatrix (Mhworldinvtrans, &wit));
HR (Mfx->setvalue (Mhambientmtrl, &mgridmtrl.ambient, sizeof (D3DXCOLOR)));
HR (Mfx->setvalue (Mhdiffusemtrl, &mgridmtrl.diffuse, sizeof (D3DXCOLOR)));
HR (Mfx->setvalue (Mhspecmtrl, &mgridmtrl.spec, sizeof (D3DXCOLOR)));
HR (Mfx->setfloat (Mhspecpower, mgridmtrl.specpower));
HR (Mfx->commitchanges ());
HR (gd3ddevice->drawindexedprimitive (d3dpt_trianglelist, 0, 0, mnumgridvertices, 0, mnumgridtriangles));
} void Spotlightdemo::d rawcylinders () {D3dxmatrix T, R, W, WIT;
D3dxmatrixrotationx (&r, d3dx_pi*0.5f);
HR (Mfx->setvalue (Mhambientmtrl, &mcylindermtrl.ambient, sizeof (D3DXCOLOR)));
HR (Mfx->setvalue (Mhdiffusemtrl, &mcylindermtrl.diffuse, sizeof (D3DXCOLOR)));
HR (Mfx->setvalue (Mhspecmtrl, &mcylindermtrl.spec, sizeof (D3DXCOLOR))); HR (mfx->SetFloat (Mhspecpower, mcylindermtrl.specpower));
for (int z = -30; z <=; z+=) {d3dxmatrixtranslation (&t, -10.0f, 3.0f, (float) z);
W = r*t;
D3dxmatrixinverse (&wit, 0, &w);
D3dxmatrixtranspose (&wit, &wit);
HR (Mfx->setmatrix (MHWVP, & (W*mview*mproj)));
HR (Mfx->setmatrix (Mhworld, &w));
HR (Mfx->setmatrix (Mhworldinvtrans, &wit));
HR (Mfx->commitchanges ());
HR (Mcylinder->drawsubset (0));
D3DXMatrixTranslation (&t, 10.0f, 3.0f, (float) z);
W = r*t;
D3dxmatrixinverse (&wit, 0, &w);
D3dxmatrixtranspose (&wit, &wit);
HR (Mfx->setmatrix (MHWVP, & (W*mview*mproj)));
HR (Mfx->setmatrix (Mhworld, &w));
HR (Mfx->setmatrix (Mhworldinvtrans, &wit));
HR (Mfx->commitchanges ());
HR (Mcylinder->drawsubset (0));
}} void Spotlightdemo::d rawspheres () {D3dxmatrix W, WIT;
HR (Mfx->setvalue (Mhambientmtrl, &mspheremtrl.ambient, sizeof (D3DXCOLOR))); HR (Mfx->setvalue (mhdiffuSemtrl, &mspheremtrl.diffuse, sizeof (D3DXCOLOR));
HR (Mfx->setvalue (Mhspecmtrl, &mspheremtrl.spec, sizeof (D3DXCOLOR)));
HR (Mfx->setfloat (Mhspecpower, mspheremtrl.specpower));
for (int z = -30; z <=; z+=) {d3dxmatrixtranslation (&w, -10.0f, 7.5f, (float) z);
D3dxmatrixinverse (&wit, 0, &w);
D3dxmatrixtranspose (&wit, &wit);
HR (Mfx->setmatrix (MHWVP, & (W*mview*mproj)));
HR (Mfx->setmatrix (Mhworld, &w));
HR (Mfx->setmatrix (Mhworldinvtrans, &wit));
HR (Mfx->commitchanges ());
HR (Msphere->drawsubset (0));
D3DXMatrixTranslation (&w, 10.0f, 7.5f, (float) z);
D3dxmatrixinverse (&wit, 0, &w);
D3dxmatrixtranspose (&wit, &wit);
HR (Mfx->setmatrix (MHWVP, & (W*mview*mproj)));
HR (Mfx->setmatrix (Mhworld, &w));
HR (Mfx->setmatrix (Mhworldinvtrans, &wit));
HR (Mfx->commitchanges ());
HR (Msphere->drawsubset (0)); }
}
Spotlight.fx
=============================================================================//Spotlight.fx by Frank Luna (C)
2004 All rights Reserved.
Does ambient, diffuse, and specular lighting with a spotlight source.
============================================================================= uniform extern float4x4 GWorld;
uniform extern float4x4 Gworldinvtrans;
uniform extern float4x4 GWVP;
uniform extern float3 GEYEPOSW;
uniform extern float4 Gambientmtrl;
uniform extern float4 Gdiffusemtrl;
uniform extern float4 Gspecmtrl;
uniform extern float gspecpower;
uniform extern float4 gambientlight;
uniform extern float4 gdiffuselight;
uniform extern float4 gspeclight;
uniform extern float3 GLIGHTPOSW;
uniform extern float3 GLIGHTDIRW;
uniform extern float3 gAttenuation012;
uniform extern float gspotpower;
struct Outputvs {float4 posh:position0;
FLOAT4 color:color0;
}; Outputvs Spotlightvs (float3 posl:position0, Float3 normall:normal0) {//Zero out OUR output.
Outputvs Outvs = (Outputvs) 0;
Transform normal to World space.
FLOAT3 NORMALW = Mul (Float4 (Normall, 0.0f), Gworldinvtrans). xyz;
NORMALW = normalize (NORMALW);
Transform vertex position to the world space.
FLOAT3 PosW = Mul (Float4 (POSL, 1.0f), Gworld). xyz;
Unit vector from vertex to light source.
FLOAT3 LIGHTVECW = normalize (GLIGHTPOSW-POSW);
Ambient light Computation.
FLOAT3 ambient = (gambientmtrl*gambientlight). RGB;
Diffuse light computation.
float s = max (dot (NORMALW, LIGHTVECW), 0.0f);
FLOAT3 diffuse = s* (gdiffusemtrl*gdiffuselight). RGB;
Specular light computation.
FLOAT3 Toeyew = normalize (GEYEPOSW-POSW);
FLOAT3 reflectw = Reflect (-LIGHTVECW, NORMALW);
float t = POW (max (dot (reflectw, Toeyew), 0.0f), gspecpower);
FLOAT3 spec = t* (gspecmtrl*gspeclight). RGB;
Attentuation.
float d = distance (GLIGHTPOSW, PosW);
Float A = gattenuation012.x + gattenuation012.y*d + gattenuation012.z*d*d;
Spotlight factor. Float SPOt = POW (max (dot (-LIGHTVECW, GLIGHTDIRW), 0.0f), gspotpower);
Everything together.
FLOAT3 color = spot* (ambient + (diffuse + spec)/A);
Pass on color and diffuse material alpha.
Outvs.color = FLOAT4 (color, GDIFFUSEMTRL.A);
Transform to homogeneous clip space.
Outvs.posh = Mul (Float4 (POSL, 1.0f), GWVP);
Done--return the output.
return Outvs;
} float4 Spotlightps (float4 c:color0): COLOR {return C;}
Technique Spotlighttech {Pass P0 {//Specify the vertex and pixel shader associated with this pass.
VertexShader = Compile vs_2_0 Spotlightvs ();
PixelShader = Compile ps_2_0 Spotlightps (); }
}