#include "ShaderProgram.h" #include "Matrix4x4.h" #include "Timer/PerfTimer.h" #include "Vector3.h" #include "Camera.h" #include "Light.h" using namespace std; namespace CHCDemoEngine { ////////// //-- changing shader parameters static float sCurrentTimer = 0; static Matrix4x4 sCurrentViewMatrix = IdentityMatrix(); static Vector3 sCurrentViewDir = Vector3::UNIT_Y(); static Vector3 sCurrentLightDir = Vector3::UNIT_Y(); /*********************************************************/ /* GPUProgramParameters implementation */ /*********************************************************/ GPUProgramParameters::GPUProgramParameters(ShaderProgram *p): mProgram(p), mTimerParam(-1), mViewDirParam(-1), mViewMatrixParam(-1), mLightDirParam(-1) { } GPUProgramParameters::GPUProgramParameters(): mProgram(NULL), mTimerParam(-1), mViewDirParam(-1), mViewMatrixParam(-1), mLightDirParam(-1) { } void GPUProgramParameters::Reset() { mFloats.clear(); mTextures.clear(); mMatrices.clear(); mArrays.clear(); mTimerParam = -1; mViewDirParam = -1; mLightDirParam = -1; mViewMatrixParam = -1; } void GPUProgramParameters::SetValue1f(int idx, float value) { if (mFloats.size() < idx + 1) mFloats.resize(idx + 1); mFloats[idx] = FloatParam(&value, 1); } void GPUProgramParameters::SetValue2f(int idx, float val1, float val2) { if (mFloats.size() < idx + 1) mFloats.resize(idx + 1); float vals[] = {val1, val2}; mFloats[idx] = FloatParam(vals, 2); } void GPUProgramParameters::SetValue3f(int idx, float val1, float val2, float val3) { if (mFloats.size() < idx + 1) mFloats.resize(idx + 1); float vals[] = {val1, val2, val3}; mFloats[idx] = FloatParam(vals, 3); } void GPUProgramParameters::SetArray1f(int idx, float *vals, int numElements) { if (mArrays.size() < idx + 1) mArrays.resize(idx + 1); mArrays[idx] = ArrayParam(vals, 1, numElements); } void GPUProgramParameters::SetArray2f(int idx, float *vals, int numElements) { if (mArrays.size() < idx + 1) mArrays.resize(idx + 1); mArrays[idx] = ArrayParam(vals, 2, numElements); } void GPUProgramParameters::SetArray3f(int idx, float *vals, int numElements) { if (mArrays.size() < idx + 1) mArrays.resize(idx + 1); mArrays[idx] = ArrayParam(vals, 3, numElements); } void GPUProgramParameters::SetTexture(int idx, unsigned int tex) { if (mTextures.size() < idx + 1) mTextures.resize(idx + 1); mTextures[idx] = IntParam(tex); } void GPUProgramParameters::SetMatrix(int idx, Matrix4x4 *mat) { if (mMatrices.size() < idx + 1) mMatrices.resize(idx + 1); mMatrices[idx] = MatrixParam(mat); } void GPUProgramParameters::SetTimerParam(int idx) { mTimerParam = idx; } void GPUProgramParameters::SetViewMatrixParam(int idx) { mViewMatrixParam = idx; } void GPUProgramParameters::SetViewDirParam(int idx) { mViewDirParam = idx; } void GPUProgramParameters::SetLightDirParam(int idx) { mLightDirParam = idx; } void GPUProgramParameters::SetValue1f(const string &name, float val) { SetValue1f(mProgram->GetParamIdxByName(name), val); } void GPUProgramParameters::SetValue2f(const string &name, float val1, float val2) { SetValue2f(mProgram->GetParamIdxByName(name), val1, val2); } void GPUProgramParameters::SetValue3f(const string &name, float val1, float val2, float val3) { SetValue3f(mProgram->GetParamIdxByName(name), val1, val2, val3); } void GPUProgramParameters::SetArray1f(const string &name, float *vals, int numElements) { SetArray1f(mProgram->GetParamIdxByName(name), vals, numElements); } void GPUProgramParameters::SetArray2f(const string &name, float *vals, int numElements) { SetArray2f(mProgram->GetParamIdxByName(name), vals, numElements); } void GPUProgramParameters::SetArray3f(const string &name, float *vals, int numElements) { SetArray3f(mProgram->GetParamIdxByName(name), vals, numElements); } void GPUProgramParameters::SetMatrix(const string &name, Matrix4x4 *mat) { SetMatrix(mProgram->GetParamIdxByName(name), mat); } void GPUProgramParameters::SetTexture(const string &name, unsigned int tex) { SetTexture(mProgram->GetParamIdxByName(name), tex); } void GPUProgramParameters::UpdateParameters() { if (!mProgram) return; for (int i = 0; i < (int)mFloats.size(); ++ i) { const FloatParam &p = mFloats[i]; if (!p.mValid) continue; switch (p.mNumComponents) { case 1: mProgram->SetValue1f(i, p.mValues[0]); break; case 2: mProgram->SetValue2f(i, p.mValues[0], p.mValues[1]); break; case 3: mProgram->SetValue3f(i, p.mValues[0], p.mValues[1], p.mValues[2]); break; default: mProgram->SetValue1f(i, p.mValues[0]); } } for (int i = 0; i < (int)mTextures.size(); ++ i) { const IntParam &p = mTextures[i]; if (p.mValid) mProgram->SetTexture(i, p.mValue); } for (int i = 0; i < (int)mMatrices.size(); ++ i) { const MatrixParam &p = mMatrices[i]; if (p.mValid) mProgram->SetMatrix(i, *p.mValue); } for (int i = 0; i < (int)mArrays.size(); ++ i) { const ArrayParam &p = mArrays[i]; if (!p.mValid) continue; switch (p.mNumComponents) { case 1: mProgram->SetArray1f(i, p.mValues, p.mNumEntries); break; case 2: mProgram->SetArray2f(i, p.mValues, p.mNumEntries); break; case 3: mProgram->SetArray3f(i, p.mValues, p.mNumEntries); break; default: mProgram->SetArray1f(i, p.mValues, p.mNumEntries); } } if (mTimerParam >= 0) mProgram->SetValue1f(mTimerParam, sCurrentTimer); if (mViewDirParam >= 0) mProgram->SetValue3f(mViewDirParam, sCurrentViewDir.x, sCurrentViewDir.y, sCurrentViewDir.z); if (mLightDirParam >= 0) mProgram->SetValue3f(mLightDirParam, sCurrentLightDir.x, sCurrentLightDir.y, sCurrentLightDir.z); if (mViewMatrixParam >= 0) mProgram->SetMatrix(mViewMatrixParam, sCurrentViewMatrix); } void GPUProgramParameters::InitFrame(Camera *cam, DirectionalLight *light) { static PerfTimer mytimer; sCurrentTimer = mytimer.Elapsedms(false) * M_PI / 180.0f; cam->GetModelViewMatrix(sCurrentViewMatrix); sCurrentViewDir = cam->GetDirection(); Matrix4x4 vo; // transform to view space cam->GetViewOrientationMatrix(vo); //sCurrentLightDir = /*vo **/ -light->GetDirection(); sCurrentLightDir = vo * -light->GetDirection(); } /********************************************************/ /* ShaderProgram implementation */ /********************************************************/ ShaderProgram::ShaderProgram(CGcontext context, const std::string &filename, CGprofile profile, const std::string &functionName) { mProgram = cgCreateProgramFromFile(context, CG_SOURCE, filename.c_str(), profile, functionName.c_str(), NULL); if (mProgram) cgGLLoadProgram(mProgram); const int maxParams = 64; mParameters.resize(maxParams); for (int i = 0; i < maxParams; ++ i) { mParameters[i] = NULL; } } void ShaderProgram::Bind() { cgGLBindProgram(mProgram); // enable all texture parameters CGParameterArray::const_iterator it, it_end = mTextureParams.end(); for (it = mTextureParams.begin(); it != it_end; ++ it) cgGLEnableTextureParameter(*it); } void ShaderProgram::Release() { CGParameterArray::const_iterator it, it_end = mTextureParams.end(); // disable all texture parameters for (it = mTextureParams.begin(); it != it_end; ++ it) cgGLDisableTextureParameter(*it); } CGparameter ShaderProgram::AddParameter(const string &name, int idx) { CGparameter p = GetOrCreateParameter(name); mParamHash[name] = idx; mParameters[idx] = p; return p; } CGparameter ShaderProgram::GetOrCreateParameter(const string &name) { CGparameter p; CGParameterMap::const_iterator it = mParamHash.find(name); if (it == mParamHash.end()) { p = cgGetNamedParameter(mProgram, name.c_str()); } else { p = mParameters[(*it).second]; } //cout << "name: " << name << " " << p << " " << mProgram << endl; return p; } CGparameter ShaderProgram::GetParameter(int idx) const { return mParameters[idx]; } void ShaderProgram::SetValue1f(int idx, float val) { cgGLSetParameter1f(GetParameter(idx), val); } void ShaderProgram::SetValue2f(int idx, float val1, float val2) { cgGLSetParameter2f(GetParameter(idx), val1, val2); } void ShaderProgram::SetValue3f(int idx, float val1, float val2, float val3) { cgGLSetParameter3f(GetParameter(idx), val1, val2, val3); } void ShaderProgram::SetArray1f(int idx, float *vals, int numElements) { cgGLSetParameterArray1f(GetParameter(idx), 0, numElements, (const float *)vals); } void ShaderProgram::SetArray2f(int idx, float *vals, int numElements) { cgGLSetParameterArray2f(GetParameter(idx), 0, numElements, (const float *)vals); } void ShaderProgram::SetArray3f(int idx, float *vals, int numElements) { cgGLSetParameterArray3f(GetParameter(idx), 0, numElements, (const float *)vals); } void ShaderProgram::SetMatrix(int idx, const Matrix4x4 &mat) { cgGLSetMatrixParameterfc(GetParameter(idx), (const float *)mat.x); } void ShaderProgram::SetTexture(int idx, unsigned int tex) { CGparameter p = GetParameter(idx); cgGLSetTextureParameter(p, tex); cgGLEnableTextureParameter(p); } void ShaderProgram::SetValue1f(const string &name, float val) { cgGLSetParameter1f(GetOrCreateParameter(name), val); } void ShaderProgram::SetValue2f(const string &name, float val1, float val2) { cgGLSetParameter2f(GetOrCreateParameter(name), val1, val2); } void ShaderProgram::SetValue3f(const string &name, float val1, float val2, float val3) { cgGLSetParameter3f(GetOrCreateParameter(name), val1, val2, val3); } void ShaderProgram::SetArray1f(const string &name, float *vals, int numElements) { cgGLSetParameterArray1f(GetOrCreateParameter(name), 0, numElements, (const float *)vals); } void ShaderProgram::SetArray2f(const string &name, float *vals, int numElements) { cgGLSetParameterArray2f(GetOrCreateParameter(name), 0, numElements, (const float *)vals); } void ShaderProgram::SetArray3f(const string &name, float *vals, int numElements) { cgGLSetParameterArray3f(GetOrCreateParameter(name), 0, numElements, (const float *)vals); } void ShaderProgram::SetMatrix(const string &name, const Matrix4x4 &mat) { cgGLSetMatrixParameterfc(GetOrCreateParameter(name), (const float *)mat.x); } void ShaderProgram::SetTexture(const string &name, unsigned int tex) { CGparameter p = GetOrCreateParameter(name); cgGLSetTextureParameter(p, tex); cgGLEnableTextureParameter(p); mTextureParams.push_back(p); } int ShaderProgram::GetParamIdxByName(const std::string &name) const { CGParameterMap::const_iterator it = mParamHash.find(name); return (*it).second; } } // namespace