⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 macros.vsh

📁 hl2 source code. Do not use it illegal.
💻 VSH
📖 第 1 页 / 共 3 页
字号:
;------------------------------------
; RULES FOR AUTHORING VERTEX SHADERS:
;------------------------------------
; - never use "def" . . .set constants in code instead. . our constant shadowing will break otherwise.
;	(same goes for pixel shaders)
; - use cN notation instead of c[N] notation. .makes grepping for registers easier.
;   The only exception is c[a0.x+blah] where you have no choice.
$g_NumRegisters = 12;

# NOTE: These must match the same values in vsh_prep.pl!
$vPos				= "v0";
$vBoneWeights		= "v1";
$vBoneIndices		= "v2";
$vNormal			= "v3";
$vColor				= "v5";
$vSpecular			= "v6";
$vTexCoord0			= "v7";
$vTexCoord1			= "v8";
$vTexCoord2			= "v9";
$vTexCoord3			= "v10";
$vTangentS			= "v11";
$vTangentT			= "v12";
$vUserData			= "v14";

if( $g_dx9 )
{
	if( $g_usesPos )
	{
		dcl_position $vPos;
	}
	if( $g_usesBoneWeights )
	{
		dcl_blendweight $vBoneWeights;
	}
	if( $g_usesBoneIndices )
	{
		dcl_blendindices $vBoneIndices;
	}
	if( $g_usesNormal )
	{
		dcl_normal $vNormal;
	}
	if( $g_usesColor )
	{
		dcl_color0 $vColor;
	}
	if( $g_usesSpecular )
	{
		dcl_color1 $vSpecular;
	}
	if( $g_usesTexCoord0 )
	{
		dcl_texcoord0 $vTexCoord0;
	}
	if( $g_usesTexCoord1 )
	{
		dcl_texcoord1 $vTexCoord1;
	}
	if( $g_usesTexCoord2 )
	{
		dcl_texcoord2 $vTexCoord2;
	}
	if( $g_usesTexCoord3 )
	{
		dcl_texcoord3 $vTexCoord3;
	}
	if( $g_usesTangentS )
	{
		dcl_tangent $vTangentS;
	}
	if( $g_usesTangentT )
	{
		dcl_binormal0 $vTangentT;
	}
	if( $g_usesUserData )
	{
		dcl_tangent $vUserData;
	}
}


$cConstants0		= "c0";
$cZero				= "c0.x";
$cOne				= "c0.y";
$cTwo				= "c0.z";
$cHalf				= "c0.w";

$cConstants1		= "c1";
$cOOGamma			= "c1.x";
#$cThree				= "c1.y";  # NOTE NOTE NOTE: This is overbright now!!!!  Don't use $cThree!!!
$cOneThird			= "c1.z";
$cOverbrightFactor	= "c1.w";

$cEyePos			= "c2";
$cWaterZ			= "c2.w";
$cEyePosWaterZ		= "c2";

$cLightIndex		= "c3";
$cLight0Offset		= "c3.x"; # 27
$cLight1Offset		= "c3.y"; # 32
$cColorToIntScale	= "c3.z"; # 3.0f * 255.0f ~= 765.01
$cModel0Index		= "c3.w"; # 42

# NOTE: These must match the same values in vsh_prep.pl!
$cModelViewProj0	= "c4";
$cModelViewProj1	= "c5";
$cModelViewProj2	= "c6";
$cModelViewProj3	= "c7";

$cViewProj0			= "c8";
$cViewProj1			= "c9";
$cViewProj2			= "c10";
$cViewProj3			= "c11";

# NOTE: These must match the same values in vsh_prep.pl!
$cModelView0		= "c12";
$cModelView1		= "c13";
$cModelView2		= "c14";
$cModelView3		= "c15";

$cFogParams			= "c16";
$cFogEndOverFogRange = "c16.x";
$cFogOne			= "c16.y";
$cHeightClipZ		= "c16.z";
$cOOFogRange		= "c16.w"; # (1/(fogEnd-fogStart))

$cViewModel0		= "c17";
$cViewModel1		= "c18";
$cViewModel2		= "c19";
$cViewModel3		= "c20";

$cAmbientColorPosX	= "c21";
$cAmbientColorNegX	= "c22";
$cAmbientColorPosY	= "c23";
$cAmbientColorNegY	= "c24";
$cAmbientColorPosZ	= "c25";
$cAmbientColorNegZ	= "c26";

$cAmbientColorPosXOffset	= "21";
$cAmbientColorPosYOffset	= "23";
$cAmbientColorPosZOffset	= "25";

