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);
88 if (r->ent->model->type != mod_brush)
91 surf = r->ent->model->surfaces + r->surface;
93 // skip decals on surfaces that aren't visible in this frame
94 if (surf->visframe != r_framecount)
97 softwaretransformforentity(r->ent);
98 softwaretransform(r->org, org);
99 softwaretransformdirection(r->dir, dir);
101 // do not render if the view origin is behind the decal
102 VectorSubtract(org, r_origin, v);
103 if (DotProduct(dir, v) < 0)
108 surf = cl.worldmodel->surfaces + r->surface;
110 // skip decals on surfaces that aren't visible in this frame
111 if (surf->visframe != r_framecount)
114 // do not render if the view origin is behind the decal
115 VectorSubtract(r->org, r_origin, v);
116 if (DotProduct(r->dir, v) < 0)
119 VectorCopy(r->org, org);
120 VectorCopy(r->dir, dir);
123 dist = -PlaneDiff(r->org, surf->plane);
124 VectorMA(r->org, dist, surf->plane->normal, impact);
126 ds = (int) (DotProduct(impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3]) - surf->texturemins[0];
127 dt = (int) (DotProduct(impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3]) - surf->texturemins[1];
129 if (ds < 0 || dt < 0 || ds > surf->extents[0] || dt > surf->extents[1])
131 // this should never happen
136 ifog = 1 - exp(fogdensity/DotProduct(v,v));
138 tex = &particletexture[r->tex][0];
139 VectorVectors(dir, right, up);
140 VectorScale(right, r->scale, right);
141 VectorScale(up, r->scale, up);
142 tvertex[0][0] = org[0] - right[0] - up[0];
143 tvertex[0][1] = org[1] - right[1] - up[1];
144 tvertex[0][2] = org[2] - right[2] - up[2];
145 tvertex[0][3] = tex->s1;
146 tvertex[0][4] = tex->t1;
147 tvertex[1][0] = org[0] - right[0] + up[0];
148 tvertex[1][1] = org[1] - right[1] + up[1];
149 tvertex[1][2] = org[2] - right[2] + up[2];
150 tvertex[1][3] = tex->s1;
151 tvertex[1][4] = tex->t2;
152 tvertex[2][0] = org[0] + right[0] + up[0];
153 tvertex[2][1] = org[1] + right[1] + up[1];
154 tvertex[2][2] = org[2] + right[2] + up[2];
155 tvertex[2][3] = tex->s2;
156 tvertex[2][4] = tex->t2;
157 tvertex[3][0] = org[0] + right[0] - up[0];
158 tvertex[3][1] = org[1] + right[1] - up[1];
159 tvertex[3][2] = org[2] + right[2] - up[2];
160 tvertex[3][3] = tex->s2;
161 tvertex[3][4] = tex->t1;
166 if ((lightmap = surf->samples))
168 if (surf->styles[0] != 255)
170 lightmap += ((dt >> 4) * ((surf->extents[0] >> 4) + 1) + (ds >> 4)) * 3;
171 fscale = d_lightstylevalue[surf->styles[0]] * (1.0f / 32768.0f);
172 fr += lightmap[0] * fscale;
173 fg += lightmap[1] * fscale;
174 fb += lightmap[2] * fscale;
175 if (surf->styles[1] != 255)
177 lightmapstep = (((surf->extents[0] >> 4) + 1) * ((surf->extents[1] >> 4) + 1)) * 3;
178 lightmap += lightmapstep;
179 fscale = d_lightstylevalue[surf->styles[1]] * (1.0f / 32768.0f);
180 fr += lightmap[0] * fscale;
181 fg += lightmap[1] * fscale;
182 fb += lightmap[2] * fscale;
183 if (surf->styles[2] != 255)
185 lightmap += lightmapstep;
186 fscale = d_lightstylevalue[surf->styles[2]] * (1.0f / 32768.0f);
187 fr += lightmap[0] * fscale;
188 fg += lightmap[1] * fscale;
189 fb += lightmap[2] * fscale;
190 if (surf->styles[3] != 255)
192 lightmap += lightmapstep;
193 fscale = d_lightstylevalue[surf->styles[3]] * (1.0f / 32768.0f);
194 fr += lightmap[0] * fscale;
195 fg += lightmap[1] * fscale;
196 fb += lightmap[2] * fscale;
203 if (surf->dlightframe == r_framecount)
205 for (j = 0;j < r_numdlights;j++)
207 if (surf->dlightbits[j >> 5] & (1 << (j & 31)))
210 VectorSubtract(r->org, rd->origin, v);
211 dist = DotProduct(v, v) + LIGHTOFFSET;
212 if (dist < rd->cullradius2)
214 f = (1.0f / dist) - rd->lightsubtract;
217 fr += f * rd->light[0];
218 fg += f * rd->light[1];
219 fb += f * rd->light[2];
226 // if the surface is transparent, render as transparent
227 m.transparent = !(surf->flags & SURF_CLIPSOLID);
228 m.cr = r->color[0] * fr;
229 m.cg = r->color[1] * fg;
230 m.cb = r->color[2] * fb;
246 m.blendfunc2 = GL_ONE;
251 for (i = 0, r = r_refdef.decals;i < r_refdef.numdecals;i++, r++)
255 if (r->ent->visframe != r_framecount)
258 Mod_CheckLoaded(r->ent->model);
260 surf = r->ent->model->surfaces + r->surface;
262 // skip decals on surfaces that aren't visible in this frame
263 if (surf->visframe != r_framecount)
266 softwaretransformforentity(r->ent);
267 softwaretransform(r->org, org);
268 softwaretransformdirection(r->dir, dir);
270 // do not render if the view origin is behind the decal
271 VectorSubtract(org, r_origin, v);
272 if (DotProduct(dir, v) < 0)
277 surf = cl.worldmodel->surfaces + r->surface;
279 // skip decals on surfaces that aren't visible in this frame
280 if (surf->visframe != r_framecount)
283 // do not render if the view origin is behind the decal
284 VectorSubtract(r->org, r_origin, v);
285 if (DotProduct(r->dir, v) < 0)
288 VectorCopy(r->org, org);
289 VectorCopy(r->dir, dir);
292 m.ca = r->color[3] * exp(fogdensity/DotProduct(v,v));
296 dist = -PlaneDiff(r->org, surf->plane);
297 VectorMA(r->org, dist, surf->plane->normal, impact);
299 ds = (int) (DotProduct(impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3]) - surf->texturemins[0];
300 dt = (int) (DotProduct(impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3]) - surf->texturemins[1];
302 if (ds < 0 || dt < 0 || ds > surf->extents[0] || dt > surf->extents[1])
304 // this should never happen
308 tex = &particletexture[r->tex][1];
309 VectorVectors(dir, right, up);
310 VectorScale(right, r->scale, right);
311 VectorScale(up, r->scale, up);
312 tvertex[0][0] = org[0] - right[0] - up[0];
313 tvertex[0][1] = org[1] - right[1] - up[1];
314 tvertex[0][2] = org[2] - right[2] - up[2];
315 tvertex[0][3] = tex->s1;
316 tvertex[0][4] = tex->t1;
317 tvertex[1][0] = org[0] - right[0] + up[0];
318 tvertex[1][1] = org[1] - right[1] + up[1];
319 tvertex[1][2] = org[2] - right[2] + up[2];
320 tvertex[1][3] = tex->s1;
321 tvertex[1][4] = tex->t2;
322 tvertex[2][0] = org[0] + right[0] + up[0];
323 tvertex[2][1] = org[1] + right[1] + up[1];
324 tvertex[2][2] = org[2] + right[2] + up[2];
325 tvertex[2][3] = tex->s2;
326 tvertex[2][4] = tex->t2;
327 tvertex[3][0] = org[0] + right[0] - up[0];
328 tvertex[3][1] = org[1] + right[1] - up[1];
329 tvertex[3][2] = org[2] + right[2] - up[2];
330 tvertex[3][3] = tex->s2;
331 tvertex[3][4] = tex->t1;
333 // if the surface is transparent, render as transparent
334 m.transparent = !(surf->flags & SURF_CLIPSOLID);