From 8d9024e33fc7f719661225438be6a67d3a915f5a Mon Sep 17 00:00:00 2001 From: Knightmare66 Date: Fri, 9 Jul 2021 21:44:55 -0400 Subject: [PATCH] Removed single-texuring surface rendering mode. Moved old functions to r_surface_singletex.c. Refactored some suface rendering functions. Moved some lightmap code from r_surface.c to r_warp.c. --- kmquake2.txt | 2 +- kmquake2_changelog.txt | 2 + renderer/r_glstate.c | 12 - renderer/r_light.c | 360 ++++++++- renderer/r_local.h | 35 +- renderer/r_main.c | 56 +- renderer/r_model.h | 13 +- renderer/r_surface.c | 1377 +++++++------------------------- renderer/r_surface_singletex.c | 924 +++++++++++++++++++++ renderer/r_warp.c | 6 +- 10 files changed, 1630 insertions(+), 1157 deletions(-) create mode 100644 renderer/r_surface_singletex.c diff --git a/kmquake2.txt b/kmquake2.txt index 89abed5..0e03654 100644 --- a/kmquake2.txt +++ b/kmquake2.txt @@ -135,7 +135,7 @@ How To Run "-portable" to the command line, or by placing an empty text file called "portable.cfg" in the baseq2 folder. An OpenGL 1.2 compatible 3D accelerator, OpenGL 1.4 support or higher (GeForce FX/Radeon 9500 or better) recommended. - (Note: 3Dfx cards are NOT supported) + Absolutely MUST have GL_ARB_multitexture support, 3Dfx cards are NOT supported. Pentium III or Athlon 800MHz+ At least 512MB of RAM (1 GB recommended) for 32-bit operating sytems, at least 2GB for 64-bit operating sytsems. diff --git a/kmquake2_changelog.txt b/kmquake2_changelog.txt index 465d4ce..c298b8d 100644 --- a/kmquake2_changelog.txt +++ b/kmquake2_changelog.txt @@ -41,6 +41,8 @@ Changes as of v0.20 update 8: - Added upscaling of the scrap image (with optional blending by Skuller from Q2Pro) used to atlas 8-bit HUD pics. Use cvar r_scrap_upscale to enable, value of 1 is pixel copy, value of 2 enables blending. Requires vid_restart for changes to take effect. + +- Removed the old, decrepit single-texturing surface rendering mode. GL_ARB_multitexture support is now required. - Now reads/writes savegames, config files, demos, etc. to /Saved Games/KMQuake2 on Windows Vista and later, and to My Documents/My Games/KMQuake2 on Windows 2000/XP/2003. diff --git a/renderer/r_glstate.c b/renderer/r_glstate.c index d0a9d8b..0be45cd 100644 --- a/renderer/r_glstate.c +++ b/renderer/r_glstate.c @@ -426,9 +426,6 @@ GL_EnableTexture */ void GL_EnableTexture (unsigned tmu) { - if (tmu > 0 && !glConfig.multitexture) - return; - if (tmu >= MAX_TEXTURE_UNITS || tmu >= glConfig.max_texunits) return; @@ -446,9 +443,6 @@ GL_DisableTexture */ void GL_DisableTexture (unsigned tmu) { - if (tmu > 0 && !glConfig.multitexture) - return; - if (tmu >= MAX_TEXTURE_UNITS || tmu >= glConfig.max_texunits) return; @@ -466,9 +460,6 @@ Only used for world drawing */ void GL_EnableMultitexture (qboolean enable) { - if (!glConfig.multitexture) - return; - if (enable) { GL_EnableTexture(1); @@ -490,9 +481,6 @@ GL_SelectTexture */ void GL_SelectTexture (unsigned tmu) { - if (!glConfig.multitexture) - return; - if (tmu >= MAX_TEXTURE_UNITS || tmu >= glConfig.max_texunits) return; diff --git a/renderer/r_light.c b/renderer/r_light.c index 38e6418..a20d191 100644 --- a/renderer/r_light.c +++ b/renderer/r_light.c @@ -26,7 +26,11 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA int r_dlightframecount; -void vectoangles (vec3_t value1, vec3_t angles); +gllightmapstate_t gl_lms; + +static void LM_InitBlock (void); +static void LM_UploadBlock (qboolean dynamic); +static qboolean LM_AllocBlock (int w, int h, int *x, int *y); //#define DLIGHT_CUTOFF 64 // Knightmare- no longer hard-coded @@ -566,7 +570,6 @@ void R_SurfLightPoint (msurface_t *surf, vec3_t p, vec3_t color, qboolean baseli if (baselight) { -#if 1 VectorCopy (vec3_origin, bestColor); for (i=0; i<9; i++) // test multiple offset points to avoid dark corners, select brightest { @@ -583,31 +586,18 @@ void R_SurfLightPoint (msurface_t *surf, vec3_t p, vec3_t color, qboolean baseli if ( (r != -1) && (VectorLength(pointcolor) > VectorLength(bestColor)) ) VectorCopy (pointcolor, bestColor); } -#else - for (i=0; i<4; i++) // test multiple points to avoid dark corners - { - VectorCopy (p, start); - VectorAdd (start, startOffset[i], start); - end[0] = start[0]; - end[1] = start[1]; - end[2] = start[2] - 2048; - - r = RecursiveLightPoint (r_worldmodel->nodes, start, end); - - if (r != -1) break; - } -#endif /* end[0] = p[0]; end[1] = p[1]; end[2] = p[2] - 2048; r = RecursiveLightPoint (r_worldmodel->nodes, p, end); - */ + if (r == -1) VectorCopy (vec3_origin, color); else - VectorCopy (pointcolor, color); + VectorCopy (pointcolor, color);*/ + VectorCopy (bestColor, color); // this catches too bright modulated color for (i=0; i<3; i++) @@ -641,7 +631,7 @@ void R_SurfLightPoint (msurface_t *surf, vec3_t p, vec3_t color, qboolean baseli } VectorSubtract (p, dlorigin, dist); // end Knightmare - //VectorSubtract (p, dl->origin, dist); + // VectorSubtract (p, dl->origin, dist); add = dl->intensity - VectorLength(dist); add *= (DIV256); @@ -734,7 +724,7 @@ void R_ShadowLight (vec3_t pos, vec3_t lightAdd) //=================================================================== -static float s_blocklights[128*128*4]; //Knightmare- was [34*34*3], supports max chop size of 2048? +static float s_blocklights[136*136*3]; //Knightmare- was [34*34*3], supports max chop size of 2048? /* =============== R_AddDynamicLights @@ -776,11 +766,9 @@ void R_AddDynamicLights (msurface_t *surf) VectorCopy (currententity->angles, entAngles); } -// if (currententity->angles[0] || currententity->angles[1] || currententity->angles[2]) if (entAngles[0] || entAngles[1] || entAngles[2]) { rotated = true; - // AngleVectors (currententity->angles, forward, right, up); AngleVectors (entAngles, forward, right, up); } @@ -798,7 +786,6 @@ void R_AddDynamicLights (msurface_t *surf) frad = dl->intensity; VectorCopy (dl->origin, dlorigin); - // VectorSubtract (dlorigin, currententity->origin, dlorigin); VectorSubtract (dlorigin, entOrigin, dlorigin); if (rotated) @@ -858,6 +845,137 @@ void R_AddDynamicLights (msurface_t *surf) } } +/* +============================================================================= + + LIGHTMAP ALLOCATION + +============================================================================= +*/ + +/* +================ +LM_InitBlock +================ +*/ +static void LM_InitBlock (void) +{ + memset( gl_lms.allocated, 0, sizeof( gl_lms.allocated ) ); + +#ifdef BATCH_LM_UPDATES + // alloc lightmap update buffer if needed + if (!gl_lms.lightmap_update[gl_lms.current_lightmap_texture]) { + gl_lms.lightmap_update[gl_lms.current_lightmap_texture] = Z_Malloc (LM_BLOCK_WIDTH*LM_BLOCK_HEIGHT*LIGHTMAP_BYTES); + } +#endif // BATCH_LM_UPDATES +} + + +/* +================ +LM_UploadBlock +================ +*/ +static void LM_UploadBlock (qboolean dynamic) +{ + int texture; + int height = 0; + + if ( dynamic ) + { + texture = 0; + } + else + { + texture = gl_lms.current_lightmap_texture; + } + + GL_Bind( glState.lightmap_textures + texture ); + qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + if ( dynamic ) + { + int i; + + for ( i = 0; i < LM_BLOCK_WIDTH; i++ ) + { + if ( gl_lms.allocated[i] > height ) + height = gl_lms.allocated[i]; + } + + qglTexSubImage2D( GL_TEXTURE_2D, + 0, + 0, 0, + LM_BLOCK_WIDTH, height, + gl_lms.format, + gl_lms.type, + // GL_LIGHTMAP_FORMAT, + // GL_UNSIGNED_BYTE, + gl_lms.lightmap_buffer ); + } + else + { + qglTexImage2D( GL_TEXTURE_2D, + 0, + gl_lms.internal_format, + LM_BLOCK_WIDTH, LM_BLOCK_HEIGHT, + 0, + gl_lms.format, + gl_lms.type, + // GL_LIGHTMAP_FORMAT, + // GL_UNSIGNED_BYTE, +#ifdef BATCH_LM_UPDATES + gl_lms.lightmap_update[gl_lms.current_lightmap_texture] ); +#else + gl_lms.lightmap_buffer ); +#endif // BATCH_LM_UPDATES + if ( ++gl_lms.current_lightmap_texture == MAX_LIGHTMAPS ) + VID_Error( ERR_DROP, "LM_UploadBlock() - MAX_LIGHTMAPS exceeded\n" ); + } +} + + +/* +================ +LM_AllocBlock +returns a texture number and the position inside it +================ +*/ +static qboolean LM_AllocBlock (int w, int h, int *x, int *y) +{ + int i, j; + int best, best2; + + best = LM_BLOCK_HEIGHT; + + for (i=0 ; i= best) + break; + if (gl_lms.allocated[i+j] > best2) + best2 = gl_lms.allocated[i+j]; + } + if (j == w) + { // this is a valid spot + *x = i; + *y = best = best2; + } + } + + if (best + h > LM_BLOCK_HEIGHT) + return false; + + for (i=0 ; iflags & (SURF_DRAWSKY|SURF_DRAWTURB)) + return; + + //if (surf->texinfo->flags & (SURF_SKY|SURF_TRANS33|SURF_TRANS66|SURF_WARP)) + if (surf->texinfo->flags & (SURF_SKY|SURF_WARP)) + return; + + smax = (surf->extents[0]>>4)+1; + tmax = (surf->extents[1]>>4)+1; + + if ( !LM_AllocBlock (smax, tmax, &surf->light_s, &surf->light_t) ) + { + LM_UploadBlock (false); + LM_InitBlock(); + if ( !LM_AllocBlock (smax, tmax, &surf->light_s, &surf->light_t) ) + { + VID_Error (ERR_FATAL, "Consecutive calls to LM_AllocBlock(%d,%d) failed\n", smax, tmax); + } + } + + surf->lightmaptexturenum = gl_lms.current_lightmap_texture; + + // copy extents + surf->light_smax = smax; + surf->light_tmax = tmax; + +#ifdef BATCH_LM_UPDATES + base = gl_lms.lightmap_update[surf->lightmaptexturenum]; +#else + base = gl_lms.lightmap_buffer; +#endif // BATCH_LM_UPDATES + + base += (surf->light_t * LM_BLOCK_WIDTH + surf->light_s); // * LIGHTMAP_BYTES + + R_SetCacheState (surf); + R_BuildLightMap (surf, (void *)base, LM_BLOCK_WIDTH*LIGHTMAP_BYTES); +} + + +#define gl_tex_solid_format 3 +#define gl_tex_alpha_format 4 +/* +================== +R_BeginBuildingLightmaps +================== +*/ +void R_BeginBuildingLightmaps (model_t *m) +{ + static lightstyle_t lightstyles[MAX_LIGHTSTYLES]; + int i; + unsigned dummy[LM_BLOCK_WIDTH*LM_BLOCK_HEIGHT]; // 128*128 + + memset( gl_lms.allocated, 0, sizeof(gl_lms.allocated) ); + +#ifdef BATCH_LM_UPDATES + // free lightmap update buffers + for (i=0; istring[0] ) == 'A' ) + { + gl_lms.internal_format = gl_tex_alpha_format; + } + // try to do hacked colored lighting with a blended texture + else if ( toupper( r_monolightmap->string[0] ) == 'C' ) + { + gl_lms.internal_format = gl_tex_alpha_format; + } + else if ( toupper( r_monolightmap->string[0] ) == 'I' ) + { + gl_lms.internal_format = GL_INTENSITY8; + } + else if ( toupper( r_monolightmap->string[0] ) == 'L' ) + { + gl_lms.internal_format = GL_LUMINANCE8; + } + else + { + gl_lms.internal_format = gl_tex_solid_format; + } + + gl_lms.format = GL_RGBA; + gl_lms.type = GL_UNSIGNED_BYTE; + } + else + { + if ( toupper( r_monolightmap->string[0] ) == 'I' ) + gl_lms.internal_format = GL_INTENSITY8; + else if ( toupper( r_monolightmap->string[0] ) == 'L' ) + gl_lms.internal_format = GL_LUMINANCE8; + else + gl_lms.internal_format = GL_RGBA8; + + gl_lms.format = GL_BGRA; + gl_lms.type = GL_UNSIGNED_INT_8_8_8_8_REV; + } + + // initialize the dynamic lightmap texture + GL_Bind( glState.lightmap_textures + 0 ); + qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + qglTexImage2D( GL_TEXTURE_2D, + 0, + gl_lms.internal_format, + LM_BLOCK_WIDTH, LM_BLOCK_HEIGHT, + 0, + gl_lms.format, + gl_lms.type, + // GL_LIGHTMAP_FORMAT, + // GL_UNSIGNED_BYTE, + dummy ); +} + + +/* +======================= +R_EndBuildingLightmaps +======================= +*/ +void R_EndBuildingLightmaps (void) +{ + LM_UploadBlock (false); + GL_EnableMultitexture (false); +} diff --git a/renderer/r_local.h b/renderer/r_local.h index a6d96ff..9b8024a 100644 --- a/renderer/r_local.h +++ b/renderer/r_local.h @@ -260,7 +260,6 @@ extern cvar_t *alt_text_color; //extern cvar_t *gl_ext_palettedtexture; //extern cvar_t *gl_ext_pointparameters; //extern cvar_t *r_ext_swapinterval; // unused -extern cvar_t *r_ext_multitexture; extern cvar_t *r_ext_draw_range_elements; extern cvar_t *r_ext_compiled_vertex_array; extern cvar_t *r_arb_texturenonpoweroftwo; @@ -470,9 +469,17 @@ extern gllightmapstate_t gl_lms; //void R_LightPoint (vec3_t p, vec3_t color); void R_LightPoint (vec3_t p, vec3_t color, qboolean isEnt); void R_LightPointDynamics (vec3_t p, vec3_t color, m_dlight_t *list, int *amount, int max); +void R_SurfLightPoint (msurface_t *surf, vec3_t p, vec3_t color, qboolean baselight); void R_PushDlights (void); void R_ShadowLight (vec3_t pos, vec3_t lightAdd); void R_MarkLights (dlight_t *light, int bit, mnode_t *node); +void R_RenderDlights (void); +void R_AddDynamicLights (msurface_t *surf); +void R_SetCacheState (msurface_t *surf); +void R_BuildLightMap (msurface_t *surf, byte *dest, int stride); +void R_CreateSurfaceLightmap (msurface_t *surf); +void R_EndBuildingLightmaps (void); +void R_BeginBuildingLightmaps (model_t *m); //==================================================================== @@ -484,6 +491,11 @@ extern float d_8to24tablef[256][3]; //Knightmare added extern int registration_sequence; +// +// cl_utils.c +// +void vectoangles (vec3_t value1, vec3_t angles); + void V_AddBlend (float r, float g, float b, float a, float *v_blend); // @@ -524,7 +536,7 @@ void R_DrawSpriteModel (entity_t *e); void R_DrawBeam( entity_t *e ); void R_DrawWorld (void); void R_RenderDlights (void); -void R_DrawAlphaSurfaces (void); +void R_DrawAllAlphaSurfaces (void); void R_RenderBrushPoly (msurface_t *fa); void R_InitMedia (void); void R_DrawInitLocal (void); @@ -645,8 +657,23 @@ void R_DrawSkyBox (void); // -// r_surf.c +// r_surface.c // +//extern surfaceHandle_t r_surfaceHandles[MAX_SURFACE_HANDLES]; + +void R_DrawWorld (void); +void R_DrawAllAlphaSurfaces (void); +void R_RenderBrushPoly (msurface_t *fa); +void R_DrawBrushModel (entity_t *e); +void R_MarkLeaves (void); +qboolean R_CullBox (vec3_t mins, vec3_t maxs); +void R_BuildPolygonFromSurface (msurface_t *surf); +void R_ResetVertextLights_f (void); +void R_BuildVertexLight (msurface_t *surf); +#ifdef BATCH_LM_UPDATES +void R_UpdateSurfaceLightmap (msurface_t *surf); +void R_RebuildLightmaps (void); +#endif // @@ -841,7 +868,7 @@ typedef struct qboolean arbTextureNonPowerOfTwo; qboolean vertexBufferObject; - qboolean multitexture; +// qboolean multitexture; qboolean mtexcombine; // added Vic's RGB brightening qboolean have_stencil; diff --git a/renderer/r_main.c b/renderer/r_main.c index 3c80a8e..b6fc187 100644 --- a/renderer/r_main.c +++ b/renderer/r_main.c @@ -118,7 +118,6 @@ cvar_t *r_rgbscale; // Vic's RGB brightening //cvar_t *r_vertex_arrays; // unused //cvar_t *r_ext_swapinterval; // unused -cvar_t *r_ext_multitexture; cvar_t *r_ext_draw_range_elements; cvar_t *r_ext_compiled_vertex_array; cvar_t *r_arb_texturenonpoweroftwo; // Knightmare- non-power-of-two texture support @@ -719,7 +718,7 @@ void R_RenderView (refdef_t *fd) R_DrawEntitiesOnList(ents_viewweaps); R_ParticleStencil (1); - R_DrawAlphaSurfaces (); + R_DrawAllAlphaSurfaces (); R_ParticleStencil (2); R_ParticleStencil (3); @@ -1106,8 +1105,6 @@ void R_Register (void) // gl_ext_palettedtexture = Cvar_Get( "gl_ext_palettedtexture", "0", CVAR_ARCHIVE ); // gl_ext_pointparameters = Cvar_Get( "gl_ext_pointparameters", "1", CVAR_ARCHIVE ); // r_ext_swapinterval = Cvar_Get( "r_ext_swapinterval", "1", CVAR_ARCHIVE ); // unused - r_ext_multitexture = Cvar_Get( "r_ext_multitexture", "1", CVAR_ARCHIVE ); - Cvar_SetDescription ("r_ext_multitexture", "Enables multitexture rendering of lightmapped surfaces."); r_ext_draw_range_elements = Cvar_Get("r_ext_draw_range_elements", "1", CVAR_ARCHIVE /*| CVAR_LATCH*/); Cvar_SetDescription ("r_ext_draw_range_elements", "Enables use of glDrawRangeElements()."); r_ext_compiled_vertex_array = Cvar_Get( "r_ext_compiled_vertex_array", "1", CVAR_ARCHIVE ); @@ -1354,47 +1351,52 @@ Grabs GL extensions */ qboolean R_CheckGLExtensions (char *reason) { + qboolean multitexture_found = false; + // OpenGL multitexture on GL 1.2.1 or later or GL_ARB_multitexture - glConfig.multitexture = false; - glConfig.max_texunits = 1; + // This is checked first, is required + glConfig.max_texunits = 2; // must have at least 2 if ( (glConfig.version_major >= 2) || (glConfig.version_major == 1 && glConfig.version_minor > 2) || (glConfig.version_major == 1 && glConfig.version_minor == 2 && glConfig.version_release >= 1) ) { qglMultiTexCoord2fARB = (void *) qwglGetProcAddress( "glMultiTexCoord2f" ); qglActiveTextureARB = (void *) qwglGetProcAddress( "glActiveTexture" ); qglClientActiveTextureARB = (void *) qwglGetProcAddress( "glClientActiveTexture" ); - if (!qglMultiTexCoord2fARB || !qglActiveTextureARB || !qglClientActiveTextureARB) - { + if (!qglMultiTexCoord2fARB || !qglActiveTextureARB || !qglClientActiveTextureARB) { VID_Printf (PRINT_ALL, "...OpenGL multitexture not found, checking for GL_ARB_multitexture\n" ); } else { VID_Printf (PRINT_ALL, "...using OpenGL multitexture\n" ); qglGetIntegerv(GL_MAX_TEXTURE_UNITS, &glConfig.max_texunits); VID_Printf (PRINT_ALL, "...GL_MAX_TEXTURE_UNITS: %i\n", glConfig.max_texunits); - glConfig.multitexture = true; + multitexture_found = true; } } - if ( (!glConfig.multitexture) && Q_StrScanToken( glConfig.extensions_string, "GL_ARB_multitexture", false ) ) + if ( (!multitexture_found) && Q_StrScanToken( glConfig.extensions_string, "GL_ARB_multitexture", false ) ) { - if (r_ext_multitexture->integer) - { - qglMultiTexCoord2fARB = (void *) qwglGetProcAddress( "glMultiTexCoord2fARB" ); - qglActiveTextureARB = (void *) qwglGetProcAddress( "glActiveTextureARB" ); - qglClientActiveTextureARB = (void *) qwglGetProcAddress( "glClientActiveTextureARB" ); - if (!qglMultiTexCoord2fARB || !qglActiveTextureARB || !qglClientActiveTextureARB) - VID_Printf (PRINT_ALL, "..." S_COLOR_RED "GL_ARB_multitexture not properly supported!\n"S_COLOR_YELLOW"WARNING: glow/caustic texture effects not enabled\n"); - else { - VID_Printf (PRINT_ALL, "...using GL_ARB_multitexture\n" ); - qglGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &glConfig.max_texunits); - VID_Printf (PRINT_ALL, "...GL_MAX_TEXTURE_UNITS_ARB: %i\n", glConfig.max_texunits); - glConfig.multitexture = true; - } + qglMultiTexCoord2fARB = (void *) qwglGetProcAddress( "glMultiTexCoord2fARB" ); + qglActiveTextureARB = (void *) qwglGetProcAddress( "glActiveTextureARB" ); + qglClientActiveTextureARB = (void *) qwglGetProcAddress( "glClientActiveTextureARB" ); + if (!qglMultiTexCoord2fARB || !qglActiveTextureARB || !qglClientActiveTextureARB) { + QGL_Shutdown(); + VID_Printf (PRINT_ALL, "R_Init() - GL_ARB_multitexture functions not implemented in driver!\n" ); + memcpy (reason, "GL_ARB_multitexture not properly implemented in driver!\0", 55); + return false; + } + else { + VID_Printf (PRINT_ALL, "...using GL_ARB_multitexture\n" ); + qglGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &glConfig.max_texunits); + VID_Printf (PRINT_ALL, "...GL_MAX_TEXTURE_UNITS_ARB: %i\n", glConfig.max_texunits); + multitexture_found = true; } - else - VID_Printf (PRINT_ALL, "...ignoring GL_ARB_multitexture\n"S_COLOR_YELLOW"WARNING: glow/caustic texture effects not enabled\n" ); } - if (!glConfig.multitexture) - VID_Printf (PRINT_ALL, "...GL_ARB_multitexture not found\n"S_COLOR_YELLOW"WARNING: glow/caustic texture effects not supported\n" ); + if (!multitexture_found) + { + QGL_Shutdown(); + VID_Printf (PRINT_ALL, "R_Init() - GL_ARB_multitexture not found\n" ); + memcpy (reason, "GL_ARB_multitexture not supported by driver!\0", 44); + return false; + } // GL_EXT_compiled_vertex_array // GL_SGI_compiled_vertex_array diff --git a/renderer/r_model.h b/renderer/r_model.h index dab02d2..7fa42e7 100644 --- a/renderer/r_model.h +++ b/renderer/r_model.h @@ -97,7 +97,7 @@ typedef struct vec2_t texture_st; vec2_t lightmap_st; byte basecolor[4]; - byte color[4]; + byte lightcolor[4]; } mpolyvertex_t; */ @@ -161,12 +161,13 @@ typedef struct msurface_s } msurface_t; -typedef struct malphasurface_s +typedef struct surfaceHandle_s { - msurface_t *surf; - entity_t *entity; // entity pointer - struct malphasurface_s *surfacechain; -} malphasurface_t; + msurface_t *surf; + entity_t *entity; // entity pointer + int flags; // entity-specific surface flags + struct surfaceHandle_s *surfacechain; // next surface +} surfaceHandle_t; typedef struct mnode_s diff --git a/renderer/r_surface.c b/renderer/r_surface.c index 7f27744..64bfed7 100644 --- a/renderer/r_surface.c +++ b/renderer/r_surface.c @@ -30,34 +30,21 @@ static vec3_t modelorg; // relative to viewpoint msurface_t *r_alpha_surfaces; +/* +#define MAX_SURFACE_HANDLES 2048 +surfaceHandle_t r_surfaceHandles[MAX_SURFACE_HANDLES]; +int r_numSurfaceHandles; +surfaceHandle_t *r_dup_alpha_surfaces; +*/ + int c_visible_lightmaps; int c_visible_textures; - -gllightmapstate_t gl_lms; - static void RB_DrawEnvMap (void); static void RB_DrawTexGlow (image_t *glowImage); static void RB_DrawCaustics (msurface_t *surf); static void R_DrawLightmappedSurface (msurface_t *surf, qboolean render); -static void LM_InitBlock (void); -static void LM_UploadBlock (qboolean dynamic); -static qboolean LM_AllocBlock (int w, int h, int *x, int *y); - -extern void R_SetCacheState( msurface_t *surf ); -extern void R_BuildLightMap (msurface_t *surf, byte *dest, int stride); - -void R_BuildVertexLight (msurface_t *surf); - -#ifdef BATCH_LM_UPDATES -void R_UpdateSurfaceLightmap (msurface_t *surf); -void R_RebuildLightmaps (void); -#endif - -// render lightmapped surfaces from texture chains -#define MULTITEXTURE_CHAINS - /* ============================================================= @@ -350,6 +337,73 @@ qboolean R_SurfHasEnvMap (msurface_t *s) } +/* +================ +R_SurfsAreBatchable +================ +*/ +qboolean R_SurfsAreBatchable (msurface_t *s1, msurface_t *s2) +{ + if (!s1 || !s2) + return false; + if (s1->entity != s2->entity) + return false; + if ((s1->flags & SURF_DRAWTURB) != (s2->flags & SURF_DRAWTURB)) + return false; + if ( ((s1->texinfo->flags & (SURF_TRANS33|SURF_TRANS66)) != 0) != ((s2->texinfo->flags & (SURF_TRANS33|SURF_TRANS66)) != 0) ) + return false; + if (R_TextureAnimation(s1) != R_TextureAnimation(s2)) + return false; + + if ( (s1->flags & SURF_DRAWTURB) && (s2->flags & SURF_DRAWTURB) ) + { + if (R_SurfIsLit(s1) != R_SurfIsLit(s2)) + return false; + return true; + } + else if ( (s1->texinfo->flags & (SURF_TRANS33|SURF_TRANS66)) + && (s2->texinfo->flags & (SURF_TRANS33|SURF_TRANS66)) ) + { + if (r_trans_lighting->integer == 2 + && ((R_SurfIsLit(s1) && s1->lightmaptexturenum) || (R_SurfIsLit(s2) && s2->lightmaptexturenum))) + return false; + if (R_SurfIsLit(s1) != R_SurfIsLit(s2)) + return false; + // must be single pass to be batchable + if ( r_glows->integer + && ((R_TextureAnimationGlow(s1) != glMedia.notexture) + || (R_TextureAnimationGlow(s2) != glMedia.notexture)) ) + return false; + if (R_SurfHasEnvMap(s1) || R_SurfHasEnvMap(s2)) + return false; + if ( r_caustics->integer + && ((s1->flags & SURF_MASK_CAUSTIC) || (s2->flags & SURF_MASK_CAUSTIC)) ) + return false; + return true; + } + else if ( !(s1->texinfo->flags & (SURF_WARP|SURF_TRANS33|SURF_TRANS66)) + && !(s2->texinfo->flags & (SURF_WARP|SURF_TRANS33|SURF_TRANS66)) ) // lightmapped surfaces + { + if (s1->lightmaptexturenum != s2->lightmaptexturenum) // lightmap image must be same + return false; +#ifndef BATCH_LM_UPDATES + if (R_SurfIsDynamic(s1, NULL) || R_SurfIsDynamic(s2, NULL)) // can't be dynamically list + return false; +#endif // BATCH_LM_UPDATES + if ((s1->texinfo->flags & SURF_ALPHATEST) != (s2->texinfo->flags & SURF_ALPHATEST)) + return false; + if (R_TextureAnimationGlow(s1) != R_TextureAnimationGlow(s2)) + return false; + if (R_SurfHasEnvMap(s1) != R_SurfHasEnvMap(s2)) + return false; + if ((s1->flags & SURF_MASK_CAUSTIC) != (s2->flags & SURF_MASK_CAUSTIC)) + return false; + return true; + } + return false; +} + + /* ================ RB_RenderGLPoly @@ -368,9 +422,9 @@ void RB_RenderGLPoly (msurface_t *surf, qboolean light) if (rb_vertex == 0 || rb_index == 0) // nothing to render return; - glowPass = ( r_glows->integer && (glow != glMedia.notexture) && glConfig.multitexture && light ); + glowPass = ( r_glows->integer && (glow != glMedia.notexture) && light ); envMap = R_SurfHasEnvMap (surf); - causticPass = ( r_caustics->integer && (surf->flags & SURF_MASK_CAUSTIC) && glConfig.multitexture && light ); + causticPass = ( r_caustics->integer && (surf->flags & SURF_MASK_CAUSTIC) && light ); c_brush_calls++; @@ -472,493 +526,86 @@ void R_DrawGLPoly (msurface_t *surf, qboolean render) RB_RenderGLPoly (surf, light); } -/* -================ -R_DrawWarpPoly -================ -*/ -void R_DrawWarpPoly (msurface_t *surf) -{ - if (!(surf->flags & SURF_DRAWTURB)) - return; - - R_BuildVertexLight (surf); - - // warp texture, no lightmaps - GL_EnableMultitexture (false); -// GL_TexEnv(GL_MODULATE); - - R_DrawWarpSurface (surf, 1.0, true); - -// GL_TexEnv(GL_REPLACE); - GL_EnableMultitexture (true); -} /* ================ -R_DrawTriangleOutlines +R_DrawAlphaSurface ================ */ -void R_DrawTriangleOutlines (void) +void R_DrawAlphaSurface (msurface_t *s, entity_t *e) { - int i, j, nv; - float *v; - msurface_t *surf; - glpoly_t *p; + qboolean light; - // not used in multitexture mode - if (glConfig.multitexture) - return; - if (!r_showtris->integer) + if (!s) return; - if (r_showtris->integer == 1) - GL_Disable(GL_DEPTH_TEST); + // go back to the world matrix + qglLoadMatrixf (r_world_matrix); - GL_DisableTexture (0); - qglPolygonMode (GL_FRONT_AND_BACK, GL_LINE); - - rb_vertex = rb_index = 0; - for (i = 0; i < MAX_LIGHTMAPS; i++) - { - for (surf = gl_lms.lightmap_surfaces[i]; surf != 0; surf = surf->lightmapchain) - { - for (p = surf->polys; p; p = p->chain) - { - v = p->verts[0]; - nv = p->numverts; - if (RB_CheckArrayOverflow (nv, (nv-2)*3)) - RB_RenderMeshGeneric (false); - for (j=0; j < nv-2; j++) { - indexArray[rb_index++] = rb_vertex; - indexArray[rb_index++] = rb_vertex+j+1; - indexArray[rb_index++] = rb_vertex+j+2; - } - for (j=0; j < nv; j++, v+= VERTEXSIZE) - { - VA_SetElem3(vertexArray[rb_vertex], v[0], v[1], v[2]); - VA_SetElem4(colorArray[rb_vertex], 1, 1, 1, 1); - rb_vertex++; - } - } - } - } -// RB_DrawArrays (); - RB_RenderMeshGeneric (false); - - qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL); - GL_EnableTexture(0); - - if (r_showtris->integer == 1) - GL_Enable(GL_DEPTH_TEST); -} - - -/* -================ -R_DrawGLPolyChain -================ -*/ -void R_DrawGLPolyChain (glpoly_t *p, float soffset, float toffset) -{ - float *v; - int j, nv; - - rb_vertex = rb_index = 0; - for ( ; p != 0; p = p->chain) - { - v = p->verts[0]; - nv = p->numverts; - if (RB_CheckArrayOverflow (nv, (nv-2)*3)) - RB_RenderMeshGeneric (false); - for (j=0; j < nv-2; j++) { - indexArray[rb_index++] = rb_vertex; - indexArray[rb_index++] = rb_vertex+j+1; - indexArray[rb_index++] = rb_vertex+j+2; - } - for (j=0; j < nv; j++, v+= VERTEXSIZE) - { - VA_SetElem2(texCoordArray[0][rb_vertex], v[5] - soffset, v[6] - toffset); - VA_SetElem3(vertexArray[rb_vertex], v[0], v[1], v[2]); - VA_SetElem4(colorArray[rb_vertex], 1, 1, 1, 1); - rb_vertex++; - } - } -// RB_DrawArrays (); - RB_RenderMeshGeneric (false); -} - - -/* -================ -R_BlendLightMaps - -This routine takes all the given light mapped surfaces in the world and -blends them into the framebuffer. -================ -*/ -void R_BlendLightmaps (void) -{ - int i; - msurface_t *surf, *newdrawsurf = 0; - - // not used in multitexture mode - if (glConfig.multitexture) - return; - // don't bother if we're set to fullbright - if (r_fullbright->integer) - return; - if (!r_worldmodel->lightdata) - return; - - // don't bother writing Z - GL_DepthMask (false); - - // set the appropriate blending mode unless we're only looking at the - // lightmaps. - if (!r_lightmap->integer) - { - GL_Enable (GL_BLEND); - - if (r_saturatelighting->integer) - { - GL_BlendFunc( GL_ONE, GL_ONE ); - } - else - { - if (r_monolightmap->string[0] != '0') - { - switch (toupper(r_monolightmap->string[0])) - { - case 'I': - GL_BlendFunc (GL_ZERO, GL_SRC_COLOR); - break; - case 'L': - GL_BlendFunc (GL_ZERO, GL_SRC_COLOR); - break; - case 'A': - default: - GL_BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - break; - } - } - else - { - GL_BlendFunc (GL_ZERO, GL_SRC_COLOR); - } - } - } - - if (currentmodel == r_worldmodel) - c_visible_lightmaps = 0; - - // render static lightmaps first - for (i = 1; i < MAX_LIGHTMAPS; i++) - { - if (gl_lms.lightmap_surfaces[i]) - { - if (currentmodel == r_worldmodel) - c_visible_lightmaps++; - GL_Bind( glState.lightmap_textures + i); - - for (surf = gl_lms.lightmap_surfaces[i]; surf != 0; surf = surf->lightmapchain) - { - if (surf->polys) - R_DrawGLPolyChain(surf->polys, 0, 0); - } - } - } - - // render dynamic lightmaps - if (r_dynamic->integer) - { - LM_InitBlock(); - - GL_Bind(glState.lightmap_textures+0); - - if (currentmodel == r_worldmodel) - c_visible_lightmaps++; - - newdrawsurf = gl_lms.lightmap_surfaces[0]; - - for (surf = gl_lms.lightmap_surfaces[0]; surf != 0; surf = surf->lightmapchain) - { - int smax, tmax; - unsigned *base; - - smax = (surf->extents[0]>>4)+1; - tmax = (surf->extents[1]>>4)+1; - - if ( LM_AllocBlock( smax, tmax, &surf->dlight_s, &surf->dlight_t ) ) - { - base = gl_lms.lightmap_buffer; - base += (surf->dlight_t * LM_BLOCK_WIDTH + surf->dlight_s); // * LIGHTMAP_BYTES - - R_BuildLightMap (surf, (void *)base, LM_BLOCK_WIDTH*LIGHTMAP_BYTES); - } - else - { - msurface_t *drawsurf; - - // upload what we have so far - LM_UploadBlock(true); - - // draw all surfaces that use this lightmap - for ( drawsurf = newdrawsurf; drawsurf != surf; drawsurf = drawsurf->lightmapchain ) - { - if (drawsurf->polys) - R_DrawGLPolyChain( drawsurf->polys, - (drawsurf->light_s - drawsurf->dlight_s) * (1.0 / 128.0), - (drawsurf->light_t - drawsurf->dlight_t) * (1.0 / 128.0) ); - } - - newdrawsurf = drawsurf; - - // clear the block - LM_InitBlock(); - - // try uploading the block now - if (!LM_AllocBlock(smax, tmax, &surf->dlight_s, &surf->dlight_t)) - { - VID_Error( ERR_FATAL, "Consecutive calls to LM_AllocBlock(%d,%d) failed (dynamic)\n", smax, tmax ); - } - - base = gl_lms.lightmap_buffer; - base += (surf->dlight_t * LM_BLOCK_WIDTH + surf->dlight_s); // * LIGHTMAP_BYTES - - R_BuildLightMap (surf, (void *)base, LM_BLOCK_WIDTH*LIGHTMAP_BYTES); - } - } - - // draw remainder of dynamic lightmaps that haven't been uploaded yet - if (newdrawsurf) - LM_UploadBlock( true ); - - for (surf = newdrawsurf; surf != 0; surf = surf->lightmapchain) - { - if (surf->polys) - R_DrawGLPolyChain( surf->polys, (surf->light_s - surf->dlight_s) * (1.0 / 128.0), (surf->light_t - surf->dlight_t) * (1.0 / 128.0) ); - } - } - - // restore state - GL_Disable (GL_BLEND); + R_BuildVertexLight (s); + GL_Enable (GL_BLEND); + GL_TexEnv (GL_MODULATE); GL_BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - GL_DepthMask (true); -} + // disable depth testing for all bmodel surfs except solid alphas + if ( s->entity && !((s->flags & SURF_TRANS33) && (s->flags & SURF_TRANS66)) ) + GL_DepthMask (false); + else + GL_DepthMask (true); -/* -================ -R_RenderBrushPoly -================ -*/ -void R_RenderBrushPoly (msurface_t *fa) -{ - int maps; -// qboolean is_dynamic = false; + // moving trans brushes - spaz + if (s->entity) + R_RotateForEntity (s->entity, true); - if (fa->flags & SURF_DRAWTURB) - { - R_BuildVertexLight (fa); + light = R_SurfIsLit(s); +// solidAlpha = ( (s->texinfo->flags & SURF_TRANS33|SURF_TRANS66) == SURF_TRANS33|SURF_TRANS66 ); +// envMap = ( (s->flags & SURF_ENVMAP) && r_glass_envmaps->integer && !solidAlpha); - // warp texture, no lightmaps - GL_TexEnv(GL_MODULATE); - - R_DrawWarpSurface (fa, 1.0, true); - - GL_TexEnv(GL_REPLACE); - - return; + if (s->flags & SURF_DRAWTURB) { + R_DrawWarpSurface (s, R_SurfAlphaCalc(s->texinfo->flags), !R_SurfsAreBatchable (s, s->texturechain)); } - - GL_TexEnv(GL_REPLACE); - - R_DrawGLPoly (fa, true); - -#if 0 - // - // check for lightmap modification - // - for (maps = 0; maps < MAXLIGHTMAPS && fa->styles[maps] != 255; maps++) + else if ( (r_trans_lighting->integer == 2) && light && s->lightmaptexturenum ) { - if (r_newrefdef.lightstyles[fa->styles[maps]].white != fa->cached_light[maps]) - goto dynamic; - } - - // dynamic this frame or dynamic previously - if ((fa->dlightframe == r_framecount)) - { -dynamic: - if (r_dynamic->integer) - { - if ( !(fa->texinfo->flags & (SURF_SKY|SURF_TRANS33|SURF_TRANS66|SURF_WARP)) ) - { - is_dynamic = true; - } - } - } -#endif - - if (R_SurfIsDynamic(fa, &maps)) - { - if ( (fa->styles[maps] >= 32 || fa->styles[maps] == 0) && (fa->dlightframe != r_framecount) ) - { - unsigned temp[34*34]; - int smax, tmax; - - smax = (fa->extents[0]>>4)+1; - tmax = (fa->extents[1]>>4)+1; - - R_BuildLightMap(fa, (void *)temp, smax*4); - R_SetCacheState(fa); - - GL_Bind(glState.lightmap_textures + fa->lightmaptexturenum); - - qglTexSubImage2D( GL_TEXTURE_2D, 0, - fa->light_s, fa->light_t, - smax, tmax, - // GL_LIGHTMAP_FORMAT, GL_UNSIGNED_BYTE, - gl_lms.format, gl_lms.type, - temp); - - fa->lightmapchain = gl_lms.lightmap_surfaces[fa->lightmaptexturenum]; - gl_lms.lightmap_surfaces[fa->lightmaptexturenum] = fa; - } - else - { - fa->lightmapchain = gl_lms.lightmap_surfaces[0]; - gl_lms.lightmap_surfaces[0] = fa; - } + GL_EnableMultitexture (true); + R_SetLightingMode (RF_TRANSLUCENT); + R_DrawLightmappedSurface (s, true); + GL_EnableMultitexture (false); } else - { - fa->lightmapchain = gl_lms.lightmap_surfaces[fa->lightmaptexturenum]; - gl_lms.lightmap_surfaces[fa->lightmaptexturenum] = fa; - } + R_DrawGLPoly (s, !R_SurfsAreBatchable (s, s->texturechain));// true); } /* ================ -R_SurfsAreBatchable -================ -*/ -qboolean R_SurfsAreBatchable (msurface_t *s1, msurface_t *s2) -{ - if (!s1 || !s2) - return false; - if (s1->entity != s2->entity) - return false; - if ((s1->flags & SURF_DRAWTURB) != (s2->flags & SURF_DRAWTURB)) - return false; - if ( ((s1->texinfo->flags & (SURF_TRANS33|SURF_TRANS66)) != 0) != ((s2->texinfo->flags & (SURF_TRANS33|SURF_TRANS66)) != 0) ) - return false; - if (R_TextureAnimation(s1) != R_TextureAnimation(s2)) - return false; - - if ( (s1->flags & SURF_DRAWTURB) && (s2->flags & SURF_DRAWTURB) ) - { - if (R_SurfIsLit(s1) != R_SurfIsLit(s2)) - return false; - return true; - } - else if ( (s1->texinfo->flags & (SURF_TRANS33|SURF_TRANS66)) - && (s2->texinfo->flags & (SURF_TRANS33|SURF_TRANS66)) ) - { - if (r_trans_lighting->integer == 2 - && ((R_SurfIsLit(s1) && s1->lightmaptexturenum) || (R_SurfIsLit(s2) && s2->lightmaptexturenum))) - return false; - if (R_SurfIsLit(s1) != R_SurfIsLit(s2)) - return false; - // must be single pass to be batchable - if ( r_glows->integer - && ((R_TextureAnimationGlow(s1) != glMedia.notexture) - || (R_TextureAnimationGlow(s2) != glMedia.notexture)) ) - return false; - if (R_SurfHasEnvMap(s1) || R_SurfHasEnvMap(s2)) - return false; - if ( r_caustics->integer - && ((s1->flags & SURF_MASK_CAUSTIC) || (s2->flags & SURF_MASK_CAUSTIC)) ) - return false; - return true; - } - else if ( !(s1->texinfo->flags & (SURF_DRAWTURB|SURF_TRANS33|SURF_TRANS66)) - && !(s2->texinfo->flags & (SURF_DRAWTURB|SURF_TRANS33|SURF_TRANS66)) ) // lightmapped surfaces - { - if (s1->lightmaptexturenum != s2->lightmaptexturenum) // lightmap image must be same - return false; -#ifndef BATCH_LM_UPDATES - if (R_SurfIsDynamic(s1, NULL) || R_SurfIsDynamic(s2, NULL)) // can't be dynamically list - return false; -#endif // BATCH_LM_UPDATES - if ((s1->texinfo->flags & SURF_ALPHATEST) != (s2->texinfo->flags & SURF_ALPHATEST)) - return false; - if (R_TextureAnimationGlow(s1) != R_TextureAnimationGlow(s2)) - return false; - if (R_SurfHasEnvMap(s1) != R_SurfHasEnvMap(s2)) - return false; - if ((s1->flags & SURF_MASK_CAUSTIC) != (s2->flags & SURF_MASK_CAUSTIC)) - return false; - return true; - } - return false; -} - - -/* -================ -R_DrawAlphaSurfaces +R_DrawAllAlphaSurfaces Draw trans water surfaces and windows. The BSP tree is waled front to back, so unwinding the chain of alpha_surfaces will draw back to front, giving proper ordering. ================ */ -void R_DrawAlphaSurfaces (void) +void R_DrawAllAlphaSurfaces (void) { msurface_t *s; - qboolean light;//solidAlpha, envMap; +// surfaceHandle_t *h; +// int oldFlags; // the textures are prescaled up for a better lighting range, // so scale it back down rb_vertex = rb_index = 0; - for (s = r_alpha_surfaces; s; s = s->texturechain) - { - // go back to the world matrix - qglLoadMatrixf (r_world_matrix); - - R_BuildVertexLight (s); - GL_Enable (GL_BLEND); - GL_TexEnv (GL_MODULATE); - GL_BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - // disable depth testing for all bmodel surfs except solid alphas - if ( s->entity && !((s->flags & SURF_TRANS33) && (s->flags & SURF_TRANS66)) ) - GL_DepthMask (false); - else - GL_DepthMask (true); - - // moving trans brushes - spaz - if (s->entity) - R_RotateForEntity (s->entity, true); - - light = R_SurfIsLit(s); - // solidAlpha = ( (s->texinfo->flags & SURF_TRANS33|SURF_TRANS66) == SURF_TRANS33|SURF_TRANS66 ); - // envMap = ( (s->flags & SURF_ENVMAP) && r_glass_envmaps->integer && !solidAlpha); - - if (s->flags & SURF_DRAWTURB) - R_DrawWarpSurface (s, R_SurfAlphaCalc(s->texinfo->flags), !R_SurfsAreBatchable (s, s->texturechain)); - else if (r_trans_lighting->integer == 2 && glConfig.multitexture && light && s->lightmaptexturenum) - { - GL_EnableMultitexture (true); - R_SetLightingMode (RF_TRANSLUCENT); - R_DrawLightmappedSurface (s, true); - GL_EnableMultitexture (false); - } - else - R_DrawGLPoly (s, !R_SurfsAreBatchable (s, s->texturechain));// true); +/* for (h = r_dup_alpha_surfaces; h; h = h->surfacechain) + if (h->surf) + { // save surface's flags and use flags from handle + VID_Printf (PRINT_ALL, "Drawing duplicate alpha surface from handle list.\n"); + oldFlags = h->surf->flags; + h->surf->flags = h->flags; + R_DrawAlphaSurface (h->surf, h->entity); + h->surf->flags = oldFlags; + }*/ + for (s = r_alpha_surfaces; s; s = s->texturechain) { + R_DrawAlphaSurface (s, s->entity); } // go back to the world matrix after shifting trans faces @@ -970,6 +617,7 @@ void R_DrawAlphaSurfaces (void) GL_Disable (GL_BLEND); GL_DepthMask (true); +// r_dup_alpha_surfaces = NULL; r_alpha_surfaces = NULL; } @@ -1065,12 +713,12 @@ void R_RebuildLightmaps (void) /* ================ -R_DrawMultiTextureChains +R_DrawTextureChains Draws solid warp surfaces im multitexture mode ================ */ -void R_DrawMultiTextureChains (void) +void R_DrawTextureChains (int renderflags) { int i; msurface_t *s; @@ -1078,9 +726,8 @@ void R_DrawMultiTextureChains (void) c_visible_textures = 0; -#ifdef MULTITEXTURE_CHAINS GL_EnableMultitexture (true); - R_SetLightingMode (0); + R_SetLightingMode (renderflags); #ifdef BATCH_LM_UPDATES R_RebuildLightmaps (); @@ -1100,7 +747,6 @@ void R_DrawMultiTextureChains (void) image->texturechain = NULL; } GL_EnableMultitexture (false); -#endif // MULTITEXTURE_CHAINS GL_TexEnv(GL_MODULATE); // warp textures, no lightmaps for (i=0, image=gltextures; iwarp_texturechain) continue; + // c_visible_textures++; rb_vertex = rb_index = 0; for (s = image->warp_texturechain; s; s=s->texturechain) { R_BuildVertexLight (s); @@ -1121,55 +768,6 @@ void R_DrawMultiTextureChains (void) } -/* -================ -R_DrawTextureChains - -Draws all solid textures in 2-pass mode -================ -*/ -void R_DrawTextureChains (void) -{ - int i; - msurface_t *s; - image_t *image; - - c_visible_textures = 0; - - for (i=0, image=gltextures; iregistration_sequence) - continue; - if (!image->texturechain) - continue; - - c_visible_textures++; - rb_vertex = rb_index = 0; - for (s = image->texturechain; s; s=s->texturechain) - R_RenderBrushPoly (s); - - image->texturechain = NULL; - } - - for (i=0, image=gltextures; iregistration_sequence) - continue; - if (!image->warp_texturechain) - continue; - - // c_visible_textures++; - rb_vertex = rb_index = 0; - for (s = image->warp_texturechain; s; s=s->texturechain) - R_RenderBrushPoly (s); - - image->warp_texturechain = NULL; - } - - GL_TexEnv (GL_REPLACE); -} - - /* =========================================== RB_DrawEnvMap @@ -1250,7 +848,7 @@ static void RB_DrawCaustics (msurface_t *surf) float scrollh, scrollv, scaleh, scalev, dstscroll; // *v, image_t *causticpic = RB_CausticForSurface (surf); qboolean previousBlend = false; - qboolean fragmentWarp = glConfig.multitexture && glConfig.arb_fragment_program && (r_caustics->integer > 1.0); + qboolean fragmentWarp = glConfig.arb_fragment_program && (r_caustics->integer > 1.0); // glpoly_t *p; // adjustment for texture size and caustic image @@ -1597,19 +1195,6 @@ void R_DrawInlineBModel (entity_t *e, int causticflag) } } -#ifdef MULTITEXTURE_CHAINS - if (!glConfig.multitexture) -#endif // MULTITEXTURE_CHAINS - { - if (currententity->flags & RF_TRANSLUCENT) - { - GL_DepthMask (false); - GL_TexEnv (GL_MODULATE); - GL_Enable (GL_BLEND); - GL_BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - } - // // draw standard surfaces // @@ -1628,8 +1213,7 @@ void R_DrawInlineBModel (entity_t *e, int causticflag) (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) { #ifdef BATCH_LM_UPDATES - if ( glConfig.multitexture && - !(psurf->texinfo->flags & (SURF_SKY|SURF_DRAWTURB)) ) + if ( !(psurf->texinfo->flags & (SURF_SKY|SURF_WARP)) ) R_UpdateSurfaceLightmap (psurf); #endif psurf->entity = NULL; @@ -1641,7 +1225,21 @@ void R_DrawInlineBModel (entity_t *e, int causticflag) duplicate = false; for (s = r_alpha_surfaces; s; s = s->texturechain) if (s == psurf) - { duplicate = true; break; } + { // this is a duplicate alpha surfaces, add a handle for it + /* if (r_numSurfaceHandles < MAX_SURFACE_HANDLES) + { + surfaceHandle_t *surfHandle; + + surfHandle = &r_surfaceHandles[r_numSurfaceHandles++]; + surfHandle->surf = psurf; + surfHandle->entity = e; + surfHandle->flags = (psurf->flags | causticflag); // set caustics + surfHandle->surfacechain = r_dup_alpha_surfaces; + r_dup_alpha_surfaces = surfHandle; + }*/ + duplicate = true; + break; + } if (!duplicate) // Don't allow surface to be added twice (fixes hang) { #if 0 @@ -1671,78 +1269,31 @@ void R_DrawInlineBModel (entity_t *e, int causticflag) else { image = R_TextureAnimation (psurf); - if ( glConfig.multitexture && !(psurf->flags & SURF_DRAWTURB) ) + if ( !(psurf->flags & SURF_DRAWTURB) ) { psurf->flags |= causticflag; // set caustics - #ifdef MULTITEXTURE_CHAINS psurf->texturechain = image->texturechain; image->texturechain = psurf; - #else - R_DrawLightmappedSurface (psurf, true); - #endif // MULTITEXTURE_CHAINS } - else if ( glConfig.multitexture && (psurf->flags & SURF_DRAWTURB) ) // warp surface + else // warp surface { - #ifdef MULTITEXTURE_CHAINS psurf->texturechain = image->warp_texturechain; image->warp_texturechain = psurf; - #else - continue; - #endif // MULTITEXTURE_CHAINS - } - else // 2-pass mode - { - GL_EnableMultitexture (false); - R_RenderBrushPoly (psurf); - GL_EnableMultitexture (true); - - // 2-pass mode-specific stuff - R_BlendLightmaps (); - R_DrawTriangleOutlines (); } } } } -#ifndef MULTITEXTURE_CHAINS - // - // draw warp surfaces - // - psurf = ¤tmodel->surfaces[currentmodel->firstmodelsurface]; - - for (i = 0; i < currentmodel->nummodelsurfaces; i++, psurf++) + if (currententity->flags & RF_TRANSLUCENT) { - // find which side of the node we are on - pplane = psurf->plane; - dot = DotProduct (modelorg, pplane->normal) - pplane->dist; - - // draw the polygon - if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || - (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) - { - if ( psurf->texinfo->flags & (SURF_TRANS33|SURF_TRANS66) ) - continue; - else if (!(psurf->flags & SURF_DRAWTURB)) // non-warp surface - continue; - else // warp surface - R_DrawWarpPoly (psurf); - } + GL_DepthMask (false); + GL_TexEnv (GL_MODULATE); + GL_Enable (GL_BLEND); + GL_BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } -#else // MULTITEXTURE_CHAINS - if (glConfig.multitexture) - { - if (currententity->flags & RF_TRANSLUCENT) - { - GL_DepthMask (false); - GL_TexEnv (GL_MODULATE); - GL_Enable (GL_BLEND); - GL_BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - R_DrawMultiTextureChains (); - } -#endif // MULTITEXTURE_CHAINS + R_DrawTextureChains (e->flags); // draw lightmapped and warp texture chains if (currententity->flags & RF_TRANSLUCENT) { @@ -1867,6 +1418,51 @@ void R_DrawBrushModel (entity_t *e) ============================================================= */ +/* +============= +R_AddWorldSurface +============= +*/ +void R_AddWorldSurface (msurface_t *surf) +{ + image_t *image; + + surf->entity = NULL; + + surf->entity = NULL; + +#ifdef BATCH_LM_UPDATES + if ( !(surf->texinfo->flags & (SURF_SKY|SURF_WARP)) ) + R_UpdateSurfaceLightmap (surf); +#endif + + if (surf->texinfo->flags & SURF_SKY) + { // just adds to visible sky bounds + R_AddSkySurface (surf); + } + else if (surf->texinfo->flags & (SURF_TRANS33|SURF_TRANS66)) + { // add to the translucent chain + surf->texturechain = r_alpha_surfaces; + r_alpha_surfaces = surf; + } + else + { + // the polygon is visible, so add it to the texture chain + image = R_TextureAnimation (surf); + if ( !(surf->flags & SURF_DRAWTURB) ) // lightmapped non-warp surface + { + surf->texturechain = image->texturechain; + image->texturechain = surf; + } + else // warp surface + { + surf->texturechain = image->warp_texturechain; + image->warp_texturechain = surf; + } + } +} + + /* ================ R_RecursiveWorldNode @@ -1879,7 +1475,7 @@ void R_RecursiveWorldNode (mnode_t *node) msurface_t *surf, **mark; mleaf_t *pleaf; float dot; - image_t *image; +// image_t *image; if (node->contents == CONTENTS_SOLID) return; // solid @@ -1960,42 +1556,8 @@ void R_RecursiveWorldNode (mnode_t *node) if ((surf->flags & SURF_PLANEBACK) != sidebit) continue; // wrong side - surf->entity = NULL; - -#ifdef BATCH_LM_UPDATES - if ( glConfig.multitexture && - !(surf->texinfo->flags & (SURF_SKY|SURF_DRAWTURB)) ) - R_UpdateSurfaceLightmap (surf); -#endif - - if (surf->texinfo->flags & SURF_SKY) - { // just adds to visible sky bounds - R_AddSkySurface (surf); - } - else if (surf->texinfo->flags & (SURF_TRANS33|SURF_TRANS66)) - { // add to the translucent chain - surf->texturechain = r_alpha_surfaces; - r_alpha_surfaces = surf; - } -#ifndef MULTITEXTURE_CHAINS - else if (glConfig.multitexture && !(surf->flags & SURF_DRAWTURB)) - { - R_DrawLightmappedSurface (surf, true); - } -#endif // MULTITEXTURE_CHAINS - else - { - // the polygon is visible, so add it to the texture chain - image = R_TextureAnimation (surf); - if ( !(surf->flags & SURF_DRAWTURB) ) { - surf->texturechain = image->texturechain; - image->texturechain = surf; - } - else { - surf->texturechain = image->warp_texturechain; - image->warp_texturechain = surf; - } - } + // add to texture chain + R_AddWorldSurface (surf); } // recurse down the back side @@ -2028,37 +1590,20 @@ void R_DrawWorld (void) ent.frame = r_worldframe = (int)(r_newrefdef.time*2); currententity = &ent; + // init surface handles (for duplicate alpha surfaces) +/* memset (r_surfaceHandles, 0, sizeof(r_surfaceHandles)); + r_numSurfaceHandles = 0; + r_dup_alpha_surfaces = NULL;*/ + glState.currenttextures[0] = glState.currenttextures[1] = -1; qglColor3f (1,1,1); memset (gl_lms.lightmap_surfaces, 0, sizeof(gl_lms.lightmap_surfaces)); R_ClearSkyBox (); - if (glConfig.multitexture) - { -#ifndef MULTITEXTURE_CHAINS - GL_EnableMultitexture (true); - R_SetLightingMode (0); -#endif // MULTITEXTURE_CHAINS + R_RecursiveWorldNode (r_worldmodel->nodes); - R_RecursiveWorldNode (r_worldmodel->nodes); - -#ifndef MULTITEXTURE_CHAINS - GL_EnableMultitexture (false); -#endif // MULTITEXTURE_CHAINS - - R_DrawMultiTextureChains (); // draw solid warp surfaces - } - else - { // add surfaces to texture chains for 2-pass rendering - R_RecursiveWorldNode (r_worldmodel->nodes); - - R_DrawTextureChains (); - - R_BlendLightmaps (); - - R_DrawTriangleOutlines (); - } + R_DrawTextureChains (0); // draw lightmapped and warp texture chains R_DrawSkyBox (); } @@ -2156,6 +1701,98 @@ void R_MarkLeaves (void) } +/* +================ +R_BuildPolygonFromSurface +================ +*/ +void R_BuildPolygonFromSurface (msurface_t *fa) +{ + int i, lindex, lnumverts; + medge_t *pedges, *r_pedge; + int vertpage; + float *vec; + float s, t; + glpoly_t *poly; + vec3_t total; + +// reconstruct the polygon + pedges = currentmodel->edges; + lnumverts = fa->numedges; + vertpage = 0; + + VectorClear (total); + + // + // draw texture + // + poly = Hunk_Alloc (sizeof(glpoly_t) + (lnumverts-4) * VERTEXSIZE*sizeof(float)); + poly->next = fa->polys; + poly->flags = fa->flags; + fa->polys = poly; + poly->numverts = lnumverts; + + // alloc vertex light fields + if (fa->texinfo->flags & (SURF_TRANS33|SURF_TRANS66)) { + int size = lnumverts*3*sizeof(byte); + poly->vertexlight = Hunk_Alloc(size); + poly->vertexlightbase = Hunk_Alloc(size); + memset(poly->vertexlight, 0, size); + memset(poly->vertexlightbase, 0, size); + poly->vertexlightset = false; + } + + for (i=0; isurfedges[fa->firstedge + i]; + + if (lindex > 0) + { + r_pedge = &pedges[lindex]; + vec = currentmodel->vertexes[r_pedge->v[0]].position; + } + else + { + r_pedge = &pedges[-lindex]; + vec = currentmodel->vertexes[r_pedge->v[1]].position; + } + // + // texture coordinates + // + s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3]; + s /= fa->texinfo->texWidth; //fa->texinfo->image->width; changed to Q2E hack + + t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3]; + t /= fa->texinfo->texHeight; //fa->texinfo->image->height; changed to Q2E hack + + VectorAdd (total, vec, total); + VectorCopy (vec, poly->verts[i]); + poly->verts[i][3] = s; + poly->verts[i][4] = t; + + // + // lightmap texture coordinates + // + s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3]; + s -= fa->texturemins[0]; + s += fa->light_s*16; + s += 8; + s /= LM_BLOCK_WIDTH*16; //fa->texinfo->texture->width; + + t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3]; + t -= fa->texturemins[1]; + t += fa->light_t*16; + t += 8; + t /= LM_BLOCK_HEIGHT*16; //fa->texinfo->texture->height; + + poly->verts[i][5] = s; + poly->verts[i][6] = t; + } + VectorScale(total, 1.0/(float)lnumverts, poly->center); // for vertex lighting + + poly->numverts = lnumverts; +} + /* ======================================================================= @@ -2281,425 +1918,3 @@ void R_BuildVertexLight (msurface_t *surf) end Quake2Max vertex lighting code ======================================================================= */ - - -/* -============================================================================= - - LIGHTMAP ALLOCATION - -============================================================================= -*/ - -/* -================ -LM_InitBlock -================ -*/ -static void LM_InitBlock (void) -{ - memset( gl_lms.allocated, 0, sizeof( gl_lms.allocated ) ); - -#ifdef BATCH_LM_UPDATES - // alloc lightmap update buffer if needed - if (!gl_lms.lightmap_update[gl_lms.current_lightmap_texture]) { - gl_lms.lightmap_update[gl_lms.current_lightmap_texture] = Z_Malloc (LM_BLOCK_WIDTH*LM_BLOCK_HEIGHT*LIGHTMAP_BYTES); - } -#endif // BATCH_LM_UPDATES -} - - -/* -================ -LM_UploadBlock -================ -*/ -static void LM_UploadBlock (qboolean dynamic) -{ - int texture; - int height = 0; - - if ( dynamic ) - { - texture = 0; - } - else - { - texture = gl_lms.current_lightmap_texture; - } - - GL_Bind( glState.lightmap_textures + texture ); - qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - if ( dynamic ) - { - int i; - - for ( i = 0; i < LM_BLOCK_WIDTH; i++ ) - { - if ( gl_lms.allocated[i] > height ) - height = gl_lms.allocated[i]; - } - - qglTexSubImage2D( GL_TEXTURE_2D, - 0, - 0, 0, - LM_BLOCK_WIDTH, height, - gl_lms.format, - gl_lms.type, - // GL_LIGHTMAP_FORMAT, - // GL_UNSIGNED_BYTE, - gl_lms.lightmap_buffer ); - } - else - { - qglTexImage2D( GL_TEXTURE_2D, - 0, - gl_lms.internal_format, - LM_BLOCK_WIDTH, LM_BLOCK_HEIGHT, - 0, - gl_lms.format, - gl_lms.type, - // GL_LIGHTMAP_FORMAT, - // GL_UNSIGNED_BYTE, -#ifdef BATCH_LM_UPDATES - gl_lms.lightmap_update[gl_lms.current_lightmap_texture] ); -#else - gl_lms.lightmap_buffer ); -#endif // BATCH_LM_UPDATES - if ( ++gl_lms.current_lightmap_texture == MAX_LIGHTMAPS ) - VID_Error( ERR_DROP, "LM_UploadBlock() - MAX_LIGHTMAPS exceeded\n" ); - } -} - - -/* -================ -LM_AllocBlock -returns a texture number and the position inside it -================ -*/ -static qboolean LM_AllocBlock (int w, int h, int *x, int *y) -{ - int i, j; - int best, best2; - - best = LM_BLOCK_HEIGHT; - - for (i=0 ; i= best) - break; - if (gl_lms.allocated[i+j] > best2) - best2 = gl_lms.allocated[i+j]; - } - if (j == w) - { // this is a valid spot - *x = i; - *y = best = best2; - } - } - - if (best + h > LM_BLOCK_HEIGHT) - return false; - - for (i=0 ; iedges; - lnumverts = fa->numedges; - vertpage = 0; - - VectorClear (total); - - // - // draw texture - // - poly = Hunk_Alloc (sizeof(glpoly_t) + (lnumverts-4) * VERTEXSIZE*sizeof(float)); - poly->next = fa->polys; - poly->flags = fa->flags; - fa->polys = poly; - poly->numverts = lnumverts; - - // alloc vertex light fields - if (fa->texinfo->flags & (SURF_TRANS33|SURF_TRANS66)) { - int size = lnumverts*3*sizeof(byte); - poly->vertexlight = Hunk_Alloc(size); - poly->vertexlightbase = Hunk_Alloc(size); - memset(poly->vertexlight, 0, size); - memset(poly->vertexlightbase, 0, size); - poly->vertexlightset = false; - } - - for (i=0; isurfedges[fa->firstedge + i]; - - if (lindex > 0) - { - r_pedge = &pedges[lindex]; - vec = currentmodel->vertexes[r_pedge->v[0]].position; - } - else - { - r_pedge = &pedges[-lindex]; - vec = currentmodel->vertexes[r_pedge->v[1]].position; - } - // - // texture coordinates - // - s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3]; - s /= fa->texinfo->texWidth; //fa->texinfo->image->width; changed to Q2E hack - - t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3]; - t /= fa->texinfo->texHeight; //fa->texinfo->image->height; changed to Q2E hack - - VectorAdd (total, vec, total); - VectorCopy (vec, poly->verts[i]); - poly->verts[i][3] = s; - poly->verts[i][4] = t; - - // - // lightmap texture coordinates - // - s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3]; - s -= fa->texturemins[0]; - s += fa->light_s*16; - s += 8; - s /= LM_BLOCK_WIDTH*16; //fa->texinfo->texture->width; - - t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3]; - t -= fa->texturemins[1]; - t += fa->light_t*16; - t += 8; - t /= LM_BLOCK_HEIGHT*16; //fa->texinfo->texture->height; - - poly->verts[i][5] = s; - poly->verts[i][6] = t; - } - VectorScale(total, 1.0/(float)lnumverts, poly->center); // for vertex lighting - - poly->numverts = lnumverts; -} - - -/* -======================== -R_CreateSurfaceLightmap -======================== -*/ -void R_CreateSurfaceLightmap (msurface_t *surf) -{ - int smax, tmax; - unsigned *base; - - if (surf->flags & (SURF_DRAWSKY|SURF_DRAWTURB)) - return; - - //if (surf->texinfo->flags & (SURF_SKY|SURF_TRANS33|SURF_TRANS66|SURF_WARP)) - if (surf->texinfo->flags & (SURF_SKY|SURF_WARP)) - return; - - smax = (surf->extents[0]>>4)+1; - tmax = (surf->extents[1]>>4)+1; - - if ( !LM_AllocBlock (smax, tmax, &surf->light_s, &surf->light_t) ) - { - LM_UploadBlock (false); - LM_InitBlock(); - if ( !LM_AllocBlock (smax, tmax, &surf->light_s, &surf->light_t) ) - { - VID_Error (ERR_FATAL, "Consecutive calls to LM_AllocBlock(%d,%d) failed\n", smax, tmax); - } - } - - surf->lightmaptexturenum = gl_lms.current_lightmap_texture; - - // copy extents - surf->light_smax = smax; - surf->light_tmax = tmax; - -#ifdef BATCH_LM_UPDATES - base = gl_lms.lightmap_update[surf->lightmaptexturenum]; -#else - base = gl_lms.lightmap_buffer; -#endif // BATCH_LM_UPDATES - - base += (surf->light_t * LM_BLOCK_WIDTH + surf->light_s); // * LIGHTMAP_BYTES - - R_SetCacheState (surf); - R_BuildLightMap (surf, (void *)base, LM_BLOCK_WIDTH*LIGHTMAP_BYTES); -} - - -#define gl_tex_solid_format 3 -#define gl_tex_alpha_format 4 -/* -================== -R_BeginBuildingLightmaps -================== -*/ -void R_BeginBuildingLightmaps (model_t *m) -{ - static lightstyle_t lightstyles[MAX_LIGHTSTYLES]; - int i; - unsigned dummy[LM_BLOCK_WIDTH*LM_BLOCK_HEIGHT]; // 128*128 - - memset( gl_lms.allocated, 0, sizeof(gl_lms.allocated) ); - -#ifdef BATCH_LM_UPDATES - // free lightmap update buffers - for (i=0; istring[0] ) == 'A' ) - { - gl_lms.internal_format = gl_tex_alpha_format; - } - // try to do hacked colored lighting with a blended texture - else if ( toupper( r_monolightmap->string[0] ) == 'C' ) - { - gl_lms.internal_format = gl_tex_alpha_format; - } - else if ( toupper( r_monolightmap->string[0] ) == 'I' ) - { - gl_lms.internal_format = GL_INTENSITY8; - } - else if ( toupper( r_monolightmap->string[0] ) == 'L' ) - { - gl_lms.internal_format = GL_LUMINANCE8; - } - else - { - gl_lms.internal_format = gl_tex_solid_format; - } - - gl_lms.format = GL_RGBA; - gl_lms.type = GL_UNSIGNED_BYTE; - } - else - { - if ( toupper( r_monolightmap->string[0] ) == 'I' ) - gl_lms.internal_format = GL_INTENSITY8; - else if ( toupper( r_monolightmap->string[0] ) == 'L' ) - gl_lms.internal_format = GL_LUMINANCE8; - else - gl_lms.internal_format = GL_RGBA8; - - gl_lms.format = GL_BGRA; - gl_lms.type = GL_UNSIGNED_INT_8_8_8_8_REV; - } - - // initialize the dynamic lightmap texture - GL_Bind( glState.lightmap_textures + 0 ); - qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - qglTexImage2D( GL_TEXTURE_2D, - 0, - gl_lms.internal_format, - LM_BLOCK_WIDTH, LM_BLOCK_HEIGHT, - 0, - gl_lms.format, - gl_lms.type, - // GL_LIGHTMAP_FORMAT, - // GL_UNSIGNED_BYTE, - dummy ); -} - - -/* -======================= -R_EndBuildingLightmaps -======================= -*/ -void R_EndBuildingLightmaps (void) -{ - LM_UploadBlock (false); - GL_EnableMultitexture (false); -} - diff --git a/renderer/r_surface_singletex.c b/renderer/r_surface_singletex.c new file mode 100644 index 0000000..e507462 --- /dev/null +++ b/renderer/r_surface_singletex.c @@ -0,0 +1,924 @@ +/* +=========================================================================== +Copyright (C) 1997-2001 Id Software, Inc. + +This file is part of Quake 2 source code. + +Quake 2 source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// r_surf_singletex.c: old single-texture 2-pass world rendering (no longer used) + +#include "r_local.h" + +#if USE_SINGLETEXTURE_MODE + +/* +================ +R_DrawWarpPoly +================ +*/ +void R_DrawWarpPoly (msurface_t *surf) +{ + if (!(surf->flags & SURF_DRAWTURB)) + return; + + R_BuildVertexLight (surf); + + // warp texture, no lightmaps + GL_EnableMultitexture (false); +// GL_TexEnv(GL_MODULATE); + + R_DrawWarpSurface (surf, 1.0, true); + +// GL_TexEnv(GL_REPLACE); + GL_EnableMultitexture (true); +} + +/* +================ +R_DrawTriangleOutlines +================ +*/ +void R_DrawTriangleOutlines (void) +{ + int i, j, nv; + float *v; + msurface_t *surf; + glpoly_t *p; + + // not used in multitexture mode + if (glConfig.multitexture) + return; + if (!r_showtris->integer) + return; + + if (r_showtris->integer == 1) + GL_Disable(GL_DEPTH_TEST); + + GL_DisableTexture (0); + qglPolygonMode (GL_FRONT_AND_BACK, GL_LINE); + + rb_vertex = rb_index = 0; + for (i = 0; i < MAX_LIGHTMAPS; i++) + { + for (surf = gl_lms.lightmap_surfaces[i]; surf != 0; surf = surf->lightmapchain) + { + for (p = surf->polys; p; p = p->chain) + { + v = p->verts[0]; + nv = p->numverts; + if (RB_CheckArrayOverflow (nv, (nv-2)*3)) + RB_RenderMeshGeneric (false); + for (j=0; j < nv-2; j++) { + indexArray[rb_index++] = rb_vertex; + indexArray[rb_index++] = rb_vertex+j+1; + indexArray[rb_index++] = rb_vertex+j+2; + } + for (j=0; j < nv; j++, v+= VERTEXSIZE) + { + VA_SetElem3(vertexArray[rb_vertex], v[0], v[1], v[2]); + VA_SetElem4(colorArray[rb_vertex], 1, 1, 1, 1); + rb_vertex++; + } + } + } + } +// RB_DrawArrays (); + RB_RenderMeshGeneric (false); + + qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL); + GL_EnableTexture(0); + + if (r_showtris->integer == 1) + GL_Enable(GL_DEPTH_TEST); +} + + +/* +================ +R_DrawGLPolyChain +================ +*/ +void R_DrawGLPolyChain (glpoly_t *p, float soffset, float toffset) +{ + float *v; + int j, nv; + + rb_vertex = rb_index = 0; + for ( ; p != 0; p = p->chain) + { + v = p->verts[0]; + nv = p->numverts; + if (RB_CheckArrayOverflow (nv, (nv-2)*3)) + RB_RenderMeshGeneric (false); + for (j=0; j < nv-2; j++) { + indexArray[rb_index++] = rb_vertex; + indexArray[rb_index++] = rb_vertex+j+1; + indexArray[rb_index++] = rb_vertex+j+2; + } + for (j=0; j < nv; j++, v+= VERTEXSIZE) + { + VA_SetElem2(texCoordArray[0][rb_vertex], v[5] - soffset, v[6] - toffset); + VA_SetElem3(vertexArray[rb_vertex], v[0], v[1], v[2]); + VA_SetElem4(colorArray[rb_vertex], 1, 1, 1, 1); + rb_vertex++; + } + } +// RB_DrawArrays (); + RB_RenderMeshGeneric (false); +} + + +/* +================ +R_DrawAlphaSurfaces + +Draw trans water surfaces and windows. +The BSP tree is waled front to back, so unwinding the chain +of alpha_surfaces will draw back to front, giving proper ordering. +================ +*/ +void R_DrawAlphaSurfaces (void) +{ + msurface_t *s; + qboolean light; //solidAlpha, envMap; + + // the textures are prescaled up for a better lighting range, + // so scale it back down + + rb_vertex = rb_index = 0; + for (s = r_alpha_surfaces; s; s = s->texturechain) + { + // go back to the world matrix + qglLoadMatrixf (r_world_matrix); + + R_BuildVertexLight (s); + GL_Enable (GL_BLEND); + GL_TexEnv (GL_MODULATE); + GL_BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + // disable depth testing for all bmodel surfs except solid alphas + if ( s->entity && !((s->flags & SURF_TRANS33) && (s->flags & SURF_TRANS66)) ) + GL_DepthMask (false); + else + GL_DepthMask (true); + + // moving trans brushes - spaz + if (s->entity) + R_RotateForEntity (s->entity, true); + + light = R_SurfIsLit(s); + // solidAlpha = ( (s->texinfo->flags & SURF_TRANS33|SURF_TRANS66) == SURF_TRANS33|SURF_TRANS66 ); + // envMap = ( (s->flags & SURF_ENVMAP) && r_glass_envmaps->integer && !solidAlpha); + + if (s->flags & SURF_DRAWTURB) + R_DrawWarpSurface (s, R_SurfAlphaCalc(s->texinfo->flags), !R_SurfsAreBatchable (s, s->texturechain)); + else if ( (r_trans_lighting->integer == 2) && glConfig.multitexture && light && s->lightmaptexturenum ) + { + GL_EnableMultitexture (true); + R_SetLightingMode (RF_TRANSLUCENT); + R_DrawLightmappedSurface (s, true); + GL_EnableMultitexture (false); + } + else + R_DrawGLPoly (s, !R_SurfsAreBatchable (s, s->texturechain));// true); + } + + // go back to the world matrix after shifting trans faces + qglLoadMatrixf (r_world_matrix); + + GL_BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + GL_TexEnv (GL_REPLACE); + qglColor4f (1,1,1,1); + GL_Disable (GL_BLEND); + GL_DepthMask (true); + + r_alpha_surfaces = NULL; +} + + +/* +================ +R_BlendLightMaps + +This routine takes all the given light mapped surfaces in the world and +blends them into the framebuffer. +================ +*/ +void R_BlendLightmaps (void) +{ + int i; + msurface_t *surf, *newdrawsurf = 0; + + // not used in multitexture mode + if (glConfig.multitexture) + return; + // don't bother if we're set to fullbright + if (r_fullbright->integer) + return; + if (!r_worldmodel->lightdata) + return; + + // don't bother writing Z + GL_DepthMask (false); + + // set the appropriate blending mode unless we're only looking at the + // lightmaps. + if (!r_lightmap->integer) + { + GL_Enable (GL_BLEND); + + if (r_saturatelighting->integer) + { + GL_BlendFunc( GL_ONE, GL_ONE ); + } + else + { + if (r_monolightmap->string[0] != '0') + { + switch (toupper(r_monolightmap->string[0])) + { + case 'I': + GL_BlendFunc (GL_ZERO, GL_SRC_COLOR); + break; + case 'L': + GL_BlendFunc (GL_ZERO, GL_SRC_COLOR); + break; + case 'A': + default: + GL_BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + break; + } + } + else + { + GL_BlendFunc (GL_ZERO, GL_SRC_COLOR); + } + } + } + + if (currentmodel == r_worldmodel) + c_visible_lightmaps = 0; + + // render static lightmaps first + for (i = 1; i < MAX_LIGHTMAPS; i++) + { + if (gl_lms.lightmap_surfaces[i]) + { + if (currentmodel == r_worldmodel) + c_visible_lightmaps++; + GL_Bind( glState.lightmap_textures + i); + + for (surf = gl_lms.lightmap_surfaces[i]; surf != 0; surf = surf->lightmapchain) + { + if (surf->polys) + R_DrawGLPolyChain(surf->polys, 0, 0); + } + } + } + + // render dynamic lightmaps + if (r_dynamic->integer) + { + LM_InitBlock(); + + GL_Bind(glState.lightmap_textures+0); + + if (currentmodel == r_worldmodel) + c_visible_lightmaps++; + + newdrawsurf = gl_lms.lightmap_surfaces[0]; + + for (surf = gl_lms.lightmap_surfaces[0]; surf != 0; surf = surf->lightmapchain) + { + int smax, tmax; + unsigned *base; + + smax = (surf->extents[0]>>4)+1; + tmax = (surf->extents[1]>>4)+1; + + if ( LM_AllocBlock( smax, tmax, &surf->dlight_s, &surf->dlight_t ) ) + { + base = gl_lms.lightmap_buffer; + base += (surf->dlight_t * LM_BLOCK_WIDTH + surf->dlight_s); // * LIGHTMAP_BYTES + + R_BuildLightMap (surf, (void *)base, LM_BLOCK_WIDTH*LIGHTMAP_BYTES); + } + else + { + msurface_t *drawsurf; + + // upload what we have so far + LM_UploadBlock(true); + + // draw all surfaces that use this lightmap + for ( drawsurf = newdrawsurf; drawsurf != surf; drawsurf = drawsurf->lightmapchain ) + { + if (drawsurf->polys) + R_DrawGLPolyChain( drawsurf->polys, + (drawsurf->light_s - drawsurf->dlight_s) * (1.0 / 128.0), + (drawsurf->light_t - drawsurf->dlight_t) * (1.0 / 128.0) ); + } + + newdrawsurf = drawsurf; + + // clear the block + LM_InitBlock(); + + // try uploading the block now + if (!LM_AllocBlock(smax, tmax, &surf->dlight_s, &surf->dlight_t)) + { + VID_Error( ERR_FATAL, "Consecutive calls to LM_AllocBlock(%d,%d) failed (dynamic)\n", smax, tmax ); + } + + base = gl_lms.lightmap_buffer; + base += (surf->dlight_t * LM_BLOCK_WIDTH + surf->dlight_s); // * LIGHTMAP_BYTES + + R_BuildLightMap (surf, (void *)base, LM_BLOCK_WIDTH*LIGHTMAP_BYTES); + } + } + + // draw remainder of dynamic lightmaps that haven't been uploaded yet + if (newdrawsurf) + LM_UploadBlock( true ); + + for (surf = newdrawsurf; surf != 0; surf = surf->lightmapchain) + { + if (surf->polys) + R_DrawGLPolyChain( surf->polys, (surf->light_s - surf->dlight_s) * (1.0 / 128.0), (surf->light_t - surf->dlight_t) * (1.0 / 128.0) ); + } + } + + // restore state + GL_Disable (GL_BLEND); + GL_BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + GL_DepthMask (true); +} + + +/* +================ +R_RenderBrushPoly +================ +*/ +void R_RenderBrushPoly (msurface_t *fa) +{ + int maps; +// qboolean is_dynamic = false; + + if (fa->flags & SURF_DRAWTURB) + { + R_BuildVertexLight (fa); + + // warp texture, no lightmaps + GL_TexEnv(GL_MODULATE); + + R_DrawWarpSurface (fa, 1.0, true); + + GL_TexEnv(GL_REPLACE); + + return; + } + + GL_TexEnv(GL_REPLACE); + + R_DrawGLPoly (fa, true); + +#if 0 + // + // check for lightmap modification + // + for (maps = 0; maps < MAXLIGHTMAPS && fa->styles[maps] != 255; maps++) + { + if (r_newrefdef.lightstyles[fa->styles[maps]].white != fa->cached_light[maps]) + goto dynamic; + } + + // dynamic this frame or dynamic previously + if ((fa->dlightframe == r_framecount)) + { +dynamic: + if (r_dynamic->integer) + { + if ( !(fa->texinfo->flags & (SURF_SKY|SURF_TRANS33|SURF_TRANS66|SURF_WARP)) ) + { + is_dynamic = true; + } + } + } +#endif + + if (R_SurfIsDynamic(fa, &maps)) + { + if ( (fa->styles[maps] >= 32 || fa->styles[maps] == 0) && (fa->dlightframe != r_framecount) ) + { + unsigned temp[34*34]; + int smax, tmax; + + smax = (fa->extents[0]>>4)+1; + tmax = (fa->extents[1]>>4)+1; + + R_BuildLightMap(fa, (void *)temp, smax*4); + R_SetCacheState(fa); + + GL_Bind(glState.lightmap_textures + fa->lightmaptexturenum); + + qglTexSubImage2D( GL_TEXTURE_2D, 0, + fa->light_s, fa->light_t, + smax, tmax, + // GL_LIGHTMAP_FORMAT, GL_UNSIGNED_BYTE, + gl_lms.format, gl_lms.type, + temp); + + fa->lightmapchain = gl_lms.lightmap_surfaces[fa->lightmaptexturenum]; + gl_lms.lightmap_surfaces[fa->lightmaptexturenum] = fa; + } + else + { + fa->lightmapchain = gl_lms.lightmap_surfaces[0]; + gl_lms.lightmap_surfaces[0] = fa; + } + } + else + { + fa->lightmapchain = gl_lms.lightmap_surfaces[fa->lightmaptexturenum]; + gl_lms.lightmap_surfaces[fa->lightmaptexturenum] = fa; + } +} + + +/* +================ +R_DrawSingleTextureChains + +Draws all solid textures in 2-pass mode +================ +*/ +void R_DrawSingleTextureChains (void) +{ + int i; + msurface_t *s; + image_t *image; + + c_visible_textures = 0; + + for (i=0, image=gltextures; iregistration_sequence) + continue; + if (!image->texturechain) + continue; + + c_visible_textures++; + rb_vertex = rb_index = 0; + for (s = image->texturechain; s; s=s->texturechain) + R_RenderBrushPoly (s); + + image->texturechain = NULL; + } + + for (i=0, image=gltextures; iregistration_sequence) + continue; + if (!image->warp_texturechain) + continue; + + // c_visible_textures++; + rb_vertex = rb_index = 0; + for (s = image->warp_texturechain; s; s=s->texturechain) + R_RenderBrushPoly (s); + + image->warp_texturechain = NULL; + } + + GL_TexEnv (GL_REPLACE); +} + + +/* +================= +R_DrawInlineBModel_Old +================= +*/ +void R_DrawInlineBModel_Old (entity_t *e, int causticflag) +{ + int i, k; + cplane_t *pplane; + float dot; + msurface_t *psurf, *s; + dlight_t *lt; + qboolean duplicate; + image_t *image; + + psurf = ¤tmodel->surfaces[currentmodel->firstmodelsurface]; + + for (i=0; inummodelsurfaces; i++, psurf++) + { + // find which side of the face we are on + pplane = psurf->plane; + if ( pplane->type < 3 ) + dot = modelorg[pplane->type] - pplane->dist; + else + dot = DotProduct (modelorg, pplane->normal) - pplane->dist; + // cull the polygon + if (dot > BACKFACE_EPSILON) + psurf->visframe = r_framecount; + } + + // calculate dynamic lighting for bmodel + if (!r_flashblend->integer) + { + lt = r_newrefdef.dlights; + if (currententity->angles[0] || currententity->angles[1] || currententity->angles[2]) + { + vec3_t temp; + vec3_t forward, right, up; + AngleVectors (currententity->angles, forward, right, up); + for (k=0; korigin, currententity->origin, temp); + lt->origin[0] = DotProduct (temp, forward); + lt->origin[1] = -DotProduct (temp, right); + lt->origin[2] = DotProduct (temp, up); + R_MarkLights (lt, k, currentmodel->nodes + currentmodel->firstnode); + VectorAdd (temp, currententity->origin, lt->origin); + } + } + else + { + for (k=0; korigin, currententity->origin, lt->origin); + R_MarkLights (lt, k, currentmodel->nodes + currentmodel->firstnode); + VectorAdd (lt->origin, currententity->origin, lt->origin); + } + } + } + +#ifdef MULTITEXTURE_CHAINS + if (!glConfig.multitexture) +#endif // MULTITEXTURE_CHAINS + { + if (currententity->flags & RF_TRANSLUCENT) + { + GL_DepthMask (false); + GL_TexEnv (GL_MODULATE); + GL_Enable (GL_BLEND); + GL_BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + } + + // + // draw standard surfaces + // + R_SetLightingMode (e->flags); // set up texture combiners + + psurf = ¤tmodel->surfaces[currentmodel->firstmodelsurface]; + + for (i = 0; i < currentmodel->nummodelsurfaces; i++, psurf++) + { + // find which side of the node we are on + pplane = psurf->plane; + dot = DotProduct (modelorg, pplane->normal) - pplane->dist; + + // draw the polygon + if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || + (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) + { +#ifdef BATCH_LM_UPDATES + if ( glConfig.multitexture && !(psurf->texinfo->flags & (SURF_SKY|SURF_WARP)) ) + R_UpdateSurfaceLightmap (psurf); +#endif + psurf->entity = NULL; + psurf->flags &= ~SURF_MASK_CAUSTIC; // clear old caustics + if ( psurf->texinfo->flags & (SURF_TRANS33|SURF_TRANS66) ) + { // add to the translucent chain + // if bmodel is used by multiple entities, adding surface + // to linked list more than once would result in an infinite loop + duplicate = false; + for (s = r_alpha_surfaces; s; s = s->texturechain) + if (s == psurf) + { duplicate = true; break; } + if (!duplicate) // Don't allow surface to be added twice (fixes hang) + { + #if 0 + msurface_t *last = NULL; + psurf->entity = e; // entity pointer to support movement + for (s = r_alpha_surfaces; s; last = s, s = s->texturechain) + { + if (SurfInFront (s, psurf)) // s is in front of psurf + break; // we know to insert here + } + if (last) { // if in front of at least one surface + psurf->texturechain = s; + last->texturechain = psurf; + } + else { // stuff in beginning of chain + psurf->texturechain = r_alpha_surfaces; + r_alpha_surfaces = psurf; + } + #else + psurf->flags |= causticflag; // set caustics + psurf->texturechain = r_alpha_surfaces; + r_alpha_surfaces = psurf; + psurf->entity = e; // entity pointer to support movement + #endif + } + } + else + { + image = R_TextureAnimation (psurf); + if ( glConfig.multitexture &/ !(psurf->flags & SURF_DRAWTURB) ) + { + psurf->flags |= causticflag; // set caustics + #ifdef MULTITEXTURE_CHAINS + psurf->texturechain = image->texturechain; + image->texturechain = psurf; + #else + R_DrawLightmappedSurface (psurf, true); + #endif // MULTITEXTURE_CHAINS + } + else if ( glConfig.multitexture && (psurf->flags & SURF_DRAWTURB) ) // warp surface + { + #ifdef MULTITEXTURE_CHAINS + psurf->texturechain = image->warp_texturechain; + image->warp_texturechain = psurf; + #else + continue; + #endif // MULTITEXTURE_CHAINS */ + } + else // 2-pass mode + { + GL_EnableMultitexture (false); + R_RenderBrushPoly (psurf); + GL_EnableMultitexture (true); + + // 2-pass mode-specific stuff + R_BlendLightmaps (); + R_DrawTriangleOutlines (); + } + } + + } + } + +#ifndef MULTITEXTURE_CHAINS + // + // draw warp surfaces + // + psurf = ¤tmodel->surfaces[currentmodel->firstmodelsurface]; + + for (i = 0; i < currentmodel->nummodelsurfaces; i++, psurf++) + { + // find which side of the node we are on + pplane = psurf->plane; + dot = DotProduct (modelorg, pplane->normal) - pplane->dist; + + // draw the polygon + if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || + (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) + { + if ( psurf->texinfo->flags & (SURF_TRANS33|SURF_TRANS66) ) + continue; + else if (!(psurf->flags & SURF_DRAWTURB)) // non-warp surface + continue; + else // warp surface + R_DrawWarpPoly (psurf); + } + } +#else // MULTITEXTURE_CHAINS + if (glConfig.multitexture) + { + if (currententity->flags & RF_TRANSLUCENT) + { + GL_DepthMask (false); + GL_TexEnv (GL_MODULATE); + GL_Enable (GL_BLEND); + GL_BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + R_DrawMultiTextureChains (); + } +#endif // MULTITEXTURE_CHAINS + + if (currententity->flags & RF_TRANSLUCENT) + { + GL_BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + GL_Disable (GL_BLEND); + GL_TexEnv (GL_REPLACE); + GL_DepthMask (true); + } +} + + +/* +================ +R_RecursiveWorldNode_Old +================ +*/ +void R_RecursiveWorldNode_Old (mnode_t *node) +{ + int c, side, sidebit; + cplane_t *plane; + msurface_t *surf, **mark; + mleaf_t *pleaf; + float dot; + image_t *image; + + if (node->contents == CONTENTS_SOLID) + return; // solid + + if (node->visframe != r_visframecount) + return; + if (R_CullBox (node->minmaxs, node->minmaxs+3)) + return; + + // if a leaf node, draw stuff + if (node->contents != -1) + { + pleaf = (mleaf_t *)node; + + // check for door connected areas + if (r_newrefdef.areabits) + { + if (! (r_newrefdef.areabits[pleaf->area>>3] & (1<<(pleaf->area&7)) ) ) + return; // not visible + } + + mark = pleaf->firstmarksurface; + c = pleaf->nummarksurfaces; + + if (c) + { + do + { + (*mark)->visframe = r_framecount; + mark++; + } while (--c); + } + + return; + } + + // node is just a decision point, so go down the apropriate sides + + // find which side of the node we are on + plane = node->plane; + + switch (plane->type) + { + case PLANE_X: + dot = modelorg[0] - plane->dist; + break; + case PLANE_Y: + dot = modelorg[1] - plane->dist; + break; + case PLANE_Z: + dot = modelorg[2] - plane->dist; + break; + default: + dot = DotProduct (modelorg, plane->normal) - plane->dist; + break; + } + + if (dot >= 0) + { + side = 0; + sidebit = 0; + } + else + { + side = 1; + sidebit = SURF_PLANEBACK; + } + + // recurse down the children, front side first + R_RecursiveWorldNode_Old (node->children[side]); + + // draw stuff + for ( c = node->numsurfaces, surf = r_worldmodel->surfaces + node->firstsurface; c ; c--, surf++) + { + if (surf->visframe != r_framecount) + continue; + + if ((surf->flags & SURF_PLANEBACK) != sidebit) + continue; // wrong side + + surf->entity = NULL; + +#ifdef BATCH_LM_UPDATES + if ( glConfig.multitexture && !(surf->texinfo->flags & (SURF_SKY|SURF_DRAWTURB)) ) + R_UpdateSurfaceLightmap (surf); +#endif + + if (surf->texinfo->flags & SURF_SKY) + { // just adds to visible sky bounds + R_AddSkySurface (surf); + } + else if (surf->texinfo->flags & (SURF_TRANS33|SURF_TRANS66)) + { // add to the translucent chain + surf->texturechain = r_alpha_surfaces; + r_alpha_surfaces = surf; + } +#ifndef MULTITEXTURE_CHAINS + else if (glConfig.multitexture && !(surf->flags & SURF_DRAWTURB)) + { + R_DrawLightmappedSurface (surf, true); + } +#endif // MULTITEXTURE_CHAINS + else + { + // the polygon is visible, so add it to the texture chain + image = R_TextureAnimation (surf); + if ( !(surf->flags & SURF_DRAWTURB) ) { + surf->texturechain = image->texturechain; + image->texturechain = surf; + } + else { + surf->texturechain = image->warp_texturechain; + image->warp_texturechain = surf; + } + } + } + + // recurse down the back side + R_RecursiveWorldNode_Old (node->children[!side]); +} + + +/* +============= +R_DrawWorld_Old +============= +*/ +void R_DrawWorld_Old (void) +{ + entity_t ent; + + if (!r_drawworld->integer) + return; + + if ( r_newrefdef.rdflags & RDF_NOWORLDMODEL ) + return; + + currentmodel = r_worldmodel; + + VectorCopy (r_newrefdef.vieworg, modelorg); + + // auto cycle the world frame for texture animation + memset (&ent, 0, sizeof(ent)); + // Knightmare added r_worldframe for trans animations + ent.frame = r_worldframe = (int)(r_newrefdef.time*2); + currententity = &ent; + + glState.currenttextures[0] = glState.currenttextures[1] = -1; + + qglColor3f (1,1,1); + memset (gl_lms.lightmap_surfaces, 0, sizeof(gl_lms.lightmap_surfaces)); + R_ClearSkyBox (); + + if (glConfig.multitexture) + { +#ifndef MULTITEXTURE_CHAINS + GL_EnableMultitexture (true); + R_SetLightingMode (0); +#endif // MULTITEXTURE_CHAINS + + R_RecursiveWorldNode_Old (r_worldmodel->nodes); + +#ifndef MULTITEXTURE_CHAINS + GL_EnableMultitexture (false); +#endif // MULTITEXTURE_CHAINS + + R_DrawMultiTextureChains (); // draw solid warp surfaces + } + else + { // add surfaces to texture chains for 2-pass rendering + R_RecursiveWorldNode_Old (r_worldmodel->nodes); + + R_DrawSingleTextureChains (); + + R_BlendLightmaps (); + + R_DrawTriangleOutlines (); + } + + R_DrawSkyBox (); +} + +#endif // USE_SINGLETEXTURE_MODE diff --git a/renderer/r_warp.c b/renderer/r_warp.c index 3dd7bbc..5b05aeb 100644 --- a/renderer/r_warp.c +++ b/renderer/r_warp.c @@ -311,8 +311,8 @@ void RB_RenderWarpSurface (msurface_t *fa) float alpha = colorArray[0][3]; image_t *image = R_TextureAnimation (fa); qboolean light = r_warp_lighting->integer && !(fa->texinfo->flags & SURF_NOLIGHTENV); - qboolean texShaderWarpNV = glConfig.NV_texshaders && glConfig.multitexture && r_pixel_shader_warp->integer; - qboolean texShaderWarpARB = glConfig.arb_fragment_program && glConfig.multitexture && r_pixel_shader_warp->integer; + qboolean texShaderWarpNV = glConfig.NV_texshaders && r_pixel_shader_warp->integer; + qboolean texShaderWarpARB = glConfig.arb_fragment_program && r_pixel_shader_warp->integer; qboolean texShaderWarp = (texShaderWarpNV || texShaderWarpARB); if (texShaderWarpNV && texShaderWarpARB) texShaderWarpARB = (r_pixel_shader_warp->integer == 1); @@ -418,7 +418,7 @@ void R_DrawWarpSurface (msurface_t *fa, float alpha, qboolean render) vec3_t point; int i; qboolean light = r_warp_lighting->integer && !r_fullbright->integer && !(fa->texinfo->flags & SURF_NOLIGHTENV); - qboolean texShaderNV = glConfig.NV_texshaders && glConfig.multitexture + qboolean texShaderNV = glConfig.NV_texshaders && ( (!glConfig.arb_fragment_program && r_pixel_shader_warp->integer) || (glConfig.arb_fragment_program && r_pixel_shader_warp->integer > 1) );