📄 macros.vsh
字号:
dp3 $worldTangentS.x, $vUserData, $blendedMatrix0
dp3 $worldTangentS.y, $vUserData, $blendedMatrix1
dp3 $worldTangentS.z, $vUserData, $blendedMatrix2
; calculate tangent t via cross( N, S ) * S[3]
&Cross( $worldTangentT, $worldNormal, $worldTangentS );
mul $worldTangentT.xyz, $vUserData.w, $worldTangentT.xyz
&FreeRegister( \$boneIndices );
&FreeRegister( \$blendedMatrix0 );
&FreeRegister( \$blendedMatrix1 );
&FreeRegister( \$blendedMatrix2 );
}
elsif( $numBones == 3 )
{
local( $boneIndices );
local( $blendedMatrix0 );
local( $blendedMatrix1 );
local( $blendedMatrix2 );
&AllocateRegister( \$boneIndices );
&AllocateRegister( \$blendedMatrix0 );
&AllocateRegister( \$blendedMatrix1 );
&AllocateRegister( \$blendedMatrix2 );
; Transform position into world space using all bones
; denormalize d3dcolor to matrix index
mad $boneIndices, $vBoneIndices, $cColorToIntScale, $cModel0Index
; r11 = boneindices at this point
; first matrix
mov a0.x, $boneIndices.z
mul $blendedMatrix0, $vBoneWeights.x, c[a0.x]
mul $blendedMatrix1, $vBoneWeights.x, c[a0.x+1]
mul $blendedMatrix2, $vBoneWeights.x, c[a0.x+2]
; second matrix
mov a0.x, $boneIndices.y
mad $blendedMatrix0, $vBoneWeights.y, c[a0.x], $blendedMatrix0
mad $blendedMatrix1, $vBoneWeights.y, c[a0.x+1], $blendedMatrix1
mad $blendedMatrix2, $vBoneWeights.y, c[a0.x+2], $blendedMatrix2
; Calculate third weight
; compute 1-(weight1+weight2) to calculate weight2
; Use $boneIndices.w as a temp since we aren't using it for anything.
add $boneIndices.w, $vBoneWeights.x, $vBoneWeights.y
sub $boneIndices.w, $cOne, $boneIndices.w
; third matrix
mov a0.x, $boneIndices.x
mad $blendedMatrix0, $boneIndices.w, c[a0.x], $blendedMatrix0
mad $blendedMatrix1, $boneIndices.w, c[a0.x+1], $blendedMatrix1
mad $blendedMatrix2, $boneIndices.w, c[a0.x+2], $blendedMatrix2
; position
dp4 $worldPos.x, $vPos, $blendedMatrix0
dp4 $worldPos.y, $vPos, $blendedMatrix1
dp4 $worldPos.z, $vPos, $blendedMatrix2
mov $worldPos.w, $cOne
; normal
dp3 $worldNormal.x, $vNormal, $blendedMatrix0
dp3 $worldNormal.y, $vNormal, $blendedMatrix1
dp3 $worldNormal.z, $vNormal, $blendedMatrix2
; tangents
dp3 $worldTangentS.x, $vUserData, $blendedMatrix0
dp3 $worldTangentS.y, $vUserData, $blendedMatrix1
dp3 $worldTangentS.z, $vUserData, $blendedMatrix2
; calculate tangent t via cross( N, S ) * S[3]
&Cross( $worldTangentT, $worldNormal, $worldTangentS );
mul $worldTangentT.xyz, $vUserData.w, $worldTangentT.xyz
&FreeRegister( \$boneIndices );
&FreeRegister( \$blendedMatrix0 );
&FreeRegister( \$blendedMatrix1 );
&FreeRegister( \$blendedMatrix2 );
}
}
sub ColorClamp
{
; ColorClamp; stomps $color.w
local( $color ) = shift;
local( $dst ) = shift;
; Get the max of RGB and stick it in W
max $color.w, $color.x, $color.y
max $color.w, $color.w, $color.z
; get the greater of one and the max color.
max $color.w, $color.w, $cOne
rcp $color.w, $color.w
mul $dst.xyz, $color.w, $color.xyz
}
sub AmbientLight
{
local( $worldNormal ) = shift;
local( $linearColor ) = shift;
local( $add ) = shift;
; Ambient lighting
&AllocateRegister( \$nSquared );
&AllocateRegister( \$isNegative );
mul $nSquared.xyz, $worldNormal.xyz, $worldNormal.xyz ; compute n times n
slt $isNegative.xyz, $worldNormal.xyz, $cZero ; Figure out whether each component is >0
mov a0.x, $isNegative.x
if( $add )
{
mad $linearColor.xyz, $nSquared.x, c[a0.x + $cAmbientColorPosXOffset], $linearColor ; $linearColor = normal[0]*normal[0] * box color of appropriate x side
}
else
{
mul $linearColor.xyz, $nSquared.x, c[a0.x + $cAmbientColorPosXOffset] ; $linearColor = normal[0]*normal[0] * box color of appropriate x side
}
mov a0.x, $isNegative.y
mad $linearColor.xyz, $nSquared.y, c[a0.x + $cAmbientColorPosYOffset], $linearColor
mov a0.x, $isNegative.z
mad $linearColor.xyz, $nSquared.z, c[a0.x + $cAmbientColorPosZOffset], $linearColor
&FreeRegister( \$isNegative );
&FreeRegister( \$nSquared );
}
sub DirectionalLight
{
local( $worldNormal ) = shift;
local( $linearColor ) = shift;
local( $add ) = shift;
&AllocateRegister( \$nDotL ); # FIXME: This only needs to be a scalar
; NOTE: Gotta use -l here, since light direction = -l
; DIRECTIONAL LIGHT
; compute n dot l
dp3 $nDotL.x, -c[a0.x + 1], $worldNormal
max $nDotL.x, $nDotL.x, c0.x ; Clamp to zero
if( $add )
{
mad $linearColor.xyz, c[a0.x], $nDotL.x, $linearColor
}
else
{
mov $linearColor.xyz, c[a0.x], $nDotL.x
}
&FreeRegister( \$nDotL );
}
sub PointLight
{
local( $worldPos ) = shift;
local( $worldNormal ) = shift;
local( $linearColor ) = shift;
local( $add ) = shift;
local( $lightDir );
&AllocateRegister( \$lightDir );
; POINT LIGHT
; compute light direction
sub $lightDir, c[a0.x+2], $worldPos
local( $lightDistSquared );
local( $ooLightDist );
&AllocateRegister( \$lightDistSquared );
&AllocateRegister( \$ooLightDist );
; normalize light direction, maintain temporaries for attenuation
dp3 $lightDistSquared, $lightDir, $lightDir
rsq $ooLightDist, $lightDistSquared.x
mul $lightDir, $lightDir, $ooLightDist.x
local( $attenuationFactors );
&AllocateRegister( \$attenuationFactors );
; compute attenuation amount (r2 = 'd*d d*d d*d d*d', r3 = '1/d 1/d 1/d 1/d')
dst $attenuationFactors, $lightDistSquared, $ooLightDist ; r4 = ( 1, d, d*d, 1/d )
&FreeRegister( \$lightDistSquared );
&FreeRegister( \$ooLightDist );
local( $attenuation );
&AllocateRegister( \$attenuation );
dp3 $attenuation, $attenuationFactors, c[a0.x+4] ; r3 = atten0 + d * atten1 + d*d * atten2
rcp $lightDir.w, $attenuation ; $lightDir.w = 1 / (atten0 + d * atten1 + d*d * atten2)
&FreeRegister( \$attenuationFactors );
&FreeRegister( \$attenuation );
local( $tmp );
&AllocateRegister( \$tmp ); # FIXME : really only needs to be a scalar
; compute n dot l, fold in distance attenutation
dp3 $tmp.x, $lightDir, $worldNormal
max $tmp.x, $tmp.x, c0.x ; Clamp to zero
mul $tmp.x, $tmp.x, $lightDir.w
if( $add )
{
mad $linearColor.xyz, c[a0.x], $tmp.x, $linearColor
}
else
{
mov $linearColor.xyz, c[a0.x], $tmp.x
}
&FreeRegister( \$lightDir );
&FreeRegister( \$tmp ); # FIXME : really only needs to be a scalar
}
sub SpotLight
{
local( $worldPos ) = shift;
local( $worldNormal ) = shift;
local( $linearColor ) = shift;
local( $add ) = shift;
local( $lightDir );
&AllocateRegister( \$lightDir );
; SPOTLIGHT
; compute light direction
sub $lightDir, c[a0.x+2], $worldPos
local( $lightDistSquared );
local( $ooLightDist );
&AllocateRegister( \$lightDistSquared );
&AllocateRegister( \$ooLightDist );
; normalize light direction, maintain temporaries for attenuation
dp3 $lightDistSquared, $lightDir, $lightDir
rsq $ooLightDist, $lightDistSquared.x
mul $lightDir, $lightDir, $ooLightDist.x
local( $attenuationFactors );
&AllocateRegister( \$attenuationFactors );
; compute attenuation amount (r2 = 'd*d d*d d*d d*d', r3 = '1/d 1/d 1/d 1/d')
dst $attenuationFactors, $lightDistSquared, $ooLightDist ; r4 = ( 1, d, d*d, 1/d )
&FreeRegister( \$lightDistSquared );
&FreeRegister( \$ooLightDist );
local( $attenuation ); &AllocateRegister( \$attenuation );
dp3 $attenuation, $attenuationFactors, c[a0.x+4] ; r3 = atten0 + d * atten1 + d*d * atten2
rcp $lightDir.w, $attenuation ; r1.w = 1 / (atten0 + d * atten1 + d*d * atten2)
&FreeRegister( \$attenuationFactors );
&FreeRegister( \$attenuation );
local( $litSrc ); &AllocateRegister( \$litSrc );
local( $tmp ); &AllocateRegister( \$tmp ); # FIXME - only needs to be scalar
; compute n dot l
dp3 $litSrc.x, $worldNormal, $lightDir
; compute angular attenuation
dp3 $tmp.x, c[a0.x+1], -$lightDir ; dot = -delta * spot direction
sub $litSrc.y, $tmp.x, c[a0.x+3].z ; r2.y = dot - stopdot2
&FreeRegister( \$tmp );
mul $litSrc.y, $litSrc.y, c[a0.x+3].w ; r2.y = (dot - stopdot2) / (stopdot - stopdot2)
mov $litSrc.w, c[a0.x+3].x ; r2.w = exponent
local( $litDst ); &AllocateRegister( \$litDst );
lit $litDst, $litSrc ; r3.y = N dot L or 0, whichever is bigger
&FreeRegister( \$litSrc );
; r3.z = pow((dot - stopdot2) / (stopdot - stopdot2), exponent)
min $litDst.z, $litDst.z, $cOne ; clamp pow() to 1
local( $tmp1 ); &AllocateRegister( \$tmp1 );
local( $tmp2 ); &AllocateRegister( \$tmp2 ); # FIXME - could be scalar
; fold in distance attenutation with other factors
mul $tmp1, c[a0.x], $lightDir.w
mul $tmp2.x, $litDst.y, $litDst.z
if( $add )
{
mad $linearColor.xyz, $tmp1, $tmp2.x, $linearColor
}
else
{
mov $linearColor.xyz, $tmp1, $tmp2.x
}
&FreeRegister( \$lightDir );
&FreeRegister( \$litDst );
&FreeRegister( \$tmp1 );
&FreeRegister( \$tmp2 );
}
sub DoLight
{
local( $lightType ) = shift;
local( $worldPos ) = shift;
local( $worldNormal ) = shift;
local( $linearColor ) = shift;
local( $add ) = shift;
if( $lightType eq "spot" )
{
&SpotLight( $worldPos, $worldNormal, $linearColor, $add );
}
elsif( $lightType eq "point" )
{
&PointLight( $worldPos, $worldNormal, $linearColor, $add );
}
elsif( $lightType eq "directional" )
{
&DirectionalLight( $worldNormal, $linearColor, $add );
}
else
{
die "don't know about light type \"$lightType\"\n";
}
}
sub DoLighting
{
local( $staticLightType ) = shift;
local( $ambientLightType ) = shift;
local( $localLightType1 ) = shift;
local( $localLightType2 ) = shift;
local( $worldPos ) = shift;
local( $worldNormal ) = shift;
# special case for no lighting
if( $staticLightType eq "none" && $ambientLightType eq "none" &&
$localLightType1 eq "none" && $localLightType2 eq "none" )
{
return;
}
# special case for static lighting only
# Don't need to bother converting to linear space in this case.
if( $staticLightType eq "static" && $ambientLightType eq "none" &&
$localLightType1 eq "none" && $localLightType2 eq "none" )
{
mov oD0, $vSpecular
return;
}
alloc $linearColor
alloc $gammaColor
local( $add ) = 0;
if( $staticLightType eq "static" )
{
; The static lighting comes in in gamma space and has also been premultiplied by $cOverbrightFactor
; need to get it into
; linear space so that we can do adds.
rcp $gammaColor.w, $cOverbrightFactor
mul $gammaColor.xyz, $vSpecular, $gammaColor.w
&GammaToLinear( $gammaColor, $linearColor );
$add = 1;
}
if( $ambientLightType eq "ambient" )
{
&AmbientLight( $worldNormal, $linearColor, $add );
$add = 1;
}
if( $localLightType1 ne "none" )
{
mov a0.x, c3.x
&DoLight( $localLightType1, $worldPos, $worldNormal, $linearColor, $add );
$add = 1;
}
if( $localLightType2 ne "none" )
{
mov a0.x, c3.y
&DoLight( $localLightType2, $worldPos, $worldNormal, $linearColor, $add );
$add = 1;
}
;------------------------------------------------------------------------------
; Output color (gamma correction)
;------------------------------------------------------------------------------
&LinearToGamma( $linearColor, $gammaColor );
if( 0 )
{
mul oD0.xyz, $gammaColor.xyz, $cOverbrightFactor
}
else
{
mul $gammaColor.xyz, $gammaColor.xyz, $cOverbrightFactor
&ColorClamp( $gammaColor, "oD0" );
}
; mov oD0.xyz, $linearColor
mov oD0.w, c0.y ; make sure all components are defined
free $linearColor
free $gammaColor
}
sub DoDynamicLightingToLinear
{
local( $ambientLightType ) = shift;
local( $localLightType1 ) = shift;
local( $localLightType2 ) = shift;
local( $worldPos ) = shift;
local( $worldNormal ) = shift;
local( $linearColor ) = shift;
# No lights at all. . note that we don't even consider static lighting here.
if( $ambientLightType eq "none" &&
$localLightType1 eq "none" && $localLightType2 eq "none" )
{
mov $linearColor, $cZero
return;
}
local( $add ) = 0;
if( $ambientLightType eq "ambient" )
{
&AmbientLight( $worldNormal, $linearColor, $add );
$add = 1;
}
if( $localLightType1 ne "none" )
{
mov a0.x, c3.x
&DoLight( $localLightType1, $worldPos, $worldNormal, $linearColor, $add );
$add = 1;
}
if( $localLightType2 ne "none" )
{
mov a0.x, c3.y
&DoLight( $localLightType2, $worldPos, $worldNormal, $linearColor, $add );
$add = 1;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -