3783 lines
91 KiB
C++
3783 lines
91 KiB
C++
/*=============================================================================
|
|
ShaderParse.cpp : implementation of the Shaders parser part of shaders manager.
|
|
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 <direct.h>
|
|
#include <io.h>
|
|
#elif defined(LINUX)
|
|
#endif
|
|
|
|
|
|
|
|
//=================================================================================================
|
|
|
|
//============================================================
|
|
// Compile functions
|
|
//============================================================
|
|
|
|
void CShader::mfCompileFogParms(SShader *ef, char *scr)
|
|
{
|
|
char* name;
|
|
long cmd;
|
|
char *params;
|
|
|
|
enum {eColor = 1, eDensity, eAxis};
|
|
static tokenDesc commands[] =
|
|
{
|
|
{eColor, "Color"},
|
|
{eDensity, "Density"},
|
|
{eAxis, "Axis"},
|
|
{0,0}
|
|
};
|
|
|
|
if (!ef->m_FogInfo)
|
|
ef->m_FogInfo = new SFogInfo;
|
|
|
|
while ((cmd = shGetObject (&scr, commands, &name, ¶ms)) > 0)
|
|
{
|
|
switch (cmd)
|
|
{
|
|
case eColor:
|
|
shGetColor(params, ef->m_FogInfo->m_FogColor);
|
|
//COLCONV(ef->FogInfo.FogColor);
|
|
break;
|
|
|
|
case eDensity:
|
|
ef->m_FogInfo->m_FogDensity = shGetFloat(params);
|
|
break;
|
|
|
|
case eAxis:
|
|
ef->m_FogInfo->m_FogAxis = shGetInt(params);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CShader::mfCompileRGBAStyle(char *scr, SShader *ef, SShaderPass *sm, bool bRGB)
|
|
{
|
|
char* name;
|
|
long cmd;
|
|
char *params;
|
|
char *data;
|
|
|
|
enum {eStyle=1, eType, eColor};
|
|
static tokenDesc commands[] =
|
|
{
|
|
{eStyle, "Style"},
|
|
{eType, "Type"},
|
|
{eColor, "Color"},
|
|
};
|
|
|
|
sm->m_eEvalRGB = eERGB_StyleIntens;
|
|
|
|
while ((cmd = shGetObject (&scr, commands, &name, ¶ms)) > 0)
|
|
{
|
|
data = NULL;
|
|
if (name)
|
|
data = name;
|
|
else
|
|
if (params)
|
|
data = params;
|
|
|
|
switch (cmd)
|
|
{
|
|
case eStyle:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing Style argument for RGBGen style in Shader '%s'\n", ef->m_Name.c_str());
|
|
break;
|
|
}
|
|
sm->m_Style = shGetInt(data);
|
|
break;
|
|
|
|
case eType:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing RConst argument for RGBGen style in Shader '%s'\n", ef->m_Name.c_str());
|
|
break;
|
|
}
|
|
if (!strnicmp(data, "Intens", 6))
|
|
sm->m_eEvalRGB = eERGB_StyleIntens;
|
|
else
|
|
if (!stricmp(data, "Color"))
|
|
sm->m_eEvalRGB = eERGB_StyleColor;
|
|
else
|
|
{
|
|
Warning( 0,0,"Warning: unknown Style type for RGBGen style in Shader '%s'\n", ef->m_Name.c_str());
|
|
sm->m_eEvalRGB = eERGB_StyleIntens;
|
|
}
|
|
break;
|
|
|
|
case eColor:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing Color argument for RGBGen style in Shader '%s'\n", ef->m_Name.c_str());
|
|
sm->m_FixedColor.dcolor = -1;
|
|
break;
|
|
}
|
|
CFColor col;
|
|
shGetColor(params, col);
|
|
COLCONV(col);
|
|
sm->m_FixedColor.dcolor = col.GetTrue();
|
|
break;
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
void CShader::mfCompileRGBNoise(SRGBGenNoise *cn, char *scr, SShader *ef)
|
|
{
|
|
char* name;
|
|
long cmd;
|
|
char *params;
|
|
char *data;
|
|
|
|
enum {eRRange=1, eRConst, eGRange, eGConst, eBRange, eBConst};
|
|
static tokenDesc commands[] =
|
|
{
|
|
{eRRange, "RRange"},
|
|
{eRConst, "RConst"},
|
|
{eGRange, "GRange"},
|
|
{eGConst, "GConst"},
|
|
{eBRange, "BRange"},
|
|
{eBConst, "BConst"},
|
|
};
|
|
|
|
while ((cmd = shGetObject (&scr, commands, &name, ¶ms)) > 0)
|
|
{
|
|
data = NULL;
|
|
if (name)
|
|
data = name;
|
|
else
|
|
if (params)
|
|
data = params;
|
|
|
|
switch (cmd)
|
|
{
|
|
case eRRange:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing RRange argument for AlphaNoise in Shader '%s'\n", ef->m_Name.c_str());
|
|
break;
|
|
}
|
|
cn->m_RangeR = shGetFloat(data);
|
|
break;
|
|
|
|
case eRConst:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing RConst argument for AlphaNoise in Shader '%s'\n", ef->m_Name.c_str());
|
|
break;
|
|
}
|
|
cn->m_ConstR = shGetFloat(data);
|
|
break;
|
|
|
|
case eGRange:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing GRange argument for AlphaNoise in Shader '%s'\n", ef->m_Name.c_str());
|
|
break;
|
|
}
|
|
cn->m_RangeG = shGetFloat(data);
|
|
break;
|
|
|
|
case eGConst:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing GConst argument for AlphaNoise in Shader '%s'\n", ef->m_Name.c_str());
|
|
break;
|
|
}
|
|
cn->m_ConstG = shGetFloat(data);
|
|
break;
|
|
|
|
case eBRange:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing BRange argument for AlphaNoise in Shader '%s'\n", ef->m_Name.c_str());
|
|
break;
|
|
}
|
|
cn->m_RangeB = shGetFloat(data);
|
|
break;
|
|
|
|
case eBConst:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing BConst argument for AlphaNoise in Shader '%s'\n", ef->m_Name.c_str());
|
|
break;
|
|
}
|
|
cn->m_ConstB = shGetFloat(data);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CShader::mfCompileAlphaNoise(SAlphaGenNoise *cn, char *scr, SShader *ef)
|
|
{
|
|
char* name;
|
|
long cmd;
|
|
char *params;
|
|
char *data;
|
|
|
|
enum {eAlphaRange=1, eAlphaConst};
|
|
static tokenDesc commands[] =
|
|
{
|
|
{eAlphaRange, "AlphaRange"},
|
|
{eAlphaConst, "AlphaConst"},
|
|
};
|
|
|
|
while ((cmd = shGetObject (&scr, commands, &name, ¶ms)) > 0)
|
|
{
|
|
data = NULL;
|
|
if (name)
|
|
data = name;
|
|
else
|
|
if (params)
|
|
data = params;
|
|
|
|
switch (cmd)
|
|
{
|
|
case eAlphaRange:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing AlphaRange argument for AlphaNoise in Shader '%s'\n", ef->m_Name.c_str());
|
|
break;
|
|
}
|
|
cn->m_RangeA = shGetFloat(data);
|
|
break;
|
|
|
|
case eAlphaConst:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing AlphaConst argument for AlphaNoise in Shader '%s'\n", ef->m_Name.c_str());
|
|
break;
|
|
}
|
|
cn->m_ConstA = shGetFloat(data);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CShader::mfCompileWaveForm(SWaveForm *wf, char *scr)
|
|
{
|
|
char* name;
|
|
long cmd;
|
|
char *params;
|
|
|
|
enum {eType=1, eLevel, eAmp, ePhase, eFreq, eClamp};
|
|
static tokenDesc commands[] =
|
|
{
|
|
{eType, "Type"},
|
|
{eLevel, "Level"},
|
|
{eAmp, "Amp"},
|
|
{ePhase, "Phase"},
|
|
{eFreq, "Freq"},
|
|
{eClamp, "Clamp"},
|
|
{0,0}
|
|
};
|
|
|
|
wf->m_Flags = 0;
|
|
|
|
while ((cmd = shGetObject (&scr, commands, &name, ¶ms)) > 0)
|
|
{
|
|
switch (cmd)
|
|
{
|
|
case eType:
|
|
if (!stricmp(params, "Sin"))
|
|
wf->m_eWFType = eWF_Sin;
|
|
else
|
|
if (!stricmp(params, "HalfSin"))
|
|
wf->m_eWFType = eWF_HalfSin;
|
|
else
|
|
if (!stricmp(params, "InvHalfSin"))
|
|
wf->m_eWFType = eWF_InvHalfSin;
|
|
else
|
|
if (!stricmp(params, "Square"))
|
|
wf->m_eWFType = eWF_Square;
|
|
else
|
|
if (!stricmp(params, "Triangle"))
|
|
wf->m_eWFType = eWF_Triangle;
|
|
else
|
|
if (!stricmp(params, "SawTooth"))
|
|
wf->m_eWFType = eWF_SawTooth;
|
|
else
|
|
if (!stricmp(params, "InverseSawTooth") || !stricmp(params, "InvSawTooth"))
|
|
wf->m_eWFType = eWF_InvSawTooth;
|
|
else
|
|
if (!stricmp(params, "Hill"))
|
|
wf->m_eWFType = eWF_Hill;
|
|
else
|
|
if (!stricmp(params, "InverseHill") || !stricmp(params, "InvHill"))
|
|
wf->m_eWFType = eWF_InvHill;
|
|
else
|
|
wf->m_eWFType = eWF_None;
|
|
break;
|
|
|
|
case eLevel:
|
|
shGetFloat(params, &wf->m_Level, &wf->m_Level1);
|
|
break;
|
|
|
|
case eAmp:
|
|
shGetFloat(params, &wf->m_Amp, &wf->m_Amp1);
|
|
break;
|
|
|
|
case ePhase:
|
|
shGetFloat(params, &wf->m_Phase, &wf->m_Phase1);
|
|
break;
|
|
|
|
case eFreq:
|
|
shGetFloat(params, &wf->m_Freq, &wf->m_Freq1);
|
|
break;
|
|
|
|
case eClamp:
|
|
wf->m_Flags |= WFF_CLAMP;
|
|
break;
|
|
}
|
|
}
|
|
if (wf->m_Freq1 != wf->m_Freq || wf->m_Amp != wf->m_Amp1 || wf->m_Level != wf->m_Level1 || wf->m_Phase != wf->m_Phase1)
|
|
wf->m_Flags |= WFF_LERP;
|
|
}
|
|
|
|
void CShader::mfCompileDeform(SShader *ef, SDeform *df, char *dname, char *scr)
|
|
{
|
|
char* name;
|
|
long cmd;
|
|
char *params;
|
|
float f;
|
|
|
|
enum {eDiv=1, eDeformGen, eFlareSize};
|
|
static tokenDesc commands[] =
|
|
{
|
|
{eDiv, "Div"},
|
|
{eDeformGen, "DeformGen"},
|
|
{eFlareSize, "FlareSize"}
|
|
};
|
|
|
|
EDeformType eType;
|
|
if (!stricmp(dname, "Bulge"))
|
|
eType = eDT_Bulge;
|
|
else
|
|
if (!stricmp(dname, "Wave"))
|
|
eType = eDT_Wave;
|
|
else
|
|
if (!stricmp(dname, "Flare"))
|
|
{
|
|
ef->m_Flags3 |= EF3_SHAREVERTS;
|
|
eType = eDT_Flare;
|
|
}
|
|
else
|
|
if (!stricmp(dname, "Beam"))
|
|
eType = eDT_Beam;
|
|
else
|
|
if (!stricmp(dname, "VerticalWave"))
|
|
eType = eDT_VerticalWave;
|
|
else
|
|
if (!stricmp(dname, "Squeeze"))
|
|
eType = eDT_Squeeze;
|
|
else
|
|
if (!stricmp(dname, "FromCenter"))
|
|
eType = eDT_FromCenter;
|
|
else
|
|
{
|
|
Warning( 0,0,"Warning: Unknown deform type %s in Shader '%s' (skipping)\n", dname, ef->m_Name.c_str());
|
|
return;
|
|
}
|
|
|
|
df->m_eType = eType;
|
|
|
|
while ((cmd = shGetObject (&scr, commands, &name, ¶ms)) > 0)
|
|
{
|
|
switch (cmd)
|
|
{
|
|
case eDiv:
|
|
f = shGetFloat(params);
|
|
if (f)
|
|
{
|
|
df->m_ScaleVerts = 1.0f / (f/100.0f);
|
|
}
|
|
else
|
|
{
|
|
df->m_ScaleVerts = 1.0f;
|
|
Warning( 0,0,"Warning: illegal div value (0) in DeformVertexes command for Shader '%s'\n", ef->m_Name.c_str());
|
|
}
|
|
break;
|
|
|
|
case eDeformGen:
|
|
mfCompileWaveForm(&df->m_DeformGen, params);
|
|
df->m_DeformGen.m_Level /= 100.0f;
|
|
df->m_DeformGen.m_Amp /= 100.0f;
|
|
break;
|
|
|
|
case eFlareSize:
|
|
{
|
|
df->m_fFlareSize = shGetFloat(params);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CShader::mfParseLightStyle(CLightStyle *ls, char *lstr)
|
|
{
|
|
int i;
|
|
char str[64], *pstr1, *pstr2;
|
|
CFColor col;
|
|
|
|
col = CFColor(0.0f);
|
|
|
|
ls->m_Map.Free();
|
|
|
|
int n = 0;
|
|
while (true)
|
|
{
|
|
pstr1 = strchr(lstr, '|');
|
|
if (!pstr1)
|
|
break;
|
|
pstr2 = strchr(pstr1+1, '|');
|
|
if (!pstr2)
|
|
break;
|
|
if (pstr2-pstr1-1 > 0)
|
|
{
|
|
strncpy(str, pstr1+1, pstr2-pstr1-1);
|
|
str[pstr2-pstr1-1] = 0;
|
|
i = sscanf(str, "%f %f %f %f", &col[0], &col[1], &col[2], &col[3]);
|
|
switch (i)
|
|
{
|
|
default:
|
|
continue;
|
|
|
|
case 1:
|
|
col[1] = col[2] = col[0];
|
|
col[3] = 1.0f;
|
|
break;
|
|
|
|
case 2:
|
|
col[2] = 1.0f;
|
|
col[3] = 1.0f;
|
|
break;
|
|
|
|
case 3:
|
|
col[3] = 1.0f;
|
|
break;
|
|
}
|
|
ls->m_Map.AddElem(col);
|
|
n++;
|
|
}
|
|
|
|
lstr = pstr2;
|
|
}
|
|
ls->m_Map.Shrink();
|
|
assert(ls->m_Map.Num() == n);
|
|
}
|
|
|
|
bool CShader::mfCompileLightStyle(SShader *ef, int num, char *scr)
|
|
{
|
|
char* name;
|
|
long cmd;
|
|
char *params;
|
|
char *data;
|
|
|
|
enum {eValueString=1, eSpeed};
|
|
static tokenDesc commands[] =
|
|
{
|
|
{eValueString, "ValueString"},
|
|
{eSpeed, "Speed"},
|
|
};
|
|
|
|
ef->m_Flags |= EF_LIGHTSTYLE;
|
|
if (CLightStyle::m_LStyles.Num() <= num)
|
|
CLightStyle::m_LStyles.ReserveNew(num+1);
|
|
CLightStyle *ls = CLightStyle::m_LStyles[num];
|
|
if (!ls)
|
|
{
|
|
ls = new CLightStyle;
|
|
ls->m_LastTime = 0;
|
|
ls->m_Color = Col_White;
|
|
CLightStyle::m_LStyles[num] = ls;
|
|
}
|
|
ls->m_TimeIncr = 60;
|
|
|
|
|
|
while ((cmd = shGetObject (&scr, commands, &name, ¶ms)) > 0)
|
|
{
|
|
data = NULL;
|
|
if (name)
|
|
data = name;
|
|
else
|
|
if (params)
|
|
data = params;
|
|
|
|
switch (cmd)
|
|
{
|
|
case eValueString:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing ValueString argument for LightStyle %i in Shader '%s'\n", num, ef->m_Name.c_str());
|
|
break;
|
|
}
|
|
mfParseLightStyle(ls, data);
|
|
break;
|
|
|
|
case eSpeed:
|
|
ls->m_TimeIncr = shGetFloat(data);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void CShader::mfCheckObjectDependParams(TArray<SCGParam4f>* PNoObj, TArray<SCGParam4f>* PObj)
|
|
{
|
|
#ifdef PIPE_USE_INSTANCING
|
|
if (!PNoObj)
|
|
return;
|
|
int i, j;
|
|
for (i=0; i<PNoObj->Num(); i++)
|
|
{
|
|
for (j=0; j<4; j++)
|
|
{
|
|
if (PNoObj->Get(i).m_Comps[j] && PNoObj->Get(i).m_Comps[j]->m_bDependsOnObject)
|
|
break;
|
|
}
|
|
if (j != 4)
|
|
{
|
|
PObj->AddElem(PNoObj->Get(i));
|
|
PNoObj->Remove(i);
|
|
i--;
|
|
}
|
|
}
|
|
PNoObj->Shrink();
|
|
PObj->Shrink();
|
|
#endif
|
|
}
|
|
|
|
void CShader::mfCheckObjectDependParams(TArray<SParam>* PNoObj, TArray<SParam>* PObj)
|
|
{
|
|
#ifdef PIPE_USE_INSTANCING
|
|
int i, j;
|
|
for (i=0; i<PNoObj->Num(); i++)
|
|
{
|
|
for (j=0; j<4; j++)
|
|
{
|
|
if (PNoObj->Get(i).m_Comps[j] && PNoObj->Get(i).m_Comps[j]->m_bDependsOnObject)
|
|
break;
|
|
}
|
|
if (j != 4)
|
|
{
|
|
PObj->AddElem(PNoObj->Get(i));
|
|
PNoObj->Remove(i);
|
|
i--;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
SShaderGenBit *CShader::mfCompileShaderGenProperty(SShader *ef, char *scr)
|
|
{
|
|
char* name;
|
|
long cmd;
|
|
char *params;
|
|
char *data;
|
|
|
|
SShaderGenBit *shgm = new SShaderGenBit;
|
|
|
|
enum {eName=1, eProperty, eDescription, eMask, eHidden};
|
|
static tokenDesc commands[] =
|
|
{
|
|
{eName, "Name"},
|
|
{eProperty, "Property"},
|
|
{eDescription, "Description"},
|
|
{eMask, "Mask"},
|
|
{eHidden, "Hidden"},
|
|
|
|
{0,0}
|
|
};
|
|
|
|
while ((cmd = shGetObject (&scr, commands, &name, ¶ms)) > 0)
|
|
{
|
|
data = NULL;
|
|
if (name)
|
|
data = name;
|
|
else
|
|
if (params)
|
|
data = params;
|
|
|
|
switch (cmd)
|
|
{
|
|
case eName:
|
|
shgm->m_ParamName = data;
|
|
break;
|
|
|
|
case eProperty:
|
|
shgm->m_ParamProp = data;
|
|
break;
|
|
|
|
case eDescription:
|
|
shgm->m_ParamDesc = data;
|
|
break;
|
|
|
|
case eHidden:
|
|
shgm->m_Flags |= SHGF_HIDDEN;
|
|
break;
|
|
|
|
case eMask:
|
|
if (data && data[0])
|
|
{
|
|
if (data[0] == '0' && (data[1] == 'x' || data[1] == 'X'))
|
|
shgm->m_Mask = shGetHex64(&data[2]);
|
|
else
|
|
shgm->m_Mask = shGetInt(data);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return shgm;
|
|
}
|
|
|
|
bool CShader::mfCompileShaderGen(SShader *ef, SShaderGen *shg, char *scr)
|
|
{
|
|
char* name;
|
|
long cmd;
|
|
char *params;
|
|
char *data;
|
|
|
|
SShaderGenBit *shgm;
|
|
|
|
enum {eProperty=1, eVersion};
|
|
static tokenDesc commands[] =
|
|
{
|
|
{eProperty, "Property"},
|
|
{eVersion, "Version"},
|
|
|
|
{0,0}
|
|
};
|
|
|
|
while ((cmd = shGetObject (&scr, commands, &name, ¶ms)) > 0)
|
|
{
|
|
data = NULL;
|
|
if (name)
|
|
data = name;
|
|
else
|
|
if (params)
|
|
data = params;
|
|
|
|
switch (cmd)
|
|
{
|
|
case eProperty:
|
|
shgm = mfCompileShaderGenProperty(ef, params);
|
|
if (shgm)
|
|
shg->m_BitMask.AddElem(shgm);
|
|
break;
|
|
|
|
case eVersion:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return shg->m_BitMask.Num() != 0;
|
|
}
|
|
|
|
bool CShader::mfCompileParams(SShader *ef, char *scr)
|
|
{
|
|
char* name;
|
|
long cmd;
|
|
char *params;
|
|
int i;
|
|
char *data;
|
|
|
|
enum {eNoMipmaps=1, eRefracted, eDontSortByDistance, ePolygonOffset, eOverlay, eTemplate, eFogParms, eFogGen, eNoCastShadows, ePortal, eGlare, eHeatMap, eNightMap, eRainMap, eDeformVertexes, eTessSize, eSkyBox, eSkyHDR, eCull, eFogShader, eFogOnly, eSort, eNoSpots, eDetail, eNoDetail, eNormal, eBumpScale, eBumpOffset, eColorMaterial, eShadowMapGen, eNoDraw, eLMIgnoreLights, eLMIgnoreProjLights, eLMBump, eClipPlane, eReflection, eIgnoreDirectionalLight, eNoLight, eHasVColors, eHasAlphaTest, eHasAlphaBlend, eUseParentSort, eUseParentCull, eMotionBlurMap, eScreenProcess, eScreenLuminosityMap, eFlashBangMap, eScreenTexture, eIgnoreResourceState, eUseLightMaterial, eSkyLayerHeight, eDofMap, eDefaultVertexFormat, eOffsetBump, eAllow3DC};
|
|
static tokenDesc commands[] =
|
|
{
|
|
{eNoDraw, "NoDraw"},
|
|
{eNoLight, "NoLight"},
|
|
{eNoMipmaps, "NoMipmaps"},
|
|
{eNoSpots, "NoSpots"},
|
|
{eNoCastShadows, "NoCastShadows"},
|
|
{ePolygonOffset, "PolygonOffset"},
|
|
{eOverlay, "Overlay"},
|
|
{eFogParms, "FogParms"},
|
|
{eFogGen, "FogGen"},
|
|
{ePortal, "Portal"},
|
|
{eTemplate, "Template"},
|
|
{eGlare, "Glare"},
|
|
{eDontSortByDistance, "DontSortByDistance"},
|
|
{eHeatMap, "HeatMap"},
|
|
{eNightMap, "NightMap"},
|
|
{eIgnoreResourceState, "IgnoreResourceState"},
|
|
|
|
{eRainMap, "RainMap"},
|
|
{eDeformVertexes, "DeformVertexes"},
|
|
{eTessSize, "TessSize"},
|
|
{eSkyBox, "SkyBox"},
|
|
{eSkyHDR, "SkyHDR"},
|
|
{eSkyLayerHeight, "SkyLayerHeight"},
|
|
{eCull, "Cull"},
|
|
{eFogShader, "FogShader"},
|
|
{eFogOnly, "FogOnly"},
|
|
{eSort, "Sort"},
|
|
{eDetail, "Detail"},
|
|
{eNoDetail, "NoDetail"},
|
|
{eClipPlane, "ClipPlane"},
|
|
{eReflection, "Reflection"},
|
|
{eNormal, "Normal"},
|
|
{eBumpScale, "BumpScale"},
|
|
{eBumpOffset, "BumpOffset"},
|
|
{eColorMaterial, "ColorMaterial"},
|
|
{eShadowMapGen, "ShadowMapGen"},
|
|
{eRefracted, "Refracted"},
|
|
|
|
{eLMBump, "LMBump"},
|
|
{eLMIgnoreLights, "LMIgnoreLights"},
|
|
{eLMIgnoreProjLights, "LMIgnoreProjLights"},
|
|
|
|
{eIgnoreDirectionalLight, "IgnoreDirectionalLight"},
|
|
|
|
{eHasVColors, "HasVColors"},
|
|
{eHasAlphaTest, "HasAlphaTest"},
|
|
{eHasAlphaBlend, "HasAlphaBlend"},
|
|
{eUseParentSort, "UseParentSort"},
|
|
{eUseParentCull, "UseParentCull"},
|
|
|
|
{eUseLightMaterial, "UseLightMaterial"},
|
|
|
|
// tiago: added
|
|
{eMotionBlurMap, "MotionBlurMap"},
|
|
{eScreenProcess, "ScreenProcess"},
|
|
{eScreenLuminosityMap, "ScreenLuminosityMap" },
|
|
{eFlashBangMap, "FlashBangMap"},
|
|
{eScreenTexture, "ScreenTexture"},
|
|
{eDofMap, "DofMap"},
|
|
{eDefaultVertexFormat, "DefaultVertexFormat"},
|
|
{eOffsetBump, "OffsetBump"},
|
|
{eAllow3DC, "Allow3DC"},
|
|
|
|
{0,0}
|
|
};
|
|
|
|
float fSkyLayerHeight = 0;
|
|
|
|
while ((cmd = shGetObject (&scr, commands, &name, ¶ms)) > 0)
|
|
{
|
|
data = NULL;
|
|
if (name)
|
|
data = name;
|
|
else
|
|
if (params)
|
|
data = params;
|
|
|
|
switch (cmd)
|
|
{
|
|
case eLMBump:
|
|
ef->m_LMFlags |= LMF_BUMPMATERIAL;
|
|
break;
|
|
|
|
case eLMIgnoreLights:
|
|
ef->m_LMFlags |= LMF_IGNORELIGHTS;
|
|
break;
|
|
|
|
case eLMIgnoreProjLights:
|
|
ef->m_LMFlags |= LMF_IGNOREPROJLIGHTS;
|
|
break;
|
|
|
|
case eHasAlphaTest:
|
|
ef->m_Flags3 |= EF3_HASALPHATEST;
|
|
break;
|
|
|
|
case eOffsetBump:
|
|
ef->m_Flags |= EF_OFFSETBUMP;
|
|
break;
|
|
|
|
case eGlare:
|
|
break;
|
|
|
|
case eAllow3DC:
|
|
ef->m_Flags |= EF_ALLOW3DC;
|
|
break;
|
|
|
|
case eUseLightMaterial:
|
|
ef->m_Flags2 |= EF2_USELIGHTMATERIAL;
|
|
break;
|
|
|
|
case eDontSortByDistance:
|
|
ef->m_Flags2 |= EF2_DONTSORTBYDIST;
|
|
break;
|
|
|
|
case eIgnoreResourceState:
|
|
ef->m_Flags2 |= EF2_IGNORERESOURCESTATES;
|
|
break;
|
|
|
|
case eDefaultVertexFormat:
|
|
ef->m_Flags2 |= EF2_DEFAULTVERTEXFORMAT;
|
|
break;
|
|
|
|
case eHasAlphaBlend:
|
|
ef->m_Flags3 |= EF3_HASALPHABLEND;
|
|
break;
|
|
|
|
case eHasVColors:
|
|
ef->m_Flags3 |= EF3_HASVCOLORS;
|
|
break;
|
|
|
|
case eUseParentSort:
|
|
ef->m_Flags3 |= EF3_USEPARENTSORT;
|
|
break;
|
|
|
|
case eUseParentCull:
|
|
ef->m_Flags3 |= EF3_USEPARENTCULL;
|
|
break;
|
|
|
|
case eNoDraw:
|
|
ef->m_Flags3 |= EF3_NODRAW;
|
|
break;
|
|
|
|
case eNoLight:
|
|
ef->m_LMFlags |= LMF_DISABLE;
|
|
break;
|
|
|
|
case eScreenTexture:
|
|
ef->m_Flags3 |= EF3_SCREENTEXTURE;
|
|
break;
|
|
|
|
case eIgnoreDirectionalLight:
|
|
ef->m_Flags3 |= EF3_IGNOREDIRECTIONALLIGHT;
|
|
break;
|
|
|
|
case eReflection:
|
|
ef->m_Flags3 |= EF3_REFLECTION;
|
|
break;
|
|
|
|
case eClipPlane:
|
|
if (!stricmp(data, "Back"))
|
|
ef->m_Flags3 |= EF3_CLIPPLANE_BACK;
|
|
else
|
|
if (!stricmp(data, "Front"))
|
|
ef->m_Flags3 |= EF3_CLIPPLANE_FRONT;
|
|
else
|
|
if (!stricmp(data, "WaterFront"))
|
|
ef->m_Flags3 |= EF3_CLIPPLANE_WATER_FRONT;
|
|
else
|
|
if (!stricmp(data, "WaterBack"))
|
|
ef->m_Flags3 |= EF3_CLIPPLANE_WATER_BACK;
|
|
else
|
|
ef->m_Flags3 |= EF3_CLIPPLANE_FRONT;
|
|
break;
|
|
|
|
case eNoMipmaps:
|
|
ef->m_Flags |= EF_NOMIPMAPS;
|
|
break;
|
|
|
|
case eTemplate:
|
|
ef->m_Flags |= EF_TEMPLNAMES;
|
|
break;
|
|
|
|
case eNoSpots:
|
|
ef->m_Flags |= EF_NOSPOTS;
|
|
break;
|
|
|
|
case eNoCastShadows:
|
|
ef->m_Flags2 |= EF2_NOCASTSHADOWS;
|
|
break;
|
|
|
|
case eNoDetail:
|
|
ef->m_Flags3 |= EF3_NODETAIL;
|
|
break;
|
|
|
|
case eShadowMapGen:
|
|
ef->m_nPreprocess |= FSPR_SHADOWMAPGEN;
|
|
break;
|
|
|
|
case eRefracted:
|
|
ef->m_nPreprocess |= FSPR_REFRACTED;
|
|
break;
|
|
|
|
case ePolygonOffset:
|
|
ef->m_Flags |= EF_POLYGONOFFSET;
|
|
break;
|
|
|
|
case eOverlay:
|
|
ef->m_Flags |= EF_OVERLAY;
|
|
break;
|
|
|
|
case eFogParms:
|
|
mfCompileFogParms(ef, params);
|
|
break;
|
|
|
|
case eFogGen:
|
|
if (!ef->m_FogInfo)
|
|
ef->m_FogInfo = new SFogInfo;
|
|
mfCompileWaveForm(&ef->m_FogInfo->m_WaveFogGen, params);
|
|
break;
|
|
|
|
case ePortal:
|
|
ef->m_nPreprocess |= FSPR_PORTAL;
|
|
break;
|
|
|
|
case eHeatMap:
|
|
ef->m_nPreprocess |= FSPR_HEATVIS;
|
|
break;
|
|
|
|
// tiago: changed preprocessing..
|
|
case eNightMap:
|
|
ef->m_nPreprocess |= FSPR_SCREENTEXMAP; // ePR_NightVis;
|
|
break;
|
|
|
|
case eDofMap:
|
|
ef->m_nPreprocess |= FSPR_DOFMAP;
|
|
break;
|
|
|
|
case eRainMap:
|
|
ef->m_nPreprocess |= FSPR_RAINOVERLAY;
|
|
break;
|
|
|
|
|
|
case eFlashBangMap:
|
|
ef->m_nPreprocess |= FSPR_FLASHBANG;
|
|
break;
|
|
|
|
case eDeformVertexes:
|
|
{
|
|
if (!ef->m_Deforms)
|
|
ef->m_Deforms = new TArray<SDeform>;
|
|
int i = ef->m_Deforms->Num();
|
|
ef->m_Deforms->ReserveNew(i+1);
|
|
SDeform *df = &ef->m_Deforms->Get(i);
|
|
mfCompileDeform(ef, df, name, params);
|
|
}
|
|
break;
|
|
|
|
case eTessSize:
|
|
ef->m_Flags2 |= EF2_TESSSIZE;
|
|
break;
|
|
|
|
case eSkyLayerHeight:
|
|
fSkyLayerHeight = shGetFloat(data);
|
|
break;
|
|
|
|
case eSkyHDR:
|
|
ef->m_Flags |= EF_SKY_HDR;
|
|
break;
|
|
|
|
case eSkyBox:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing SkyBox argument in Shader '%s'\n", ef->m_Name.c_str());
|
|
break;
|
|
}
|
|
if (!ef->m_Sky)
|
|
ef->m_Sky = new SSkyInfo;
|
|
|
|
ef->m_Flags |= EF_SKY;
|
|
|
|
for (i=0; i<3; i++)
|
|
{
|
|
static char *skypostfix[6] = {"12", "34", "5"};
|
|
char nsky[64];
|
|
|
|
sprintf(nsky, "%s_%s", data, skypostfix[i]);
|
|
ef->m_Sky->m_SkyBox[i] = (STexPic*)gRenDev->EF_LoadTexture(nsky, FT_SKY, FT2_NODXT, eTT_Base);
|
|
}
|
|
break;
|
|
|
|
case eCull:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing Cull argument in Shader '%s'\n", ef->m_Name.c_str());
|
|
ef->m_eCull = eCULL_Back;
|
|
break;
|
|
}
|
|
ef->m_Flags |= EF_HASCULL;
|
|
if (!stricmp(data, "None") || !stricmp(data, "TwoSided") || !stricmp(data, "Disable"))
|
|
ef->m_eCull = eCULL_None;
|
|
else
|
|
if (!strnicmp(data, "Back", 4))
|
|
ef->m_eCull = eCULL_Back;
|
|
else
|
|
if (!strnicmp(data, "Front", 5))
|
|
ef->m_eCull = eCULL_Front;
|
|
else
|
|
Warning( 0,0,"Warning: invalid Cull parm '%s' in Shader '%s'\n", data, ef->m_Name.c_str());
|
|
break;
|
|
|
|
case eDetail:
|
|
break;
|
|
|
|
case eFogShader:
|
|
case eFogOnly:
|
|
ef->m_Flags |= EF_FOGSHADER;
|
|
break;
|
|
|
|
case eNormal:
|
|
if (!ef->m_NormGen)
|
|
ef->m_NormGen = new SNormalsGen;
|
|
if (!stricmp(data, "Custom"))
|
|
{
|
|
ef->m_NormGen->m_eNormal = eNORM_Custom;
|
|
if (!params || !params[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing RgbStyle Fixed value in Shader '%s' (use 1.0)\n", ef->m_Name.c_str());
|
|
ef->m_NormGen->m_CustomNormal = Vec3d(1, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
shGetVector(params, ef->m_NormGen->m_CustomNormal);
|
|
}
|
|
}
|
|
else
|
|
if (!stricmp(data, "Wave"))
|
|
{
|
|
ef->m_NormGen->m_eNormal = eNORM_Wave;
|
|
mfCompileWaveForm(&ef->m_NormGen->m_WaveEvalNormal, params);
|
|
}
|
|
else
|
|
if (!strnicmp(data, "Front", 5))
|
|
ef->m_NormGen->m_eNormal = eNORM_Front;
|
|
else
|
|
if (!strnicmp(data, "Back", 4))
|
|
ef->m_NormGen->m_eNormal = eNORM_Back;
|
|
else
|
|
if (!stricmp(data, "Edge"))
|
|
ef->m_NormGen->m_eNormal = eNORM_Edge;
|
|
else
|
|
if (!stricmp(data, "InvEdge"))
|
|
ef->m_NormGen->m_eNormal = eNORM_InvEdge;
|
|
break;
|
|
|
|
case eSort:
|
|
if (!stricmp(data, "ZBuff"))
|
|
ef->m_eSort = eS_ZBuff;
|
|
else
|
|
if (!stricmp(data, "Portal"))
|
|
ef->m_nPreprocess |= FSPR_PORTAL;
|
|
else
|
|
if (!stricmp(data, "Stencil"))
|
|
ef->m_eSort = eS_Stencil;
|
|
else
|
|
if (!stricmp(data, "Terrain"))
|
|
ef->m_eSort = eS_Terrain;
|
|
else
|
|
if (!stricmp(data, "TerrainShadowPass"))
|
|
ef->m_eSort = eS_TerrainShadowPass;
|
|
else
|
|
if (!stricmp(data, "TerrainLightPass"))
|
|
ef->m_eSort = eS_TerrainLightPass;
|
|
else
|
|
if (!stricmp(data, "TerrainDetailTextures"))
|
|
ef->m_eSort = eS_TerrainDetailTextures;
|
|
else
|
|
if (!stricmp(data, "WaterBeach"))
|
|
ef->m_eSort = eS_WaterBeach;
|
|
else
|
|
if (!stricmp(data, "TerrainDetailObjects"))
|
|
ef->m_eSort = eS_TerrainDetailObjects;
|
|
else
|
|
if (!stricmp(data, "TerrainParticles"))
|
|
ef->m_eSort = eS_Particles;
|
|
else
|
|
if (!stricmp(data, "Sky"))
|
|
ef->m_eSort = eS_Sky;
|
|
else
|
|
if (!stricmp(data, "Opaque"))
|
|
ef->m_eSort = eS_Opaque;
|
|
else
|
|
if (!strnicmp(data, "Tree", 4))
|
|
ef->m_eSort = eS_Trees;
|
|
else
|
|
if (!strnicmp(data, "Sprite", 6))
|
|
ef->m_eSort = eS_Sprites;
|
|
else
|
|
if (!stricmp(data, "Decal"))
|
|
ef->m_eSort = eS_Decal;
|
|
else
|
|
if (!stricmp(data, "SeeThrough"))
|
|
ef->m_eSort = eS_SeeThrough;
|
|
else
|
|
if (!stricmp(data, "Shadowmap"))
|
|
ef->m_eSort = eS_ShadowMap;
|
|
else
|
|
if (!stricmp(data, "Banner"))
|
|
ef->m_eSort = eS_Banner;
|
|
else
|
|
if (!stricmp(data, "UnderWater"))
|
|
ef->m_eSort = eS_UnderWater;
|
|
else
|
|
if (!stricmp(data, "MuzzleFlash"))
|
|
ef->m_eSort = eS_MuzzleFlash;
|
|
else
|
|
if (!stricmp(data, "Water"))
|
|
ef->m_eSort = eS_Water;
|
|
else
|
|
if (!stricmp(data, "Additive"))
|
|
ef->m_eSort = eS_Additive;
|
|
else
|
|
if (!stricmp(data, "Nearest"))
|
|
ef->m_eSort = eS_Nearest;
|
|
else
|
|
if (!stricmp(data, "OcclusionTest"))
|
|
ef->m_eSort = eS_OcclusionTest;
|
|
else
|
|
if (!stricmp(data, "HeatVision"))
|
|
ef->m_eSort = eS_HeatVision;
|
|
else
|
|
if (!stricmp(data, "Glare"))
|
|
ef->m_eSort = eS_Glare;
|
|
else
|
|
if (!stricmp(data, "HDR"))
|
|
ef->m_eSort = eS_HDR;
|
|
else
|
|
if (!strnicmp(data, "Refract", 7))
|
|
ef->m_eSort = eS_Refractive;
|
|
else
|
|
if (!stricmp(data, "Preprocess"))
|
|
ef->m_eSort = eS_PreProcess;
|
|
else
|
|
{
|
|
if (!isdigit(data[0]))
|
|
Warning( 0,0,"Warning: Bad Sort value '%s' in Shader '%s'\n", data, ef->m_Name.c_str());
|
|
else
|
|
{
|
|
i = shGetInt(data);
|
|
if (i <= 0 || i >= eS_Max)
|
|
Warning( 0,0,"Warning: Sort value '%s' out of range in Shader '%s'\n", data, ef->m_Name.c_str());
|
|
else
|
|
ef->m_eSort = (EF_Sort)i;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case eBumpScale:
|
|
//ef->m_fBumpScale = shGetFloat(data);
|
|
break;
|
|
|
|
case eBumpOffset:
|
|
//ef->m_fBumpOffset = shGetFloat(data);
|
|
break;
|
|
|
|
case eColorMaterial:
|
|
ef->m_LMFlags |= LMF_COLMAT_AMB;
|
|
break;
|
|
|
|
default:
|
|
Warning( 0,0,"Warning: Unknown general Shader parameter '%s' in '%s'\n", params, ef->m_Name.c_str());
|
|
return false;
|
|
}
|
|
}
|
|
if (ef->m_Sky)
|
|
ef->m_Sky->m_fSkyLayerHeight = fSkyLayerHeight;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CShader::mfCompilePublic(SShader *ef, char *scr)
|
|
{
|
|
char* name;
|
|
long cmd;
|
|
char *params;
|
|
char *data;
|
|
|
|
enum {eByte=1, eShort, eInt, eFloat, eString, eColor, eVector};
|
|
static tokenDesc commands[] =
|
|
{
|
|
{eByte, "Byte"},
|
|
{eShort, "Short"},
|
|
{eInt, "Int"},
|
|
{eFloat, "Float"},
|
|
{eString, "String"},
|
|
{eColor, "Color"},
|
|
{eVector, "Vector"},
|
|
|
|
{0,0}
|
|
};
|
|
|
|
while ((cmd = shGetObject (&scr, commands, &name, ¶ms)) > 0)
|
|
{
|
|
data = NULL;
|
|
if (name)
|
|
data = name;
|
|
else
|
|
if (params)
|
|
data = params;
|
|
|
|
SShaderParam pr;
|
|
pr.m_Type = eType_UNKNOWN;
|
|
|
|
switch (cmd)
|
|
{
|
|
case eByte:
|
|
pr.m_Type = eType_BYTE;
|
|
strlwr(name);
|
|
strncpy(pr.m_Name, name, 32);
|
|
pr.m_Value.m_Byte = shGetInt(params);
|
|
break;
|
|
|
|
case eShort:
|
|
pr.m_Type = eType_SHORT;
|
|
strlwr(name);
|
|
strncpy(pr.m_Name, name, 32);
|
|
pr.m_Value.m_Short = shGetInt(params);
|
|
break;
|
|
|
|
case eInt:
|
|
pr.m_Type = eType_INT;
|
|
strlwr(name);
|
|
strncpy(pr.m_Name, name, 32);
|
|
pr.m_Value.m_Int = shGetInt(params);
|
|
break;
|
|
|
|
case eFloat:
|
|
pr.m_Type = eType_FLOAT;
|
|
strlwr(name);
|
|
strncpy(pr.m_Name, name, 32);
|
|
pr.m_Value.m_Float = shGetFloat(params);
|
|
break;
|
|
|
|
case eColor:
|
|
pr.m_Type = eType_FCOLOR;
|
|
strlwr(name);
|
|
strncpy(pr.m_Name, name, 32);
|
|
shGetColor(params, pr.m_Value.m_Color);
|
|
break;
|
|
|
|
case eVector:
|
|
pr.m_Type = eType_VECTOR;
|
|
strlwr(name);
|
|
strncpy(pr.m_Name, name, 32);
|
|
shGetVector(params, pr.m_Value.m_Vector);
|
|
break;
|
|
|
|
case eString:
|
|
{
|
|
pr.m_Type = eType_STRING;
|
|
strlwr(name);
|
|
strncpy(pr.m_Name, name, 32);
|
|
|
|
size_t len = strlen(params)+1;
|
|
char *str = new char[len];
|
|
strcpy(str, params);
|
|
pr.m_Value.m_String = str;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
Warning( 0,0,"Warning: Unknown general Shader public parameter '%s' in '%s'\n", params, ef->m_Name.c_str());
|
|
return false;
|
|
}
|
|
if (pr.m_Type != eType_UNKNOWN)
|
|
ef->m_PublicParams.AddElem(pr);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool CShader::mfCompileRenderParams(SShader *ef, char *scr)
|
|
{
|
|
char* name;
|
|
long cmd;
|
|
char *params;
|
|
char *data;
|
|
|
|
enum {eDrawWater=1, eDrawTerrain, eDrawPlayer, eDrawDetailTextures, eDrawDetailObjects, eDrawIndoors, eDrawFarSprites, eDrawStaticObjects, eDrawEntities, eDrawParticles, eUseLights, eUpdateFactor, eFullDetailTerrain};
|
|
static tokenDesc commands[] =
|
|
{
|
|
{eDrawWater, "DrawWater"},
|
|
{eDrawPlayer, "DrawPlayer"},
|
|
{eDrawTerrain, "DrawTerrain"},
|
|
{eDrawDetailTextures, "DrawDetailTextures"},
|
|
{eDrawDetailObjects, "DrawDetailObjects"},
|
|
{eDrawIndoors, "DrawIndoors"},
|
|
{eDrawFarSprites, "DrawFarSprites"},
|
|
{eDrawStaticObjects, "DrawStaticObjects"},
|
|
{eDrawEntities, "DrawEntities"},
|
|
{eDrawParticles, "DrawParticles"},
|
|
{eUseLights, "UseLights"},
|
|
{eUpdateFactor, "UpdateFactor"},
|
|
{eFullDetailTerrain, "FullDetailTerrain"},
|
|
|
|
{0,0}
|
|
};
|
|
|
|
while ((cmd = shGetObject (&scr, commands, &name, ¶ms)) > 0)
|
|
{
|
|
data = NULL;
|
|
if (name)
|
|
data = name;
|
|
else
|
|
if (params)
|
|
data = params;
|
|
switch (cmd)
|
|
{
|
|
case eDrawWater:
|
|
ef->m_DLDFlags |= DLD_TERRAIN_WATER;
|
|
break;
|
|
|
|
case eDrawPlayer:
|
|
ef->m_DLDFlags |= DLD_FIRST_PERSON_CAMERA_OWNER;
|
|
break;
|
|
|
|
case eDrawTerrain:
|
|
ef->m_DLDFlags |= DLD_TERRAIN;
|
|
break;
|
|
|
|
case eDrawDetailTextures:
|
|
ef->m_DLDFlags |= DLD_DETAIL_TEXTURES;
|
|
break;
|
|
|
|
case eDrawDetailObjects:
|
|
ef->m_DLDFlags |= DLD_DETAIL_OBJECTS;
|
|
break;
|
|
|
|
case eFullDetailTerrain:
|
|
ef->m_DLDFlags |= DLD_TERRAIN_FULLRES;
|
|
break;
|
|
|
|
case eDrawIndoors:
|
|
// ef->m_DLDFlags |= DLD_INDOORS;
|
|
break;
|
|
|
|
case eDrawFarSprites:
|
|
ef->m_DLDFlags |= DLD_FAR_SPRITES;
|
|
break;
|
|
|
|
case eDrawStaticObjects:
|
|
ef->m_DLDFlags |= DLD_STATIC_OBJECTS;
|
|
break;
|
|
|
|
case eDrawEntities:
|
|
ef->m_DLDFlags |= DLD_ENTITIES;
|
|
break;
|
|
|
|
case eDrawParticles:
|
|
ef->m_DLDFlags |= DLD_PARTICLES;
|
|
break;
|
|
|
|
case eUseLights:
|
|
// ef->m_DLDFlags |= DLD_ADD_LIGHTSOURCES;
|
|
break;
|
|
|
|
case eUpdateFactor:
|
|
ef->m_fUpdateFactor = shGetFloat(data);
|
|
break;
|
|
|
|
default:
|
|
Warning( 0,0,"Warning: Unknown general Shader render parameter '%s' in '%s'\n", params, ef->m_Name.c_str());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void sGetBlend (char *data, SShader *ef, uint *src, uint *dst)
|
|
{
|
|
char *token;
|
|
char sbfsrc[32];
|
|
char sbfdst[32];
|
|
int bfsrc, bfdst;
|
|
|
|
token = strtok(data, " ");
|
|
if (!token)
|
|
{
|
|
Warning( 0,0,"Warning: invalid Blend name '%s' in Shader '%s'\n", data, ef->m_Name.c_str());
|
|
return;
|
|
}
|
|
strcpy(sbfsrc, token);
|
|
token = strtok(NULL, " ");
|
|
if (!token)
|
|
{
|
|
Warning( 0,0,"Warning: invalid Blend name '%s' in Shader '%s'\n", data, ef->m_Name.c_str());
|
|
return;
|
|
}
|
|
strcpy(sbfdst, token);
|
|
|
|
// find SRC factor
|
|
if (!stricmp(sbfsrc, "ONE"))
|
|
bfsrc = GS_BLSRC_ONE;
|
|
else
|
|
if (!stricmp(sbfsrc, "ZERO"))
|
|
bfsrc = GS_BLSRC_ZERO;
|
|
else
|
|
if (!stricmp(sbfsrc, "DST_COLOR"))
|
|
bfsrc = GS_BLSRC_DSTCOL;
|
|
else
|
|
if (!stricmp(sbfsrc, "ONE_MINUS_DST_COLOR"))
|
|
bfsrc = GS_BLSRC_ONEMINUSDSTCOL;
|
|
else
|
|
if (!stricmp(sbfsrc, "SRC_ALPHA") || !stricmp(sbfsrc, "SrcAlpha"))
|
|
bfsrc = GS_BLSRC_SRCALPHA;
|
|
else
|
|
if (!stricmp(sbfsrc, "ONE_MINUS_SRC_ALPHA") || !stricmp(sbfsrc, "InvSrcAlpha"))
|
|
bfsrc = GS_BLSRC_ONEMINUSSRCALPHA;
|
|
else
|
|
if (!stricmp(sbfsrc, "DST_ALPHA"))
|
|
bfsrc = GS_BLSRC_DSTALPHA;
|
|
else
|
|
if (!stricmp(sbfsrc, "ONE_MINUS_DST_ALPHA"))
|
|
bfsrc = GS_BLSRC_ONEMINUSDSTALPHA;
|
|
else
|
|
if (!stricmp(sbfsrc, "SRC_ALPHA_SATURATE"))
|
|
bfsrc = GS_BLSRC_ALPHASATURATE;
|
|
else
|
|
{
|
|
Warning( 0,0,"Warning: unknown SRC BlendMode '%s' in Shader '%s', substituting ONE\n", sbfsrc, ef->m_Name.c_str());
|
|
bfsrc = GS_BLSRC_ONE;
|
|
}
|
|
|
|
// find DST factor
|
|
if (!stricmp(sbfdst, "ONE"))
|
|
bfdst = GS_BLDST_ONE;
|
|
else
|
|
if (!stricmp(sbfdst, "ZERO"))
|
|
bfdst = GS_BLDST_ZERO;
|
|
else
|
|
if (!stricmp(sbfdst, "SRC_ALPHA") || !stricmp(sbfsrc, "SrcAlpha"))
|
|
bfdst = GS_BLDST_SRCALPHA;
|
|
else
|
|
if (!stricmp(sbfdst, "ONE_MINUS_SRC_ALPHA") || !stricmp(sbfsrc, "InvSrcAlpha"))
|
|
bfdst = GS_BLDST_ONEMINUSSRCALPHA;
|
|
else
|
|
if (!stricmp(sbfdst, "DST_ALPHA"))
|
|
bfdst = GS_BLDST_DSTALPHA;
|
|
else
|
|
if (!stricmp(sbfdst, "ONE_MINUS_DST_ALPHA"))
|
|
bfdst = GS_BLDST_ONEMINUSDSTALPHA;
|
|
else
|
|
if (!stricmp(sbfdst, "SRC_COLOR"))
|
|
bfdst = GS_BLDST_SRCCOL;
|
|
else
|
|
if (!stricmp(sbfdst, "ONE_MINUS_SRC_COLOR"))
|
|
bfdst = GS_BLDST_ONEMINUSSRCCOL;
|
|
else
|
|
{
|
|
Warning( 0,0,"Warning: unknown DST BlendMode '%s' in Shader '%s', substituting ONE\n", sbfdst, ef->m_Name.c_str());
|
|
bfdst = GS_BLDST_ONE;
|
|
}
|
|
*src = bfsrc;
|
|
*dst = bfdst;
|
|
}
|
|
|
|
uint CShader::mfCompileRendState(SShader *ef, SShaderPass *sm, char *scr)
|
|
{
|
|
char* name;
|
|
long cmd;
|
|
char *params;
|
|
char *data;
|
|
|
|
enum {eBlend = 1, eNoColorMask, eColorMaskOnlyAlpha, eColorMaskOnlyRGB, eColorMaskOnlyColor, eAlphaFunc, eDepthFunc, eDepthWrite, eDepthMask, eNoDepthTest, ePolyLine, eDepthTest};
|
|
static tokenDesc commands[] =
|
|
{
|
|
{eBlend, "Blend"},
|
|
{eDepthFunc, "DepthFunc"},
|
|
{eAlphaFunc, "AlphaFunc"},
|
|
{eNoColorMask, "NoColorMask"},
|
|
{eColorMaskOnlyAlpha, "ColorMaskOnlyAlpha"},
|
|
{eColorMaskOnlyRGB, "ColorMaskOnlyRGB"},
|
|
{eColorMaskOnlyColor, "ColorMaskOnlyColor"},
|
|
{ePolyLine, "PolyLine"},
|
|
{eDepthMask, "DepthMask"},
|
|
{eDepthWrite, "DepthWrite"},
|
|
{eNoDepthTest, "NoDepthTest"},
|
|
{eDepthTest, "DepthTest"},
|
|
{0,0}
|
|
};
|
|
|
|
uint af = 0;
|
|
uint df = 0;
|
|
uint bfsrc = 0;
|
|
uint bfdst = 0;
|
|
uint dm = GS_DEPTHWRITE;
|
|
|
|
while ((cmd = shGetObject (&scr, commands, &name, ¶ms)) > 0)
|
|
{
|
|
data = NULL;
|
|
if (params)
|
|
data = params;
|
|
else
|
|
if (name)
|
|
data = name;
|
|
|
|
switch (cmd)
|
|
{
|
|
case eNoColorMask:
|
|
af |= GS_NOCOLMASK;
|
|
break;
|
|
|
|
case eColorMaskOnlyAlpha:
|
|
af |= GS_COLMASKONLYALPHA;
|
|
break;
|
|
|
|
case eColorMaskOnlyRGB:
|
|
case eColorMaskOnlyColor:
|
|
af |= GS_COLMASKONLYRGB;
|
|
break;
|
|
|
|
case ePolyLine:
|
|
af |= GS_POLYLINE;
|
|
break;
|
|
|
|
case eAlphaFunc:
|
|
if (!stricmp(data, "GT0"))
|
|
af = GS_ALPHATEST_GREATER0;
|
|
else
|
|
if (!stricmp(data, "LT128"))
|
|
af = GS_ALPHATEST_LESS128;
|
|
else
|
|
if (!stricmp(data, "GE128"))
|
|
af = GS_ALPHATEST_GEQUAL128;
|
|
else
|
|
Warning( 0,0,"Warning: invalid AlphaFunc name '%s' in Shader '%s'\n", data, ef->m_Name.c_str());
|
|
break;
|
|
|
|
case eDepthFunc:
|
|
if (!stricmp(data, "LEqual"))
|
|
df = 0;
|
|
else
|
|
if (!stricmp(data, "Equal"))
|
|
df = GS_DEPTHFUNC_EQUAL;
|
|
else
|
|
Warning( 0,0,"Warning: unknown DepthFunc name '%s' in Shader '%s'\n", data, ef->m_Name.c_str());
|
|
break;
|
|
|
|
case eBlend:
|
|
sGetBlend(data, ef, &bfsrc, &bfdst);
|
|
dm = 0;
|
|
break;
|
|
|
|
case eDepthMask:
|
|
case eDepthWrite:
|
|
if (data && data[0])
|
|
{
|
|
if (shGetBool(data))
|
|
{
|
|
dm |= GS_DEPTHWRITE;
|
|
ef->m_Flags3 |= EF3_DEPTHWRITE;
|
|
}
|
|
else
|
|
{
|
|
dm &= ~GS_DEPTHWRITE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dm |= GS_DEPTHWRITE;
|
|
ef->m_Flags3 |= EF3_DEPTHWRITE;
|
|
}
|
|
break;
|
|
|
|
case eDepthTest:
|
|
if (data && data[0])
|
|
{
|
|
if (!shGetBool(data))
|
|
dm |= GS_NODEPTHTEST;
|
|
else
|
|
dm &= ~GS_NODEPTHTEST;
|
|
}
|
|
else
|
|
dm &= ~GS_NODEPTHTEST;
|
|
break;
|
|
|
|
case eNoDepthTest:
|
|
dm |= GS_NODEPTHTEST;
|
|
dm &= ~GS_DEPTHWRITE;
|
|
break;
|
|
}
|
|
}
|
|
uint factor = dm | df | bfsrc | bfdst | af;
|
|
|
|
return factor;
|
|
}
|
|
|
|
byte sGetColorOp(char *data, SShader *ef)
|
|
{
|
|
if (!stricmp(data, "NoSet"))
|
|
return eCO_NOSET;
|
|
else
|
|
if (!stricmp(data, "Disable") || !stricmp(data, "None"))
|
|
return eCO_DISABLE;
|
|
else
|
|
if (!stricmp(data, "Replace") || !stricmp(data, "SelectArg1"))
|
|
return eCO_REPLACE;
|
|
else
|
|
if (!stricmp(data, "SelectArg2"))
|
|
return eCO_ARG2;
|
|
else
|
|
if (!stricmp(data, "Decal"))
|
|
return eCO_DECAL;
|
|
else
|
|
if (!stricmp(data, "BlendDiffuseAlpha"))
|
|
return eCO_BLENDDIFFUSEALPHA;
|
|
else
|
|
if (!stricmp(data, "Modulate"))
|
|
return eCO_MODULATE;
|
|
else
|
|
if (!stricmp(data, "Modulate4X"))
|
|
return eCO_MODULATE4X;
|
|
else
|
|
if (!stricmp(data, "Modulate2X"))
|
|
return eCO_MODULATE2X;
|
|
else
|
|
if (!stricmp(data, "Add"))
|
|
return eCO_ADD;
|
|
else
|
|
if (!stricmp(data, "MultiplyAdd"))
|
|
return eCO_MULTIPLYADD;
|
|
else
|
|
if (!stricmp(data, "AddSigned") || !stricmp(data, "Add_Signed"))
|
|
return eCO_ADDSIGNED;
|
|
else
|
|
if (!stricmp(data, "AddSigned2X"))
|
|
return eCO_ADDSIGNED2X;
|
|
else
|
|
if (!stricmp(data, "BumpEnvMap"))
|
|
return eCO_BUMPENVMAP;
|
|
else
|
|
if (!stricmp(data, "MODULATEALPHA_ADDCOLOR"))
|
|
return eCO_MODULATEALPHA_ADDCOLOR;
|
|
else
|
|
if (!stricmp(data, "MODULATECOLOR_ADDALPHA"))
|
|
return eCO_MODULATECOLOR_ADDALPHA;
|
|
else
|
|
if (!stricmp(data, "MODULATEINVALPHA_ADDCOLOR"))
|
|
return eCO_MODULATEINVALPHA_ADDCOLOR;
|
|
else
|
|
if (!stricmp(data, "MODULATEINVCOLOR_ADDALPHA"))
|
|
return eCO_MODULATEINVCOLOR_ADDALPHA;
|
|
else
|
|
if (!stricmp(data, "DOTPRODUCT3"))
|
|
return eCO_DOTPRODUCT3;
|
|
else
|
|
if (!stricmp(data, "LERP"))
|
|
return eCO_LERP;
|
|
else
|
|
if (!stricmp(data, "SUBTRACT"))
|
|
return eCO_SUBTRACT;
|
|
else
|
|
{
|
|
Warning( 0,0,"Warning: unknown TexColorOp parameter '%s' in Shader '%s' (Skipping)\n", data, ef->m_Name.c_str());
|
|
return eCO_MODULATE;
|
|
}
|
|
}
|
|
|
|
byte sGetColorArg(char *data, SShader *ef)
|
|
{
|
|
if (!stricmp(data, "Texture"))
|
|
return eCA_Texture;
|
|
else
|
|
if (!stricmp(data, "Diffuse"))
|
|
return eCA_Diffuse;
|
|
else
|
|
if (!stricmp(data, "Specular"))
|
|
return eCA_Specular;
|
|
else
|
|
if (!stricmp(data, "Previous") || !stricmp(data, "Current"))
|
|
return eCA_Previous;
|
|
else
|
|
if (!stricmp(data, "Constant") || !stricmp(data, "TFactor"))
|
|
return eCA_Constant;
|
|
else
|
|
{
|
|
Warning( 0,0,"Warning: unknown TexColorArg parameter '%s' in Shader '%s' (Skipping)\n", data, ef->m_Name.c_str());
|
|
return eCA_Texture;
|
|
}
|
|
}
|
|
|
|
bool CShader::mfCompileLayer(SShader *ef, int nl, char *scr, SShaderPass *sm)
|
|
{
|
|
char* name;
|
|
long cmd;
|
|
char *params;
|
|
char *data;
|
|
|
|
char mapname[128] = "";
|
|
uint af = 0;
|
|
uint df = 0;
|
|
uint ctc = 0;
|
|
uint bfsrc = 0;
|
|
uint bfdst = 0;
|
|
uint dm = GS_DEPTHWRITE;
|
|
ETexType eTT = eTT_Base;
|
|
bool bNoMips = false;
|
|
int BumpDet = 0;
|
|
int Flags2 = 0;
|
|
bool bProjected = false;
|
|
float fBumpAmount = -1.0f;
|
|
bool bNoScale = false;
|
|
|
|
SShaderTexUnit *ml;
|
|
if (!sm)
|
|
{
|
|
ef->m_Passes.ReserveNew(nl+1);
|
|
sm = &ef->m_Passes[nl];
|
|
sm->m_RenderState = GS_DEPTHWRITE;
|
|
sm->mfAddNewTexUnits(1);
|
|
ml = &sm->m_TUnits[0];
|
|
}
|
|
else
|
|
{
|
|
sm->mfAddNewTexUnits(1);
|
|
ml = &sm->m_TUnits[sm->m_TUnits.Num()-1];
|
|
}
|
|
ml->m_eColorOp = eCO_MODULATE;
|
|
ml->m_eAlphaOp = eCO_MODULATE;
|
|
if (sm->m_TUnits.Num() == 1)
|
|
{
|
|
ml->m_eColorArg = eCA_Texture | (eCA_Diffuse << 3);
|
|
ml->m_eAlphaArg = eCA_Texture | (eCA_Diffuse << 3);
|
|
}
|
|
else
|
|
{
|
|
ml->m_eColorArg = eCA_Texture | (eCA_Previous << 3);
|
|
ml->m_eAlphaArg = eCA_Texture | (eCA_Previous << 3);
|
|
}
|
|
|
|
enum {eMap = 1, eBlend, eProjected, eNoColorMask, eColorMaskOnlyAlpha, eColorMaskOnlyRGB, eColorMaskOnlyColor, eNoDXT, eAlphaFunc, eDepthFunc, eDepthWrite, eClampTexCoords, eUClamp, eVClamp, ergbGen, eAlphaGen, eTexGen, etcGen, eDepthMask, eNoDepthTest, eDepthTest, eSequence, eTexType, eNoMipmaps, eBumpDetect, eTexColorOp, eTexAlphaOp, eTexColorArg0, eTexColorArg1, eTexColorArg2, eTexAlphaArg0, eTexAlphaArg1, eTexAlphaArg2, eForceOpaque, ePolyLine, eBumpAmount, eTexLodBias, eBumpHighRes, eBumpLowRes, eBumpCompressed, eBumpInverted, eSecondPassRendState, eRendState, eTexFilter, eTexNoScale, eHDRTexColorOp};
|
|
static tokenDesc commands[] =
|
|
{
|
|
{eMap, "Map"},
|
|
{eTexType, "TexType"},
|
|
{eBlend, "Blend"},
|
|
{eProjected, "Projected"},
|
|
{eRendState, "RendState"},
|
|
{eSecondPassRendState, "SecondPassRendState"},
|
|
{eDepthFunc, "DepthFunc"},
|
|
{eAlphaFunc, "AlphaFunc"},
|
|
{eClampTexCoords, "ClampTexCoords"},
|
|
{eUClamp, "UClamp"},
|
|
{eVClamp, "VClamp"},
|
|
{ergbGen, "rgbGen"},
|
|
{eNoColorMask, "NoColorMask"},
|
|
{eNoDXT, "NoDXT"},
|
|
{eColorMaskOnlyAlpha, "ColorMaskOnlyAlpha"},
|
|
{eColorMaskOnlyRGB, "ColorMaskOnlyRGB"},
|
|
{eColorMaskOnlyColor, "ColorMaskOnlyColor"},
|
|
{eAlphaGen, "AlphaGen"},
|
|
{eTexGen, "TexGen"},
|
|
{ePolyLine, "PolyLine"},
|
|
{etcGen, "tcGen"},
|
|
{eDepthMask, "DepthMask"},
|
|
{eDepthWrite, "DepthWrite"},
|
|
{eNoDepthTest, "NoDepthTest"},
|
|
{eDepthTest, "DepthTest"},
|
|
{eSequence, "Sequence"},
|
|
{eNoMipmaps, "NoMipmaps"},
|
|
{eBumpDetect, "BumpDetect"},
|
|
{eBumpAmount, "BumpAmount"},
|
|
{eBumpHighRes, "BumpHighRes"},
|
|
{eBumpLowRes, "BumpLowRes"},
|
|
{eBumpCompressed, "BumpCompressed"},
|
|
{eBumpInverted, "BumpInverted"},
|
|
{eTexColorOp, "TexColorOp"},
|
|
{eTexAlphaOp, "TexAlphaOp"},
|
|
{eTexColorArg0, "TexColorArg0"},
|
|
{eTexColorArg1, "TexColorArg1"},
|
|
{eTexColorArg2, "TexColorArg2"},
|
|
{eTexAlphaArg0, "TexAlphaArg0"},
|
|
{eTexAlphaArg1, "TexAlphaArg1"},
|
|
{eTexAlphaArg2, "TexAlphaArg2"},
|
|
{eTexLodBias, "TexLodBias"},
|
|
{eTexNoScale, "TexNoScale"},
|
|
|
|
{eTexFilter, "TexFilter"},
|
|
|
|
{eForceOpaque, "ForceOpaque"},
|
|
{eHDRTexColorOp, "HDRTexColorOp"},
|
|
{0,0}
|
|
};
|
|
|
|
while ((cmd = shGetObject (&scr, commands, &name, ¶ms)) > 0)
|
|
{
|
|
data = NULL;
|
|
if (name)
|
|
data = name;
|
|
else
|
|
if (params)
|
|
data = params;
|
|
|
|
switch (cmd)
|
|
{
|
|
case eMap:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing Map argument for layer %d in Shader '%s'\n", sm-&ef->m_Passes[0], ef->m_Name.c_str());
|
|
break;
|
|
}
|
|
strcpy(mapname, data);
|
|
break;
|
|
|
|
case eNoColorMask:
|
|
af |= GS_NOCOLMASK;
|
|
break;
|
|
|
|
case eNoDXT:
|
|
Flags2 |= FT2_NODXT;
|
|
break;
|
|
|
|
case eTexNoScale:
|
|
bNoScale = true;
|
|
break;
|
|
|
|
case eTexFilter:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing TexFilter argument for layer %d in Shader '%s'\n", sm-&ef->m_Passes[0], ef->m_Name.c_str());
|
|
break;
|
|
}
|
|
if (!stricmp(data, "Bilinear"))
|
|
Flags2 |= FT2_FILTER_BILINEAR;
|
|
else
|
|
if (!stricmp(data, "Trilinear"))
|
|
Flags2 |= FT2_FILTER_TRILINEAR;
|
|
else
|
|
if (!stricmp(data, "Nearest"))
|
|
Flags2 |= FT2_FILTER_NEAREST;
|
|
else
|
|
if (!stricmp(data, "Anisotropic"))
|
|
Flags2 |= FT2_FILTER_ANISOTROPIC;
|
|
else
|
|
{
|
|
Warning( 0,0,"Warning: unknown TexFilter argument (%s) for layer %d in Shader '%s'\n", data, sm-&ef->m_Passes[0], ef->m_Name.c_str());
|
|
}
|
|
break;
|
|
|
|
case eSecondPassRendState:
|
|
sm->m_SecondRenderState = mfCompileRendState(ef, sm, params);
|
|
sm->m_Flags |= SHPF_USEDSECONDRS;
|
|
break;
|
|
|
|
case eRendState:
|
|
sm->m_RenderState = mfCompileRendState(ef, sm, params);
|
|
break;
|
|
|
|
case eColorMaskOnlyAlpha:
|
|
af |= GS_COLMASKONLYALPHA;
|
|
break;
|
|
|
|
case eColorMaskOnlyRGB:
|
|
case eColorMaskOnlyColor:
|
|
af |= GS_COLMASKONLYRGB;
|
|
break;
|
|
|
|
case eTexType:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing TexType argument for layer %d in Shader '%s'\n", sm-&ef->m_Passes[0], ef->m_Name.c_str());
|
|
break;
|
|
}
|
|
if (!strnicmp(data, "Base", 4))
|
|
eTT = eTT_Base;
|
|
else
|
|
if (!strnicmp(data, "Bump", 4))
|
|
eTT = eTT_Bumpmap;
|
|
else
|
|
if (!strnicmp(data, "DSDTBump", 8))
|
|
eTT = eTT_DSDTBump;
|
|
else
|
|
if (!strnicmp(data, "Volume", 6))
|
|
eTT = eTT_3D;
|
|
else
|
|
if (!strnicmp(data, "Cube", 4))
|
|
eTT = eTT_Cubemap;
|
|
else
|
|
{
|
|
Warning( 0,0,"Warning: unknown TexType argument (%s) for layer %d in Shader '%s'\n", data, sm-&ef->m_Passes[0], ef->m_Name.c_str());
|
|
eTT = eTT_Base;
|
|
}
|
|
break;
|
|
|
|
case eSequence:
|
|
mfCompileSequence(ef, ml, nl, params, eTT, 0, Flags2, fBumpAmount);
|
|
break;
|
|
|
|
case eForceOpaque:
|
|
ef->m_Flags2 |= EF2_HASOPAQUE;
|
|
ml->m_nFlags |= FTU_OPAQUE;
|
|
break;
|
|
|
|
case eNoMipmaps:
|
|
bNoMips = true;
|
|
break;
|
|
|
|
case eTexLodBias:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing TexLodBias argument for layer %d in Shader '%s'\n", sm-&ef->m_Passes[0], ef->m_Name.c_str());
|
|
break;
|
|
}
|
|
ml->m_fTexFilterLodBias = shGetFloat(data);
|
|
break;
|
|
|
|
case eBumpAmount:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing BumpAmount argument for layer %d in Shader '%s'\n", sm-&ef->m_Passes[0], ef->m_Name.c_str());
|
|
break;
|
|
}
|
|
fBumpAmount = CLAMP(shGetFloat(data), 2.0f, 100.0f);
|
|
break;
|
|
|
|
case eBumpHighRes:
|
|
Flags2 |= FT2_BUMPHIGHRES;
|
|
break;
|
|
|
|
case eBumpLowRes:
|
|
Flags2 |= FT2_BUMPLOWRES;
|
|
break;
|
|
|
|
case eBumpCompressed:
|
|
Flags2 |= FT2_BUMPCOMPRESED;
|
|
break;
|
|
|
|
case eBumpInverted:
|
|
Flags2 |= FT2_BUMPINVERTED;
|
|
break;
|
|
|
|
case eProjected:
|
|
bProjected = true;
|
|
break;
|
|
|
|
case eBumpDetect:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing BumpDetect argument for layer %d in Shader '%s'\n", sm-&ef->m_Passes[0], ef->m_Name.c_str());
|
|
break;
|
|
}
|
|
if (!stricmp(data, "Red"))
|
|
BumpDet = FT_BUMP_DETRED;
|
|
else
|
|
if (!stricmp(data, "Blue"))
|
|
BumpDet = FT_BUMP_DETBLUE;
|
|
else
|
|
if (!stricmp(data, "Intensity"))
|
|
BumpDet = FT_BUMP_DETINTENS;
|
|
else
|
|
if (!stricmp(data, "Alpha"))
|
|
BumpDet = FT_BUMP_DETALPHA;
|
|
else
|
|
{
|
|
Warning( 0,0,"Warning: invalid BumpDetect argument '%s' in Shader '%s'\n", data, ef->m_Name.c_str());
|
|
BumpDet = FT_BUMP_DETINTENS;
|
|
}
|
|
break;
|
|
|
|
case ePolyLine:
|
|
af |= GS_POLYLINE;
|
|
break;
|
|
|
|
case eAlphaFunc:
|
|
if (!stricmp(data, "GT0"))
|
|
af = GS_ALPHATEST_GREATER0;
|
|
else
|
|
if (!stricmp(data, "LT128"))
|
|
af = GS_ALPHATEST_LESS128;
|
|
else
|
|
if (!stricmp(data, "GE128"))
|
|
af = GS_ALPHATEST_GEQUAL128;
|
|
else
|
|
Warning( 0,0,"Warning: invalid AlphaFunc name '%s' in Shader '%s'\n", data, ef->m_Name.c_str());
|
|
break;
|
|
|
|
case eDepthFunc:
|
|
if (!stricmp(data, "LEqual"))
|
|
df = 0;
|
|
else
|
|
if (!stricmp(data, "Equal"))
|
|
df = GS_DEPTHFUNC_EQUAL;
|
|
else
|
|
if (!strnicmp(data, "Great", 5))
|
|
df = GS_DEPTHFUNC_GREAT;
|
|
else
|
|
Warning( 0,0,"Warning: unknown DepthFunc name '%s' in Shader '%s'\n", data, ef->m_Name.c_str());
|
|
break;
|
|
|
|
case eClampTexCoords:
|
|
ctc |= GS_TEXPARAM_CLAMP;
|
|
break;
|
|
|
|
case eUClamp:
|
|
ctc |= GS_TEXPARAM_UCLAMP;
|
|
break;
|
|
|
|
case eVClamp:
|
|
ctc |= GS_TEXPARAM_VCLAMP;
|
|
break;
|
|
|
|
case eTexColorOp:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing parameters for TexColorOp in Shader '%s' (Skipping)\n", ef->m_Name.c_str());
|
|
break;
|
|
}
|
|
ml->m_eColorOp = sGetColorOp(data, ef);
|
|
break;
|
|
|
|
case eHDRTexColorOp:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing parameters for HDRTexColorOp in Shader '%s' (Skipping)\n", ef->m_Name.c_str());
|
|
break;
|
|
}
|
|
ml->m_eHDRColorOp = sGetColorOp(data, ef);
|
|
break;
|
|
|
|
case eTexAlphaOp:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing parameters for TexAlphaOp in Shader '%s' (Skipping)\n", ef->m_Name.c_str());
|
|
break;
|
|
}
|
|
ml->m_eAlphaOp = sGetColorOp(data, ef);
|
|
break;
|
|
|
|
case eTexColorArg0:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing parameters for TexColorArg0 in Shader '%s' (Skipping)\n", ef->m_Name.c_str());
|
|
break;
|
|
}
|
|
ml->m_eColorArg &= ~7;
|
|
ml->m_eColorArg |= sGetColorArg(data, ef);
|
|
break;
|
|
|
|
case eTexColorArg1:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing parameters for TexColorArg1 in Shader '%s' (Skipping)\n", ef->m_Name.c_str());
|
|
break;
|
|
}
|
|
ml->m_eColorArg &= ~(7<<3);
|
|
ml->m_eColorArg |= sGetColorArg(data, ef) << 3;
|
|
break;
|
|
|
|
case eTexColorArg2:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing parameters for TexColorArg2 in Shader '%s' (Skipping)\n", ef->m_Name.c_str());
|
|
break;
|
|
}
|
|
ml->m_eColorArg &= ~(7<<6);
|
|
ml->m_eColorArg |= sGetColorArg(data, ef) << 6;
|
|
break;
|
|
|
|
case eTexAlphaArg0:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing parameters for TexAlphaArg0 in Shader '%s' (Skipping)\n", ef->m_Name.c_str());
|
|
break;
|
|
}
|
|
ml->m_eAlphaArg &= ~7;
|
|
ml->m_eAlphaArg |= sGetColorArg(data, ef);
|
|
break;
|
|
|
|
case eTexAlphaArg1:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing parameters for TexAlphaArg1 in Shader '%s' (Skipping)\n", ef->m_Name.c_str());
|
|
break;
|
|
}
|
|
ml->m_eAlphaArg &= ~(7<<3);
|
|
ml->m_eAlphaArg |= sGetColorArg(data, ef) << 3;
|
|
break;
|
|
|
|
case eTexAlphaArg2:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing parameters for TexAlphaArg2 in Shader '%s' (Skipping)\n", ef->m_Name.c_str());
|
|
break;
|
|
}
|
|
ml->m_eAlphaArg &= ~(7<<6);
|
|
ml->m_eAlphaArg |= sGetColorArg(data, ef) << 6;
|
|
break;
|
|
|
|
case eBlend:
|
|
sGetBlend(data, ef, &bfsrc, &bfdst);
|
|
dm = 0;
|
|
break;
|
|
|
|
case ergbGen:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing parameters for rgbGen in Shader '%s' (Skipping)\n", ef->m_Name.c_str());
|
|
break;
|
|
}
|
|
ef->m_Flags3 |= EF3_HASRGBGEN;
|
|
if (!stricmp(data, "Wave"))
|
|
{
|
|
sm->m_WaveEvalRGB = new SWaveForm;
|
|
mfCompileWaveForm(sm->m_WaveEvalRGB, params);
|
|
sm->m_eEvalRGB = eERGB_Wave;
|
|
}
|
|
else
|
|
if (!stricmp(data, "Noise"))
|
|
{
|
|
sm->m_RGBNoise = new SRGBGenNoise;
|
|
mfCompileRGBNoise(sm->m_RGBNoise, params, ef);
|
|
sm->m_eEvalRGB = eERGB_Noise;
|
|
}
|
|
else
|
|
if (!strnicmp(data, "Comp", 4))
|
|
{
|
|
sm->m_RGBComps = new SParam;
|
|
mfCompileParamComps(sm->m_RGBComps, params, ef);
|
|
sm->m_eEvalRGB = eERGB_Comps;
|
|
}
|
|
else
|
|
if (!stricmp(data, "Identity"))
|
|
sm->m_eEvalRGB = eERGB_Identity;
|
|
else
|
|
if (!stricmp(data, "NoFill"))
|
|
sm->m_eEvalRGB = eERGB_NoFill;
|
|
else
|
|
if (!stricmp(data, "Object") || !strnicmp(data, "FromObj", 7))
|
|
sm->m_eEvalRGB = eERGB_Object;
|
|
else
|
|
if (!stricmp(data, "OneMinusObject"))
|
|
sm->m_eEvalRGB = eERGB_OneMinusObject;
|
|
else
|
|
if (!stricmp(data, "RE") || !stricmp(data, "FromRE"))
|
|
sm->m_eEvalRGB = eERGB_RE;
|
|
else
|
|
if (!stricmp(data, "OneMinusRE"))
|
|
sm->m_eEvalRGB = eERGB_OneMinusRE;
|
|
else
|
|
if (!stricmp(data, "World") || !stricmp(data, "FromWorld") || !stricmp(data, "WorldColor"))
|
|
sm->m_eEvalRGB = eERGB_World;
|
|
else
|
|
if (!stricmp(data, "FromClient"))
|
|
{
|
|
sm->m_eEvalRGB = eERGB_FromClient;
|
|
sm->m_eEvalAlpha = eEALPHA_FromClient;
|
|
}
|
|
else
|
|
if (!stricmp(data, "OneMinusFromClient"))
|
|
sm->m_eEvalRGB = eERGB_OneMinusFromClient;
|
|
else
|
|
if (!stricmp(data, "Fixed"))
|
|
{
|
|
sm->m_eEvalRGB = eERGB_Fixed;
|
|
sm->m_eEvalAlpha = eEALPHA_Fixed;
|
|
if (!params || !params[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing RgbGen Fixed value in Shader '%s' (use 1.0)\n", ef->m_Name.c_str());
|
|
sm->m_FixedColor.bcolor[0] = 255;
|
|
sm->m_FixedColor.bcolor[1] = 255;
|
|
sm->m_FixedColor.bcolor[2] = 255;
|
|
}
|
|
else
|
|
{
|
|
CFColor col;
|
|
shGetColor(params, col);
|
|
COLCONV(col);
|
|
sm->m_FixedColor.dcolor = col.GetTrue();
|
|
}
|
|
}
|
|
else
|
|
if (!stricmp(data, "Style"))
|
|
{
|
|
mfCompileRGBAStyle(params, ef, sm, true);
|
|
sm->m_eEvalRGB = eERGB_StyleIntens;
|
|
}
|
|
else
|
|
Warning( 0,0,"Warning: unknown rgbGen parameter '%s' in Shader '%s'\n", data, ef->m_Name.c_str());
|
|
break;
|
|
|
|
case eAlphaGen:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing parameters for AlphaGen in Shader '%s' (Skipping)\n", ef->m_Name.c_str());
|
|
break;
|
|
}
|
|
ef->m_Flags3 |= EF3_HASALPHAGEN;
|
|
if (!stricmp(data, "Wave"))
|
|
{
|
|
sm->m_WaveEvalAlpha = new SWaveForm;
|
|
mfCompileWaveForm(sm->m_WaveEvalAlpha, params);
|
|
sm->m_eEvalAlpha = eEALPHA_Wave;
|
|
}
|
|
else
|
|
if (!stricmp(data, "Noise"))
|
|
{
|
|
sm->m_ANoise = new SAlphaGenNoise;
|
|
mfCompileAlphaNoise(sm->m_ANoise, params, ef);
|
|
sm->m_eEvalAlpha = eEALPHA_Noise;
|
|
}
|
|
else
|
|
if (!stricmp(data, "Style"))
|
|
{
|
|
mfCompileRGBAStyle(params, ef, sm, false);
|
|
sm->m_eEvalAlpha = eEALPHA_Style;
|
|
}
|
|
else
|
|
if (!stricmp(data, "Identity"))
|
|
sm->m_eEvalAlpha = eEALPHA_Identity;
|
|
else
|
|
if (!strnicmp(data, "Comp", 4))
|
|
{
|
|
sm->m_RGBComps = new SParam;
|
|
mfCompileParamComps(sm->m_RGBComps, params, ef);
|
|
sm->m_eEvalAlpha = eEALPHA_Comps;
|
|
}
|
|
else
|
|
if (!stricmp(data, "NoFill"))
|
|
sm->m_eEvalAlpha = eEALPHA_NoFill;
|
|
else
|
|
if (!stricmp(data, "Object") || !strnicmp(data, "FromObj", 7))
|
|
sm->m_eEvalAlpha = eEALPHA_Object;
|
|
else
|
|
if (!stricmp(data, "OneMinusObject"))
|
|
sm->m_eEvalAlpha = eEALPHA_OneMinusObject;
|
|
else
|
|
if (!stricmp(data, "RE") || !stricmp(data, "FromRE"))
|
|
sm->m_eEvalAlpha = eEALPHA_RE;
|
|
else
|
|
if (!stricmp(data, "OneMinusRE"))
|
|
sm->m_eEvalAlpha = eEALPHA_OneMinusRE;
|
|
else
|
|
if (!stricmp(data, "World") || !stricmp(data, "FromWorld") || !stricmp(data, "WorldColor"))
|
|
sm->m_eEvalAlpha = eEALPHA_World;
|
|
else
|
|
if (!stricmp(data, "FromClient"))
|
|
sm->m_eEvalAlpha = eEALPHA_FromClient;
|
|
else
|
|
if (!stricmp(data, "OneMinusFromClient"))
|
|
sm->m_eEvalAlpha = eEALPHA_OneMinusFromClient;
|
|
else
|
|
if (!stricmp(data, "Portal"))
|
|
sm->m_eEvalAlpha = eEALPHA_Portal;
|
|
else
|
|
if (!stricmp(data, "Fixed"))
|
|
{
|
|
sm->m_eEvalAlpha = eEALPHA_Fixed;
|
|
if (!params || !params[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing AlphaGen Fixed value in Shader '%s' (use 1.0)\n", ef->m_Name.c_str());
|
|
sm->m_FixedColor.bcolor[3] = 255;
|
|
}
|
|
else
|
|
sm->m_FixedColor.bcolor[3] = (int)(shGetFloat(params) * 255.0);
|
|
}
|
|
else
|
|
if (!stricmp(data, "Beam"))
|
|
{
|
|
sm->m_eEvalAlpha = eEALPHA_Beam;
|
|
}
|
|
else
|
|
Warning( 0,0,"Warning: unknown AlphaGen parameter '%s' in Shader '%s'\n", data, ef->m_Name.c_str());
|
|
break;
|
|
|
|
case eTexGen:
|
|
case etcGen:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing parameters for TexGen in Shader '%s' (Skipping)\n", ef->m_Name.c_str());
|
|
break;
|
|
}
|
|
if (!stricmp(data, "NoFill"))
|
|
ml->m_eGenTC = eGTC_NoFill;
|
|
else
|
|
if (!stricmp(data, "Environment"))
|
|
ml->m_eGenTC = eGTC_Environment;
|
|
else
|
|
if (!stricmp(data, "SphereMap"))
|
|
ml->m_eGenTC = eGTC_SphereMap;
|
|
else
|
|
if (!stricmp(data, "Projection"))
|
|
ml->m_eGenTC = eGTC_Projection;
|
|
else
|
|
if (!stricmp(data, "SphereMapEnvironment"))
|
|
ml->m_eGenTC = eGTC_SphereMapEnvironment;
|
|
else
|
|
if (!stricmp(data, "ShadowMap"))
|
|
ml->m_eGenTC = eGTC_ShadowMap;
|
|
else
|
|
if (!stricmp(data, "Lightmap"))
|
|
ml->m_eGenTC = eGTC_LightMap;
|
|
else
|
|
if (!stricmp(data, "Quad"))
|
|
ml->m_eGenTC = eGTC_Quad;
|
|
else
|
|
if (!stricmp(data, "Texture") || !stricmp(data, "Base"))
|
|
ml->m_eGenTC = eGTC_Base;
|
|
else
|
|
if (!mfCompileTexGen(name, params, ef, ml))
|
|
Warning( 0,0,"Warning: unknown TexGen parameter '%s' in Shader '%s'\n", data, ef->m_Name.c_str());
|
|
break;
|
|
|
|
case eDepthMask:
|
|
case eDepthWrite:
|
|
if (data && data[0])
|
|
{
|
|
if (shGetBool(data))
|
|
{
|
|
dm |= GS_DEPTHWRITE;
|
|
ef->m_Flags3 |= EF3_DEPTHWRITE;
|
|
}
|
|
else
|
|
{
|
|
dm &= ~GS_DEPTHWRITE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dm |= GS_DEPTHWRITE;
|
|
ef->m_Flags3 |= EF3_DEPTHWRITE;
|
|
}
|
|
break;
|
|
|
|
case eNoDepthTest:
|
|
dm |= GS_NODEPTHTEST;
|
|
dm &= ~GS_DEPTHWRITE;
|
|
break;
|
|
|
|
case eDepthTest:
|
|
if (data && data[0])
|
|
{
|
|
if (!shGetBool(data))
|
|
dm |= GS_NODEPTHTEST;
|
|
else
|
|
dm &= ~GS_NODEPTHTEST;
|
|
}
|
|
else
|
|
dm &= ~GS_NODEPTHTEST;
|
|
break;
|
|
|
|
default:
|
|
Warning( 0,0,"Warning: unknown parameter '%s' in Shader '%s' for layer %d\n", strtok(params, " \n"), ef->m_Name.c_str(), sm - &ef->m_Passes[0]);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/*if (bfsrc == GS_BLSRC_ONE && bfdst == GS_BLDST_ZERO)
|
|
{
|
|
bfsrc = bfdst = 0;
|
|
dm = GS_DEPTHWRITE;
|
|
}
|
|
if (bf1src == GS_BLSRC_ONE && bf1dst == GS_BLDST_ZERO)
|
|
{
|
|
bf1src = bf1dst = 0;
|
|
dm1 = GS_DEPTHWRITE;
|
|
}*/
|
|
sm->m_RenderState = ctc | df | af | dm | bfsrc | bfdst;
|
|
|
|
int State = sm->m_RenderState;
|
|
int mp = ((ef->m_Flags & EF_NOMIPMAPS) || bNoMips) ? FT_NOMIPS : 0;
|
|
mp |= BumpDet;
|
|
if (ef->m_eClass == eSH_Screen)
|
|
mp |= FT_NOREMOVE;
|
|
if (bNoScale)
|
|
mp |= FT_NORESIZE;
|
|
if (ctc & GS_TEXPARAM_CLAMP)
|
|
{
|
|
mp |= FT_CLAMP;
|
|
ml->m_nFlags |= FTU_CLAMP;
|
|
}
|
|
if (ctc & GS_TEXPARAM_UCLAMP)
|
|
{
|
|
Flags2 |= FT2_UCLAMP;
|
|
ml->m_nFlags |= FTU_CLAMP;
|
|
}
|
|
if (ctc & GS_TEXPARAM_VCLAMP)
|
|
{
|
|
Flags2 |= FT2_VCLAMP;
|
|
ml->m_nFlags |= FTU_CLAMP;
|
|
}
|
|
if (bProjected)
|
|
{
|
|
mp |= FT_PROJECTED;
|
|
ml->m_nFlags |= FTU_PROJECTED;
|
|
}
|
|
if (bNoMips)
|
|
ml->m_nFlags |= FTU_NOMIPS;
|
|
if (eTT == eTT_Bumpmap || eTT == eTT_DSDTBump)
|
|
{
|
|
if ((gRenDev->GetFeatures() & RFT_BUMP))
|
|
{
|
|
State = GS_BUMP;
|
|
ef->m_LMFlags |= LMF_BUMPMATERIAL;
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
if (!ml->m_TexPic)
|
|
ml->m_TexPic = mfCheckTemplateTexName(mapname, eTT, ml->m_nFlags);
|
|
|
|
if (Flags2 & FT2_FILTER_BILINEAR)
|
|
ml->m_nFlags |= FTU_FILTERBILINEAR;
|
|
else
|
|
if (Flags2 & FT2_FILTER_TRILINEAR)
|
|
ml->m_nFlags |= FTU_FILTERTRILINEAR;
|
|
else
|
|
if (Flags2 & FT2_FILTER_NEAREST)
|
|
ml->m_nFlags |= FTU_FILTERNEAREST;
|
|
|
|
if (!ml->m_TexPic)
|
|
{
|
|
if (mapname[0])
|
|
{
|
|
if (stricmp(mapname, "$None") != 0)
|
|
ml->m_TexPic = (STexPic*)gRenDev->EF_LoadTexture(mapname, mp, Flags2, eTT, fBumpAmount);
|
|
}
|
|
}
|
|
|
|
if (stricmp(mapname, "$None") && !ml->m_TexPic)
|
|
{
|
|
if (!gRenDev->m_IsDedicated)
|
|
Warning( 0,0,"Warning: Couldn't load Texture '%s' in Shader '%s'\n", mapname, ef->m_Name.c_str());
|
|
return false;
|
|
}
|
|
ml->m_eTexType = eTT;
|
|
if (ml->m_TexPic == &gRenDev->m_TexMan->m_Templates[EFTT_DIFFUSE])
|
|
ef->m_Flags |= EF_HASDIFFUSEMAP;
|
|
|
|
if (!(sm->m_Flags & SHPF_USEDSECONDRS))
|
|
sm->m_SecondRenderState = sm->m_RenderState;
|
|
|
|
return true;
|
|
}
|
|
|
|
void CShader::mfCompileOrient(SShader *ef, int num, char *scr)
|
|
{
|
|
char* name;
|
|
long cmd;
|
|
char *params;
|
|
char *data;
|
|
SOrient *orn;
|
|
|
|
enum {eX = 1, eY, eOrigin};
|
|
static tokenDesc commands[] =
|
|
{
|
|
{eX, "X"},
|
|
{eY, "Y"},
|
|
{eOrigin, "Origin"},
|
|
{0,0}
|
|
};
|
|
|
|
if (num >= MAX_ORIENTS)
|
|
{
|
|
Warning( 0,0,"Warning: MAX_ORIENTS hit\n");
|
|
return;
|
|
}
|
|
orn = &m_Orients[num];
|
|
if (num >= m_NumOrients)
|
|
m_NumOrients = num+1;
|
|
memset(orn, 0, sizeof(SOrient));
|
|
|
|
while ((cmd = shGetObject (&scr, commands, &name, ¶ms)) > 0)
|
|
{
|
|
data = NULL;
|
|
if (name)
|
|
data = name;
|
|
else
|
|
if (params)
|
|
data = params;
|
|
|
|
switch (cmd)
|
|
{
|
|
case eX:
|
|
shGetVector(data, orn->m_Coord.m_Vecs[1]);
|
|
if (GetLengthSquared(orn->m_Coord.m_Vecs[1]) == 0)
|
|
orn->m_Flags |= FOR_ORTHO;
|
|
else
|
|
orn->m_Coord.m_Vecs[1].Normalize();
|
|
break;
|
|
|
|
case eY:
|
|
shGetVector(data, orn->m_Coord.m_Vecs[2]);
|
|
orn->m_Coord.m_Vecs[2].Normalize();
|
|
break;
|
|
|
|
case eOrigin:
|
|
shGetVector(data, orn->m_Coord.m_Org);
|
|
break;
|
|
}
|
|
}
|
|
orn->m_Coord.m_Vecs[0] = orn->m_Coord.m_Vecs[1] ^ orn->m_Coord.m_Vecs[2];
|
|
}
|
|
|
|
//==================================================================================================
|
|
|
|
void CShader::mfCompileLightMove(SShader *ef, char *nameMove, SLightEval *le, char *scr)
|
|
{
|
|
char* name;
|
|
long cmd;
|
|
char *params;
|
|
char *data;
|
|
|
|
enum {eDirection = 1, eWave, eSpeed};
|
|
static tokenDesc commands[] =
|
|
{
|
|
{eDirection, "Direction"},
|
|
{eWave, "Wave"},
|
|
{eSpeed, "Speed"},
|
|
{0,0}
|
|
};
|
|
|
|
if (le->m_LightMove)
|
|
delete le->m_LightMove;
|
|
le->m_LightMove = new SLightMove;
|
|
if (!stricmp(nameMove, "Wave"))
|
|
le->m_LightMove->m_eLMType = eLMT_Wave;
|
|
else
|
|
if (!stricmp(nameMove, "Patch"))
|
|
le->m_LightMove->m_eLMType = eLMT_Patch;
|
|
else
|
|
Warning( 0,0,"Warning: Unknown LightMove Type int shader '%s'\n", ef->m_Name.c_str());
|
|
le->m_LightMove->m_Dir = Vec3d(0,0,1);
|
|
|
|
while ((cmd = shGetObject (&scr, commands, &name, ¶ms)) > 0)
|
|
{
|
|
data = NULL;
|
|
if (name)
|
|
data = name;
|
|
else
|
|
if (params)
|
|
data = params;
|
|
switch (cmd)
|
|
{
|
|
case eDirection:
|
|
shGetVector(data, le->m_LightMove->m_Dir);
|
|
break;
|
|
|
|
case eSpeed:
|
|
le->m_LightMove->m_fSpeed = shGetFloat(data);
|
|
break;
|
|
|
|
case eWave:
|
|
mfCompileWaveForm(&le->m_LightMove->m_Wave, params);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CShader::mfCompileEvalLight(SShader *ef, char *scr)
|
|
{
|
|
char* name;
|
|
long cmd;
|
|
char *params;
|
|
char *data;
|
|
|
|
enum {eStyle = 1, eUpdateStyle, eProjRotate, eLightRotate, eLightMove, eLightOffset, eLightPos};
|
|
static tokenDesc commands[] =
|
|
{
|
|
{eStyle, "Style"},
|
|
{eUpdateStyle, "UpdateStyle"},
|
|
{eProjRotate, "ProjRotate"},
|
|
{eLightRotate, "LightRotate"},
|
|
{eLightMove, "LightMove"},
|
|
{eLightPos, "LightPos"},
|
|
{eLightOffset, "LightOffset"},
|
|
{0,0}
|
|
};
|
|
|
|
if (ef->m_EvalLights)
|
|
delete ef->m_EvalLights;
|
|
ef->m_EvalLights = new SLightEval;
|
|
|
|
while ((cmd = shGetObject (&scr, commands, &name, ¶ms)) > 0)
|
|
{
|
|
data = NULL;
|
|
if (name)
|
|
data = name;
|
|
else
|
|
if (params)
|
|
data = params;
|
|
switch (cmd)
|
|
{
|
|
case eStyle:
|
|
ef->m_EvalLights->m_LightStyle = shGetInt(data);
|
|
break;
|
|
|
|
case eUpdateStyle:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing parameters for UpdateStyle in Shader '%s' (Skipping)\n", ef->m_Name.c_str());
|
|
break;
|
|
}
|
|
if (!strnicmp(data, "Intens", 6))
|
|
ef->m_EvalLights->m_EStyleType = eLS_Intensity;
|
|
else
|
|
if (!stricmp(data, "Color") || !stricmp(data, "RGB"))
|
|
ef->m_EvalLights->m_EStyleType = eLS_RGB;
|
|
else
|
|
Warning( 0,0,"Warning: unknown UpdateStyle parameter '%s' in Shader '%s' (Skipping)\n", data, ef->m_Name.c_str());
|
|
break;
|
|
|
|
case eProjRotate:
|
|
mfCompileParamComps(&ef->m_EvalLights->m_ProjRotate, data, ef);
|
|
break;
|
|
|
|
case eLightRotate:
|
|
shGetVector(data, ef->m_EvalLights->m_LightRotate);
|
|
break;
|
|
|
|
case eLightMove:
|
|
mfCompileLightMove(ef, name, ef->m_EvalLights, params);
|
|
break;
|
|
|
|
case eLightOffset:
|
|
case eLightPos:
|
|
shGetVector(data, ef->m_EvalLights->m_LightOffset);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static int sGetOp(char *op, SShader *ef)
|
|
{
|
|
if (!stricmp(op, "KEEP"))
|
|
return FSS_STENCOP_KEEP;
|
|
if (!stricmp(op, "REPLACE"))
|
|
return FSS_STENCOP_REPLACE;
|
|
if (!stricmp(op, "INCR"))
|
|
return FSS_STENCOP_INCR;
|
|
if (!stricmp(op, "DECR"))
|
|
return FSS_STENCOP_DECR;
|
|
if (!stricmp(op, "ZERO"))
|
|
return FSS_STENCOP_ZERO;
|
|
|
|
Warning( 0,0,"Invalid StencilOp '%s' in Shader '%s\n", op, ef->m_Name.c_str());
|
|
return FSS_STENCOP_KEEP;
|
|
}
|
|
|
|
void CShader::mfCompileStencil(SShader *ef, char *scr)
|
|
{
|
|
char* name;
|
|
long cmd;
|
|
char *params;
|
|
char *data;
|
|
int n = 0;
|
|
|
|
if (!ef->m_State)
|
|
return;
|
|
|
|
ef->m_State->m_Stencil = new SStencil;
|
|
SStencil *sm = ef->m_State->m_Stencil;
|
|
|
|
enum {eFunc = 1, eOp};
|
|
static tokenDesc commands[] =
|
|
{
|
|
{eFunc, "Func"},
|
|
{eOp, "Op"},
|
|
{0,0}
|
|
};
|
|
|
|
while ((cmd = shGetObject (&scr, commands, &name, ¶ms)) > 0)
|
|
{
|
|
data = NULL;
|
|
if (name)
|
|
data = name;
|
|
else
|
|
if (params)
|
|
data = params;
|
|
|
|
switch (cmd)
|
|
{
|
|
case eFunc:
|
|
{
|
|
char func[3][32];
|
|
sscanf(data, "%s %s %s", func[0], func[1], func[2]);
|
|
if (!stricmp(func[0], "ALWAYS"))
|
|
sm->m_State |= FSS_STENCFUNC_ALWAYS;
|
|
else
|
|
if (!stricmp(func[0], "NEVER"))
|
|
sm->m_State |= FSS_STENCFUNC_NEVER;
|
|
else
|
|
if (!stricmp(func[0], "LESS"))
|
|
sm->m_State |= FSS_STENCFUNC_LESS;
|
|
else
|
|
if (!stricmp(func[0], "LEQUAL"))
|
|
sm->m_State |= FSS_STENCFUNC_LEQUAL;
|
|
else
|
|
if (!stricmp(func[0], "GREATER"))
|
|
sm->m_State |= FSS_STENCFUNC_GREATER;
|
|
else
|
|
if (!stricmp(func[0], "GEQUAL"))
|
|
sm->m_State |= FSS_STENCFUNC_GEQUAL;
|
|
else
|
|
if (!stricmp(func[0], "EQUAL"))
|
|
sm->m_State |= FSS_STENCFUNC_EQUAL;
|
|
else
|
|
if (!stricmp(func[0], "NOTEQUAL"))
|
|
sm->m_State |= FSS_STENCFUNC_NOTEQUAL;
|
|
else
|
|
Warning( 0,0,"invalid StencilFunc '%s' in Shader '%s\n", func[0]);
|
|
|
|
sm->m_FuncRef = atol(func[1]);
|
|
sm->m_FuncMask = atol(func[2]);
|
|
}
|
|
break;
|
|
|
|
case eOp:
|
|
{
|
|
char func[3][32];
|
|
sscanf(data, "%s %s %s", func[0], func[1], func[2]);
|
|
sm->m_State |= sGetOp(func[0], ef) << FSS_STENCFAIL_SHIFT;
|
|
sm->m_State |= sGetOp(func[1], ef) << FSS_STENCZFAIL_SHIFT;
|
|
sm->m_State |= sGetOp(func[2], ef) << FSS_STENCPASS_SHIFT;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CShader::mfCompileState(SShader *ef, char *scr)
|
|
{
|
|
char* name;
|
|
long cmd;
|
|
char *params;
|
|
char *data;
|
|
|
|
enum {eStencil = 1, eBlend, eAlphaGen, eRGBGen, eCullFront, eDepthFunc, eAlphaFunc, eDepthMask, eDepthWrite, eNoDepthTest, eNoColorMask, eColorMask, eClampTexCoords, eClearStencil, ePolyLine, eNoCull};
|
|
static tokenDesc commands[] =
|
|
{
|
|
{eStencil, "Stencil"},
|
|
{eClearStencil, "ClearStencil"},
|
|
{eBlend, "Blend"},
|
|
{eNoCull, "NoCull"},
|
|
{eCullFront, "CullFront"},
|
|
{eDepthFunc, "DepthFunc"},
|
|
{eAlphaFunc, "AlphaFunc"},
|
|
{eDepthMask, "DepthMask"},
|
|
{eDepthWrite, "DepthWrite"},
|
|
{eNoDepthTest, "NoDepthTest"},
|
|
{ePolyLine, "PolyLine"},
|
|
{eNoColorMask, "NoColorMask"},
|
|
{eColorMask, "ColorMask"},
|
|
{eClampTexCoords, "ClampTexCoords"},
|
|
{eAlphaGen, "AlphaGen"},
|
|
{eRGBGen, "RGBGen"},
|
|
{0,0}
|
|
};
|
|
|
|
ef->m_State = new SEfState;
|
|
ef->m_State->m_Stencil = NULL;
|
|
ef->m_State->m_Flags = 0;
|
|
ef->m_State->m_bClearStencil = false;
|
|
ef->m_State->m_State = 0;
|
|
ef->m_State->m_FixedColor[0] = ef->m_State->m_FixedColor[1] = ef->m_State->m_FixedColor[2] = ef->m_State->m_FixedColor[3] = 0;
|
|
int dm = GS_DEPTHWRITE;
|
|
uint bfsrc = 0;
|
|
uint bfdst = 0;
|
|
int af = 0;
|
|
int ctc = 0;
|
|
int df = 0;
|
|
|
|
|
|
while ((cmd = shGetObject (&scr, commands, &name, ¶ms)) > 0)
|
|
{
|
|
data = NULL;
|
|
if (name)
|
|
data = name;
|
|
else
|
|
if (params)
|
|
data = params;
|
|
switch (cmd)
|
|
{
|
|
case eStencil:
|
|
mfCompileStencil(ef, data);
|
|
break;
|
|
|
|
case eClearStencil:
|
|
ef->m_State->m_bClearStencil = true;
|
|
break;
|
|
|
|
case eBlend:
|
|
sGetBlend(data, ef, &bfsrc, &bfdst);
|
|
dm = 0;
|
|
ef->m_State->m_Flags = ESF_STATE;
|
|
break;
|
|
|
|
case eAlphaGen:
|
|
ef->m_State->m_Flags |= ESF_ALPHAGEN;
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing parameters for AlphaGen in Shader '%s' (Skipping)\n", ef->m_Name.c_str());
|
|
break;
|
|
}
|
|
if (!stricmp(data, "Fixed"))
|
|
{
|
|
ef->m_State->m_eEvalAlpha = eEALPHA_Fixed;
|
|
if (!params || !params[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing AlphaGen Fixed value in Shader '%s' (use 1.0)\n", ef->m_Name.c_str());
|
|
ef->m_State->m_FixedColor[3] = 255;
|
|
}
|
|
else
|
|
ef->m_State->m_FixedColor[3] = (int)(shGetFloat(params) * 255.0);
|
|
}
|
|
break;
|
|
|
|
case eRGBGen:
|
|
ef->m_State->m_Flags |= ESF_RGBGEN;
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing parameters for AlphaGen in Shader '%s' (Skipping)\n", ef->m_Name.c_str());
|
|
break;
|
|
}
|
|
if (!stricmp(data, "Fixed"))
|
|
{
|
|
ef->m_State->m_eEvalRGB = eERGB_Fixed;
|
|
if (!params || !params[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing RgbGen Fixed value in Shader '%s' (use 1.0)\n", ef->m_Name.c_str());
|
|
ef->m_State->m_FixedColor[0] = 255;
|
|
ef->m_State->m_FixedColor[1] = 255;
|
|
ef->m_State->m_FixedColor[2] = 255;
|
|
}
|
|
else
|
|
{
|
|
CFColor col;
|
|
shGetColor(params, col);
|
|
COLCONV(col);
|
|
ef->m_State->m_FixedColor[0] = (int)(col[0] * 255.0);
|
|
ef->m_State->m_FixedColor[1] = (int)(col[1] * 255.0);
|
|
ef->m_State->m_FixedColor[2] = (int)(col[2] * 255.0);
|
|
ef->m_State->m_FixedColor[3] = (int)(col[3] * 255.0);
|
|
}
|
|
}
|
|
else
|
|
Warning( 0,0,"Warning: unknown rgbGen parameter '%s' in Shader '%s'\n", data, ef->m_Name.c_str());
|
|
break;
|
|
|
|
case eColorMask:
|
|
ef->m_State->m_Flags |= ESF_COLORMASK;
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing parameters for ColorMask in Shader '%s' (Skipping)\n", ef->m_Name.c_str());
|
|
break;
|
|
}
|
|
if (!params || !params[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing ColorMask values in Shader '%s' (use 1.0)\n", ef->m_Name.c_str());
|
|
ef->m_State->m_ColorMask[0] = 1;
|
|
ef->m_State->m_ColorMask[1] = 1;
|
|
ef->m_State->m_ColorMask[2] = 1;
|
|
}
|
|
else
|
|
{
|
|
CFColor col;
|
|
shGetColor(params, col);
|
|
ef->m_State->m_ColorMask[0] = (int)(col[0]);
|
|
ef->m_State->m_ColorMask[1] = (int)(col[1]);
|
|
ef->m_State->m_ColorMask[2] = (int)(col[2]);
|
|
ef->m_State->m_ColorMask[3] = (int)(col[3]);
|
|
}
|
|
break;
|
|
|
|
case eDepthMask:
|
|
case eDepthWrite:
|
|
ef->m_State->m_Flags |= ESF_STATE;
|
|
if (data && data[0])
|
|
{
|
|
if (shGetBool(data))
|
|
dm |= GS_DEPTHWRITE;
|
|
else
|
|
dm &= ~GS_DEPTHWRITE;
|
|
}
|
|
else
|
|
dm |= GS_DEPTHWRITE;
|
|
break;
|
|
|
|
case eNoDepthTest:
|
|
ef->m_State->m_Flags |= ESF_STATE;
|
|
dm |= GS_NODEPTHTEST;
|
|
dm &= ~GS_DEPTHWRITE;
|
|
break;
|
|
|
|
case eNoColorMask:
|
|
ef->m_State->m_Flags |= ESF_STATE;
|
|
af |= GS_NOCOLMASK;
|
|
break;
|
|
|
|
case ePolyLine:
|
|
ef->m_State->m_Flags |= ESF_POLYLINE;
|
|
break;
|
|
|
|
case eNoCull:
|
|
ef->m_State->m_Flags |= ESF_NOCULL;
|
|
break;
|
|
|
|
case eCullFront:
|
|
ef->m_State->m_Flags |= ESF_CULLFRONT;
|
|
break;
|
|
|
|
case eAlphaFunc:
|
|
ef->m_State->m_Flags |= ESF_STATE;
|
|
if (!stricmp(data, "GT0"))
|
|
af = GS_ALPHATEST_GREATER0;
|
|
else
|
|
if (!stricmp(data, "LT128"))
|
|
af = GS_ALPHATEST_LESS128;
|
|
else
|
|
if (!stricmp(data, "GE128"))
|
|
af = GS_ALPHATEST_GEQUAL128;
|
|
else
|
|
Warning( 0,0,"Warning: invalid AlphaFunc name '%s' in Shader '%s'\n", data, ef->m_Name.c_str());
|
|
break;
|
|
|
|
case eDepthFunc:
|
|
ef->m_State->m_Flags |= ESF_STATE;
|
|
if (!stricmp(data, "LEqual"))
|
|
df = 0;
|
|
else
|
|
if (!stricmp(data, "Equal"))
|
|
df = GS_DEPTHFUNC_EQUAL;
|
|
else
|
|
if (!strnicmp(data, "Great", 5))
|
|
df = GS_DEPTHFUNC_GREAT;
|
|
else
|
|
Warning( 0,0,"Warning: unknown DepthFunc name '%s' in Shader '%s'\n", data, ef->m_Name.c_str());
|
|
break;
|
|
|
|
case eClampTexCoords:
|
|
ef->m_State->m_Flags |= ESF_STATE;
|
|
ctc |= GS_TEXPARAM_CLAMP;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (ef->m_State->m_Flags & ESF_STATE)
|
|
dm |= GS_ADDITIONALSTATE;
|
|
ef->m_State->m_State = dm | bfsrc | bfdst | af | ctc | df;
|
|
}
|
|
|
|
SShader *CShader::mfCompile(SShader *ef, char *scr)
|
|
{
|
|
char* name;
|
|
long cmd;
|
|
char *params;
|
|
int n = 0;
|
|
|
|
m_CurShader = ef;
|
|
|
|
enum {eParams = 1, eRenderParams, ePublic, eCorona, eState, eLayer, eFlare, eSunFlares, eCurFlare, eClientEffect, eOrient, eLightStyle, eHW, eTemplates, eEvalLight};
|
|
static tokenDesc commands[] =
|
|
{
|
|
{ePublic, "Public"},
|
|
{eParams, "Params"},
|
|
{eRenderParams, "RenderParams"},
|
|
{eState, "State"},
|
|
{eFlare, "Flare"},
|
|
{eLayer, "Layer"},
|
|
{eSunFlares, "SunFlares"},
|
|
{eCurFlare, "CurFlare"},
|
|
{eClientEffect, "ClientEffect"},
|
|
{eOrient, "Orient"},
|
|
{eLightStyle, "LightStyle"},
|
|
{eHW, "HW"},
|
|
{eTemplates, "Templates"},
|
|
{eEvalLight, "EvalLight"},
|
|
|
|
{0,0}
|
|
};
|
|
|
|
while ((cmd = shGetObject (&scr, commands, &name, ¶ms)) > 0)
|
|
{
|
|
switch (cmd)
|
|
{
|
|
case eParams:
|
|
mfCompileParams(ef, params);
|
|
break;
|
|
|
|
case eRenderParams:
|
|
mfCompileRenderParams(ef, params);
|
|
break;
|
|
|
|
case ePublic:
|
|
mfCompilePublic(ef, params);
|
|
break;
|
|
|
|
case eFlare:
|
|
{
|
|
CREFlareProp *ps = new CREFlareProp;
|
|
if (ps->mfCompile(ef, params))
|
|
ef->m_REs.AddElem(ps);
|
|
else
|
|
delete ps;
|
|
}
|
|
break;
|
|
|
|
case eSunFlares:
|
|
mfCompileSunFlares(ef, name, params);
|
|
break;
|
|
|
|
case eState:
|
|
mfCompileState(ef, params);
|
|
break;
|
|
|
|
case eEvalLight:
|
|
mfCompileEvalLight(ef, params);
|
|
break;
|
|
|
|
case eCurFlare:
|
|
if (!params || !params[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing CurFlare name in Shader '%s' (skipping)!\n", ef->m_Name.c_str());
|
|
break;
|
|
}
|
|
CSunFlares::m_CurFlares = CSunFlares::mfForName(params);
|
|
ef->m_Flares = CSunFlares::m_CurFlares;
|
|
if (!CSunFlares::m_CurFlares)
|
|
{
|
|
Warning( 0,0,"Warning: Can't find Global Flare '%s' in Shader '%s' (skipping)!\n", params, ef->m_Name.c_str());
|
|
break;
|
|
}
|
|
ef->m_Flags2 |= EF2_HASSUNFLARE;
|
|
break;
|
|
|
|
case eHW:
|
|
{
|
|
SShaderTechnique *hw = mfCompileHW(ef, params, ef->m_HWTechniques.Num());
|
|
if (hw)
|
|
{
|
|
hw->m_Id = ef->m_HWTechniques.Num();
|
|
ef->m_HWTechniques.AddElem(hw);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case eClientEffect:
|
|
mfClEfCompile(ef, params, name);
|
|
break;
|
|
|
|
case eOrient:
|
|
if (!name || !name[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing Orients number in Orient Shader (skipping)!\n");
|
|
break;
|
|
}
|
|
mfCompileOrient(ef, shGetInt(name), params);
|
|
ef->m_Flags |= EF_ORIENT | EF_SYSTEM;
|
|
break;
|
|
|
|
case eLightStyle:
|
|
if (!name || !name[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing LightStyle number in LightStyles Shader (skipping)!\n");
|
|
break;
|
|
}
|
|
mfCompileLightStyle(ef, shGetInt(name), params);
|
|
break;
|
|
|
|
case eLayer:
|
|
if (mfCompileLayer(ef, n, params, NULL))
|
|
{
|
|
if (n > 0)
|
|
{
|
|
if (!(ef->m_Passes[n].m_RenderState & GS_BLEND_MASK))
|
|
Warning( 0,0,"Warning: Shader '%s' has opaque maps defined after layer 0!!!\n", ef->m_Name.c_str());
|
|
|
|
if ((ef->m_Passes[n].m_RenderState & GS_DEPTHWRITE))
|
|
Warning( 0,0,"Warning: Shader '%s' has depthmask enabled after layer 0!!!\n", ef->m_Name.c_str());
|
|
}
|
|
n++;
|
|
}
|
|
else
|
|
{
|
|
ef->m_Passes.SetNum(n);
|
|
ef->m_Passes.Realloc();
|
|
}
|
|
break;
|
|
|
|
case eTemplates:
|
|
mfCompileTemplate(ef, params);
|
|
break;
|
|
}
|
|
}
|
|
ef->m_HWTechniques.Shrink();
|
|
|
|
if (!ef->m_Passes.Num() && !ef->m_HWTechniques.Num() && !(ef->m_Flags & EF_SKY) && !(ef->m_Flags & EF_FOGSHADER))
|
|
{
|
|
mfConstruct(ef);
|
|
return ef;
|
|
}
|
|
|
|
ef->m_Flags |= EF_COMPILEDLAYERS;
|
|
|
|
mfConstruct(ef);
|
|
|
|
return ef;
|
|
}
|
|
|
|
SShader *CShader::mfCompileShader(SShader *ef, char *scr)
|
|
{
|
|
char* name;
|
|
long cmd;
|
|
char *params;
|
|
|
|
enum {eShader=1, eVersion, eSubrScript};
|
|
static tokenDesc commands[] =
|
|
{
|
|
{eShader, "Shader"},
|
|
{eVersion, "Version"},
|
|
{eSubrScript, "SubrScript"},
|
|
|
|
{0,0}
|
|
};
|
|
|
|
SShader *ef1 = NULL;
|
|
float ver;
|
|
|
|
while ((cmd = shGetObject (&scr, commands, &name, ¶ms)) > 0)
|
|
{
|
|
switch (cmd)
|
|
{
|
|
case eShader:
|
|
ef1 = mfCompile(ef, params);
|
|
break;
|
|
|
|
case eVersion:
|
|
ver = shGetFloat(params);
|
|
if (ver != SHADER_VERSION)
|
|
{
|
|
Warning( 0,0,"Warning: Shader Script version (%f) must be %f\n", ver, SHADER_VERSION);
|
|
return NULL;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return ef1;
|
|
}
|
|
|
|
//===========================================================================
|
|
|
|
bool CShader::mfCompileSequence(SShader *ef, SShaderTexUnit *tl, int nLayer, char *scr, ETexType eTT, int Flags, int Flags2, float fBumpAmount)
|
|
{
|
|
char* name;
|
|
long cmd;
|
|
char *params;
|
|
char *data;
|
|
|
|
char mapname[256];
|
|
|
|
float time = 0;
|
|
int n;
|
|
int rn = 0;
|
|
bool loop = 0;
|
|
|
|
|
|
enum {eMaps = 1, eTime, eRandom, eLoop};
|
|
static tokenDesc commands[] =
|
|
{
|
|
{eMaps, "Maps"},
|
|
{eTime, "Time"},
|
|
{eRandom, "Random"},
|
|
{eLoop, "Loop"},
|
|
{0,0}
|
|
};
|
|
|
|
while ((cmd = shGetObject (&scr, commands, &name, ¶ms)) > 0)
|
|
{
|
|
data = NULL;
|
|
if (name)
|
|
data = name;
|
|
else
|
|
if (params)
|
|
data = params;
|
|
|
|
switch (cmd)
|
|
{
|
|
case eMaps:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing Maps Sequence argument for layer %d in Shader '%s'\n", nLayer, ef->m_Name.c_str());
|
|
return false;
|
|
}
|
|
strcpy(mapname, data);
|
|
break;
|
|
|
|
case eTime:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing Time Sequence argument for layer %d in Shader '%s'\n", nLayer, ef->m_Name.c_str());
|
|
return false;
|
|
}
|
|
time = shGetFloat(data);
|
|
break;
|
|
|
|
case eLoop:
|
|
loop = 1;
|
|
break;
|
|
|
|
case eRandom:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing Random Sequence argument for layer %d in Shader '%s'\n", nLayer, ef->m_Name.c_str());
|
|
return false;
|
|
}
|
|
rn = shGetInt(data);
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
if (!mapname[0])
|
|
return false;
|
|
|
|
STexAnim *at = new STexAnim;
|
|
memset(at, 0, sizeof(STexAnim));
|
|
tl->m_AnimInfo = at;
|
|
|
|
// at->Sequence = mapname;
|
|
|
|
if (strstr(mapname, "*.*"))
|
|
n = mfReadAllImgFiles(ef, tl, at, mapname);
|
|
else
|
|
if (strchr(mapname, '#') || strchr(mapname, '$'))
|
|
n = mfReadTexSequence(ef, tl->m_AnimInfo->m_TexPics, mapname, eTT, Flags, Flags2, fBumpAmount);
|
|
else
|
|
tl->m_TexPic = (STexPic*)gRenDev->EF_LoadTexture(mapname, Flags, Flags2, eTT, fBumpAmount);
|
|
|
|
if (!tl->m_TexPic && !tl->m_AnimInfo->m_TexPics.Num())
|
|
{
|
|
delete at;
|
|
tl->m_AnimInfo = NULL;
|
|
return false;
|
|
}
|
|
|
|
at->m_NumAnimTexs = n;
|
|
|
|
STexPic *tx;
|
|
if (at->m_TexPics.Num())
|
|
{
|
|
int rni;
|
|
if (rn >= 0)
|
|
rni = -rn;
|
|
else
|
|
{
|
|
int nn = min(n, -rn);
|
|
rni = rand() % nn;
|
|
}
|
|
|
|
tx = at->m_TexPics[0];
|
|
int nn = 0;
|
|
while (rni)
|
|
{
|
|
if (nn >= at->m_TexPics.Num())
|
|
{
|
|
tx = at->m_TexPics[0];
|
|
break;
|
|
}
|
|
tx = at->m_TexPics[nn];
|
|
rni--;
|
|
nn++;
|
|
}
|
|
tl->m_TexPic = tx;
|
|
if (loop)
|
|
at->m_bLoop = loop;
|
|
}
|
|
at->m_Rand = rn;
|
|
at->m_Time = time;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
int CShader::mfReadTexSequence(SShader *ef, TArray<STexPic *>& tl, const char *na, byte eTT, int Flags, int Flags2, float fAmount1, float fAmount2)
|
|
{
|
|
char prefix[64];
|
|
char postfix[64];
|
|
char *nm;
|
|
int i, j, l, m;
|
|
char nam[64];
|
|
int n;
|
|
STexPic *tx, *tp;
|
|
int startn, endn, nums;
|
|
char name[128];
|
|
|
|
tx = NULL;
|
|
|
|
StripExtension(na, name);
|
|
|
|
char chSep = '#';
|
|
nm = strchr(name, chSep);
|
|
if (!nm)
|
|
{
|
|
nm = strchr(name, '$');
|
|
if (!nm)
|
|
return 0;
|
|
char chSep = '$';
|
|
}
|
|
|
|
float fSpeed = 0.05f;
|
|
{
|
|
char nName[128];
|
|
strcpy(nName, name);
|
|
nm = strchr(nName, '(');
|
|
if (nm)
|
|
{
|
|
name[nm-nName] = 0;
|
|
char *speed = &nName[nm-nName+1];
|
|
if(nm=strchr(speed, ')'))
|
|
speed[nm-speed] = 0;
|
|
fSpeed = (float)atof(speed);
|
|
}
|
|
}
|
|
|
|
j = 0;
|
|
n = 0;
|
|
l = -1;
|
|
m = -1;
|
|
while (name[n])
|
|
{
|
|
if (name[n] == chSep)
|
|
{
|
|
j++;
|
|
if (l == -1)
|
|
l = n;
|
|
}
|
|
else
|
|
if (l >= 0 && m < 0)
|
|
m = n;
|
|
n++;
|
|
}
|
|
if (!j)
|
|
return 0;
|
|
|
|
strncpy(prefix, name, l);
|
|
prefix[l] = 0;
|
|
char dig[64];
|
|
l = 0;
|
|
if (m < 0)
|
|
{
|
|
startn = 0;
|
|
endn = 999;
|
|
postfix[0] = 0;
|
|
}
|
|
else
|
|
{
|
|
while(isdigit(name[m]))
|
|
{
|
|
dig[l++] = name[m];
|
|
m++;
|
|
}
|
|
dig[l] = 0;
|
|
startn = strtol(dig, NULL, 10);
|
|
m++;
|
|
|
|
l = 0;
|
|
while(isdigit(name[m]))
|
|
{
|
|
dig[l++] = name[m];
|
|
m++;
|
|
}
|
|
dig[l] = 0;
|
|
endn = strtol(dig, NULL, 10);
|
|
|
|
strcpy(postfix, &name[m]);
|
|
}
|
|
|
|
nums = endn-startn+1;
|
|
|
|
n = 0;
|
|
char frm[64];
|
|
char frd[4];
|
|
|
|
frd[0] = j + '0';
|
|
frd[1] = 0;
|
|
|
|
strcpy(frm, "%s%.");
|
|
strcat(frm, frd);
|
|
strcat(frm, "d%s");
|
|
for (i=0; i<nums; i++)
|
|
{
|
|
sprintf(nam, frm, prefix, startn+i, postfix);
|
|
tp = (STexPic*)gRenDev->EF_LoadTexture(nam, Flags, Flags2, eTT, fAmount1, fAmount2);
|
|
if (!tp || (tp->m_Flags & FT_NOTFOUND))
|
|
{
|
|
if (tp)
|
|
tp->Release(0);
|
|
break;
|
|
}
|
|
tl.AddElem(tp);
|
|
tp->m_fAnimSpeed = fSpeed;
|
|
n++;
|
|
}
|
|
|
|
return n;
|
|
}
|
|
|
|
int CShader::mfReadAllImgFiles(SShader *ef, SShaderTexUnit *tl, STexAnim *ta, char *name)
|
|
{
|
|
struct __finddata64_t fileinfo;
|
|
intptr_t handle;
|
|
char d[1024];
|
|
char drn[1024], ddr[1024];
|
|
char dirn[1024];
|
|
char en[64];
|
|
char fn[1024], fn1[1024];
|
|
int ns = 0;
|
|
STexPic *tp, *tx;
|
|
char *path, *pt, nm[1024];
|
|
|
|
int fl = 0;
|
|
tx = NULL;
|
|
|
|
pt = NULL;
|
|
path = strtok(name, "%");
|
|
if (path)
|
|
{
|
|
if (!stricmp(path, "ModelsPath"))
|
|
pt = m_ModelsPath;
|
|
else
|
|
if (!stricmp(path, "TexturesPath"))
|
|
pt = m_TexturesPath;
|
|
else
|
|
if (!stricmp(path, "SystemPath"))
|
|
pt = m_SystemPath;
|
|
|
|
if (pt)
|
|
UsePath((char *)ef->m_Name.c_str(), pt, nm);
|
|
else
|
|
strcpy(nm, path);
|
|
}
|
|
else
|
|
{
|
|
strcpy(nm, name);
|
|
fl = 1;
|
|
}
|
|
|
|
ConvertUnixToDosName( d, nm );
|
|
|
|
_splitpath(d, drn, dirn, fn, en);
|
|
|
|
strcpy(ddr, dirn);
|
|
|
|
if (!fl)
|
|
strcat(dirn, "*.*");
|
|
|
|
handle = _findfirst64 (dirn, &fileinfo);
|
|
|
|
if (handle == -1)
|
|
return 0;
|
|
|
|
do
|
|
{
|
|
if (fileinfo.attrib & _A_SUBDIR)
|
|
continue;
|
|
if (fileinfo.name[0] == '.')
|
|
continue;
|
|
|
|
strcpy(fn1, drn);
|
|
strcat(fn1, ddr);
|
|
strcat(fn1, fileinfo.name);
|
|
|
|
tp = (STexPic*)gRenDev->EF_LoadTexture(fn1, 0, 0, eTT_Base);
|
|
if ( !tp )
|
|
continue;
|
|
ta->m_TexPics.AddElem(tp);
|
|
ns++;
|
|
} while (_findnext64( handle, &fileinfo ) != -1);
|
|
|
|
return ns;
|
|
}
|
|
|
|
//===========================================================================
|
|
|
|
//#include "RendElements/ProcTree/Tree.h"
|
|
//#include "RendElements/Terrain/CTerrainRE.h"
|
|
|
|
void CShader::mfClEfCompile(SShader *ef, char *scr, char *name)
|
|
{
|
|
if (!name || !name[0])
|
|
{
|
|
Warning( 0,0,"Warning: missing parameter in ClientEffect for Shader '%s' (skipping)\n", ef->m_Name.c_str());
|
|
return;
|
|
}
|
|
|
|
if (!stricmp(name, "PolyBlend"))
|
|
{
|
|
CREPolyBlend *ps = new CREPolyBlend;
|
|
if (ps->mfCompile(ef, scr))
|
|
ef->m_REs.AddElem(ps);
|
|
else
|
|
delete ps;
|
|
return;
|
|
}
|
|
else
|
|
if (!stricmp(name, "AnimPolyBlend"))
|
|
{
|
|
CREAnimPolyBlend *ps = new CREAnimPolyBlend;
|
|
if (ps->mfCompile(ef, scr))
|
|
ef->m_REs.AddElem(ps);
|
|
else
|
|
delete ps;
|
|
return;
|
|
}
|
|
else
|
|
if (!stricmp(name, "ParticleSpray"))
|
|
{
|
|
#ifdef DEBUGALLOC
|
|
#undef new
|
|
#endif
|
|
CREParticleSpray *ps = new CREParticleSpray;
|
|
#ifdef DEBUGALLOC
|
|
#define new DEBUG_CLIENTBLOCK
|
|
#endif
|
|
if (ps->mfCompile(ef, scr))
|
|
ef->m_REs.AddElem(ps);
|
|
else
|
|
delete ps;
|
|
return;
|
|
}
|
|
else
|
|
if (!stricmp(name, "Corona"))
|
|
{
|
|
CREFlare *ps = new CREFlare;
|
|
if (ps->mfCompile(ef, scr))
|
|
{
|
|
ef->m_REs.AddElem(ps);
|
|
ef->m_nPreprocess |= FSPR_CORONA;
|
|
}
|
|
else
|
|
delete ps;
|
|
return;
|
|
}
|
|
else
|
|
if (!stricmp(name, "Beam"))
|
|
{
|
|
CREBeam *ps = new CREBeam;
|
|
if (ps->mfCompile(ef, scr))
|
|
{
|
|
ef->m_REs.AddElem(ps);
|
|
}
|
|
else
|
|
delete ps;
|
|
return;
|
|
}
|
|
else
|
|
if (!stricmp(name, "Tree"))
|
|
{
|
|
/*CRETree *ps = new CRETree;
|
|
if (ps->mfCompile(ef, scr))
|
|
ef->m_RE = ps;
|
|
else
|
|
delete ps;*/
|
|
return;
|
|
}
|
|
else
|
|
if (!stricmp(name, "GeomPrefab") || !stricmp(name, "Prefab"))
|
|
{
|
|
CREPrefabGeom *ps = new CREPrefabGeom;
|
|
if (ps->mfCompile(ef, scr))
|
|
ef->m_REs.AddElem(ps);
|
|
else
|
|
delete ps;
|
|
return;
|
|
}
|
|
else
|
|
if (!stricmp(name, "Flare"))
|
|
{
|
|
CREFlareProp *ps = new CREFlareProp;
|
|
if (ps->mfCompile(ef, scr))
|
|
ef->m_REs.AddElem(ps);
|
|
else
|
|
delete ps;
|
|
}
|
|
else
|
|
if (!stricmp(name, "Terrain"))
|
|
{
|
|
/*CRETerrain *ps = new CRETerrain;
|
|
if (ps->mfCompile(ef, scr))
|
|
ef->m_RE = ps;
|
|
else
|
|
delete ps;*/
|
|
}
|
|
else
|
|
if (!stricmp(name, "SkyZone"))
|
|
{
|
|
CRESkyZone *ps = NULL;//new CRESkyZone;
|
|
if (ps->mfCompile(ef, scr))
|
|
ef->m_REs.AddElem(ps);
|
|
else
|
|
delete ps;
|
|
return;
|
|
}
|
|
else
|
|
if (!stricmp(name, "Ocean"))
|
|
{
|
|
#ifdef DEBUGALLOC
|
|
#undef new
|
|
#endif
|
|
CREOcean *ps = new CREOcean;
|
|
#ifdef DEBUGALLOC
|
|
#define new DEBUG_CLIENTBLOCK
|
|
#endif
|
|
if (ps->mfCompile(ef, scr))
|
|
ef->m_REs.AddElem(ps);
|
|
else
|
|
delete ps;
|
|
return;
|
|
}
|
|
else
|
|
Warning( 0,0,"Warning: unknown ClientEffect (%s) in Shader '%s' (skipping)\n", name, ef->m_Name.c_str());
|
|
}
|
|
|
|
|
|
//=========================================================================
|
|
|
|
TArray<CSunFlares *> CSunFlares::m_SunFlares;
|
|
CSunFlares *CSunFlares::m_CurFlares = NULL;
|
|
|
|
CSunFlares *CSunFlares::mfForName(char *name)
|
|
{
|
|
int i;
|
|
|
|
for (i=0; i<m_SunFlares.Num(); i++)
|
|
{
|
|
if (!stricmp(m_SunFlares[i]->m_Name, name))
|
|
return m_SunFlares[i];
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
bool CShader::mfCompileFlare(SShader *ef, SSunFlare *fl, char *scr)
|
|
{
|
|
char* name;
|
|
long cmd;
|
|
char *params;
|
|
char *data;
|
|
char namefl[64];
|
|
|
|
enum {eName = 1, eLocation, eScale, eColor};
|
|
static tokenDesc commands[] =
|
|
{
|
|
{eName, "Name"},
|
|
{eLocation, "Location"},
|
|
{eScale, "Scale"},
|
|
{eColor, "Color"},
|
|
|
|
{0,0}
|
|
};
|
|
|
|
while ((cmd = shGetObject (&scr, commands, &name, ¶ms)) > 0)
|
|
{
|
|
data = NULL;
|
|
if (name)
|
|
data = name;
|
|
else
|
|
if (params)
|
|
data = params;
|
|
|
|
switch (cmd)
|
|
{
|
|
case eName:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: Missing flare name in system Shader '%s'\n", ef->m_Name.c_str());
|
|
return false;
|
|
}
|
|
strcpy(namefl, data);
|
|
break;
|
|
|
|
case eLocation:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: Missing Location arg in system Shader '%s'\n", ef->m_Name.c_str());
|
|
return false;
|
|
}
|
|
fl->m_Loc = shGetFloat(data);
|
|
break;
|
|
|
|
case eScale:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: Missing Scale arg in system Shader '%s'\n", ef->m_Name.c_str());
|
|
return false;
|
|
}
|
|
fl->m_Scale = shGetFloat(data);
|
|
break;
|
|
|
|
case eColor:
|
|
if (!data || !data[0])
|
|
{
|
|
Warning( 0,0,"Warning: Missing Color arg in system Shader '%s'\n", ef->m_Name.c_str());
|
|
return false;
|
|
}
|
|
shGetColor(data, fl->m_Color);
|
|
COLCONV(fl->m_Color);
|
|
break;
|
|
}
|
|
}
|
|
|
|
fl->m_Tex = (STexPic*)gRenDev->EF_LoadTexture(namefl, FT_NOMIPS, 0, eTT_Base);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CShader::mfCompileSunFlares(SShader *ef, char *namefl, char *scr)
|
|
{
|
|
char* name;
|
|
long cmd;
|
|
char *params;
|
|
char *data;
|
|
CSunFlares *sf;
|
|
SSunFlare flares[64];
|
|
int numfl = 0;
|
|
|
|
enum {eFlare = 1};
|
|
static tokenDesc commands[] =
|
|
{
|
|
{eFlare, "Flare"},
|
|
|
|
{0,0}
|
|
};
|
|
|
|
sf = new CSunFlares;
|
|
strcpy(sf->m_Name, namefl);
|
|
CSunFlares::m_SunFlares.AddElem(sf);
|
|
|
|
while ((cmd = shGetObject (&scr, commands, &name, ¶ms)) > 0)
|
|
{
|
|
data = NULL;
|
|
if (name)
|
|
data = name;
|
|
else
|
|
if (params)
|
|
data = params;
|
|
|
|
switch (cmd)
|
|
{
|
|
case eFlare:
|
|
if (mfCompileFlare(ef, &flares[numfl], params))
|
|
{
|
|
numfl++;
|
|
if (numfl >= 64)
|
|
{
|
|
Warning( 0,0,"Warning: Too many flares in system Shader '%s'\n", ef->m_Name.c_str());
|
|
goto dl;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
dl:
|
|
if (numfl>0)
|
|
{
|
|
sf->m_Flares = new SSunFlare[numfl];
|
|
for (int i=0; i<numfl; i++)
|
|
{
|
|
memcpy(&sf->m_Flares[i], &flares[i], sizeof(SSunFlare));
|
|
if (sf->m_Flares[i].m_Tex)
|
|
sf->m_Flares[i].m_Tex->AddRef();
|
|
}
|
|
sf->m_NumFlares = numfl;
|
|
ef->m_Flags |= EF_SUNFLARES;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|