forked from fte/fteqw
1
0
Fork 0

Moved entity and poly handling code to a common location. This means sprites work in D3D. Fixed .alpha on mdls. Slightly better q2 compat.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3779 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2011-04-23 20:37:20 +00:00
parent 0ffb6c11e2
commit f7aece9d48
20 changed files with 684 additions and 869 deletions

View File

@ -1887,6 +1887,8 @@ void CL_LinkPacketEntities (void)
ent->flags |= Q2RF_ADDITIVE;
if (state->effects & EF_NODEPTHTEST)
ent->flags |= RF_NODEPTHTEST;
if (state->trans != 0xff)
ent->flags |= Q2RF_TRANSLUCENT;
/*FIXME: pay attention to tags instead, so nexuiz can work with splitscreen*/
if (ent->flags & Q2RF_EXTERNALMODEL)
@ -2812,10 +2814,12 @@ void CL_LinkPlayers (void)
#ifdef PEXT_SCALE
ent->scale = state->scale;
#endif
ent->shaderRGBAf[0] = state->colourmod[0]/32;
ent->shaderRGBAf[1] = state->colourmod[1]/32;
ent->shaderRGBAf[2] = state->colourmod[2]/32;
ent->shaderRGBAf[3] = state->alpha/255;
ent->shaderRGBAf[0] = state->colourmod[0]/32.0f;
ent->shaderRGBAf[1] = state->colourmod[1]/32.0f;
ent->shaderRGBAf[2] = state->colourmod[2]/32.0f;
ent->shaderRGBAf[3] = state->alpha/255.0f;
if (state->alpha != 255)
ent->flags |= Q2RF_TRANSLUCENT;
ent->fatness = state->fatness/16;
//

View File

@ -1890,6 +1890,7 @@ void CL_SmokeAndFlash(vec3_t origin)
// ex->type = ex_misc;
ex->numframes = 4;
ex->flags = Q2RF_TRANSLUCENT;
ex->alpha = 1;
ex->start = cl.time;
ex->model = Mod_ForName (q2tentmodels[q2cl_mod_smoke].modelname, false);
@ -2060,7 +2061,8 @@ void CLQ2_ParseTEnt (void)
ex->model = Mod_ForName (q2tentmodels[q2cl_mod_explode].modelname, false);
ex->firstframe = 0;
ex->numframes = 4;
ex->flags = Q2RF_FULLBRIGHT|Q2RF_ADDITIVE|RF_NOSHADOW;
ex->flags = Q2RF_FULLBRIGHT|Q2RF_ADDITIVE|RF_NOSHADOW|Q2RF_TRANSLUCENT;
ex->alpha = 1;
ex->angles[0] = acos(dir[2])/M_PI*180;
// PMM - fixed to correct for pitch of 0
@ -2137,8 +2139,8 @@ void CLQ2_ParseTEnt (void)
S_StartSound (-2, 0, S_PrecacheSound ("weapons/grenlx1a.wav"), pos, 1, 1, 0);
// sprite
/*
if (!R_ParticleExplosionHeart(pos))
// if (!R_ParticleExplosionHeart(pos))
{
ex = CL_AllocExplosion ();
VectorCopy (pos, ex->origin);
@ -2146,9 +2148,10 @@ void CLQ2_ParseTEnt (void)
ex->start = cl.time;
ex->model = Mod_ForName (q2tentmodels[q2cl_mod_explo4].modelname, true);
ex->firstframe = 30;
ex->alpha = 1;
ex->flags |= Q2RF_TRANSLUCENT;
ex->numframes = 19;
}
*/
break;
/*
ex = CL_AllocExplosion ();
@ -2232,19 +2235,21 @@ void CLQ2_ParseTEnt (void)
S_StartSound (-2, 0, S_PrecacheSound ("weapons/rocklx1a.wav"), pos, 1, 1, 0);
// sprite
/* if (!R_ParticleExplosionHeart(pos))
// if (!R_ParticleExplosionHeart(pos))
{
ex = CL_AllocExplosion ();
VectorCopy (pos, ex->origin);
VectorClear(ex->angles);
ex->start = cl.time;
ex->model = Mod_ForName (q2tentmodels[q2cl_mod_explo4].modelname, false);
ex->alpha = 1;
ex->flags |= Q2RF_TRANSLUCENT;
if (rand()&1)
ex->firstframe = 15;
else
ex->firstframe = 0;
ex->numframes = 15;
}*/
}
break;
/*
ex = CL_AllocExplosion ();
@ -3011,11 +3016,23 @@ void CL_UpdateExplosions (void)
ent->framestate.g[FS_REG].frame[1] = (int)f+firstframe;
ent->framestate.g[FS_REG].frame[0] = of+firstframe;
ent->framestate.g[FS_REG].lerpfrac = (f - (int)f);
if (ent->model->type == mod_sprite)
if (ent->model && ent->model->type == mod_sprite)
ent->shaderRGBAf[3] = ex->alpha; /*sprites don't fade over time, the animation should do it*/
else
ent->shaderRGBAf[3] = (1.0 - f/(numframes))*ex->alpha;
ent->flags = ex->flags;
if (ex->flags & Q2RF_BEAM)
{
ent->rtype = RT_BEAM;
ent->shaderRGBAf[0] = ((d_8to24rgbtable[ex->skinnum & 0xFF] >> 0) & 0xFF)/255.0;
ent->shaderRGBAf[1] = ((d_8to24rgbtable[ex->skinnum & 0xFF] >> 8) & 0xFF)/255.0;
ent->shaderRGBAf[2] = ((d_8to24rgbtable[ex->skinnum & 0xFF] >> 16) & 0xFF)/255.0;
}
else
{
ent->skinnum = 7*f/(numframes);
}
}
explosions_running = lastrunningexplosion + 1;

View File

@ -406,6 +406,7 @@ void VQ3_AddEntity(const q3refEntity_t *q3)
ent.shaderRGBAf[2] = q3->shaderRGBA[2]/255.0f;
ent.shaderRGBAf[3] = q3->shaderRGBA[3]/255.0f;
/*don't set translucent, the shader is meant to already be correct*/
// if (ent.shaderRGBAf[3] <= 0)
// return;

View File

@ -1307,7 +1307,7 @@ int CLHL_ParseGamePacket(void)
ef->firstframe = 0;
ef->numframes = ef->model->numframes;
if (!(flags & 1))
ef->flags = Q2RF_ADDATIVE;
ef->flags = Q2RF_ADDITIVE;
else
ef->flags = 0;
break;

View File

@ -1351,6 +1351,7 @@ void CLQ2_AddPacketEntities (q2frame_t *frame)
effects = s1->effects;
renderfx = s1->renderfx;
ent.rtype = RT_MODEL;
ent.keynum = s1->number;
ent.scale = 1;
@ -1427,10 +1428,14 @@ void CLQ2_AddPacketEntities (q2frame_t *frame)
// tweak the color of beams
if ( renderfx & Q2RF_BEAM )
{ // the four beam colors are encoded in 32 bits of skinnum (hack)
ent.shaderRGBAf[3] = 0.30;
ent.skinnum = (s1->skinnum >> ((rand() % 4)*8)) & 0xff;
ent.shaderRGBAf[0] = ((d_8to24rgbtable[ent.skinnum & 0xFF] >> 0) & 0xFF)/255.0;
ent.shaderRGBAf[1] = ((d_8to24rgbtable[ent.skinnum & 0xFF] >> 8) & 0xFF)/255.0;
ent.shaderRGBAf[2] = ((d_8to24rgbtable[ent.skinnum & 0xFF] >> 16) & 0xFF)/255.0;
ent.shaderRGBAf[3] = 0.30;
ent.model = NULL;
ent.framestate.g[FS_REG].lerpfrac = 1;
ent.rtype = RT_BEAM;
}
else
{
@ -1629,14 +1634,12 @@ void CLQ2_AddPacketEntities (q2frame_t *frame)
}
}
// pmm
ent.flags = renderfx | Q2RF_TRANSLUCENT;
ent.flags = renderfx;
ent.shaderRGBAf[3] = 0.30;
ent.fatness = 1;
ent.shaderRGBAf[0] = (!!(renderfx & Q2RF_SHELL_RED));
ent.shaderRGBAf[1] = (!!(renderfx & Q2RF_SHELL_GREEN));
ent.shaderRGBAf[2] = (!!(renderfx & Q2RF_SHELL_BLUE));
ent.forcedshader = R_RegisterCustom("q2/shell", Shader_DefaultSkinShell, NULL);
VQ2_AddLerpEntity (&ent);
}
ent.forcedshader = NULL;

View File

