Kyle Hayward's

Portfolio

GRFramework Code Samples

Description

The GRFramework is a simple framework that I have developed to use with Direct3D projects. There are raw pointer and smart pointer variants of the framework. The samples listed here are shown using boost::shared_ptr for user objects and com smart pointers (_com_ptr_t) for D3D objects. Four samples are provided: RenderTargetPool, ModelEntity, Mesh, and Shader.

RenderTargetPool.cpp , RenderTargetPool.h

RenderTargetPool is a helper class used to buffer render targets. All render targets are created through this class. RenderTargetPool will check to see if a requested render target already exists, if it does it will return the already created render target, else it will create a new render target. Also it also provides the ability to forcibly create a new render target even if it already exists. This helps reuse render targets and cut down on memory.

#include "RenderTargetPool.h"

#include "RenderTarget.h"
#include "Services.h"
#include "Renderer.h"

#include <string>
#include <iostream>

using namespace std;

//list of render targets
map<RenderTargetInfo, RTObject> RenderTargetPool::mRTPool;

IDirect3DDevice9Ptr RenderTargetPool::GDevice;
D3DVIEWPORT9 RenderTargetPool::Viewport;

RTObject::RTObject()
{
    RefCount = 0;
}
RTObject::~RTObject()
{
    //rt automatically deleted w/ shared_ptr
}

/*----------------------------------------------------
 * Initialize the rt pool
 *----------------------------------------------------*/
void RenderTargetPool::Initialize(IDirect3DDevice9Ptr &device, D3DVIEWPORT9& viewport)
{
    GDevice = device;
    Viewport = viewport;
}

/*----------------------------------------------------
 * Destroy all the render targets
 *----------------------------------------------------*/
void RenderTargetPool::DestroyRenderTargets()
{
    if(mRTPool.size() == 0)
        return;

    mRTPool.clear();
}

/*----------------------------------------------------
 * Notify render targets of lost device
 *----------------------------------------------------*/
void RenderTargetPool::OnLostDevice()
{
    static map<RenderTargetInfo, RTObject>::iterator iter;
    for( iter = mRTPool.begin(); iter != mRTPool.end(); ++iter ) 
    {
        iter->second.RT->OnLostDevice();
    }
}

/*----------------------------------------------------
 * Notify render targets of reset device
 *----------------------------------------------------*/
void RenderTargetPool::OnResetDevice()
{
    static map<RenderTargetInfo, RTObject>::iterator iter;
    for( iter = mRTPool.begin(); iter != mRTPool.end(); ++iter ) 
    {
        iter->second.RT->OnResetDevice();
    }
}

/*----------------------------------------------------
 * Retrieve a render target. If the render target
 * already exists this will update its ref count and
 * return the already existing render target. If the
 * render target doesn't exist it will create a new one
 * and return it.
 *
 * @info - the information about the rendertarget to get
 *           specifies: w + h, surface formats
 *
 * @return - A valid render target created with info
 *----------------------------------------------------*/
RenderTargetPtr RenderTargetPool::GetRenderTarget(RenderTargetInfo& info)
{
    //update the reference count
    static map<RenderTargetInfo, RTObject>::iterator iter;
    for( iter = mRTPool.begin(); iter != mRTPool.end(); ++iter ) 
    {
        if(iter->first == info)
        {
            iter->second.RefCount++;
            return iter->second.RT;
        }
    }

    //check for support for the render target
    RendererPtr renderer = boost::static_pointer_cast<Renderer>(Services::GetService(RendererService));
    if(GDevice == NULL && !IsFormatSupported(renderer->GetD3D(), 
                                             info.Format, 
                                             renderer->GetPresentParams().BackBufferFormat))
    {
        return RenderTargetPtr();
    }

    RTObject rtObject;
    rtObject.RefCount = 1;
    rtObject.RT = RenderTargetPtr(new RenderTarget(GDevice, Viewport, 
                                                    (UINT)info.Width, 
                                                    (UINT)info.Height, 
                                                    1, info.Format));

    //insert the info[key] and object[data] pair into the map
    mRTPool.insert(make_pair(info, rtObject));

    return rtObject.RT;
}

