/* =========================================================================== Copyright (C) 1999-2005 Id Software, Inc. Copyright (C) 2006-2011 Robert Beckebans This file is part of XreaL source code. XreaL source code 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. XreaL source code 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 XreaL source code; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ // tr_init.c -- functions that are not called every frame #include "tr_local.h" #if defined(__cplusplus) extern "C" { #endif glconfig_t glConfig; glconfig2_t glConfig2; #if defined(USE_D3D10) dxGlobals_t dx; #else glstate_t glState; #endif float displayAspect = 0.0f; qboolean textureFilterAnisotropic = qfalse; int maxAnisotropy = 0; static void GfxInfo_f(void); cvar_t *r_glCoreProfile; cvar_t *r_glMinMajorVersion; cvar_t *r_glMinMinorVersion; cvar_t *r_flares; cvar_t *r_flareSize; cvar_t *r_flareFade; cvar_t *r_railWidth; cvar_t *r_railCoreWidth; cvar_t *r_railSegmentLength; cvar_t *r_verbose; cvar_t *r_ignore; cvar_t *r_displayRefresh; cvar_t *r_znear; cvar_t *r_zfar; cvar_t *r_smp; cvar_t *r_showSmp; cvar_t *r_skipBackEnd; cvar_t *r_skipLightBuffer; cvar_t *r_ignorehwgamma; cvar_t *r_measureOverdraw; cvar_t *r_inGameVideo; cvar_t *r_fastsky; cvar_t *r_drawSun; cvar_t *r_lodBias; cvar_t *r_lodScale; cvar_t *r_lodTest; cvar_t *r_norefresh; cvar_t *r_drawentities; cvar_t *r_drawworld; cvar_t *r_drawpolies; cvar_t *r_speeds; cvar_t *r_novis; cvar_t *r_nocull; cvar_t *r_facePlaneCull; cvar_t *r_showcluster; cvar_t *r_nocurves; cvar_t *r_nobatching; cvar_t *r_noLightScissors; cvar_t *r_noLightVisCull; cvar_t *r_noInteractionSort; cvar_t *r_dynamicLight; cvar_t *r_staticLight; cvar_t *r_dynamicLightCastShadows; cvar_t *r_precomputedLighting; cvar_t *r_vertexLighting; cvar_t *r_compressDiffuseMaps; cvar_t *r_compressSpecularMaps; cvar_t *r_compressNormalMaps; cvar_t *r_heatHazeFix; cvar_t *r_noMarksOnTrisurfs; cvar_t *r_ext_compressed_textures; cvar_t *r_ext_occlusion_query; cvar_t *r_ext_texture_non_power_of_two; cvar_t *r_ext_draw_buffers; cvar_t *r_ext_vertex_array_object; cvar_t *r_ext_half_float_pixel; cvar_t *r_ext_texture_float; cvar_t *r_ext_stencil_wrap; cvar_t *r_ext_texture_filter_anisotropic; cvar_t *r_ext_stencil_two_side; cvar_t *r_ext_separate_stencil; cvar_t *r_ext_depth_bounds_test; cvar_t *r_ext_framebuffer_object; cvar_t *r_ext_packed_depth_stencil; cvar_t *r_ext_framebuffer_blit; cvar_t *r_extx_framebuffer_mixed_formats; cvar_t *r_ext_generate_mipmap; cvar_t *r_ignoreGLErrors; cvar_t *r_logFile; cvar_t *r_stencilbits; cvar_t *r_depthbits; cvar_t *r_colorbits; cvar_t *r_stereo; cvar_t *r_drawBuffer; cvar_t *r_uiFullScreen; cvar_t *r_shadows; cvar_t *r_softShadows; cvar_t *r_shadowBlur; cvar_t *r_shadowMapQuality; cvar_t *r_shadowMapSizeUltra; cvar_t *r_shadowMapSizeVeryHigh; cvar_t *r_shadowMapSizeHigh; cvar_t *r_shadowMapSizeMedium; cvar_t *r_shadowMapSizeLow; cvar_t *r_shadowMapSizeSunUltra; cvar_t *r_shadowMapSizeSunVeryHigh; cvar_t *r_shadowMapSizeSunHigh; cvar_t *r_shadowMapSizeSunMedium; cvar_t *r_shadowMapSizeSunLow; cvar_t *r_shadowOffsetFactor; cvar_t *r_shadowOffsetUnits; cvar_t *r_shadowLodBias; cvar_t *r_shadowLodScale; cvar_t *r_noShadowPyramids; cvar_t *r_cullShadowPyramidFaces; cvar_t *r_cullShadowPyramidCurves; cvar_t *r_cullShadowPyramidTriangles; cvar_t *r_debugShadowMaps; cvar_t *r_noShadowFrustums; cvar_t *r_noLightFrustums; cvar_t *r_shadowMapLuminanceAlpha; cvar_t *r_shadowMapLinearFilter; cvar_t *r_lightBleedReduction; cvar_t *r_overDarkeningFactor; cvar_t *r_shadowMapDepthScale; cvar_t *r_parallelShadowSplits; cvar_t *r_parallelShadowSplitWeight; cvar_t *r_lightSpacePerspectiveWarping; cvar_t *r_mode; cvar_t *r_collapseStages; cvar_t *r_nobind; cvar_t *r_singleShader; cvar_t *r_roundImagesDown; cvar_t *r_colorMipLevels; cvar_t *r_picmip; cvar_t *r_finish; cvar_t *r_clear; cvar_t *r_swapInterval; cvar_t *r_textureMode; cvar_t *r_offsetFactor; cvar_t *r_offsetUnits; cvar_t *r_forceSpecular; cvar_t *r_specularExponent; cvar_t *r_specularExponent2; cvar_t *r_specularScale; cvar_t *r_normalScale; cvar_t *r_normalMapping; cvar_t *r_wrapAroundLighting; cvar_t *r_halfLambertLighting; cvar_t *r_rimLighting; cvar_t *r_rimExponent; cvar_t *r_gamma; cvar_t *r_intensity; cvar_t *r_lockpvs; cvar_t *r_noportals; cvar_t *r_portalOnly; cvar_t *r_portalSky; cvar_t *r_subdivisions; cvar_t *r_stitchCurves; cvar_t *r_fullscreen; cvar_t *r_customwidth; cvar_t *r_customheight; cvar_t *r_customaspect; cvar_t *r_overBrightBits; cvar_t *r_mapOverBrightBits; cvar_t *r_debugSurface; cvar_t *r_simpleMipMaps; cvar_t *r_showImages; cvar_t *r_forceFog; cvar_t *r_wolfFog; cvar_t *r_noFog; cvar_t *r_forceAmbient; cvar_t *r_ambientScale; cvar_t *r_lightScale; cvar_t *r_debugLight; cvar_t *r_debugSort; cvar_t *r_printShaders; cvar_t *r_maxPolys; cvar_t *r_maxPolyVerts; cvar_t *r_showTris; cvar_t *r_showSky; cvar_t *r_showShadowVolumes; cvar_t *r_showShadowLod; cvar_t *r_showShadowMaps; cvar_t *r_showSkeleton; cvar_t *r_showEntityTransforms; cvar_t *r_showLightTransforms; cvar_t *r_showLightInteractions; cvar_t *r_showLightScissors; cvar_t *r_showLightBatches; cvar_t *r_showLightGrid; cvar_t *r_showOcclusionQueries; cvar_t *r_showBatches; cvar_t *r_showLightMaps; cvar_t *r_showDeluxeMaps; cvar_t *r_showAreaPortals; cvar_t *r_showCubeProbes; cvar_t *r_showBspNodes; cvar_t *r_showParallelShadowSplits; cvar_t *r_showDecalProjectors; cvar_t *r_showDeferredDiffuse; cvar_t *r_showDeferredNormal; cvar_t *r_showDeferredSpecular; cvar_t *r_showDeferredPosition; cvar_t *r_showDeferredRender; cvar_t *r_showDeferredLight; cvar_t *r_vboFaces; cvar_t *r_vboCurves; cvar_t *r_vboTriangles; cvar_t *r_vboShadows; cvar_t *r_vboLighting; cvar_t *r_vboModels; cvar_t *r_vboOptimizeVertices; cvar_t *r_vboVertexSkinning; cvar_t *r_vboDeformVertexes; cvar_t *r_vboSmoothNormals; #if defined(USE_BSP_CLUSTERSURFACE_MERGING) cvar_t *r_mergeClusterSurfaces; cvar_t *r_mergeClusterFaces; cvar_t *r_mergeClusterCurves; cvar_t *r_mergeClusterTriangles; #endif cvar_t *r_deferredShading; cvar_t *r_parallaxMapping; cvar_t *r_parallaxDepthScale; cvar_t *r_dynamicBspOcclusionCulling; cvar_t *r_dynamicEntityOcclusionCulling; cvar_t *r_dynamicLightOcclusionCulling; cvar_t *r_chcMaxPrevInvisNodesBatchSize; cvar_t *r_chcMaxVisibleFrames; cvar_t *r_chcVisibilityThreshold; cvar_t *r_chcIgnoreLeaves; cvar_t *r_hdrRendering; cvar_t *r_hdrMinLuminance; cvar_t *r_hdrMaxLuminance; cvar_t *r_hdrKey; cvar_t *r_hdrContrastThreshold; cvar_t *r_hdrContrastOffset; cvar_t *r_hdrLightmap; cvar_t *r_hdrLightmapExposure; cvar_t *r_hdrLightmapGamma; cvar_t *r_hdrLightmapCompensate; cvar_t *r_hdrToneMappingOperator; cvar_t *r_hdrGamma; cvar_t *r_hdrDebug; #ifdef EXPERIMENTAL cvar_t *r_screenSpaceAmbientOcclusion; #endif #ifdef EXPERIMENTAL cvar_t *r_depthOfField; #endif cvar_t *r_reflectionMapping; cvar_t *r_highQualityNormalMapping; cvar_t *r_bloom; cvar_t *r_bloomBlur; cvar_t *r_bloomPasses; cvar_t *r_rotoscope; cvar_t *r_cameraPostFX; cvar_t *r_cameraVignette; cvar_t *r_cameraFilmGrain; cvar_t *r_cameraFilmGrainScale; cvar_t *r_evsmPostProcess; cvar_t *r_allowExtensions; cvar_t *r_ext_multitexture; cvar_t *r_ext_compiled_vertex_array; cvar_t *r_ext_texture_env_add; cvar_t *r_ext_max_anisotropy; // IneQuation cvar_t *r_ext_multisample_samples; cvar_t *r_texturebits; static void AssertCvarRange(cvar_t * cv, float minVal, float maxVal, qboolean shouldBeIntegral) { if(shouldBeIntegral) { if((int)cv->value != cv->integer) { ri.Printf(PRINT_WARNING, "WARNING: cvar '%s' must be integral (%f)\n", cv->name, cv->value); ri.Cvar_Set(cv->name, va("%d", cv->integer)); } } if(cv->value < minVal) { ri.Printf(PRINT_WARNING, "WARNING: cvar '%s' out of range (%f < %f)\n", cv->name, cv->value, minVal); ri.Cvar_Set(cv->name, va("%f", minVal)); } else if(cv->value > maxVal) { ri.Printf(PRINT_WARNING, "WARNING: cvar '%s' out of range (%f > %f)\n", cv->name, cv->value, maxVal); ri.Cvar_Set(cv->name, va("%f", maxVal)); } } /* ** InitOpenGL ** ** This function is responsible for initializing a valid OpenGL subsystem. This ** is done by calling GLimp_Init (which gives us a working OGL subsystem) then ** setting variables, checking GL constants, and reporting the gfx system config ** to the user. */ #if !defined(USE_D3D10) static void InitOpenGL(void) { char renderer_buffer[1024]; // // initialize OS specific portions of the renderer // // GLimp_Init directly or indirectly references the following cvars: // - r_fullscreen // - r_glDriver // - r_mode // - r_(color|depth|stencil)bits // - r_ignorehwgamma // - r_gamma // if(glConfig.vidWidth == 0) { GLint temp; GLimp_Init(); glewInit(); GL_CheckErrors(); strcpy(renderer_buffer, glConfig.renderer_string); Q_strlwr(renderer_buffer); // OpenGL driver constants glGetIntegerv(GL_MAX_TEXTURE_SIZE, &temp); glConfig.maxTextureSize = temp; // stubbed or broken drivers may have reported 0... if(glConfig.maxTextureSize <= 0) { glConfig.maxTextureSize = 0; } #if defined(GLSL_COMPILE_STARTUP_ONLY) GLSL_InitGPUShaders(); #endif } GL_CheckErrors(); // init command buffers and SMP R_InitCommandBuffers(); GL_CheckErrors(); // print info GfxInfo_f(); GL_CheckErrors(); // set default state GL_SetDefaultState(); GL_CheckErrors(); } #endif /* ================== GL_CheckErrors ================== */ void GL_CheckErrors_(const char *fileName, int line) { int err; char s[128]; if(glConfig.smpActive) { // we can't print onto the console while rendering in another thread return; } if(r_ignoreGLErrors->integer) { return; } err = glGetError(); if(err == GL_NO_ERROR) { return; } switch (err) { case GL_INVALID_ENUM: strcpy(s, "GL_INVALID_ENUM"); break; case GL_INVALID_VALUE: strcpy(s, "GL_INVALID_VALUE"); break; case GL_INVALID_OPERATION: strcpy(s, "GL_INVALID_OPERATION"); break; case GL_STACK_OVERFLOW: strcpy(s, "GL_STACK_OVERFLOW"); break; case GL_STACK_UNDERFLOW: strcpy(s, "GL_STACK_UNDERFLOW"); break; case GL_OUT_OF_MEMORY: strcpy(s, "GL_OUT_OF_MEMORY"); break; case GL_TABLE_TOO_LARGE: strcpy(s, "GL_TABLE_TOO_LARGE"); break; case GL_INVALID_FRAMEBUFFER_OPERATION_EXT: strcpy(s, "GL_INVALID_FRAMEBUFFER_OPERATION_EXT"); break; default: Com_sprintf(s, sizeof(s), "0x%X", err); break; } ri.Error(ERR_FATAL, "caught OpenGL error: %s in file %s line %i", s, fileName, line); } /* ** R_GetModeInfo */ typedef struct vidmode_s { const char *description; int width, height; float pixelAspect; // pixel width / height } vidmode_t; vidmode_t r_vidModes[] = { {"Mode 0: 320x240", 320, 240, 1}, {"Mode 1: 400x300", 400, 300, 1}, {"Mode 2: 512x384", 512, 384, 1}, {"Mode 3: 640x480", 640, 480, 1}, {"Mode 4: 800x600", 800, 600, 1}, {"Mode 5: 960x720", 960, 720, 1}, {"Mode 6: 1024x768", 1024, 768, 1}, {"Mode 7: 1152x864", 1152, 864, 1}, {"Mode 8: 1280x720 (16:9)", 1280, 720, 1}, {"Mode 9: 1280x768 (16:10)", 1280, 768, 1}, {"Mode 10: 1280x800 (16:10)", 1280, 800, 1}, {"Mode 11: 1280x1024", 1280, 1024, 1}, {"Mode 12: 1360x768 (16:9)", 1360, 768, 1}, {"Mode 13: 1440x900 (16:10)", 1440, 900, 1}, {"Mode 14: 1680x1050 (16:10)", 1680, 1050, 1}, {"Mode 15: 1600x1200", 1600, 1200, 1}, {"Mode 16: 1920x1080 (16:9)", 1920, 1080, 1}, {"Mode 17: 1920x1200 (16:10)", 1920, 1200, 1}, {"Mode 18: 2048x1536", 2048, 1536, 1}, {"Mode 19: 2560x1600 (16:10)", 2560, 1600, 1}, }; static int s_numVidModes = (sizeof(r_vidModes) / sizeof(r_vidModes[0])); qboolean R_GetModeInfo(int *width, int *height, float *windowAspect, int mode) { vidmode_t *vm; if(mode < -1) { return qfalse; } if(mode >= s_numVidModes) { return qfalse; } if(mode == -1) { *width = r_customwidth->integer; *height = r_customheight->integer; *windowAspect = r_customaspect->value; return qtrue; } vm = &r_vidModes[mode]; *width = vm->width; *height = vm->height; *windowAspect = (float)vm->width / (vm->height * vm->pixelAspect); return qtrue; } /* ** R_ModeList_f */ static void R_ModeList_f(void) { int i; ri.Printf(PRINT_ALL, "\n"); for(i = 0; i < s_numVidModes; i++) { ri.Printf(PRINT_ALL, "%s\n", r_vidModes[i].description); } ri.Printf(PRINT_ALL, "\n"); } /* ============================================================================== SCREEN SHOTS screenshots get written in fs_homepath + fs_gamedir .. base/screenshots\*.* three commands: "screenshot", "screenshotJPEG" and "screenshotPNG" the format is xreal-YYYY_MM_DD-HH_MM_SS-MS.tga/jpeg/png ============================================================================== */ /* ================== RB_TakeScreenshot ================== */ static void RB_TakeScreenshot(int x, int y, int width, int height, char *fileName) { byte *buffer; int i, c, temp; buffer = (byte*) ri.Malloc(glConfig.vidWidth * glConfig.vidHeight * 3 + 18); Com_Memset(buffer, 0, 18); buffer[2] = 2; // uncompressed type buffer[12] = width & 255; buffer[13] = width >> 8; buffer[14] = height & 255; buffer[15] = height >> 8; buffer[16] = 24; // pixel size #if defined(USE_D3D10) // TODO #else glReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer + 18); #endif // swap rgb to bgr c = 18 + width * height * 3; for(i = 18; i < c; i += 3) { temp = buffer[i]; buffer[i] = buffer[i + 2]; buffer[i + 2] = temp; } // gamma correct if((tr.overbrightBits > 0) && glConfig.deviceSupportsGamma) { R_GammaCorrect(buffer + 18, glConfig.vidWidth * glConfig.vidHeight * 3); } ri.FS_WriteFile(fileName, buffer, c); ri.Free(buffer); } /* ================== RB_TakeScreenshotJPEG ================== */ static void RB_TakeScreenshotJPEG(int x, int y, int width, int height, char *fileName) { byte *buffer; buffer = (byte*) ri.Malloc(glConfig.vidWidth * glConfig.vidHeight * 3); #if defined(USE_D3D10) // TODO #else glReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer); #endif // gamma correct if((tr.overbrightBits > 0) && glConfig.deviceSupportsGamma) { R_GammaCorrect(buffer, glConfig.vidWidth * glConfig.vidHeight * 3); } ri.FS_WriteFile(fileName, buffer, 1); // create path SaveJPG(fileName, 90, glConfig.vidWidth, glConfig.vidHeight, buffer); ri.Free(buffer); } /* ================== RB_TakeScreenshotPNG ================== */ static void RB_TakeScreenshotPNG(int x, int y, int width, int height, char *fileName) { byte *buffer; buffer = (byte*) ri.Malloc(glConfig.vidWidth * glConfig.vidHeight * 3); #if defined(USE_D3D10) // TODO #else glReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer); #endif // gamma correct if((tr.overbrightBits > 0) && glConfig.deviceSupportsGamma) { R_GammaCorrect(buffer, glConfig.vidWidth * glConfig.vidHeight * 3); } ri.FS_WriteFile(fileName, buffer, 1); // create path SavePNG(fileName, buffer, glConfig.vidWidth, glConfig.vidHeight, 3, qfalse); ri.Free(buffer); } /* ================== RB_TakeScreenshotCmd ================== */ const void *RB_TakeScreenshotCmd(const void *data) { const screenshotCommand_t *cmd; cmd = (const screenshotCommand_t *)data; switch (cmd->format) { case SSF_TGA: RB_TakeScreenshot(cmd->x, cmd->y, cmd->width, cmd->height, cmd->fileName); break; case SSF_JPEG: RB_TakeScreenshotJPEG(cmd->x, cmd->y, cmd->width, cmd->height, cmd->fileName); break; case SSF_PNG: RB_TakeScreenshotPNG(cmd->x, cmd->y, cmd->width, cmd->height, cmd->fileName); break; } return (const void *)(cmd + 1); } /* ================== R_TakeScreenshot ================== */ void R_TakeScreenshot(char *name, ssFormat_t format) { static char fileName[MAX_OSPATH]; // bad things may happen if two screenshots per frame are taken. screenshotCommand_t *cmd; int lastNumber; cmd = (screenshotCommand_t *) R_GetCommandBuffer(sizeof(*cmd)); if(!cmd) { return; } #if 0 if(ri.Cmd_Argc() == 2) { Com_sprintf(fileName, sizeof(fileName), "screenshots/" PRODUCT_NAME_LOWER "-%s.%s", ri.Cmd_Argv(1), name); } else { qtime_t t; ri.RealTime(&t); // scan for a free filename for(lastNumber = 0; lastNumber <= 999; lastNumber++) { Com_sprintf(fileName, sizeof(fileName), "screenshots/" PRODUCT_NAME_LOWER "-%04d%02d%02d-%02d%02d%02d-%03d.%s", 1900 + t.tm_year, 1 + t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, lastNumber, name); if(!ri.FS_FileExists(fileName)) { break; // file doesn't exist } } if(lastNumber == 1000) { ri.Printf(PRINT_ALL, "ScreenShot: Couldn't create a file\n"); return; } lastNumber++; } ri.Printf(PRINT_ALL, "Wrote %s\n", fileName); #else ri.Printf(PRINT_ALL,"Fixme."); #endif cmd->commandId = RC_SCREENSHOT; cmd->x = 0; cmd->y = 0; cmd->width = glConfig.vidWidth; cmd->height = glConfig.vidHeight; cmd->fileName = fileName; cmd->format = format; } /* ================== R_ScreenShot_f screenshot screenshot [filename] ================== */ static void R_ScreenShot_f(void) { R_TakeScreenshot("tga", SSF_TGA); } static void R_ScreenShotJPEG_f(void) { R_TakeScreenshot("jpg", SSF_JPEG); } static void R_ScreenShotPNG_f(void) { R_TakeScreenshot("png", SSF_PNG); } /* ==================== R_LevelShot levelshots are specialized 128*128 thumbnails for the menu system, sampled down from full screen distorted images ==================== */ /*static void R_LevelShot(void) { char checkname[MAX_OSPATH]; byte *buffer; byte *source; byte *src, *dst; int x, y; int r, g, b; float xScale, yScale; int xx, yy; sprintf(checkname, "levelshots/%s.tga", tr.world->baseName); source = ri.Malloc(glConfig.vidWidth * glConfig.vidHeight * 3); buffer = ri.Malloc(128 * 128 * 3 + 18); Com_Memset(buffer, 0, 18); buffer[2] = 2; // uncompressed type buffer[12] = 128; buffer[14] = 128; buffer[16] = 24; // pixel size glReadPixels(0, 0, glConfig.vidWidth, glConfig.vidHeight, GL_RGB, GL_UNSIGNED_BYTE, source); // resample from source xScale = glConfig.vidWidth / 512.0f; yScale = glConfig.vidHeight / 384.0f; for(y = 0; y < 128; y++) { for(x = 0; x < 128; x++) { r = g = b = 0; for(yy = 0; yy < 3; yy++) { for(xx = 0; xx < 4; xx++) { src = source + 3 * (glConfig.vidWidth * (int)((y * 3 + yy) * yScale) + (int)((x * 4 + xx) * xScale)); r += src[0]; g += src[1]; b += src[2]; } } dst = buffer + 18 + 3 * (y * 128 + x); dst[0] = b / 12; dst[1] = g / 12; dst[2] = r / 12; } } // gamma correct if((tr.overbrightBits > 0) && glConfig.deviceSupportsGamma) { R_GammaCorrect(buffer + 18, 128 * 128 * 3); } ri.FS_WriteFile(checkname, buffer, 128 * 128 * 3 + 18); ri.Free(buffer); ri.Free(source); ri.Printf(PRINT_ALL, "Wrote %s\n", checkname); }*/ /* static int QDECL MaterialNameCompare(const void *a, const void *b) { char *s1, *s2; int c1, c2; s1 = *(char **)a; s2 = *(char **)b; do { c1 = *s1++; c2 = *s2++; if(c1 >= 'a' && c1 <= 'z') { c1 -= ('a' - 'A'); } if(c2 >= 'a' && c2 <= 'z') { c2 -= ('a' - 'A'); } if(c1 == '\\' || c1 == ':') { c1 = '/'; } if(c2 == '\\' || c2 == ':') { c2 = '/'; } if(c1 < c2) { // strings not equal return -1; } if(c1 > c2) { return 1; } } while(c1); // strings are equal return 0; } */ /* static void R_GenerateMaterialFile_f(void) { char **dirnames; int ndirs; int i; fileHandle_t f; char fileName[MAX_QPATH]; char fileName2[MAX_QPATH]; char cleanName[MAX_QPATH]; char cleanName2[MAX_QPATH]; char baseName[MAX_QPATH]; char baseName2[MAX_QPATH]; char path[MAX_QPATH]; char extension[MAX_QPATH]; int len; if(Cmd_Argc() < 3) { Com_Printf("usage: generatemtr [image extension]\n"); return; } Q_strncpyz(path, ri.Cmd_Argv(1), sizeof(path)); Q_strncpyz(extension, ri.Cmd_Argv(2), sizeof(extension)); Q_strreplace(extension, sizeof(extension), ".", ""); Q_strncpyz(fileName, ri.Cmd_Argv(1), sizeof(fileName)); Com_DefaultExtension(fileName, sizeof(fileName), ".mtr"); Com_Printf("Writing %s.\n", fileName); f = FS_FOpenFileWrite(fileName); if(!f) { Com_Printf("Couldn't write %s.\n", fileName); return; } FS_Printf(f, "// generated by XreaL\n\n"); dirnames = FS_ListFiles(path, extension, &ndirs); qsort(dirnames, ndirs, sizeof(char *), MaterialNameCompare); for(i = 0; i < ndirs; i++) { // clean name Q_strncpyz(fileName, dirnames[i], sizeof(fileName)); Q_strncpyz(cleanName, dirnames[i], sizeof(cleanName)); Q_strreplace(cleanName, sizeof(cleanName), "MaPZone[", ""); Q_strreplace(cleanName, sizeof(cleanName), "]", ""); Q_strreplace(cleanName, sizeof(cleanName), "&", "_"); if(strcmp(fileName, cleanName)) { Com_sprintf(fileName2, sizeof(fileName2), "%s/%s", path, fileName); Com_sprintf(cleanName2, sizeof(cleanName2), "%s/%s", path, cleanName); Com_Printf("renaming '%s' into '%s'\n", fileName2, cleanName2); FS_Rename(fileName2, cleanName2); } COM_StripExtension(cleanName, cleanName, sizeof(cleanName)); if(!Q_stristr(cleanName, "_nm") && !Q_stristr(cleanName, "blend")) { Q_strncpyz(baseName, cleanName, sizeof(baseName)); Q_strreplace(baseName, sizeof(baseName), "_diffuse", ""); FS_Printf(f, "%s/%s\n", path, baseName); FS_Printf(f, "{\n"); FS_Printf(f, "\t qer_editorImage\t %s/%s.%s\n", path, cleanName, extension); FS_Printf(f, "\n"); FS_Printf(f, "\t parallax\n"); FS_Printf(f, "\n"); FS_Printf(f, "\t diffuseMap\t\t %s/%s.%s\n", path, baseName, extension); Com_sprintf(fileName, sizeof(fileName), "%s/%s_nm.%s", path, baseName, extension); if(ri.FS_ReadFile(fileName, NULL) > 0) { FS_Printf(f, "\t normalMap\t\t %s/%s_nm.%s\n", path, baseName, extension); } Q_strncpyz(baseName2, baseName, sizeof(baseName2)); len = strlen(baseName); baseName2[len -1] = '\0'; Com_sprintf(fileName, sizeof(fileName), "%s/speculars/%s_s.%s", path, baseName2, extension); if(ri.FS_ReadFile(fileName, NULL) > 0) { FS_Printf(f, "\t specularMap\t %s/speculars/%s_s.%s\n", path, baseName2, extension); } Com_sprintf(fileName, sizeof(fileName), "%s/%s.blend.%s", path, baseName, extension); if(ri.FS_ReadFile(fileName, NULL) > 0) { FS_Printf(f, "\t glowMap\t\t %s/%s.blend.%s\n", path, baseName, extension); } FS_Printf(f, "}\n\n"); } } ri.FS_FreeFileList(dirnames); ri.FS_FCloseFile(f); } */ //============================================================================ /* ================== RB_TakeVideoFrameCmd ================== */ const void *RB_TakeVideoFrameCmd(const void *data) { const videoFrameCommand_t *cmd; int frameSize; int i; cmd = (const videoFrameCommand_t *)data; // RB: it is possible to we still have a videoFrameCommand_t but we already stopped // video recording #if 0 if(ri.CL_VideoRecording()) { glReadPixels(0, 0, cmd->width, cmd->height, GL_RGB, GL_UNSIGNED_BYTE, cmd->captureBuffer); // gamma correct if((tr.overbrightBits > 0) && glConfig.deviceSupportsGamma) { R_GammaCorrect(cmd->captureBuffer, cmd->width * cmd->height * 4); } if(cmd->motionJpeg) { frameSize = SaveJPGToBuffer(cmd->encodeBuffer, cmd->width * cmd->height * 3, 90, cmd->width, cmd->height, cmd->captureBuffer); ri.CL_WriteAVIVideoFrame(cmd->encodeBuffer, frameSize); } else { frameSize = cmd->width * cmd->height; for(i = 0; i < frameSize; i++) // Pack to 24bpp and swap R and B { cmd->encodeBuffer[i * 3] = cmd->captureBuffer[i * 3 + 2]; cmd->encodeBuffer[i * 3 + 1] = cmd->captureBuffer[i * 3 + 1]; cmd->encodeBuffer[i * 3 + 2] = cmd->captureBuffer[i * 3]; } ri.CL_WriteAVIVideoFrame(cmd->encodeBuffer, frameSize * 3); } } #endif return (const void *)(cmd + 1); } //============================================================================ /* ** GL_SetDefaultState */ void GL_SetDefaultState(void) { int i; GLimp_LogComment("--- GL_SetDefaultState ---\n"); GL_ClearDepth(1.0f); if(glConfig.stencilBits >= 4) { GL_ClearStencil(128); } GL_FrontFace(GL_CCW); GL_CullFace(GL_FRONT); glState.faceCulling = CT_TWO_SIDED; glDisable(GL_CULL_FACE); GL_CheckErrors(); glVertexAttrib4fARB(ATTR_INDEX_COLOR, 1, 1, 1, 1); GL_CheckErrors(); // initialize downstream texture units if we're running // in a multitexture environment if(glConfig.driverType == GLDRV_OPENGL3) { for(i = 31; i >= 0; i--) { GL_SelectTexture(i); GL_TextureMode(r_textureMode->string); } } else { if(GLEW_ARB_multitexture) { for(i = glConfig.numTextureUnits - 1; i >= 0; i--) { GL_SelectTexture(i); GL_TextureMode(r_textureMode->string); /* if(i != 0) glDisable(GL_TEXTURE_2D); else glEnable(GL_TEXTURE_2D); */ } } } GL_CheckErrors(); GL_DepthFunc(GL_LEQUAL); // make sure our GL state vector is set correctly glState.glStateBits = GLS_DEPTHTEST_DISABLE | GLS_DEPTHMASK_TRUE; glState.vertexAttribsState = 0; glState.vertexAttribPointersSet = 0; glState.currentProgram = 0; glUseProgramObjectARB(0); glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); glState.currentVBO = NULL; glState.currentIBO = NULL; GL_CheckErrors(); // the vertex array is always enabled, but the color and texture // arrays are enabled and disabled around the compiled vertex array call glEnableVertexAttribArrayARB(ATTR_INDEX_POSITION); /* OpenGL 3.0 spec: E.1. PROFILES AND DEPRECATED FEATURES OF OPENGL 3.0 405 Calling VertexAttribPointer when no buffer object or no vertex array object is bound will generate an INVALID OPERATION error, as will calling any array drawing command when no vertex array object is bound. */ if(glConfig2.framebufferObjectAvailable) { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); glState.currentFBO = NULL; } /* if(glConfig2.drawBuffersAvailable && glConfig2.maxDrawBuffers >= 4) { // enable all attachments as draw buffers GLenum drawbuffers[] = {GL_DRAW_BUFFER0_ARB, GL_DRAW_BUFFER1_ARB, GL_DRAW_BUFFER2_ARB, GL_DRAW_BUFFER3_ARB}; glDrawBuffersARB(4, drawbuffers); } */ GL_PolygonMode(GL_FRONT_AND_BACK, GL_FILL); GL_DepthMask(GL_TRUE); glDisable(GL_DEPTH_TEST); glEnable(GL_SCISSOR_TEST); glDisable(GL_BLEND); GL_CheckErrors(); glState.stackIndex = 0; for(i = 0; i < MAX_GLSTACK; i++) { MatrixIdentity(glState.modelViewMatrix[i]); MatrixIdentity(glState.projectionMatrix[i]); MatrixIdentity(glState.modelViewProjectionMatrix[i]); } } /* ================ GfxInfo_f ================ */ void GfxInfo_f(void) { /*const char *enablestrings[] = { "disabled", "enabled" };*/ const char *fsstrings[] = { "windowed", "fullscreen" }; ri.Printf(PRINT_ALL, "\nGL_VENDOR: %s\n", glConfig.vendor_string); ri.Printf(PRINT_ALL, "GL_RENDERER: %s\n", glConfig.renderer_string); ri.Printf(PRINT_ALL, "GL_VERSION: %s\n", glConfig.version_string); ri.Printf(PRINT_ALL, "GL_EXTENSIONS: %s\n", glConfig.extensions_string); ri.Printf(PRINT_ALL, "GL_MAX_TEXTURE_SIZE: %d\n", glConfig.maxTextureSize); if(glConfig.driverType != GLDRV_OPENGL3) { ri.Printf(PRINT_ALL, "GL_MAX_TEXTURE_UNITS_ARB: %d\n", glConfig.numTextureUnits); } /* if(glConfig.fragmentProgramAvailable) { ri.Printf(PRINT_ALL, "GL_MAX_TEXTURE_IMAGE_UNITS_ARB: %d\n", glConfig.maxTextureImageUnits); } */ ri.Printf(PRINT_ALL, "GL_SHADING_LANGUAGE_VERSION_ARB: %s\n", glConfig2.shadingLanguageVersion); ri.Printf(PRINT_ALL, "GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB %d\n", glConfig2.maxVertexUniforms); // ri.Printf(PRINT_ALL, "GL_MAX_VARYING_FLOATS_ARB %d\n", glConfig2.maxVaryingFloats); ri.Printf(PRINT_ALL, "GL_MAX_VERTEX_ATTRIBS_ARB %d\n", glConfig2.maxVertexAttribs); if(glConfig2.occlusionQueryAvailable) { ri.Printf(PRINT_ALL, "%d occlusion query bits\n", glConfig2.occlusionQueryBits); } if(glConfig2.drawBuffersAvailable) { ri.Printf(PRINT_ALL, "GL_MAX_DRAW_BUFFERS_ARB: %d\n", glConfig2.maxDrawBuffers); } if(glConfig2.textureAnisotropyAvailable) { ri.Printf(PRINT_ALL, "GL_TEXTURE_MAX_ANISOTROPY_EXT: %f\n", glConfig2.maxTextureAnisotropy); } if(glConfig2.framebufferObjectAvailable) { ri.Printf(PRINT_ALL, "GL_MAX_RENDERBUFFER_SIZE_EXT: %d\n", glConfig2.maxRenderbufferSize); ri.Printf(PRINT_ALL, "GL_MAX_COLOR_ATTACHMENTS_EXT: %d\n", glConfig2.maxColorAttachments); } ri.Printf(PRINT_ALL, "\nPIXELFORMAT: color(%d-bits) Z(%d-bit) stencil(%d-bits)\n", glConfig.colorBits, glConfig.depthBits, glConfig.stencilBits); ri.Printf(PRINT_ALL, "MODE: %d, %d x %d %s hz:", r_mode->integer, glConfig.vidWidth, glConfig.vidHeight, fsstrings[r_fullscreen->integer == 1]); if(glConfig.displayFrequency) { ri.Printf(PRINT_ALL, "%d\n", glConfig.displayFrequency); } else { ri.Printf(PRINT_ALL, "N/A\n"); } if(glConfig.deviceSupportsGamma) { ri.Printf(PRINT_ALL, "GAMMA: hardware w/ %d overbright bits\n", tr.overbrightBits); } else { ri.Printf(PRINT_ALL, "GAMMA: software w/ %d overbright bits\n", tr.overbrightBits); } ri.Printf(PRINT_ALL, "texturemode: %s\n", r_textureMode->string); ri.Printf(PRINT_ALL, "picmip: %d\n", r_picmip->integer); if(glConfig.driverType == GLDRV_OPENGL3) { int contextFlags, profile; ri.Printf(PRINT_ALL, S_COLOR_GREEN "Using OpenGL 3.x context\n"); // check if we have a core-profile glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &profile); if(profile == GL_CONTEXT_CORE_PROFILE_BIT) { ri.Printf(PRINT_ALL, S_COLOR_GREEN "Having a core profile\n"); } else { ri.Printf(PRINT_ALL, S_COLOR_RED "Having a compatibility profile\n"); } // check if context is forward compatible glGetIntegerv(GL_CONTEXT_FLAGS, &contextFlags); if(contextFlags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT) { ri.Printf(PRINT_ALL, S_COLOR_GREEN "Context is forward compatible\n"); } else { ri.Printf(PRINT_ALL, S_COLOR_RED "Context is NOT forward compatible\n"); } } if(glConfig.hardwareType == GLHW_ATI) { ri.Printf(PRINT_ALL, "HACK: ATI approximations\n"); } if(glConfig.textureCompression != TC_NONE) { ri.Printf(PRINT_ALL, "Using S3TC (DXTC) texture compression\n"); } if(glConfig.hardwareType == GLHW_ATI_DX10) { ri.Printf(PRINT_ALL, "Using ATI DirectX 10 hardware features\n"); } if(glConfig.hardwareType == GLHW_NV_DX10) { ri.Printf(PRINT_ALL, "Using NVIDIA DirectX 10 hardware features\n"); } if(glConfig2.vboVertexSkinningAvailable) { ri.Printf(PRINT_ALL, "Using GPU vertex skinning with max %i bones in a single pass\n", glConfig2.maxVertexSkinningBones); } if(glConfig.smpActive) { ri.Printf(PRINT_ALL, "Using dual processor acceleration\n"); } if(r_finish->integer) { ri.Printf(PRINT_ALL, "Forcing glFinish\n"); } } #if !defined(USE_D3D10) static void GLSL_restart_f(void) { // make sure the render thread is stopped R_SyncRenderThread(); GLSL_ShutdownGPUShaders(); GLSL_InitGPUShaders(); } #endif /* =============== R_Register =============== */ void R_Register(void) { //#if defined(_WIN32) // r_glCoreProfile = ri.Cvar_Get("r_glCoreProfile", "1", CVAR_INIT); //#else // most open source Linux drivers don't support OpenGL 3 r_glCoreProfile = ri.Cvar_Get("r_glCoreProfile", "0", CVAR_INIT); //#endif r_glMinMajorVersion = ri.Cvar_Get("r_glMinMajorVersion", "3", CVAR_LATCH); r_glMinMinorVersion = ri.Cvar_Get("r_glMinMinorVersion", "2", CVAR_LATCH); // // latched and archived variables // r_allowExtensions = ri.Cvar_Get( "r_allowExtensions", "1", CVAR_ARCHIVE | CVAR_LATCH ); r_ext_multitexture = ri.Cvar_Get( "r_ext_multitexture", "1", CVAR_ARCHIVE | CVAR_LATCH ); r_ext_compiled_vertex_array = ri.Cvar_Get( "r_ext_compiled_vertex_array", "1", CVAR_ARCHIVE | CVAR_LATCH); r_ext_texture_env_add = ri.Cvar_Get( "r_ext_texture_env_add", "1", CVAR_ARCHIVE | CVAR_LATCH); r_ext_texture_filter_anisotropic = ri.Cvar_Get( "r_ext_texture_filter_anisotropic", "0", CVAR_ARCHIVE | CVAR_LATCH ); r_ext_max_anisotropy = ri.Cvar_Get( "r_ext_max_anisotropy", "2", CVAR_ARCHIVE | CVAR_LATCH ); // IneQuation r_ext_multisample_samples = ri.Cvar_Get("r_ext_multisample_samples", "0", CVAR_ARCHIVE | CVAR_LATCH); // latched and archived variables r_ext_compressed_textures = ri.Cvar_Get("r_ext_compressed_textures", "1", CVAR_ARCHIVE | CVAR_LATCH); r_ext_occlusion_query = ri.Cvar_Get("r_ext_occlusion_query", "1", CVAR_CHEAT | CVAR_LATCH); r_ext_texture_non_power_of_two = ri.Cvar_Get("r_ext_texture_non_power_of_two", "1", CVAR_CHEAT | CVAR_LATCH); r_ext_draw_buffers = ri.Cvar_Get("r_ext_draw_buffers", "1", CVAR_CHEAT | CVAR_LATCH); r_ext_vertex_array_object = ri.Cvar_Get("r_ext_vertex_array_object", "1", CVAR_CHEAT | CVAR_LATCH); r_ext_half_float_pixel = ri.Cvar_Get("r_ext_half_float_pixel", "1", CVAR_CHEAT | CVAR_LATCH); r_ext_texture_float = ri.Cvar_Get("r_ext_texture_float", "1", CVAR_CHEAT | CVAR_LATCH); r_ext_stencil_wrap = ri.Cvar_Get("r_ext_stencil_wrap", "1", CVAR_CHEAT | CVAR_LATCH); r_ext_texture_filter_anisotropic = ri.Cvar_Get("r_ext_texture_filter_anisotropic", "4", CVAR_ARCHIVE | CVAR_LATCH); r_ext_stencil_two_side = ri.Cvar_Get("r_ext_stencil_two_side", "1", CVAR_CHEAT | CVAR_LATCH); r_ext_separate_stencil = ri.Cvar_Get("r_ext_separate_stencil", "1", CVAR_CHEAT | CVAR_LATCH); r_ext_depth_bounds_test = ri.Cvar_Get("r_ext_depth_bounds_test", "1", CVAR_CHEAT | CVAR_LATCH); r_ext_framebuffer_object = ri.Cvar_Get("r_ext_framebuffer_object", "1", CVAR_ARCHIVE | CVAR_LATCH); r_ext_packed_depth_stencil = ri.Cvar_Get("r_ext_packed_depth_stencil", "1", CVAR_CHEAT | CVAR_LATCH); r_ext_framebuffer_blit = ri.Cvar_Get("r_ext_framebuffer_blit", "1", CVAR_CHEAT | CVAR_LATCH); r_extx_framebuffer_mixed_formats = ri.Cvar_Get("r_extx_framebuffer_mixed_formats", "1", CVAR_ARCHIVE | CVAR_LATCH); r_ext_generate_mipmap = ri.Cvar_Get("r_ext_generate_mipmap", "1", CVAR_CHEAT | CVAR_LATCH); r_collapseStages = ri.Cvar_Get("r_collapseStages", "1", CVAR_LATCH | CVAR_CHEAT); r_picmip = ri.Cvar_Get("r_picmip", "1", CVAR_ARCHIVE | CVAR_LATCH); AssertCvarRange(r_picmip, 0, 3, qtrue); r_roundImagesDown = ri.Cvar_Get("r_roundImagesDown", "1", CVAR_ARCHIVE | CVAR_LATCH); r_colorMipLevels = ri.Cvar_Get("r_colorMipLevels", "0", CVAR_LATCH); r_colorbits = ri.Cvar_Get("r_colorbits", "0", CVAR_ARCHIVE | CVAR_LATCH); r_stereo = ri.Cvar_Get("r_stereo", "0", CVAR_ARCHIVE | CVAR_LATCH); r_stencilbits = ri.Cvar_Get("r_stencilbits", "8", CVAR_ARCHIVE | CVAR_LATCH); r_depthbits = ri.Cvar_Get("r_depthbits", "0", CVAR_ARCHIVE | CVAR_LATCH); r_ignorehwgamma = ri.Cvar_Get("r_ignorehwgamma", "1", CVAR_ARCHIVE | CVAR_LATCH); r_mode = ri.Cvar_Get("r_mode", "3", CVAR_ARCHIVE | CVAR_LATCH); r_fullscreen = ri.Cvar_Get("r_fullscreen", "0", CVAR_ARCHIVE | CVAR_LATCH); r_customwidth = ri.Cvar_Get("r_customwidth", "1600", CVAR_ARCHIVE | CVAR_LATCH); r_customheight = ri.Cvar_Get("r_customheight", "1024", CVAR_ARCHIVE | CVAR_LATCH); r_customaspect = ri.Cvar_Get("r_customaspect", "1", CVAR_ARCHIVE | CVAR_LATCH); r_simpleMipMaps = ri.Cvar_Get("r_simpleMipMaps", "0", CVAR_ARCHIVE | CVAR_LATCH); r_uiFullScreen = ri.Cvar_Get("r_uifullscreen", "0", 0); r_subdivisions = ri.Cvar_Get("r_subdivisions", "4", CVAR_ARCHIVE | CVAR_LATCH); r_deferredShading = ri.Cvar_Get("r_deferredShading", "0", CVAR_ARCHIVE | CVAR_LATCH); r_parallaxMapping = ri.Cvar_Get("r_parallaxMapping", "0", CVAR_ARCHIVE | CVAR_LATCH); r_dynamicLightCastShadows = ri.Cvar_Get("r_dynamicLightCastShadows", "1", CVAR_ARCHIVE); r_precomputedLighting = ri.Cvar_Get("r_precomputedLighting", "1", CVAR_ARCHIVE | CVAR_LATCH); r_vertexLighting = ri.Cvar_Get("r_vertexLighting", "0", CVAR_ARCHIVE | CVAR_LATCH); r_compressDiffuseMaps = ri.Cvar_Get("r_compressDiffuseMaps", "1", CVAR_ARCHIVE | CVAR_LATCH); r_compressSpecularMaps = ri.Cvar_Get("r_compressSpecularMaps", "1", CVAR_ARCHIVE | CVAR_LATCH); r_compressNormalMaps = ri.Cvar_Get("r_compressNormalMaps", "0", CVAR_ARCHIVE | CVAR_LATCH); r_heatHazeFix = ri.Cvar_Get("r_heatHazeFix", "0", CVAR_CHEAT); r_noMarksOnTrisurfs = ri.Cvar_Get("r_noMarksOnTrisurfs", "1", CVAR_CHEAT); r_texturebits = ri.Cvar_Get( "r_texturebits", "16", CVAR_ARCHIVE | CVAR_LATCH ); r_forceFog = ri.Cvar_Get("r_forceFog", "0", CVAR_CHEAT /* | CVAR_LATCH */ ); AssertCvarRange(r_forceFog, 0.0f, 1.0f, qfalse); r_wolfFog = ri.Cvar_Get("r_wolfFog", "1", CVAR_CHEAT); r_noFog = ri.Cvar_Get("r_noFog", "0", CVAR_CHEAT); #ifdef EXPERIMENTAL r_screenSpaceAmbientOcclusion = ri.Cvar_Get("r_screenSpaceAmbientOcclusion", "0", CVAR_ARCHIVE); //AssertCvarRange(r_screenSpaceAmbientOcclusion, 0, 2, qtrue); #endif #ifdef EXPERIMENTAL r_depthOfField = ri.Cvar_Get("r_depthOfField", "0", CVAR_ARCHIVE); #endif r_reflectionMapping = ri.Cvar_Get("r_reflectionMapping", "0", CVAR_CHEAT); r_highQualityNormalMapping = ri.Cvar_Get("r_highQualityNormalMapping", "0", CVAR_ARCHIVE | CVAR_LATCH); r_forceAmbient = ri.Cvar_Get("r_forceAmbient", "0.125", CVAR_ARCHIVE | CVAR_LATCH); AssertCvarRange(r_forceAmbient, 0.0f, 0.3f, qfalse); r_smp = ri.Cvar_Get("r_smp", "0", CVAR_ARCHIVE | CVAR_LATCH); // temporary latched variables that can only change over a restart r_displayRefresh = ri.Cvar_Get("r_displayRefresh", "0", CVAR_LATCH); AssertCvarRange(r_displayRefresh, 0, 200, qtrue); #if defined(COMPAT_Q3A) || defined(COMPAT_ET) r_overBrightBits = ri.Cvar_Get("r_overBrightBits", "1", CVAR_CHEAT | CVAR_LATCH); r_mapOverBrightBits = ri.Cvar_Get("r_mapOverBrightBits", "2", CVAR_CHEAT | CVAR_LATCH); #else r_overBrightBits = ri.Cvar_Get("r_overBrightBits", "0", CVAR_CHEAT | CVAR_LATCH); r_mapOverBrightBits = ri.Cvar_Get("r_mapOverBrightBits", "0", CVAR_CHEAT | CVAR_LATCH); #endif AssertCvarRange(r_overBrightBits, 0, 1, qtrue); // ydnar: limit to overbrightbits 1 (sorry 1337 players) AssertCvarRange(r_mapOverBrightBits, 0, 3, qtrue); r_intensity = ri.Cvar_Get("r_intensity", "1", CVAR_LATCH); AssertCvarRange(r_intensity, 0, 1.5, qfalse); r_singleShader = ri.Cvar_Get("r_singleShader", "0", CVAR_CHEAT | CVAR_LATCH); r_stitchCurves = ri.Cvar_Get("r_stitchCurves", "1", CVAR_CHEAT | CVAR_LATCH); r_debugShadowMaps = ri.Cvar_Get("r_debugShadowMaps", "0", CVAR_CHEAT); r_shadowMapLuminanceAlpha = ri.Cvar_Get("r_shadowMapLuminanceAlpha", "1", CVAR_ARCHIVE | CVAR_LATCH); r_shadowMapLinearFilter = ri.Cvar_Get("r_shadowMapLinearFilter", "1", CVAR_CHEAT | CVAR_LATCH); r_lightBleedReduction = ri.Cvar_Get("r_lightBleedReduction", "0", CVAR_CHEAT); r_overDarkeningFactor = ri.Cvar_Get("r_overDarkeningFactor", "30.0", CVAR_CHEAT); r_shadowMapDepthScale = ri.Cvar_Get("r_shadowMapDepthScale", "1.41", CVAR_CHEAT); r_parallelShadowSplitWeight = ri.Cvar_Get("r_parallelShadowSplitWeight", "0.9", CVAR_CHEAT); r_parallelShadowSplits = ri.Cvar_Get("r_parallelShadowSplits", "2", CVAR_CHEAT); AssertCvarRange(r_parallelShadowSplits, 0, MAX_SHADOWMAPS -1, qtrue); r_lightSpacePerspectiveWarping = ri.Cvar_Get("r_lightSpacePerspectiveWarping", "1", CVAR_CHEAT); // archived variables that can change at any time r_lodBias = ri.Cvar_Get("r_lodBias", "0", CVAR_ARCHIVE); r_flares = ri.Cvar_Get("r_flares", "0", CVAR_ARCHIVE); r_znear = ri.Cvar_Get("r_znear", "4", CVAR_CHEAT); r_zfar = ri.Cvar_Get("r_zfar", "1024", CVAR_CHEAT); r_ignoreGLErrors = ri.Cvar_Get("r_ignoreGLErrors", "1", CVAR_ARCHIVE); r_fastsky = ri.Cvar_Get("r_fastsky", "0", CVAR_ARCHIVE); r_inGameVideo = ri.Cvar_Get("r_inGameVideo", "1", CVAR_ARCHIVE); r_drawSun = ri.Cvar_Get("r_drawSun", "0", CVAR_ARCHIVE); r_finish = ri.Cvar_Get("r_finish", "0", CVAR_CHEAT); r_textureMode = ri.Cvar_Get("r_textureMode", "GL_LINEAR_MIPMAP_NEAREST", CVAR_ARCHIVE); r_swapInterval = ri.Cvar_Get("r_swapInterval", "0", CVAR_ARCHIVE); r_gamma = ri.Cvar_Get("r_gamma", "1", CVAR_ARCHIVE); r_facePlaneCull = ri.Cvar_Get("r_facePlaneCull", "1", CVAR_ARCHIVE); r_railWidth = ri.Cvar_Get("r_railWidth", "96", CVAR_ARCHIVE); r_railCoreWidth = ri.Cvar_Get("r_railCoreWidth", "16", CVAR_ARCHIVE); r_railSegmentLength = ri.Cvar_Get("r_railSegmentLength", "32", CVAR_ARCHIVE); r_ambientScale = ri.Cvar_Get("r_ambientScale", "0.6", CVAR_CHEAT); r_lightScale = ri.Cvar_Get("r_lightScale", "2", CVAR_CHEAT); r_vboFaces = ri.Cvar_Get("r_vboFaces", "1", CVAR_CHEAT); r_vboCurves = ri.Cvar_Get("r_vboCurves", "1", CVAR_CHEAT); r_vboTriangles = ri.Cvar_Get("r_vboTriangles", "1", CVAR_CHEAT); r_vboShadows = ri.Cvar_Get("r_vboShadows", "1", CVAR_CHEAT); r_vboLighting = ri.Cvar_Get("r_vboLighting", "1", CVAR_CHEAT); r_vboModels = ri.Cvar_Get("r_vboModels", "1", CVAR_CHEAT); r_vboOptimizeVertices = ri.Cvar_Get("r_vboOptimizeVertices", "1", CVAR_CHEAT | CVAR_LATCH); r_vboVertexSkinning = ri.Cvar_Get("r_vboVertexSkinning", "1", CVAR_ARCHIVE | CVAR_LATCH); r_vboDeformVertexes = ri.Cvar_Get("r_vboDeformVertexes", "0", CVAR_ARCHIVE | CVAR_LATCH); r_vboSmoothNormals = ri.Cvar_Get("r_vboSmoothNormals", "1", CVAR_ARCHIVE | CVAR_LATCH); #if defined(USE_BSP_CLUSTERSURFACE_MERGING) r_mergeClusterSurfaces = ri.Cvar_Get("r_mergeClusterSurfaces", "0", CVAR_CHEAT); r_mergeClusterFaces = ri.Cvar_Get("r_mergeClusterFaces", "1", CVAR_CHEAT); r_mergeClusterCurves = ri.Cvar_Get("r_mergeClusterCurves", "1", CVAR_CHEAT); r_mergeClusterTriangles = ri.Cvar_Get("r_mergeClusterTriangles", "1", CVAR_CHEAT); #endif r_dynamicBspOcclusionCulling = ri.Cvar_Get("r_dynamicBspOcclusionCulling", "0", CVAR_ARCHIVE); r_dynamicEntityOcclusionCulling = ri.Cvar_Get("r_dynamicEntityOcclusionCulling", "0", CVAR_CHEAT); r_dynamicLightOcclusionCulling = ri.Cvar_Get("r_dynamicLightOcclusionCulling", "0", CVAR_CHEAT); r_chcMaxPrevInvisNodesBatchSize = ri.Cvar_Get("r_chcMaxPrevInvisNodesBatchSize", "50", CVAR_CHEAT); r_chcMaxVisibleFrames = ri.Cvar_Get("r_chcMaxVisibleFrames", "10", CVAR_CHEAT); r_chcVisibilityThreshold = ri.Cvar_Get("r_chcVisibilityThreshold", "20", CVAR_CHEAT); r_chcIgnoreLeaves = ri.Cvar_Get("r_chcIgnoreLeaves", "0", CVAR_CHEAT); r_hdrRendering = ri.Cvar_Get("r_hdrRendering", "0", CVAR_ARCHIVE | CVAR_LATCH); // HACK turn off HDR for development if(r_deferredShading->integer) { AssertCvarRange(r_hdrRendering, 0, 0, qtrue); } r_hdrMinLuminance = ri.Cvar_Get("r_hdrMinLuminance", "0.18", CVAR_CHEAT); r_hdrMaxLuminance = ri.Cvar_Get("r_hdrMaxLuminance", "3000", CVAR_CHEAT); r_hdrKey = ri.Cvar_Get("r_hdrKey", "0.28", CVAR_CHEAT); r_hdrContrastThreshold = ri.Cvar_Get("r_hdrContrastThreshold", "1.3", CVAR_CHEAT); r_hdrContrastOffset = ri.Cvar_Get("r_hdrContrastOffset", "3.0", CVAR_CHEAT); r_hdrLightmap = ri.Cvar_Get("r_hdrLightmap", "1", CVAR_CHEAT | CVAR_LATCH); r_hdrLightmapExposure = ri.Cvar_Get("r_hdrLightmapExposure", "1.0", CVAR_CHEAT | CVAR_LATCH); r_hdrLightmapGamma = ri.Cvar_Get("r_hdrLightmapGamma", "1.7", CVAR_CHEAT | CVAR_LATCH); r_hdrLightmapCompensate = ri.Cvar_Get("r_hdrLightmapCompensate", "1.0", CVAR_CHEAT | CVAR_LATCH); r_hdrToneMappingOperator = ri.Cvar_Get("r_hdrToneMappingOperator", "1", CVAR_CHEAT); r_hdrGamma = ri.Cvar_Get("r_hdrGamma", "1.1", CVAR_CHEAT); r_hdrDebug = ri.Cvar_Get("r_hdrDebug", "0", CVAR_CHEAT); r_evsmPostProcess = ri.Cvar_Get("r_evsmPostProcess", "0", CVAR_ARCHIVE | CVAR_LATCH); r_printShaders = ri.Cvar_Get("r_printShaders", "0", CVAR_ARCHIVE); r_bloom = ri.Cvar_Get("r_bloom", "0", CVAR_ARCHIVE); r_bloomBlur = ri.Cvar_Get("r_bloomBlur", "5.0", CVAR_CHEAT); r_bloomPasses = ri.Cvar_Get("r_bloomPasses", "2", CVAR_CHEAT); r_rotoscope = ri.Cvar_Get("r_rotoscope", "0", CVAR_ARCHIVE); r_cameraPostFX = ri.Cvar_Get("r_cameraPostFX", "0", CVAR_ARCHIVE); r_cameraVignette = ri.Cvar_Get("r_cameraVignette", "1", CVAR_ARCHIVE); r_cameraFilmGrain = ri.Cvar_Get("r_cameraFilmGrain", "1", CVAR_ARCHIVE); r_cameraFilmGrainScale = ri.Cvar_Get("r_cameraFilmGrainScale", "3", CVAR_ARCHIVE); // temporary variables that can change at any time r_showImages = ri.Cvar_Get("r_showImages", "0", CVAR_TEMP); r_debugLight = ri.Cvar_Get("r_debuglight", "0", CVAR_TEMP); r_debugSort = ri.Cvar_Get("r_debugSort", "0", CVAR_CHEAT); r_nocurves = ri.Cvar_Get("r_nocurves", "0", CVAR_CHEAT); r_nobatching = ri.Cvar_Get("r_nobatching", "0", CVAR_CHEAT); r_noLightScissors = ri.Cvar_Get("r_noLightScissors", "0", CVAR_CHEAT); r_noLightVisCull = ri.Cvar_Get("r_noLightVisCull", "0", CVAR_CHEAT); r_noInteractionSort = ri.Cvar_Get("r_noInteractionSort", "0", CVAR_CHEAT); r_dynamicLight = ri.Cvar_Get("r_dynamicLight", "1", CVAR_ARCHIVE); r_staticLight = ri.Cvar_Get("r_staticLight", "1", CVAR_CHEAT); r_drawworld = ri.Cvar_Get("r_drawworld", "1", CVAR_CHEAT); r_portalOnly = ri.Cvar_Get("r_portalOnly", "0", CVAR_CHEAT); r_portalSky = ri.Cvar_Get("cg_skybox", "1", 0); r_flareSize = ri.Cvar_Get("r_flareSize", "40", CVAR_CHEAT); r_flareFade = ri.Cvar_Get("r_flareFade", "7", CVAR_CHEAT); r_showSmp = ri.Cvar_Get("r_showSmp", "0", CVAR_CHEAT); r_skipBackEnd = ri.Cvar_Get("r_skipBackEnd", "0", CVAR_CHEAT); r_skipLightBuffer = ri.Cvar_Get("r_skipLightBuffer", "0", CVAR_CHEAT); r_measureOverdraw = ri.Cvar_Get("r_measureOverdraw", "0", CVAR_CHEAT); r_lodScale = ri.Cvar_Get("r_lodScale", "5", CVAR_CHEAT); r_lodTest = ri.Cvar_Get("r_lodTest", "0.5", CVAR_CHEAT); r_norefresh = ri.Cvar_Get("r_norefresh", "0", CVAR_CHEAT); r_drawentities = ri.Cvar_Get("r_drawentities", "1", CVAR_CHEAT); r_drawpolies = ri.Cvar_Get("r_drawpolies", "1", CVAR_CHEAT); r_ignore = ri.Cvar_Get("r_ignore", "1", CVAR_CHEAT); r_nocull = ri.Cvar_Get("r_nocull", "0", CVAR_CHEAT); r_novis = ri.Cvar_Get("r_novis", "0", CVAR_CHEAT); r_showcluster = ri.Cvar_Get("r_showcluster", "0", CVAR_CHEAT); r_speeds = ri.Cvar_Get("r_speeds", "0", 0); r_verbose = ri.Cvar_Get("r_verbose", "0", CVAR_CHEAT); r_logFile = ri.Cvar_Get("r_logFile", "0", CVAR_CHEAT); r_debugSurface = ri.Cvar_Get("r_debugSurface", "0", CVAR_CHEAT); r_nobind = ri.Cvar_Get("r_nobind", "0", CVAR_CHEAT); r_clear = ri.Cvar_Get("r_clear", "1", CVAR_CHEAT); r_offsetFactor = ri.Cvar_Get("r_offsetFactor", "-1", CVAR_CHEAT); r_offsetUnits = ri.Cvar_Get("r_offsetUnits", "-2", CVAR_CHEAT); r_forceSpecular = ri.Cvar_Get("r_forceSpecular", "0", CVAR_CHEAT); r_specularExponent = ri.Cvar_Get("r_specularExponent", "16", CVAR_CHEAT); r_specularExponent2 = ri.Cvar_Get("r_specularExponent2", "3", CVAR_CHEAT); r_specularScale = ri.Cvar_Get("r_specularScale", "1.4", CVAR_CHEAT); r_normalScale = ri.Cvar_Get("r_normalScale", "1.1", CVAR_CHEAT); r_normalMapping = ri.Cvar_Get("r_normalMapping", "1", CVAR_ARCHIVE | CVAR_LATCH); r_parallaxDepthScale = ri.Cvar_Get("r_parallaxDepthScale", "0.03", CVAR_CHEAT); r_wrapAroundLighting = ri.Cvar_Get("r_wrapAroundLighting", "0.7", CVAR_CHEAT); r_halfLambertLighting = ri.Cvar_Get("r_halfLambertLighting", "1", CVAR_CHEAT); r_rimLighting = ri.Cvar_Get("r_rimLighting", "1", CVAR_ARCHIVE | CVAR_LATCH); r_rimExponent = ri.Cvar_Get("r_rimExponent", "3", CVAR_CHEAT); AssertCvarRange(r_rimExponent, 0.5, 8.0, qfalse); r_drawBuffer = ri.Cvar_Get("r_drawBuffer", "GL_BACK", CVAR_CHEAT); r_lockpvs = ri.Cvar_Get("r_lockpvs", "0", CVAR_CHEAT); r_noportals = ri.Cvar_Get("r_noportals", "0", CVAR_CHEAT); r_shadows = ri.Cvar_Get("cg_shadows", "1", CVAR_ARCHIVE | CVAR_LATCH); AssertCvarRange(r_shadows, 0, SHADOWING_EVSM32, qtrue); r_softShadows = ri.Cvar_Get("r_softShadows", "0", CVAR_ARCHIVE); AssertCvarRange(r_softShadows, 0, 6, qtrue); r_shadowBlur = ri.Cvar_Get("r_shadowBlur", "2", CVAR_ARCHIVE); r_shadowMapQuality = ri.Cvar_Get("r_shadowMapQuality", "3", CVAR_ARCHIVE | CVAR_LATCH); AssertCvarRange(r_shadowMapQuality, 0, 4, qtrue); r_shadowMapSizeUltra = ri.Cvar_Get("r_shadowMapSizeUltra", "1024", CVAR_ARCHIVE | CVAR_LATCH); AssertCvarRange(r_shadowMapSizeUltra, 32, 2048, qtrue); r_shadowMapSizeVeryHigh = ri.Cvar_Get("r_shadowMapSizeVeryHigh", "512", CVAR_ARCHIVE | CVAR_LATCH); AssertCvarRange(r_shadowMapSizeVeryHigh, 32, 2048, qtrue); r_shadowMapSizeHigh = ri.Cvar_Get("r_shadowMapSizeHigh", "256", CVAR_ARCHIVE | CVAR_LATCH); AssertCvarRange(r_shadowMapSizeHigh, 32, 2048, qtrue); r_shadowMapSizeMedium = ri.Cvar_Get("r_shadowMapSizeMedium", "128", CVAR_ARCHIVE | CVAR_LATCH); AssertCvarRange(r_shadowMapSizeMedium, 32, 2048, qtrue); r_shadowMapSizeLow = ri.Cvar_Get("r_shadowMapSizeLow", "64", CVAR_ARCHIVE | CVAR_LATCH); AssertCvarRange(r_shadowMapSizeLow, 32, 2048, qtrue); shadowMapResolutions[0] = r_shadowMapSizeUltra->integer; shadowMapResolutions[1] = r_shadowMapSizeVeryHigh->integer; shadowMapResolutions[2] = r_shadowMapSizeHigh->integer; shadowMapResolutions[3] = r_shadowMapSizeMedium->integer; shadowMapResolutions[4] = r_shadowMapSizeLow->integer; r_shadowMapSizeSunUltra = ri.Cvar_Get("r_shadowMapSizeSunUltra", "1024", CVAR_ARCHIVE | CVAR_LATCH); AssertCvarRange(r_shadowMapSizeSunUltra, 32, 2048, qtrue); r_shadowMapSizeSunVeryHigh = ri.Cvar_Get("r_shadowMapSizeSunVeryHigh", "1024", CVAR_ARCHIVE | CVAR_LATCH); AssertCvarRange(r_shadowMapSizeSunVeryHigh, 512, 2048, qtrue); r_shadowMapSizeSunHigh = ri.Cvar_Get("r_shadowMapSizeSunHigh", "1024", CVAR_ARCHIVE | CVAR_LATCH); AssertCvarRange(r_shadowMapSizeSunHigh, 512, 2048, qtrue); r_shadowMapSizeSunMedium = ri.Cvar_Get("r_shadowMapSizeSunMedium", "1024", CVAR_ARCHIVE | CVAR_LATCH); AssertCvarRange(r_shadowMapSizeSunMedium, 512, 2048, qtrue); r_shadowMapSizeSunLow = ri.Cvar_Get("r_shadowMapSizeSunLow", "1024", CVAR_ARCHIVE | CVAR_LATCH); AssertCvarRange(r_shadowMapSizeSunLow, 512, 2048, qtrue); sunShadowMapResolutions[0] = r_shadowMapSizeSunUltra->integer; sunShadowMapResolutions[1] = r_shadowMapSizeSunVeryHigh->integer; sunShadowMapResolutions[2] = r_shadowMapSizeSunHigh->integer; sunShadowMapResolutions[3] = r_shadowMapSizeSunMedium->integer; sunShadowMapResolutions[4] = r_shadowMapSizeSunLow->integer; r_shadowOffsetFactor = ri.Cvar_Get("r_shadowOffsetFactor", "0", CVAR_CHEAT); r_shadowOffsetUnits = ri.Cvar_Get("r_shadowOffsetUnits", "0", CVAR_CHEAT); r_shadowLodBias = ri.Cvar_Get("r_shadowLodBias", "0", CVAR_CHEAT); r_shadowLodScale = ri.Cvar_Get("r_shadowLodScale", "0.8", CVAR_CHEAT); r_noShadowPyramids = ri.Cvar_Get("r_noShadowPyramids", "0", CVAR_CHEAT); r_cullShadowPyramidFaces = ri.Cvar_Get("r_cullShadowPyramidFaces", "0", CVAR_CHEAT); r_cullShadowPyramidCurves = ri.Cvar_Get("r_cullShadowPyramidCurves", "1", CVAR_CHEAT); r_cullShadowPyramidTriangles = ri.Cvar_Get("r_cullShadowPyramidTriangles", "1", CVAR_CHEAT); r_noShadowFrustums = ri.Cvar_Get("r_noShadowFrustums", "0", CVAR_CHEAT); r_noLightFrustums = ri.Cvar_Get("r_noLightFrustums", "0", CVAR_CHEAT); r_maxPolys = ri.Cvar_Get("r_maxpolys", "10000", 0); // 600 in vanilla Q3A AssertCvarRange(r_maxPolys, 600, 30000, qtrue); r_maxPolyVerts = ri.Cvar_Get("r_maxpolyverts", "100000", 0); // 3000 in vanilla Q3A AssertCvarRange(r_maxPolyVerts, 3000, 200000, qtrue); r_showTris = ri.Cvar_Get("r_showTris", "0", CVAR_CHEAT); r_showSky = ri.Cvar_Get("r_showSky", "0", CVAR_CHEAT); r_showShadowVolumes = ri.Cvar_Get("r_showShadowVolumes", "0", CVAR_CHEAT); r_showShadowLod = ri.Cvar_Get("r_showShadowLod", "0", CVAR_CHEAT); r_showShadowMaps = ri.Cvar_Get("r_showShadowMaps", "0", CVAR_CHEAT); r_showSkeleton = ri.Cvar_Get("r_showSkeleton", "0", CVAR_CHEAT); r_showEntityTransforms = ri.Cvar_Get("r_showEntityTransforms", "0", CVAR_CHEAT); r_showLightTransforms = ri.Cvar_Get("r_showLightTransforms", "0", CVAR_CHEAT); r_showLightInteractions = ri.Cvar_Get("r_showLightInteractions", "0", CVAR_CHEAT); r_showLightScissors = ri.Cvar_Get("r_showLightScissors", "0", CVAR_CHEAT); r_showLightBatches = ri.Cvar_Get("r_showLightBatches", "0", CVAR_CHEAT); r_showLightGrid = ri.Cvar_Get("r_showLightGrid", "0", CVAR_CHEAT); r_showOcclusionQueries = ri.Cvar_Get("r_showOcclusionQueries", "0", CVAR_CHEAT); r_showBatches = ri.Cvar_Get("r_showBatches", "0", CVAR_CHEAT); r_showLightMaps = ri.Cvar_Get("r_showLightMaps", "0", CVAR_CHEAT); r_showDeluxeMaps = ri.Cvar_Get("r_showDeluxeMaps", "0", CVAR_CHEAT); r_showAreaPortals = ri.Cvar_Get("r_showAreaPortals", "0", CVAR_CHEAT); r_showCubeProbes = ri.Cvar_Get("r_showCubeProbes", "0", CVAR_CHEAT); r_showBspNodes = ri.Cvar_Get("r_showBspNodes", "0", CVAR_CHEAT); r_showParallelShadowSplits = ri.Cvar_Get("r_showParallelShadowSplits", "0", CVAR_CHEAT); r_showDecalProjectors = ri.Cvar_Get("r_showDecalProjectors", "0", CVAR_CHEAT); r_showDeferredDiffuse = ri.Cvar_Get("r_showDeferredDiffuse", "0", CVAR_CHEAT); r_showDeferredNormal = ri.Cvar_Get("r_showDeferredNormal", "0", CVAR_CHEAT); r_showDeferredSpecular = ri.Cvar_Get("r_showDeferredSpecular", "0", CVAR_CHEAT); r_showDeferredPosition = ri.Cvar_Get("r_showDeferredPosition", "0", CVAR_CHEAT); r_showDeferredRender = ri.Cvar_Get("r_showDeferredRender", "0", CVAR_CHEAT); r_showDeferredLight = ri.Cvar_Get("r_showDeferredLight", "0", CVAR_CHEAT); // make sure all the commands added here are also removed in R_Shutdown ri.Cmd_AddCommand("imagelist", R_ImageList_f); ri.Cmd_AddCommand("shaderlist", R_ShaderList_f); ri.Cmd_AddCommand("shaderexp", R_ShaderExp_f); ri.Cmd_AddCommand("skinlist", R_SkinList_f); ri.Cmd_AddCommand("modellist", R_Modellist_f); ri.Cmd_AddCommand("modelist", R_ModeList_f); #if defined(USE_REFENTITY_ANIMATIONSYSTEM) ri.Cmd_AddCommand("animationlist", R_AnimationList_f); #endif ri.Cmd_AddCommand("fbolist", R_FBOList_f); ri.Cmd_AddCommand("vbolist", R_VBOList_f); ri.Cmd_AddCommand("screenshot", R_ScreenShot_f); ri.Cmd_AddCommand("screenshotJPEG", R_ScreenShotJPEG_f); ri.Cmd_AddCommand("screenshotPNG", R_ScreenShotPNG_f); ri.Cmd_AddCommand("gfxinfo", GfxInfo_f); // ri.Cmd_AddCommand("generatemtr", R_GenerateMaterialFile_f); ri.Cmd_AddCommand("buildcubemaps", R_BuildCubeMaps); #if !defined(USE_D3D10) ri.Cmd_AddCommand("glsl_restart", GLSL_restart_f); #endif } /* =============== R_Init =============== */ void R_Init(void) { int err; int i; ri.Printf(PRINT_ALL, "----- R_Init -----\n"); // RB: Wolf's q_shared.c requires this #if defined(COMPAT_ET) Swap_Init(); #endif // clear all our internal state Com_Memset(&tr, 0, sizeof(tr)); Com_Memset(&backEnd, 0, sizeof(backEnd)); Com_Memset(&tess, 0, sizeof(tess)); if((intptr_t) tess.xyz & 15) Com_Printf("WARNING: tess.xyz not 16 byte aligned\n"); // init function tables for(i = 0; i < FUNCTABLE_SIZE; i++) { tr.sinTable[i] = sin(DEG2RAD(i * 360.0f / ((float)(FUNCTABLE_SIZE - 1)))); tr.squareTable[i] = (i < FUNCTABLE_SIZE / 2) ? 1.0f : -1.0f; tr.sawToothTable[i] = (float)i / FUNCTABLE_SIZE; tr.inverseSawToothTable[i] = 1.0f - tr.sawToothTable[i]; if(i < FUNCTABLE_SIZE / 2) { if(i < FUNCTABLE_SIZE / 4) { tr.triangleTable[i] = (float)i / (FUNCTABLE_SIZE / 4); } else { tr.triangleTable[i] = 1.0f - tr.triangleTable[i - FUNCTABLE_SIZE / 4]; } } else { tr.triangleTable[i] = -tr.triangleTable[i - FUNCTABLE_SIZE / 2]; } } R_InitFogTable(); R_NoiseInit(); R_Register(); backEndData[0] = (backEndData_t *) ri.Hunk_Alloc(sizeof(*backEndData[0]), h_low); backEndData[0]->polys = (srfPoly_t *) ri.Hunk_Alloc(r_maxPolys->integer * sizeof(srfPoly_t), h_low); backEndData[0]->polyVerts = (polyVert_t *) ri.Hunk_Alloc(r_maxPolyVerts->integer * sizeof(polyVert_t), h_low); backEndData[0]->polybuffers = (srfPolyBuffer_t *) ri.Hunk_Alloc(r_maxPolys->integer * sizeof(srfPolyBuffer_t), h_low); if(r_smp->integer) { backEndData[1] = (backEndData_t *) ri.Hunk_Alloc(sizeof(*backEndData[1]), h_low); backEndData[1]->polys = (srfPoly_t *) ri.Hunk_Alloc(r_maxPolys->integer * sizeof(srfPoly_t), h_low); backEndData[1]->polyVerts = (polyVert_t *) ri.Hunk_Alloc(r_maxPolyVerts->integer * sizeof(polyVert_t), h_low); backEndData[1]->polybuffers = (srfPolyBuffer_t *) ri.Hunk_Alloc(r_maxPolys->integer * sizeof(srfPolyBuffer_t), h_low); } else { backEndData[1] = NULL; } R_ToggleSmpFrame(); #if defined(USE_D3D10) if(glConfig.vidWidth == 0) { DXGI_SWAP_CHAIN_DESC sd; SDL_SysWMinfo info; HRESULT hr = S_OK; RECT rc; ID3D10Texture2D* backBuffer; UINT createDeviceFlags = 0; int i; D3D10_DRIVER_TYPE driverTypes[] = { D3D10_DRIVER_TYPE_HARDWARE, D3D10_DRIVER_TYPE_REFERENCE, }; UINT numDriverTypes = sizeof(driverTypes) / sizeof(driverTypes[0]); GLimp_Init(); ri.Printf(PRINT_ALL, "------- D3D10 Initialization -------\n"); SDL_VERSION(&info.version); if(!SDL_GetWMInfo(&info)) { ri.Error(ERR_FATAL, "R_Init: Failed to obtain HWND from SDL (InputRegistry)"); } //GetClientRect(info.window, &rc); //UINT width = rc.right - rc.left; //UINT height = rc.bottom - rc.top; #ifdef _DEBUG createDeviceFlags |= D3D10_CREATE_DEVICE_DEBUG; #endif ZeroMemory(&sd, sizeof(sd)); sd.BufferCount = 1; sd.BufferDesc.Width = glConfig.vidWidth; sd.BufferDesc.Height = glConfig.vidHeight; sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.BufferDesc.RefreshRate.Numerator = 60; sd.BufferDesc.RefreshRate.Denominator = 1; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.OutputWindow = info.window; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.Windowed = TRUE; #if 1 // Look for 'NVIDIA PerfHUD' adapter // If it is present, override default settings IDXGIFactory *pDXGIFactory; hr = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&pDXGIFactory); // Search for a PerfHUD adapter. UINT nAdapter = 0; IDXGIAdapter* adapter = NULL; IDXGIAdapter* selectedAdapter = NULL; dx.driverType = D3D10_DRIVER_TYPE_HARDWARE; ri.Printf(PRINT_ALL, "Looking for PerfHUD..."); bool gotPerfHUD = false; while (pDXGIFactory->EnumAdapters(nAdapter, &adapter) != DXGI_ERROR_NOT_FOUND) { if(adapter) { DXGI_ADAPTER_DESC adaptDesc; if(SUCCEEDED(adapter->GetDesc(&adaptDesc))) { const bool isPerfHUD = wcscmp(adaptDesc.Description, L"NVIDIA PerfHUD") == 0; // Select the first adapter in normal circumstances or the PerfHUD one if it exists. if(nAdapter == 0 || isPerfHUD) selectedAdapter = adapter; if(isPerfHUD) { gotPerfHUD = true; ri.Printf(PRINT_ALL, "found\n"); dx.driverType = D3D10_DRIVER_TYPE_REFERENCE; break; } } } ++nAdapter; } if(!gotPerfHUD) ri.Printf(PRINT_ALL, "failed\n"); hr = D3D10CreateDeviceAndSwapChain( selectedAdapter, dx.driverType, NULL, createDeviceFlags, D3D10_SDK_VERSION, &sd, &dx.swapChain, &dx.d3dDevice); if(FAILED(hr)) #endif { ri.Printf(PRINT_ALL, "R_Init: Failed to find PerfHUD"); for(i = 0; i < numDriverTypes; i++ ) { dx.driverType = driverTypes[i]; hr = D3D10CreateDeviceAndSwapChain( NULL, dx.driverType, NULL, createDeviceFlags, D3D10_SDK_VERSION, &sd, &dx.swapChain, &dx.d3dDevice); if(SUCCEEDED(hr)) break; } if(FAILED(hr)) { ri.Error(ERR_FATAL, "R_Init: Failed to create a D3D10 device and swap chain"); } } // create a render target view hr = dx.swapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), (LPVOID*) &backBuffer); if(FAILED(hr)) ri.Error(ERR_FATAL, "R_Init: Failed to get a D3D10 back buffer"); hr = dx.d3dDevice->CreateRenderTargetView(backBuffer, NULL, &dx.renderTargetView); backBuffer->Release(); if(FAILED(hr)) ri.Error(ERR_FATAL, "R_Init: Failed to create a D3D10 render target view"); dx.d3dDevice->OMSetRenderTargets(1, &dx.renderTargetView, NULL); // TODO move this to renderer backend // setup the viewport D3D10_VIEWPORT vp; vp.Width = glConfig.vidWidth; vp.Height = glConfig.vidHeight; vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; vp.TopLeftX = 0; vp.TopLeftY = 0; dx.d3dDevice->RSSetViewports(1, &vp); #if 0 // create the effect DWORD dwShaderFlags = D3D10_SHADER_ENABLE_STRICTNESS; #if defined( DEBUG ) || defined( _DEBUG ) // Set the D3D10_SHADER_DEBUG flag to embed debug information in the shaders. // Setting this flag improves the shader debugging experience, but still allows // the shaders to be optimized and to run exactly the way they will run in // the release configuration of this program. dwShaderFlags |= D3D10_SHADER_DEBUG; #endif byte *effectBuffer; int effectBufferLen; effectBufferLen = ri.FS_ReadFile("shaders/Generic.fx", (void**) &effectBuffer); if(effectBufferLen == 0) { ri.Error(ERR_FATAL, "The FX file cannot be located. Please run this executable from the directory that contains the FX file."); } hr = D3DX10CreateEffectFromMemory(effectBuffer, effectBufferLen, "shaders/Generic.fx", NULL, NULL, "fx_4_0", dwShaderFlags, 0, dx.d3dDevice, NULL, NULL, &dx.genericEffect, NULL, NULL); if(FAILED(hr)) { ri.Error(ERR_FATAL, "D3DX10CreateEffect failed %i", hr); } // obtain the technique dx.genericTechnique = dx.genericEffect->GetTechniqueByName("Render"); // define the input layout D3D10_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; UINT numElements = sizeof(layout) / sizeof(layout[0]); // create the input layout D3D10_PASS_DESC PassDesc; dx.genericTechnique->GetPassByIndex(0)->GetDesc(&PassDesc); hr = dx.d3dDevice->CreateInputLayout( layout, numElements, PassDesc.pIAInputSignature, PassDesc.IAInputSignatureSize, &dx.vertexLayout ); if(FAILED(hr)) ri.Error(ERR_FATAL, "R_Init: Failed to create a D3D10 input layout"); // set the input layout dx.d3dDevice->IASetInputLayout(dx.vertexLayout); // create vertex buffer D3DXVECTOR3 vertices[] = { D3DXVECTOR3( 0.0f, 0.5f, 0.5f ), D3DXVECTOR3( 0.5f, -0.5f, 0.5f ), D3DXVECTOR3( -0.5f, -0.5f, 0.5f ), }; D3D10_BUFFER_DESC bd; bd.Usage = D3D10_USAGE_DEFAULT; bd.ByteWidth = sizeof(D3DXVECTOR3) * 3; bd.BindFlags = D3D10_BIND_VERTEX_BUFFER; bd.CPUAccessFlags = 0; bd.MiscFlags = 0; D3D10_SUBRESOURCE_DATA InitData; InitData.pSysMem = vertices; hr = dx.d3dDevice->CreateBuffer(&bd, &InitData, &dx.vertexBuffer); if(FAILED(hr)) ri.Error(ERR_FATAL, "R_Init: Failed to create a D3D10 input layout"); // set vertex buffer UINT stride = sizeof(D3DXVECTOR3); UINT offset = 0; dx.d3dDevice->IASetVertexBuffers(0, 1, &dx.vertexBuffer, &stride, &offset); // set primitive topology dx.d3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); #endif ri.Printf(PRINT_ALL, "------------------------------------\n"); } // init command buffers and SMP R_InitCommandBuffers(); // print info GfxInfo_f(); // set default state //D3D10_SetDefaultState(); #else InitOpenGL(); #if !defined(GLSL_COMPILE_STARTUP_ONLY) GLSL_InitGPUShaders(); #endif #endif R_InitImages(); R_InitFBOs(); if(glConfig.driverType == GLDRV_OPENGL3) { tr.vao = 0; glGenVertexArrays(1, &tr.vao); glBindVertexArray(tr.vao); } R_InitVBOs(); R_InitShaders(); R_InitSkins(); R_ModelInit(); #if defined(USE_REFENTITY_ANIMATIONSYSTEM) R_InitAnimations(); #endif R_InitFreeType(); if(glConfig2.textureAnisotropyAvailable) { AssertCvarRange(r_ext_texture_filter_anisotropic, 0, glConfig2.maxTextureAnisotropy, qfalse); } if(glConfig2.occlusionQueryBits && glConfig.driverType != GLDRV_MESA) { glGenQueriesARB(MAX_OCCLUSION_QUERIES, tr.occlusionQueryObjects); } err = glGetError(); if(err != GL_NO_ERROR) { //ri.Error(ERR_FATAL, "R_Init() - glGetError() failed = 0x%x\n", err); ri.Printf(PRINT_ALL, "glGetError() = 0x%x\n", err); } tr.smpFrame = 0; ri.Printf(PRINT_ALL, "----- finished R_Init -----\n"); } /* =============== RE_Shutdown =============== */ void RE_Shutdown(qboolean destroyWindow) { ri.Printf(PRINT_ALL, "RE_Shutdown( destroyWindow = %i )\n", destroyWindow); ri.Cmd_RemoveCommand("modellist"); ri.Cmd_RemoveCommand("screenshotPNG"); ri.Cmd_RemoveCommand("screenshotJPEG"); ri.Cmd_RemoveCommand("screenshot"); ri.Cmd_RemoveCommand("imagelist"); ri.Cmd_RemoveCommand("shaderlist"); ri.Cmd_RemoveCommand("shaderexp"); ri.Cmd_RemoveCommand("skinlist"); ri.Cmd_RemoveCommand("gfxinfo"); ri.Cmd_RemoveCommand("modelist"); ri.Cmd_RemoveCommand("shaderstate"); ri.Cmd_RemoveCommand("animationlist"); ri.Cmd_RemoveCommand("fbolist"); ri.Cmd_RemoveCommand("vbolist"); ri.Cmd_RemoveCommand("generatemtr"); ri.Cmd_RemoveCommand("buildcubemaps"); ri.Cmd_RemoveCommand("glsl_restart"); if(tr.registered) { R_SyncRenderThread(); R_ShutdownCommandBuffers(); R_ShutdownImages(); R_ShutdownVBOs(); R_ShutdownFBOs(); if(glConfig.driverType == GLDRV_OPENGL3) { glDeleteVertexArrays(1, &tr.vao); tr.vao = 0; } if(glConfig2.occlusionQueryBits && glConfig.driverType != GLDRV_MESA) { glDeleteQueriesARB(MAX_OCCLUSION_QUERIES, tr.occlusionQueryObjects); if(tr.world) { int j; bspNode_t *node; //trRefLight_t *light; for(j = 0; j < tr.world->numnodes; j++) { node = &tr.world->nodes[j]; glDeleteQueriesARB(MAX_VIEWS, node->occlusionQueryObjects); } /* for(j = 0; j < tr.world->numLights; j++) { light = &tr.world->lights[j]; glDeleteQueriesARB(MAX_VIEWS, light->occlusionQueryObjects); } */ } } #if !defined(GLSL_COMPILE_STARTUP_ONLY) GLSL_ShutdownGPUShaders(); #endif //GLimp_ShutdownRenderThread(); } R_DoneFreeType(); // shut down platform specific OpenGL stuff // Tr3B: this should be always executed if we want to avoid some GLSL problems with SMP // Update: Having the JVM running with all its threads can cause problems with an old OpenGL context. // Maybe an OpenGL driver problem. It is safer to destroy the context in that case or you will get really weird crashes when rendering stuff. // #if !defined(SMP)// && !defined(USE_JAVA) if(destroyWindow) #endif { #if defined(GLSL_COMPILE_STARTUP_ONLY) GLSL_ShutdownGPUShaders(); #endif GLimp_Shutdown(); #if defined(USE_D3D10) if(dx.d3dDevice) dx.d3dDevice->ClearState(); if(dx.renderTargetView) dx.renderTargetView->Release(); if(dx.swapChain) dx.swapChain->Release(); if(dx.d3dDevice) dx.d3dDevice->Release(); #endif } tr.registered = qfalse; } /* ============= RE_EndRegistration Touch all images to make sure they are resident ============= */ void RE_EndRegistration(void) { R_SyncRenderThread(); /* if(!Sys_LowPhysicalMemory()) { RB_ShowImages(); } */ } static void RE_PurgeCache(void) { ri.Printf(PRINT_ALL, S_COLOR_RED "TODO RE_PurgeCache\n"); /* R_PurgeShaders(9999999); R_PurgeBackupImages(9999999); R_PurgeModels(9999999); */ } int RE_GetShaderWidth(qhandle_t shader) { return 512; } int RE_GetShaderHeight(qhandle_t shader) { return 512; } /* ===================== GetRefAPI ===================== */ refexport_t* GetRefAPI(int apiVersion, refimport_t * rimp) { static refexport_t re; ri = *rimp; ri.Printf(PRINT_ALL, "GetRefAPI()\n"); Com_Memset(&re, 0, sizeof(re)); if(apiVersion != REF_API_VERSION) { ri.Printf(PRINT_ALL, "Mismatched REF_API_VERSION: expected %i, got %i\n", REF_API_VERSION, apiVersion); return NULL; } // the RE_ functions are Renderer Entry points // Q3A BEGIN re.Shutdown = RE_Shutdown; re.BeginRegistration = RE_BeginRegistration; re.RegisterModel = RE_RegisterModel; re.RegisterSkin = RE_RegisterSkin; re.RegisterShader = RE_RegisterShader; re.RegisterShaderNoMip = RE_RegisterShaderNoMip; #if !defined(COMPAT_ET) // re.RegisterShaderLightAttenuation = RE_RegisterShaderLightAttenuation; #endif re.LoadWorld = RE_LoadWorldMap; re.SetWorldVisData = RE_SetWorldVisData; re.EndRegistration = RE_EndRegistration; re.BeginFrame = RE_BeginFrame; re.EndFrame = RE_EndFrame; re.MarkFragments = R_MarkFragments; #if defined(COMPAT_ET) re.LerpTag = RE_LerpTagET; #else re.LerpTag = RE_LerpTagQ3A; #endif re.ModelBounds = R_ModelBounds; re.ClearScene = RE_ClearScene; re.AddRefEntityToScene = RE_AddRefEntityToScene; #if defined(COMPAT_ET) re.AddPolyToScene = RE_AddPolyToSceneET; re.AddPolysToScene = RE_AddPolysToScene; #else re.AddPolyToScene = RE_AddPolyToSceneQ3A; #endif #if !defined(COMPAT_ET) re.LightForPoint = R_LightForPoint; #endif #if defined(COMPAT_ET) re.AddLightToScene = RE_AddDynamicLightToSceneET; #else re.AddLightToScene = RE_AddDynamicLightToSceneQ3A; #endif re.RenderScene = RE_RenderScene; re.SetColor = RE_SetColor; re.DrawStretchPic = RE_StretchPic; re.DrawStretchRaw = RE_StretchRaw; re.UploadCinematic = RE_UploadCinematic; re.RotatedPic = RE_RotatedPic; //re.Add2dPolys = RE_2DPolyies; //re.DrawStretchPicGradient = RE_StretchPicGradient; re.RegisterFont = RE_RegisterFont; re.RemapShader = R_RemapShader; re.GetEntityToken = R_GetEntityToken; re.inPVS = R_inPVS; // Q3A END // ET BEGIN #if defined(COMPAT_ET) re.GetSkinModel = RE_GetSkinModel; re.GetShaderFromModel = RE_GetShaderFromModel; re.ProjectDecal = RE_ProjectDecal; re.ClearDecals = RE_ClearDecals; re.DrawDebugPolygon = R_DebugPolygon; re.DrawDebugText = R_DebugText; re.SaveViewParms = RE_SaveViewParms; re.RestoreViewParms = RE_RestoreViewParms; re.AddCoronaToScene = RE_AddCoronaToScene; re.AddPolyBufferToScene = RE_AddPolyBufferToScene; re.SetFog = RE_SetFog; re.SetGlobalFog = RE_SetGlobalFog; re.purgeCache = RE_PurgeCache; re.LoadDynamicShader = RE_LoadDynamicShader; re.GetTextureId = RE_GetTextureId; re.RenderToTexture = RE_RenderToTexture; re.Finish = RE_Finish; #endif // ET END // XreaL BEGIN re.TakeVideoFrame = RE_TakeVideoFrame; #if !defined(COMPAT_ET) // re.TakeScreenshotPNG = RB_TakeScreenshotPNG; #endif #if defined(USE_REFLIGHT) re.RegisterShaderLightAttenuation = RE_RegisterShaderLightAttenuation; re.AddRefLightToScene = RE_AddRefLightToScene; #endif #if defined(USE_REFENTITY_ANIMATIONSYSTEM) re.RegisterAnimation = RE_RegisterAnimation; re.CheckSkeleton = RE_CheckSkeleton; re.BuildSkeleton = RE_BuildSkeleton; re.BlendSkeleton = RE_BlendSkeleton; re.BoneIndex = RE_BoneIndex; re.AnimNumFrames = RE_AnimNumFrames; re.AnimFrameRate = RE_AnimFrameRate; #endif // XreaL END // IneQuation re.Text_Width = RE_Text_Width; re.Text_Height = RE_Text_Height; re.Text_Paint = RE_Text_Paint; re.Text_PaintChar = RE_Text_PaintChar; // su44 re.GetShaderHeight = RE_GetShaderHeight; re.GetShaderWidth = RE_GetShaderWidth; return &re; } #if defined(__cplusplus) } #endif