openmohaa/code/renderer_gl3/tr_init.cpp

2447 lines
72 KiB
C++
Raw Normal View History

2016-03-27 11:49:47 +02:00
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2006-2011 Robert Beckebans <trebor_7@users.sourceforge.net>
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 <directory> [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