/*----------------------------------------------------
 * Retrieve a render target. If the render target
 * already exists this will update its ref count and
 * return the already existing render target. If the
 * render target doesn't exist it will create a new one
 * and return it.
 *
 * @info - the information about the rendertarget to get
 *           specifies: w + h, surface formats
 * @createNew - [true]will forcibly create a new render 
 *                target even if one with the same formats
 *                and dimenstions already already exists.
 *
 * @return - A valid render target created with info
 *----------------------------------------------------*/
RenderTargetPtr RenderTargetPool::GetRenderTarget(RenderTargetInfo &info, bool createNew)
{
    static map<RenderTargetInfo, RTObject>::iterator iter;
    if(createNew && (iter = mRTPool.find(info)) != mRTPool.end())
    {
        info.Modifier = 0;
        info.Modifier += iter->second.RefCount + iter->first.Modifier;
    }

    return GetRenderTarget(info);
}

/*----------------------------------------------------
 * Check for support for a render target
 * @device - a valid D3D object
 * @format - the surface format of the render target
 * @adapterFormat - backbuffer format
 *
 * @return - return true if successfull
 *----------------------------------------------------*/
bool RenderTargetPool::IsFormatSupported(const IDirect3D9Ptr& device, 
                                         D3DFORMAT format, 
                                         D3DFORMAT adapterFormat)
{
    HRESULT hr = device->CheckDeviceFormat( D3DADAPTER_DEFAULT,
                                            D3DDEVTYPE_HAL,
                                            adapterFormat,
                                            D3DUSAGE_RENDERTARGET,
                                            D3DRTYPE_SURFACE,
                                            format);
    
    return SUCCEEDED( hr );

}

ModelEntity.cpp , ModelEntity.h

The ModelEntity class represents an object that has a mesh and a shader. The class draws the set mesh with the provided shader. The constructor takes a function pointer to a function that is responsible for setting the parameters of the shader. This way, the model entity doesn't have to have intimate knowledge about the shader. It simply calls the function pointed to by the shader function pointer.

#include "ModelEntity.h"
#include "Services.h"
#include "Renderer.h"
#include "ResourceManager.h"
#include "Material.h"
#include "Shader.h"
#include "Mesh.h"

#include <vector>

using namespace std;

/*----------------------------------------------------
 * Constructor
 * @SetShaderValuesFunc - function pointer that points
 *                    to a function that will be
 *                    responsible for setting all the
 *                    shader params for the shader set
 *                    on this model entity
 *----------------------------------------------------*/
ModelEntity::ModelEntity( void (*SetShaderValuesFunc)(ShaderPtr& shader, ModelEntity* mesh) )
{
    SetShaderValues = SetShaderValuesFunc;

    D3DXMatrixIdentity(&mWorld);
    D3DXQuaternionIdentity(&mOrientation);

    mScale = D3DXVECTOR3(1.0f, 1.0f, 1.0f);
    mPosition = D3DXVECTOR3(0.0f, 0.0f, 0.0f);

    mCanDraw = true;
}

/*----------------------------------------------------
 * Destructor. Removes this model's mesh and shader
 * from the mesh and shader resource managers.
 *----------------------------------------------------*/
ModelEntity::~ModelEntity()
{
    //don't manually release the mesh or shader, call the material managers instead
    ShaderRCManagerPtr shaders = boost::static_pointer_cast<ResourceManager<Shader>>(Services::GetService(ShaderResService));
    MeshRCManagerPtr meshes = boost::static_pointer_cast<ResourceManager<Mesh>>(Services::GetService(MeshResService));

    shaders->Remove(mShader);
    meshes->Remove(mMesh);
}

/*----------------------------------------------------
 * Create the world matrix from the scale, position,
 * and orientation. And perform any other initialization
 *----------------------------------------------------*/
