hackeverything

engine/rendergl.cpp

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