#include "Shader.h" #include "Services.h" #include "Renderer.h" #include "Camera.h" #include "ModelEntity.h" #include #include using namespace std; /*---------------------------------------------------- * Default Constructor *----------------------------------------------------*/ Shader::Shader() : Resource("null", "null") { } /*---------------------------------------------------- * Constructor * @name - file name of the .fx file * @path - path to the file *----------------------------------------------------*/ Shader::Shader(const std::string &name, const std::string &path) : Resource(name, path) { LoadEffectFile(); } /*---------------------------------------------------- * Release the effect *----------------------------------------------------*/ Shader::~Shader() { mEffect = 0; } /*---------------------------------------------------- * Begin the shader *----------------------------------------------------*/ unsigned int Shader::Begin() { static unsigned int numPasses = 0; HR(mEffect->Begin(&numPasses, 0)); return numPasses; } /*---------------------------------------------------- * Begin the current pass *----------------------------------------------------*/ void Shader::BeginPass(int i) { HR(mEffect->BeginPass(i)); } /*---------------------------------------------------- * End the pass *----------------------------------------------------*/ void Shader::EndPass() { HR(mEffect->EndPass()); } /*---------------------------------------------------- * End the shader effect *----------------------------------------------------*/ void Shader::End() { HR(mEffect->End()); } /*---------------------------------------------------- * Perform any updating and commit *----------------------------------------------------*/ void Shader::Update(float dt) { HR(mEffect->CommitChanges()); } /*---------------------------------------------------- * Add a light to the list of lights that effect this * shader. *----------------------------------------------------*/ void Shader::AddLight(const D3DLIGHT9& light) { if(mLights.size() == Shader::MaxNumberOfLights) return; mLights.push_back(light); } /*---------------------------------------------------- * Set the light values on the shader *----------------------------------------------------*/ void Shader::ApplyLights() { //set the lights on the shader stringstream param; for(int i = 0; i < mLights.size(); i++) { param.str(""); param << "Light[" << i << "]"; //determine the type of light to set switch(mLights[i].Type) { case D3DLIGHT_DIRECTIONAL: { DirectionalLight light = (DirectionalLight)mLights[i]; HR(mEffect->SetValue(param.str().c_str(), &light, sizeof(DirectionalLight))); break; } case D3DLIGHT_POINT: { PointLight light = (PointLight)mLights[i]; HR(mEffect->SetValue(param.str().c_str(), &light, sizeof(PointLight))); break; } case D3DLIGHT_SPOT: { SpotLight light = (SpotLight)mLights[i]; HR(mEffect->SetValue(param.str().c_str(), &light, sizeof(SpotLight))); break; } default: break; } } } /*---------------------------------------------------- * Set the material *----------------------------------------------------*/ void Shader::SetMtrl(const D3DMATERIAL9& mtrl) { HR(mEffect->SetValue(mHMtrl, &mtrl, sizeof(D3DMATERIAL9))); } /*---------------------------------------------------- * Set the texture *----------------------------------------------------*/ void Shader::SetTexture(IDirect3DTexture9Ptr texture) { HR(mEffect->SetTexture(mHTexture, texture)); } /*---------------------------------------------------- * Load an effect file *----------------------------------------------------*/ void Shader::LoadEffectFile() { RendererPtr renderer = boost::static_pointer_cast(Services::GetService(RendererService)); //check to see if we're given a .fx or .cfx file ID3DXBuffer* errors = 0; HR(D3DXCreateEffectFromFile(renderer->GetDevice(), GetFileName().c_str(), 0, 0, D3DXSHADER_DEBUG, 0, &mEffect, &errors)); if( errors ) MessageBox(0, (char*)errors->GetBufferPointer(), 0, 0); // Obtain handles. mHTech = mEffect->GetTechnique(0); mHTech = mEffect->GetTechniqueByName("Phong"); mHWorld = mEffect->GetParameterByName(0, "World"); mHWorldViewProj = mEffect->GetParameterByName(0, "WorldViewProj"); mHWorldInvTrans = mEffect->GetParameterByName(0, "WorldInvTrans"); mHMtrl = mEffect->GetParameterByName(0, "Mtrl"); mHLight = mEffect->GetParameterByName(0, "Light"); mHTexture = mEffect->GetParameterByName(0, "Texture"); // Set parameters that do not vary: HR(mEffect->SetTechnique(mHTech)); } /*---------------------------------------------------- * Set the shader values that won't change with every pass *----------------------------------------------------*/ void SetDefaultShaderValues(ShaderPtr& shader, ModelEntity* mesh) { CameraPtr cam = boost::static_pointer_cast(Services::GetService(RendererService))->GetCamera(); ID3DXEffectPtr effect = shader->GetEffect(); D3DXMATRIX wvp; D3DXMatrixIdentity(&wvp); wvp = mesh->GetWorld() * cam->ViewProj(); D3DXMATRIX worldInvTrans; D3DXMatrixInverse(&worldInvTrans, NULL, &mesh->GetWorld()); D3DXMatrixTranspose(&worldInvTrans, &worldInvTrans); HR(effect->SetMatrix("World", &mesh->GetWorld())); HR(effect->SetMatrix("WorldViewProj", &wvp)); HR(effect->SetMatrix("WorldInvTrans", &worldInvTrans)); }