/*============================================================================= ShaderTemplate.cpp : implementation of the Shaders templates support. Copyright (c) 2001 Crytek Studios. All Rights Reserved. Revision history: * Created by Honitch Andrey =============================================================================*/ #include "RenderPCH.h" #include "I3DEngine.h" #include "CryHeaders.h" #if defined(WIN32) || defined(WIN64) #include #include #elif defined(LINUX) #endif //=============================================================================== SRenderShaderResources::~SRenderShaderResources() { int i; for (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_Name.empty() || pSrc->m_Textures[i].m_TU.m_TexPic)) { if (!m_Textures[i]) AddTextureMap(i); *m_Textures[i] = pSrc->m_Textures[i]; } else { if (m_Textures[i]) m_Textures[i]->Reset(); m_Textures[i] = NULL; } } } SRenderShaderResources *CShader::mfCreateShaderResources(const SInputShaderResources *Res, bool bShare) { int i, j; SInputShaderResources RS; RS = *Res; for (i=0; iIsTextureLoaded()) { Warning( VALIDATOR_FLAG_TEXTURE,RS.m_Textures[i].m_Name.c_str(),"Error: CShader::mfCreateShaderResources: Couldn't find detail texture\n'%s' in path '%s'\n", RS.m_Textures[i].m_Name.c_str(), RS.m_TexturePath.c_str()); RS.m_Textures[i].m_TU.m_TexPic = mfLoadResourceTexture(CRenderer::CV_r_detaildefault->GetString(), RS.m_TexturePath.c_str(), RS.m_Textures[i].m_TU.GetTexFlags(), RS.m_Textures[i].m_TU.GetTexFlags2(), eTT_Base, NULL, &RS.m_Textures[i], RS.m_Textures[i].m_Amount); if (!RS.m_Textures[i].m_TU.m_TexPic->IsTextureLoaded()) RS.m_Textures[i].m_TU.m_TexPic = mfLoadResourceTexture("Textures/detail/rock", RS.m_TexturePath.c_str(), RS.m_Textures[i].m_TU.GetTexFlags(), RS.m_Textures[i].m_TU.GetTexFlags2(), eTT_Base, NULL, &RS.m_Textures[i], RS.m_Textures[i].m_Amount); } } if (i == EFTT_DECAL_OVERLAY && !RS.m_Textures[i].m_Name.empty()) { RS.m_Textures[i].m_TU.m_TexPic = mfLoadResourceTexture(RS.m_Textures[i].m_Name.c_str(), RS.m_TexturePath.c_str(), RS.m_Textures[i].m_TU.GetTexFlags(), RS.m_Textures[i].m_TU.GetTexFlags2(), eTT_Base, NULL, &RS.m_Textures[i], RS.m_Textures[i].m_Amount); if (!RS.m_Textures[i].m_TU.m_TexPic->IsTextureLoaded()) Warning( VALIDATOR_FLAG_TEXTURE,RS.m_Textures[i].m_Name.c_str(),"Error: CShader::mfCreateShaderResources: Couldn't find decal texture\n'%s' in path '%s'\n", RS.m_Textures[i].m_Name.c_str(), RS.m_TexturePath.c_str()); } if (i == EFTT_SUBSURFACE && !RS.m_Textures[i].m_Name.empty()) { RS.m_Textures[i].m_TU.m_TexPic = mfLoadResourceTexture(RS.m_Textures[i].m_Name.c_str(), RS.m_TexturePath.c_str(), RS.m_Textures[i].m_TU.GetTexFlags(), RS.m_Textures[i].m_TU.GetTexFlags2(), eTT_Base, NULL, &RS.m_Textures[i], RS.m_Textures[i].m_Amount); if (!RS.m_Textures[i].m_TU.m_TexPic->IsTextureLoaded()) Warning( VALIDATOR_FLAG_TEXTURE,RS.m_Textures[i].m_Name.c_str(),"Error: CShader::mfCreateShaderResources: Couldn't find subsurface texture\n'%s' in path '%s'\n", RS.m_Textures[i].m_Name.c_str(), RS.m_TexturePath.c_str()); } if (i == EFTT_ATTENUATION2D) { SEfResTexture *Tex = &RS.m_Textures[EFTT_ATTENUATION2D]; if (!Tex->m_TU.m_TexPic) { if (!Tex->m_Name.empty()) Tex->m_TU.m_TexPic = mfLoadResourceTexture(Tex->m_Name.c_str(), RS.m_TexturePath.c_str(), Tex->m_TU.GetTexFlags(), Tex->m_TU.GetTexFlags2(), eTT_Base, NULL, Tex); if (!Tex->m_TU.m_TexPic || !Tex->m_TU.m_TexPic->IsTextureLoaded()) Tex->m_TU.m_TexPic = mfLoadResourceTexture("Textures/Defaults/PointLight2D", RS.m_TexturePath.c_str(), Tex->m_TU.GetTexFlags(), Tex->m_TU.GetTexFlags2(), eTT_Base, NULL, Tex); } } if (i == EFTT_ATTENUATION1D) { SEfResTexture *Tex = &RS.m_Textures[EFTT_ATTENUATION1D]; if (!Tex->m_TU.m_TexPic) { if (!Tex->m_Name.empty()) Tex->m_TU.m_TexPic = mfLoadResourceTexture(Tex->m_Name.c_str(), RS.m_TexturePath.c_str(), Tex->m_TU.GetTexFlags(), Tex->m_TU.GetTexFlags2(), eTT_Base, NULL, Tex); if (!Tex->m_TU.m_TexPic || !Tex->m_TU.m_TexPic->IsTextureLoaded()) { if (gRenDev->m_TexMan->m_Text_Atten1D) Tex->m_TU.m_TexPic = gRenDev->m_TexMan->m_Text_Atten1D; else Tex->m_TU.m_TexPic = mfLoadResourceTexture("Textures/Defaults/PointLight1D", RS.m_TexturePath.c_str(), Tex->m_TU.GetTexFlags(), Tex->m_TU.GetTexFlags2(), eTT_Base, NULL, Tex); } } } } if (RS.m_LMaterial) RS.m_LMaterial = SLightMaterial::mfAdd(NULL, RS.m_LMaterial); int nFree = -1; for (i=1; im_ShaderParams.Num()) break; continue; } if (!bShare || Res->m_ShaderParams.Num()) continue; if (RS.m_ResFlags == pSR->m_ResFlags && RS.m_LMaterial == pSR->m_LMaterial && RS.m_Opacity == pSR->m_Opacity && RS.m_AlphaRef == pSR->m_AlphaRef && !stricmp(RS.m_TexturePath.c_str(), pSR->m_TexturePath.c_str())) { for (j=0; jm_Textures[j] || pSR->m_Textures[j]->m_Name.empty()) { if (RS.m_Textures[j].m_Name.empty()) continue; break; } else if (RS.m_Textures[j].m_Name.empty()) break; if (RS.m_Textures[j] != *pSR->m_Textures[j]) break; } if (j == EFTT_MAX) { pSR->m_nRefCounter++; SAFE_RELEASE(RS.m_LMaterial); return pSR; } } } SRenderShaderResources *pSR = new SRenderShaderResources(&RS); pSR->m_nRefCounter = 1; pSR->m_nCheckedTemplates = 0; if (!SShader::m_ShaderResources_known.Num()) { SShader::m_ShaderResources_known.AddIndex(1); SRenderShaderResources *pSRNULL = new SRenderShaderResources; pSRNULL->m_nRefCounter = 1; SShader::m_ShaderResources_known[0] = pSRNULL; } else if (SShader::m_ShaderResources_known.Num() >= MAX_SHADER_RES) { Warning( 0,0,"ERROR: CShader::mfCreateShaderResources: MAX_SHADER_RESOURCES hit"); return SShader::m_ShaderResources_known[1]; } if (nFree > 0) { pSR->m_Id = nFree; SShader::m_ShaderResources_known[nFree] = pSR; } else { pSR->m_Id = SShader::m_ShaderResources_known.Num(); SShader::m_ShaderResources_known.AddElem(pSR); } pSR->PostLoad(); return pSR; } void CShader::mfShaderNameForAlias(const char *nameAlias, char *nameEf, int nSize) { CName cn = CName(nameAlias, eFN_Find); SNameAlias *na; int i; strncpy(nameEf, nameAlias, nSize); if (cn.GetIndex()) { for (i=0; im_Alias == cn) break; } if (im_Name.c_str(), nSize); cn = CName(nameEf, eFN_Find); for (i=0; im_Alias == cn) break; } if (im_Name.c_str(), nSize); } } SShaderItem CShader::mfShaderItemForName (const char *nameEf, EShClass Class, bool bShare, const char *tmplName, int flags, const SInputShaderResources *Res, uint64 nMaskGen) { SShaderItem SI; SLightMaterial mtl; if (Res && !Res->m_LMaterial) { SInputShaderResources *pRes = (SInputShaderResources *)Res; int nQBM = CRenderer::CV_r_Quality_BumpMapping; if (((gRenDev->GetFeatures() & RFT_HW_MASK) == RFT_HW_GF2) || nQBM == 0) pRes->m_LMaterial = &mtl; } SI.m_pShaderResources = mfCreateShaderResources(Res, bShare); m_pCurResources = SI.m_pShaderResources; char sNewShaderName[256]=""; char templName[256]; if (tmplName && tmplName[0]) mfShaderNameForAlias(tmplName, templName, 256); else templName[0] = 0; SI.m_pShader = mfForName(nameEf, Class, flags, Res, 0); int n = 0; while (true) { bool bTryNew = false; SEfTemplates *eft = SI.m_pShader->GetTemplates(); if (eft && eft->m_TemplShaders.Num() && eft->m_TemplShaders[EFT_DEFAULT]) { if (!templName) bTryNew = true; else { SShader *pSH = eft->m_TemplShaders[EFT_DEFAULT]; if (stricmp(pSH->GetName(), templName) != 0) bTryNew = true; } } else if ((SI.m_pShader->GetFlags3() & EF3_NOTEMPLATE) && templName) bTryNew = true; if (!bTryNew) break; n++; sprintf(sNewShaderName, "%s_%d", nameEf, n); int Flags3 = SI.m_pShader->GetFlags3(); SI.m_pShader->Release(); SI.m_pShader = mfForName(sNewShaderName, Class, flags, Res, 0); SI.m_pShader->SetFlags3(SI.m_pShader->GetFlags3() | (Flags3 & EF3_NODRAW)); } if (templName && templName[0]) { int nTemp = EFT_DEFAULT; if(!SI.m_pShader->AddTemplate(SI.m_pShaderResources, nTemp, templName, true, nMaskGen)) { iLog->Log("Error: Specified shader template not found: %s\nFull material name: %s", templName, nameEf); SI.m_pShader->SetFlags3(EF3_NOTEMPLATE); } } else SI.m_pShader->SetFlags3(EF3_NOTEMPLATE); SI.m_pShaderResources = m_pCurResources; SI.m_pShaderResources->PostLoad(); m_pCurResources = NULL; return SI; } //================================================================================================= STexPic *CShader::mfCheckTemplateTexName(char *mapname, ETexType eTT, short &nFlags) { STexPic *TexPic = NULL; if (mapname[0] != '$') return NULL; if (!stricmp(mapname, "$NormalizeCubemap") || !stricmp(mapname, "$NormalizationCubemap")) TexPic = gRenDev->m_TexMan->m_Text_NormalizeCMap; else if (!stricmp(mapname, "$Lightmap")) TexPic = &gRenDev->m_TexMan->m_Templates[EFTT_LIGHTMAP]; else if (!stricmp(mapname, "$LightmapDirection")) TexPic = &gRenDev->m_TexMan->m_Templates[EFTT_LIGHTMAP_DIR]; else if (!strnicmp(mapname, "$VFog", 4)) TexPic = gRenDev->m_TexMan->m_Text_VFog; else if (!strnicmp(mapname, "$FogEnter", 8)) TexPic = gRenDev->m_TexMan->m_Text_Fog_Enter; else if (!strnicmp(mapname, "$Fog", 4)) TexPic = gRenDev->m_TexMan->m_Text_Fog; else if (!strnicmp(mapname, "$Flare", 6)) TexPic = gRenDev->m_TexMan->m_Text_Flare; else if (!stricmp(mapname, "$LightCubemap")) TexPic = gRenDev->m_TexMan->m_Text_LightCMap; else if (!stricmp(mapname, "$FromRE") || !stricmp(mapname, "$FromRE0")) TexPic = gRenDev->m_TexMan->m_Text_FromRE[0]; else if (!stricmp(mapname, "$FromRE1")) TexPic = gRenDev->m_TexMan->m_Text_FromRE[1]; else if (!stricmp(mapname, "$FromRE2")) TexPic = gRenDev->m_TexMan->m_Text_FromRE[2]; else if (!stricmp(mapname, "$FromRE3")) TexPic = gRenDev->m_TexMan->m_Text_FromRE[3]; else if (!stricmp(mapname, "$FromRE4")) TexPic = gRenDev->m_TexMan->m_Text_FromRE[4]; else if (!stricmp(mapname, "$FromRE5")) TexPic = gRenDev->m_TexMan->m_Text_FromRE[5]; else if (!stricmp(mapname, "$FromRE6")) TexPic = gRenDev->m_TexMan->m_Text_FromRE[6]; else if (!stricmp(mapname, "$FromRE7")) TexPic = gRenDev->m_TexMan->m_Text_FromRE[7]; else if (!stricmp(mapname, "$FromObj") || !stricmp(mapname, "$FromObj0")) TexPic = gRenDev->m_TexMan->m_Text_FromObj; else if (!stricmp(mapname, "$FromLight")) TexPic = gRenDev->m_TexMan->m_Text_FromLight; else if (!strnicmp(mapname, "$Phong_", 7)) { int n = atoi(&mapname[7]); TexPic = gRenDev->EF_MakePhongTexture(n); } else if (!strnicmp(mapname, "$Phong", 6)) { TexPic = &gRenDev->m_TexMan->m_Templates[EFTT_PHONG]; } else if (!stricmp(mapname, "$WhiteShadow")) TexPic = gRenDev->m_TexMan->LoadTexture(*gRenDev->m_TexMan->m_Text_WhiteShadow->m_SearchName, 0, FT2_NOANISO, eTT); else if (!strnicmp(mapname, "$White", 6)) TexPic = gRenDev->m_TexMan->LoadTexture(*gRenDev->m_TexMan->m_Text_White->m_SearchName, 0, FT2_NOANISO, eTT); else if (!strnicmp(mapname, "$EnvCMap", 8) || !stricmp(mapname, "$EnvironmentCubeMap")) TexPic = gRenDev->m_TexMan->m_Text_EnvCMap; else if (!strnicmp(mapname, "$EnvLightCMap", 13) || !stricmp(mapname, "$EnvironmentLightCubeMap")) TexPic = gRenDev->m_TexMan->m_Text_EnvLCMap; else if (!stricmp(mapname, "$Ghost")) TexPic = gRenDev->m_TexMan->m_Text_Ghost; else if (!stricmp(mapname, "$RainMap")) TexPic = gRenDev->m_TexMan->m_Text_RainMap; else if (!strnicmp(mapname, "$EnvTex", 7) || !stricmp(mapname, "$EnvironmentTexture")) TexPic = gRenDev->m_TexMan->m_Text_EnvTex; else if (!strnicmp(mapname, "$EnvScr", 7) || !stricmp(mapname, "$EnvironmentScreen")) TexPic = gRenDev->m_TexMan->m_Text_EnvScr; else if (!strnicmp(mapname, "$WaterMap", 9)) TexPic = gRenDev->m_TexMan->m_Text_WaterMap; else if (!strnicmp(mapname, "$CustomCMap", 11)) { int n; if (mapname[11] == '_') n = atoi(&mapname[12]); else n = atoi(&mapname[11]); TexPic = gRenDev->m_TexMan->m_CustomCMaps[n].m_Tex; } else if (!strnicmp(mapname, "$CustomTexture", 14)) { int n; if (mapname[11] == '_') n = atoi(&mapname[12]); else n = atoi(&mapname[11]); TexPic = gRenDev->m_TexMan->m_CustomTextures[n].m_Tex; } else if (!stricmp(mapname, "$Diffuse")) TexPic = &gRenDev->m_TexMan->m_Templates[EFTT_DIFFUSE]; else if (!stricmp(mapname, "$DecalOverlay")) TexPic = &gRenDev->m_TexMan->m_Templates[EFTT_DECAL_OVERLAY]; else if (!stricmp(mapname, "$Detail")) TexPic = &gRenDev->m_TexMan->m_Templates[EFTT_DETAIL_OVERLAY]; else if (!stricmp(mapname, "$Opacity")) TexPic = &gRenDev->m_TexMan->m_Templates[EFTT_OPACITY]; else if (!strnicmp(mapname, "$Specular", 9)) TexPic = &gRenDev->m_TexMan->m_Templates[EFTT_SPECULAR]; else if (!stricmp(mapname, "$Attenuation2D")) TexPic = &gRenDev->m_TexMan->m_Templates[EFTT_ATTENUATION2D]; else if (!stricmp(mapname, "$Attenuation1D")) TexPic = &gRenDev->m_TexMan->m_Templates[EFTT_ATTENUATION1D]; else if (!strnicmp(mapname, "$BumpPlants", 11)) { TexPic = &gRenDev->m_TexMan->m_Templates[EFTT_BUMP]; nFlags |= FTU_BUMPPLANTS; } else if (!strnicmp(mapname, "$BumpDiffuse", 12)) TexPic = &gRenDev->m_TexMan->m_Templates[EFTT_BUMP_DIFFUSE]; else if (!strnicmp(mapname, "$BumpHeight", 10)) TexPic = &gRenDev->m_TexMan->m_Templates[EFTT_BUMP_HEIGHT]; else if (!strnicmp(mapname, "$Bump", 5)) TexPic = &gRenDev->m_TexMan->m_Templates[EFTT_BUMP]; else if (!strnicmp(mapname, "$Subsurface", 11)) TexPic = &gRenDev->m_TexMan->m_Templates[EFTT_SUBSURFACE]; else if (!stricmp(mapname, "$Cubemap")) TexPic = &gRenDev->m_TexMan->m_Templates[EFTT_CUBEMAP]; else if (!strnicmp(mapname, "$Occlusion", 10)) TexPic = &gRenDev->m_TexMan->m_Templates[EFTT_OCCLUSION]; else if (!strnicmp(mapname, "$Gloss", 6)) TexPic = &gRenDev->m_TexMan->m_Templates[EFTT_GLOSS]; else // tiago: added if (!stricmp(mapname, "$FlashBangMap")) TexPic = gRenDev->m_TexMan->m_Text_FlashBangMap; else if (!stricmp(mapname, "$ScreenTexMap")) TexPic = gRenDev->m_TexMan->m_Text_ScreenMap; else if (!stricmp(mapname, "$PrevScreenTexMap")) TexPic = gRenDev->m_TexMan->m_Text_PrevScreenMap; else if (!stricmp(mapname, "$ScreenLuminosityMap")) TexPic = gRenDev->m_TexMan->m_Text_ScreenLuminosityMap; else if (!stricmp(mapname, "$ScreenCurrLuminosityMap")) TexPic = gRenDev->m_TexMan->m_Text_ScreenCurrLuminosityMap; else if (!stricmp(mapname, "$ScreenLowMap")) TexPic = gRenDev->m_TexMan->m_Text_ScreenLowMap; else if (!stricmp(mapname, "$ScreenAvg1x1")) TexPic = gRenDev->m_TexMan->m_Text_ScreenAvg1x1; else if (!stricmp(mapname, "$DofTexMap")) TexPic = gRenDev->m_TexMan->m_Text_DofMap; return TexPic; } bool CShader::mfCheckAnimatedSequence(SShaderTexUnit *tl, STexPic *tx) { if (tl->m_AnimInfo) return false; if (!tx) tx = tl->m_TexPic; if (!tx || (tx->m_Flags & FT_NOTFOUND)) return true; if (!tx->m_NextTxt) return true; STexAnim *ta = new STexAnim; ta->m_bLoop = true; STexPic *tp = tx; while (tp) { ta->m_Time = tp->m_fAnimSpeed; ta->m_TexPics.AddElem(tp); tp = tp->m_NextTxt; } ta->m_NumAnimTexs = ta->m_TexPics.Num(); tl->m_AnimInfo = ta; tl->m_TexPic = tx; return false; } STexPic *CShader::mfTryToLoadTexture(const char *nameTex, int Flags, int Flags2, byte eTT, SShader *sh, float fAmount1, float fAmount2) { STexPic *tx = NULL; if (nameTex && (strchr(nameTex, '#') && !strstr(nameTex, " #")) || (strchr(nameTex, '$') && !strstr(nameTex, " $"))) // test for " #" to skip max material names { TArray Texs; int n = mfReadTexSequence(sh, Texs, nameTex, eTT, Flags, Flags2, fAmount1, fAmount2); if (n > 1) { STexPic *tp = NULL; for (int j=0; jm_NextTxt = NULL; } else tp->m_NextTxt = t; tp = t; } } } if (!tx) { tx = (STexPic *)gRenDev->EF_LoadTexture(nameTex, Flags, Flags2, eTT, fAmount1, fAmount2); tx->m_NextTxt = NULL; } return tx; } STexPic *CShader::mfLoadResourceTexture(const char *nameTex, const char *path, int Flags, int Flags2, byte eTT, SShader *sh, SEfResTexture *Tex, float fAmount1, float fAmount2) { STexPic *tx = mfTryToLoadTexture(nameTex, Flags, Flags2, eTT, sh, fAmount1, fAmount2); if ((!tx || !tx->IsTextureLoaded()) && nameTex && path) { if (strnicmp(nameTex, path, strlen(path))) { if (tx) tx->Release(false); char name[256]; char ext[32]; char pname[256]; char *pPath = (char *)path; size_t ln = strlen(nameTex); size_t lp = strlen(path); if (ln + lp >= 250) { Warning( VALIDATOR_FLAG_TEXTURE,nameTex,"Warning: Too long texture name (path: '%s', name: '%s')\n", path, nameTex); pPath = "Textures\\"; } _splitpath(nameTex, NULL, NULL, name, ext); strcat(name, ext); UsePath((char *)name, (char *)pPath, pname); tx = mfTryToLoadTexture(pname, Flags, Flags2, eTT, sh, fAmount1, fAmount2); if ((!tx || !tx->IsTextureLoaded()) && nameTex && path) { if (tx) tx->Release(false); strcpy(name, pPath); strcat(name, nameTex); tx = mfTryToLoadTexture(name, Flags, Flags2, eTT, sh, fAmount1, fAmount2); } } } if (Tex && tx && tx->IsTextureLoaded()) { mfCheckAnimatedSequence(&Tex->m_TU, tx); if (!strchr(tx->m_SourceName.c_str(), '+')) Tex->m_Name = tx->m_SourceName; } return tx; } void CShader::mfCheckShaderResTextures(TArray &Dst, SShader *ef, SRenderShaderResources *Res) { const char *patch = Res->m_TexturePath.c_str(); SEfResTexture *Tex; for (int i=0; im_TexMan->m_Templates[EFTT_DIFFUSE]) { if (!Res->m_Textures[EFTT_DIFFUSE]) { Warning( VALIDATOR_FLAG_TEXTURE,0,"WARNING: Missed texture '%s' for shader template '%s'", mfTemplateTexIdToName(EFTT_DIFFUSE), ef->m_Name.c_str()); Res->AddTextureMap(EFTT_DIFFUSE); } Tex = Res->m_Textures[EFTT_DIFFUSE]; if (!Tex->m_TU.m_TexPic) { Tex->m_TU.m_TexPic = mfLoadResourceTexture(Tex->m_Name.c_str(), patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT_Base, ef, Tex); if (Tex->m_TU.m_TexPic && Tex->m_TU.m_TexPic->IsTextureLoaded()) Tex->m_TU.m_TexPic->m_Flags2 |= FT2_DIFFUSETEXTURE; } else mfCheckAnimatedSequence(&Res->m_Textures[EFTT_DIFFUSE]->m_TU, Res->m_Textures[EFTT_DIFFUSE]->m_TU.m_TexPic); } else if (Dst[i].m_TUnits[j].m_TexPic == &gRenDev->m_TexMan->m_Templates[EFTT_PHONG]) { if (!Res->m_Textures[EFTT_PHONG]) { Res->AddTextureMap(EFTT_PHONG); Tex = Res->m_Textures[EFTT_PHONG]; if (!Tex->m_TU.m_TexPic) { float n = CRenderer::CV_r_shininess; if (Res->m_LMaterial) n = Res->m_LMaterial->Front.m_SpecShininess; Tex->m_TU.m_TexPic = gRenDev->EF_MakePhongTexture((int)n); } } } else if (Dst[i].m_TUnits[j].m_TexPic == &gRenDev->m_TexMan->m_Templates[EFTT_GLOSS]) { if (!Res->m_Textures[EFTT_GLOSS]) { Warning( VALIDATOR_FLAG_TEXTURE,0,"WARNING: Missed texture '%s' for shader template '%s'", mfTemplateTexIdToName(EFTT_GLOSS), ef->m_Name.c_str()); Res->AddTextureMap(EFTT_GLOSS); } Tex = Res->m_Textures[EFTT_GLOSS]; if (!Tex->m_TU.m_TexPic) { if (!Tex->m_Name.empty()) Tex->m_TU.m_TexPic = mfLoadResourceTexture(Tex->m_Name.c_str(), patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT_Base, ef, Tex); if (!Tex->m_TU.m_TexPic || !Tex->m_TU.m_TexPic->IsTextureLoaded()) { if (!stricmp(CRenderer::CV_r_glossdefault->GetString(), "$Diffuse")) Tex->m_TU.m_TexPic = mfLoadResourceTexture(Res->m_Textures[EFTT_DIFFUSE]->m_Name.c_str(), patch, Res->m_Textures[EFTT_DIFFUSE]->m_TU.GetTexFlags() | Flags, Res->m_Textures[EFTT_DIFFUSE]->m_TU.GetTexFlags2(), eTT_Base, ef, Res->m_Textures[EFTT_GLOSS]); else Tex->m_TU.m_TexPic = mfLoadResourceTexture(CRenderer::CV_r_glossdefault->GetString(), patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT_Base, ef, Tex); } } } else if (Dst[i].m_TUnits[j].m_TexPic == &gRenDev->m_TexMan->m_Templates[EFTT_DETAIL_OVERLAY]) { if (!Res->m_Textures[EFTT_DETAIL_OVERLAY]) Warning( VALIDATOR_FLAG_TEXTURE,0,"WARNING: Missed texture '%s' for shader template '%s'", mfTemplateTexIdToName(EFTT_DETAIL_OVERLAY), ef->m_Name.c_str()); else { Tex = Res->m_Textures[EFTT_DETAIL_OVERLAY]; if (!Tex->m_TU.m_TexPic) { Tex->m_TU.m_TexPic = mfLoadResourceTexture(Tex->m_Name.c_str(), patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT_Base, ef, Tex); if (!Tex->m_TU.m_TexPic->IsTextureLoaded()) { Tex->m_TU.m_TexPic = mfLoadResourceTexture(CRenderer::CV_r_detaildefault->GetString(), patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT_Base, ef, Tex); if (!Tex->m_TU.m_TexPic->IsTextureLoaded()) Tex->m_TU.m_TexPic = mfLoadResourceTexture("detail/dirty", patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT_Base, ef, Tex); } } } } else if (Dst[i].m_TUnits[j].m_TexPic == &gRenDev->m_TexMan->m_Templates[EFTT_OPACITY]) { if (!Res->m_Textures[EFTT_OPACITY]) Warning( VALIDATOR_FLAG_TEXTURE,0,"WARNING: Missed texture '%s' for shader template '%s'", mfTemplateTexIdToName(EFTT_OPACITY), ef->m_Name.c_str()); else { Tex = Res->m_Textures[EFTT_OPACITY]; if (!Tex->m_TU.m_TexPic) { Tex->m_TU.m_TexPic = mfLoadResourceTexture(Tex->m_Name.c_str(), patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT_Base, ef, Tex); if (!Tex->m_TU.m_TexPic->IsTextureLoaded()) { Tex->m_TU.m_TexPic = mfLoadResourceTexture(CRenderer::CV_r_opacitydefault->GetString(), patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT_Base, ef, Tex); if (!Tex->m_TU.m_TexPic->IsTextureLoaded()) Tex->m_TU.m_TexPic = mfLoadResourceTexture("Textures/white", patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT_Base, ef, Tex); } } } } else if (Dst[i].m_TUnits[j].m_TexPic == &gRenDev->m_TexMan->m_Templates[EFTT_SPECULAR]) { if (!Res->m_Textures[EFTT_SPECULAR]) Warning( VALIDATOR_FLAG_TEXTURE,0,"WARNING: Missed texture '%s' for shader template '%s'", mfTemplateTexIdToName(EFTT_SPECULAR), ef->m_Name.c_str()); else { Tex = Res->m_Textures[EFTT_SPECULAR]; if (!Tex->m_TU.m_TexPic) { Tex->m_TU.m_TexPic = mfLoadResourceTexture(Tex->m_Name.c_str(), patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT_Base, ef, Tex); if (!Tex->m_TU.m_TexPic->IsTextureLoaded()) { if (Res->m_Textures[EFTT_DIFFUSE]) Tex->m_TU.m_TexPic = mfLoadResourceTexture(Res->m_Textures[EFTT_DIFFUSE]->m_Name.c_str(), patch, Res->m_Textures[EFTT_DIFFUSE]->m_TU.GetTexFlags() | Flags, Res->m_Textures[EFTT_DIFFUSE]->m_TU.GetTexFlags2(), eTT_Base, ef, Tex); } } } } else if (Dst[i].m_TUnits[j].m_TexPic == &gRenDev->m_TexMan->m_Templates[EFTT_BUMP]) { if (Res->m_Textures[EFTT_BUMP] && Res->m_Textures[EFTT_NORMALMAP]) { char fullname[256]; sprintf(fullname, "%s+norm_%s", Res->m_Textures[EFTT_BUMP]->m_Name.c_str(), Res->m_Textures[EFTT_NORMALMAP]->m_Name.c_str()); Res->m_Textures[EFTT_BUMP]->m_TU.m_TexPic = mfLoadResourceTexture(fullname, patch, Res->m_Textures[EFTT_BUMP]->m_TU.GetTexFlags() | Flags, Res->m_Textures[EFTT_BUMP]->m_TU.GetTexFlags2(), eTT_Bumpmap, ef, Res->m_Textures[EFTT_BUMP], (float)Res->m_Textures[EFTT_BUMP]->m_Amount, (float)Res->m_Textures[EFTT_NORMALMAP]->m_Amount); } if (!Res->m_Textures[EFTT_BUMP]) Res->AddTextureMap(EFTT_BUMP); Tex = Res->m_Textures[EFTT_BUMP]; if (!Tex->m_TU.m_TexPic || !Tex->m_TU.m_TexPic->IsTextureLoaded()) { Tex = Res->m_Textures[EFTT_BUMP]; if (!Tex->m_Name.empty()) Tex->m_TU.m_TexPic = mfLoadResourceTexture(Tex->m_Name.c_str(), patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT_Bumpmap, ef, Tex, (float)Tex->m_Amount); if (!Tex->m_TU.m_TexPic || !Tex->m_TU.m_TexPic->IsTextureLoaded()) { if (Res->m_Textures[EFTT_NORMALMAP]) Tex->m_TU.m_TexPic = mfLoadResourceTexture(Res->m_Textures[EFTT_NORMALMAP]->m_Name.c_str(), patch, Res->m_Textures[EFTT_NORMALMAP]->m_TU.GetTexFlags() | Flags, Res->m_Textures[EFTT_NORMALMAP]->m_TU.GetTexFlags2(), eTT_Bumpmap, ef, Res->m_Textures[EFTT_BUMP], (float)Res->m_Textures[EFTT_NORMALMAP]->m_Amount); } if (!Tex->m_TU.m_TexPic || !Tex->m_TU.m_TexPic->IsTextureLoaded()) { Tex->m_TU.m_nFlags |= FTU_NOBUMP; if (!(Tex->m_TU.m_nFlags & FTU_BUMPPLANTS)) Tex->m_TU.m_TexPic = mfLoadResourceTexture("Textures/white_ddn", patch, Flags, 0, eTT_Bumpmap, ef, Tex); else Tex->m_TU.m_TexPic = mfLoadResourceTexture("Textures/white_ddn", patch, Flags, 0, eTT_Bumpmap, ef, Tex); } } } else if (Dst[i].m_TUnits[j].m_TexPic == &gRenDev->m_TexMan->m_Templates[EFTT_DECAL_OVERLAY]) { if (!Res->m_Textures[EFTT_DECAL_OVERLAY]) Res->AddTextureMap(EFTT_DECAL_OVERLAY); Tex = Res->m_Textures[EFTT_DECAL_OVERLAY]; if (!Tex->m_TU.m_TexPic || !Tex->m_TU.m_TexPic->IsTextureLoaded()) { if (!Tex->m_Name.empty()) Tex->m_TU.m_TexPic = mfLoadResourceTexture(Tex->m_Name.c_str(), patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT_Base, ef, Tex, (float)Tex->m_Amount); else Tex->m_TU.m_TexPic = mfLoadResourceTexture("Textures/white", patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT_Base, ef, Tex, (float)Tex->m_Amount); } } else if (Dst[i].m_TUnits[j].m_TexPic == &gRenDev->m_TexMan->m_Templates[EFTT_ATTENUATION2D]) { if (!Res->m_Textures[EFTT_ATTENUATION2D]) Res->AddTextureMap(EFTT_ATTENUATION2D); Tex = Res->m_Textures[EFTT_ATTENUATION2D]; if (!Tex->m_TU.m_TexPic) { if (!Tex->m_Name.empty()) Tex->m_TU.m_TexPic = mfLoadResourceTexture(Tex->m_Name.c_str(), patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT_Base, ef, Tex); if (!Tex->m_TU.m_TexPic->IsTextureLoaded()) Tex->m_TU.m_TexPic = mfLoadResourceTexture("Textures/Defaults/PointLight2D", patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT_Base, ef, Tex); } } else if (Dst[i].m_TUnits[j].m_TexPic == &gRenDev->m_TexMan->m_Templates[EFTT_SUBSURFACE]) { if (!Res->m_Textures[EFTT_SUBSURFACE]) Warning( VALIDATOR_FLAG_TEXTURE,0,"WARNING: Missed texture '%s' for shader template '%s'", mfTemplateTexIdToName(EFTT_SUBSURFACE), ef->m_Name.c_str()); else { Tex = Res->m_Textures[EFTT_SUBSURFACE]; if (!Tex->m_TU.m_TexPic) { Tex->m_TU.m_TexPic = mfLoadResourceTexture(Tex->m_Name.c_str(), patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT_Base, ef, Tex); if (!Tex->m_TU.m_TexPic->IsTextureLoaded()) { Tex->m_TU.m_TexPic = NULL; } } } } else if (Dst[i].m_TUnits[j].m_TexPic == &gRenDev->m_TexMan->m_Templates[EFTT_ATTENUATION1D]) { if (!Res->m_Textures[EFTT_ATTENUATION1D]) Res->AddTextureMap(EFTT_ATTENUATION1D); Tex = Res->m_Textures[EFTT_ATTENUATION1D]; if (!Tex->m_TU.m_TexPic) { if (!Tex->m_Name.empty()) Tex->m_TU.m_TexPic = mfLoadResourceTexture(Tex->m_Name.c_str(), patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT_Base, ef, Tex); if (!Tex->m_TU.m_TexPic || !Tex->m_TU.m_TexPic->IsTextureLoaded()) { if (gRenDev->m_TexMan->m_Text_Atten1D) Tex->m_TU.m_TexPic = gRenDev->m_TexMan->m_Text_Atten1D; else Tex->m_TU.m_TexPic = mfLoadResourceTexture("Textures/Defaults/PointLight1D", patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT_Base, ef, Tex); } } } else if (Dst[i].m_TUnits[j].m_TexPic == &gRenDev->m_TexMan->m_Templates[EFTT_CUBEMAP]) { if (!Res->m_Textures[EFTT_CUBEMAP]) { Warning( VALIDATOR_FLAG_TEXTURE,0,"WARNING: Missed texture '%s' for shader template '%s'", mfTemplateTexIdToName(EFTT_CUBEMAP), ef->m_Name.c_str()); Res->AddTextureMap(EFTT_CUBEMAP); } Tex = Res->m_Textures[EFTT_CUBEMAP]; if (!Tex->m_TU.m_TexPic) { Tex->m_TU.m_TexPic = mfLoadResourceTexture(Tex->m_Name.c_str(), patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT_Cubemap, ef, Tex); if (!Tex->m_TU.m_TexPic->IsTextureLoaded()) { Tex->m_TU.m_TexPic = mfLoadResourceTexture("Textures/Defaults/DefaultCM", patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT_Cubemap, ef, Tex); } } } } } } void CShader::mfCheckShaderResTexturesHW(TArray &Dst, SShader *ef, SRenderShaderResources *Res) { const char *patch = Res->m_TexturePath.c_str(); SEfResTexture *Tex; for (int i=0; im_TexMan->m_Templates[EFTT_DIFFUSE]) { if (!Res->m_Textures[EFTT_DIFFUSE]) { Warning( VALIDATOR_FLAG_TEXTURE,0,"WARNING: Missed texture '%s' for shader template '%s'", mfTemplateTexIdToName(EFTT_DIFFUSE), ef->m_Name.c_str()); Res->AddTextureMap(EFTT_DIFFUSE); } Tex = Res->m_Textures[EFTT_DIFFUSE]; if (!Tex->m_TU.m_TexPic) { Tex->m_TU.m_TexPic = mfLoadResourceTexture(Tex->m_Name.c_str(), patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), Tex->m_TU.m_eTexType, ef, Tex); if (Tex->m_TU.m_TexPic && Tex->m_TU.m_TexPic->IsTextureLoaded()) Tex->m_TU.m_TexPic->m_Flags2 |= FT2_DIFFUSETEXTURE; } else mfCheckAnimatedSequence(&Res->m_Textures[EFTT_DIFFUSE]->m_TU, Res->m_Textures[EFTT_DIFFUSE]->m_TU.m_TexPic); } else if (Dst[i].m_TUnits[j].m_TexPic == &gRenDev->m_TexMan->m_Templates[EFTT_PHONG]) { if (!Res->m_Textures[EFTT_PHONG]) { Res->AddTextureMap(EFTT_PHONG); Tex = Res->m_Textures[EFTT_PHONG]; if (!Tex->m_TU.m_TexPic) { float n = CRenderer::CV_r_shininess; if (Res->m_LMaterial) n = Res->m_LMaterial->Front.m_SpecShininess; Tex->m_TU.m_TexPic = gRenDev->EF_MakePhongTexture((int)n); } } } else if (Dst[i].m_TUnits[j].m_TexPic == &gRenDev->m_TexMan->m_Templates[EFTT_GLOSS]) { if (!Res->m_Textures[EFTT_GLOSS]) { Warning( VALIDATOR_FLAG_TEXTURE,0,"WARNING: Missed texture '%s' for shader template '%s'", mfTemplateTexIdToName(EFTT_GLOSS), ef->m_Name.c_str()); Res->AddTextureMap(EFTT_GLOSS); } Tex = Res->m_Textures[EFTT_GLOSS]; if (!Tex->m_TU.m_TexPic) { if (!Tex->m_Name.empty()) Tex->m_TU.m_TexPic = mfLoadResourceTexture(Tex->m_Name.c_str(), patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT_Base, ef, Tex); if (!Tex->m_TU.m_TexPic || !Tex->m_TU.m_TexPic->IsTextureLoaded()) { if (!stricmp(CRenderer::CV_r_glossdefault->GetString(), "$Diffuse")) Tex->m_TU.m_TexPic = mfLoadResourceTexture(Res->m_Textures[EFTT_DIFFUSE]->m_Name.c_str(), patch, Res->m_Textures[EFTT_DIFFUSE]->m_TU.GetTexFlags() | Flags, Res->m_Textures[EFTT_DIFFUSE]->m_TU.GetTexFlags2(), eTT_Base, ef, Res->m_Textures[EFTT_GLOSS]); else Tex->m_TU.m_TexPic = mfLoadResourceTexture(CRenderer::CV_r_glossdefault->GetString(), patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT_Base, ef, Tex); } } } else if (Dst[i].m_TUnits[j].m_TexPic == &gRenDev->m_TexMan->m_Templates[EFTT_DETAIL_OVERLAY]) { if (!Res->m_Textures[EFTT_DETAIL_OVERLAY]) Warning( VALIDATOR_FLAG_TEXTURE,0,"WARNING: Missed texture '%s' for shader template '%s'", mfTemplateTexIdToName(EFTT_DETAIL_OVERLAY), ef->m_Name.c_str()); else { Tex = Res->m_Textures[EFTT_DETAIL_OVERLAY]; if (!Tex->m_TU.m_TexPic) { Tex->m_TU.m_TexPic = mfLoadResourceTexture(Tex->m_Name.c_str(), patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT_Base, ef, Tex); if (!Tex->m_TU.m_TexPic->IsTextureLoaded()) { Tex->m_TU.m_TexPic = mfLoadResourceTexture(CRenderer::CV_r_detaildefault->GetString(), patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT_Base, ef, Tex); if (!Tex->m_TU.m_TexPic->IsTextureLoaded()) Tex->m_TU.m_TexPic = mfLoadResourceTexture("detail/dirty", patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT_Base, ef, Tex); } } } } else if (Dst[i].m_TUnits[j].m_TexPic == &gRenDev->m_TexMan->m_Templates[EFTT_OPACITY]) { if (!Res->m_Textures[EFTT_OPACITY]) Warning( VALIDATOR_FLAG_TEXTURE,0,"WARNING: Missed texture '%s' for shader template '%s'", mfTemplateTexIdToName(EFTT_OPACITY), ef->m_Name.c_str()); else { Tex = Res->m_Textures[EFTT_OPACITY]; if (!Tex->m_TU.m_TexPic) { Tex->m_TU.m_TexPic = mfLoadResourceTexture(Tex->m_Name.c_str(), patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT_Base, ef, Tex); if (!Tex->m_TU.m_TexPic->IsTextureLoaded()) { Tex->m_TU.m_TexPic = mfLoadResourceTexture(CRenderer::CV_r_opacitydefault->GetString(), patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT_Base, ef, Tex); if (!Tex->m_TU.m_TexPic->IsTextureLoaded()) Tex->m_TU.m_TexPic = mfLoadResourceTexture("Textures/white", patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT_Base, ef, Tex); } } } } else if (Dst[i].m_TUnits[j].m_TexPic == &gRenDev->m_TexMan->m_Templates[EFTT_SPECULAR]) { if (!Res->m_Textures[EFTT_SPECULAR]) Warning( VALIDATOR_FLAG_TEXTURE,0,"WARNING: Missed texture '%s' for shader template '%s'", mfTemplateTexIdToName(EFTT_SPECULAR), ef->m_Name.c_str()); else { Tex = Res->m_Textures[EFTT_SPECULAR]; if (!Tex->m_TU.m_TexPic) { Tex->m_TU.m_TexPic = mfLoadResourceTexture(Tex->m_Name.c_str(), patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT_Base, ef, Tex); if (!Tex->m_TU.m_TexPic->IsTextureLoaded()) { if (Res->m_Textures[EFTT_DIFFUSE]) Tex->m_TU.m_TexPic = mfLoadResourceTexture(Res->m_Textures[EFTT_DIFFUSE]->m_Name.c_str(), patch, Res->m_Textures[EFTT_DIFFUSE]->m_TU.GetTexFlags() | Flags, Res->m_Textures[EFTT_DIFFUSE]->m_TU.GetTexFlags2(), eTT_Base, ef, Tex); } } } } else if (Dst[i].m_TUnits[j].m_TexPic == &gRenDev->m_TexMan->m_Templates[EFTT_BUMP]) { #ifdef USE_3DC if (gRenDev->m_bDeviceSupportsComprNormalmaps && (ef->m_Flags & EF_ALLOW3DC)) { Flags |= FT_ALLOW3DC; if (CRenderer::CV_r_texnormalmapcompressed) Flags |= FT_3DC; } #endif if (Res->m_Textures[EFTT_BUMP] && !Res->m_Textures[EFTT_BUMP]->m_Name.empty() && Res->m_Textures[EFTT_NORMALMAP] && !Res->m_Textures[EFTT_NORMALMAP]->m_Name.empty()) { char fullname[512]; sprintf(fullname, "%s+norm_%s", Res->m_Textures[EFTT_BUMP]->m_Name.c_str(), Res->m_Textures[EFTT_NORMALMAP]->m_Name.c_str()); Res->m_Textures[EFTT_BUMP]->m_TU.m_TexPic = mfLoadResourceTexture(fullname, patch, Res->m_Textures[EFTT_BUMP]->m_TU.GetTexFlags() | Flags, Res->m_Textures[EFTT_BUMP]->m_TU.GetTexFlags2(), eTT_Bumpmap, ef, Res->m_Textures[EFTT_BUMP], (float)Res->m_Textures[EFTT_BUMP]->m_Amount, (float)Res->m_Textures[EFTT_NORMALMAP]->m_Amount); } if (!Res->m_Textures[EFTT_BUMP]) Res->AddTextureMap(EFTT_BUMP); Tex = Res->m_Textures[EFTT_BUMP]; if (!Tex->m_TU.m_TexPic || !Tex->m_TU.m_TexPic->IsTextureLoaded()) { Tex = Res->m_Textures[EFTT_BUMP]; ETexType eTT = Dst[i].m_TUnits[j].m_eTexType==eTT_DSDTBump ? eTT_DSDTBump : eTT_Bumpmap; if (!Tex->m_Name.empty()) Tex->m_TU.m_TexPic = mfLoadResourceTexture(Tex->m_Name.c_str(), patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT, ef, Tex, (float)Tex->m_Amount); if (!Tex->m_TU.m_TexPic || !Tex->m_TU.m_TexPic->IsTextureLoaded()) { if (Res->m_Textures[EFTT_NORMALMAP]) { Tex->m_TU.m_TexPic = mfLoadResourceTexture(Res->m_Textures[EFTT_NORMALMAP]->m_Name.c_str(), patch, Res->m_Textures[EFTT_NORMALMAP]->m_TU.GetTexFlags() | Flags, Res->m_Textures[EFTT_NORMALMAP]->m_TU.GetTexFlags2(), eTT, ef, Res->m_Textures[EFTT_BUMP], (float)Res->m_Textures[EFTT_NORMALMAP]->m_Amount); SAFE_DELETE(Res->m_Textures[EFTT_NORMALMAP]); } } if (!Tex->m_TU.m_TexPic || !Tex->m_TU.m_TexPic->IsTextureLoaded()) { Tex->m_TU.m_nFlags |= FTU_NOBUMP; if (!(Dst[i].m_TUnits[j].m_nFlags & FTU_BUMPPLANTS)) Tex->m_TU.m_TexPic = mfLoadResourceTexture("Textures/white_ddn", patch, Flags, 0, eTT_Bumpmap, ef, Tex); else Tex->m_TU.m_TexPic = mfLoadResourceTexture("Textures/white_ddn", patch, Flags, 0, eTT_Bumpmap, ef, Tex); } } } else if (Dst[i].m_TUnits[j].m_TexPic == &gRenDev->m_TexMan->m_Templates[EFTT_BUMP_DIFFUSE]) { char nameBump[256]; char nameNorm[256]; nameBump[0] = 0; nameNorm[0] = 0; if (Res->m_Textures[EFTT_BUMP] && !Res->m_Textures[EFTT_BUMP]->m_Name.empty()) { char *str; if (str=strstr(Res->m_Textures[EFTT_BUMP]->m_Name.c_str(), "_ddn")) { int nSize = str - Res->m_Textures[EFTT_BUMP]->m_Name.c_str(); memcpy(nameBump, Res->m_Textures[EFTT_BUMP]->m_Name.c_str(), nSize); memcpy(&nameBump[nSize], "_ddndif", 7); strcpy(&nameBump[nSize+7], &str[4]); FILE *fp = iSystem->GetIPak()->FOpen(nameBump, "rb"); if (!fp) nameBump[0] = 0; else iSystem->GetIPak()->FClose(fp); } if (!nameBump[0]) strcpy(nameBump, Res->m_Textures[EFTT_BUMP]->m_Name.c_str()); } if (Res->m_Textures[EFTT_NORMALMAP] && !Res->m_Textures[EFTT_NORMALMAP]->m_Name.empty()) { char *str; if (str=strstr(Res->m_Textures[EFTT_NORMALMAP]->m_Name.c_str(), "_ddn")) { int nSize = str - Res->m_Textures[EFTT_NORMALMAP]->m_Name.c_str(); memcpy(nameNorm, Res->m_Textures[EFTT_NORMALMAP]->m_Name.c_str(), nSize); memcpy(&nameNorm[nSize], "_ddndif", 7); strcpy(&nameNorm[nSize+7], &str[4]); FILE *fp = iSystem->GetIPak()->FOpen(nameNorm, "rb"); if (!fp) nameNorm[0] = 0; else iSystem->GetIPak()->FClose(fp); } if (!nameNorm[0]) strcpy(nameNorm, Res->m_Textures[EFTT_NORMALMAP]->m_Name.c_str()); } if (!Res->m_Textures[EFTT_BUMP_DIFFUSE]) Res->AddTextureMap(EFTT_BUMP_DIFFUSE); if (nameBump[0] && nameNorm[0]) { char fullname[256]; sprintf(fullname, "%s+norm_%s", nameBump, nameNorm); Res->m_Textures[EFTT_BUMP_DIFFUSE]->m_TU.m_TexPic = mfLoadResourceTexture(fullname, patch, Res->m_Textures[EFTT_BUMP]->m_TU.GetTexFlags() | Flags, Res->m_Textures[EFTT_BUMP]->m_TU.GetTexFlags2(), eTT_Bumpmap, ef, Res->m_Textures[EFTT_BUMP_DIFFUSE], (float)Res->m_Textures[EFTT_BUMP]->m_Amount, (float)Res->m_Textures[EFTT_NORMALMAP]->m_Amount); } Tex = Res->m_Textures[EFTT_BUMP_DIFFUSE]; if (!Tex->m_TU.m_TexPic || !Tex->m_TU.m_TexPic->IsTextureLoaded()) { ETexType eTT = Dst[i].m_TUnits[j].m_eTexType==eTT_DSDTBump ? eTT_DSDTBump : eTT_Bumpmap; if (nameBump[0]) Tex->m_TU.m_TexPic = mfLoadResourceTexture(nameBump, patch, Res->m_Textures[EFTT_BUMP]->m_TU.GetTexFlags() | Flags, Res->m_Textures[EFTT_BUMP]->m_TU.GetTexFlags2(), eTT, ef, Tex, (float)Res->m_Textures[EFTT_BUMP]->m_Amount); if (!Tex->m_TU.m_TexPic || !Tex->m_TU.m_TexPic->IsTextureLoaded()) { if (nameNorm[0]) Tex->m_TU.m_TexPic = mfLoadResourceTexture(nameNorm, patch, Res->m_Textures[EFTT_NORMALMAP]->m_TU.GetTexFlags() | Flags, Res->m_Textures[EFTT_NORMALMAP]->m_TU.GetTexFlags2(), eTT, ef, Tex, (float)Res->m_Textures[EFTT_NORMALMAP]->m_Amount); } if (!Tex->m_TU.m_TexPic || !Tex->m_TU.m_TexPic->IsTextureLoaded()) { Tex->m_TU.m_nFlags |= FTU_NOBUMP; Tex->m_TU.m_TexPic = mfLoadResourceTexture("Textures/white_ddn", patch, Flags, 0, eTT_Bumpmap, ef, Tex); } } } else if (Dst[i].m_TUnits[j].m_TexPic == &gRenDev->m_TexMan->m_Templates[EFTT_DECAL_OVERLAY]) { if (!Res->m_Textures[EFTT_DECAL_OVERLAY]) Res->AddTextureMap(EFTT_DECAL_OVERLAY); Tex = Res->m_Textures[EFTT_DECAL_OVERLAY]; if (!Tex->m_TU.m_TexPic || !Tex->m_TU.m_TexPic->IsTextureLoaded()) { if (!Tex->m_Name.empty()) Tex->m_TU.m_TexPic = mfLoadResourceTexture(Tex->m_Name.c_str(), patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT_Base, ef, Tex, (float)Tex->m_Amount); else Tex->m_TU.m_TexPic = mfLoadResourceTexture("Textures/white", patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT_Base, ef, Tex, (float)Tex->m_Amount); } } else if (Dst[i].m_TUnits[j].m_TexPic == &gRenDev->m_TexMan->m_Templates[EFTT_ATTENUATION2D]) { if (!Res->m_Textures[EFTT_ATTENUATION2D]) Res->AddTextureMap(EFTT_ATTENUATION2D); Tex = Res->m_Textures[EFTT_ATTENUATION2D]; if (!Tex->m_TU.m_TexPic) { if (!Tex->m_Name.empty()) Tex->m_TU.m_TexPic = mfLoadResourceTexture(Tex->m_Name.c_str(), patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT_Base, ef, Tex); if (!Tex->m_TU.m_TexPic || !Tex->m_TU.m_TexPic->IsTextureLoaded()) Tex->m_TU.m_TexPic = mfLoadResourceTexture("Textures/Defaults/PointLight2D", patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT_Base, ef, Tex); } } else if (Dst[i].m_TUnits[j].m_TexPic == &gRenDev->m_TexMan->m_Templates[EFTT_SUBSURFACE]) { if (!Res->m_Textures[EFTT_SUBSURFACE]) Warning( VALIDATOR_FLAG_TEXTURE,0,"WARNING: Missed texture '%s' for shader template '%s'", mfTemplateTexIdToName(EFTT_SUBSURFACE), ef->m_Name.c_str()); else { Tex = Res->m_Textures[EFTT_SUBSURFACE]; if (!Tex->m_TU.m_TexPic) { Tex->m_TU.m_TexPic = mfLoadResourceTexture(Tex->m_Name.c_str(), patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT_Base, ef, Tex); if (!Tex->m_TU.m_TexPic->IsTextureLoaded()) { Tex->m_TU.m_TexPic = NULL; } } } } else if (Dst[i].m_TUnits[j].m_TexPic == &gRenDev->m_TexMan->m_Templates[EFTT_ATTENUATION1D]) { if (!Res->m_Textures[EFTT_ATTENUATION1D]) Res->AddTextureMap(EFTT_ATTENUATION1D); Tex = Res->m_Textures[EFTT_ATTENUATION1D]; if (!Tex->m_TU.m_TexPic) { if (!Tex->m_Name.empty()) Tex->m_TU.m_TexPic = mfLoadResourceTexture(Tex->m_Name.c_str(), patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT_Base, ef, Tex); if (!Tex->m_TU.m_TexPic || !Tex->m_TU.m_TexPic->IsTextureLoaded()) { if (gRenDev->m_TexMan->m_Text_Atten1D) Tex->m_TU.m_TexPic = gRenDev->m_TexMan->m_Text_Atten1D; else Tex->m_TU.m_TexPic = mfLoadResourceTexture("Textures/Defaults/PointLight1D", patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT_Base, ef, Tex); } } } else if (Dst[i].m_TUnits[j].m_TexPic == &gRenDev->m_TexMan->m_Templates[EFTT_CUBEMAP]) { if (!Res->m_Textures[EFTT_CUBEMAP]) { Warning( VALIDATOR_FLAG_TEXTURE,0,"WARNING: Missed texture '%s' for shader template '%s'", mfTemplateTexIdToName(EFTT_CUBEMAP), ef->m_Name.c_str()); Res->AddTextureMap(EFTT_CUBEMAP); } Tex = Res->m_Textures[EFTT_CUBEMAP]; if (!Tex->m_TU.m_TexPic) { Tex->m_TU.m_TexPic = mfLoadResourceTexture(Tex->m_Name.c_str(), patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT_Cubemap, ef, Tex); if (!Tex->m_TU.m_TexPic->IsTextureLoaded()) { Tex->m_TU.m_TexPic = mfLoadResourceTexture("Textures/Defaults/DefaultCM", patch, Tex->m_TU.GetTexFlags() | Flags, Tex->m_TU.GetTexFlags2(), eTT_Cubemap, ef, Tex); } } } } } } bool CShader::mfSetOpacity (SShaderPass *Layer, float Opa, SShader *ef, int Mode) { if (!Layer) return false; if (Mode == 0) { Layer->m_RenderState = GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA; if (ef->m_Flags3 & EF3_DEPTHWRITE) Layer->m_RenderState |= GS_DEPTHWRITE; //if (!ef->m_LightMaterial) { if (ef->m_eSort <= eS_Opaque) ef->m_eSort = eS_SeeThrough; Layer->m_FixedColor.dcolor = -1; float opa = CLAMP(Opa, 0.0f, 1.0f); Layer->m_FixedColor.bcolor[3] = (byte)(opa * 255.0f); Layer->m_eEvalRGB = eERGB_Fixed; Layer->m_eEvalAlpha = eEALPHA_Fixed; } } else { Layer->m_RenderState = GS_BLSRC_SRCALPHA | GS_BLDST_ONE; //if (!ef->m_LightMaterial) { if (ef->m_eSort <= eS_Opaque) ef->m_eSort = eS_SeeThrough; Layer->m_FixedColor.dcolor = -1; float opa = CLAMP(Opa, 0.0f, 1.0f); Layer->m_FixedColor.bcolor[3] = (byte)(opa * 255.0f); Layer->m_eEvalRGB = eERGB_Fixed; Layer->m_eEvalAlpha = eEALPHA_Fixed; } } return true; } bool SShader::mfSetOpacity(float Opa, int Mode) { if (m_Passes.Num()) gRenDev->m_cEF.mfSetOpacity(&m_Passes[0], Opa, this, Mode); else for (int i=0; im_Passes.Num()) gRenDev->m_cEF.mfSetOpacity(&m_HWTechniques[i]->m_Passes[0], Opa, this, Mode); } if (m_Templates) { for (int i=0; im_TemplShaders.Num(); i++) { if (!m_Templates->m_TemplShaders[i]) continue; m_Templates->m_TemplShaders[i]->mfSetOpacity(Opa, Mode); } } return true; } //====================================================================================== // Templates support void SEfTemplates::mfFree(SShader *ef) { for (int i=0; iRelease(); } m_TemplShaders.Free(); delete this; } void SEfTemplates::mfSetPreferred(SShader *ef) { if (m_nPreferred >= 0 && m_TemplShaders.Num()>m_nPreferred && m_TemplShaders[m_nPreferred]) { m_Preferred = m_TemplShaders[m_nPreferred]; return; } if (m_TemplShaders.Num() > EFT_DEFAULT && m_TemplShaders[EFT_DEFAULT]) { m_Preferred = m_TemplShaders[EFT_DEFAULT]; return; } for (int i=0; im_Flags & EF_NOTFOUND) && (ef->m_Flags & EF_COMPILEDLAYERS)) { m_Preferred = ef; return; } } void SEfTemplates::mfClear(SShader *e) { for (int i=0; i= m_KnownTemplates.Num()) { m_KnownTemplates.ReserveNew(nTemplId + 1); } if (m_KnownTemplates[nTemplId].m_Name[0] && !bReplace) { Warning( 0,0,"Warning: CShader::mfRegisterTemplate: template %d already defined\n", nTemplId); return false; } strncpy(m_KnownTemplates[nTemplId].m_Name, Name, 63); // Preload shader m_KnownTemplates[nTemplId].m_pShader = mfForName(Name, eSH_World, 0, NULL); return true; } void CShader::mfUnregisterDefaultTemplates() { int i; for (i=0; im_pShader); } m_KnownTemplates.Free(); } void CShader::mfRegisterDefaultTemplates() { mfRegisterTemplate(EFT_WHITE, "White", false, true); mfRegisterTemplate(EFT_WHITESHADOW, "WhiteShadow", false, true); mfRegisterTemplate(EFT_DECAL, "TemplDecal", false, true); //mfRegisterTemplate(EFT_DETAIL_OVERLAY, "TemplDetail_Overlay", false, true); //mfRegisterTemplate(EFT_DETAIL_OVERLAY_VP, "TemplDetail_Overlay_VP", false, true); //mfRegisterTemplate(EFT_BUMP_MODEL, "TemplBumpDiffuse_NOCM", false, true); //mfRegisterTemplate(EFT_BUMP, "TemplBumpDiffuse", false, true); //mfRegisterTemplate(EFT_BUMPSPEC, "TemplBumpSpec", false, true); mfRegisterTemplate(EFT_HEATVISION, "TemplHeatVis_Sources", false, true); mfRegisterTemplate(EFT_INVLIGHT, "TemplInvLight", false, true); mfRegisterTemplate(EFT_DOF, "TemplDof", false, true); //mfRegisterTemplate(EFT_REFLECTCM, "TemplReflCM", false, true); //mfRegisterTemplate(EFT_REFLECTCMDECAL, "TemplReflCMDecal", false, true); //mfRegisterTemplate(EFT_REFLECTENVDECAL, "TemplReflEnvDecal", false, true); //mfRegisterTemplate(EFT_REFRACTCM, "TemplRefrCM", false, true); //mfRegisterTemplate(EFT_BUMPREFLECTCM, "TemplBumpReflCM", false, true); //mfRegisterTemplate(EFT_BUMPREFRACTCM, "TemplBumpRefrCM", false, true); //mfRegisterTemplate(EFT_BUMPREFLECTENVCM, "TemplBumpReflEnvCM", false, true); //mfRegisterTemplate(EFT_BUMPREFRACTENVCM, "TemplBumpRefrEnvCM", false, true); //mfRegisterTemplate(EFT_REFLECTENVCM, "TemplReflEnvCM", false, true); //mfRegisterTemplate(EFT_REFRACTENVCM, "TemplRefrEnvCM", false, true); //mfRegisterTemplate(EFT_REFRACTENVTEX, "TemplRefrEnvTex", false, true); //mfRegisterTemplate(EFT_DECALALPHATEST, "TemplDecalAlphaTestForShadows", false, true); //mfRegisterTemplate(EFT_ALPHABLENDDECAL, "TemplAlphaBlend", false, true); //mfRegisterTemplate(EFT_ENVBUMPENV2D, "TemplBumpOffsetEnv", false, true); } void CShader::mfRefreshResources(SShader *eft, SRenderShaderResources *Res) { mfCheckShaderResTextures(eft->m_Passes, eft, Res); for (int i=0; im_HWTechniques.Num(); i++) { SShaderTechnique *hs = eft->m_HWTechniques[i]; mfCheckShaderResTexturesHW(hs->m_Passes, eft, Res); } if (Res && Res->m_Textures[EFTT_BUMP] && Res->m_Textures[EFTT_BUMP]->m_TU.m_TexPic && (Res->m_Textures[EFTT_BUMP]->m_TU.m_TexPic->m_Flags & FT_3DC) && (Res->m_Textures[EFTT_BUMP]->m_TU.m_TexPic->m_Flags & FT_HASALPHA) && (eft->m_Flags & EF_OFFSETBUMP)) { const char *patch = Res->m_TexturePath.c_str(); if (!Res->m_Textures[EFTT_BUMP_HEIGHT]) Res->AddTextureMap(EFTT_BUMP_HEIGHT); Res->m_Textures[EFTT_BUMP_HEIGHT]->m_TU.m_TexPic = mfLoadResourceTexture(Res->m_Textures[EFTT_BUMP]->m_Name.c_str(), patch, Res->m_Textures[EFTT_BUMP]->m_TU.GetTexFlags() | FT_3DC | FT_3DC_A, Res->m_Textures[EFTT_BUMP]->m_TU.GetTexFlags2(), eTT_Bumpmap, eft, Res->m_Textures[EFTT_BUMP_HEIGHT], (float)Res->m_Textures[EFTT_BUMP]->m_Amount); } } bool CShader::mfAddTemplate(SRenderShaderResources *Res, SShader *ef, int IdTempl, const char *Name, uint64 nMaskGen) { if (IdTempl < 0 || IdTempl >= m_KnownTemplates.Num() && !Name) { Warning( 0,0,"Warning: CShader::mfAddTemplate: invalid template number IdTempl=%d (not registered)\n", IdTempl); return false; } if (Name && IdTempl != EFT_DEFAULT && IdTempl < EFT_USER_FIRST) { Warning( 0,0,"Warning: CShader::mfAddTemplate: you cannot rename fixed template %d\n", IdTempl); return false; } SRegTemplate *rt = NULL; if (IdTempl < EFT_USER_FIRST) rt = &m_KnownTemplates[IdTempl]; const char *name = Name; if (!name) name = rt->m_Name; if (!name || !name[0]) { if (IdTempl == EFT_DEFAULT) Warning( 0,0,"Warning: CShader::mfAddTemplate: missed name for default template\n"); else Warning( 0,0,"Warning: CShader::mfAddTemplate: template %d not registered\n", IdTempl); return false; } // Load template shader SShader *eft = mfForName(name, eSH_Misc, 0, NULL, nMaskGen); if (!eft || (eft->m_Flags & EF_NOTFOUND)) { eft->Release(); Warning( 0,0,"Warning: CShader::mfAddTemplate: Couldn't find template shader '%s' for '%s'\n", name, ef->m_Name.c_str()); return false; } ef->m_Templates->m_nMaskAuto |= (1<GetTemplate(-1); bool bSep = false; if (IdTempl == EFT_DEFAULT) { ef->m_Flags3 = eft->m_Flags3; } if (eft->m_Flags3 & (EF3_USEPARENTCULL | EF3_USEPARENTSORT)) bSep = true; if (IdTempl != EFT_DEFAULT) { if (efdt->m_Flags3 & (EF3_HASVCOLORS | EF3_HASALPHATEST | EF3_HASALPHABLEND)) bSep = true; } else { ef->m_eCull = eft->m_eCull; ef->m_eSort = eft->m_eSort; ef->m_Flags3 |= (eft->m_Flags3 & (EF3_HASVCOLORS | EF3_HASALPHATEST | EF3_HASALPHABLEND)); } if (bSep) { char nameEf[128]; char sufName[128]; strcpy(sufName, name); strlwr(sufName); sprintf(nameEf, "%s#%s", ef->m_Name.c_str(), sufName); SShader *efn = mfNewShader(eft->m_eClass, -1); int id = efn->m_Id; *efn = *eft; efn->m_Name = nameEf; efn->m_Id = id; if (efn->m_Flags3 & EF3_USEPARENTSORT) efn->m_eSort = ef->m_eSort; if (efn->m_Flags3 & EF3_USEPARENTCULL) efn->m_eCull = ef->m_eCull; efn->m_Flags3 |= (efdt->m_Flags3 & (EF3_HASVCOLORS | EF3_HASALPHATEST | EF3_HASALPHABLEND | EF3_NODRAW)); eft = efn; } if (Res) mfRefreshResources(eft, Res); ef->m_Templates->mfReserve(IdTempl); ef->m_Templates->m_TemplShaders[IdTempl] = eft; return true; } void SShader::RemoveTemplate(int TemplId) { if (!m_Templates || !m_Templates->m_TemplShaders[TemplId]) return; if (m_Templates->m_TemplShaders[TemplId] != this) m_Templates->m_TemplShaders[TemplId]->Release(); m_Templates->m_TemplShaders[TemplId] = NULL; } bool SShader::AddTemplate(SRenderShaderResources *Res, int& TemplId, const char *Name, bool bSetPreferred, uint64 nMaskGen) { bool bRes = true; bool bHasT = true; char name[128] = ""; if (m_Flags2 & (EF2_TEMPLATE | EF_SYSTEM)) return false; if (!Name && (TemplId == EFT_HEATVISION)) { if (m_Templates && m_Templates->m_TemplShaders.Num() && m_Templates->m_TemplShaders[0] && m_Templates->m_TemplShaders[0]->m_eSort > eS_Additive) return false; } if (Name && Name[0]) { strcpy(name, Name); strlwr(name); if (m_Name == name) return true; // Try to find free template slot (or already registered with the same name) if (TemplId < 0) { if (!m_Templates) TemplId = EFT_USER_FIRST; else { int nFirst = -1; int i; for (i=EFT_USER_FIRST; im_TemplShaders.Num(); i++) { SShader *sh = m_Templates->m_TemplShaders[i]; if (!sh) { nFirst = i; continue; } if (!strcmp(name, sh->m_Name.c_str())) { TemplId = i; return true; } } if (nFirst > 0) TemplId = nFirst; else TemplId = i; } if (TemplId < 0) return false; } } else if (TemplId < 0) return false; if (!m_Templates) { bHasT = false; m_Templates = new SEfTemplates; } if (Res && (!Res->m_Textures[EFTT_DIFFUSE] || Res->m_Textures[EFTT_DIFFUSE]->m_Name.empty())) { if (!Res->m_Textures[EFTT_DIFFUSE]) Res->AddTextureMap(EFTT_DIFFUSE); } //if (Res && (!Res->m_Textures[EFTT_SUBSURFACE] || Res->m_Textures[EFTT_SUBSURFACE]->m_Name.empty())) //{ // if (!Res->m_Textures[EFTT_SUBSURFACE]) // Res->AddTextureMap(EFTT_SUBSURFACE); //} if (m_Flags3 & EF3_REBUILD) m_Templates->mfClear(this); bool bCheckResources = false; if (Res) { if (!(Res->m_nCheckedTemplates & (1<m_nCheckedTemplates |= (1<m_TemplShaders.Num(); i++) { if (!m_Templates->m_TemplShaders[i]) continue; if (!(Res->m_nCheckedTemplates & (1<m_nCheckedTemplates |= (1<m_cEF.mfRefreshResources(m_Templates->m_TemplShaders[i], Res); } } } } if (TemplId < m_Templates->m_TemplShaders.Num() && m_Templates->m_TemplShaders[TemplId]) { if (!Name || !strcmp(name, m_Templates->m_TemplShaders[TemplId]->m_Name.c_str())) { if (bCheckResources) gRenDev->m_cEF.mfRefreshResources(m_Templates->m_TemplShaders[TemplId], Res); return true; } m_Templates->m_TemplShaders[TemplId]->Release(); m_Templates->m_TemplShaders[TemplId] = NULL; } m_Templates->mfReserve(TemplId); bRes = gRenDev->m_cEF.mfAddTemplate(Res, this, TemplId, Name, nMaskGen); if (TemplId < EFT_USER_FIRST && TemplId != EFT_WHITE && TemplId != EFT_WHITESHADOW && bRes && bSetPreferred) m_Templates->mfSetPreferred(this); return bRes; } int CShader::mfTemplateNameToId(char *name) { if (isdigit(name[0])) return atoi(name); int n = -1; if (!stricmp("Default", name)) n = EFT_DEFAULT; else if (!stricmp("Decal", name)) n = EFT_DECAL; else if (!stricmp("InvLight", name)) n = EFT_INVLIGHT; else if (!stricmp("White", name)) n = EFT_WHITE; else if (!stricmp("WhiteShadow", name)) n = EFT_WHITESHADOW; else if (!stricmp("HeatVision", name)) n = EFT_HEATVISION; else if (!strnicmp("User", name, 4)) n = atoi(&name[4])+EFT_USER_FIRST; return n; } const char *CShader::mfTemplateTexIdToName(int Id) { switch(Id) { case EFTT_DIFFUSE: return "Diffuse"; case EFTT_GLOSS: return "Gloss"; case EFTT_BUMP: return "Bump"; case EFTT_CUBEMAP: return "Cubemap"; case EFTT_OCCLUSION: return "Occlusion"; case EFTT_ATTENUATION2D: return "Attenuation2D"; case EFTT_SUBSURFACE: return "SubSurface"; case EFTT_ATTENUATION1D: return "Attenuation1D"; case EFTT_SPECULAR: return "Specular"; case EFTT_DETAIL_OVERLAY: return "Detail"; case EFTT_REFLECTION: return "Reflection"; case EFTT_OPACITY: return "Opacity"; case EFTT_LIGHTMAP: case EFTT_LIGHTMAP_HDR: return "Lightmap"; case EFTT_DECAL_OVERLAY: return "Decal"; default: return "Unknown"; } return "Unknown"; } void CShader::mfCompileTemplate(SShader *ef, char *scr) { char* name; long cmd; char *params; char *data; if (!ef->m_Templates) ef->m_Templates = new SEfTemplates; SEfTemplates *st = ef->m_Templates; int n = -1; SInputShaderResources Res(m_pCurResources); enum {eTexDecal = 1, eTexSubSurface, eTexAttenuation2D, eTexAttenuation1D, eTexProcedure, eTexDetail, eTexSpecular, ePreferred, eTexCubemap, eTexBump, eTexOcclusion, eTexGloss, eTemplate}; static tokenDesc commands[] = { {eTexAttenuation2D, "TexAttenuation2D"}, {eTexAttenuation1D, "TexAttenuation1D"}, {eTexDecal, "TexDecal"}, {eTexDetail, "TexDetail"}, {eTexProcedure, "TexProcedure"}, {eTexCubemap, "TexCubemap"}, {eTexBump, "TexBump"}, {eTexOcclusion, "TexOcclusion"}, {eTexGloss, "TexGloss"}, {eTexSpecular, "TexSpecular"}, {eTexSubSurface, "TexSubSurface"}, {eTemplate, "Template"}, {ePreferred, "Preferred"}, {0,0} }; SShader *eft; char szTemplName[128]; char szTemplate[128]; while ((cmd = shGetObject (&scr, commands, &name, ¶ms)) > 0) { data = NULL; if (name) data = name; else if (params) data = params; switch (cmd) { case eTexDecal: Res.m_Textures[EFTT_DIFFUSE].m_Name = data; Res.m_Textures[EFTT_DIFFUSE].m_TU.m_TexPic = NULL; break; case eTexAttenuation2D: Res.m_Textures[EFTT_ATTENUATION2D].m_TU.m_TexPic = NULL; Res.m_Textures[EFTT_ATTENUATION2D].m_Name = data; Res.m_Textures[EFTT_ATTENUATION2D].m_TU.m_nFlags |= FTU_CLAMP; break; case eTexSubSurface: Res.m_Textures[EFTT_SUBSURFACE].m_TU.m_TexPic = NULL; Res.m_Textures[EFTT_SUBSURFACE].m_Name = data; break; case eTexAttenuation1D: Res.m_Textures[EFTT_ATTENUATION1D].m_TU.m_TexPic = NULL; Res.m_Textures[EFTT_ATTENUATION1D].m_Name = data; Res.m_Textures[EFTT_ATTENUATION1D].m_TU.m_nFlags |= FTU_CLAMP; break; case eTexDetail: Res.m_Textures[EFTT_DETAIL_OVERLAY].m_TU.m_TexPic = NULL; Res.m_Textures[EFTT_DETAIL_OVERLAY].m_Name = data; break; case eTexBump: Res.m_Textures[EFTT_BUMP].m_TU.m_TexPic = NULL; Res.m_Textures[EFTT_BUMP].m_Name = data; Res.m_Textures[EFTT_BUMP].m_TU.m_eTexType = eTT_Bumpmap; break; case eTexSpecular: Res.m_Textures[EFTT_SPECULAR].m_TU.m_TexPic = NULL; Res.m_Textures[EFTT_SPECULAR].m_Name = data; break; case eTexOcclusion: Res.m_Textures[EFTT_OCCLUSION].m_TU.m_TexPic = NULL; Res.m_Textures[EFTT_OCCLUSION].m_Name = data; Res.m_Textures[EFTT_OCCLUSION].m_TU.m_eTexType = eTT_DSDTBump; break; case eTexCubemap: Res.m_Textures[EFTT_CUBEMAP].m_TU.m_TexPic = NULL; Res.m_Textures[EFTT_CUBEMAP].m_Name = data; Res.m_Textures[EFTT_CUBEMAP].m_TU.m_eTexType = eTT_Cubemap; break; case eTexGloss: Res.m_Textures[EFTT_GLOSS].m_TU.m_TexPic = NULL; Res.m_Textures[EFTT_GLOSS].m_Name = data; break; case ePreferred: st->m_nPreferred = mfTemplateNameToId(data); break; case eTemplate: strcpy(szTemplName, name); strcpy(szTemplate, params); break; } } m_pCurResources = mfCreateShaderResources(&Res, true); if (!szTemplate[0] || !szTemplName[0]) return; eft = gRenDev->m_cEF.mfForName(szTemplate, ef->m_eClass, 0); eft->m_Flags2 |= EF2_TEMPLATE; if (!eft || (eft->m_Flags & EF_NOTFOUND)) Warning( 0,0,"Warning: Couldn't find template shader '%s' for name '%s'", params, ef->m_Name.c_str()); else { int flags3 = (ef->m_Flags3 | eft->m_Flags3) & (EF3_HASVCOLORS | EF3_HASALPHATEST | EF3_HASALPHABLEND); ef->m_Flags3 |= flags3; eft->m_Flags3 |= flags3; mfCheckShaderResTextures(eft->m_Passes, eft, m_pCurResources); for (int i=0; im_HWTechniques.Num(); i++) { SShaderTechnique *hs = eft->m_HWTechniques[i]; mfCheckShaderResTexturesHW(hs->m_Passes, eft, m_pCurResources); } n = mfTemplateNameToId(szTemplName); if (st->m_nPreferred < 0) st->m_nPreferred = n; if (n >= 0 && eft) { st->mfReserve(n); st->m_TemplShaders[n] = eft; } } st->mfSetPreferred(ef); }