2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 cvar_t r_drawdecals = {0, "r_drawdecals", "1"};
25 static void r_decals_start(void)
29 static void r_decals_shutdown(void)
33 static void r_decals_newmap(void)
37 void R_Decals_Init(void)
39 Cvar_RegisterVariable (&r_drawdecals);
41 R_RegisterModule("R_Decals", r_decals_start, r_decals_shutdown, r_decals_newmap);
44 static int decalindexarray[2*3] =
50 void R_DrawDecals (void)
53 int i, j, lightmapstep, ds, dt;
54 float fscale, fr, fg, fb, dist, f, ifog, impact[3], v[3], org[3], dir[3], right[3], up[3], tvertex[4][5];
55 particletexture_t *tex;
61 if (!r_drawdecals.integer)
66 Mod_CheckLoaded(cl.worldmodel);
68 memset(&m, 0, sizeof(m));
69 m.blendfunc1 = GL_SRC_ALPHA;
70 m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
73 m.index = decalindexarray;
74 m.vertex = &tvertex[0][0];
75 m.vertexstep = sizeof(float[5]);
76 m.tex[0] = R_GetTexture(particlefonttexture);
77 m.texcoords[0] = &tvertex[0][3];
78 m.texcoordstep[0] = sizeof(float[5]);
80 for (i = 0, r = r_refdef.decals;i < r_refdef.numdecals;i++, r++)
84 if (r->ent->visframe != r_framecount)
87 Mod_CheckLoaded(r->ent->model);
89 surf = r->ent->model->surfaces + r->surface;
91 // skip decals on surfaces that aren't visible in this frame
92 if (surf->visframe != r_framecount)
95 softwaretransformforentity(r->ent);
96 softwaretransform(r->org, org);
97 softwaretransformdirection(r->dir, dir);
99 // do not render if the view origin is behind the decal
100 VectorSubtract(org, r_origin, v);
101 if (DotProduct(dir, v) < 0)
106 surf = cl.worldmodel->surfaces + r->surface;
108 // skip decals on surfaces that aren't visible in this frame
109 if (surf->visframe != r_framecount)
112 // do not render if the view origin is behind the decal
113 VectorSubtract(r->org, r_origin, v);
114 if (DotProduct(r->dir, v) < 0)
117 VectorCopy(r->org, org);
118 VectorCopy(r->dir, dir);
121 dist = -PlaneDiff(r->org, surf->plane);
122 VectorMA(r->org, dist, surf->plane->normal, impact);
124 ds = (int) (DotProduct(impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3]) - surf->texturemins[0];
125 dt = (int) (DotProduct(impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3]) - surf->texturemins[1];
127 if (ds < 0 || dt < 0 || ds > surf->extents[0] || dt > surf->extents[1])
129 // this should never happen
134 ifog = 1 - exp(fogdensity/DotProduct(v,v));
136 tex = &particletexture[r->tex][0];
137 VectorVectors(dir, right, up);
138 VectorScale(right, r->scale, right);
139 VectorScale(up, r->scale, up);
140 tvertex[0][0] = org[0] - right[0] - up[0];
141 tvertex[0][1] = org[1] - right[1] - up[1];
142 tvertex[0][2] = org[2] - right[2] - up[2];
143 tvertex[0][3] = tex->s1;
144 tvertex[0][4] = tex->t1;
145 tvertex[1][0] = org[0] - right[0] + up[0];
146 tvertex[1][1] = org[1] - right[1] + up[1];
147 tvertex[1][2] = org[2] - right[2] + up[2];
148 tvertex[1][3] = tex->s1;
149 tvertex[1][4] = tex->t2;
150 tvertex[2][0] = org[0] + right[0] + up[0];
151 tvertex[2][1] = org[1] + right[1] + up[1];
152 tvertex[2][2] = org[2] + right[2] + up[2];
153 tvertex[2][3] = tex->s2;
154 tvertex[2][4] = tex->t2;
155 tvertex[3][0] = org[0] + right[0] - up[0];
156 tvertex[3][1] = org[1] + right[1] - up[1];
157 tvertex[3][2] = org[2] + right[2] - up[2];
158 tvertex[3][3] = tex->s2;
159 tvertex[3][4] = tex->t1;
164 if ((lightmap = surf->samples))
166 if (surf->styles[0] != 255)
168 lightmap += ((dt >> 4) * ((surf->extents[0] >> 4) + 1) + (ds >> 4)) * 3;
169 fscale = d_lightstylevalue[surf->styles[0]] * (1.0f / 32768.0f);
170 fr += lightmap[0] * fscale;
171 fg += lightmap[1] * fscale;
172 fb += lightmap[2] * fscale;
173 if (surf->styles[1] != 255)
175 lightmapstep = (((surf->extents[0] >> 4) + 1) * ((surf->extents[1] >> 4) + 1)) * 3;
176 lightmap += lightmapstep;
177 fscale = d_lightstylevalue[surf->styles[1]] * (1.0f / 32768.0f);
178 fr += lightmap[0] * fscale;
179 fg += lightmap[1] * fscale;
180 fb += lightmap[2] * fscale;
181 if (surf->styles[2] != 255)
183 lightmap += lightmapstep;
184 fscale = d_lightstylevalue[surf->styles[2]] * (1.0f / 32768.0f);
185 fr += lightmap[0] * fscale;
186 fg += lightmap[1] * fscale;
187 fb += lightmap[2] * fscale;
188 if (surf->styles[3] != 255)
190 lightmap += lightmapstep;
191 fscale = d_lightstylevalue[surf->styles[3]] * (1.0f / 32768.0f);
192 fr += lightmap[0] * fscale;
193 fg += lightmap[1] * fscale;
194 fb += lightmap[2] * fscale;
201 if (surf->dlightframe == r_framecount)
203 for (j = 0;j < r_numdlights;j++)
205 if (surf->dlightbits[j >> 5] & (1 << (j & 31)))
208 VectorSubtract(r->org, rd->origin, v);
209 dist = DotProduct(v, v) + LIGHTOFFSET;
210 if (dist < rd->cullradius2)
212 f = (1.0f / dist) - rd->lightsubtract;
215 fr += f * rd->light[0];
216 fg += f * rd->light[1];
217 fb += f * rd->light[2];
224 // if the surface is transparent, render as transparent
225 m.transparent = !(surf->flags & SURF_CLIPSOLID);
226 m.cr = r->color[0] * fr;
227 m.cg = r->color[1] * fg;
228 m.cb = r->color[2] * fb;
244 m.blendfunc2 = GL_ONE;
249 for (i = 0, r = r_refdef.decals;i < r_refdef.numdecals;i++, r++)
253 if (r->ent->visframe != r_framecount)
256 Mod_CheckLoaded(r->ent->model);
258 surf = r->ent->model->surfaces + r->surface;
260 // skip decals on surfaces that aren't visible in this frame
261 if (surf->visframe != r_framecount)
264 softwaretransformforentity(r->ent);
265 softwaretransform(r->org, org);
266 softwaretransformdirection(r->dir, dir);
268 // do not render if the view origin is behind the decal
269 VectorSubtract(org, r_origin, v);
270 if (DotProduct(dir, v) < 0)
275 surf = cl.worldmodel->surfaces + r->surface;
277 // skip decals on surfaces that aren't visible in this frame
278 if (surf->visframe != r_framecount)
281 // do not render if the view origin is behind the decal
282 VectorSubtract(r->org, r_origin, v);
283 if (DotProduct(r->dir, v) < 0)
286 VectorCopy(r->org, org);
287 VectorCopy(r->dir, dir);
290 m.ca = r->color[3] * exp(fogdensity/DotProduct(v,v));
294 dist = -PlaneDiff(r->org, surf->plane);
295 VectorMA(r->org, dist, surf->plane->normal, impact);
297 ds = (int) (DotProduct(impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3]) - surf->texturemins[0];
298 dt = (int) (DotProduct(impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3]) - surf->texturemins[1];
300 if (ds < 0 || dt < 0 || ds > surf->extents[0] || dt > surf->extents[1])
302 // this should never happen
306 tex = &particletexture[r->tex][1];
307 VectorVectors(dir, right, up);
308 VectorScale(right, r->scale, right);
309 VectorScale(up, r->scale, up);
310 tvertex[0][0] = org[0] - right[0] - up[0];
311 tvertex[0][1] = org[1] - right[1] - up[1];
312 tvertex[0][2] = org[2] - right[2] - up[2];
313 tvertex[0][3] = tex->s1;
314 tvertex[0][4] = tex->t1;
315 tvertex[1][0] = org[0] - right[0] + up[0];
316 tvertex[1][1] = org[1] - right[1] + up[1];
317 tvertex[1][2] = org[2] - right[2] + up[2];
318 tvertex[1][3] = tex->s1;
319 tvertex[1][4] = tex->t2;
320 tvertex[2][0] = org[0] + right[0] + up[0];
321 tvertex[2][1] = org[1] + right[1] + up[1];
322 tvertex[2][2] = org[2] + right[2] + up[2];
323 tvertex[2][3] = tex->s2;
324 tvertex[2][4] = tex->t2;
325 tvertex[3][0] = org[0] + right[0] - up[0];
326 tvertex[3][1] = org[1] + right[1] - up[1];
327 tvertex[3][2] = org[2] + right[2] - up[2];
328 tvertex[3][3] = tex->s2;
329 tvertex[3][4] = tex->t1;
331 // if the surface is transparent, render as transparent
332 m.transparent = !(surf->flags & SURF_CLIPSOLID);