slightly better doom3 compat

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4439 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2013-07-29 17:36:44 +00:00
parent e4565ee476
commit a05f3f36a0
8 changed files with 216 additions and 102 deletions

View file

@ -1516,7 +1516,7 @@ nacl-dbg:
#makes an ant project for us
droid/build.xml:
-cd droid && PATH=$$PATH:$(ANDROID_HOME)/tools:$(ANDROID_NDK_ROOT) $(ANDROID_SCRIPT) update project -t android-8 -p . -n FTEDroid
-cd droid && PATH=$$PATH:$(realpath $(ANDROID_HOME)/tools):$(realpath $(ANDROID_NDK_ROOT)) $(ANDROID_SCRIPT) update project -t android-8 -p . -n FTEDroid
#build FTE as a library, then build the java+package (release)
droid/ftekeystore:
@ -1537,7 +1537,8 @@ else
@$(JAVATOOL)keytool -genkey -keystore $@ -alias autogen -keyalg RSA -keysize 2048 -validity 10000 -noprompt $(KEYTOOLARGS)
endif
droid-rel: droid/build.xml droid/ftekeystore
droid-rel:
$(MAKE) FTE_TARGET=droid droid/build.xml droid/ftekeystore
$(foreach a, $(DROID_ARCH), $(MAKE) FTE_TARGET=droid gl-rel DROID_ARCH=$a; )
@$(foreach a, $(DROID_ARCH), mkdir -p droid/libs/$a; )
-@$(foreach a, $(DROID_ARCH), cp $(RELEASE_DIR)/gl_droid-$a/libftedroid.so droid/libs/$a/libftedroid.so; )
@ -1563,7 +1564,8 @@ endif
-rm -f $(RELEASE_DIR)/FTEDroid.apk
$(ANDROID_HOME)/tools/zipalign 4 droid/bin/FTEDroid-release-unsigned.apk $(RELEASE_DIR)/FTEDroid.apk
droid-opt: droid/build.xml droid/ftekeystore
droid-opt:
$(MAKE) FTE_TARGET=droid droid/build.xml droid/ftekeystore
$(MAKE) FTE_TARGET=droid gl-rel
mkdir -p droid/libs/armeabi
@cp $(RELEASE_DIR)/libftedroid.so droid/libs/armeabi/
@ -1571,7 +1573,8 @@ droid-opt: droid/build.xml droid/ftekeystore
cp droid/bin/FTEDroid-unsigned.apk $(RELEASE_DIR)/FTEDroid.apk
#build FTE as a library, then build the java+package (release). also installs it onto the 'current' device.
droid-dbg: droid/build.xml
droid-dbg:
$(MAKE) FTE_TARGET=droid droid/build.xml
$(foreach a, $(DROID_ARCH), $(MAKE) FTE_TARGET=droid gl-dbg DROID_ARCH=$a; )
@$(foreach a, $(DROID_ARCH), mkdir -p droid/libs/$a; )
-@$(foreach a, $(DROID_ARCH), cp $(DEBUG_DIR)/gl_droid-$a/libftedroid.so droid/libs/$a/libftedroid.so; )

View file

