/* * Copyright(c) 1997-2001 Id Software, Inc. * Copyright(c) 2002 The Quakeforge Project. * Copyright(c) 2006 Quetoo. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or(at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "client.h" viddef_t viddef; int QGL_TEXTURE0, QGL_TEXTURE1; model_t *r_worldmodel; float gldepthmin, gldepthmax; glconfig_t gl_config; glstate_t gl_state; image_t *r_notexture; // use for bad textures image_t *r_particletexture; // little dot for particles entity_t *currententity; model_t *currentmodel; cplane_t frustum[4]; int r_visframecount; // bumped when going to a new PVS int c_brush_polys, c_alias_polys; byte color_white[4] = {255, 255, 255, 255}; byte color_black[4] = {0, 0, 0, 128}; // view origin vec3_t vup; vec3_t vpn; vec3_t vright; vec3_t r_origin; float r_world_matrix[16]; float r_base_world_matrix[16]; // screen size info viewdef_t r_viewdef; int r_viewcluster, r_viewcluster2, r_oldviewcluster, r_oldviewcluster2; cvar_t *r_drawentities; cvar_t *r_speeds; cvar_t *r_fullbright; cvar_t *r_novis; cvar_t *r_nocull; cvar_t *r_lerpmodels; cvar_t *gl_vertex_arrays; cvar_t *gl_ext_multitexture; cvar_t *gl_ext_compiled_vertex_array; cvar_t *gl_log; cvar_t *gl_drawbuffer; cvar_t *gl_driver; cvar_t *gl_lightmap; cvar_t *gl_monolightmap; cvar_t *gl_loadtga; cvar_t *gl_modulate; cvar_t *gl_intensity; cvar_t *gl_rounddown; cvar_t *gl_picmip; cvar_t *gl_skymip; cvar_t *gl_playermip; cvar_t *gl_wireframe; cvar_t *gl_ztrick; cvar_t *gl_finish; cvar_t *gl_clear; cvar_t *gl_cull; cvar_t *gl_texturemode; cvar_t *gl_texturealphamode; cvar_t *gl_texturesolidmode; cvar_t *gl_lockpvs; cvar_t *vid_width; cvar_t *vid_height; cvar_t *vid_fullscreen; cvar_t *vid_gamma; cvar_t *skydistance; /* GL_CullBox Returns true if the box is completely outside the frustum */ qboolean GL_CullBox(vec3_t mins, vec3_t maxs){ int i; if(r_nocull->value) return false; for(i = 0; i < 4; i++) if(BOX_ON_PLANE_SIDE(mins, maxs, &frustum[i]) == 2) return true; return false; } void GL_RotateForEntity(entity_t *e){ qglTranslatef(e->origin[0], e->origin[1], e->origin[2]); qglRotatef(e->angles[1], 0, 0, 1); qglRotatef(-e->angles[0], 0, 1, 0); qglRotatef(-e->angles[2], 1, 0, 0); } /* SPRITE MODELS */ /* GL_DrawSpriteModel */ void GL_DrawSpriteModel(entity_t *e){ float alpha = 1.0F; vec3_t point; dsprframe_t *frame; float *up, *right; dsprite_t *psprite; // don't even bother culling, because it's just a single // polygon without a surface cache psprite = (dsprite_t *)currentmodel->extradata; e->frame %= psprite->numframes; frame = &psprite->frames[e->frame]; up = vup; right = vright; if(e->flags & RF_TRANSLUCENT) alpha = e->alpha; if(alpha != 1.0F){ qglEnable(GL_BLEND); color_white[3] = alpha * 255; } qglColor4ubv(color_white); GL_Bind(currentmodel->skins[e->frame]->texnum); GL_TexEnv(GL_MODULATE); if(alpha == 1.0) qglEnable(GL_ALPHA_TEST); else qglDisable(GL_ALPHA_TEST); qglBegin(GL_QUADS); qglTexCoord2f(0, 1); VectorMA(e->origin, -frame->origin_y, up, point); VectorMA(point, -frame->origin_x, right, point); qglVertex3fv(point); qglTexCoord2f(0, 0); VectorMA(e->origin, frame->height - frame->origin_y, up, point); VectorMA(point, -frame->origin_x, right, point); qglVertex3fv(point); qglTexCoord2f(1, 0); VectorMA(e->origin, frame->height - frame->origin_y, up, point); VectorMA(point, frame->width - frame->origin_x, right, point); qglVertex3fv(point); qglTexCoord2f(1, 1); VectorMA(e->origin, -frame->origin_y, up, point); VectorMA(point, frame->width - frame->origin_x, right, point); qglVertex3fv(point); qglEnd(); qglDisable(GL_ALPHA_TEST); GL_TexEnv(GL_REPLACE); if(alpha != 1.0F){ qglDisable(GL_BLEND); color_white[3] = 255; } qglColor4ubv(color_white); } /* GL_DrawNullModel */ void GL_DrawNullModel(void){ vec3_t shadelight; int i; if(currententity->flags & RF_FULLBRIGHT) shadelight[0] = shadelight[1] = shadelight[2] = 1.0F; else GL_LightPoint(currententity->origin, shadelight); qglPushMatrix(); GL_RotateForEntity(currententity); qglDisable(GL_TEXTURE_2D); qglColor3fv(shadelight); qglBegin(GL_TRIANGLE_FAN); qglVertex3f(0, 0, -16); for(i = 0; i <= 4; i++) qglVertex3f(16*cos(i*M_PI / 2), 16*sin(i*M_PI / 2), 0); qglEnd(); qglBegin(GL_TRIANGLE_FAN); qglVertex3f(0, 0, 16); for(i = 4; i >= 0; i--) qglVertex3f(16*cos(i*M_PI / 2), 16*sin(i*M_PI / 2), 0); qglEnd(); qglColor3ubv(color_white); qglPopMatrix(); qglEnable(GL_TEXTURE_2D); } /* GL_DrawBeam */ void GL_DrawBeam(entity_t *e){ #define NUM_BEAM_SEGS 6 int i; float r, g, b; vec3_t perpvec; vec3_t direction, normalized_direction; vec3_t start_points[NUM_BEAM_SEGS], end_points[NUM_BEAM_SEGS]; vec3_t oldorigin, origin; oldorigin[0] = e->oldorigin[0]; oldorigin[1] = e->oldorigin[1]; oldorigin[2] = e->oldorigin[2]; origin[0] = e->origin[0]; origin[1] = e->origin[1]; origin[2] = e->origin[2]; normalized_direction[0] = direction[0] = oldorigin[0] - origin[0]; normalized_direction[1] = direction[1] = oldorigin[1] - origin[1]; normalized_direction[2] = direction[2] = oldorigin[2] - origin[2]; if(VectorNormalize(normalized_direction) == 0) return; PerpendicularVector(perpvec, normalized_direction); VectorScale(perpvec, e->frame / 2, perpvec); for(i = 0; i < 6; i++){ RotatePointAroundVector(start_points[i], normalized_direction, perpvec,(360.0 / NUM_BEAM_SEGS)*i); VectorAdd(start_points[i], origin, start_points[i]); VectorAdd(start_points[i], direction, end_points[i]); } qglDisable(GL_TEXTURE_2D); qglEnable(GL_BLEND); qglDepthMask(GL_FALSE); r = (d_8to24table[e->skinnum & 0xFF]) & 0xFF; g = (d_8to24table[e->skinnum & 0xFF] >> 8) & 0xFF; b = (d_8to24table[e->skinnum & 0xFF] >> 16) & 0xFF; r *= 1 / 255.0F; g *= 1 / 255.0F; b *= 1 / 255.0F; qglColor4f(r, g, b, e->alpha); qglBegin(GL_TRIANGLE_STRIP); for(i = 0; i < NUM_BEAM_SEGS; i++){ qglVertex3fv(start_points[i]); qglVertex3fv(end_points[i]); qglVertex3fv(start_points[(i + 1) % NUM_BEAM_SEGS]); qglVertex3fv(end_points[(i + 1) % NUM_BEAM_SEGS]); } qglEnd(); qglEnable(GL_TEXTURE_2D); qglDisable(GL_BLEND); qglDepthMask(GL_TRUE); } /* GL_DrawEntitiesOnList */ void GL_DrawEntitiesOnList(void){ int i; if(!r_drawentities->value) return; // draw non-transparent first for(i = 0; i < r_viewdef.num_entities; i++){ currententity = &r_viewdef.entities[i]; if(currententity->flags & RF_TRANSLUCENT) continue; // solid if(currententity->flags & RF_BEAM){ GL_DrawBeam(currententity); } else { currentmodel = currententity->model; if(!currentmodel){ GL_DrawNullModel(); continue; } switch(currentmodel->type){ case mod_alias: GL_DrawAliasModel(currententity); break; case mod_brush: GL_DrawBrushModel(currententity); break; case mod_sprite: GL_DrawSpriteModel(currententity); break; default: Com_Error(ERR_DROP, "Bad modeltype"); break; } } } // draw transparent entities // we could sort these if it ever becomes a problem... qglDepthMask(0); // no z writes for(i = 0; i < r_viewdef.num_entities; i++){ currententity = &r_viewdef.entities[i]; if(!(currententity->flags & RF_TRANSLUCENT)) continue; // solid if(currententity->flags & RF_BEAM){ GL_DrawBeam(currententity); } else { currentmodel = currententity->model; if(!currentmodel){ GL_DrawNullModel(); continue; } switch(currentmodel->type){ case mod_alias: GL_DrawAliasModel(currententity); break; case mod_brush: GL_DrawBrushModel(currententity); break; case mod_sprite: GL_DrawSpriteModel(currententity); break; default: Com_Error(ERR_DROP, "Bad modeltype"); break; } } } qglDepthMask(1); // back to writing } /* GL_DrawParticles */ void GL_DrawParticles(void){ const particle_t *p; int i; vec3_t up, right, up_right_scale, down_right_scale, VA[4]; float scale; byte color[4]; GL_Bind(r_particletexture->texnum); qglDepthMask(GL_FALSE); // no z buffering qglEnable(GL_BLEND); GL_TexEnv(GL_MODULATE); qglBegin(GL_QUADS); for(p = r_viewdef.particles, i = 0; i < r_viewdef.num_particles; i++, p++){ // hack a scale up to keep particles from disapearing scale = (p->origin[0] - r_origin[0]) * vpn[0] + (p->origin[1] - r_origin[1]) * vpn[1] + (p->origin[2] - r_origin[2]) * vpn[2]; scale *= 0.002; VectorScale(vup, scale, up); VectorScale(vright, scale, right); VectorAdd(up, right, up_right_scale); VectorSubtract(right, up, down_right_scale); VectorSubtract(p->origin, down_right_scale, VA[0]); VectorAdd(p->origin, up_right_scale, VA[1]); VectorAdd(p->origin, down_right_scale, VA[2]); VectorSubtract(p->origin, up_right_scale, VA[3]); *(int *)color = d_8to24table[p->color]; color[3] = p->alpha * 255; qglColor4ubv(color); qglTexCoord2f(0.0, 0.0); qglVertex3fv(VA[0]); qglTexCoord2f(1.0, 0.0); qglVertex3fv(VA[1]); qglTexCoord2f(1.0, 1.0); qglVertex3fv(VA[2]); qglTexCoord2f(0.0, 1.0); qglVertex3fv(VA[3]); } qglEnd(); qglDisable(GL_BLEND); qglColor4ubv(color_white); qglDepthMask(GL_TRUE); // back to normal Z buffering GL_TexEnv(GL_REPLACE); } int SignbitsForPlane(cplane_t *out){ int bits, j; // for fast box on planeside test bits = 0; for(j = 0; j < 3; j++){ if(out->normal[j] < 0) bits |= 1 << j; } return bits; } void GL_SetFrustum(void){ int i; // rotate VPN right by FOV_X/2 degrees RotatePointAroundVector(frustum[0].normal, vup, vpn, -(90 - r_viewdef.fov_x / 2)); // rotate VPN left by FOV_X/2 degrees RotatePointAroundVector(frustum[1].normal, vup, vpn, 90 - r_viewdef.fov_x / 2); // rotate VPN up by FOV_X/2 degrees RotatePointAroundVector(frustum[2].normal, vright, vpn, 90 - r_viewdef.fov_y / 2); // rotate VPN down by FOV_X/2 degrees RotatePointAroundVector(frustum[3].normal, vright, vpn, -(90 - r_viewdef.fov_y / 2)); for(i = 0; i < 4; i++){ frustum[i].type = PLANE_ANYZ; frustum[i].dist = DotProduct(r_origin, frustum[i].normal); frustum[i].signbits = SignbitsForPlane(&frustum[i]); } } /* GL_SetupFrame */ void GL_SetupFrame(void){ mleaf_t *leaf; // build the transformation matrix for the given view angles VectorCopy(r_viewdef.vieworg, r_origin); AngleVectors(r_viewdef.viewangles, vpn, vright, vup); // current viewcluster if(!(r_viewdef.rdflags & RDF_NOWORLDMODEL)){ r_oldviewcluster = r_viewcluster; r_oldviewcluster2 = r_viewcluster2; leaf = Mod_PointInLeaf(r_origin, r_worldmodel); r_viewcluster = r_viewcluster2 = leaf->cluster; // check above and below so crossing solid water doesn't draw wrong if(!leaf->contents){ // look down a bit vec3_t temp; VectorCopy(r_origin, temp); temp[2] -= 16; leaf = Mod_PointInLeaf(temp, r_worldmodel); if(!(leaf->contents & CONTENTS_SOLID) && (leaf->cluster != r_viewcluster2)) r_viewcluster2 = leaf->cluster; } else { // look up a bit vec3_t temp; VectorCopy(r_origin, temp); temp[2] += 16; leaf = Mod_PointInLeaf(temp, r_worldmodel); if(!(leaf->contents & CONTENTS_SOLID) && (leaf->cluster != r_viewcluster2)) r_viewcluster2 = leaf->cluster; } } c_brush_polys = 0; c_alias_polys = 0; } void MYgluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar){ GLdouble xmin, xmax, ymin, ymax; ymax = zNear * tan(fovy * M_PI / 360.0); ymin = -ymax; xmin = ymin * aspect; xmax = ymax * aspect; qglFrustum(xmin, xmax, ymin, ymax, zNear, zFar); } /* GL_SetupGL */ void GL_SetupGL(void){ float screenaspect; int x, x2, y2, y, w, h; /* skybox vars */ static GLdouble farz; GLdouble boxsize; // set up viewport x = floor(r_viewdef.x * viddef.width / viddef.width); x2 = ceil((r_viewdef.x + r_viewdef.width) * viddef.width / viddef.width); y = floor(viddef.height - r_viewdef.y * viddef.height / viddef.height); y2 = ceil(viddef.height -(r_viewdef.y + r_viewdef.height) * viddef.height / viddef.height); w = x2 - x; h = y - y2; qglViewport(x, y2, w, h); // block of code for SkyBox Size change if(skydistance->modified){ skydistance->modified = false; boxsize = skydistance->value; boxsize -= 252 * ceil(boxsize / 2300); farz = 1.0; while(farz < boxsize){ // make this value a power-of-2 farz *= 2.0; if(farz >= 65536.0) // don't make it larger than this break; } // double since boxsize is distance from camera to // edge of skybox - not total size of skybox farz *= 2.0; Com_DPrintf("farz now set to %g\n", farz); } // set up projection matrix screenaspect = (float)r_viewdef.width / r_viewdef.height; qglMatrixMode(GL_PROJECTION); qglLoadIdentity(); MYgluPerspective(r_viewdef.fov_y, screenaspect, 4, farz); qglCullFace(GL_FRONT); qglMatrixMode(GL_MODELVIEW); qglLoadIdentity(); qglRotatef(-90, 1, 0, 0); // put Z going up qglRotatef(90, 0, 0, 1); // put Z going up qglRotatef(-r_viewdef.viewangles[2], 1, 0, 0); qglRotatef(-r_viewdef.viewangles[0], 0, 1, 0); qglRotatef(-r_viewdef.viewangles[1], 0, 0, 1); qglTranslatef(-r_viewdef.vieworg[0], -r_viewdef.vieworg[1], -r_viewdef.vieworg[2]); qglGetFloatv(GL_MODELVIEW_MATRIX, r_world_matrix); // set drawing parms if(gl_cull->value) qglEnable(GL_CULL_FACE); else qglDisable(GL_CULL_FACE); qglDisable(GL_BLEND); qglDisable(GL_ALPHA_TEST); qglEnable(GL_DEPTH_TEST); } /* GL_Clear */ void GL_Clear(void){ if(gl_ztrick->value && cls.state == ca_active){ static int trickframe; if(gl_clear->value) qglClear(GL_COLOR_BUFFER_BIT); trickframe++; if(trickframe & 1){ gldepthmin = 0; gldepthmax = 0.49999; qglDepthFunc(GL_LEQUAL); } else { gldepthmin = 1; gldepthmax = 0.5; qglDepthFunc(GL_GEQUAL); } } else { if(gl_clear->value) qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); else qglClear(GL_DEPTH_BUFFER_BIT); gldepthmin = 0; gldepthmax = 1; qglDepthFunc(GL_LEQUAL); } qglDepthRange(gldepthmin, gldepthmax); } /* GL_RenderFrame r_viewdef must be set before the first call */ void GL_RenderFrame(viewdef_t *fd){ if(cls.state != ca_active) return; if(!cl.view_prepped) return; // still loading r_viewdef = *fd; if(!r_worldmodel && !(r_viewdef.rdflags & RDF_NOWORLDMODEL)) Com_Error(ERR_DROP, "GL_RenderView: NULL worldmodel"); if(r_speeds->value){ c_brush_polys = 0; c_alias_polys = 0; } if(gl_finish->value) qglFinish(); GL_SetupFrame(); GL_SetFrustum(); GL_SetupGL(); GL_MarkLeafs(); // done here so we know if we're in water if(gl_wireframe->value){ qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE); qglClear(GL_COLOR_BUFFER_BIT); } GL_DrawWorld(); if(gl_wireframe->value) qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL); GL_DrawEntitiesOnList(); GL_DrawParticles(); GL_DrawAlphaSurfaces(); if(r_speeds->value){ Com_Printf( "%4i wpoly %4i epoly %i tex %i lmaps\n", c_brush_polys, c_alias_polys, c_visible_textures, c_visible_lightmaps); } } /* GL_SetGL2D */ void GL_SetGL2D(void){ qglViewport(0, 0, viddef.width, viddef.height); qglMatrixMode(GL_PROJECTION); qglLoadIdentity(); qglOrtho(0, viddef.width, viddef.height, 0, -99999, 99999); qglMatrixMode(GL_MODELVIEW); qglLoadIdentity(); qglDisable(GL_DEPTH_TEST); qglDisable(GL_CULL_FACE); qglDisable(GL_BLEND); qglEnable(GL_ALPHA_TEST); qglEnable(GL_TEXTURE_2D); qglColor4f(1, 1, 1, 1); } /* GL_SetMode */ qboolean GL_SetMode(void){ if(GL_InitGraphics(vid_width->value, vid_height->value, vid_fullscreen->value)){ viddef.width = (int)vid_width->value; viddef.height = (int)vid_height->value; gl_state.prev_width = vid_width->value; gl_state.prev_height = vid_height->value; return true; } Cvar_SetValue("vid_width", gl_state.prev_width); //failed, revert Cvar_SetValue("vid_height", gl_state.prev_height); GL_InitGraphics(gl_state.prev_width, gl_state.prev_height, false); return false; } char *strlwr(char *s){ char *p = s; while(*s){ *s = tolower(*s); s++; } return p; } /* GL_Init */ void GL_Init(void){ char renderer_buffer[MAX_STRING_CHARS]; char vendor_buffer[MAX_STRING_CHARS]; int j, err; extern float r_turbsin[256]; for(j = 0; j < 256; j++){ r_turbsin[j] *= 0.5; } Com_Printf("Video initialization..\n"); GL_Register(); // initialize our QGL dynamic bindings if(!QGL_Init(gl_driver->string)){ Com_Printf("Failed to load GL driver %s.\n", gl_driver->string); QGL_Shutdown(); return; } gl_state.prev_width = 640; gl_state.prev_height = 480; // create the window and set up the context if(!GL_SetMode()){ Com_Printf("Failed to set video mode.\n"); QGL_Shutdown(); return; } gl_config.renderer_string = (char *)qglGetString(GL_RENDERER); gl_config.vendor_string = (char *)qglGetString(GL_VENDOR); gl_config.version_string = (char *)qglGetString(GL_VERSION); gl_config.extensions_string = (char *)qglGetString(GL_EXTENSIONS); strncpy(renderer_buffer, gl_config.renderer_string, sizeof(renderer_buffer)); strncpy(vendor_buffer, gl_config.vendor_string, sizeof(vendor_buffer)); strlwr(renderer_buffer); strlwr(vendor_buffer); // enable available extensions if(strstr(gl_config.extensions_string, "GL_EXT_compiled_vertex_array") || strstr(gl_config.extensions_string, "GL_SGI_compiled_vertex_array")){ qglLockArraysEXT = (void(APIENTRY*)(int, int)) qwglGetProcAddress("glLockArraysEXT"); qglUnlockArraysEXT = (void(APIENTRY*)(void)) qwglGetProcAddress("glUnlockArraysEXT"); Com_Printf(" GL_EXT_compiled_vertex_array\n"); } if(strstr(gl_config.extensions_string, "GL_ARB_multitexture") && gl_ext_multitexture->value){ qglMultiTexCoord2fARB = (void(APIENTRY*)(GLenum, GLfloat, GLfloat)) qwglGetProcAddress("glMultiTexCoord2fARB"); qglActiveTextureARB = (void(APIENTRY*)(GLenum)) qwglGetProcAddress("glActiveTextureARB"); qglClientActiveTextureARB = (void(APIENTRY*)(GLenum)) qwglGetProcAddress("glClientActiveTextureARB"); QGL_TEXTURE0 = GL_TEXTURE0_ARB; QGL_TEXTURE1 = GL_TEXTURE1_ARB; Com_Printf(" GL_ARB_multitexture\n"); } GL_SetDefaultState(); GL_InitImages(); Mod_Init(); GL_InitParticleTexture(); GL_InitNoTexture(); Draw_InitLocal(); err = qglGetError(); if(err != GL_NO_ERROR) Com_Printf( "glGetError() = 0x%x\n", err); Com_Printf("Video initialized %dx%d %s.\n", viddef.width, viddef.height, (vid_fullscreen->value ? "fullscreen" : "windowed")); } /* GL_Shutdown */ void GL_Shutdown(void){ Cmd_RemoveCommand("screenshot"); Cmd_RemoveCommand("imagelist"); Mod_FreeAll(); GL_ShutdownImages(); // shut down OS specific OpenGL stuff like contexts, etc. GL_ShutdownGraphics(); // shutdown our QGL subsystem QGL_Shutdown(); } /* GL_BeginFrame */ void GL_BeginFrame(void){ if(gl_log->modified){ GL_EnableLogging(gl_log->value); gl_log->modified = false; } if(gl_log->value){ GL_LogNewFrame(); } // draw buffer stuff if(gl_drawbuffer->modified){ gl_drawbuffer->modified = false; if(!Q_stricmp(gl_drawbuffer->string, "GL_FRONT")) qglDrawBuffer(GL_FRONT); else qglDrawBuffer(GL_BACK); } // texturemode stuff if(gl_texturemode->modified){ GL_TextureMode(gl_texturemode->string); gl_texturemode->modified = false; } if(gl_texturealphamode->modified){ GL_TextureAlphaMode(gl_texturealphamode->string); gl_texturealphamode->modified = false; } if(gl_texturesolidmode->modified){ GL_TextureSolidMode(gl_texturesolidmode->string); gl_texturesolidmode->modified = false; } // clear screen if desired GL_Clear(); } /* GL_Reload_f */ void GL_Reload_f(void){ cl.view_prepped = false; Draw_Fill(0, 0, r_viewdef.width, r_viewdef.height, 0); GL_ShutdownImages(); GL_InitImages(); GL_InitParticleTexture(); GL_InitNoTexture(); Draw_InitLocal(); V_RegisterViewMedia(); } /* Vid_Restart_f */ void VID_Restart_f(void){ extern qboolean update_viewdef; GL_SetMode(); update_viewdef = true; } /* GL_Register */ void GL_Register(void){ r_fullbright = Cvar_Get("r_fullbright", "0", 0); r_drawentities = Cvar_Get("r_drawentities", "1", 0); r_novis = Cvar_Get("r_novis", "0", 0); r_nocull = Cvar_Get("r_nocull", "0", 0); r_lerpmodels = Cvar_Get("r_lerpmodels", "1", 0); r_speeds = Cvar_Get("r_speeds", "0", 0); gl_log = Cvar_Get("gl_log", "0", 0); gl_modulate = Cvar_Get("gl_modulate", "1", CVAR_ARCHIVE); gl_intensity = Cvar_Get("gl_intensity", "2", CVAR_ARCHIVE); gl_lightmap = Cvar_Get("gl_lightmap", "0", 0); gl_monolightmap = Cvar_Get("gl_monolightmap", "0", 0); gl_loadtga = Cvar_Get("gl_loadtga", "1", CVAR_ARCHIVE); gl_rounddown = Cvar_Get("gl_rounddown", "1", 0); gl_picmip = Cvar_Get("gl_picmip", "0", 0); gl_skymip = Cvar_Get("gl_skymip", "0", 0); gl_playermip = Cvar_Get("gl_playermip", "0", 0); gl_wireframe = Cvar_Get("gl_wireframe", "0", 0); gl_ztrick = Cvar_Get("gl_ztrick", "1", CVAR_ARCHIVE); gl_finish = Cvar_Get("gl_finish", "0", CVAR_ARCHIVE); gl_clear = Cvar_Get("gl_clear", "0", 0); gl_cull = Cvar_Get("gl_cull", "1", 0); #ifdef _WIN32 gl_driver = Cvar_Get("gl_driver", "opengl32", CVAR_ARCHIVE); #else gl_driver = Cvar_Get("gl_driver", "libGL.so.1", CVAR_ARCHIVE); #endif gl_texturemode = Cvar_Get("gl_texturemode", "GL_LINEAR_MIPMAP_NEAREST", CVAR_ARCHIVE); gl_texturealphamode = Cvar_Get("gl_texturealphamode", "default", CVAR_ARCHIVE); gl_texturesolidmode = Cvar_Get("gl_texturesolidmode", "default", CVAR_ARCHIVE); gl_lockpvs = Cvar_Get("gl_lockpvs", "0", 0); gl_vertex_arrays = Cvar_Get("gl_vertex_arrays", "1", CVAR_ARCHIVE); gl_ext_multitexture = Cvar_Get("gl_ext_multitexture", "1", CVAR_ARCHIVE); gl_ext_compiled_vertex_array = Cvar_Get("gl_ext_compiled_vertex_array", "1", CVAR_ARCHIVE); gl_drawbuffer = Cvar_Get("gl_drawbuffer", "GL_BACK", 0); vid_width = Cvar_Get("vid_width", "640", CVAR_ARCHIVE); vid_height = Cvar_Get("vid_height", "480", CVAR_ARCHIVE); vid_fullscreen = Cvar_Get("vid_fullscreen", "0", CVAR_ARCHIVE); vid_gamma = Cvar_Get("vid_gamma", "1.0", CVAR_ARCHIVE); skydistance = Cvar_Get("skydistance", "2300", CVAR_ARCHIVE); Cmd_AddCommand("imagelist", GL_ImageList_f); Cmd_AddCommand("screenshot", GL_Screenshot_f); Cmd_AddCommand("gl_reload", GL_Reload_f); Cmd_AddCommand("vid_restart", VID_Restart_f); }