@ -606,12 +606,12 @@ static model_t *CSQC_GetModelForIndex(int index)
static qboolean CopyCSQCEdictToEntity(csqcedict_t *in, entity_t *out)
{
int i;
int i, ival;
model_t *model;
unsigned int rflags;
i = in->v->modelindex;
model = CSQC_GetModelForIndex(in->v->modelindex);
ival = in->v->modelindex;
model = CSQC_GetModelForIndex(ival);
if (!model)
return false; //there might be other ent types later as an extension that stop this.
@ -668,23 +668,31 @@ static qboolean CopyCSQCEdictToEntity(csqcedict_t *in, entity_t *out)
}
}
if (in->v->colormap > 0 && in->v->colormap <= MAX_CLIENTS)
ival = in->v->colormap;
if (ival > 0 && ival <= MAX_CLIENTS)
{
out->scoreboard = &cl.players[(int)in->v->colormap-1];
} // TODO: DP COLORMAP extension?
out->scoreboard = &cl.players[ival-1];
}
// TODO: DP COLORMAP extension?
out->shaderRGBAf[0] = 1;
out->shaderRGBAf[1] = 1;
out->shaderRGBAf[2] = 1;
if (!in->xv->alpha)
out->shaderRGBAf[3] = 1;
if (!in->xv->alpha || in->xv->alpha == 1)
{
out->shaderRGBAf[3] = 1.0f;
}
else
{
out->flags |= Q2RF_TRANSLUCENT;
out->shaderRGBAf[3] = in->xv->alpha;
}
out->skinnum = in->v->skin;
out->fatness = in->xv->fatness;
if (in->xv->forceshader >= 1)
out->forcedshader = r_shaders + ((int)in->xv->forceshader-1);
ival = in->xv->forceshader;
if (ival >= 1 && ival <= MAX_SHADERS)
out->forcedshader = r_shaders + (ival-1);
else
out->forcedshader = NULL;

View File

@ -253,7 +253,10 @@ void R2D_Init(void)
mpic_t *R2D_SafeCachePic (char *path)
{
shader_t *s = R_RegisterPic(path);
shader_t *s;
if (!qrenderer)
return NULL;
s = R_RegisterPic(path);
if (s->width)
return s;
return NULL;

View File

@ -1933,7 +1933,7 @@ void Surf_GenBrushBatches(batch_t **batches, entity_t *ent)
bef |= BEF_FORCETRANSPARENT;
ent->shaderRGBAf[3] = r_wateralpha.value;
}
else if (ent->shaderRGBAf[3] < 1 && cls.protocol != CP_QUAKE3)
else if (ent->flags & Q2RF_TRANSLUCENT && cls.protocol != CP_QUAKE3)
bef |= BEF_FORCETRANSPARENT;
if (ent->flags & RF_NODEPTHTEST)
bef |= BEF_FORCENODEPTH;

View File

@ -169,6 +169,8 @@ extern struct texture_s *r_notexture_mip;
extern entity_t r_worldentity;
void BE_GenModelBatches(struct batch_s **batches);
//gl_alias.c
void R_GAlias_DrawBatch(struct batch_s *batch);
void R_GAlias_GenerateBatches(entity_t *e, struct batch_s **batches);

View File

