added Bloom effect (r_bloom* cvars)
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Sat, 18 Dec 2004 02:40:48 +0000 (02:40 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Sat, 18 Dec 2004 02:40:48 +0000 (02:40 +0000)
added Bloom effect cvars to graphics options menu
cleaned up r_speeds variables (c_*) which were being declared and externed and cleared all over the place (that's most of these files)

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@4851 d7cf8633-e32d-0410-b094-e92efae38249

cl_screen.c
gl_backend.c
gl_backend.h
gl_rmain.c
gl_textures.c
menu.c
r_shadow.c
render.h

index e00a463..d34f838 100644 (file)
@@ -340,9 +340,6 @@ void R_TimeReport(char *desc)
        }
 }
 
-extern int c_rt_lights, c_rt_clears, c_rt_scissored;
-extern int c_rt_shadowmeshes, c_rt_shadowtris, c_rt_lightmeshes, c_rt_lighttris;
-extern int c_rtcached_shadowmeshes, c_rtcached_shadowtris;
 void R_TimeReport_Start(void)
 {
        r_timereport_active = r_speeds.integer && cls.signon == SIGNONS && cls.state == ca_connected;
@@ -350,23 +347,14 @@ void R_TimeReport_Start(void)
        if (r_timereport_active)
        {
                speedstringcount = 0;
-               sprintf(r_speeds_string,
-                       "org:'%+8.2f %+8.2f %+8.2f' dir:'%+2.3f %+2.3f %+2.3f'\n"
-                       "world:%6i faces%6i nodes%6i leafs%6i dlitwalls\n"
-                       "%5i models%5i bmodels%5i sprites%6i particles%4i dlights\n"
-                       "%6i modeltris%6i meshs%6i meshtris\n",
-                       r_vieworigin[0], r_vieworigin[1], r_vieworigin[2], r_viewforward[0], r_viewforward[1], r_viewforward[2],
-                       c_faces, c_nodes, c_leafs, c_light_polys,
-                       c_models, c_bmodels, c_sprites, c_particles, c_dlights,
-                       c_alias_polys, c_meshs, c_meshelements / 3);
-
-               sprintf(r_speeds_string + strlen(r_speeds_string),
-                       "realtime lighting:%4i lights%4i clears%4i scissored\n"
-                       "dynamic: %6i shadowmeshes%6i shadowtris%6i lightmeshes%6i lighttris\n"
-                       "precomputed: %6i shadowmeshes%6i shadowtris\n",
-                       c_rt_lights, c_rt_clears, c_rt_scissored,
-                       c_rt_shadowmeshes, c_rt_shadowtris, c_rt_lightmeshes, c_rt_lighttris,
-                       c_rtcached_shadowmeshes, c_rtcached_shadowtris);
+               sprintf(r_speeds_string + strlen(r_speeds_string), "org:'%+8.2f %+8.2f %+8.2f' dir:'%+2.3f %+2.3f %+2.3f'\n", r_vieworigin[0], r_vieworigin[1], r_vieworigin[2], r_viewforward[0], r_viewforward[1], r_viewforward[2]);
+               sprintf(r_speeds_string + strlen(r_speeds_string), "world:%6i faces%6i nodes%6i leafs%6i dlitwalls\n", c_faces, c_nodes, c_leafs, c_light_polys);
+               sprintf(r_speeds_string + strlen(r_speeds_string), "%5i models%5i bmodels%5i sprites%6i particles%4i dlights\n", c_models, c_bmodels, c_sprites, c_particles, c_dlights);
+               sprintf(r_speeds_string + strlen(r_speeds_string), "%6i modeltris%6i meshs%6i meshtris\n", c_alias_polys, c_meshs, c_meshelements / 3);
+               sprintf(r_speeds_string + strlen(r_speeds_string), "bloom %s: %i copies (%i pixels) %i draws (%i pixels)\n", c_bloom ? "active" : "inactive", c_bloomcopies, c_bloomcopypixels, c_bloomdraws, c_bloomdrawpixels);
+               sprintf(r_speeds_string + strlen(r_speeds_string), "realtime lighting:%4i lights%4i clears%4i scissored\n", c_rt_lights, c_rt_clears, c_rt_scissored);
+               sprintf(r_speeds_string + strlen(r_speeds_string), "dynamic: %6i shadowmeshes%6i shadowtris%6i lightmeshes%6i lighttris\n", c_rt_shadowmeshes, c_rt_shadowtris, c_rt_lightmeshes, c_rt_lighttris);
+               sprintf(r_speeds_string + strlen(r_speeds_string), "precomputed: %6i shadowmeshes%6i shadowtris\n", c_rtcached_shadowmeshes, c_rtcached_shadowtris);
 
                c_alias_polys = 0;
                c_light_polys = 0;
@@ -377,8 +365,23 @@ void R_TimeReport_Start(void)
                c_bmodels = 0;
                c_sprites = 0;
                c_particles = 0;
+               c_dlights = 0;
                c_meshs = 0;
                c_meshelements = 0;
+               c_rt_lights = 0;
+               c_rt_clears = 0;
+               c_rt_scissored = 0;
+               c_rt_shadowmeshes = 0;
+               c_rt_shadowtris = 0;
+               c_rt_lightmeshes = 0;
+               c_rt_lighttris = 0;
+               c_rtcached_shadowmeshes = 0;
+               c_rtcached_shadowtris = 0;
+               c_bloom = 0;
+               c_bloomcopies = 0;
+               c_bloomcopypixels = 0;
+               c_bloomdraws = 0;
+               c_bloomdrawpixels = 0;
 
                r_timereport_start = Sys_DoubleTime();
        }
index a400d8b..1433875 100644 (file)
@@ -75,8 +75,6 @@ void GL_PrintError(int errornumber, char *filename, int linenumber)
 
 #define BACKENDACTIVECHECK if (!backendactive) Sys_Error("GL backend function called when backend is not active\n");
 
-int c_meshs, c_meshelements;
-
 void SCR_ScreenShot_f (void);
 
 static matrix4x4_t backend_viewmatrix;
index 6928750..8b8d969 100644 (file)
@@ -31,8 +31,6 @@ extern cvar_t gl_mesh_copyarrays;
 extern cvar_t gl_paranoid;
 extern cvar_t gl_printcheckerror;
 
-extern int c_meshelements, c_meshs;
-
 //input to R_Mesh_State
 typedef struct
 {
index 75e6ee6..4c73adc 100644 (file)
@@ -32,7 +32,7 @@ mplane_t frustum[4];
 
 matrix4x4_t r_identitymatrix;
 
-int c_alias_polys, c_light_polys, c_faces, c_nodes, c_leafs, c_models, c_bmodels, c_sprites, c_particles, c_dlights;
+int c_alias_polys, c_light_polys, c_faces, c_nodes, c_leafs, c_models, c_bmodels, c_sprites, c_particles, c_dlights, c_meshs, c_meshelements, c_rt_lights, c_rt_clears, c_rt_scissored, c_rt_shadowmeshes, c_rt_shadowtris, c_rt_lightmeshes, c_rt_lighttris, c_rtcached_shadowmeshes, c_rtcached_shadowtris, c_bloom, c_bloomcopies, c_bloomcopypixels, c_bloomdraws, c_bloomdrawpixels;
 
 // true during envmap command capture
 qboolean envmap;
@@ -101,6 +101,14 @@ cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1"};
 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1"};
 cvar_t r_watershader = {CVAR_SAVE, "r_watershader", "1"};
 
+cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0"};
+cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "2"};
+cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "8"};
+cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "256"};
+cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "4"};
+rtexturepool_t *r_main_texturepool;
+rtexture_t *r_bloom_texture_screen;
+rtexture_t *r_bloom_texture_bloom;
 
 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
 {
@@ -202,10 +210,18 @@ void FOG_registercvars(void)
 
 void gl_main_start(void)
 {
+       r_main_texturepool = R_AllocTexturePool();
+       r_bloom_texture_screen = NULL;
+       r_bloom_texture_bloom = NULL;
 }
 
 void gl_main_shutdown(void)
 {
+       // this seems to cause a already freed crash after a couple vid_restarts...
+       //R_FreeTexturePool(&r_main_texturepool);
+       r_main_texturepool = NULL;
+       r_bloom_texture_screen = NULL;
+       r_bloom_texture_bloom = NULL;
 }
 
 extern void CL_ParseEntityLump(char *entitystring);
@@ -253,6 +269,11 @@ void GL_Main_Init(void)
        Cvar_RegisterVariable(&r_waterscroll);
        Cvar_RegisterVariable(&r_watershader);
        Cvar_RegisterVariable(&r_drawcollisionbrushes);
+       Cvar_RegisterVariable(&r_bloom);
+       Cvar_RegisterVariable(&r_bloom_intensity);
+       Cvar_RegisterVariable(&r_bloom_blur);
+       Cvar_RegisterVariable(&r_bloom_resolution);
+       Cvar_RegisterVariable(&r_bloom_power);
        if (gamemode == GAME_NEHAHRA || gamemode == GAME_NEXUIZ || gamemode == GAME_TENEBRAE)
                Cvar_SetValue("r_fullbrights", 0);
        R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
@@ -506,33 +527,194 @@ static void R_SetFrustum(void)
 static void R_BlendView(void)
 {
        rmeshstate_t m;
-       float r;
-       float vertex3f[3*3];
 
-       if (r_refdef.viewblend[3] < 0.01f)
+       if (r_refdef.viewblend[3] < 0.01f && !r_bloom.integer)
                return;
 
-       R_Mesh_Matrix(&r_identitymatrix);
-
-       memset(&m, 0, sizeof(m));
-       m.pointer_vertex = vertex3f;
-       R_Mesh_State(&m);
-
-       GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+       GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
        GL_DepthMask(true);
-       GL_DepthTest(false); // magic
-       GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
-       r = 64;
-       vertex3f[0] = r_vieworigin[0] + r_viewforward[0] * 1.5 + r_viewleft[0] * r - r_viewup[0] * r;
-       vertex3f[1] = r_vieworigin[1] + r_viewforward[1] * 1.5 + r_viewleft[1] * r - r_viewup[1] * r;
-       vertex3f[2] = r_vieworigin[2] + r_viewforward[2] * 1.5 + r_viewleft[2] * r - r_viewup[2] * r;
-       vertex3f[3] = r_vieworigin[0] + r_viewforward[0] * 1.5 + r_viewleft[0] * r + r_viewup[0] * r * 3;
-       vertex3f[4] = r_vieworigin[1] + r_viewforward[1] * 1.5 + r_viewleft[1] * r + r_viewup[1] * r * 3;
-       vertex3f[5] = r_vieworigin[2] + r_viewforward[2] * 1.5 + r_viewleft[2] * r + r_viewup[2] * r * 3;
-       vertex3f[6] = r_vieworigin[0] + r_viewforward[0] * 1.5 - r_viewleft[0] * r * 3 - r_viewup[0] * r;
-       vertex3f[7] = r_vieworigin[1] + r_viewforward[1] * 1.5 - r_viewleft[1] * r * 3 - r_viewup[1] * r;
-       vertex3f[8] = r_vieworigin[2] + r_viewforward[2] * 1.5 - r_viewleft[2] * r * 3 - r_viewup[2] * r;
-       R_Mesh_Draw(3, 1, polygonelements);
+       GL_DepthTest(false);
+       R_Mesh_Matrix(&r_identitymatrix);
+       varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
+       varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
+       varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
+       varray_vertex3f[9] = 0;varray_vertex3f[10] = 1;varray_vertex3f[11] = 0;
+       if (r_bloom.integer && r_bloom_resolution.value >= 32 && r_bloom_power.integer >= 1 && r_bloom_power.integer < 100 && r_bloom_blur.value >= 0 && r_bloom_blur.value < 512)
+       {
+               int screenwidth, screenheight, bloomwidth, bloomheight, x, dobloomblend, range;
+               float xoffset, yoffset, r;
+               c_bloom++;
+               for (screenwidth = 1;screenwidth < vid.realwidth;screenwidth *= 2);
+               for (screenheight = 1;screenheight < vid.realheight;screenheight *= 2);
+               bloomwidth = min(r_view_width, r_bloom_resolution.integer);
+               bloomheight = min(r_view_height, r_bloom_resolution.integer);
+               varray_texcoord2f[0][0] = 0;
+               varray_texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
+               varray_texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
+               varray_texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
+               varray_texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
+               varray_texcoord2f[0][5] = 0;
+               varray_texcoord2f[0][6] = 0;
+               varray_texcoord2f[0][7] = 0;
+               varray_texcoord2f[1][0] = 0;
+               varray_texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
+               varray_texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
+               varray_texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
+               varray_texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
+               varray_texcoord2f[1][5] = 0;
+               varray_texcoord2f[1][6] = 0;
+               varray_texcoord2f[1][7] = 0;
+               if (!r_bloom_texture_screen)
+                       r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
+               if (!r_bloom_texture_bloom)
+                       r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
+               memset(&m, 0, sizeof(m));
+               m.pointer_vertex = varray_vertex3f;
+               m.pointer_texcoord[0] = varray_texcoord2f[0];
+               m.tex[0] = R_GetTexture(r_bloom_texture_screen);
+               R_Mesh_State(&m);
+               // copy view to a texture
+               GL_ActiveTexture(0);
+               qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.realheight - (r_view_y + r_view_height), r_view_width, r_view_height);
+               c_bloomcopies++;
+               c_bloomcopypixels += r_view_width * r_view_height;
+               // now scale it down to the bloom size and raise to a power of itself
+               qglViewport(r_view_x, vid.realheight - (r_view_y + bloomheight), bloomwidth, bloomheight);
+               // TODO: optimize with multitexture or GLSL
+               GL_BlendFunc(GL_ONE, GL_ZERO);
+               GL_Color(1, 1, 1, 1);
+               R_Mesh_Draw(4, 2, polygonelements);
+               c_bloomdraws++;
+               c_bloomdrawpixels += bloomwidth * bloomheight;
+               GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
+               for (x = 1;x < r_bloom_power.integer;x++)
+               {
+                       R_Mesh_Draw(4, 2, polygonelements);
+                       c_bloomdraws++;
+                       c_bloomdrawpixels += bloomwidth * bloomheight;
+               }
+               // copy the bloom view to a texture
+               memset(&m, 0, sizeof(m));
+               m.pointer_vertex = varray_vertex3f;
+               m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
+               m.pointer_texcoord[0] = varray_texcoord2f[2];
+               R_Mesh_State(&m);
+               GL_ActiveTexture(0);
+               qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.realheight - (r_view_y + bloomheight), bloomwidth, bloomheight);
+               c_bloomcopies++;
+               c_bloomcopypixels += bloomwidth * bloomheight;
+               // blend on at multiple offsets vertically
+               // TODO: do offset blends using GLSL
+               range = r_bloom_blur.integer;//(int)(r_bloom_blur.value * bloomwidth / 320);
+               GL_BlendFunc(GL_ONE, GL_ZERO);
+               for (x = -range;x <= range;x++)
+               {
+                       xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
+                       yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
+                       varray_texcoord2f[2][0] = xoffset+0;
+                       varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
+                       varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
+                       varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
+                       varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
+                       varray_texcoord2f[2][5] = yoffset+0;
+                       varray_texcoord2f[2][6] = xoffset+0;
+                       varray_texcoord2f[2][7] = yoffset+0;
+                       r = r_bloom_intensity.value/(range*2+1)*(1 - fabs(x*x)/(float)(range*range));
+                       if (r < 0.01f)
+                               continue;
+                       GL_Color(r, r, r, 1);
+                       R_Mesh_Draw(4, 2, polygonelements);
+                       c_bloomdraws++;
+                       c_bloomdrawpixels += bloomwidth * bloomheight;
+                       GL_BlendFunc(GL_ONE, GL_ONE);
+               }
+               // copy the blurred bloom view to a texture
+               GL_ActiveTexture(0);
+               qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.realheight - (r_view_y + bloomheight), bloomwidth, bloomheight);
+               c_bloomcopies++;
+               c_bloomcopypixels += bloomwidth * bloomheight;
+               // blend on at multiple offsets horizontally
+               // TODO: do offset blends using GLSL
+               range = r_bloom_blur.integer * bloomheight / r_view_height;//(int)(r_bloom_blur.value * bloomwidth / 320);
+               GL_BlendFunc(GL_ONE, GL_ZERO);
+               for (x = -range;x <= range;x++)
+               {
+                       xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
+                       yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
+                       varray_texcoord2f[2][0] = xoffset+0;
+                       varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
+                       varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
+                       varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
+                       varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
+                       varray_texcoord2f[2][5] = yoffset+0;
+                       varray_texcoord2f[2][6] = xoffset+0;
+                       varray_texcoord2f[2][7] = yoffset+0;
+                       r = r_bloom_intensity.value/(range*2+1)*(1 - fabs(x*x)/(float)(range*range));
+                       if (r < 0.01f)
+                               continue;
+                       GL_Color(r, r, r, 1);
+                       R_Mesh_Draw(4, 2, polygonelements);
+                       c_bloomdraws++;
+                       c_bloomdrawpixels += bloomwidth * bloomheight;
+                       GL_BlendFunc(GL_ONE, GL_ONE);
+               }
+               // copy the blurred bloom view to a texture
+               GL_ActiveTexture(0);
+               qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.realheight - (r_view_y + bloomheight), bloomwidth, bloomheight);
+               c_bloomcopies++;
+               c_bloomcopypixels += bloomwidth * bloomheight;
+               // go back to full view area
+               qglViewport(r_view_x, vid.realheight - (r_view_y + r_view_height), r_view_width, r_view_height);
+               // put the original view back in place
+               memset(&m, 0, sizeof(m));
+               m.pointer_vertex = varray_vertex3f;
+               m.tex[0] = R_GetTexture(r_bloom_texture_screen);
+               m.pointer_texcoord[0] = varray_texcoord2f[0];
+#if 0
+               dobloomblend = false;
+#else
+               // do both in one pass if possible
+               if (r_textureunits.integer >= 2 && gl_combine.integer)
+               {
+                       dobloomblend = false;
+                       m.texcombinergb[1] = GL_ADD;
+                       m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
+                       m.pointer_texcoord[1] = varray_texcoord2f[1];
+               }
+               else
+                       dobloomblend = true;
+#endif
+               R_Mesh_State(&m);
+               GL_BlendFunc(GL_ONE, GL_ZERO);
+               GL_Color(1,1,1,1);
+               R_Mesh_Draw(4, 2, polygonelements);
+               c_bloomdraws++;
+               c_bloomdrawpixels += r_view_width * r_view_height;
+               // now blend on the bloom texture if multipass
+               if (dobloomblend)
+               {
+                       memset(&m, 0, sizeof(m));
+                       m.pointer_vertex = varray_vertex3f;
+                       m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
+                       m.pointer_texcoord[0] = varray_texcoord2f[1];
+                       R_Mesh_State(&m);
+                       GL_BlendFunc(GL_ONE, GL_ONE);
+                       GL_Color(1,1,1,1);
+                       R_Mesh_Draw(4, 2, polygonelements);
+                       c_bloomdraws++;
+                       c_bloomdrawpixels += r_view_width * r_view_height;
+               }
+       }
+       if (r_refdef.viewblend[3] >= 0.01f)
+       {
+               // apply a color tint to the whole view
+               memset(&m, 0, sizeof(m));
+               m.pointer_vertex = varray_vertex3f;
+               R_Mesh_State(&m);
+               GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+               GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
+               R_Mesh_Draw(4, 2, polygonelements);
+       }
 }
 
 void R_RenderScene(void);
