#include "quakedef.h"
-#define MAX_DECALS 2048
-
-typedef struct decal_s
-{
- vec3_t org;
- vec3_t direction;
- vec3_t vert[4];
- byte color[4];
- rtexture_t *tex;
- msurface_t *surface;
- byte *lightmapaddress;
- int lightmapstep;
-}
-decal_t;
-
-decal_t *decals;
-int currentdecal; // wraps around in decal array, replacing old ones when a new one is needed
-
cvar_t r_drawdecals = {0, "r_drawdecals", "1"};
-cvar_t r_decals_lighting = {0, "r_decals_lighting", "1"};
-void r_decals_start(void)
+static void r_decals_start(void)
{
- decals = (decal_t *) qmalloc(MAX_DECALS * sizeof(decal_t));
- memset(decals, 0, MAX_DECALS * sizeof(decal_t));
- currentdecal = 0;
}
-void r_decals_shutdown(void)
+static void r_decals_shutdown(void)
{
- qfree(decals);
}
-void r_decals_newmap(void)
+static void r_decals_newmap(void)
{
- memset(decals, 0, MAX_DECALS * sizeof(decal_t));
- currentdecal = 0;
}
void R_Decals_Init(void)
{
Cvar_RegisterVariable (&r_drawdecals);
- Cvar_RegisterVariable (&r_decals_lighting);
R_RegisterModule("R_Decals", r_decals_start, r_decals_shutdown, r_decals_newmap);
}
-// these are static globals only to avoid putting unnecessary things on the stack
-static vec3_t decalorg;
-static float decalbestdist;
-static msurface_t *decalbestsurf;
-static int decalbestlightmapofs;
-void R_RecursiveDecalSurface (mnode_t *node)
+/*
+static int decalindexarray[2*3] =
+{
+ 0, 1, 2,
+ 0, 2, 3,
+};
+*/
+
+void R_DrawDecals (void)
{
- // these are static because only one occurance of them need exist at once, so avoid putting them on the stack
- static float ndist, dist;
- static msurface_t *surf, *endsurf;
- static vec3_t impact;
- static int ds, dt;
-
-loc0:
- if (node->contents < 0)
+ renderdecal_t *r;
+ int i, j, lightmapstep, ds, dt;
+ float fscale, fr, fg, fb, dist, f, fog, ifog, fogvec[3], impact[3], v[3], org[3], dir[3], right[3], up[3], tvxyz[4][4], tvst[4][2];
+ particletexture_t *tex, *texfog;
+ byte *lightmap;
+ msurface_t *surf;
+ rdlight_t *rd;
+ rmeshinfo_t m;
+
+ if (!r_drawdecals.integer)
return;
- ndist = PlaneDiff(decalorg, node->plane);
-
- if (ndist > 16)
- {
- node = node->children[0];
- goto loc0;
- }
- if (ndist < -16)
+ fog = 0;
+ ifog = 1;
+
+ Mod_CheckLoaded(cl.worldmodel);
+
+ // LordHavoc: this meshinfo must match up with R_Mesh_DrawDecal
+ // LordHavoc: the commented out lines are hardwired behavior in R_Mesh_DrawDecal
+ memset(&m, 0, sizeof(m));
+ m.blendfunc1 = GL_SRC_ALPHA;
+ m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
+ //m.numtriangles = 2;
+ //m.numverts = 4;
+ //m.index = decalindexarray;
+ m.vertex = &tvxyz[0][0];
+ //m.vertexstep = sizeof(float[4]);
+ m.tex[0] = R_GetTexture(particlefonttexture);
+ m.texcoords[0] = &tvst[0][0];
+ //m.texcoordstep[0] = sizeof(float[2]);
+
+ for (i = 0, r = r_refdef.decals;i < r_refdef.numdecals;i++, r++)
{
- node = node->children[1];
- goto loc0;
- }
+ if (r->ent)
+ {
+ if (r->ent->visframe != r_framecount)
+ continue;
-// mark the polygons
- surf = cl.worldmodel->surfaces + node->firstsurface;
- endsurf = surf + node->numsurfaces;
- for (;surf < endsurf;surf++)
- {
- if (surf->flags & SURF_DRAWTILED)
- continue; // no lightmaps
+ Mod_CheckLoaded(r->ent->model);
+ if (r->ent->model->type != mod_brush)
+ continue;
- dist = PlaneDiff(decalorg, surf->plane);
- if (surf->flags & SURF_PLANEBACK)
- dist = -dist;
- if (dist < 0)
- continue;
- if (dist >= decalbestdist)
- continue;
+ surf = r->ent->model->surfaces + r->surface;
- impact[0] = decalorg[0] - surf->plane->normal[0] * dist;
- impact[1] = decalorg[1] - surf->plane->normal[1] * dist;
- impact[2] = decalorg[2] - surf->plane->normal[2] * dist;
+ // skip decals on surfaces that aren't visible in this frame
+ if (surf->visframe != r_framecount)
+ continue;
- ds = (int) (DotProduct(impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3]);
- dt = (int) (DotProduct(impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3]);
+ softwaretransformforentity(r->ent);
+ softwaretransform(r->org, org);
+ softwaretransformdirection(r->dir, dir);
- if (ds < surf->texturemins[0] || dt < surf->texturemins[1])
- continue;
-
- ds -= surf->texturemins[0];
- dt -= surf->texturemins[1];
-
- if (ds > surf->extents[0] || dt > surf->extents[1])
+ // do not render if the view origin is behind the decal
+ VectorSubtract(org, r_origin, fogvec);
+ if (DotProduct(dir, fogvec) < 0)
+ continue;
+ }
+ else
+ {
+ surf = cl.worldmodel->surfaces + r->surface;
+
+ // skip decals on surfaces that aren't visible in this frame
+ if (surf->visframe != r_framecount)
+ continue;
+
+ // do not render if the view origin is behind the decal
+ VectorSubtract(r->org, r_origin, fogvec);
+ if (DotProduct(r->dir, fogvec) < 0)
+ continue;
+
+ VectorCopy(r->org, org);
+ VectorCopy(r->dir, dir);
+ }
+
+ dist = -PlaneDiff(r->org, surf->plane);
+ VectorMA(r->org, dist, surf->plane->normal, impact);
+
+ ds = (int) (DotProduct(impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3]) - surf->texturemins[0];
+ dt = (int) (DotProduct(impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3]) - surf->texturemins[1];
+
+ if (ds < 0 || dt < 0 || ds > surf->extents[0] || dt > surf->extents[1])
+ {
+ // this should never happen
continue;
+ }
- decalbestsurf = surf;
- decalbestdist = dist;
- decalbestlightmapofs = (dt >> 4) * ((surf->extents[0] >> 4) + 1) + (ds >> 4);
- }
+ tex = &particletexture[r->tex][0];
+ VectorVectors(dir, right, up);
+ VectorScale(right, r->scale, right);
+ VectorScale(up, r->scale, up);
+ tvxyz[0][0] = org[0] - right[0] - up[0];
+ tvxyz[0][1] = org[1] - right[1] - up[1];
+ tvxyz[0][2] = org[2] - right[2] - up[2];
+ tvxyz[1][0] = org[0] - right[0] + up[0];
+ tvxyz[1][1] = org[1] - right[1] + up[1];
+ tvxyz[1][2] = org[2] - right[2] + up[2];
+ tvxyz[2][0] = org[0] + right[0] + up[0];
+ tvxyz[2][1] = org[1] + right[1] + up[1];
+ tvxyz[2][2] = org[2] + right[2] + up[2];
+ tvxyz[3][0] = org[0] + right[0] - up[0];
+ tvxyz[3][1] = org[1] + right[1] - up[1];
+ tvxyz[3][2] = org[2] + right[2] - up[2];
+ tvst[0][0] = tex->s1;
+ tvst[0][1] = tex->t1;
+ tvst[1][0] = tex->s1;
+ tvst[1][1] = tex->t2;
+ tvst[2][0] = tex->s2;
+ tvst[2][1] = tex->t2;
+ tvst[3][0] = tex->s2;
+ tvst[3][1] = tex->t1;
+
+ // lighting
+ fr = fg = fb = 0.0f;
- if (node->children[0]->contents >= 0)
- {
- if (node->children[1]->contents >= 0)
+ if ((lightmap = surf->samples))
{
- R_RecursiveDecalSurface (node->children[0]);
- node = node->children[1];
- goto loc0;
+ if (surf->styles[0] != 255)
+ {
+ lightmap += ((dt >> 4) * ((surf->extents[0] >> 4) + 1) + (ds >> 4)) * 3;
+ fscale = d_lightstylevalue[surf->styles[0]] * (1.0f / 32768.0f);
+ fr += lightmap[0] * fscale;
+ fg += lightmap[1] * fscale;
+ fb += lightmap[2] * fscale;
+ if (surf->styles[1] != 255)
+ {
+ lightmapstep = (((surf->extents[0] >> 4) + 1) * ((surf->extents[1] >> 4) + 1)) * 3;
+ lightmap += lightmapstep;
+ fscale = d_lightstylevalue[surf->styles[1]] * (1.0f / 32768.0f);
+ fr += lightmap[0] * fscale;
+ fg += lightmap[1] * fscale;
+ fb += lightmap[2] * fscale;
+ if (surf->styles[2] != 255)
+ {
+ lightmap += lightmapstep;
+ fscale = d_lightstylevalue[surf->styles[2]] * (1.0f / 32768.0f);
+ fr += lightmap[0] * fscale;
+ fg += lightmap[1] * fscale;
+ fb += lightmap[2] * fscale;
+ if (surf->styles[3] != 255)
+ {
+ lightmap += lightmapstep;
+ fscale = d_lightstylevalue[surf->styles[3]] * (1.0f / 32768.0f);
+ fr += lightmap[0] * fscale;
+ fg += lightmap[1] * fscale;
+ fb += lightmap[2] * fscale;
+ }
+ }
+ }
+ }
}
- else
+
+ if (surf->dlightframe == r_framecount)
{
- node = node->children[0];
- goto loc0;
+ for (j = 0;j < r_numdlights;j++)
+ {
+ if (surf->dlightbits[j >> 5] & (1 << (j & 31)))
+ {
+ rd = &r_dlight[j];
+ VectorSubtract(r->org, rd->origin, v);
+ dist = DotProduct(v, v) + LIGHTOFFSET;
+ if (dist < rd->cullradius2)
+ {
+ f = (1.0f / dist) - rd->lightsubtract;
+ if (f > 0)
+ {
+ fr += f * rd->light[0];
+ fg += f * rd->light[1];
+ fb += f * rd->light[2];
+ }
+ }
+ }
+ }
}
- }
- else if (node->children[1]->contents >= 0)
- {
- node = node->children[1];
- goto loc0;
+
+ // if the surface is transparent, render as transparent
+ m.transparent = !(surf->flags & SURF_CLIPSOLID);
+ m.cr = r->color[0] * fr;
+ m.cg = r->color[1] * fg;
+ m.cb = r->color[2] * fb;
+ m.ca = r->color[3];
+
+ if (fogenabled)
+ {
+ fog = exp(fogdensity/DotProduct(fogvec,fogvec));
+ texfog = &particletexture[r->tex][1];
+ if (fog >= (1.0f / 64.0f))
+ {
+ if (fog >= (1.0f - (1.0f / 64.0f)))
+ {
+ // fully fogged, just use the fog texture and render as alpha
+ m.cr = fogcolor[0];
+ m.cg = fogcolor[1];
+ m.cb = fogcolor[2];
+ m.ca = r->color[3];
+ tvst[0][0] = texfog->s1;
+ tvst[0][1] = texfog->t1;
+ tvst[1][0] = texfog->s1;
+ tvst[1][1] = texfog->t2;
+ tvst[2][0] = texfog->s2;
+ tvst[2][1] = texfog->t2;
+ tvst[3][0] = texfog->s2;
+ tvst[3][1] = texfog->t1;
+ R_Mesh_DrawDecal(&m);
+ }
+ else
+ {
+ // partially fogged, darken the first pass
+ ifog = 1 - fog;
+ m.cr *= ifog;
+ m.cg *= ifog;
+ m.cb *= ifog;
+ if (tex->s1 == texfog->s1 && tex->t1 == texfog->t1)
+ {
+ // fog texture is the same as the base, just change the color
+ m.cr += fogcolor[0] * fog;
+ m.cg += fogcolor[1] * fog;
+ m.cb += fogcolor[2] * fog;
+ R_Mesh_DrawDecal(&m);
+ }
+ else
+ {
+ // render the first pass (alpha), then do additive fog
+ R_Mesh_DrawDecal(&m);
+ m.blendfunc2 = GL_ONE;
+ m.cr = fogcolor[0];
+ m.cg = fogcolor[1];
+ m.cb = fogcolor[2];
+ m.ca = r->color[3] * fog;
+ tvst[0][0] = texfog->s1;
+ tvst[0][1] = texfog->t1;
+ tvst[1][0] = texfog->s1;
+ tvst[1][1] = texfog->t2;
+ tvst[2][0] = texfog->s2;
+ tvst[2][1] = texfog->t2;
+ tvst[3][0] = texfog->s2;
+ tvst[3][1] = texfog->t1;
+ R_Mesh_DrawDecal(&m);
+ m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
+ }
+ }
+ }
+ else
+ R_Mesh_DrawDecal(&m);
+ }
+ else
+ R_Mesh_DrawDecal(&m);
}
}
-void R_Decal(vec3_t org, rtexture_t *tex, float scale, int cred, int cgreen, int cblue, int alpha)
+/*
+void R_DrawDecals (void)
{
- vec3_t center, right, up;
- decal_t *decal;
+ renderdecal_t *r;
+ int i, j, lightmapstep, ds, dt;
+ float fscale, fr, fg, fb, dist, f, fog, ifog, impact[3], v[3], org[3], dir[3], right[3], up[3], tv[4][5];
+ particletexture_t *tex;
+ byte *lightmap;
+ msurface_t *surf;
+ rdlight_t *rd;
+ rmeshinfo_t m;
- if (alpha < 1)
+ if (!r_drawdecals.integer)
return;
- // find the best surface to place the decal on
- decalbestsurf = NULL;
- decalbestdist = 16;
- decalbestlightmapofs = 0;
- VectorCopy(org, decalorg);
+ ifog = 1;
- R_RecursiveDecalSurface (cl.worldmodel->nodes);
+ Mod_CheckLoaded(cl.worldmodel);
- // abort if no suitable surface was found
- if (decalbestsurf == NULL)
- return;
+ memset(&m, 0, sizeof(m));
+ m.blendfunc1 = GL_SRC_ALPHA;
+ m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
+ m.numtriangles = 2;
+ m.numverts = 4;
+ m.index = decalindexarray;
+ m.vertex = &tv[0][0];
+ m.vertexstep = sizeof(float[5]);
+ m.tex[0] = R_GetTexture(particlefonttexture);
+ m.texcoords[0] = &tv[0][3];
+ m.texcoordstep[0] = sizeof(float[5]);
- // grab a decal from the array and advance to the next decal to replace, wrapping to replace an old decal if necessary
- decal = decals + currentdecal;
- currentdecal++;
- if (currentdecal >= MAX_DECALS)
- currentdecal = 0;
- decal->tex = tex;
- VectorCopy(decalbestsurf->plane->normal, decal->direction);
- // reverse direction
- if (decalbestsurf->flags & SURF_PLANEBACK)
- VectorNegate(decal->direction, decal->direction);
- VectorNegate(decal->direction, decal->direction);
- // 0.25 to push it off the surface a bit
- decalbestdist -= 0.25f;
- decal->org[0] = center[0] = org[0] + decal->direction[0] * decalbestdist;
- decal->org[1] = center[1] = org[1] + decal->direction[1] * decalbestdist;
- decal->org[2] = center[2] = org[2] + decal->direction[2] * decalbestdist;
- // set up the 4 corners
- scale *= 0.5f;
- VectorVectors(decal->direction, right, up);
- decal->vert[0][0] = center[0] - right[0] * scale - up[0] * scale; // texcoords 0 1
- decal->vert[0][1] = center[1] - right[1] * scale - up[1] * scale;
- decal->vert[0][2] = center[2] - right[2] * scale - up[2] * scale;
- decal->vert[1][0] = center[0] - right[0] * scale + up[0] * scale; // texcoords 0 0
- decal->vert[1][1] = center[1] - right[1] * scale + up[1] * scale;
- decal->vert[1][2] = center[2] - right[2] * scale + up[2] * scale;
- decal->vert[2][0] = center[0] + right[0] * scale + up[0] * scale; // texcoords 1 0
- decal->vert[2][1] = center[1] + right[1] * scale + up[1] * scale;
- decal->vert[2][2] = center[2] + right[2] * scale + up[2] * scale;
- decal->vert[3][0] = center[0] + right[0] * scale - up[0] * scale; // texcoords 1 1
- decal->vert[3][1] = center[1] + right[1] * scale - up[1] * scale;
- decal->vert[3][2] = center[2] + right[2] * scale - up[2] * scale;
- // store the color
- decal->color[0] = (byte) bound(0, cred, 255);
- decal->color[1] = (byte) bound(0, cgreen, 255);
- decal->color[2] = (byte) bound(0, cblue, 255);
- decal->color[3] = (byte) bound(0, alpha, 255);
- // store the surface information for lighting
- decal->surface = decalbestsurf;
- decal->lightmapstep = ((decalbestsurf->extents[0]>>4)+1) * ((decalbestsurf->extents[1]>>4)+1)*3; // LordHavoc: *3 for colored lighting
- if (decalbestsurf->samples)
- decal->lightmapaddress = decalbestsurf->samples + decalbestlightmapofs * 3; // LordHavoc: *3 for colored lighitng
- else
- decal->lightmapaddress = NULL;
-}
+ for (i = 0, r = r_refdef.decals;i < r_refdef.numdecals;i++, r++)
+ {
+ if (r->ent)
+ {
+ if (r->ent->visframe != r_framecount)
+ continue;
-void GL_DrawDecals (void)
-{
- decal_t *p;
- int i, j, k, dynamiclight, bits, texnum;
- float scale, fr, fg, fb, dist, rad, mindist;
- byte *lightmap;
- vec3_t v;
- msurface_t *surf;
- dlight_t *dl;
+ Mod_CheckLoaded(r->ent->model);
+ if (r->ent->model->type != mod_brush)
+ continue;
- if (!r_drawdecals.value)
- return;
+ surf = r->ent->model->surfaces + r->surface;
- dynamiclight = (int) r_dynamic.value != 0 && (int) r_decals_lighting.value != 0;
+ // skip decals on surfaces that aren't visible in this frame
+ if (surf->visframe != r_framecount)
+ continue;
- mindist = DotProduct(r_origin, vpn) + 4.0f;
+ softwaretransformforentity(r->ent);
+ softwaretransform(r->org, org);
+ softwaretransformdirection(r->dir, dir);
- if (r_render.value)
- {
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- glEnable(GL_BLEND);
- glShadeModel(GL_FLAT);
- glDepthMask(0); // disable zbuffer updates
- glDisable(GL_ALPHA_TEST);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
- texnum = -1;
+ // do not render if the view origin is behind the decal
+ VectorSubtract(org, r_origin, v);
+ if (DotProduct(dir, v) < 0)
+ continue;
+ }
+ else
+ {
+ surf = cl.worldmodel->surfaces + r->surface;
- for (i = 0, p = decals;i < MAX_DECALS;i++, p++)
- {
- if (p->tex == NULL)
- break;
- // skip decals on surfaces that aren't visible in this frame
- if (p->surface->visframe != r_framecount)
- continue;
+ // skip decals on surfaces that aren't visible in this frame
+ if (surf->visframe != r_framecount)
+ continue;
- // do not render if the decal is behind the view
- if (DotProduct(p->org, vpn) < mindist)
- continue;
+ // do not render if the view origin is behind the decal
+ VectorSubtract(r->org, r_origin, v);
+ if (DotProduct(r->dir, v) < 0)
+ continue;
+
+ VectorCopy(r->org, org);
+ VectorCopy(r->dir, dir);
+ }
+
+ dist = -PlaneDiff(r->org, surf->plane);
+ VectorMA(r->org, dist, surf->plane->normal, impact);
- // do not render if the view origin is behind the decal
- VectorSubtract(p->org, r_origin, v);
- if (DotProduct(p->direction, v) < 0)
+ ds = (int) (DotProduct(impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3]) - surf->texturemins[0];
+ dt = (int) (DotProduct(impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3]) - surf->texturemins[1];
+
+ if (ds < 0 || dt < 0 || ds > surf->extents[0] || dt > surf->extents[1])
+ {
+ // this should never happen
continue;
+ }
+
+ if (fogenabled)
+ {
+ ifog = 1 - exp(fogdensity/DotProduct(v,v));
+ ifog = bound(0, ifog, 1);
+ }
- // get the surface lighting
- surf = p->surface;
- lightmap = p->lightmapaddress;
+ tex = &particletexture[r->tex][0];
+ VectorVectors(dir, right, up);
+ VectorScale(right, r->scale, right);
+ VectorScale(up, r->scale, up);
+ tv[0][0] = org[0] - right[0] - up[0];
+ tv[0][1] = org[1] - right[1] - up[1];
+ tv[0][2] = org[2] - right[2] - up[2];
+ tv[0][3] = tex->s1;
+ tv[0][4] = tex->t1;
+ tv[1][0] = org[0] - right[0] + up[0];
+ tv[1][1] = org[1] - right[1] + up[1];
+ tv[1][2] = org[2] - right[2] + up[2];
+ tv[1][3] = tex->s1;
+ tv[1][4] = tex->t2;
+ tv[2][0] = org[0] + right[0] + up[0];
+ tv[2][1] = org[1] + right[1] + up[1];
+ tv[2][2] = org[2] + right[2] + up[2];
+ tv[2][3] = tex->s2;
+ tv[2][4] = tex->t2;
+ tv[3][0] = org[0] + right[0] - up[0];
+ tv[3][1] = org[1] + right[1] - up[1];
+ tv[3][2] = org[2] + right[2] - up[2];
+ tv[3][3] = tex->s2;
+ tv[3][4] = tex->t1;
+
+ // lighting
fr = fg = fb = 0.0f;
- if (lightmap)
+
+ if ((lightmap = surf->samples))
{
if (surf->styles[0] != 255)
{
- scale = d_lightstylevalue[surf->styles[0]] * (1.0f / 256.0f);
- fr += lightmap[0] * scale;
- fg += lightmap[1] * scale;
- fb += lightmap[2] * scale;
+ lightmap += ((dt >> 4) * ((surf->extents[0] >> 4) + 1) + (ds >> 4)) * 3;
+ fscale = d_lightstylevalue[surf->styles[0]] * (1.0f / 32768.0f);
+ fr += lightmap[0] * fscale;
+ fg += lightmap[1] * fscale;
+ fb += lightmap[2] * fscale;
if (surf->styles[1] != 255)
{
- lightmap += p->lightmapstep;
- scale = d_lightstylevalue[surf->styles[1]] * (1.0f / 256.0f);
- fr += lightmap[0] * scale;
- fg += lightmap[1] * scale;
- fb += lightmap[2] * scale;
+ lightmapstep = (((surf->extents[0] >> 4) + 1) * ((surf->extents[1] >> 4) + 1)) * 3;
+ lightmap += lightmapstep;
+ fscale = d_lightstylevalue[surf->styles[1]] * (1.0f / 32768.0f);
+ fr += lightmap[0] * fscale;
+ fg += lightmap[1] * fscale;
+ fb += lightmap[2] * fscale;
if (surf->styles[2] != 255)
{
- lightmap += p->lightmapstep;
- scale = d_lightstylevalue[surf->styles[2]] * (1.0f / 256.0f);
- fr += lightmap[0] * scale;
- fg += lightmap[1] * scale;
- fb += lightmap[2] * scale;
+ lightmap += lightmapstep;
+ fscale = d_lightstylevalue[surf->styles[2]] * (1.0f / 32768.0f);
+ fr += lightmap[0] * fscale;
+ fg += lightmap[1] * fscale;
+ fb += lightmap[2] * fscale;
if (surf->styles[3] != 255)
{
- lightmap += p->lightmapstep;
- scale = d_lightstylevalue[surf->styles[3]] * (1.0f / 256.0f);
- fr += lightmap[0] * scale;
- fg += lightmap[1] * scale;
- fb += lightmap[2] * scale;
+ lightmap += lightmapstep;
+ fscale = d_lightstylevalue[surf->styles[3]] * (1.0f / 32768.0f);
+ fr += lightmap[0] * fscale;
+ fg += lightmap[1] * fscale;
+ fb += lightmap[2] * fscale;
}
}
}
}
- /*
- for (j = 0;j < MAXLIGHTMAPS && surf->styles[j] != 255;j++)
- {
- scale = d_lightstylevalue[surf->styles[j]] * (1.0f / 256.0f);
- fr += lightmap[0] * scale;
- fg += lightmap[1] * scale;
- fb += lightmap[2] * scale;
- lightmap += p->lightmapstep;
- }
- */
}
- // dynamic lighting
- if (dynamiclight)
+
+ if (surf->dlightframe == r_framecount)
{
- if (surf->dlightframe == r_framecount)
+ for (j = 0;j < r_numdlights;j++)
{
- for (j = 0;j < 8;j++)
+ if (surf->dlightbits[j >> 5] & (1 << (j & 31)))
{
- bits = surf->dlightbits[j];
- if (bits)
+ rd = &r_dlight[j];
+ VectorSubtract(r->org, rd->origin, v);
+ dist = DotProduct(v, v) + LIGHTOFFSET;
+ if (dist < rd->cullradius2)
{
- for (k = 0, dl = cl_dlights + j * 32;bits;k++, dl++)
+ f = (1.0f / dist) - rd->lightsubtract;
+ if (f > 0)
{
- if (bits & (1 << k))
- {
- bits -= 1 << k;
- VectorSubtract(p->org, dl->origin, v);
- dist = DotProduct(v, v) + LIGHTOFFSET;
- rad = dl->radius * dl->radius;
- if (dist < rad)
- {
- rad *= 128.0f / dist;
- fr += rad * dl->color[0];
- fg += rad * dl->color[1];
- fb += rad * dl->color[2];
- }
- }
+ fr += f * rd->light[0];
+ fg += f * rd->light[1];
+ fb += f * rd->light[2];
}
}
}
}
}
- /*
+
+ // if the surface is transparent, render as transparent
+ m.transparent = !(surf->flags & SURF_CLIPSOLID);
+ m.cr = r->color[0] * fr;
+ m.cg = r->color[1] * fg;
+ m.cb = r->color[2] * fb;
+ m.ca = r->color[3];
+
+ if (fogenabled)
+ {
+ m.cr *= ifog;
+ m.cg *= ifog;
+ m.cb *= ifog;
+ }
+
+ R_Mesh_DrawDecal(&m);
+ }
+
+ if (!fogenabled)
+ return;
+
+ m.blendfunc2 = GL_ONE;
+ m.cr = fogcolor[0];
+ m.cg = fogcolor[1];
+ m.cb = fogcolor[2];
+
+ for (i = 0, r = r_refdef.decals;i < r_refdef.numdecals;i++, r++)
+ {
+ if (r->ent)
+ {
+ if (r->ent->visframe != r_framecount)
+ continue;
+
+ Mod_CheckLoaded(r->ent->model);
+
+ surf = r->ent->model->surfaces + r->surface;
+
+ // skip decals on surfaces that aren't visible in this frame
+ if (surf->visframe != r_framecount)
+ continue;
+
+ softwaretransformforentity(r->ent);
+ softwaretransform(r->org, org);
+ softwaretransformdirection(r->dir, dir);
+
+ // do not render if the view origin is behind the decal
+ VectorSubtract(org, r_origin, v);
+ if (DotProduct(dir, v) < 0)
+ continue;
+ }
+ else
{
- int ir, ig, ib;
- byte br, bg, bb, ba;
- // apply color to lighting
- ir = (int) (fr * p->color[0] * (1.0f / 128.0f));
- ig = (int) (fg * p->color[1] * (1.0f / 128.0f));
- ib = (int) (fb * p->color[2] * (1.0f / 128.0f));
- // compute byte color
- br = (byte) min(ir, 255);
- bg = (byte) min(ig, 255);
- bb = (byte) min(ib, 255);
- ba = p->color[3];
- // put into transpoly system for sorted drawing later
- transpolybegin(R_GetTexture(p->tex), 0, R_GetTexture(p->tex), TPOLYTYPE_ALPHA);
- transpolyvertub(p->vert[0][0], p->vert[0][1], p->vert[0][2], 0,1,br,bg,bb,ba);
- transpolyvertub(p->vert[1][0], p->vert[1][1], p->vert[1][2], 0,0,br,bg,bb,ba);
- transpolyvertub(p->vert[2][0], p->vert[2][1], p->vert[2][2], 1,0,br,bg,bb,ba);
- transpolyvertub(p->vert[3][0], p->vert[3][1], p->vert[3][2], 1,1,br,bg,bb,ba);
- transpolyend();
+ surf = cl.worldmodel->surfaces + r->surface;
+
+ // skip decals on surfaces that aren't visible in this frame
+ if (surf->visframe != r_framecount)
+ continue;
+
+ // do not render if the view origin is behind the decal
+ VectorSubtract(r->org, r_origin, v);
+ if (DotProduct(r->dir, v) < 0)
+ continue;
+
+ VectorCopy(r->org, org);
+ VectorCopy(r->dir, dir);
}
- */
- if (r_render.value)
+
+ fog = exp(fogdensity/DotProduct(v,v));
+ fog = bound(0, fog, 1);
+ m.ca = r->color[3] * fog;
+
+ if (m.ca >= 0.01f)
{
- j = R_GetTexture(p->tex);
- if (texnum != j)
+ dist = -PlaneDiff(r->org, surf->plane);
+ VectorMA(r->org, dist, surf->plane->normal, impact);
+
+ ds = (int) (DotProduct(impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3]) - surf->texturemins[0];
+ dt = (int) (DotProduct(impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3]) - surf->texturemins[1];
+
+ if (ds < 0 || dt < 0 || ds > surf->extents[0] || dt > surf->extents[1])
{
- glEnd();
- texnum = j;
- glBindTexture(GL_TEXTURE_2D, texnum);
- glBegin(GL_QUADS);
+ // this should never happen
+ continue;
}
- if (lighthalf)
- glColor4f(fr * p->color[0] * (1.0f / 255.0f / 256.0f), fg * p->color[1] * (1.0f / 255.0f / 256.0f), fb * p->color[2] * (1.0f / 255.0f / 256.0f), p->color[3] * (1.0f / 255.0f));
- else
- glColor4f(fr * p->color[0] * (1.0f / 255.0f / 128.0f), fg * p->color[1] * (1.0f / 255.0f / 128.0f), fb * p->color[2] * (1.0f / 255.0f / 128.0f), p->color[3] * (1.0f / 255.0f));
- glTexCoord2f(0, 1);
- glVertex3fv(p->vert[0]);
- glTexCoord2f(0, 0);
- glVertex3fv(p->vert[1]);
- glTexCoord2f(1, 0);
- glVertex3fv(p->vert[2]);
- glTexCoord2f(1, 1);
- glVertex3fv(p->vert[3]);
- }
- }
-
- if (r_render.value)
- {
- glEnd();
- glDepthMask(1); // enable zbuffer updates
- glDisable(GL_ALPHA_TEST);
+ tex = &particletexture[r->tex][1];
+ VectorVectors(dir, right, up);
+ VectorScale(right, r->scale, right);
+ VectorScale(up, r->scale, up);
+ tv[0][0] = org[0] - right[0] - up[0];
+ tv[0][1] = org[1] - right[1] - up[1];
+ tv[0][2] = org[2] - right[2] - up[2];
+ tv[0][3] = tex->s1;
+ tv[0][4] = tex->t1;
+ tv[1][0] = org[0] - right[0] + up[0];
+ tv[1][1] = org[1] - right[1] + up[1];
+ tv[1][2] = org[2] - right[2] + up[2];
+ tv[1][3] = tex->s1;
+ tv[1][4] = tex->t2;
+ tv[2][0] = org[0] + right[0] + up[0];
+ tv[2][1] = org[1] + right[1] + up[1];
+ tv[2][2] = org[2] + right[2] + up[2];
+ tv[2][3] = tex->s2;
+ tv[2][4] = tex->t2;
+ tv[3][0] = org[0] + right[0] - up[0];
+ tv[3][1] = org[1] + right[1] - up[1];
+ tv[3][2] = org[2] + right[2] - up[2];
+ tv[3][3] = tex->s2;
+ tv[3][4] = tex->t1;
+
+ // if the surface is transparent, render as transparent
+ m.transparent = !(surf->flags & SURF_CLIPSOLID);
+ R_Mesh_DrawDecal(&m);
+ }
}
}
+*/