/*============================================================================= IShader.h : Shaders common interface. Copyright (c) 2001-2002 Crytek Studios. All Rights Reserved. Revision history: * Created by Honich Andrey =============================================================================*/ #ifndef _ISHADER_H_ #define _ISHADER_H_ #include "TString.h" #include "TArrays.h" #include "smartptr.h" #include "Cry_XOptimise.h" #ifdef LINUX # include #endif struct IShader; struct SShader; class CMaterial; struct SShaderTexUnit; struct STexAnim; struct SShaderPass; struct CLeafBuffer; struct SShaderItem; struct STexPic; struct SParam; struct ICryCharInstance; struct IDeformableRenderMesh; class CPShader; template class list2; union UCol { DWORD dcolor; bvec4 bcolor; }; //================================================================ // HW Culling type enum ECull { eCULL_Back = 0, eCULL_Front, eCULL_None }; //========================================================================= // Array Pointers for HW Shaders enum ESrcPointer { eSrcPointer_Unknown, eSrcPointer_Vert, eSrcPointer_Color, eSrcPointer_SecColor, eSrcPointer_Tex, eSrcPointer_TexLM, eSrcPointer_Normal, eSrcPointer_Binormal, eSrcPointer_Tangent, eSrcPointer_TNormal, eSrcPointer_LightVector, eSrcPointer_LightVector_Terrain, eSrcPointer_NormLightVector, eSrcPointer_HalfAngleVector, eSrcPointer_HalfAngleVector_Terrain, eSrcPointer_Attenuation, eSrcPointer_LAttenuationSpec0, eSrcPointer_LAttenuationSpec1, eSrcPointer_LAttenuationSpec0_Terrain, eSrcPointer_LAttenuationSpec1_Terrain, eSrcPointer_Refract, eSrcPointer_Project, eSrcPointer_ProjectTexture, eSrcPointer_ProjectAttenFromCamera, eSrcPointer_Detail, eSrcPointer_Max, }; enum EDstPointer { eDstPointer_Unknown, eDstPointer_Vert, eDstPointer_Normal, eDstPointer_Color, eDstPointer_SecColor, eDstPointer_FogC, eDstPointer_Tex0, eDstPointer_Tex1, eDstPointer_Tex2, eDstPointer_Tex3, eDstPointer_Tex4, eDstPointer_Tex5, eDstPointer_Tex6, eDstPointer_Tex7, eDstPointer_Max, }; class COrthoNormalBasis { public: COrthoNormalBasis() { m_vForward = Vec3(1,0,0); m_vUp = Vec3(0,0,1); m_vRight = Vec3(0,1,0); } COrthoNormalBasis(const COrthoNormalBasis& basis) { m_vForward = basis.m_vForward; m_vUp = basis.m_vUp; m_vRight = basis.m_vRight; } COrthoNormalBasis(const Vec3& vForward, const Vec3& vUp, const Vec3& vRight) { m_vForward = vForward; m_vUp = vUp; m_vRight = vRight; } ~COrthoNormalBasis() { } COrthoNormalBasis& operator=(const COrthoNormalBasis& basis) { m_vForward = basis.m_vForward; m_vUp = basis.m_vUp; m_vRight = basis.m_vRight; return *this; }; Matrix44 matrixBasisToXYZ() const { Matrix44 mat; mat.SetIdentity(); mat(0,0) = m_vForward.x; mat(0,1) = m_vForward.y; mat(0,2) = m_vForward.z; mat(1,0) = m_vUp.x; mat(1,1) = m_vUp.y; mat(1,2) = m_vUp.z; mat(2,0) = m_vRight.x; mat(2,1) = m_vRight.y; mat(2,2) = m_vRight.z; return mat; } Matrix44 matrixXYZToBasis() const { Matrix44 mat; mat.SetIdentity(); mat(0,0) = m_vForward.x; mat(0,1) = m_vUp.x; mat(0,2) = m_vRight.x; mat(1,0) = m_vForward.y; mat(1,1) = m_vUp.y; mat(1,2) = m_vRight.y; mat(2,0) = m_vForward.z; mat(2,1) = m_vUp.z; mat(2,2) = m_vRight.z; return mat; } Matrix44 matrixBasisToDestBasis(const COrthoNormalBasis& dest) const { return (dest.matrixXYZToBasis() * this->matrixBasisToXYZ()); } COrthoNormalBasis& rotate(const Vec3& axis, const float degrees) { //Vec3 a = axis; //a.Normalize(); Matrix33 m; //m = m.GetRotation(a, degrees); m.SetRotationAA(DEG2RAD(degrees),GetNormalized(axis)); m_vForward = m * m_vForward; m_vRight = m * m_vRight; m_vUp = m * m_vUp; return *this; }; Vec3 m_vForward; //tangent Vec3 m_vUp; //binormal Vec3 m_vRight; //normal }; ////////////////////////////////////////////////////////////////////// // CCObject::m_ObjFlags: Flags used by shader pipeline #define FOB_SORTPOLYS 1 #define FOB_SELECTED 2 #define FOB_NEAREST 4 #define FOB_PORTAL 8 #define FOB_CUBE_POSX 0x10 #define FOB_CUBE_NEGX 0x20 #define FOB_CUBE_POSY 0x40 #define FOB_CUBE_NEGY 0x80 #define FOB_CUBE_POSZ 0x100 #define FOB_CUBE_NEGZ 0x200 #define FOB_TEXTURE 0x400 #define FOB_CUBE_MASK 0x7f0 #define FOB_CUBE_SHIFT 4 #define FOB_IGNOREMATERIALAMBIENT 0x800 #define FOB_DRSUN 0x1000 #define FOB_REFRACTED 0x2000 #define FOB_ZPASS 0x4000 #define FOB_LIGHTPASS 0x8000 #define FOB_FOGPASS 0x10000 #define FOB_RENDER_INTO_SHADOWMAP 0x20000 #define FOB_SPECULAR 0x40000 #define FOB_IGNOREREPOINTER 0x80000 #define FOB_ENVLIGHTING 0x100000 #define FOB_BENDED 0x200000 #define FOB_NOBUMP 0x400000 #define FOB_HASALPHA 0x800000 #define FOB_HOTAMBIENT 0x1000000 #define FOB_MASKCONDITIONS (FOB_BENDED | FOB_HASALPHA | FOB_SPECULAR | FOB_NOBUMP | FOB_INSHADOW | FOB_HEATVISION | FOB_HOTAMBIENT | FOB_ENVLIGHTING) #define FOB_REMOVED 0x2000000 #define FOB_HEATVISION 0x4000000 #define FOB_INSHADOW 0x8000000 #define FOB_TRANS_ROTATE 0x10000000 #define FOB_TRANS_SCALE 0x20000000 #define FOB_TRANS_TRANSLATE 0x40000000 #define FOB_TRANS_MASK (FOB_TRANS_ROTATE | FOB_TRANS_SCALE | FOB_TRANS_TRANSLATE) #define FOB_NOSCISSOR 0x80000000 struct SWaveForm; struct SWaveForm2; typedef TAllocator16 MatrixAllocator16; typedef TGrowArray MatrixArray16; //========================================================================= enum EParamType { eType_UNKNOWN, eType_BYTE, eType_BOOL, eType_SHORT, eType_INT, eType_FLOAT, eType_STRING, eType_FCOLOR, eType_VECTOR }; union UParamVal { byte m_Byte; bool m_Bool; short m_Short; int m_Int; float m_Float; char *m_String; float m_Color[4]; float m_Vector[3]; }; struct SShaderParam { // in order to facilitate the memory allocation tracking, we're using here this class; // if you don't like it, please write a substitute for all string within the project and use them everywhere char m_Name[32]; EParamType m_Type; UParamVal m_Value; int m_nMaterial; SShaderParam() { m_nMaterial = -1; m_Value.m_Int = 0; } size_t Size() { size_t nSize = sizeof(*this); nSize += sizeof(m_Name); if (m_Type == eType_STRING) nSize += strlen (m_Value.m_String) + 1; return nSize; } ~SShaderParam() { if (m_Type == eType_STRING) delete [] m_Value.m_String; } static bool SetParam(const char *name, TArray *Params, UParamVal& pr, int nMaterial) { int i; for (i=0; iNum(); i++) { SShaderParam *sp = &Params->Get(i); if (!sp) continue; const char *nm = sp->m_Name; int n = 0; char ch = 0; int ind = -1; while (true) { ch = name[n]; if (!ch) break; if (ch == '[') { char dig[16]; int m = 0; n++; while(true) { ch = name[n]; if (!ch) break; if (ch == ']') break; dig[m++] = ch; dig[m] = 0; n++; } if (!ch) break; ind = atoi(dig); ch = 0; break; } if (ch != nm[n]) break; n++; } if (!ch) { sp->m_nMaterial = nMaterial; switch (sp->m_Type) { case eType_INT: case eType_FLOAT: case eType_SHORT: sp->m_Value.m_Int = pr.m_Int; break; case eType_VECTOR: if (ind >= 0) sp->m_Value.m_Vector[ind] = pr.m_Vector[ind]; else { sp->m_Value.m_Vector[0] = pr.m_Vector[0]; sp->m_Value.m_Vector[1] = pr.m_Vector[1]; sp->m_Value.m_Vector[2] = pr.m_Vector[2]; } break; case eType_FCOLOR: if (ind >= 0) sp->m_Value.m_Color[ind] = pr.m_Color[ind]; else { sp->m_Value.m_Color[0] = pr.m_Color[0]; sp->m_Value.m_Color[1] = pr.m_Color[1]; sp->m_Value.m_Color[2] = pr.m_Color[2]; sp->m_Value.m_Color[3] = pr.m_Color[3]; } break; case eType_STRING: { char *str = pr.m_String; size_t len = strlen(str)+1; sp->m_Value.m_String = new char [len]; strcpy(sp->m_Value.m_String, str); } break; } break; } } if (i == Params->Num()) return false; return true; } static float GetFloat(const char *name, TArray *Params, int nMaterial) { int i; for (i=0; iNum(); i++) { SShaderParam *sp = &Params->Get(i); if (!sp) continue; if (sp->m_nMaterial != nMaterial) continue; const char *nm = sp->m_Name; int n = 0; char ch = 0; int ind = -1; while (true) { ch = name[n]; if (!ch) break; if (ch == '[') { char dig[16]; int m = 0; n++; while(true) { ch = name[n]; if (!ch) break; if (ch == ']') break; dig[m++] = ch; dig[m] = 0; n++; } if (!ch) break; ind = atoi(dig); ch = 0; break; } if (tolower(ch) != nm[n]) break; n++; } if (!ch) { switch (sp->m_Type) { case eType_INT: case eType_FLOAT: case eType_SHORT: return sp->m_Value.m_Float; break; case eType_VECTOR: if (ind >= 0) return sp->m_Value.m_Vector[ind]; else return -9999; break; case eType_FCOLOR: if (ind >= 0) return sp->m_Value.m_Color[ind]; else return -9999; break; case eType_STRING: { return -9999; } break; } } } return -9999; } }; ////////////////////////////////////////////////////////////////////// // Objects using in shader pipeline // Size of CCObject currently is 256 bytes. If you add new members better to ask me before or just // make sure CCObject is cache line aligned (64 bytes) class CCObject { public: CCObject() { m_ShaderParams = NULL; m_bShaderParamCreatedInRenderer = false; m_VPMatrixId = -1; m_VPMatrixFrame = -1; } ~CCObject(); short m_Id; short m_Counter; short m_VisId; short m_VPMatrixId; uint m_ObjFlags; Matrix44 m_Matrix; bool m_bShaderParamCreatedInRenderer; TArray *m_ShaderParams; // Lightmap textures ID's short m_nLMId; short m_nLMDirId; short m_nOcclId; short m_nHDRLMId; uint m_Reserved1; uint m_DynLMMask; float m_Trans2[3]; float m_Angs2[3]; // Different useful vars (ObjVal component in shaders) // [0] - used for blending trees sun-rabbits on distance (0-1) float m_TempVars[5]; float m_fDistanceToCam; CRendElement *m_RE; IShader *m_EF; void *m_CustomData; uint m_RenderState; float m_SortId; // Custom sort value short m_InvMatrixId; short m_VPMatrixFrame; short m_NumCM; // Custom Cube/Texture id (indoor engine soft shadows) union { short m_nLod; short m_NumWFX; short m_TexId0; }; union { short m_nTemplId; short m_NumWFY; short m_TexId1; }; union { short m_FrameLight; bool m_bVisible; }; short m_LightStyle; short m_nScissorX1, m_nScissorY1, m_nScissorX2, m_nScissorY2; union { float m_fRefract; float m_StartTime; }; union { float m_fBump; float m_fLightFadeTime; }; float m_fHeatFactor; list2 * m_pShadowCasters; // list of shadow casters struct ShadowMapFrustum * m_pShadowFrustum; // will define projection of shadow from this object Vec3d m_AmbColor; CFColor m_Color; IDeformableRenderMesh * m_pCharInstance; struct CLeafBuffer *m_pLMTCBufferO; union { ITexPic *m_pLightImage; CDLight *m_pLight; float m_fBending; float m_fLastUpdate; byte m_OcclLights[4]; }; _inline Vec3 GetTranslation() const { return m_Matrix.GetTranslationOLD(); } _inline float GetScaleX() const { return cry_sqrtf(m_Matrix(0,0)*m_Matrix(0,0) + m_Matrix(0,1)*m_Matrix(0,1) + m_Matrix(0,2)*m_Matrix(0,2)); } _inline float GetScaleZ() const { return cry_sqrtf(m_Matrix(2,0)*m_Matrix(2,0) + m_Matrix(2,1)*m_Matrix(2,1) + m_Matrix(2,2)*m_Matrix(2,2)); } _inline bool IsMergable() { if (m_Color.a != 1.0f) return false; if (m_pShadowCasters) return false; if (m_pCharInstance) return false; return true; } static TArray m_Waves; static MatrixArray16 m_ObjMatrices; void Init(); void CloneObject(CCObject *srcObj) { int Id = m_Id; int VisId = m_VisId; memcpy(this, srcObj, sizeof(*srcObj)); m_Id = Id; m_VisId = VisId; } Matrix44 &GetMatrix() { return m_Matrix; } Matrix44 &GetInvMatrix(); Matrix44 &GetVPMatrix(); void SetScissor(); void SetAlphaState(CPShader *pPS, int nCurState); virtual void AddWaves(SWaveForm2 **wf); virtual void SetShaderFloat(const char *Name, float Val); virtual void RemovePermanent(); #ifdef _RENDERER #ifdef DEBUGALLOC #undef new #endif // Sergiy: it's enough to allocate 16 bytes more, even on 64-bit machine // - and we need to store only the offset, not the actual pointer void* operator new( size_t Size ) { byte *ptr = (byte *)malloc(Size+16+4); memset(ptr, 0, Size+16+4); byte *bPtrRes = (byte *)((INT_PTR)(ptr+4+16) & ~0xf); ((byte**)bPtrRes)[-1] = ptr; return bPtrRes; } void* operator new[](size_t Size) { byte *ptr = (byte *)malloc(Size+16+2*sizeof(INT_PTR)); memset(ptr, 0, Size+16+2*sizeof(INT_PTR)); byte *bPtrRes = (byte *)((INT_PTR)(ptr+16+2*sizeof(INT_PTR)) & ~0xf); ((byte**)bPtrRes)[-2] = ptr; return bPtrRes-sizeof(INT_PTR); } void operator delete( void *Ptr ) { byte *bActualPtr = ((byte **)Ptr)[-1]; assert (bActualPtr <= (byte*)Ptr && (byte*)Ptr-bActualPtr < 20); free ((void *)bActualPtr); } void operator delete[]( void *Ptr ) { byte *bActualPtr = ((byte **)Ptr)[-1]; free ((void *)bActualPtr); } #ifdef DEBUGALLOC #define new DEBUG_CLIENTBLOCK #endif #endif // _RENDERER }; //================================================================================= // Materials #define LMF_IGNORELIGHTS 1 #define LMF_BUMPMATERIAL 2 #define LMF_NOAMBIENT 4 #define LMF_COLMAT_AMB 8 #define LMF_POLYOFFSET 0x10 #define LMF_NOALPHA 0x20 #define LMF_IGNOREPROJLIGHTS 0x40 #define LMF_NOBUMP 0x80 #define LMF_DISABLE 0x100 #define LMF_NOSPECULAR 0x200 #define LMF_NOADDSPECULAR 0x400 #define LMF_HASPSHADER 0x800 #define LMF_DIVIDEAMB4 0x1000 #define LMF_DIVIDEAMB2 0x2000 #define LMF_DIVIDEDIFF4 0x4000 #define LMF_DIVIDEDIFF2 0x8000 #define LMF_LIGHT0 0x10000 #define LMF_LIGHT1 0x20000 #define LMF_LIGHT2 0x30000 #define LMF_LIGHT3 0x40000 #define LMF_LIGHT4 0x50000 #define LMF_LIGHT5 0x60000 #define LMF_LIGHT6 0x70000 #define LMF_LIGHT7 0x80000 #define LMF_LIGHT_MASK 0xf0000 #define LMF_1SAMPLES 0x100000 #define LMF_2SAMPLES 0x200000 #define LMF_3SAMPLES 0x400000 #define LMF_4SAMPLES 0x800000 #define LMF_SAMPLES 0xf00000 #define LMF_LIGHT_SHIFT 16 #define LMF_ONLYMATERIALAMBIENT 0x1000000 #define LMF_USEOCCLUSIONMAP 0x2000000 #define LMF_HASAMBIENT 0x4000000 #define LMF_HASDOT3LM 0x8000000 struct SSideMaterial { SSideMaterial::SSideMaterial() : m_Ambient(1.0f, 1.0f, 1.0f, 1.0f), m_Diffuse(1.0f, 1.0f, 1.0f, 1.0f), m_Specular(1.0f, 1.0f, 1.0, 1.0f), m_Emission(0.0f, 0.0f, 0.0f, 1.0f), m_SpecShininess(10.0f) {} CFColor m_Ambient; CFColor m_Diffuse; CFColor m_Specular; CFColor m_Emission; float m_SpecShininess; _inline friend bool operator ==(const SSideMaterial &m1, const SSideMaterial &m2) { if (m1.m_Ambient == m2.m_Ambient && m1.m_Diffuse == m2.m_Diffuse && m1.m_Specular == m2.m_Specular && m1.m_Emission == m2.m_Emission && m1.m_SpecShininess == m2.m_SpecShininess) return true; return false; } }; struct SLightMaterial { SLightMaterial() { name[0] = 0; bNeverReplace = false; m_nRefCounter = 0; } int Id; char name[64]; enum Side {FRONT, BACK, BOTH} side; int m_nRefCounter; SSideMaterial Front; SSideMaterial Back; bool bNeverReplace; int Size() { int nSize = sizeof(SLightMaterial); return nSize; } void mfApply(int Flags); void Release(); static SLightMaterial* mfAdd(char *name, SLightMaterial *Compare=NULL); static SLightMaterial* mfGet(char *name); static SLightMaterial* current_material; static int m_ObjFrame; static TArray known_materials; }; //========================================================================================= // Wave form evaluators enum EWaveForm { eWF_None, eWF_Sin, eWF_HalfSin, eWF_InvHalfSin, eWF_Square, eWF_Triangle, eWF_SawTooth, eWF_InvSawTooth, eWF_Hill, eWF_InvHill, }; #define WFF_CLAMP 1 #define WFF_LERP 2 // Wave form definition struct SWaveForm { EWaveForm m_eWFType; byte m_Flags; float m_Level; float m_Level1; float m_Amp; float m_Amp1; float m_Phase; float m_Phase1; float m_Freq; float m_Freq1; int Size() { int nSize = sizeof(SWaveForm); return nSize; } SWaveForm() { memset(this, 0, sizeof(SWaveForm)); } bool operator == (SWaveForm wf) { if (m_eWFType == wf.m_eWFType && m_Level == wf.m_Level && m_Amp == wf.m_Amp && m_Phase == wf.m_Phase && m_Freq == wf.m_Freq && m_Level1 == wf.m_Level1 && m_Amp1 == wf.m_Amp1 && m_Phase1 == wf.m_Phase1 && m_Freq1 == wf.m_Freq1 && m_Flags == wf.m_Flags) return true; return false; } SWaveForm& operator += (const SWaveForm& wf ) { m_Level += wf.m_Level; m_Level1 += wf.m_Level1; m_Amp += wf.m_Amp; m_Amp1 += wf.m_Amp1; m_Phase += wf.m_Phase; m_Phase1 += wf.m_Phase1; m_Freq += wf.m_Freq; m_Freq1 += wf.m_Freq1; return *this; } }; struct SWaveForm2 { EWaveForm m_eWFType; float m_Level; float m_Amp; float m_Phase; float m_Freq; SWaveForm2() { memset(this, 0, sizeof(SWaveForm2)); } bool operator == (SWaveForm2 wf) { if (m_eWFType == wf.m_eWFType && m_Level == wf.m_Level && m_Amp == wf.m_Amp && m_Phase == wf.m_Phase && m_Freq == wf.m_Freq) return true; return false; } SWaveForm2& operator += (const SWaveForm2& wf ) { m_Level += wf.m_Level; m_Amp += wf.m_Amp; m_Phase += wf.m_Phase; m_Freq += wf.m_Freq; return *this; } }; //====================================================== // Texture coords generating types enum EGenTC { eGTC_NoFill = 0, eGTC_None, eGTC_LightMap, eGTC_Quad, eGTC_Base, eGTC_Projection, eGTC_Environment, eGTC_SphereMap, eGTC_SphereMapEnvironment, eGTC_ShadowMap, }; // Color operations enum EColorOp { eCO_NOSET, eCO_DISABLE, eCO_REPLACE, eCO_DECAL, eCO_ARG2, eCO_MODULATE, eCO_MODULATE2X, eCO_MODULATE4X, eCO_BLENDDIFFUSEALPHA, eCO_BLENDTEXTUREALPHA, eCO_DETAIL, eCO_ADD, eCO_ADDSIGNED, eCO_ADDSIGNED2X, eCO_MULTIPLYADD, eCO_BUMPENVMAP, eCO_BLEND, eCO_MODULATEALPHA_ADDCOLOR, eCO_MODULATECOLOR_ADDALPHA, eCO_MODULATEINVALPHA_ADDCOLOR, eCO_MODULATEINVCOLOR_ADDALPHA, eCO_DOTPRODUCT3, eCO_LERP, eCO_SUBTRACT, }; enum EColorArg { eCA_Specular, eCA_Texture, eCA_Diffuse, eCA_Previous, eCA_Constant, }; #define DEF_TEXARG0 (eCA_Texture|(eCA_Diffuse<<3)) #define DEF_TEXARG1 (eCA_Texture|(eCA_Previous<<3)) // Animating Texture sequence definition struct STexAnim { TArray m_TexPics; int m_Rand; int m_NumAnimTexs; bool m_bLoop; float m_Time; int Size() { int nSize = sizeof(STexAnim); nSize += m_TexPics.GetSize() * sizeof(STexPic *); return nSize; } STexAnim() { m_Rand = 0; m_NumAnimTexs = 0; m_bLoop = false; m_Time = 0.0f; } ~STexAnim() { for (int i=0; iAddRef(); m_TexPics.AddElem(sl.m_TexPics[i]); } m_Rand = sl.m_Rand; m_NumAnimTexs = sl.m_NumAnimTexs; m_bLoop = sl.m_bLoop; m_Time = sl.m_Time; return *this; } }; struct SGenTC { int m_Mask; bool m_bDependsOnObject; virtual ~SGenTC() { } SGenTC() { m_Mask = 0x3; m_bDependsOnObject = false; } virtual SGenTC *mfCopy() = 0; virtual bool mfSet(bool bEnable) = 0; virtual void mfCompile(char *params, SShader *ef) = 0; virtual int Size() = 0; }; // Type of the texture enum ETexType { eTT_Base, eTT_Cubemap, eTT_AutoCubemap, eTT_Bumpmap, eTT_DSDTBump, eTT_Rectangle, eTT_3D }; #define FFILT_NONE 0 #define FFILT_POINT 1 #define FFILT_LINEAR 2 #define FFILT_ANISOTROPIC 3 #define FTU_OPAQUE 1 #define FTU_CLAMP 2 #define FTU_NOMIPS 4 #define FTU_NOBUMP 8 #define FTU_PROJECTED 0x10 #define FTU_FILTERBILINEAR 0x20 #define FTU_FILTERTRILINEAR 0x40 #define FTU_FILTERNEAREST 0x80 #define FTU_FILTERLINEAR 0x100 #define FTU_BUMPPLANTS 0x1000 #define FTU_NOSCALE 0x2000 // General texture layer struct SShaderTexUnit { SShaderTexUnit() { memset(this, 0, sizeof(SShaderTexUnit)); } void mfFree() { SAFE_DELETE(m_GTC); if (m_AnimInfo) { SAFE_DELETE(m_AnimInfo); } else if (m_ITexPic) m_ITexPic->Release(false); } ~SShaderTexUnit() { mfFree(); } union { STexPic *m_TexPic; ITexPic *m_ITexPic; }; STexAnim *m_AnimInfo; SGenTC *m_GTC; byte m_eColorOp; byte m_eAlphaOp; byte m_eColorArg; byte m_eAlphaArg; byte m_eGenTC; byte m_eTexType; byte m_eHDRColorOp; short m_nFlags; float m_fTexFilterLodBias; int Size() { int nSize = sizeof(SShaderTexUnit); if (m_AnimInfo) nSize += m_AnimInfo->Size(); if (m_GTC) nSize += m_GTC->Size(); return nSize; } int GetTexFlags() const { int Flags = 0; if (m_nFlags & FTU_NOMIPS) Flags |= FT_NOMIPS; if (m_nFlags & FTU_CLAMP) Flags |= FT_CLAMP; if (m_nFlags & FTU_NOSCALE) Flags |= FT_NORESIZE; return Flags; } int GetTexFlags2() const { int Flags = 0; return Flags; } int mfSetTexture(int nt=-1); void mfUpdate(void); void mfUpdateAnim(CCObject *obj, int o); void mfCopy (SShaderTexUnit *dtl) const { dtl->mfFree(); memcpy(dtl, this, sizeof(SShaderTexUnit)); if (m_AnimInfo) { dtl->m_AnimInfo = new STexAnim; *dtl->m_AnimInfo = *m_AnimInfo; } if (m_GTC) dtl->m_GTC = m_GTC->mfCopy(); if (m_ITexPic) m_ITexPic->AddRef(); } }; enum ETexModRotateType { ETMR_NoChange, ETMR_Fixed, ETMR_Constant, ETMR_Oscillated, }; enum ETexModMoveType { ETMM_NoChange, ETMM_Fixed, ETMM_Constant, ETMM_Jitter, ETMM_Pan, ETMM_Stretch, ETMM_StretchRepeat, }; enum ETexGenType { ETG_Stream, ETG_World, ETG_Camera, ETG_WorldEnvMap, ETG_CameraEnvMap, ETG_NormalMap, ETG_SphereMap, }; #define CASE_TEXMOD(var_name)\ if(!stricmp(#var_name,szParamName))\ {\ var_name = fValue;\ return true;\ }\ #define CASE_TEXMODANGLE(var_name)\ if(!stricmp(#var_name,szParamName))\ {\ var_name = Degr2Word(fValue);\ return true;\ }\ #define CASE_TEXMODBYTE(var_name)\ if(!stricmp(#var_name,szParamName))\ {\ var_name = (byte)fValue;\ return true;\ }\ #define CASE_TEXMODBOOL(var_name)\ if(!stricmp(#var_name,szParamName))\ {\ var_name = (fValue==1.f);\ return true;\ }\ struct SEfTexModificator { bool SetMember(const char * szParamName, float fValue) { CASE_TEXMODBYTE(m_eTGType); CASE_TEXMODBYTE(m_eRotType); CASE_TEXMODBYTE(m_eUMoveType); CASE_TEXMODBYTE(m_eVMoveType); CASE_TEXMODBOOL(m_bTexGenProjected); CASE_TEXMOD(m_Tiling[0]); CASE_TEXMOD(m_Tiling[1]); CASE_TEXMOD(m_Tiling[2]); CASE_TEXMOD(m_Offs[0]); CASE_TEXMOD(m_Offs[1]); CASE_TEXMOD(m_Offs[2]); CASE_TEXMODANGLE(m_Rot[0]); CASE_TEXMODANGLE(m_Rot[1]); CASE_TEXMODANGLE(m_Rot[2]); CASE_TEXMODANGLE(m_RotOscRate[0]); CASE_TEXMODANGLE(m_RotOscRate[1]); CASE_TEXMODANGLE(m_RotOscRate[2]); CASE_TEXMODANGLE(m_RotOscAmplitude[0]); CASE_TEXMODANGLE(m_RotOscAmplitude[1]); CASE_TEXMODANGLE(m_RotOscAmplitude[2]); CASE_TEXMODANGLE(m_RotOscPhase[0]); CASE_TEXMODANGLE(m_RotOscPhase[1]); CASE_TEXMODANGLE(m_RotOscPhase[2]); CASE_TEXMOD(m_RotOscCenter[0]); CASE_TEXMOD(m_RotOscCenter[1]); CASE_TEXMOD(m_RotOscCenter[2]); CASE_TEXMOD(m_UOscRate); CASE_TEXMOD(m_VOscRate); CASE_TEXMOD(m_UOscAmplitude); CASE_TEXMOD(m_VOscAmplitude); CASE_TEXMOD(m_UOscPhase); CASE_TEXMOD(m_VOscPhase); return false; } byte m_eTGType; byte m_eRotType; byte m_eUMoveType; byte m_eVMoveType; bool m_bTexGenProjected; float m_Tiling[3]; float m_Offs[3]; ushort m_Rot[3]; ushort m_RotOscRate[3]; ushort m_RotOscAmplitude[3]; ushort m_RotOscPhase[3]; float m_RotOscCenter[3]; float m_UOscRate; float m_VOscRate; float m_UOscAmplitude; float m_VOscAmplitude; float m_UOscPhase; float m_VOscPhase; // This members are used only during updating of the matrices int m_nFrameUpdated; int m_nLastRecursionLevel; int m_UpdateFlags; Matrix44 m_TexMatrix; Matrix44 m_TexGenMatrix; float m_LastUTime; float m_LastVTime; float m_CurrentUJitter; float m_CurrentVJitter; _inline friend bool operator != (const SEfTexModificator &m1, const SEfTexModificator &m2) { if (m1.m_eTGType != m2.m_eTGType || m1.m_eRotType != m2.m_eRotType || m1.m_eUMoveType != m2.m_eUMoveType || m1.m_eVMoveType != m2.m_eVMoveType || m1.m_bTexGenProjected != m2.m_bTexGenProjected || m1.m_UOscRate != m2.m_UOscRate || m1.m_VOscRate != m2.m_VOscRate || m1.m_UOscAmplitude != m2.m_UOscAmplitude || m1.m_VOscAmplitude != m2.m_VOscAmplitude || m1.m_UOscPhase != m2.m_UOscPhase || m1.m_VOscPhase != m2.m_VOscPhase) return true; for (int i=0; i<3; i++) { if (m1.m_Tiling[i] != m2.m_Tiling[i] || m1.m_Offs[i] != m2.m_Offs[i] || m1.m_Rot[i] != m2.m_Rot[i] || m1.m_RotOscRate[i] != m2.m_RotOscRate[i] || m1.m_RotOscAmplitude[i] != m2.m_RotOscAmplitude[i] || m1.m_RotOscPhase[i] != m2.m_RotOscPhase[i] || m1.m_RotOscCenter[i] != m2.m_RotOscCenter[i]) return true; } return false; } }; struct SEfResTexture { // in order to facilitate the memory allocation tracking, we're using here this class; // if you don't like it, please write a substitute for all string within the project and use them everywhere CryBasicString m_Name; byte m_TexFlags; byte m_Amount; bool m_bUTile; bool m_bVTile; SEfTexModificator m_TexModificator; SShaderTexUnit m_TU; void Update(int nTU); _inline friend bool operator != (const SEfResTexture &m1, const SEfResTexture &m2) { if (stricmp(m1.m_Name.c_str(), m2.m_Name.c_str()) != 0 || m1.m_TexFlags != m2.m_TexFlags || m1.m_Amount != m2.m_Amount || m1.m_bUTile != m2.m_bUTile || m1.m_bVTile != m2.m_bVTile || m1.m_TexModificator != m2.m_TexModificator) return true; return false; } bool IsNeedTexTransform() { if (m_TexModificator.m_eRotType != ETMR_NoChange || m_TexModificator.m_eUMoveType != ETMM_NoChange || m_TexModificator.m_eVMoveType != ETMM_NoChange) return true; return false; } bool IsNeedTexGen() { if (m_TexModificator.m_eTGType != ETG_Stream) return true; return false; } int Size() { int nSize = sizeof(SEfResTexture) - sizeof(SShaderTexUnit); nSize += m_Name.size(); nSize += m_TU.Size(); return nSize; } ~SEfResTexture() { } void Reset() { memset(this, 0, sizeof(*this)); m_bUTile = true; m_bVTile = true; m_Amount = 100; m_TexModificator.m_Tiling[0] = 1.0f; m_TexModificator.m_Tiling[1] = 1.0f; m_TexModificator.m_Tiling[2] = 1.0f; m_TexModificator.m_TexMatrix.SetIdentity(); m_TexModificator.m_nFrameUpdated = -1; } SEfResTexture& operator=(const SEfResTexture& src) { src.m_TU.mfCopy(&m_TU); memcpy(&m_TexModificator, &src.m_TexModificator, sizeof(SEfTexModificator)); m_Amount = src.m_Amount; m_TexFlags = src.m_TexFlags; m_Name = src.m_Name; m_bUTile = src.m_bUTile; m_bVTile = src.m_bVTile; return *this; } SEfResTexture() { Reset(); } }; #define EFTT_DIFFUSE 0 #define EFTT_BUMP 1 #define EFTT_BUMP_DIFFUSE 2 #define EFTT_GLOSS 3 #define EFTT_CUBEMAP 4 #define EFTT_PHONG 5 #define EFTT_BUMP_HEIGHT 6 #define EFTT_ATTENUATION2D 7 #define EFTT_SPECULAR 8 #define EFTT_DETAIL_OVERLAY 9 #define EFTT_REFLECTION 10 #define EFTT_SUBSURFACE 11 #define EFTT_ATTENUATION1D 12 #define EFTT_OPACITY 13 #define EFTT_LIGHTMAP 14 #define EFTT_LIGHTMAP_HDR 15 #define EFTT_LIGHTMAP_DIR 16 #define EFTT_OCCLUSION 17 #define EFTT_DECAL_OVERLAY 18 #define EFTT_NORMALMAP 19 #define EFTT_MAX 20 struct SBaseShaderResources { int m_ResFlags; float m_Opacity; float m_AlphaRef; SLightMaterial *m_LMaterial; TArray m_ShaderParams; // in order to facilitate the memory allocation tracking, we're using here this class; // if you don't like it, please write a substitute for all string within the project and use them everywhere CryBasicString m_TexturePath; int Size() { int nSize = sizeof(SBaseShaderResources) + m_ShaderParams.GetMemoryUsage(); return nSize; } SBaseShaderResources& operator=(const SBaseShaderResources& src) { m_ResFlags = src.m_ResFlags; m_Opacity = src.m_Opacity; m_AlphaRef = src.m_AlphaRef; m_LMaterial = src.m_LMaterial; m_ShaderParams.Copy(src.m_ShaderParams); return *this; } SBaseShaderResources() { m_ResFlags = 0; m_Opacity = 1.0f; m_AlphaRef = 0; m_LMaterial = NULL; } ~SBaseShaderResources() { m_ShaderParams.Free(); } }; struct SRenderShaderResources : SBaseShaderResources { int m_Id; int m_nRefCounter; int m_nCheckedTemplates; bool m_bNeedNormals; SEfResTexture *m_Textures[EFTT_MAX]; int m_nLastTexture; int m_nFrameLoad; float m_fMinDistanceLoad; void AddTextureMap(int Id) { assert (Id >=0 && Id < EFTT_MAX); m_Textures[Id] = new SEfResTexture; } int Size() { int nSize = sizeof(SRenderShaderResources); for (int i=0; iSize(); } return nSize; } SRenderShaderResources& operator=(const SRenderShaderResources& src) { SBaseShaderResources::operator = (src); int i; for (i=0; im_TexModificator.m_UpdateFlags = 0; if (m_Textures[i]->m_TexModificator.m_eTGType == ETG_WorldEnvMap || m_Textures[i]->m_TexModificator.m_eTGType == ETG_CameraEnvMap) { m_bNeedNormals = true; break; } } } bool IsNeedNormals() { return m_bNeedNormals; } void Reset() { for (int i=0; im_TexturePath; m_ResFlags = pSrc->m_ResFlags; m_Opacity = pSrc->m_Opacity; m_AlphaRef = pSrc->m_AlphaRef; m_LMaterial = pSrc->m_LMaterial; m_ShaderParams.Copy(pSrc->m_ShaderParams); } for (int i=0; im_Textures[i]) { m_Textures[i] = *pSrc->m_Textures[i]; } else { m_Textures[i].Reset(); } } } ~SInputShaderResources() { } }; // Texture formats enum ETEX_Format { eTF_Unknown = 0, eTF_Index, eTF_HSV, eTF_0888, eTF_8888, // Usually BGRA eTF_RGBA, // Used only in CGLRenderer::DownLoadToVideoMemory eTF_8000, eTF_0565, eTF_0555, eTF_4444, eTF_1555, eTF_DXT1, eTF_DXT3, eTF_DXT5, // Only for normal maps eTF_SIGNED_HILO16, eTF_SIGNED_HILO8, eTF_SIGNED_RGB8, eTF_RGB8, // Only for DSDT bump (3 floats) eTF_DSDT_MAG, eTF_DSDT, eTF_V8U8, eTF_V16U16, eTF_0088, // Luminance, Alpha eTF_DEPTH, }; //=================================================================================== // Shader gen structure (used for automatic shader script generating) #define SHGF_HIDDEN 1 struct SShaderGenBit { SShaderGenBit() { m_Mask = 0; m_Flags = 0; } string m_ParamName; string m_ParamProp; string m_ParamDesc; uint64 m_Mask; uint m_Flags; }; struct SShaderGen { TArray m_BitMask; }; //=========================================================================== //==================================================================== // Template types #define EFT_DEFAULT 0 // Default shader as it is #define EFT_DECAL 1 // Only decal without lights #define EFT_INVLIGHT 3 // Decal with HW lights (DLight should be added) #define EFT_WHITESHADOW 4 // Depth map #define EFT_WHITE 7 // Just white texture with Z write #define EFT_FROMMAX 14 // Max #define EFT_HEATVISION 19 // Heat vision template #define EFT_DOF 20 // Depth of field template #define EFT_USER_FIRST 30 // First user defined template (each user's template must be registered) //==================================================================================== // Phys. material flags #define MATF_NOCLIP 1 //==================================================================================== #define EFSLIST_PREPROCESS_ID 2 #define EFSLIST_DISTSORT_ID 1 #define EFSLIST_GENERAL_ID 0 #define EFSLIST_STENCIL_ID 3 #define EFSLIST_LAST_ID 4 #define EFSLIST_UNSORTED_ID 5 #define EFSLIST_MASK (15<<28) #define EFSLIST_PREPROCESS (EFSLIST_PREPROCESS_ID << 28) // Rendering 1st (preprocess items) #define EFSLIST_STENCIL (EFSLIST_STENCIL_ID << 28) // Rendering 2nd (opaque surfaces with stencil shadows supporting) #define EFSLIST_LAST (EFSLIST_LAST_ID << 28) // Rendering last (6th) (sorted list of all fog passes, screen shaders, ...) #define EFSLIST_GENERAL (EFSLIST_GENERAL_ID << 28) // Rendering 4th (default sorted list for most render items) #define EFSLIST_DISTSORT (EFSLIST_DISTSORT_ID << 28) // Rendering 5th (blended sorted by distance render items) #define EFSLIST_UNSORTED (EFSLIST_UNSORTED_ID << 28) // Rendering 3rd (unsorted shadow passes on terrain) struct SEfTemplates { TArray m_TemplShaders; // All templates (Shaders) int m_nPreferred; int m_nMaskAuto; SShader *m_Preferred; SEfTemplates () { memset(this, 0, sizeof(SEfTemplates)); m_nPreferred = -1; } ~SEfTemplates() { } void mfFree(SShader *ef); void mfSetPreferred(SShader *ef); void mfClear(SShader *ef); void mfReserve(int Num) { if (Num >= m_TemplShaders.Num()) m_TemplShaders.ReserveNew(Num + 1); } int Size() { int nSize = sizeof(SEfTemplates); nSize += m_TemplShaders.GetSize() * sizeof(SShader *); return nSize; } }; // Class of the shader #define MAX_SH_CLASS 16 enum EShClass { eSH_Misc, eSH_World, eSH_ClientEffect, eSH_ClientPoly, eSH_Model, eSH_Indoor, eSH_MotModel, eSH_Screen, eSH_Temp, eSH_Tree_Leaves, eSH_Tree_Branches, eSH_Max }; //================================================================ // Sorting type of the Shader enum EF_Sort { eS_Unknown = 0, eS_PreProcess = 1, // Preprocess shader (draw to texture, visibility check, ...) eS_Sky = 2, // Sky box shader eS_ZBuff = 3, eS_ShadowMap = 4, eS_Terrain = 5, // Terrain surface eS_TerrainShadowPass = 6, // Terrain shadow pass eS_TerrainDetailTextures = 7, // Terrain detail textures eS_TerrainLightPass = 8, // Terrain light overlay pass eS_TerrainFogPass = 9, // Terrain fog overlay pass eS_Stencil = 10, // Stencil buffer pass eS_Opaque = 11, // General opaque surfaces eS_Decal = 12, // Decals on surfaces eS_Trees = 13, // Trees eS_SeeThrough = 14, // Alphatest shaders (Z-buffer writing is enabled) eS_Banner = 15, // Blend shaders (Z-buffer writing is disabled) eS_UnderWater = 16, // Under water objects eS_Water = 17, // Water surface eS_WaterBeach = 18, // Water beach eS_Additive = 19, // Additive blend polygons eS_Sprites = 20, // Billboards / sprites eS_TerrainDetailObjects = 21, // Terrain detail grass eS_Particles = 22, // All terrain particles eS_OcclusionTest = 23, // Occlusion test geometry eS_HeatVision = 24, eS_MuzzleFlash = 25, eS_Nearest = 26, // Nearest (first person weapon) eS_FogShader = 27, // Fog polygon eS_FogShader_Trans = 28, // Fog polygon eS_Refractive = 29, // Refractive objects eS_HDR = 30, // HDR post-processing eS_Glare = 31, // Glare fullscreen polygon eS_Max = 32 }; // Different preprocess flags for shaders that require preprocessing (like recursive render to texture, screen effects, visibility check, ...) // SShader->m_nPreprocess flags in priority order #define SPRID_CORONA 0 #define FSPR_CORONA (1< *GetREs () = 0; virtual bool AddTemplate(SRenderShaderResources *Res, int& TemplId, const char *Name=NULL, bool bSetPreferred=false, uint64 nMaskGen=0) = 0; virtual void RemoveTemplate(int TemplId) = 0; virtual IShader *GetTemplate(int num) = 0; virtual SEfTemplates *GetTemplates() = 0; virtual TArray& GetPublicParams() = 0; virtual int GetTexId () = 0; virtual ITexPic *GetBaseTexture(int *nPass, int *nTU) = 0; virtual unsigned int GetUsedTextureTypes(void) = 0; virtual int GetVertexFormat(void) = 0; virtual int Size(int Flags) = 0; virtual uint64 GetGenerationMask() = 0; virtual SShaderGen* GetGenerationParams() = 0; }; struct SShaderItem { SShaderItem() { m_pShader=0; m_pShaderResources=0; } IShader *m_pShader; SRenderShaderResources *m_pShaderResources; int GetSort(IShader *pSh) { int nSort = pSh->GetSort(); if (m_pShaderResources && m_pShaderResources->m_Opacity != 1.0f) { if (nSort <= eS_Opaque) nSort = eS_Banner | (nSort & EFSLIST_MASK); } return nSort; } _inline bool IsTransparent() { // note: if you change this function please check bTransparent variable in CLeafBuffer::Render() IShader *pSH = m_pShader->GetTemplate(-1); if (!(pSH->GetFlags2() & EF2_OPAQUE) || (m_pShaderResources && m_pShaderResources->m_Opacity != 1.0f)) return true; return false; } }; ////////////////////////////////////////////////////////////////////////// // Used in IMatInfo:Set/GetFlags ////////////////////////////////////////////////////////////////////////// #define MIF_POLYBUMP 1 #define MIF_INVPOLYBUMP 2 #define MIF_PHYSIC 4 #define MIF_NOCASTSHADOWS 8 #define MIF_COLLIDABLE 16 #define MIF_INVALID 32 // Set when material marked as invalid #define MIF_WASUSED 64 // Set when material assigned to some object #define MIF_CHILD 128 // Set if material is parent material ////////////////////////////////////////////////////////////////////////// // Material class used by renderer and 3D engine. ////////////////////////////////////////////////////////////////////////// struct IMatInfo { virtual ~IMatInfo() {}; ////////////////////////////////////////////////////////////////////////// // Reference counting. ////////////////////////////////////////////////////////////////////////// virtual void AddRef() = 0; virtual void Release() = 0; virtual int GetNumRefs() = 0; ////////////////////////////////////////////////////////////////////////// // material name ////////////////////////////////////////////////////////////////////////// //! Set material name, (Do not use this directly, to change material name use I3DEngine::RenameMatInfo method). virtual void SetName(const char * pName) = 0; //! Returns material name. virtual const char *GetName() = 0; //! Material flags. //! @see MIF_INVALID // see MIF_ flags (like MIF_INVALID) virtual void SetFlags( int flags ) = 0; virtual int GetFlags() const = 0; // shader item virtual void SetShaderItem(SShaderItem & _ShaderItem) = 0; virtual const SShaderItem & GetShaderItem() = 0; //! Used by custom material to override shader item. virtual bool OverrideShaderItem( int subMtlId,SShaderItem &si ) = 0; // shader params virtual void SetShaderParams(TArray * _pShaderParams) = 0; virtual const TArray * GetShaderParams() = 0; ////////////////////////////////////////////////////////////////////////// // Sub materials access. ////////////////////////////////////////////////////////////////////////// //! Returns number of child sub materials holded by this material. virtual int GetSubMtlCount() = 0; //! Return sub material at specified index. virtual IMatInfo* GetSubMtl( int i ) = 0; //! Adds new sub material to the end of sub materials list. virtual void AddSubMtl( IMatInfo *pMtl ) = 0; //! Deletes material from sub material list. virtual void RemoveSubMtl( IMatInfo *pMtl ) = 0; //! Remove all child sub materials at once. virtual void RemoveAllSubMtls() = 0; }; ////////////////////////////////////////////////////////////////////// struct CMatInfo : public IMatInfo { CMatInfo() { m_nRefCount = 0; sScriptMaterial[0]=0; sMaterialName[0] = 0; m_Id=0; m_Flags=0; nGamePhysMatId=0; m_dwNumSections=0; m_pPrimitiveGroups=0; m_vCenter.Set(0,0,0); m_fRadius=0; nFirstIndexId=0; nNumIndices=0; nFirstVertId=0; nNumVerts=0; pRE=0; fAlpha=0; pShaderParams=0; fAlpha=1; m_Id = -1; pMatEnt=0; pSubMtls = 0; m_nCGFMaterialID=-1; } ~CMatInfo() { RemoveAllSubMtls(); } virtual int GetNumRefs() { return m_nRefCount; }; char sScriptMaterial[32]; char sMaterialName[64]; //! Number of references to this material. int m_nRefCount; int m_Id; int m_nCGFMaterialID; //! Material flags. //! @see EMatInfoFlags int m_Flags; int nGamePhysMatId; ushort m_dwNumSections; SPrimitiveGroup *m_pPrimitiveGroups; Vec3 m_vCenter; float m_fRadius; int nFirstIndexId; int nNumIndices; int nFirstVertId; int nNumVerts; SShaderItem shaderItem; CREOcLeaf * pRE; float fAlpha; struct MAT_ENTITY * pMatEnt; // used by resource compiler TArray *pShaderParams; //! Array of Sub materials. typedef TArray SubMtls; SubMtls *pSubMtls; ////////////////////////////////////////////////////////////////////////// // IMatInfo implementation ////////////////////////////////////////////////////////////////////////// // material name int Size(); CMatInfo& operator=(const CMatInfo& src) { memcpy(this, &src, sizeof(CMatInfo)); if (shaderItem.m_pShader) shaderItem.m_pShader->AddRef(); if (shaderItem.m_pShaderResources) shaderItem.m_pShaderResources->AddRef(); return *this; }; virtual void AddRef() { m_nRefCount++; }; virtual void Release() { if (--m_nRefCount <= 0) delete this; } virtual void SetName(const char * pName) { strncpy( sMaterialName,pName,sizeof(sMaterialName) ); sMaterialName[sizeof(sMaterialName)-1] = 0; } virtual const char* GetName() { return sMaterialName; }; virtual void SetFlags( int flags ) { m_Flags = flags; }; virtual int GetFlags() const { return m_Flags; }; // shader item virtual void SetShaderItem(SShaderItem & _ShaderItem) { shaderItem = _ShaderItem; } virtual const SShaderItem & GetShaderItem() { return shaderItem; }; // shader params virtual void SetShaderParams(TArray * _pShaderParams) { pShaderParams = _pShaderParams; } virtual const TArray * GetShaderParams() { return pShaderParams; } ////////////////////////////////////////////////////////////////////////// virtual bool OverrideShaderItem( int subMtlId,SShaderItem &si ) { // Assume that the root material is the first material, sub materials start from index 1. if (subMtlId == 0) { si = shaderItem; return true; } if (pSubMtls) { if (subMtlId-1 < (int)pSubMtls->size()) { si = (*pSubMtls)[subMtlId-1]->GetShaderItem();; return true; } } return false; } ////////////////////////////////////////////////////////////////////////// // Sub materials. ////////////////////////////////////////////////////////////////////////// virtual int GetSubMtlCount() { if (pSubMtls) return pSubMtls->size(); return 0; } virtual IMatInfo* GetSubMtl( int i ) { assert( pSubMtls ); //ASSERT( i >= 0 && i < pSubMtls->size() ); return (*pSubMtls)[i]; } virtual void AddSubMtl( IMatInfo *pMtl ) { assert( pMtl ); if (!pSubMtls) pSubMtls = new SubMtls; pSubMtls->push_back( pMtl ); pMtl->SetFlags(pMtl->GetFlags() | MIF_CHILD); } virtual void RemoveSubMtl( IMatInfo *pMtl ) { assert( pMtl ); if (pSubMtls) { for (unsigned int i = 0; i < pSubMtls->size(); i++) { if ((*pSubMtls)[i] == pMtl) { pSubMtls->Delete(i); break; } } } } virtual void RemoveAllSubMtls() { if (pSubMtls) delete pSubMtls; pSubMtls = 0; } }; ////////////////////////////////////////////////////////////////////// // DLights #define DLF_DETAIL 1 #define DLF_DIRECTIONAL 2 #define DLF_DYNAMIC 4 //dynamic lights #define DLF_ACTIVE 8 //light is active/disactive #define DLF_CASTSHADOW_MAPS 0x10 //light casting shadows #define DLF_POINT 0x20 #define DLF_PROJECT 0x40 #define DLF_CASTSHADOW_VOLUME 0x80 //light casting shadows #define DLF_POSITIONCHANGED 0x100 #define DLF_NOATTENUATION 0x200 #define DLF_UPDATED 0x400 #define DLF_INWORLDSPACE 0x800 #define DLF_TEMP 0x1000 #define DLF_STATIC_ADDED 0x2000 //this static light has been already added to the list #define DLF_HASAMBIENT 0x4000 #define DLF_HEATSOURCE 0x8000 #define DLF_LIGHTSOURCE 0x10000 #define DLF_FAKE 0x20000 //actually it's not LS, just render elements (Flares, beams, ...) #define DLF_SUN 0x40000 //only sun may use this flag #define DLF_COPY 0x80000 #define DLF_LOCAL 0x100000 #define DLF_LM 0x200000 #define DLF_THIS_AREA_ONLY 0x400000 // affects only current area/sector #define DLF_AMBIENT_LIGHT 0x800000 // only used to add better ambient lighting to polybump characters #define DLF_IGNORE_OWNER 0x1000000 // do not affect light owner object #define DLF_IGNORE_TERRAIN 0x2000000 // do not affect heightmap #define DLF_ONLY_FOR_HIGHSPEC 0x4000000 //!< This light is active as dynamic light only for high spec machines. #define DLF_SPECULAR_ONLY_FOR_HIGHSPEC 0x8000000 //!< This light have specular component enabled only for high spec machines. #define DLF_LMDOT3 0x10000000 #define DLF_FAKE_RADIOSITY 0x20000000 #define DLF_LMOCCL 0x40000000 #define DLF_LIGHTTYPE_MASK (DLF_DIRECTIONAL | DLF_POINT | DLF_PROJECT) struct IEntity; struct ShadowMapLightSourceInstance; // Marco's NOTE: Andrey / Vlad please subividide this class // by putting the members into functions and use the names // info only if in debug mode, other strcutres can be // allocated only if needed in the constructor and destroyed in // the destructor, and you can even define an operator -> to // access the data into the various structures inside the class ////////////////////////////////////////////////////////////////////// class CDLight { public: //! constructor CDLight( void ) { memset(this, 0, sizeof(CDLight)); m_fLightFrustumAngle = 45.0f; m_fRadius = 4.0f; m_fDirectFactor = 1.0f; m_Flags = DLF_LIGHTSOURCE; m_Orientation.m_vForward = Vec3(1,0,0); m_Orientation.m_vUp = Vec3(0,1,0); m_Orientation.m_vRight = Vec3(0,0,1); m_NumCM = -1; m_nEntityLightId = -1; // m_nStaticLightId = -1; } //! destructor ~CDLight() { SAFE_RELEASE( m_pShader ); SAFE_RELEASE( m_pLightImage ); } //! bool Parse( void ) { if (!m_Name[0]) return false; if (strncmp(m_Name, "ls_", 3)==0 || strstr(m_Name, "_ls")) m_Flags |= DLF_LIGHTSOURCE; if (strncmp(m_Name, "hs_", 3)==0 || strstr(m_Name, "_hs")) m_Flags |= DLF_HEATSOURCE; return true; } void MakeBaseParams() { m_BaseOrigin = m_Origin; m_BaseColor = m_Color; m_BaseSpecColor = m_SpecColor; m_fBaseRadius = m_fRadius; m_fBaseLightFrustumAngle = m_fLightFrustumAngle; m_BaseProjAngles = m_ProjAngles; } //! assignment operator CDLight& operator=( const CDLight& dl ) { memcpy(this, &dl, sizeof(CDLight)); if (m_pShader) m_pShader->AddRef(); if (m_pLightImage) m_pLightImage->AddRef(); m_Flags |= DLF_COPY; return *this; } int m_Id; Vec3 m_Origin; //world space position Vec3 m_BaseOrigin; //world space position CFColor m_Color; //!< clampled diffuse light color CFColor m_BaseColor; //!< clampled diffuse light color CFColor m_SpecColor; CFColor m_BaseSpecColor; Vec3 m_vObjectSpacePos; //Object space position float m_fRadius; float m_fBaseRadius; float m_fDirectFactor; float m_fStartRadius; float m_fEndRadius; float m_fLastTime; int m_NumCM; // Scissor parameters (2d extent) short m_sX; short m_sY; short m_sWidth; short m_sHeight; // Far/near planes float m_fNear; float m_fFar; struct IEntityRender * m_pOwner; // int m_nStaticLightId; //for static spot light sources casting volumetric shadows int m_nReserved; // compensates for the vtbl COrthoNormalBasis m_Orientation; int m_CustomTextureId; Matrix44 m_TextureMatrix; CCObject * m_pObject[4][4]; //!< Object for light coronas and light flares //the light image ITexPic* m_pLightImage; float m_fLightFrustumAngle; float m_fBaseLightFrustumAngle; float m_fAnimSpeed; IShader* m_pShader; Vec3 m_ProjAngles; Vec3 m_BaseProjAngles; uint m_Flags; //!< flags from above (prefix DLF_) char m_Name[64]; int m_nLightStyle; float m_fCoronaScale; float m_fStartTime; float m_fLifeTime; //!< lsource will be removed after this number of seconds char m_sDebugName[8]; //!< name of light creator (for debuging, pointer can't be used since entity may be deleted) ShadowMapLightSourceInstance * m_pShadowMapLightSource; //!< CLeafBuffer * m_arrLightLeafBuffers[8]; //!< array of leafbuffers used for heightmap lighting pass int m_nEntityLightId; //!< int m_nFrameID; //!< /* // next change: inline CFColor GetClampedDiffColor( void ) { CFColor ret=m_Color; ret.Clamp(); return(ret); } private: CFColor m_Color; //!< non clampled diffuse light color */ ICryCharInstance * m_pCharInstance; // pointer to character this source is attached to }; #include "RendElement.h" #endif// _ISHADER_H_