index 0c9147c..8192754 100644 (file)
@@ -713,7 +713,7 @@ static void R_Upload(gltexture_t *glt, qbyte *data)
                if (prevbuffer == NULL)
                {
                        R_MakeResizeBufferBigger(glt->image->width * glt->image->height * glt->image->depth * glt->image->bytesperpixel);
-                       memset(resizebuffer, 255, glt->width * glt->height * glt->image->depth * glt->image->bytesperpixel);
+                       memset(resizebuffer, 0, glt->width * glt->height * glt->image->depth * glt->image->bytesperpixel);
                        prevbuffer = resizebuffer;
                }
                else if (glt->textype->textype == TEXTYPE_PALETTE)
@@ -760,7 +760,7 @@ static void R_Upload(gltexture_t *glt, qbyte *data)
                        width = glt->image->width;
                        height = glt->image->height;
                        depth = glt->image->depth;
-                       memset(resizebuffer, 255, width * height * depth * glt->image->bytesperpixel);
+                       memset(resizebuffer, 0, width * height * depth * glt->image->bytesperpixel);
                        prevbuffer = resizebuffer;
                }
                else
diff --git a/menu.c b/menu.c
index 4e5fb58..3bbb549 100644 (file)
--- a/menu.c
+++ b/menu.c
@@ -156,8 +156,8 @@ float menu_x, menu_y, menu_width, menu_height;
 
 void M_Background(int width, int height)
 {
-       menu_width = width;
-       menu_height = height;
+       menu_width = bound(1, width, vid.conwidth);
+       menu_height = bound(1, height, vid.conheight);
        menu_x = (vid.conwidth - menu_width) * 0.5;
        menu_y = (vid.conheight - menu_height) * 0.5;
        //DrawQ_Fill(menu_x, menu_y, menu_width, menu_height, 0, 0, 0, 0.5, 0);
@@ -1358,7 +1358,7 @@ void M_Options_Draw (void)
        int visible;
        cachepic_t      *p;
 
-       M_Background(320, 240);
+       M_Background(320, bound(200, 32 + OPTIONS_ITEMS * 8, vid.conheight));
 
        M_DrawPic(16, 4, "gfx/qplaque.lmp");
        p = Draw_CachePic("gfx/p_option.lmp");
@@ -1366,7 +1366,7 @@ void M_Options_Draw (void)
 
        optnum = 0;
        optcursor = options_cursor;
-       visible = (vid.conheight - 32) / 8;
+       visible = (menu_height - 32) / 8;
        opty = 32 - bound(0, optcursor - (visible >> 1), max(0, OPTIONS_ITEMS - visible)) * 8;
 
        M_Options_PrintCommand( "Customize controls", true);
@@ -1557,7 +1557,7 @@ void M_Options_Effects_Draw (void)
        int visible;
        cachepic_t      *p;
 
-       M_Background(320, 200);
+       M_Background(320, bound(200, 32 + OPTIONS_EFFECTS_ITEMS * 8, vid.conheight));
 
        M_DrawPic(16, 4, "gfx/qplaque.lmp");
        p = Draw_CachePic("gfx/p_option.lmp");
@@ -1565,7 +1565,7 @@ void M_Options_Effects_Draw (void)
 
        optcursor = options_effects_cursor;
        optnum = 0;
-       visible = (vid.conheight - 32) / 8;
+       visible = (menu_height - 32) / 8;
        opty = 32 - bound(0, optcursor - (visible >> 1), max(0, OPTIONS_EFFECTS_ITEMS - visible)) * 8;
 
        M_Options_PrintSlider(  "      Lights Per Model", true, r_modellights.value, 0, 8);
@@ -1645,7 +1645,7 @@ void M_Options_Effects_Key (int k, char ascii)
 }
 
 