void ModelEntity::Initialize()
{
    RendererPtr renderer = boost::static_pointer_cast<Renderer>(Services::GetService(RendererService));
    mGDevice = renderer->GetDevice();

    //create our world matrix
    D3DXMatrixIdentity(&mWorld);

    D3DXMATRIX scale;
    D3DXMatrixScaling(&scale, mScale.x, mScale.y, mScale.z);

    D3DXMATRIX trans;
    D3DXMatrixTranslation(&trans, mPosition.x, mPosition.y, mPosition.z);

    D3DXMATRIX orient;
    D3DXVECTOR3 axis;
    float angle = 0.0f;

    D3DXQuaternionToAxisAngle(&mOrientation, &axis, &angle);
    D3DXMatrixRotationAxis(&orient, &axis, angle);

    mWorld = scale * orient * trans;
}

/*----------------------------------------------------
 * Update the world matrix
 *----------------------------------------------------*/
void ModelEntity::Update(float dt)
{
    //rebuild world matrix
    D3DXMatrixIdentity(&mWorld);

    D3DXMATRIX scale;
    D3DXMatrixScaling(&scale, mScale.x, mScale.y, mScale.z);

    D3DXMATRIX trans;
    D3DXMatrixTranslation(&trans, mPosition.x, mPosition.y, mPosition.z);

    D3DXMATRIX orient;
    D3DXVECTOR3 axis;
    float angle = 0.0f;

    D3DXQuaternionToAxisAngle(&mOrientation, &axis, &angle);
    D3DXMatrixRotationAxis(&orient, &axis, angle);

    mWorld = scale * orient * trans;
}

/*----------------------------------------------------
 * Draw the model
 *----------------------------------------------------*/
void ModelEntity::Draw(float dt)
{
    if(!mCanDraw)
        return;

    //if we have a shader, draw with a shader applied
    //else just draw it.
    if(mShader)
    {
        DrawShader(dt);
    }
    else
    {
        HR(mGDevice->SetTransform(D3DTS_WORLD, &mWorld));
        mMesh->Draw(0);
    }
}

/*----------------------------------------------------
 * Draws a model with the shader set on the model ent.
 *----------------------------------------------------*/
void ModelEntity::DrawShader(float dt)
{
    //set shader values that this object doesn't know about
    if(SetShaderValues != 0)
        SetShaderValues(mShader, this);    

    vector<MaterialPtr> mtrls = mMesh->GetMaterials();

    mShader->ApplyLights();
    mShader->Begin();
    mShader->BeginPass(0);

    for(UINT j = 0; j < mtrls.size(); ++j)
    {
        mShader->SetMtrl(mtrls[j]->GetMaterial());
    
        // If there is a texture, then use.
        if(mtrls[j]->GetTexture() != 0)
        {
            mShader->SetTexture(mtrls[j]->GetTexture());
        }
    
        mShader->Update(dt); //commit values
        mMesh->Draw(j);
    }

    mShader->EndPass();
    mShader->End();
}

/*----------------------------------------------------
 * Notify the mesh and shader of the lost device
 *----------------------------------------------------*/
void ModelEntity::OnLostDevice()
{
    mMesh->OnLostDevice();
    mShader->OnLostDevice();
}

/*----------------------------------------------------
 * Notify the mesh and shader of the reset device
 *----------------------------------------------------*/
void ModelEntity::OnResetDevice()
{
    mMesh->OnResetDevice();
    mShader->OnResetDevice();
}

/*----------------------------------------------------
 * Set the shader for the model. Use the name and path
 * to find the shader in the shader resource manager.
 * If it's not there already the manager is respoinsible
 * for creating the shader.
 *----------------------------------------------------*/
void ModelEntity::SetShader(const std::string& name, const std::string& path)
{
    ShaderRCManagerPtr shaders = 
        boost::static_pointer_cast<ResourceManager<Shader>>(Services::GetService(ShaderResService));

    //if a shader already existed, remove its reference from the manager
    if(mShader)
        shaders->Remove(mShader);

    mShader = shaders->Add(name, path);
}

/*----------------------------------------------------
 * Set the mesh for the model. Use the name and path
 * to find the mesh in the mesh resource manager.
 * If it's not there already the manager is respoinsible
 * for creating the mesh.
 *----------------------------------------------------*/
