Sdk particle: Difference between revisions

From Valve Developer Community
Jump to navigation Jump to search
(Created page with '{{wrongtitle|sdk_lightmap}} sdk_lightmap is a sample Shader that was provided with the original Source SDK, it has since been replaced by the current set of SDK Shaders. == …')
 
(Added obsolete template)
 
(7 intermediate revisions by 4 users not shown)
Line 1: Line 1:
{{wrongtitle|sdk_lightmap}}
{{obsolete|shader=1}}
sdk_lightmap is a sample [[Shader]] that was provided with the original Source SDK, it has since been replaced by the current set of SDK Shaders.
{{DISPLAYTITLE:sdk_particle}}
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_lightmap_ps20.fxc ==
{{warning|This shader relies on deprecated functionality of the materialsystem that has been removed from the [[Orange_Box|Source 2007 SDK]] and upwards.}}
<source lang=cpp>#include "common_ps_fxc.h"


sampler BaseTextureSampler : register( s0 );
== sdk_particle_ps11.fxc ==
sampler LightmapSampler : register( s1 );
<source lang=cpp>sampler BumpmapSampler : register( s0 );


struct PS_INPUT
struct PS_INPUT
{
{
HALF2 vBaseTexCoord : TEXCOORD0;
float2 vBumpTexCoord : TEXCOORD0;
HALF2 vLightmapTexCoord : TEXCOORD1;
float3 vTangentSpaceLightDir : TEXCOORD1;
float4 vDirLightScale : COLOR0;
float3 vAmbientColor : COLOR1;
};
};


HALF4 main( PS_INPUT i ) : COLOR
float4 main( PS_INPUT i ) : COLOR
{
{
// Sample the texture and lightmap.
float4 baseColor = tex2D( BumpmapSampler, i.vBumpTexCoord );
HALF4 baseColor = tex2D( BaseTextureSampler, i.vBaseTexCoord );
HALF4 lightmapSample = tex2D( LightmapSampler, i.vLightmapTexCoord );
// Multiply the base and lightmap colors.
// Dot the bump normal and the light vector.
baseColor *= lightmapSample;
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;
return baseColor;
// 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;
}</source>
}</source>


== sdk_lightmap_vs20.fxc ==
== sdk_particle_vs11.fxc ==
<source lang=cpp>#include "common_vs_fxc.h"
<source lang=cpp>// 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
struct VS_INPUT
{
{
float3 vPos : POSITION;
// If this is float4, and the input is float3, the w component default to one.
float2 vBaseTexCoord : TEXCOORD0;
float4 vPos : POSITION;  
float2 vLightmapTexCoord : TEXCOORD1;
float2 vBumpTexCoord : TEXCOORD0;
float4 vAmbientColor : COLOR0;
};
};


struct VS_OUTPUT
struct VS_OUTPUT
{
{
     float4 vProjPos : POSITION;
     float4 projPos : POSITION;
float  flFog : FOG;
float  fog : FOG;
float2 vBaseTexCoord : TEXCOORD0;
float2 vLightmapTexCoord : TEXCOORD2;
float2 vBumpTexCoord : TEXCOORD0;
float3 vTangentSpaceLightDir : TEXCOORD1;
float4 vDirLightScale : COLOR0;
float3 vAmbientColor : COLOR1;
};
};


VS_OUTPUT main( const VS_INPUT v )
VS_OUTPUT main( const VS_INPUT v )
{
{
VS_OUTPUT o = ( VS_OUTPUT )0;
VS_OUTPUT o;


// Project the point.
// Transform the input position.
float4 vProjPos = mul( float4( v.vPos, 1 ), cModelViewProj );
float4 projPos = mul( v.vPos, cModelViewProj );
o.vProjPos = vProjPos;
o.projPos = projPos;


// Pass texture coordinates through to the pixel shader.
// Setup fog.
o.vBaseTexCoord = v.vBaseTexCoord;
o.fog = CalcFog( mul( v.vPos, cModel[0] ), projPos, g_FogType );
o.vLightmapTexCoord = v.vLightmapTexCoord;


// Calculate the fog.
// Copy texcoords over.
float3 worldPos = mul( float4( v.vPos, 1 ), cModel[0] );
o.vBumpTexCoord = v.vBumpTexCoord;
o.flFog = 0;


// 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;
return o;
}</source>
}</source>