-#define        OPTIONS_GRAPHICS_ITEMS  7
+#define        OPTIONS_GRAPHICS_ITEMS  12
 
 int options_graphics_cursor;
 
@@ -1663,6 +1663,11 @@ extern cvar_t r_shadow_realtime_world;
 extern cvar_t r_shadow_realtime_world_dlightshadows;
 extern cvar_t r_shadow_realtime_world_lightmaps;
 extern cvar_t r_shadow_realtime_world_shadows;
+extern cvar_t r_bloom;
+extern cvar_t r_bloom_intensity;
+extern cvar_t r_bloom_power;
+extern cvar_t r_bloom_blur;
+extern cvar_t r_bloom_resolution;
 
 void M_Menu_Options_Graphics_AdjustSliders (int dir)
 {
@@ -1678,6 +1683,11 @@ void M_Menu_Options_Graphics_AdjustSliders (int dir)
        else if (options_graphics_cursor == optnum++) Cvar_SetValueQuick (&r_shadow_realtime_world_dlightshadows,       !r_shadow_realtime_world_dlightshadows.integer);
        else if (options_graphics_cursor == optnum++) Cvar_SetValueQuick (&r_shadow_realtime_world_lightmaps,           bound(0, r_shadow_realtime_world_lightmaps.value + dir * 0.1, 1));
        else if (options_graphics_cursor == optnum++) Cvar_SetValueQuick (&r_shadow_realtime_world_shadows,                     !r_shadow_realtime_world_shadows.integer);
+       else if (options_graphics_cursor == optnum++) Cvar_SetValueQuick (&r_bloom,                                 !r_bloom.integer);
+       else if (options_graphics_cursor == optnum++) Cvar_SetValueQuick (&r_bloom_intensity,                       bound(1, r_bloom_intensity.value + dir * 1, 16));
+       else if (options_graphics_cursor == optnum++) Cvar_SetValueQuick (&r_bloom_power,                           bound(1, r_bloom_power.value + dir * 1, 16));
+       else if (options_graphics_cursor == optnum++) Cvar_SetValueQuick (&r_bloom_blur,                            bound(1, r_bloom_blur.value + dir * 1, 16));
+       else if (options_graphics_cursor == optnum++) Cvar_SetValueQuick (&r_bloom_resolution,                      bound(64, r_bloom_resolution.value + dir * 64, 2048));
 }
 
 