void ModelEntity::SetMesh(const std::string& name, const std::string& path)
{
    MeshRCManagerPtr meshes = 
        boost::static_pointer_cast<ResourceManager<Mesh>>(Services::GetService(MeshResService));

    //if a mesh already existed, remove its reference from the manager
    if(mMesh)
        meshes->Remove(mMesh);

    mMesh = meshes->Add(name, path);
}

Mesh.cpp , Mesh.h

The Mesh class is a simple class that holds an ID3DXMesh object. It is responsible for loading its .X model and finding and storing the materials. Inherits from templated base class Resource.

#include "Mesh.h"

#include "Renderer.h"
#include "Services.h"
#include "ResourceManager.h"
#include "Material.h"
#include "VertexFormats.h"

/*----------------------------------------------------
 * Constructor: default material
 *----------------------------------------------------*/
Mesh::Mesh() : Resource<Mesh>("null", "null")
{
    mMesh = 0;
}
/*----------------------------------------------------
 * Constructor
 * @name - file name of the .x model
 * @path - path to the file
 *----------------------------------------------------*/
Mesh::Mesh(const std::string& name, const std::string& path) : Resource<Mesh>(name, path)
{
    mMesh = 0;

    LoadXFile();
}

/*----------------------------------------------------
 * Mesh constructor:
 * Takes the name and path of the model.
 * Also takes the name of the texture and Mtrl to use
 * ***There must be a one:one ratio of materials and texture names
 *----------------------------------------------------*/
Mesh::Mesh(const std::string& name, 
           const std::string& path,
           const std::string& textureName,
           D3DMATERIAL9& material) : Resource<Mesh>(name, path)
{
    //get the material manager from the services manager
    MaterialRCManagerPtr mtrlManager = 
        boost::static_pointer_cast<ResourceManager<Material>>(Services::GetService(MaterialResService));

    //create/get the material
    MaterialPtr mtrl = mtrlManager->Add(textureName, path);
    mtrl->SetMaterial(material);

    //add it to our list
    mMaterials.push_back(mtrl);
    
    mMesh = 0;

    LoadXFile();
}

/*----------------------------------------------------
 * Release the mesh
 *----------------------------------------------------*/
Mesh::~Mesh()
{
    //release the d3d mesh
    mMesh = 0;

    //remove the materials from the manager
    MaterialRCManagerPtr mtrlManager = 
            boost::static_pointer_cast<ResourceManager<Material>>(Services::GetService(MaterialResService));

    for(int i = 0; i < mMaterials.size(); i++)
    {
        mtrlManager->Remove(mMaterials[i]);
    }

    mMaterials.clear();
}

/*----------------------------------------------------
 * Set a material on a mesh. 
 * Should be called only when the mesh has one material
 *----------------------------------------------------*/
void Mesh::SetMaterial(const std::string& name, 
                       const std::string& path)
{
    if(mMaterials.size() > 0) // we have a material
    {
        mMaterials[0]->LoadTexture(name, path);
    }
    else //else create a new material
    {
        //get the material manager from the services manager
        MaterialRCManagerPtr mtrlManager = 
            boost::static_pointer_cast<ResourceManager<Material>>(Services::GetService(MaterialResService));

        //create/get the material
        MaterialPtr mtrl = mtrlManager->Add(name, path);

        //add it to our list
        mMaterials.push_back(mtrl);
    }
}

/*----------------------------------------------------
 * Draw the mesh subset
 *----------------------------------------------------*/
void Mesh::Draw(int subset)
{
    HR(mMesh->DrawSubset(subset));
}

/*----------------------------------------------------
 * Load an .x model
 *----------------------------------------------------*/
