sdk_particle
Jump to navigation
Jump to search
This entity is Obsolete. Its use is discouraged, and it may only exist/function in older engine branches.
sdk_particle is a sample Shader that was provided with the original Source SDK, it has since been replaced by the current set of SDK Shaders.
Warning:This shader relies on deprecated functionality of the materialsystem that has been removed from the Source 2007 SDK and upwards.
sdk_particle_ps11.fxc
sampler BumpmapSampler : register( s0 );
struct PS_INPUT
{
float2 vBumpTexCoord : TEXCOORD0;
float3 vTangentSpaceLightDir : TEXCOORD1;
float4 vDirLightScale : COLOR0;
float3 vAmbientColor : COLOR1;
};
float4 main( PS_INPUT i ) : COLOR
{
float4 baseColor = tex2D( BumpmapSampler, i.vBumpTexCoord );
// Dot the bump normal and the light vector.
float4 vBumpMapNormal = (baseColor - 0.5); // The format of the sphere map is 0 to 1,
// so this is now -0.5 to 0.5.
float3 vTangentSpaceLightDir = (i.vTangentSpaceLightDir - 0.5) * 2; // This is -1 to 1
float4 vOutput = dot( vBumpMapNormal, vTangentSpaceLightDir ) + 0.5;
// Scale by the light color outputted by the vertex shader (ie: based on distance).
vOutput *= i.vDirLightScale;
// Add ambient.
vOutput += float4( i.vAmbientColor.x, i.vAmbientColor.y, i.vAmbientColor.z, 0 );
// Alpha = normal map alpha * vertex alpha
vOutput.a = baseColor.a * i.vDirLightScale.a;
return vOutput;
}
sdk_particle_vs11.fxc
// DYNAMIC: "FOGTYPE" "0..1"
#include "common_vs_fxc.h"
static const int g_FogType = FOGTYPE;
const float4 cCustomConstants[6] : register( SHADER_SPECIFIC_CONST_0 );
const float4 g_vLightPosition : register( SHADER_SPECIFIC_CONST_0 );
const float4 g_vLightColor : register( SHADER_SPECIFIC_CONST_1 ); // range 0-1
const float g_flLightIntensity : register( SHADER_SPECIFIC_CONST_2 ); // scales g_vLightColor
struct VS_INPUT
{
// If this is float4, and the input is float3, the w component default to one.
float4 vPos : POSITION;
float2 vBumpTexCoord : TEXCOORD0;
float4 vAmbientColor : COLOR0;
};
struct VS_OUTPUT
{
float4 projPos : POSITION;
float fog : FOG;
float2 vBumpTexCoord : TEXCOORD0;
float3 vTangentSpaceLightDir : TEXCOORD1;
float4 vDirLightScale : COLOR0;
float3 vAmbientColor : COLOR1;
};
VS_OUTPUT main( const VS_INPUT v )
{
VS_OUTPUT o;
// Transform the input position.
float4 projPos = mul( v.vPos, cModelViewProj );
o.projPos = projPos;
// Setup fog.
o.fog = CalcFog( mul( v.vPos, cModel[0] ), projPos, g_FogType );
// Copy texcoords over.
o.vBumpTexCoord = v.vBumpTexCoord;
// Copy the vertex color over.
o.vAmbientColor = v.vAmbientColor;
// ------------------------------------------------------------------------------
// Generate a tangent space and rotate L.
// This can be thought of as rotating the normal map to face the viewer.
//
// This is useful when a particle is way off to the side of the screen.
// You should be looking at the half-sphere with a normal pointing from the
// particle to the viewer. Instead, you're looking at the half-sphere with
// a normal along Z. This tangent space builder code fixes the problem.
//
// Note that since the model and view matrices are identity, the coordinate
// system has X=right, Y=up, and Z=behind you (negative Z goes into the screen).
// ------------------------------------------------------------------------------
// This basis wants Z positive going into the screen so flip it here.
float4 vForward = normalize( float4( v.vPos.x, v.vPos.y, -v.vPos.z, 1 ) );
// This is the same as CrossProduct( vForward, Vector( 1, 0, 0 ) )
float4 vUp = normalize( float4( 0, vForward.z, -vForward.y, vForward.w ) );
// vRight = CrossProduct( vUp, vForward )
float4 vRight = vUp.yzxw * vForward.zxyw;
vRight += -vUp.zxyw * vForward.yzxw;
// Put the light in tangent space.
float4 vToLight = g_vLightPosition - v.vPos;
float4 vTangentSpaceLight = vRight*vToLight.x + vUp*vToLight.y + vForward*vToLight.z;
// Output texcoord 1 holds the normalized transformed light direction.
o.vTangentSpaceLightDir = normalize( vTangentSpaceLight ) * 0.5 + 0.5; // make it 0-1 for the pixel shader
// Handle oversaturation here. The shader code already scaled the light color so its max value is 1,
// so if our intensity/distance scale is > 1, then all we need to do is use the light color.
float flTransposedLenSqr = dot( vTangentSpaceLight, vTangentSpaceLight );
float flScaledIntensity = g_flLightIntensity / flTransposedLenSqr;
if ( flScaledIntensity > 1 )
{
o.vDirLightScale.xyz = g_vLightColor;
}
else
{
o.vDirLightScale.xyz = g_vLightColor * flScaledIntensity;
}
// Alpha comes right from the vertex color.
o.vDirLightScale.a = v.vAmbientColor.a;
return o;
}
sdk_particle.cpp
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Header: $
// $NoKeywords: $
//=============================================================================//
#include "BaseVSShader.h"
#include "sdk_particle_vs11.inc"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
BEGIN_VS_SHADER( SDK_Particle,
"Help for SDK_Particle" )
BEGIN_SHADER_PARAMS
SHADER_PARAM( USINGPIXELSHADER, SHADER_PARAM_TYPE_BOOL, "0", "Tells to client code whether the shader is using DX8 vertex/pixel shaders or not" )
SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "base texture" )
SHADER_PARAM( LIGHTS, SHADER_PARAM_TYPE_FOURCC, "", "array of lights" )
SHADER_PARAM( LIGHT_POSITION, SHADER_PARAM_TYPE_VEC3, "0 0 0", "This is the directional light position." )
SHADER_PARAM( LIGHT_COLOR, SHADER_PARAM_TYPE_VEC3, "1 1 1", "This is the directional light color." )
END_SHADER_PARAMS
bool UsePixelShaders( IMaterialVar **params ) const
{
return params[BUMPMAP]->IsDefined() && g_pHardwareConfig->SupportsVertexAndPixelShaders();
}
SHADER_INIT
{
// If this would return false, then we should have fallen back to the DX6 one.
Assert( UsePixelShaders( params ) );
params[USINGPIXELSHADER]->SetIntValue( true );
LoadBumpMap( BUMPMAP );
}
SHADER_FALLBACK
{
// If their hardware doesn't support pixel shaders, or if there is
// no bump map specified in the materal, then fall back to a simple shader.
if( !UsePixelShaders(params) )
{
return "UnlitGeneric_DX6";
}
return 0;
}
SHADER_DRAW
{
SHADOW_STATE
{
pShaderShadow->EnableTexture( SHADER_TEXTURE_STAGE0, true );
int tCoordDimensions[] = {2};
pShaderShadow->VertexShaderVertexFormat(
VERTEX_POSITION | VERTEX_COLOR, 1, tCoordDimensions, 0, 0 );
pShaderShadow->EnableBlending( true );
pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA );
pShaderShadow->EnableDepthWrites( false );
sdk_particle_vs11_Static_Index vshIndex;
pShaderShadow->SetVertexShader( "sdk_particle_vs11", vshIndex.GetIndex() );
pShaderShadow->SetPixelShader( "sdk_particle_ps11" );
FogToFogColor();
}
DYNAMIC_STATE
{
BindTexture( SHADER_TEXTURE_STAGE0, BUMPMAP );
pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, params[LIGHT_POSITION]->GetVecValue() );
// Separate the light color into something that has a max value of 1 and a scale
// so the vertex shader can determine if it's going to overflow the color and scale back
// if it needs to.
//
// (It does this by seeing if the intensity*1/distSqr is > 1. If so, then it scales it so
// it is equal to 1).
const float *f = params[LIGHT_COLOR]->GetVecValue();
Vector vLightColor( f[0], f[1], f[2] );
float flScale = max( vLightColor.x, max( vLightColor.y, vLightColor.z ) );
if ( flScale < 0.01f )
flScale = 0.01f;
float vScaleVec[3] = { flScale, flScale, flScale };
vLightColor /= flScale;
pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, vLightColor.Base() );
pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, vScaleVec );
// Compute the vertex shader index.
sdk_particle_vs11_Dynamic_Index vshIndex;
vshIndex.SetFOGTYPE( s_pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z );
s_pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() );
}
Draw();
}
END_SHADER