@@ -1686,7 +1696,7 @@ void M_Options_Graphics_Draw (void)
        int visible;
        cachepic_t      *p;
 
-       M_Background(320, 200);
+       M_Background(320, bound(200, 32 + OPTIONS_GRAPHICS_ITEMS * 8, vid.conheight));
 
        M_DrawPic(16, 4, "gfx/qplaque.lmp");
        p = Draw_CachePic("gfx/p_option.lmp");
@@ -1694,7 +1704,7 @@ void M_Options_Graphics_Draw (void)
 
        optcursor = options_graphics_cursor;
        optnum = 0;
-       visible = (vid.conheight - 32) / 8;
+       visible = (menu_height - 32) / 8;
        opty = 32 - bound(0, optcursor - (visible >> 1), max(0, OPTIONS_GRAPHICS_ITEMS - visible)) * 8;
 
        M_Options_PrintSlider(  "             Gloss Mode", true, r_shadow_gloss.integer, 0, 2);
@@ -1704,6 +1714,11 @@ void M_Options_Graphics_Draw (void)
        M_Options_PrintCheckbox("RT World DLight Shadows", true, r_shadow_realtime_world_dlightshadows.integer);
        M_Options_PrintSlider(  "     RT World Lightmaps", true, r_shadow_realtime_world_lightmaps.value, 0, 1);
        M_Options_PrintCheckbox("        RT World Shadow", true, r_shadow_realtime_world_shadows.integer);
