Exemplo n.º 1
0
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : flags - 
// Output : int
//-----------------------------------------------------------------------------
int CSprite::DrawModel( int flags, const RenderableInstance_t &instance )
{
	VPROF_BUDGET( "CSprite::DrawModel", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
	//See if we should draw
	if ( !IsVisible() || ( m_bReadyToDraw == false ) )
		return 0;



	// Tracker 16432:  If rendering a savegame screenshot then don't draw sprites 
	//   who have viewmodels as their moveparent
	if ( g_bRenderingScreenshot || !r_drawviewmodel.GetBool() )
	{
		C_BaseViewModel *vm = ToBaseViewModel( GetMoveParent() );
		if ( vm )
		{
			return 0;
		}
	}

	//Must be a sprite
	if ( modelinfo->GetModelType( GetModel() ) != mod_sprite )
	{
		const char *modelName = modelinfo->GetModelName( GetModel() );
		char msg[256];
		V_snprintf( msg, 256, "Sprite %d has non-mod_sprite model %s (type %d)\n",
			entindex(), modelName, modelinfo->GetModelType( GetModel() ) );
		AssertMsgOnce( 0, msg );
		return 0;
	}

	float renderscale = GetRenderScale();
	if ( m_bWorldSpaceScale )
	{
		CEngineSprite *psprite = ( CEngineSprite * )modelinfo->GetModelExtraData( GetModel() );
		float flMinSize = MIN( psprite->GetWidth(), psprite->GetHeight() );
		renderscale /= flMinSize;
	}

	//Draw it
	int drawn = DrawSprite( 
		this,
		GetModel(), 
		GetAbsOrigin(), 
		GetAbsAngles(), 
		m_flFrame,				// sprite frame to render
		m_hAttachedToEntity,	// attach to
		m_nAttachment,			// attachment point
		GetRenderMode(),		// rendermode
		GetRenderFX(),
		(float)( GetRenderBrightness() * instance.m_nAlpha ) * ( 1.0f / 255.0f ) + 0.5f,	// alpha
		GetRenderColorR(),
		GetRenderColorG(),
		GetRenderColorB(),
		renderscale,			// sprite scale
		GetHDRColorScale()		// HDR Color Scale
		);

	return drawn;
}
Exemplo n.º 2
0
//-----------------------------------------------------------------------------
// Purpose: Retrieve sprite object and set it up for rendering
// Input  : *pSpriteModel - 
//			frame - 
//			rendermode - 
// Output : CEngineSprite
//-----------------------------------------------------------------------------
CEngineSprite *Draw_SetSpriteTexture( const model_t *pSpriteModel, int frame, int rendermode )
{
	CEngineSprite			*psprite;
	IMaterial		*material;

	psprite = ( CEngineSprite * )modelinfo->GetModelExtraData( pSpriteModel );
	Assert( psprite );

	material = psprite->GetMaterial();
	if( !material )
		return NULL;
	
	CMatRenderContextPtr pRenderContext( materials );
	if ( ShouldDrawInWireFrameMode() || r_DrawBeams.GetInt() == 2 )
	{
		if ( !g_pBeamWireframeMaterial )
			g_pBeamWireframeMaterial = materials->FindMaterial( "shadertest/wireframevertexcolor", TEXTURE_GROUP_OTHER );
		pRenderContext->Bind( g_pBeamWireframeMaterial, NULL );
		return psprite;
	}
	
	psprite->SetFrame( frame );
	psprite->SetRenderMode( rendermode );

	pRenderContext->Bind( material );
	return psprite;
}
bool CClientTools::DrawSprite( IClientRenderable *pRenderable, float scale, float frame, int rendermode, int renderfx, const Color &color, float flProxyRadius, int *pVisHandle )
{
	Vector origin = pRenderable->GetRenderOrigin();
	QAngle angles = pRenderable->GetRenderAngles();

	// Get extra data
	CEngineSprite *psprite = (CEngineSprite *)modelinfo->GetModelExtraData( pRenderable->GetModel() );
	if ( !psprite )
		return false;

	// Get orthonormal bases for current view - re-align to current camera (vs. recorded camera)
	Vector forward, right, up;
	C_SpriteRenderer::GetSpriteAxes( ( C_SpriteRenderer::SPRITETYPE )psprite->GetOrientation(), origin, angles, forward, right, up );

	int r = color.r();
	int g = color.g();
	int b = color.b();

	float oldBlend = render->GetBlend();
	if ( rendermode != kRenderNormal )
	{
		// kRenderGlow and kRenderWorldGlow have a special blending function
		if (( rendermode == kRenderGlow ) || ( rendermode == kRenderWorldGlow ))
		{
			pixelvis_queryparams_t params;
			if ( flProxyRadius != 0.0f )
			{
				params.Init( origin, flProxyRadius );
				params.bSizeInScreenspace = true;
			}
			else
			{
				params.Init( origin );
			}
			float blend = oldBlend * StandardGlowBlend( params, ( pixelvis_handle_t* )pVisHandle, rendermode, renderfx, color.a(), &scale );

			if ( blend <= 0.0f )
				return false;

			//Fade out the sprite depending on distance from the view origin.
			r *= blend;
			g *= blend;
			b *= blend;

			render->SetBlend( blend );
		}
	}

	DrawSpriteModel( ( IClientEntity* )pRenderable, psprite, origin, scale, frame, rendermode, r, g, b, color.a(), forward, right, up );

	if (( rendermode == kRenderGlow ) || ( rendermode == kRenderWorldGlow ))
	{
		render->SetBlend( oldBlend );
	}

	return true;
}
Exemplo n.º 4
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CSprite::GetToolRecordingState( KeyValues *msg )
{
	if ( !ToolsEnabled() )
		return;

	VPROF_BUDGET( "CSprite::GetToolRecordingState", VPROF_BUDGETGROUP_TOOLS );

	BaseClass::GetToolRecordingState( msg );

	// Use attachment point
	if ( m_hAttachedToEntity )
	{
		C_BaseEntity *ent = m_hAttachedToEntity->GetBaseEntity();
		if ( ent )
		{
			BaseEntityRecordingState_t *pState = (BaseEntityRecordingState_t*)msg->GetPtr( "baseentity" );

			// override position if we're driven by an attachment
			QAngle temp;
			pState->m_vecRenderOrigin = GetAbsOrigin();
			ent->GetAttachment( m_nAttachment, pState->m_vecRenderOrigin, temp );

			// override viewmodel if we're driven by an attachment
			bool bViewModel = ToBaseViewModel( ent ) != NULL;
			msg->SetInt( "viewmodel", bViewModel );
		}
	}

	float renderscale = GetRenderScale();
	if ( m_bWorldSpaceScale )
	{
		CEngineSprite *psprite = ( CEngineSprite * )modelinfo->GetModelExtraData( GetModel() );
		float flMinSize = MIN( psprite->GetWidth(), psprite->GetHeight() );
		renderscale /= flMinSize;
	}

	color24 c = GetRenderColor();

	// sprite params
	static SpriteRecordingState_t state;
	state.m_flRenderScale = renderscale;
	state.m_flFrame = m_flFrame;
	state.m_flProxyRadius = m_flGlowProxySize;
	state.m_nRenderMode = GetRenderMode();
	state.m_nRenderFX = GetRenderFX() ? true : false;
	state.m_Color.SetColor( c.r, c.g, c.b, GetRenderBrightness() );

	msg->SetPtr( "sprite", &state );
}
Exemplo n.º 5
0
//-----------------------------------------------------------------------------
// Purpose: Get the rendered extents of the sprite
//-----------------------------------------------------------------------------
void CSprite::GetRenderBounds( Vector &vecMins, Vector &vecMaxs )
{
	float flScale = GetRenderScale() * 0.5f;

	// If our scale is normalized we need to convert that to actual world units
	if ( m_bWorldSpaceScale == false )
	{
		CEngineSprite *psprite = (CEngineSprite *) modelinfo->GetModelExtraData( GetModel() );
		if ( psprite )
		{
			float flSize = MAX( psprite->GetWidth(), psprite->GetHeight() );
			flScale *= flSize;
		}
	}

	vecMins.Init( -flScale, -flScale, -flScale );
	vecMaxs.Init(  flScale,  flScale,  flScale );

#if 0
	// Visualize the bounds
	debugoverlay->AddBoxOverlay( GetRenderOrigin(), vecMins, vecMaxs, GetRenderAngles(), 255, 255, 255, 0, 0.01f );
#endif
}
Exemplo n.º 6
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
int CSpriteTrail::DrawModel( int flags )
{
	VPROF_BUDGET( "CSpriteTrail::DrawModel", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
	
	// Must have at least one point
	if ( m_nStepCount < 1 )
		return 1;

	//See if we should draw
	if ( !IsVisible() || ( m_bReadyToDraw == false ) )
		return 0;

	CEngineSprite *pSprite = Draw_SetSpriteTexture( GetModel(), m_flFrame, GetRenderMode() );
	if ( pSprite == NULL )
		return 0;

	// Specify all the segments.
	CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
	CBeamSegDraw segDraw;
	segDraw.Start( pRenderContext, m_nStepCount + 1, pSprite->GetMaterial() );
	
	// Setup the first point, always emanating from the attachment point
	TrailPoint_t *pLast = GetTrailPoint( m_nStepCount-1 );
	TrailPoint_t currentPoint;
	currentPoint.m_flDieTime = gpGlobals->curtime + m_flLifeTime;
	ComputeScreenPosition( &currentPoint.m_vecScreenPos );
	currentPoint.m_flTexCoord = pLast->m_flTexCoord + currentPoint.m_vecScreenPos.DistTo(pLast->m_vecScreenPos) * m_flTextureRes;
	currentPoint.m_flWidthVariance = 0.0f;

#if SCREEN_SPACE_TRAILS
	VMatrix	viewMatrix;
	materials->GetMatrix( MATERIAL_VIEW, &viewMatrix );
	viewMatrix = viewMatrix.InverseTR();
#endif

	TrailPoint_t *pPrevPoint = NULL;
	float flTailAlphaDist = m_flMinFadeLength;
	for ( int i = 0; i <= m_nStepCount; ++i )
	{
		// This makes it so that we're always drawing to the current location
		TrailPoint_t *pPoint = (i != m_nStepCount) ? GetTrailPoint(i) : &currentPoint;

		float flLifePerc = (pPoint->m_flDieTime - gpGlobals->curtime) / m_flLifeTime;
		flLifePerc = clamp( flLifePerc, 0.0f, 1.0f );

		BeamSeg_t curSeg;
		curSeg.m_vColor.x = (float) m_clrRender->r / 255.0f;
		curSeg.m_vColor.y = (float) m_clrRender->g / 255.0f;
		curSeg.m_vColor.z = (float) m_clrRender->b / 255.0f;

		float flAlphaFade = flLifePerc;
		if ( flTailAlphaDist > 0.0f )
		{
			if ( pPrevPoint )
			{
				float flDist = pPoint->m_vecScreenPos.DistTo( pPrevPoint->m_vecScreenPos );
				flTailAlphaDist -= flDist;
			}

			if ( flTailAlphaDist > 0.0f )
			{
				float flTailFade = Lerp( (m_flMinFadeLength - flTailAlphaDist) / m_flMinFadeLength, 0.0f, 1.0f );
				if ( flTailFade < flAlphaFade )
				{
					flAlphaFade = flTailFade;
				}
			}
		}
		curSeg.m_flAlpha  = ( (float) GetRenderBrightness() / 255.0f ) * flAlphaFade;

#if SCREEN_SPACE_TRAILS
		curSeg.m_vPos = viewMatrix * pPoint->m_vecScreenPos;
#else
		curSeg.m_vPos = pPoint->m_vecScreenPos;
#endif

		if ( m_flEndWidth >= 0.0f )
		{
			curSeg.m_flWidth = Lerp( flLifePerc, m_flEndWidth.Get(), m_flStartWidth.Get() );
		}
		else
		{
			curSeg.m_flWidth = m_flStartWidth.Get();
		}
		curSeg.m_flWidth += pPoint->m_flWidthVariance;
		if ( curSeg.m_flWidth < 0.0f )
		{
			curSeg.m_flWidth = 0.0f;
		}

		curSeg.m_flTexCoord = pPoint->m_flTexCoord;

		segDraw.NextSeg( &curSeg );

		// See if we're done with this bad boy
		if ( pPoint->m_flDieTime <= gpGlobals->curtime )
		{
			// Push this back onto the top for use
			++m_nFirstStep;
			--i;
			--m_nStepCount;
		}

		pPrevPoint = pPoint;
	}

	segDraw.End();

	return 1;
}
Exemplo n.º 7
0
//-----------------------------------------------------------------------------
// Purpose: 
// Output : int
//-----------------------------------------------------------------------------
int C_SpriteRenderer::DrawSprite( 
	IClientEntity *entity,
	const model_t *model, 
	const Vector& origin, 
	const QAngle& angles,
	float frame,
	IClientEntity *attachedto,
	int attachmentindex,
	int rendermode,
	int renderfx,
	int alpha,
	int r, 
	int g, 
	int b,
	float scale,
	float flHDRColorScale
	)
{
	VPROF_BUDGET( "C_SpriteRenderer::DrawSprite", VPROF_BUDGETGROUP_PARTICLE_RENDERING );

	if ( !r_drawsprites.GetBool() || !model || modelinfo->GetModelType( model ) != mod_sprite )
	{
		return 0;
	}

	// Get extra data
	CEngineSprite *psprite = (CEngineSprite *)modelinfo->GetModelExtraData( model );
	if ( !psprite )
	{
		return 0;
	}

	Vector effect_origin;
	VectorCopy( origin, effect_origin );

	// Use attachment point
	if ( attachedto )
	{
		C_BaseEntity *ent = attachedto->GetBaseEntity();
		if ( ent )
		{
			// don't draw viewmodel effects in reflections
			if ( CurrentViewID() == VIEW_REFLECTION )
			{
				if ( g_pClientLeafSystem->IsRenderingWithViewModels( ent->RenderHandle() ) )
					return 0;
			}
			QAngle temp;
			ent->GetAttachment( attachmentindex, effect_origin, temp );
		}
	}

	if ( rendermode != kRenderNormal )
	{
		float blend = render->GetBlend();

		// kRenderGlow and kRenderWorldGlow have a special blending function
		if (( rendermode == kRenderGlow ) || ( rendermode == kRenderWorldGlow ))
		{
			blend *= GlowBlend( psprite, effect_origin, rendermode, renderfx, alpha, &scale );

			// Fade out the sprite depending on distance from the view origin.
			r *= blend;
			g *= blend;
			b *= blend;
		}

		render->SetBlend( blend );
		if ( blend <= 0.0f )
		{
			return 0;
		}
	}
	
	// Get orthonormal basis
	Vector forward, right, up;
	GetSpriteAxes( (SPRITETYPE)psprite->GetOrientation(), origin, angles, forward, right, up );

	// Draw
	DrawSpriteModel( 
		entity,
		psprite, 
		effect_origin,
		scale,
		frame, 
		rendermode, 
		r, 
		g, 
		b,
		alpha, 
		forward, right, up, flHDRColorScale );

	return 1;
}
Exemplo n.º 8
0
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : noise_divisions - 
//			*prgNoise - 
//			*spritemodel - 
//			frame - 
//			rendermode - 
//			source - 
//			delta - 
//			flags - 
//			*color - 
//			fadescale - 
//-----------------------------------------------------------------------------
void DrawSegs( int noise_divisions, float *prgNoise, const model_t* spritemodel,
				float frame, int rendermode, const Vector& source, const Vector& delta, 
				float startWidth, float endWidth, float scale, float freq, float speed, int segments,
				int flags, float* color, float fadeLength, float flHDRColorScale )
{
	int				i, noiseIndex, noiseStep;
	float			div, length, fraction, factor, vLast, vStep, brightness;
	
	Assert( fadeLength >= 0.0f );
	CEngineSprite *pSprite = Draw_SetSpriteTexture( spritemodel, frame, rendermode );
	if ( !pSprite )
		return;

	if ( segments < 2 )
		return;

	IMaterial *pMaterial = pSprite->GetMaterial( (RenderMode_t)rendermode );
	if( pMaterial )
	{
		static unsigned int nHDRColorScaleCache = 0;
		IMaterialVar *pHDRColorScaleVar = pMaterial->FindVarFast( "$hdrcolorscale", &nHDRColorScaleCache );
		if( pHDRColorScaleVar )
		{
			pHDRColorScaleVar->SetFloatValue( flHDRColorScale );
		}
	}
	
	length = VectorLength( delta );
	float flMaxWidth = MAX(startWidth, endWidth) * 0.5f;
	div = 1.0 / (segments-1);

	if ( length*div < flMaxWidth * 1.414 )
	{
		// Here, we have too many segments; we could get overlap... so lets have less segments
		segments = (int)(length / (flMaxWidth * 1.414)) + 1;
		if ( segments < 2 )
		{
			segments = 2;
		}
	}

	if ( segments > noise_divisions )		// UNDONE: Allow more segments?
	{
		segments = noise_divisions;
	}

	div = 1.0 / (segments-1);
	length *= 0.01;

	// UNDONE: Expose texture length scale factor to control "fuzziness"

	if ( flags & FBEAM_NOTILE )
	{
		// Don't tile
		vStep = div;
	}
	else
	{
		// Texture length texels per space pixel
		vStep = length*div;	
	}
	
	// UNDONE: Expose this paramter as well(3.5)?  Texture scroll rate along beam
	vLast = fmod(freq*speed,1);	// Scroll speed 3.5 -- initial texture position, scrolls 3.5/sec (1.0 is entire texture)

	if ( flags & FBEAM_SINENOISE )
	{
		if ( segments < 16 )
		{
			segments = 16;
			div = 1.0 / (segments-1);
		}
		scale *= 100;
		length = segments * (1.0/10);
	}
	else
	{
		scale *= length;
	}

	// Iterator to resample noise waveform (it needs to be generated in powers of 2)
	noiseStep = (int)((float)(noise_divisions-1) * div * 65536.0f);
	noiseIndex = 0;
	
	if ( flags & FBEAM_SINENOISE )
	{
		noiseIndex = 0;
	}

	brightness = 1.0;
	if ( flags & FBEAM_SHADEIN )
	{
		brightness = 0;
	}

	// What fraction of beam should be faded
	Assert( fadeLength >= 0.0f );
	float fadeFraction = fadeLength/ delta.Length();
	
	// BUGBUG: This code generates NANs when fadeFraction is zero! REVIST!
	fadeFraction = clamp(fadeFraction,1.e-6f,1.f);

	// Choose two vectors that are perpendicular to the beam
	Vector perp1;
	ComputeBeamPerpendicular( delta, &perp1 );

	// Specify all the segments.
	CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
	CBeamSegDraw segDraw;
	segDraw.Start( pRenderContext, segments, NULL );

	for ( i = 0; i < segments; i++ )
	{
		Assert( noiseIndex < (noise_divisions<<16) );
		BeamSeg_t curSeg;
		curSeg.m_flAlpha = 1;

		fraction = i * div;

		// Fade in our out beam to fadeLength

		if ( (flags & FBEAM_SHADEIN) && (flags & FBEAM_SHADEOUT) )
		{
			if (fraction < 0.5)
			{
				brightness = 2*(fraction/fadeFraction);
			}
			else
			{
				brightness = 2*(1.0 - (fraction/fadeFraction));
			}
		}
		else if ( flags & FBEAM_SHADEIN )
		{
			brightness = fraction/fadeFraction;
		}
		else if ( flags & FBEAM_SHADEOUT )
		{
			brightness = 1.0 - (fraction/fadeFraction);
		}

		// clamps
		if (brightness < 0 )		
		{
			brightness = 0;
		}
		else if (brightness > 1)		
		{
			brightness = 1;
		}

		VectorScale( *((Vector*)color), brightness, curSeg.m_vColor );

		// UNDONE: Make this a spline instead of just a line?
		VectorMA( source, fraction, delta, curSeg.m_vPos );
 
		// Distort using noise
		if ( scale != 0 )
		{
			factor = prgNoise[noiseIndex>>16] * scale;
			if ( flags & FBEAM_SINENOISE )
			{
				float	s, c;
				SinCos( fraction*M_PI*length + freq, &s, &c );
				VectorMA( curSeg.m_vPos, factor * s, CurrentViewUp(), curSeg.m_vPos );
				// Rotate the noise along the perpendicluar axis a bit to keep the bolt from looking diagonal
				VectorMA( curSeg.m_vPos, factor * c, CurrentViewRight(), curSeg.m_vPos );
			}
			else
			{
				VectorMA( curSeg.m_vPos, factor, perp1, curSeg.m_vPos );
			}
		}

		// Specify the next segment.
		if( endWidth == startWidth )
		{
			curSeg.m_flWidth = startWidth * 2;
		}
		else
		{
			curSeg.m_flWidth = ((fraction*(endWidth-startWidth))+startWidth) * 2;
		}
		
		curSeg.m_flTexCoord = vLast;
		segDraw.NextSeg( &curSeg );


		vLast += vStep;	// Advance texture scroll (v axis only)
		noiseIndex += noiseStep;
	}
Exemplo n.º 9
0
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : flags - 
// Output : int
//-----------------------------------------------------------------------------
int CSprite::DrawModel( int flags )
{
	VPROF_BUDGET( "CSprite::DrawModel", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
	//See if we should draw
	if ( !IsVisible() || ( m_bReadyToDraw == false ) )
		return 0;

#ifdef PORTAL
	if ( ( !g_pPortalRender->IsRenderingPortal() && !m_bDrawInMainRender ) || 
		( g_pPortalRender->IsRenderingPortal() && !m_bDrawInPortalRender ) )
	{
		return 0;
	}
#endif //#ifdef PORTAL

	// Tracker 16432:  If rendering a savegame screenshot then don't draw sprites 
	//   who have viewmodels as their moveparent
	if ( g_bRenderingScreenshot || !r_drawviewmodel.GetBool() )
	{
		C_BaseViewModel *vm = dynamic_cast< C_BaseViewModel * >( GetMoveParent() );
		if ( vm )
		{
			return 0;
		}
	}

	//Must be a sprite
	if ( modelinfo->GetModelType( GetModel() ) != mod_sprite )
	{
		Assert( 0 );
		return 0;
	}

	float renderscale = GetRenderScale();
	if ( m_bWorldSpaceScale )
	{
		CEngineSprite *psprite = ( CEngineSprite * )modelinfo->GetModelExtraData( GetModel() );
		float flMinSize = MIN( psprite->GetWidth(), psprite->GetHeight() );
		renderscale /= flMinSize;
	}

	//Draw it
	int drawn = DrawSprite( 
		this,
		GetModel(), 
		GetAbsOrigin(), 
		GetAbsAngles(), 
		m_flFrame,				// sprite frame to render
		m_hAttachedToEntity,	// attach to
		m_nAttachment,			// attachment point
		GetRenderMode(),		// rendermode
		m_nRenderFX,
		GetRenderBrightness(),	// alpha
		m_clrRender->r,
		m_clrRender->g,
		m_clrRender->b,
		renderscale,			// sprite scale
		GetHDRColorScale()		// HDR Color Scale
		);

	return drawn;
}
Exemplo n.º 10
0
//-----------------------------------------------------------------------------
// Purpose: 
// Output : int
//-----------------------------------------------------------------------------
int C_SpriteRenderer::DrawSprite( 
	IClientEntity *entity,
	const model_t *model, 
	const Vector& origin, 
	const QAngle& angles,
	float frame,
	IClientEntity *attachedto,
	int attachmentindex,
	int rendermode,
	int renderfx,
	int alpha,
	int r, 
	int g, 
	int b,
	float scale,
	float flHDRColorScale
	)
{
	VPROF_BUDGET( "C_SpriteRenderer::DrawSprite", VPROF_BUDGETGROUP_PARTICLE_RENDERING );

	if ( !r_drawsprites.GetBool() || !model || modelinfo->GetModelType( model ) != mod_sprite )
		return 0;

	// Get extra data
	CEngineSprite *psprite = (CEngineSprite *)modelinfo->GetModelExtraData(model);

	if ( !psprite )
		return 0;

	Vector effect_origin;
	VectorCopy(origin, effect_origin);

	// Use attachment point
	if ( attachedto )
	{
		C_BaseEntity *ent = attachedto->GetBaseEntity();

		if ( ent )
		{
			if ( ent->GetBaseAnimating() && ent->GetBaseAnimating()->IsViewModel() && ::input->CAM_IsThirdPersonOverShoulder() )
			{
				C_BaseViewModel *pVm = (C_BaseViewModel*)ent;
				C_BasePlayer *pOwner = ( pVm->GetOwner() && pVm->GetOwner()->IsPlayer() ) ? (C_BasePlayer*)pVm->GetOwner() : NULL;

				if ( pOwner && pOwner->GetActiveWeapon() )
					return 0; //worldmodels don't have the same attachments, so just get out (crossbow)
			}

			// don't draw viewmodel effects in reflections
			if ( CurrentViewID() == VIEW_REFLECTION )
			{
				int group = ent->GetRenderGroup();

				if ( group == RENDER_GROUP_VIEW_MODEL_TRANSLUCENT || group == RENDER_GROUP_VIEW_MODEL_OPAQUE )
					return 0;
			}

			QAngle temp;
			ent->GetAttachment(attachmentindex, effect_origin, temp);
		}
	}

	if ( rendermode != kRenderNormal )
	{
		float blend = render->GetBlend();

		// kRenderGlow and kRenderWorldGlow have a special blending function
		if (( rendermode == kRenderGlow ) || ( rendermode == kRenderWorldGlow ))
		{
			blend *= GlowBlend( psprite, effect_origin, rendermode, renderfx, alpha, &scale );

			// Fade out the sprite depending on distance from the view origin.
			r *= blend;
			g *= blend;
			b *= blend;
		}

		render->SetBlend( blend );
		if ( blend <= 0.0f )
		{
			return 0;
		}
	}
	
	// Get orthonormal basis
	Vector forward, right, up;
	GetSpriteAxes( (SPRITETYPE)psprite->GetOrientation(), origin, angles, forward, right, up );

	// Draw
	DrawSpriteModel( 
		entity,
		psprite, 
		effect_origin,
		scale,
		frame, 
		rendermode, 
		r, 
		g, 
		b,
		alpha, 
		forward, right, up, flHDRColorScale );

	return 1;
}