void Mesh::LoadXFile()
{
    // Step 1: Load the .x file from file into a system memory mesh.
    RendererPtr renderer = boost::static_pointer_cast<Renderer>(Services::GetService(RendererService));

    ID3DXMeshPtr meshSys      = 0;
    ID3DXBufferPtr adjBuffer  = 0;
    ID3DXBufferPtr mtrlBuffer = 0;
    DWORD numMtrls          = 0;

    HR(D3DXLoadMeshFromX(GetFileName().c_str(), D3DXMESH_SYSTEMMEM, renderer->GetDevice(),
        &adjBuffer,    &mtrlBuffer, 0, &numMtrls, &meshSys));


    // Step 2: Find out if the mesh already has normal info?
    D3DVERTEXELEMENT9 elems[MAX_FVF_DECL_SIZE];
    HR(meshSys->GetDeclaration(elems));
    
    bool hasNormals = false;
    D3DVERTEXELEMENT9 term = D3DDECL_END();
    for(int i = 0; i < MAX_FVF_DECL_SIZE; ++i)
    {
        // Did we reach D3DDECL_END() {0xFF,0,D3DDECLTYPE_UNUSED, 0,0,0}?
        if(elems[i].Stream == 0xff )
            break;

        if( elems[i].Type == D3DDECLTYPE_FLOAT3 &&
            elems[i].Usage == D3DDECLUSAGE_NORMAL &&
            elems[i].UsageIndex == 0 )
        {
            hasNormals = true;
            break;
        }
    }

    // Step 3: Change vertex format to VertexPNT.
    D3DVERTEXELEMENT9 elements[64];
    UINT numElements = 0;
    VertexPNT::Decl->GetDeclaration(elements, &numElements);

    ID3DXMeshPtr temp = 0;
    HR(meshSys->CloneMesh(D3DXMESH_SYSTEMMEM, 
        elements, renderer->GetDevice(), &temp));

    meshSys = 0;
    meshSys = temp;


    // Step 4: If the mesh did not have normals, generate them.
    if( hasNormals == false)
        HR(D3DXComputeNormals(meshSys, 0));


    // Step 5: Optimize the mesh.
    HR(meshSys->Optimize(D3DXMESH_MANAGED | 
        D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE, 
        (DWORD*)adjBuffer->GetBufferPointer(), 0, 0, 0, &mMesh));

    meshSys = 0;   // Done w/ system mesh.
    adjBuffer = 0; // Done w/ buffer.

    
    // Step 6: Extract the materials and load the textures.
    MaterialRCManagerPtr mtrlManager = 
        boost::static_pointer_cast<ResourceManager<Material>>(Services::GetService(MaterialResService));

    if( mtrlBuffer != 0 && numMtrls != 0 )
    {
        D3DXMATERIAL* d3dxmtrls = (D3DXMATERIAL*)mtrlBuffer->GetBufferPointer();

        for(DWORD i = 0; i < numMtrls; ++i)
        {
            // Save the ith material.  Note that the MatD3D property does not have an ambient
            // value set when its loaded, so just set it to the diffuse value.
            D3DMATERIAL9 m;
            m.Ambient   = d3dxmtrls[i].MatD3D.Diffuse;
            m.Diffuse   = d3dxmtrls[i].MatD3D.Diffuse;
            m.Specular  = d3dxmtrls[i].MatD3D.Specular;
            m.Power        = d3dxmtrls[i].MatD3D.Power;

            //mtrls.push_back( m );

            // Check if the ith material has an associative texture
            MaterialPtr mtrl;
            if( d3dxmtrls[i].pTextureFilename != 0 )
            {
                //add a reference to the mtrl manager
                //if the material with the texture name exists the mtrl manager
                //will just return the existing material.
                //If not, it will create a new material
                mtrl = mtrlManager->Add(d3dxmtrls[i].pTextureFilename, GetPath());
            }
            else
            {
                // No texture for the ith subset
                mtrl = mtrlManager->Add(GetName() + "_mtrl", "null");
            }

            //set the d3d material 
            mtrl->SetMaterial(m);

            //add the material to the list
            mMaterials.push_back(mtrl);
        }
    }

    mtrlBuffer = 0; // done w/ buffer
}

Shader.cpp , Shader.h

The Shader class is a simple class responsible for creating a shader and setting the correct shader parameters. It provides a specific function that sets parameters relevant to the shader.  Inherits from templated base class Resource.

#include "Shader.h"

#include "Services.h"
#include "Renderer.h"
#include "Camera.h"
#include "ModelEntity.h"

#include <vector>
#include <sstream>

using namespace std;

/*----------------------------------------------------
 * Default Constructor
 *----------------------------------------------------*/
Shader::Shader() : Resource<Shader>("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<Shader>(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<Renderer>(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<Renderer>(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));
    
}