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_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
+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_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_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_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
+cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
+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_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"};
-extern qboolean v_flipped_state;
+extern cvar_t v_glslgamma;
-typedef struct r_glsl_bloomshader_s
-{
- int program;
- int loc_Texture_Bloom;
-}
-r_glsl_bloomshader_t;
+extern qboolean v_flipped_state;
static struct r_bloomstate_s
{
int bloomtexturewidth, bloomtextureheight;
rtexture_t *texture_bloom;
- r_glsl_bloomshader_t *shader;
-
// arrays for rendering the screen passes
float screentexcoord2f[8];
float bloomtexcoord2f[8];
rtexture_t *r_texture_whitecube;
rtexture_t *r_texture_normalizationcube;
rtexture_t *r_texture_fogattenuation;
+rtexture_t *r_texture_gammaramps;
+unsigned int r_texture_gammaramps_serial;
//rtexture_t *r_texture_fogintensity;
char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
"# endif\n"
"\n"
"#else\n"
-"#ifdef MODE_GENERIC\n"
"\n"
+"#ifdef MODE_POSTPROCESS\n"
+"# ifdef VERTEX_SHADER\n"
+"void main(void)\n"
+"{\n"
+" gl_FrontColor = gl_Color;\n"
+" gl_Position = ftransform();\n"
+" gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
+"#ifdef USEGLOW\n"
+" gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
+"#endif\n"
+"}\n"
+"# endif\n"
+"# ifdef FRAGMENT_SHADER\n"
+"\n"
+"uniform sampler2D Texture_First;\n"
+"#ifdef USEGLOW\n"
+"uniform sampler2D Texture_Second;\n"
+"#endif\n"
+"#ifdef USEGAMMARAMPS\n"
+"uniform sampler2D Texture_Attenuation;\n"
+"#endif\n"
+"#ifdef USEVERTEXTEXTUREBLEND\n"
+"uniform vec4 TintColor;\n"
+"#endif\n"
+"#ifdef USECOLORMOD\n"
+"uniform vec3 Gamma;\n"
+"#endif\n"
+"//uncomment these if you want to use them:\n"
+"// uniform vec4 UserVec1;\n"
+"// uniform vec4 UserVec2;\n"
+"// uniform vec4 UserVec3;\n"
+"// uniform vec4 UserVec4;\n"
+"// uniform float ClientTime;\n"
+"void main(void)\n"
+"{\n"
+" gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
+"#ifdef USEGLOW\n"
+" gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
+"#endif\n"
+"#ifdef USEVERTEXTEXTUREBLEND\n"
+" gl_FragColor = mix(TintColor, gl_FragColor, TintColor.a);\n"
+"#endif\n"
+"\n"
+"#ifdef USEPOSTPROCESSING\n"
+"// add your own postprocessing here or make your own ifdef for it\n"
+"#endif\n"
+"\n"
+"#ifdef USEGAMMARAMPS\n"
+" gl_FragColor.r = texture2D(Texture_Attenuation, vec2(gl_FragColor.r, 0)).r;\n"
+" gl_FragColor.g = texture2D(Texture_Attenuation, vec2(gl_FragColor.g, 0)).g;\n"
+" gl_FragColor.b = texture2D(Texture_Attenuation, vec2(gl_FragColor.b, 0)).b;\n"
+"#endif\n"
+"}\n"
+"# endif\n"
+"\n"
+"\n"
+"#else\n"
+"#ifdef MODE_GENERIC\n"
"# ifdef VERTEX_SHADER\n"
"void main(void)\n"
"{\n"
"varying vec2 TexCoord;\n"
"varying vec2 TexCoordLightmap;\n"
"\n"
-"//#ifdef MODE_LIGHTSOURCE\n"
+"#ifdef MODE_LIGHTSOURCE\n"
"varying vec3 CubeVector;\n"
-"//#endif\n"
+"#endif\n"
"\n"
-"//#ifdef MODE_LIGHTSOURCE\n"
+"#ifdef MODE_LIGHTSOURCE\n"
"varying vec3 LightVector;\n"
-"//#else\n"
-"//# ifdef MODE_LIGHTDIRECTION\n"
-"//varying vec3 LightVector;\n"
-"//# endif\n"
-"//#endif\n"
+"#endif\n"
+"#ifdef MODE_LIGHTDIRECTION\n"
+"varying vec3 LightVector;\n"
+"#endif\n"
"\n"
"varying vec3 EyeVector;\n"
-"//#ifdef USEFOG\n"
+"#ifdef USEFOG\n"
"varying vec3 EyeVectorModelSpace;\n"
-"//#endif\n"
+"#endif\n"
"\n"
"varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
"varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
"varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
"\n"
-"//#ifdef MODE_WATER\n"
+"#ifdef MODE_WATER\n"
"varying vec4 ModelViewProjectionPosition;\n"
-"//#else\n"
-"//# ifdef MODE_REFRACTION\n"
-"//varying vec4 ModelViewProjectionPosition;\n"
-"//# else\n"
-"//# ifdef USEREFLECTION\n"
-"//varying vec4 ModelViewProjectionPosition;\n"
-"//# endif\n"
-"//# endif\n"
-"//#endif\n"
+"#ifdef MODE_REFRACTION\n"
+"varying vec4 ModelViewProjectionPosition;\n"
+"#else\n"
+"# ifdef USEREFLECTION\n"
+"varying vec4 ModelViewProjectionPosition;\n"
+"# endif\n"
+"#endif\n"
+"#endif\n"
"\n"
"\n"
"\n"
"#endif // FRAGMENT_SHADER\n"
"\n"
"#endif // !MODE_GENERIC\n"
+"#endif // !MODE_POSTPROCESS\n"
"#endif // !MODE_DEPTH_OR_SHADOW\n"
;
SHADERPERMUTATION_REFLECTION = 1<<8, // normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
SHADERPERMUTATION_OFFSETMAPPING = 1<<9, // adjust texcoords to roughly simulate a displacement mapped surface
SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<10, // adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
- SHADERPERMUTATION_LIMIT = 1<<11, // size of permutations array
- SHADERPERMUTATION_COUNT = 11 // size of shaderpermutationinfo array
+ SHADERPERMUTATION_GAMMARAMPS = 1<<11, // gamma (postprocessing only)
+ SHADERPERMUTATION_POSTPROCESSING = 1<<12, // user defined postprocessing
+ SHADERPERMUTATION_LIMIT = 1<<13, // size of permutations array
+ SHADERPERMUTATION_COUNT = 13 // size of shaderpermutationinfo array
}
shaderpermutation_t;
{"#define USEREFLECTION\n", " reflection"},
{"#define USEOFFSETMAPPING\n", " offsetmapping"},
{"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
+ {"#define USEGAMMARAMPS\n", " gammaramps"},
+ {"#define USEPOSTPROCESSING\n", " postprocessing"},
};
// this enum is multiplied by SHADERPERMUTATION_MODEBASE
typedef enum shadermode_e
{
SHADERMODE_GENERIC, // (particles/HUD/etc) vertex color, optionally multiplied by one texture
+ SHADERMODE_POSTPROCESS, // postprocessing shader (r_glsl_postprocess)
SHADERMODE_DEPTH_OR_SHADOW, // (depthfirst/shadows) vertex shader only
SHADERMODE_FLATCOLOR, // (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
SHADERMODE_VERTEXCOLOR, // (lightmap) modulate texture by vertex colors (q3bsp)
shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
{
{"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
+ {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
{"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
{"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
{"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
int loc_SpecularColor;
int loc_LightDir;
int loc_ContrastBoostCoeff; // 1 - 1/ContrastBoost
+ int loc_GammaCoeff; // 1 / gamma
int loc_DistortScaleRefractReflect;
int loc_ScreenScaleRefractReflect;
int loc_ScreenCenterRefractReflect;
int loc_ReflectColor;
int loc_ReflectFactor;
int loc_ReflectOffset;
+ int loc_UserVec1;
+ int loc_UserVec2;
+ int loc_UserVec3;
+ int loc_UserVec4;
+ int loc_ClientTime;
}
r_glsl_permutation_t;
p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
+ p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff");
+ p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
+ p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
+ p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
+ p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
+ p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
// initialize the samplers to refer to the texture units we use
if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
R_BuildNormalizationCube();
}
r_texture_fogattenuation = NULL;
+ r_texture_gammaramps = NULL;
//r_texture_fogintensity = NULL;
memset(&r_bloomstate, 0, sizeof(r_bloomstate));
memset(&r_waterstate, 0, sizeof(r_waterstate));
r_texture_whitecube = NULL;
r_texture_normalizationcube = NULL;
r_texture_fogattenuation = NULL;
+ r_texture_gammaramps = NULL;
//r_texture_fogintensity = NULL;
memset(&r_bloomstate, 0, sizeof(r_bloomstate));
memset(&r_waterstate, 0, sizeof(r_waterstate));
Cvar_RegisterVariable(&r_fog_exp2);
Cvar_RegisterVariable(&r_textureunits);
Cvar_RegisterVariable(&r_glsl);
+ Cvar_RegisterVariable(&r_glsl_contrastboost);
+ Cvar_RegisterVariable(&r_glsl_deluxemapping);
Cvar_RegisterVariable(&r_glsl_offsetmapping);
Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
- Cvar_RegisterVariable(&r_glsl_deluxemapping);
+ Cvar_RegisterVariable(&r_glsl_postprocess);
+ Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
+ 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_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);
R_SetupGenericShader(true);
}
-/*
- R_Bloom_SetupShader(
-"// bloom shader\n"
-"// written by Forest 'LordHavoc' Hale\n"
-"\n"
-"// common definitions between vertex shader and fragment shader:\n"
-"\n"
-"#ifdef __GLSL_CG_DATA_TYPES\n"
-"#define myhalf half\n"
-"#define myhalf2 half2\n"
-"#define myhalf3 half3\n"
-"#define myhalf4 half4\n"
-"#else\n"
-"#define myhalf float\n"
-"#define myhalf2 vec2\n"
-"#define myhalf3 vec3\n"
-"#define myhalf4 vec4\n"
-"#endif\n"
-"\n"
-"varying vec2 ScreenTexCoord;\n"
-"varying vec2 BloomTexCoord;\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"// vertex shader specific:\n"
-"#ifdef VERTEX_SHADER\n"
-"\n"
-"void main(void)\n"
-"{\n"
-" ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
-" BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
-" // transform vertex to camera space, using ftransform to match non-VS\n"
-" // rendering\n"
-" gl_Position = ftransform();\n"
-"}\n"
-"\n"
-"#endif // VERTEX_SHADER\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"// fragment shader specific:\n"
-"#ifdef FRAGMENT_SHADER\n"
-"\n"
-"void main(void)\n"
-"{\n"
-" int x, y;
-" myhalf3 color = myhalf3(texture2D(Texture_Screen, ScreenTexCoord));\n"
-" for (x = -BLUR_X;x <= BLUR_X;x++)
-" color.rgb += myhalf3(texture2D(Texture_Bloom, BloomTexCoord));\n"
-" color.rgb += myhalf3(texture2D(Texture_Bloom, BloomTexCoord));\n"
-" color.rgb += myhalf3(texture2D(Texture_Bloom, BloomTexCoord));\n"
-" color.rgb += myhalf3(texture2D(Texture_Bloom, BloomTexCoord));\n"
-
-" gl_FragColor = vec4(color);\n"
-"}\n"
-"\n"
-"#endif // FRAGMENT_SHADER\n"
-*/
-
void R_RenderScene(qboolean addwaterplanes);
static void R_Water_StartFrame(void)
r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
+ r_bloomstate.bloomwidth = min(r_bloomstate.bloomwidth, gl_max_texture_size);
+ r_bloomstate.bloomheight = min(r_bloomstate.bloomheight, gl_max_texture_size);
// calculate desired texture sizes
if (gl_support_arb_texture_non_power_of_two)
for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
}
- if (r_hdr.integer)
- {
- screentexturewidth = screentextureheight = 0;
- }
- else if (r_bloom.integer)
+ if ((r_hdr.integer || r_bloom.integer) && ((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))
{
+ Cvar_SetValueQuick(&r_hdr, 0);
+ Cvar_SetValueQuick(&r_bloom, 0);
}
- else
- {
+
+ if (!(r_glsl.integer && (r_glsl_postprocess.integer || (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;
- }
-
- if ((!bloomtexturewidth && !bloomtextureheight) || r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512 || screentexturewidth > gl_max_texture_size || screentextureheight > gl_max_texture_size || bloomtexturewidth > gl_max_texture_size || bloomtextureheight > gl_max_texture_size)
- {
- // can't use bloom if the parameters are too weird
- // can't use bloom if the card does not support the texture size
- if (r_bloomstate.texture_screen)
- R_FreeTexture(r_bloomstate.texture_screen);
- if (r_bloomstate.texture_bloom)
- R_FreeTexture(r_bloomstate.texture_bloom);
- memset(&r_bloomstate, 0, sizeof(r_bloomstate));
- return;
- }
-
- r_bloomstate.enabled = true;
- r_bloomstate.hdr = r_hdr.integer != 0;
// allocate textures as needed
if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
// set up a texcoord array for the full resolution screen image
// (we have to keep this around to copy back during final render)
r_bloomstate.screentexcoord2f[0] = 0;
- r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
- r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
- r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
- r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
+ r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
+ r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
+ r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
+ r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
r_bloomstate.screentexcoord2f[5] = 0;
r_bloomstate.screentexcoord2f[6] = 0;
r_bloomstate.screentexcoord2f[7] = 0;
// (which will be additive blended over the screen image)
r_bloomstate.bloomtexcoord2f[0] = 0;
r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
- r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
+ r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
- r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
+ r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
r_bloomstate.bloomtexcoord2f[5] = 0;
r_bloomstate.bloomtexcoord2f[6] = 0;
r_bloomstate.bloomtexcoord2f[7] = 0;
+
+ if (r_hdr.integer || r_bloom.integer)
+ {
+ r_bloomstate.enabled = true;
+ r_bloomstate.hdr = r_hdr.integer != 0;
+ }
}
-void R_Bloom_CopyScreenTexture(float colorscale)
+void R_Bloom_CopyBloomTexture(float colorscale)
{
r_refdef.stats.bloom++;
- R_ResetViewRendering2D();
- R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
- R_Mesh_ColorPointer(NULL, 0, 0);
- R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
- R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
- R_SetupGenericShader(true);
-
- // copy view into the screen texture
- GL_ActiveTexture(0);
- CHECKGLERROR
- qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
- r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
-
- // now scale it down to the bloom texture size
+ // scale down screen texture to the bloom texture size
CHECKGLERROR
qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
GL_BlendFunc(GL_ONE, GL_ZERO);
GL_Color(colorscale, colorscale, colorscale, 1);
// TODO: optimize with multitexture or GLSL
+ R_SetupGenericShader(true);
+ R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
+ R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
static void R_BlendView(void)
{
- if (r_bloomstate.enabled && r_bloomstate.hdr)
+ if (r_bloomstate.texture_screen)
+ {
+ // copy view into the screen texture
+ 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
+ qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
+ r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
+ }
+
+ if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
+ {
+ unsigned int permutation =
+ (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);
+
+ if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
+ {
+ // 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();
+ }
+
+ 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);
+ R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
+ R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
+ R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
+ R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
+ R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
+ if (r_glsl_permutation->loc_Texture_Attenuation >= 0)
+ R_Mesh_TexBind(GL20TU_ATTENUATION, R_GetTexture(r_texture_gammaramps));
+ if (r_glsl_permutation->loc_TintColor >= 0)
+ qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
+ if (r_glsl_permutation->loc_ClientTime >= 0)
+ qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
+ if (r_glsl_permutation->loc_UserVec1 >= 0)
+ {
+ float a=0, b=0, c=0, d=0;
+ sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
+ qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
+ }
+ if (r_glsl_permutation->loc_UserVec2 >= 0)
+ {
+ float a=0, b=0, c=0, d=0;
+ sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
+ qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
+ }
+ if (r_glsl_permutation->loc_UserVec3 >= 0)
+ {
+ float a=0, b=0, c=0, d=0;
+ sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
+ qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
+ }
+ if (r_glsl_permutation->loc_UserVec4 >= 0)
+ {
+ float a=0, b=0, c=0, d=0;
+ sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
+ qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
+ }
+ R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
+ r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.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
R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
}
- else if (r_bloomstate.enabled)
+ 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_CopyScreenTexture(r_bloom_colorscale.value);
+ 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
}
else
r_refdef.fogenabled = false;
+
+ if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
+ {
+ 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 ramprgb[RAMPWIDTH][4];
+ int i;
+
+ r_texture_gammaramps_serial = vid_gammatables_serial;
+
+ VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
+ for(i = 0; i < RAMPWIDTH; ++i)
+ {
+ ramprgb[i][0] = ramp[i] >> 8;
+ ramprgb[i][1] = ramp[i + RAMPWIDTH] >> 8;
+ ramprgb[i][2] = ramp[i + 2 * RAMPWIDTH] >> 8;
+ ramprgb[i][3] = 0;
+ }
+ if (r_texture_gammaramps)
+ {
+ R_UpdateTexture(r_texture_gammaramps, &ramprgb[0][0], 0, 0, RAMPWIDTH, 1);
+ }
+ else
+ {
+ r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &ramprgb[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
+ }
+ }
+ }
+ else
+ {
+ // remove GLSL gamma texture
+ }
}
static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
t->currentmaterialflags |= MATERIALFLAG_WATERSHADER;
*/
}
+ if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled)
+ t->currentalpha *= t->r_water_wateralpha;
if(!r_waterstate.enabled)
t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
if (!(ent->flags & RENDER_LIGHT))