// player model is only shown with chase_active on
if (e->state_current.number == cl.viewentity)
e->render.flags |= RENDER_EXTERIORMODEL;
- // transparent stuff can't be lit during the opaque stage
- if (e->render.effects & (EF_ADDITIVE | EF_NODEPTHTEST) || e->render.alpha < 1)
- e->render.flags |= RENDER_TRANSPARENT;
- // double sided rendering mode causes backfaces to be visible
- // (mostly useful on transparent stuff)
- if (e->render.effects & EF_DOUBLESIDED)
- e->render.flags |= RENDER_NOCULLFACE;
// either fullbright or lit
if (!(e->render.effects & EF_FULLBRIGHT) && !r_fullbright.integer)
e->render.flags |= RENDER_LIGHT;
// hide player shadow during intermission or nehahra movie
- if (!(e->render.effects & EF_NOSHADOW)
- && !(e->render.flags & (RENDER_VIEWMODEL | RENDER_TRANSPARENT))
+ if (!(e->render.effects & (EF_NOSHADOW | EF_ADDITIVE | EF_NODEPTHTEST))
+ && (e->render.alpha >= 1)
+ && !(e->render.flags & RENDER_VIEWMODEL)
&& (!(e->render.flags & RENDER_EXTERIORMODEL) || (!cl.intermission && cls.protocol != PROTOCOL_NEHAHRAMOVIE && !cl_noplayershadow.integer)))
e->render.flags |= RENDER_SHADOW;
}
// need to re-fetch the model pointer
e->render.model = cl.model_precache[e->state_baseline.modelindex];
CL_UpdateRenderEntity(&e->render);
- // transparent stuff can't be lit during the opaque stage
- if (e->render.effects & (EF_ADDITIVE | EF_NODEPTHTEST) || e->render.alpha < 1)
- e->render.flags |= RENDER_TRANSPARENT;
// either fullbright or lit
if (!(e->render.effects & EF_FULLBRIGHT) && !r_fullbright.integer)
e->render.flags |= RENDER_LIGHT;
// hide player shadow during intermission or nehahra movie
- if (!(e->render.effects & EF_NOSHADOW) && !(e->render.flags & RENDER_TRANSPARENT))
+ if (!(e->render.effects & (EF_NOSHADOW | EF_ADDITIVE | EF_NODEPTHTEST)) && (e->render.alpha >= 1))
e->render.flags |= RENDER_SHADOW;
VectorSet(e->render.colormod, 1, 1, 1);
R_LerpAnimation(&e->render);
Matrix4x4_CreateFromQuakeEntity(&staticent->render.matrix, ent->fields.client->origin[0], ent->fields.client->origin[1], ent->fields.client->origin[2], ent->fields.client->angles[0], ent->fields.client->angles[1], ent->fields.client->angles[2], staticent->render.scale);
CL_UpdateRenderEntity(&staticent->render);
- // transparent stuff can't be lit during the opaque stage
- if (staticent->render.effects & (EF_ADDITIVE | EF_NODEPTHTEST) || staticent->render.alpha < 1)
- staticent->render.flags |= RENDER_TRANSPARENT;
- // double sided rendering mode causes backfaces to be visible
- // (mostly useful on transparent stuff)
- if (staticent->render.effects & EF_DOUBLESIDED)
- staticent->render.flags |= RENDER_NOCULLFACE;
// either fullbright or lit
if (!(staticent->render.effects & EF_FULLBRIGHT) && !r_fullbright.integer)
staticent->render.flags |= RENDER_LIGHT;
// turn off shadows from transparent objects
- if (!(staticent->render.effects & EF_NOSHADOW)
- && !(staticent->render.flags & RENDER_TRANSPARENT))
+ if (!(staticent->render.effects & (EF_NOSHADOW | EF_ADDITIVE | EF_NODEPTHTEST)) && (staticent->render.alpha >= 1))
staticent->render.flags |= RENDER_SHADOW;
}
else
}
for (i = 0;i < numtriangles;i++, element3i += 3)
{
- if (segmentmaxs[0] >= min(vertex3f[element3i[0]*3+0], min(vertex3f[element3i[1]*3+0], vertex3f[element3i[2]*3+0]))
- && segmentmins[0] <= max(vertex3f[element3i[0]*3+0], max(vertex3f[element3i[1]*3+0], vertex3f[element3i[2]*3+0]))
- && segmentmaxs[1] >= min(vertex3f[element3i[0]*3+1], min(vertex3f[element3i[1]*3+1], vertex3f[element3i[2]*3+1]))
- && segmentmins[1] <= max(vertex3f[element3i[0]*3+1], max(vertex3f[element3i[1]*3+1], vertex3f[element3i[2]*3+1]))
- && segmentmaxs[2] >= min(vertex3f[element3i[0]*3+2], min(vertex3f[element3i[1]*3+2], vertex3f[element3i[2]*3+2]))
- && segmentmins[2] <= max(vertex3f[element3i[0]*3+2], max(vertex3f[element3i[1]*3+2], vertex3f[element3i[2]*3+2])))
+ if (TriangleOverlapsBox(vertex3f + element3i[0]*3, vertex3f + element3i[1]*3, vertex3f + element3i[2]*3, segmentmins, segmentmaxs))
{
VectorCopy(vertex3f + element3i[0] * 3, polyf_points[0].v);
VectorCopy(vertex3f + element3i[1] * 3, polyf_points[1].v);
}
for (i = 0;i < numtriangles;i++, element3i += 3)
{
- if (segmentmaxs[0] >= min(vertex3f[element3i[0]*3+0], min(vertex3f[element3i[1]*3+0], vertex3f[element3i[2]*3+0]))
- && segmentmins[0] <= max(vertex3f[element3i[0]*3+0], max(vertex3f[element3i[1]*3+0], vertex3f[element3i[2]*3+0]))
- && segmentmaxs[1] >= min(vertex3f[element3i[0]*3+1], min(vertex3f[element3i[1]*3+1], vertex3f[element3i[2]*3+1]))
- && segmentmins[1] <= max(vertex3f[element3i[0]*3+1], max(vertex3f[element3i[1]*3+1], vertex3f[element3i[2]*3+1]))
- && segmentmaxs[2] >= min(vertex3f[element3i[0]*3+2], min(vertex3f[element3i[1]*3+2], vertex3f[element3i[2]*3+2]))
- && segmentmins[2] <= max(vertex3f[element3i[0]*3+2], max(vertex3f[element3i[1]*3+2], vertex3f[element3i[2]*3+2])))
+ if (TriangleOverlapsBox(vertex3f + element3i[0]*3, vertex3 + [element3i[1]*3, vertex3f + element3i[2]*3, segmentmins, segmentmaxs))
{
VectorCopy(vertex3f + element3i[0] * 3, polyf_points[0].v);
VectorCopy(vertex3f + element3i[1] * 3, polyf_points[1].v);
if(i & RF_ADDITIVE) e->render.effects |= EF_ADDITIVE;
}
- // transparent stuff can't be lit during the opaque stage
- if (e->render.effects & (EF_ADDITIVE | EF_NODEPTHTEST) || e->render.alpha < 1)
- e->render.flags |= RENDER_TRANSPARENT;
- // double sided rendering mode causes backfaces to be visible
- // (mostly useful on transparent stuff)
- if (e->render.effects & EF_DOUBLESIDED)
- e->render.flags |= RENDER_NOCULLFACE;
// either fullbright or lit
if (!(e->render.effects & EF_FULLBRIGHT) && !r_fullbright.integer)
e->render.flags |= RENDER_LIGHT;
// hide player shadow during intermission or nehahra movie
- if (!(e->render.effects & EF_NOSHADOW)
- && !(e->render.flags & (RENDER_VIEWMODEL | RENDER_TRANSPARENT))
+ if (!(e->render.effects & (EF_NOSHADOW | EF_ADDITIVE | EF_NODEPTHTEST))
+ && (e->render.alpha >= 1)
+ && !(e->render.flags & RENDER_VIEWMODEL)
&& (!(e->render.flags & RENDER_EXTERIORMODEL) || (!cl.intermission && cls.protocol != PROTOCOL_NEHAHRAMOVIE && !cl_noplayershadow.integer)))
e->render.flags |= RENDER_SHADOW;
GL_DepthMask(true);
}
GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
- GL_CullFace((ent->flags & RENDER_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
+ GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
R_Mesh_VertexPointer(nomodelvertex3f);
if (r_refdef.fogenabled)
{
t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_NOSHADOW;
else if (t->currentalpha < 1)
t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_NOSHADOW;
- if (ent->flags & RENDER_NOCULLFACE)
- t->currentmaterialflags |= MATERIALFLAG_NOSHADOW;
+ if (ent->effects & EF_DOUBLESIDED)
+ t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
if (ent->effects & EF_NODEPTHTEST)
t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_NOSHADOW;
if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
{
GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
- GL_CullFace(((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE)) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
+ GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
if (rsurface_mode != RSURFMODE_SHOWSURFACES)
{
rsurface_mode = RSURFMODE_SHOWSURFACES;
R_Mesh_Matrix(&rsurface_entity->matrix);
}
GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
- GL_CullFace(((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE)) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
+ GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
GL_DepthMask(true);
// LordHavoc: HalfLife maps have freaky skypolys so don't use
// skymasking on them, and Quake3 never did sky masking (unlike
else if (rsurface_texture->currentnumlayers)
{
GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
- GL_CullFace(((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE)) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
+ GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
#define VectorReflect(a,r,b,c) do{double d;d = DotProduct((a), (b)) * -(1.0 + (r));VectorMA((a), (d), (b), (c));}while(0)
#define BoxesOverlap(a,b,c,d) ((a)[0] <= (d)[0] && (b)[0] >= (c)[0] && (a)[1] <= (d)[1] && (b)[1] >= (c)[1] && (a)[2] <= (d)[2] && (b)[2] >= (c)[2])
#define BoxInsideBox(a,b,c,d) ((a)[0] >= (c)[0] && (b)[0] <= (d)[0] && (a)[1] >= (c)[1] && (b)[1] <= (d)[1] && (a)[2] >= (c)[2] && (b)[2] <= (d)[2])
+#define TriangleOverlapsBox(a,b,c,d,e) (min((a)[0], min((b)[0], (c)[0])) < (e)[0] && max((a)[0], max((b)[0], (c)[0])) > (d)[0] && min((a)[1], min((b)[1], (c)[1])) < (e)[1] && max((a)[1], max((b)[1], (c)[1])) > (d)[1] && min((a)[2], min((b)[2], (c)[2])) < (e)[2] && max((a)[2], max((b)[2], (c)[2])) > (d)[2])
#define TriangleNormal(a,b,c,n) ( \
(n)[0] = ((a)[1] - (b)[1]) * ((c)[2] - (b)[2]) - ((a)[2] - (b)[2]) * ((c)[1] - (b)[1]), \
// identify if this is a blended terrain shader or similar
if (shader->numlayers)
{
+ shader->backgroundlayer = NULL;
shader->primarylayer = shader->layers + 0;
if ((shader->layers[0].blendfunc[0] == GL_ONE && shader->layers[0].blendfunc[1] == GL_ZERO && !shader->layers[0].alphatest)
&& ((shader->layers[1].blendfunc[0] == GL_SRC_ALPHA && shader->layers[1].blendfunc[1] == GL_ONE_MINUS_SRC_ALPHA && !shader->layers[0].alphatest)
}
// now see if the lightmap came first, and if so choose the second texture instead
if (!strcasecmp(shader->primarylayer->texturename[0], "$lightmap"))
+ {
+ shader->backgroundlayer = NULL;
shader->primarylayer = shader->layers + 1;
+ }
}
}
Mem_Free(f);
out->basematerialflags |= MATERIALFLAG_WALL;
if (shader->layers[0].alphatest)
out->basematerialflags |= MATERIALFLAG_ALPHATEST | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_NOSHADOW;
- if (shader->textureflags & (Q3TEXTUREFLAG_TWOSIDED | Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
+ if (shader->textureflags & Q3TEXTUREFLAG_TWOSIDED)
+ out->basematerialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
+ if (shader->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
out->basematerialflags |= MATERIALFLAG_NOSHADOW;
out->customblendfunc[0] = GL_ONE;
out->customblendfunc[1] = GL_ZERO;
#define MATERIALFLAG_NOSHADOW 16384
// render using vertex alpha (q3bsp) as texture blend parameter between foreground (normal) skinframe and background skinframe
#define MATERIALFLAG_VERTEXTEXTUREBLEND 32768
+// disables GL_CULL_FACE on this texture (making it double sided)
+#define MATERIALFLAG_NOCULLFACE 65536
typedef struct medge_s
{
int j;
const int *elements;
const float *vertex3f;
- float v[9], trimins[3], trimaxs[3];
+ float v[9];
vertex3f = info->model->surfmesh.data_vertex3f;
elements = (info->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
for (j = 0;j < surface->num_triangles;j++, elements += 3)
VectorCopy(vertex3f + elements[0] * 3, v + 0);
VectorCopy(vertex3f + elements[1] * 3, v + 3);
VectorCopy(vertex3f + elements[2] * 3, v + 6);
- if (PointInfrontOfTriangle(info->eye, v + 0, v + 3, v + 6))
+ if (PointInfrontOfTriangle(info->eye, v + 0, v + 3, v + 6) && TriangleOverlapsBox(v, v + 3, v + 6, info->boxmins, info->boxmaxs) && Portal_PortalThroughPortalPlanes(&portalplanes[firstclipplane], numclipplanes, v, 3, &portaltemppoints2[0][0], 256) > 0)
{
- trimins[0] = min(v[0], min(v[3], v[6]));
- trimaxs[0] = max(v[0], max(v[3], v[6]));
- trimins[1] = min(v[1], min(v[4], v[7]));
- trimaxs[1] = max(v[1], max(v[4], v[7]));
- trimins[2] = min(v[2], min(v[5], v[8]));
- trimaxs[2] = max(v[2], max(v[5], v[8]));
- if (BoxesOverlap(trimins, trimaxs, info->boxmins, info->boxmaxs) && Portal_PortalThroughPortalPlanes(&portalplanes[firstclipplane], numclipplanes, v, 3, &portaltemppoints2[0][0], 256) > 0)
- {
- SETPVSBIT(info->surfacepvs, surfaceindex);
- info->surfacelist[info->numsurfaces++] = surfaceindex;
- break;
- }
+ SETPVSBIT(info->surfacepvs, surfaceindex);
+ info->surfacelist[info->numsurfaces++] = surfaceindex;
+ break;
}
}
}
#define RENDER_COLORMAPPED 32
#define RENDER_SHADOW 65536 // cast shadow
#define RENDER_LIGHT 131072 // receive light
-#define RENDER_TRANSPARENT 262144 // can't light during opaque stage
-#define RENDER_NOCULLFACE 524288 // render as double sided (disable GL_CULL_FACE)
// this is 88 bytes
typedef struct entity_state_s
if (!BoxesOverlap(lightmins, lightmaxs, surfacemins, surfacemaxs))
return;
tend = firsttriangle + numtris;
- if (surfacemins[0] >= lightmins[0] && surfacemaxs[0] <= lightmaxs[0]
- && surfacemins[1] >= lightmins[1] && surfacemaxs[1] <= lightmaxs[1]
- && surfacemins[2] >= lightmins[2] && surfacemaxs[2] <= lightmaxs[2])
+ if (BoxInsideBox(surfacemins, surfacemaxs, lightmins, lightmaxs))
{
// surface box entirely inside light box, no box cull
if (projectdirection)
v[2] = invertex3f + e[2] * 3;
TriangleNormal(v[0], v[1], v[2], normal);
if (r_shadow_frontsidecasting.integer == (DotProduct(normal, projectdirection) < 0)
- && lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0]))
- && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0]))
- && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1]))
- && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1]))
- && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2]))
- && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2])))
+ && TriangleOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
shadowmarklist[numshadowmark++] = t;
}
}
v[1] = invertex3f + e[1] * 3;
v[2] = invertex3f + e[2] * 3;
if (r_shadow_frontsidecasting.integer == PointInfrontOfTriangle(projectorigin, v[0], v[1], v[2])
- && lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0]))
- && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0]))
- && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1]))
- && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1]))
- && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2]))
- && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2])))
+ && TriangleOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
shadowmarklist[numshadowmark++] = t;
}
}
if ((r_shadow_rtlight->ambientscale + r_shadow_rtlight->diffusescale) * VectorLength2(lightcolorbase) + (r_shadow_rtlight->specularscale * rsurface_texture->specularscale) * VectorLength2(lightcolorbase) < (1.0f / 1048576.0f))
return;
GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
- GL_CullFace(((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE)) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
+ GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
if (rsurface_texture->colormapping)
{
qboolean dopants = rsurface_texture->currentskinframe->pants != NULL && VectorLength2(rsurface_entity->colormap_pantscolor) >= (1.0f / 1048576.0f);
{
int i;
model_t *model = ent->model;
- vec3_t left, up, org, color, diffusecolor, diffusenormal, mforward, mleft, mup;
+ vec3_t left, up, org, mforward, mleft, mup;
float scale;
// nudge it toward the view to make sure it isn't in a wall
R_Mesh_Matrix(&identitymatrix);
- if (!(ent->flags & RENDER_LIGHT))
- color[0] = color[1] = color[2] = 1;
- else
- {
- vec3_t org;
- Matrix4x4_OriginFromMatrix(&ent->matrix, org);
- R_CompleteLightPoint(color, diffusecolor, diffusenormal, org, true);
- VectorMA(color, 0.5f, diffusecolor, color);
- }
- color[0] *= ent->colormod[0];
- color[1] *= ent->colormod[1];
- color[2] *= ent->colormod[2];
-
// LordHavoc: interpolated sprite rendering
for (i = 0;i < 4;i++)
{
texture_t *texture = &frame->texture;
R_UpdateTextureInfo(ent, texture);
// FIXME: negate left and right in loader
- R_DrawSprite(texture->currentlayers[0].blendfunc1, texture->currentlayers[0].blendfunc2, frame->texture.currentskinframe->base, frame->texture.currentskinframe->fog, (ent->effects & EF_NODEPTHTEST), org, left, up, frame->left, frame->right, frame->down, frame->up, color[0], color[1], color[2], ent->alpha * ent->frameblend[i].lerp);
+ R_DrawSprite(texture->currentlayers[0].blendfunc1, texture->currentlayers[0].blendfunc2, frame->texture.currentskinframe->base, frame->texture.currentskinframe->fog, (ent->effects & EF_NODEPTHTEST), org, left, up, frame->left, frame->right, frame->down, frame->up, texture->currentlayers[0].color[0], texture->currentlayers[0].color[1], texture->currentlayers[0].color[2], ent->alpha * ent->frameblend[i].lerp);
}
}
}