00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "r_local.h"
00026 #include "r_program.h"
00027 #include "r_sphere.h"
00028 #include "r_draw.h"
00029 #include "r_font.h"
00030 #include "r_light.h"
00031 #include "r_lightmap.h"
00032 #include "r_main.h"
00033 #include "r_geoscape.h"
00034 #include "r_misc.h"
00035 #include "r_error.h"
00036 #include "../../common/tracing.h"
00037 #include "../ui/ui_windows.h"
00038 #include "../../ports/system.h"
00039
00040 rendererData_t refdef;
00041
00042 rconfig_t r_config;
00043 rstate_t r_state;
00044 rlocals_t r_locals;
00045
00046 image_t *r_noTexture;
00047 image_t *r_warpTexture;
00048
00049 static cvar_t *r_maxtexres;
00050
00051 cvar_t *r_brightness;
00052 cvar_t *r_contrast;
00053 cvar_t *r_saturation;
00054 cvar_t *r_drawentities;
00055 cvar_t *r_drawworld;
00056 cvar_t *r_nocull;
00057 cvar_t *r_isometric;
00058 cvar_t *r_anisotropic;
00059 cvar_t *r_texture_lod;
00060 cvar_t *r_screenshot_format;
00061 cvar_t *r_screenshot_jpeg_quality;
00062 cvar_t *r_lightmap;
00063 cvar_t *r_debug_normals;
00064 cvar_t *r_debug_tangents;
00065 static cvar_t *r_deluxemap;
00066 cvar_t *r_ext_texture_compression;
00067 static cvar_t *r_ext_s3tc_compression;
00068 static cvar_t *r_ext_nonpoweroftwo;
00069 static cvar_t *r_intel_hack;
00070 static cvar_t *r_texturemode;
00071 static cvar_t *r_texturealphamode;
00072 static cvar_t *r_texturesolidmode;
00073 cvar_t *r_materials;
00074 cvar_t *r_checkerror;
00075 cvar_t *r_drawbuffer;
00076 cvar_t *r_driver;
00077 cvar_t *r_shadows;
00078 cvar_t *r_soften;
00079 cvar_t *r_modulate;
00080 cvar_t *r_swapinterval;
00081 cvar_t *r_multisample;
00082 cvar_t *r_wire;
00083 cvar_t *r_showbox;
00084 cvar_t *r_threads;
00085 cvar_t *r_vertexbuffers;
00086 cvar_t *r_warp;
00087 cvar_t *r_lights;
00088 cvar_t *r_dynamic_lights;
00089 cvar_t *r_programs;
00090 cvar_t *r_postprocess;
00091 cvar_t *r_maxlightmap;
00092 cvar_t *r_shownormals;
00093 cvar_t *r_bumpmap;
00094 cvar_t *r_specular;
00095 cvar_t *r_hardness;
00096 cvar_t *r_parallax;
00097 cvar_t *r_fog;
00098 cvar_t *r_flares;
00099 cvar_t *r_coronas;
00100
00101 static void R_PrintInfo (const char *pre, const char *msg)
00102 {
00103 char buf[4096];
00104 const size_t length = sizeof(buf);
00105 const size_t maxLength = strlen(msg);
00106 int i;
00107
00108 Com_Printf("%s: ", pre);
00109 for (i = 0; i < maxLength; i += length) {
00110 Q_strncpyz(buf, msg + i, sizeof(buf));
00111 Com_Printf("%s", buf);
00112 }
00113 Com_Printf("\n");
00114 }
00115
00119 static void R_Strings_f (void)
00120 {
00121 R_PrintInfo("GL_VENDOR", r_config.vendorString);
00122 R_PrintInfo("GL_RENDERER", r_config.rendererString);
00123 R_PrintInfo("GL_VERSION", r_config.versionString);
00124 R_PrintInfo("GL_EXTENSIONS", r_config.extensionsString);
00125 }
00126
00127 void R_SetupFrustum (void)
00128 {
00129 int i;
00130
00131
00132 AngleVectors(refdef.viewAngles, r_locals.forward, r_locals.right, r_locals.up);
00133
00134
00135 if (refdef.rendererFlags & RDF_NOWORLDMODEL) {
00136 glEnable(GL_SCISSOR_TEST);
00137 glScissor(viddef.x, viddef.height - viddef.viewHeight - viddef.y, viddef.viewWidth, viddef.viewHeight);
00138 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00139 R_CheckError();
00140 glDisable(GL_SCISSOR_TEST);
00141 }
00142
00143 if (r_isometric->integer) {
00144
00145 VectorScale(r_locals.right, +1, r_locals.frustum[0].normal);
00146 VectorScale(r_locals.right, -1, r_locals.frustum[1].normal);
00147 VectorScale(r_locals.up, +1, r_locals.frustum[2].normal);
00148 VectorScale(r_locals.up, -1, r_locals.frustum[3].normal);
00149
00150 for (i = 0; i < 4; i++) {
00151 r_locals.frustum[i].type = PLANE_ANYZ;
00152 r_locals.frustum[i].dist = DotProduct(refdef.viewOrigin, r_locals.frustum[i].normal);
00153 }
00154 r_locals.frustum[0].dist -= 10 * refdef.fieldOfViewX;
00155 r_locals.frustum[1].dist -= 10 * refdef.fieldOfViewX;
00156 r_locals.frustum[2].dist -= 10 * refdef.fieldOfViewX * ((float) viddef.viewHeight / viddef.viewWidth);
00157 r_locals.frustum[3].dist -= 10 * refdef.fieldOfViewX * ((float) viddef.viewHeight / viddef.viewWidth);
00158 } else {
00159
00160 RotatePointAroundVector(r_locals.frustum[0].normal, r_locals.up, r_locals.forward, -(90 - refdef.fieldOfViewX / 2));
00161
00162 RotatePointAroundVector(r_locals.frustum[1].normal, r_locals.up, r_locals.forward, 90 - refdef.fieldOfViewX / 2);
00163
00164 RotatePointAroundVector(r_locals.frustum[2].normal, r_locals.right, r_locals.forward, 90 - refdef.fieldOfViewY / 2);
00165
00166 RotatePointAroundVector(r_locals.frustum[3].normal, r_locals.right, r_locals.forward, -(90 - refdef.fieldOfViewY / 2));
00167
00168 for (i = 0; i < 4; i++) {
00169 r_locals.frustum[i].type = PLANE_ANYZ;
00170 r_locals.frustum[i].dist = DotProduct(refdef.viewOrigin, r_locals.frustum[i].normal);
00171 }
00172 }
00173 }
00174
00178 static inline void R_Clear (void)
00179 {
00180 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00181 R_CheckError();
00182 glDepthFunc(GL_LEQUAL);
00183 R_CheckError();
00184
00185 glDepthRange(0.0f, 1.0f);
00186 R_CheckError();
00187 }
00188
00192 static inline void R_ClearScene (void)
00193 {
00194
00195 refdef.numEntities = refdef.numLights = refdef.numCoronas = 0;
00196 }
00197
00202 void R_BeginFrame (void)
00203 {
00204
00205 if (vid_mode->modified || vid_fullscreen->modified || vid_strech->modified) {
00206 R_SetMode();
00207 #if defined(_WIN32) || defined(__APPLE__)
00208 VID_Restart_f();
00209 #endif
00210 }
00211
00212 if (Com_IsRenderModified()) {
00213 Com_Printf("Modified render related cvars\n");
00214 if (Cvar_PendingCvars(CVAR_R_CONTEXT))
00215 VID_Restart_f();
00216 else if (Cvar_PendingCvars(CVAR_R_PROGRAMS))
00217 R_RestartPrograms_f();
00218
00219 Com_SetRenderModified(qfalse);
00220 }
00221
00222 if (r_anisotropic->modified) {
00223 if (r_anisotropic->integer > r_config.maxAnisotropic) {
00224 Com_Printf("...max GL_EXT_texture_filter_anisotropic value is %i\n", r_config.maxAnisotropic);
00225 Cvar_SetValue("r_anisotropic", r_config.maxAnisotropic);
00226 }
00227
00228 r_anisotropic->modified = qfalse;
00229 }
00230
00231
00232 if (r_drawbuffer->modified) {
00233 r_drawbuffer->modified = qfalse;
00234
00235 if (Q_strcasecmp(r_drawbuffer->string, "GL_FRONT") == 0)
00236 glDrawBuffer(GL_FRONT);
00237 else
00238 glDrawBuffer(GL_BACK);
00239 R_CheckError();
00240 }
00241
00242
00243
00244 if (r_texturemode->modified) {
00245 R_TextureMode(r_texturemode->string);
00246 r_texturemode->modified = qfalse;
00247 }
00248
00249 if (r_texturealphamode->modified) {
00250 R_TextureAlphaMode(r_texturealphamode->string);
00251 r_texturealphamode->modified = qfalse;
00252 }
00253
00254 if (r_texturesolidmode->modified) {
00255 R_TextureSolidMode(r_texturesolidmode->string);
00256 r_texturesolidmode->modified = qfalse;
00257 }
00258
00259
00260 if (r_threads->modified) {
00261 if (r_threads->integer)
00262 R_InitThreads();
00263 else
00264 R_ShutdownThreads();
00265 r_threads->modified = qfalse;
00266 }
00267
00268 R_Setup2D();
00269
00270
00271 R_Clear();
00272 }
00273
00278 void R_RenderFrame (void)
00279 {
00280
00281 R_Setup3D();
00282
00283
00284 if (r_wire->integer)
00285 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
00286
00287 if (!(refdef.rendererFlags & RDF_NOWORLDMODEL)) {
00288 int tile;
00289 if (r_threads->integer) {
00290 while (r_threadstate.state != THREAD_RENDERER)
00291 Sys_Sleep(0);
00292
00293 r_threadstate.state = THREAD_CLIENT;
00294 } else {
00295 R_SetupFrustum();
00296
00297
00298 R_GetLevelSurfaceLists();
00299 }
00300
00301 R_EnableLights();
00302
00303 R_CheckError();
00304
00305 for (tile = 0; tile < r_numMapTiles; tile++) {
00306 R_EnableFog(qtrue);
00307
00308 R_DrawOpaqueSurfaces(r_mapTiles[tile]->bsp.opaque_surfaces);
00309 R_DrawOpaqueWarpSurfaces(r_mapTiles[tile]->bsp.opaque_warp_surfaces);
00310
00311 R_DrawAlphaTestSurfaces(r_mapTiles[tile]->bsp.alpha_test_surfaces);
00312
00313 R_EnableBlend(qtrue);
00314
00315 R_DrawMaterialSurfaces(r_mapTiles[tile]->bsp.material_surfaces);
00316
00317 R_DrawFlareSurfaces(r_mapTiles[tile]->bsp.flare_surfaces);
00318
00319 R_EnableFog(qfalse);
00320
00321 R_DrawCoronas();
00322
00323 R_DrawBlendSurfaces(r_mapTiles[tile]->bsp.blend_surfaces);
00324 R_DrawBlendWarpSurfaces(r_mapTiles[tile]->bsp.blend_warp_surfaces);
00325
00326 R_EnableBlend(qfalse);
00327
00328 R_DrawBspNormals(tile);
00329 }
00330 }
00331
00332 R_DrawEntities();
00333
00334 R_EnableBlend(qtrue);
00335
00336 R_DrawParticles();
00337
00338 R_EnableBlend(qfalse);
00339
00340 R_DrawBloom();
00341
00342
00343 if (r_wire->integer)
00344 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00345
00346 R_ResetArrayState();
00347
00348
00349 R_Setup2D();
00350
00351 R_CheckError();
00352 }
00353
00358 void R_EndFrame (void)
00359 {
00360 if (vid_gamma->modified) {
00361 if (!vid_ignoregamma->integer) {
00362 const float g = vid_gamma->value;
00363 SDL_SetGamma(g, g, g);
00364 }
00365 vid_gamma->modified = qfalse;
00366 }
00367
00368 R_ClearScene();
00369
00370 SDL_GL_SwapBuffers();
00371 }
00372
00373 static const cmdList_t r_commands[] = {
00374 {"r_listimages", R_ImageList_f, "Show all loaded images on game console"},
00375 {"r_listfontcache", R_FontListCache_f, "Show information about font cache"},
00376 {"r_screenshot", R_ScreenShot_f, "Take a screenshot"},
00377 {"r_listmodels", R_ModModellist_f, "Show all loaded models on game console"},
00378 {"r_strings", R_Strings_f, "Print openGL vendor and other strings"},
00379 {"r_restartprograms", R_RestartPrograms_f, "Reloads the shaders"},
00380
00381 {NULL, NULL, NULL}
00382 };
00383
00384 static qboolean R_CvarCheckMaxLightmap (cvar_t *cvar)
00385 {
00386 if (r_config.maxTextureSize && cvar->integer > r_config.maxTextureSize) {
00387 Com_Printf("%s exceeded max supported texture size\n", cvar->name);
00388 Cvar_SetValue(cvar->name, r_config.maxTextureSize);
00389 return qfalse;
00390 }
00391
00392 if (!Q_IsPowerOfTwo(cvar->integer)) {
00393 Com_Printf("%s must be power of two\n", cvar->name);
00394 Cvar_SetValue(cvar->name, LIGHTMAP_BLOCK_WIDTH);
00395 return qfalse;
00396 }
00397
00398 return Cvar_AssertValue(cvar, 128, LIGHTMAP_BLOCK_WIDTH, qtrue);
00399 }
00400
00401 static qboolean R_CvarCheckLights (cvar_t *cvar)
00402 {
00403 if (!cvar->integer)
00404 Cvar_SetValue("r_dynamic_lights", 0);
00405
00406 return Cvar_AssertValue(cvar, 0, 1, qtrue);
00407 }
00408
00409 static qboolean R_CvarCheckDynamicLights (cvar_t *cvar)
00410 {
00411 if (!r_lights->integer){
00412 Cvar_SetValue(cvar->name, 0);
00413 return qfalse;
00414 }
00415 return Cvar_AssertValue(cvar, 1, r_config.maxLights, qtrue);
00416 }
00417
00418 static qboolean R_CvarPrograms (cvar_t *cvar)
00419 {
00420 if (qglUseProgram) {
00421 if (!cvar->integer || !r_config.drawBuffers)
00422 Cvar_SetValue("r_postprocess", 0);
00423 return Cvar_AssertValue(cvar, 0, 1, qtrue);
00424 }
00425
00426 Cvar_SetValue(cvar->name, 0);
00427 return qtrue;
00428 }
00429
00430 static qboolean R_CvarPostProcess (cvar_t *cvar)
00431 {
00432 if (r_config.frameBufferObject && r_programs->integer && r_config.drawBuffers)
00433 return Cvar_AssertValue(cvar, 0, 1, qtrue);
00434
00435 Cvar_SetValue(cvar->name, 0);
00436 return qtrue;
00437 }
00438
00439 static void R_RegisterSystemVars (void)
00440 {
00441 const cmdList_t *commands;
00442
00443 r_driver = Cvar_Get("r_driver", "", CVAR_ARCHIVE | CVAR_R_CONTEXT, "You can define the opengl driver you want to use - empty if you want to use the system default");
00444 r_drawentities = Cvar_Get("r_drawentities", "1", 0, "Draw the local entities");
00445 r_drawworld = Cvar_Get("r_drawworld", "1", 0, "Draw the world brushes");
00446 r_isometric = Cvar_Get("r_isometric", "0", CVAR_ARCHIVE, "Draw the world in isometric mode");
00447 r_nocull = Cvar_Get("r_nocull", "0", 0, "Don't perform culling for brushes and entities");
00448 r_anisotropic = Cvar_Get("r_anisotropic", "1", CVAR_ARCHIVE, NULL);
00449 r_texture_lod = Cvar_Get("r_texture_lod", "0", CVAR_ARCHIVE, NULL);
00450 r_screenshot_format = Cvar_Get("r_screenshot_format", "jpg", CVAR_ARCHIVE, "png, jpg or tga are valid screenshot formats");
00451 r_screenshot_jpeg_quality = Cvar_Get("r_screenshot_jpeg_quality", "75", CVAR_ARCHIVE, "jpeg quality in percent for jpeg screenshots");
00452 r_threads = Cvar_Get("r_threads", "0", CVAR_ARCHIVE, "Activate threads for the renderer");
00453
00454 r_materials = Cvar_Get("r_materials", "1", CVAR_ARCHIVE, "Activate material subsystem");
00455 r_checkerror = Cvar_Get("r_checkerror", "0", CVAR_ARCHIVE, "Check for opengl errors");
00456 r_shadows = Cvar_Get("r_shadows", "1", CVAR_ARCHIVE, "Activate or deactivate shadows");
00457 r_maxtexres = Cvar_Get("r_maxtexres", "2048", CVAR_ARCHIVE | CVAR_R_IMAGES, "The maximum texture resolution UFO should use");
00458 r_texturemode = Cvar_Get("r_texturemode", "GL_LINEAR_MIPMAP_NEAREST", CVAR_ARCHIVE, "change the filtering and mipmapping for textures");
00459 r_texturealphamode = Cvar_Get("r_texturealphamode", "GL_RGBA", CVAR_ARCHIVE, NULL);
00460 r_texturesolidmode = Cvar_Get("r_texturesolidmode", "GL_RGB", CVAR_ARCHIVE, NULL);
00461 r_wire = Cvar_Get("r_wire", "0", 0, "Draw the scene in wireframe mode");
00462 r_showbox = Cvar_Get("r_showbox", "0", CVAR_ARCHIVE, "1=Shows model bounding box, 2=show also the brushes bounding boxes");
00463 r_lightmap = Cvar_Get("r_lightmap", "0", CVAR_R_PROGRAMS, "Draw only the lightmap");
00464 r_lightmap->modified = qfalse;
00465 r_deluxemap = Cvar_Get("r_deluxemap", "0", CVAR_R_PROGRAMS, "Draw only the deluxemap");
00466 r_deluxemap->modified = qfalse;
00467 r_debug_normals = Cvar_Get("r_debug_normals", "0", CVAR_R_PROGRAMS, "Draw dot(normal, light_0 direction)");
00468 r_debug_normals->modified = qfalse;
00469 r_debug_tangents = Cvar_Get("r_debug_tangents", "0", CVAR_R_PROGRAMS, "Draw tangent, bitangent, and normal dotted with light dir as RGB espectively");
00470 r_debug_tangents->modified = qfalse;
00471 r_ext_texture_compression = Cvar_Get("r_ext_texture_compression", "0", CVAR_ARCHIVE | CVAR_R_CONTEXT, NULL);
00472 r_ext_nonpoweroftwo = Cvar_Get("r_ext_nonpoweroftwo", "1", CVAR_ARCHIVE, "Enable or disable the non power of two extension");
00473 r_ext_s3tc_compression = Cvar_Get("r_ext_s3tc_compression", "1", CVAR_ARCHIVE, "Also see r_ext_texture_compression");
00474 r_intel_hack = Cvar_Get("r_intel_hack", "1", CVAR_ARCHIVE, "Intel cards have activated texture compression until this is set to 0");
00475 r_vertexbuffers = Cvar_Get("r_vertexbuffers", "0", CVAR_ARCHIVE | CVAR_R_CONTEXT, "Controls usage of OpenGL Vertex Buffer Objects (VBO) versus legacy vertex arrays.");
00476 r_maxlightmap = Cvar_Get("r_maxlightmap", "2048", CVAR_ARCHIVE | CVAR_LATCH, "Reduce this value on older hardware");
00477 Cvar_SetCheckFunction("r_maxlightmap", R_CvarCheckMaxLightmap);
00478
00479 r_drawbuffer = Cvar_Get("r_drawbuffer", "GL_BACK", 0, NULL);
00480 r_swapinterval = Cvar_Get("r_swapinterval", "0", CVAR_ARCHIVE | CVAR_R_CONTEXT, "Controls swap interval synchronization (V-Sync). Values between 0 and 2");
00481 r_multisample = Cvar_Get("r_multisample", "0", CVAR_ARCHIVE | CVAR_R_CONTEXT, "Controls multisampling (anti-aliasing). Values between 0 and 4");
00482 r_lights = Cvar_Get("r_lights", "1", CVAR_ARCHIVE | CVAR_R_PROGRAMS, "Activates or deactivates hardware lighting");
00483 Cvar_SetCheckFunction("r_lights", R_CvarCheckLights);
00484 r_warp = Cvar_Get("r_warp", "1", CVAR_ARCHIVE, "Activates or deactivates warping surface rendering");
00485 r_shownormals = Cvar_Get("r_shownormals", "0", CVAR_ARCHIVE, "Show normals on bsp surfaces");
00486 r_bumpmap = Cvar_Get("r_bumpmap", "1.0", CVAR_ARCHIVE | CVAR_R_PROGRAMS, "Activate bump mapping");
00487 r_specular = Cvar_Get("r_specular", "1.0", CVAR_ARCHIVE, "Controls specular parameters");
00488 r_hardness = Cvar_Get("r_hardness", "1.0", CVAR_ARCHIVE, "Hardness controll for GLSL shaders (specular, bump, ...)");
00489 r_parallax = Cvar_Get("r_parallax", "1.0", CVAR_ARCHIVE, "Controls parallax parameters");
00490 r_fog = Cvar_Get("r_fog", "1", CVAR_ARCHIVE | CVAR_R_PROGRAMS, "Activate or deactivate fog");
00491 r_flares = Cvar_Get("r_flares", "1", CVAR_ARCHIVE, "Activate or deactivate flares");
00492 r_coronas = Cvar_Get("r_coronas", "1", CVAR_ARCHIVE, "Activate or deactivate coronas");
00493
00494 for (commands = r_commands; commands->name; commands++)
00495 Cmd_AddCommand(commands->name, commands->function, commands->description);
00496 }
00497
00502 static void R_RegisterImageVars (void)
00503 {
00504 r_brightness = Cvar_Get("r_brightness", "1.0", CVAR_ARCHIVE | CVAR_R_IMAGES, "Brightness for images");
00505 r_contrast = Cvar_Get("r_contrast", "1.5", CVAR_ARCHIVE | CVAR_R_IMAGES, "Contrast for images");
00506 r_saturation = Cvar_Get("r_saturation", "1.0", CVAR_ARCHIVE | CVAR_R_IMAGES, "Saturation for images");
00507 if (r_config.hardwareType == GLHW_NVIDIA)
00508 r_modulate = Cvar_Get("r_modulate", "1.0", CVAR_ARCHIVE | CVAR_R_IMAGES, "Scale lightmap values");
00509 else
00510 r_modulate = Cvar_Get("r_modulate", "2.0", CVAR_ARCHIVE | CVAR_R_IMAGES, "Scale lightmap values");
00511 r_soften = Cvar_Get("r_soften", "0", CVAR_ARCHIVE | CVAR_R_IMAGES, "Apply blur to lightmap");
00512 }
00513
00514 static void R_UpdateVidDef (const vidmode_t *vidmode)
00515 {
00516 viddef.width = vidmode->width;
00517 viddef.height = vidmode->height;
00518
00519 if (viddef.strech) {
00520 viddef.virtualWidth = VID_NORM_WIDTH;
00521 viddef.virtualHeight = VID_NORM_HEIGHT;
00522 } else {
00523 float normRatio = (float) VID_NORM_WIDTH / (float) VID_NORM_HEIGHT;
00524 float screenRatio = (float) viddef.width / (float) viddef.height;
00525
00526
00527 if (screenRatio > normRatio) {
00528 viddef.virtualWidth = VID_NORM_HEIGHT * screenRatio;
00529 viddef.virtualHeight = VID_NORM_HEIGHT;
00530
00531 } else if (screenRatio < normRatio) {
00532 viddef.virtualWidth = VID_NORM_WIDTH;
00533 viddef.virtualHeight = VID_NORM_WIDTH / screenRatio;
00534
00535 } else {
00536 viddef.virtualWidth = VID_NORM_WIDTH;
00537 viddef.virtualHeight = VID_NORM_HEIGHT;
00538 }
00539 }
00540 viddef.rx = (float)viddef.width / viddef.virtualWidth;
00541 viddef.ry = (float)viddef.height / viddef.virtualHeight;
00542 }
00543
00544 qboolean R_SetMode (void)
00545 {
00546 qboolean result;
00547 unsigned prevWidth;
00548 unsigned prevHeight;
00549 int prevMode;
00550 qboolean prevFullscreen;
00551 vidmode_t vidmode;
00552
00553 Com_Printf("I: setting mode %d\n", vid_mode->integer);
00554
00555
00556 prevWidth = viddef.width;
00557 prevHeight = viddef.height;
00558 prevFullscreen = viddef.fullscreen;
00559 prevMode = viddef.mode;
00560
00561
00562 viddef.mode = vid_mode->integer;
00563 viddef.fullscreen = vid_fullscreen->integer;
00564 viddef.strech = vid_strech->integer;
00565 if (!VID_GetModeInfo(viddef.mode, &vidmode)) {
00566 Com_Printf("I: invalid mode\n");
00567 return qfalse;
00568 }
00569
00570 result = R_InitGraphics(viddef.fullscreen, vidmode.width, vidmode.height);
00571 R_UpdateVidDef(&vidmode);
00572 R_ShutdownFBObjects();
00573 R_InitFBObjects();
00574 UI_InvalidateStack();
00575
00576 Cvar_SetValue("vid_width", viddef.width);
00577 Cvar_SetValue("vid_height", viddef.height);
00578
00579 Com_Printf("I: %dx%d (fullscreen: %s)\n", vidmode.width, vidmode.height, viddef.fullscreen ? "yes" : "no");
00580 if (result)
00581 return qtrue;
00582
00583 Com_Printf("Failed to set video mode %dx%d %s.\n",
00584 viddef.width, viddef.height,
00585 (vid_fullscreen->integer ? "fullscreen" : "windowed"));
00586
00587 Cvar_SetValue("vid_width", prevWidth);
00588 Cvar_SetValue("vid_height", prevHeight);
00589 Cvar_SetValue("vid_mode", prevMode);
00590 Cvar_SetValue("vid_fullscreen", prevFullscreen);
00591
00592 viddef.mode = vid_mode->integer;
00593 viddef.fullscreen = vid_fullscreen->integer;
00594 if (!VID_GetModeInfo(viddef.mode, &vidmode))
00595 return qfalse;
00596
00597 result = R_InitGraphics(viddef.fullscreen, vidmode.width, vidmode.height);
00598 R_UpdateVidDef(&vidmode);
00599 R_ShutdownFBObjects();
00600 R_InitFBObjects();
00601 UI_InvalidateStack();
00602 return result;
00603 }
00604
00609 static qboolean R_InitExtensions (void)
00610 {
00611 GLenum err;
00612 int tmpInteger;
00613
00614
00615 qglActiveTexture = NULL;
00616 qglClientActiveTexture = NULL;
00617
00618
00619 qglGenBuffers = NULL;
00620 qglDeleteBuffers = NULL;
00621 qglBindBuffer = NULL;
00622 qglBufferData = NULL;
00623
00624
00625 qglCreateShader = NULL;
00626 qglDeleteShader = NULL;
00627 qglShaderSource = NULL;
00628 qglCompileShader = NULL;
00629 qglGetShaderiv = NULL;
00630 qglGetShaderInfoLog = NULL;
00631 qglCreateProgram = NULL;
00632 qglDeleteProgram = NULL;
00633 qglAttachShader = NULL;
00634 qglDetachShader = NULL;
00635 qglLinkProgram = NULL;
00636 qglUseProgram = NULL;
00637 qglGetProgramiv = NULL;
00638 qglGetProgramInfoLog = NULL;
00639 qglGetUniformLocation = NULL;
00640 qglUniform1i = NULL;
00641 qglUniform1f = NULL;
00642 qglUniform2fv = NULL;
00643 qglUniform3fv = NULL;
00644 qglUniform4fv = NULL;
00645
00646
00647 qglEnableVertexAttribArray = NULL;
00648 qglDisableVertexAttribArray = NULL;
00649 qglVertexAttribPointer = NULL;
00650
00651
00652 qglIsRenderbufferEXT = NULL;
00653 qglBindRenderbufferEXT = NULL;
00654 qglDeleteRenderbuffersEXT = NULL;
00655 qglGenRenderbuffersEXT = NULL;
00656 qglRenderbufferStorageEXT = NULL;
00657 qglGetRenderbufferParameterivEXT = NULL;
00658 qglIsFramebufferEXT = NULL;
00659 qglBindFramebufferEXT = NULL;
00660 qglDeleteFramebuffersEXT = NULL;
00661 qglGenFramebuffersEXT = NULL;
00662 qglCheckFramebufferStatusEXT = NULL;
00663 qglFramebufferTexture1DEXT = NULL;
00664 qglFramebufferTexture2DEXT = NULL;
00665 qglFramebufferTexture3DEXT = NULL;
00666 qglFramebufferRenderbufferEXT = NULL;
00667 qglGetFramebufferAttachmentParameterivEXT = NULL;
00668 qglGenerateMipmapEXT = NULL;
00669 qglDrawBuffers = NULL;
00670
00671
00672 if (strstr(r_config.extensionsString, "GL_ARB_multitexture")) {
00673 qglActiveTexture = SDL_GL_GetProcAddress("glActiveTexture");
00674 qglClientActiveTexture = SDL_GL_GetProcAddress("glClientActiveTexture");
00675 }
00676
00677 if (strstr(r_config.extensionsString, "GL_ARB_texture_compression")) {
00678 if (r_ext_texture_compression->integer) {
00679 Com_Printf("using GL_ARB_texture_compression\n");
00680 if (r_ext_s3tc_compression->integer && strstr(r_config.extensionsString, "GL_EXT_texture_compression_s3tc")) {
00681 r_config.gl_compressed_solid_format = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
00682 r_config.gl_compressed_alpha_format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
00683 } else {
00684 r_config.gl_compressed_solid_format = GL_COMPRESSED_RGB_ARB;
00685 r_config.gl_compressed_alpha_format = GL_COMPRESSED_RGBA_ARB;
00686 }
00687 }
00688 }
00689
00690 if (strstr(r_config.extensionsString, "GL_ARB_texture_non_power_of_two")) {
00691 if (r_ext_nonpoweroftwo->integer) {
00692 Com_Printf("using GL_ARB_texture_non_power_of_two\n");
00693 r_config.nonPowerOfTwo = qtrue;
00694 } else {
00695 r_config.nonPowerOfTwo = qfalse;
00696 Com_Printf("ignoring GL_ARB_texture_non_power_of_two\n");
00697 }
00698 } else {
00700 r_config.nonPowerOfTwo = qfalse;
00701 }
00702
00703
00704 if (strstr(r_config.extensionsString, "GL_EXT_texture_filter_anisotropic")) {
00705 if (r_anisotropic->integer) {
00706 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &r_config.maxAnisotropic);
00707 R_CheckError();
00708 if (r_anisotropic->integer > r_config.maxAnisotropic) {
00709 Com_Printf("max GL_EXT_texture_filter_anisotropic value is %i\n", r_config.maxAnisotropic);
00710 Cvar_SetValue("r_anisotropic", r_config.maxAnisotropic);
00711 }
00712
00713 if (r_config.maxAnisotropic)
00714 r_config.anisotropic = qtrue;
00715 }
00716 }
00717
00718 if (strstr(r_config.extensionsString, "GL_EXT_texture_lod_bias"))
00719 r_config.lod_bias = qtrue;
00720
00721
00722 if (strstr(r_config.extensionsString, "GL_ARB_vertex_buffer_object")) {
00723 qglGenBuffers = SDL_GL_GetProcAddress("glGenBuffers");
00724 qglDeleteBuffers = SDL_GL_GetProcAddress("glDeleteBuffers");
00725 qglBindBuffer = SDL_GL_GetProcAddress("glBindBuffer");
00726 qglBufferData = SDL_GL_GetProcAddress("glBufferData");
00727 }
00728
00729
00730 if (strstr(r_config.extensionsString, "GL_ARB_fragment_shader")) {
00731 qglCreateShader = SDL_GL_GetProcAddress("glCreateShader");
00732 qglDeleteShader = SDL_GL_GetProcAddress("glDeleteShader");
00733 qglShaderSource = SDL_GL_GetProcAddress("glShaderSource");
00734 qglCompileShader = SDL_GL_GetProcAddress("glCompileShader");
00735 qglGetShaderiv = SDL_GL_GetProcAddress("glGetShaderiv");
00736 qglGetShaderInfoLog = SDL_GL_GetProcAddress("glGetShaderInfoLog");
00737 qglCreateProgram = SDL_GL_GetProcAddress("glCreateProgram");
00738 qglDeleteProgram = SDL_GL_GetProcAddress("glDeleteProgram");
00739 qglAttachShader = SDL_GL_GetProcAddress("glAttachShader");
00740 qglDetachShader = SDL_GL_GetProcAddress("glDetachShader");
00741 qglLinkProgram = SDL_GL_GetProcAddress("glLinkProgram");
00742 qglUseProgram = SDL_GL_GetProcAddress("glUseProgram");
00743 qglGetProgramiv = SDL_GL_GetProcAddress("glGetProgramiv");
00744 qglGetProgramInfoLog = SDL_GL_GetProcAddress("glGetProgramInfoLog");
00745 qglGetUniformLocation = SDL_GL_GetProcAddress("glGetUniformLocation");
00746 qglUniform1i = SDL_GL_GetProcAddress("glUniform1i");
00747 qglUniform1f = SDL_GL_GetProcAddress("glUniform1f");
00748 qglUniform1fv = SDL_GL_GetProcAddress("glUniform1fv");
00749 qglUniform2fv = SDL_GL_GetProcAddress("glUniform2fv");
00750 qglUniform3fv = SDL_GL_GetProcAddress("glUniform3fv");
00751 qglUniform4fv = SDL_GL_GetProcAddress("glUniform4fv");
00752 qglGetAttribLocation = SDL_GL_GetProcAddress("glGetAttribLocation");
00753
00754
00755 qglEnableVertexAttribArray = SDL_GL_GetProcAddress("glEnableVertexAttribArray");
00756 qglDisableVertexAttribArray = SDL_GL_GetProcAddress("glDisableVertexAttribArray");
00757 qglVertexAttribPointer = SDL_GL_GetProcAddress("glVertexAttribPointer");
00758 }
00759
00760 if (strstr(r_config.extensionsString, "GL_ARB_shading_language_100")) {
00761 r_config.shadingLanguageVersion = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION_ARB);
00762 Com_Printf("using GL_ARB_shading_language_100\n");
00763 Com_Printf("GLSL Version: %s\n", r_config.shadingLanguageVersion);
00764 }
00765
00766
00767 if (strstr(r_config.extensionsString, "GL_ARB_framebuffer_object")
00768 || strstr(r_config.extensionsString, "GL_EXT_framebuffer_object")) {
00769 qglIsRenderbufferEXT = SDL_GL_GetProcAddress("glIsRenderbufferEXT");
00770 qglBindRenderbufferEXT = SDL_GL_GetProcAddress("glBindRenderbufferEXT");
00771 qglDeleteRenderbuffersEXT = SDL_GL_GetProcAddress("glDeleteRenderbuffersEXT");
00772 qglGenRenderbuffersEXT = SDL_GL_GetProcAddress("glGenRenderbuffersEXT");
00773 qglRenderbufferStorageEXT = SDL_GL_GetProcAddress("glRenderbufferStorageEXT");
00774 qglGetRenderbufferParameterivEXT = SDL_GL_GetProcAddress("glGetRenderbufferParameterivEXT");
00775 qglIsFramebufferEXT = SDL_GL_GetProcAddress("glIsFramebufferEXT");
00776 qglBindFramebufferEXT = SDL_GL_GetProcAddress("glBindFramebufferEXT");
00777 qglDeleteFramebuffersEXT = SDL_GL_GetProcAddress("glDeleteFramebuffersEXT");
00778 qglGenFramebuffersEXT = SDL_GL_GetProcAddress("glGenFramebuffersEXT");
00779 qglCheckFramebufferStatusEXT = SDL_GL_GetProcAddress("glCheckFramebufferStatusEXT");
00780 qglFramebufferTexture1DEXT = SDL_GL_GetProcAddress("glFramebufferTexture1DEXT");
00781 qglFramebufferTexture2DEXT = SDL_GL_GetProcAddress("glFramebufferTexture2DEXT");
00782 qglFramebufferTexture3DEXT = SDL_GL_GetProcAddress("glFramebufferTexture3DEXT");
00783 qglFramebufferRenderbufferEXT = SDL_GL_GetProcAddress("glFramebufferRenderbufferEXT");
00784 qglGetFramebufferAttachmentParameterivEXT = SDL_GL_GetProcAddress("glGetFramebufferAttachmentParameterivEXT");
00785 qglGenerateMipmapEXT = SDL_GL_GetProcAddress("glGenerateMipmapEXT");
00786 qglDrawBuffers = SDL_GL_GetProcAddress("glDrawBuffers");
00787
00788 if (qglBindFramebufferEXT && qglDeleteRenderbuffersEXT && qglDeleteFramebuffersEXT && qglGenFramebuffersEXT
00789 && qglBindFramebufferEXT && qglFramebufferTexture2DEXT && qglBindRenderbufferEXT && qglRenderbufferStorageEXT
00790 && qglCheckFramebufferStatusEXT) {
00791 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &r_config.maxDrawBuffers);
00792 glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE_EXT, &r_config.maxRenderbufferSize);
00793 glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &r_config.maxColorAttachments);
00794
00795 r_config.frameBufferObject = qtrue;
00796
00797 Com_Printf("using GL_ARB_framebuffer_object\n");
00798 Com_Printf("max draw buffers: %i\n", r_config.maxDrawBuffers);
00799 Com_Printf("max render buffer size: %i\n", r_config.maxRenderbufferSize);
00800 Com_Printf("max color attachments: %i\n", r_config.maxColorAttachments);
00801 }
00802
00803 if ((strstr(r_config.extensionsString, "GL_ARB_draw_buffers")
00804 || strstr(r_config.extensionsString, "GL_EXT_draw_buffers"))
00805 && r_config.maxDrawBuffers > 1) {
00806 Com_Printf("using GL_ARB_draw_buffers\n");
00807 r_config.drawBuffers = qtrue;
00808 } else {
00809 r_config.drawBuffers = qfalse;
00810 }
00811 }
00812
00813 r_programs = Cvar_Get("r_programs", "1", CVAR_ARCHIVE | CVAR_R_PROGRAMS, "Use GLSL shaders");
00814 r_programs->modified = qfalse;
00815 Cvar_SetCheckFunction("r_programs", R_CvarPrograms);
00816
00817 r_postprocess = Cvar_Get("r_postprocess", "1", CVAR_ARCHIVE | CVAR_R_PROGRAMS, "Activate postprocessing shader effects");
00818 Cvar_SetCheckFunction("r_postprocess", R_CvarPostProcess);
00819
00820
00821 R_CheckError();
00822
00823 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &r_config.maxVertexTextureImageUnits);
00824 Com_Printf("max supported vertex texture units: %i\n", r_config.maxVertexTextureImageUnits);
00825
00826 glGetIntegerv(GL_MAX_LIGHTS, &r_config.maxLights);
00827 Com_Printf("max supported lights: %i\n", r_config.maxLights);
00828
00829 r_dynamic_lights = Cvar_Get("r_dynamic_lights", "1", CVAR_ARCHIVE | CVAR_R_PROGRAMS, "Sets max number of GL lightsources to use in shaders");
00830 Cvar_SetCheckFunction("r_dynamic_lights", R_CvarCheckDynamicLights);
00831
00832 glGetIntegerv(GL_MAX_TEXTURE_UNITS, &r_config.maxTextureUnits);
00833 Com_Printf("max texture units: %i\n", r_config.maxTextureUnits);
00834 if (r_config.maxTextureUnits < 2)
00835 Com_Error(ERR_FATAL, "You need at least 2 texture units to run "GAME_TITLE);
00836
00837 glGetIntegerv(GL_MAX_TEXTURE_COORDS, &r_config.maxTextureCoords);
00838 Com_Printf("max texture coords: %i\n", r_config.maxTextureCoords);
00839 r_config.maxTextureCoords = max(r_config.maxTextureUnits, r_config.maxTextureCoords);
00840
00841 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &r_config.maxVertexAttribs);
00842 Com_Printf("max vertex attributes: %i\n", r_config.maxVertexAttribs);
00843
00844 glGetIntegerv(GL_MAX_VARYING_FLOATS, &tmpInteger);
00845 Com_Printf("max varying floats: %i\n", tmpInteger);
00846
00847 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &tmpInteger);
00848 Com_Printf("max fragment uniform components: %i\n", tmpInteger);
00849
00850 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, &tmpInteger);
00851 Com_Printf("max vertex uniform components: %i\n", tmpInteger);
00852
00853
00854 R_CheckError();
00855
00856
00857 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &r_config.maxTextureSize);
00858
00859 if (r_config.maxTextureSize <= 0)
00860 r_config.maxTextureSize = 256;
00861
00862 if ((err = glGetError()) != GL_NO_ERROR) {
00863 Com_Printf("max texture size: cannot detect - using %i! (%s)\n", r_config.maxTextureSize, R_TranslateError(err));
00864 Cvar_SetValue("r_maxtexres", r_config.maxTextureSize);
00865 } else {
00866 Com_Printf("max texture size: detected %d\n", r_config.maxTextureSize);
00867 if (r_maxtexres->integer > r_config.maxTextureSize) {
00868 Com_Printf("...downgrading from %i\n", r_maxtexres->integer);
00869 Cvar_SetValue("r_maxtexres", r_config.maxTextureSize);
00870
00871 } else if (r_maxtexres->integer >= 128 && r_maxtexres->integer < r_config.maxTextureSize) {
00872 Com_Printf("...but using %i as requested\n", r_maxtexres->integer);
00873 r_config.maxTextureSize = r_maxtexres->integer;
00874 }
00875 }
00876
00877 if (r_config.maxTextureSize > 4096 && R_ImageExists(va("pics/geoscape/%s/map_earth_season_00", "high"))) {
00878 Q_strncpyz(r_config.lodDir, "high", sizeof(r_config.lodDir));
00879 Com_Printf("Using high resolution globe textures as requested.\n");
00880 } else if (r_config.maxTextureSize > 2048 && R_ImageExists("pics/geoscape/med/map_earth_season_00")) {
00881 if (r_config.maxTextureSize > 4096) {
00882 Com_Printf("Warning: high resolution globe textures requested, but could not be found; falling back to medium resolution globe textures.\n");
00883 } else {
00884 Com_Printf("Using medium resolution globe textures as requested.\n");
00885 }
00886 Q_strncpyz(r_config.lodDir, "med", sizeof(r_config.lodDir));
00887 } else {
00888 if (r_config.maxTextureSize > 2048) {
00889 Com_Printf("Warning: medium resolution globe textures requested, but could not be found; falling back to low resolution globe textures.\n");
00890 } else {
00891 Com_Printf("Using low resolution globe textures as requested.\n");
00892 }
00893 Q_strncpyz(r_config.lodDir, "low", sizeof(r_config.lodDir));
00894 }
00895
00896
00897 if (!qglActiveTexture || !qglClientActiveTexture)
00898 return qfalse;
00899
00900 return qtrue;
00901 }
00902
00906 static inline void R_EnforceVersion (void)
00907 {
00908 int maj, min, rel;
00909
00910 sscanf(r_config.versionString, "%d.%d.%d ", &maj, &min, &rel);
00911
00912 if (maj > 1)
00913 return;
00914
00915 if (maj < 1)
00916 Com_Error(ERR_FATAL, "OpenGL version %s is less than 1.2.1", r_config.versionString);
00917
00918 if (min > 2)
00919 return;
00920
00921 if (min < 2)
00922 Com_Error(ERR_FATAL, "OpenGL Version %s is less than 1.2.1", r_config.versionString);
00923
00924 if (rel > 1)
00925 return;
00926
00927 if (rel < 1)
00928 Com_Error(ERR_FATAL, "OpenGL version %s is less than 1.2.1", r_config.versionString);
00929 }
00930
00934 static qboolean R_SearchForVendor (const char *vendor)
00935 {
00936 return Q_stristr(r_config.vendorString, vendor)
00937 || Q_stristr(r_config.rendererString, vendor);
00938 }
00939
00940 #define INTEL_TEXTURE_RESOLUTION 1024
00941
00945 static inline void R_VerifyDriver (void)
00946 {
00947 #ifdef _WIN32
00948 if (!Q_strcasecmp((const char*)glGetString(GL_RENDERER), "gdi generic"))
00949 Com_Error(ERR_FATAL, "No hardware acceleration detected.\n"
00950 "Update your graphic card drivers.");
00951 #else
00952 if (!Q_strcasecmp((const char*)glGetString(GL_RENDERER), "Software Rasterizer"))
00953 Com_Error(ERR_FATAL, "No hardware acceleration detected.\n"
00954 "Update your graphic card drivers.");
00955 #endif
00956 if (r_intel_hack->integer && R_SearchForVendor("Intel")) {
00957
00958 Com_Printf("Activate texture compression for Intel chips - see cvar r_intel_hack\n");
00959 Cvar_Set("r_ext_texture_compression", "1");
00960 if (r_maxtexres->integer > INTEL_TEXTURE_RESOLUTION) {
00961 Com_Printf("Set max. texture resolution to %i - see cvar r_intel_hack\n", INTEL_TEXTURE_RESOLUTION);
00962 Cvar_SetValue("r_maxtexres", INTEL_TEXTURE_RESOLUTION);
00963 }
00964 r_ext_texture_compression->modified = qfalse;
00965 r_config.hardwareType = GLHW_INTEL;
00966 } else if (R_SearchForVendor("NVIDIA")) {
00967 r_config.hardwareType = GLHW_NVIDIA;
00968 } else if (R_SearchForVendor("ATI") || R_SearchForVendor("Advanced Micro Devices") || R_SearchForVendor("AMD")) {
00969 r_config.hardwareType = GLHW_ATI;
00970 } else if (R_SearchForVendor("mesa")) {
00971 r_config.hardwareType = GLHW_MESA;
00972 } else {
00973 r_config.hardwareType = GLHW_GENERIC;
00974 }
00975 }
00976
00977 qboolean R_Init (void)
00978 {
00979 R_RegisterSystemVars();
00980
00981 memset(&r_state, 0, sizeof(r_state));
00982 memset(&r_locals, 0, sizeof(r_locals));
00983 memset(&r_config, 0, sizeof(r_config));
00984
00985
00986 r_config.gl_solid_format = GL_RGB;
00987 r_config.gl_alpha_format = GL_RGBA;
00988 r_config.gl_filter_min = GL_LINEAR_MIPMAP_NEAREST;
00989 r_config.gl_filter_max = GL_LINEAR;
00990 r_config.maxTextureSize = 256;
00991
00992
00993 if (!Rimp_Init())
00994 return qfalse;
00995
00996
00997 r_config.vendorString = (const char *)glGetString(GL_VENDOR);
00998 r_config.rendererString = (const char *)glGetString(GL_RENDERER);
00999 r_config.versionString = (const char *)glGetString(GL_VERSION);
01000 r_config.extensionsString = (const char *)glGetString(GL_EXTENSIONS);
01001 R_Strings_f();
01002
01003
01004 R_VerifyDriver();
01005 R_EnforceVersion();
01006
01007 R_RegisterImageVars();
01008
01009
01010 Cvar_ClearVars(CVAR_R_MASK);
01011
01012 R_InitExtensions();
01013 R_SetDefaultState();
01014 R_InitPrograms();
01015 R_InitImages();
01016 R_InitMiscTexture();
01017 R_DrawInitLocal();
01018 R_SphereInit();
01019 R_FontInit();
01020 R_InitFBObjects();
01021
01022 R_CheckError();
01023
01024 return qtrue;
01025 }
01026
01030 void R_Shutdown (void)
01031 {
01032 const cmdList_t *commands;
01033
01034 for (commands = r_commands; commands->name; commands++)
01035 Cmd_RemoveCommand(commands->name);
01036
01037 R_ShutdownModels(qtrue);
01038 R_ShutdownImages();
01039
01040 R_ShutdownPrograms();
01041 R_FontShutdown();
01042 R_ShutdownFBObjects();
01043
01044
01045 Rimp_Shutdown();
01046
01047 R_ShutdownThreads();
01048 }