2010-02-15 23:26:55 +00:00
/*
Copyright ( C ) 1996 - 2001 Id Software , Inc .
Copyright ( C ) 2002 - 2009 John Fitzgibbons and others
Copyright ( C ) 2007 - 2008 Kristian Duske
2014-09-22 08:55:46 +00:00
Copyright ( C ) 2010 - 2014 QuakeSpasm developers
2010-02-15 23:26:55 +00:00
This program 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 .
This program 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 this program ; if not , write to the Free Software
Foundation , Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*/
// r_brush.c: brush model rendering. renamed from r_surf.c
# include "quakedef.h"
extern cvar_t gl_fullbrights , r_drawflat , gl_overbright , r_oldwater ; //johnfitz
2023-03-18 11:14:40 +00:00
extern cvar_t r_brokenturbbias ; // to replicate a QuakeSpasm bug.
2011-08-24 07:47:29 +00:00
extern cvar_t gl_zfix ; // QuakeSpasm z-fighting fix
2010-02-15 23:26:55 +00:00
int gl_lightmap_format ;
int lightmap_bytes ;
2021-07-13 05:20:09 +00:00
qboolean lightmaps_latecached ;
2024-03-01 08:09:56 +00:00
qboolean lightmaps_skipupdates ;
2010-02-15 23:26:55 +00:00
2019-09-12 06:49:35 +00:00
# define MAX_SANITY_LIGHTMAPS (1u<<20)
2021-06-23 01:37:10 +00:00
struct lightmap_s * lightmaps ;
2019-09-12 06:49:35 +00:00
int lightmap_count ;
2024-03-01 08:09:56 +00:00
static int last_lightmap_allocated ;
static int * allocated ;
int LMBLOCK_WIDTH , LMBLOCK_HEIGHT ;
2010-02-15 23:26:55 +00:00
/*
= = = = = = = = = = = = = = =
R_TextureAnimation - - johnfitz - - added " frame " param to eliminate use of " currententity " global
Returns the proper texture for a given time and base texture
= = = = = = = = = = = = = = =
*/
texture_t * R_TextureAnimation ( texture_t * base , int frame )
{
int relative ;
int count ;
if ( frame )
if ( base - > alternate_anims )
base = base - > alternate_anims ;
if ( ! base - > anim_total )
return base ;
relative = ( int ) ( cl . time * 10 ) % base - > anim_total ;
count = 0 ;
while ( base - > anim_min > relative | | base - > anim_max < = relative )
{
base = base - > anim_next ;
if ( ! base )
Sys_Error ( " R_TextureAnimation: broken cycle " ) ;
if ( + + count > 100 )
Sys_Error ( " R_TextureAnimation: infinite cycle " ) ;
}
return base ;
}
/*
= = = = = = = = = = = = = = = =
DrawGLPoly
= = = = = = = = = = = = = = = =
*/
void DrawGLPoly ( glpoly_t * p )
{
float * v ;
int i ;
glBegin ( GL_POLYGON ) ;
v = p - > verts [ 0 ] ;
for ( i = 0 ; i < p - > numverts ; i + + , v + = VERTEXSIZE )
{
glTexCoord2f ( v [ 3 ] , v [ 4 ] ) ;
glVertex3fv ( v ) ;
}
glEnd ( ) ;
}
/*
= = = = = = = = = = = = = = = =
DrawGLTriangleFan - - johnfitz - - like DrawGLPoly but for r_showtris
= = = = = = = = = = = = = = = =
*/
void DrawGLTriangleFan ( glpoly_t * p )
{
float * v ;
int i ;
glBegin ( GL_TRIANGLE_FAN ) ;
v = p - > verts [ 0 ] ;
for ( i = 0 ; i < p - > numverts ; i + + , v + = VERTEXSIZE )
{
glVertex3fv ( v ) ;
}
glEnd ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
BRUSH MODELS
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
2014-08-29 08:27:22 +00:00
#if 0
2010-02-15 23:26:55 +00:00
/*
= = = = = = = = = = = = = = = =
R_DrawSequentialPoly - - johnfitz - - rewritten
= = = = = = = = = = = = = = = =
*/
void R_DrawSequentialPoly ( msurface_t * s )
{
glpoly_t * p ;
texture_t * t ;
float * v ;
float entalpha ;
int i ;
t = R_TextureAnimation ( s - > texinfo - > texture , currententity - > frame ) ;
entalpha = ENTALPHA_DECODE ( currententity - > alpha ) ;
// drawflat
if ( r_drawflat_cheatsafe )
{
if ( ( s - > flags & SURF_DRAWTURB ) & & r_oldwater . value )
{
for ( p = s - > polys - > next ; p ; p = p - > next )
{
2011-04-01 14:55:45 +00:00
srand ( ( unsigned int ) ( uintptr_t ) p ) ;
2010-02-15 23:26:55 +00:00
glColor3f ( rand ( ) % 256 / 255.0 , rand ( ) % 256 / 255.0 , rand ( ) % 256 / 255.0 ) ;
DrawGLPoly ( p ) ;
rs_brushpasses + + ;
}
return ;
}
2011-04-01 14:55:45 +00:00
srand ( ( unsigned int ) ( uintptr_t ) s - > polys ) ;
2010-02-15 23:26:55 +00:00
glColor3f ( rand ( ) % 256 / 255.0 , rand ( ) % 256 / 255.0 , rand ( ) % 256 / 255.0 ) ;
DrawGLPoly ( s - > polys ) ;
rs_brushpasses + + ;
return ;
}
// fullbright
if ( ( r_fullbright_cheatsafe ) & & ! ( s - > flags & SURF_DRAWTILED ) )
{
if ( entalpha < 1 )
{
glDepthMask ( GL_FALSE ) ;
glEnable ( GL_BLEND ) ;
glTexEnvf ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_MODULATE ) ;
glColor4f ( 1 , 1 , 1 , entalpha ) ;
}
2014-08-19 02:20:12 +00:00
if ( s - > flags & SURF_DRAWFENCE )
glEnable ( GL_ALPHA_TEST ) ; // Flip on alpha test
2010-02-15 23:26:55 +00:00
GL_Bind ( t - > gltexture ) ;
DrawGLPoly ( s - > polys ) ;
rs_brushpasses + + ;
2014-08-19 02:20:12 +00:00
if ( s - > flags & SURF_DRAWFENCE )
glDisable ( GL_ALPHA_TEST ) ; // Flip alpha test back off
2010-02-15 23:26:55 +00:00
if ( entalpha < 1 )
{
glDepthMask ( GL_TRUE ) ;
glDisable ( GL_BLEND ) ;
glTexEnvf ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_REPLACE ) ;
glColor3f ( 1 , 1 , 1 ) ;
}
goto fullbrights ;
}
// r_lightmap
if ( r_lightmap_cheatsafe )
{
if ( s - > flags & SURF_DRAWTILED )
{
glDisable ( GL_TEXTURE_2D ) ;
DrawGLPoly ( s - > polys ) ;
glEnable ( GL_TEXTURE_2D ) ;
rs_brushpasses + + ;
return ;
}
R_RenderDynamicLightmaps ( s ) ;
GL_Bind ( lightmap_textures [ s - > lightmaptexturenum ] ) ;
if ( ! gl_overbright . value )
{
glTexEnvf ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_MODULATE ) ;
glColor3f ( 0.5 , 0.5 , 0.5 ) ;
}
glBegin ( GL_POLYGON ) ;
v = s - > polys - > verts [ 0 ] ;
for ( i = 0 ; i < s - > polys - > numverts ; i + + , v + = VERTEXSIZE )
{
glTexCoord2f ( v [ 5 ] , v [ 6 ] ) ;
glVertex3fv ( v ) ;
}
glEnd ( ) ;
if ( ! gl_overbright . value )
{
glColor3f ( 1 , 1 , 1 ) ;
glTexEnvf ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_REPLACE ) ;
}
rs_brushpasses + + ;
return ;
}
// sky poly -- skip it, already handled in gl_sky.c
if ( s - > flags & SURF_DRAWSKY )
return ;
// water poly
if ( s - > flags & SURF_DRAWTURB )
{
if ( currententity - > alpha = = ENTALPHA_DEFAULT )
2022-06-02 11:33:10 +00:00
{
entalpha = GL_WaterAlphaForSurface ( s ) ;
if ( entalpha > 1.0f ) entalpha = 1.0f ;
else if ( entalpha < 0.0f ) entalpha = 0.0f ;
}
2010-02-15 23:26:55 +00:00
if ( entalpha < 1 )
{
glDepthMask ( GL_FALSE ) ;
glEnable ( GL_BLEND ) ;
glTexEnvf ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_MODULATE ) ;
glColor4f ( 1 , 1 , 1 , entalpha ) ;
}
if ( r_oldwater . value )
{
GL_Bind ( s - > texinfo - > texture - > gltexture ) ;
for ( p = s - > polys - > next ; p ; p = p - > next )
{
DrawWaterPoly ( p ) ;
rs_brushpasses + + ;
}
rs_brushpasses + + ;
}
else
{
GL_Bind ( s - > texinfo - > texture - > warpimage ) ;
s - > texinfo - > texture - > update_warp = true ; // FIXME: one frame too late!
DrawGLPoly ( s - > polys ) ;
rs_brushpasses + + ;
}
if ( entalpha < 1 )
{
glDepthMask ( GL_TRUE ) ;
glDisable ( GL_BLEND ) ;
glTexEnvf ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_REPLACE ) ;
glColor3f ( 1 , 1 , 1 ) ;
}
return ;
}
// missing texture
if ( s - > flags & SURF_NOTEXTURE )
{
if ( entalpha < 1 )
{
glDepthMask ( GL_FALSE ) ;
glEnable ( GL_BLEND ) ;
glTexEnvf ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_MODULATE ) ;
glColor4f ( 1 , 1 , 1 , entalpha ) ;
}
GL_Bind ( t - > gltexture ) ;
DrawGLPoly ( s - > polys ) ;
rs_brushpasses + + ;
if ( entalpha < 1 )
{
glDepthMask ( GL_TRUE ) ;
glDisable ( GL_BLEND ) ;
glTexEnvf ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_REPLACE ) ;
glColor3f ( 1 , 1 , 1 ) ;
}
return ;
}
// lightmapped poly
if ( entalpha < 1 )
{
glDepthMask ( GL_FALSE ) ;
glEnable ( GL_BLEND ) ;
glTexEnvf ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_MODULATE ) ;
glColor4f ( 1 , 1 , 1 , entalpha ) ;
}
else
glColor3f ( 1 , 1 , 1 ) ;
2014-08-19 02:20:12 +00:00
if ( s - > flags & SURF_DRAWFENCE )
glEnable ( GL_ALPHA_TEST ) ; // Flip on alpha test
2010-02-15 23:26:55 +00:00
if ( gl_overbright . value )
{
if ( gl_texture_env_combine & & gl_mtexable ) //case 1: texture and lightmap in one pass, overbright using texture combiners
{
GL_DisableMultitexture ( ) ; // selects TEXTURE0
GL_Bind ( t - > gltexture ) ;
glTexEnvf ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_MODULATE ) ;
GL_EnableMultitexture ( ) ; // selects TEXTURE1
GL_Bind ( lightmap_textures [ s - > lightmaptexturenum ] ) ;
R_RenderDynamicLightmaps ( s ) ;
glTexEnvi ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_COMBINE_EXT ) ;
glTexEnvi ( GL_TEXTURE_ENV , GL_COMBINE_RGB_EXT , GL_MODULATE ) ;
glTexEnvi ( GL_TEXTURE_ENV , GL_SOURCE0_RGB_EXT , GL_PREVIOUS_EXT ) ;
glTexEnvi ( GL_TEXTURE_ENV , GL_SOURCE1_RGB_EXT , GL_TEXTURE ) ;
glTexEnvf ( GL_TEXTURE_ENV , GL_RGB_SCALE_EXT , 2.0f ) ;
glBegin ( GL_POLYGON ) ;
v = s - > polys - > verts [ 0 ] ;
for ( i = 0 ; i < s - > polys - > numverts ; i + + , v + = VERTEXSIZE )
{
2014-08-30 08:00:34 +00:00
GL_MTexCoord2fFunc ( GL_TEXTURE0_ARB , v [ 3 ] , v [ 4 ] ) ;
GL_MTexCoord2fFunc ( GL_TEXTURE1_ARB , v [ 5 ] , v [ 6 ] ) ;
2010-02-15 23:26:55 +00:00
glVertex3fv ( v ) ;
}
glEnd ( ) ;
glTexEnvf ( GL_TEXTURE_ENV , GL_RGB_SCALE_EXT , 1.0f ) ;
glTexEnvf ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_MODULATE ) ;
GL_DisableMultitexture ( ) ;
rs_brushpasses + + ;
}
2014-08-19 02:20:12 +00:00
else if ( entalpha < 1 | | ( s - > flags & SURF_DRAWFENCE ) ) //case 2: can't do multipass if entity has alpha, so just draw the texture
2010-02-15 23:26:55 +00:00
{
GL_Bind ( t - > gltexture ) ;
DrawGLPoly ( s - > polys ) ;
rs_brushpasses + + ;
}
else //case 3: texture in one pass, lightmap in second pass using 2x modulation blend func, fog in third pass
{
//first pass -- texture with no fog
Fog_DisableGFog ( ) ;
GL_Bind ( t - > gltexture ) ;
DrawGLPoly ( s - > polys ) ;
Fog_EnableGFog ( ) ;
rs_brushpasses + + ;
//second pass -- lightmap with black fog, modulate blended
R_RenderDynamicLightmaps ( s ) ;
GL_Bind ( lightmap_textures [ s - > lightmaptexturenum ] ) ;
glDepthMask ( GL_FALSE ) ;
glEnable ( GL_BLEND ) ;
glBlendFunc ( GL_DST_COLOR , GL_SRC_COLOR ) ; //2x modulate
Fog_StartAdditive ( ) ;
glBegin ( GL_POLYGON ) ;
v = s - > polys - > verts [ 0 ] ;
for ( i = 0 ; i < s - > polys - > numverts ; i + + , v + = VERTEXSIZE )
{
glTexCoord2f ( v [ 5 ] , v [ 6 ] ) ;
glVertex3fv ( v ) ;
}
glEnd ( ) ;
Fog_StopAdditive ( ) ;
rs_brushpasses + + ;
//third pass -- black geo with normal fog, additive blended
if ( Fog_GetDensity ( ) > 0 )
{
glBlendFunc ( GL_ONE , GL_ONE ) ; //add
glTexEnvf ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_MODULATE ) ;
glColor3f ( 0 , 0 , 0 ) ;
DrawGLPoly ( s - > polys ) ;
glColor3f ( 1 , 1 , 1 ) ;
glTexEnvf ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_REPLACE ) ;
rs_brushpasses + + ;
}
glBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ;
glDisable ( GL_BLEND ) ;
glDepthMask ( GL_TRUE ) ;
}
}
else
{
if ( gl_mtexable ) //case 4: texture and lightmap in one pass, regular modulation
{
GL_DisableMultitexture ( ) ; // selects TEXTURE0
GL_Bind ( t - > gltexture ) ;
glTexEnvf ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_MODULATE ) ;
GL_EnableMultitexture ( ) ; // selects TEXTURE1
GL_Bind ( lightmap_textures [ s - > lightmaptexturenum ] ) ;
R_RenderDynamicLightmaps ( s ) ;
glTexEnvf ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_MODULATE ) ;
glBegin ( GL_POLYGON ) ;
v = s - > polys - > verts [ 0 ] ;
for ( i = 0 ; i < s - > polys - > numverts ; i + + , v + = VERTEXSIZE )
{
2014-08-30 08:00:34 +00:00
GL_MTexCoord2fFunc ( GL_TEXTURE0_ARB , v [ 3 ] , v [ 4 ] ) ;
GL_MTexCoord2fFunc ( GL_TEXTURE1_ARB , v [ 5 ] , v [ 6 ] ) ;
2010-02-15 23:26:55 +00:00
glVertex3fv ( v ) ;
}
glEnd ( ) ;
GL_DisableMultitexture ( ) ;
rs_brushpasses + + ;
}
2014-08-19 02:20:12 +00:00
else if ( entalpha < 1 | | ( s - > flags & SURF_DRAWFENCE ) ) //case 5: can't do multipass if entity has alpha, so just draw the texture
2010-02-15 23:26:55 +00:00
{
GL_Bind ( t - > gltexture ) ;
DrawGLPoly ( s - > polys ) ;
rs_brushpasses + + ;
}
else //case 6: texture in one pass, lightmap in a second pass, fog in third pass
{
//first pass -- texture with no fog
Fog_DisableGFog ( ) ;
GL_Bind ( t - > gltexture ) ;
DrawGLPoly ( s - > polys ) ;
Fog_EnableGFog ( ) ;
rs_brushpasses + + ;
//second pass -- lightmap with black fog, modulate blended
R_RenderDynamicLightmaps ( s ) ;
GL_Bind ( lightmap_textures [ s - > lightmaptexturenum ] ) ;
glDepthMask ( GL_FALSE ) ;
glEnable ( GL_BLEND ) ;
glBlendFunc ( GL_ZERO , GL_SRC_COLOR ) ; //modulate
Fog_StartAdditive ( ) ;
glBegin ( GL_POLYGON ) ;
v = s - > polys - > verts [ 0 ] ;
for ( i = 0 ; i < s - > polys - > numverts ; i + + , v + = VERTEXSIZE )
{
glTexCoord2f ( v [ 5 ] , v [ 6 ] ) ;
glVertex3fv ( v ) ;
}
glEnd ( ) ;
Fog_StopAdditive ( ) ;
rs_brushpasses + + ;
//third pass -- black geo with normal fog, additive blended
if ( Fog_GetDensity ( ) > 0 )
{
glBlendFunc ( GL_ONE , GL_ONE ) ; //add
glTexEnvf ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_MODULATE ) ;
glColor3f ( 0 , 0 , 0 ) ;
DrawGLPoly ( s - > polys ) ;
glColor3f ( 1 , 1 , 1 ) ;
glTexEnvf ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_REPLACE ) ;
rs_brushpasses + + ;
}
glBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ;
glDisable ( GL_BLEND ) ;
glDepthMask ( GL_TRUE ) ;
}
}
if ( entalpha < 1 )
{
glDepthMask ( GL_TRUE ) ;
glDisable ( GL_BLEND ) ;
glTexEnvf ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_REPLACE ) ;
glColor3f ( 1 , 1 , 1 ) ;
}
2014-08-17 21:12:54 +00:00
2014-08-19 02:20:12 +00:00
if ( s - > flags & SURF_DRAWFENCE )
glDisable ( GL_ALPHA_TEST ) ; // Flip alpha test back off
2010-02-15 23:26:55 +00:00
fullbrights :
if ( gl_fullbrights . value & & t - > fullbright )
{
glDepthMask ( GL_FALSE ) ;
glEnable ( GL_BLEND ) ;
glBlendFunc ( GL_ONE , GL_ONE ) ;
glTexEnvf ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_MODULATE ) ;
glColor3f ( entalpha , entalpha , entalpha ) ;
GL_Bind ( t - > fullbright ) ;
Fog_StartAdditive ( ) ;
DrawGLPoly ( s - > polys ) ;
Fog_StopAdditive ( ) ;
glColor3f ( 1 , 1 , 1 ) ;
glTexEnvf ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_REPLACE ) ;
glBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ;
glDisable ( GL_BLEND ) ;
glDepthMask ( GL_TRUE ) ;
rs_brushpasses + + ;
}
}
2014-08-29 08:27:22 +00:00
# endif
2010-02-15 23:26:55 +00:00
/*
= = = = = = = = = = = = = = = = =
R_DrawBrushModel
= = = = = = = = = = = = = = = = =
*/
void R_DrawBrushModel ( entity_t * e )
{
chase.c, cl_input.c, cl_parse.c, client.h, common.c, common.h, console.h,
cvar.h, draw.h, gl_draw.c, gl_fog.c, gl_mesh.c, gl_model.c, gl_model.h,
gl_rmain.c, gl_rmisc.c, gl_screen.c, gl_sky.c, gl_texmgr.c, glquake.h,
host.c, keys.c, keys.h, main.c, menu.c, menu.h, pr_cmds.c, quakedef.h,
r_alias.c, r_brush.c, r_part.c, r_sprite.c, r_world.c, sbar.c, sbar.h,
screen.h, snd_dma.c, snd_mem.c, snd_mix.c, sv_main.c, sys_sdl.c, vid.h,
view.h, world.c, world.h: Loads of warning fixes about missing function
prototypes, missing parens around &, missing braces leading to ambiguous
else statements and unused and uninitialized variables. There are still a
couple of unitialised variables here and there, but not much. The warnings
about strict aliasing violations need taking care of.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@21 af15c1b1-3010-417e-b628-4374ebc0bcbd
2010-02-16 12:01:07 +00:00
int i , k ;
2010-02-15 23:26:55 +00:00
msurface_t * psurf ;
float dot ;
mplane_t * pplane ;
2012-05-30 08:56:06 +00:00
qmodel_t * clmodel ;
2018-05-25 10:54:33 +00:00
vec3_t lightorg ;
2024-03-01 08:09:56 +00:00
extern byte * skipsubmodels ;
if ( e - > model - > submodelof = = cl . worldmodel & &
skipsubmodels & &
skipsubmodels [ e - > model - > submodelidx > > 3 ] & ( 1u < < ( e - > model - > submodelidx & 7 ) ) )
return ; //its in the scenecache that we're drawing. don't draw it twice (and certainly not the slow way).
2010-02-15 23:26:55 +00:00
if ( R_CullModelForEntity ( e ) )
return ;
currententity = e ;
clmodel = e - > model ;
VectorSubtract ( r_refdef . vieworg , e - > origin , modelorg ) ;
if ( e - > angles [ 0 ] | | e - > angles [ 1 ] | | e - > angles [ 2 ] )
{
vec3_t temp ;
vec3_t forward , right , up ;
VectorCopy ( modelorg , temp ) ;
AngleVectors ( e - > angles , forward , right , up ) ;
modelorg [ 0 ] = DotProduct ( temp , forward ) ;
modelorg [ 1 ] = - DotProduct ( temp , right ) ;
modelorg [ 2 ] = DotProduct ( temp , up ) ;
}
psurf = & clmodel - > surfaces [ clmodel - > firstmodelsurface ] ;
// calculate dynamic lighting for bmodel if it's not an
// instanced model
if ( clmodel - > firstmodelsurface ! = 0 & & ! gl_flashblend . value )
2024-03-01 08:09:56 +00:00
if ( e - > model - > submodelof = = cl . worldmodel ) //R_MarkLights has a hacky assumption about cl.worldmodel that could crash if we imported some other model.
2010-02-15 23:26:55 +00:00
{
for ( k = 0 ; k < MAX_DLIGHTS ; k + + )
{
if ( ( cl_dlights [ k ] . die < cl . time ) | |
( ! cl_dlights [ k ] . radius ) )
continue ;
2018-05-25 10:54:33 +00:00
VectorSubtract ( cl_dlights [ k ] . origin , e - > origin , lightorg ) ;
2024-03-01 08:09:56 +00:00
R_MarkLights ( & cl_dlights [ k ] , lightorg , r_framecount , k ,
2010-02-15 23:26:55 +00:00
clmodel - > nodes + clmodel - > hulls [ 0 ] . firstclipnode ) ;
}
}
2016-04-28 21:47:12 +00:00
glPushMatrix ( ) ;
2010-02-15 23:26:55 +00:00
e - > angles [ 0 ] = - e - > angles [ 0 ] ; // stupid quake bug
2011-08-24 07:47:29 +00:00
if ( gl_zfix . value )
{
e - > origin [ 0 ] - = DIST_EPSILON ;
e - > origin [ 1 ] - = DIST_EPSILON ;
e - > origin [ 2 ] - = DIST_EPSILON ;
}
2017-09-17 02:12:53 +00:00
R_RotateForEntity ( e - > origin , e - > angles , e - > netstate . scale ) ;
2011-08-24 07:47:29 +00:00
if ( gl_zfix . value )
{
e - > origin [ 0 ] + = DIST_EPSILON ;
e - > origin [ 1 ] + = DIST_EPSILON ;
e - > origin [ 2 ] + = DIST_EPSILON ;
}
2010-02-15 23:26:55 +00:00
e - > angles [ 0 ] = - e - > angles [ 0 ] ; // stupid quake bug
2014-08-29 08:27:22 +00:00
R_ClearTextureChains ( clmodel , chain_model ) ;
2010-02-15 23:26:55 +00:00
for ( i = 0 ; i < clmodel - > nummodelsurfaces ; i + + , psurf + + )
{
pplane = psurf - > plane ;
dot = DotProduct ( modelorg , pplane - > normal ) - pplane - > dist ;
if ( ( ( psurf - > flags & SURF_PLANEBACK ) & & ( dot < - BACKFACE_EPSILON ) ) | |
( ! ( psurf - > flags & SURF_PLANEBACK ) & & ( dot > BACKFACE_EPSILON ) ) )
{
2014-08-29 08:27:22 +00:00
R_ChainSurface ( psurf , chain_model ) ;
2021-09-03 06:19:38 +00:00
R_RenderDynamicLightmaps ( clmodel , psurf ) ;
2010-02-15 23:26:55 +00:00
rs_brushpolys + + ;
}
}
2014-08-29 08:27:22 +00:00
R_DrawTextureChains ( clmodel , e , chain_model ) ;
R_DrawTextureChains_Water ( clmodel , e , chain_model ) ;
2010-02-15 23:26:55 +00:00
glPopMatrix ( ) ;
}
/*
= = = = = = = = = = = = = = = = =
R_DrawBrushModel_ShowTris - - johnfitz
= = = = = = = = = = = = = = = = =
*/
void R_DrawBrushModel_ShowTris ( entity_t * e )
{
chase.c, cl_input.c, cl_parse.c, client.h, common.c, common.h, console.h,
cvar.h, draw.h, gl_draw.c, gl_fog.c, gl_mesh.c, gl_model.c, gl_model.h,
gl_rmain.c, gl_rmisc.c, gl_screen.c, gl_sky.c, gl_texmgr.c, glquake.h,
host.c, keys.c, keys.h, main.c, menu.c, menu.h, pr_cmds.c, quakedef.h,
r_alias.c, r_brush.c, r_part.c, r_sprite.c, r_world.c, sbar.c, sbar.h,
screen.h, snd_dma.c, snd_mem.c, snd_mix.c, sv_main.c, sys_sdl.c, vid.h,
view.h, world.c, world.h: Loads of warning fixes about missing function
prototypes, missing parens around &, missing braces leading to ambiguous
else statements and unused and uninitialized variables. There are still a
couple of unitialised variables here and there, but not much. The warnings
about strict aliasing violations need taking care of.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@21 af15c1b1-3010-417e-b628-4374ebc0bcbd
2010-02-16 12:01:07 +00:00
int i ;
2010-02-15 23:26:55 +00:00
msurface_t * psurf ;
float dot ;
mplane_t * pplane ;
2012-05-30 08:56:06 +00:00
qmodel_t * clmodel ;
2010-02-15 23:26:55 +00:00
glpoly_t * p ;
if ( R_CullModelForEntity ( e ) )
return ;
currententity = e ;
clmodel = e - > model ;
VectorSubtract ( r_refdef . vieworg , e - > origin , modelorg ) ;
if ( e - > angles [ 0 ] | | e - > angles [ 1 ] | | e - > angles [ 2 ] )
{
vec3_t temp ;
vec3_t forward , right , up ;
VectorCopy ( modelorg , temp ) ;
AngleVectors ( e - > angles , forward , right , up ) ;
modelorg [ 0 ] = DotProduct ( temp , forward ) ;
modelorg [ 1 ] = - DotProduct ( temp , right ) ;
modelorg [ 2 ] = DotProduct ( temp , up ) ;
}
psurf = & clmodel - > surfaces [ clmodel - > firstmodelsurface ] ;
2013-02-20 06:22:42 +00:00
glPushMatrix ( ) ;
2010-02-15 23:26:55 +00:00
e - > angles [ 0 ] = - e - > angles [ 0 ] ; // stupid quake bug
2017-09-17 02:12:53 +00:00
R_RotateForEntity ( e - > origin , e - > angles , e - > netstate . scale ) ;
2010-02-15 23:26:55 +00:00
e - > angles [ 0 ] = - e - > angles [ 0 ] ; // stupid quake bug
//
// draw it
//
for ( i = 0 ; i < clmodel - > nummodelsurfaces ; i + + , psurf + + )
{
pplane = psurf - > plane ;
dot = DotProduct ( modelorg , pplane - > normal ) - pplane - > dist ;
if ( ( ( psurf - > flags & SURF_PLANEBACK ) & & ( dot < - BACKFACE_EPSILON ) ) | |
( ! ( psurf - > flags & SURF_PLANEBACK ) & & ( dot > BACKFACE_EPSILON ) ) )
{
2023-03-18 11:14:40 +00:00
if ( ( psurf - > flags & SURF_DRAWTURB ) & & ! gl_glsl_water_able )
2010-02-15 23:26:55 +00:00
for ( p = psurf - > polys - > next ; p ; p = p - > next )
DrawGLTriangleFan ( p ) ;
else
DrawGLTriangleFan ( psurf - > polys ) ;
}
}
glPopMatrix ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
LIGHTMAPS
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = =
R_RenderDynamicLightmaps
called during rendering
= = = = = = = = = = = = = = = =
*/
2017-09-17 02:12:53 +00:00
void R_RenderDynamicLightmaps ( qmodel_t * model , msurface_t * fa )
2010-02-15 23:26:55 +00:00
{
byte * base ;
int maps ;
glRect_t * theRect ;
int smax , tmax ;
if ( fa - > flags & SURF_DRAWTILED ) //johnfitz -- not a lightmapped surface
return ;
// add to lightmap chain
2021-06-23 01:37:10 +00:00
fa - > polys - > chain = lightmaps [ fa - > lightmaptexturenum ] . polys ;
lightmaps [ fa - > lightmaptexturenum ] . polys = fa - > polys ;
2010-02-15 23:26:55 +00:00
// check for lightmap modification
2019-09-10 14:41:11 +00:00
for ( maps = 0 ; maps < MAXLIGHTMAPS & & fa - > styles [ maps ] ! = INVALID_LIGHTSTYLE ; maps + + )
2010-02-15 23:26:55 +00:00
if ( d_lightstylevalue [ fa - > styles [ maps ] ] ! = fa - > cached_light [ maps ] )
goto dynamic ;
if ( fa - > dlightframe = = r_framecount // dynamic this frame
| | fa - > cached_dlight ) // dynamic previously
{
dynamic :
if ( r_dynamic . value )
{
2021-06-23 01:37:10 +00:00
struct lightmap_s * lm = & lightmaps [ fa - > lightmaptexturenum ] ;
2019-09-12 06:49:35 +00:00
lm - > modified = true ;
theRect = & lm - > rectchange ;
2010-02-15 23:26:55 +00:00
if ( fa - > light_t < theRect - > t ) {
if ( theRect - > h )
theRect - > h + = theRect - > t - fa - > light_t ;
theRect - > t = fa - > light_t ;
}
if ( fa - > light_s < theRect - > l ) {
if ( theRect - > w )
theRect - > w + = theRect - > l - fa - > light_s ;
theRect - > l = fa - > light_s ;
}
2023-11-02 23:18:42 +00:00
smax = fa - > extents [ 0 ] + 1 ;
tmax = fa - > extents [ 1 ] + 1 ;
2010-02-15 23:26:55 +00:00
if ( ( theRect - > w + theRect - > l ) < ( fa - > light_s + smax ) )
theRect - > w = ( fa - > light_s - theRect - > l ) + smax ;
if ( ( theRect - > h + theRect - > t ) < ( fa - > light_t + tmax ) )
theRect - > h = ( fa - > light_t - theRect - > t ) + tmax ;
2024-03-01 08:09:56 +00:00
base = lm - > pbodata ;
2019-09-12 06:49:27 +00:00
base + = fa - > light_t * LMBLOCK_WIDTH * lightmap_bytes + fa - > light_s * lightmap_bytes ;
2024-03-01 08:09:56 +00:00
R_BuildLightMap ( model , fa , base , LMBLOCK_WIDTH * lightmap_bytes , currententity , r_framecount , cl_dlights ) ;
2010-02-15 23:26:55 +00:00
}
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
AllocBlock - - returns a texture number and the position inside it
= = = = = = = = = = = = = = = = = = = = = = = =
*/
int AllocBlock ( int w , int h , int * x , int * y )
{
int i , j ;
int best , best2 ;
int texnum ;
2014-08-05 18:22:58 +00:00
// ericw -- rather than searching starting at lightmap 0 every time,
// start at the last lightmap we allocated a surface in.
// This makes AllocBlock much faster on large levels (can shave off 3+ seconds
// of load time on a level with 180 lightmaps), at a cost of not quite packing
// lightmaps as tightly vs. not doing this (uses ~5% more lightmaps)
2019-09-12 06:49:35 +00:00
for ( texnum = last_lightmap_allocated ; texnum < MAX_SANITY_LIGHTMAPS ; texnum + + )
2010-02-15 23:26:55 +00:00
{
2019-09-12 06:49:35 +00:00
if ( texnum = = lightmap_count )
{
lightmap_count + + ;
2021-06-23 01:37:10 +00:00
lightmaps = ( struct lightmap_s * ) realloc ( lightmaps , sizeof ( * lightmaps ) * lightmap_count ) ;
memset ( & lightmaps [ texnum ] , 0 , sizeof ( lightmaps [ texnum ] ) ) ;
2024-03-01 08:09:56 +00:00
if ( GL_BufferStorageFunc )
{ //if we have bufferstorage then we have mapbufferrange+persistent+coherent
GL_GenBuffersFunc ( 1 , & lightmaps [ texnum ] . pbohandle ) ;
GL_BindBufferFunc ( GL_PIXEL_UNPACK_BUFFER_ARB , lightmaps [ texnum ] . pbohandle ) ;
GL_BufferStorageFunc ( GL_PIXEL_UNPACK_BUFFER_ARB , 4 * LMBLOCK_WIDTH * LMBLOCK_HEIGHT , NULL , GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_CLIENT_STORAGE_BIT ) ;
lightmaps [ texnum ] . pbodata = GL_MapBufferRangeFunc ( GL_PIXEL_UNPACK_BUFFER_ARB , 0 , 4 * LMBLOCK_WIDTH * LMBLOCK_HEIGHT , GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT ) ;
GL_BindBufferFunc ( GL_PIXEL_UNPACK_BUFFER_ARB , 0 ) ;
}
else
lightmaps [ texnum ] . pbodata = ( byte * ) calloc ( 1 , 4 * LMBLOCK_WIDTH * LMBLOCK_HEIGHT ) ;
2019-09-12 06:49:35 +00:00
//as we're only tracking one texture, we don't need multiple copies of allocated any more.
2024-03-01 08:09:56 +00:00
memset ( allocated , 0 , sizeof ( * allocated ) * LMBLOCK_WIDTH ) ;
2021-07-13 05:20:09 +00:00
2021-08-31 05:43:13 +00:00
lightmaps [ texnum ] . modified = true ;
lightmaps [ texnum ] . rectchange . l = 0 ;
lightmaps [ texnum ] . rectchange . t = 0 ;
lightmaps [ texnum ] . rectchange . h = LMBLOCK_HEIGHT ;
lightmaps [ texnum ] . rectchange . w = LMBLOCK_WIDTH ;
2019-09-12 06:49:35 +00:00
}
2019-09-12 06:49:27 +00:00
best = LMBLOCK_HEIGHT ;
2010-02-15 23:26:55 +00:00
2019-09-12 06:49:27 +00:00
for ( i = 0 ; i < LMBLOCK_WIDTH - w ; i + + )
2010-02-15 23:26:55 +00:00
{
best2 = 0 ;
for ( j = 0 ; j < w ; j + + )
{
2019-09-12 06:49:35 +00:00
if ( allocated [ i + j ] > = best )
2010-02-15 23:26:55 +00:00
break ;
2019-09-12 06:49:35 +00:00
if ( allocated [ i + j ] > best2 )
best2 = allocated [ i + j ] ;
2010-02-15 23:26:55 +00:00
}
if ( j = = w )
{ // this is a valid spot
* x = i ;
* y = best = best2 ;
}
}
2019-09-12 06:49:27 +00:00
if ( best + h > LMBLOCK_HEIGHT )
2010-02-15 23:26:55 +00:00
continue ;
for ( i = 0 ; i < w ; i + + )
2019-09-12 06:49:35 +00:00
allocated [ * x + i ] = best + h ;
2010-02-15 23:26:55 +00:00
2019-09-12 06:49:35 +00:00
last_lightmap_allocated = texnum ;
2010-02-15 23:26:55 +00:00
return texnum ;
}
Sys_Error ( " AllocBlock: full " ) ;
return 0 ; //johnfitz -- shut up compiler
}
mvertex_t * r_pcurrentvertbase ;
2012-05-30 08:56:06 +00:00
qmodel_t * currentmodel ;
2010-02-15 23:26:55 +00:00
int nColinElim ;
/*
= = = = = = = = = = = = = = = = = = = = = = = =
GL_CreateSurfaceLightmap
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2017-09-17 02:12:53 +00:00
void GL_CreateSurfaceLightmap ( qmodel_t * model , msurface_t * surf )
2010-02-15 23:26:55 +00:00
{
int smax , tmax ;
byte * base ;
2021-11-12 02:31:34 +00:00
if ( surf - > flags & SURF_DRAWTILED )
{
surf - > lightmaptexturenum = - 1 ;
return ;
}
2023-11-02 23:18:42 +00:00
smax = surf - > extents [ 0 ] + 1 ;
tmax = surf - > extents [ 1 ] + 1 ;
2010-02-15 23:26:55 +00:00
surf - > lightmaptexturenum = AllocBlock ( smax , tmax , & surf - > light_s , & surf - > light_t ) ;
2024-03-01 08:09:56 +00:00
base = lightmaps [ surf - > lightmaptexturenum ] . pbodata ;
2019-09-12 06:49:27 +00:00
base + = ( surf - > light_t * LMBLOCK_WIDTH + surf - > light_s ) * lightmap_bytes ;
2024-03-01 08:09:56 +00:00
R_BuildLightMap ( model , surf , base , LMBLOCK_WIDTH * lightmap_bytes , currententity , r_framecount , cl_dlights ) ;
2010-02-15 23:26:55 +00:00
}
/*
= = = = = = = = = = = = = = = =
BuildSurfaceDisplayList - - called at level load time
= = = = = = = = = = = = = = = =
*/
2023-03-18 11:14:40 +00:00
static void BuildSurfaceDisplayList ( msurface_t * fa )
2010-02-15 23:26:55 +00:00
{
int i , lindex , lnumverts ;
medge_t * pedges , * r_pedge ;
float * vec ;
2023-07-25 14:08:00 +00:00
float s , t , s0 , t0 ;
2010-02-15 23:26:55 +00:00
glpoly_t * poly ;
// reconstruct the polygon
pedges = currentmodel - > edges ;
lnumverts = fa - > numedges ;
//
// draw texture
//
host_cmd.c, console.c, gl_draw.c, image.c, gl_model.c, r_sprite.c, cl_parse.c,
gl_warp.c, host.c, gl_mesh.c, gl_sky.c, gl_texmgr.c, cvar.c, sv_main.c, cvar.h,
gl_screen.c, r_brush.c, gl_vidsdl.c, zone.c, cl_main.c, cmd.c, snd_dma.c,
snd_mem.c, common.c, sv_phys.c: Added explicit casts to eliminate -Wc++-compat
warnings.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@170 af15c1b1-3010-417e-b628-4374ebc0bcbd
2010-05-31 07:42:36 +00:00
poly = ( glpoly_t * ) Hunk_Alloc ( sizeof ( glpoly_t ) + ( lnumverts - 4 ) * VERTEXSIZE * sizeof ( float ) ) ;
2010-02-15 23:26:55 +00:00
poly - > next = fa - > polys ;
fa - > polys = poly ;
poly - > numverts = lnumverts ;
2023-03-18 11:14:40 +00:00
if ( ( fa - > flags & SURF_DRAWTURB ) & & r_brokenturbbias . value )
2022-08-07 10:31:18 +00:00
{
// match Mod_PolyForUnlitSurface
s0 = t0 = 0.f ;
}
else
{
s0 = fa - > texinfo - > vecs [ 0 ] [ 3 ] ;
t0 = fa - > texinfo - > vecs [ 1 ] [ 3 ] ;
}
2010-02-15 23:26:55 +00:00
for ( i = 0 ; i < lnumverts ; i + + )
{
lindex = currentmodel - > surfedges [ fa - > firstedge + i ] ;
if ( lindex > 0 )
{
r_pedge = & pedges [ lindex ] ;
vec = r_pcurrentvertbase [ r_pedge - > v [ 0 ] ] . position ;
}
else
{
r_pedge = & pedges [ - lindex ] ;
vec = r_pcurrentvertbase [ r_pedge - > v [ 1 ] ] . position ;
}
2022-08-07 10:31:18 +00:00
s = DotProduct ( vec , fa - > texinfo - > vecs [ 0 ] ) + s0 ;
2010-02-15 23:26:55 +00:00
s / = fa - > texinfo - > texture - > width ;
2022-08-07 10:31:18 +00:00
t = DotProduct ( vec , fa - > texinfo - > vecs [ 1 ] ) + t0 ;
2010-02-15 23:26:55 +00:00
t / = fa - > texinfo - > texture - > height ;
VectorCopy ( vec , poly - > verts [ i ] ) ;
poly - > verts [ i ] [ 3 ] = s ;
poly - > verts [ i ] [ 4 ] = t ;
2021-09-02 17:50:50 +00:00
// Q64 RERELEASE texture shift
if ( fa - > texinfo - > texture - > shift > 0 )
{
poly - > verts [ i ] [ 3 ] / = ( 2 * fa - > texinfo - > texture - > shift ) ;
poly - > verts [ i ] [ 4 ] / = ( 2 * fa - > texinfo - > texture - > shift ) ;
}
2010-02-15 23:26:55 +00:00
//
// lightmap texture coordinates
//
2024-02-25 05:29:21 +00:00
s = DotProduct ( vec , fa - > lmvecs [ 0 ] ) + fa - > lmvecs [ 0 ] [ 3 ] + 0.5 ;
2023-11-02 23:18:42 +00:00
s + = fa - > light_s ;
s / = LMBLOCK_WIDTH ;
2024-02-25 05:29:21 +00:00
t = DotProduct ( vec , fa - > lmvecs [ 1 ] ) + fa - > lmvecs [ 1 ] [ 3 ] + 0.5 ;
2023-11-02 23:18:42 +00:00
t + = fa - > light_t ;
t / = LMBLOCK_HEIGHT ;
2010-02-15 23:26:55 +00:00
poly - > verts [ i ] [ 5 ] = s ;
poly - > verts [ i ] [ 6 ] = t ;
}
//johnfitz -- removed gl_keeptjunctions code
poly - > numverts = lnumverts ;
2021-11-12 02:31:34 +00:00
//oldwater is lame. subdivide it now.
if ( ( fa - > flags & SURF_DRAWTURB ) & & ! gl_glsl_water_able )
GL_SubdivideSurface ( fa ) ;
2010-02-15 23:26:55 +00:00
}
2020-09-03 10:39:38 +00:00
/*
Makes sure the model is good to go .
*/
void GL_BuildModel ( qmodel_t * m )
{
int i ;
if ( m - > name [ 0 ] = = ' * ' )
return ;
r_pcurrentvertbase = m - > vertexes ;
currentmodel = m ;
for ( i = 0 ; i < m - > numsurfaces ; i + + )
{
//johnfitz -- rewritten to use SURF_DRAWTILED instead of the sky/water flags
GL_CreateSurfaceLightmap ( m , m - > surfaces + i ) ;
BuildSurfaceDisplayList ( m - > surfaces + i ) ;
//johnfitz
}
// GL_BuildBModelVertexBuffer();
}
2010-02-15 23:26:55 +00:00
/*
= = = = = = = = = = = = = = = = = =
GL_BuildLightmaps - - called at level load time
Builds the lightmap texture
with all the surfaces from all brush models
= = = = = = = = = = = = = = = = = =
*/
void GL_BuildLightmaps ( void )
{
2019-09-18 09:17:24 +00:00
char name [ 24 ] ;
2010-02-15 23:26:55 +00:00
int i , j ;
2019-09-12 06:49:35 +00:00
struct lightmap_s * lm ;
2012-05-30 08:56:06 +00:00
qmodel_t * m ;
2010-02-15 23:26:55 +00:00
2024-03-01 08:09:56 +00:00
RSceneCache_Shutdown ( ) ; //make sure there's nothing poking them off-thread.
2010-02-15 23:26:55 +00:00
r_framecount = 1 ; // no dlightcache
2019-09-12 06:49:35 +00:00
//Spike -- wipe out all the lightmap data (johnfitz -- the gltexture objects were already freed by Mod_ClearAll)
for ( i = 0 ; i < lightmap_count ; i + + )
2021-07-13 05:20:09 +00:00
{
2021-08-31 05:43:13 +00:00
if ( lightmaps [ i ] . texture )
TexMgr_FreeTexture ( lightmaps [ i ] . texture ) ;
2024-03-01 08:09:56 +00:00
if ( lightmaps [ i ] . pbohandle )
{
GL_BindBufferFunc ( GL_PIXEL_UNPACK_BUFFER_ARB , lightmaps [ i ] . pbohandle ) ;
GL_UnmapBufferFunc ( GL_PIXEL_UNPACK_BUFFER_ARB ) ;
GL_BindBufferFunc ( GL_PIXEL_UNPACK_BUFFER_ARB , 0 ) ;
GL_DeleteBuffersFunc ( 1 , & lightmaps [ i ] . pbohandle ) ;
}
else
free ( lightmaps [ i ] . pbodata ) ;
2021-07-13 05:20:09 +00:00
}
2021-06-23 01:37:10 +00:00
free ( lightmaps ) ;
lightmaps = NULL ;
2019-09-12 06:49:35 +00:00
last_lightmap_allocated = 0 ;
lightmap_count = 0 ;
2024-03-01 08:09:56 +00:00
allocated = realloc ( allocated , sizeof ( * allocated ) * LMBLOCK_WIDTH ) ;
2010-02-15 23:26:55 +00:00
2023-06-29 15:40:18 +00:00
if ( gl_texture_e5bgr9 ) // && cl.worldmodel && (cl.worldmodel->flags&MOD_HDRLIGHTING))
gl_lightmap_format = GL_RGB9_E5 ; //requires gl3, allowing for hdr lighting.
else
gl_lightmap_format = GL_RGBA ; //FIXME: hardcoded for now!
2010-02-15 23:26:55 +00:00
switch ( gl_lightmap_format )
{
2023-06-29 15:40:18 +00:00
case GL_RGB9_E5 :
lightmap_bytes = 4 ;
break ;
2013-02-20 06:01:10 +00:00
case GL_RGBA :
lightmap_bytes = 4 ;
break ;
case GL_BGRA :
lightmap_bytes = 4 ;
2010-02-15 23:26:55 +00:00
break ;
default :
Sys_Error ( " GL_BuildLightmaps: bad lightmap format " ) ;
}
for ( j = 1 ; j < MAX_MODELS ; j + + )
{
m = cl . model_precache [ j ] ;
if ( ! m )
2021-07-13 05:20:09 +00:00
continue ;
2020-09-03 10:39:38 +00:00
GL_BuildModel ( m ) ;
}
for ( j = 1 ; j < MAX_MODELS ; j + + )
{
m = cl . model_precache_csqc [ j ] ;
if ( ! m )
break ;
GL_BuildModel ( m ) ;
2010-02-15 23:26:55 +00:00
}
//
// upload all lightmaps that were filled
//
2019-09-12 06:49:35 +00:00
for ( i = 0 ; i < lightmap_count ; i + + )
2010-02-15 23:26:55 +00:00
{
2021-06-23 01:37:10 +00:00
lm = & lightmaps [ i ] ;
2019-09-12 06:49:35 +00:00
lm - > modified = false ;
lm - > rectchange . l = LMBLOCK_WIDTH ;
lm - > rectchange . t = LMBLOCK_HEIGHT ;
lm - > rectchange . w = 0 ;
lm - > rectchange . h = 0 ;
2010-02-15 23:26:55 +00:00
//johnfitz -- use texture manager
2019-09-18 09:17:24 +00:00
sprintf ( name , " lightmap%07i " , i ) ;
2024-03-01 08:09:56 +00:00
if ( lm - > pbohandle )
{
GL_BindBufferFunc ( GL_PIXEL_UNPACK_BUFFER_ARB , lm - > pbohandle ) ;
lm - > texture = TexMgr_LoadImage ( NULL , name , LMBLOCK_WIDTH , LMBLOCK_HEIGHT ,
SRC_LIGHTMAP , NULL , " " , ( src_offset_t ) lm - > pbodata , TEXPREF_LINEAR | TEXPREF_NOPICMIP | TEXPREF_PERSIST ) ;
GL_BindBufferFunc ( GL_PIXEL_UNPACK_BUFFER_ARB , 0 ) ;
}
else
{
lm - > texture = TexMgr_LoadImage ( NULL , name , LMBLOCK_WIDTH , LMBLOCK_HEIGHT ,
SRC_LIGHTMAP , lm - > pbodata , " " , ( src_offset_t ) lm - > pbodata , TEXPREF_LINEAR | TEXPREF_NOPICMIP | TEXPREF_PERSIST ) ;
}
2010-02-15 23:26:55 +00:00
//johnfitz
}
//johnfitz -- warn about exceeding old limits
2019-09-18 09:17:24 +00:00
//GLQuake limit was 64 textures of 128x128. Estimate how many 128x128 textures we would need
//given that we are using lightmap_count of LMBLOCK_WIDTH x LMBLOCK_HEIGHT
i = lightmap_count * ( ( LMBLOCK_WIDTH / 128 ) * ( LMBLOCK_HEIGHT / 128 ) ) ;
if ( i > 64 )
Con_DWarning ( " %i lightmaps exceeds standard limit of 64. \n " , i ) ;
2010-02-15 23:26:55 +00:00
//johnfitz
}
Load world and brush models into a VBO, and draw it in batches in R_DrawTextureChains_Multitexture. Uses the same immediate mode code as before if VBOs are not available, or if "-novbo" used at the command line. I only touched R_DrawTextureChains_Multitexture because it's usually the main bottleneck aside from alias model rendering.
This seems to help fps a fair bit on maps with a lot of world polys like jam2_tronyn. Tried on a few computers with intel and nvidia gpus, windows, mac os, linux, and there's always at least some fps improvement. Best case was 70fps -> 96fps on jam2_tronyn, on OS X + nvidia 650gt.
Interested to hear how this works for amd gpu's, just do a timedemo with and without "-novbo".
Only downside is I had to disable the fast path in Vid_Toggle_f() because at least with SDL1, the vbo no longer works after a toggle. So as a result, fullscreen toggles with alt-enter are slightly slower.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@1018 af15c1b1-3010-417e-b628-4374ebc0bcbd
2014-09-11 04:55:16 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
VBO support
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
Alias model rendering fast-path using OpenGL 2.
In GL_MakeAliasModelDisplayLists, after saving the standerd triangle strips and fans onto the hunk, if the system is GL2 capable, we also save a second version of the mdl on the hunk designed to be loaded into a VBO (GL_MakeAliasModelDisplayLists_VBO). In R_NewMap, and on video mode changes, we call GLMesh_LoadVertexBuffers which loops over all precached mdl's and loads the data into a pair of VBO's (vertices and vertex indices).
Finally, in R_DrawAliasModel, assuming no rendering options are disabling the fast-path (r_drawflat 1, r_lightmap 1, or r_fullbright 1 would disable it), we call GL_DrawAliasFrame_GLSL, which sets up all of the bindings and draws the (possibly lerped) mdl in one glDrawElements call.
Special thanks to MH for some of the code from RMQEngine and the general concept.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@1151 af15c1b1-3010-417e-b628-4374ebc0bcbd
2015-01-20 18:59:15 +00:00
GLuint gl_bmodel_vbo = 0 ;
Load world and brush models into a VBO, and draw it in batches in R_DrawTextureChains_Multitexture. Uses the same immediate mode code as before if VBOs are not available, or if "-novbo" used at the command line. I only touched R_DrawTextureChains_Multitexture because it's usually the main bottleneck aside from alias model rendering.
This seems to help fps a fair bit on maps with a lot of world polys like jam2_tronyn. Tried on a few computers with intel and nvidia gpus, windows, mac os, linux, and there's always at least some fps improvement. Best case was 70fps -> 96fps on jam2_tronyn, on OS X + nvidia 650gt.
Interested to hear how this works for amd gpu's, just do a timedemo with and without "-novbo".
Only downside is I had to disable the fast path in Vid_Toggle_f() because at least with SDL1, the vbo no longer works after a toggle. So as a result, fullscreen toggles with alt-enter are slightly slower.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@1018 af15c1b1-3010-417e-b628-4374ebc0bcbd
2014-09-11 04:55:16 +00:00
2015-09-20 20:10:49 +00:00
void GL_DeleteBModelVertexBuffer ( void )
{
if ( ! ( gl_vbo_able & & gl_mtexable & & gl_max_texture_units > = 3 ) )
return ;
GL_DeleteBuffersFunc ( 1 , & gl_bmodel_vbo ) ;
gl_bmodel_vbo = 0 ;
GL_ClearBufferBindings ( ) ;
}
Load world and brush models into a VBO, and draw it in batches in R_DrawTextureChains_Multitexture. Uses the same immediate mode code as before if VBOs are not available, or if "-novbo" used at the command line. I only touched R_DrawTextureChains_Multitexture because it's usually the main bottleneck aside from alias model rendering.
This seems to help fps a fair bit on maps with a lot of world polys like jam2_tronyn. Tried on a few computers with intel and nvidia gpus, windows, mac os, linux, and there's always at least some fps improvement. Best case was 70fps -> 96fps on jam2_tronyn, on OS X + nvidia 650gt.
Interested to hear how this works for amd gpu's, just do a timedemo with and without "-novbo".
Only downside is I had to disable the fast path in Vid_Toggle_f() because at least with SDL1, the vbo no longer works after a toggle. So as a result, fullscreen toggles with alt-enter are slightly slower.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@1018 af15c1b1-3010-417e-b628-4374ebc0bcbd
2014-09-11 04:55:16 +00:00
/*
= = = = = = = = = = = = = = = = = =
2015-09-20 20:10:49 +00:00
GL_BuildBModelVertexBuffer
Load world and brush models into a VBO, and draw it in batches in R_DrawTextureChains_Multitexture. Uses the same immediate mode code as before if VBOs are not available, or if "-novbo" used at the command line. I only touched R_DrawTextureChains_Multitexture because it's usually the main bottleneck aside from alias model rendering.
This seems to help fps a fair bit on maps with a lot of world polys like jam2_tronyn. Tried on a few computers with intel and nvidia gpus, windows, mac os, linux, and there's always at least some fps improvement. Best case was 70fps -> 96fps on jam2_tronyn, on OS X + nvidia 650gt.
Interested to hear how this works for amd gpu's, just do a timedemo with and without "-novbo".
Only downside is I had to disable the fast path in Vid_Toggle_f() because at least with SDL1, the vbo no longer works after a toggle. So as a result, fullscreen toggles with alt-enter are slightly slower.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@1018 af15c1b1-3010-417e-b628-4374ebc0bcbd
2014-09-11 04:55:16 +00:00
Deletes gl_bmodel_vbo if it already exists , then rebuilds it with all
surfaces from world + all brush models
= = = = = = = = = = = = = = = = = =
*/
2015-09-20 20:10:49 +00:00
void GL_BuildBModelVertexBuffer ( void )
Load world and brush models into a VBO, and draw it in batches in R_DrawTextureChains_Multitexture. Uses the same immediate mode code as before if VBOs are not available, or if "-novbo" used at the command line. I only touched R_DrawTextureChains_Multitexture because it's usually the main bottleneck aside from alias model rendering.
This seems to help fps a fair bit on maps with a lot of world polys like jam2_tronyn. Tried on a few computers with intel and nvidia gpus, windows, mac os, linux, and there's always at least some fps improvement. Best case was 70fps -> 96fps on jam2_tronyn, on OS X + nvidia 650gt.
Interested to hear how this works for amd gpu's, just do a timedemo with and without "-novbo".
Only downside is I had to disable the fast path in Vid_Toggle_f() because at least with SDL1, the vbo no longer works after a toggle. So as a result, fullscreen toggles with alt-enter are slightly slower.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@1018 af15c1b1-3010-417e-b628-4374ebc0bcbd
2014-09-11 04:55:16 +00:00
{
unsigned int numverts , varray_bytes , varray_index ;
int i , j ;
qmodel_t * m ;
float * varray ;
2014-09-20 01:08:13 +00:00
if ( ! ( gl_vbo_able & & gl_mtexable & & gl_max_texture_units > = 3 ) )
Load world and brush models into a VBO, and draw it in batches in R_DrawTextureChains_Multitexture. Uses the same immediate mode code as before if VBOs are not available, or if "-novbo" used at the command line. I only touched R_DrawTextureChains_Multitexture because it's usually the main bottleneck aside from alias model rendering.
This seems to help fps a fair bit on maps with a lot of world polys like jam2_tronyn. Tried on a few computers with intel and nvidia gpus, windows, mac os, linux, and there's always at least some fps improvement. Best case was 70fps -> 96fps on jam2_tronyn, on OS X + nvidia 650gt.
Interested to hear how this works for amd gpu's, just do a timedemo with and without "-novbo".
Only downside is I had to disable the fast path in Vid_Toggle_f() because at least with SDL1, the vbo no longer works after a toggle. So as a result, fullscreen toggles with alt-enter are slightly slower.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@1018 af15c1b1-3010-417e-b628-4374ebc0bcbd
2014-09-11 04:55:16 +00:00
return ;
// ask GL for a name for our VBO
GL_DeleteBuffersFunc ( 1 , & gl_bmodel_vbo ) ;
GL_GenBuffersFunc ( 1 , & gl_bmodel_vbo ) ;
// count all verts in all models
numverts = 0 ;
for ( j = 1 ; j < MAX_MODELS ; j + + )
{
m = cl . model_precache [ j ] ;
if ( ! m | | m - > name [ 0 ] = = ' * ' | | m - > type ! = mod_brush )
continue ;
for ( i = 0 ; i < m - > numsurfaces ; i + + )
{
numverts + = m - > surfaces [ i ] . numedges ;
}
}
2020-09-03 10:39:38 +00:00
for ( j = 1 ; j < MAX_MODELS ; j + + )
{
m = cl . model_precache_csqc [ j ] ;
if ( ! m | | m - > name [ 0 ] = = ' * ' | | m - > type ! = mod_brush )
continue ;
for ( i = 0 ; i < m - > numsurfaces ; i + + )
{
numverts + = m - > surfaces [ i ] . numedges ;
}
}
Load world and brush models into a VBO, and draw it in batches in R_DrawTextureChains_Multitexture. Uses the same immediate mode code as before if VBOs are not available, or if "-novbo" used at the command line. I only touched R_DrawTextureChains_Multitexture because it's usually the main bottleneck aside from alias model rendering.
This seems to help fps a fair bit on maps with a lot of world polys like jam2_tronyn. Tried on a few computers with intel and nvidia gpus, windows, mac os, linux, and there's always at least some fps improvement. Best case was 70fps -> 96fps on jam2_tronyn, on OS X + nvidia 650gt.
Interested to hear how this works for amd gpu's, just do a timedemo with and without "-novbo".
Only downside is I had to disable the fast path in Vid_Toggle_f() because at least with SDL1, the vbo no longer works after a toggle. So as a result, fullscreen toggles with alt-enter are slightly slower.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@1018 af15c1b1-3010-417e-b628-4374ebc0bcbd
2014-09-11 04:55:16 +00:00
// build vertex array
varray_bytes = VERTEXSIZE * sizeof ( float ) * numverts ;
varray = ( float * ) malloc ( varray_bytes ) ;
varray_index = 0 ;
for ( j = 1 ; j < MAX_MODELS ; j + + )
{
m = cl . model_precache [ j ] ;
if ( ! m | | m - > name [ 0 ] = = ' * ' | | m - > type ! = mod_brush )
continue ;
for ( i = 0 ; i < m - > numsurfaces ; i + + )
{
msurface_t * s = & m - > surfaces [ i ] ;
s - > vbo_firstvert = varray_index ;
memcpy ( & varray [ VERTEXSIZE * varray_index ] , s - > polys - > verts , VERTEXSIZE * sizeof ( float ) * s - > numedges ) ;
varray_index + = s - > numedges ;
}
}
2020-09-03 10:39:38 +00:00
for ( j = 1 ; j < MAX_MODELS ; j + + )
{
m = cl . model_precache_csqc [ j ] ;
if ( ! m | | m - > name [ 0 ] = = ' * ' | | m - > type ! = mod_brush )
continue ;
for ( i = 0 ; i < m - > numsurfaces ; i + + )
{
msurface_t * s = & m - > surfaces [ i ] ;
s - > vbo_firstvert = varray_index ;
memcpy ( & varray [ VERTEXSIZE * varray_index ] , s - > polys - > verts , VERTEXSIZE * sizeof ( float ) * s - > numedges ) ;
varray_index + = s - > numedges ;
}
}
Load world and brush models into a VBO, and draw it in batches in R_DrawTextureChains_Multitexture. Uses the same immediate mode code as before if VBOs are not available, or if "-novbo" used at the command line. I only touched R_DrawTextureChains_Multitexture because it's usually the main bottleneck aside from alias model rendering.
This seems to help fps a fair bit on maps with a lot of world polys like jam2_tronyn. Tried on a few computers with intel and nvidia gpus, windows, mac os, linux, and there's always at least some fps improvement. Best case was 70fps -> 96fps on jam2_tronyn, on OS X + nvidia 650gt.
Interested to hear how this works for amd gpu's, just do a timedemo with and without "-novbo".
Only downside is I had to disable the fast path in Vid_Toggle_f() because at least with SDL1, the vbo no longer works after a toggle. So as a result, fullscreen toggles with alt-enter are slightly slower.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@1018 af15c1b1-3010-417e-b628-4374ebc0bcbd
2014-09-11 04:55:16 +00:00
// upload to GPU
GL_BindBufferFunc ( GL_ARRAY_BUFFER , gl_bmodel_vbo ) ;
GL_BufferDataFunc ( GL_ARRAY_BUFFER , varray_bytes , varray , GL_STATIC_DRAW ) ;
free ( varray ) ;
Alias model rendering fast-path using OpenGL 2.
In GL_MakeAliasModelDisplayLists, after saving the standerd triangle strips and fans onto the hunk, if the system is GL2 capable, we also save a second version of the mdl on the hunk designed to be loaded into a VBO (GL_MakeAliasModelDisplayLists_VBO). In R_NewMap, and on video mode changes, we call GLMesh_LoadVertexBuffers which loops over all precached mdl's and loads the data into a pair of VBO's (vertices and vertex indices).
Finally, in R_DrawAliasModel, assuming no rendering options are disabling the fast-path (r_drawflat 1, r_lightmap 1, or r_fullbright 1 would disable it), we call GL_DrawAliasFrame_GLSL, which sets up all of the bindings and draws the (possibly lerped) mdl in one glDrawElements call.
Special thanks to MH for some of the code from RMQEngine and the general concept.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@1151 af15c1b1-3010-417e-b628-4374ebc0bcbd
2015-01-20 18:59:15 +00:00
// invalidate the cached bindings
GL_ClearBufferBindings ( ) ;
Load world and brush models into a VBO, and draw it in batches in R_DrawTextureChains_Multitexture. Uses the same immediate mode code as before if VBOs are not available, or if "-novbo" used at the command line. I only touched R_DrawTextureChains_Multitexture because it's usually the main bottleneck aside from alias model rendering.
This seems to help fps a fair bit on maps with a lot of world polys like jam2_tronyn. Tried on a few computers with intel and nvidia gpus, windows, mac os, linux, and there's always at least some fps improvement. Best case was 70fps -> 96fps on jam2_tronyn, on OS X + nvidia 650gt.
Interested to hear how this works for amd gpu's, just do a timedemo with and without "-novbo".
Only downside is I had to disable the fast path in Vid_Toggle_f() because at least with SDL1, the vbo no longer works after a toggle. So as a result, fullscreen toggles with alt-enter are slightly slower.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@1018 af15c1b1-3010-417e-b628-4374ebc0bcbd
2014-09-11 04:55:16 +00:00
}
2010-02-15 23:26:55 +00:00
/*
= = = = = = = = = = = = = = =
R_AddDynamicLights
= = = = = = = = = = = = = = =
*/
2024-03-01 08:09:56 +00:00
static void R_AddDynamicLights ( msurface_t * surf , unsigned * blocklights , entity_t * currentent , dlight_t * lights )
2010-02-15 23:26:55 +00:00
{
int lnum ;
int sd , td ;
float dist , rad , minlight ;
vec3_t impact , local ;
int s , t ;
int i ;
int smax , tmax ;
//johnfitz -- lit support via lordhavoc
float cred , cgreen , cblue , brightness ;
unsigned * bl ;
//johnfitz
2018-05-25 10:54:33 +00:00
vec3_t lightofs ; //Spike: light surfaces based upon where they are now instead of their default position.
2010-02-15 23:26:55 +00:00
2023-11-02 23:18:42 +00:00
smax = surf - > extents [ 0 ] + 1 ;
tmax = surf - > extents [ 1 ] + 1 ;
2010-02-15 23:26:55 +00:00
for ( lnum = 0 ; lnum < MAX_DLIGHTS ; lnum + + )
{
2012-07-10 11:21:17 +00:00
if ( ! ( surf - > dlightbits [ lnum > > 5 ] & ( 1U < < ( lnum & 31 ) ) ) )
2010-02-15 23:26:55 +00:00
continue ; // not lit by this light
2024-03-01 08:09:56 +00:00
rad = lights [ lnum ] . radius ;
if ( currentent - > currentangles [ 0 ] | | currentent - > currentangles [ 1 ] | | currentent - > currentangles [ 2 ] )
{
vec3_t temp , axis [ 3 ] ;
VectorSubtract ( lights [ lnum ] . origin , currentent - > origin , temp ) ;
AngleVectors ( currentent - > currentangles , axis [ 0 ] , axis [ 1 ] , axis [ 2 ] ) ;
lightofs [ 0 ] = + DotProduct ( temp , axis [ 0 ] ) ;
lightofs [ 1 ] = - DotProduct ( temp , axis [ 1 ] ) ;
lightofs [ 2 ] = + DotProduct ( temp , axis [ 2 ] ) ;
}
else
VectorSubtract ( lights [ lnum ] . origin , currentent - > origin , lightofs ) ;
2018-05-25 10:54:33 +00:00
dist = DotProduct ( lightofs , surf - > plane - > normal ) - surf - > plane - > dist ;
2010-02-15 23:26:55 +00:00
rad - = fabs ( dist ) ;
2024-03-01 08:09:56 +00:00
minlight = lights [ lnum ] . minlight ;
2010-02-15 23:26:55 +00:00
if ( rad < minlight )
continue ;
minlight = rad - minlight ;
for ( i = 0 ; i < 3 ; i + + )
{
2018-05-25 10:54:33 +00:00
impact [ i ] = lightofs [ i ] -
2010-02-15 23:26:55 +00:00
surf - > plane - > normal [ i ] * dist ;
}
2023-11-02 23:18:42 +00:00
local [ 0 ] = DotProduct ( impact , surf - > lmvecs [ 0 ] ) + surf - > lmvecs [ 0 ] [ 3 ] ;
local [ 1 ] = DotProduct ( impact , surf - > lmvecs [ 1 ] ) + surf - > lmvecs [ 1 ] [ 3 ] ;
2010-02-15 23:26:55 +00:00
//johnfitz -- lit support via lordhavoc
bl = blocklights ;
2024-03-01 08:09:56 +00:00
cred = lights [ lnum ] . color [ 0 ] * 256.0f ;
cgreen = lights [ lnum ] . color [ 1 ] * 256.0f ;
cblue = lights [ lnum ] . color [ 2 ] * 256.0f ;
2010-02-15 23:26:55 +00:00
//johnfitz
for ( t = 0 ; t < tmax ; t + + )
{
2023-11-02 23:18:42 +00:00
td = ( local [ 1 ] - t ) * surf - > lmvecscale [ 1 ] ;
2010-02-15 23:26:55 +00:00
if ( td < 0 )
td = - td ;
for ( s = 0 ; s < smax ; s + + )
{
2023-11-02 23:18:42 +00:00
sd = ( local [ 0 ] - s ) * surf - > lmvecscale [ 0 ] ;
2010-02-15 23:26:55 +00:00
if ( sd < 0 )
sd = - sd ;
if ( sd > td )
dist = sd + ( td > > 1 ) ;
else
dist = td + ( sd > > 1 ) ;
if ( dist < minlight )
//johnfitz -- lit support via lordhavoc
{
brightness = rad - dist ;
bl [ 0 ] + = ( int ) ( brightness * cred ) ;
bl [ 1 ] + = ( int ) ( brightness * cgreen ) ;
bl [ 2 ] + = ( int ) ( brightness * cblue ) ;
}
bl + = 3 ;
//johnfitz
}
}
}
}
/*
= = = = = = = = = = = = = = =
R_BuildLightMap - - johnfitz - - revised for lit support via lordhavoc
Combine and scale multiple lightmaps into the 8.8 format in blocklights
= = = = = = = = = = = = = = =
*/
2024-03-01 08:09:56 +00:00
void R_BuildLightMap ( qmodel_t * model , msurface_t * surf , byte * dest , int stride , entity_t * currentent , int framecount , dlight_t * lights )
2010-02-15 23:26:55 +00:00
{
int smax , tmax ;
2013-02-20 06:01:10 +00:00
int r , g , b ;
2010-02-15 23:26:55 +00:00
int i , j , size ;
unsigned scale ;
int maps ;
unsigned * bl ;
2024-03-01 08:09:56 +00:00
unsigned * blocklights ; //moved this to stack, so workers working on the worldmodel won't fight the main thread processing the submodels.
2010-02-15 23:26:55 +00:00
2024-03-01 08:09:56 +00:00
surf - > cached_dlight = ( surf - > dlightframe = = framecount ) ;
2010-02-15 23:26:55 +00:00
2023-11-02 23:18:42 +00:00
smax = surf - > extents [ 0 ] + 1 ;
tmax = surf - > extents [ 1 ] + 1 ;
2010-02-15 23:26:55 +00:00
size = smax * tmax ;
2024-03-01 08:09:56 +00:00
blocklights = alloca ( size * 3 * sizeof ( * blocklights ) ) ; //alloca is unsafe, but at least we memset it... should probably memset in stack order in the hopes of getting a standard stack-overflow-segfault instead of poking completely outside what the system thinks is the stack in the case of massive surfs...
2017-09-17 02:12:53 +00:00
if ( model - > lightdata )
2010-02-15 23:26:55 +00:00
{
// clear to no light
memset ( & blocklights [ 0 ] , 0 , size * 3 * sizeof ( unsigned int ) ) ; //johnfitz -- lit support via lordhavoc
// add all the lightmaps
2023-06-29 15:40:18 +00:00
if ( ! surf - > samples )
; //unlit surfaces are black... FIXME: unless lit water (could be new-qbsp + old-light)...
else if ( model - > flags & MOD_HDRLIGHTING )
{
uint32_t * lightmap = surf - > samples ;
for ( maps = 0 ; maps < MAXLIGHTMAPS & & surf - > styles [ maps ] ! = INVALID_LIGHTSTYLE ;
maps + + )
{
scale = d_lightstylevalue [ surf - > styles [ maps ] ] ;
surf - > cached_light [ maps ] = scale ; // 8.8 fraction
bl = blocklights ; //it sucks that blocklights is an int array. we can still massively overbright though, just not underbright quite as accurately (still quite a bit more than rgb8 precision there).
for ( i = 0 ; i < size ; i + + )
{
static const float rgb9e5tab [ 32 ] = { //multipliers for the 9-bit mantissa, according to the biased mantissa
//aka: pow(2, biasedexponent - bias-bits) where bias is 15 and bits is 9
1.0 / ( 1 < < 24 ) , 1.0 / ( 1 < < 23 ) , 1.0 / ( 1 < < 22 ) , 1.0 / ( 1 < < 21 ) , 1.0 / ( 1 < < 20 ) , 1.0 / ( 1 < < 19 ) , 1.0 / ( 1 < < 18 ) , 1.0 / ( 1 < < 17 ) ,
1.0 / ( 1 < < 16 ) , 1.0 / ( 1 < < 15 ) , 1.0 / ( 1 < < 14 ) , 1.0 / ( 1 < < 13 ) , 1.0 / ( 1 < < 12 ) , 1.0 / ( 1 < < 11 ) , 1.0 / ( 1 < < 10 ) , 1.0 / ( 1 < < 9 ) ,
1.0 / ( 1 < < 8 ) , 1.0 / ( 1 < < 7 ) , 1.0 / ( 1 < < 6 ) , 1.0 / ( 1 < < 5 ) , 1.0 / ( 1 < < 4 ) , 1.0 / ( 1 < < 3 ) , 1.0 / ( 1 < < 2 ) , 1.0 / ( 1 < < 1 ) ,
1.0 , 1.0 * ( 1 < < 1 ) , 1.0 * ( 1 < < 2 ) , 1.0 * ( 1 < < 3 ) , 1.0 * ( 1 < < 4 ) , 1.0 * ( 1 < < 5 ) , 1.0 * ( 1 < < 6 ) , 1.0 * ( 1 < < 7 ) ,
} ;
uint32_t e5bgr9 = * lightmap + + ;
float e = rgb9e5tab [ e5bgr9 > > 27 ] * ( 1 < < 7 ) * scale ; //we're converting to a scale that holds overbrights, so 1->128, its 2->255ish
* bl + + + = e * ( ( e5bgr9 > > 0 ) & 0x1ff ) ; //red
* bl + + + = e * ( ( e5bgr9 > > 9 ) & 0x1ff ) ; //green
* bl + + + = e * ( ( e5bgr9 > > 18 ) & 0x1ff ) ; //blue
}
}
}
else
2016-04-28 21:47:12 +00:00
{
2023-06-29 15:40:18 +00:00
byte * lightmap = surf - > samples ;
2019-09-10 14:41:11 +00:00
for ( maps = 0 ; maps < MAXLIGHTMAPS & & surf - > styles [ maps ] ! = INVALID_LIGHTSTYLE ;
2010-02-15 23:26:55 +00:00
maps + + )
{
scale = d_lightstylevalue [ surf - > styles [ maps ] ] ;
surf - > cached_light [ maps ] = scale ; // 8.8 fraction
//johnfitz -- lit support via lordhavoc
bl = blocklights ;
for ( i = 0 ; i < size ; i + + )
{
* bl + + + = * lightmap + + * scale ;
* bl + + + = * lightmap + + * scale ;
* bl + + + = * lightmap + + * scale ;
}
//johnfitz
}
2016-04-28 21:47:12 +00:00
}
2010-02-15 23:26:55 +00:00
// add all the dynamic lights
2024-03-01 08:09:56 +00:00
if ( surf - > dlightframe = = framecount )
R_AddDynamicLights ( surf , blocklights , currentent , lights ) ;
2010-02-15 23:26:55 +00:00
}
else
{
// set to full bright if no light data
2024-03-01 08:09:56 +00:00
for ( i = 0 ; i < size ; i + + )
blocklights [ i ] = 0xffff ; //don't use memset, it oversaturates FAR too much with hdr...
2010-02-15 23:26:55 +00:00
}
// bound, invert, and shift
chase.c, cl_input.c, cl_parse.c, client.h, common.c, common.h, console.h,
cvar.h, draw.h, gl_draw.c, gl_fog.c, gl_mesh.c, gl_model.c, gl_model.h,
gl_rmain.c, gl_rmisc.c, gl_screen.c, gl_sky.c, gl_texmgr.c, glquake.h,
host.c, keys.c, keys.h, main.c, menu.c, menu.h, pr_cmds.c, quakedef.h,
r_alias.c, r_brush.c, r_part.c, r_sprite.c, r_world.c, sbar.c, sbar.h,
screen.h, snd_dma.c, snd_mem.c, snd_mix.c, sv_main.c, sys_sdl.c, vid.h,
view.h, world.c, world.h: Loads of warning fixes about missing function
prototypes, missing parens around &, missing braces leading to ambiguous
else statements and unused and uninitialized variables. There are still a
couple of unitialised variables here and there, but not much. The warnings
about strict aliasing violations need taking care of.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@21 af15c1b1-3010-417e-b628-4374ebc0bcbd
2010-02-16 12:01:07 +00:00
// store:
2010-02-15 23:26:55 +00:00
switch ( gl_lightmap_format )
{
2023-06-29 15:40:18 +00:00
case GL_RGB9_E5 :
{
int e ;
float m ;
float scale , identity = 1u < < ( ( gl_overbright . value ? 8 : 7 ) + 8 ) ; //overbright is redundant with this, but its easier to leave it than conditionally block it.
stride - = smax * 4 ;
bl = blocklights ;
for ( i = 0 ; i < tmax ; i + + , dest + = stride )
{
for ( j = 0 ; j < smax ; j + + )
{
e = 0 ;
m = q_max ( q_max ( bl [ 0 ] , bl [ 1 ] ) , bl [ 2 ] ) / identity ;
if ( m > = 0.5 )
{ //positive exponent
while ( m > = ( 1 < < ( e ) ) & & e < 30 - 15 ) //don't do nans.
e + + ;
}
else
{ //negative exponent...
while ( m < 1 / ( 1 < < - e ) & & e > - 15 ) //don't do denormals.
e - - ;
}
scale = pow ( 2 , e - 9 ) ;
scale * = identity ;
* ( unsigned int * ) dest = ( ( e + 15 ) < < 27 ) |
CLAMP ( 0 , ( int ) ( bl [ 0 ] / scale + 0.5 ) , 0x1ff ) < < 0 |
CLAMP ( 0 , ( int ) ( bl [ 1 ] / scale + 0.5 ) , 0x1ff ) < < 9 |
CLAMP ( 0 , ( int ) ( bl [ 2 ] / scale + 0.5 ) , 0x1ff ) < < 18 ;
bl + = 3 ;
dest + = 4 ;
}
}
}
break ;
2013-02-20 06:01:10 +00:00
case GL_RGBA :
stride - = smax * 4 ;
bl = blocklights ;
for ( i = 0 ; i < tmax ; i + + , dest + = stride )
{
for ( j = 0 ; j < smax ; j + + )
{
if ( gl_overbright . value )
{
r = * bl + + > > 8 ;
g = * bl + + > > 8 ;
b = * bl + + > > 8 ;
}
else
{
r = * bl + + > > 7 ;
g = * bl + + > > 7 ;
b = * bl + + > > 7 ;
}
2016-04-28 21:47:12 +00:00
* dest + + = ( r > 255 ) ? 255 : r ;
* dest + + = ( g > 255 ) ? 255 : g ;
* dest + + = ( b > 255 ) ? 255 : b ;
2013-02-20 06:01:10 +00:00
* dest + + = 255 ;
}
}
break ;
case GL_BGRA :
stride - = smax * 4 ;
2010-02-15 23:26:55 +00:00
bl = blocklights ;
for ( i = 0 ; i < tmax ; i + + , dest + = stride )
{
for ( j = 0 ; j < smax ; j + + )
{
if ( gl_overbright . value )
{
2013-02-20 06:01:10 +00:00
r = * bl + + > > 8 ;
g = * bl + + > > 8 ;
b = * bl + + > > 8 ;
2010-02-15 23:26:55 +00:00
}
else
{
2013-02-20 06:01:10 +00:00
r = * bl + + > > 7 ;
g = * bl + + > > 7 ;
b = * bl + + > > 7 ;
2010-02-15 23:26:55 +00:00
}
2016-04-28 21:47:12 +00:00
* dest + + = ( b > 255 ) ? 255 : b ;
* dest + + = ( g > 255 ) ? 255 : g ;
* dest + + = ( r > 255 ) ? 255 : r ;
2013-02-20 06:01:10 +00:00
* dest + + = 255 ;
2010-02-15 23:26:55 +00:00
}
}
break ;
default :
Sys_Error ( " R_BuildLightMap: bad lightmap format " ) ;
}
}
/*
= = = = = = = = = = = = = = =
R_UploadLightmap - - johnfitz - - uploads the modified lightmap to opengl if necessary
assumes lightmap texture is already bound
= = = = = = = = = = = = = = =
*/
2014-07-12 07:01:58 +00:00
static void R_UploadLightmap ( int lmap )
2010-02-15 23:26:55 +00:00
{
2021-06-23 01:37:10 +00:00
struct lightmap_s * lm = & lightmaps [ lmap ] ;
2010-02-15 23:26:55 +00:00
2019-09-12 06:49:35 +00:00
if ( ! lm - > modified )
2010-02-15 23:26:55 +00:00
return ;
2019-09-12 06:49:35 +00:00
lm - > modified = false ;
2010-02-15 23:26:55 +00:00
2024-03-01 08:09:56 +00:00
if ( lm - > pbohandle )
{
GL_BindBufferFunc ( GL_PIXEL_UNPACK_BUFFER_ARB , lm - > pbohandle ) ;
if ( gl_lightmap_format = = GL_RGB9_E5 )
glTexSubImage2D ( GL_TEXTURE_2D , 0 , 0 , lm - > rectchange . t , LMBLOCK_WIDTH , lm - > rectchange . h , GL_RGB ,
GL_UNSIGNED_INT_5_9_9_9_REV , ( byte * ) NULL + lm - > rectchange . t * LMBLOCK_WIDTH * lightmap_bytes ) ;
else
glTexSubImage2D ( GL_TEXTURE_2D , 0 , 0 , lm - > rectchange . t , LMBLOCK_WIDTH , lm - > rectchange . h , gl_lightmap_format ,
GL_UNSIGNED_BYTE , ( byte * ) NULL + lm - > rectchange . t * LMBLOCK_WIDTH * lightmap_bytes ) ;
GL_BindBufferFunc ( GL_PIXEL_UNPACK_BUFFER_ARB , 0 ) ;
}
2023-06-29 15:40:18 +00:00
else
2024-03-01 08:09:56 +00:00
{
if ( gl_lightmap_format = = GL_RGB9_E5 )
glTexSubImage2D ( GL_TEXTURE_2D , 0 , 0 , lm - > rectchange . t , LMBLOCK_WIDTH , lm - > rectchange . h , GL_RGB ,
GL_UNSIGNED_INT_5_9_9_9_REV , lm - > pbodata + lm - > rectchange . t * LMBLOCK_WIDTH * lightmap_bytes ) ;
else
glTexSubImage2D ( GL_TEXTURE_2D , 0 , 0 , lm - > rectchange . t , LMBLOCK_WIDTH , lm - > rectchange . h , gl_lightmap_format ,
GL_UNSIGNED_BYTE , lm - > pbodata + lm - > rectchange . t * LMBLOCK_WIDTH * lightmap_bytes ) ;
}
2019-09-12 06:49:35 +00:00
lm - > rectchange . l = LMBLOCK_WIDTH ;
lm - > rectchange . t = LMBLOCK_HEIGHT ;
lm - > rectchange . h = 0 ;
lm - > rectchange . w = 0 ;
2010-02-15 23:26:55 +00:00
rs_dynamiclightmaps + + ;
}
2014-07-12 07:01:58 +00:00
void R_UploadLightmaps ( void )
{
int lmap ;
2021-07-13 05:20:09 +00:00
if ( lightmaps_latecached )
{
GL_BuildLightmaps ( ) ;
GL_BuildBModelVertexBuffer ( ) ;
lightmaps_latecached = false ;
}
2024-03-01 08:09:56 +00:00
if ( lightmaps_skipupdates )
return ;
2019-09-12 06:49:35 +00:00
for ( lmap = 0 ; lmap < lightmap_count ; lmap + + )
2014-07-12 07:01:58 +00:00
{
2021-06-23 01:37:10 +00:00
if ( ! lightmaps [ lmap ] . modified )
2014-07-12 07:01:58 +00:00
continue ;
2021-08-31 05:43:13 +00:00
if ( ! lightmaps [ lmap ] . texture )
2021-07-13 05:20:09 +00:00
{
char name [ 24 ] ;
sprintf ( name , " lightmap%07i " , lmap ) ;
2024-03-01 08:09:56 +00:00
if ( lightmaps [ lmap ] . pbohandle )
{
GL_BindBufferFunc ( GL_PIXEL_UNPACK_BUFFER_ARB , lightmaps [ lmap ] . pbohandle ) ;
lightmaps [ lmap ] . texture = TexMgr_LoadImage ( NULL , name , LMBLOCK_WIDTH , LMBLOCK_HEIGHT ,
SRC_LIGHTMAP , NULL , " " , ( src_offset_t ) lightmaps [ lmap ] . pbodata , TEXPREF_LINEAR | TEXPREF_NOPICMIP | TEXPREF_PERSIST ) ;
GL_BindBufferFunc ( GL_PIXEL_UNPACK_BUFFER_ARB , 0 ) ;
}
else
{
lightmaps [ lmap ] . texture = TexMgr_LoadImage ( NULL , name , LMBLOCK_WIDTH , LMBLOCK_HEIGHT ,
SRC_LIGHTMAP , lightmaps [ lmap ] . pbodata , " " , ( src_offset_t ) lightmaps [ lmap ] . pbodata , TEXPREF_LINEAR | TEXPREF_NOPICMIP | TEXPREF_PERSIST ) ;
}
2021-08-31 05:43:13 +00:00
lightmaps [ lmap ] . modified = false ;
lightmaps [ lmap ] . rectchange . l = LMBLOCK_WIDTH ;
lightmaps [ lmap ] . rectchange . t = LMBLOCK_HEIGHT ;
lightmaps [ lmap ] . rectchange . h = 0 ;
lightmaps [ lmap ] . rectchange . w = 0 ;
2021-07-13 05:20:09 +00:00
}
else
{
2021-08-31 05:43:13 +00:00
GL_Bind ( lightmaps [ lmap ] . texture ) ;
2021-07-13 05:20:09 +00:00
R_UploadLightmap ( lmap ) ;
}
2014-07-12 07:01:58 +00:00
}
}
2010-02-15 23:26:55 +00:00
/*
= = = = = = = = = = = = = = = =
R_RebuildAllLightmaps - - johnfitz - - called when gl_overbright gets toggled
= = = = = = = = = = = = = = = =
*/
void R_RebuildAllLightmaps ( void )
{
int i , j ;
2012-05-30 08:56:06 +00:00
qmodel_t * mod ;
2010-02-15 23:26:55 +00:00
msurface_t * fa ;
byte * base ;
if ( ! cl . worldmodel ) // is this the correct test?
return ;
//for each surface in each model, rebuild lightmap with new scale
for ( i = 1 ; i < MAX_MODELS ; i + + )
{
if ( ! ( mod = cl . model_precache [ i ] ) )
continue ;
fa = & mod - > surfaces [ mod - > firstmodelsurface ] ;
for ( j = 0 ; j < mod - > nummodelsurfaces ; j + + , fa + + )
{
if ( fa - > flags & SURF_DRAWTILED )
continue ;
2024-03-01 08:09:56 +00:00
base = lightmaps [ fa - > lightmaptexturenum ] . pbodata ;
2019-09-12 06:49:27 +00:00
base + = fa - > light_t * LMBLOCK_WIDTH * lightmap_bytes + fa - > light_s * lightmap_bytes ;
2024-03-01 08:09:56 +00:00
R_BuildLightMap ( mod , fa , base , LMBLOCK_WIDTH * lightmap_bytes , currententity , r_framecount , cl_dlights ) ;
2010-02-15 23:26:55 +00:00
}
}
//for each lightmap, upload it
2019-09-12 06:49:35 +00:00
for ( i = 0 ; i < lightmap_count ; i + + )
2010-02-15 23:26:55 +00:00
{
2021-08-31 05:43:13 +00:00
if ( ! lightmaps [ i ] . texture )
2021-07-13 05:20:09 +00:00
{
char name [ 24 ] ;
sprintf ( name , " lightmap%07i " , i ) ;
2024-03-01 08:09:56 +00:00
if ( lightmaps [ i ] . pbohandle )
{
GL_BindBufferFunc ( GL_PIXEL_UNPACK_BUFFER_ARB , lightmaps [ i ] . pbohandle ) ;
lightmaps [ i ] . texture = TexMgr_LoadImage ( NULL , name , LMBLOCK_WIDTH , LMBLOCK_HEIGHT ,
SRC_LIGHTMAP , NULL , " " , ( src_offset_t ) lightmaps [ i ] . pbodata , TEXPREF_LINEAR | TEXPREF_NOPICMIP | TEXPREF_PERSIST ) ;
GL_BindBufferFunc ( GL_PIXEL_UNPACK_BUFFER_ARB , 0 ) ;
}
else
{
lightmaps [ i ] . texture = TexMgr_LoadImage ( NULL , name , LMBLOCK_WIDTH , LMBLOCK_HEIGHT ,
SRC_LIGHTMAP , lightmaps [ i ] . pbodata , " " , ( src_offset_t ) lightmaps [ i ] . pbodata , TEXPREF_LINEAR | TEXPREF_NOPICMIP | TEXPREF_PERSIST ) ;
}
2021-07-13 05:20:09 +00:00
}
else
{
2021-08-31 05:43:13 +00:00
GL_Bind ( lightmaps [ i ] . texture ) ;
2024-03-01 08:09:56 +00:00
if ( lightmaps [ i ] . pbohandle )
{
GL_BindBufferFunc ( GL_PIXEL_UNPACK_BUFFER_ARB , lightmaps [ i ] . pbohandle ) ;
if ( gl_lightmap_format = = GL_RGB9_E5 )
glTexSubImage2D ( GL_TEXTURE_2D , 0 , 0 , 0 , LMBLOCK_WIDTH , LMBLOCK_HEIGHT , GL_RGB ,
GL_UNSIGNED_INT_5_9_9_9_REV , NULL ) ;
else
glTexSubImage2D ( GL_TEXTURE_2D , 0 , 0 , 0 , LMBLOCK_WIDTH , LMBLOCK_HEIGHT , gl_lightmap_format ,
GL_UNSIGNED_BYTE , NULL ) ;
GL_BindBufferFunc ( GL_PIXEL_UNPACK_BUFFER_ARB , 0 ) ;
}
2023-06-29 15:40:18 +00:00
else
2024-03-01 08:09:56 +00:00
{
if ( gl_lightmap_format = = GL_RGB9_E5 )
glTexSubImage2D ( GL_TEXTURE_2D , 0 , 0 , 0 , LMBLOCK_WIDTH , LMBLOCK_HEIGHT , GL_RGB ,
GL_UNSIGNED_INT_5_9_9_9_REV , lightmaps [ i ] . pbodata ) ;
else
glTexSubImage2D ( GL_TEXTURE_2D , 0 , 0 , 0 , LMBLOCK_WIDTH , LMBLOCK_HEIGHT , gl_lightmap_format ,
GL_UNSIGNED_BYTE , lightmaps [ i ] . pbodata ) ;
}
2021-07-13 05:20:09 +00:00
}
2021-08-31 05:43:13 +00:00
lightmaps [ i ] . modified = false ;
lightmaps [ i ] . rectchange . l = LMBLOCK_WIDTH ;
lightmaps [ i ] . rectchange . t = LMBLOCK_HEIGHT ;
lightmaps [ i ] . rectchange . h = 0 ;
lightmaps [ i ] . rectchange . w = 0 ;
2010-02-15 23:26:55 +00:00
}
}