#include "shader_d3d9.h" #include #include "graphics_interface.h" #include "context_d3d9.h" #include "texture_d3d9.h" #include "d3d9_util.h" #include "leak_dumper.h" using namespace std; namespace Shared{ namespace Graphics{ namespace D3d9{ // =============================================== // class ShaderD3d9 // =============================================== ShaderProgramD3d9::ShaderProgramD3d9(){ GraphicsInterface &gi= GraphicsInterface::getInstance(); d3dDevice= static_cast(gi.getCurrentContext())->getD3dDevice(); vertexShader= NULL; pixelShader= NULL; } void ShaderProgramD3d9::attach(VertexShader *vs, FragmentShader *fs){ vertexShader= static_cast(vs); pixelShader= static_cast(fs); } bool ShaderProgramD3d9::link(string &messages){ d3dVsConstantTable= vertexShader->getD3dConstantTable(); d3dPsConstantTable= pixelShader->getD3dConstantTable(); return true; } void ShaderProgramD3d9::activate(){ d3dDevice->SetVertexShader(vertexShader->getD3dVertexShader()); d3dDevice->SetPixelShader(pixelShader->getD3dPixelShader()); } void ShaderProgramD3d9::setUniform(const string &name, int value){ D3DXHANDLE vsHandle= d3dVsConstantTable->GetConstantByName(NULL, name.c_str()); D3DXHANDLE psHandle= d3dPsConstantTable->GetConstantByName(NULL, name.c_str()); HRESULT vsResult= d3dVsConstantTable->SetInt(d3dDevice, vsHandle, value); HRESULT psResult= d3dPsConstantTable->SetInt(d3dDevice, psHandle, value); if(vsResult!=D3D_OK && psResult!=D3D_OK){ throw megaglest_runtime_error("Error setting shader uniform: "+string(name)); } } void ShaderProgramD3d9::setUniform(const string &name, float value){ D3DXHANDLE vsHandle= d3dVsConstantTable->GetConstantByName(NULL, name.c_str()); D3DXHANDLE psHandle= d3dPsConstantTable->GetConstantByName(NULL, name.c_str()); HRESULT vsResult= d3dVsConstantTable->SetFloat(d3dDevice, vsHandle, value); HRESULT psResult= d3dPsConstantTable->SetFloat(d3dDevice, psHandle, value); if(vsResult!=D3D_OK && psResult!=D3D_OK){ throw megaglest_runtime_error("Error setting shader uniform: "+string(name)); } } void ShaderProgramD3d9::setUniform(const string &name, const Vec2f &value){ setUniform(name, Vec4f(value.x, value.y, 0.0f, 0.0f)); } void ShaderProgramD3d9::setUniform(const string &name, const Vec3f &value){ setUniform(name, Vec4f(value.x, value.y, value.z, 0.0f)); } void ShaderProgramD3d9::setUniform(const string &name, const Vec4f &value){ D3DXVECTOR4 v; memcpy(&v, &value, sizeof(float)*4); D3DXHANDLE vsHandle= d3dVsConstantTable->GetConstantByName(NULL, name.c_str()); D3DXHANDLE psHandle= d3dPsConstantTable->GetConstantByName(NULL, name.c_str()); HRESULT vsResult= d3dVsConstantTable->SetVector(d3dDevice, vsHandle, &v); HRESULT psResult= d3dPsConstantTable->SetVector(d3dDevice, psHandle, &v); if(vsResult!=D3D_OK && psResult!=D3D_OK){ throw megaglest_runtime_error("Error setting shader uniform: "+string(name)); } } void ShaderProgramD3d9::setUniform(const string &name, const Matrix3f &value){ throw megaglest_runtime_error("Not implemented"); } void ShaderProgramD3d9::setUniform(const string &name, const Matrix4f &value){ D3DXMATRIX m; memcpy(&m, &value, sizeof(float)*16); D3DXHANDLE vsHandle= d3dVsConstantTable->GetConstantByName(NULL, name.c_str()); D3DXHANDLE psHandle= d3dPsConstantTable->GetConstantByName(NULL, name.c_str()); HRESULT vsResult= d3dVsConstantTable->SetMatrix(d3dDevice, vsHandle, &m); HRESULT psResult= d3dPsConstantTable->SetMatrix(d3dDevice, psHandle, &m); if(vsResult!=D3D_OK && psResult!=D3D_OK){ throw megaglest_runtime_error("Error setting shader uniform: "+string(name)); } } /*void ShaderD3d9::setUniform(const string &name, const Texture *value){ D3DXHANDLE handle= d3dConstantTable->GetConstantByName(NULL, name); D3DXCONSTANT_DESC d3dDesc; UINT i=1; IDirect3DTexture9 *d3dTexture= static_cast(value)->getD3dTexture(); HRESULT result= d3dConstantTable->GetConstantDesc(handle, &d3dDesc, &i); if(result==D3D_OK) d3dDevice->SetTexture(d3dDesc.RegisterIndex, d3dTexture); else throw megaglest_runtime_error("Error setting shader uniform sampler: "+string(name)); } bool ShaderD3d9::isUniform(char *name){ D3DXCONSTANT_DESC d3dDesc; UINT i=1; D3DXHANDLE handle= d3dConstantTable->GetConstantByName(NULL, name); HRESULT result= d3dConstantTable->GetConstantDesc(handle, &d3dDesc, &i); return result==D3D_OK; }*/ // =============================================== // class ShaderD3d9 // =============================================== ShaderD3d9::ShaderD3d9(){ GraphicsInterface &gi= GraphicsInterface::getInstance(); d3dDevice= static_cast(gi.getCurrentContext())->getD3dDevice(); d3dConstantTable= NULL; } void ShaderD3d9::end(){ if(d3dConstantTable!=NULL){ d3dConstantTable->Release(); d3dConstantTable= NULL; } } void ShaderD3d9::load(const string &path){ source.load(path); } // =============================================== // class VertexShaderD3d9 // =============================================== VertexShaderD3d9::VertexShaderD3d9(){ target= "vs_2_0"; d3dVertexShader= NULL; } void VertexShaderD3d9::end(){ ShaderD3d9::end(); if(d3dVertexShader!=NULL){ d3dVertexShader->Release(); d3dVertexShader= NULL; } } bool VertexShaderD3d9::compile(string &messages){ //compile shader ID3DXBuffer *code= NULL; ID3DXBuffer *errors= NULL; HRESULT result= D3DXCompileShader( source.getCode().c_str(), source.getCode().size(), NULL, NULL, "main", target.c_str(), 0, &code, &errors, &d3dConstantTable); if(errors!=NULL){ messages+= reinterpret_cast(errors->GetBufferPointer()); } if(FAILED(result)){ return false; } //create shader if(code!=NULL){ D3DCALL(d3dDevice->CreateVertexShader((DWORD*) code->GetBufferPointer(), &d3dVertexShader)); //release code->Release(); } if(errors!=NULL){ errors->Release(); } //set defaults if(d3dConstantTable!=NULL){ d3dConstantTable->SetDefaults(d3dDevice); } return true; } // =============================================== // class PixelShaderD3d9 // =============================================== PixelShaderD3d9::PixelShaderD3d9(){ target= "ps_2_0"; d3dPixelShader= NULL; } void PixelShaderD3d9::end(){ ShaderD3d9::end(); if(d3dPixelShader!=NULL){ d3dPixelShader->Release(); d3dPixelShader= NULL; } } bool PixelShaderD3d9::compile(string &messages){ messages+= "Compiling shader: " + source.getPathInfo() + "\n"; //compile shader ID3DXBuffer *code= NULL; ID3DXBuffer *errors= NULL; HRESULT result= D3DXCompileShader( source.getCode().c_str(), source.getCode().size(), NULL, NULL, "main", target.c_str(), 0, &code, &errors, &d3dConstantTable); if(errors!=NULL){ messages+= reinterpret_cast(errors->GetBufferPointer()); } if(FAILED(result)){ return false; } if(code!=NULL) { //create shader D3DCALL(d3dDevice->CreatePixelShader((DWORD*) code->GetBufferPointer(), &d3dPixelShader)); //release code->Release(); } if(errors!=NULL){ errors->Release(); } //set defaults if(d3dConstantTable!=NULL){ d3dConstantTable->SetDefaults(d3dDevice); } return true; } }}}//end namespace