cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
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!)"};
extern cvar_t v_glslgamma;
"#ifdef USEGAMMARAMPS\n"
"uniform sampler2D Texture_GammaRamps;\n"
"#endif\n"
+"#ifdef USESATURATION\n"
+"uniform float Saturation;\n"
+"#endif\n"
"#ifdef USEVERTEXTEXTUREBLEND\n"
"uniform vec4 TintColor;\n"
"#endif\n"
" gl_FragColor /= (1 + 5 * UserVec1.y);\n"
"#endif\n"
"\n"
+"#ifdef USESATURATION\n"
+" //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
+" myhalf y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
+" //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
+" gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n" // TODO: test this on ATI
+"#endif\n"
+"\n"
"#ifdef USEGAMMARAMPS\n"
" gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
" gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
" // 0.25 supports up to 75.5 degrees normal/deluxe angle\n"
"# ifdef USESPECULAR\n"
"# ifdef USEEXACTSPECULARMATH\n"
-" tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
+" tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(normalize(diffusenormal), surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
"# else\n"
" myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
" tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<11, // adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
SHADERPERMUTATION_GAMMARAMPS = 1<<12, // gamma (postprocessing only)
SHADERPERMUTATION_POSTPROCESSING = 1<<13, // user defined postprocessing
- SHADERPERMUTATION_LIMIT = 1<<14, // size of permutations array
- SHADERPERMUTATION_COUNT = 14 // size of shaderpermutationinfo array
+ SHADERPERMUTATION_SATURATION = 1<<14, // user defined postprocessing
+ SHADERPERMUTATION_LIMIT = 1<<15, // size of permutations array
+ SHADERPERMUTATION_COUNT = 15 // size of shaderpermutationinfo array
}
shaderpermutation_t;
{"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
{"#define USEGAMMARAMPS\n", " gammaramps"},
{"#define USEPOSTPROCESSING\n", " postprocessing"},
+ {"#define USESATURATION\n", " saturation"},
};
// this enum is multiplied by SHADERPERMUTATION_MODEBASE
int loc_UserVec4;
int loc_ClientTime;
int loc_PixelSize;
+ int loc_Saturation;
}
r_glsl_permutation_t;
r_refdef.fogmasktable_density = 0;
}
+extern rtexture_t *loadingscreentexture;
void gl_main_shutdown(void)
{
if (r_maxqueries)
Mem_Free(r_svbsp.nodes);
memset(&r_svbsp, 0, sizeof (r_svbsp));
R_FreeTexturePool(&r_main_texturepool);
+ loadingscreentexture = NULL;
r_texture_blanknormalmap = NULL;
r_texture_white = NULL;
r_texture_grey128 = NULL;
Cvar_RegisterVariable(&gl_lightmaps);
Cvar_RegisterVariable(&r_test);
Cvar_RegisterVariable(&r_batchmode);
+ Cvar_RegisterVariable(&r_glsl_saturation);
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);
Cvar_SetValueQuick(&r_bloom, 0);
}
- if (!(r_glsl.integer && (r_glsl_postprocess.integer || (v_glslgamma.integer && !vid_gammatables_trivial) || r_bloom.integer || r_hdr.integer)) && !r_bloom.integer)
+ if (!(r_glsl.integer && (r_glsl_postprocess.integer || r_glsl_saturation.value != 1 || (v_glslgamma.integer && !vid_gammatables_trivial) || r_bloom.integer || r_hdr.integer)) && !r_bloom.integer)
screentexturewidth = screentextureheight = 0;
if (!r_hdr.integer && !r_bloom.integer)
bloomtexturewidth = bloomtextureheight = 0;
r_refdef.view.showdebug = false;
r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
+ R_ResetViewRendering3D();
+
R_ClearScreen(r_refdef.fogenabled);
if (r_timereport_active)
R_TimeReport("HDRclear");
(r_bloomstate.texture_bloom ? SHADERPERMUTATION_GLOW : 0)
| (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0)
| ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
- | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0);
+ | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
+ | (r_glsl_saturation.value != 1 ? SHADERPERMUTATION_SATURATION : 0);
if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
{
sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
}
+ if (r_glsl_permutation->loc_Saturation >= 0)
+ qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
return;
float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
{
- float l, d, eyedir[3];
- VectorSubtract(rsurface.modelorg, vertex, eyedir);
- l = 0.5f / VectorLength(eyedir);
- d = DotProduct(normal, eyedir)*2;
- out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
- out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
+ // identical to Q3A's method, but executed in worldspace so
+ // carried models can be shiny too
+
+ float viewer[3], d, reflected[3], worldreflected[3];
+
+ VectorSubtract(rsurface.modelorg, vertex, viewer);
+ // VectorNormalize(viewer);
+
+ d = DotProduct(normal, viewer);
+
+ reflected[0] = normal[0]*2*d - viewer[0];
+ reflected[1] = normal[1]*2*d - viewer[1];
+ reflected[2] = normal[2]*2*d - viewer[2];
+ // note: this is proportinal to viewer, so we can normalize later
+
+ Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
+ VectorNormalize(worldreflected);
+
+ // note: this sphere map only uses world x and z!
+ // so positive and negative y will LOOK THE SAME.
+ out_tc[0] = 0.5 + 0.5 * worldreflected[1];
+ out_tc[1] = 0.5 - 0.5 * worldreflected[2];
}
}
rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
if (debug)
{
R_DrawDebugModel(r_refdef.scene.worldentity);
+ rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
return;
}
R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
// don't do anything if there were no surfaces
if (!numsurfacelist)
+ {
+ rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
return;
+ }
R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
GL_AlphaTest(false);
for (j = 0;j < numsurfacelist;j++)
r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
}
+ rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
}
void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
if (debug)
{
R_DrawDebugModel(ent);
+ rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
return;
}
r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
// don't do anything if there were no surfaces
if (!numsurfacelist)
+ {
+ rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
return;
+ }
// update lightmaps if needed
if (update)
for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
// add to stats if desired
if (r_speeds.integer && !skysurfaces && !depthonly)
{
- r_refdef.stats.entities++;
r_refdef.stats.entities_surfaces += numsurfacelist;
for (j = 0;j < numsurfacelist;j++)
r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
}
+ rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
}