@ -6,10 +6,10 @@
#endif
void Mod_SetParent (mnode_t *node, mnode_t *parent);
int D3_LeafnumForPoint (struct model_s *model, vec3_t point);
static int D3_LeafnumForPoint (struct model_s *model, vec3_t point);
#ifndef SERVERONLY
qboolean Mod_LoadMap_Proc(model_t *model, char *data)
static qboolean Mod_LoadMap_Proc(model_t *model, char *data)
{
char token[256];
int ver = 0;
@ -359,7 +359,7 @@ qboolean R_CullBox (vec3_t mins, vec3_t maxs);
static int walkno;
/*convert each portal to a 2d box, because its much much simpler than true poly clipping*/
void D3_WalkPortal(model_t *mod, int start, vec_t bounds[4], unsigned char *vis)
static void D3_WalkPortal(model_t *mod, int start, vec_t bounds[4], unsigned char *vis)
{
int i;
portal_t *p;
@ -462,14 +462,15 @@ void D3_GenerateAreas(model_t *mod)
#endif
//edict system as opposed to q2 game dll system.
void D3_FindTouchedLeafs (struct model_s *model, struct pvscache_s *ent, vec3_t cullmins, vec3_t cullmaxs)
static void D3_FindTouchedLeafs (struct model_s *model, struct pvscache_s *ent, vec3_t cullmins, vec3_t cullmaxs)
{
}
qbyte *D3_LeafPVS (struct model_s *model, int num, qbyte *buffer, unsigned int buffersize)
static qbyte *D3_LeafPVS (struct model_s *model, int num, qbyte *buffer, unsigned int buffersize)
{
memset(buffer, 0xff, buffersize);
return buffer;
}
int D3_LeafnumForPoint (struct model_s *model, vec3_t point)
static int D3_LeafnumForPoint (struct model_s *model, vec3_t point)
{
float p;
int c;
@ -485,16 +486,16 @@ int D3_LeafnumForPoint (struct model_s *model, vec3_t point)
}
return 0;
}
unsigned int D3_FatPVS (struct model_s *model, vec3_t org, qbyte *pvsbuffer, unsigned int buffersize, qboolean merge)
static unsigned int D3_FatPVS (struct model_s *model, vec3_t org, qbyte *pvsbuffer, unsigned int buffersize, qboolean merge)
{
return 0;
}
void D3_StainNode (struct mnode_s *node, float *parms)
static void D3_StainNode (struct mnode_s *node, float *parms)
{
}
void D3_LightPointValues (struct model_s *model, vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir)
static void D3_LightPointValues (struct model_s *model, vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir)
{
/*basically require rtlighting for any light*/
VectorClear(res_diffuse);
@ -504,7 +505,7 @@ void D3_LightPointValues (struct model_s *model, vec3_t point, vec3_t res_diffus
}
qboolean D3_EdictInFatPVS (struct model_s *model, struct pvscache_s *edict, qbyte *pvsbuffer)
static qboolean D3_EdictInFatPVS (struct model_s *model, struct pvscache_s *edict, qbyte *pvsbuffer)
{
int i;
for (i = 0; i < edict->num_leafs; i++)
@ -840,7 +841,7 @@ return;
D3_RecursiveSurfCheck (node->child[side^1], midf, p2f, mid, p2);
}
qboolean D3_Trace (struct model_s *model, int hulloverride, int frame, vec3_t axis[3], vec3_t p1, vec3_t p2, vec3_t mins, vec3_t maxs, unsigned int hitcontentsmask, struct trace_s *trace)
static qboolean D3_Trace (struct model_s *model, int hulloverride, int frame, vec3_t axis[3], vec3_t p1, vec3_t p2, vec3_t mins, vec3_t maxs, unsigned int hitcontentsmask, struct trace_s *trace)
{
int i;
float e1,e2;
@ -922,7 +923,7 @@ qboolean D3_Trace (struct model_s *model, int hulloverride, int frame, vec3_t ax
return false;
}
unsigned int D3_PointContents (struct model_s *model, vec3_t axis[3], vec3_t p)
static unsigned int D3_PointContents (struct model_s *model, vec3_t axis[3], vec3_t p)
{
cm_node_t *node = model->cnodes;
cm_brush_t *brush;
@ -975,7 +976,7 @@ unsigned int D3_PointContents (struct model_s *model, vec3_t axis[3], vec3_t p)
#define ensurenewtoken(t) buf = COM_ParseOut(buf, token, sizeof(token)); if (strcmp(token, t)) break;
int D3_ParseContents(char *str)
static int D3_ParseContents(char *str)
{
char *e, *n;
unsigned int contents = 0;
@ -1305,6 +1306,7 @@ qboolean D3_LoadMap_CollisionMap(model_t *mod, char *buf)
mod->funcs.StainNode = D3_StainNode;
mod->funcs.LightPointValues = D3_LightPointValues;
mod->funcs.EdictInFatPVS = D3_EdictInFatPVS;
mod->funcs.LeafPVS = D3_LeafPVS;
mod->fromgame = fg_doom3;

View file

@ -1319,7 +1319,8 @@ int QCLibEditor(pubprogfuncs_t *prfncs, char *filename, int line, int statement,
}
realtime = oldrealtime;
key_dest = oldkeydest;
if (oldkeydest != key_console)
key_dest = oldkeydest;
editormodal = false;
}

View file

@ -2148,7 +2148,7 @@ const gamemode_info_t gamemode_info[] = {
{"-halflife", "hl", "FTE-HalfLife", {"valve/liblist.gam"}, NULL, {"valve", "ftehl"}, "Half-Life"},
//the rest are not supported in any real way. maps-only mostly, if that
{"-q4", "q4", "FTE-Quake4", {"q4base/pak00.pk4"}, NULL, {"q4base", "fteq4"}, "Quake 4"},
{"-quake4", "q4", "FTE-Quake4", {"q4base/pak00.pk4"}, NULL, {"q4base", "fteq4"}, "Quake 4"},
{"-et", "et", "FTE-EnemyTerritory", {"etmain/pak0.pk3"}, NULL, {"etmain", "fteet"}, "Wolfenstein - Enemy Territory"},
{"-jk2", "jk2", "FTE-JK2", {"base/assets0.pk3"}, NULL, {"base", "fte"}, "Jedi Knight II: Jedi Outcast"},
@ -2156,6 +2156,7 @@ const gamemode_info_t gamemode_info[] = {
{"-doom", "doom", "FTE-Doom", {"doom.wad"}, NULL, {"*doom.wad", "ftedoom"}, "Doom"},
{"-doom2", "doom2", "FTE-Doom2", {"doom2.wad"}, NULL, {"*doom2.wad", "ftedoom"}, "Doom2"},
{"-doom3", "doom3", "FTE-Doom3", {"doom3.wad"}, NULL, {"*doom2.wad", "ftedoom"}, "Doom2"},
{NULL}
};

View file

@ -2123,9 +2123,10 @@ static shaderkey_t shaderkeys[] =
{"dp_camera", Shader_DP_Camera},
/*doom3 compat*/
{"diffusemap", Shader_DiffuseMap},
{"bumpmap", NULL},
{"specularmap", NULL},
{"diffusemap", Shader_DiffuseMap}, //macro for "{\nstage diffusemap\nmap <map>\n}"
{"bumpmap", NULL}, //macro for "{\nstage bumpmap\nmap <map>\n}"
{"specularmap", NULL}, //macro for "{\nstage specularmap\nmap <map>\n}"
{"discrete", NULL},
{"nonsolid", NULL},
{"noimpact", NULL},
{"translucent", Shader_Translucent},
@ -2136,6 +2137,19 @@ static shaderkey_t shaderkeys[] =
{NULL, NULL}
};
static struct
{
char *name;
char *body;
} shadermacros[] =
{
{"decal_macro", "polygonOffset 1\ndiscrete\nsort decal\nnoShadows"},
// {"diffusemap", "{\nblend diffusemap\nmap %1\n}"},
// {"bumpmap", "{\nblend bumpmap\nmap %1\n}"},
// {"specularmap", "{\nblend specularmap\nmap %1\n}"},
{NULL}
};
// ===============================================================
static qboolean Shaderpass_MapGen (shader_t *shader, shaderpass_t *pass, char *tname)
@ -2550,33 +2564,25 @@ static void Shaderpass_BlendFunc (shader_t *shader, shaderpass_t *pass, char **p
{
char *token;
//reset to defaults
pass->shaderbits &= ~(SBITS_BLEND_BITS);
pass->stagetype = ST_AMBIENT;
token = Shader_ParseString (ptr);
if ( !Q_stricmp (token, "diffusemap"))
{
//if the shader is translucent then this pass must be meant to be blended
if (shader->flags & SHADER_BLEND)
pass->shaderbits |= SBITS_SRCBLEND_SRC_ALPHA | SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA;
else
pass->shaderbits |= SBITS_SRCBLEND_NONE | SBITS_DSTBLEND_NONE;
}
if ( !Q_stricmp (token, "bumpmap")) //doom3 is awkward...
pass->stagetype = ST_BUMPMAP;
else if ( !Q_stricmp (token, "specularmap")) //doom3 is awkward...
pass->stagetype = ST_SPECULARMAP;
else if ( !Q_stricmp (token, "diffusemap")) //doom3 is awkward...
pass->stagetype = ST_DIFFUSEMAP;
else if ( !Q_stricmp (token, "blend"))
{
pass->shaderbits |= SBITS_SRCBLEND_SRC_ALPHA | SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA;
}
else if (!Q_stricmp (token, "filter"))
{
pass->shaderbits |= SBITS_SRCBLEND_DST_COLOR | SBITS_DSTBLEND_ZERO;
}
else if (!Q_stricmp (token, "add"))
{
pass->shaderbits |= SBITS_SRCBLEND_ONE | SBITS_DSTBLEND_ONE;
}
else if (!Q_stricmp (token, "replace"))
{
pass->shaderbits |= SBITS_SRCBLEND_NONE | SBITS_DSTBLEND_NONE;
}
else
{
pass->shaderbits |= Shader_BlendFactor(token, false);
@ -3296,6 +3302,7 @@ void Shader_Readpass (shader_t *shader, char **ptr)
pass->tcgen = TC_GEN_BASE;
pass->numtcmods = 0;
pass->numMergedPasses = 1;
pass->stagetype = ST_AMBIENT;
if (shader->flags & SHADER_NOMIPMAPS)
pass->flags |= SHADER_PASS_NOMIPMAP;
@ -3364,8 +3371,31 @@ void Shader_Readpass (shader_t *shader, char **ptr)
Con_Printf("if statements without endif in shader %s\n", shader->name);
}
if (!ignore)
{
switch(pass->stagetype)
{
case ST_DIFFUSEMAP:
if (pass->texgen == T_GEN_SINGLEMAP)
shader->defaulttextures.bump = pass->anim_frames[0];
break;
case ST_AMBIENT:
break;
case ST_BUMPMAP:
if (pass->texgen == T_GEN_SINGLEMAP)
shader->defaulttextures.bump = pass->anim_frames[0];
ignore = true;
break;
case ST_SPECULARMAP:
if (pass->texgen == T_GEN_SINGLEMAP)
shader->defaulttextures.specular = pass->anim_frames[0];
ignore = true;
break;
}
}
// check some things
if ( ignore )
if (ignore)
{
Shader_FreePass (pass);
shader->numpasses--;
@ -3618,6 +3648,11 @@ void Shader_Finish (shader_t *s)
{
int i;
shaderpass_t *pass;
//FIXME: reorder doom3 stages.
//put diffuse first. give it a lightmap pass also, if we found a diffuse one with no lightmap.
//then the ambient stages.
//and forget about the bump/specular stages as we don't support them and already stripped them.
if (s->flags & SHADER_SKY)
{
@ -4727,81 +4762,115 @@ void Shader_Default2D(char *shortname, shader_t *s, const void *genargs)
}
}
//loads a shader string into an existing shader object, and finalises it and stuff
static void Shader_ReadShader(shader_t *s, char *shadersource, int parsemode)
qboolean Shader_ReadShaderTerms(shader_t *s, char **shadersource, int parsemode, int *conddepth, int maxconddepth, int *cond)
{
char *token;
int conddepth = 0;
int cond[8] = {0};
#define COND_IGNORE 1
#define COND_IGNOREPARENT 2
#define COND_ALLOWELSE 4
token = COM_ParseExt (shadersource, true, true);
if ( !token[0] )
return true;
else if (!Q_stricmp(token, "if"))
{
if (*conddepth+1 == maxconddepth)
{
Con_Printf("if statements nest too deeply in shader %s\n", s->name);
return false;
}
*conddepth+=1;
cond[*conddepth] = (!Shader_EvaluateCondition(s, shadersource)?COND_IGNORE:0);
cond[*conddepth] |= COND_ALLOWELSE;
if (cond[*conddepth-1] & (COND_IGNORE|COND_IGNOREPARENT))
cond[*conddepth] |= COND_IGNOREPARENT;
}
else if (!Q_stricmp(token, "endif"))
{
if (!*conddepth)
{
Con_Printf("endif without if in shader %s\n", s->name);
return false;
}
*conddepth-=1;
}
else if (!Q_stricmp(token, "else"))
{
if (cond[*conddepth] & COND_ALLOWELSE)
{
cond[*conddepth] ^= COND_IGNORE;
cond[*conddepth] &= ~COND_ALLOWELSE;
}
else
Con_Printf("unexpected else statement in shader %s\n", s->name);
}
else if (cond[*conddepth] & (COND_IGNORE|COND_IGNOREPARENT))
{
//eat it.
while (**shadersource)
{
token = COM_ParseExt(shadersource, false, true);
if ( !token[0] )
break;
}
}
else
{
int i;
for (i = 0; shadermacros[i].name; i++)
{
if (!Q_stricmp (token, shadermacros[i].name))
{
#define SHADER_MACRO_ARGS 6
int argn = 0;
char *body;
char arg[SHADER_MACRO_ARGS][256];
int cond = 0;
//parse args until the end of the line
while (*shadersource)
{
token = COM_ParseExt(shadersource, false, true);
if ( !token[0] )
{
break;
}
if (argn <= SHADER_MACRO_ARGS)
{
Q_strncpyz(arg[argn], token, sizeof(arg[argn]));
argn++;
}
}
body = shadermacros[i].body;
Shader_ReadShaderTerms(s, &body, parsemode, &cond, 0, &cond);
return true;
}
}
if (token[0] == '}')
return false;
else if (token[0] == '{')
Shader_Readpass(s, shadersource);
else if (Shader_Parsetok(s, NULL, shaderkeys, token, shadersource))
return false;
}
return true;
}
//loads a shader string into an existing shader object, and finalises it and stuff
static void Shader_ReadShader(shader_t *s, char *shadersource, int parsemode)
{
int conddepth = 0;
int cond[8];
cond[0] = 0;
shaderparsemode = parsemode;
// set defaults
s->flags = SHADER_CULL_FRONT;
s->uses = 1;
while (shadersource)
while (Shader_ReadShaderTerms(s, &shadersource, parsemode, &conddepth, sizeof(cond)/sizeof(cond[0]), cond))
{
token = COM_ParseExt (&shadersource, true, true);
if ( !token[0] )
continue;
else if (!Q_stricmp(token, "if"))
{
if (conddepth+1 == sizeof(cond)/sizeof(cond[0]))
{
Con_Printf("if statements nest too deeply in shader %s\n", s->name);
break;
}
conddepth++;
cond[conddepth] = (!Shader_EvaluateCondition(s, &shadersource)?COND_IGNORE:0);
cond[conddepth] |= COND_ALLOWELSE;
if (cond[conddepth-1] & (COND_IGNORE|COND_IGNOREPARENT))
cond[conddepth] |= COND_IGNOREPARENT;
}
else if (!Q_stricmp(token, "endif"))
{
if (!conddepth)
{
Con_Printf("endif without if in shader %s\n", s->name);
break;
}
conddepth--;
}
else if (!Q_stricmp(token, "else"))
{
if (cond[conddepth] & COND_ALLOWELSE)
{
cond[conddepth] ^= COND_IGNORE;
cond[conddepth] &= ~COND_ALLOWELSE;
}
else
Con_Printf("unexpected else statement in shader %s\n", s->name);
}
else if (cond[conddepth] & (COND_IGNORE|COND_IGNOREPARENT))
{
//eat it.
while (*shadersource)
{
token = COM_ParseExt(&shadersource, false, true);
if ( !token[0] )
{
break;
}
}
}
else
{
if (token[0] == '}')
break;
else if (token[0] == '{')
Shader_Readpass(s, &shadersource);
else if (Shader_Parsetok(s, NULL, shaderkeys, token, &shadersource))
break;
}
}
if (conddepth)

View file

@ -1,3 +1,32 @@
/*
Copyright spike. GNU GPL V2. etc.
Much of this file and the parser derives originally from qfusion by vic.
Quake1 rendering works by:
Draw everything in depth order and stall lots from switching textures.
draw transparent water surfaces last.
Quake3 rendering works by:
generate a batch for every model+shader in the world.
sort batches by shader sort key, entity, shader.
draw surfaces.
Doom3 rendering works by:
generate a batch for every model+shader in the world.
sort batches by shader sort key, entity, shader.
depth is drawn (yay alpha masked surfaces)
for each light+batch
draw each bump/diffuse/specular stage. combine to one pass if that ordering is not maintained. switch diffuse/specular if needed
ambient stages from each batch are added over the top.
FTE rtlight rendering works by:
generate a batch for every model+shader in the world.
sort batches by shader sort key, entity, shader.
draw surfaces. if rtworld_lightmaps is 0 and there's no additive stuff, draw as black, otherwise just scale lightmap passes.
lights are then added over the top based upon the diffusemap, bumpmap and specularmap, and without any pass-specific info (no tcmods).
*/
#ifndef SHADER_H
#define SHADER_H
typedef void (shader_gen_t)(char *name, shader_t*, const void *args);
@ -238,6 +267,13 @@ typedef struct shaderpass_s {
T_GEN_3DMAP, //use a 3d texture instead, otherwise T_GEN_SINGLEMAP.
} texgen;
enum {
ST_DIFFUSEMAP,
ST_AMBIENT,
ST_BUMPMAP,
ST_SPECULARMAP
} stagetype;
enum {
SHADER_PASS_CLAMP = 1<<0, //needed for d3d's sampler states, infects image flags
SHADER_PASS_NEAREST = 1<<1, //needed for d3d's sampler states, infects image flags

View file

@ -432,7 +432,6 @@ LONG WINAPI MainWndProc (
r.right = nw*usingstretch;
r.bottom = nh*usingstretch;
AdjustWindowRectEx(&r, WS_OVERLAPPEDWINDOW, FALSE, 0);
vid.recalc_refdef = true;
if (move)
MoveWindow(hWnd, nl, nt, r.right - r.left, r.bottom - r.top, true);
else

View file

@ -4304,6 +4304,9 @@ qintptr_t JCL_Shutdown(qintptr_t *args)
if (jcl)
JCL_CloseConnection(jcl, false);
}
// if (_CrtDumpMemoryLeaks())
// OutputDebugStringA("Leaks detected\n");
return true;
}