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;
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)
for (i = (SHADERPERMUTATION_MAX >> 1);;i>>=1)
{
if (!i)
+ {
+ 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))
continue;
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));
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)
{
{
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;
}
- t->currentpolygonfactor = r_refdef.polygonfactor;
- t->currentpolygonoffset = r_refdef.polygonoffset;
+ // 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_refdef.polygonfactor + r_polygonoffset_submodel_factor.value;
- t->currentpolygonoffset = r_refdef.polygonoffset + r_polygonoffset_submodel_offset.value;
+ t->currentpolygonfactor += r_polygonoffset_submodel_factor.value;
+ t->currentpolygonoffset += r_polygonoffset_submodel_offset.value;
}
VectorClear(t->dlightcolor);
// 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;
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);
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);