@ -672,6 +672,12 @@ void Sbar_ShowScores (void)
}
void Sbar_Hexen2InvLeft_f(void)
{
if (cls.protocol == CP_QUAKE2)
{
CL_SendClientCommand(true, "invprev");
}
else
{
int tries = 15;
int pnum = CL_TargettedSplit(false);
@ -686,7 +692,14 @@ void Sbar_Hexen2InvLeft_f(void)
break;
}
}
}
void Sbar_Hexen2InvRight_f(void)
{
if (cls.protocol == CP_QUAKE2)
{
CL_SendClientCommand(true, "invnext");
}
else
{
int tries = 15;
int pnum = CL_TargettedSplit(false);
@ -701,11 +714,19 @@ void Sbar_Hexen2InvRight_f(void)
break;
}
}
}
void Sbar_Hexen2InvUse_f(void)
{
if (cls.protocol == CP_QUAKE2)
{
CL_SendClientCommand(true, "invuse");
}
else
{
int pnum = CL_TargettedSplit(false);
Cmd_ExecuteString(va("impulse %d\n", 100+sb_hexen2_cur_item[pnum]), Cmd_ExecLevel);
}
}
void Sbar_Hexen2ShowInfo_f(void)
{
int pnum = CL_TargettedSplit(false);
@ -938,6 +959,8 @@ void Sbar_Init (void)
//stuff to get hexen2 working out-of-the-box
Cmd_AddCommand ("invleft", Sbar_Hexen2InvLeft_f);
Cmd_AddCommand ("invright", Sbar_Hexen2InvRight_f);
Cmd_AddCommand ("invprev", Sbar_Hexen2InvLeft_f);
Cmd_AddCommand ("invnext", Sbar_Hexen2InvRight_f);
Cmd_AddCommand ("invuse", Sbar_Hexen2InvUse_f);
Cmd_AddCommand ("+showinfo", Sbar_Hexen2ShowInfo_f);
Cmd_AddCommand ("-showinfo", Sbar_Hexen2DontShowInfo_f);

View File

@ -123,6 +123,8 @@ typedef struct
int curvertdecl;
unsigned int shaderbits;
unsigned int curcull;
float depthbias;
float depthfactor;
unsigned int lastpasscount;
texid_t curtex[MAX_TMUS];
@ -338,14 +340,17 @@ static void D3DBE_ApplyShaderBits(unsigned int bits)
{
unsigned int delta;
if (shaderstate.flags & ~BEF_PUSHDEPTH)
if (shaderstate.flags & (BEF_FORCEADDITIVE|BEF_FORCETRANSPARENT|BEF_FORCENODEPTH|BEF_FORCEDEPTHTEST|BEF_FORCEDEPTHWRITE))
{
if (shaderstate.flags & BEF_FORCEADDITIVE)
bits = (bits & ~(SBITS_MISC_DEPTHWRITE|SBITS_BLEND_BITS|SBITS_ATEST_BITS))
| (SBITS_SRCBLEND_ONE | SBITS_DSTBLEND_ONE);
else if ((shaderstate.flags & BEF_FORCETRANSPARENT) && !(bits & SBITS_BLEND_BITS)) /*if transparency is forced, clear alpha test bits*/
| (SBITS_SRCBLEND_SRC_ALPHA | SBITS_DSTBLEND_ONE);
else if (shaderstate.flags & BEF_FORCETRANSPARENT)
{
if ((bits & SBITS_BLEND_BITS) == (SBITS_SRCBLEND_ONE|SBITS_DSTBLEND_ZERO) || !(bits & SBITS_BLEND_BITS)) /*if transparency is forced, clear alpha test bits*/
bits = (bits & ~(SBITS_MISC_DEPTHWRITE|SBITS_BLEND_BITS|SBITS_ATEST_BITS))
| (SBITS_SRCBLEND_SRC_ALPHA | SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA);
}
if (shaderstate.flags & BEF_FORCENODEPTH) /*EF_NODEPTHTEST dp extension*/
bits |= SBITS_MISC_NODEPTHTEST;
@ -1549,8 +1554,24 @@ static void BE_DrawMeshChain_Internal(void)
unsigned int mno;
unsigned int passno = 0;
shaderpass_t *pass = shaderstate.curshader->passes;
extern cvar_t r_polygonoffset_submodel_offset, r_polygonoffset_submodel_factor;
float pushdepth;
// float pushfactor;
BE_Cull(shaderstate.curshader->flags & (SHADER_CULL_FRONT | SHADER_CULL_BACK));
pushdepth = (shaderstate.curshader->polyoffset.factor + ((shaderstate.flags & BEF_PUSHDEPTH)?r_polygonoffset_submodel_offset.value:0))/0xffff;
if (pushdepth != shaderstate.depthbias)
{
shaderstate.depthbias = pushdepth;
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_DEPTHBIAS, *(DWORD*)&shaderstate.depthbias);
}
// pushdepth = shaderstate.curshader->polyoffset.unit/-1;// + ((shaderstate.flags & BEF_PUSHDEPTH)?8:0);
// pushfactor = shaderstate.curshader->polyoffset.factor/-1;
// if (pushfactor != shaderstate.depthfactor)
// {
// shaderstate.depthfactor = pushfactor;
// IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_SLOPESCALEDEPTHBIAS, *(DWORD*)&shaderstate.depthfactor);
// }
for (mno = 0, vertcount = 0, idxcount = 0; mno < shaderstate.nummeshes; mno++)
{
@ -1995,18 +2016,19 @@ void D3DBE_SubmitBatch(batch_t *batch)
BE_DrawMeshChain_Internal();
}
void D3DBE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **meshlist, vbo_t *vbo, texnums_t *texnums)
void D3DBE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **meshlist, vbo_t *vbo, texnums_t *texnums, unsigned int beflags)
{
shaderstate.curshader = shader;
shaderstate.curtexnums = texnums;
shaderstate.curlightmap = r_nulltex;
shaderstate.meshlist = meshlist;
shaderstate.nummeshes = nummeshes;
shaderstate.flags = beflags;
BE_DrawMeshChain_Internal();
}
void D3DBE_DrawMesh_Single(shader_t *shader, mesh_t *meshchain, vbo_t *vbo, texnums_t *texnums)
void D3DBE_DrawMesh_Single(shader_t *shader, mesh_t *meshchain, vbo_t *vbo, texnums_t *texnums, unsigned int beflags)
{
shaderstate.curtime = realtime;
shaderstate.curshader = shader;
@ -2014,209 +2036,11 @@ void D3DBE_DrawMesh_Single(shader_t *shader, mesh_t *meshchain, vbo_t *vbo, texn
shaderstate.curlightmap = r_nulltex;
shaderstate.meshlist = &meshchain;
shaderstate.nummeshes = 1;
shaderstate.flags = beflags;
BE_DrawMeshChain_Internal();
}
qboolean BE_ShouldDraw(entity_t *e)
{
if (!r_refdef.externalview && (e->externalmodelview & (1<<r_refdef.currentplayernum)))
return false;
if (!Cam_DrawPlayer(r_refdef.currentplayernum, e->keynum-1))
return false;
return true;
}
#ifdef Q3CLIENT
//q3 lightning gun
static void R_DrawLightning(entity_t *e)
{
vec3_t v;
vec3_t dir, cr;
float scale = e->scale;
float length;
vecV_t points[4];
vec2_t texcoords[4] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}};
static index_t indexarray[6] = {0, 1, 2, 0, 2, 3};
mesh_t mesh;
if (!e->forcedshader)
return;
if (!scale)
scale = 10;
VectorSubtract(e->origin, e->oldorigin, dir);
length = Length(dir);
//this seems to be about right.
texcoords[2][0] = length/128;
texcoords[3][0] = length/128;
VectorSubtract(r_refdef.vieworg, e->origin, v);
CrossProduct(v, dir, cr);
VectorNormalize(cr);
VectorMA(e->origin, -scale/2, cr, points[0]);
VectorMA(e->origin, scale/2, cr, points[1]);
VectorSubtract(r_refdef.vieworg, e->oldorigin, v);
CrossProduct(v, dir, cr);
VectorNormalize(cr);
VectorMA(e->oldorigin, scale/2, cr, points[2]);
VectorMA(e->oldorigin, -scale/2, cr, points[3]);
memset(&mesh, 0, sizeof(mesh));
mesh.vbofirstelement = 0;
mesh.vbofirstvert = 0;
mesh.xyz_array = points;
mesh.indexes = indexarray;
mesh.numindexes = sizeof(indexarray)/sizeof(indexarray[0]);
mesh.colors4f_array = NULL;
mesh.lmst_array = NULL;
mesh.normals_array = NULL;
mesh.numvertexes = 4;
mesh.st_array = texcoords;
BE_DrawMesh_Single(e->forcedshader, &mesh, NULL, NULL, 0);
}
//q3 railgun beam
static void R_DrawRailCore(entity_t *e)
{
vec3_t v;
vec3_t dir, cr;
float scale = e->scale;
float length;
mesh_t mesh;
vecV_t points[4];
vec2_t texcoords[4] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}};
static index_t indexarray[6] = {0, 1, 2, 0, 2, 3};
vec4_t colors[4];
if (!e->forcedshader)
return;
if (!scale)
scale = 10;
VectorSubtract(e->origin, e->oldorigin, dir);
length = Length(dir);
//this seems to be about right.
texcoords[2][0] = length/128;
texcoords[3][0] = length/128;
VectorSubtract(r_refdef.vieworg, e->origin, v);
CrossProduct(v, dir, cr);
VectorNormalize(cr);
VectorMA(e->origin, -scale/2, cr, points[0]);
VectorMA(e->origin, scale/2, cr, points[1]);
VectorSubtract(r_refdef.vieworg, e->oldorigin, v);
CrossProduct(v, dir, cr);
VectorNormalize(cr);
VectorMA(e->oldorigin, scale/2, cr, points[2]);
VectorMA(e->oldorigin, -scale/2, cr, points[3]);
Vector4Copy(e->shaderRGBAf, colors[0]);
Vector4Copy(e->shaderRGBAf, colors[1]);
Vector4Copy(e->shaderRGBAf, colors[2]);
Vector4Copy(e->shaderRGBAf, colors[3]);
memset(&mesh, 0, sizeof(mesh));
mesh.vbofirstelement = 0;
mesh.vbofirstvert = 0;
mesh.xyz_array = points;
mesh.indexes = indexarray;
mesh.numindexes = sizeof(indexarray)/sizeof(indexarray[0]);
mesh.colors4f_array = (vec4_t*)colors;
mesh.lmst_array = NULL;
mesh.normals_array = NULL;
mesh.numvertexes = 4;
mesh.st_array = texcoords;
BE_DrawMesh_Single(e->forcedshader, &mesh, NULL, NULL, 0);
}
#endif
static void BE_GenModelBatches(batch_t **batches)
{
int i;
entity_t *ent;
/*clear the batch list*/
for (i = 0; i < SHADER_SORT_COUNT; i++)
batches[i] = NULL;
if (!r_drawentities.ival)
return;
// draw sprites seperately, because of alpha blending
for (i=0 ; i<cl_numvisedicts ; i++)
{
ent = &cl_visedicts[i];
if (!BE_ShouldDraw(ent))
continue;
switch(ent->rtype)
{
case RT_MODEL:
default:
if (!ent->model)
continue;
if (ent->model->needload)
continue;
switch(ent->model->type)
{
case mod_brush:
if (r_drawentities.ival == 2)
continue;
Surf_GenBrushBatches(batches, ent);
break;
case mod_alias:
if (r_drawentities.ival == 3)
continue;
R_GAlias_GenerateBatches(ent, batches);
break;
case mod_sprite:
break;
}
break;
case RT_SPRITE:
//RQ_AddDistReorder(GLR_DrawSprite, currententity, NULL, currententity->origin);
break;
#ifdef Q3CLIENT
case RT_BEAM:
case RT_RAIL_RINGS:
case RT_LIGHTNING:
R_DrawLightning(ent);
continue;
case RT_RAIL_CORE:
R_DrawRailCore(ent);
continue;
#endif
case RT_POLY:
/*not implemented*/
break;
case RT_PORTALSURFACE:
/*nothing*/
break;
}
}
}
static void BE_SubmitMeshesSortList(batch_t *sortlist)
{
batch_t *batch;

View File

@ -991,6 +991,12 @@ void R_GAlias_GenerateBatches(entity_t *e, batch_t **batches)
b->lightmap = -1;
b->surf_first = surfnum;
b->flags = 0;
if (e->flags & Q2RF_ADDITIVE)
b->flags |= BEF_FORCEADDITIVE;
if (e->flags & Q2RF_TRANSLUCENT)
b->flags |= BEF_FORCETRANSPARENT;
if (e->flags & RF_NODEPTHTEST)
b->flags |= BEF_FORCENODEPTH;
b->vbo = 0;
b->next = batches[shader->sort];
batches[shader->sort] = b;
@ -1433,3 +1439,487 @@ void GL_GenerateNormals(float *orgs, float *normals, int *indicies, int numtris,
#endif
#endif // defined(GLQUAKE)
qboolean BE_ShouldDraw(entity_t *e)
{
if (!r_refdef.externalview && (e->externalmodelview & (1<<r_refdef.currentplayernum)))
return false;
if (!Cam_DrawPlayer(r_refdef.currentplayernum, e->keynum-1))
return false;
return true;
}
#ifdef Q3CLIENT
//q3 lightning gun
static void R_DB_LightningBeam(batch_t *batch)
{
entity_t *e = batch->ent;
vec3_t v;
vec3_t dir, cr;
float scale = e->scale;
float length;
static vecV_t points[4];
static vec2_t texcoords[4] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}};
static index_t indexarray[6] = {0, 1, 2, 0, 2, 3};
static vec4_t colors[4];
static mesh_t mesh;
static mesh_t *meshptr = &mesh;
scale *= -10;
if (!scale)
scale = 10;
VectorSubtract(e->origin, e->oldorigin, dir);
length = Length(dir);
//this seems to be about right.
texcoords[2][0] = length/128;
texcoords[3][0] = length/128;
VectorSubtract(r_refdef.vieworg, e->origin, v);
CrossProduct(v, dir, cr);
VectorNormalize(cr);
VectorMA(e->origin, -scale/2, cr, points[0]);
VectorMA(e->origin, scale/2, cr, points[1]);
VectorSubtract(r_refdef.vieworg, e->oldorigin, v);
CrossProduct(v, dir, cr);
VectorNormalize(cr);
VectorMA(e->oldorigin, scale/2, cr, points[2]);
VectorMA(e->oldorigin, -scale/2, cr, points[3]);
/*this is actually meant to be 4 separate quads at 45 degrees from each other*/
Vector4Copy(e->shaderRGBAf, colors[0]);
Vector4Copy(e->shaderRGBAf, colors[1]);
Vector4Copy(e->shaderRGBAf, colors[2]);
Vector4Copy(e->shaderRGBAf, colors[3]);
batch->ent = &r_worldentity;
batch->mesh = &meshptr;
memset(&mesh, 0, sizeof(mesh));
mesh.vbofirstelement = 0;
mesh.vbofirstvert = 0;
mesh.xyz_array = points;
mesh.indexes = indexarray;
mesh.numindexes = sizeof(indexarray)/sizeof(indexarray[0]);
mesh.colors4f_array = (vec4_t*)colors;
mesh.lmst_array = NULL;
mesh.normals_array = NULL;
mesh.numvertexes = 4;
mesh.st_array = texcoords;
}
//q3 railgun beam
static void R_DB_RailgunBeam(batch_t *batch)
{
entity_t *e = batch->ent;
vec3_t v;
vec3_t dir, cr;
float scale = e->scale;
float length;
static mesh_t mesh;
static mesh_t *meshptr = &mesh;
static vecV_t points[4];
static vec2_t texcoords[4] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}};
static index_t indexarray[6] = {0, 1, 2, 0, 2, 3};
static vec4_t colors[4];
if (!e->forcedshader)
return;
if (!scale)
scale = 10;
VectorSubtract(e->origin, e->oldorigin, dir);
length = Length(dir);
//this seems to be about right.
texcoords[2][0] = length/128;
texcoords[3][0] = length/128;
VectorSubtract(r_refdef.vieworg, e->origin, v);
CrossProduct(v, dir, cr);
VectorNormalize(cr);
VectorMA(e->origin, -scale/2, cr, points[0]);
VectorMA(e->origin, scale/2, cr, points[1]);
VectorSubtract(r_refdef.vieworg, e->oldorigin, v);
CrossProduct(v, dir, cr);
VectorNormalize(cr);
VectorMA(e->oldorigin, scale/2, cr, points[2]);
VectorMA(e->oldorigin, -scale/2, cr, points[3]);
Vector4Copy(e->shaderRGBAf, colors[0]);
Vector4Copy(e->shaderRGBAf, colors[1]);
Vector4Copy(e->shaderRGBAf, colors[2]);
Vector4Copy(e->shaderRGBAf, colors[3]);
batch->ent = &r_worldentity;
batch->mesh = &meshptr;
memset(&mesh, 0, sizeof(mesh));
mesh.vbofirstelement = 0;
mesh.vbofirstvert = 0;
mesh.xyz_array = points;
mesh.indexes = indexarray;
mesh.numindexes = sizeof(indexarray)/sizeof(indexarray[0]);
mesh.colors4f_array = (vec4_t*)colors;
mesh.lmst_array = NULL;
mesh.normals_array = NULL;
mesh.numvertexes = 4;
mesh.st_array = texcoords;
}
#endif
static void R_DB_Sprite(batch_t *batch)
{
entity_t *e = batch->ent;
vec3_t point;
mspriteframe_t *frame, genframe;
vec3_t forward, right, up;
msprite_t *psprite;
vec3_t sprorigin;
unsigned int fl = 0;
unsigned int sprtype;
static vec2_t texcoords[4]={{0, 1},{0,0},{1,0},{1,1}};
static index_t indexes[6] = {0, 1, 2, 0, 2, 3};
static vecV_t vertcoords[4];
static avec4_t colours[4];
static mesh_t mesh;
static mesh_t *meshptr = &mesh;
if (e->flags & Q2RF_WEAPONMODEL && r_refdef.currentplayernum >= 0)
{
sprorigin[0] = cl.viewent[r_refdef.currentplayernum].origin[0];
sprorigin[1] = cl.viewent[r_refdef.currentplayernum].origin[1];
sprorigin[2] = cl.viewent[r_refdef.currentplayernum].origin[2];
VectorMA(sprorigin, e->origin[0], cl.viewent[r_refdef.currentplayernum].axis[0], sprorigin);
VectorMA(sprorigin, e->origin[1], cl.viewent[r_refdef.currentplayernum].axis[1], sprorigin);
VectorMA(sprorigin, e->origin[2], cl.viewent[r_refdef.currentplayernum].axis[2], sprorigin);
VectorMA(sprorigin, 12, vpn, sprorigin);
batch->flags |= BEF_FORCENODEPTH;
}
else
VectorCopy(e->origin, sprorigin);
if (!e->model || e->forcedshader)
{
genframe.shader = e->forcedshader;
genframe.up = genframe.left = -1;
genframe.down = genframe.right = 1;
sprtype = SPR_VP_PARALLEL;
frame = &genframe;
}
else
{
// don't even bother culling, because it's just a single
// polygon without a surface cache
frame = R_GetSpriteFrame (e);
psprite = e->model->cache.data;
sprtype = psprite->type;
}
if (!frame->shader)
return;
switch(sprtype)
{
case SPR_ORIENTED:
// bullet marks on walls
AngleVectors (e->angles, forward, right, up);
break;
case SPR_FACING_UPRIGHT:
up[0] = 0;up[1] = 0;up[2]=1;
right[0] = sprorigin[1] - r_origin[1];
right[1] = -(sprorigin[0] - r_origin[0]);
right[2] = 0;
VectorNormalize (right);
break;
case SPR_VP_PARALLEL_UPRIGHT:
up[0] = 0;up[1] = 0;up[2]=1;
VectorCopy (vright, right);
break;
default:
case SPR_VP_PARALLEL:
//normal sprite
VectorCopy(vup, up);
VectorCopy(vright, right);
break;
}
up[0]*=e->scale;
up[1]*=e->scale;
up[2]*=e->scale;
right[0]*=e->scale;
right[1]*=e->scale;
right[2]*=e->scale;
if (e->shaderRGBAf[0] > 1)
e->shaderRGBAf[0] = 1;
if (e->shaderRGBAf[1] > 1)
e->shaderRGBAf[1] = 1;
if (e->shaderRGBAf[2] > 1)
e->shaderRGBAf[2] = 1;
Vector4Copy(e->shaderRGBAf, colours[0]);
Vector4Copy(e->shaderRGBAf, colours[1]);
Vector4Copy(e->shaderRGBAf, colours[2]);
Vector4Copy(e->shaderRGBAf, colours[3]);
VectorMA (sprorigin, frame->down, up, point);
VectorMA (point, frame->left, right, vertcoords[0]);
VectorMA (sprorigin, frame->up, up, point);
VectorMA (point, frame->left, right, vertcoords[1]);
VectorMA (sprorigin, frame->up, up, point);
VectorMA (point, frame->right, right, vertcoords[2]);
VectorMA (sprorigin, frame->down, up, point);
VectorMA (point, frame->right, right, vertcoords[3]);
batch->ent = &r_worldentity;
batch->flags |= fl;
batch->mesh = &meshptr;
memset(&mesh, 0, sizeof(mesh));
mesh.vbofirstelement = 0;
mesh.vbofirstvert = 0;
mesh.xyz_array = vertcoords;
mesh.indexes = indexes;
mesh.numindexes = sizeof(indexes)/sizeof(indexes[0]);
mesh.colors4f_array = colours;
mesh.lmst_array = NULL;
mesh.normals_array = NULL;
mesh.numvertexes = 4;
mesh.st_array = texcoords;
mesh.istrifan = true;
}
static void R_Sprite_GenerateBatch(entity_t *e, batch_t **batches, void (*drawfunc)(batch_t *batch))
{
extern cvar_t gl_blendsprites;
shader_t *shader = NULL;
batch_t *b;
shadersort_t sort;
if (!e->model || e->model->type != mod_sprite || e->forcedshader)
{
shader = e->forcedshader;
if (!shader)
shader = R_RegisterShader("q2beam",
"{\n"
"{\n"
"map $whiteimage\n"
"rgbgen vertex\n"
"alphagen vertex\n"
"blendfunc blend\n"
"}\n"
"}\n"
);
}
else
{
// don't even bother culling, because it's just a single
// polygon without a surface cache
shader = R_GetSpriteFrame(e)->shader;
}
if (!shader)
return;
b = BE_GetTempBatch();
if (!b)
return;
b->flags = 0;
sort = shader->sort;
if (e->flags & Q2RF_ADDITIVE)
{
b->flags |= BEF_FORCEADDITIVE;
if (sort < SHADER_SORT_ADDITIVE)
sort = SHADER_SORT_ADDITIVE;
}
if (e->flags & Q2RF_TRANSLUCENT || (gl_blendsprites.ival && drawfunc == R_DB_Sprite))
{
b->flags |= BEF_FORCETRANSPARENT;
if (sort < SHADER_SORT_BLEND)
sort = SHADER_SORT_BLEND;
}
if (e->flags & RF_NODEPTHTEST)
{
b->flags |= BEF_FORCENODEPTH;
if (sort < SHADER_SORT_BANNER)
sort = SHADER_SORT_BANNER;
}
b->buildmeshes = drawfunc;
b->ent = e;
b->mesh = NULL;
b->firstmesh = 0;
b->meshes = 1;
b->skin = &shader->defaulttextures;
b->texture = NULL;
b->shader = shader;
b->lightmap = -1;
b->surf_first = 0;
b->flags |= BEF_NODLIGHT|BEF_NOSHADOWS;
b->vbo = 0;
b->next = batches[sort];
batches[sort] = b;
}
static void R_DB_Poly(batch_t *batch)
{
static mesh_t mesh;
static mesh_t *meshptr = &mesh;
unsigned int i = batch->surf_first;
batch->mesh = &meshptr;
mesh.xyz_array = cl_strisvertv + cl_stris[i].firstvert;
mesh.st_array = cl_strisvertt + cl_stris[i].firstvert;
mesh.colors4f_array = cl_strisvertc + cl_stris[i].firstvert;
mesh.indexes = cl_strisidx + cl_stris[i].firstidx;
mesh.numindexes = cl_stris[i].numidx;
mesh.numvertexes = cl_stris[i].numvert;
}
void BE_GenPolyBatches(batch_t **batches)
{
shader_t *shader = NULL;
batch_t *b;
unsigned int i;
for (i = 0; i < cl_numstris; i++)
{
b = BE_GetTempBatch();
if (!b)
return;
shader = cl_stris[i].shader;
b->buildmeshes = R_DB_Poly;
b->ent = &r_worldentity;
b->mesh = NULL;
b->firstmesh = 0;
b->meshes = 1;
b->skin = &shader->defaulttextures;
b->texture = NULL;
b->shader = shader;
b->lightmap = -1;
b->surf_first = i;
b->flags = BEF_NODLIGHT|BEF_NOSHADOWS;
b->vbo = 0;
b->next = batches[shader->sort];
batches[shader->sort] = b;
}
}
void BE_GenModelBatches(batch_t **batches)
{
int i;
entity_t *ent;
/*clear the batch list*/
for (i = 0; i < SHADER_SORT_COUNT; i++)
batches[i] = NULL;
if (!r_drawentities.ival)
return;
// draw sprites seperately, because of alpha blending
for (i=0 ; i<cl_numvisedicts ; i++)
{
ent = &cl_visedicts[i];
if (!BE_ShouldDraw(ent))
continue;
switch(ent->rtype)
{
case RT_MODEL:
default:
if (!ent->model)
continue;
if (ent->model->needload)
continue;
if (cl.lerpents && (cls.allow_anyparticles || ent->visframe)) //allowed or static
{
if (gl_part_flame.value)
{
if (ent->model->engineflags & MDLF_ENGULPHS)
continue;
}
}
if (ent->model->engineflags & MDLF_NOTREPLACEMENTS)
{
if (ent->model->fromgame != fg_quake || ent->model->type != mod_alias)
if (!ruleset_allow_sensative_texture_replacements.value)
continue;
}
switch(ent->model->type)
{
case mod_brush:
if (r_drawentities.ival == 2)
continue;
Surf_GenBrushBatches(batches, ent);
break;
case mod_alias:
if (r_drawentities.ival == 3)
continue;
R_GAlias_GenerateBatches(ent, batches);
break;
case mod_sprite:
R_Sprite_GenerateBatch(ent, batches, R_DB_Sprite);
break;
}
break;
case RT_SPRITE:
R_Sprite_GenerateBatch(ent, batches, R_DB_Sprite);
break;
#ifdef Q3CLIENT
case RT_BEAM:
case RT_RAIL_RINGS:
case RT_LIGHTNING:
R_Sprite_GenerateBatch(ent, batches, R_DB_LightningBeam);
continue;
case RT_RAIL_CORE:
R_Sprite_GenerateBatch(ent, batches, R_DB_RailgunBeam);
continue;
#endif
case RT_POLY:
/*not implemented*/
break;
case RT_PORTALSURFACE:
/*nothing*/
break;
}
}
if (cl_numstris)
BE_GenPolyBatches(batches);
}

