/*============================================================================= D3DCGVPrograms.cpp : Direct3D cg vertex programs support. Copyright (c) 2001 Crytek Studios. All Rights Reserved. Revision history: * Created by Honitch Andrey =============================================================================*/ #include "stdafx.h" #include "DriverD3D8.h" #include "D3DCGVProgram.h" #undef THIS_FILE static char THIS_FILE[] = __FILE__; TArray CVProgram::m_VPrograms; //======================================================================= CVProgram *CVProgram::mfForName(char *name, bool bCGType) { int i; if (!name || !name[0]) return NULL; for (i=0; im_Name.c_str())) { m_VPrograms[i]->m_RefCounter++; return m_VPrograms[i]; } } char scrname[128]; char dir[128]; if (!bCGType) { iLog->Log("Error: Attempt to load assembly vertex shader '%s'", name); iLog->Log("Error: Assembly vertex shaders aren't supported anymore"); return NULL; } else { sprintf(dir, "%sDeclarations/CGVShaders/", gcEf.m_HWPath); sprintf(scrname, "%s%s.crycg", dir, name); } FILE *fp = iSystem->GetIPak()->FOpen(scrname, "r"); if (!fp) { iLog->Log("WARNING: Couldn't find vertex shader '%s'", name); return NULL; } iSystem->GetIPak()->FSeek(fp, 0, SEEK_END); int len = iSystem->GetIPak()->FTell(fp); char *buf = new char [len+1]; iSystem->GetIPak()->FSeek(fp, 0, SEEK_SET); len = iSystem->GetIPak()->FRead(buf, 1, len, fp); iSystem->GetIPak()->FClose(fp); buf[len] = 0; if (bCGType) buf = gcEf.mfScriptPreprocessor(buf, dir, scrname); CVProgram *p = NULL; { CVProgram *pr = new CCGVProgram_D3D; HANDLE statussrc = CreateFile(scrname,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,NULL); if (statussrc != INVALID_HANDLE_VALUE) { GetFileTime(statussrc,NULL,NULL,&pr->m_WriteTime); CloseHandle(statussrc); } pr->m_Name = name; pr->m_Id = i; m_VPrograms.AddElem(pr); pr->m_RefCounter = 1; p = pr; } p->mfCompile(buf); delete [] buf; return p; } //======================================================================= TArray CCGVProgram_D3D::m_CGScripts; void SCGScript::mfRemoveFromList() { int i; for (i=0; im_Name.GetIndex()) SAFE_RELEASE(m_Script); if (m_CoreScript && !m_CoreScript->m_Name.GetIndex()) SAFE_RELEASE(m_CoreScript); if (m_DeclarationsScript && !m_DeclarationsScript->m_Name.GetIndex()) SAFE_RELEASE(m_DeclarationsScript); if (m_InputParmsScript && !m_InputParmsScript->m_Name.GetIndex()) SAFE_RELEASE(m_InputParmsScript); if (m_PosScript && !m_PosScript->m_Name.GetIndex()) SAFE_RELEASE(m_PosScript); m_Pointers.Free(); m_ParamsNoObj.Free(); m_ParamsObj.Free(); m_MatrixNoObj.Free(); m_MatrixObj.Free(); mfReset(); } CCGVProgram_D3D::~CCGVProgram_D3D() { mfFree(); } bool CCGVProgram_D3D::mfHasPointer(ESrcPointer ePtr) { for (int i=0; iePT == ePtr) return true; } return false; } static char *sAdditionalVP[] = { { "OUT.FogC = IN.Fog.x;\n" "return OUT;\n" "}\n" }, { "float fCameraSpacePosZ = dot(ModelViewProj._31_32_33_34, vPos);\n" "OUT.FogC = vPos.w - ((Fog.x - fCameraSpacePosZ) * Fog.y);\n" "return OUT;\n" "}\n" }, { "OUT.FogC = IN.Fog.x;\n" "OUT.Tex3.w = dot(IN.Position, ClipPlane);\n" "OUT.Tex3.xyz = IN.Position.w;\n" "return OUT;\n" "}\n" }, { "float fCameraSpacePosZ = dot(ModelViewProj._31_32_33_34, vPos);\n" "OUT.FogC = vPos.w - ((Fog.x - fCameraSpacePosZ) * Fog.y);\n" "OUT.Tex3.w = dot(IN.Position, ClipPlane);\n" "OUT.Tex3.xyz = IN.Position.w;\n" "return OUT;\n" "}\n" }, { "return OUT;\n" "}\n" }, { "return OUT;\n" "}\n" }, { "OUT.Tex3.w = dot(IN.Position, ClipPlane);\n" "OUT.Tex3.xyz = IN.Position.w;\n" "return OUT;\n" "}\n" }, { "OUT.Tex3.w = dot(IN.Position, ClipPlane);\n" "OUT.Tex3.xyz = IN.Position.w;\n" "return OUT;\n" "}\n" } }; SCGScript *CCGVProgram_D3D::mfGenerateScriptVP(SCGScript *pPosScript) { TArray newScr; if (m_DeclarationsScript) newScr.Copy(m_DeclarationsScript->m_Script, strlen(m_DeclarationsScript->m_Script)); char *szInputParms = m_InputParmsScript->m_Script; if (pPosScript && m_PosScript->m_Name != m_Insts[m_CurInst].m_PosScriptName) { char str[1024]; strcpy(str, szInputParms); szInputParms = str; if (gRenDev->m_RP.m_pShader->m_DefaultVProgram && gRenDev->m_RP.m_pShader->m_DefaultVProgram->m_bCGType) { CCGVProgram_D3D *pVPD3D = (CCGVProgram_D3D *)gRenDev->m_RP.m_pShader->m_DefaultVProgram; for (int i=0; im_ParamsNoObj.Num(); i++) { if (!strstr(str, pVPD3D->m_ParamsNoObj[i].m_Name.c_str())) { strcat(str, ", uniform float4 "); strcat(str, pVPD3D->m_ParamsNoObj[i].m_Name.c_str()); } } for (int i=0; im_ParamsObj.Num(); i++) { if (!strstr(str, pVPD3D->m_ParamsObj[i].m_Name.c_str())) { strcat(str, ", uniform float4 "); strcat(str, pVPD3D->m_ParamsObj[i].m_Name.c_str()); } } } } char str[512]; sprintf(str, "vertout main(appin IN, %s)\n{\n vertout OUT;\n", szInputParms); newScr.Copy(str, strlen(str)); if (pPosScript) newScr.Copy(pPosScript->m_Script, strlen(pPosScript->m_Script)); if (m_CoreScript) newScr.Copy(m_CoreScript->m_Script, strlen(m_CoreScript->m_Script)); char *pExit = "return OUT;\n}"; newScr.Copy(pExit, strlen(pExit)); newScr.AddElem(0); SCGScript *cgs = mfAddNewScript(NULL, &newScr[0]); return cgs; } void CCGVProgram_D3D::mfPrecache() { int bPrevCP = gRenDev->m_RP.m_ClipPlaneEnabled; gRenDev->m_RP.m_ClipPlaneEnabled = false; mfSet(true, 0); gRenDev->m_RP.m_ClipPlaneEnabled = true; mfSet(true, 0); gRenDev->m_RP.m_ClipPlaneEnabled = bPrevCP; mfSet(false, 0); } char *CCGVProgram_D3D::mfCreateAdditionalVP(SCGScript *pPosScript) { SCGScript *pScript = m_Script; if (!pScript) pScript = mfGenerateScriptVP(pPosScript); if (!pScript) return NULL; const char *scr = pScript->m_Script; int len, n; char *sNewStr = pScript->m_Script; while (true) { sNewStr = strstr(sNewStr, "return"); if (!sNewStr) { len = strlen(pScript->m_Script)+1; sNewStr = new char[len]; strcpy(sNewStr, pScript->m_Script); return sNewStr; } n = 0; while (sNewStr[n]!=0x20 && sNewStr[n]!=8 && sNewStr[n]!=0xa) {n++;} while (sNewStr[n]==0x20 || sNewStr[n]==8 || sNewStr[n]==0xa) {n++;} if (!strncmp(&sNewStr[n], "OUT", 3)) break; } n = sNewStr - pScript->m_Script; len = strlen(pScript->m_Script)+1; int lenN = strlen(sAdditionalVP[m_Insts[m_CurInst].m_Mask]); int newSize = n+1+lenN; char *newScr = new char [newSize]; strncpy(newScr, scr, n); strcpy(&newScr[n], sAdditionalVP[m_Insts[m_CurInst].m_Mask]); if ((m_Insts[m_CurInst].m_Mask & VPVST_NOISE) && !strstr(newScr, "register(c32)")) { sNewStr = newScr; while (true) { sNewStr = strstr(sNewStr, "main"); if (!sNewStr) break; n = 0; while (sNewStr[n]!=0x20 && sNewStr[n]!=8 && sNewStr[n]!=0xa && sNewStr[n] != '(') {n++;} while (sNewStr[n]==0x20 || sNewStr[n]==8 || sNewStr[n]==0xa) {n++;} if (sNewStr[n] == '(') { int m = 0; n++; while (true) { if (sNewStr[n]==')') { if (!m) break; m--; } if (sNewStr[n]=='(') m++; n++; } len = strlen(", uniform float4 pg[64] : register(c32)"); int len2 = strlen(newScr)+1; char *newScr2 = new char[len+len2]; n = sNewStr-newScr+n; strncpy(newScr2, newScr, n); strcpy(&newScr2[n], ", uniform float4 pg[64] : register(c32)"); strcpy(&newScr2[n+len], &newScr[n]); delete [] newScr; newScr = newScr2; break; } } } if (m_Insts[m_CurInst].m_Mask & VPVST_FOGGLOBAL) { sNewStr = newScr; while (true) { sNewStr = strstr(sNewStr, "main"); if (!sNewStr) break; n = 0; while (sNewStr[n]!=0x20 && sNewStr[n]!=8 && sNewStr[n]!=0xa && sNewStr[n] != '(') {n++;} while (sNewStr[n]==0x20 || sNewStr[n]==8 || sNewStr[n]==0xa) {n++;} if (sNewStr[n] == '(') { int m = 0; n++; while (true) { if (sNewStr[n]==')') { if (!m) break; m--; } if (sNewStr[n]=='(') m++; n++; } len = strlen(", uniform float3 Fog"); int len2 = strlen(newScr)+1; char *newScr2 = new char[len+len2]; n = sNewStr-newScr+n; strncpy(newScr2, newScr, n); strcpy(&newScr2[n], ", uniform float3 Fog"); strcpy(&newScr2[n+len], &newScr[n]); delete [] newScr; newScr = newScr2; break; } } } if (!(m_Insts[m_CurInst].m_Mask & VPVST_NOFOG)) { sNewStr = newScr; while (true) { sNewStr = strstr(sNewStr, "vertout"); if (!sNewStr) break; n = 0; while (sNewStr[n]!=0x20 && sNewStr[n]!=8 && sNewStr[n]!=0xa && sNewStr[n] != '{') {n++;} while (sNewStr[n]==0x20 || sNewStr[n]==8 || sNewStr[n]==0xa) {n++;} if (sNewStr[n] == '{') { n++; while (sNewStr[n]==0x20 || sNewStr[n]==8 || sNewStr[n]==0xd || sNewStr[n]==0xa) {n++;} len = strlen("float FogC : FOG;\n"); int len2 = strlen(newScr)+1; char *newScr2 = new char[len+len2]; n = sNewStr-newScr+n; strncpy(newScr2, newScr, n); strcpy(&newScr2[n], "float FogC : FOG;\n"); strcpy(&newScr2[n+len], &newScr[n]); delete [] newScr; newScr = newScr2; break; } } } if (m_Insts[m_CurInst].m_Mask & VPVST_CLIPPLANES) { sNewStr = newScr; while (true) { sNewStr = strstr(sNewStr, "main"); if (!sNewStr) break; n = 0; while (sNewStr[n]!=0x20 && sNewStr[n]!=8 && sNewStr[n]!=0xa && sNewStr[n] != '(') {n++;} while (sNewStr[n]==0x20 || sNewStr[n]==8 || sNewStr[n]==0xa) {n++;} if (sNewStr[n] == '(') { int m = 0; n++; while (true) { if (sNewStr[n]==')') { if (!m) break; m--; } if (sNewStr[n]=='(') m++; n++; } len = strlen(", uniform float4 ClipPlane"); int len2 = strlen(newScr)+1; char *newScr2 = new char[len+len2]; n = sNewStr-newScr+n; strncpy(newScr2, newScr, n); strcpy(&newScr2[n], ", uniform float4 ClipPlane"); strcpy(&newScr2[n+len], &newScr[n]); delete [] newScr; newScr = newScr2; break; } } sNewStr = newScr; if (!strstr(sNewStr, "TEX3")) { while (true) { sNewStr = strstr(sNewStr, "vertout"); if (!sNewStr) break; n = 0; while (sNewStr[n]!=0x20 && sNewStr[n]!=8 && sNewStr[n]!=0xa && sNewStr[n] != '{') {n++;} while (sNewStr[n]==0x20 || sNewStr[n]==8 || sNewStr[n]==0xa) {n++;} if (sNewStr[n] == '{') { n++; while (sNewStr[n]==0x20 || sNewStr[n]==8 || sNewStr[n]==0xa) {n++;} len = strlen("float4 Tex3 : TEXCOORD3;\n"); int len2 = strlen(newScr)+1; char *newScr2 = new char[len+len2]; n = sNewStr-newScr+n; strncpy(newScr2, newScr, n); strcpy(&newScr2[n], "float4 Tex3 : TEXCOORD3;\n"); strcpy(&newScr2[n+len], &newScr[n]); delete [] newScr; newScr = newScr2; break; } } } } return newScr; } void CCGVProgram_D3D::mfCompileParam4f(char *scr, SShader *ef, TArray *Params, int nLights) { guard(CCGVProgram_D3D::mfCompileParam4f); gcEf.mfCompileCGParam(scr, ef, Params, nLights); unguard; } void CCGVProgram_D3D::mfCompileParamStateMatrix(char *scr, SShader *ef, TArray *Params) { char* name; long cmd; char *params; char *data; guard(CCGVProgram_D3D::mfCompileParamStateMatrix); enum {eType=1, eName}; static tokenDesc commands[] = { {eType, "Type"}, {eName, "Name"}, {0,0} }; SCGMatrix pr; pr.m_pBind = NULL; while ((cmd = shGetObject (&scr, commands, &name, ¶ms)) > 0) { data = NULL; if (name) data = name; else if (params) data = params; switch (cmd) { case eName: pr.m_Name = data; break; case eType: if (!stricmp(data, "ViewProj")) pr.m_eCGParamType = ECGP_Matr_ViewProj; else if (!stricmp(data, "View")) pr.m_eCGParamType = ECGP_Matr_View; else if (!stricmp(data, "View_I")) pr.m_eCGParamType = ECGP_Matr_View_I; else if (!stricmp(data, "View_T")) pr.m_eCGParamType = ECGP_Matr_View_T; else if (!stricmp(data, "View_IT")) pr.m_eCGParamType = ECGP_Matr_View_IT; else pr.m_eCGParamType = ECGP_Unknown; } } if (pr.m_eCGParamType != ECGP_Unknown && pr.m_Name.GetIndex()) { Params->AddElem(pr); } unguard; } void CCGVProgram_D3D::mfCompileVertAttributes(char *scr, SShader *ef) { char* name; long cmd; char *params; char *data; guard(CCGVProgram_D3D::mfCompileVertAttributes); enum {eVertArray=1}; static tokenDesc commands[] = { {eVertArray, "VertArray"}, {0,0} }; while ((cmd = shGetObject (&scr, commands, &name, ¶ms)) > 0) { data = NULL; if (name) data = name; else if (params) data = params; switch (cmd) { case eVertArray: { if (!data || !data[0]) { iLog->Log("Warning: Missing parameters for VertArray in Shader '%s'\n", ef->m_Name.c_str()); break; } gcEf.mfCompileArrayPointer(m_Pointers, params, ef); } break; } } unguard; } bool CCGVProgram_D3D::mfCompile(char *scr) { char* name; long cmd; char *params; char *data; guard(CCGVProgram_D3D::mfCompile); enum {eScript=1, eParam4f, eVertAttributes, eParamStateMatrix, eNoFog, eNoise, eUnifiedPosScript, eMainInput, eDeclarationsScript, ePositionScript, eCoreScript}; static tokenDesc commands[] = { {eScript, "Script"}, {eParam4f, "Param4f"}, {eParamStateMatrix, "ParamStateMatrix"}, {eVertAttributes, "VertAttributes"}, {eMainInput, "MainInput"}, {eDeclarationsScript, "DeclarationsScript"}, {ePositionScript, "PositionScript"}, {eCoreScript, "CoreScript"}, {eNoFog, "NoFog"}, {eNoise, "Noise"}, {eUnifiedPosScript, "UnifiedPosScript"}, {0,0} }; mfFree(); SShader *ef = gcEf.m_CurShader; while ((cmd = shGetObject (&scr, commands, &name, ¶ms)) > 0) { data = NULL; if (name) data = name; else if (params) data = params; switch (cmd) { case eVertAttributes: mfCompileVertAttributes(params, ef); break; case eMainInput: m_InputParmsScript = mfAddNewScript(name, params); break; case eDeclarationsScript: m_DeclarationsScript = mfAddNewScript(name, params); break; case ePositionScript: if (strchr(params, ';')) m_PosScript = mfAddNewScript(name, params); else { m_PosScript = mfAddNewScript(params, NULL); if (!m_PosScript) m_PosScript = mfAddNewScript("PosCommon", NULL); } break; case eCoreScript: m_CoreScript = mfAddNewScript(name, params); break; case eParam4f: mfCompileParam4f(params, ef, &m_ParamsNoObj, -1); break; case eParamStateMatrix: mfCompileParamStateMatrix(params, ef, &m_MatrixNoObj); break; case eUnifiedPosScript: m_Flags |= VPFI_UNIFIEDPOS; break; case eNoFog: m_Flags |= VPFI_NOFOG; break; case eNoise: m_Flags |= VPFI_NOISE; break; case eScript: { SAFE_RELEASE(m_Script); m_Script = mfAddNewScript(NULL, data); } break; } } int i; for (i=0; im_eCGParamType == ECGP_Matr_ViewProj) break; } if (i == m_MatrixNoObj.Num()) { SCGMatrix m; m.m_eCGParamType = ECGP_Matr_ViewProj; m.m_Name = "ModelViewProj"; m_MatrixNoObj.AddElem(m); } unguard; return 1; } void CCGVProgram_D3D::mfSetVariables(TArray* Vars) { int i; for (i=0; iNum(); i++) { SCGParam4f *p = &Vars->Get(i); if (p->m_nComponents > 1) { float matr[4][4]; int nLast = i+p->m_nComponents; int n = 0; SCGParam4f *pMatr = p; for (; iGet(i); float *v = p->mfGet(); matr[n][0] = v[0]; matr[n][1] = v[1]; matr[n][2] = v[2]; matr[n][3] = v[3]; } i--; mfParameter(pMatr, &matr[0][0], pMatr->m_nComponents); continue; } float *v = p->mfGet(); mfParameter4f(p, v); } } void CCGVProgram_D3D::mfSetVariables(bool bObj, TArray* Parms) { if (m_Insts[m_CurInst].m_dwHandle == 0 || m_Insts[m_CurInst].m_dwHandle == -1) return; if (!bObj) { if (m_ParamsNoObj.Num()) mfSetVariables(&m_ParamsNoObj); if (m_Insts[m_CurInst].m_ParamsNoObj) mfSetVariables(m_Insts[m_CurInst].m_ParamsNoObj); } else { if (m_ParamsObj.Num()) mfSetVariables(&m_ParamsObj); if (m_Insts[m_CurInst].m_ParamsObj) mfSetVariables(m_Insts[m_CurInst].m_ParamsObj); } if (Parms) mfSetVariables((TArray *)Parms); } /* returns a random floating point number between 0.0 and 1.0 */ static float frand() { return (float) (rand() / (float) RAND_MAX); } /* returns a random floating point number between -1.0 and 1.0 */ static float sfrand() { return (float) (rand() * 2.0f/ (float) RAND_MAX) - 1.0f; } void CCGVProgram_D3D::mfGetSrcFileName(char *srcname) { sprintf(srcname, "%sDeclarations/CGVShaders/%s.crycg", gcEf.m_HWPath, m_Name.c_str()); } void CCGVProgram_D3D::mfGetDstFileName(char *dstname, SCGScript *pPosScr) { char *type; #ifndef _XBOX if (m_CGProfileType == CG_PROFILE_VS_1_1) type = "D3D8_VS11"; else if (m_CGProfileType == CG_PROFILE_VS_2_0) type = "D3D8_VS20"; else if (m_CGProfileType == CG_PROFILE_VS_2_X) type = "D3D8_VS2X"; #else type = "D3D8_VS11"; #endif char *fog; if (m_Insts[m_CurInst].m_Mask & VPVST_FOGGLOBAL) fog = "Fog"; else if (m_Insts[m_CurInst].m_Mask & VPVST_NOFOG) fog = "NoFog"; char *cp; if (m_Insts[m_CurInst].m_Mask & VPVST_CLIPPLANES) cp = "CP"; else cp = "NoCP"; const char *szPos = pPosScr ? pPosScr->m_Name.c_str() : "None"; sprintf(dstname, "%sDeclarations/CGVShaders/Cache/%s$%s$%s$%s#%s.cgvp", gcEf.m_HWPath, m_Name.c_str(), type, fog, cp, szPos); } static char *sGetText(char **buf) { bool bBetween = false; SkipCharacters(buf, " "); if (**buf == ':') { ++*buf; SkipCharacters(buf, " "); if (**buf == ':') return NULL; } char *result = *buf; // now, we need to find the next whitespace to end the data char theChar; while ((theChar = **buf) != 0) { if (theChar <= 0x20) // space and control chars break; ++*buf; } **buf = 0; // null terminate it if (theChar) // skip the terminator ++*buf; return result; } bool CCGVProgram_D3D::mfActivate(CCGVProgram_D3D *pPosVP) { CD3D8Renderer *r = gcpRendD3D; LPDIRECT3DDEVICE8 dv = r->mfGetD3DDevice(); if (!m_Insts[m_CurInst].m_dwHandle) { bool bCreate = false; char namesrc[256]; char namedst[256]; char strVer[128]; char strVer0[128]; sprintf(strVer, "//CGVER%.1f\n", CG_CACHE_VER); mfGetSrcFileName(namesrc); mfGetDstFileName(namedst, pPosVP->m_PosScript); #ifndef _XBOX FILETIME writetimesrc,writetimedst; HANDLE statussrc, statusdst; statusdst = CreateFile(namedst,GENERIC_READ,FILE_SHARE_READ, NULL,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,NULL); if (statusdst == INVALID_HANDLE_VALUE) bCreate = true; else { statussrc = CreateFile(namesrc,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,NULL); GetFileTime(statussrc,NULL,NULL,&writetimesrc); GetFileTime(statusdst,NULL,NULL,&writetimedst); CloseHandle(statussrc); CloseHandle(statusdst); if (CompareFileTime(&writetimesrc,&writetimedst)!=0) bCreate = true; FILE *fp = iSystem->GetIPak()->FOpen(namedst, "r"); if (!fp) bCreate = true; else { iSystem->GetIPak()->FGets(strVer0, 128, fp); iSystem->GetIPak()->FClose(fp); if (strcmp(strVer, strVer0)) bCreate = true; } } if (bCreate) { char *scr; scr = mfCreateAdditionalVP(pPosVP->m_PosScript); const char *code = mfLoadCG(scr); delete [] scr; if (code) { FILE *fp = fopen(namedst, "w"); if (fp) { fprintf(fp, "%s%s", strVer, code); fclose(fp); } statusdst = CreateFile(namedst,GENERIC_WRITE,FILE_SHARE_READ, NULL,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,NULL); statussrc = CreateFile(namesrc,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,NULL); GetFileTime(statussrc,NULL,NULL,&writetimesrc); SetFileTime(statusdst,NULL,NULL,&writetimesrc); CloseHandle(statussrc); CloseHandle(statusdst); } if (m_Insts[m_CurInst].m_CGProgram) cgDestroyProgram(m_Insts[m_CurInst].m_CGProgram); m_Insts[m_CurInst].m_CGProgram = NULL; } #endif FILE *fp = iSystem->GetIPak()->FOpen(namedst, "r"); if (!fp) iLog->Log("Error: couldn't open for read vertex shader file '%s'", namedst); else { iSystem->GetIPak()->FSeek(fp, 0, SEEK_END); int len = iSystem->GetIPak()->FTell(fp); iSystem->GetIPak()->FSeek(fp, 0, SEEK_SET); char *pbuf = new char [len+1]; iSystem->GetIPak()->FGets(strVer0, 128, fp); len = iSystem->GetIPak()->FRead(pbuf, 1, len, fp); pbuf[len] = 0; iSystem->GetIPak()->FClose(fp); #ifdef _XBOX char *s = pbuf; while (s) { s = strstr(s, ", v"); if (s) { char dig[3]; dig[0] = s[3]; if (isdigit(s[4])) { dig[1] = s[4]; dig[2] = 0; } else dig[1] = 0; int n = atoi(dig); switch(n) { case 3: s[3] = '2'; break; case 5: s[3] = '3'; break; case 6: s[3] = '4'; break; case 7: s[3] = '9'; break; case 8: s[1] = 'v'; s[2] = '1'; s[3] = '0'; break; case 9: s[1] = 'v'; s[2] = '1'; s[3] = '1'; break; case 0: case 1: case 2: break; case 10: s[3] = '1'; s[4] = '2'; break; default: assert(0); } s = &s[4]; } } #endif mfLoad(pbuf); // parse variables and constants from CG object code int nComps = 1; char *scr = pbuf; char *token = strtok(scr, "//"); while (token) { if (!strncmp(token, "const", 5)) { token += 5; char *szhReg = sGetText(&token); char *szEqual = sGetText(&token); char *szF0 = sGetText(&token); char *szF1 = sGetText(&token); char *szF2 = sGetText(&token); char *szF3 = sGetText(&token); if (!m_Insts[m_CurInst].m_BindConstants) m_Insts[m_CurInst].m_BindConstants = new TArray; SCGBindConst cgp; cgp.m_nComponents = 1; cgp.m_Val[0] = (float)atof(szF0); cgp.m_Val[1] = (float)atof(szF1); cgp.m_Val[2] = (float)atof(szF2); cgp.m_Val[3] = (float)atof(szF3); cgp.m_dwBind = atoi(&szhReg[2]); m_Insts[m_CurInst].m_BindConstants->AddElem(cgp); } else if (!strncmp(token, "var", 3)) { token += 3; char *szType = sGetText(&token); char *szName = sGetText(&token); char *szvAttr = sGetText(&token); char *szhReg = sGetText(&token); int len = strlen(szhReg); if (szhReg[len-1] == ',') { char *sznComps = sGetText(&token); nComps = atoi(sznComps); } else nComps = 1; char *szVarType = sGetText(&token); char *sznVar = sGetText(&token); if (!szvAttr) { if (!m_Insts[m_CurInst].m_BindVars) m_Insts[m_CurInst].m_BindVars = new TArray; SCGBind cgp; cgp.m_nComponents = nComps; cgp.m_Name = szName; cgp.m_dwBind = atoi(&szhReg[2]); m_Insts[m_CurInst].m_BindVars->AddElem(cgp); } } token = strtok(NULL, "//"); } } mfUnbind(); if (!m_bCreateNoise) { m_bCreateNoise = true; // create a table containing a random permuation of the integers from 0-63 vec4_t c[64]; int i; // want reproducable behaviour for debug //srand(1); for(i=0; i<64; i++) { c[i][3] = (float)i; c[i][0] = frand(); c[i][1] = frand(); c[i][2] = frand(); } for(i=0; i<500; i++) { // choose two entries at random and swap int a, b; float t; a = (rand() >> 4) & 63; // lower bits of rand() are bogus sometimes b = (rand() >> 4) & 63; t = c[a][3]; c[a][3] = c[b][3]; c[b][3] = t; } for(i=0; i<64; i++) { dv->SetVertexShaderConstant(32+i, &c[i][0], 1); } float cons[4]; cons[0] = 0; cons[1] = 0.25f; cons[2] = 0.5f; cons[3] = 1.0f; dv->SetVertexShaderConstant(28, cons, 1); } } if (!m_Insts[m_CurInst].m_dwHandle) return false; return true; } bool CCGVProgram_D3D::mfSet(bool bStat, SShaderPassHW *slw, int nSetPointers) { if (!bStat) { if (CRenderer::CV_r_log == 4) gRenDev->Logv(SRendItem::m_RecurseLevel, "--- Reset VProgram \"%s\"\n", m_Name.c_str()); m_LastVP = NULL; return true; } gRenDev->m_RP.m_CurVP = this; int CurV = gRenDev->m_RP.m_CurD3DVFormat; int Num; if ((m_Flags & VPFI_NOFOG) || !CRenderer::CV_r_vpfog || (gRenDev->GetFeatures() & RFT_HW_RADEON8500)) Num = VPVST_NOFOG; else Num = VPVST_FOGGLOBAL; if (gRenDev->m_RP.m_ClipPlaneEnabled == 1) Num |= VPVST_CLIPPLANES; //Num = VPVST_NOFOG; int Streams = gRenDev->m_RP.m_FlagsModificators & 7; CCGVProgram_D3D *pPosVP = this; if (m_Flags & VPFI_UNIFIEDPOS) { CVProgram *pVP; if (gRenDev->m_RP.m_RendPass) pVP = gRenDev->m_RP.m_LastVP; else pVP = gRenDev->m_RP.m_pShader->m_DefaultVProgram; if (pVP && pVP->m_bCGType) { CCGVProgram_D3D *pVPD3D = (CCGVProgram_D3D *)pVP; if (pVPD3D->m_PosScript) pPosVP = pVPD3D; } } if (CRenderer::CV_r_log == 4) gRenDev->Logv(SRendItem::m_RecurseLevel, "--- Set VProgram \"%s\" (%d Type)\n", m_Name.c_str(), Num); int Id = mfGetCGInstanceID(Streams, CurV, Num, pPosVP); m_LastTypeVP = Id; #ifndef _XBOX if ((int)m_Insts[Id].m_CGProgram == -1) #else if (m_Insts[Id].m_dwHandle == -1) #endif return false; #ifndef _XBOX if (!m_Insts[Id].m_CGProgram) #else if (!m_Insts[Id].m_dwHandle) #endif { if (!mfActivate(pPosVP)) { m_Insts[Id].m_dwHandle = -1; return false; } m_LastVP = NULL; } if (m_Frame != gRenDev->GetFrameID()) { m_Frame = gRenDev->GetFrameID(); gRenDev->m_RP.m_PS.m_NumVShaders++; } m_LastVP = m_Id; // select the vertex shader //if (m_LastVP != m_Id || m_LastTypeVP != Num) { //m_LastTypeVP = Num; mfBind(); } gRenDev->m_RP.m_PersFlags |= RBPF_VSNEEDSET; mfSetStateMatrices(false); if (slw && slw->m_VPParamsNoObj.Num()) mfSetVariables(false, &slw->m_VPParamsNoObj); else mfSetVariables(false, NULL); if (!(m_Flags & VPFI_UNIFIEDPOS)) gRenDev->m_RP.m_LastVP = this; return true; }