== sdk_lightmap.cpp ==
== sdk_particle.cpp ==
<source lang=cpp>//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
<source lang=cpp>//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
//
// Purpose: Just about as simple as a shader gets. Specify a vertex
// Purpose:  
//          and pixel shader, bind textures, and that's it.
//
//
// $Header: $
// $Header: $
Line 74: Line 149:


#include "BaseVSShader.h"
#include "BaseVSShader.h"
#include "convar.h"
#include "sdk_particle_vs11.inc"
 
// Note: you have to run buildshaders.bat to generate these files from the FXC code.
#include "sdk_lightmap_ps20.inc"
#include "sdk_lightmap_vs20.inc"
 


BEGIN_VS_SHADER( SDK_Lightmap, "Help for SDK_Lightmap" )
// 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
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
END_SHADER_PARAMS


// Set up anything that is necessary to make decisions in SHADER_FALLBACK.
bool UsePixelShaders( IMaterialVar **params ) const
SHADER_INIT_PARAMS()
{
{
return params[BUMPMAP]->IsDefined() && g_pHardwareConfig->SupportsVertexAndPixelShaders();
}
}


SHADER_FALLBACK
SHADER_INIT
{
{
return 0;
// 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_INIT
SHADER_FALLBACK
{
{
LoadTexture( BASETEXTURE );
// 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;
}
}


Line 105: Line 194:
SHADOW_STATE
SHADOW_STATE
{
{
// Enable the texture for base texture and lightmap.
pShaderShadow->EnableTexture( SHADER_TEXTURE_STAGE0, true );
pShaderShadow->EnableTexture( SHADER_TEXTURE_STAGE0, true );
pShaderShadow->EnableTexture( SHADER_TEXTURE_STAGE1, true );
int fmt = VERTEX_POSITION;
int tCoordDimensions[] = {2};
pShaderShadow->VertexShaderVertexFormat( fmt, 2, 0, 0, 0 );
pShaderShadow->VertexShaderVertexFormat(  
VERTEX_POSITION | VERTEX_COLOR, 1, tCoordDimensions, 0, 0 );


sdk_lightmap_vs20_Static_Index vshIndex;
pShaderShadow->EnableBlending( true );
pShaderShadow->SetVertexShader( "sdk_lightmap_vs20", vshIndex.GetIndex() );
pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA );
 
pShaderShadow->EnableDepthWrites( false );
sdk_lightmap_ps20_Static_Index pshIndex;
pShaderShadow->SetPixelShader( "sdk_lightmap_ps20", pshIndex.GetIndex() );
sdk_particle_vs11_Static_Index vshIndex;
pShaderShadow->SetVertexShader( "sdk_particle_vs11", vshIndex.GetIndex() );


DefaultFog();
pShaderShadow->SetPixelShader( "sdk_particle_ps11" );
FogToFogColor();
}
}
DYNAMIC_STATE
DYNAMIC_STATE
{
{
BindTexture( SHADER_TEXTURE_STAGE0, BASETEXTURE, FRAME );
BindTexture( SHADER_TEXTURE_STAGE0, BUMPMAP );
pShaderAPI->BindLightmap( SHADER_TEXTURE_STAGE1 );
 
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();
Draw();
}
}
END_SHADER
END_SHADER</source>
</source>


[[Category: Programming]]
[[Category: Programming]]
[[Category: Shaders]]
[[Category: Shaders]]
[[Category: Snippets]]
[[Category: Particle_Effects]]

Latest revision as of 11:41, 9 June 2019

Obsolete-notext.png
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.

Warning.pngWarning: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