UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
r_state.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_program.h"
27 #include "r_error.h"
28 
29 /* useful for particles, pics, etc.. */
31  {0.0, 0.0}, {1.0, 0.0}, {1.0, 1.0}, {0.0, 1.0}
32 };
33 
34 /* Hack to keep track of active rendering program (have to reinit binings&parameters once it changed)*/
35 static r_program_t* lastProgram = nullptr;
36 
41 {
42  if (texunit == r_state.active_texunit)
43  return true;
44 
45  /* not supported */
46  if (texunit->texture >= r_config.maxTextureCoords + GL_TEXTURE0)
47  return false;
48 
49  r_state.active_texunit = texunit;
50 
51  qglActiveTexture(texunit->texture);
52  qglClientActiveTexture(texunit->texture);
53  return true;
54 }
55 
56 static void R_BindTexture_ (int texnum)
57 {
58  if (texnum == r_state.active_texunit->texnum)
59  return;
60 
61  assert(texnum > 0);
62 
63  r_state.active_texunit->texnum = texnum;
64 
65  glBindTexture(GL_TEXTURE_2D, texnum);
66  R_CheckError();
67 }
68 
69 void R_BindTextureDebug (int texnum, const char* file, int line, const char* function)
70 {
71  if (texnum <= 0) {
72  Com_Printf("Bad texnum (%d) in: %s (%d): %s\n", texnum, file, line, function);
73  }
74  R_BindTexture_(texnum);
75 }
76 
78 {
79  /* small optimization to save state changes */
80  if (texnum == texunit->texnum)
81  return;
82 
83  R_SelectTexture(texunit);
84 
85  R_BindTexture(texnum);
86 
88 }
89 
91 {
93 }
94 
96 {
98 }
99 
101 {
103 }
104 
105 void R_UseMaterial (const material_t* material)
106 {
107  static float last_b, last_p, last_s, last_h;
108  float b;
109 
110  if (r_state.active_material == material)
111  return;
112 
114  return;
115 
116  if (material)
117  r_state.active_material = material;
118  else
120 
122  if (b != last_b)
123  R_ProgramParameter1f("BUMP", b);
124  last_b = b;
125 
127  const float p = r_state.active_material->parallax * r_parallax->value;
128  if (p != last_p)
129  R_ProgramParameter1f("PARALLAX", p);
130  last_p = p;
131 
132  const float h = r_state.active_material->hardness * r_hardness->value;
133  if (h != last_h)
134  R_ProgramParameter1f("HARDNESS", h);
135  last_h = h;
136 
137  const float s = r_state.active_material->specular * r_specular->value;
138  if (s != last_s)
139  R_ProgramParameter1f("SPECULAR", s);
140  last_s = s;
141  } else {
142  last_p = -1;
143  last_h = -1;
144  last_s = -1;
145  }
146 }
147 
148 void R_BindArray (GLenum target, GLenum type, const void* array)
149 {
150  const int v = static_cast<int>(target);
151  switch (v) {
152  case GL_VERTEX_ARRAY:
153  glVertexPointer(COMPONENTS_VERTEX_ARRAY3D, type, 0, array);
154  break;
155  case GL_TEXTURE_COORD_ARRAY:
156  glTexCoordPointer(COMPONENTS_TEXCOORD_ARRAY, type, 0, array);
157  break;
158  case GL_COLOR_ARRAY:
159  glColorPointer(COMPONENTS_COLOR_ARRAY, type, 0, array);
160  break;
161  case GL_NORMAL_ARRAY:
162  glNormalPointer(type, 0, array);
163  break;
164  case GL_TANGENT_ARRAY:
165  R_AttributePointer("TANGENTS", COMPONENTS_TANGENT_ARRAY, array);
166  break;
168  R_AttributePointer("NEXT_FRAME_VERTS", COMPONENTS_VERTEX_ARRAY3D, array);
169  break;
171  R_AttributePointer("NEXT_FRAME_NORMALS", COMPONENTS_NORMAL_ARRAY, array);
172  break;
174  R_AttributePointer("NEXT_FRAME_TANGENTS", COMPONENTS_TANGENT_ARRAY, array);
175  break;
176  }
177 }
178 
183 {
184  const int v = static_cast<int>(target);
185  switch (v) {
186  case GL_VERTEX_ARRAY:
187  R_BindArray(target, GL_FLOAT, r_state.vertex_array_3d);
188  break;
189  case GL_TEXTURE_COORD_ARRAY:
190  R_BindArray(target, GL_FLOAT, r_state.active_texunit->texcoord_array);
191  break;
192  case GL_COLOR_ARRAY:
193  R_BindArray(target, GL_FLOAT, r_state.color_array);
194  break;
195  case GL_NORMAL_ARRAY:
196  R_BindArray(target, GL_FLOAT, r_state.normal_array);
197  break;
198  case GL_TANGENT_ARRAY:
199  R_BindArray(target, GL_FLOAT, r_state.tangent_array);
200  break;
202  R_BindArray(target, GL_FLOAT, r_state.next_vertex_array_3d);
203  break;
205  R_BindArray(target, GL_FLOAT, r_state.next_normal_array);
206  break;
208  R_BindArray(target, GL_FLOAT, r_state.next_tangent_array);
209  break;
210  }
211 }
212 
214 {
215  if (!qglBindBuffer)
216  return;
217 
218  if (!r_vertexbuffers->integer)
219  return;
220 
221  if (target == GL_ELEMENT_ARRAY_BUFFER) {
222  qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, id);
223  return; /* No need to call gl***Poiner -- this binding is special and automates that */
224  } else {
225  qglBindBuffer(GL_ARRAY_BUFFER, id);
226  }
227 
228  if (type && id) /* assign the array pointer as well */
229  R_BindArray(target, type, nullptr);
230 }
231 
233 {
234  if (r_state.blend_src == src && r_state.blend_dest == dest)
235  return;
236 
237  r_state.blend_src = src;
239 
240  glBlendFunc(src, dest);
241 }
242 
243 void R_EnableMultisample (bool enable)
244 {
245  if (r_multisample->integer == 0 && enable)
246  return;
247 
248  if (r_state.multisample_enabled == enable)
249  return;
250 
251  r_state.multisample_enabled = enable;
252 
253  if (enable) {
254  glEnable(GL_MULTISAMPLE);
255  } else {
256  glDisable(GL_MULTISAMPLE);
257  }
258  R_CheckError();
259 }
260 
261 void R_EnableBlend (bool enable)
262 {
263  if (r_state.blend_enabled == enable)
264  return;
265 
266  r_state.blend_enabled = enable;
267 
268  if (enable) {
269  glEnable(GL_BLEND);
270  glDepthMask(GL_FALSE);
271  } else {
272  glDisable(GL_BLEND);
273  glDepthMask(GL_TRUE);
274  }
275 }
276 
277 void R_EnableAlphaTest (bool enable)
278 {
279  if (r_state.alpha_test_enabled == enable)
280  return;
281 
282  r_state.alpha_test_enabled = enable;
283 
284  if (enable)
285  glEnable(GL_ALPHA_TEST);
286  else
287  glDisable(GL_ALPHA_TEST);
288 }
289 
290 void R_EnableStencilTest (bool enable)
291 {
292  if (r_state.stencil_test_enabled == enable)
293  return;
294 
295  r_state.stencil_test_enabled = enable;
296 
297  if (enable)
298  glEnable(GL_STENCIL_TEST);
299  else
300  glDisable(GL_STENCIL_TEST);
301 }
302 
303 void R_EnableTexture (gltexunit_t* texunit, bool enable)
304 {
305  if (enable == texunit->enabled)
306  return;
307 
308  texunit->enabled = enable;
309 
310  R_SelectTexture(texunit);
311 
312  if (enable) {
313  /* activate texture unit */
314  glEnable(GL_TEXTURE_2D);
315 
316  glEnableClientState(GL_TEXTURE_COORD_ARRAY);
317 
318  if (texunit == &texunit_lightmap) {
319  if (r_lightmap->integer)
320  R_TexEnv(GL_REPLACE);
321  else
322  R_TexEnv(GL_MODULATE);
323  }
324  } else {
325  /* disable on the second texture unit */
326  glDisable(GL_TEXTURE_2D);
327  glDisableClientState(GL_TEXTURE_COORD_ARRAY);
328  }
330 }
331 
332 void R_EnableColorArray (bool enable)
333 {
334  if (r_state.color_array_enabled == enable)
335  return;
336 
337  r_state.color_array_enabled = enable;
338 
339  if (enable)
340  glEnableClientState(GL_COLOR_ARRAY);
341  else
342  glDisableClientState(GL_COLOR_ARRAY);
343 }
344 
350 bool R_EnableLighting (r_program_t* program, bool enable)
351 {
352  if (!r_programs->integer)
353  return r_state.lighting_enabled;
354 
355  if (enable && (!program || !program->id))
356  return r_state.lighting_enabled;
357 
358  if (r_state.lighting_enabled == enable && r_state.active_program == program)
359  return r_state.lighting_enabled;
360 
361  r_state.lighting_enabled = enable;
362 
363  if (enable) { /* toggle state */
364  R_UseProgram(program);
365 
366  glEnableClientState(GL_NORMAL_ARRAY);
367  } else {
368  glDisableClientState(GL_NORMAL_ARRAY);
369 
370  R_UseProgram(nullptr);
371  }
372 
373  return r_state.lighting_enabled;
374 }
375 
376 void R_SetupSpotLight (int index, const light_t* light)
377 {
378  const vec4_t blackColor = {0.0, 0.0, 0.0, 1.0};
379  vec4_t position;
380 
382  return;
383 
384  if (index < 0 || index >= r_dynamic_lights->integer)
385  return;
386 
387  index += GL_LIGHT0;
388 
389  glEnable(index);
390  glLightf(index, GL_CONSTANT_ATTENUATION, MIN_GL_CONSTANT_ATTENUATION);
391  glLightf(index, GL_LINEAR_ATTENUATION, 0);
392  glLightf(index, GL_QUADRATIC_ATTENUATION, 16.0 / (light->radius * light->radius));
393 
394  VectorCopy(light->origin, position);
395  position[3] = 1.0; /* spot light */
396 
397  glLightfv(index, GL_POSITION, position);
398  glLightfv(index, GL_AMBIENT, blackColor);
399  glLightfv(index, GL_DIFFUSE, light->color);
400  glLightfv(index, GL_SPECULAR, blackColor);
401 }
402 
404 {
405  const vec4_t blackColor = {0.0, 0.0, 0.0, 1.0};
406 
408  return;
409 
410  if (index < 0 || index >= MAX_GL_LIGHTS - 1)
411  return;
412 
413  index += GL_LIGHT0;
414 
415  glDisable(index);
416  glLightf(index, GL_CONSTANT_ATTENUATION, MIN_GL_CONSTANT_ATTENUATION);
417  glLightf(index, GL_LINEAR_ATTENUATION, 0.0);
418  glLightf(index, GL_QUADRATIC_ATTENUATION, 0.0);
419  glLightfv(index, GL_AMBIENT, blackColor);
420  glLightfv(index, GL_DIFFUSE, blackColor);
421  glLightfv(index, GL_SPECULAR, blackColor);
422 }
423 
430 void R_EnableAnimation (const mAliasMesh_t* mesh, float backlerp, bool enable)
431 {
433  return;
434 
435  r_state.animation_enabled = enable;
436 
437  if (enable) {
438  R_EnableAttribute("NEXT_FRAME_VERTS");
439  R_EnableAttribute("NEXT_FRAME_NORMALS");
440  R_EnableAttribute("NEXT_FRAME_TANGENTS");
441  R_ProgramParameter1i("ANIMATE", 1);
442 
443  R_ProgramParameter1f("TIME", backlerp);
444 
445  R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, mesh->texcoords);
446  R_BindArray(GL_VERTEX_ARRAY, GL_FLOAT, mesh->verts);
447  R_BindArray(GL_NORMAL_ARRAY, GL_FLOAT, mesh->normals);
448  R_BindArray(GL_TANGENT_ARRAY, GL_FLOAT, mesh->tangents);
449  R_BindArray(GL_NEXT_VERTEX_ARRAY, GL_FLOAT, mesh->next_verts);
452  } else {
453  R_DisableAttribute("NEXT_FRAME_VERTS");
454  R_DisableAttribute("NEXT_FRAME_NORMALS");
455  R_DisableAttribute("NEXT_FRAME_TANGENTS");
456  R_ProgramParameter1i("ANIMATE", 0);
457  }
458 }
459 
465 void R_EnableBumpmap (const image_t* normalmap)
466 {
468  return;
469 
470  if (!r_bumpmap->value)
471  return;
472 
473  if (r_state.active_normalmap == normalmap)
474  return;
475 
476  if (!normalmap) {
477  /* disable bump mapping */
478  R_ProgramParameter1i("BUMPMAP", 0);
479 
480  r_state.active_normalmap = normalmap;
481  return;
482  }
483 
484  if (!r_state.active_normalmap) {
485  /* enable bump mapping */
486  R_ProgramParameter1i("BUMPMAP", 1);
487  /* default material to use if no material gets loaded */
489  }
490 
491  R_BindNormalmapTexture(normalmap->texnum);
492 
493  r_state.active_normalmap = normalmap;
494 }
495 
496 void R_EnableWarp (r_program_t* program, bool enable)
497 {
498  if (!r_programs->integer)
499  return;
500 
501  if (enable && (!program || !program->id))
502  return;
503 
504  if (!r_warp->integer || r_state.warp_enabled == enable)
505  return;
506 
507  r_state.warp_enabled = enable;
508 
510 
511  if (enable) {
512  glEnable(GL_TEXTURE_2D);
514  R_UseProgram(program);
515  } else {
516  glDisable(GL_TEXTURE_2D);
517  R_UseProgram(nullptr);
518  }
519 
521 }
522 
523 void R_EnableBlur (r_program_t* program, bool enable, r_framebuffer_t* source, r_framebuffer_t* dest, int dir)
524 {
525  if (!r_programs->integer)
526  return;
527 
528  if (enable && (!program || !program->id))
529  return;
530 
531  if (!r_postprocess->integer || r_state.blur_enabled == enable)
532  return;
533 
534  r_state.blur_enabled = enable;
535 
537 
538  if (enable) {
539  float userdata[] = { static_cast<float>(source->width), static_cast<float>(dir) };
540  R_UseFramebuffer(dest);
541  program->userdata = userdata;
542  R_UseProgram(program);
543  } else {
545  R_UseProgram(nullptr);
546  }
547 
549 }
550 
551 void R_EnableShell (bool enable)
552 {
553  if (enable == r_state.shell_enabled)
554  return;
555 
556  r_state.shell_enabled = enable;
557 
558  if (enable) {
559  glEnable(GL_POLYGON_OFFSET_FILL);
560  glPolygonOffset(-1.0, 1.0);
561 
562  R_EnableDrawAsGlow(true);
563  R_EnableBlend(true);
564  R_BlendFunc(GL_SRC_ALPHA, GL_ONE);
565 
567  R_ProgramParameter1f("OFFSET", refdef.time / 3.0);
568  } else {
569  R_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
570  R_EnableBlend(false);
571  R_EnableDrawAsGlow(false);
572 
573  glPolygonOffset(0.0, 0.0);
574  glDisable(GL_POLYGON_OFFSET_FILL);
575 
577  R_ProgramParameter1f("OFFSET", 0.0);
578  }
579 }
580 
581 #define FOG_START 300.0
582 #define FOG_END 2500.0
583 
585 
586 void R_EnableFog (bool enable)
587 {
588  if (!r_fog->integer || r_state.fog_enabled == enable)
589  return;
590 
591  r_state.fog_enabled = false;
592 
593  /* This is ugly. Shaders could be enabled or disabled between this and rendering call, so we have to setup both FFP and GLSL */
594  if (enable) {
595  if (((refdef.weather & WEATHER_FOG) && r_fog->integer) || r_fog->integer == 2) {
596  r_state.fog_enabled = true;
597 
598  glFogfv(GL_FOG_COLOR, refdef.fogColor);
599  glFogf(GL_FOG_DENSITY, refdef.fogColor[3]);
600  glEnable(GL_FOG);
601 
604  R_ProgramParameter1f("FOGDENSITY", refdef.fogColor[3]);
605  R_ProgramParameter2fv("FOGRANGE", fogRange);
606  }
607  }
608  } else {
609  glFogf(GL_FOG_DENSITY, 0.0);
610  glDisable(GL_FOG);
612  R_ProgramParameter1f("FOGDENSITY", 0.0f);
613  }
614 }
615 
616 static void R_UpdateGlowBufferBinding (void)
617 {
618 #ifndef GL_VERSION_ES_CM_1_0
619  static GLenum glowRenderTarget = GL_COLOR_ATTACHMENT1_EXT; // Not supported in GLES
620 
621  if (r_state.active_program) {
622  /* got an active shader */
624  /* switch the draw buffer to the glow buffer */
625  R_BindColorAttachments(1, &glowRenderTarget);
626  R_ProgramParameter1f("GLOWSCALE", 0.0); /* Plumbing to avoid state leak */
627  } else {
628  /* switch back to the draw buffer we are currently rendering into ... */
629  R_DrawBuffers(2);
630  /* ... and enable glow, if there is a glow map */
631  if (r_state.glowmap_enabled) {
632  R_ProgramParameter1f("GLOWSCALE", 1.0);
633  } else {
634  R_ProgramParameter1f("GLOWSCALE", 0.0);
635  }
636  }
637  } else {
638  /* no shader */
640  /* switch the draw buffer to the glow buffer */
641  R_BindColorAttachments(1, &glowRenderTarget);
642  } else {
643  if (!r_state.glowmap_enabled) {
644  /* Awkward case. Postprocessing is requested, but fragment
645  * shader is disabled, and we are supposed to draw non-glowing object.
646  * So we just draw this object into color buffer only and hope that it's not
647  * supposed to overlay any glowing objects.
648  */
649  R_DrawBuffers(1);
650  } else {
651  /* FIXME: Had to draw glowmapped object, but don't know how to do it
652  * when rendering through FFP.
653  * So -- just copy color into glow buffer.
654  * (R_DrawAsGlow may hit this)
655  */
656  R_DrawBuffers(2);
657  /*Con_Print("GLSL glow with no program!\n");*/
658  }
659  }
660  }
661 #endif
662 }
663 
664 void R_EnableGlowMap (const image_t* image)
665 {
666  if (!r_programs->integer)
667  return;
668 
669  if (image)
671 
673  if (!image && r_state.glowmap_enabled == !!image && r_state.active_program == lastProgram)
674  return;
675 
676  r_state.glowmap_enabled = !!image;
677 
678  /* Shouldn't render glow without GLSL, so enable simple program for it */
679  if (image) {
680  if (!r_state.active_program)
682  } else {
684  R_UseProgram(nullptr);
685  }
686 
687  lastProgram = r_state.active_program;
688 
690 }
691 
692 void R_EnableDrawAsGlow (bool enable)
693 {
694  if (!r_programs->integer)
695  return;
696 
697  if (r_state.draw_glow_enabled == enable && r_state.active_program == lastProgram)
698  return;
699 
700  r_state.draw_glow_enabled = enable;
701 
702  lastProgram = r_state.active_program;
703 
705 }
706 
707 void R_EnableSpecularMap (const image_t* image, bool enable)
708 {
710  return;
711 
712  if (r_programs->integer < 2)
713  return;
714 
715  if (enable && image != nullptr) {
717  R_ProgramParameter1i("SPECULARMAP", 1);
718  r_state.specularmap_enabled = enable;
719  } else {
720  R_ProgramParameter1i("SPECULARMAP", 0);
722  }
723 }
724 
725 void R_EnableRoughnessMap (const image_t* image, bool enable)
726 {
728  return;
729 
730  if (enable && image != nullptr) {
732  R_ProgramParameter1i("ROUGHMAP", 1);
733  r_state.roughnessmap_enabled = enable;
734  } else {
735  R_ProgramParameter1i("ROUGHMAP", 0);
737  }
738 }
739 
743 static void MYgluPerspective (GLfloat zNear, GLfloat zFar)
744 {
745  GLfloat xmin, xmax, ymin, ymax, yaspect = (float) viddef.context.height / viddef.context.width;
746 
747  if (r_isometric->integer) {
748  glOrtho(-10 * refdef.fieldOfViewX, 10 * refdef.fieldOfViewX, -10 * refdef.fieldOfViewX * yaspect, 10 * refdef.fieldOfViewX * yaspect, -zFar, zFar);
749  } else {
750  xmax = zNear * tan(refdef.fieldOfViewX * (M_PI / 360.0));
751  xmin = -xmax;
752 
753  ymin = xmin * yaspect;
754  ymax = xmax * yaspect;
755 
756  glFrustum(xmin, xmax, ymin, ymax, zNear, zFar);
757  }
758 }
759 
763 void R_Setup3D (void)
764 {
765  /* only for the battlescape rendering */
766  if ((refdef.rendererFlags & RDF_NOWORLDMODEL) == 0) {
767  int x, x2, y2, y, w, h;
768 
769  /* set up viewport */
770  x = floorf(viddef.x * viddef.context.width / viddef.context.width);
774 
775  w = x2 - x;
776  h = y - y2;
777 
778  glViewport(x, y2, w, h);
779  R_CheckError();
780  }
781 
782  /* set up projection matrix */
783  glMatrixMode(GL_PROJECTION);
784 
785  glLoadIdentity();
786  if ((refdef.rendererFlags & RDF_NOWORLDMODEL) != 0) {
787  /* center image into the viewport */
788  float x = viddef.x + (viddef.viewWidth - VID_NORM_WIDTH) / 2.0 - (viddef.virtualWidth - VID_NORM_WIDTH) / 2.0;
789  float y = viddef.y + (viddef.viewHeight - VID_NORM_HEIGHT) / 2.0 - (viddef.virtualHeight - VID_NORM_HEIGHT) / 2.0;
790  /* @todo magic coef, i dont know where it come from */
791  x *= 2.0f / (float) viddef.virtualWidth;
792  y *= 2.0f / (float) viddef.virtualHeight;
793  glTranslatef(x, -y, 0.0f);
794  }
796 
797  glMatrixMode(GL_MODELVIEW);
798  glLoadIdentity();
799  glRotatef(-90.0, 1.0, 0.0, 0.0); /* put Z going up */
800  glRotatef(90.0, 0.0, 0.0, 1.0); /* put Z going up */
801  glRotatef(-refdef.viewAngles[2], 1.0, 0.0, 0.0);
802  glRotatef(-refdef.viewAngles[0], 0.0, 1.0, 0.0);
803  glRotatef(-refdef.viewAngles[1], 0.0, 0.0, 1.0);
804  glTranslatef(-refdef.viewOrigin[0], -refdef.viewOrigin[1], -refdef.viewOrigin[2]);
805 
806  /* retrieve the resulting matrix for other manipulations */
807  glGetFloatv(GL_MODELVIEW_MATRIX, r_locals.world_matrix);
808 
809  /* set vertex array pointer */
810  R_BindDefaultArray(GL_VERTEX_ARRAY);
811 
812  glDisable(GL_BLEND);
813 
814  glEnable(GL_DEPTH_TEST);
815 
816  /* set up framebuffers for postprocessing */
817  R_EnableRenderbuffer(true);
818 
819  R_CheckError();
820 }
821 
825 void R_Setup2D (void)
826 {
827  /* only for the battlescape rendering */
828  if ((refdef.rendererFlags & RDF_NOWORLDMODEL) == 0) {
829  /* set 2D virtual screen size */
830  glViewport(0, 0, viddef.context.width, viddef.context.height);
831  }
832 
833  glMatrixMode(GL_PROJECTION);
834  glLoadIdentity();
835 
836  /* switch to orthographic (2 dimensional) projection
837  * don't draw anything before skybox */
838  glOrtho(0, viddef.context.width, viddef.context.height, 0, 9999.0f, SKYBOX_DEPTH);
839 
840  glMatrixMode(GL_MODELVIEW);
841  glLoadIdentity();
842 
843  /* bind default vertex array */
844  R_BindDefaultArray(GL_VERTEX_ARRAY);
845 
846  R_Color(nullptr);
847 
848  glEnable(GL_BLEND);
849 
850  glDisable(GL_DEPTH_TEST);
851 
852  glDisable(GL_LIGHTING);
853 
854  /* disable render-to-framebuffer */
855  R_EnableRenderbuffer(false);
856 
857  R_CheckError();
858 }
859 
860 void R_SetDefaultState (void)
861 {
862  r_state.shell_enabled = false;
863  r_state.blend_enabled = false;
865  r_state.alpha_test_enabled = false;
867  r_state.lighting_enabled = false;
868  r_state.warp_enabled = false;
869  r_state.fog_enabled = false;
870  r_state.blur_enabled = false;
871  r_state.glowmap_enabled = false;
872  r_state.draw_glow_enabled = false;
876  r_state.animation_enabled = false;
878  r_state.active_material = nullptr;
879  r_state.blend_src = 0;
880  r_state.blend_dest = 0;
881  r_state.active_texunit = nullptr;
882 
883  glClearColor(0, 0, 0, 0);
884 
885  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
886 
893 
894  /* setup vertex array pointers */
895  glEnableClientState(GL_VERTEX_ARRAY);
896  R_BindDefaultArray(GL_VERTEX_ARRAY);
897 
898  R_EnableColorArray(true);
899  R_BindDefaultArray(GL_COLOR_ARRAY);
900  R_EnableColorArray(false);
901 
902  glEnableClientState(GL_NORMAL_ARRAY);
903  R_BindDefaultArray(GL_NORMAL_ARRAY);
904  glDisableClientState(GL_NORMAL_ARRAY);
905 
906  R_EnableAlphaTest(false);
907 
908  /* reset gl error state */
909  R_CheckError();
910 
911  /* setup texture units */
912  for (int i = 0; i < r_config.maxTextureCoords && i < MAX_GL_TEXUNITS; i++) {
913  gltexunit_t* tex = &r_state.texunits[i];
914  tex->texture = GL_TEXTURE0 + i;
915  tex->enabled = false;
916 
917  R_EnableTexture(tex, true);
918 
919  R_BindDefaultArray(GL_TEXTURE_COORD_ARRAY);
920  R_TexEnv(GL_MODULATE);
922 
923  if (i > 0) /* turn them off for now */
924  R_EnableTexture(tex, false);
925 
926  R_CheckError();
927  }
928 
930  /* alpha test parameters */
931  glAlphaFunc(GL_GREATER, 0.01f);
932 
933  /* fog parameters */
934  glFogi(GL_FOG_MODE, GL_LINEAR);
935  glFogf(GL_FOG_START, FOG_START);
936  glFogf(GL_FOG_END, FOG_END);
937 
938  /* stencil test parameters */
939  glStencilFunc(GL_GEQUAL, 1, 0xff);
940  glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
941 
942  /* polygon offset parameters */
943  glPolygonOffset(1, 1);
944 
945  /* alpha blend parameters */
946  R_EnableBlend(true);
947  R_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
948 
949  /* remove leftover lights */
951 
952  /* reset gl error state */
953  R_CheckError();
954 }
955 
957 {
958  if (mode == r_state.active_texunit->texenv)
959  return;
960 
961  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, mode);
963 }
964 
969 {
970  R_SelectTexture(&texunit_lightmap); /* abuse lightmap texture unit for color manipulation */
971 
972  if (!rgba) {
973  R_TexEnv(GL_MODULATE);
974  glDisable(GL_TEXTURE_2D);
976  return;
977  }
978 
979  glEnable(GL_TEXTURE_2D);
980 
981  R_TexEnv(GL_COMBINE); /* enable color combiner */
982  /* setup texture combiner to blend between actual color of previous texture stage and the constant rgb color given as the parameter to this function
983  * amount of blending is defined by alpha channel of constant color
984  */
985  glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_CONSTANT); /* set constant color as blending target*/
986  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
987  glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS); /* set incoming color as blending source */
988  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
989  glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_CONSTANT); /* set constant color alpha as blending factor */
990  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);
991  glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); /* set blending mode to interpolation from src1 to src0 */
992  /* copy alpha from incoming color, it could be used later for framebuffer operations */
993  glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
994  glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
995  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
996 
997  glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, rgba);
998 
1000 
1002 }
1003 
1004 const vec4_t color_white = {1, 1, 1, 1};
1005 
1011 void R_Color (const vec4_t rgba)
1012 {
1013  const float* color;
1014  if (rgba)
1015  color = rgba;
1016  else
1017  color = color_white;
1018 
1019  glColor4f(color[0], color[1], color[2], color[3]);
1020  R_CheckError();
1021 }
1022 
1030 {
1031  if (size <= r_state.array_size)
1032  return;
1035  r_state.color_array = (GLfloat*) Mem_SafeReAlloc(r_state.color_array, size * COMPONENTS_COLOR_ARRAY * sizeof(GLfloat));
1037  r_state.normal_array = (GLfloat*) Mem_SafeReAlloc(r_state.normal_array, size * COMPONENTS_NORMAL_ARRAY * sizeof(GLfloat));
1038  r_state.tangent_array = (GLfloat*) Mem_SafeReAlloc(r_state.tangent_array, size * COMPONENTS_TANGENT_ARRAY * sizeof(GLfloat));
1043  R_BindDefaultArray(GL_VERTEX_ARRAY);
1044  R_BindDefaultArray(GL_COLOR_ARRAY);
1045  R_BindDefaultArray(GL_NORMAL_ARRAY);
1050 }
1051 
1060 {
1061  if (size <= texunit->array_size)
1062  return;
1063  texunit->texcoord_array = (GLfloat*) Mem_SafeReAlloc(texunit->texcoord_array, size * COMPONENTS_TEXCOORD_ARRAY * sizeof(GLfloat));
1064  texunit->array_size = size;
1065  if (!r_state.active_texunit)
1066  r_state.active_texunit = texunit;
1067  R_BindDefaultArray(GL_TEXTURE_COORD_ARRAY);
1068 }
void R_EnableDrawAsGlow(bool enable)
Definition: r_state.cpp:692
bool R_EnableRenderbuffer(bool enable)
Enable the render to the framebuffer.
#define texunit_specularmap
Definition: r_state.h:73
cvar_t * r_bumpmap
Definition: r_main.cpp:103
void R_DisableAttribute(const char *name)
Definition: r_program.cpp:231
#define texunit_glowmap
Definition: r_state.h:72
void R_UseProgram(r_program_t *prog)
Definition: r_program.cpp:43
r_program_t * warp_program
Definition: r_state.h:134
bool fog_enabled
Definition: r_state.h:156
image_t * r_dummyTexture
Definition: r_main.cpp:53
#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 GL_TANGENT_ARRAY
Definition: r_gl.h:76
void R_EnableBumpmap(const image_t *normalmap)
Enables bumpmapping and binds the given normalmap.
Definition: r_state.cpp:465
void * userdata
Definition: r_program.h:62
void R_TexEnv(GLenum mode)
Definition: r_state.cpp:956
#define MAX_GL_TEXUNITS
Definition: r_state.h:58
int viewHeight
Definition: cl_video.h:76
void glBindTexture(GLenum target, GLuint id)
Definition: gldummy.cpp:4
#define FOG_END
Definition: r_state.cpp:582
cvar_t * r_vertexbuffers
Definition: r_main.cpp:94
int maxTextureCoords
Definition: r_local.h:169
QGL_EXTERN GLint GLenum type
Definition: r_gl.h:94
bool roughnessmap_enabled
Definition: r_state.h:162
void R_ProgramParameter2fv(const char *name, GLfloat *value)
Definition: r_program.cpp:141
void R_BindBuffer(GLenum target, GLenum type, GLuint id)
Definition: r_state.cpp:213
void R_EnableAnimation(const mAliasMesh_t *mesh, float backlerp, bool enable)
Enables animation using keyframe interpolation on the GPU.
Definition: r_state.cpp:430
#define COMPONENTS_VERTEX_ARRAY3D
Definition: r_state.h:76
void R_EnableShell(bool enable)
Definition: r_state.cpp:551
void R_EnableStencilTest(bool enable)
Definition: r_state.cpp:290
bool multisample_enabled
Definition: r_state.h:150
vec_t * normals
r_program_t * active_program
Definition: r_state.h:140
void R_BindLightmapTexture(GLuint texnum)
Definition: r_state.cpp:90
void R_BindNormalmapTexture(GLuint texnum)
Definition: r_state.cpp:100
void R_EnableAlphaTest(bool enable)
Definition: r_state.cpp:277
float fieldOfViewX
Definition: cl_renderer.h:171
void R_DisableSpotLight(int index)
Definition: r_state.cpp:403
GLfloat * vertex_array_3d
Definition: r_state.h:100
bool warp_enabled
Definition: r_state.h:155
#define texunit_4
Definition: r_state.h:65
const GLenum *typedef GLint
Definition: r_gl.h:205
cvar_t * r_programs
Definition: r_main.cpp:97
void R_BlendFunc(GLenum src, GLenum dest)
Definition: r_state.cpp:232
void R_SetDefaultState(void)
Definition: r_state.cpp:860
int array_size
Definition: r_state.h:55
GLfloat * normal_array
Definition: r_state.h:104
float value
Definition: cvar.h:80
viddef_t viddef
Definition: cl_video.cpp:34
vec3_t viewAngles
Definition: cl_renderer.h:173
local graphics definitions
float bump
Definition: r_material.h:159
static r_program_t * lastProgram
Definition: r_state.cpp:35
cvar_t * r_dynamic_lights
Definition: r_main.cpp:96
#define MIN_GL_CONSTANT_ATTENUATION
Definition: r_local.h:45
GLenum texenv
Definition: r_state.h:52
unsigned width
Definition: cl_video.h:44
GLenum texture
Definition: r_state.h:50
void Com_Printf(const char *const fmt,...)
Definition: common.cpp:386
rconfig_t r_config
Definition: r_main.cpp:47
bool blur_enabled
Definition: r_state.h:157
vec_t * texcoords
int virtualHeight
Definition: cl_video.h:74
static void R_BindTexture_(int texnum)
Definition: r_state.cpp:56
bool animation_enabled
Definition: r_state.h:163
#define COMPONENTS_INDEX_ARRAY
Definition: r_state.h:79
QGL_EXTERN GLuint
Definition: r_gl.h:124
gltexunit_t texunits[MAX_GL_TEXUNITS]
Definition: r_state.h:114
cvar_t * r_postprocess
Definition: r_main.cpp:100
int integer
Definition: cvar.h:81
a light source
Definition: r_light.h:29
bool renderbuffer_enabled
Definition: r_state.h:164
#define texunit_lightmap
Definition: r_state.h:69
const GLuint *typedef GLuint *typedef GLenum
Definition: r_gl.h:190
void R_BindDeluxemapTexture(GLuint texnum)
Definition: r_state.cpp:95
GLshort * vertex_array_2d
Definition: r_state.h:101
void R_ClearStaticLights(void)
Remove all static light data.
Definition: r_light.cpp:300
bool lighting_enabled
Definition: r_state.h:154
void R_EnableMultisample(bool enable)
Definition: r_state.cpp:243
#define Mem_SafeReAlloc(ptr, size)
Definition: mem.h:45
cvar_t * r_multisample
Definition: r_main.cpp:90
vec3_t viewOrigin
Definition: cl_renderer.h:172
#define texunit_normalmap
Definition: r_state.h:71
#define FOG_START
Definition: r_state.cpp:581
void R_SetupSpotLight(int index, const light_t *light)
Definition: r_state.cpp:376
void R_Color(const vec4_t rgba)
Change the color to given value.
Definition: r_state.cpp:1011
GLfloat * tangent_array
Definition: r_state.h:105
GLenum blend_dest
Definition: r_state.h:143
float world_matrix[16]
Definition: r_local.h:112
#define GL_SOURCE1_RGB
bool draw_glow_enabled
Definition: r_state.h:159
int x
Definition: cl_video.h:76
vec2_t fogRange
Definition: r_state.cpp:584
gltexunit_t * active_texunit
Definition: r_state.h:117
void R_EnableWarp(r_program_t *program, bool enable)
Definition: r_state.cpp:496
GLsizei size
Definition: r_gl.h:152
bool enabled
Definition: r_state.h:49
void R_ReallocateTexunitArray(gltexunit_t *texunit, int size)
Reallocate texcoord array of the specified texunit, if needed.
Definition: r_state.cpp:1059
rendererData_t refdef
Definition: r_main.cpp:45
#define texunit_1
Definition: r_state.h:62
rlocals_t r_locals
Definition: r_main.cpp:49
void R_ProgramParameter3fv(const char *name, GLfloat *value)
Definition: r_program.cpp:161
GLuint id
Definition: r_program.h:55
#define M_PI
Definition: mathlib.h:34
vec_t * tangents
#define MAX_GL_LIGHTS
Definition: cl_renderer.h:55
void R_ProgramParameter1i(const char *name, GLint value)
Definition: r_program.cpp:111
#define GL_SOURCE2_RGB
#define GL_SOURCE0_RGB
int array_size
Definition: r_state.h:111
void R_EnableColorArray(bool enable)
Definition: r_state.cpp:332
texunits maintain multitexture state
Definition: r_state.h:48
vec_t * next_verts
GLfloat * next_vertex_array_3d
Definition: r_state.h:106
GLint * index_array
Definition: r_state.h:103
material_t defaultMaterial
Definition: r_material.cpp:34
void R_Setup2D(void)
Definition: r_state.cpp:825
#define WEATHER_FOG
Definition: cl_renderer.h:38
void R_BindDefaultArray(GLenum target)
Binds the appropriate shared vertex array to the specified target.
Definition: r_state.cpp:182
viddefContext_t context
Definition: cl_video.h:67
#define COMPONENTS_TANGENT_ARRAY
Definition: r_state.h:81
QGL_EXTERN GLenum GLuint * dest
Definition: r_gl.h:101
#define RDF_NOWORLDMODEL
Definition: cl_renderer.h:34
r_program_t * simple_glow_program
Definition: r_state.h:139
float specular
Definition: r_material.h:162
bool color_array_enabled
Definition: r_state.h:151
#define VID_NORM_WIDTH
Definition: cl_renderer.h:40
QGL_EXTERN GLuint index
Definition: r_gl.h:110
bool dynamic_lighting_enabled
Definition: r_state.h:160
#define GL_SOURCE0_ALPHA
QGL_EXTERN GLfloat f
Definition: r_gl.h:114
void R_DrawBuffers(unsigned int drawBufferNum)
Activate draw buffer(s)
#define COMPONENTS_COLOR_ARRAY
Definition: r_state.h:78
cvar_t * r_hardness
Definition: r_main.cpp:105
vec4_t color
Definition: r_light.h:31
void R_EnableRoughnessMap(const image_t *image, bool enable)
Definition: r_state.cpp:725
#define texunit_2
Definition: r_state.h:63
float parallax
Definition: r_material.h:160
#define texunit_0
Definition: r_state.h:61
#define GL_ARRAY_LENGTH_CHUNK
Definition: r_state.h:44
#define texunit_diffuse
Definition: r_state.h:68
cvar_t * r_lightmap
Definition: r_main.cpp:68
#define VID_NORM_HEIGHT
Definition: cl_renderer.h:41
vec_t * next_tangents
r_program_t * world_program
Definition: r_state.h:132
cvar_t * r_parallax
Definition: r_main.cpp:106
void R_EnableAttribute(const char *name)
Definition: r_program.cpp:221
bool shell_enabled
Definition: r_state.h:148
QGL_EXTERN GLint i
Definition: r_gl.h:113
#define COMPONENTS_VERTEX_ARRAY2D
Definition: r_state.h:77
int viewWidth
Definition: cl_video.h:76
const material_t * active_material
Definition: r_state.h:145
void R_EnableBlend(bool enable)
Definition: r_state.cpp:261
void R_AttributePointer(const char *name, GLuint size, const GLvoid *array)
Definition: r_program.cpp:211
#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
#define GL_NEXT_TANGENT_ARRAY
Definition: r_gl.h:79
vec3_t origin
Definition: r_light.h:30
#define GL_NEXT_NORMAL_ARRAY
Definition: r_gl.h:78
void R_UseMaterial(const material_t *material)
Definition: r_state.cpp:105
bool alpha_test_enabled
Definition: r_state.h:152
const char int mode
Definition: ioapi.h:41
cvar_t * r_isometric
Definition: r_main.cpp:63
GLfloat * next_normal_array
Definition: r_state.h:107
GLenum blend_src
Definition: r_state.h:143
Error checking function.
image_t * r_warpTexture
Definition: r_main.cpp:52
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_BindColorAttachments(unsigned int n, unsigned int *attachments)
Activate draw buffer(s)
void R_Setup3D(void)
Definition: r_state.cpp:763
#define MAX_WORLD_WIDTH
-MAX_WORLD_WIDTH up tp +MAX_WORLD_WIDTH
Definition: defines.h:288
bool R_EnableLighting(r_program_t *program, bool enable)
Enables hardware-accelerated lighting with the specified program. This should be called after any tex...
Definition: r_state.cpp:350
rstate_t r_state
Definition: r_main.cpp:48
r_program_t * model_program
Definition: r_state.h:133
bool glowmap_enabled
Definition: r_state.h:158
int y
Definition: cl_video.h:76
int virtualWidth
Definition: cl_video.h:74
#define R_CheckError()
Definition: r_error.h:30
GLfloat * color_array
Definition: r_state.h:102
static void MYgluPerspective(GLfloat zNear, GLfloat zFar)
Definition: r_state.cpp:743
#define texunit_3
Definition: r_state.h:64
bool stencil_test_enabled
Definition: r_state.h:153
bool specularmap_enabled
Definition: r_state.h:161
#define texunit_roughnessmap
Definition: r_state.h:74
vec_t * next_normals
GLfloat * next_tangent_array
Definition: r_state.h:108
unsigned height
Definition: cl_video.h:45
#define texunit_deluxemap
Definition: r_state.h:70
void R_ReallocateStateArrays(int size)
Reallocate arrays of GL primitives if needed.
Definition: r_state.cpp:1029
cvar_t * r_specular
Definition: r_main.cpp:104
#define fbo_screen
Definition: r_state.h:87
QGL_EXTERN int GLboolean GLfloat * v
Definition: r_gl.h:120
bool blend_enabled
Definition: r_state.h:149
void R_ProgramParameter1f(const char *name, GLfloat value)
Definition: r_program.cpp:121
void R_TexOverride(vec4_t rgba)
Sets special texture environment mode to override texture color; don't forget to call R_TexOverride(n...
Definition: r_state.cpp:968
cvar_t * r_fog
Definition: r_main.cpp:107
void R_EnableSpecularMap(const image_t *image, bool enable)
Definition: r_state.cpp:707
float hardness
Definition: r_material.h:161
#define COMPONENTS_NORMAL_ARRAY
Definition: r_state.h:80
const vec2_t default_texcoords[4]
Definition: r_state.cpp:30
const vec4_t color_white
Definition: r_state.cpp:1004
static void R_UpdateGlowBufferBinding(void)
Definition: r_state.cpp:616
void R_BindTextureForTexUnit(GLuint texnum, gltexunit_t *texunit)
Definition: r_state.cpp:77
cvar_t * r_warp
Definition: r_main.cpp:95
#define R_BindTexture(tn)
Definition: r_state.h:184
const struct image_s * active_normalmap
Definition: r_state.h:166
void R_EnableGlowMap(const image_t *image)
Definition: r_state.cpp:664
#define COMPONENTS_TEXCOORD_ARRAY
Definition: r_state.h:82
GLint texnum
Definition: r_state.h:51
void R_EnableFog(bool enable)
Definition: r_state.cpp:586
#define GL_NEXT_VERTEX_ARRAY
Definition: r_gl.h:77
void R_BindTextureDebug(int texnum, const char *file, int line, const char *function)
Definition: r_state.cpp:69
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
GLfloat * texcoord_array
Definition: r_state.h:53
GLuint texnum
Definition: r_image.h:66
vec_t vec4_t[4]
Definition: ufotypes.h:40
float radius
Definition: r_light.h:32