$cLight0DiffColor	= "c27";
$cLight0Dir			= "c28";
$cLight0Pos			= "c29";
$cLight0SpotParams  = "c30"; # [ exponent, stopdot, stopdot2, 1 / (stopdot - stopdot2)
$cLight0Atten		= "c31"; # [ constant, linear, quadratic, 0.0f ]

$cLight1DiffColor	= "c32";
$cLight1Dir			= "c33";
$cLight1Pos			= "c34";
$cLight1SpotParams  = "c35"; # [ exponent, stopdot, stopdot2, 1 / (stopdot - stopdot2)
$cLight1Atten		= "c36"; # [ constant, linear, quadratic, 0.0f ]

# c37-c41 unused! (would be used for a third light if we had one)
$cClipDirection		= "c37.x";
$cClipDirectionTimesHeightClipZ	= "c37.y";
$cModulationColor	= "c38";
$cThree				= "c39.x";

# There are 16 model matrices for skinning
# NOTE: These must match the same values in vsh_prep.pl!
$cModel0			= "c42";
$cModel1			= "c43";
$cModel2			= "c44";

# the last cmodel is c89

# c90-c95 are reserved for shader specific constants

sub OutputUsedRegisters
{
	local( $i );
	; USED REGISTERS
	for( $i = 0; $i < $g_NumRegisters; $i++ )
	{
		if( $g_allocated[$i] )
		{
			; $g_allocatedname[$i] = r$i
		}
	}
	;
}

sub AllocateRegister
{
	local( *reg ) = shift;
	local( $regname ) = shift;
	local( $i );
	for( $i = 0; $i < $g_NumRegisters; $i++ )
	{
		if( !$g_allocated[$i] )
		{
			$g_allocated[$i] = 1;
			$g_allocatedname[$i] = $regname;
			; AllocateRegister $regname = r$i
			$reg = "r$i";
			&OutputUsedRegisters();
			return;
		}
	}
	; Out of registers allocating $regname!
	$reg = "rERROR_OUT_OF_REGISTERS";
	&OutputUsedRegisters();
}

# pass in a reference to a var that contains a register. . ie \$var where var will constain "r1", etc
sub FreeRegister
{
	local( *reg ) = shift;
	local( $regname ) = shift;
	; FreeRegister $regname = $reg
	if( $reg =~ m/rERROR_DEALLOCATED/ )
	{
		; $regname already deallocated
		; $reg = "rALREADY_DEALLOCATED";
		&OutputUsedRegisters();
		return;
	}
#	if( $regname ne g_allocatedname[$reg] )
#	{
#		; Error freeing $reg
#		mov compileerror, freed unallocated register $regname
#	}

	if( ( $reg =~ m/r(.*)/ ) )
	{
		$g_allocated[$1] = 0;
	}
	$reg = "rERROR_DEALLOCATED";
	&OutputUsedRegisters();
}

sub CheckUnfreedRegisters()
{
	local( $i );
	for( $i = 0; $i < $g_NumRegisters; $i++ )
	{
		if( $g_allocated[$i] )
		{
			print "ERROR: r$i allocated to $g_allocatedname[$i] at end of program\n";
			$g_allocated[$i] = 0;
		}
	}
}

sub Normalize
{
	local( $r ) = shift;
	dp3 $r.w, $r, $r
	rsq $r.w, $r.w
	mul $r, $r, $r.w
}

sub Cross
{
	local( $result ) = shift;
	local( $a ) = shift;
	local( $b ) = shift;

	mul $result.xyz, $a.yzx, $b.zxy
	mad $result.xyz, -$b.yzx, $a.zxy, $result
}

