X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=r_decals.c;h=74a9b35dbda1ffd983d97d97baa099df13fde444;hb=96cb4c1485603e38068a9473f970f763b121450a;hp=cea29fdbb6bd12f8236aca654c3799c4e0c08e41;hpb=4d162c39ec059b7f3191fbb4fb18304bc9b1db59;p=xonotic%2Fdarkplaces.git diff --git a/r_decals.c b/r_decals.c index cea29fdb..74a9b35d 100644 --- a/r_decals.c +++ b/r_decals.c @@ -8,7 +8,7 @@ of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -20,261 +20,579 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" -#define MAX_DECALS 2048 +cvar_t r_drawdecals = {0, "r_drawdecals", "1"}; -typedef struct decal_s +static void r_decals_start(void) { - 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 = {"r_drawdecals", "1"}; -cvar_t r_decals_lighting = {"r_decals_lighting", "1"}; - -void r_decals_start() -{ - decals = (decal_t *) qmalloc(MAX_DECALS * sizeof(decal_t)); - memset(decals, 0, MAX_DECALS * sizeof(decal_t)); - currentdecal = 0; -} - -void r_decals_shutdown() +static void r_decals_shutdown(void) { - qfree(decals); } -void r_decals_newmap() +static void r_decals_newmap(void) { - memset(decals, 0, MAX_DECALS * sizeof(decal_t)); - currentdecal = 0; } -void R_Decals_Init() +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); } -void R_Decal(vec3_t org, rtexture_t *tex, float scale, int cred, int cgreen, int cblue, int alpha) +/* +static int decalindexarray[2*3] = { - int i, ds, dt, bestlightmapofs; - float bestdist, dist; - vec3_t impact, right, up; - decal_t *decal; -// mleaf_t *leaf; - msurface_t *surf/*, **mark, **endmark*/, *bestsurf; - - if (alpha < 1) + 0, 1, 2, + 0, 2, 3, +}; +*/ + +void R_DrawDecals (void) +{ + 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; -// leaf = Mod_PointInLeaf(org, cl.worldmodel); -// if (!leaf->nummarksurfaces) -// return; - -// mark = leaf->firstmarksurface; -// endmark = mark + leaf->nummarksurfaces; - - // find the best surface to place the decal on - bestsurf = NULL; - bestdist = 16; - bestlightmapofs = 0; -// while(mark < endmark) -// { -// surf = *mark++; - surf = &cl.worldmodel->surfaces[cl.worldmodel->firstmodelsurface]; - for (i = 0;i < cl.worldmodel->nummodelsurfaces;i++, surf++) + 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++) { - if (surf->flags & SURF_DRAWTILED) - continue; // no lightmaps + if (r->ent) + { + if (r->ent->visframe != r_framecount) + continue; - dist = PlaneDiff(org, surf->plane); - if (surf->flags & SURF_PLANEBACK) - dist = -dist; - if (dist < 0) - continue; - if (dist >= bestdist) - continue; + Mod_CheckLoaded(r->ent->model); + if (r->ent->model->type != mod_brush) + continue; - impact[0] = org[0] - surf->plane->normal[0] * dist; - impact[1] = org[1] - surf->plane->normal[1] * dist; - impact[2] = org[2] - surf->plane->normal[2] * dist; + surf = r->ent->model->surfaces + r->surface; - 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]); + // skip decals on surfaces that aren't visible in this frame + if (surf->visframe != r_framecount) + continue; - 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]) + 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, 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; + } - bestsurf = surf; - bestdist = dist; - bestlightmapofs = (dt >> 4) * ((surf->extents[0] >> 4) + 1) + (ds >> 4); - } - // abort if no suitable surface was found - if (bestsurf == NULL) - return; + 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; - // 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; - // reverse direction - if (bestsurf->flags & SURF_PLANEBACK) - { - VectorCopy(bestsurf->plane->normal, decal->direction); - } - else - { - VectorNegate(bestsurf->plane->normal, decal->direction); + if ((lightmap = surf->samples)) + { + 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; + } + } + } + } + } + + if (surf->dlightframe == r_framecount) + { + 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]; + } + } + } + } + } + + // 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); } - // - 0.25 to push it off the surface a bit - decal->org[0] = impact[0] = org[0] + decal->direction[0] * (bestdist - 0.25f); - decal->org[1] = impact[1] = org[1] + decal->direction[1] * (bestdist - 0.25f); - decal->org[2] = impact[2] = org[2] + decal->direction[2] * (bestdist - 0.25f); - // set up the 4 corners - scale *= 0.5f; - VectorVectors(decal->direction, right, up); - decal->vert[0][0] = impact[0] - up[0] * scale - right[0] * scale; - decal->vert[0][1] = impact[1] - up[1] * scale - right[1] * scale; - decal->vert[0][2] = impact[2] - up[2] * scale - right[2] * scale; - decal->vert[1][0] = impact[0] + up[0] * scale - right[0] * scale; - decal->vert[1][1] = impact[1] + up[1] * scale - right[1] * scale; - decal->vert[1][2] = impact[2] + up[2] * scale - right[2] * scale; - decal->vert[2][0] = impact[0] + up[0] * scale + right[0] * scale; - decal->vert[2][1] = impact[1] + up[1] * scale + right[1] * scale; - decal->vert[2][2] = impact[2] + up[2] * scale + right[2] * scale; - decal->vert[3][0] = impact[0] - up[0] * scale + right[0] * scale; - decal->vert[3][1] = impact[1] - up[1] * scale + right[1] * scale; - decal->vert[3][2] = impact[2] - up[2] * scale + right[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 = bestsurf; - decal->lightmapstep = ((bestsurf->extents[0]>>4)+1) * ((bestsurf->extents[1]>>4)+1)*3; // LordHavoc: *3 for colored lighting - if (bestsurf->samples) - decal->lightmapaddress = bestsurf->samples + bestlightmapofs * 3; // LordHavoc: *3 for colored lighitng - else - decal->lightmapaddress = NULL; } +/* void R_DrawDecals (void) { - decal_t *p; - int i, j, k, dynamiclight, ir, ig, ib, maps, bits; - byte br, bg, bb, ba; - float scale, fr, fg, fb, dist, rad, mindist; + 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; - vec3_t v; msurface_t *surf; - dlight_t *dl; + rdlight_t *rd; + rmeshinfo_t m; - if (!r_drawdecals.value) + if (!r_drawdecals.integer) return; - dynamiclight = (int) r_dynamic.value != 0 && (int) r_decals_lighting.value != 0; + ifog = 1; - mindist = DotProduct(r_refdef.vieworg, vpn) + 4.0f; + Mod_CheckLoaded(cl.worldmodel); - for (i = 0, p = decals;i < MAX_DECALS;i++, p++) + 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]); + + for (i = 0, r = r_refdef.decals;i < r_refdef.numdecals;i++, r++) { - if (p->tex == NULL) - break; + if (r->ent) + { + if (r->ent->visframe != r_framecount) + continue; - // do not render if the decal is behind the view - if (DotProduct(p->org, vpn) < mindist) - continue; + Mod_CheckLoaded(r->ent->model); + if (r->ent->model->type != mod_brush) + continue; + + surf = r->ent->model->surfaces + r->surface; - // do not render if the view origin is behind the decal - VectorSubtract(p->org, r_refdef.vieworg, v); - if (DotProduct(p->direction, v) < 0) + // 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 + { + 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); + } + + 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; + } + + 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)) { - for (maps = 0;maps < MAXLIGHTMAPS && surf->styles[maps] != 255;maps++) + if (surf->styles[0] != 255) { - scale = d_lightstylevalue[surf->styles[maps]]; - fr += lightmap[0] * scale; - fg += lightmap[1] * scale; - fb += lightmap[2] * scale; - lightmap += p->lightmapstep; + 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; + } + } + } } } - fr *= (1.0f / 256.0f); - fg *= (1.0f / 256.0f); - fb *= (1.0f / 256.0f); - // dynamic lighting - if (dynamiclight) + + if (surf->dlightframe == r_framecount) { - if (surf->dlightframe == r_dlightframecount) + 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]; } } } } } - // 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(); + + // 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 + { + 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); + } + + fog = exp(fogdensity/DotProduct(v,v)); + fog = bound(0, fog, 1); + m.ca = r->color[3] * fog; + + if (m.ca >= 0.01f) + { + 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; + } + + 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); + } } } +*/