#include "ShaderProgram.h" #include "Matrix4x4.h" #include "Timer/PerfTimer.h" #include "Vector3.h" #include "Camera.h" #include "Light.h" #include "SceneEntity.h" #include "Transform3.h" using namespace std; namespace CHCDemoEngine { ////////// //-- changing shader parameters static float sCurrentTimer = 0; static float sOldTimer = 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) { Reset(); } GPUProgramParameters::GPUProgramParameters(): mProgram(NULL) { Reset(); } void GPUProgramParameters::Reset() { mFloats.clear(); mTextures.clear(); mMatrices.clear(); mArrays.clear(); mMatrixArrays.clear(); mTimerParam = -1; mOldTimerParam = -1; mViewDirParam = -1; mLightDirParam = -1; mViewMatrixParam = -1; mModelMatrixParam = -1; mOldModelMatrixParam = -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::SetMatrixArray(int idx, float *mats, int numElements) { if (mMatrixArrays.size() < idx + 1) mMatrixArrays.resize(idx + 1); mMatrixArrays[idx] = MatrixArrayParam(mats, 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, const Matrix4x4 &mat) { if (mMatrices.size() < idx + 1) mMatrices.resize(idx + 1); mMatrices[idx] = MatrixParam(mat); } void GPUProgramParameters::SetTimerParam(int idx) { mTimerParam = idx; } void GPUProgramParameters::SetOldTimerParam(int idx) { mOldTimerParam = idx; } void GPUProgramParameters::SetViewMatrixParam(int idx) { mViewMatrixParam = idx; } void GPUProgramParameters::SetViewDirParam(int idx) { mViewDirParam = idx; } void GPUProgramParameters::SetLightDirParam(int idx) { mLightDirParam = idx; } void GPUProgramParameters::SetModelMatrixParam(int idx) { mModelMatrixParam = idx; } void GPUProgramParameters::SetOldModelMatrixParam(int idx) { mOldModelMatrixParam = 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, const Matrix4x4 &mat) { SetMatrix(mProgram->GetParamIdxByName(name), mat); } void GPUProgramParameters::SetMatrixArray(const string &name, float *mats, int numElements) { SetMatrixArray(mProgram->GetParamIdxByName(name), mats, numElements); } void GPUProgramParameters::SetTexture(const string &name, unsigned int tex) { SetTexture(mProgram->GetParamIdxByName(name), tex); } void GPUProgramParameters::UpdateParameters(SceneEntity *ent) { 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); } } for (int i = 0; i < (int)mMatrixArrays.size(); ++ i) { const MatrixArrayParam &p = mMatrixArrays[i]; if (p.mValid) mProgram->SetMatrixArray(i, p.mValues, p.mNumEntries); } if (mTimerParam >= 0) mProgram->SetValue1f(mTimerParam, sCurrentTimer); if (mOldTimerParam >= 0) mProgram->SetValue1f(mOldTimerParam, sOldTimer); 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); if (ent) { if (mModelMatrixParam >= 0) mProgram->SetMatrix(mModelMatrixParam, ent->GetTransform()->GetMatrix()); if (mOldModelMatrixParam >= 0) mProgram->SetMatrix(mOldModelMatrixParam, ent->GetTransform()->GetOldMatrix()); } } void GPUProgramParameters::InitFrame(Camera *cam, DirectionalLight *light) { static PerfTimer mytimer; sOldTimer = sCurrentTimer; 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(); } /********************************************************/ /* ShaderProgram implementation */ /********************************************************/ ShaderProgram::ShaderProgram(CGcontext context, const std::string &filename, CGprofile profile, const std::string &functionName, PROGRAM_TYPE programType): mProgramType(programType) { 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; } void ShaderProgram::AddParameters(std::string params[], int startIdx, int numElements) { for (int i = 0; i < numElements; ++ i) AddParameter(params[i], startIdx + i); } 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::SetMatrixArray(int idx, float *mats, int numElements) { cgGLSetMatrixParameterArrayfc(GetParameter(idx), 0, numElements, (const float *)mats); } 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