You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
689 lines
25 KiB
689 lines
25 KiB
//========= Copyright © 1996-2007, Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose:
|
|
//
|
|
// $NoKeywords: $
|
|
//=============================================================================//
|
|
#include "cbase.h"
|
|
|
|
#include "c_surfacerender.h"
|
|
|
|
#include "view.h"
|
|
#include "view_shared.h"
|
|
#include "iviewrender.h"
|
|
#include "engine/ivdebugoverlay.h"
|
|
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include "tier0/memdbgon.h"
|
|
|
|
|
|
#ifdef USE_BLOBULATOR
|
|
|
|
ConVar r_surface_draw_isosurface( "r_surface_draw_isosurface", "1", 0, "Draws the surface as an isosurface" );
|
|
|
|
ConVar r_surface_rotate( "r_surface_rotate", "1", FCVAR_NONE, "Whether to rotate for transparency" );
|
|
ConVar r_surface_rotate_by90( "r_surface_rotate_by90", "1", FCVAR_NONE, "Whether to only rotate in 90 degree increments" );
|
|
|
|
ConVar r_surface_blr_scale( "r_surface_blr_scale", "1.0", FCVAR_NONE, "Scale all surface rendering parameters." );
|
|
ConVar r_surface_blr_cubewidth( "r_surface_blr_cubewidth", "0.8", FCVAR_NONE, "Set cubewidth (coarseness of the mesh)" );
|
|
ConVar r_surface_blr_render_radius( "r_surface_blr_render_radius", "1.3", FCVAR_NONE, "Set render radius (how far from particle center surface will be)" );
|
|
ConVar r_surface_blr_cutoff_radius( "r_surface_blr_cutoff_radius", "3.3", FCVAR_NONE, "Set cutoff radius (how far field extends from each particle)" );
|
|
|
|
ConVar r_surface_calc_uv_and_tan( "r_surface_calc_uv_and_tan", "1", FCVAR_ARCHIVE, "Calculate UVs and Tangents" );
|
|
ConVar r_surface_calc_tan_only( "r_surface_calc_tan_only", "0", FCVAR_ARCHIVE, "Calculate Only Tangents" );
|
|
ConVar r_surface_calc_color( "r_surface_calc_color", "0", FCVAR_ARCHIVE, "Just interpolate colors" );
|
|
ConVar r_surface_calc_hifreq_color( "r_surface_calc_hifreq_color", "0", FCVAR_ARCHIVE, "Experimental hi-freq colors" );
|
|
ConVar r_surface_calc_tile_color( "r_surface_calc_tile_color", "0", FCVAR_ARCHIVE, "Shows color of the tile" );
|
|
|
|
ConVar r_surface_debug_use_tiler("r_surface_debug_use_tiler", "1", FCVAR_NONE, "Use the tiler");
|
|
ConVar r_surface_debug_max_tiles( "r_surface_debug_max_tiles", "-1", FCVAR_NONE, "The maximum number of tiles to draw" );
|
|
ConVar r_surface_debug_max_slices( "r_surface_debug_max_slices", "-1", FCVAR_NONE, "The maximum number of slices to draw" );
|
|
ConVar r_surface_debug_tile("r_surface_debug_tile", "1", FCVAR_NONE, "If tiler is enabled, whether we draw all tiles or just the central one.");
|
|
ConVar r_surface_debug_draw_margin("r_surface_debug_draw_margin", "0", FCVAR_NONE, "If tiler is disabled, whether to draw the margin.");
|
|
ConVar r_surface_debug_draw_tile_boundaries("r_surface_debug_draw_tile_boundaries", "0", FCVAR_NONE, "Whether to draw outlines of all tiles.");
|
|
|
|
ConVar r_surface_wireframe( "r_surface_wireframe", "0", FCVAR_NONE, "Draw wireframe" );
|
|
ConVar r_surface_material("r_surface_material", "-1", FCVAR_NONE, "Choose a material from 0 to N");
|
|
ConVar r_surface_shader("r_surface_shader", "", FCVAR_NONE, "Choose a shader");
|
|
|
|
|
|
CUtlVector< ImpParticleWithFourInterpolants, CUtlMemoryAligned< ImpParticleWithFourInterpolants, 16 > > g_SurfaceRenderParticles; // This must be aligned due to SSE use
|
|
const QAngle g_SurfaceRenderAnglesAngles( 0.0f, 0.0f, 0.0f ); // our local coordinate system is always aligned to world space
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Draw a Sphere
|
|
//-----------------------------------------------------------------------------
|
|
|
|
float g_FastSpherePosData[51][8] = {
|
|
{ 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 0.0000, 1.0000 },
|
|
{ -0.0000, 0.5000, 0.8660, 0.2500, 0.1667, -0.0000, 0.5000, 0.8660 },
|
|
{ 0.5000, 0.0000, 0.8660, 0.0000, 0.1667, 0.5000, 0.0000, 0.8660 },
|
|
{ 0.0000, 0.0000, 1.0000, 0.5000, 0.0000, 0.0000, 0.0000, 1.0000 },
|
|
{ -0.5000, -0.0000, 0.8660, 0.5000, 0.1667, -0.5000, -0.0000, 0.8660 },
|
|
{ 0.0000, 0.0000, -1.0000, 0.0000, 1.0000, 0.0000, 0.0000, -1.0000 },
|
|
{ 0.5000, 0.0000, -0.8660, 0.0000, 0.8333, 0.5000, 0.0000, -0.8660 },
|
|
{ -0.0000, 0.5000, -0.8660, 0.2500, 0.8333, -0.0000, 0.5000, -0.8660 },
|
|
{ 0.0000, 0.0000, -1.0000, 0.5000, 1.0000, 0.0000, 0.0000, -1.0000 },
|
|
{ -0.5000, -0.0000, -0.8660, 0.5000, 0.8333, -0.5000, -0.0000, -0.8660 },
|
|
{ 0.0000, -0.5000, 0.8660, 0.7500, 0.1667, 0.0000, -0.5000, 0.8660 },
|
|
{ 0.0000, 0.0000, 1.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000 },
|
|
{ 0.5000, 0.0000, 0.8660, 1.0000, 0.1667, 0.5000, 0.0000, 0.8660 },
|
|
{ 0.0000, -0.5000, -0.8660, 0.7500, 0.8333, 0.0000, -0.5000, -0.8660 },
|
|
{ 0.0000, 0.0000, -1.0000, 1.0000, 1.0000, 0.0000, 0.0000, -1.0000 },
|
|
{ 0.5000, 0.0000, -0.8660, 1.0000, 0.8333, 0.5000, 0.0000, -0.8660 },
|
|
{ 0.6124, 0.6124, 0.5000, 0.1250, 0.3333, 0.6124, 0.6124, 0.5000 },
|
|
{ 0.8660, 0.0000, 0.5000, 0.0000, 0.3333, 0.8660, 0.0000, 0.5000 },
|
|
{ -0.0000, 0.8660, 0.5000, 0.2500, 0.3333, -0.0000, 0.8660, 0.5000 },
|
|
{ 0.8660, 0.0000, -0.5000, 0.0000, 0.6667, 0.8660, 0.0000, -0.5000 },
|
|
{ 0.6124, 0.6124, -0.5000, 0.1250, 0.6667, 0.6124, 0.6124, -0.5000 },
|
|
{ -0.0000, 0.8660, -0.5000, 0.2500, 0.6667, -0.0000, 0.8660, -0.5000 },
|
|
{ -0.6124, 0.6124, 0.5000, 0.3750, 0.3333, -0.6124, 0.6124, 0.5000 },
|
|
{ -0.8660, -0.0000, 0.5000, 0.5000, 0.3333, -0.8660, -0.0000, 0.5000 },
|
|
{ -0.6124, 0.6124, -0.5000, 0.3750, 0.6667, -0.6124, 0.6124, -0.5000 },
|
|
{ -0.8660, -0.0000, -0.5000, 0.5000, 0.6667, -0.8660, -0.0000, -0.5000 },
|
|
{ -0.6124, -0.6124, 0.5000, 0.6250, 0.3333, -0.6124, -0.6124, 0.5000 },
|
|
{ 0.0000, -0.8660, 0.5000, 0.7500, 0.3333, 0.0000, -0.8660, 0.5000 },
|
|
{ -0.6124, -0.6124, -0.5000, 0.6250, 0.6667, -0.6124, -0.6124, -0.5000 },
|
|
{ 0.0000, -0.8660, -0.5000, 0.7500, 0.6667, 0.0000, -0.8660, -0.5000 },
|
|
{ 0.6124, -0.6124, 0.5000, 0.8750, 0.3333, 0.6124, -0.6124, 0.5000 },
|
|
{ 0.8660, 0.0000, 0.5000, 1.0000, 0.3333, 0.8660, 0.0000, 0.5000 },
|
|
{ 0.6124, -0.6124, -0.5000, 0.8750, 0.6667, 0.6124, -0.6124, -0.5000 },
|
|
{ 0.8660, 0.0000, -0.5000, 1.0000, 0.6667, 0.8660, 0.0000, -0.5000 },
|
|
{ 0.9239, 0.3827, 0.0000, 0.0625, 0.5000, 0.9239, 0.3827, 0.0000 },
|
|
{ 1.0000, 0.0000, 0.0000, 0.0000, 0.5000, 1.0000, 0.0000, 0.0000 },
|
|
{ 0.7071, 0.7071, 0.0000, 0.1250, 0.5000, 0.7071, 0.7071, 0.0000 },
|
|
{ 0.3827, 0.9239, 0.0000, 0.1875, 0.5000, 0.3827, 0.9239, 0.0000 },
|
|
{ -0.0000, 1.0000, 0.0000, 0.2500, 0.5000, -0.0000, 1.0000, 0.0000 },
|
|
{ -0.3827, 0.9239, 0.0000, 0.3125, 0.5000, -0.3827, 0.9239, 0.0000 },
|
|
{ -0.7071, 0.7071, 0.0000, 0.3750, 0.5000, -0.7071, 0.7071, 0.0000 },
|
|
{ -0.9239, 0.3827, 0.0000, 0.4375, 0.5000, -0.9239, 0.3827, 0.0000 },
|
|
{ -1.0000, -0.0000, 0.0000, 0.5000, 0.5000, -1.0000, -0.0000, 0.0000 },
|
|
{ -0.9239, -0.3827, 0.0000, 0.5625, 0.5000, -0.9239, -0.3827, 0.0000 },
|
|
{ -0.7071, -0.7071, 0.0000, 0.6250, 0.5000, -0.7071, -0.7071, 0.0000 },
|
|
{ -0.3827, -0.9239, 0.0000, 0.6875, 0.5000, -0.3827, -0.9239, 0.0000 },
|
|
{ 0.0000, -1.0000, 0.0000, 0.7500, 0.5000, 0.0000, -1.0000, 0.0000 },
|
|
{ 0.3827, -0.9239, 0.0000, 0.8125, 0.5000, 0.3827, -0.9239, 0.0000 },
|
|
{ 0.7071, -0.7071, 0.0000, 0.8750, 0.5000, 0.7071, -0.7071, 0.0000 },
|
|
{ 0.9239, -0.3827, 0.0000, 0.9375, 0.5000, 0.9239, -0.3827, 0.0000 },
|
|
{ 1.0000, 0.0000, 0.0000, 1.0000, 0.5000, 1.0000, 0.0000, 0.0000 }
|
|
};
|
|
|
|
|
|
int g_FastSphereTriData[84][3] = {
|
|
{ 0, 1, 2 },
|
|
{ 0, 3, 1 },
|
|
{ 3, 4, 1 },
|
|
{ 5, 6, 7 },
|
|
{ 5, 7, 8 },
|
|
{ 8, 7, 9 },
|
|
{ 3, 10, 4 },
|
|
{ 3, 11, 10 },
|
|
{ 11, 12, 10 },
|
|
{ 8, 9, 13 },
|
|
{ 8, 13, 14 },
|
|
{ 14, 13, 15 },
|
|
{ 2, 16, 17 },
|
|
{ 2, 1, 16 },
|
|
{ 1, 18, 16 },
|
|
{ 6, 19, 20 },
|
|
{ 6, 20, 7 },
|
|
{ 7, 20, 21 },
|
|
{ 1, 22, 18 },
|
|
{ 1, 4, 22 },
|
|
{ 4, 23, 22 },
|
|
{ 7, 21, 24 },
|
|
{ 7, 24, 9 },
|
|
{ 9, 24, 25 },
|
|
{ 4, 26, 23 },
|
|
{ 4, 10, 26 },
|
|
{ 10, 27, 26 },
|
|
{ 9, 25, 28 },
|
|
{ 9, 28, 13 },
|
|
{ 13, 28, 29 },
|
|
{ 10, 30, 27 },
|
|
{ 10, 12, 30 },
|
|
{ 12, 31, 30 },
|
|
{ 13, 29, 32 },
|
|
{ 13, 32, 15 },
|
|
{ 15, 32, 33 },
|
|
{ 17, 34, 35 },
|
|
{ 17, 16, 34 },
|
|
{ 16, 36, 34 },
|
|
{ 19, 35, 34 },
|
|
{ 19, 34, 20 },
|
|
{ 20, 34, 36 },
|
|
{ 16, 37, 36 },
|
|
{ 16, 18, 37 },
|
|
{ 18, 38, 37 },
|
|
{ 20, 36, 37 },
|
|
{ 20, 37, 21 },
|
|
{ 21, 37, 38 },
|
|
{ 18, 39, 38 },
|
|
{ 18, 22, 39 },
|
|
{ 22, 40, 39 },
|
|
{ 21, 38, 39 },
|
|
{ 21, 39, 24 },
|
|
{ 24, 39, 40 },
|
|
{ 22, 41, 40 },
|
|
{ 22, 23, 41 },
|
|
{ 23, 42, 41 },
|
|
{ 24, 40, 41 },
|
|
{ 24, 41, 25 },
|
|
{ 25, 41, 42 },
|
|
{ 23, 43, 42 },
|
|
{ 23, 26, 43 },
|
|
{ 26, 44, 43 },
|
|
{ 25, 42, 43 },
|
|
{ 25, 43, 28 },
|
|
{ 28, 43, 44 },
|
|
{ 26, 45, 44 },
|
|
{ 26, 27, 45 },
|
|
{ 27, 46, 45 },
|
|
{ 28, 44, 45 },
|
|
{ 28, 45, 29 },
|
|
{ 29, 45, 46 },
|
|
{ 27, 47, 46 },
|
|
{ 27, 30, 47 },
|
|
{ 30, 48, 47 },
|
|
{ 29, 46, 47 },
|
|
{ 29, 47, 32 },
|
|
{ 32, 47, 48 },
|
|
{ 30, 49, 48 },
|
|
{ 30, 31, 49 },
|
|
{ 31, 50, 49 },
|
|
{ 32, 48, 49 },
|
|
{ 32, 49, 33 },
|
|
{ 33, 49, 50 }
|
|
};
|
|
|
|
|
|
void Surface_DrawFastSphere( CMeshBuilder &meshBuilder, const Vector ¢er, float radius, float r, float g, float b )
|
|
{
|
|
int offset = meshBuilder.GetCurrentVertex();
|
|
|
|
Vector pos;
|
|
for (int i = 0; i < 51; i++)
|
|
{
|
|
pos.x = g_FastSpherePosData[i][0] + center.x + g_FastSpherePosData[i][5] * radius;
|
|
pos.y = g_FastSpherePosData[i][1] + center.y + g_FastSpherePosData[i][6] * radius;
|
|
pos.z = g_FastSpherePosData[i][2] + center.z + g_FastSpherePosData[i][7] * radius;
|
|
|
|
meshBuilder.Position3fv( pos.Base() );
|
|
meshBuilder.Normal3fv( &g_FastSpherePosData[i][5] );
|
|
meshBuilder.TexCoord2fv( 0, &g_FastSpherePosData[i][3] );
|
|
meshBuilder.Color3f( r, g, b );
|
|
meshBuilder.AdvanceVertex();
|
|
}
|
|
|
|
for (int i = 0; i < 84; i++)
|
|
{
|
|
meshBuilder.FastIndex( g_FastSphereTriData[i][0] + offset );
|
|
meshBuilder.FastIndex( g_FastSphereTriData[i][1] + offset );
|
|
meshBuilder.FastIndex( g_FastSphereTriData[i][2] + offset );
|
|
}
|
|
}
|
|
|
|
struct Surface_DrawSpheres_sortParticles_t
|
|
{
|
|
int no;
|
|
float dist;
|
|
|
|
class C
|
|
{
|
|
public:
|
|
static bool gt(Surface_DrawSpheres_sortParticles_t a, Surface_DrawSpheres_sortParticles_t b)
|
|
{
|
|
return a.dist < b.dist;
|
|
}
|
|
};
|
|
};
|
|
|
|
void Surface_DrawSpheres( IMaterial *pMaterial, float flRadius )
|
|
{
|
|
Point3D eye = view->GetViewSetup()->origin;
|
|
|
|
SmartArray<Surface_DrawSpheres_sortParticles_t> sort_particles;
|
|
sort_particles.ensureCapacity(g_SurfaceRenderParticles.Count());
|
|
sort_particles.size = g_SurfaceRenderParticles.Count();
|
|
for(int i = 0; i < g_SurfaceRenderParticles.Count(); i++)
|
|
{
|
|
sort_particles[i].no = i;
|
|
sort_particles[i].dist = g_SurfaceRenderParticles[i].center.length(eye);
|
|
}
|
|
sort_particles.sort<Surface_DrawSpheres_sortParticles_t::C>();
|
|
|
|
CMatRenderContextPtr pRenderContext( materials );
|
|
|
|
pRenderContext->MatrixMode( MATERIAL_MODEL );
|
|
pRenderContext->Bind( pMaterial );
|
|
|
|
IMesh* pMesh = pRenderContext->GetDynamicMesh( true );
|
|
|
|
int vertMax = MIN( 24000 / 51, 32768 / (84 * 3) );
|
|
|
|
int j = 0;
|
|
// Msg( "point %.2f %.2f %.2f\n", m_vecSurfacePos[0].x, m_vecSurfacePos[0].y, m_vecSurfacePos[0].z );
|
|
while (j < g_SurfaceRenderParticles.Count())
|
|
{
|
|
int total = MIN( g_SurfaceRenderParticles.Count() - j, vertMax );
|
|
|
|
CMeshBuilder meshBuilder;
|
|
meshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, total * 51, total * 84 * 3 );
|
|
|
|
int i = 0;
|
|
while (i < vertMax && j < g_SurfaceRenderParticles.Count())
|
|
{
|
|
ImpParticleWithOneInterpolant* imp_particle = &(g_SurfaceRenderParticles[sort_particles[j].no]);
|
|
|
|
if (imp_particle->scale > 0.01)
|
|
{
|
|
Surface_DrawFastSphere( meshBuilder, imp_particle->center.AsVector(), flRadius * imp_particle->scale, imp_particle->interpolants1[0], imp_particle->interpolants1[1], imp_particle->interpolants1[2] );
|
|
i++;
|
|
}
|
|
j++;
|
|
}
|
|
|
|
meshBuilder.End();
|
|
pMesh->Draw();
|
|
}
|
|
}
|
|
|
|
|
|
void Surface_SafeLightCubeUpdate( const Vector &vecRenderOrigin, Vector4D *cachedCubeColours )
|
|
{
|
|
// We sometimes get an invalid ambient lightcube for the isosurface sample point, this func smooths over that
|
|
// FIXME: this is probably to do with sampling at invalid locations
|
|
// FIXME: we need more complex lighting data for isosurfaces anyway
|
|
// (per-vertex light sample indices ala skinning, or UVWs into a light sample texture)
|
|
|
|
Vector boxColors[6];
|
|
engine->ComputeLightingCube( vecRenderOrigin, false, boxColors );
|
|
|
|
// Are we trying to sample outside the world?
|
|
bool invalidOrigin = enginetrace->PointOutsideWorld( vecRenderOrigin );
|
|
|
|
for ( int i = 0; i < 6; i++ )
|
|
{
|
|
if( !IsFinite( boxColors[i].x ) || !IsFinite( boxColors[i].y ) || !IsFinite( boxColors[i].z ) )
|
|
{
|
|
DevWarning( "Isosurface lighting cube with infinite values!\n%s",
|
|
invalidOrigin ? "(lighting origin is !OUTSIDE! the world)\n" : "" );
|
|
return;
|
|
}
|
|
}
|
|
|
|
for ( int i = 0; i < 6; i++ )
|
|
{
|
|
if( boxColors[i].x < -0.1f || boxColors[i].y < -0.1f || boxColors[i].z < -0.1f )
|
|
{
|
|
DevWarning( "Isosurface lighting cube negative: %f %f %f\n%s", boxColors[i].x, boxColors[i].y, boxColors[i].z,
|
|
invalidOrigin ? "(lighting origin is !OUTSIDE! the world)\n" : "" );
|
|
}
|
|
|
|
cachedCubeColours[i].AsVector3D() = Lerp( clamp( 2.0f * gpGlobals->frametime, 0.0f, 1.0f ), cachedCubeColours[i].AsVector3D(), boxColors[i] );
|
|
}
|
|
|
|
bool bBadLightCube = false;
|
|
for ( int i = 0; i < 6; i++ )
|
|
{
|
|
if ( !IsFinite( cachedCubeColours[i].x ) || !IsFinite( cachedCubeColours[i].y ) || !IsFinite( cachedCubeColours[i].z ) ||
|
|
( cachedCubeColours[i].x < -0.01f ) || ( cachedCubeColours[i].y < -0.01f ) || ( cachedCubeColours[i].z < -0.01f ) )
|
|
{
|
|
DevWarning( "Isosurface lighting cube bad. Resetting.\n%s",
|
|
invalidOrigin ? "(lighting origin is !OUTSIDE! the world)\n" : "" );
|
|
bBadLightCube = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( bBadLightCube )
|
|
{
|
|
memset( cachedCubeColours, 0, sizeof( cachedCubeColours ) );
|
|
}
|
|
}
|
|
|
|
|
|
IMaterial* GetDrawMaterial( void )
|
|
{
|
|
if ( r_surface_wireframe.GetBool() )
|
|
{
|
|
if( r_surface_material.GetInt() < 0 )
|
|
{
|
|
return materials->FindMaterial("shadertest/wireframe", TEXTURE_GROUP_OTHER);
|
|
}
|
|
else
|
|
{
|
|
return materials->FindMaterial("shadertest/wireframevertexcolornocull", TEXTURE_GROUP_OTHER);
|
|
}
|
|
}
|
|
else if ( strlen( r_surface_shader.GetString() ) > 0 )
|
|
{
|
|
return materials->FindMaterial( r_surface_shader.GetString(), TEXTURE_GROUP_OTHER, true );
|
|
}
|
|
else
|
|
{
|
|
switch ( r_surface_material.GetInt() )
|
|
{
|
|
case 0:
|
|
return materials->FindMaterial( "models/debug/debugwhite", TEXTURE_GROUP_OTHER, true );
|
|
case 1:
|
|
return materials->FindMaterial( "models/debug/debugwhite2", TEXTURE_GROUP_OTHER, true );
|
|
case 2:
|
|
return materials->FindMaterial( "models/debug/debugwhite3", TEXTURE_GROUP_OTHER, true );
|
|
case 3:
|
|
return materials->FindMaterial( "debug/debugvertexcolor", TEXTURE_GROUP_OTHER, true );
|
|
case 4:
|
|
return materials->FindMaterial( "debug/env_cubemap_model", TEXTURE_GROUP_OTHER, true );
|
|
case 5:
|
|
return materials->FindMaterial( "models/blob/env_cubemap_model_translucent_fountain", TEXTURE_GROUP_OTHER, true );
|
|
case 6:
|
|
return materials->FindMaterial( "models/debug/debugmesh", TEXTURE_GROUP_OTHER, true );
|
|
case 7:
|
|
return materials->FindMaterial( "models/debug/debugmesh_transparent", TEXTURE_GROUP_OTHER, true );
|
|
case 8:
|
|
return materials->FindMaterial( "models/ihvtest/tongue_bumped", TEXTURE_GROUP_OTHER, true );
|
|
case 9:
|
|
return materials->FindMaterial( "models/debug/debugbumps", TEXTURE_GROUP_OTHER, true );
|
|
case 10:
|
|
return materials->FindMaterial( "debug/env_cubemap_model_translucent_no_bumps", TEXTURE_GROUP_OTHER, true );
|
|
case 11:
|
|
return materials->FindMaterial( "models/shadertest/predator", TEXTURE_GROUP_OTHER, true );
|
|
default:
|
|
return NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void SetUpImpRendererUserDefinedFuncs( void )
|
|
{
|
|
RENDERER_CLASS::setCalcSignFunc(calcSign);
|
|
RENDERER_CLASS::setCalcSign2Func(calcSign2);
|
|
|
|
if(r_surface_calc_uv_and_tan.GetBool())
|
|
{
|
|
RENDERER_CLASS::setCalcCornerFunc(CALC_CORNER_NORMAL_COLOR_UV_TAN_CI_SIZE, calcCornerNormalColorUVTan);
|
|
//RENDERER_CLASS::setCalcVertexFunc(calcVertexNormalNColorUVTan);
|
|
RENDERER_CLASS::setCalcVertexFunc(calcVertexNormalNTexCoord4); // HACKHACK: This is blob specific!
|
|
}
|
|
else if(r_surface_calc_tan_only.GetBool())
|
|
{
|
|
RENDERER_CLASS::setCalcCornerFunc(CALC_CORNER_NORMAL_COLOR_UV_TAN_CI_SIZE, calcCornerNormalColorTanNoUV);
|
|
RENDERER_CLASS::setCalcVertexFunc(calcVertexNormalNColorTanNoUV);
|
|
}
|
|
else if (r_surface_calc_color.GetBool())
|
|
{
|
|
RENDERER_CLASS::setCalcCornerFunc(CALC_CORNER_NORMAL_COLOR_CI_SIZE, calcCornerNormalColor);
|
|
RENDERER_CLASS::setCalcVertexFunc(calcVertexNormalNColor);
|
|
}
|
|
else if (r_surface_calc_hifreq_color.GetBool())
|
|
{
|
|
RENDERER_CLASS::setCalcCornerFunc(CALC_CORNER_NORMAL_COLOR_CI_SIZE, calcCornerNormalHiFreqColor);
|
|
RENDERER_CLASS::setCalcVertexFunc(calcVertexNormalNColor);
|
|
}
|
|
else if (r_surface_calc_tile_color.GetBool())
|
|
{
|
|
RENDERER_CLASS::setCalcCornerFunc(CALC_CORNER_NORMAL_CI_SIZE, calcCornerNormal);
|
|
RENDERER_CLASS::setCalcVertexFunc(calcVertexNormalDebugColor);
|
|
}
|
|
else
|
|
{
|
|
RENDERER_CLASS::setCalcCornerFunc(CALC_CORNER_NORMAL_CI_SIZE, calcCornerNormal);
|
|
RENDERER_CLASS::setCalcVertexFunc(calcVertexNormal);
|
|
}
|
|
}
|
|
|
|
|
|
void TransformParticles( float angle, const Vector& center, Vector& transformedCenter, Vector& transformedEye, VMatrix& rotationMatrix, VMatrix& invRotationMatrix )
|
|
{
|
|
for (int i = 0; i < g_SurfaceRenderParticles.Count(); i++)
|
|
{
|
|
ImpParticleWithFourInterpolants* imp_particle = &(g_SurfaceRenderParticles[i]);
|
|
|
|
Vector vParticle = imp_particle->center.AsVector();
|
|
Vector transformedParticle = vParticle-center;
|
|
|
|
transformedParticle = rotationMatrix.ApplyRotation(transformedParticle);
|
|
|
|
Point3D pParticle = transformedParticle;
|
|
|
|
imp_particle->center = pParticle;
|
|
|
|
// HACK ALERT!!!
|
|
// TODO: This code should not be here as this is very specific to blobs.
|
|
|
|
// interpolants1[0..2] is the color. interpolants1[3] is the v coordinate
|
|
// imp_particle1->interpolants1[3] = MIN(MAX(1.4f - vec.length()/17.0f, 0.0f), 1.0f);
|
|
// interpolants2[0..2] is the tangent vector.
|
|
// interpolants3[0..2] and interpolants4[0..2] are the normal and
|
|
// binormal which are used to generate a u coordinate
|
|
Point3D pCenter = transformedCenter;
|
|
Point3D vec = (pParticle - pCenter);
|
|
|
|
imp_particle->interpolants2 = vec.unit();
|
|
imp_particle->interpolants4.set(0.0f, 0.0f, -1.0f);
|
|
imp_particle->interpolants3 = imp_particle->interpolants2.crossProduct(imp_particle->interpolants4);
|
|
imp_particle->interpolants3.normalize();
|
|
imp_particle->interpolants4 = imp_particle->interpolants2.crossProduct(imp_particle->interpolants3);
|
|
imp_particle->interpolants4.normalize();
|
|
}
|
|
}
|
|
|
|
|
|
void Surface_DrawIsoSurface( IClientRenderable *pClientRenderable, const Vector &vecRenderOrigin, IMaterial *pMaterial, float flCubeWidth )
|
|
{
|
|
IMaterial *pSpecialMaterial = GetDrawMaterial();
|
|
|
|
if( pSpecialMaterial && !IsErrorMaterial( pSpecialMaterial ) )
|
|
{
|
|
pMaterial = pSpecialMaterial;
|
|
}
|
|
|
|
//////////////////////////////////////////////////
|
|
// Set up the render context
|
|
/////////////////////////////////////////////////
|
|
CMatRenderContextPtr pRenderContext( materials );
|
|
pRenderContext->MatrixMode( MATERIAL_MODEL );
|
|
pRenderContext->Bind( pMaterial, pClientRenderable );
|
|
pRenderContext->PushMatrix();
|
|
pRenderContext->LoadIdentity();
|
|
|
|
|
|
////////////////////////////////////////////////////
|
|
// Set up rotations and translations and corresponding matrices.
|
|
////////////////////////////////////////////////////
|
|
Vector transformedCenter = vecRenderOrigin;
|
|
|
|
pRenderContext->Translate(vecRenderOrigin.x, vecRenderOrigin.y, vecRenderOrigin.z);
|
|
|
|
VMatrix rotationMatrix;
|
|
VMatrix invRotationMatrix;
|
|
Vector transformedEye;
|
|
float angle = 0.0f;
|
|
if( r_surface_rotate.GetBool() )
|
|
{
|
|
angle = view->GetViewSetup()->angles.y+180.0f;
|
|
|
|
if( r_surface_rotate_by90.GetBool() )
|
|
{
|
|
// This is a test mode which locks the rotation to a multiple of 90.
|
|
angle = float(int((angle + 45.0f) / 90.0f) * 90);
|
|
}
|
|
|
|
pRenderContext->Rotate(angle, 0.0f, 0.0f, 1.0f);
|
|
|
|
rotationMatrix = SetupMatrixAxisRot(Vector(0.0f, 0.0f, 1.0f), -angle);
|
|
invRotationMatrix = SetupMatrixAxisRot(Vector(0.0f, 0.0f, 1.0f), angle);
|
|
Vector eye = view->GetViewSetup()->origin;
|
|
transformedEye = eye-vecRenderOrigin;
|
|
transformedEye = rotationMatrix.ApplyRotation(transformedEye);
|
|
}
|
|
else
|
|
{
|
|
rotationMatrix.Identity();
|
|
invRotationMatrix.Identity();
|
|
transformedEye.Init();
|
|
angle = 0.0f;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
// Begin Rendering by initializing the sweepRenderer or Tiler
|
|
// (depending on whether we're using the tiler)
|
|
///////////////////////////////////////////////////////////////
|
|
|
|
// TODO: These probably shouldn't be static variables (not thread safe)
|
|
RENDERER_CLASS::setCubeWidth( flCubeWidth * r_surface_blr_scale.GetFloat() * r_surface_blr_cubewidth.GetFloat());
|
|
RENDERER_CLASS::setRenderR( flCubeWidth * r_surface_blr_scale.GetFloat() * r_surface_blr_render_radius.GetFloat());
|
|
RENDERER_CLASS::setCutoffR( flCubeWidth * r_surface_blr_scale.GetFloat() * r_surface_blr_cutoff_radius.GetFloat());
|
|
SetUpImpRendererUserDefinedFuncs();
|
|
|
|
TransformParticles( angle, vecRenderOrigin, transformedCenter, transformedEye, rotationMatrix, invRotationMatrix );
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
// Insert the particles into the tiler/renderer, and do a rendering
|
|
// pass. If we are tiling, we can also visualize the tiles and slices.
|
|
///////////////////////////////////////////////////////////////
|
|
if( r_surface_debug_use_tiler.GetBool() )
|
|
{
|
|
ImpTiler* tiler = ImpTilerFactory::factory->getTiler();
|
|
RENDERER_CLASS* sweepRenderer = tiler->getRenderer();
|
|
|
|
tiler->setMaxNoTilesToDraw(r_surface_debug_max_tiles.GetInt());
|
|
sweepRenderer->setMaxNoSlicesToDraw(r_surface_debug_max_slices.GetInt());
|
|
|
|
// TODO: Do we always want to center the tiler on 0,0,0?
|
|
// I guess if we are centering the render coordinates, then the answer
|
|
// is a yes.
|
|
tiler->beginFrame(Point3D(0.0f, 0.0f, 0.0f), (void*)&pRenderContext, !(r_surface_debug_draw_margin.GetBool()));
|
|
|
|
for (int i = 0; i < g_SurfaceRenderParticles.Count(); i++)
|
|
{
|
|
tiler->insertParticle(&g_SurfaceRenderParticles[i]);
|
|
}
|
|
|
|
if(r_surface_debug_tile.GetBool())
|
|
{
|
|
if(r_surface_rotate.GetBool())
|
|
{
|
|
tiler->drawSurfaceSorted(Point3D(transformedEye));
|
|
}
|
|
else
|
|
{
|
|
tiler->drawSurface();
|
|
}
|
|
|
|
// This is code used for visualizing the boundaries of every tile that's drawn
|
|
// and maybe in the future, slices within the tiles.
|
|
if( r_surface_debug_draw_tile_boundaries.GetBool() == true )
|
|
{
|
|
for( int i = 0; i < tiler->getNoTiles(); i++ )
|
|
{
|
|
Vector overlayCenter = invRotationMatrix.ApplyRotation(tiler->getTileOffset(i).AsVector());
|
|
Vector mins = tiler->getRenderDim().AsVector() * -0.5f;
|
|
Vector maxs = tiler->getRenderDim().AsVector() * 0.5f;
|
|
debugoverlay->AddBoxOverlay(overlayCenter + vecRenderOrigin, mins, maxs, QAngle( 0, angle, 0 ), 0, 255, 0, 0, 0 );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
tiler->drawTile(0,0,0);
|
|
|
|
// This is code used for visualizing the boundaries of the last tile drawn
|
|
// slices within that tile
|
|
if( r_surface_debug_max_tiles.GetInt() > 0 || r_surface_debug_tile.GetBool() == false )
|
|
{
|
|
Vector overlayCenter = invRotationMatrix.ApplyRotation(tiler->getLastTilesOffset().AsVector());
|
|
Vector mins = tiler->getRenderDim().AsVector() * -0.5f;
|
|
Vector maxs = tiler->getRenderDim().AsVector() * 0.5f;
|
|
debugoverlay->AddBoxOverlay(overlayCenter + vecRenderOrigin, mins, maxs, QAngle( 0, angle, 0 ), 0, 255, 0, 0, 0 );
|
|
|
|
if( r_surface_debug_max_slices.GetInt() > 0 )
|
|
{
|
|
Vector sliceMins = mins;
|
|
Vector sliceMaxs = maxs;
|
|
sliceMins.x += (sweepRenderer->getLastSliceDrawn() - sweepRenderer->getMarginNCubes()) * sweepRenderer->getCubeWidth();
|
|
sliceMaxs.x = sliceMins.x + sweepRenderer->getCubeWidth();
|
|
debugoverlay->AddBoxOverlay( overlayCenter + vecRenderOrigin, sliceMins, sliceMaxs, QAngle( 0, angle, 0 ), 255, 0, 0, 0, 0 );
|
|
}
|
|
}
|
|
}
|
|
|
|
tiler->endFrame();
|
|
|
|
ImpTilerFactory::factory->returnTiler(tiler);
|
|
}
|
|
else
|
|
{
|
|
RENDERER_CLASS* sweepRenderer = ImpRendererFactory::factory->getRenderer();
|
|
|
|
// This is the no tiler version. We just draw the center tile.
|
|
sweepRenderer->beginFrame(!(r_surface_debug_draw_margin.GetBool()), (void*)&pRenderContext);
|
|
sweepRenderer->setOffset(Point3D(0.0f, 0.0f, 0.0f));
|
|
sweepRenderer->beginTile(NULL);
|
|
|
|
for (int i = 0; i < g_SurfaceRenderParticles.Count(); i++)
|
|
{
|
|
sweepRenderer->addParticle(&(g_SurfaceRenderParticles[i]));
|
|
}
|
|
|
|
sweepRenderer->endTile();
|
|
sweepRenderer->endFrame();
|
|
|
|
ImpRendererFactory::factory->returnRenderer(sweepRenderer);
|
|
}
|
|
|
|
//////////////////////////////////////
|
|
// Clean up render context
|
|
//////////////////////////////////////
|
|
pRenderContext->PopMatrix();
|
|
}
|
|
|
|
|
|
void Surface_CullOutOfViewParticles( void )
|
|
{
|
|
int iParticlesRemoved = 0;
|
|
|
|
for ( int i = 0; i < g_SurfaceRenderParticles.Count() - iParticlesRemoved; ++i )
|
|
{
|
|
ImpParticleWithOneInterpolant* imp_particle = &(g_SurfaceRenderParticles[ i ]);
|
|
Vector vCenter = Vector( imp_particle->center[ 0 ], imp_particle->center[ 1 ], imp_particle->center[ 2 ] );
|
|
|
|
if ( R_CullSphere( view->GetFrustum(), 5, &vCenter, imp_particle->scale * 24.0f ) )
|
|
{
|
|
ImpParticleWithOneInterpolant* last_particle = &(g_SurfaceRenderParticles[ g_SurfaceRenderParticles.Count() - iParticlesRemoved - 1 ]);
|
|
*imp_particle = *last_particle;
|
|
|
|
++iParticlesRemoved;
|
|
--i;
|
|
}
|
|
}
|
|
|
|
if ( iParticlesRemoved )
|
|
{
|
|
g_SurfaceRenderParticles.SetCountNonDestructively( g_SurfaceRenderParticles.Count() - iParticlesRemoved );
|
|
}
|
|
}
|
|
|
|
|
|
void Surface_Draw( IClientRenderable *pClientRenderable, const Vector &vecRenderOrigin, IMaterial *pMaterial, float flCubeWidth, bool bSurfaceNoParticleCull )
|
|
{
|
|
if ( !bSurfaceNoParticleCull )
|
|
{
|
|
// Reduce the complexity by first removing particles that won't visibly affect the view
|
|
Surface_CullOutOfViewParticles();
|
|
}
|
|
|
|
if ( !r_surface_draw_isosurface.GetBool() )
|
|
{
|
|
// This draws particles as spheres instead of an isosurface
|
|
Surface_DrawSpheres( pMaterial, flCubeWidth );
|
|
}
|
|
else
|
|
{
|
|
Surface_DrawIsoSurface( pClientRenderable, vecRenderOrigin, pMaterial, flCubeWidth );
|
|
}
|
|
}
|
|
|
|
#endif
|