static int r_frame = 0; ///< used only by R_GetCurrentTexture
+qboolean r_loadnormalmap;
+qboolean r_loadgloss;
+qboolean r_loadfog;
+
//
// screen size info
//
cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
-cvar_t r_animcache = {CVAR_SAVE, "r_animcache", "1", "cache animation frames to save CPU usage, primarily optimizes shadows and reflections"};
-
cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
-cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
+cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
+static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
+static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
-cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
-cvar_t r_glsl_usegeneric = {CVAR_SAVE, "r_glsl_usegeneric", "1", "use shaders for rendering simple geometry (rather than conventional fixed-function rendering for this purpose)"};
cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
+cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "1", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
+
extern cvar_t v_glslgamma;
extern qboolean v_flipped_state;
}
}
}
- r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
+ r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
}
static void R_BuildWhiteCube(void)
p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
- p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
+ p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
}
if (i >= SHADERPERMUTATION_COUNT)
{
- Con_Printf("OpenGL 2.0 shaders disabled - unable to find a working shader permutation fallback on this driver (set r_glsl 1 if you want to try again)\n");
- Cvar_SetValueQuick(&r_glsl, 0);
- R_GLSL_Restart_f(); // unload shaders
- return; // no bit left to clear
+ Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
+ r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
+ qglUseProgramObjectARB(0);CHECKGLERROR
+ return; // no bit left to clear, entire mode is broken
}
}
}
void R_SetupGenericShader(qboolean usetexture)
{
- if (gl_support_fragment_shader)
+ switch(vid.renderpath)
{
- if (r_glsl.integer && r_glsl_usegeneric.integer)
- R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
- else if (r_glsl_permutation)
- {
- r_glsl_permutation = NULL;
- qglUseProgramObjectARB(0);CHECKGLERROR
- }
+ case RENDERPATH_GL20:
+ R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
+ break;
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL11:
+ break;
}
}
void R_SetupGenericTwoTextureShader(int texturemode)
{
- if (gl_support_fragment_shader)
+ switch (vid.renderpath)
{
- if (r_glsl.integer && r_glsl_usegeneric.integer)
- R_SetupShader_SetPermutation(SHADERMODE_GENERIC, SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
- else if (r_glsl_permutation)
- {
- r_glsl_permutation = NULL;
- qglUseProgramObjectARB(0);CHECKGLERROR
- }
- }
- if (!r_glsl_permutation)
- {
- if (texturemode == GL_DECAL && gl_combine.integer)
- texturemode = GL_INTERPOLATE_ARB;
- R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
+ case RENDERPATH_GL20:
+ R_SetupShader_SetPermutation(SHADERMODE_GENERIC, SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
+ break;
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL11:
+ R_Mesh_TexCombine(1, GL_DECAL, GL_DECAL, 1, 1);
+ break;
}
}
void R_SetupDepthOrShadowShader(void)
{
- if (gl_support_fragment_shader)
+ switch (vid.renderpath)
{
- if (r_glsl.integer && r_glsl_usegeneric.integer)
- R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
- else if (r_glsl_permutation)
- {
- r_glsl_permutation = NULL;
- qglUseProgramObjectARB(0);CHECKGLERROR
- }
+ case RENDERPATH_GL20:
+ R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
+ break;
+ case RENDERPATH_GL13:
+ break;
+ case RENDERPATH_GL11:
+ break;
}
}
void R_SetupShowDepthShader(void)
{
- if (gl_support_fragment_shader)
+ switch (vid.renderpath)
{
- if (r_glsl.integer && r_glsl_usegeneric.integer)
- R_SetupShader_SetPermutation(SHADERMODE_SHOWDEPTH, 0);
- else if (r_glsl_permutation)
- {
- r_glsl_permutation = NULL;
- qglUseProgramObjectARB(0);CHECKGLERROR
- }
+ case RENDERPATH_GL20:
+ R_SetupShader_SetPermutation(SHADERMODE_SHOWDEPTH, 0);
+ break;
+ case RENDERPATH_GL13:
+ break;
+ case RENDERPATH_GL11:
+ break;
}
}
skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
}
-skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int textureflags, qboolean complain, qboolean *has_alpha)
+skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
{
- // FIXME: it should be possible to disable loading various layers using
- // cvars, to prevent wasted loading time and memory usage if the user does
- // not want them
- qboolean loadnormalmap = true;
- qboolean loadgloss = true;
- qboolean loadpantsandshirt = true;
- qboolean loadglow = true;
int j;
unsigned char *pixels;
unsigned char *bumppixels;
int basepixels_height;
skinframe_t *skinframe;
- if (has_alpha)
- *has_alpha = false;
-
if (cls.state == ca_dedicated)
return NULL;
skinframe->gloss = NULL;
skinframe->glow = NULL;
skinframe->fog = NULL;
+ skinframe->hasalpha = false;
basepixels_width = image_width;
basepixels_height = image_height;
if (textureflags & TEXF_ALPHA)
{
for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
+ {
if (basepixels[j] < 255)
+ {
+ skinframe->hasalpha = true;
break;
- if (j < basepixels_width * basepixels_height * 4)
+ }
+ }
+ if (r_loadfog && skinframe->hasalpha)
{
// has transparent pixels
- if (has_alpha)
- *has_alpha = true;
pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
for (j = 0;j < image_width * image_height * 4;j += 4)
{
//Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
// _norm is the name used by tenebrae and has been adopted as standard
- if (loadnormalmap)
+ if (r_loadnormalmap)
{
if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
{
// _luma is supported for tenebrae compatibility
// (I think it's a very stupid name, but oh well)
// _glow is the preferred name
- if (loadglow && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false)) != NULL || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false)) != NULL)) {skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
- if (loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false)) != NULL) {skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
- if (loadpantsandshirt && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false)) != NULL) {skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
- if (loadpantsandshirt && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false)) != NULL) {skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
+ if ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false))) {skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
+ if (r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false))) {skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
+ if ((pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false))) {skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
+ if ((pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false))) {skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
if (basepixels)
Mem_Free(basepixels);
return skinframe;
}
-skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
-{
- return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, NULL);
-}
-
-static rtexture_t *R_SkinFrame_TextureForSkinLayer(const unsigned char *in, int width, int height, const char *name, const unsigned int *palette, int textureflags, qboolean force)
-{
- int i;
- if (!force)
- {
- for (i = 0;i < width*height;i++)
- if (((unsigned char *)&palette[in[i]])[3] > 0)
- break;
- if (i == width*height)
- return NULL;
- }
- return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
-}
-
// this is only used by .spr32 sprites, HL .spr files, HL .bsp files
skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
{
skinframe->gloss = NULL;
skinframe->glow = NULL;
skinframe->fog = NULL;
+ skinframe->hasalpha = false;
// if no data was provided, then clearly the caller wanted to get a blank skinframe
if (!skindata)
if (developer_loading.integer)
Con_Printf("loading 32bit skin \"%s\"\n", name);
- if (r_shadow_bumpscale_basetexture.value > 0)
+ if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
{
temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
temp2 = temp1 + width * height * 4;
if (textureflags & TEXF_ALPHA)
{
for (i = 3;i < width * height * 4;i += 4)
+ {
if (skindata[i] < 255)
+ {
+ skinframe->hasalpha = true;
break;
- if (i < width * height * 4)
+ }
+ }
+ if (r_loadfog && skinframe->hasalpha)
{
unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
memcpy(fogpixels, skindata, width * height * 4);
skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
{
int i;
- unsigned char *temp1, *temp2;
- unsigned int *palette;
+ int featuresmask;
skinframe_t *skinframe;
if (cls.state == ca_dedicated)
if (skinframe && skinframe->base)
return skinframe;
- palette = (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete));
-
skinframe->stain = NULL;
skinframe->merged = NULL;
skinframe->base = r_texture_notexture;
skinframe->gloss = NULL;
skinframe->glow = NULL;
skinframe->fog = NULL;
+ skinframe->hasalpha = false;
// if no data was provided, then clearly the caller wanted to get a blank skinframe
if (!skindata)
if (developer_loading.integer)
Con_Printf("loading quake skin \"%s\"\n", name);
- if (r_shadow_bumpscale_basetexture.value > 0)
+ // we actually don't upload anything until the first use, because mdl skins frequently go unused, and are almost never used in both modes (colormapped and non-colormapped)
+ skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
+ memcpy(skinframe->qpixels, skindata, width*height);
+ skinframe->qwidth = width;
+ skinframe->qheight = height;
+
+ featuresmask = 0;
+ for (i = 0;i < width * height;i++)
+ featuresmask |= palette_featureflags[skindata[i]];
+
+ skinframe->hasalpha = false;
+ skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
+ skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
+ skinframe->qgeneratemerged = true;
+ skinframe->qgeneratebase = skinframe->qhascolormapping;
+ skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
+
+ R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
+ //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
+
+ return skinframe;
+}
+
+static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
+{
+ int width;
+ int height;
+ unsigned char *skindata;
+
+ if (!skinframe->qpixels)
+ return;
+
+ if (!skinframe->qhascolormapping)
+ colormapped = false;
+
+ if (colormapped)
+ {
+ if (!skinframe->qgeneratebase)
+ return;
+ }
+ else
{
+ if (!skinframe->qgeneratemerged)
+ return;
+ }
+
+ width = skinframe->qwidth;
+ height = skinframe->qheight;
+ skindata = skinframe->qpixels;
+
+ if (skinframe->qgeneratenmap)
+ {
+ unsigned char *temp1, *temp2;
+ skinframe->qgeneratenmap = false;
temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
temp2 = temp1 + width * height * 4;
// use either a custom palette or the quake palette
skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
Mem_Free(temp1);
}
- // use either a custom palette, or the quake palette
- skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette, skinframe->textureflags, true); // all
- if (loadglowtexture)
- skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
- if (loadpantsandshirt)
+
+ if (skinframe->qgenerateglow)
{
- skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
- skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
+ skinframe->qgenerateglow = false;
+ skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
}
- if (skinframe->pants || skinframe->shirt)
- skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename), loadglowtexture ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap, skinframe->textureflags, false); // no special colors
- if (textureflags & TEXF_ALPHA)
+
+ if (colormapped)
{
- for (i = 0;i < width * height;i++)
- if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
- break;
- if (i < width * height)
- skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
+ skinframe->qgeneratebase = false;
+ skinframe->base = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
+ skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
+ skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
+ }
+ else
+ {
+ skinframe->qgeneratemerged = false;
+ skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
}
- R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
- //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
-
- return skinframe;
+ if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
+ {
+ Mem_Free(skinframe->qpixels);
+ skinframe->qpixels = NULL;
+ }
}
skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette)
skinframe->gloss = NULL;
skinframe->glow = NULL;
skinframe->fog = NULL;
+ skinframe->hasalpha = false;
// if no data was provided, then clearly the caller wanted to get a blank skinframe
if (!skindata)
if (developer_loading.integer)
Con_Printf("loading embedded 8bit image \"%s\"\n", name);
- skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, skinframe->basename, palette, skinframe->textureflags, true);
+ skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
if (textureflags & TEXF_ALPHA)
{
for (i = 0;i < width * height;i++)
- if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255)
+ {
+ if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
+ {
+ skinframe->hasalpha = true;
break;
- if (i < width * height)
- skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), alphapalette, skinframe->textureflags, true); // fog mask
+ }
+ }
+ if (r_loadfog && skinframe->hasalpha)
+ skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
}
R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
skinframe->gloss = NULL;
skinframe->glow = NULL;
skinframe->fog = NULL;
+ skinframe->hasalpha = false;
skinframe->avgcolor[0] = rand() / RAND_MAX;
skinframe->avgcolor[1] = rand() / RAND_MAX;
void gl_main_start(void)
{
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL20:
+ Cvar_SetValueQuick(&r_textureunits, vid.texunits);
+ Cvar_SetValueQuick(&gl_combine, 1);
+ Cvar_SetValueQuick(&r_glsl, 1);
+ r_loadnormalmap = true;
+ r_loadgloss = true;
+ r_loadfog = false;
+ break;
+ case RENDERPATH_GL13:
+ Cvar_SetValueQuick(&r_textureunits, vid.texunits);
+ Cvar_SetValueQuick(&gl_combine, 1);
+ Cvar_SetValueQuick(&r_glsl, 0);
+ r_loadnormalmap = false;
+ r_loadgloss = false;
+ r_loadfog = true;
+ break;
+ case RENDERPATH_GL11:
+ Cvar_SetValueQuick(&r_textureunits, vid.texunits);
+ Cvar_SetValueQuick(&gl_combine, 0);
+ Cvar_SetValueQuick(&r_glsl, 0);
+ r_loadnormalmap = false;
+ r_loadgloss = false;
+ r_loadfog = true;
+ break;
+ }
+
+ R_AnimCache_Free();
+ R_FrameData_Reset();
+
r_numqueries = 0;
r_maxqueries = 0;
memset(r_queries, 0, sizeof(r_queries));
r_main_texturepool = R_AllocTexturePool();
R_BuildBlankTextures();
R_BuildNoTexture();
- if (gl_texturecubemap)
+ if (vid.support.arb_texture_cube_map)
{
R_BuildWhiteCube();
R_BuildNormalizationCube();
extern rtexture_t *loadingscreentexture;
void gl_main_shutdown(void)
{
+ R_AnimCache_Free();
+ R_FrameData_Reset();
+
R_Main_FreeViewCache();
if (r_maxqueries)
CL_ParseEntityLump(cl.worldmodel->brush.entities);
}
R_Main_FreeViewCache();
+
+ R_FrameData_Reset();
}
void GL_Main_Init(void)
Cvar_RegisterVariable(&r_equalize_entities_minambient);
Cvar_RegisterVariable(&r_equalize_entities_by);
Cvar_RegisterVariable(&r_equalize_entities_to);
- Cvar_RegisterVariable(&r_animcache);
Cvar_RegisterVariable(&r_depthfirst);
Cvar_RegisterVariable(&r_useinfinitefarclip);
Cvar_RegisterVariable(&r_farclip_base);
Cvar_RegisterVariable(&r_fog_exp2);
Cvar_RegisterVariable(&r_drawfog);
Cvar_RegisterVariable(&r_textureunits);
+ Cvar_RegisterVariable(&gl_combine);
Cvar_RegisterVariable(&r_glsl);
Cvar_RegisterVariable(&r_glsl_deluxemapping);
Cvar_RegisterVariable(&r_glsl_offsetmapping);
Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
- Cvar_RegisterVariable(&r_glsl_usegeneric);
Cvar_RegisterVariable(&r_water);
Cvar_RegisterVariable(&r_water_resolutionmultiplier);
Cvar_RegisterVariable(&r_water_clippingplanebias);
Cvar_RegisterVariable(&r_test);
Cvar_RegisterVariable(&r_batchmode);
Cvar_RegisterVariable(&r_glsl_saturation);
+ Cvar_RegisterVariable(&r_framedatasize);
if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
Cvar_SetValue("r_fullbrights", 0);
R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
//==================================================================================
+// LordHavoc: this stores temporary data used within the same frame
+
+qboolean r_framedata_failed;
+static size_t r_framedata_size;
+static size_t r_framedata_current;
+static void *r_framedata_base;
+
+void R_FrameData_Reset(void)
+{
+ if (r_framedata_base);
+ Mem_Free(r_framedata_base);
+ r_framedata_base = NULL;
+ r_framedata_size = 0;
+ r_framedata_current = 0;
+}
+
+void R_FrameData_NewFrame(void)
+{
+ size_t wantedsize;
+ if (r_framedata_failed)
+ Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value * 1.25f);
+ wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
+ wantedsize = bound(65536, wantedsize, 128*1024*1024);
+ if (r_framedata_size < wantedsize)
+ {
+ r_framedata_size = wantedsize;
+ if (!r_framedata_base)
+ r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
+ }
+ r_framedata_current = 0;
+ r_framedata_failed = false;
+}
+
+void *R_FrameData_Alloc(size_t size)
+{
+ void *data;
+
+ // align to 16 byte boundary
+ size = (size + 15) & ~15;
+ data = r_framedata_base + r_framedata_current;
+ r_framedata_current += size;
+
+ // check overflow
+ if (r_framedata_current > r_framedata_size)
+ r_framedata_failed = true;
+
+ // return NULL on everything after a failure
+ if (r_framedata_failed)
+ return NULL;
+
+ return data;
+}
+
+void *R_FrameData_Store(size_t size, void *data)
+{
+ void *d = R_FrameData_Alloc(size);
+ if (d)
+ memcpy(d, data, size);
+ return d;
+}
+
+//==================================================================================
+
// LordHavoc: animcache written by Echon, refactored and reformatted by me
/**
float *normal3f;
float *svector3f;
float *tvector3f;
- int maxvertices;
- qboolean wantnormals;
- qboolean wanttangents;
}
r_animcache_entity_t;
void R_AnimCache_Free(void)
{
- int idx;
- for (idx=0 ; idx<r_animcachestate.maxindex ; idx++)
- {
- r_animcachestate.entity[idx].maxvertices = 0;
- Mem_Free(r_animcachestate.entity[idx].vertex3f);
- r_animcachestate.entity[idx].vertex3f = NULL;
- r_animcachestate.entity[idx].normal3f = NULL;
- r_animcachestate.entity[idx].svector3f = NULL;
- r_animcachestate.entity[idx].tvector3f = NULL;
- }
- r_animcachestate.currentindex = 0;
- r_animcachestate.maxindex = 0;
+ memset(&r_animcachestate, 0, sizeof(r_animcachestate));
}
-void R_AnimCache_ResizeEntityCache(const int cacheIdx, const int numvertices)
-{
- int arraySize;
- float *base;
- r_animcache_entity_t *cache = &r_animcachestate.entity[cacheIdx];
-
- if (cache->maxvertices >= numvertices)
- return;
-
- // Release existing memory
- if (cache->vertex3f)
- Mem_Free(cache->vertex3f);
-
- // Pad by 1024 verts
- cache->maxvertices = (numvertices + 1023) & ~1023;
- arraySize = cache->maxvertices * 3;
-
- // Allocate, even if we don't need this memory in this instance it will get ignored and potentially used later
- base = (float *)Mem_Alloc(r_main_mempool, arraySize * sizeof(float) * 4);
- r_animcachestate.entity[cacheIdx].vertex3f = base;
- r_animcachestate.entity[cacheIdx].normal3f = base + arraySize;
- r_animcachestate.entity[cacheIdx].svector3f = base + arraySize*2;
- r_animcachestate.entity[cacheIdx].tvector3f = base + arraySize*3;
-
-// Con_Printf("allocated cache for %i (%f KB)\n", cacheIdx, (arraySize*sizeof(float)*4)/1024.0f);
-}
-
-void R_AnimCache_NewFrame(void)
+void R_AnimCache_ClearCache(void)
{
int i;
+ entity_render_t *ent;
- if (r_animcache.integer && r_drawentities.integer)
- r_animcachestate.maxindex = sizeof(r_animcachestate.entity) / sizeof(r_animcachestate.entity[0]);
- else if (r_animcachestate.maxindex)
- R_AnimCache_Free();
-
+ r_animcachestate.maxindex = sizeof(r_animcachestate.entity) / sizeof(r_animcachestate.entity[0]);
r_animcachestate.currentindex = 0;
for (i = 0;i < r_refdef.scene.numentities;i++)
- r_refdef.scene.entities[i]->animcacheindex = -1;
+ {
+ ent = r_refdef.scene.entities[i];
+ ent->animcacheindex = -1;
+ }
}
qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
{
dp_model_t *model = ent->model;
r_animcache_entity_t *c;
+ int numvertices;
// see if it's already cached this frame
if (ent->animcacheindex >= 0)
{
// add normals/tangents if needed
- c = r_animcachestate.entity + ent->animcacheindex;
- if (c->wantnormals)
- wantnormals = false;
- if (c->wanttangents)
- wanttangents = false;
if (wantnormals || wanttangents)
- model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
+ {
+ c = r_animcachestate.entity + ent->animcacheindex;
+ if (c->normal3f)
+ wantnormals = false;
+ if (c->svector3f)
+ wanttangents = false;
+ if (wantnormals || wanttangents)
+ {
+ numvertices = model->surfmesh.num_vertices;
+ if (wantnormals)
+ c->normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
+ if (wanttangents)
+ {
+ c->svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
+ c->tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
+ }
+ if (!r_framedata_failed)
+ model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
+ }
+ }
}
else
{
// see if this ent is worth caching
if (r_animcachestate.maxindex <= r_animcachestate.currentindex)
return false;
- if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0))
+ if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
return false;
- // assign it a cache entry and make sure the arrays are big enough
- R_AnimCache_ResizeEntityCache(r_animcachestate.currentindex, model->surfmesh.num_vertices);
+ // assign it a cache entry and get some temp memory
ent->animcacheindex = r_animcachestate.currentindex++;
c = r_animcachestate.entity + ent->animcacheindex;
- c->wantnormals = wantnormals;
- c->wanttangents = wanttangents;
- model->AnimateVertices(model, ent->frameblend, ent->skeleton, c->vertex3f, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
+ numvertices = model->surfmesh.num_vertices;
+ memset(c, 0, sizeof(*c));
+ c->vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
+ if (wantnormals)
+ c->normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
+ if (wanttangents)
+ {
+ c->svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
+ c->tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
+ }
+ if (!r_framedata_failed)
+ model->AnimateVertices(model, ent->frameblend, ent->skeleton, c->vertex3f, c->normal3f, c->svector3f, c->tvector3f);
}
- return true;
+ return !r_framedata_failed;
}
void R_AnimCache_CacheVisibleEntities(void)
{
int i;
- qboolean wantnormals;
- qboolean wanttangents;
-
- if (!r_animcachestate.maxindex)
- return;
+ entity_render_t *ent;
+ qboolean wantnormals = !r_showsurfaces.integer;
+ qboolean wanttangents = !r_showsurfaces.integer;
- wantnormals = !r_showsurfaces.integer;
- wanttangents = !r_showsurfaces.integer && (r_glsl.integer || r_refdef.scene.rtworld || r_refdef.scene.rtdlight);
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL20:
+ break;
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL11:
+ wanttangents = false;
+ break;
+ }
- // TODO: thread this?
+ // TODO: thread this
for (i = 0;i < r_refdef.scene.numentities;i++)
{
if (!r_refdef.viewcache.entityvisible[i])
continue;
- R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
+ ent = r_refdef.scene.entities[i];
+ if (ent->animcacheindex >= 0)
+ continue;
+ R_AnimCache_GetEntity(ent, wantnormals, wanttangents);
}
}
vec3_t start;
vec3_t end;
dp_model_t *model = r_refdef.scene.worldmodel;
-
+
if (!model || !model->brush.TraceLineOfSight)
return true;
if (!r_refdef.view.useperspective)
R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
- else if (gl_stencil && r_useinfinitefarclip.integer)
+ else if (vid.stencil && r_useinfinitefarclip.integer)
R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
else
R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
int waterwidth, waterheight, texturewidth, textureheight;
r_waterstate_waterplane_t *p;
+ if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
+ return;
+
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL20:
+ break;
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL11:
+ return;
+ }
+
// set waterwidth and waterheight to the water resolution that will be
// used (often less than the screen resolution for faster rendering)
waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
// calculate desired texture sizes
// can't use water if the card does not support the texture size
- if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size || r_showsurfaces.integer)
+ if (!r_water.integer || r_showsurfaces.integer)
texturewidth = textureheight = waterwidth = waterheight = 0;
- else if (gl_support_arb_texture_non_power_of_two)
+ else if (vid.support.arb_texture_non_power_of_two)
{
texturewidth = waterwidth;
textureheight = waterheight;
{
int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL20:
+ break;
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL11:
+ return;
+ }
+
// set bloomwidth and bloomheight to the bloom resolution that will be
// used (often less than the screen resolution for faster rendering)
r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
- r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, gl_max_texture_size);
- r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, gl_max_texture_size);
+ r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
+ r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
// calculate desired texture sizes
- if (gl_support_arb_texture_non_power_of_two)
+ if (vid.support.arb_texture_non_power_of_two)
{
screentexturewidth = r_refdef.view.width;
screentextureheight = r_refdef.view.height;
for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
}
- if ((r_hdr.integer || r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > gl_max_texture_size || r_refdef.view.height > gl_max_texture_size))
+ if ((r_hdr.integer || r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > (int)vid.maxtexturesize_2d || r_refdef.view.height > (int)vid.maxtexturesize_2d))
{
Cvar_SetValueQuick(&r_hdr, 0);
Cvar_SetValueQuick(&r_bloom, 0);
Cvar_SetValueQuick(&r_damageblur, 0);
}
- if (!(r_glsl.integer && (r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))) && !r_bloom.integer && !r_hdr.integer && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0)))
+ if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial)) && !r_bloom.integer && !r_hdr.integer && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0)))
screentexturewidth = screentextureheight = 0;
if (!r_hdr.integer && !r_bloom.integer)
bloomtexturewidth = bloomtextureheight = 0;
// apply subtract last
// (just like it would be in a GLSL shader)
- if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
+ if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
{
GL_BlendFunc(GL_ONE, GL_ZERO);
R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
static void R_BlendView(void)
{
- if (r_bloomstate.texture_screen)
- {
- // make sure the buffer is available
- if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
-
- R_ResetViewRendering2D();
- R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
- R_Mesh_ColorPointer(NULL, 0, 0);
- R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
- GL_ActiveTexture(0);CHECKGLERROR
-
- if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
- {
- // declare variables
- float speed;
- static float avgspeed;
-
- speed = VectorLength(cl.movement_velocity);
-
- cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
- avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
-
- speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
- speed = bound(0, speed, 1);
- speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
-
- // calculate values into a standard alpha
- cl.motionbluralpha = 1 - exp(-
- (
- (r_motionblur.value * speed / 80)
- +
- (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
- )
- /
- max(0.0001, cl.time - cl.oldtime) // fps independent
- );
-
- cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
- cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
- // apply the blur
- if (cl.motionbluralpha > 0)
- {
- R_SetupGenericShader(true);
- GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- GL_Color(1, 1, 1, cl.motionbluralpha);
- R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
- R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
- R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
- r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
- }
- }
-
- // copy view into the screen texture
- qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);CHECKGLERROR
- r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
- }
+ unsigned int permutation;
- if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
+ switch (vid.renderpath)
{
- unsigned int permutation =
+ case RENDERPATH_GL20:
+ permutation =
(r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
| (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
| ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
| (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
| ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
+ if (r_bloomstate.texture_screen)
+ {
+ // make sure the buffer is available
+ if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
+
+ R_ResetViewRendering2D();
+ R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
+ R_Mesh_ColorPointer(NULL, 0, 0);
+ R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
+ GL_ActiveTexture(0);CHECKGLERROR
+
+ if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
+ {
+ // declare variables
+ float speed;
+ static float avgspeed;
+
+ speed = VectorLength(cl.movement_velocity);
+
+ cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
+ avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
+
+ speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
+ speed = bound(0, speed, 1);
+ speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
+
+ // calculate values into a standard alpha
+ cl.motionbluralpha = 1 - exp(-
+ (
+ (r_motionblur.value * speed / 80)
+ +
+ (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
+ )
+ /
+ max(0.0001, cl.time - cl.oldtime) // fps independent
+ );
+
+ cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
+ cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
+ // apply the blur
+ if (cl.motionbluralpha > 0)
+ {
+ R_SetupGenericShader(true);
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ GL_Color(1, 1, 1, cl.motionbluralpha);
+ R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
+ R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
+ R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
+ r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
+ }
+ }
+
+ // copy view into the screen texture
+ qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);CHECKGLERROR
+ r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
+ }
+ else if (!r_bloomstate.texture_bloom)
+ break; // no screen processing, no bloom, skip it
+
if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
{
// render simple bloom effect
qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
- return;
- }
-
-
-
- if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
- {
- // render high dynamic range bloom effect
- // the bloom texture was made earlier this render, so we just need to
- // blend it onto the screen...
- R_ResetViewRendering2D();
- R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
- R_Mesh_ColorPointer(NULL, 0, 0);
- R_SetupGenericShader(true);
- GL_Color(1, 1, 1, 1);
- GL_BlendFunc(GL_ONE, GL_ONE);
- R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
- R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
- R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
- r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
- }
- else if (r_bloomstate.texture_bloom)
- {
- // render simple bloom effect
- // copy the screen and shrink it and darken it for the bloom process
- R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
- // make the bloom texture
- R_Bloom_MakeTexture();
- // put the original screen image back in place and blend the bloom
- // texture on it
- R_ResetViewRendering2D();
- R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
- R_Mesh_ColorPointer(NULL, 0, 0);
- GL_Color(1, 1, 1, 1);
- GL_BlendFunc(GL_ONE, GL_ZERO);
- // do both in one pass if possible
- R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
- R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
- if (r_textureunits.integer >= 2 && gl_combine.integer)
- {
- R_SetupGenericTwoTextureShader(GL_ADD);
- R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
- R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
- }
- else
+ break;
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL11:
+ if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
{
- R_SetupGenericShader(true);
+ // apply a color tint to the whole view
+ R_ResetViewRendering2D();
+ R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
+ R_Mesh_ColorPointer(NULL, 0, 0);
+ R_SetupGenericShader(false);
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
- r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
- // now blend on the bloom texture
- GL_BlendFunc(GL_ONE, GL_ONE);
- R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
- R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
}
- R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
- r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
- }
- if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
- {
- // apply a color tint to the whole view
- R_ResetViewRendering2D();
- R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
- R_Mesh_ColorPointer(NULL, 0, 0);
- R_SetupGenericShader(false);
- GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
- R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
+ break;
}
}
r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
- r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
+ r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
- r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
+ r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
if (r_showsurfaces.integer)
{
else
r_refdef.fogenabled = false;
- if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
+ switch(vid.renderpath)
{
- if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
+ case RENDERPATH_GL20:
+ if(v_glslgamma.integer && !vid_gammatables_trivial)
{
- // build GLSL gamma texture
+ if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
+ {
+ // build GLSL gamma texture
#define RAMPWIDTH 256
- unsigned short ramp[RAMPWIDTH * 3];
- unsigned char rampbgr[RAMPWIDTH][4];
- int i;
+ unsigned short ramp[RAMPWIDTH * 3];
+ unsigned char rampbgr[RAMPWIDTH][4];
+ int i;
- r_texture_gammaramps_serial = vid_gammatables_serial;
+ r_texture_gammaramps_serial = vid_gammatables_serial;
- VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
- for(i = 0; i < RAMPWIDTH; ++i)
- {
- rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
- rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
- rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
- rampbgr[i][3] = 0;
- }
- if (r_texture_gammaramps)
- {
- R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
- }
- else
- {
- r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
+ VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
+ for(i = 0; i < RAMPWIDTH; ++i)
+ {
+ rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
+ rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
+ rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
+ rampbgr[i][3] = 0;
+ }
+ if (r_texture_gammaramps)
+ {
+ R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
+ }
+ else
+ {
+ r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
+ }
}
}
- }
- else
- {
- // remove GLSL gamma texture
+ else
+ {
+ // remove GLSL gamma texture
+ }
+ break;
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL11:
+ break;
}
}
r_frame++; // used only by R_GetCurrentTexture
rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
- R_AnimCache_NewFrame();
+ R_AnimCache_ClearCache();
+ R_FrameData_NewFrame();
if (r_refdef.view.isoverlay)
{
r_refdef.view.clear = true;
// this produces a bloom texture to be used in R_BlendView() later
- if (r_hdr.integer)
+ if (r_hdr.integer && r_bloomstate.bloomwidth)
R_HDR_RenderBloomTexture();
r_refdef.view.showdebug = true;
}
R_AnimCache_CacheVisibleEntities();
+ R_PrepareRTLights();
if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
{
R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
+ if (t->currentskinframe->qpixels)
+ R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
t->glosstexture = r_texture_black;
t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
CHECKGLERROR
RSurf_SetupDepthAndCulling();
if (r_showsurfaces.integer == 3)
+ {
R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
- else if (r_glsl.integer && gl_support_fragment_shader)
+ return;
+ }
+ switch (vid.renderpath)
+ {
+ case RENDERPATH_GL20:
R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
- else if (gl_combine.integer && r_textureunits.integer >= 2)
+ break;
+ case RENDERPATH_GL13:
R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
- else
+ break;
+ case RENDERPATH_GL11:
R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
+ break;
+ }
CHECKGLERROR
}
CHECKGLERROR
RSurf_SetupDepthAndCulling();
if (r_showsurfaces.integer == 3)
+ {
R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
- else if (r_glsl.integer && gl_support_fragment_shader)
+ return;
+ }
+ switch (vid.renderpath)
+ {
+ case RENDERPATH_GL20:
R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
- else if (gl_combine.integer && r_textureunits.integer >= 2)
+ break;
+ case RENDERPATH_GL13:
R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
- else
+ break;
+ case RENDERPATH_GL11:
R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
+ break;
+ }
CHECKGLERROR
}
else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
RSurf_ActiveModelEntity(ent, false, false);
else
- RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
+ {
+ switch (vid.renderpath)
+ {
+ case RENDERPATH_GL20:
+ RSurf_ActiveModelEntity(ent, true, true);
+ break;
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL11:
+ RSurf_ActiveModelEntity(ent, true, false);
+ break;
+ }
+ }
for (i = 0;i < numsurfaces;i = j)
{
RSurf_ActiveWorldEntity();
else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
RSurf_ActiveModelEntity(ent, false, false);
+ else if (depthonly)
+ RSurf_ActiveModelEntity(ent, false, false);
else
- RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
+ {
+ switch (vid.renderpath)
+ {
+ case RENDERPATH_GL20:
+ RSurf_ActiveModelEntity(ent, true, true);
+ break;
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL11:
+ RSurf_ActiveModelEntity(ent, true, false);
+ break;
+ }
+ }
surfaces = model->data_surfaces;
update = model->brushq1.lightmapupdateflags;