sdk_particle
Jump to navigation
Jump to search
Warning:This shader relies on deprecated functionality of the materialsystem that has been removed from the Source 2007 SDK and upwards.

This entity is obsolete. Its use is discouraged. 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.

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