cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this)"};
cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
+cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
+cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "2", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
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_contrastboost = {CVAR_SAVE, "r_glsl_contrastboost", "1", "by how much to multiply the contrast in dark areas (1 is no change)"};
cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
rtexture_t *r_texture_blanknormalmap;
rtexture_t *r_texture_white;
+rtexture_t *r_texture_grey128;
rtexture_t *r_texture_black;
rtexture_t *r_texture_notexture;
rtexture_t *r_texture_whitecube;
data[2] = 255;
data[3] = 255;
r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
+ data[0] = 128;
+ data[1] = 128;
+ data[2] = 128;
+ data[3] = 255;
+ r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
data[0] = 0;
data[1] = 0;
data[2] = 0;
"\n"
"uniform myhalf GlowScale;\n"
"uniform myhalf SceneBrightness;\n"
+"#ifdef USECONTRASTBOOST\n"
+"uniform myhalf ContrastBoostCoeff;\n"
+"#endif\n"
"\n"
"uniform float OffsetMapping_Scale;\n"
"uniform float OffsetMapping_Bias;\n"
" color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
"#endif\n"
"\n"
+"#ifdef USECONTRASTBOOST\n"
+" color.rgb = color.rgb * SceneBrightness / (ContrastBoostCoeff * color.rgb + myhvec3(1, 1, 1));\n"
+"#else\n"
" color.rgb *= SceneBrightness;\n"
+"#endif\n"
"\n"
" gl_FragColor = vec4(color);\n"
"}\n"
{"#define USEFOG\n", " fog"},
{"#define USECOLORMAPPING\n", " colormapping"},
{"#define USEDIFFUSE\n", " diffuse"},
+ {"#define USECONTRASTBOOST\n", " contrastboost"},
{"#define USESPECULAR\n", " specular"},
{"#define USECUBEFILTER\n", " cubefilter"},
{"#define USEOFFSETMAPPING\n", " offsetmapping"},
p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
+ p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
// initialize the samplers to refer to the texture units we use
if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
qglUseProgramObjectARB(0);CHECKGLERROR
}
else
- Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
+ Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, filename);
if (shaderstring)
Mem_Free(shaderstring);
}
memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
}
+void R_GLSL_DumpShader_f(void)
+{
+ int i;
+
+ qfile_t *file = FS_Open("glsl/default.glsl", "w", false, false);
+ if(!file)
+ {
+ Con_Printf("failed to write to glsl/default.glsl\n");
+ return;
+ }
+
+ FS_Print(file, "// The engine may define the following macros:\n");
+ FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
+ for (i = 0;permutationinfo[i][0];i++)
+ FS_Printf(file, "// %s", permutationinfo[i][0]);
+ FS_Print(file, "\n");
+ FS_Print(file, builtinshaderstring);
+ FS_Close(file);
+
+ Con_Printf("glsl/default.glsl written\n");
+}
+
extern rtexture_t *r_shadow_attenuationgradienttexture;
extern rtexture_t *r_shadow_attenuation2dtexture;
extern rtexture_t *r_shadow_attenuation3dtexture;
// fragment shader on features that are not being used
const char *shaderfilename = NULL;
unsigned int permutation = 0;
+ rtexture_t *nmap;
r_glsl_permutation = NULL;
// TODO: implement geometry-shader based shadow volumes someday
if (rsurface.rtlight)
if (r_glsl_offsetmapping_reliefmapping.integer)
permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
}
+ if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
+ permutation |= SHADERPERMUTATION_CONTRASTBOOST;
}
else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
{
if (r_glsl_offsetmapping_reliefmapping.integer)
permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
}
+ if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
+ permutation |= SHADERPERMUTATION_CONTRASTBOOST;
}
else if (modellighting)
{
if (r_glsl_offsetmapping_reliefmapping.integer)
permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
}
+ if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
+ permutation |= SHADERPERMUTATION_CONTRASTBOOST;
}
else
{
if (r_glsl_offsetmapping_reliefmapping.integer)
permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
}
+ if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
+ permutation |= SHADERPERMUTATION_CONTRASTBOOST;
}
if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
{
{
// remove features until we find a valid permutation
unsigned int i;
- for (i = SHADERPERMUTATION_MASK;;i>>=1)
+ for (i = (SHADERPERMUTATION_MAX >> 1);;i>>=1)
{
if (!i)
- return 0; // utterly failed
+ {
+ 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);
+ return 0; // no bit left to clear
+ }
// reduce i more quickly whenever it would not remove any bits
- if (permutation < i)
+ if (!(permutation & i))
continue;
- permutation &= i;
+ permutation &= ~i;
if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
R_GLSL_CompilePermutation(shaderfilename, permutation);
if (r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
}
- if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(rsurface.texture->currentskinframe->nmap));
+ nmap = rsurface.texture->currentskinframe->nmap;
+ if (gl_lightmaps.integer)
+ nmap = r_texture_blanknormalmap;
+ if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(nmap));
if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface.texture->basetexture));
if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface.texture->glosstexture));
//if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(rsurface.rtlight->currentcubemap));
//if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface.texture->currentskinframe->glow));
if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
- if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
+ if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
+ {
+ // The formula used is actually:
+ // color.rgb *= SceneBrightness;
+ // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
+ // I simplify that to
+ // color.rgb *= [[SceneBrightness * ContrastBoost]];
+ // color.rgb /= [[(ContrastBoost - 1) / ContrastBoost]] * color.rgb + 1;
+ // and Black:
+ // color.rgb = [[SceneBrightness * ContrastBoost]] / ([[(ContrastBoost - 1) * SceneBrightness]] + 1 / color.rgb);
+ // and do [[calculations]] here in the engine
+ qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, (r_glsl_contrastboost.value - 1) * r_view.colorscale);
+ if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale * r_glsl_contrastboost.value);
+ }
+ else
+ if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
if (r_glsl_permutation->loc_FogColor >= 0)
{
// additive passes are only darkened by fog, not tinted
basepixels_width = image_width;
basepixels_height = image_height;
- skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
+ skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
if (textureflags & TEXF_ALPHA)
{
pixels[j+2] = 255;
pixels[j+3] = basepixels[j+3];
}
- skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
+ skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
Mem_Free(pixels);
}
}
{
if ((pixels = loadimagepixels(va("%s_norm", skinframe->basename), false, 0, 0)) != NULL)
{
- skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
+ skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
Mem_Free(pixels);
pixels = NULL;
}
{
pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
Image_HeightmapToNormalmap(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
- skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
+ skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
Mem_Free(pixels);
Mem_Free(bumppixels);
}
{
pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
Image_HeightmapToNormalmap(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
- skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
+ skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
Mem_Free(pixels);
}
}
// _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 = loadimagepixels(va("%s_glow", skinframe->basename), false, 0, 0)) != NULL || (pixels = loadimagepixels(va("%s_luma", skinframe->basename), false, 0, 0)) != NULL)) {skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);Mem_Free(pixels);pixels = NULL;}
- if (loadgloss && (pixels = loadimagepixels(va("%s_gloss", skinframe->basename), false, 0, 0)) != NULL) {skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);Mem_Free(pixels);pixels = NULL;}
- if (loadpantsandshirt && (pixels = loadimagepixels(va("%s_pants", skinframe->basename), false, 0, 0)) != NULL) {skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);Mem_Free(pixels);pixels = NULL;}
- if (loadpantsandshirt && (pixels = loadimagepixels(va("%s_shirt", skinframe->basename), false, 0, 0)) != NULL) {skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);Mem_Free(pixels);pixels = NULL;}
+ if (loadglow && ((pixels = loadimagepixels(va("%s_glow", skinframe->basename), false, 0, 0)) != NULL || (pixels = loadimagepixels(va("%s_luma", skinframe->basename), false, 0, 0)) != NULL)) {skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
+ if (loadgloss && (pixels = loadimagepixels(va("%s_gloss", skinframe->basename), false, 0, 0)) != NULL) {skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
+ if (loadpantsandshirt && (pixels = loadimagepixels(va("%s_pants", skinframe->basename), false, 0, 0)) != NULL) {skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
+ if (loadpantsandshirt && (pixels = loadimagepixels(va("%s_shirt", skinframe->basename), false, 0, 0)) != NULL) {skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
if (basepixels)
Mem_Free(basepixels);
temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
temp2 = temp1 + width * height * 4;
Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
- skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, textureflags | TEXF_ALPHA, NULL);
+ skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, skinframe->textureflags | TEXF_ALPHA, NULL);
Mem_Free(temp1);
}
- skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_RGBA, textureflags, NULL);
+ skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_RGBA, skinframe->textureflags, NULL);
if (textureflags & TEXF_ALPHA)
{
for (i = 3;i < width * height * 4;i += 4)
memcpy(fogpixels, skindata, width * height * 4);
for (i = 0;i < width * height * 4;i += 4)
fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
- skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_RGBA, textureflags, NULL);
+ skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
Mem_Free(fogpixels);
}
}
Image_Copy8bitRGBA(skindata, temp1, width * height, palette ? palette : palette_complete);
Image_HeightmapToNormalmap(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
}
- skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, textureflags | TEXF_ALPHA, NULL);
+ skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, 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 ? palette : (loadglowtexture ? palette_nofullbrights : ((textureflags & TEXF_ALPHA) ? palette_transparent : palette_complete)), textureflags, true); // all
+ skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette ? palette : (loadglowtexture ? palette_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_transparent : palette_complete)), skinframe->textureflags, true); // all
if (!palette && loadglowtexture)
- skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_onlyfullbrights, textureflags, false); // glow
+ skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_onlyfullbrights, skinframe->textureflags, false); // glow
if (!palette && loadpantsandshirt)
{
- skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_pantsaswhite, textureflags, false); // pants
- skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_shirtaswhite, textureflags, false); // shirt
+ skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_pantsaswhite, skinframe->textureflags, false); // pants
+ skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_shirtaswhite, skinframe->textureflags, false); // shirt
}
if (skinframe->pants || skinframe->shirt)
- skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename),loadglowtexture ? palette_nocolormapnofullbrights : palette_nocolormap, textureflags, false); // no special colors
+ skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename),loadglowtexture ? palette_nocolormapnofullbrights : palette_nocolormap, skinframe->textureflags, false); // no special colors
if (textureflags & TEXF_ALPHA)
{
// if not using a custom alphapalette, use the quake one
if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255)
break;
if (i < width * height)
- skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), alphapalette, textureflags, true); // fog mask
+ skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), alphapalette, skinframe->textureflags, true); // fog mask
}
}
R_FreeTexturePool(&r_main_texturepool);
r_texture_blanknormalmap = NULL;
r_texture_white = NULL;
+ r_texture_grey128 = NULL;
r_texture_black = NULL;
r_texture_whitecube = NULL;
r_texture_normalizationcube = NULL;
r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
+ Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
// FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
if (gamemode == GAME_NEHAHRA)
{
Cvar_RegisterVariable(&r_shadows);
Cvar_RegisterVariable(&r_shadows_throwdistance);
Cvar_RegisterVariable(&r_q1bsp_skymasking);
+ Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
+ Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
Cvar_RegisterVariable(&r_textureunits);
Cvar_RegisterVariable(&r_glsl);
Cvar_RegisterVariable(&r_glsl_offsetmapping);
Cvar_RegisterVariable(&r_bloom_colorsubtract);
Cvar_RegisterVariable(&r_hdr);
Cvar_RegisterVariable(&r_hdr_scenebrightness);
+ Cvar_RegisterVariable(&r_glsl_contrastboost);
Cvar_RegisterVariable(&r_hdr_glowintensity);
Cvar_RegisterVariable(&r_hdr_range);
Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
- slopex = 1.0 / r_view.frustum_x;
- slopey = 1.0 / r_view.frustum_y;
- VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
- VectorMA(r_view.forward, slopex, r_view.left, r_view.frustum[1].normal);
- VectorMA(r_view.forward, -slopey, r_view.up , r_view.frustum[2].normal);
- VectorMA(r_view.forward, slopey, r_view.up , r_view.frustum[3].normal);
- VectorCopy(r_view.forward, r_view.frustum[4].normal);
- VectorNormalize(r_view.frustum[0].normal);
- VectorNormalize(r_view.frustum[1].normal);
- VectorNormalize(r_view.frustum[2].normal);
- VectorNormalize(r_view.frustum[3].normal);
- r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
- r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
- r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
- r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
- r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
+ if (r_view.useperspective)
+ {
+ slopex = 1.0 / r_view.frustum_x;
+ slopey = 1.0 / r_view.frustum_y;
+ VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
+ VectorMA(r_view.forward, slopex, r_view.left, r_view.frustum[1].normal);
+ VectorMA(r_view.forward, -slopey, r_view.up , r_view.frustum[2].normal);
+ VectorMA(r_view.forward, slopey, r_view.up , r_view.frustum[3].normal);
+ VectorCopy(r_view.forward, r_view.frustum[4].normal);
+
+ // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
+ VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
+ VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
+ VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[2]);
+ VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[3]);
+
+ r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
+ r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
+ r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
+ r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
+ r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
+ }
+ else
+ {
+ VectorScale(r_view.left, -r_view.ortho_x, r_view.frustum[0].normal);
+ VectorScale(r_view.left, r_view.ortho_x, r_view.frustum[1].normal);
+ VectorScale(r_view.up, -r_view.ortho_y, r_view.frustum[2].normal);
+ VectorScale(r_view.up, r_view.ortho_y, r_view.frustum[3].normal);
+ VectorCopy(r_view.forward, r_view.frustum[4].normal);
+ r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal) + r_view.ortho_x;
+ r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal) + r_view.ortho_x;
+ r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal) + r_view.ortho_y;
+ r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal) + r_view.ortho_y;
+ r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
+ }
+
PlaneClassify(&r_view.frustum[0]);
PlaneClassify(&r_view.frustum[1]);
PlaneClassify(&r_view.frustum[2]);
PlaneClassify(&r_view.frustum[3]);
PlaneClassify(&r_view.frustum[4]);
- // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
- VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
- VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
- VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[2]);
- VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[3]);
-
// LordHavoc: note to all quake engine coders, Quake had a special case
// for 90 degrees which assumed a square view (wrong), so I removed it,
// Quake2 has it disabled as well.
void R_SetupView(const matrix4x4_t *matrix)
{
- if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
+ if (!r_view.useperspective)
+ GL_SetupView_Mode_Ortho(-r_view.ortho_x, -r_view.ortho_y, r_view.ortho_x, r_view.ortho_y, -r_refdef.farclip, r_refdef.farclip);
+ else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
else
GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
GL_DepthTest(false);
R_Mesh_Matrix(&identitymatrix);
R_Mesh_ResetTextureState();
- qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
+ GL_PolygonOffset(0, 0);
qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
qglDepthFunc(GL_LEQUAL);CHECKGLERROR
qglDisable(GL_STENCIL_TEST);CHECKGLERROR
GL_DepthTest(true);
R_Mesh_Matrix(&identitymatrix);
R_Mesh_ResetTextureState();
- qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
+ GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
qglDepthFunc(GL_LEQUAL);CHECKGLERROR
qglDisable(GL_STENCIL_TEST);CHECKGLERROR
// TODO: add exposure compensation features
// TODO: add fp16 framebuffer support
+ r_view.showdebug = false;
r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
if (r_hdr.integer)
r_view.colorscale /= r_hdr_range.value;
R_RenderScene();
+ r_view.showdebug = true;
R_ResetViewRendering2D();
R_Bloom_StartFrame();
+ r_view.showdebug = true;
+
// this produces a bloom texture to be used in R_BlendView() later
if (r_hdr.integer)
R_HDR_RenderBloomTexture();
}
VM_CL_AddPolygonsToMeshQueue();
- if (cl_locs_show.integer)
+ if (r_view.showdebug)
{
- R_DrawLocs();
- if (r_timereport_active)
- R_TimeReport("showlocs");
- }
-
- if (r_drawportals.integer)
- {
- R_DrawPortals();
- if (r_timereport_active)
- R_TimeReport("portals");
- }
-
- if (r_showbboxes.value > 0)
- {
- R_DrawEntityBBoxes();
- if (r_timereport_active)
- R_TimeReport("bboxes");
+ if (cl_locs_show.integer)
+ {
+ R_DrawLocs();
+ if (r_timereport_active)
+ R_TimeReport("showlocs");
+ }
+
+ if (r_drawportals.integer)
+ {
+ R_DrawPortals();
+ if (r_timereport_active)
+ R_TimeReport("portals");
+ }
+
+ if (r_showbboxes.value > 0)
+ {
+ R_DrawEntityBBoxes();
+ if (r_timereport_active)
+ R_TimeReport("bboxes");
+ }
}
if (gl_support_fragment_shader)
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
GL_DepthMask(false);
GL_DepthRange(0, 1);
+ GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
R_Mesh_Matrix(&identitymatrix);
R_Mesh_ResetTextureState();
GL_DepthMask(true);
}
GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
+ GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
GL_DepthMask(false);
GL_DepthRange(0, depthshort ? 0.0625 : 1);
+ GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
GL_DepthTest(!depthdisable);
vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
{
// use an alternate animation if the entity's frame is not 0,
// and only if the texture has an alternate animation
- if (ent->frame != 0 && t->anim_total[1])
+ if (ent->frame2 != 0 && t->anim_total[1])
t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
else
t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
{
strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
- r_qwskincache_skinframe[i] = R_SkinFrame_LoadExternal(va("skins/%s", r_qwskincache[i]), TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP, developer.integer > 0);
+ r_qwskincache_skinframe[i] = R_SkinFrame_LoadExternal(va("skins/%s", r_qwskincache[i]), TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS, developer.integer > 0);
}
t->currentskinframe = r_qwskincache_skinframe[i];
if (t->currentskinframe == NULL)
t->specularscale = r_shadow_gloss2intensity.value;
}
+ // lightmaps mode looks bad with dlights using actual texturing, so turn
+ // off the colormap and glossmap, but leave the normalmap on as it still
+ // accurately represents the shading involved
+ if (gl_lightmaps.integer && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
+ {
+ t->basetexture = r_texture_white;
+ t->specularscale = 0;
+ }
+
+ t->currentpolygonfactor = r_refdef.polygonfactor + t->basepolygonfactor;
+ t->currentpolygonoffset = r_refdef.polygonoffset + t->basepolygonoffset;
+ // submodels are biased to avoid z-fighting with world surfaces that they
+ // may be exactly overlapping (avoids z-fighting artifacts on certain
+ // doors and things in Quake maps)
+ if (ent->model->brush.submodel)
+ {
+ t->currentpolygonfactor += r_polygonoffset_submodel_factor.value;
+ t->currentpolygonoffset += r_polygonoffset_submodel_offset.value;
+ }
+
VectorClear(t->dlightcolor);
t->currentnumlayers = 0;
if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
// q3bsp has no lightmap updates, so the lightstylevalue that
// would normally be baked into the lightmap must be
// applied to the color
+ // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
if (ent->model->type == mod_brushq3)
colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
colorscale *= r_refdef.lightmapintensity;
{
const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
const float *v1, *v2;
+ vec3_t start, end;
float f, l;
struct
{
float length2;
- int quadedge;
+ const float *v1;
+ const float *v2;
}
shortest[2];
+ memset(shortest, 0, sizeof(shortest));
// a single autosprite surface can contain multiple sprites...
for (j = 0;j < surface->num_vertices - 3;j += 4)
{
for (i = 0;i < 4;i++)
VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
VectorScale(center, 0.25f, center);
- shortest[0].quadedge = shortest[1].quadedge = 0;
- shortest[0].length2 = shortest[1].length2 = 0;
// find the two shortest edges, then use them to define the
// axis vectors for rotating around the central axis
for (i = 0;i < 6;i++)
{
v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
+#if 0
+ Debug_PolygonBegin(NULL, 0, false, 0);
+ Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
+ Debug_PolygonVertex((v1[0] + v2[0]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 4, (v1[1] + v2[1]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1], (v1[2] + v2[2]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2], 0, 0, 1, 1, 0, 1);
+ Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
+ Debug_PolygonEnd();
+#endif
l = VectorDistance2(v1, v2);
+ // this length bias tries to make sense of square polygons, assuming they are meant to be upright
+ if (v1[2] != v2[2])
+ l += (1.0f / 1024.0f);
if (shortest[0].length2 > l || i == 0)
{
shortest[1] = shortest[0];
shortest[0].length2 = l;
- shortest[0].quadedge = i;
+ shortest[0].v1 = v1;
+ shortest[0].v2 = v2;
}
else if (shortest[1].length2 > l || i == 1)
{
shortest[1].length2 = l;
- shortest[1].quadedge = i;
+ shortest[1].v1 = v1;
+ shortest[1].v2 = v2;
}
}
- // this calculates the midpoints *2 (not bothering to average) of the two shortest edges, and subtracts one from the other to get the up vector
- for (i = 0;i < 3;i++)
- {
- right[i] = rsurface.vertex3f[3 * (surface->num_firstvertex + quadedges[shortest[1].quadedge][1]) + i]
- + rsurface.vertex3f[3 * (surface->num_firstvertex + quadedges[shortest[1].quadedge][0]) + i];
- up[i] = rsurface.vertex3f[3 * (surface->num_firstvertex + quadedges[shortest[1].quadedge][0]) + i]
- + rsurface.vertex3f[3 * (surface->num_firstvertex + quadedges[shortest[1].quadedge][1]) + i]
- - rsurface.vertex3f[3 * (surface->num_firstvertex + quadedges[shortest[0].quadedge][0]) + i]
- - rsurface.vertex3f[3 * (surface->num_firstvertex + quadedges[shortest[0].quadedge][1]) + i];
- }
+ VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
+ VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
+#if 0
+ Debug_PolygonBegin(NULL, 0, false, 0);
+ Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
+ Debug_PolygonVertex(center[0] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 4, center[1] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1] * 4, center[2] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2] * 4, 0, 0, 0, 1, 0, 1);
+ Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
+ Debug_PolygonEnd();
+#endif
+ // this calculates the right vector from the shortest edge
+ // and the up vector from the edge midpoints
+ VectorSubtract(shortest[0].v1, shortest[0].v2, right);
+ VectorNormalize(right);
+ VectorSubtract(end, start, up);
+ VectorNormalize(up);
// calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
- VectorSubtract(rsurface.modelorg, center, forward);
+ //VectorSubtract(rsurface.modelorg, center, forward);
+ Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, forward);
+ VectorNegate(forward, forward);
+ VectorReflect(forward, 0, up, forward);
+ VectorNormalize(forward);
CrossProduct(up, forward, newright);
- // normalize the vectors involved
- VectorNormalize(right);
VectorNormalize(newright);
+#if 0
+ Debug_PolygonBegin(NULL, 0, false, 0);
+ Debug_PolygonVertex(center[0] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 8, center[1] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1] * 8, center[2] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2] * 8, 0, 0, 1, 0, 0, 1);
+ Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
+ Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
+ Debug_PolygonEnd();
+#endif
+#if 0
+ Debug_PolygonBegin(NULL, 0, false, 0);
+ Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
+ Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
+ Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
+ Debug_PolygonEnd();
+#endif
// rotate the quad around the up axis vector, this is made
// especially easy by the fact we know the quad is flat,
// so we only have to subtract the center position and
// displacement from the center, which we do with a
// DotProduct, the subtraction/addition of center is also
// optimized into DotProducts here
- l = DotProduct(newright, center) - DotProduct(right, center);
+ l = DotProduct(right, center);
for (i = 0;i < 4;i++)
{
v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
- f = DotProduct(right, v1) - DotProduct(newright, v1) + l;
- VectorMA(v1, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
+ f = DotProduct(right, v1) - l;
+ VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
}
}
Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformednormal3f, r_smoothnormals_areaweighting.integer);
static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
{
GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
+ GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
if (rsurface.mode != RSURFMODE_SHOWSURFACES)
R_Mesh_Matrix(&rsurface.matrix);
}
GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
+ GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
GL_DepthMask(true);
GL_Color(rsurface.texture->currentlayers[0].color[0], rsurface.texture->currentlayers[0].color[1], rsurface.texture->currentlayers[0].color[2], rsurface.texture->currentlayers[0].color[3]);
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
{
- R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
+ R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
R_Mesh_ColorPointer(NULL, 0, 0);
if (r_depthfirst.integer == 3)
{
int i = (int)(texturesurfacelist[0] - rsurface.modelsurfaces);
- GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1);
+ if (!r_view.showdebug)
+ GL_Color(0, 0, 0, 1);
+ else
+ GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1);
}
else
{
GL_Color(1,1,1,1);
}
GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
+ GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
GL_DepthTest(true);
GL_BlendFunc(GL_ONE, GL_ZERO);
}
else if (r_depthfirst.integer == 3)
return;
+ else if (!r_view.showdebug && (r_showsurfaces.integer || gl_lightmaps.integer))
+ {
+ GL_Color(0, 0, 0, 1);
+ RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
+ }
else if (r_showsurfaces.integer)
{
if (rsurface.mode != RSURFMODE_MULTIPASS)
rsurface.mode = RSURFMODE_MULTIPASS;
GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
+ GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
GL_DepthTest(true);
GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
GL_BlendFunc(GL_ONE, GL_ZERO);
GL_DepthMask(writedepth);
GL_Color(1,1,1,1);
GL_AlphaTest(false);
+ // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
+ rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
R_Mesh_ColorPointer(NULL, 0, 0);
memset(&m, 0, sizeof(m));
m.tex[0] = R_GetTexture(r_texture_white);
else if (rsurface.texture->currentnumlayers)
{
// write depth for anything we skipped on the depth-only pass earlier
- if (!writedepth && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
+ if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
writedepth = true;
GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
+ GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
GL_DepthMask(false);
GL_DepthRange(0, 1);
+ GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
GL_DepthTest(true);
GL_CullFace(GL_NONE);
R_Mesh_Matrix(&identitymatrix);
GL_DepthMask(false);
GL_DepthRange(0, 1);
GL_DepthTest(!r_showdisabledepthtest.integer);
- qglPolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
+ GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
if (brush->colbrushf && brush->colbrushf->numtriangles)
R_DrawCollisionBrush(brush->colbrushf);
for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
if (surface->num_collisiontriangles)
R_DrawCollisionSurface(ent, surface);
- qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
+ GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
}
void R_DrawTrianglesAndNormals(entity_render_t *ent, qboolean drawtris, qboolean drawnormals, int flagsmask)
CHECKGLERROR
GL_DepthRange(0, 1);
GL_DepthTest(!r_showdisabledepthtest.integer);
+ GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
GL_DepthMask(true);
GL_BlendFunc(GL_ONE, GL_ZERO);
R_Mesh_ColorPointer(NULL, 0, 0);
r_refdef.stats.entities_triangles += counttriangles;
RSurf_CleanUp();
- if (r_showcollisionbrushes.integer && !skysurfaces && !depthonly)
+ if (r_showcollisionbrushes.integer && r_view.showdebug && !skysurfaces && !depthonly)
R_DrawCollisionBrushes(r_refdef.worldentity);
- if ((r_showtris.integer || r_shownormals.integer) && !depthonly)
+ if ((r_showtris.integer || r_shownormals.integer) && r_view.showdebug && !depthonly)
R_DrawTrianglesAndNormals(r_refdef.worldentity, r_showtris.integer, r_shownormals.integer, flagsmask);
}
r_refdef.stats.entities_triangles += counttriangles;
RSurf_CleanUp();
- if (r_showcollisionbrushes.integer && !skysurfaces && !depthonly)
- R_DrawCollisionBrushes(ent);
+ if (r_view.showdebug)
+ {
+ if (r_showcollisionbrushes.integer && !skysurfaces && !depthonly)
+ R_DrawCollisionBrushes(ent);
- if ((r_showtris.integer || r_shownormals.integer) && !depthonly)
- R_DrawTrianglesAndNormals(ent, r_showtris.integer, r_shownormals.integer, flagsmask);
+ if ((r_showtris.integer || r_shownormals.integer) && !depthonly)
+ R_DrawTrianglesAndNormals(ent, r_showtris.integer, r_shownormals.integer, flagsmask);
+ }
}