Paranoia2/cl_dll/render/gl_debug.cpp

576 lines
15 KiB
C++

//
// written by BUzer for HL: Paranoia modification
//
// 2006
#include "hud.h"
#include "cl_util.h"
#include "const.h"
#include "com_model.h"
#include "r_studioint.h"
#include "ref_params.h"
#include "r_efx.h"
#include "event_api.h"
#include "pm_defs.h"
#include "pmtrace.h"
#include "triangleapi.h"
#include "gl_local.h"
#include "stringlib.h"
#include "gl_world.h"
#include "gl_shader.h"
#include "vertex_fmt.h"
void GL_GpuMemUsage_f( void )
{
GLint cur_avail_mem_kb = 0;
GLint total_mem_kb = 0;
if( glConfig.hardware_type == GLHW_NVIDIA )
{
pglGetIntegerv( GL_GPU_MEM_INFO_TOTAL_AVAILABLE_MEM_NVX, &total_mem_kb );
pglGetIntegerv( GL_GPU_MEM_INFO_CURRENT_AVAILABLE_MEM_NVX, &cur_avail_mem_kb );
}
Msg( "TEX used memory %s\n", Q_memprint( RENDER_GET_PARM( PARM_TEX_MEMORY, 0 )));
Msg( "VBO used memory %s\n", Q_memprint( tr.total_vbo_memory ));
Msg( "GPU used memory %s\n", Q_memprint(( total_mem_kb - cur_avail_mem_kb ) * 1024 ));
}
void DBG_PrintVertexVBOSizes( void )
{
if( developer_level < at_aiconsole )
return;
ALERT( at_console, "sizeof( bvert_v0_gl21_t ) == %d bytes\n", sizeof( bvert_v0_gl21_t ));
ALERT( at_console, "sizeof( bvert_v0_gl30_t ) == %d bytes\n", sizeof( bvert_v0_gl30_t ));
ALERT( at_console, "sizeof( gvert_v0_gl21_t ) == %d bytes\n", sizeof( gvert_v0_gl21_t ));
ALERT( at_console, "sizeof( gvert_v0_gl30_t ) == %d bytes\n", sizeof( gvert_v0_gl30_t ));
ALERT( at_console, "sizeof( gvert_v1_gl21_t ) == %d bytes\n", sizeof( gvert_v1_gl21_t ));
ALERT( at_console, "sizeof( gvert_v1_gl30_t ) == %d bytes\n", sizeof( gvert_v1_gl30_t ));
ALERT( at_console, "sizeof( svert_v0_gl21_t ) == %d bytes\n", sizeof( svert_v0_gl21_t ));
ALERT( at_console, "sizeof( svert_v0_gl30_t ) == %d bytes\n", sizeof( svert_v0_gl30_t ));
ALERT( at_console, "sizeof( svert_v1_gl21_t ) == %d bytes\n", sizeof( svert_v1_gl21_t ));
ALERT( at_console, "sizeof( svert_v1_gl30_t ) == %d bytes\n", sizeof( svert_v1_gl30_t ));
ALERT( at_console, "sizeof( svert_v2_gl21_t ) == %d bytes\n", sizeof( svert_v2_gl21_t ));
ALERT( at_console, "sizeof( svert_v2_gl30_t ) == %d bytes\n", sizeof( svert_v2_gl30_t ));
ALERT( at_console, "sizeof( svert_v3_gl21_t ) == %d bytes\n", sizeof( svert_v3_gl21_t ));
ALERT( at_console, "sizeof( svert_v3_gl30_t ) == %d bytes\n", sizeof( svert_v3_gl30_t ));
ALERT( at_console, "sizeof( svert_v4_gl21_t ) == %d bytes\n", sizeof( svert_v4_gl21_t ));
ALERT( at_console, "sizeof( svert_v4_gl30_t ) == %d bytes\n", sizeof( svert_v4_gl30_t ));
ALERT( at_console, "sizeof( svert_v5_gl21_t ) == %d bytes\n", sizeof( svert_v5_gl21_t ));
ALERT( at_console, "sizeof( svert_v5_gl30_t ) == %d bytes\n", sizeof( svert_v5_gl30_t ));
ALERT( at_console, "sizeof( svert_v6_gl21_t ) == %d bytes\n", sizeof( svert_v6_gl21_t ));
ALERT( at_console, "sizeof( svert_v6_gl30_t ) == %d bytes\n", sizeof( svert_v6_gl30_t ));
ALERT( at_console, "sizeof( svert_v7_gl21_t ) == %d bytes\n", sizeof( svert_v7_gl21_t ));
ALERT( at_console, "sizeof( svert_v7_gl30_t ) == %d bytes\n", sizeof( svert_v7_gl30_t ));
ALERT( at_console, "sizeof( svert_v8_gl21_t ) == %d bytes\n", sizeof( svert_v8_gl21_t ));
ALERT( at_console, "sizeof( svert_v8_gl30_t ) == %d bytes\n", sizeof( svert_v8_gl30_t ));
}
// some simple helpers to draw a cube in the special way the ambient visualization wants
static float *CubeSide( const vec3_t pos, float size, int vert )
{
static vec3_t side;
VectorCopy( pos, side );
side[0] += (vert & 1) ? -size : size;
side[1] += (vert & 2) ? -size : size;
side[2] += (vert & 4) ? -size : size;
return side;
}
static void CubeFace( const vec3_t org, int v0, int v1, int v2, int v3, float size, const byte *color )
{
uint scale = tr.lightstyle[0];
uint unclamped[3];
int col[3];
unclamped[0] = TEXTURE_TO_TEXGAMMA( color[0] ) * scale;
unclamped[1] = TEXTURE_TO_TEXGAMMA( color[1] ) * scale;
unclamped[2] = TEXTURE_TO_TEXGAMMA( color[2] ) * scale;
col[0] = min((unclamped[0] >> 7), 255 );
col[1] = min((unclamped[1] >> 7), 255 );
col[2] = min((unclamped[2] >> 7), 255 );
// pglColor3ub( col[0], col[1], col[2] );
pglColor3ub( color[0], color[1], color[2] );
pglVertex3fv( CubeSide( org, size, v0 ));
pglVertex3fv( CubeSide( org, size, v1 ));
pglVertex3fv( CubeSide( org, size, v2 ));
pglVertex3fv( CubeSide( org, size, v3 ));
}
void R_RenderLightProbe( mlightprobe_t *probe )
{
float rad = 4.0f;
pglBegin( GL_QUADS );
CubeFace( probe->origin, 4, 6, 2, 0, rad, probe->cube.color[0] );
CubeFace( probe->origin, 7, 5, 1, 3, rad, probe->cube.color[1] );
CubeFace( probe->origin, 0, 1, 5, 4, rad, probe->cube.color[2] );
CubeFace( probe->origin, 3, 2, 6, 7, rad, probe->cube.color[3] );
CubeFace( probe->origin, 2, 3, 1, 0, rad, probe->cube.color[4] );
CubeFace( probe->origin, 4, 5, 7, 6, rad, probe->cube.color[5] );
pglEnd ();
}
void R_RenderCubemap( mcubemap_t *cube )
{
float rad = (float)cube->size * 0.1f;
byte color[3] = { 127, 127, 127 };
pglBegin( GL_QUADS );
CubeFace( cube->origin, 4, 6, 2, 0, rad, color );
CubeFace( cube->origin, 7, 5, 1, 3, rad, color );
CubeFace( cube->origin, 0, 1, 5, 4, rad, color );
CubeFace( cube->origin, 3, 2, 6, 7, rad, color );
CubeFace( cube->origin, 2, 3, 1, 0, rad, color );
CubeFace( cube->origin, 4, 5, 7, 6, rad, color );
pglEnd ();
}
void R_RenderLightProbeInternal( const Vector &origin, const Vector lightCube[] )
{
mlightprobe_t probe;
for( int i = 0; i < 6; i++ )
{
probe.cube.color[i][0] = lightCube[i].x * 255;
probe.cube.color[i][1] = lightCube[i].y * 255;
probe.cube.color[i][2] = lightCube[i].z * 255;
}
probe.origin = origin;
R_RenderLightProbe( &probe );
}
/*
===============
R_DrawAABB
===============
*/
static void R_DrawAABB( const Vector &absmin, const Vector &absmax, int contents )
{
vec3_t bbox[8];
int i;
// compute a full bounding box
for( i = 0; i < 8; i++ )
{
bbox[i][0] = ( i & 1 ) ? absmin[0] : absmax[0];
bbox[i][1] = ( i & 2 ) ? absmin[1] : absmax[1];
bbox[i][2] = ( i & 4 ) ? absmin[2] : absmax[2];
}
GL_BindTexture( GL_TEXTURE0, tr.whiteTexture );
pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
pglDisable( GL_DEPTH_TEST );
switch( contents )
{
case CONTENTS_EMPTY:
pglColor4f( 0.5f, 1.0f, 0.0f, 1.0f ); // green for empty
break;
case CONTENTS_SOLID:
pglColor4f( 1.0f, 0.0f, 0.0f, 1.0f ); // red for solid
break;
case CONTENTS_WATER:
pglColor4f( 0.0f, 0.5f, 1.0f, 1.0f ); // blue for water
break;
default:
pglColor4f( 0.5f, 0.5f, 0.5f, 1.0f ); // gray as default
break;
}
pglBegin( GL_LINES );
for( i = 0; i < 2; i += 1 )
{
pglVertex3fv( bbox[i+0] );
pglVertex3fv( bbox[i+2] );
pglVertex3fv( bbox[i+4] );
pglVertex3fv( bbox[i+6] );
pglVertex3fv( bbox[i+0] );
pglVertex3fv( bbox[i+4] );
pglVertex3fv( bbox[i+2] );
pglVertex3fv( bbox[i+6] );
pglVertex3fv( bbox[i*2+0] );
pglVertex3fv( bbox[i*2+1] );
pglVertex3fv( bbox[i*2+4] );
pglVertex3fv( bbox[i*2+5] );
}
pglEnd();
pglEnable( GL_DEPTH_TEST );
}
/*
===============
R_RenderVisibleLeafs
===============
*/
static void R_RenderVisibleLeafs( void )
{
mleaf_t *leaf;
int i;
// always skip the leaf 0, because is outside leaf
for( i = 1, leaf = &worldmodel->leafs[1]; i < worldmodel->numleafs + 1; i++, leaf++ )
{
mextraleaf_t *eleaf = LEAF_INFO( leaf, worldmodel );
if( CHECKVISBIT( RI->view.pvsarray, leaf->cluster ) && ( leaf->efrags || leaf->nummarksurfaces ))
{
R_DrawAABB( eleaf->mins, eleaf->maxs, CONTENTS_WATER );
R_DrawAABB( Vector( leaf->minmaxs ), Vector( leaf->minmaxs + 3 ), leaf->contents );
}
}
}
/*
=============
DrawViewLeaf
=============
*/
void DrawViewLeaf( void )
{
if( !CVAR_TO_BOOL( r_show_viewleaf ))
return;
GL_Blend( GL_FALSE );
R_RenderVisibleLeafs();
}
/*
=============
DrawLightProbes
=============
*/
void DrawLightProbes( void )
{
int i, j;
mlightprobe_t *probe;
mleaf_t *leaf;
mextraleaf_t *info;
if( !CVAR_TO_BOOL( r_show_lightprobes ))
return;
GL_Blend( GL_FALSE );
GL_BindTexture( GL_TEXTURE0, tr.whiteTexture );
pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
// draw the all visible probes
for( i = 1; i < world->numleafs; i++ )
{
leaf = (mleaf_t *)&worldmodel->leafs[i];
info = LEAF_INFO( leaf, worldmodel );
if( !CHECKVISBIT( RI->view.pvsarray, leaf->cluster ))
continue; // not visible from player
for( j = 0; j < info->num_lightprobes; j++ )
{
probe = info->ambient_light + j;
R_RenderLightProbe( probe );
}
}
pglColor3f( 1.0f, 1.0f, 1.0f );
}
/*
=============
DrawCubeMaps
=============
*/
void DrawCubeMaps( void )
{
mcubemap_t *cm;
if( !CVAR_TO_BOOL( r_show_cubemaps ))
return;
GL_Blend( GL_FALSE );
GL_BindTexture( GL_TEXTURE0, tr.whiteTexture );
pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
// draw the all cubemaps
for( int i = 0; i < world->num_cubemaps; i++ )
{
cm = &world->cubemaps[i];
R_RenderCubemap( cm );
}
pglColor3f( 1.0f, 1.0f, 1.0f );
}
void DBG_DrawBBox( const Vector &mins, const Vector &maxs )
{
Vector bbox[8];
int i;
for( i = 0; i < 8; i++ )
{
bbox[i][0] = ( i & 1 ) ? mins[0] : maxs[0];
bbox[i][1] = ( i & 2 ) ? mins[1] : maxs[1];
bbox[i][2] = ( i & 4 ) ? mins[2] : maxs[2];
}
pglColor4f( 1.0f, 0.0f, 1.0f, 1.0f ); // yellow bboxes for frustum
GL_BindTexture( GL_TEXTURE0, tr.whiteTexture );
pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
pglBegin( GL_LINES );
for( i = 0; i < 2; i += 1 )
{
pglVertex3fv( bbox[i+0] );
pglVertex3fv( bbox[i+2] );
pglVertex3fv( bbox[i+4] );
pglVertex3fv( bbox[i+6] );
pglVertex3fv( bbox[i+0] );
pglVertex3fv( bbox[i+4] );
pglVertex3fv( bbox[i+2] );
pglVertex3fv( bbox[i+6] );
pglVertex3fv( bbox[i*2+0] );
pglVertex3fv( bbox[i*2+1] );
pglVertex3fv( bbox[i*2+4] );
pglVertex3fv( bbox[i*2+5] );
}
pglEnd();
}
void DBG_DrawLightFrustum( void )
{
if( CVAR_TO_BOOL( r_scissor_light_debug ) && RP_NORMALPASS( ))
{
pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
for( int i = 0; i < MAX_DLIGHTS; i++ )
{
CDynLight *pl = &tr.dlights[i];
if( !pl->Active( )) continue;
if( r_scissor_light_debug->value == 1.0f )
{
R_DrawScissorRectangle( pl->x, pl->y, pl->w, pl->h );
}
else if( r_scissor_light_debug->value == 2.0f )
{
if( pl->type == LIGHT_DIRECTIONAL )
{
for( int j = 0; j < NUM_SHADOW_SPLITS + 1; j++ )
pl->splitFrustum[j].DrawFrustumDebug();
}
else pl->frustum.DrawFrustumDebug();
}
else
{
DBG_DrawBBox( pl->absmin, pl->absmax );
}
}
}
}
void DBG_DrawGlassScissors( void )
{
if( CVAR_TO_BOOL( r_scissor_glass_debug ) && RP_NORMALPASS( ))
{
// debug scissor code
GL_BindShader( NULL );
// debug scissor code
for( int k = 0; k < RI->frame.trans_list.Count(); k++ )
{
CTransEntry *entry = &RI->frame.trans_list[k];
entry->RenderScissorDebug();
}
}
}
/*
================
DrawTangentSpaces
Draws vertex tangent spaces for debugging
================
*/
void DrawTangentSpaces( void )
{
float temp[3];
float vecLen = 4.0f;
if( !CVAR_TO_BOOL( cv_show_tbn ))
return;
GL_BindTexture( GL_TEXTURE0, tr.whiteTexture );
pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
pglDisable( GL_DEPTH_TEST );
GL_Blend( GL_FALSE );
pglBegin( GL_LINES );
for( int i = 0; i < worldmodel->nummodelsurfaces; i++ )
{
msurface_t *surf = &worldmodel->surfaces[i];
mextrasurf_t *esrf = surf->info;
if( FBitSet( surf->flags, SURF_DRAWTURB|SURF_DRAWSKY ))
continue;
bvert_t *mv = &world->vertexes[esrf->firstvertex];
for( int j = 0; j < esrf->numverts; j++, mv++ )
{
pglColor3f( 1.0f, 0.0f, 0.0f );
pglVertex3fv( mv->vertex );
VectorMA( mv->vertex, vecLen, Vector( mv->tangent ), temp );
pglVertex3fv( temp );
pglColor3f( 0.0f, 1.0f, 0.0f );
pglVertex3fv( mv->vertex );
VectorMA( mv->vertex, vecLen, Vector( mv->binormal ), temp );
pglVertex3fv( temp );
pglColor3f( 0.0f, 0.0f, 1.0f );
pglVertex3fv( mv->vertex );
VectorMA( mv->vertex, vecLen, Vector( mv->normal ), temp );
pglVertex3fv( temp );
}
}
pglEnd();
pglEnable( GL_DEPTH_TEST );
}
void DrawWireFrame( void )
{
int i;
if( !CVAR_TO_BOOL( r_wireframe ))
return;
pglEnable( GL_BLEND );
pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
pglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
pglColor4f( 1.0f, 1.0f, 1.0f, 0.99f );
pglDisable( GL_DEPTH_TEST );
pglEnable( GL_LINE_SMOOTH );
GL_BindTexture( GL_TEXTURE0, tr.whiteTexture );
pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
pglEnable( GL_POLYGON_SMOOTH );
pglHint( GL_LINE_SMOOTH_HINT, GL_NICEST );
pglHint( GL_POLYGON_SMOOTH_HINT, GL_NICEST );
for( i = 0; i < RI->frame.solid_faces.Count(); i++ )
{
if( RI->frame.solid_faces[i].m_bDrawType != DRAWTYPE_SURFACE )
continue;
msurface_t *surf = RI->frame.solid_faces[i].m_pSurf;
mextrasurf_t *es = surf->info;
pglBegin( GL_POLYGON );
for( int j = 0; j < es->numverts; j++ )
{
bvert_t *v = &world->vertexes[es->firstvertex + j];
pglVertex3fv( v->vertex + Vector( v->normal ) * 0.1f );
}
pglEnd();
}
pglColor4f( 0.0f, 1.0f, 0.0f, 0.99f );
for( i = 0; i < RI->frame.trans_list.Count(); i++ )
{
if( RI->frame.trans_list[i].m_bDrawType != DRAWTYPE_SURFACE )
continue;
msurface_t *surf = RI->frame.trans_list[i].m_pSurf;
mextrasurf_t *es = surf->info;
pglBegin( GL_POLYGON );
for( int j = 0; j < es->numverts; j++ )
{
bvert_t *v = &world->vertexes[es->firstvertex + j];
pglVertex3fv( v->vertex + Vector( v->normal ) * 0.1f );
}
pglEnd();
}
pglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
pglDisable( GL_POLYGON_SMOOTH );
pglDisable( GL_LINE_SMOOTH );
pglEnable( GL_DEPTH_TEST );
pglDisable( GL_BLEND );
}
void DrawWirePoly( msurface_t *surf )
{
if( !surf ) return;
pglEnable( GL_BLEND );
pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
pglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
pglColor4f( 0.5f, 1.0f, 0.36f, 0.99f );
pglLineWidth( 4.0f );
pglDisable( GL_DEPTH_TEST );
pglEnable( GL_LINE_SMOOTH );
pglEnable( GL_POLYGON_SMOOTH );
pglHint( GL_LINE_SMOOTH_HINT, GL_NICEST );
pglHint( GL_POLYGON_SMOOTH_HINT, GL_NICEST );
mextrasurf_t *es = surf->info;
pglBegin( GL_POLYGON );
for( int j = 0; j < es->numverts; j++ )
{
bvert_t *v = &world->vertexes[es->firstvertex + j];
pglVertex3fv( v->vertex + Vector( v->normal ) * 0.1f );
}
pglEnd();
pglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
pglDisable( GL_POLYGON_SMOOTH );
pglDisable( GL_LINE_SMOOTH );
pglEnable( GL_DEPTH_TEST );
pglDisable( GL_BLEND );
pglLineWidth( 1.0f );
}
void R_ShowLightMaps( void )
{
int index = 0;
if( !CVAR_TO_BOOL( r_showlightmaps ))
return;
index = r_showlightmaps->value - 1.0f;
if( tr.lightmaps[index].state == LM_FREE )
return;
GL_BindTexture( GL_TEXTURE0, tr.lightmaps[index].lightmap );
pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
GL_Setup2D();
pglBegin( GL_QUADS );
pglTexCoord2f( 0.0f, 0.0f );
pglVertex2f( 0.0f, 0.0f );
pglTexCoord2f( 1.0f, 0.0f );
pglVertex2f( glState.width, 0.0f );
pglTexCoord2f( 1.0f, 1.0f );
pglVertex2f( glState.width, glState.height );
pglTexCoord2f( 0.0f, 1.0f );
pglVertex2f( 0.0f, glState.height );
pglEnd();
GL_Setup3D();
}