+       M_Options_PrintCheckbox("           Bloom Effect", true, r_bloom.integer);
+       M_Options_PrintSlider(  "        Bloom Intensity", true, r_bloom_intensity.value, 1, 16);
+       M_Options_PrintSlider(  "            Bloom Power", true, r_bloom_power.value, 1, 16);
+       M_Options_PrintSlider(  "             Bloom Blur", true, r_bloom_blur.value, 1, 16);
+       M_Options_PrintSlider(  "       Bloom Resolution", true, r_bloom_resolution.value, 64, 2048);
 }
 
 
@@ -1872,7 +1887,7 @@ void M_Options_ColorControl_Draw (void)
 
        optcursor = options_colorcontrol_cursor;
        optnum = 0;
-       visible = (vid.conheight - 32) / 8;
+       visible = (menu_height - 32) / 8;
        opty = 32 - bound(0, optcursor - (visible >> 1), max(0, OPTIONS_COLORCONTROL_ITEMS - visible)) * 8;
 
        M_Options_PrintCommand( "     Reset to defaults", true);
@@ -3813,9 +3828,9 @@ void M_ServerList_Draw (void)
        s = va("%i/%i masters %i/%i servers", masterreplycount, masterquerycount, serverreplycount, serverquerycount);
        M_PrintRed((640 - strlen(s) * 8) / 2, 32, s);
        if (*m_return_reason)