sub RangeFog
{
	; Can either be viewPos or projPos since z should be the same for both.
	local( $viewPos ) = shift;

	;------------------------------
	; Regular range fog
	;------------------------------

	; oFog.x = 1.0f = no fog
	; oFog.x = 0.0f = full fog
	; compute fog factor f = (fog_end - dist)*(1/(fog_end-fog_start))
	; this is == to: (fog_end/(fog_end-fog_start) - dist/(fog_end-fog_start)
	; which can be expressed with a single mad instruction!
	if( $g_dx9 )
	{
		mad oFog, -$viewPos.z, $cOOFogRange, $cFogEndOverFogRange
	}
	else
	{
		mad oFog.x, -$viewPos.z, $cOOFogRange, $cFogEndOverFogRange
	}
}

sub WaterFog
{
	; oFog.x = 1.0f = no fog
	; oFog.x = 0.0f = full fog
;	mov oFog.x, $cOne
;	return;
	; only $worldPos.z is used out of worldPos
	local( $worldPos ) = shift;
	local( $viewPos ) = shift;
	
	; $viewPos.z is the distance from the eye to the vertex
	local( $tmp );
	&AllocateRegister( \$tmp );
	; Calculate the ratio of the line of sight integral through the water to the total line
	; integral
	; These could both be done in a single add if cWaterZ and cEyePos.z were in the same constant
;	add $tmp.x, $cWaterZ, -$worldPos.z
;	add $tmp.y, $cEyePos.z, -$worldPos.z
	add $tmp.xy, $cEyePosWaterZ.wz, -$worldPos.z

	; $tmp.x is the distance from the water surface to the vert
	; $tmp.y is the distance from the eye position to the vert

	; if $tmp.x < 0, then set it to 0
	; This is the equivalent of moving the vert to the water surface if it's above the water surface
	max $tmp.x, $tmp.x, $cZero

	; $tmp.w = $tmp.x / $tmp.y
	rcp $tmp.z, $tmp.y
	mul $tmp.w, $tmp.x, $tmp.z

	; If the eye is under water, then always use the whole fog amount
	; Duh, if the eye is under water, use regular fog!
;	sge $tmp.z, $tmp.y, $cZero
	; $tmp.z = 0 if the eye is underwater, otherwise $tmp.z = 1
;	mul $tmp.w, $tmp.w, $tmp.z
;	add $tmp.z, $cOne, -$tmp.z
;	add $tmp.w, $tmp.w, $tmp.z

	mul $tmp.w, $tmp.w, $viewPos.z
	; $tmp.w is now the distance that we see through water.

	if( $g_dx9 )
	{
		mad oFog, -$tmp.w, $cOOFogRange, $cFogOne
	}
	else
	{
		mad oFog.x, -$tmp.w, $cOOFogRange, $cFogOne
	}

	&FreeRegister( \$tmp );
}


#------------------------------------------------------------------------------
# Main fogging routine
#------------------------------------------------------------------------------
sub CalcFog
{
	; CalcFog
	local( $worldPos ) = shift;
	local( $projPos ) = shift;

	if( $g_fogType eq "rangefog" )
	{
		&RangeFog( $projPos );
	}
	elsif( $g_fogType eq "heightfog" )
	{
		&WaterFog( $worldPos, $projPos );
	}
	else
	{
		die;
	}	
}


sub DoHeightClip
{
	; DoHeightClip
;	$texReg = $cClipDirection * ( $cHeightClipZ - $worldPos.z )
;	$texReg = $cClipDirection * $cHeightClipZ - $cClipDirection * $worldPos.z
;	$const = $cClipDirection * $cHeightClipZ;
;	$texReg = $const - $cClipDirection * $worldPos.z
;	$texReg = ( - $cClipDirection * $worldPos.z ) + $const

	local( $worldPos ) = shift;
	local( $texReg ) = shift;
	local( $tmp );

	# Do a user clip plan using texkill in the case that we don't have
	# a detail texture.
	# optimize!  Can probably do an arbitrary plane in one or two instructions.
	if( 0 )
	{
		&AllocateRegister( \$tmp );
		add $tmp, -$worldPos.z, $cHeightClipZ
		# This determines which side we are clipping on.
		mul $texReg, $tmp, $cClipDirection
		&FreeRegister( \$tmp );
	}
	else
	{
		mad $texReg, -$cClipDirection, $worldPos.z, $cClipDirectionTimesHeightClipZ	
	}
}

sub GammaToLinear
{
	local( $gamma ) = shift;
	local( $linear ) = shift;

	local( $tmp );
	&AllocateRegister( \$tmp );

	; Is rcp more expensive than just storing 2.2 somewhere and doing a mov?
	rcp $gamma.w, $cOOGamma							; $gamma.w = 2.2
	lit $linear.z, $gamma.zzzw						; r0.z = linear blue
	lit $tmp.z, $gamma.yyyw							; r2.z = linear green
	mov $linear.y, $tmp.z							; r0.y = linear green
	lit $tmp.z, $gamma.xxxw							; r2.z = linear red
	mov $linear.x, $tmp.z							; r0.x = linear red

	&FreeRegister( \$tmp );
}

sub LinearToGamma
{
	local( $linear ) = shift;
	local( $gamma ) = shift;

	local( $tmp );
	&AllocateRegister( \$tmp );

	mov $linear.w, $cOOGamma						; $linear.w = 1.0/2.2
	lit $gamma.z, $linear.zzzw						; r0.z = gamma blue
	lit $tmp.z, $linear.yyyw						; r2.z = gamma green
	mov $gamma.y, $tmp.z							; r0.y = gamma green
	lit $tmp.z, $linear.xxxw						; r2.z = gamma red
	mov $gamma.x, $tmp.z							; r0.x = gamma red

	&FreeRegister( \$tmp );
}

sub ComputeReflectionVector
{
	local( $worldPos ) = shift;
	local( $worldNormal ) = shift;
	local( $reflectionVector ) = shift;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -