UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
r_geoscape.cpp
Go to the documentation of this file.
1 
5 /*
6 Copyright (C) 1997-2001 Id Software, Inc.
7 
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12 
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 
17 See the GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 
23 */
24 
25 #include "r_local.h"
26 #include "r_error.h"
27 #include "r_sphere.h"
28 #include "r_geoscape.h"
29 
30 #include "r_mesh.h"
31 #include "r_draw.h"
32 
33 #define MARKER_SIZE 60.0
34 
48 void R_DrawFlatGeoscape (const vec2_t nodePos, const vec2_t nodeSize, float p, float cx, float cy, float iz, const char* map, bool overlayNation, bool overlayXVI, bool overlayRadar, image_t* r_dayandnightTexture, image_t* r_xviTexture, image_t* r_radarTexture)
49 {
50  image_t* gl;
51  float geoscape_texcoords[4 * 2];
52  short geoscape_verts[4 * 2];
53 
54  /* normalize */
55  const float nx = nodePos[0] * viddef.rx;
56  const float ny = nodePos[1] * viddef.ry;
57  const float nw = nodeSize[0] * viddef.rx;
58  const float nh = nodeSize[1] * viddef.ry;
59 
60  /* load day image */
61  gl = R_FindImage(va("pics/geoscape/%s_day", map), it_wrappic);
62  if (gl == r_noTexture)
63  Com_Error(ERR_FATAL, "Could not load geoscape day image");
64 
65  /* alter the array pointers */
66  glVertexPointer(2, GL_SHORT, 0, geoscape_verts);
67  R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, geoscape_texcoords);
68 
69  geoscape_texcoords[0] = cx - iz;
70  geoscape_texcoords[1] = cy - iz;
71  geoscape_texcoords[2] = cx + iz;
72  geoscape_texcoords[3] = cy - iz;
73  geoscape_texcoords[4] = cx + iz;
74  geoscape_texcoords[5] = cy + iz;
75  geoscape_texcoords[6] = cx - iz;
76  geoscape_texcoords[7] = cy + iz;
77 
78  geoscape_verts[0] = nx;
79  geoscape_verts[1] = ny;
80  geoscape_verts[2] = nx + nw;
81  geoscape_verts[3] = ny;
82  geoscape_verts[4] = nx + nw;
83  geoscape_verts[5] = ny + nh;
84  geoscape_verts[6] = nx;
85  geoscape_verts[7] = ny + nh;
86 
87  /* draw day image */
88  R_BindTexture(gl->texnum);
89  glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
90 
92 
93  /* draw night map */
94  gl = R_FindImage(va("pics/geoscape/%s_night", map), it_wrappic);
95  /* maybe the campaign map doesn't have a night image */
96  if (gl != r_noTexture) {
97  float geoscape_nighttexcoords[4 * 2];
98 
99  R_BindTexture(gl->texnum);
102 
103  geoscape_nighttexcoords[0] = geoscape_texcoords[0] + p;
104  geoscape_nighttexcoords[1] = geoscape_texcoords[1];
105  geoscape_nighttexcoords[2] = geoscape_texcoords[2] + p;
106  geoscape_nighttexcoords[3] = geoscape_texcoords[3];
107  geoscape_nighttexcoords[4] = geoscape_texcoords[4] + p;
108  geoscape_nighttexcoords[5] = geoscape_texcoords[5];
109  geoscape_nighttexcoords[6] = geoscape_texcoords[6] + p;
110  geoscape_nighttexcoords[7] = geoscape_texcoords[7];
111 
112  R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, geoscape_nighttexcoords);
113 
114  R_BindTexture(r_dayandnightTexture->texnum);
115 
117  glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
118 
119  refdef.batchCount++;
120 
122  R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, geoscape_texcoords);
123 
125  }
126 
127  /* draw nation overlay */
128  if (overlayNation) {
129  gl = R_FindImage(va("pics/geoscape/%s_nations_overlay", map), it_wrappic);
130  if (gl == r_noTexture)
131  Com_Error(ERR_FATAL, "Could not load geoscape nation overlay image");
132 
133  /* draw day image */
134  R_BindTexture(gl->texnum);
135  glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
136 
137  refdef.batchCount++;
138  }
139 
140  /* draw XVI image */
141  if (overlayXVI) {
142  gl = R_FindImage(va("pics/geoscape/%s_xvi_overlay", map), it_wrappic);
143  if (gl == r_noTexture)
144  Com_Error(ERR_FATAL, "Could not load xvi overlay image");
145 
146  R_BindTexture(gl->texnum);
147 
149  R_BindLightmapTexture(r_xviTexture->texnum);
150 
151  glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
152 
153  refdef.batchCount++;
154 
156  }
157 
158  /* draw radar image */
159  if (overlayRadar) {
160  R_BindTexture(r_radarTexture->texnum);
161  glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
162 
163  refdef.batchCount++;
164  }
165 
166  /* and restore them */
167  R_BindDefaultArray(GL_TEXTURE_COORD_ARRAY);
168  R_BindDefaultArray(GL_VERTEX_ARRAY);
169 }
170 
178 void R_Draw2DMapMarkers (const vec2_t screenPos, float direction, const char* model, int skin)
179 {
180  modelInfo_t mi;
181  vec2_t size;
182  vec3_t scale, center, position, angles;
183  float zoom = 0.4f;
184 
185  OBJZERO(mi);
186  VectorCopy(vec3_origin, position);
187  VectorCopy(vec3_origin, angles);
188 
189  mi.model = R_FindModel(model);
190  if (!mi.model) {
191  Com_Printf("Could not find model '%s'\n", model);
192  return;
193  }
194 
195  mi.name = model;
196  mi.origin = position;
197  mi.angles = angles;
198  mi.skin = skin;
199 
200  size[0] = size[1] = MARKER_SIZE * zoom;
201  R_ModelAutoScale(size, &mi, scale, center);
202  /* reset the center, as we want to place the models onto the surface of the earth */
203  mi.center = nullptr;
204 
205  /* go to a new matrix */
206  glPushMatrix();
207 
208  /* Apply all transformation to model. Note that the transformations are applied starting
209  * from the last one and ending with the first one */
210 
211  /* move model to its location */
212  glTranslatef(screenPos[0]* viddef.rx, screenPos[1]* viddef.ry, 0);
213  /* scale model to proper resolution */
214  glScalef(viddef.rx, viddef.ry, 1.0f);
215  /* rotate model to proper direction. */
216  glRotatef(-90.f + direction, 0, 0, 1);
217 
218  R_DrawModelDirect(&mi, nullptr, nullptr);
219 
220  /* restore previous matrix */
221  glPopMatrix();
222 }
223 
235 void R_Draw3DMapMarkers (const vec2_t nodePos, const vec2_t nodeSize, const vec3_t rotate, const vec2_t pos, float direction, float earthRadius, const char* model, int skin)
236 {
237  /* normalize */
238  const float nx = nodePos[0] * viddef.rx;
239  const float ny = nodePos[1] * viddef.ry;
240  const float nw = nodeSize[0] * viddef.rx;
241  const float nh = nodeSize[1] * viddef.ry;
242 
243  /* Earth center is in the middle of node.
244  * Due to Orthographic view, this is also camera position */
245  const vec3_t earthPos = {nx + nw / 2.0f, ny + nh / 2.0f, 0.0f};
246 
247  modelInfo_t mi;
248  vec2_t size;
249  vec3_t scale, center, position, angles;
250  float zoom = 0.4f;
251 
252  OBJZERO(mi);
253  VectorCopy(vec3_origin, position);
254  VectorCopy(vec3_origin, angles);
255 
256  mi.model = R_FindModel(model);
257  if (!mi.model) {
258  Com_Printf("Could not find model '%s'\n", model);
259  return;
260  }
261 
262  mi.name = model;
263  mi.origin = position;
264  mi.angles = angles;
265  mi.skin = skin;
266 
267  size[0] = size[1] = MARKER_SIZE * zoom;
268  R_ModelAutoScale(size, &mi, scale, center);
269  /* reset the center, as we want to place the models onto the surface of the earth */
270  mi.center = nullptr;
271 
272  /* go to a new matrix */
273  glPushMatrix();
274 
275  /* Apply all transformation to model. Note that the transformations are applied starting
276  * from the last one and ending with the first one */
277 
278  /* center model on earth. Translate also along z to avoid seeing
279  * bottom part of the model through earth (only half of earth is drawn) */
280  glTranslatef(earthPos[0], earthPos[1], 10.0f);
281  /* scale model to proper resolution */
282  glScalef(viddef.rx, viddef.ry, 1.0f);
283  /* place model on earth: make it tangent to earth surface, heading toward it if direction is used. */
284  glRotatef(-rotate[1], 1, 0, 0);
285  glRotatef(rotate[2], 0, 1, 0);
286  glRotatef(rotate[0] - pos[0], 0, 0, 1);
287  glRotatef(90.0f - pos[1], 1, 0, 0);
288  glTranslatef(0, 0, earthRadius);
289  glRotatef(90.0f + direction, 0, 0, 1);
290 
291  R_DrawModelDirect(&mi, nullptr, nullptr);
292 
293  /* restore previous matrix */
294  glPopMatrix();
295 }
296 
304 #define SKYBOX_HALFSIZE 800.0f
305 
306 static const float starFieldVerts[] = {
307  /* face 1 */
312 
313  /* face 2 */
318 
319  /* face 3 */
324 
325  /* face 4 */
330 
331  /* face 5 */
336 
337  /* face 6 */
341  -SKYBOX_HALFSIZE, -SKYBOX_HALFSIZE, -SKYBOX_HALFSIZE
342 };
343 
344 static const float starFieldTexCoords[] = {
345  0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0,
346  0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0,
347  0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0,
348  0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0,
349  0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0,
350  0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0,
351 };
352 
365 static void R_DrawStarfield (int texnum, const vec3_t pos, const vec3_t rotate, float timeOfDay)
366 {
367  vec3_t angle;
369  /* go to a new matrix */
370  glPushMatrix();
371 
372  /* we must center the skybox on the camera border of view, and not on the earth, in order
373  * to see only the inside of the cube */
374  glTranslatef(pos[0], pos[1], -SKYBOX_DEPTH);
375 
376  /* rotates starfield: only time and rotation of earth around itself causes starfield to rotate. */
377  VectorSet(angle, rotate[0] - timeOfDay * todeg, rotate[1], rotate[2]);
378  glRotatef(angle[YAW], 1, 0, 0);
379  glRotatef(angle[ROLL], 0, 1, 0);
380  glRotatef(angle[PITCH], 0, 0, 1);
381 
382  R_BindTexture(texnum);
383 
384  /* alter the array pointers */
385  glVertexPointer(3, GL_FLOAT, 0, starFieldVerts);
386  glTexCoordPointer(2, GL_FLOAT, 0, starFieldTexCoords);
387 
388  /* draw the cube */
389 #ifdef GL_VERSION_ES_CM_1_0
390  for( int ii = 0; ii < 6; ii++ )
391  glDrawArrays(GL_TRIANGLE_FAN, ii * 4, 4);
392 #else
393  glDrawArrays(GL_QUADS, 0, 24);
394 #endif
395 
396  refdef.batchCount++;
397 
398  /* restore previous matrix */
399  glPopMatrix();
400 }
401 
405 static inline void R_RotateCelestialBody (const vec4_t v, vec4_t r, const vec3_t rotate, const vec3_t earthPos, const float celestialDist)
406 {
407  vec4_t v1;
408  vec3_t v2;
409  vec3_t rotationAxis;
410 
411  VectorSet(v2, v[1], v[0], v[2]);
412  VectorSet(rotationAxis, 0, 0, 1);
413  RotatePointAroundVector(v1, rotationAxis, v2, -rotate[PITCH]);
414  VectorSet(rotationAxis, 0, 1, 0);
415  RotatePointAroundVector(v2, rotationAxis, v1, -rotate[YAW]);
416 
417  Vector4Set(r, earthPos[0] + celestialDist * v2[1], earthPos[1] + celestialDist * v2[0], -celestialDist * v2[2], 0);
418 }
419 
428 void R_Draw3DGlobe (const vec2_t pos, const vec2_t size, int day, int second, const vec3_t rotate, float zoom, const char* map,
429  bool disableSolarRender, float ambient, bool overlayNation, bool overlayXVI, bool overlayRadar, image_t* r_xviTexture,
430  image_t* r_radarTexture, bool renderNationGlow)
431 {
432  /* globe scaling */
433  const float fullscale = zoom / STANDARD_3D_ZOOM;
434 
435  /* lighting colors */
436  static const vec4_t diffuseLightColor = { 1.75f, 1.75f, 1.75f, 1.0f };
437  static const vec4_t specularLightColor = { 2.0f, 1.9f, 1.7f, 1.0f };
438  static const vec4_t darknessLightColor = { 0.0f, 0.0f, 0.0f, 1.0f };
439  static const vec4_t brightDiffuseLightColor = { 5.0f, 5.0f, 5.0f, 1.0f };
440  const vec4_t ambientLightColor = { ambient + 0.2f, ambient + 0.2f, ambient + 0.2f, ambient + 0.2f };
441  /* billboard textures */
442  image_t* starfield;
443  image_t* sun;
444  image_t* sunOverlay;
445 
446  /* set distance of the sun and moon to make them static on starfield when
447  * time is stoped. this distance should be used for any celestial body
448  * considered at infinite location (sun, moon) */
449  static const float celestialDist = 1.37f * SKYBOX_HALFSIZE;
450  static const float moonSize = 0.025f;
451  vec4_t sunPos;
452  vec4_t antiSunPos;
453  vec4_t moonLoc;
454  vec4_t sunLoc;
455 
456  /* normalize */
457  const float nx = pos[0] * viddef.rx;
458  const float ny = pos[1] * viddef.ry;
459  const float nw = size[0] * viddef.rx;
460  const float nh = size[1] * viddef.ry;
461 
462  /* Earth center is in the middle of node.
463  * Due to Orthographic view, this is also camera position */
464  const vec3_t earthPos = { nx + nw / 2.0f, ny + nh / 2.0f, 0.0f };
465 
466  /* estimate the progress through the current season so we can do
467  * smooth transitions between textures. Currently there are 12
468  * "seasons", because we have one image per Earth-month. */
469  const float season = (float) (day % DAYS_PER_YEAR) / ((float) (DAYS_PER_YEAR) / (float) (SEASONS_PER_YEAR));
470  const int currSeason = (int) floorf(season) % SEASONS_PER_YEAR;
471  const int nextSeason = (int) ceilf(season) % SEASONS_PER_YEAR;
472  const float seasonProgress = season - (float) currSeason;
473 
474  /* Compute sun position in absolute frame */
475  const float q = (day % DAYS_PER_YEAR * SECONDS_PER_DAY + second) * (2.0f * M_PI / (SECONDS_PER_DAY * DAYS_PER_YEAR)); /* sun rotation (year) */
476  const float a = cos(q) * SIN_ALPHA; /* due to earth obliquity */
477  const float sqrta = sqrt(0.5f * (1 - a * a));
478 
479  /* earth rotation (day) */
480  const float p = (second - SECONDS_PER_DAY / 4) * (2.0f * M_PI / SECONDS_PER_DAY);
481  /* lunar orbit */
482  const float m = p + (((double)((10 * day % 249) / 10.0f) + ((double)second / (double)SECONDS_PER_DAY)) / 24.9f) * (2.0f * M_PI);
483 
484  glPushMatrix();
485  glMatrixMode(GL_TEXTURE);
486  glLoadIdentity();
487  glMatrixMode(GL_MODELVIEW);
488  glDisable(GL_LIGHTING);
489  /* draw the starfield, rotating with the planet */
490  starfield = R_FindImage(va("pics/geoscape/%s_stars", map), it_wrappic);
491  if (starfield != r_noTexture)
492  R_DrawStarfield(starfield->texnum, earthPos, rotate, p);
493 
494  glPopMatrix();
495 
496  /* set up position vectors for celestial bodies */
497  Vector4Set(sunPos, cos(p) * sqrta, -sin(p) * sqrta, a, 0);
498  Vector4Set(antiSunPos, -cos(p) * sqrta, sin(p) * sqrta, -a, 0);
499 
500  /* Rotate the sun in the relative frame of player view, to get sun location */
501  R_RotateCelestialBody(sunPos, sunLoc, rotate, earthPos, 1.0f);
502  /* load sun texture image */
503  sun = R_FindImage(va("pics/geoscape/%s_sun", map), it_wrappic);
504  sunOverlay = R_FindImage(va("pics/geoscape/%s_sun_overlay", map), it_pic);
505  if (sun != r_noTexture && sunOverlay != r_noTexture && sunLoc[2] > 0 && !disableSolarRender) {
506  const int sunx = earthPos[0] + viddef.rx * (-128.0f + celestialDist * (sunLoc[0] - earthPos[0]));
507  const int suny = earthPos[1] + viddef.ry * (-128.0f + celestialDist * (sunLoc[1] - earthPos[1]));
508 
509  R_DrawTexture(sunOverlay->texnum, sunx, suny, 256.0f * viddef.rx, 256.0f * viddef.ry);
510  R_DrawBuffers(2);
511  R_DrawTexture(sun->texnum, sunx, suny, 256.0 * viddef.rx, 256.0 * viddef.ry);
512  R_DrawBuffers(1);
513  }
514 
515  /* calculate position of the moon (it rotates around earth with a period of
516  * about 24.9 h, and we must take day into account to avoid moon to "jump"
517  * every time the day is changing) */
518  VectorSet(moonLoc, cos(m) * sqrta, -sin(m) * sqrta, a);
519  R_RotateCelestialBody(moonLoc, moonLoc, rotate, earthPos, celestialDist);
520 
521  /* free last month's texture image */
522  if (r_globeEarth.season != currSeason) {
523  r_globeEarth.season = currSeason;
525  }
526 
527  /* load diffuse texture map (with embedded night-glow map as alpha channel) */
528  r_globeEarth.texture = R_FindImage(va("pics/geoscape/%s/%s_season_%02d", r_config.lodDir, map, currSeason), it_wrappic);
530  Com_Error(ERR_FATAL, "Could not find pics/geoscape/%s/%s_season_%02d\n", r_config.lodDir, map, currSeason);
531 
532  /* set up for advanced GLSL rendering if we have the capability */
533  if (r_programs->integer) {
535  /* load earth image for the next month so we can blend them */
536  r_globeEarth.blendTexture = R_FindImage(va("pics/geoscape/%s/%s_season_%02d", r_config.lodDir, map, nextSeason), it_wrappic);
538  Com_Error(ERR_FATAL, "Could not find pics/geoscape/%s/%s_season_%02d\n", r_config.lodDir, map, nextSeason);
539 
540  /* load normal map (with embedded gloss map as alpha channel) */
541  r_globeEarth.normalMap = R_FindImage(va("pics/geoscape/%s/%s_bump", r_config.lodDir, map), it_wrappic);
543  r_globeEarth.normalMap = nullptr;
544 
545  /* weight the blending based on how much of the month has elapsed */
546  r_globeEarth.blendScale = seasonProgress;
547  /* set up lights for nighttime city glow */
549  glLightfv(GL_LIGHT1, GL_AMBIENT, darknessLightColor);
550  glLightfv(GL_LIGHT1, GL_DIFFUSE, brightDiffuseLightColor);
551  glLightfv(GL_LIGHT1, GL_SPECULAR, darknessLightColor);
552 
553  r_globeEarth.glowScale = 0.7f;
554  }
555 
556  /* load moon texture image */
557  r_globeMoon.texture = R_FindImage(va("pics/geoscape/%s_moon", map), it_wrappic);
558 
559  /* globe texture scaling */
560  glMatrixMode(GL_TEXTURE);
561  glLoadIdentity();
562  glScalef(2.0f, 1.0f, 1.0f);
563  glMatrixMode(GL_MODELVIEW);
564 
565  /* enable the lighting */
566  glEnable(GL_LIGHTING);
567  glEnable(GL_LIGHT0);
568  glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLightColor);
569  glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLightColor);
570  glLightfv(GL_LIGHT0, GL_SPECULAR, specularLightColor);
571 
572  /* draw the moon */
573  if (r_globeMoon.texture != r_noTexture && moonLoc[2] > 0 && !disableSolarRender)
574  R_SphereRender(&r_globeMoon, moonLoc, rotate, moonSize, sunPos);
575 
576  /* activate depth to hide 3D models behind earth */
577  glEnable(GL_DEPTH_TEST);
578 
579  /* draw the earth */
580  R_DrawBuffers(2);
581 #if 0 /* old rendering code which doesn't render city lights in FFP */
582  if (r_programs->integer == 0) /* ignore alpha channel, since the city-light map is stored there */
583  glBlendFunc(GL_ONE, GL_ZERO);
584 
585  R_SphereRender(&r_globeEarth, earthPos, rotate, fullscale, sunPos);
586 
587  if (r_programs->integer == 0) /* restore default blend function */
588  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
589 #else /* new which does render city lights in FFP */
590  if (r_programs->integer == 0) {
591  /* set up rendering of city lights map, which is stored in alpha channel; OpenGL 1.3 required */
592  R_SelectTexture(&texunit_diffuse); /* select texture to edit texture environment for */
593  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); /* enable color combiner */
594  /* setup texture combiner to blend between daylight diffuse map stored in the RGB channels of the diffuse texture
595  * and the monochomatic emission map (which simulates city lights) stored in the alpha channel;
596  * incoming color value is the blend factor.
597  */
598  glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE); /* set day color as blending target*/
599  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
600  glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE); /* set night color as blending source */
601  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_ALPHA);
602  glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_PREVIOUS); /* set incoming color as blending factor */
603  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR);
604  glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); /* set blending mode to interpolation from src1 to src0 */
605  /* copy alpha from incoming color, bypassing the value read from texture, which is not a "real" alpha anyway */
606  glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
607  glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
608  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
609  }
610 
611  R_SphereRender(&r_globeEarth, earthPos, rotate, fullscale, sunPos);
612 
613  if (r_programs->integer == 0) { /* disable combiner */
615  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
616  }
617 #endif
618 
619  r_globeEarthAtmosphere.texture = R_FindImage(va("pics/geoscape/%s_atmosphere", map), it_wrappic);
620 
621  /* Draw earth atmosphere */
628  R_SphereRender(&r_globeEarthAtmosphere, earthPos, rotate, fullscale, sunPos);
629  } else {
630  image_t* halo = R_FindImage("pics/geoscape/map_earth_halo", it_pic);
631  if (halo != r_noTexture) {
633  const float earthSizeX = fullscale * 20500.0f * viddef.rx;
634  const float earthSizeY = fullscale * 20500.0f * viddef.ry;
635  glMatrixMode(GL_TEXTURE);
636  glPushMatrix();
637  glLoadIdentity();
638  glDisable(GL_LIGHTING);
639 
640  R_DrawTexture(halo->texnum, earthPos[0] - earthSizeX * 0.5f, earthPos[1] - earthSizeY * 0.5f, earthSizeX, earthSizeY);
641  glEnable(GL_LIGHTING);
642  glPopMatrix();
643  glMatrixMode(GL_MODELVIEW);
644  }
645  }
646 
647  R_DrawBuffers(1);
648  glDisable(GL_DEPTH_TEST);
649 
650  /* draw nation overlay */
651  if (overlayNation) {
652  r_globeEarth.overlay = R_FindImage(va("pics/geoscape/%s_nations_overlay", map), it_wrappic);
654  Com_Error(ERR_FATAL, "Could not load geoscape nation overlay image");
655 
656  R_SphereRender(&r_globeEarth, earthPos, rotate, fullscale, sunPos);
657 
658  if (renderNationGlow) {
659  /* draw glowing borders */
660  r_globeEarth.overlay = R_FindImage(va("pics/geoscape/%s_nations_overlay_glow", map), it_wrappic);
662  Com_Error(ERR_FATAL, "Could not load geoscape nation overlay glow image");
663 
664  R_DrawBuffers(2);
665  glDisable(GL_LIGHTING);
666  R_SphereRender(&r_globeEarth, earthPos, rotate, fullscale, sunPos);
667  glEnable(GL_LIGHTING);
668  R_DrawBuffers(1);
669  }
670 
671  r_globeEarth.overlay = nullptr;
672  }
673  /* draw XVI overlay */
674  if (overlayXVI) {
675  r_globeEarth.overlay = R_FindImage(va("pics/geoscape/%s_xvi_overlay", map), it_wrappic);
678  R_SphereRender(&r_globeEarth, earthPos, rotate, fullscale, sunPos);
679  r_globeEarth.overlayAlphaMask = nullptr;
680  r_globeEarth.overlay = nullptr;
681  }
682  /* draw radar overlay */
683  if (overlayRadar) {
685  assert(r_globeEarth.overlay);
686  R_SphereRender(&r_globeEarth, earthPos, rotate, fullscale, sunPos);
687  r_globeEarth.overlay = nullptr;
688  }
689 
690  /* disable 3d geoscape lighting */
691  glDisable(GL_LIGHTING);
692 
693  /* restore the previous matrix */
694  glMatrixMode(GL_TEXTURE);
695  glLoadIdentity();
696  glMatrixMode(GL_MODELVIEW);
697 }
698 
702 static inline void R_DrawQuad (void)
703 {
705  const vec2_t texcoord[] = { { 0.0f, 1.0f }, { 1.0f, 1.0f }, { 1.0f, 0.0f }, { 0.0f, 0.0f } };
706  const vec2_t verts[] = { { 0.0f, 0.0f }, Vector2FromInt(fbo_render->width, 0.0f), Vector2FromInt(fbo_render->width, fbo_render->height), Vector2FromInt(0.0f, fbo_render->height) };
707 
708  glVertexPointer(2, GL_FLOAT, 0, verts);
709  R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, texcoord);
710 
711  glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
712 
713  refdef.batchCount++;
714 
715  R_BindDefaultArray(GL_TEXTURE_COORD_ARRAY);
716  R_BindDefaultArray(GL_VERTEX_ARRAY);
717 }
718 
723 static void R_Blur (r_framebuffer_t* source, r_framebuffer_t* dest, int tex, int dir)
724 {
725  R_EnableBlur(r_state.convolve_program, true, source, dest, dir);
726 
727  /* draw new texture onto a flat surface */
729  R_UseViewport(source);
730  R_DrawQuad();
731 
732  R_EnableBlur(r_state.convolve_program, false, nullptr, nullptr, 0);
733 }
734 
738 static void R_BlurStack (int levels, r_framebuffer_t** sources, r_framebuffer_t** dests)
739 {
740  for (int i = 0; i < levels; i++) {
741  const int l = levels - i - 1;
742 
744  R_UseFramebuffer(dests[l]);
745  R_BindTextureForTexUnit(sources[l]->textures[0], &texunit_0);
746  if (i != 0)
747  R_BindTextureForTexUnit(dests[l + 1]->textures[0], &texunit_1);
748 
749  R_UseViewport(sources[l]);
750  R_DrawQuad();
751 
752  R_Blur(dests[l], sources[l], 0, 1);
753  R_Blur(sources[l], dests[l], 0, 0);
754  }
755 }
756 
760 void R_DrawBloom (void)
761 {
762  int i;
763  bool renderBufferState;
764 
766  return;
767 
768  /* save state, then set up for blit-style rendering to quads */
769  renderBufferState = R_RenderbufferEnabled();
770  glMatrixMode(GL_MODELVIEW);
771  glPushMatrix();
772  glLoadIdentity();
773  glMatrixMode(GL_TEXTURE);
774  glPushMatrix();
775  glLoadIdentity();
776  glMatrixMode(GL_PROJECTION);
777  glPushMatrix();
778  glLoadIdentity();
779 #ifndef GL_VERSION_ES_CM_1_0
780  glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT | GL_LIGHTING_BIT | GL_DEPTH_BUFFER_BIT);
781 #endif
782  glOrtho(0, viddef.context.width, viddef.context.height, 0, 9999.0f, SKYBOX_DEPTH);
783 
784  glDisable(GL_LIGHTING);
785  glDisable(GL_DEPTH_TEST);
786 
787  /* downsample into image pyramid */
789  R_BindTexture(fbo_render->textures[1]);
790  qglGenerateMipmapEXT(GL_TEXTURE_2D);
791 
792  R_Blur(fbo_render, fbo_bloom0, 1, 0);
793  R_Blur(fbo_bloom0, fbo_bloom1, 0, 1);
794 
796  R_BindTexture(fbo_bloom1->textures[0]);
797  qglGenerateMipmapEXT(GL_TEXTURE_2D);
799  R_DrawQuad();
800 
801  for (i = 1; i < DOWNSAMPLE_PASSES; i++) {
802  R_Blur(r_state.buffers0[i - 1], r_state.buffers1[i - 1], 0, 0);
803  R_Blur(r_state.buffers1[i - 1], r_state.buffers2[i - 1], 0, 1);
807  R_DrawQuad();
808  }
809 
810  /* blur and combine downsampled images */
811  R_BlurStack(DOWNSAMPLE_PASSES, r_state.buffers0, r_state.buffers1);
812 
813  /* re-combine the blurred version with the original "glow" image */
818 
820  R_DrawQuad();
821 
822  /* draw final result to the screenbuffer */
827 
828  R_DrawQuad();
829 
830  /* cleanup before returning */
832 
833  R_CheckError();
834 
835 #ifndef GL_VERSION_ES_CM_1_0
836  glPopAttrib();
837 #endif
838  glMatrixMode(GL_PROJECTION);
839  glPopMatrix();
840  glMatrixMode(GL_TEXTURE);
841  glPopMatrix();
842  glMatrixMode(GL_MODELVIEW);
843  glPopMatrix();
844  R_CheckError();
845 
846  /* reset renderbuffer state to what it was before */
847  R_EnableRenderbuffer(renderBufferState);
848 }
bool R_EnableRenderbuffer(bool enable)
Enable the render to the framebuffer.
void R_UseProgram(r_program_t *prog)
Definition: r_program.cpp:43
#define VectorCopy(src, dest)
Definition: vector.h:51
void R_UseFramebuffer(const r_framebuffer_t *buf)
bind specified framebuffer object so we render to it
void R_EnableTexture(gltexunit_t *texunit, bool enable)
Definition: r_state.cpp:303
#define fbo_bloom0
Definition: r_state.h:89
#define VectorSet(v, x, y, z)
Definition: vector.h:59
float * origin
Definition: cl_renderer.h:61
#define SEASONS_PER_YEAR
Definition: common.h:300
r_framebuffer_t * buffers2[DOWNSAMPLE_PASSES]
Definition: r_state.h:125
const char * va(const char *format,...)
does a varargs printf into a temp buffer, so I don't need to have varargs versions of all text functi...
Definition: shared.cpp:410
QGL_EXTERN GLuint GLchar ** sources
Definition: r_gl.h:99
#define ROLL
Definition: mathlib.h:56
const char * name
Definition: cl_renderer.h:59
static const vec3_t scale
image_t * r_xviTexture
#define SIN_ALPHA
Definition: mathlib.h:65
image_t * r_radarTexture
r_program_t * atmosphere_program
Definition: r_state.h:138
void R_BindLightmapTexture(GLuint texnum)
Definition: r_state.cpp:90
unsigned int * textures
Definition: r_framebuffer.h:44
const vec3_t vec3_origin
Definition: mathlib.cpp:35
cvar_t * r_programs
Definition: r_main.cpp:97
static const float starFieldVerts[]
Definition: r_geoscape.cpp:306
image_t * blendTexture
Definition: r_sphere.h:33
float rx
Definition: cl_video.h:71
r_program_t * combine2_program
Definition: r_state.h:137
viddef_t viddef
Definition: cl_video.cpp:34
local graphics definitions
static void R_DrawQuad(void)
Draw the current texture on a quad the size of the renderbuffer.
Definition: r_geoscape.cpp:702
static void R_DrawStarfield(int texnum, const vec3_t pos, const vec3_t rotate, float timeOfDay)
Bind and draw starfield.
Definition: r_geoscape.cpp:365
void RotatePointAroundVector(vec3_t dst, const vec3_t dir, const vec3_t point, float degrees)
Rotate a point around a given vector.
Definition: mathlib.cpp:849
int season
Definition: r_sphere.h:44
unsigned width
Definition: cl_video.h:44
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
void Com_Printf(const char *const fmt,...)
Definition: common.cpp:386
rconfig_t r_config
Definition: r_main.cpp:47
image_t * r_noTexture
Definition: r_main.cpp:51
Definition: r_image.h:45
cvar_t * r_postprocess
Definition: r_main.cpp:100
int integer
Definition: cvar.h:81
#define DAYS_PER_YEAR
Definition: common.h:296
#define texunit_lightmap
Definition: r_state.h:69
#define ERR_FATAL
Definition: common.h:210
bool frameBufferObject
Definition: r_local.h:186
void R_DrawModelDirect(modelInfo_t *mi, modelInfo_t *pmi, const char *tagname)
Draws a model in 2d mode (for rendering model data from the ui)
Definition: r_mesh.cpp:306
#define YAW
Definition: mathlib.h:55
void Com_Error(int code, const char *fmt,...)
Definition: common.cpp:417
image_t * R_FindImage(const char *pname, imagetype_t type)
Finds or loads the given image.
Definition: r_image.cpp:603
void R_Draw3DMapMarkers(const vec2_t nodePos, const vec2_t nodeSize, const vec3_t rotate, const vec2_t pos, float direction, float earthRadius, const char *model, int skin)
Draw 3D Marker on the 3D geoscape.
Definition: r_geoscape.cpp:235
void R_Draw2DMapMarkers(const vec2_t screenPos, float direction, const char *model, int skin)
Draw 3D Marker on the 2D geoscape.
Definition: r_geoscape.cpp:178
#define todeg
Definition: mathlib.h:51
float * angles
Definition: cl_renderer.h:62
bool R_RenderbufferEnabled(void)
sphere_t r_globeEarthAtmosphere
Definition: r_sphere.cpp:35
#define GL_SOURCE1_RGB
void R_DrawTexture(int texnum, int x, int y, int w, int h)
Bind and draw a texture.
Definition: r_draw.cpp:328
#define fbo_render
Definition: r_state.h:88
#define STANDARD_3D_ZOOM
Typical zoom to use on the 3D geoscape to use same zoom values for both 2D and 3D geoscape...
Definition: r_geoscape.h:32
float * center
Definition: cl_renderer.h:64
GLsizei size
Definition: r_gl.h:152
rendererData_t refdef
Definition: r_main.cpp:45
static void R_Blur(r_framebuffer_t *source, r_framebuffer_t *dest, int tex, int dir)
does 1D filter convolution to blur a framebuffer texture. dir=0 for horizontal, dir=1 for vertical ...
Definition: r_geoscape.cpp:723
#define OBJZERO(obj)
Definition: shared.h:178
#define DOWNSAMPLE_PASSES
Definition: r_state.h:84
#define Vector4Set(v, r, g, b, a)
Definition: vector.h:62
#define texunit_1
Definition: r_state.h:62
#define M_PI
Definition: mathlib.h:34
image_t * texture
Definition: r_sphere.h:32
static void R_BlurStack(int levels, r_framebuffer_t **sources, r_framebuffer_t **dests)
blur from the source image pyramid into the dest image pyramid
Definition: r_geoscape.cpp:738
#define SKYBOX_HALFSIZE
Half size of Skybox.
Definition: r_geoscape.cpp:304
model_t * model
Definition: cl_renderer.h:58
#define GL_SOURCE2_RGB
#define GL_SOURCE0_RGB
#define PITCH
Definition: mathlib.h:54
r_program_t * geoscape_program
Definition: r_state.h:135
void R_BindDefaultArray(GLenum target)
Binds the appropriate shared vertex array to the specified target.
Definition: r_state.cpp:182
model_t * R_FindModel(const char *name)
Tries to load a model.
Definition: r_model.cpp:203
viddefContext_t context
Definition: cl_video.h:67
QGL_EXTERN GLenum GLuint * dest
Definition: r_gl.h:101
void R_ModelAutoScale(const vec2_t boxSize, modelInfo_t *mi, vec3_t scale, vec3_t center)
Compute scale and center for a model info data structure.
Definition: r_mesh.cpp:278
sphere_t r_globeEarth
Definition: r_sphere.cpp:33
#define GL_SOURCE0_ALPHA
#define default_program
Definition: r_state.h:92
QGL_EXTERN GLfloat f
Definition: r_gl.h:114
void R_DrawBuffers(unsigned int drawBufferNum)
Activate draw buffer(s)
char lodDir[8]
Definition: r_local.h:178
float blendScale
Definition: r_sphere.h:41
#define Vector2FromInt(x, y)
Definition: vector.h:40
#define texunit_0
Definition: r_state.h:61
#define texunit_diffuse
Definition: r_state.h:68
void R_SphereRender(const sphere_t *sphere, const vec3_t pos, const vec3_t rotate, const float scale, const vec4_t lightPos)
Draw the sphere.
Definition: r_sphere.cpp:247
static void R_RotateCelestialBody(const vec4_t v, vec4_t r, const vec3_t rotate, const vec3_t earthPos, const float celestialDist)
rotate a planet (sun or moon) with respect to the earth
Definition: r_geoscape.cpp:405
r_framebuffer_t * buffers0[DOWNSAMPLE_PASSES]
Definition: r_state.h:123
image_t * overlay
Definition: r_sphere.h:34
QGL_EXTERN GLint i
Definition: r_gl.h:113
float glowScale
Definition: r_sphere.h:42
#define SKYBOX_DEPTH
Center position of skybox along z-axis. This is used to make sure we see only the inside of Skybox...
Definition: r_state.h:41
void R_Draw3DGlobe(const vec2_t pos, const vec2_t size, int day, int second, const vec3_t rotate, float zoom, const char *map, bool disableSolarRender, float ambient, bool overlayNation, bool overlayXVI, bool overlayRadar, image_t *r_xviTexture, image_t *r_radarTexture, bool renderNationGlow)
responsible for drawing the 3d globe on geoscape param[in] rotate the rotate angle of the globe param...
Definition: r_geoscape.cpp:428
#define SECONDS_PER_DAY
Definition: common.h:301
Error checking function.
image_t * r_dayandnightTexture
#define MARKER_SIZE
Definition: r_geoscape.cpp:33
vec_t vec3_t[3]
Definition: ufotypes.h:39
vec_t vec2_t[2]
Definition: ufotypes.h:38
void R_EnableBlur(r_program_t *program, bool enable, r_framebuffer_t *source, r_framebuffer_t *dest, int dir)
Definition: r_state.cpp:523
void R_FreeImage(image_t *image)
Free the image and its assigned maps (roughness, normal, specular, glow - if there are any) ...
Definition: r_image.cpp:735
rstate_t r_state
Definition: r_main.cpp:48
#define fbo_bloom1
Definition: r_state.h:90
vec4_t nightLightPos
Definition: r_sphere.h:43
static const float starFieldTexCoords[]
Definition: r_geoscape.cpp:344
#define R_CheckError()
Definition: r_error.h:30
void R_DrawBloom(void)
handle post-processing bloom
Definition: r_geoscape.cpp:760
r_framebuffer_t * buffers1[DOWNSAMPLE_PASSES]
Definition: r_state.h:124
void R_DrawFlatGeoscape(const vec2_t nodePos, const vec2_t nodeSize, float p, float cx, float cy, float iz, const char *map, bool overlayNation, bool overlayXVI, bool overlayRadar, image_t *r_dayandnightTexture, image_t *r_xviTexture, image_t *r_radarTexture)
Draw the day and night images of a flat geoscape multitexture feature is used to blend the images...
Definition: r_geoscape.cpp:48
r_program_t * convolve_program
Definition: r_state.h:136
void R_ResolveMSAA(const r_framebuffer_t *buf)
Forces multisample antialiasing resolve on given framebuffer, if needed.
unsigned height
Definition: cl_video.h:45
float ry
Definition: cl_video.h:72
image_t * overlayAlphaMask
Definition: r_sphere.h:35
Functions to generate and render spheres.
void R_UseViewport(const r_framebuffer_t *buf)
Set the viewport to the dimensions of the given framebuffer.
#define fbo_screen
Definition: r_state.h:87
QGL_EXTERN int GLboolean GLfloat * v
Definition: r_gl.h:120
image_t * normalMap
Definition: r_sphere.h:36
static struct mdfour * m
Definition: md4.cpp:35
void R_BindTextureForTexUnit(GLuint texnum, gltexunit_t *texunit)
Definition: r_state.cpp:77
#define R_BindTexture(tn)
Definition: r_state.h:184
r_program_t * glslProgram
Definition: r_sphere.h:40
sphere_t r_globeMoon
Definition: r_sphere.cpp:34
bool R_SelectTexture(gltexunit_t *texunit)
Returns false if the texunit is not supported.
Definition: r_state.cpp:40
void R_BindArray(GLenum target, GLenum type, const void *array)
Definition: r_state.cpp:148
GLuint texnum
Definition: r_image.h:66
vec_t vec4_t[4]
Definition: ufotypes.h:40