View File

@ -395,12 +395,9 @@ struct {
texid_t lighttexture;
};
int wmesh;
int maxwmesh;
int wbatch;
int maxwbatches;
batch_t *wbatches;
mesh_t **wmeshes;
} shaderstate;
struct {
@ -1943,14 +1940,17 @@ static void BE_SendPassBlendDepthMask(unsigned int sbits)
sbits &= ~(SBITS_MISC_DEPTHWRITE|SBITS_MISC_DEPTHEQUALONLY);
sbits |= SBITS_MISC_NODEPTHTEST;
}
if (shaderstate.flags & ~BEF_PUSHDEPTH)
if (shaderstate.flags & (BEF_FORCEADDITIVE|BEF_FORCETRANSPARENT|BEF_FORCENODEPTH|BEF_FORCEDEPTHTEST|BEF_FORCEDEPTHWRITE))
{
if (shaderstate.flags & BEF_FORCEADDITIVE)
sbits = (sbits & ~(SBITS_MISC_DEPTHWRITE|SBITS_BLEND_BITS|SBITS_ATEST_BITS))
| (SBITS_SRCBLEND_ONE | SBITS_DSTBLEND_ONE);
else if ((shaderstate.flags & BEF_FORCETRANSPARENT) && !(sbits & SBITS_BLEND_BITS)) /*if transparency is forced, clear alpha test bits*/
| (SBITS_SRCBLEND_SRC_ALPHA | SBITS_DSTBLEND_ONE);
else if (shaderstate.flags & BEF_FORCETRANSPARENT)
{
if ((sbits & SBITS_BLEND_BITS) == (SBITS_SRCBLEND_ONE| SBITS_DSTBLEND_ZERO) || !(sbits & SBITS_BLEND_BITS)) /*if transparency is forced, clear alpha test bits*/
sbits = (sbits & ~(SBITS_MISC_DEPTHWRITE|SBITS_BLEND_BITS|SBITS_ATEST_BITS))
| (SBITS_SRCBLEND_SRC_ALPHA | SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA);
}
if (shaderstate.flags & BEF_FORCENODEPTH) /*EF_NODEPTHTEST dp extension*/
sbits |= SBITS_MISC_NODEPTHTEST;
@ -2568,6 +2568,7 @@ void GLBE_SelectMode(backendmode_t mode)
if (mode != shaderstate.mode)
{
shaderstate.mode = mode;
shaderstate.flags = 0;
#ifdef RTLIGHTS
if (mode == BEM_STENCIL)
{
@ -2957,29 +2958,6 @@ void GLBE_DrawMesh_Single(shader_t *shader, mesh_t *mesh, vbo_t *vbo, texnums_t
BE_DrawMesh_List(shader, 1, &mesh, NULL, texnums, beflags);
}
void BE_DrawPolys(qboolean decalsset)
{
unsigned int i;
mesh_t m;
if (!cl_numstris)
return;
memset(&m, 0, sizeof(m));
for (i = 0; i < cl_numstris; i++)
{
if ((cl_stris[i].shader->sort <= SHADER_SORT_DECAL) ^ decalsset)
continue;
m.xyz_array = cl_strisvertv + cl_stris[i].firstvert;
m.st_array = cl_strisvertt + cl_stris[i].firstvert;
m.colors4f_array = cl_strisvertc + cl_stris[i].firstvert;
m.indexes = cl_strisidx + cl_stris[i].firstidx;
m.numindexes = cl_stris[i].numidx;
m.numvertexes = cl_stris[i].numvert;
BE_DrawMesh_Single(cl_stris[i].shader, &m, NULL, &cl_stris[i].shader->defaulttextures, 0);
}
}
void GLBE_SubmitBatch(batch_t *batch)
{
int lm;
@ -3102,6 +3080,13 @@ static void BE_SubmitMeshesSortList(batch_t *sortlist)
if (batch->meshes == batch->firstmesh)
continue;
if (batch->flags & BEF_NODLIGHT)
if (shaderstate.mode == BEM_LIGHT || shaderstate.mode == BEM_SMAPLIGHT)
continue;
if (batch->flags & BEF_NOSHADOWS)
if (shaderstate.mode == BEM_STENCIL)
continue;
if (batch->buildmeshes)
batch->buildmeshes(batch);
else if (batch->texture)
@ -3216,46 +3201,6 @@ batch_t *GLBE_GetTempBatch(void)
return &shaderstate.wbatches[shaderstate.wbatch++];
}
void BE_GenModelBatches(batch_t **batches)
{
int i;
entity_t *ent;
/*clear the batch list*/
for (i = 0; i < SHADER_SORT_COUNT; i++)
batches[i] = NULL;
if (!r_drawentities.ival)
return;
// draw sprites seperately, because of alpha blending
for (i=0 ; i<cl_numvisedicts ; i++)
{
ent = &cl_visedicts[i];
if (!ent->model)
continue;
if (ent->model->needload)
continue;
if (!R_ShouldDraw(ent))
continue;
switch(ent->model->type)
{
case mod_brush:
if (r_drawentities.ival == 2)
continue;
Surf_GenBrushBatches(batches, ent);
break;
case mod_alias:
if (r_drawentities.ival == 3)
continue;
R_GAlias_GenerateBatches(ent, batches);
break;
default:
break;
}
}
}
/*called from shadowmapping code*/
#ifdef RTLIGHTS
void BE_BaseEntTextures(void)
@ -3279,13 +3224,6 @@ void GLBE_DrawWorld (qbyte *vis)
if (!r_refdef.recurse)
{
if (shaderstate.wmesh > shaderstate.maxwmesh)
{
int newm = shaderstate.wmesh;
shaderstate.wmeshes = BZ_Realloc(shaderstate.wmeshes, newm * sizeof(*shaderstate.wmeshes));
memset(shaderstate.wmeshes + shaderstate.maxwmesh, 0, (newm - shaderstate.maxwmesh) * sizeof(*shaderstate.wmeshes));
shaderstate.maxwmesh = newm;
}
if (shaderstate.wbatch > shaderstate.maxwbatches)
{
int newm = shaderstate.wbatch;
@ -3294,7 +3232,6 @@ void GLBE_DrawWorld (qbyte *vis)
shaderstate.maxwbatches = newm;
}
shaderstate.wmesh = 0;
shaderstate.wbatch = 0;
}
BE_GenModelBatches(batches);
@ -3341,8 +3278,6 @@ void GLBE_DrawWorld (qbyte *vis)
RSpeedEnd(RSPEED_STENCILSHADOWS);
#endif
BE_DrawPolys(false);
if (r_refdef.gfog_alpha)
{
BE_SelectMode(BEM_FOG);
@ -3362,13 +3297,6 @@ void BE_DrawNonWorld (void)
checkglerror();
if (shaderstate.wmesh > shaderstate.maxwmesh)
{
int newm = shaderstate.wmesh;
shaderstate.wmeshes = BZ_Realloc(shaderstate.wmeshes, newm * sizeof(*shaderstate.wmeshes));
memset(shaderstate.wmeshes + shaderstate.maxwmesh, 0, (newm - shaderstate.maxwmesh) * sizeof(*shaderstate.wmeshes));
shaderstate.maxwmesh = newm;
}
if (shaderstate.wbatch > shaderstate.maxwbatches)
{
int newm = shaderstate.wbatch;
@ -3377,7 +3305,6 @@ void BE_DrawNonWorld (void)
shaderstate.maxwbatches = newm;
}
shaderstate.wmesh = 0;
shaderstate.wbatch = 0;
BE_GenModelBatches(batches);

View File

@ -3513,8 +3513,8 @@ qboolean RMod_LoadSprite2Model (model_t *mod, void *buffer)
origin[0] = LittleLong (pframetype->origin_x);
origin[1] = LittleLong (pframetype->origin_y);
frame->up = -origin[1];
frame->down = h - origin[1];
frame->down = -origin[1];
frame->up = h - origin[1];
frame->left = -origin[0];
frame->right = w - origin[0];

View File

@ -460,476 +460,8 @@ void R_RotateForEntity (float *modelview, const entity_t *e, const model_t *mod)
}
}
/*
=============================================================
SPRITE MODELS
=============================================================
*/
/*
=================
R_DrawSpriteModel
=================
*/
void R_DrawSpriteModel (entity_t *e)
{
vec3_t point;
mspriteframe_t *frame, genframe;
vec3_t forward, right, up;
msprite_t *psprite;
vec3_t sprorigin;
unsigned int fl;
unsigned int sprtype;
static vec2_t texcoords[4]={{0, 1},{0,0},{1,0},{1,1}};
static index_t indexes[6] = {0, 1, 2, 0, 2, 3};
vecV_t vertcoords[4];
avec4_t colours[4];
mesh_t mesh;
if (e->flags & Q2RF_WEAPONMODEL && r_refdef.currentplayernum >= 0)
{
sprorigin[0] = cl.viewent[r_refdef.currentplayernum].origin[0];
sprorigin[1] = cl.viewent[r_refdef.currentplayernum].origin[1];
sprorigin[2] = cl.viewent[r_refdef.currentplayernum].origin[2];
VectorMA(sprorigin, e->origin[0], cl.viewent[r_refdef.currentplayernum].axis[0], sprorigin);
VectorMA(sprorigin, e->origin[1], cl.viewent[r_refdef.currentplayernum].axis[1], sprorigin);
VectorMA(sprorigin, e->origin[2], cl.viewent[r_refdef.currentplayernum].axis[2], sprorigin);
VectorMA(sprorigin, 12, vpn, sprorigin);
e->flags |= RF_NODEPTHTEST;
}
else
VectorCopy(e->origin, sprorigin);
if (!e->model || e->forcedshader)
{
genframe.shader = e->forcedshader;
genframe.up = genframe.left = -1;
genframe.down = genframe.right = 1;
sprtype = SPR_VP_PARALLEL;
frame = &genframe;
}
else
{
// don't even bother culling, because it's just a single
// polygon without a surface cache
frame = R_GetSpriteFrame (e);
psprite = e->model->cache.data;
sprtype = psprite->type;
}
if (!frame->shader)
return;
switch(sprtype)
{
case SPR_ORIENTED:
// bullet marks on walls
AngleVectors (e->angles, forward, right, up);
break;
case SPR_FACING_UPRIGHT:
up[0] = 0;up[1] = 0;up[2]=1;
right[0] = sprorigin[1] - r_origin[1];
right[1] = -(sprorigin[0] - r_origin[0]);
right[2] = 0;
VectorNormalize (right);
break;
case SPR_VP_PARALLEL_UPRIGHT:
up[0] = 0;up[1] = 0;up[2]=1;
VectorCopy (vright, right);
break;
default:
case SPR_VP_PARALLEL:
//normal sprite
VectorCopy(vup, up);
VectorCopy(vright, right);
break;
}
up[0]*=e->scale;
up[1]*=e->scale;
up[2]*=e->scale;
right[0]*=e->scale;
right[1]*=e->scale;
right[2]*=e->scale;
Vector4Copy(e->shaderRGBAf, colours[0]);
Vector4Copy(e->shaderRGBAf, colours[1]);
Vector4Copy(e->shaderRGBAf, colours[2]);
Vector4Copy(e->shaderRGBAf, colours[3]);
fl = 0;
if (e->flags & Q2RF_ADDITIVE)
fl |= BEF_FORCEADDITIVE;
if (e->shaderRGBAf[3]<1 || gl_blendsprites.value)
fl |= BEF_FORCETRANSPARENT;
if (e->flags & RF_NODEPTHTEST)
fl |= BEF_FORCENODEPTH;
VectorMA (sprorigin, frame->down, up, point);
VectorMA (point, frame->left, right, vertcoords[0]);
VectorMA (sprorigin, frame->up, up, point);
VectorMA (point, frame->left, right, vertcoords[1]);
VectorMA (sprorigin, frame->up, up, point);
VectorMA (point, frame->right, right, vertcoords[2]);
VectorMA (sprorigin, frame->down, up, point);
VectorMA (point, frame->right, right, vertcoords[3]);
memset(&mesh, 0, sizeof(mesh));
mesh.vbofirstelement = 0;
mesh.vbofirstvert = 0;
mesh.xyz_array = vertcoords;
mesh.indexes = indexes;
mesh.numindexes = sizeof(indexes)/sizeof(indexes[0]);
mesh.colors4f_array = colours;
mesh.lmst_array = NULL;
mesh.normals_array = NULL;
mesh.numvertexes = 4;
mesh.st_array = texcoords;
mesh.istrifan = true;
BE_DrawMesh_Single(frame->shader, &mesh, NULL, &frame->shader->defaulttextures, fl);
}
//==================================================================================
void GLR_DrawSprite(int count, void **e, void *parm)
{
while(count--)
{
#pragma message("this needs merging or q3 railgun will lag like hell")
currententity = e[count];
R_DrawSpriteModel (currententity);
}
}
#ifdef Q3CLIENT
//q3 lightning gun
void R_DrawLightning(entity_t *e)
{
vec3_t v;
vec3_t dir, cr;
float scale = e->scale;
float length;
vecV_t points[4];
vec2_t texcoords[4] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}};
static index_t indexarray[6] = {0, 1, 2, 0, 2, 3};
mesh_t mesh;
if (!e->forcedshader)
return;
if (!scale)
scale = 10;
VectorSubtract(e->origin, e->oldorigin, dir);
length = Length(dir);
//this seems to be about right.
texcoords[2][0] = length/128;
texcoords[3][0] = length/128;
VectorSubtract(r_refdef.vieworg, e->origin, v);
CrossProduct(v, dir, cr);
VectorNormalize(cr);
VectorMA(e->origin, -scale/2, cr, points[0]);
VectorMA(e->origin, scale/2, cr, points[1]);
VectorSubtract(r_refdef.vieworg, e->oldorigin, v);
CrossProduct(v, dir, cr);
VectorNormalize(cr);
VectorMA(e->oldorigin, scale/2, cr, points[2]);
VectorMA(e->oldorigin, -scale/2, cr, points[3]);
memset(&mesh, 0, sizeof(mesh));
mesh.vbofirstelement = 0;
mesh.vbofirstvert = 0;
mesh.xyz_array = points;
mesh.indexes = indexarray;
mesh.numindexes = sizeof(indexarray)/sizeof(indexarray[0]);
mesh.colors4f_array = NULL;
mesh.lmst_array = NULL;
mesh.normals_array = NULL;
mesh.numvertexes = 4;
mesh.st_array = texcoords;
BE_DrawMesh_Single(e->forcedshader, &mesh, NULL, NULL, 0);
}
//q3 railgun beam
void R_DrawRailCore(entity_t *e)
{
vec3_t v;
vec3_t dir, cr;
float scale = e->scale;
float length;
mesh_t mesh;
vecV_t points[4];
vec2_t texcoords[4] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}};
static index_t indexarray[6] = {0, 1, 2, 0, 2, 3};
vec4_t colors[4];
if (!e->forcedshader)
return;
if (!scale)
scale = 10;
VectorSubtract(e->origin, e->oldorigin, dir);
length = Length(dir);
//this seems to be about right.
texcoords[2][0] = length/128;
texcoords[3][0] = length/128;
VectorSubtract(r_refdef.vieworg, e->origin, v);
CrossProduct(v, dir, cr);
VectorNormalize(cr);
VectorMA(e->origin, -scale/2, cr, points[0]);
VectorMA(e->origin, scale/2, cr, points[1]);
VectorSubtract(r_refdef.vieworg, e->oldorigin, v);
CrossProduct(v, dir, cr);
VectorNormalize(cr);
VectorMA(e->oldorigin, scale/2, cr, points[2]);
VectorMA(e->oldorigin, -scale/2, cr, points[3]);
Vector4Copy(e->shaderRGBAf, colors[0]);
Vector4Copy(e->shaderRGBAf, colors[1]);
Vector4Copy(e->shaderRGBAf, colors[2]);
Vector4Copy(e->shaderRGBAf, colors[3]);
memset(&mesh, 0, sizeof(mesh));
mesh.vbofirstelement = 0;
mesh.vbofirstvert = 0;
mesh.xyz_array = points;
mesh.indexes = indexarray;
mesh.numindexes = sizeof(indexarray)/sizeof(indexarray[0]);
mesh.colors4f_array = (vec4_t*)colors;
mesh.lmst_array = NULL;
mesh.normals_array = NULL;
mesh.numvertexes = 4;
mesh.st_array = texcoords;
BE_DrawMesh_Single(e->forcedshader, &mesh, NULL, NULL, 0);
}
#endif
/*quick test: map bunk1 ware1 */
void R_DrawBeam(entity_t *e)
{
float r, g, b;
vec3_t dir, v, cr;
vecV_t points[4];
float length, scale;
static byte_vec4_t colours[4];
static vec2_t texcoords[4] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}};
static index_t indexarray[6] = {0, 1, 2, 0, 2, 3};
mesh_t mesh;
shader_t *beamshader;
beamshader = R_RegisterShader("q2beam",
"{\n"
"{\n"
"map $whiteimage\n"
"rgbgen vertex\n"
"alphagen vertex\n"
"blendfunc blend\n"
"}\n"
"}\n"
);
VectorSubtract(e->origin, e->oldorigin, dir);
length = Length(dir);
scale = e->scale;
if (!scale)
scale = 1;
scale *= e->framestate.g[FS_REG].frame[0];
if (!scale)
scale = 6;
scale/= 2;
VectorSubtract(r_refdef.vieworg, e->origin, v);
CrossProduct(v, dir, cr);
VectorNormalize(cr);
VectorMA(e->origin, scale, cr, points[0]);
VectorMA(e->origin, -scale, cr, points[1]);
VectorSubtract(r_refdef.vieworg, e->oldorigin, v);
CrossProduct(v, dir, cr);
VectorNormalize(cr);
VectorMA(e->oldorigin, -scale, cr, points[2]);
VectorMA(e->oldorigin, scale, cr, points[3]);
r = ( d_8to24rgbtable[e->skinnum & 0xFF] ) & 0xFF;
g = ( d_8to24rgbtable[e->skinnum & 0xFF] >> 8 ) & 0xFF;
b = ( d_8to24rgbtable[e->skinnum & 0xFF] >> 16 ) & 0xFF;
r *= e->shaderRGBAf[0];
g *= e->shaderRGBAf[1];
b *= e->shaderRGBAf[2];
colours[0][0] = r;
colours[0][1] = g;
colours[0][2] = b;
colours[0][3] = 255*0.666;
*(int*)colours[1] = *(int*)colours[0];
*(int*)colours[2] = *(int*)colours[0];
*(int*)colours[3] = *(int*)colours[0];
memset(&mesh, 0, sizeof(mesh));
mesh.vbofirstelement = 0;
mesh.vbofirstvert = 0;
mesh.xyz_array = points;
mesh.indexes = indexarray;
mesh.numindexes = sizeof(indexarray)/sizeof(indexarray[0]);
mesh.colors4b_array = colours;
mesh.lmst_array = NULL;
mesh.normals_array = NULL;
mesh.numvertexes = sizeof(points)/sizeof(points[0]);
mesh.st_array = texcoords;
BE_DrawMesh_Single(beamshader, &mesh, NULL, &beamshader->defaulttextures, 0);
}
/*
=============
R_ShouldDraw
Ents are added to the list regardless.
This is where they're filtered (based on which view is currently being drawn).
=============
*/
qboolean R_ShouldDraw(entity_t *e)
{
if (!r_refdef.externalview && (e->externalmodelview & (1<<r_refdef.currentplayernum)))
return false;
if (!Cam_DrawPlayer(r_refdef.currentplayernum, e->keynum-1))
return false;
return true;
}
/*
=============
R_DrawEntitiesOnList
=============
*/
void GLR_DrawEntitiesOnList (void)
{
int i;
if (!r_drawentities.value)
return;
// draw sprites seperately, because of alpha blending
for (i=0 ; i<cl_numvisedicts ; i++)
{
currententity = &cl_visedicts[i];
if (!R_ShouldDraw(currententity))
continue;
switch (currententity->rtype)
{
case RT_SPRITE:
RQ_AddDistReorder(GLR_DrawSprite, currententity, NULL, currententity->origin);
// R_DrawSpriteModel(currententity);
continue;
#ifdef Q3CLIENT
case RT_BEAM:
case RT_RAIL_RINGS:
case RT_LIGHTNING:
R_DrawLightning(currententity);
continue;
case RT_RAIL_CORE:
R_DrawRailCore(currententity);
continue;
#endif
case RT_MODEL: //regular model
break;
case RT_PORTALSURFACE:
continue; //this doesn't do anything anyway, does it?
default:
case RT_POLY: //these are a little painful, we need to do them some time... just not yet.
continue;
}
if (currententity->flags & Q2RF_BEAM)
{
R_DrawBeam(currententity);
continue;
}
if (!currententity->model)
continue;
if (cl.lerpents && (cls.allow_anyparticles || currententity->visframe)) //allowed or static
{
if (gl_part_flame.value)
{
if (currententity->model->engineflags & MDLF_ENGULPHS)
continue;
}
}
if (currententity->model->engineflags & MDLF_NOTREPLACEMENTS)
{
if (currententity->model->fromgame != fg_quake || currententity->model->type != mod_alias)
if (!ruleset_allow_sensative_texture_replacements.value)
continue;
}
switch (currententity->model->type)
{
case mod_alias:
break;
#ifdef HALFLIFEMODELS
case mod_halflife:
R_DrawHLModel (currententity);
break;
#endif
case mod_brush:
break;
case mod_sprite:
RQ_AddDistReorder(GLR_DrawSprite, currententity, NULL, currententity->origin);
break;
#ifdef TERRAIN
case mod_heightmap:
GL_DrawHeightmapModel(currententity);
break;
#endif
default:
break;
}
}
}
/*
=============
R_SetupGL
@ -1076,9 +608,6 @@ void R_RenderScene (void)
S_ExtraUpdate (); // don't let sound get messed up if going slow
TRACE(("dbg: calling GLR_DrawEntitiesOnList\n"));
GLR_DrawEntitiesOnList ();
// R_DrawDecals();
TRACE(("dbg: calling R_RenderDlights\n"));

View File

@ -67,10 +67,6 @@ qbyte FloatToByte( float x )
cvar_t r_detailtextures;
#define MAX_SHADERS 2048 //fixme: this takes a lot of bss in the r_shaders list
#define MAX_TOKEN_CHARS 1024
char *COM_ParseExt (char **data_p, qboolean nl)
@ -1209,6 +1205,7 @@ struct sbuiltin_s
"#endif\n"
"varying vec2 tc;\n"
"varying vec3 light;\n"
"uniform vec4 e_colour;\n"
"void main (void)\n"
"{\n"
@ -1223,6 +1220,7 @@ struct sbuiltin_s
"#ifdef FULLBRIGHT\n"
" gl_FragColor += texture2D(s_t3, tc);\n"
"#endif\n"
" gl_FragColor *= e_colour;\n"
"}\n"
"#endif\n"
},
@ -3811,33 +3809,18 @@ void Shader_DefaultSkin(char *shortname, shader_t *s, const void *args)
}
void Shader_DefaultSkinShell(char *shortname, shader_t *s, const void *args)
{
shaderpass_t *pass;
pass = &s->passes[0];
pass->shaderbits |= SBITS_MISC_DEPTHWRITE;
pass->anim_frames[0] = R_LoadHiResTexture(shortname, NULL, 0);
if (!TEXVALID(pass->anim_frames[0]))
pass->anim_frames[0] = missing_texture;
pass->rgbgen = RGB_GEN_ENTITY;
pass->alphagen = ALPHA_GEN_ENTITY;
pass->numtcmods = 0;
pass->tcgen = TC_GEN_BASE;
pass->shaderbits |= SBITS_SRCBLEND_SRC_ALPHA;
pass->shaderbits |= SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA;
pass->numMergedPasses = 1;
Shader_SetBlendmode(pass);
if (!TEXVALID(pass->anim_frames[0]))
{
Con_DPrintf (CON_WARNING "Shader %s has a stage with no image: %s.\n", s->name, shortname );
pass->anim_frames[0] = missing_texture;
}
s->numpasses = 1;
s->numdeforms = 0;
s->flags = SHADER_DEPTHWRITE|SHADER_CULL_FRONT;
s->features = MF_STCOORDS|MF_NORMALS;
s->sort = SHADER_SORT_OPAQUE;
s->uses = 1;
Shader_DefaultScript(shortname, s,
"{\n"
"sort blend\n"
"deformvertexes normal 1 1\n"
"{\n"
"map $diffuse\n"
"rgbgen entity\n"
"alphagen entity\n"
"blendfunc blend\n"
"}\n"
"}\n"
);
}
void Shader_Default2D(char *shortname, shader_t *s, const void *genargs)
{

View File

@ -277,10 +277,6 @@ void GL_SelectTexture (int tmunum);
void GL_SetShaderState2D(qboolean is2d);
void GL_ForceDepthWritable(void);
void R_DrawRailCore(entity_t *e);
void R_DrawLightning(entity_t *e);
void R_DrawBeam( entity_t *e );
#endif
//

View File

@ -392,6 +392,7 @@ struct shader_s
bucket_t bucket;
};
#define MAX_SHADERS 2048 //fixme: this takes a lot of bss in the r_shaders list
extern shader_t *r_shaders;
extern int be_maxpasses;
@ -431,6 +432,8 @@ mfog_t *CM_FogForOrigin(vec3_t org);
#define BEF_FORCETRANSPARENT 8 //texenv replace -> modulate
#define BEF_FORCENODEPTH 16 //disables any and all depth.
#define BEF_PUSHDEPTH 32 //additional polygon offset
#define BEF_NODLIGHT 64 //don't use a dlight pass
#define BEF_NOSHADOWS 128 //don't appear in shadows
#ifdef GLQUAKE
void GLBE_Init(void);
@ -449,8 +452,8 @@ void GLBE_SelectEntity(entity_t *ent);
#ifdef D3DQUAKE
void D3DBE_Init(void);
void D3DBE_SelectMode(backendmode_t mode);
void D3DBE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **mesh, vbo_t *vbo, texnums_t *texnums);
void D3DBE_DrawMesh_Single(shader_t *shader, mesh_t *meshchain, vbo_t *vbo, texnums_t *texnums);
void D3DBE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **mesh, vbo_t *vbo, texnums_t *texnums, unsigned int beflags);
void D3DBE_DrawMesh_Single(shader_t *shader, mesh_t *meshchain, vbo_t *vbo, texnums_t *texnums, unsigned int beflags);
void D3DBE_SubmitBatch(batch_t *batch);
batch_t *D3DBE_GetTempBatch(void);
void D3DBE_GenBrushModelVBO(model_t *mod);

View File

@ -747,6 +747,8 @@ qboolean SVQ2_InitGameProgs(void)
return false;
}
if (!deathmatch.value && !coop.value)
maxclients.value = 1;
if (maxclients.value > MAX_CLIENTS)
Cvar_SetValue(&maxclients, MAX_CLIENTS);

View File

@ -421,13 +421,13 @@ static void SVQ3_Trace(q3trace_t *result, vec3_t start, vec3_t mins, vec3_t maxs
{
if (start[i] < end[i])
{
mmins[i] = start[i]+mins[i];
mmaxs[i] = end[i]+maxs[i];
mmins[i] = start[i]+mins[i]-1;
mmaxs[i] = end[i]+maxs[i]+1;
}
else
{
mmins[i] = end[i]+mins[i];
mmaxs[i] = start[i]+maxs[i];
mmins[i] = end[i]+mins[i]-1;
mmaxs[i] = start[i]+maxs[i]+1;
}
}
@ -454,12 +454,12 @@ static void SVQ3_Trace(q3trace_t *result, vec3_t start, vec3_t mins, vec3_t maxs
if (entnum != ENTITYNUM_WORLD)
{
// if (contactlist[i] == entnum)
// continue; // don't clip against the pass entity
// if (es->r.ownerNum == entnum)
// continue; // don't clip against own missiles
// if (es->r.ownerNum == ourowner)
// continue; // don't clip against other missiles from our owner
if (contactlist[i] == entnum)
continue;
if (es->r.ownerNum == entnum)
continue;
if (es->r.ownerNum == ourowner)
continue;
}
if (es->r.bmodel)
@ -528,12 +528,12 @@ static int SVQ3_PointContents(vec3_t pos, int entnum)
if (entnum != ENTITYNUM_WORLD)
{
// if (contactlist[i] == entnum)
// continue; // don't clip against the pass entity
// if (es->r.ownerNum == entnum)
// continue; // don't clip against own missiles
// if (es->r.ownerNum == ourowner)
// continue; // don't clip against other missiles from our owner
if (contactlist[i] == entnum)
continue; // don't clip against the pass entity
if (es->r.ownerNum == entnum)
continue; // don't clip against own missiles
if (es->r.ownerNum == ourowner)
continue; // don't clip against other missiles from our owner
}
if (es->r.bmodel)