hackeverything

sauerbraten/src/engine/rendergl.cpp

Oct 27th, 2011
444
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 81.80 KB | None | 0 0
  1. // rendergl.cpp: core opengl rendering stuff
  2.  
  3. #include "engine.h"
  4. #include "bot_util.h"            //modification
  5. #include "../shared/cube.h"      //modification
  6. bool hasVBO = false, hasDRE = false, hasOQ = false, hasTR = false, hasFBO = false, hasDS = false, hasTF = false, hasBE = false, hasBC = false, hasCM = false, hasNP2 = false, hasTC = false, hasTE = false, hasMT = false, hasD3 = false, hasAF = false, hasVP2 = false, hasVP3 = false, hasPP = false, hasMDA = false, hasTE3 = false, hasTE4 = false, hasVP = false, hasFP = false, hasGLSL = false, hasGM = false, hasNVFB = false, hasSGIDT = false, hasSGISH = false, hasDT = false, hasSH = false, hasNVPCF = false, hasRN = false, hasPBO = false, hasFBB = false, hasUBO = false, hasBUE = false, hasFC = false, hasTEX = false;
  7. int hasstencil = 0;
  8.  
  9. VAR(renderpath, 1, 0, 0);
  10.  
  11. // GL_ARB_vertex_buffer_object, GL_ARB_pixel_buffer_object
  12. PFNGLGENBUFFERSARBPROC       glGenBuffers_       = NULL;
  13. PFNGLBINDBUFFERARBPROC       glBindBuffer_       = NULL;
  14. PFNGLMAPBUFFERARBPROC        glMapBuffer_        = NULL;
  15. PFNGLUNMAPBUFFERARBPROC      glUnmapBuffer_      = NULL;
  16. PFNGLBUFFERDATAARBPROC       glBufferData_       = NULL;
  17. PFNGLBUFFERSUBDATAARBPROC    glBufferSubData_    = NULL;
  18. PFNGLDELETEBUFFERSARBPROC    glDeleteBuffers_    = NULL;
  19. PFNGLGETBUFFERSUBDATAARBPROC glGetBufferSubData_ = NULL;
  20.  
  21. // GL_ARB_multitexture
  22. PFNGLACTIVETEXTUREARBPROC       glActiveTexture_       = NULL;
  23. PFNGLCLIENTACTIVETEXTUREARBPROC glClientActiveTexture_ = NULL;
  24. PFNGLMULTITEXCOORD2FARBPROC     glMultiTexCoord2f_     = NULL;
  25. PFNGLMULTITEXCOORD3FARBPROC     glMultiTexCoord3f_     = NULL;
  26. PFNGLMULTITEXCOORD4FARBPROC     glMultiTexCoord4f_     = NULL;
  27.  
  28. // GL_ARB_vertex_program, GL_ARB_fragment_program
  29. PFNGLGENPROGRAMSARBPROC              glGenPrograms_              = NULL;
  30. PFNGLDELETEPROGRAMSARBPROC           glDeletePrograms_           = NULL;
  31. PFNGLBINDPROGRAMARBPROC              glBindProgram_              = NULL;
  32. PFNGLPROGRAMSTRINGARBPROC            glProgramString_            = NULL;
  33. PFNGLGETPROGRAMIVARBPROC             glGetProgramiv_             = NULL;
  34. PFNGLPROGRAMENVPARAMETER4FARBPROC    glProgramEnvParameter4f_    = NULL;
  35. PFNGLPROGRAMENVPARAMETER4FVARBPROC   glProgramEnvParameter4fv_   = NULL;
  36. PFNGLENABLEVERTEXATTRIBARRAYARBPROC  glEnableVertexAttribArray_  = NULL;
  37. PFNGLDISABLEVERTEXATTRIBARRAYARBPROC glDisableVertexAttribArray_ = NULL;
  38. PFNGLVERTEXATTRIBPOINTERARBPROC      glVertexAttribPointer_      = NULL;
  39.  
  40. // GL_EXT_gpu_program_parameters
  41. PFNGLPROGRAMENVPARAMETERS4FVEXTPROC   glProgramEnvParameters4fv_   = NULL;
  42. PFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC glProgramLocalParameters4fv_ = NULL;
  43.  
  44. // GL_ARB_occlusion_query
  45. PFNGLGENQUERIESARBPROC        glGenQueries_        = NULL;
  46. PFNGLDELETEQUERIESARBPROC     glDeleteQueries_     = NULL;
  47. PFNGLBEGINQUERYARBPROC        glBeginQuery_        = NULL;
  48. PFNGLENDQUERYARBPROC          glEndQuery_          = NULL;
  49. PFNGLGETQUERYIVARBPROC        glGetQueryiv_        = NULL;
  50. PFNGLGETQUERYOBJECTIVARBPROC  glGetQueryObjectiv_  = NULL;
  51. PFNGLGETQUERYOBJECTUIVARBPROC glGetQueryObjectuiv_ = NULL;
  52.  
  53. // GL_EXT_framebuffer_object
  54. PFNGLBINDRENDERBUFFEREXTPROC        glBindRenderbuffer_        = NULL;
  55. PFNGLDELETERENDERBUFFERSEXTPROC     glDeleteRenderbuffers_     = NULL;
  56. PFNGLGENFRAMEBUFFERSEXTPROC         glGenRenderbuffers_        = NULL;
  57. PFNGLRENDERBUFFERSTORAGEEXTPROC     glRenderbufferStorage_     = NULL;
  58. PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC  glCheckFramebufferStatus_  = NULL;
  59. PFNGLBINDFRAMEBUFFEREXTPROC         glBindFramebuffer_         = NULL;
  60. PFNGLDELETEFRAMEBUFFERSEXTPROC      glDeleteFramebuffers_      = NULL;
  61. PFNGLGENFRAMEBUFFERSEXTPROC         glGenFramebuffers_         = NULL;
  62. PFNGLFRAMEBUFFERTEXTURE2DEXTPROC    glFramebufferTexture2D_    = NULL;
  63. PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbuffer_ = NULL;
  64. PFNGLGENERATEMIPMAPEXTPROC          glGenerateMipmap_          = NULL;
  65.  
  66. // GL_EXT_framebuffer_blit
  67. PFNGLBLITFRAMEBUFFEREXTPROC         glBlitFramebuffer_         = NULL;
  68.  
  69. // GL_ARB_shading_language_100, GL_ARB_shader_objects, GL_ARB_fragment_shader, GL_ARB_vertex_shader
  70. PFNGLCREATEPROGRAMOBJECTARBPROC       glCreateProgramObject_      = NULL;
  71. PFNGLDELETEOBJECTARBPROC              glDeleteObject_             = NULL;
  72. PFNGLUSEPROGRAMOBJECTARBPROC          glUseProgramObject_         = NULL;
  73. PFNGLCREATESHADEROBJECTARBPROC        glCreateShaderObject_       = NULL;
  74. PFNGLSHADERSOURCEARBPROC              glShaderSource_             = NULL;
  75. PFNGLCOMPILESHADERARBPROC             glCompileShader_            = NULL;
  76. PFNGLGETOBJECTPARAMETERIVARBPROC      glGetObjectParameteriv_     = NULL;
  77. PFNGLATTACHOBJECTARBPROC              glAttachObject_             = NULL;
  78. PFNGLGETINFOLOGARBPROC                glGetInfoLog_               = NULL;
  79. PFNGLLINKPROGRAMARBPROC               glLinkProgram_              = NULL;
  80. PFNGLGETUNIFORMLOCATIONARBPROC        glGetUniformLocation_       = NULL;
  81. PFNGLUNIFORM1FARBPROC                 glUniform1f_                = NULL;
  82. PFNGLUNIFORM2FARBPROC                 glUniform2f_                = NULL;
  83. PFNGLUNIFORM3FARBPROC                 glUniform3f_                = NULL;
  84. PFNGLUNIFORM4FARBPROC                 glUniform4f_                = NULL;
  85. PFNGLUNIFORM1FVARBPROC                glUniform1fv_               = NULL;
  86. PFNGLUNIFORM2FVARBPROC                glUniform2fv_               = NULL;
  87. PFNGLUNIFORM3FVARBPROC                glUniform3fv_               = NULL;
  88. PFNGLUNIFORM4FVARBPROC                glUniform4fv_               = NULL;
  89. PFNGLUNIFORM1IARBPROC                 glUniform1i_                = NULL;
  90. PFNGLBINDATTRIBLOCATIONARBPROC        glBindAttribLocation_       = NULL;
  91. PFNGLGETACTIVEUNIFORMARBPROC          glGetActiveUniform_         = NULL;
  92.  
  93. // GL_EXT_draw_range_elements
  94. PFNGLDRAWRANGEELEMENTSEXTPROC glDrawRangeElements_ = NULL;
  95.  
  96. // GL_EXT_blend_minmax
  97. PFNGLBLENDEQUATIONEXTPROC glBlendEquation_ = NULL;
  98.  
  99. // GL_EXT_blend_color
  100. PFNGLBLENDCOLOREXTPROC glBlendColor_ = NULL;
  101.  
  102. // GL_EXT_multi_draw_arrays
  103. PFNGLMULTIDRAWARRAYSEXTPROC   glMultiDrawArrays_   = NULL;
  104. PFNGLMULTIDRAWELEMENTSEXTPROC glMultiDrawElements_ = NULL;
  105.  
  106. // GL_ARB_texture_compression
  107. PFNGLCOMPRESSEDTEXIMAGE3DARBPROC    glCompressedTexImage3D_    = NULL;
  108. PFNGLCOMPRESSEDTEXIMAGE2DARBPROC    glCompressedTexImage2D_    = NULL;
  109. PFNGLCOMPRESSEDTEXIMAGE1DARBPROC    glCompressedTexImage1D_    = NULL;
  110. PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC glCompressedTexSubImage3D_ = NULL;
  111. PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC glCompressedTexSubImage2D_ = NULL;
  112. PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC glCompressedTexSubImage1D_ = NULL;
  113. PFNGLGETCOMPRESSEDTEXIMAGEARBPROC   glGetCompressedTexImage_   = NULL;
  114.  
  115. // GL_ARB_uniform_buffer_object
  116. PFNGLGETUNIFORMINDICESPROC       glGetUniformIndices_       = NULL;
  117. PFNGLGETACTIVEUNIFORMSIVPROC     glGetActiveUniformsiv_     = NULL;
  118. PFNGLGETUNIFORMBLOCKINDEXPROC    glGetUniformBlockIndex_    = NULL;
  119. PFNGLGETACTIVEUNIFORMBLOCKIVPROC glGetActiveUniformBlockiv_ = NULL;
  120. PFNGLUNIFORMBLOCKBINDINGPROC     glUniformBlockBinding_     = NULL;
  121. PFNGLBINDBUFFERBASEPROC          glBindBufferBase_          = NULL;
  122. PFNGLBINDBUFFERRANGEPROC         glBindBufferRange_         = NULL;
  123.  
  124. // GL_EXT_bindable_uniform
  125. PFNGLUNIFORMBUFFEREXTPROC        glUniformBuffer_        = NULL;
  126. PFNGLGETUNIFORMBUFFERSIZEEXTPROC glGetUniformBufferSize_ = NULL;
  127. PFNGLGETUNIFORMOFFSETEXTPROC     glGetUniformOffset_     = NULL;
  128.  
  129. // GL_EXT_fog_coord
  130. PFNGLFOGCOORDPOINTEREXTPROC glFogCoordPointer_ = NULL;
  131.  
  132. void *getprocaddress(const char *name)
  133. {
  134.     return SDL_GL_GetProcAddress(name);
  135. }
  136.  
  137. VARP(ati_skybox_bug, 0, 0, 1);
  138. VAR(ati_oq_bug, 0, 0, 1);
  139. VAR(ati_minmax_bug, 0, 0, 1);
  140. VAR(ati_dph_bug, 0, 0, 1);
  141. VAR(ati_teximage_bug, 0, 0, 1);
  142. VAR(ati_line_bug, 0, 0, 1);
  143. VAR(ati_cubemap_bug, 0, 0, 1);
  144. VAR(ati_ubo_bug, 0, 0, 1);
  145. VAR(nvidia_scissor_bug, 0, 0, 1);
  146. VAR(apple_glsldepth_bug, 0, 0, 1);
  147. VAR(apple_ff_bug, 0, 0, 1);
  148. VAR(apple_vp_bug, 0, 0, 1);
  149. VAR(sdl_backingstore_bug, -1, 0, 1);
  150. VAR(intel_quadric_bug, 0, 0, 1);
  151. VAR(mesa_program_bug, 0, 0, 1);
  152. VAR(avoidshaders, 1, 0, 0);
  153. VAR(minimizetcusage, 1, 0, 0);
  154. VAR(emulatefog, 1, 0, 0);
  155. VAR(usevp2, 1, 0, 0);
  156. VAR(usevp3, 1, 0, 0);
  157. VAR(usetexrect, 1, 0, 0);
  158. VAR(hasglsl, 1, 0, 0);
  159. VAR(useubo, 1, 0, 0);
  160. VAR(usebue, 1, 0, 0);
  161. VAR(rtscissor, 0, 1, 1);
  162. VAR(blurtile, 0, 1, 1);
  163. VAR(rtsharefb, 0, 1, 1);
  164.  
  165. static bool checkseries(const char *s, int low, int high)
  166. {
  167.     while(*s && !isdigit(*s)) ++s;
  168.     if(!*s) return false;
  169.     int n = 0;
  170.     while(isdigit(*s)) n = n*10 + (*s++ - '0');    
  171.     return n >= low && n < high;
  172. }
  173.  
  174. VAR(dbgexts, 0, 0, 1);
  175.  
  176. void gl_checkextensions()
  177. {
  178.     const char *vendor = (const char *)glGetString(GL_VENDOR);
  179.     const char *exts = (const char *)glGetString(GL_EXTENSIONS);
  180.     const char *renderer = (const char *)glGetString(GL_RENDERER);
  181.     const char *version = (const char *)glGetString(GL_VERSION);
  182.     conoutf(CON_INIT, "Renderer: %s (%s)", renderer, vendor);
  183.     conoutf(CON_INIT, "Driver: %s", version);
  184.  
  185. #ifdef __APPLE__
  186.     extern int mac_osversion();
  187.     int osversion = mac_osversion();  /* 0x1050 = 10.5 (Leopard) */
  188.     sdl_backingstore_bug = -1;
  189. #endif
  190.  
  191.     //extern int shaderprecision;
  192.     // default to low precision shaders on certain cards, can be overridden with -f3
  193.     // char *weakcards[] = { "GeForce FX", "Quadro FX", "6200", "9500", "9550", "9600", "9700", "9800", "X300", "X600", "FireGL", "Intel", "Chrome", NULL }
  194.     // if(shaderprecision==2) for(char **wc = weakcards; *wc; wc++) if(strstr(renderer, *wc)) shaderprecision = 1;
  195.  
  196.     if(strstr(exts, "GL_EXT_texture_env_combine") || strstr(exts, "GL_ARB_texture_env_combine"))
  197.     {
  198.         hasTE = true;
  199.         if(strstr(exts, "GL_ARB_texture_env_crossbar")) hasTEX = true;
  200.         if(strstr(exts, "GL_ATI_texture_env_combine3")) hasTE3 = true;
  201.         if(strstr(exts, "GL_NV_texture_env_combine4")) hasTE4 = true;
  202.         if(strstr(exts, "GL_EXT_texture_env_dot3") || strstr(exts, "GL_ARB_texture_env_dot3")) hasD3 = true;
  203.         if(dbgexts) conoutf(CON_INIT, "Using GL_ARB_texture_env_combine extension.");
  204.     }
  205.     else conoutf(CON_WARN, "WARNING: No texture_env_combine extension! (your video card is WAY too old)");
  206.  
  207.     if(strstr(exts, "GL_ARB_multitexture"))
  208.     {
  209.         glActiveTexture_       = (PFNGLACTIVETEXTUREARBPROC)      getprocaddress("glActiveTextureARB");
  210.         glClientActiveTexture_ = (PFNGLCLIENTACTIVETEXTUREARBPROC)getprocaddress("glClientActiveTextureARB");
  211.         glMultiTexCoord2f_     = (PFNGLMULTITEXCOORD2FARBPROC)    getprocaddress("glMultiTexCoord2fARB");
  212.         glMultiTexCoord3f_     = (PFNGLMULTITEXCOORD3FARBPROC)    getprocaddress("glMultiTexCoord3fARB");
  213.         glMultiTexCoord4f_     = (PFNGLMULTITEXCOORD4FARBPROC)    getprocaddress("glMultiTexCoord4fARB");
  214.         hasMT = true;
  215.         if(dbgexts) conoutf(CON_INIT, "Using GL_ARB_multitexture extension.");
  216.     }
  217.     else conoutf(CON_WARN, "WARNING: No multitexture extension!");
  218.  
  219.  
  220.     if(strstr(exts, "GL_ARB_vertex_buffer_object"))
  221.     {
  222.         hasVBO = true;
  223.         if(dbgexts) conoutf(CON_INIT, "Using GL_ARB_vertex_buffer_object extension.");
  224.     }
  225.     else conoutf(CON_WARN, "WARNING: No vertex_buffer_object extension! (geometry heavy maps will be SLOW)");
  226. #ifdef __APPLE__
  227.     /* VBOs over 256KB seem to destroy performance on 10.5, but not in 10.6 */
  228.     extern int maxvbosize;
  229.     if(osversion < 0x1060) maxvbosize = min(maxvbosize, 8192);  
  230. #endif
  231.  
  232.     if(strstr(exts, "GL_ARB_pixel_buffer_object"))
  233.     {
  234.         hasPBO = true;
  235.         if(dbgexts) conoutf(CON_INIT, "Using GL_ARB_pixel_buffer_object extension.");
  236.     }
  237.  
  238.     if(hasVBO || hasPBO)
  239.     {
  240.         glGenBuffers_       = (PFNGLGENBUFFERSARBPROC)      getprocaddress("glGenBuffersARB");
  241.         glBindBuffer_       = (PFNGLBINDBUFFERARBPROC)      getprocaddress("glBindBufferARB");
  242.         glMapBuffer_        = (PFNGLMAPBUFFERARBPROC)       getprocaddress("glMapBufferARB");
  243.         glUnmapBuffer_      = (PFNGLUNMAPBUFFERARBPROC)     getprocaddress("glUnmapBufferARB");
  244.         glBufferData_       = (PFNGLBUFFERDATAARBPROC)      getprocaddress("glBufferDataARB");
  245.         glBufferSubData_    = (PFNGLBUFFERSUBDATAARBPROC)   getprocaddress("glBufferSubDataARB");
  246.         glDeleteBuffers_    = (PFNGLDELETEBUFFERSARBPROC)   getprocaddress("glDeleteBuffersARB");
  247.         glGetBufferSubData_ = (PFNGLGETBUFFERSUBDATAARBPROC)getprocaddress("glGetBufferSubDataARB");
  248.     }
  249.  
  250.     if(strstr(exts, "GL_EXT_draw_range_elements"))
  251.     {
  252.         glDrawRangeElements_ = (PFNGLDRAWRANGEELEMENTSEXTPROC)getprocaddress("glDrawRangeElementsEXT");
  253.         hasDRE = true;
  254.         if(dbgexts) conoutf(CON_INIT, "Using GL_EXT_draw_range_elements extension.");
  255.     }
  256.  
  257.     if(strstr(exts, "GL_EXT_multi_draw_arrays"))
  258.     {
  259.         glMultiDrawArrays_   = (PFNGLMULTIDRAWARRAYSEXTPROC)  getprocaddress("glMultiDrawArraysEXT");
  260.         glMultiDrawElements_ = (PFNGLMULTIDRAWELEMENTSEXTPROC)getprocaddress("glMultiDrawElementsEXT");
  261.         hasMDA = true;
  262.         if(dbgexts) conoutf(CON_INIT, "Using GL_EXT_multi_draw_arrays extension.");
  263.     }
  264.  
  265. #ifdef __APPLE__
  266.     // floating point FBOs not fully supported until 10.5
  267.     if(osversion>=0x1050)
  268. #endif
  269.     if(strstr(exts, "GL_ARB_texture_float") || strstr(exts, "GL_ATI_texture_float"))
  270.     {
  271.         hasTF = true;
  272.         if(dbgexts) conoutf(CON_INIT, "Using GL_ARB_texture_float extension.");
  273.         shadowmap = 1;
  274.         extern int smoothshadowmappeel;
  275.         smoothshadowmappeel = 1;
  276.     }
  277.  
  278.     if(strstr(exts, "GL_NV_float_buffer"))
  279.     {
  280.         hasNVFB = true;
  281.         if(dbgexts) conoutf(CON_INIT, "Using GL_NV_float_buffer extension.");
  282.     }
  283.  
  284.     if(strstr(exts, "GL_EXT_framebuffer_object"))
  285.     {
  286.         glBindRenderbuffer_        = (PFNGLBINDRENDERBUFFEREXTPROC)       getprocaddress("glBindRenderbufferEXT");
  287.         glDeleteRenderbuffers_     = (PFNGLDELETERENDERBUFFERSEXTPROC)    getprocaddress("glDeleteRenderbuffersEXT");
  288.         glGenRenderbuffers_        = (PFNGLGENFRAMEBUFFERSEXTPROC)        getprocaddress("glGenRenderbuffersEXT");
  289.         glRenderbufferStorage_     = (PFNGLRENDERBUFFERSTORAGEEXTPROC)    getprocaddress("glRenderbufferStorageEXT");
  290.         glCheckFramebufferStatus_  = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) getprocaddress("glCheckFramebufferStatusEXT");
  291.         glBindFramebuffer_         = (PFNGLBINDFRAMEBUFFEREXTPROC)        getprocaddress("glBindFramebufferEXT");
  292.         glDeleteFramebuffers_      = (PFNGLDELETEFRAMEBUFFERSEXTPROC)     getprocaddress("glDeleteFramebuffersEXT");
  293.         glGenFramebuffers_         = (PFNGLGENFRAMEBUFFERSEXTPROC)        getprocaddress("glGenFramebuffersEXT");
  294.         glFramebufferTexture2D_    = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)   getprocaddress("glFramebufferTexture2DEXT");
  295.         glFramebufferRenderbuffer_ = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)getprocaddress("glFramebufferRenderbufferEXT");
  296.         glGenerateMipmap_          = (PFNGLGENERATEMIPMAPEXTPROC)         getprocaddress("glGenerateMipmapEXT");
  297.         hasFBO = true;
  298.         if(dbgexts) conoutf(CON_INIT, "Using GL_EXT_framebuffer_object extension.");
  299.  
  300.         if(strstr(exts, "GL_EXT_framebuffer_blit"))
  301.         {
  302.             glBlitFramebuffer_     = (PFNGLBLITFRAMEBUFFEREXTPROC)        getprocaddress("glBlitFramebufferEXT");
  303.             hasFBB = true;
  304.             if(dbgexts) conoutf(CON_INIT, "Using GL_EXT_framebuffer_blit extension.");
  305.         }
  306.     }
  307.     else conoutf(CON_WARN, "WARNING: No framebuffer object support. (reflective water may be slow)");
  308.  
  309.     if(strstr(exts, "GL_ARB_occlusion_query"))
  310.     {
  311.         GLint bits;
  312.         glGetQueryiv_ = (PFNGLGETQUERYIVARBPROC)getprocaddress("glGetQueryivARB");
  313.         glGetQueryiv_(GL_SAMPLES_PASSED_ARB, GL_QUERY_COUNTER_BITS_ARB, &bits);
  314.         if(bits)
  315.         {
  316.             glGenQueries_ =        (PFNGLGENQUERIESARBPROC)       getprocaddress("glGenQueriesARB");
  317.             glDeleteQueries_ =     (PFNGLDELETEQUERIESARBPROC)    getprocaddress("glDeleteQueriesARB");
  318.             glBeginQuery_ =        (PFNGLBEGINQUERYARBPROC)       getprocaddress("glBeginQueryARB");
  319.             glEndQuery_ =          (PFNGLENDQUERYARBPROC)         getprocaddress("glEndQueryARB");
  320.             glGetQueryObjectiv_ =  (PFNGLGETQUERYOBJECTIVARBPROC) getprocaddress("glGetQueryObjectivARB");
  321.             glGetQueryObjectuiv_ = (PFNGLGETQUERYOBJECTUIVARBPROC)getprocaddress("glGetQueryObjectuivARB");
  322.             hasOQ = true;
  323.             if(dbgexts) conoutf(CON_INIT, "Using GL_ARB_occlusion_query extension.");
  324. #if defined(__APPLE__) && SDL_BYTEORDER == SDL_BIG_ENDIAN
  325.             if(strstr(vendor, "ATI") && (osversion<0x1050)) ati_oq_bug = 1;
  326. #endif
  327.             if(ati_oq_bug) conoutf(CON_WARN, "WARNING: Using ATI occlusion query bug workaround. (use \"/ati_oq_bug 0\" to disable if unnecessary)");
  328.         }
  329.     }
  330.     if(!hasOQ)
  331.     {
  332.         conoutf(CON_WARN, "WARNING: No occlusion query support! (large maps may be SLOW)");
  333.         extern int vacubesize;
  334.         vacubesize = 64;
  335.         waterreflect = 0;
  336.     }
  337.  
  338.     extern int reservedynlighttc, reserveshadowmaptc, batchlightmaps, ffdynlights;
  339.     if(strstr(vendor, "ATI"))
  340.     {
  341.         //conoutf(CON_WARN, "WARNING: ATI cards may show garbage in skybox. (use \"/ati_skybox_bug 1\" to fix)");
  342.  
  343.         reservedynlighttc = 2;
  344.         reserveshadowmaptc = 3;
  345.         minimizetcusage = 1;
  346.         emulatefog = 1;
  347.         extern int depthfxprecision;
  348.         if(hasTF) depthfxprecision = 1;
  349.  
  350. #if 0
  351.         //causes problems with Catalyst AI advanced setting, hope this is fixed by now - 11-21-09
  352. #if !defined(WIN32) && !defined(__APPLE__)
  353.         // reported on ATI Radeon HD 4800, Gentoo Linux kernel 2.6.26, Catalyst 9.3, 4-29-09, driver overreads memory on mipmapped GL_RGB textures for base level once max level is specified
  354.         // ... doesn't seem to affect Radeon X1300 on Catalyst 9.3, however
  355.         // TODO: verify if this is fixed in newer Catalyst releases
  356.         if(strstr(renderer, "Radeon HD")) ati_teximage_bug = 1;
  357. #endif
  358. #endif
  359.     }
  360.     else if(strstr(vendor, "NVIDIA"))
  361.     {
  362.         reservevpparams = 10;
  363.         rtsharefb = 0; // work-around for strange driver stalls involving when using many FBOs
  364.         extern int filltjoints;
  365.         if(!strstr(exts, "GL_EXT_gpu_shader4")) filltjoints = 0; // DX9 or less NV cards seem to not cause many sparklies
  366.        
  367.         if(hasFBO && !hasTF) nvidia_scissor_bug = 1; // 5200 bug, clearing with scissor on an FBO messes up on reflections, may affect lesser cards too
  368.         extern int fpdepthfx;
  369.         if(hasTF && (!strstr(renderer, "GeForce") || !checkseries(renderer, 6000, 6600)))
  370.             fpdepthfx = 1; // FP filtering causes software fallback on 6200?
  371.     }
  372.     else if(strstr(vendor, "Intel"))
  373.     {
  374.         avoidshaders = 1;
  375.         intel_quadric_bug = 1;
  376.         maxtexsize = 256;
  377.         reservevpparams = 20;
  378.         batchlightmaps = 0;
  379.         ffdynlights = 0;
  380.  
  381.         if(!hasOQ) waterrefract = 0;
  382.  
  383. #ifdef __APPLE__
  384.         apple_vp_bug = 1;
  385. #endif
  386.     }
  387.     else if(strstr(vendor, "Tungsten") || strstr(vendor, "Mesa") || strstr(vendor, "DRI") || strstr(vendor, "Microsoft") || strstr(vendor, "S3 Graphics"))
  388.     {
  389.         avoidshaders = 1;
  390.         maxtexsize = 256;
  391.         reservevpparams = 20;
  392.         batchlightmaps = 0;
  393.         ffdynlights = 0;
  394.  
  395.         if(!hasOQ) waterrefract = 0;
  396.     }
  397.  
  398.     if(strstr(exts, "GL_ARB_vertex_program") && strstr(exts, "GL_ARB_fragment_program"))
  399.     {
  400.         hasVP = hasFP = true;
  401.         glGenPrograms_ =              (PFNGLGENPROGRAMSARBPROC)              getprocaddress("glGenProgramsARB");
  402.         glDeletePrograms_ =           (PFNGLDELETEPROGRAMSARBPROC)           getprocaddress("glDeleteProgramsARB");
  403.         glBindProgram_ =              (PFNGLBINDPROGRAMARBPROC)              getprocaddress("glBindProgramARB");
  404.         glProgramString_ =            (PFNGLPROGRAMSTRINGARBPROC)            getprocaddress("glProgramStringARB");
  405.         glGetProgramiv_ =             (PFNGLGETPROGRAMIVARBPROC)             getprocaddress("glGetProgramivARB");
  406.         glProgramEnvParameter4f_ =    (PFNGLPROGRAMENVPARAMETER4FARBPROC)    getprocaddress("glProgramEnvParameter4fARB");
  407.         glProgramEnvParameter4fv_ =   (PFNGLPROGRAMENVPARAMETER4FVARBPROC)   getprocaddress("glProgramEnvParameter4fvARB");
  408.         glEnableVertexAttribArray_ =  (PFNGLENABLEVERTEXATTRIBARRAYARBPROC)  getprocaddress("glEnableVertexAttribArrayARB");
  409.         glDisableVertexAttribArray_ = (PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) getprocaddress("glDisableVertexAttribArrayARB");
  410.         glVertexAttribPointer_ =      (PFNGLVERTEXATTRIBPOINTERARBPROC)      getprocaddress("glVertexAttribPointerARB");
  411.  
  412.         if(strstr(vendor, "ATI")) ati_dph_bug = ati_line_bug = 1;
  413.         else if(strstr(vendor, "Tungsten")) mesa_program_bug = 1;
  414.  
  415. #ifdef __APPLE__
  416.         if(osversion>=0x1050) // fixed in 1055 for some hardware.. but not all..
  417.         {
  418.             apple_ff_bug = 1;
  419.             conoutf(CON_WARN, "WARNING: Using Leopard ARB_position_invariant bug workaround. (use \"/apple_ff_bug 0\" to disable if unnecessary)");
  420.         }
  421. #endif
  422.     }
  423.    
  424.     if(strstr(exts, "GL_ARB_shading_language_100") && strstr(exts, "GL_ARB_shader_objects") && strstr(exts, "GL_ARB_vertex_shader") && strstr(exts, "GL_ARB_fragment_shader"))
  425.     {
  426.         glCreateProgramObject_ =        (PFNGLCREATEPROGRAMOBJECTARBPROC)     getprocaddress("glCreateProgramObjectARB");
  427.         glDeleteObject_ =               (PFNGLDELETEOBJECTARBPROC)            getprocaddress("glDeleteObjectARB");
  428.         glUseProgramObject_ =           (PFNGLUSEPROGRAMOBJECTARBPROC)        getprocaddress("glUseProgramObjectARB");
  429.         glCreateShaderObject_ =         (PFNGLCREATESHADEROBJECTARBPROC)      getprocaddress("glCreateShaderObjectARB");
  430.         glShaderSource_ =               (PFNGLSHADERSOURCEARBPROC)            getprocaddress("glShaderSourceARB");
  431.         glCompileShader_ =              (PFNGLCOMPILESHADERARBPROC)           getprocaddress("glCompileShaderARB");
  432.         glGetObjectParameteriv_ =       (PFNGLGETOBJECTPARAMETERIVARBPROC)    getprocaddress("glGetObjectParameterivARB");
  433.         glAttachObject_ =               (PFNGLATTACHOBJECTARBPROC)            getprocaddress("glAttachObjectARB");
  434.         glGetInfoLog_ =                 (PFNGLGETINFOLOGARBPROC)              getprocaddress("glGetInfoLogARB");
  435.         glLinkProgram_ =                (PFNGLLINKPROGRAMARBPROC)             getprocaddress("glLinkProgramARB");
  436.         glGetUniformLocation_ =         (PFNGLGETUNIFORMLOCATIONARBPROC)      getprocaddress("glGetUniformLocationARB");
  437.         glUniform1f_ =                  (PFNGLUNIFORM1FARBPROC)               getprocaddress("glUniform1fARB");
  438.         glUniform2f_ =                  (PFNGLUNIFORM2FARBPROC)               getprocaddress("glUniform2fARB");
  439.         glUniform3f_ =                  (PFNGLUNIFORM3FARBPROC)               getprocaddress("glUniform3fARB");
  440.         glUniform4f_ =                  (PFNGLUNIFORM4FARBPROC)               getprocaddress("glUniform4fARB");
  441.         glUniform1fv_ =                 (PFNGLUNIFORM1FVARBPROC)              getprocaddress("glUniform1fvARB");
  442.         glUniform2fv_ =                 (PFNGLUNIFORM2FVARBPROC)              getprocaddress("glUniform2fvARB");
  443.         glUniform3fv_ =                 (PFNGLUNIFORM3FVARBPROC)              getprocaddress("glUniform3fvARB");
  444.         glUniform4fv_ =                 (PFNGLUNIFORM4FVARBPROC)              getprocaddress("glUniform4fvARB");
  445.         glUniform1i_ =                  (PFNGLUNIFORM1IARBPROC)               getprocaddress("glUniform1iARB");
  446.         glBindAttribLocation_ =         (PFNGLBINDATTRIBLOCATIONARBPROC)      getprocaddress("glBindAttribLocationARB");
  447.         glGetActiveUniform_ =           (PFNGLGETACTIVEUNIFORMARBPROC)        getprocaddress("glGetActiveUniformARB");
  448.         if(!hasVP || !hasFP)
  449.         {
  450.             glEnableVertexAttribArray_ =  (PFNGLENABLEVERTEXATTRIBARRAYARBPROC)  getprocaddress("glEnableVertexAttribArrayARB");
  451.             glDisableVertexAttribArray_ = (PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) getprocaddress("glDisableVertexAttribArrayARB");
  452.             glVertexAttribPointer_ =      (PFNGLVERTEXATTRIBPOINTERARBPROC)      getprocaddress("glVertexAttribPointerARB");
  453.         }
  454.  
  455.         extern bool checkglslsupport();
  456.         if(checkglslsupport())
  457.         {
  458.             hasGLSL = true;
  459.             hasglsl = 1;
  460. #ifdef __APPLE__
  461.             //if(osversion<0x1050) ??
  462.             if(hasVP && hasFP) apple_glsldepth_bug = 1;
  463. #endif
  464.             if(apple_glsldepth_bug) conoutf(CON_WARN, "WARNING: Using Apple GLSL depth bug workaround. (use \"/apple_glsldepth_bug 0\" to disable if unnecessary");
  465.         }
  466.     }
  467.    
  468.     bool hasshaders = (hasVP && hasFP) || hasGLSL;
  469.     if(hasshaders)
  470.     {
  471.         extern int matskel;
  472.         if(!avoidshaders) matskel = 0;
  473.     }
  474.  
  475.     if(strstr(exts, "GL_NV_vertex_program2_option")) { usevp2 = 1; hasVP2 = true; }
  476.     if(strstr(exts, "GL_NV_vertex_program3")) { usevp3 = 1; hasVP3 = true; }
  477.  
  478.     if(strstr(exts, "GL_EXT_gpu_program_parameters"))
  479.     {
  480.         glProgramEnvParameters4fv_   = (PFNGLPROGRAMENVPARAMETERS4FVEXTPROC)  getprocaddress("glProgramEnvParameters4fvEXT");
  481.         glProgramLocalParameters4fv_ = (PFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC)getprocaddress("glProgramLocalParameters4fvEXT");
  482.         hasPP = true;
  483.         if(dbgexts) conoutf(CON_INIT, "Using GL_EXT_gpu_program_parameters extension.");
  484.     }
  485.  
  486.     if(strstr(exts, "GL_ARB_uniform_buffer_object"))
  487.     {
  488.         glGetUniformIndices_       = (PFNGLGETUNIFORMINDICESPROC)      getprocaddress("glGetUniformIndices");
  489.         glGetActiveUniformsiv_     = (PFNGLGETACTIVEUNIFORMSIVPROC)    getprocaddress("glGetActiveUniformsiv");
  490.         glGetUniformBlockIndex_    = (PFNGLGETUNIFORMBLOCKINDEXPROC)   getprocaddress("glGetUniformBlockIndex");
  491.         glGetActiveUniformBlockiv_ = (PFNGLGETACTIVEUNIFORMBLOCKIVPROC)getprocaddress("glGetActiveUniformBlockiv");
  492.         glUniformBlockBinding_     = (PFNGLUNIFORMBLOCKBINDINGPROC)    getprocaddress("glUniformBlockBinding");
  493.         glBindBufferBase_          = (PFNGLBINDBUFFERBASEPROC)         getprocaddress("glBindBufferBase");
  494.         glBindBufferRange_         = (PFNGLBINDBUFFERRANGEPROC)        getprocaddress("glBindBufferRange");
  495.  
  496.         useubo = 1;
  497.         hasUBO = true;
  498.         if(strstr(vendor, "ATI")) ati_ubo_bug = 1;
  499.         if(dbgexts) conoutf(CON_INIT, "Using GL_ARB_uniform_buffer_object extension.");
  500.     }
  501.     else if(strstr(exts, "GL_EXT_bindable_uniform"))
  502.     {
  503.         glUniformBuffer_        = (PFNGLUNIFORMBUFFEREXTPROC)       getprocaddress("glUniformBufferEXT");
  504.         glGetUniformBufferSize_ = (PFNGLGETUNIFORMBUFFERSIZEEXTPROC)getprocaddress("glGetUniformBufferSizeEXT");
  505.         glGetUniformOffset_     = (PFNGLGETUNIFORMOFFSETEXTPROC)    getprocaddress("glGetUniformOffsetEXT");
  506.  
  507.         usebue = 1;
  508.         hasBUE = true;
  509.         if(strstr(vendor, "ATI")) ati_ubo_bug = 1;
  510.         if(dbgexts) conoutf(CON_INIT, "Using GL_EXT_bindable_uniform extension.");
  511.     }
  512.  
  513.     if(strstr(exts, "GL_EXT_texture_rectangle") || strstr(exts, "GL_ARB_texture_rectangle"))
  514.     {
  515.         usetexrect = 1;
  516.         hasTR = true;
  517.         if(dbgexts) conoutf(CON_INIT, "Using GL_ARB_texture_rectangle extension.");
  518.     }
  519.     else if(hasMT && hasshaders) conoutf(CON_WARN, "WARNING: No texture rectangle support. (no full screen shaders)");
  520.  
  521.     if(strstr(exts, "GL_EXT_packed_depth_stencil") || strstr(exts, "GL_NV_packed_depth_stencil"))
  522.     {
  523.         hasDS = true;
  524.         if(dbgexts) conoutf(CON_INIT, "Using GL_EXT_packed_depth_stencil extension.");
  525.     }
  526.  
  527.     if(strstr(exts, "GL_EXT_blend_minmax"))
  528.     {
  529.         glBlendEquation_ = (PFNGLBLENDEQUATIONEXTPROC) getprocaddress("glBlendEquationEXT");
  530.         hasBE = true;
  531.         if(strstr(vendor, "ATI")) ati_minmax_bug = 1;
  532.         if(dbgexts) conoutf(CON_INIT, "Using GL_EXT_blend_minmax extension.");
  533.     }
  534.  
  535.     if(strstr(exts, "GL_EXT_blend_color"))
  536.     {
  537.         glBlendColor_ = (PFNGLBLENDCOLOREXTPROC) getprocaddress("glBlendColorEXT");
  538.         hasBC = true;
  539.         if(dbgexts) conoutf(CON_INIT, "Using GL_EXT_blend_color extension.");
  540.     }
  541.  
  542.     if(strstr(exts, "GL_EXT_fog_coord"))
  543.     {
  544.         glFogCoordPointer_ = (PFNGLFOGCOORDPOINTEREXTPROC) getprocaddress("glFogCoordPointerEXT");
  545.         hasFC = true;
  546.         if(dbgexts) conoutf(CON_INIT, "Using GL_EXT_fog_coord extension.");
  547.     }
  548.  
  549.     if(strstr(exts, "GL_ARB_texture_cube_map"))
  550.     {
  551.         GLint val;
  552.         glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB, &val);
  553.         hwcubetexsize = val;
  554.         hasCM = true;
  555.         // On Catalyst 10.2, issuing an occlusion query on the first draw using a given cubemap texture causes a nasty crash
  556.         if(strstr(vendor, "ATI")) ati_cubemap_bug = 1;
  557.         if(dbgexts) conoutf(CON_INIT, "Using GL_ARB_texture_cube_map extension.");
  558.     }
  559.     else conoutf(CON_WARN, "WARNING: No cube map texture support. (no reflective glass)");
  560.  
  561.     extern int usenp2;
  562.     if(strstr(exts, "GL_ARB_texture_non_power_of_two"))
  563.     {
  564.         hasNP2 = true;
  565.         if(dbgexts) conoutf(CON_INIT, "Using GL_ARB_texture_non_power_of_two extension.");
  566.     }
  567.     else if(usenp2) conoutf(CON_WARN, "WARNING: Non-power-of-two textures not supported!");
  568.  
  569.     if(strstr(exts, "GL_ARB_texture_compression") && strstr(exts, "GL_EXT_texture_compression_s3tc"))
  570.     {
  571.         glCompressedTexImage3D_ =    (PFNGLCOMPRESSEDTEXIMAGE3DARBPROC)   getprocaddress("glCompressedTexImage3DARB");
  572.         glCompressedTexImage2D_ =    (PFNGLCOMPRESSEDTEXIMAGE2DARBPROC)   getprocaddress("glCompressedTexImage2DARB");
  573.         glCompressedTexImage1D_ =    (PFNGLCOMPRESSEDTEXIMAGE1DARBPROC)   getprocaddress("glCompressedTexImage1DARB");
  574.         glCompressedTexSubImage3D_ = (PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC)getprocaddress("glCompressedTexSubImage3DARB");
  575.         glCompressedTexSubImage2D_ = (PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC)getprocaddress("glCompressedTexSubImage2DARB");
  576.         glCompressedTexSubImage1D_ = (PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC)getprocaddress("glCompressedTexSubImage1DARB");
  577.         glGetCompressedTexImage_ =   (PFNGLGETCOMPRESSEDTEXIMAGEARBPROC)  getprocaddress("glGetCompressedTexImageARB");
  578.  
  579.         hasTC = true;
  580.         if(dbgexts) conoutf(CON_INIT, "Using GL_EXT_texture_compression_s3tc extension.");
  581.     }
  582.  
  583.     if(strstr(exts, "GL_EXT_texture_filter_anisotropic"))
  584.     {
  585.        GLint val;
  586.        glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &val);
  587.        hwmaxaniso = val;
  588.        hasAF = true;
  589.        if(dbgexts) conoutf(CON_INIT, "Using GL_EXT_texture_filter_anisotropic extension.");
  590.     }
  591.  
  592.     if(strstr(exts, "GL_SGIS_generate_mipmap"))
  593.     {
  594.         hasGM = true;
  595.         if(dbgexts) conoutf(CON_INIT, "Using GL_SGIS_generate_mipmap extension.");
  596.     }
  597.  
  598.     if(strstr(exts, "GL_ARB_depth_texture"))
  599.     {
  600.         hasSGIDT = hasDT = true;
  601.         if(dbgexts) conoutf(CON_INIT, "Using GL_ARB_depth_texture extension.");
  602.     }
  603.     else if(strstr(exts, "GL_SGIX_depth_texture"))
  604.     {
  605.         hasSGIDT = true;
  606.         if(dbgexts) conoutf(CON_INIT, "Using GL_SGIX_depth_texture extension.");
  607.     }
  608.  
  609.     if(strstr(exts, "GL_ARB_shadow"))
  610.     {
  611.         hasSGISH = hasSH = true;
  612.         if(strstr(vendor, "NVIDIA") || strstr(renderer, "Radeon HD")) hasNVPCF = true;
  613.         if(dbgexts) conoutf(CON_INIT, "Using GL_ARB_shadow extension.");
  614.     }
  615.     else if(strstr(exts, "GL_SGIX_shadow"))
  616.     {
  617.         hasSGISH = true;
  618.         if(dbgexts) conoutf(CON_INIT, "Using GL_SGIX_shadow extension.");
  619.     }
  620.  
  621.     if(strstr(exts, "GL_EXT_rescale_normal"))
  622.     {
  623.         hasRN = true;
  624.         if(dbgexts) conoutf(CON_INIT, "Using GL_EXT_rescale_normal extension.");
  625.     }
  626.  
  627.     if(!hasSGIDT && !hasSGISH) shadowmap = 0;
  628.  
  629.     if(strstr(exts, "GL_EXT_gpu_shader4") && !avoidshaders)
  630.     {
  631.         // on DX10 or above class cards (i.e. GF8 or RadeonHD) enable expensive features
  632.         extern int grass, glare, maxdynlights, depthfxsize, depthfxrect, depthfxfilter, blurdepthfx;
  633.         grass = 1;
  634.         if(hasOQ)
  635.         {
  636.             waterfallrefract = 1;
  637.             glare = 1;
  638.             maxdynlights = MAXDYNLIGHTS;
  639.             if(hasTR)
  640.             {
  641.                 depthfxsize = 10;
  642.                 depthfxrect = 1;
  643.                 depthfxfilter = 0;
  644.                 blurdepthfx = 0;
  645.             }
  646.         }
  647.     }
  648.  
  649.     GLint val;
  650.     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &val);
  651.     hwtexsize = val;
  652. }
  653.  
  654. void glext(char *ext)
  655. {
  656.     const char *exts = (const char *)glGetString(GL_EXTENSIONS);
  657.     intret(strstr(exts, ext) ? 1 : 0);
  658. }
  659. COMMAND(glext, "s");
  660.  
  661. void gl_init(int w, int h, int bpp, int depth, int fsaa)
  662. {
  663.     glViewport(0, 0, w, h);
  664.     glClearColor(0, 0, 0, 0);
  665.     glClearDepth(1);
  666.     glDepthFunc(GL_LESS);
  667.     glDisable(GL_DEPTH_TEST);
  668.     glShadeModel(GL_SMOOTH);
  669.    
  670.    
  671.     glDisable(GL_FOG);
  672.     glFogi(GL_FOG_MODE, GL_LINEAR);
  673.     //glHint(GL_FOG_HINT, GL_NICEST);
  674.     GLfloat fogcolor[4] = { 0, 0, 0, 0 };
  675.     glFogfv(GL_FOG_COLOR, fogcolor);
  676.    
  677.  
  678.     glEnable(GL_LINE_SMOOTH);
  679.     //glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
  680.  
  681.     glFrontFace(GL_CW);
  682.     glCullFace(GL_BACK);
  683.     glDisable(GL_CULL_FACE);
  684.  
  685. #ifdef __APPLE__
  686.     if(sdl_backingstore_bug)
  687.     {
  688.         if(fsaa)
  689.         {
  690.             sdl_backingstore_bug = 1;
  691.             // since SDL doesn't add kCGLPFABackingStore to the pixelformat and so it isn't guaranteed to be preserved - only manifests when using fsaa?
  692.             //conoutf(CON_WARN, "WARNING: Using SDL backingstore workaround. (use \"/sdl_backingstore_bug 0\" to disable if unnecessary)");
  693.         }
  694.         else sdl_backingstore_bug = -1;
  695.     }
  696. #endif
  697.  
  698.     extern int useshaders, forceglsl;
  699.     bool hasshaders = (hasVP && hasFP) || hasGLSL;
  700.     if(!useshaders || (useshaders<0 && avoidshaders) || !hasMT || !hasshaders)
  701.     {
  702.         if(!hasMT || !hasshaders) conoutf(CON_WARN, "WARNING: No shader support! Using fixed-function fallback. (no fancy visuals for you)");
  703.         else if(useshaders<0 && !hasTF) conoutf(CON_WARN, "WARNING: Disabling shaders for extra performance. (use \"/shaders 1\" to enable shaders if desired)");
  704.         renderpath = R_FIXEDFUNCTION;
  705.     }
  706.     else renderpath = hasGLSL ? (!hasVP || !hasFP || forceglsl > 0 ? R_GLSLANG : R_ASMGLSLANG) : R_ASMSHADER;
  707.  
  708.     static const char * const rpnames[4] = { "fixed-function", "assembly shader", "GLSL shader", "assembly/GLSL shader" };
  709.     conoutf(CON_INIT, "Rendering using the OpenGL %s path.", rpnames[renderpath]);
  710.  
  711.     inittmus();
  712.     setuptexcompress();
  713. }
  714.  
  715. void cleanupgl()
  716. {
  717.     extern int nomasks, nolights, nowater;
  718.     nomasks = nolights = nowater = 0;
  719.  
  720.     extern void cleanupmotionblur();
  721.     cleanupmotionblur();
  722.  
  723.     extern void clearminimap();
  724.     clearminimap();
  725. }
  726.  
  727. #define VARRAY_INTERNAL
  728. #include "varray.h"
  729.  
  730. VAR(wireframe, 0, 0, 1);
  731.  
  732. ICOMMAND(getcampos, "", (),
  733. {
  734.     defformatstring(pos)("%s %s %s", floatstr(camera1->o.x), floatstr(camera1->o.y), floatstr(camera1->o.z));
  735.     result(pos);
  736. });
  737.  
  738. vec worldpos, camdir, camright, camup;
  739.  
  740. void findorientation()
  741. {
  742.     vecfromyawpitch(camera1->yaw, camera1->pitch, 1, 0, camdir);
  743.     vecfromyawpitch(camera1->yaw, 0, 0, -1, camright);
  744.     vecfromyawpitch(camera1->yaw, camera1->pitch+90, 1, 0, camup);
  745.  
  746.     if(raycubepos(camera1->o, camdir, worldpos, 0, RAY_CLIPMAT|RAY_SKIPFIRST) == -1)
  747.         worldpos = vec(camdir).mul(2*worldsize).add(camera1->o); //otherwise 3dgui won't work when outside of map
  748. }
  749.  
  750. void transplayer()
  751. {
  752.     // move from RH to Z-up LH quake style worldspace
  753.     glLoadMatrixf(viewmatrix.v);
  754.  
  755.     glRotatef(camera1->roll, 0, 1, 0);
  756.     glRotatef(camera1->pitch, -1, 0, 0);
  757.     glRotatef(camera1->yaw, 0, 0, -1);
  758.  
  759.     glTranslatef(-camera1->o.x, -camera1->o.y, -camera1->o.z);  
  760. }
  761.  
  762. float curfov = 100, curavatarfov = 65, fovy, aspect;
  763. int farplane;
  764. VARP(zoominvel, 0, 250, 5000);
  765. VARP(zoomoutvel, 0, 100, 5000);
  766. VARP(zoomfov, 10, 35, 60);
  767. VARP(fov, 10, 100, 150);
  768. VAR(avatarzoomfov, 10, 25, 60);
  769. VAR(avatarfov, 10, 65, 150);
  770. FVAR(avatardepth, 0, 0.5f, 1);
  771.  
  772. static int zoommillis = 0;
  773. VARF(zoom, -1, 0, 1,
  774.     if(zoom) zoommillis = totalmillis;
  775. );
  776.  
  777. void disablezoom()
  778. {
  779.     zoom = 0;
  780.     zoommillis = totalmillis;
  781. }
  782.  
  783. void computezoom()
  784. {
  785.     if(!zoom) { curfov = fov; curavatarfov = avatarfov; return; }
  786.     if(zoom < 0 && curfov >= fov) { zoom = 0; curfov = fov; curavatarfov = avatarfov; return; } // don't zoom-out if not zoomed-in
  787.     int zoomvel = zoom > 0 ? zoominvel : zoomoutvel,
  788.         oldfov = zoom > 0 ? fov : zoomfov,
  789.         newfov = zoom > 0 ? zoomfov : fov,
  790.         oldavatarfov = zoom > 0 ? avatarfov : avatarzoomfov,
  791.         newavatarfov = zoom > 0 ? avatarzoomfov : avatarfov;
  792.     float t = zoomvel ? float(zoomvel - (totalmillis - zoommillis)) / zoomvel : 0;
  793.     if(t <= 0)
  794.     {
  795.         if(!zoomvel && fabs(newfov - curfov) >= 1)
  796.         {
  797.             curfov = newfov;
  798.             curavatarfov = newavatarfov;
  799.         }
  800.         zoom = max(zoom, 0);
  801.     }
  802.     else
  803.     {
  804.         curfov = oldfov*t + newfov*(1 - t);
  805.         curavatarfov = oldavatarfov*t + newavatarfov*(1 - t);
  806.     }
  807. }
  808.  
  809. FVARP(zoomsens, 1e-3f, 1, 1000);
  810. FVARP(zoomaccel, 0, 0, 1000);
  811. VARP(zoomautosens, 0, 1, 1);
  812. FVARP(sensitivity, 1e-3f, 3, 1000);
  813. FVARP(sensitivityscale, 1e-3f, 1, 1000);
  814. VARP(invmouse, 0, 0, 1);
  815. FVARP(mouseaccel, 0, 0, 1000);
  816.  
  817. VAR(thirdperson, 0, 0, 2);
  818. FVAR(thirdpersondistance, 0, 20, 1000);
  819. physent *camera1 = NULL;
  820. bool detachedcamera = false;
  821. bool isthirdperson() { return player!=camera1 || detachedcamera || reflecting; }
  822.  
  823. void fixcamerarange()
  824. {
  825.     const float MAXPITCH = 90.0f;
  826.     if(camera1->pitch>MAXPITCH) camera1->pitch = MAXPITCH;
  827.     if(camera1->pitch<-MAXPITCH) camera1->pitch = -MAXPITCH;
  828.     while(camera1->yaw<0.0f) camera1->yaw += 360.0f;
  829.     while(camera1->yaw>=360.0f) camera1->yaw -= 360.0f;
  830. }
  831.  
  832. void mousemove(int dx, int dy)
  833. {
  834.     float cursens = sensitivity, curaccel = mouseaccel;
  835.     if(zoom)
  836.     {
  837.         if(zoomautosens)
  838.         {
  839.             cursens = float(sensitivity*zoomfov)/fov;
  840.             curaccel = float(mouseaccel*zoomfov)/fov;
  841.         }
  842.         else
  843.         {
  844.             cursens = zoomsens;
  845.             curaccel = zoomaccel;
  846.         }
  847.     }
  848.     if(curaccel && curtime && (dx || dy)) cursens += curaccel * sqrtf(dx*dx + dy*dy)/curtime;
  849.     cursens /= 33.0f*sensitivityscale;
  850.     camera1->yaw += dx*cursens;
  851.     camera1->pitch -= dy*cursens*(invmouse ? -1 : 1);
  852.     fixcamerarange();
  853.     if(camera1!=player && !detachedcamera)
  854.     {
  855.         player->yaw = camera1->yaw;
  856.         player->pitch = camera1->pitch;
  857.     }
  858. }
  859.  
  860. void recomputecamera()
  861. {
  862.     game::setupcamera();
  863.     computezoom();
  864.  
  865.     bool shoulddetach = thirdperson > 1 || game::detachcamera();
  866.     if(!thirdperson && !shoulddetach)
  867.     {
  868.         camera1 = player;
  869.         detachedcamera = false;
  870.     }
  871.     else
  872.     {
  873.         static physent tempcamera;
  874.         camera1 = &tempcamera;
  875.         if(detachedcamera && shoulddetach) camera1->o = player->o;
  876.         else
  877.         {
  878.             *camera1 = *player;
  879.             detachedcamera = shoulddetach;
  880.         }
  881.         camera1->reset();
  882.         camera1->type = ENT_CAMERA;
  883.         camera1->collidetype = COLLIDE_AABB;
  884.         camera1->move = -1;
  885.         camera1->eyeheight = camera1->aboveeye = camera1->radius = camera1->xradius = camera1->yradius = 2;
  886.        
  887.         vec dir;
  888.         vecfromyawpitch(camera1->yaw, camera1->pitch, -1, 0, dir);
  889.         if(game::collidecamera())
  890.         {
  891.             movecamera(camera1, dir, thirdpersondistance, 1);
  892.             movecamera(camera1, dir, clamp(thirdpersondistance - camera1->o.dist(player->o), 0.0f, 1.0f), 0.1f);
  893.         }
  894.         else camera1->o.add(vec(dir).mul(thirdpersondistance));
  895.     }
  896.  
  897.     setviewcell(camera1->o);
  898. }
  899.  
  900. extern const glmatrixf viewmatrix(vec4(-1, 0, 0, 0), vec4(0, 0, 1, 0), vec4(0, -1, 0, 0));
  901. glmatrixf mvmatrix, projmatrix, mvpmatrix, invmvmatrix, invmvpmatrix;
  902.  
  903. void readmatrices()
  904. {
  905.     glGetFloatv(GL_MODELVIEW_MATRIX, mvmatrix.v);
  906.     glGetFloatv(GL_PROJECTION_MATRIX, projmatrix.v);
  907.  
  908.     mvpmatrix.mul(projmatrix, mvmatrix);
  909.     invmvmatrix.invert(mvmatrix);
  910.     invmvpmatrix.invert(mvpmatrix);
  911. }
  912.  
  913. FVAR(nearplane, 1e-3f, 0.54f, 1e3f);
  914.  
  915. void project(float fovy, float aspect, int farplane, bool flipx = false, bool flipy = false, bool swapxy = false, float zscale = 1)
  916. {
  917.     glMatrixMode(GL_PROJECTION);
  918.     glLoadIdentity();
  919.     if(swapxy) glRotatef(90, 0, 0, 1);
  920.     if(flipx || flipy!=swapxy || zscale!=1) glScalef(flipx ? -1 : 1, flipy!=swapxy ? -1 : 1, zscale);
  921.     GLdouble ydist = nearplane * tan(fovy/2*RAD), xdist = ydist * aspect;
  922.     glFrustum(-xdist, xdist, -ydist, ydist, nearplane, farplane);
  923.     glMatrixMode(GL_MODELVIEW);
  924. }
  925.  
  926. vec calcavatarpos(const vec &pos, float dist)
  927. {
  928.     vec eyepos;
  929.     mvmatrix.transform(pos, eyepos);
  930.     GLdouble ydist = nearplane * tan(curavatarfov/2*RAD), xdist = ydist * aspect;
  931.     vec4 scrpos;
  932.     scrpos.x = eyepos.x*nearplane/xdist;
  933.     scrpos.y = eyepos.y*nearplane/ydist;
  934.     scrpos.z = (eyepos.z*(farplane + nearplane) - 2*nearplane*farplane) / (farplane - nearplane);
  935.     scrpos.w = -eyepos.z;
  936.  
  937.     vec worldpos = invmvpmatrix.perspectivetransform(scrpos);
  938.     vec dir = vec(worldpos).sub(camera1->o).rescale(dist);
  939.     return dir.add(camera1->o);
  940. }
  941.  
  942. VAR(reflectclip, 0, 6, 64);
  943. VAR(reflectclipavatar, -64, 0, 64);
  944.  
  945. glmatrixf clipmatrix;
  946.  
  947. static const glmatrixf dummymatrix;
  948. static int projectioncount = 0;
  949. void pushprojection(const glmatrixf &m = dummymatrix)
  950. {
  951.     glMatrixMode(GL_PROJECTION);
  952.     if(projectioncount <= 0) glPushMatrix();
  953.     if(&m != &dummymatrix) glLoadMatrixf(m.v);
  954.     if(fogging)
  955.     {
  956.         glMultMatrixf(mvmatrix.v);
  957.         glMultMatrixf(invfogmatrix.v);
  958.     }
  959.     glMatrixMode(GL_MODELVIEW);
  960.     projectioncount++;
  961. }
  962.  
  963. void popprojection()
  964. {
  965.     --projectioncount;
  966.     glMatrixMode(GL_PROJECTION);
  967.     glPopMatrix();
  968.     if(projectioncount > 0)
  969.     {
  970.         glPushMatrix();
  971.         if(fogging)
  972.         {
  973.             glMultMatrixf(mvmatrix.v);
  974.             glMultMatrixf(invfogmatrix.v);
  975.         }
  976.     }
  977.     glMatrixMode(GL_MODELVIEW);
  978. }
  979.  
  980. FVAR(polygonoffsetfactor, -1e4f, -3.0f, 1e4f);
  981. FVAR(polygonoffsetunits, -1e4f, -3.0f, 1e4f);
  982. FVAR(depthoffset, -1e4f, 0.01f, 1e4f);
  983.  
  984. void enablepolygonoffset(GLenum type)
  985. {
  986.     if(!depthoffset)
  987.     {
  988.         glPolygonOffset(polygonoffsetfactor, polygonoffsetunits);
  989.         glEnable(type);
  990.         return;
  991.     }
  992.    
  993.     bool clipped = reflectz < 1e15f && reflectclip;
  994.  
  995.     glmatrixf offsetmatrix = clipped ? clipmatrix : projmatrix;
  996.     offsetmatrix[14] += depthoffset * projmatrix[10];
  997.  
  998.     glMatrixMode(GL_PROJECTION);
  999.     if(!clipped) glPushMatrix();
  1000.     glLoadMatrixf(offsetmatrix.v);
  1001.     if(fogging)
  1002.     {
  1003.         glMultMatrixf(mvmatrix.v);
  1004.         glMultMatrixf(invfogmatrix.v);
  1005.     }
  1006.     glMatrixMode(GL_MODELVIEW);
  1007. }
  1008.  
  1009. void disablepolygonoffset(GLenum type)
  1010. {
  1011.     if(!depthoffset)
  1012.     {
  1013.         glDisable(type);
  1014.         return;
  1015.     }
  1016.    
  1017.     bool clipped = reflectz < 1e15f && reflectclip;
  1018.  
  1019.     glMatrixMode(GL_PROJECTION);
  1020.     if(clipped)
  1021.     {
  1022.         glLoadMatrixf(clipmatrix.v);
  1023.         if(fogging)
  1024.         {
  1025.             glMultMatrixf(mvmatrix.v);
  1026.             glMultMatrixf(invfogmatrix.v);
  1027.         }
  1028.     }
  1029.     else glPopMatrix();
  1030.     glMatrixMode(GL_MODELVIEW);
  1031. }
  1032.  
  1033. void calcspherescissor(const vec &center, float size, float &sx1, float &sy1, float &sx2, float &sy2)
  1034. {
  1035.     vec worldpos(center);
  1036.     if(reflecting) worldpos.z = 2*reflectz - worldpos.z;
  1037.     vec e(mvmatrix.transformx(worldpos),
  1038.           mvmatrix.transformy(worldpos),
  1039.           mvmatrix.transformz(worldpos));
  1040.     if(e.z > 2*size) { sx1 = sy1 = 1; sx2 = sy2 = -1; return; }
  1041.     float zzrr = e.z*e.z - size*size,
  1042.           dx = e.x*e.x + zzrr, dy = e.y*e.y + zzrr,
  1043.           focaldist = 1.0f/tan(fovy*0.5f*RAD);
  1044.     sx1 = sy1 = -1;
  1045.     sx2 = sy2 = 1;
  1046.     #define CHECKPLANE(c, dir, focaldist, low, high) \
  1047.     do { \
  1048.         float nzc = (cz*cz + 1) / (cz dir drt) - cz, \
  1049.               pz = (d##c)/(nzc*e.c - e.z); \
  1050.         if(pz > 0) \
  1051.         { \
  1052.             float c = (focaldist)*nzc, \
  1053.                   pc = pz*nzc; \
  1054.             if(pc < e.c) low = c; \
  1055.             else if(pc > e.c) high = c; \
  1056.         } \
  1057.     } while(0)
  1058.     if(dx > 0)
  1059.     {
  1060.         float cz = e.x/e.z, drt = sqrtf(dx)/size;
  1061.         CHECKPLANE(x, -, focaldist/aspect, sx1, sx2);
  1062.         CHECKPLANE(x, +, focaldist/aspect, sx1, sx2);
  1063.     }
  1064.     if(dy > 0)
  1065.     {
  1066.         float cz = e.y/e.z, drt = sqrtf(dy)/size;
  1067.         CHECKPLANE(y, -, focaldist, sy1, sy2);
  1068.         CHECKPLANE(y, +, focaldist, sy1, sy2);
  1069.     }
  1070. }
  1071.  
  1072. static int scissoring = 0;
  1073. static GLint oldscissor[4];
  1074.  
  1075. int pushscissor(float sx1, float sy1, float sx2, float sy2)
  1076. {
  1077.     scissoring = 0;
  1078.  
  1079.     if(sx1 <= -1 && sy1 <= -1 && sx2 >= 1 && sy2 >= 1) return 0;
  1080.  
  1081.     sx1 = max(sx1, -1.0f);
  1082.     sy1 = max(sy1, -1.0f);
  1083.     sx2 = min(sx2, 1.0f);
  1084.     sy2 = min(sy2, 1.0f);
  1085.  
  1086.     GLint viewport[4];
  1087.     glGetIntegerv(GL_VIEWPORT, viewport);
  1088.     int sx = viewport[0] + int(floor((sx1+1)*0.5f*viewport[2])),
  1089.         sy = viewport[1] + int(floor((sy1+1)*0.5f*viewport[3])),
  1090.         sw = viewport[0] + int(ceil((sx2+1)*0.5f*viewport[2])) - sx,
  1091.         sh = viewport[1] + int(ceil((sy2+1)*0.5f*viewport[3])) - sy;
  1092.     if(sw <= 0 || sh <= 0) return 0;
  1093.  
  1094.     if(glIsEnabled(GL_SCISSOR_TEST))
  1095.     {
  1096.         glGetIntegerv(GL_SCISSOR_BOX, oldscissor);
  1097.         sw += sx;
  1098.         sh += sy;
  1099.         sx = max(sx, int(oldscissor[0]));
  1100.         sy = max(sy, int(oldscissor[1]));
  1101.         sw = min(sw, int(oldscissor[0] + oldscissor[2])) - sx;
  1102.         sh = min(sh, int(oldscissor[1] + oldscissor[3])) - sy;
  1103.         if(sw <= 0 || sh <= 0) return 0;
  1104.         scissoring = 2;
  1105.     }
  1106.     else scissoring = 1;
  1107.  
  1108.     glScissor(sx, sy, sw, sh);
  1109.     if(scissoring<=1) glEnable(GL_SCISSOR_TEST);
  1110.    
  1111.     return scissoring;
  1112. }
  1113.  
  1114. void popscissor()
  1115. {
  1116.     if(scissoring>1) glScissor(oldscissor[0], oldscissor[1], oldscissor[2], oldscissor[3]);
  1117.     else if(scissoring) glDisable(GL_SCISSOR_TEST);
  1118.     scissoring = 0;
  1119. }
  1120.  
  1121. glmatrixf envmatrix;
  1122.  
  1123. void setenvmatrix()
  1124. {
  1125.     envmatrix = fogging ? fogmatrix : mvmatrix;
  1126.     if(reflecting) envmatrix.reflectz(reflectz);
  1127.     envmatrix.transpose();
  1128. }
  1129.  
  1130. VARR(fog, 16, 4000, 1000024);
  1131. bvec fogcolor(0x80, 0x99, 0xB3);
  1132. HVARFR(fogcolour, 0, 0x8099B3, 0xFFFFFF,
  1133. {
  1134.     fogcolor = bvec((fogcolour>>16)&0xFF, (fogcolour>>8)&0xFF, fogcolour&0xFF);
  1135. });
  1136.  
  1137. static float findsurface(int fogmat, const vec &v, int &abovemat)
  1138. {
  1139.     ivec o(v), co;
  1140.     int csize;
  1141.     do
  1142.     {
  1143.         cube &c = lookupcube(o.x, o.y, o.z, 0, co, csize);
  1144.         if(!c.ext || (c.ext->material&MATF_VOLUME) != fogmat)
  1145.         {
  1146.             abovemat = c.ext && isliquid(c.ext->material&MATF_VOLUME) ? c.ext->material&MATF_VOLUME : MAT_AIR;
  1147.             return o.z;
  1148.         }
  1149.         o.z = co.z + csize;
  1150.     }
  1151.     while(o.z < worldsize);
  1152.     abovemat = MAT_AIR;
  1153.     return worldsize;
  1154. }
  1155.  
  1156. static void blendfog(int fogmat, float blend, float logblend, float &start, float &end, float *fogc)
  1157. {
  1158.     switch(fogmat)
  1159.     {
  1160.         case MAT_WATER:
  1161.             loopk(3) fogc[k] += blend*watercolor[k]/255.0f;
  1162.             end += logblend*min(fog, max(waterfog*4, 32));
  1163.             break;
  1164.  
  1165.         case MAT_LAVA:
  1166.             loopk(3) fogc[k] += blend*lavacolor[k]/255.0f;
  1167.             end += logblend*min(fog, max(lavafog*4, 32));
  1168.             break;
  1169.  
  1170.         default:
  1171.             loopk(3) fogc[k] += blend*fogcolor[k]/255.0f;
  1172.             start += logblend*(fog+64)/8;
  1173.             end += logblend*fog;
  1174.             break;
  1175.     }
  1176. }
  1177.  
  1178. static void setfog(int fogmat, float below = 1, int abovemat = MAT_AIR)
  1179. {
  1180.     float fogc[4] = { 0, 0, 0, 1 };
  1181.     float start = 0, end = 0;
  1182.     float logscale = 256, logblend = log(1 + (logscale - 1)*below) / log(logscale);
  1183.  
  1184.     blendfog(fogmat, below, logblend, start, end, fogc);
  1185.     if(below < 1) blendfog(abovemat, 1-below, 1-logblend, start, end, fogc);
  1186.  
  1187.     glFogf(GL_FOG_START, start);
  1188.     glFogf(GL_FOG_END, end);
  1189.     glFogfv(GL_FOG_COLOR, fogc);
  1190.     glClearColor(fogc[0], fogc[1], fogc[2], 1.0f);
  1191. }
  1192.  
  1193. static void blendfogoverlay(int fogmat, float blend, float *overlay)
  1194. {
  1195.     float maxc;
  1196.     switch(fogmat)
  1197.     {
  1198.         case MAT_WATER:
  1199.             maxc = max(watercolor[0], max(watercolor[1], watercolor[2]));
  1200.             loopk(3) overlay[k] += blend*max(0.4f, watercolor[k]/min(32.0f + maxc*7.0f/8.0f, 255.0f));
  1201.             break;
  1202.  
  1203.         case MAT_LAVA:
  1204.             maxc = max(lavacolor[0], max(lavacolor[1], lavacolor[2]));
  1205.             loopk(3) overlay[k] += blend*max(0.4f, lavacolor[k]/min(32.0f + maxc*7.0f/8.0f, 255.0f));
  1206.             break;
  1207.  
  1208.         default:
  1209.             loopk(3) overlay[k] += blend;
  1210.             break;
  1211.     }
  1212. }
  1213.  
  1214. void drawfogoverlay(int fogmat, float fogblend, int abovemat)
  1215. {
  1216.     notextureshader->set();
  1217.     glDisable(GL_TEXTURE_2D);
  1218.  
  1219.     glEnable(GL_BLEND);
  1220.     glBlendFunc(GL_ZERO, GL_SRC_COLOR);
  1221.     float overlay[3] = { 0, 0, 0 };
  1222.     blendfogoverlay(fogmat, fogblend, overlay);
  1223.     blendfogoverlay(abovemat, 1-fogblend, overlay);
  1224.  
  1225.     glMatrixMode(GL_PROJECTION);
  1226.     glPushMatrix();
  1227.     glLoadIdentity();
  1228.  
  1229.     glMatrixMode(GL_MODELVIEW);
  1230.     glPushMatrix();
  1231.     glLoadIdentity();
  1232.  
  1233.     glColor3fv(overlay);
  1234.     glBegin(GL_TRIANGLE_STRIP);
  1235.     glVertex2f(-1, -1);
  1236.     glVertex2f(1, -1);
  1237.     glVertex2f(-1, 1);
  1238.     glVertex2f(1, 1);
  1239.     glEnd();
  1240.     glDisable(GL_BLEND);
  1241.  
  1242.     glMatrixMode(GL_PROJECTION);
  1243.     glPopMatrix();
  1244.  
  1245.     glMatrixMode(GL_MODELVIEW);
  1246.     glPopMatrix();
  1247.  
  1248.     glEnable(GL_TEXTURE_2D);
  1249.     defaultshader->set();
  1250. }
  1251.  
  1252. bool renderedgame = false;
  1253.  
  1254. void rendergame(bool mainpass)
  1255. {
  1256.     game::rendergame(mainpass);
  1257.     if(!shadowmapping) renderedgame = true;
  1258. }
  1259.  
  1260. VARP(skyboxglare, 0, 1, 1);
  1261.  
  1262. void drawglare()
  1263. {
  1264.     glaring = true;
  1265.     refracting = -1;
  1266.  
  1267.     float oldfogstart, oldfogend, oldfogcolor[4], zerofog[4] = { 0, 0, 0, 1 };
  1268.     glGetFloatv(GL_FOG_START, &oldfogstart);
  1269.     glGetFloatv(GL_FOG_END, &oldfogend);
  1270.     glGetFloatv(GL_FOG_COLOR, oldfogcolor);
  1271.  
  1272.     glFogf(GL_FOG_START, (fog+64)/8);
  1273.     glFogf(GL_FOG_END, fog);
  1274.     glFogfv(GL_FOG_COLOR, zerofog);
  1275.  
  1276.     glClearColor(0, 0, 0, 1);
  1277.     glClear((skyboxglare ? 0 : GL_COLOR_BUFFER_BIT) | GL_DEPTH_BUFFER_BIT);
  1278.  
  1279.     rendergeom();
  1280.  
  1281.     if(skyboxglare) drawskybox(farplane, false);
  1282.  
  1283.     renderreflectedmapmodels();
  1284.     rendergame();
  1285.     if(!isthirdperson())
  1286.     {
  1287.         project(curavatarfov, aspect, farplane, false, false, false, avatardepth);
  1288.         game::renderavatar();
  1289.         project(fovy, aspect, farplane);
  1290.     }
  1291.  
  1292.     renderwater();
  1293.     rendermaterials();
  1294.     renderalphageom();
  1295.     renderparticles();
  1296.  
  1297.     glFogf(GL_FOG_START, oldfogstart);
  1298.     glFogf(GL_FOG_END, oldfogend);
  1299.     glFogfv(GL_FOG_COLOR, oldfogcolor);
  1300.  
  1301.     refracting = 0;
  1302.     glaring = false;
  1303. }
  1304.  
  1305. VARP(reflectmms, 0, 1, 1);
  1306. VARR(refractsky, 0, 0, 1);
  1307.  
  1308. glmatrixf fogmatrix, invfogmatrix;
  1309.  
  1310. void drawreflection(float z, bool refract)
  1311. {
  1312.     reflectz = z < 0 ? 1e16f : z;
  1313.     reflecting = !refract;
  1314.     refracting = refract ? (z < 0 || camera1->o.z >= z ? -1 : 1) : 0;
  1315.     fading = renderpath!=R_FIXEDFUNCTION && waterrefract && waterfade && hasFBO && z>=0;
  1316.     fogging = refracting<0 && z>=0;
  1317.  
  1318.     float oldfogstart, oldfogend, oldfogcolor[4];
  1319.     glGetFloatv(GL_FOG_START, &oldfogstart);
  1320.     glGetFloatv(GL_FOG_END, &oldfogend);
  1321.     glGetFloatv(GL_FOG_COLOR, oldfogcolor);
  1322.  
  1323.     if(fogging)
  1324.     {
  1325.         glFogf(GL_FOG_START, camera1->o.z - z);
  1326.         glFogf(GL_FOG_END, camera1->o.z - (z-waterfog));
  1327.         GLfloat m[16] =
  1328.         {
  1329.              1,   0,  0, 0,
  1330.              0,   1,  0, 0,
  1331.              0,   0,  1, 0,
  1332.             -camera1->o.x, -camera1->o.y, -camera1->o.z, 1
  1333.         };
  1334.         memcpy(fogmatrix.v, m, sizeof(m));
  1335.         invfogmatrix.invert(fogmatrix);
  1336.         pushprojection();
  1337.         glPushMatrix();
  1338.         glLoadMatrixf(fogmatrix.v);
  1339.         float fogc[4] = { watercolor.x/255.0f, watercolor.y/255.0f, watercolor.z/255.0f, 1.0f };
  1340.         glFogfv(GL_FOG_COLOR, fogc);
  1341.     }
  1342.     else
  1343.     {
  1344.         glFogf(GL_FOG_START, (fog+64)/8);
  1345.         glFogf(GL_FOG_END, fog);
  1346.         float fogc[4] = { fogcolor.x/255.0f, fogcolor.y/255.0f, fogcolor.z/255.0f, 1.0f };
  1347.         glFogfv(GL_FOG_COLOR, fogc);
  1348.     }
  1349.  
  1350.     if(fading)
  1351.     {
  1352.         float scale = fogging ? -0.25f : 0.25f, offset = 2*fabs(scale) - scale*z;
  1353.         setenvparamf("waterfadeparams", SHPARAM_VERTEX, 8, scale, offset, -scale, offset + camera1->o.z*scale);
  1354.         setenvparamf("waterfadeparams", SHPARAM_PIXEL, 8, scale, offset, -scale, offset + camera1->o.z*scale);
  1355.     }
  1356.  
  1357.     if(reflecting)
  1358.     {
  1359.         glPushMatrix();
  1360.         glTranslatef(0, 0, 2*z);
  1361.         glScalef(1, 1, -1);
  1362.  
  1363.         glFrontFace(GL_CCW);
  1364.     }
  1365.  
  1366.     setenvmatrix();
  1367.  
  1368.     if(reflectclip && z>=0)
  1369.     {
  1370.         float zoffset = reflectclip/4.0f, zclip;
  1371.         if(refracting<0)
  1372.         {
  1373.             zclip = z+zoffset;
  1374.             if(camera1->o.z<=zclip) zclip = z;
  1375.         }
  1376.         else
  1377.         {
  1378.             zclip = z-zoffset;
  1379.             if(camera1->o.z>=zclip && camera1->o.z<=z+4.0f) zclip = z;
  1380.             if(reflecting) zclip = 2*z - zclip;
  1381.         }
  1382.         plane clipplane;
  1383.         invmvmatrix.transposedtransform(plane(0, 0, refracting>0 ? 1 : -1, refracting>0 ? -zclip : zclip), clipplane);
  1384.         clipmatrix.clip(clipplane, projmatrix);
  1385.         pushprojection(clipmatrix);
  1386.     }
  1387.  
  1388.     renderreflectedgeom(refracting<0 && z>=0 && caustics, fogging);
  1389.  
  1390.     if(reflecting || refracting>0 || (refracting<0 && refractsky) || z<0)
  1391.     {
  1392.         if(fading) glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  1393.         if(reflectclip && z>=0) popprojection();
  1394.         if(fogging)
  1395.         {
  1396.             popprojection();
  1397.             glPopMatrix();
  1398.         }
  1399.         drawskybox(farplane, false);
  1400.         if(fogging)
  1401.         {
  1402.             pushprojection();
  1403.             glPushMatrix();
  1404.             glLoadMatrixf(fogmatrix.v);
  1405.         }
  1406.         if(reflectclip && z>=0) pushprojection(clipmatrix);
  1407.         if(fading) glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
  1408.     }
  1409.     else if(fading) glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
  1410.  
  1411.     renderdecals();
  1412.  
  1413.     if(reflectmms) renderreflectedmapmodels();
  1414.     rendergame();
  1415.  
  1416.     if(refracting && z>=0 && !isthirdperson() && fabs(camera1->o.z-z) <= 0.5f*(player->eyeheight + player->aboveeye))
  1417.     {  
  1418.         glmatrixf avatarproj;
  1419.         avatarproj.perspective(curavatarfov, aspect, nearplane, farplane);
  1420.         if(reflectclip)
  1421.         {
  1422.             popprojection();
  1423.             glmatrixf avatarclip;
  1424.             plane clipplane;
  1425.             invmvmatrix.transposedtransform(plane(0, 0, refracting, reflectclipavatar/4.0f - refracting*z), clipplane);
  1426.             avatarclip.clip(clipplane, avatarproj);
  1427.             pushprojection(avatarclip);
  1428.         }
  1429.         else pushprojection(avatarproj);
  1430.         game::renderavatar();
  1431.         popprojection();
  1432.         if(reflectclip) pushprojection(clipmatrix);
  1433.     }
  1434.  
  1435.     if(refracting) rendergrass();
  1436.     rendermaterials();
  1437.     renderalphageom(fogging);
  1438.     renderparticles();
  1439.  
  1440.     if(fading) glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  1441.  
  1442.     if(reflectclip && z>=0) popprojection();
  1443.  
  1444.     if(reflecting)
  1445.     {
  1446.         glPopMatrix();
  1447.  
  1448.         glFrontFace(GL_CW);
  1449.     }
  1450.  
  1451.     if(fogging)
  1452.     {
  1453.         popprojection();
  1454.         glPopMatrix();
  1455.     }
  1456.     glFogf(GL_FOG_START, oldfogstart);
  1457.     glFogf(GL_FOG_END, oldfogend);
  1458.     glFogfv(GL_FOG_COLOR, oldfogcolor);
  1459.    
  1460.     reflectz = 1e16f;
  1461.     refracting = 0;
  1462.     reflecting = fading = fogging = false;
  1463.  
  1464.     setenvmatrix();
  1465. }
  1466.  
  1467. bool envmapping = false;
  1468.  
  1469. void drawcubemap(int size, const vec &o, float yaw, float pitch, const cubemapside &side)
  1470. {
  1471.     envmapping = true;
  1472.  
  1473.     physent *oldcamera = camera1;
  1474.     static physent cmcamera;
  1475.     cmcamera = *player;
  1476.     cmcamera.reset();
  1477.     cmcamera.type = ENT_CAMERA;
  1478.     cmcamera.o = o;
  1479.     cmcamera.yaw = yaw;
  1480.     cmcamera.pitch = pitch;
  1481.     cmcamera.roll = 0;
  1482.     camera1 = &cmcamera;
  1483.     setviewcell(camera1->o);
  1484.    
  1485.     defaultshader->set();
  1486.  
  1487.     int fogmat = lookupmaterial(o)&MATF_VOLUME;
  1488.     if(fogmat!=MAT_WATER && fogmat!=MAT_LAVA) fogmat = MAT_AIR;
  1489.  
  1490.     setfog(fogmat);
  1491.  
  1492.     glClear(GL_DEPTH_BUFFER_BIT);
  1493.  
  1494.     int farplane = worldsize*2;
  1495.  
  1496.     project(90.0f, 1.0f, farplane, !side.flipx, !side.flipy, side.swapxy);
  1497.  
  1498.     transplayer();
  1499.     readmatrices();
  1500.     findorientation();
  1501.     setenvmatrix();
  1502.  
  1503.     glEnable(GL_FOG);
  1504.     glEnable(GL_CULL_FACE);
  1505.     glEnable(GL_DEPTH_TEST);
  1506.     glEnable(GL_TEXTURE_2D);
  1507.  
  1508.     xtravertsva = xtraverts = glde = gbatches = 0;
  1509.  
  1510.     visiblecubes();
  1511.  
  1512.     if(limitsky()) drawskybox(farplane, true);
  1513.  
  1514.     rendergeom();
  1515.  
  1516.     if(!limitsky()) drawskybox(farplane, false);
  1517.  
  1518. //    queryreflections();
  1519.  
  1520.     rendermapmodels();
  1521.     renderalphageom();
  1522.  
  1523. //    drawreflections();
  1524.  
  1525. //    renderwater();
  1526. //    rendermaterials();
  1527.  
  1528.     glDisable(GL_TEXTURE_2D);
  1529.     glDisable(GL_DEPTH_TEST);
  1530.     glDisable(GL_CULL_FACE);
  1531.     glDisable(GL_FOG);
  1532.  
  1533.     camera1 = oldcamera;
  1534.     envmapping = false;
  1535. }
  1536.  
  1537. bool minimapping = false;
  1538.  
  1539. GLuint minimaptex = 0;
  1540. vec minimapcenter(0, 0, 0), minimapradius(0, 0, 0), minimapscale(0, 0, 0);
  1541.  
  1542. void clearminimap()
  1543. {
  1544.     if(minimaptex) { glDeleteTextures(1, &minimaptex); minimaptex = 0; }
  1545. }
  1546.  
  1547. VARR(minimapheight, 0, 0, 2<<16);
  1548. bvec minimapcolor(0, 0, 0);
  1549. HVARFR(minimapcolour, 0, 0, 0xFFFFFF,
  1550. {
  1551.     minimapcolor = bvec((minimapcolour>>16)&0xFF, (minimapcolour>>8)&0xFF, minimapcolour&0xFF);
  1552. });
  1553. VARR(minimapclip, 0, 0, 1);
  1554. VARFP(minimapsize, 7, 8, 10, { if(minimaptex) drawminimap(); });
  1555.  
  1556. void bindminimap()
  1557. {
  1558.     glBindTexture(GL_TEXTURE_2D, minimaptex);
  1559. }
  1560.  
  1561. void clipminimap(ivec &bbmin, ivec &bbmax, cube *c = worldroot, int x = 0, int y = 0, int z = 0, int size = worldsize>>1)
  1562. {
  1563.     loopi(8)
  1564.     {
  1565.         ivec o(i, x, y, z, size);
  1566.         if(c[i].children) clipminimap(bbmin, bbmax, c[i].children, o.x, o.y, o.z, size>>1);
  1567.         else if(!isentirelysolid(c[i]) && (!c[i].ext || (c[i].ext->material&MATF_CLIP)!=MAT_CLIP))
  1568.         {
  1569.             loopk(3) bbmin[k] = min(bbmin[k], o[k]);
  1570.             loopk(3) bbmax[k] = max(bbmax[k], o[k] + size);
  1571.         }
  1572.     }
  1573. }
  1574.  
  1575. void drawminimap()
  1576. {
  1577.     if(!game::needminimap()) { clearminimap(); return; }
  1578.  
  1579.     renderprogress(0, "generating mini-map...", 0, !renderedframe);
  1580.  
  1581.     int size = 1<<minimapsize, sizelimit = min(hwtexsize, min(screen->w, screen->h));
  1582.     while(size > sizelimit) size /= 2;
  1583.     if(!minimaptex) glGenTextures(1, &minimaptex);
  1584.  
  1585.     extern vector<vtxarray *> valist;
  1586.     ivec bbmin(worldsize, worldsize, worldsize), bbmax(0, 0, 0);
  1587.     loopv(valist)
  1588.     {
  1589.         vtxarray *va = valist[i];
  1590.         loopk(3)
  1591.         {
  1592.             if(va->geommin[k]>va->geommax[k]) continue;
  1593.             bbmin[k] = min(bbmin[k], va->geommin[k]);
  1594.             bbmax[k] = max(bbmax[k], va->geommax[k]);
  1595.         }
  1596.     }
  1597.     if(minimapclip)
  1598.     {
  1599.         ivec clipmin(worldsize, worldsize, worldsize), clipmax(0, 0, 0);
  1600.         clipminimap(clipmin, clipmax);
  1601.         loopk(2) bbmin[k] = max(bbmin[k], clipmin[k]);
  1602.         loopk(2) bbmax[k] = min(bbmax[k], clipmax[k]);
  1603.     }
  1604.  
  1605.     minimapradius = bbmax.tovec().sub(bbmin.tovec()).mul(0.5f);
  1606.     minimapcenter = bbmin.tovec().add(minimapradius);
  1607.     minimapradius.x = minimapradius.y = max(minimapradius.x, minimapradius.y);
  1608.     minimapscale = vec((0.5f - 1.0f/size)/minimapradius.x, (0.5f - 1.0f/size)/minimapradius.y, 1.0f);
  1609.  
  1610.     envmapping = minimapping = true;
  1611.  
  1612.     physent *oldcamera = camera1;
  1613.     static physent cmcamera;
  1614.     cmcamera = *player;
  1615.     cmcamera.reset();
  1616.     cmcamera.type = ENT_CAMERA;
  1617.     cmcamera.o = vec(minimapcenter.x, minimapcenter.y, max(minimapcenter.z + minimapradius.z + 1, float(minimapheight)));
  1618.     cmcamera.yaw = 0;
  1619.     cmcamera.pitch = -90;
  1620.     cmcamera.roll = 0;
  1621.     camera1 = &cmcamera;
  1622.     setviewcell(vec(-1, -1, -1));
  1623.  
  1624.     glMatrixMode(GL_PROJECTION);
  1625.     glLoadIdentity();
  1626.     glOrtho(-minimapradius.x, minimapradius.x, -minimapradius.y, minimapradius.y, 0, camera1->o.z + 1);
  1627.     glScalef(-1, 1, 1);
  1628.     glMatrixMode(GL_MODELVIEW);
  1629.  
  1630.     transplayer();
  1631.  
  1632.     defaultshader->set();
  1633.  
  1634.     GLfloat fogc[4] = { minimapcolor.x/255.0f, minimapcolor.y/255.0f, minimapcolor.z/255.0f, 1.0f };
  1635.     glFogf(GL_FOG_START, 0);
  1636.     glFogf(GL_FOG_END, 1000000);
  1637.     glFogfv(GL_FOG_COLOR, fogc);
  1638.  
  1639.     glClearColor(fogc[0], fogc[1], fogc[2], fogc[3]);
  1640.     glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
  1641.  
  1642.     glViewport(1, 1, size-2, size-2);
  1643.     glScissor(1, 1, size-2, size-2);
  1644.     glEnable(GL_SCISSOR_TEST);
  1645.  
  1646.     glDisable(GL_FOG);
  1647.     glEnable(GL_CULL_FACE);
  1648.     glEnable(GL_DEPTH_TEST);
  1649.     glEnable(GL_TEXTURE_2D);
  1650.  
  1651.     glFrontFace(GL_CCW);
  1652.  
  1653.     xtravertsva = xtraverts = glde = gbatches = 0;
  1654.  
  1655.     visiblecubes(false);
  1656.     queryreflections();
  1657.     drawreflections();
  1658.  
  1659.     loopi(minimapheight > 0 && minimapheight < minimapcenter.z + minimapradius.z ? 2 : 1)
  1660.     {
  1661.         if(i)
  1662.         {
  1663.             glClear(GL_DEPTH_BUFFER_BIT);
  1664.             camera1->o.z = minimapheight;
  1665.             transplayer();
  1666.         }
  1667.         rendergeom();
  1668.         rendermapmodels();
  1669.         renderwater();
  1670.         rendermaterials();
  1671.         renderalphageom();
  1672.     }
  1673.  
  1674.     glFrontFace(GL_CW);
  1675.  
  1676.     glDisable(GL_TEXTURE_2D);
  1677.     glDisable(GL_DEPTH_TEST);
  1678.     glDisable(GL_CULL_FACE);
  1679.     glDisable(GL_FOG);
  1680.  
  1681.     glDisable(GL_SCISSOR_TEST);
  1682.     glViewport(0, 0, screen->w, screen->h);
  1683.  
  1684.     camera1 = oldcamera;
  1685.     envmapping = minimapping = false;
  1686.  
  1687.     glBindTexture(GL_TEXTURE_2D, minimaptex);
  1688.     glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5, 0, 0, size, size, 0);
  1689.     setuptexparameters(minimaptex, NULL, 3, 1, GL_RGB5, GL_TEXTURE_2D);
  1690.     glBindTexture(GL_TEXTURE_2D, 0);
  1691. }
  1692.  
  1693. GLuint motiontex = 0;
  1694. int motionw = 0, motionh = 0, lastmotion = 0;
  1695.  
  1696. void cleanupmotionblur()
  1697. {
  1698.     if(motiontex) { glDeleteTextures(1, &motiontex); motiontex = 0; }
  1699.     motionw = motionh = 0;
  1700.     lastmotion = 0;
  1701. }
  1702.  
  1703. VARFP(motionblur, 0, 0, 1, { if(!motionblur) cleanupmotionblur(); });
  1704. VARP(motionblurmillis, 1, 5, 1000);
  1705. FVARP(motionblurscale, 0, 0.5f, 1);
  1706.  
  1707. void addmotionblur()
  1708. {
  1709.     if(!motionblur || !hasTR || max(screen->w, screen->h) > hwtexsize) return;
  1710.  
  1711.     if(paused || game::ispaused()) { lastmotion = 0; return; }
  1712.  
  1713.     if(!motiontex || motionw != screen->w || motionh != screen->h)
  1714.     {
  1715.         if(!motiontex) glGenTextures(1, &motiontex);
  1716.         motionw = screen->w;
  1717.         motionh = screen->h;
  1718.         lastmotion = 0;
  1719.         createtexture(motiontex, motionw, motionh, NULL, 3, 0, GL_RGB, GL_TEXTURE_RECTANGLE_ARB);
  1720.     }
  1721.  
  1722.     glBindTexture(GL_TEXTURE_RECTANGLE_ARB, motiontex);
  1723.  
  1724.     glMatrixMode(GL_PROJECTION);
  1725.     glPushMatrix();
  1726.     glLoadIdentity();
  1727.  
  1728.     glMatrixMode(GL_MODELVIEW);
  1729.     glPushMatrix();
  1730.     glLoadIdentity();
  1731.  
  1732.     glEnable(GL_BLEND);
  1733.     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  1734.  
  1735.     glDisable(GL_TEXTURE_2D);
  1736.     glEnable(GL_TEXTURE_RECTANGLE_ARB);
  1737.  
  1738.     rectshader->set();
  1739.  
  1740.     glColor4f(1, 1, 1, lastmotion ? pow(motionblurscale, max(float(lastmillis - lastmotion)/motionblurmillis, 1.0f)) : 0);
  1741.     glBegin(GL_TRIANGLE_STRIP);
  1742.     glTexCoord2f(      0,       0); glVertex2f(-1, -1);
  1743.     glTexCoord2f(motionw,       0); glVertex2f( 1, -1);
  1744.     glTexCoord2f(      0, motionh); glVertex2f(-1,  1);
  1745.     glTexCoord2f(motionw, motionh); glVertex2f( 1,  1);
  1746.     glEnd();
  1747.  
  1748.     glDisable(GL_TEXTURE_RECTANGLE_ARB);
  1749.     glEnable(GL_TEXTURE_2D);
  1750.  
  1751.     glDisable(GL_BLEND);
  1752.  
  1753.     glMatrixMode(GL_PROJECTION);
  1754.     glPopMatrix();
  1755.  
  1756.     glMatrixMode(GL_MODELVIEW);
  1757.     glPopMatrix();
  1758.  
  1759.     if(lastmillis - lastmotion >= motionblurmillis)
  1760.     {
  1761.         lastmotion = lastmillis - lastmillis%motionblurmillis;
  1762.  
  1763.         glCopyTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, 0, 0, screen->w, screen->h);
  1764.     }
  1765. }
  1766.  
  1767. bool dopostfx = false;
  1768.  
  1769. void invalidatepostfx()
  1770. {
  1771.     dopostfx = false;
  1772. }
  1773. extern fpsent *player1 = NULL;
  1774. int GetBestTarget()
  1775. {
  1776.     int ttarget=-1;
  1777.     if(lasttarget != -1 && players[lasttarget]->state == CS_ALIVE && players[lasttarget] != NULL && player1 != NULL && player1->state == CS_ALIVE)
  1778.     {
  1779.         if(IsVisible(player1->o, players[lasttarget]->o)==true)
  1780.         {
  1781.             return lasttarget; // our old target is visible so lets keep aiming for him =D
  1782.         }
  1783.     }
  1784.     loopv(players)
  1785.     {
  1786.         if(players[i] == NULL || player1 == NULL || players[i] == player1) // if player or a possible target is null, or if our possible target is ourselves skip  it.
  1787.         {
  1788.             continue;
  1789.         }
  1790.         if(players[i]->state == CS_ALIVE && player1->state == CS_ALIVE) // if we're both alive.
  1791.         {
  1792.             if(isteam(player1->team, players[i]->team)) // if our target is on our team skip it.
  1793.             {
  1794.                 continue;
  1795.             }
  1796.             float tDist = Get2DDistance(player1->o, players[i]->o); // assign tDist with the 2d distance between us and our temporary target
  1797.             if(IsVisible(player1->o, players[i]->o) && tDist<bestdist) //if he is visible and closer then the previous visible enemies
  1798.             {
  1799.                 ttarget=i; // set him as our temporary target
  1800.                 bestdist=tDist; // set the last distance as the best distance
  1801.             }
  1802.         }  
  1803.     }
  1804.     if(ttarget==-1)
  1805.     {
  1806.         lasttarget=-1;
  1807.         return -1;
  1808.     }
  1809.     lasttarget=ttarget; // assign the current target as last target
  1810.     bestdist=0.0f; //reset the best distance so we wont fuck up next time we call the target function
  1811.     return ttarget; // return the temp target
  1812. }
  1813.  
  1814. void gl_drawhud(int w, int h);
  1815.  
  1816. int xtraverts, xtravertsva;
  1817.  
  1818. void gl_drawframe(int w, int h)
  1819. {
  1820.     defaultshader->set();
  1821.  
  1822.     updatedynlights();
  1823.  
  1824.     aspect = w/float(h);
  1825.     fovy = 2*atan2(tan(curfov/2*RAD), aspect)/RAD;
  1826.    
  1827.     int fogmat = lookupmaterial(camera1->o)&MATF_VOLUME, abovemat = MAT_AIR;
  1828.     float fogblend = 1.0f, causticspass = 0.0f;
  1829.     if(fogmat==MAT_WATER || fogmat==MAT_LAVA)
  1830.     {
  1831.         float z = findsurface(fogmat, camera1->o, abovemat) - WATER_OFFSET;
  1832.         if(camera1->o.z < z + 1) fogblend = min(z + 1 - camera1->o.z, 1.0f);
  1833.         else fogmat = abovemat;
  1834.         if(caustics && fogmat==MAT_WATER && camera1->o.z < z)
  1835.             causticspass = renderpath==R_FIXEDFUNCTION ? 1.0f : min(z - camera1->o.z, 1.0f);
  1836.     }
  1837.     else fogmat = MAT_AIR;    
  1838.     setfog(fogmat, fogblend, abovemat);
  1839.     if(fogmat!=MAT_AIR)
  1840.     {
  1841.         float blend = abovemat==MAT_AIR ? fogblend : 1.0f;
  1842.         fovy += blend*sinf(lastmillis/1000.0)*2.0f;
  1843.         aspect += blend*sinf(lastmillis/1000.0+PI)*0.1f;
  1844.     }
  1845.  
  1846.     farplane = worldsize*2;
  1847.  
  1848.     project(fovy, aspect, farplane);
  1849.     transplayer();
  1850.     readmatrices();
  1851.     findorientation();
  1852.     setenvmatrix();
  1853.  
  1854.     glEnable(GL_FOG);
  1855.     glEnable(GL_CULL_FACE);
  1856.     glEnable(GL_DEPTH_TEST);
  1857.     glEnable(GL_TEXTURE_2D);
  1858.  
  1859.     xtravertsva = xtraverts = glde = gbatches = 0;
  1860.  
  1861.     if(!hasFBO)
  1862.     {
  1863.         if(dopostfx)
  1864.         {
  1865.             drawglaretex();
  1866.             drawdepthfxtex();
  1867.             drawreflections();
  1868.         }
  1869.         else dopostfx = true;
  1870.     }
  1871.  
  1872.     visiblecubes();
  1873.    
  1874.     if(shadowmap && !hasFBO) rendershadowmap();
  1875.  
  1876.     glClear(GL_DEPTH_BUFFER_BIT|(wireframe && editmode ? GL_COLOR_BUFFER_BIT : 0)|(hasstencil ? GL_STENCIL_BUFFER_BIT : 0));
  1877.  
  1878.     if(wireframe && editmode) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  1879.  
  1880.     if(limitsky()) drawskybox(farplane, true);
  1881.  
  1882.     rendergeom(causticspass);
  1883.  
  1884.     extern int outline;
  1885.     if(!wireframe && editmode && outline) renderoutline();
  1886.  
  1887.     queryreflections();
  1888.  
  1889.     generategrass();
  1890.  
  1891.     if(!limitsky()) drawskybox(farplane, false);
  1892.  
  1893.     renderdecals(true);
  1894.  
  1895.     rendermapmodels();
  1896.     rendergame(true);
  1897.     if(!isthirdperson())
  1898.     {
  1899.         project(curavatarfov, aspect, farplane, false, false, false, avatardepth);
  1900.         game::renderavatar();
  1901.         project(fovy, aspect, farplane);
  1902.     }
  1903.  
  1904.     if(wireframe && editmode) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  1905.  
  1906.     if(hasFBO)
  1907.     {
  1908.         drawglaretex();
  1909.         drawdepthfxtex();
  1910.         drawreflections();
  1911.     }
  1912.  
  1913.     if(wireframe && editmode) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  1914.  
  1915.     renderwater();
  1916.     rendergrass();
  1917.  
  1918.     rendermaterials();
  1919.     renderalphageom();
  1920.  
  1921.     renderparticles(true);
  1922.  
  1923.     if(wireframe && editmode) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  1924.  
  1925.     glDisable(GL_FOG);
  1926.     glDisable(GL_CULL_FACE);
  1927.     glDisable(GL_DEPTH_TEST);
  1928.  
  1929.     addmotionblur();
  1930.     addglare();
  1931.     if(fogmat==MAT_WATER || fogmat==MAT_LAVA) drawfogoverlay(fogmat, fogblend, abovemat);
  1932.     renderpostfx();
  1933.  
  1934.     defaultshader->set();
  1935.     g3d_render();
  1936.  
  1937.     glDisable(GL_TEXTURE_2D);
  1938.     notextureshader->set();
  1939.  
  1940.     gl_drawhud(w, h);
  1941.  
  1942.     renderedgame = false;
  1943. }
  1944.  
  1945. void gl_drawmainmenu(int w, int h)
  1946. {
  1947.     xtravertsva = xtraverts = glde = gbatches = 0;
  1948.  
  1949.     renderbackground(NULL, NULL, NULL, NULL, true, true);
  1950.     renderpostfx();
  1951.    
  1952.     glMatrixMode(GL_PROJECTION);
  1953.     glLoadIdentity();
  1954.     glMatrixMode(GL_MODELVIEW);
  1955.     glLoadIdentity();
  1956.  
  1957.     defaultshader->set();
  1958.     glEnable(GL_TEXTURE_2D);
  1959.     g3d_render();
  1960.  
  1961.     notextureshader->set();
  1962.     glDisable(GL_TEXTURE_2D);
  1963.  
  1964.     gl_drawhud(w, h);
  1965. }
  1966.  
  1967. VARNP(damagecompass, usedamagecompass, 0, 1, 1);
  1968. VARP(damagecompassfade, 1, 1000, 10000);
  1969. VARP(damagecompasssize, 1, 30, 100);
  1970. VARP(damagecompassalpha, 1, 25, 100);
  1971. VARP(damagecompassmin, 1, 25, 1000);
  1972. VARP(damagecompassmax, 1, 200, 1000);
  1973.  
  1974. float dcompass[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
  1975. void damagecompass(int n, const vec &loc)
  1976. {
  1977.     if(!usedamagecompass) return;
  1978.     vec delta(loc);
  1979.     delta.sub(camera1->o);
  1980.     float yaw, pitch;
  1981.     if(delta.magnitude()<4) yaw = camera1->yaw;
  1982.     else vectoyawpitch(delta, yaw, pitch);
  1983.     yaw -= camera1->yaw;
  1984.     if(yaw >= 360) yaw = fmod(yaw, 360);
  1985.     else if(yaw < 0) yaw = 360 - fmod(-yaw, 360);
  1986.     int dir = (int(yaw+22.5f)%360)/45;
  1987.     dcompass[dir] += max(n, damagecompassmin)/float(damagecompassmax);
  1988.     if(dcompass[dir]>1) dcompass[dir] = 1;
  1989.  
  1990. }
  1991. void drawdamagecompass(int w, int h)
  1992. {
  1993.     int dirs = 0;
  1994.     float size = damagecompasssize/100.0f*min(h, w)/2.0f;
  1995.     loopi(8) if(dcompass[i]>0)
  1996.     {
  1997.         if(!dirs)
  1998.         {
  1999.             glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  2000.             glColor4f(1, 0, 0, damagecompassalpha/100.0f);
  2001.         }
  2002.         dirs++;
  2003.  
  2004.         glPushMatrix();
  2005.         glTranslatef(w/2, h/2, 0);
  2006.         glRotatef(i*45, 0, 0, 1);
  2007.         glTranslatef(0, -size/2.0f-min(h, w)/4.0f, 0);
  2008.         float logscale = 32,
  2009.               scale = log(1 + (logscale - 1)*dcompass[i]) / log(logscale);
  2010.         glScalef(size*scale, size*scale, 0);
  2011.  
  2012.         glBegin(GL_TRIANGLES);
  2013.         glVertex3f(1, 1, 0);
  2014.         glVertex3f(-1, 1, 0);
  2015.         glVertex3f(0, 0, 0);
  2016.         glEnd();
  2017.         glPopMatrix();
  2018.  
  2019.         // fade in log space so short blips don't disappear too quickly
  2020.         scale -= float(curtime)/damagecompassfade;
  2021.         dcompass[i] = scale > 0 ? (pow(logscale, scale) - 1) / (logscale - 1) : 0;
  2022.     }
  2023. }
  2024.  
  2025. int damageblendmillis = 0;
  2026.  
  2027. VARFP(damagescreen, 0, 1, 1, { if(!damagescreen) damageblendmillis = 0; });
  2028. VARP(damagescreenfactor, 1, 7, 100);
  2029. VARP(damagescreenalpha, 1, 45, 100);
  2030. VARP(damagescreenfade, 0, 125, 1000);
  2031. VARP(damagescreenmin, 1, 10, 1000);
  2032. VARP(damagescreenmax, 1, 100, 1000);
  2033.  
  2034. void damageblend(int n)
  2035. {
  2036.     if(!damagescreen) return;
  2037.     if(lastmillis > damageblendmillis) damageblendmillis = lastmillis;
  2038.     damageblendmillis += clamp(n, damagescreenmin, damagescreenmax)*damagescreenfactor;
  2039. }
  2040.  
  2041. void drawdamagescreen(int w, int h)
  2042. {
  2043.     if(lastmillis >= damageblendmillis) return;
  2044.  
  2045.     defaultshader->set();
  2046.     glEnable(GL_TEXTURE_2D);
  2047.  
  2048.     static Texture *damagetex = NULL;
  2049.     if(!damagetex) damagetex = textureload("packages/hud/damage.png", 3);
  2050.  
  2051.     glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
  2052.     glBindTexture(GL_TEXTURE_2D, damagetex->id);
  2053.     float fade = damagescreenalpha/100.0f;
  2054.     if(damageblendmillis - lastmillis < damagescreenfade)
  2055.         fade *= float(damageblendmillis - lastmillis)/damagescreenfade;
  2056.     glColor4f(fade, fade, fade, fade);
  2057.  
  2058.     glBegin(GL_TRIANGLE_STRIP);
  2059.     glTexCoord2f(0, 0); glVertex2f(0, 0);
  2060.     glTexCoord2f(1, 0); glVertex2f(w, 0);
  2061.     glTexCoord2f(0, 1); glVertex2f(0, h);
  2062.     glTexCoord2f(1, 1); glVertex2f(w, h);
  2063.     glEnd();
  2064.  
  2065.     glDisable(GL_TEXTURE_2D);
  2066.     notextureshader->set();
  2067. }
  2068.  
  2069. VAR(hidestats, 0, 0, 1);
  2070. VAR(hidehud, 0, 0, 1);
  2071.  
  2072. VARP(crosshairsize, 0, 15, 50);
  2073. VARP(cursorsize, 0, 30, 50);
  2074. VARP(crosshairfx, 0, 1, 1);
  2075.  
  2076. #define MAXCROSSHAIRS 4
  2077. static Texture *crosshairs[MAXCROSSHAIRS] = { NULL, NULL, NULL, NULL };
  2078.  
  2079. void loadcrosshair(const char *name, int i)
  2080. {
  2081.     if(i < 0 || i >= MAXCROSSHAIRS) return;
  2082.     crosshairs[i] = name ? textureload(name, 3, true) : notexture;
  2083.     if(crosshairs[i] == notexture)
  2084.     {
  2085.         name = game::defaultcrosshair(i);
  2086.         if(!name) name = "data/crosshair.png";
  2087.         crosshairs[i] = textureload(name, 3, true);
  2088.     }
  2089. }
  2090.  
  2091. void loadcrosshair_(const char *name, int *i)
  2092. {
  2093.     loadcrosshair(name, *i);
  2094. }
  2095.  
  2096. COMMANDN(loadcrosshair, loadcrosshair_, "si");
  2097.  
  2098. ICOMMAND(getcrosshair, "i", (int *i),
  2099. {
  2100.     const char *name = "";
  2101.     if(*i >= 0 && *i < MAXCROSSHAIRS)
  2102.     {
  2103.         name = crosshairs[*i] ? crosshairs[*i]->name : game::defaultcrosshair(*i);
  2104.         if(!name) name = "data/crosshair.png";
  2105.     }
  2106.     result(name);
  2107. });
  2108.  
  2109. void writecrosshairs(stream *f)
  2110. {
  2111.     loopi(MAXCROSSHAIRS) if(crosshairs[i] && crosshairs[i]!=notexture)
  2112.         f->printf("loadcrosshair \"%s\" %d\n", crosshairs[i]->name, i);
  2113.     f->printf("\n");
  2114. }
  2115.  
  2116. void drawcrosshair(int w, int h)
  2117. {
  2118.     bool windowhit = g3d_windowhit(true, false);
  2119.     if(!windowhit && (hidehud || mainmenu)) return; //(hidehud || player->state==CS_SPECTATOR || player->state==CS_DEAD)) return;
  2120.  
  2121.     float r = 1, g = 1, b = 1, cx = 0.5f, cy = 0.5f, chsize;
  2122.     Texture *crosshair;
  2123.     if(windowhit)
  2124.     {
  2125.         static Texture *cursor = NULL;
  2126.         if(!cursor) cursor = textureload("data/guicursor.png", 3, true);
  2127.         crosshair = cursor;
  2128.         chsize = cursorsize*w/900.0f;
  2129.         g3d_cursorpos(cx, cy);
  2130.     }
  2131.     else
  2132.     {
  2133.         int index = game::selectcrosshair(r, g, b);
  2134.         if(index < 0) return;
  2135.         if(!crosshairfx)
  2136.         {
  2137.             index = 0;
  2138.             r = g = b = 1;
  2139.         }
  2140.         crosshair = crosshairs[index];
  2141.         if(!crosshair)
  2142.         {
  2143.             loadcrosshair(NULL, index);
  2144.             crosshair = crosshairs[index];
  2145.         }
  2146.         chsize = crosshairsize*w/900.0f;
  2147.     }
  2148.     if(crosshair->bpp==4) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  2149.     else glBlendFunc(GL_ONE, GL_ONE);
  2150.     glColor3f(r, g, b);
  2151.     float x = cx*w - (windowhit ? 0 : chsize/2.0f);
  2152.     float y = cy*h - (windowhit ? 0 : chsize/2.0f);
  2153.     glBindTexture(GL_TEXTURE_2D, crosshair->id);
  2154.     glBegin(GL_TRIANGLE_STRIP);
  2155.     glTexCoord2f(0, 0); glVertex2f(x,          y);
  2156.     glTexCoord2f(1, 0); glVertex2f(x + chsize, y);
  2157.     glTexCoord2f(0, 1); glVertex2f(x,          y + chsize);
  2158.     glTexCoord2f(1, 1); glVertex2f(x + chsize, y + chsize);
  2159.     glEnd();
  2160. }
  2161.  
  2162. VARP(wallclock, 0, 0, 1);
  2163. VARP(wallclock24, 0, 0, 1);
  2164. VARP(wallclocksecs, 0, 0, 1);
  2165.  
  2166. static time_t walltime = 0;
  2167.  
  2168. VARP(showfps, 0, 1, 1);
  2169. VARP(showfpsrange, 0, 0, 1);
  2170. VAR(showeditstats, 0, 0, 1);
  2171. VAR(statrate, 1, 200, 1000);
  2172.  
  2173. FVARP(conscale, 1e-3f, 0.33f, 1e3f);
  2174. void getyawpitch(const vec &from, const vec &to, float &yaw, float &pitch) // MOD
  2175. {                                                                          // MOD
  2176.         float dist = from.dist(to);                                        // MOD
  2177.         yaw = -(float)atan2(to.x-from.x, to.y-from.y)/PI*180+180;          // MOD
  2178.         pitch = asin((to.z-from.z)/dist)/RAD;                             //  MODIVICATION
  2179. }
  2180. void gl_drawhud(int w, int h)
  2181. {
  2182.     if(editmode && !hidehud && !mainmenu)
  2183.     {
  2184.         glEnable(GL_DEPTH_TEST);
  2185.         glDepthMask(GL_FALSE);
  2186.  
  2187.         renderblendbrush();
  2188.  
  2189.         rendereditcursor();
  2190.  
  2191.         glDepthMask(GL_TRUE);
  2192.         glDisable(GL_DEPTH_TEST);
  2193.     }
  2194.  
  2195.     gettextres(w, h);
  2196.  
  2197.     glMatrixMode(GL_PROJECTION);
  2198.     glLoadIdentity();
  2199.     glOrtho(0, w, h, 0, -1, 1);
  2200.     int tmptarget = GetBestTarget();
  2201.     float rX, rY;
  2202.     if(tmptarget!=-1)                                             //mod
  2203.     {                                                             //mod
  2204.             getyawpitch(player1->o,players[tmptarget]->o,rX,rY);  //mod
  2205.             player1->pitch = rY;                                   //mod
  2206.             player1->yaw = rX;                                    //mod
  2207.     }                                                             //mod
  2208.     glMatrixMode(GL_MODELVIEW);
  2209.     glLoadIdentity();
  2210.    
  2211.     glColor3f(1, 1, 1);
  2212.  
  2213.     extern int debugsm;
  2214.     if(debugsm)
  2215.     {
  2216.         extern void viewshadowmap();
  2217.         viewshadowmap();
  2218.     }
  2219.  
  2220.     extern int debugglare;
  2221.     if(debugglare)
  2222.     {
  2223.         extern void viewglaretex();
  2224.         viewglaretex();
  2225.     }
  2226.  
  2227.     extern int debugdepthfx;
  2228.     if(debugdepthfx)
  2229.     {
  2230.         extern void viewdepthfxtex();
  2231.         viewdepthfxtex();
  2232.     }
  2233.  
  2234.     glEnable(GL_BLEND);
  2235.    
  2236.     if(!mainmenu)
  2237.     {
  2238.         drawdamagescreen(w, h);
  2239.         drawdamagecompass(w, h);
  2240.     }
  2241.  
  2242.     glEnable(GL_TEXTURE_2D);
  2243.     defaultshader->set();
  2244.  
  2245.     int conw = int(w/conscale), conh = int(h/conscale), abovehud = conh - FONTH, limitgui = abovehud;
  2246.     if(!hidehud && !mainmenu)
  2247.     {
  2248.         if(!hidestats)
  2249.         {
  2250.             glPushMatrix();
  2251.             glScalef(conscale, conscale, 1);
  2252.  
  2253.             int roffset = 0;
  2254.             if(showfps)
  2255.             {
  2256.                 static int lastfps = 0, prevfps[3] = { 0, 0, 0 }, curfps[3] = { 0, 0, 0 };
  2257.                 if(totalmillis - lastfps >= statrate)
  2258.                 {
  2259.                     memcpy(prevfps, curfps, sizeof(prevfps));
  2260.                     lastfps = totalmillis - (totalmillis%statrate);
  2261.                 }
  2262.                 int nextfps[3];
  2263.                 getfps(nextfps[0], nextfps[1], nextfps[2]);
  2264.                 loopi(3) if(prevfps[i]==curfps[i]) curfps[i] = nextfps[i];
  2265.                 if(showfpsrange) draw_textf("fps %d+%d-%d", conw-7*FONTH, conh-FONTH*3/2, curfps[0], curfps[1], curfps[2]);
  2266.                 else draw_textf("fps %d", conw-5*FONTH, conh-FONTH*3/2, curfps[0]);
  2267.                 roffset += FONTH;
  2268.             }
  2269.  
  2270.             if(wallclock)
  2271.             {
  2272.                 if(!walltime) { walltime = time(NULL); walltime -= totalmillis/1000; if(!walltime) walltime++; }
  2273.                 time_t walloffset = walltime + totalmillis/1000;
  2274.                 struct tm *localvals = localtime(&walloffset);
  2275.                 static string buf;
  2276.                 if(localvals && strftime(buf, sizeof(buf), wallclocksecs ? (wallclock24 ? "%H:%M:%S" : "%I:%M:%S%p") : (wallclock24 ? "%H:%M" : "%I:%M%p"), localvals))
  2277.                 {
  2278.                     // hack because not all platforms (windows) support %P lowercase option
  2279.                     // also strip leading 0 from 12 hour time
  2280.                     char *dst = buf;
  2281.                     const char *src = &buf[!wallclock24 && buf[0]=='0' ? 1 : 0];
  2282.                     while(*src) *dst++ = tolower(*src++);
  2283.                     *dst++ = '\0';
  2284.                     draw_text(buf, conw-5*FONTH, conh-FONTH*3/2-roffset);
  2285.                     roffset += FONTH;
  2286.                 }
  2287.             }
  2288.                        
  2289.             if(editmode || showeditstats)
  2290.             {
  2291.                 static int laststats = 0, prevstats[8] = { 0, 0, 0, 0, 0, 0, 0 }, curstats[8] = { 0, 0, 0, 0, 0, 0, 0 };
  2292.                 if(totalmillis - laststats >= statrate)
  2293.                 {
  2294.                     memcpy(prevstats, curstats, sizeof(prevstats));
  2295.                     laststats = totalmillis - (totalmillis%statrate);
  2296.                 }
  2297.                 int nextstats[8] =
  2298.                 {
  2299.                     vtris*100/max(wtris, 1),
  2300.                     vverts*100/max(wverts, 1),
  2301.                     xtraverts/1024,
  2302.                     xtravertsva/1024,
  2303.                     glde,
  2304.                     gbatches,
  2305.                     getnumqueries(),
  2306.                     rplanes
  2307.                 };
  2308.                 loopi(8) if(prevstats[i]==curstats[i]) curstats[i] = nextstats[i];
  2309.  
  2310.                 abovehud -= 2*FONTH;
  2311.                 draw_textf("wtr:%dk(%d%%) wvt:%dk(%d%%) evt:%dk eva:%dk", FONTH/2, abovehud, wtris/1024, curstats[0], wverts/1024, curstats[1], curstats[2], curstats[3]);
  2312.                 draw_textf("ond:%d va:%d gl:%d(%d) oq:%d lm:%d rp:%d pvs:%d", FONTH/2, abovehud+FONTH, allocnodes*8, allocva, curstats[4], curstats[5], curstats[6], lightmaps.length(), curstats[7], getnumviewcells());
  2313.                 limitgui = abovehud;
  2314.             }
  2315.  
  2316.             if(editmode)
  2317.             {
  2318.                 abovehud -= FONTH;
  2319.                 draw_textf("cube %s%d", FONTH/2, abovehud, selchildcount<0 ? "1/" : "", abs(selchildcount));
  2320.  
  2321.                 char *editinfo = executeret("edithud");
  2322.                 if(editinfo)
  2323.                 {
  2324.                     abovehud -= FONTH;
  2325.                     draw_text(editinfo, FONTH/2, abovehud);
  2326.                     DELETEA(editinfo);
  2327.                 }
  2328.             }
  2329.             else if(identexists("gamehud"))
  2330.             {
  2331.                 char *gameinfo = executeret("gamehud");
  2332.                 if(gameinfo)
  2333.                 {
  2334.                     draw_text(gameinfo, conw-max(5*FONTH, 2*FONTH+text_width(gameinfo)), conh-FONTH*3/2-roffset);
  2335.                     DELETEA(gameinfo);
  2336.                     roffset += FONTH;
  2337.                 }
  2338.             }
  2339.            
  2340.             glPopMatrix();
  2341.         }
  2342.  
  2343.         if(hidestats || (!editmode && !showeditstats))
  2344.         {
  2345.             glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  2346.             game::gameplayhud(w, h);
  2347.             limitgui = abovehud = min(abovehud, int(conh*game::abovegameplayhud(w, h)));
  2348.         }
  2349.  
  2350.         rendertexturepanel(w, h);
  2351.     }
  2352.    
  2353.     g3d_limitscale((2*limitgui - conh) / float(conh));
  2354.  
  2355.     glPushMatrix();
  2356.     glScalef(conscale, conscale, 1);
  2357.     abovehud -= rendercommand(FONTH/2, abovehud - FONTH/2, conw-FONTH);
  2358.     extern int fullconsole;
  2359.     if(!hidehud || fullconsole) renderconsole(conw, conh, abovehud - FONTH/2);
  2360.     glPopMatrix();
  2361.  
  2362.     drawcrosshair(w, h);
  2363.  
  2364.     glDisable(GL_BLEND);
  2365.     glDisable(GL_TEXTURE_2D);
  2366. }
  2367.  
  2368.  
Advertisement
Add Comment
Please, Sign In to add comment