X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=gl_rmain.c;h=1f504139682957dec5ec743b091593ead21cc94f;hp=ec27666473e46b340e91993ef3c470abdd3f4ac7;hb=582c8871d441ba4659a646462143d917712d5c4b;hpb=9281ac3710ded410932b6ddd1571bf8393affe00 diff --git a/gl_rmain.c b/gl_rmain.c index ec276664..1f504139 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -30,7 +30,7 @@ mplane_t frustum[5]; 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, 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; +renderstats_t renderstats; // true during envmap command capture qboolean envmap; @@ -62,8 +62,6 @@ int r_view_z; int r_view_width; int r_view_height; int r_view_depth; -float r_view_fov_x; -float r_view_fov_y; matrix4x4_t r_view_matrix; // @@ -71,46 +69,44 @@ matrix4x4_t r_view_matrix; // refdef_t r_refdef; -// 8.8 fraction of base light value -unsigned short d_lightstylevalue[256]; +cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"}; +cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"}; +cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"}; +cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"}; +cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"}; +cvar_t r_fullbright = {0, "r_fullbright","0", "make everything bright cheat (not allowed in multiplayer)"}; +cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"}; +cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"}; +cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"}; +cvar_t r_drawcollisionbrushes = {0, "r_drawcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"}; -cvar_t r_showtris = {0, "r_showtris", "0"}; -cvar_t r_drawentities = {0, "r_drawentities","1"}; -cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1"}; -cvar_t r_speeds = {0, "r_speeds","0"}; -cvar_t r_fullbright = {0, "r_fullbright","0"}; -cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1"}; -cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1"}; -cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1"}; -cvar_t r_drawcollisionbrushes = {0, "r_drawcollisionbrushes", "0"}; +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 gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"}; +cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"}; +cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"}; +cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"}; +cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"}; -cvar_t gl_fogenable = {0, "gl_fogenable", "0"}; -cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25"}; -cvar_t gl_fogred = {0, "gl_fogred","0.3"}; -cvar_t gl_foggreen = {0, "gl_foggreen","0.3"}; -cvar_t gl_fogblue = {0, "gl_fogblue","0.3"}; -cvar_t gl_fogstart = {0, "gl_fogstart", "0"}; -cvar_t gl_fogend = {0, "gl_fogend","0"}; +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_textureunits = {0, "r_textureunits", "32"}; +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"}; +cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"}; -cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1"}; -cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1"}; -cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1"}; +cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"}; +cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "1.5", "how bright the glow is"}; +cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"}; +cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"}; +cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "2", "how much to darken the image before blurring to make the bloom effect"}; -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", "320"}; -cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "4"}; +cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"}; -cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1"}; +cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"}; -cvar_t developer_texturelogging = {0, "developer_texturelogging", "0"}; +cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"}; -cvar_t gl_lightmaps = {0, "gl_lightmaps", "0"}; - -cvar_t r_test = {0, "r_test", "0"}; // used for testing renderer code changes, otherwise does nothing +cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"}; // used for testing renderer code changes, otherwise does nothing rtexturepool_t *r_main_texturepool; rtexture_t *r_bloom_texture_screen; @@ -121,6 +117,8 @@ rtexture_t *r_texture_black; rtexture_t *r_texture_notexture; rtexture_t *r_texture_whitecube; rtexture_t *r_texture_normalizationcube; +rtexture_t *r_texture_fogattenuation; +rtexture_t *r_texture_fogintensity; void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b) { @@ -151,6 +149,11 @@ void R_FillColors(float *out, int verts, float r, float g, float b, float a) vec3_t fogcolor; vec_t fogdensity; +vec_t fogrange; +vec_t fograngerecip; +int fogtableindex; +vec_t fogtabledistmultiplier; +float fogtable[FOGTABLEWIDTH]; float fog_density, fog_red, fog_green, fog_blue; qboolean fogenabled; qboolean oldgl_fogenable; @@ -185,6 +188,12 @@ void R_UpdateFog(void) { fogenabled = true; fogdensity = -4000.0f / (fog_density * fog_density); + // this is the point where the fog reaches 0.9986 alpha, which we + // consider a good enough cutoff point for the texture + // (0.9986 * 256 == 255.6) + fogrange = 400 / fog_density; + fograngerecip = 1.0f / fogrange; + fogtabledistmultiplier = FOGTABLEWIDTH * fograngerecip; // fog color was already set } else @@ -208,6 +217,9 @@ void FOG_clear(void) // FIXME: move this to client? void FOG_registercvars(void) { + int x; + double r, alpha; + if (gamemode == GAME_NEHAHRA) { Cvar_RegisterVariable (&gl_fogenable); @@ -218,11 +230,20 @@ void FOG_registercvars(void) Cvar_RegisterVariable (&gl_fogstart); Cvar_RegisterVariable (&gl_fogend); } + + r = (-1.0/256.0) * (FOGTABLEWIDTH * FOGTABLEWIDTH); + for (x = 0;x < FOGTABLEWIDTH;x++) + { + alpha = exp(r / ((double)x*(double)x)); + if (x == FOGTABLEWIDTH - 1) + alpha = 1; + fogtable[x] = bound(0, alpha, 1); + } } static void R_BuildBlankTextures(void) { - qbyte data[4]; + unsigned char data[4]; data[0] = 128; // normal X data[1] = 128; // normal Y data[2] = 255; // normal Z @@ -243,7 +264,7 @@ static void R_BuildBlankTextures(void) static void R_BuildNoTexture(void) { int x, y; - qbyte pix[16][16][4]; + unsigned char pix[16][16][4]; // this makes a light grey/dark grey checkerboard texture for (y = 0;y < 16;y++) { @@ -270,7 +291,7 @@ static void R_BuildNoTexture(void) static void R_BuildWhiteCube(void) { - qbyte data[6*1*1*4]; + unsigned char data[6*1*1*4]; data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255; data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255; data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255; @@ -286,7 +307,7 @@ static void R_BuildNormalizationCube(void) vec3_t v; vec_t s, t, intensity; #define NORMSIZE 64 - qbyte data[6][NORMSIZE][NORMSIZE][4]; + unsigned char data[6][NORMSIZE][NORMSIZE][4]; for (side = 0;side < 6;side++) { for (y = 0;y < NORMSIZE;y++) @@ -297,6 +318,7 @@ static void R_BuildNormalizationCube(void) t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f; switch(side) { + default: case 0: v[0] = 1; v[1] = -t; @@ -339,6 +361,34 @@ static void R_BuildNormalizationCube(void) r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL); } +static void R_BuildFogTexture(void) +{ + int x, b; + double r, alpha; +#define FOGWIDTH 64 + unsigned char data1[FOGWIDTH][4]; + unsigned char data2[FOGWIDTH][4]; + r = (-1.0/256.0) * (FOGWIDTH * FOGWIDTH); + for (x = 0;x < FOGWIDTH;x++) + { + alpha = exp(r / ((double)x*(double)x)); + if (x == FOGWIDTH - 1) + alpha = 1; + b = (int)(256.0 * alpha); + b = bound(0, b, 255); + data1[x][0] = 255 - b; + data1[x][1] = 255 - b; + data1[x][2] = 255 - b; + data1[x][3] = 255; + data2[x][0] = b; + data2[x][1] = b; + data2[x][2] = b; + data2[x][3] = 255; + } + r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL); + r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL); +} + void gl_main_start(void) { r_main_texturepool = R_AllocTexturePool(); @@ -351,6 +401,7 @@ void gl_main_start(void) R_BuildWhiteCube(); R_BuildNormalizationCube(); } + R_BuildFogTexture(); } void gl_main_shutdown(void) @@ -379,7 +430,7 @@ void gl_main_newmap(void) if (l >= 0 && !strcmp(entname + l, ".bsp")) { strcpy(entname + l, ".ent"); - if ((entities = FS_LoadFile(entname, tempmempool, true))) + if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL))) { CL_ParseEntityLump(entities); Mem_Free(entities); @@ -397,6 +448,7 @@ void GL_Main_Init(void) // FIXME: move this to client? FOG_registercvars(); Cvar_RegisterVariable(&r_showtris); + Cvar_RegisterVariable(&r_shownormals); Cvar_RegisterVariable(&r_drawentities); Cvar_RegisterVariable(&r_drawviewmodel); Cvar_RegisterVariable(&r_speeds); @@ -581,7 +633,6 @@ static void R_MarkEntities (void) for (i = 0;i < r_refdef.numentities;i++) { ent = r_refdef.entities[i]; - Mod_CheckLoaded(ent->model); // some of the renderer still relies on origin... Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin); // some of the renderer still relies on scale... @@ -599,7 +650,6 @@ static void R_MarkEntities (void) for (i = 0;i < r_refdef.numentities;i++) { ent = r_refdef.entities[i]; - Mod_CheckLoaded(ent->model); // some of the renderer still relies on origin... Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin); // some of the renderer still relies on scale... @@ -649,6 +699,7 @@ void R_DrawModels(void) ent = r_refdef.entities[i]; if (ent->visframe == r_framecount) { + renderstats.entities++; if (ent->model && ent->model->Draw != NULL) ent->model->Draw(ent); else @@ -663,41 +714,137 @@ static void R_SetFrustum(void) Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin); VectorNegate(r_viewleft, r_viewright); - // LordHavoc: note to all quake engine coders, the special case for 90 - // degrees assumed a square view (wrong), so I removed it, Quake2 has it - // disabled as well. +#if 0 + frustum[0].normal[0] = 0 - 1.0 / r_refdef.frustum_x; + frustum[0].normal[1] = 0 - 0; + frustum[0].normal[2] = -1 - 0; + frustum[1].normal[0] = 0 + 1.0 / r_refdef.frustum_x; + frustum[1].normal[1] = 0 + 0; + frustum[1].normal[2] = -1 + 0; + frustum[2].normal[0] = 0 - 0; + frustum[2].normal[1] = 0 - 1.0 / r_refdef.frustum_y; + frustum[2].normal[2] = -1 - 0; + frustum[3].normal[0] = 0 + 0; + frustum[3].normal[1] = 0 + 1.0 / r_refdef.frustum_y; + frustum[3].normal[2] = -1 + 0; +#endif - // rotate R_VIEWFORWARD right by FOV_X/2 degrees - RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_view_fov_x / 2)); +#if 0 + zNear = 1.0; + nudge = 1.0 - 1.0 / (1<<23); + frustum[4].normal[0] = 0 - 0; + frustum[4].normal[1] = 0 - 0; + frustum[4].normal[2] = -1 - -nudge; + frustum[4].dist = 0 - -2 * zNear * nudge; + frustum[5].normal[0] = 0 + 0; + frustum[5].normal[1] = 0 + 0; + frustum[5].normal[2] = -1 + -nudge; + frustum[5].dist = 0 + -2 * zNear * nudge; +#endif + + + +#if 0 + frustum[0].normal[0] = m[3] - m[0]; + frustum[0].normal[1] = m[7] - m[4]; + frustum[0].normal[2] = m[11] - m[8]; + frustum[0].dist = m[15] - m[12]; + + frustum[1].normal[0] = m[3] + m[0]; + frustum[1].normal[1] = m[7] + m[4]; + frustum[1].normal[2] = m[11] + m[8]; + frustum[1].dist = m[15] + m[12]; + + frustum[2].normal[0] = m[3] - m[1]; + frustum[2].normal[1] = m[7] - m[5]; + frustum[2].normal[2] = m[11] - m[9]; + frustum[2].dist = m[15] - m[13]; + + frustum[3].normal[0] = m[3] + m[1]; + frustum[3].normal[1] = m[7] + m[5]; + frustum[3].normal[2] = m[11] + m[9]; + frustum[3].dist = m[15] + m[13]; + + frustum[4].normal[0] = m[3] - m[2]; + frustum[4].normal[1] = m[7] - m[6]; + frustum[4].normal[2] = m[11] - m[10]; + frustum[4].dist = m[15] - m[14]; + + frustum[5].normal[0] = m[3] + m[2]; + frustum[5].normal[1] = m[7] + m[6]; + frustum[5].normal[2] = m[11] + m[10]; + frustum[5].dist = m[15] + m[14]; +#endif + + + + VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_x, r_viewleft, frustum[0].normal); + VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_x, r_viewleft, frustum[1].normal); + VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_y, r_viewup, frustum[2].normal); + VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_y, r_viewup, frustum[3].normal); + VectorCopy(r_viewforward, frustum[4].normal); + VectorNormalize(frustum[0].normal); + VectorNormalize(frustum[1].normal); + VectorNormalize(frustum[2].normal); + VectorNormalize(frustum[3].normal); frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal); + frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal); + frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal); + frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal); + frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + 1.0f; PlaneClassify(&frustum[0]); + PlaneClassify(&frustum[1]); + PlaneClassify(&frustum[2]); + PlaneClassify(&frustum[3]); + PlaneClassify(&frustum[4]); + + // 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. + + // rotate R_VIEWFORWARD right by FOV_X/2 degrees + //RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_refdef.fov_x / 2)); + //frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal); + //PlaneClassify(&frustum[0]); // rotate R_VIEWFORWARD left by FOV_X/2 degrees - RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_view_fov_x / 2)); - frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal); - PlaneClassify(&frustum[1]); + //RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_refdef.fov_x / 2)); + //frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal); + //PlaneClassify(&frustum[1]); // rotate R_VIEWFORWARD up by FOV_X/2 degrees - RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_view_fov_y / 2)); - frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal); - PlaneClassify(&frustum[2]); + //RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_refdef.fov_y / 2)); + //frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal); + //PlaneClassify(&frustum[2]); // rotate R_VIEWFORWARD down by FOV_X/2 degrees - RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_view_fov_y / 2)); - frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal); - PlaneClassify(&frustum[3]); + //RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_refdef.fov_y / 2)); + //frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal); + //PlaneClassify(&frustum[3]); // nearclip plane - VectorCopy(r_viewforward, frustum[4].normal); - frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + 1.0f; - PlaneClassify(&frustum[4]); + //VectorCopy(r_viewforward, frustum[4].normal); + //frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + 1.0f; + //PlaneClassify(&frustum[4]); } static void R_BlendView(void) { + int screenwidth, screenheight; + qboolean dobloom; + qboolean doblend; rmeshstate_t m; - if (r_refdef.viewblend[3] < 0.01f && !r_bloom.integer) + // set the (poorly named) screenwidth and screenheight variables to + // a power of 2 at least as large as the screen, these will define the + // size of the texture to allocate + for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2); + for (screenheight = 1;screenheight < vid.height;screenheight *= 2); + + doblend = r_refdef.viewblend[3] >= 0.01f; + dobloom = r_bloom.integer && screenwidth <= gl_max_texture_size && screenheight <= gl_max_texture_size && 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; + + if (!dobloom && !doblend) return; GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100); @@ -709,16 +856,11 @@ static void R_BlendView(void) 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) + if (dobloom) { - int screenwidth, screenheight, bloomwidth, bloomheight, x, dobloomblend, range; + int bloomwidth, bloomheight, x, dobloomblend, range; float xoffset, yoffset, r; - c_bloom++; - // set the (poorly named) screenwidth and screenheight variables to - // a power of 2 at least as large as the screen, these will define the - // size of the texture to allocate - for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2); - for (screenheight = 1;screenheight < vid.height;screenheight *= 2); + renderstats.bloom++; // allocate textures as needed 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); @@ -756,8 +898,7 @@ static void R_BlendView(void) // copy view into the full resolution screen image texture GL_ActiveTexture(0); qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height); - c_bloomcopies++; - c_bloomcopypixels += r_view_width * r_view_height; + renderstats.bloom_copypixels += r_view_width * r_view_height; // now scale it down to the bloom size and raise to a power of itself // to darken it (this leaves the really bright stuff bright, and // everything else becomes very dark) @@ -766,15 +907,13 @@ static void R_BlendView(void) GL_BlendFunc(GL_ONE, GL_ZERO); GL_Color(1, 1, 1, 1); R_Mesh_Draw(0, 4, 2, polygonelements); - c_bloomdraws++; - c_bloomdrawpixels += bloomwidth * bloomheight; + renderstats.bloom_drawpixels += bloomwidth * bloomheight; // render multiple times with a multiply blendfunc to raise to a power GL_BlendFunc(GL_DST_COLOR, GL_ZERO); for (x = 1;x < r_bloom_power.integer;x++) { R_Mesh_Draw(0, 4, 2, polygonelements); - c_bloomdraws++; - c_bloomdrawpixels += bloomwidth * bloomheight; + renderstats.bloom_drawpixels += bloomwidth * bloomheight; } // we now have a darkened bloom image in the framebuffer, copy it into // the bloom image texture for more processing @@ -785,8 +924,7 @@ static void R_BlendView(void) R_Mesh_State(&m); GL_ActiveTexture(0); qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight); - c_bloomcopies++; - c_bloomcopypixels += bloomwidth * bloomheight; + renderstats.bloom_copypixels += bloomwidth * bloomheight; // blend on at multiple vertical offsets to achieve a vertical blur // TODO: do offset blends using GLSL range = r_bloom_blur.integer * bloomwidth / 320; @@ -812,15 +950,13 @@ static void R_BlendView(void) continue; GL_Color(r, r, r, 1); R_Mesh_Draw(0, 4, 2, polygonelements); - c_bloomdraws++; - c_bloomdrawpixels += bloomwidth * bloomheight; + renderstats.bloom_drawpixels += bloomwidth * bloomheight; GL_BlendFunc(GL_ONE, GL_ONE); } // copy the vertically blurred bloom view to a texture GL_ActiveTexture(0); qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight); - c_bloomcopies++; - c_bloomcopypixels += bloomwidth * bloomheight; + renderstats.bloom_copypixels += bloomwidth * bloomheight; // blend the vertically blurred image at multiple offsets horizontally // to finish the blur effect // TODO: do offset blends using GLSL @@ -847,15 +983,13 @@ static void R_BlendView(void) continue; GL_Color(r, r, r, 1); R_Mesh_Draw(0, 4, 2, polygonelements); - c_bloomdraws++; - c_bloomdrawpixels += bloomwidth * bloomheight; + renderstats.bloom_drawpixels += 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.height - (r_view_y + bloomheight), bloomwidth, bloomheight); - c_bloomcopies++; - c_bloomcopypixels += bloomwidth * bloomheight; + renderstats.bloom_copypixels += bloomwidth * bloomheight; // go back to full view area qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height); // put the original screen image back in place and blend the bloom @@ -882,8 +1016,7 @@ static void R_BlendView(void) GL_BlendFunc(GL_ONE, GL_ZERO); GL_Color(1,1,1,1); R_Mesh_Draw(0, 4, 2, polygonelements); - c_bloomdraws++; - c_bloomdrawpixels += r_view_width * r_view_height; + renderstats.bloom_drawpixels += r_view_width * r_view_height; // now blend on the bloom texture if multipass if (dobloomblend) { @@ -895,11 +1028,10 @@ static void R_BlendView(void) GL_BlendFunc(GL_ONE, GL_ONE); GL_Color(1,1,1,1); R_Mesh_Draw(0, 4, 2, polygonelements); - c_bloomdraws++; - c_bloomdrawpixels += r_view_width * r_view_height; + renderstats.bloom_drawpixels += r_view_width * r_view_height; } } - if (r_refdef.viewblend[3] >= 0.01f) + if (doblend) { // apply a color tint to the whole view memset(&m, 0, sizeof(m)); @@ -931,8 +1063,6 @@ void R_RenderView(void) r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width); r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height); r_view_z = 0; - r_view_fov_x = bound(1, r_refdef.fov_x, 170); - r_view_fov_y = bound(1, r_refdef.fov_y, 170); r_view_matrix = r_refdef.viewentitymatrix; GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1); r_rtworld = r_shadow_realtime_world.integer; @@ -949,7 +1079,6 @@ void R_RenderView(void) R_ClearScreen(); R_Textures_Frame(); R_UpdateFog(); - R_UpdateLights(); R_TimeReport("setup"); qglDepthFunc(GL_LEQUAL); @@ -968,7 +1097,58 @@ void R_RenderView(void) GL_ScissorTest(false); } +//[515]: csqc +void CSQC_R_ClearScreen (void) +{ + if (!r_refdef.entities/* || !r_refdef.worldmodel*/) + return; //Host_Error ("R_RenderView: NULL worldmodel"); + + r_view_width = bound(0, r_refdef.width, vid.width); + r_view_height = bound(0, r_refdef.height, vid.height); + r_view_depth = 1; + r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width); + r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height); + r_view_z = 0; + r_view_matrix = r_refdef.viewentitymatrix; + GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1); + r_rtworld = r_shadow_realtime_world.integer; + r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil; + r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer; + r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil; + r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1; + + // GL is weird because it's bottom to top, r_view_y is top to bottom + qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height); + GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height); + GL_ScissorTest(true); + GL_DepthMask(true); + R_ClearScreen(); + R_Textures_Frame(); + R_UpdateFog(); + R_TimeReport("setup"); +} + +//[515]: csqc +void CSQC_R_RenderScene (void) +{ + qglDepthFunc(GL_LEQUAL); + qglPolygonOffset(0, 0); + qglEnable(GL_POLYGON_OFFSET_FILL); + + R_RenderScene(); + + qglPolygonOffset(0, 0); + qglDisable(GL_POLYGON_OFFSET_FILL); + + R_BlendView(); + R_TimeReport("blendview"); + + GL_Scissor(0, 0, vid.width, vid.height); + GL_ScissorTest(false); +} + extern void R_DrawLightningBeams (void); +extern void VM_AddPolygonsToMeshQueue (void); void R_RenderScene(void) { // don't let sound skip if going slow @@ -985,9 +1165,9 @@ void R_RenderScene(void) r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f; if (r_rtworldshadows || r_rtdlightshadows) - GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view_fov_x, r_view_fov_y, 1.0f); + GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.frustum_x, r_refdef.frustum_y, 1.0f); else - GL_SetupView_Mode_Perspective(r_view_fov_x, r_view_fov_y, 1.0f, r_farclip); + GL_SetupView_Mode_Perspective(r_refdef.frustum_x, r_refdef.frustum_y, 1.0f, r_farclip); GL_SetupView_Orientation_FromEntity(&r_view_matrix); @@ -1007,21 +1187,24 @@ void R_RenderScene(void) if (r_refdef.extraupdate) S_ExtraUpdate (); - GL_ShowTrisColor(0.025, 0.025, 0, 1); - if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky) + if (cl.csqc_vidvars.drawworld) { - r_refdef.worldmodel->DrawSky(r_refdef.worldentity); - R_TimeReport("worldsky"); - } + GL_ShowTrisColor(0.025, 0.025, 0, 1); + if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky) + { + r_refdef.worldmodel->DrawSky(r_refdef.worldentity); + R_TimeReport("worldsky"); + } - if (R_DrawBrushModelsSky()) - R_TimeReport("bmodelsky"); + if (R_DrawBrushModelsSky()) + R_TimeReport("bmodelsky"); - GL_ShowTrisColor(0.05, 0.05, 0.05, 1); - if (r_refdef.worldmodel && r_refdef.worldmodel->Draw) - { - r_refdef.worldmodel->Draw(r_refdef.worldentity); - R_TimeReport("world"); + GL_ShowTrisColor(0.05, 0.05, 0.05, 1); + if (r_refdef.worldmodel && r_refdef.worldmodel->Draw) + { + r_refdef.worldmodel->Draw(r_refdef.worldentity); + R_TimeReport("world"); + } } // don't let sound skip if going slow @@ -1047,23 +1230,33 @@ void R_RenderScene(void) GL_ShowTrisColor(0.1, 0, 0, 1); - R_DrawLightningBeams(); - R_TimeReport("lightning"); + if (cl.csqc_vidvars.drawworld) + { + R_DrawLightningBeams(); + R_TimeReport("lightning"); - R_DrawParticles(); - R_TimeReport("particles"); + R_DrawParticles(); + R_TimeReport("particles"); - R_DrawExplosions(); - R_TimeReport("explosions"); + R_DrawExplosions(); + R_TimeReport("explosions"); + } R_MeshQueue_RenderTransparent(); R_TimeReport("drawtrans"); - R_DrawCoronas(); - R_TimeReport("coronas"); + if (cl.csqc_vidvars.drawworld) + { + R_DrawCoronas(); + R_TimeReport("coronas"); + } + if(cl.csqc_vidvars.drawcrosshair) + { + R_DrawWorldCrosshair(); + R_TimeReport("crosshair"); + } - R_DrawWorldCrosshair(); - R_TimeReport("crosshair"); + VM_AddPolygonsToMeshQueue(); R_MeshQueue_Render(); R_MeshQueue_EndScene(); @@ -1105,8 +1298,7 @@ void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, floa { for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4) { - VectorSubtract(v, r_vieworigin, diff); - f2 = exp(fogdensity/DotProduct(diff, diff)); + f2 = VERTEXFOGTABLE(VectorDistance(v, r_vieworigin)); f1 = 1 - f2; c[0] = c[0] * f1 + fogcolor[0] * f2; c[1] = c[1] * f1 + fogcolor[1] * f2; @@ -1153,11 +1345,10 @@ float nomodelcolor4f[6*4] = 0.5f, 0.0f, 0.0f, 1.0f }; -void R_DrawNoModelCallback(const void *calldata1, int calldata2) +void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight) { - const entity_render_t *ent = calldata1; int i; - float f1, f2, *c, diff[3]; + float f1, f2, *c; float color4f[6*4]; rmeshstate_t m; R_Mesh_Matrix(&ent->matrix); @@ -1185,8 +1376,7 @@ void R_DrawNoModelCallback(const void *calldata1, int calldata2) { memcpy(color4f, nomodelcolor4f, sizeof(float[6*4])); m.pointer_color = color4f; - VectorSubtract(ent->origin, r_vieworigin, diff); - f2 = exp(fogdensity/DotProduct(diff, diff)); + f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin)); f1 = 1 - f2; for (i = 0, c = color4f;i < 6;i++, c += 4) { @@ -1212,7 +1402,7 @@ void R_DrawNoModelCallback(const void *calldata1, int calldata2) void R_DrawNoModel(entity_render_t *ent) { //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1)) - R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModelCallback, ent, 0); + R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight); //else // R_DrawNoModelCallback(ent, 0); } @@ -1249,16 +1439,14 @@ void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, flo float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1}; -void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, int depthdisable, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2, float cr, float cg, float cb, float ca) +void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, rtexture_t *fogtexture, int depthdisable, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2, float cr, float cg, float cb, float ca) { - float diff[3]; + float fog = 0.0f, ifog; rmeshstate_t m; if (fogenabled) - { - VectorSubtract(origin, r_vieworigin, diff); - ca *= 1 - exp(fogdensity/DotProduct(diff,diff)); - } + fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin)); + ifog = 1 - fog; R_Mesh_Matrix(&r_identitymatrix); GL_BlendFunc(blendfunc1, blendfunc2); @@ -1283,8 +1471,16 @@ void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, int depth m.pointer_texcoord[0] = spritetexcoord2f; m.pointer_vertex = varray_vertex3f; R_Mesh_State(&m); - GL_Color(cr, cg, cb, ca); + GL_Color(cr * ifog, cg * ifog, cb * ifog, ca); R_Mesh_Draw(0, 4, 2, polygonelements); + + if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA) + { + R_Mesh_TexBind(0, R_GetTexture(fogtexture)); + GL_BlendFunc(blendfunc1, GL_ONE); + GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca); + R_Mesh_Draw(0, 4, 2, polygonelements); + } } int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v) @@ -1354,7 +1550,7 @@ void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *plane } } -void R_Texture_AddLayer(texture_t *t, qboolean depthmask, int blendfunc1, int blendfunc2, texturelayertype_t type, rtexture_t *texture, matrix4x4_t *matrix, float r, float g, float b, float a, int texrgbscale) +void R_Texture_AddLayer(texture_t *t, qboolean depthmask, int blendfunc1, int blendfunc2, texturelayertype_t type, rtexture_t *texture, matrix4x4_t *matrix, float r, float g, float b, float a) { texturelayer_t *layer; layer = t->currentlayers + t->currentnumlayers++; @@ -1368,7 +1564,6 @@ void R_Texture_AddLayer(texture_t *t, qboolean depthmask, int blendfunc1, int bl layer->color[1] = g; layer->color[2] = b; layer->color[3] = a; - layer->texrgbscale = texrgbscale; } void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) @@ -1382,8 +1577,6 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) int s = ent->skinnum; if ((unsigned int)s >= (unsigned int)model->numskins) s = 0; - if (s >= 1) - c_models++; if (model->skinscenes) { if (model->skinscenes[s].framecount > 1) @@ -1399,17 +1592,14 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) } t->currentmaterialflags = t->basematerialflags; - t->currentcolorbase[0] = ent->colormod[0]; - t->currentcolorbase[1] = ent->colormod[1]; - t->currentcolorbase[2] = ent->colormod[2]; - t->currentcolorbase[3] = ent->alpha; + t->currentalpha = ent->alpha; if (t->basematerialflags & MATERIALFLAG_WATERALPHA) - t->currentcolorbase[3] *= r_wateralpha.value; + t->currentalpha *= r_wateralpha.value; if (!(ent->flags & RENDER_LIGHT)) t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT; if (ent->effects & EF_ADDITIVE) t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT; - else if (t->currentcolorbase[3] < 1) + else if (t->currentalpha < 1) t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT; if (ent->effects & EF_NODEPTHTEST) t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST; @@ -1417,224 +1607,102 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) t->currenttexmatrix = r_waterscrollmatrix; else t->currenttexmatrix = r_identitymatrix; - if (ent->colormap >= 0) - { - int b; - qbyte *bcolor; - t->currentbasetexture = t->skin.base; - t->currentdopants = t->skin.pants != NULL; - t->currentdoshirt = t->skin.shirt != NULL; - // 128-224 are backwards ranges - b = (ent->colormap & 0xF) << 4;b += (b >= 128 && b < 224) ? 4 : 12; - t->currentdofullbrightpants = (b >= 224) || (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT); - bcolor = (qbyte *) (&palette_complete[b]); - t->currentcolorpants[0] = bcolor[0] * (1.0f / 255.0f) * t->currentcolorbase[0]; - t->currentcolorpants[1] = bcolor[1] * (1.0f / 255.0f) * t->currentcolorbase[1]; - t->currentcolorpants[2] = bcolor[2] * (1.0f / 255.0f) * t->currentcolorbase[2]; - t->currentcolorpants[3] = t->currentcolorbase[3]; - // 128-224 are backwards ranges - b = (ent->colormap & 0xF0);b += (b >= 128 && b < 224) ? 4 : 12; - t->currentdofullbrightshirt = (b >= 224) || (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT); - bcolor = (qbyte *) (&palette_complete[b]); - t->currentcolorshirt[0] = bcolor[0] * (1.0f / 255.0f) * t->currentcolorbase[0]; - t->currentcolorshirt[1] = bcolor[1] * (1.0f / 255.0f) * t->currentcolorbase[1]; - t->currentcolorshirt[2] = bcolor[2] * (1.0f / 255.0f) * t->currentcolorbase[2]; - t->currentcolorshirt[3] = t->currentcolorbase[3]; - } - else - { - t->currentbasetexture = t->skin.merged ? t->skin.merged : t->skin.base; - t->currentdopants = false; - t->currentdoshirt = false; - t->currentdofullbrightpants = false; - t->currentdofullbrightshirt = false; - } - t->currentfogallpasses = fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT); t->currentnumlayers = 0; if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW)) { - int blendfunc1, blendfunc2, depthmask; - if (t->currentmaterialflags & MATERIALFLAG_ADD) - { - blendfunc1 = GL_SRC_ALPHA; - blendfunc2 = GL_ONE; - depthmask = false; - } - else if (t->currentmaterialflags & MATERIALFLAG_ALPHA) - { - blendfunc1 = GL_SRC_ALPHA; - blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; - depthmask = false; - } - else - { - blendfunc1 = GL_ONE; - blendfunc2 = GL_ZERO; - depthmask = true; - } if (gl_lightmaps.integer) - R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LIGHTMAP, r_texture_white, &r_identitymatrix, 1, 1, 1, 1, 1); + R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &r_identitymatrix, 1, 1, 1, 1); else if (t->currentmaterialflags & MATERIALFLAG_SKY) { // transparent sky would be ridiculous if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT)) - R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_SKY, r_texture_white, &r_identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], 1, 1); + R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_SKY, r_texture_white, &r_identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], 1); } - else if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL)) + else { - int type; - float colorscale, r, g, b; - rtexture_t *currentbasetexture; - colorscale = 2; - // q3bsp has no lightmap updates, so the lightstylevalue that - // would normally be baked into the lightmaptexture must be - // applied to the color - if (!(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) && ent->model->type == mod_brushq3) - colorscale *= d_lightstylevalue[0] * (1.0f / 128.0f); - r = t->currentcolorbase[0] * colorscale; - g = t->currentcolorbase[1] * colorscale; - b = t->currentcolorbase[2] * colorscale; - // transparent and fullbright are not affected by r_lightmapintensity - if (!(t->currentmaterialflags & (MATERIALFLAG_TRANSPARENT | MATERIALFLAG_FULLBRIGHT))) + int blendfunc1, blendfunc2, depthmask; + if (t->currentmaterialflags & MATERIALFLAG_ADD) { - r *= r_lightmapintensity; - g *= r_lightmapintensity; - b *= r_lightmapintensity; + blendfunc1 = GL_SRC_ALPHA; + blendfunc2 = GL_ONE; + depthmask = false; } - currentbasetexture = (ent->colormap >= 0 && t->skin.merged) ? t->skin.merged : t->skin.base; - if (!(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) && r_textureunits.integer >= 2 && gl_combine.integer) + else if (t->currentmaterialflags & MATERIALFLAG_ALPHA) { - if ((r > 2 || g > 2 || b > 2) && gl_combine.integer) - R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LIGHTMAP_DOUBLEMODULATE_TEXTURE, currentbasetexture, &t->currenttexmatrix, r * 0.25f, g * 0.25f, b * 0.25f, t->currentcolorbase[3], 4); - else if ((r > 1 || g > 1 || b > 1) && gl_combine.integer) - R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LIGHTMAP_DOUBLEMODULATE_TEXTURE, currentbasetexture, &t->currenttexmatrix, r * 0.5f, g * 0.5f, b * 0.5f, t->currentcolorbase[3], 2); - else - R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LIGHTMAP_DOUBLEMODULATE_TEXTURE, currentbasetexture, &t->currenttexmatrix, r, g, b, t->currentcolorbase[3], 1); - } - else if ((t->currentmaterialflags & (MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_TRANSPARENT)) == 0) - { - R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LIGHTMAP, r_texture_white, &r_identitymatrix, 1, 1, 1, 1, 1); - if (r > 1 || g > 1 || b > 1) - R_Texture_AddLayer(t, false, GL_DST_COLOR, GL_SRC_COLOR, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, r * 0.5f, g * 0.5f, b * 0.5f, t->currentcolorbase[3], 1); - else - R_Texture_AddLayer(t, false, GL_ZERO, GL_SRC_COLOR, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, r, g, b, t->currentcolorbase[3], 1); + blendfunc1 = GL_SRC_ALPHA; + blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; + depthmask = false; } else { - if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) - { - type = TEXTURELAYERTYPE_TEXTURE; - r *= 0.5f; - g *= 0.5f; - b *= 0.5f; - } - else - type = TEXTURELAYERTYPE_VERTEXTEXTURE; - if ((r > 2 || g > 2 || b > 2) && gl_combine.integer) - R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, type, currentbasetexture, &t->currenttexmatrix, r * 0.25f, g * 0.25f, b * 0.25f, t->currentcolorbase[3], 4); - else if ((r > 1 || g > 1 || b > 1) && gl_combine.integer) - R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, type, currentbasetexture, &t->currenttexmatrix, r * 0.5f, g * 0.5f, b * 0.5f, t->currentcolorbase[3], 2); - else - R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, type, currentbasetexture, &t->currenttexmatrix, r, g, b, t->currentcolorbase[3], 1); + blendfunc1 = GL_ONE; + blendfunc2 = GL_ZERO; + depthmask = true; } - if (ent->colormap >= 0 && t->skin.pants) + if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL)) { - int cb; - qbyte *cbcolor; - // 128-224 are backwards ranges - cb = (ent->colormap & 0xF) << 4;cb += (cb >= 128 && cb < 224) ? 4 : 12; - cbcolor = (qbyte *) (&palette_complete[cb]); - r = cbcolor[0] * (1.0f / 255.0f) * t->currentcolorbase[0] * colorscale; - g = cbcolor[1] * (1.0f / 255.0f) * t->currentcolorbase[1] * colorscale; - b = cbcolor[2] * (1.0f / 255.0f) * t->currentcolorbase[2] * colorscale; - // transparent and fullbright are not affected by r_lightmapintensity - if ((cb >= 224) || (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) + rtexture_t *currentbasetexture; + int layerflags = 0; + if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT)) + layerflags |= TEXTURELAYERFLAG_FOGDARKEN; + currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base; + if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) { - type = TEXTURELAYERTYPE_TEXTURE; - r *= 0.5f; - g *= 0.5f; - b *= 0.5f; + // fullbright is not affected by r_lightmapintensity + R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha); + if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants) + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0], ent->colormap_pantscolor[1] * ent->colormod[1], ent->colormap_pantscolor[2] * ent->colormod[2], t->currentalpha); + if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt) + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0], ent->colormap_shirtcolor[1] * ent->colormod[1], ent->colormap_shirtcolor[2] * ent->colormod[2], t->currentalpha); } else { - type = TEXTURELAYERTYPE_VERTEXTEXTURE; - if (!(t->currentmaterialflags & (MATERIALFLAG_TRANSPARENT | MATERIALFLAG_FULLBRIGHT))) + float colorscale; + colorscale = 2; + // q3bsp has no lightmap updates, so the lightstylevalue that + // would normally be baked into the lightmaptexture must be + // applied to the color + if (ent->model->type == mod_brushq3) + colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f); + colorscale *= r_lightmapintensity; + if (r_textureunits.integer >= 2 && gl_combine.integer) + R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE_COMBINE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale, ent->colormod[1] * colorscale, ent->colormod[2] * colorscale, t->currentalpha); + else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0) + R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale * 0.5f, ent->colormod[1] * colorscale * 0.5f, ent->colormod[2] * colorscale * 0.5f, t->currentalpha); + else + R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE_VERTEX, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale, ent->colormod[1] * colorscale, ent->colormod[2] * colorscale, t->currentalpha); + if (r_ambient.value >= (1.0f/64.0f)) + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha); + if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants) { - r *= r_lightmapintensity; - g *= r_lightmapintensity; - b *= r_lightmapintensity; + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE_VERTEX, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0] * colorscale, ent->colormap_pantscolor[1] * ent->colormod[1] * colorscale, ent->colormap_pantscolor[2] * ent->colormod[2] * colorscale, t->currentalpha); + if (r_ambient.value >= (1.0f/64.0f)) + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[1] * ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[2] * ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha); } - } - if ((r > 2 || g > 2 || b > 2) && gl_combine.integer) - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, type, t->skin.pants, &t->currenttexmatrix, r * 0.25f, g * 0.25f, b * 0.25f, t->currentcolorbase[3], 4); - else if ((r > 1 || g > 1 || b > 1) && gl_combine.integer) - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, type, t->skin.pants, &t->currenttexmatrix, r * 0.5f, g * 0.5f, b * 0.5f, t->currentcolorbase[3], 2); - else - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, type, t->skin.pants, &t->currenttexmatrix, r, g, b, t->currentcolorbase[3], 1); - } - if (ent->colormap >= 0 && t->skin.shirt) - { - int cb; - qbyte *cbcolor; - // 128-224 are backwards ranges - cb = (ent->colormap & 0xF0);cb += (cb >= 128 && cb < 224) ? 4 : 12; - cbcolor = (qbyte *) (&palette_complete[cb]); - r = cbcolor[0] * (1.0f / 255.0f) * t->currentcolorbase[0] * colorscale; - g = cbcolor[1] * (1.0f / 255.0f) * t->currentcolorbase[1] * colorscale; - b = cbcolor[2] * (1.0f / 255.0f) * t->currentcolorbase[2] * colorscale; - // transparent and fullbright are not affected by r_lightmapintensity - if ((cb >= 224) || (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) - { - type = TEXTURELAYERTYPE_TEXTURE; - r *= 0.5f; - g *= 0.5f; - b *= 0.5f; - } - else - { - type = TEXTURELAYERTYPE_VERTEXTEXTURE; - if (!(t->currentmaterialflags & (MATERIALFLAG_TRANSPARENT | MATERIALFLAG_FULLBRIGHT))) + if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt) { - r *= r_lightmapintensity; - g *= r_lightmapintensity; - b *= r_lightmapintensity; + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE_VERTEX, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0] * colorscale, ent->colormap_shirtcolor[1] * ent->colormod[1] * colorscale, ent->colormap_shirtcolor[2] * ent->colormod[2] * colorscale, t->currentalpha); + if (r_ambient.value >= (1.0f/64.0f)) + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[1] * ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[2] * ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha); } } - if ((r > 2 || g > 2 || b > 2) && gl_combine.integer) - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, type, t->skin.shirt, &t->currenttexmatrix, r * 0.25f, g * 0.25f, b * 0.25f, t->currentcolorbase[3], 4); - else if ((r > 1 || g > 1 || b > 1) && gl_combine.integer) - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, type, t->skin.shirt, &t->currenttexmatrix, r * 0.5f, g * 0.5f, b * 0.5f, t->currentcolorbase[3], 2); - else - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, type, t->skin.shirt, &t->currenttexmatrix, r, g, b, t->currentcolorbase[3], 1); - } - if (r_ambient.value >= (1.0f/64.0f)) - { - r = t->currentcolorbase[0] * colorscale * r_ambient.value * (1.0f / 64.0f); - g = t->currentcolorbase[1] * colorscale * r_ambient.value * (1.0f / 64.0f); - b = t->currentcolorbase[2] * colorscale * r_ambient.value * (1.0f / 64.0f); - if ((r > 2 || g > 2 || b > 2) && gl_combine.integer) - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, r * 0.25f, g * 0.25f, b * 0.25f, t->currentcolorbase[3], 4); - else if ((r > 1 || g > 1 || b > 1) && gl_combine.integer) - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, r * 0.5f, g * 0.5f, b * 0.5f, t->currentcolorbase[3], 2); - else - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, r, g, b, t->currentcolorbase[3], 1); - } - if (t->skin.glow != NULL) - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentcolorbase[3], 1); - if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD)) - { - // if this is opaque use alpha blend which will darken the earlier - // passes cheaply. - // - // if this is an alpha blended material, all the earlier passes - // were darkened by fog already, so we only need to add the fog - // color ontop through the fog mask texture - // - // if this is an additive blended material, all the earlier passes - // were darkened by fog already, and we should not add fog color - // (because the background was not darkened, there is no fog color - // that was lost behind it). - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, t->currentfogallpasses ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->skin.fog, &r_identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], t->currentcolorbase[3], 1); + if (t->skin.glow != NULL) + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha); + if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD)) + { + // if this is opaque use alpha blend which will darken the earlier + // passes cheaply. + // + // if this is an alpha blended material, all the earlier passes + // were darkened by fog already, so we only need to add the fog + // color ontop through the fog mask texture + // + // if this is an additive blended material, all the earlier passes + // were darkened by fog already, and we should not add fog color + // (because the background was not darkened, there is no fog color + // that was lost behind it). + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->skin.fog, &r_identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], t->currentalpha); + } } } } @@ -1751,7 +1819,6 @@ void RSurf_SetColorPointer(const entity_render_t *ent, const msurface_t *surface int i; float f; float *v, *c, *c2; - vec3_t diff; if (lightmode >= 2) { // model lighting @@ -1788,28 +1855,33 @@ void RSurf_SetColorPointer(const entity_render_t *ent, const msurface_t *surface { for (i = 0, c = varray_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4) { - const qbyte *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i]; - float scale = d_lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f); - VectorScale(lm, scale, c); - if (surface->lightmapinfo->styles[1] != 255) + const unsigned char *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i]; + if (lm) { - int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3; - lm += size3; - scale = d_lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f); - VectorMA(c, scale, lm, c); - if (surface->lightmapinfo->styles[2] != 255) + float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f); + VectorScale(lm, scale, c); + if (surface->lightmapinfo->styles[1] != 255) { + int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3; lm += size3; - scale = d_lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f); + scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f); VectorMA(c, scale, lm, c); - if (surface->lightmapinfo->styles[3] != 255) + if (surface->lightmapinfo->styles[2] != 255) { lm += size3; - scale = d_lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f); + scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f); VectorMA(c, scale, lm, c); + if (surface->lightmapinfo->styles[3] != 255) + { + lm += size3; + scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f); + VectorMA(c, scale, lm, c); + } } } } + else + VectorClear(c); } rsurface_lightmapcolor4f = varray_color4f; } @@ -1824,8 +1896,7 @@ void RSurf_SetColorPointer(const entity_render_t *ent, const msurface_t *surface { for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (rsurface_lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4, c2 += 4) { - VectorSubtract(v, modelorg, diff); - f = 1 - exp(fogdensity/DotProduct(diff, diff)); + f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg)); c2[0] = c[0] * f; c2[1] = c[1] * f; c2[2] = c[2] * f; @@ -1836,8 +1907,7 @@ void RSurf_SetColorPointer(const entity_render_t *ent, const msurface_t *surface { for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c2 = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4) { - VectorSubtract(v, modelorg, diff); - f = 1 - exp(fogdensity/DotProduct(diff, diff)); + f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg)); c2[0] = f; c2[1] = f; c2[2] = f; @@ -1861,63 +1931,49 @@ void RSurf_SetColorPointer(const entity_render_t *ent, const msurface_t *surface GL_Color(r, g, b, a); } - static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg) { - int i; int texturesurfaceindex; int lightmode; - const float *v; - float *c; - float diff[3]; - float f, r, g, b, a, colorscale; const msurface_t *surface; qboolean applycolor; rmeshstate_t m; if (texture->currentmaterialflags & MATERIALFLAG_NODRAW) return; - c_faces += texturenumsurfaces; + renderstats.entities_surfaces += texturenumsurfaces; // FIXME: identify models using a better check than ent->model->brush.shadowmesh lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2; - // gl_lightmaps debugging mode skips normal texturing - if (gl_lightmaps.integer) - { - GL_BlendFunc(GL_ONE, GL_ZERO); - GL_DepthMask(true); - GL_DepthTest(true); - qglDisable(GL_CULL_FACE); - GL_Color(1, 1, 1, 1); - memset(&m, 0, sizeof(m)); - R_Mesh_State(&m); - for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) - { - surface = texturesurfacelist[texturesurfaceindex]; - R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture)); - R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f); - RSurf_SetVertexPointer(ent, texture, surface, modelorg); - RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, lightmode ? lightmode : !surface->lightmaptexture, false, false); - GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); - GL_LockArrays(0, 0); - } - qglEnable(GL_CULL_FACE); - return; - } GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST)); - if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) + if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE)) qglDisable(GL_CULL_FACE); -if (r_test.integer) -{ if (texture->currentnumlayers) { int layerindex; texturelayer_t *layer; for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++) { + vec4_t layercolor; + int layertexrgbscale; GL_DepthMask(layer->depthmask); GL_BlendFunc(layer->blendfunc1, layer->blendfunc2); - GL_Color(layer->color[0], layer->color[1], layer->color[2], layer->color[3]); - applycolor = layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1; + if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask)) + { + layertexrgbscale = 4; + VectorScale(layer->color, 0.25f, layercolor); + } + else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask)) + { + layertexrgbscale = 2; + VectorScale(layer->color, 0.5f, layercolor); + } + else + { + layertexrgbscale = 1; + VectorScale(layer->color, 1.0f, layercolor); + } + layercolor[3] = layer->color[3]; + GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]); + applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1; switch (layer->type) { case TEXTURELAYERTYPE_SKY: @@ -1929,7 +1985,7 @@ if (r_test.integer) R_Sky(); // restore entity matrix and GL_Color R_Mesh_Matrix(&ent->matrix); - GL_Color(layer->color[0], layer->color[1], layer->color[2], layer->color[3]); + GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]); } } // LordHavoc: HalfLife maps have freaky skypolys... @@ -1962,11 +2018,11 @@ if (r_test.integer) GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1); } break; - case TEXTURELAYERTYPE_LIGHTMAP_DOUBLEMODULATE_TEXTURE: + case TEXTURELAYERTYPE_LITTEXTURE_COMBINE: memset(&m, 0, sizeof(m)); m.tex[1] = R_GetTexture(layer->texture); m.texmatrix[1] = layer->texmatrix; - m.texrgbscale[1] = layer->texrgbscale; + m.texrgbscale[1] = layertexrgbscale; m.pointer_color = varray_color4f; R_Mesh_State(&m); for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) @@ -1978,25 +2034,29 @@ if (r_test.integer) if (lightmode == 2) { R_Mesh_TexBind(0, R_GetTexture(r_texture_white)); - RSurf_SetColorPointer(ent, surface, modelorg, layer->color[0], layer->color[1], layer->color[2], layer->color[3], 2, applycolor, texture->currentfogallpasses); + RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN); } else if (surface->lightmaptexture) { R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture)); - RSurf_SetColorPointer(ent, surface, modelorg, layer->color[0], layer->color[1], layer->color[2], layer->color[3], 0, applycolor, texture->currentfogallpasses); + RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN); } else { R_Mesh_TexBind(0, R_GetTexture(r_texture_white)); - RSurf_SetColorPointer(ent, surface, modelorg, layer->color[0], layer->color[1], layer->color[2], layer->color[3], 1, applycolor, texture->currentfogallpasses); + RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN); } GL_LockArrays(surface->num_firstvertex, surface->num_vertices); R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); GL_LockArrays(0, 0); } break; - case TEXTURELAYERTYPE_LIGHTMAP: + case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS: memset(&m, 0, sizeof(m)); + m.tex[0] = R_GetTexture(layer->texture); + m.texmatrix[0] = layer->texmatrix; + m.pointer_color = varray_color4f; + m.texrgbscale[0] = layertexrgbscale; R_Mesh_State(&m); for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) { @@ -2006,7 +2066,7 @@ if (r_test.integer) if (lightmode == 2) { R_Mesh_TexBind(0, R_GetTexture(r_texture_white)); - RSurf_SetColorPointer(ent, surface, modelorg, layer->color[0], layer->color[1], layer->color[2], layer->color[3], 2, applycolor, false); + RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 2, false, false); } else if (surface->lightmaptexture) { @@ -2016,27 +2076,43 @@ if (r_test.integer) else { R_Mesh_TexBind(0, R_GetTexture(r_texture_white)); - // TODO: use a specialized RSurf_SetColorPointer - RSurf_SetColorPointer(ent, surface, modelorg, layer->color[0], layer->color[1], layer->color[2], layer->color[3], 1, applycolor, false); + RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 1, false, false); } GL_LockArrays(surface->num_firstvertex, surface->num_vertices); R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); GL_LockArrays(0, 0); } + GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); + memset(&m, 0, sizeof(m)); + m.tex[0] = R_GetTexture(layer->texture); + m.texmatrix[0] = layer->texmatrix; + m.pointer_color = varray_color4f; + m.texrgbscale[0] = layertexrgbscale; + R_Mesh_State(&m); + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) + { + surface = texturesurfacelist[texturesurfaceindex]; + RSurf_SetVertexPointer(ent, texture, surface, modelorg); + R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f); + RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN); + GL_LockArrays(surface->num_firstvertex, surface->num_vertices); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); + GL_LockArrays(0, 0); + } break; - case TEXTURELAYERTYPE_VERTEXTEXTURE: + case TEXTURELAYERTYPE_LITTEXTURE_VERTEX: memset(&m, 0, sizeof(m)); m.tex[0] = R_GetTexture(layer->texture); m.texmatrix[0] = layer->texmatrix; + m.texrgbscale[0] = layertexrgbscale; m.pointer_color = varray_color4f; - m.texrgbscale[0] = layer->texrgbscale; R_Mesh_State(&m); for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) { surface = texturesurfacelist[texturesurfaceindex]; RSurf_SetVertexPointer(ent, texture, surface, modelorg); R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f); - RSurf_SetColorPointer(ent, surface, modelorg, layer->color[0], layer->color[1], layer->color[2], layer->color[3], lightmode ? lightmode : 1, applycolor, texture->currentfogallpasses); + RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode ? lightmode : 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN); GL_LockArrays(surface->num_firstvertex, surface->num_vertices); R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); GL_LockArrays(0, 0); @@ -2047,14 +2123,14 @@ if (r_test.integer) m.tex[0] = R_GetTexture(layer->texture); m.texmatrix[0] = layer->texmatrix; m.pointer_color = varray_color4f; - m.texrgbscale[0] = layer->texrgbscale; + m.texrgbscale[0] = layertexrgbscale; R_Mesh_State(&m); for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) { surface = texturesurfacelist[texturesurfaceindex]; RSurf_SetVertexPointer(ent, texture, surface, modelorg); R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f); - RSurf_SetColorPointer(ent, surface, modelorg, layer->color[0], layer->color[1], layer->color[2], layer->color[3], 0, applycolor, texture->currentfogallpasses); + RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN); GL_LockArrays(surface->num_firstvertex, surface->num_vertices); R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); GL_LockArrays(0, 0); @@ -2079,12 +2155,11 @@ if (r_test.integer) R_Mesh_ColorPointer(varray_color4f); for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4) { - VectorSubtract(v, modelorg, diff); - f = exp(fogdensity/DotProduct(diff, diff)); - c[0] = layer->color[0]; - c[1] = layer->color[1]; - c[2] = layer->color[2]; - c[3] = f * layer->color[3]; + f = VERTEXFOGTABLE(VectorDistance(v, modelorg)); + c[0] = layercolor[0]; + c[1] = layercolor[1]; + c[2] = layercolor[2]; + c[3] = f * layercolor[3]; } GL_LockArrays(surface->num_firstvertex, surface->num_vertices); R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); @@ -2094,440 +2169,82 @@ if (r_test.integer) default: Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type); } - } - } -} -else -{ - GL_DepthMask(!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)); - if (texture->currentmaterialflags & MATERIALFLAG_ADD) - GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); - else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA) - GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - else - GL_BlendFunc(GL_ONE, GL_ZERO); - if (texture->currentmaterialflags & MATERIALFLAG_SKY) - { - if (skyrendernow) - { - skyrendernow = false; - if (skyrendermasked) - R_Sky(); - } - // LordHavoc: HalfLife maps have freaky skypolys... - //if (!ent->model->brush.ishlbsp) - { - R_Mesh_Matrix(&ent->matrix); - GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1); - if (skyrendermasked) - { - // depth-only (masking) - GL_ColorMask(0,0,0,0); - // just to make sure that braindead drivers don't draw anything - // despite that colormask... - GL_BlendFunc(GL_ZERO, GL_ONE); - } - else - { - // fog sky - GL_BlendFunc(GL_ONE, GL_ZERO); - } - GL_DepthMask(true); - GL_DepthTest(true); - memset(&m, 0, sizeof(m)); - R_Mesh_State(&m); - for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) - { - surface = texturesurfacelist[texturesurfaceindex]; - RSurf_SetVertexPointer(ent, texture, surface, modelorg); - GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); - GL_LockArrays(0, 0); - } - GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1); - } - } - else if (texture->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL)) - { - // normal surface (wall or water) - if (!(texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) && r_textureunits.integer >= 2 && gl_combine.integer) - { - // multitexture single pass - memset(&m, 0, sizeof(m)); - m.tex[1] = R_GetTexture(texture->currentbasetexture); - m.texmatrix[1] = texture->currenttexmatrix; - m.texrgbscale[1] = 2; - m.pointer_color = varray_color4f; - R_Mesh_State(&m); - // transparent is not affected by r_lightmapintensity - if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)) - colorscale = r_lightmapintensity; - else - colorscale = 1; - // q3bsp has no lightmap updates, so the lightstylevalue that - // would normally be baked into the lightmaptexture must be - // applied to the color - if (ent->model->type == mod_brushq3) - colorscale *= d_lightstylevalue[0] * (1.0f / 128.0f); - r = texture->currentcolorbase[0] * colorscale; - g = texture->currentcolorbase[1] * colorscale; - b = texture->currentcolorbase[2] * colorscale; - a = texture->currentcolorbase[3]; - applycolor = r != 1 || g != 1 || b != 1 || a != 1; - for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) - { - surface = texturesurfacelist[texturesurfaceindex]; - RSurf_SetVertexPointer(ent, texture, surface, modelorg); - R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f); - R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f); - if (surface->lightmaptexture) - R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture)); - else - R_Mesh_TexBind(0, R_GetTexture(r_texture_white)); - RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, lightmode ? lightmode : !surface->lightmaptexture, applycolor, texture->currentfogallpasses); - GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); - GL_LockArrays(0, 0); - } - } - // FIXME: identify models using a better check than ent->model->brush.shadowmesh - else if (!(texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) && !(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT) && ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh)) - { - // single texture two pass - GL_BlendFunc(GL_ONE, GL_ZERO); - GL_DepthMask(true); - GL_Color(1, 1, 1, 1); - memset(&m, 0, sizeof(m)); - R_Mesh_State(&m); - for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) - { - surface = texturesurfacelist[texturesurfaceindex]; - RSurf_SetVertexPointer(ent, texture, surface, modelorg); - R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f); - if (surface->lightmaptexture) - { - R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture)); - R_Mesh_ColorPointer(NULL); - } - else - { - R_Mesh_TexBind(0, R_GetTexture(r_texture_white)); - R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f); - } - GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); - GL_LockArrays(0, 0); - } - GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); - GL_DepthMask(false); - GL_Color(r_lightmapintensity * texture->currentcolorbase[0], r_lightmapintensity * texture->currentcolorbase[1], r_lightmapintensity * texture->currentcolorbase[2], texture->currentcolorbase[3]); - memset(&m, 0, sizeof(m)); - m.tex[0] = R_GetTexture(texture->currentbasetexture); - m.texmatrix[0] = texture->currenttexmatrix; - R_Mesh_State(&m); - for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) - { - surface = texturesurfacelist[texturesurfaceindex]; - RSurf_SetVertexPointer(ent, texture, surface, modelorg); - R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f); - GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); - GL_LockArrays(0, 0); - } - } - else - { - // single texture single pass (vertex lit only) - memset(&m, 0, sizeof(m)); - m.tex[0] = R_GetTexture(texture->currentbasetexture); - m.texmatrix[0] = texture->currenttexmatrix; - m.pointer_color = varray_color4f; - colorscale = 2; - if (gl_combine.integer) - { - m.texrgbscale[0] = 2; - colorscale = 1; - } - // transparent is not affected by r_lightmapintensity - if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)) - colorscale *= r_lightmapintensity; - // q3bsp has no lightmap updates, so the lightstylevalue that - // would normally be baked into the lightmaptexture must be - // applied to the color - if (!(texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) && ent->model->type == mod_brushq3) - colorscale *= d_lightstylevalue[0] * (1.0f / 128.0f); - R_Mesh_State(&m); - r = texture->currentcolorbase[0] * colorscale; - g = texture->currentcolorbase[1] * colorscale; - b = texture->currentcolorbase[2] * colorscale; - a = texture->currentcolorbase[3]; - applycolor = r != 1 || g != 1 || b != 1 || a != 1; - if (!(texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) - { - for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) - { - surface = texturesurfacelist[texturesurfaceindex]; - RSurf_SetVertexPointer(ent, texture, surface, modelorg); - R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f); - RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, lightmode ? lightmode : 1, applycolor, texture->currentfogallpasses); - GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); - GL_LockArrays(0, 0); - } - } - else - { - for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) - { - surface = texturesurfacelist[texturesurfaceindex]; - RSurf_SetVertexPointer(ent, texture, surface, modelorg); - R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f); - RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, 0, applycolor, texture->currentfogallpasses); - GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); - GL_LockArrays(0, 0); - } - } - } - if (texture->currentdopants) - { - GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); - memset(&m, 0, sizeof(m)); - m.tex[0] = R_GetTexture(texture->skin.pants); - m.texmatrix[0] = texture->currenttexmatrix; - m.pointer_color = varray_color4f; - colorscale = 2; - if (gl_combine.integer) - { - m.texrgbscale[0] = 2; - colorscale = 1; - } - // transparent is not affected by r_lightmapintensity - if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)) - colorscale *= r_lightmapintensity; - // q3bsp has no lightmap updates, so the lightstylevalue that - // would normally be baked into the lightmaptexture must be - // applied to the color - if (!(texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) && !texture->currentdofullbrightpants && ent->model->type == mod_brushq3) - colorscale *= d_lightstylevalue[0] * (1.0f / 128.0f); - R_Mesh_State(&m); - r = texture->currentcolorpants[0] * colorscale; - g = texture->currentcolorpants[1] * colorscale; - b = texture->currentcolorpants[2] * colorscale; - a = texture->currentcolorpants[3]; - applycolor = r != 1 || g != 1 || b != 1 || a != 1; - if (!(texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) && !texture->currentdofullbrightpants) - { - for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) - { - surface = texturesurfacelist[texturesurfaceindex]; - RSurf_SetVertexPointer(ent, texture, surface, modelorg); - R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f); - RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, lightmode, applycolor, texture->currentfogallpasses); - GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); - GL_LockArrays(0, 0); - } - } - else + // if trying to do overbright on first pass of an opaque surface + // when combine is not supported, brighten as a post process + if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask) { + int scale; + GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); + GL_Color(1, 1, 1, 1); + memset(&m, 0, sizeof(m)); + R_Mesh_State(&m); for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) { surface = texturesurfacelist[texturesurfaceindex]; RSurf_SetVertexPointer(ent, texture, surface, modelorg); - R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f); - RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, 0, applycolor, texture->currentfogallpasses); GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); + for (scale = 1;scale < layertexrgbscale;scale <<= 1) + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); GL_LockArrays(0, 0); } } } - if (texture->currentdoshirt) + if (r_shownormals.integer && !r_showtrispass) { - GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); + int j, k; + float v[3]; + GL_DepthTest(true); + GL_DepthMask(texture->currentlayers->depthmask); + GL_BlendFunc(texture->currentlayers->blendfunc1, texture->currentlayers->blendfunc2); memset(&m, 0, sizeof(m)); - m.tex[0] = R_GetTexture(texture->skin.shirt); - m.texmatrix[0] = texture->currenttexmatrix; - m.pointer_color = varray_color4f; - colorscale = 2; - if (gl_combine.integer) - { - m.texrgbscale[0] = 2; - colorscale = 1; - } - // transparent is not affected by r_lightmapintensity - if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)) - colorscale *= r_lightmapintensity; - // q3bsp has no lightmap updates, so the lightstylevalue that - // would normally be baked into the lightmaptexture must be - // applied to the color - if (!(texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) && !texture->currentdofullbrightshirt && ent->model->type == mod_brushq3) - colorscale *= d_lightstylevalue[0] * (1.0f / 128.0f); R_Mesh_State(&m); - r = texture->currentcolorshirt[0] * colorscale; - g = texture->currentcolorshirt[1] * colorscale; - b = texture->currentcolorshirt[2] * colorscale; - a = texture->currentcolorshirt[3]; - applycolor = r != 1 || g != 1 || b != 1 || a != 1; - if (!(texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) && !texture->currentdofullbrightshirt) + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) { - for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) + surface = texturesurfacelist[texturesurfaceindex]; + RSurf_SetVertexPointer(ent, texture, surface, modelorg); + if (!rsurface_svector3f) { - surface = texturesurfacelist[texturesurfaceindex]; - RSurf_SetVertexPointer(ent, texture, surface, modelorg); - R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f); - RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, lightmode, applycolor, texture->currentfogallpasses); - GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); - GL_LockArrays(0, 0); + rsurface_svector3f = varray_svector3f; + rsurface_tvector3f = varray_tvector3f; + rsurface_normal3f = varray_normal3f; + Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_texcoordtexture2f, surface->groupmesh->data_element3i + surface->num_firsttriangle * 3, rsurface_svector3f, rsurface_tvector3f, rsurface_normal3f, r_smoothnormals_areaweighting.integer); } - } - else - { - for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) + GL_Color(1, 0, 0, 1); + qglBegin(GL_LINES); + for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++) { - surface = texturesurfacelist[texturesurfaceindex]; - RSurf_SetVertexPointer(ent, texture, surface, modelorg); - R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f); - RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, 0, applycolor, texture->currentfogallpasses); - GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); - GL_LockArrays(0, 0); + VectorCopy(rsurface_vertex3f + k * 3, v); + qglVertex3f(v[0], v[1], v[2]); + VectorMA(v, 8, rsurface_svector3f + k * 3, v); + qglVertex3f(v[0], v[1], v[2]); } - } - } - if (r_ambient.value >= (1/64.0f)) - { - GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); - GL_DepthMask(false); - memset(&m, 0, sizeof(m)); - m.tex[0] = R_GetTexture(texture->skin.base); - m.texmatrix[0] = texture->currenttexmatrix; - m.pointer_color = varray_color4f; - colorscale = 1; - if (gl_combine.integer && (ent->colormod[0] > 1 || ent->colormod[1] > 1 || ent->colormod[2] > 1)) - { - m.texrgbscale[0] = 4; - colorscale = 0.25f; - } - R_Mesh_State(&m); - colorscale *= r_ambient.value * (1.0f / 64.0f); - r = texture->currentcolorbase[0] * colorscale; - g = texture->currentcolorbase[1] * colorscale; - b = texture->currentcolorbase[2] * colorscale; - a = texture->currentcolorbase[3]; - applycolor = r != 1 || g != 1 || b != 1 || a != 1; - for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) - { - surface = texturesurfacelist[texturesurfaceindex]; - RSurf_SetVertexPointer(ent, texture, surface, modelorg); - R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f); - RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, 0, applycolor, texture->currentfogallpasses); - GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); - GL_LockArrays(0, 0); - } - } - if (texture->skin.glow != NULL) - { - // if glow was not already done using multitexture, do it now. - GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); - GL_DepthMask(false); - memset(&m, 0, sizeof(m)); - m.tex[0] = R_GetTexture(texture->skin.glow); - m.texmatrix[0] = texture->currenttexmatrix; - m.pointer_color = varray_color4f; - R_Mesh_State(&m); - r = 1; - g = 1; - b = 1; - a = texture->currentcolorbase[3]; - applycolor = r != 1 || g != 1 || b != 1 || a != 1; - for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) - { - surface = texturesurfacelist[texturesurfaceindex]; - RSurf_SetVertexPointer(ent, texture, surface, modelorg); - R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f); - RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, 0, applycolor, texture->currentfogallpasses); - GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); - GL_LockArrays(0, 0); - } - } - if (fogenabled && !(texture->currentmaterialflags & MATERIALFLAG_ADD)) - { - // if this is opaque use alpha blend which will darken the earlier - // passes cheaply. - // - // if this is an alpha blended material, all the earlier passes - // were darkened by fog already, so we only need to add the fog - // color ontop through the fog mask texture - // - // if this is an additive blended material, all the earlier passes - // were darkened by fog already, and we should not add fog color - // (because the background was not darkened, there is no fog color - // that was lost behind it). - if (texture->currentfogallpasses) - GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); - else - GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - GL_DepthMask(false); - memset(&m, 0, sizeof(m)); - m.tex[0] = R_GetTexture(texture->skin.fog); - m.texmatrix[0] = texture->currenttexmatrix; - R_Mesh_State(&m); - r = fogcolor[0]; - g = fogcolor[1]; - b = fogcolor[2]; - a = texture->currentcolorbase[3]; - applycolor = r != 1 || g != 1 || b != 1 || a != 1; - for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) - { - surface = texturesurfacelist[texturesurfaceindex]; - RSurf_SetVertexPointer(ent, texture, surface, modelorg); - R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f); - R_Mesh_ColorPointer(varray_color4f); - //RSurf_FogPassColors_Vertex3f_Color4f((surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex), varray_color4f, fogcolor[0], fogcolor[1], fogcolor[2], texture->currentcolorbase[3], 1, surface->num_vertices, modelorg); - if (!surface->lightmaptexture && surface->groupmesh->data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)) + GL_Color(0, 0, 1, 1); + for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++) { - for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4) - { - VectorSubtract(v, modelorg, diff); - f = exp(fogdensity/DotProduct(diff, diff)); - c[0] = r; - c[1] = g; - c[2] = b; - c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * f * a; - } + VectorCopy(rsurface_vertex3f + k * 3, v); + qglVertex3f(v[0], v[1], v[2]); + VectorMA(v, 8, rsurface_tvector3f + k * 3, v); + qglVertex3f(v[0], v[1], v[2]); } - else + GL_Color(0, 1, 0, 1); + for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++) { - for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4) - { - VectorSubtract(v, modelorg, diff); - f = exp(fogdensity/DotProduct(diff, diff)); - c[0] = r; - c[1] = g; - c[2] = b; - c[3] = f * a; - } + VectorCopy(rsurface_vertex3f + k * 3, v); + qglVertex3f(v[0], v[1], v[2]); + VectorMA(v, 8, rsurface_normal3f + k * 3, v); + qglVertex3f(v[0], v[1], v[2]); } - GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); - GL_LockArrays(0, 0); + qglEnd(); } } } -} - if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) + if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE)) qglEnable(GL_CULL_FACE); } -static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata2) +static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight) { - const entity_render_t *ent = calldata1; - const msurface_t *surface = ent->model->data_surfaces + calldata2; + const msurface_t *surface = ent->model->data_surfaces + surfacenumber; vec3_t modelorg; texture_t *texture; @@ -2558,7 +2275,7 @@ void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int tex tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f; tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f; Matrix4x4_Transform(&ent->matrix, tempcenter, center); - R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, RSurfShader_Transparent_Callback, ent, surface - ent->model->data_surfaces); + R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, ent, surface - ent->model->data_surfaces, r_shadow_rtlight); } } } @@ -2570,6 +2287,7 @@ extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface); void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces) { int i, j, f, flagsmask; + int counttriangles = 0; msurface_t *surface, **surfacechain; texture_t *t, *texture; model_t *model = ent->model; @@ -2587,9 +2305,9 @@ void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces) { for (i = 0;i < model->brushq1.light_styles;i++) { - if (model->brushq1.light_stylevalue[i] != d_lightstylevalue[model->brushq1.light_style[i]]) + if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]]) { - model->brushq1.light_stylevalue[i] = d_lightstylevalue[model->brushq1.light_style[i]]; + model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]]; if ((surfacechain = model->brushq1.light_styleupdatechains[i])) for (;(surface = *surfacechain);surfacechain++) surface->cached_dlight = true; @@ -2627,6 +2345,7 @@ void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces) R_BuildLightMap(ent, surface); // add face to draw list surfacelist[numsurfacelist++] = surface; + counttriangles += surface->num_triangles; if (numsurfacelist >= maxsurfacelist) { R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg); @@ -2657,6 +2376,7 @@ void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces) R_BuildLightMap(ent, surface); // add face to draw list surfacelist[numsurfacelist++] = surface; + counttriangles += surface->num_triangles; if (numsurfacelist >= maxsurfacelist) { R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg); @@ -2667,5 +2387,7 @@ void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces) } if (numsurfacelist) R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg); + if (!r_showtrispass) + renderstats.entities_triangles += counttriangles; }