-               M_Print(16, vid.conheight - 8, m_return_reason);
+               M_Print(16, menu_height - 8, m_return_reason);
        y = 48;
-       visible = (vid.conheight - 16 - y) / 8;
+       visible = (menu_height - 16 - y) / 8;
        start = bound(0, slist_cursor - (visible >> 1), hostCacheCount - visible);
        end = min(start + visible, hostCacheCount);
 
index 43d416e..c447789 100644 (file)
@@ -199,10 +199,6 @@ cvar_t r_editlights_quakelightsizescale = {CVAR_SAVE, "r_editlights_quakelightsi
 cvar_t r_editlights_rtlightssizescale = {CVAR_SAVE, "r_editlights_rtlightssizescale", "0.7"};
 cvar_t r_editlights_rtlightscolorscale = {CVAR_SAVE, "r_editlights_rtlightscolorscale", "2"};
 
-int c_rt_lights, c_rt_clears, c_rt_scissored;
-int c_rt_shadowmeshes, c_rt_shadowtris, c_rt_lightmeshes, c_rt_lighttris;
-int c_rtcached_shadowmeshes, c_rtcached_shadowtris;
-
 float r_shadow_attenpower, r_shadow_attenscale;
 
 rtlight_t *r_shadow_compilingrtlight;
@@ -882,10 +878,6 @@ void R_Shadow_Stage_Begin(void)
        qglEnable(GL_CULL_FACE);
        GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
        r_shadowstage = SHADOWSTAGE_NONE;
-
-       c_rt_lights = c_rt_clears = c_rt_scissored = 0;
-       c_rt_shadowmeshes = c_rt_shadowtris = c_rt_lightmeshes = c_rt_lighttris = 0;
-       c_rtcached_shadowmeshes = c_rtcached_shadowtris = 0;
 }
 
 void R_Shadow_Stage_ShadowVolumes(void)
index 5a4d978..e9cd43b 100644 (file)
--- a/render.h
+++ b/render.h
@@ -77,9 +77,10 @@ void R_FillColors(float *out, int verts, float r, float g, float b, float a);
 
 //=============================================================================
 
-extern int                     r_framecount;
-extern mplane_t        frustum[4];
-extern int             c_alias_polys, c_light_polys, c_faces, c_nodes, c_leafs, c_models, c_bmodels, c_sprites, c_particles, c_dlights;
+extern int r_framecount;
+extern mplane_t frustum[4];
+
+extern int c_alias_polys, c_light_polys, c_faces, c_nodes, c_leafs, c_models, c_bmodels, c_sprites, c_particles, c_dlights, c_meshs, c_meshelements, c_rt_lights, c_rt_clears, c_rt_scissored, c_rt_shadowmeshes, c_rt_shadowtris, c_rt_lightmeshes, c_rt_lighttris, c_rtcached_shadowmeshes, c_rtcached_shadowtris, c_bloom, c_bloomcopies, c_bloomcopypixels, c_bloomdraws, c_bloomdrawpixels;
 
 // brightness of world lightmaps and related lighting
 // (often reduced when world rtlights are enabled)