diff --git a/devtools/bin/buildshaderlist.pl b/devtools/bin/buildshaderlist.pl new file mode 100644 index 00000000..57790ace --- /dev/null +++ b/devtools/bin/buildshaderlist.pl @@ -0,0 +1,22 @@ +use File::DosGlob; +@ARGV = map { + my @g = File::DosGlob::glob($_) if /[*?]/; + @g ? @g : $_; + } @ARGV; + +open FILE, ">__tmpshaderlist.txt"; + +foreach $arg (@ARGV) +{ + if( $arg =~ m/\.fxc$/i || $arg =~ m/\.vsh$/i || $arg =~ m/\.psh$/i ) + { + print $arg . "\n"; + print FILE $arg . "\n"; + } +} + +close FILE; + +system "buildshaders.bat __tmpshaderlist"; + +unlink "__tmpshaderlist.txt"; \ No newline at end of file diff --git a/devtools/bin/checkshaderchecksums.pl b/devtools/bin/checkshaderchecksums.pl new file mode 100644 index 00000000..b0a42762 --- /dev/null +++ b/devtools/bin/checkshaderchecksums.pl @@ -0,0 +1,116 @@ +use String::CRC32; +BEGIN {use File::Basename; push @INC, dirname($0); } +require "valve_perl_helpers.pl"; + +sub GetShaderType +{ + my $shadername = shift; + my $shadertype; + if( $shadername =~ m/\.vsh/i ) + { + $shadertype = "vsh"; + } + elsif( $shadername =~ m/\.psh/i ) + { + $shadertype = "psh"; + } + elsif( $shadername =~ m/\.fxc/i ) + { + $shadertype = "fxc"; + } + else + { + die; + } + return $shadertype; +} + +sub GetShaderSrc +{ + my $shadername = shift; + if ( $shadername =~ m/^(.*)-----/i ) + { + return $1; + } + else + { + return $shadername; + } +} + +sub GetShaderType +{ + my $shadername = shift; + my $shadertype; + if( $shadername =~ m/\.vsh/i ) + { + $shadertype = "vsh"; + } + elsif( $shadername =~ m/\.psh/i ) + { + $shadertype = "psh"; + } + elsif( $shadername =~ m/\.fxc/i ) + { + $shadertype = "fxc"; + } + else + { + die; + } + return $shadertype; +} + +sub GetShaderBase +{ + my $shadername = shift; + if ( $shadername =~ m/-----(.*)$/i ) + { + return $1; + } + else + { + my $shadertype = &GetShaderType( $shadername ); + $shadername =~ s/\.$shadertype//i; + return $shadername; + } +} + +$g_x360 = 0; +$g_vcsext = ".vcs"; + +while( 1 ) +{ + $inputbase = shift; + + if( $inputbase =~ m/-x360/ ) + { + $g_x360 = 1; + $g_vcsext = ".360.vcs"; + } + else + { + last; + } +} + +# rip the txt off the end if it's there. +$inputbase =~ s/\.txt//i; + +my @srcfiles = &LoadShaderListFile( $inputbase ); + +foreach $srcfile ( @srcfiles ) +{ + my $shadertype = &GetShaderType( $srcfile ); + my $shaderbase = &GetShaderBase( $srcfile ); + my $shadersrc = &GetShaderSrc( $srcfile ); + my $vcsFileName = "..\\..\\..\\game\\platform\\shaders\\$shadertype\\$shaderbase" . $g_vcsext; +# print "shadersrc: $shadersrc vcsFileName: $vcsFileName\n"; + + if( $g_x360 && ( $shaderbase =~ m/_ps20$/i ) ) + { + next; # skip _ps20 files for 360 + } + + &CheckCRCAgainstTarget( $shadersrc, $vcsFileName, 1 ); +} diff --git a/devtools/bin/copyshaderincfiles.pl b/devtools/bin/copyshaderincfiles.pl new file mode 100644 index 00000000..51061091 --- /dev/null +++ b/devtools/bin/copyshaderincfiles.pl @@ -0,0 +1,81 @@ +BEGIN {use File::Basename; push @INC, dirname($0); } +require "valve_perl_helpers.pl"; +use Cwd; +use String::CRC32; + +my $txtfilename = shift; +my $arg = shift; + +my $is360 = 0; +my $platformextension = ""; +if( $arg =~ m/-x360/i ) +{ + $is360 = 1; + $platformextension = ".360"; +} + +open TXTFILE, "<$txtfilename"; + +my $src; +my $dst; +while( $src = ) +{ + # get rid of comments + $src =~ s,//.*,,g; + + # skip blank lines + if( $src =~ m/^\s*$/ ) + { + next; + } + + # Get rid of newlines. + $src =~ s/\n//g; + + # Save off the shader source filename. + my $dst = $src; + + $dst =~ s/_tmp//gi; + + # Does the dst exist? + my $dstexists = -e $dst; + my $srcexists = -e $src; + # What are the time stamps for the src and dst? + my $srcmodtime = ( stat $src )[9]; + my $dstmodtime = ( stat $dst )[9]; + + if( $dstexists && !$srcexists ) + { + printf STDERR "$src doesn't exist, deleting $dst\n"; + unlink $dst; + } + + # Open for edit or add if different than what is in perforce already. + if( !$dstexists || ( $srcmodtime != $dstmodtime ) ) + { + # Make the target writable if it exists + if( $dstexists ) + { + MakeFileWritable( $dst ); + } + + my $dir = $dst; + $dir =~ s,([^/\\]*$),,; # rip the filename off the end + my $filename = $1; + + # create the target directory if it doesn't exist + if( !$dstexists ) + { + &MakeDirHier( $dir, 0777 ); + } + + # copy the file to its targets. . . we want to see STDERR here if there is an error. + my $cmd = "copy $src $dst > nul"; +# print STDERR "$cmd\n"; + system $cmd; + + MakeFileReadOnly( $dst ); + } +} + +close TXTFILE; diff --git a/devtools/bin/copyshaders.pl b/devtools/bin/copyshaders.pl new file mode 100644 index 00000000..f8ce3b76 --- /dev/null +++ b/devtools/bin/copyshaders.pl @@ -0,0 +1,161 @@ +BEGIN {use File::Basename; push @INC, dirname($0); } +require "valve_perl_helpers.pl"; +use Cwd; +use String::CRC32; + +sub ReadInputFileWithIncludes +{ + local( $filename ) = shift; + + local( *INPUT ); + local( $output ); + + open INPUT, "<$filename" || die; + + local( $line ); + local( $linenum ) = 1; + while( $line = ) + { + if( $line =~ m/\#include\s+\"(.*)\"/i ) + { + $output.= ReadInputFileWithIncludes( $1 ); + } + else + { + $output .= $line; + } + } + + close INPUT; + return $output; +} + +sub PatchCRC +{ + my $filename = shift; + my $crc = shift; +# print STDERR "PatchCRC( $filename, $crc )\n"; + local( *FP ); + open FP, "+<$filename" || die; + binmode( FP ); + seek FP, 6 * 4, 0; + my $uInt = "I"; + if( $filename =~ m/360/ ) + { + $uInt = "N"; + } + print FP pack $uInt, $crc; + close FP; +} + +my $txtfilename = shift; +my $arg = shift; + +my $is360 = 0; +my $platformextension = ""; +if( $arg =~ m/-x360/i ) +{ + $is360 = 1; + $platformextension = ".360"; +} + +open TXTFILE, "<$txtfilename"; + +my $src; +my $dst; +while( $src = ) +{ + # get rid of comments + $src =~ s,//.*,,g; + + # skip blank lines + if( $src =~ m/^\s*$/ ) + { + next; + } + + # Get rid of newlines. + $src =~ s/\n//g; + + # Save off the shader source filename. + my $shadersrcfilename = $src; + $shadersrcfilename =~ s/-----.*$//; + # use only target basename. + $src =~ s/^.*-----//; + + # where the binary vcs file is + my $spath = ""; + + if ( $shadersrcfilename =~ m@\.fxc@i ) + { + $spath = "shaders\\fxc\\"; + } + if ( $shadersrcfilename =~ m@\.vsh@i ) + { + $spath = "shaders\\vsh\\"; + } + if ( $shadersrcfilename =~ m@\.psh@i ) + { + $spath = "shaders\\psh\\"; + } + + # make the source have path and extension + $src = $spath . $src . $platformextension . ".vcs"; + + # build the dest filename. + $dst = $src; + + $dst =~ s/shaders\\/..\\..\\..\\game\\platform\\shaders\\/i; + + # Does the dst exist? + my $dstexists = -e $dst; + my $srcexists = -e $src; + # What are the time stamps for the src and dst? + my $srcmodtime = ( stat $src )[9]; + my $dstmodtime = ( stat $dst )[9]; + + # Write $dst to a file so that we can do perforce stuff to it later. + local( *VCSLIST ); + open VCSLIST, ">>vcslist.txt" || die; + print VCSLIST $dst . "\n"; + close VCSLIST; + + # Open for edit or add if different than what is in perforce already. + if( !$dstexists || ( $srcmodtime != $dstmodtime ) ) + { + if ( $srcexists && $shadersrcfilename =~ m@\.fxc@i ) + { + # Get the CRC for the source file. + my $srccode = ReadInputFileWithIncludes( $shadersrcfilename ); + my $crc = crc32( $srccode ); + + # Patch the source VCS file with the CRC32 of the source code used to build that file. + PatchCRC( $src, $crc ); + } + + # Make the target vcs writable if it exists + if( $dstexists ) + { + MakeFileWritable( $dst ); + } + + my $dir = $dst; + $dir =~ s,([^/\\]*$),,; # rip the filename off the end + my $filename = $1; + + # create the target directory if it doesn't exist + if( !$dstexists ) + { + &MakeDirHier( $dir, 0777 ); + } + + # copy the file to its targets. . . we want to see STDERR here if there is an error. + my $cmd = "copy $src $dst > nul"; +# print STDERR "$cmd\n"; + system $cmd; + + MakeFileReadOnly( $dst ); + } +} + +close TXTFILE; diff --git a/devtools/bin/d3dx10_33.dll b/devtools/bin/d3dx10_33.dll new file mode 100644 index 00000000..05342c8c Binary files /dev/null and b/devtools/bin/d3dx10_33.dll differ diff --git a/devtools/bin/d3dx9_33.dll b/devtools/bin/d3dx9_33.dll new file mode 100644 index 00000000..a005f8fa Binary files /dev/null and b/devtools/bin/d3dx9_33.dll differ diff --git a/devtools/bin/fix_particle_operator_names.pl b/devtools/bin/fix_particle_operator_names.pl new file mode 100644 index 00000000..86fd0f0f --- /dev/null +++ b/devtools/bin/fix_particle_operator_names.pl @@ -0,0 +1,110 @@ +#!perl +use File::Find; + +&BuildRemapTable; + +find(\&convert, "." ); + + +sub convert + { + return unless (/\.pcf$/i); + return if (/^tmp\.pcf$/i); + return if (/^tmp2\.pcf$/i); + return if (/360\.pcf$/i); + print STDERR "process ", $File::Find::name," ($_) dir=",`cd`," \n"; + my $fname=$_; + print `p4 edit $fname`; + print `dmxconvert -i $_ -o tmp.pcf -oe keyvalues2`; + open(TMP, "tmp.pcf" ) || return; + open(OUT, ">tmp2.pcf" ) || die; + while() + { + s/[\n\r]//g; + if ( (/^(\s*\"functionName\"\s*\"string\"\s*\")(.*)\"(.*)$/) && + length($map{$2}) ) + { + $_=$1.$map{$2}.'"'.$3; + } + if ( (/^(\s*\"name\"\s*\"string\"\s*\")(.*)\"(.*)$/) && + length($map{$2}) ) + { + $_=$1.$map{$2}.'"'.$3; + } + print OUT "$_\n"; + } + close OUT; + close TMP; + print `dmxconvert -i tmp2.pcf -o $fname -ie keyvalues2 -oe binary`; + unlink "tmp.pcf"; + unlink "tmp2.pcf"; +} + + + + + + + + + + + + +sub BuildRemapTable +{ + $map{"alpha_fade"}= "Alpha Fade and Decay"; + $map{"alpha_fade_in_random"}= "Alpha Fade In Random"; + $map{"alpha_fade_out_random"}= "Alpha Fade Out Random"; + $map{"basic_movement"}= "Movement Basic"; + $map{"color_fade"}= "Color Fade"; + $map{"controlpoint_light"}= "Color Light From Control Point"; + $map{"Dampen Movement Relative to Control Point"}= "Movement Dampen Relative to Control Point"; + $map{"Distance Between Control Points Scale"}= "Remap Distance Between Two Control Points to Scalar"; + $map{"Distance to Control Points Scale"}= "Remap Distance to Control Point to Scalar"; + $map{"lifespan_decay"}= "Lifespan Decay"; + $map{"lock to bone"}= "Movement Lock to Bone"; + $map{"postion_lock_to_controlpoint"}= "Movement Lock to Control Point"; + $map{"maintain position along path"}= "Movement Maintain Position Along Path"; + $map{"Match Particle Velocities"}= "Movement Match Particle Velocities"; + $map{"Max Velocity"}= "Movement Max Velocity"; + $map{"noise"}= "Noise Scalar"; + $map{"vector noise"}= "Noise Vector"; + $map{"oscillate_scalar"}= "Oscillate Scalar"; + $map{"oscillate_vector"}= "Oscillate Vector"; + $map{"Orient Rotation to 2D Direction"}= "Rotation Orient to 2D Direction"; + $map{"radius_scale"}= "Radius Scale"; + $map{"Random Cull"}= "Cull Random"; + $map{"remap_scalar"}= "Remap Scalar"; + $map{"rotation_movement"}= "Rotation Basic"; + $map{"rotation_spin"}= "Rotation Spin Roll"; + $map{"rotation_spin yaw"}= "Rotation Spin Yaw"; + $map{"alpha_random"}= "Alpha Random"; + $map{"color_random"}= "Color Random"; + $map{"create from parent particles"}= "Position From Parent Particles"; + $map{"Create In Hierarchy"}= "Position In CP Hierarchy"; + $map{"random position along path"}= "Position Along Path Random"; + $map{"random position on model"}= "Position on Model Random"; + $map{"sequential position along path"}= "Position Along Path Sequential"; + $map{"position_offset_random"}= "Position Modify Offset Random"; + $map{"position_warp_random"}= "Position Modify Warp Random"; + $map{"position_within_box"}= "Position Within Box Random"; + $map{"position_within_sphere"}= "Position Within Sphere Random"; + $map{"Inherit Velocity"}= "Velocity Inherit from Control Point"; + $map{"Initial Repulsion Velocity"}= "Velocity Repulse from World"; + $map{"Initial Velocity Noise"}= "Velocity Noise"; + $map{"Initial Scalar Noise"}= "Remap Noise to Scalar"; + $map{"Lifespan from distance to world"}= "Lifetime from Time to Impact"; + $map{"Pre-Age Noise"}= "Lifetime Pre-Age Noise"; + $map{"lifetime_random"}= "Lifetime Random"; + $map{"radius_random"}= "Radius Random"; + $map{"random yaw"}= "Rotation Yaw Random"; + $map{"Randomly Flip Yaw"}= "Rotation Yaw Flip Random"; + $map{"rotation_random"}= "Rotation Random"; + $map{"rotation_speed_random"}= "Rotation Speed Random"; + $map{"sequence_random"}= "Sequence Random"; + $map{"second_sequence_random"}= "Sequence Two Random"; + $map{"trail_length_random"}= "Trail Length Random"; + $map{"velocity_random"}= "Velocity Random"; +} + diff --git a/devtools/bin/fxc_prep.pl b/devtools/bin/fxc_prep.pl new file mode 100644 index 00000000..e8d60899 --- /dev/null +++ b/devtools/bin/fxc_prep.pl @@ -0,0 +1,1004 @@ +BEGIN {use File::Basename; push @INC, dirname($0); } +require "valve_perl_helpers.pl"; + +sub ReadInputFile +{ + local( $filename ) = shift; + local( *INPUT ); + local( @output ); + open INPUT, "<$filename" || die; + + local( $line ); + local( $linenum ) = 1; + while( $line = ) + { +# print "LINE: $line"; +# $line =~ s/\n//g; +# local( $postfix ) = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"; +# $postfix .= "; LINEINFO($filename)($linenum)\n"; + if( $line =~ m/\#include\s+\"(.*)\"/i ) + { + push @output, &ReadInputFile( $1 ); + } + else + { +# push @output, $line . $postfix; + push @output, $line; + } + $linenum++; + } + + close INPUT; +# print "-----------------\n"; +# print @output; +# print "-----------------\n"; + return @output; +} + +$dynamic_compile = defined $ENV{"dynamic_shaders"} && $ENV{"dynamic_shaders"} != 0; +$generateListingFile = 0; +$spewCombos = 0; + +@startTimes = times; +$startTime = time; + +$g_produceCppClasses = 1; +$g_produceCompiledVcs = 1; + +$g_sfm = 1; + +while( 1 ) +{ + $fxc_filename = shift; + if( $fxc_filename =~ m/-source/ ) + { + shift; + } + elsif( $fxc_filename =~ m/-nv3x/i ) + { + $nvidia = 1; + } + elsif( $fxc_filename =~ m/-ps20a/i ) + { + $ps2a = 1; + } + elsif( $fxc_filename =~ m/-x360/i ) + { + # enable x360 + $g_x360 = 1; + } + elsif( $fxc_filename =~ m/-novcs/i ) + { + $g_produceCompiledVcs = 0; + } + elsif( $fxc_filename =~ m/-nocpp/i ) + { + $g_produceCppClasses = 0; + } + else + { + last; + } +} + +$argstring = $fxc_filename; +$fxc_basename = $fxc_filename; +$fxc_basename =~ s/^.*-----//; +$fxc_filename =~ s/-----.*$//; + +$debug = 0; +$forcehalf = 0; + +sub ToUpper +{ + local( $in ) = shift; + $in =~ tr/a-z/A-Z/; + return $in; +} + +sub CreateCCodeToSpewDynamicCombo +{ + local( $out ) = ""; + + $out .= "\t\tOutputDebugString( \"src:$fxc_filename vcs:$fxc_basename dynamic index\" );\n"; + $out .= "\t\tchar tmp[128];\n"; + $out .= "\t\tint shaderID = "; + local( $scale ) = 1; + for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ ) + { + local( $name ) = @dynamicDefineNames[$i]; + local( $varname ) = "m_n" . $name; + $out .= "( $scale * $varname ) + "; + $scale *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1; + } + $out .= "0;\n"; + if( scalar( @dynamicDefineNames ) + scalar( @staticDefineNames ) > 0 ) + { + $out .= "\t\tint nCombo = shaderID;\n"; + } + + my $type = GetShaderType( $fxc_filename ); + for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ ) + { + $out .= "\t\tint n$dynamicDefineNames[$i] = nCombo % "; + $out .= ( $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1 ) + $dynamicDefineMin[$i]; + $out .= ";\n"; + + $out .= "\t\tsprintf( tmp, \"\%d\", n$dynamicDefineNames[$i] );\n"; + $out .= "\t\tOutputDebugString( \" $dynamicDefineNames[$i]"; + $out .= "=\" );\n"; + $out .= "\t\tOutputDebugString( tmp );\n"; + + $out .= "\t\tnCombo = nCombo / " . ( $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1 ) . ";\n"; + $out .= "\n"; + } + $out .= "\t\tOutputDebugString( \"\\n\" );\n"; + return $out; +} + +sub CreateCCodeToSpewStaticCombo +{ + local( $out ) = ""; + + $out .= "\t\tOutputDebugString( \"src:$fxc_filename vcs:$fxc_basename static index\" );\n"; + $out .= "\t\tchar tmp[128];\n"; + $out .= "\t\tint shaderID = "; + + local( $scale ) = 1; + for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ ) + { + $scale *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1; + } + for( $i = 0; $i < scalar( @staticDefineNames ); $i++ ) + { + local( $name ) = @staticDefineNames[$i]; + local( $varname ) = "m_n" . $name; + $out .= "( $scale * $varname ) + "; + $scale *= $staticDefineMax[$i] - $staticDefineMin[$i] + 1; + } + $out .= "0;\n"; + +# $out .= "\t\tsprintf( tmp, \"\%d\\n\", shaderID );\n"; +# $out .= "\t\tOutputDebugString( tmp );\n\n"; + if( scalar( @staticDefineNames ) + scalar( @staticDefineNames ) > 0 ) + { + $out .= "\t\tint nCombo = shaderID;\n"; + } + + my $type = GetShaderType( $fxc_filename ); + for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ ) + { + $out .= "\t\tnCombo = nCombo / " . ( $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1 ) . ";\n"; + } + for( $i = 0; $i < scalar( @staticDefineNames ); $i++ ) + { + $out .= "\t\tint n$staticDefineNames[$i] = nCombo % "; + $out .= ( $staticDefineMax[$i] - $staticDefineMin[$i] + 1 ) + $staticDefineMin[$i]; + $out .= ";\n"; + + $out .= "\t\tsprintf( tmp, \"\%d\", n$staticDefineNames[$i] );\n"; + $out .= "\t\tOutputDebugString( \" $staticDefineNames[$i]"; + $out .= "=\" );\n"; + $out .= "\t\tOutputDebugString( tmp );\n"; + + $out .= "\t\tnCombo = nCombo / " . ( $staticDefineMax[$i] - $staticDefineMin[$i] + 1 ) . ";\n"; + $out .= "\n"; + } + $out .= "\t\tOutputDebugString( \"\\n\" );\n"; + return $out; +} + +sub WriteHelperVar +{ + local( $name ) = shift; + local( $min ) = shift; + local( $max ) = shift; + local( $varname ) = "m_n" . $name; + local( $boolname ) = "m_b" . $name; + push @outputHeader, "private:\n"; + push @outputHeader, "\tint $varname;\n"; + push @outputHeader, "#ifdef _DEBUG\n"; + push @outputHeader, "\tbool $boolname;\n"; + push @outputHeader, "#endif\n"; + push @outputHeader, "public:\n"; + # int version of set function + push @outputHeader, "\tvoid Set" . $name . "( int i )\n"; + push @outputHeader, "\t{\n"; + push @outputHeader, "\t\tAssert( i >= $min && i <= $max );\n"; + push @outputHeader, "\t\t$varname = i;\n"; + push @outputHeader, "#ifdef _DEBUG\n"; + push @outputHeader, "\t\t$boolname = true;\n"; + push @outputHeader, "#endif\n"; + push @outputHeader, "\t}\n"; + # bool version of set function + push @outputHeader, "\tvoid Set" . $name . "( bool i )\n"; + push @outputHeader, "\t{\n"; +# push @outputHeader, "\t\tAssert( i >= $min && i <= $max );\n"; + push @outputHeader, "\t\t$varname = i ? 1 : 0;\n"; + push @outputHeader, "#ifdef _DEBUG\n"; + push @outputHeader, "\t\t$boolname = true;\n"; + push @outputHeader, "#endif\n"; + push @outputHeader, "\t}\n"; +} + +sub WriteStaticBoolExpression +{ + local( $prefix ) = shift; + local( $operator ) = shift; + for( $i = 0; $i < scalar( @staticDefineNames ); $i++ ) + { + if( $i ) + { + push @outputHeader, " $operator "; + } + local( $name ) = @staticDefineNames[$i]; + local( $boolname ) = "m_b" . $name; + push @outputHeader, "$prefix$boolname"; + } + push @outputHeader, ";\n"; +} + +sub WriteDynamicBoolExpression +{ + local( $prefix ) = shift; + local( $operator ) = shift; + for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ ) + { + if( $i ) + { + push @outputHeader, " $operator "; + } + local( $name ) = @dynamicDefineNames[$i]; + local( $boolname ) = "m_b" . $name; + push @outputHeader, "$prefix$boolname"; + } + push @outputHeader, ";\n"; +} + +sub WriteDynamicHelperClasses +{ + local( $basename ) = $fxc_basename; + $basename =~ tr/A-Z/a-z/; + local( $classname ) = $basename . "_Dynamic_Index"; + push @outputHeader, "class $classname\n"; + push @outputHeader, "{\n"; + for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ ) + { + $name = $dynamicDefineNames[$i]; + $min = $dynamicDefineMin[$i]; + $max = $dynamicDefineMax[$i]; + &WriteHelperVar( $name, $min, $max ); + } + push @outputHeader, "public:\n"; +# push @outputHeader, "void SetPixelShaderIndex( IShaderAPI *pShaderAPI ) { pShaderAPI->SetPixelShaderIndex( GetIndex() ); }\n"; + # CONSTRUCTOR + push @outputHeader, "\t// CONSTRUCTOR\n\t$classname( IShaderDynamicAPI *pShaderAPI )\n"; + push @outputHeader, "\t{\n"; + for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ ) + { + local( $name ) = @dynamicDefineNames[$i]; + local( $boolname ) = "m_b" . $name; + local( $varname ) = "m_n" . $name; + if ( length( $dynamicDefineInit{$name} ) ) + { + push @outputHeader, "#ifdef _DEBUG\n"; + push @outputHeader, "\t\t$boolname = true;\n"; + push @outputHeader, "#endif // _DEBUG\n"; + push @outputHeader, "\t\t$varname = $dynamicDefineInit{$name};\n"; + } + else + { + push @outputHeader, "#ifdef _DEBUG\n"; + push @outputHeader, "\t\t$boolname = false;\n"; + push @outputHeader, "#endif // _DEBUG\n"; + push @outputHeader, "\t\t$varname = 0;\n"; + } + } + push @outputHeader, "\t}\n"; + push @outputHeader, "\tint GetIndex()\n"; + push @outputHeader, "\t{\n"; + push @outputHeader, "\t\t// Asserts to make sure that we aren't using any skipped combinations.\n"; + foreach $skip (@perlskipcodeindividual) + { + # can't do this static and dynamic can see each other. +# $skip =~ s/\$/m_n/g; +# $skip =~ s/defined//g; +# push @outputHeader, "\t\tAssert( !( $skip ) );\n"; +# print "\t\tAssert( !( $skip ) );\n"; + } + push @outputHeader, "\t\t// Asserts to make sure that we are setting all of the combination vars.\n"; + + push @outputHeader, "#ifdef _DEBUG\n"; + if( scalar( @dynamicDefineNames ) > 0 ) + { + push @outputHeader, "\t\tbool bAllDynamicVarsDefined = "; + WriteDynamicBoolExpression( "", "&&" ); + } + if( scalar( @dynamicDefineNames ) > 0 ) + { + push @outputHeader, "\t\tAssert( bAllDynamicVarsDefined );\n"; + } + push @outputHeader, "#endif // _DEBUG\n"; + + if( $spewCombos && scalar( @dynamicDefineNames ) ) + { + push @outputHeader, &CreateCCodeToSpewDynamicCombo(); + } + push @outputHeader, "\t\treturn "; + local( $scale ) = 1; + for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ ) + { + local( $name ) = @dynamicDefineNames[$i]; + local( $varname ) = "m_n" . $name; + push @outputHeader, "( $scale * $varname ) + "; + $scale *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1; + } + push @outputHeader, "0;\n"; + push @outputHeader, "\t}\n"; + push @outputHeader, "};\n"; + push @outputHeader, "\#define shaderDynamicTest_" . $basename . " "; + my $prefix; + my $shaderType = &GetShaderType( $fxc_filename ); + if( $shaderType =~ m/^vs/i ) + { + $prefix = "vsh_"; + } + else + { + $prefix = "psh_"; + } + for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ ) + { + local( $name ) = @dynamicDefineNames[$i]; + if ( !length( $dynamicDefineInit{$name} ) ) + { + push @outputHeader, $prefix . "forgot_to_set_dynamic_" . $name . " + "; + } + } + push @outputHeader, "0\n"; +} + +sub WriteSkips +{ + my $skip; + + push @outputHeader, "// ALL SKIP STATEMENTS THAT AFFECT THIS SHADER!!!\n"; + foreach $skip (@perlskipcodeindividual) + { +# $skip =~ s/\$/m_n/g; + push @outputHeader, "// $skip\n"; + } +} + +sub WriteStaticHelperClasses +{ + local( $basename ) = $fxc_basename; + $basename =~ tr/A-Z/a-z/; + local( $classname ) = $basename . "_Static_Index"; + push @outputHeader, "#include \"shaderlib/cshader.h\"\n"; + push @outputHeader, "class $classname\n"; + push @outputHeader, "{\n"; + for( $i = 0; $i < scalar( @staticDefineNames ); $i++ ) + { + $name = $staticDefineNames[$i]; + $min = $staticDefineMin[$i]; + $max = $staticDefineMax[$i]; + &WriteHelperVar( $name, $min, $max ); + } + push @outputHeader, "public:\n"; +# push @outputHeader, "void SetShaderIndex( IShaderShadow *pShaderShadow ) { pShaderShadow->SetPixelShaderIndex( GetIndex() ); }\n"; + # WRITE THE CONSTRUCTOR + push @outputHeader, "\t// CONSTRUCTOR\n\t$classname( IShaderShadow *pShaderShadow, IMaterialVar **params )\n"; + push @outputHeader, "\t{\n"; + for( $i = 0; $i < scalar( @staticDefineNames ); $i++ ) + { + local( $name ) = @staticDefineNames[$i]; + local( $boolname ) = "m_b" . $name; + local( $varname ) = "m_n" . $name; + if ( length( $staticDefineInit{$name} ) ) + { + push @outputHeader, "#ifdef _DEBUG\n"; + push @outputHeader, "\t\t$boolname = true;\n"; + push @outputHeader, "#endif // _DEBUG\n"; + push @outputHeader, "\t\t$varname = $staticDefineInit{$name};\n"; + } + else + { + push @outputHeader, "#ifdef _DEBUG\n"; + push @outputHeader, "\t\t$boolname = false;\n"; + push @outputHeader, "#endif // _DEBUG\n"; + push @outputHeader, "\t\t$varname = 0;\n"; + } + } + push @outputHeader, "\t}\n"; + push @outputHeader, "\tint GetIndex()\n"; + push @outputHeader, "\t{\n"; + push @outputHeader, "\t\t// Asserts to make sure that we aren't using any skipped combinations.\n"; + foreach $skip (@perlskipcodeindividual) + { + $skip =~ s/\$/m_n/g; +# push @outputHeader, "\t\tAssert( !( $skip ) );\n"; + } + push @outputHeader, "\t\t// Asserts to make sure that we are setting all of the combination vars.\n"; + + push @outputHeader, "#ifdef _DEBUG\n"; + if( scalar( @staticDefineNames ) > 0 ) + { + push @outputHeader, "\t\tbool bAllStaticVarsDefined = "; + WriteStaticBoolExpression( "", "&&" ); + + } + if( scalar( @staticDefineNames ) > 0 ) + { + push @outputHeader, "\t\tAssert( bAllStaticVarsDefined );\n"; + } + push @outputHeader, "#endif // _DEBUG\n"; + + if( $spewCombos && scalar( @staticDefineNames ) ) + { + push @outputHeader, &CreateCCodeToSpewStaticCombo(); + } + push @outputHeader, "\t\treturn "; + local( $scale ) = 1; + for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ ) + { + $scale *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1; + } + for( $i = 0; $i < scalar( @staticDefineNames ); $i++ ) + { + local( $name ) = @staticDefineNames[$i]; + local( $varname ) = "m_n" . $name; + push @outputHeader, "( $scale * $varname ) + "; + $scale *= $staticDefineMax[$i] - $staticDefineMin[$i] + 1; + } + push @outputHeader, "0;\n"; + if( $scale > 0x7fffffff ) + { + $g_toomanycombos = 1; + $g_totalcombos = $scale; + } + push @outputHeader, "\t}\n"; + push @outputHeader, "};\n"; + push @outputHeader, "\#define shaderStaticTest_" . $basename . " "; + my $prefix; + my $shaderType = &GetShaderType( $fxc_filename ); + if( $shaderType =~ m/^vs/i ) + { + $prefix = "vsh_"; + } + else + { + $prefix = "psh_"; + } + for( $i = 0; $i < scalar( @staticDefineNames ); $i++ ) + { + local( $name ) = @staticDefineNames[$i]; + if ( !length( $staticDefineInit{$name} ) ) + { + push @outputHeader, $prefix . "forgot_to_set_static_" . $name . " + "; + } + } + push @outputHeader, "0\n"; +} + +sub GetNewMainName +{ + local( $shadername ) = shift; + local( $combo ) = shift; + local( $i ); + $shadername =~ s/\./_/g; + local( $name ) = $shadername; + for( $i = 0; $i < scalar( @defineNames ); $i++ ) + { + local( $val ) = ( $combo % ( $defineMax[$i] - $defineMin[$i] + 1 ) ) + $defineMin[$i]; + $name .= "_" . $defineNames[$i] . "_" . $val; + $combo = $combo / ( $defineMax[$i] - $defineMin[$i] + 1 ); + } +# return $name; + return "main"; +} + +sub RenameMain +{ + local( $shadername ) = shift; + local( $combo ) = shift; + local( $name ) = &GetNewMainName( $shadername, $combo ); + return "/Dmain=$name /E$name "; +} + +sub GetShaderType +{ + local( $shadername ) = shift; # hack - use global variables + $shadername = $fxc_basename; + if( $shadername =~ m/ps30/i ) + { + if( $debug ) + { + return "ps_3_sw"; + } + else + { + return "ps_3_0"; + } + } + elsif( $shadername =~ m/ps20b/i ) + { + return "ps_2_b"; + } + elsif( $shadername =~ m/ps20/i ) + { + if( $debug ) + { + return "ps_2_sw"; + } + else + { + if( $ps2a ) + { + return "ps_2_a"; + } + else + { + return "ps_2_0"; + } + } + } + elsif( $shadername =~ m/ps14/i ) + { + return "ps_1_4"; + } + elsif( $shadername =~ m/ps11/i ) + { + return "ps_1_1"; + } + elsif( $shadername =~ m/vs30/i ) + { + if( $debug ) + { + return "vs_3_sw"; + } + else + { + return "vs_3_0"; + } + } + elsif( $shadername =~ m/vs20/i ) + { + if( $debug ) + { + return "vs_2_sw"; + } + else + { + return "vs_2_0"; + } + } + elsif( $shadername =~ m/vs14/i ) + { + return "vs_1_1"; + } + elsif( $shadername =~ m/vs11/i ) + { + return "vs_1_1"; + } + else + { + die "\n\nSHADERNAME = $shadername\n\n"; + } +} + +sub CalcNumCombos +{ + local( $i, $numCombos ); + $numCombos = 1; + for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ ) + { + $numCombos *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1; + } + for( $i = 0; $i < scalar( @staticDefineNames ); $i++ ) + { + $numCombos *= $staticDefineMax[$i] - $staticDefineMin[$i] + 1; + } + return $numCombos; +} + +sub CalcNumDynamicCombos +{ + local( $i, $numCombos ); + $numCombos = 1; + for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ ) + { + $numCombos *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1; + } + return $numCombos; +} + +sub CreateCFuncToCreateCompileCommandLine +{ + local( $out ) = ""; + + $out .= "\t\tOutputDebugString( \"compiling src:$fxc_filename vcs:$fxc_basename \" );\n"; + $out .= "\t\tchar tmp[128];\n"; + $out .= "\t\tsprintf( tmp, \"\%d\\n\", shaderID );\n"; + $out .= "\t\tOutputDebugString( tmp );\n"; + $out .= "\t\tstatic PrecompiledShaderByteCode_t byteCode;\n"; + if( scalar( @dynamicDefineNames ) + scalar( @staticDefineNames ) > 0 ) + { + $out .= "\t\tint nCombo = shaderID;\n"; + } + +# $out .= "\tvoid BuildCompileCommandLine( int nCombo, char *pResult, int maxLength )\n"; +# $out .= "\t{\n"; + $out .= "\t\tD3DXMACRO "; + $out .= "defineMacros"; + $out .= "["; + $out .= scalar( @dynamicDefineNames ) + scalar( @staticDefineNames ) + 1; # add 1 for null termination + $out .= "];\n"; + if( scalar( @dynamicDefineNames ) + scalar( @staticDefineNames ) > 0 ) + { + $out .= "\t\tchar tmpStringBuf[1024];\n"; + $out .= "\t\tchar *pTmpString = tmpStringBuf;\n\n"; + } + + local( $i ); + my $type = GetShaderType( $fxc_filename ); + for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ ) + { + $out .= "\t\tsprintf( pTmpString, \"%d\", nCombo % "; + $out .= ( $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1 ) + $dynamicDefineMin[$i]; + $out .= " );\n"; + $out .= "\t\tdefineMacros"; + $out .= "["; + $out .= $i; + $out .= "]"; + $out .= "\.Name = "; + $out .= "\"$dynamicDefineNames[$i]\";\n"; + + $out .= "\t\tint n$dynamicDefineNames[$i] = nCombo % "; + $out .= ( $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1 ) + $dynamicDefineMin[$i]; + $out .= ";\n"; + $out .= "\t\tUNUSED( n$dynamicDefineNames[$i] );\n"; + + $out .= "\t\tdefineMacros"; + $out .= "["; + $out .= $i; + $out .= "]"; + $out .= "\.Definition = "; + $out .= "pTmpString;\n"; + $out .= "\t\tpTmpString += strlen( pTmpString ) + 1;\n"; + + $out .= "\t\tsprintf( tmp, \"\%d\", n$dynamicDefineNames[$i] );\n"; + $out .= "\t\tOutputDebugString( \" $dynamicDefineNames[$i]"; + $out .= "=\" );\n"; + $out .= "\t\tOutputDebugString( tmp );\n"; + + $out .= "\t\tnCombo = nCombo / " . ( $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1 ) . ";\n"; + $out .= "\n"; + } + for( $i = 0; $i < scalar( @staticDefineNames ); $i++ ) + { + $out .= "\t\tsprintf( pTmpString, \"%d\", nCombo % "; + $out .= ( $staticDefineMax[$i] - $staticDefineMin[$i] + 1 ) + $staticDefineMin[$i]; + $out .= " );\n"; + $out .= "\t\tdefineMacros"; + $out .= "["; + $out .= $i + scalar( @dynamicDefineNames ); + $out .= "]"; + $out .= "\.Name = "; + $out .= "\"$staticDefineNames[$i]\";\n"; + + $out .= "\t\tint n$staticDefineNames[$i] = nCombo % "; + $out .= ( $staticDefineMax[$i] - $staticDefineMin[$i] + 1 ) + $staticDefineMin[$i]; + $out .= ";\n"; + $out .= "\t\tUNUSED( n$staticDefineNames[$i] );\n"; + + $out .= "\t\tdefineMacros"; + $out .= "["; + $out .= $i + scalar( @dynamicDefineNames ); + $out .= "]"; + $out .= "\.Definition = "; + $out .= "pTmpString;\n"; + $out .= "\t\tpTmpString += strlen( pTmpString ) + 1;\n"; + + $out .= "\t\tsprintf( tmp, \"\%d\", n$staticDefineNames[$i] );\n"; + $out .= "\t\tOutputDebugString( \" $staticDefineNames[$i]"; + $out .= "=\" );\n"; + $out .= "\t\tOutputDebugString( tmp );\n"; + + $out .= "\t\tnCombo = nCombo / " . ( $staticDefineMax[$i] - $staticDefineMin[$i] + 1 ) . ";\n"; + $out .= "\n"; + } + + $out .= "\t\tOutputDebugString( \"\\n\" );\n"; + + $cskipcode = $perlskipcode; + $cskipcode =~ s/\$/n/g; + $out .= "\t\tif( $cskipcode )\n\t\t{\n"; + $out .= "\t\t\tstatic char blah[4] = { 0, 0, 0, 0 };\n"; + $out .= "\t\t\tbyteCode.m_pRawData = blah;\n"; + $out .= "\t\t\tbyteCode.m_nSizeInBytes = 4;\n"; + $out .= "\t\t\treturn byteCode;\n"; + $out .= "\t\t}\n"; + + + + $out .= "\t\t// Must null terminate macros.\n"; + $out .= "\t\tdefineMacros["; + $out .= scalar( @dynamicDefineNames ) + scalar( @staticDefineNames ); + $out .= "]"; + $out .= ".Name = NULL;\n"; + $out .= "\t\tdefineMacros["; + $out .= scalar( @dynamicDefineNames ) + scalar( @staticDefineNames ); + $out .= "]"; + $out .= ".Definition = NULL;\n\n"; + + + $out .= "\t\tLPD3DXBUFFER pShader; // NOTE: THESE LEAK!!!\n"; + $out .= "\t\tLPD3DXBUFFER pErrorMessages; // NOTE: THESE LEAK!!!\n"; + $out .= "\t\tHRESULT hr = D3DXCompileShaderFromFile( \"u:\\\\hl2_e3_2004\\\\src_e3_2004\\\\materialsystem\\\\stdshaders\\\\$fxc_filename\",\n\t\t\tdefineMacros,\n\t\t\tNULL, // LPD3DXINCLUDE \n\t\t\t\"main\",\n\t\t\t\"$type\",\n\t\t\t0, // DWORD Flags\n\t\t\t&pShader,\n\t\t\t&pErrorMessages,\n\t\t\tNULL // LPD3DXCONSTANTTABLE *ppConstantTable\n\t\t\t );\n"; + $out .= "\t\tif( hr != D3D_OK )\n"; + $out .= "\t\t{\n"; + $out .= "\t\t\tconst char *pErrorMessageString = ( const char * )pErrorMessages->GetBufferPointer();\n"; + $out .= "\t\t\tOutputDebugString( pErrorMessageString );\n"; + $out .= "\t\t\tOutputDebugString( \"\\n\" );\n"; + $out .= "\t\t\tAssert( 0 );\n"; + $out .= "\t\t\tstatic char blah[4] = { 0, 0, 0, 0 };\n"; + $out .= "\t\t\tbyteCode.m_pRawData = blah;\n"; + $out .= "\t\t\tbyteCode.m_nSizeInBytes = 4;\n"; + $out .= "\t\t}\n"; + $out .= "\t\telse\n"; + $out .= "\t\t{\n"; + $out .= "\t\t\tbyteCode.m_pRawData = pShader->GetBufferPointer();\n"; + $out .= "\t\t\tbyteCode.m_nSizeInBytes = pShader->GetBufferSize();\n"; + $out .= "\t\t}\n"; + $out .= "\t\treturn byteCode;\n"; + return $out; +} + +#print "--------\n"; + +if ( $g_x360 ) +{ + $fxctmp = "fxctmp9_360_tmp"; +} +else +{ + $fxctmp = "fxctmp9_tmp"; +} + +if( !stat $fxctmp ) +{ + mkdir $fxctmp, 0777 || die $!; +} + +# suck in an input file (using includes) +#print "$fxc_filename..."; +@fxc = ReadInputFile( $fxc_filename ); + +# READ THE TOP OF THE FILE TO FIND SHADER COMBOS +foreach $line ( @fxc ) +{ + $line="" if ($g_x360 && ($line=~/\[PC\]/)); # line marked as [PC] when building for x360 + $line="" if (($g_x360 == 0) && ($line=~/\[XBOX\]/)); # line marked as [XBOX] when building for pc + + $line="" if ( ( $g_sfm == 0 ) && ( $line =~ /\[SFM\]/ ) ); # line marked as [SFM] when not building for sfm + $line="" if ( ( $g_sfm ) && ( $line =~ /\[\!SFM\]/ ) ); # line marked as [!SFM] when building for sfm + + if ( $fxc_basename =~ m/_ps(\d+\w?)$/i ) + { + my $psver = $1; + $line="" if (($line =~/\[ps\d+\w?\]/i) && ($line!~/\[ps$psver\]/i)); # line marked for a version of compiler and not what we build + } + if ( $fxc_basename =~ m/_vs(\d+\w?)$/i ) + { + my $vsver = $1; + $line="" if (($line =~/\[vs\d+\w?\]/i) && ($line!~/\[vs$vsver\]/i)); # line marked for a version of compiler and not what we build + } + + my $init_expr; + + # looks for something like [=0] after the base part of the combo definition. + if ( $line =~ /\[\s*\=\s*([^\]]+)\]/ ) + { + $init_expr = $1; # parse default init expression for combos + } + + $line=~s/\[[^\[\]]*\]//; # cut out all occurrences of + # square brackets and whatever is + # inside all these modifications + # to the line are seen later when + # processing skips and centroids + + next if( $line =~ m/^\s*$/ ); + + if( $line =~ m/^\s*\/\/\s*STATIC\s*\:\s*\"(.*)\"\s+\"(\d+)\.\.(\d+)\"/ ) + { + local( $name, $min, $max ); + $name = $1; + $min = $2; + $max = $3; + # print STDERR "STATIC: \"$name\" \"$min..$max\"\n"; + push @staticDefineNames, $name; + push @staticDefineMin, $min; + push @staticDefineMax, $max; + $staticDefineInit{$name} = $init_expr; + } + elsif( $line =~ m/^\s*\/\/\s*DYNAMIC\s*\:\s*\"(.*)\"\s+\"(\d+)\.\.(\d+)\"/ ) + { + local( $name, $min, $max ); + $name = $1; + $min = $2; + $max = $3; + # print STDERR "DYNAMIC: \"$name\" \"$min..$max\"\n"; + push @dynamicDefineNames, $name; + push @dynamicDefineMin, $min; + push @dynamicDefineMax, $max; + $dynamicDefineInit{$name} = $init_expr; + } +} +# READ THE WHOLE FILE AND FIND SKIP STATEMENTS +foreach $line ( @fxc ) +{ + if( $line =~ m/^\s*\/\/\s*SKIP\s*\s*\:\s*(.*)$/ ) + { + # print $1 . "\n"; + $perlskipcode .= "(" . $1 . ")||"; + push @perlskipcodeindividual, $1; + } +} + +if( defined $perlskipcode ) +{ + $perlskipcode .= "0"; + $perlskipcode =~ s/\n//g; +} +else +{ + $perlskipcode = "0"; +} + +# READ THE WHOLE FILE AND FIND CENTROID STATEMENTS +foreach $line ( @fxc ) +{ + if( $line =~ m/^\s*\/\/\s*CENTROID\s*\:\s*TEXCOORD(\d+)\s*$/ ) + { + $centroidEnable{$1} = 1; +# print "CENTROID: $1\n"; + } +} + +if( $spewCombos ) +{ + push @outputHeader, "#include \"windows.h\"\n"; +} + +#push @outputHeader, "\#include \"shaderlib\\baseshader.h\"\n"; +#push @outputHeader, "IShaderDynamicAPI *CBaseShader::s_pShaderAPI;\n"; + +# Go ahead an compute the mask of samplers that need to be centroid sampled +$centroidMask = 0; +foreach $centroidRegNum ( keys( %centroidEnable ) ) +{ +# print "THING: $samplerName $centroidRegNum\n"; + $centroidMask += 1 << $centroidRegNum; +} + +#printf "0x%x\n", $centroidMask; + +$numCombos = &CalcNumCombos(); +#print "$numCombos combos\n"; + + +if( $g_produceCompiledVcs && !$dynamic_compile ) +{ + open FOUT, ">>filelistgen.txt" || die "can't open filelistgen.txt"; + + print FOUT "**** generated by fxc_prep.pl ****\n"; + print FOUT "#BEGIN " . $fxc_basename . "\n"; + print FOUT "$fxc_filename" . "\n"; + print FOUT "#DEFINES-D:\n"; + for( $i = 0; $i < scalar( @dynamicDefineNames ); \$i++ ) + { + print FOUT "$dynamicDefineNames[$i]="; + print FOUT $dynamicDefineMin[$i]; + print FOUT ".."; + print FOUT $dynamicDefineMax[$i]; + print FOUT "\n"; + } + print FOUT "#DEFINES-S:\n"; + for( $i = 0; $i < scalar( @staticDefineNames ); \$i++ ) + { + print FOUT "$staticDefineNames[$i]="; + print FOUT $staticDefineMin[$i]; + print FOUT ".."; + print FOUT $staticDefineMax[$i]; + print FOUT "\n"; + } + print FOUT "#SKIP:\n"; + print FOUT "$perlskipcode\n"; + print FOUT "#COMMAND:\n"; + # first line + print FOUT "fxc.exe "; + print FOUT "/DTOTALSHADERCOMBOS=$numCombos "; + print FOUT "/DCENTROIDMASK=$centroidMask "; + print FOUT "/DNUMDYNAMICCOMBOS=" . &CalcNumDynamicCombos() . " "; + print FOUT "/DFLAGS=0x0 "; # Nothing here for now. + print FOUT "\n"; +#defines go here +# second line + print FOUT &RenameMain( $fxc_filename, $i ); + print FOUT "/T" . &GetShaderType( $fxc_filename ) . " "; + print FOUT "/DSHADER_MODEL_" . &ToUpper( &GetShaderType( $fxc_filename ) ) . "=1 "; + if( $nvidia ) + { + print FOUT "/DNV3X=1 "; # enable NV3X codepath + } + if ( $g_x360 ) + { + print FOUT "/D_X360=1 "; # shaders can identify X360 centric code + # print FOUT "/Xbe:2- "; # use the less-broken old back end + } + if( $debug ) + { + print FOUT "/Od "; # disable optimizations + print FOUT "/Zi "; # enable debug info + } +# print FOUT "/Zi "; # enable debug info + print FOUT "/nologo "; +# print FOUT "/Fhtmpshader.h "; + print FOUT "/Foshader.o "; + print FOUT "$fxc_filename"; + print FOUT ">output.txt 2>&1"; + print FOUT "\n"; + #end of command line + print FOUT "#END\n"; + print FOUT "**** end ****\n"; + + close FOUT; +} + +if ( $g_produceCppClasses ) +{ + # Write out the C++ helper class for picking shader combos + &WriteSkips(); + &WriteStaticHelperClasses(); + &WriteDynamicHelperClasses(); + my $incfilename = "$fxctmp\\$fxc_basename" . ".inc"; + if( $g_toomanycombos ) + { + unlink $incfilename; + print STDERR "ERROR: too many combos in $fxc_filename ($g_totalcombos > 4294967295)!\n"; + } + else + { + &WriteFile( $incfilename, join( "", @outputHeader ) ); + } +} + + + +if( $generateListingFile ) +{ + my $listFileName = "$fxctmp/$fxc_basename" . ".lst"; + print "writing $listFileName\n"; + if( !open FILE, ">$listFileName" ) + { + die; + } + print FILE @listingOutput; + close FILE; +} + + +@endTimes = times; + +$endTime = time; + +#printf "Elapsed user time: %.2f seconds!\n", $endTimes[0] - $startTimes[0]; +#printf "Elapsed system time: %.2f seconds!\n", $endTimes[1] - $startTimes[1]; +#printf "Elapsed child user time: %.2f seconds!\n", $endTimes[2] - $startTimes[2]; +#printf "Elapsed child system time: %.2f seconds!\n", $endTimes[3] - $startTimes[3]; + +#printf "Elapsed total time: %.2f seconds!\n", $endTime - $startTime; + + diff --git a/devtools/bin/psh_prep.pl b/devtools/bin/psh_prep.pl new file mode 100644 index 00000000..5aa49c11 --- /dev/null +++ b/devtools/bin/psh_prep.pl @@ -0,0 +1,333 @@ +use String::CRC32; +BEGIN {use File::Basename; push @INC, dirname($0); } +require "valve_perl_helpers.pl"; + +sub BuildDefineOptions +{ + local( $output ); + local( $combo ) = shift; + local( $i ); + for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ ) + { + local( $val ) = ( $combo % ( $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1 ) ) + $dynamicDefineMin[$i]; + $output .= "/D$dynamicDefineNames[$i]=$val "; + $combo = $combo / ( $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1 ); + } + for( $i = 0; $i < scalar( @staticDefineNames ); $i++ ) + { + local( $val ) = ( $combo % ( $staticDefineMax[$i] - $staticDefineMin[$i] + 1 ) ) + $staticDefineMin[$i]; + $output .= "/D$staticDefineNames[$i]=$val "; + $combo = $combo / ( $staticDefineMax[$i] - $staticDefineMin[$i] + 1 ); + } + return $output; +} + +sub CalcNumCombos +{ + local( $i, $numCombos ); + $numCombos = 1; + for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ ) + { + $numCombos *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1; + } + for( $i = 0; $i < scalar( @staticDefineNames ); $i++ ) + { + $numCombos *= $staticDefineMax[$i] - $staticDefineMin[$i] + 1; + } + return $numCombos; +} + +sub CalcNumDynamicCombos +{ + local( $i, $numCombos ); + $numCombos = 1; + for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ ) + { + $numCombos *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1; + } + return $numCombos; +} + +$g_dx9 = 1; + +while( 1 ) +{ + $psh_filename = shift; + + if( $psh_filename =~ m/-source/ ) + { + $g_SourceDir = shift; + } + elsif( $psh_filename =~ m/-x360/ ) + { + $g_x360 = 1; + } + else + { + last; + } +} + +$psh_filename =~ s/-----.*$//; + + +# Get the shader binary version number from a header file. +open FILE, "<$g_SourceDir\\public\\materialsystem\\shader_vcs_version.h" || die; +while( $line = ) +{ + if( $line =~ m/^\#define\s+SHADER_VCS_VERSION_NUMBER\s+(\d+)\s*$/ ) + { + $shaderVersion = $1; + last; + } +} +if( !defined $shaderVersion ) +{ + die "couldn't get shader version from shader_vcs_version.h"; +} +close FILE; + + + +local( @staticDefineNames ); +local( @staticDefineMin ); +local( @staticDefineMax ); +local( @dynamicDefineNames ); +local( @dynamicDefineMin ); +local( @dynamicDefineMax ); + +# Parse the combos. +open PSH, "<$psh_filename"; +while( ) +{ + last if( !m,^;, ); + s,^;\s*,,; + if( m/\s*STATIC\s*\:\s*\"(.*)\"\s+\"(\d+)\.\.(\d+)\"/ ) + { + local( $name, $min, $max ); + $name = $1; + $min = $2; + $max = $3; +# print "\"STATIC: $name\" \"$min..$max\"\n"; + if (/\[(.*)\]/) + { + $platforms=$1; + next if ( ($g_x360) && (!($platforms=~/XBOX/i)) ); + next if ( (!$g_x360) && (!($platforms=~/PC/i)) ); + } + push @staticDefineNames, $name; + push @staticDefineMin, $min; + push @staticDefineMax, $max; + } + elsif( m/\s*DYNAMIC\s*\:\s*\"(.*)\"\s+\"(\d+)\.\.(\d+)\"/ ) + { + local( $name, $min, $max ); + $name = $1; + $min = $2; + $max = $3; +# print "\"DYNAMIC: $name\" \"$min..$max\"\n"; + if (/\[(.*)\]/) + { + $platforms=$1; + next if ( ($g_x360) && (!($platforms=~/XBOX/i)) ); + next if ( (!$g_x360) && (!($platforms=~/PC/i)) ); + } + push @dynamicDefineNames, $name; + push @dynamicDefineMin, $min; + push @dynamicDefineMax, $max; + } +} +close PSH; + +$numCombos = &CalcNumCombos(); +$numDynamicCombos = &CalcNumDynamicCombos(); +print "$psh_filename\n"; +#print "$numCombos combos\n"; +#print "$numDynamicCombos dynamic combos\n"; + +if( $g_x360 ) +{ + $pshtmp = "pshtmp9_360"; +} +elsif( $g_dx9 ) +{ + $pshtmp = "pshtmp9"; +} +else +{ + $pshtmp = "pshtmp8"; +} +$basename = $psh_filename; +$basename =~ s/\.psh$//i; + +for( $shaderCombo = 0; $shaderCombo < $numCombos; $shaderCombo++ ) +{ + my $tempFilename = "shader$shaderCombo.o"; + unlink $tempFilename; + + if( $g_x360 ) + { + $cmd = "$g_SourceDir\\x360xdk\\bin\\win32\\psa /D_X360=1 /Foshader$shaderCombo.o /nologo " . &BuildDefineOptions( $shaderCombo ) . "$psh_filename > NIL"; + } + else + { + $cmd = "$g_SourceDir\\dx9sdk\\utilities\\psa /Foshader$shaderCombo.o /nologo " . &BuildDefineOptions( $shaderCombo ) . "$psh_filename > NIL"; + } + + if( !stat $pshtmp ) + { + mkdir $pshtmp, 0777 || die $!; + } + +# print $cmd . "\n"; + system $cmd || die $!; + + # Make sure a file got generated because sometimes the die above won't happen on compile errors. + my $filesize = (stat $tempFilename)[7]; + if ( !$filesize ) + { + die "Error compiling shader$shaderCombo.o"; + } + + push @outputHeader, @hdr; +} + +$basename =~ s/\.fxc//gi; +push @outputHeader, "static PrecompiledShaderByteCode_t " . $basename . "_pixel_shaders[" . $numCombos . "] = \n"; +push @outputHeader, "{\n"; +local( $j ); +for( $j = 0; $j < $numCombos; $j++ ) +{ + local( $thing ) = "pixelShader_" . $basename . "_" . $j; + push @outputHeader, "\t{ " . "$thing, sizeof( $thing ) },\n"; +} +push @outputHeader, "};\n"; + +push @outputHeader, "struct $basename" . "PixelShader_t : public PrecompiledShader_t\n"; +push @outputHeader, "{\n"; +push @outputHeader, "\t$basename" . "PixelShader_t()\n"; +push @outputHeader, "\t{\n"; +push @outputHeader, "\t\tm_nFlags = 0;\n"; +push @outputHeader, "\t\tm_pByteCode = " . $basename . "_pixel_shaders;\n"; +push @outputHeader, "\t\tm_nShaderCount = $numCombos;\n"; +#push @outputHeader, "\t\tm_nDynamicCombos = m_nShaderCount;\n"; +push @outputHeader, "\t\t// NOTE!!! psh_prep.pl shaders are always static combos!\n"; +push @outputHeader, "\t\tm_nDynamicCombos = 1;\n"; +push @outputHeader, "\t\tm_pName = \"$basename\";\n"; +if( $basename =~ /vs\d\d/ ) # hack +{ + push @outputHeader, "\t\tGetShaderDLL()->InsertPrecompiledShader( PRECOMPILED_VERTEX_SHADER, this );\n"; +} +else +{ + push @outputHeader, "\t\tGetShaderDLL()->InsertPrecompiledShader( PRECOMPILED_PIXEL_SHADER, this );\n"; +} +push @outputHeader, "\t}\n"; +push @outputHeader, "\tvirtual const PrecompiledShaderByteCode_t &GetByteCode( int shaderID )\n"; +push @outputHeader, "\t{\n"; +push @outputHeader, "\t\treturn m_pByteCode[shaderID];\n"; +push @outputHeader, "\t}\n"; +push @outputHeader, "};\n"; + +push @outputHeader, "static $basename" . "PixelShader_t $basename" . "_PixelShaderInstance;\n"; + + +&MakeDirHier( "shaders/psh" ); + +my $vcsName = ""; +if( $g_x360 ) +{ + $vcsName = $basename . ".360.vcs"; +} +else +{ + $vcsName = $basename . ".vcs"; +} + +open COMPILEDSHADER, ">shaders/psh/$vcsName" || die; +binmode( COMPILEDSHADER ); + +# +# Write out the part of the header that we know. . we'll write the rest after writing the object code. +# + +#print $numCombos . "\n"; + +# Pack arguments +my $sInt = "i"; +my $uInt = "I"; +if ( $g_x360 ) +{ + # Change arguments to "big endian long" + $sInt = "N"; + $uInt = "N"; +} + +open PSH, "<$psh_filename"; +my $crc = crc32( *PSH ); +close PSH; +#print STDERR "crc for $psh_filename: $crc\n"; + +# version +print COMPILEDSHADER pack $sInt, 4; +# totalCombos +print COMPILEDSHADER pack $sInt, $numCombos; +# dynamic combos +print COMPILEDSHADER pack $sInt, $numDynamicCombos; +# flags +print COMPILEDSHADER pack $uInt, 0x0; # nothing here for now. +# centroid mask +print COMPILEDSHADER pack $uInt, 0; +# reference size for diffs +print COMPILEDSHADER pack $uInt, 0; +# crc32 of the source code +print COMPILEDSHADER pack $uInt, $crc; + +my $beginningOfDir = tell COMPILEDSHADER; + +# Write out a blank directionary. . we'll fill it in later. +for( $i = 0; $i < $numCombos; $i++ ) +{ + # offset from beginning of file. + print COMPILEDSHADER pack $sInt, 0; + # size + print COMPILEDSHADER pack $sInt, 0; +} + +my $startByteCode = tell COMPILEDSHADER; +my @byteCodeStart; +my @byteCodeSize; + +# Write out the shader object code. +for( $shaderCombo = 0; $shaderCombo < $numCombos; $shaderCombo++ ) +{ + my $filename = "shader$shaderCombo\.o"; + my $filesize = (stat $filename)[7]; + + $byteCodeStart[$shaderCombo] = tell COMPILEDSHADER; + $byteCodeSize[$shaderCombo] = $filesize; + open SHADERBYTECODE, "<$filename"; + binmode SHADERBYTECODE; + + my $bin; + my $numread = read SHADERBYTECODE, $bin, $filesize; +# print "filename: $filename numread: $numread filesize: $filesize\n"; + close SHADERBYTECODE; + unlink $filename; + + print COMPILEDSHADER $bin; +} + +# Seek back to the directory and write it out. +seek COMPILEDSHADER, $beginningOfDir, 0; +for( $i = 0; $i < $numCombos; $i++ ) +{ + # offset from beginning of file. + print COMPILEDSHADER pack $sInt, $byteCodeStart[$i]; + # size + print COMPILEDSHADER pack $sInt, $byteCodeSize[$i]; +} + +close COMPILEDSHADER; + + diff --git a/devtools/bin/shaderinfo.pl b/devtools/bin/shaderinfo.pl new file mode 100644 index 00000000..ae0b96c8 --- /dev/null +++ b/devtools/bin/shaderinfo.pl @@ -0,0 +1,36 @@ +#! perl + +my $fname=shift || die "format is shaderinfo blah.vcs"; + +open(SHADER, $fname) || die "can't open $fname"; +binmode SHADER; + +read(SHADER,$header,20); +($ver,$ntotal,$ndynamic,$flags,$centroidmask)=unpack("LLLLL",$header); + +#print "Version $ver total combos=$ntotal, num dynamic combos=$ndynamic,\n flags=$flags, centroid mask=$centroidmask\n"; + +read(SHADER,$refsize,4); +$refsize=unpack("L",$refsize); +#print "Size of reference shader for diffing=$refsize\n"; + +seek(SHADER,$refsize,1); + +$nskipped_combos=0; +for(1..$ntotal) + { + read(SHADER,$combodata,8); + ($ofs,$combosize)=unpack("LL",$combodata); + if ( $ofs == 0xffffffff) + { + $nskipped_combos++; + } + else + { + } + } +#print "$nskipped_combos skipped, for an actual total of ",$ntotal-$nskipped_combos,"\n"; +#print "Real to skipped ratio = ",($ntotal-$nskipped_combos)/$ntotal,"\n"; +# csv output - name, real combos, virtual combos, dynamic combos +my $real_combos=$ntotal-$nskipped_combos; +print "$fname,$real_combos,$ntotal,$ndynamic\n"; diff --git a/devtools/bin/splitdiff3.pl b/devtools/bin/splitdiff3.pl new file mode 100644 index 00000000..e38b493a --- /dev/null +++ b/devtools/bin/splitdiff3.pl @@ -0,0 +1,54 @@ +$infilename = shift; +$outfilename1 = shift; +$outfilename2 = shift; +open INPUT, $infilename || die; +@input = ; +close INPUT; + +open MERGEDMINE, ">$outfilename1" || die; +open MERGEDTHEIRS, ">$outfilename2" || die; + +for( $i = 0; $i < scalar( @input ); $i++ ) +{ + $line = $input[$i]; + + if( $line =~ m/^(.*)<<<<<<>>>>>>/ ) + { + $first = $second = 0; + print MERGEDTHEIRS $1; + next; + } + + if( $first ) + { + print MERGEDMINE $line; + } + elsif( $second ) + { + print MERGEDTHEIRS $line; + } + else + { + print MERGEDMINE $line; + print MERGEDTHEIRS $line; + } +} + +close MERGEDMINE; +close MERGEDTHEIRS; diff --git a/devtools/bin/uniqifylist.pl b/devtools/bin/uniqifylist.pl new file mode 100644 index 00000000..d8d40afd --- /dev/null +++ b/devtools/bin/uniqifylist.pl @@ -0,0 +1,6 @@ +foreach $_ (sort <> ) +{ + next if( defined( $prevline ) && $_ eq $prevline ); + $prevline = $_; + print; +} diff --git a/devtools/bin/updateshaders.pl b/devtools/bin/updateshaders.pl new file mode 100644 index 00000000..c0697684 --- /dev/null +++ b/devtools/bin/updateshaders.pl @@ -0,0 +1,305 @@ +use String::CRC32; +BEGIN {use File::Basename; push @INC, dirname($0); } +require "valve_perl_helpers.pl"; + +$dynamic_compile = defined $ENV{"dynamic_shaders"} && $ENV{"dynamic_shaders"} != 0; + +$depnum = 0; +$baseSourceDir = "."; + +my %dep; + +sub GetAsmShaderDependencies_R +{ + local( $shadername ) = shift; + local( *SHADER ); + + open SHADER, "<$shadername"; + while( ) + { + if( m/^\s*\#\s*include\s+\"(.*)\"/ ) + { + # make sure it isn't in there already. + if( !defined( $dep{$1} ) ) + { + $dep{$1} = 1; + GetAsmShaderDependencies_R( $1 ); + } + } + } + close SHADER; +} + +sub GetAsmShaderDependencies +{ + local( $shadername ) = shift; + undef %dep; + GetAsmShaderDependencies_R( $shadername ); +# local( $i ); +# foreach $i ( keys( %dep ) ) +# { +# print "$shadername depends on $i\n"; +# } + return keys( %dep ); +} + +sub GetShaderType +{ + my $shadername = shift; + my $shadertype; + if( $shadername =~ m/\.vsh/i ) + { + $shadertype = "vsh"; + } + elsif( $shadername =~ m/\.psh/i ) + { + $shadertype = "psh"; + } + elsif( $shadername =~ m/\.fxc/i ) + { + $shadertype = "fxc"; + } + else + { + die; + } + return $shadertype; +} + +sub GetShaderSrc +{ + my $shadername = shift; + if ( $shadername =~ m/^(.*)-----/i ) + { + return $1; + } + else + { + return $shadername; + } +} + +sub GetShaderBase +{ + my $shadername = shift; + if ( $shadername =~ m/-----(.*)$/i ) + { + return $1; + } + else + { + my $shadertype = &GetShaderType( $shadername ); + $shadername =~ s/\.$shadertype//i; + return $shadername; + } +} + +sub DoAsmShader +{ + my $argstring = shift; + my $shadername = &GetShaderSrc( $argstring ); + my $shaderbase = &GetShaderBase( $argstring ); + my $shadertype = &GetShaderType( $argstring ); + my $incfile = ""; + if( $shadertype eq "fxc" || $shadertype eq "vsh" ) + { + $incfile = $shadertype . "tmp9" . $g_tmpfolder . "\\$shaderbase.inc "; + } + + my $vcsfile = $shaderbase . $g_vcsext; + my $bWillCompileVcs = 1; + if( ( $shadertype eq "fxc") && $dynamic_compile ) + { + $bWillCompileVcs = 0; + } + if( $shadercrcpass{$argstring} ) + { + $bWillCompileVcs = 0; + } + + if( $bWillCompileVcs ) + { + &output_makefile_line( $incfile . "shaders\\$shadertype\\$vcsfile: $shadername ..\\..\\devtools\\bin\\updateshaders.pl ..\\..\\devtools\\bin\\" . $shadertype . "_prep.pl" . " @dep\n") ; + } + else + { + # psh files don't need a rule at this point since they don't have inc files and we aren't compiling a vcs. + if( $shadertype eq "fxc" || $shadertype eq "vsh" ) + { + &output_makefile_line( $incfile . ": $shadername ..\\..\\devtools\\bin\\updateshaders.pl ..\\..\\devtools\\bin\\" . $shadertype . "_prep.pl" . " @dep\n") ; + } + } + + + my $x360switch = ""; + my $moreswitches = ""; + if( !$bWillCompileVcs && $shadertype eq "fxc" ) + { + $moreswitches .= "-novcs "; + } + if( $g_x360 ) + { + $x360switch = "-x360"; + + if( $bWillCompileVcs && ( $shaderbase =~ m/_ps20$/i ) ) + { + $moreswitches .= "-novcs "; + $bWillCompileVcs = 0; + } + } + + # if we are psh and we are compiling the vcs, we don't need this rule. + if( !( $shadertype eq "psh" && !$bWillCompileVcs ) ) + { + &output_makefile_line( "\tperl $g_SourceDir\\devtools\\bin\\" . $shadertype . "_prep.pl $moreswitches $x360switch -source \"$g_SourceDir\" $argstring\n") ; + } + + if( $bWillCompileVcs ) + { + &output_makefile_line( "\techo $shadername>> filestocopy.txt\n") ; + my $dep; + foreach $dep( @dep ) + { + &output_makefile_line( "\techo $dep>> filestocopy.txt\n") ; + } + } + &output_makefile_line( "\n") ; +} + +if( scalar( @ARGV ) == 0 ) +{ + die "Usage updateshaders.pl shaderprojectbasename\n\tie: updateshaders.pl stdshaders_dx6\n"; +} + +$g_x360 = 0; +$g_tmpfolder = "_tmp"; +$g_vcsext = ".vcs"; + +while( 1 ) +{ + $inputbase = shift; + + if( $inputbase =~ m/-source/ ) + { + $g_SourceDir = shift; + } + elsif( $inputbase =~ m/-x360/ ) + { + $g_x360 = 1; + $g_tmpfolder = "_360_tmp"; + $g_vcsext = ".360.vcs"; + } + elsif( $inputbase =~ m/-execute/ ) + { + $g_execute = 1; + } + elsif( $inputbase =~ m/-nv3x/ ) + { + $nv3x = 1; + } + else + { + last; + } +} + +my @srcfiles = &LoadShaderListFile( $inputbase ); + +open MAKEFILE, ">makefile\.$inputbase"; +open COPYFILE, ">makefile\.$inputbase\.copy"; +open INCLIST, ">inclist.txt"; +open VCSLIST, ">vcslist.txt"; + +# make a default dependency that depends on all of the shaders. +&output_makefile_line( "default: ") ; +foreach $shader ( @srcfiles ) +{ + my $shadertype = &GetShaderType( $shader ); + my $shaderbase = &GetShaderBase( $shader ); + my $shadersrc = &GetShaderSrc( $shader ); + if( $shadertype eq "fxc" || $shadertype eq "vsh" ) + { + # We only generate inc files for fxc and vsh files. + my $incFileName = "$shadertype" . "tmp9" . $g_tmpfolder . "\\" . $shaderbase . "\.inc"; + &output_makefile_line( " $incFileName" ); + &output_inclist_line( "$incFileName\n" ); + } + + my $vcsfile = $shaderbase . $g_vcsext; + + my $compilevcs = 1; + if( $shadertype eq "fxc" && $dynamic_compile ) + { + $compilevcs = 0; + } + if( $g_x360 && ( $shaderbase =~ m/_ps20$/i ) ) + { + $compilevcs = 0; + } + if( $compilevcs ) + { + my $vcsFileName = "..\\..\\..\\game\\platform\\shaders\\$shadertype\\$shaderbase" . $g_vcsext; + # We want to check for perforce operations even if the crc matches in the event that a file has been manually reverted and needs to be checked out again. + &output_vcslist_line( "$vcsFileName\n" ); + $shadercrcpass{$shader} = &CheckCRCAgainstTarget( $shadersrc, $vcsFileName, 0 ); + if( $shadercrcpass{$shader} ) + { + $compilevcs = 0; + } + } + if( $compilevcs ) + { + &output_makefile_line( " shaders\\$shadertype\\$vcsfile" ); + # emit a list of vcs files to copy to the target since we want to build them. + &output_copyfile_line( GetShaderSrc($shader) . "-----" . GetShaderBase($shader) . "\n" ); + } +} +&output_makefile_line( "\n\n") ; + +# Insert all of our vertex shaders and depencencies +$lastshader = ""; +foreach $shader ( @srcfiles ) +{ + my $currentshader = &GetShaderSrc( $shader ); + if ( $lastshader ne $currentshader ) + { + $lastshader = $currentshader; + @dep = &GetAsmShaderDependencies( $lastshader ); + } + &DoAsmShader( $shader ); +} +close VCSLIST; +close INCLIST; +close COPYFILE; +close MAKEFILE; + +# nuke the copyfile if it is zero length +if( ( stat "makefile\.$inputbase\.copy" )[7] == 0 ) +{ + unlink "makefile\.$inputbase\.copy"; +} + +sub output_makefile_line +{ + local ($_)=@_; + print MAKEFILE $_; +} + +sub output_copyfile_line +{ + local ($_)=@_; + print COPYFILE $_; +} + +sub output_vcslist_line +{ + local ($_)=@_; + print VCSLIST $_; +} + +sub output_inclist_line +{ + local ($_)=@_; + print INCLIST $_; +} + diff --git a/devtools/bin/valve_perl_helpers.pl b/devtools/bin/valve_perl_helpers.pl new file mode 100644 index 00000000..e0fc53f4 --- /dev/null +++ b/devtools/bin/valve_perl_helpers.pl @@ -0,0 +1,539 @@ +sub BackToForwardSlash +{ + my( $path ) = shift; + $path =~ s,\\,/,g; + return $path; +} + +sub RemoveFileName +{ + my( $in ) = shift; + $in = &BackToForwardSlash( $in ); + $in =~ s,/[^/]*$,,; + return $in; +} + +sub RemovePath +{ + my( $in ) = shift; + $in = &BackToForwardSlash( $in ); + $in =~ s,^(.*)/([^/]*)$,$2,; + return $in; +} + +sub MakeDirHier +{ + my( $in ) = shift; +# print "MakeDirHier( $in )\n"; + $in = &BackToForwardSlash( $in ); + my( @path ); + while( $in =~ m,/, ) # while $in still has a slash + { + my( $end ) = &RemovePath( $in ); + push @path, $end; +# print $in . "\n"; + $in = &RemoveFileName( $in ); + } + my( $i ); + my( $numelems ) = scalar( @path ); + my( $curpath ); + for( $i = $numelems - 1; $i >= 0; $i-- ) + { + $curpath .= "/" . $path[$i]; + my( $dir ) = $in . $curpath; + if( !stat $dir ) + { +# print "mkdir $dir\n"; + mkdir $dir, 0777; + } + } +} + +sub FileExists +{ + my $filename = shift; + my @statresult = stat $filename; + my $iswritable = @statresult != 0; + return $iswritable; +} + +sub MakeFileWritable +{ + my $filename = shift; + if ( &FileExists( $filename ) ) + { + chmod 0666, $filename || die; + } +} + +sub MakeFileReadOnly +{ + my $filename = shift; + chmod 0444, $filename || die; +} + +# Run a command and get stdout and stderr to an array +sub RunCommand +{ + my $cmd = shift; +# print STDERR "command: $cmd\n"; + system "$cmd > cmdout.txt 2>&1" || die; + local( *FILE ); + open FILE, "; +# print STDERR "command output: @output\n"; + close FILE; + unlink "cmdout.txt" || die; + return @output; +} + +sub PerforceEditOrAdd +{ + return; + my $filename = shift; + my $changelistarg = shift; + + # Is the file on the client? + my $cmd = "p4 fstat \"$filename\""; + my @p4output = &RunCommand( $cmd ); + my $p4output = join "", @p4output; + if( $p4output =~ m/no such file/ ) + { + # not on client. . add + my $cmd = "p4 add $changelistarg $filename"; + my @p4output = &RunCommand( $cmd ); + my $p4output = join "", @p4output; + if( $p4output =~ m/opened for add/ ) + { + print $p4output; + return; + } + print "ERROR: $p4output"; + return; + } + + # The file is known to be on the client at this point. + + # Is it open for edit? + if( $p4output =~ m/action edit/ ) + { + # Is is open for edit, let's see if it's still different. + # check for opened files that are not different from the revision in the depot. + my $cmd = "p4 diff -sr \"$filename\""; + my @p4output = &RunCommand( $cmd ); + my $outputstring = join "", @p4output; + # check for empty string + if( !( $outputstring =~ m/^\s*$/ ) ) + { + my $cmd = "p4 revert \"$filename\""; + my @p4output = &RunCommand( $cmd ); + my $outputstring = join "", @p4output; + print $outputstring; + return; + } + } + + # check for unopened files that are different from the revision in the depot. + my $cmd = "p4 diff -se \"$filename\""; + my @p4output = &RunCommand( $cmd ); + my $outputstring = join "", @p4output; + # check for empty string + if( $outputstring =~ m/^\s*$/ ) + { + &MakeFileReadOnly( $filename ); + return; + } + + # We need to edit the file since it is known to be different here. + my $cmd = "p4 edit $changelistarg \"$filename\""; + my @p4output = &RunCommand( $cmd ); + + my $line; + foreach $line ( @p4output ) + { + if( $line =~ m/not on client/ ) + { + #print "notonclient..."; + print "ERROR: @p4output\n"; + return; + } + if( $line =~ m/currently opened for edit/ ) + { + return; + } + if( $line =~ m/opened for edit/ ) + { + print $line; + } + } +} + +sub FileIsWritable +{ + local( $filename ) = shift; + local( @statresult ) = stat $filename; + local( $mode, $iswritable ); + $mode = oct( $statresult[2] ); + $iswritable = ( $mode & 2 ) != 0; + return $iswritable; +} + +sub TouchFile +{ + my $filename = shift; + if( !&FileExists( $filename ) ) + { + if( !open FILE, ">$filename" ) + { + die; + } + close FILE; + } + my $now = time; + local( *FILE ); + utime $now, $now, $filename; +} + +sub FileExistsInPerforce +{ + my $filename = shift; + my @output = &RunCommand( "p4 fstat $filename" ); + my $line; + foreach $line (@output) + { + if( $line =~ m/no such file/ ) + { + return 0; + } + } + return 1; +} + +sub PerforceWriteFile +{ + my $filename = shift; + my $filecontents = shift; + + # Make the target vcs writable if it exists + MakeFileWritable( $filename ); + + # Write the file. + local( *FP ); + open FP, ">$filename"; + print FP $filecontents; + close FP; +} + +sub WriteFile +{ + my $filename = shift; + my $filecontents = shift; + + # Make the target vcs writable if it exists + MakeFileWritable( $filename ); + + # Write the file. + local( *FP ); + open FP, ">$filename"; + print FP $filecontents; + close FP; +} + +sub PrintCleanPerforceOutput +{ + my $line; + while( $line = shift ) + { + if( $line =~ m/currently opened/i ) + { + next; + } + if( $line =~ m/already opened for edit/i ) + { + next; + } + if( $line =~ m/also opened/i ) + { + next; + } + if( $line =~ m/add of existing file/i ) + { + next; + } + print $line; + } +} + +# HACK!!!! Need to pass something in to do this rather than hard coding. +sub NormalizePerforceFilename +{ + my $line = shift; + + # remove newlines. + $line =~ s/\n//; + # downcase. + $line =~ tr/[A-Z]/[a-z]/; + # backslash to forwardslash + $line =~ s,\\,/,g; + + # for inc files HACK! + $line =~ s/^.*(fxctmp9.*)/$1/i; + $line =~ s/^.*(vshtmp9.*)/$1/i; + + # for vcs files. HACK! + $line =~ s,^.*game/platform/shaders/,,i; + + return $line; +} + +sub MakeSureFileExists +{ + local( $filename ) = shift; + local( $testexists ) = shift; + local( $testwrite ) = shift; + + local( @statresult ) = stat $filename; + if( !@statresult && $testexists ) + { + die "$filename doesn't exist!\n"; + } + local( $mode, $iswritable ); + $mode = oct( $statresult[2] ); + $iswritable = ( $mode & 2 ) != 0; + if( !$iswritable && $testwrite ) + { + die "$filename isn't writable!\n"; + } +} + +sub LoadShaderListFile_GetShaderType +{ + my $shadername = shift; + my $shadertype; + if( $shadername =~ m/\.vsh/i ) + { + $shadertype = "vsh"; + } + elsif( $shadername =~ m/\.psh/i ) + { + $shadertype = "psh"; + } + elsif( $shadername =~ m/\.fxc/i ) + { + $shadertype = "fxc"; + } + else + { + die; + } + return $shadertype; +} + +sub LoadShaderListFile_GetShaderSrc +{ + my $shadername = shift; + if ( $shadername =~ m/^(.*)-----/i ) + { + return $1; + } + else + { + return $shadername; + } +} + +sub LoadShaderListFile_GetShaderBase +{ + my $shadername = shift; + if ( $shadername =~ m/-----(.*)$/i ) + { + return $1; + } + else + { + my $shadertype = &LoadShaderListFile_GetShaderType( $shadername ); + $shadername =~ s/\.$shadertype//i; + return $shadername; + } +} + +sub LoadShaderListFile +{ + my $inputbase = shift; + + my @srcfiles; + &MakeSureFileExists( "$inputbase.txt", 1, 0 ); + + open SHADERLISTFILE, "<$inputbase.txt" || die; + my $line; + while( $line = ) + { + $line =~ s/\/\/.*$//; # remove comments "//..." + $line =~ s/^\s*//; # trim leading whitespace + $line =~ s/\s*$//; # trim trailing whitespace + next if( $line =~ m/^\s*$/ ); + if( $line =~ m/\.fxc/ || $line =~ m/\.vsh/ || $line =~ m/\.psh/ ) + { + my $shaderbase = &LoadShaderListFile_GetShaderBase( $line ); + + if( $ENV{"DIRECTX_FORCE_MODEL"} =~ m/^30$/i ) # forcing all shaders to be ver. 30 + { + my $targetbase = $shaderbase; + $targetbase =~ s/_ps2x/_ps30/i; + $targetbase =~ s/_ps20b/_ps30/i; + $targetbase =~ s/_ps20/_ps30/i; + $targetbase =~ s/_vs20/_vs30/i; + $targetbase =~ s/_vsxx/_vs30/i; + push @srcfiles, ( $line . "-----" . $targetbase ); + } + else + { + if( $shaderbase =~ m/_ps2x/i ) + { + my $targetbase = $shaderbase; + $targetbase =~ s/_ps2x/_ps20/i; + push @srcfiles, ( $line . "-----" . $targetbase ); + + $targetbase = $shaderbase; + $targetbase =~ s/_ps2x/_ps20b/i; + push @srcfiles, ( $line . "-----" . $targetbase ); + } + elsif( $shaderbase =~ m/_vsxx/i ) + { + my $targetbase = $shaderbase; + $targetbase =~ s/_vsxx/_vs20/i; + push @srcfiles, ( $line . "-----" . $targetbase ); + } + else + { + push @srcfiles, ( $line . "-----" . $shaderbase ); + } + } + } + } + close SHADERLISTFILE; + return @srcfiles; +} + +sub ReadInputFileWithIncludes +{ + local( $filename ) = shift; +# print STDERR "ReadInputFileWithIncludes: $filename\n"; + + local( *INPUT ); + local( $output ); + +# print STDERR "before open\n"; + open INPUT, "<$filename" || die; +# print STDERR "after open\n"; + + local( $line ); + while( $line = ) + { +# print STDERR $line; + if( $line =~ m/\#include\s+\"(.*)\"/i ) + { + $output.= ReadInputFileWithIncludes( $1 ); + } + else + { + $output .= $line; + } + } + + close INPUT; + return $output; +} + +sub GetCRCFromSourceFile +{ + my $filename = shift; + my $data = &ReadInputFileWithIncludes( $filename ); +# print STDERR $data; + $crc = crc32( $data ); +# print STDERR "GetCRCFromSourceFile: $crc\n"; + return $crc; +} + +sub GetCRCFromVCSFile +{ + my $filename = shift; +# print STDERR "GetCRCFromVCSFile $filename\n"; + local( *FP ); + open FP, "<$filename" || die "GetCRCFromVCSFile: can't open file $filename\n"; + binmode( FP ); + + # unpack arguments + my $sInt = "i"; + my $uInt = "I"; + if( $filename =~ m/\.360\./ ) + { + # Change arguments to "big endian long" + $sInt = "N"; + $uInt = "N"; + } + + my $header; + read FP, $header, 7 * 4 || die "updateshaders.pl:GetCRCFromVCSFile: can't read header for $filename\n"; + my $version,$numCombos,$numDynamicCombos,$flags,$centroidMask,$refSize,$crc; + ($version,$numCombos,$numDynamicCombos,$flags,$centroidMask,$refSize,$crc) = unpack "$sInt$sInt$sInt$uInt$uInt$uInt$uInt", $header; + unless( $version == 4 || $version == 5 || $version == 6 ) + { + print STDERR "ERROR: GetCRCFromVCSFile: $filename is version $version\n"; + return 0; + } +# print STDERR "version: $version\n"; +# print STDERR "numCombos: $numCombos\n"; +# print STDERR "numDynamicCombos: $numDynamicCombos\n"; +# print STDERR "flags: $flags\n"; +# print STDERR "centroidMask: $centroidMask\n"; +# print STDERR "refSize: $refSize\n"; +# print STDERR "GetCRCFromVCSFile: $crc\n"; + close( FP ); + return $crc; +} + +sub CheckCRCAgainstTarget +{ + my $srcFileName = shift; + my $vcsFileName = shift; + my $warn = shift; + + # Make sure both files exist. +# print STDERR "$srcFileName doesn't exist\n" if( !( -e $srcFileName ) ); +# print STDERR "$vcsFileName doesn't exist\n" if( !( -e $vcsFileName ) ); + if( !( -e $srcFileName ) ) + { + if( $warn ) + { + print "$srcFileName missing\n"; + } + return 0; + } + if( !( -e $vcsFileName ) ) + { + if( $warn ) + { + print "$vcsFileName missing\n"; + } + return 0; + } +# print STDERR "CheckCRCAgainstTarget( $srcFileName, $vcsFileName );\n"; +# print STDERR "vcsFileName: $vcsFileName\n"; +# print STDERR "vcsFileName: $srcFileName\n"; + my $vcsCRC = &GetCRCFromVCSFile( $vcsFileName ); + my $srcCRC = &GetCRCFromSourceFile( $srcFileName ); + if( $warn && ( $vcsCRC != $srcCRC ) ) + { + print "$vcsFileName checksum ($vcsCRC) != $srcFileName checksum: ($srcCRC)\n"; + } + +# return 0; # use this to skip crc checking. +# if( $vcsCRC == $srcCRC ) +# { +# print STDERR "CRC passed for $srcFileName $vcsFileName $vcsCRC\n"; +# } + return $vcsCRC == $srcCRC; +} + +1; diff --git a/devtools/bin/vsh_prep.pl b/devtools/bin/vsh_prep.pl new file mode 100644 index 00000000..1ba8b6f1 --- /dev/null +++ b/devtools/bin/vsh_prep.pl @@ -0,0 +1,1106 @@ +use String::CRC32; +BEGIN {use File::Basename; push @INC, dirname($0); } +require "valve_perl_helpers.pl"; + +sub WriteHelperVar +{ + local( $name ) = shift; + local( $min ) = shift; + local( $max ) = shift; + local( $varname ) = "m_n" . $name; + local( $boolname ) = "m_b" . $name; + push @outputHeader, "private:\n"; + push @outputHeader, "\tint $varname;\n"; + push @outputHeader, "#ifdef _DEBUG\n"; + push @outputHeader, "\tbool $boolname;\n"; + push @outputHeader, "#endif\n"; + push @outputHeader, "public:\n"; + # int version of set function + push @outputHeader, "\tvoid Set" . $name . "( int i )\n"; + push @outputHeader, "\t{\n"; + if ( $min != $max ) + { + push @outputHeader, "\t\tAssert( i >= $min && i <= $max );\n"; + push @outputHeader, "\t\t$varname = i;\n"; + push @outputHeader, "#ifdef _DEBUG\n"; + push @outputHeader, "\t\t$boolname = true;\n"; + push @outputHeader, "#endif\n"; + } + push @outputHeader, "\t}\n"; + # bool version of set function + push @outputHeader, "\tvoid Set" . $name . "( bool i )\n"; + push @outputHeader, "\t{\n"; + if ( $min != $max ) + { +# push @outputHeader, "\t\tAssert( i >= $min && i <= $max );\n"; + push @outputHeader, "\t\t$varname = i ? 1 : 0;\n"; + push @outputHeader, "#ifdef _DEBUG\n"; + push @outputHeader, "\t\t$boolname = true;\n"; + push @outputHeader, "#endif\n"; + } + push @outputHeader, "\t}\n"; +} + +sub WriteStaticBoolExpression +{ + local( $prefix ) = shift; + local( $operator ) = shift; + for( $i = 0; $i < scalar( @staticDefineNames ); $i++ ) + { + if( $i ) + { + push @outputHeader, " $operator "; + } + local( $name ) = @staticDefineNames[$i]; + local( $boolname ) = "m_b" . $name; + push @outputHeader, "$prefix$boolname"; + } + push @outputHeader, ";\n"; +} + +sub WriteDynamicBoolExpression +{ + local( $prefix ) = shift; + local( $operator ) = shift; + for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ ) + { + if( $i ) + { + push @outputHeader, " $operator "; + } + local( $name ) = @dynamicDefineNames[$i]; + local( $boolname ) = "m_b" . $name; + push @outputHeader, "$prefix$boolname"; + } + push @outputHeader, ";\n"; +} + +sub WriteDynamicHelperClasses +{ + local( $basename ) = $fxc_filename; + $basename =~ s/\.fxc//i; + $basename =~ tr/A-Z/a-z/; + local( $classname ) = $basename . "_Dynamic_Index"; + push @outputHeader, "class $classname\n"; + push @outputHeader, "{\n"; + for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ ) + { + $name = $dynamicDefineNames[$i]; + $min = $dynamicDefineMin[$i]; + $max = $dynamicDefineMax[$i]; + &WriteHelperVar( $name, $min, $max ); + } + push @outputHeader, "public:\n"; + push @outputHeader, "\t$classname()\n"; + push @outputHeader, "\t{\n"; + for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ ) + { + $min = $dynamicDefineMin[$i]; + $max = $dynamicDefineMax[$i]; + + local( $name ) = @dynamicDefineNames[$i]; + local( $boolname ) = "m_b" . $name; + local( $varname ) = "m_n" . $name; + push @outputHeader, "#ifdef _DEBUG\n"; + if ( $min != $max ) + { + push @outputHeader, "\t\t$boolname = false;\n"; + } + else + { + push @outputHeader, "\t\t$boolname = true;\n"; + } + push @outputHeader, "#endif // _DEBUG\n"; + push @outputHeader, "\t\t$varname = 0;\n"; + } + push @outputHeader, "\t}\n"; + push @outputHeader, "\tint GetIndex()\n"; + push @outputHeader, "\t{\n"; + push @outputHeader, "\t\t// Asserts to make sure that we aren't using any skipped combinations.\n"; + foreach $skip (@perlskipcodeindividual) + { + $skip =~ s/\$/m_n/g; +# push @outputHeader, "\t\tAssert( !( $skip ) );\n"; + } + push @outputHeader, "\t\t// Asserts to make sure that we are setting all of the combination vars.\n"; + + push @outputHeader, "#ifdef _DEBUG\n"; + if( scalar( @dynamicDefineNames ) > 0 ) + { + push @outputHeader, "\t\tbool bAllDynamicVarsDefined = "; + WriteDynamicBoolExpression( "", "&&" ); + } + if( scalar( @dynamicDefineNames ) > 0 ) + { + push @outputHeader, "\t\tAssert( bAllDynamicVarsDefined );\n"; + } + push @outputHeader, "#endif // _DEBUG\n"; + + if( $spewCombos && scalar( @dynamicDefineNames ) ) + { + push @outputHeader, &CreateCCodeToSpewDynamicCombo(); + } + push @outputHeader, "\t\treturn "; + local( $scale ) = 1; + for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ ) + { + local( $name ) = @dynamicDefineNames[$i]; + local( $varname ) = "m_n" . $name; + push @outputHeader, "( $scale * $varname ) + "; + $scale *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1; + } + push @outputHeader, "0;\n"; + push @outputHeader, "\t}\n"; + push @outputHeader, "};\n"; +} + +sub WriteStaticHelperClasses +{ + local( $basename ) = $fxc_filename; + $basename =~ s/\.fxc//i; + $basename =~ tr/A-Z/a-z/; + local( $classname ) = $basename . "_Static_Index"; + push @outputHeader, "class $classname\n"; + push @outputHeader, "{\n"; + for( $i = 0; $i < scalar( @staticDefineNames ); $i++ ) + { + $name = $staticDefineNames[$i]; + $min = $staticDefineMin[$i]; + $max = $staticDefineMax[$i]; + &WriteHelperVar( $name, $min, $max ); + } + push @outputHeader, "public:\n"; + push @outputHeader, "\t$classname()\n"; + push @outputHeader, "\t{\n"; + for( $i = 0; $i < scalar( @staticDefineNames ); $i++ ) + { + $min = $staticDefineMin[$i]; + $max = $staticDefineMax[$i]; + + local( $name ) = @staticDefineNames[$i]; + local( $boolname ) = "m_b" . $name; + local( $varname ) = "m_n" . $name; + + push @outputHeader, "#ifdef _DEBUG\n"; + if ( $min != $max ) + { + push @outputHeader, "\t\t$boolname = false;\n"; + } + else + { + push @outputHeader, "\t\t$boolname = true;\n"; + } + push @outputHeader, "#endif // _DEBUG\n"; + push @outputHeader, "\t\t$varname = 0;\n"; + } + push @outputHeader, "\t}\n"; + push @outputHeader, "\tint GetIndex()\n"; + push @outputHeader, "\t{\n"; + push @outputHeader, "\t\t// Asserts to make sure that we aren't using any skipped combinations.\n"; + foreach $skip (@perlskipcodeindividual) + { + $skip =~ s/\$/m_n/g; +# push @outputHeader, "\t\tAssert( !( $skip ) );\n"; + } + push @outputHeader, "\t\t// Asserts to make sure that we are setting all of the combination vars.\n"; + + push @outputHeader, "#ifdef _DEBUG\n"; + if( scalar( @staticDefineNames ) > 0 ) + { + push @outputHeader, "\t\tbool bAllStaticVarsDefined = "; + WriteStaticBoolExpression( "", "&&" ); + + } + if( scalar( @staticDefineNames ) > 0 ) + { + push @outputHeader, "\t\tAssert( bAllStaticVarsDefined );\n"; + } + push @outputHeader, "#endif // _DEBUG\n"; + + if( $spewCombos && scalar( @staticDefineNames ) ) + { + push @outputHeader, &CreateCCodeToSpewStaticCombo(); + } + push @outputHeader, "\t\treturn "; + local( $scale ) = 1; + for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ ) + { + $scale *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1; + } + for( $i = 0; $i < scalar( @staticDefineNames ); $i++ ) + { + local( $name ) = @staticDefineNames[$i]; + local( $varname ) = "m_n" . $name; + push @outputHeader, "( $scale * $varname ) + "; + $scale *= $staticDefineMax[$i] - $staticDefineMin[$i] + 1; + } + push @outputHeader, "0;\n"; + push @outputHeader, "\t}\n"; + push @outputHeader, "};\n"; +} + +sub CreateFuncToSetPerlVars +{ + local( $out ) = ""; + + $out .= "sub SetPerlVarsFunc\n"; + $out .= "{\n"; + $out .= " local( \$combo ) = shift;\n"; + $out .= " local( \$i );\n"; + local( $i ); + for( $i = 0; $i < scalar( @dynamicDefineNames ); \$i++ ) + { + $out .= " \$$dynamicDefineNames[$i] = \$combo % "; + $out .= ( $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1 ) + $dynamicDefineMin[$i]; + $out .= ";\n"; + $out .= " \$combo = \$combo / " . ( $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1 ) . ";\n"; + } + for( $i = 0; $i < scalar( @staticDefineNames ); \$i++ ) + { + $out .= " \$$staticDefineNames[$i] = \$combo % "; + $out .= ( $staticDefineMax[$i] - $staticDefineMin[$i] + 1 ) + $staticDefineMin[$i]; + $out .= ";\n"; + $out .= " \$combo = \$combo / " . ( $staticDefineMax[$i] - $staticDefineMin[$i] + 1 ) . ";\n"; + } + $out .= "}\n"; + +# print $out; + eval $out; +} + +# These sections can be interchanged to enable profiling. +#$ShowTimers = 1; +#use Time::HiRes; +#sub SampleTime() +#{ +# return Time::HiRes::time(); +#} + +$ShowTimers = 0; +sub SampleTime() { return 0; } + +$total_start_time = SampleTime(); + +# NOTE: These must match the same values in macros.vsh! +$vPos = "v0"; +$vBoneWeights = "v1"; +$vBoneIndices = "v2"; +$vNormal = "v3"; +if( $g_x360 ) +{ + $vPosFlex = "v4"; + $vNormalFlex = "v13"; +} +$vColor = "v5"; +$vSpecular = "v6"; +$vTexCoord0 = "v7"; +$vTexCoord1 = "v8"; +$vTexCoord2 = "v9"; +$vTexCoord3 = "v10"; +$vTangentS = "v11"; +$vTangentT = "v12"; +$vUserData = "v14"; + +sub ReadInputFileWithLineInfo +{ + local( $base_filename ) = shift; + + local( *INPUT ); + local( @output ); + + # Look in the stdshaders directory, followed by the current directory. + # (This is for the SDK, since some of its files are under stdshaders). + local( $filename ) = $base_filename; + if ( !-e $filename ) + { + $filename = "$g_SourceDir\\materialsystem\\stdshaders\\$base_filename"; + if ( !-e $filename ) + { + die "\nvsh_prep.pl ERROR: missing include file: $filename.\n\n"; + } + } + + open INPUT, "<$filename" || die; + + local( $line ); + local( $linenum ) = 1; + while( $line = ) + { + $line =~ s/\n//g; + local( $postfix ) = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"; + $postfix .= "; LINEINFO($filename)($linenum)\n"; + if( $line =~ m/\#include\s+\"(.*)\"/i ) + { + push @output, &ReadInputFileWithLineInfo( $1 ); + } + else + { + push @output, $line . $postfix; + } + $linenum++; + } + + close INPUT; + return @output; +} + +sub ReadInputFileWithoutLineInfo +{ + local( $base_filename ) = shift; + + local( *INPUT ); + local( @output ); + + # Look in the stdshaders directory, followed by the current directory. + # (This is for the SDK, since some of its files are under stdshaders). + local( $filename ) = $base_filename; + if ( !-e $filename ) + { + $filename = "$g_SourceDir\\materialsystem\\stdshaders\\$base_filename"; + if ( !-e $filename ) + { + die "\nERROR: missing include file: $filename.\n\n"; + } + } + + open INPUT, "<$filename" || die; + + local( $line ); + while( $line = ) + { + if( $line =~ m/\#include\s+\"(.*)\"/i ) + { + push @output, &ReadInputFileWithoutLineInfo( $1 ); + } + else + { + push @output, $line; + } + } + + close INPUT; + return @output; +} + +sub IsPerl +{ + local( $line ) = shift; + if( $line =~ m/^\s*sub.*\,/ ) + { + return 0; + } + if( $line =~ m/^\#include/ || + $line =~ m/^\#define/ || + $line =~ m/^\#undef/ || + $line =~ m/^\#ifdef/ || + $line =~ m/^\#ifndef/ || + $line =~ m/^\#else/ || + $line =~ m/^\#endif/ || + $line =~ m/^\#error/ + ) + { + return 0; + } + if( $line =~ m/^\s*if\s*\(/ || + $line =~ m/^\s*else/ || + $line =~ m/^\s*elsif/ || + $line =~ m/^\s*for\s*\(/ || + $line =~ m/^\s*\{/ || + $line =~ m/^sub\s*/ || + $line =~ m/^\s*\}/ || + $line =~ m/^\s*\&/ || + $line =~ m/^\s*\#/ || + $line =~ m/^\s*\$/ || + $line =~ m/^\s*print/ || + $line =~ m/^\s*return/ || + $line =~ m/^\s*exit/ || + $line =~ m/^\s*die/ || + $line =~ m/^\s*eval/ || + $line =~ m/^\s*local/ || + $line =~ m/^\s*my\s+/ || + $line =~ m/^\s*@/ || + $line =~ m/^\s*alloc\s+/ || + $line =~ m/^\s*free\s+/ + ) + { + return 1; + } + return 0; +} + +# translate the output into something that takes us back to the source line +# that we care about in msdev +sub TranslateErrorMessages +{ + local( $origline ); + while( $origline = shift ) + { + if( $origline =~ m/(.*)\((\d+)\)\s*:\s*(.*)$/i ) + { + local( $filename ) = $1; + local( $linenum ) = $2; + local( $error ) = $3; + local( *FILE ); + open FILE, "<$filename" || die; + local( $i ); + local( $line ); + for( $i = 1; $i < $linenum; $i++ ) + { + $line = ; + } + if( $line =~ m/LINEINFO\((.*)\)\((.*)\)/ ) + { + print "$1\($2\) : $error\n"; + my $num = $linenum - 1; + print "$filename\($num\) : original error location\n"; + } + close FILE; + } + else + { + $origline =~ s/successful compile\!.*//gi; + if( !( $origline =~ m/^\s*$/ ) ) + { +# print "WTF: $origline\n"; + } + } + } +} + + +sub CountInstructions +{ + local( $line ); + local( $count ) = 0; + while( $line = shift ) + { + # get rid of comments + $line =~ s/;.*//gi; + $line =~ s/\/\/.*//gi; + # skip the vs1.1 statement + $line =~ s/^\s*vs.*//gi; + # if there's any text left, it's an instruction + if( $line =~ /\S/gi ) + { + $count++; + } + } + return $count; +} + + +%compiled = (); + +sub UsesRegister +{ + my $registerName = shift; + my $str = shift; + + # Cache a compiled RE for each register name. This makes UsesRegister about 2.5x faster. + if ( !$compiled{$registerName} ) + { + $compiled{$registerName} = qr/\b$registerName\b/; + } + + $ret = 0; + if( $str =~ /$compiled{$registerName}/gi ) + { + $ret = 1; + } + + return $ret; +} + +sub PadString +{ + local( $str ) = shift; + local( $desiredLen ) = shift; + local( $len ) = length $str; + while( $len < $desiredLen ) + { + $str .= " "; + $len++; + } + return $str; +} + +sub FixupAllocateFree +{ + local( $line ) = shift; + $line =~ s/\&AllocateRegister\s*\(\s*\\(\S+)\s*\)/&AllocateRegister( \\$1, \"\\$1\" )/g; + $line =~ s/\&FreeRegister\s*\(\s*\\(\S+)\s*\)/&FreeRegister( \\$1, \"\\$1\" )/g; + $line =~ s/alloc\s+(\S+)\s*/local( $1 ); &AllocateRegister( \\$1, \"\\$1\" );/g; + $line =~ s/free\s+(\S+)\s*/&FreeRegister( \\$1, \"\\$1\" );/g; + return $line; +} + +sub TranslateDXKeywords +{ + local( $line ) = shift; + $line =~ s/\bENDIF\b/endif/g; + $line =~ s/\bIF\b/if/g; + $line =~ s/\bELSE\b/else/g; + + return $line; +} + +# This is used to make the generated pl files all pretty. +sub GetLeadingWhiteSpace +{ + local( $str ) = shift; + if( $str =~ m/^;\S/ || $str =~ m/^; \S/ ) + { + return ""; + } + $str =~ s/^;/ /g; # count a leading ";" as whitespace as far as this is concerned. + $str =~ m/^(\s*)/; + return $1; +} + +$g_dx9 = 1; +$g_SourceDir = "..\\.."; + +while( 1 ) +{ + $filename = shift; + + if ( $filename =~ m/-source/i ) + { + $g_SourceDir = shift; + } + elsif( $filename =~ m/-x360/i ) + { + $g_x360 = 1; + } + else + { + last; + } +} + +$filename =~ s/-----.*$//; + + +# +# Get the shader binary version number from a header file. +# +open FILE, "<$g_SourceDir\\public\\materialsystem\\shader_vcs_version.h" || die; +while( $line = ) +{ + if( $line =~ m/^\#define\s+SHADER_VCS_VERSION_NUMBER\s+(\d+)\s*$/ ) + { + $shaderVersion = $1; + last; + } +} +if( !defined $shaderVersion ) +{ + die "couldn't get shader version from shader_vcs_version.h"; +} +close FILE; + + +if( $g_x360 ) +{ + $vshtmp = "vshtmp9_360_tmp"; +} +else +{ + $vshtmp = "vshtmp9_tmp"; +} + +if( !stat $vshtmp ) +{ + mkdir $vshtmp, 0777 || die $!; +} + +# suck in all files, including $include files. +@input = &ReadInputFileWithLineInfo( $filename ); + +sub CalcNumCombos +{ + local( $i, $numCombos ); + $numCombos = 1; + for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ ) + { + $numCombos *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1; + } + for( $i = 0; $i < scalar( @staticDefineNames ); $i++ ) + { + $numCombos *= $staticDefineMax[$i] - $staticDefineMin[$i] + 1; + } + return $numCombos; +} + +sub CalcNumDynamicCombos +{ + local( $i, $numCombos ); + $numCombos = 1; + for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ ) + { + $numCombos *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1; + } + return $numCombos; +} + +# READ THE TOP OF THE FILE TO FIND SHADER COMBOS +foreach $_ ( @input ) +{ + next if( m/^\s*$/ ); +# last if( !m,^//, ); + s,^//\s*,,; + if( m/\s*STATIC\s*\:\s*\"(.*)\"\s+\"(\d+)\.\.(\d+)\"/ ) + { + local( $name, $min, $max ); + $name = $1; + $min = $2; + $max = $3; +# print "\"$name\" \"$min..$max\"\n"; + if (/\[(.*)\]/) + { + $platforms=$1; + next if ( ($g_x360) && (!($platforms=~/XBOX/i)) ); + next if ( (!$g_x360) && (!($platforms=~/PC/i)) ); + } + push @staticDefineNames, $name; + push @staticDefineMin, $min; + push @staticDefineMax, $max; + } + elsif( m/\s*DYNAMIC\s*\:\s*\"(.*)\"\s+\"(\d+)\.\.(\d+)\"/ ) + { + local( $name, $min, $max ); + $name = $1; + $min = $2; + $max = $3; + if (/\[(.*)\]/) + { + $platforms=$1; + next if ( ($g_x360) && (!($platforms=~/XBOX/i)) ); + next if ( (!$g_x360) && (!($platforms=~/PC/i)) ); + } +# print "\"$name\" \"$min..$max\"\n"; + push @dynamicDefineNames, $name; + push @dynamicDefineMin, $min; + push @dynamicDefineMax, $max; + } +} + +# READ THE WHOLE FILE AND FIND SKIP STATEMENTS +foreach $_ ( @input ) +{ + if( m/^\s*\#\s*SKIP\s*\:\s*(.*\S+)\s*\; LINEINFO.*$/ ) + { + $perlskipcode .= "(" . $1 . ")||"; + push @perlskipcodeindividual, $1; + } +} +if( defined $perlskipcode ) +{ + $perlskipcode .= "0"; + $perlskipcode =~ s/\n//g; +} +else +{ + $perlskipcode = "0"; +} + +#print $perlskipcode . "\n"; + + +# Translate the input into a perl program that'll unroll everything and +# substitute variables. +while( $inputLine = shift @input ) +{ + $inputLine =~ s/\n//g; + # leave out lines that are only whitespace. + if( $inputLine =~ m/^\s*; LINEINFO.*$/ ) + { + next; + } + local( $inputLineNoLineNum ) = $inputLine; + $inputLineNoLineNum =~ s/; LINEINFO.*//gi; + if( &IsPerl( $inputLineNoLineNum ) ) + { + $inputLineNoLineNum = &FixupAllocateFree( $inputLineNoLineNum ); + push @outputProgram, $inputLineNoLineNum . "\n"; + } + else + { + # make asm lines that have quotes in them not barf. + $inputLine =~ s/\"/\\\"/g; + $inputLine = &TranslateDXKeywords( $inputLine ); + push @outputProgram, &GetLeadingWhiteSpace( $inputLine ) . "push \@output, \"" . + $inputLine . "\\n\";\n"; + } +} + +$outputProgram = join "", @outputProgram; + +$filename_base = $filename; +$filename_base =~ s/\.vsh//i; + +open DEBUGOUT, ">$vshtmp" . "/$filename_base.pl" || die; +print DEBUGOUT $outputProgram; +close DEBUGOUT; + +# Make a function called OutputProgram() +$bigProg = "sub OutputProgram { " . $outputProgram . "}"; +eval( $bigProg ); + + +#print $outputProgram; + +#push @finalheader, "// hack to force dependency checking\n"; +#push @finalheader, "\#ifdef NEVER\n"; +#push @finalheader, "\#include \"" . $filename_base . "\.vsh\"\n"; +#push @finalheader, "\#include \"..\\..\\devtools\\bin\\vsh_prep.pl\"\n"; +#push @finalheader, "\#endif\n"; + +%g_TimingBlocks = (); +$main_start_time = SampleTime(); + +$numCombos = &CalcNumCombos(); +$numDynamicCombos = &CalcNumDynamicCombos(); +#print "$numCombos total combos\n"; +#print "$numDynamicCombos dynamic combos\n"; +#print $numCombos / $numDynamicCombos . " static combos\n"; + +# Write out the C++ helper class for picking shader combos +$fxc_filename = $filename_base; +&WriteStaticHelperClasses(); +&WriteDynamicHelperClasses(); + +# Create a subroutine out of $perlskipcode +$perlskipfunc = "sub SkipCombo { return $perlskipcode; }\n"; +#print $perlskipfunc; + +eval $perlskipfunc; +&CreateFuncToSetPerlVars(); + +my $incfilename = "$vshtmp/$filename_base" . ".inc"; + +# Write the inc file that has indexing helpers, etc. +&WriteFile( $incfilename, join( "", @outputHeader ) ); + + +# Run the output program for all the combinations of bones and lights. +print "$filename_base.vsh\n"; +for( $i = 0; $i < $numCombos; $i++ ) +{ +# print "combo $i\n"; + &SetPerlVarsFunc( $i ); + local( $compileFailed ); + $ret = &SkipCombo; + if( !defined $ret ) + { + die "$@\n"; + } + if( $ret ) + { + # skip this combo! + $compileFailed = 1; + $numSkipped++; + next; + } + + $start = SampleTime(); + + $g_usesPos = 0; + $g_usesPosFlex = 0; + $g_usesBoneWeights = 0; + $g_usesBoneIndices = 0; + $g_usesNormal = 0; + $g_usesNormalFlex = 0; + $g_usesColor = 0; + $g_usesSpecular = 0; + $g_usesTexCoord0 = 0; + $g_usesTexCoord1 = 0; + $g_usesTexCoord2 = 0; + $g_usesTexCoord3 = 0; + $g_usesTangentS = 0; + $g_usesTangentT = 0; + $g_usesUserData = 0; + + undef @output; + + $g_TimingBlocks{"inner1"} += SampleTime() - $start; + + $eval_start_time = SampleTime(); + &OutputProgram(); + $eval_total_time += (SampleTime() - $eval_start_time); + + $start = SampleTime(); + + # Strip out comments once so we don't have to do it in all the UsesRegister calls. + @stripped = @output; + map + { + $_ =~ s/;.*//gi; + $_ =~ s/\/\/.*//gi; + } @stripped; + my $strippedStr = join( "", @stripped ); + + $g_TimingBlocks{"inner2"} += SampleTime() - $start; + + $start = SampleTime(); + + # Have to make another pass through after we know which v registers are used. . yuck. + $g_usesPos = &UsesRegister( $vPos, $strippedStr ); + if( $g_x360 ) + { + $g_usesPosFlex = &UsesRegister( $vPosFlex, $strippedStr ); + $g_usesNormalFlex = &UsesRegister( $vNormalFlex, $strippedStr ); + } + $g_usesBoneWeights = &UsesRegister( $vBoneWeights, $strippedStr ); + $g_usesBoneIndices = &UsesRegister( $vBoneIndices, $strippedStr ); + $g_usesNormal = &UsesRegister( $vNormal, $strippedStr ); + $g_usesColor = &UsesRegister( $vColor, $strippedStr ); + $g_usesSpecular = &UsesRegister( $vSpecular, $strippedStr ); + $g_usesTexCoord0 = &UsesRegister( $vTexCoord0, $strippedStr ); + $g_usesTexCoord1 = &UsesRegister( $vTexCoord1, $strippedStr ); + $g_usesTexCoord2 = &UsesRegister( $vTexCoord2, $strippedStr ); + $g_usesTexCoord3 = &UsesRegister( $vTexCoord3, $strippedStr ); + $g_usesTangentS = &UsesRegister( $vTangentS, $strippedStr ); + $g_usesTangentT = &UsesRegister( $vTangentT, $strippedStr ); + $g_usesUserData = &UsesRegister( $vUserData, $strippedStr ); + undef @output; + + $g_TimingBlocks{"inner2"} += SampleTime() - $start; + + $eval_start_time = SampleTime(); + # Running OutputProgram generates $outfilename + &OutputProgram(); + $eval_total_time += (SampleTime() - $eval_start_time); + + $start = SampleTime(); + + &CheckUnfreedRegisters(); + + for( $j = 0; $j < scalar( @output ); $j++ ) + { + # remove whitespace from the beginning of each line. + $output[$j] =~ s/^\s+//; + # remove LINEINFO from empty lines. + $output[$j] =~ s/^; LINEINFO.*//; + } + + $g_TimingBlocks{"inner3"} += SampleTime() - $start; + $start = SampleTime(); + + + $outfilename_base = $filename_base . "_" . $i; + + # $outfilename is the name of the file generated from executing the perl code + # for this shader. This file is generated once per combo. + # We will assemble this shader with vsa.exe. + $outfilename = "$vshtmp\\" . $outfilename_base . ".tmp"; + +# $outhdrfilename = "$vshtmp\\" . $outfilename_base . ".h"; +# unlink $outhdrfilename; + + open OUTPUT, ">$outfilename" || die; + print OUTPUT @output; + close OUTPUT; + + $g_TimingBlocks{"inner4"} += SampleTime() - $start; + $start = SampleTime(); + + local( $instructionCount ) = &CountInstructions( @output ); + $g_TimingBlocks{"inner5"} += SampleTime() - $start; + + local( $debug ); + + $debug = 1; +# for( $debug = 1; $debug >= 0; $debug-- ) + { + # assemble the vertex shader + unlink "shader$i.o"; + if( $g_x360 ) + { + $vsa = "..\\..\\x360xdk\\bin\\win32\\vsa"; + } + else + { + $vsa = "..\\..\\dx9sdk\\utilities\\vsa"; + } + $vsadebug = "$vsa /nologo /Foshader$i.o $outfilename"; + $vsanodebug = "$vsa /nologo /Foshader$i.o $outfilename"; + + $vsa_start_time = SampleTime(); + + if( $debug ) + { +# print $vsadebug . "\n"; + @vsaoutput = `$vsadebug 2>&1`; +# print @vsaoutput; + } + else + { + @vsaoutput = `$vsanodebug 2>&1`; + } + + $vsa_total_time += SampleTime() - $vsa_start_time; + + $start = SampleTime(); + + &TranslateErrorMessages( @vsaoutput ); + + $g_TimingBlocks{"inner6"} += SampleTime() - $start; + + push @finalheader, @hdr; + } +} + + +$main_total_time = SampleTime() - $main_start_time; + +# stick info about the shaders at the end of the inc file. +push @finalheader, "static PrecompiledShaderByteCode_t $filename_base" . "_vertex_shaders[] = {\n"; +for( $i = 0; $i < $numCombos; $i++ ) +{ + $outfilename_base = $filename_base . "_" . $i; + push @finalheader, "{ $outfilename_base, sizeof( $outfilename_base ) },\n"; +} +push @finalheader, "};\n"; + + +push @finalheader, "struct $filename_base" . "_VertexShader_t : public PrecompiledShader_t\n"; +push @finalheader, "{\n"; +push @finalheader, "\t$filename_base" . "_VertexShader_t()\n"; +push @finalheader, "\t{\n"; +push @finalheader, "\t\tm_nFlags = 0;\n"; + +$flags = 0; +#push @finalheader, "\t\tppVertexShaders = $filename_base" . "_vertex_shaders;\n"; +push @finalheader, "\t\tm_pByteCode = $filename_base" . "_vertex_shaders;\n"; +push @finalheader, "\t\tm_pName = \"$filename_base\";\n"; +push @finalheader, "\t\tm_nShaderCount = " . ( $maxNumBones + 1 ) * $totalFogCombos * $totalLightCombos . ";\n"; +push @finalheader, "\t\tm_nDynamicCombos = m_nShaderCount;\n"; +push @finalheader, "\t\tGetShaderDLL()->InsertPrecompiledShader( PRECOMPILED_VERTEX_SHADER, this );\n"; +push @finalheader, "\t}\n"; +push @finalheader, "\tvirtual const PrecompiledShaderByteCode_t &GetByteCode( int shaderID )\n"; +push @finalheader, "\t{\n"; +push @finalheader, "\t\treturn m_pByteCode[shaderID];\n"; +push @finalheader, "\t}\n"; +push @finalheader, "};\n"; +push @finalheader, "static $filename_base" . "_VertexShader_t $filename_base" . "_VertexShaderInstance;\n"; + +# Write the final header file with the compiled vertex shader programs. +$finalheadername = "$vshtmp\\" . $filename_base . ".inc"; +#print "writing $finalheadername\n"; +#open FINALHEADER, ">$finalheadername" || die; +#print FINALHEADER @finalheader; +#close FINALHEADER; + +&MakeDirHier( "shaders/vsh" ); + +my $vcsName = ""; +if( $g_x360 ) +{ + $vcsName = $filename_base . ".360.vcs"; +} +else +{ + $vcsName = $filename_base . ".vcs"; +} +open COMPILEDSHADER, ">shaders/vsh/$vcsName" || die; +binmode( COMPILEDSHADER ); + +# +# Write out the part of the header that we know. . we'll write the rest after writing the object code. +# + +# Pack arguments +my $sInt = "i"; +my $uInt = "I"; +if ( $g_x360 ) +{ + # Change arguments to "big endian long" + $sInt = "N"; + $uInt = "N"; +} + +my $undecoratedinput = join "", &ReadInputFileWithoutLineInfo( $filename ); +#print STDERR "undecoratedinput: $undecoratedinput\n"; +my $crc = crc32( $undecoratedinput ); +#print STDERR "crc for $filename: $crc\n"; + +# version +print COMPILEDSHADER pack $sInt, 4; +# totalCombos +print COMPILEDSHADER pack $sInt, $numCombos; +# dynamic combos +print COMPILEDSHADER pack $sInt, $numDynamicCombos; +# flags +print COMPILEDSHADER pack $uInt, $flags; +# centroid mask +print COMPILEDSHADER pack $uInt, 0; +# reference size +print COMPILEDSHADER pack $uInt, 0; +# crc32 of the source code +print COMPILEDSHADER pack $uInt, $crc; + +my $beginningOfDir = tell COMPILEDSHADER; + +# Write out a blank directionary. . we'll fill it in later. +for( $i = 0; $i < $numCombos; $i++ ) +{ + # offset from beginning of file. + print COMPILEDSHADER pack $sInt, 0; + # size + print COMPILEDSHADER pack $sInt, 0; +} + +my $startByteCode = tell COMPILEDSHADER; +my @byteCodeStart; +my @byteCodeSize; + +# Write out the shader object code. +for( $shaderCombo = 0; $shaderCombo < $numCombos; $shaderCombo++ ) +{ + my $filename = "shader$shaderCombo\.o"; + my $filesize = (stat $filename)[7]; + $byteCodeStart[$shaderCombo] = tell COMPILEDSHADER; + $byteCodeSize[$shaderCombo] = $filesize; + open SHADERBYTECODE, "<$filename" || die; + binmode SHADERBYTECODE; + my $bin; + my $numread = read SHADERBYTECODE, $bin, $filesize; +# print "filename: $filename numread: $numread filesize: $filesize\n"; + close SHADERBYTECODE; + unlink $filename; + + print COMPILEDSHADER $bin; +} + +# Seek back to the directory and write it out. +seek COMPILEDSHADER, $beginningOfDir, 0; +for( $i = 0; $i < $numCombos; $i++ ) +{ + # offset from beginning of file. + print COMPILEDSHADER pack $sInt, $byteCodeStart[$i]; + # size + print COMPILEDSHADER pack $sInt, $byteCodeSize[$i]; +} + +close COMPILEDSHADER; + +$total_time = SampleTime() - $total_start_time; + +if ( $ShowTimers ) +{ + print "\n\n"; + print sprintf( "Main loop time : %0.4f sec, (%0.2f%%)\n", $main_total_time, 100*$main_total_time / $total_time ); + print sprintf( "Inner1 time : %0.4f sec, (%0.2f%%)\n", $inner1_total_time, 100*$inner1_total_time / $total_time ); + print sprintf( "VSA time : %0.4f sec, (%0.2f%%)\n", $vsa_total_time, 100*$vsa_total_time / $total_time ); + print sprintf( "eval() time : %0.4f sec, (%0.2f%%)\n", $eval_total_time, 100*$eval_total_time / $total_time ); + print sprintf( "UsesRegister time: %0.4f sec, (%0.2f%%)\n", $usesr_total_time, 100*$usesr_total_time / $total_time ); + + foreach $key ( keys %g_TimingBlocks ) + { + print sprintf( "$key time: %0.4f sec, (%0.2f%%)\n", $g_TimingBlocks{$key}, 100*$g_TimingBlocks{$key} / $total_time ); + } + + print sprintf( "Total time : %0.4f sec\n", $total_time ); +} + diff --git a/dx10sdk/utilities/dx9_30/dx_proxy.dll b/dx10sdk/utilities/dx9_30/dx_proxy.dll new file mode 100644 index 00000000..adb1cfdf Binary files /dev/null and b/dx10sdk/utilities/dx9_30/dx_proxy.dll differ diff --git a/dx9sdk/utilities/dx_proxy.dll b/dx9sdk/utilities/dx_proxy.dll new file mode 100644 index 00000000..7640fd86 Binary files /dev/null and b/dx9sdk/utilities/dx_proxy.dll differ diff --git a/game/client/swarm/gameui/swarm/basemodpanel.cpp b/game/client/swarm/gameui/swarm/basemodpanel.cpp index bd2d9c28..80f7d145 100644 --- a/game/client/swarm/gameui/swarm/basemodpanel.cpp +++ b/game/client/swarm/gameui/swarm/basemodpanel.cpp @@ -1642,7 +1642,7 @@ void CBaseModPanel::OnEvent( KeyValues *pEvent ) } } - CUIGameData::Get()->OpenWaitScreen( szWaitScreenText, flMinDisplayTime, pSettings ); + CUIGameData::Get()->OpenWaitScreen( szWaitScreenText, flMinDisplayTime, pSettings, 7.0f ); } else if ( !Q_stricmp( "searchresult", szProgress ) ) { diff --git a/game/client/swarm/gameui/swarm/uigamedata.cpp b/game/client/swarm/gameui/swarm/uigamedata.cpp index 18609d32..d58cb780 100644 --- a/game/client/swarm/gameui/swarm/uigamedata.cpp +++ b/game/client/swarm/gameui/swarm/uigamedata.cpp @@ -615,7 +615,7 @@ bool CUIGameData::IsXUIOpen() return m_bXUIOpen; } -void CUIGameData::OpenWaitScreen( const char * messageText, float minDisplayTime, KeyValues *pSettings ) +void CUIGameData::OpenWaitScreen( const char * messageText, float minDisplayTime, KeyValues *pSettings, float maxDisplayTime ) { if ( UI_IsDebug() ) { @@ -642,6 +642,7 @@ void CUIGameData::OpenWaitScreen( const char * messageText, float minDisplayTime waitScreen->SetNavBack( backFrame ); waitScreen->ClearData(); waitScreen->AddMessageText( messageText, minDisplayTime ); + waitScreen->SetMaxDisplayTime( maxDisplayTime ); } } diff --git a/game/client/swarm/gameui/swarm/uigamedata.h b/game/client/swarm/gameui/swarm/uigamedata.h index d8e2cc97..caaf5b8d 100644 --- a/game/client/swarm/gameui/swarm/uigamedata.h +++ b/game/client/swarm/gameui/swarm/uigamedata.h @@ -172,7 +172,7 @@ public: bool IsXUIOpen(); - void OpenWaitScreen( const char * messageText, float minDisplayTime = 3.0f, KeyValues *pSettings = NULL ); + void OpenWaitScreen( const char * messageText, float minDisplayTime = 3.0f, KeyValues *pSettings = NULL, float maxDisplayTime = 0.0f ); void UpdateWaitPanel( const char * messageText, float minDisplayTime = 3.0f ); void UpdateWaitPanel( const wchar_t * messageText, float minDisplayTime = 3.0f ); void CloseWaitScreen( vgui::Panel * callbackPanel, const char * messageName ); diff --git a/game/client/swarm/gameui/swarm/vgenericwaitscreen.cpp b/game/client/swarm/gameui/swarm/vgenericwaitscreen.cpp index 9663aff1..27622d03 100644 --- a/game/client/swarm/gameui/swarm/vgenericwaitscreen.cpp +++ b/game/client/swarm/gameui/swarm/vgenericwaitscreen.cpp @@ -252,7 +252,11 @@ void GenericWaitScreen::CheckIfNeedsToClose() { if ( m_MsgStartDisplayTime + m_MsgMaxDisplayTime < time ) { - NavigateBack(); + if ( !NavigateBack() ) + { + Close(); + CBaseModPanel::GetSingleton().OpenFrontScreen(); + } if ( m_pfnMaxTimeOut ) m_pfnMaxTimeOut(); diff --git a/game/shared/swarm/asw_gamerules.cpp b/game/shared/swarm/asw_gamerules.cpp index 87f95f47..adb8af7c 100644 --- a/game/shared/swarm/asw_gamerules.cpp +++ b/game/shared/swarm/asw_gamerules.cpp @@ -167,6 +167,7 @@ ConVar asw_stim_time_scale("asw_stim_time_scale", "0.35", FCVAR_REPLICATED | FCV ConVar asw_time_scale_delay("asw_time_scale_delay", "0.15", FCVAR_REPLICATED | FCVAR_CHEAT, "Delay before timescale changes to give a chance for the client to comply and predict."); ConVar asw_ignore_need_two_player_requirement("asw_ignore_need_two_player_requirement", "0", FCVAR_REPLICATED, "If set to 1, ignores the mission setting that states two players are needed to start the mission."); ConVar mp_gamemode( "mp_gamemode", "campaign", FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY, "Current game mode, acceptable values are campaign and single_mission.", false, 0.0f, false, 0.0f ); +ConVar mm_max_players( "mm_max_players", "4", FCVAR_REPLICATED | FCVAR_CHEAT, "Max players for matchmaking system" ); ConVar asw_sentry_friendly_fire_scale( "asw_sentry_friendly_fire_scale", "0", FCVAR_REPLICATED, "Damage scale for sentry gun friendly fire" #ifdef GAME_DLL ,UpdateMatchmakingTagsCallback ); diff --git a/materialsystem/IShaderSystem.h b/materialsystem/IShaderSystem.h new file mode 100644 index 00000000..b192890b --- /dev/null +++ b/materialsystem/IShaderSystem.h @@ -0,0 +1,115 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +// An interface that should not ever be accessed directly from shaders +// but instead is visible only to shaderlib. +//===========================================================================// + +#ifndef ISHADERSYSTEM_H +#define ISHADERSYSTEM_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "interface.h" +#include + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +enum Sampler_t; +class ITexture; +class IShader; + + +//----------------------------------------------------------------------------- +// The Shader system interface version +//----------------------------------------------------------------------------- +#define SHADERSYSTEM_INTERFACE_VERSION "ShaderSystem002" + + +//----------------------------------------------------------------------------- +// Modulation flags +//----------------------------------------------------------------------------- +enum +{ + SHADER_USING_ALPHA_MODULATION = 0x1, + SHADER_USING_FLASHLIGHT = 0x2, + SHADER_USING_FIXED_FUNCTION_BAKED_LIGHTING = 0x4, + SHADER_USING_EDITOR = 0x8, + + // the BUFFER0 and GBUFFER1 bits provide 3 g-buffermodes plus the normal modes. + // the modes are: + // Normal rendering = ( gbuffer1 = 0, gbuffer0 = 0 ) + // Output pos, normal, albedo via mrts = (0,1) + // output fixed lighted single image = (1,0) + // output the normal = (1,1) + SHADER_USING_GBUFFER0 = 0x10, + SHADER_USING_GBUFFER1 = 0x20, +}; + + +//----------------------------------------------------------------------------- +// The shader system (a singleton) +//----------------------------------------------------------------------------- +abstract_class IShaderSystem +{ +public: + virtual ShaderAPITextureHandle_t GetShaderAPITextureBindHandle( ITexture *pTexture, int nFrameVar, int nTextureChannel = 0 ) =0; + + // Binds a texture + virtual void BindTexture( Sampler_t sampler1, ITexture *pTexture, int nFrameVar = 0 ) = 0; + virtual void BindTexture( Sampler_t sampler1, Sampler_t sampler2, ITexture *pTexture, int nFrameVar = 0 ) = 0; + + // Takes a snapshot + virtual void TakeSnapshot( ) = 0; + + // Draws a snapshot + virtual void DrawSnapshot( const unsigned char *pInstanceCommandBuffer, bool bMakeActualDrawCall = true ) = 0; + + // Are we using graphics? + virtual bool IsUsingGraphics() const = 0; + + // Are editor materials enabled? + virtual bool CanUseEditorMaterials() const = 0; + + // Bind vertex texture + virtual void BindVertexTexture( VertexTextureSampler_t vtSampler, ITexture *pTexture, int nFrameVar = 0 ) = 0; +}; + + +//----------------------------------------------------------------------------- +// The Shader plug-in DLL interface version +//----------------------------------------------------------------------------- +#define SHADER_DLL_INTERFACE_VERSION "ShaderDLL004" + + +//----------------------------------------------------------------------------- +// The Shader interface versions +//----------------------------------------------------------------------------- +abstract_class IShaderDLLInternal +{ +public: + // Here's where the app systems get to learn about each other + virtual bool Connect( CreateInterfaceFn factory, bool bIsMaterialSystem ) = 0; + virtual void Disconnect( bool bIsMaterialSystem ) = 0; + + // Returns the number of shaders defined in this DLL + virtual int ShaderCount() const = 0; + + // Returns information about each shader defined in this DLL + virtual IShader *GetShader( int nShader ) = 0; +}; + + +//----------------------------------------------------------------------------- +// Singleton interface +//----------------------------------------------------------------------------- +IShaderDLLInternal *GetShaderDLLInternal(); + + +#endif // ISHADERSYSTEM_H diff --git a/materialsystem/imaterialinternal.h b/materialsystem/imaterialinternal.h new file mode 100644 index 00000000..6cc85c35 --- /dev/null +++ b/materialsystem/imaterialinternal.h @@ -0,0 +1,176 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// + +#ifndef IMATERIALINTERNAL_H +#define IMATERIALINTERNAL_H + +#ifdef _WIN32 +#pragma once +#endif + +// identifier was truncated to '255' characters in the debug information +#pragma warning(disable: 4786) + +#include "materialsystem/imaterialsystem.h" +#include "materialsystem/imaterial.h" +#include "shaderapi/ishaderapi.h" +#include "filesystem.h" + + +//----------------------------------------------------------------------------- +// forward declarations +//----------------------------------------------------------------------------- +enum MaterialPrimitiveType_t; +class IShader; +class IMesh; +class IVertexBuffer; +class IIndexBuffer; +struct Shader_VertexArrayData_t; +struct ShaderRenderState_t; +class KeyValues; + + +struct tokencache_t +{ + unsigned short symbol; + unsigned char varIndex; + unsigned char cached : 1; + unsigned char subrect : 1; +}; + + +//----------------------------------------------------------------------------- +// Interface for materials used only within the material system +//----------------------------------------------------------------------------- +abstract_class IMaterialInternal : public IMaterial +{ +public: + // class factory methods + static IMaterialInternal* CreateMaterial( char const* pMaterialName, const char *pTextureGroupName, KeyValues *pKeyValues = NULL ); + static void DestroyMaterial( IMaterialInternal* pMaterial ); + + // If supplied, pKeyValues and pPatchKeyValues should come from LoadVMTFile() + static IMaterialInternal* CreateMaterialSubRect( char const* pMaterialName, const char *pTextureGroupName, + KeyValues *pKeyValues = NULL, KeyValues *pPatchKeyValues = NULL, bool bAssumeCreateFromFile = false ); + static void DestroyMaterialSubRect( IMaterialInternal* pMaterial ); + + // refcount + virtual int GetReferenceCount( ) const = 0; + + // enumeration id + virtual void SetEnumerationID( int id ) = 0; + + // White lightmap methods + virtual void SetNeedsWhiteLightmap( bool val ) = 0; + virtual bool GetNeedsWhiteLightmap( ) const = 0; + + // load/unload + virtual void Uncache( bool bPreserveVars = false ) = 0; + virtual void Precache() = 0; + // If supplied, pKeyValues and pPatchKeyValues should come from LoadVMTFile() + virtual bool PrecacheVars( KeyValues *pKeyValues = NULL, KeyValues *pPatchKeyValues = NULL, CUtlVector *pIncludes = NULL ) = 0; + + // reload all textures used by this materals + virtual void ReloadTextures() = 0; + + // lightmap pages associated with this material + virtual void SetMinLightmapPageID( int pageID ) = 0; + virtual void SetMaxLightmapPageID( int pageID ) = 0;; + virtual int GetMinLightmapPageID( ) const = 0; + virtual int GetMaxLightmapPageID( ) const = 0; + + virtual IShader *GetShader() const = 0; + + // Can we use it? + virtual bool IsPrecached( ) const = 0; + virtual bool IsPrecachedVars() const = 0; + + // main draw method + virtual void DrawMesh( VertexCompressionType_t vertexCompression, bool bIsAlphaModulating, bool bUsingPreTessPatches ) = 0; + + // Gets the vertex format + virtual VertexFormat_t GetVertexFormat() const = 0; + virtual VertexFormat_t GetVertexUsage() const = 0; + + // Performs a debug trace on this material + virtual bool PerformDebugTrace() const = 0; + + // Can we override this material in debug? + virtual bool NoDebugOverride() const = 0; + + // Should we draw? + virtual void ToggleSuppression() = 0; + + // Are we suppressed? + virtual bool IsSuppressed() const = 0; + + // Should we debug? + virtual void ToggleDebugTrace() = 0; + + // Do we use fog? + virtual bool UseFog() const = 0; + + // Adds a material variable to the material + virtual void AddMaterialVar( IMaterialVar *pMaterialVar ) = 0; + + // Gets the renderstate + virtual ShaderRenderState_t *GetRenderState() = 0; + + // Was this manually created (not read from a file?) + virtual bool IsManuallyCreated() const = 0; + + virtual bool NeedsFixedFunctionFlashlight() const = 0; + + virtual bool IsUsingVertexID() const = 0; + + // Identifies a material mounted through the preload path + virtual void MarkAsPreloaded( bool bSet ) = 0; + virtual bool IsPreloaded() const = 0; + + // Conditonally increments the refcount + virtual void ArtificialAddRef( void ) = 0; + virtual void ArtificialRelease( void ) = 0; + + virtual void ReportVarChanged( IMaterialVar *pVar ) = 0; + virtual uint32 GetChangeID() const = 0; + + virtual bool IsTranslucentInternal( float fAlphaModulation ) const = 0; + + //Is this the queue friendly or realtime version of the material? + virtual bool IsRealTimeVersion( void ) const = 0; + + virtual void ClearContextData( void ) + { + } + + //easy swapping between the queue friendly and realtime versions of the material + virtual IMaterialInternal *GetRealTimeVersion( void ) = 0; + virtual IMaterialInternal *GetQueueFriendlyVersion( void ) = 0; + + virtual void PrecacheMappingDimensions( void ) = 0; + virtual void FindRepresentativeTexture( void ) = 0; + + // These are used when a new whitelist is passed in. First materials to be reloaded are flagged, then they are reloaded. + virtual void DecideShouldReloadFromWhitelist( IFileList *pFileList ) = 0; + virtual void ReloadFromWhitelistIfMarked() = 0; + + virtual void CompactMaterialVars() = 0; +}; + +extern void InsertKeyValues( KeyValues& dst, KeyValues& src, bool bCheckForExistence ); +extern void WriteKeyValuesToFile( const char *pFileName, KeyValues& keyValues ); +extern void ExpandPatchFile( KeyValues& keyValues, KeyValues &patchKeyValues ); +// patchKeyValues accumulates keys applied by VMT patch files (this is necessary to make $fallbackmaterial +// work properly - the patch keys need to be reapplied when the fallback VMT is loaded). It may contain +// previously accumulated patch keys on entry, and may contain more encountered patch keys on exit. +extern bool LoadVMTFile( KeyValues &vmtKeyValues, KeyValues &patchKeyValues, const char *pMaterialName, bool bUsesUNCFilename, CUtlVector *pIncludes ); + +extern void CompactMaterialVars( IMaterialVar **ppMaterialVars, int nVars ); +extern void CompactMaterialVarHeap(); + +#endif // IMATERIALINTERNAL_H diff --git a/materialsystem/imaterialsysteminternal.h b/materialsystem/imaterialsysteminternal.h new file mode 100644 index 00000000..b4662049 --- /dev/null +++ b/materialsystem/imaterialsysteminternal.h @@ -0,0 +1,229 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// + +#ifndef IMATERIALSYSTEMINTERNAL_H +#define IMATERIALSYSTEMINTERNAL_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "materialsystem/imaterialsystem.h" +#include "tier1/callqueue.h" +#include "tier1/memstack.h" + +class IMaterialInternal; + +//----------------------------------------------------------------------------- +// Special call queue that knows (a) single threaded access, and (b) all +// functions called after last function added +//----------------------------------------------------------------------------- + +class CMatCallQueue +{ +public: + CMatCallQueue() + { + MEM_ALLOC_CREDIT_( "CMatCallQueue.m_Allocator" ); +#ifdef SWDS + m_Allocator.Init( 2*1024, 0, 0, 4 ); +#else + m_Allocator.Init( IsX360() ? 2*1024*1024 : 8*1024*1024, 64*1024, 256*1024, 4 ); +#endif + m_FunctorFactory.SetAllocator( &m_Allocator ); + m_pHead = m_pTail = NULL; + } + + size_t GetMemoryUsed() + { + return m_Allocator.GetUsed(); + } + + int Count() + { + int i = 0; + Elem_t *pCurrent = m_pHead; + while ( pCurrent ) + { + i++; + pCurrent = pCurrent->pNext; + } + return i; + } + + void CallQueued() + { + if ( !m_pHead ) + { + return; + } + + CFunctor *pFunctor; + + Elem_t *pCurrent = m_pHead; + while ( pCurrent ) + { + pFunctor = pCurrent->pFunctor; +#ifdef _DEBUG + if ( pFunctor->m_nUserID == m_nBreakSerialNumber) + { + m_nBreakSerialNumber = (unsigned)-1; + } +#endif + (*pFunctor)(); + pFunctor->Release(); + pCurrent = pCurrent->pNext; + } +#ifdef DEBUG_MATCALLQUEUE + static int prevHigh = 0; + if ( m_Allocator.GetUsed() > prevHigh ) + { + Msg( "***%d\n", m_Allocator.GetUsed() ); + prevHigh = m_Allocator.GetUsed(); + } +#endif + m_Allocator.FreeAll( false ); + m_pHead = m_pTail = NULL; + } + + void QueueFunctor( CFunctor *pFunctor ) + { + Assert( pFunctor ); + QueueFunctorInternal( RetAddRef( pFunctor ) ); + } + + void Flush() + { + if ( !m_pHead ) + { + return; + } + + CFunctor *pFunctor; + + Elem_t *pCurrent = m_pHead; + while ( pCurrent ) + { + pFunctor = pCurrent->pFunctor; + pFunctor->Release(); + pCurrent = pCurrent->pNext; + } + + m_Allocator.FreeAll( false ); + m_pHead = m_pTail = NULL; + } + + #define DEFINE_MATCALLQUEUE_NONMEMBER_QUEUE_CALL(N) \ + template \ + void QueueCall(FUNCTION_RETTYPE (*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \ + { \ + QueueFunctorInternal( m_FunctorFactory.CreateFunctor( pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ) ); \ + } + + //------------------------------------- + + #define DEFINE_MATCALLQUEUE_MEMBER_QUEUE_CALL(N) \ + template \ + void QueueCall(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \ + { \ + QueueFunctorInternal( m_FunctorFactory.CreateFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ) ); \ + } + + //------------------------------------- + + #define DEFINE_MATCALLQUEUE_CONST_MEMBER_QUEUE_CALL(N) \ + template \ + void QueueCall(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \ + { \ + QueueFunctorInternal( m_FunctorFactory.CreateFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ) ); \ + } + + //------------------------------------- + + FUNC_GENERATE_ALL( DEFINE_MATCALLQUEUE_NONMEMBER_QUEUE_CALL ); + FUNC_GENERATE_ALL( DEFINE_MATCALLQUEUE_MEMBER_QUEUE_CALL ); + FUNC_GENERATE_ALL( DEFINE_MATCALLQUEUE_CONST_MEMBER_QUEUE_CALL ); + +private: + void QueueFunctorInternal( CFunctor *pFunctor ) + { +#ifdef _DEBUG + pFunctor->m_nUserID = m_nCurSerialNumber++; +#endif + MEM_ALLOC_CREDIT_( "CMatCallQueue.m_Allocator" ); + Elem_t *pNew = (Elem_t *)m_Allocator.Alloc( sizeof(Elem_t) ); + if ( m_pTail ) + { + m_pTail->pNext = pNew; + m_pTail = pNew; + } + else + { + m_pHead = m_pTail = pNew; + } + pNew->pNext = NULL; + pNew->pFunctor = pFunctor; + } + + struct Elem_t + { + Elem_t *pNext; + CFunctor *pFunctor; + }; + + Elem_t *m_pHead; + Elem_t *m_pTail; + + CMemoryStack m_Allocator; + CCustomizedFunctorFactory > > m_FunctorFactory; + unsigned m_nCurSerialNumber; + unsigned m_nBreakSerialNumber; +}; + +#define MATCONFIG_FLAGS_SUPPORT_EDITOR ( 1 << 0 ) +#define MATCONFIG_FLAGS_SUPPORT_GBUFFER ( 1 << 1 ) +//----------------------------------------------------------------------------- +// Additional interfaces used internally to the library +//----------------------------------------------------------------------------- +abstract_class IMaterialSystemInternal : public IMaterialSystem +{ +public: + // Returns the current material + virtual IMaterial* GetCurrentMaterial() = 0; + + virtual int GetLightmapPage( void ) = 0; + + // Gets the maximum lightmap page size... + virtual int GetLightmapWidth( int lightmap ) const = 0; + virtual int GetLightmapHeight( int lightmap ) const = 0; + + virtual ITexture *GetLocalCubemap( void ) = 0; + +// virtual bool RenderZOnlyWithHeightClipEnabled( void ) = 0; + virtual void ForceDepthFuncEquals( bool bEnable ) = 0; + virtual enum MaterialHeightClipMode_t GetHeightClipMode( void ) = 0; + + // FIXME: Remove? Here for debugging shaders in CShaderSystem + virtual void AddMaterialToMaterialList( IMaterialInternal *pMaterial ) = 0; + virtual void RemoveMaterial( IMaterialInternal *pMaterial ) = 0; + virtual void RemoveMaterialSubRect( IMaterialInternal *pMaterial ) = 0; + virtual bool InFlashlightMode() const = 0; + + // Can we use editor materials? + virtual bool CanUseEditorMaterials() const = 0; + virtual int GetConfigurationFlags( void ) const = 0; + virtual const char *GetForcedTextureLoadPathID() = 0; + + virtual CMatCallQueue *GetRenderCallQueue() = 0; + + virtual void UnbindMaterial( IMaterial *pMaterial ) = 0; + virtual uint GetRenderThreadId() const = 0 ; +}; + + +#endif // IMATERIALSYSTEMINTERNAL_H diff --git a/materialsystem/materialsystem_global.cpp b/materialsystem/materialsystem_global.cpp new file mode 100644 index 00000000..82240203 --- /dev/null +++ b/materialsystem/materialsystem_global.cpp @@ -0,0 +1,21 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=====================================================================================// + +#include "materialsystem_global.h" +#include "shaderapi/ishaderapi.h" +#include "shadersystem.h" +#include +#include "filesystem.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +int g_FrameNum; +IShaderAPI *g_pShaderAPI = 0; +IShaderDeviceMgr* g_pShaderDeviceMgr = 0; +IShaderDevice *g_pShaderDevice = 0; +IShaderShadow* g_pShaderShadow = 0; +IClientMaterialSystem *g_pClientMaterialSystem = 0; diff --git a/materialsystem/materialsystem_global.h b/materialsystem/materialsystem_global.h new file mode 100644 index 00000000..db4ae6bc --- /dev/null +++ b/materialsystem/materialsystem_global.h @@ -0,0 +1,112 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +// +//=============================================================================// + +#ifndef MATERIALSYSTEM_GLOBAL_H +#define MATERIALSYSTEM_GLOBAL_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "imaterialsysteminternal.h" +#include "tier0/dbg.h" +#include "tier2/tier2.h" + + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class ITextureInternal; +class IShaderAPI; +class IHardwareConfigInternal; +class IShaderUtil; +class IShaderShadow; +class IShaderDeviceMgr; +class IShaderDevice; +class IShaderSystemInternal; +class IMaterialInternal; +class IColorCorrectionSystem; +class IMaterialVar; +class IClientMaterialSystem; + + +//----------------------------------------------------------------------------- +// Constants used by the system +//----------------------------------------------------------------------------- + +#define MATERIAL_MAX_PATH 256 + +// GR - limits for blured image (HDR stuff) +#define MAX_BLUR_IMAGE_WIDTH 256 +#define MAX_BLUR_IMAGE_HEIGHT 192 + +#define CLAMP_BLUR_IMAGE_WIDTH( _w ) ( ( _w < MAX_BLUR_IMAGE_WIDTH ) ? _w : MAX_BLUR_IMAGE_WIDTH ) +#define CLAMP_BLUR_IMAGE_HEIGHT( _h ) ( ( _h < MAX_BLUR_IMAGE_HEIGHT ) ? _h : MAX_BLUR_IMAGE_HEIGHT ) + +//----------------------------------------------------------------------------- +// Global structures +//----------------------------------------------------------------------------- +extern MaterialSystem_Config_t g_config; +extern uint32 g_nDebugVarsSignature; + +//extern MaterialSystem_ErrorFunc_t Error; +//extern MaterialSystem_WarningFunc_t Warning; + +extern int g_FrameNum; + +extern IShaderAPI* g_pShaderAPI; +extern IShaderDeviceMgr* g_pShaderDeviceMgr; +extern IShaderDevice* g_pShaderDevice; +extern IShaderShadow* g_pShaderShadow; +extern IClientMaterialSystem *g_pClientMaterialSystem; + +extern IMaterialInternal *g_pErrorMaterial; + +IShaderSystemInternal* ShaderSystem(); +inline IShaderSystemInternal* ShaderSystem() +{ + extern IShaderSystemInternal *g_pShaderSystem; + return g_pShaderSystem; +} + +inline IHardwareConfigInternal *HardwareConfig() +{ + extern IHardwareConfigInternal* g_pHWConfig; + return g_pHWConfig; +} + +//----------------------------------------------------------------------------- +// Accessor to get at the material system +//----------------------------------------------------------------------------- +inline IMaterialSystemInternal* MaterialSystem() +{ + extern IMaterialSystemInternal *g_pInternalMaterialSystem; + return g_pInternalMaterialSystem; +} + +inline IShaderUtil* ShaderUtil() +{ + extern IShaderUtil *g_pShaderUtil; + return g_pShaderUtil; +} + +extern IColorCorrectionSystem *g_pColorCorrectionSystem; +inline IColorCorrectionSystem *ColorCorrectionSystem() +{ + return g_pColorCorrectionSystem; +} + + +//----------------------------------------------------------------------------- +// Global methods related to material vars +//----------------------------------------------------------------------------- +void EnableThreadedMaterialVarAccess( bool bEnable, IMaterialVar **ppParams, int nVarCount ); + + +#endif // MATERIALSYSTEM_GLOBAL_H diff --git a/materialsystem/shaderapidx9/locald3dtypes.h b/materialsystem/shaderapidx9/locald3dtypes.h new file mode 100644 index 00000000..9a8e4fb2 --- /dev/null +++ b/materialsystem/shaderapidx9/locald3dtypes.h @@ -0,0 +1,191 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + +#ifndef LOCALD3DTYPES_H +#define LOCALD3DTYPES_H + +#ifdef _WIN32 +#pragma once +#endif + +#if defined( DX10 ) && !defined( POSIX ) + +#include +#include + +struct IDirect3D10BaseTexture +{ + ID3D10Resource *m_pBaseTexture; + ID3D10ShaderResourceView *m_pSRView; + ID3D10RenderTargetView *m_pRTView; +}; + +class CDx10Types +{ +public: + typedef struct IDirect3D10BaseTexture IDirect3DTexture; + // FIXME: What is this called now ? + // typedef ID3D10TextureCube IDirect3DCubeTexture; + typedef ID3D10Texture3D IDirect3DVolumeTexture; + typedef ID3D10Device IDirect3DDevice; + typedef D3D10_VIEWPORT D3DVIEWPORT; + typedef ID3D10Buffer IDirect3DIndexBuffer; + typedef ID3D10Buffer IDirect3DVertexBuffer; + typedef ID3D10VertexShader IDirect3DVertexShader; + typedef ID3D10PixelShader IDirect3DPixelShader; + typedef ID3D10ShaderResourceView IDirect3DSurface; + typedef ID3DX10Font ID3DXFont; + typedef ID3D10Query ID3DQuery; + + typedef ID3D10Device *LPDIRECT3DDEVICE; + typedef ID3D10Buffer *LPDIRECT3DINDEXBUFFER; + typedef ID3D10Buffer *LPDIRECT3DVERTEXBUFFER; +}; + +#endif // defined( DX10 ) && !defined( POSIX ) + + +#if !defined( _X360 ) && !defined( POSIX ) +#ifdef _DEBUG +#define D3D_DEBUG_INFO 1 +#endif +#endif + +struct IDirect3DTexture9; +struct IDirect3DBaseTexture9; +struct IDirect3DCubeTexture9; +struct IDirect3D9; +struct IDirect3DDevice9; +struct IDirect3DSurface9; +struct IDirect3DIndexBuffer9; +struct IDirect3DVertexBuffer9; +struct IDirect3DVertexShader9; +struct IDirect3DPixelShader9; +struct IDirect3DVolumeTexture9; + +typedef struct _D3DLIGHT9 D3DLIGHT9; +typedef struct _D3DADAPTER_IDENTIFIER9 D3DADAPTER_IDENTIFIER9; +typedef struct _D3DCAPS9 D3DCAPS9; +typedef struct _D3DVIEWPORT9 D3DVIEWPORT9; +typedef struct _D3DMATERIAL9 D3DMATERIAL9; +typedef IDirect3DTexture9 IDirect3DTexture; +typedef IDirect3DBaseTexture9 IDirect3DBaseTexture; +typedef IDirect3DCubeTexture9 IDirect3DCubeTexture; +typedef IDirect3DVolumeTexture9 IDirect3DVolumeTexture; +typedef IDirect3DDevice9 IDirect3DDevice; +typedef D3DMATERIAL9 D3DMATERIAL; +typedef D3DLIGHT9 D3DLIGHT; +typedef IDirect3DSurface9 IDirect3DSurface; +typedef D3DCAPS9 D3DCAPS; +typedef IDirect3DIndexBuffer9 IDirect3DIndexBuffer; +typedef IDirect3DVertexBuffer9 IDirect3DVertexBuffer; +typedef IDirect3DPixelShader9 IDirect3DPixelShader; +typedef IDirect3DDevice *LPDIRECT3DDEVICE; +typedef IDirect3DIndexBuffer *LPDIRECT3DINDEXBUFFER; +typedef IDirect3DVertexBuffer *LPDIRECT3DVERTEXBUFFER; + +class CDx9Types +{ +public: + typedef IDirect3DTexture9 IDirect3DTexture; + typedef IDirect3DBaseTexture9 IDirect3DBaseTexture; + typedef IDirect3DCubeTexture9 IDirect3DCubeTexture; + typedef IDirect3DVolumeTexture9 IDirect3DVolumeTexture; + typedef IDirect3DDevice9 IDirect3DDevice; + typedef D3DMATERIAL9 D3DMATERIAL; + typedef D3DLIGHT9 D3DLIGHT; + typedef IDirect3DSurface9 IDirect3DSurface; + typedef D3DCAPS9 D3DCAPS; + typedef IDirect3DIndexBuffer9 IDirect3DIndexBuffer; + typedef IDirect3DVertexBuffer9 IDirect3DVertexBuffer; + typedef IDirect3DPixelShader9 IDirect3DPixelShader; + typedef IDirect3DDevice *LPDIRECT3DDEVICE; + typedef IDirect3DIndexBuffer *LPDIRECT3DINDEXBUFFER; + typedef IDirect3DVertexBuffer *LPDIRECT3DVERTEXBUFFER; +}; + +typedef void *HardwareShader_t; + +//----------------------------------------------------------------------------- +// The vertex and pixel shader type +//----------------------------------------------------------------------------- +typedef int VertexShader_t; +typedef int PixelShader_t; + +//----------------------------------------------------------------------------- +// Bitpattern for an invalid shader +//----------------------------------------------------------------------------- +#define INVALID_SHADER ( 0xFFFFFFFF ) +#define INVALID_HARDWARE_SHADER ( NULL ) + +#define D3DSAMP_NOTSUPPORTED D3DSAMP_FORCE_DWORD +#define D3DRS_NOTSUPPORTED D3DRS_FORCE_DWORD + +//#include "dxabstract.h" + +#if defined( _X360 ) + +// not supported, keeping for port ease +#define D3DSAMP_SRGBTEXTURE D3DSAMP_NOTSUPPORTED +#define D3DRS_LIGHTING D3DRS_NOTSUPPORTED +#define D3DRS_DIFFUSEMATERIALSOURCE D3DRS_NOTSUPPORTED +#define D3DRS_SPECULARENABLE D3DRS_NOTSUPPORTED +#define D3DRS_SHADEMODE D3DRS_NOTSUPPORTED +#define D3DRS_LASTPIXEL D3DRS_NOTSUPPORTED +#define D3DRS_DITHERENABLE D3DRS_NOTSUPPORTED +#define D3DRS_FOGENABLE D3DRS_NOTSUPPORTED +#define D3DRS_FOGCOLOR D3DRS_NOTSUPPORTED +#define D3DRS_FOGTABLEMODE D3DRS_NOTSUPPORTED +#define D3DRS_FOGSTART D3DRS_NOTSUPPORTED +#define D3DRS_FOGEND D3DRS_NOTSUPPORTED +#define D3DRS_FOGDENSITY D3DRS_NOTSUPPORTED +#define D3DRS_RANGEFOGENABLE D3DRS_NOTSUPPORTED +#define D3DRS_TEXTUREFACTOR D3DRS_NOTSUPPORTED +#define D3DRS_CLIPPING D3DRS_NOTSUPPORTED +#define D3DRS_AMBIENT D3DRS_NOTSUPPORTED +#define D3DRS_FOGVERTEXMODE D3DRS_NOTSUPPORTED +#define D3DRS_COLORVERTEX D3DRS_NOTSUPPORTED +#define D3DRS_LOCALVIEWER D3DRS_NOTSUPPORTED +#define D3DRS_NORMALIZENORMALS D3DRS_NOTSUPPORTED +#define D3DRS_SPECULARMATERIALSOURCE D3DRS_NOTSUPPORTED +#define D3DRS_AMBIENTMATERIALSOURCE D3DRS_NOTSUPPORTED +#define D3DRS_EMISSIVEMATERIALSOURCE D3DRS_NOTSUPPORTED +#define D3DRS_VERTEXBLEND D3DRS_NOTSUPPORTED +#define D3DRS_POINTSCALEENABLE D3DRS_NOTSUPPORTED +#define D3DRS_POINTSCALE_A D3DRS_NOTSUPPORTED +#define D3DRS_POINTSCALE_B D3DRS_NOTSUPPORTED +#define D3DRS_POINTSCALE_C D3DRS_NOTSUPPORTED +#define D3DRS_PATCHEDGESTYLE D3DRS_NOTSUPPORTED +#define D3DRS_DEBUGMONITORTOKEN D3DRS_NOTSUPPORTED +#define D3DRS_INDEXEDVERTEXBLENDENABLE D3DRS_NOTSUPPORTED +#define D3DRS_TWEENFACTOR D3DRS_NOTSUPPORTED +#define D3DRS_POSITIONDEGREE D3DRS_NOTSUPPORTED +#define D3DRS_NORMALDEGREE D3DRS_NOTSUPPORTED +#define D3DRS_ANTIALIASEDLINEENABLE D3DRS_NOTSUPPORTED +#define D3DRS_ADAPTIVETESS_X D3DRS_NOTSUPPORTED +#define D3DRS_ADAPTIVETESS_Y D3DRS_NOTSUPPORTED +#define D3DRS_ADAPTIVETESS_Z D3DRS_NOTSUPPORTED +#define D3DRS_ADAPTIVETESS_W D3DRS_NOTSUPPORTED +#define D3DRS_ENABLEADAPTIVETESSELLATION D3DRS_NOTSUPPORTED +#define D3DRS_SRGBWRITEENABLE D3DRS_NOTSUPPORTED +#define D3DLOCK_DISCARD 0 +#define D3DUSAGE_DYNAMIC 0 +#define D3DUSAGE_AUTOGENMIPMAP 0 +#define D3DDEVTYPE_REF D3DDEVTYPE_HAL +#define D3DENUM_WHQL_LEVEL 0 +#define D3DCREATE_SOFTWARE_VERTEXPROCESSING D3DCREATE_HARDWARE_VERTEXPROCESSING +#define D3DDMT_ENABLE 0 + +typedef enum D3DSHADEMODE +{ + D3DSHADE_FLAT = 0, + D3DSHADE_GOURAUD = 0, +}; + +#endif // _X360 + +#endif // LOCALD3DTYPES_H diff --git a/materialsystem/shaderlib/BaseShader.cpp b/materialsystem/shaderlib/BaseShader.cpp new file mode 100644 index 00000000..4e425ad9 --- /dev/null +++ b/materialsystem/shaderlib/BaseShader.cpp @@ -0,0 +1,985 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +//===========================================================================// + +#include "shaderlib/BaseShader.h" +#include "shaderlib/ShaderDLL.h" +#include "tier0/dbg.h" +#include "shaderDLL_Global.h" +#include "../IShaderSystem.h" +#include "materialsystem/imaterial.h" +#include "materialsystem/itexture.h" +#include "materialsystem/ishaderapi.h" +#include "materialsystem/materialsystem_config.h" +#include "shaderlib/cshader.h" +#include "shaderlib/commandbuilder.h" +#include "renderparm.h" +#include "mathlib/vmatrix.h" +#include "tier1/strtools.h" +#include "convar.h" +#include "tier0/vprof.h" + +// NOTE: This must be the last include file in a .cpp file! +#include "tier0/memdbgon.h" + + +//----------------------------------------------------------------------------- +// Storage buffer used for instance command buffers +//----------------------------------------------------------------------------- +class CPerInstanceContextData : public CBasePerInstanceContextData +{ +public: + CPerInstanceContextData() : m_pCommandBuffer( NULL ), m_nSize( 0 ) {} + virtual ~CPerInstanceContextData() + { + if ( m_pCommandBuffer ) + { + delete m_pCommandBuffer; + } + } + unsigned char *m_pCommandBuffer; + int m_nSize; +}; + + +//----------------------------------------------------------------------------- +// Globals +//----------------------------------------------------------------------------- +const char *CBaseShader::s_pTextureGroupName = NULL; +IMaterialVar **CBaseShader::s_ppParams; +IShaderShadow *CBaseShader::s_pShaderShadow; +IShaderDynamicAPI *CBaseShader::s_pShaderAPI; +IShaderInit *CBaseShader::s_pShaderInit; +int CBaseShader::s_nModulationFlags; +int CBaseShader::s_nPassCount = 0; +CPerInstanceContextData** CBaseShader::s_pInstanceDataPtr = NULL; +static bool s_bBuildingInstanceCommandBuffer = false; +static CInstanceCommandBufferBuilder< CFixedCommandStorageBuffer< 512 > > s_InstanceCommandBuffer; + +bool g_shaderConfigDumpEnable = false; //true; //DO NOT CHECK IN ENABLED FIXME +static ConVar mat_fullbright( "mat_fullbright","0", FCVAR_CHEAT ); + +//----------------------------------------------------------------------------- +// constructor +//----------------------------------------------------------------------------- +CBaseShader::CBaseShader() +{ + GetShaderDLL()->InsertShader( this ); +} + + +//----------------------------------------------------------------------------- +// Shader parameter info +//----------------------------------------------------------------------------- +// Look in BaseShader.h for the enumeration for these. +// Update there if you update here. +static ShaderParamInfo_t s_StandardParams[NUM_SHADER_MATERIAL_VARS] = +{ + { "$flags", "flags", SHADER_PARAM_TYPE_INTEGER, "0", SHADER_PARAM_NOT_EDITABLE }, + { "$flags_defined", "flags_defined", SHADER_PARAM_TYPE_INTEGER, "0", SHADER_PARAM_NOT_EDITABLE }, + { "$flags2", "flags2", SHADER_PARAM_TYPE_INTEGER, "0", SHADER_PARAM_NOT_EDITABLE }, + { "$flags_defined2", "flags2_defined", SHADER_PARAM_TYPE_INTEGER, "0", SHADER_PARAM_NOT_EDITABLE }, + { "$color", "color", SHADER_PARAM_TYPE_COLOR, "[1 1 1]", 0 }, + { "$alpha", "alpha", SHADER_PARAM_TYPE_FLOAT, "1.0", 0 }, + { "$basetexture", "Base Texture with lighting built in", SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", 0 }, + { "$frame", "Animation Frame", SHADER_PARAM_TYPE_INTEGER, "0", 0 }, + { "$basetexturetransform", "Base Texture Texcoord Transform",SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", 0 }, + { "$flashlighttexture", "flashlight spotlight shape texture", SHADER_PARAM_TYPE_TEXTURE, "effects/flashlight001", SHADER_PARAM_NOT_EDITABLE }, + { "$flashlighttextureframe", "Animation Frame for $flashlight", SHADER_PARAM_TYPE_INTEGER, "0", SHADER_PARAM_NOT_EDITABLE }, + { "$color2", "color2", SHADER_PARAM_TYPE_COLOR, "[1 1 1]", 0 }, + { "$srgbtint", "tint value to be applied when running on new-style srgb parts", SHADER_PARAM_TYPE_COLOR, "[1 1 1]", 0 }, +}; + + +//----------------------------------------------------------------------------- +// Gets the standard shader parameter names +// FIXME: Turn this into one function? +//----------------------------------------------------------------------------- +int CBaseShader::GetParamCount( ) const +{ + return NUM_SHADER_MATERIAL_VARS; +} + +const ShaderParamInfo_t &CBaseShader::GetParamInfo( int nParamIndex ) const +{ + Assert( nParamIndex < NUM_SHADER_MATERIAL_VARS ); + return s_StandardParams[nParamIndex]; +} + + +//----------------------------------------------------------------------------- +// Necessary to snag ahold of some important data for the helper methods +//----------------------------------------------------------------------------- +void CBaseShader::InitShaderParams( IMaterialVar** ppParams, const char *pMaterialName ) +{ + // Re-entrancy check + Assert( !s_ppParams ); + + s_ppParams = ppParams; + + OnInitShaderParams( ppParams, pMaterialName ); + + s_ppParams = NULL; +} + +void CBaseShader::InitShaderInstance( IMaterialVar** ppParams, IShaderInit *pShaderInit, const char *pMaterialName, const char *pTextureGroupName ) +{ + // Re-entrancy check + Assert( !s_ppParams ); + + s_ppParams = ppParams; + s_pShaderInit = pShaderInit; + s_pTextureGroupName = pTextureGroupName; + + OnInitShaderInstance( ppParams, pShaderInit, pMaterialName ); + + s_pTextureGroupName = NULL; + s_ppParams = NULL; + s_pShaderInit = NULL; +} + +void CBaseShader::DrawElements( IMaterialVar **ppParams, int nModulationFlags, + IShaderShadow* pShaderShadow, IShaderDynamicAPI* pShaderAPI, VertexCompressionType_t vertexCompression, CBasePerMaterialContextData **pContextDataPtr, CBasePerInstanceContextData** pInstanceDataPtr ) +{ + VPROF("CBaseShader::DrawElements"); + // Re-entrancy check + Assert( !s_ppParams ); + + s_ppParams = ppParams; + s_pShaderAPI = pShaderAPI; + s_pShaderShadow = pShaderShadow; + s_nModulationFlags = nModulationFlags; + s_pInstanceDataPtr = (CPerInstanceContextData**)( pInstanceDataPtr ); + s_nPassCount = 0; + + if ( IsSnapshotting() ) + { + // Set up the shadow state + SetInitialShadowState( ); + } + + OnDrawElements( ppParams, pShaderShadow, pShaderAPI, vertexCompression, pContextDataPtr ); + + s_pInstanceDataPtr = NULL; + s_nPassCount = 0; + s_nModulationFlags = 0; + s_ppParams = NULL; + s_pShaderAPI = NULL; + s_pShaderShadow = NULL; +} + + +//----------------------------------------------------------------------------- +// Sets the default shadow state +//----------------------------------------------------------------------------- +void CBaseShader::SetInitialShadowState( ) +{ + // Set the default state + s_pShaderShadow->SetDefaultState(); + + // Init the standard states... + int flags = s_ppParams[FLAGS]->GetIntValue(); + if (flags & MATERIAL_VAR_IGNOREZ) + { + s_pShaderShadow->EnableDepthTest( false ); + s_pShaderShadow->EnableDepthWrites( false ); + } + + if (flags & MATERIAL_VAR_DECAL) + { + s_pShaderShadow->EnablePolyOffset( SHADER_POLYOFFSET_DECAL ); + s_pShaderShadow->EnableDepthWrites( false ); + } + + if (flags & MATERIAL_VAR_NOCULL) + { + s_pShaderShadow->EnableCulling( false ); + } + + if (flags & MATERIAL_VAR_ZNEARER) + { + s_pShaderShadow->DepthFunc( SHADER_DEPTHFUNC_NEARER ); + } + + if (flags & MATERIAL_VAR_WIREFRAME) + { + s_pShaderShadow->PolyMode( SHADER_POLYMODEFACE_FRONT_AND_BACK, SHADER_POLYMODE_LINE ); + } + + // Set alpha to coverage + if (flags & MATERIAL_VAR_ALLOWALPHATOCOVERAGE) + { + // Force the bit on and then check against alpha blend and test states in CShaderShadowDX8::ComputeAggregateShadowState() + s_pShaderShadow->EnableAlphaToCoverage( true ); + } +} + + +//----------------------------------------------------------------------------- +// Draws a snapshot +//----------------------------------------------------------------------------- +void CBaseShader::Draw( bool bMakeActualDrawCall ) +{ + // You forgot to call PI_EndCommandBuffer + Assert( !s_bBuildingInstanceCommandBuffer ); + + if ( IsSnapshotting() ) + { + // Turn off transparency if we're asked to.... + if (g_pConfig->bNoTransparency && + ((s_ppParams[FLAGS]->GetIntValue() & MATERIAL_VAR_NO_DEBUG_OVERRIDE) == 0)) + { + s_pShaderShadow->EnableDepthWrites( true ); + s_pShaderShadow->EnableBlending( false ); + } + + GetShaderSystem()->TakeSnapshot(); + + // Automagically add skinning + vertex lighting + if ( !s_pInstanceDataPtr[s_nPassCount] ) + { + bool bIsSkinning = CShader_IsFlag2Set( s_ppParams, MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + bool bIsVertexLit = CShader_IsFlag2Set( s_ppParams, MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + if ( bIsSkinning || bIsVertexLit ) + { + PI_BeginCommandBuffer(); + + // NOTE: EndCommandBuffer will insert the appropriate commands + PI_EndCommandBuffer(); + } + } + } + else + { + GetShaderSystem()->DrawSnapshot( s_pInstanceDataPtr[s_nPassCount] ? + s_pInstanceDataPtr[s_nPassCount]->m_pCommandBuffer : NULL, bMakeActualDrawCall ); + } + + ++s_nPassCount; +} + + +//----------------------------------------------------------------------------- +// Methods related to building per-instance command buffers +//----------------------------------------------------------------------------- +void CBaseShader::PI_BeginCommandBuffer() +{ + // NOTE: This assertion is here because the memory allocation strategy + // is perhaps not the best if this is used in dynamic states; we should + // rethink in that case. + Assert( IsSnapshotting() ); + + Assert( !s_bBuildingInstanceCommandBuffer ); + s_bBuildingInstanceCommandBuffer = true; + s_InstanceCommandBuffer.Reset(); +} + +void CBaseShader::PI_EndCommandBuffer() +{ + Assert( s_bBuildingInstanceCommandBuffer ); + + // Automagically add skinning + if ( CShader_IsFlag2Set( s_ppParams, MATERIAL_VAR2_SUPPORTS_HW_SKINNING ) ) + { + PI_SetSkinningMatrices(); + } + + if ( CShader_IsFlag2Set( s_ppParams, MATERIAL_VAR2_LIGHTING_VERTEX_LIT ) ) + { + PI_SetVertexShaderLocalLighting(); + } + + s_bBuildingInstanceCommandBuffer = false; + s_InstanceCommandBuffer.End(); + int nSize = s_InstanceCommandBuffer.Size(); + if ( nSize > 0 ) + { + CPerInstanceContextData *pContextData = s_pInstanceDataPtr[ s_nPassCount ]; + if ( !pContextData ) + { + pContextData = new CPerInstanceContextData; + s_pInstanceDataPtr[ s_nPassCount ] = pContextData; + } + unsigned char *pBuf = pContextData->m_pCommandBuffer; + if ( pContextData->m_nSize < nSize ) + { + if ( pContextData->m_pCommandBuffer ) + { + delete pContextData->m_pCommandBuffer; + } + pBuf = new unsigned char[nSize]; + pContextData->m_pCommandBuffer = pBuf; + pContextData->m_nSize = nSize; + } + memcpy( pBuf, s_InstanceCommandBuffer.Base(), nSize ); + } +} + + +//----------------------------------------------------------------------------- +// Queues commands onto the instance command buffer +//----------------------------------------------------------------------------- +void CBaseShader::PI_SetPixelShaderAmbientLightCube( int nFirstRegister ) +{ + Assert( s_bBuildingInstanceCommandBuffer ); + s_InstanceCommandBuffer.SetPixelShaderAmbientLightCube( nFirstRegister ); +} + +void CBaseShader::PI_SetPixelShaderLocalLighting( int nFirstRegister ) +{ + Assert( s_bBuildingInstanceCommandBuffer ); + s_InstanceCommandBuffer.SetPixelShaderLocalLighting( nFirstRegister ); +} + +void CBaseShader::PI_SetVertexShaderAmbientLightCube( /*int nFirstRegister*/ ) +{ + Assert( s_bBuildingInstanceCommandBuffer ); + s_InstanceCommandBuffer.SetVertexShaderAmbientLightCube( /*nFirstRegister*/ ); +} + +void CBaseShader::PI_SetVertexShaderLocalLighting() +{ + Assert( s_bBuildingInstanceCommandBuffer ); + s_InstanceCommandBuffer.SetVertexShaderLocalLighting( ); +} + +void CBaseShader::PI_SetSkinningMatrices() +{ + Assert( s_bBuildingInstanceCommandBuffer ); + s_InstanceCommandBuffer.SetSkinningMatrices(); +} + +void CBaseShader::PI_SetPixelShaderAmbientLightCubeLuminance( int nFirstRegister ) +{ + Assert( s_bBuildingInstanceCommandBuffer ); + s_InstanceCommandBuffer.SetPixelShaderAmbientLightCubeLuminance( nFirstRegister ); +} + +void CBaseShader::PI_SetPixelShaderGlintDamping( int nFirstRegister ) +{ + Assert( s_bBuildingInstanceCommandBuffer ); + s_InstanceCommandBuffer.SetPixelShaderGlintDamping( nFirstRegister ); +} + +void CBaseShader::PI_SetModulationPixelShaderDynamicState_LinearColorSpace_LinearScale( int nRegister, float scale ) +{ + Assert( s_bBuildingInstanceCommandBuffer ); + Vector color2( 1.0f, 1.0f, 1.0f ); + ApplyColor2Factor( color2.Base() ); + s_InstanceCommandBuffer.SetModulationPixelShaderDynamicState_LinearColorSpace_LinearScale( nRegister, color2, scale ); +} + +void CBaseShader::PI_SetModulationPixelShaderDynamicState_LinearScale( int nRegister, float scale ) +{ + Assert( s_bBuildingInstanceCommandBuffer ); + Vector color2( 1.0f, 1.0f, 1.0f ); + ApplyColor2Factor( color2.Base() ); + s_InstanceCommandBuffer.SetModulationPixelShaderDynamicState_LinearScale( nRegister, color2, scale ); +} + +void CBaseShader::PI_SetModulationPixelShaderDynamicState_LinearScale_ScaleInW( int nRegister, float scale ) +{ + Assert( s_bBuildingInstanceCommandBuffer ); + Vector color2( 1.0f, 1.0f, 1.0f ); + ApplyColor2Factor( color2.Base() ); + s_InstanceCommandBuffer.SetModulationPixelShaderDynamicState_LinearScale_ScaleInW( nRegister, color2, scale ); +} + +void CBaseShader::PI_SetModulationPixelShaderDynamicState_LinearColorSpace( int nRegister ) +{ + Assert( s_bBuildingInstanceCommandBuffer ); + Vector color2( 1.0f, 1.0f, 1.0f ); + ApplyColor2Factor( color2.Base() ); + s_InstanceCommandBuffer.SetModulationPixelShaderDynamicState_LinearColorSpace( nRegister, color2 ); +} + +void CBaseShader::PI_SetModulationPixelShaderDynamicState( int nRegister ) +{ + Assert( s_bBuildingInstanceCommandBuffer ); + Vector color2( 1.0f, 1.0f, 1.0f ); + ApplyColor2Factor( color2.Base() ); + s_InstanceCommandBuffer.SetModulationPixelShaderDynamicState( nRegister, color2 ); +} + +void CBaseShader::PI_SetModulationVertexShaderDynamicState() +{ + Assert( s_bBuildingInstanceCommandBuffer ); + Vector color2( 1.0f, 1.0f, 1.0f ); + ApplyColor2Factor( color2.Base() ); + s_InstanceCommandBuffer.SetModulationVertexShaderDynamicState( VERTEX_SHADER_MODULATION_COLOR, color2 ); +} + +void CBaseShader::PI_SetModulationVertexShaderDynamicState_LinearScale( float flScale ) +{ + Assert( s_bBuildingInstanceCommandBuffer ); + Vector color2( 1.0f, 1.0f, 1.0f ); + ApplyColor2Factor( color2.Base() ); + s_InstanceCommandBuffer.SetModulationVertexShaderDynamicState_LinearScale( VERTEX_SHADER_MODULATION_COLOR, color2, flScale ); +} + +void CBaseShader::PI_SetModulationPixelShaderDynamicState_Identity( int nRegister ) +{ + Assert( s_bBuildingInstanceCommandBuffer ); + s_InstanceCommandBuffer.SetModulationPixelShaderDynamicState_Identity( nRegister ); +} + +//----------------------------------------------------------------------------- +// Finds a particular parameter (works because the lowest parameters match the shader) +//----------------------------------------------------------------------------- +int CBaseShader::FindParamIndex( const char *pName ) const +{ + int numParams = GetParamCount(); + for( int i = 0; i < numParams; i++ ) + { + if( Q_strnicmp( GetParamInfo( i ).m_pName, pName, 64 ) == 0 ) + { + return i; + } + } + return -1; +} + + +//----------------------------------------------------------------------------- +// Are we using graphics? +//----------------------------------------------------------------------------- +bool CBaseShader::IsUsingGraphics() +{ + return GetShaderSystem()->IsUsingGraphics(); +} + + +//----------------------------------------------------------------------------- +// Are we using graphics? +//----------------------------------------------------------------------------- +bool CBaseShader::CanUseEditorMaterials() const +{ + return GetShaderSystem()->CanUseEditorMaterials(); +} + + +//----------------------------------------------------------------------------- +// Loads a texture +//----------------------------------------------------------------------------- +void CBaseShader::LoadTexture( int nTextureVar ) +{ + if ((!s_ppParams) || (nTextureVar == -1)) + return; + + IMaterialVar* pNameVar = s_ppParams[nTextureVar]; + if( pNameVar && pNameVar->IsDefined() ) + { + s_pShaderInit->LoadTexture( pNameVar, s_pTextureGroupName ); + } +} + + +//----------------------------------------------------------------------------- +// Loads a bumpmap +//----------------------------------------------------------------------------- +void CBaseShader::LoadBumpMap( int nTextureVar ) +{ + if ((!s_ppParams) || (nTextureVar == -1)) + return; + + IMaterialVar* pNameVar = s_ppParams[nTextureVar]; + if( pNameVar && pNameVar->IsDefined() ) + { + s_pShaderInit->LoadBumpMap( pNameVar, s_pTextureGroupName ); + } +} + + +//----------------------------------------------------------------------------- +// Loads a cubemap +//----------------------------------------------------------------------------- +void CBaseShader::LoadCubeMap( int nTextureVar ) +{ + if ((!s_ppParams) || (nTextureVar == -1)) + return; + + IMaterialVar* pNameVar = s_ppParams[nTextureVar]; + if( pNameVar && pNameVar->IsDefined() ) + { + s_pShaderInit->LoadCubeMap( s_ppParams, pNameVar ); + } +} + + +ShaderAPITextureHandle_t CBaseShader::GetShaderAPITextureBindHandle( int nTextureVar, int nFrameVar, int nTextureChannel ) +{ + Assert( !IsSnapshotting() ); + Assert( nTextureVar != -1 ); + Assert ( s_ppParams ); + + IMaterialVar* pTextureVar = s_ppParams[nTextureVar]; + IMaterialVar* pFrameVar = (nFrameVar != -1) ? s_ppParams[nFrameVar] : NULL; + int nFrame = pFrameVar ? pFrameVar->GetIntValue() : 0; + return GetShaderSystem()->GetShaderAPITextureBindHandle( pTextureVar->GetTextureValue(), nFrame, nTextureChannel ); +} + +void CBaseShader::BindVertexTexture( VertexTextureSampler_t vtSampler, int nTextureVar, int nFrame /* = 0 */) +{ + Assert( !IsSnapshotting() ); + + IMaterialVar* pTextureVar = s_ppParams[nTextureVar]; + if ( !pTextureVar ) + return; + + GetShaderSystem()->BindVertexTexture( vtSampler, pTextureVar->GetTextureValue() ); +} + +ShaderAPITextureHandle_t CBaseShader::GetShaderAPITextureBindHandle( ITexture *pTexture, int nFrame, int nTextureChannel ) +{ + return GetShaderSystem()->GetShaderAPITextureBindHandle( pTexture, nFrame, nTextureChannel ); +} + +//----------------------------------------------------------------------------- +// Four different flavors of BindTexture(), handling the two-sampler +// case as well as ITexture* versus textureVar forms +//----------------------------------------------------------------------------- + +void CBaseShader::BindTexture( Sampler_t sampler1, int nTextureVar, int nFrameVar /* = -1 */ ) +{ + BindTexture( sampler1, (Sampler_t) -1, nTextureVar, nFrameVar ); +} + + +void CBaseShader::BindTexture( Sampler_t sampler1, Sampler_t sampler2, int nTextureVar, int nFrameVar /* = -1 */ ) +{ + Assert( !IsSnapshotting() ); + Assert( nTextureVar != -1 ); + Assert ( s_ppParams ); + + IMaterialVar* pTextureVar = s_ppParams[nTextureVar]; + IMaterialVar* pFrameVar = (nFrameVar != -1) ? s_ppParams[nFrameVar] : NULL; + if (pTextureVar) + { + int nFrame = pFrameVar ? pFrameVar->GetIntValue() : 0; + + if ( sampler2 == -1 ) + { + GetShaderSystem()->BindTexture( sampler1, pTextureVar->GetTextureValue(), nFrame ); + } + else + { + GetShaderSystem()->BindTexture( sampler1, sampler2, pTextureVar->GetTextureValue(), nFrame ); + } + } +} + + +void CBaseShader::BindTexture( Sampler_t sampler1, ITexture *pTexture, int nFrame /* = 0 */ ) +{ + BindTexture( sampler1, (Sampler_t) -1, pTexture, nFrame ); +} + +void CBaseShader::BindTexture( Sampler_t sampler1, Sampler_t sampler2, ITexture *pTexture, int nFrame /* = 0 */ ) +{ + Assert( !IsSnapshotting() ); + + if ( sampler2 == -1 ) + { + GetShaderSystem()->BindTexture( sampler1, pTexture, nFrame ); + } + else + { + GetShaderSystem()->BindTexture( sampler1, sampler2, pTexture, nFrame ); + } +} + + +//----------------------------------------------------------------------------- +// Does the texture store translucency in its alpha channel? +//----------------------------------------------------------------------------- +bool CBaseShader::TextureIsTranslucent( int textureVar, bool isBaseTexture ) +{ + if (textureVar < 0) + return false; + + IMaterialVar** params = s_ppParams; + if (params[textureVar]->GetType() == MATERIAL_VAR_TYPE_TEXTURE) + { + if (!isBaseTexture) + { + return params[textureVar]->GetTextureValue()->IsTranslucent(); + } + else + { + // Override translucency settings if this flag is set. + if (IS_FLAG_SET(MATERIAL_VAR_OPAQUETEXTURE)) + return false; + + bool bHasSelfIllum = ( ( CurrentMaterialVarFlags() & MATERIAL_VAR_SELFILLUM ) != 0 ); + bool bHasSelfIllumMask = ( ( CurrentMaterialVarFlags2() & MATERIAL_VAR2_SELFILLUMMASK ) != 0 ); + bool bHasBaseAlphaEnvmapMask = ( ( CurrentMaterialVarFlags() & MATERIAL_VAR_BASEALPHAENVMAPMASK ) != 0 ); + bool bUsingBaseTextureAlphaForSelfIllum = bHasSelfIllum && !bHasSelfIllumMask; + // Check if we are using base texture alpha for something other than translucency. + if ( !bUsingBaseTextureAlphaForSelfIllum && !bHasBaseAlphaEnvmapMask ) + { + // We aren't using base alpha for anything other than trancluceny. + + // check if the material is marked as translucent or alpha test. + if ((CurrentMaterialVarFlags() & MATERIAL_VAR_TRANSLUCENT) || + (CurrentMaterialVarFlags() & MATERIAL_VAR_ALPHATEST)) + { + // Make sure the texture has an alpha channel. + return params[textureVar]->GetTextureValue()->IsTranslucent(); + } + } + } + } + + return false; +} + + +//----------------------------------------------------------------------------- +// +// Helper methods for color modulation +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Are we alpha or color modulating? +//----------------------------------------------------------------------------- +bool CBaseShader::IsAlphaModulating() +{ + return (s_nModulationFlags & SHADER_USING_ALPHA_MODULATION) != 0; +} +// FIXME: Figure out a better way to do this? +//----------------------------------------------------------------------------- +int CBaseShader::ComputeModulationFlags( IMaterialVar** params, IShaderDynamicAPI* pShaderAPI ) +{ + s_pShaderAPI = pShaderAPI; + + int mod = 0; + if( UsingFlashlight(params) ) + { + mod |= SHADER_USING_FLASHLIGHT; + } + + if ( UsingEditor(params) ) + { + mod |= SHADER_USING_EDITOR; + } + + if( IS_FLAG2_SET( MATERIAL_VAR2_USE_FIXED_FUNCTION_BAKED_LIGHTING ) ) + { + AssertOnce( IS_FLAG2_SET( MATERIAL_VAR2_NEEDS_BAKED_LIGHTING_SNAPSHOTS ) ); + if( IS_FLAG2_SET( MATERIAL_VAR2_NEEDS_BAKED_LIGHTING_SNAPSHOTS ) ) + { + mod |= SHADER_USING_FIXED_FUNCTION_BAKED_LIGHTING; + } + } + + if ( IsSnapshotting() ) + { + if ( IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER0 ) ) + mod |= SHADER_USING_GBUFFER0; + if ( IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER1 ) ) + mod |= SHADER_USING_GBUFFER1; + } + else + { + int nFixedLightingMode = pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_ENABLE_FIXED_LIGHTING ); + if ( nFixedLightingMode & 1 ) + mod |= SHADER_USING_GBUFFER0; + if ( nFixedLightingMode & 2 ) + mod |= SHADER_USING_GBUFFER1; + } + s_pShaderAPI = NULL; + return mod; +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +bool CBaseShader::NeedsPowerOfTwoFrameBufferTexture( IMaterialVar **params, bool bCheckSpecificToThisFrame ) const +{ + return CShader_IsFlag2Set( params, MATERIAL_VAR2_NEEDS_POWER_OF_TWO_FRAME_BUFFER_TEXTURE ); +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +bool CBaseShader::NeedsFullFrameBufferTexture( IMaterialVar **params, bool bCheckSpecificToThisFrame ) const +{ + return CShader_IsFlag2Set( params, MATERIAL_VAR2_NEEDS_FULL_FRAME_BUFFER_TEXTURE ); +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +bool CBaseShader::IsTranslucent( IMaterialVar **params ) const +{ + return IS_FLAG_SET( MATERIAL_VAR_TRANSLUCENT ); +} + +//----------------------------------------------------------------------------- +// Returns the translucency... +//----------------------------------------------------------------------------- +void CBaseShader::ApplyColor2Factor( float *pColorOut ) const // (*pColorOut) *= COLOR2 +{ + if ( !g_pConfig->bShowDiffuse ) + { + pColorOut[0] = pColorOut[1] = pColorOut[2] = 0.0f; + return; + } + + IMaterialVar* pColor2Var = s_ppParams[COLOR2]; + if ( pColor2Var->GetType() == MATERIAL_VAR_TYPE_VECTOR ) + { + float flColor2[3]; + pColor2Var->GetVecValue( flColor2, 3 ); + + pColorOut[0] *= flColor2[0]; + pColorOut[1] *= flColor2[1]; + pColorOut[2] *= flColor2[2]; + } + if ( g_pHardwareConfig->UsesSRGBCorrectBlending() ) + { + IMaterialVar* pSRGBVar = s_ppParams[SRGBTINT]; + if (pSRGBVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + { + float flSRGB[3]; + pSRGBVar->GetVecValue( flSRGB, 3 ); + + pColorOut[0] *= flSRGB[0]; + pColorOut[1] *= flSRGB[1]; + pColorOut[2] *= flSRGB[2]; + } + } +} + + +//----------------------------------------------------------------------------- +// +// Helper methods for alpha blending.... +// +//----------------------------------------------------------------------------- +void CBaseShader::EnableAlphaBlending( ShaderBlendFactor_t src, ShaderBlendFactor_t dst ) +{ + Assert( IsSnapshotting() ); + s_pShaderShadow->EnableBlending( true ); + s_pShaderShadow->BlendFunc( src, dst ); + s_pShaderShadow->EnableDepthWrites(false); +} + +void CBaseShader::DisableAlphaBlending() +{ + Assert( IsSnapshotting() ); + s_pShaderShadow->EnableBlending( false ); +} + +void CBaseShader::SetNormalBlendingShadowState( int textureVar, bool isBaseTexture ) +{ + Assert( IsSnapshotting() ); + + // Either we've got a constant modulation + bool isTranslucent = IsAlphaModulating(); + + // Or we've got a vertex alpha + isTranslucent = isTranslucent || (CurrentMaterialVarFlags() & MATERIAL_VAR_VERTEXALPHA); + + // Or we've got a texture alpha + isTranslucent = isTranslucent || ( TextureIsTranslucent( textureVar, isBaseTexture ) && + !(CurrentMaterialVarFlags() & MATERIAL_VAR_ALPHATEST ) ); + + if (isTranslucent) + { + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + else + { + DisableAlphaBlending(); + } +} + +//ConVar mat_debug_flashlight_only( "mat_debug_flashlight_only", "0" ); +void CBaseShader::SetAdditiveBlendingShadowState( int textureVar, bool isBaseTexture ) +{ + Assert( IsSnapshotting() ); + + // Either we've got a constant modulation + bool isTranslucent = IsAlphaModulating(); + + // Or we've got a vertex alpha + isTranslucent = isTranslucent || (CurrentMaterialVarFlags() & MATERIAL_VAR_VERTEXALPHA); + + // Or we've got a texture alpha + isTranslucent = isTranslucent || ( TextureIsTranslucent( textureVar, isBaseTexture ) && + !(CurrentMaterialVarFlags() & MATERIAL_VAR_ALPHATEST ) ); + + /* + if ( mat_debug_flashlight_only.GetBool() ) + { + if (isTranslucent) + { + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA); + //s_pShaderShadow->EnableAlphaTest( true ); + //s_pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GREATER, 0.99f ); + } + else + { + EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ZERO); + } + } + else + */ + { + if (isTranslucent) + { + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + } + else + { + EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); + } + } +} + +void CBaseShader::SetDefaultBlendingShadowState( int textureVar, bool isBaseTexture ) +{ + if ( CurrentMaterialVarFlags() & MATERIAL_VAR_ADDITIVE ) + { + SetAdditiveBlendingShadowState( textureVar, isBaseTexture ); + } + else + { + SetNormalBlendingShadowState( textureVar, isBaseTexture ); + } +} + +void CBaseShader::SetBlendingShadowState( BlendType_t nMode ) +{ + switch ( nMode ) + { + case BT_NONE: + DisableAlphaBlending(); + break; + + case BT_BLEND: + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + break; + + case BT_ADD: + EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); + break; + + case BT_BLENDADD: + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + break; + } +} + + + +//----------------------------------------------------------------------------- +// Sets lightmap blending mode for single texturing +//----------------------------------------------------------------------------- +void CBaseShader::SingleTextureLightmapBlendMode( ) +{ + Assert( IsSnapshotting() ); + + s_pShaderShadow->EnableBlending( true ); + s_pShaderShadow->BlendFunc( SHADER_BLEND_DST_COLOR, SHADER_BLEND_SRC_COLOR ); +} + +FORCEINLINE void CBaseShader::SetFogMode( ShaderFogMode_t fogMode ) +{ + if (( CurrentMaterialVarFlags() & MATERIAL_VAR_NOFOG ) == 0) + { + bool bVertexFog = ( ( CurrentMaterialVarFlags() & MATERIAL_VAR_VERTEXFOG ) != 0 ); + s_pShaderShadow->FogMode( fogMode, bVertexFog ); + } + else + { + s_pShaderShadow->FogMode( SHADER_FOGMODE_DISABLED, false ); + } +} + +//----------------------------------------------------------------------------- +// +// Helper methods for fog +// +//----------------------------------------------------------------------------- +void CBaseShader::FogToOOOverbright( void ) +{ + Assert( IsSnapshotting() ); + SetFogMode( SHADER_FOGMODE_OO_OVERBRIGHT ); +} + +void CBaseShader::FogToWhite( void ) +{ + Assert( IsSnapshotting() ); + SetFogMode( SHADER_FOGMODE_WHITE ); +} +void CBaseShader::FogToBlack( void ) +{ + Assert( IsSnapshotting() ); + SetFogMode( SHADER_FOGMODE_BLACK ); +} + +void CBaseShader::FogToGrey( void ) +{ + Assert( IsSnapshotting() ); + SetFogMode( SHADER_FOGMODE_GREY ); +} + +void CBaseShader::FogToFogColor( void ) +{ + Assert( IsSnapshotting() ); + SetFogMode( SHADER_FOGMODE_FOGCOLOR ); +} + +void CBaseShader::DisableFog( void ) +{ + Assert( IsSnapshotting() ); + s_pShaderShadow->FogMode( SHADER_FOGMODE_DISABLED, false ); +} + +void CBaseShader::DefaultFog( void ) +{ + if ( CurrentMaterialVarFlags() & MATERIAL_VAR_ADDITIVE ) + { + FogToBlack(); + } + else + { + FogToFogColor(); + } +} + +bool CBaseShader::UsingFlashlight( IMaterialVar **params ) const +{ + if( IsSnapshotting() ) + { + return CShader_IsFlag2Set( params, MATERIAL_VAR2_USE_FLASHLIGHT ); + } + else + { + return s_pShaderAPI->InFlashlightMode(); + } +} + +bool CBaseShader::UsingEditor( IMaterialVar **params ) const +{ + if( IsSnapshotting() ) + { + return CShader_IsFlag2Set( params, MATERIAL_VAR2_USE_EDITOR ); + } + else + { + return s_pShaderAPI->InEditorMode(); + } +} + +bool CBaseShader::IsHDREnabled( void ) +{ + // HDRFIXME! Need to fix this for vgui materials + HDRType_t hdr_mode = g_pHardwareConfig->GetHDRType(); + return ( hdr_mode == HDR_TYPE_INTEGER ) || ( hdr_mode == HDR_TYPE_FLOAT ); +} diff --git a/materialsystem/shaderlib/ShaderDLL.cpp b/materialsystem/shaderlib/ShaderDLL.cpp new file mode 100644 index 00000000..70324ef5 --- /dev/null +++ b/materialsystem/shaderlib/ShaderDLL.cpp @@ -0,0 +1,169 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +//===========================================================================// + +#include "shaderlib/ShaderDLL.h" +#include "materialsystem/IShader.h" +#include "tier1/utlvector.h" +#include "tier0/dbg.h" +#include "materialsystem/imaterialsystemhardwareconfig.h" +#include "materialsystem/materialsystem_config.h" +#include "IShaderSystem.h" +#include "materialsystem/ishaderapi.h" +#include "shaderlib_cvar.h" +#include "mathlib/mathlib.h" +#include "tier2/tier2.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +//----------------------------------------------------------------------------- +// The standard implementation of CShaderDLL +//----------------------------------------------------------------------------- +class CShaderDLL : public IShaderDLLInternal, public IShaderDLL +{ +public: + CShaderDLL(); + + // methods of IShaderDLL + virtual bool Connect( CreateInterfaceFn factory ); + virtual void Disconnect(); + virtual int ShaderCount() const; + virtual IShader *GetShader( int nShader ); + + // methods of IShaderDLLInternal + virtual bool Connect( CreateInterfaceFn factory, bool bIsMaterialSystem ); + virtual void Disconnect( bool bIsMaterialSystem ); + virtual void InsertShader( IShader *pShader ); + +private: + CUtlVector< IShader * > m_ShaderList; +}; + + +//----------------------------------------------------------------------------- +// Global interfaces/structures +//----------------------------------------------------------------------------- +IMaterialSystemHardwareConfig* g_pHardwareConfig; +const MaterialSystem_Config_t *g_pConfig; + + +//----------------------------------------------------------------------------- +// Interfaces/structures local to shaderlib +//----------------------------------------------------------------------------- +IShaderSystem* g_pSLShaderSystem; + + +// Pattern necessary because shaders register themselves in global constructors +static CShaderDLL *s_pShaderDLL; + + +//----------------------------------------------------------------------------- +// Global accessor +//----------------------------------------------------------------------------- +IShaderDLL *GetShaderDLL() +{ + // Pattern necessary because shaders register themselves in global constructors + if ( !s_pShaderDLL ) + { + s_pShaderDLL = new CShaderDLL; + } + + return s_pShaderDLL; +} + +IShaderDLLInternal *GetShaderDLLInternal() +{ + // Pattern necessary because shaders register themselves in global constructors + if ( !s_pShaderDLL ) + { + s_pShaderDLL = new CShaderDLL; + } + + return static_cast( s_pShaderDLL ); +} + +//----------------------------------------------------------------------------- +// Singleton interface +//----------------------------------------------------------------------------- +EXPOSE_INTERFACE_FN( (InstantiateInterfaceFn)GetShaderDLLInternal, IShaderDLLInternal, SHADER_DLL_INTERFACE_VERSION ); + +//----------------------------------------------------------------------------- +// Connect, disconnect... +//----------------------------------------------------------------------------- +CShaderDLL::CShaderDLL() +{ + MathLib_Init( 2.2f, 2.2f, 0.0f, 2.0f ); +} + + +//----------------------------------------------------------------------------- +// Connect, disconnect... +//----------------------------------------------------------------------------- +bool CShaderDLL::Connect( CreateInterfaceFn factory, bool bIsMaterialSystem ) +{ + g_pHardwareConfig = (IMaterialSystemHardwareConfig*)factory( MATERIALSYSTEM_HARDWARECONFIG_INTERFACE_VERSION, NULL ); + g_pConfig = (const MaterialSystem_Config_t*)factory( MATERIALSYSTEM_CONFIG_VERSION, NULL ); + g_pSLShaderSystem = (IShaderSystem*)factory( SHADERSYSTEM_INTERFACE_VERSION, NULL ); + + if ( !bIsMaterialSystem ) + { + ConnectTier1Libraries( &factory, 1 ); + InitShaderLibCVars( factory ); + } + + return ( g_pConfig != NULL ) && (g_pHardwareConfig != NULL) && ( g_pSLShaderSystem != NULL ); +} + +void CShaderDLL::Disconnect( bool bIsMaterialSystem ) +{ + if ( !bIsMaterialSystem ) + { + ConVar_Unregister(); + DisconnectTier1Libraries(); + } + + g_pHardwareConfig = NULL; + g_pConfig = NULL; + g_pSLShaderSystem = NULL; +} + +bool CShaderDLL::Connect( CreateInterfaceFn factory ) +{ + return Connect( factory, false ); +} + +void CShaderDLL::Disconnect() +{ + Disconnect( false ); +} + + +//----------------------------------------------------------------------------- +// Iterates over all shaders +//----------------------------------------------------------------------------- +int CShaderDLL::ShaderCount() const +{ + return m_ShaderList.Count(); +} + +IShader *CShaderDLL::GetShader( int nShader ) +{ + if ( ( nShader < 0 ) || ( nShader >= m_ShaderList.Count() ) ) + return NULL; + + return m_ShaderList[nShader]; +} + + +//----------------------------------------------------------------------------- +// Adds to the shader lists +//----------------------------------------------------------------------------- +void CShaderDLL::InsertShader( IShader *pShader ) +{ + Assert( pShader ); + m_ShaderList.AddToTail( pShader ); +} + diff --git a/materialsystem/shaderlib/shaderDLL_Global.h b/materialsystem/shaderlib/shaderDLL_Global.h new file mode 100644 index 00000000..d38a25b2 --- /dev/null +++ b/materialsystem/shaderlib/shaderDLL_Global.h @@ -0,0 +1,33 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#ifndef SHADERDLL_GLOBAL_H +#define SHADERDLL_GLOBAL_H + +#ifdef _WIN32 +#pragma once +#endif + + +//----------------------------------------------------------------------------- +// forward declarations +//----------------------------------------------------------------------------- +class IShaderSystem; + + +//----------------------------------------------------------------------------- +// forward declarations +//----------------------------------------------------------------------------- +inline IShaderSystem *GetShaderSystem() +{ + extern IShaderSystem* g_pSLShaderSystem; + return g_pSLShaderSystem; +} + + +#endif // SHADERDLL_GLOBAL_H diff --git a/materialsystem/shaderlib/shaderlib_cvar.cpp b/materialsystem/shaderlib/shaderlib_cvar.cpp new file mode 100644 index 00000000..f894c4a9 --- /dev/null +++ b/materialsystem/shaderlib/shaderlib_cvar.cpp @@ -0,0 +1,42 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +//===========================================================================// + +#include "icvar.h" +#include "tier1/tier1.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +// ------------------------------------------------------------------------------------------- // +// ConVar stuff. +// ------------------------------------------------------------------------------------------- // +class CShaderLibConVarAccessor : public IConCommandBaseAccessor +{ +public: + virtual bool RegisterConCommandBase( ConCommandBase *pCommand ) + { + // Link to engine's list instead + g_pCVar->RegisterConCommand( pCommand ); + + char const *pValue = g_pCVar->GetCommandLineValue( pCommand->GetName() ); + if( pValue && !pCommand->IsCommand() ) + { + ( ( ConVar * )pCommand )->SetValue( pValue ); + } + return true; + } +}; + +CShaderLibConVarAccessor g_ConVarAccessor; + + +void InitShaderLibCVars( CreateInterfaceFn cvarFactory ) +{ + if ( g_pCVar ) + { + ConVar_Register( FCVAR_MATERIAL_SYSTEM_THREAD, &g_ConVarAccessor ); + } +} diff --git a/materialsystem/shaderlib/shaderlib_cvar.h b/materialsystem/shaderlib/shaderlib_cvar.h new file mode 100644 index 00000000..b53670fd --- /dev/null +++ b/materialsystem/shaderlib/shaderlib_cvar.h @@ -0,0 +1,20 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#ifndef SHADERLIB_CVAR_H +#define SHADERLIB_CVAR_H +#ifdef _WIN32 +#pragma once +#endif + + +#include "interface.h" + + +void InitShaderLibCVars( CreateInterfaceFn cvarFactory ); + + +#endif // SHADERLIB_CVAR_H diff --git a/materialsystem/shaderlib/shaderlib_sdk.vcproj b/materialsystem/shaderlib/shaderlib_sdk.vcproj new file mode 100644 index 00000000..3ebd619f --- /dev/null +++ b/materialsystem/shaderlib/shaderlib_sdk.vcproj @@ -0,0 +1,423 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/materialsystem/stdshaders/BaseVSShader.cpp b/materialsystem/stdshaders/BaseVSShader.cpp new file mode 100644 index 00000000..43c40927 --- /dev/null +++ b/materialsystem/stdshaders/BaseVSShader.cpp @@ -0,0 +1,1177 @@ +//===== Copyright © 1996-2007, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $NoKeywords: $ +// This is what all vs/ps (dx8+) shaders inherit from. +//===========================================================================// +#if !defined(_STATIC_LINKED) || defined(STDSHADER_DX9_DLL_EXPORT) + +#include "cpp_shader_constant_register_map.h" +#include "basevsshader.h" +#include "mathlib/vmatrix.h" +#include "mathlib/bumpvects.h" +#include "ConVar.h" +#include "tier0/icommandline.h" + +#ifdef HDR +#include "vertexlit_and_unlit_generic_hdr_ps20.inc" +#include "vertexlit_and_unlit_generic_hdr_ps20b.inc" +#endif + +#ifndef _X360 +#include "lightmappedgeneric_flashlight_vs30.inc" +#include "flashlight_ps30.inc" +#endif + +#include "lightmappedgeneric_flashlight_vs20.inc" +#include "flashlight_ps20.inc" +#include "flashlight_ps20b.inc" +#include "vertexlitgeneric_flashlight_vs20.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +static ConVar mat_fullbright( "mat_fullbright","0", FCVAR_CHEAT ); + +// NOTE: This is externed in BaseVSShader.h so it needs to be here +ConVar r_flashlightbrightness( "r_flashlightbrightness", "0.25", FCVAR_CHEAT ); + +// These functions are to be called from the shaders. + +//----------------------------------------------------------------------------- +// Pixel and vertex shader constants.... +//----------------------------------------------------------------------------- +void CBaseVSShader::SetPixelShaderConstant( int pixelReg, int constantVar, int constantVar2 ) +{ + Assert( !IsSnapshotting() ); + if ((!s_ppParams) || (constantVar == -1) || (constantVar2 == -1)) + return; + + IMaterialVar* pPixelVar = s_ppParams[constantVar]; + Assert( pPixelVar ); + IMaterialVar* pPixelVar2 = s_ppParams[constantVar2]; + Assert( pPixelVar2 ); + + float val[4]; + if (pPixelVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + { + pPixelVar->GetVecValue( val, 3 ); + } + else + { + val[0] = val[1] = val[2] = pPixelVar->GetFloatValue(); + } + + val[3] = pPixelVar2->GetFloatValue(); + s_pShaderAPI->SetPixelShaderConstant( pixelReg, val ); +} + +void CBaseVSShader::SetPixelShaderConstantGammaToLinear( int pixelReg, int constantVar, int constantVar2 ) +{ + Assert( !IsSnapshotting() ); + if ((!s_ppParams) || (constantVar == -1) || (constantVar2 == -1)) + return; + + IMaterialVar* pPixelVar = s_ppParams[constantVar]; + Assert( pPixelVar ); + IMaterialVar* pPixelVar2 = s_ppParams[constantVar2]; + Assert( pPixelVar2 ); + + float val[4]; + if (pPixelVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + { + pPixelVar->GetVecValue( val, 3 ); + } + else + { + val[0] = val[1] = val[2] = pPixelVar->GetFloatValue(); + } + + val[3] = pPixelVar2->GetFloatValue(); + val[0] = val[0] > 1.0f ? val[0] : GammaToLinear( val[0] ); + val[1] = val[1] > 1.0f ? val[1] : GammaToLinear( val[1] ); + val[2] = val[2] > 1.0f ? val[2] : GammaToLinear( val[2] ); + + s_pShaderAPI->SetPixelShaderConstant( pixelReg, val ); +} + +void CBaseVSShader::SetPixelShaderConstant_W( int pixelReg, int constantVar, float fWValue ) +{ + Assert( !IsSnapshotting() ); + if ((!s_ppParams) || (constantVar == -1)) + return; + + IMaterialVar* pPixelVar = s_ppParams[constantVar]; + Assert( pPixelVar ); + + float val[4]; + if (pPixelVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + pPixelVar->GetVecValue( val, 4 ); + else + val[0] = val[1] = val[2] = val[3] = pPixelVar->GetFloatValue(); + val[3]=fWValue; + s_pShaderAPI->SetPixelShaderConstant( pixelReg, val ); +} + +void CBaseVSShader::SetPixelShaderConstant( int pixelReg, int constantVar ) +{ + Assert( !IsSnapshotting() ); + if ((!s_ppParams) || (constantVar == -1)) + return; + + IMaterialVar* pPixelVar = s_ppParams[constantVar]; + Assert( pPixelVar ); + + float val[4]; + if (pPixelVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + pPixelVar->GetVecValue( val, 4 ); + else + val[0] = val[1] = val[2] = val[3] = pPixelVar->GetFloatValue(); + s_pShaderAPI->SetPixelShaderConstant( pixelReg, val ); +} + +void CBaseVSShader::SetPixelShaderConstantGammaToLinear( int pixelReg, int constantVar ) +{ + Assert( !IsSnapshotting() ); + if ((!s_ppParams) || (constantVar == -1)) + return; + + IMaterialVar* pPixelVar = s_ppParams[constantVar]; + Assert( pPixelVar ); + + float val[4]; + if (pPixelVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + pPixelVar->GetVecValue( val, 4 ); + else + val[0] = val[1] = val[2] = val[3] = pPixelVar->GetFloatValue(); + + val[0] = val[0] > 1.0f ? val[0] : GammaToLinear( val[0] ); + val[1] = val[1] > 1.0f ? val[1] : GammaToLinear( val[1] ); + val[2] = val[2] > 1.0f ? val[2] : GammaToLinear( val[2] ); + + s_pShaderAPI->SetPixelShaderConstant( pixelReg, val ); +} + +void CBaseVSShader::SetVertexShaderConstantGammaToLinear( int var, float const* pVec, int numConst, bool bForce ) +{ + int i; + for( i = 0; i < numConst; i++ ) + { + float vec[4]; + vec[0] = pVec[i*4+0] > 1.0f ? pVec[i*4+0] : GammaToLinear( pVec[i*4+0] ); + vec[1] = pVec[i*4+1] > 1.0f ? pVec[i*4+1] : GammaToLinear( pVec[i*4+1] ); + vec[2] = pVec[i*4+2] > 1.0f ? pVec[i*4+2] : GammaToLinear( pVec[i*4+2] ); + vec[3] = pVec[i*4+3]; + + s_pShaderAPI->SetVertexShaderConstant( var + i, vec, 1, bForce ); + } +} + +void CBaseVSShader::SetPixelShaderConstantGammaToLinear( int var, float const* pVec, int numConst, bool bForce ) +{ + int i; + for( i = 0; i < numConst; i++ ) + { + float vec[4]; + vec[0] = pVec[i*4+0] > 1.0f ? pVec[i*4+0] : GammaToLinear( pVec[i*4+0] ); + vec[1] = pVec[i*4+1] > 1.0f ? pVec[i*4+1] : GammaToLinear( pVec[i*4+1] ); + vec[2] = pVec[i*4+2] > 1.0f ? pVec[i*4+2] : GammaToLinear( pVec[i*4+2] ); + + vec[3] = pVec[i*4+3]; + + s_pShaderAPI->SetPixelShaderConstant( var + i, vec, 1, bForce ); + } +} + +// GR - special version with fix for const/lerp issue +void CBaseVSShader::SetPixelShaderConstantFudge( int pixelReg, int constantVar ) +{ + Assert( !IsSnapshotting() ); + if ((!s_ppParams) || (constantVar == -1)) + return; + + IMaterialVar* pPixelVar = s_ppParams[constantVar]; + Assert( pPixelVar ); + + float val[4]; + if (pPixelVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + { + pPixelVar->GetVecValue( val, 4 ); + val[0] = val[0] * 0.992f + 0.0078f; + val[1] = val[1] * 0.992f + 0.0078f; + val[2] = val[2] * 0.992f + 0.0078f; + val[3] = val[3] * 0.992f + 0.0078f; + } + else + val[0] = val[1] = val[2] = val[3] = pPixelVar->GetFloatValue() * 0.992f + 0.0078f; + s_pShaderAPI->SetPixelShaderConstant( pixelReg, val ); +} + +void CBaseVSShader::SetVertexShaderConstant( int vertexReg, int constantVar ) +{ + Assert( !IsSnapshotting() ); + if ((!s_ppParams) || (constantVar == -1)) + return; + + IMaterialVar* pVertexVar = s_ppParams[constantVar]; + Assert( pVertexVar ); + + float val[4]; + if (pVertexVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + pVertexVar->GetVecValue( val, 4 ); + else + val[0] = val[1] = val[2] = val[3] = pVertexVar->GetFloatValue(); + s_pShaderAPI->SetVertexShaderConstant( vertexReg, val ); +} + + +//----------------------------------------------------------------------------- +// Sets vertex shader texture transforms +//----------------------------------------------------------------------------- +void CBaseVSShader::SetVertexShaderTextureTranslation( int vertexReg, int translationVar ) +{ + float offset[2] = {0, 0}; + + IMaterialVar* pTranslationVar = s_ppParams[translationVar]; + if (pTranslationVar) + { + if (pTranslationVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + pTranslationVar->GetVecValue( offset, 2 ); + else + offset[0] = offset[1] = pTranslationVar->GetFloatValue(); + } + + Vector4D translation[2]; + translation[0].Init( 1.0f, 0.0f, 0.0f, offset[0] ); + translation[1].Init( 0.0f, 1.0f, 0.0f, offset[1] ); + s_pShaderAPI->SetVertexShaderConstant( vertexReg, translation[0].Base(), 2 ); +} + +void CBaseVSShader::SetVertexShaderTextureScale( int vertexReg, int scaleVar ) +{ + float scale[2] = {1, 1}; + + IMaterialVar* pScaleVar = s_ppParams[scaleVar]; + if (pScaleVar) + { + if (pScaleVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + pScaleVar->GetVecValue( scale, 2 ); + else if (pScaleVar->IsDefined()) + scale[0] = scale[1] = pScaleVar->GetFloatValue(); + } + + Vector4D scaleMatrix[2]; + scaleMatrix[0].Init( scale[0], 0.0f, 0.0f, 0.0f ); + scaleMatrix[1].Init( 0.0f, scale[1], 0.0f, 0.0f ); + s_pShaderAPI->SetVertexShaderConstant( vertexReg, scaleMatrix[0].Base(), 2 ); +} + +void CBaseVSShader::SetVertexShaderTextureTransform( int vertexReg, int transformVar ) +{ + Vector4D transformation[2]; + IMaterialVar* pTransformationVar = s_ppParams[transformVar]; + if (pTransformationVar && (pTransformationVar->GetType() == MATERIAL_VAR_TYPE_MATRIX)) + { + const VMatrix &mat = pTransformationVar->GetMatrixValue(); + transformation[0].Init( mat[0][0], mat[0][1], mat[0][2], mat[0][3] ); + transformation[1].Init( mat[1][0], mat[1][1], mat[1][2], mat[1][3] ); + } + else + { + transformation[0].Init( 1.0f, 0.0f, 0.0f, 0.0f ); + transformation[1].Init( 0.0f, 1.0f, 0.0f, 0.0f ); + } + s_pShaderAPI->SetVertexShaderConstant( vertexReg, transformation[0].Base(), 2 ); +} + +void CBaseVSShader::SetVertexShaderTextureScaledTransform( int vertexReg, int transformVar, int scaleVar ) +{ + Vector4D transformation[2]; + IMaterialVar* pTransformationVar = s_ppParams[transformVar]; + if (pTransformationVar && (pTransformationVar->GetType() == MATERIAL_VAR_TYPE_MATRIX)) + { + const VMatrix &mat = pTransformationVar->GetMatrixValue(); + transformation[0].Init( mat[0][0], mat[0][1], mat[0][2], mat[0][3] ); + transformation[1].Init( mat[1][0], mat[1][1], mat[1][2], mat[1][3] ); + } + else + { + transformation[0].Init( 1.0f, 0.0f, 0.0f, 0.0f ); + transformation[1].Init( 0.0f, 1.0f, 0.0f, 0.0f ); + } + + Vector2D scale( 1, 1 ); + IMaterialVar* pScaleVar = s_ppParams[scaleVar]; + if (pScaleVar) + { + if (pScaleVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + pScaleVar->GetVecValue( scale.Base(), 2 ); + else if (pScaleVar->IsDefined()) + scale[0] = scale[1] = pScaleVar->GetFloatValue(); + } + + // Apply the scaling + transformation[0][0] *= scale[0]; + transformation[0][1] *= scale[1]; + transformation[1][0] *= scale[0]; + transformation[1][1] *= scale[1]; + transformation[0][3] *= scale[0]; + transformation[1][3] *= scale[1]; + s_pShaderAPI->SetVertexShaderConstant( vertexReg, transformation[0].Base(), 2 ); +} + + +//----------------------------------------------------------------------------- +// Sets pixel shader texture transforms +//----------------------------------------------------------------------------- +void CBaseVSShader::SetPixelShaderTextureTranslation( int pixelReg, int translationVar ) +{ + float offset[2] = {0, 0}; + + IMaterialVar* pTranslationVar = s_ppParams[translationVar]; + if (pTranslationVar) + { + if (pTranslationVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + pTranslationVar->GetVecValue( offset, 2 ); + else + offset[0] = offset[1] = pTranslationVar->GetFloatValue(); + } + + Vector4D translation[2]; + translation[0].Init( 1.0f, 0.0f, 0.0f, offset[0] ); + translation[1].Init( 0.0f, 1.0f, 0.0f, offset[1] ); + s_pShaderAPI->SetPixelShaderConstant( pixelReg, translation[0].Base(), 2 ); +} + +void CBaseVSShader::SetPixelShaderTextureScale( int pixelReg, int scaleVar ) +{ + float scale[2] = {1, 1}; + + IMaterialVar* pScaleVar = s_ppParams[scaleVar]; + if (pScaleVar) + { + if (pScaleVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + pScaleVar->GetVecValue( scale, 2 ); + else if (pScaleVar->IsDefined()) + scale[0] = scale[1] = pScaleVar->GetFloatValue(); + } + + Vector4D scaleMatrix[2]; + scaleMatrix[0].Init( scale[0], 0.0f, 0.0f, 0.0f ); + scaleMatrix[1].Init( 0.0f, scale[1], 0.0f, 0.0f ); + s_pShaderAPI->SetPixelShaderConstant( pixelReg, scaleMatrix[0].Base(), 2 ); +} + +void CBaseVSShader::SetPixelShaderTextureTransform( int pixelReg, int transformVar ) +{ + Vector4D transformation[2]; + IMaterialVar* pTransformationVar = s_ppParams[transformVar]; + if (pTransformationVar && (pTransformationVar->GetType() == MATERIAL_VAR_TYPE_MATRIX)) + { + const VMatrix &mat = pTransformationVar->GetMatrixValue(); + transformation[0].Init( mat[0][0], mat[0][1], mat[0][2], mat[0][3] ); + transformation[1].Init( mat[1][0], mat[1][1], mat[1][2], mat[1][3] ); + } + else + { + transformation[0].Init( 1.0f, 0.0f, 0.0f, 0.0f ); + transformation[1].Init( 0.0f, 1.0f, 0.0f, 0.0f ); + } + s_pShaderAPI->SetPixelShaderConstant( pixelReg, transformation[0].Base(), 2 ); +} + +void CBaseVSShader::SetPixelShaderTextureScaledTransform( int pixelReg, int transformVar, int scaleVar ) +{ + Vector4D transformation[2]; + IMaterialVar* pTransformationVar = s_ppParams[transformVar]; + if (pTransformationVar && (pTransformationVar->GetType() == MATERIAL_VAR_TYPE_MATRIX)) + { + const VMatrix &mat = pTransformationVar->GetMatrixValue(); + transformation[0].Init( mat[0][0], mat[0][1], mat[0][2], mat[0][3] ); + transformation[1].Init( mat[1][0], mat[1][1], mat[1][2], mat[1][3] ); + } + else + { + transformation[0].Init( 1.0f, 0.0f, 0.0f, 0.0f ); + transformation[1].Init( 0.0f, 1.0f, 0.0f, 0.0f ); + } + + Vector2D scale( 1, 1 ); + IMaterialVar* pScaleVar = s_ppParams[scaleVar]; + if (pScaleVar) + { + if (pScaleVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + pScaleVar->GetVecValue( scale.Base(), 2 ); + else if (pScaleVar->IsDefined()) + scale[0] = scale[1] = pScaleVar->GetFloatValue(); + } + + // Apply the scaling + transformation[0][0] *= scale[0]; + transformation[0][1] *= scale[1]; + transformation[1][0] *= scale[0]; + transformation[1][1] *= scale[1]; + transformation[0][3] *= scale[0]; + transformation[1][3] *= scale[1]; + s_pShaderAPI->SetPixelShaderConstant( pixelReg, transformation[0].Base(), 2 ); +} + + +//----------------------------------------------------------------------------- +// Moves a matrix into vertex shader constants +//----------------------------------------------------------------------------- +void CBaseVSShader::SetVertexShaderMatrix3x4( int vertexReg, int matrixVar ) +{ + IMaterialVar* pTranslationVar = s_ppParams[matrixVar]; + if (pTranslationVar) + { + s_pShaderAPI->SetVertexShaderConstant( vertexReg, &pTranslationVar->GetMatrixValue( )[0][0], 3 ); + } + else + { + VMatrix matrix; + MatrixSetIdentity( matrix ); + s_pShaderAPI->SetVertexShaderConstant( vertexReg, &matrix[0][0], 3 ); + } +} + +void CBaseVSShader::SetVertexShaderMatrix4x4( int vertexReg, int matrixVar ) +{ + IMaterialVar* pTranslationVar = s_ppParams[matrixVar]; + if (pTranslationVar) + { + s_pShaderAPI->SetVertexShaderConstant( vertexReg, &pTranslationVar->GetMatrixValue( )[0][0], 4 ); + } + else + { + VMatrix matrix; + MatrixSetIdentity( matrix ); + s_pShaderAPI->SetVertexShaderConstant( vertexReg, &matrix[0][0], 4 ); + } +} + + +//----------------------------------------------------------------------------- +// Loads the view matrix into vertex shader constants +//----------------------------------------------------------------------------- +void CBaseVSShader::LoadViewMatrixIntoVertexShaderConstant( int vertexReg ) +{ + VMatrix mat, transpose; + s_pShaderAPI->GetMatrix( MATERIAL_VIEW, mat.m[0] ); + + MatrixTranspose( mat, transpose ); + s_pShaderAPI->SetVertexShaderConstant( vertexReg, transpose.m[0], 3 ); +} + + +//----------------------------------------------------------------------------- +// Loads the projection matrix into pixel shader constants +//----------------------------------------------------------------------------- +void CBaseVSShader::LoadProjectionMatrixIntoVertexShaderConstant( int vertexReg ) +{ + VMatrix mat, transpose; + s_pShaderAPI->GetMatrix( MATERIAL_PROJECTION, mat.m[0] ); + + MatrixTranspose( mat, transpose ); + s_pShaderAPI->SetVertexShaderConstant( vertexReg, transpose.m[0], 4 ); +} + + +//----------------------------------------------------------------------------- +// Loads the model * view matrix into pixel shader constants +//----------------------------------------------------------------------------- +void CBaseVSShader::LoadModelViewMatrixIntoVertexShaderConstant( int vertexReg ) +{ + VMatrix view, model, modelView, transpose; + s_pShaderAPI->GetMatrix( MATERIAL_MODEL, model.m[0] ); + MatrixTranspose( model, model ); + s_pShaderAPI->GetMatrix( MATERIAL_VIEW, view.m[0] ); + MatrixTranspose( view, view ); + + MatrixMultiply( view, model, modelView ); + s_pShaderAPI->SetVertexShaderConstant( vertexReg, modelView.m[0], 3 ); +} + + +//----------------------------------------------------------------------------- +// Loads bump lightmap coordinates into the pixel shader +//----------------------------------------------------------------------------- +void CBaseVSShader::LoadBumpLightmapCoordinateAxes_PixelShader( int pixelReg ) +{ + Vector4D basis[3]; + for (int i = 0; i < 3; ++i) + { + memcpy( &basis[i], &g_localBumpBasis[i], 3 * sizeof(float) ); + basis[i][3] = 0.0f; + } + s_pShaderAPI->SetPixelShaderConstant( pixelReg, (float*)basis, 3 ); +} + + +//----------------------------------------------------------------------------- +// Loads bump lightmap coordinates into the pixel shader +//----------------------------------------------------------------------------- +void CBaseVSShader::LoadBumpLightmapCoordinateAxes_VertexShader( int vertexReg ) +{ + Vector4D basis[3]; + + // transpose + int i; + for (i = 0; i < 3; ++i) + { + basis[i][0] = g_localBumpBasis[0][i]; + basis[i][1] = g_localBumpBasis[1][i]; + basis[i][2] = g_localBumpBasis[2][i]; + basis[i][3] = 0.0f; + } + s_pShaderAPI->SetVertexShaderConstant( vertexReg, (float*)basis, 3 ); + for (i = 0; i < 3; ++i) + { + memcpy( &basis[i], &g_localBumpBasis[i], 3 * sizeof(float) ); + basis[i][3] = 0.0f; + } + s_pShaderAPI->SetVertexShaderConstant( vertexReg + 3, (float*)basis, 3 ); +} + + +//----------------------------------------------------------------------------- +// Helper methods for pixel shader overbrighting +//----------------------------------------------------------------------------- +void CBaseVSShader::EnablePixelShaderOverbright( int reg, bool bEnable, bool bDivideByTwo ) +{ + // can't have other overbright values with pixel shaders as it stands. + float v[4]; + if( bEnable ) + { + v[0] = v[1] = v[2] = v[3] = bDivideByTwo ? OVERBRIGHT / 2.0f : OVERBRIGHT; + } + else + { + v[0] = v[1] = v[2] = v[3] = bDivideByTwo ? 1.0f / 2.0f : 1.0f; + } + s_pShaderAPI->SetPixelShaderConstant( reg, v, 1 ); +} + +//----------------------------------------------------------------------------- +// Converts a color + alpha into a vector4 +//----------------------------------------------------------------------------- +void CBaseVSShader::ColorVarsToVector( int colorVar, int alphaVar, Vector4D &color ) +{ + color.Init( 1.0, 1.0, 1.0, 1.0 ); + if ( colorVar != -1 ) + { + IMaterialVar* pColorVar = s_ppParams[colorVar]; + if ( pColorVar->GetType() == MATERIAL_VAR_TYPE_VECTOR ) + { + pColorVar->GetVecValue( color.Base(), 3 ); + } + else + { + color[0] = color[1] = color[2] = pColorVar->GetFloatValue(); + } + } + if ( alphaVar != -1 ) + { + float flAlpha = s_ppParams[alphaVar]->GetFloatValue(); + color[3] = clamp( flAlpha, 0.0f, 1.0f ); + } +} + +#ifdef _DEBUG +ConVar mat_envmaptintoverride( "mat_envmaptintoverride", "-1" ); +ConVar mat_envmaptintscale( "mat_envmaptintscale", "-1" ); +#endif + +ConVar r_emulategl( "r_emulategl", "0" ); + +//----------------------------------------------------------------------------- +// Helpers for dealing with envmap tint +//----------------------------------------------------------------------------- +// set alphaVar to -1 to ignore it. +void CBaseVSShader::SetEnvMapTintPixelShaderDynamicState( int pixelReg, int tintVar, int alphaVar, bool bConvertFromGammaToLinear ) +{ + float color[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + if( g_pConfig->bShowSpecular && mat_fullbright.GetInt() != 2 ) + { + IMaterialVar* pAlphaVar = NULL; + if( alphaVar >= 0 ) + { + pAlphaVar = s_ppParams[alphaVar]; + } + if( pAlphaVar ) + { + color[3] = pAlphaVar->GetFloatValue(); + } + + IMaterialVar* pTintVar = s_ppParams[tintVar]; +#ifdef _DEBUG + pTintVar->GetVecValue( color, 3 ); + + float envmapTintOverride = mat_envmaptintoverride.GetFloat(); + float envmapTintScaleOverride = mat_envmaptintscale.GetFloat(); + + if( envmapTintOverride != -1.0f ) + { + color[0] = color[1] = color[2] = envmapTintOverride; + } + if( envmapTintScaleOverride != -1.0f ) + { + color[0] *= envmapTintScaleOverride; + color[1] *= envmapTintScaleOverride; + color[2] *= envmapTintScaleOverride; + } + + if( bConvertFromGammaToLinear ) + { + color[0] = color[0] > 1.0f ? color[0] : GammaToLinear( color[0] ); + color[1] = color[1] > 1.0f ? color[1] : GammaToLinear( color[1] ); + color[2] = color[2] > 1.0f ? color[2] : GammaToLinear( color[2] ); + } +#else + if( bConvertFromGammaToLinear ) + { + pTintVar->GetLinearVecValue( color, 3 ); + } + else + { + pTintVar->GetVecValue( color, 3 ); + } +#endif + } + else + { + color[0] = color[1] = color[2] = color[3] = 0.0f; + } + s_pShaderAPI->SetPixelShaderConstant( pixelReg, color, 1 ); +} + + +//----------------------------------------------------------------------------- +// Sets up hw morphing state for the vertex shader +//----------------------------------------------------------------------------- +void CBaseVSShader::SetHWMorphVertexShaderState( int nDimConst, int nSubrectConst, VertexTextureSampler_t morphSampler ) +{ +#ifndef _X360 + if ( !s_pShaderAPI->IsHWMorphingEnabled() ) + return; + + int nMorphWidth, nMorphHeight; + s_pShaderAPI->GetStandardTextureDimensions( &nMorphWidth, &nMorphHeight, TEXTURE_MORPH_ACCUMULATOR ); + + int nDim = s_pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_MORPH_ACCUMULATOR_4TUPLE_COUNT ); + float pMorphAccumSize[4] = { nMorphWidth, nMorphHeight, nDim, 0.0f }; + s_pShaderAPI->SetVertexShaderConstant( nDimConst, pMorphAccumSize ); + + int nXOffset = s_pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_MORPH_ACCUMULATOR_X_OFFSET ); + int nYOffset = s_pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_MORPH_ACCUMULATOR_Y_OFFSET ); + int nWidth = s_pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_MORPH_ACCUMULATOR_SUBRECT_WIDTH ); + int nHeight = s_pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_MORPH_ACCUMULATOR_SUBRECT_HEIGHT ); + float pMorphAccumSubrect[4] = { nXOffset, nYOffset, nWidth, nHeight }; + s_pShaderAPI->SetVertexShaderConstant( nSubrectConst, pMorphAccumSubrect ); + + s_pShaderAPI->BindStandardVertexTexture( morphSampler, TEXTURE_MORPH_ACCUMULATOR ); +#endif +} + + +//----------------------------------------------------------------------------- +// GR - translucency query +//----------------------------------------------------------------------------- +BlendType_t CBaseVSShader::EvaluateBlendRequirements( int textureVar, bool isBaseTexture, + int detailTextureVar ) +{ + // Either we've got a constant modulation + bool isTranslucent = IsAlphaModulating(); + + // Or we've got a vertex alpha + isTranslucent = isTranslucent || (CurrentMaterialVarFlags() & MATERIAL_VAR_VERTEXALPHA); + + // Or we've got a texture alpha (for blending or alpha test) + isTranslucent = isTranslucent || ( TextureIsTranslucent( textureVar, isBaseTexture ) && + !(CurrentMaterialVarFlags() & MATERIAL_VAR_ALPHATEST ) ); + + if ( ( detailTextureVar != -1 ) && ( ! isTranslucent ) ) + { + isTranslucent = TextureIsTranslucent( detailTextureVar, isBaseTexture ); + } + + if ( CurrentMaterialVarFlags() & MATERIAL_VAR_ADDITIVE ) + { + return isTranslucent ? BT_BLENDADD : BT_ADD; // Additive + } + else + { + return isTranslucent ? BT_BLEND : BT_NONE; // Normal blending + } +} + +void CBaseVSShader::SetFlashlightVertexShaderConstants( bool bBump, int bumpTransformVar, bool bDetail, int detailScaleVar, bool bSetTextureTransforms ) +{ + Assert( !IsSnapshotting() ); + + VMatrix worldToTexture; + const FlashlightState_t &flashlightState = s_pShaderAPI->GetFlashlightState( worldToTexture ); + + // Set the flashlight origin + float pos[4]; + pos[0] = flashlightState.m_vecLightOrigin[0]; + pos[1] = flashlightState.m_vecLightOrigin[1]; + pos[2] = flashlightState.m_vecLightOrigin[2]; + pos[3] = 1.0f / ( ( 0.6f * flashlightState.m_FarZ ) - flashlightState.m_FarZ ); // DX8 needs this + + s_pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, pos, 1 ); + + s_pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, worldToTexture.Base(), 4 ); + + // Set the flashlight attenuation factors + float atten[4]; + atten[0] = flashlightState.m_fConstantAtten; + atten[1] = flashlightState.m_fLinearAtten; + atten[2] = flashlightState.m_fQuadraticAtten; + atten[3] = flashlightState.m_FarZAtten; + s_pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_5, atten, 1 ); + + if ( bDetail ) + { + SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_8, BASETEXTURETRANSFORM, detailScaleVar ); + } + + if( bSetTextureTransforms ) + { + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, BASETEXTURETRANSFORM ); + if( !bDetail && bBump && bumpTransformVar != -1 ) + { + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_8, bumpTransformVar ); // aliased on top of detail transform + } + } +} + + +void CBaseVSShader::DrawFlashlight_dx90( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, DrawFlashlight_dx90_Vars_t &vars ) +{ + // FLASHLIGHTFIXME: hack . . need to fix the vertex shader so that it can deal with and without bumps for vertexlitgeneric + if( !vars.m_bLightmappedGeneric ) + { + vars.m_bBump = false; + } + bool bBump2 = vars.m_bWorldVertexTransition && vars.m_bBump && vars.m_nBumpmap2Var != -1 && params[vars.m_nBumpmap2Var]->IsTexture(); + bool bSeamless = vars.m_fSeamlessScale != 0.0; + bool bDetail = vars.m_bLightmappedGeneric && (vars.m_nDetailVar != -1) && params[vars.m_nDetailVar]->IsDefined() && (vars.m_nDetailScale != -1); + + int nDetailBlendMode = 0; + if ( bDetail ) + { + nDetailBlendMode = GetIntParam( vars.m_nDetailTextureCombineMode, params ); + ITexture *pDetailTexture = params[vars.m_nDetailVar]->GetTextureValue(); + if ( pDetailTexture->GetFlags() & TEXTUREFLAGS_SSBUMP ) + { + if ( vars.m_bBump ) + nDetailBlendMode = 10; // ssbump + else + nDetailBlendMode = 11; // ssbump_nobump + } + } + + if( pShaderShadow ) + { + SetInitialShadowState(); + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableAlphaWrites( false ); + + // Alpha blend + SetAdditiveBlendingShadowState( BASETEXTURE, true ); + + // Alpha test + pShaderShadow->EnableAlphaTest( IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) ); + if ( vars.m_nAlphaTestReference != -1 && params[vars.m_nAlphaTestReference]->GetFloatValue() > 0.0f ) + { + pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GEQUAL, params[vars.m_nAlphaTestReference]->GetFloatValue() ); + } + + // Spot sampler + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + // Base sampler + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); + + // Normalizing cubemap sampler + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + + // Normalizing cubemap sampler2 or normal map sampler + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + + // RandomRotation sampler + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); + + // Flashlight depth sampler + pShaderShadow->EnableTexture( SHADER_SAMPLER7, true ); + pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER7 ); + + if( vars.m_bWorldVertexTransition ) + { + // $basetexture2 + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER4, true ); + } + if( bBump2 ) + { + // Normalmap2 sampler + pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); + } + if( bDetail ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER8, true ); // detail sampler + if ( nDetailBlendMode == 1 ) + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER8, true ); + } + + pShaderShadow->EnableSRGBWrite( true ); + + if( vars.m_bLightmappedGeneric ) + { +#ifndef _X360 + if ( g_pHardwareConfig->HasFastVertexTextures() ) + { + DECLARE_STATIC_VERTEX_SHADER( lightmappedgeneric_flashlight_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( WORLDVERTEXTRANSITION, vars.m_bWorldVertexTransition ); + SET_STATIC_VERTEX_SHADER_COMBO( NORMALMAP, vars.m_bBump ); + SET_STATIC_VERTEX_SHADER_COMBO( SEAMLESS, bSeamless ); + SET_STATIC_VERTEX_SHADER_COMBO( DETAIL, bDetail ); + SET_STATIC_VERTEX_SHADER( lightmappedgeneric_flashlight_vs30 ); + } + else +#endif + { + DECLARE_STATIC_VERTEX_SHADER( lightmappedgeneric_flashlight_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( WORLDVERTEXTRANSITION, vars.m_bWorldVertexTransition ); + SET_STATIC_VERTEX_SHADER_COMBO( NORMALMAP, vars.m_bBump ); + SET_STATIC_VERTEX_SHADER_COMBO( SEAMLESS, bSeamless ); + SET_STATIC_VERTEX_SHADER_COMBO( DETAIL, bDetail ); + SET_STATIC_VERTEX_SHADER( lightmappedgeneric_flashlight_vs20 ); + } + + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL; + if( vars.m_bBump ) + { + flags |= VERTEX_TANGENT_S | VERTEX_TANGENT_T; + } + int numTexCoords = 1; + if( vars.m_bWorldVertexTransition ) + { + flags |= VERTEX_COLOR; + numTexCoords = 2; // need lightmap texcoords to get alpha. + } + pShaderShadow->VertexShaderVertexFormat( flags, numTexCoords, 0, 0 ); + } + else + { + + // Need a 3.0 vs here? + + DECLARE_STATIC_VERTEX_SHADER( vertexlitgeneric_flashlight_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( TEETH, vars.m_bTeeth ); + SET_STATIC_VERTEX_SHADER( vertexlitgeneric_flashlight_vs20 ); + + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL; + int numTexCoords = 1; + pShaderShadow->VertexShaderVertexFormat( flags, numTexCoords, 0, vars.m_bBump ? 4 : 0 ); + } + + int nBumpMapVariant = 0; + if ( vars.m_bBump ) + { + nBumpMapVariant = ( vars.m_bSSBump ) ? 2 : 1; + } + +#ifndef _X360 + if ( g_pHardwareConfig->HasFastVertexTextures() ) + { + int nShadowFilterMode = g_pHardwareConfig->GetShadowFilterMode(); + + DECLARE_STATIC_PIXEL_SHADER( flashlight_ps30 ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMALMAP, nBumpMapVariant ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMALMAP2, bBump2 ); + SET_STATIC_PIXEL_SHADER_COMBO( WORLDVERTEXTRANSITION, vars.m_bWorldVertexTransition ); + SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS, bSeamless ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, bDetail ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER( flashlight_ps30 ); + } + else +#endif + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + int nShadowFilterMode = g_pHardwareConfig->GetShadowFilterMode(); + + DECLARE_STATIC_PIXEL_SHADER( flashlight_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMALMAP, nBumpMapVariant ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMALMAP2, bBump2 ); + SET_STATIC_PIXEL_SHADER_COMBO( WORLDVERTEXTRANSITION, vars.m_bWorldVertexTransition ); + SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS, bSeamless ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, bDetail ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER( flashlight_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( flashlight_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMALMAP, nBumpMapVariant ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMALMAP2, bBump2 ); + SET_STATIC_PIXEL_SHADER_COMBO( WORLDVERTEXTRANSITION, vars.m_bWorldVertexTransition ); + SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS, bSeamless ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, bDetail ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode ); + SET_STATIC_PIXEL_SHADER( flashlight_ps20 ); + } + FogToBlack(); + + PI_BeginCommandBuffer(); + PI_SetModulationPixelShaderDynamicState( PSREG_DIFFUSE_MODULATION ); + PI_EndCommandBuffer(); + } + else + { + VMatrix worldToTexture; + ITexture *pFlashlightDepthTexture; + FlashlightState_t flashlightState = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture ); + + SetFlashLightColorFromState( flashlightState, pShaderAPI, false ); + + BindTexture( SHADER_SAMPLER0, flashlightState.m_pSpotlightTexture, flashlightState.m_nSpotlightTextureFrame ); + + pShaderAPI->BindStandardTexture( SHADER_SAMPLER5, TEXTURE_SHADOW_NOISE_2D ); + if( pFlashlightDepthTexture && g_pConfig->ShadowDepthTexture() && flashlightState.m_bEnableShadows ) + { + BindTexture( SHADER_SAMPLER7, pFlashlightDepthTexture, 0 ); + + // Tweaks associated with a given flashlight + float tweaks[4]; + tweaks[0] = ShadowFilterFromState( flashlightState ); + tweaks[1] = ShadowAttenFromState( flashlightState ); + HashShadow2DJitter( flashlightState.m_flShadowJitterSeed, &tweaks[2], &tweaks[3] ); + pShaderAPI->SetPixelShaderConstant( PSREG_ENVMAP_TINT__SHADOW_TWEAKS, tweaks, 1 ); + + // Dimensions of screen, used for screen-space noise map sampling + float vScreenScale[4] = {1280.0f / 32.0f, 720.0f / 32.0f, 0, 0}; + int nWidth, nHeight; + pShaderAPI->GetBackBufferDimensions( nWidth, nHeight ); + + int nTexWidth, nTexHeight; + pShaderAPI->GetStandardTextureDimensions( &nTexWidth, &nTexHeight, TEXTURE_SHADOW_NOISE_2D ); + + vScreenScale[0] = (float) nWidth / nTexWidth; + vScreenScale[1] = (float) nHeight / nTexHeight; + + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_SCREEN_SCALE, vScreenScale, 1 ); + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER7, TEXTURE_WHITE ); + } + + if( params[BASETEXTURE]->IsTexture() && mat_fullbright.GetInt() != 2 ) + { + BindTexture( SHADER_SAMPLER1, BASETEXTURE, FRAME ); + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_GREY ); + } + if( vars.m_bWorldVertexTransition ) + { + Assert( vars.m_nBaseTexture2Var >= 0 && vars.m_nBaseTexture2FrameVar >= 0 ); + BindTexture( SHADER_SAMPLER4, vars.m_nBaseTexture2Var, vars.m_nBaseTexture2FrameVar ); + } + pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_NORMALIZATION_CUBEMAP ); + if( vars.m_bBump ) + { + BindTexture( SHADER_SAMPLER3, vars.m_nBumpmapVar, vars.m_nBumpmapFrame ); + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER3, TEXTURE_NORMALIZATION_CUBEMAP ); + } + + if( bDetail ) + { + BindTexture( SHADER_SAMPLER8, vars.m_nDetailVar ); + } + + if( vars.m_bWorldVertexTransition ) + { + if( bBump2 ) + { + BindTexture( SHADER_SAMPLER6, vars.m_nBumpmap2Var, vars.m_nBumpmap2Frame ); + } + } + + if( vars.m_bLightmappedGeneric ) + { +#ifndef _X360 + if ( g_pHardwareConfig->HasFastVertexTextures() ) + { + DECLARE_DYNAMIC_VERTEX_SHADER( lightmappedgeneric_flashlight_vs30 ); + SET_DYNAMIC_VERTEX_SHADER( lightmappedgeneric_flashlight_vs30 ); + } + else +#endif + { + DECLARE_DYNAMIC_VERTEX_SHADER( lightmappedgeneric_flashlight_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( lightmappedgeneric_flashlight_vs20 ); + } + + if ( bSeamless ) + { + float const0[4]={ vars.m_fSeamlessScale,0,0,0}; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, const0 ); + } + + if ( bDetail ) + { + float vDetailConstants[4] = {1,1,1,1}; + + if ( vars.m_nDetailTint != -1 ) + { + params[vars.m_nDetailTint]->GetVecValue( vDetailConstants, 3 ); + } + + if ( vars.m_nDetailTextureBlendFactor != -1 ) + { + vDetailConstants[3] = params[vars.m_nDetailTextureBlendFactor]->GetFloatValue(); + } + + pShaderAPI->SetPixelShaderConstant( 0, vDetailConstants, 1 ); + } + } + else + { + DECLARE_DYNAMIC_VERTEX_SHADER( vertexlitgeneric_flashlight_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER( vertexlitgeneric_flashlight_vs20 ); + + if( vars.m_bTeeth ) + { + Assert( vars.m_nTeethForwardVar >= 0 ); + Assert( vars.m_nTeethIllumFactorVar >= 0 ); + Vector4D lighting; + params[vars.m_nTeethForwardVar]->GetVecValue( lighting.Base(), 3 ); + lighting[3] = params[vars.m_nTeethIllumFactorVar]->GetFloatValue(); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, lighting.Base() ); + } + } + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + float vEyePos_SpecExponent[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + vEyePos_SpecExponent[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + +#ifndef _X360 + if ( g_pHardwareConfig->HasFastVertexTextures() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( flashlight_ps30 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, flashlightState.m_bEnableShadows ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( UBERLIGHT, flashlightState.m_bUberlight ); + SET_DYNAMIC_PIXEL_SHADER( flashlight_ps30 ); + + SetupUberlightFromState( pShaderAPI, flashlightState ); + } + else +#endif + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( flashlight_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, flashlightState.m_bEnableShadows ); + SET_DYNAMIC_PIXEL_SHADER( flashlight_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( flashlight_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( flashlight_ps20 ); + } + + float atten[4]; // Set the flashlight attenuation factors + atten[0] = flashlightState.m_fConstantAtten; + atten[1] = flashlightState.m_fLinearAtten; + atten[2] = flashlightState.m_fQuadraticAtten; + atten[3] = flashlightState.m_FarZAtten; + s_pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_ATTENUATION, atten, 1 ); + + float pos[4]; // Set the flashlight origin + pos[0] = flashlightState.m_vecLightOrigin[0]; + pos[1] = flashlightState.m_vecLightOrigin[1]; + pos[2] = flashlightState.m_vecLightOrigin[2]; + pos[3] = flashlightState.m_FarZ; + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_POSITION_RIM_BOOST, pos, 1 ); // rim boost not really used here + + SetFlashlightVertexShaderConstants( vars.m_bBump, vars.m_nBumpTransform, bDetail, vars.m_nDetailScale, bSeamless ? false : true ); + } + Draw(); +} + +// Take 0..1 seed and map to (u, v) coordinate to be used in shadow filter jittering... +void CBaseVSShader::HashShadow2DJitter( const float fJitterSeed, float *fU, float* fV ) +{ + int nTexWidth, nTexHeight; + s_pShaderAPI->GetStandardTextureDimensions( &nTexWidth, &nTexHeight, TEXTURE_SHADOW_NOISE_2D ); + + int nSeed = fmod (fJitterSeed, 1.0f) * nTexWidth * nTexHeight; + + int nRow = nSeed / nTexHeight; + int nCol = nSeed % nTexWidth; + + // Div and mod to get an individual texel in the fTexRes x fTexRes grid + *fU = nRow / (float) nTexHeight; // Row + *fV = nCol / (float) nTexWidth; // Column +} + +#endif // !_STATIC_LINKED || STDSHADER_DX8_DLL_EXPORT + + + +void CBaseVSShader::DrawEqualDepthToDestAlpha( void ) +{ +#ifdef STDSHADER_DX9_DLL_EXPORT + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + bool bMakeActualDrawCall = false; + if( s_pShaderShadow ) + { + s_pShaderShadow->EnableColorWrites( false ); + s_pShaderShadow->EnableAlphaWrites( true ); + s_pShaderShadow->EnableDepthWrites( false ); + s_pShaderShadow->EnableAlphaTest( false ); + s_pShaderShadow->EnableBlending( false ); + + s_pShaderShadow->DepthFunc( SHADER_DEPTHFUNC_EQUAL ); + + s_pShaderShadow->SetVertexShader( "depthtodestalpha_vs20", 0 ); + s_pShaderShadow->SetPixelShader( "depthtodestalpha_ps20b", 0 ); + } + if( s_pShaderAPI ) + { + s_pShaderAPI->SetVertexShaderIndex( 0 ); + s_pShaderAPI->SetPixelShaderIndex( 0 ); + + bMakeActualDrawCall = s_pShaderAPI->ShouldWriteDepthToDestAlpha(); + } + Draw( bMakeActualDrawCall ); + } +#else + Assert( 0 ); //probably just needs a shader update to the latest +#endif +} + + +//----------------------------------------------------------------------------- +bool ToolsEnabled() +{ + static bool bToolsMode = ( CommandLine()->CheckParm( "-tools" ) != NULL ); + return bToolsMode; +} diff --git a/materialsystem/stdshaders/BaseVSShader.h b/materialsystem/stdshaders/BaseVSShader.h new file mode 100644 index 00000000..27d47d4f --- /dev/null +++ b/materialsystem/stdshaders/BaseVSShader.h @@ -0,0 +1,372 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $NoKeywords: $ +// This is what all vs/ps (dx8+) shaders inherit from. +//===========================================================================// + +#ifndef BASEVSSHADER_H +#define BASEVSSHADER_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "cpp_shader_constant_register_map.h" +#include "shaderlib/cshader.h" +#include "shaderlib/baseshader.h" +#include "ConVar.h" +#include + + +//----------------------------------------------------------------------------- +// Helper macro for vertex shaders +//----------------------------------------------------------------------------- +#define BEGIN_VS_SHADER_FLAGS(_name, _help, _flags) __BEGIN_SHADER_INTERNAL( CBaseVSShader, _name, _help, _flags ) +#define BEGIN_VS_SHADER(_name,_help) __BEGIN_SHADER_INTERNAL( CBaseVSShader, _name, _help, 0 ) + + +// useful parameter initialization macro +#define INIT_FLOAT_PARM( parm, value ) \ + if ( !params[(parm)]->IsDefined() ) \ + { \ + params[(parm)]->SetFloatValue( (value) ); \ + } + +// useful pixel shader declaration macro for ps20/20b c++ code +#define SET_STATIC_PS2X_PIXEL_SHADER_NO_COMBOS( basename ) \ + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) \ + { \ + DECLARE_STATIC_PIXEL_SHADER( basename##_ps20b ); \ + SET_STATIC_PIXEL_SHADER( basename##_ps20b ); \ + } \ + else \ + { \ + DECLARE_STATIC_PIXEL_SHADER( basename##_ps20 ); \ + SET_STATIC_PIXEL_SHADER( basename##_ps20 ); \ + } + +#define SET_DYNAMIC_PS2X_PIXEL_SHADER_NO_COMBOS( basename ) \ + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) \ + { \ + DECLARE_DYNAMIC_PIXEL_SHADER( basename##_ps20b ); \ + SET_DYNAMIC_PIXEL_SHADER( basename##_ps20b ); \ + } \ + else \ + { \ + DECLARE_DYNAMIC_PIXEL_SHADER( basename##_ps20 ); \ + SET_DYNAMIC_PIXEL_SHADER( basename##_ps20 ); \ + } + + +//----------------------------------------------------------------------------- +// Base class for shaders, contains helper methods. +//----------------------------------------------------------------------------- +class CBaseVSShader : public CBaseShader +{ +public: + // Loads bump lightmap coordinates into the pixel shader + void LoadBumpLightmapCoordinateAxes_PixelShader( int pixelReg ); + + // Loads bump lightmap coordinates into the vertex shader + void LoadBumpLightmapCoordinateAxes_VertexShader( int vertexReg ); + + // Pixel and vertex shader constants.... + void SetPixelShaderConstant( int pixelReg, int constantVar ); + + // Pixel and vertex shader constants.... + void SetPixelShaderConstantGammaToLinear( int pixelReg, int constantVar ); + + // This version will put constantVar into x,y,z, and constantVar2 into the w + void SetPixelShaderConstant( int pixelReg, int constantVar, int constantVar2 ); + void SetPixelShaderConstantGammaToLinear( int pixelReg, int constantVar, int constantVar2 ); + + // Helpers for setting constants that need to be converted to linear space (from gamma space). + void SetVertexShaderConstantGammaToLinear( int var, float const* pVec, int numConst = 1, bool bForce = false ); + void SetPixelShaderConstantGammaToLinear( int var, float const* pVec, int numConst = 1, bool bForce = false ); + + void SetVertexShaderConstant( int vertexReg, int constantVar ); + + // set rgb components of constant from a color parm and give an explicit w value + void SetPixelShaderConstant_W( int pixelReg, int constantVar, float fWValue ); + + // GR - fix for const/lerp issues + void SetPixelShaderConstantFudge( int pixelReg, int constantVar ); + + // Sets vertex shader texture transforms + void SetVertexShaderTextureTranslation( int vertexReg, int translationVar ); + void SetVertexShaderTextureScale( int vertexReg, int scaleVar ); + void SetVertexShaderTextureTransform( int vertexReg, int transformVar ); + void SetVertexShaderTextureScaledTransform( int vertexReg, + int transformVar, int scaleVar ); + + // Set pixel shader texture transforms + void SetPixelShaderTextureTranslation( int pixelReg, int translationVar ); + void SetPixelShaderTextureScale( int pixelReg, int scaleVar ); + void SetPixelShaderTextureTransform( int pixelReg, int transformVar ); + void SetPixelShaderTextureScaledTransform( int pixelReg, + int transformVar, int scaleVar ); + + // Moves a matrix into vertex shader constants + void SetVertexShaderMatrix3x4( int vertexReg, int matrixVar ); + void SetVertexShaderMatrix4x4( int vertexReg, int matrixVar ); + + // Loads the view matrix into vertex shader constants + void LoadViewMatrixIntoVertexShaderConstant( int vertexReg ); + + // Loads the projection matrix into vertex shader constants + void LoadProjectionMatrixIntoVertexShaderConstant( int vertexReg ); + + // Loads the model->view matrix into vertex shader constants + void LoadModelViewMatrixIntoVertexShaderConstant( int vertexReg ); + + // Helpers for dealing with envmaptint + void SetEnvMapTintPixelShaderDynamicState( int pixelReg, int tintVar, int alphaVar, bool bConvertFromGammaToLinear = false ); + + // Helper methods for pixel shader overbrighting + void EnablePixelShaderOverbright( int reg, bool bEnable, bool bDivideByTwo ); + + // Sets up hw morphing state for the vertex shader + void SetHWMorphVertexShaderState( int nDimConst, int nSubrectConst, VertexTextureSampler_t morphSampler ); + + BlendType_t EvaluateBlendRequirements( int textureVar, bool isBaseTexture, int detailTextureVar = -1 ); + + // Helper for setting up flashlight constants + void SetFlashlightVertexShaderConstants( bool bBump, int bumpTransformVar, bool bDetail, int detailScaleVar, bool bSetTextureTransforms ); + + struct DrawFlashlight_dx90_Vars_t + { + DrawFlashlight_dx90_Vars_t() + { + // set all ints to -1 + memset( this, 0xFF, sizeof(DrawFlashlight_dx90_Vars_t) ); + // set all bools to a default value. + m_bBump = false; + m_bLightmappedGeneric = false; + m_bWorldVertexTransition = false; + m_bTeeth = false; + m_bSSBump = false; + m_fSeamlessScale = 0.0; + } + bool m_bBump; + bool m_bLightmappedGeneric; + bool m_bWorldVertexTransition; + bool m_bTeeth; + int m_nBumpmapVar; + int m_nBumpmapFrame; + int m_nBumpTransform; + int m_nFlashlightTextureVar; + int m_nFlashlightTextureFrameVar; + int m_nBaseTexture2Var; + int m_nBaseTexture2FrameVar; + int m_nBumpmap2Var; + int m_nBumpmap2Frame; + int m_nBump2Transform; + int m_nDetailVar; + int m_nDetailScale; + int m_nDetailTextureCombineMode; + int m_nDetailTextureBlendFactor; + int m_nDetailTint; + int m_nTeethForwardVar; + int m_nTeethIllumFactorVar; + int m_nAlphaTestReference; + bool m_bSSBump; + float m_fSeamlessScale; // 0.0 = not seamless + }; + void DrawFlashlight_dx90( IMaterialVar** params, + IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, DrawFlashlight_dx90_Vars_t &vars ); + + void HashShadow2DJitter( const float fJitterSeed, float *fU, float* fV ); + + //Alpha tested materials can end up leaving garbage in the dest alpha buffer if they write depth. + //This pass fills in the areas that passed the alpha test with depth in dest alpha + //by writing only equal depth pixels and only if we should be writing depth to dest alpha + void DrawEqualDepthToDestAlpha( void ); + +private: + // Converts a color + alpha into a vector4 + void ColorVarsToVector( int colorVar, int alphaVar, Vector4D &color ); +}; + +FORCEINLINE char * GetFlashlightTextureFilename() +{ + //if ( !IsX360() && ( g_pHardwareConfig->SupportsBorderColor() ) ) + //{ + // return "effects/flashlight001_border"; + //} + //else + { + return "effects/flashlight001"; + } +} + +extern ConVar r_flashlightbrightness; + +FORCEINLINE void SetFlashLightColorFromState( FlashlightState_t const &state, IShaderDynamicAPI *pShaderAPI, bool bSinglePassFlashlight, int nPSRegister=28, bool bFlashlightNoLambert=false ) +{ + // Old code + //float flToneMapScale = ( pShaderAPI->GetToneMappingScaleLinear() ).x; + //float flFlashlightScale = 1.0f / flToneMapScale; + + // Fix to old code to keep flashlight from ever getting brighter than 1.0 + //float flToneMapScale = ( pShaderAPI->GetToneMappingScaleLinear() ).x; + //if ( flToneMapScale < 1.0f ) + // flToneMapScale = 1.0f; + //float flFlashlightScale = 1.0f / flToneMapScale; + + float flFlashlightScale = r_flashlightbrightness.GetFloat(); + + if ( !g_pHardwareConfig->GetHDREnabled() ) + { + // Non-HDR path requires 2.0 flashlight + flFlashlightScale = 2.0f; + } + + // DX10 hardware and single pass flashlight require a hack scalar since the flashlight is added in linear space + if ( ( g_pHardwareConfig->UsesSRGBCorrectBlending() ) || ( bSinglePassFlashlight ) ) + { + flFlashlightScale *= 2.5f; // Magic number that works well on the 360 and NVIDIA 8800 + } + + flFlashlightScale *= state.m_fBrightnessScale; + + // Generate pixel shader constant + float const *pFlashlightColor = state.m_Color; + float vPsConst[4] = { flFlashlightScale * pFlashlightColor[0], flFlashlightScale * pFlashlightColor[1], flFlashlightScale * pFlashlightColor[2], pFlashlightColor[3] }; + vPsConst[3] = bFlashlightNoLambert ? 2.0f : 0.0f; // This will be added to N.L before saturate to force a 1.0 N.L term + + // Red flashlight for testing + //vPsConst[0] = 0.5f; vPsConst[1] = 0.0f; vPsConst[2] = 0.0f; + + pShaderAPI->SetPixelShaderConstant( nPSRegister, ( float * )vPsConst ); +} + +FORCEINLINE float ShadowAttenFromState( FlashlightState_t const &state ) +{ + // DX10 requires some hackery due to sRGB/blend ordering change from DX9, which makes the shadows too light + if ( g_pHardwareConfig->UsesSRGBCorrectBlending() ) + return state.m_flShadowAtten * 0.1f; // magic number + + return state.m_flShadowAtten; +} + +FORCEINLINE float ShadowFilterFromState( FlashlightState_t const &state ) +{ + // We developed shadow maps at 1024, so we expect the penumbra size to have been tuned relative to that + return state.m_flShadowFilterSize / 1024.0f; +} + + +FORCEINLINE void SetupUberlightFromState( IShaderDynamicAPI *pShaderAPI, FlashlightState_t const &state ) +{ + // Bail if we can't do ps30 or we don't even want an uberlight + if ( !g_pHardwareConfig->HasFastVertexTextures() || !state.m_bUberlight || !pShaderAPI ) + return; + + UberlightState_t u = state.m_uberlightState; + + // Set uberlight shader parameters as function of user controls from UberlightState_t + Vector4D vSmoothEdge0 = Vector4D( 0.0f, u.m_fCutOn - u.m_fNearEdge, u.m_fCutOff, 0.0f ); + Vector4D vSmoothEdge1 = Vector4D( 0.0f, u.m_fCutOn, u.m_fCutOff + u.m_fFarEdge, 0.0f ); + Vector4D vSmoothOneOverW = Vector4D( 0.0f, 1.0f / u.m_fNearEdge, 1.0f / u.m_fFarEdge, 0.0f ); + Vector4D vShearRound = Vector4D( u.m_fShearx, u.m_fSheary, 2.0f / u.m_fRoundness, -u.m_fRoundness / 2.0f ); + Vector4D vaAbB = Vector4D( u.m_fWidth, u.m_fWidth + u.m_fWedge, u.m_fHeight, u.m_fHeight + u.m_fHedge ); + + pShaderAPI->SetPixelShaderConstant( PSREG_UBERLIGHT_SMOOTH_EDGE_0, vSmoothEdge0.Base(), 1 ); + pShaderAPI->SetPixelShaderConstant( PSREG_UBERLIGHT_SMOOTH_EDGE_1, vSmoothEdge1.Base(), 1 ); + pShaderAPI->SetPixelShaderConstant( PSREG_UBERLIGHT_SMOOTH_EDGE_OOW, vSmoothOneOverW.Base(), 1 ); + pShaderAPI->SetPixelShaderConstant( PSREG_UBERLIGHT_SHEAR_ROUND, vShearRound.Base(), 1 ); + pShaderAPI->SetPixelShaderConstant( PSREG_UBERLIGHT_AABB, vaAbB.Base(), 1 ); + + QAngle angles; + QuaternionAngles( state.m_quatOrientation, angles ); + + // World to Light's View matrix + matrix3x4_t viewMatrix, viewMatrixInverse; + AngleMatrix( angles, state.m_vecLightOrigin, viewMatrixInverse ); + MatrixInvert( viewMatrixInverse, viewMatrix ); + pShaderAPI->SetPixelShaderConstant( PSREG_UBERLIGHT_WORLD_TO_LIGHT, viewMatrix.Base(), 4 ); +} + + +// convenient material variable access functions for helpers to use. +FORCEINLINE bool IsTextureSet( int nVar, IMaterialVar **params ) +{ + return ( nVar != -1 ) && ( params[nVar]->IsTexture() ); +} + +FORCEINLINE bool IsBoolSet( int nVar, IMaterialVar **params ) +{ + return ( nVar != -1 ) && ( params[nVar]->GetIntValue() ); +} + +FORCEINLINE int GetIntParam( int nVar, IMaterialVar **params, int nDefaultValue = 0 ) +{ + return ( nVar != -1 ) ? ( params[nVar]->GetIntValue() ) : nDefaultValue; +} + +FORCEINLINE float GetFloatParam( int nVar, IMaterialVar **params, float flDefaultValue = 0.0 ) +{ + return ( nVar != -1 ) ? ( params[nVar]->GetFloatValue() ) : flDefaultValue; +} + +FORCEINLINE void InitFloatParam( int nIndex, IMaterialVar **params, float flValue ) +{ + if ( (nIndex != -1) && !params[nIndex]->IsDefined() ) + { + params[nIndex]->SetFloatValue( flValue ); + } +} + +FORCEINLINE void InitIntParam( int nIndex, IMaterialVar **params, int nValue ) +{ + if ( (nIndex != -1) && !params[nIndex]->IsDefined() ) + { + params[nIndex]->SetIntValue( nValue ); + } +} + +FORCEINLINE void InitVecParam( int nIndex, IMaterialVar **params, float x, float y ) +{ + if ( (nIndex != -1) && !params[nIndex]->IsDefined() ) + { + params[nIndex]->SetVecValue( x, y ); + } +} + +FORCEINLINE void InitVecParam( int nIndex, IMaterialVar **params, float x, float y, float z ) +{ + if ( (nIndex != -1) && !params[nIndex]->IsDefined() ) + { + params[nIndex]->SetVecValue( x, y, z ); + } +} + +FORCEINLINE void InitVecParam( int nIndex, IMaterialVar **params, float x, float y, float z, float w ) +{ + if ( (nIndex != -1) && !params[nIndex]->IsDefined() ) + { + params[nIndex]->SetVecValue( x, y, z, w ); + } +} + +// Did we launch with -tools +bool ToolsEnabled(); + +class ConVar; + +#ifdef _DEBUG +extern ConVar mat_envmaptintoverride; +extern ConVar mat_envmaptintscale; +#endif + + +extern ConVar r_emulategl; + +FORCEINLINE bool IsOpenGL( void ) +{ + return IsPosix() || r_emulategl.GetBool(); +} + +#endif // BASEVSSHADER_H diff --git a/materialsystem/stdshaders/Bloom.cpp b/materialsystem/stdshaders/Bloom.cpp new file mode 100644 index 00000000..3174a3cc --- /dev/null +++ b/materialsystem/stdshaders/Bloom.cpp @@ -0,0 +1,88 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" + +#include "screenspaceeffect_vs20.inc" +#include "bloom_ps20.inc" +#include "bloom_ps20b.inc" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +BEGIN_VS_SHADER_FLAGS( Bloom, "Help for Bloom", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( FBTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "_rt_FullFrameFB", "" ) + SHADER_PARAM( BLURTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "_rt_SmallHDR0", "" ) + END_SHADER_PARAMS + + SHADER_INIT + { + if( params[FBTEXTURE]->IsDefined() ) + { + LoadTexture( FBTEXTURE ); + } + if( params[BLURTEXTURE]->IsDefined() ) + { + LoadTexture( BLURTEXTURE ); + } + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + int fmt = VERTEX_POSITION; + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 ); + + // Pre-cache shaders + DECLARE_STATIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + SET_STATIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( bloom_ps20b ); + SET_STATIC_PIXEL_SHADER( bloom_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( bloom_ps20 ); + SET_STATIC_PIXEL_SHADER( bloom_ps20 ); + } + } + + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, FBTEXTURE, -1 ); + BindTexture( SHADER_SAMPLER1, BLURTEXTURE, -1 ); + DECLARE_DYNAMIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( bloom_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( bloom_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( bloom_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( bloom_ps20 ); + } + } + Draw(); + } +END_SHADER diff --git a/materialsystem/stdshaders/Bloom_ps2x.fxc b/materialsystem/stdshaders/Bloom_ps2x.fxc new file mode 100644 index 00000000..a2f8b39f --- /dev/null +++ b/materialsystem/stdshaders/Bloom_ps2x.fxc @@ -0,0 +1,19 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#include "common_ps_fxc.h" + +sampler FBSampler : register( s0 ); +sampler BlurSampler : register( s1 ); + +struct PS_INPUT +{ + float2 texCoord : TEXCOORD0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float4 fbSample = tex2D( FBSampler, i.texCoord ); + float4 blurSample = tex2D( BlurSampler, i.texCoord ); + + return FinalOutput( float4( fbSample + blurSample.rgb * blurSample.a * MAX_HDR_OVERBRIGHT, 1.0f ), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} \ No newline at end of file diff --git a/materialsystem/stdshaders/BlurFilterX.cpp b/materialsystem/stdshaders/BlurFilterX.cpp new file mode 100644 index 00000000..bab9b0b8 --- /dev/null +++ b/materialsystem/stdshaders/BlurFilterX.cpp @@ -0,0 +1,131 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" +#include "blurfilter_vs20.inc" +#include "blurfilter_ps20.inc" +#include "blurfilter_ps20b.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_VS_SHADER_FLAGS( BlurFilterX, "Help for BlurFilterX", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( KERNEL, SHADER_PARAM_TYPE_INTEGER, "0", "Kernel type" ) + END_SHADER_PARAMS + + SHADER_INIT + { + if( params[BASETEXTURE]->IsDefined() ) + { + LoadTexture( BASETEXTURE ); + } + + if ( !( params[ KERNEL ]->IsDefined() ) ) + { + params[ KERNEL ]->SetIntValue( 0 ); + } + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableAlphaWrites( true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 1, 0, 0 ); + + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, false ); + pShaderShadow->EnableSRGBWrite( false ); + + DECLARE_STATIC_VERTEX_SHADER( blurfilter_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( KERNEL, params[ KERNEL ]->GetIntValue() ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER( blurfilter_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( blurfilter_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( KERNEL, params[ KERNEL ]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER_COMBO( CLEAR_COLOR, false ); + SET_STATIC_PIXEL_SHADER( blurfilter_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( blurfilter_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( KERNEL, params[ KERNEL ]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER_COMBO( CLEAR_COLOR, false ); + SET_STATIC_PIXEL_SHADER( blurfilter_ps20 ); + } + + if ( IS_FLAG_SET( MATERIAL_VAR_ADDITIVE ) ) + EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); + } + + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, -1 ); + + float v[4]; + + // The temp buffer is 1/4 back buffer size + ITexture *src_texture = params[BASETEXTURE]->GetTextureValue(); + int width = src_texture->GetActualWidth(); + float dX = 1.0f / width; + + // Tap offsets + v[0] = 1.3366f * dX; + v[1] = 0.0f; + v[2] = 0; + v[3] = 0; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, v, 1 ); + v[0] = 3.4295f * dX; + v[1] = 0.0f; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, v, 1 ); + v[0] = 5.4264f * dX; + v[1] = 0.0f; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, v, 1 ); + + v[0] = 7.4359f * dX; + v[1] = 0.0f; + pShaderAPI->SetPixelShaderConstant( 0, v, 1 ); + v[0] = 9.4436f * dX; + v[1] = 0.0f; + pShaderAPI->SetPixelShaderConstant( 1, v, 1 ); + v[0] = 11.4401f * dX; + v[1] = 0.0f; + pShaderAPI->SetPixelShaderConstant( 2, v, 1 ); + + v[0] = v[1] = v[2] = v[3] = 1.0; + pShaderAPI->SetPixelShaderConstant( 3, v, 1 ); + + v[0] = v[1] = v[2] = v[3] = 0.0; + v[0] = dX; + pShaderAPI->SetPixelShaderConstant( 4, v, 1 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( blurfilter_ps20 ); + SET_DYNAMIC_VERTEX_SHADER( blurfilter_ps20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( blurfilter_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( blurfilter_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( blurfilter_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( blurfilter_ps20 ); + } + } + Draw(); + } +END_SHADER diff --git a/materialsystem/stdshaders/BlurFilterY.cpp b/materialsystem/stdshaders/BlurFilterY.cpp new file mode 100644 index 00000000..a73a19a0 --- /dev/null +++ b/materialsystem/stdshaders/BlurFilterY.cpp @@ -0,0 +1,154 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +//===========================================================================// + +#include "BaseVSShader.h" +#include "blurfilter_vs20.inc" +#include "blurfilter_ps20.inc" +#include "blurfilter_ps20b.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_VS_SHADER_FLAGS( BlurFilterY, "Help for BlurFilterY", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( BLOOMAMOUNT, SHADER_PARAM_TYPE_FLOAT, "1.0", "" ) + SHADER_PARAM( FRAMETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "_rt_SmallHDR0", "" ) + SHADER_PARAM( KERNEL, SHADER_PARAM_TYPE_INTEGER, "0", "Kernel type" ) + SHADER_PARAM( ENABLECLEARCOLOR, SHADER_PARAM_TYPE_BOOL, "0", "clear RGB channels to a solid color" ) + SHADER_PARAM( CLEARCOLOR, SHADER_PARAM_TYPE_VEC3, "[0 0 0]", "clear color" ) + END_SHADER_PARAMS + + SHADER_INIT + { + if ( params[BASETEXTURE]->IsDefined() ) + { + LoadTexture( BASETEXTURE ); + } + if ( !( params[BLOOMAMOUNT]->IsDefined() ) ) + { + params[BLOOMAMOUNT]->SetFloatValue(1.0); + } + + if ( !( params[ KERNEL ]->IsDefined() ) ) + { + params[ KERNEL ]->SetIntValue( 0 ); + } + + if ( !( params[ ENABLECLEARCOLOR ]->IsDefined() ) ) + { + params[ ENABLECLEARCOLOR ]->SetIntValue( 0 ); + } + + if ( !( params[ CLEARCOLOR ]->IsDefined() ) ) + { + params[ CLEARCOLOR ]->SetVecValue( 0.0f, 0.0f, 0.0f ); + } + + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableAlphaWrites( true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 1, 0, 0 ); + + //avoid srgb conversions to alleviate some of the srgb texture lookup problems + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, false ); + pShaderShadow->EnableSRGBWrite( false ); + + DECLARE_STATIC_VERTEX_SHADER( blurfilter_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( KERNEL, params[ KERNEL ]->GetIntValue() ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER( blurfilter_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( blurfilter_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( KERNEL, params[ KERNEL ]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER_COMBO( CLEAR_COLOR, params[ ENABLECLEARCOLOR ]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER( blurfilter_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( blurfilter_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( KERNEL, params[ KERNEL ]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER_COMBO( CLEAR_COLOR, params[ ENABLECLEARCOLOR ]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER( blurfilter_ps20 ); + } + + if ( IS_FLAG_SET( MATERIAL_VAR_ADDITIVE ) ) + EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); + } + + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, -1 ); + + // The temp buffer is 1/4 back buffer size + ITexture *src_texture = params[BASETEXTURE]->GetTextureValue(); + int height = src_texture->GetActualHeight(); + float dY = 1.0f / height; +// dY *= 0.4; + float v[4]; + + // Tap offsets + v[0] = 0.0f; + v[1] = 1.3366f * dY; + v[2] = 0; + v[3] = 0; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, v, 1 ); + v[0] = 0.0f; + v[1] = 3.4295f * dY; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, v, 1 ); + v[0] = 0.0f; + v[1] = 5.4264f * dY; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, v, 1 ); + + v[0] = 0.0f; + v[1] = 7.4359f * dY; + pShaderAPI->SetPixelShaderConstant( 0, v, 1 ); + v[0] = 0.0f; + v[1] = 9.4436f * dY; + pShaderAPI->SetPixelShaderConstant( 1, v, 1 ); + v[0] = 0.0f; + v[1] = 11.4401f * dY; + pShaderAPI->SetPixelShaderConstant( 2, v, 1 ); + + v[0] = v[1] = v[2] = params[BLOOMAMOUNT]->GetFloatValue(); + pShaderAPI->SetPixelShaderConstant( 3, v, 1 ); + + v[0] = v[1] = v[2] = v[3] = 0.0; + v[1] = dY; + pShaderAPI->SetPixelShaderConstant( 4, v, 1 ); + + params[CLEARCOLOR]->GetVecValue( v, 3 ); + v[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( 5, v, 1 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( blurfilter_ps20 ); + SET_DYNAMIC_VERTEX_SHADER( blurfilter_ps20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( blurfilter_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( blurfilter_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( blurfilter_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( blurfilter_ps20 ); + } + } + Draw(); + } +END_SHADER diff --git a/materialsystem/stdshaders/BlurFilter_ps2x.fxc b/materialsystem/stdshaders/BlurFilter_ps2x.fxc new file mode 100644 index 00000000..33b50720 --- /dev/null +++ b/materialsystem/stdshaders/BlurFilter_ps2x.fxc @@ -0,0 +1,128 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "KERNEL" "0..4" +// STATIC: "CLEAR_COLOR" "0..1" + +#include "common_ps_fxc.h" + +sampler TexSampler : register( s0 ); + +struct PS_INPUT +{ + float2 coordTap0 : TEXCOORD0; + #if ( KERNEL == 0 ) // Original kernel that has a '+' plus shape + float2 coordTap1 : TEXCOORD1; + float2 coordTap2 : TEXCOORD2; + float2 coordTap3 : TEXCOORD3; + float2 coordTap1Neg : TEXCOORD4; + float2 coordTap2Neg : TEXCOORD5; + float2 coordTap3Neg : TEXCOORD6; + #endif +}; + +float2 g_vPsTapOffset[3] : register( c0 ); +float3 g_vScaleFactor : register( c3 ); + +float2 g_vUvOffsetToNeighborPixel : register( c4 ); +float3 g_vClearColor : register( c5 ); + +float4 main( PS_INPUT i ) : COLOR +{ + #if ( KERNEL == 0 ) // Original kernel that has a '+' plus shape (used for bloom?) + { + float4 s0, s1, s2, s3, s4, s5, s6, color; + + // Sample taps with coordinates from VS + s0 = saturate( tex2D( TexSampler, i.coordTap0 ) ); + s1 = saturate( tex2D( TexSampler, i.coordTap1 ) ); + s2 = saturate( tex2D( TexSampler, i.coordTap2 ) ); + s3 = saturate( tex2D( TexSampler, i.coordTap3 ) ); + s4 = saturate( tex2D( TexSampler, i.coordTap1Neg ) ); + s5 = saturate( tex2D( TexSampler, i.coordTap2Neg ) ); + s6 = saturate( tex2D( TexSampler, i.coordTap3Neg ) ); + + color = s0 * 0.2013f; + color += ( s1 + s4 ) * 0.2185f; + color += ( s2 + s5 ) * 0.0821f; + color += ( s3 + s6 ) * 0.0461f; + + // Compute tex coords for other taps + float2 coordTap4 = i.coordTap0 + g_vPsTapOffset[0]; + float2 coordTap5 = i.coordTap0 + g_vPsTapOffset[1]; + float2 coordTap6 = i.coordTap0 + g_vPsTapOffset[2]; + float2 coordTap4Neg = i.coordTap0 - g_vPsTapOffset[0]; + float2 coordTap5Neg = i.coordTap0 - g_vPsTapOffset[1]; + float2 coordTap6Neg = i.coordTap0 - g_vPsTapOffset[2]; + + // Sample the taps + s1 = saturate( tex2D( TexSampler, coordTap4 ) ); + s2 = saturate( tex2D( TexSampler, coordTap5 ) ); + s3 = saturate( tex2D( TexSampler, coordTap6 ) ); + s4 = saturate( tex2D( TexSampler, coordTap4Neg ) ); + s5 = saturate( tex2D( TexSampler, coordTap5Neg ) ); + s6 = saturate( tex2D( TexSampler, coordTap6Neg ) ); + + color += ( s1 + s4 ) * 0.0262f; + color += ( s2 + s5 ) * 0.0162f; + color += ( s3 + s6 ) * 0.0102f; + #if CLEAR_COLOR == 1 + { + color.rgb = g_vClearColor.rgb; + } + #else + { + color.xyz *= g_vScaleFactor.xyz; + } + #endif + + return color; + } + #else // Gaussian kernel + { + #if ( KERNEL == 1 ) + // Gaussian kernel 7 pixels wide + int kNumSamples = 5; + float vKernel[5] = { 0.004433f, 0.296042f, 0.399050f, 0.296042f, 0.004433f }; + float vUvOffset[5] = { -3.000000f, -1.182425f, 0.000000f, 1.182425f, 3.000000f }; + #elif ( KERNEL == 2 ) + // Gaussian kernel 9 pixels wide + int kNumSamples = 5; + float vKernel[5] = { 0.019827f, 0.320561f, 0.319224f, 0.320561f, 0.019827f }; + float vUvOffset[5] = { -3.096215f, -1.276878f, 0.000000f, 1.276878f, 3.096215f }; + #elif ( KERNEL == 3 ) + // Gaussian kernel 13 pixels wide + int kNumSamples = 7; + float vKernel[7] = { 0.004487f, 0.069185f, 0.312325f, 0.228005f, 0.312325f, 0.069185f, 0.004487f }; + float vUvOffset[7] = { -5.142349f, -3.241796f, -1.379942f, 0.000000f, 1.379942f, 3.241796f, 5.142349f }; + #elif ( KERNEL == 4 ) + // Gaussian kernel 25 pixels wide + int kNumSamples = 13; + float vKernel[13] = { 0.000534f, 0.003733f, 0.018004f, 0.059928f, 0.137740f, 0.218677f, 0.122765f, 0.218677f, 0.137740f, 0.059928f, 0.018004f, 0.003733f, 0.000534f }; + float vUvOffset[13] = { -11.251852f, -9.289172f, -7.329586f, -5.372686f, -3.417910f, -1.464557f, 0.000000f, 1.464557f, 3.417910f, 5.372686f, 7.329586f, 9.289172f, 11.251852f }; + #endif + + float2 vStartUv = i.coordTap0.xy; + + float4 cColor = { 0.0f, 0.0f, 0.0f, 0.0f }; + for ( int j = 0; j < kNumSamples; j++ ) + { + // Calculate uv + float2 vUvTmp = vStartUv.xy + ( vUvOffset[j].xx * g_vUvOffsetToNeighborPixel.xy ); + + // Sample pixel + cColor.rgba += vKernel[j] * tex2D( TexSampler, vUvTmp.xy ); + } + + #if CLEAR_COLOR == 1 + { + cColor.rgb = g_vClearColor.rgb; + } + #else + { + cColor.rgb = cColor.rgb * g_vScaleFactor.rgb; + } + #endif + return cColor.rgba; + } + #endif +} diff --git a/materialsystem/stdshaders/BlurFilter_vs20.fxc b/materialsystem/stdshaders/BlurFilter_vs20.fxc new file mode 100644 index 00000000..578a842d --- /dev/null +++ b/materialsystem/stdshaders/BlurFilter_vs20.fxc @@ -0,0 +1,45 @@ +#include "common_vs_fxc.h" + +// STATIC: "KERNEL" "0..1" + +struct VS_INPUT +{ + float3 vPos : POSITION; + float2 vBaseTexCoord : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; + float2 coordTap0 : TEXCOORD0; + #if ( KERNEL == 0 ) // Original kernel that has a '+' plus shape + float2 coordTap1 : TEXCOORD1; + float2 coordTap2 : TEXCOORD2; + float2 coordTap3 : TEXCOORD3; + float2 coordTap1Neg : TEXCOORD4; + float2 coordTap2Neg : TEXCOORD5; + float2 coordTap3Neg : TEXCOORD6; + #endif +}; + +float2 vsTapOffs[3] : register ( SHADER_SPECIFIC_CONST_0 ); + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + o.projPos = float4( v.vPos, 1.0f ); + o.coordTap0.xy = v.vBaseTexCoord.xy; + #if ( KERNEL == 0 ) // Original kernel + o.coordTap1 = v.vBaseTexCoord + vsTapOffs[0]; + o.coordTap2 = v.vBaseTexCoord + vsTapOffs[1]; + o.coordTap3 = v.vBaseTexCoord + vsTapOffs[2]; + o.coordTap1Neg = v.vBaseTexCoord - vsTapOffs[0]; + o.coordTap2Neg = v.vBaseTexCoord - vsTapOffs[1]; + o.coordTap3Neg = v.vBaseTexCoord - vsTapOffs[2]; + #endif + + return o; +} + + diff --git a/materialsystem/stdshaders/BufferClearObeyStencil_dx9.cpp b/materialsystem/stdshaders/BufferClearObeyStencil_dx9.cpp new file mode 100644 index 00000000..2f3cc0f0 --- /dev/null +++ b/materialsystem/stdshaders/BufferClearObeyStencil_dx9.cpp @@ -0,0 +1,105 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: Clears color/depth, but obeys stencil while doing so +// +//=============================================================================// + +#include "BaseVSShader.h" + +#include "bufferclearobeystencil_vs20.inc" +#include "bufferclearobeystencil_ps20.inc" +#include "bufferclearobeystencil_ps20b.inc" + + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( BufferClearObeyStencil, BufferClearObeyStencil_DX9 ) + +BEGIN_VS_SHADER_FLAGS( BufferClearObeyStencil_DX9, "", SHADER_NOT_EDITABLE ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( CLEARCOLOR, SHADER_PARAM_TYPE_INTEGER, "1", "activates clearing of color" ) + SHADER_PARAM( CLEARALPHA, SHADER_PARAM_TYPE_INTEGER, "-1", "activates clearing of alpha. -1 == copy CLEARCOLOR setting" ) + SHADER_PARAM( CLEARDEPTH, SHADER_PARAM_TYPE_INTEGER, "1", "activates clearing of depth" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + if ( !params[CLEARALPHA]->IsDefined() ) + { + params[CLEARALPHA]->SetIntValue( -1 ); + } + } + + SHADER_DRAW + { + bool bEnableColorWrites = params[CLEARCOLOR]->GetIntValue() != 0; + bool bEnableAlphaWrites = (params[CLEARALPHA]->GetIntValue() >= 0) ? (params[CLEARALPHA]->GetIntValue() != 0) : bEnableColorWrites; + + bool bUsesColor = bEnableColorWrites || bEnableAlphaWrites; + SHADOW_STATE + { + pShaderShadow->DepthFunc( SHADER_DEPTHFUNC_ALWAYS ); + bool bEnableDepthWrites = params[CLEARDEPTH]->GetIntValue() != 0; + pShaderShadow->EnableDepthWrites( bEnableDepthWrites ); + + pShaderShadow->EnableColorWrites( bEnableColorWrites ); + pShaderShadow->EnableAlphaWrites( bEnableAlphaWrites ); + + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION|VERTEX_COLOR, 1, NULL, 0 ); + + DECLARE_STATIC_VERTEX_SHADER( bufferclearobeystencil_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( USESCOLOR, bUsesColor ); + SET_STATIC_VERTEX_SHADER( bufferclearobeystencil_vs20 ); + + //avoid setting a pixel shader when only doing depth/stencil operations, as recommended by PIX + if( bUsesColor ) + { + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( bufferclearobeystencil_ps20b ); + SET_STATIC_PIXEL_SHADER( bufferclearobeystencil_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( bufferclearobeystencil_ps20 ); + SET_STATIC_PIXEL_SHADER( bufferclearobeystencil_ps20 ); + } + } + } + + DYNAMIC_STATE + { + DECLARE_DYNAMIC_VERTEX_SHADER( bufferclearobeystencil_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( bufferclearobeystencil_vs20 ); + + //avoid setting a pixel shader when only doing depth/stencil operations, as recommended by PIX + if( bUsesColor ) + { + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( bufferclearobeystencil_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( bufferclearobeystencil_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( bufferclearobeystencil_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( bufferclearobeystencil_ps20 ); + } + } + } + + Draw( ); + } + +END_SHADER diff --git a/materialsystem/stdshaders/DebugDrawDepth_ps2x.fxc b/materialsystem/stdshaders/DebugDrawDepth_ps2x.fxc new file mode 100644 index 00000000..86e39673 --- /dev/null +++ b/materialsystem/stdshaders/DebugDrawDepth_ps2x.fxc @@ -0,0 +1,21 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#include "common_ps_fxc.h" + +struct PS_INPUT +{ + float4 projPos : POSITION; + float3 zValue : TEXCOORD0; +}; + +const float3 g_ZFilter : register( c1 ); +const float3 g_ModulationColor : register( c2 ); + +float4 main( PS_INPUT i ) : COLOR +{ + float z = dot( i.zValue, g_ZFilter ); + z = saturate( z ); + float4 color = float4( z, z, z, 1.0f ); + color.rgb *= g_ModulationColor; + return FinalOutput( color, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} diff --git a/materialsystem/stdshaders/DebugDrawDepth_vs20.fxc b/materialsystem/stdshaders/DebugDrawDepth_vs20.fxc new file mode 100644 index 00000000..2cbeeb1c --- /dev/null +++ b/materialsystem/stdshaders/DebugDrawDepth_vs20.fxc @@ -0,0 +1,38 @@ +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "SKINNING" "0..1" + +#include "common_vs_fxc.h" + +static const bool g_bSkinning = SKINNING ? true : false; + +const float2 cDepthFactor : register( SHADER_SPECIFIC_CONST_0 ); + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; + float2 zValue : TEXCOORD0; +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 worldPos; + SkinPosition( g_bSkinning, v.vPos, v.vBoneWeights, v.vBoneIndices, worldPos ); + float4 projPos = mul( float4( worldPos, 1 ), cViewProj ); + o.projPos = projPos; + o.zValue.x = (o.projPos.z - cDepthFactor.y) / cDepthFactor.x; + o.zValue.y = (o.projPos.w - cDepthFactor.y) / cDepthFactor.x; + return o; +} + + + + diff --git a/materialsystem/stdshaders/DebugDrawEnvmapMask.cpp b/materialsystem/stdshaders/DebugDrawEnvmapMask.cpp new file mode 100644 index 00000000..46f5647f --- /dev/null +++ b/materialsystem/stdshaders/DebugDrawEnvmapMask.cpp @@ -0,0 +1,89 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +//===========================================================================// + +#include "BaseVSShader.h" +#include "debugdrawenvmapmask_vs20.inc" +#include "debugdrawenvmapmask_ps20.inc" +#include "debugdrawenvmapmask_ps20b.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_VS_SHADER_FLAGS( DebugDrawEnvmapMask, "Help for DebugDrawEnvmapMask", SHADER_NOT_EDITABLE ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( SHOWALPHA, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + } + + SHADER_INIT + { + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + DECLARE_STATIC_VERTEX_SHADER( debugdrawenvmapmask_vs20 ); + SET_STATIC_VERTEX_SHADER( debugdrawenvmapmask_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( debugdrawenvmapmask_ps20b ); + SET_STATIC_PIXEL_SHADER( debugdrawenvmapmask_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( debugdrawenvmapmask_ps20 ); + SET_STATIC_PIXEL_SHADER( debugdrawenvmapmask_ps20 ); + } + } + DYNAMIC_STATE + { + int numBones = s_pShaderAPI->GetCurrentNumBones(); + + DECLARE_DYNAMIC_VERTEX_SHADER( debugdrawenvmapmask_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, numBones > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( debugdrawenvmapmask_vs20 ); + + bool bShowAlpha = params[SHOWALPHA]->GetIntValue() ? true : false; + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( debugdrawenvmapmask_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( SHOWALPHA, bShowAlpha ); + SET_DYNAMIC_PIXEL_SHADER( debugdrawenvmapmask_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( debugdrawenvmapmask_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( SHOWALPHA, bShowAlpha ); + SET_DYNAMIC_PIXEL_SHADER( debugdrawenvmapmask_ps20 ); + } + + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BASETEXTURETRANSFORM ); + } + Draw(); + } +END_SHADER diff --git a/materialsystem/stdshaders/DebugDrawEnvmapMask_ps2x.fxc b/materialsystem/stdshaders/DebugDrawEnvmapMask_ps2x.fxc new file mode 100644 index 00000000..124f00a9 --- /dev/null +++ b/materialsystem/stdshaders/DebugDrawEnvmapMask_ps2x.fxc @@ -0,0 +1,24 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// DYNAMIC: "SHOWALPHA" "0..1" + +#include "common_ps_fxc.h" + +sampler BaseTextureSampler : register( s0 ); + +struct PS_INPUT +{ + float4 projPos : POSITION; + float2 baseTexCoord : TEXCOORD0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float4 baseColor = tex2D( BaseTextureSampler, i.baseTexCoord ); +#if SHOWALPHA + float4 result = float4( baseColor.a, baseColor.a, baseColor.a, 1.0f ); +#else + float4 result = float4( baseColor.rgb, 1.0f ); +#endif + return FinalOutput( result, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} diff --git a/materialsystem/stdshaders/DebugDrawEnvmapMask_vs20.fxc b/materialsystem/stdshaders/DebugDrawEnvmapMask_vs20.fxc new file mode 100644 index 00000000..b9c6f0e9 --- /dev/null +++ b/materialsystem/stdshaders/DebugDrawEnvmapMask_vs20.fxc @@ -0,0 +1,39 @@ +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "SKINNING" "0..1" + +#include "common_vs_fxc.h" + +static const bool g_bSkinning = SKINNING ? true : false; + +const float4 cBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_0 ); + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vTexCoord0 : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; + float2 baseTexCoord : TEXCOORD0; +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 worldPos; + SkinPosition( g_bSkinning, v.vPos, v.vBoneWeights, v.vBoneIndices, worldPos ); + float4 projPos = mul( float4( worldPos, 1 ), cViewProj ); + o.projPos = projPos; + o.baseTexCoord.x = dot( v.vTexCoord0, cBaseTexCoordTransform[0] ); + o.baseTexCoord.y = dot( v.vTexCoord0, cBaseTexCoordTransform[1] ); + return o; +} + + + + diff --git a/materialsystem/stdshaders/DebugTextureView.cpp b/materialsystem/stdshaders/DebugTextureView.cpp new file mode 100644 index 00000000..5ecc1a8d --- /dev/null +++ b/materialsystem/stdshaders/DebugTextureView.cpp @@ -0,0 +1,104 @@ +//========= Copyright © 1996-2007, Valve Corporation, All rights reserved. ============// + +#include "BaseVSShader.h" +#include "shaderlib/CShader.h" + +#include "debugtextureview_vs20.inc" +#include "debugtextureview_ps20.inc" +#include "debugtextureview_ps20b.inc" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +DEFINE_FALLBACK_SHADER( DebugTextureView, DebugTextureView_dx9 ) +BEGIN_VS_SHADER( DebugTextureView_dx9, "Help for DebugTextureView" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( SHOWALPHA, SHADER_PARAM_TYPE_BOOL, "0", "" ) + END_SHADER_PARAMS + + SHADER_INIT + { + if ( params[BASETEXTURE]->IsDefined() ) + { + LoadTexture( BASETEXTURE ); + } + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableAlphaTest( true ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + DECLARE_STATIC_VERTEX_SHADER( debugtextureview_vs20 ); + SET_STATIC_VERTEX_SHADER( debugtextureview_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( debugtextureview_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( SHOWALPHA, params[SHOWALPHA]->GetIntValue() != 0 ); + SET_STATIC_PIXEL_SHADER( debugtextureview_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( debugtextureview_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( SHOWALPHA, params[SHOWALPHA]->GetIntValue() != 0 ); + SET_STATIC_PIXEL_SHADER( debugtextureview_ps20 ); + } + } + + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + //pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP ); + + ITexture *pTexture = params[BASETEXTURE]->GetTextureValue(); + + float cPsConst0[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + if ( ( pTexture->GetImageFormat() == IMAGE_FORMAT_RGBA16161616F ) || + ( pTexture->GetImageFormat() == IMAGE_FORMAT_RGBA16161616 ) || + ( pTexture->GetImageFormat() == IMAGE_FORMAT_RGB323232F ) || + ( pTexture->GetImageFormat() == IMAGE_FORMAT_RGBA32323232F ) ) + { + if ( pTexture->IsCubeMap() ) + cPsConst0[0] = 1.0f; + else + cPsConst0[1] = 1.0f; + } + pShaderAPI->SetPixelShaderConstant( 0, cPsConst0 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( debugtextureview_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( debugtextureview_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( debugtextureview_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( ISCUBEMAP, pTexture->IsCubeMap() ); + SET_DYNAMIC_PIXEL_SHADER( debugtextureview_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( debugtextureview_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( ISCUBEMAP, pTexture->IsCubeMap() ); + SET_DYNAMIC_PIXEL_SHADER( debugtextureview_ps20 ); + } + } + Draw(); + } +END_SHADER diff --git a/materialsystem/stdshaders/DebugTextureView_ps2x.fxc b/materialsystem/stdshaders/DebugTextureView_ps2x.fxc new file mode 100644 index 00000000..2047e656 --- /dev/null +++ b/materialsystem/stdshaders/DebugTextureView_ps2x.fxc @@ -0,0 +1,80 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "SHOWALPHA" "0..1" +// DYNAMIC: "ISCUBEMAP" "0..1" + +#include "common_ps_fxc.h" + +sampler g_tSampler : register( s0 ); + +struct PS_INPUT +{ + float2 texCoord : TEXCOORD0; +}; + +const float3 g_vConst0 : register( c0 ); +#define g_flIsHdrCube g_vConst0.x +#define g_flIsHdr2D g_vConst0.y + +float4 main( PS_INPUT i ) : COLOR +{ + float4 sample = tex2D( g_tSampler, i.texCoord ); + float4 result = { 0.0f, 0.0f, 0.0f, 1.0f }; + + result.rgb = sample.rgb; + #if SHOWALPHA + result.rgb = sample.a; + #endif + + if ( g_flIsHdr2D ) + result.rgb *= MAX_HDR_OVERBRIGHT; + + #if ISCUBEMAP + bool bNoDataForThisPixel = false; + float3 vec = float3( 0, 0, 0 ); + float x = i.texCoord.x; + float y = i.texCoord.y; + float x2 = frac( ( i.texCoord.x ) * 3.0f ) * 2.0f - 1.0f; + float y2 = frac( ( i.texCoord.y ) * 4.0f ) * 2.0f - 1.0f; + if ( ( x >= 0.3333f ) && ( x <= 0.6666f ) ) //Center row + { + if ( y >= 0.75f ) + vec = float3( x2, 1.0, y2 ); + else if ( y >= 0.5f ) + vec = float3( x2, y2, -1.0 ); + else if ( y >= 0.25f ) + vec = float3( x2, -1.0, -y2 ); + else if ( y >= 0.0f ) + vec = float3( x2, -y2, 1.0 ); + } + else if ( ( y >= 0.25f ) && ( y <= 0.5f ) ) + { + if ( x <= 0.3333f ) + vec = float3( -1.0f, -x2, -y2 ); + else if (x >= 0.6666f) + vec = float3( 1.0f, x2, -y2 ); + else + bNoDataForThisPixel = true; + } + else + { + bNoDataForThisPixel = true; + } + + float4 cBase = texCUBE( g_tSampler, vec ); + #if SHOWALPHA + cBase.rgb = cBase.a; + #endif + + if ( g_flIsHdrCube ) + cBase.rgb *= ENV_MAP_SCALE; + + if ( bNoDataForThisPixel == true ) + cBase.rgb = float3( 0.9f, 0.4f, 0.15f ); + + result.rgb = cBase.rgb; + result.a = 1.0f; // - bNoDataForThisPixel; + #endif + + return FinalOutput( result, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} diff --git a/materialsystem/stdshaders/DebugTextureView_vs20.fxc b/materialsystem/stdshaders/DebugTextureView_vs20.fxc new file mode 100644 index 00000000..a9857f01 --- /dev/null +++ b/materialsystem/stdshaders/DebugTextureView_vs20.fxc @@ -0,0 +1,23 @@ +// DYNAMIC: "COMPRESSED_VERTS" "0..1" + +#include "common_vs_fxc.h" + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vTexCoord0 : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; + float2 vUv0 : TEXCOORD0; +}; + +VS_OUTPUT main( const VS_INPUT i ) +{ + VS_OUTPUT o; + o.vProjPos.xyzw = mul( i.vPos.xyzw, cModelViewProj ); + o.vUv0.xy = i.vTexCoord0.xy; + return o; +} diff --git a/materialsystem/stdshaders/DecalModulate_dx9.cpp b/materialsystem/stdshaders/DecalModulate_dx9.cpp new file mode 100644 index 00000000..d42a3666 --- /dev/null +++ b/materialsystem/stdshaders/DecalModulate_dx9.cpp @@ -0,0 +1,227 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" +#include "cpp_shader_constant_register_map.h" + +#include "decalmodulate_vs20.inc" +#include "decalmodulate_ps20.inc" +#include "decalmodulate_ps20b.inc" + +#ifndef _X360 +#include "decalmodulate_vs30.inc" +#include "decalmodulate_ps30.inc" +#endif + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( DecalModulate, DecalModulate_DX9 ) + +BEGIN_VS_SHADER( DecalModulate_dx9, + "Help for DecalModulate_dx9" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( FOGEXPONENT, SHADER_PARAM_TYPE_FLOAT, "0.4", "exponent to tweak fog fade" ) + SHADER_PARAM( FOGSCALE, SHADER_PARAM_TYPE_FLOAT, "1.0", "scale to tweak fog fade" ) + END_SHADER_PARAMS + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT_PARAMS() + { + if( !params[ FOGEXPONENT ]->IsDefined() ) + { + params[ FOGEXPONENT ]->SetFloatValue( 0.4f ); + } + + if( !params[ FOGSCALE ]->IsDefined() ) + { + params[ FOGSCALE ]->SetFloatValue( 1.0f ); + } + + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + +#ifndef _X360 + if ( g_pHardwareConfig->HasFastVertexTextures() ) + { + // The vertex shader uses the vertex id stream + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + } +#endif + } + + SHADER_INIT + { + LoadTexture( BASETEXTURE ); + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableAlphaTest( true ); + pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GREATER, 0.0f ); + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnablePolyOffset( SHADER_POLYOFFSET_DECAL ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + // Be sure not to write to dest alpha + pShaderShadow->EnableAlphaWrites( false ); + + //SRGB conversions hose the blend on some hardware, so keep everything in gamma space. + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, false ); + pShaderShadow->EnableSRGBWrite( false ); + + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_DST_COLOR, SHADER_BLEND_SRC_COLOR ); + pShaderShadow->DisableFogGammaCorrection( true ); //fog should stay exactly middle grey + FogToGrey(); + + int nLightingPreviewMode = IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER0 ) + 2 * IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER1 ); + + bool bHasVertexAlpha = IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR ) && IS_FLAG_SET( MATERIAL_VAR_VERTEXALPHA ); + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_STATIC_VERTEX_SHADER( decalmodulate_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( VERTEXCOLOR, bHasVertexAlpha ); + SET_STATIC_VERTEX_SHADER_COMBO( LIGHTING_PREVIEW, nLightingPreviewMode != 0 ); + SET_STATIC_VERTEX_SHADER( decalmodulate_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( decalmodulate_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( VERTEXALPHA, bHasVertexAlpha ); + SET_STATIC_PIXEL_SHADER( decalmodulate_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( decalmodulate_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( VERTEXALPHA, bHasVertexAlpha ); + SET_STATIC_PIXEL_SHADER( decalmodulate_ps20 ); + } + } +#ifndef _X360 + else + { + DECLARE_STATIC_VERTEX_SHADER( decalmodulate_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( VERTEXCOLOR, bHasVertexAlpha ); + SET_STATIC_VERTEX_SHADER_COMBO( LIGHTING_PREVIEW, nLightingPreviewMode != 0 ); + SET_STATIC_VERTEX_SHADER( decalmodulate_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( decalmodulate_ps30 ); + SET_STATIC_PIXEL_SHADER_COMBO( VERTEXALPHA, bHasVertexAlpha ); + SET_STATIC_PIXEL_SHADER( decalmodulate_ps30 ); + } +#endif + + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_FORMAT_COMPRESSED; + + if ( bHasVertexAlpha ) + { + flags |= VERTEX_COLOR; + } + +#ifndef _X360 + // The VS30 shader offsets decals along the normal (for morphed geom) + flags |= g_pHardwareConfig->HasFastVertexTextures() ? VERTEX_NORMAL : 0; +#endif + int pTexCoordDim[3] = { 2, 0, 3 }; + int nTexCoordCount = 1; + int userDataSize = 0; + +#ifndef _X360 + if ( g_pHardwareConfig->HasFastVertexTextures() ) + { + nTexCoordCount = 3; + } +#endif + + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, pTexCoordDim, userDataSize ); + } + DYNAMIC_STATE + { + if ( pShaderAPI->InFlashlightMode() && !IsX360() ) + { + // Don't draw anything for the flashlight pass + Draw( false ); + return; + } + + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + + // Set an identity base texture transformation + Vector4D transformation[2]; + transformation[0].Init( 1.0f, 0.0f, 0.0f, 0.0f ); + transformation[1].Init( 0.0f, 1.0f, 0.0f, 0.0f ); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, transformation[0].Base(), 2 ); + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + float vEyePos_SpecExponent[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + vEyePos_SpecExponent[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + + // fog tweaks + float fConsts[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + fConsts[0] = params[ FOGEXPONENT ]->GetFloatValue(); + fConsts[1] = params[ FOGSCALE ]->GetFloatValue(); + pShaderAPI->SetPixelShaderConstant( 0, fConsts ); + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_DYNAMIC_VERTEX_SHADER( decalmodulate_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); +// SET_DYNAMIC_VERTEX_SHADER_COMBO( TESSELLATION, 0 ); // JasonM TODO: set this appropriately when we care about decals on subds + SET_DYNAMIC_VERTEX_SHADER( decalmodulate_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( decalmodulate_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( decalmodulate_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( decalmodulate_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( decalmodulate_ps20 ); + } + } +#ifndef _X360 + else + { + SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, SHADER_VERTEXTEXTURE_SAMPLER0 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( decalmodulate_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); +// SET_DYNAMIC_VERTEX_SHADER_COMBO( TESSELLATION, 0 ); // JasonM TODO: set this appropriately when we care about decals on subds + SET_DYNAMIC_VERTEX_SHADER( decalmodulate_vs30 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( decalmodulate_ps30 ); + SET_DYNAMIC_PIXEL_SHADER( decalmodulate_ps30 ); + + bool bUnusedTexCoords[3] = { false, false, !pShaderAPI->IsHWMorphingEnabled() }; + pShaderAPI->MarkUnusedVertexFields( 0, 3, bUnusedTexCoords ); + } +#endif + } + Draw( ); + } +END_SHADER diff --git a/materialsystem/stdshaders/DepthOfField_dx9.cpp b/materialsystem/stdshaders/DepthOfField_dx9.cpp new file mode 100644 index 00000000..727a3473 --- /dev/null +++ b/materialsystem/stdshaders/DepthOfField_dx9.cpp @@ -0,0 +1,280 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: Depth of field material +// +//===========================================================================// + +#include "BaseVSShader.h" +#include "depth_of_field_vs20.inc" +#include "depth_of_field_ps20b.inc" +#include "convar.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +ConVar mat_dof_max_blur_radius( "mat_dof_max_blur_radius", "10" ); +ConVar mat_dof_quality( "mat_dof_quality", "0" ); + +// 8 samples +static const float s_flPoissonConstsQuality0[16] = { + 0.0, 0.0, + 0.527837, -0.085868, + -0.040088, 0.536087, + -0.670445, -0.179949, + -0.419418, -0.616039, + 0.440453, -0.639399, + -0.757088, 0.349334, + 0.574619, 0.685879 +}; + +// 16 samples +static const float s_flPoissonConstsQuality1[32] = { + 0.0747, -0.8341, + -0.9138, 0.3251, + 0.8667, -0.3029, + -0.4642, 0.2187, + -0.1505, 0.7320, + 0.7310, -0.6786, + 0.2859, -0.3254, + -0.1311, -0.2292, + 0.3518, 0.6470, + -0.7485, -0.6307, + 0.1687, 0.1873, + -0.3604, -0.7483, + -0.5658, -0.1521, + 0.7102, 0.0536, + -0.6056, 0.7747, + 0.7793, 0.6194 +}; + +// 32 samples +static const float s_flPoissonConstsQuality2[64] = { + 0.0854f, -0.0644f, + 0.8744f, 0.1665f, + 0.2329f, 0.3995f, + -0.7804f, 0.5482f, + -0.4577f, 0.7647f, + -0.1936f, 0.5564f, + 0.4205f, -0.5768f, + -0.0304f, -0.9050f, + -0.5215f, 0.1854f, + 0.3161f, -0.2954f, + 0.0666f, -0.5564f, + -0.2137f, -0.0072f, + -0.4112f, -0.3311f, + 0.6438f, -0.2484f, + -0.9055f, -0.0360f, + 0.8323f, 0.5268f, + 0.5592f, 0.3459f, + -0.6797f, -0.5201f, + -0.4325f, -0.8857f, + 0.8768f, -0.4197f, + 0.3090f, -0.8646f, + 0.5034f, 0.8603f, + 0.3752f, 0.0627f, + -0.0161f, 0.2627f, + 0.0969f, 0.7054f, + -0.2291f, -0.6595f, + -0.5887f, -0.1100f, + 0.7048f, -0.6528f, + -0.8438f, 0.2706f, + -0.5061f, 0.4653f, + -0.1245f, -0.3302f, + -0.1801f, 0.8486f +}; + +DEFINE_FALLBACK_SHADER( DepthOfField, DepthOfField_dx9 ) +BEGIN_VS_SHADER_FLAGS( DepthOfField_dx9, "Depth of Field", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( SMALLFB, SHADER_PARAM_TYPE_TEXTURE, "_rt_SmallFB1", "Downsampled backbuffer" ) + SHADER_PARAM( NEARPLANE, SHADER_PARAM_TYPE_FLOAT, "0", "Near plane depth" ) + SHADER_PARAM( FARPLANE, SHADER_PARAM_TYPE_FLOAT, "0", "Far plane depth" ) + SHADER_PARAM( NEARBLURDEPTH, SHADER_PARAM_TYPE_FLOAT, "0", "Near blur plane depth" ) + SHADER_PARAM( NEARFOCUSDEPTH, SHADER_PARAM_TYPE_FLOAT, "0", "Near focus plane depth" ) + SHADER_PARAM( FARFOCUSDEPTH, SHADER_PARAM_TYPE_FLOAT, "0", "Far focus plane depth" ) + SHADER_PARAM( FARBLURDEPTH, SHADER_PARAM_TYPE_FLOAT, "0", "Far blur plane depth" ) + SHADER_PARAM( NEARBLURRADIUS, SHADER_PARAM_TYPE_FLOAT, "0", "Max near blur radius" ) + SHADER_PARAM( FARBLURRADIUS, SHADER_PARAM_TYPE_FLOAT, "0", "Max far blur radius" ) + SHADER_PARAM( QUALITY, SHADER_PARAM_TYPE_INTEGER, "0", "Quality level. Selects different algorithms." ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_PARAM_STRING_IF_NOT_DEFINED( SMALLFB, "_rt_SmallFB1" ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( NEARPLANE, 0.0f ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( FARPLANE, 0.0f ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( NEARBLURDEPTH, 0.0f ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( NEARFOCUSDEPTH, 0.0f ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( FARFOCUSDEPTH, 0.0f ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( FARBLURDEPTH, 0.0f ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( NEARBLURRADIUS, 0.0f ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( FARBLURRADIUS, 0.0f ); + SET_PARAM_INT_IF_NOT_DEFINED( QUALITY, 0 ); + } + + SHADER_FALLBACK + { + if ( g_pHardwareConfig->GetDXSupportLevel() < 92 ) + { + return "Wireframe"; + } + + return 0; + } + + SHADER_INIT + { + if ( params[BASETEXTURE]->IsDefined() ) + { + LoadTexture( BASETEXTURE ); + } + if ( params[SMALLFB]->IsDefined() ) + { + LoadTexture( SMALLFB ); + } + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 1, 0, 0 ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, false ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, false ); + pShaderShadow->EnableSRGBWrite( false ); + + DECLARE_STATIC_VERTEX_SHADER( depth_of_field_vs20 ); + SET_STATIC_VERTEX_SHADER( depth_of_field_vs20 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( depth_of_field_ps20b ); + SET_STATIC_PIXEL_SHADER( depth_of_field_ps20b ); + } + else + { + Assert( !"No ps_2_b. This shouldn't be happening" ); + } + + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableAlphaWrites( false ); + } + + DYNAMIC_STATE + { + DECLARE_DYNAMIC_VERTEX_SHADER( depth_of_field_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( depth_of_field_vs20 ); + + // Bind textures + BindTexture( SHADER_SAMPLER0, BASETEXTURE ); + BindTexture( SHADER_SAMPLER1, SMALLFB ); + + // near blur = blur of stuff in front of focus range + // far blur = blur of stuff behind focus range + + // C0: set near/far blur and focus distances + // x = near blur distance + // y = near focus distance + // z = far focus distance + // w = far blur distance + // C1: + // x = blur radius for near blur (in pixels) + // y = blur radius for far blur (in pixels) + // TODO: Specifying this stuff in pixels makes blurs look smaller on high backbuffer resolutions. + // This might be a problem for tweaking these values. + float vConst[16] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + + vConst[0] = params[NEARBLURDEPTH]->GetFloatValue(); + vConst[1] = params[NEARFOCUSDEPTH]->GetFloatValue(); + vConst[2] = params[FARFOCUSDEPTH]->GetFloatValue(); + vConst[3] = params[FARBLURDEPTH]->GetFloatValue();; + // max blur radius will need to be set based on qulity level and screen res + vConst[4] = mat_dof_max_blur_radius.GetFloat(); + vConst[5] = MIN( params[NEARBLURRADIUS]->GetFloatValue(), vConst[4] ) / vConst[4]; // near and far blur radius as fraction of max radius + vConst[6] = MIN( params[FARBLURRADIUS]->GetFloatValue(), vConst[4] ) / vConst[4]; + + vConst[8] = params[NEARPLANE]->GetFloatValue(); + vConst[9] = params[FARPLANE]->GetFloatValue(); + + // 8192 is the magic number for HDR mode 3 (see FLOAT_RENDERPARM_DEST_ALPHA_DEPTH_SCALE in shaderapidx8.cpp) + vConst[10] = 8192.0f * ( vConst[9] - vConst[8] ) / vConst[9]; + + vConst[12] = vConst[10] / ( vConst[0] - vConst[1] ); + vConst[13] = ( vConst[8] - vConst[1] ) / ( vConst[0] - vConst[1] ); + vConst[14] = vConst[10] / ( vConst[3] - vConst[2] ); + vConst[15] = ( vConst[8] - vConst[2] ) / ( vConst[3] - vConst[2] ); + + pShaderAPI->SetPixelShaderConstant( 0, vConst, 4 ); + + // set up poisson sample location constants pre-divided by screen res + int nNumPoissonSamples = 0; + const float *pPoissonSrc = NULL; + switch ( params[QUALITY]->GetIntValue() ) + { + case 0: + // NOTE: These must match the shader + nNumPoissonSamples = 8; + pPoissonSrc = s_flPoissonConstsQuality0; + break; + + case 1: + case 2: + nNumPoissonSamples = 16; + pPoissonSrc = s_flPoissonConstsQuality1; + break; + + case 3: + nNumPoissonSamples = 32; + pPoissonSrc = s_flPoissonConstsQuality2; + break; + + default: + Warning( "Invalid mat_dof_quality value. Resetting to 0.\n" ); + mat_dof_quality.SetValue( 0 ); + nNumPoissonSamples = 8; + pPoissonSrc = s_flPoissonConstsQuality0; + break; + } + + float vPoissonConst[64]; // temp table + + // Get texture dimensions + ITexture *pTex = params[BASETEXTURE]->GetTextureValue(); + Assert( pTex ); + float flInvTexWidth = 1.0f / static_cast( pTex->GetActualWidth() ); + float flInvTexHeight = 1.0f / static_cast( pTex->GetActualHeight() ); + + for ( int i = 0; i < nNumPoissonSamples; i++ ) + { + vPoissonConst[ 2*i ] = pPoissonSrc[ 2*i ] * flInvTexWidth; + vPoissonConst[ 2*i+1 ] = pPoissonSrc[ 2*i+1 ] * flInvTexHeight; + } + + // swizzle every other 2-tuple so that I can use the free .wz swizzle in the shader + for ( int i = 1; i < nNumPoissonSamples; i += 2) + { + float t = vPoissonConst[ 2*i ]; + vPoissonConst[ 2*i ] = vPoissonConst[ 2*i+1 ]; + vPoissonConst[ 2*i+1 ] = t; + } + + pShaderAPI->SetPixelShaderConstant( 4, vPoissonConst, nNumPoissonSamples / 2 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( depth_of_field_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( QUALITY, params[QUALITY]->GetIntValue() ); + SET_DYNAMIC_PIXEL_SHADER( depth_of_field_ps20b ); + } + else + { + Assert( !"No ps_2_b. This shouldn't be happening" ); + } + } + + Draw(); + } +END_SHADER diff --git a/materialsystem/stdshaders/Downsample.cpp b/materialsystem/stdshaders/Downsample.cpp new file mode 100644 index 00000000..15957baa --- /dev/null +++ b/materialsystem/stdshaders/Downsample.cpp @@ -0,0 +1,105 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" +#include "common_hlsl_cpp_consts.h" + +#include "downsample_ps20.inc" +#include "downsample_ps20b.inc" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +BEGIN_VS_SHADER_FLAGS( Downsample, "Help for Downsample", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + END_SHADER_PARAMS + + SHADER_INIT + { + LoadTexture( BASETEXTURE ); + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableAlphaWrites( true ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, false ); + pShaderShadow->EnableSRGBWrite( false ); + + int fmt = VERTEX_POSITION; + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 ); + + pShaderShadow->SetVertexShader( "Downsample_vs20", 0 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( downsample_ps20b ); + SET_STATIC_PIXEL_SHADER( downsample_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( downsample_ps20 ); + SET_STATIC_PIXEL_SHADER( downsample_ps20 ); + } + } + + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, -1 ); + + int width, height; + pShaderAPI->GetBackBufferDimensions( width, height ); + + float v[4]; + float dX = 1.0f / width; + float dY = 1.0f / height; + + v[0] = -dX; + v[1] = -dY; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, v, 1 ); + v[0] = -dX; + v[1] = dY; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, v, 1 ); + v[0] = dX; + v[1] = -dY; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, v, 1 ); + v[0] = dX; + v[1] = dY; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, v, 1 ); + + // Setup luminance threshold (all values are scaled down by max luminance) +// v[0] = 1.0f / MAX_HDR_OVERBRIGHT; + v[0] = 0.0f; + pShaderAPI->SetPixelShaderConstant( 0, v, 1 ); + + pShaderAPI->SetVertexShaderIndex( 0 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( downsample_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( downsample_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( downsample_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( downsample_ps20 ); + } + } + Draw(); + } +END_SHADER diff --git a/materialsystem/stdshaders/Downsample_nohdr_ps2x.fxc b/materialsystem/stdshaders/Downsample_nohdr_ps2x.fxc new file mode 100644 index 00000000..315f3892 --- /dev/null +++ b/materialsystem/stdshaders/Downsample_nohdr_ps2x.fxc @@ -0,0 +1,78 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "BLOOMTYPE" "0..1" +// DYNAMIC: "FLOAT_BACK_BUFFER" "0..1" [ps20b] [ps30] [PC] +// DYNAMIC: "FLOAT_BACK_BUFFER" "0..0" [ps20b] [XBOX] + +#include "common_ps_fxc.h" + +sampler TexSampler : register( s0 ); +float4 params : register( c0 ); +float4 params2 : register( c1 ); +#define g_flBloomExp params2.x +#define g_flBloomSaturation params2.y + +struct PS_INPUT +{ + float2 coordTap0 : TEXCOORD0; + float2 coordTap1 : TEXCOORD1; + float2 coordTap2 : TEXCOORD2; + float2 coordTap3 : TEXCOORD3; +}; + +float4 Shape( float4 cColor ) +{ + #if ( BLOOMTYPE == 0 ) + { + float flLum = dot( cColor.xyz, params.xyz ); + cColor.rgb = pow( cColor.xyz, params.w ) * flLum; + } + #endif + + #if ( BLOOMTYPE == 1 ) + { + float flScale = 1.55f; // Color scale + float flBias = -0.09f; // Color bias + float flBrightnessClamp = 0.59f; // After scale and bias, clamp RGB values brighter than this + float flExp = g_flBloomExp; + cColor.rgb = pow( saturate( min( flBrightnessClamp, ( cColor.rgb * flScale ) + flBias ) ), flExp ); + } + #endif + + return cColor; +} + +float4 main( PS_INPUT i ) : COLOR +{ + float4 s0, s1, s2, s3; + + // Sample 4 taps + s0 = tex2D( TexSampler, i.coordTap0 ); + s1 = tex2D( TexSampler, i.coordTap1 ); + s2 = tex2D( TexSampler, i.coordTap2 ); + s3 = tex2D( TexSampler, i.coordTap3 ); + + #if ( FLOAT_BACK_BUFFER == 1 ) + { + // for float HDR mode, match the color space of the int render pass, to get identical bloom results + s0.rgb = SrgbLinearToGamma( saturate( s0.rgb ) ); + s1.rgb = SrgbLinearToGamma( saturate( s1.rgb ) ); + s2.rgb = SrgbLinearToGamma( saturate( s2.rgb ) ); + s3.rgb = SrgbLinearToGamma( saturate( s3.rgb ) ); + } + #endif + + float4 avgColor = ( s0 + s1 + s2 + s3 ) * 0.25f; + float fAvgLuminance = dot( avgColor.rgb, float3( 0.299, 0.587, 0.114 ) ); + avgColor = Shape( avgColor ); + + // Saturation + #if ( BLOOMTYPE == 1 ) + { + avgColor.rgb = lerp( dot( params.rgb, avgColor.rgb ), avgColor.rgb, g_flBloomSaturation ); + } + #endif + + avgColor.a = fAvgLuminance; + return FinalOutput( avgColor, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} diff --git a/materialsystem/stdshaders/Downsample_ps2x.fxc b/materialsystem/stdshaders/Downsample_ps2x.fxc new file mode 100644 index 00000000..6c59f23b --- /dev/null +++ b/materialsystem/stdshaders/Downsample_ps2x.fxc @@ -0,0 +1,30 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#include "common_ps_fxc.h" + +sampler TexSampler : register( s0 ); + +struct PS_INPUT +{ + float2 coordTap0 : TEXCOORD0; + float2 coordTap1 : TEXCOORD1; + float2 coordTap2 : TEXCOORD2; + float2 coordTap3 : TEXCOORD3; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float4 s0, s1, s2, s3; + + // Sample 4 taps + s0 = tex2D( TexSampler, i.coordTap0 ); + s1 = tex2D( TexSampler, i.coordTap1 ); + s2 = tex2D( TexSampler, i.coordTap2 ); + s3 = tex2D( TexSampler, i.coordTap3 ); + + // store grayscale version of buffer in alpha + float4 vResult = ( s0 + s1 + s2 + s3 ) * 0.25f; + vResult.a = dot( float3( 0.3f, 0.59f, 0.11f ), vResult.rgb ); + + return vResult; +} diff --git a/materialsystem/stdshaders/Downsample_vs20.fxc b/materialsystem/stdshaders/Downsample_vs20.fxc new file mode 100644 index 00000000..f742f85d --- /dev/null +++ b/materialsystem/stdshaders/Downsample_vs20.fxc @@ -0,0 +1,34 @@ +#include "common_vs_fxc.h" + +struct VS_INPUT +{ + float3 vPos : POSITION; + float2 vBaseTexCoord : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; + float2 coordTap0 : TEXCOORD0; + float2 coordTap1 : TEXCOORD1; + float2 coordTap2 : TEXCOORD2; + float2 coordTap3 : TEXCOORD3; +}; + +float2 vsTapOffs[4] : register ( SHADER_SPECIFIC_CONST_0 ); + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + o.projPos = float4( v.vPos, 1.0f ); + + o.coordTap0 = v.vBaseTexCoord + vsTapOffs[0]; + o.coordTap1 = v.vBaseTexCoord + vsTapOffs[1]; + o.coordTap2 = v.vBaseTexCoord + vsTapOffs[2]; + o.coordTap3 = v.vBaseTexCoord + vsTapOffs[3]; + + return o; +} + + diff --git a/materialsystem/stdshaders/Engine_Post_dx9.cpp b/materialsystem/stdshaders/Engine_Post_dx9.cpp new file mode 100644 index 00000000..1603a6f1 --- /dev/null +++ b/materialsystem/stdshaders/Engine_Post_dx9.cpp @@ -0,0 +1,658 @@ +//========= Copyright © 1996-2007, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#include "basevsshader.h" + +#include "screenspaceeffect_vs20.inc" +#include "Engine_Post_ps20.inc" +#include "Engine_Post_ps20b.inc" + +#include "..\materialsystem_global.h" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + +ConVar mat_screen_blur_override( "mat_screen_blur_override", "-1.0" ); +ConVar mat_depth_blur_focal_distance_override( "mat_depth_blur_focal_distance_override", "-1.0" ); +ConVar mat_depth_blur_strength_override( "mat_depth_blur_strength_override", "-1.0" ); +ConVar mat_grain_scale_override( "mat_grain_scale_override", "-1.0" ); +ConVar mat_local_contrast_scale_override( "mat_local_contrast_scale_override", "0.0" ); +ConVar mat_local_contrast_midtone_mask_override( "mat_local_contrast_midtone_mask_override", "-1.0" ); +ConVar mat_local_contrast_vignette_start_override( "mat_local_contrast_vignette_start_override", "-1.0" ); +ConVar mat_local_contrast_vignette_end_override( "mat_local_contrast_vignette_end_override", "-1.0" ); +ConVar mat_local_contrast_edge_scale_override( "mat_local_contrast_edge_scale_override", "-1000.0" ); + +DEFINE_FALLBACK_SHADER( Engine_Post, Engine_Post_dx9 ) +BEGIN_VS_SHADER_FLAGS( Engine_Post_dx9, "Engine post-processing effects (software anti-aliasing, bloom, color-correction", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( FBTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "_rt_FullFrameFB", "Full framebuffer texture" ) + SHADER_PARAM( AAENABLE, SHADER_PARAM_TYPE_BOOL, "0", "Enable software anti-aliasing" ) + SHADER_PARAM( AAINTERNAL1, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0]", "Internal anti-aliasing values set via material proxy" ) + SHADER_PARAM( AAINTERNAL2, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0]", "Internal anti-aliasing values set via material proxy" ) + SHADER_PARAM( AAINTERNAL3, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0]", "Internal anti-aliasing values set via material proxy" ) + SHADER_PARAM( BLOOMENABLE, SHADER_PARAM_TYPE_BOOL, "1", "Enable bloom" ) + SHADER_PARAM( BLOOMAMOUNT, SHADER_PARAM_TYPE_FLOAT, "1.0", "Bloom scale factor" ) + SHADER_PARAM( SCREENEFFECTTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "used for paint or vomit screen effect" ) + SHADER_PARAM( DEPTHBLURENABLE, SHADER_PARAM_TYPE_BOOL, "0", "Inexpensive depth-of-field substitute" ) + + SHADER_PARAM( ALLOWVIGNETTE, SHADER_PARAM_TYPE_BOOL, "0", "Allow vignette" ) + SHADER_PARAM( VIGNETTEENABLE, SHADER_PARAM_TYPE_BOOL, "0", "Enable vignette" ) + SHADER_PARAM( INTERNAL_VIGNETTETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "dev/vignette", "" ) + + SHADER_PARAM( ALLOWNOISE, SHADER_PARAM_TYPE_BOOL, "0", "Allow noise" ) + SHADER_PARAM( NOISEENABLE, SHADER_PARAM_TYPE_BOOL, "0", "Enable noise" ) + SHADER_PARAM( NOISESCALE, SHADER_PARAM_TYPE_FLOAT, "0", "Noise scale" ) + SHADER_PARAM( NOISETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Noise texture" ) + + SHADER_PARAM( ALLOWLOCALCONTRAST, SHADER_PARAM_TYPE_BOOL, "0", "Enable local contrast enhancement" ) + SHADER_PARAM( LOCALCONTRASTENABLE, SHADER_PARAM_TYPE_BOOL, "0", "Enable local contrast enhancement" ) + SHADER_PARAM( LOCALCONTRASTSCALE, SHADER_PARAM_TYPE_FLOAT, "0", "Local contrast scale" ) + SHADER_PARAM( LOCALCONTRASTMIDTONEMASK, SHADER_PARAM_TYPE_FLOAT, "0", "Local contrast midtone mask" ) + SHADER_PARAM( LOCALCONTRASTVIGNETTESTART, SHADER_PARAM_TYPE_BOOL, "0", "Enable local contrast enhancement" ) + SHADER_PARAM( LOCALCONTRASTVIGNETTEEND, SHADER_PARAM_TYPE_FLOAT, "0", "Local contrast scale" ) + SHADER_PARAM( LOCALCONTRASTEDGESCALE, SHADER_PARAM_TYPE_FLOAT, "0", "Local contrast midtone mask" ) + + SHADER_PARAM( BLURREDVIGNETTEENABLE, SHADER_PARAM_TYPE_BOOL, "0", "Enable blurred vignette" ) + SHADER_PARAM( BLURREDVIGNETTESCALE, SHADER_PARAM_TYPE_FLOAT, "0", "blurred vignette strength" ) + SHADER_PARAM( FADETOBLACKSCALE, SHADER_PARAM_TYPE_FLOAT, "0", "fade strength" ) + + SHADER_PARAM( DEPTHBLURFOCALDISTANCE, SHADER_PARAM_TYPE_FLOAT, "0", "Distance in dest-alpha space [0,1] of focal plane." ) + SHADER_PARAM( DEPTHBLURSTRENGTH, SHADER_PARAM_TYPE_FLOAT, "0", "Strength of depth-blur effect" ) + SHADER_PARAM( SCREENBLURSTRENGTH, SHADER_PARAM_TYPE_FLOAT, "0", "Full-screen blur factor" ) + + SHADER_PARAM( VOMITCOLOR1, SHADER_PARAM_TYPE_VEC3, "[0 0 0 0]", "1st vomit blend color" ) + SHADER_PARAM( VOMITCOLOR2, SHADER_PARAM_TYPE_VEC3, "[0 0 0 0]", "2st vomit blend color" ) + SHADER_PARAM( VOMITREFRACTSCALE, SHADER_PARAM_TYPE_FLOAT, "0.15", "vomit refract strength" ) + SHADER_PARAM( VOMITENABLE, SHADER_PARAM_TYPE_BOOL, "0", "Enable vomit refract" ) + + SHADER_PARAM( FADECOLOR, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0]", "viewfade color" ) + SHADER_PARAM( FADE, SHADER_PARAM_TYPE_INTEGER, "0", "fade type. 0 = off, 1 = lerp, 2 = modulate" ) + + SHADER_PARAM( TV_GAMMA, SHADER_PARAM_TYPE_INTEGER, "0", "0 default, 1 used for laying off 360 movies" ) + SHADER_PARAM( DESATURATEENABLE, SHADER_PARAM_TYPE_INTEGER, "0", "Desaturate with math, turns off color correction" ) + SHADER_PARAM( DESATURATION, SHADER_PARAM_TYPE_FLOAT, "0", "Desaturation Amount" ) + + // Tool color correction setup + SHADER_PARAM( TOOLMODE, SHADER_PARAM_TYPE_BOOL, "1", "tool mode" ) + SHADER_PARAM( TOOLCOLORCORRECTION, SHADER_PARAM_TYPE_FLOAT, "1", "tool color correction override" ) + SHADER_PARAM( WEIGHT_DEFAULT, SHADER_PARAM_TYPE_FLOAT, "1", "weight default" ) + SHADER_PARAM( WEIGHT0, SHADER_PARAM_TYPE_FLOAT, "1", "weight0" ) + SHADER_PARAM( WEIGHT1, SHADER_PARAM_TYPE_FLOAT, "1", "weight1" ) + SHADER_PARAM( WEIGHT2, SHADER_PARAM_TYPE_FLOAT, "1", "weight2" ) + SHADER_PARAM( WEIGHT3, SHADER_PARAM_TYPE_FLOAT, "1", "weight3" ) + SHADER_PARAM( NUM_LOOKUPS, SHADER_PARAM_TYPE_FLOAT, "0", "num_lookups" ) + SHADER_PARAM( TOOLTIME, SHADER_PARAM_TYPE_FLOAT, "0", "tooltime" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + if ( !params[ INTERNAL_VIGNETTETEXTURE ]->IsDefined() ) + { + params[ INTERNAL_VIGNETTETEXTURE ]->SetStringValue( "dev/vignette" ); + } + if ( !params[ AAENABLE ]->IsDefined() ) + { + params[ AAENABLE ]->SetIntValue( 0 ); + } + if ( !params[ AAINTERNAL1 ]->IsDefined() ) + { + params[ AAINTERNAL1 ]->SetVecValue( 0, 0, 0, 0 ); + } + if ( !params[ AAINTERNAL2 ]->IsDefined() ) + { + params[ AAINTERNAL2 ]->SetVecValue( 0, 0, 0, 0 ); + } + if ( !params[ AAINTERNAL3 ]->IsDefined() ) + { + params[ AAINTERNAL3 ]->SetVecValue( 0, 0, 0, 0 ); + } + if ( !params[ BLOOMENABLE ]->IsDefined() ) + { + params[ BLOOMENABLE ]->SetIntValue( 1 ); + } + if ( !params[ BLOOMAMOUNT ]->IsDefined() ) + { + params[ BLOOMAMOUNT ]->SetFloatValue( 1.0f ); + } + if ( !params[ DEPTHBLURENABLE ]->IsDefined() ) + { + params[ DEPTHBLURENABLE ]->SetIntValue( 0 ); + } + if ( !params[ ALLOWNOISE ]->IsDefined() ) + { + params[ ALLOWNOISE ]->SetIntValue( 1 ); + } + if ( !params[ NOISESCALE ]->IsDefined() ) + { + params[ NOISESCALE ]->SetFloatValue( 1.0f ); + } + if ( !params[ NOISEENABLE ]->IsDefined() ) + { + params[ NOISEENABLE ]->SetIntValue( 0 ); + } + if ( !params[ ALLOWVIGNETTE ]->IsDefined() ) + { + params[ ALLOWVIGNETTE ]->SetIntValue( 1 ); + } + if ( !params[ VIGNETTEENABLE ]->IsDefined() ) + { + params[ VIGNETTEENABLE ]->SetIntValue( 0 ); + } + if ( !params[ ALLOWLOCALCONTRAST ]->IsDefined() ) + { + params[ ALLOWLOCALCONTRAST ]->SetIntValue( 1 ); + } + if ( !params[ LOCALCONTRASTSCALE ]->IsDefined() ) + { + params[ LOCALCONTRASTSCALE ]->SetFloatValue( 1.0f ); + } + if ( !params[ LOCALCONTRASTMIDTONEMASK ]->IsDefined() ) + { + params[ LOCALCONTRASTMIDTONEMASK ]->SetFloatValue( 1000.0f ); + } + if ( !params[ LOCALCONTRASTENABLE ]->IsDefined() ) + { + params[ LOCALCONTRASTENABLE ]->SetIntValue( 0 ); + } + if ( !params[ LOCALCONTRASTVIGNETTESTART ]->IsDefined() ) + { + params[ LOCALCONTRASTVIGNETTESTART ]->SetFloatValue( 0.7f ); + } + if ( !params[ LOCALCONTRASTVIGNETTEEND ]->IsDefined() ) + { + params[ LOCALCONTRASTVIGNETTEEND ]->SetFloatValue( 1.0f ); + } + if ( !params[ LOCALCONTRASTEDGESCALE ]->IsDefined() ) + { + params[ LOCALCONTRASTEDGESCALE ]->SetFloatValue( 0.0f ); + } + if ( !params[ BLURREDVIGNETTEENABLE ]->IsDefined() ) + { + params[ BLURREDVIGNETTEENABLE ]->SetIntValue( 0 ); + } + if ( !params[ BLURREDVIGNETTESCALE ]->IsDefined() ) + { + params[ BLURREDVIGNETTESCALE ]->SetFloatValue( 0.0f ); + } + if ( !params[ FADETOBLACKSCALE ]->IsDefined() ) + { + params[ FADETOBLACKSCALE ]->SetFloatValue( 0.0f ); + } + if ( !params[ DEPTHBLURFOCALDISTANCE ]->IsDefined() ) + { + params[ DEPTHBLURFOCALDISTANCE ]->SetFloatValue( 0.0f ); + } + if ( !params[ DEPTHBLURSTRENGTH ]->IsDefined() ) + { + params[ DEPTHBLURSTRENGTH ]->SetFloatValue( 0.0f ); + } + if ( !params[ SCREENBLURSTRENGTH ]->IsDefined() ) + { + params[ SCREENBLURSTRENGTH ]->SetFloatValue( 0.0f ); + } + if ( !params[ TOOLMODE ]->IsDefined() ) + { + params[ TOOLMODE ]->SetIntValue( 0 ); + } + if ( !params[ TOOLCOLORCORRECTION ]->IsDefined() ) + { + params[ TOOLCOLORCORRECTION ]->SetFloatValue( 0.0f ); + } + if ( !params[ VOMITENABLE ]->IsDefined() ) + { + params[ VOMITENABLE ]->SetIntValue( 0 ); + } + if ( !params[ VOMITREFRACTSCALE ]->IsDefined() ) + { + params[ VOMITREFRACTSCALE ]->SetFloatValue( 0.15f ); + } + if ( !params[ VOMITCOLOR1 ]->IsDefined() ) + { + params[ VOMITCOLOR1 ]->SetVecValue( 1.0, 1.0, 0.0 ); + } + if ( !params[ VOMITCOLOR2 ]->IsDefined() ) + { + params[ VOMITCOLOR2 ]->SetVecValue( 0.0, 1.0, 0.0 ); + } + if ( !params[ FADE ]->IsDefined() ) + { + params[ FADE ]->SetIntValue( 0 ); + } + if ( !params[ FADECOLOR ]->IsDefined() ) + { + params[ FADECOLOR ]->SetVecValue( 0.0f, 0.0f, 0.0f, 0.0f ); + } + if ( !params[ TV_GAMMA ]->IsDefined() ) + { + params[ TV_GAMMA ]->SetIntValue( 0 ); + } + if ( !params[ DESATURATEENABLE ]->IsDefined() ) + { + params[ DESATURATEENABLE ]->SetIntValue( 0 ); + } + if ( !params[ DESATURATION ]->IsDefined() ) + { + params[ DESATURATION ]->SetFloatValue( 0.0f ); + } + + SET_FLAGS2( MATERIAL_VAR2_NEEDS_FULL_FRAME_BUFFER_TEXTURE ); + } + + SHADER_FALLBACK + { + // This shader should not be *used* unless we're >= DX9 (bloomadd.vmt/screenspace_general_dx8 should be used for DX8) + return 0; + } + + SHADER_INIT + { + if ( params[BASETEXTURE]->IsDefined() ) + { + LoadTexture( BASETEXTURE ); + } + + if ( params[FBTEXTURE]->IsDefined() ) + { + LoadTexture( FBTEXTURE ); + } + + if ( params[SCREENEFFECTTEXTURE]->IsDefined() ) + { + LoadTexture( SCREENEFFECTTEXTURE ); + } + + if ( params[NOISETEXTURE]->IsDefined() ) + { + LoadTexture( NOISETEXTURE ); + } + + if ( params[INTERNAL_VIGNETTETEXTURE]->IsDefined() ) + { + LoadTexture( INTERNAL_VIGNETTETEXTURE ); + } + } + + SHADER_DRAW + { + bool bToolMode = params[TOOLMODE]->GetIntValue() != 0; + bool bDepthBlurEnable = params[ DEPTHBLURENABLE ]->GetIntValue() != 0; + + SHADOW_STATE + { + // This shader uses opaque blending, but needs to match the behaviour of bloom_add/screen_spacegeneral, + // which uses additive blending (and is used when bloom is enabled but col-correction and AA are not). + // BUT! + // Hardware sRGB blending is incorrect (on pre-DX10 cards, sRGB values are added directly). + // SO... + // When doing the bloom addition in the pixel shader, we need to emulate that incorrect + // behaviour - by turning sRGB read OFF for the FB texture and by turning sRGB write OFF + // (which is fine, since the AA process works better on an sRGB framebuffer than a linear + // one; gamma colours more closely match luminance perception. The color-correction process + // has always taken gamma-space values as input anyway). + + pShaderShadow->EnableBlending( false ); + + // The (sRGB) bloom texture is bound to sampler 0 + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, false ); + pShaderShadow->EnableSRGBWrite( false ); + + // The (sRGB) full framebuffer texture is bound to sampler 1: + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, false ); + + // Up to 4 (sRGB) color-correction lookup textures are bound to samplers 2-5: + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, false ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER3, false ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER4, false ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER5, false ); + + // Noise + pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER6, false ); + + // Vignette + pShaderShadow->EnableTexture( SHADER_SAMPLER7, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER7, false ); + + // Screen effect texture + pShaderShadow->EnableTexture( SHADER_SAMPLER8, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER8, false ); + + pShaderShadow->EnableSRGBWrite( false ); + + int format = VERTEX_POSITION; + int numTexCoords = 1; + int * pTexCoordDimensions = NULL; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( format, numTexCoords, pTexCoordDimensions, userDataSize ); + + DECLARE_STATIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + SET_STATIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( engine_post_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( TOOL_MODE, bToolMode ); + SET_STATIC_PIXEL_SHADER_COMBO( DEPTH_BLUR_ENABLE, bDepthBlurEnable ); + SET_STATIC_PIXEL_SHADER( engine_post_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( engine_post_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( TOOL_MODE, bToolMode ); + SET_STATIC_PIXEL_SHADER_COMBO( DEPTH_BLUR_ENABLE, false ); + SET_STATIC_PIXEL_SHADER( engine_post_ps20 ); + } + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, -1 ); + + // FIXME: need to set FBTEXTURE to be point-sampled (will speed up this shader significantly on 360) + // and assert that it's set to SHADER_TEXWRAPMODE_CLAMP (since the shader will sample offscreen) + BindTexture( SHADER_SAMPLER1, FBTEXTURE, -1 ); + + ShaderColorCorrectionInfo_t ccInfo = { false, 0, 1.0f, { 1.0f, 1.0f, 1.0f, 1.0f } }; + + float flTime; + if ( bToolMode ) + { + flTime = params[TOOLTIME]->GetFloatValue(); + } + else + { + flTime = pShaderAPI->CurrentTime(); + } + + // PC, ps20b has a desaturation control that overrides color correction + bool bDesaturateEnable = bToolMode && ( params[DESATURATEENABLE]->GetIntValue() != 0 ) && g_pHardwareConfig->SupportsPixelShaders_2_b() && IsPC(); + + float vPsConst16[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vPsConst16[0] = params[ DESATURATION ]->GetFloatValue(); + vPsConst16[1] = ( params[FADE]->GetIntValue() == 2 ) ? 1.0f : 0.0f; // Enable lerping to ( color * fadecolor ) for FADE_COLOR=2 + pShaderAPI->SetPixelShaderConstant( 16, vPsConst16, 1 ); + + if ( params[FADE]->GetIntValue() == 0 ) + { + // Not fading, so set the constant to cause nothing to change about the pixel color + float vConst[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + pShaderAPI->SetPixelShaderConstant( 15, vConst ); + } + else + { + pShaderAPI->SetPixelShaderConstant( 15, params[ FADECOLOR ]->GetVecValue(), 1 ); + } + + if ( !bDesaturateEnable ) // set up color correction + { + bool bToolColorCorrection = params[TOOLCOLORCORRECTION]->GetIntValue() != 0; + if ( bToolColorCorrection ) + { + ccInfo.m_bIsEnabled = true; + + ccInfo.m_nLookupCount = (int) params[NUM_LOOKUPS]->GetFloatValue(); + ccInfo.m_flDefaultWeight = params[WEIGHT_DEFAULT]->GetFloatValue(); + ccInfo.m_pLookupWeights[0] = params[WEIGHT0]->GetFloatValue(); + ccInfo.m_pLookupWeights[1] = params[WEIGHT1]->GetFloatValue(); + ccInfo.m_pLookupWeights[2] = params[WEIGHT2]->GetFloatValue(); + ccInfo.m_pLookupWeights[3] = params[WEIGHT3]->GetFloatValue(); + } + else + { + pShaderAPI->GetCurrentColorCorrection( &ccInfo ); + } + } + + int colCorrectNumLookups = MIN( ccInfo.m_nLookupCount, 3 ); + for ( int i = 0; i < colCorrectNumLookups; i++ ) + { + pShaderAPI->BindStandardTexture( (Sampler_t)(SHADER_SAMPLER2 + i), (StandardTextureId_t)(TEXTURE_COLOR_CORRECTION_VOLUME_0 + i) ); + } + + // Upload 1-pixel X&Y offsets [ (+dX,0,+dY,-dX) is chosen to work with the allowed ps20 swizzles ] + // The shader will sample in a cross (up/down/left/right from the current sample), for 5-tap + // (quality 0) mode and add another 4 samples in a diagonal cross, for 9-tap (quality 1) mode + ITexture * pTarget = params[FBTEXTURE]->GetTextureValue(); + int width = pTarget->GetActualWidth(); + int height = pTarget->GetActualHeight(); + float dX = 1.0f / width; + float dY = 1.0f / height; + float offsets[4] = { +dX, 0, +dY, -dX }; + pShaderAPI->SetPixelShaderConstant( 0, &offsets[0], 1 ); + + // Upload AA tweakables: + // x - strength (this can be used to toggle the AA off, or to weaken it where pathological cases are showing) + // y - reduction of 1-pixel-line blurring (blurring of 1-pixel lines causes issues, so it's tunable) + // z - edge threshold multiplier (default 1.0, < 1.0 => more edges softened, > 1.0 => fewer edges softened) + // w - tap offset multiplier (default 1.0, < 1.0 => sharper image, > 1.0 => blurrier image) + float tweakables[4] = { params[ AAINTERNAL1 ]->GetVecValue()[0], + params[ AAINTERNAL1 ]->GetVecValue()[1], + params[ AAINTERNAL3 ]->GetVecValue()[0], + params[ AAINTERNAL3 ]->GetVecValue()[1] }; + pShaderAPI->SetPixelShaderConstant( 1, &tweakables[0], 1 ); + + // Upload AA UV transform (converts bloom texture UVs to framebuffer texture UVs) + // NOTE: we swap the order of the z and w components since 'wz' is an allowed ps20 swizzle, but 'zw' is not: + float uvTrans[4] = { params[ AAINTERNAL2 ]->GetVecValue()[0], + params[ AAINTERNAL2 ]->GetVecValue()[1], + params[ AAINTERNAL2 ]->GetVecValue()[3], + params[ AAINTERNAL2 ]->GetVecValue()[2] }; + pShaderAPI->SetPixelShaderConstant( 2, &uvTrans[0], 1 ); + + // Upload color-correction weights: + pShaderAPI->SetPixelShaderConstant( 3, &ccInfo.m_flDefaultWeight ); + pShaderAPI->SetPixelShaderConstant( 4, ccInfo.m_pLookupWeights ); + + int aaEnabled = ( IsX360() && ( params[ AAINTERNAL1 ]->GetVecValue()[0] != 0.0f ) ) ? 1 : 0; + int bloomEnabled = ( params[ BLOOMENABLE ]->GetIntValue() == 0 ) ? 0 : 1; + int colCorrectEnabled = ccInfo.m_bIsEnabled; + + float flBloomFactor = bloomEnabled ? 1.0f : 0.0f; + flBloomFactor *= params[BLOOMAMOUNT]->GetFloatValue(); + float bloomConstant[4] = + { + flBloomFactor, + params[ SCREENBLURSTRENGTH ]->GetFloatValue(), + params[ DEPTHBLURFOCALDISTANCE ]->GetFloatValue(), + params[ DEPTHBLURSTRENGTH ]->GetFloatValue() + }; + + if ( mat_screen_blur_override.GetFloat() >= 0.0f ) + { + bloomConstant[1] = mat_screen_blur_override.GetFloat(); + } + if ( mat_depth_blur_focal_distance_override.GetFloat() >= 0.0f ) + { + bloomConstant[2] = mat_depth_blur_focal_distance_override.GetFloat(); + } +#ifdef _X360 + bloomConstant[3] = 0.0f; // Depth blur is currently broken on X360 because we're not writing out the depth scale properly +#else // !_X360 + if ( mat_depth_blur_strength_override.GetFloat() >= 0.0f ) + { + bloomConstant[3] = mat_depth_blur_strength_override.GetFloat(); + } +#endif // _X360 + + pShaderAPI->SetPixelShaderConstant( 5, bloomConstant ); + + // Vignette + bool bVignetteEnable = ( params[ VIGNETTEENABLE ]->GetIntValue() != 0 ) && ( params[ ALLOWVIGNETTE ]->GetIntValue() != 0 ); + if ( bVignetteEnable ) + { + BindTexture( SHADER_SAMPLER7, INTERNAL_VIGNETTETEXTURE ); + } + + // Noise + bool bNoiseEnable = ( params[ NOISEENABLE ]->GetIntValue() != 0 ) && ( params[ ALLOWNOISE ]->GetIntValue() != 0 ); + + int nFbTextureHeight = params[FBTEXTURE]->GetTextureValue()->GetActualHeight(); + if ( nFbTextureHeight < 720 ) + { + // Disable noise at low resolutions + bNoiseEnable = false; + } + + if ( bNoiseEnable ) + { + BindTexture( SHADER_SAMPLER6, NOISETEXTURE ); + + // Noise scale + float vPsConst6[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vPsConst6[0] = params[ NOISESCALE ]->GetFloatValue(); + if ( mat_grain_scale_override.GetFloat() != -1.0f ) + { + vPsConst6[0] = mat_grain_scale_override.GetFloat(); + } + + if ( IsX360() ) + { + vPsConst6[0] *= 0.15f; + } + + if ( vPsConst6[0] <= 0.0f ) + { + bNoiseEnable = false; + } + + pShaderAPI->SetPixelShaderConstant( 6, vPsConst6 ); + + // Time % 1000 for scrolling + float vPsConst[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vPsConst[0] = flTime; + vPsConst[0] -= (float)( (int)( vPsConst[0] / 1000.0f ) ) * 1000.0f; + pShaderAPI->SetPixelShaderConstant( 7, vPsConst, 1 ); + } + + // Local Contrast + bool bLocalContrastEnable = ( params[ LOCALCONTRASTENABLE ]->GetIntValue() != 0 ) && ( params[ ALLOWLOCALCONTRAST ]->GetIntValue() != 0 ); + bool bBlurredVignetteEnable = ( bLocalContrastEnable ) && ( params[ BLURREDVIGNETTEENABLE ]->GetIntValue() != 0 ); + + if ( bLocalContrastEnable ) + { + // Contrast scale + float vPsConst[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vPsConst[0] = params[ LOCALCONTRASTSCALE ]->GetFloatValue(); + if ( mat_local_contrast_scale_override.GetFloat() != 0.0f ) + { + vPsConst[0] = mat_local_contrast_scale_override.GetFloat(); + } + vPsConst[1] = params[ LOCALCONTRASTMIDTONEMASK ]->GetFloatValue(); + if ( mat_local_contrast_midtone_mask_override.GetFloat() >= 0.0f ) + { + vPsConst[1] = mat_local_contrast_midtone_mask_override.GetFloat(); + } + vPsConst[2] = params[ BLURREDVIGNETTESCALE ]->GetFloatValue(); + pShaderAPI->SetPixelShaderConstant( 8, vPsConst, 1 ); + + vPsConst[0] = params[ LOCALCONTRASTVIGNETTESTART ]->GetFloatValue(); + if ( mat_local_contrast_vignette_start_override.GetFloat() >= 0.0f ) + { + vPsConst[0] = mat_local_contrast_vignette_start_override.GetFloat(); + } + vPsConst[1] = params[ LOCALCONTRASTVIGNETTEEND ]->GetFloatValue(); + if ( mat_local_contrast_vignette_end_override.GetFloat() >= 0.0f ) + { + vPsConst[1] = mat_local_contrast_vignette_end_override.GetFloat(); + } + vPsConst[2] = params[ LOCALCONTRASTEDGESCALE ]->GetFloatValue(); + if ( mat_local_contrast_edge_scale_override.GetFloat() >= -1.0f ) + { + vPsConst[2] = mat_local_contrast_edge_scale_override.GetFloat(); + } + pShaderAPI->SetPixelShaderConstant( 9, vPsConst, 1 ); + } + + // fade to black + float vPsConst[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vPsConst[0] = params[ FADETOBLACKSCALE ]->GetFloatValue(); + pShaderAPI->SetPixelShaderConstant( 10, vPsConst, 1 ); + + bool bVomitEnable = ( params[ VOMITENABLE ]->GetIntValue() != 0 ); + if ( bVomitEnable ) + { + BindTexture( SHADER_SAMPLER8, SCREENEFFECTTEXTURE ); + + params[ VOMITCOLOR1 ]->GetVecValue( vPsConst, 3 ); + vPsConst[3] = params[ VOMITREFRACTSCALE ]->GetFloatValue(); + pShaderAPI->SetPixelShaderConstant( 11, vPsConst, 1 ); + params[ VOMITCOLOR2 ]->GetVecValue( vPsConst, 3 ); + vPsConst[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( 12, vPsConst, 1 ); + + // Get viewport and render target dimensions and set shader constant to do a 2D mad + int nViewportX, nViewportY, nViewportWidth, nViewportHeight; + pShaderAPI->GetCurrentViewport( nViewportX, nViewportY, nViewportWidth, nViewportHeight ); + + int nRtWidth, nRtHeight; + pShaderAPI->GetCurrentRenderTargetDimensions( nRtWidth, nRtHeight ); + + float vViewportMad[4]; + + // screen->viewport transform + vViewportMad[0] = ( float )nRtWidth / ( float )nViewportWidth; + vViewportMad[1] = ( float )nRtHeight / ( float )nViewportHeight; + vViewportMad[2] = -( float )nViewportX / ( float )nViewportWidth; + vViewportMad[3] = -( float )nViewportY / ( float )nViewportHeight; + pShaderAPI->SetPixelShaderConstant( 13, vViewportMad, 1 ); + + // viewport->screen transform + vViewportMad[0] = ( float )nViewportWidth / ( float )nRtWidth; + vViewportMad[1] = ( float )nViewportHeight / ( float )nRtHeight; + vViewportMad[2] = ( float )nViewportX / ( float )nRtWidth; + vViewportMad[3] = ( float )nViewportY / ( float )nRtHeight; + pShaderAPI->SetPixelShaderConstant( 14, vViewportMad, 1 ); + } + + if ( !colCorrectEnabled ) + { + colCorrectNumLookups = 0; + } + + bool bConvertFromLinear = ( g_pHardwareConfig->GetHDRType() == HDR_TYPE_FLOAT ); + + // JasonM - double check this if the SFM needs to use the engine post FX clip in main + bool bConvertToLinear = bToolMode && bConvertFromLinear && ( g_pHardwareConfig->GetHDRType() == HDR_TYPE_FLOAT ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( engine_post_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( AA_ENABLE, aaEnabled ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( COL_CORRECT_NUM_LOOKUPS, colCorrectNumLookups ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( CONVERT_FROM_LINEAR, bConvertFromLinear ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( CONVERT_TO_LINEAR, bConvertToLinear ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NOISE_ENABLE, bNoiseEnable ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( VIGNETTE_ENABLE, bVignetteEnable ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( LOCAL_CONTRAST_ENABLE, bLocalContrastEnable ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( BLURRED_VIGNETTE_ENABLE, bBlurredVignetteEnable ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( VOMIT_ENABLE, bVomitEnable ); +#ifndef _X360 + SET_DYNAMIC_PIXEL_SHADER_COMBO( TV_GAMMA, params[TV_GAMMA]->GetIntValue() && bToolMode ? 1 : 0 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( DESATURATEENABLE, bDesaturateEnable ); +#endif + SET_DYNAMIC_PIXEL_SHADER( engine_post_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( engine_post_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( AA_ENABLE, aaEnabled ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( COL_CORRECT_NUM_LOOKUPS, colCorrectNumLookups ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( VOMIT_ENABLE, bVomitEnable ); + SET_DYNAMIC_PIXEL_SHADER( engine_post_ps20 ); + } + + DECLARE_DYNAMIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + } + Draw(); + } +END_SHADER diff --git a/materialsystem/stdshaders/Engine_Post_ps2x.fxc b/materialsystem/stdshaders/Engine_Post_ps2x.fxc new file mode 100644 index 00000000..81f600f1 --- /dev/null +++ b/materialsystem/stdshaders/Engine_Post_ps2x.fxc @@ -0,0 +1,440 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// FIXMEL4DTOMAINMERGE +// Need to re-enable bloom and disable other L4D-only features in here and the cpp file. + +// STATIC: "TOOL_MODE" "0..1" +// STATIC: "DEPTH_BLUR_ENABLE" "0..1" + +// DYNAMIC: "AA_ENABLE" "0..0" [PC] +// DYNAMIC: "AA_ENABLE" "0..1" [XBOX] + +// DYNAMIC: "COL_CORRECT_NUM_LOOKUPS" "0..3" + +// DYNAMIC: "CONVERT_FROM_LINEAR" "0..1" [ps20b] [ps30] [PC] +// DYNAMIC: "CONVERT_TO_LINEAR" "0..1" [ps20b] [ps30] [PC] +// DYNAMIC: "CONVERT_FROM_LINEAR" "0..0" [ps20b] [XBOX] +// DYNAMIC: "CONVERT_TO_LINEAR" "0..0" [ps20b] [XBOX] +// SKIP: ( $CONVERT_FROM_LINEAR == 0 ) && ( $CONVERT_TO_LINEAR == 1 ) +// SKIP: ( $TOOL_MODE == 0 ) && ( $CONVERT_TO_LINEAR == 1 ) + +// DYNAMIC: "NOISE_ENABLE" "0..1" [ps20b] [ps30] +// DYNAMIC: "VIGNETTE_ENABLE" "0..1" [ps20b] [ps30] +// DYNAMIC: "LOCAL_CONTRAST_ENABLE" "0..1" [ps20b] [ps30] +// DYNAMIC: "BLURRED_VIGNETTE_ENABLE" "0..1" [ps20b] [ps30] +// DYNAMIC: "VOMIT_ENABLE" "0..1" +// SKIP: ( $LOCAL_CONTRAST_ENABLE == 0 ) && ( $BLURRED_VIGNETTE_ENABLE == 1 ) + +// DYNAMIC: "TV_GAMMA" "0..1" [ps20b] [PC] +// DYNAMIC: "DESATURATEENABLE" "0..1" [ps20b] [PC] +// SKIP: ( $TOOL_MODE == 0 ) && $TV_GAMMA +// SKIP: ( $TOOL_MODE == 0 ) && $DESATURATEENABLE + +#include "common_ps_fxc.h" + +sampler BaseTextureSampler : register( s0 ); +sampler FBTextureSampler : register( s1 ); +sampler ColorCorrectionVolumeTexture0 : register( s2 ); +sampler ColorCorrectionVolumeTexture1 : register( s3 ); +sampler ColorCorrectionVolumeTexture2 : register( s4 ); +sampler ColorCorrectionVolumeTexture3 : register( s5 ); +sampler NoiseSampler : register( s6 ); +sampler VignetteSampler : register( s7 ); +sampler ScreenEffectSampler : register( s8 ); // used for vomit/paint screen particle effects + +float4 psTapOffs_Packed : register( c0 ); // psTapOffs_packed contains 1-pixel offsets: ( +dX, 0, +dY, -dX ) +float4 tweakables : register( c1 ); // (x - AA strength/unused) (y - reduction of 1-pixel-line blur) + // (z - edge threshold multipler) (w - tap offset multiplier) +float4 uvTransform : register( c2 ); // Transform BaseTexture UVs for use with the FBTexture + +float ColorCorrectionDefaultWeight : register( c3 ); +float4 ColorCorrectionVolumeWeights : register( c4 ); + +// Bloom & Depth Blur parameters +// x: bloom amount; multiply bloom downscale buffer by this value and add to base color +// y: bloom lerp amount; lerp between base color and blurred bloom buffer with this factor (allows for color bleeding in dark areas) +// z: depth blur focal plane distance. Value is in dest alpha space [0,1], not world units. +// w: depth blur scale value; scale distance from focal plane by this amount +float4 BloomParameters : register( c5 ); +#define g_flBloomAmount ( BloomParameters.x ) +#define g_flBloomLerpFactor ( BloomParameters.y ) +#define g_flDepthBlurFocalDistance ( BloomParameters.z ) +#define g_flDepthBlurScale ( BloomParameters.w ) + +float g_flNoiseScalar : register( c6 ); +float g_flTime : register( c7 ); +float4 g_vLocalContrastParams : register( c8 ); +#define g_flLocalContrastStrength g_vLocalContrastParams.x +#define g_flLocalContrastMidToneMask g_vLocalContrastParams.y +#define g_flBlurredVignetteStrength g_vLocalContrastParams.z + +float4 g_vLocalContrastVignetteParams : register( c9 ); +#define g_flLocalContrastVignetteStart g_vLocalContrastVignetteParams.x +#define g_flLocalContrastVignetteEnd g_vLocalContrastVignetteParams.y +#define g_flLocalContrastEdgeStrength g_vLocalContrastVignetteParams.z + +float g_flFadeToBlackStrength : register( c10 ); + +float4 g_vVomitColor[2] : register( c11 ); +#define g_flVomitRefractStrength g_vVomitColor[0].a + +float4 g_vViewportTransform : register( c13 ); +float4 g_vInvViewportTransform : register( c14 ); + +float4 g_vViewFadeColor : register( c15 ); + +float2 g_c16 : register( c16 ); +#define g_flDesaturation g_c16.x +#define g_flFadeMode2 g_c16.y + +float Luminance( float3 cColor ) +{ + float3 tmpv = { 0.2125, 0.7154, 0.0721 }; + float flLuminance = dot( cColor.rgb, tmpv.rgb ); + return flLuminance; +} + +float4 GetBloomColor( float2 bloomUV ) +{ + return tex2D( BaseTextureSampler, bloomUV ); +} + +float4 PerformColorCorrection( float4 outColor ) +{ + if (COL_CORRECT_NUM_LOOKUPS > 0) + { + // NOTE: This code requires the color correction texture to be 32 units to be correct. + // This code will cause (0,0,0) to be read from 0.5f/32 + // and (1,1,1) to be read from 31.5f/32 + float4 offsetOutColor = outColor*(31.0f/32.0f) + (0.5f/32.0f); + + outColor.rgb = outColor.rgb * ColorCorrectionDefaultWeight; + outColor.rgb += tex3D( ColorCorrectionVolumeTexture0, offsetOutColor.rgb ) * ColorCorrectionVolumeWeights.x; + if (COL_CORRECT_NUM_LOOKUPS > 1) + { + outColor.rgb += tex3D( ColorCorrectionVolumeTexture1, offsetOutColor.rgb ) * ColorCorrectionVolumeWeights.y; + if (COL_CORRECT_NUM_LOOKUPS > 2) + { + outColor.rgb += tex3D( ColorCorrectionVolumeTexture2, offsetOutColor.rgb ) * ColorCorrectionVolumeWeights.z; + if (COL_CORRECT_NUM_LOOKUPS > 3) + { + outColor.rgb += tex3D( ColorCorrectionVolumeTexture3, offsetOutColor.rgb ) * ColorCorrectionVolumeWeights.w; + } + } + } + } + + return outColor; +} + +float3 PerformVomitBlend( float3 vRefractParams, float3 vFullResColor, float3 vBlurredColor ) +{ + float3 vVomitColor = lerp( g_vVomitColor[0].rgb, g_vVomitColor[1].rgb, vRefractParams.z ); // vomit tint + + vFullResColor.rgb *= lerp( float3( 1, 1, 1 ), vVomitColor, vRefractParams.z ); // vomit tint full-res buffer + vFullResColor.rgb = lerp ( vFullResColor.rgb, vVomitColor.rgb * vBlurredColor.rgb, vRefractParams.z ); + return vFullResColor.rgb; +} + +float2 PerformUVTransform( float2 bloomUVs ) +{ + // NOTE: 'wz' is used since 'zw' is not a valid swizzle for ps20 shaders + return bloomUVs*uvTransform.wz + uvTransform.xy; +} + +// Apply TV Gamma for movie layoff specific to 360 TV movie playback path +float3 SrgbGammaToTvGamma( float3 cInput ) +{ + float3 cLinear = SrgbGammaToLinear( cInput ); + return pow( cLinear, 1.0f / 2.5f ); +} + + +struct PS_INPUT +{ + float2 baseTexCoord : TEXCOORD0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float4 fbTexCoord = 0; + #if !defined( SHADER_MODEL_PS_2_0 ) + { + fbTexCoord.xy = PerformUVTransform( i.baseTexCoord ); + fbTexCoord.zw = i.baseTexCoord; + } + #else + { + fbTexCoord.xy = PerformUVTransform( i.baseTexCoord ); + } + #endif + + float4 cBloomBlurredLum = GetBloomColor( i.baseTexCoord ); // bloom color and blurred luminance in alpha + float4 vVomitRefractParams; + #if ( VOMIT_ENABLE == 1 ) + { + // perturb texture coordinate + vVomitRefractParams = tex2D( ScreenEffectSampler, i.baseTexCoord ); + fbTexCoord = fbTexCoord + g_flVomitRefractStrength * ( vVomitRefractParams.xyxy - 0.5 ); + + #if !defined( SHADER_MODEL_PS_2_0 ) + { + // screen coords -> viewport coords + float4 vNormalizedTexCoord = g_vViewportTransform.xyxy * fbTexCoord + g_vViewportTransform.zwzw; + // mirrored repeat texcoord math doesn't fit into 2.0 + vNormalizedTexCoord = min( 2.0 - vNormalizedTexCoord, abs( vNormalizedTexCoord ) ); + // viewport coords -> screen coords + fbTexCoord = g_vInvViewportTransform.xyxy * vNormalizedTexCoord + g_vInvViewportTransform.zwzw; + + cBloomBlurredLum = GetBloomColor( fbTexCoord.zw ); // fetch again with perturbed texcoords + } + #else + { + cBloomBlurredLum = GetBloomColor( fbTexCoord.xy ); // fetch again with perturbed texcoords + } + #endif + } + #endif + + float4 rawColor = tex2D( FBTextureSampler, fbTexCoord.xy ).rgba; + float3 baseColor = rawColor.rgb; + float depthValue = rawColor.a; + + #if ( CONVERT_FROM_LINEAR == 1 ) + { + baseColor.rgb = SrgbLinearToGamma( baseColor.rgb ); + } + #endif + + float4 outColor = float4( baseColor, 1 ); + + #if ( AA_ENABLE == 1 ) + { + float3 up; + float3 dn; + float3 lf; + float3 rt; + float3 uplf; + float3 uprt; + float3 dnlf; + float3 dnrt; + + #if defined( _X360 ) + asm + { + tfetch2D up.xyz, fbTexCoord.xy, FBTextureSampler, OffsetX = 0.0, OffsetY = -1.0, MagFilter = point, MinFilter = point, MipFilter = point + tfetch2D dn.xyz, fbTexCoord.xy, FBTextureSampler, OffsetX = 0.0, OffsetY = 1.0, MagFilter = point, MinFilter = point, MipFilter = point + tfetch2D lf.xyz, fbTexCoord.xy, FBTextureSampler, OffsetX = -1.0, OffsetY = 0.0, MagFilter = point, MinFilter = point, MipFilter = point + tfetch2D rt.xyz, fbTexCoord.xy, FBTextureSampler, OffsetX = 1.0, OffsetY = 0.0, MagFilter = point, MinFilter = point, MipFilter = point + + tfetch2D uplf.xyz, fbTexCoord.xy, FBTextureSampler, OffsetX = -1.0, OffsetY = -1.0, MagFilter = point, MinFilter = point, MipFilter = point + tfetch2D uprt.xyz, fbTexCoord.xy, FBTextureSampler, OffsetX = 1.0, OffsetY = -1.0, MagFilter = point, MinFilter = point, MipFilter = point + tfetch2D dnlf.xyz, fbTexCoord.xy, FBTextureSampler, OffsetX = -1.0, OffsetY = 1.0, MagFilter = point, MinFilter = point, MipFilter = point + tfetch2D dnrt.xyz, fbTexCoord.xy, FBTextureSampler, OffsetX = 1.0, OffsetY = 1.0, MagFilter = point, MinFilter = point, MipFilter = point + }; + #else + { + // psTapOffs_packed contains 1-pixel offsets: ( +dX, 0, +dY, -dX ) + float4 texelDelta = psTapOffs_Packed.xyzw; + dn = tex2D( FBTextureSampler, fbTexCoord.xy + texelDelta.yz ).rgb; // ( 0,+1) + rt = tex2D( FBTextureSampler, fbTexCoord.xy + texelDelta.xy ).rgb; // (+1, 0) + up = tex2D( FBTextureSampler, fbTexCoord.xy - texelDelta.yz ).rgb; // ( 0,-1) + lf = tex2D( FBTextureSampler, fbTexCoord.xy - texelDelta.xy ).rgb; // (-1, 0) + dnlf = tex2D( FBTextureSampler, fbTexCoord.xy + texelDelta.wz ).rgb; // (-1,+1) + uprt = tex2D( FBTextureSampler, fbTexCoord.xy - texelDelta.wz ).rgb; // (+1,-1) + texelDelta.y = texelDelta.z; // Can't quite get all 8 sample offsets from a single float4 with the allowed swizzles! + uplf = tex2D( FBTextureSampler, fbTexCoord.xy + texelDelta.xy ).rgb; // (+1,+1) + dnrt = tex2D( FBTextureSampler, fbTexCoord.xy - texelDelta.xy ).rgb; // (-1,-1) + } + #endif + + // Generate the edge mask + float flBaseLum = Luminance( baseColor.rgb ); + float flEdge = saturate( abs( Luminance( dn.rgb ) - flBaseLum ) - 0.1 ); + flEdge += saturate( abs( Luminance( up.rgb ) - flBaseLum ) - 0.1 ); + flEdge += saturate( abs( Luminance( lf.rgb ) - flBaseLum ) - 0.1 ); + flEdge += saturate( abs( Luminance( rt.rgb ) - flBaseLum ) - 0.1 ); + flEdge *= 5.0; + #if defined( _X360 ) + flEdge *= 4.0; // Magic number to compensate for 360 gamma space + #endif + + // Average full 3x3 neighborhood of pixels giving more weight to the center sample + float3 vBlurColor = ( baseColor.rgb * 4.0f ) + up.rgb + dn.rgb + lf.rgb + rt.rgb + dnrt.rgb + uprt.rgb + dnlf.rgb + uplf.rgb; + vBlurColor.rgb *= 0.0833333; // 1.0 / 12.0 + + // Lerp between crisp and blurry pixel based on edge mask + outColor.rgb = lerp( baseColor.rgb, vBlurColor.rgb, saturate( flEdge ) ); + } + #endif + + #if ( VOMIT_ENABLE == 1 ) + { + outColor.rgb = PerformVomitBlend( vVomitRefractParams.xyz, outColor.rgb, cBloomBlurredLum.aaa ); + } + #endif + + #if ( LOCAL_CONTRAST_ENABLE == 1 ) + { + float fMask = 1.0; + + // Extract midtones and limit contrast enhancement there + // TODO: This can probably go away for perf. + //float fBrightness = dot( outColor.rgb, float3( 0.3, 0.59, 0.11 ) ); + // bell-shaped mask + //fMask = smoothstep( 0.5 - g_flLocalContrastMidToneMask, 0.5, fBrightness ); + //fMask *= smoothstep( 0.5 + g_flLocalContrastMidToneMask, 0.5, fBrightness ); + + //fMask = smoothstep( 1.0, 0.5, fBrightness ); + + /* + // unsharp mask on luminance only + // This is the technically correct way, going to YUV, applying contrast to Y, and converting back to RGB + float3 outColorYUV; + outColorYUV.x = dot( outColor.rgb, float3( 0.299, 0.587, 0.114 ) ); + outColorYUV.y = dot( outColor.rgb, float3( -0.14713, -0.28886, 0.436 ) ); + outColorYUV.z = dot( outColor.rgb, float3( 0.615, -0.51499, -0.10001 ) ); + outColorYUV.x = outColorYUV.x + g_flLocalContrastStrength * fMask * ( outColorYUV.x - cBloomBlurredLum.aaa ); + outColor.r = dot( outColorYUV.xyz, float3( 1.0, 0.0, 1.13983 ) ); + outColor.g = dot( outColorYUV.xyz, float3( 1.0, -0.39465, -0.58060 ) ); + outColor.b = dot( outColorYUV.xyz, float3( 1.0, 2.03211, 0.0 ) ); + */ + + // This applies the delta contrast derived from the luminance to all color channels. The difference to the + // correct way is imperceptible. + float fLuminance = dot( outColor.rgb, float3( 0.299, 0.587, 0.114 ) ); + float fContrastLum = fLuminance + g_flLocalContrastStrength * ( fLuminance - cBloomBlurredLum.a ); + + // Mask off pixels that got very bright, to control super-contrast + //fMask = 1.0 - smoothstep( 0.3, 1.0, fContrastLum ); + + float2 vCenterDir = ( 2.0 * i.baseTexCoord.xy ) - 1.0; + float fMyVignette = smoothstep( g_flLocalContrastVignetteStart, g_flLocalContrastVignetteEnd, length( vCenterDir ) ); + float fMyVignette2 = fMyVignette; + fMyVignette = lerp( g_flLocalContrastStrength, g_flLocalContrastEdgeStrength, fMyVignette ); + + fMask = fMyVignette; + + // If the mask is positive, only brighten pixels. If the mask is negative, don't let it get less than -1.0. + //outColor.rgb += fMask * ( fLuminance - cBloomBlurredLum.aaa ); + outColor.rgb += max( fMask * ( fLuminance - cBloomBlurredLum.aaa ), -1.0 + step( 0.0, fMask ) ); // Selective clamp to positive adds 4 instructions + + #if ( BLURRED_VIGNETTE_ENABLE == 1 ) + outColor.rgb = lerp( outColor.rgb, cBloomBlurredLum.aaa, fMyVignette2 * g_flBlurredVignetteStrength ); + #endif + } + #endif + + // Composite bloom and full-screen + depth blur effects + #if ( DEPTH_BLUR_ENABLE ) + { + float blurFactor = g_flBloomLerpFactor + abs( depthValue - g_flDepthBlurFocalDistance ) * g_flDepthBlurScale; + blurFactor = clamp( blurFactor, 0, 1 ); + outColor.rgb = lerp( outColor.rgb, cBloomBlurredLum.rgb, blurFactor ); + outColor.rgb += g_flBloomAmount * cBloomBlurredLum.rgb; + } + #else + { + outColor.rgb += g_flBloomAmount * cBloomBlurredLum.rgb; + } + #endif + + // Used to be FADE_TYPE 0..2 combo + float3 vFadeDestColor = lerp( g_vViewFadeColor.rgb, g_vViewFadeColor.rgb * outColor.rgb, g_flFadeMode2 ); + outColor.rgb = lerp( outColor.rgb, vFadeDestColor.rgb, g_vViewFadeColor.a ); + + #if ( DESATURATEENABLE ) + { + float flLum = saturate( dot( outColor.rgb, float3( 0.3f, 0.59f, 0.11f) ) ); + outColor.rgb = lerp( saturate( outColor.rgb ), flLum.xxx, saturate( g_flDesaturation ) ); + } + #else + { + outColor = PerformColorCorrection( outColor ); // Color correction + } + #endif + + // Vignette + #if ( VIGNETTE_ENABLE == 1 ) + { + // Vignette + float2 vUv = i.baseTexCoord.xy; + //float2 vTmp = ( vUv.xy * 2.0 ) - 1.0; + float flVignette; + + #if defined( _X360 ) + { + // Make title safe and deal with different gamma space + //flVignette = 1.0 - pow( abs( vTmp.x ), 4.0f ); + //flVignette *= 1.0 - pow( abs( vTmp.y ), 4.0f ); + //flVignette = 1.0 - ( 1.0 - flVignette ) * ( ( saturate( ( 1.0 - vUv.y ) - 0.1 ) / 0.9 ) ); + + // This tex2D solves the 3 lines of math above + flVignette = tex2D( VignetteSampler, vUv.xy ).g; // Green is for the 360 + flVignette = saturate( flVignette * 0.75 + 0.26 ); + } + #else + { + //flVignette = 1.0 - pow( abs( vTmp.x ), 6.0f ); + //flVignette *= 1.0 - pow( abs( vTmp.y ), 6.0f ); + //flVignette = 1.0 - ( 1.0 - flVignette ) * ( ( saturate( ( 1.0 - vUv.y ) - 0.3 ) / 0.7 ) ); + + // This tex2D solves the 3 lines of math above + flVignette = tex2D( VignetteSampler, vUv.xy ).r; // Red is for the PC + flVignette = saturate( flVignette * 0.55 + 0.46 ); + } + #endif + + outColor.rgb *= flVignette; + } + #endif + + // Noise + #if ( NOISE_ENABLE == 1 ) + { + // Additive Noise + float2 vUv0 = i.baseTexCoord.xy * 10.0 + g_flTime; + float2 vUv1 = i.baseTexCoord.yx * 20.0 - g_flTime; + float2 vNoiseTexelUv; + vNoiseTexelUv.x = tex2D( NoiseSampler, vUv0.xy ).g; + vNoiseTexelUv.y = tex2D( NoiseSampler, vUv1.xy ).g; + float flNoiseTexel = tex2D( NoiseSampler, vNoiseTexelUv.xy ).g; + + float3 vTmp = { 0.2125f, 0.7154f, 0.0721f }; + float flLuminance = saturate( dot( outColor.rgb, vTmp.rgb ) ); + + #if defined( _X360 ) + { + // 360 + float flNoiseScalar = 0.2f + 1.0f * ( saturate( pow( 1.0 - flLuminance, 64.0 ) ) ); + outColor.rgb += ( ( flNoiseTexel * 0.3f ) - 0.15f ) * g_flNoiseScalar * flNoiseScalar; + } + #else + { + // PC + float flNoiseScalar = 0.2f + 0.8f * ( saturate( pow( 1.0 - flLuminance, 12.0 ) ) ); + outColor.rgb += ( ( flNoiseTexel * 0.3f ) - 0.15f ) * g_flNoiseScalar * flNoiseScalar; + } + #endif + } + #endif + + // Fade to black + outColor.rgb = lerp( outColor.rgb, 0.0, g_flFadeToBlackStrength ); + + #if TV_GAMMA + { + // Used for SFM to record movies in native TV gamma space + outColor.rgb = SrgbGammaToTvGamma( outColor.rgb ); + } + #endif + + #if ( CONVERT_TO_LINEAR == 1 ) + { + // If we have a float back buffer, we want to remain in linear space after this shader + outColor.rgb = SrgbGammaToLinear( outColor.rgb ); + } + #endif + + return FinalOutput( outColor, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} diff --git a/materialsystem/stdshaders/Eyes_vs20.fxc b/materialsystem/stdshaders/Eyes_vs20.fxc new file mode 100644 index 00000000..e224eaf6 --- /dev/null +++ b/materialsystem/stdshaders/Eyes_vs20.fxc @@ -0,0 +1,133 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// +// $SHADER_SPECIFIC_CONST_0 = eyeball origin +// $SHADER_SPECIFIC_CONST_1 = eyeball up * 0.5 +// $SHADER_SPECIFIC_CONST_2 = iris projection U +// $SHADER_SPECIFIC_CONST_3 = iris projection V +// $SHADER_SPECIFIC_CONST_4 = glint projection U +// $SHADER_SPECIFIC_CONST_5 = glint projection V +//===========================================================================// + +// STATIC: "INTRO" "0..1" +// STATIC: "HALFLAMBERT" "0..1" + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "SKINNING" "0..1" +#include "common_fog_vs_fxc.h" +// DYNAMIC: "DYNAMIC_LIGHT" "0..1" +// DYNAMIC: "STATIC_LIGHT" "0..1" + +// DYNAMIC: "MORPHING" "0..1" [vs30] [ = pShaderAPI->IsHWMorphingEnabled() ] + +#include "vortwarp_vs20_helper.h" + +static const int g_bSkinning = SKINNING ? true : false; +static const int g_FogType = DOWATERFOG; +static const bool g_bHalfLambert = HALFLAMBERT ? true : false; + +const float3 cEyeOrigin : register( SHADER_SPECIFIC_CONST_0 ); +const float3 cHalfEyeballUp : register( SHADER_SPECIFIC_CONST_1 ); +const float4 cIrisProjectionU : register( SHADER_SPECIFIC_CONST_2 ); +const float4 cIrisProjectionV : register( SHADER_SPECIFIC_CONST_3 ); +const float4 cGlintProjectionU : register( SHADER_SPECIFIC_CONST_4 ); +const float4 cGlintProjectionV : register( SHADER_SPECIFIC_CONST_5 ); +#if INTRO +const float4 const4 : register( SHADER_SPECIFIC_CONST_6 ); +#define g_Time const4.w +#define modelOrigin const4.xyz +#endif + +#ifdef SHADER_MODEL_VS_3_0 +// NOTE: cMorphTargetTextureDim.xy = target dimensions, +// cMorphTargetTextureDim.z = 4tuples/morph +const float3 cMorphTargetTextureDim : register( SHADER_SPECIFIC_CONST_7 ); +const float4 cMorphSubrect : register( SHADER_SPECIFIC_CONST_8 ); + +sampler2D morphSampler : register( D3DVERTEXTEXTURESAMPLER0, s0 ); +#endif + +struct VS_INPUT +{ + float4 vPos : POSITION; // Position + float4 vBoneWeights : BLENDWEIGHT; // Skin weights + float4 vBoneIndices : BLENDINDICES; // Skin indices + float4 vTexCoord0 : TEXCOORD0; // Base (sclera) texture coordinates + + float3 vPosFlex : POSITION1; // Delta positions for flexing +#ifdef SHADER_MODEL_VS_3_0 + float vVertexID : POSITION2; +#endif +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; // Projection-space position +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + float fog : FOG; // Fixed-function fog factor +#endif + float2 baseTC : TEXCOORD0; // Base texture coordinate + float2 irisTC : TEXCOORD1; // Iris texture coordinates + float2 glintTC : TEXCOORD2; // Glint texture coordinates + float3 vColor : TEXCOORD3; // Vertex-lit color + + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = (VS_OUTPUT)0; + + bool bDynamicLight = DYNAMIC_LIGHT ? true : false; + bool bStaticLight = STATIC_LIGHT ? true : false; + + float4 vPosition = v.vPos; + float3 dummy = v.vPos.xyz; // dummy values that can't be optimized out + +#if !defined( SHADER_MODEL_VS_3_0 ) || !MORPHING + ApplyMorph( v.vPosFlex, vPosition.xyz ); +#else + ApplyMorph( morphSampler, cMorphTargetTextureDim, cMorphSubrect, v.vVertexID, dummy, vPosition.xyz ); +#endif + + // Transform the position and dummy normal (not doing the dummy normal causes invariance issues with the flashlight!) + float3 worldNormal, worldPos; + SkinPositionAndNormal( + g_bSkinning, + vPosition, dummy, + v.vBoneWeights, v.vBoneIndices, + worldPos, worldNormal ); + +#if INTRO + WorldSpaceVertexProcess( g_Time, modelOrigin, worldPos, dummy, dummy, dummy ); +#endif + + // Transform into projection space + o.projPos = mul( float4( worldPos, 1 ), cViewProj ); + o.worldPos_projPosZ = float4( worldPos.xyz, o.projPos.z ); + +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + o.fog = CalcFixedFunctionFog( worldPos, g_FogType ); +#endif + + // Normal = (Pos - Eye origin) - just step on dummy normal created above + worldNormal = worldPos - cEyeOrigin; + + // Normal -= 0.5f * (Normal dot Eye Up) * Eye Up + float normalDotUp = -dot( worldNormal, cHalfEyeballUp) * 0.5f; + worldNormal = normalize(normalDotUp * cHalfEyeballUp + worldNormal); + + // Compute vertex lighting + o.vColor = DoLighting( worldPos, worldNormal, float3(0.0f, 0.0f, 0.0f), bStaticLight, bDynamicLight, g_bHalfLambert ); + + // Texture 0 is the base texture + // Texture 1 is a planar projection used for the iris + // Texture 2 is a planar projection used for the glint + o.baseTC = v.vTexCoord0; + o.irisTC.x = dot( cIrisProjectionU, float4(worldPos, 1) ); + o.irisTC.y = dot( cIrisProjectionV, float4(worldPos, 1) ); + o.glintTC.x = dot( cGlintProjectionU, float4(worldPos, 1) ); + o.glintTC.y = dot( cGlintProjectionV, float4(worldPos, 1) ); + + return o; +} + + diff --git a/materialsystem/stdshaders/HDRCombineTo16Bit.cpp b/materialsystem/stdshaders/HDRCombineTo16Bit.cpp new file mode 100644 index 00000000..26949e65 --- /dev/null +++ b/materialsystem/stdshaders/HDRCombineTo16Bit.cpp @@ -0,0 +1,81 @@ +//========= Copyright © 1996-2004, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#include "BaseVSShader.h" +#include "common_hlsl_cpp_consts.h" +#include "hdrcombineto16bit_ps20.inc" +#include "hdrcombineto16bit_ps20b.inc" +#include "hdrcombineto16bit_vs20.inc" +#include "convar.h" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +BEGIN_VS_SHADER_FLAGS( HDRCombineTo16Bit, "Help for HDRCombineTo16Bit", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( SOURCEMRTRENDERTARGET, SHADER_PARAM_TYPE_TEXTURE, "", "" ) + END_SHADER_PARAMS + + SHADER_INIT + { + LoadTexture( SOURCEMRTRENDERTARGET ); + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableAlphaWrites( false ); + pShaderShadow->EnableDepthTest( false ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + int fmt = VERTEX_POSITION; + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 ); + + DECLARE_STATIC_VERTEX_SHADER( hdrcombineto16bit_vs20 ); + SET_STATIC_VERTEX_SHADER( hdrcombineto16bit_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( hdrcombineto16bit_ps20b ); + SET_STATIC_PIXEL_SHADER( hdrcombineto16bit_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( hdrcombineto16bit_ps20 ); + SET_STATIC_PIXEL_SHADER( hdrcombineto16bit_ps20 ); + } + } + + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, SOURCEMRTRENDERTARGET, -1 ); + DECLARE_DYNAMIC_VERTEX_SHADER( hdrcombineto16bit_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( hdrcombineto16bit_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( hdrcombineto16bit_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( hdrcombineto16bit_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( hdrcombineto16bit_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( hdrcombineto16bit_ps20 ); + } + } + Draw(); + } +END_SHADER diff --git a/materialsystem/stdshaders/HDRCombineTo16Bit_ps2x.fxc b/materialsystem/stdshaders/HDRCombineTo16Bit_ps2x.fxc new file mode 100644 index 00000000..e2ed8a04 --- /dev/null +++ b/materialsystem/stdshaders/HDRCombineTo16Bit_ps2x.fxc @@ -0,0 +1,23 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#include "common_ps_fxc.h" + +sampler LowSampler : register( s0 ); +sampler HiSampler : register( s1 ); + +struct PS_INPUT +{ + float2 texCoord : TEXCOORD0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float4 lowColor = tex2D( LowSampler, i.texCoord ); + float3 hiColor = tex2D( HiSampler, i.texCoord ); + + lowColor.rgb = GammaToLinear( lowColor.rgb ); + hiColor.rgb = GammaToLinear( hiColor.rgb ); + + float4 result = float4( ( 1.0f / MAX_HDR_OVERBRIGHT ) * max( lowColor.xyz, hiColor.xyz * MAX_HDR_OVERBRIGHT ), lowColor.a ); + return FinalOutput( result, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} diff --git a/materialsystem/stdshaders/HDRCombineTo16Bit_vs20.fxc b/materialsystem/stdshaders/HDRCombineTo16Bit_vs20.fxc new file mode 100644 index 00000000..d4ef3aad --- /dev/null +++ b/materialsystem/stdshaders/HDRCombineTo16Bit_vs20.fxc @@ -0,0 +1,24 @@ +#include "common_vs_fxc.h" + +struct VS_INPUT +{ + float3 vPos : POSITION; + float2 vBaseTexCoord : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; + float2 texCoord : TEXCOORD0; +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + o.projPos = float4( v.vPos, 1.0f ); + o.texCoord = v.vBaseTexCoord; + return o; +} + + diff --git a/materialsystem/stdshaders/HDRSelectRange.cpp b/materialsystem/stdshaders/HDRSelectRange.cpp new file mode 100644 index 00000000..d8d0cd39 --- /dev/null +++ b/materialsystem/stdshaders/HDRSelectRange.cpp @@ -0,0 +1,79 @@ +//========= Copyright © 1996-2004, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#include "BaseVSShader.h" +#include "common_hlsl_cpp_consts.h" + +#include "hdrselectrange_ps20.inc" +#include "hdrselectrange_ps20b.inc" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +BEGIN_VS_SHADER_FLAGS( HDRSelectRange, "Help for HDRSelectRange", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( SOURCEMRTRENDERTARGET, SHADER_PARAM_TYPE_TEXTURE, "", "" ) + END_SHADER_PARAMS + + SHADER_INIT + { + LoadTexture( SOURCEMRTRENDERTARGET ); + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableAlphaWrites( false ); + pShaderShadow->EnableDepthTest( false ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + int fmt = VERTEX_POSITION; + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 ); + + pShaderShadow->SetVertexShader( "HDRSelectRange_vs20", 0 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( hdrselectrange_ps20b ); + SET_STATIC_PIXEL_SHADER( hdrselectrange_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( hdrselectrange_ps20 ); + SET_STATIC_PIXEL_SHADER( hdrselectrange_ps20 ); + } + + } + + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, SOURCEMRTRENDERTARGET, -1 ); + pShaderAPI->SetVertexShaderIndex( 0 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( hdrselectrange_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( hdrselectrange_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( hdrselectrange_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( hdrselectrange_ps20 ); + } + } + Draw(); + } +END_SHADER diff --git a/materialsystem/stdshaders/HDRSelectRange_ps2x.fxc b/materialsystem/stdshaders/HDRSelectRange_ps2x.fxc new file mode 100644 index 00000000..90c082ce --- /dev/null +++ b/materialsystem/stdshaders/HDRSelectRange_ps2x.fxc @@ -0,0 +1,42 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#include "common_ps_fxc.h" + +sampler LowSampler : register( s0 ); +sampler HiSampler : register( s1 ); + +struct PS_INPUT +{ + float2 texCoord : TEXCOORD0; +}; + +struct MYHDR_PS_OUTPUT +{ + float4 color[2] : COLOR0; +}; + +MYHDR_PS_OUTPUT main( PS_INPUT i ) : COLOR +{ + float3 lowColor = GammaToLinear( tex2D( LowSampler, i.texCoord ) ); + float3 hiColor = GammaToLinear( tex2D( HiSampler, i.texCoord ) ); + + float4 lowOut; + lowOut.a = 1.0f; + float4 hiOut; + hiOut.a = 1.0f; + + float3 hdrColor = max( lowColor, hiColor * MAX_HDR_OVERBRIGHT ); + + float fMax = max( hdrColor.b, max( hdrColor.r, hdrColor.g ) ); + + float blendFactor = saturate( ( fMax - 0.9f ) * 10.0f ); + + blendFactor = 1.0f; + + lowOut.rgb = LinearToGamma( lowColor * ( 1.0f - blendFactor ) ); + hiOut.rgb = LinearToGamma( hiColor * ( blendFactor ) ); + MYHDR_PS_OUTPUT output; + output.color[0] = lowOut; + output.color[1] = hiOut; + return output; +} diff --git a/materialsystem/stdshaders/HDRSelectRange_vs20.fxc b/materialsystem/stdshaders/HDRSelectRange_vs20.fxc new file mode 100644 index 00000000..d4ef3aad --- /dev/null +++ b/materialsystem/stdshaders/HDRSelectRange_vs20.fxc @@ -0,0 +1,24 @@ +#include "common_vs_fxc.h" + +struct VS_INPUT +{ + float3 vPos : POSITION; + float2 vBaseTexCoord : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; + float2 texCoord : TEXCOORD0; +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + o.projPos = float4( v.vPos, 1.0f ); + o.texCoord = v.vBaseTexCoord; + return o; +} + + diff --git a/materialsystem/stdshaders/MonitorScreen_dx9.cpp b/materialsystem/stdshaders/MonitorScreen_dx9.cpp new file mode 100644 index 00000000..4e808e42 --- /dev/null +++ b/materialsystem/stdshaders/MonitorScreen_dx9.cpp @@ -0,0 +1,182 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "BaseVSShader.h" +#include "unlittwotexture_vs20.inc" +#include "monitorscreen_ps20.inc" +#include "monitorscreen_ps20b.inc" +#include "cpp_shader_constant_register_map.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( MonitorScreen, MonitorScreen_DX9 ) + +BEGIN_VS_SHADER( MonitorScreen_DX9, + "This is a shader that does a contrast/saturation version of base times lightmap." ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( CONTRAST, SHADER_PARAM_TYPE_FLOAT, "0.0", "contrast 0 == normal 1 == color*color" ) + SHADER_PARAM( SATURATION, SHADER_PARAM_TYPE_FLOAT, "1.0", "saturation 0 == greyscale 1 == normal" ) + SHADER_PARAM( TINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "monitor tint" ) + SHADER_PARAM( TEXTURE2, SHADER_PARAM_TYPE_TEXTURE, "shadertest/lightmappedtexture", "second texture" ) + SHADER_PARAM( FRAME2, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $texture2" ) + SHADER_PARAM( TEXTURE2TRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$texture2 texcoord transform" ) + END_SHADER_PARAMS + + // Set up anything that is necessary to make decisions in SHADER_FALLBACK. + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + if( !params[CONTRAST]->IsDefined() ) + { + params[CONTRAST]->SetFloatValue( 0.0f ); + } + if( !params[SATURATION]->IsDefined() ) + { + params[SATURATION]->SetFloatValue( 1.0f ); + } + if( !params[TINT]->IsDefined() ) + { + params[TINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + } + if (!IS_FLAG_DEFINED( MATERIAL_VAR_MODEL )) + { + CLEAR_FLAGS( MATERIAL_VAR_MODEL ); + } + } + + SHADER_FALLBACK + { + if( params && !params[BASETEXTURE]->IsDefined() ) + return "LightmappedGeneric"; + + return 0; + } + + SHADER_INIT + { + if (params[BASETEXTURE]->IsDefined()) + { + LoadTexture( BASETEXTURE ); + } + if (params[TEXTURE2]->IsDefined()) + { + LoadTexture( TEXTURE2 ); + } + } + + SHADER_DRAW + { + bool bHasTexture2 = params[TEXTURE2]->IsTexture(); + BlendType_t nBlendType = EvaluateBlendRequirements( BASETEXTURE, true ); + bool bFullyOpaque = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !IS_FLAG_SET(MATERIAL_VAR_ALPHATEST); //dest alpha is free for special use + + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + if ( bHasTexture2 ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); + } + + pShaderShadow->EnableSRGBWrite( true ); + + // Either we've got a constant modulation + bool isTranslucent = IsAlphaModulating(); + + // Or we've got a texture alpha on either texture + isTranslucent = isTranslucent || TextureIsTranslucent( BASETEXTURE, true ) || + TextureIsTranslucent( TEXTURE2, true ); + + if ( isTranslucent ) + { + if ( IS_FLAG_SET(MATERIAL_VAR_ADDITIVE) ) + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + else + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + else + { + if ( IS_FLAG_SET(MATERIAL_VAR_ADDITIVE) ) + EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); + else + DisableAlphaBlending( ); + } + + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + DECLARE_STATIC_VERTEX_SHADER( unlittwotexture_vs20 ); + SET_STATIC_VERTEX_SHADER( unlittwotexture_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( monitorscreen_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( TEXTURE2, (bHasTexture2)?(1):(0) ); + SET_STATIC_PIXEL_SHADER( monitorscreen_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( monitorscreen_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( TEXTURE2, (bHasTexture2)?(1):(0) ); + SET_STATIC_PIXEL_SHADER( monitorscreen_ps20 ); + } + + DefaultFog(); + + pShaderShadow->EnableAlphaWrites( bFullyOpaque ); + PI_BeginCommandBuffer(); + PI_SetModulationVertexShaderDynamicState(); + PI_EndCommandBuffer(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + if( bHasTexture2 ) + { + BindTexture( SHADER_SAMPLER1, TEXTURE2, FRAME2 ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, TEXTURE2TRANSFORM ); + } + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BASETEXTURETRANSFORM ); + SetPixelShaderConstant( 1, CONTRAST ); + SetPixelShaderConstant( 2, SATURATION ); + SetPixelShaderConstant( 3, TINT ); + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + float vEyePos_SpecExponent[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + vEyePos_SpecExponent[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + + + DECLARE_DYNAMIC_VERTEX_SHADER( unlittwotexture_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( WORLD_NORMAL, 0 ); + SET_DYNAMIC_VERTEX_SHADER( unlittwotexture_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( monitorscreen_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bFullyOpaque && pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( monitorscreen_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( monitorscreen_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( monitorscreen_ps20 ); + } + } + Draw(); + } +END_SHADER diff --git a/materialsystem/stdshaders/Refract_vs20.fxc b/materialsystem/stdshaders/Refract_vs20.fxc new file mode 100644 index 00000000..8240ec99 --- /dev/null +++ b/materialsystem/stdshaders/Refract_vs20.fxc @@ -0,0 +1,143 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// +// +// Purpose: +// +//===========================================================================// + +// STATIC: "MODEL" "0..1" +// STATIC: "COLORMODULATE" "0..1" + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "SKINNING" "0..1" + +#include "common_vs_fxc.h" + +static const bool g_bSkinning = SKINNING ? true : false; +static const bool g_bModel = MODEL ? true : false; + +const float4 cBumpTexCoordTransform[4] : register( SHADER_SPECIFIC_CONST_1 ); + +const float g_flTime : register( SHADER_SPECIFIC_CONST_5 ); + +const float4 g_vViewportMad : register( SHADER_SPECIFIC_CONST_6 ); + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vNormal : NORMAL; + float4 vBaseTexCoord : TEXCOORD0; +#if !MODEL + float3 vTangentS : TANGENT; + float3 vTangentT : BINORMAL0; +#else + float4 vUserData : TANGENT; +#endif +#if COLORMODULATE + float4 vColor : COLOR0; +#endif +}; + +struct VS_OUTPUT +{ + float4 vProjPos_POSITION : POSITION; +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + float fog : FOG; +#endif + float4 vBumpTexCoord : TEXCOORD0; + float3 vTangentEyeVect : TEXCOORD1; + float3 vWorldNormal : TEXCOORD2; + float3 vWorldTangent : TEXCOORD3; + float3 vWorldBinormal : TEXCOORD4; + float3 vRefractXYW : TEXCOORD5; + float3 vWorldViewVector : TEXCOORD6; +#if COLORMODULATE + float4 vColor : COLOR0; +#endif + + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + +#if COLORMODULATE + o.vColor = v.vColor; +#endif + + float3 worldNormal, worldPos, worldTangentS, worldTangentT; + + float3 vObjNormal; +#if MODEL + float4 vObjTangent; + DecompressVertex_NormalTangent( v.vNormal, v.vUserData, vObjNormal, vObjTangent ); + + SkinPositionNormalAndTangentSpace( + g_bSkinning, + v.vPos, vObjNormal, vObjTangent, + v.vBoneWeights, v.vBoneIndices, + worldPos, worldNormal, worldTangentS, worldTangentT ); +#else + DecompressVertex_Normal( v.vNormal, vObjNormal ); + + worldPos = mul( v.vPos, cModel[0] ); + worldTangentS = mul( v.vTangentS, ( const float3x3 )cModel[0] ); + worldTangentT = mul( v.vTangentT, ( const float3x3 )cModel[0] ); + worldNormal = mul( vObjNormal, ( float3x3 )cModel[0] ); +#endif + + // World normal + o.vWorldNormal.xyz = normalize( worldNormal.xyz ); + + // Projected position + float4 vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + o.vProjPos_POSITION = vProjPos; + o.worldPos_projPosZ = float4( worldPos.xyz, vProjPos.z ); + //o.projNormal.xyz = mul( worldNormal, cViewProj ); + + // Map projected position to the refraction texture + float2 vRefractPos; + vRefractPos.x = vProjPos.x; + vRefractPos.y = -vProjPos.y; // invert Y + vRefractPos = (vRefractPos + vProjPos.w) * 0.5f; + + // Adjust for current viewport + vRefractPos.xy = ( ( ( vRefractPos.xy / vProjPos.w ) * g_vViewportMad.xy ) + g_vViewportMad.zw ) * vProjPos.w; + + // Refraction transform + o.vRefractXYW = float3(vRefractPos.x, vRefractPos.y, vProjPos.w); + + // Compute fog based on the position + float3 vWorldPos = mul( v.vPos, cModel[0] ); + +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + o.fog = CalcFixedFunctionFog( vWorldPos, FOGTYPE_RANGE ); +#endif + + // Eye vector + float3 vWorldEyeVect = normalize( cEyePos - vWorldPos ); + o.vWorldViewVector.xyz = -vWorldEyeVect.xyz; + + // Transform to the tangent space + o.vTangentEyeVect.x = dot( vWorldEyeVect, worldTangentS ); + o.vTangentEyeVect.y = dot( vWorldEyeVect, worldTangentT ); + o.vTangentEyeVect.z = dot( vWorldEyeVect, worldNormal ); + + // Tranform bump coordinates + o.vBumpTexCoord.x = dot( v.vBaseTexCoord, cBumpTexCoordTransform[0] ); + o.vBumpTexCoord.y = dot( v.vBaseTexCoord, cBumpTexCoordTransform[1] ); + + // Tranform bump coordinates (note wz, not zw) + o.vBumpTexCoord.w = dot( v.vBaseTexCoord, cBumpTexCoordTransform[2] ); + o.vBumpTexCoord.z = dot( v.vBaseTexCoord, cBumpTexCoordTransform[3] ); + + + // Tangent space transform + o.vWorldNormal.xyz = normalize( worldNormal.xyz ); + o.vWorldTangent.xyz = worldTangentS.xyz; + o.vWorldBinormal.xyz = worldTangentT.xyz; + + return o; +} diff --git a/materialsystem/stdshaders/ScreenSpaceEffect.vsh b/materialsystem/stdshaders/ScreenSpaceEffect.vsh new file mode 100644 index 00000000..ad1ec0e2 --- /dev/null +++ b/materialsystem/stdshaders/ScreenSpaceEffect.vsh @@ -0,0 +1,29 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +;------------------------------------------------------------------------------ +; Constants specified by the app +; c0 = (0, 1, 2, 0.5) +; c1 = (1/2.2, 3, 255, overbright factor) +; c2 = camera position *in world space* +; c4-c7 = modelViewProj matrix (transpose) +; c8-c11 = ViewProj matrix (transpose) +; c12-c15 = model->view matrix (transpose) +; c16 = [fogStart, fogEnd, fogRange, 1.0/fogRange] +; $SHADER_SPECIFIC_CONST_0-$SHADER_SPECIFIC_CONST_1 = Base texture transform +; $SHADER_SPECIFIC_CONST_2-$SHADER_SPECIFIC_CONST_3 = Mask texture transform +;------------------------------------------------------------------------------ + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; No vertex blending required. Input vertex data is in screen space +;------------------------------------------------------------------------------ +mov oPos.xyz, $vPos.xyz +mov oPos.w, $cOne + +;------------------------------------------------------------------------------ +; Pass any and all texture coordinates through +;------------------------------------------------------------------------------ +mov oT0, $vTexCoord0 diff --git a/materialsystem/stdshaders/SetZ.cpp b/materialsystem/stdshaders/SetZ.cpp new file mode 100644 index 00000000..74d5d6e3 --- /dev/null +++ b/materialsystem/stdshaders/SetZ.cpp @@ -0,0 +1,43 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: Naively sets the depth buffer values without testing the old values and without writing to alpha or color +// +// $NoKeywords: $ +//=============================================================================// + +#include "shaderlib/CShader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( SetZ, SetZ_DX6 ) + +BEGIN_SHADER_FLAGS( SetZ_DX6, "Help for SetZ_DX6", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + } + + SHADER_INIT + { + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableColorWrites( false ); + pShaderShadow->EnableAlphaWrites( false ); + pShaderShadow->DepthFunc( SHADER_DEPTHFUNC_ALWAYS ); + + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION ); + } + DYNAMIC_STATE + { + } + Draw(); + } +END_SHADER + diff --git a/materialsystem/stdshaders/ShadowModel.psh b/materialsystem/stdshaders/ShadowModel.psh new file mode 100644 index 00000000..a7514020 --- /dev/null +++ b/materialsystem/stdshaders/ShadowModel.psh @@ -0,0 +1,22 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +def c0,1.0f, 1.0f, 1.0f, 1.0f + +tex t0 ; shadow color +texkill t1 ; Clip +texkill t2 +texkill t3 ; backface cull + +; Darkening equation, compute a color = (shadow color * shadow alpha + 1- shadow alpha) +;sub r1, t0, v0.a ; r1 = shadow alpha +lrp r0.rgb, t0.a, v0, c0 + ; r0.rgb = (shadow color * shadow alpha + 1 - shadow alpha) +mov r0.a, c0.a ; r0.a = 1 + diff --git a/materialsystem/stdshaders/ShadowModel.vsh b/materialsystem/stdshaders/ShadowModel.vsh new file mode 100644 index 00000000..d7aec97a --- /dev/null +++ b/materialsystem/stdshaders/ShadowModel.vsh @@ -0,0 +1,85 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" +# DYNAMIC: "SKINNING" "0..1" + +;------------------------------------------------------------------------------ +; Constants specified by the app +; $SHADER_SPECIFIC_CONST_0-$SHADER_SPECIFIC_CONST_2 = Shadow texture matrix +; $SHADER_SPECIFIC_CONST_3 = Tex origin +; $SHADER_SPECIFIC_CONST_4 = Tex Scale +; $SHADER_SPECIFIC_CONST_5 = [Shadow falloff offset, 1/Shadow distance, Shadow scale, 0 ] +;------------------------------------------------------------------------------ + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending (whacks r1-r7, positions in r7, normals in r8) +;------------------------------------------------------------------------------ +&AllocateRegister( \$worldPos ); +&AllocateRegister( \$worldNormal ); +&SkinPositionAndNormal( $worldPos, $worldNormal ); + +; Transform the position from world to view space +&AllocateRegister( \$projPos ); + +dp4 $projPos.x, $worldPos, $cViewProj0 +dp4 $projPos.y, $worldPos, $cViewProj1 +dp4 $projPos.z, $worldPos, $cViewProj2 +dp4 $projPos.w, $worldPos, $cViewProj3 +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ +&CalcFog( $worldPos, $projPos ); +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Transform position into texture space (from 0 to 1) +;------------------------------------------------------------------------------ +&AllocateRegister( \$texturePos ); +dp4 $texturePos.x, $worldPos, $SHADER_SPECIFIC_CONST_0 +dp4 $texturePos.y, $worldPos, $SHADER_SPECIFIC_CONST_1 +dp4 $texturePos.z, $worldPos, $SHADER_SPECIFIC_CONST_2 +&FreeRegister( \$worldPos ); + +;------------------------------------------------------------------------------ +; Figure out the shadow fade amount +;------------------------------------------------------------------------------ +&AllocateRegister( \$shadowFade ); +sub $shadowFade, $texturePos.z, $SHADER_SPECIFIC_CONST_5.x +mul $shadowFade, $shadowFade, $SHADER_SPECIFIC_CONST_5.y + +;------------------------------------------------------------------------------ +; Offset it into the texture +;------------------------------------------------------------------------------ +&AllocateRegister( \$actualTextureCoord ); +mul $actualTextureCoord.xyz, $SHADER_SPECIFIC_CONST_4, $texturePos +add oT0.xyz, $actualTextureCoord, $SHADER_SPECIFIC_CONST_3 +;mov oT0.xyz, $texturePos +&FreeRegister( \$actualTextureCoord ); + +;------------------------------------------------------------------------------ +; We're doing clipping by using texkill +;------------------------------------------------------------------------------ +mov oT1.xyz, $texturePos ; also clips when shadow z < 0 ! +sub oT2.xyz, $cOne, $texturePos +sub oT2.z, $cOne, $shadowFade.z ; clips when shadow z > shadow distance +&FreeRegister( \$texturePos ); + +;------------------------------------------------------------------------------ +; We're doing backface culling by using texkill also (wow yucky) +;------------------------------------------------------------------------------ +; Transform z component of normal in texture space +; If it's negative, then don't draw the pixel +dp3 oT3, $worldNormal, -$SHADER_SPECIFIC_CONST_2 +&FreeRegister( \$worldNormal ); + +;------------------------------------------------------------------------------ +; Shadow color, falloff +;------------------------------------------------------------------------------ +mov oD0, $cModulationColor +mul oD0.w, $shadowFade.x, $SHADER_SPECIFIC_CONST_5.z +&FreeRegister( \$shadowFade ); + diff --git a/materialsystem/stdshaders/ShatteredGlass_ps2x.fxc b/materialsystem/stdshaders/ShatteredGlass_ps2x.fxc new file mode 100644 index 00000000..13fe827a --- /dev/null +++ b/materialsystem/stdshaders/ShatteredGlass_ps2x.fxc @@ -0,0 +1,128 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "CUBEMAP" "0..1" +// STATIC: "VERTEXCOLOR" "0..1" +// STATIC: "ENVMAPMASK" "0..1" +// STATIC: "BASEALPHAENVMAPMASK" "0..1" +// STATIC: "HDRTYPE" "0..2" + +#include "common_fog_ps_fxc.h" + +// HDRFIXME: Need to make this work. + +#define USE_32BIT_LIGHTMAPS_ON_360 //uncomment to use 32bit lightmaps, be sure to keep this in sync with the same #define in materialsystem/cmatlightmaps.cpp + +#include "common_ps_fxc.h" +#include "common_lightmappedgeneric_fxc.h" + +const HALF4 g_EnvmapTint : register( c0 ); +const HALF3 g_DiffuseModulation : register( c1 ); +const HALF3 g_EnvmapContrast : register( c2 ); +const HALF3 g_EnvmapSaturation : register( c3 ); +const HALF4 g_FresnelReflection : register( c4 ); +const HALF3 g_EyePos : register( c5 ); +const HALF3 g_OverbrightFactor : register( c6 ); + +const HALF4 g_FogParams : register( c12 ); + +// CENTROID: TEXCOORD2 + +sampler BaseTextureSampler : register( s0 ); +sampler LightmapSampler : register( s1 ); +sampler EnvmapSampler : register( s2 ); +sampler DetailSampler : register( s3 ); +sampler EnvmapMaskSampler : register( s5 ); + +sampler NormalizeSampler : register( s6 ); + +struct PS_INPUT +{ + HALF2 baseTexCoord : TEXCOORD0; + HALF2 detailTexCoord : TEXCOORD1; + HALF2 lightmapTexCoord : TEXCOORD2; + HALF2 envmapMaskTexCoord : TEXCOORD3; + HALF4 worldPos_projPosZ : TEXCOORD4; + HALF3 worldSpaceNormal : TEXCOORD5; + HALF4 vertexColor : COLOR; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + bool bCubemap = CUBEMAP ? true : false; + bool bVertexColor = VERTEXCOLOR ? true : false; + bool bEnvmapMask = ENVMAPMASK ? true : false; + bool bBaseAlphaEnvmapMask = BASEALPHAENVMAPMASK ? true : false; + + HALF4 baseColor = tex2D( BaseTextureSampler, i.baseTexCoord ); + HALF4 detailColor = tex2D( DetailSampler, i.detailTexCoord ); + + HALF2 lightmapCoordinates = i.lightmapTexCoord; + HALF3 lightmapColor = LightMapSample( LightmapSampler, lightmapCoordinates ); + + HALF3 specularFactor = 1.0f; + if( bEnvmapMask ) + { + specularFactor = tex2D( EnvmapMaskSampler, i.detailTexCoord ).xyz; + } + + if( bBaseAlphaEnvmapMask ) + { + specularFactor *= 1.0 - baseColor.a; // this blows! + } + + HALF3 diffuseLighting = lightmapColor; + diffuseLighting *= g_DiffuseModulation; + diffuseLighting *= LIGHT_MAP_SCALE; + + HALF3 albedo = baseColor; + HALF alpha = 1.0f; + + if( !bBaseAlphaEnvmapMask ) + { + alpha *= baseColor.a; + } + + albedo *= detailColor; + alpha *= detailColor.a; + + // FIXME: seperate vertexcolor and vertexalpha? + // vertex alpha is ignored if vertexcolor isn't set. . need to check other version. + if( bVertexColor ) + { + albedo *= i.vertexColor; + alpha *= i.vertexColor.a; // not sure about this one + } + + HALF3 specularLighting = HALF3( 0.0f, 0.0f, 0.0f ); + if( bCubemap ) + { + float3 worldVertToEyeVector = g_EyePos - i.worldPos_projPosZ.xyz; + worldVertToEyeVector = NormalizeWithCubemap( NormalizeSampler, worldVertToEyeVector ); + HALF3 reflectVect = CalcReflectionVectorUnnormalized( i.worldSpaceNormal, worldVertToEyeVector ); + + // Calc Fresnel factor + HALF3 worldSpaceNormal = NormalizeWithCubemap( NormalizeSampler, i.worldSpaceNormal ); + HALF fresnel = 1.0 - dot( worldSpaceNormal, worldVertToEyeVector ); + fresnel = pow( fresnel, 5.0 ); + fresnel = fresnel * g_FresnelReflection.b + g_FresnelReflection.a; + + specularLighting = texCUBE( EnvmapSampler, reflectVect ); + specularLighting *= specularFactor; + + specularLighting *= g_EnvmapTint; +#if HDRTYPE == HDR_TYPE_NONE + HALF3 specularLightingSquared = specularLighting * specularLighting; + specularLighting = lerp( specularLighting, specularLightingSquared, g_EnvmapContrast ); + HALF3 greyScale = dot( specularLighting, HALF3( 0.299f, 0.587f, 0.114f ) ); + specularLighting = lerp( greyScale, specularLighting, g_EnvmapSaturation ); +#endif + specularLighting *= fresnel; + } + + // Do it somewhat unlit + HALF3 result = albedo*(g_OverbrightFactor.z*diffuseLighting + g_OverbrightFactor.y) + specularLighting; + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos.xyz, i.worldPos_projPosZ.xyz, i.worldPos_projPosZ.w ); + return FinalOutput( HALF4( result, alpha ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR ); +} + diff --git a/materialsystem/stdshaders/ShatteredGlass_vs20.fxc b/materialsystem/stdshaders/ShatteredGlass_vs20.fxc new file mode 100644 index 00000000..ec8f1b53 --- /dev/null +++ b/materialsystem/stdshaders/ShatteredGlass_vs20.fxc @@ -0,0 +1,66 @@ +#include "common_fog_vs_fxc.h" +// STATIC: "ENVMAP_MASK" "0..1" +#include "common_vs_fxc.h" + +static const int g_FogType = DOWATERFOG; +static const bool g_UseSeparateEnvmapMask = ENVMAP_MASK; + +const float4 cBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_0 ); +const float4 cDetailTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_2 ); + +struct VS_INPUT +{ + float3 vPos : POSITION; + float4 vNormal : NORMAL; + float2 vBaseTexCoord : TEXCOORD0; + float2 vLightmapTexCoord : TEXCOORD1; + float2 vDetailTexCoord : TEXCOORD2; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + float fog : FOG; +#endif + float2 baseTexCoord : TEXCOORD0; + float2 detailTexCoord : TEXCOORD1; + float2 lightmapTexCoord : TEXCOORD2; + float2 envmapMaskTexCoord : TEXCOORD3; + float4 worldPos_projPosZ : TEXCOORD4; + float3 worldNormal : TEXCOORD5; + float4 vertexColor : COLOR; +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 vObjNormal; + DecompressVertex_Normal( v.vNormal, vObjNormal ); + + float4 projPos; + projPos = mul( float4( v.vPos, 1 ), cModelViewProj ); + o.projPos = projPos; + + o.worldPos_projPosZ.w = projPos.z; + o.worldPos_projPosZ.xyz = mul( float4( v.vPos, 1 ), cModel[0] ); + o.worldNormal = mul( vObjNormal, ( float3x3 )cModel[0] ); + o.baseTexCoord.x = dot( v.vBaseTexCoord, cBaseTexCoordTransform[0] ) + cBaseTexCoordTransform[0].w; + o.baseTexCoord.y = dot( v.vBaseTexCoord, cBaseTexCoordTransform[1] ) + cBaseTexCoordTransform[1].w; + o.detailTexCoord.x = dot( v.vDetailTexCoord, cDetailTexCoordTransform[0] ) + cDetailTexCoordTransform[0].w; + o.detailTexCoord.y = dot( v.vDetailTexCoord, cDetailTexCoordTransform[1] ) + cDetailTexCoordTransform[1].w; + o.envmapMaskTexCoord.x = dot( v.vDetailTexCoord, cDetailTexCoordTransform[0] ) + cDetailTexCoordTransform[0].w; + o.envmapMaskTexCoord.y = dot( v.vDetailTexCoord, cDetailTexCoordTransform[1] ) + cDetailTexCoordTransform[1].w; + o.lightmapTexCoord = v.vLightmapTexCoord; + +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + o.fog = CalcFixedFunctionFog( o.worldPos_projPosZ.xyz, g_FogType ); +#endif + + o.vertexColor = cModulationColor; + + return o; +} + + diff --git a/materialsystem/stdshaders/TreeLeaf.cpp b/materialsystem/stdshaders/TreeLeaf.cpp new file mode 100644 index 00000000..fd5df806 --- /dev/null +++ b/materialsystem/stdshaders/TreeLeaf.cpp @@ -0,0 +1,96 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" + +#include "treeleaf_ps20.inc" +#include "treeleaf_ps20b.inc" +#include "treeleaf_vs20.inc" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +BEGIN_VS_SHADER_FLAGS( TreeLeaf, "Help for TreeLeaf", SHADER_NOT_EDITABLE ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( LEAFCENTER, SHADER_PARAM_TYPE_VEC3, "[0 0 0]", "Center of leaf cluster for lighting" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + + if ( params[BASETEXTURE]->IsDefined() ) + { + LoadTexture( BASETEXTURE ); + } + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + pShaderShadow->EnableAlphaTest( true ); + pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GREATER, 0.5f ); + + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL; + int numTexCoords = 1; + pShaderShadow->VertexShaderVertexFormat( flags, numTexCoords, 0, 0 ); + + DECLARE_STATIC_VERTEX_SHADER( treeleaf_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT, true ); + SET_STATIC_VERTEX_SHADER( treeleaf_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( treeleaf_ps20b ); + SET_STATIC_PIXEL_SHADER( treeleaf_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( treeleaf_ps20 ); + SET_STATIC_PIXEL_SHADER( treeleaf_ps20 ); + } + + // we are writing linear values from this shader. + // This is kinda wrong. We are writing linear or gamma depending on "IsHDREnabled" below. + // The COLOR really decides if we are gamma or linear. + pShaderShadow->EnableSRGBWrite( false ); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + + // We need the view matrix + LoadViewMatrixIntoVertexShaderConstant( VERTEX_SHADER_VIEWMODEL ); + + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, params[ LEAFCENTER ]->GetVecValue() ); + + LightState_t lightState; + pShaderAPI->GetDX9LightState( &lightState ); + + DECLARE_DYNAMIC_VERTEX_SHADER( treeleaf_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DYNAMIC_LIGHT, lightState.HasDynamicLight() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( STATIC_LIGHT, lightState.m_bStaticLight ? 1 : 0 ); + SET_DYNAMIC_VERTEX_SHADER( treeleaf_vs20 ); + } + Draw( ); + } +END_SHADER diff --git a/materialsystem/stdshaders/TreeLeaf_ps2x.fxc b/materialsystem/stdshaders/TreeLeaf_ps2x.fxc new file mode 100644 index 00000000..1a16cf92 --- /dev/null +++ b/materialsystem/stdshaders/TreeLeaf_ps2x.fxc @@ -0,0 +1,19 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_fxc.h" + +struct PS_INPUT +{ + float2 texCoord0 : TEXCOORD0; + float3 color : COLOR; +}; + +sampler BaseTextureSampler : register( s0 ); + +HALF4 main( PS_INPUT i ) : COLOR +{ + float4 baseTex = tex2D( BaseTextureSampler, i.texCoord0 ); + return FinalOutput( baseTex * float4( i.color, 1 ), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} + diff --git a/materialsystem/stdshaders/TreeLeaf_vs20.fxc b/materialsystem/stdshaders/TreeLeaf_vs20.fxc new file mode 100644 index 00000000..7ac56229 --- /dev/null +++ b/materialsystem/stdshaders/TreeLeaf_vs20.fxc @@ -0,0 +1,61 @@ +// STATIC: "HALFLAMBERT" "0..1" +// DYNAMIC: "DYNAMIC_LIGHT" "0..1" +// DYNAMIC: "STATIC_LIGHT" "0..1" + +#include "common_vs_fxc.h" + +static const bool g_bHalfLambert = HALFLAMBERT ? true : false; + +const float3 cLeafCenter : register(SHADER_SPECIFIC_CONST_0); + +struct VS_INPUT +{ + // This is all of the stuff that we ever use. + float4 vPos : POSITION; + float4 vNormal : NORMAL; + float2 vTexCoord : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; + float2 texCoord : TEXCOORD0; + float3 color : COLOR; +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + bool bDynamicLight = DYNAMIC_LIGHT ? true : false; + bool bStaticLight = STATIC_LIGHT ? true : false; + + float3 worldPos; + worldPos = mul( v.vPos, cModel[0] ); + + float3 normal = v.vPos.xyz - cLeafCenter.xyz; + normal = normalize( normal ); + + float3 worldNormal = mul( float4( normal, 0.0f ), cModel[0] ); + float3 lighting = DoLighting( worldPos, worldNormal, float3(0,0,0), bStaticLight, bDynamicLight, g_bHalfLambert ); + + float3 xAxis = float3( cViewModel[0].x, cViewModel[1].x, cViewModel[2].x ); + float3 yAxis = float3( cViewModel[0].y, cViewModel[1].y, cViewModel[2].y ); + + worldPos += xAxis * v.vTexCoord.x; + worldPos += yAxis * (1.0f-v.vTexCoord.y); + + float4 projPos = mul( float4(worldPos, 1.0f), cViewProj ); + + float3 light_vec = float3( 1.0f, 0.0, 1.0 ); + light_vec = normalize( light_vec ); + + o.projPos = projPos; + // FIXME: if this shader gets put back into use, be sure this usage of normals jives with compressed verts + o.texCoord = v.vNormal.xy; + o.color = lighting; + + return o; +} + + diff --git a/materialsystem/stdshaders/UnlitGeneric.psh b/materialsystem/stdshaders/UnlitGeneric.psh new file mode 100644 index 00000000..53fab24d --- /dev/null +++ b/materialsystem/stdshaders/UnlitGeneric.psh @@ -0,0 +1,13 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t0 ; base color + +mul r0, t0, v0 \ No newline at end of file diff --git a/materialsystem/stdshaders/WaterCheap_ps2x.fxc b/materialsystem/stdshaders/WaterCheap_ps2x.fxc new file mode 100644 index 00000000..bf8135c0 --- /dev/null +++ b/materialsystem/stdshaders/WaterCheap_ps2x.fxc @@ -0,0 +1,297 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "MULTITEXTURE" "0..1" +// STATIC: "FRESNEL" "0..1" +// STATIC: "BLEND" "0..1" +// STATIC: "REFRACTALPHA" "0..1" +// STATIC: "HDRTYPE" "0..2" +// STATIC: "FLOWMAP" "0..1" +// STATIC: "FLOW_DEBUG" "0..1" + +// DYNAMIC: "HDRENABLED" "0..1" + +#include "common_fog_ps_fxc.h" + +#include "common_ps_fxc.h" +#include "shader_constant_register_map.h" + +// Constants +const float3 g_WaterFogColor : register( c0 ); + +const float4 g_CheapWaterParams : register( c1 ); +#define g_CheapWaterStart g_CheapWaterParams.x +#define g_CheapWaterEnd g_CheapWaterParams.y +#define g_CheapWaterDeltaRecip g_CheapWaterParams.z +#define g_CheapWaterStartDivDelta g_CheapWaterParams.w + +const float4 g_ReflectTint : register( c2 ); +const float g_flTime : register( c10 ); + +const float4 g_EyePos : register( PSREG_EYEPOS_SPEC_EXPONENT ); // c11 +const float4 g_PixelFogParams : register( PSREG_FOG_PARAMS ); // c12 + +const float4 g_vFlowParams1 : register( c13 ); +#define g_flWorldUvScale ( g_vFlowParams1.x ) // 1.0f / 10.0f +#define g_flNormalUvScale ( g_vFlowParams1.y ) // 1.0f / 1.15f +#define g_flBumpStrength ( g_vFlowParams1.z ) // 3.0f +#define g_flTimeScale ( g_vFlowParams1.w ) // 1.0f + +const float3 g_vFlowParams2 : register( c14 ); +#define g_flFlowTimeIntervalInSeconds ( g_vFlowParams2.x ) // 0.4f // Number of seconds to lerp from texture 1 to texture 2 +#define g_flFlowUvScrollDistance ( g_vFlowParams2.y ) // 0.25f // Distance in uv space to fetch +#define g_flNoiseScale ( g_vFlowParams2.z ) + +// Textures +sampler EnvmapSampler : register( s0 ); +sampler NormalMapSampler : register( s1 ); + +#if REFRACTALPHA + sampler RefractSampler : register( s2 ); +#endif + +sampler FlowSampler : register( s3 ); + +sampler FlowNoiseSampler : register( s4 ); + +sampler NormalizeSampler : register( s6 ); + +struct PS_INPUT +{ + float4 worldSpaceEyeVect_normalMapX : TEXCOORD1; + float3x3 tangentSpaceTranspose : TEXCOORD2; + float4 vRefract_W_ProjZ : TEXCOORD5; + + #if MULTITEXTURE + float4 vExtraBumpTexCoord : TEXCOORD6; + #endif + + float4 worldPos_normalMapY : TEXCOORD7; +}; + +float2 UnpackNormal2D( float2 vNormal ) +{ + return ( ( vNormal.xy * 2.0 ) - 1.0 ); +} + +float3 UnpackNormal3D( float3 vNormal ) +{ + return ( ( vNormal.xyz * 2.0 ) - 1.0 ); +} + +float3 ComputeNormalFromXY( float2 vXY ) +{ + float3 vNormalTs; + + vNormalTs.xy = vXY.xy; + vNormalTs.z = sqrt( saturate( 1.0 - dot( vNormalTs.xy, vNormalTs.xy ) ) ); + + return vNormalTs.xyz; +} + +float3 ComputeNormalFromRGTexture( float2 vRGPixel ) +{ + float3 vNormalTs; + + vNormalTs.xy = UnpackNormal2D( vRGPixel.rg ); + vNormalTs.z = sqrt( saturate( 1.0 - dot( vNormalTs.xy, vNormalTs.xy ) ) ); + + return vNormalTs.xyz; +} + +float4 main( PS_INPUT i ) : COLOR +{ + float2 normalMapTexCoord = float2( i.worldSpaceEyeVect_normalMapX.w, i.worldPos_normalMapY.w ); + + float3 vNormal; + #if ( FLOWMAP ) + { + //* + float flWorldUvScale = g_flWorldUvScale; + float flNormalUvScale = g_flNormalUvScale; + float flFlowTimeIntervalInSeconds = g_flFlowTimeIntervalInSeconds; + float flFlowUvScrollDistance = g_flFlowUvScrollDistance; + float flBumpStrength = g_flBumpStrength; + float flTimeScale = g_flTimeScale; + float flNoiseScale = g_flNoiseScale; + //*/ + + /* River + float flWorldUvScale = 1.0f / 6.0f; + float flNormalUvScale = 1.0f / 0.5f; + float flFlowTimeIntervalInSeconds = 0.4f; // Number of seconds to lerp from texture 1 to texture 2 + float flFlowUvScrollDistance = 0.2f; // Distance in uv space to fetch + float flBumpStrength = 1.0f; + float flTimeScale = 0.75f; + //*/ + + /* Swamp - Heavy churn + float flWorldUvScale = 1.0f / 10.0f; + float flNormalUvScale = 1.0f / 1.15f; + float flFlowTimeIntervalInSeconds = 0.4f; // Number of seconds to lerp from texture 1 to texture 2 + float flFlowUvScrollDistance = 0.25f; // Distance in uv space to fetch + float flBumpStrength = 3.0f; + float flTimeScale = 1.0f; + //*/ + + /* Swamp - Calmer + float flWorldUvScale = 1.0f / 10.0f; + float flNormalUvScale = 1.0f / 1.15f; + float flFlowTimeIntervalInSeconds = 0.25f; // Number of seconds to lerp from texture 1 to texture 2 + float flFlowUvScrollDistance = 0.15f; // Distance in uv space to fetch + float flBumpStrength = 1.05f; + float flTimeScale = 0.35f; + //*/ + + // Input uv + float2 vWorldUv = normalMapTexCoord.xy * flWorldUvScale; + float2 vUv1 = float2( i.worldPos_normalMapY.x, -i.worldPos_normalMapY.y ) * flNormalUvScale; + float2 vUv2 = vUv1.xy; + + // Noise texture is used to offset the time interval different spatially so we don't see pulsing + float flNoise = tex2D( FlowNoiseSampler, float2( i.worldPos_normalMapY.x, -i.worldPos_normalMapY.y ) * flNoiseScale ).g; + + // Flow texel has a 2D flow vector in the rg channels of the texture + float4 vFlowTexel = tex2D( FlowSampler, vWorldUv.xy ); + #if FLOW_DEBUG + { + return float4( vFlowTexel.rgb, 0 ); + } + #endif + + // Unpack world flow vector from texture + float2 vFlowVectorTs = ( vFlowTexel.rg * 2.0f ) - 1.0f; + + float flTimeInIntervals = ( ( g_flTime * flTimeScale ) + flNoise ) / ( flFlowTimeIntervalInSeconds * 2.0f ); + float flScrollTime1 = frac( flTimeInIntervals ); + float flScrollTime2 = frac( flTimeInIntervals + 0.5f ); // Half an interval off from texture 1 + + // Every interval has a unique offset so we don't see the same bump texels repeating continuously + float flOffset1 = floor( flTimeInIntervals ) * 0.311f; + float flOffset2 = floor( flTimeInIntervals + 0.5f ) * 0.311f + 0.5f; // The +0.5 is to match the phase offset + + // Final flow uv is originalUv + interval offset + ( flowvector * scroll + float2 vFlowUv1 = vUv1.xy + flOffset1 + ( flScrollTime1 * ( flFlowUvScrollDistance * vFlowVectorTs.xy ) ); + float2 vFlowUv2 = vUv2.xy + flOffset2 + ( flScrollTime2 * ( flFlowUvScrollDistance * vFlowVectorTs.xy ) ); + + // Lerp values to blend between the two layers of bump + float flWeight1 = abs( ( 2.0f * frac( flTimeInIntervals + 0.5f ) ) - 1.0f ); + float flWeight2 = abs( ( 2.0f * frac( flTimeInIntervals ) ) - 1.0f ); + + float4 vNormalTexel1 = tex2D( NormalMapSampler, vFlowUv1.xy ); + float4 vNormalTexel2 = tex2D( NormalMapSampler, vFlowUv2.xy ); + + float3 vNormal1 = ( vNormalTexel1.rgb ); + float3 vNormal2 = ( vNormalTexel2.rgb ); + + // Combine both layers + vNormal.xy = UnpackNormal2D( lerp( vNormal1.xy, vNormal2.xy, flWeight2 ) ); + + // Change bump strength based on the length of the flow vector + //vNormal.xy *= ( length( vFlowVectorTs.xy ) + 0.05f ) * flBumpStrength; + vNormal.xy *= ( ( vFlowVectorTs.x * vFlowVectorTs.x + vFlowVectorTs.y * vFlowVectorTs.y ) + 0.05f ) * flBumpStrength; + + // Generate normal from 2D scaled normal + vNormal.xyz = ComputeNormalFromXY( vNormal.xy ); + } + #elif ( MULTITEXTURE ) + { + vNormal.xyz = tex2D( NormalMapSampler, normalMapTexCoord ); + float3 vNormal1 = tex2D( NormalMapSampler, i.vExtraBumpTexCoord.xy ); + float3 vNormal2 = tex2D( NormalMapSampler, i.vExtraBumpTexCoord.zw ); + vNormal = 0.33 * ( vNormal + vNormal1 + vNormal2 ); + + vNormal = 2.0 * vNormal - 1.0; + } + #else + { + vNormal.xyz = DecompressNormal( NormalMapSampler, normalMapTexCoord, NORM_DECODE_NONE ); + } + #endif + + float3 worldSpaceNormal = mul( vNormal, i.tangentSpaceTranspose ); + float3 worldSpaceEye; + + float flWorldSpaceDist = 1.0f; + + #ifdef NV3X + // for some reason, fxc doesn't convert length( half3 v ) into all _pp opcodes. + #if ( BLEND ) + { + worldSpaceEye = i.worldSpaceEyeVect_normalMapX.xyz; + float worldSpaceDistSqr = dot( worldSpaceEye, worldSpaceEye ); + float rcpWorldSpaceDist = rsqrt( worldSpaceDistSqr ); + worldSpaceEye *= rcpWorldSpaceDist; + flWorldSpaceDist = worldSpaceDistSqr * rcpWorldSpaceDist; + } + #else + { + worldSpaceEye = NormalizeWithCubemap( NormalizeSampler, i.worldSpaceEyeVect_normalMapX.xyz ); + } + #endif + #else // !NV3X + #if ( BLEND ) + { + worldSpaceEye = i.worldSpaceEyeVect_normalMapX.xyz; + flWorldSpaceDist = length( worldSpaceEye ); + worldSpaceEye /= flWorldSpaceDist; + } + #else + { + worldSpaceEye = NormalizeWithCubemap( NormalizeSampler, i.worldSpaceEyeVect_normalMapX.xyz ); + } + #endif + #endif + + float3 reflectVect = CalcReflectionVectorUnnormalized( worldSpaceNormal, worldSpaceEye ); + float3 specularLighting = ENV_MAP_SCALE * texCUBE( EnvmapSampler, reflectVect ); + specularLighting *= g_ReflectTint; + + #if FRESNEL + // FIXME: It's unclear that we want to do this for cheap water + // but the code did this previously and I didn't want to change it + float flDotResult = dot( worldSpaceEye, worldSpaceNormal ); + flDotResult = 1.0f - max( 0.0f, flDotResult ); + + float flFresnelFactor = flDotResult * flDotResult; + flFresnelFactor *= flFresnelFactor; + flFresnelFactor *= flDotResult; + #else + float flFresnelFactor = g_ReflectTint.a; + #endif + + float flAlpha; + #if ( BLEND ) + { + float flReflectAmount = saturate( flWorldSpaceDist * g_CheapWaterDeltaRecip - g_CheapWaterStartDivDelta ); + flAlpha = saturate( flFresnelFactor + flReflectAmount ); + + #if REFRACTALPHA + // Perform division by W only once + float ooW = 1.0f / i.vRefract_W_ProjZ.z; + float2 unwarpedRefractTexCoord = i.vRefract_W_ProjZ * ooW; + float fogDepthValue = tex2D( RefractSampler, unwarpedRefractTexCoord ).a; + // Fade on the border between the water and land. + flAlpha *= saturate( ( fogDepthValue - .05f ) * 20.0f ); + #endif + } + #else + { + flAlpha = 1.0f; + #if HDRTYPE == 0 || HDRENABLED == 0 + specularLighting = lerp( g_WaterFogColor, specularLighting, flFresnelFactor ); + #else + specularLighting = lerp( GammaToLinear( g_WaterFogColor ), specularLighting, flFresnelFactor ); + #endif + } + #endif + + // multiply the color by alpha.since we are using alpha blending to blend against dest alpha for borders. + + #if (PIXELFOGTYPE == PIXEL_FOG_TYPE_RANGE) + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_PixelFogParams, g_EyePos.xyz, i.worldPos_normalMapY.xyz, i.vRefract_W_ProjZ.w ); + #else + float fogFactor = 0; + #endif + + return FinalOutput( float4( specularLighting, flAlpha ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR ); +} diff --git a/materialsystem/stdshaders/WaterCheap_vs20.fxc b/materialsystem/stdshaders/WaterCheap_vs20.fxc new file mode 100644 index 00000000..d8dbebd1 --- /dev/null +++ b/materialsystem/stdshaders/WaterCheap_vs20.fxc @@ -0,0 +1,86 @@ +// STATIC: "BLEND" "0..1" +#include "common_vs_fxc.h" + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vNormal : NORMAL; + float2 vNormalMapCoord : TEXCOORD0; + float3 vTangentS : TANGENT; + float3 vTangentT : BINORMAL; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + float fog : FOG; +#endif + float4 worldVertToEyeVector_normalMapX : TEXCOORD1; + float3x3 tangentSpaceTranspose : TEXCOORD2; + float4 vRefract_W_ProjZ : TEXCOORD5; + float4 vExtraBumpTexCoord : TEXCOORD6; + float4 worldPos_normalMapY : TEXCOORD7; +}; + +const float4 cNormalMapTransform[2] : register( SHADER_SPECIFIC_CONST_0 ); +const float4 TexOffsets : register( SHADER_SPECIFIC_CONST_3 ); + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 vObjNormal; + DecompressVertex_Normal( v.vNormal, vObjNormal ); + + float4 projPos; + float3 worldPos; + + projPos = mul( v.vPos, cModelViewProj ); + o.projPos = projPos; + +#if BLEND + // Map projected position to the reflection texture + o.vRefract_W_ProjZ.x = projPos.x; + o.vRefract_W_ProjZ.y = -projPos.y; // invert Y + o.vRefract_W_ProjZ.xy = (o.vRefract_W_ProjZ + projPos.w) * 0.5f; + o.vRefract_W_ProjZ.z = projPos.w; +#endif + + o.vRefract_W_ProjZ.w = projPos.z; + + worldPos = mul( v.vPos, cModel[0] ); + + float3 worldTangentS = mul( v.vTangentS, ( const float3x3 )cModel[0] ); + float3 worldTangentT = mul( v.vTangentT, ( const float3x3 )cModel[0] ); + float3 worldNormal = mul( vObjNormal, ( float3x3 )cModel[0] ); + o.tangentSpaceTranspose[0] = worldTangentS; + o.tangentSpaceTranspose[1] = worldTangentT; + o.tangentSpaceTranspose[2] = worldNormal; + + float3 worldVertToEyeVector = VSHADER_VECT_SCALE * (cEyePos - worldPos); + o.worldVertToEyeVector_normalMapX.xyz = worldVertToEyeVector; + + // FIXME: need to add a normalMapTransform to all of the water shaders. + //o.worldVertToEyeVector_normalMapX.w = dot( v.vNormalMapCoord, cNormalMapTransform[0] ) + cNormalMapTransform[0].w; + //o.worldPos_normalMapY.w = dot( v.vNormalMapCoord, cNormalMapTransform[1] ) + cNormalMapTransform[1].w; + o.worldVertToEyeVector_normalMapX.w = v.vNormalMapCoord.x; + o.worldPos_normalMapY.w = v.vNormalMapCoord.y; + + float f45x=v.vNormalMapCoord.x+v.vNormalMapCoord.y; + float f45y=v.vNormalMapCoord.y-v.vNormalMapCoord.x; + o.vExtraBumpTexCoord.x=f45x*0.1+TexOffsets.x; + o.vExtraBumpTexCoord.y=f45y*0.1+TexOffsets.y; + o.vExtraBumpTexCoord.z=v.vNormalMapCoord.y*0.45+TexOffsets.z; + o.vExtraBumpTexCoord.w=v.vNormalMapCoord.x*0.45+TexOffsets.w; + + o.worldPos_normalMapY.xyz = worldPos; + +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + o.fog = CalcFixedFunctionFog( worldPos, FOGTYPE_RANGE ); +#endif + + return o; +} + + diff --git a/materialsystem/stdshaders/Water_vs20.fxc b/materialsystem/stdshaders/Water_vs20.fxc new file mode 100644 index 00000000..13b44db7 --- /dev/null +++ b/materialsystem/stdshaders/Water_vs20.fxc @@ -0,0 +1,160 @@ +//============ Copyright (c) Valve Corporation, All rights reserved. ============ + +// STATIC: "BASETEXTURE" "0..1" +// STATIC: "MULTITEXTURE" "0..1" +// STATIC: "FLASHLIGHT" "0..1" +// STATIC: "LIGHTMAPWATERFOG" "0..1" +// STATIC: "FLOWMAP" "0..1" + +// Multitexture and basetexture are mutually exclusive. +// SKIP: $MULTITEXTURE && $BASETEXTURE + +// flowmap doesn't play with multitexture or basetexture +// SKIP: $FLOWMAP && $MULTITEXTURE + +// Have to have the flashlight on to get flashlightshadows. +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 ) + +// basetexture doesn't work with flashlight or lightmapwaterfog. multitexture doesn't either. We don't use basetexture or multitexture in newer code and instead use flowmap and flashlight. +// SKIP: ( $FLASHLIGHT || $LIGHTMAPWATERFOG ) && ( ( $BASETEXTURE && !$FLOWMAP ) || $MULTITEXTURE ) + +#include "common_vs_fxc.h" + +const float4 cBumpTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_1 ); +const float4 TexOffsets : register( SHADER_SPECIFIC_CONST_3 ); + +#if FLASHLIGHT + const float4x4 g_FlashlightWorldToTexture : register( SHADER_SPECIFIC_CONST_4 ); +#endif + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vNormal : NORMAL; + float4 vBaseTexCoord : TEXCOORD0; + float2 vLightmapTexCoord : TEXCOORD1; + float2 vLightmapTexCoordOffset : TEXCOORD2; + float3 vTangentS : TANGENT; + float3 vTangentT : BINORMAL0; +}; + +struct VS_OUTPUT +{ + float4 vProjPos_POSITION : POSITION; + #if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + float fog : FOG; + #endif + float2 vBumpTexCoord : TEXCOORD0; + float3 vPositionToCameraRayWs : TEXCOORD1; + float4 vReflectXY_vRefractYX : TEXCOORD2; + float4 vProjPos : TEXCOORD3; + float3 worldPos : TEXCOORD4; + #if FLASHLIGHT + float4 flashlightSpacePos : TEXCOORD5; + #endif + #if MULTITEXTURE + float4 vExtraBumpTexCoord : TEXCOORD5; + #endif + #if ( BASETEXTURE && !FLOWMAP ) + float4 lightmapTexCoord1And2 : TEXCOORD5; + float2 lightmapTexCoord3 : TEXCOORD6; + #endif + + #if LIGHTMAPWATERFOG + float2 lightmapTexCoord : TEXCOORD7; + #endif +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o; + + float3 vObjNormal; + DecompressVertex_Normal( v.vNormal, vObjNormal ); + + // Projected position + float4 vProjPos = mul( v.vPos, cModelViewProj ); + o.vProjPos = o.vProjPos_POSITION = vProjPos; + + // Project tangent basis + float2 vProjTangentS = mul( v.vTangentS, cViewProj ); + float2 vProjTangentT = mul( v.vTangentT, cViewProj ); + + // Map projected position to the reflection texture + float2 vReflectPos; + vReflectPos = (vProjPos.xy + vProjPos.w) * 0.5f; + + // Map projected position to the refraction texture + float2 vRefractPos; + vRefractPos.x = vProjPos.x; + vRefractPos.y = -vProjPos.y; // invert Y + vRefractPos = (vRefractPos + vProjPos.w) * 0.5f; + + // Reflection transform + o.vReflectXY_vRefractYX = float4( vReflectPos.x, vReflectPos.y, vRefractPos.y, vRefractPos.x ); + + // Compute fog based on the position + float3 vWorldPos = mul( v.vPos, cModel[0] ); + o.worldPos = vWorldPos; + + #if ( !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) ) + { + o.fog = CalcFixedFunctionFog( vWorldPos, FOGTYPE_RANGE ); + } + #endif + + // Eye vector + float3 vPositionToCameraRayWs = cEyePos.xyz - vWorldPos.xyz; + + // Transform to the tangent space + //o.vTangentEyeVect.x = dot( vPositionToCameraRayWs, v.vTangentS ); + //o.vTangentEyeVect.y = dot( vPositionToCameraRayWs, v.vTangentT ); + //o.vTangentEyeVect.z = dot( vPositionToCameraRayWs, vObjNormal ); + + o.vPositionToCameraRayWs.xyz = vPositionToCameraRayWs.xyz; + + // Tranform bump coordinates + o.vBumpTexCoord.x = dot( v.vBaseTexCoord, cBumpTexCoordTransform[0] ); + o.vBumpTexCoord.y = dot( v.vBaseTexCoord, cBumpTexCoordTransform[1] ); + float f45x=v.vBaseTexCoord.x+v.vBaseTexCoord.y; + float f45y=v.vBaseTexCoord.y-v.vBaseTexCoord.x; + #if ( MULTITEXTURE ) + { + o.vExtraBumpTexCoord.x=f45x*0.1+TexOffsets.x; + o.vExtraBumpTexCoord.y=f45y*0.1+TexOffsets.y; + o.vExtraBumpTexCoord.z=v.vBaseTexCoord.y*0.45+TexOffsets.z; + o.vExtraBumpTexCoord.w=v.vBaseTexCoord.x*0.45+TexOffsets.w; + } + #endif + + #if ( BASETEXTURE && !FLOWMAP ) + { + o.lightmapTexCoord1And2.xy = v.vLightmapTexCoord + v.vLightmapTexCoordOffset; + + float2 lightmapTexCoord2 = o.lightmapTexCoord1And2.xy + v.vLightmapTexCoordOffset; + float2 lightmapTexCoord3 = lightmapTexCoord2 + v.vLightmapTexCoordOffset; + + // reversed component order + o.lightmapTexCoord1And2.w = lightmapTexCoord2.x; + o.lightmapTexCoord1And2.z = lightmapTexCoord2.y; + + o.lightmapTexCoord3.xy = lightmapTexCoord3; + } + #endif + + #if LIGHTMAPWATERFOG + { + o.lightmapTexCoord.xy = v.vLightmapTexCoord.xy; + } + #endif + + #if FLASHLIGHT + { + o.flashlightSpacePos = mul( float4( vWorldPos, 1.0f ), g_FlashlightWorldToTexture ); + } + #endif + + return o; +} + + diff --git a/materialsystem/stdshaders/WorldVertexAlpha.psh b/materialsystem/stdshaders/WorldVertexAlpha.psh new file mode 100644 index 00000000..e610452e --- /dev/null +++ b/materialsystem/stdshaders/WorldVertexAlpha.psh @@ -0,0 +1,10 @@ +ps.1.1 + +tex t0 ; basetexture +tex t1 ; lightmap + +mov r0.a, 1-t1.a +;mov r0.rgb, t0 ; * 2 * (overbrightFactor/2) +;mov_x2 r0.rgb, t0 ; * 2 * (overbrightFactor/2) +mul r0.rgb, t0, t1; +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/materialsystem/stdshaders/WorldVertexAlpha.vsh b/materialsystem/stdshaders/WorldVertexAlpha.vsh new file mode 100644 index 00000000..a026f18d --- /dev/null +++ b/materialsystem/stdshaders/WorldVertexAlpha.vsh @@ -0,0 +1,37 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +#include "macros.vsh" + +local( $worldPos, $worldNormal, $projPos, $reflectionVector ); + +&AllocateRegister( \$projPos ); + +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 +mov oPos, $projPos + +&AllocateRegister( \$worldPos ); + +; garymcthack +dp4 $worldPos.z, $vPos, $cModel2 + +&CalcFog( $worldPos, $projPos ); + +&FreeRegister( \$worldPos ); +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ +; base texcoords +mov oT0, $vTexCoord0 + +; lightmap texcoords +mov oT1, $vTexCoord1 + +&FreeRegister( \$worldPos ); # garymcthack + diff --git a/materialsystem/stdshaders/WorldVertexAlpha_ps2x.fxc b/materialsystem/stdshaders/WorldVertexAlpha_ps2x.fxc new file mode 100644 index 00000000..53118584 --- /dev/null +++ b/materialsystem/stdshaders/WorldVertexAlpha_ps2x.fxc @@ -0,0 +1,42 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "PASS" "0..1" + +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_fxc.h" + +// CENTROID: TEXCOORD1 + +sampler BaseSampler : register( s0 ); +sampler LightmapSampler: register( s1 ); +sampler LightmapAlphaSampler: register( s2 ); + +struct PS_INPUT +{ + float2 baseCoord : TEXCOORD0; + float2 lightmapCoord : TEXCOORD1; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + bool bAlphaPass = PASS ? true : false; + + float4 base = tex2D( BaseSampler, i.baseCoord ); + float4 lightmap = tex2D( LightmapSampler, i.lightmapCoord ); + float4 alpha = tex2D( LightmapAlphaSampler, i.lightmapCoord ); + + float4 color; + + base.a = dot( base, HALF3( HALF_CONSTANT(0.33333f), HALF_CONSTANT(0.33333f), HALF_CONSTANT(0.33333f) ) ); + color = 2.0f * base * lightmap; // The 2x is for an assumed overbright 2 (it's always 2 on dx9) + + if( bAlphaPass ) + { + // Don't care about color, just return pre-multiplied alpha + return FinalOutput( float4( 0.0f, 0.0f, 1.0f, (1.0f - alpha.a) * color.a ), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); + } + else + { + return FinalOutput( float4( color.rgb, (1.0f - alpha.a) ), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); + } +} diff --git a/materialsystem/stdshaders/WorldVertexTransition.vsh b/materialsystem/stdshaders/WorldVertexTransition.vsh new file mode 100644 index 00000000..07c3ada9 --- /dev/null +++ b/materialsystem/stdshaders/WorldVertexTransition.vsh @@ -0,0 +1,48 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +#include "macros.vsh" + +local( $worldPos, $worldNormal, $projPos, $reflectionVector ); + +&AllocateRegister( \$projPos ); + +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 +mov oPos, $projPos + +&AllocateRegister( \$worldPos ); + +; garymcthack +dp4 $worldPos.z, $vPos, $cModel2 + +&CalcFog( $worldPos, $projPos ); + +&FreeRegister( \$worldPos ); +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ +; base texcoords +dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 +dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 + +dp4 oT1.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_2 +dp4 oT1.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_3 + +; lightmap texcoords +mov oT2, $vTexCoord1 + +; detail +dp4 oT3.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_4 +dp4 oT3.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_5 + +; Now the basetexture/basetexture2 blend uses vertex color, so send it into the psh. +mov oD0, $vColor + +&FreeRegister( \$worldPos ); # garymcthack + diff --git a/materialsystem/stdshaders/WorldVertexTransition_BlendBase2.psh b/materialsystem/stdshaders/WorldVertexTransition_BlendBase2.psh new file mode 100644 index 00000000..d4a5c623 --- /dev/null +++ b/materialsystem/stdshaders/WorldVertexTransition_BlendBase2.psh @@ -0,0 +1,16 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t0 +tex t1 +mul r0.rgb, t1, t0 ; fold in lightmap (color) ++mov r0.a, v0.a ; fold in lightmap (alpha) +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + diff --git a/materialsystem/stdshaders/WorldVertexTransition_Editor.psh b/materialsystem/stdshaders/WorldVertexTransition_Editor.psh new file mode 100644 index 00000000..936edc9e --- /dev/null +++ b/materialsystem/stdshaders/WorldVertexTransition_Editor.psh @@ -0,0 +1,10 @@ +ps.1.1 + +tex t0 ; basetexture +tex t1 ; basetexture2 +tex t2 ; lightmap + +; The editor uses vertex alpha as the blend factor +lrp r0, 1-v0.a, t1, t0 +mul r0, r0, t2 +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/materialsystem/stdshaders/WorldVertexTransition_ps2x.fxc b/materialsystem/stdshaders/WorldVertexTransition_ps2x.fxc new file mode 100644 index 00000000..4cf72fea --- /dev/null +++ b/materialsystem/stdshaders/WorldVertexTransition_ps2x.fxc @@ -0,0 +1,50 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "MACROS" "0..1" + +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_fxc.h" + +sampler BaseSampler : register( s0 ); +// NOTE: LightmapSampler is at the same place as the lightmap sampler in lightmappedgeneric so that we have +// generally the same texture state here. +sampler LightmapSampler: register( s1 ); +sampler BaseSampler2: register( s2 ); +sampler LightmapAlphaSampler: register( s3 ); +sampler MacrosSampler: register( s4 ); + +struct PS_INPUT +{ + float2 baseCoord : TEXCOORD0; + float2 baseCoord2 : TEXCOORD1; +// CENTROID: TEXCOORD2 + #if defined( _X360 ) + float2 lightmapCoord : TEXCOORD2_centroid; + #else + float2 lightmapCoord : TEXCOORD2; + #endif + float2 macrosCoord : TEXCOORD3; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + bool bMacros = MACROS ? true : false; + + float4 base = tex2D( BaseSampler, i.baseCoord ); + float4 base2 = tex2D( BaseSampler2, i.baseCoord2 ); + + float4 lightmap = tex2D( LightmapSampler, i.lightmapCoord ); + float blendFactor = lightmap.a; + + float4 color = 2.0f * lightmap * lerp( base2, base, blendFactor ); + if( bMacros ) + { + float4 macros = tex2D( MacrosSampler, i.macrosCoord ); + + // Not sure what to do with macro alpha + color.rgb *= 2.0f * lerp( macros.a, macros.b, blendFactor ); + } + + return FinalOutput( color, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} + diff --git a/materialsystem/stdshaders/WorldVertexTransition_vs20.fxc b/materialsystem/stdshaders/WorldVertexTransition_vs20.fxc new file mode 100644 index 00000000..37f2f63b --- /dev/null +++ b/materialsystem/stdshaders/WorldVertexTransition_vs20.fxc @@ -0,0 +1,62 @@ +#include "common_fog_vs_fxc.h" + +#include "common_vs_fxc.h" + +static const int g_FogType = DOWATERFOG; + +const float4 cBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_0 ); +const float4 cBaseTexCoordTransform2[2] : register( SHADER_SPECIFIC_CONST_2 ); +const float4 cMacrosTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_4 ); + +struct VS_INPUT +{ + // This is all of the stuff that we ever use. + float4 vPos : POSITION; + float4 vColor : COLOR0; + float4 vTexCoord0 : TEXCOORD0; + float4 vTexCoord1 : TEXCOORD1; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; +#if !defined( _X360 ) + float fog : FOG; +#endif + float2 baseCoord : TEXCOORD0; + float2 baseCoord2 : TEXCOORD1; + float2 lightmapCoord : TEXCOORD2; + float2 macrosCoord : TEXCOORD3; + float4 color : COLOR0; +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 worldNormal, worldPos; + float2 texCoord; + worldPos = mul( v.vPos, cModel[0] ); + float4 projPos = mul( float4( worldPos, 1 ), cViewProj ); + o.projPos = projPos; + o.fogFactorsYZW = CalcFog( worldPos, projPos, g_FogType ); +#if !defined( _X360 ) + o.fog = o.fogFactorsYZW; +#endif + o.color = v.vColor; + + o.baseCoord.x = dot( v.vTexCoord0, cBaseTexCoordTransform[0] ); + o.baseCoord.y = dot( v.vTexCoord0, cBaseTexCoordTransform[1] ); + + o.baseCoord2.x = dot( v.vTexCoord0, cBaseTexCoordTransform2[0] ); + o.baseCoord2.y = dot( v.vTexCoord0, cBaseTexCoordTransform2[1] ); + + o.lightmapCoord = v.vTexCoord1; + + o.macrosCoord.x = dot( v.vTexCoord0, cMacrosTexCoordTransform[0] ); + o.macrosCoord.y = dot( v.vTexCoord0, cMacrosTexCoordTransform[1] ); + + return o; +} + + diff --git a/materialsystem/stdshaders/aftershock.cpp b/materialsystem/stdshaders/aftershock.cpp new file mode 100644 index 00000000..bb1df244 --- /dev/null +++ b/materialsystem/stdshaders/aftershock.cpp @@ -0,0 +1,71 @@ +//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============// + +#include "BaseVSShader.h" +#include "aftershock_helper.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( Aftershock, Aftershock_dx9 ) +BEGIN_VS_SHADER( Aftershock_dx9, "Aftershock" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( COLORTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Color tint" ) + SHADER_PARAM( REFRACTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "2", "" ) + + SHADER_PARAM( NORMALMAP, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "normal map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + + SHADER_PARAM( SILHOUETTETHICKNESS, SHADER_PARAM_TYPE_FLOAT, "1", "" ) + SHADER_PARAM( SILHOUETTECOLOR, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Silhouette color tint" ) + SHADER_PARAM( GROUNDMIN, SHADER_PARAM_TYPE_FLOAT, "1", "" ) + SHADER_PARAM( GROUNDMAX, SHADER_PARAM_TYPE_FLOAT, "1", "" ) + SHADER_PARAM( BLURAMOUNT, SHADER_PARAM_TYPE_FLOAT, "1", "" ) + + SHADER_PARAM( TIME, SHADER_PARAM_TYPE_FLOAT, "0.0", "Needs CurrentTime Proxy" ) + END_SHADER_PARAMS + + void SetupVarsAftershock( AftershockVars_t &info ) + { + info.m_nColorTint = COLORTINT; + info.m_nRefractAmount = REFRACTAMOUNT; + + info.m_nBumpmap = NORMALMAP; + info.m_nBumpFrame = BUMPFRAME; + info.m_nBumpTransform = BUMPTRANSFORM; + + info.m_nSilhouetteThickness = SILHOUETTETHICKNESS; + info.m_nSilhouetteColor = SILHOUETTECOLOR; + info.m_nGroundMin = GROUNDMIN; + info.m_nGroundMax = GROUNDMAX; + info.m_nBlurAmount = BLURAMOUNT; + + info.m_nTime = TIME; + } + + SHADER_INIT_PARAMS() + { + AftershockVars_t info; + SetupVarsAftershock( info ); + InitParamsAftershock( this, params, pMaterialName, info ); + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + AftershockVars_t info; + SetupVarsAftershock( info ); + InitAftershock( this, params, info ); + } + + SHADER_DRAW + { + AftershockVars_t info; + SetupVarsAftershock( info ); + DrawAftershock( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } +END_SHADER diff --git a/materialsystem/stdshaders/aftershock_helper.cpp b/materialsystem/stdshaders/aftershock_helper.cpp new file mode 100644 index 00000000..8050bb66 --- /dev/null +++ b/materialsystem/stdshaders/aftershock_helper.cpp @@ -0,0 +1,199 @@ +//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============// + +#include "BaseVSShader.h" +#include "mathlib/VMatrix.h" +#include "aftershock_helper.h" +#include "convar.h" + +// Auto generated inc files +#include "aftershock_vs20.inc" +#include "aftershock_ps20.inc" +#include "aftershock_ps20b.inc" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +void InitParamsAftershock( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, AftershockVars_t &info ) +{ + // Set material flags + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + + SET_FLAGS( MATERIAL_VAR_TRANSLUCENT ); + SET_FLAGS2( MATERIAL_VAR2_NEEDS_POWER_OF_TWO_FRAME_BUFFER_TEXTURE ); + + // Set material parameter default values + if ( ( info.m_nRefractAmount != -1 ) && ( !params[info.m_nRefractAmount]->IsDefined() ) ) + { + params[info.m_nRefractAmount]->SetFloatValue( kDefaultRefractAmount ); + } + + if ( ( info.m_nColorTint != -1 ) && ( !params[info.m_nColorTint]->IsDefined() ) ) + { + params[info.m_nColorTint]->SetVecValue( kDefaultColorTint[0], kDefaultColorTint[1], kDefaultColorTint[2], kDefaultColorTint[3] ); + } + + if( (info.m_nBumpFrame != -1 ) && !params[info.m_nBumpFrame]->IsDefined() ) + { + params[info.m_nBumpFrame]->SetIntValue( 0 ); + } + + if ( ( info.m_nSilhouetteThickness != -1 ) && ( !params[info.m_nSilhouetteThickness]->IsDefined() ) ) + { + params[info.m_nSilhouetteThickness]->SetFloatValue( kDefaultSilhouetteThickness ); + } + + if ( ( info.m_nSilhouetteColor != -1 ) && ( !params[info.m_nSilhouetteColor]->IsDefined() ) ) + { + params[info.m_nSilhouetteColor]->SetVecValue( kDefaultSilhouetteColor[0], kDefaultSilhouetteColor[1], kDefaultSilhouetteColor[2], kDefaultSilhouetteColor[3] ); + } + + if ( ( info.m_nGroundMin != -1 ) && ( !params[info.m_nGroundMin]->IsDefined() ) ) + { + params[info.m_nGroundMin]->SetFloatValue( kDefaultGroundMin ); + } + + if ( ( info.m_nGroundMax != -1 ) && ( !params[info.m_nGroundMax]->IsDefined() ) ) + { + params[info.m_nGroundMax]->SetFloatValue( kDefaultGroundMax ); + } + + if ( ( info.m_nBlurAmount != -1 ) && ( !params[info.m_nBlurAmount]->IsDefined() ) ) + { + params[info.m_nBlurAmount]->SetFloatValue( kDefaultBlurAmount ); + } + + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nTime, 0.0f ); +} + +void InitAftershock( CBaseVSShader *pShader, IMaterialVar** params, AftershockVars_t &info ) +{ + // Load textures + if ( (info.m_nBumpmap != -1) && params[info.m_nBumpmap]->IsDefined() ) + { + pShader->LoadTexture( info.m_nBumpmap ); + } +} + +void DrawAftershock( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, AftershockVars_t &info, VertexCompressionType_t vertexCompression ) +{ + bool bBumpMapping = ( info.m_nBumpmap == -1 ) || !params[info.m_nBumpmap]->IsTexture() ? 0 : 1; + + SHADOW_STATE + { + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + // Vertex Shader + DECLARE_STATIC_VERTEX_SHADER( aftershock_vs20 ); + SET_STATIC_VERTEX_SHADER( aftershock_vs20 ); + + // Pixel Shader + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( aftershock_ps20b ); + SET_STATIC_PIXEL_SHADER( aftershock_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( aftershock_ps20 ); + SET_STATIC_PIXEL_SHADER( aftershock_ps20 ); + } + + // Textures + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); // Refraction texture + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); // Bump + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, false ); // Not sRGB + pShaderShadow->EnableSRGBWrite( true ); + + // Blending + pShader->EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + pShaderShadow->EnableAlphaWrites( false ); + + // !!! We need to turn this back on because EnableAlphaBlending() above disables it! + //pShaderShadow->EnableDepthWrites( true ); + } + DYNAMIC_STATE + { + // Set Vertex Shader Combos + DECLARE_DYNAMIC_VERTEX_SHADER( aftershock_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( aftershock_vs20 ); + + // Set Vertex Shader Constants + if ( info.m_nBumpTransform != -1 ) + { + pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, info.m_nBumpTransform ); + } + + // Time % 1000 + float vPackedVsConst1[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + float flTime = IS_PARAM_DEFINED( info.m_nTime ) && params[info.m_nTime]->GetFloatValue() > 0.0f ? params[info.m_nTime]->GetFloatValue() : pShaderAPI->CurrentTime(); + vPackedVsConst1[0] = flTime; + vPackedVsConst1[0] -= (float)( (int)( vPackedVsConst1[0] / 1000.0f ) ) * 1000.0f; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, vPackedVsConst1, 1 ); + + // Set Pixel Shader Combos + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( aftershock_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( aftershock_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( aftershock_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( aftershock_ps20 ); + } + + // Bind textures + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_FRAME_BUFFER_FULL_TEXTURE_0 ); // Refraction Map + if ( bBumpMapping ) + { + pShader->BindTexture( SHADER_SAMPLER1, info.m_nBumpmap, info.m_nBumpFrame ); + } + + // Set Pixel Shader Constants + float vEyePos[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos ); + pShaderAPI->SetPixelShaderConstant( 5, vEyePos, 1 ); + + float vPackedConst1[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vPackedConst1[0] = IS_PARAM_DEFINED( info.m_nBlurAmount ) ? params[info.m_nBlurAmount]->GetFloatValue() : kDefaultBlurAmount; + vPackedConst1[1] = IS_PARAM_DEFINED( info.m_nRefractAmount ) ? params[info.m_nRefractAmount]->GetFloatValue() : kDefaultRefractAmount; + vPackedConst1[3] = vPackedVsConst1[0]; // Time + pShaderAPI->SetPixelShaderConstant( 6, vPackedConst1, 1 ); + + // Refract color tint + pShaderAPI->SetPixelShaderConstant( 7, IS_PARAM_DEFINED( info.m_nColorTint ) ? params[info.m_nColorTint]->GetVecValue() : kDefaultColorTint, 1 ); + + // Silhouette values + float vPackedConst8[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vPackedConst8[0] = IS_PARAM_DEFINED( info.m_nSilhouetteColor ) ? params[info.m_nSilhouetteColor]->GetVecValue()[0] : kDefaultSilhouetteColor[0]; + vPackedConst8[1] = IS_PARAM_DEFINED( info.m_nSilhouetteColor ) ? params[info.m_nSilhouetteColor]->GetVecValue()[1] : kDefaultSilhouetteColor[1]; + vPackedConst8[2] = IS_PARAM_DEFINED( info.m_nSilhouetteColor ) ? params[info.m_nSilhouetteColor]->GetVecValue()[2] : kDefaultSilhouetteColor[2]; + vPackedConst8[3] = IS_PARAM_DEFINED( info.m_nSilhouetteThickness ) ? params[info.m_nSilhouetteThickness]->GetFloatValue() : kDefaultSilhouetteThickness; + pShaderAPI->SetPixelShaderConstant( 8, vPackedConst8, 1 ); + + // Ground min/max + float vPackedConst9[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vPackedConst9[0] = IS_PARAM_DEFINED( info.m_nGroundMin ) ? params[info.m_nGroundMin]->GetFloatValue() : kDefaultGroundMin; + vPackedConst9[1] = IS_PARAM_DEFINED( info.m_nGroundMax ) ? params[info.m_nGroundMax]->GetFloatValue() : kDefaultGroundMax; + pShaderAPI->SetPixelShaderConstant( 9, vPackedConst9, 1 ); + + // Set c0 and c1 to contain first two rows of ViewProj matrix + VMatrix mView, mProj; + pShaderAPI->GetMatrix( MATERIAL_VIEW, mView.m[0] ); + pShaderAPI->GetMatrix( MATERIAL_PROJECTION, mProj.m[0] ); + VMatrix mViewProj = mView * mProj; + mViewProj = mViewProj.Transpose3x3(); + pShaderAPI->SetPixelShaderConstant( 0, mViewProj.m[0], 2 ); + } + pShader->Draw(); +} diff --git a/materialsystem/stdshaders/aftershock_helper.h b/materialsystem/stdshaders/aftershock_helper.h new file mode 100644 index 00000000..f4b41c54 --- /dev/null +++ b/materialsystem/stdshaders/aftershock_helper.h @@ -0,0 +1,56 @@ +//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============// + +#ifndef AFTERSHOCK_HELPER_H +#define AFTERSHOCK_HELPER_H +#ifdef _WIN32 +#pragma once +#endif + +#include + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct AftershockVars_t +{ + AftershockVars_t() { memset( this, 0xFF, sizeof(AftershockVars_t) ); } + + int m_nColorTint; + int m_nRefractAmount; + + int m_nBumpmap; + int m_nBumpFrame; + int m_nBumpTransform; + + int m_nSilhouetteThickness; + int m_nSilhouetteColor; + int m_nGroundMin; + int m_nGroundMax; + int m_nBlurAmount; + + int m_nTime; +}; + +// Default values (Arrays should only be vec[4]) +static const float kDefaultColorTint[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; +static const float kDefaultRefractAmount = 0.1f; +static const float kDefaultSilhouetteThickness = 0.2f; +static const float kDefaultSilhouetteColor[4] = { 0.3f, 0.3f, 0.5f, 1.0f }; +static const float kDefaultGroundMin = -0.3f; +static const float kDefaultGroundMax = -0.1f; +static const float kDefaultBlurAmount = 0.01f; + +void InitParamsAftershock( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, AftershockVars_t &info ); +void InitAftershock( CBaseVSShader *pShader, IMaterialVar** params, AftershockVars_t &info ); +void DrawAftershock( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, AftershockVars_t &info, VertexCompressionType_t vertexCompression ); + +#endif // AFTERSHOCK_HELPER_H diff --git a/materialsystem/stdshaders/aftershock_ps2x.fxc b/materialsystem/stdshaders/aftershock_ps2x.fxc new file mode 100644 index 00000000..8ed08f8f --- /dev/null +++ b/materialsystem/stdshaders/aftershock_ps2x.fxc @@ -0,0 +1,159 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// Includes ======================================================================================= +#include "common_vertexlitgeneric_dx9.h" + +// Texture Samplers =============================================================================== +sampler g_tRefractionSampler : register( s0 ); +sampler g_tBumpSampler : register( s1 ); + +// Shaders Constants and Globals ================================================================== +const float4 g_mViewProj0 : register( c0 ); // 1st row of matrix +const float4 g_mViewProj1 : register( c1 ); // 2nd row of matrix + +const float4 g_vCameraPosition : register( c5 ); +const float4 g_vPackedConst6 : register( c6 ); +#define g_flBlurAmount g_vPackedConst6.x // 0.01f; +#define g_flRefractAmount g_vPackedConst6.y // Default = 1.0f +#define g_flTime g_vPackedConst6.w + +const float4 g_cColorTint : register( c7 ); + +const float4 g_vPackedConst8 : register( c8 ); +#define g_cSilhouetteColor g_vPackedConst8 //= { 0.3, 0.3, 0.5 }; +#define g_flSilhouetteThickness g_vPackedConst8.w //= 0.2f; + +const float2 g_vGroundMinMax : register( c9 ); //= { -0.3, -0.1 }; + +// 8 2D Poisson offsets (designed to use .xy and .wz swizzles (not .zw) +static const float4 g_vPoissonOffset[4] = { float4 (-0.0876f, 0.9703f, 0.5651f, 0.4802f ), + float4 ( 0.1851f, 0.1580f, -0.0617f, -0.2616f ), + float4 (-0.5477f, -0.6603f, 0.0711f, -0.5325f ), + float4 (-0.0751f, -0.8954f, 0.4054f, 0.6384f ) }; + +// Interpolated values ============================================================================ +struct PS_INPUT +{ + float3 vWorldNormal : TEXCOORD0; // World-space normal + float3 vWorldTangent : TEXCOORD1; + float3 vWorldBinormal : TEXCOORD2; + float3 vProjPosForRefract : TEXCOORD3; + float3 vWorldViewVector : TEXCOORD4; + float4 vUv0 : TEXCOORD5; // uv.xy, uvScroll.xy + float4 vUv1 : TEXCOORD6; // uv.xy, uvScroll.xy + float2 vUvGroundNoise : TEXCOORD7; +}; + +// Main =========================================================================================== +float4 main( PS_INPUT i ) : COLOR +{ + /* + // Bump layer 0 + float2 vUv0 = i.vUv0Uv1.xy; + float2 vUv0Scroll = i.vUv0Uv1.xy * 3.0f; + vUv0Scroll.y -= g_flTime * 0.1f; + + float4 vBumpTexel0 = tex2D( g_tBumpSampler, vUv0Scroll.xy ); + vBumpTexel0 = tex2D( g_tBumpSampler, vUv0.xy + (vBumpTexel0.xy*0.03) ); + + // Bump layer 1 + float2 vUv1 = i.vUv0Uv1.xy * 10.0f; + float2 vUv1Scroll = i.vUv0Uv1.xy * 32.0f; + vUv1Scroll.y -= g_flTime * 0.1f; + + float4 vBumpTexel1 = tex2D( g_tBumpSampler, vUv1Scroll.xy ); + vBumpTexel1 = tex2D( g_tBumpSampler, vUv1.xy + (vBumpTexel1.xy*0.03) ); + //*/ + + // Bump layer 0 + float4 vBumpTexel0 = tex2D( g_tBumpSampler, i.vUv0.wz ); + vBumpTexel0 = tex2D( g_tBumpSampler, i.vUv0.xy + ( vBumpTexel0.xy*0.03 ) ); + + // Bump layer 1 + float4 vBumpTexel1 = tex2D( g_tBumpSampler, i.vUv1.wz ); + vBumpTexel1 = tex2D( g_tBumpSampler, i.vUv1.xy + ( vBumpTexel1.xy*0.03 ) ); + + // Combine bump layers into tangetn normal + float3 vTangentNormal = ( vBumpTexel0 * 2.0f ) - 1.0f; + vTangentNormal.xyz += ( vBumpTexel1 * 2.0f - 1.0f ) * 0.5f; // * 0.5f; + + // Transform into world space + float3 vWorldNormal = Vec3TangentToWorld( vTangentNormal.xyz, i.vWorldNormal, i.vWorldTangent, i.vWorldBinormal ); + + // Effect mask + //float flEffectMask = saturate( dot( -i.vWorldViewVector.xyz, i.vWorldNormal.xyz ) * lerp( 2.0f, 1.0f, g_flSilhouetteThickness ) ); + float flEffectMask = saturate( dot( -i.vWorldViewVector.xyz, i.vWorldNormal.xyz ) * ( (2.0f - g_flSilhouetteThickness) ) ); + + // Simulate ground intersection + flEffectMask *= smoothstep( g_vGroundMinMax.x, g_vGroundMinMax.y, i.vWorldNormal.z ); + + // Soften mask by squaring term + flEffectMask *= flEffectMask; + + // Silhouette mask + float flSilhouetteHighlightMask = saturate( flEffectMask * ( 1.0f - flEffectMask ) * 4.0f ); + flSilhouetteHighlightMask *= flSilhouetteHighlightMask * flSilhouetteHighlightMask; + + // Transform world space normal into clip space and project + float3 vProjNormal; + vProjNormal.x = dot( vWorldNormal.xyz, g_mViewProj0.xyz ); // 1st row + vProjNormal.y = dot( vWorldNormal.xyz, g_mViewProj1.xyz ); // 2nd row + + // Compute coordinates for sampling refraction + float2 vRefractTexCoordNoWarp = i.vProjPosForRefract.xy / i.vProjPosForRefract.z; + float2 vRefractTexCoord = vProjNormal.xy; + float scale = lerp( 0.0f, g_flRefractAmount, flEffectMask );// * flEffectMask * flEffectMask ); // Using flEffectMask^3 + vRefractTexCoord.xy *= scale; + vRefractTexCoord.xy += vRefractTexCoordNoWarp.xy; + + // Blur by scalable Poisson filter + float flBlurAmount = g_flBlurAmount * flEffectMask; + float3 cRefract = tex2D( g_tRefractionSampler, vRefractTexCoord.xy ); + cRefract += tex2D( g_tRefractionSampler, vRefractTexCoord.xy + ( g_vPoissonOffset[0].xy * flBlurAmount ) ); + cRefract += tex2D( g_tRefractionSampler, vRefractTexCoord.xy + ( g_vPoissonOffset[0].wz * flBlurAmount ) ); + cRefract += tex2D( g_tRefractionSampler, vRefractTexCoord.xy + ( g_vPoissonOffset[1].xy * flBlurAmount ) ); + cRefract += tex2D( g_tRefractionSampler, vRefractTexCoord.xy + ( g_vPoissonOffset[1].wz * flBlurAmount ) ); + cRefract += tex2D( g_tRefractionSampler, vRefractTexCoord.xy + ( g_vPoissonOffset[2].xy * flBlurAmount ) ); + cRefract += tex2D( g_tRefractionSampler, vRefractTexCoord.xy + ( g_vPoissonOffset[2].wz * flBlurAmount ) ); + cRefract += tex2D( g_tRefractionSampler, vRefractTexCoord.xy + ( g_vPoissonOffset[3].xy * flBlurAmount ) ); + cRefract += tex2D( g_tRefractionSampler, vRefractTexCoord.xy + ( g_vPoissonOffset[3].wz * flBlurAmount ) ); + cRefract /= 9.0f; + + // Undo tone mapping + cRefract /= LINEAR_LIGHT_SCALE; + + // Refract color tint + float fColorTintStrength = 1.0f - flEffectMask; + float3 cRefractColorTint = lerp( g_cColorTint, 1.0f, fColorTintStrength ); + + // Ground noise + //float flGroundNoise = tex2D( g_tBumpSampler, i.vUvGroundNoise.xy ).g; + //flGroundNoise *= smoothstep( g_vGroundMinMax.y, g_vGroundMinMax.y+0.4, -i.vWorldNormal.z ); + //flGroundNoise = smoothstep( 0.2, 0.9, flGroundNoise ); + + //===============// + // Combine terms // + //===============// + float4 result; + result.rgb = cRefract.rgb * cRefractColorTint.rgb; + result.rgb += result.rgb * ( flSilhouetteHighlightMask * g_cSilhouetteColor.rgb ); + //result.rgb += flGroundNoise; + +//result.rgb = float3( 0.0, 0.0, 0.0 ); +//result.rg = vRefractTexCoord.xy; +//result.rg = i.vUv0Uv1.xy; +//result.rgb = vBumpTexel0.rgb; +//result.rgb = vTangentNormal; +//result.rgb = vWorldNormal; +//result = flEffectMask; +//result = flSilhouetteHighlightMask; + +//result = tex2D( g_tBumpSampler, i.vUvGroundNoise.xy ).y; +//result.rgb = flGroundNoise; + + // Set alpha to... + result.a = flEffectMask; + + + return FinalOutput( result, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_LINEAR ); //go back to final output when it'll fit. +} diff --git a/materialsystem/stdshaders/aftershock_vs20.fxc b/materialsystem/stdshaders/aftershock_vs20.fxc new file mode 100644 index 00000000..a22bb435 --- /dev/null +++ b/materialsystem/stdshaders/aftershock_vs20.fxc @@ -0,0 +1,110 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "SKINNING" "0..1" + +// Includes +#include "common_vs_fxc.h" + +// Globals +static const bool g_bSkinning = SKINNING ? true : false; +const float g_flTime : register( SHADER_SPECIFIC_CONST_0 ); +const float4 cBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_1 ); + +// Structs +struct VS_INPUT +{ + float4 vPos : POSITION; // Position + float4 vNormal : NORMAL; // Normal + float4 vBoneWeights : BLENDWEIGHT; // Skin weights + float4 vBoneIndices : BLENDINDICES; // Skin indices + float4 vTexCoord0 : TEXCOORD0; // Base texture coordinates + float4 vTangent : TANGENT; +}; + +struct VS_OUTPUT +{ + float4 vProjPosition : POSITION; // Projection-space position + float3 vWorldNormal : TEXCOORD0; // World-space normal + float3 vWorldTangent : TEXCOORD1; + float3 vWorldBinormal : TEXCOORD2; + float3 vProjPosForRefract : TEXCOORD3; + float3 vWorldViewVector : TEXCOORD4; + float4 vUv0 : TEXCOORD5; + float4 vUv1 : TEXCOORD6; + float2 vUvGroundNoise : TEXCOORD7; +}; + +// Main +VS_OUTPUT main( const VS_INPUT i ) +{ + VS_OUTPUT o; + + float4 vObjPosition = i.vPos; + float4 vObjTangent = i.vTangent; + float3 vObjNormal; + DecompressVertex_Normal( i.vNormal, vObjNormal ); + + // Transform the position + float3 vWorldPosition = { 0.0f, 0.0f, 0.0f }; + float3 vWorldNormal = { 0.0f, 0.0f, 0.0f }; + float3 vWorldTangent = { 0.0f, 0.0f, 0.0f }; + float3 vWorldBinormal = { 0.0f, 0.0f, 0.0f }; + SkinPositionNormalAndTangentSpace( g_bSkinning, vObjPosition, vObjNormal.xyz, vObjTangent.xyzw, i.vBoneWeights, i.vBoneIndices, vWorldPosition, vWorldNormal, vWorldTangent, vWorldBinormal ); + vWorldNormal.xyz = normalize( vWorldNormal.xyz ); + vWorldTangent.xyz = normalize( vWorldTangent.xyz ); + vWorldBinormal.xyz = normalize( vWorldBinormal.xyz ); + + o.vWorldNormal.xyz = vWorldNormal.xyz; + o.vWorldTangent.xyz = vWorldTangent.xyz; + o.vWorldBinormal.xyz = vWorldBinormal.xyz; + + // Transform into projection space + float4 vProjPosition = mul( float4( vWorldPosition, 1.0f ), cViewProj ); + o.vProjPosition = vProjPosition; + + // Map projected position to the refraction texture + float2 vRefractPos; + vRefractPos.x = vProjPosition.x; + vRefractPos.y = -vProjPosition.y; // Invert Y + vRefractPos = (vRefractPos + vProjPosition.w) * 0.5f; + o.vProjPosForRefract.xyz = float3(vRefractPos.x, vRefractPos.y, vProjPosition.w); + + // View vector + float3 vWorldViewVector = normalize (vWorldPosition.xyz - cEyePos.xyz); + o.vWorldViewVector.xyz = vWorldViewVector.xyz; + + // Tangent space transform + //o.mTangentSpaceTranspose[0] = float3( vWorldTangent.x, vWorldBinormal.x, vWorldNormal.x ); + //o.mTangentSpaceTranspose[1] = float3( vWorldTangent.y, vWorldBinormal.y, vWorldNormal.y ); + //o.mTangentSpaceTranspose[2] = float3( vWorldTangent.z, vWorldBinormal.z, vWorldNormal.z ); + + // Texture coordinates + float2 vBaseUv; + vBaseUv.x = dot( i.vTexCoord0.xy, cBaseTexCoordTransform[0] ); + vBaseUv.y = dot( i.vTexCoord0.xy, cBaseTexCoordTransform[1] ); + + // Bump layer 0 + float2 vUv0 = vBaseUv.xy; + float2 vUv0Scroll = vBaseUv.xy * 3.0f; + vUv0Scroll.y -= g_flTime * 0.1f; + + o.vUv0.xy = vUv0.xy; + o.vUv0.wz = vUv0Scroll.xy; + + // Bump layer 1 + float2 vUv1 = vBaseUv.xy * 8.0f; + float2 vUv1Scroll = vBaseUv.xy * 16.0f; + vUv1Scroll.y -= g_flTime * 0.1f; + + o.vUv1.xy = vUv1.xy; + o.vUv1.wz = vUv1Scroll.xy; + + // Ground noise + o.vUvGroundNoise.xy = vBaseUv.xy; + o.vUvGroundNoise.x *= 3.5f; + o.vUvGroundNoise.y *= 0.2105f; + o.vUvGroundNoise.y -= g_flTime * 0.04f; + + return o; +} diff --git a/materialsystem/stdshaders/bloomadd_ps2x.fxc b/materialsystem/stdshaders/bloomadd_ps2x.fxc new file mode 100644 index 00000000..fb2c35a7 --- /dev/null +++ b/materialsystem/stdshaders/bloomadd_ps2x.fxc @@ -0,0 +1,19 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#include "common_ps_fxc.h" + +sampler TexSampler : register( s0 ); + +float g_flBloomAmount : register( c0 ); + +struct PS_INPUT +{ + HALF2 baseTexCoord : TEXCOORD0; // Base texture coordinate +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float4 result = g_flBloomAmount * tex2D( TexSampler, i.baseTexCoord ); + result.a = 1.0f; + return result; //FinalOutput( result, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} diff --git a/materialsystem/stdshaders/blurentity_ps2x.fxc b/materialsystem/stdshaders/blurentity_ps2x.fxc new file mode 100644 index 00000000..07452bcc --- /dev/null +++ b/materialsystem/stdshaders/blurentity_ps2x.fxc @@ -0,0 +1,34 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// +// blurs colors by averages +// bleeds alpha by max of current vs averages + +sampler g_texSampler : register( s0 ); + +struct PS_INPUT +{ + float2 uv : TEXCOORD0; +}; + +float2 g_vPsTapOffsets[2] : register( c0 ); + +float4 main( PS_INPUT i ) : COLOR +{ + float4 cOut; + + cOut = tex2D( g_texSampler, float2( i.uv.x + g_vPsTapOffsets[0].x, i.uv.y + g_vPsTapOffsets[0].y ) ); + cOut += tex2D( g_texSampler, float2( i.uv.x , i.uv.y + g_vPsTapOffsets[0].y ) ); + cOut += tex2D( g_texSampler, float2( i.uv.x - g_vPsTapOffsets[0].x, i.uv.y + g_vPsTapOffsets[0].y ) ); + + cOut += tex2D( g_texSampler, float2( i.uv.x + g_vPsTapOffsets[0].x, i.uv.y ) ); + cOut += tex2D( g_texSampler, float2( i.uv.x , i.uv.y ) ); + cOut += tex2D( g_texSampler, float2( i.uv.x - g_vPsTapOffsets[0].x, i.uv.y ) ); + + cOut += tex2D( g_texSampler, float2( i.uv.x + g_vPsTapOffsets[0].x, i.uv.y - g_vPsTapOffsets[0].y ) ); + cOut += tex2D( g_texSampler, float2( i.uv.x , i.uv.y - g_vPsTapOffsets[0].y ) ); + cOut += tex2D( g_texSampler, float2( i.uv.x - g_vPsTapOffsets[0].x, i.uv.y - g_vPsTapOffsets[0].y ) ); + + cOut *= (1.0f/9.0f); + + cOut.a = max( cOut.a * 1.0f, tex2D( g_texSampler, i.uv ).a ); //never reduce alpha, only increase it + return saturate( cOut ); +} diff --git a/materialsystem/stdshaders/blurgaussian_3x3_ps2x.fxc b/materialsystem/stdshaders/blurgaussian_3x3_ps2x.fxc new file mode 100644 index 00000000..ef88c835 --- /dev/null +++ b/materialsystem/stdshaders/blurgaussian_3x3_ps2x.fxc @@ -0,0 +1,22 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +sampler g_texSampler : register( s0 ); + +struct PS_INPUT +{ + float2 uv : TEXCOORD0; +}; + +float2 g_vPsTapOffsets[2] : register( c0 ); + +float4 main( PS_INPUT i ) : COLOR +{ + float4 cOut; + + cOut = 0.25 * tex2D( g_texSampler, i.uv + g_vPsTapOffsets[0] ); + cOut += 0.25 * tex2D( g_texSampler, i.uv - g_vPsTapOffsets[0] ); + cOut += 0.25 * tex2D( g_texSampler, i.uv + g_vPsTapOffsets[1] ); + cOut += 0.25 * tex2D( g_texSampler, i.uv - g_vPsTapOffsets[1] ); + + return cOut; +} diff --git a/materialsystem/stdshaders/bufferclearobeystencil_ps2x.fxc b/materialsystem/stdshaders/bufferclearobeystencil_ps2x.fxc new file mode 100644 index 00000000..a549abc8 --- /dev/null +++ b/materialsystem/stdshaders/bufferclearobeystencil_ps2x.fxc @@ -0,0 +1,13 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#include "common_ps_fxc.h" + +struct PS_INPUT +{ + float4 vColor : COLOR0; +}; + +HALF4 main( PS_INPUT i ) : COLOR +{ + return i.vColor; +} diff --git a/materialsystem/stdshaders/bufferclearobeystencil_vs20.fxc b/materialsystem/stdshaders/bufferclearobeystencil_vs20.fxc new file mode 100644 index 00000000..802b9e68 --- /dev/null +++ b/materialsystem/stdshaders/bufferclearobeystencil_vs20.fxc @@ -0,0 +1,35 @@ +#include "common_vs_fxc.h" +// STATIC: "USESCOLOR" "0..1" + +struct VS_INPUT +{ + float4 vPos : POSITION; +# if (USESCOLOR == 1) + float4 vColor : COLOR0; +# endif +}; + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; +# if (USESCOLOR == 1) + float4 vColor : COLOR0; +# endif +}; + + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + o.vProjPos.xyz = v.vPos.xyz; + o.vProjPos.w = 1.0f; + +# if (USESCOLOR == 1) + { + o.vColor = v.vColor; + } +# endif + + return o; +} \ No newline at end of file diff --git a/materialsystem/stdshaders/buildsdkshaders.bat b/materialsystem/stdshaders/buildsdkshaders.bat new file mode 100644 index 00000000..da76fd8c --- /dev/null +++ b/materialsystem/stdshaders/buildsdkshaders.bat @@ -0,0 +1,66 @@ +@echo off +setlocal + +rem Use dynamic shaders to build .inc files only +rem set dynamic_shaders=1 +rem == Setup path to nmake.exe, from vc 2005 common tools directory == +call "%VS80COMNTOOLS%vsvars32.bat" + +rem ================================ +rem ==== MOD PATH CONFIGURATIONS === + +rem == Set the absolute path to your mod's game directory here == +rem == Note that this path needs does not support long file/directory names == +rem == So instead of a path such as "C:\Program Files\Steam\steamapps\mymod" == +rem == you need to find the 8.3 abbreviation for the directory name using 'dir /x' == +rem == and set the directory to something like C:\PROGRA~2\Steam\steamapps\sourcemods\mymod == +set GAMEDIR= + +rem == Set the relative path to steamapps\common\Alien Swarm\bin == +rem == As above, this path does not support long directory names or spaces == +rem == e.g. ..\..\..\..\..\PROGRA~2\Steam\steamapps\common\ALIENS~1\bin == +set SDKBINDIR=..\..\..\..\STEAME~1\steamapps\common\ALIENS~1\bin + +rem == Set the Path to your mods root source code == +rem this should already be correct, accepts relative paths only! +set SOURCEDIR=..\.. + +rem ==== MOD PATH CONFIGURATIONS END === +rem ==================================== + + + + + +set TTEXE=..\..\devtools\bin\timeprecise.exe +if not exist %TTEXE% goto no_ttexe +goto no_ttexe_end + +:no_ttexe +set TTEXE=time /t +:no_ttexe_end + + +rem echo. +rem echo ~~~~~~ buildsdkshaders %* ~~~~~~ +%TTEXE% -cur-Q +set tt_all_start=%ERRORLEVEL% +set tt_all_chkpt=%tt_start% + +set BUILD_SHADER=call buildshaders.bat +set ARG_EXTRA= + +%BUILD_SHADER% stdshader_dx9_20b -game %GAMEDIR% -source %SOURCEDIR% +%BUILD_SHADER% stdshader_dx9_20b_new -game %GAMEDIR% -source %SOURCEDIR% -dx9_30 +%BUILD_SHADER% stdshader_dx9_30 -game %GAMEDIR% -source %SOURCEDIR% -dx9_30 -force30 + + +rem echo. +if not "%dynamic_shaders%" == "1" ( + rem echo Finished full buildallshaders %* +) else ( + rem echo Finished dynamic buildallshaders %* +) + +rem %TTEXE% -diff %tt_all_start% -cur +rem echo. diff --git a/materialsystem/stdshaders/buildshaders.bat b/materialsystem/stdshaders/buildshaders.bat new file mode 100644 index 00000000..41994083 --- /dev/null +++ b/materialsystem/stdshaders/buildshaders.bat @@ -0,0 +1,208 @@ +@echo off + +set TTEXE=..\..\devtools\bin\timeprecise.exe +if not exist %TTEXE% goto no_ttexe +goto no_ttexe_end + +:no_ttexe +set TTEXE=time /t +:no_ttexe_end + +echo. +rem echo ==================== buildshaders %* ================== +%TTEXE% -cur-Q +set tt_start=%ERRORLEVEL% +set tt_chkpt=%tt_start% + + +REM **************** +REM usage: buildshaders +REM **************** + +setlocal +set arg_filename=%1 +set shadercompilecommand=shadercompile.exe +set targetdir=shaders +set SrcDirBase=..\.. +set shaderDir=shaders +set SDKArgs= +set SHADERINCPATH=vshtmp9/... fxctmp9/... + + +if "%1" == "" goto usage +set inputbase=%1 + +set DIRECTX_SDK_VER=pc09.00 +set DIRECTX_SDK_BIN_DIR=dx9sdk\utilities + +if /i "%6" == "-dx9_30" goto dx_sdk_dx9_30 +goto dx_sdk_end +:dx_sdk_dx9_30 + set DIRECTX_SDK_VER=pc09.30 + set DIRECTX_SDK_BIN_DIR=dx10sdk\utilities\dx9_30 + goto dx_sdk_end +:dx_sdk_end + +if /i "%7" == "-force30" goto set_force30_arg +goto set_force_end +:set_force30_arg + set DIRECTX_FORCE_MODEL=30 + goto set_force_end +:set_force_end + +if /i "%2" == "-game" goto set_mod_args +goto build_shaders + +REM **************** +REM USAGE +REM **************** +:usage +echo. +echo "usage: buildshaders [-game] [gameDir if -game was specified] [-source sourceDir]" +echo " gameDir is where gameinfo.txt is (where it will store the compiled shaders)." +echo " sourceDir is where the source code is (where it will find scripts and compilers)." +echo "ex : buildshaders myshaders" +echo "ex : buildshaders myshaders -game c:\steam\steamapps\sourcemods\mymod -source c:\mymod\src" +goto :end + +REM **************** +REM MOD ARGS - look for -game or the vproject environment variable +REM **************** +:set_mod_args + +if not exist %SDKBINDIR%\shadercompile.exe goto NoShaderCompile +set ChangeToDir=%SDKBINDIR% + +if /i "%4" NEQ "-source" goto NoSourceDirSpecified +set SrcDirBase=%~5 + +REM ** use the -game parameter to tell us where to put the files +set targetdir=%~3\shaders +set SDKArgs=-nompi -nop4 -game "%~3" + +if not exist "%~3\gameinfo.txt" goto InvalidGameDirectory +goto build_shaders + +REM **************** +REM ERRORS +REM **************** +:InvalidGameDirectory +echo - +echo Error: "%~3" is not a valid game directory. +echo (The -game directory must have a gameinfo.txt file) +echo - +goto end + +:NoSourceDirSpecified +echo ERROR: If you specify -game on the command line, you must specify -source. +goto usage +goto end + +:NoShaderCompile +echo - +echo - ERROR: shadercompile.exe doesn't exist in %SDKBINDIR% +echo - +goto end + +REM **************** +REM BUILD SHADERS +REM **************** +:build_shaders + +rem echo -------------------------------- +rem echo %inputbase% +rem echo -------------------------------- +REM make sure that target dirs exist +REM files will be built in these targets and copied to their final destination +if not exist %shaderDir% mkdir %shaderDir% +if not exist %shaderDir%\fxc mkdir %shaderDir%\fxc +if not exist %shaderDir%\vsh mkdir %shaderDir%\vsh +if not exist %shaderDir%\psh mkdir %shaderDir%\psh +REM Nuke some files that we will add to later. +if exist filelist.txt del /f /q filelist.txt +if exist filestocopy.txt del /f /q filestocopy.txt +if exist filelistgen.txt del /f /q filelistgen.txt +if exist inclist.txt del /f /q inclist.txt +if exist vcslist.txt del /f /q vcslist.txt + +REM **************** +REM Generate a makefile for the shader project +REM **************** +perl "%SrcDirBase%\devtools\bin\updateshaders.pl" -source "%SrcDirBase%" %inputbase% + + +REM **************** +REM Run the makefile, generating minimal work/build list for fxc files, go ahead and compile vsh and psh files. +REM **************** +rem nmake /S /C -f makefile.%inputbase% clean > clean.txt 2>&1 +echo Building inc files, asm vcs files, and VMPI worklist for %inputbase%... +nmake /S /C -f makefile.%inputbase% + +REM **************** +REM Copy the inc files to their target +REM **************** +if exist "inclist.txt" ( + echo Publishing shader inc files to target... + perl %SrcDirBase%\devtools\bin\copyshaderincfiles.pl inclist.txt +) + +REM **************** +REM Add the executables to the worklist. +REM **************** +if /i "%DIRECTX_SDK_VER%" == "pc09.00" ( + rem echo "Copy extra files for dx 9 std +) +if /i "%DIRECTX_SDK_VER%" == "pc09.30" ( + echo %SrcDirBase%\devtools\bin\d3dx9_33.dll >> filestocopy.txt +) + +echo %SrcDirBase%\%DIRECTX_SDK_BIN_DIR%\dx_proxy.dll >> filestocopy.txt + +echo %SDKBINDIR%\shadercompile.exe >> filestocopy.txt +echo %SDKBINDIR%\shadercompile_dll.dll >> filestocopy.txt +echo %SDKBINDIR%\vstdlib.dll >> filestocopy.txt +echo %SDKBINDIR%\tier0.dll >> filestocopy.txt + +REM **************** +REM Cull duplicate entries in work/build list +REM **************** +if exist filestocopy.txt type filestocopy.txt | perl "%SrcDirBase%\devtools\bin\uniqifylist.pl" > uniquefilestocopy.txt +if exist filelistgen.txt if not "%dynamic_shaders%" == "1" ( + echo Generating action list... + copy filelistgen.txt filelist.txt >nul +) + +REM **************** +REM Execute distributed process on work/build list +REM **************** + +set shader_path_cd=%cd% +if exist "filelist.txt" if exist "uniquefilestocopy.txt" if not "%dynamic_shaders%" == "1" ( + echo Running distributed shader compilation... + + cd /D %ChangeToDir% + %shadercompilecommand% %SDKArgs% -shaderpath "%shader_path_cd:/=\%" -allowdebug + cd /D %shader_path_cd% +) + +REM **************** +REM PC Shader copy +REM Publish the generated files to the output dir using XCOPY +REM This batch file may have been invoked standalone or slaved (master does final smart mirror copy) +REM **************** +:DoXCopy +if not "%dynamic_shaders%" == "1" ( +if not exist "%targetdir%" md "%targetdir%" +if not "%targetdir%"=="%shaderDir%" xcopy %shaderDir%\*.* "%targetdir%" /e /y +) +goto end + +REM **************** +REM END +REM **************** +:end + + +%TTEXE% -diff %tt_start% +echo. + diff --git a/materialsystem/stdshaders/cable_dx9.cpp b/materialsystem/stdshaders/cable_dx9.cpp new file mode 100644 index 00000000..dae932c4 --- /dev/null +++ b/materialsystem/stdshaders/cable_dx9.cpp @@ -0,0 +1,133 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: A wet version of base * lightmap +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" + +#include "cable_vs20.inc" +#include "cable_ps20.inc" +#include "cable_ps20b.inc" +#include "cpp_shader_constant_register_map.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +extern ConVar mat_fullbright; + +DEFINE_FALLBACK_SHADER( Cable, Cable_DX9 ) + +BEGIN_VS_SHADER( Cable_DX9, + "Help for Cable shader" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "cable/cablenormalmap", "bumpmap texture" ) + SHADER_PARAM( MINLIGHT, SHADER_PARAM_TYPE_FLOAT, "0.1", "Minimum amount of light (0-1 value)" ) + SHADER_PARAM( MAXLIGHT, SHADER_PARAM_TYPE_FLOAT, "0.3", "Maximum amount of light" ) + END_SHADER_PARAMS + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + LoadBumpMap( BUMPMAP ); + LoadTexture( BASETEXTURE ); + } + + SHADER_DRAW + { + BlendType_t nBlendType = EvaluateBlendRequirements( BASETEXTURE, true ); + bool bFullyOpaque = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !IS_FLAG_SET(MATERIAL_VAR_ALPHATEST); //dest alpha is free for special use + + SHADOW_STATE + { + // Enable blending? + if ( IS_FLAG_SET( MATERIAL_VAR_TRANSLUCENT ) ) + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + + pShaderShadow->EnableAlphaTest( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + if ( g_pHardwareConfig->GetDXSupportLevel() >= 90) + { + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); + } + + int tCoordDimensions[] = {2,2}; + pShaderShadow->VertexShaderVertexFormat( + VERTEX_POSITION | VERTEX_COLOR | VERTEX_TANGENT_S | VERTEX_TANGENT_T, + 2, tCoordDimensions, 0 ); + + DECLARE_STATIC_VERTEX_SHADER( cable_vs20 ); + SET_STATIC_VERTEX_SHADER( cable_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( cable_ps20b ); + SET_STATIC_PIXEL_SHADER( cable_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( cable_ps20 ); + SET_STATIC_PIXEL_SHADER( cable_ps20 ); + } + + // we are writing linear values from this shader. + // This is kinda wrong. We are writing linear or gamma depending on "IsHDREnabled" below. + // The COLOR really decides if we are gamma or linear. + pShaderShadow->EnableSRGBWrite( true ); + + FogToFogColor(); + + pShaderShadow->EnableAlphaWrites( bFullyOpaque ); + } + DYNAMIC_STATE + { + bool bLightingOnly = mat_fullbright.GetInt() == 2 && !IS_FLAG_SET( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + + BindTexture( SHADER_SAMPLER0, BUMPMAP ); + if ( bLightingOnly ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_GREY ); + + } + else + { + BindTexture( SHADER_SAMPLER1, BASETEXTURE ); + } + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + float vEyePos_SpecExponent[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + vEyePos_SpecExponent[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( cable_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( cable_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( cable_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bFullyOpaque && pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( cable_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( cable_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( cable_ps20 ); + } + } + Draw(); + } +END_SHADER diff --git a/materialsystem/stdshaders/cable_ps2x.fxc b/materialsystem/stdshaders/cable_ps2x.fxc new file mode 100644 index 00000000..5c27c619 --- /dev/null +++ b/materialsystem/stdshaders/cable_ps2x.fxc @@ -0,0 +1,52 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#include "common_fog_ps_fxc.h" +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] + +#if defined( SHADER_MODEL_PS_2_0 ) +# define WRITE_DEPTH_TO_DESTALPHA 0 +#endif + +#include "common_ps_fxc.h" +#include "shader_constant_register_map.h" + +sampler NormalSampler : register( s0 ); +sampler BaseTextureSampler : register( s1 ); + +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT ); + +struct PS_INPUT +{ + float2 vTexCoord0 : TEXCOORD0; + float2 vTexCoord1 : TEXCOORD1; + + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog + + float4 directionalLightColor : COLOR0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float3 vNormalMapDir = tex2D( NormalSampler, i.vTexCoord0 ); // Get the 3-vector from the normal map + float4 textureColor = tex2D( BaseTextureSampler, i.vTexCoord1 ); // Interpret tcoord t1 as color data. + + //Expand compacted vectors + //TODO: find if there's a better way to expand a color normal to a full vector ( _bx2 was used in the assembly code ) + vNormalMapDir = (vNormalMapDir - 0.5) * 2.0; + float3 vLightDir = float3( 0.0f, 0.0f, 1.0f ); + + float lightDirDotNormalMap = dot( vNormalMapDir, vLightDir ); //normalMap dot dirLightDir + + // do half-lambert on the dot + lightDirDotNormalMap = lightDirDotNormalMap * 0.5 + 0.5; + lightDirDotNormalMap = lightDirDotNormalMap * lightDirDotNormalMap; + + float4 resultColor; + resultColor.xyz = lightDirDotNormalMap * ( textureColor.rgb * i.directionalLightColor.rgb ); + resultColor.a = textureColor.a * i.directionalLightColor.a; + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos_SpecExponent.xyz, i.worldPos_projPosZ.xyz, i.worldPos_projPosZ.w ); + return FinalOutput( resultColor, fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, (WRITE_DEPTH_TO_DESTALPHA != 0), i.worldPos_projPosZ.w ); +} diff --git a/materialsystem/stdshaders/cable_vs20.fxc b/materialsystem/stdshaders/cable_vs20.fxc new file mode 100644 index 00000000..25bdfe23 --- /dev/null +++ b/materialsystem/stdshaders/cable_vs20.fxc @@ -0,0 +1,74 @@ +#include "common_fog_vs_fxc.h" + +#include "common_vs_fxc.h" + +static const int g_FogType = DOWATERFOG; + +struct VS_INPUT +{ + float4 vPos : POSITION; + float2 vTexCoord0 : TEXCOORD0; + float2 vTexCoord1 : TEXCOORD1; + + float4 directionalLightColor : COLOR0; + + float3 vTangentS : TANGENT; + float3 vTangentT : BINORMAL; +}; + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; + float2 vTexCoord0 : TEXCOORD0; + float2 vTexCoord1 : TEXCOORD1; + + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog + + float4 directionalLightColor : COLOR0; + +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + float fog : FOG; +#endif +}; + + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 worldPos; + worldPos = mul( v.vPos, cModel[0] ); + o.vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + o.worldPos_projPosZ = float4( worldPos.xyz, o.vProjPos.z ); + +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + o.fog = CalcFixedFunctionFog( worldPos, g_FogType ); +#endif + + //------------------------------------------------------------------------------ + // Setup the tangent space + //------------------------------------------------------------------------------ + + // Get S crossed with T (call it R) + float3 r = cross( v.vTangentS, v.vTangentT ); + + // Normalize S (into s) + float3 s = normalize( v.vTangentS ); + + // Normalize R (into r) + r = normalize( r ); + + // Regenerate T (into t) + float3 t = cross( r, v.vTangentS ); + + //------------------------------------------------------------------------------ + // Copy texcoords for the normal map and base texture + //------------------------------------------------------------------------------ + o.vTexCoord0 = v.vTexCoord0; + o.vTexCoord1 = v.vTexCoord1; + + // Pass the dirlight color through + o.directionalLightColor = v.directionalLightColor; + + return o; +} \ No newline at end of file diff --git a/materialsystem/stdshaders/clean.bat b/materialsystem/stdshaders/clean.bat new file mode 100644 index 00000000..46088064 --- /dev/null +++ b/materialsystem/stdshaders/clean.bat @@ -0,0 +1,43 @@ +@echo off +setlocal + +if /i "%1" == "-game" goto CleanGameDir + +rem Clean out platform +if exist ..\..\..\game\platform\shaders rd /s /q ..\..\..\game\platform\shaders +goto CleanOtherStuff + +:CleanGameDir +set __GameDir=%~2 +if not exist "%__GameDir%\gameinfo.txt" goto MissingGameInfo +if exist "%__GameDir%\shaders" rd /s /q "%2\shaders" +goto CleanOtherStuff + +:CleanOtherStuff +if exist debug_dx9 rd /s /q debug_dx9 + +if exist fxctmp9 rd /s /q fxctmp9 +if exist vshtmp9 rd /s /q vshtmp9 +if exist pshtmp9 rd /s /q pshtmp9 + +if exist fxctmp9_360 rd /s /q fxctmp9_360 +if exist vshtmp9_360 rd /s /q vshtmp9_360 +if exist pshtmp9_360 rd /s /q pshtmp9_360 + +if exist fxctmp9_tmp rd /s /q fxctmp9_tmp +if exist vshtmp9_tmp rd /s /q vshtmp9_tmp +if exist pshtmp9_tmp rd /s /q pshtmp9_tmp + +if exist fxctmp9_360_tmp rd /s /q fxctmp9_360_tmp +if exist vshtmp9_360_tmp rd /s /q vshtmp9_360_tmp +if exist pshtmp9_360_tmp rd /s /q pshtmp9_360_tmp + +if exist shaders rd /s /q shaders +goto end + +:MissingGameInfo +echo Invalid -game parameter specified (no "%__GameDir%\gameinfo.txt" exists). +goto end + + +:end \ No newline at end of file diff --git a/materialsystem/stdshaders/cleantemps.bat b/materialsystem/stdshaders/cleantemps.bat new file mode 100644 index 00000000..51478ee4 --- /dev/null +++ b/materialsystem/stdshaders/cleantemps.bat @@ -0,0 +1,12 @@ +@echo off +setlocal + +if exist fxctmp9_tmp rd /s /q fxctmp9_tmp +if exist vshtmp9_tmp rd /s /q vshtmp9_tmp +if exist pshtmp9_tmp rd /s /q pshtmp9_tmp + +if exist fxctmp9_360_tmp rd /s /q fxctmp9_360_tmp +if exist vshtmp9_360_tmp rd /s /q vshtmp9_360_tmp +if exist pshtmp9_360_tmp rd /s /q pshtmp9_360_tmp + +if exist shaders rd /s /q shaders diff --git a/materialsystem/stdshaders/clearalpha_ps2x.fxc b/materialsystem/stdshaders/clearalpha_ps2x.fxc new file mode 100644 index 00000000..a6735f96 --- /dev/null +++ b/materialsystem/stdshaders/clearalpha_ps2x.fxc @@ -0,0 +1,8 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +const float4 g_vClearVal : register( c0 ); + +float4 main() : COLOR +{ + return g_vClearVal; +} diff --git a/materialsystem/stdshaders/cloak.cpp b/materialsystem/stdshaders/cloak.cpp new file mode 100644 index 00000000..47b8daab --- /dev/null +++ b/materialsystem/stdshaders/cloak.cpp @@ -0,0 +1,123 @@ +//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============// +// +// Purpose: Cloaking shader for Spy in TF2 (and probably many other things to come) +// +// $NoKeywords: $ +//=====================================================================================// + +#include "BaseVSShader.h" +#include "convar.h" +#include "cloak_dx9_helper.h" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +DEFINE_FALLBACK_SHADER( Cloak, Cloak_DX90 ) + +BEGIN_VS_SHADER( Cloak_DX90, "Help for Cloak" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM_OVERRIDE( COLOR, SHADER_PARAM_TYPE_COLOR, "{255 255 255}", "unused", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM_OVERRIDE( ALPHA, SHADER_PARAM_TYPE_FLOAT, "1.0", "unused", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM( REFRACTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "2", "" ) + SHADER_PARAM( REFRACTTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "refraction tint" ) + SHADER_PARAM( NORMALMAP, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "normal map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( TIME, SHADER_PARAM_TYPE_FLOAT, "0.0f", "" ) + SHADER_PARAM( REFRACTTINTTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shield", "" ) + SHADER_PARAM( REFRACTTINTTEXTUREFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( FRESNELREFLECTION, SHADER_PARAM_TYPE_FLOAT, "1.0", "1.0 == mirror, 0.0 == water" ) + SHADER_PARAM( NOWRITEZ, SHADER_PARAM_TYPE_INTEGER, "0", "0 == write z, 1 = no write z" ) + SHADER_PARAM( MASKED, SHADER_PARAM_TYPE_BOOL, "0", "mask using dest alpha" ) + SHADER_PARAM( CLOAKFACTOR, SHADER_PARAM_TYPE_FLOAT, "0", "How cloaked? Zero is not cloaked, 1 is fully cloaked." ) + SHADER_PARAM( LIGHTWARPTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "1D ramp texture for tinting scalar diffuse term" ) + SHADER_PARAM( PHONGEXPONENT, SHADER_PARAM_TYPE_FLOAT, "5.0", "Phong exponent for local specular lights" ) + SHADER_PARAM( PHONGTINT, SHADER_PARAM_TYPE_VEC3, "5.0", "Phong tint for local specular lights" ) + SHADER_PARAM( PHONGALBEDOTINT, SHADER_PARAM_TYPE_BOOL, "1.0", "Apply tint by albedo (controlled by spec exponent texture" ) + SHADER_PARAM( PHONGFRESNELRANGES, SHADER_PARAM_TYPE_VEC3, "[0 0.5 1]", "Parameters for remapping fresnel output" ) + SHADER_PARAM( PHONGBOOST, SHADER_PARAM_TYPE_FLOAT, "1.0", "Phong overbrightening factor (specular mask channel should be authored to account for this)" ) + SHADER_PARAM( PHONGEXPONENTTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "Phong Exponent map" ) + + // Rim lighting terms + SHADER_PARAM( RIMLIGHT, SHADER_PARAM_TYPE_BOOL, "0", "enables rim lighting" ) + SHADER_PARAM( RIMLIGHTEXPONENT, SHADER_PARAM_TYPE_FLOAT, "4.0", "Exponent for rim lights" ) + SHADER_PARAM( RIMLIGHTBOOST, SHADER_PARAM_TYPE_FLOAT, "1.0", "Boost for rim lights" ) + SHADER_PARAM( RIMMASK, SHADER_PARAM_TYPE_BOOL, "0", "Indicates whether or not to use alpha channel of exponent texture to mask the rim term" ) + END_SHADER_PARAMS +// FIXME: doesn't support Fresnel! + + void SetupVars( Cloak_DX9_Vars_t& info ) + { + info.m_nBaseTexture = BASETEXTURE; + info.m_nRefractAmount = REFRACTAMOUNT; + info.m_nRefractTint = REFRACTTINT; + info.m_nNormalMap = NORMALMAP; + info.m_nBumpFrame = BUMPFRAME; + info.m_nBumpTransform = BUMPTRANSFORM; + info.m_nRefractTintTexture = REFRACTTINTTEXTURE; + info.m_nRefractTintTextureFrame = REFRACTTINTTEXTUREFRAME; + info.m_nFresnelReflection = FRESNELREFLECTION; + info.m_nMasked = MASKED; + info.m_nCloakFactor = CLOAKFACTOR; + info.m_nDiffuseWarpTexture = LIGHTWARPTEXTURE; + info.m_nPhongExponent = PHONGEXPONENT; + info.m_nPhongTint = PHONGTINT; + info.m_nPhongAlbedoTint = PHONGALBEDOTINT; + info.m_nPhongExponentTexture = PHONGEXPONENTTEXTURE; + info.m_nPhongBoost = PHONGBOOST; + info.m_nPhongFresnelRanges = PHONGFRESNELRANGES; + + // Rim lighting parameters + info.m_nRimLight = RIMLIGHT; + info.m_nRimLightPower = RIMLIGHTEXPONENT; + info.m_nRimLightBoost = RIMLIGHTBOOST; + info.m_nRimMask = RIMMASK; + } + + bool NeedsPowerOfTwoFrameBufferTexture( IMaterialVar **params, bool bCheckSpecificToThisFrame ) const + { + if ( bCheckSpecificToThisFrame == false ) // For setting model flag at load time + return true; + else if ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) // Per-frame check + return true; + else + return false; + } + + bool IsTranslucent( IMaterialVar **params ) const + { + if ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) // Per-frame check + return true; + else + return false; + } + + SHADER_INIT_PARAMS() + { + Cloak_DX9_Vars_t info; + SetupVars( info ); + InitParamsCloak_DX9( this, params, pMaterialName, info ); + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + Cloak_DX9_Vars_t info; + SetupVars( info ); + InitCloak_DX9( this, params, info ); + } + + SHADER_DRAW + { + Cloak_DX9_Vars_t info; + SetupVars( info ); + DrawCloak_DX9( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } +END_SHADER + diff --git a/materialsystem/stdshaders/cloak_blended_pass_helper.cpp b/materialsystem/stdshaders/cloak_blended_pass_helper.cpp new file mode 100644 index 00000000..80450756 --- /dev/null +++ b/materialsystem/stdshaders/cloak_blended_pass_helper.cpp @@ -0,0 +1,361 @@ +//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============// + +/* Example how to plug this into an existing shader: + + In the VMT: + // Cloak Pass + "$cloakPassEnabled" "1" + + #include "cloak_blended_pass_helper.h" + + In BEGIN_SHADER_PARAMS: + // Cloak Pass + SHADER_PARAM( CLOAKPASSENABLED, SHADER_PARAM_TYPE_BOOL, "0", "Enables cloak render in a second pass" ) + SHADER_PARAM( CLOAKFACTOR, SHADER_PARAM_TYPE_FLOAT, "0.0", "" ) + SHADER_PARAM( CLOAKCOLORTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Cloak color tint" ) + SHADER_PARAM( REFRACTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "2", "" ) + + // This should already exist + //SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "bump map" ) + //SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + //SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + + Add this above SHADER_INIT_PARAMS() + // Cloak Pass + void SetupVarsCloakBlendedPass( CloakBlendedPassVars_t &info ) + { + info.m_nCloakFactor = CLOAKFACTOR; + info.m_nCloakColorTint = CLOAKCOLORTINT; + info.m_nRefractAmount = REFRACTAMOUNT; + + // Delete these lines if not bump mapping! + info.m_nBumpmap = BUMPMAP; + info.m_nBumpFrame = BUMPFRAME; + info.m_nBumpTransform = BUMPTRANSFORM; + } + + bool NeedsPowerOfTwoFrameBufferTexture( IMaterialVar **params, bool bCheckSpecificToThisFrame ) const + { + if ( params[CLOAKPASSENABLED]->GetIntValue() ) // If material supports cloaking + { + if ( bCheckSpecificToThisFrame == false ) // For setting model flag at load time + return true; + else if ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) // Per-frame check + return true; + // else, not cloaking this frame, so check flag2 in case the base material still needs it + } + + // Check flag2 if not drawing cloak pass + return IS_FLAG2_SET( MATERIAL_VAR2_NEEDS_POWER_OF_TWO_FRAME_BUFFER_TEXTURE ); + } + + bool IsTranslucent( IMaterialVar **params ) const + { + if ( params[CLOAKPASSENABLED]->GetIntValue() ) // If material supports cloaking + { + if ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) // Per-frame check + return true; + // else, not cloaking this frame, so check flag in case the base material still needs it + } + + // Check flag if not drawing cloak pass + return IS_FLAG_SET( MATERIAL_VAR_TRANSLUCENT ); + } + + In SHADER_INIT_PARAMS() + // Cloak Pass + if ( !params[CLOAKPASSENABLED]->IsDefined() ) + { + params[CLOAKPASSENABLED]->SetIntValue( 0 ); + } + else if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + InitParamsCloakBlendedPass( this, params, pMaterialName, info ); + } + + In SHADER_INIT + // Cloak Pass + if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + InitCloakBlendedPass( this, params, info ); + } + + Modify SHADER_DRAW to look something like this: + // Skip the standard rendering if cloak pass is fully opaque + bool bDrawStandardPass = true; + if ( params[CLOAKPASSENABLED]->GetIntValue() && ( pShaderShadow == NULL ) ) // && not snapshotting + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + if ( CloakBlendedPassIsFullyOpaque( params, info ) ) + { + bDrawStandardPass = false; + } + } + + // Standard rendering pass + if ( bDrawStandardPass ) + { + Eye_Refract_Vars_t info; + SetupVarsEyeRefract( info ); + Draw_Eyes_Refract( this, params, pShaderAPI, pShaderShadow, info ); + } + else + { + // Skip this pass! + Draw( false ); + } + + // Cloak Pass + if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + // If ( snapshotting ) or ( we need to draw this frame ) + if ( ( pShaderShadow != NULL ) || ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + DrawCloakBlendedPass( this, params, pShaderAPI, pShaderShadow, info ); + } + else // We're not snapshotting and we don't need to draw this frame + { + // Skip this pass! + Draw( false ); + } + } + +==================================================================================================== */ + +#include "BaseVSShader.h" +#include "mathlib/VMatrix.h" +#include "cloak_blended_pass_helper.h" +#include "convar.h" + +// Auto generated inc files +#include "cloak_blended_pass_vs20.inc" +#include "cloak_blended_pass_ps20.inc" +#include "cloak_blended_pass_ps20b.inc" + +#ifndef _X360 +#include "cloak_blended_pass_vs30.inc" +#include "cloak_blended_pass_ps30.inc" +#endif + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +void InitParamsCloakBlendedPass( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, CloakBlendedPassVars_t &info ) +{ + // Set material flags + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + SET_FLAGS( MATERIAL_VAR_MODEL ); + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + + // Set material parameter default values + if ( ( info.m_nCloakFactor != -1 ) && ( !params[info.m_nCloakFactor]->IsDefined() ) ) + { + params[info.m_nCloakFactor]->SetFloatValue( kDefaultCloakFactor ); + } + + if ( ( info.m_nRefractAmount != -1 ) && ( !params[info.m_nRefractAmount]->IsDefined() ) ) + { + params[info.m_nRefractAmount]->SetFloatValue( kDefaultRefractAmount ); + } + + if ( ( info.m_nCloakColorTint != -1 ) && ( !params[info.m_nCloakColorTint]->IsDefined() ) ) + { + params[info.m_nCloakColorTint]->SetVecValue( kDefaultCloakColorTint[0], kDefaultCloakColorTint[1], kDefaultCloakColorTint[2], kDefaultCloakColorTint[3] ); + } + + if( (info.m_nBumpFrame != -1 ) && !params[info.m_nBumpFrame]->IsDefined() ) + { + params[info.m_nBumpFrame]->SetIntValue( 0 ); + } +} + +void InitCloakBlendedPass( CBaseVSShader *pShader, IMaterialVar** params, CloakBlendedPassVars_t &info ) +{ + // Load textures + if ( g_pConfig->UseBumpmapping() ) + { + if ( (info.m_nBumpmap != -1) && params[info.m_nBumpmap]->IsDefined() ) + { + pShader->LoadTexture( info.m_nBumpmap ); + } + } +} + +void DrawCloakBlendedPass( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, CloakBlendedPassVars_t &info, VertexCompressionType_t vertexCompression ) +{ + bool bBumpMapping = ( !g_pConfig->UseBumpmapping() ) || ( info.m_nBumpmap == -1 ) || !params[info.m_nBumpmap]->IsTexture() ? 0 : 1; + + SHADOW_STATE + { + // Reset shadow state manually since we're drawing from two materials + pShader->SetInitialShadowState( ); + + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + // Vertex Shader + DECLARE_STATIC_VERTEX_SHADER( cloak_blended_pass_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( BUMPMAP, bBumpMapping ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER( cloak_blended_pass_vs20 ); + + // Pixel Shader + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( cloak_blended_pass_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP, bBumpMapping ? 1 : 0 ); + SET_STATIC_PIXEL_SHADER( cloak_blended_pass_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( cloak_blended_pass_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP, bBumpMapping ? 1 : 0 ); + SET_STATIC_PIXEL_SHADER( cloak_blended_pass_ps20 ); + } + } +#ifndef _X360 + else + { + // The vertex shader uses the vertex id stream + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + + // Vertex Shader + DECLARE_STATIC_VERTEX_SHADER( cloak_blended_pass_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( BUMPMAP, bBumpMapping ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER( cloak_blended_pass_vs30 ); + + // Pixel Shader + DECLARE_STATIC_PIXEL_SHADER( cloak_blended_pass_ps30 ); + SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP, bBumpMapping ? 1 : 0 ); + SET_STATIC_PIXEL_SHADER( cloak_blended_pass_ps30 ); + } +#endif + + // Textures + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); // Refraction texture + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + if ( bBumpMapping ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); // Bump + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, false ); // Not sRGB + } + pShaderShadow->EnableSRGBWrite( true ); + + // Blending + pShader->EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + pShaderShadow->EnableAlphaWrites( false ); + + // !!! We need to turn this back on because EnableAlphaBlending() above disables it! + pShaderShadow->EnableDepthWrites( true ); + } + DYNAMIC_STATE + { + // Reset render state manually since we're drawing from two materials + pShaderAPI->SetDefaultState(); + + // Set Vertex Shader Constants + if ( ( bBumpMapping ) && ( info.m_nBumpTransform != -1 ) ) + { + pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, info.m_nBumpTransform ); + } + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + // Set Vertex Shader Combos + DECLARE_DYNAMIC_VERTEX_SHADER( cloak_blended_pass_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( cloak_blended_pass_vs20 ); + + // Set Pixel Shader Combos + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( cloak_blended_pass_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( cloak_blended_pass_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( cloak_blended_pass_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( cloak_blended_pass_ps20 ); + } + } +#ifndef _X360 + else + { + pShader->SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, SHADER_VERTEXTEXTURE_SAMPLER0 ); + + // Set Vertex Shader Combos + DECLARE_DYNAMIC_VERTEX_SHADER( cloak_blended_pass_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( cloak_blended_pass_vs30 ); + + // Set Pixel Shader Combos + DECLARE_DYNAMIC_PIXEL_SHADER( cloak_blended_pass_ps30 ); + SET_DYNAMIC_PIXEL_SHADER( cloak_blended_pass_ps30 ); + } +#endif + + // Bind textures + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_FRAME_BUFFER_FULL_TEXTURE_0 ); // Refraction Map + if ( bBumpMapping ) + { + pShader->BindTexture( SHADER_SAMPLER1, info.m_nBumpmap, info.m_nBumpFrame ); + } + + // Set Pixel Shader Constants + float vEyePos[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos ); + pShaderAPI->SetPixelShaderConstant( 5, vEyePos, 1 ); + + float vPackedConst1[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vPackedConst1[0] = IS_PARAM_DEFINED( info.m_nCloakFactor ) ? params[info.m_nCloakFactor]->GetFloatValue() : kDefaultCloakFactor; + vPackedConst1[1] = IS_PARAM_DEFINED( info.m_nRefractAmount ) ? params[info.m_nRefractAmount]->GetFloatValue() : kDefaultRefractAmount; + pShaderAPI->SetPixelShaderConstant( 6, vPackedConst1, 1 ); + + // Refract color tint + pShaderAPI->SetPixelShaderConstant( 7, IS_PARAM_DEFINED( info.m_nCloakColorTint ) ? params[info.m_nCloakColorTint]->GetVecValue() : kDefaultCloakColorTint, 1 ); + + // Set c0 and c1 to contain first two rows of ViewProj matrix + VMatrix mView, mProj; + pShaderAPI->GetMatrix( MATERIAL_VIEW, mView.m[0] ); + pShaderAPI->GetMatrix( MATERIAL_PROJECTION, mProj.m[0] ); + VMatrix mViewProj = mView * mProj; + mViewProj = mViewProj.Transpose3x3(); + pShaderAPI->SetPixelShaderConstant( 0, mViewProj.m[0], 2 ); + } + pShader->Draw(); +} + +bool CloakBlendedPassIsFullyOpaque ( IMaterialVar** params, CloakBlendedPassVars_t &info ) +{ + float flCloakFactor = IS_PARAM_DEFINED( info.m_nCloakFactor ) ? params[info.m_nCloakFactor]->GetFloatValue() : kDefaultCloakFactor; + //float flRefractAmount = IS_PARAM_DEFINED( info.m_nRefractAmount ) ? params[info.m_nRefractAmount]->GetFloatValue() : kDefaultRefractAmount; + + // NOTE: If this math changes, you need to update the pixel shader code! + float flFresnel = 1.0f - ( 0.0f ); // Assume V.N = 0.0f; + float flCloakLerpFactor = clamp( Lerp( clamp( flCloakFactor, 0.0f, 1.0f ), 1.0f, flFresnel - 1.35f ), 0.0f, 1.0f ); + //flCloakLerpFactor = 1.0f - smoothstep( 0.4f, 0.425f, flCloakLerpFactor ); + + if ( flCloakLerpFactor <= 0.4f ) + return true; + + return false; +} diff --git a/materialsystem/stdshaders/cloak_blended_pass_helper.h b/materialsystem/stdshaders/cloak_blended_pass_helper.h new file mode 100644 index 00000000..de59c9b1 --- /dev/null +++ b/materialsystem/stdshaders/cloak_blended_pass_helper.h @@ -0,0 +1,46 @@ +//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============// + +#ifndef CLOAK_BLENDED_PASS_HELPER_H +#define CLOAK_BLENDED_PASS_HELPER_H +#ifdef _WIN32 +#pragma once +#endif + +#include + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct CloakBlendedPassVars_t +{ + CloakBlendedPassVars_t() { memset( this, 0xFF, sizeof(CloakBlendedPassVars_t) ); } + + int m_nCloakFactor; + int m_nCloakColorTint; + int m_nRefractAmount; + + int m_nBumpmap; + int m_nBumpFrame; + int m_nBumpTransform; +}; + +// Default values (Arrays should only be vec[4]) +static const float kDefaultCloakFactor = 0.0f; +static const float kDefaultCloakColorTint[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; +static const float kDefaultRefractAmount = 0.1f; + +void InitParamsCloakBlendedPass( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, CloakBlendedPassVars_t &info ); +void InitCloakBlendedPass( CBaseVSShader *pShader, IMaterialVar** params, CloakBlendedPassVars_t &info ); +void DrawCloakBlendedPass( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, CloakBlendedPassVars_t &info, VertexCompressionType_t vertexCompression ); +bool CloakBlendedPassIsFullyOpaque ( IMaterialVar** params, CloakBlendedPassVars_t &info ); + +#endif // CLOAK_BLENDED_PASS_HELPER_H diff --git a/materialsystem/stdshaders/cloak_blended_pass_ps2x.fxc b/materialsystem/stdshaders/cloak_blended_pass_ps2x.fxc new file mode 100644 index 00000000..32371a27 --- /dev/null +++ b/materialsystem/stdshaders/cloak_blended_pass_ps2x.fxc @@ -0,0 +1,103 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "BUMPMAP" "0..1" + +// Includes ======================================================================================= +#include "common_vertexlitgeneric_dx9.h" + +// Texture Samplers =============================================================================== +sampler g_tRefractionSampler : register( s0 ); +#if BUMPMAP + sampler g_tBumpSampler : register( s1 ); +#endif + +// Shaders Constants and Globals ================================================================== +const float4 g_mViewProj0 : register( c0 ); // 1st row of matrix +const float4 g_mViewProj1 : register( c1 ); // 2nd row of matrix + +const float4 g_vCameraPosition : register( c5 ); +const float4 g_vPackedConst6 : register( c6 ); +#define g_flCloakFactor g_vPackedConst6.x // Default = 1.0f +#define g_flRefractAmount g_vPackedConst6.y // Default = 1.0f + +const float4 g_cCloakColorTint : register( c7 ); + +// 8 2D Poisson offsets (designed to use .xy and .wz swizzles (not .zw) +static const float4 g_vPoissonOffset[4] = { float4 (-0.0876f, 0.9703f, 0.5651f, 0.4802f ), + float4 ( 0.1851f, 0.1580f, -0.0617f, -0.2616f ), + float4 (-0.5477f, -0.6603f, 0.0711f, -0.5325f ), + float4 (-0.0751f, -0.8954f, 0.4054f, 0.6384f ) }; + +// Interpolated values ============================================================================ +struct PS_INPUT +{ + float3 vWorldNormal : TEXCOORD0; // World-space normal + float3 vProjPosForRefract : TEXCOORD1; + float3 vWorldViewVector : TEXCOORD2; + #if BUMPMAP + float3x3 mTangentSpaceTranspose : TEXCOORD3; + // second row : TEXCOORD4; + // third row : TEXCOORD5; + float2 vTexCoord0 : TEXCOORD6; + #endif +}; + +// Main =========================================================================================== +float4 main( PS_INPUT i ) : COLOR +{ + float3 vWorldNormal = normalize( i.vWorldNormal.xyz ); + + #if BUMPMAP + float4 vBumpTexel = tex2D( g_tBumpSampler, i.vTexCoord0.xy ); + float3 vTangentNormal = ( 2.0f * vBumpTexel ) - 1.0f; + vWorldNormal.xyz = mul( i.mTangentSpaceTranspose, vTangentNormal.xyz ); + #endif + + // Transform world space normal into clip space and project + float3 vProjNormal; + vProjNormal.x = dot( vWorldNormal.xyz, g_mViewProj0.xyz ); // 1st row + vProjNormal.y = dot( vWorldNormal.xyz, g_mViewProj1.xyz ); // 2nd row + + // Compute coordinates for sampling refraction + float2 vRefractTexCoordNoWarp = i.vProjPosForRefract.xy / i.vProjPosForRefract.z; + float2 vRefractTexCoord = vProjNormal.xy; + float scale = lerp( g_flRefractAmount, 0.0f, saturate( g_flCloakFactor ) ); + vRefractTexCoord.xy *= scale; + vRefractTexCoord.xy += vRefractTexCoordNoWarp.xy; + + // Blur by scalable Poisson filter + float flBlurAmount = lerp( 0.05f, 0.0f, saturate( g_flCloakFactor ) ); + float3 cRefract = tex2D( g_tRefractionSampler, vRefractTexCoord.xy ); + cRefract += tex2D( g_tRefractionSampler, vRefractTexCoord.xy + ( g_vPoissonOffset[0].xy * flBlurAmount ) ); + cRefract += tex2D( g_tRefractionSampler, vRefractTexCoord.xy + ( g_vPoissonOffset[0].wz * flBlurAmount ) ); + cRefract += tex2D( g_tRefractionSampler, vRefractTexCoord.xy + ( g_vPoissonOffset[1].xy * flBlurAmount ) ); + cRefract += tex2D( g_tRefractionSampler, vRefractTexCoord.xy + ( g_vPoissonOffset[1].wz * flBlurAmount ) ); + cRefract += tex2D( g_tRefractionSampler, vRefractTexCoord.xy + ( g_vPoissonOffset[2].xy * flBlurAmount ) ); + cRefract += tex2D( g_tRefractionSampler, vRefractTexCoord.xy + ( g_vPoissonOffset[2].wz * flBlurAmount ) ); + cRefract += tex2D( g_tRefractionSampler, vRefractTexCoord.xy + ( g_vPoissonOffset[3].xy * flBlurAmount ) ); + cRefract += tex2D( g_tRefractionSampler, vRefractTexCoord.xy + ( g_vPoissonOffset[3].wz * flBlurAmount ) ); + cRefract /= 9.0f; + + // 1-(N.V) for Fresnel term (NOTE: If this math changes, you need to update the C code that mimics this on the CPU) + float flFresnel = 1.0f - saturate( dot( i.vWorldNormal.xyz, normalize( -i.vWorldViewVector.xyz ) ) ); + float flCloakLerpFactor = saturate( lerp( 1.0f, flFresnel - 1.35f, saturate( g_flCloakFactor ) ) ); + flCloakLerpFactor = 1.0f - smoothstep( 0.4f, 0.425f, flCloakLerpFactor ); + + // Slightly dim the facing pixels and brighten the silhouette pixels + cRefract.rgb *= lerp( flFresnel * 0.4 + 0.8, 1.0f, saturate( g_flCloakFactor ) * saturate( g_flCloakFactor ) ); // This gives a scalar in the range [0.8 1.2] + + // Refract color tint + float fColorTintStrength = saturate( ( saturate( g_flCloakFactor ) - 0.75f ) * 4.0f ); + cRefract.rgb *= lerp( g_cCloakColorTint, 1.0f, fColorTintStrength ); + + //===============// + // Combine terms // + //===============// + float4 result; + result.rgb = cRefract.rgb; + + // Set alpha to cloak mask + result.a = flCloakLerpFactor; + + return FinalOutput( result, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} diff --git a/materialsystem/stdshaders/cloak_blended_pass_vs20.fxc b/materialsystem/stdshaders/cloak_blended_pass_vs20.fxc new file mode 100644 index 00000000..8fb175db --- /dev/null +++ b/materialsystem/stdshaders/cloak_blended_pass_vs20.fxc @@ -0,0 +1,133 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "BUMPMAP" "0..1" + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "SKINNING" "0..1" + +// DYNAMIC: "MORPHING" "0..1" [vs30] [ = pShaderAPI->IsHWMorphingEnabled() ] + +// Includes +#include "common_vs_fxc.h" + +// Globals +static const bool g_bSkinning = SKINNING ? true : false; +const float4 cBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_0 ); + +#ifdef SHADER_MODEL_VS_3_0 +// NOTE: cMorphTargetTextureDim.xy = target dimensions, +// cMorphTargetTextureDim.z = 4tuples/morph +const float3 cMorphTargetTextureDim : register( SHADER_SPECIFIC_CONST_6 ); +const float4 cMorphSubrect : register( SHADER_SPECIFIC_CONST_7 ); + +sampler2D morphSampler : register( D3DVERTEXTEXTURESAMPLER0, s0 ); +#endif + +// Structs +struct VS_INPUT +{ + float4 vPos : POSITION; // Position + float4 vNormal : NORMAL; // Normal + float4 vBoneWeights : BLENDWEIGHT; // Skin weights + float4 vBoneIndices : BLENDINDICES; // Skin indices + float4 vTexCoord0 : TEXCOORD0; // Base texture coordinates + + #if BUMPMAP + float4 vTangent : TANGENT; + #endif + + // Position and normal/tangent deltas + float3 vPosFlex : POSITION1; + float3 vNormalFlex : NORMAL1; + + #ifdef SHADER_MODEL_VS_3_0 + float vVertexID : POSITION2; + #endif +}; + +struct VS_OUTPUT +{ + float4 vProjPosition : POSITION; // Projection-space position + float3 vWorldNormal : TEXCOORD0; // World-space normal + float3 vProjPosForRefract : TEXCOORD1; + float3 vWorldViewVector : TEXCOORD2; + + #if BUMPMAP + float3x3 mTangentSpaceTranspose : TEXCOORD3; + // second row : TEXCOORD4; + // third row : TEXCOORD5; + float2 vTexCoord0 : TEXCOORD6; + #endif +}; + +// Main +VS_OUTPUT main( const VS_INPUT i ) +{ + VS_OUTPUT o; + + // Flexes coming in from a separate stream (contribution masked by cFlexScale.x) + float4 vObjPosition = i.vPos; + float3 vObjNormal; + + #if BUMPMAP + float4 vObjTangent; + DecompressVertex_NormalTangent( i.vNormal, i.vTangent, vObjNormal, vObjTangent ); + + #if !defined( SHADER_MODEL_VS_3_0 ) || !MORPHING + ApplyMorph( i.vPosFlex, i.vNormalFlex, vObjPosition.xyz, vObjNormal, vObjTangent.xyz ); + #else + ApplyMorph( morphSampler, cMorphTargetTextureDim, cMorphSubrect, i.vVertexID, float3( 0, 0, 0 ), vObjPosition.xyz, vObjNormal, vObjTangent.xyz ); + #endif + #else // !BUMPMAP + DecompressVertex_Normal( i.vNormal, vObjNormal ); + + #if !defined( SHADER_MODEL_VS_3_0 ) || !MORPHING + ApplyMorph( i.vPosFlex, i.vNormalFlex, vObjPosition.xyz, vObjNormal ); + #else + ApplyMorph( morphSampler, cMorphTargetTextureDim, cMorphSubrect, i.vVertexID, float3( 0, 0, 0 ), + vObjPosition.xyz, vObjNormal ); + #endif + #endif + + // Transform the position + float3 vWorldPosition = { 0.0f, 0.0f, 0.0f }; + float3 vWorldNormal = { 0.0f, 0.0f, 0.0f }; + #if BUMPMAP + float3 vWorldTangent = { 0.0f, 0.0f, 0.0f }; + float3 vWorldBinormal = { 0.0f, 0.0f, 0.0f }; + SkinPositionNormalAndTangentSpace( g_bSkinning, vObjPosition, vObjNormal.xyz, vObjTangent.xyzw, i.vBoneWeights, i.vBoneIndices, vWorldPosition, vWorldNormal, vWorldTangent, vWorldBinormal ); + #else + SkinPositionAndNormal( g_bSkinning, vObjPosition, vObjNormal.xyz, i.vBoneWeights, i.vBoneIndices, vWorldPosition, vWorldNormal ); + #endif + o.vWorldNormal.xyz = normalize( vWorldNormal.xyz ); + + // Transform into projection space + float4 vProjPosition = mul( float4( vWorldPosition, 1.0f ), cViewProj ); + o.vProjPosition = vProjPosition; + + // Map projected position to the refraction texture + float2 vRefractPos; + vRefractPos.x = vProjPosition.x; + vRefractPos.y = -vProjPosition.y; // Invert Y + vRefractPos = (vRefractPos + vProjPosition.w) * 0.5f; + o.vProjPosForRefract.xyz = float3(vRefractPos.x, vRefractPos.y, vProjPosition.w); + + // View vector + float3 vWorldViewVector = normalize (vWorldPosition.xyz - cEyePos.xyz); + o.vWorldViewVector.xyz = vWorldViewVector.xyz; + + // Tangent space transform + #if BUMPMAP + o.mTangentSpaceTranspose[0] = float3( vWorldTangent.x, vWorldBinormal.x, vWorldNormal.x ); + o.mTangentSpaceTranspose[1] = float3( vWorldTangent.y, vWorldBinormal.y, vWorldNormal.y ); + o.mTangentSpaceTranspose[2] = float3( vWorldTangent.z, vWorldBinormal.z, vWorldNormal.z ); + #endif + + // Texture coordinates + #if BUMPMAP + o.vTexCoord0.x = dot( i.vTexCoord0.xy, cBaseTexCoordTransform[0] ); + o.vTexCoord0.y = dot( i.vTexCoord0.xy, cBaseTexCoordTransform[1] ); + #endif + + return o; +} diff --git a/materialsystem/stdshaders/cloak_dx9_helper.cpp b/materialsystem/stdshaders/cloak_dx9_helper.cpp new file mode 100644 index 00000000..5af7d0b7 --- /dev/null +++ b/materialsystem/stdshaders/cloak_dx9_helper.cpp @@ -0,0 +1,328 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" +#include "cloak_dx9_helper.h" +#include "..\shaderapidx9\locald3dtypes.h" +#include "convar.h" +#include "cpp_shader_constant_register_map.h" +#include "cloak_vs20.inc" +#include "cloak_ps20.inc" +#include "cloak_ps20b.inc" + +#ifndef _X360 +#include "cloak_vs30.inc" +#include "cloak_ps30.inc" +#endif + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +static ConVar r_lightwarpidentity( "r_lightwarpidentity", "0", FCVAR_CHEAT ); + +// FIXME: doesn't support fresnel! +void InitParamsCloak_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, Cloak_DX9_Vars_t &info ) +{ + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + SET_FLAGS( MATERIAL_VAR_TRANSLUCENT ); + + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + + if( !params[info.m_nFresnelReflection]->IsDefined() ) + { + params[info.m_nFresnelReflection]->SetFloatValue( 1.0f ); + } + if( !params[info.m_nMasked]->IsDefined() ) + { + params[info.m_nMasked]->SetIntValue( 0 ); + } + SET_FLAGS2( MATERIAL_VAR2_NEEDS_POWER_OF_TWO_FRAME_BUFFER_TEXTURE ); +} + +void InitCloak_DX9( CBaseVSShader *pShader, IMaterialVar** params, Cloak_DX9_Vars_t &info ) +{ + if (params[info.m_nBaseTexture]->IsDefined() ) + { + pShader->LoadTexture( info.m_nBaseTexture ); + } + + if (params[info.m_nNormalMap]->IsDefined() ) + { + pShader->LoadBumpMap( info.m_nNormalMap ); + } + + if ( (info.m_nDiffuseWarpTexture != -1) && params[info.m_nDiffuseWarpTexture]->IsDefined() ) + { + pShader->LoadTexture( info.m_nDiffuseWarpTexture ); + } + + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); +} + +void DrawCloak_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, Cloak_DX9_Vars_t &info, VertexCompressionType_t vertexCompression ) +{ + bool bIsModel = IS_FLAG_SET( MATERIAL_VAR_MODEL ); + bool bMasked = (params[info.m_nMasked]->GetIntValue() != 0); + bool hasDiffuseWarp = (info.m_nDiffuseWarpTexture != -1) && params[info.m_nDiffuseWarpTexture]->IsTexture(); + bool hasPhongExponentTexture = (info.m_nPhongExponentTexture != -1) && params[info.m_nPhongExponentTexture]->IsTexture(); + bool hasPhongTintMap = hasPhongExponentTexture && (info.m_nPhongAlbedoTint != -1) && ( params[info.m_nPhongAlbedoTint]->GetIntValue() != 0 ); + bool bHasRimLight = (info.m_nRimLight != -1) && ( params[info.m_nRimLight]->GetIntValue() != 0 ); + bool bHasRimMaskMap = hasPhongExponentTexture && bHasRimLight && (info.m_nRimMask != -1) && ( params[info.m_nRimMask]->GetIntValue() != 0 ); + + SHADOW_STATE + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + + pShader->SetInitialShadowState( ); + + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); // Always SRGB read on base map + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, true ); // Refraction map sampler... + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); + + pShaderShadow->EnableSRGBWrite( true ); + + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL; + int nTexCoordCount = 1; + int userDataSize = 0; + if( bIsModel ) + { + userDataSize = 4; + } + else + { + flags |= VERTEX_TANGENT_S | VERTEX_TANGENT_T; + } + + // This shader supports compressed vertices, so OR in that flag: + flags |= VERTEX_FORMAT_COMPRESSED; + + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_STATIC_VERTEX_SHADER( cloak_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( MODEL, bIsModel ); + SET_STATIC_VERTEX_SHADER( cloak_vs20 ); + + // Bind ps_2_b shader so we can get Phong terms + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( cloak_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, hasDiffuseWarp ); + SET_STATIC_PIXEL_SHADER( cloak_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( cloak_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, hasDiffuseWarp ); + SET_STATIC_PIXEL_SHADER( cloak_ps20 ); + } + } +#ifndef _X360 + else + { + // The vertex shader uses the vertex id stream + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + + DECLARE_STATIC_VERTEX_SHADER( cloak_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( MODEL, bIsModel ); + SET_STATIC_VERTEX_SHADER( cloak_vs30 ); + + // Bind ps_2_b shader so we can get Phong terms + DECLARE_STATIC_PIXEL_SHADER( cloak_ps30 ); + SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, hasDiffuseWarp ); + SET_STATIC_PIXEL_SHADER( cloak_ps30 ); + } +#endif + + pShader->DefaultFog(); + + if( bMasked ) + { + pShader->EnableAlphaBlending( SHADER_BLEND_ONE_MINUS_SRC_ALPHA, SHADER_BLEND_SRC_ALPHA ); + } + + // Lighting constants + pShader->PI_BeginCommandBuffer(); + pShader->PI_SetPixelShaderAmbientLightCube( PSREG_AMBIENT_CUBE ); + pShader->PI_SetPixelShaderLocalLighting( PSREG_LIGHT_INFO_ARRAY ); + pShader->PI_EndCommandBuffer(); + } + DYNAMIC_STATE + { + pShaderAPI->SetDefaultState(); + + // Bind textures + pShader->BindTexture( SHADER_SAMPLER0, info.m_nBaseTexture, 0 ); // Base Map + pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_FRAME_BUFFER_FULL_TEXTURE_0 ); // Refraction Map + pShader->BindTexture( SHADER_SAMPLER3, info.m_nNormalMap, info.m_nBumpFrame ); // Normal Map + pShaderAPI->BindStandardTexture( SHADER_SAMPLER5, TEXTURE_NORMALIZATION_CUBEMAP_SIGNED ); // Normalization cube map + + if ( hasDiffuseWarp ) + { + if ( r_lightwarpidentity.GetBool() ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_IDENTITY_LIGHTWARP ); + } + else + { + pShader->BindTexture( SHADER_SAMPLER1, info.m_nDiffuseWarpTexture ); // Light warp texture + } + } + + MaterialFogMode_t fogType = pShaderAPI->GetSceneFogMode(); + + LightState_t lightState; + pShaderAPI->GetDX9LightState( &lightState ); + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_DYNAMIC_VERTEX_SHADER( cloak_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( cloak_vs20 ); + + // Bind ps_2_b shader so we can get Phong, rim and a cloudier refraction + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( cloak_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_PIXEL_SHADER( cloak_ps20b ); + } + else + { + // JasonM Hack + // + // In general, cloaking on ps_2_0 needs re-working for multipass...yuck... + // + int nPS20NumLights = MAX( lightState.m_nNumLights, 1 ); + DECLARE_DYNAMIC_PIXEL_SHADER( cloak_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, nPS20NumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_PIXEL_SHADER( cloak_ps20 ); + } + } +#ifndef _X360 + else + { + pShader->SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, SHADER_VERTEXTEXTURE_SAMPLER0 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( cloak_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( cloak_vs30 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( cloak_ps30 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_PIXEL_SHADER( cloak_ps30 ); + } +#endif + + pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, info.m_nBumpTransform ); + + if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ) + { + pShader->SetPixelShaderConstant( 27, info.m_nRefractTint ); + } + else + { + pShader->SetPixelShaderConstantGammaToLinear( 27, info.m_nRefractTint ); + } + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + // Pack phong exponent in with the eye position + float vEyePos_SpecExponent[4], vFresnelRanges_SpecBoost[4] = {0, 0.5, 1, 1}; + float vSpecularTint[4] = {1, 1, 1, 1}, vRimBoost[4] = {1, 1, 1, 1}; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + + if ( (info.m_nPhongExponent != -1) && params[info.m_nPhongExponent]->IsDefined() ) + vEyePos_SpecExponent[3] = params[info.m_nPhongExponent]->GetFloatValue(); // This overrides the channel in the map + else + vEyePos_SpecExponent[3] = 0; // Use the alpha channel of the normal map for the exponent + + if ( (info.m_nPhongTint != -1 ) && params[info.m_nPhongTint]->IsDefined() ) // Get the tint parameter + params[info.m_nPhongTint]->GetVecValue(vSpecularTint, 4); + + // Get the rim light power (goes in w of Phong tint) + if ( bHasRimLight && (info.m_nRimLightPower != -1) && params[info.m_nRimLightPower]->IsDefined() ) + { + vSpecularTint[3] = params[info.m_nRimLightPower]->GetFloatValue(); + vSpecularTint[3] = MAX(vSpecularTint[3], 1.0f); // Make sure this is at least 1 + } + + // Get the rim boost power (goes in w of flashlight position) + if ( bHasRimLight && (info.m_nRimLightBoost != -1) && params[info.m_nRimLightBoost]->IsDefined() ) + { + vRimBoost[3] = params[info.m_nRimLightBoost]->GetFloatValue(); + } + + // Rim mask...if this is true, use alpha channel of spec exponent texture to mask the rim term + if ( bHasRimMaskMap ) + { + float vRimMaskControl[4] = {0, 0, 0, 0}; // Only x is relevant in shader code + vRimMaskControl[0] = params[info.m_nRimMask]->GetFloatValue(); + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_ATTENUATION, vRimMaskControl, 1 ); + } + + // If it's all zeros, there was no constant tint in the vmt + if ( (vSpecularTint[0] == 0.0f) && (vSpecularTint[1] == 0.0f) && (vSpecularTint[2] == 0.0f) ) + { + if ( hasPhongTintMap ) // If we have a map to use, tell the shader + { + vSpecularTint[0] = -1; + } + else // Otherwise, just tint with white + { + vSpecularTint[0] = 1.0f; + vSpecularTint[1] = 1.0f; + vSpecularTint[2] = 1.0f; + } + } + + if ( (info.m_nPhongFresnelRanges != -1 ) && params[info.m_nPhongFresnelRanges]->IsDefined() ) + params[info.m_nPhongFresnelRanges]->GetVecValue( vFresnelRanges_SpecBoost, 3 ); // Grab optional fresnel range parameters + + if ( ( info.m_nPhongBoost != -1 ) &¶ms[info.m_nPhongBoost]->IsDefined() ) // Grab optional phong boost param + vFresnelRanges_SpecBoost[3] = params[info.m_nPhongBoost]->GetFloatValue(); + else + vFresnelRanges_SpecBoost[3] = 1.0f; + + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + pShaderAPI->SetPixelShaderConstant( PSREG_FRESNEL_SPEC_PARAMS, vFresnelRanges_SpecBoost, 1 ); + + pShaderAPI->SetPixelShaderConstant( PSREG_SPEC_RIM_PARAMS, vSpecularTint, 1 ); + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_POSITION_RIM_BOOST, vRimBoost, 1 ); // Rim boost in w on non-flashlight pass + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + // Set c0 and c1 to contain first two rows of ViewProj matrix + VMatrix matView, matProj, matViewProj; + pShaderAPI->GetMatrix( MATERIAL_VIEW, matView.m[0] ); + pShaderAPI->GetMatrix( MATERIAL_PROJECTION, matProj.m[0] ); + matViewProj = matView * matProj; + pShaderAPI->SetPixelShaderConstant( 0, matViewProj.m[0], 2 ); + + // Cloaking control constants + float vCloakControls[4] = { params[info.m_nRefractAmount]->GetFloatValue(), params[info.m_nCloakFactor]->GetFloatValue(), 0.0f, 0.0f }; + pShaderAPI->SetPixelShaderConstant( 3, vCloakControls, 1 ); + } + pShader->Draw(); +} diff --git a/materialsystem/stdshaders/cloak_dx9_helper.h b/materialsystem/stdshaders/cloak_dx9_helper.h new file mode 100644 index 00000000..c2e358f4 --- /dev/null +++ b/materialsystem/stdshaders/cloak_dx9_helper.h @@ -0,0 +1,63 @@ +//====== Copyright © 1996-2006, Valve Corporation, All rights reserved. ======= +// +// Purpose: +// +//============================================================================= + +#ifndef CLOAK_DX9_HELPER_H +#define CLOAK_DX9_HELPER_H +#ifdef _WIN32 +#pragma once +#endif + +#include + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct Cloak_DX9_Vars_t +{ + Cloak_DX9_Vars_t() { memset( this, 0xFF, sizeof( *this ) ); } + + int m_nBaseTexture; + int m_nRefractAmount; + int m_nRefractTint; + int m_nNormalMap; + int m_nBumpFrame; + int m_nBumpTransform; + int m_nRefractTintTexture; + int m_nRefractTintTextureFrame; + int m_nFresnelReflection; + int m_nMasked; + int m_nCloakFactor; + int m_nDiffuseWarpTexture; + + int m_nPhongExponent; + int m_nPhongTint; + int m_nPhongAlbedoTint; + int m_nPhongExponentTexture; + int m_nPhongBoost; + int m_nPhongFresnelRanges; + + // Rim lighting parameters + int m_nRimLight; + int m_nRimLightPower; + int m_nRimLightBoost; + int m_nRimMask; +}; + +void InitParamsCloak_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, + Cloak_DX9_Vars_t &info ); +void InitCloak_DX9( CBaseVSShader *pShader, IMaterialVar** params, Cloak_DX9_Vars_t &info ); +void DrawCloak_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, Cloak_DX9_Vars_t &info, VertexCompressionType_t vertexCompression ); + +#endif // CLOAK_DX9_HELPER_H diff --git a/materialsystem/stdshaders/cloak_ps2x.fxc b/materialsystem/stdshaders/cloak_ps2x.fxc new file mode 100644 index 00000000..500773f1 --- /dev/null +++ b/materialsystem/stdshaders/cloak_ps2x.fxc @@ -0,0 +1,194 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "LIGHTWARPTEXTURE" "0..1" +#include "common_fog_ps_fxc.h" +// DYNAMIC: "WRITEWATERFOGTODESTALPHA" "0..1" +// DYNAMIC: "NUM_LIGHTS" "0..2" [ps20] +// DYNAMIC: "NUM_LIGHTS" "0..4" [ps20b] +// DYNAMIC: "NUM_LIGHTS" "0..4" [ps30] + + +#include "shader_constant_register_map.h" + +sampler BaseSampler : register( s0 ); // Base map +sampler DiffuseWarpSampler : register( s1 ); // 1D texture for diffuse lighting modification +sampler RefractSampler : register( s2 ); // Refraction map copied from back buffer +sampler NormalSampler : register( s3 ); // Normal map +sampler SpecExponentSampler : register( s4 ); // Flashlight cookie +sampler NormalizeSampler : register( s5 ); // Normalization cube map + +const float3x3 g_ViewProj : register( c0 ); // 1st row of Projection matrix +// c1 // 2nd row +// c2 // 4th row +const float2 g_CloakControl : register( c3 ); // { refract amount, cloak, ?, ? } +const float3 cAmbientCube[6] : register( PSREG_AMBIENT_CUBE ); +const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT ); +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float4 g_FlashlightAttenuationFactors_RimMask : register( PSREG_FLASHLIGHT_ATTENUATION ); // On non-flashlight pass, x has rim mask control +const float4 g_RimBoost : register( PSREG_FLASHLIGHT_POSITION_RIM_BOOST ); +const float4 g_FresnelSpecParams : register( PSREG_FRESNEL_SPEC_PARAMS ); // xyz are fresnel, w is specular boost +const float4 g_SpecularRimParams : register( PSREG_SPEC_RIM_PARAMS ); // xyz are specular tint color, w is rim power +PixelShaderLightInfo cLightInfo[3] : register( PSREG_LIGHT_INFO_ARRAY ); // 2 registers each - 6 registers total + +#define g_fRimBoost g_RimBoost.w +#define g_FresnelRanges g_FresnelSpecParams.xyz +#define g_SpecularBoost g_FresnelSpecParams.w +#define g_SpecularTint g_SpecularRimParams.xyz +#define g_RimExponent g_SpecularRimParams.w +#define g_FlashlightAttenuationFactors g_FlashlightAttenuationFactors_RimMask +#define g_RimMaskControl g_FlashlightAttenuationFactors_RimMask.x + +// 8 2D Poisson offsets (designed to use .xy and .wz swizzles (not .zw) +static const float4 gPoissonOffset[4] = { float4 (-0.0876f, 0.9703f, 0.5651f, 0.4802f ), + float4 ( 0.1851f, 0.1580f, -0.0617f, -0.2616f ), + float4 (-0.5477f, -0.6603f, 0.0711f, -0.5325f ), + float4 (-0.0751f, -0.8954f, 0.4054f, 0.6384f ) }; + +struct PS_INPUT +{ + float2 vBaseTexCoord : TEXCOORD0; + float3x3 tangentSpaceTranspose : TEXCOORD1; + // second row : TEXCOORD2; + // third row : TEXCOORD3; + float3 worldPos : TEXCOORD4; + float3 projPos : TEXCOORD5; + float4 lightAtten : TEXCOORD6; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float3 vSpecular = float3( 0.0f, 0.0f, 0.0f ); + bool bDoDiffuseWarp = LIGHTWARPTEXTURE ? true : false; + int nNumLights = NUM_LIGHTS; + + // Base color + float4 albedo = tex2D( BaseSampler, i.vBaseTexCoord ); + + // Load normal and expand range + float4 vNormalSample = tex2D( NormalSampler, i.vBaseTexCoord ); + float3 tangentSpaceNormal = 2.0f * vNormalSample.xyz - 1.0f; + + // We need a world space normal if we're doing any lighting + float3 vWorldNormal = normalize( mul( i.tangentSpaceTranspose, tangentSpaceNormal ) ); + float3 vWorldEyeDir = normalize( g_EyePos_SpecExponent.xyz - i.worldPos ); + + // Vanilla 1-(N.V) fresnel term used later in transition lerp + float fresnel = 1-saturate( dot( vWorldNormal, vWorldEyeDir ) ); + + // Summation of diffuse illumination from all local lights + float3 diffuseLighting = PixelShaderDoLighting( i.worldPos, vWorldNormal, + float3( 0.0f, 0.0f, 0.0f ), false, + true, i.lightAtten, cAmbientCube, NormalizeSampler, + nNumLights, cLightInfo, true, + bDoDiffuseWarp, DiffuseWarpSampler ); + + + + + + // Transform world space normal into clip space and project + float2 vProjNormal; + vProjNormal.x = dot( vWorldNormal, g_ViewProj[0] ); // 1st row + vProjNormal.y = dot( vWorldNormal, g_ViewProj[1] ); // 2nd row + + // Compute coordinates for sampling refraction + float2 vRefractTexCoordNoWarp = i.projPos.xy / i.projPos.z; + float2 vRefractTexCoord = vProjNormal.xy; + float scale = lerp( g_CloakControl.x, 0.0f, g_CloakControl.y ); + vRefractTexCoord *= scale; + vRefractTexCoord += vRefractTexCoordNoWarp; + +#ifdef SHADER_MODEL_PS_2_0 + float3 vRefract = tex2D( RefractSampler, vRefractTexCoordNoWarp ); +#endif + + // Extra refraction rays, specular, rim etc are only done on ps_2_b +#if defined( SHADER_MODEL_PS_2_B ) || defined( SHADER_MODEL_PS_3_0 ) + // Blur by scalable Poisson filter + float fBlurAmount = lerp( 0.05f, 0.0f, g_CloakControl.y ); + float3 vRefract = tex2D( RefractSampler, vRefractTexCoord ); + vRefract += tex2D( RefractSampler, vRefractTexCoord + gPoissonOffset[0].xy * fBlurAmount ); + vRefract += tex2D( RefractSampler, vRefractTexCoord + gPoissonOffset[0].wz * fBlurAmount ); + vRefract += tex2D( RefractSampler, vRefractTexCoord + gPoissonOffset[1].xy * fBlurAmount ); + vRefract += tex2D( RefractSampler, vRefractTexCoord + gPoissonOffset[1].wz * fBlurAmount ); + vRefract += tex2D( RefractSampler, vRefractTexCoord + gPoissonOffset[2].xy * fBlurAmount ); + vRefract += tex2D( RefractSampler, vRefractTexCoord + gPoissonOffset[2].wz * fBlurAmount ); + +// We're right at the hairy edge of constant register usage and hence have to drop these taps... +// vRefract += tex2D( RefractSampler, vRefractTexCoord + gPoissonOffset[3].xy * fBlurAmount ); +// vRefract += tex2D( RefractSampler, vRefractTexCoord + gPoissonOffset[3].wz * fBlurAmount ); + vRefract /= 7.0f; + + float3 rimLighting = float3( 0.0f, 0.0f, 0.0f ); + float3 specularLighting = float3( 0.0f, 0.0f, 0.0f ); + float fSpecExp = g_EyePos_SpecExponent.w; + float fSpecMask = vNormalSample.a; + + float4 vSpecExpMap = tex2D( SpecExponentSampler, i.vBaseTexCoord ); + float fSpecExpMap = vSpecExpMap.r; + float fRimMask = 1.0f;//lerp( 1.0f, vSpecExpMap.a, g_RimMaskControl ); // Select rim mask + float3 vSpecularTint; + + // If the exponent passed in as a constant is zero, use the value from the map as the exponent + if ( fSpecExp == 0 ) + fSpecExp = 1.0f - fSpecExpMap + 150.0f * fSpecExpMap; + + // If constant tint is negative, tint with albedo, based upon scalar tint map + if ( g_SpecularTint.r == -1 ) + vSpecularTint = lerp( float3(1.0f, 1.0f, 1.0f), albedo, vSpecExpMap.g ); + else + vSpecularTint = g_SpecularTint.rgb; + + // Fresnel to match regular specular lighting + float fFresnelRanges = Fresnel( vWorldNormal, vWorldEyeDir, g_FresnelRanges ); + + // Summation of specular from all local lights besides the flashlight + PixelShaderDoSpecularLighting( i.worldPos, vWorldNormal, fSpecExp, vWorldEyeDir, + i.lightAtten, nNumLights, cLightInfo, false, + NormalizeSampler, 1.0f, true, g_RimExponent, + + // Outputs + specularLighting, rimLighting ); + + // Modulate with spec mask, boost, tint and fresnel ranges + specularLighting *= fSpecMask * g_SpecularBoost * fFresnelRanges * vSpecularTint; + + float fRimFresnel = Fresnel4( vWorldNormal, vWorldEyeDir ); + + // Add in rim light modulated with tint, mask and traditional Fresnel (not using Fresnel ranges) + rimLighting *= vSpecularTint * fRimMask * fRimFresnel; + + // Fold rim lighting into specular term by using the max so that we don't really add light twice... + specularLighting = max (specularLighting, rimLighting); + + // Add in view-ray lookup from ambient cube + specularLighting += fRimFresnel * fRimMask * vSpecularTint /* g_fRimBoost */ * PixelShaderAmbientLight( vWorldEyeDir, cAmbientCube) * saturate(dot(vWorldNormal, float3(0, 0 , 1)) ); + + float tintLerpFactor = saturate(lerp( 1, fresnel-1.1, saturate(g_CloakControl.y))); + tintLerpFactor = smoothstep( 0.4f, 0.425f, tintLerpFactor ); + float3 vTintedRefract = lerp( vRefract, albedo * vRefract, 0.7f ); + vRefract = lerp( vRefract, vTintedRefract, tintLerpFactor ); + + vSpecular = specularLighting * smoothstep( 0.98, 0.8, saturate(g_CloakControl.y )); +#endif + + // Blend refraction component with diffusely lit model + float diffuseLerpFactor = saturate(lerp( 1, fresnel - 1.35, saturate(g_CloakControl.y))); + diffuseLerpFactor = smoothstep( 0.4f, 0.425f, diffuseLerpFactor ); + + float3 fDiffuse = lerp( vRefract, albedo * diffuseLighting, diffuseLerpFactor ); + float3 result = fDiffuse + vSpecular; + + float alpha = 1.0f; + + // Emulate LinearColorToHDROutput() when uncloaked + result = lerp( result.xyz * LINEAR_LIGHT_SCALE, result, saturate(g_CloakControl.y) ); + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos_SpecExponent.xyz, i.worldPos.xyz, i.projPos.z ); + +#if WRITEWATERFOGTODESTALPHA && (PIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT) + alpha = fogFactor; +#endif + + return FinalOutput( float4( result, alpha ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_NONE ); +} diff --git a/materialsystem/stdshaders/cloak_vs20.fxc b/materialsystem/stdshaders/cloak_vs20.fxc new file mode 100644 index 00000000..e617113b --- /dev/null +++ b/materialsystem/stdshaders/cloak_vs20.fxc @@ -0,0 +1,129 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// +// +// Purpose: +// +//===========================================================================// + +// STATIC: "MODEL" "0..1" + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +#include "common_fog_vs_fxc.h" +// DYNAMIC: "SKINNING" "0..1" + +// DYNAMIC: "MORPHING" "0..1" [vs30] [ = pShaderAPI->IsHWMorphingEnabled() ] + +#include "common_vs_fxc.h" + +static const bool g_bSkinning = SKINNING ? true : false; +static const int g_FogType = DOWATERFOG; + +#ifdef SHADER_MODEL_VS_3_0 +// NOTE: cMorphTargetTextureDim.xy = target dimensions, +// cMorphTargetTextureDim.z = 4tuples/morph +const float3 cMorphTargetTextureDim : register( SHADER_SPECIFIC_CONST_6 ); +const float4 cMorphSubrect : register( SHADER_SPECIFIC_CONST_7 ); + +sampler2D morphSampler : register( D3DVERTEXTEXTURESAMPLER0, s0 ); +#endif + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vNormal : NORMAL; + float4 vBaseTexCoord : TEXCOORD0; + float4 vUserData : TANGENT; + + // Position and normal/tangent deltas + float3 vPosFlex : POSITION1; + float3 vNormalFlex : NORMAL1; + +#ifdef SHADER_MODEL_VS_3_0 + float vVertexID : POSITION2; +#endif +}; + +struct VS_OUTPUT +{ + float4 vSetupProjPos : POSITION; +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + float fog : FOG; +#endif + float2 vBaseTexCoord : TEXCOORD0; + float3x3 tangentSpaceTranspose : TEXCOORD1; + // second row : TEXCOORD2; + // third row : TEXCOORD3; + float3 worldPos : TEXCOORD4; + float3 projPos : TEXCOORD5; + float4 lightAtten : TEXCOORD6; +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float4 vPosition = v.vPos; + float3 vNormal; + float4 vTangent; + + DecompressVertex_NormalTangent( v.vNormal, v.vUserData, vNormal, vTangent ); + +#if !defined( SHADER_MODEL_VS_3_0 ) || !MORPHING + ApplyMorph( v.vPosFlex, v.vNormalFlex, vPosition.xyz, vNormal, vTangent.xyz ); +#else + ApplyMorph( morphSampler, cMorphTargetTextureDim, cMorphSubrect, v.vVertexID, float3( 0, 0, 0 ), + vPosition.xyz, vNormal, vTangent.xyz ); +#endif + + // Perform skinning + float3 worldNormal, worldPos, worldTangentS, worldTangentT; + SkinPositionNormalAndTangentSpace( g_bSkinning, vPosition, vNormal, vTangent, + v.vBoneWeights, v.vBoneIndices, worldPos, + worldNormal, worldTangentS, worldTangentT ); + + // Always normalize since flex path is controlled by runtime + // constant not a shader combo and will always generate the normalization + worldNormal = normalize( worldNormal ); + worldTangentS = normalize( worldTangentS ); + worldTangentT = normalize( worldTangentT ); + + // Projected position + float4 vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + o.vSetupProjPos = vProjPos; + + // Map projected position to the refraction texture + float2 vRefractPos; + vRefractPos.x = vProjPos.x; + vRefractPos.y = -vProjPos.y; // invert Y + vRefractPos = (vRefractPos + vProjPos.w) * 0.5f; + + // Scalar light attenuation + o.lightAtten.x = GetVertexAttenForLight( worldPos, 0 ); + o.lightAtten.y = GetVertexAttenForLight( worldPos, 1 ); + o.lightAtten.z = GetVertexAttenForLight( worldPos, 2 ); + o.lightAtten.w = GetVertexAttenForLight( worldPos, 3 ); + + // Compute fog based on the position + float3 vWorldPos = mul( v.vPos, cModel[0] ); + +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + o.fog = CalcFixedFunctionFog( vWorldPos, g_FogType ); +#endif + + // World position + o.worldPos = worldPos; + + // Refract position + o.projPos = float3(vRefractPos.x, vRefractPos.y, vProjPos.w); + + // Tranform bump coordinates + o.vBaseTexCoord = v.vBaseTexCoord; + + // Tangent space transform + o.tangentSpaceTranspose[0] = float3( worldTangentS.x, worldTangentT.x, worldNormal.x ); + o.tangentSpaceTranspose[1] = float3( worldTangentS.y, worldTangentT.y, worldNormal.y ); + o.tangentSpaceTranspose[2] = float3( worldTangentS.z, worldTangentT.z, worldNormal.z ); + + return o; +} diff --git a/materialsystem/stdshaders/cloud.cpp b/materialsystem/stdshaders/cloud.cpp new file mode 100644 index 00000000..eb88afdf --- /dev/null +++ b/materialsystem/stdshaders/cloud.cpp @@ -0,0 +1,76 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "shaderlib/CShader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_SHADER( Cloud, + "Help for Cloud" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM_OVERRIDE( BASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/cloud", "cloud texture", 0 ) + SHADER_PARAM( CLOUDALPHATEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/cloudalpha", "cloud alpha texture" ) + SHADER_PARAM( CLOUDSCALE, SHADER_PARAM_TYPE_VEC2, "[1 1]", "cloudscale" ) + SHADER_PARAM( MASKSCALE, SHADER_PARAM_TYPE_VEC2, "[1 1]", "maskscale" ) + END_SHADER_PARAMS + SHADER_INIT + { + LoadTexture( BASETEXTURE ); + LoadTexture( CLOUDALPHATEXTURE ); + if( !params[CLOUDSCALE]->IsDefined() ) + { + params[CLOUDSCALE]->SetVecValue( 1.0f, 1.0f ); + } + if( !params[MASKSCALE]->IsDefined() ) + { + params[MASKSCALE]->SetVecValue( 1.0f, 1.0f ); + } + } + + SHADER_DRAW + { + if( g_pHardwareConfig->GetSamplerCount() >= 2 ) + { + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + if ( IS_FLAG_SET( MATERIAL_VAR_ADDITIVE ) ) + { + pShaderShadow->BlendFunc( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); + } + else + { + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | + SHADER_DRAW_TEXCOORD0 | SHADER_DRAW_TEXCOORD1 ); + DefaultFog(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + BindTexture( SHADER_SAMPLER1, CLOUDALPHATEXTURE ); + + // handle scrolling of base texture + SetFixedFunctionTextureScaledTransform( MATERIAL_TEXTURE0, + BASETEXTURETRANSFORM, CLOUDSCALE ); + SetFixedFunctionTextureScale( MATERIAL_TEXTURE1, MASKSCALE ); + } + Draw(); + } + else + { + ShaderWarning("Cloud not supported for single-texturing boards!\n"); + } + } +END_SHADER diff --git a/materialsystem/stdshaders/colorcorrection.cpp b/materialsystem/stdshaders/colorcorrection.cpp new file mode 100644 index 00000000..863fe1ea --- /dev/null +++ b/materialsystem/stdshaders/colorcorrection.cpp @@ -0,0 +1,140 @@ +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#include "basevsshader.h" + +#include "screenspaceeffect_vs20.inc" +#include "colorcorrection_ps20.inc" +#include "colorcorrection_ps20b.inc" + +#include "..\materialsystem_global.h" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +BEGIN_VS_SHADER_FLAGS( ColorCorrection, "Help for ColorCorrection", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( WEIGHT_DEFAULT, SHADER_PARAM_TYPE_FLOAT, "1", "Volume Texture Default Weight" ) + SHADER_PARAM( WEIGHT0, SHADER_PARAM_TYPE_FLOAT, "0", "Volume Texture Weight 0" ) + SHADER_PARAM( WEIGHT1, SHADER_PARAM_TYPE_FLOAT, "0", "Volume Texture Weight 1" ) + SHADER_PARAM( WEIGHT2, SHADER_PARAM_TYPE_FLOAT, "0", "Volume Texture Weight 2" ) + SHADER_PARAM( WEIGHT3, SHADER_PARAM_TYPE_FLOAT, "0", "Volume Texture Weight 3" ) + SHADER_PARAM( NUM_LOOKUPS, SHADER_PARAM_TYPE_INTEGER, "0", "Number of lookup maps" ) + SHADER_PARAM( USE_FB_TEXTURE, SHADER_PARAM_TYPE_BOOL, "0", "Use frame buffer texture as input" ) + SHADER_PARAM( INPUT_TEXTURE, SHADER_PARAM_TYPE_TEXTURE, "0", "Input texture" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + if( !params[ WEIGHT_DEFAULT ]->IsDefined() ) + { + params[ WEIGHT_DEFAULT ]->SetFloatValue( 1.0f) ; + } + if( !params[ WEIGHT0 ]->IsDefined() ) + { + params[ WEIGHT0 ]->SetFloatValue( 1.0f ); + } + if( !params[ WEIGHT1 ]->IsDefined() ) + { + params[ WEIGHT1 ]->SetFloatValue( 1.0f ); + } + if( !params[ WEIGHT2 ]->IsDefined() ) + { + params[ WEIGHT2 ]->SetFloatValue( 1.0f ); + } + if( !params[ WEIGHT3 ]->IsDefined() ) + { + params[ WEIGHT3 ]->SetFloatValue( 1.0f ); + } + if( !params[ NUM_LOOKUPS ]->IsDefined() ) + { + params[ NUM_LOOKUPS ]->SetIntValue( 0 ); + } + SET_FLAGS2( MATERIAL_VAR2_NEEDS_FULL_FRAME_BUFFER_TEXTURE ); + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + + int fmt = VERTEX_POSITION; + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 ); + + DECLARE_STATIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + SET_STATIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( colorcorrection_ps20b ); + SET_STATIC_PIXEL_SHADER( colorcorrection_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( colorcorrection_ps20 ); + SET_STATIC_PIXEL_SHADER( colorcorrection_ps20 ); + } + pShaderShadow->EnableSRGBWrite( false ); + } + DYNAMIC_STATE + { + if( params[ USE_FB_TEXTURE ]->GetIntValue() ) + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_FRAME_BUFFER_FULL_TEXTURE_0 ); + else + BindTexture( SHADER_SAMPLER0, INPUT_TEXTURE, -1 ); + + for( int i=0;iGetIntValue();i++ ) + { + pShaderAPI->BindStandardTexture( (Sampler_t)(SHADER_SAMPLER1+i), (StandardTextureId_t)(TEXTURE_COLOR_CORRECTION_VOLUME_0+i) ); + } + + float default_weight = params[ WEIGHT_DEFAULT ]->GetFloatValue(); + float weights[4] = { params[ WEIGHT0 ]->GetFloatValue(), + params[ WEIGHT1 ]->GetFloatValue(), + params[ WEIGHT2 ]->GetFloatValue(), + params[ WEIGHT3 ]->GetFloatValue() }; + + pShaderAPI->SetPixelShaderConstant( 0, &default_weight ); + pShaderAPI->SetPixelShaderConstant( 1, &weights[0] ); + pShaderAPI->SetPixelShaderConstant( 2, &weights[1] ); + pShaderAPI->SetPixelShaderConstant( 3, &weights[2] ); + pShaderAPI->SetPixelShaderConstant( 4, &weights[3] ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( colorcorrection_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LOOKUPS, params[ NUM_LOOKUPS ]->GetIntValue() ); + SET_DYNAMIC_PIXEL_SHADER( colorcorrection_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( colorcorrection_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LOOKUPS, params[ NUM_LOOKUPS ]->GetIntValue() ); + SET_DYNAMIC_PIXEL_SHADER( colorcorrection_ps20 ); + } + + DECLARE_DYNAMIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + } + Draw(); + } +END_SHADER diff --git a/materialsystem/stdshaders/colorcorrection_ps2x.fxc b/materialsystem/stdshaders/colorcorrection_ps2x.fxc new file mode 100644 index 00000000..ae9a19c5 --- /dev/null +++ b/materialsystem/stdshaders/colorcorrection_ps2x.fxc @@ -0,0 +1,53 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// DYNAMIC: "NUM_LOOKUPS" "0..4" + +#include "common_ps_fxc.h" + +sampler BaseTextureSampler : register( s0 ); +sampler ColorCorrectionVolumeTexture0 : register( s1 ); +sampler ColorCorrectionVolumeTexture1 : register( s2 ); +sampler ColorCorrectionVolumeTexture2 : register( s3 ); +sampler ColorCorrectionVolumeTexture3 : register( s4 ); + +float ColorCorrectionDefaultWeight : register( c0 ); +float ColorCorrectionVolumeWeight0 : register( c1 ); +float ColorCorrectionVolumeWeight1 : register( c2 ); +float ColorCorrectionVolumeWeight2 : register( c3 ); +float ColorCorrectionVolumeWeight3 : register( c4 ); + +struct PS_INPUT +{ + float2 baseTexCoord : TEXCOORD0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float4 baseColor = tex2D( BaseTextureSampler, i.baseTexCoord ); + + // NOTE: This code requires the color correction texture to be 32 units to be correct. + // This code will cause (0,0,0) to be read from 0.5f/32 + // and (1,1,1) to be read from 31.5f/32 + float4 offsetBaseColor = baseColor*( 31.0f / 32.0f ) + ( 0.5f / 32.0f ); + + float4 outColor = float4( 0.0f, 0.0f, 0.0f, baseColor.a ); + outColor.rgb = baseColor * ColorCorrectionDefaultWeight; + if (NUM_LOOKUPS > 0) + { + outColor.rgb += tex3D( ColorCorrectionVolumeTexture0, offsetBaseColor.rgb ) * ColorCorrectionVolumeWeight0; + if (NUM_LOOKUPS > 1) + { + outColor.rgb += tex3D( ColorCorrectionVolumeTexture1, offsetBaseColor.rgb ) * ColorCorrectionVolumeWeight1; + if (NUM_LOOKUPS > 2) + { + outColor.rgb += tex3D( ColorCorrectionVolumeTexture2, offsetBaseColor.rgb ) * ColorCorrectionVolumeWeight2; + if (NUM_LOOKUPS > 3) + { + outColor.rgb += tex3D( ColorCorrectionVolumeTexture3, offsetBaseColor.rgb ) * ColorCorrectionVolumeWeight3; + } + } + } + } + + return FinalOutput( outColor, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} diff --git a/materialsystem/stdshaders/common_flashlight_fxc.h b/materialsystem/stdshaders/common_flashlight_fxc.h new file mode 100644 index 00000000..4c4bd131 --- /dev/null +++ b/materialsystem/stdshaders/common_flashlight_fxc.h @@ -0,0 +1,865 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// +// +// Purpose: Common pixel shader code specific to flashlights +// +// $NoKeywords: $ +// +//=============================================================================// +#ifndef COMMON_FLASHLIGHT_FXC_H_ +#define COMMON_FLASHLIGHT_FXC_H_ + +#include "common_ps_fxc.h" + + +// Superellipse soft clipping +// +// Input: +// - Point Q on the x-y plane +// - The equations of two superellipses (with major/minor axes given by +// a,b and A,B for the inner and outer ellipses, respectively) +// - This is changed a bit from the original RenderMan code to be better vectorized +// +// Return value: +// - 0 if Q was inside the inner ellipse +// - 1 if Q was outside the outer ellipse +// - smoothly varying from 0 to 1 in between +float2 ClipSuperellipse( float2 Q, // Point on the xy plane + float4 aAbB, // Dimensions of superellipses + float2 rounds ) // Same roundness for both ellipses +{ + float2 qr, Qabs = abs(Q); // Project to +x +y quadrant + + float2 bx_Bx = Qabs.x * aAbB.zw; + float2 ay_Ay = Qabs.y * aAbB.xy; + + qr.x = pow( pow(bx_Bx.x, rounds.x) + pow(ay_Ay.x, rounds.x), rounds.y ); // rounds.x = 2 / roundness + qr.y = pow( pow(bx_Bx.y, rounds.x) + pow(ay_Ay.y, rounds.x), rounds.y ); // rounds.y = -roundness/2 + + return qr * aAbB.xy * aAbB.zw; +} + +// Volumetric light shaping +// +// Inputs: +// - the point being shaded, in the local light space +// - all information about the light shaping, including z smooth depth +// clipping, superellipse xy shaping, and distance falloff. +// Return value: +// - attenuation factor based on the falloff and shaping +float uberlight(float3 PL, // Point in light space + + float3 smoothEdge0, // edge0 for three smooth steps + float3 smoothEdge1, // edge1 for three smooth steps + float3 smoothOneOverWidth, // width of three smooth steps + + float2 shear, // shear in X and Y + float4 aAbB, // Superellipse dimensions + float2 rounds ) // two functions of roundness packed together +{ + float2 qr = ClipSuperellipse( (PL / PL.z) - shear, aAbB, rounds ); + + smoothEdge0.x = qr.x; // Fill in the dynamic parts of the smoothsteps + smoothEdge1.x = qr.y; // The other components are pre-computed outside of the shader + smoothOneOverWidth.x = 1.0f / ( qr.y - qr.x ); + float3 x = float3( 1, PL.z, PL.z ); + + float3 atten3 = smoothstep3( smoothEdge0, smoothEdge1, smoothOneOverWidth, x ); + + // Modulate the three resulting attenuations (flipping the sense of the attenuation from the superellipse and the far clip) + return (1.0f - atten3.x) * atten3.y * (1.0f - atten3.z); +} + + +// JasonM - TODO: remove this simpleton version +float DoShadow( sampler DepthSampler, float4 texCoord ) +{ + const float g_flShadowBias = 0.0005f; + float2 uoffset = float2( 0.5f/512.f, 0.0f ); + float2 voffset = float2( 0.0f, 0.5f/512.f ); + float3 projTexCoord = texCoord.xyz / texCoord.w; + float4 flashlightDepth = float4( tex2D( DepthSampler, projTexCoord + uoffset + voffset ).x, + tex2D( DepthSampler, projTexCoord + uoffset - voffset ).x, + tex2D( DepthSampler, projTexCoord - uoffset + voffset ).x, + tex2D( DepthSampler, projTexCoord - uoffset - voffset ).x ); + +# if ( defined( REVERSE_DEPTH_ON_X360 ) ) + { + flashlightDepth = 1.0f - flashlightDepth; + } +# endif + + float shadowed = 0.0f; + float z = texCoord.z/texCoord.w; + float4 dz = float4(z,z,z,z) - (flashlightDepth + float4( g_flShadowBias, g_flShadowBias, g_flShadowBias, g_flShadowBias)); + float4 shadow = float4(0.25f,0.25f,0.25f,0.25f); + + if( dz.x <= 0.0f ) + shadowed += shadow.x; + if( dz.y <= 0.0f ) + shadowed += shadow.y; + if( dz.z <= 0.0f ) + shadowed += shadow.z; + if( dz.w <= 0.0f ) + shadowed += shadow.w; + + return shadowed; +} + + +float DoShadowNvidiaRAWZOneTap( sampler DepthSampler, const float4 shadowMapPos ) +{ + float ooW = 1.0f / shadowMapPos.w; // 1 / w + float3 shadowMapCenter_objDepth = shadowMapPos.xyz * ooW; // Do both projections at once + + float2 shadowMapCenter = shadowMapCenter_objDepth.xy; // Center of shadow filter + float objDepth = shadowMapCenter_objDepth.z; // Object depth in shadow space + + float fDepth = dot(tex2D(DepthSampler, shadowMapCenter).arg, float3(0.996093809371817670572857294849, 0.0038909914428586627756752238080039, 1.5199185323666651467481343000015e-5)); + + return fDepth > objDepth; +} + + +float DoShadowNvidiaRAWZ( sampler DepthSampler, const float4 shadowMapPos ) +{ + float fE = 1.0f / 512.0f; // Epsilon + + float ooW = 1.0f / shadowMapPos.w; // 1 / w + float3 shadowMapCenter_objDepth = shadowMapPos.xyz * ooW; // Do both projections at once + + float2 shadowMapCenter = shadowMapCenter_objDepth.xy; // Center of shadow filter + float objDepth = shadowMapCenter_objDepth.z; // Object depth in shadow space + + float4 vDepths; + vDepths.x = dot(tex2D(DepthSampler, shadowMapCenter + float2( fE, fE )).arg, float3(0.996093809371817670572857294849, 0.0038909914428586627756752238080039, 1.5199185323666651467481343000015e-5)); + vDepths.y = dot(tex2D(DepthSampler, shadowMapCenter + float2( -fE, fE )).arg, float3(0.996093809371817670572857294849, 0.0038909914428586627756752238080039, 1.5199185323666651467481343000015e-5)); + vDepths.z = dot(tex2D(DepthSampler, shadowMapCenter + float2( fE, -fE )).arg, float3(0.996093809371817670572857294849, 0.0038909914428586627756752238080039, 1.5199185323666651467481343000015e-5)); + vDepths.w = dot(tex2D(DepthSampler, shadowMapCenter + float2( -fE, -fE )).arg, float3(0.996093809371817670572857294849, 0.0038909914428586627756752238080039, 1.5199185323666651467481343000015e-5)); + + return dot(vDepths > objDepth.xxxx, float4(0.25, 0.25, 0.25, 0.25)); +} + + +float DoShadowNvidiaCheap( sampler DepthSampler, const float4 shadowMapPos ) +{ + float fTexelEpsilon = 1.0f / 1024.0f; + + float ooW = 1.0f / shadowMapPos.w; // 1 / w + float3 shadowMapCenter_objDepth = shadowMapPos.xyz * ooW; // Do both projections at once + + float2 shadowMapCenter = shadowMapCenter_objDepth.xy; // Center of shadow filter + float objDepth = shadowMapCenter_objDepth.z; // Object depth in shadow space + + float4 vTaps; + vTaps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTexelEpsilon, fTexelEpsilon), objDepth, 1 ) ).x; + vTaps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTexelEpsilon, fTexelEpsilon), objDepth, 1 ) ).x; + vTaps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTexelEpsilon, -fTexelEpsilon), objDepth, 1 ) ).x; + vTaps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTexelEpsilon, -fTexelEpsilon), objDepth, 1 ) ).x; + + return dot(vTaps, float4(0.25, 0.25, 0.25, 0.25)); +} + +float DoShadowNvidiaPCF3x3Box( sampler DepthSampler, const float4 shadowMapPos ) +{ + float fTexelEpsilon = 1.0f / 1024.0f; + + float ooW = 1.0f / shadowMapPos.w; // 1 / w + float3 shadowMapCenter_objDepth = shadowMapPos.xyz * ooW; // Do both projections at once + + float2 shadowMapCenter = shadowMapCenter_objDepth.xy; // Center of shadow filter + float objDepth = shadowMapCenter_objDepth.z; // Object depth in shadow space + + float4 vOneTaps; + vOneTaps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTexelEpsilon, fTexelEpsilon ), objDepth, 1 ) ).x; + vOneTaps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTexelEpsilon, fTexelEpsilon ), objDepth, 1 ) ).x; + vOneTaps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTexelEpsilon, -fTexelEpsilon ), objDepth, 1 ) ).x; + vOneTaps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTexelEpsilon, -fTexelEpsilon ), objDepth, 1 ) ).x; + float flOneTaps = dot( vOneTaps, float4(1.0f / 9.0f, 1.0f / 9.0f, 1.0f / 9.0f, 1.0f / 9.0f)); + + float4 vTwoTaps; + vTwoTaps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTexelEpsilon, 0 ), objDepth, 1 ) ).x; + vTwoTaps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTexelEpsilon, 0 ), objDepth, 1 ) ).x; + vTwoTaps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( 0, -fTexelEpsilon ), objDepth, 1 ) ).x; + vTwoTaps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( 0, -fTexelEpsilon ), objDepth, 1 ) ).x; + float flTwoTaps = dot( vTwoTaps, float4(1.0f / 9.0f, 1.0f / 9.0f, 1.0f / 9.0f, 1.0f / 9.0f)); + + float flCenterTap = tex2Dproj( DepthSampler, float4( shadowMapCenter, objDepth, 1 ) ).x * (1.0f / 9.0f); + + // Sum all 9 Taps + return flOneTaps + flTwoTaps + flCenterTap; +} + + +// +// 1 4 7 4 1 +// 4 20 33 20 4 +// 7 33 55 33 7 +// 4 20 33 20 4 +// 1 4 7 4 1 +// +float DoShadowNvidiaPCF5x5Gaussian( sampler DepthSampler, const float4 shadowMapPos ) +{ + float fEpsilon = 1.0f / 512.0f; + float fTwoEpsilon = 2.0f * fEpsilon; + + float ooW = 1.0f / shadowMapPos.w; // 1 / w + float3 shadowMapCenter_objDepth = shadowMapPos.xyz * ooW; // Do both projections at once + + float2 shadowMapCenter = shadowMapCenter_objDepth.xy; // Center of shadow filter + float objDepth = shadowMapCenter_objDepth.z; // Object depth in shadow space + + float4 vOneTaps; + vOneTaps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTwoEpsilon, fTwoEpsilon ), objDepth, 1 ) ).x; + vOneTaps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTwoEpsilon, fTwoEpsilon ), objDepth, 1 ) ).x; + vOneTaps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTwoEpsilon, -fTwoEpsilon ), objDepth, 1 ) ).x; + vOneTaps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTwoEpsilon, -fTwoEpsilon ), objDepth, 1 ) ).x; + float flOneTaps = dot( vOneTaps, float4(1.0f / 331.0f, 1.0f / 331.0f, 1.0f / 331.0f, 1.0f / 331.0f)); + + float4 vSevenTaps; + vSevenTaps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTwoEpsilon, 0 ), objDepth, 1 ) ).x; + vSevenTaps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTwoEpsilon, 0 ), objDepth, 1 ) ).x; + vSevenTaps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( 0, -fTwoEpsilon ), objDepth, 1 ) ).x; + vSevenTaps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( 0, -fTwoEpsilon ), objDepth, 1 ) ).x; + float flSevenTaps = dot( vSevenTaps, float4( 7.0f / 331.0f, 7.0f / 331.0f, 7.0f / 331.0f, 7.0f / 331.0f ) ); + + float4 vFourTapsA, vFourTapsB; + vFourTapsA.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTwoEpsilon, fEpsilon ), objDepth, 1 ) ).x; + vFourTapsA.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fEpsilon, fTwoEpsilon ), objDepth, 1 ) ).x; + vFourTapsA.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fEpsilon, fTwoEpsilon ), objDepth, 1 ) ).x; + vFourTapsA.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTwoEpsilon, fEpsilon ), objDepth, 1 ) ).x; + vFourTapsB.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTwoEpsilon, -fEpsilon ), objDepth, 1 ) ).x; + vFourTapsB.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fEpsilon, -fTwoEpsilon ), objDepth, 1 ) ).x; + vFourTapsB.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fEpsilon, -fTwoEpsilon ), objDepth, 1 ) ).x; + vFourTapsB.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTwoEpsilon, -fEpsilon ), objDepth, 1 ) ).x; + float flFourTapsA = dot( vFourTapsA, float4( 4.0f / 331.0f, 4.0f / 331.0f, 4.0f / 331.0f, 4.0f / 331.0f ) ); + float flFourTapsB = dot( vFourTapsB, float4( 4.0f / 331.0f, 4.0f / 331.0f, 4.0f / 331.0f, 4.0f / 331.0f ) ); + + float4 v20Taps; + v20Taps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fEpsilon, fEpsilon ), objDepth, 1 ) ).x; + v20Taps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fEpsilon, fEpsilon ), objDepth, 1 ) ).x; + v20Taps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fEpsilon, -fEpsilon ), objDepth, 1 ) ).x; + v20Taps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fEpsilon, -fEpsilon ), objDepth, 1 ) ).x; + float fl20Taps = dot( v20Taps, float4(20.0f / 331.0f, 20.0f / 331.0f, 20.0f / 331.0f, 20.0f / 331.0f)); + + float4 v33Taps; + v33Taps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fEpsilon, 0 ), objDepth, 1 ) ).x; + v33Taps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fEpsilon, 0 ), objDepth, 1 ) ).x; + v33Taps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( 0, -fEpsilon ), objDepth, 1 ) ).x; + v33Taps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( 0, -fEpsilon ), objDepth, 1 ) ).x; + float fl33Taps = dot( v33Taps, float4(33.0f / 331.0f, 33.0f / 331.0f, 33.0f / 331.0f, 33.0f / 331.0f)); + + float flCenterTap = tex2Dproj( DepthSampler, float4( shadowMapCenter, objDepth, 1 ) ).x * (55.0f / 331.0f); + + // Sum all 25 Taps + return flOneTaps + flSevenTaps + flFourTapsA + flFourTapsB + fl20Taps + fl33Taps + flCenterTap; +} + + +float DoShadowATICheap( sampler DepthSampler, const float4 shadowMapPos ) +{ + float2 shadowMapCenter = shadowMapPos.xy/shadowMapPos.w; + float objDepth = shadowMapPos.z / shadowMapPos.w; + float fSampleDepth = tex2D( DepthSampler, shadowMapCenter ).x; + + objDepth = min( objDepth, 0.99999 ); //HACKHACK: On 360, surfaces at or past the far flashlight plane have an abrupt cutoff. This is temp until a smooth falloff is implemented + + return fSampleDepth > objDepth; +} + + +// Poisson disc, randomly rotated at different UVs +float DoShadowPoisson16Sample( sampler DepthSampler, sampler RandomRotationSampler, const float3 vProjCoords, const float2 vScreenPos, const float4 vShadowTweaks, bool bForceSimple, bool bNvidiaHardwarePCF, bool bFetch4 ) +{ + float2 vPoissonOffset[8] = { float2( 0.3475f, 0.0042f ), float2( 0.8806f, 0.3430f ), float2( -0.0041f, -0.6197f ), float2( 0.0472f, 0.4964f ), + float2( -0.3730f, 0.0874f ), float2( -0.9217f, -0.3177f ), float2( -0.6289f, 0.7388f ), float2( 0.5744f, -0.7741f ) }; + + float flScaleOverMapSize = vShadowTweaks.x * 2; // Tweak parameters to shader + float2 vNoiseOffset = vShadowTweaks.zw; + float4 vLightDepths = 0, accum = 0.0f; + float2 rotOffset = 0; + + float2 shadowMapCenter = vProjCoords.xy; // Center of shadow filter + float objDepth = min( vProjCoords.z, 0.99999 ); // Object depth in shadow space + + // 2D Rotation Matrix setup + float3 RMatTop = 0, RMatBottom = 0; +#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) + RMatTop.xy = tex2D( RandomRotationSampler, cFlashlightScreenScale.xy * (vScreenPos * 0.5 + 0.5) + vNoiseOffset) * 2.0 - 1.0; + RMatBottom.xy = float2(-1.0, 1.0) * RMatTop.yx; // 2x2 rotation matrix in 4-tuple +#endif + + RMatTop *= flScaleOverMapSize; // Scale up kernel while accounting for texture resolution + RMatBottom *= flScaleOverMapSize; + + RMatTop.z = shadowMapCenter.x; // To be added in d2adds generated below + RMatBottom.z = shadowMapCenter.y; + + float fResult = 0.0f; + + if ( bNvidiaHardwarePCF ) + { + if ( bForceSimple ) + { + rotOffset.x = dot( RMatTop.xy, vPoissonOffset[1].xy ) + RMatTop.z; + rotOffset.y = dot( RMatBottom.xy, vPoissonOffset[1].xy ) + RMatBottom.z; + return tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x; + } + else + { + rotOffset.x = dot( RMatTop.xy, vPoissonOffset[0].xy ) + RMatTop.z; + rotOffset.y = dot( RMatBottom.xy, vPoissonOffset[0].xy ) + RMatBottom.z; + vLightDepths.x += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x; + + rotOffset.x = dot( RMatTop.xy, vPoissonOffset[1].xy ) + RMatTop.z; + rotOffset.y = dot( RMatBottom.xy, vPoissonOffset[1].xy ) + RMatBottom.z; + vLightDepths.y += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x; + + rotOffset.x = dot( RMatTop.xy, vPoissonOffset[2].xy ) + RMatTop.z; + rotOffset.y = dot( RMatBottom.xy, vPoissonOffset[2].xy ) + RMatBottom.z; + vLightDepths.z += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x; + + rotOffset.x = dot( RMatTop.xy, vPoissonOffset[3].xy ) + RMatTop.z; + rotOffset.y = dot( RMatBottom.xy, vPoissonOffset[3].xy ) + RMatBottom.z; + vLightDepths.w += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x; + + rotOffset.x = dot( RMatTop.xy, vPoissonOffset[4].xy ) + RMatTop.z; + rotOffset.y = dot( RMatBottom.xy, vPoissonOffset[4].xy ) + RMatBottom.z; + vLightDepths.x += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x; + + rotOffset.x = dot( RMatTop.xy, vPoissonOffset[5].xy ) + RMatTop.z; + rotOffset.y = dot( RMatBottom.xy, vPoissonOffset[5].xy ) + RMatBottom.z; + vLightDepths.y += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x; + + rotOffset.x = dot( RMatTop.xy, vPoissonOffset[6].xy ) + RMatTop.z; + rotOffset.y = dot( RMatBottom.xy, vPoissonOffset[6].xy ) + RMatBottom.z; + vLightDepths.z += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x; + + rotOffset.x = dot( RMatTop.xy, vPoissonOffset[7].xy ) + RMatTop.z; + rotOffset.y = dot( RMatBottom.xy, vPoissonOffset[7].xy ) + RMatBottom.z; + vLightDepths.w += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x; + + // This should actually be float4( 0.125, 0.125, 0.125, 0.125) but we've tuned so many shots in the SFM + // relying on this bug that it doesn't seem right to fix until we have done something like move + // this code out to a staging branch for a shipping game. + // This is certainly one source of difference between ATI and nVidia in SFM layoffs + return dot( vLightDepths, float4( 0.25, 0.25, 0.25, 0.25) ); + } + } + else if ( bFetch4 ) + { + if ( bForceSimple ) + { + rotOffset.x = dot( RMatTop.xy, vPoissonOffset[1].xy ) + RMatTop.z; + rotOffset.y = dot( RMatBottom.xy, vPoissonOffset[1].xy ) + RMatBottom.z; + vLightDepths = tex2D( DepthSampler, rotOffset.xy ); + return dot( vLightDepths > objDepth.xxxx, float4( 0.25f, 0.25f, 0.25f, 0.25f ) ); + } + else + { + for( int i=0; i<8; i++ ) + { + rotOffset.x = dot( RMatTop.xy, vPoissonOffset[i].xy ) + RMatTop.z; + rotOffset.y = dot( RMatBottom.xy, vPoissonOffset[i].xy ) + RMatBottom.z; + vLightDepths = tex2D( DepthSampler, rotOffset.xy ); + accum += (vLightDepths > objDepth.xxxx); + } + + return dot( accum, float4( 1.0f/32.0f, 1.0f/32.0f, 1.0f/32.0f, 1.0f/32.0f) ); + } + } + else // ATI vanilla hardware shadow mapping + { + if ( bForceSimple ) + { + rotOffset.x = dot( RMatTop.xy, vPoissonOffset[1].xy ) + RMatTop.z; + rotOffset.y = dot( RMatBottom.xy, vPoissonOffset[1].xy ) + RMatBottom.z; + return tex2D( DepthSampler, rotOffset.xy ).x > objDepth; + } + else + { + for( int i=0; i<2; i++ ) + { + rotOffset.x = dot( RMatTop.xy, vPoissonOffset[4*i+0].xy ) + RMatTop.z; + rotOffset.y = dot( RMatBottom.xy, vPoissonOffset[4*i+0].xy ) + RMatBottom.z; + vLightDepths.x = tex2D( DepthSampler, rotOffset.xy ).x; + + rotOffset.x = dot( RMatTop.xy, vPoissonOffset[4*i+1].xy ) + RMatTop.z; + rotOffset.y = dot( RMatBottom.xy, vPoissonOffset[4*i+1].xy ) + RMatBottom.z; + vLightDepths.y = tex2D( DepthSampler, rotOffset.xy ).x; + + rotOffset.x = dot( RMatTop.xy, vPoissonOffset[4*i+2].xy ) + RMatTop.z; + rotOffset.y = dot( RMatBottom.xy, vPoissonOffset[4*i+2].xy ) + RMatBottom.z; + vLightDepths.z = tex2D( DepthSampler, rotOffset.xy ).x; + + rotOffset.x = dot( RMatTop.xy, vPoissonOffset[4*i+3].xy ) + RMatTop.z; + rotOffset.y = dot( RMatBottom.xy, vPoissonOffset[4*i+3].xy ) + RMatBottom.z; + vLightDepths.w = tex2D( DepthSampler, rotOffset.xy ).x; + + accum += (vLightDepths > objDepth.xxxx); + } + + return dot( accum, float4( 0.125, 0.125, 0.125, 0.125 ) ); + } + } +} + +#if defined( _X360 ) + +// Poisson disc, randomly rotated at different UVs +float DoShadow360Simple( sampler DepthSampler, const float3 vProjCoords ) +{ + float fLOD; + float2 shadowMapCenter = vProjCoords.xy; // Center of shadow filter + float objDepth = min( vProjCoords.z, 0.99999 ); // Object depth in shadow space + +#if defined( REVERSE_DEPTH_ON_X360 ) + objDepth = 1.0f - objDepth; +#endif + + float4 vSampledDepths, vWeights; + + asm { + getCompTexLOD2D fLOD.x, shadowMapCenter.xy, DepthSampler, AnisoFilter=max16to1 + setTexLOD fLOD.x + + tfetch2D vSampledDepths.x___, shadowMapCenter, DepthSampler, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepths._x__, shadowMapCenter, DepthSampler, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepths.__x_, shadowMapCenter, DepthSampler, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepths.___x, shadowMapCenter, DepthSampler, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + + getWeights2D vWeights, shadowMapCenter.xy, DepthSampler, MagFilter=linear, MinFilter=linear, UseComputedLOD=false, UseRegisterLOD=true + }; + + vWeights = float4( (1-vWeights.x)*(1-vWeights.y), vWeights.x*(1-vWeights.y), (1-vWeights.x)*vWeights.y, vWeights.x*vWeights.y ); + +#if defined( REVERSE_DEPTH_ON_X360 ) + float4 vCompare = (vSampledDepths < objDepth.xxxx); +#else + float4 vCompare = (vSampledDepths > objDepth.xxxx); +#endif + + return dot( vCompare, vWeights ); +} + + +float Do360PCFFetch( sampler DepthSampler, float2 tc, float objDepth ) +{ + float fLOD; + float4 vSampledDepths, vWeights; + + asm { + getCompTexLOD2D fLOD.x, tc.xy, DepthSampler, AnisoFilter=max16to1 + setTexLOD fLOD.x + + tfetch2D vSampledDepths.x___, tc, DepthSampler, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepths._x__, tc, DepthSampler, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepths.__x_, tc, DepthSampler, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepths.___x, tc, DepthSampler, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + + getWeights2D vWeights, tc.xy, DepthSampler, MagFilter=linear, MinFilter=linear, UseComputedLOD=false, UseRegisterLOD=true + }; + + vWeights = float4( (1-vWeights.x)*(1-vWeights.y), vWeights.x*(1-vWeights.y), (1-vWeights.x)*vWeights.y, vWeights.x*vWeights.y ); + +#if defined( REVERSE_DEPTH_ON_X360 ) + float4 vCompare = (vSampledDepths < objDepth.xxxx); +#else + float4 vCompare = (vSampledDepths > objDepth.xxxx); +#endif + + return dot( vCompare, vWeights ); +} + + + +float Do360NearestFetch( sampler DepthSampler, float2 tc, float objDepth ) +{ + float fLOD; + float4 vSampledDepth; + + asm { + getCompTexLOD2D fLOD.x, tc.xy, DepthSampler, AnisoFilter=max16to1 + setTexLOD fLOD.x + + tfetch2D vSampledDepth.x___, tc, DepthSampler, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + }; + +#if defined( REVERSE_DEPTH_ON_X360 ) + return (vSampledDepth.x < objDepth.x); +#else + return (vSampledDepth.x > objDepth.x); +#endif + +} + + +float AmountShadowed_8Tap_360( sampler DepthSampler, float2 tc, float objDepth ) +{ + float fLOD; + float4 vSampledDepthsA, vSampledDepthsB; + + // Optimal 8 rooks pattern to get an idea about whether we're at a penumbra or not + // From [Kallio07] "Scanline Edge-Flag Algorithm for Antialiasing" + // + // +---+---+---+---+---+---+---+---+ + // | | | | | | o | | | + // +---+---+---+---+---+---+---+---+ + // | o | | | | | | | | + // +---+---+---+---+---+---+---+---+ + // | | | | o | | | | | + // +---+---+---+---+---+---+---+---+ + // | | | | | | | o | | + // +---+---+---+---+---+---+---+---+ + // | | o | | | | | | | + // +---+---+---+---+---+---+---+---+ + // | | | | | o | | | | + // +---+---+---+---+---+---+---+---+ + // | | | | | | | | o | + // +---+---+---+---+---+---+---+---+ + // | | | o | | | | | | + // +---+---+---+---+---+---+---+---+ + // + asm { + getCompTexLOD2D fLOD.x, tc.xy, DepthSampler, AnisoFilter=max16to1 + setTexLOD fLOD.x + + tfetch2D vSampledDepthsA.x___, tc, DepthSampler, OffsetX = -2.0, OffsetY = -1.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepthsA._x__, tc, DepthSampler, OffsetX = -1.5, OffsetY = 0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepthsA.__x_, tc, DepthSampler, OffsetX = -1.0, OffsetY = 2.0, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepthsA.___x, tc, DepthSampler, OffsetX = -0.5, OffsetY = -1.0, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + + tfetch2D vSampledDepthsB.x___, tc, DepthSampler, OffsetX = 0.5, OffsetY = 1.0, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepthsB._x__, tc, DepthSampler, OffsetX = 1.0, OffsetY = -2.0, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepthsB.__x_, tc, DepthSampler, OffsetX = 1.5, OffsetY = -0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepthsB.___x, tc, DepthSampler, OffsetX = 2.0, OffsetY = 1.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + }; + +#if defined( REVERSE_DEPTH_ON_X360 ) + float4 vCompareA = (vSampledDepthsA < objDepth.xxxx); + float4 vCompareB = (vSampledDepthsB < objDepth.xxxx); +#else + float4 vCompareA = (vSampledDepthsA > objDepth.xxxx); + float4 vCompareB = (vSampledDepthsB > objDepth.xxxx); +#endif + + return dot( vCompareA, float4(0.125,0.125,0.125,0.125) ) + dot( vCompareB, float4(0.125,0.125,0.125,0.125) ); +} + + +float AmountShadowed_4Tap_360( sampler DepthSampler, float2 tc, float objDepth ) +{ + float fLOD; + float4 vSampledDepths; + + // Rotated grid pattern to get an idea about whether we're at a penumbra or not + asm { + getCompTexLOD2D fLOD.x, tc.xy, DepthSampler, AnisoFilter=max16to1 + setTexLOD fLOD.x + + tfetch2D vSampledDepths.x___, tc, DepthSampler, OffsetX = -1.0, OffsetY = 0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepths._x__, tc, DepthSampler, OffsetX = -0.5, OffsetY = -1.0, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepths.__x_, tc, DepthSampler, OffsetX = 0.5, OffsetY = 1.0, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + tfetch2D vSampledDepths.___x, tc, DepthSampler, OffsetX = 1.0, OffsetY = -0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point + }; + +#if defined( REVERSE_DEPTH_ON_X360 ) + float4 vCompare = (vSampledDepths < objDepth.xxxx); +#else + float4 vCompare = (vSampledDepths > objDepth.xxxx); +#endif + + return dot( vCompare, float4(0.25,0.25,0.25,0.25) ); +} + +// Poisson disc, randomly rotated at different UVs +float DoShadowPoisson360( sampler DepthSampler, sampler RandomRotationSampler, const float3 vProjCoords, const float2 vScreenPos, const float4 vShadowTweaks ) +{ + float2 vPoissonOffset[8] = { float2( 0.3475f, 0.0042f ), float2( 0.8806f, 0.3430f ), + float2( -0.0041f, -0.6197f ), float2( 0.0472f, 0.4964f ), + float2( -0.3730f, 0.0874f ), float2( -0.9217f, -0.3177f ), + float2( -0.6289f, 0.7388f ), float2( 0.5744f, -0.7741f ) }; + + float2 shadowMapCenter = vProjCoords.xy; // Center of shadow filter + float objDepth = min( vProjCoords.z, 0.99999 ); // Object depth in shadow space + +#if defined( REVERSE_DEPTH_ON_X360 ) + objDepth = 1.0f - objDepth; +#endif + + float fAmountShadowed = AmountShadowed_4Tap_360( DepthSampler, shadowMapCenter, objDepth ); + + if ( fAmountShadowed >= 1.0f ) // Fully in light + { + return 1.0f; + } + else // Do the expensive filtering since we're at least partially shadowed + { + float flScaleOverMapSize = 1.7f / 512.0f; // Tweak parameters to shader + + // 2D Rotation Matrix setup + float3 RMatTop = 0, RMatBottom = 0; +#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) + RMatTop.xy = tex2D( RandomRotationSampler, cFlashlightScreenScale.xy * (vScreenPos * 0.5 + 0.5)) * 2.0 - 1.0; + RMatBottom.xy = float2(-1.0, 1.0) * RMatTop.yx; // 2x2 rotation matrix in 4-tuple +#endif + + RMatTop *= flScaleOverMapSize; // Scale up kernel while accounting for texture resolution + RMatBottom *= flScaleOverMapSize; + RMatTop.z = shadowMapCenter.x; // To be added in d2adds generated below + RMatBottom.z = shadowMapCenter.y; + float2 rotOffset = float2(0,0); + float4 vAccum = 0; + + rotOffset.x = dot( RMatTop.xy, vPoissonOffset[0].xy) + RMatTop.z; + rotOffset.y = dot( RMatBottom.xy, vPoissonOffset[0].xy) + RMatBottom.z; + vAccum.x = Do360NearestFetch( DepthSampler, rotOffset, objDepth ); + + rotOffset.x = dot( RMatTop.xy, vPoissonOffset[1].xy) + RMatTop.z; + rotOffset.y = dot( RMatBottom.xy, vPoissonOffset[1].xy) + RMatBottom.z; + vAccum.y = Do360NearestFetch( DepthSampler, rotOffset, objDepth ); + + rotOffset.x = dot( RMatTop.xy, vPoissonOffset[2].xy) + RMatTop.z; + rotOffset.y = dot( RMatBottom.xy, vPoissonOffset[2].xy) + RMatBottom.z; + vAccum.z = Do360NearestFetch( DepthSampler, rotOffset, objDepth ); + + rotOffset.x = dot( RMatTop.xy, vPoissonOffset[3].xy) + RMatTop.z; + rotOffset.y = dot( RMatBottom.xy, vPoissonOffset[3].xy) + RMatBottom.z; + vAccum.w = Do360NearestFetch( DepthSampler, rotOffset, objDepth ); + + rotOffset.x = dot( RMatTop.xy, vPoissonOffset[4].xy) + RMatTop.z; + rotOffset.y = dot( RMatBottom.xy, vPoissonOffset[4].xy) + RMatBottom.z; + vAccum.x += Do360NearestFetch( DepthSampler, rotOffset, objDepth ); + + rotOffset.x = dot( RMatTop.xy, vPoissonOffset[5].xy) + RMatTop.z; + rotOffset.y = dot( RMatBottom.xy, vPoissonOffset[5].xy) + RMatBottom.z; + vAccum.y += Do360NearestFetch( DepthSampler, rotOffset, objDepth ); + + rotOffset.x = dot( RMatTop.xy, vPoissonOffset[6].xy) + RMatTop.z; + rotOffset.y = dot( RMatBottom.xy, vPoissonOffset[6].xy) + RMatBottom.z; + vAccum.z += Do360NearestFetch( DepthSampler, rotOffset, objDepth ); + + rotOffset.x = dot( RMatTop.xy, vPoissonOffset[7].xy) + RMatTop.z; + rotOffset.y = dot( RMatBottom.xy, vPoissonOffset[7].xy) + RMatBottom.z; + vAccum.w += Do360NearestFetch( DepthSampler, rotOffset, objDepth ); + + return dot( vAccum, float4( 0.25, 0.25, 0.25, 0.25) ); + } +} + +#endif // _X360 + + +float DoFlashlightShadow( sampler DepthSampler, sampler RandomRotationSampler, float3 vProjCoords, float2 vScreenPos, int nShadowLevel, float4 vShadowTweaks, bool bAllowHighQuality, bool bForceSimple = false ) +{ + float flShadow = 1.0f; + +#if !defined( _X360 ) //PC + + if( nShadowLevel == NVIDIA_PCF_POISSON ) + flShadow = DoShadowPoisson16Sample( DepthSampler, RandomRotationSampler, vProjCoords, vScreenPos, vShadowTweaks, bForceSimple, true, false ); + else if( nShadowLevel == ATI_NOPCF ) + flShadow = DoShadowPoisson16Sample( DepthSampler, RandomRotationSampler, vProjCoords, vScreenPos, vShadowTweaks, bForceSimple, false, false ); + else if( nShadowLevel == ATI_NO_PCF_FETCH4 ) + flShadow = DoShadowPoisson16Sample( DepthSampler, RandomRotationSampler, vProjCoords, vScreenPos, vShadowTweaks, bForceSimple, false, true ); + + return flShadow; +#else + + // Compile-time switch for shaders which allow high quality modes on 360 + if ( bAllowHighQuality ) + { + // Static control flow switch for shadow quality. Some non-interactive sequences use the high quality path + if ( g_bHighQualityShadows ) + { + flShadow = DoShadowPoisson360( DepthSampler, RandomRotationSampler, vProjCoords, vScreenPos, vShadowTweaks ); + } + else + { + flShadow = DoShadow360Simple( DepthSampler, vProjCoords ); + } + } + else + { + flShadow = DoShadow360Simple( DepthSampler, vProjCoords ); + } + + return flShadow; + +#endif +} + +float3 SpecularLight( const float3 vWorldNormal, const float3 vLightDir, const float fSpecularExponent, + const float3 vEyeDir, const bool bDoSpecularWarp, in sampler specularWarpSampler, float fFresnel ) +{ + float3 result = float3(0.0f, 0.0f, 0.0f); + + float3 vReflect = reflect( -vEyeDir, vWorldNormal ); // Reflect view through normal + float3 vSpecular = saturate(dot( vReflect, vLightDir )); // L.R (use half-angle instead?) + vSpecular = pow( vSpecular.x, fSpecularExponent ); // Raise to specular power + + // Optionally warp as function of scalar specular and fresnel + if ( bDoSpecularWarp ) + vSpecular *= tex2D( specularWarpSampler, float2(vSpecular.x, fFresnel) ); // Sample at { (L.R)^k, fresnel } + + return vSpecular; +} + +void DoSpecularFlashlight( float3 flashlightPos, float3 worldPos, float4 flashlightSpacePosition, float3 worldNormal, + float3 attenuationFactors, float farZ, sampler FlashlightSampler, sampler FlashlightDepthSampler, sampler RandomRotationSampler, + int nShadowLevel, bool bDoShadows, bool bAllowHighQuality, const float2 vScreenPos, const float fSpecularExponent, const float3 vEyeDir, + const bool bDoDiffuseWarp, sampler DiffuseWarpSampler, const bool bDoSpecularWarp, sampler specularWarpSampler, float fFresnel, float4 vShadowTweaks, + + // Outputs of this shader...separate shadowed diffuse and specular from the flashlight + out float3 diffuseLighting, out float3 specularLighting ) +{ + float3 vProjCoords = flashlightSpacePosition.xyz / flashlightSpacePosition.w; + float3 flashlightColor = float3(1,1,1); + + flashlightColor = tex2D( FlashlightSampler, vProjCoords ); + +#if !defined( _X360 ) +#if defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) + flashlightColor *= flashlightSpacePosition.www > float3(0,0,0); // Catch back projection (PC-only, ps2b and up) +#endif +#endif + +#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) + flashlightColor *= cFlashlightColor.xyz; // Flashlight color +#endif + + float3 delta = flashlightPos - worldPos; + float3 L = normalize( delta ); + float distSquared = dot( delta, delta ); + float dist = sqrt( distSquared ); + + float endFalloffFactor = RemapValClamped( dist, farZ, 0.6f * farZ, 0.0f, 1.0f ); + + // Attenuation for light and to fade out shadow over distance + float fAtten = saturate( dot( attenuationFactors, float3( 1.0f, 1.0f/dist, 1.0f/distSquared ) ) ); + + // Shadowing and coloring terms +#if (defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)) + if ( bDoShadows ) + { + float flShadow = DoFlashlightShadow( FlashlightDepthSampler, RandomRotationSampler, vProjCoords, vScreenPos, nShadowLevel, vShadowTweaks, bAllowHighQuality ); + float flAttenuated = lerp( flShadow, 1.0f, vShadowTweaks.y ); // Blend between fully attenuated and not attenuated + flShadow = saturate( lerp( flAttenuated, flShadow, fAtten ) ); // Blend between shadow and above, according to light attenuation + flashlightColor *= flShadow; // Shadow term + } +#endif + + diffuseLighting = fAtten; + float NdotL = dot( L.xyz, worldNormal.xyz ); + + // JasonM - experimenting with light-warping the flashlight + if ( false )//bDoDiffuseWarp ) + { + float warpCoord = saturate(NdotL * 0.5f + 0.5f); // 0..1 + diffuseLighting *= tex2D( DiffuseWarpSampler, float2( warpCoord, 0.0f) ); // Look up warped light + } + else // common path + { +#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) + NdotL += flFlashlightNoLambertValue; +#endif + diffuseLighting *= saturate( NdotL ); // Lambertian term + } + + diffuseLighting *= flashlightColor; + diffuseLighting *= endFalloffFactor; + + // Specular term (masked by diffuse) + specularLighting = diffuseLighting * SpecularLight ( worldNormal, L, fSpecularExponent, vEyeDir, bDoSpecularWarp, specularWarpSampler, fFresnel ); +} + +// Diffuse only version +float3 DoFlashlight( float3 flashlightPos, float3 worldPos, float4 flashlightSpacePosition, float3 worldNormal, + float3 attenuationFactors, float farZ, sampler FlashlightSampler, sampler FlashlightDepthSampler, + sampler RandomRotationSampler, int nShadowLevel, bool bDoShadows, bool bAllowHighQuality, + const float2 vScreenPos, bool bClip, float4 vShadowTweaks = float4(3/1024.0f, 0.0005f, 0.0f, 0.0f), bool bHasNormal = true, bool bForceSimple = false ) +{ + float3 vProjCoords = flashlightSpacePosition.xyz / flashlightSpacePosition.w; + float3 flashlightColor = float3(1,1,1); + + #if ( defined( _X360 ) ) + { + float3 ltz = vProjCoords.xyz < float3( 0.0f, 0.0f, 0.0f ); + ltz.z = 0.0f; // don't clip the near plane per pixel since we don't do that on the PC. + float3 gto = vProjCoords.xyz > float3( 1.0f, 1.0f, 1.0f ); + + [branch] + if ( dot(ltz + gto, float3(1,1,1)) > 0 ) + { + if ( bClip ) + { + clip(-1); + } + return float3(0,0,0); + } + else + { + flashlightColor = tex2D( FlashlightSampler, vProjCoords ); + } + } + #else + { + flashlightColor = tex2D( FlashlightSampler, vProjCoords ); + + #if ( defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) ) + flashlightColor *= flashlightSpacePosition.www > float3(0,0,0); // Catch back projection (PC-only, ps2b and up) + #endif + } + #endif + + #if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) + { + flashlightColor *= cFlashlightColor.xyz; // Flashlight color + } + #endif + + float3 delta = flashlightPos - worldPos; + float3 L = normalize( delta ); + float distSquared = dot( delta, delta ); + float dist = sqrt( distSquared ); + + float endFalloffFactor = RemapValClamped( dist, farZ, 0.6f * farZ, 0.0f, 1.0f ); + + // Attenuation for light and to fade out shadow over distance + float fAtten = saturate( dot( attenuationFactors, float3( 1.0f, 1.0f/dist, 1.0f/distSquared ) ) ); + + // Shadowing and coloring terms +#if (defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)) + if ( bDoShadows ) + { + float flShadow = DoFlashlightShadow( FlashlightDepthSampler, RandomRotationSampler, vProjCoords, vScreenPos, nShadowLevel, vShadowTweaks, bAllowHighQuality, bForceSimple ); + float flAttenuated = lerp( saturate( flShadow ), 1.0f, vShadowTweaks.y ); // Blend between fully attenuated and not attenuated + flShadow = saturate( lerp( flAttenuated, flShadow, fAtten ) ); // Blend between shadow and above, according to light attenuation + flashlightColor *= flShadow; // Shadow term + } +#endif + + float3 diffuseLighting = fAtten; + + float flLDotWorldNormal; + if ( bHasNormal ) + { + flLDotWorldNormal = dot( L.xyz, worldNormal.xyz ); + } + else + { + flLDotWorldNormal = 1.0f; + } + +#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) + diffuseLighting *= saturate( flLDotWorldNormal + flFlashlightNoLambertValue ); // Lambertian term +#else + diffuseLighting *= saturate( flLDotWorldNormal ); // Lambertian (not Half-Lambert) term +#endif + + diffuseLighting *= flashlightColor; + diffuseLighting *= endFalloffFactor; + + return diffuseLighting; +} + +#endif //#ifndef COMMON_FLASHLIGHT_FXC_H_ diff --git a/materialsystem/stdshaders/common_fog_ps_forcevertexfog_fxc.h b/materialsystem/stdshaders/common_fog_ps_forcevertexfog_fxc.h new file mode 100644 index 00000000..529869ec --- /dev/null +++ b/materialsystem/stdshaders/common_fog_ps_forcevertexfog_fxc.h @@ -0,0 +1,23 @@ +// +// - This is the fog header to include for pixel shaders if the shader does support pixel-shader-blended vertex fog. +// + +// -- PIXELFOGTYPE is 0 for RANGE FOG, 1 for WATER/HEIGHT FOG -- +// DYNAMIC: "PIXELFOGTYPE" "0..0" [ = 0; ] //( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ) ? 1 : 0 ] + +// -- DOPIXELFOG is 1 if the material has $vertexfog 0, or if the material forces pixel fog by default (lightmappedgeneric for instance.) -- +// STATIC: "DOPIXELFOG" "0..0" [ = 0 ] + +#if ( PIXELFOGTYPE == 1 ) + // No matter what shader model we are, we do pixel fog for water and don't use fixed function hardware fog blending. + #undef DOPIXELFOG + #define DOPIXELFOG 1 +#endif + +#if defined( SHADER_MODEL_PS_2_0 ) && ( PIXELFOGTYPE == 0 ) + #define HARDWAREFOGBLEND 1 +#else + #define HARDWAREFOGBLEND 0 +#endif + +// FIXME! Will need to revisit this once we are doing water/height fog again. Needs to be pixel for in the water case. diff --git a/materialsystem/stdshaders/common_fog_ps_fxc.h b/materialsystem/stdshaders/common_fog_ps_fxc.h new file mode 100644 index 00000000..f65967a2 --- /dev/null +++ b/materialsystem/stdshaders/common_fog_ps_fxc.h @@ -0,0 +1,22 @@ +// +// - This is the fog header to include for pixel shaders if the shader doesn't support pixel-shader-blended vertex fog. +// + +// -- PIXELFOGTYPE is 0 for RANGE FOG, 1 for WATER/HEIGHT FOG -- +// DYNAMIC: "PIXELFOGTYPE" "0..1" [ = ( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ) ] + +#if ( PIXELFOGTYPE == 1 ) + // No matter what shader model we are, we do pixel fog for water. + #define DOPIXELFOG 1 + #define HARDWAREFOGBLEND 0 +#else + #if defined( SHADER_MODEL_PS_2_0 ) + // Never do pixel for for ps20 (unless we are in water) + #define DOPIXELFOG 0 + #define HARDWAREFOGBLEND 1 + #else + // Never do vertex fog for >ps20 + #define DOPIXELFOG 1 + #define HARDWAREFOGBLEND 0 + #endif +#endif diff --git a/materialsystem/stdshaders/common_fog_ps_supportsvertexfog_fxc.h b/materialsystem/stdshaders/common_fog_ps_supportsvertexfog_fxc.h new file mode 100644 index 00000000..37998f16 --- /dev/null +++ b/materialsystem/stdshaders/common_fog_ps_supportsvertexfog_fxc.h @@ -0,0 +1,25 @@ +// +// - This is the fog header to include for pixel shaders if the shader does support pixel-shader-blended vertex fog. +// + +// -- PIXELFOGTYPE is 0 for RANGE FOG, 1 for WATER/HEIGHT FOG -- +// DYNAMIC: "PIXELFOGTYPE" "0..1" [ = ( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ) ] + +// -- DOPIXELFOG is 1 if the material has $pixelfog 1, or if the material forces pixel fog by default (lightmappedgeneric for instance.) -- +// STATIC: "DOPIXELFOG" "0..0" [ = 0 ] [ps20] +// STATIC: "DOPIXELFOG" "0..1" [ = !IS_FLAG_SET( MATERIAL_VAR_VERTEXFOG ) ? 1 : 0 ] [ps20b] +// STATIC: "DOPIXELFOG" "0..1" [ = !IS_FLAG_SET( MATERIAL_VAR_VERTEXFOG ) ? 1 : 0 ] [ps30] + +#if ( PIXELFOGTYPE == 1 ) + // No matter what shader model we are, we do pixel fog for water and don't use fixed function hardware fog blending. + #undef DOPIXELFOG + #define DOPIXELFOG 1 +#endif + +#if defined( SHADER_MODEL_PS_2_0 ) && ( PIXELFOGTYPE == 0 ) + #define HARDWAREFOGBLEND 1 +#else + #define HARDWAREFOGBLEND 0 +#endif + +// FIXME! Will need to revisit this once we are doing water/height fog again. Needs to be pixel for in the water case. diff --git a/materialsystem/stdshaders/common_fog_vs_forcevertexfog_fxc.h b/materialsystem/stdshaders/common_fog_vs_forcevertexfog_fxc.h new file mode 100644 index 00000000..a7852278 --- /dev/null +++ b/materialsystem/stdshaders/common_fog_vs_forcevertexfog_fxc.h @@ -0,0 +1,25 @@ +// +// - This is the fog header to include for vertex shaders if the shader does support pixel-shader-blended vertex fog. +// + +// -- DOWATERFOG is 0 for RANGE FOG, 1 for WATER/HEIGHT FOG -- +// DYNAMIC: "DOWATERFOG" "0..0" [ = 0; ] // ( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ) ? 1 : 0 ] + +// -- DOPIXELFOG is 1 if the material has $pixelfog 1, or if the material forces pixel fog by default (lightmappedgeneric for instance.) -- +// FIXME! Will need to revisit this once we are doing water/height fog again. Needs to be pixel for in the water case. +// STATIC: "DOPIXELFOG" "0..0" [ = 0; ] //( g_pHardwareConfig->SupportsPixelShaders_2_b() && !IS_FLAG_SET( MATERIAL_VAR_VERTEXFOG ) ) ? 1 : 0 ] + +// STATIC: "HARDWAREFOGBLEND" "0..0" [XBOX] [ = 0 ] +// STATIC: "HARDWAREFOGBLEND" "0..1" [PC] [vs20] [ = !g_pHardwareConfig->SupportsPixelShaders_2_b() ] +// STATIC: "HARDWAREFOGBLEND" "0..0" [PC] [vs30] [ = 0 ] + +// Can't do fixed-function fog and pixelfog at the same time, but only if we aren't doing water since HARDWAREFOGBLEND and DOPIXELFOG get redefined below. +// SKIP: ( $DOWATERFOG == 0 ) && ( $DOPIXELFOG && $HARDWAREFOGBLEND ) + +#if DOWATERFOG == 1 + #undef HARDWAREFOGBLEND + #define HARDWAREFOGBLEND 0 + + #undef DOPIXELFOG + #define DOPIXELFOG 1 +#endif diff --git a/materialsystem/stdshaders/common_fog_vs_fxc.h b/materialsystem/stdshaders/common_fog_vs_fxc.h new file mode 100644 index 00000000..1b5f9f8f --- /dev/null +++ b/materialsystem/stdshaders/common_fog_vs_fxc.h @@ -0,0 +1,29 @@ +// +// - This is the fog header to include for vertex shaders if the shader doesn't support pixel-shader-blended vertex fog. +// + +// -- DOWATERFOG is 0 for RANGE FOG, 1 for WATER/HEIGHT FOG -- +// DYNAMIC: "DOWATERFOG" "0..1" [ = ( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ) ] + +// -- DOPIXELFOG is 1 if the material has $pixelfog 1, or if the material forces pixel fog by default (lightmappedgeneric for instance.) -- +// FIXME! Will need to revisit this once we are doing water/height fog again. Needs to be pixel for in the water case. +// STATIC: "DOPIXELFOG" "0..1" [ = g_pHardwareConfig->SupportsPixelShaders_2_b() ] + +// STATIC: "HARDWAREFOGBLEND" "0..0" [XBOX] [ = 0 ] +// STATIC: "HARDWAREFOGBLEND" "0..1" [PC] [vs20] [ = !g_pHardwareConfig->SupportsPixelShaders_2_b() ] +// STATIC: "HARDWAREFOGBLEND" "0..0" [PC] [vs30] [ = 0 ] + +// Can't do fixed-function fog and pixelfog at the same time, but only if we aren't doing water since HARDWAREFOGBLEND and DOPIXELFOG get redefined below. +// SKIP: ( $DOWATERFOG == 0 ) && ( $DOPIXELFOG && $HARDWAREFOGBLEND ) + +// Support either pixel fog or fixed-function fog, skip everything else. +// SKIP: ( $DOWATERFOG == 0 ) && ( $HARDWAREFOGBLEND == 0 ) && ( $DOPIXELFOG == 0 ) + +#if DOWATERFOG == 1 + #undef HARDWAREFOGBLEND + #define HARDWAREFOGBLEND 0 + + #undef DOPIXELFOG + #define DOPIXELFOG 1 +#endif + diff --git a/materialsystem/stdshaders/common_fog_vs_supportsvertexfog_fxc.h b/materialsystem/stdshaders/common_fog_vs_supportsvertexfog_fxc.h new file mode 100644 index 00000000..1c336040 --- /dev/null +++ b/materialsystem/stdshaders/common_fog_vs_supportsvertexfog_fxc.h @@ -0,0 +1,25 @@ +// +// - This is the fog header to include for vertex shaders if the shader does support pixel-shader-blended vertex fog. +// + +// -- DOWATERFOG is 0 for RANGE FOG, 1 for WATER/HEIGHT FOG -- +// DYNAMIC: "DOWATERFOG" "0..1" [ = ( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ) ] + +// -- DOPIXELFOG is 1 if the material has $pixelfog 1, or if the material forces pixel fog by default (lightmappedgeneric for instance.) -- +// FIXME! Will need to revisit this once we are doing water/height fog again. Needs to be pixel for in the water case. +// STATIC: "DOPIXELFOG" "0..1" [ = ( g_pHardwareConfig->SupportsPixelShaders_2_b() && !IS_FLAG_SET( MATERIAL_VAR_VERTEXFOG ) ) ? 1 : 0 ] + +// STATIC: "HARDWAREFOGBLEND" "0..0" [XBOX] [ = 0 ] +// STATIC: "HARDWAREFOGBLEND" "0..1" [PC] [vs20] [ = !g_pHardwareConfig->SupportsPixelShaders_2_b() ] +// STATIC: "HARDWAREFOGBLEND" "0..0" [PC] [vs30] [ = 0 ] + +// Can't do fixed-function fog and pixelfog at the same time, but only if we aren't doing water since HARDWAREFOGBLEND and DOPIXELFOG get redefined below. +// SKIP: ( $DOWATERFOG == 0 ) && ( $DOPIXELFOG && $HARDWAREFOGBLEND ) + +#if DOWATERFOG == 1 + #undef HARDWAREFOGBLEND + #define HARDWAREFOGBLEND 0 + + #undef DOPIXELFOG + #define DOPIXELFOG 1 +#endif diff --git a/materialsystem/stdshaders/common_fxc.h b/materialsystem/stdshaders/common_fxc.h new file mode 100644 index 00000000..9cf5ad92 --- /dev/null +++ b/materialsystem/stdshaders/common_fxc.h @@ -0,0 +1,375 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// +// +// Purpose: +// +// $NoKeywords: $ +// +//===========================================================================// +#ifndef COMMON_FXC_H_ +#define COMMON_FXC_H_ + +#include "common_pragmas.h" +#include "common_hlsl_cpp_consts.h" + +#ifdef NV3X +# define HALF half +# define HALF2 half2 +# define HALF3 half3 +# define HALF4 half4 +# define HALF3x3 half3x3 +# define HALF3x4 half3x4 +# define HALF4x3 half4x3 +# define HALF_CONSTANT( _constant ) ((HALF)_constant) +#else +# define HALF float +# define HALF2 float2 +# define HALF3 float3 +# define HALF4 float4 +# define HALF3x3 float3x3 +# define HALF3x4 float3x4 +# define HALF4x3 float4x3 +# define HALF_CONSTANT( _constant ) _constant +#endif + +#define FP16_MAX 65504.0f + +// This is where all common code for both vertex and pixel shaders. +#define OO_SQRT_3 0.57735025882720947f +static const HALF3 bumpBasis[3] = { + HALF3( 0.81649661064147949f, 0.0f, OO_SQRT_3 ), + HALF3( -0.40824833512306213f, 0.70710676908493042f, OO_SQRT_3 ), + HALF3( -0.40824821591377258f, -0.7071068286895752f, OO_SQRT_3 ) +}; +static const HALF3 bumpBasisTranspose[3] = { + HALF3( 0.81649661064147949f, -0.40824833512306213f, -0.40824833512306213f ), + HALF3( 0.0f, 0.70710676908493042f, -0.7071068286895752f ), + HALF3( OO_SQRT_3, OO_SQRT_3, OO_SQRT_3 ) +}; + +#if defined( _X360 ) +#define REVERSE_DEPTH_ON_X360 //uncomment to use D3DFMT_D24FS8 with an inverted depth viewport for better performance. Keep this in sync with the same named #define in public/shaderapi/shareddefs.h +//Note that the reversal happens in the viewport. So ONLY reading back from a depth texture should be affected. Projected math is unaffected. +#endif + +bool IsX360( void ) +{ + #if defined( _X360 ) + return true; + #else + return false; + #endif +} + +HALF3 CalcReflectionVectorNormalized( HALF3 normal, HALF3 eyeVector ) +{ + // FIXME: might be better of normalizing with a normalizing cube map and + // get rid of the dot( normal, normal ) + // compute reflection vector r = 2 * ((n dot v)/(n dot n)) n - v + return 2.0 * ( dot( normal, eyeVector ) / dot( normal, normal ) ) * normal - eyeVector; +} + +HALF3 CalcReflectionVectorUnnormalized( HALF3 normal, HALF3 eyeVector ) +{ + // FIXME: might be better of normalizing with a normalizing cube map and + // get rid of the dot( normal, normal ) + // compute reflection vector r = 2 * ((n dot v)/(n dot n)) n - v + // multiply all values through by N.N. uniformly scaling reflection vector won't affect result + // since it is used in a cubemap lookup + return (2.0*(dot( normal, eyeVector ))*normal) - (dot( normal, normal )*eyeVector); +} + +float3 HuePreservingColorClamp( float3 c ) +{ + // Get the max of all of the color components and a specified maximum amount + float maximum = max( max( c.x, c.y ), max( c.z, 1.0f ) ); + + return (c / maximum); +} + +HALF3 HuePreservingColorClamp( HALF3 c, HALF maxVal ) +{ + // Get the max of all of the color components and a specified maximum amount + float maximum = max( max( c.x, c.y ), max( c.z, maxVal ) ); + return (c * ( maxVal / maximum ) ); +} + +#if (AA_CLAMP==1) +HALF2 ComputeLightmapCoordinates( HALF4 Lightmap1and2Coord, HALF2 Lightmap3Coord ) +{ + HALF2 result = saturate(Lightmap1and2Coord.xy) * Lightmap1and2Coord.wz * 0.99; + result += Lightmap3Coord; + return result; +} + +void ComputeBumpedLightmapCoordinates( HALF4 Lightmap1and2Coord, HALF2 Lightmap3Coord, + out HALF2 bumpCoord1, + out HALF2 bumpCoord2, + out HALF2 bumpCoord3 ) +{ + HALF2 result = saturate(Lightmap1and2Coord.xy) * Lightmap1and2Coord.wz * 0.99; + result += Lightmap3Coord; + bumpCoord1 = result + HALF2(Lightmap1and2Coord.z, 0); + bumpCoord2 = result + 2*HALF2(Lightmap1and2Coord.z, 0); + bumpCoord3 = result + 3*HALF2(Lightmap1and2Coord.z, 0); +} +#else +HALF2 ComputeLightmapCoordinates( HALF4 Lightmap1and2Coord, HALF2 Lightmap3Coord ) +{ + return Lightmap1and2Coord.xy; +} + +void ComputeBumpedLightmapCoordinates( HALF4 Lightmap1and2Coord, HALF2 Lightmap3Coord, + out HALF2 bumpCoord1, + out HALF2 bumpCoord2, + out HALF2 bumpCoord3 ) +{ + bumpCoord1 = Lightmap1and2Coord.xy; + bumpCoord2 = Lightmap1and2Coord.wz; // reversed order!!! + bumpCoord3 = Lightmap3Coord.xy; +} +#endif + +// Versions of matrix multiply functions which force HLSL compiler to explictly use DOTs, +// not giving it the option of using MAD expansion. In a perfect world, the compiler would +// always pick the best strategy, and these shouldn't be needed.. but.. well.. umm.. +// +// lorenmcq + +float3 mul3x3(float3 v, float3x3 m) +{ +#if !defined( _X360 ) + return float3(dot(v, transpose(m)[0]), dot(v, transpose(m)[1]), dot(v, transpose(m)[2])); +#else + // xbox360 fxc.exe (new back end) borks with transposes, generates bad code + return mul( v, m ); +#endif +} + +float3 mul4x3(float4 v, float4x3 m) +{ +#if !defined( _X360 ) + return float3(dot(v, transpose(m)[0]), dot(v, transpose(m)[1]), dot(v, transpose(m)[2])); +#else + // xbox360 fxc.exe (new back end) borks with transposes, generates bad code + return mul( v, m ); +#endif +} + +float3 DecompressHDR( float4 input ) +{ + return input.rgb * input.a * MAX_HDR_OVERBRIGHT; +} + +float4 CompressHDR( float3 input ) +{ + // FIXME: want to use min so that we clamp to white, but what happens if we + // have an albedo component that's less than 1/MAX_HDR_OVERBRIGHT? + // float fMax = max( max( color.r, color.g ), color.b ); + float4 output; + float fMax = min( min( input.r, input.g ), input.b ); + if( fMax > 1.0f ) + { + float oofMax = 1.0f / fMax; + output.rgb = oofMax * input.rgb; + output.a = min( fMax / MAX_HDR_OVERBRIGHT, 1.0f ); + } + else + { + output.rgb = input.rgb; + output.a = 0.0f; + } + return output; +} + +// 2.2 gamma conversion routines +float LinearToGamma( const float f1linear ) +{ + return pow( f1linear, 1.0f / 2.2f ); +} + +float3 LinearToGamma( const float3 f3linear ) +{ + return pow( f3linear, 1.0f / 2.2f ); +} + +float4 LinearToGamma( const float4 f4linear ) +{ + return float4( pow( f4linear.xyz, 1.0f / 2.2f ), f4linear.w ); +} + +float GammaToLinear( const float gamma ) +{ + return pow( gamma, 2.2f ); +} + +float3 GammaToLinear( const float3 gamma ) +{ + return pow( gamma, 2.2f ); +} + +float4 GammaToLinear( const float4 gamma ) +{ + return float4( pow( gamma.xyz, 2.2f ), gamma.w ); +} + +// sRGB gamma conversion routines +float3 SrgbGammaToLinear( float3 vSrgbGammaColor ) +{ + // 15 asm instructions + float3 vLinearSegment = vSrgbGammaColor.rgb / 12.92f; + float3 vExpSegment = pow( ( ( vSrgbGammaColor.rgb / 1.055f ) + ( 0.055f / 1.055f ) ), 2.4f ); + + float3 vLinearColor = { ( vSrgbGammaColor.r <= 0.04045f ) ? vLinearSegment.r : vExpSegment.r, + ( vSrgbGammaColor.g <= 0.04045f ) ? vLinearSegment.g : vExpSegment.g, + ( vSrgbGammaColor.b <= 0.04045f ) ? vLinearSegment.b : vExpSegment.b }; + + return vLinearColor.rgb; +} + +float3 SrgbLinearToGamma( float3 vLinearColor ) +{ + // 15 asm instructions + float3 vLinearSegment = vLinearColor.rgb * 12.92f; + float3 vExpSegment = ( 1.055f * pow( vLinearColor.rgb, ( 1.0f / 2.4f ) ) ) - 0.055f; + + float3 vGammaColor = { ( vLinearColor.r <= 0.0031308f ) ? vLinearSegment.r : vExpSegment.r, + ( vLinearColor.g <= 0.0031308f ) ? vLinearSegment.g : vExpSegment.g, + ( vLinearColor.b <= 0.0031308f ) ? vLinearSegment.b : vExpSegment.b }; + + return vGammaColor.rgb; +} + +// These two functions use the XBox 360's exact piecewise linear algorithm +float3 X360GammaToLinear( float3 v360GammaColor ) +{ + // This code reduces the asm down to 11 instructions from the 63 instructions in the 360 XDK + float4 vTmpMul1 = { 1.0f, 2.0f, 4.0f, 8.0f }; + float4 vTmpAdd1 = { 0.0f, ( -64.0f / 255.0f ), ( -96.0f / 255.0f ), ( -192.0f / 255.0f ) }; + float4 vTmpAdd2 = { 0.0f, ( 64.0f / 255.0f ), ( 128.0f / 255.0f ), ( 513.0f / 255.0f ) }; + + float4 vRed = ( v360GammaColor.r * vTmpMul1.xyzw * 0.25f ) + ( ( ( vTmpAdd1.xyzw * vTmpMul1.xyzw ) + vTmpAdd2.xyzw ) * 0.25f ); + float4 vGreen = ( v360GammaColor.g * vTmpMul1.xyzw * 0.25f ) + ( ( ( vTmpAdd1.xyzw * vTmpMul1.xyzw ) + vTmpAdd2.xyzw ) * 0.25f ); + float4 vBlue = ( v360GammaColor.b * vTmpMul1.xyzw * 0.25f ) + ( ( ( vTmpAdd1.xyzw * vTmpMul1.xyzw ) + vTmpAdd2.xyzw ) * 0.25f ); + + float3 vMax1 = { max( vRed.x, vRed.y ), max( vGreen.x, vGreen.y ), max( vBlue.x, vBlue.y ) }; + float3 vMax2 = { max( vRed.z, vRed.w ), max( vGreen.z, vGreen.w ), max( vBlue.z, vBlue.w ) }; + float3 vLinearColor = max( vMax1.rgb, vMax2.rgb ); + + return vLinearColor.rgb; +} + +float X360LinearToGamma( float flLinearValue ) +{ + // This needs to be optimized + float fl360GammaValue; + + flLinearValue = saturate( flLinearValue ); + if ( flLinearValue < ( 128.0f / 1023.0f ) ) + { + if ( flLinearValue < ( 64.0f / 1023.0f ) ) + { + fl360GammaValue = flLinearValue * ( 1023.0f * ( 1.0f / 255.0f ) ); + } + else + { + fl360GammaValue = flLinearValue * ( ( 1023.0f / 2.0f ) * ( 1.0f / 255.0f ) ) + ( 32.0f / 255.0f ); + } + } + else + { + if ( flLinearValue < ( 512.0f / 1023.0f ) ) + { + fl360GammaValue = flLinearValue * ( ( 1023.0f / 4.0f ) * ( 1.0f / 255.0f ) ) + ( 64.0f / 255.0f ); + } + else + { + fl360GammaValue = flLinearValue * ( ( 1023.0f /8.0f ) * ( 1.0f / 255.0f ) ) + ( 128.0f /255.0f ); // 1.0 -> 1.0034313725490196078431372549016 + fl360GammaValue = saturate( fl360GammaValue ); + } + } + + fl360GammaValue = saturate( fl360GammaValue ); + return fl360GammaValue; +} + +float3 SrgbGammaTo360Gamma( float3 vSrgbGammaColor ) +{ + return X360LinearToGamma( SrgbGammaToLinear( vSrgbGammaColor.rgb ) ); +} + +// Function to do srgb read in shader code +#ifndef SHADER_SRGB_READ + #define SHADER_SRGB_READ 0 +#endif + +float4 tex2Dsrgb( sampler iSampler, float2 iUv ) +{ + // This function is named as a hint that the texture is meant to be read with + // an sRGB->linear conversion. We have to do this in shader code on the 360 sometimes. + #if ( SHADER_SRGB_READ == 0 ) + { + // Don't fake the srgb read in shader code + return tex2D( iSampler, iUv.xy ); + } + #else + { + if ( IsX360() ) + { + float4 vTextureValue = tex2D( iSampler, iUv.xy ); + vTextureValue.rgb = X360GammaToLinear( vTextureValue.rgb ); + return vTextureValue.rgba; + } + else + { + float4 vTextureValue = tex2D( iSampler, iUv.xy ); + vTextureValue.rgb = SrgbGammaToLinear( vTextureValue.rgb ); + return vTextureValue.rgba; + } + } + #endif +} + +// Tangent transform helper functions +float3 Vec3WorldToTangent( float3 iWorldVector, float3 iWorldNormal, float3 iWorldTangent, float3 iWorldBinormal ) +{ + float3 vTangentVector; + vTangentVector.x = dot( iWorldVector.xyz, iWorldTangent.xyz ); + vTangentVector.y = dot( iWorldVector.xyz, iWorldBinormal.xyz ); + vTangentVector.z = dot( iWorldVector.xyz, iWorldNormal.xyz ); + return vTangentVector.xyz; // Return without normalizing +} + +float3 Vec3WorldToTangentNormalized( float3 iWorldVector, float3 iWorldNormal, float3 iWorldTangent, float3 iWorldBinormal ) +{ + return normalize( Vec3WorldToTangent( iWorldVector, iWorldNormal, iWorldTangent, iWorldBinormal ) ); +} + +float3 Vec3TangentToWorld( float3 iTangentVector, float3 iWorldNormal, float3 iWorldTangent, float3 iWorldBinormal ) +{ + float3 vWorldVector; + vWorldVector.xyz = iTangentVector.x * iWorldTangent.xyz; + vWorldVector.xyz += iTangentVector.y * iWorldBinormal.xyz; + vWorldVector.xyz += iTangentVector.z * iWorldNormal.xyz; + return vWorldVector.xyz; // Return without normalizing +} + +float3 Vec3TangentToWorldNormalized( float3 iTangentVector, float3 iWorldNormal, float3 iWorldTangent, float3 iWorldBinormal ) +{ + return normalize( Vec3TangentToWorld( iTangentVector, iWorldNormal, iWorldTangent, iWorldBinormal ) ); +} + +// returns 1.0f for no fog, 0.0f for fully fogged +float CalcRangeFogFactorFixedFunction( float3 worldPos, float3 eyePos, float flFogMaxDensity, float flFogEndOverRange, float flFogOORange ) +{ + float dist = distance( eyePos.xyz, worldPos.xyz ); + return max( flFogMaxDensity, ( -dist * flFogOORange ) + flFogEndOverRange ); +} + +// returns 0.0f for no fog, 1.0f for fully fogged which is opposite of what fixed function fog expects so that we don't have to do a "1-x" in the pixel shader. +float CalcRangeFogFactorNonFixedFunction( float3 worldPos, float3 eyePos, float flFogMaxDensity, float flFogEndOverRange, float flFogOORange ) +{ + float dist = distance( eyePos.xyz, worldPos.xyz ); + return min( flFogMaxDensity, saturate( flFogEndOverRange + ( dist * flFogOORange ) ) ); +} + +#endif //#ifndef COMMON_FXC_H_ diff --git a/materialsystem/stdshaders/common_hlsl_cpp_consts.h b/materialsystem/stdshaders/common_hlsl_cpp_consts.h new file mode 100644 index 00000000..8e56747d --- /dev/null +++ b/materialsystem/stdshaders/common_hlsl_cpp_consts.h @@ -0,0 +1,27 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// +// +// Purpose: +// +// $NoKeywords: $ +// +//===========================================================================// +#ifndef COMMON_HLSL_CONSTS_H_ +#define COMMON_HLSL_CONSTS_H_ + +#ifdef NV3X + #define PSHADER_VECT_SCALE 20.0 + #define VSHADER_VECT_SCALE (1.0 / (PSHADER_VECT_SCALE) ) +#else + #define PSHADER_VECT_SCALE 1.0 + #define VSHADER_VECT_SCALE 1.0 +#endif + +// GR - HDR luminance maps to 0..n range +// IMPORTANT: Keep the same value as in materialsystem_global.h +// HDRFIXME: Make this a pixel shader constant? +#define MAX_HDR_OVERBRIGHT 16.0f + +#define LINEAR_FOG_COLOR 29 +#define TONE_MAPPING_SCALE_PSH_CONSTANT 30 + +#endif //#ifndef COMMON_HLSL_CONSTS_H_ diff --git a/materialsystem/stdshaders/common_lightmappedgeneric_fxc.h b/materialsystem/stdshaders/common_lightmappedgeneric_fxc.h new file mode 100644 index 00000000..a1c6986f --- /dev/null +++ b/materialsystem/stdshaders/common_lightmappedgeneric_fxc.h @@ -0,0 +1,282 @@ +#if defined( _X360 ) + +void GetBaseTextureAndNormal( sampler base, sampler base2, sampler bump, bool bBase2, bool bBump, + float3 coords, float2 bumpcoords, + float3 vWeights, + out float4 vResultBase, out float4 vResultBase2, out float4 vResultBump ) +{ + vResultBase = 0; + vResultBase2 = 0; + vResultBump = 0; + + if ( !bBump ) + { + vResultBump = float4(0, 0, 1, 1); + } + +#if SEAMLESS + + vWeights = max( vWeights - 0.3, 0 ); + vWeights *= 1.0f / dot( vWeights, float3(1,1,1) ); + + [branch] + if (vWeights.x > 0) + { + vResultBase += vWeights.x * tex2D( base, coords.zy ); + + if ( bBase2 ) + { + vResultBase2 += vWeights.x * tex2D( base2, coords.zy ); + } + + if ( bBump ) + { + vResultBump += vWeights.x * tex2D( bump, coords.zy ); + } + } + + [branch] + if (vWeights.y > 0) + { + vResultBase += vWeights.y * tex2D( base, coords.xz ); + + if ( bBase2 ) + { + vResultBase2 += vWeights.y * tex2D( base2, coords.xz ); + } + if ( bBump ) + { + vResultBump += vWeights.y * tex2D( bump, coords.xz ); + } + } + + [branch] + if (vWeights.z > 0) + { + vResultBase += vWeights.z * tex2D( base, coords.xy ); + if ( bBase2 ) + { + vResultBase2 += vWeights.z * tex2D( base2, coords.xy ); + } + + if ( bBump ) + { + vResultBump += vWeights.z * tex2D( bump, coords.xy ); + } + } + + #if ( SHADER_SRGB_READ == 1 ) + // Do this after the blending to save shader ops + vResultBase.rgb = X360GammaToLinear( vResultBase.rgb ); + vResultBase2.rgb = X360GammaToLinear( vResultBase2.rgb ); + #endif + +#else // not seamless + + vResultBase = tex2Dsrgb( base, coords.xy ); + + if ( bBase2 ) + { + vResultBase2 = tex2Dsrgb( base2, coords.xy ); + } + + if ( bBump ) + { + vResultBump = tex2D( bump, bumpcoords.xy ); + } + +#endif +} + +#else // PC + +void GetBaseTextureAndNormal( sampler base, sampler base2, sampler bump, bool bBase2, bool bBump, + float3 coords, float2 bumpcoords, float3 vWeights, + out float4 vResultBase, out float4 vResultBase2, out float4 vResultBump ) +{ + vResultBase = 0; + vResultBase2 = 0; + vResultBump = 0; + + if ( !bBump ) + { + vResultBump = float4(0, 0, 1, 1); + } + +#if SEAMLESS + + vResultBase += vWeights.x * tex2D( base, coords.zy ); + if ( bBase2 ) + { + vResultBase2 += vWeights.x * tex2D( base2, coords.zy ); + } + if ( bBump ) + { + vResultBump += vWeights.x * tex2D( bump, coords.zy ); + } + + vResultBase += vWeights.y * tex2D( base, coords.xz ); + if ( bBase2 ) + { + vResultBase2 += vWeights.y * tex2D( base2, coords.xz ); + } + if ( bBump ) + { + vResultBump += vWeights.y * tex2D( bump, coords.xz ); + } + + vResultBase += vWeights.z * tex2D( base, coords.xy ); + if ( bBase2 ) + { + vResultBase2 += vWeights.z * tex2D( base2, coords.xy ); + } + if ( bBump ) + { + vResultBump += vWeights.z * tex2D( bump, coords.xy ); + } + +#else // not seamless + + vResultBase = tex2D( base, coords.xy ); + if ( bBase2 ) + { + vResultBase2 = tex2D( base2, coords.xy ); + } + if ( bBump ) + { + vResultBump = tex2D( bump, bumpcoords.xy ); + } +#endif + +} + +#endif + + +float3 LightMapSample( sampler LightmapSampler, float2 vTexCoord ) +{ + #if ( !defined( _X360 ) || !defined( USE_32BIT_LIGHTMAPS_ON_360 ) ) + { + float3 sample = tex2D( LightmapSampler, vTexCoord ); + + return sample; + } + #else + { + #if 0 //1 for cheap sampling, 0 for accurate scaling from the individual samples + { + float4 sample = tex2D( LightmapSampler, vTexCoord ); + + return sample.rgb * sample.a; + } + #else + { + float4 Weights; + float4 samples_0; //no arrays allowed in inline assembly + float4 samples_1; + float4 samples_2; + float4 samples_3; + + asm { + tfetch2D samples_0, vTexCoord.xy, LightmapSampler, OffsetX = -0.5, OffsetY = -0.5, MinFilter=point, MagFilter=point, MipFilter=keep, UseComputedLOD=false + tfetch2D samples_1, vTexCoord.xy, LightmapSampler, OffsetX = 0.5, OffsetY = -0.5, MinFilter=point, MagFilter=point, MipFilter=keep, UseComputedLOD=false + tfetch2D samples_2, vTexCoord.xy, LightmapSampler, OffsetX = -0.5, OffsetY = 0.5, MinFilter=point, MagFilter=point, MipFilter=keep, UseComputedLOD=false + tfetch2D samples_3, vTexCoord.xy, LightmapSampler, OffsetX = 0.5, OffsetY = 0.5, MinFilter=point, MagFilter=point, MipFilter=keep, UseComputedLOD=false + + getWeights2D Weights, vTexCoord.xy, LightmapSampler + }; + + Weights = float4( (1-Weights.x)*(1-Weights.y), Weights.x*(1-Weights.y), (1-Weights.x)*Weights.y, Weights.x*Weights.y ); + + float3 result; + result.rgb = samples_0.rgb * (samples_0.a * Weights.x); + result.rgb += samples_1.rgb * (samples_1.a * Weights.y); + result.rgb += samples_2.rgb * (samples_2.a * Weights.z); + result.rgb += samples_3.rgb * (samples_3.a * Weights.w); + + return result; + } + #endif + } + #endif +} + +#ifdef PIXELSHADER +#define VS_OUTPUT PS_INPUT +#endif + +struct VS_OUTPUT +{ +#ifndef PIXELSHADER + float4 projPos : POSITION; +# if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + float fog : FOG; +# endif +#endif +#if SEAMLESS + #if HARDWAREFOGBLEND || DOPIXELFOG + float3 SeamlessTexCoord_fogFactorW : TEXCOORD0; // zy xz + #else + float4 SeamlessTexCoord_fogFactorW : TEXCOORD0; // zy xz + #endif +#else + #if HARDWAREFOGBLEND || DOPIXELFOG + float2 baseTexCoord_fogFactorZ : TEXCOORD0; + #else + float3 baseTexCoord_fogFactorZ : TEXCOORD0; + #endif + + // detail textures and bumpmaps are mutually exclusive so that we have enough texcoords. +#endif + float4 detailOrBumpAndEnvmapMaskTexCoord : TEXCOORD1; // envmap mask + + // CENTROID: TEXCOORD2 +#if defined( _X360 ) + float4 lightmapTexCoord1And2 : TEXCOORD2_centroid; +#else + float4 lightmapTexCoord1And2 : TEXCOORD2; +#endif + + // CENTROID: TEXCOORD3 +#if defined( _X360 ) + float4 lightmapTexCoord3 : TEXCOORD3_centroid; +#else + float4 lightmapTexCoord3 : TEXCOORD3; +#endif + + float4 worldPos_projPosZ : TEXCOORD4; + float3x3 tangentSpaceTranspose : TEXCOORD5; + // tangentSpaceTranspose : TEXCOORD6 + // tangentSpaceTranspose : TEXCOORD7 + float4 vertexColor : COLOR0; + float vertexBlendX : COLOR1; + + // Extra iterators on 360, used in flashlight combo +#if defined( _X360 ) && FLASHLIGHT + float4 flashlightSpacePos : TEXCOORD8; + float4 vProjPos : TEXCOORD9; +#endif +}; + +#define DETAILCOORDS detailOrBumpAndEnvmapMaskTexCoord.xy +#define DETAILORBUMPCOORDS DETAILCOORDS +#define ENVMAPMASKCOORDS detailOrBumpAndEnvmapMaskTexCoord.wz + +#if DETAILTEXTURE && BUMPMAP && !SELFILLUM && !FANCY_BLENDING + #define BUMPCOORDS lightmapTexCoord3.wz +#elif DETAILTEXTURE + #define BUMPCOORDS baseTexCoord_fogFactorZ.xy +#else + // This is the SEAMLESS case too since we skip SEAMLESS && DETAILTEXTURE + #define BUMPCOORDS detailOrBumpAndEnvmapMaskTexCoord.xy +#endif + +#if FANCY_BLENDING + #define FANCYBLENDMASKCOORDS lightmapTexCoord3.wz +#endif + +#if SEAMLESS + // don't use BASETEXCOORD in the SEAMLESS case +#else + #define BASETEXCOORD baseTexCoord_fogFactorZ.xy +#endif diff --git a/materialsystem/stdshaders/common_pragmas.h b/materialsystem/stdshaders/common_pragmas.h new file mode 100644 index 00000000..4a7311c7 --- /dev/null +++ b/materialsystem/stdshaders/common_pragmas.h @@ -0,0 +1,38 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// +// +// Purpose: Common shader compiler pragmas +// +// $NoKeywords: $ +// +//===========================================================================// +#ifndef COMMON_PRAGMAS_H_ +#define COMMON_PRAGMAS_H_ + +// +// Validated shader models: +// +// SHADER_MODEL_VS_1_1 +// SHADER_MODEL_VS_2_0 +// SHADER_MODEL_VS_3_0 +// +// SHADER_MODEL_PS_1_1 +// SHADER_MODEL_PS_1_4 +// SHADER_MODEL_PS_2_0 +// SHADER_MODEL_PS_2_B +// SHADER_MODEL_PS_3_0 +// +// +// +// Platforms: +// +// PC +// _X360 +// + +// Special pragmas silencing common warnings +#pragma warning ( disable : 3557 ) // warning X3557: Loop only executes for N iteration(s), forcing loop to unroll +#pragma warning ( disable : 3595 ) // warning X3595: Microcode Compiler possible performance issue: pixel shader input semantic ___ is unused +#pragma warning ( disable : 3596 ) // warning X3596: Microcode Compiler possible performance issue: pixel shader input semantic ___ is unused +#pragma warning ( disable : 4702 ) // warning X4702: complement opportunity missed because input result WAS clamped from 0 to 1 + +#endif //#ifndef COMMON_PRAGMAS_H_ diff --git a/materialsystem/stdshaders/common_ps_fxc.h b/materialsystem/stdshaders/common_ps_fxc.h new file mode 100644 index 00000000..6925d082 --- /dev/null +++ b/materialsystem/stdshaders/common_ps_fxc.h @@ -0,0 +1,805 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// +// +// Purpose: Common pixel shader code +// +// $NoKeywords: $ +// +//===========================================================================// + +#ifndef COMMON_PS_FXC_H_ +#define COMMON_PS_FXC_H_ + +#include "common_fxc.h" + +// Put global skip commands here. . make sure and check that the appropriate vars are defined +// so these aren't used on the wrong shaders! + +// -------------------------------------------------------------------------------- +// We don't ever write water fog to dest alpha if we aren't doing water fog. +// SKIP: defined $PIXELFOGTYPE && defined $WRITEWATERFOGTODESTALPHA && ( $PIXELFOGTYPE != 1 ) && $WRITEWATERFOGTODESTALPHA +// -------------------------------------------------------------------------------- +// Ditch all fastpath attempts if we are doing LIGHTING_PREVIEW. +// SKIP: defined $LIGHTING_PREVIEW && defined $FASTPATHENVMAPTINT && $LIGHTING_PREVIEW && $FASTPATHENVMAPTINT +// SKIP: defined $LIGHTING_PREVIEW && defined $FASTPATHENVMAPCONTRAST && $LIGHTING_PREVIEW && $FASTPATHENVMAPCONTRAST +// SKIP: defined $LIGHTING_PREVIEW && defined $FASTPATH && $LIGHTING_PREVIEW && $FASTPATH +// -------------------------------------------------------------------------------- +// Ditch flashlight depth when flashlight is disabled +// SKIP: ($FLASHLIGHT || $FLASHLIGHTSHADOWS) && $LIGHTING_PREVIEW +// -------------------------------------------------------------------------------- + +// System defined pixel shader constants + +#if defined( _X360 ) +const bool g_bHighQualityShadows : register( b0 ); +#endif + +// NOTE: w == 1.0f / (Dest alpha compressed depth range). +const float4 g_LinearFogColor : register( c29 ); +#define OO_DESTALPHA_DEPTH_RANGE (g_LinearFogColor.w) + +// Linear and gamma light scale values +const float4 cLightScale : register( c30 ); +#define LINEAR_LIGHT_SCALE (cLightScale.x) +#define LIGHT_MAP_SCALE (cLightScale.y) +#define ENV_MAP_SCALE (cLightScale.z) +#define GAMMA_LIGHT_SCALE (cLightScale.w) + +// Flashlight constants +#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) + const float4 cFlashlightColor : register( c28 ); + const float4 cFlashlightScreenScale : register( c31 ); // .zw are currently unused + #define flFlashlightNoLambertValue cFlashlightColor.w // This is either 0.0 or 2.0 +#endif + +// 3.0 standard constants +#if defined( SHADER_MODEL_PS_3_0 ) +const float4 cScreenSize : register( c32 ); // Used for converting VPOS to useful 2D coordinates +#endif + +#define HDR_INPUT_MAP_SCALE 16.0f + +#define TONEMAP_SCALE_NONE 0 +#define TONEMAP_SCALE_LINEAR 1 +#define TONEMAP_SCALE_GAMMA 2 + +#define PIXEL_FOG_TYPE_NONE -1 //MATERIAL_FOG_NONE is handled by PIXEL_FOG_TYPE_RANGE, this is for explicitly disabling fog in the shader +#define PIXEL_FOG_TYPE_RANGE 0 //range+none packed together in ps2b. Simply none in ps20 (instruction limits) +#define PIXEL_FOG_TYPE_HEIGHT 1 + +// If you change these, make the corresponding change in hardwareconfig.cpp +#define NVIDIA_PCF_POISSON 0 +#define ATI_NOPCF 1 +#define ATI_NO_PCF_FETCH4 2 + +struct LPREVIEW_PS_OUT +{ + float4 color : COLOR0; + float4 normal : COLOR1; + float4 position : COLOR2; + float4 flags : COLOR3; +}; + +/* +// unused +HALF Luminance( HALF3 color ) +{ + return dot( color, HALF3( HALF_CONSTANT(0.30f), HALF_CONSTANT(0.59f), HALF_CONSTANT(0.11f) ) ); +} +*/ + +/* +// unused +HALF LuminanceScaled( HALF3 color ) +{ + return dot( color, HALF3( HALF_CONSTANT(0.30f) / MAX_HDR_OVERBRIGHT, HALF_CONSTANT(0.59f) / MAX_HDR_OVERBRIGHT, HALF_CONSTANT(0.11f) / MAX_HDR_OVERBRIGHT ) ); +} +*/ + +/* +// unused +HALF AvgColor( HALF3 color ) +{ + return dot( color, HALF3( HALF_CONSTANT(0.33333f), HALF_CONSTANT(0.33333f), HALF_CONSTANT(0.33333f) ) ); +} +*/ + +/* +// unused +HALF4 DiffuseBump( sampler lightmapSampler, + float2 lightmapTexCoord1, + float2 lightmapTexCoord2, + float2 lightmapTexCoord3, + HALF3 normal ) +{ + HALF3 lightmapColor1 = tex2D( lightmapSampler, lightmapTexCoord1 ); + HALF3 lightmapColor2 = tex2D( lightmapSampler, lightmapTexCoord2 ); + HALF3 lightmapColor3 = tex2D( lightmapSampler, lightmapTexCoord3 ); + + HALF3 diffuseLighting; + diffuseLighting = saturate( dot( normal, bumpBasis[0] ) ) * lightmapColor1 + + saturate( dot( normal, bumpBasis[1] ) ) * lightmapColor2 + + saturate( dot( normal, bumpBasis[2] ) ) * lightmapColor3; + + return HALF4( diffuseLighting, LuminanceScaled( diffuseLighting ) ); +} +*/ + + +/* +// unused +HALF Fresnel( HALF3 normal, + HALF3 eye, + HALF2 scaleBias ) +{ + HALF fresnel = HALF_CONSTANT(1.0f) - dot( normal, eye ); + fresnel = pow( fresnel, HALF_CONSTANT(5.0f) ); + + return fresnel * scaleBias.x + scaleBias.y; +} +*/ + +/* +// unused +HALF4 GetNormal( sampler normalSampler, + float2 normalTexCoord ) +{ + HALF4 normal = tex2D( normalSampler, normalTexCoord ); + normal.rgb = HALF_CONSTANT(2.0f) * normal.rgb - HALF_CONSTANT(1.0f); + + return normal; +} +*/ + +// Needs to match NormalDecodeMode_t enum in imaterialsystem.h +#define NORM_DECODE_NONE 0 +#define NORM_DECODE_ATI2N 1 +#define NORM_DECODE_ATI2N_ALPHA 2 + +float4 DecompressNormal( sampler NormalSampler, float2 tc, int nDecompressionMode, sampler AlphaSampler ) +{ + float4 normalTexel = tex2D( NormalSampler, tc ); + float4 result; + + if ( nDecompressionMode == NORM_DECODE_NONE ) + { + result = float4(normalTexel.xyz * 2.0f - 1.0f, normalTexel.a ); + } + else if ( nDecompressionMode == NORM_DECODE_ATI2N ) + { + result.xy = normalTexel.xy * 2.0f - 1.0f; + result.z = sqrt( 1.0f - dot(result.xy, result.xy) ); + result.a = 1.0f; + } + else // ATI2N plus ATI1N for alpha + { + result.xy = normalTexel.xy * 2.0f - 1.0f; + result.z = sqrt( 1.0f - dot(result.xy, result.xy) ); + result.a = tex2D( AlphaSampler, tc ).x; // Note that this comes in on the X channel + } + + return result; +} + + +float4 DecompressNormal( sampler NormalSampler, float2 tc, int nDecompressionMode ) +{ + return DecompressNormal( NormalSampler, tc, nDecompressionMode, NormalSampler ); +} + + +HALF3 NormalizeWithCubemap( sampler normalizeSampler, HALF3 input ) +{ +// return texCUBE( normalizeSampler, input ) * 2.0f - 1.0f; + return texCUBE( normalizeSampler, input ); +} + +/* +HALF4 EnvReflect( sampler envmapSampler, + sampler normalizeSampler, + HALF3 normal, + float3 eye, + HALF2 fresnelScaleBias ) +{ + HALF3 normEye = NormalizeWithCubemap( normalizeSampler, eye ); + HALF fresnel = Fresnel( normal, normEye, fresnelScaleBias ); + HALF3 reflect = CalcReflectionVectorUnnormalized( normal, eye ); + return texCUBE( envmapSampler, reflect ); +} +*/ + +#if defined( SHADER_MODEL_PS_3_0 ) +// cScreenSize.xy contains { 1.0/w, 1.0/h } +// cScreenSize.zw contains { 0.5/w, 0.5/h } +float2 ComputeScreenPos( float2 vPos ) +{ + return vPos * cScreenSize.xy + cScreenSize.zw; +} +#endif + + +// Vectorized smoothstep for doing three smoothsteps at once. Used by uberlight +float3 smoothstep3( float3 edge0, float3 edge1, float3 OneOverWidth, float3 x ) +{ + x = saturate((x - edge0) * OneOverWidth); // Scale, bias and saturate x to the range of zero to one + return x*x*(3-2*x); // Evaluate polynomial +} + + +float CalcWaterFogAlpha( const float flWaterZ, const float flEyePosZ, const float flWorldPosZ, const float flProjPosZ, const float flFogOORange ) +{ +#if 0 + // This version is what you use if you want a line-integral throught he water for water fog. +// float flDepthFromWater = flWaterZ - flWorldPosZ + 2.0f; // hackity hack . .this is for the DF_FUDGE_UP in view_scene.cpp + float flDepthFromWater = flWaterZ - flWorldPosZ; + + // if flDepthFromWater < 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 + // We'll do this with the saturate at the end instead. +// flDepthFromWater = max( 0.0f, flDepthFromWater ); + + // Calculate the ratio of water fog to regular fog (ie. how much of the distance from the viewer + // to the vert is actually underwater. + float flDepthFromEye = flEyePosZ - flWorldPosZ; + float f = (flDepthFromWater / flDepthFromEye) * flProjPosZ; + + // $tmp.w is now the distance that we see through water. + return saturate( f * flFogOORange ); +#else + // This version is simply using the depth of the water to determine fog factor, + // which is cheaper than doing the line integral and also fixes some problems with having + // a hard line on the shore when the water surface is viewed tangentially. + // hackity hack . .the 2.0 is for the DF_FUDGE_UP in view_scene.cpp + return saturate( ( flWaterZ - flWorldPosZ - 2.0f ) * flFogOORange ); +#endif +} + +float CalcPixelFogFactor( int iPIXELFOGTYPE, const float4 fogParams, const float3 vEyePos, const float3 vWorldPos, const float flProjPosZ ) +{ + float retVal; + if ( iPIXELFOGTYPE == PIXEL_FOG_TYPE_NONE ) + { + retVal = 0.0f; + } + if ( iPIXELFOGTYPE == PIXEL_FOG_TYPE_RANGE ) //range fog, or no fog depending on fog parameters + { + // This is one only path that we go down for L4D. + float flFogMaxDensity = fogParams.z; + float flFogEndOverRange = fogParams.x; + float flFogOORange = fogParams.w; + retVal = CalcRangeFogFactorNonFixedFunction( vWorldPos, vEyePos, flFogMaxDensity, flFogEndOverRange, flFogOORange ); + } + else if ( iPIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT ) //height fog + { + retVal = CalcWaterFogAlpha( fogParams.y, vEyePos.z, vWorldPos.z, flProjPosZ, fogParams.w ); + } + + return retVal; +} + +float CalcPixelFogFactorSupportsVertexFog( int iPIXELFOGTYPE, const float4 fogParams, const float3 vEyePos, const float3 vWorldPos, const float flProjPosZ, const float flVertexFogFactor ) +{ + #if ( DOPIXELFOG ) + { + return CalcPixelFogFactor( iPIXELFOGTYPE, fogParams, vEyePos, vWorldPos, flProjPosZ ); + } + #else + { + return flVertexFogFactor; + } + #endif +} + +//g_FogParams not defined by default, but this is the same layout for every shader that does define it +#define g_FogEndOverRange g_FogParams.x +#define g_WaterZ g_FogParams.y +#define g_FogMaxDensity g_FogParams.z +#define g_FogOORange g_FogParams.w +float3 BlendPixelFog( const float3 vShaderColor, float pixelFogFactor, const float3 vFogColor, const int iPIXELFOGTYPE ) +{ + if( iPIXELFOGTYPE == PIXEL_FOG_TYPE_RANGE ) //either range fog or no fog depending on fog parameters and whether this is ps20 or ps2b + { + #if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) //Minimum requirement of ps2b + return lerp( vShaderColor.rgb, vFogColor.rgb, pixelFogFactor * pixelFogFactor ); //squaring the factor will get the middle range mixing closer to hardware fog + #else + return vShaderColor; + #endif + } + else if( iPIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT ) + { + return lerp( vShaderColor.rgb, vFogColor.rgb, pixelFogFactor ); + } + else if( iPIXELFOGTYPE == PIXEL_FOG_TYPE_NONE ) + { + return vShaderColor; + } +} + + +float SoftParticleDepth( float flDepth ) +{ + return flDepth * OO_DESTALPHA_DEPTH_RANGE; +} + + +float DepthToDestAlpha( const float flProjZ ) +{ + #if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) //Minimum requirement of ps2b + return SoftParticleDepth( flProjZ ); + #else + return 1.0f; + #endif +} + +float4 FinalOutput( const float4 vShaderColor, float pixelFogFactor, const int iPIXELFOGTYPE, const int iTONEMAP_SCALE_TYPE, const bool bWriteDepthToDestAlpha = false, const float flProjZ = 1.0f ) +{ + float4 result; + if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_LINEAR ) + { + result.rgb = vShaderColor.rgb * LINEAR_LIGHT_SCALE; + } + else if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_GAMMA ) + { + result.rgb = vShaderColor.rgb * GAMMA_LIGHT_SCALE; + } + else if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_NONE ) + { + result.rgb = vShaderColor.rgb; + } + + if( bWriteDepthToDestAlpha ) + result.a = DepthToDestAlpha( flProjZ ); + else + result.a = vShaderColor.a; + + if ( iPIXELFOGTYPE == PIXEL_FOG_TYPE_RANGE ) + { + result.rgb = BlendPixelFog( result.rgb, pixelFogFactor, g_LinearFogColor.rgb, iPIXELFOGTYPE ); + } + + + return result; +} + +LPREVIEW_PS_OUT FinalOutput( const LPREVIEW_PS_OUT vShaderColor, float pixelFogFactor, const int iPIXELFOGTYPE, const int iTONEMAP_SCALE_TYPE ) +{ + LPREVIEW_PS_OUT result; + result.color = FinalOutput( vShaderColor.color, pixelFogFactor, iPIXELFOGTYPE, iTONEMAP_SCALE_TYPE ); + result.normal.rgb = vShaderColor.normal.rgb; + result.normal.a = vShaderColor.normal.a; + + result.position.rgb = vShaderColor.position.rgb; + result.position.a = vShaderColor.position.a; + + result.flags.rgb = vShaderColor.flags.rgb; + result.flags.a = vShaderColor.flags.a; + + return result; +} + + +float RemapValClamped( float val, float A, float B, float C, float D) +{ + float cVal = (val - A) / (B - A); + cVal = saturate( cVal ); + + return C + (D - C) * cVal; +} + + +//===================================================================================// +// This is based on Natasha Tatarchuk's Parallax Occlusion Mapping (ATI) +//===================================================================================// +// INPUT: +// inTexCoord: +// the texcoord for the height/displacement map before parallaxing +// +// vParallax: +// Compute initial parallax displacement direction: +// float2 vParallaxDirection = normalize( vViewTS.xy ); +// float fLength = length( vViewTS ); +// float fParallaxLength = sqrt( fLength * fLength - vViewTS.z * vViewTS.z ) / vViewTS.z; +// Out.vParallax = vParallaxDirection * fParallaxLength * fProjectedBumpHeight; +// +// vNormal: +// tangent space normal +// +// vViewW: +// float3 vViewW = /*normalize*/(mul( matViewInverse, float4( 0, 0, 0, 1)) - inPosition ); +// +// OUTPUT: +// the new texcoord after parallaxing +float2 CalcParallaxedTexCoord( float2 inTexCoord, float2 vParallax, float3 vNormal, + float3 vViewW, sampler HeightMapSampler ) +{ + const int nMinSamples = 8; + const int nMaxSamples = 50; + + // Normalize the incoming view vector to avoid artifacts: +// vView = normalize( vView ); + vViewW = normalize( vViewW ); +// vLight = normalize( vLight ); + + // Change the number of samples per ray depending on the viewing angle + // for the surface. Oblique angles require smaller step sizes to achieve + // more accurate precision + int nNumSteps = (int) lerp( nMaxSamples, nMinSamples, dot( vViewW, vNormal ) ); + + float4 cResultColor = float4( 0, 0, 0, 1 ); + + //===============================================// + // Parallax occlusion mapping offset computation // + //===============================================// + float fCurrHeight = 0.0; + float fStepSize = 1.0 / (float) nNumSteps; + float fPrevHeight = 1.0; + float fNextHeight = 0.0; + + int nStepIndex = 0; +// bool bCondition = true; + + float2 dx = ddx( inTexCoord ); + float2 dy = ddy( inTexCoord ); + + float2 vTexOffsetPerStep = fStepSize * vParallax; + + float2 vTexCurrentOffset = inTexCoord; + float fCurrentBound = 1.0; + + float x = 0; + float y = 0; + float xh = 0; + float yh = 0; + + float2 texOffset2 = 0; + + bool bCondition = true; + while ( bCondition == true && nStepIndex < nNumSteps ) + { + vTexCurrentOffset -= vTexOffsetPerStep; + + fCurrHeight = tex2Dgrad( HeightMapSampler, vTexCurrentOffset, dx, dy ).r; + + fCurrentBound -= fStepSize; + + if ( fCurrHeight > fCurrentBound ) + { + x = fCurrentBound; + y = fCurrentBound + fStepSize; + xh = fCurrHeight; + yh = fPrevHeight; + + texOffset2 = vTexCurrentOffset - vTexOffsetPerStep; + + bCondition = false; + } + else + { + nStepIndex++; + fPrevHeight = fCurrHeight; + } + + } // End of while ( bCondition == true && nStepIndex > -1 )#else + + fCurrentBound -= fStepSize; + + float fParallaxAmount; + float numerator = (x * (y - yh) - y * (x - xh)); + float denomenator = ((y - yh) - (x - xh)); + // avoid NaN generation + if( ( numerator == 0.0f ) && ( denomenator == 0.0f ) ) + { + fParallaxAmount = 0.0f; + } + else + { + fParallaxAmount = numerator / denomenator; + } + + float2 vParallaxOffset = vParallax * (1 - fParallaxAmount ); + + // Sample the height at the next possible step: + fNextHeight = tex2Dgrad( HeightMapSampler, texOffset2, dx, dy ).r; + + // Original offset: + float2 texSampleBase = inTexCoord - vParallaxOffset; + + return texSampleBase; + +#if 0 + cResultColor.rgb = ComputeDiffuseColor( texSampleBase, vLight ); + + float fBound = 1.0 - fStepSize * nStepIndex; + if ( fNextHeight < fCurrentBound ) +// if( 0 ) + { + //void DoIteration( in float2 vParallaxJittered, in float3 vLight, inout float4 cResultColor ) + //cResultColor.rgb = float3(1,0,0); + DoIteration( vParallax + vPixelSize, vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor ); + DoIteration( vParallax - vPixelSize, vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor ); + DoIteration( vParallax + float2( -vPixelSize.x, vPixelSize.y ), vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor ); + DoIteration( vParallax + float2( vPixelSize.x, -vPixelSize.y ), vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor ); + + cResultColor.rgb /= 5; +// cResultColor.rgb = float3( 1.0f, 0.0f, 0.0f ); + } // End of if ( fNextHeight < fCurrentBound ) + +#if DOSHADOWS + { + //============================================// + // Soft shadow and self-occlusion computation // + //============================================// + // Compute the blurry shadows (note that this computation takes into + // account self-occlusion for shadow computation): + float sh0 = tex2D( sNormalMap, texSampleBase).w; + float shA = (tex2D( sNormalMap, texSampleBase + inXY * 0.88 ).w - sh0 - 0.88 ) * 1 * fShadowSoftening; + float sh9 = (tex2D( sNormalMap, texSampleBase + inXY * 0.77 ).w - sh0 - 0.77 ) * 2 * fShadowSoftening; + float sh8 = (tex2D( sNormalMap, texSampleBase + inXY * 0.66 ).w - sh0 - 0.66 ) * 4 * fShadowSoftening; + float sh7 = (tex2D( sNormalMap, texSampleBase + inXY * 0.55 ).w - sh0 - 0.55 ) * 6 * fShadowSoftening; + float sh6 = (tex2D( sNormalMap, texSampleBase + inXY * 0.44 ).w - sh0 - 0.44 ) * 8 * fShadowSoftening; + float sh5 = (tex2D( sNormalMap, texSampleBase + inXY * 0.33 ).w - sh0 - 0.33 ) * 10 * fShadowSoftening; + float sh4 = (tex2D( sNormalMap, texSampleBase + inXY * 0.22 ).w - sh0 - 0.22 ) * 12 * fShadowSoftening; + + // Compute the actual shadow strength: + float fShadow = 1 - max( max( max( max( max( max( shA, sh9 ), sh8 ), sh7 ), sh6 ), sh5 ), sh4 ); + + cResultColor.rgb *= fShadow * 0.6 + 0.4; + } +#endif + + return cResultColor; +#endif +} + + +//======================================// +// HSL Color space conversion routines // +//======================================// + +#define HUE 0 +#define SATURATION 1 +#define LIGHTNESS 2 + +// Convert from RGB to HSL color space +float4 RGBtoHSL( float4 inColor ) +{ + float h, s; + float flMax = max( inColor.r, max( inColor.g, inColor.b ) ); + float flMin = min( inColor.r, min( inColor.g, inColor.b ) ); + + float l = (flMax + flMin) / 2.0f; + + if (flMax == flMin) // achromatic case + { + s = h = 0; + } + else // chromatic case + { + // Next, calculate the hue + float delta = flMax - flMin; + + // First, calculate the saturation + if (l < 0.5f) // If we're in the lower hexcone + { + s = delta/(flMax + flMin); + } + else + { + s = delta/(2 - flMax - flMin); + } + + if ( inColor.r == flMax ) + { + h = (inColor.g - inColor.b)/delta; // color between yellow and magenta + } + else if ( inColor.g == flMax ) + { + h = 2 + (inColor.b - inColor.r)/delta; // color between cyan and yellow + } + else // blue must be max + { + h = 4 + (inColor.r - inColor.g)/delta; // color between magenta and cyan + } + + h *= 60.0f; + + if (h < 0.0f) + { + h += 360.0f; + } + + h /= 360.0f; + } + + return float4 (h, s, l, 1.0f); +} + +float HueToRGB( float v1, float v2, float vH ) +{ + float fResult = v1; + + vH = fmod (vH + 1.0f, 1.0f); + + if ( ( 6.0f * vH ) < 1.0f ) + { + fResult = ( v1 + ( v2 - v1 ) * 6.0f * vH ); + } + else if ( ( 2.0f * vH ) < 1.0f ) + { + fResult = ( v2 ); + } + else if ( ( 3.0f * vH ) < 2.0f ) + { + fResult = ( v1 + ( v2 - v1 ) * ( ( 2.0f / 3.0f ) - vH ) * 6.0f ); + } + + return fResult; +} + +// Convert from HSL to RGB color space +float4 HSLtoRGB( float4 hsl ) +{ + float r, g, b; + float h = hsl[HUE]; + float s = hsl[SATURATION]; + float l = hsl[LIGHTNESS]; + + if ( s == 0 ) + { + r = g = b = l; + } + else + { + float v1, v2; + + if ( l < 0.5f ) + v2 = l * ( 1.0f + s ); + else + v2 = ( l + s ) - ( s * l ); + + v1 = 2 * l - v2; + + r = HueToRGB( v1, v2, h + ( 1.0f / 3.0f ) ); + g = HueToRGB( v1, v2, h ); + b = HueToRGB( v1, v2, h - ( 1.0f / 3.0f ) ); + } + + return float4( r, g, b, 1.0f ); +} + + +// texture combining modes for combining base and detail/basetexture2 +#define TCOMBINE_RGB_EQUALS_BASE_x_DETAILx2 0 // original mode +#define TCOMBINE_RGB_ADDITIVE 1 // base.rgb+detail.rgb*fblend +#define TCOMBINE_DETAIL_OVER_BASE 2 +#define TCOMBINE_FADE 3 // straight fade between base and detail. +#define TCOMBINE_BASE_OVER_DETAIL 4 // use base alpha for blend over detail +#define TCOMBINE_RGB_ADDITIVE_SELFILLUM 5 // add detail color post lighting +#define TCOMBINE_RGB_ADDITIVE_SELFILLUM_THRESHOLD_FADE 6 +#define TCOMBINE_MOD2X_SELECT_TWO_PATTERNS 7 // use alpha channel of base to select between mod2x channels in r+a of detail +#define TCOMBINE_MULTIPLY 8 +#define TCOMBINE_MASK_BASE_BY_DETAIL_ALPHA 9 // use alpha channel of detail to mask base +#define TCOMBINE_SSBUMP_BUMP 10 // use detail to modulate lighting as an ssbump +#define TCOMBINE_SSBUMP_NOBUMP 11 // detail is an ssbump but use it as an albedo. shader does the magic here - no user needs to specify mode 11 +#define TCOMBINE_NONE 12 // there is no detail texture + +float4 TextureCombine( float4 baseColor, float4 detailColor, int combine_mode, + float fBlendFactor ) +{ + if ( combine_mode == TCOMBINE_MOD2X_SELECT_TWO_PATTERNS) + { + float3 dc=lerp(detailColor.r,detailColor.a, baseColor.a); + baseColor.rgb*=lerp(float3(1,1,1),2.0*dc,fBlendFactor); + } + if ( combine_mode == TCOMBINE_RGB_EQUALS_BASE_x_DETAILx2) + baseColor.rgb*=lerp(float3(1,1,1),2.0*detailColor.rgb,fBlendFactor); + if ( combine_mode == TCOMBINE_RGB_ADDITIVE ) + baseColor.rgb += fBlendFactor * detailColor.rgb; + if ( combine_mode == TCOMBINE_DETAIL_OVER_BASE ) + { + float fblend=fBlendFactor * detailColor.a; + baseColor.rgb = lerp( baseColor.rgb, detailColor.rgb, fblend); + } + if ( combine_mode == TCOMBINE_FADE ) + { + baseColor = lerp( baseColor, detailColor, fBlendFactor); + } + if ( combine_mode == TCOMBINE_BASE_OVER_DETAIL ) + { + float fblend=fBlendFactor * (1-baseColor.a); + baseColor.rgb = lerp( baseColor.rgb, detailColor.rgb, fblend ); + baseColor.a = detailColor.a; + } + if ( combine_mode == TCOMBINE_MULTIPLY ) + { + baseColor = lerp( baseColor, baseColor*detailColor, fBlendFactor); + } + + if (combine_mode == TCOMBINE_MASK_BASE_BY_DETAIL_ALPHA ) + { + baseColor.a = lerp( baseColor.a, baseColor.a*detailColor.a, fBlendFactor ); + } + if ( combine_mode == TCOMBINE_SSBUMP_NOBUMP ) + { + baseColor.rgb = baseColor.rgb * dot( detailColor.rgb, 2.0/3.0 ); + } + return baseColor; +} + +float3 lerp5(float3 f1, float3 f2, float i1, float i2, float x) +{ + return f1+(f2-f1)*(x-i1)/(i2-i1); +} + +float3 TextureCombinePostLighting( float3 lit_baseColor, float4 detailColor, int combine_mode, + float fBlendFactor ) +{ + if ( combine_mode == TCOMBINE_RGB_ADDITIVE_SELFILLUM ) + lit_baseColor += fBlendFactor * detailColor.rgb; + if ( combine_mode == TCOMBINE_RGB_ADDITIVE_SELFILLUM_THRESHOLD_FADE ) + { + // fade in an unusual way - instead of fading out color, remap an increasing band of it from + // 0..1 + if ( fBlendFactor > 0.5) + lit_baseColor += min(1, (1.0/fBlendFactor)*max(0, detailColor.rgb-(1-fBlendFactor) ) ); + else + lit_baseColor += 2*fBlendFactor*2*max(0, detailColor.rgb-.5); + } + return lit_baseColor; +} + +//NOTE: On X360. fProjZ is expected to be pre-reversed for cheaper math here in the pixel shader +float DepthFeathering( sampler DepthSampler, const float2 vScreenPos, float fProjZ, float fProjW, float4 vDepthBlendConstants ) +{ +# if ( !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) ) //minimum requirement of ps2b + { + float flFeatheredAlpha; + float2 flDepths; +#define flSceneDepth flDepths.x +#define flSpriteDepth flDepths.y + +# if ( defined( _X360 ) ) + { + //Get depth from the depth texture. Need to sample with the offset of (0.5, 0.5) to fix rounding errors + asm { + tfetch2D flDepths.x___, vScreenPos, DepthSampler, OffsetX=0.5, OffsetY=0.5, MinFilter=point, MagFilter=point, MipFilter=point + }; + +# if( !defined( REVERSE_DEPTH_ON_X360 ) ) + flSceneDepth = 1.0f - flSceneDepth; +# endif + + //get the sprite depth into the same range as the texture depth + flSpriteDepth = fProjZ / fProjW; + + //unproject to get at the pre-projection z. This value is much more linear than depth + flDepths = vDepthBlendConstants.z / flDepths; + flDepths = vDepthBlendConstants.y - flDepths; + + flFeatheredAlpha = flSceneDepth - flSpriteDepth; + flFeatheredAlpha *= vDepthBlendConstants.x; + flFeatheredAlpha = saturate( flFeatheredAlpha ); + } +# else + { + flSceneDepth = tex2D( DepthSampler, vScreenPos ).a; // PC uses dest alpha of the frame buffer + flSpriteDepth = SoftParticleDepth( fProjZ ); + + flFeatheredAlpha = abs(flSceneDepth - flSpriteDepth) * vDepthBlendConstants.x; + flFeatheredAlpha = max( smoothstep( 0.75f, 1.0f, flSceneDepth ), flFeatheredAlpha ); //as the sprite approaches the edge of our compressed depth space, the math stops working. So as the sprite approaches the far depth, smoothly remove feathering. + flFeatheredAlpha = saturate( flFeatheredAlpha ); + } +# endif + +#undef flSceneDepth +#undef flSpriteDepth + + return flFeatheredAlpha; + } +# else + { + return 1.0f; + } +# endif +} + +#endif //#ifndef COMMON_PS_FXC_H_ diff --git a/materialsystem/stdshaders/common_shinyblood_fxc.h b/materialsystem/stdshaders/common_shinyblood_fxc.h new file mode 100644 index 00000000..a01a01d5 --- /dev/null +++ b/materialsystem/stdshaders/common_shinyblood_fxc.h @@ -0,0 +1,28 @@ +// +// Custom Fresnel with low, mid and high parameters defining a piecewise continuous function +// with traditional fresnel (0 to 1 range) as input. The 0 to 0.5 range blends between +// low and mid while the 0.5 to 1 range blends between mid and high +// +// | +// | . M . . . H +// | . +// L +// | +// +---------------- +// 0 1 +// +float FresnelHack( const float3 vNormal, const float3 vEyeDir, float3 vRanges, float fSpecMask ) +{ + float result, f = Fresnel( vNormal, vEyeDir ); // Traditional Fresnel + + if ( f > 0.5f ) + { + result = lerp( vRanges.y, vRanges.z, (2*f)-1 ); // Blend between mid and high values + } + else + { + result = lerp( fSpecMask * vRanges.x, vRanges.y, 2*f ); // Blend between low and mid values + } + + return result; +} diff --git a/materialsystem/stdshaders/common_splinerope_fxc.h b/materialsystem/stdshaders/common_splinerope_fxc.h new file mode 100644 index 00000000..c3a2ff3f --- /dev/null +++ b/materialsystem/stdshaders/common_splinerope_fxc.h @@ -0,0 +1,26 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#ifdef PIXELSHADER + #define VS_OUTPUT PS_INPUT +#endif + +struct VS_OUTPUT +{ +#ifndef PIXELSHADER + float4 projPos : POSITION; +#endif + + float2 texCoord : TEXCOORD0; + float4 worldPos_projPosZ : TEXCOORD1; + float4 argbcolor : COLOR; + +#ifndef PIXELSHADER + #if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + float fog : FOG; + #endif +#endif +}; + +#ifdef PIXELSHADER + #undef VS_OUTPUT +#endif diff --git a/materialsystem/stdshaders/common_spritecard_fxc.h b/materialsystem/stdshaders/common_spritecard_fxc.h new file mode 100644 index 00000000..14334f2d --- /dev/null +++ b/materialsystem/stdshaders/common_spritecard_fxc.h @@ -0,0 +1,75 @@ +#ifdef PIXELSHADER + #define VS_OUTPUT PS_INPUT +#endif + +#ifndef ADDBASETEXTURE2 + #error "missing define" +#endif + +#ifndef EXTRACTGREENALPHA + #error "missing define" +#endif + +#ifndef ANIMBLEND + #error "missing define" +#endif + +#ifndef MAXLUMFRAMEBLEND1 + #error "missing define" +#endif + +#ifndef DUALSEQUENCE + #error "missing define" +#endif + +#ifndef PACKED_INTERPOLATOR + #error "missing define" +#endif + +#define HAS_BLENDFACTOR0 ( ANIMBLEND || MAXLUMFRAMEBLEND1 || EXTRACTGREENALPHA || DUALSEQUENCE ) + +struct VS_OUTPUT +{ +#ifndef PIXELSHADER + float4 projPos : POSITION; +#endif + + float4 texCoord0_1 : TEXCOORD0; + +#if ( PACKED_INTERPOLATOR == 0 ) + // in packed-interpolator case, texCoord0_1.zw store argbcolor.ra + float4 argbcolor : COLOR; +#endif + +#if HAS_BLENDFACTOR0 + float4 blendfactor0 : TEXCOORD1; +#endif + +#if ADDBASETEXTURE2 + float2 texCoord2 : TEXCOORD2; +#endif + +#if EXTRACTGREENALPHA + float4 blendfactor1 : TEXCOORD3; +#endif + +#if DUALSEQUENCE + float4 vSeq2TexCoord0_1 : TEXCOORD4; +#else + float4 vecOutlineTint : TEXCOORD4; +#endif + +#if DEPTHBLEND + #if defined( REVERSE_DEPTH_ON_X360 ) + float4 vScreenPos_ReverseZ : TEXCOORD5; + #else + float4 vScreenPos : TEXCOORD7; + #endif +#endif + +#ifndef PIXELSHADER + #if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + float fog : FOG; + #endif +#endif +}; diff --git a/materialsystem/stdshaders/common_vertexlitgeneric_dx9.h b/materialsystem/stdshaders/common_vertexlitgeneric_dx9.h new file mode 100644 index 00000000..b4785f6c --- /dev/null +++ b/materialsystem/stdshaders/common_vertexlitgeneric_dx9.h @@ -0,0 +1,398 @@ +#ifndef COMMON_VERTEXLITGENERIC_DX9_H_ +#define COMMON_VERTEXLITGENERIC_DX9_H_ + +#include "common_ps_fxc.h" + +// We store four light colors and positions in an +// array of three of these structures like so: +// +// x y z w +// +------+------+------+------+ +// | L0.rgb | | +// +------+------+------+ | +// | L0.pos | L3 | +// +------+------+------+ rgb | +// | L1.rgb | | +// +------+------+------+------+ +// | L1.pos | | +// +------+------+------+ | +// | L2.rgb | L3 | +// +------+------+------+ pos | +// | L2.pos | | +// +------+------+------+------+ +// +struct PixelShaderLightInfo +{ + float4 color; + float4 pos; +}; + +#define cOverbright 2.0f +#define cOOOverbright 0.5f + +#define LIGHTTYPE_NONE 0 +#define LIGHTTYPE_SPOT 1 +#define LIGHTTYPE_POINT 2 +#define LIGHTTYPE_DIRECTIONAL 3 + +// Better suited to Pixel shader models, 11 instructions in pixel shader +float3 PixelShaderAmbientLight( const float3 worldNormal, const float3 cAmbientCube[6] ) +{ + float3 linearColor, nSquared = worldNormal * worldNormal; + float3 isNegative = ( worldNormal < 0.0 ); + float3 isPositive = 1-isNegative; + + isNegative *= nSquared; + isPositive *= nSquared; + + linearColor = isPositive.x * cAmbientCube[0] + isNegative.x * cAmbientCube[1] + + isPositive.y * cAmbientCube[2] + isNegative.y * cAmbientCube[3] + + isPositive.z * cAmbientCube[4] + isNegative.z * cAmbientCube[5]; + + return linearColor; +} + +// Better suited to Vertex shader models +// Six VS instructions due to use of constant indexing (slt, mova, mul, mul, mad, mad) +float3 VertexShaderAmbientLight( const float3 worldNormal, const float3 cAmbientCube[6] ) +{ + float3 nSquared = worldNormal * worldNormal; + int3 isNegative = ( worldNormal < 0.0 ); + float3 linearColor; + linearColor = nSquared.x * cAmbientCube[isNegative.x] + + nSquared.y * cAmbientCube[isNegative.y+2] + + nSquared.z * cAmbientCube[isNegative.z+4]; + return linearColor; +} + +float3 AmbientLight( const float3 worldNormal, const float3 cAmbientCube[6] ) +{ +#if defined( SHADER_MODEL_VS_1_0 ) || defined( SHADER_MODEL_VS_1_1 ) || defined( SHADER_MODEL_VS_2_0 ) || defined( SHADER_MODEL_VS_3_0 ) + return VertexShaderAmbientLight( worldNormal, cAmbientCube ); +#else + return PixelShaderAmbientLight( worldNormal, cAmbientCube ); +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: Compute scalar diffuse term +//----------------------------------------------------------------------------- +float3 DiffuseTerm(const bool bHalfLambert, const float3 worldNormal, const float3 lightDir, + const bool bDoLightingWarp, in sampler lightWarpSampler ) +{ + float fResult; + + float NDotL = dot( worldNormal, lightDir ); // Unsaturated dot (-1 to 1 range) + + if ( bHalfLambert ) + { + fResult = saturate(NDotL * 0.5 + 0.5); // Scale and bias to 0 to 1 range + + if ( !bDoLightingWarp ) + { + fResult *= fResult; // Square + } + } + else + { + fResult = saturate( NDotL ); // Saturate pure Lambertian term + } + + float3 fOut = float3( fResult, fResult, fResult ); + if ( bDoLightingWarp ) + { + fOut = 2.0f * tex1D( lightWarpSampler, fResult ); + } + + return fOut; +} + +float3 PixelShaderDoGeneralDiffuseLight( const float fAtten, const float3 worldPos, const float3 worldNormal, + in sampler NormalizeSampler, + const float3 vPosition, const float3 vColor, const bool bHalfLambert, + const bool bDoLightingWarp, in sampler lightWarpSampler ) +{ +#if (defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)) + float3 lightDir = normalize( vPosition - worldPos ); +#else + float3 lightDir = NormalizeWithCubemap( NormalizeSampler, vPosition - worldPos ); +#endif + return vColor * fAtten * DiffuseTerm( bHalfLambert, worldNormal, lightDir, + bDoLightingWarp, lightWarpSampler ); +} + +float3 PixelShaderGetLightVector( const float3 worldPos, PixelShaderLightInfo cLightInfo[3], int nLightIndex ) +{ + if ( nLightIndex == 3 ) + { + // Unpack light 3 from w components... + float3 vLight3Pos = float3( cLightInfo[1].pos.w, cLightInfo[2].color.w, cLightInfo[2].pos.w ); + return normalize( vLight3Pos - worldPos ); + } + else + { + return normalize( cLightInfo[nLightIndex].pos - worldPos ); + } +} + +float3 PixelShaderGetLightColor( PixelShaderLightInfo cLightInfo[3], int nLightIndex ) +{ + if ( nLightIndex == 3 ) + { + // Unpack light 3 from w components... + return float3( cLightInfo[0].color.w, cLightInfo[0].pos.w, cLightInfo[1].color.w ); + } + else + { + return cLightInfo[nLightIndex].color.rgb; + } +} + + +void SpecularAndRimTerms( const float3 vWorldNormal, const float3 vLightDir, const float fSpecularExponent, const float3 vEyeDir, + const bool bDoSpecularWarp, in sampler specularWarpSampler, const float fFresnel, + const float3 color, const bool bDoRimLighting, const float fRimExponent, + + // Outputs + out float3 specularLighting, out float3 rimLighting ) +{ + rimLighting = float3(0.0f, 0.0f, 0.0f); + + float3 vReflect = reflect( -vEyeDir, vWorldNormal ); // Reflect view through normal + float LdotR = saturate(dot( vReflect, vLightDir )); // L.R (use half-angle instead?) + specularLighting = pow( LdotR, fSpecularExponent ); // Raise to specular exponent + + // Optionally warp as function of scalar specular and fresnel + if ( bDoSpecularWarp ) + specularLighting *= tex2D( specularWarpSampler, float2(specularLighting.x, fFresnel) ); // Sample at { (L.R)^k, fresnel } + + specularLighting *= saturate(dot( vWorldNormal, vLightDir )); // Mask with N.L + specularLighting *= color; // Modulate with light color + + if ( bDoRimLighting ) // Optionally do rim lighting + { + rimLighting = pow( LdotR, fRimExponent ); // Raise to rim exponent + rimLighting *= saturate(dot( vWorldNormal, vLightDir )); // Mask with N.L + rimLighting *= color; // Modulate with light color + } +} + +// Traditional fresnel term approximation +float Fresnel( const float3 vNormal, const float3 vEyeDir ) +{ + float fresnel = 1-saturate( dot( vNormal, vEyeDir ) ); // 1-(N.V) for Fresnel term + return fresnel * fresnel; // Square for a more subtle look +} + +// Traditional fresnel term approximation which uses 4th power (square twice) +float Fresnel4( const float3 vNormal, const float3 vEyeDir ) +{ + float fresnel = 1-saturate( dot( vNormal, vEyeDir ) ); // 1-(N.V) for Fresnel term + fresnel = fresnel * fresnel; // Square + return fresnel * fresnel; // Square again for a more subtle look +} + + +// +// Custom Fresnel with low, mid and high parameters defining a piecewise continuous function +// with traditional fresnel (0 to 1 range) as input. The 0 to 0.5 range blends between +// low and mid while the 0.5 to 1 range blends between mid and high +// +// | +// | . M . . . H +// | . +// L +// | +// +---------------- +// 0 1 +// +float Fresnel( const float3 vNormal, const float3 vEyeDir, float3 vRanges ) +{ + float result, f = Fresnel( vNormal, vEyeDir ); // Traditional Fresnel + + if ( f > 0.5f ) + result = lerp( vRanges.y, vRanges.z, (2*f)-1 ); // Blend between mid and high values + else + result = lerp( vRanges.x, vRanges.y, 2*f ); // Blend between low and mid values + + return result; +} + +void PixelShaderDoSpecularLight( const float3 vWorldPos, const float3 vWorldNormal, const float fSpecularExponent, const float3 vEyeDir, + const float fAtten, const float3 vLightColor, const float3 vLightDir, + const bool bDoSpecularWarp, in sampler specularWarpSampler, float fFresnel, + const bool bDoRimLighting, const float fRimExponent, + + // Outputs + out float3 specularLighting, out float3 rimLighting ) +{ + // Compute Specular and rim terms + SpecularAndRimTerms( vWorldNormal, vLightDir, fSpecularExponent, vEyeDir, + bDoSpecularWarp, specularWarpSampler, fFresnel, vLightColor * fAtten, + bDoRimLighting, fRimExponent, specularLighting, rimLighting ); +} + +float3 PixelShaderDoLightingLinear( const float3 worldPos, const float3 worldNormal, + const float3 staticLightingColor, const bool bStaticLight, + const bool bAmbientLight, const float4 lightAtten, const float3 cAmbientCube[6], + in sampler NormalizeSampler, const int nNumLights, PixelShaderLightInfo cLightInfo[3], const bool bHalfLambert, + const bool bDoLightingWarp, in sampler lightWarpSampler ) +{ + float3 linearColor = 0.0f; + + if ( bStaticLight ) + { + // The static lighting comes in in gamma space and has also been premultiplied by $cOOOverbright + // need to get it into + // linear space so that we can do adds. + linearColor += GammaToLinear( staticLightingColor * cOverbright ); + } + + if ( bAmbientLight ) + { + linearColor += AmbientLight( worldNormal, cAmbientCube ); + } + + + if ( nNumLights > 0 ) + { + linearColor += PixelShaderDoGeneralDiffuseLight( lightAtten.x, worldPos, worldNormal, NormalizeSampler, + cLightInfo[0].pos, cLightInfo[0].color, bHalfLambert, + bDoLightingWarp, lightWarpSampler ); + if ( nNumLights > 1 ) + { + linearColor += PixelShaderDoGeneralDiffuseLight( lightAtten.y, worldPos, worldNormal, NormalizeSampler, + cLightInfo[1].pos, cLightInfo[1].color, bHalfLambert, + bDoLightingWarp, lightWarpSampler ); + if ( nNumLights > 2 ) + { + linearColor += PixelShaderDoGeneralDiffuseLight( lightAtten.z, worldPos, worldNormal, NormalizeSampler, + cLightInfo[2].pos, cLightInfo[2].color, bHalfLambert, + bDoLightingWarp, lightWarpSampler ); + if ( nNumLights > 3 ) + { + // Unpack the 4th light's data from tight constant packing + float3 vLight3Color = float3( cLightInfo[0].color.w, cLightInfo[0].pos.w, cLightInfo[1].color.w ); + float3 vLight3Pos = float3( cLightInfo[1].pos.w, cLightInfo[2].color.w, cLightInfo[2].pos.w ); + linearColor += PixelShaderDoGeneralDiffuseLight( lightAtten.w, worldPos, worldNormal, NormalizeSampler, + vLight3Pos, vLight3Color, bHalfLambert, + bDoLightingWarp, lightWarpSampler ); + } + } + } + } + + return linearColor; +} + +void PixelShaderDoSpecularLighting( const float3 worldPos, const float3 worldNormal, const float fSpecularExponent, const float3 vEyeDir, + const float4 lightAtten, const int nNumLights, PixelShaderLightInfo cLightInfo[3], + const bool bDoSpecularWarp, in sampler specularWarpSampler, float fFresnel, + const bool bDoRimLighting, const float fRimExponent, + + // Outputs + out float3 specularLighting, out float3 rimLighting ) +{ + specularLighting = rimLighting = float3( 0.0f, 0.0f, 0.0f ); + float3 localSpecularTerm, localRimTerm; + + if( nNumLights > 0 ) + { + PixelShaderDoSpecularLight( worldPos, worldNormal, fSpecularExponent, vEyeDir, + lightAtten.x, PixelShaderGetLightColor( cLightInfo, 0 ), + PixelShaderGetLightVector( worldPos, cLightInfo, 0 ), + bDoSpecularWarp, specularWarpSampler, fFresnel, + bDoRimLighting, fRimExponent, + localSpecularTerm, localRimTerm ); + + specularLighting += localSpecularTerm; // Accumulate specular and rim terms + rimLighting += localRimTerm; + } + + if( nNumLights > 1 ) + { + PixelShaderDoSpecularLight( worldPos, worldNormal, fSpecularExponent, vEyeDir, + lightAtten.y, PixelShaderGetLightColor( cLightInfo, 1 ), + PixelShaderGetLightVector( worldPos, cLightInfo, 1 ), + bDoSpecularWarp, specularWarpSampler, fFresnel, + bDoRimLighting, fRimExponent, + localSpecularTerm, localRimTerm ); + + specularLighting += localSpecularTerm; // Accumulate specular and rim terms + rimLighting += localRimTerm; + } + + + if( nNumLights > 2 ) + { + PixelShaderDoSpecularLight( worldPos, worldNormal, fSpecularExponent, vEyeDir, + lightAtten.z, PixelShaderGetLightColor( cLightInfo, 2 ), + PixelShaderGetLightVector( worldPos, cLightInfo, 2 ), + bDoSpecularWarp, specularWarpSampler, fFresnel, + bDoRimLighting, fRimExponent, + localSpecularTerm, localRimTerm ); + + specularLighting += localSpecularTerm; // Accumulate specular and rim terms + rimLighting += localRimTerm; + } + + if( nNumLights > 3 ) + { + PixelShaderDoSpecularLight( worldPos, worldNormal, fSpecularExponent, vEyeDir, + lightAtten.w, PixelShaderGetLightColor( cLightInfo, 3 ), + PixelShaderGetLightVector( worldPos, cLightInfo, 3 ), + bDoSpecularWarp, specularWarpSampler, fFresnel, + bDoRimLighting, fRimExponent, + localSpecularTerm, localRimTerm ); + + specularLighting += localSpecularTerm; // Accumulate specular and rim terms + rimLighting += localRimTerm; + } + +} + +float3 PixelShaderDoRimLighting( const float3 worldNormal, const float3 vEyeDir, const float3 cAmbientCube[6], float fFresnel ) +{ + float3 vReflect = reflect( -vEyeDir, worldNormal ); // Reflect view through normal + + return fFresnel * PixelShaderAmbientLight( vEyeDir, cAmbientCube ); +} + +// Called directly by newer shaders or through the following wrapper for older shaders +float3 PixelShaderDoLighting( const float3 worldPos, const float3 worldNormal, + const float3 staticLightingColor, const bool bStaticLight, + const bool bAmbientLight, const float4 lightAtten, const float3 cAmbientCube[6], + in sampler NormalizeSampler, const int nNumLights, PixelShaderLightInfo cLightInfo[3], + const bool bHalfLambert, const bool bDoLightingWarp, in sampler lightWarpSampler ) +{ + float3 returnColor; + + // special case for no lighting + if( !bStaticLight && !bAmbientLight ) + { + returnColor = float3( 0.0f, 0.0f, 0.0f ); + } + else if( bStaticLight && !bAmbientLight ) + { + // special case for static lighting only + returnColor = GammaToLinear( staticLightingColor ); + } + else + { + float3 linearColor; + + linearColor = PixelShaderDoLightingLinear( worldPos, worldNormal, staticLightingColor, + bStaticLight, bAmbientLight, lightAtten, + cAmbientCube, NormalizeSampler, nNumLights, cLightInfo, bHalfLambert, + bDoLightingWarp, lightWarpSampler ); + + // go ahead and clamp to the linear space equivalent of overbright 2 so that we match + // everything else. +// returnColor = HuePreservingColorClamp( linearColor, pow( 2.0f, 2.2 ) ); + returnColor = linearColor; + } + + return returnColor; +} + +#endif //#ifndef COMMON_VERTEXLITGENERIC_DX9_H_ diff --git a/materialsystem/stdshaders/common_vertexlitgeneric_vs20.fxc b/materialsystem/stdshaders/common_vertexlitgeneric_vs20.fxc new file mode 100644 index 00000000..e69de29b diff --git a/materialsystem/stdshaders/common_vs_fxc.h b/materialsystem/stdshaders/common_vs_fxc.h new file mode 100644 index 00000000..7d309fce --- /dev/null +++ b/materialsystem/stdshaders/common_vs_fxc.h @@ -0,0 +1,901 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// +// +// Purpose: This is where all common code for vertex shaders go. +// +// $NoKeywords: $ +// +//===========================================================================// + + + +#ifndef COMMON_VS_FXC_H_ +#define COMMON_VS_FXC_H_ + +#include "common_fxc.h" + +// Put global skip commands here. . make sure and check that the appropriate vars are defined +// so these aren't used on the wrong shaders! +// -------------------------------------------------------------------------------- +// Ditch all fastpath attemps if we are doing LIGHTING_PREVIEW. +// SKIP: defined $LIGHTING_PREVIEW && defined $FASTPATH && $LIGHTING_PREVIEW && $FASTPATH +// -------------------------------------------------------------------------------- + + +#ifndef COMPRESSED_VERTS +// Default to no vertex compression +#define COMPRESSED_VERTS 0 +#endif + +#if ( !defined( SHADER_MODEL_VS_2_0 ) && !defined( SHADER_MODEL_VS_3_0 ) ) +#if COMPRESSED_VERTS == 1 +#error "Vertex compression is only for DX9 and up!" +#endif +#endif + +// We're testing 2 normal compression methods +// One compressed normals+tangents into a SHORT2 each (8 bytes total) +// The other compresses them together, into a single UBYTE4 (4 bytes total) +// FIXME: pick one or the other, compare lighting quality in important cases +#define COMPRESSED_NORMALS_SEPARATETANGENTS_SHORT2 0 +#define COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 1 +//#define COMPRESSED_NORMALS_TYPE COMPRESSED_NORMALS_SEPARATETANGENTS_SHORT2 +#define COMPRESSED_NORMALS_TYPE COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 + + +#define FOGTYPE_RANGE 0 +#define FOGTYPE_HEIGHT 1 + +#define COMPILE_ERROR ( 1/0; ) + +// ------------------------- +// CONSTANTS +// ------------------------- + +#pragma def ( vs, c0, 0.0f, 1.0f, 2.0f, 0.5f ) + +const float4 cConstants1 : register(c1); +#define cOOGamma cConstants1.x +#define cOverbright 2.0f +#define cOneThird cConstants1.z +#define cOOOverbright ( 1.0f / 2.0f ) + + +// The g_bLightEnabled registers and g_nLightCountRegister hold the same information regarding +// enabling lights, but callers internal to this file tend to use the loops, while external +// callers will end up using the booleans +const bool g_bLightEnabled[4] : register(b0); + // through b3 + +const int g_nLightCountRegister : register(i0); + + +#define g_nLightCount g_nLightCountRegister.x + +const float4 cEyePos_WaterHeightW : register(c2); +#define cEyePos cEyePos_WaterHeightW.xyz +#define cWaterHeight cEyePos_WaterHeightW.w + +// This is still used by asm stuff. +const float4 cObsoleteLightIndex : register(c3); + +const float4x4 cModelViewProj : register(c4); +const float4x4 cViewProj : register(c8); + +// Only cFlexScale.x is used +// It is a binary value used to switch on/off the addition of the flex delta stream +const float4 cFlexScale : register(c13); + +const float4 cFogParams : register(c16); +#define cFogEndOverFogRange cFogParams.x +// cFogParams.y unused +#define cRadialFogMaxDensity cFogParams.z //radial fog max density in fractional portion. height fog max density stored in integer portion and is multiplied by 1e10 +#define cOOFogRange cFogParams.w + +const float4x4 cViewModel : register(c17); + +const float3 cAmbientCubeX [ 2 ] : register ( c21 ) ; +const float3 cAmbientCubeY [ 2 ] : register ( c23 ) ; +const float3 cAmbientCubeZ [ 2 ] : register ( c25 ) ; + +#ifdef SHADER_MODEL_VS_3_0 +const float4 cFlexWeights [ 512 ] : register ( c1024 ) ; +#endif + +struct LightInfo +{ + float4 color; // {xyz} is color w is light type code (see comment below) + float4 dir; // {xyz} is dir w is light type code + float4 pos; + float4 spotParams; + float4 atten; +}; + +// w components of color and dir indicate light type: +// 1x - directional +// 01 - spot +// 00 - point + +// Four lights x 5 constants each = 20 constants +LightInfo cLightInfo[4] : register(c27); +#define LIGHT_0_POSITION_REG c29 + +#ifdef SHADER_MODEL_VS_1_1 + +const float4 cModulationColor : register(c37); + +#define SHADER_SPECIFIC_CONST_0 c38 +#define SHADER_SPECIFIC_CONST_1 c39 +#define SHADER_SPECIFIC_CONST_2 c40 +#define SHADER_SPECIFIC_CONST_3 c41 +#define SHADER_SPECIFIC_CONST_4 c42 +#define SHADER_SPECIFIC_CONST_5 c43 +#define SHADER_SPECIFIC_CONST_6 c44 +#define SHADER_SPECIFIC_CONST_7 c45 +#define SHADER_SPECIFIC_CONST_8 c46 +#define SHADER_SPECIFIC_CONST_9 c47 +#define SHADER_SPECIFIC_CONST_10 c14 +#define SHADER_SPECIFIC_CONST_11 c15 + +static const int cModel0Index = 48; +const float4x3 cModel[16] : register(c48); +// last cmodel is c105 for dx80, c214 for dx90 + +#else // DX9 shaders (vs20 and beyond) + +const float4 cModulationColor : register( c47 ); + +#define SHADER_SPECIFIC_CONST_0 c48 +#define SHADER_SPECIFIC_CONST_1 c49 +#define SHADER_SPECIFIC_CONST_2 c50 +#define SHADER_SPECIFIC_CONST_3 c51 +#define SHADER_SPECIFIC_CONST_4 c52 +#define SHADER_SPECIFIC_CONST_5 c53 +#define SHADER_SPECIFIC_CONST_6 c54 +#define SHADER_SPECIFIC_CONST_7 c55 +#define SHADER_SPECIFIC_CONST_8 c56 +#define SHADER_SPECIFIC_CONST_9 c57 +#define SHADER_SPECIFIC_CONST_10 c14 +#define SHADER_SPECIFIC_CONST_11 c15 +#define SHADER_SPECIFIC_CONST_12 c12 + +static const int cModel0Index = 58; +const float4x3 cModel[53] : register( c58 ); +// last cmodel is c105 for dx80, c214 for dx90 + +#define SHADER_SPECIFIC_BOOL_CONST_0 b4 +#define SHADER_SPECIFIC_BOOL_CONST_1 b5 +#define SHADER_SPECIFIC_BOOL_CONST_2 b6 +#define SHADER_SPECIFIC_BOOL_CONST_3 b7 +#define SHADER_SPECIFIC_BOOL_CONST_4 b8 +#define SHADER_SPECIFIC_BOOL_CONST_5 b9 +#define SHADER_SPECIFIC_BOOL_CONST_6 b10 +#define SHADER_SPECIFIC_BOOL_CONST_7 b11 +#endif // vertex shader model constant packing changes + + +//======================================================================================= +// Methods to decompress vertex normals +//======================================================================================= + +//----------------------------------------------------------------------------------- +// Decompress a normal from two-component compressed format +// We expect this data to come from a signed SHORT2 stream in the range of -32768..32767 +// +// -32678 and 0 are invalid encodings +// w contains the sign to use in the cross product when generating a binormal +void _DecompressShort2Tangent( float2 inputTangent, out float4 outputTangent ) +{ + float2 ztSigns = sign( inputTangent ); // sign bits for z and tangent (+1 or -1) + float2 xyAbs = abs( inputTangent ); // 1..32767 + outputTangent.xy = (xyAbs - 16384.0f) / 16384.0f; // x and y + outputTangent.z = ztSigns.x * sqrt( saturate( 1.0f - dot( outputTangent.xy, outputTangent.xy ) ) ); + outputTangent.w = ztSigns.y; +} + +//----------------------------------------------------------------------------------- +// Same code as _DecompressShort2Tangent, just one returns a float4, one a float3 +void _DecompressShort2Normal( float2 inputNormal, out float3 outputNormal ) +{ + float4 result; + _DecompressShort2Tangent( inputNormal, result ); + outputNormal = result.xyz; +} + +//----------------------------------------------------------------------------------- +// Decompress normal+tangent together +void _DecompressShort2NormalTangent( float2 inputNormal, float2 inputTangent, out float3 outputNormal, out float4 outputTangent ) +{ + // FIXME: if we end up sticking with the SHORT2 format, pack the normal and tangent into a single SHORT4 element + // (that would make unpacking normal+tangent here together much cheaper than the sum of their parts) + _DecompressShort2Normal( inputNormal, outputNormal ); + _DecompressShort2Tangent( inputTangent, outputTangent ); +} + +//======================================================================================= +// Decompress a normal and tangent from four-component compressed format +// We expect this data to come from an unsigned UBYTE4 stream in the range of 0..255 +// The final vTangent.w contains the sign to use in the cross product when generating a binormal +void _DecompressUByte4NormalTangent( float4 inputNormal, + out float3 outputNormal, // {nX, nY, nZ} + out float4 outputTangent ) // {tX, tY, tZ, sign of binormal} +{ + float fOne = 1.0f; + + float4 ztztSignBits = ( inputNormal - 128.0f ) < 0; // sign bits for zs and binormal (1 or 0) set-less-than (slt) asm instruction + float4 xyxyAbs = abs( inputNormal - 128.0f ) - ztztSignBits; // 0..127 + float4 xyxySignBits = ( xyxyAbs - 64.0f ) < 0; // sign bits for xs and ys (1 or 0) + float4 normTan = (abs( xyxyAbs - 64.0f ) - xyxySignBits) / 63.0f; // abs({nX, nY, tX, tY}) + outputNormal.xy = normTan.xy; // abs({nX, nY, __, __}) + outputTangent.xy = normTan.zw; // abs({tX, tY, __, __}) + + float4 xyxySigns = 1 - 2*xyxySignBits; // Convert sign bits to signs + float4 ztztSigns = 1 - 2*ztztSignBits; // ( [1,0] -> [-1,+1] ) + + outputNormal.z = 1.0f - outputNormal.x - outputNormal.y; // Project onto x+y+z=1 + outputNormal.xyz = normalize( outputNormal.xyz ); // Normalize onto unit sphere + outputNormal.xy *= xyxySigns.xy; // Restore x and y signs + outputNormal.z *= ztztSigns.x; // Restore z sign + + outputTangent.z = 1.0f - outputTangent.x - outputTangent.y; // Project onto x+y+z=1 + outputTangent.xyz = normalize( outputTangent.xyz ); // Normalize onto unit sphere + outputTangent.xy *= xyxySigns.zw; // Restore x and y signs + outputTangent.z *= ztztSigns.z; // Restore z sign + outputTangent.w = ztztSigns.w; // Binormal sign +} + + +//----------------------------------------------------------------------------------- +// Decompress just a normal from four-component compressed format (same as above) +// We expect this data to come from an unsigned UBYTE4 stream in the range of 0..255 +// [ When compiled, this works out to approximately 17 asm instructions ] +void _DecompressUByte4Normal( float4 inputNormal, + out float3 outputNormal) // {nX, nY, nZ} +{ + float fOne = 1.0f; + + float2 ztSigns = ( inputNormal.xy - 128.0f ) < 0; // sign bits for zs and binormal (1 or 0) set-less-than (slt) asm instruction + float2 xyAbs = abs( inputNormal.xy - 128.0f ) - ztSigns; // 0..127 + float2 xySigns = ( xyAbs - 64.0f ) < 0; // sign bits for xs and ys (1 or 0) + outputNormal.xy = ( abs( xyAbs - 64.0f ) - xySigns ) / 63.0f; // abs({nX, nY}) + + outputNormal.z = 1.0f - outputNormal.x - outputNormal.y; // Project onto x+y+z=1 + outputNormal.xyz = normalize( outputNormal.xyz ); // Normalize onto unit sphere + + outputNormal.xy *= lerp( fOne.xx, -fOne.xx, xySigns ); // Restore x and y signs + outputNormal.z *= lerp( fOne.x, -fOne.x, ztSigns.x ); // Restore z sign +} + + +void DecompressVertex_Normal( float4 inputNormal, out float3 outputNormal ) +{ + if ( COMPRESSED_VERTS == 1 ) + { + if ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_SEPARATETANGENTS_SHORT2 ) + { + _DecompressShort2Normal( inputNormal.xy, outputNormal ); + } + else // ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 ) + { + _DecompressUByte4Normal( inputNormal, outputNormal ); + } + } + else + { + outputNormal = inputNormal.xyz; + } +} + +void DecompressVertex_NormalTangent( float4 inputNormal, float4 inputTangent, out float3 outputNormal, out float4 outputTangent ) +{ + if ( COMPRESSED_VERTS == 1 ) + { + if ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_SEPARATETANGENTS_SHORT2 ) + { + _DecompressShort2NormalTangent( inputNormal.xy, inputTangent.xy, outputNormal, outputTangent ); + } + else // ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 ) + { + _DecompressUByte4NormalTangent( inputNormal, outputNormal, outputTangent ); + } + } + else + { + outputNormal = inputNormal.xyz; + outputTangent = inputTangent; + } +} + + +#ifdef SHADER_MODEL_VS_3_0 + +//----------------------------------------------------------------------------- +// Methods to sample morph data from a vertex texture +// NOTE: vMorphTargetTextureDim.x = width, cVertexTextureDim.y = height, cVertexTextureDim.z = # of float4 fields per vertex +// For position + normal morph for example, there will be 2 fields. +//----------------------------------------------------------------------------- +float4 SampleMorphDelta( sampler2D vt, const float3 vMorphTargetTextureDim, const float4 vMorphSubrect, const float flVertexID, const float flField ) +{ + float flColumn = floor( flVertexID / vMorphSubrect.w ); + + float4 t; + t.x = vMorphSubrect.x + vMorphTargetTextureDim.z * flColumn + flField + 0.5f; + t.y = vMorphSubrect.y + flVertexID - flColumn * vMorphSubrect.w + 0.5f; + t.xy /= vMorphTargetTextureDim.xy; + t.z = t.w = 0.f; + + return tex2Dlod( vt, t ); +} + +// Optimized version which reads 2 deltas +void SampleMorphDelta2( sampler2D vt, const float3 vMorphTargetTextureDim, const float4 vMorphSubrect, const float flVertexID, out float4 delta1, out float4 delta2 ) +{ + float flColumn = floor( flVertexID / vMorphSubrect.w ); + + float4 t; + t.x = vMorphSubrect.x + vMorphTargetTextureDim.z * flColumn + 0.5f; + t.y = vMorphSubrect.y + flVertexID - flColumn * vMorphSubrect.w + 0.5f; + t.xy /= vMorphTargetTextureDim.xy; + t.z = t.w = 0.f; + + delta1 = tex2Dlod( vt, t ); + t.x += 1.0f / vMorphTargetTextureDim.x; + delta2 = tex2Dlod( vt, t ); +} + +#endif // SHADER_MODEL_VS_3_0 + +//----------------------------------------------------------------------------- +// Method to apply morphs +//----------------------------------------------------------------------------- +bool ApplyMorph( float3 vPosFlex, inout float3 vPosition ) +{ + // Flexes coming in from a separate stream + float3 vPosDelta = vPosFlex.xyz * cFlexScale.x; + vPosition.xyz += vPosDelta; + return true; +} + +bool ApplyMorph( float3 vPosFlex, float3 vNormalFlex, inout float3 vPosition, inout float3 vNormal ) +{ + // Flexes coming in from a separate stream + float3 vPosDelta = vPosFlex.xyz * cFlexScale.x; + float3 vNormalDelta = vNormalFlex.xyz * cFlexScale.x; + vPosition.xyz += vPosDelta; + vNormal += vNormalDelta; + return true; +} + +bool ApplyMorph( float3 vPosFlex, float3 vNormalFlex, + inout float3 vPosition, inout float3 vNormal, inout float3 vTangent ) +{ + // Flexes coming in from a separate stream + float3 vPosDelta = vPosFlex.xyz * cFlexScale.x; + float3 vNormalDelta = vNormalFlex.xyz * cFlexScale.x; + vPosition.xyz += vPosDelta; + vNormal += vNormalDelta; + vTangent.xyz += vNormalDelta; + return true; +} + +bool ApplyMorph( float4 vPosFlex, float3 vNormalFlex, + inout float3 vPosition, inout float3 vNormal, inout float3 vTangent, out float flWrinkle ) +{ + // Flexes coming in from a separate stream + float3 vPosDelta = vPosFlex.xyz * cFlexScale.x; + float3 vNormalDelta = vNormalFlex.xyz * cFlexScale.x; + flWrinkle = vPosFlex.w * cFlexScale.y; + vPosition.xyz += vPosDelta; + vNormal += vNormalDelta; + vTangent.xyz += vNormalDelta; + return true; +} + +#ifdef SHADER_MODEL_VS_3_0 + +bool ApplyMorph( sampler2D morphSampler, const float3 vMorphTargetTextureDim, const float4 vMorphSubrect, + const float flVertexID, const float3 vMorphTexCoord, + inout float3 vPosition ) +{ +#if MORPHING + +#if !DECAL + // Flexes coming in from a separate stream + float4 vPosDelta = SampleMorphDelta( morphSampler, vMorphTargetTextureDim, vMorphSubrect, flVertexID, 0 ); + vPosition += vPosDelta.xyz; +#else + float4 t = float4( vMorphTexCoord.x, vMorphTexCoord.y, 0.0f, 0.0f ); + float3 vPosDelta = tex2Dlod( morphSampler, t ); + vPosition += vPosDelta.xyz * vMorphTexCoord.z; +#endif // DECAL + + return true; + +#else // !MORPHING + return false; +#endif +} + +bool ApplyMorph( sampler2D morphSampler, const float3 vMorphTargetTextureDim, const float4 vMorphSubrect, + const float flVertexID, const float3 vMorphTexCoord, + inout float3 vPosition, inout float3 vNormal ) +{ +#if MORPHING + +#if !DECAL + float4 vPosDelta, vNormalDelta; + SampleMorphDelta2( morphSampler, vMorphTargetTextureDim, vMorphSubrect, flVertexID, vPosDelta, vNormalDelta ); + vPosition += vPosDelta.xyz; + vNormal += vNormalDelta.xyz; +#else + float4 t = float4( vMorphTexCoord.x, vMorphTexCoord.y, 0.0f, 0.0f ); + float3 vPosDelta = tex2Dlod( morphSampler, t ); + t.x += 1.0f / vMorphTargetTextureDim.x; + float3 vNormalDelta = tex2Dlod( morphSampler, t ); + vPosition += vPosDelta.xyz * vMorphTexCoord.z; + vNormal += vNormalDelta.xyz * vMorphTexCoord.z; +#endif // DECAL + + return true; + +#else // !MORPHING + return false; +#endif +} + +bool ApplyMorph( sampler2D morphSampler, const float3 vMorphTargetTextureDim, const float4 vMorphSubrect, + const float flVertexID, const float3 vMorphTexCoord, + inout float3 vPosition, inout float3 vNormal, inout float3 vTangent ) +{ +#if MORPHING + +#if !DECAL + float4 vPosDelta, vNormalDelta; + SampleMorphDelta2( morphSampler, vMorphTargetTextureDim, vMorphSubrect, flVertexID, vPosDelta, vNormalDelta ); + vPosition += vPosDelta.xyz; + vNormal += vNormalDelta.xyz; + vTangent += vNormalDelta.xyz; +#else + float4 t = float4( vMorphTexCoord.x, vMorphTexCoord.y, 0.0f, 0.0f ); + float3 vPosDelta = tex2Dlod( morphSampler, t ); + t.x += 1.0f / vMorphTargetTextureDim.x; + float3 vNormalDelta = tex2Dlod( morphSampler, t ); + vPosition += vPosDelta.xyz * vMorphTexCoord.z; + vNormal += vNormalDelta.xyz * vMorphTexCoord.z; + vTangent += vNormalDelta.xyz * vMorphTexCoord.z; +#endif // DECAL + + return true; + +#else // MORPHING + + return false; +#endif +} + +bool ApplyMorph( sampler2D morphSampler, const float3 vMorphTargetTextureDim, const float4 vMorphSubrect, + const float flVertexID, const float3 vMorphTexCoord, + inout float3 vPosition, inout float3 vNormal, inout float3 vTangent, out float flWrinkle ) +{ +#if MORPHING + +#if !DECAL + float4 vPosDelta, vNormalDelta; + SampleMorphDelta2( morphSampler, vMorphTargetTextureDim, vMorphSubrect, flVertexID, vPosDelta, vNormalDelta ); + vPosition += vPosDelta.xyz; + vNormal += vNormalDelta.xyz; + vTangent += vNormalDelta.xyz; + flWrinkle = vPosDelta.w; +#else + float4 t = float4( vMorphTexCoord.x, vMorphTexCoord.y, 0.0f, 0.0f ); + float4 vPosDelta = tex2Dlod( morphSampler, t ); + t.x += 1.0f / vMorphTargetTextureDim.x; + float3 vNormalDelta = tex2Dlod( morphSampler, t ); + + vPosition += vPosDelta.xyz * vMorphTexCoord.z; + vNormal += vNormalDelta.xyz * vMorphTexCoord.z; + vTangent += vNormalDelta.xyz * vMorphTexCoord.z; + flWrinkle = vPosDelta.w * vMorphTexCoord.z; +#endif // DECAL + + return true; + +#else // MORPHING + + flWrinkle = 0.0f; + return false; + +#endif +} + +#endif // SHADER_MODEL_VS_3_0 + +float CalcFixedFunctionFog( const float3 worldPos, const bool bWaterFog ) +{ + if( !bWaterFog ) + { + return CalcRangeFogFactorFixedFunction( worldPos, cEyePos, cRadialFogMaxDensity, cFogEndOverFogRange, cOOFogRange ); + } + else + { + return 0.0f; //all done in the pixel shader as of ps20 (current min-spec) + } +} + +float CalcFixedFunctionFog( const float3 worldPos, const int fogType ) +{ + return CalcFixedFunctionFog( worldPos, fogType != FOGTYPE_RANGE ); +} + +float CalcNonFixedFunctionFog( const float3 worldPos, const bool bWaterFog ) +{ + if( !bWaterFog ) + { + return CalcRangeFogFactorNonFixedFunction( worldPos, cEyePos, cRadialFogMaxDensity, cFogEndOverFogRange, cOOFogRange ); + } + else + { + return 0.0f; //all done in the pixel shader as of ps20 (current min-spec) + } +} + +float CalcNonFixedFunctionFog( const float3 worldPos, const int fogType ) +{ + return CalcNonFixedFunctionFog( worldPos, fogType != FOGTYPE_RANGE ); +} + +float4 DecompressBoneWeights( const float4 weights ) +{ + float4 result = weights; + + if ( COMPRESSED_VERTS ) + { + // Decompress from SHORT2 to float. In our case, [-1, +32767] -> [0, +1] + // NOTE: we add 1 here so we can divide by 32768 - which is exact (divide by 32767 is not). + // This avoids cracking between meshes with different numbers of bone weights. + // We use SHORT2 instead of SHORT2N for a similar reason - the GPU's conversion + // from [-32768,+32767] to [-1,+1] is imprecise in the same way. + result += 1; + result /= 32768; + } + + return result; +} + +void SkinPosition( bool bSkinning, const float4 modelPos, + const float4 boneWeights, float4 fBoneIndices, + out float3 worldPos ) +{ +#if !defined( _X360 ) + int3 boneIndices = D3DCOLORtoUBYTE4( fBoneIndices ); +#else + int3 boneIndices = fBoneIndices; +#endif + + // Needed for invariance issues caused by multipass rendering +#if defined( _X360 ) + [isolate] +#endif + { + if ( !bSkinning ) + { + worldPos = mul4x3( modelPos, cModel[0] ); + } + else // skinning - always three bones + { + float4x3 mat1 = cModel[boneIndices[0]]; + float4x3 mat2 = cModel[boneIndices[1]]; + float4x3 mat3 = cModel[boneIndices[2]]; + + float3 weights = DecompressBoneWeights( boneWeights ).xyz; + weights[2] = 1 - (weights[0] + weights[1]); + + float4x3 blendMatrix = mat1 * weights[0] + mat2 * weights[1] + mat3 * weights[2]; + worldPos = mul4x3( modelPos, blendMatrix ); + } + } +} + +void SkinPositionAndNormal( bool bSkinning, const float4 modelPos, const float3 modelNormal, + const float4 boneWeights, float4 fBoneIndices, + out float3 worldPos, out float3 worldNormal ) +{ + // Needed for invariance issues caused by multipass rendering +#if defined( _X360 ) + [isolate] +#endif + { + +#if !defined( _X360 ) + int3 boneIndices = D3DCOLORtoUBYTE4( fBoneIndices ); +#else + int3 boneIndices = fBoneIndices; +#endif + + if ( !bSkinning ) + { + worldPos = mul4x3( modelPos, cModel[0] ); + worldNormal = mul3x3( modelNormal, ( const float3x3 )cModel[0] ); + } + else // skinning - always three bones + { + float4x3 mat1 = cModel[boneIndices[0]]; + float4x3 mat2 = cModel[boneIndices[1]]; + float4x3 mat3 = cModel[boneIndices[2]]; + + float3 weights = DecompressBoneWeights( boneWeights ).xyz; + weights[2] = 1 - (weights[0] + weights[1]); + + float4x3 blendMatrix = mat1 * weights[0] + mat2 * weights[1] + mat3 * weights[2]; + worldPos = mul4x3( modelPos, blendMatrix ); + worldNormal = mul3x3( modelNormal, ( float3x3 )blendMatrix ); + } + + } // end [isolate] +} + +// Is it worth keeping SkinPosition and SkinPositionAndNormal around since the optimizer +// gets rid of anything that isn't used? +void SkinPositionNormalAndTangentSpace( + bool bSkinning, + const float4 modelPos, const float3 modelNormal, + const float4 modelTangentS, + const float4 boneWeights, float4 fBoneIndices, + out float3 worldPos, out float3 worldNormal, + out float3 worldTangentS, out float3 worldTangentT ) +{ +#if !defined( _X360 ) + int3 boneIndices = D3DCOLORtoUBYTE4( fBoneIndices ); +#else + int3 boneIndices = fBoneIndices; +#endif + + // Needed for invariance issues caused by multipass rendering +#if defined( _X360 ) + [isolate] +#endif + { + if ( !bSkinning ) + { + worldPos = mul4x3( modelPos, cModel[0] ); + worldNormal = mul3x3( modelNormal, ( const float3x3 )cModel[0] ); + worldTangentS = mul3x3( ( float3 )modelTangentS, ( const float3x3 )cModel[0] ); + } + else // skinning - always three bones + { + float4x3 mat1 = cModel[boneIndices[0]]; + float4x3 mat2 = cModel[boneIndices[1]]; + float4x3 mat3 = cModel[boneIndices[2]]; + + float3 weights = DecompressBoneWeights( boneWeights ).xyz; + weights[2] = 1 - (weights[0] + weights[1]); + + float4x3 blendMatrix = mat1 * weights[0] + mat2 * weights[1] + mat3 * weights[2]; + worldPos = mul4x3( modelPos, blendMatrix ); + worldNormal = mul3x3( modelNormal, ( const float3x3 )blendMatrix ); + worldTangentS = mul3x3( ( float3 )modelTangentS, ( const float3x3 )blendMatrix ); + } + worldTangentT = cross( worldNormal, worldTangentS ) * modelTangentS.w; + } +} + + +//----------------------------------------------------------------------------- +// Lighting helper functions +//----------------------------------------------------------------------------- + +float3 AmbientLight( const float3 worldNormal ) +{ + float3 nSquared = worldNormal * worldNormal; + int3 isNegative = ( worldNormal < 0.0 ); + float3 linearColor; + linearColor = nSquared.x * cAmbientCubeX[isNegative.x] + + nSquared.y * cAmbientCubeY[isNegative.y] + + nSquared.z * cAmbientCubeZ[isNegative.z]; + return linearColor; +} + +// The following "internal" routines are called "privately" by other routines in this file which +// handle the particular flavor of vs20 control flow appropriate to the original caller +float VertexAttenInternal( const float3 worldPos, int lightNum ) +{ + float result = 0.0f; + + // Get light direction + float3 lightDir = cLightInfo[lightNum].pos - worldPos; + + // Get light distance squared. + float lightDistSquared = dot( lightDir, lightDir ); + + // Get 1/lightDistance + float ooLightDist = rsqrt( lightDistSquared ); + + // Normalize light direction + lightDir *= ooLightDist; + + float3 vDist; +# if defined( _X360 ) + { + //X360 dynamic compile hits an internal compiler error using dst(), this is the breakdown of how dst() works from the 360 docs. + vDist.x = 1; + vDist.y = lightDistSquared * ooLightDist; + vDist.z = lightDistSquared; + //flDist.w = ooLightDist; + } +# else + { + vDist = dst( lightDistSquared, ooLightDist ); + } +# endif + + float flDistanceAtten = 1.0f / dot( cLightInfo[lightNum].atten.xyz, vDist ); + + // Spot attenuation + float flCosTheta = dot( cLightInfo[lightNum].dir.xyz, -lightDir ); + float flSpotAtten = (flCosTheta - cLightInfo[lightNum].spotParams.z) * cLightInfo[lightNum].spotParams.w; + flSpotAtten = max( 0.0001f, flSpotAtten ); + flSpotAtten = pow( flSpotAtten, cLightInfo[lightNum].spotParams.x ); + flSpotAtten = saturate( flSpotAtten ); + + // Select between point and spot + float flAtten = lerp( flDistanceAtten, flDistanceAtten * flSpotAtten, cLightInfo[lightNum].dir.w ); + + // Select between above and directional (no attenuation) + result = lerp( flAtten, 1.0f, cLightInfo[lightNum].color.w ); + + return result; +} + +float CosineTermInternal( const float3 worldPos, const float3 worldNormal, int lightNum, bool bHalfLambert ) +{ + // Calculate light direction assuming this is a point or spot + float3 lightDir = normalize( cLightInfo[lightNum].pos - worldPos ); + + // Select the above direction or the one in the structure, based upon light type + lightDir = lerp( lightDir, -cLightInfo[lightNum].dir, cLightInfo[lightNum].color.w ); + + // compute N dot L + float NDotL = dot( worldNormal, lightDir ); + + if ( !bHalfLambert ) + { + NDotL = max( 0.0f, NDotL ); + } + else // Half-Lambert + { + NDotL = NDotL * 0.5 + 0.5; + NDotL = NDotL * NDotL; + } + return NDotL; +} + +// This routine uses booleans to do early-outs and is meant to be called by routines OUTSIDE of this file +float GetVertexAttenForLight( const float3 worldPos, int lightNum ) +{ + float result = 0.0f; + if ( g_bLightEnabled[lightNum] ) + { + result = VertexAttenInternal( worldPos, lightNum ); + } + + return result; +} + +// This routine uses booleans to do early-outs and is meant to be called by routines OUTSIDE of this file +float CosineTerm( const float3 worldPos, const float3 worldNormal, int lightNum, bool bHalfLambert ) +{ + float flResult = 0.0f; + if ( g_bLightEnabled[lightNum] ) + { + flResult = CosineTermInternal( worldPos, worldNormal, lightNum, bHalfLambert ); + } + + return flResult; +} + +float3 DoLightInternal( const float3 worldPos, const float3 worldNormal, int lightNum, bool bHalfLambert ) +{ + return cLightInfo[lightNum].color * + CosineTermInternal( worldPos, worldNormal, lightNum, bHalfLambert ) * + VertexAttenInternal( worldPos, lightNum ); +} + +// This routine +float3 DoLighting( const float3 worldPos, const float3 worldNormal, + const float3 staticLightingColor, const bool bStaticLight, + const bool bDynamicLight, bool bHalfLambert ) +{ + float3 linearColor = float3( 0.0f, 0.0f, 0.0f ); + + if( bStaticLight ) // Static light + { + linearColor += GammaToLinear( staticLightingColor.rgb * cOverbright ); + } + + if( bDynamicLight ) // Dynamic light + { + for (int i = 0; i < g_nLightCount; i++) + { + linearColor += DoLightInternal( worldPos, worldNormal, i, bHalfLambert ); + } + } + + if( bDynamicLight ) + { + linearColor += AmbientLight( worldNormal ); //ambient light is already remapped + } + + return linearColor; +} + +float3 DoLightingUnrolled( const float3 worldPos, const float3 worldNormal, + const float3 staticLightingColor, const bool bStaticLight, + const bool bDynamicLight, bool bHalfLambert, const int nNumLights ) +{ + float3 linearColor = float3( 0.0f, 0.0f, 0.0f ); + + if( bStaticLight ) // Static light + { + linearColor += GammaToLinear( staticLightingColor * cOverbright ); + } + + if( bDynamicLight ) // Ambient light + { + if ( nNumLights >= 1 ) + linearColor += DoLightInternal( worldPos, worldNormal, 0, bHalfLambert ); + if ( nNumLights >= 2 ) + linearColor += DoLightInternal( worldPos, worldNormal, 1, bHalfLambert ); + if ( nNumLights >= 3 ) + linearColor += DoLightInternal( worldPos, worldNormal, 2, bHalfLambert ); + if ( nNumLights >= 4 ) + linearColor += DoLightInternal( worldPos, worldNormal, 3, bHalfLambert ); + } + + if( bDynamicLight ) + { + linearColor += AmbientLight( worldNormal ); //ambient light is already remapped + } + + return linearColor; +} + +int4 FloatToInt( in float4 floats ) +{ + return D3DCOLORtoUBYTE4( floats.zyxw / 255.001953125 ); +} + +float2 ComputeSphereMapTexCoords( in float3 reflectionVector ) +{ + // transform reflection vector into view space + reflectionVector = mul( reflectionVector, ( float3x3 )cViewModel ); + + // generate + float3 tmp = float3( reflectionVector.x, reflectionVector.y, reflectionVector.z + 1.0f ); + + // find 1 / len + float ooLen = dot( tmp, tmp ); + ooLen = 1.0f / sqrt( ooLen ); + + // tmp = tmp/|tmp| + 1 + tmp.xy = ooLen * tmp.xy + 1.0f; + + return tmp.xy * 0.5f; +} + + +#define DEFORMATION_CLAMP_TO_BOX_IN_WORLDSPACE 1 + // minxyz.minsoftness / maxxyz.maxsoftness +float3 ApplyDeformation( float3 worldpos, int deftype, float4 defparms0, float4 defparms1, + float4 defparms2, float4 defparms3 ) +{ + float3 ret = worldpos; + if ( deftype == DEFORMATION_CLAMP_TO_BOX_IN_WORLDSPACE ) + { + ret=max( ret, defparms2.xyz ); + ret=min( ret, defparms3.xyz ); + } + + return ret; +} + + +#endif //#ifndef COMMON_VS_FXC_H_ diff --git a/materialsystem/stdshaders/compositedeferredshadow_ps2x.fxc b/materialsystem/stdshaders/compositedeferredshadow_ps2x.fxc new file mode 100644 index 00000000..a2e3706b --- /dev/null +++ b/materialsystem/stdshaders/compositedeferredshadow_ps2x.fxc @@ -0,0 +1,17 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +sampler g_sShadow : register( s0 ); + +struct PS_INPUT +{ + float2 uv : TEXCOORD0; +}; + +float4 main( PS_INPUT i ) : COLOR0 +{ + float4 vShadow = tex2D( g_sShadow, i.uv ); + + float4 o = 0; + o.a = 1.0 - vShadow.x; + return o; +} diff --git a/materialsystem/stdshaders/constant_color_ps2x.fxc b/materialsystem/stdshaders/constant_color_ps2x.fxc new file mode 100644 index 00000000..bd16a19e --- /dev/null +++ b/materialsystem/stdshaders/constant_color_ps2x.fxc @@ -0,0 +1,19 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#include "common_ps_fxc.h" + +// this pixel shader compares the luminance against a conatnt value and retruns all 1s when +// greater. + +struct PS_INPUT +{ + float2 coordTap0 : TEXCOORD0; +}; + +float4 Constant_color : register( c0 ); + +float4 main( PS_INPUT i ) : COLOR +{ + return FinalOutput( float4(0,1,0,1), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); //Constant_color; +} + diff --git a/materialsystem/stdshaders/copy_fp_rt_ps2x.fxc b/materialsystem/stdshaders/copy_fp_rt_ps2x.fxc new file mode 100644 index 00000000..3edd1176 --- /dev/null +++ b/materialsystem/stdshaders/copy_fp_rt_ps2x.fxc @@ -0,0 +1,17 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#include "common_ps_fxc.h" + +sampler InputTexture : register( s0 ); + +struct PS_INPUT +{ + float2 texCoord : TEXCOORD0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float4 input=tex2D( InputTexture, i.texCoord ); + + return FinalOutput( float4(input.xyz,1), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} diff --git a/materialsystem/stdshaders/cpp_shader_constant_register_map.h b/materialsystem/stdshaders/cpp_shader_constant_register_map.h new file mode 100644 index 00000000..303a6b85 --- /dev/null +++ b/materialsystem/stdshaders/cpp_shader_constant_register_map.h @@ -0,0 +1,58 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// +// +// Purpose: Provide convenient mapping for shader constants +// +// $NoKeywords: $ +//===========================================================================// + +#define C_CODE_HACK +#include "shader_constant_register_map.h" +#undef C_CODE_HACK + +// For the C code, map the above file's defines back to integers... +#define PSREG_CONSTANT_00 0 +#define PSREG_CONSTANT_01 1 +#define PSREG_CONSTANT_02 2 +#define PSREG_CONSTANT_03 3 +#define PSREG_CONSTANT_04 4 +#define PSREG_CONSTANT_05 5 +#define PSREG_CONSTANT_06 6 +#define PSREG_CONSTANT_07 7 +#define PSREG_CONSTANT_08 8 +#define PSREG_CONSTANT_09 9 +#define PSREG_CONSTANT_10 10 +#define PSREG_CONSTANT_11 11 +#define PSREG_CONSTANT_12 12 +#define PSREG_CONSTANT_13 13 +#define PSREG_CONSTANT_14 14 +#define PSREG_CONSTANT_15 15 +#define PSREG_CONSTANT_16 16 +#define PSREG_CONSTANT_17 17 +#define PSREG_CONSTANT_18 18 +#define PSREG_CONSTANT_19 19 +#define PSREG_CONSTANT_20 20 +#define PSREG_CONSTANT_21 21 +#define PSREG_CONSTANT_22 22 +#define PSREG_CONSTANT_23 23 +#define PSREG_CONSTANT_24 24 +#define PSREG_CONSTANT_25 25 +#define PSREG_CONSTANT_26 26 +#define PSREG_CONSTANT_27 27 +#define PSREG_CONSTANT_28 28 +#define PSREG_CONSTANT_29 29 +#define PSREG_CONSTANT_30 30 +#define PSREG_CONSTANT_31 31 +#define PSREG_CONSTANT_32 32 +#define PSREG_CONSTANT_33 33 +#define PSREG_CONSTANT_34 34 +#define PSREG_CONSTANT_35 35 +#define PSREG_CONSTANT_36 36 +#define PSREG_CONSTANT_37 37 +#define PSREG_CONSTANT_38 38 +#define PSREG_CONSTANT_39 39 +#define PSREG_CONSTANT_40 40 +#define PSREG_CONSTANT_41 41 +#define PSREG_CONSTANT_42 42 +#define PSREG_CONSTANT_43 43 +#define PSREG_CONSTANT_44 44 +#define PSREG_CONSTANT_45 45 diff --git a/materialsystem/stdshaders/debugdepth.cpp b/materialsystem/stdshaders/debugdepth.cpp new file mode 100644 index 00000000..936084b5 --- /dev/null +++ b/materialsystem/stdshaders/debugdepth.cpp @@ -0,0 +1,108 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "shaderlib/CShader.h" +#include "convar.h" +#include "debugdrawdepth_vs20.inc" +#include "debugdrawdepth_ps20.inc" +#include "debugdrawdepth_ps20b.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +static ConVar mat_debugdepthmode( "mat_debugdepthmode", "0" ); +static ConVar mat_debugdepthval( "mat_debugdepthval", "128.0f" ); +static ConVar mat_debugdepthvalmax( "mat_debugdepthvalmax", "256.0f" ); + +BEGIN_SHADER_FLAGS( DebugDepth, "Help for DebugDepth", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + } + + SHADER_INIT + { + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_DRAW + { + SHADOW_STATE + { + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + DECLARE_STATIC_VERTEX_SHADER( debugdrawdepth_vs20 ); + SET_STATIC_VERTEX_SHADER( debugdrawdepth_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( debugdrawdepth_ps20b ); + SET_STATIC_PIXEL_SHADER( debugdrawdepth_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( debugdrawdepth_ps20 ); + SET_STATIC_PIXEL_SHADER( debugdrawdepth_ps20 ); + } + } + DYNAMIC_STATE + { + DECLARE_DYNAMIC_VERTEX_SHADER( debugdrawdepth_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, s_pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( debugdrawdepth_vs20 ); + + Vector4D vecZFilter( 0, 0, 0, 1 ); + int nDepthMode = mat_debugdepthmode.GetInt(); + if ( nDepthMode > 1 ) + { + nDepthMode = 0; + } + + vecZFilter[nDepthMode] = 1; + s_pShaderAPI->SetPixelShaderConstant( 1, vecZFilter.Base() ); + + Vector4D vecModulationColor( 0, 0, 0, 1 ); + if ( IS_FLAG_SET( MATERIAL_VAR_DECAL ) ) + { + vecModulationColor[0] = 0; + vecModulationColor[1] = 1; + vecModulationColor[2] = 1; + } + else + { + vecModulationColor[0] = 1; + vecModulationColor[1] = 1; + vecModulationColor[2] = 1; + } + s_pShaderAPI->SetPixelShaderConstant( 2, vecModulationColor.Base() ); + + float flDepthFactor = mat_debugdepthval.GetFloat(); + float flDepthFactorMax = mat_debugdepthvalmax.GetFloat(); + if ( flDepthFactor == 0 ) + { + flDepthFactor = 1.0f; + } + Vector4D vecZFactor( (flDepthFactorMax - flDepthFactor), flDepthFactor, 1, 1 ); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, vecZFactor.Base() ); + } + Draw(); + } +END_SHADER + diff --git a/materialsystem/stdshaders/debugluxel.cpp b/materialsystem/stdshaders/debugluxel.cpp new file mode 100644 index 00000000..e1d676fa --- /dev/null +++ b/materialsystem/stdshaders/debugluxel.cpp @@ -0,0 +1,97 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "shaderlib/CShader.h" + +#include "debugluxel_ps20b.inc" +#include "debugluxel_ps20.inc" +#include "debugluxel_vs20.inc" + + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_SHADER_FLAGS( DebugLuxels, "Help for DebugLuxels", SHADER_NOT_EDITABLE ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( NOSCALE, SHADER_PARAM_TYPE_BOOL, "0", "fixme" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + + if( g_pHardwareConfig->GetDXSupportLevel() >= 90 ) + { + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + } + } + + SHADER_INIT + { + LoadTexture( BASETEXTURE ); + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + DECLARE_STATIC_VERTEX_SHADER( debugluxel_vs20 ); + SET_STATIC_VERTEX_SHADER( debugluxel_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( debugluxel_ps20b ); + SET_STATIC_PIXEL_SHADER( debugluxel_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( debugluxel_ps20 ); + SET_STATIC_PIXEL_SHADER( debugluxel_ps20 ); + } + + SetDefaultBlendingShadowState( BASETEXTURE ); + DisableFog(); + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 2, NULL, 0 ); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + + int texCoordScaleX = 1, texCoordScaleY = 1; + if (!params[NOSCALE]->GetIntValue()) + { + pShaderAPI->GetLightmapDimensions( &texCoordScaleX, &texCoordScaleY ); + } + + DECLARE_DYNAMIC_VERTEX_SHADER( debugluxel_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( debugluxel_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( debugluxel_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( debugluxel_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( debugluxel_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( debugluxel_ps20 ); + } + + //texture scale transform + Vector4D transformation[2]; + transformation[0].Init( texCoordScaleX, 0.0f, 0.0f, 0.0f ); + transformation[1].Init( 0.0f, texCoordScaleY, 0.0f, 0.0f ); + s_pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, transformation[0].Base(), 2 ); + } + Draw(); + } +END_SHADER diff --git a/materialsystem/stdshaders/debugluxel_ps2x.fxc b/materialsystem/stdshaders/debugluxel_ps2x.fxc new file mode 100644 index 00000000..4c594f5a --- /dev/null +++ b/materialsystem/stdshaders/debugluxel_ps2x.fxc @@ -0,0 +1,15 @@ +#include "common_ps_fxc.h" + +sampler TextureSampler : register( s0 ); + +struct PS_INPUT +{ + float2 baseTexCoord : TEXCOORD0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float4 result = tex2D( TextureSampler, i.baseTexCoord ); + return FinalOutput( result, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} + diff --git a/materialsystem/stdshaders/debugluxel_vs20.fxc b/materialsystem/stdshaders/debugluxel_vs20.fxc new file mode 100644 index 00000000..62ba75da --- /dev/null +++ b/materialsystem/stdshaders/debugluxel_vs20.fxc @@ -0,0 +1,32 @@ +#include "common_vs_fxc.h" + +const float4 cLightmapTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_0 ); + +struct VS_INPUT +{ + float3 vPos : POSITION; + float2 vBaseTexCoord : TEXCOORD0; + float2 vLightmapTexCoord : TEXCOORD1; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; + float2 baseTexCoord : TEXCOORD0; +}; + + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float4 projPos; + float3 worldPos; + + projPos = mul( float4( v.vPos, 1 ), cModelViewProj ); + o.projPos = projPos; + + o.baseTexCoord.x = dot( v.vLightmapTexCoord, cLightmapTexCoordTransform[0] ) + cLightmapTexCoordTransform[0].w; + o.baseTexCoord.y = dot( v.vLightmapTexCoord, cLightmapTexCoordTransform[1] ) + cLightmapTexCoordTransform[1].w; + return o; +} diff --git a/materialsystem/stdshaders/debugmodifyvertex.cpp b/materialsystem/stdshaders/debugmodifyvertex.cpp new file mode 100644 index 00000000..f36a808a --- /dev/null +++ b/materialsystem/stdshaders/debugmodifyvertex.cpp @@ -0,0 +1,93 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: This is an example of a material that modifies vertex data +// in the shader. NOTE: Every pass is given a clean set of vertex data. +// Modifications made in the first pass are *not* carried over to the next pass +// Modifications must take place during the DYNAMIC_STATE block. +// Use the function MeshBuilder() to build the mesh +// +// Also note: Using thie feature is *really expensive*! It makes a copy of +// the vertex data *per pass!* If you wish to modify vertex data to be used +// with all passes, your best bet is to construct a dynamic mesh instead. +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "shaderlib/CShader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_SHADER_FLAGS( DebugModifyVertex, "Help for DebugModifyVertex", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( WAVE, SHADER_PARAM_TYPE_FLOAT, "1.0", "wave amplitude" ) + END_SHADER_PARAMS + + SHADER_INIT + { + LoadTexture( BASETEXTURE ); + } + + SHADER_DRAW + { + if( g_pHardwareConfig->GetSamplerCount() >= 2 ) + { + // lightmap + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableVertexDataPreprocess( true ); + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 ); + FogToFogColor(); + } + + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + + float amp = params[WAVE]->GetFloatValue(); + float currTime = pShaderAPI->CurrentTime(); + for (int i = 0; i < MeshBuilder()->NumVertices(); ++i) + { + float const* pPos = MeshBuilder()->Position(); + MeshBuilder()->Position3f( pPos[0] + amp * sin( currTime + pPos[2] / 4 ), + pPos[1] + amp * sin( currTime + pPos[2] / 4 + 2 * 3.14 / 3 ), + pPos[2] + amp * sin( currTime + pPos[2] / 4 + 4 * 3.14 / 3 ) ); + MeshBuilder()->AdvanceVertex(); + } + } + Draw(); + + // base * vertex color + SHADOW_STATE + { + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_COLOR | + SHADER_DRAW_TEXCOORD0 ); + FogToFogColor(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + + // Notice here that since we didn't modify the position, and this is a second + // pass, the position has been reset to it's initial, unmodified position + float currTime = pShaderAPI->CurrentTime(); + for (int i = 0; i < MeshBuilder()->NumVertices(); ++i) + { + float const* pPos = MeshBuilder()->Position(); + MeshBuilder()->Color3f( ( sin( currTime + pPos[0] ) + 1.0F) * 0.5, + ( sin( currTime + pPos[1] ) + 1.0F) * 0.5, + ( sin( currTime + pPos[2] ) + 1.0F) * 0.5 ); + MeshBuilder()->AdvanceVertex(); + } + } + Draw(); + } + else + { + ShaderWarning( "DebugModifyVertex: not " + "implemented for single-texturing hardware\n" ); + } + } +END_SHADER diff --git a/materialsystem/stdshaders/debugmorphaccumulator_dx9.cpp b/materialsystem/stdshaders/debugmorphaccumulator_dx9.cpp new file mode 100644 index 00000000..c55c2195 --- /dev/null +++ b/materialsystem/stdshaders/debugmorphaccumulator_dx9.cpp @@ -0,0 +1,68 @@ +//===== Copyright © 1996-2007, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" + +#include "debugmorphaccumulator_ps30.inc" +#include "debugmorphaccumulator_vs30.inc" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +BEGIN_VS_SHADER_FLAGS( DebugMorphAccumulator, "Help for Debug Morph Accumulator", SHADER_NOT_EDITABLE ) + + BEGIN_SHADER_PARAMS + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + LoadTexture( BASETEXTURE ); + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableDepthTest( false ); + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableCulling( false ); + pShaderShadow->FogMode( SHADER_FOGMODE_DISABLED, false ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBWrite( false ); + + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 1, 0, 0 ); + + DECLARE_STATIC_VERTEX_SHADER( debugmorphaccumulator_vs30 ); + SET_STATIC_VERTEX_SHADER( debugmorphaccumulator_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( debugmorphaccumulator_ps30 ); + SET_STATIC_PIXEL_SHADER( debugmorphaccumulator_ps30 ); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE ); + + DECLARE_DYNAMIC_VERTEX_SHADER( debugmorphaccumulator_vs30 ); + SET_DYNAMIC_VERTEX_SHADER( debugmorphaccumulator_vs30 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( debugmorphaccumulator_ps30 ); + SET_DYNAMIC_PIXEL_SHADER( debugmorphaccumulator_ps30 ); + } + Draw( ); + } +END_SHADER diff --git a/materialsystem/stdshaders/debugmorphaccumulator_ps30.fxc b/materialsystem/stdshaders/debugmorphaccumulator_ps30.fxc new file mode 100644 index 00000000..f81459d7 --- /dev/null +++ b/materialsystem/stdshaders/debugmorphaccumulator_ps30.fxc @@ -0,0 +1,17 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#include "common_ps_fxc.h" + +struct PS_INPUT +{ + float2 vTexCoord : TEXCOORD0; +}; + +sampler MorphAccumulator : register( s0 ); + +HALF4 main( PS_INPUT i ) : COLOR +{ + float4 vDeltas = tex2D( MorphAccumulator, i.vTexCoord ); + return float4( abs( vDeltas.x ), abs( vDeltas.z ), abs( vDeltas.y ) + abs( vDeltas.w ), 1.0f ); +} + diff --git a/materialsystem/stdshaders/debugmorphaccumulator_vs30.fxc b/materialsystem/stdshaders/debugmorphaccumulator_vs30.fxc new file mode 100644 index 00000000..5600cdc5 --- /dev/null +++ b/materialsystem/stdshaders/debugmorphaccumulator_vs30.fxc @@ -0,0 +1,23 @@ +#include "common_vs_fxc.h" + +struct VS_INPUT +{ + float4 vPos : POSITION; + float2 vTexCoord : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; + float2 vTexCoord : TEXCOORD0; +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + o.vProjPos = mul( v.vPos, cModelViewProj ); + o.vTexCoord = v.vTexCoord; + + return o; +} \ No newline at end of file diff --git a/materialsystem/stdshaders/debugmrttexture.cpp b/materialsystem/stdshaders/debugmrttexture.cpp new file mode 100644 index 00000000..b2dff83e --- /dev/null +++ b/materialsystem/stdshaders/debugmrttexture.cpp @@ -0,0 +1,86 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" + +#include "debugmrttexture_ps20.inc" +#include "debugmrttexture_ps20b.inc" +#include "debugmrttexture_vs20.inc" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +BEGIN_VS_SHADER_FLAGS( DebugMRTTexture, "Help for DebugMRTTexture", SHADER_NOT_EDITABLE ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( MRTINDEX, SHADER_PARAM_TYPE_INTEGER, "", "" ) + END_SHADER_PARAMS + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT_PARAMS() + { + } + + SHADER_INIT + { + LoadTexture( BASETEXTURE ); + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + DECLARE_STATIC_VERTEX_SHADER( debugmrttexture_vs20 ); + SET_STATIC_VERTEX_SHADER( debugmrttexture_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( debugmrttexture_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( MRTINDEX, params[MRTINDEX]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER( debugmrttexture_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( debugmrttexture_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( MRTINDEX, params[MRTINDEX]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER( debugmrttexture_ps20 ); + } + + int numTexCoords = 2; + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, numTexCoords, 0, 0 ); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + + DECLARE_DYNAMIC_VERTEX_SHADER( debugmrttexture_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( debugmrttexture_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( debugmrttexture_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( debugmrttexture_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( debugmrttexture_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( debugmrttexture_ps20 ); + } + } + Draw(); + } +END_SHADER + diff --git a/materialsystem/stdshaders/debugmrttexture_ps2x.fxc b/materialsystem/stdshaders/debugmrttexture_ps2x.fxc new file mode 100644 index 00000000..9309ab87 --- /dev/null +++ b/materialsystem/stdshaders/debugmrttexture_ps2x.fxc @@ -0,0 +1,25 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "MRTINDEX" "0..1" + +#include "common_ps_fxc.h" + +struct PS_INPUT +{ + float2 baseTexCoord : TEXCOORD0; +}; + +sampler BaseTextureSampler1 : register( s0 ); +sampler BaseTextureSampler2 : register( s1 ); + +float4 main( PS_INPUT i ) : COLOR +{ +#if MRTINDEX == 0 + float4 result = tex2D( BaseTextureSampler1, i.baseTexCoord ); +#else + float4 result = tex2D( BaseTextureSampler2, i.baseTexCoord ); +#endif + + return FinalOutput( result, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} + diff --git a/materialsystem/stdshaders/debugmrttexture_vs20.fxc b/materialsystem/stdshaders/debugmrttexture_vs20.fxc new file mode 100644 index 00000000..f4708b83 --- /dev/null +++ b/materialsystem/stdshaders/debugmrttexture_vs20.fxc @@ -0,0 +1,29 @@ +#include "common_vs_fxc.h" + +struct VS_INPUT +{ + float3 vPos : POSITION; + float2 vBaseTexCoord : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; + float2 baseTexCoord : TEXCOORD0; +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float4 projPos; + float3 worldPos; + + projPos = mul( float4( v.vPos, 1 ), cModelViewProj ); + o.projPos = projPos; + + o.baseTexCoord = v.vBaseTexCoord; + return o; +} + + diff --git a/materialsystem/stdshaders/debugnormalmap.cpp b/materialsystem/stdshaders/debugnormalmap.cpp new file mode 100644 index 00000000..280d49fe --- /dev/null +++ b/materialsystem/stdshaders/debugnormalmap.cpp @@ -0,0 +1,163 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" +#include "convar.h" + +#include "unlitgeneric_vs20.inc" +#include "unlitgeneric_ps20.inc" +#include "unlitgeneric_ps20b.inc" + +#if !defined( _X360 ) + #include "unlitgeneric_ps30.inc" + #include "unlitgeneric_vs30.inc" +#endif + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +static ConVar mat_displacementmap( "mat_displacementmap", "1", FCVAR_CHEAT ); + +BEGIN_VS_SHADER_FLAGS( DebugNormalMap, "Help for DebugNormalMap", SHADER_NOT_EDITABLE ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/WorldDiffuseBumpMap_bump", "bump map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + } + + SHADER_INIT + { + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_STATIC_VERTEX_SHADER( unlitgeneric_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( VERTEXCOLOR, 0 ); + SET_STATIC_VERTEX_SHADER( unlitgeneric_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( unlitgeneric_ps20b ); + SET_STATIC_PIXEL_SHADER( unlitgeneric_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( unlitgeneric_ps20 ); + SET_STATIC_PIXEL_SHADER( unlitgeneric_ps20 ); + } + } +#ifndef _X360 + else + { + DECLARE_STATIC_VERTEX_SHADER( unlitgeneric_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( VERTEXCOLOR, 0 ); + SET_STATIC_VERTEX_SHADER( unlitgeneric_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( unlitgeneric_ps30 ); + SET_STATIC_PIXEL_SHADER( unlitgeneric_ps30 ); + } +#endif + + } + DYNAMIC_STATE + { + if ( params[BUMPMAP]->IsTexture() ) + { + BindTexture( SHADER_SAMPLER0, BUMPMAP, BUMPFRAME ); + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_NORMALMAP_FLAT ); + } + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BUMPTRANSFORM ); + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_DYNAMIC_VERTEX_SHADER( unlitgeneric_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( TESSELLATION, 0 ); + SET_DYNAMIC_VERTEX_SHADER( unlitgeneric_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( unlitgeneric_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( unlitgeneric_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( unlitgeneric_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( unlitgeneric_ps20 ); + } + } +#ifndef _X360 + else + { + TessellationMode_t nTessellationMode = pShaderAPI->GetTessellationMode(); + if ( nTessellationMode != TESSELLATION_MODE_DISABLED ) + { + pShaderAPI->BindStandardVertexTexture( SHADER_VERTEXTEXTURE_SAMPLER1, TEXTURE_SUBDIVISION_PATCHES ); + + bool bHasDisplacement = false; // TODO + float vSubDDimensions[4] = { 1.0f/pShaderAPI->GetSubDHeight(), bHasDisplacement && mat_displacementmap.GetBool()? 1.0f : 0.0f, 0.0f, 0.0f }; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_8, vSubDDimensions ); + +// JasonM - revisit this later...requires plumbing in a separate vertex texture param type?? +// bool bHasDisplacement = (info.m_nDisplacementMap != -1) && params[info.m_nDisplacementMap]->IsTexture(); +// if( bHasDisplacement ) +// { +// pShader->BindVertexTexture( SHADER_VERTEXTEXTURE_SAMPLER2, info.m_nDisplacementMap ); +// } +// else +// { +// pShaderAPI->BindStandardVertexTexture( SHADER_VERTEXTEXTURE_SAMPLER2, VERTEX_TEXTURE_BLACK ); +// } + } + DECLARE_DYNAMIC_VERTEX_SHADER( unlitgeneric_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( TESSELLATION, nTessellationMode ); + SET_DYNAMIC_VERTEX_SHADER( unlitgeneric_vs30 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( unlitgeneric_ps30 ); + SET_DYNAMIC_PIXEL_SHADER( unlitgeneric_ps30 ); + } +#endif + + } + Draw(); + } +END_SHADER + diff --git a/materialsystem/stdshaders/debugsoftwarevertexshader.cpp b/materialsystem/stdshaders/debugsoftwarevertexshader.cpp new file mode 100644 index 00000000..38ac0df5 --- /dev/null +++ b/materialsystem/stdshaders/debugsoftwarevertexshader.cpp @@ -0,0 +1,56 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "shaderlib/CShader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +SOFTWARE_VERTEX_SHADER( myHappyLittleSoftwareVertexShader ) +{ + float t = pShaderAPI->CurrentTime(); + for( int i = 0; i < meshBuilder.NumVertices(); i++ ) + { + const float *pPos = meshBuilder.Position(); + meshBuilder.Position3f( pPos[0], pPos[1], pPos[2] + 10.0f * sin( t + pPos[0] ) ); + meshBuilder.AdvanceVertex(); + } +} + +FORWARD_DECLARE_SOFTWARE_VERTEX_SHADER( myHappyLittleSoftwareVertexShader ); + +BEGIN_SHADER_FLAGS( DebugSoftwareVertexShader, "blah", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + SHADER_PARAM_OVERRIDE( BASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/basetexture", "unused", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM_OVERRIDE( FRAME, SHADER_PARAM_TYPE_INTEGER, "0", "unused", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM_OVERRIDE( BASETEXTURETRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "unused", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM_OVERRIDE( COLOR, SHADER_PARAM_TYPE_COLOR, "{255 255 255}", "unused", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM_OVERRIDE( ALPHA, SHADER_PARAM_TYPE_FLOAT, "1.0", "unused", SHADER_PARAM_NOT_EDITABLE ) + END_SHADER_PARAMS + + SHADER_INIT + { + if( g_pHardwareConfig->SupportsVertexAndPixelShaders() ) + { + USE_SOFTWARE_VERTEX_SHADER( myHappyLittleSoftwareVertexShader ); + } + else + { + USE_SOFTWARE_VERTEX_SHADER( myHappyLittleSoftwareVertexShader ); + } + } + SHADER_DRAW + { + SHADOW_STATE + { + } + DYNAMIC_STATE + { + } + Draw(); + } +END_SHADER diff --git a/materialsystem/stdshaders/debugtangentspace.cpp b/materialsystem/stdshaders/debugtangentspace.cpp new file mode 100644 index 00000000..f33b312e --- /dev/null +++ b/materialsystem/stdshaders/debugtangentspace.cpp @@ -0,0 +1,81 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "shaderlib/CShader.h" + +#include "debugtangentspace_vs20.inc" +#include "unlitgeneric_notexture_ps20.inc" +#include "unlitgeneric_notexture_ps20b.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_SHADER( DebugTangentSpace, "Help for DebugTangentSpace" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM_OVERRIDE( BASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/basetexture", "unused", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM_OVERRIDE( FRAME, SHADER_PARAM_TYPE_INTEGER, "0", "unused", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM_OVERRIDE( BASETEXTURETRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "unused", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM_OVERRIDE( COLOR, SHADER_PARAM_TYPE_COLOR, "{255 255 255}", "unused", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM_OVERRIDE( ALPHA, SHADER_PARAM_TYPE_FLOAT, "1.0", "unused", SHADER_PARAM_NOT_EDITABLE ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + } + + SHADER_INIT + { + } + + SHADER_DRAW + { + SHADOW_STATE + { + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 0; + int userDataSize = 4; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + DECLARE_STATIC_VERTEX_SHADER( debugtangentspace_vs20 ); + SET_STATIC_VERTEX_SHADER( debugtangentspace_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( unlitgeneric_notexture_ps20b ); + SET_STATIC_PIXEL_SHADER( unlitgeneric_notexture_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( unlitgeneric_notexture_ps20 ); + SET_STATIC_PIXEL_SHADER( unlitgeneric_notexture_ps20 ); + } + } + DYNAMIC_STATE + { + DECLARE_DYNAMIC_VERTEX_SHADER( debugtangentspace_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( debugtangentspace_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( unlitgeneric_notexture_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( unlitgeneric_notexture_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( unlitgeneric_notexture_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( unlitgeneric_notexture_ps20 ); + } + } + Draw(); + } +END_SHADER + diff --git a/materialsystem/stdshaders/debugtangentspace.vsh b/materialsystem/stdshaders/debugtangentspace.vsh new file mode 100644 index 00000000..8fac2c9e --- /dev/null +++ b/materialsystem/stdshaders/debugtangentspace.vsh @@ -0,0 +1,34 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" +# DYNAMIC: "SKINNING" "0..1" + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending +;------------------------------------------------------------------------------ +&AllocateRegister( \$worldPos ); +&AllocateRegister( \$worldNormal ); +&SkinPositionAndNormal( $worldPos, $worldNormal ); + +;------------------------------------------------------------------------------ +; Transform the position from world to view space +;------------------------------------------------------------------------------ + +&AllocateRegister( \$projPos ); + +dp4 $projPos.x, $worldPos, $cViewProj0 +dp4 $projPos.y, $worldPos, $cViewProj1 +dp4 $projPos.z, $worldPos, $cViewProj2 +dp4 $projPos.w, $worldPos, $cViewProj3 +mov oPos, $projPos + +&FreeRegister( \$worldPos ); + +; stick the normal in the color channel +mov oD0.xyz, $worldNormal.xyz +mov oD0.w, $cOne ; make sure all components are defined + +&FreeRegister( \$projPos ); +&FreeRegister( \$worldNormal ); diff --git a/materialsystem/stdshaders/debugtangentspace_vs20.fxc b/materialsystem/stdshaders/debugtangentspace_vs20.fxc new file mode 100644 index 00000000..18eecafb --- /dev/null +++ b/materialsystem/stdshaders/debugtangentspace_vs20.fxc @@ -0,0 +1,52 @@ +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +#include "common_fog_vs_fxc.h" +// DYNAMIC: "SKINNING" "0..1" + +#include "common_vs_fxc.h" + +static const int g_FogType = DOWATERFOG; +static const bool g_bSkinning = SKINNING ? true : false; + + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vNormal : NORMAL; +}; + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; + + float4 vDiffuse : COLOR0; + +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + float fog : FOG; +#endif +}; + + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 vObjNormal; + DecompressVertex_Normal( v.vNormal, vObjNormal ); + + float3 worldPos, worldNormal; + SkinPositionAndNormal( g_bSkinning, v.vPos, vObjNormal, v.vBoneWeights, v.vBoneIndices, worldPos, worldNormal ); + + o.vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + o.fog = CalcFixedFunctionFog( worldPos, g_FogType ); +#endif + + // stick the normal in the color channel + o.vDiffuse.rgb = worldNormal; + o.vDiffuse.a = 1.0f; + + return o; +} \ No newline at end of file diff --git a/materialsystem/stdshaders/decal.cpp b/materialsystem/stdshaders/decal.cpp new file mode 100644 index 00000000..85a9070f --- /dev/null +++ b/materialsystem/stdshaders/decal.cpp @@ -0,0 +1,127 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "shaderlib/CShader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_SHADER_FLAGS( Decal, "Help for Decal", SHADER_NOT_EDITABLE ) + + BEGIN_SHADER_PARAMS + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + } + + SHADER_INIT + { + LoadTexture( BASETEXTURE ); + } + + SHADER_DRAW + { + // vertex alpha 0 = mod2x, vertex alpha 1 = src_alpha,1-src_alpha + // need to set constant color to grey + SHADOW_STATE + { + // common stuff + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnablePolyOffset( SHADER_POLYOFFSET_DECAL ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableBlending( true ); + } + // MOD2X pass + SHADOW_STATE + { + pShaderShadow->EnableCustomPixelPipe( true ); + pShaderShadow->CustomTextureStages( 2 ); + + // color = texture + // alpha = vertexalpha + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_COLOR, SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_TEXTURE, SHADER_TEXARG_NONE ); + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_ALPHA, SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_SPECULARCOLOR, SHADER_TEXARG_NONE ); + + // color = texture + // alpha = blend + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_COLOR, SHADER_TEXOP_BLEND_PREVIOUSSTAGEALPHA, + SHADER_TEXARG_CONSTANTCOLOR, SHADER_TEXARG_PREVIOUSSTAGE ); + + pShaderShadow->BlendFunc( SHADER_BLEND_DST_COLOR, SHADER_BLEND_SRC_COLOR ); + FogToGrey(); + + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 | SHADER_DRAW_SPECULAR + | SHADER_DRAW_LIGHTMAP_TEXCOORD1 ); + } + DYNAMIC_STATE + { + pShaderAPI->Color3f( 0.5f, 0.5f, 0.5f ); + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP ); + } + Draw(); + + // srcalpha,1-srcalpha pass + SHADOW_STATE + { + pShaderShadow->EnableCustomPixelPipe( true ); + pShaderShadow->CustomTextureStages( 2 ); + + // color = texture + // alpha = texture + if (IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR )) + { + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_COLOR, SHADER_TEXOP_MODULATE, + SHADER_TEXARG_TEXTURE, SHADER_TEXARG_VERTEXCOLOR ); + } + else + { + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_COLOR, SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_TEXTURE, SHADER_TEXARG_NONE ); + } + + if( IS_FLAG_SET( MATERIAL_VAR_VERTEXALPHA ) ) + { + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_ALPHA, SHADER_TEXOP_MODULATE, + SHADER_TEXARG_TEXTURE, SHADER_TEXARG_VERTEXCOLOR ); + } + else + { + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_ALPHA, SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_TEXTURE, SHADER_TEXARG_NONE ); + } + + // color = texture [* vertex color] * lightmap color + // alpha = texture alpha [* vertex alpha] * specular alpha + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_COLOR, SHADER_TEXOP_MODULATE2X, + SHADER_TEXARG_PREVIOUSSTAGE, SHADER_TEXARG_TEXTURE ); + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_ALPHA, SHADER_TEXOP_MODULATE, + SHADER_TEXARG_PREVIOUSSTAGE, SHADER_TEXARG_SPECULARCOLOR ); + + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + FogToFogColor(); + } + DYNAMIC_STATE + { + SetColorState( COLOR ); + } + Draw(); + } +END_SHADER diff --git a/materialsystem/stdshaders/decalmodulate.cpp b/materialsystem/stdshaders/decalmodulate.cpp new file mode 100644 index 00000000..59a77d95 --- /dev/null +++ b/materialsystem/stdshaders/decalmodulate.cpp @@ -0,0 +1,63 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "shaderlib/CShader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( DecalModulate, DecalModulate_DX6 ) + +BEGIN_SHADER( DecalModulate_dx6, + "Help for DecalModulate_dx6" ) + + BEGIN_SHADER_PARAMS + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + } + + SHADER_INIT + { + LoadTexture( BASETEXTURE ); + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableAlphaTest( true ); + pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GREATER, 0.0f ); + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnablePolyOffset( SHADER_POLYOFFSET_DECAL ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_DST_COLOR, SHADER_BLEND_SRC_COLOR ); + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 ); + FogToGrey(); + } + DYNAMIC_STATE + { + // This is kinda gross. We really don't want to render anything here for the flashlight + // pass since we are multiplying by what is already flashlight lit in the framebuffer. + // There is no easy way to draw nothing conditionally, so I'll bind grey and multiply + // which shouldn't change the contents of the framebuffer much. + if( pShaderAPI->InFlashlightMode() ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY ); + } + else + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + } + } + Draw( ); + } +END_SHADER diff --git a/materialsystem/stdshaders/decalmodulate_ps2x.fxc b/materialsystem/stdshaders/decalmodulate_ps2x.fxc new file mode 100644 index 00000000..bc4bf46e --- /dev/null +++ b/materialsystem/stdshaders/decalmodulate_ps2x.fxc @@ -0,0 +1,45 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// +// paired with "vertexlit_and_unlit_generic_vs##" + +// STATIC: "VERTEXALPHA" "0..1" +#include "common_fog_ps_fxc.h" + +#include "common_ps_fxc.h" +#include "shader_constant_register_map.h" + +sampler TexSampler : register( s0 ); + +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT ); +const float4 g_FogTweakParams : register( c0 ); +#define g_fFogExponentTweak g_FogTweakParams.x +#define g_fFogScaleTweak g_FogTweakParams.y + +struct PS_INPUT +{ + HALF2 baseTexCoord : TEXCOORD0; // Base texture coordinate + + float4 worldPos_projPosZ : TEXCOORD1; // Necessary for pixel fog + + float4 color : COLOR1; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float4 result = tex2D( TexSampler, i.baseTexCoord ); + + // Blend towards grey based on alpha + float flFactor = 1.0; +#if VERTEXALPHA + flFactor *= i.color.w; +#endif + result.xyz = lerp( float3( 0.5, 0.5, 0.5 ), result.xyz, flFactor ); + + // Since we're blending with a mod2x, we need to compensate with this hack + // NOTE: If the fog color (not fog density) is extremely dark, this can makes some decals seem + // a little transparent, but it's better than not doing this + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos_SpecExponent.xyz, i.worldPos_projPosZ.xyz, i.worldPos_projPosZ.w ); + fogFactor = pow( saturate( g_fFogScaleTweak * fogFactor ), g_fFogExponentTweak ); + + return FinalOutput( result, fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_NONE ); +} diff --git a/materialsystem/stdshaders/decalmodulate_vs20.fxc b/materialsystem/stdshaders/decalmodulate_vs20.fxc new file mode 100644 index 00000000..979209a2 --- /dev/null +++ b/materialsystem/stdshaders/decalmodulate_vs20.fxc @@ -0,0 +1,143 @@ +// based on vertexlit_and_unlit_generic_vs20.fxc +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "VERTEXCOLOR" "0..1" +// STATIC: "LIGHTING_PREVIEW" "0..1" [PC] +// STATIC: "LIGHTING_PREVIEW" "0..0" [XBOX] + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +#include "common_fog_vs_fxc.h" +// DYNAMIC: "SKINNING" "0..0" [vs20] +// DYNAMIC: "SKINNING" "0..1" [vs30] + +// DYNAMIC: "MORPHING" "0..1" [vs30] [ = pShaderAPI->IsHWMorphingEnabled() ] + +#include "common_vs_fxc.h" + +static const bool g_bSkinning = SKINNING ? true : false; +static const int g_FogType = DOWATERFOG; +static const bool g_bVertexColor = VERTEXCOLOR ? true : false; +#if ( defined( SHADER_MODEL_VS_3_0 ) && MORPHING ) + #define DECALOFFSET 1 +#else + #define DECALOFFSET 0 +#endif + +const float4 cBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_0 ); + +#ifdef SHADER_MODEL_VS_3_0 +// NOTE: cMorphTargetTextureDim.xy = target dimensions, +// cMorphTargetTextureDim.z = 4tuples/morph +const float3 cMorphTargetTextureDim : register( SHADER_SPECIFIC_CONST_10 ); +const float4 cMorphSubrect : register( SHADER_SPECIFIC_CONST_11 ); +sampler2D morphSampler : register( D3DVERTEXTEXTURESAMPLER0, s0 ); +#endif + +struct VS_INPUT +{ + // This is all of the stuff that we ever use. + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vNormal : NORMAL; + float4 vColor : COLOR0; + float3 vSpecular : COLOR1; + // make these float2's and stick the [n n 0 1] in the dot math. + float4 vTexCoord0 : TEXCOORD0; + float4 vTexCoord1 : TEXCOORD1; + float4 vTexCoord2 : TEXCOORD2; + float4 vTexCoord3 : TEXCOORD3; + + // Position and normal/tangent deltas + float3 vPosFlex : POSITION1; + float3 vNormalFlex : NORMAL1; +#ifdef SHADER_MODEL_VS_3_0 + float vVertexID : POSITION2; +#endif +}; + + +struct VS_OUTPUT +{ + float4 projPos : POSITION; // Projection-space position +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + float fog : FOG; +#endif + + HALF2 baseTexCoord : TEXCOORD0; // Base texture coordinate + float4 worldPos_ProjPosZ : TEXCOORD1; + float4 color : COLOR1; // Vertex color (from lighting or unlit) +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float4 vPosition = v.vPos; + float3 vNormal = 0; + if ( LIGHTING_PREVIEW || DECALOFFSET ) + { + // The vertex only contains valid normals if they are actually needed (fetching them when absent makes D3D complain) + DecompressVertex_Normal( v.vNormal, vNormal ); + } + +#if !defined( SHADER_MODEL_VS_3_0 ) || !MORPHING + ApplyMorph( v.vPosFlex, v.vNormalFlex, vPosition.xyz, vNormal ); +#else + ApplyMorph( morphSampler, cMorphTargetTextureDim, cMorphSubrect, + v.vVertexID, v.vTexCoord2, vPosition.xyz, vNormal ); +#endif + + // Perform skinning + float3 worldNormal, worldPos; + SkinPositionAndNormal( + g_bSkinning, + vPosition, vNormal, + v.vBoneWeights, v.vBoneIndices, + worldPos, worldNormal ); + + if ( !g_bVertexColor ) + { + worldNormal = normalize( worldNormal ); + } + +#if defined( SHADER_MODEL_VS_3_0 ) && MORPHING + // Avoid z precision errors + worldPos += worldNormal * 0.05f * v.vTexCoord2.z; +#endif + + // Transform into projection space + float4 projPos = mul( float4( worldPos, 1 ), cViewProj ); + o.projPos = projPos; + +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + o.fog = CalcFixedFunctionFog( worldPos, g_FogType ); +#endif + + o.worldPos_ProjPosZ.xyz = worldPos.xyz; + o.worldPos_ProjPosZ.w = projPos.z; + + if ( g_bVertexColor ) + { + // Assume that this is unlitgeneric if you are using vertex color. + o.color.rgb = GammaToLinear( v.vColor.rgb ); + o.color.a = v.vColor.a; + } + else + { + o.color = float4( 1.0f, 1.0f, 1.0f, 1.0f ); + } + + // Base texture coordinates + o.baseTexCoord.x = dot( v.vTexCoord0, cBaseTexCoordTransform[0] ); + o.baseTexCoord.y = dot( v.vTexCoord0, cBaseTexCoordTransform[1] ); + +#if LIGHTING_PREVIEW + float dot=0.5+0.5*worldNormal*float3(0.7071,0.7071,0); + o.color.xyz=float3(dot,dot,dot); +#endif + + return o; +} + + diff --git a/materialsystem/stdshaders/depth_of_field_ps20b.fxc b/materialsystem/stdshaders/depth_of_field_ps20b.fxc new file mode 100644 index 00000000..e2778a9c --- /dev/null +++ b/materialsystem/stdshaders/depth_of_field_ps20b.fxc @@ -0,0 +1,137 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// DYNAMIC: "QUALITY" "0..3" + +// Includes ======================================================================================= +#include "common_ps_fxc.h" + +// Texture Samplers =============================================================================== +sampler g_tFullFB : register( s0 ); +sampler g_tSmallFB : register( s1 ); + +// Shaders Constants and Globals ================================================================== +float4 g_vDists : register( c0 ); +#define g_flNearBlurDist g_vDists.x +#define g_flNearFocusDist g_vDists.y +#define g_flFarFocusDist g_vDists.z +#define g_flFarBlurDist g_vDists.w + +float3 g_vBlurAmounts : register( c1 ); +#define g_flMaxBlurRadius g_vBlurAmounts.x +#define g_flNearBlurStrength g_vBlurAmounts.y +#define g_flFarBlurStrength g_vBlurAmounts.z + +float3 g_vNearFarDists : register( c2 ); +#define g_flNearPlaneDist g_vNearFarDists.x +#define g_flFarPlaneDist g_vNearFarDists.y +#define g_flDepthConv g_vNearFarDists.z + +float4 g_vMagicConsts : register( c3 ); + +#if ( QUALITY == 0 ) + #define NUM_SAMPLES 8 // These must match the C code +#elif ( QUALITY == 1 ) + #define NUM_SAMPLES 16 +#elif ( QUALITY == 2 ) + #define NUM_SAMPLES 16 +#elif ( QUALITY == 3 ) + #define NUM_SAMPLES 32 +#endif + +float4 g_vPoisson[ NUM_SAMPLES/2 ] : register( c4 ); + +// Interpolated values ============================================================================ +struct PS_INPUT +{ + float2 vUv0 : TEXCOORD0; +}; + +float DestAlphaDepthToViewSpaceDepth( float flDepth ) +{ + return g_flDepthConv * flDepth + g_flNearPlaneDist; +} + +// returns blur radius from depth as a fraction of max_blur. +float BlurAmountFromDepth( float flDestAlphaDepth ) +{ + /* + dist = DestAlphaDepthToViewSpaceDepth( flDestAlphaDepth ); + float flBlur = max( g_flNearBlurStrength * saturate( (flDestAlphaDepth - g_flNearFocusDist) / ( g_flNearBlurDist - g_flNearFocusDist ) ), + g_flFarBlurStrength * saturate( (flDestAlphaDepth - g_flFarFocusDist) / ( g_flFarBlurDist - g_flFarFocusDist ) ) ); + */ + + // A more optimized version that concatenates the math above and the one in DestAlphaDepthToViewSpaceDepth to a single muladd + float flBlur = max( g_flNearBlurStrength * saturate( g_vMagicConsts.x * flDestAlphaDepth + g_vMagicConsts.y ), + g_flFarBlurStrength * saturate( g_vMagicConsts.z * flDestAlphaDepth + g_vMagicConsts.w ) ); + return flBlur; +} + +float BlurRadiusFromDepth( float flDepth ) +{ + return g_flMaxBlurRadius * BlurAmountFromDepth( flDepth ); +} + +float4 ComputeTap( float flCenterDepth, float flCenterBlurRadius, float2 vUV, float2 vPoisson ) +{ + float4 cTapSmall; + float4 cTap; + float2 vPoissonUV = vUV.xy + flCenterBlurRadius * vPoisson.xy; + + cTapSmall = tex2D( g_tSmallFB, vPoissonUV.xy ); + cTap = tex2D( g_tFullFB, vPoissonUV.xy ); + + float flTapBlur = BlurAmountFromDepth( cTap.a ); // Maybe 50/50 mix between low and high here? + + cTap = lerp( cTap, cTapSmall, saturate( 2.2 * flTapBlur ) ); // TODO: tweak blur amount. + float flLerpedTapBlur = BlurAmountFromDepth( cTap.a ); + + float weight = ( cTap.a >= flCenterDepth ) ? 1.0 : ( flLerpedTapBlur*flLerpedTapBlur ); + return float4( cTap.rgb, 1 ) * weight; +} + +float4 ComputeTapHQ( float flCenterDepth, float flCenterBlurRadius, float2 vUV, float2 vPoisson ) +{ + float4 cTap; + + cTap = tex2D( g_tFullFB, vUV.xy + flCenterBlurRadius * vPoisson.xy ); + float flTapBlur = BlurAmountFromDepth( cTap.a ); + float weight = ( cTap.a >= flCenterDepth ) ? 1.0 : ( flTapBlur * flTapBlur ); + return float4( cTap.rgb, 1 ) * weight; +} + +// Main =========================================================================================== +float4 main( PS_INPUT i ) : COLOR +{ + // TODO: BETTER DOWNSAMPLE THAT TAKES DEPTH INTO ACCOUNT? + + float4 cOut = { 0, 0, 0, 0 }; + float4 cCenterTap = tex2D( g_tFullFB, i.vUv0 ); + float flCenterBlurRadius = BlurRadiusFromDepth( cCenterTap.a ); // circle of confusion radius for current pixel + cCenterTap.a -= 0.001; // z-bias to avoid strange banding artifact on almost orthogonal walls + +#if ( QUALITY < 2 ) + // ATI's Ruby1-style algorithm + for ( int t = 0; t < NUM_SAMPLES/2; t++ ) + { + cOut.rgba += ComputeTap( cCenterTap.a, flCenterBlurRadius, i.vUv0, g_vPoisson[t].xy ); + cOut.rgba += ComputeTap( cCenterTap.a, flCenterBlurRadius, i.vUv0, g_vPoisson[t].wz ); + } +#else + // Less fancy, with less fetches per tap and less math. Needs more samples to look smooth. + cOut = cCenterTap; + cOut.a = 1.0; // Use the center sample we just fetched + for ( int t = 0; t < NUM_SAMPLES/2; t++ ) + { + cOut.rgba += ComputeTapHQ( cCenterTap.a, flCenterBlurRadius, i.vUv0, g_vPoisson[t].xy ); + cOut.rgba += ComputeTapHQ( cCenterTap.a, flCenterBlurRadius, i.vUv0, g_vPoisson[t].wz ); + } +#endif + //cOut.rgb = cOut.a / float(NUM_SAMPLES+1); + //cOut = lerp( tex2D( g_tFullFB, i.vUv0 ), tex2D( g_tSmallFB, i.vUv0 ).aaaa, 0.5 ); + if ( cOut.a > 0.0 ) + cOut.rgba /= cOut.a; + else + cOut.rgba = cCenterTap.rgba; + + return cOut; +} diff --git a/materialsystem/stdshaders/depth_of_field_vs20.fxc b/materialsystem/stdshaders/depth_of_field_vs20.fxc new file mode 100644 index 00000000..b8a86977 --- /dev/null +++ b/materialsystem/stdshaders/depth_of_field_vs20.fxc @@ -0,0 +1,29 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// Includes ======================================================================================= +#include "common_vs_fxc.h" + +// Input values =================================================================================== +struct VS_INPUT +{ + float3 vPos : POSITION; + float2 vBaseTexCoord : TEXCOORD0; +}; + +// Interpolated values ============================================================================ +struct VS_OUTPUT +{ + float4 projPos : POSITION; + float2 vUv0 : TEXCOORD0; +}; + +// Main =========================================================================================== +VS_OUTPUT main( const VS_INPUT i ) +{ + VS_OUTPUT o; + + o.projPos.xyzw = float4( i.vPos.xyz, 1.0f ); + o.vUv0.xy = i.vBaseTexCoord.xy; + + return o; +} diff --git a/materialsystem/stdshaders/depthtodestalpha_ps20b.fxc b/materialsystem/stdshaders/depthtodestalpha_ps20b.fxc new file mode 100644 index 00000000..384c78fe --- /dev/null +++ b/materialsystem/stdshaders/depthtodestalpha_ps20b.fxc @@ -0,0 +1,11 @@ +#include "common_ps_fxc.h" + +struct PS_INPUT +{ + float projPosZ : TEXCOORD0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + return FinalOutput( float4( 0, 0, 0, 1.0f ), 0.0f, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE, true, i.projPosZ ); +} diff --git a/materialsystem/stdshaders/depthtodestalpha_vs20.fxc b/materialsystem/stdshaders/depthtodestalpha_vs20.fxc new file mode 100644 index 00000000..4445d438 --- /dev/null +++ b/materialsystem/stdshaders/depthtodestalpha_vs20.fxc @@ -0,0 +1,23 @@ +#include "common_vs_fxc.h" + +struct VS_INPUT +{ + float4 vPos : POSITION; +}; + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; + float projPosZ : TEXCOORD0; +}; + + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + o.vProjPos = mul( v.vPos, cModelViewProj ); + o.projPosZ = o.vProjPos.z; + + return o; +} diff --git a/materialsystem/stdshaders/depthwrite.cpp b/materialsystem/stdshaders/depthwrite.cpp new file mode 100644 index 00000000..b05403a1 --- /dev/null +++ b/materialsystem/stdshaders/depthwrite.cpp @@ -0,0 +1,290 @@ +//========= Copyright © 1996-2007, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" +#include "convar.h" + +#include "depthwrite_ps20.inc" +#include "depthwrite_ps20b.inc" +#include "depthwrite_vs20.inc" + +#if !defined( _X360 ) +#include "depthwrite_ps30.inc" +#include "depthwrite_vs30.inc" +#endif + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + +static ConVar mat_displacementmap( "mat_displacementmap", "1", FCVAR_CHEAT ); + +BEGIN_VS_SHADER_FLAGS( DepthWrite, "Help for Depth Write", SHADER_NOT_EDITABLE ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( ALPHATESTREFERENCE, SHADER_PARAM_TYPE_FLOAT, "", "Alpha reference value" ) + SHADER_PARAM( DISPLACEMENTMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "Displacement map" ) + SHADER_PARAM( DISPLACEMENTWRINKLE, SHADER_PARAM_TYPE_BOOL, "0", "Displacement map contains wrinkle displacements") + + // vertexlitgeneric tree sway animation control + SHADER_PARAM( TREESWAY, SHADER_PARAM_TYPE_INTEGER, "0", "" ); + SHADER_PARAM( TREESWAYHEIGHT, SHADER_PARAM_TYPE_FLOAT, "1000", "" ); + SHADER_PARAM( TREESWAYSTARTHEIGHT, SHADER_PARAM_TYPE_FLOAT, "0.2", "" ); + SHADER_PARAM( TREESWAYRADIUS, SHADER_PARAM_TYPE_FLOAT, "300", "" ); + SHADER_PARAM( TREESWAYSTARTRADIUS, SHADER_PARAM_TYPE_FLOAT, "0.1", "" ); + SHADER_PARAM( TREESWAYSPEED, SHADER_PARAM_TYPE_FLOAT, "1", "" ); + SHADER_PARAM( TREESWAYSPEEDHIGHWINDMULTIPLIER, SHADER_PARAM_TYPE_FLOAT, "2", "" ); + SHADER_PARAM( TREESWAYSTRENGTH, SHADER_PARAM_TYPE_FLOAT, "10", "" ); + SHADER_PARAM( TREESWAYSCRUMBLESPEED, SHADER_PARAM_TYPE_FLOAT, "0.1", "" ); + SHADER_PARAM( TREESWAYSCRUMBLESTRENGTH, SHADER_PARAM_TYPE_FLOAT, "0.1", "" ); + SHADER_PARAM( TREESWAYSCRUMBLEFREQUENCY, SHADER_PARAM_TYPE_FLOAT, "0.1", "" ); + SHADER_PARAM( TREESWAYFALLOFFEXP, SHADER_PARAM_TYPE_FLOAT, "1.5", "" ); + SHADER_PARAM( TREESWAYSCRUMBLEFALLOFFEXP, SHADER_PARAM_TYPE_FLOAT, "1.0", "" ); + SHADER_PARAM( TREESWAYSPEEDLERPSTART, SHADER_PARAM_TYPE_FLOAT, "3", "" ); + SHADER_PARAM( TREESWAYSPEEDLERPEND, SHADER_PARAM_TYPE_FLOAT, "6", "" ); + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + if ( params[DISPLACEMENTMAP]->IsDefined() ) + { + LoadTexture( DISPLACEMENTMAP ); + } + } + + SHADER_DRAW + { + bool bAlphaClip = IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ); + int nTreeSwayMode = GetIntParam( TREESWAY, params, 0 ); + nTreeSwayMode = clamp( nTreeSwayMode, 0, 2 ); + bool bHasDisplacement = params[DISPLACEMENTMAP]->IsTexture(); +#if !defined( PLATFORM_X360 ) + bool bHasDisplacementWrinkles = params[DISPLACEMENTWRINKLE]->GetIntValue() != 0; +#endif + + SHADOW_STATE + { + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + // Bias primitives when rendering into shadow map so we get slope-scaled depth bias + // rather than having to apply a constant bias in the filtering shader later + pShaderShadow->EnablePolyOffset( SHADER_POLYOFFSET_SHADOW_BIAS ); + + // Turn off writes to color buffer since we always sample shadows from the DEPTH texture later + // This gives us double-speed fill when rendering INTO the shadow map + pShaderShadow->EnableColorWrites( false ); + pShaderShadow->EnableAlphaWrites( false ); + + // Don't backface cull unless alpha clipping, since this can cause artifacts when the + // geometry is clipped by the flashlight near plane + // If a material was already marked nocull, don't cull it + pShaderShadow->EnableCulling( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) && !IS_FLAG_SET(MATERIAL_VAR_NOCULL) ); + + + + if ( bHasDisplacement && IsPC() && g_pHardwareConfig->HasFastVertexTextures() ) + { + pShaderShadow->EnableVertexTexture( SHADER_VERTEXTEXTURE_SAMPLER2, true ); + } + + + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_STATIC_VERTEX_SHADER( depthwrite_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( ONLY_PROJECT_POSITION, !bAlphaClip && IsX360() ); //360 needs to know if it *shouldn't* output texture coordinates to avoid shader patches + SET_STATIC_VERTEX_SHADER_COMBO( TREESWAY, nTreeSwayMode ); + SET_STATIC_VERTEX_SHADER( depthwrite_vs20 ); + + if( bAlphaClip ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( depthwrite_ps20b ); + SET_STATIC_PIXEL_SHADER( depthwrite_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( depthwrite_ps20 ); + SET_STATIC_PIXEL_SHADER( depthwrite_ps20 ); + } + } + } +#ifndef _X360 + else + { + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_TESSELLATION ); + + DECLARE_STATIC_VERTEX_SHADER( depthwrite_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( ONLY_PROJECT_POSITION, 0 ); //360 only combo, and this is a PC path + SET_STATIC_VERTEX_SHADER_COMBO( TREESWAY, nTreeSwayMode ); + SET_STATIC_VERTEX_SHADER( depthwrite_vs30 ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); // irrelevant, since we just need alpha + + DECLARE_STATIC_PIXEL_SHADER( depthwrite_ps30 ); + SET_STATIC_PIXEL_SHADER( depthwrite_ps30 ); + } +#endif + } + DYNAMIC_STATE + { + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_DYNAMIC_VERTEX_SHADER( depthwrite_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, ( int )vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( TESSELLATION, 0 ); + SET_DYNAMIC_VERTEX_SHADER( depthwrite_vs20 ); + + if ( bAlphaClip ) + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + + float vAlphaThreshold[4] = {0.7f, 0.7f, 0.7f, 0.7f}; + if ( ALPHATESTREFERENCE != -1 && ( params[ALPHATESTREFERENCE]->GetFloatValue() > 0.0f ) ) + { + vAlphaThreshold[0] = vAlphaThreshold[1] = vAlphaThreshold[2] = vAlphaThreshold[3] = params[ALPHATESTREFERENCE]->GetFloatValue(); + } + + pShaderAPI->SetPixelShaderConstant( 0, vAlphaThreshold, 1 ); + } + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( depthwrite_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( ALPHACLIP, bAlphaClip ); + SET_DYNAMIC_PIXEL_SHADER( depthwrite_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( depthwrite_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( ALPHACLIP, bAlphaClip ); + SET_DYNAMIC_PIXEL_SHADER( depthwrite_ps20 ); + } + } +#ifndef _X360 + else // 3.0 shader case (PC only) + { + TessellationMode_t nTessellationMode = pShaderAPI->GetTessellationMode(); + if ( nTessellationMode != TESSELLATION_MODE_DISABLED ) + { + pShaderAPI->BindStandardVertexTexture( SHADER_VERTEXTEXTURE_SAMPLER1, TEXTURE_SUBDIVISION_PATCHES ); + + float vSubDControls[4] = { 1.0f/pShaderAPI->GetSubDHeight(), + bHasDisplacement && mat_displacementmap.GetBool() ? 1.0f : 0.0f, + bHasDisplacementWrinkles && mat_displacementmap.GetBool() ? 1.0f : 0.0f, 0.0f }; + + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_8, vSubDControls ); + + if( bHasDisplacement ) + { + BindVertexTexture( SHADER_VERTEXTEXTURE_SAMPLER2, DISPLACEMENTMAP ); + } + else + { + pShaderAPI->BindStandardVertexTexture( SHADER_VERTEXTEXTURE_SAMPLER2, TEXTURE_BLACK ); + } + + // Currently, tessellation is mutually exclusive with any kind of GPU-side skinning, morphing or vertex compression + Assert( !pShaderAPI->IsHWMorphingEnabled() ); + Assert( pShaderAPI->GetCurrentNumBones() == 0 ); + Assert( vertexCompression == 0); + } + + SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, SHADER_VERTEXTEXTURE_SAMPLER0 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( depthwrite_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, ( pShaderAPI->GetCurrentNumBones() > 0 ) && ( nTessellationMode == TESSELLATION_MODE_DISABLED ) ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression && ( nTessellationMode == TESSELLATION_MODE_DISABLED ) ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( TESSELLATION, nTessellationMode ); + SET_DYNAMIC_VERTEX_SHADER( depthwrite_vs30 ); + + if ( bAlphaClip ) + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + + float vAlphaThreshold[4] = {0.7f, 0.7f, 0.7f, 0.7f}; + if ( ALPHATESTREFERENCE != -1 && ( params[ALPHATESTREFERENCE]->GetFloatValue() > 0.0f ) ) + { + vAlphaThreshold[0] = vAlphaThreshold[1] = vAlphaThreshold[2] = vAlphaThreshold[3] = params[ALPHATESTREFERENCE]->GetFloatValue(); + } + + pShaderAPI->SetPixelShaderConstant( 0, vAlphaThreshold, 1 ); + } + + DECLARE_DYNAMIC_PIXEL_SHADER( depthwrite_ps30 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( ALPHACLIP, bAlphaClip ); + SET_DYNAMIC_PIXEL_SHADER( depthwrite_ps30 ); + } +#endif + + if ( nTreeSwayMode != 0 ) + { + float flParams[4]; + + flParams[0] = pShaderAPI->CurrentTime(); + Vector windDir = pShaderAPI->GetVectorRenderingParameter( VECTOR_RENDERPARM_WIND_DIRECTION ); + flParams[1] = windDir.x; + flParams[2] = windDir.y; + flParams[3] = 0.0f; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, flParams ); + + flParams[0] = GetFloatParam( TREESWAYSCRUMBLEFALLOFFEXP, params, 1.0f ); + flParams[1] = GetFloatParam( TREESWAYFALLOFFEXP, params, 1.0f ); + flParams[2] = GetFloatParam( TREESWAYSCRUMBLESPEED, params, 3.0f ); + flParams[3] = GetFloatParam( TREESWAYSPEEDHIGHWINDMULTIPLIER, params, 2.0f ); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, flParams ); + + flParams[0] = GetFloatParam( TREESWAYHEIGHT, params, 1000.0f ); + flParams[1] = GetFloatParam( TREESWAYSTARTHEIGHT, params, 0.1f ); + flParams[2] = GetFloatParam( TREESWAYRADIUS, params, 300.0f ); + flParams[3] = GetFloatParam( TREESWAYSTARTRADIUS, params, 0.2f ); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, flParams ); + + flParams[0] = GetFloatParam( TREESWAYSPEED, params, 1.0f ); + flParams[1] = GetFloatParam( TREESWAYSTRENGTH, params, 10.0f ); + flParams[2] = GetFloatParam( TREESWAYSCRUMBLEFREQUENCY, params, 12.0f ); + flParams[3] = GetFloatParam( TREESWAYSCRUMBLESTRENGTH, params, 10.0f ); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_5, flParams ); + + flParams[0] = GetFloatParam( TREESWAYSPEEDLERPSTART, params, 3.0f ); + flParams[1] = GetFloatParam( TREESWAYSPEEDLERPEND, params, 6.0f ); + flParams[2] = 0.0f; + flParams[3] = 0.0f; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_9, flParams ); + + } + + } // DYNAMIC_STATE + + Draw( ); + } +END_SHADER diff --git a/materialsystem/stdshaders/depthwrite_ps2x.fxc b/materialsystem/stdshaders/depthwrite_ps2x.fxc new file mode 100644 index 00000000..ac08555a --- /dev/null +++ b/materialsystem/stdshaders/depthwrite_ps2x.fxc @@ -0,0 +1,24 @@ +// DYNAMIC: "ALPHACLIP" "0..1" + +const float g_AlphaThreshold : register( c0 ); + +struct PS_INPUT +{ +#if ALPHACLIP + float2 texCoord0 : TEXCOORD0; +#endif +}; + +sampler BaseTextureSampler : register( s0 ); + +float4 main( PS_INPUT i ) : COLOR +{ + float4 color = float4( 1, 0, 0, 1 ); // opaque alpha....the color doesn't matter for this shader + +#if ALPHACLIP + color = tex2D( BaseTextureSampler, i.texCoord0 ); + clip( color.a - g_AlphaThreshold ); +#endif + + return color; +} diff --git a/materialsystem/stdshaders/depthwrite_vs20.fxc b/materialsystem/stdshaders/depthwrite_vs20.fxc new file mode 100644 index 00000000..d9d2fd7b --- /dev/null +++ b/materialsystem/stdshaders/depthwrite_vs20.fxc @@ -0,0 +1,145 @@ +// STATIC: "ONLY_PROJECT_POSITION" "0..1" [XBOX] +// STATIC: "ONLY_PROJECT_POSITION" "0..0" [PC] +// STATIC: "TREESWAY" "0..2" + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "SKINNING" "0..1" + +// DYNAMIC: "MORPHING" "0..1" [vs30] [ = pShaderAPI->IsHWMorphingEnabled() ] +// DYNAMIC: "TESSELLATION" "0..2" [vs30] [PC] +// DYNAMIC: "TESSELLATION" "0..0" [XBOX] +// DYNAMIC: "TESSELLATION" "0..0" [vs20] [PC] + +// SKIP: ( $MORPHING || $SKINNING || $COMPRESSED_VERTS ) && $TESSELLATION + +#include "common_vs_fxc.h" + +static const bool g_bSkinning = SKINNING ? true : false; + +#ifdef SHADER_MODEL_VS_3_0 +// NOTE: cMorphTargetTextureDim.xy = target dimensions, +// cMorphTargetTextureDim.z = 4tuples/morph +const float3 cMorphTargetTextureDim : register( SHADER_SPECIFIC_CONST_6 ); +const float4 cMorphSubrect : register( SHADER_SPECIFIC_CONST_7 ); + +sampler2D morphSampler : register( D3DVERTEXTEXTURESAMPLER0, s0 ); +#endif + +#if ( TREESWAY ) + const float4 g_vTreeSwayParams0 : register( SHADER_SPECIFIC_CONST_2 ); + const float4 g_vTreeSwayParams1 : register( SHADER_SPECIFIC_CONST_3 ); + const float4 g_vTreeSwayParams2 : register( SHADER_SPECIFIC_CONST_4 ); + const float4 g_vTreeSwayParams3 : register( SHADER_SPECIFIC_CONST_5 ); + const float4 g_vTreeSwayParams4 : register( SHADER_SPECIFIC_CONST_9 ); + + #define g_flTime g_vTreeSwayParams0.x + #define g_vWindDir g_vTreeSwayParams0.yz + + #define g_flScrumbleFalloffCurve g_vTreeSwayParams1.x + #define g_flSwayFalloffCurve g_vTreeSwayParams1.y + #define g_flScrumbleSpeed g_vTreeSwayParams1.z + #define g_flFastSwaySpeedScale g_vTreeSwayParams1.w + + + #define g_flHeight g_vTreeSwayParams2.x + #define g_flStartHeight g_vTreeSwayParams2.y + #define g_flRadius g_vTreeSwayParams2.z + #define g_flStartRadius g_vTreeSwayParams2.w + + #define g_flSwaySpeed g_vTreeSwayParams3.x + #define g_flSwayIntensity g_vTreeSwayParams3.y + #define g_flScrumbleWaveCount g_vTreeSwayParams3.z + #define g_flScrumbleIntensity g_vTreeSwayParams3.w + + #define g_flWindSpeedLerpStart g_vTreeSwayParams4.x + #define g_flWindSpeedLerpEnd g_vTreeSwayParams4.y +#endif + +#if TESSELLATION + +#include "tessellation_vs_fxc.h" + +const float4 g_SubDControls : register( SHADER_SPECIFIC_CONST_8 ); +sampler2D BezierSampler : register( s1 ); +sampler2D DispSampler : register( s2 ); +// VS_INPUT defined in header + +#else // no TESSELLATION + +struct VS_INPUT +{ + float4 vPos : POSITION; + float2 vTexCoord : TEXCOORD0; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + // Position delta stream + float3 vPosFlex : POSITION1; +#ifdef SHADER_MODEL_VS_3_0 + float vVertexID : POSITION2; +#endif +}; + +#endif // TESSELLATION + +struct VS_OUTPUT +{ + float4 projPos : POSITION; + +#if (ONLY_PROJECT_POSITION == 0) //360 sometimes runs without the pixel shader component, but has to patch this output if it does. + float2 texCoord : TEXCOORD0; +#endif +}; + +#include "tree_sway.h" + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + float3 worldPos; + + #if ( TESSELLATION ) + { + float2 detailUV, baseUV; + float3 worldNormal, worldTangentS, worldTangentT; + EvaluateSubdivisionSurface( v, g_SubDControls.x, g_SubDControls.y, g_SubDControls.z, BezierSampler, DispSampler, worldNormal, worldPos, baseUV, detailUV ); + + #if (ONLY_PROJECT_POSITION == 0) + { + o.texCoord = baseUV; + } + #endif + } + #else // not tessellating + { + float4 vPosition = v.vPos; + + #if ( !defined( SHADER_MODEL_VS_3_0 ) || !MORPHING ) + { + ApplyMorph( v.vPosFlex, vPosition.xyz ); + } + #else + { + ApplyMorph( morphSampler, cMorphTargetTextureDim, cMorphSubrect, v.vVertexID, float3(0, 0, 0), vPosition.xyz ); + } + #endif + + #if ( TREESWAY ) + { + vPosition.xyz = ComputeTreeSway( vPosition.xyz, g_flTime ); + } + #endif + + SkinPosition( g_bSkinning, vPosition, v.vBoneWeights, v.vBoneIndices, worldPos ); + + #if ( ONLY_PROJECT_POSITION == 0 ) + { + o.texCoord = v.vTexCoord; + } + #endif + } + #endif + + o.projPos = mul( float4( worldPos, 1.0f ), cViewProj ); + + return o; +} diff --git a/materialsystem/stdshaders/detail.cpp b/materialsystem/stdshaders/detail.cpp new file mode 100644 index 00000000..4d11a0ca --- /dev/null +++ b/materialsystem/stdshaders/detail.cpp @@ -0,0 +1,37 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_VS_SHADER( Detail, "Help for Detail" ) + + BEGIN_SHADER_PARAMS + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS( MATERIAL_VAR_TRANSLUCENT ); + } + + SHADER_FALLBACK + { + return "UnlitGeneric"; + } + + SHADER_INIT + { + } + + SHADER_DRAW + { + } + +END_SHADER + diff --git a/materialsystem/stdshaders/downsample_nohdr.cpp b/materialsystem/stdshaders/downsample_nohdr.cpp new file mode 100644 index 00000000..0d0e85c1 --- /dev/null +++ b/materialsystem/stdshaders/downsample_nohdr.cpp @@ -0,0 +1,138 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "BaseVSShader.h" +#include "common_hlsl_cpp_consts.h" +#include "convar.h" + +#include "downsample_nohdr_ps20.inc" +#include "downsample_nohdr_ps20b.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +static ConVar r_bloomtintr( "r_bloomtintr", "0.3" ); +static ConVar r_bloomtintg( "r_bloomtintg", "0.59" ); +static ConVar r_bloomtintb( "r_bloomtintb", "0.11" ); +static ConVar r_bloomtintexponent( "r_bloomtintexponent", "2.2" ); + +BEGIN_VS_SHADER_FLAGS( Downsample_nohdr, "Help for Downsample_nohdr", SHADER_NOT_EDITABLE ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( BLOOMTYPE, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( BLOOMEXP, SHADER_PARAM_TYPE_FLOAT, "2.5", "" ) + SHADER_PARAM( BLOOMSATURATION, SHADER_PARAM_TYPE_FLOAT, "1.0", "" ) + SHADER_PARAM( BLOOMTINTENABLE, SHADER_PARAM_TYPE_INTEGER, "1", "" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_PARAM_FLOAT_IF_NOT_DEFINED( BLOOMEXP, 2.5f ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( BLOOMSATURATION, 1.0f ); + SET_PARAM_INT_IF_NOT_DEFINED( BLOOMTINTENABLE, 1 ); + + if ( !params[BLOOMTYPE]->IsDefined() ) + { + params[BLOOMTYPE]->SetIntValue( 0 ); + } + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + LoadTexture( BASETEXTURE ); + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableAlphaWrites( true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, false ); + pShaderShadow->EnableSRGBWrite( false ); + + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 1, 0, 0 ); + + pShaderShadow->SetVertexShader( "Downsample_vs20", 0 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( downsample_nohdr_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( BLOOMTYPE, params[BLOOMTYPE]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER( downsample_nohdr_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( downsample_nohdr_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( BLOOMTYPE, params[BLOOMTYPE]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER( downsample_nohdr_ps20 ); + } + } + + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, -1 ); + + int width, height; + pShaderAPI->GetBackBufferDimensions( width, height ); + + float v[4][4]; + float dX = 1.0f/width; + float dY = 1.0f/height; + + v[0][0] = .5*dX; + v[0][1] = .5*dY; + v[1][0] = 2.5*dX; + v[1][1] = .5*dY; + v[2][0] = .5*dX; + v[2][1] = 2.5*dY; + v[3][0] = 2.5*dX; + v[3][1] = 2.5*dY; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, &v[0][0], 4 ); + + pShaderAPI->SetVertexShaderIndex( 0 ); + + float flPixelShaderParams[4] = { r_bloomtintr.GetFloat(), + r_bloomtintg.GetFloat(), + r_bloomtintb.GetFloat(), + r_bloomtintexponent.GetFloat() }; + if ( params[ BLOOMTINTENABLE ]->GetIntValue() == 0 ) + { + flPixelShaderParams[0] = 1.0f; + flPixelShaderParams[1] = 1.0f; + flPixelShaderParams[2] = 1.0f; + flPixelShaderParams[3] = 1.0f; + } + pShaderAPI->SetPixelShaderConstant( 0, flPixelShaderParams, 1 ); + + float vPsConst1[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vPsConst1[0] = params[BLOOMEXP]->GetFloatValue(); + vPsConst1[1] = params[BLOOMSATURATION]->GetFloatValue(); + pShaderAPI->SetPixelShaderConstant( 1, vPsConst1, 1 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + int floatBackBuffer = ( ( g_pHardwareConfig->GetHDRType() == HDR_TYPE_FLOAT ) && !IsX360() ) ? 1 : 0; + + DECLARE_DYNAMIC_PIXEL_SHADER( downsample_nohdr_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLOAT_BACK_BUFFER, floatBackBuffer ); + SET_DYNAMIC_PIXEL_SHADER( downsample_nohdr_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( downsample_nohdr_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( downsample_nohdr_ps20 ); + } + } + Draw(); + } +END_SHADER diff --git a/materialsystem/stdshaders/downsample_nohdr_dx80.cpp b/materialsystem/stdshaders/downsample_nohdr_dx80.cpp new file mode 100644 index 00000000..86f2389d --- /dev/null +++ b/materialsystem/stdshaders/downsample_nohdr_dx80.cpp @@ -0,0 +1,77 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "BaseVSShader.h" +#include "common_hlsl_cpp_consts.h" +#include "ConVar.h" +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( Downsample_nohdr, Downsample_nohdr_DX80 ) + +BEGIN_VS_SHADER_FLAGS( Downsample_nohdr_DX80, "Help for Downsample_nohdr_DX80", SHADER_NOT_EDITABLE ) + + BEGIN_SHADER_PARAMS + END_SHADER_PARAMS + + SHADER_INIT + { + LoadTexture( BASETEXTURE ); + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableAlphaWrites( true ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 1, 0, 0 ); + + pShaderShadow->SetVertexShader( "Downsample_vs11", 0 ); + pShaderShadow->SetPixelShader( "Downsample_nohdr_ps11" ); + } + + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, -1 ); + BindTexture( SHADER_SAMPLER1, BASETEXTURE, -1 ); + BindTexture( SHADER_SAMPLER2, BASETEXTURE, -1 ); + BindTexture( SHADER_SAMPLER3, BASETEXTURE, -1 ); + + int width, height; + pShaderAPI->GetBackBufferDimensions( width, height ); + + float v[4][4]; + float dX = 1.0f/width; + float dY = 1.0f/height; + + v[0][0] = .5*dX; + v[0][1] = .5*dY; + v[1][0] = 2.5*dX; + v[1][1] = .5*dY; + v[2][0] = .5*dX; + v[2][1] = 2.5*dY; + v[3][0] = 2.5*dX; + v[3][1] = 2.5*dY; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, &v[0][0], 4 ); + + pShaderAPI->SetVertexShaderIndex( 0 ); + pShaderAPI->SetPixelShaderIndex( 0 ); + } + Draw(); + } +END_SHADER diff --git a/materialsystem/stdshaders/downsampledepth_extractnormal_ps2x.fxc b/materialsystem/stdshaders/downsampledepth_extractnormal_ps2x.fxc new file mode 100644 index 00000000..02a0e850 --- /dev/null +++ b/materialsystem/stdshaders/downsampledepth_extractnormal_ps2x.fxc @@ -0,0 +1,62 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +sampler g_sDepth : register( s0 ); +float4x4 g_mInvVP : register( c0 ); +float2 g_vInvScreenSize : register( c4 ); + +struct PS_INPUT +{ +#ifdef _X360 + float2 vPos : VPOS; +#else + float2 uv : TEXCOORD0; +#endif + +}; + +struct PSOutput +{ + float4 vColor : COLOR0; + float fDepth : DEPTH; +}; + +PSOutput main( PS_INPUT i) +{ +#ifdef _X360 + float2 vUV = 4.0 * i.vPos + 0.5; + vUV *= g_vInvScreenSize; +#else + float2 vUV = i.uv; +#endif + + float4 vDepths; + vDepths.x = tex2D( g_sDepth, vUV ); + vDepths.y = tex2D( g_sDepth, vUV + float2(g_vInvScreenSize.x, 0.0) ); + vDepths.z = tex2D( g_sDepth, vUV + float2(0.0, g_vInvScreenSize.y) ); + vDepths.w = tex2D( g_sDepth, vUV + g_vInvScreenSize ); + + // convert sample to world-space + float4 vClipPos; + vClipPos.xy = 2.0 * vUV.xy - 1.0; + vClipPos.y = -vClipPos.y; + vClipPos.z = 1.0 - vDepths.x; + vClipPos.w = 1.0; + float4 vWorldPos = mul( vClipPos, g_mInvVP ); + vWorldPos /= vWorldPos.w; + + // Derive normal from depth buffer. Ideally I'd compute a world space pos from vDepths.x, y, and z and then cross the deltas of that, + // but that's a lot of work. + float3 vNormal = cross( ddx(vWorldPos.xyz), ddy(vWorldPos.xyz) ); + + PSOutput o; + + // TODO: output normal + o.vColor = 1.0;//-vPos.x/320.0;//float4( 0.5 * vNormal + 0.5, 0.0 ); + + // get max depth + vDepths.xy = min( vDepths.xy, vDepths.zw ); + o.fDepth = min( vDepths.x, vDepths.y ); + //o.fDepth = dot( vDepths, float4( 0.25, 0.25, 0.25, 0.25 ) ); + + return o; +} diff --git a/materialsystem/stdshaders/emissive_scroll_blended_pass_helper.cpp b/materialsystem/stdshaders/emissive_scroll_blended_pass_helper.cpp new file mode 100644 index 00000000..d4511f1b --- /dev/null +++ b/materialsystem/stdshaders/emissive_scroll_blended_pass_helper.cpp @@ -0,0 +1,281 @@ +//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============// + +/* Example how to plug this into an existing shader: + + In the VMT: + // Emissive Scroll Pass + "$emissiveBlendEnabled" "1" // Enables effect + "$emissiveBlendTexture" "models/vortigaunt/vortigaunt_illum" + "$emissiveBlendBaseTexture" "Models/Vortigaunt/vortigaunt_blue" + "$emissiveBlendFlowTexture" "models/vortigaunt/vortigaunt_flow" + "$emissiveBlendTint" "[10 10 10]" + "$emissiveBlendStrength" "1.0" // Set by game code + "$emissiveBlendScrollVector" "[0.11 0.124]" + "Proxies" + { + "VortEmissive" // For setting $selfillumstrength + { + } + } + + #include "emissive_scroll_blended_pass_helper.h" + + In BEGIN_SHADER_PARAMS: + // Emissive Scroll Pass + SHADER_PARAM( EMISSIVEBLENDENABLED, SHADER_PARAM_TYPE_BOOL, "0", "Enable emissive blend pass" ) + SHADER_PARAM( EMISSIVEBLENDBASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "self-illumination map" ) + SHADER_PARAM( EMISSIVEBLENDSCROLLVECTOR, SHADER_PARAM_TYPE_VEC2, "[0.11 0.124]", "Emissive scroll vec" ) + SHADER_PARAM( EMISSIVEBLENDSTRENGTH, SHADER_PARAM_TYPE_FLOAT, "1.0", "Emissive blend strength" ) + SHADER_PARAM( EMISSIVEBLENDTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "self-illumination map" ) + SHADER_PARAM( EMISSIVEBLENDTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Self-illumination tint" ) + SHADER_PARAM( EMISSIVEBLENDFLOWTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "flow map" ) + + Add this above SHADER_INIT_PARAMS() + // Emissive Scroll Pass + void SetupVarsEmissiveScrollBlendedPass( EmissiveScrollBlendedPassVars_t &info ) + { + info.m_nBlendStrength = EMISSIVEBLENDSTRENGTH; + info.m_nBaseTexture = EMISSIVEBLENDBASETEXTURE; + info.m_nFlowTexture = EMISSIVEBLENDFLOWTEXTURE; + info.m_nEmissiveTexture = EMISSIVEBLENDTEXTURE; + info.m_nEmissiveTint = EMISSIVEBLENDTINT; + info.m_nEmissiveScrollVector = EMISSIVEBLENDSCROLLVECTOR; + } + + In SHADER_INIT_PARAMS() + // Emissive Scroll Pass + if ( !params[EMISSIVEBLENDENABLED]->IsDefined() ) + { + params[EMISSIVEBLENDENABLED]->SetIntValue( 0 ); + } + else if ( params[EMISSIVEBLENDENABLED]->GetIntValue() ) + { + EmissiveScrollBlendedPassVars_t info; + SetupVarsEmissiveScrollBlendedPass( info ); + InitParamsEmissiveScrollBlendedPass( this, params, pMaterialName, info ); + } + + In SHADER_INIT + // Emissive Scroll Pass + if ( params[EMISSIVEBLENDENABLED]->GetIntValue() ) + { + EmissiveScrollBlendedPassVars_t info; + SetupVarsEmissiveScrollBlendedPass( info ); + InitEmissiveScrollBlendedPass( this, params, info ); + } + + At the very end of SHADER_DRAW + // Emissive Scroll Pass + if ( params[EMISSIVEBLENDENABLED]->GetIntValue() ) + { + // If ( snapshotting ) or ( we need to draw this frame ) + if ( ( pShaderShadow != NULL ) || ( params[EMISSIVEBLENDSTRENGTH]->GetFloatValue() > 0.0f ) ) + { + EmissiveScrollBlendedPassVars_t info; + SetupVarsEmissiveScrollBlendedPass( info ); + DrawEmissiveScrollBlendedPass( this, params, pShaderAPI, pShaderShadow, info ); + } + else // We're not snapshotting and we don't need to draw this frame + { + // Skip this pass! + Draw( false ); + } + } + +==================================================================================================== */ + +#include "BaseVSShader.h" +#include "mathlib/VMatrix.h" +#include "emissive_scroll_blended_pass_helper.h" +#include "convar.h" + +// Auto generated inc files +#include "emissive_scroll_blended_pass_vs20.inc" +#include "emissive_scroll_blended_pass_ps20.inc" +#include "emissive_scroll_blended_pass_ps20b.inc" + +#ifndef _X360 +#include "emissive_scroll_blended_pass_vs30.inc" +#include "emissive_scroll_blended_pass_ps30.inc" +#endif + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +void InitParamsEmissiveScrollBlendedPass( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, EmissiveScrollBlendedPassVars_t &info ) +{ + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + + if ( ( info.m_nEmissiveScrollVector != -1 ) && ( !params[info.m_nEmissiveScrollVector]->IsDefined() ) ) + { + params[info.m_nEmissiveScrollVector]->SetVecValue( kDefaultEmissiveScrollVector, 4 ); + } + + if ( ( info.m_nBlendStrength != -1 ) && ( !params[info.m_nBlendStrength]->IsDefined() ) ) + { + params[info.m_nBlendStrength]->SetFloatValue( kDefaultEmissiveBlendStrength ); + } + + if ( ( info.m_nEmissiveTint != -1 ) && ( !params[info.m_nEmissiveTint]->IsDefined() ) ) + { + params[info.m_nEmissiveTint]->SetVecValue( kDefaultEmissiveTint, 4 ); + } + + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nTime, 0.0f ); +} + +void InitEmissiveScrollBlendedPass( CBaseVSShader *pShader, IMaterialVar** params, EmissiveScrollBlendedPassVars_t &info ) +{ + // Load textures + pShader->LoadTexture( info.m_nBaseTexture ); + pShader->LoadTexture( info.m_nFlowTexture ); + pShader->LoadTexture( info.m_nEmissiveTexture ); +} + +void DrawEmissiveScrollBlendedPass( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, EmissiveScrollBlendedPassVars_t &info, VertexCompressionType_t vertexCompression ) +{ + SHADOW_STATE + { + // Reset shadow state manually since we're drawing from two materials + pShader->SetInitialShadowState(); + + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + // Vertex Shader + DECLARE_STATIC_VERTEX_SHADER( emissive_scroll_blended_pass_vs20 ); + SET_STATIC_VERTEX_SHADER( emissive_scroll_blended_pass_vs20 ); + + // Pixel Shader + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( emissive_scroll_blended_pass_ps20b ); + SET_STATIC_PIXEL_SHADER( emissive_scroll_blended_pass_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( emissive_scroll_blended_pass_ps20 ); + SET_STATIC_PIXEL_SHADER( emissive_scroll_blended_pass_ps20 ); + } + } +#ifndef _X360 + else + { + // The vertex shader uses the vertex id stream + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + + DECLARE_STATIC_VERTEX_SHADER( emissive_scroll_blended_pass_vs30 ); + SET_STATIC_VERTEX_SHADER( emissive_scroll_blended_pass_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( emissive_scroll_blended_pass_ps30 ); + SET_STATIC_PIXEL_SHADER( emissive_scroll_blended_pass_ps30 ); + } +#endif + + // Textures + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, false ); // Flow texture not sRGB + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, true ); + pShaderShadow->EnableSRGBWrite( true ); + + // Blending + pShader->EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); + pShaderShadow->EnableAlphaWrites( false ); + } + DYNAMIC_STATE + { + // Reset render state manually since we're drawing from two materials + pShaderAPI->SetDefaultState(); + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + // Set Vertex Shader Combos + DECLARE_DYNAMIC_VERTEX_SHADER( emissive_scroll_blended_pass_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( emissive_scroll_blended_pass_vs20 ); + + // Set Vertex Shader Constants + // None? + + // Set Pixel Shader Combos + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( emissive_scroll_blended_pass_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( emissive_scroll_blended_pass_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( emissive_scroll_blended_pass_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( emissive_scroll_blended_pass_ps20 ); + } + } +#ifndef _X360 + else + { + pShader->SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, SHADER_VERTEXTEXTURE_SAMPLER0 ); + + // Set Vertex Shader Combos + DECLARE_DYNAMIC_VERTEX_SHADER( emissive_scroll_blended_pass_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( emissive_scroll_blended_pass_vs30 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( emissive_scroll_blended_pass_ps30 ); + SET_DYNAMIC_PIXEL_SHADER( emissive_scroll_blended_pass_ps30 ); + } +#endif + + // Bind textures + pShader->BindTexture( SHADER_SAMPLER0, info.m_nBaseTexture ); + pShader->BindTexture( SHADER_SAMPLER1, info.m_nFlowTexture ); + pShader->BindTexture( SHADER_SAMPLER2, info.m_nEmissiveTexture ); + + // Set Pixel Shader Constants + //float vConstZero[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + + // This brings in the electricity and the second base texture when the second base texture is present + float vPsConst0[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + if (1) + { + // Overall blend strength + vPsConst0[0] = IS_PARAM_DEFINED( info.m_nBlendStrength ) ? params[info.m_nBlendStrength]->GetFloatValue() : kDefaultEmissiveBlendStrength; + if ( vPsConst0[0] < 0.0f ) + vPsConst0[0] = 0.0f; + if ( vPsConst0[0] > 1.0f ) + vPsConst0[0] = 1.0f; + + // Time % 1000 for scrolling + vPsConst0[1] = IS_PARAM_DEFINED( info.m_nTime ) && params[info.m_nTime]->GetFloatValue() > 0.0f ? params[info.m_nTime]->GetFloatValue() : pShaderAPI->CurrentTime(); + vPsConst0[1] -= (float)( (int)( vPsConst0[1] / 1000.0f ) ) * 1000.0f; + + // Dest alpha value for warping mask - NOTE: If we want to use this, we have to modify the blending mode above! + //if ( ( params[info.m_nWarpParam]->GetFloatValue() > 0.0f ) && ( params[info.m_nWarpParam]->GetFloatValue() < 1.0f ) ) + // tmpVec[2] = 1.0f; + //else + // tmpVec[2] = 0.0f; + } + pShaderAPI->SetPixelShaderConstant( 0, vPsConst0, 1 ); + + // Scroll vector + pShaderAPI->SetPixelShaderConstant( 1, IS_PARAM_DEFINED( info.m_nEmissiveScrollVector ) ? params[info.m_nEmissiveScrollVector]->GetVecValue() : kDefaultEmissiveScrollVector, 1 ); + + // Self illum tint + pShaderAPI->SetPixelShaderConstant( 2, IS_PARAM_DEFINED( info.m_nEmissiveTint ) ? params[info.m_nEmissiveTint]->GetVecValue() : kDefaultEmissiveTint, 1 ); + } + pShader->Draw(); +} diff --git a/materialsystem/stdshaders/emissive_scroll_blended_pass_helper.h b/materialsystem/stdshaders/emissive_scroll_blended_pass_helper.h new file mode 100644 index 00000000..72ff3c06 --- /dev/null +++ b/materialsystem/stdshaders/emissive_scroll_blended_pass_helper.h @@ -0,0 +1,45 @@ +//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============// + +#ifndef EMISSIVE_SCROLL_BLENDED_PASS_HELPER_H +#define EMISSIVE_SCROLL_BLENDED_PASS_HELPER_H +#ifdef _WIN32 +#pragma once +#endif + +#include + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct EmissiveScrollBlendedPassVars_t +{ + EmissiveScrollBlendedPassVars_t() { memset( this, 0xFF, sizeof(EmissiveScrollBlendedPassVars_t) ); } + + int m_nBlendStrength; // Amount this layer is blended in globally + int m_nBaseTexture; + int m_nFlowTexture; + int m_nEmissiveTexture; + int m_nEmissiveTint; + int m_nEmissiveScrollVector; + int m_nTime; +}; + +// Default values (Arrays should only be vec[4]) +static const float kDefaultEmissiveBlendStrength = 0.0f; +static const float kDefaultEmissiveTint[4] = { 1.0f, 1.0f, 1.0f, 0.0f } ; +static const float kDefaultEmissiveScrollVector[4] = { 0.11f, 0.124f, 0.0f, 0.0f } ; + +void InitParamsEmissiveScrollBlendedPass( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, EmissiveScrollBlendedPassVars_t &info ); +void InitEmissiveScrollBlendedPass( CBaseVSShader *pShader, IMaterialVar** params, EmissiveScrollBlendedPassVars_t &info ); +void DrawEmissiveScrollBlendedPass( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, EmissiveScrollBlendedPassVars_t &info, VertexCompressionType_t vertexCompression ); + +#endif // EMISSIVE_SCROLL_BLENDED_PASS_HELPER_H diff --git a/materialsystem/stdshaders/emissive_scroll_blended_pass_ps2x.fxc b/materialsystem/stdshaders/emissive_scroll_blended_pass_ps2x.fxc new file mode 100644 index 00000000..8d40ada3 --- /dev/null +++ b/materialsystem/stdshaders/emissive_scroll_blended_pass_ps2x.fxc @@ -0,0 +1,48 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// Includes ======================================================================================= +#include "common_vertexlitgeneric_dx9.h" + +// Texture Samplers =============================================================================== +sampler g_tBaseSampler : register( s0 ); +sampler g_tFlowSampler : register( s1 ); +sampler g_tSelfIllumSampler : register( s2 ); + +// Shaders Constants and Globals ================================================================== +const float4 g_vPackedConst0 : register( c0 ); +#define g_flBlendStrength g_vPackedConst0.x +#define g_flTime g_vPackedConst0.y + +const float2 g_vEmissiveScrollVector : register( c1 ); +const float3 g_cSelfIllumTint : register( c2 ); + +// Interpolated values ============================================================================ +struct PS_INPUT +{ + float2 vTexCoord0 : TEXCOORD0; +}; + +// Main =========================================================================================== +//float4 main( PS_INPUT i ) : COLOR // Non-HDR for debugging +float4 main( PS_INPUT i ) : COLOR +{ + // Color texture + float4 cBaseColor = tex2D( g_tBaseSampler, i.vTexCoord0.xy ); + + // Fetch from dudv map and then fetch from emissive texture with new uv's & scroll + float4 vFlowValue = tex2D( g_tFlowSampler, i.vTexCoord0.xy ); + float2 vEmissiveTexCoord = vFlowValue.xy + ( g_vEmissiveScrollVector.xy * g_flTime ); + float4 cEmissiveColor = tex2D( g_tSelfIllumSampler, vEmissiveTexCoord.xy ); + + //===============// + // Combine terms // + //===============// + float4 result; + result.rgb = cBaseColor.rgb * cEmissiveColor.rgb * g_cSelfIllumTint.rgb; + result.rgb *= g_flBlendStrength; + + // Set alpha to 0.0f so it doesn't change dest alpha (I should probably disable dest alpha writes) + result.a = 0.0f; + + return FinalOutput( result, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_LINEAR ); +} diff --git a/materialsystem/stdshaders/emissive_scroll_blended_pass_vs20.fxc b/materialsystem/stdshaders/emissive_scroll_blended_pass_vs20.fxc new file mode 100644 index 00000000..b4d078e0 --- /dev/null +++ b/materialsystem/stdshaders/emissive_scroll_blended_pass_vs20.fxc @@ -0,0 +1,69 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "SKINNING" "0..1" + +// DYNAMIC: "MORPHING" "0..1" [vs30] [ = pShaderAPI->IsHWMorphingEnabled() ] + +// Includes +#include "common_vs_fxc.h" + +// Globals +static const bool g_bSkinning = SKINNING ? true : false; + +#ifdef SHADER_MODEL_VS_3_0 +// NOTE: cMorphTargetTextureDim.xy = target dimensions, +// cMorphTargetTextureDim.z = 4tuples/morph +const float3 cMorphTargetTextureDim : register( SHADER_SPECIFIC_CONST_6 ); +const float4 cMorphSubrect : register( SHADER_SPECIFIC_CONST_7 ); + +sampler2D morphSampler : register( D3DVERTEXTEXTURESAMPLER0, s0 ); +#endif + +// Structs +struct VS_INPUT +{ + float4 vPos : POSITION; // Position + float4 vBoneWeights : BLENDWEIGHT; // Skin weights + float4 vBoneIndices : BLENDINDICES; // Skin indices + float4 vTexCoord0 : TEXCOORD0; // Base texture coordinates + + float3 vPosFlex : POSITION1; // Delta positions for flexing + +#ifdef SHADER_MODEL_VS_3_0 + float vVertexID : POSITION2; +#endif +}; + +struct VS_OUTPUT +{ + float4 vProjPosition : POSITION; // Projection-space position + float2 vTexCoord0 : TEXCOORD0; +}; + +// Main +VS_OUTPUT main( const VS_INPUT i ) +{ + VS_OUTPUT o; + + float4 vObjPosition = i.vPos; + +#if !defined( SHADER_MODEL_VS_3_0 ) || !MORPHING + ApplyMorph( i.vPosFlex, vObjPosition.xyz ); +#else + ApplyMorph( morphSampler, cMorphTargetTextureDim, cMorphSubrect, i.vVertexID, float3( 0, 0, 0 ), vObjPosition.xyz ); +#endif + + // Transform the position + float3 vWorldPosition = { 0.0f, 0.0f, 0.0f }; + SkinPosition( g_bSkinning, vObjPosition, i.vBoneWeights, i.vBoneIndices, vWorldPosition ); + + // Transform into projection space + float4 vProjPosition = mul( float4( vWorldPosition, 1.0f ), cViewProj ); + o.vProjPosition = vProjPosition; + + // Pass through tex coords + o.vTexCoord0.xy = i.vTexCoord0.xy; + + return o; +} diff --git a/materialsystem/stdshaders/eye_refract.cpp b/materialsystem/stdshaders/eye_refract.cpp new file mode 100644 index 00000000..6d8b924c --- /dev/null +++ b/materialsystem/stdshaders/eye_refract.cpp @@ -0,0 +1,251 @@ +//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============// + +#include "BaseVSShader.h" +#include "eye_refract_helper.h" +#include "cloak_blended_pass_helper.h" +#include "emissive_scroll_blended_pass_helper.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( EyeRefract, EyeRefract_dx9 ) +BEGIN_VS_SHADER( EyeRefract_dx9, "Help for Eyes" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( IRIS, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "iris texture" ) + SHADER_PARAM( IRISFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame for the iris texture" ) + SHADER_PARAM( CORNEATEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "cornea texture" ) + SHADER_PARAM( AMBIENTOCCLTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "reflection texture" ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + + SHADER_PARAM( EYEORIGIN, SHADER_PARAM_TYPE_VEC3, "[0 0 0]", "origin for the eyes" ) + + SHADER_PARAM( IRISU, SHADER_PARAM_TYPE_VEC4, "[0 1 0 0 ]", "U projection vector for the iris" ) + SHADER_PARAM( IRISV, SHADER_PARAM_TYPE_VEC4, "[0 0 1 0]", "V projection vector for the iris" ) + + SHADER_PARAM( DILATION, SHADER_PARAM_TYPE_FLOAT, "0", "Pupil dilation (0 is none, 1 is maximal)" ) + SHADER_PARAM( GLOSSINESS, SHADER_PARAM_TYPE_FLOAT, "1", "Glossiness of eye (1 is default, 0 is not glossy at all)" ) + SHADER_PARAM( SPHERETEXKILLCOMBO, SHADER_PARAM_TYPE_BOOL, "1", "texkill pixels not on sphere" ) + SHADER_PARAM( RAYTRACESPHERE, SHADER_PARAM_TYPE_BOOL, "1", "Raytrace sphere" ) + SHADER_PARAM( PARALLAXSTRENGTH, SHADER_PARAM_TYPE_FLOAT, "1", "Parallax strength" ) + SHADER_PARAM( CORNEABUMPSTRENGTH, SHADER_PARAM_TYPE_FLOAT, "1", "Cornea strength" ) + + SHADER_PARAM( AMBIENTOCCLCOLOR, SHADER_PARAM_TYPE_VEC3, "[1 1 1]", "Ambient occlusion color" ) + SHADER_PARAM( AMBIENTOCCLUSION, SHADER_PARAM_TYPE_FLOAT, "1.0", "Dynamic ambient occlusion strength" ) + + SHADER_PARAM( EYEBALLRADIUS, SHADER_PARAM_TYPE_FLOAT, "0", "Eyeball radius for ray casting" ) + + SHADER_PARAM( INTRO, SHADER_PARAM_TYPE_BOOL, "0", "is eyes in the ep1 intro" ) + SHADER_PARAM( ENTITYORIGIN, SHADER_PARAM_TYPE_VEC3,"0.0","center if the model in world space" ) + SHADER_PARAM( WARPPARAM, SHADER_PARAM_TYPE_FLOAT,"0.0","animation param between 0 and 1" ) + + SHADER_PARAM( LIGHTWARPTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "1D ramp texture for tinting scalar diffuse term" ) + + // Cloak Pass + SHADER_PARAM( CLOAKPASSENABLED, SHADER_PARAM_TYPE_BOOL, "0", "Enables cloak render in a second pass" ) + SHADER_PARAM( CLOAKFACTOR, SHADER_PARAM_TYPE_FLOAT, "0.0", "" ) + SHADER_PARAM( CLOAKCOLORTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Cloak color tint" ) + SHADER_PARAM( REFRACTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "2", "" ) + + // Emissive Scroll Pass + SHADER_PARAM( EMISSIVEBLENDENABLED, SHADER_PARAM_TYPE_BOOL, "0", "Enable emissive blend pass" ) + SHADER_PARAM( EMISSIVEBLENDSCROLLVECTOR, SHADER_PARAM_TYPE_VEC2, "[0.11 0.124]", "Emissive scroll vec" ) + SHADER_PARAM( EMISSIVEBLENDSTRENGTH, SHADER_PARAM_TYPE_FLOAT, "1.0", "Emissive blend strength" ) + SHADER_PARAM( EMISSIVEBLENDTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "self-illumination map" ) + SHADER_PARAM( EMISSIVEBLENDTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Self-illumination tint" ) + SHADER_PARAM( EMISSIVEBLENDFLOWTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "flow map" ) + END_SHADER_PARAMS + + void SetupVarsEyeRefract( Eye_Refract_Vars_t &info ) + { + info.m_nFrame = FRAME; + info.m_nIris = IRIS; + info.m_nIrisFrame = IRISFRAME; + info.m_nEyeOrigin = EYEORIGIN; + info.m_nIrisU = IRISU; + info.m_nIrisV = IRISV; + info.m_nDilation = DILATION; + info.m_nGlossiness = GLOSSINESS; + info.m_nIntro = INTRO; + info.m_nEntityOrigin = ENTITYORIGIN; + info.m_nWarpParam = WARPPARAM; + info.m_nCorneaTexture = CORNEATEXTURE; + info.m_nAmbientOcclTexture = AMBIENTOCCLTEXTURE; + info.m_nEnvmap = ENVMAP; + info.m_nSphereTexKillCombo = SPHERETEXKILLCOMBO; + info.m_nRaytraceSphere = RAYTRACESPHERE; + info.m_nParallaxStrength = PARALLAXSTRENGTH; + info.m_nCorneaBumpStrength = CORNEABUMPSTRENGTH; + info.m_nAmbientOcclColor = AMBIENTOCCLCOLOR; + info.m_nEyeballRadius = EYEBALLRADIUS; + info.m_nDiffuseWarpTexture = LIGHTWARPTEXTURE; + info.m_nAmbientOcclusion = AMBIENTOCCLUSION; + } + + // Cloak Pass + void SetupVarsCloakBlendedPass( CloakBlendedPassVars_t &info ) + { + info.m_nCloakFactor = CLOAKFACTOR; + info.m_nCloakColorTint = CLOAKCOLORTINT; + info.m_nRefractAmount = REFRACTAMOUNT; + } + + bool NeedsPowerOfTwoFrameBufferTexture( IMaterialVar **params, bool bCheckSpecificToThisFrame ) const + { + if ( params[CLOAKPASSENABLED]->GetIntValue() ) // If material supports cloaking + { + if ( bCheckSpecificToThisFrame == false ) // For setting model flag at load time + return true; + else if ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) // Per-frame check + return true; + // else, not cloaking this frame, so check flag2 in case the base material still needs it + } + + // Check flag2 if not drawing cloak pass + return IS_FLAG2_SET( MATERIAL_VAR2_NEEDS_POWER_OF_TWO_FRAME_BUFFER_TEXTURE ); + } + + bool IsTranslucent( IMaterialVar **params ) const + { + if ( params[CLOAKPASSENABLED]->GetIntValue() ) // If material supports cloaking + { + if ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) // Per-frame check + return true; + // else, not cloaking this frame, so check flag in case the base material still needs it + } + + // Check flag if not drawing cloak pass + return IS_FLAG_SET( MATERIAL_VAR_TRANSLUCENT ); + } + + // Emissive Scroll Pass + void SetupVarsEmissiveScrollBlendedPass( EmissiveScrollBlendedPassVars_t &info ) + { + info.m_nBlendStrength = EMISSIVEBLENDSTRENGTH; + info.m_nBaseTexture = IRIS; + info.m_nFlowTexture = EMISSIVEBLENDFLOWTEXTURE; + info.m_nEmissiveTexture = EMISSIVEBLENDTEXTURE; + info.m_nEmissiveTint = EMISSIVEBLENDTINT; + info.m_nEmissiveScrollVector = EMISSIVEBLENDSCROLLVECTOR; + } + + SHADER_INIT_PARAMS() + { + Eye_Refract_Vars_t info; + SetupVarsEyeRefract( info ); + InitParams_Eyes_Refract( this, params, pMaterialName, info ); + + // Cloak Pass + if ( !params[CLOAKPASSENABLED]->IsDefined() ) + { + params[CLOAKPASSENABLED]->SetIntValue( 0 ); + } + else if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + InitParamsCloakBlendedPass( this, params, pMaterialName, info ); + } + + // Emissive Scroll Pass + if ( !params[EMISSIVEBLENDENABLED]->IsDefined() ) + { + params[EMISSIVEBLENDENABLED]->SetIntValue( 0 ); + } + else if ( params[EMISSIVEBLENDENABLED]->GetIntValue() ) + { + EmissiveScrollBlendedPassVars_t info; + SetupVarsEmissiveScrollBlendedPass( info ); + InitParamsEmissiveScrollBlendedPass( this, params, pMaterialName, info ); + } + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + Eye_Refract_Vars_t info; + SetupVarsEyeRefract( info ); + Init_Eyes_Refract( this, params, info ); + + // Cloak Pass + if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + InitCloakBlendedPass( this, params, info ); + } + + // Emissive Scroll Pass + if ( params[EMISSIVEBLENDENABLED]->GetIntValue() ) + { + EmissiveScrollBlendedPassVars_t info; + SetupVarsEmissiveScrollBlendedPass( info ); + InitEmissiveScrollBlendedPass( this, params, info ); + } + } + + SHADER_DRAW + { + // Skip the standard rendering if cloak pass is fully opaque + bool bDrawStandardEye = true; + if ( params[CLOAKPASSENABLED]->GetIntValue() && ( pShaderShadow == NULL ) ) // && not snapshotting + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + if ( CloakBlendedPassIsFullyOpaque( params, info ) ) + { + bDrawStandardEye = false; + } + } + + // Standard rendering pass + if ( bDrawStandardEye ) + { + Eye_Refract_Vars_t info; + SetupVarsEyeRefract( info ); + Draw_Eyes_Refract( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else + { + // Skip this pass! + Draw( false ); + } + + // Cloak Pass + if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + // If ( snapshotting ) or ( we need to draw this frame ) + if ( ( pShaderShadow != NULL ) || ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + DrawCloakBlendedPass( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else // We're not snapshotting and we don't need to draw this frame + { + // Skip this pass! + Draw( false ); + } + } + + // Emissive Scroll Pass + if ( params[EMISSIVEBLENDENABLED]->GetIntValue() ) + { + // If ( snapshotting ) or ( we need to draw this frame ) + if ( ( pShaderShadow != NULL ) || ( params[EMISSIVEBLENDSTRENGTH]->GetFloatValue() > 0.0f ) ) + { + EmissiveScrollBlendedPassVars_t info; + SetupVarsEmissiveScrollBlendedPass( info ); + DrawEmissiveScrollBlendedPass( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else // We're not snapshotting and we don't need to draw this frame + { + // Skip this pass! + Draw( false ); + } + } + } +END_SHADER diff --git a/materialsystem/stdshaders/eye_refract_helper.cpp b/materialsystem/stdshaders/eye_refract_helper.cpp new file mode 100644 index 00000000..f3bb5d2a --- /dev/null +++ b/materialsystem/stdshaders/eye_refract_helper.cpp @@ -0,0 +1,537 @@ +//===== Copyright © 1996-2008, Valve Corporation, All rights reserved. ======// + +#include "BaseVSShader.h" +#include "mathlib/VMatrix.h" +#include "eye_refract_helper.h" + +#include "cpp_shader_constant_register_map.h" + +#include "eye_refract_vs20.inc" +#include "eye_refract_ps20.inc" +#include "eye_refract_ps20b.inc" + +#ifndef _X360 +#include "eye_refract_vs30.inc" +#include "eye_refract_ps30.inc" +#endif + +#include "convar.h" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +static ConVar r_lightwarpidentity( "r_lightwarpidentity","0", FCVAR_CHEAT ); +static ConVar mat_displacementmap( "mat_displacementmap", "1", FCVAR_CHEAT ); + +void InitParams_Eyes_Refract( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, Eye_Refract_Vars_t &info ) +{ + params[FLASHLIGHTTEXTURE]->SetStringValue( GetFlashlightTextureFilename() ); + + // Set material flags + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + + // Set material parameter default values + if ( ( info.m_nIntro >= 0 ) && ( !params[info.m_nIntro]->IsDefined() ) ) + { + params[info.m_nIntro]->SetIntValue( kDefaultIntro ); + } + + if ( ( info.m_nDilation >= 0 ) && ( !params[info.m_nDilation]->IsDefined() ) ) + { + params[info.m_nDilation]->SetFloatValue( kDefaultDilation ); + } + + if ( ( info.m_nGlossiness >= 0 ) && ( !params[info.m_nGlossiness]->IsDefined() ) ) + { + params[info.m_nGlossiness]->SetFloatValue( kDefaultGlossiness ); + } + + if ( ( info.m_nSphereTexKillCombo >= 0 ) && ( !params[info.m_nSphereTexKillCombo]->IsDefined() ) ) + { + params[info.m_nSphereTexKillCombo]->SetIntValue( kDefaultSphereTexKillCombo ); + } + + if ( ( info.m_nRaytraceSphere >= 0 ) && ( !params[info.m_nRaytraceSphere]->IsDefined() ) ) + { + params[info.m_nRaytraceSphere]->SetIntValue( kDefaultRaytraceSphere ); + } + + if ( ( info.m_nAmbientOcclColor >= 0 ) && ( !params[info.m_nAmbientOcclColor]->IsDefined() ) ) + { + params[info.m_nAmbientOcclColor]->SetVecValue( kDefaultAmbientOcclColor, 4 ); + } + + if ( ( info.m_nEyeballRadius >= 0 ) && ( !params[info.m_nEyeballRadius]->IsDefined() ) ) + { + params[info.m_nEyeballRadius]->SetFloatValue( kDefaultEyeballRadius ); + } + + if ( ( info.m_nParallaxStrength >= 0 ) && ( !params[info.m_nParallaxStrength]->IsDefined() ) ) + { + params[info.m_nParallaxStrength]->SetFloatValue( kDefaultParallaxStrength ); + } + + if ( ( info.m_nCorneaBumpStrength >= 0 ) && ( !params[info.m_nCorneaBumpStrength]->IsDefined() ) ) + { + params[info.m_nCorneaBumpStrength]->SetFloatValue( kDefaultCorneaBumpStrength ); + } + + if ( ( info.m_nAmbientOcclusion >= 0 ) && ( !params[info.m_nAmbientOcclusion]->IsDefined() ) ) + { + params[info.m_nAmbientOcclusion]->SetFloatValue( 0.0f ); + } +} + +void Init_Eyes_Refract( CBaseVSShader *pShader, IMaterialVar** params, Eye_Refract_Vars_t &info ) +{ + pShader->LoadTexture( FLASHLIGHTTEXTURE ); + pShader->LoadTexture( info.m_nIris ); + pShader->LoadTexture( info.m_nCorneaTexture ); + pShader->LoadTexture( info.m_nAmbientOcclTexture ); + pShader->LoadCubeMap( info.m_nEnvmap ); + + if ( IS_PARAM_DEFINED( info.m_nDiffuseWarpTexture ) ) + { + pShader->LoadTexture( info.m_nDiffuseWarpTexture ); + } +} + +void Draw_Eyes_Refract_Internal( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, bool bDrawFlashlightAdditivePass, Eye_Refract_Vars_t &info, VertexCompressionType_t vertexCompression ) +{ + bool bDiffuseWarp = IS_PARAM_DEFINED( info.m_nDiffuseWarpTexture ); + bool bIntro = IS_PARAM_DEFINED( info.m_nIntro ) ? ( params[info.m_nIntro]->GetIntValue() ? true : false ) : false; + + SHADOW_STATE + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); // Cornea normal + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); // Iris + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); // Cube reflection + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); // Ambient occlusion + + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + if ( bDiffuseWarp ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); // Light warp + } + +#if !defined( PLATFORM_X360 ) + bool bWorldNormal = ( ENABLE_FIXED_LIGHTING_OUTPUTNORMAL_AND_DEPTH == ( IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER0 ) + 2 * IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER1 ))); +#endif + + int nShadowFilterMode = 0; + if ( bDrawFlashlightAdditivePass == true ) + { + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + nShadowFilterMode = g_pHardwareConfig->GetShadowFilterMode(); // Based upon vendor and device dependent formats + } + + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableAlphaWrites( false ); + pShader->EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); // Additive blending + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); // Flashlight cookie + } + else + { + pShaderShadow->EnableAlphaWrites( true ); + } + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_STATIC_VERTEX_SHADER( eye_refract_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT, IS_FLAG_SET( MATERIAL_VAR_HALFLAMBERT ) ); + SET_STATIC_VERTEX_SHADER_COMBO( INTRO, bIntro ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER_COMBO( FLASHLIGHT, bDrawFlashlightAdditivePass ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER_COMBO( LIGHTWARPTEXTURE, bDiffuseWarp ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER_COMBO( WORLD_NORMAL, 0 ); + SET_STATIC_VERTEX_SHADER( eye_refract_vs20 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + bool bSphereTexKillCombo = IS_PARAM_DEFINED( info.m_nSphereTexKillCombo ) ? ( params[info.m_nSphereTexKillCombo]->GetIntValue() ? true : false ) : ( kDefaultSphereTexKillCombo ? true : false ); + bool bRayTraceSphere = IS_PARAM_DEFINED( info.m_nRaytraceSphere ) ? ( params[info.m_nRaytraceSphere]->GetIntValue() ? true : false ) : ( kDefaultRaytraceSphere ? true : false ); + + DECLARE_STATIC_PIXEL_SHADER( eye_refract_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( SPHERETEXKILLCOMBO, bSphereTexKillCombo ? 1 : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( RAYTRACESPHERE, bRayTraceSphere ? 1 : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bDrawFlashlightAdditivePass ? 1 : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, bDiffuseWarp ? 1 : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER_COMBO( WORLD_NORMAL, 0 ); + SET_STATIC_PIXEL_SHADER( eye_refract_ps20b ); + + if ( bDrawFlashlightAdditivePass == true ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); // Shadow depth map + pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER6 ); + pShaderShadow->EnableTexture( SHADER_SAMPLER7, true ); // Noise map + } + } + else + { + DECLARE_STATIC_PIXEL_SHADER( eye_refract_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bDrawFlashlightAdditivePass ? 1 : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, bDiffuseWarp ? 1 : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( WORLD_NORMAL, 0 ); + SET_STATIC_PIXEL_SHADER( eye_refract_ps20 ); + } + } +#ifndef _X360 + else + { + pShaderShadow->EnableTexture( SHADER_SAMPLER8, true ); // Screen space ambient occlusion + + // The vertex shader uses the vertex id stream + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_TESSELLATION ); + + DECLARE_STATIC_VERTEX_SHADER( eye_refract_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT, IS_FLAG_SET( MATERIAL_VAR_HALFLAMBERT ) ); + SET_STATIC_VERTEX_SHADER_COMBO( INTRO, bIntro ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER_COMBO( FLASHLIGHT, bDrawFlashlightAdditivePass ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER_COMBO( LIGHTWARPTEXTURE, bDiffuseWarp ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER_COMBO( WORLD_NORMAL, bWorldNormal ); + SET_STATIC_VERTEX_SHADER( eye_refract_vs30 ); + + bool bSphereTexKillCombo = IS_PARAM_DEFINED( info.m_nSphereTexKillCombo ) ? ( params[info.m_nSphereTexKillCombo]->GetIntValue() ? true : false ) : ( kDefaultSphereTexKillCombo ? true : false ); + bool bRayTraceSphere = IS_PARAM_DEFINED( info.m_nRaytraceSphere ) ? ( params[info.m_nRaytraceSphere]->GetIntValue() ? true : false ) : ( kDefaultRaytraceSphere ? true : false ); + + DECLARE_STATIC_PIXEL_SHADER( eye_refract_ps30 ); + SET_STATIC_PIXEL_SHADER_COMBO( SPHERETEXKILLCOMBO, bSphereTexKillCombo ? 1 : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( RAYTRACESPHERE, bRayTraceSphere ? 1 : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bDrawFlashlightAdditivePass ? 1 : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, bDiffuseWarp ? 1 : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER_COMBO( WORLD_NORMAL, bWorldNormal ); + SET_STATIC_PIXEL_SHADER( eye_refract_ps30 ); + + if ( bDrawFlashlightAdditivePass == true ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); // Shadow depth map + pShaderShadow->EnableTexture( SHADER_SAMPLER7, true ); // Noise map + } + } +#endif + + // On DX9, get the gamma read and write correct + //pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, false ); // Cornea normal + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); // Iris + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, true ); // Cube map reflection + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER3, true ); // Ambient occlusion + pShaderShadow->EnableSRGBWrite( true ); + + if ( bDiffuseWarp ) + { + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER4, true ); // Light Warp + } + + if ( bDrawFlashlightAdditivePass == true ) + { + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER5, true ); // Flashlight cookie + } + + // Fog + if ( bDrawFlashlightAdditivePass == true ) + { + pShader->FogToBlack(); + } + else + { + pShader->FogToFogColor(); + } + + // Per-instance state + pShader->PI_BeginCommandBuffer(); + if ( !bDrawFlashlightAdditivePass ) + { + pShader->PI_SetPixelShaderLocalLighting( PSREG_LIGHT_INFO_ARRAY ); + } + pShader->PI_SetVertexShaderAmbientLightCube(); + pShader->PI_SetPixelShaderAmbientLightCubeLuminance( 10 ); + pShader->PI_EndCommandBuffer(); + } + DYNAMIC_STATE + { + VMatrix worldToTexture; + ITexture *pFlashlightDepthTexture = NULL; + FlashlightState_t flashlightState; + bool bFlashlightShadows = false; + if ( bDrawFlashlightAdditivePass == true ) + { + flashlightState = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture ); + bFlashlightShadows = flashlightState.m_bEnableShadows; + } + + bool bSinglePassFlashlight = false; + + pShader->BindTexture( SHADER_SAMPLER0, info.m_nCorneaTexture ); + pShader->BindTexture( SHADER_SAMPLER1, info.m_nIris, info.m_nIrisFrame ); + pShader->BindTexture( SHADER_SAMPLER2, info.m_nEnvmap ); + pShader->BindTexture( SHADER_SAMPLER3, info.m_nAmbientOcclTexture ); + + if ( bDiffuseWarp ) + { + if ( r_lightwarpidentity.GetBool() ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER4, TEXTURE_IDENTITY_LIGHTWARP ); + } + else + { + pShader->BindTexture( SHADER_SAMPLER4, info.m_nDiffuseWarpTexture ); + } + } + + // On PC, we sample from ambient occlusion texture + if ( IsPC() && g_pHardwareConfig->HasFastVertexTextures() ) + { + ITexture *pAOTexture = pShaderAPI->GetTextureRenderingParameter( TEXTURE_RENDERPARM_AMBIENT_OCCLUSION ); + + if ( pAOTexture ) + { + pShader->BindTexture( SHADER_SAMPLER8, pAOTexture ); + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER8, TEXTURE_WHITE ); + } + } + + if ( bDrawFlashlightAdditivePass == true ) + pShader->BindTexture( SHADER_SAMPLER5, flashlightState.m_pSpotlightTexture, flashlightState.m_nSpotlightTextureFrame ); + + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, info.m_nEyeOrigin ); + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, info.m_nIrisU ); + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, info.m_nIrisV ); + + if ( bDrawFlashlightAdditivePass == true ) + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, flashlightState.m_vecLightOrigin.Base(), 1 ); + + LightState_t lightState = { 0, false, false }; + if ( bDrawFlashlightAdditivePass == false ) + { + pShaderAPI->GetDX9LightState( &lightState ); + } + + int nFixedLightingMode = pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_ENABLE_FIXED_LIGHTING ); + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_DYNAMIC_VERTEX_SHADER( eye_refract_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DYNAMIC_LIGHT, lightState.HasDynamicLight() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( TESSELLATION, 0 ); + SET_DYNAMIC_VERTEX_SHADER( eye_refract_vs20 ); + } +#ifndef _X360 + else + { + pShader->SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_10, VERTEX_SHADER_SHADER_SPECIFIC_CONST_11, SHADER_VERTEXTEXTURE_SAMPLER0 ); + + if ( nFixedLightingMode == ENABLE_FIXED_LIGHTING_OUTPUTNORMAL_AND_DEPTH ) + { + float vEyeDir[4]; + pShaderAPI->GetWorldSpaceCameraDirection( vEyeDir ); + + float flFarZ = pShaderAPI->GetFarZ(); + vEyeDir[0] /= flFarZ; // Divide by farZ for SSAO algorithm + vEyeDir[1] /= flFarZ; + vEyeDir[2] /= flFarZ; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_5, vEyeDir ); + } + + TessellationMode_t nTessellationMode = pShaderAPI->GetTessellationMode(); + if ( nTessellationMode != TESSELLATION_MODE_DISABLED ) + { + pShaderAPI->BindStandardVertexTexture( SHADER_VERTEXTEXTURE_SAMPLER1, TEXTURE_SUBDIVISION_PATCHES ); + + bool bHasDisplacement = false; // TODO + float vSubDDimensions[4] = { 1.0f/pShaderAPI->GetSubDHeight(), bHasDisplacement && mat_displacementmap.GetBool() ? 1.0f : 0.0f, 0.0f, 0.0f }; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, vSubDDimensions ); + } + + DECLARE_DYNAMIC_VERTEX_SHADER( eye_refract_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DYNAMIC_LIGHT, lightState.HasDynamicLight() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( TESSELLATION, nTessellationMode ); + SET_DYNAMIC_VERTEX_SHADER( eye_refract_vs30 ); + } +#endif + + // Special constant for DX9 eyes: { Dilation, Glossiness, x, x }; + float vPSConst[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vPSConst[0] = IS_PARAM_DEFINED( info.m_nDilation ) ? params[info.m_nDilation]->GetFloatValue() : kDefaultDilation; + vPSConst[1] = IS_PARAM_DEFINED( info.m_nGlossiness ) ? params[info.m_nGlossiness]->GetFloatValue() : kDefaultGlossiness; + vPSConst[2] = 0.0f; // NOT USED + vPSConst[3] = IS_PARAM_DEFINED( info.m_nCorneaBumpStrength ) ? params[info.m_nCorneaBumpStrength]->GetFloatValue() : kDefaultCorneaBumpStrength; + pShaderAPI->SetPixelShaderConstant( 0, vPSConst, 1 ); + + pShaderAPI->SetPixelShaderConstant( 1, IS_PARAM_DEFINED( info.m_nEyeOrigin ) ? params[info.m_nEyeOrigin]->GetVecValue() : kDefaultEyeOrigin, 1 ); + pShaderAPI->SetPixelShaderConstant( 2, IS_PARAM_DEFINED( info.m_nIrisU ) ? params[info.m_nIrisU]->GetVecValue() : kDefaultIrisU, 1 ); + pShaderAPI->SetPixelShaderConstant( 3, IS_PARAM_DEFINED( info.m_nIrisV ) ? params[info.m_nIrisV]->GetVecValue() : kDefaultIrisV, 1 ); + + float vEyePos[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos ); + pShaderAPI->SetPixelShaderConstant( 4, vEyePos, 1 ); + + float vAmbientOcclusion[4] = { 0.33f, 0.33f, 0.33f, 0.0f }; + if ( IS_PARAM_DEFINED( info.m_nAmbientOcclColor ) ) + { + params[info.m_nAmbientOcclColor]->GetVecValue( vAmbientOcclusion, 3 ); + } + vAmbientOcclusion[3] = IS_PARAM_DEFINED( info.m_nAmbientOcclusion ) ? params[info.m_nAmbientOcclusion]->GetFloatValue() : 0.0f; + + float vPackedConst6[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + //vPackedConst6[0] Unused + vPackedConst6[1] = IS_PARAM_DEFINED( info.m_nEyeballRadius ) ? params[info.m_nEyeballRadius]->GetFloatValue() : kDefaultEyeballRadius; + //vPackedConst6[2] = IS_PARAM_DEFINED( info.m_nRaytraceSphere ) ? params[info.m_nRaytraceSphere]->GetFloatValue() : kDefaultRaytraceSphere; + vPackedConst6[3] = IS_PARAM_DEFINED( info.m_nParallaxStrength ) ? params[info.m_nParallaxStrength]->GetFloatValue() : kDefaultParallaxStrength; + pShaderAPI->SetPixelShaderConstant( 6, vPackedConst6, 1 ); + + if ( bDrawFlashlightAdditivePass == true ) + { + SetFlashLightColorFromState( flashlightState, pShaderAPI, bSinglePassFlashlight ); + + if ( pFlashlightDepthTexture && g_pConfig->ShadowDepthTexture() && flashlightState.m_bEnableShadows ) + { + pShader->BindTexture( SHADER_SAMPLER6, pFlashlightDepthTexture, 0 ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER7, TEXTURE_SHADOW_NOISE_2D ); + } + } + + if ( nFixedLightingMode == ENABLE_FIXED_LIGHTING_OUTPUTNORMAL_AND_DEPTH ) + { + float vEyeDir[4]; + pShaderAPI->GetWorldSpaceCameraDirection( vEyeDir ); + + float flFarZ = pShaderAPI->GetFarZ(); + vEyeDir[0] /= flFarZ; // Divide by farZ for SSAO algorithm + vEyeDir[1] /= flFarZ; + vEyeDir[2] /= flFarZ; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_5, vEyeDir ); + } + + // Flashlight tax +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( eye_refract_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER( eye_refract_ps20b ); + } + else // ps.2.0 + { + DECLARE_DYNAMIC_PIXEL_SHADER( eye_refract_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER( eye_refract_ps20 ); + } + } +#ifndef _X360 + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( eye_refract_ps30 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, nFixedLightingMode ? 0 : lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, nFixedLightingMode ? false : bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( UBERLIGHT, flashlightState.m_bUberlight ); + SET_DYNAMIC_PIXEL_SHADER( eye_refract_ps30 ); + + // Set constant to enable translation of VPOS to render target coordinates in ps_3_0 + pShaderAPI->SetScreenSizeForVPOS(); + + SetupUberlightFromState( pShaderAPI, flashlightState ); + } +#endif + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + if ( bDrawFlashlightAdditivePass == true ) + { + float atten[4], pos[4], tweaks[4]; + atten[0] = flashlightState.m_fConstantAtten; // Set the flashlight attenuation factors + atten[1] = flashlightState.m_fLinearAtten; + atten[2] = flashlightState.m_fQuadraticAtten; + atten[3] = flashlightState.m_FarZAtten; + pShaderAPI->SetPixelShaderConstant( 7, atten, 1 ); + + pos[0] = flashlightState.m_vecLightOrigin[0]; // Set the flashlight origin + pos[1] = flashlightState.m_vecLightOrigin[1]; + pos[2] = flashlightState.m_vecLightOrigin[2]; + pShaderAPI->SetPixelShaderConstant( 8, pos, 1 ); + + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, worldToTexture.Base(), 4 ); + + // Tweaks associated with a given flashlight + tweaks[0] = ShadowFilterFromState( flashlightState ); + tweaks[1] = ShadowAttenFromState( flashlightState ); + pShader->HashShadow2DJitter( flashlightState.m_flShadowJitterSeed, &tweaks[2], &tweaks[3] ); + pShaderAPI->SetPixelShaderConstant( 9, tweaks, 1 ); + + // Dimensions of screen, used for screen-space noise map sampling + float vScreenScale[4] = {1280.0f / 32.0f, 720.0f / 32.0f, 0, 0}; + int nWidth, nHeight; + pShaderAPI->GetBackBufferDimensions( nWidth, nHeight ); + + int nTexWidth, nTexHeight; + pShaderAPI->GetStandardTextureDimensions( &nTexWidth, &nTexHeight, TEXTURE_SHADOW_NOISE_2D ); + + vScreenScale[0] = (float) nWidth / nTexWidth; + vScreenScale[1] = (float) nHeight / nTexHeight; + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_SCREEN_SCALE, vScreenScale, 1 ); + + vAmbientOcclusion[3] *= flashlightState.m_flAmbientOcclusion; + } + + vAmbientOcclusion[3] = MIN( MAX( vAmbientOcclusion[3], 0.0f ), 1.0f ); + pShaderAPI->SetPixelShaderConstant( 5, vAmbientOcclusion, 1 ); + + // Intro tax + if ( bIntro ) + { + float curTime = params[info.m_nWarpParam]->GetFloatValue(); + float timeVec[4] = { 0.0f, 0.0f, 0.0f, curTime }; + if ( IS_PARAM_DEFINED( info.m_nEntityOrigin ) ) + { + params[info.m_nEntityOrigin]->GetVecValue( timeVec, 3 ); + } + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_5, timeVec, 1 ); + } + } + pShader->Draw(); +} + + +void Draw_Eyes_Refract( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, Eye_Refract_Vars_t &info, VertexCompressionType_t vertexCompression ) +{ + bool bHasFlashlight = pShader->UsingFlashlight( params ); + if ( bHasFlashlight && IsX360() ) + { + Draw_Eyes_Refract_Internal( pShader, params, pShaderAPI, pShaderShadow, false, info, vertexCompression ); + if ( pShaderShadow ) + { + pShader->SetInitialShadowState( ); + } + } + Draw_Eyes_Refract_Internal( pShader, params, pShaderAPI, pShaderShadow, bHasFlashlight, info, vertexCompression ); +} diff --git a/materialsystem/stdshaders/eye_refract_helper.h b/materialsystem/stdshaders/eye_refract_helper.h new file mode 100644 index 00000000..58ae2c78 --- /dev/null +++ b/materialsystem/stdshaders/eye_refract_helper.h @@ -0,0 +1,70 @@ +//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============// + +#ifndef EYE_REFRACT_HELPER_H +#define EYE_REFRACT_HELPER_H +#ifdef _WIN32 +#pragma once +#endif + +#include + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct Eye_Refract_Vars_t +{ + Eye_Refract_Vars_t() { memset( this, 0xFF, sizeof(Eye_Refract_Vars_t) ); } + + int m_nFrame; + int m_nIris; + int m_nIrisFrame; + int m_nEyeOrigin; + int m_nIrisU; + int m_nIrisV; + int m_nDilation; + int m_nGlossiness; + int m_nIntro; + int m_nEntityOrigin; // Needed for intro + int m_nWarpParam; + int m_nCorneaTexture; + int m_nAmbientOcclTexture; + int m_nEnvmap; + int m_nSphereTexKillCombo; + int m_nRaytraceSphere; + int m_nParallaxStrength; + int m_nCorneaBumpStrength; + int m_nAmbientOcclColor; + int m_nEyeballRadius; + int m_nDiffuseWarpTexture; + int m_nAmbientOcclusion; +}; + +// Default values (Arrays should only be vec[4]) +static const int kDefaultIntro = 0; +static const float kDefaultEyeOrigin[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; +static const float kDefaultIrisU[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; +static const float kDefaultIrisV[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; +static const float kDefaultDilation = 0.5f; +static const float kDefaultGlossiness = 1.0f; +static const float kDefaultWarpParam = 0.0f; +static const int kDefaultSphereTexKillCombo = 0; +static const int kDefaultRaytraceSphere = 0; +static const float kDefaultParallaxStrength = 0.25f; +static const float kDefaultCorneaBumpStrength = 1.0f; +static const float kDefaultAmbientOcclColor[4] = { 0.33f, 0.33f, 0.33f, 0.0f }; +static const float kDefaultEyeballRadius = 0.5f; + +void InitParams_Eyes_Refract( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, Eye_Refract_Vars_t &info ); +void Init_Eyes_Refract( CBaseVSShader *pShader, IMaterialVar** params, Eye_Refract_Vars_t &info ); +void Draw_Eyes_Refract( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, Eye_Refract_Vars_t &info, VertexCompressionType_t vertexCompression ); + +#endif // EYES_DX8_DX9_HELPER_H diff --git a/materialsystem/stdshaders/eye_refract_ps2x.fxc b/materialsystem/stdshaders/eye_refract_ps2x.fxc new file mode 100644 index 00000000..4412a876 --- /dev/null +++ b/materialsystem/stdshaders/eye_refract_ps2x.fxc @@ -0,0 +1,513 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#include "common_fog_ps_fxc.h" + +// STATIC: "FLASHLIGHT" "0..1" +// STATIC: "LIGHTWARPTEXTURE" "0..1" + +// STATIC: "SPHERETEXKILLCOMBO" "0..1" [ps20b] +// STATIC: "SPHERETEXKILLCOMBO" "0..1" [ps30] + +// STATIC: "RAYTRACESPHERE" "0..1" [ps20b] +// STATIC: "RAYTRACESPHERE" "0..1" [ps30] + +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps20b] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps30] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..0" [ps20b] [XBOX] +// STATIC: "WORLD_NORMAL" "0..0" [ps20] [PC] +// STATIC: "WORLD_NORMAL" "0..0" [ps20b] [PC] +// STATIC: "WORLD_NORMAL" "0..1" [ps30] [PC] +// STATIC: "WORLD_NORMAL" "0..0" [XBOX] + +// DYNAMIC: "NUM_LIGHTS" "0..2" [ps20] +// DYNAMIC: "NUM_LIGHTS" "0..4" [ps20b] +// DYNAMIC: "NUM_LIGHTS" "0..4" [ps30] +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps20b] +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps30] + +// DYNAMIC: "UBERLIGHT" "0..1" [ps30] [PC] + +// We don't use other lights when doing the flashlight +// SKIP: ( $FLASHLIGHT != 0 ) && ( $NUM_LIGHTS > 0 ) + +// We don't care about flashlight depth unless the flashlight is on +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 ) [ps20b] +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 ) [ps30] + +// SKIP: ( $RAYTRACESPHERE == 0 ) && ( $SPHERETEXKILLCOMBO == 1 ) [ps30] +// SKIP: ( $RAYTRACESPHERE == 0 ) && ( $SPHERETEXKILLCOMBO == 1 ) [ps20b] + +// SKIP: ( $WORLD_NORMAL ) && ( $FLASHLIGHTSHADOWS != 0 ) && ( $NUM_LIGHTS != 0 ) [ps30] + +// We don't care about uberlight unless the flashlight is on +// SKIP: ( $FLASHLIGHT == 0 ) && ( $UBERLIGHT == 1 ) [ps30] + + +// Debug 2.0 shader locally +//#ifdef SHADER_MODEL_PS_2_B +//#undef SHADER_MODEL_PS_2_B +//#define SHADER_MODEL_PS_2_0 +//#endif + + +// Includes ======================================================================================= +#include "common_flashlight_fxc.h" +#include "shader_constant_register_map.h" + +// Texture Samplers =============================================================================== +sampler g_tCorneaSampler : register( s0 ); +sampler g_tIrisSampler : register( s1 ); +sampler g_tEyeReflectionCubemapSampler : register( s2 ); +sampler g_tEyeAmbientOcclSampler : register( s3 ); +sampler g_tLightwarpSampler : register( s4 ); // 1D texture for TF NPR lighting + +sampler g_tFlashlightCookieSampler : register( s5 ); +sampler g_tFlashlightDepthSampler : register( s6 ); +sampler g_tRandomRotationSampler : register( s7 ); +sampler g_tAmbientOcclusionSampler : register( s8 ); + +// Shaders Constants and Globals ================================================================== +const float4 g_vPackedConst0 : register( c0 ); +#define g_flDilationFactor g_vPackedConst0.x +#define g_flGlossiness g_vPackedConst0.y +//#define g_fPixelFogType g_vPackedConst0.z +#define g_flCorneaBumpStrength g_vPackedConst0.w + +const float3 g_vEyeOrigin : register( c1 ); +const float4 g_vIrisProjectionU : register( c2 ); +const float4 g_vIrisProjectionV : register( c3 ); +const float4 g_vCameraPosition : register( c4 ); +const float4 g_cAmbientOcclColor : register( c5 ); + +const float4 g_vPackedConst6 : register( c6 ); +#define g_flEyeballRadius g_vPackedConst6.y //0.51f +//#define g_bRaytraceSphere g_vPackedConst6.z //1.0f +#define g_flParallaxStrength g_vPackedConst6.w //0.25f + +// Flashlight constants +const float4 g_vFlashlightAttenuationFactors : register( c7 ); // FarZ in w +#define g_flFarZ g_vFlashlightAttenuationFactors.w +const float3 g_vFlashlightPos : register( c8 ); +const float4 g_vShadowTweaks : register( c9 ); +const float4 g_AverageAmbient : register( c10 ); +#define g_flAverageAmbient g_AverageAmbient.x + +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); + +PixelShaderLightInfo g_sLightInfo[3] : register( PSREG_LIGHT_INFO_ARRAY ); // 2 registers each - 6 registers total + +#if UBERLIGHT && defined( SHADER_MODEL_PS_3_0 ) +const float3 g_vSmoothEdge0 : register( PSREG_UBERLIGHT_SMOOTH_EDGE_0 ); // ps_3_0 and up (over 32 registers) +const float3 g_vSmoothEdge1 : register( PSREG_UBERLIGHT_SMOOTH_EDGE_1 ); +const float3 g_vSmoothOneOverWidth : register( PSREG_UBERLIGHT_SMOOTH_EDGE_OOW ); +const float4 g_vShearRound : register( PSREG_UBERLIGHT_SHEAR_ROUND ); +const float4 g_aAbB : register( PSREG_UBERLIGHT_AABB ); +const float4x4 g_FlashlightWorldToLight : register( PSREG_UBERLIGHT_WORLD_TO_LIGHT ); +#endif + +// Interpolated values ============================================================================ +struct PS_INPUT +{ + float4 vAmbientOcclUv_fallbackCorneaUv : TEXCOORD0; + float4 cVertexLight : TEXCOORD1; // w is used for the flashlight pass + float4 vTangentViewVector : TEXCOORD2; // Tangent view vector (Note: w is used for flashlight pass) + float4 vWorldPosition_ProjPosZ : TEXCOORD3; + float3 vWorldNormal : TEXCOORD4; // World-space normal + float3 vWorldTangent : TEXCOORD5; // World-space tangent + float4 vLightFalloffCosine01 : TEXCOORD6; // Light falloff and cosine terms for first two local lights + float4 vLightFalloffCosine23 : TEXCOORD7; // Light falloff and cosine terms for next two local lights + + float3 vWorldBinormal : COLOR0; // World-space normal + +#ifdef SHADER_MODEL_PS_3_0 + float2 vPos : VPOS; // Normalized Screenpos, call ComputeScreenPos() to get useful 2D coordinates +#endif +}; + +// Ray sphere intersect returns distance along ray to intersection ================================ +float IntersectRaySphere ( float3 cameraPos, float3 ray, float3 sphereCenter, float sphereRadius) +{ + float3 dst = cameraPos.xyz - sphereCenter.xyz; + float B = dot(dst, ray); + float C = dot(dst, dst) - (sphereRadius * sphereRadius); + float D = B*B - C; + return (D > 0) ? (-B - sqrt(D)) : 0; +} + + +// Main =========================================================================================== +float4 main( PS_INPUT i ) : COLOR +{ + // Set bools to compile out code + bool bFlashlight = ( FLASHLIGHT != 0 ) ? true : false; + bool bDoDiffuseWarp = LIGHTWARPTEXTURE ? true : false; + int nNumLights = FLASHLIGHT ? 1 : NUM_LIGHTS; // Flashlight is considered one light, otherwise, use numlights combo + +#if !defined( SHADER_MODEL_PS_2_0 ) + bool bRayCast = RAYTRACESPHERE ? true : false; + bool bRayCastTexKill = SPHERETEXKILLCOMBO ? true : false; +#endif + + float flFlashlightNDotL = i.vTangentViewVector.w; + float4 vFlashlightTexCoord = { 0.0f, 0.0f, 0.0f, 0.0f }; + if ( bFlashlight ) + { + vFlashlightTexCoord.xyzw = i.cVertexLight.xyzw; // This was hidden in this interpolator + i.cVertexLight.rgba = float4( 0.0f, 0.0f, 0.0f, 0.0f ); + } + + // Interpolated vectors + float3 vWorldNormal = i.vWorldNormal.xyz; + float3 vWorldTangent = i.vWorldTangent.xyz; + float3 vWorldBinormal = ( i.vWorldBinormal.xyz * 2.0f ) - 1.0f; // normalize( cross( vWorldNormal.xyz, vWorldTangent.xyz ) ); + + #if ( WORLD_NORMAL ) + { + return float4( vWorldNormal, i.vWorldPosition_ProjPosZ.w ); + } + #endif + + float3 vTangentViewVector = i.vTangentViewVector.xyz; + + // World position + float3 vWorldPosition = i.vWorldPosition_ProjPosZ.xyz; + + // World view vector to pixel + float3 vWorldViewVector = normalize( vWorldPosition.xyz - g_vCameraPosition.xyz ); + + //=================// + // TF NPR lighting // + //=================// + if ( bDoDiffuseWarp ) + { + // Replace the interpolated vertex light + if ( bFlashlight == true ) + { + // Deal with this below in the flashlight section + } + else + { + if ( nNumLights > 0 ) + { + float3 cWarpedLight = 2.0f * tex1D( g_tLightwarpSampler, i.vLightFalloffCosine01.z ).rgb; + i.cVertexLight.rgb += i.vLightFalloffCosine01.x * PixelShaderGetLightColor( g_sLightInfo, 0 ) * cWarpedLight.rgb; + } + + if ( nNumLights > 1 ) + { + float3 cWarpedLight = 2.0f * tex1D( g_tLightwarpSampler, i.vLightFalloffCosine01.w ).rgb; + i.cVertexLight.rgb += i.vLightFalloffCosine01.y * PixelShaderGetLightColor( g_sLightInfo, 1 ) * cWarpedLight.rgb; + } + + if ( nNumLights > 2 ) + { + float3 cWarpedLight = 2.0f * tex1D( g_tLightwarpSampler, i.vLightFalloffCosine23.z ).rgb; + i.cVertexLight.rgb += i.vLightFalloffCosine23.x * PixelShaderGetLightColor( g_sLightInfo, 2 ) * cWarpedLight.rgb; + } + + if ( nNumLights > 3 ) + { + float3 cWarpedLight = 2.0f * tex1D( g_tLightwarpSampler, i.vLightFalloffCosine23.w ).rgb; + i.cVertexLight.rgb += i.vLightFalloffCosine23.y * PixelShaderGetLightColor( g_sLightInfo, 3 ) * cWarpedLight.rgb; + } + } + } + + //==========================================================================================================// + // Ray cast against sphere representing eyeball to reduce artifacts from non-spherical morphed eye geometry // + //==========================================================================================================// +#if !defined( SHADER_MODEL_PS_2_0 ) + if ( bRayCast ) + { + float fSphereRayCastDistance = IntersectRaySphere( g_vCameraPosition.xyz, vWorldViewVector.xyz, g_vEyeOrigin.xyz, g_flEyeballRadius ); + vWorldPosition.xyz = g_vCameraPosition.xyz + ( vWorldViewVector.xyz * fSphereRayCastDistance ); + if (fSphereRayCastDistance == 0) + { + if ( bRayCastTexKill ) + clip(-1); // texkill to get a better silhouette + vWorldPosition.xyz = g_vEyeOrigin.xyz + ( vWorldNormal.xyz * g_flEyeballRadius ); + } + } +#endif + + //=================================// + // Generate sphere and cornea uv's // + //=================================// +#if !defined( SHADER_MODEL_PS_2_0 ) + float2 vCorneaUv; // Note: Cornea texture is a cropped version of the iris texture + vCorneaUv.x = dot( g_vIrisProjectionU, float4( vWorldPosition, 1.0f ) ); + vCorneaUv.y = dot( g_vIrisProjectionV, float4( vWorldPosition, 1.0f ) ); + float2 vSphereUv = ( vCorneaUv.xy * 0.5f ) + 0.25f; +#else // ps_20 + float2 vCorneaUv = i.vAmbientOcclUv_fallbackCorneaUv.wz; // Note: Cornea texture is a cropped version of the iris texture + float2 vSphereUv = ( vCorneaUv.xy * 0.5f ) + 0.25f; +#endif + + //=================================// + // Hacked parallax mapping on iris // + //=================================// + float fIrisOffset = tex2D( g_tCorneaSampler, vCorneaUv.xy ).b; + +#if !defined( SHADER_MODEL_PS_2_0 ) + float2 vParallaxVector = ( ( vTangentViewVector.xy * fIrisOffset * g_flParallaxStrength ) / ( 1.0f - vTangentViewVector.z ) ); // Note: 0.25 is a magic number + vParallaxVector.x = -vParallaxVector.x; //Need to flip x...not sure why. + //vParallaxVector.x *= -1.0; //Need to flip x...not sure why. + //vParallaxVector = 0.0f; //Disable parallax for debugging +#else // Disable parallax effect in 2.0 version + float2 vParallaxVector = { 0.0f, 0.0f }; +#endif + + float2 vIrisUv = vSphereUv.xy - vParallaxVector.xy; + + // Note: We fetch from this texture twice right now with different uv's for the color and alpha + float2 vCorneaNoiseUv = vSphereUv.xy + ( vParallaxVector.xy * 0.5 ); + float fCorneaNoise = tex2D( g_tIrisSampler, vCorneaNoiseUv.xy ).a; + + //===============// + // Cornea normal // + //===============// + // Sample 2D normal from texture + float3 vCorneaTangentNormal = { 0.0, 0.0, 1.0 }; + float4 vCorneaSample = tex2D( g_tCorneaSampler, vCorneaUv.xy ); + vCorneaTangentNormal.xy = vCorneaSample.rg - 0.5f; // Note: This scales the bump to 50% strength + + // Scale strength of normal + vCorneaTangentNormal.xy *= g_flCorneaBumpStrength; + + // Add in surface noise and imperfections (NOTE: This should be baked into the normal map!) + vCorneaTangentNormal.xy += fCorneaNoise * 0.1f; + + // Normalize tangent vector +#if !defined( SHADER_MODEL_PS_2_0 ) + // Since this isn't used later in 2.0, skip the normalize to save shader instructions + vCorneaTangentNormal.xyz = normalize( vCorneaTangentNormal.xyz ); +#endif + + // Transform into world space + float3 vCorneaWorldNormal = Vec3TangentToWorldNormalized( vCorneaTangentNormal.xyz, vWorldNormal.xyz, vWorldTangent.xyz, vWorldBinormal.xyz ); + + //============// + // Flashlight // + //============// + float3 vFlashlightVector = { 0.0f, 0.0f, 0.0f }; + float3 cFlashlightColorFalloff = { 0.0f, 0.0f, 0.0f }; + if ( bFlashlight == true ) + { + // Flashlight vector + vFlashlightVector.xyz = normalize( g_vFlashlightPos.xyz - i.vWorldPosition_ProjPosZ.xyz ); + + // Distance attenuation for flashlight and to fade out shadow over distance + float3 vDelta = g_vFlashlightPos.xyz - i.vWorldPosition_ProjPosZ.xyz; + float flDistSquared = dot( vDelta, vDelta ); + float flDist = sqrt( flDistSquared ); + float flFlashlightAttenuation = saturate( dot( g_vFlashlightAttenuationFactors.xyz, float3( 1.0f, 1.0f/flDist, 1.0f/flDistSquared ) ) ); + float flEndFalloffFactor = RemapValClamped( flDist, g_flFarZ, 0.6f * g_flFarZ, 0.0f, 1.0f ); // Ramp down at end of range + + // Flashlight cookie +#if !defined( SHADER_MODEL_PS_2_0 ) + float3 vProjCoords = vFlashlightTexCoord.xyz / vFlashlightTexCoord.w; + float3 cFlashlightCookieColor = tex2D( g_tFlashlightCookieSampler, vProjCoords ); +#else + float3 cFlashlightCookieColor = tex2Dproj( g_tFlashlightCookieSampler, vFlashlightTexCoord.xyzw ); +#endif + + +#if UBERLIGHT && defined( SHADER_MODEL_PS_3_0 ) + float4 uberLightPosition = mul( float4( i.vWorldPosition_ProjPosZ.xyz, 1.0f ), g_FlashlightWorldToLight ).yzxw; + cFlashlightCookieColor *= uberlight( uberLightPosition, g_vSmoothEdge0, g_vSmoothEdge1, + g_vSmoothOneOverWidth, g_vShearRound.xy, g_aAbB, g_vShearRound.zw ); +#endif + +#if !defined( _X360 ) + cFlashlightCookieColor *= vFlashlightTexCoord.www > float3(0,0,0); // Catch back projection (PC-only) +#endif + + // Shadow depth map +#if FLASHLIGHTSHADOWS && !defined( SHADER_MODEL_PS_2_0 ) + int nShadowLevel = FLASHLIGHTDEPTHFILTERMODE; + float flShadow = DoFlashlightShadow( g_tFlashlightDepthSampler, g_tRandomRotationSampler, vProjCoords, float2(0,0), nShadowLevel, g_vShadowTweaks, false ); + float flAttenuated = lerp( flShadow, 1.0f, g_vShadowTweaks.y ); // Blend between fully attenuated and not attenuated + flShadow = saturate( lerp( flAttenuated, flShadow, flFlashlightAttenuation ) ); // Blend between shadow and above, according to light attenuation + cFlashlightCookieColor *= flShadow; // Apply shadow term to cookie color +#endif + + // Make sure attenuation falls off to zero in last 40% of range + flFlashlightAttenuation *= RemapValClamped( flDist, g_vFlashlightAttenuationFactors.w, 0.6f * g_vFlashlightAttenuationFactors.w, 0.0f, 1.0f ); + + // Flashlight color intensity (needs to be multiplied by global flashlight color later) + cFlashlightColorFalloff.rgb = flFlashlightAttenuation * cFlashlightCookieColor.rgb; + + // Add this into the interpolated lighting + i.cVertexLight.rgb += cFlashlightColorFalloff.rgb * cFlashlightColor.rgb * flFlashlightNDotL; //TODO: bDoDiffuseWarp in flashlight pass? + } + + //==============// + // Dilate pupil // + //==============// +#if !defined( SHADER_MODEL_PS_2_0 ) + vIrisUv.xy -= 0.5f; // Center around (0,0) + float fPupilCenterToBorder = saturate( length( vIrisUv.xy ) / 0.2f ); //Note: 0.2 is the uv radius of the iris + float fPupilDilateFactor = g_flDilationFactor; // This value should be between 0-1 + vIrisUv.xy *= lerp (1.0f, fPupilCenterToBorder, saturate( fPupilDilateFactor ) * 2.5f - 1.25f ); + vIrisUv.xy += 0.5f; +#endif + + //============// + // Iris color // + //============// + float4 cIrisColor = tex2D( g_tIrisSampler, vIrisUv.xy ); + + //==========================// + // Iris lighting highlights // + //==========================// + float3 cIrisLighting = float3( 0.0f, 0.0f, 0.0f ); + +#if !defined( SHADER_MODEL_PS_2_0 ) + // Mask off everything but the iris pixels + float fIrisHighlightMask = tex2D( g_tCorneaSampler, vCorneaUv.xy ).a; + + // Generate the normal + float3 vIrisTangentNormal = vCorneaTangentNormal.xyz; + vIrisTangentNormal.xy *= -2.5f; // I'm not normalizing on purpose + + for ( int j=0; j < nNumLights; j++ ) + { + // World light vector + float3 vWorldLightVector; + if ( ( j == 0 ) && ( bFlashlight == true ) ) + vWorldLightVector = vFlashlightVector.xyz; + else + vWorldLightVector = PixelShaderGetLightVector( i.vWorldPosition_ProjPosZ.xyz, g_sLightInfo, j ); + + // Tangent light vector + float3 vTangentLightVector = Vec3WorldToTangent( vWorldLightVector.xyz, vWorldNormal.xyz, vWorldTangent.xyz, vWorldBinormal.xyz ); + + // Adjust the tangent light vector to generate the iris lighting + float3 tmpv = -vTangentLightVector.xyz; + tmpv.xy *= -0.5f; //Flatten tangent view + tmpv.z = max( tmpv.z, 0.5f ); //Clamp z of tangent view to help maintain highlight + tmpv.xyz = normalize( tmpv.xyz ); + + // Core iris lighting math + float fIrisFacing = pow( abs( dot( vIrisTangentNormal.xyz, tmpv.xyz ) ), 6.0f ) * 0.5f; // Yes, 6.0 and 0.5 are magic numbers + + // Cone of darkness to darken iris highlights when light falls behind eyeball past a certain point + float flConeOfDarkness = pow( 1.0f - saturate( ( -vTangentLightVector.z - 0.25f ) / 0.75f ), 4.0f ); + //float flConeOfDarkness = pow( 1.0f - saturate( ( -dot( vIrisTangentNormal.xyz, vTangentLightVector.xyz ) - 0.15f ) / 0.85f ), 8.0f ); + + // Tint by iris color and cone of darkness + float3 cIrisLightingTmp = fIrisFacing * fIrisHighlightMask * flConeOfDarkness; + + // Attenuate by light color and light falloff + if ( ( j == 0 ) && ( bFlashlight == true ) ) + cIrisLightingTmp.rgb *= cFlashlightColorFalloff.rgb * cFlashlightColor.rgb; + else if ( j == 0 ) + cIrisLightingTmp.rgb *= i.vLightFalloffCosine01.x * PixelShaderGetLightColor( g_sLightInfo, 0 ); + else if ( j == 1 ) + cIrisLightingTmp.rgb *= i.vLightFalloffCosine01.y * PixelShaderGetLightColor( g_sLightInfo, 1 ); + else if ( j == 2 ) + cIrisLightingTmp.rgb *= i.vLightFalloffCosine23.x * PixelShaderGetLightColor( g_sLightInfo, 2 ); + else + cIrisLightingTmp.rgb *= i.vLightFalloffCosine23.y * PixelShaderGetLightColor( g_sLightInfo, 3 ); + + // Sum into final variable + cIrisLighting.rgb += cIrisLightingTmp.rgb; + } + + // Add slight view dependent iris lighting based on ambient light intensity to enhance situations with no local lights (0.5f is to help keep it subtle) + cIrisLighting.rgb += saturate( dot( vIrisTangentNormal.xyz, -vTangentViewVector.xyz ) ) * g_flAverageAmbient * fIrisHighlightMask * 0.5f; +#else + // Else, intensify light over cornea to simulate the brightening that happens above + cIrisLighting.rgb += i.cVertexLight.rgb * vCorneaSample.a; +#endif + + //===================// + // Ambient occlusion // + //===================// + float3 cAmbientOcclFromTexture = tex2D( g_tEyeAmbientOcclSampler, i.vAmbientOcclUv_fallbackCorneaUv.xy ).rgb; + float3 cAmbientOcclColor = lerp( g_cAmbientOcclColor.rgb, float3(1.0f, 1.0f, 1.0f), cAmbientOcclFromTexture.rgb ); // Color the ambient occlusion + i.cVertexLight.rgb *= cAmbientOcclColor.rgb; + + //==========================// + // Reflection from cube map // + //==========================// + float3 vCorneaReflectionVector = reflect ( vWorldViewVector.xyz, vCorneaWorldNormal.xyz ); + + //float3 cReflection = ENV_MAP_SCALE * texCUBE( g_tEyeReflectionCubemapSampler, vCorneaReflectionVector.xyz ).rgb; + float3 cReflection = g_flGlossiness * texCUBE( g_tEyeReflectionCubemapSampler, vCorneaReflectionVector.xyz ).rgb; + + // Hack: Only add in half of the env map for the flashlight pass. This looks reasonable. + if ( bFlashlight ) + { + cReflection.rgb *= 0.5f; + } + + //===========================// + // Glint specular highlights // + //===========================// + float3 cSpecularHighlights = 0.0f; + if ( bFlashlight ) + { + cSpecularHighlights.rgb += pow( saturate( dot( vCorneaReflectionVector.xyz, vFlashlightVector.xyz ) ), 128.0f ) * cFlashlightColorFalloff.rgb * cFlashlightColor.rgb; + } + else // no flashlight + { + if ( nNumLights > 0 ) + cSpecularHighlights.rgb += pow( saturate( dot( vCorneaReflectionVector.xyz, PixelShaderGetLightVector( i.vWorldPosition_ProjPosZ.xyz, g_sLightInfo, 0 ) ) ), 128.0f ) * i.vLightFalloffCosine01.x * PixelShaderGetLightColor( g_sLightInfo, 0 ); + + if ( nNumLights > 1 ) + cSpecularHighlights.rgb += pow( saturate( dot( vCorneaReflectionVector.xyz, PixelShaderGetLightVector( i.vWorldPosition_ProjPosZ.xyz, g_sLightInfo, 1 ) ) ), 128.0f ) * i.vLightFalloffCosine01.y * PixelShaderGetLightColor( g_sLightInfo, 1 ); + + if ( nNumLights > 2 ) + cSpecularHighlights.rgb += pow( saturate( dot( vCorneaReflectionVector.xyz, PixelShaderGetLightVector( i.vWorldPosition_ProjPosZ.xyz, g_sLightInfo, 2 ) ) ), 128.0f ) * i.vLightFalloffCosine23.x * PixelShaderGetLightColor( g_sLightInfo, 2 ); + + if ( nNumLights > 3 ) + cSpecularHighlights.rgb += pow( saturate( dot( vCorneaReflectionVector.xyz, PixelShaderGetLightVector( i.vWorldPosition_ProjPosZ.xyz, g_sLightInfo, 3 ) ) ), 128.0f ) * i.vLightFalloffCosine23.y * PixelShaderGetLightColor( g_sLightInfo, 3 ); + } + + // Screen-space dynamic ambient occlusion on PC + float fAmbientOcclusion = 1.0f; + #if ( !defined( _X360 ) && defined( SHADER_MODEL_PS_3_0 ) ) + { + fAmbientOcclusion = lerp( 1.0f, tex2D( g_tAmbientOcclusionSampler, ComputeScreenPos( i.vPos ) ).r, g_cAmbientOcclColor.w ); + } + #endif + + //===============// + // Combine terms // + //===============// + float4 result; + + // Unlit iris, pupil, and sclera color + result.rgb = cIrisColor.rgb; + + // Add in slight cornea noise to help define raised cornea layer for close-ups + result.rgb += fCorneaNoise * 0.1f; + + // Diffuse light (Vertex lighting + extra iris caustic lighting) + result.rgb *= i.cVertexLight.rgb + cIrisLighting.rgb; + + // Environment map + result.rgb += cReflection.rgb * i.cVertexLight.rgb; + + // Local light glints + result.rgb += cSpecularHighlights.rgb; + + // Attenuate by ambient occlusion + result.rgb *= fAmbientOcclusion; + + // Set alpha to 1.0 by default + result.a = 1.0; + + float fogFactor = 0.0f; + + #if ( !defined( SHADER_MODEL_PS_2_0 ) ) + { + fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_vCameraPosition.xyz, i.vWorldPosition_ProjPosZ.xyz, i.vWorldPosition_ProjPosZ.w ); + } + #endif + + // Always write depth to dest alpha since we are always either opaque or using additive blending (ie. not using alpha to do blending). + bool bWriteDepthToDestAlpha = true; + return FinalOutput( result, fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, bWriteDepthToDestAlpha, i.vWorldPosition_ProjPosZ.w ); +} diff --git a/materialsystem/stdshaders/eye_refract_vs20.fxc b/materialsystem/stdshaders/eye_refract_vs20.fxc new file mode 100644 index 00000000..fc909c40 --- /dev/null +++ b/materialsystem/stdshaders/eye_refract_vs20.fxc @@ -0,0 +1,253 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "INTRO" "0..1" +// STATIC: "HALFLAMBERT" "0..1" +// STATIC: "FLASHLIGHT" "0..1" +// STATIC: "LIGHTWARPTEXTURE" "0..1" +// STATIC: "WORLD_NORMAL" "0..0" [vs20] [PC] +// STATIC: "WORLD_NORMAL" "0..1" [vs30] [PC] +// STATIC: "WORLD_NORMAL" "0..0" [XBOX] + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "SKINNING" "0..1" +#include "common_fog_vs_fxc.h" +// DYNAMIC: "DYNAMIC_LIGHT" "0..1" +// DYNAMIC: "NUM_LIGHTS" "0..4" +// DYNAMIC: "TESSELLATION" "0..2" [vs30] [PC] +// DYNAMIC: "TESSELLATION" "0..0" [XBOX] +// DYNAMIC: "TESSELLATION" "0..0" [vs20] [PC] + +// DYNAMIC: "MORPHING" "0..1" [vs30] [ = pShaderAPI->IsHWMorphingEnabled() ] + +// These are mutually exclusive (constant collision) +// SKIP: ( $WORLD_NORMAL ) && $INTRO + +// SKIP: ( $MORPHING || $SKINNING || $COMPRESSED_VERTS ) && $TESSELLATION + +#include "vortwarp_vs20_helper.h" + +static const bool g_bSkinning = SKINNING ? true : false; +static const int g_iFogType = DOWATERFOG; +static const bool g_bHalfLambert = HALFLAMBERT ? true : false; + +const float3 g_cEyeOrigin : register( SHADER_SPECIFIC_CONST_0 ); +const float4 g_vIrisProjectionU : register( SHADER_SPECIFIC_CONST_2 ); +const float4 g_vIrisProjectionV : register( SHADER_SPECIFIC_CONST_3 ); +const float4 g_vFlashlightPosition : register( SHADER_SPECIFIC_CONST_4 ); + +#if ( INTRO ) + const float4 g_vConst4 : register( SHADER_SPECIFIC_CONST_5 ); + #define g_vModelOrigin g_vConst4.xyz + #define g_flTime g_vConst4.w +#elif ( WORLD_NORMAL ) + const float4 g_vEyeVector : register( SHADER_SPECIFIC_CONST_5 ); +#endif + +const float4x4 g_vFlashlightMatrix : register( SHADER_SPECIFIC_CONST_6 ); // 6 & 7 & 8 & 9 +#ifdef SHADER_MODEL_VS_3_0 +// NOTE: cMorphTargetTextureDim.xy = target dimensions, +// cMorphTargetTextureDim.z = 4tuples/morph +const float3 cMorphTargetTextureDim : register( SHADER_SPECIFIC_CONST_10 ); +const float4 cMorphSubrect : register( SHADER_SPECIFIC_CONST_11 ); +sampler2D morphSampler : register( D3DVERTEXTEXTURESAMPLER0, s0 ); +#endif + + + +#if TESSELLATION + +#include "tessellation_vs_fxc.h" + +const float4 g_SubDControls : register( SHADER_SPECIFIC_CONST_1 ); +sampler2D BezierSampler : register( s1 ); +sampler2D DispSampler : register( s2 ); +// VS_INPUT defined in header + +#else // no TESSELLATION + +struct VS_INPUT +{ + float4 vPos : POSITION; // Position + float4 vBoneWeights : BLENDWEIGHT; // Skin weights + float4 vBoneIndices : BLENDINDICES; // Skin indices + float4 vTexCoord0 : TEXCOORD0; // Base (sclera) texture coordinates + + // Position deltas + float3 vPosFlex : POSITION1; + +#ifdef SHADER_MODEL_VS_3_0 + float vVertexID : POSITION2; +#endif +}; + +#endif // TESSELLATION + +struct VS_OUTPUT +{ + float4 projPos : POSITION; // Projection-space position +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + float fog : FOG; // Fixed-function fog factor +#endif + float4 vAmbientOcclUv_fallbackCorneaUv : TEXCOORD0; // Base texture coordinate + float4 cVertexLight : TEXCOORD1; // Vertex-lit color (Note: w is used for flashlight pass) + float4 vTangentViewVector : TEXCOORD2; // Tangent view vector (Note: w is used for flashlight pass) + float4 vWorldPosition_ProjPosZ : TEXCOORD3; + float3 vWorldNormal : TEXCOORD4; // World-space normal + float3 vWorldTangent : TEXCOORD5; // World-space tangent + float4 vLightFalloffCosine01 : TEXCOORD6; // Light falloff and cosine terms for first two local lights + float4 vLightFalloffCosine23 : TEXCOORD7; // Light falloff and cosine terms for next two local lights + + float3 vWorldBinormal : COLOR0; // World-space normal +}; + + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o; + + bool bDynamicLight = DYNAMIC_LIGHT ? true : false; + + float2 baseTexCoords; + float3 vWorldPosition; + + #if ( TESSELLATION ) + { + float3 dummyNormal; + float2 patchCoords; + EvaluateSubdivisionSurface( v, g_SubDControls.x, g_SubDControls.y, g_SubDControls.z, BezierSampler, DispSampler, + dummyNormal, vWorldPosition, baseTexCoords, patchCoords ); + } + #else // not tessellating + { + float4 vPosition = v.vPos; + baseTexCoords = v.vTexCoord0.xy; + + #if ( !defined( SHADER_MODEL_VS_3_0 ) || !MORPHING ) + { + ApplyMorph( v.vPosFlex, vPosition.xyz ); + } + #else + { + ApplyMorph( morphSampler, cMorphTargetTextureDim, cMorphSubrect, v.vVertexID, float3( 0, 0, 0 ), vPosition.xyz ); + } + #endif + + // Transform the position + SkinPosition( g_bSkinning, vPosition, v.vBoneWeights, v.vBoneIndices, vWorldPosition ); + } + #endif // TESSELLATION + + // Note: I'm relying on the iris projection vector math not changing or this will break + float3 vEyeSocketUpVector = normalize( -g_vIrisProjectionV.xyz ); + float3 vEyeSocketLeftVector = normalize( -g_vIrisProjectionU.xyz ); + + #if ( INTRO ) + { + float3 dummy = float3( 0.0f, 0.0f, 0.0f ); + WorldSpaceVertexProcess( g_flTime, g_vModelOrigin, vWorldPosition, dummy, dummy, dummy ); + } + #endif + + o.vWorldPosition_ProjPosZ.xyz = vWorldPosition.xyz; + + // Transform into projection space + float4 vProjPos = mul( float4( vWorldPosition, 1.0f ), cViewProj ); + #if defined( _X360 ) + { + // Without the isolate keyword here the output position for the flashlight pass is slightly behind the position of the main pass + // and the flashlight pass will be z-culled. + [isolate] o.projPos = vProjPos; + } + #else + { + o.projPos = vProjPos; + } + #endif + +#if ( WORLD_NORMAL ) + o.vWorldPosition_ProjPosZ.w = dot( g_vEyeVector, vWorldPosition.xyz - cEyePos.xyz ); // Linear depth +#else + o.vWorldPosition_ProjPosZ.w = vProjPos.z; +#endif + +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + o.fog = CalcFixedFunctionFog( vWorldPosition, g_iFogType ); +#endif + + // Normal = (Pos - Eye origin) + float3 vWorldNormal = normalize( vWorldPosition.xyz - g_cEyeOrigin.xyz ); + o.vWorldNormal.xyz = vWorldNormal.xyz; + + // Tangent & binormal + float3 vWorldTangent = normalize( cross( vEyeSocketUpVector.xyz, vWorldNormal.xyz ) ); + o.vWorldTangent.xyz = vWorldTangent.xyz; + + float3 vWorldBinormal = normalize( cross( vWorldNormal.xyz, vWorldTangent.xyz ) ); + o.vWorldBinormal.xyz = vWorldBinormal.xyz * 0.5f + 0.5f; + + float3 vWorldViewVector = normalize (vWorldPosition.xyz - cEyePos.xyz); + o.vTangentViewVector.xyz = Vec3WorldToTangentNormalized (vWorldViewVector.xyz, vWorldNormal.xyz, vWorldTangent.xyz, vWorldBinormal.xyz); + + // AV - I think this will effectively make the eyeball less rounded left to right to help vertex lighting quality + // AV - Note: This probably won't look good if put on an exposed eyeball + //float vNormalDotSideVec = -dot( vWorldNormal, g_vEyeballUp ) * 0.5f; + float vNormalDotSideVec = -dot( vWorldNormal, vEyeSocketLeftVector) * 0.5f; + float3 vBentWorldNormal = normalize(vNormalDotSideVec * vEyeSocketLeftVector + vWorldNormal); + + // Compute vertex lighting + o.cVertexLight.a = 0.0f; //Only used for flashlight pass + o.cVertexLight.rgb = DoLightingUnrolled( vWorldPosition, vBentWorldNormal, float3(0.0f, 0.0f, 0.0f), false, bDynamicLight, g_bHalfLambert, NUM_LIGHTS ); + + // Only interpolate ambient light for TF NPR lighting + bool bDoDiffuseWarp = LIGHTWARPTEXTURE ? true : false; + if ( bDoDiffuseWarp ) + { + if( bDynamicLight ) + { + o.cVertexLight.rgb = AmbientLight( vBentWorldNormal.xyz ); + } + else + { + o.cVertexLight.rgb = float3( 0.0f, 0.0f, 0.0f ); + } + } + + // Light falloff for first two local lights + o.vLightFalloffCosine01.x = VertexAttenInternal( vWorldPosition.xyz, 0 ); + o.vLightFalloffCosine01.y = VertexAttenInternal( vWorldPosition.xyz, 1 ); + o.vLightFalloffCosine01.z = CosineTermInternal( vWorldPosition.xyz, vWorldNormal.xyz, 0, g_bHalfLambert ); + o.vLightFalloffCosine01.w = CosineTermInternal( vWorldPosition.xyz, vWorldNormal.xyz, 1, g_bHalfLambert ); + + // Light falloff for next two local lights + o.vLightFalloffCosine23.x = VertexAttenInternal( vWorldPosition.xyz, 2 ); + o.vLightFalloffCosine23.y = VertexAttenInternal( vWorldPosition.xyz, 3 ); + o.vLightFalloffCosine23.z = CosineTermInternal( vWorldPosition.xyz, vWorldNormal.xyz, 2, g_bHalfLambert ); + o.vLightFalloffCosine23.w = CosineTermInternal( vWorldPosition.xyz, vWorldNormal.xyz, 3, g_bHalfLambert ); + + // Texture coordinates set by artists for ambient occlusion + o.vAmbientOcclUv_fallbackCorneaUv.xy = baseTexCoords; + + // Cornea uv for ps.2.0 fallback + float2 vCorneaUv; // Note: Cornea texture is a cropped version of the iris texture + vCorneaUv.x = dot( g_vIrisProjectionU, float4( vWorldPosition, 1.0f ) ); + vCorneaUv.y = dot( g_vIrisProjectionV, float4( vWorldPosition, 1.0f ) ); + float2 vSphereUv = ( vCorneaUv.xy * 0.5f ) + 0.25f; + o.vAmbientOcclUv_fallbackCorneaUv.wz = vCorneaUv.xy; // Note: wz unpacks faster than zw in ps.2.0! + + // Step on the vertex light interpolator for the flashlight tex coords + bool bFlashlight = ( FLASHLIGHT != 0 ) ? true : false; + o.vTangentViewVector.w = 0.0f; + if ( bFlashlight ) + { + o.cVertexLight = mul( float4( vWorldPosition.xyz, 1.0f ), g_vFlashlightMatrix ); + + o.vTangentViewVector.w = saturate( dot( vBentWorldNormal.xyz, normalize ( g_vFlashlightPosition.xyz - vWorldPosition.xyz ) ) ); // Flashlight N.L with modified normal + + // Half lambert version + //o.cVertexLight.z = dot( vBentWorldNormal.xyz, normalize ( g_vFlashlightPosition.xyz - vWorldPosition.xyz ) ); // Flashlight N.L with modified normal + //o.cVertexLight.z = ( o.cVertexLight.z * 0.5f ) + 0.5f; + //o.cVertexLight.z *= o.cVertexLight.z; + } + + return o; +} diff --git a/materialsystem/stdshaders/eyeball.cpp b/materialsystem/stdshaders/eyeball.cpp new file mode 100644 index 00000000..f7a9264d --- /dev/null +++ b/materialsystem/stdshaders/eyeball.cpp @@ -0,0 +1,37 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: Eyeball shader +// +//=============================================================================// + +#include "basevsshader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_VS_SHADER( Eyeball, "Help for EyeBall" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM_OVERRIDE( BASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "models/alyx/pupil_l", "iris texture", 0 ) + SHADER_PARAM_OVERRIDE( BASETEXTURETRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "unused", SHADER_PARAM_NOT_EDITABLE ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + } + + SHADER_FALLBACK + { + // This should be a dead shader... + return "Wireframe"; + } + + SHADER_INIT + { + } + + SHADER_DRAW + { + } + +END_SHADER diff --git a/materialsystem/stdshaders/eyeglint_dx9.cpp b/materialsystem/stdshaders/eyeglint_dx9.cpp new file mode 100644 index 00000000..659e51ef --- /dev/null +++ b/materialsystem/stdshaders/eyeglint_dx9.cpp @@ -0,0 +1,66 @@ +//===== Copyright © 1996-2007, Valve Corporation, All rights reserved. ======// +// +// Run procedural glint generation inner loop in pixel shader +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" +#include "shaderlib/CShader.h" + +#include "eyeglint_vs20.inc" +#include "eyeglint_ps20.inc" +#include "eyeglint_ps20b.inc" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +DEFINE_FALLBACK_SHADER( EyeGlint, EyeGlint_dx9 ) +BEGIN_VS_SHADER( EyeGlint_dx9, "Help for EyeGlint" ) + +BEGIN_SHADER_PARAMS +END_SHADER_PARAMS + +SHADER_INIT +{ +} + +SHADER_FALLBACK +{ + return 0; +} + +SHADER_DRAW +{ + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); // Additive blending + + int pTexCoords[3] = { 2, 2, 3 }; + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 3, pTexCoords, 0 ); + + pShaderShadow->EnableCulling( false ); + + pShaderShadow->EnableSRGBWrite( true ); + + DECLARE_STATIC_VERTEX_SHADER( eyeglint_vs20 ); + SET_STATIC_VERTEX_SHADER( eyeglint_vs20 ); + + SET_STATIC_PS2X_PIXEL_SHADER_NO_COMBOS( eyeglint ); + } + + DYNAMIC_STATE + { + DECLARE_DYNAMIC_VERTEX_SHADER( eyeglint_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( eyeglint_vs20 ); + + SET_DYNAMIC_PS2X_PIXEL_SHADER_NO_COMBOS( eyeglint ); + } + Draw(); +} +END_SHADER diff --git a/materialsystem/stdshaders/eyeglint_ps2x.fxc b/materialsystem/stdshaders/eyeglint_ps2x.fxc new file mode 100644 index 00000000..42449dfb --- /dev/null +++ b/materialsystem/stdshaders/eyeglint_ps2x.fxc @@ -0,0 +1,32 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// +// +// Run procedural glint generation inner loop in pixel shader (ps_2_0) +// +// ==========================================================================// + +struct PS_INPUT +{ + float2 tc : TEXCOORD0; // Interpolated coordinate of current texel + float2 glintCenter : TEXCOORD1; // Uniform value containing center of glint + float3 glintColor : TEXCOORD2; // Uniform value of color of glint +}; + +float GlintGaussSpotCoefficient( float2 d ) +{ + return saturate( exp( -25.0f * dot(d, d) ) ); +} + +float4 main( PS_INPUT i ) : COLOR +{ + float2 uv = i.tc - i.glintCenter; // This texel relative to glint center + + float intensity = GlintGaussSpotCoefficient( uv + float2(-0.25f, -0.25f) ) + + GlintGaussSpotCoefficient( uv + float2( 0.25f, -0.25f) ) + + 5 * GlintGaussSpotCoefficient( uv ) + + GlintGaussSpotCoefficient( uv + float2(-0.25f, 0.25f) ) + + GlintGaussSpotCoefficient( uv + float2( 0.25f, 0.25f) ); + + intensity *= 4.0f/9.0f; + + return float4( intensity * i.glintColor, 1.0f ); +} \ No newline at end of file diff --git a/materialsystem/stdshaders/eyeglint_vs20.fxc b/materialsystem/stdshaders/eyeglint_vs20.fxc new file mode 100644 index 00000000..cf8b83d9 --- /dev/null +++ b/materialsystem/stdshaders/eyeglint_vs20.fxc @@ -0,0 +1,38 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// +// +// Vertex shader to pass through texcoords needed to run the +// procedural glint generation inner loop in the pixel shader +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "common_vs_fxc.h" + +struct VS_INPUT +{ + float3 vPos : POSITION; + float2 tc : TEXCOORD0; // Interpolated coordinate of current texel in 3x3 quad + float2 glintCenter : TEXCOORD1; // Uniform value containing center of glint in local 3x3 quad + float3 glintColor : TEXCOORD2; // Uniform value of color of glint +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; + float2 tc : TEXCOORD0; // Interpolated coordinate of current texel in 3x3 quad + float2 glintCenter : TEXCOORD1; // Uniform value containing center of glint in local 3x3 quad + float3 glintColor : TEXCOORD2; // Uniform value of color of glint +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + o.projPos = float4( v.vPos, 1.0f ); + o.tc = v.tc; + o.glintCenter = v.glintCenter; + o.glintColor = v.glintColor; + return o; +} + + diff --git a/materialsystem/stdshaders/eyes.cpp b/materialsystem/stdshaders/eyes.cpp new file mode 100644 index 00000000..c10dc6da --- /dev/null +++ b/materialsystem/stdshaders/eyes.cpp @@ -0,0 +1,183 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: eye renderer +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" +#include "eyes_dx8_dx9_helper.h" +#include "cloak_blended_pass_helper.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( eyes, Eyes_dx8 ) + +BEGIN_VS_SHADER( Eyes_dx8, + "Help for Eyes" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM_OVERRIDE( BASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "models/alyx/eyeball_l", "iris texture", 0 ) + SHADER_PARAM( IRIS, SHADER_PARAM_TYPE_TEXTURE, "models/alyx/pupil_l", "iris texture" ) + SHADER_PARAM( IRISFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame for the iris texture" ) + SHADER_PARAM( GLINT, SHADER_PARAM_TYPE_TEXTURE, "models/humans/male/glint", "glint texture" ) + SHADER_PARAM( EYEORIGIN, SHADER_PARAM_TYPE_VEC3, "[0 0 0]", "origin for the eyes" ) + SHADER_PARAM( EYEUP, SHADER_PARAM_TYPE_VEC3, "[0 0 1]", "up vector for the eyes" ) + SHADER_PARAM( IRISU, SHADER_PARAM_TYPE_VEC4, "[0 1 0 0]", "U projection vector for the iris" ) + SHADER_PARAM( IRISV, SHADER_PARAM_TYPE_VEC4, "[0 0 1 0]", "V projection vector for the iris" ) + SHADER_PARAM( GLINTU, SHADER_PARAM_TYPE_VEC4, "[0 1 0 0]", "U projection vector for the glint" ) + SHADER_PARAM( GLINTV, SHADER_PARAM_TYPE_VEC4, "[0 0 1 0]", "V projection vector for the glint" ) + SHADER_PARAM( DILATION, SHADER_PARAM_TYPE_FLOAT, "0", "Iris dilation" ) + SHADER_PARAM( INTRO, SHADER_PARAM_TYPE_BOOL, "0", "is eyes in the ep1 intro" ) + SHADER_PARAM( ENTITYORIGIN, SHADER_PARAM_TYPE_VEC3,"0.0","center if the model in world space" ) + SHADER_PARAM( WARPPARAM, SHADER_PARAM_TYPE_FLOAT,"0.0","animation param between 0 and 1" ) + + // Cloak Pass + SHADER_PARAM( CLOAKPASSENABLED, SHADER_PARAM_TYPE_BOOL, "0", "Enables cloak render in a second pass" ) + SHADER_PARAM( CLOAKFACTOR, SHADER_PARAM_TYPE_FLOAT, "0.0", "" ) + SHADER_PARAM( CLOAKCOLORTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Cloak color tint" ) + SHADER_PARAM( REFRACTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "2", "" ) + END_SHADER_PARAMS + + void SetupVars( Eyes_DX8_DX9_Vars_t &info ) + { + info.m_nBaseTexture = BASETEXTURE; + info.m_nFrame = FRAME; + info.m_nIris = IRIS; + info.m_nIrisFrame = IRISFRAME; + info.m_nGlint = GLINT; + info.m_nEyeOrigin = EYEORIGIN; + info.m_nEyeUp = EYEUP; + info.m_nIrisU = IRISU; + info.m_nIrisV = IRISV; + info.m_nGlintU = GLINTU; + info.m_nGlintV = GLINTV; + info.m_nDilation = DILATION; + info.m_nIntro = INTRO; + info.m_nEntityOrigin = ENTITYORIGIN; + info.m_nWarpParam = WARPPARAM; + } + + // Cloak Pass + void SetupVarsCloakBlendedPass( CloakBlendedPassVars_t &info ) + { + info.m_nCloakFactor = CLOAKFACTOR; + info.m_nCloakColorTint = CLOAKCOLORTINT; + info.m_nRefractAmount = REFRACTAMOUNT; + } + + bool NeedsPowerOfTwoFrameBufferTexture( IMaterialVar **params, bool bCheckSpecificToThisFrame ) const + { + if ( params[CLOAKPASSENABLED]->GetIntValue() ) // If material supports cloaking + { + if ( bCheckSpecificToThisFrame == false ) // For setting model flag at load time + return true; + else if ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) // Per-frame check + return true; + // else, not cloaking this frame, so check flag2 in case the base material still needs it + } + + // Check flag2 if not drawing cloak pass + return IS_FLAG2_SET( MATERIAL_VAR2_NEEDS_POWER_OF_TWO_FRAME_BUFFER_TEXTURE ); + } + + bool IsTranslucent( IMaterialVar **params ) const + { + if ( params[CLOAKPASSENABLED]->GetIntValue() ) // If material supports cloaking + { + if ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) // Per-frame check + return true; + // else, not cloaking this frame, so check flag in case the base material still needs it + } + + // Check flag if not drawing cloak pass + return IS_FLAG_SET( MATERIAL_VAR_TRANSLUCENT ); + } + + SHADER_INIT_PARAMS() + { + Eyes_DX8_DX9_Vars_t info; + SetupVars( info ); + InitParamsEyes_DX8_DX9( this, params, pMaterialName, info ); + + // Cloak Pass + if ( !params[CLOAKPASSENABLED]->IsDefined() ) + { + params[CLOAKPASSENABLED]->SetIntValue( 0 ); + } + else if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + InitParamsCloakBlendedPass( this, params, pMaterialName, info ); + } + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + Eyes_DX8_DX9_Vars_t info; + SetupVars( info ); + InitEyes_DX8_DX9( this, params, info ); + + // Cloak Pass + if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + InitCloakBlendedPass( this, params, info ); + } + } + + SHADER_DRAW + { + // Skip the standard rendering if cloak pass is fully opaque + bool bDrawStandardPass = true; + if ( params[CLOAKPASSENABLED]->GetIntValue() && ( pShaderShadow == NULL ) ) // && not snapshotting + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + if ( CloakBlendedPassIsFullyOpaque( params, info ) ) + { + // There is some strangeness in DX8 when trying to skip the main pass, so leave this alone for now + //bDrawStandardPass = false; + } + } + + // Standard rendering pass + if ( bDrawStandardPass ) + { + Eyes_DX8_DX9_Vars_t info; + SetupVars( info ); + DrawEyes_DX8_DX9( false, this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else + { + // Skip this pass! + Draw( false ); + } + + // Cloak Pass + if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + // If ( snapshotting ) or ( we need to draw this frame ) + if ( ( pShaderShadow != NULL ) || ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + DrawCloakBlendedPass( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else // We're not snapshotting and we don't need to draw this frame + { + // Skip this pass! + Draw( false ); + } + } + } +END_SHADER diff --git a/materialsystem/stdshaders/eyes_dx8_dx9_helper.cpp b/materialsystem/stdshaders/eyes_dx8_dx9_helper.cpp new file mode 100644 index 00000000..d946acd7 --- /dev/null +++ b/materialsystem/stdshaders/eyes_dx8_dx9_helper.cpp @@ -0,0 +1,470 @@ +//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======= +// +// Purpose: +// +//============================================================================= + +#include "BaseVSShader.h" +#include "tier1/convar.h" +#include "mathlib/VMatrix.h" +#include "eyes_dx8_dx9_helper.h" +#include "cpp_shader_constant_register_map.h" + +#include "eyes_vs20.inc" +#include "eyes_ps20.inc" +#include "eyes_ps20b.inc" +#include "eyes_flashlight_vs20.inc" +#include "eyes_flashlight_ps20.inc" +#include "eyes_flashlight_ps20b.inc" + +#ifndef _X360 +#include "eyes_vs30.inc" +#include "eyes_ps30.inc" +#include "eyes_flashlight_vs30.inc" +#include "eyes_flashlight_ps30.inc" +#endif + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +void InitParamsEyes_DX8_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, + Eyes_DX8_DX9_Vars_t &info ) +{ + params[FLASHLIGHTTEXTURE]->SetStringValue( GetFlashlightTextureFilename() ); + + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + + Assert( info.m_nIntro != -1 ); + if( info.m_nIntro != -1 && !params[info.m_nIntro]->IsDefined() ) + { + params[info.m_nIntro]->SetIntValue( 0 ); + } +} + +void InitEyes_DX8_DX9( CBaseVSShader *pShader, IMaterialVar** params, Eyes_DX8_DX9_Vars_t &info ) +{ + pShader->LoadTexture( FLASHLIGHTTEXTURE ); + pShader->LoadTexture( info.m_nBaseTexture ); + pShader->LoadTexture( info.m_nIris ); + pShader->LoadTexture( info.m_nGlint ); + + // Be sure dilation is zeroed if undefined + if( !params[info.m_nDilation]->IsDefined() ) + { + params[info.m_nDilation]->SetFloatValue( 0.0f ); + } +} + +static void SetDepthFlashlightParams( CBaseVSShader *pShader, IShaderDynamicAPI *pShaderAPI, const VMatrix& worldToTexture, const FlashlightState_t& flashlightState ) +{ + float atten[4], pos[4], tweaks[4]; + atten[0] = flashlightState.m_fConstantAtten; // Set the flashlight attenuation factors + atten[1] = flashlightState.m_fLinearAtten; + atten[2] = flashlightState.m_fQuadraticAtten; + atten[3] = flashlightState.m_FarZAtten; + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_ATTENUATION, atten, 1 ); + + pos[0] = flashlightState.m_vecLightOrigin[0]; // Set the flashlight origin + pos[1] = flashlightState.m_vecLightOrigin[1]; + pos[2] = flashlightState.m_vecLightOrigin[2]; + pos[3] = flashlightState.m_FarZ; + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_POSITION_RIM_BOOST, pos, 1 ); + + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_TO_WORLD_TEXTURE, worldToTexture.Base(), 4 ); + + // Tweaks associated with a given flashlight + tweaks[0] = ShadowFilterFromState( flashlightState ); + tweaks[1] = ShadowAttenFromState( flashlightState ); + pShader->HashShadow2DJitter( flashlightState.m_flShadowJitterSeed, &tweaks[2], &tweaks[3] ); + pShaderAPI->SetPixelShaderConstant( PSREG_ENVMAP_TINT__SHADOW_TWEAKS, tweaks, 1 ); + + // Dimensions of screen, used for screen-space noise map sampling + float vScreenScale[4] = {1280.0f / 32.0f, 720.0f / 32.0f, 0, 0}; + int nWidth, nHeight; + pShaderAPI->GetBackBufferDimensions( nWidth, nHeight ); + + int nTexWidth, nTexHeight; + pShaderAPI->GetStandardTextureDimensions( &nTexWidth, &nTexHeight, TEXTURE_SHADOW_NOISE_2D ); + + vScreenScale[0] = (float) nWidth / nTexWidth; + vScreenScale[1] = (float) nHeight / nTexHeight; + + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_SCREEN_SCALE, vScreenScale, 1 ); + + if ( IsX360() ) + { + pShaderAPI->SetBooleanPixelShaderConstant( 0, &flashlightState.m_nShadowQuality, 1 ); + } +} + + +static void DrawFlashlight( bool bDX9, CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, Eyes_DX8_DX9_Vars_t &info, VertexCompressionType_t vertexCompression ) +{ + if( pShaderShadow ) + { + pShaderShadow->EnableDepthWrites( false ); + + pShader->EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); // Write over the eyes that were already there + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); // Spot + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); // Base + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); // Normalizing cubemap + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); // Iris + + // Set stream format (note that this shader supports compression) + int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + // Be sure not to write to dest alpha + pShaderShadow->EnableAlphaWrites( false ); + +#ifdef STDSHADER_DX9_DLL_EXPORT + Assert( bDX9 ); + + int nShadowFilterMode = g_pHardwareConfig->GetShadowFilterMode(); // Based upon vendor and device dependent formats +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_STATIC_VERTEX_SHADER( eyes_flashlight_vs20 ); + SET_STATIC_VERTEX_SHADER( eyes_flashlight_vs20 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( eyes_flashlight_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER( eyes_flashlight_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( eyes_flashlight_ps20 ); + SET_STATIC_PIXEL_SHADER( eyes_flashlight_ps20 ); + } + } +#ifndef _X360 + else + { + // The vertex shader uses the vertex id stream + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + + DECLARE_STATIC_VERTEX_SHADER( eyes_flashlight_vs30 ); + SET_STATIC_VERTEX_SHADER( eyes_flashlight_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( eyes_flashlight_ps30 ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER( eyes_flashlight_ps30 ); + } +#endif + + // On DX9, get the gamma read and write correct + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); // Spot + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); // Base + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER3, true ); // Iris + pShaderShadow->EnableSRGBWrite( true ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); // Shadow depth map + pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER4 ); + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); // Shadow noise rotation map + } +#endif + + pShader->FogToBlack(); + } + else + { + VMatrix worldToTexture; + ITexture *pFlashlightDepthTexture; + FlashlightState_t flashlightState = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture ); + + pShader->BindTexture( SHADER_SAMPLER0, flashlightState.m_pSpotlightTexture, flashlightState.m_nSpotlightTextureFrame ); + pShader->BindTexture( SHADER_SAMPLER1, info.m_nBaseTexture, info.m_nFrame ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_NORMALIZATION_CUBEMAP ); + pShader->BindTexture( SHADER_SAMPLER3, info.m_nIris, info.m_nIrisFrame ); + +#ifdef STDSHADER_DX9_DLL_EXPORT + Assert( bDX9 ); + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_DYNAMIC_VERTEX_SHADER( eyes_flashlight_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( eyes_flashlight_vs20 ); + } +#ifndef _X360 + else + { + pShader->SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_10, VERTEX_SHADER_SHADER_SPECIFIC_CONST_11, SHADER_VERTEXTEXTURE_SAMPLER0 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( eyes_flashlight_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( eyes_flashlight_vs30 ); + } +#endif + +// float vPSConst[4] = {params[info.m_nDilation]->GetFloatValue(), 0.0f, 0.0f, 0.0f}; +// pShaderAPI->SetPixelShaderConstant( 0, vPSConst, 1 ); + + SetFlashLightColorFromState( flashlightState, pShaderAPI, false ); + + if( pFlashlightDepthTexture && g_pConfig->ShadowDepthTexture() && flashlightState.m_bEnableShadows ) + { + pShader->BindTexture( SHADER_SAMPLER4, pFlashlightDepthTexture, 0 ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER5, TEXTURE_SHADOW_NOISE_2D ); + } + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + float vEyePos_SpecExponent[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + vEyePos_SpecExponent[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( eyes_flashlight_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, flashlightState.m_bEnableShadows ); + SET_DYNAMIC_PIXEL_SHADER( eyes_flashlight_ps20b ); + + SetDepthFlashlightParams( pShader, pShaderAPI, worldToTexture, flashlightState ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( eyes_flashlight_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( eyes_flashlight_ps20 ); + } + } +#ifndef _X360 + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( eyes_flashlight_ps30 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, flashlightState.m_bEnableShadows ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( UBERLIGHT, flashlightState.m_bUberlight ); + SET_DYNAMIC_PIXEL_SHADER( eyes_flashlight_ps30 ); + + SetDepthFlashlightParams( pShader, pShaderAPI, worldToTexture, flashlightState ); + + SetupUberlightFromState( pShaderAPI, flashlightState ); + } +#endif +#endif + + // This uses from VERTEX_SHADER_SHADER_SPECIFIC_CONST_0 to VERTEX_SHADER_SHADER_SPECIFIC_CONST_5 + pShader->SetFlashlightVertexShaderConstants( false, -1, false, -1, false ); + + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, info.m_nEyeOrigin ); + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, info.m_nEyeUp ); + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_8, info.m_nIrisU ); + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_9, info.m_nIrisV ); + } + pShader->Draw(); +} + +static void DrawUsingVertexShader( bool bDX9, CBaseVSShader *pShader, IMaterialVar** params, + IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, + Eyes_DX8_DX9_Vars_t &info, VertexCompressionType_t vertexCompression ) +{ + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); // Base + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); // Iris + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); // Glint + + // Set stream format (note that this shader supports compression) + int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + pShaderShadow->EnableAlphaWrites( true ); //we end up hijacking destination alpha for opaques most of the time. + +#ifdef STDSHADER_DX9_DLL_EXPORT + Assert( bDX9 ); +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_STATIC_VERTEX_SHADER( eyes_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT, IS_FLAG_SET( MATERIAL_VAR_HALFLAMBERT ) ); + SET_STATIC_VERTEX_SHADER_COMBO( INTRO, params[info.m_nIntro]->GetIntValue() ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER( eyes_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( eyes_ps20b ); + SET_STATIC_PIXEL_SHADER( eyes_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( eyes_ps20 ); + SET_STATIC_PIXEL_SHADER( eyes_ps20 ); + } + } +#ifndef _X360 + else + { + // The vertex shader uses the vertex id stream + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + + DECLARE_STATIC_VERTEX_SHADER( eyes_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT, IS_FLAG_SET( MATERIAL_VAR_HALFLAMBERT ) ); + SET_STATIC_VERTEX_SHADER_COMBO( INTRO, params[info.m_nIntro]->GetIntValue() ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER( eyes_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( eyes_ps30 ); + SET_STATIC_PIXEL_SHADER( eyes_ps30 ); + } +#endif + // On DX9, get the gamma read and write correct + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); // Base + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); // White + pShaderShadow->EnableSRGBWrite( true ); +#endif + pShader->FogToFogColor(); + + // Per-instance state + pShader->PI_BeginCommandBuffer(); + pShader->PI_SetVertexShaderAmbientLightCube(); + pShader->PI_SetPixelShaderGlintDamping( 1 ); + pShader->PI_EndCommandBuffer(); + } + DYNAMIC_STATE + { + pShader->BindTexture( SHADER_SAMPLER0, info.m_nBaseTexture, info.m_nFrame ); + pShader->BindTexture( SHADER_SAMPLER1, info.m_nIris, info.m_nIrisFrame ); + pShader->BindTexture( SHADER_SAMPLER2, info.m_nGlint ); + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, info.m_nEyeOrigin ); + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, info.m_nEyeUp ); + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, info.m_nIrisU ); + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, info.m_nIrisV ); + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, info.m_nGlintU ); + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_5, info.m_nGlintV ); + +#ifdef STDSHADER_DX9_DLL_EXPORT + Assert( bDX9 ); + + LightState_t lightState; + pShaderAPI->GetDX9LightState( &lightState ); + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_DYNAMIC_VERTEX_SHADER( eyes_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DYNAMIC_LIGHT, lightState.HasDynamicLight() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( STATIC_LIGHT, lightState.m_bStaticLight ? 1 : 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( eyes_vs20 ); + } +#ifndef _X360 + else + { + pShader->SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, VERTEX_SHADER_SHADER_SPECIFIC_CONST_8, SHADER_VERTEXTEXTURE_SAMPLER0 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( eyes_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DYNAMIC_LIGHT, lightState.HasDynamicLight() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( STATIC_LIGHT, lightState.m_bStaticLight ? 1 : 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( eyes_vs30 ); + } +#endif + + // Special constant for DX9 eyes: { Dilation, x, x, x }; + float vPSConst[4] = {params[info.m_nDilation]->GetFloatValue(), 0.0f, 0.0f, 0.0f}; + pShaderAPI->SetPixelShaderConstant( 0, vPSConst, 1 ); + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + float vEyePos_SpecExponent[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + vEyePos_SpecExponent[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( eyes_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( eyes_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( eyes_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( eyes_ps20 ); + } + } +#ifndef _X360 + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( eyes_ps30 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( eyes_ps30 ); + } +#endif + + Assert( info.m_nIntro != -1 ); + if( params[info.m_nIntro]->GetIntValue() ) + { + float curTime = params[info.m_nWarpParam]->GetFloatValue(); + float timeVec[4] = { 0.0f, 0.0f, 0.0f, curTime }; + Assert( params[info.m_nEntityOrigin]->IsDefined() ); + params[info.m_nEntityOrigin]->GetVecValue( timeVec, 3 ); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, timeVec, 1 ); + } +#endif + } + pShader->Draw(); +} + +static void DrawEyes_DX8_DX9_Internal( bool bDX9, CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, bool bHasFlashlight, Eyes_DX8_DX9_Vars_t &info, VertexCompressionType_t vertexCompression ) +{ + if( !bHasFlashlight ) + { + DrawUsingVertexShader( bDX9, pShader, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else + { + DrawFlashlight( bDX9, pShader, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } +} + +void DrawEyes_DX8_DX9( bool bDX9, CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, Eyes_DX8_DX9_Vars_t &info, VertexCompressionType_t vertexCompression ) +{ + SHADOW_STATE + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + } + bool bHasFlashlight = pShader->UsingFlashlight( params ); + if ( bHasFlashlight && IsX360() ) + { + DrawEyes_DX8_DX9_Internal( bDX9, pShader, params, pShaderAPI, pShaderShadow, false, info, vertexCompression ); + if ( pShaderShadow ) + { + pShader->SetInitialShadowState( ); + } + } + DrawEyes_DX8_DX9_Internal( bDX9, pShader, params, pShaderAPI, pShaderShadow, bHasFlashlight, info, vertexCompression ); +} + + diff --git a/materialsystem/stdshaders/eyes_dx8_dx9_helper.h b/materialsystem/stdshaders/eyes_dx8_dx9_helper.h new file mode 100644 index 00000000..87232c98 --- /dev/null +++ b/materialsystem/stdshaders/eyes_dx8_dx9_helper.h @@ -0,0 +1,54 @@ +//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======= +// +// Purpose: +// +//============================================================================= + +#ifndef EYES_DX8_DX9_HELPER_H +#define EYES_DX8_DX9_HELPER_H +#ifdef _WIN32 +#pragma once +#endif + +#include + + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct Eyes_DX8_DX9_Vars_t +{ + Eyes_DX8_DX9_Vars_t() { memset( this, 0xFF, sizeof(Eyes_DX8_DX9_Vars_t) ); } + + int m_nBaseTexture; + int m_nFrame; + int m_nIris; + int m_nIrisFrame; + int m_nGlint; + int m_nEyeOrigin; + int m_nEyeUp; + int m_nIrisU; + int m_nIrisV; + int m_nGlintU; + int m_nGlintV; + int m_nDilation; + int m_nIntro; + int m_nEntityOrigin; + int m_nWarpParam; +}; + +void InitParamsEyes_DX8_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, Eyes_DX8_DX9_Vars_t &info ); +void InitEyes_DX8_DX9( CBaseVSShader *pShader, IMaterialVar** params, Eyes_DX8_DX9_Vars_t &info ); +void DrawEyes_DX8_DX9( bool bDX9, CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, Eyes_DX8_DX9_Vars_t &info, VertexCompressionType_t vertexCompression ); + +#endif // EYES_DX8_DX9_HELPER_H diff --git a/materialsystem/stdshaders/eyes_dx9.cpp b/materialsystem/stdshaders/eyes_dx9.cpp new file mode 100644 index 00000000..400ffba0 --- /dev/null +++ b/materialsystem/stdshaders/eyes_dx9.cpp @@ -0,0 +1,81 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: eye renderer +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" +#include "eyes_dx8_dx9_helper.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( eyes, Eyes_dx9 ) + +BEGIN_VS_SHADER( Eyes_dx9, "Help for Eyes" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( IRIS, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "iris texture" ) + SHADER_PARAM( IRISFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame for the iris texture" ) + SHADER_PARAM( GLINT, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "glint texture" ) + SHADER_PARAM( EYEORIGIN, SHADER_PARAM_TYPE_VEC3, "[0 0 0]", "origin for the eyes" ) + SHADER_PARAM( EYEUP, SHADER_PARAM_TYPE_VEC3, "[0 0 1]", "up vector for the eyes" ) + SHADER_PARAM( IRISU, SHADER_PARAM_TYPE_VEC4, "[0 1 0 0 ]", "U projection vector for the iris" ) + SHADER_PARAM( IRISV, SHADER_PARAM_TYPE_VEC4, "[0 0 1 0]", "V projection vector for the iris" ) + SHADER_PARAM( GLINTU, SHADER_PARAM_TYPE_VEC4, "[0 1 0 0]", "U projection vector for the glint" ) + SHADER_PARAM( GLINTV, SHADER_PARAM_TYPE_VEC4, "[0 0 1 0]", "V projection vector for the glint" ) + SHADER_PARAM( DILATION, SHADER_PARAM_TYPE_FLOAT, "0", "Pupil dilation (0 is none, 1 is maximal)" ) + SHADER_PARAM( INTRO, SHADER_PARAM_TYPE_BOOL, "0", "is eyes in the ep1 intro" ) + SHADER_PARAM( ENTITYORIGIN, SHADER_PARAM_TYPE_VEC3,"0.0","center if the model in world space" ) + SHADER_PARAM( WARPPARAM, SHADER_PARAM_TYPE_FLOAT,"0.0","animation param between 0 and 1" ) + END_SHADER_PARAMS + + void SetupVars( Eyes_DX8_DX9_Vars_t &info ) + { + info.m_nBaseTexture = BASETEXTURE; + info.m_nFrame = FRAME; + info.m_nIris = IRIS; + info.m_nIrisFrame = IRISFRAME; + info.m_nGlint = GLINT; + info.m_nEyeOrigin = EYEORIGIN; + info.m_nEyeUp = EYEUP; + info.m_nIrisU = IRISU; + info.m_nIrisV = IRISV; + info.m_nGlintU = GLINTU; + info.m_nGlintV = GLINTV; + info.m_nDilation = DILATION; + info.m_nIntro = INTRO; + info.m_nEntityOrigin = ENTITYORIGIN; + info.m_nWarpParam = WARPPARAM; + } + + SHADER_INIT_PARAMS() + { + Eyes_DX8_DX9_Vars_t info; + SetupVars( info ); + InitParamsEyes_DX8_DX9( this, params, pMaterialName, info ); + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + Eyes_DX8_DX9_Vars_t info; + SetupVars( info ); + InitEyes_DX8_DX9( this, params, info ); + } + + + SHADER_DRAW + { + Eyes_DX8_DX9_Vars_t info; + SetupVars( info ); + DrawEyes_DX8_DX9( true, this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } +END_SHADER + diff --git a/materialsystem/stdshaders/eyes_flashlight_inc.fxc b/materialsystem/stdshaders/eyes_flashlight_inc.fxc new file mode 100644 index 00000000..4306d812 --- /dev/null +++ b/materialsystem/stdshaders/eyes_flashlight_inc.fxc @@ -0,0 +1,111 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// +// +// Purpose: +// +//===========================================================================// + +#include "common_flashlight_fxc.h" +#include "shader_constant_register_map.h" + + +const float4 g_vShadowTweaks : register( PSREG_ENVMAP_TINT__SHADOW_TWEAKS ); + +sampler SpotSampler : register( s0 ); +sampler BaseTextureSampler : register( s1 ); +sampler IrisSampler : register( s3 ); + +#if FLASHLIGHTSHADOWS && (!SHADER_MODEL_PS_1_1) && (!SHADER_MODEL_PS_1_4) && (!SHADER_MODEL_PS_2_0) +sampler FlashlightDepthSampler : register( s4 ); +sampler RandomRotationSampler : register( s5 ); +#endif + +#if UBERLIGHT && defined( SHADER_MODEL_PS_3_0 ) +const float3 g_vSmoothEdge0 : register( PSREG_UBERLIGHT_SMOOTH_EDGE_0 ); // ps_3_0 and up (over 32 registers) +const float3 g_vSmoothEdge1 : register( PSREG_UBERLIGHT_SMOOTH_EDGE_1 ); +const float3 g_vSmoothOneOverWidth : register( PSREG_UBERLIGHT_SMOOTH_EDGE_OOW ); +const float4 g_vShearRound : register( PSREG_UBERLIGHT_SHEAR_ROUND ); +const float4 g_aAbB : register( PSREG_UBERLIGHT_AABB ); +const float4x4 g_FlashlightWorldToLight : register( PSREG_UBERLIGHT_WORLD_TO_LIGHT ); +#endif + + +#if defined( SHADER_MODEL_PS_1_1 ) || defined ( SHADER_MODEL_PS_1_4 ) + +#else + const float4 g_FogParams : register( PSREG_FOG_PARAMS ); + const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT ); +#endif + +struct PS_INPUT +{ + float4 spotTexCoord : TEXCOORD0; + float2 baseTexCoord : TEXCOORD1; + float2 irisTexCoord : TEXCOORD3; +#if defined( SHADER_MODEL_PS_1_1 ) || defined ( SHADER_MODEL_PS_1_4 ) + float3 vertAtten : COLOR0; +#else + float3 vertAtten : TEXCOORD4; + float3 worldPos : TEXCOORD5; + float3 projPos : TEXCOORD7; +#endif +}; + +float4 main( PS_INPUT i ) : COLOR +{ +#if defined(SHADER_MODEL_PS_2_0) + float3 spotColor = tex2Dproj( SpotSampler, i.spotTexCoord.xyzw ) * cFlashlightColor; +#elif ( defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) ) + float3 vProjCoords = i.spotTexCoord.xyz / i.spotTexCoord.w; + float3 spotColor = tex2D( SpotSampler, vProjCoords ) * cFlashlightColor; +#else + float3 spotColor = tex2D( SpotSampler, i.spotTexCoord ); +#endif + + float4 baseSample = tex2D( BaseTextureSampler, i.baseTexCoord ); + float4 irisSample = tex2D( IrisSampler, i.irisTexCoord ); + + float3 outcolor = float3(1,1,1); + +#if !defined( SHADER_MODEL_PS_1_1 ) && !defined( SHADER_MODEL_PS_1_4 ) + if( i.spotTexCoord.w <= 0.0f ) + { + outcolor = float3(0,0,0); + } +#endif + + // Composite the iris and sclera together +#if defined( SHADER_MODEL_PS_1_1 ) || defined ( SHADER_MODEL_PS_1_4 ) + float3 albedo = lerp( baseSample.xyz, irisSample.xyz, irisSample.a ); +#else + float3 albedo = lerp( baseSample.xyz, irisSample.xyz * 0.5f, irisSample.a ); // dim down the iris in HDR +#endif + + // Do shadow depth mapping... +#if FLASHLIGHTSHADOWS && ( defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) ) + float flShadow = DoFlashlightShadow( FlashlightDepthSampler, RandomRotationSampler, vProjCoords, i.projPos.xy / i.projPos.z, FLASHLIGHTDEPTHFILTERMODE, g_vShadowTweaks, true ); + float flAttenuated = lerp( flShadow, 1.0f, g_vShadowTweaks.y ); // Blend between fully attenuated and not attenuated + flShadow = lerp( flAttenuated, flShadow, dot(i.vertAtten, float3(0.30f, 0.59f, 0.11f) ) ); // Blend between shadow and above, according to light attenuation + outcolor *= flShadow * spotColor * albedo; + +#if UBERLIGHT && defined( SHADER_MODEL_PS_3_0 ) + float4 uberLightPosition = mul( float4( i.worldPos, 1.0f ), g_FlashlightWorldToLight ).yzxw; + outcolor *= uberlight( uberLightPosition, g_vSmoothEdge0, g_vSmoothEdge1, + g_vSmoothOneOverWidth, g_vShearRound.xy, g_aAbB, g_vShearRound.zw ); +#endif + +#else + outcolor *= spotColor * albedo; +#endif + + // NOTE!! This has to be last to avoid loss of range. + outcolor *= i.vertAtten; + outcolor = max( 0, outcolor ); + +#if defined( SHADER_MODEL_PS_1_1 ) || defined ( SHADER_MODEL_PS_1_4 ) + return float4( outcolor, baseSample.a ); +#else + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos_SpecExponent.z, i.worldPos.z, i.projPos.z ); + return FinalOutput( float4( outcolor, 1.0f ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR ); +#endif + +} diff --git a/materialsystem/stdshaders/eyes_flashlight_ps2x.fxc b/materialsystem/stdshaders/eyes_flashlight_ps2x.fxc new file mode 100644 index 00000000..62c8f7df --- /dev/null +++ b/materialsystem/stdshaders/eyes_flashlight_ps2x.fxc @@ -0,0 +1,17 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// +// +// Purpose: +// +//===========================================================================// + +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps20b] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps30] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..0" [ps20b] [XBOX] + +#include "common_fog_ps_fxc.h" +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps20b] +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps30] + +// DYNAMIC: "UBERLIGHT" "0..1" [ps30] [PC] + +#include "eyes_flashlight_inc.fxc" diff --git a/materialsystem/stdshaders/eyes_flashlight_vs20.fxc b/materialsystem/stdshaders/eyes_flashlight_vs20.fxc new file mode 100644 index 00000000..7119f2f1 --- /dev/null +++ b/materialsystem/stdshaders/eyes_flashlight_vs20.fxc @@ -0,0 +1,145 @@ +// ------------------------------------------------------------------------------ +// $cLight0Pos = world space light position +// $SHADER_SPECIFIC_CONST_1 = spotlight projection +// $SHADER_SPECIFIC_CONST_2 = spotlight projection +// $SHADER_SPECIFIC_CONST_3 = spotlight projection +// $SHADER_SPECIFIC_CONST_4 = spotlight projection +// $SHADER_SPECIFIC_CONST_5 = far z +// $SHADER_SPECIFIC_CONST_6 = eyeball origin +// $SHADER_SPECIFIC_CONST_7 = eyeball up * 0.5 +// $SHADER_SPECIFIC_CONST_8 = iris projection U +// $SHADER_SPECIFIC_CONST_9 = iris projection V +// ------------------------------------------------------------------------------ + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "SKINNING" "0..1" +#include "common_fog_vs_fxc.h" + +// DYNAMIC: "MORPHING" "0..1" [vs30] [ = pShaderAPI->IsHWMorphingEnabled() ] + +#include "common_vs_fxc.h" + +static const bool g_bSkinning = SKINNING ? true : false; +static const int g_FogType = DOWATERFOG; + +const float4 cLightPosition : register( SHADER_SPECIFIC_CONST_0 ); +const float4 cSpotlightProj1 : register( SHADER_SPECIFIC_CONST_1 ); +const float4 cSpotlightProj2 : register( SHADER_SPECIFIC_CONST_2 ); +const float4 cSpotlightProj3 : register( SHADER_SPECIFIC_CONST_3 ); +const float4 cSpotlightProj4 : register( SHADER_SPECIFIC_CONST_4 ); +const float4 cFlashlighAtten : register( SHADER_SPECIFIC_CONST_5 ); // const, linear, quadratic & farZ +const float4 cIrisProjectionU : register( SHADER_SPECIFIC_CONST_8 ); +const float4 cIrisProjectionV : register( SHADER_SPECIFIC_CONST_9 ); + +#ifdef SHADER_MODEL_VS_3_0 +// NOTE: cMorphTargetTextureDim.xy = target dimensions, +// cMorphTargetTextureDim.z = 4tuples/morph +const float3 cMorphTargetTextureDim : register( SHADER_SPECIFIC_CONST_10 ); +const float4 cMorphSubrect : register( SHADER_SPECIFIC_CONST_11 ); + +sampler2D morphSampler : register( D3DVERTEXTEXTURESAMPLER0, s0 ); +#endif + +struct VS_INPUT +{ + float4 vPos : POSITION; // Position + float4 vBoneWeights : BLENDWEIGHT; // Skin weights + float4 vBoneIndices : BLENDINDICES; // Skin indices + float4 vNormal : NORMAL; + float4 vTexCoord0 : TEXCOORD0; // Base (sclera) texture coordinates + + // Position and normal/tangent deltas + float3 vPosFlex : POSITION1; + float3 vNormalFlex : NORMAL1; +#ifdef SHADER_MODEL_VS_3_0 + float vVertexID : POSITION2; +#endif +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; // Projection-space position +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + float fog : FOG; // Fixed-function fog factor +#endif + float4 spotTexCoord : TEXCOORD0; // Spotlight texture coordinates + float2 baseTexCoord : TEXCOORD1; // Base texture coordinates + float2 irisTexCoord : TEXCOORD3; // Iris texture coordinates + float3 vertAtten : TEXCOORD4; // vertex attenuation + float3 worldPos : TEXCOORD5; + float3 projPosXYZ : TEXCOORD7; +}; + + +float RemapValClamped_01( float val, float A, float B ) +{ + float cVal = (val - A) / (B - A); + cVal = saturate( cVal ); + return cVal; +} + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float4 vPosition = v.vPos; + float3 vNormal; + DecompressVertex_Normal( v.vNormal, vNormal ); + +#if !defined( SHADER_MODEL_VS_3_0 ) || !MORPHING + ApplyMorph( v.vPosFlex, v.vNormalFlex, vPosition.xyz, vNormal ); +#else + ApplyMorph( morphSampler, cMorphTargetTextureDim, cMorphSubrect, v.vVertexID, float3( 0, 0, 0 ), vPosition.xyz, vNormal ); +#endif + + // Perform skinning + float3 worldNormal, worldPos; + SkinPositionAndNormal( + g_bSkinning, + vPosition, vNormal, + v.vBoneWeights, v.vBoneIndices, + worldPos, worldNormal ); + + worldNormal = normalize( worldNormal ); + + // Transform into projection space + float4 projPos = mul( float4( worldPos, 1 ), cViewProj ); + o.projPos = projPos; + o.projPosXYZ = projPos.xyz; + o.worldPos = worldPos.xyz; + +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + o.fog = CalcFixedFunctionFog( worldPos, g_FogType ); +#endif + + // Base texture coordinates + o.baseTexCoord = v.vTexCoord0; + + // Spotlight texture coordinates + o.spotTexCoord.x = dot( cSpotlightProj1, float4(worldPos, 1) ); + o.spotTexCoord.y = dot( cSpotlightProj2, float4(worldPos, 1) ); + o.spotTexCoord.z = dot( cSpotlightProj3, float4(worldPos, 1) ); + o.spotTexCoord.w = dot( cSpotlightProj4, float4(worldPos, 1) ); + + // Compute vector to light + float3 vWorldPosToLightVector = cLightPosition.xyz - worldPos; + + float3 vDistAtten = float3(1, 1, 1); + vDistAtten.z = dot( vWorldPosToLightVector, vWorldPosToLightVector ); // distsquared + vDistAtten.y = rsqrt( vDistAtten.z ); // 1 / dist + + float flDist = vDistAtten.z * vDistAtten.y; // dist + vDistAtten.z = 1.0f / vDistAtten.z; // 1 / distsquared + + float fFarZ = cFlashlighAtten.w; + + float endFalloffFactor = RemapValClamped_01( flDist, fFarZ, 0.6 * fFarZ ); + o.vertAtten.xyz = endFalloffFactor * dot( vDistAtten, cFlashlighAtten.xyz ); + + o.vertAtten *= dot( normalize( vWorldPosToLightVector ), worldNormal ); + + o.irisTexCoord.x = dot( cIrisProjectionU, float4(worldPos, 1) ); + o.irisTexCoord.y = dot( cIrisProjectionV, float4(worldPos, 1) ); + + return o; +} diff --git a/materialsystem/stdshaders/eyes_ps2x.fxc b/materialsystem/stdshaders/eyes_ps2x.fxc new file mode 100644 index 00000000..1d71fe68 --- /dev/null +++ b/materialsystem/stdshaders/eyes_ps2x.fxc @@ -0,0 +1,69 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// +// +// Purpose: +// +//===========================================================================// + +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps30] +#include "common_fog_ps_fxc.h" + +#include "common_ps_fxc.h" +#include "shader_constant_register_map.h" + +sampler BaseTextureSampler : register( s0 ); +sampler IrisSampler : register( s1 ); +sampler GlintSampler : register( s2 ); +const float4 cEyeScalars : register( c0 ); // { Dilation, x, x, x } +const float4 cEyeScalars2 : register( c1 ); // { ambient, ambient, ambient, ambient } + +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT ); + +struct PS_INPUT +{ + float2 baseTexCoord : TEXCOORD0; + float2 irisTexCoord : TEXCOORD1; + float2 glintTexCoord : TEXCOORD2; + float3 vertAtten : TEXCOORD3; + + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog +}; + +#define fDilationFactor cEyeScalars.x +#define fGlintDamping cEyeScalars2.x + +float4 main( PS_INPUT i ) : COLOR +{ + float4 baseSample = tex2D( BaseTextureSampler, i.baseTexCoord ); + float4 glintSample = tex2D( GlintSampler, i.glintTexCoord ); +/* + // Dilate the pupil/iris texture (1 is max dilation, 0 is none) + float2 biasedCoords = i.irisTexCoord * 2.0f - 1.0f; // -1 to +1 range + float fDilatability = saturate(0.8f - sqrt(dot(biasedCoords, biasedCoords) )); // 1 in the center, fading out to 0 at 0.8 from center, since irises are inset into maps + float2 scaledCoords = biasedCoords * (1 + fDilatability); // Maximal dilation + + // Blend undilated and maximally dilated based upon dilation factor + float2 dilatedCoords = lerp( scaledCoords, biasedCoords, 1.0f-saturate(cDilationFactor.x)); + dilatedCoords = dilatedCoords * 0.5f + 0.5f; // Back to 0..1 range +*/ + + float4 irisSample = tex2D( IrisSampler, i.irisTexCoord ); // Sample the iris map using dilated coordinates + + float4 result; + result.rgb = lerp( baseSample.rgb, irisSample.rgb, irisSample.a ); + result.rgb *= i.vertAtten; + result.rgb += glintSample.rgb * fGlintDamping; + result.a = baseSample.a; + + bool bWriteDepthToAlpha = false; + + // ps_2_b and beyond +#if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) + bWriteDepthToAlpha = WRITE_DEPTH_TO_DESTALPHA != 0; +#endif + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos_SpecExponent.xyz, i.worldPos_projPosZ.xyz, i.worldPos_projPosZ.w ); + return FinalOutput( result, fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, bWriteDepthToAlpha, i.worldPos_projPosZ.w ); +} diff --git a/materialsystem/stdshaders/fade_blur_ps2x.fxc b/materialsystem/stdshaders/fade_blur_ps2x.fxc new file mode 100644 index 00000000..aaeb28bb --- /dev/null +++ b/materialsystem/stdshaders/fade_blur_ps2x.fxc @@ -0,0 +1,27 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +sampler g_sBase : register( s0 ); + +float g_flAlpha : register( c0 ); +float g_flDesaturate : register( c1 ); + +struct PS_INPUT +{ + float2 uv : TEXCOORD0; +}; + +float4 main( PS_INPUT i ) : COLOR0 +{ + // Fetch blurred texel + float4 o = tex2D( g_sBase, i.uv ); + + // Desaturate + float3 tmpv = { 0.2125, 0.7154, 0.0721 }; + float flLuminance = dot( o.rgb, tmpv.rgb ); + o.rgb = lerp( o.rgb, flLuminance, saturate( g_flDesaturate ) ); + + // Set alpha blend value + o.a = g_flAlpha; + + return o; +} diff --git a/materialsystem/stdshaders/fillrate.cpp b/materialsystem/stdshaders/fillrate.cpp new file mode 100644 index 00000000..1a5952b6 --- /dev/null +++ b/materialsystem/stdshaders/fillrate.cpp @@ -0,0 +1,152 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" + +#include "fillrate_vs20.inc" +#include "fillrate_ps20.inc" +#include "fillrate_ps20b.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_VS_SHADER_FLAGS( Fillrate, "Help for Fillrate", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( PASSCOUNT, SHADER_PARAM_TYPE_INTEGER, "1", "Number of passes for this material" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + } + + SHADER_INIT + { + } + + SHADER_FALLBACK + { + return 0; + } + + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableDepthTest( false ); + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); + + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + DECLARE_STATIC_VERTEX_SHADER( fillrate_vs20 ); + SET_STATIC_VERTEX_SHADER( fillrate_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( fillrate_ps20b ); + SET_STATIC_PIXEL_SHADER( fillrate_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( fillrate_ps20 ); + SET_STATIC_PIXEL_SHADER( fillrate_ps20 ); + } + } + DYNAMIC_STATE + { + int numPasses = params[PASSCOUNT]->GetIntValue(); + float color[4]; + if (g_pConfig->bMeasureFillRate) + { + // have to multiply by 2/255 since pixel shader constant are 1.7. + // Will divide the 2 out in the pixel shader. + color[0] = numPasses * ( 2.0f / 255.0f ); + } + else + { + color[0] = ( 16 * numPasses ) * ( 2.0f / 255.0f ); + } + color[1] = 0.0f; + color[2] = 0.0f; + color[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( 0, color, 1 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( fillrate_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( fillrate_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( fillrate_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( fillrate_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( fillrate_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( fillrate_ps20 ); + } + } + Draw(); + + SHADOW_STATE + { + pShaderShadow->EnableDepthTest( false ); + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 1, 0, 0 ); + pShaderShadow->PolyMode( SHADER_POLYMODEFACE_FRONT_AND_BACK, SHADER_POLYMODE_LINE ); + + DECLARE_STATIC_VERTEX_SHADER( fillrate_vs20 ); + SET_STATIC_VERTEX_SHADER( fillrate_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( fillrate_ps20b ); + SET_STATIC_PIXEL_SHADER( fillrate_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( fillrate_ps20 ); + SET_STATIC_PIXEL_SHADER( fillrate_ps20 ); + } + } + DYNAMIC_STATE + { + float color[4] = { 0.0f, 0.05f, 0.05f, 0.0f }; + pShaderAPI->SetPixelShaderConstant( 0, color, 1 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( fillrate_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( fillrate_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( fillrate_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( fillrate_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( fillrate_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( fillrate_ps20 ); + } + } + Draw(); + } +END_SHADER + + diff --git a/materialsystem/stdshaders/fillrate_ps2x.fxc b/materialsystem/stdshaders/fillrate_ps2x.fxc new file mode 100644 index 00000000..cbf716c8 --- /dev/null +++ b/materialsystem/stdshaders/fillrate_ps2x.fxc @@ -0,0 +1,12 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#include "common_ps_fxc.h" + +const float4 g_ColorConstant : register( c0 ); + +float4 main( void ) : COLOR +{ + float4 result = (g_ColorConstant * (1.0 / 2.0)); + + return FinalOutput( result, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} diff --git a/materialsystem/stdshaders/fillrate_vs20.fxc b/materialsystem/stdshaders/fillrate_vs20.fxc new file mode 100644 index 00000000..d3f40e07 --- /dev/null +++ b/materialsystem/stdshaders/fillrate_vs20.fxc @@ -0,0 +1,33 @@ +#include "common_fog_vs_fxc.h" +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "SKINNING" "0..1" + +#include "common_vs_fxc.h" + +static const int g_FogType = DOWATERFOG; +static const bool g_bSkinning = SKINNING ? true : false; + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; +}; + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; +}; + + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 worldPos; + SkinPosition( g_bSkinning, v.vPos, v.vBoneWeights, v.vBoneIndices, worldPos ); + + o.vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + + return o; +} \ No newline at end of file diff --git a/materialsystem/stdshaders/filmdust.cpp b/materialsystem/stdshaders/filmdust.cpp new file mode 100644 index 00000000..8681b193 --- /dev/null +++ b/materialsystem/stdshaders/filmdust.cpp @@ -0,0 +1,68 @@ +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#include "basevsshader.h" + +#include "screenspaceeffect_vs20.inc" +#include "filmdust_ps20.inc" + +#include "..\materialsystem_global.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_VS_SHADER_FLAGS( FilmDust, "Help for FilmDust", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( DUST_TEXTURE, SHADER_PARAM_TYPE_TEXTURE, "0", "Film dust texture" ) + SHADER_PARAM( CHANNEL_SELECT, SHADER_PARAM_TYPE_VEC4, "", "Select which color channel to use" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_NEEDS_FULL_FRAME_BUFFER_TEXTURE ); + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + LoadTexture( DUST_TEXTURE ); + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableCulling( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_ZERO, SHADER_BLEND_SRC_COLOR ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + int fmt = VERTEX_POSITION; + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 ); + + DECLARE_STATIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + SET_STATIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + + DECLARE_STATIC_PIXEL_SHADER( filmdust_ps20 ); + SET_STATIC_PIXEL_SHADER( filmdust_ps20 ); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, DUST_TEXTURE, -1 ); + + SetPixelShaderConstant( 0, CHANNEL_SELECT ); + + DECLARE_DYNAMIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + } + Draw(); + } +END_SHADER diff --git a/materialsystem/stdshaders/filmdust_ps20.fxc b/materialsystem/stdshaders/filmdust_ps20.fxc new file mode 100644 index 00000000..956b9b58 --- /dev/null +++ b/materialsystem/stdshaders/filmdust_ps20.fxc @@ -0,0 +1,18 @@ +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_fxc.h" + +sampler FilmDustSampler : register( s0 ); + +const float4 vChannelSelect : register( c0 ); + +struct PS_INPUT +{ + float2 grainTexCoord : TEXCOORD0; +}; + +HALF4 main( PS_INPUT i ) : COLOR +{ + HALF4 noise = dot( tex2D( FilmDustSampler, i.grainTexCoord ), vChannelSelect ); + + return HALF4( noise.x, noise.y, noise.z, 1.0 ); +} diff --git a/materialsystem/stdshaders/filmgrain.cpp b/materialsystem/stdshaders/filmgrain.cpp new file mode 100644 index 00000000..8a95e3a0 --- /dev/null +++ b/materialsystem/stdshaders/filmgrain.cpp @@ -0,0 +1,67 @@ +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#include "basevsshader.h" + +#include "screenspaceeffect_vs20.inc" +#include "filmgrain_ps20.inc" + +#include "..\materialsystem_global.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_VS_SHADER_FLAGS( FilmGrain, "Help for FilmGrain", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( GRAIN_TEXTURE, SHADER_PARAM_TYPE_TEXTURE, "0", "Film grain texture" ) + SHADER_PARAM( NOISESCALE, SHADER_PARAM_TYPE_VEC4, "", "Strength of film grain" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_NEEDS_FULL_FRAME_BUFFER_TEXTURE ); + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + LoadTexture( GRAIN_TEXTURE ); + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_ONE, SHADER_BLEND_SRC_ALPHA ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + int fmt = VERTEX_POSITION; + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 ); + + DECLARE_STATIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + SET_STATIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + + DECLARE_STATIC_PIXEL_SHADER( filmgrain_ps20 ); + SET_STATIC_PIXEL_SHADER( filmgrain_ps20 ); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, GRAIN_TEXTURE, -1 ); + + SetPixelShaderConstant( 0, NOISESCALE ); + + DECLARE_DYNAMIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + } + Draw(); + } +END_SHADER diff --git a/materialsystem/stdshaders/filmgrain_ps20.fxc b/materialsystem/stdshaders/filmgrain_ps20.fxc new file mode 100644 index 00000000..13cf8956 --- /dev/null +++ b/materialsystem/stdshaders/filmgrain_ps20.fxc @@ -0,0 +1,21 @@ +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_fxc.h" + +sampler FilmGrainSampler : register( s0 ); + +const float4 vNoiseScale : register( c0 ); + +struct PS_INPUT +{ + float2 grainTexCoord : TEXCOORD0; +}; + +HALF4 main( PS_INPUT i ) : COLOR +{ + HALF4 noise = tex2D( FilmGrainSampler, i.grainTexCoord ); + + noise.w = noise.x*(1.0-vNoiseScale.w) + vNoiseScale.w; + noise.xyz *= vNoiseScale.xyz; + + return HALF4( noise.x, noise.y, noise.z, noise.w ); +} diff --git a/materialsystem/stdshaders/filmgrain_vs20.fxc b/materialsystem/stdshaders/filmgrain_vs20.fxc new file mode 100644 index 00000000..574a4a9e --- /dev/null +++ b/materialsystem/stdshaders/filmgrain_vs20.fxc @@ -0,0 +1,32 @@ +#include "common_vs_fxc.h" + +struct VS_INPUT +{ + float3 vPos : POSITION; + float2 vInputImageCoord : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; + float2 InputImageCoord : TEXCOORD0; + float2 FilmGrainCoord : TEXCOORD1; +}; + +// +const float4 cFilmGrainOffset : register( SHADER_SPECIFIC_CONST_0 ); // should be SHADER_SPECIFIC_CONST_0 + + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + // Just copy these through to the output... + o.projPos = float4( v.vPos, 1.0f ); + o.InputImageCoord = v.vInputImageCoord; + + // Scale and bias the input coordinates to get grain coordinates + o.FilmGrainCoord.xy = v.vInputImageCoord.xy * cFilmGrainOffset.xy + cFilmGrainOffset.zw; + + return o; +} diff --git a/materialsystem/stdshaders/flashlight_ps2x.fxc b/materialsystem/stdshaders/flashlight_ps2x.fxc new file mode 100644 index 00000000..992bb0d6 --- /dev/null +++ b/materialsystem/stdshaders/flashlight_ps2x.fxc @@ -0,0 +1,294 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// +// +// Purpose: +// +//===========================================================================// + +// vertexshaders that pair with this pixel shader: +// lightmappedgeneric_flashlight_vs20 +// vertexlitgeneric_flashlight_vs20 + +// STATIC: "NORMALMAP" "0..2" +// STATIC: "NORMALMAP2" "0..1" +// STATIC: "WORLDVERTEXTRANSITION" "0..1" +// STATIC: "SEAMLESS" "0..1" +// STATIC: "DETAILTEXTURE" "0..1" +// STATIC: "DETAIL_BLEND_MODE" "0..11" +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps20b] [ps30] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..0" [ps20b] [XBOX] + +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps20b] [ps30] +// DYNAMIC: "UBERLIGHT" "0..1" [ps30] [PC] + +// SKIP: !$WORLDVERTEXTRANSITION && $NORMALMAP2 +// SKIP: !$NORMALMAP && $NORMALMAP2 +// SKIP: !$DETAILTEXTURE && ( $DETAIL_BLEND_MODE != 0 ) + +#include "common_fog_ps_supportsvertexfog_fxc.h" +#include "shader_constant_register_map.h" +#include "common_flashlight_fxc.h" +#include "common_lightmappedgeneric_fxc.h" + +const float4 g_DetailConstants : register( c0 ); +const float3 g_DiffuseModulation : register( PSREG_DIFFUSE_MODULATION ); +const float4 g_vShadowTweaks : register( PSREG_ENVMAP_TINT__SHADOW_TWEAKS ); +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float4 g_EyePos : register( PSREG_EYEPOS_SPEC_EXPONENT ); +const float4 g_FlashlightAttenuation : register( PSREG_FLASHLIGHT_ATTENUATION ); + +#if !defined( SHADER_MODEL_PS_2_0 ) +const float4 g_FlashlightPos : register( PSREG_FLASHLIGHT_POSITION_RIM_BOOST ); +#else +// Lock flashlight pos to eye pos in ps_2_0 +#define g_FlashlightPos g_EyePos +#endif + +#if UBERLIGHT && defined( SHADER_MODEL_PS_3_0 ) +const float3 g_vSmoothEdge0 : register( PSREG_UBERLIGHT_SMOOTH_EDGE_0 ); +const float3 g_vSmoothEdge1 : register( PSREG_UBERLIGHT_SMOOTH_EDGE_1 ); +const float3 g_vSmoothOneOverWidth : register( PSREG_UBERLIGHT_SMOOTH_EDGE_OOW ); +const float4 g_vShearRound : register( PSREG_UBERLIGHT_SHEAR_ROUND ); +const float4 g_aAbB : register( PSREG_UBERLIGHT_AABB ); +const float4x4 g_FlashlightWorldToLight : register( PSREG_UBERLIGHT_WORLD_TO_LIGHT ); +#endif + +sampler SpotSampler : register( s0 ); +sampler BaseTextureSampler : register( s1 ); +sampler NormalizingCubemapSampler : register( s2 ); + +// use a normalizing cube map here if we aren't normal mapping +sampler BumpMapSampler : register( s3 ); +sampler BaseTextureSampler2 : register( s4 ); + +#ifdef WORLDVERTEXTRANSITION +sampler NormalMap2Sampler : register( s6 ); +#endif + +#if DETAILTEXTURE +sampler DetailSampler : register( s8 ); +#endif + +#if FLASHLIGHTSHADOWS && ( defined( SHADER_MODEL_PS_2_B ) || defined( SHADER_MODEL_PS_3_0 ) ) +sampler RandomRotationSampler : register( s5 ); // Random rotation sampler +sampler FlashlightDepthSampler : register( s7 ); +#endif + +struct PS_INPUT +{ + float4 spotTexCoord : TEXCOORD0; +#if SEAMLESS + float3 SeamlessTexCoord : TEXCOORD1; +#else + float2 baseTexCoord : TEXCOORD1; +#endif +#if NORMALMAP + float3 tangentPosToLightVector : TEXCOORD2; + float2 normalMapTexCoord : TEXCOORD3; +#else + float3 worldPosToLightVector : TEXCOORD2; + float3 normal : TEXCOORD3; +#endif + + float2 detailCoords : TEXCOORD4; + float4 worldPos_worldTransition : TEXCOORD5; +#if HARDWAREFOGBLEND || DOPIXELFOG + float3 projPos_fogFactorW : TEXCOORD6; +#else + float4 projPos_fogFactorW : TEXCOORD6; +#endif + + float4 vNormalSqr : COLOR1; +}; + + + +float4 SampleNormal( sampler s, PS_INPUT i ) +{ +#if SEAMLESS + float4 szy=tex2D( s, i.SeamlessTexCoord.zy ); + float4 sxz=tex2D( s, i.SeamlessTexCoord.xz ); + float4 syx=tex2D( s, i.SeamlessTexCoord.xy ); + return i.vNormalSqr.r*szy + i.vNormalSqr.g*sxz + i.vNormalSqr.b*syx; +#else +#if NORMALMAP + return tex2D( s, i.normalMapTexCoord.xy); +#else + return float4(0,0,1,1); +#endif +#endif + +} + +float4 main( PS_INPUT i ) : COLOR +{ + bool bBase2 = WORLDVERTEXTRANSITION ? true : false; + bool bBump = (NORMALMAP != 0) ? true : false; + + // Do spot stuff early since we can bail out + float3 spotColor = float3(0,0,0); + float3 vProjCoords = i.spotTexCoord.xyz / i.spotTexCoord.w; + +#if ( defined( _X360 ) ) + + float3 ltz = vProjCoords.xyz < float3( 0.0f, 0.0f, 0.0f ); + float3 gto = vProjCoords.xyz > float3( 1.0f, 1.0f, 1.0f ); + + [branch] + if ( dot(ltz + gto, float3(1,1,1)) > 0 ) + { + clip (-1); + return float4(0,0,0,0); + } + else + { + spotColor = tex2D( SpotSampler, vProjCoords ); + + [branch] + if ( dot(spotColor.xyz, float3(1,1,1)) <= 0 ) + { + clip(-1); + return float4(0,0,0,0); + } + else + { +#else + spotColor = tex2D( SpotSampler, vProjCoords ); + +#if ( defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) ) + spotColor *= i.spotTexCoord.www > float3(0,0,0); // Catch back projection (PC-only at the moment) +#endif + +#endif + + float4 baseColor = 0.0f; + float4 baseColor2 = 0.0f; + float4 vNormal = float4(0, 0, 1, 1); + float3 baseTexCoords = float3(0,0,0); + float3 normalTexCoords = float3( 0, 0, 0 ); + +#if SEAMLESS + baseTexCoords = i.SeamlessTexCoord.xyz; + normalTexCoords = baseTexCoords; +#else + baseTexCoords.xy = i.baseTexCoord.xy; + #if ( NORMALMAP != 0 ) + normalTexCoords.xy = i.normalMapTexCoord.xy; + #else + normalTexCoords = baseTexCoords; + #endif +#endif + + GetBaseTextureAndNormal( BaseTextureSampler, BaseTextureSampler2, BumpMapSampler, bBase2, bBump, + baseTexCoords, normalTexCoords, i.vNormalSqr.xyz, baseColor, baseColor2, vNormal ); + +#if DETAILTEXTURE + float4 detailColor = float4( g_DetailConstants.xyz, 1.0f ) * tex2D( DetailSampler, i.detailCoords ); +#endif +#if WORLDVERTEXTRANSITION + float lerpAlpha = 1-i.worldPos_worldTransition.a; +#endif + +#if ( NORMALMAP == 0 ) + vNormal.xyz = normalize( i.normal.xyz ); +#endif + +#if ( NORMALMAP == 1 ) + vNormal.xyz = vNormal.xyz * 2.0f - 1.0f; // signed + +# if NORMALMAP2 + float3 normal2 = SampleNormal( NormalMap2Sampler, i ) * 2.0f - 1.0f; + vNormal.xyz = lerp( normal2, vNormal.xyz, lerpAlpha ); +# endif +#endif + +// ssbump +#if ( NORMALMAP == 2 ) + + +# if NORMALMAP2 + float3 normal2 = SampleNormal( NormalMap2Sampler, i ); + vNormal.xyz = lerp( normal2, vNormal.xyz, lerpAlpha ); +# endif +#if ( DETAILTEXTURE && ( DETAIL_BLEND_MODE == TCOMBINE_SSBUMP_BUMP ) ) + vNormal.xyz *= 2.0 * detailColor; +#endif + +#else + // Normalize normal after all of the lerps above (including the tri/bilinear texel fetches) + vNormal.xyz = normalize( vNormal.xyz ); +#endif + + spotColor.rgb *= cFlashlightColor.rgb; + + // Compute per-pixel distance attenuation + float3 delta = g_FlashlightPos.xyz - i.worldPos_worldTransition.xyz; + float distSquared = dot( delta, delta ); + float dist = sqrt( distSquared ); + float farZAtten = g_FlashlightAttenuation.w; + float endFalloffFactor = RemapValClamped( dist, farZAtten, 0.6f * farZAtten, 0.0f, 1.0f ); + float flAtten = saturate(endFalloffFactor * dot( g_FlashlightAttenuation.xyz, float3( 1.0f, 1.0f/dist, 1.0f/distSquared ) ) ); + +#if FLASHLIGHTSHADOWS && ( defined( SHADER_MODEL_PS_2_B ) || defined( SHADER_MODEL_PS_3_0 ) ) + float flShadow = DoFlashlightShadow( FlashlightDepthSampler, RandomRotationSampler, vProjCoords, i.projPos_fogFactorW.xy / i.projPos_fogFactorW.z, FLASHLIGHTDEPTHFILTERMODE, g_vShadowTweaks, false ); + float flAttenuated = lerp( flShadow, 1.0f, g_vShadowTweaks.y ); // Blend between fully attenuated and not attenuated + flShadow = saturate(lerp( flAttenuated, flShadow, flAtten )); // Blend between shadow and above, according to light attenuation + spotColor *= flShadow; +#endif + +#if UBERLIGHT && defined( SHADER_MODEL_PS_3_0 ) + // Transform from world space position to light space position + float3 flashlightSpacePosition = mul( float4( i.worldPos_worldTransition.xyz, 1.0f ), g_FlashlightWorldToLight ).yzx; + spotColor *= uberlight( flashlightSpacePosition, g_vSmoothEdge0, g_vSmoothEdge1, + g_vSmoothOneOverWidth, g_vShearRound.xy, g_aAbB, g_vShearRound.zw ); +#endif + + +#if WORLDVERTEXTRANSITION + baseColor.xyz = lerp( baseColor2.xyz, baseColor.xyz, lerpAlpha ); +#endif + +#if DETAILTEXTURE + float4 vBase = TextureCombine( baseColor, detailColor, DETAIL_BLEND_MODE, g_DetailConstants.w ); + baseColor.xyz = vBase.xyz; +#endif + +#if NORMALMAP == 0 + float3 worldPosToLightVector = texCUBE( NormalizingCubemapSampler, i.worldPosToLightVector ) * 2.0f - 1.0f; + float nDotL = dot( worldPosToLightVector, vNormal.xyz ); +#endif + +#if NORMALMAP == 1 + // flashlightfixme: wrap this! + float3 tangentPosToLightVector = texCUBE( NormalizingCubemapSampler, i.tangentPosToLightVector ) * 2.0f - 1.0f; + float nDotL = dot( tangentPosToLightVector, vNormal.xyz ); +#endif + +#if NORMALMAP == 2 + float3 tangentPosToLightVector = normalize( i.tangentPosToLightVector ); + + float nDotL = + vNormal.x*dot( tangentPosToLightVector, bumpBasis[0]) + + vNormal.y*dot( tangentPosToLightVector, bumpBasis[1]) + + vNormal.z*dot( tangentPosToLightVector, bumpBasis[2]); +#endif + + float3 outColor; + outColor = g_DiffuseModulation * spotColor * baseColor.xyz * saturate( nDotL ); + outColor *= flAtten; + + float flVertexFogFactor = 0.0f; + #if ( !HARDWAREFOGBLEND && !DOPIXELFOG ) + { + flVertexFogFactor = i.projPos_fogFactorW.w; + } + #endif + float fogFactor = CalcPixelFogFactorSupportsVertexFog( PIXELFOGTYPE, g_FogParams, g_EyePos.xyz, i.worldPos_worldTransition.xyz, i.projPos_fogFactorW.z, flVertexFogFactor ); + return FinalOutput( float4(outColor, baseColor.a), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR ); + + // so we can jump over all of the above +#if ( defined( _X360 ) ) + } + } +#endif + +} diff --git a/materialsystem/stdshaders/flesh_dx9.cpp b/materialsystem/stdshaders/flesh_dx9.cpp new file mode 100644 index 00000000..deffedd5 --- /dev/null +++ b/materialsystem/stdshaders/flesh_dx9.cpp @@ -0,0 +1,184 @@ +//========= Copyright © 1996-2009, Valve Corporation, All rights reserved. ============// +// +// Purpose: General 'flesh' shader for AlienSwarm +// +//=============================================================================// + +#include "BaseVSShader.h" +#include "flesh_helper.h" +#include "cpp_shader_constant_register_map.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( Flesh, Flesh_dx9 ) + +BEGIN_VS_SHADER( Flesh_dx9, "Flesh" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( NORMALMAP, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "normal map" ) + SHADER_PARAM( TRANSMATMASKSTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "Masks for material changes: fresnel hue-shift, jellyfish, forward scatter and back scatter" ); + SHADER_PARAM( EFFECTMASKSTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "Masks for material effects: self-illum, color warping, iridescence and clearcoat" ) + SHADER_PARAM( COLORWARPTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "3D rgb-lookup table texture for tinting color map" ) + SHADER_PARAM( FRESNELCOLORWARPTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "3D rgb-lookup table texture for tinting fresnel-based hue shift color" ) + SHADER_PARAM( OPACITYTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "Texture to control surface opacity when INTERIOR=1" ) + SHADER_PARAM( IRIDESCENTWARP, SHADER_PARAM_TYPE_TEXTURE, "shader/BaseTexture", "1D lookup texture for iridescent effect" ) + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shader/BaseTexture", "detail map" ) + + SHADER_PARAM( UVSCALE, SHADER_PARAM_TYPE_FLOAT, "1", "uv scale" ) + SHADER_PARAM( DETAILBLENDMODE, SHADER_PARAM_TYPE_INTEGER, "0", "detail blend mode: 1=mod2x, 2=add, 3=alpha blend (detailalpha), 4=crossfade, 5=additive self-illum, 6=multiply" ) + SHADER_PARAM( DETAILBLENDFACTOR, SHADER_PARAM_TYPE_FLOAT, "1.0", "strength of detail map" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "4.0", "detail map scale based on original UV set" ) + SHADER_PARAM( DETAILFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $detail" ) + SHADER_PARAM( DETAILTEXTURETRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$detail texcoord transform" ) + SHADER_PARAM( BUMPSTRENGTH, SHADER_PARAM_TYPE_FLOAT, "1.0", "bump map strength" ) + SHADER_PARAM( FRESNELBUMPSTRENGTH, SHADER_PARAM_TYPE_FLOAT, "1.0", "bump map strength for fresnel" ) + SHADER_PARAM( TRANSLUCENTFRESNELMINMAXEXP, SHADER_PARAM_TYPE_VEC3, "[0.8 1.0 1.0]", "translucency fresnel params" ) + + SHADER_PARAM( INTERIOR, SHADER_PARAM_TYPE_BOOL, "1", "enable surface translucency (refractive/foggy interior)" ) + SHADER_PARAM( INTERIORFOGSTRENGTH, SHADER_PARAM_TYPE_FLOAT, "0.06", "fog strength" ) + SHADER_PARAM( INTERIORBACKGROUNDBOOST, SHADER_PARAM_TYPE_FLOAT, "7", "boosts the brightness of bright background pixels" ) + SHADER_PARAM( INTERIORAMBIENTSCALE, SHADER_PARAM_TYPE_FLOAT, "0.3", "scales ambient light in the interior volume" ); + SHADER_PARAM( INTERIORBACKLIGHTSCALE, SHADER_PARAM_TYPE_FLOAT, "0.3", "scales backlighting in the interior volume" ); + SHADER_PARAM( INTERIORCOLOR, SHADER_PARAM_TYPE_VEC3, "[0.7 0.5 0.45]", "tints light in the interior volume" ) + SHADER_PARAM( INTERIORREFRACTSTRENGTH, SHADER_PARAM_TYPE_FLOAT, "0.015", "strength of bumped refract of the background seen through the interior" ) + SHADER_PARAM( INTERIORREFRACTBLUR, SHADER_PARAM_TYPE_FLOAT, "0.2", "strength of blur applied to the background seen through the interior" ) + + SHADER_PARAM( DIFFUSESOFTNORMAL, SHADER_PARAM_TYPE_FLOAT, "0.0f", "diffuse lighting uses softened normal" ) + SHADER_PARAM( DIFFUSEEXPONENT, SHADER_PARAM_TYPE_FLOAT, "1.0f", "diffuse lighting exponent" ) + SHADER_PARAM( PHONGEXPONENT, SHADER_PARAM_TYPE_FLOAT, "1.0", "specular exponent" ) + SHADER_PARAM( PHONGSCALE, SHADER_PARAM_TYPE_FLOAT, "1.0", "specular lighting scale" ) + SHADER_PARAM( PHONGEXPONENT2, SHADER_PARAM_TYPE_FLOAT, "1.0", "specular exponent 2" ) + SHADER_PARAM( PHONGFRESNEL, SHADER_PARAM_TYPE_VEC3, "[0 0.5 1]", "phong fresnel terms view-forward, 45 degrees, edge" ) + SHADER_PARAM( PHONGSCALE2, SHADER_PARAM_TYPE_FLOAT, "1.0", "specular lighting 2 scale" ) + SHADER_PARAM( PHONGFRESNEL2, SHADER_PARAM_TYPE_VEC3, "[1 1 1]", "phong fresnel terms view-forward, 45 degrees, edge" ) + SHADER_PARAM( PHONG2SOFTNESS, SHADER_PARAM_TYPE_FLOAT, "1.0", "clearcoat uses softened normal" ) + SHADER_PARAM( RIMLIGHTEXPONENT, SHADER_PARAM_TYPE_FLOAT, "1.0", "rim lighting exponent" ) + SHADER_PARAM( RIMLIGHTSCALE, SHADER_PARAM_TYPE_FLOAT, "1.0", "rim lighting scale" ) + SHADER_PARAM( PHONGCOLORTINT, SHADER_PARAM_TYPE_VEC3, "[1.0 1.0 1.0]", "specular texture tint" ) + SHADER_PARAM( AMBIENTBOOST, SHADER_PARAM_TYPE_FLOAT, "0.0", "ambient boost amount" ) + SHADER_PARAM( AMBIENTBOOSTMASKMODE, SHADER_PARAM_TYPE_INTEGER, "0", "masking mode for ambient scale: 0 = allover, 1 or 2 = mask by transmatmask r or g, 3 to 5 effectmask g b or a" ) + + SHADER_PARAM( BACKSCATTER, SHADER_PARAM_TYPE_FLOAT, "0.0", "subsurface back-scatter intensity" ) + SHADER_PARAM( FORWARDSCATTER, SHADER_PARAM_TYPE_FLOAT, "0.0", "subsurface forward-scatter intensity" ) + SHADER_PARAM( SSDEPTH, SHADER_PARAM_TYPE_FLOAT, "0.1", "subsurface depth over which effect is not visible" ) + SHADER_PARAM( SSBENTNORMALINTENSITY, SHADER_PARAM_TYPE_FLOAT, "0.2", "subsurface bent normal intensity: higher is more view-dependent" ) + SHADER_PARAM( SSCOLORTINT, SHADER_PARAM_TYPE_VEC3, "[0.2, 0.05, 0.0]", "color tint for subsurface effects" ) + SHADER_PARAM( SSTINTBYALBEDO, SHADER_PARAM_TYPE_FLOAT, "0.0", "blend ss color tint to albedo color based on this factor" ) + SHADER_PARAM( NORMAL2SOFTNESS, SHADER_PARAM_TYPE_FLOAT, "0.0", "mip level for effects with soft normal (clearcoat and subsurface)" ) + SHADER_PARAM( HUESHIFTINTENSITY, SHADER_PARAM_TYPE_FLOAT, "0.5", "scales effect of fresnel-based hue-shift" ) + SHADER_PARAM( HUESHIFTFRESNELEXPONENT, SHADER_PARAM_TYPE_FLOAT, "2.0f", "fresnel exponent for hue-shift (edge-based)" ) + SHADER_PARAM( IRIDESCENCEBOOST, SHADER_PARAM_TYPE_FLOAT, "1.0f", "boost iridescence effect") + SHADER_PARAM( IRIDESCENCEEXPONENT, SHADER_PARAM_TYPE_FLOAT, "2.0f", "fresnel exponent for iridescence effect (center-based)" ) + SHADER_PARAM( SELFILLUMTINT, SHADER_PARAM_TYPE_VEC3, "[0.7 0.5 0.45]", "self-illum color tint" ) + + SHADER_PARAM( UVPROJOFFSET, SHADER_PARAM_TYPE_VEC3, "[0 0 0]", "Center for UV projection" ) + SHADER_PARAM( BBMIN, SHADER_PARAM_TYPE_VEC3, "[0 0 0]", "UV projection bounding box min" ) + SHADER_PARAM( BBMAX, SHADER_PARAM_TYPE_VEC3, "[0 0 0]", "UV projection bounding box max" ) + + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "normal map animated texture frame" ) + END_SHADER_PARAMS + + void SetupVarsFlesh( FleshVars_t &info ) + { + info.m_nBaseTexture = BASETEXTURE; + info.m_nBaseTextureTransform = BASETEXTURETRANSFORM; + info.m_nNormalMap = NORMALMAP; + info.m_nDetailTexture = DETAIL; + info.m_nColorWarpTexture = COLORWARPTEXTURE; + info.m_nFresnelColorWarpTexture = FRESNELCOLORWARPTEXTURE; + info.m_nTransMatMasksTexture = TRANSMATMASKSTEXTURE; + info.m_nEffectMasksTexture = EFFECTMASKSTEXTURE; + info.m_nIridescentWarpTexture = IRIDESCENTWARP; + info.m_nOpacityTexture = OPACITYTEXTURE; + info.m_nBumpStrength = BUMPSTRENGTH; + info.m_nFresnelBumpStrength = FRESNELBUMPSTRENGTH; + info.m_nUVScale = UVSCALE; + info.m_nDetailScale = DETAILSCALE; + info.m_nDetailFrame = DETAILFRAME; + info.m_nDetailBlendMode = DETAILBLENDMODE; + info.m_nDetailBlendFactor = DETAILBLENDFACTOR; + info.m_nDetailTextureTransform = DETAILTEXTURETRANSFORM; + + info.m_nInteriorEnable = INTERIOR; + info.m_nInteriorFogStrength = INTERIORFOGSTRENGTH; + info.m_nInteriorBackgroundBoost = INTERIORBACKGROUNDBOOST; + info.m_nInteriorAmbientScale = INTERIORAMBIENTSCALE; + info.m_nInteriorBackLightScale = INTERIORBACKLIGHTSCALE; + info.m_nInteriorColor = INTERIORCOLOR; + info.m_nInteriorRefractStrength = INTERIORREFRACTSTRENGTH; + info.m_nInteriorRefractBlur = INTERIORREFRACTBLUR; + + info.m_nFresnelParams = TRANSLUCENTFRESNELMINMAXEXP; + info.m_nDiffuseSoftNormal = DIFFUSESOFTNORMAL; + info.m_nDiffuseExponent = DIFFUSEEXPONENT; + info.m_nSpecExp = PHONGEXPONENT; + info.m_nSpecScale = PHONGSCALE; + info.m_nSpecFresnel = PHONGFRESNEL; + info.m_nSpecExp2 = PHONGEXPONENT2; + info.m_nSpecScale2 = PHONGSCALE2; + info.m_nSpecFresnel2 = PHONGFRESNEL2; + info.m_nPhong2Softness = PHONG2SOFTNESS; + info.m_nRimLightExp = RIMLIGHTEXPONENT; + info.m_nRimLightScale = RIMLIGHTSCALE; + info.m_nPhongColorTint = PHONGCOLORTINT; + info.m_nSelfIllumTint = SELFILLUMTINT; + info.m_nUVProjOffset = UVPROJOFFSET; + info.m_nBBMin = BBMIN; + info.m_nBBMax = BBMAX; + info.m_nFlashlightTexture = FLASHLIGHTTEXTURE; + info.m_nFlashlightTextureFrame = FLASHLIGHTTEXTUREFRAME; + info.m_nBumpFrame = BUMPFRAME; + info.m_nBackScatter = BACKSCATTER; + info.m_nForwardScatter = FORWARDSCATTER; + info.m_nAmbientBoost = AMBIENTBOOST; + info.m_nAmbientBoostMaskMode = AMBIENTBOOSTMASKMODE; + info.m_nIridescenceExponent = IRIDESCENCEEXPONENT; + info.m_nIridescenceBoost = IRIDESCENCEBOOST; + info.m_nHueShiftIntensity = HUESHIFTINTENSITY; + info.m_nHueShiftFresnelExponent = HUESHIFTFRESNELEXPONENT; + info.m_nSSDepth = SSDEPTH; + info.m_nSSTintByAlbedo = SSTINTBYALBEDO; + info.m_nSSBentNormalIntensity = SSBENTNORMALINTENSITY; + info.m_nSSColorTint = SSCOLORTINT; + info.m_nNormal2Softness = NORMAL2SOFTNESS; + } + + bool IsTranslucent( IMaterialVar **params ) const + { + // Could be alpha-blended or refractive ('interior') + return IS_FLAG_SET( MATERIAL_VAR_TRANSLUCENT ) || !!params[INTERIOR]->GetIntValue(); + } + + SHADER_INIT_PARAMS() + { + FleshVars_t info; + SetupVarsFlesh( info ); + InitParamsFlesh( this, params, pMaterialName, info ); + } + + SHADER_FALLBACK + { + // TODO: Reasonable fallback + if ( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + { + return "Wireframe"; + } + + return 0; + } + + SHADER_INIT + { + FleshVars_t info; + SetupVarsFlesh( info ); + InitFlesh( this, params, info ); + } + + SHADER_DRAW + { + FleshVars_t info; + SetupVarsFlesh( info ); + DrawFlesh( this, params, pShaderAPI, pShaderShadow, info, vertexCompression, pContextDataPtr ); + } + +END_SHADER \ No newline at end of file diff --git a/materialsystem/stdshaders/flesh_helper.cpp b/materialsystem/stdshaders/flesh_helper.cpp new file mode 100644 index 00000000..5e143ae8 --- /dev/null +++ b/materialsystem/stdshaders/flesh_helper.cpp @@ -0,0 +1,577 @@ +//========= Copyright © 1996-2009, Valve Corporation, All rights reserved. ============// + +#include "BaseVSShader.h" +#include "flesh_helper.h" +#include "cpp_shader_constant_register_map.h" +/* +#include "mathlib/VMatrix.h" +#include "convar.h" +*/ + +// Auto generated inc files +#include "flesh_vs30.inc" +#include "flesh_ps30.inc" + +#include "shaderlib/commandbuilder.h" + + +void InitParamsFlesh( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, FleshVars_t &info ) +{ + // Set material parameter default values + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nUVScale, kDefaultUVScale ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nDetailScale, kDefaultDetailScale ); + SET_PARAM_INT_IF_NOT_DEFINED( info.m_nDetailFrame, kDefaultDetailFrame ); + SET_PARAM_INT_IF_NOT_DEFINED( info.m_nDetailBlendMode, kDefaultDetailBlendMode ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nDetailBlendFactor, kDefaultDetailBlendFactor ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nBumpStrength, kDefaultBumpStrength ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nFresnelBumpStrength, kDefaultFresnelBumpStrength ); + + SET_PARAM_INT_IF_NOT_DEFINED( info.m_nInteriorEnable, kDefaultInteriorEnable ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nInteriorFogStrength, kDefaultInteriorFogStrength ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nInteriorBackgroundBoost, kDefaultInteriorBackgroundBoost ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nInteriorAmbientScale, kDefaultInteriorAmbientScale ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nInteriorBackLightScale, kDefaultInteriorBackLightScale ); + SET_PARAM_VEC_IF_NOT_DEFINED( info.m_nInteriorColor, kDefaultInteriorColor, 3 ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nInteriorRefractStrength, kDefaultInteriorRefractStrength ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nInteriorRefractBlur, kDefaultInteriorRefractBlur ); + + SET_PARAM_VEC_IF_NOT_DEFINED( info.m_nFresnelParams, kDefaultFresnelParams, 3 ); + SET_PARAM_VEC_IF_NOT_DEFINED( info.m_nPhongColorTint, kDefaultPhongColorTint, 3 ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nDiffuseSoftNormal, kDefaultDiffuseSoftNormal ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nDiffuseExponent, kDefaultDiffuseExponent ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nSpecExp, kDefaultSpecExp ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nSpecScale, kDefaultSpecScale ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nSpecExp2, kDefaultSpecExp ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nSpecScale2, kDefaultSpecScale ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nPhong2Softness, kDefaultPhong2Softness ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nRimLightExp, kDefaultRimLightExp ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nRimLightScale, kDefaultRimLightScale ); + SET_PARAM_VEC_IF_NOT_DEFINED( info.m_nSelfIllumTint, kDefaultSelfIllumTint, 3 ); + SET_PARAM_VEC_IF_NOT_DEFINED( info.m_nUVProjOffset, kDefaultUVProjOffset, 3 ); + SET_PARAM_VEC_IF_NOT_DEFINED( info.m_nBBMin, kDefaultBB, 3 ); + SET_PARAM_VEC_IF_NOT_DEFINED( info.m_nBBMax, kDefaultBB, 3 ); + + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nBackScatter, kDefaultBackScatter ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nForwardScatter, kDefaultForwardScatter ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nAmbientBoost, kDefaultAmbientBoost ); + SET_PARAM_INT_IF_NOT_DEFINED( info.m_nAmbientBoostMaskMode, kDefaultAmbientBoostMaskMode ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nIridescenceExponent, kDefaultIridescenceExponent ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nIridescenceBoost, kDefaultIridescenceBoost ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nHueShiftIntensity, kDefaultHueShiftIntensity ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nHueShiftFresnelExponent, kDefaultHueShiftFresnelExponent ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nSSDepth, kDefaultSSDepth ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nSSTintByAlbedo, kDefaultSSTintByAlbedo ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nSSBentNormalIntensity, kDefaultSSBentNormalIntensity ); + SET_PARAM_VEC_IF_NOT_DEFINED( info.m_nSSColorTint, kDefaultSSColorTint, 3 ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nNormal2Softness, kDefaultNormal2Softness ); + + // FLASHLIGHTFIXME: Do ShaderAPI::BindFlashlightTexture + Assert( info.m_nFlashlightTexture >= 0 ); + params[FLASHLIGHTTEXTURE]->SetStringValue( GetFlashlightTextureFilename() ); + + SET_PARAM_INT_IF_NOT_DEFINED( info.m_nFlashlightTextureFrame, 0 ); + + SET_PARAM_INT_IF_NOT_DEFINED( info.m_nBumpFrame, kDefaultBumpFrame ) + + // Set material flags + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + + //SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + + // If 'interior' is enabled, we use the refract buffer: + if ( params[info.m_nInteriorEnable]->IsDefined() && params[info.m_nInteriorEnable]->GetIntValue() != 0 ) + { + //SET_FLAGS2( MATERIAL_VAR2_NEEDS_FULL_FRAME_BUFFER_TEXTURE ); + SET_FLAGS2( MATERIAL_VAR2_NEEDS_POWER_OF_TWO_FRAME_BUFFER_TEXTURE ); + } +} + +void InitFlesh( CBaseVSShader *pShader, IMaterialVar** params, FleshVars_t &info ) +{ + // Load textures + if ( (info.m_nBaseTexture != -1) && params[info.m_nBaseTexture]->IsDefined() ) + { + pShader->LoadTexture( info.m_nBaseTexture ); + } + + if ( (info.m_nNormalMap != -1) && params[info.m_nNormalMap]->IsDefined() ) + { + pShader->LoadTexture( info.m_nNormalMap ); + } + + if ( (info.m_nTransMatMasksTexture != -1) && params[info.m_nTransMatMasksTexture]->IsDefined() ) + { + pShader->LoadTexture( info.m_nTransMatMasksTexture ); + } + + if ( (info.m_nEffectMasksTexture != -1) && params[info.m_nEffectMasksTexture]->IsDefined() ) + { + pShader->LoadTexture( info.m_nEffectMasksTexture ); + } + + if ( (info.m_nIridescentWarpTexture != -1) && params[info.m_nIridescentWarpTexture]->IsDefined() ) + { + pShader->LoadTexture( info.m_nIridescentWarpTexture ); + } + + if ( (info.m_nFresnelColorWarpTexture != -1) && params[info.m_nFresnelColorWarpTexture]->IsDefined() ) + { + pShader->LoadTexture( info.m_nFresnelColorWarpTexture ); + } + + if ( (info.m_nColorWarpTexture != -1) && params[info.m_nColorWarpTexture]->IsDefined() ) + { + pShader->LoadTexture( info.m_nColorWarpTexture ); + } + + if ( (info.m_nOpacityTexture != -1) && params[info.m_nOpacityTexture]->IsDefined() ) + { + pShader->LoadTexture( info.m_nOpacityTexture ); + } + + if ( (info.m_nFlashlightTexture != -1) && params[info.m_nFlashlightTexture]->IsDefined() ) + { + pShader->LoadTexture( info.m_nFlashlightTexture ); + } + + if ( ( info.m_nDetailTexture != -1) && params[info.m_nDetailTexture]->IsDefined() ) + { + pShader->LoadTexture( info.m_nDetailTexture ); + } +} + +class CFlesh_DX9_Context : public CBasePerMaterialContextData +{ +public: + CCommandBufferBuilder< CFixedCommandStorageBuffer< 1200 > > m_SemiStaticCmdsOut; +}; + +void DrawFlesh( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, FleshVars_t &info, VertexCompressionType_t vertexCompression, + CBasePerMaterialContextData **pContextDataPtr ) +{ + CFlesh_DX9_Context *pContextData = reinterpret_cast< CFlesh_DX9_Context *> ( *pContextDataPtr ); + + bool bHasFlashlight = pShader->UsingFlashlight( params ); + bool bAlphaBlend = IS_FLAG_SET( MATERIAL_VAR_TRANSLUCENT ); + bool bDetail = ( info.m_nDetailTexture != -1 ) && ( params[info.m_nDetailTexture]->IsTexture() ); + + if ( pShader->IsSnapshotting() || (! pContextData ) || ( pContextData->m_bMaterialVarsChanged ) ) + { + bool bTransMatMasks = (info.m_nTransMatMasksTexture != -1) && params[info.m_nTransMatMasksTexture]->IsTexture(); + bool bEffectMasks = (info.m_nEffectMasksTexture != -1) && params[info.m_nEffectMasksTexture]->IsTexture(); + bool bIridescentWarp = (info.m_nIridescentWarpTexture != -1) && params[info.m_nIridescentWarpTexture]->IsTexture(); + bool bFresnelColorWarp = (info.m_nFresnelColorWarpTexture != -1) && params[info.m_nFresnelColorWarpTexture]->IsTexture(); + bool bColorWarp = (info.m_nColorWarpTexture != -1) && params[info.m_nColorWarpTexture]->IsTexture(); + bool bOpacityTexture = (info.m_nOpacityTexture != -1) && params[info.m_nOpacityTexture]->IsTexture(); + bool bInteriorLayer = (info.m_nInteriorEnable != -1) && ( params[info.m_nInteriorEnable]->GetIntValue() > 0 ); + bool bBackScatter = ( info.m_nBackScatter != -1 ) && ( params[info.m_nBackScatter]->GetFloatValue() > 0 ); + bool bForwardScatter = ( info.m_nForwardScatter != -1) && ( params[info.m_nForwardScatter]->GetFloatValue() > 0 ); + bool bNormal2 = ( info.m_nNormal2Softness != -1 ) && ( params[info.m_nNormal2Softness]->GetFloatValue() > 0 ); + + if ( pShader->IsSnapshotting() ) + { + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 4; + int texCoordDims[4] = { 2, 2, 2, 2 }; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, texCoordDims, userDataSize ); + + int nShadowFilterMode = 0; + if ( bHasFlashlight ) + { + nShadowFilterMode = g_pHardwareConfig->GetShadowFilterMode(); // Based upon vendor and device dependent formats + } + + DECLARE_STATIC_VERTEX_SHADER( flesh_vs30 ); + SET_STATIC_VERTEX_SHADER( flesh_vs30 ); + + // Pixel Shader + if( /* g_pHardwareConfig->SupportsPixelShaders_3_0() */ true ) + { + DECLARE_STATIC_PIXEL_SHADER( flesh_ps30 ); + SET_STATIC_PIXEL_SHADER_COMBO( ALPHABLEND, bAlphaBlend ); + SET_STATIC_PIXEL_SHADER_COMBO( TRANSMAT, bTransMatMasks ); + SET_STATIC_PIXEL_SHADER_COMBO( FRESNEL_WARP, bFresnelColorWarp ); + SET_STATIC_PIXEL_SHADER_COMBO( EFFECTS, bEffectMasks ); + SET_STATIC_PIXEL_SHADER_COMBO( TINTING, bColorWarp ); + SET_STATIC_PIXEL_SHADER_COMBO( IRIDESCENCE, bIridescentWarp ); + SET_STATIC_PIXEL_SHADER_COMBO( OPACITY_TEXTURE, bOpacityTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL, bDetail ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMAL2SOFT, bNormal2 ); + SET_STATIC_PIXEL_SHADER_COMBO( INTERIOR_LAYER, bInteriorLayer ); + SET_STATIC_PIXEL_SHADER_COMBO( BACK_SCATTER, bBackScatter ); + SET_STATIC_PIXEL_SHADER_COMBO( FORWARD_SCATTER, bForwardScatter ); + SET_STATIC_PIXEL_SHADER_COMBO( HIGH_PRECISION_DEPTH, (g_pHardwareConfig->GetHDRType() == HDR_TYPE_FLOAT) ? true : false ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER( flesh_ps30 ); + } + else + { + Assert( !"No ps_3_0" ); + } + + // Textures + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); // [sRGB] Base + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); // Bump + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, false ); + if( bInteriorLayer ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); // [sRGB] Backbuffer + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, true ); + } + if( bTransMatMasks ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); // Trans mat masks + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER3, false ); + } + if( bColorWarp ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); // [sRGB] Color Warp + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER4, true ); + } + if( bFresnelColorWarp ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); // [sRGB] Fresnel color warp (should be sRGB?) + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER5, true ); + } + if( bOpacityTexture ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); // Opacity + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER6, false ); + } + if( bEffectMasks ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER10, true ); // Effect masks + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER10, false ); + } + if( bIridescentWarp ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER11, true ); // [sRGB] Iridescent warp + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER11, true ); + } + if( bDetail ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER12, true ); // [sRGB] Detail + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER12, true ); + } + if ( bHasFlashlight ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER7, true ); // Shadow depth map + pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER7 ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER7, false ); + pShaderShadow->EnableTexture( SHADER_SAMPLER8, true ); // Noise map + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER8, false ); + pShaderShadow->EnableTexture( SHADER_SAMPLER9, true ); //[sRGB] Flashlight cookie + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER9, true ); + + // Flashlight passes - additive blending + pShader->EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + pShaderShadow->EnableAlphaWrites( false ); + pShaderShadow->EnableDepthWrites( false ); + } + else if ( bAlphaBlend ) + { + // Base pass - alpha blending (regular translucency) + pShader->EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + pShaderShadow->EnableAlphaWrites( false ); // TODO: write alpha for fog or not? + pShaderShadow->EnableDepthWrites( true ); // Rely on depth-sorting + } + else + { + // Base pass - opaque blending (solid flesh or refractive translucency) + pShader->DisableAlphaBlending(); + pShaderShadow->EnableAlphaWrites( true ); + pShaderShadow->EnableDepthWrites( true ); + } + + pShaderShadow->EnableSRGBWrite( true ); + + // Per-instance state + pShader->PI_BeginCommandBuffer(); + pShader->PI_SetVertexShaderAmbientLightCube(); + pShader->PI_SetPixelShaderAmbientLightCube( PSREG_AMBIENT_CUBE ); + pShader->PI_SetPixelShaderLocalLighting( PSREG_LIGHT_INFO_ARRAY ); + pShader->PI_EndCommandBuffer(); + } + if ( pShaderAPI && ( (! pContextData ) || ( pContextData->m_bMaterialVarsChanged ) ) ) + { + if ( !pContextData ) // make sure allocated + { + pContextData = new CFlesh_DX9_Context; + *pContextDataPtr = pContextData; + } + pContextData->m_bMaterialVarsChanged = false; + pContextData->m_SemiStaticCmdsOut.Reset(); + /////////////////////////// + // Semi-static block + /////////////////////////// + float flConsts[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + + flConsts[0] = IS_PARAM_DEFINED( info.m_nBumpStrength ) ? params[info.m_nBumpStrength]->GetFloatValue() : kDefaultBumpStrength; + flConsts[1] = (g_pHardwareConfig->GetHDRType() == HDR_TYPE_FLOAT) ? 8192.0f : 192.0f; // destalpha dest scale factor. TODO: put this in its own const and call shaderAPI method to set + flConsts[2] = IS_PARAM_DEFINED( info.m_nInteriorFogStrength ) ? params[info.m_nInteriorFogStrength]->GetFloatValue() : kDefaultInteriorFogStrength; + flConsts[3] = IS_PARAM_DEFINED( info.m_nInteriorRefractStrength ) ? params[info.m_nInteriorRefractStrength]->GetFloatValue() : kDefaultInteriorRefractStrength; + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 0, flConsts, 1 ); + + Assert( IS_PARAM_DEFINED( info.m_nFresnelParams ) ); + if ( IS_PARAM_DEFINED( info.m_nFresnelParams ) ) + params[info.m_nFresnelParams]->GetVecValue( flConsts, 3 ); + else + memcpy( flConsts, kDefaultFresnelParams, sizeof( kDefaultFresnelParams ) ); + flConsts[3] = params[info.m_nInteriorBackgroundBoost]->GetFloatValue(); + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 1, flConsts, 1 ); + + flConsts[0] = IS_PARAM_DEFINED( info.m_nRimLightExp ) ? params[info.m_nRimLightExp]->GetFloatValue() : kDefaultRimLightExp; + flConsts[1] = IS_PARAM_DEFINED( info.m_nRimLightScale ) ? params[info.m_nRimLightScale]->GetFloatValue() : kDefaultRimLightScale; + flConsts[2] = IS_PARAM_DEFINED( info.m_nSpecScale ) ? params[info.m_nSpecScale]->GetFloatValue() : kDefaultSpecScale; + flConsts[3] = IS_PARAM_DEFINED( info.m_nSpecExp2 ) ? params[info.m_nSpecExp2]->GetFloatValue() : kDefaultSpecExp; + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 3, flConsts, 1 ); + + flConsts[0] = IS_PARAM_DEFINED( info.m_nSpecScale2 ) ? params[info.m_nSpecScale2]->GetFloatValue() : kDefaultSpecScale; + flConsts[1] = IS_PARAM_DEFINED( info.m_nFresnelBumpStrength ) ? params[info.m_nFresnelBumpStrength]->GetFloatValue() : kDefaultFresnelBumpStrength; + flConsts[2] = IS_PARAM_DEFINED( info.m_nDiffuseSoftNormal ) ? params[info.m_nDiffuseSoftNormal]->GetFloatValue() : kDefaultDiffuseSoftNormal; + flConsts[3] = IS_PARAM_DEFINED( info.m_nInteriorAmbientScale ) ? params[info.m_nInteriorAmbientScale]->GetFloatValue() : kDefaultInteriorAmbientScale; + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 10, flConsts, 1 ); + + // Depth alpha [ TODO: support fog ] + bool bWriteDepthToAlpha = pShaderAPI->ShouldWriteDepthToDestAlpha() && !bAlphaBlend; + if ( IS_PARAM_DEFINED( info.m_nSpecFresnel ) ) + params[info.m_nSpecFresnel]->GetVecValue( flConsts, 3 ); + else + memcpy( flConsts, kDefaultSpecFresnel, sizeof( kDefaultSpecFresnel ) ); + flConsts[3] = bWriteDepthToAlpha ? 1.0f : 0.0f; + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 12, flConsts, 1 ); + + if ( IS_PARAM_DEFINED( info.m_nPhongColorTint ) ) + params[info.m_nPhongColorTint]->GetVecValue( flConsts, 3 ); + else + memcpy( flConsts, kDefaultPhongColorTint, sizeof( kDefaultPhongColorTint ) ); + flConsts[3] = IS_PARAM_DEFINED( info.m_nInteriorBackLightScale ) ? params[info.m_nInteriorBackLightScale]->GetFloatValue() : kDefaultInteriorBackLightScale; + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 19, flConsts, 1 ); + + if( bIridescentWarp || bFresnelColorWarp ) + { + flConsts[0] = ( IS_PARAM_DEFINED( info.m_nIridescenceBoost ) ) ? params[info.m_nIridescenceBoost]->GetFloatValue(): kDefaultIridescenceBoost; + flConsts[1] = ( IS_PARAM_DEFINED( info.m_nIridescenceExponent ) ) ? params[info.m_nIridescenceExponent]->GetFloatValue(): kDefaultIridescenceExponent; + flConsts[2] = ( IS_PARAM_DEFINED( info.m_nHueShiftIntensity ) ) ? params[info.m_nHueShiftIntensity]->GetFloatValue(): kDefaultHueShiftIntensity; + flConsts[3] = ( IS_PARAM_DEFINED( info.m_nHueShiftFresnelExponent ) ) ? params[info.m_nHueShiftFresnelExponent]->GetFloatValue(): kDefaultHueShiftFresnelExponent; + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 26, flConsts, 1 ); + } + + if ( IS_PARAM_DEFINED( info.m_nSelfIllumTint ) ) + params[info.m_nSelfIllumTint]->GetVecValue( flConsts, 3 ); + else + memcpy( flConsts, kDefaultSelfIllumTint, sizeof( kDefaultSelfIllumTint ) ); + float flDiffuseExp = IS_PARAM_DEFINED( info.m_nDiffuseExponent ) ? params[info.m_nDiffuseExponent]->GetFloatValue() : kDefaultDiffuseExponent; + flConsts[3] = pow( 0.5f, flDiffuseExp ); + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 27, flConsts, 1 ); + + if ( IS_PARAM_DEFINED( info.m_nInteriorColor ) ) + params[info.m_nInteriorColor]->GetVecValue( flConsts, 3 ); + else + memcpy( flConsts, kDefaultInteriorColor, sizeof( kDefaultInteriorColor ) ); + flConsts[3] = params[info.m_nInteriorRefractBlur]->GetFloatValue(); + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 32, flConsts, 1 ); + + if ( IS_PARAM_DEFINED( info.m_nSpecFresnel2 ) ) + params[info.m_nSpecFresnel2]->GetVecValue( flConsts, 3 ); + else + memcpy( flConsts, kDefaultSpecFresnel2, sizeof( kDefaultSpecFresnel2 ) ); + flConsts[3] = IS_PARAM_DEFINED( info.m_nPhong2Softness ) ? params[info.m_nPhong2Softness]->GetFloatValue() : kDefaultPhong2Softness; + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 42, flConsts, 1 ); + + flConsts[0] = flDiffuseExp; + flConsts[1] = IS_PARAM_DEFINED( info.m_nNormal2Softness ) ? params[info.m_nNormal2Softness]->GetFloatValue() : kDefaultNormal2Softness; + flConsts[2] = IS_PARAM_DEFINED( info.m_nAmbientBoost ) ? params[info.m_nAmbientBoost]->GetFloatValue() : kDefaultAmbientBoost; + flConsts[3] = IS_PARAM_DEFINED( info.m_nAmbientBoostMaskMode ) ? params[info.m_nAmbientBoostMaskMode]->GetIntValue() : kDefaultAmbientBoostMaskMode; + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 43, flConsts, 1 ); + + if ( bForwardScatter || bBackScatter ) + { + flConsts[0] = IS_PARAM_DEFINED( info.m_nForwardScatter ) ? params[info.m_nForwardScatter]->GetFloatValue() : kDefaultForwardScatter; + flConsts[1] = IS_PARAM_DEFINED( info.m_nBackScatter ) ? params[info.m_nBackScatter]->GetFloatValue() : kDefaultBackScatter; + flConsts[2] = IS_PARAM_DEFINED( info.m_nSSDepth ) ? params[info.m_nSSDepth]->GetFloatValue() : kDefaultSSDepth; + flConsts[3] = IS_PARAM_DEFINED( info.m_nSSBentNormalIntensity ) ? params[info.m_nSSBentNormalIntensity]->GetFloatValue() : kDefaultSSBentNormalIntensity; + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 44, flConsts, 1 ); + + if( IS_PARAM_DEFINED( info.m_nSSColorTint ) ) + params[info.m_nSSColorTint]->GetVecValue( flConsts, 3 ); + else + memcpy( flConsts, kDefaultSSColorTint, sizeof( kDefaultSSColorTint ) ); + flConsts[3] = IS_PARAM_DEFINED( info.m_nSSTintByAlbedo ) ? params[info.m_nSSTintByAlbedo]->GetFloatValue() : kDefaultSSTintByAlbedo; + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 45, flConsts, 1 ); + } + + flConsts[0] = 0.0f; + flConsts[1] = 0.0f; + if ( bDetail ) + { + flConsts[0] = IS_PARAM_DEFINED( info.m_nDetailBlendMode ) ? params[info.m_nDetailBlendMode]->GetIntValue() : kDefaultDetailBlendMode; + flConsts[1] = IS_PARAM_DEFINED( info.m_nDetailBlendFactor) ? params[info.m_nDetailBlendFactor]->GetFloatValue() : kDefaultDetailBlendFactor; + flConsts[2] = 0.0f; + } + flConsts[3] = IS_PARAM_DEFINED( info.m_nSpecExp ) ? params[info.m_nSpecExp]->GetFloatValue() : kDefaultSpecExp; + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 46, flConsts, 1 ); + + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER0, BASETEXTURE, -1 ); + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER1, info.m_nNormalMap, -1 ); + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER2, TEXTURE_FRAME_BUFFER_FULL_TEXTURE_0 ); // Refraction Map + + if ( bTransMatMasks ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER3, info.m_nTransMatMasksTexture, -1 ); + } + + if ( bColorWarp ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER4, info.m_nColorWarpTexture, -1 ); + } + + if ( bFresnelColorWarp ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER5, info.m_nFresnelColorWarpTexture, -1 ); + } + + if ( bOpacityTexture ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER6, info.m_nOpacityTexture, -1 ); + } + + if ( bEffectMasks ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER10, info.m_nEffectMasksTexture, -1 ); + } + + if ( bIridescentWarp ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER11, info.m_nIridescentWarpTexture, -1 ); + } + + // VS consts + flConsts[0] = IS_PARAM_DEFINED( info.m_nUVScale ) ? params[info.m_nUVScale]->GetFloatValue() : kDefaultUVScale; + pContextData->m_SemiStaticCmdsOut.SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, flConsts, 1 ); + + flConsts[0] = IS_PARAM_DEFINED( info.m_nDetailScale ) ? params[info.m_nDetailScale]->GetFloatValue() : kDefaultDetailScale; + pContextData->m_SemiStaticCmdsOut.SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, flConsts, 1 ); + + if ( IS_PARAM_DEFINED( info.m_nDetailTextureTransform ) ) + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, info.m_nDetailTextureTransform, info.m_nDetailScale ); + else + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, info.m_nBaseTextureTransform, info.m_nDetailScale ); + + pContextData->m_SemiStaticCmdsOut.End(); + // end semi-static block + } + } + + if ( pShaderAPI ) //DYNAMIC_STATE + { + CCommandBufferBuilder< CFixedCommandStorageBuffer< 400 > > DynamicCmdsOut; + DynamicCmdsOut.Call( pContextData->m_SemiStaticCmdsOut.Base() ); + /////////////////////////// + // dynamic block + /////////////////////////// + + float camPos[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + pShaderAPI->GetWorldSpaceCameraPosition( camPos ); + DynamicCmdsOut.SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, camPos ); + + if ( bDetail ) + { + DynamicCmdsOut.BindTexture( pShader, SHADER_SAMPLER12, info.m_nDetailTexture, info.m_nDetailFrame ); + } + + float mView[16]; + pShaderAPI->GetMatrix( MATERIAL_VIEW, mView ); + DynamicCmdsOut.SetPixelShaderConstant( 33, mView, 3 ); + + DynamicCmdsOut.SetPixelShaderFogParams( 36 ); + + LightState_t lightState = { 0, false, false }; + pShaderAPI->GetDX9LightState( &lightState ); + + // flashlightfixme: put this in common code. + bool bFlashlightShadows = false; + if ( bHasFlashlight ) + { + Assert( info.m_nFlashlightTexture >= 0 && info.m_nFlashlightTextureFrame >= 0 ); + VMatrix worldToTexture; + ITexture *pFlashlightDepthTexture; + FlashlightState_t state = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture ); + DynamicCmdsOut.BindTexture( pShader, SHADER_SAMPLER9, state.m_pSpotlightTexture, state.m_nSpotlightTextureFrame ); + bFlashlightShadows = state.m_bEnableShadows; + + SetFlashLightColorFromState( state, pShaderAPI, PSREG_FLASHLIGHT_COLOR ); + + if( pFlashlightDepthTexture && g_pConfig->ShadowDepthTexture() && state.m_bEnableShadows ) + { + DynamicCmdsOut.BindTexture( pShader, SHADER_SAMPLER7, pFlashlightDepthTexture, -1 ); + DynamicCmdsOut.BindStandardTexture( SHADER_SAMPLER8, TEXTURE_SHADOW_NOISE_2D ); + } + + float atten[4], pos[4], tweaks[4]; + + atten[0] = state.m_fConstantAtten; // Set the flashlight attenuation factors + atten[1] = state.m_fLinearAtten; + atten[2] = state.m_fQuadraticAtten; + atten[3] = state.m_FarZAtten; + DynamicCmdsOut.SetPixelShaderConstant( PSREG_FLASHLIGHT_ATTENUATION, atten, 1 ); + + pos[0] = state.m_vecLightOrigin[0]; // Set the flashlight origin + pos[1] = state.m_vecLightOrigin[1]; + pos[2] = state.m_vecLightOrigin[2]; + pos[3] = state.m_FarZ; + + DynamicCmdsOut.SetPixelShaderConstant( PSREG_FLASHLIGHT_POSITION_RIM_BOOST, pos, 1 ); // steps on rim boost + DynamicCmdsOut.SetPixelShaderConstant( PSREG_FLASHLIGHT_TO_WORLD_TEXTURE, worldToTexture.Base(), 4 ); + + // Tweaks associated with a given flashlight + tweaks[0] = ShadowFilterFromState( state ); + tweaks[1] = ShadowAttenFromState( state ); + pShader->HashShadow2DJitter( state.m_flShadowJitterSeed, &tweaks[2], &tweaks[3] ); + DynamicCmdsOut.SetPixelShaderConstant( PSREG_ENVMAP_TINT__SHADOW_TWEAKS, tweaks, 1 ); + + // Dimensions of screen, used for screen-space noise map sampling + float vScreenScale[4] = {1280.0f / 32.0f, 720.0f / 32.0f, 0, 0}; + int nWidth, nHeight; + pShaderAPI->GetBackBufferDimensions( nWidth, nHeight ); + + int nTexWidth, nTexHeight; + pShaderAPI->GetStandardTextureDimensions( &nTexWidth, &nTexHeight, TEXTURE_SHADOW_NOISE_2D ); + + vScreenScale[0] = (float) nWidth / nTexWidth; + vScreenScale[1] = (float) nHeight / nTexHeight; + + DynamicCmdsOut.SetPixelShaderConstant( PSREG_FLASHLIGHT_SCREEN_SCALE, vScreenScale, 1 ); + } + DynamicCmdsOut.End(); + + // end dynamic block + pShaderAPI->ExecuteCommandBuffer( DynamicCmdsOut.Base() ); + + // Set Vertex Shader Combos + DECLARE_DYNAMIC_VERTEX_SHADER( flesh_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( flesh_vs30 ); + + // Set Pixel Shader Combos + if( /*g_pHardwareConfig->SupportsPixelShaders_2_b()*/ true ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( flesh_ps30 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER( flesh_ps30 ); + } + else + { + Assert( !"No ps_3_0" ); + } + } + pShader->Draw(); +} diff --git a/materialsystem/stdshaders/flesh_helper.h b/materialsystem/stdshaders/flesh_helper.h new file mode 100644 index 00000000..71f33d12 --- /dev/null +++ b/materialsystem/stdshaders/flesh_helper.h @@ -0,0 +1,148 @@ +//========= Copyright © 1996-2009, Valve Corporation, All rights reserved. ============// + +#ifndef FLESH_HELPER_H +#define FLESH_HELPER_H +#ifdef _WIN32 +#pragma once +#endif + +#include + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + +//----------------------------------------------------------------------------- +// Struct to hold shader param indices +//----------------------------------------------------------------------------- +struct FleshVars_t +{ + FleshVars_t() + { + memset( this, 0xFF, sizeof( FleshVars_t ) ); + } + + int m_nBumpStrength; + int m_nFresnelBumpStrength; + int m_nNormalMap; + int m_nBaseTexture; + int m_nBaseTextureTransform; + int m_nDetailTexture; + int m_nColorWarpTexture; + int m_nFresnelColorWarpTexture; + int m_nEffectMasksTexture; + int m_nIridescentWarpTexture; + int m_nOpacityTexture; + int m_nTransMatMasksTexture; + int m_nUVScale; + int m_nDetailScale; + int m_nDetailFrame; + int m_nDetailBlendMode; + int m_nDetailBlendFactor; + int m_nDetailTextureTransform; + + int m_nInteriorEnable; + int m_nInteriorFogStrength; + int m_nInteriorBackgroundBoost; + int m_nInteriorAmbientScale; + int m_nInteriorBackLightScale; + int m_nInteriorColor; + int m_nInteriorRefractStrength; + int m_nInteriorRefractBlur; + + int m_nFresnelParams; + int m_nDiffuseSoftNormal; + int m_nDiffuseExponent; + int m_nSpecExp; + int m_nSpecScale; + int m_nSpecFresnel; + int m_nSpecExp2; + int m_nSpecScale2; + int m_nSpecFresnel2; + int m_nPhong2Softness; + int m_nRimLightExp; + int m_nRimLightScale; + int m_nPhongColorTint; + int m_nSelfIllumTint; + int m_nUVProjOffset; + int m_nBBMin; + int m_nBBMax; + int m_nFlashlightTexture; + int m_nFlashlightTextureFrame; + int m_nBumpFrame; + int m_nGlowScale; + int m_nBackScatter; + int m_nForwardScatter; + int m_nAmbientBoost; + int m_nAmbientBoostMaskMode; + int m_nIridescenceExponent; + int m_nIridescenceBoost; + int m_nHueShiftIntensity; + int m_nHueShiftFresnelExponent; + int m_nSSDepth; + int m_nSSTintByAlbedo; + int m_nSSBentNormalIntensity; + int m_nSSColorTint; + int m_nNormal2Softness; +}; + +// default shader param values +static const float kDefaultBumpStrength = 1.0f; +static const float kDefaultFresnelBumpStrength = 1.0f; +static const float kDefaultUVScale = 1.0f; +static const float kDefaultDetailScale = 4.0f; +static const int kDefaultDetailFrame = 0; +static const int kDefaultDetailBlendMode = 0; +static const float kDefaultDetailBlendFactor = 1.0f; + +static const int kDefaultInteriorEnable = 0; +static const float kDefaultInteriorFogStrength = 0.06f; +static const float kDefaultInteriorBackgroundBoost = 0.0f; +static const float kDefaultInteriorAmbientScale = 0.3f; +static const float kDefaultInteriorBackLightScale = 0.3f; +static const float kDefaultInteriorColor[3] = { 0.5f, 0.5f, 0.5f }; +static const float kDefaultInteriorRefractStrength = 0.015f; +static const float kDefaultInteriorRefractBlur = 0.2f; + +static const float kDefaultFresnelParams[3] = { 0.0f, 0.5f, 2.0f }; +static const float kDefaultPhongColorTint[3] = { 1.0f, 1.0f, 1.0f }; +static const float kDefaultDiffuseSoftNormal = 0.0f; +static const float kDefaultDiffuseExponent = 1.0f; +static const float kDefaultSpecExp = 1.0f; +static const float kDefaultSpecScale = 1.0f; +static const float kDefaultSpecFresnel[3] = { 0.0f, 0.5f, 1.0f }; +static const float kDefaultSpecFresnel2[3] = { 1.0f, 1.0f, 1.0f }; +static const float kDefaultPhong2Softness = 1.0f; +static const float kDefaultRimLightExp = 10.0f; +static const float kDefaultRimLightScale = 1.0f; +static const float kDefaultSelfIllumTint[3] = { 0.0f, 0.0f, 0.0f }; +static const float kDefaultUVProjOffset[3] = { 0.0f, 0.0f, 0.0f }; +static const float kDefaultBB[3] = { 0.0f, 0.0f, 0.0f }; + +static const int kDefaultBumpFrame = 0; +static const float kDefaultGlowScale = 1.0f; +static const float kDefaultBackScatter = 0.0f; +static const float kDefaultForwardScatter = 0.0f; +static const float kDefaultAmbientBoost = 0.0f; +static const int kDefaultAmbientBoostMaskMode = 0; +static const float kDefaultIridescenceExponent = 2.0f; +static const float kDefaultIridescenceBoost = 1.0f; +static const float kDefaultHueShiftIntensity = 0.5f; +static const float kDefaultHueShiftFresnelExponent = 2.0f; +static const float kDefaultSSDepth = 0.1f; +static const float kDefaultSSTintByAlbedo = 0.0f; +static const float kDefaultSSBentNormalIntensity = 0.1f; +static const float kDefaultSSColorTint[3] = { 0.2f, 0.05f, 0.0f }; +static const float kDefaultNormal2Softness = 0.0f; + +void InitParamsFlesh( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, FleshVars_t &info ); +void InitFlesh( CBaseVSShader *pShader, IMaterialVar** params, FleshVars_t &info ); +void DrawFlesh( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, FleshVars_t &info, VertexCompressionType_t vertexCompression, + CBasePerMaterialContextData **pContextDataPtr ); + +#endif // FLESH_HELPER_H diff --git a/materialsystem/stdshaders/flesh_interior_blended_pass_helper.cpp b/materialsystem/stdshaders/flesh_interior_blended_pass_helper.cpp new file mode 100644 index 00000000..4cb07c66 --- /dev/null +++ b/materialsystem/stdshaders/flesh_interior_blended_pass_helper.cpp @@ -0,0 +1,354 @@ +//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============// + +/* Example how to plug this into an existing shader: + + In the VMT: + // Flesh Interior Pass + "$FleshInteriorEnabled" "1" // Enables effect + "$FleshInteriorTexture" "models/Alyx/alyx_flesh_color" // Mask in alpha + "$FleshNormalTexture" "models/Alyx/alyx_flesh_normal" + "$FleshBorderTexture1D" "models/Alyx/alyx_flesh_border" + "$FleshInteriorNoiseTexture" "Engine/noise-blur-256x256" + "$FleshSubsurfaceTexture" "models/Alyx/alyx_flesh_subsurface" + "$FleshBorderNoiseScale" "1.5" // Flesh Noise UV scalar for border + "$FleshBorderWidth" "0.3" // Width of flesh border + "$FleshBorderSoftness" "0.42" // Border softness must be greater than 0.0 and up tp 0.5 + "$FleshBorderTint" "[1 1 1]" // Tint / brighten the border 1D texture + "$FleshGlossBrightness" "0.66" // Change the brightness of the glossy layer + "$FleshDebugForceFleshOn" "0" // DEBUG: This will force on full flesh for testing + "$FleshScrollSpeed" "1.0" + "Proxies" + { + "FleshInterior" + { + } + } + + #include "flesh_interior_blended_pass_helper.h" + + In BEGIN_SHADER_PARAMS: + // Flesh Interior Pass + SHADER_PARAM( FLESHINTERIORENABLED, SHADER_PARAM_TYPE_BOOL, "0", "Enable Flesh interior blend pass" ) + SHADER_PARAM( FLESHINTERIORTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh color texture" ) + SHADER_PARAM( FLESHINTERIORNOISETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh noise texture" ) + SHADER_PARAM( FLESHBORDERTEXTURE1D, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh border 1D texture" ) + SHADER_PARAM( FLESHNORMALTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh normal texture" ) + SHADER_PARAM( FLESHSUBSURFACETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh subsurface texture" ) + SHADER_PARAM( FLESHCUBETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh cubemap texture" ) + SHADER_PARAM( FLESHBORDERNOISESCALE, SHADER_PARAM_TYPE_FLOAT, "1.5", "Flesh Noise UV scalar for border" ) + SHADER_PARAM( FLESHDEBUGFORCEFLESHON, SHADER_PARAM_TYPE_BOOL, "0", "Flesh Debug full flesh" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS1, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS2, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS3, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS4, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHSUBSURFACETINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Subsurface Color" ) + SHADER_PARAM( FLESHBORDERWIDTH, SHADER_PARAM_TYPE_FLOAT, "0.3", "Flesh border" ) + SHADER_PARAM( FLESHBORDERSOFTNESS, SHADER_PARAM_TYPE_FLOAT, "0.42", "Flesh border softness (> 0.0 && <= 0.5)" ) + SHADER_PARAM( FLESHBORDERTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Flesh border Color" ) + SHADER_PARAM( FLESHGLOBALOPACITY, SHADER_PARAM_TYPE_FLOAT, "1.0", "Flesh global opacity" ) + SHADER_PARAM( FLESHGLOSSBRIGHTNESS, SHADER_PARAM_TYPE_FLOAT, "0.66", "Flesh gloss brightness" ) + SHADER_PARAM( FLESHSCROLLSPEED, SHADER_PARAM_TYPE_FLOAT, "1.0", "Flesh scroll speed" ) + + Add this above SHADER_INIT_PARAMS() + // Flesh Interior Pass + void SetupVarsFleshInteriorBlendedPass( FleshInteriorBlendedPassVars_t &info ) + { + info.m_nFleshTexture = FLESHINTERIORTEXTURE; + info.m_nFleshNoiseTexture = FLESHINTERIORNOISETEXTURE; + info.m_nFleshBorderTexture1D = FLESHBORDERTEXTURE1D; + info.m_nFleshNormalTexture = FLESHNORMALTEXTURE; + info.m_nFleshSubsurfaceTexture = FLESHSUBSURFACETEXTURE; + info.m_nFleshCubeTexture = FLESHCUBETEXTURE; + + info.m_nflBorderNoiseScale = FLESHBORDERNOISESCALE; + info.m_nflDebugForceFleshOn = FLESHDEBUGFORCEFLESHON; + info.m_nvEffectCenterRadius1 = FLESHEFFECTCENTERRADIUS1; + info.m_nvEffectCenterRadius2 = FLESHEFFECTCENTERRADIUS2; + info.m_nvEffectCenterRadius3 = FLESHEFFECTCENTERRADIUS3; + info.m_nvEffectCenterRadius4 = FLESHEFFECTCENTERRADIUS4; + + info.m_ncSubsurfaceTint = FLESHSUBSURFACETINT; + info.m_nflBorderWidth = FLESHBORDERWIDTH; + info.m_nflBorderSoftness = FLESHBORDERSOFTNESS; + info.m_ncBorderTint = FLESHBORDERTINT; + info.m_nflGlobalOpacity = FLESHGLOBALOPACITY; + info.m_nflGlossBrightness = FLESHGLOSSBRIGHTNESS; + info.m_nflScrollSpeed = FLESHSCROLLSPEED; + } + + In SHADER_INIT_PARAMS() + // Flesh Interior Pass + if ( !params[FLESHINTERIORENABLED]->IsDefined() ) + { + params[FLESHINTERIORENABLED]->SetIntValue( 0 ); + } + else if ( params[FLESHINTERIORENABLED]->GetIntValue() ) + { + FleshInteriorBlendedPassVars_t info; + SetupVarsFleshInteriorBlendedPass( info ); + InitParamsFleshInteriorBlendedPass( this, params, pMaterialName, info ); + } + + In SHADER_INIT + // Flesh Interior Pass + if ( params[FLESHINTERIORENABLED]->GetIntValue() ) + { + FleshInteriorBlendedPassVars_t info; + SetupVarsFleshInteriorBlendedPass( info ); + InitFleshInteriorBlendedPass( this, params, info ); + } + + At the very end of SHADER_DRAW + // Flesh Interior Pass + if ( params[FLESHINTERIORENABLED]->GetIntValue() ) + { + // If ( snapshotting ) or ( we need to draw this frame ) + if ( ( pShaderShadow != NULL ) || ( true ) ) + { + FleshInteriorBlendedPassVars_t info; + SetupVarsFleshInteriorBlendedPass( info ); + DrawFleshInteriorBlendedPass( this, params, pShaderAPI, pShaderShadow, info ); + } + else // We're not snapshotting and we don't need to draw this frame + { + // Skip this pass! + Draw( false ); + } + } + +==================================================================================================== */ + +#include "BaseVSShader.h" +#include "mathlib/VMatrix.h" +#include "convar.h" +#include "flesh_interior_blended_pass_helper.h" + +// Auto generated inc files +#include "flesh_interior_blended_pass_vs20.inc" +#include "flesh_interior_blended_pass_ps20.inc" +#include "flesh_interior_blended_pass_ps20b.inc" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +void InitParamsFleshInteriorBlendedPass( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, FleshInteriorBlendedPassVars_t &info ) +{ + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + + SET_PARAM_STRING_IF_NOT_DEFINED( info.m_nFleshCubeTexture, "env_cubemap" ); // Default to in-game env map + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nflBorderNoiseScale, kDefaultBorderNoiseScale ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nflDebugForceFleshOn, kDefaultDebugForceFleshOn ); + SET_PARAM_VEC_IF_NOT_DEFINED( info.m_nvEffectCenterRadius1, kDefaultEffectCenterRadius, 4 ); + SET_PARAM_VEC_IF_NOT_DEFINED( info.m_nvEffectCenterRadius2, kDefaultEffectCenterRadius, 4 ); + SET_PARAM_VEC_IF_NOT_DEFINED( info.m_nvEffectCenterRadius3, kDefaultEffectCenterRadius, 4 ); + SET_PARAM_VEC_IF_NOT_DEFINED( info.m_nvEffectCenterRadius4, kDefaultEffectCenterRadius, 4 ); + SET_PARAM_VEC_IF_NOT_DEFINED( info.m_ncSubsurfaceTint, kDefaultSubsurfaceTint, 4 ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nflBorderWidth, kDefaultBorderWidth ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nflBorderSoftness, kDefaultBorderSoftness ); + SET_PARAM_VEC_IF_NOT_DEFINED( info.m_ncBorderTint, kDefaultBorderTint, 4 ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nflGlobalOpacity, kDefaultGlobalOpacity ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nflGlossBrightness, kDefaultGlossBrightness ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nflScrollSpeed, kDefaultScrollSpeed ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nTime, 0.0f ); +} + +void InitFleshInteriorBlendedPass( CBaseVSShader *pShader, IMaterialVar** params, FleshInteriorBlendedPassVars_t &info ) +{ + // Load textures + pShader->LoadTexture( info.m_nFleshTexture ); + pShader->LoadTexture( info.m_nFleshNoiseTexture ); + pShader->LoadTexture( info.m_nFleshBorderTexture1D ); + pShader->LoadTexture( info.m_nFleshNormalTexture ); + pShader->LoadTexture( info.m_nFleshSubsurfaceTexture ); + pShader->LoadCubeMap( info.m_nFleshCubeTexture ); +} + +void DrawFleshInteriorBlendedPass( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, FleshInteriorBlendedPassVars_t &info, VertexCompressionType_t vertexCompression ) +{ + SHADOW_STATE + { + // Reset shadow state manually since we're drawing from two materials + pShader->SetInitialShadowState(); + + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + // Vertex Shader + DECLARE_STATIC_VERTEX_SHADER( flesh_interior_blended_pass_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT, IS_FLAG_SET( MATERIAL_VAR_HALFLAMBERT ) ); + SET_STATIC_VERTEX_SHADER( flesh_interior_blended_pass_vs20 ); + + // Pixel Shader + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( flesh_interior_blended_pass_ps20b ); + SET_STATIC_PIXEL_SHADER( flesh_interior_blended_pass_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( flesh_interior_blended_pass_ps20 ); + SET_STATIC_PIXEL_SHADER( flesh_interior_blended_pass_ps20 ); + } + + // Textures + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, false ); // Noise texture not sRGB + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER3, false ); // Normal texture not sRGB + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER4, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER5, true ); + pShaderShadow->EnableSRGBWrite( true ); + + // Blending + pShader->EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + pShaderShadow->EnableAlphaTest( true ); + pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GREATER, 0.0f ); + + // Per-instance state + pShader->PI_BeginCommandBuffer(); + pShader->PI_SetVertexShaderAmbientLightCube(); + pShader->PI_EndCommandBuffer(); + } + DYNAMIC_STATE + { + // Reset render state manually since we're drawing from two materials + pShaderAPI->SetDefaultState(); + + // Set Vertex Shader Combos + LightState_t lightState = { 0, false, false }; + pShaderAPI->GetDX9LightState( &lightState ); + DECLARE_DYNAMIC_VERTEX_SHADER( flesh_interior_blended_pass_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DYNAMIC_LIGHT, lightState.HasDynamicLight() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( STATIC_LIGHT, lightState.m_bStaticLight ? 1 : 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( flesh_interior_blended_pass_vs20 ); + + // Time % 1000 + float flCurrentTime = IS_PARAM_DEFINED( info.m_nTime ) && params[info.m_nTime]->GetFloatValue() > 0.0f ? params[info.m_nTime]->GetFloatValue() : pShaderAPI->CurrentTime(); + flCurrentTime *= IS_PARAM_DEFINED( info.m_nflScrollSpeed ) ? params[info.m_nflScrollSpeed]->GetFloatValue() : kDefaultScrollSpeed; // This is a dirty hack, but it works well enough + + float vVsConst0[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vVsConst0[0] = flCurrentTime; + vVsConst0[0] -= (float)( (int)( vVsConst0[0] / 1000.0f ) ) * 1000.0f; + + // Noise UV scroll + vVsConst0[1] = flCurrentTime / 100.0f; + vVsConst0[1] -= (float)( (int)( vVsConst0[1] ) ); + + // Border noise scale + vVsConst0[2] = IS_PARAM_DEFINED( info.m_nflBorderNoiseScale ) ? params[info.m_nflBorderNoiseScale]->GetFloatValue() : kDefaultBorderNoiseScale; + + // Debug force flesh on + vVsConst0[3] = IS_PARAM_DEFINED( info.m_nflDebugForceFleshOn ) ? params[info.m_nflDebugForceFleshOn]->GetFloatValue() : kDefaultDebugForceFleshOn; + + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, vVsConst0, 1 ); + + // Flesh effect centers and radii + float vVsConst1[4] = { kDefaultEffectCenterRadius[0], kDefaultEffectCenterRadius[1], kDefaultEffectCenterRadius[2], kDefaultEffectCenterRadius[3] }; + if ( IS_PARAM_DEFINED( info.m_nvEffectCenterRadius1 ) ) + { + params[info.m_nvEffectCenterRadius1]->GetVecValue( vVsConst1, 4 ); + if ( vVsConst1[3] < 0.001f ) + vVsConst1[3] = 0.001f; + vVsConst1[3] = 1.0f / vVsConst1[3]; // Pass 1.0/radius so we do a mul instead of a divide in the shader + } + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, vVsConst1, 1 ); + + float vVsConst2[4] = { kDefaultEffectCenterRadius[0], kDefaultEffectCenterRadius[1], kDefaultEffectCenterRadius[2], kDefaultEffectCenterRadius[3] }; + if ( IS_PARAM_DEFINED( info.m_nvEffectCenterRadius2 ) ) + { + params[info.m_nvEffectCenterRadius2]->GetVecValue( vVsConst2, 4 ); + if ( vVsConst2[3] < 0.001f ) + vVsConst2[3] = 0.001f; + vVsConst2[3] = 1.0f / vVsConst2[3]; // Pass 1.0/radius so we do a mul instead of a divide in the shader + } + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, vVsConst2, 2 ); + + float vVsConst3[4] = { kDefaultEffectCenterRadius[0], kDefaultEffectCenterRadius[1], kDefaultEffectCenterRadius[2], kDefaultEffectCenterRadius[3] }; + if ( IS_PARAM_DEFINED( info.m_nvEffectCenterRadius3 ) ) + { + params[info.m_nvEffectCenterRadius3]->GetVecValue( vVsConst3, 4 ); + if ( vVsConst3[3] < 0.001f ) + vVsConst3[3] = 0.001f; + vVsConst3[3] = 1.0f / vVsConst3[3]; // Pass 1.0/radius so we do a mul instead of a divide in the shader + } + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, vVsConst3, 3 ); + + float vVsConst4[4] = { kDefaultEffectCenterRadius[0], kDefaultEffectCenterRadius[4], kDefaultEffectCenterRadius[2], kDefaultEffectCenterRadius[3] }; + if ( IS_PARAM_DEFINED( info.m_nvEffectCenterRadius4 ) ) + { + params[info.m_nvEffectCenterRadius4]->GetVecValue( vVsConst4, 4 ); + if ( vVsConst4[3] < 0.001f ) + vVsConst4[3] = 0.001f; + vVsConst4[3] = 1.0f / vVsConst4[3]; // Pass 1.0/radius so we do a mul instead of a divide in the shader + } + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, vVsConst4, 4 ); + + // Set Pixel Shader Combos + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( flesh_interior_blended_pass_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( flesh_interior_blended_pass_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( flesh_interior_blended_pass_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( flesh_interior_blended_pass_ps20 ); + } + + // Bind textures + pShader->BindTexture( SHADER_SAMPLER0, info.m_nFleshTexture ); + pShader->BindTexture( SHADER_SAMPLER1, info.m_nFleshNoiseTexture ); + pShader->BindTexture( SHADER_SAMPLER2, info.m_nFleshBorderTexture1D ); + pShader->BindTexture( SHADER_SAMPLER3, info.m_nFleshNormalTexture ); + pShader->BindTexture( SHADER_SAMPLER4, info.m_nFleshSubsurfaceTexture ); + pShader->BindTexture( SHADER_SAMPLER5, info.m_nFleshCubeTexture ); + + // Set Pixel Shader Constants + + // Subsurface tint + pShaderAPI->SetPixelShaderConstant( 0, IS_PARAM_DEFINED( info.m_ncSubsurfaceTint ) ? params[info.m_ncSubsurfaceTint]->GetVecValue() : kDefaultSubsurfaceTint, 1 ); + + // Border width + float vPsConst1[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vPsConst1[0] = IS_PARAM_DEFINED( info.m_nflBorderWidth ) ? params[info.m_nflBorderWidth]->GetFloatValue() : kDefaultBorderWidth; + vPsConst1[0] = 1.0f / vPsConst1[0]; // ( 1.0f / g_flBorderWidthFromVmt ) + vPsConst1[1] = vPsConst1[0] - 1.0f; // ( 1.0f / g_flBorderWidthFromVmt ) - 1.0f + pShaderAPI->SetPixelShaderConstant( 1, vPsConst1, 1 ); + + // Border softness + float vPsConst2[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vPsConst2[0] = IS_PARAM_DEFINED( info.m_nflBorderSoftness ) ? params[info.m_nflBorderSoftness]->GetFloatValue() : kDefaultBorderSoftness; + if ( vPsConst2[0] < 0.01f ) + vPsConst2[0] = 0.01f; + else if ( vPsConst2[0] > 0.5f ) + vPsConst2[0] = 0.5f; + pShaderAPI->SetPixelShaderConstant( 2, vPsConst2, 1 ); + + // Border color tint + pShaderAPI->SetPixelShaderConstant( 3, IS_PARAM_DEFINED( info.m_ncBorderTint ) ? params[info.m_ncBorderTint]->GetVecValue() : kDefaultBorderTint, 1 ); + + // Global opacity + float vPsConst4[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vPsConst4[0] = IS_PARAM_DEFINED( info.m_nflGlobalOpacity ) ? params[info.m_nflGlobalOpacity]->GetFloatValue() : kDefaultGlobalOpacity; + pShaderAPI->SetPixelShaderConstant( 4, vPsConst4, 1 ); + + // Gloss brightness + float vPsConst5[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vPsConst5[0] = IS_PARAM_DEFINED( info.m_nflGlossBrightness ) ? params[info.m_nflGlossBrightness]->GetFloatValue() : kDefaultGlossBrightness; + pShaderAPI->SetPixelShaderConstant( 5, vPsConst5, 1 ); + } + pShader->Draw(); +} diff --git a/materialsystem/stdshaders/flesh_interior_blended_pass_helper.h b/materialsystem/stdshaders/flesh_interior_blended_pass_helper.h new file mode 100644 index 00000000..4dda5b90 --- /dev/null +++ b/materialsystem/stdshaders/flesh_interior_blended_pass_helper.h @@ -0,0 +1,68 @@ +//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============// + +#ifndef FLESH_INTERIOR_BLENDED_PASS_HELPER_H +#define FLESH_INTERIOR_BLENDED_PASS_HELPER_H +#ifdef _WIN32 +#pragma once +#endif + +#include + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct FleshInteriorBlendedPassVars_t +{ + FleshInteriorBlendedPassVars_t() { memset( this, 0xFF, sizeof(FleshInteriorBlendedPassVars_t) ); } + + int m_nFleshTexture; + int m_nFleshNoiseTexture; + int m_nFleshBorderTexture1D; + int m_nFleshNormalTexture; + int m_nFleshSubsurfaceTexture; + int m_nFleshCubeTexture; + + int m_nflBorderNoiseScale; + int m_nflDebugForceFleshOn; + int m_nvEffectCenterRadius1; + int m_nvEffectCenterRadius2; + int m_nvEffectCenterRadius3; + int m_nvEffectCenterRadius4; + + int m_ncSubsurfaceTint; + int m_nflBorderWidth; + int m_nflBorderSoftness; // > 0.0f && < 0.5f ! + int m_ncBorderTint; + int m_nflGlobalOpacity; + int m_nflGlossBrightness; + int m_nflScrollSpeed; + + int m_nTime; +}; + +// Default values (Arrays should only be vec[4]) +static const float kDefaultBorderNoiseScale = 1.5f; +static const float kDefaultDebugForceFleshOn = 0.0f; +static const float kDefaultEffectCenterRadius[4] = { 0.0f, 0.0f, 0.0f, 0.0001f }; // Disabled by default +static const float kDefaultSubsurfaceTint[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; // Disabled by default +static const float kDefaultBorderWidth = 0.3f; +static const float kDefaultBorderSoftness = 0.42f; // > 0.0f && < 0.5f ! +static const float kDefaultBorderTint[4] = { 1.0f, 1.0f, 1.0f, 0.0f }; +static const float kDefaultGlobalOpacity = 1.0f; +static const float kDefaultGlossBrightness = 0.66f; +static const float kDefaultScrollSpeed = 1.0f; + +void InitParamsFleshInteriorBlendedPass( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, FleshInteriorBlendedPassVars_t &info ); +void InitFleshInteriorBlendedPass( CBaseVSShader *pShader, IMaterialVar** params, FleshInteriorBlendedPassVars_t &info ); +void DrawFleshInteriorBlendedPass( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, FleshInteriorBlendedPassVars_t &info, VertexCompressionType_t vertexCompression ); + +#endif // FLESH_INTERIOR_BLENDED_PASS_HELPER_H diff --git a/materialsystem/stdshaders/flesh_interior_blended_pass_ps2x.fxc b/materialsystem/stdshaders/flesh_interior_blended_pass_ps2x.fxc new file mode 100644 index 00000000..c14b91e2 --- /dev/null +++ b/materialsystem/stdshaders/flesh_interior_blended_pass_ps2x.fxc @@ -0,0 +1,126 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// Includes ======================================================================================= +#include "common_vertexlitgeneric_dx9.h" + +// Texture Samplers =============================================================================== +sampler g_tBaseSampler : register( s0 ); +sampler g_tNoiseSampler : register( s1 ); +sampler g_tBorder1DSampler : register( s2 ); +sampler g_tNormalSampler : register( s3 ); +sampler g_tSubsurfaceSampler: register( s4 ); +sampler g_tCubeSampler : register( s5 ); + +// Shaders Constants and Globals ================================================================== +const float3 g_cSubsurfaceTint : register( c0 ); +const float2 g_flBorderWidth : register( c1 ); //{ 1.0f / g_flBorderWidthFromVmt, ( 1.0f / g_flBorderWidthFromVmt ) - 1.0f }; +const float g_flBorderSoftness : register( c2 ); +const float3 g_cBorderTint : register( c3 ); +const float g_flGlobalOpacity : register( c4 ); +const float g_flGlossBrightness : register( c5 ); + +// Interpolated values ============================================================================ +struct PS_INPUT +{ + float2 vTexCoord0 : TEXCOORD0; + float2 flDistanceToEffectCenter_flFresnelEffect : TEXCOORD1; + float4 vNoiseTexCoord : TEXCOORD2; + float3 vTangentViewVector : TEXCOORD3; + float3 cVertexLight : TEXCOORD4; + float3x3 mTangentSpaceTranspose : TEXCOORD5; + // second row : TEXCOORD6; + // third row : TEXCOORD7; +}; + +// Main =========================================================================================== +float4 main( PS_INPUT i ) : COLOR +{ + // Color texture + float4 cBaseColor = tex2D( g_tBaseSampler, i.vTexCoord0.xy ); + float flFleshMaskFromTexture = cBaseColor.a; + + // Subsurface colors + float4 cSubsurfaceColor = tex2D( g_tSubsurfaceSampler, i.vTexCoord0.xy ); + cBaseColor.rgb += cBaseColor.rgb * cSubsurfaceColor.rgb * g_cSubsurfaceTint.rgb; + + // Scroll noise textures to ripple border of opening + float flNoise0 = tex2D( g_tNoiseSampler, i.vNoiseTexCoord.xy ).g; // Use green so we can DXT1 if we want + float flNoise1 = tex2D( g_tNoiseSampler, i.vNoiseTexCoord.wz ).g; // Use green so we can DXT1 if we want + float flNoise = ( flNoise0 + flNoise1 ) * 0.5f; + + // Generate 0-1 mask from distance computed in the VS + float flClampedInputMask = 0.0f; + flClampedInputMask = 1.0f - saturate( i.flDistanceToEffectCenter_flFresnelEffect.x ); + flClampedInputMask *= i.flDistanceToEffectCenter_flFresnelEffect.y; + flClampedInputMask *= flFleshMaskFromTexture; + + // Noise mask - Only apply noise around border of sphere + float flBorderMask = saturate( ( 1.0f - flClampedInputMask ) * g_flBorderWidth.x - g_flBorderWidth.y ); + float flNoiseMask = 1.0f - abs( ( flBorderMask * 2.0f ) - 1.0f ); + + // This is used to lerp in the 1D border texture over the flesh color + float flBorderMaskWithNoise = ( 1.0f - smoothstep( flNoiseMask - g_flBorderSoftness, flNoiseMask + g_flBorderSoftness, flNoise.r ) ) * flNoiseMask; + + // Border color + float vBorderUv = ( sign( flBorderMask - 0.5 ) * (1.0f - pow( flBorderMaskWithNoise, 4.0f )) * 0.5f ) + 0.5f; + float4 cBorderColor = 2.0f * tex2D( g_tBorder1DSampler, vBorderUv ); + cBorderColor.rgb *= g_cBorderTint; + cBorderColor.rgb *= flNoise; + + // Normal map + float4 vNormalMapValue = tex2D( g_tNormalSampler, i.vTexCoord0.xy ); + float3 vTangentNormal = ( vNormalMapValue.xyz * 2.0f ) - 1.0f; + vTangentNormal.xy += ( flNoise * 1.5f ) - 0.75f; // NOTE: This will denormalize the normal. + //float3 vWorldNormal = mul( i.mTangentSpaceTranspose, vTangentNormal.xyz ); + + // Specular gloss layer + float3 vTangentReflectionVector = reflect( i.vTangentViewVector.xyz, vTangentNormal.xyz ); + //vTangentReflectionVector.xy += ( flNoise * 1.5f ) - 0.75f; + float3 vWorldReflectionVector = mul( i.mTangentSpaceTranspose, vTangentReflectionVector.xyz ); + float3 cGlossLayer = ENV_MAP_SCALE * texCUBE( g_tCubeSampler, vWorldReflectionVector.xyz ).rgb; + cGlossLayer.rgb *= g_flGlossBrightness; + + // Gloss mask is just hard-coded fresnel for now + float flGlossMask = pow( saturate( dot( vTangentNormal.xyz, -i.vTangentViewVector.xyz ) ), 8.0f ); + + // Opacity + float flOpacity = 1.0f; + flOpacity = max( flBorderMaskWithNoise, step( flBorderMask, 0.5f ) ); + + // Apply global opacity + flOpacity *= g_flGlobalOpacity; + + //===============// + // Combine terms // + //===============// + float4 result; + result.rgb = cBaseColor.rgb * i.cVertexLight.rgb; + result.rgb += cGlossLayer.rgb * flGlossMask; + result.rgb *= pow( 1.0f - flBorderMaskWithNoise, 2.0f ); // Darken near border + result.rgb = lerp( result.rgb, cBorderColor.rgb, saturate( vBorderUv * 2.0f ) ); // bring in transition 1D texture + + //result.rgb = flClampedInputMask; + //result.rgb = flBorderMask; + //result.rgb = saturate( flClampedInputMask * 2.0f ); + //result.rgb = i.flDistanceToEffectCenter_flFresnelEffect.x;// * i.flDistanceToEffectCenter_flFresnelEffect.y; + //result.rgb = i.flDistanceToEffectCenter_flFresnelEffect.y * g_flBorderWidth.x - g_flBorderWidth.y; + //result.rgb = flNoiseMask; + //result.rgb = flBorderMaskWithNoise; + //result.rgb = flOpacity; + //result.rgb = flBorderUv; + //result.rgb = cBorderColor; + //result.rgb = -i.vTangentViewVector.z; + //result.rgb = vNormalMapValue.xyz; + //result.rgb = vTangentNormal.xyz; + //result.rgb = flGlossLayer; + //result.rgb = i.cVertexLight.rgb; + //result.rgb = texCUBE( g_tCubeSampler, vTangentNormal.xyz ).rgb; + //result.rgb = i.vTangentViewVector.x; + //result.rgb = cGlossLayer.rgb; + + // Set alpha for blending + result.a = flOpacity; + //result.a = 1.0f; + + return FinalOutput( result, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_LINEAR ); +} diff --git a/materialsystem/stdshaders/flesh_interior_blended_pass_vs20.fxc b/materialsystem/stdshaders/flesh_interior_blended_pass_vs20.fxc new file mode 100644 index 00000000..2c0b1c91 --- /dev/null +++ b/materialsystem/stdshaders/flesh_interior_blended_pass_vs20.fxc @@ -0,0 +1,145 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "HALFLAMBERT" "0..1" + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "SKINNING" "0..1" +#include "common_fog_vs_fxc.h" +// DYNAMIC: "DYNAMIC_LIGHT" "0..1" +// DYNAMIC: "STATIC_LIGHT" "0..1" + +// Includes +#include "common_vs_fxc.h" + +// Globals +static const int g_iFogType = DOWATERFOG; +static const bool g_bHalfLambert = HALFLAMBERT ? true : false; +static const bool g_bSkinning = SKINNING ? true : false; + +const float4 g_vConst0 : register( SHADER_SPECIFIC_CONST_0 ); +#define g_flTime g_vConst0.x +#define g_flNoiseUvScroll g_vConst0.y +#define g_flBorderNoiseScale g_vConst0.z +#define g_flDebugForceFleshOn g_vConst0.w + +const float4 g_vEffectCenterOoRadius1 : register( SHADER_SPECIFIC_CONST_1 ); //= { -295.0f, -5.0f, 40.0f, 1.0f/20.0f }; +const float4 g_vEffectCenterOoRadius2 : register( SHADER_SPECIFIC_CONST_2 ); //= { -295.0f, 15.0f, 40.0f, 1.0f/10.0f }; +const float4 g_vEffectCenterOoRadius3 : register( SHADER_SPECIFIC_CONST_3 ); //= { -295.0f, 35.0f, 40.0f, 1.0f/10.0f }; +const float4 g_vEffectCenterOoRadius4 : register( SHADER_SPECIFIC_CONST_4 ); //= { -295.0f, 55.0f, 40.0f, 1.0f/10.0f }; + +// Structs +struct VS_INPUT +{ + float4 vPos : POSITION; // Position + float4 vNormal : NORMAL; // Normal + float4 vBoneWeights : BLENDWEIGHT; // Skin weights + float4 vBoneIndices : BLENDINDICES; // Skin indices + float4 vTexCoord0 : TEXCOORD0; // Base texture coordinates + float3 vPosFlex : POSITION1; // Delta positions for flexing + float4 vTangent : TANGENT; +}; + +struct VS_OUTPUT +{ + float4 vProjPosition : POSITION; // Projection-space position + float2 vTexCoord0 : TEXCOORD0; + float2 flDistanceToEffectCenter_flFresnelEffect : TEXCOORD1; + float4 vNoiseTexCoord : TEXCOORD2; + float3 vTangentViewVector : TEXCOORD3; + float3 cVertexLight : TEXCOORD4; + float3x3 mTangentSpaceTranspose : TEXCOORD5; + // second row : TEXCOORD6; + // third row : TEXCOORD7; + +}; + +// Main +VS_OUTPUT main( const VS_INPUT i ) +{ + VS_OUTPUT o; + + // Flexes coming in from a separate stream (contribution masked by cFlexScale.x) + float4 vObjPosition = i.vPos; + vObjPosition.xyz += i.vPosFlex.xyz * cFlexScale.x; + + float3 vObjNormal; + float4 vObjTangent; + DecompressVertex_NormalTangent( i.vNormal, i.vTangent, vObjNormal, vObjTangent ); + + // Transform the position + float3 vWorldPosition = { 0.0f, 0.0f, 0.0f }; + float3 vWorldNormal = { 0.0f, 0.0f, 0.0f }; + float3 vWorldTangent = { 0.0f, 0.0f, 0.0f }; + float3 vWorldBinormal = { 0.0f, 0.0f, 0.0f }; + SkinPositionNormalAndTangentSpace( g_bSkinning, vObjPosition, vObjNormal, vObjTangent, i.vBoneWeights, i.vBoneIndices, vWorldPosition, vWorldNormal, vWorldTangent, vWorldBinormal ); + + // Transform into projection space + float4 vProjPosition = mul( float4( vWorldPosition, 1.0f ), cViewProj ); + o.vProjPosition = vProjPosition; + + // Pass through tex coords + o.vTexCoord0.xy = i.vTexCoord0.xy; + + // Store the closest effect intensity + o.flDistanceToEffectCenter_flFresnelEffect.x = 9999.0f; // A very large distance + o.flDistanceToEffectCenter_flFresnelEffect.x = min( o.flDistanceToEffectCenter_flFresnelEffect.x, length( vWorldPosition.xyz - g_vEffectCenterOoRadius1.xyz ) * g_vEffectCenterOoRadius1.w ); + o.flDistanceToEffectCenter_flFresnelEffect.x = min( o.flDistanceToEffectCenter_flFresnelEffect.x, length( vWorldPosition.xyz - g_vEffectCenterOoRadius2.xyz ) * g_vEffectCenterOoRadius2.w ); + o.flDistanceToEffectCenter_flFresnelEffect.x = min( o.flDistanceToEffectCenter_flFresnelEffect.x, length( vWorldPosition.xyz - g_vEffectCenterOoRadius3.xyz ) * g_vEffectCenterOoRadius3.w ); + o.flDistanceToEffectCenter_flFresnelEffect.x = min( o.flDistanceToEffectCenter_flFresnelEffect.x, length( vWorldPosition.xyz - g_vEffectCenterOoRadius4.xyz ) * g_vEffectCenterOoRadius4.w ); + + /* + // Test values for development in Alyx_interior map + o.flDistanceToEffectCenter_flFresnelEffect.x = 9999.0f; // A very large distance + float3 vTestPosition = { -295.0f, -5.0f, 40.0f }; + float flMinY = -5.0f; + float flMaxY = 66.0f; + vTestPosition.y = lerp( flMinY, flMaxY, ( abs( frac( g_flTime / 20.0f ) * 2.0 - 1.0 ) ) ); + //vTestPosition.y = lerp( flMinY, flMaxY, 0.65f ); + + //1.0f - saturate( i.flDistanceToEffectCenter_flFresnelEffect.x * 4.0f - 3.0f ) + + //o.flDistanceToEffectCenter_flFresnelEffect.x = 9999.0f; // A very large distance + + const float g_flInteriorRadius = 20.0f; + if ( g_flInteriorRadius ) + { + o.flDistanceToEffectCenter_flFresnelEffect.x = min( o.flDistanceToEffectCenter_flFresnelEffect.x, length( vWorldPosition.xyz - vTestPosition.xyz ) / g_flInteriorRadius ); + } + + const float g_flInteriorRadius2 = 14.0f; + if ( g_flInteriorRadius2 ) + { + vTestPosition.y = lerp( flMinY, flMaxY, 0.65f ); + //vTestPosition.z = lerp( 37, 45, ( abs( frac( g_flTime / 4.0f ) * 2.0 - 1.0 ) ) ); + o.flDistanceToEffectCenter_flFresnelEffect.x = min( o.flDistanceToEffectCenter_flFresnelEffect.x, length( vWorldPosition.xyz - vTestPosition.xyz ) / g_flInteriorRadius2 ); + } + //*/ + + if ( g_flDebugForceFleshOn ) + { + o.flDistanceToEffectCenter_flFresnelEffect.x = 0.0f; + } + + // Fresnel mask + float3 vWorldViewVector = normalize( vWorldPosition.xyz - cEyePos.xyz ); + o.flDistanceToEffectCenter_flFresnelEffect.y = pow( saturate( dot( -vWorldViewVector.xyz, vWorldNormal.xyz ) ), 1.5f ); + + // Noise UV + o.vNoiseTexCoord.xy = o.vTexCoord0.xy * g_flBorderNoiseScale + g_flNoiseUvScroll; + o.vNoiseTexCoord.zw = o.vTexCoord0.xy * g_flBorderNoiseScale - g_flNoiseUvScroll; // Will fetch as wz to avoid matching layers + + // Tangent view vector + o.vTangentViewVector.xyz = Vec3WorldToTangentNormalized( vWorldViewVector.xyz, vWorldNormal.xyz, vWorldTangent.xyz, vWorldBinormal.xyz ); + + // Compute vertex lighting + bool bDynamicLight = DYNAMIC_LIGHT ? true : false; + bool bStaticLight = STATIC_LIGHT ? true : false; + o.cVertexLight.rgb = DoLighting( vWorldPosition, vWorldNormal, float3(0.0f, 0.0f, 0.0f), bStaticLight, bDynamicLight, g_bHalfLambert ); + + // Tangent space transform + o.mTangentSpaceTranspose[0] = float3( vWorldTangent.x, vWorldBinormal.x, vWorldNormal.x ); + o.mTangentSpaceTranspose[1] = float3( vWorldTangent.y, vWorldBinormal.y, vWorldNormal.y ); + o.mTangentSpaceTranspose[2] = float3( vWorldTangent.z, vWorldBinormal.z, vWorldNormal.z ); + + return o; +} diff --git a/materialsystem/stdshaders/flesh_ps30.fxc b/materialsystem/stdshaders/flesh_ps30.fxc new file mode 100644 index 00000000..7eeb1d6e --- /dev/null +++ b/materialsystem/stdshaders/flesh_ps30.fxc @@ -0,0 +1,742 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#include "common_fog_ps_fxc.h" +// STATIC: "ALPHABLEND" "0..1" +// STATIC: "TRANSMAT" "0..1" +// STATIC: "FRESNEL_WARP" "0..1" +// STATIC: "EFFECTS" "0..1" +// STATIC: "TINTING" "0..1" +// STATIC: "IRIDESCENCE" "0..1" +// STATIC: "BACK_SCATTER" "0..1" +// STATIC: "FORWARD_SCATTER" "0..1" +// STATIC: "HIGH_PRECISION_DEPTH" "0..1" +// STATIC: "INTERIOR_LAYER" "0..1" +// STATIC: "OPACITY_TEXTURE" "0..1" +// STATIC: "NORMAL2SOFT" "0..1" +// STATIC: "DETAIL" "0..1" +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps20b] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps30] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..0" [ps20b] [XBOX] +// DYNAMIC: "NUM_LIGHTS" "0..4" [ps20b] +// DYNAMIC: "NUM_LIGHTS" "0..4" [ps30] +// DYNAMIC: "FLASHLIGHT" "0..1" +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" + +#include "common_ps_fxc.h" +#include "common_vertexlitgeneric_dx9.h" +#include "common_flashlight_fxc.h" +#include "shader_constant_register_map.h" + +// SAMPLERS +sampler g_tBase : register( s0 ); +sampler g_tBump : register( s1 ); +sampler g_tScreen : register( s2 ); +sampler g_tTransMatMasks : register( s3 ); // Effect masks for material changes: fresnel hue-shift, jellyfish, forward scatter and back scatter +sampler g_tColorWarp : register( s4 ); // Color warp 3D texture +sampler g_tFresnelColorWarp : register( s5 ); // Fresnel color warp 3D texture +sampler g_tOpacity : register( s6 ); +sampler g_tShadowDepth : register( s7 ); // Flashlight shadow depth map sampler +sampler g_tNormalizeRandRot : register( s8 ); // Normalization / RandomRotation samplers +sampler g_tFlashlightCookie : register( s9 ); // Flashlight cookie +sampler g_tEffectMasks : register( s10 ); // Special effect masks for self-illum, color warping, iridescence and clearcoat +sampler g_tIridescentWarp : register( s11 ); // 2D gradient for iridescent color +sampler g_tDetail : register( s12 ); // Detail texture + +// SHADER CONSTANTS + +#define flOverBright 2.0f //overbright lights consistent with vertexlitgeneric + +const float4 g_vMisc : register( c0 ); +#define g_flBumpStrength g_vMisc.x +#define g_flDepthScale g_vMisc.y +#define g_flInnerFogStrength g_vMisc.z +#define g_flRefractStrength g_vMisc.w + +const float4 g_vTranslucentFresnelParams_InteriorBoost : register( c1 ); +#define g_vTranslucentFresnelParams g_vTranslucentFresnelParams_InteriorBoost.xyz +#define g_flInteriorBoost g_vTranslucentFresnelParams_InteriorBoost.w + +const float4 g_vMisc2 : register( c3 ); +#define g_flRimLightExp g_vMisc2.x +#define g_flRimLightScale g_vMisc2.y +#define g_flSpecScale g_vMisc2.z +#define g_flSpecExp2 g_vMisc2.w + +const float4 g_vMisc3 : register( c10 ); +#define g_flSpecScale2 g_vMisc3.x +#define g_flFresnelBumpStrength g_vMisc3.y +#define g_flDiffuseSoftNormal g_vMisc3.z +#define g_flInteriorAmbientScale g_vMisc3.w + +const float4 g_vEyePos : register( PSREG_EYEPOS_SPEC_EXPONENT ); +#define g_vEyePos g_vEyePos.xyz +//#define UNUSED g_vEyePos.w + +const float4 g_vPhongFresnel_ShaderControls : register( c12 ); +#define g_vPhongFresnel g_vPhongFresnel_ShaderControls.xyz +#define g_fWriteDepthToAlpha g_vPhongFresnel_ShaderControls.w + +const float4 g_vPhongTint_InteriorBackLightScale : register( c19 ); +#define g_cPhongTint g_vPhongTint_InteriorBackLightScale.rgb +#define g_flInteriorBackLightScale g_vPhongTint_InteriorBackLightScale.w + +// TODO: pass in FOV so that we can account for it properly +#define g_flHalfWindowWidth 1 /* tan(fov/2) */ + +const float4 g_vFresnelFx : register( c26 ); +#define g_flIridBoost g_vFresnelFx.x +#define g_flIridExp g_vFresnelFx.y +#define g_flFresnelWarpScale g_vFresnelFx.z +#define g_flFresnelWarpExp g_vFresnelFx.w + +const float4 g_vSelfIllumTint_DiffuseBias : register( c27 ); +#define g_cSelfIllumTint g_vSelfIllumTint_DiffuseBias.rgb +#define g_flDiffuseBias g_vSelfIllumTint_DiffuseBias.w + +const float4 g_vInteriorColor_RefractBlur : register( c32 ); +#define g_cInteriorColor g_vInteriorColor_RefractBlur.rgb +#define g_flRefractBlur g_vInteriorColor_RefractBlur.w + +const float3 cAmbientCube[6] : register( PSREG_AMBIENT_CUBE ); + +const PixelShaderLightInfo g_sLightInfo[3] : register( PSREG_LIGHT_INFO_ARRAY ); // 2 registers each - 6 registers total + +const float4 g_vFlashlightAttenuationFactors_FarZ : register( PSREG_FLASHLIGHT_ATTENUATION ); +#define g_vFlashlightAttenuationFactors g_vFlashlightAttenuationFactors_FarZ.xyz +#define g_flFlashlightFarZ g_vFlashlightAttenuationFactors_FarZ.w + +const float4 g_vFlashlightPos : register( PSREG_FLASHLIGHT_POSITION_RIM_BOOST ); + +const float4x4 g_mFlashlightWorldToTexture : register( PSREG_FLASHLIGHT_TO_WORLD_TEXTURE ); + +const float4 g_vShadowTweaks : register( PSREG_ENVMAP_TINT__SHADOW_TWEAKS ); + +const float3x3 g_mView : register( c33 ); + +const float4 g_FogParams : register( c36 ); + +const float4 g_vPhongFresnel2_Phong2Softness : register( c42 ); +#define g_vPhongFresnel2 g_vPhongFresnel2_Phong2Softness.xyz +#define g_vPhong2Softness g_vPhongFresnel2_Phong2Softness.w + +const float4 g_vFleshLightingParams : register( c43 ); +#define g_flDiffuseExponent g_vFleshLightingParams.x +#define g_flNormal2Softness g_vFleshLightingParams.y +#define g_flAmbientBoost g_vFleshLightingParams.z +#define g_flMaskMode g_vFleshLightingParams.w + +const float4 g_vFleshSSParams : register( c44 ); +#define g_flForwardScatter g_vFleshSSParams.x +#define g_flBackScatter g_vFleshSSParams.y +#define g_flSSDepth g_vFleshSSParams.z +#define g_flBentNormalScale g_vFleshSSParams.w + +const float4 g_vFleshSSColor_TintByAlbedo : register( c45 ); +#define g_cSSColor g_vFleshSSColor_TintByAlbedo.xyz +#define g_flSSTintByAlbedo g_vFleshSSColor_TintByAlbedo.w + +const float4 g_vDetailBlendInfo_SpecExp : register( c46 ); +#define g_flDetailMode g_vDetailBlendInfo_SpecExp.x +#define g_flDetailBlendAmt g_vDetailBlendInfo_SpecExp.y +//#define UNUSED g_vDetailBlendInfo_SpecExp.z +#define g_flSpecExp g_vDetailBlendInfo_SpecExp.w + +// For now, use vertex UVs rather than position-derived UVs +#define USE_AUTHORED_UVS 1 + +// COMBO-DERIVED CONSTANTS +static const bool bAlphaBlend = ALPHABLEND ? true : false; +static const bool bFlashLight = FLASHLIGHT ? true : false; +static const bool bInterior = INTERIOR_LAYER ? true : false; +static const bool bOpacityTexture = OPACITY_TEXTURE ? true : false; + +// INPUT STRUCT +struct PS_INPUT +{ + float4 vWorldNormal : TEXCOORD0; // w is proj. z coord (for depth stuff) + float4 vVertexColor : TEXCOORD1; + float4 vWorldPos : TEXCOORD2; // w is proj. w coord + float4 vUV0 : TEXCOORD3; + float2 vUV1 : TEXCOORD4; + float4 vLightAtten : TEXCOORD5; + float3 vLightCube : TEXCOORD6; + float3 vWorldTangent : TEXCOORD7; + float3 vWorldBinormal : TEXCOORD8; +}; + + +//============================================================================================================================================================== +float Luminance( const float3 colour ) +{ + return dot( colour, float3( 0.3, 0.59, 0.11 ) ); +} + +//============================================================================================================================================================== +float3 BumpedToWorldNormal( float3 vBumpedNormal, float3 vWorldNormal, float3 vWorldTangent, float3 vWorldBinormal ) +{ + float3x3 mTanToWorld; + mTanToWorld[2] = vWorldNormal; + mTanToWorld[0] = vWorldTangent; + mTanToWorld[1] = vWorldBinormal; + return normalize( mul( vBumpedNormal, mTanToWorld ) ); +} + +void ApplyDetail( float4 cDetail, float flMode, float flAmt, inout float3 cBase, inout float flSelfIllum, inout float3 flSelfIllumColor ) +{ + if ( flMode == 1 ) + { + cBase.rgb *= lerp( 1.0f, cDetail.rgb * 2.0f, flAmt ); + cBase.rgb = saturate( cBase.rgb ); + return; + } + if ( flMode == 2 ) + { + cBase.rgb += lerp( 0.0f, cDetail.rgb * flAmt, saturate( flAmt ) ); + cBase.rgb = saturate( cBase.rgb ); + return; + } + if ( flMode == 3 ) + { + cBase.rgb = lerp( cBase.rgb, cDetail.rgb, saturate( flAmt * cDetail.a ) ); + return; + } + if( flMode == 4 ) + { + cBase.rgb = lerp( cBase.rgb, cDetail.rgb, saturate( flAmt ) ); + return; + } + if( flMode == 5 ) + { + cBase.rgb += lerp( 0.0f, cDetail.rgb * ( 1.0 + flAmt ), saturate( flAmt ) ); + float flAddSelfIllum = saturate( Luminance( cBase.rgb ) - 1.0f ); + flSelfIllum += flAddSelfIllum; + flSelfIllumColor.rgb = lerp( flSelfIllumColor.rgb, cBase.rgb, flAddSelfIllum ); + cBase.rgb = saturate( cBase.rgb ); + return; + } + if( flMode == 6 ) + { + cBase.rgb *= ( 1.0f, cDetail.rgb, flAmt ); + return; + } +} + + +//============================================================================================================================================================== +void ComputeOpacityAndFresnel( float2 vUV0, float3 vEyeDir, float3 vWorldNormal, + // Function outputs: + out float flSkinOpacity, inout float flFresnel ) +{ + flSkinOpacity = 1; + if ( ( bOpacityTexture ) && ( bInterior || bAlphaBlend ) ) + { + flSkinOpacity = tex2D( g_tOpacity, vUV0.xy ); + } + + float fTranslucentFresnel; + fTranslucentFresnel = lerp( g_vTranslucentFresnelParams.x, g_vTranslucentFresnelParams.y, pow( flFresnel, g_vTranslucentFresnelParams.z ) ); + + #if ( INTERIOR_LAYER ) + { + flSkinOpacity = flSkinOpacity*fTranslucentFresnel; + } + #endif +} + +//============================================================================================================================================================== +float3 BlobAmbientLight( float3 vVertexAmbient, float3 vEyeDir, float3 vWorldNormal, float flFresnel ) +{ + // Ambient lighting now comes from VS + float3 cAmbient = vVertexAmbient; + + // TODO: Replace lambert diffuse with pixelshader-ambient term of full lighting env. + //float3 cAmbient = PixelShaderAmbientLight( vBumpedWorldNormal, cAmbientCube ); + + //float3 cAmbientSheen = PixelShaderAmbientLight( reflect( -vEyeDir, vBumpedWorldNormal ), cAmbientCube ); + //cAmbient = lerp( cAmbient, cAmbientSheen, flFresnel ); + + return cAmbient; +} + +//============================================================================================================================================================== +float BlobPhongFresnel( float flFresnel, float3 vPhongFresnelParams ) +{ + float flFresnelTerm = lerp( vPhongFresnelParams.y, vPhongFresnelParams.x, saturate( flFresnel ) ); + flFresnelTerm = lerp( flFresnelTerm, vPhongFresnelParams.z, saturate( -flFresnel ) ); + return flFresnelTerm; +} + +//============================================================================================================================================================== +void BlobLight( float3 vWorldPos, float3 vEyeDir, float3 vBumpedWorldNormal, float3 vBumpedWorldNormal2, + float flCurvature, float flForwardSSMask, float flBackSSMask, float3 cLightColor, float3 cLightColorScattered, + float3 vLightDirection, float flIridMask, + // Outputs: + inout float3 cDiffuse, inout float3 cSpec, inout float3 cSpec2, inout float3 cShadowTerminator, inout float3 cRim, inout float3 cIrid ) +{ + float NdotL = dot( vBumpedWorldNormal, vLightDirection ); + float NdotLSoft = NdotL; + float flInvNdotLSoft = 0.0f; + float HNdotL = NdotL * 0.5f + 0.5f; + float HNdotLSoft = NdotL; + #if( NORMAL2SOFT ) + { + NdotLSoft = dot( vBumpedWorldNormal2, vLightDirection ); + } + #endif + #if FORWARD_SCATTER || BACK_SCATTER + { + flInvNdotLSoft = saturate( 1.0f - NdotLSoft ); + } + #endif + NdotL = saturate( NdotL ); + + float SSNdotL = 0.0f; + float flInvSSCurvature = 1.0f; + #if FORWARD_SCATTER || BACK_SCATTER + { + flInvSSCurvature = 1.0f / ( flCurvature * g_flSSDepth ); + float flLocalizedBentNormalScale = g_flBentNormalScale * ( flCurvature ); // less view-dependance on highly curved areas + float3 vSSNormal = lerp( vBumpedWorldNormal2.rgb, vEyeDir.rgb, flLocalizedBentNormalScale ); // partially view-dependent normal for ss lighting calc + vSSNormal = normalize( vSSNormal ); + SSNdotL = 1.0f - abs( dot( vSSNormal, vLightDirection ) ); + SSNdotL = pow( SSNdotL, flInvSSCurvature ); + float cSSMask = 1.0f; + } + #endif + + #if( NORMAL2SOFT ) + { + HNdotLSoft = NdotLSoft * 0.5f + 0.5f; + NdotLSoft = saturate( NdotLSoft ); + } + #else + { + NdotLSoft = NdotL; + } + #endif + + float3 vHalf = normalize( vEyeDir.xyz + vLightDirection.xyz ); + float NdotH = saturate( dot( vHalf.xyz, vBumpedWorldNormal.xyz ) ); + float NdotHSoft = NdotH; + + float VdotN = dot( vEyeDir, vBumpedWorldNormal ); + VdotN = saturate( VdotN ); + + float flSSMask = 0.0f; + #if( FORWARD_SCATTER ) + { + flSSMask += flInvNdotLSoft * SSNdotL * flForwardSSMask * cLightColorScattered.rgb; // back half of terminator + } + #endif + #if( BACK_SCATTER ) + { + flSSMask += SSNdotL * NdotLSoft * flBackSSMask * cLightColor.rgb; + } + #endif + + #if FORWARD_SCATTER || BACK_SCATTER + { + cShadowTerminator.rgb += flSSMask; + } + #endif + + #if( NORMAL2SOFT ) + { + float3 vHalfSoft = normalize( vEyeDir.xyz + vLightDirection.xyz ); + NdotHSoft = saturate( dot( vHalfSoft.xyz, vBumpedWorldNormal2.xyz ) ); + } + #endif + + //dual spec + float flFresnel = saturate( VdotN ) * 2.0f - 1.0f; + cSpec += pow( NdotH, g_flSpecExp ) * NdotL * cLightColor * BlobPhongFresnel( flFresnel, g_vPhongFresnel ); + float flSpec2Soft = lerp( NdotH, NdotHSoft, g_vPhong2Softness ); + float flSpec2Limit = lerp( NdotL, NdotLSoft, g_vPhong2Softness ); + cSpec2 += pow( flSpec2Soft, g_flSpecExp2 ) * flSpec2Limit * cLightColor * BlobPhongFresnel( flFresnel, g_vPhongFresnel2 ); + + #if( IRIDESCENCE ) + { + float flIridCoord = dot( vHalf, vLightDirection ) * flIridMask; + cIrid = tex2Dlod( g_tIridescentWarp, float4( flIridCoord, 0.5f, 0.0f, 0.0f ) ).rgb; + cIrid *= smoothstep( 0.1, 0.2, flIridMask ); // one channel describes thin film variation and masking, with values below 0.1 meaning "off" + cIrid *= pow( VdotN, g_flIridExp ) * g_flIridBoost; + cIrid *= cLightColor; + cIrid *= HNdotL; + } + #endif + + //diffuse + //float flDiffuseLevel = lerp( NdotL, NdotLSoft, g_flDiffuseSoftNormal ); + float flDiffuseLevel = lerp( HNdotL, HNdotLSoft, g_flDiffuseSoftNormal ); + flDiffuseLevel -= g_flDiffuseBias; + flDiffuseLevel = saturate( flDiffuseLevel ); + flDiffuseLevel = pow( flDiffuseLevel, g_flDiffuseExponent ); + cDiffuse.rgb += flDiffuseLevel * cLightColor.rgb; + + //rim + float flRim = saturate( 1.0f - VdotN ); + flRim = pow( flRim, g_flRimLightExp ); + flRim *= NdotL; + cRim += flRim * cLightColor.rgb; +} + +//============================================================================================================================================================== +float4 BlobBlurFlashlight( sampler tFlashlightCookie, float2 flProjUv ) +{ + // TODO: get framebuffer res from constants + float2 vScreenRes = float2( 1600, 1200 ); + float2 g_vInvScreenRes = 1.0 / vScreenRes; + + static const float2 vPoissonOffset[8] = { float2( 0.3475f, 0.0042f ), float2( 0.8806f, 0.3430f ), + float2( -0.0041f, -0.6197f ), float2( 0.0472f, 0.4964f ), + float2( -0.3730f, 0.0874f ), float2( -0.9217f, -0.3177f ), + float2( -0.6289f, 0.7388f ), float2( 0.5744f, -0.7741f ) }; + + float4 cOut = 0; + float blurFactor = g_flSSDepth * 50; + for( int i = 0; i < 8; i++ ) + { + cOut += 1.0/8.0 * tex2D( tFlashlightCookie, flProjUv + blurFactor * g_vInvScreenRes.xy * vPoissonOffset[i] ); + } + return cOut; +} + +//============================================================================================================================================================== +float4 SampleBackgroundBlurred( float2 vBumpedTSNormal, float3 vWorldNormal, float2 vScreenPos, float flBlurDepth ) +{ + static const float2 vPoissonOffset[8] = { float2( 0.3475f, 0.0042f ), float2( 0.8806f, 0.3430f ), + float2( -0.0041f, -0.6197f ), float2( 0.0472f, 0.4964f ), + float2( -0.3730f, 0.0874f ), float2( -0.9217f, -0.3177f ), + float2( -0.6289f, 0.7388f ), float2( 0.5744f, -0.7741f ) }; + // TODO: get framebuffer res from constants + float2 vScreenRes = float2( 1600, 1200 ); + float2 g_vInvScreenRes = 1.0 / vScreenRes; + + // Project world-space blur radius into screen space. + float flBlurRadius = g_flRefractBlur * flBlurDepth * ( vScreenRes.x / g_flHalfWindowWidth ); + + // Bumped refract + float flRefractStrength = g_flRefractStrength * flBlurDepth / g_flHalfWindowWidth; + float2 vBackgroundUV = flRefractStrength * vBumpedTSNormal + vScreenPos.xy; + + float4 cOut = 0; + for( int i = 0; i < 8; i++ ) + { + cOut += 1.0/8.0 * tex2D( g_tScreen, vBackgroundUV + flBlurRadius * g_vInvScreenRes.xy * vPoissonOffset[i] ); + } + return cOut; +} + +//============================================================================================================================================================== +float3 CubeAverage( void ) +{ + // TODO: Pass this average light color in as a const + float3 cAvgLight = 0.0; + for( int j = 0; j < 6; j++ ) + { + cAvgLight += cAmbientCube[j] / 6.0; + } + return cAvgLight; +} + +//============================================================================================================================================================== +float3 BlobInterior( float3 vWorldNormal, float2 vBumpedTSNormal, float3 vEyeDir, + float2 vScreenPos, float flPixelDepth, float flCamDist ) +{ + float3 cInterior = float3( 0.0f, 0.0f, 0.0f ); + + // Sample the background (and inner blob brain/tentacles) + // Boost bright background pixels + float4 cBackground = tex2D( g_tScreen, vScreenPos.xy ); + float flLuminance = Luminance( cBackground.rgb ); + cBackground.rgb *= 1.0 + g_flInteriorBoost * flLuminance * flLuminance; + + // Fake refract-like vector without any total internal reflection crappiness + float3 vRefract = normalize( -( vEyeDir + vWorldNormal ) ); + + // Interior lighting through ambient cube + float3 cAvgLight = CubeAverage(); + float3 cBackLight = g_flInteriorAmbientScale * cAvgLight.rgb; + cBackLight *= g_cInteriorColor.rgb; + + //float flFogAtten = BlobInteriorFog( cBackground.a, flPixelDepth ); + + float flFogAtten = 1.0f - saturate( flLuminance ); + float VdotN = dot( vEyeDir, vWorldNormal ); + flFogAtten *= VdotN; + cBackground = SampleBackgroundBlurred( vBumpedTSNormal, vWorldNormal, vScreenPos, flFogAtten ); + flLuminance = Luminance( cBackground ); + + flFogAtten = 1.0f - saturate( flLuminance ); + flFogAtten *= ( VdotN + g_flInnerFogStrength ); + flFogAtten = saturate( flFogAtten ); + + cInterior = lerp( cBackground, cBackLight, flFogAtten ); + + return cInterior; +} + +//============================================================================================================================================================== +float4 main( PS_INPUT i ) : COLOR +{ + float4 cOut = { 0, 0, 0, 1 }; + + // Set up misc camera variables + float flPixelDepth = i.vWorldNormal.w; + float2 vScreenPos = i.vUV0.wz / i.vWorldPos.w; + float3 vEyeDir = g_vEyePos.xyz - i.vWorldPos.xyz; + float flCamDist = length( vEyeDir ); + vEyeDir /= flCamDist; + float3 vWorldNormal = normalize( i.vWorldNormal.xyz ); + float3 vWorldTangent = normalize( i.vWorldTangent.xyz ); + float3 vWorldBinormal = normalize( i.vWorldBinormal.xyz ); + + // Base (albedo) map + float4 vBase = tex2D( g_tBase, i.vUV0.xy ); + float3 cBase = vBase.rgb; + float flSpecMask = vBase.a; + + // Normal mapping + float4 vNormal = tex2D( g_tBump, i.vUV0.xy ); + float3 vBumpedTangentNormal = normalize( ( vNormal.xyz * 2.0f - 1.0f ) * float3( g_flBumpStrength, g_flBumpStrength, 1.0f ) ); + float3 vBumpedWorldNormal = BumpedToWorldNormal( vBumpedTangentNormal, vWorldNormal, vWorldTangent, vWorldBinormal ); + float flCurvature = 1.0f - vNormal.a + 0.01; // invert mask (makes more sense visually when white is high curvature) and + // make sure it is never zero (else divide by zero errors later) + + // Initialize masks for fx + float flSelfIllum = 0; + float3 cSelfIllum = g_cSelfIllumTint; + float flTinting = 1; + float flIridMask = vBase.a; + float flSpec2Mask = 1; + float4 vEffectMasks = tex2D( g_tEffectMasks, i.vUV0.xy ); + #if( EFFECTS ) + { + flSelfIllum = vEffectMasks.r; + flTinting = vEffectMasks.g; + flIridMask = vEffectMasks.b; + flSpec2Mask = vEffectMasks.a; + } + #endif + + // Initialize masks and color for subsurface effects + float flFresnelWarpMask = 1.0f; + float flSkinOpacityMask = 1.0f; + float flForwardSSMask = g_flForwardScatter; + float flBackSSMask = g_flBackScatter; + float flInteriorFogMask = 0.0f; + float3 cSSColor = lerp( 1.0f, cBase.rgb, g_flSSTintByAlbedo ) * g_cSSColor.rgb; + #if ( TRANSMAT ) + { + float4 vTransmatMasks = tex2D( g_tTransMatMasks, i.vUV0.xy ); + flForwardSSMask = vTransmatMasks.r * g_flForwardScatter; + flInteriorFogMask = vTransmatMasks.r; + flSkinOpacityMask = vTransmatMasks.g; + flFresnelWarpMask = vTransmatMasks.b; + flBackSSMask = vTransmatMasks.a * g_flBackScatter; + } + #endif + + // Apply detail texture + #if( DETAIL ) + { + float4 cDetail = tex2D( g_tDetail, i.vUV1.xy ); + ApplyDetail( cDetail, g_flDetailMode, g_flDetailBlendAmt, cBase, flSelfIllum, cSelfIllum ); + } + #endif + + // Ambient boost factor + float flAmbientBoost = g_flAmbientBoost; + if ( g_flMaskMode == 1 ) + { + flAmbientBoost *= flTinting; + } + if ( g_flMaskMode == 2 ) + { + flAmbientBoost *= flSkinOpacityMask; + } + if ( g_flMaskMode == 3 ) + { + flAmbientBoost *= flIridMask; + } + if ( g_flMaskMode == 4 ) + { + flAmbientBoost *= flSpec2Mask; + } + if ( g_flMaskMode == 5 ) + { + flAmbientBoost *= flFresnelWarpMask; + } + flAmbientBoost += 1.0f; // boost, not scale! + + // Soft normals + float3 vBumpedTangentNormal2 = vBumpedTangentNormal; + float3 vBumpedWorldNormal2 = vBumpedWorldNormal; + #if( NORMAL2SOFT ) + { + float4 vNormal2 = tex2Dbias( g_tBump, float4( i.vUV0.xy, 0, g_flNormal2Softness ) ); + vBumpedTangentNormal2 = normalize( ( vNormal2.xyz * 2.0f - 1.0f ) * float3( g_flBumpStrength, g_flBumpStrength, 1.0f ) ); + vBumpedWorldNormal2 = BumpedToWorldNormal( vBumpedTangentNormal2, vWorldNormal, vWorldTangent, vWorldBinormal ); + } + #endif + + float flSkinOpacity = 1.0f; + // Opacity and fresnel + float flFresnel = saturate( 1.0 - dot( vEyeDir.xyz, vWorldNormal.xyz ) ); + float flEdgeFresnel = flFresnel; + ComputeOpacityAndFresnel( i.vUV0.xy, vEyeDir, vBumpedWorldNormal, + flSkinOpacity, flFresnel ); + flSkinOpacity *= ( 1.0f - flSkinOpacityMask ); + + // Initialize lighting params + float3 cInterior = float3( 0.0f, 0.0f, 0.0f ); + float3 cAmbient = float3( 0.0f, 0.0f, 0.0f ); + float3 cDiffuse = float3( 0.0f, 0.0f, 0.0f ); + float3 cSpec = float3( 0.0f, 0.0f, 0.0f ); + float3 cSpec2 = float3( 0.0f, 0.0f, 0.0f ); + float3 cShadowTerminator = float3( 0.0f, 0.0f, 0.0f ); + float3 cRim = float3( 0.0f, 0.0f, 0.0f ); + float3 cIrid = float3( 0.0f, 0.0f, 0.0f ); + + if ( FLASHLIGHT ) + { + float4 vFlashlightSpacePosition = mul( float4( i.vWorldPos.xyz, 1.0f ), g_mFlashlightWorldToTexture ); // TODO: Move to vertex shader + float3 vProjCoords = vFlashlightSpacePosition.xyz / vFlashlightSpacePosition.w; + + float3 cFlashlightColor = tex2D( g_tFlashlightCookie, vProjCoords.xyz ) * flOverBright; + float3 cFlashlightColorBlurred = float3( 1.0f, 1.0f, 1.0f ) * flOverBright; + + float3 delta = g_vFlashlightPos.xyz - i.vWorldPos.xyz; + float3 vLightDirection = normalize( delta ); + float flDistSquared = dot( delta, delta ); + float flDist = sqrt( flDistSquared ); + + float endFalloffFactor = RemapValClamped( flDist, g_flFlashlightFarZ, 0.6f * g_flFlashlightFarZ, 0.0f, 1.0f ); + + // Attenuation for light and to fade out shadow over distance + float fAtten = saturate( dot( g_vFlashlightAttenuationFactors.xyz, float3( 1.0f, 1.0f/flDist, 1.0f/flDistSquared ) ) ); + cFlashlightColor *= fAtten; + + #if FORWARD_SCATTER || INTERIOR_LAYER + { + cFlashlightColorBlurred = BlobBlurFlashlight( g_tFlashlightCookie, vProjCoords.xy ); + cFlashlightColorBlurred * fAtten; + flForwardSSMask *= fAtten; // forward scatter color will attenuate faster by thickness + } + #endif + + if ( FLASHLIGHTSHADOWS ) + { + float flShadow = DoFlashlightShadow( g_tShadowDepth, g_tNormalizeRandRot, vProjCoords, vScreenPos, FLASHLIGHTDEPTHFILTERMODE, g_vShadowTweaks, true, true ); + float flAttenuated = lerp( flShadow, 1.0f, g_vShadowTweaks.y ); // Blend between fully attenuated and not attenuated + flShadow = saturate( lerp( flAttenuated, flShadow, fAtten ) ); // Blend between shadow and above, according to light attenuation + cFlashlightColor *= flShadow; // Shadow term + #if FORWARD_SCATTER || BACK_SCATTER + { + float3 flScatterPos = vProjCoords; + flScatterPos.z -= flForwardSSMask * ( g_flSSDepth / 100 ); + float flScatterShadow = DoFlashlightShadow( g_tShadowDepth, g_tNormalizeRandRot, flScatterPos, vScreenPos, FLASHLIGHTDEPTHFILTERMODE, g_vShadowTweaks, true, true ); + cFlashlightColorBlurred *= flScatterShadow; + } + #else + { + cFlashlightColorBlurred *= flShadow; + } + #endif + } + + BlobLight( i.vWorldPos.xyz, vEyeDir.xyz, vBumpedWorldNormal.xyz, vBumpedWorldNormal2.xyz, + flCurvature, flForwardSSMask, flBackSSMask, cFlashlightColor.rgb, cFlashlightColorBlurred.rgb, + vLightDirection.xyz, flIridMask, + cDiffuse, cSpec, cSpec2, cShadowTerminator, cRim, cIrid ); + + #if ( INTERIOR_LAYER ) + { + cInterior = cFlashlightColorBlurred; + cInterior *= flInteriorFogMask; // forward scatter mask without modulation + cInterior *= g_cInteriorColor; + cInterior *= cFlashlightColorBlurred; + cInterior *= g_flInteriorBackLightScale; + } + #endif + + cDiffuse.rgb = lerp( cDiffuse.rgb, float3( 0.0f, 0.0f, 0.0f ), flSelfIllum ); // don't over-brighten self-illuminated areas in flashlight passes + cOut.a = 0.0f; // don't contribute extra opacity info in flashlight passes + } + else + { + + // Ambient light + cAmbient = BlobAmbientLight( i.vLightCube, vEyeDir, vBumpedWorldNormal, flFresnel ); + + // Dynamic lights + for ( int l = 0; l < NUM_LIGHTS; l++ ) + { + float3 cLightColor = PixelShaderGetLightColor( g_sLightInfo, l ).rgb * i.vLightAtten[l] * flOverBright; + float3 vLightDirection = PixelShaderGetLightVector( i.vWorldPos.xyz, g_sLightInfo, l ).xyz; + BlobLight( i.vWorldPos.xyz, vEyeDir.xyz, vBumpedWorldNormal.xyz, vBumpedWorldNormal2.xyz, + flCurvature, flForwardSSMask, flBackSSMask, cLightColor.rgb, cLightColor.rgb, vLightDirection.xyz, + flIridMask, + cDiffuse, cSpec, cSpec2, cShadowTerminator, cRim, cIrid ); + } + + // Blob interior colour (blurred refract buffer, plus fog and glow) + #if ( INTERIOR_LAYER ) + { + cInterior = BlobInterior( vWorldNormal, vBumpedTangentNormal, vEyeDir, + vScreenPos, flPixelDepth, flCamDist ); + } + #endif + + cDiffuse.rgb = lerp( cDiffuse.rgb, cSelfIllum.rgb, flSelfIllum ); + cOut.a = bAlphaBlend ? flSkinOpacity : 1; + } + + float4 hueShiftCoords = float4( 0, 0, 0, 0.0f ); + hueShiftCoords.r = cBase.r; + hueShiftCoords.g = cBase.g; + hueShiftCoords.b = cBase.b; + hueShiftCoords = pow( hueShiftCoords, 0.4545 ); //degamma the rgb for texture lookup + + #if( TINTING ) + { + float3 cTintedBase = ( tex3Dlod( g_tColorWarp, hueShiftCoords.xyzw ) ).rgb; + cBase = lerp( cBase, cTintedBase, flTinting ); + } + #endif + + // Fresnel-based Hue shift + #if( FRESNEL_WARP ) + { + float3 cHueShiftedBase = ( tex3Dlod( g_tFresnelColorWarp, hueShiftCoords.xyzw ) ).rgb; + flFresnelWarpMask *= pow( flEdgeFresnel, g_flFresnelWarpExp ); + flFresnelWarpMask *= g_flFresnelWarpScale; + cBase = lerp( cBase, cHueShiftedBase, flFresnelWarpMask ); + } + #endif + + cSpec.rgb *= g_flSpecScale * g_cPhongTint.rgb; + cSpec2.rgb *= g_flSpecScale2; + cSpec2.rgb *= flSpec2Mask; + cSpec.rgb += cSpec2.rgb; + cIrid.rgb *= ( cAmbient.rgb + cDiffuse.rgb ); + cSpec.rgb *= flSpecMask; + cRim.rgb *= g_flRimLightScale; + cInterior.rgb += cRim.rgb; + cAmbient.rgb *= flAmbientBoost; + cShadowTerminator *= cSSColor; + // Outer diffuse lighting blended over interior/background colours, with spec added on top + float3 cOuterSkin = cBase.rgb * ( cAmbient.rgb + cDiffuse.rgb + cRim.rgb ) + cShadowTerminator.rgb; + #if( INTERIOR_LAYER ) + { + cOut.rgb = lerp( cInterior.rgb, cOuterSkin.rgb, flSkinOpacity ); + } + #else + { + cOut.rgb = cOuterSkin.rgb; + } + #endif + cOut.rgb += cSpec.rgb + cIrid.rgb; + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_vEyePos.xyz, i.vWorldPos.xyz, flPixelDepth ); + return FinalOutput( cOut, fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, g_fWriteDepthToAlpha, flPixelDepth ); +} \ No newline at end of file diff --git a/materialsystem/stdshaders/flesh_vs30.fxc b/materialsystem/stdshaders/flesh_vs30.fxc new file mode 100644 index 00000000..82ad8072 --- /dev/null +++ b/materialsystem/stdshaders/flesh_vs30.fxc @@ -0,0 +1,102 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#include "common_fog_vs_fxc.h" +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "SKINNING" "0..1" + +// Includes +#include "common_vs_fxc.h" + +// Globals +const float g_flUVScale : register( SHADER_SPECIFIC_CONST_0 ); +const float g_flDetailUVScale : register( SHADER_SPECIFIC_CONST_1 ); +const float4 cDetailTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_2 ); // 2 & 3 + +// Structs +struct VS_INPUT +{ + float4 vPos : POSITION; // Position + float4 vNormal : NORMAL; // Normal + float4 vUserData : TANGENT; // Tangent + float4 vBoneWeights : BLENDWEIGHT; // Skin weights + float4 vBoneIndices : BLENDINDICES; // Skin indices + float4 vTexCoord : TEXCOORD0; + float4 vColor : COLOR0; + + // Position and normal/tangent deltas + float4 vPosFlex : POSITION1; + float4 vNormalFlex : NORMAL1; +}; + +struct VS_OUTPUT +{ + float4 vProjPosition : POSITION; // Projection-space position + float4 vWorldNormal : TEXCOORD0; // w is proj. z coord (for depth stuff) + float4 vColor : TEXCOORD1; + float4 vWorldPos : TEXCOORD2; // w is proj. w coord + float4 vUV0 : TEXCOORD3; + float2 vUV1 : TEXCOORD4; + float4 vLightAtten : TEXCOORD5; + float3 vAmbient : TEXCOORD6; + float3 vWorldTangent : TEXCOORD7; + float3 vWorldBinormal : TEXCOORD8; +}; + +// Main +VS_OUTPUT main( const VS_INPUT i ) +{ + VS_OUTPUT o; + + float4 vObjPosition = i.vPos; + float4 vObjTangent; + float3 vObjNormal; + DecompressVertex_NormalTangent( i.vNormal, i.vUserData, vObjNormal, vObjTangent ); + + float flWrinkleWeight; + ApplyMorph( i.vPosFlex, i.vNormalFlex, vObjPosition.xyz, vObjNormal.xyz, vObjTangent.xyz, flWrinkleWeight ); // not keeping wrinkle weight + + // Transform the position and normal + float3 vWorldPosition = { 0.0f, 0.0f, 0.0f }; + float3 vWorldNormal = { 0.0f, 0.0f, 0.0f }; + float3 vWorldTangent = { 0.0f, 0.0f, 0.0f }; + float3 vWorldBinormal = { 0.0f, 0.0f, 0.0f }; + SkinPositionNormalAndTangentSpace( SKINNING ? true : false, + vObjPosition, vObjNormal.xyz, vObjTangent.xyzw, + i.vBoneWeights, i.vBoneIndices, + vWorldPosition, vWorldNormal, vWorldTangent, vWorldBinormal ); + vWorldNormal.xyz = normalize( vWorldNormal.xyz ); + + o.vWorldNormal.xyz = vWorldNormal.xyz; + o.vWorldTangent = normalize( vWorldTangent.xyz ); + o.vWorldBinormal = normalize( vWorldBinormal.xyz ); + o.vWorldPos.xyz = vWorldPosition.xyz; + + // Transform into projection space + float4 vProjPosition = mul( float4( vWorldPosition, 1.0f ), cViewProj ); + o.vProjPosition = vProjPosition; + o.vWorldNormal.w = vProjPosition.z; + o.vWorldPos.w = vProjPosition.w; + o.vUV0.xy = g_flUVScale * i.vTexCoord.xy; + // Detail texture coords: + o.vUV1.xy = i.vTexCoord.xy;//g_flDetailUVScale * i.vTexCoord.xy; + o.vUV1.x = dot( i.vTexCoord, cDetailTexCoordTransform[0] ); + o.vUV1.y = dot( i.vTexCoord, cDetailTexCoordTransform[1] ); + + // Screen-space texcoord + float2 vScreenPos = float2( 0.5, -0.5 ) * vProjPosition.xy + 0.5 * vProjPosition.w; + o.vUV0.wz = vScreenPos; + + // Dynamic light attenuation factors + o.vLightAtten.x = GetVertexAttenForLight( vWorldPosition, 0 ); + o.vLightAtten.y = GetVertexAttenForLight( vWorldPosition, 1 ); + o.vLightAtten.z = GetVertexAttenForLight( vWorldPosition, 2 ); + o.vLightAtten.w = GetVertexAttenForLight( vWorldPosition, 3 ); + + // Ambient light + o.vAmbient = AmbientLight( vWorldNormal ); + + // Vertex colour for self-illumination glow + o.vColor.rgba = i.vColor.rgba * 2.0f; + + return o; +} diff --git a/materialsystem/stdshaders/floatcombine.cpp b/materialsystem/stdshaders/floatcombine.cpp new file mode 100644 index 00000000..9ac9738f --- /dev/null +++ b/materialsystem/stdshaders/floatcombine.cpp @@ -0,0 +1,116 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" + +#include "screenspaceeffect_vs20.inc" +#include "floatcombine_ps20.inc" +#include "floatcombine_ps20b.inc" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +BEGIN_VS_SHADER_FLAGS( floatcombine, "Help for floatcombine", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( BLOOMTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "" ) + SHADER_PARAM( SHARPNESS, SHADER_PARAM_TYPE_FLOAT, "1", "" ) + SHADER_PARAM( WOODCUT, SHADER_PARAM_TYPE_FLOAT, "0", "" ) + SHADER_PARAM( VIGNETTE_MIN_BRIGHT,SHADER_PARAM_TYPE_FLOAT,"1","") + SHADER_PARAM( VIGNETTE_POWER,SHADER_PARAM_TYPE_FLOAT,"4","") + SHADER_PARAM( EDGE_SOFTNESS,SHADER_PARAM_TYPE_FLOAT,"0","") + SHADER_PARAM( BLOOMAMOUNT, SHADER_PARAM_TYPE_FLOAT, "1.0", "" ) + SHADER_PARAM( BLOOMEXPONENT, SHADER_PARAM_TYPE_FLOAT, "2.0", "" ) + SHADER_PARAM( ALPHASHARPENFACTOR, SHADER_PARAM_TYPE_FLOAT, "0.0", "" ) + END_SHADER_PARAMS + + SHADER_INIT + { + if( params[BASETEXTURE]->IsDefined() ) + { + LoadTexture( BASETEXTURE ); + } + if( params[BLOOMTEXTURE]->IsDefined() ) + { + LoadTexture( BLOOMTEXTURE ); + } + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + int fmt = VERTEX_POSITION; + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 ); + + // convert from linear to gamma on write. + pShaderShadow->EnableSRGBWrite( true ); + + // Pre-cache shaders + DECLARE_STATIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + SET_STATIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( floatcombine_ps20b ); + SET_STATIC_PIXEL_SHADER( floatcombine_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( floatcombine_ps20 ); + SET_STATIC_PIXEL_SHADER( floatcombine_ps20 ); + } + } + + DYNAMIC_STATE + { + float c0[4]={params[SHARPNESS]->GetFloatValue(), + params[WOODCUT]->GetFloatValue(), + params[BLOOMAMOUNT]->GetFloatValue(), + params[ALPHASHARPENFACTOR]->GetFloatValue()}; + float c1[4]={params[BLOOMEXPONENT]->GetFloatValue(), + params[VIGNETTE_MIN_BRIGHT]->GetFloatValue(), + params[VIGNETTE_POWER]->GetFloatValue(), + params[EDGE_SOFTNESS]->GetFloatValue()}; + pShaderAPI->SetPixelShaderConstant( 0, c0, 1 ); + pShaderAPI->SetPixelShaderConstant( 1, c1, 1 ); + BindTexture( SHADER_SAMPLER0, BASETEXTURE, -1 ); + BindTexture( SHADER_SAMPLER1, BLOOMTEXTURE, -1 ); + + ITexture *base_texture=params[BASETEXTURE]->GetTextureValue(); + ITexture *bloom_texture=params[BLOOMTEXTURE]->GetTextureValue(); + + float v0[4]={1.0/base_texture->GetActualWidth(),1.0/base_texture->GetActualHeight(), + 1.0/bloom_texture->GetActualWidth(),1.0/bloom_texture->GetActualHeight()}; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, v0, 1 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( floatcombine_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( floatcombine_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( floatcombine_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( floatcombine_ps20 ); + } + } + Draw(); + } +END_SHADER diff --git a/materialsystem/stdshaders/floatcombine_autoexpose.cpp b/materialsystem/stdshaders/floatcombine_autoexpose.cpp new file mode 100644 index 00000000..1df49125 --- /dev/null +++ b/materialsystem/stdshaders/floatcombine_autoexpose.cpp @@ -0,0 +1,121 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" + +#include "screenspaceeffect_vs20.inc" +#include "floatcombine_autoexpose_ps20.inc" +#include "floatcombine_autoexpose_ps20b.inc" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +BEGIN_VS_SHADER( floatcombine_autoexpose, "Help for floatcombine_autoexpose" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( BLOOMTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "" ) + SHADER_PARAM( SHARPNESS, SHADER_PARAM_TYPE_FLOAT, "1", "" ) + SHADER_PARAM( WOODCUT, SHADER_PARAM_TYPE_FLOAT, "0", "" ) + SHADER_PARAM( VIGNETTE_MIN_BRIGHT,SHADER_PARAM_TYPE_FLOAT,"1","") + SHADER_PARAM( VIGNETTE_POWER,SHADER_PARAM_TYPE_FLOAT,"4","") + SHADER_PARAM( EDGE_SOFTNESS,SHADER_PARAM_TYPE_FLOAT,"0","") + SHADER_PARAM( BLOOMAMOUNT, SHADER_PARAM_TYPE_FLOAT, "1.0", "" ) + SHADER_PARAM( BLOOMEXPONENT, SHADER_PARAM_TYPE_FLOAT, "2.0", "" ) + SHADER_PARAM( ALPHASHARPENFACTOR, SHADER_PARAM_TYPE_FLOAT, "0.0", "" ) + SHADER_PARAM( EXPOSURE_TEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "" ) + SHADER_PARAM( AUTOEXPOSE_MIN, SHADER_PARAM_TYPE_FLOAT, ".5", "" ) + SHADER_PARAM( AUTOEXPOSE_MAX, SHADER_PARAM_TYPE_FLOAT, "2", "" ) + END_SHADER_PARAMS + + SHADER_INIT + { + if( params[BASETEXTURE]->IsDefined() ) + { + LoadTexture( BASETEXTURE ); + } + if( params[BLOOMTEXTURE]->IsDefined() ) + { + LoadTexture( BLOOMTEXTURE ); + } + if( params[EXPOSURE_TEXTURE]->IsDefined() ) + { + LoadTexture( EXPOSURE_TEXTURE ); + } + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + int fmt = VERTEX_POSITION; + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 ); + + // convert from linear to gamma on write. + pShaderShadow->EnableSRGBWrite( true ); + + // Pre-cache shaders + DECLARE_STATIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + SET_STATIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( floatcombine_autoexpose_ps20b ); + SET_STATIC_PIXEL_SHADER( floatcombine_autoexpose_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( floatcombine_autoexpose_ps20 ); + SET_STATIC_PIXEL_SHADER( floatcombine_autoexpose_ps20 ); + } + } + + DYNAMIC_STATE + { + float c0[4]={params[SHARPNESS]->GetFloatValue(), + params[WOODCUT]->GetFloatValue(), + params[BLOOMAMOUNT]->GetFloatValue(), + params[ALPHASHARPENFACTOR]->GetFloatValue()}; + float c1[4]={params[BLOOMEXPONENT]->GetFloatValue(), + params[VIGNETTE_MIN_BRIGHT]->GetFloatValue(), + params[VIGNETTE_POWER]->GetFloatValue(), + params[EDGE_SOFTNESS]->GetFloatValue()}; + float c2[4]={params[AUTOEXPOSE_MIN]->GetFloatValue(), + params[AUTOEXPOSE_MAX]->GetFloatValue(), + 0,0}; + pShaderAPI->SetPixelShaderConstant( 0, c0, 1 ); + pShaderAPI->SetPixelShaderConstant( 1, c1, 1 ); + pShaderAPI->SetPixelShaderConstant( 2, c2, 1 ); + BindTexture( SHADER_SAMPLER0, BASETEXTURE, -1 ); + BindTexture( SHADER_SAMPLER1, BLOOMTEXTURE, -1 ); + BindTexture( SHADER_SAMPLER2, EXPOSURE_TEXTURE, -1 ); + DECLARE_DYNAMIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( floatcombine_autoexpose_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( floatcombine_autoexpose_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( floatcombine_autoexpose_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( floatcombine_autoexpose_ps20 ); + } + } + Draw(); + } +END_SHADER diff --git a/materialsystem/stdshaders/floatcombine_autoexpose_ps2x.fxc b/materialsystem/stdshaders/floatcombine_autoexpose_ps2x.fxc new file mode 100644 index 00000000..1d5b0689 --- /dev/null +++ b/materialsystem/stdshaders/floatcombine_autoexpose_ps2x.fxc @@ -0,0 +1,44 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#include "common_ps_fxc.h" + +sampler FBSampler : register( s0 ); +sampler BloomSampler : register( s1 ); +sampler Exposure_Sampler : register( s2 ); + +const HALF4 settings : register( c0 ); + // x=sharpness,y=woodcut,z=bloom_amt,w=alpha sharpen factor +const HALF4 settings2 : register( c1 ); // x=bloom exp,y=vignette min scale z=vignette_power +const HALF4 settings3 : register( c2 ); // x=autoexpose min y=autoexpose_max + +struct PS_INPUT +{ + float2 texCoord : TEXCOORD0; +}; + + +float4 main( PS_INPUT i ) : COLOR +{ + float4 fbSample = tex2D( FBSampler, i.texCoord ); + float4 bloom=tex2D(BloomSampler,i.texCoord); + float4 exposure_data=tex2D(Exposure_Sampler, float2( 0.0f, 0.0f ) ); + float avg_lum=exposure_data.r; + float tmscale=max(0.18/max(avg_lum,0.0001),settings3.x); + tmscale=min(tmscale,settings3.y); + + + float2 xofs=2*(i.texCoord-float2(0.5,0.5)); + float dist=(1.0/2.0)*(xofs.x*xofs.x+xofs.y*xofs.y); + float vig=pow(1-dist,settings2.z); + + fbSample=lerp(fbSample,bloom,(1-vig)*settings2.w); + fbSample=lerp(bloom,fbSample,settings.x+settings.w*fbSample.a*settings2.w); + + bloom.xyz=min(bloom.xyz,1.0); + float lum=.3*bloom.x+.59*bloom.y+.11*bloom.z; + lum=min(1.0,lum); + + float4 c_out=(fbSample)+settings.z*pow(lum,settings2.x)*bloom; + c_out.xyz*=tmscale; + return FinalOutput( c_out, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} diff --git a/materialsystem/stdshaders/floatcombine_ps2x.fxc b/materialsystem/stdshaders/floatcombine_ps2x.fxc new file mode 100644 index 00000000..a93b6de4 --- /dev/null +++ b/materialsystem/stdshaders/floatcombine_ps2x.fxc @@ -0,0 +1,60 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#include "common_ps_fxc.h" + +sampler FBSampler : register( s0 ); +sampler BloomSampler : register( s1 ); + +const HALF4 settings : register( c0 ); + // x=sharpness,y=woodcut,z=bloom_amt,w=alpha sharpen factor +const HALF4 settings2 : register( c1 ); // x=bloom exp,y=vignette min scale z=vignette_power + +struct PS_INPUT +{ + float2 texCoord : TEXCOORD0; + //float2 bloomTexCoord : TEXCOORD2; +}; + + +float4 main( PS_INPUT i ) : COLOR +{ + float4 fbSample = tex2D( FBSampler, i.texCoord ); + return fbSample; // Temporary hack to work around color tint problem in float HDR mode. This disables bloom in this mode. + +/* + float4 bloom=tex2D(BloomSampler,i.bloomTexCoord); + + float2 xofs=2*(i.texCoord-float2(0.5,0.5)); + float dist=(1.0/2.0)*(xofs.x*xofs.x+xofs.y*xofs.y); + float vig=pow(1-dist,settings2.z); + + fbSample=lerp(fbSample,bloom,(1-vig)*settings2.w); + fbSample=lerp(bloom,fbSample,settings.x+settings.w*fbSample.a*settings2.w); + + float3 woodcut; + if (bloom.xIsDefined() ) + { + LoadTexture( FBTEXTURE ); + } + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + int fmt = VERTEX_POSITION; + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 ); + + // convert from linear to gamma on write. + if ( !IsX360() ) // The 360 is using this shader when it shouldn't...this is just a quick hack to keep things looking right on the 360 + { + pShaderShadow->EnableSRGBWrite( true ); + } + + // Pre-cache shaders + DECLARE_STATIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + SET_STATIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + +// DECLARE_STATIC_PIXEL_SHADER( floattoscreen_ps20 ); +// SET_STATIC_PIXEL_SHADER( floattoscreen_ps20 ); + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + const char *szPixelShader = params[PIXSHADER]->GetStringValue(); + size_t iLength = Q_strlen( szPixelShader ); + + if( (iLength > 5) && (Q_stricmp( &szPixelShader[iLength - 5], "_ps20" ) == 0) ) //detect if it's trying to load a ps20 shader + { + //replace it with the ps20b shader + char *szNewName = (char *)stackalloc( sizeof( char ) * (iLength + 2) ); + memcpy( szNewName, szPixelShader, sizeof( char ) * iLength ); + szNewName[iLength] = 'b'; + szNewName[iLength + 1] = '\0'; + pShaderShadow->SetPixelShader( szNewName, 0 ); + } + else + { + pShaderShadow->SetPixelShader( params[PIXSHADER]->GetStringValue(), 0 ); + } + } + else + { + pShaderShadow->SetPixelShader( params[PIXSHADER]->GetStringValue(), 0 ); + } + } + + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, FBTEXTURE, -1 ); + DECLARE_DYNAMIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + +// DECLARE_DYNAMIC_PIXEL_SHADER( floattoscreen_ps20 ); +// SET_DYNAMIC_PIXEL_SHADER( floattoscreen_ps20 ); + pShaderAPI->SetPixelShaderIndex( 0 ); + } + Draw(); + } +END_SHADER diff --git a/materialsystem/stdshaders/floattoscreen_notonemap_ps2x.fxc b/materialsystem/stdshaders/floattoscreen_notonemap_ps2x.fxc new file mode 100644 index 00000000..e1d6a32d --- /dev/null +++ b/materialsystem/stdshaders/floattoscreen_notonemap_ps2x.fxc @@ -0,0 +1,35 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#include "common_ps_fxc.h" + +sampler FBSampler : register( s0 ); + +struct PS_INPUT +{ + float2 texCoord : TEXCOORD0; +}; + +#define MAX_LUM 5 +#define MIN_LUM .1 + +float4 main( PS_INPUT i ) : COLOR +{ + float4 fbSample = tex2D( FBSampler, i.texCoord ); + + float lum=0.33*(fbSample.x+fbSample.y+fbSample.z); + // derive a luminance-based scale factor for tone mapping + float factor=1.0; + if (lumMAX_LUM) + { + } + + + // linear scale for tone mapping +// fbSample *= lum * LINEAR_LIGHT_SCALE; + + // assume that sRGB write is enabled. + return FinalOutput( fbSample, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} diff --git a/materialsystem/stdshaders/floattoscreen_ps2x.fxc b/materialsystem/stdshaders/floattoscreen_ps2x.fxc new file mode 100644 index 00000000..74c04645 --- /dev/null +++ b/materialsystem/stdshaders/floattoscreen_ps2x.fxc @@ -0,0 +1,20 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#include "common_ps_fxc.h" + +sampler FBSampler : register( s0 ); + +struct PS_INPUT +{ + float2 texCoord : TEXCOORD0; +}; + + +float4 main( PS_INPUT i ) : COLOR +{ + float4 fbSample = tex2D( FBSampler, i.texCoord ); + // Temporary hack to work around color tint problem in float HDR mode. + // fbSample *= float4(cLightScale.xyz, 1); + + return FinalOutput( fbSample, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} diff --git a/materialsystem/stdshaders/floattoscreen_vanilla.cpp b/materialsystem/stdshaders/floattoscreen_vanilla.cpp new file mode 100644 index 00000000..f64cc72b --- /dev/null +++ b/materialsystem/stdshaders/floattoscreen_vanilla.cpp @@ -0,0 +1,86 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" + +#include "screenspaceeffect_vs20.inc" +#include "floattoscreen_vanilla_ps20.inc" +#include "floattoscreen_vanilla_ps20b.inc" +#include "floattoscreen_ps20.inc" +#include "floattoscreen_ps20b.inc" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +BEGIN_VS_SHADER_FLAGS( floattoscreen_vanilla, "Help for floattoscreen_vanilla", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( FBTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "" ) + END_SHADER_PARAMS + + SHADER_INIT + { + if( params[FBTEXTURE]->IsDefined() ) + { + LoadTexture( FBTEXTURE ); + } + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + int fmt = VERTEX_POSITION; + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 ); + + // convert from linear to gamma on write. + pShaderShadow->EnableSRGBWrite( true ); + + // Pre-cache shaders + DECLARE_STATIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + SET_STATIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( floattoscreen_ps20b ); + SET_STATIC_PIXEL_SHADER( floattoscreen_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( floattoscreen_ps20 ); + SET_STATIC_PIXEL_SHADER( floattoscreen_ps20 ); + } + } + + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, FBTEXTURE, -1 ); + DECLARE_DYNAMIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( floattoscreen_vanilla_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( floattoscreen_vanilla_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( floattoscreen_vanilla_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( floattoscreen_vanilla_ps20 ); + } + } + Draw(); + } +END_SHADER diff --git a/materialsystem/stdshaders/floattoscreen_vanilla_ps2x.fxc b/materialsystem/stdshaders/floattoscreen_vanilla_ps2x.fxc new file mode 100644 index 00000000..d10235f3 --- /dev/null +++ b/materialsystem/stdshaders/floattoscreen_vanilla_ps2x.fxc @@ -0,0 +1,16 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#include "common_ps_fxc.h" + +sampler FBSampler : register( s0 ); + +struct PS_INPUT +{ + float2 texCoord : TEXCOORD0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float4 fbSample = tex2D( FBSampler, i.texCoord ); + return fbSample; +} diff --git a/materialsystem/stdshaders/fow_ps_fxc.h b/materialsystem/stdshaders/fow_ps_fxc.h new file mode 100644 index 00000000..d857c793 --- /dev/null +++ b/materialsystem/stdshaders/fow_ps_fxc.h @@ -0,0 +1,37 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// +// +// Purpose: This is where all common code for vertex shaders go. +// +// $NoKeywords: $ +// +//===========================================================================// + +#ifndef _FOW_PS_FXC_H +#define _FOW_PS_FXC_H + + +#if ( FOW == 1 ) + + +static const float3 g_FoWToGray = float3( 0.3, 0.59, 0.11 ); + +#define FOW_DARKNESS_VALUE 0.5 +#define FOW_GRAY_FACTOR 0.75 +#define FOW_COLOR_FACTOR 0.25 +#define FOW_GRAY_HILIGHTS 2.0 + +float3 CalcFoW( const sampler FoWSampler, const float2 vFoWCoords, const float3 CurrentColor ) +{ + float vFoWResult = tex2D( FoWSampler, vFoWCoords.xy ).r; + + float3 vGray = pow( dot( CurrentColor, g_FoWToGray ), FOW_GRAY_HILIGHTS ); + float3 vFinalColor = ( vGray * FOW_GRAY_FACTOR * FOW_DARKNESS_VALUE ) + ( CurrentColor * FOW_COLOR_FACTOR * FOW_DARKNESS_VALUE ); + + return ( vFinalColor * ( 1.0 - vFoWResult ) ) + ( CurrentColor * vFoWResult ); +} + + +#endif + + +#endif // _FOW_PS_FXC_H diff --git a/materialsystem/stdshaders/fow_vs_fxc.h b/materialsystem/stdshaders/fow_vs_fxc.h new file mode 100644 index 00000000..422690a4 --- /dev/null +++ b/materialsystem/stdshaders/fow_vs_fxc.h @@ -0,0 +1,25 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// +// +// Purpose: This is where all common code for vertex shaders go. +// +// $NoKeywords: $ +// +//===========================================================================// + +#ifndef _FOW_VS_FXC_H +#define _FOW_VS_FXC_H + + +#if ( FOW == 1 ) + + +float2 CalcFoWCoord( const float4 vFoWWorldSize, const float2 vWorldPos ) +{ + return ( vWorldPos - vFoWWorldSize.xy ) / vFoWWorldSize.zw; +} + + +#endif + + +#endif // _FOW_VS_FXC_H diff --git a/materialsystem/stdshaders/gamecontrols.cpp b/materialsystem/stdshaders/gamecontrols.cpp new file mode 100644 index 00000000..e9df3e70 --- /dev/null +++ b/materialsystem/stdshaders/gamecontrols.cpp @@ -0,0 +1,62 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" +#include "gamecontrols_vs20.inc" +#include "gamecontrols_ps20.inc" + + +BEGIN_VS_SHADER_FLAGS( GAMECONTROLS, "Help for Game Controls", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS( MATERIAL_VAR_TRANSLUCENT ); + SET_FLAGS( MATERIAL_VAR_NOCULL ); + SET_FLAGS( MATERIAL_VAR_IGNOREZ ); + } + + SHADER_INIT + { + LoadTexture( BASETEXTURE ); + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + int nTexCoordDimensions = 3; + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION | VERTEX_COLOR, 1, &nTexCoordDimensions, 0 ); + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + + DECLARE_STATIC_VERTEX_SHADER( gamecontrols_vs20 ); + SET_STATIC_VERTEX_SHADER( gamecontrols_vs20 ); + + DECLARE_STATIC_PIXEL_SHADER( gamecontrols_ps20 ); + SET_STATIC_PIXEL_SHADER( gamecontrols_ps20 ); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE ); + + DECLARE_DYNAMIC_VERTEX_SHADER( gamecontrols_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( gamecontrols_vs20 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( gamecontrols_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( gamecontrols_ps20 ); + } + Draw(); + } +END_SHADER diff --git a/materialsystem/stdshaders/gamecontrols_ps20.fxc b/materialsystem/stdshaders/gamecontrols_ps20.fxc new file mode 100644 index 00000000..f2118076 --- /dev/null +++ b/materialsystem/stdshaders/gamecontrols_ps20.fxc @@ -0,0 +1,17 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + + +sampler Texture1Sampler : register( s0 ); + +struct PS_INPUT +{ + float3 vTexCoord : TEXCOORD0; + float4 vColor : TEXCOORD1; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float4 c = tex2D( Texture1Sampler, i.vTexCoord.xy ); + c *= i.vColor; + return c; +} diff --git a/materialsystem/stdshaders/gamecontrols_vs20.fxc b/materialsystem/stdshaders/gamecontrols_vs20.fxc new file mode 100644 index 00000000..688d4afb --- /dev/null +++ b/materialsystem/stdshaders/gamecontrols_vs20.fxc @@ -0,0 +1,29 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + + +#include "common_vs_fxc.h" + +struct VS_INPUT +{ + float3 vPos : POSITION; + float3 vTexCoord : TEXCOORD0; + float4 vColor : COLOR0; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; + float3 vTexCoord : TEXCOORD0; + float4 vColor : TEXCOORD1; +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + o.projPos.xyzw = mul( float4( v.vPos.xyz, 1.0f ), cModelViewProj ); + o.vTexCoord = v.vTexCoord; + o.vColor.rgba = v.vColor.rgba; + + return o; +} diff --git a/materialsystem/stdshaders/genwaterloop.pl b/materialsystem/stdshaders/genwaterloop.pl new file mode 100644 index 00000000..0a4701ce --- /dev/null +++ b/materialsystem/stdshaders/genwaterloop.pl @@ -0,0 +1,9 @@ +for($ix=-2;$ix<=2;$ix++) +{ + for($iy=-2;$iy<=2;$iy++) + { + print "vRefractColor += tex2D( RefractSampler, vRefractTexCoord + $ix * ddx1 + $iy * ddy1 );\n"; + $sumweights+=1; + } +} +print "float sumweights = $sumweights;\n"; diff --git a/materialsystem/stdshaders/haloadd_ps2x.fxc b/materialsystem/stdshaders/haloadd_ps2x.fxc new file mode 100644 index 00000000..ae732b95 --- /dev/null +++ b/materialsystem/stdshaders/haloadd_ps2x.fxc @@ -0,0 +1,26 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#include "common_ps_fxc.h" + +sampler TexSampler : register( s0 ); + +float g_flDimValue : register( c0 ); + +struct PS_INPUT +{ + HALF2 baseTexCoord : TEXCOORD0; // Base texture coordinate +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float4 result = tex2D( TexSampler, i.baseTexCoord ); + + // Scale by dim value before computing luminance below + result.rgb *= saturate( g_flDimValue ); + + // Store max color component in alpha for alpha blend of one/invSrcAlpha + float flLuminance = max( result.r, max( result.g, result.b ) ); + result.a = pow( flLuminance, 0.8f ); + + return result.rgba; +} diff --git a/materialsystem/stdshaders/hsl_filmgrain_pass1.cpp b/materialsystem/stdshaders/hsl_filmgrain_pass1.cpp new file mode 100644 index 00000000..c407cc1f --- /dev/null +++ b/materialsystem/stdshaders/hsl_filmgrain_pass1.cpp @@ -0,0 +1,101 @@ +//========= Copyright © 1996-2005, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#include "BaseVSShader.h" +#include "convar.h" +#include "filmgrain_vs20.inc" +#include "hsl_filmgrain_pass1_ps20.inc" +#include "hsl_filmgrain_pass1_ps20b.inc" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +// +// First pass converts from RGB to HSL and tweaks with noise similar to After Effects +// + +BEGIN_VS_SHADER( hsl_filmgrain_pass1, "Help for Film Grain" ) + BEGIN_SHADER_PARAMS + // Input textures + SHADER_PARAM( INPUT, SHADER_PARAM_TYPE_TEXTURE, "", "" ) + SHADER_PARAM( GRAIN, SHADER_PARAM_TYPE_TEXTURE, "", "" ) + + // Grain parameters to control positioning and noise params + SHADER_PARAM( SCALEBIAS, SHADER_PARAM_TYPE_VEC4, "", "Scale and bias for grain placement" ) + SHADER_PARAM( HSLNOISESCALE, SHADER_PARAM_TYPE_VEC4, "", "Strength of film grain" ) + + END_SHADER_PARAMS + + SHADER_INIT + { + LoadTexture( INPUT ); + LoadTexture( GRAIN ); + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableDepthTest( false ); + pShaderShadow->EnableAlphaWrites( false ); + pShaderShadow->EnableBlending( false ); + pShaderShadow->EnableCulling( false ); +// pShaderShadow->PolyMode( SHADER_POLYMODEFACE_FRONT_AND_BACK, SHADER_POLYMODE_LINE ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + int fmt = VERTEX_POSITION; + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 ); + + DECLARE_STATIC_VERTEX_SHADER( filmgrain_vs20 ); + SET_STATIC_VERTEX_SHADER( filmgrain_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( hsl_filmgrain_pass1_ps20b ); + SET_STATIC_PIXEL_SHADER( hsl_filmgrain_pass1_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( hsl_filmgrain_pass1_ps20 ); + SET_STATIC_PIXEL_SHADER( hsl_filmgrain_pass1_ps20 ); + } + } + + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, INPUT, -1 ); + BindTexture( SHADER_SAMPLER1, GRAIN, -1 ); + + SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, SCALEBIAS ); + + SetPixelShaderConstant( 0, HSLNOISESCALE ); + + DECLARE_DYNAMIC_VERTEX_SHADER( filmgrain_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( filmgrain_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( hsl_filmgrain_pass1_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( hsl_filmgrain_pass1_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( hsl_filmgrain_pass1_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( hsl_filmgrain_pass1_ps20 ); + } + } + Draw(); + } +END_SHADER diff --git a/materialsystem/stdshaders/hsl_filmgrain_pass1_ps2x.fxc b/materialsystem/stdshaders/hsl_filmgrain_pass1_ps2x.fxc new file mode 100644 index 00000000..f30829e0 --- /dev/null +++ b/materialsystem/stdshaders/hsl_filmgrain_pass1_ps2x.fxc @@ -0,0 +1,24 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#include "common_ps_fxc.h" + +sampler InputSampler : register( s0 ); +sampler FilmGrain : register( s1 ); + +const float4 vNoiseScale : register( c0 ); + +struct PS_INPUT +{ + float2 inputImageCoords : TEXCOORD0; // Input image having grain added + float2 filmGrainCoords : TEXCOORD1; // Tiling film grain texture +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float3 hsl = RGBtoHSL( tex2D( InputSampler, i.inputImageCoords ) ); + float3 hslNoise = tex2D( FilmGrain, i.filmGrainCoords ) * 2.0f - 1.0f; + + hsl += hslNoise * vNoiseScale * float3( 0.5f, 1.0f, 1.0f ); + + return FinalOutput( float4 ( hsl, 1.0f ), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} diff --git a/materialsystem/stdshaders/hsl_filmgrain_pass2.cpp b/materialsystem/stdshaders/hsl_filmgrain_pass2.cpp new file mode 100644 index 00000000..aabb4d56 --- /dev/null +++ b/materialsystem/stdshaders/hsl_filmgrain_pass2.cpp @@ -0,0 +1,90 @@ +//========= Copyright © 1996-2005, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#include "BaseVSShader.h" +#include "convar.h" +#include "filmgrain_vs20.inc" +#include "hsl_filmgrain_pass2_ps20.inc" +#include "hsl_filmgrain_pass2_ps20b.inc" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +// +// Second pass merely converts from HSL back to RGB space, noise was already applied in first pass +// + +BEGIN_VS_SHADER( hsl_filmgrain_pass2, "Help for Film Grain" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( INPUT, SHADER_PARAM_TYPE_TEXTURE, "", "" ) + + END_SHADER_PARAMS + + SHADER_INIT + { + LoadTexture( INPUT ); + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableDepthTest( false ); + pShaderShadow->EnableAlphaWrites( false ); + pShaderShadow->EnableBlending( false ); + pShaderShadow->EnableCulling( false ); +// pShaderShadow->PolyMode( SHADER_POLYMODEFACE_FRONT_AND_BACK, SHADER_POLYMODE_LINE ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + int fmt = VERTEX_POSITION; + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 ); + + DECLARE_STATIC_VERTEX_SHADER( filmgrain_vs20 ); + SET_STATIC_VERTEX_SHADER( filmgrain_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( hsl_filmgrain_pass2_ps20b ); + SET_STATIC_PIXEL_SHADER( hsl_filmgrain_pass2_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( hsl_filmgrain_pass2_ps20 ); + SET_STATIC_PIXEL_SHADER( hsl_filmgrain_pass2_ps20 ); + } + } + + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, INPUT, -1 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( filmgrain_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( filmgrain_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( hsl_filmgrain_pass2_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( hsl_filmgrain_pass2_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( hsl_filmgrain_pass2_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( hsl_filmgrain_pass2_ps20 ); + } + } + Draw(); + } +END_SHADER + + diff --git a/materialsystem/stdshaders/hsl_filmgrain_pass2_ps2x.fxc b/materialsystem/stdshaders/hsl_filmgrain_pass2_ps2x.fxc new file mode 100644 index 00000000..3c5e3184 --- /dev/null +++ b/materialsystem/stdshaders/hsl_filmgrain_pass2_ps2x.fxc @@ -0,0 +1,16 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#include "common_ps_fxc.h" + +sampler InputSampler : register( s0 ); + +struct PS_INPUT +{ + float2 inputImageCoords : TEXCOORD0; // Input image + float2 filmGrainCoords : TEXCOORD1; // Tiling film grain texture +}; + +float4 main( PS_INPUT i ) : COLOR +{ + return FinalOutput( HSLtoRGB( tex2D( InputSampler, i.inputImageCoords ) ), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} diff --git a/materialsystem/stdshaders/hsv.cpp b/materialsystem/stdshaders/hsv.cpp new file mode 100644 index 00000000..5c945aef --- /dev/null +++ b/materialsystem/stdshaders/hsv.cpp @@ -0,0 +1,65 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" +#include "screenspaceeffect_vs20.inc" +#include "hsv_ps20.inc" +#include "hsv_ps20b.inc" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +BEGIN_VS_SHADER_FLAGS( HSV, "Help for HSV", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_NEEDS_FULL_FRAME_BUFFER_TEXTURE ); + } + + SHADER_INIT + { + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + int fmt = VERTEX_POSITION; + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 ); + + DECLARE_STATIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + SET_STATIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( hsv_ps20b ); + SET_STATIC_PIXEL_SHADER( hsv_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( hsv_ps20 ); + SET_STATIC_PIXEL_SHADER( hsv_ps20 ); + } + } + DYNAMIC_STATE + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_FRAME_BUFFER_FULL_TEXTURE_0 ); + DECLARE_DYNAMIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + } + Draw(); + } +END_SHADER diff --git a/materialsystem/stdshaders/hsv_ps2x.fxc b/materialsystem/stdshaders/hsv_ps2x.fxc new file mode 100644 index 00000000..44519f9d --- /dev/null +++ b/materialsystem/stdshaders/hsv_ps2x.fxc @@ -0,0 +1,24 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#include "common_ps_fxc.h" + +sampler BaseTextureSampler : register( s0 ); + +struct PS_INPUT +{ + float2 baseTexCoord : TEXCOORD0; +}; + +HALF4 main( PS_INPUT i ) : COLOR +{ + HALF4 result; + HALF4 baseColor; + HALF maxValue; + + baseColor = tex2D( BaseTextureSampler, i.baseTexCoord ); + maxValue = max( baseColor.r, baseColor.g ); + maxValue = max( baseColor.b, maxValue ); + result = maxValue; + result.a = 1.0f; + return FinalOutput( result, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} diff --git a/materialsystem/stdshaders/lightingonly_vs20.fxc b/materialsystem/stdshaders/lightingonly_vs20.fxc new file mode 100644 index 00000000..1261a26e --- /dev/null +++ b/materialsystem/stdshaders/lightingonly_vs20.fxc @@ -0,0 +1,62 @@ +// STATIC: "HALFLAMBERT" "0..1" +#include "common_fog_vs_fxc.h" +// DYNAMIC: "SKINNING" "0..1" +// DYNAMIC: "DYNAMIC_LIGHT" "0..1" +// DYNAMIC: "STATIC_LIGHT" "0..1" + + +#include "common_vs_fxc.h" + +static const int g_FogType = DOWATERFOG; +static const bool g_bHalfLambert = HALFLAMBERT ? true : false; +static const int g_nSkinning = SKINNING; +static const bool g_bDynamicLight = DYNAMIC_LIGHT ? true : false; +static const bool g_bStaticLight = STATIC_LIGHT ? true : false; + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vNormal : NORMAL; + + float3 vSpecular : COLOR1; + + float2 vTexCoord0 : TEXCOORD0; + float2 vTexCoord1 : TEXCOORD1; + float2 vTexCoord2 : TEXCOORD2; + +}; + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; + float3 vColor0 : COLOR0; + +#if !defined( _X360 ) + float fog : FOG; +#endif +}; + + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 vObjNormal; + DecompressVertex_Normal( v.vNormal, vObjNormal ); + + float3 worldPos, worldNormal; + SkinPositionAndNormal( g_bSkinning, v.vPos, vObjNormal, v.vBoneWeights, v.vBoneIndices, worldPos, worldNormal ); + + o.vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + o.fog = CalcFixedFunctionFog( worldPos, g_FogType ); +#endif + + // Compute vertex lighting + o.vColor0 = DoLighting( worldPos, worldNormal, float3(0.0f, 0.0f, 0.0f), g_bStaticLight, g_bDynamicLight, g_bHalfLambert ); + + return o; +} \ No newline at end of file diff --git a/materialsystem/stdshaders/lightmappedgeneric_decal.cpp b/materialsystem/stdshaders/lightmappedgeneric_decal.cpp new file mode 100644 index 00000000..7ed8f631 --- /dev/null +++ b/materialsystem/stdshaders/lightmappedgeneric_decal.cpp @@ -0,0 +1,128 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: Lightmap only shader +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" + +#include "lightmappedgeneric_decal.inc" +#include "mathlib/bumpvects.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + +BEGIN_VS_SHADER( LightmappedGeneric_Decal, + "Help for LightmappedGeneric_Decal" ) + + BEGIN_SHADER_PARAMS + END_SHADER_PARAMS + + // Set up anything that is necessary to make decisions in SHADER_FALLBACK. + SHADER_INIT_PARAMS() + { + params[FLASHLIGHTTEXTURE]->SetStringValue( GetFlashlightTextureFilename() ); + + // No texture means no self-illum or env mask in base alpha + if ( !params[BASETEXTURE]->IsDefined() ) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + SET_FLAGS( MATERIAL_VAR_DECAL ); + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + LoadTexture( FLASHLIGHTTEXTURE ); + + if (params[BASETEXTURE]->IsDefined()) + { + LoadTexture( BASETEXTURE ); + + if ( !params[BASETEXTURE]->GetTextureValue()->IsTranslucent() ) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + } + + // Don't alpha test if the alpha channel is used for other purposes + if (IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK) ) + { + CLEAR_FLAGS( MATERIAL_VAR_ALPHATEST ); + } + } + + void DrawDecal( IMaterialVar **params, IShaderDynamicAPI *pShaderAPI, IShaderShadow *pShaderShadow ) + { + if( IsSnapshotting() ) + { + // Be sure not to write to dest alpha + pShaderShadow->EnableAlphaWrites( false ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + + SetNormalBlendingShadowState( BASETEXTURE, true ); + + int pTexCoords[3] = { 2, 2, 1 }; + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION | VERTEX_COLOR, 3, pTexCoords, 0 ); + + lightmappedgeneric_decal_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "LightmappedGeneric_Decal", vshIndex.GetIndex() ); + pShaderShadow->SetPixelShader( "LightmappedGeneric_Decal" ); + FogToFogColor(); + } + else + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + + // Load the z^2 components of the lightmap coordinate axes only + // This is (N dot basis)^2 + Vector vecZValues( g_localBumpBasis[0].z, g_localBumpBasis[1].z, g_localBumpBasis[2].z ); + vecZValues *= vecZValues; + + Vector4D basis[3]; + basis[0].Init( vecZValues.x, vecZValues.x, vecZValues.x, 0.0f ); + basis[1].Init( vecZValues.y, vecZValues.y, vecZValues.y, 0.0f ); + basis[2].Init( vecZValues.z, vecZValues.z, vecZValues.z, 0.0f ); + pShaderAPI->SetPixelShaderConstant( 0, (float*)basis, 3 ); + + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP_BUMPED ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BASETEXTURETRANSFORM ); + SetModulationPixelShaderDynamicState( 3 ); + + lightmappedgeneric_decal_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); + } + + SHADER_DRAW + { + if( UsingFlashlight( params ) ) + { + DrawFlashlight_dx80( params, pShaderAPI, pShaderShadow, false, -1, -1, -1, + FLASHLIGHTTEXTURE, FLASHLIGHTTEXTUREFRAME, true, false, 0, -1, -1 ); + } + else + { + DrawDecal( params, pShaderAPI, pShaderShadow ); + } + } +END_SHADER diff --git a/materialsystem/stdshaders/lightmappedgeneric_decal_ps2x.fxc b/materialsystem/stdshaders/lightmappedgeneric_decal_ps2x.fxc new file mode 100644 index 00000000..f18b62da --- /dev/null +++ b/materialsystem/stdshaders/lightmappedgeneric_decal_ps2x.fxc @@ -0,0 +1,58 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#include "common_fog_ps_fxc.h" + +#include "common_ps_fxc.h" +#include "shader_constant_register_map.h" + +sampler BaseTextureSampler : register( s0 ); +sampler LightMap0Sampler : register( s1 ); +sampler LightMap1Sampler : register( s2 ); +sampler LightMap2Sampler : register( s3 ); + +const float4 g_LightMap0Color : register( c0 ); +const float4 g_LightMap1Color : register( c1 ); +const float4 g_LightMap2Color : register( c2 ); +const float4 g_ModulationColor : register( c3 ); + +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT ); + + +struct PS_INPUT +{ + float4 vProjPos : POSITION; + float2 vTexCoord0 : TEXCOORD0; + float2 vTexCoord1 : TEXCOORD1; + float2 vTexCoord2 : TEXCOORD2; + float2 vTexCoord3 : TEXCOORD3; + float4 worldPos_projPosZ : TEXCOORD4; // Necessary for pixel fog + + float4 vColor : COLOR0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float4 resultColor; + + // output = lightmapColor[0] * ( ( N dot basis[0] )^2 ) + + // lightmapColor[1] * ( ( N dot basis[1] )^2 ) + + // lightmapColor[2] * ( ( N dot basis[2] )^2 ) + + resultColor = tex2D( LightMap0Sampler, i.vTexCoord1 ) * g_LightMap0Color; + resultColor = (tex2D( LightMap1Sampler, i.vTexCoord2 ) * g_LightMap1Color) + resultColor; + resultColor = (tex2D( LightMap2Sampler, i.vTexCoord3 ) * g_LightMap2Color) + resultColor; + + // Modulate by decal texture + float4 decalColor = tex2D( BaseTextureSampler, i.vTexCoord0 ); + resultColor.rgb = resultColor * decalColor; + resultColor.a = decalColor.a; + + // Modulate by constant color + resultColor = resultColor * g_ModulationColor; + + // Modulate by per-vertex factor + resultColor = resultColor * i.vColor; + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos_SpecExponent.xyz, i.worldPos_projPosZ.xyz, i.worldPos_projPosZ.w ); + return FinalOutput( resultColor, fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR ); +} diff --git a/materialsystem/stdshaders/lightmappedgeneric_decal_vs20.fxc b/materialsystem/stdshaders/lightmappedgeneric_decal_vs20.fxc new file mode 100644 index 00000000..71b9f28e --- /dev/null +++ b/materialsystem/stdshaders/lightmappedgeneric_decal_vs20.fxc @@ -0,0 +1,68 @@ +#include "common_fog_vs_fxc.h" + +#include "common_vs_fxc.h" + +static const int g_FogType = DOWATERFOG; + +const float4 cShaderConst0 : register( SHADER_SPECIFIC_CONST_0 ); +const float4 cShaderConst1 : register( SHADER_SPECIFIC_CONST_1 ); + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vTexCoord0 : TEXCOORD0; + float4 vTexCoord1 : TEXCOORD1; + float2 vTexCoord2 : TEXCOORD2; + + float4 vColor : COLOR0; +}; + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; + float2 vTexCoord0 : TEXCOORD0; + float2 vTexCoord1 : TEXCOORD1; + float2 vTexCoord2 : TEXCOORD2; + float2 vTexCoord3 : TEXCOORD3; + + float4 worldPos_projPosZ : TEXCOORD4; // Necessary for pixel fog + + float4 vColor : COLOR0; + +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + float fog : FOG; +#endif +}; + + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 worldPos; + worldPos = mul( v.vPos, cModel[0] ); + o.vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + o.worldPos_projPosZ = float4( worldPos.xyz, o.vProjPos.z ); + +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + o.fog = CalcFixedFunctionFog( worldPos, g_FogType ); +#endif + + + // Compute the texture coordinates given the offset between + // each bumped lightmap + float2 offset; + offset.x = v.vTexCoord2.x; + offset.y = 0.0f; + + o.vTexCoord0.x = dot( v.vTexCoord0, cShaderConst0 ); + o.vTexCoord0.y = dot( v.vTexCoord0, cShaderConst1 ); + + o.vTexCoord1 = offset + v.vTexCoord1.xy; + o.vTexCoord2 = (offset * 2.0) + v.vTexCoord1.xy; + o.vTexCoord3 = (offset * 3.0) + v.vTexCoord1.xy; + + o.vColor = v.vColor; + + return o; +} \ No newline at end of file diff --git a/materialsystem/stdshaders/lightmappedgeneric_dx9.cpp b/materialsystem/stdshaders/lightmappedgeneric_dx9.cpp new file mode 100644 index 00000000..aac39257 --- /dev/null +++ b/materialsystem/stdshaders/lightmappedgeneric_dx9.cpp @@ -0,0 +1,216 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: Lightmap only shader +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" +#include "convar.h" +#include "lightmappedgeneric_dx9_helper.h" +#include "lightmappedpaint_dx9_helper.h" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +ConVar r_twopasspaint( "r_twopasspaint", "1", 0, "HAZARD: Only change this outside a map. Enable two-pass paint method. You will need to reload all materials when changing this convar" ); +static LightmappedGeneric_DX9_Vars_t s_info; + + +BEGIN_VS_SHADER( LightmappedGeneric, + "Help for LightmappedGeneric" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( ALBEDO, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "albedo (Base texture with no baked lighting)" ) + SHADER_PARAM( SELFILLUMTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Self-illumination tint" ) + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/detail", "detail texture" ) + SHADER_PARAM( DETAILFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $detail" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "4", "scale of the detail texture" ) + + SHADER_PARAM( ALPHA2, SHADER_PARAM_TYPE_FLOAT, "1", "" ) + + // detail (multi-) texturing + SHADER_PARAM( DETAILBLENDMODE, SHADER_PARAM_TYPE_INTEGER, "0", "mode for combining detail texture with base. 0=normal, 1= additive, 2=alpha blend detail over base, 3=crossfade" ) + SHADER_PARAM( DETAILBLENDFACTOR, SHADER_PARAM_TYPE_FLOAT, "1", "blend amount for detail texture." ) + SHADER_PARAM( DETAILTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "detail texture tint" ) + + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( ENVMAPMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_envmask", "envmap mask" ) + SHADER_PARAM( ENVMAPMASKFRAME, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( ENVMAPMASKTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$envmapmask texcoord transform" ) + SHADER_PARAM( ENVMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "envmap tint" ) + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "bump map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( ENVMAPCONTRAST, SHADER_PARAM_TYPE_FLOAT, "0.0", "contrast 0 == normal 1 == color*color" ) + SHADER_PARAM( ENVMAPSATURATION, SHADER_PARAM_TYPE_FLOAT, "1.0", "saturation 0 == greyscale 1 == normal" ) + SHADER_PARAM( FRESNELREFLECTION, SHADER_PARAM_TYPE_FLOAT, "1.0", "1.0 == mirror, 0.0 == water" ) + SHADER_PARAM( NODIFFUSEBUMPLIGHTING, SHADER_PARAM_TYPE_INTEGER, "0", "0 == Use diffuse bump lighting, 1 = No diffuse bump lighting" ) + SHADER_PARAM( BUMPMAP2, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader3_normal", "bump map" ) + SHADER_PARAM( BUMPFRAME2, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM2, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( BUMPMASK, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader3_normal", "bump map" ) + SHADER_PARAM( BASETEXTURE2, SHADER_PARAM_TYPE_TEXTURE, "shadertest/lightmappedtexture", "Blended texture" ) + SHADER_PARAM( FRAME2, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $basetexture2" ) + SHADER_PARAM( BASETEXTURENOENVMAP, SHADER_PARAM_TYPE_BOOL, "0", "" ) + SHADER_PARAM( BASETEXTURE2NOENVMAP, SHADER_PARAM_TYPE_BOOL, "0", "" ) + SHADER_PARAM( DETAIL_ALPHA_MASK_BASE_TEXTURE, SHADER_PARAM_TYPE_BOOL, "0", + "If this is 1, then when detail alpha=0, no base texture is blended and when " + "detail alpha=1, you get detail*base*lightmap" ) + SHADER_PARAM( LIGHTWARPTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "light munging lookup texture" ) + SHADER_PARAM( BLENDMODULATETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "texture to use r/g channels for blend range for" ) + SHADER_PARAM( MASKEDBLENDING, SHADER_PARAM_TYPE_INTEGER, "0", "blend using texture with no vertex alpha. For using texture blending on non-displacements" ) + SHADER_PARAM( BLENDMASKTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$blendmodulatetexture texcoord transform" ) + SHADER_PARAM( SSBUMP, SHADER_PARAM_TYPE_INTEGER, "0", "whether or not to use alternate bumpmap format with height" ) + SHADER_PARAM( SEAMLESS_SCALE, SHADER_PARAM_TYPE_FLOAT, "0", "Scale factor for 'seamless' texture mapping. 0 means to use ordinary mapping" ) + SHADER_PARAM( ALPHATESTREFERENCE, SHADER_PARAM_TYPE_FLOAT, "0.0", "" ) + + SHADER_PARAM( SOFTEDGES, SHADER_PARAM_TYPE_BOOL, "0", "Enable soft edges to distance coded textures.") + SHADER_PARAM( EDGESOFTNESSSTART, SHADER_PARAM_TYPE_FLOAT, "0.6", "Start value for soft edges for distancealpha."); + SHADER_PARAM( EDGESOFTNESSEND, SHADER_PARAM_TYPE_FLOAT, "0.5", "End value for soft edges for distancealpha."); + + SHADER_PARAM( OUTLINE, SHADER_PARAM_TYPE_BOOL, "0", "Enable outline for distance coded textures.") + SHADER_PARAM( OUTLINECOLOR, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "color of outline for distance coded images." ) + SHADER_PARAM( OUTLINEALPHA, SHADER_PARAM_TYPE_FLOAT, "0.0", "alpha value for outline") + SHADER_PARAM( OUTLINESTART0, SHADER_PARAM_TYPE_FLOAT, "0.0", "outer start value for outline") + SHADER_PARAM( OUTLINESTART1, SHADER_PARAM_TYPE_FLOAT, "0.0", "inner start value for outline") + SHADER_PARAM( OUTLINEEND0, SHADER_PARAM_TYPE_FLOAT, "0.0", "inner end value for outline") + SHADER_PARAM( OUTLINEEND1, SHADER_PARAM_TYPE_FLOAT, "0.0", "outer end value for outline") + + SHADER_PARAM( PARALLAXMAP, SHADER_PARAM_TYPE_INTEGER, "0", "1=treat alpha of bumpmap as height" ) + SHADER_PARAM( HEIGHT_SCALE, SHADER_PARAM_TYPE_FLOAT, "0.1", "height map scale for parallax mapping" ) + + SHADER_PARAM( SHADERSRGBREAD360, SHADER_PARAM_TYPE_BOOL, "0", "Simulate srgb read in shader code") + + SHADER_PARAM( ENVMAPLIGHTSCALE, SHADER_PARAM_TYPE_FLOAT, "0.0", "How much the lightmap effects environment map reflection, 0.0 is off, 1.0 will allow complete blackness of the environment map if the lightmap is black" ) + + SHADER_PARAM( FOW, SHADER_PARAM_TYPE_TEXTURE, "", "FoW Render Target" ) + SHADER_PARAM( PAINTSPLATNORMALMAP, SHADER_PARAM_TYPE_TEXTURE, "paint/splatnormal_default", "The paint splat normal map to use when paint is enabled on the surface" ) + SHADER_PARAM( PAINTSPLATENVMAP, SHADER_PARAM_TYPE_TEXTURE, "env_cubemap", "The envmap to use on the paint pass. You're getting one whether you like it or not" ) + +END_SHADER_PARAMS + + void SetupVars( LightmappedGeneric_DX9_Vars_t& info ) + { + info.m_nBaseTexture = BASETEXTURE; + info.m_nBaseTextureFrame = FRAME; + info.m_nBaseTextureTransform = BASETEXTURETRANSFORM; + info.m_nAlbedo = ALBEDO; + info.m_nSelfIllumTint = SELFILLUMTINT; + + info.m_nAlpha2 = ALPHA2; + + info.m_nDetail = DETAIL; + info.m_nDetailFrame = DETAILFRAME; + info.m_nDetailScale = DETAILSCALE; + info.m_nDetailTextureCombineMode = DETAILBLENDMODE; + info.m_nDetailTextureBlendFactor = DETAILBLENDFACTOR; + info.m_nDetailTint = DETAILTINT; + + info.m_nEnvmap = ENVMAP; + info.m_nEnvmapFrame = ENVMAPFRAME; + info.m_nEnvmapMask = ENVMAPMASK; + info.m_nEnvmapMaskFrame = ENVMAPMASKFRAME; + info.m_nEnvmapMaskTransform = ENVMAPMASKTRANSFORM; + info.m_nEnvmapTint = ENVMAPTINT; + info.m_nBumpmap = BUMPMAP; + info.m_nBumpFrame = BUMPFRAME; + info.m_nBumpTransform = BUMPTRANSFORM; + info.m_nEnvmapContrast = ENVMAPCONTRAST; + info.m_nEnvmapSaturation = ENVMAPSATURATION; + info.m_nFresnelReflection = FRESNELREFLECTION; + info.m_nNoDiffuseBumpLighting = NODIFFUSEBUMPLIGHTING; + info.m_nBumpmap2 = BUMPMAP2; + info.m_nBumpFrame2 = BUMPFRAME2; + info.m_nBumpTransform2 = BUMPTRANSFORM2; + info.m_nBumpMask = BUMPMASK; + info.m_nBaseTexture2 = BASETEXTURE2; + info.m_nBaseTexture2Frame = FRAME2; + info.m_nBaseTextureNoEnvmap = BASETEXTURENOENVMAP; + info.m_nBaseTexture2NoEnvmap = BASETEXTURE2NOENVMAP; + info.m_nDetailAlphaMaskBaseTexture = DETAIL_ALPHA_MASK_BASE_TEXTURE; + info.m_nFlashlightTexture = FLASHLIGHTTEXTURE; + info.m_nFlashlightTextureFrame = FLASHLIGHTTEXTUREFRAME; + info.m_nLightWarpTexture = LIGHTWARPTEXTURE; + info.m_nBlendModulateTexture = BLENDMODULATETEXTURE; + info.m_nMaskedBlending = MASKEDBLENDING; + info.m_nBlendMaskTransform = BLENDMASKTRANSFORM; + info.m_nSelfShadowedBumpFlag = SSBUMP; + info.m_nSeamlessMappingScale = SEAMLESS_SCALE; + info.m_nAlphaTestReference = ALPHATESTREFERENCE; + + info.m_nSoftEdges = SOFTEDGES; + info.m_nEdgeSoftnessStart = EDGESOFTNESSSTART; + info.m_nEdgeSoftnessEnd = EDGESOFTNESSEND; + info.m_nOutline = OUTLINE; + info.m_nOutlineColor = OUTLINECOLOR; + info.m_nOutlineAlpha = OUTLINEALPHA; + info.m_nOutlineStart0 = OUTLINESTART0; + info.m_nOutlineStart1 = OUTLINESTART1; + info.m_nOutlineEnd0 = OUTLINEEND0; + info.m_nOutlineEnd1 = OUTLINEEND1; + info.m_nParallaxMap = PARALLAXMAP; + info.m_nHeightScale = HEIGHT_SCALE; + + info.m_nShaderSrgbRead360 = SHADERSRGBREAD360; + + info.m_nEnvMapLightScale = ENVMAPLIGHTSCALE; + + info.m_nFoW = FOW; + + info.m_nPaintSplatNormal = PAINTSPLATNORMALMAP; + info.m_nPaintSplatEnvMap = PAINTSPLATENVMAP; + } + + SHADER_FALLBACK + { + return 0; + } + + // Set up anything that is necessary to make decisions in SHADER_FALLBACK. + SHADER_INIT_PARAMS() + { + SetupVars( s_info ); + InitParamsLightmappedGeneric_DX9( this, params, pMaterialName, s_info ); + } + + SHADER_INIT + { + SetupVars( s_info ); + InitLightmappedGeneric_DX9( this, params, s_info ); + } + + SHADER_DRAW + { + DrawLightmappedGeneric_DX9( this, params, pShaderAPI, pShaderShadow, s_info, pContextDataPtr ); + + // If the game/mod can potentially support the paint feature, then we need to always record snapshots + // as though there may be a 2nd pass. When in a map containing paint, you need to also draw the 2nd pass. + if ( g_pConfig->m_bPaintInGame ) + { + // If recording snapshots OR in a map with paint... + if ( ( pShaderShadow || g_pConfig->m_bPaintInMap ) && r_twopasspaint.GetBool() ) + { + #ifdef _X360 + // Do not render paint during the auto Z pass on Xbox 360 + if ( pShaderAPI ) + pShaderAPI->EnablePredication( false, true ); + #endif // _X360 + + DrawLightmappedPaint_DX9( this, params, pShaderAPI, pShaderShadow, s_info, pContextDataPtr ); + + #ifdef _X360 + if ( pShaderAPI ) + pShaderAPI->DisablePredication(); + #endif // _X360 + } + else + { + Draw( false ); + } + } + } +END_SHADER diff --git a/materialsystem/stdshaders/lightmappedgeneric_dx9_helper.cpp b/materialsystem/stdshaders/lightmappedgeneric_dx9_helper.cpp new file mode 100644 index 00000000..02843585 --- /dev/null +++ b/materialsystem/stdshaders/lightmappedgeneric_dx9_helper.cpp @@ -0,0 +1,1140 @@ +//========= Copyright © 1996-2007, Valve LLC, All rights reserved. ============ +// +// Purpose: Lightmap only shader +// +// $Header: $ +// $NoKeywords: $ +//============================================================================= + +#include "lightmappedgeneric_dx9_helper.h" +#include "BaseVSShader.h" +#include "shaderlib/commandbuilder.h" +#include "convar.h" +#include "lightmappedgeneric_ps20.inc" +#include "lightmappedgeneric_vs20.inc" +#include "lightmappedgeneric_ps20b.inc" + +#include "tier0/vprof.h" + +#include "tier0/memdbgon.h" + +ConVar mat_disable_lightwarp( "mat_disable_lightwarp", "0" ); +ConVar mat_disable_fancy_blending( "mat_disable_fancy_blending", "0" ); +ConVar mat_fullbright( "mat_fullbright","0", FCVAR_CHEAT ); + +ConVar mat_ambient_light_r( "mat_ambient_light_r", "0.0", FCVAR_CHEAT ); +ConVar mat_ambient_light_g( "mat_ambient_light_g", "0.0", FCVAR_CHEAT ); +ConVar mat_ambient_light_b( "mat_ambient_light_b", "0.0", FCVAR_CHEAT ); + +extern ConVar r_twopasspaint; + + + +static ConVar mat_force_vertexfog( "mat_force_vertexfog", "0", FCVAR_DEVELOPMENTONLY ); + +void InitParamsLightmappedGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, LightmappedGeneric_DX9_Vars_t &info ) +{ + // Override vertex fog via the global setting if it isn't enabled/disabled in the material file. + if ( !IS_FLAG_DEFINED( MATERIAL_VAR_VERTEXFOG ) && mat_force_vertexfog.GetBool() ) + { + SET_FLAGS( MATERIAL_VAR_VERTEXFOG ); + } + + params[FLASHLIGHTTEXTURE]->SetStringValue( GetFlashlightTextureFilename() ); + + // Write over $basetexture with $albedo if we are going to be using diffuse normal mapping. + if( g_pConfig->UseBumpmapping() && params[info.m_nBumpmap]->IsDefined() && params[info.m_nAlbedo]->IsDefined() && + params[info.m_nBaseTexture]->IsDefined() && + !( params[info.m_nNoDiffuseBumpLighting]->IsDefined() && params[info.m_nNoDiffuseBumpLighting]->GetIntValue() ) ) + { + params[info.m_nBaseTexture]->SetStringValue( params[info.m_nAlbedo]->GetStringValue() ); + } + + if( pShader->IsUsingGraphics() && params[info.m_nEnvmap]->IsDefined() && !pShader->CanUseEditorMaterials() ) + { + if( stricmp( params[info.m_nEnvmap]->GetStringValue(), "env_cubemap" ) == 0 ) + { + Warning( "env_cubemap used on world geometry without rebuilding map. . ignoring: %s\n", pMaterialName ); + params[info.m_nEnvmap]->SetUndefined(); + } + } + + if ( (mat_disable_lightwarp.GetBool() ) && + (info.m_nLightWarpTexture != -1) ) + { + params[info.m_nLightWarpTexture]->SetUndefined(); + } + if ( (mat_disable_fancy_blending.GetBool() ) && + (info.m_nBlendModulateTexture != -1) ) + { + params[info.m_nBlendModulateTexture]->SetUndefined(); + } + + if( !params[info.m_nEnvmapTint]->IsDefined() ) + params[info.m_nEnvmapTint]->SetVecValue( 1.0f, 1.0f, 1.0f ); + + if( !params[info.m_nNoDiffuseBumpLighting]->IsDefined() ) + params[info.m_nNoDiffuseBumpLighting]->SetIntValue( 0 ); + + if( !params[info.m_nSelfIllumTint]->IsDefined() ) + params[info.m_nSelfIllumTint]->SetVecValue( 1.0f, 1.0f, 1.0f ); + + if( !params[info.m_nDetailScale]->IsDefined() ) + params[info.m_nDetailScale]->SetFloatValue( 4.0f ); + + if ( !params[info.m_nDetailTint]->IsDefined() ) + params[info.m_nDetailTint]->SetVecValue( 1.0f, 1.0f, 1.0f, 1.0f ); + + InitFloatParam( info.m_nDetailTextureBlendFactor, params, 1.0 ); + InitIntParam( info.m_nDetailTextureCombineMode, params, 0 ); + + if( !params[info.m_nFresnelReflection]->IsDefined() ) + params[info.m_nFresnelReflection]->SetFloatValue( 1.0f ); + + if( !params[info.m_nEnvmapMaskFrame]->IsDefined() ) + params[info.m_nEnvmapMaskFrame]->SetIntValue( 0 ); + + if( !params[info.m_nEnvmapFrame]->IsDefined() ) + params[info.m_nEnvmapFrame]->SetIntValue( 0 ); + + if( !params[info.m_nBumpFrame]->IsDefined() ) + params[info.m_nBumpFrame]->SetIntValue( 0 ); + + if( !params[info.m_nDetailFrame]->IsDefined() ) + params[info.m_nDetailFrame]->SetIntValue( 0 ); + + if( !params[info.m_nEnvmapContrast]->IsDefined() ) + params[info.m_nEnvmapContrast]->SetFloatValue( 0.0f ); + + if( !params[info.m_nEnvmapSaturation]->IsDefined() ) + params[info.m_nEnvmapSaturation]->SetFloatValue( 1.0f ); + + InitFloatParam( info.m_nAlphaTestReference, params, 0.0f ); + + // No texture means no self-illum or env mask in base alpha + if ( !params[info.m_nBaseTexture]->IsDefined() ) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + if( params[info.m_nBumpmap]->IsDefined() ) + { + params[info.m_nEnvmapMask]->SetUndefined(); + } + + // If in decal mode, no debug override... + if (IS_FLAG_SET(MATERIAL_VAR_DECAL)) + { + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + } + + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + if( g_pConfig->UseBumpmapping() && params[info.m_nBumpmap]->IsDefined() && (params[info.m_nNoDiffuseBumpLighting]->GetIntValue() == 0) ) + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_BUMPED_LIGHTMAP ); + } + + // If mat_specular 0, then get rid of envmap + if( !g_pConfig->UseSpecular() && params[info.m_nEnvmap]->IsDefined() && params[info.m_nBaseTexture]->IsDefined() ) + { + params[info.m_nEnvmap]->SetUndefined(); + } + + if( !params[info.m_nBaseTextureNoEnvmap]->IsDefined() ) + { + params[info.m_nBaseTextureNoEnvmap]->SetIntValue( 0 ); + } + if( !params[info.m_nBaseTexture2NoEnvmap]->IsDefined() ) + { + params[info.m_nBaseTexture2NoEnvmap]->SetIntValue( 0 ); + } + + if( ( info.m_nSelfShadowedBumpFlag != -1 ) && + ( !params[info.m_nSelfShadowedBumpFlag]->IsDefined() ) + ) + { + params[info.m_nSelfShadowedBumpFlag]->SetIntValue( 0 ); + } + // handle line art parms + InitFloatParam( info.m_nEdgeSoftnessStart, params, 0.5 ); + InitFloatParam( info.m_nEdgeSoftnessEnd, params, 0.5 ); + InitFloatParam( info.m_nOutlineAlpha, params, 1.0 ); + + // parallax mapping + InitFloatParam( info.m_nHeightScale, params, 0.1 ); + + // srgb read 360 + InitIntParam( info.m_nShaderSrgbRead360, params, 0 ); + + InitFloatParam( info.m_nEnvMapLightScale, params, 0.0f ); + + if ( g_pConfig->m_bPaintInGame ) + { + if( info.m_nPaintSplatNormal != -1 ) + { + if( !params[info.m_nPaintSplatNormal]->IsDefined() ) + { + params[info.m_nPaintSplatNormal]->SetStringValue( "paint/splatnormal_default" ); + } + } + + if( info.m_nPaintSplatEnvMap != -1 ) + { + if( !params[info.m_nPaintSplatEnvMap]->IsDefined() ) + { + if( params[info.m_nEnvmap]->IsDefined() ) + { + params[info.m_nPaintSplatEnvMap]->SetStringValue( params[info.m_nEnvmap]->GetStringValue() ); + } + else + { + params[info.m_nPaintSplatEnvMap]->SetStringValue( "env_cubemap" ); + } + } + } + } + else + { + if( info.m_nPaintSplatNormal != -1 ) + { + params[info.m_nPaintSplatNormal]->SetUndefined(); + } + + if( info.m_nPaintSplatEnvMap != -1 ) + { + params[info.m_nPaintSplatEnvMap]->SetUndefined(); + } + } +} + +void InitLightmappedGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, LightmappedGeneric_DX9_Vars_t &info ) +{ + bool hasNormalMapAlphaEnvmapMask = g_pConfig->UseSpecular() && IS_FLAG_SET( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ); + + if ( ( g_pConfig->UseBumpmapping() || hasNormalMapAlphaEnvmapMask ) && params[info.m_nBumpmap]->IsDefined() ) + { + pShader->LoadBumpMap( info.m_nBumpmap ); + } + + if ( g_pConfig->UseBumpmapping() && params[info.m_nBumpmap2]->IsDefined() ) + { + pShader->LoadBumpMap( info.m_nBumpmap2 ); + } + + if ( g_pConfig->UseBumpmapping() && params[info.m_nBumpMask]->IsDefined() ) + { + pShader->LoadBumpMap( info.m_nBumpMask ); + } + + if (params[info.m_nBaseTexture]->IsDefined()) + { + pShader->LoadTexture( info.m_nBaseTexture ); + + if (!params[info.m_nBaseTexture]->GetTextureValue()->IsTranslucent()) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + } + + if (params[info.m_nBaseTexture2]->IsDefined() ) + { + pShader->LoadTexture( info.m_nBaseTexture2 ); + } + + if (params[info.m_nBaseTexture2]->IsDefined() ) + { + pShader->LoadTexture( info.m_nBaseTexture2 ); + } + + if ((info.m_nBlendModulateTexture != -1) && + (params[info.m_nBlendModulateTexture]->IsDefined()) ) + { + pShader->LoadTexture( info.m_nBlendModulateTexture ); + } + + if (params[info.m_nDetail]->IsDefined()) + { + int nDetailBlendMode = ( info.m_nDetailTextureCombineMode == -1 ) ? 0 : params[info.m_nDetailTextureCombineMode]->GetIntValue(); + nDetailBlendMode = nDetailBlendMode > 1 ? 1 : nDetailBlendMode; + + if ( nDetailBlendMode == 0 ) //Mod2X + pShader->LoadTexture( info.m_nDetail ); + else + pShader->LoadTexture( info.m_nDetail ); + } + + pShader->LoadTexture( info.m_nFlashlightTexture ); + + // Don't alpha test if the alpha channel is used for other purposes + if (IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK) ) + { + CLEAR_FLAGS( MATERIAL_VAR_ALPHATEST ); + } + + if ( g_pConfig->UseSpecular() ) + { + if ( params[info.m_nEnvmap]->IsDefined() ) + { + pShader->LoadCubeMap( info.m_nEnvmap ); + + if (params[info.m_nEnvmapMask]->IsDefined()) + { + pShader->LoadTexture( info.m_nEnvmapMask ); + } + } + else + { + params[info.m_nEnvmapMask]->SetUndefined(); + } + } + else + { + params[info.m_nEnvmap]->SetUndefined(); + params[info.m_nEnvmapMask]->SetUndefined(); + } + + // We always need this because of the flashlight. + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + + if( IS_PARAM_DEFINED( info.m_nPaintSplatNormal ) ) + { + pShader->LoadBumpMap( info.m_nPaintSplatNormal ); + } + + if( IS_PARAM_DEFINED( info.m_nPaintSplatEnvMap ) ) + { + pShader->LoadCubeMap( info.m_nPaintSplatEnvMap ); + } +} + +void DrawLightmappedGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, + LightmappedGeneric_DX9_Vars_t &info, CBasePerMaterialContextData **pContextDataPtr ) +{ + bool bSinglePassFlashlight = true; + bool hasFlashlight = pShader->UsingFlashlight( params ); + CLightmappedGeneric_DX9_Context *pContextData = reinterpret_cast< CLightmappedGeneric_DX9_Context *> ( *pContextDataPtr ); + bool bShaderSrgbRead = ( IsX360() && IS_PARAM_DEFINED( info.m_nShaderSrgbRead360 ) && params[info.m_nShaderSrgbRead360]->GetIntValue() ); + + if ( pShaderShadow || ( ! pContextData ) || pContextData->m_bMaterialVarsChanged || ( hasFlashlight && !IsX360() ) ) + { + bool hasBaseTexture = params[info.m_nBaseTexture]->IsTexture(); + int nAlphaChannelTextureVar = hasBaseTexture ? (int)info.m_nBaseTexture : (int)info.m_nEnvmapMask; + BlendType_t nBlendType = pShader->EvaluateBlendRequirements( nAlphaChannelTextureVar, hasBaseTexture ); + bool bIsAlphaTested = IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) != 0; + bool bFullyOpaqueWithoutAlphaTest = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && (!hasFlashlight || IsX360()); //dest alpha is free for special use + bool bFullyOpaque = bFullyOpaqueWithoutAlphaTest && !bIsAlphaTested; + bool bNeedRegenStaticCmds = (! pContextData ) || pShaderShadow; + + if ( ! pContextData ) // make sure allocated + { + pContextData = new CLightmappedGeneric_DX9_Context; + *pContextDataPtr = pContextData; + } + + bool hasBump = ( params[info.m_nBumpmap]->IsTexture() ) && g_pConfig->UseBumpmapping(); + bool hasSSBump = hasBump && (info.m_nSelfShadowedBumpFlag != -1) && ( params[info.m_nSelfShadowedBumpFlag]->GetIntValue() ); + bool hasBaseTexture2 = hasBaseTexture && params[info.m_nBaseTexture2]->IsTexture(); + bool hasLightWarpTexture = params[info.m_nLightWarpTexture]->IsTexture(); + bool hasBump2 = hasBump && params[info.m_nBumpmap2]->IsTexture(); + bool hasDetailTexture = params[info.m_nDetail]->IsTexture(); + bool hasSelfIllum = IS_FLAG_SET( MATERIAL_VAR_SELFILLUM ); + bool hasBumpMask = hasBump && hasBump2 && params[info.m_nBumpMask]->IsTexture() && !hasSelfIllum && + !hasDetailTexture && !hasBaseTexture2 && (params[info.m_nBaseTextureNoEnvmap]->GetIntValue() == 0); + bool bHasBlendModulateTexture = + (info.m_nBlendModulateTexture != -1) && + (params[info.m_nBlendModulateTexture]->IsTexture() ); + bool hasNormalMapAlphaEnvmapMask = g_pConfig->UseSpecular() && IS_FLAG_SET( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ); + + bool bParallaxMapping = false; + // L4D: no parallax mapping + /* + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + bParallaxMapping = ( info.m_nParallaxMap != -1 ) && ( params[info.m_nParallaxMap]->GetIntValue() != 0 ); + */ + + if ( hasFlashlight && !IsX360() ) + { + // !!speed!! do this in the caller so we don't build struct every time + CBaseVSShader::DrawFlashlight_dx90_Vars_t vars; + vars.m_bBump = hasBump; + vars.m_nBumpmapVar = info.m_nBumpmap; + vars.m_nBumpmapFrame = info.m_nBumpFrame; + vars.m_nBumpTransform = info.m_nBumpTransform; + vars.m_nFlashlightTextureVar = info.m_nFlashlightTexture; + vars.m_nFlashlightTextureFrameVar = info.m_nFlashlightTextureFrame; + vars.m_bLightmappedGeneric = true; + vars.m_bWorldVertexTransition = hasBaseTexture2; + vars.m_nBaseTexture2Var = info.m_nBaseTexture2; + vars.m_nBaseTexture2FrameVar = info.m_nBaseTexture2Frame; + vars.m_nBumpmap2Var = info.m_nBumpmap2; + vars.m_nBumpmap2Frame = info.m_nBumpFrame2; + vars.m_nBump2Transform = info.m_nBumpTransform2; + vars.m_nAlphaTestReference = info.m_nAlphaTestReference; + vars.m_bSSBump = hasSSBump; + vars.m_nDetailVar = info.m_nDetail; + vars.m_nDetailScale = info.m_nDetailScale; + vars.m_nDetailTextureCombineMode = info.m_nDetailTextureCombineMode; + vars.m_nDetailTextureBlendFactor = info.m_nDetailTextureBlendFactor; + vars.m_nDetailTint = info.m_nDetailTint; + + if ( ( info.m_nSeamlessMappingScale != -1 ) ) + vars.m_fSeamlessScale = params[info.m_nSeamlessMappingScale]->GetFloatValue(); + else + vars.m_fSeamlessScale = 0.0; + + pShader->DrawFlashlight_dx90( params, pShaderAPI, pShaderShadow, vars ); + return; + } + + pContextData->m_bFullyOpaque = bFullyOpaque; + pContextData->m_bFullyOpaqueWithoutAlphaTest = bFullyOpaqueWithoutAlphaTest; + + bool bHasOutline = IsBoolSet( info.m_nOutline, params ); + pContextData->m_bPixelShaderForceFastPathBecauseOutline = bHasOutline; + bool bHasSoftEdges = IsBoolSet( info.m_nSoftEdges, params ); + bool hasEnvmapMask = params[info.m_nEnvmapMask]->IsTexture(); + + + float fDetailBlendFactor = GetFloatParam( info.m_nDetailTextureBlendFactor, params, 1.0 ); + + if ( pShaderShadow || bNeedRegenStaticCmds ) + { + bool hasVertexColor = IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR ); + bool hasDiffuseBumpmap = hasBump && (params[info.m_nNoDiffuseBumpLighting]->GetIntValue() == 0); + + bool hasEnvmap = params[info.m_nEnvmap]->IsTexture(); + int envmap_variant; //0 = no envmap, 1 = regular, 2 = darken in shadow mode + if( hasEnvmap ) + { + //only enabled darkened cubemap mode when the scale calls for it. And not supported in ps20 when also using a 2nd bumpmap + envmap_variant = ((GetFloatParam( info.m_nEnvMapLightScale, params ) > 0.0f) && (g_pHardwareConfig->SupportsPixelShaders_2_b() || !hasBump2)) ? 2 : 1; + } + else + { + envmap_variant = 0; + } + + bool bSeamlessMapping = ( ( info.m_nSeamlessMappingScale != -1 ) && + ( params[info.m_nSeamlessMappingScale]->GetFloatValue() != 0.0 ) ); + + if ( bNeedRegenStaticCmds ) + { + pContextData->ResetStaticCmds(); + CCommandBufferBuilder< CFixedCommandStorageBuffer< 5000 > > staticCmdsBuf; + + int nLightingPreviewMode = IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER0 ) + 2 * IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER1 ); + if ( ( nLightingPreviewMode == ENABLE_FIXED_LIGHTING_OUTPUTNORMAL_AND_DEPTH ) && IsPC() ) + { + staticCmdsBuf.SetVertexShaderNearAndFarZ( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6 ); // Needed for SSAO + } + + if( !hasBaseTexture ) + { + if( hasEnvmap ) + { + // if we only have an envmap (no basetexture), then we want the albedo to be black. + staticCmdsBuf.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_BLACK ); + } + else + { + staticCmdsBuf.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_WHITE ); + } + } + staticCmdsBuf.BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP ); + + if ( g_pConfig->m_bPaintInGame && !r_twopasspaint.GetBool() ) + { + staticCmdsBuf.BindStandardTexture( SHADER_SAMPLER9, TEXTURE_PAINT ); + } + + if ( bSeamlessMapping ) + { + staticCmdsBuf.SetVertexShaderConstant4( + VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, + params[info.m_nSeamlessMappingScale]->GetFloatValue(),0,0,0 ); + } + staticCmdsBuf.StoreEyePosInPixelShaderConstant( 10 ); + staticCmdsBuf.SetPixelShaderFogParams( 11 ); + staticCmdsBuf.End(); + // now, copy buf + pContextData->m_pStaticCmds = new uint8[staticCmdsBuf.Size()]; + memcpy( pContextData->m_pStaticCmds, staticCmdsBuf.Base(), staticCmdsBuf.Size() ); + } + if ( pShaderShadow ) + { + + // Alpha test: FIXME: shouldn't this be handled in Shader_t::SetInitialShadowState + pShaderShadow->EnableAlphaTest( bIsAlphaTested ); + if ( info.m_nAlphaTestReference != -1 && params[info.m_nAlphaTestReference]->GetFloatValue() > 0.0f ) + { + pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GEQUAL, params[info.m_nAlphaTestReference]->GetFloatValue() ); + } + + pShader->SetDefaultBlendingShadowState( nAlphaChannelTextureVar, hasBaseTexture ); + + unsigned int flags = VERTEX_POSITION; + + // base texture + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, !bShaderSrgbRead ); + + if ( g_pConfig->m_bPaintInGame && !r_twopasspaint.GetBool() ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER9, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER9, !bShaderSrgbRead ); + } + + if ( hasLightWarpTexture ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER6, false ); + } + if ( bHasBlendModulateTexture ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER3, false ); + } + + if ( hasBaseTexture2 ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER7, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER7, !bShaderSrgbRead ); + } +// if( hasLightmap ) + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ) + { + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); + } + else + { + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, false ); + } + + if( hasEnvmap || ( IsX360() && hasFlashlight ) ) + { + if( hasEnvmap ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ) + { + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, true ); + } + } + flags |= VERTEX_TANGENT_S | VERTEX_TANGENT_T | VERTEX_NORMAL; + } + +#define TCOMBINE_NONE 12 // there is no detail texture + + int nDetailBlendMode = TCOMBINE_NONE; + + if ( hasDetailTexture ) + { + nDetailBlendMode = GetIntParam( info.m_nDetailTextureCombineMode, params ); + ITexture *pDetailTexture = params[info.m_nDetail]->GetTextureValue(); + if ( pDetailTexture->GetFlags() & TEXTUREFLAGS_SSBUMP ) + { + if ( hasBump ) + nDetailBlendMode = 10; // ssbump + else + nDetailBlendMode = 11; // ssbump_nobump + } + pShaderShadow->EnableTexture( SHADER_SAMPLER12, true ); + bool bSRGBState = ( nDetailBlendMode == 1 ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER12, bSRGBState ); + } + + // Hijack detail blend mode 9 for paint (this blend mode was previously skipped/unused in lightmappedgeneric) + if ( g_pConfig->m_bPaintInGame && !r_twopasspaint.GetBool() ) + { + nDetailBlendMode = 9; + } + + if( hasBump || hasNormalMapAlphaEnvmapMask ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + } + if( hasBump2 ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); + } + if( hasBumpMask ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER8, true ); + } + if( hasEnvmapMask ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); + } + + if( hasFlashlight && IsX360() ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER13, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER14, true ); + pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER14 ); + pShaderShadow->EnableTexture( SHADER_SAMPLER15, true ); + } + + if( hasVertexColor || hasBaseTexture2 || hasBump2 ) + { + flags |= VERTEX_COLOR; + } + + // texcoord0 : base texcoord + // texcoord1 : lightmap texcoord + // texcoord2 : lightmap texcoord offset + int numTexCoords; + + // if ( pShaderAPI->InEditorMode() ) +// if ( pShader->CanUseEditorMaterials() ) +// { +// numTexCoords = 1; +// } +// else + { + numTexCoords = 2; + if( hasBump ) + { + numTexCoords = 3; + } + } + + int nLightingPreviewMode = IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER0 ) + 2 * IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER1 ); + + pShaderShadow->VertexShaderVertexFormat( flags, numTexCoords, 0, 0 ); + + // Pre-cache pixel shaders + bool hasBaseAlphaEnvmapMask = IS_FLAG_SET( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + + int bumpmap_variant=(hasSSBump) ? 2 : hasBump; + bool bMaskedBlending=( (info.m_nMaskedBlending != -1) && + (params[info.m_nMaskedBlending]->GetIntValue() != 0) ); + + DECLARE_STATIC_VERTEX_SHADER( lightmappedgeneric_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( ENVMAP_MASK, hasEnvmapMask ); + SET_STATIC_VERTEX_SHADER_COMBO( TANGENTSPACE, params[info.m_nEnvmap]->IsTexture() ); + SET_STATIC_VERTEX_SHADER_COMBO( BUMPMAP, hasBump ); + SET_STATIC_VERTEX_SHADER_COMBO( DIFFUSEBUMPMAP, hasDiffuseBumpmap ); + SET_STATIC_VERTEX_SHADER_COMBO( VERTEXCOLOR, IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR ) ); + SET_STATIC_VERTEX_SHADER_COMBO( VERTEXALPHATEXBLENDFACTOR, hasBaseTexture2 || hasBump2 ); + SET_STATIC_VERTEX_SHADER_COMBO( BUMPMASK, hasBumpMask ); + SET_STATIC_VERTEX_SHADER_COMBO( LIGHTING_PREVIEW, nLightingPreviewMode ); + SET_STATIC_VERTEX_SHADER_COMBO( PARALLAX_MAPPING, bParallaxMapping ); + SET_STATIC_VERTEX_SHADER_COMBO( SEAMLESS, bSeamlessMapping ); + SET_STATIC_VERTEX_SHADER_COMBO( DETAILTEXTURE, hasDetailTexture ); + SET_STATIC_VERTEX_SHADER_COMBO( FANCY_BLENDING, bHasBlendModulateTexture ); + SET_STATIC_VERTEX_SHADER_COMBO( SELFILLUM, hasSelfIllum ); +#ifdef _X360 + SET_STATIC_VERTEX_SHADER_COMBO( FLASHLIGHT, hasFlashlight); +#endif + SET_STATIC_VERTEX_SHADER( lightmappedgeneric_vs20 ); + +#define TCOMBINE_NONE 12 // there is no detail texture + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( lightmappedgeneric_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE2, hasBaseTexture2 ); + SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP, bumpmap_variant ); + SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP2, hasBump2 ); + SET_STATIC_PIXEL_SHADER_COMBO( BUMPMASK, hasBumpMask ); + SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSEBUMPMAP, hasDiffuseBumpmap ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, envmap_variant ); + SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPMASK, hasEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( BASEALPHAENVMAPMASK, hasBaseAlphaEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, hasSelfIllum ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMALMAPALPHAENVMAPMASK, hasNormalMapAlphaEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURENOENVMAP, params[info.m_nBaseTextureNoEnvmap]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE2NOENVMAP, params[info.m_nBaseTexture2NoEnvmap]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER_COMBO( WARPLIGHTING, hasLightWarpTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( FANCY_BLENDING, bHasBlendModulateTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( MASKEDBLENDING, bMaskedBlending); + SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS, bSeamlessMapping ); + SET_STATIC_PIXEL_SHADER_COMBO( OUTLINE, bHasOutline ); + SET_STATIC_PIXEL_SHADER_COMBO( SOFTEDGES, bHasSoftEdges ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode ); +#ifdef _X360 + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, hasFlashlight); +#endif + SET_STATIC_PIXEL_SHADER_COMBO( PARALLAX_MAPPING, bParallaxMapping ); + SET_STATIC_PIXEL_SHADER_COMBO( SHADER_SRGB_READ, bShaderSrgbRead ); + SET_STATIC_PIXEL_SHADER_COMBO( LIGHTING_PREVIEW, nLightingPreviewMode ); + SET_STATIC_PIXEL_SHADER( lightmappedgeneric_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( lightmappedgeneric_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE2, hasBaseTexture2 ); + SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP, bumpmap_variant ); + SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP2, hasBump2 ); + SET_STATIC_PIXEL_SHADER_COMBO( BUMPMASK, hasBumpMask ); + SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSEBUMPMAP, hasDiffuseBumpmap ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, envmap_variant ); + SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPMASK, hasEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( BASEALPHAENVMAPMASK, hasBaseAlphaEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, hasSelfIllum ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMALMAPALPHAENVMAPMASK, hasNormalMapAlphaEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURENOENVMAP, params[info.m_nBaseTextureNoEnvmap]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE2NOENVMAP, params[info.m_nBaseTexture2NoEnvmap]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER_COMBO( WARPLIGHTING, hasLightWarpTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( FANCY_BLENDING, bHasBlendModulateTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( MASKEDBLENDING, bMaskedBlending); + SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS, bSeamlessMapping ); + SET_STATIC_PIXEL_SHADER_COMBO( OUTLINE, bHasOutline ); + SET_STATIC_PIXEL_SHADER_COMBO( SOFTEDGES, bHasSoftEdges ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode ); + SET_STATIC_PIXEL_SHADER_COMBO( PARALLAX_MAPPING, bParallaxMapping ); + SET_STATIC_PIXEL_SHADER_COMBO( SHADER_SRGB_READ, bShaderSrgbRead ); + SET_STATIC_PIXEL_SHADER_COMBO( LIGHTING_PREVIEW, nLightingPreviewMode ); + SET_STATIC_PIXEL_SHADER( lightmappedgeneric_ps20 ); + } + // HACK HACK HACK - enable alpha writes all the time so that we have them for + // underwater stuff and writing depth to dest alpha + // But only do it if we're not using the alpha already for translucency + pShaderShadow->EnableAlphaWrites( bFullyOpaque ); + + pShaderShadow->EnableSRGBWrite( true ); + + pShader->DefaultFog(); + + // NOTE: This isn't optimal. If $color2 is ever changed by a material + // proxy, this code won't get re-run, but too bad. No time to make this work + // Also note that if the lightmap scale factor changes + // all shadow state blocks will be re-run, so that's ok + float flLScale = pShaderShadow->GetLightMapScaleFactor(); + pShader->PI_BeginCommandBuffer(); + pShader->PI_SetModulationPixelShaderDynamicState( 21 ); + + // MAINTOL4DMERGEFIXME + // Need to reflect this change which is from this rel changelist since this constant set was moved from the dynamic block to here: + // Change 578692 by Alex@alexv_rel on 2008/06/04 18:07:31 + // + // Fix for portalareawindows in ep2 being rendered black. The color variable was being multipurposed for both the vs and ps differently where the ps doesn't care about alpha, but the vs does. Only applying the alpha2 DoD hack to the pixel shader constant where the alpha was never used in the first place and leaving alpha as is for the vs. + + // color[3] *= ( IS_PARAM_DEFINED( info.m_nAlpha2 ) && params[ info.m_nAlpha2 ]->GetFloatValue() > 0.0f ) ? params[ info.m_nAlpha2 ]->GetFloatValue() : 1.0f; + // pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 12, color ); + + pShader->PI_SetModulationPixelShaderDynamicState_LinearScale_ScaleInW( 12, flLScale ); + pShader->PI_SetModulationVertexShaderDynamicState_LinearScale( flLScale ); + pShader->PI_EndCommandBuffer(); + } // end shadow state + } // end shadow || regen display list + + if ( pShaderAPI && ( pContextData->m_bMaterialVarsChanged ) ) + { + // need to regenerate the semistatic cmds + pContextData->m_SemiStaticCmdsOut.Reset(); + pContextData->m_bMaterialVarsChanged = false; + + bool bHasBlendMaskTransform= ( + (info.m_nBlendMaskTransform != -1) && + (info.m_nMaskedBlending != -1) && + (params[info.m_nMaskedBlending]->GetIntValue() ) && + ( ! (params[info.m_nBumpTransform]->MatrixIsIdentity() ) ) ); + + // If we don't have a texture transform, we don't have + // to set vertex shader constants or run vertex shader instructions + // for the texture transform. + bool bHasTextureTransform = + !( params[info.m_nBaseTextureTransform]->MatrixIsIdentity() && + params[info.m_nBumpTransform]->MatrixIsIdentity() && + params[info.m_nBumpTransform2]->MatrixIsIdentity() && + params[info.m_nEnvmapMaskTransform]->MatrixIsIdentity() ); + + bHasTextureTransform |= bHasBlendMaskTransform; + + pContextData->m_bVertexShaderFastPath = !bHasTextureTransform; + + if( params[info.m_nDetail]->IsTexture() ) + { + pContextData->m_bVertexShaderFastPath = false; + } + int nTransformToLoad = info.m_nBlendMaskTransform; + if( ( hasBump || hasSSBump ) && hasDetailTexture && !hasSelfIllum && !bHasBlendModulateTexture ) + { + nTransformToLoad = info.m_nBumpTransform; + } + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( + VERTEX_SHADER_SHADER_SPECIFIC_CONST_10, nTransformToLoad ); + + if ( ! pContextData->m_bVertexShaderFastPath ) + { + bool bSeamlessMapping = ( ( info.m_nSeamlessMappingScale != -1 ) && + ( params[info.m_nSeamlessMappingScale]->GetFloatValue() != 0.0 ) ); + bool hasEnvmapMask = params[info.m_nEnvmapMask]->IsTexture(); + if (!bSeamlessMapping ) + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, info.m_nBaseTextureTransform ); + // If we have a detail texture, then the bump texcoords are the same as the base texcoords. + if( hasBump && !hasDetailTexture ) + { + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, info.m_nBumpTransform ); + } + if( hasEnvmapMask ) + { + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, info.m_nEnvmapMaskTransform ); + } + else if ( hasBump2 ) + { + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, info.m_nBumpTransform2 ); + } + } + pContextData->m_SemiStaticCmdsOut.SetEnvMapTintPixelShaderDynamicState( 0, info.m_nEnvmapTint ); + + if ( hasDetailTexture ) + { + float detailTintAndBlend[4] = {1, 1, 1, 1}; + + if ( info.m_nDetailTint != -1 ) + { + params[info.m_nDetailTint]->GetVecValue( detailTintAndBlend, 3 ); + } + + detailTintAndBlend[3] = fDetailBlendFactor; + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 8, detailTintAndBlend ); + } + + float envmapTintVal[4]; + float selfIllumTintVal[4]; + params[info.m_nEnvmapTint]->GetVecValue( envmapTintVal, 3 ); + params[info.m_nSelfIllumTint]->GetVecValue( selfIllumTintVal, 3 ); + float envmapContrast = params[info.m_nEnvmapContrast]->GetFloatValue(); + float envmapSaturation = params[info.m_nEnvmapSaturation]->GetFloatValue(); + float fresnelReflection = params[info.m_nFresnelReflection]->GetFloatValue(); + bool hasEnvmap = params[info.m_nEnvmap]->IsTexture(); + int envmap_variant; //0 = no envmap, 1 = regular, 2 = darken in shadow mode + if( hasEnvmap ) + { + //only enabled darkened cubemap mode when the scale calls for it. And not supported in ps20 when also using a 2nd bumpmap + envmap_variant = ((GetFloatParam( info.m_nEnvMapLightScale, params ) > 0.0f) && (g_pHardwareConfig->SupportsPixelShaders_2_b() || !hasBump2)) ? 2 : 1; + } + else + { + envmap_variant = 0; + } + + pContextData->m_bPixelShaderFastPath = true; + bool bUsingContrastOrSaturation = hasEnvmap && ( ( (envmapContrast != 0.0f) && (envmapContrast != 1.0f) ) || (envmapSaturation != 1.0f) ); + bool bUsingFresnel = hasEnvmap && (fresnelReflection != 1.0f); + bool bUsingSelfIllumTint = IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) && (selfIllumTintVal[0] != 1.0f || selfIllumTintVal[1] != 1.0f || selfIllumTintVal[2] != 1.0f); + if ( bUsingContrastOrSaturation || bUsingFresnel || bUsingSelfIllumTint || !g_pConfig->bShowSpecular ) + { + pContextData->m_bPixelShaderFastPath = false; + } + if( !pContextData->m_bPixelShaderFastPath ) + { + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstants( 2, 3 ); + pContextData->m_SemiStaticCmdsOut.OutputConstantData( params[info.m_nEnvmapContrast]->GetVecValue() ); + pContextData->m_SemiStaticCmdsOut.OutputConstantData( params[info.m_nEnvmapSaturation]->GetVecValue() ); + float flFresnel = params[info.m_nFresnelReflection]->GetFloatValue(); + // [ 0, 0, 1-R(0), R(0) ] + pContextData->m_SemiStaticCmdsOut.OutputConstantData4( 0., 0., 1.0 - flFresnel, flFresnel ); + + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 7, params[info.m_nSelfIllumTint]->GetVecValue() ); + } + else + { + if ( bHasOutline ) + { + float flOutlineParms[8] = { GetFloatParam( info.m_nOutlineStart0, params ), + GetFloatParam( info.m_nOutlineStart1, params ), + GetFloatParam( info.m_nOutlineEnd0, params ), + GetFloatParam( info.m_nOutlineEnd1, params ), + 0,0,0, + GetFloatParam( info.m_nOutlineAlpha, params ) }; + if ( info.m_nOutlineColor != -1 ) + { + params[info.m_nOutlineColor]->GetVecValue( flOutlineParms + 4, 3 ); + } + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 2, flOutlineParms, 2 ); + } + + if ( bHasSoftEdges ) + { + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant4( + 4, GetFloatParam( info.m_nEdgeSoftnessStart, params ), + GetFloatParam( info.m_nEdgeSoftnessEnd, params ), + 0,0 ); + } + } + + // parallax and cubemap light scale mapping parms (c20) + if ( bParallaxMapping || (envmap_variant == 2) ) + { + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant4( 20, GetFloatParam( info.m_nHeightScale, params), GetFloatParam( info.m_nEnvMapLightScale, params), 0, 0 ); + } + + // texture binds + if( hasBaseTexture ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER0, info.m_nBaseTexture, info.m_nBaseTextureFrame ); + } + // handle mat_fullbright 2 + bool bLightingOnly = mat_fullbright.GetInt() == 2 && !IS_FLAG_SET( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + if( bLightingOnly ) + { + // BASE TEXTURE + if( hasSelfIllum ) + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY_ALPHA_ZERO ); + } + else + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY ); + } + + // BASE TEXTURE 2 + if( hasBaseTexture2 ) + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER7, TEXTURE_GREY ); + } + + // DETAIL TEXTURE + if( hasDetailTexture ) + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER12, TEXTURE_GREY ); + } + + // disable color modulation + float color[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + pContextData->m_SemiStaticCmdsOut.SetVertexShaderConstant( VERTEX_SHADER_MODULATION_COLOR, color ); + + // turn off environment mapping + envmapTintVal[0] = 0.0f; + envmapTintVal[1] = 0.0f; + envmapTintVal[2] = 0.0f; + } + + // always set the transform for detail textures since I'm assuming that you'll + // always have a detailscale. + if( hasDetailTexture ) + { + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, info.m_nBaseTextureTransform, info.m_nDetailScale ); + } + + if( hasBaseTexture2 ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER7, info.m_nBaseTexture2, info.m_nBaseTexture2Frame ); + } + if( hasDetailTexture ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER12, info.m_nDetail, info.m_nDetailFrame ); + } + + if( hasBump || hasNormalMapAlphaEnvmapMask ) + { + if( !g_pConfig->m_bFastNoBump ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER4, info.m_nBumpmap, info.m_nBumpFrame ); + } + else + { + if( hasSSBump ) + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER4, TEXTURE_SSBUMP_FLAT ); + } + else + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER4, TEXTURE_NORMALMAP_FLAT ); + } + } + } + if( hasBump2 ) + { + if( !g_pConfig->m_bFastNoBump ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER5, info.m_nBumpmap2, info.m_nBumpFrame2 ); + } + else + { + if( hasSSBump ) + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER5, TEXTURE_NORMALMAP_FLAT ); + } + else + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER5, TEXTURE_SSBUMP_FLAT ); + } + } + } + if( hasBumpMask ) + { + if( !g_pConfig->m_bFastNoBump ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER8, info.m_nBumpMask, -1 ); + } + else + { + // this doesn't make sense + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER8, TEXTURE_NORMALMAP_FLAT ); + } + } + + if( hasEnvmapMask ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER5, info.m_nEnvmapMask, info.m_nEnvmapMaskFrame ); + } + + if ( hasLightWarpTexture ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER6, info.m_nLightWarpTexture, -1 ); + } + + if ( bHasBlendModulateTexture ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER3, info.m_nBlendModulateTexture, -1 ); + } + + if ( hasFlashlight && IsX360() ) + { + pContextData->m_SemiStaticCmdsOut.SetVertexShaderFlashlightState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6 ); + + CBCmdSetPixelShaderFlashlightState_t state; + state.m_LightSampler = SHADER_SAMPLER13; + state.m_DepthSampler = SHADER_SAMPLER14; + state.m_ShadowNoiseSampler = SHADER_SAMPLER15; + state.m_nColorConstant = 28; + state.m_nAttenConstant = 13; + state.m_nOriginConstant = 14; + state.m_nDepthTweakConstant = 19; + state.m_nScreenScaleConstant = 31; + state.m_nWorldToTextureConstant = -1; + state.m_bFlashlightNoLambert = false; + state.m_bSinglePassFlashlight = bSinglePassFlashlight; + pContextData->m_SemiStaticCmdsOut.SetPixelShaderFlashlightState( state ); + } + + pContextData->m_SemiStaticCmdsOut.End(); + } + } + DYNAMIC_STATE + { + CCommandBufferBuilder< CFixedCommandStorageBuffer< 1000 > > DynamicCmdsOut; + DynamicCmdsOut.Call( pContextData->m_pStaticCmds ); + DynamicCmdsOut.Call( pContextData->m_SemiStaticCmdsOut.Base() ); + + bool hasEnvmap = params[info.m_nEnvmap]->IsTexture(); + + if( hasEnvmap ) + { + DynamicCmdsOut.BindTexture( pShader, SHADER_SAMPLER2, info.m_nEnvmap, info.m_nEnvmapFrame ); + } + + bool bVertexShaderFastPath = pContextData->m_bVertexShaderFastPath; + + int nFixedLightingMode = pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_ENABLE_FIXED_LIGHTING ); + if( nFixedLightingMode != ENABLE_FIXED_LIGHTING_NONE ) + { + if ( pContextData->m_bPixelShaderForceFastPathBecauseOutline ) + { + nFixedLightingMode = ENABLE_FIXED_LIGHTING_NONE; + } + else + { + bVertexShaderFastPath = false; + } + } + + bool bWorldNormal = ( nFixedLightingMode == ENABLE_FIXED_LIGHTING_OUTPUTNORMAL_AND_DEPTH ); + if ( bWorldNormal && IsPC() ) + { + float vEyeDir[4]; + pShaderAPI->GetWorldSpaceCameraDirection( vEyeDir ); + + float flFarZ = pShaderAPI->GetFarZ(); + vEyeDir[0] /= flFarZ; // Divide by farZ for SSAO algorithm + vEyeDir[1] /= flFarZ; + vEyeDir[2] /= flFarZ; + DynamicCmdsOut.SetVertexShaderConstant4( 12, vEyeDir[0], vEyeDir[1], vEyeDir[2], 1.0f ); + } + + MaterialFogMode_t fogType = pShaderAPI->GetSceneFogMode(); + DECLARE_DYNAMIC_VERTEX_SHADER( lightmappedgeneric_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( FASTPATH, bVertexShaderFastPath ); + SET_DYNAMIC_VERTEX_SHADER_CMD( DynamicCmdsOut, lightmappedgeneric_vs20 ); + + bool bPixelShaderFastPath = pContextData->m_bPixelShaderFastPath; + + if ( nFixedLightingMode != ENABLE_FIXED_LIGHTING_NONE ) + { + bPixelShaderFastPath = false; + } + bool bWriteDepthToAlpha; + bool bWriteWaterFogToAlpha; + if( pContextData->m_bFullyOpaque ) + { + bWriteDepthToAlpha = pShaderAPI->ShouldWriteDepthToDestAlpha(); + bWriteWaterFogToAlpha = (fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z); + AssertMsg( !(bWriteDepthToAlpha && bWriteWaterFogToAlpha), "Can't write two values to alpha at the same time." ); + } + else + { + //can't write a special value to dest alpha if we're actually using as-intended alpha + bWriteDepthToAlpha = false; + bWriteWaterFogToAlpha = false; + } + + bool bFlashlightShadows = false; + bool bUberlight = false; + if( hasFlashlight && IsX360() ) + { + pShaderAPI->GetFlashlightShaderInfo( &bFlashlightShadows, &bUberlight ); + } + else + { + // only do ambient light when not using flashlight + static ConVarRef mat_ambient_light_r_forced( "mat_ambient_light_r_forced" ); + static ConVarRef mat_ambient_light_g_forced( "mat_ambient_light_g_forced" ); + static ConVarRef mat_ambient_light_b_forced( "mat_ambient_light_b_forced" ); + + float vAmbientColor[4] = { mat_ambient_light_r_forced.GetFloat() != -1.0f ? mat_ambient_light_r_forced.GetFloat() : mat_ambient_light_r.GetFloat(), + mat_ambient_light_g_forced.GetFloat() != -1.0f ? mat_ambient_light_g_forced.GetFloat() : mat_ambient_light_g.GetFloat(), + mat_ambient_light_b_forced.GetFloat() != -1.0f ? mat_ambient_light_b_forced.GetFloat() : mat_ambient_light_b.GetFloat(), + 0.0f }; + if ( mat_fullbright.GetInt() == 1 ) + { + vAmbientColor[0] = vAmbientColor[1] = vAmbientColor[2] = 0.0f; + } + DynamicCmdsOut.SetPixelShaderConstant( 31, vAmbientColor, 1 ); + } + + float envmapContrast = params[info.m_nEnvmapContrast]->GetFloatValue(); + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( lightmappedgeneric_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FASTPATH, bPixelShaderFastPath || pContextData->m_bPixelShaderForceFastPathBecauseOutline ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FASTPATHENVMAPCONTRAST, bPixelShaderFastPath && envmapContrast == 1.0f ); + + // Don't write fog to alpha if we're using translucency + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bWriteDepthToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER_CMD( DynamicCmdsOut, lightmappedgeneric_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( lightmappedgeneric_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FASTPATH, bPixelShaderFastPath ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FASTPATHENVMAPCONTRAST, bPixelShaderFastPath && envmapContrast == 1.0f ); + + // Don't write fog to alpha if we're using translucency + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_CMD( DynamicCmdsOut, lightmappedgeneric_ps20 ); + } + + DynamicCmdsOut.End(); + pShaderAPI->ExecuteCommandBuffer( DynamicCmdsOut.Base() ); + } + pShader->Draw(); + + if( IsPC() && (IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) != 0) && pContextData->m_bFullyOpaqueWithoutAlphaTest ) + { + //Alpha testing makes it so we can't write to dest alpha + //Writing to depth makes it so later polygons can't write to dest alpha either + //This leads to situations with garbage in dest alpha. + + //Fix it now by converting depth to dest alpha for any pixels that just wrote. + pShader->DrawEqualDepthToDestAlpha(); + } +} diff --git a/materialsystem/stdshaders/lightmappedgeneric_dx9_helper.h b/materialsystem/stdshaders/lightmappedgeneric_dx9_helper.h new file mode 100644 index 00000000..a0879078 --- /dev/null +++ b/materialsystem/stdshaders/lightmappedgeneric_dx9_helper.h @@ -0,0 +1,152 @@ +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef LIGHTMAPPEDGENERIC_DX9_HELPER_H +#define LIGHTMAPPEDGENERIC_DX9_HELPER_H + +#include +#include "BaseVSShader.h" +#include "shaderlib/commandbuilder.h" + + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct LightmappedGeneric_DX9_Vars_t +{ + LightmappedGeneric_DX9_Vars_t() { memset( this, 0xFF, sizeof(LightmappedGeneric_DX9_Vars_t) ); } + + int m_nBaseTexture; + int m_nBaseTextureFrame; + int m_nBaseTextureTransform; + int m_nAlbedo; + int m_nSelfIllumTint; + + int m_nAlpha2; // Hack for DoD srgb blend issues on overlays + + int m_nDetail; + int m_nDetailFrame; + int m_nDetailScale; + int m_nDetailTextureCombineMode; + int m_nDetailTextureBlendFactor; + int m_nDetailTint; + + int m_nEnvmap; + int m_nEnvmapFrame; + int m_nEnvmapMask; + int m_nEnvmapMaskFrame; + int m_nEnvmapMaskTransform; + int m_nEnvmapTint; + int m_nBumpmap; + int m_nBumpFrame; + int m_nBumpTransform; + int m_nEnvmapContrast; + int m_nEnvmapSaturation; + int m_nFresnelReflection; + int m_nNoDiffuseBumpLighting; + int m_nBumpmap2; + int m_nBumpFrame2; + int m_nBumpTransform2; + int m_nBumpMask; + int m_nBaseTexture2; + int m_nBaseTexture2Frame; + int m_nBaseTextureNoEnvmap; + int m_nBaseTexture2NoEnvmap; + int m_nDetailAlphaMaskBaseTexture; + int m_nFlashlightTexture; + int m_nFlashlightTextureFrame; + int m_nLightWarpTexture; + int m_nBlendModulateTexture; + int m_nMaskedBlending; + int m_nBlendMaskTransform; + int m_nSelfShadowedBumpFlag; + int m_nSeamlessMappingScale; + int m_nAlphaTestReference; + + int m_nSoftEdges; + int m_nEdgeSoftnessStart; + int m_nEdgeSoftnessEnd; + + int m_nOutline; + int m_nOutlineColor; + int m_nOutlineAlpha; + int m_nOutlineStart0; + int m_nOutlineStart1; + int m_nOutlineEnd0; + int m_nOutlineEnd1; + + int m_nParallaxMap; + int m_nHeightScale; + + int m_nShaderSrgbRead360; + + int m_nEnvMapLightScale; + + int m_nFoW; + + int m_nPaintSplatNormal; + int m_nPaintSplatEnvMap; +}; + +class CLightmappedGeneric_DX9_Context : public CBasePerMaterialContextData +{ +public: + uint8 *m_pStaticCmds; + CCommandBufferBuilder< CFixedCommandStorageBuffer< 900 > > m_SemiStaticCmdsOut; + + bool m_bVertexShaderFastPath; + bool m_bPixelShaderFastPath; + bool m_bPixelShaderForceFastPathBecauseOutline; + bool m_bFullyOpaque; + bool m_bFullyOpaqueWithoutAlphaTest; + + CLightmappedGeneric_DX9_Context *m_pPaintSubcontext; //passed off to the lightmapped paint shader if we're running that + + void ResetStaticCmds( void ) + { + if ( m_pStaticCmds ) + { + delete[] m_pStaticCmds; + m_pStaticCmds = NULL; + } + } + + CLightmappedGeneric_DX9_Context( void ) + { + m_pStaticCmds = NULL; + m_pPaintSubcontext = NULL; + } + + ~CLightmappedGeneric_DX9_Context( void ) + { + ResetStaticCmds(); + + if( m_pPaintSubcontext ) + { + delete m_pPaintSubcontext; + } + } + +}; + +void InitParamsLightmappedGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, LightmappedGeneric_DX9_Vars_t &info ); +void InitLightmappedGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, LightmappedGeneric_DX9_Vars_t &info ); +void DrawLightmappedGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, + IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, + LightmappedGeneric_DX9_Vars_t &info, CBasePerMaterialContextData **pContextDataPtr ); + + +#endif // LIGHTMAPPEDGENERIC_DX9_HELPER_H diff --git a/materialsystem/stdshaders/lightmappedgeneric_flashlight_vs20.fxc b/materialsystem/stdshaders/lightmappedgeneric_flashlight_vs20.fxc new file mode 100644 index 00000000..5416dcdb --- /dev/null +++ b/materialsystem/stdshaders/lightmappedgeneric_flashlight_vs20.fxc @@ -0,0 +1,191 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// +// +// Purpose: +// +//===========================================================================// + +// STATIC: "NORMALMAP" "0..1" +// STATIC: "WORLDVERTEXTRANSITION" "0..1" +// STATIC: "SEAMLESS" "0..1" +// STATIC: "DETAIL" "0..1" + +#include "common_fog_vs_supportsvertexfog_fxc.h" +#include "common_vs_fxc.h" + +const float3 g_FlashlightPos : register( SHADER_SPECIFIC_CONST_0 ); +const float4x4 g_FlashlightWorldToTexture : register( SHADER_SPECIFIC_CONST_1 ); +const float4 g_FlashlightAttenuationFactors : register( SHADER_SPECIFIC_CONST_5 ); + +#if SEAMLESS +const float4 SeamlessScale : register( SHADER_SPECIFIC_CONST_6 ); +#define SEAMLESS_SCALE (SeamlessScale.x) +#endif +const float4 cBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_6 ); +const float4 cNormalMapOrDetailTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_8 ); + +static const int g_FogType = DOWATERFOG; + +struct VS_INPUT +{ + float3 vPos : POSITION; //This HAS to match lightmappedgeneric_vs20.fxc's position input. Otherwise depth fighting errors occur on the 360 + float4 vNormal : NORMAL; + float2 vBaseTexCoord : TEXCOORD0; +#if WORLDVERTEXTRANSITION + float2 vLightmapTexCoord : TEXCOORD1; + float4 vColor : COLOR0; +#endif +#if NORMALMAP + float3 vTangentS : TANGENT; + float3 vTangentT : BINORMAL; +#endif +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; +#if HARDWAREFOGBLEND + float fog : FOG; +#endif + + float4 spotTexCoord : TEXCOORD0; + +#if SEAMLESS + float3 SeamlessTexCoord : TEXCOORD1; +#else + float2 baseTexCoord : TEXCOORD1; +#endif + +#if NORMALMAP + float3 tangentPosToLightVector : TEXCOORD2; + float2 normalMapTexCoord : TEXCOORD3; +#else + float3 worldPosToLightVector : TEXCOORD2; + float3 normal : TEXCOORD3; +#endif + + float2 detailCoords : TEXCOORD4; + float4 worldPos_worldTransition : TEXCOORD5; +#if HARDWAREFOGBLEND || DOPIXELFOG + float3 projPos_fogFactorW : TEXCOORD6; +#else + float4 projPos_fogFactorW : TEXCOORD6; +#endif + float4 vNormalSqr : COLOR1; +}; + +float RemapValClamped( float val, float A, float B, float C, float D) +{ + float cVal = (val - A) / (B - A); + cVal = saturate( cVal ); + + return C + (D - C) * cVal; +} + + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = (VS_OUTPUT)0; + + float3 vObjNormal; + DecompressVertex_Normal( v.vNormal, vObjNormal ); + + float4 projPos; + float3 worldPos; + float3 worldNormal; + float3 eyeVector; + + //Projection math HAS to match lightmappedgeneric_vs20.fxc's math exactly. Otherwise depth fighting errors occur on the 360 + projPos = mul( float4( v.vPos, 1 ), cModelViewProj ); + o.projPos = projPos; + o.projPos_fogFactorW.xyz = projPos.xyw; + + worldPos = mul( float4( v.vPos, 1 ), cModel[0] ); + worldNormal = mul( vObjNormal, ( float3x3 )cModel[0] ); + + o.worldPos_worldTransition = float4( worldPos.xyz, 1.0f ); + +#if HARDWAREFOGBLEND + o.fog = CalcFixedFunctionFog( worldPos, g_FogType ); +#endif + +#if !DOPIXELFOG && !HARDWAREFOGBLEND + o.projPos_fogFactorW.w = CalcNonFixedFunctionFog( worldPos, g_FogType ); +#endif + +#if NORMALMAP + float3 worldTangentS = mul( v.vTangentS, cModel[0] ); + float3 worldTangentT = mul( v.vTangentT, cModel[0] ); +#endif +#if SEAMLESS + float3 vNormal=normalize( worldNormal ); + o.vNormalSqr.xyz = vNormal * vNormal; // sums to 1. + o.SeamlessTexCoord = SEAMLESS_SCALE*worldPos; + + // Generate new tangent and binormal with seamless projection + #if NORMALMAP + // Brute-force for prototype - This must match the projection in the pixel shader! + //float3 vVecX = { 1.0f, 0.0f, 0.0f }; + //float3 vVecY = { 0.0f, 1.0f, 0.0f }; + //float3 vVecZ = { 0.0f, 0.0f, 1.0f }; + //worldTangentS.xyz = normalize( ( o.vNormalSqr.x * vVecZ.xyz ) + ( o.vNormalSqr.y * vVecX.xyz ) + ( o.vNormalSqr.z * vVecX.xyz ) ); + //worldTangentT.xyz = normalize( ( o.vNormalSqr.x * vVecY.xyz ) + ( o.vNormalSqr.y * vVecZ.xyz ) + ( o.vNormalSqr.z * vVecY.xyz ) ); + + // Optimized version - This must match the projection in the pixel shader! + worldTangentS.xyz = normalize( float3( o.vNormalSqr.y + o.vNormalSqr.z, 0.0f, o.vNormalSqr.x ) ); + worldTangentT.xyz = normalize( float3( 0.0f, o.vNormalSqr.x + o.vNormalSqr.z, o.vNormalSqr.y ) ); + #endif +#else +#if (SEAMLESS == 0 ) + o.baseTexCoord.x = dot( v.vBaseTexCoord, cBaseTexCoordTransform[0] ) + cBaseTexCoordTransform[0].w; + o.baseTexCoord.y = dot( v.vBaseTexCoord, cBaseTexCoordTransform[1] ) + cBaseTexCoordTransform[1].w; +#endif +#endif + + float4 spotTexCoord = mul( float4( worldPos, 1.0f ), g_FlashlightWorldToTexture ); + o.spotTexCoord = spotTexCoord.xyzw; + + float3 worldPosToLightVector = g_FlashlightPos - worldPos; +#if NORMALMAP + +#if (DETAIL == 0) + o.normalMapTexCoord.x = dot( v.vBaseTexCoord, cNormalMapOrDetailTexCoordTransform[0] ) + cNormalMapOrDetailTexCoordTransform[0].w; + o.normalMapTexCoord.y = dot( v.vBaseTexCoord, cNormalMapOrDetailTexCoordTransform[1] ) + cNormalMapOrDetailTexCoordTransform[1].w; +#else + +#if SEAMLESS + o.normalMapTexCoord = v.vBaseTexCoord; +#else + o.normalMapTexCoord = o.baseTexCoord; +#endif + +#endif + + o.tangentPosToLightVector.x = dot( worldPosToLightVector, worldTangentS ); + o.tangentPosToLightVector.y = dot( worldPosToLightVector, worldTangentT ); + o.tangentPosToLightVector.z = dot( worldPosToLightVector, worldNormal ); +#else + o.worldPosToLightVector = worldPosToLightVector; + o.normal = worldNormal; +#endif + +#if DETAIL + o.detailCoords.x = dot( v.vBaseTexCoord, cNormalMapOrDetailTexCoordTransform[0] ) + cNormalMapOrDetailTexCoordTransform[0].w; + o.detailCoords.y = dot( v.vBaseTexCoord, cNormalMapOrDetailTexCoordTransform[1] ) + cNormalMapOrDetailTexCoordTransform[1].w; +#else + o.detailCoords = float2(0,0); +#endif + + //float3 delta = worldPosToLightVector; + //float distSquared = dot( delta, delta ); + //float dist = sqrt( distSquared ); + //float farZ = g_FlashlightAttenuationFactors.w; + //float endFalloffFactor = RemapValClamped( dist, farZ, 0.6f * farZ, 0.0f, 1.0f ); + //o.projPos_atten.w = endFalloffFactor * dot( g_FlashlightAttenuationFactors, float3( 1.0f, 1.0f/dist, 1.0f/distSquared ) ); + //o.projPos_atten.w = saturate( o.projPos_atten.w ); + +#if WORLDVERTEXTRANSITION + o.worldPos_worldTransition.w = v.vColor.w; +#endif + + return o; +} diff --git a/materialsystem/stdshaders/lightmappedgeneric_ps11.fxc b/materialsystem/stdshaders/lightmappedgeneric_ps11.fxc new file mode 100644 index 00000000..9870ad28 --- /dev/null +++ b/materialsystem/stdshaders/lightmappedgeneric_ps11.fxc @@ -0,0 +1,122 @@ +// STATIC: "BASETEXTURE" "0..1" +// STATIC: "ENVMAP" "0..1" +// STATIC: "ENVMAPMASK" "0..1" +// STATIC: "SELFILLUM" "0..1" +// STATIC: "BASEALPHAENVMAPMASK" "0..1" + +// SKIP: !$ENVMAP && ( $BASEALPHAENVMAPMASK || $ENVMAPMASK ) +// SKIP: !$BASETEXTURE && $BASEALPHAENVMAPMASK +// SKIP: $BASEALPHAENVMAPMASK && $ENVMAPMASK +// SKIP: !$BASETEXTURE && $BASEALPHAENVMAPMASK +// SKIP: $SELFILLUM && $BASEALPHAENVMAPMASK +// SKIP: !$BASETEXTURE && $SELFILLUM + +const float3 g_OverbrightFactor : register( c0 ); +const float3 g_SelfIllumTint : register( c1 ); +const float3 g_EnvmapTint : register( c2 ); + +sampler BaseTextureSampler : register( s0 ); +sampler LightmapSampler : register( s1 ); +sampler EnvmapSampler : register( s2 ); +sampler EnvmapMaskSampler : register( s3 ); + +//sampler DetailSampler : register( s3 ); + +struct PS_INPUT +{ + float2 baseTexCoord : TEXCOORD0; + float2 lightmapTexCoord : TEXCOORD1; + float3 envmapTexCoord : TEXCOORD2; + float2 envmapMaskTexCoord : TEXCOORD3; + float4 vertexColor : COLOR0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + bool bBaseTexture = BASETEXTURE ? true : false; + bool bEnvmap = ENVMAP ? true : false; + bool bEnvmapMask = ENVMAPMASK ? true : false; + bool bSelfIllum = SELFILLUM ? true : false; + bool bBaseAlphaEnvmapMask = BASEALPHAENVMAPMASK ? true : false; + +#if 1 + float4 baseColor = float4( 1.0f, 1.0f, 1.0f, 1.0f ); + if( bBaseTexture ) + { + baseColor = tex2D( BaseTextureSampler, i.baseTexCoord ); + } + + float3 specularFactor = 1.0f; + + if( bEnvmapMask ) + { + specularFactor *= tex2D( EnvmapMaskSampler, i.envmapMaskTexCoord ).xyz; + } + if( bBaseAlphaEnvmapMask ) + { + specularFactor *= 1.0 - baseColor.a; // this blows! + } + + float3 diffuseLighting = tex2D( LightmapSampler, i.lightmapTexCoord ); + + float3 albedo = float3( 1.0f, 1.0f, 1.0f ); + float alpha = 1.0f; + if( bBaseTexture ) + { + albedo *= baseColor; + if( !bBaseAlphaEnvmapMask && !bSelfIllum ) + { + alpha *= baseColor.a; + } + } + + // The vertex color contains the modulation color + vertex color combined + albedo *= i.vertexColor; + alpha *= i.vertexColor.a; // not sure about this one + + float3 diffuseComponent = ( albedo * diffuseLighting * 2.0f ) * g_OverbrightFactor; + + if( bSelfIllum ) + { + float3 selfIllumComponent = g_SelfIllumTint * albedo; + diffuseComponent = lerp( diffuseComponent, selfIllumComponent, baseColor.a ); + } + + float3 specularLighting = float3( 0.0f, 0.0f, 0.0f ); + + if( bEnvmap ) + { + specularLighting = tex2D( EnvmapSampler, i.envmapTexCoord ); + specularLighting *= specularFactor; + specularLighting *= g_EnvmapTint; + } + + float3 result = diffuseComponent + specularLighting; + return float4( result, alpha ); +#endif + +#if 0 + float4 baseColor = float4( 1.0f, 1.0f, 1.0f, 1.0f ); + float3 diffuseLighting = tex2D( LightmapSampler, i.lightmapTexCoord ); + + float3 albedo = float3( 1.0f, 1.0f, 1.0f ); + float alpha = 1.0f; + albedo *= i.vertexColor; + alpha *= i.vertexColor.a; // not sure about this one + + float3 diffuseComponent = ( albedo * diffuseLighting * 2.0f ) * g_OverbrightFactor; + float3 result = diffuseComponent; + return float4( result, alpha ); +#endif + +#if 0 + float4 result; + + result.rgb = tex2D( LightmapSampler, i.lightmapTexCoord ).rgb * i.vertexColor.rgb; + result.a = i.vertexColor.a; + result.rgb = ( result.rgb * g_OverbrightFactor ) * 2.0f; + return result; +#endif +} + + diff --git a/materialsystem/stdshaders/lightmappedgeneric_ps2_3_x.h b/materialsystem/stdshaders/lightmappedgeneric_ps2_3_x.h new file mode 100644 index 00000000..fed7f292 --- /dev/null +++ b/materialsystem/stdshaders/lightmappedgeneric_ps2_3_x.h @@ -0,0 +1,651 @@ +// SKIP: $BUMPMAP2 && $WARPLIGHTING +// SKIP: $WARPLIGHTING && ( $DETAIL_BLEND_MODE != 12 ) +// SKIP: $ENVMAPMASK && $BUMPMAP +// SKIP: $NORMALMAPALPHAENVMAPMASK && $BASEALPHAENVMAPMASK +// SKIP: $NORMALMAPALPHAENVMAPMASK && $ENVMAPMASK +// SKIP: $BASEALPHAENVMAPMASK && $ENVMAPMASK +// SKIP: $BASEALPHAENVMAPMASK && $SELFILLUM +// SKIP: !$FASTPATH && $FASTPATHENVMAPCONTRAST +// SKIP: !$FASTPATH && $FASTPATHENVMAPTINT +// SKIP: !$BUMPMAP && $DIFFUSEBUMPMAP +// SKIP: !$BUMPMAP && $BUMPMAP2 +// SKIP: $ENVMAPMASK && $BUMPMAP2 +// SKIP: $BASETEXTURENOENVMAP && ( !$BASETEXTURE2 || !$CUBEMAP ) +// SKIP: $BASETEXTURE2NOENVMAP && ( !$BASETEXTURE2 || !$CUBEMAP ) +// SKIP: $BASEALPHAENVMAPMASK && $BUMPMAP +// SKIP: $PARALLAXMAP && ( $DETAIL_BLEND_MODE != 12 ) +// SKIP: $SEAMLESS && $PARALLAXMAP +// SKIP: $SEAMLESS && ( $DETAIL_BLEND_MODE != 12 ) +// SKIP: $SEAMLESS && $MASKEDBLENDING +// SKIP: $BUMPMASK && ( $SEAMLESS || ( $DETAILTEXTURE != 12 ) || $SELFILLUM || $BASETEXTURENOENVMAP || $BASETEXTURE2 ) + +// 360 compiler craps out on some combo in this family. Content doesn't use blendmode 10 anyway +// SKIP: $FASTPATH && $PIXELFOGTYPE && $BASETEXTURE2 && $CUBEMAP && ($DETAIL_BLEND_MODE == 10 ) [XBOX] + +// Too many instructions to do this all at once: +// SKIP: $FANCY_BLENDING && $BUMPMAP && $DETAILTEXTURE + +#define USE_32BIT_LIGHTMAPS_ON_360 //uncomment to use 32bit lightmaps, be sure to keep this in sync with the same #define in materialsystem/cmatlightmaps.cpp + +// NOTE: This has to be before inclusion of common_lightmappedgeneric_fxc.h to get the vertex format right! +#if ( DETAIL_BLEND_MODE == 12 ) +#define DETAILTEXTURE 0 +#else +#define DETAILTEXTURE 1 +#endif + +#include "common_ps_fxc.h" +#include "common_flashlight_fxc.h" +#define PIXELSHADER +#include "common_lightmappedgeneric_fxc.h" + +#if SEAMLESS +#define USE_FAST_PATH 1 +#else +#define USE_FAST_PATH FASTPATH +#endif + +const float4 g_EnvmapTint : register( c0 ); + +#if USE_FAST_PATH == 1 + +# if FASTPATHENVMAPCONTRAST == 0 +static const float3 g_EnvmapContrast = { 0.0f, 0.0f, 0.0f }; +# else +static const float3 g_EnvmapContrast = { 1.0f, 1.0f, 1.0f }; +# endif +static const float3 g_EnvmapSaturation = { 1.0f, 1.0f, 1.0f }; +static const float g_FresnelReflection = 1.0f; +static const float g_OneMinusFresnelReflection = 0.0f; +static const float4 g_SelfIllumTint = { 1.0f, 1.0f, 1.0f, 1.0f }; +# if OUTLINE +const float4 g_OutlineParams : register( c2 ); +#define OUTLINE_MIN_VALUE0 g_OutlineParams.x +#define OUTLINE_MIN_VALUE1 g_OutlineParams.y +#define OUTLINE_MAX_VALUE0 g_OutlineParams.z +#define OUTLINE_MAX_VALUE1 g_OutlineParams.w + +const float4 g_OutlineColor : register( c3 ); +#define OUTLINE_COLOR g_OutlineColor + +# endif +# if SOFTEDGES +const float4 g_EdgeSoftnessParms : register( c4 ); +#define SOFT_MASK_MIN g_EdgeSoftnessParms.x +#define SOFT_MASK_MAX g_EdgeSoftnessParms.y +# endif +#else + +const float3 g_EnvmapContrast : register( c2 ); +const float3 g_EnvmapSaturation : register( c3 ); +const float4 g_FresnelReflectionReg : register( c4 ); +#define g_FresnelReflection g_FresnelReflectionReg.a +#define g_OneMinusFresnelReflection g_FresnelReflectionReg.b +const float4 g_SelfIllumTint : register( c7 ); +#endif + +const float4 g_DetailTint_and_BlendFactor : register( c8 ); +#define g_DetailTint (g_DetailTint_and_BlendFactor.rgb) +#define g_DetailBlendFactor (g_DetailTint_and_BlendFactor.w) + +const float3 g_EyePos : register( c10 ); +const float4 g_FogParams : register( c11 ); +const float4 g_TintValuesTimesLightmapScale : register( c12 ); + +#define g_flAlpha2 g_TintValuesTimesLightmapScale.w + +const float4 g_FlashlightAttenuationFactors : register( c13 ); +const float3 g_FlashlightPos : register( c14 ); +const float4x4 g_FlashlightWorldToTexture : register( c15 ); // through c18 +const float4 g_ShadowTweaks : register( c19 ); + +#if !defined( SHADER_MODEL_PS_2_0 ) && ( FLASHLIGHT == 0 ) +#define g_cAmbientColor cFlashlightScreenScale.rgb +//const float3 g_cAmbientColor : register( c31 ); +#endif + +#if PARALLAX_MAPPING || (CUBEMAP == 2) +const float4 g_ParallaxMappingControl : register( c20 ); +#endif + +#if PARALLAX_MAPPING +#define HEIGHT_SCALE ( g_ParallaxMappingControl.x ) +#else +#define HEIGHT_SCALE 0 +#endif + +#if (CUBEMAP == 2) +#define g_DiffuseCubemapScale g_ParallaxMappingControl.y +#endif + +const float3 g_TintValuesWithoutLightmapScale : register( c21 ); + +sampler BaseTextureSampler : register( s0 ); +sampler LightmapSampler : register( s1 ); +sampler EnvmapSampler : register( s2 ); +#if FANCY_BLENDING +sampler BlendModulationSampler : register( s3 ); +#endif + +#if DETAILTEXTURE +sampler DetailSampler : register( s12 ); +#endif + +sampler BumpmapSampler : register( s4 ); + +#if BUMPMAP2 == 1 +sampler BumpmapSampler2 : register( s5 ); +#else +sampler EnvmapMaskSampler : register( s5 ); +#endif + +#if ( DETAIL_BLEND_MODE == 9 ) +sampler PaintSampler : register( s9 ); +#endif + +#if WARPLIGHTING +sampler WarpLightingSampler : register( s6 ); +#endif +sampler BaseTextureSampler2 : register( s7 ); + +#if BUMPMASK == 1 +sampler BumpMaskSampler : register( s8 ); +#if NORMALMASK_DECODE_MODE == NORM_DECODE_ATI2N_ALPHA +sampler AlphaMaskSampler : register( s11 ); // alpha +#else +#define AlphaMaskSampler BumpMaskSampler +#endif +#endif + +#if defined( _X360 ) && FLASHLIGHT +sampler FlashlightSampler : register( s13 ); +sampler ShadowDepthSampler : register( s14 ); +sampler RandRotSampler : register( s15 ); +#endif + +#if defined( _X360 ) + // The compiler runs out of temp registers in certain combos, increase the maximum for now + #if ( BASETEXTURE2 && (BUMPMAP == 2) && CUBEMAP && NORMALMAPALPHAENVMAPMASK && DIFFUSEBUMPMAP && FLASHLIGHT && SHADER_SRGB_READ ) + [maxtempreg(39)] + #elif ( SHADER_SRGB_READ == 1 ) + [maxtempreg(36)] + #endif +#endif + +#if LIGHTING_PREVIEW == 2 +LPREVIEW_PS_OUT main( PS_INPUT i ) : COLOR +#else +float4 main( PS_INPUT i ) : COLOR +#endif +{ + bool bBaseTexture2 = BASETEXTURE2 ? true : false; + bool bDetailTexture = DETAILTEXTURE ? true : false; + bool bBumpmap = BUMPMAP ? true : false; + bool bDiffuseBumpmap = DIFFUSEBUMPMAP ? true : false; + bool bCubemap = CUBEMAP ? true : false; + bool bEnvmapMask = ENVMAPMASK ? true : false; + bool bBaseAlphaEnvmapMask = BASEALPHAENVMAPMASK ? true : false; + bool bSelfIllum = SELFILLUM ? true : false; + bool bNormalMapAlphaEnvmapMask = NORMALMAPALPHAENVMAPMASK ? true : false; + bool bBaseTextureNoEnvmap = BASETEXTURENOENVMAP ? true : false; + bool bBaseTexture2NoEnvmap = BASETEXTURE2NOENVMAP ? true : false; + + float4 baseColor = 0.0f; + float4 baseColor2 = 0.0f; + float4 vNormal = float4(0, 0, 1, 1); + float3 baseTexCoords = float3(0,0,0); + float3 worldPos = i.worldPos_projPosZ.xyz; + float3x3 tangenttranspose = i.tangentSpaceTranspose; + + float3 worldVertToEyeVector = g_EyePos - worldPos; +#if SEAMLESS + baseTexCoords = i.SeamlessTexCoord_fogFactorW.xyz; +#else + baseTexCoords.xy = i.BASETEXCOORD.xy; +#endif + + float3 coords = baseTexCoords; + + if ( PARALLAX_MAPPING ) + { + float3 tangentspace_eye_vector = mul( worldVertToEyeVector, transpose( tangenttranspose ) ); + + float flParallaxLimit = length( tangentspace_eye_vector.xy ) / tangentspace_eye_vector.z; + float2 vOffset = normalize( -tangentspace_eye_vector.xy ); + float CurHeight = 1.0; + float NewHeight = tex2D( BumpmapSampler, coords.xy ).a; + float dist = min( 0.06, HEIGHT_SCALE * flParallaxLimit * ( CurHeight - NewHeight ) ); + coords.x += dist * vOffset.x; + coords.y += dist * vOffset.y; + } + + float2 detailTexCoord = 0.0f; + float2 bumpmapTexCoord = 0.0f; + float2 bumpmap2TexCoord = 0.0f; + +#if ( DETAILTEXTURE == 1 ) + detailTexCoord = i.DETAILCOORDS; +#endif + +#if BUMPMAP + bumpmapTexCoord = i.BUMPCOORDS; +#endif + +#if BUMPMASK + bumpmap2TexCoord = i.ENVMAPMASKCOORDS; +#endif + + if ( PARALLAX_MAPPING ) + { + detailTexCoord = 0; + bumpmapTexCoord = coords; + } + + GetBaseTextureAndNormal( BaseTextureSampler, BaseTextureSampler2, BumpmapSampler, + bBaseTexture2, bBumpmap || bNormalMapAlphaEnvmapMask, + coords, bumpmapTexCoord, + i.vertexColor.rgb, baseColor, baseColor2, vNormal ); + +#if BUMPMAP == 1 // not ssbump + vNormal.xyz = vNormal.xyz * 2.0f - 1.0f; // make signed if we're not ssbump + + float3 vThisReallyIsANormal = vNormal; +#endif + + float3 lightmapColor1 = float3( 1.0f, 1.0f, 1.0f ); + float3 lightmapColor2 = float3( 1.0f, 1.0f, 1.0f ); + float3 lightmapColor3 = float3( 1.0f, 1.0f, 1.0f ); +#if LIGHTING_PREVIEW == 0 + if( bBumpmap && bDiffuseBumpmap ) + { + float2 bumpCoord1; + float2 bumpCoord2; + float2 bumpCoord3; + ComputeBumpedLightmapCoordinates( i.lightmapTexCoord1And2, i.lightmapTexCoord3.xy, + bumpCoord1, bumpCoord2, bumpCoord3 ); + + lightmapColor1 = LightMapSample( LightmapSampler, bumpCoord1 ); + lightmapColor2 = LightMapSample( LightmapSampler, bumpCoord2 ); + lightmapColor3 = LightMapSample( LightmapSampler, bumpCoord3 ); + } + else + { + float2 bumpCoord1 = ComputeLightmapCoordinates( i.lightmapTexCoord1And2, i.lightmapTexCoord3.xy ); + lightmapColor1 = LightMapSample( LightmapSampler, bumpCoord1 ); + } +#endif + +#if ( DETAIL_BLEND_MODE == 9 ) && ( defined(SHADER_MODEL_PS_2_B ) || defined( SHADER_MODEL_PS_3_0 ) ) + float2 paintCoord; + if( bBumpmap && bDiffuseBumpmap ) + { + float2 bumpCoord1; + float2 bumpCoord2; + float2 bumpCoord3; + ComputeBumpedLightmapCoordinates( i.lightmapTexCoord1And2, i.lightmapTexCoord3.xy, + bumpCoord1, bumpCoord2, bumpCoord3 ); + paintCoord.y = bumpCoord1.y; + paintCoord.x = bumpCoord1.x - ( bumpCoord2.x - bumpCoord1.x ); + } + else + { + paintCoord = ComputeLightmapCoordinates( i.lightmapTexCoord1And2, i.lightmapTexCoord3.xy ); + } + float4 paintColor = tex2D( PaintSampler, paintCoord ); + baseColor.xyz = lerp( baseColor.xyz, paintColor.xyz, paintColor.w ); +#endif + + float2 envmapMaskTexCoord = i.ENVMAPMASKCOORDS; + + float4 detailColor = float4( 1.0f, 1.0f, 1.0f, 1.0f ); + +#if DETAILTEXTURE +#if SHADER_MODEL_PS_2_0 + detailColor = tex2D( DetailSampler, detailTexCoord ); +#else + detailColor = float4( g_DetailTint, 1.0f ) * tex2D( DetailSampler, detailTexCoord ); +#endif +#endif + +#if ( OUTLINE || SOFTEDGES ) + float distAlphaMask = baseColor.a; + +# if OUTLINE + if ( ( distAlphaMask >= OUTLINE_MIN_VALUE0 ) && + ( distAlphaMask <= OUTLINE_MAX_VALUE1 ) ) + { + float oFactor=1.0; + if ( distAlphaMask <= OUTLINE_MIN_VALUE1 ) + { + oFactor=smoothstep( OUTLINE_MIN_VALUE0, OUTLINE_MIN_VALUE1, distAlphaMask ); + } + else + { + oFactor=smoothstep( OUTLINE_MAX_VALUE1, OUTLINE_MAX_VALUE0, distAlphaMask ); + } + baseColor = lerp( baseColor, OUTLINE_COLOR, oFactor ); + } +# endif +# if SOFTEDGES + baseColor.a *= smoothstep( SOFT_MASK_MAX, SOFT_MASK_MIN, distAlphaMask ); +# else + baseColor.a *= distAlphaMask >= 0.5; +# endif +#endif + + + float blendedAlpha = baseColor.a; + +#if MASKEDBLENDING + float blendfactor=0.5; +#else + float blendfactor=i.vertexBlendX.x; +#endif + + if( bBaseTexture2 ) + { +#if (SELFILLUM == 0) && (NORMALMAPALPHAENVMAPMASK==0) && (PIXELFOGTYPE != PIXEL_FOG_TYPE_HEIGHT) && (FANCY_BLENDING) + float4 modt=tex2D(BlendModulationSampler,i.lightmapTexCoord3.zw); +#if MASKEDBLENDING + float minb=modt.g-modt.r; + float maxb=modt.g+modt.r; +#else + float minb=max(0,modt.g-modt.r); + float maxb=min(1,modt.g+modt.r); +#endif + blendfactor=smoothstep(minb,maxb,blendfactor); +#endif + baseColor.rgb = lerp( baseColor, baseColor2.rgb, blendfactor ); + blendedAlpha = lerp( baseColor.a, baseColor2.a, blendfactor ); + } + + float3 specularFactor = 1.0f; + float4 vNormalMask = float4(0, 0, 1, 1); + if( bBumpmap ) + { + if( bBaseTextureNoEnvmap ) + { + vNormal.a = 0.0f; + } + +#if ( BUMPMAP2 == 1 ) + { + #if ( BUMPMASK == 1 ) + float2 b2TexCoord = bumpmap2TexCoord; + #else + float2 b2TexCoord = bumpmapTexCoord; + #endif + + float4 vNormal2; + #if ( BUMPMAP == 2 ) + { + vNormal2 = tex2D( BumpmapSampler2, b2TexCoord ); + } + #else + { + float4 normalTexel = tex2D( BumpmapSampler2, b2TexCoord ); + vNormal2 = float4( normalTexel.xyz * 2.0f - 1.0f, normalTexel.a ); + } + #endif + + if( bBaseTexture2NoEnvmap ) + { + vNormal2.a = 0.0f; + } + + #if ( BUMPMASK == 1 ) + float3 vNormal1 = DecompressNormal( BumpmapSampler, i.BUMPCOORDS, NORMALMASK_DECODE_MODE, AlphaMapSampler ); + + vNormal.xyz = normalize( vNormal1.xyz + vNormal2.xyz ); + + // Third normal map...same coords as base + normalTexel = tex2D( BumpMaskSampler, i.baseTexCoord.xy ); + vNormalMask = float4( normalTexel.xyz * 2.0f - 1.0f, normalTexel.a ); + + vNormal.xyz = lerp( vNormalMask.xyz, vNormal.xyz, vNormalMask.a ); // Mask out normals from vNormal + specularFactor = vNormalMask.a; + #else // BUMPMASK == 0 + vNormal.xyz = lerp( vNormal.xyz, vNormal2.xyz, blendfactor); + #endif + + } + +#endif // BUMPMAP2 == 1 + + if( bNormalMapAlphaEnvmapMask ) + { + specularFactor *= vNormal.a; + } + } + else if ( bNormalMapAlphaEnvmapMask ) + { + specularFactor *= vNormal.a; + } + +#if ( BUMPMAP2 == 0 ) + if( bEnvmapMask ) + { + specularFactor *= tex2D( EnvmapMaskSampler, envmapMaskTexCoord ).xyz; + } +#endif + + if( bBaseAlphaEnvmapMask ) + { + specularFactor *= 1.0 - blendedAlpha; // Reversing alpha blows! + } + + float4 albedo = float4( 1.0f, 1.0f, 1.0f, 1.0f ); + float alpha = 1.0f; + albedo *= baseColor; + if( !bBaseAlphaEnvmapMask && !bSelfIllum ) + { + alpha *= baseColor.a; + } + + #if ( DETAIL_BLEND_MODE != 9 ) + { + if( bDetailTexture ) + { + albedo = TextureCombine( albedo, detailColor, DETAIL_BLEND_MODE, g_DetailBlendFactor ); + #if ( ( DETAIL_BLEND_MODE == TCOMBINE_MOD2X_SELECT_TWO_PATTERNS ) && !MASKEDBLENDING && !BASETEXTURE2 && !SELFILLUM ) + { + // don't do this in the MASKEDBLENDING or SELFILLUM case since we don't have enough instructions in ps20 + specularFactor *= 2.0 * lerp( detailColor.g, detailColor.b, baseColor.a ); + } + #endif + } + } + #endif + + // The vertex color contains the modulation color + vertex color combined +#if ( SEAMLESS == 0 ) + albedo.xyz *= i.vertexColor; +#endif + // MAINTOL4DMERGEFIXME +// alpha *= i.vertexColor.a * g_flAlpha2; // not sure about this one + alpha *= i.vertexColor.a; // not sure about this one + + // Save this off for single-pass flashlight, since we'll still need the SSBump vector, not a real normal + float3 vSSBumpVector = vNormal.xyz; + + float3 diffuseLighting; + if( bBumpmap && bDiffuseBumpmap ) + { + +// ssbump +#if ( BUMPMAP == 2 ) +#if ( DETAIL_BLEND_MODE == TCOMBINE_SSBUMP_BUMP ) + vNormal *= 2*detailColor; +#endif + diffuseLighting = vNormal.x * lightmapColor1 + + vNormal.y * lightmapColor2 + + vNormal.z * lightmapColor3; + diffuseLighting *= g_TintValuesTimesLightmapScale.rgb; + // now, calculate vNormal for reflection purposes. if vNormal isn't needed, hopefully + // the compiler will eliminate these calculations + vNormal.xyz = normalize( bumpBasis[0]*vNormal.x + bumpBasis[1]*vNormal.y + bumpBasis[2]*vNormal.z); +#else + float3 dp; + dp.x = saturate( dot( vNormal, bumpBasis[0] ) ); + dp.y = saturate( dot( vNormal, bumpBasis[1] ) ); + dp.z = saturate( dot( vNormal, bumpBasis[2] ) ); + dp *= dp; + +#if ( DETAIL_BLEND_MODE == TCOMBINE_SSBUMP_BUMP ) + dp *= 2*detailColor; +#endif + diffuseLighting = dp.x * lightmapColor1 + + dp.y * lightmapColor2 + + dp.z * lightmapColor3; + float sum = dot( dp, float3( 1.0f, 1.0f, 1.0f ) ); + diffuseLighting *= g_TintValuesTimesLightmapScale.rgb / sum; +#endif + } + else + { + diffuseLighting = lightmapColor1 * g_TintValuesTimesLightmapScale.rgb; + } + +#if WARPLIGHTING && ( SEAMLESS == 0 ) + float len=0.5*length(diffuseLighting); + // FIXME: 8-bit lookup textures like this need a "nice filtering" VTF option, which converts + // them to 16-bit on load or does filtering in the shader (since most hardware - 360 + // included - interpolates 8-bit textures at 8-bit precision, which causes banding) + diffuseLighting *= 2.0*tex2D(WarpLightingSampler,float2(len,0)); +#endif + + float3 worldSpaceNormal = mul( vNormal, tangenttranspose ); +#if !defined( SHADER_MODEL_PS_2_0 ) && ( FLASHLIGHT == 0 ) + diffuseLighting += g_cAmbientColor; +#endif + + float3 diffuseComponent = albedo * diffuseLighting; + +#if defined( _X360 ) && FLASHLIGHT + + // ssbump doesn't pass a normal to the flashlight...it computes shadowing a different way +#if ( BUMPMAP == 2 ) + bool bHasNormal = false; + + float3 worldPosToLightVector = g_FlashlightPos - worldPos; + + float3 tangentPosToLightVector; + tangentPosToLightVector.x = dot( worldPosToLightVector, tangenttranspose[0] ); + tangentPosToLightVector.y = dot( worldPosToLightVector, tangenttranspose[1] ); + tangentPosToLightVector.z = dot( worldPosToLightVector, tangenttranspose[2] ); + + tangentPosToLightVector = normalize( tangentPosToLightVector ); + float nDotL = saturate( vSSBumpVector.x*dot( tangentPosToLightVector, bumpBasis[0]) + + vSSBumpVector.y*dot( tangentPosToLightVector, bumpBasis[1]) + + vSSBumpVector.z*dot( tangentPosToLightVector, bumpBasis[2]) ); +#else + bool bHasNormal = true; + float nDotL = 1.0f; +#endif + + bool bShadows = FLASHLIGHTSHADOWS ? true : false; + float3 flashlightColor = DoFlashlight( g_FlashlightPos, worldPos, i.flashlightSpacePos, + worldSpaceNormal, g_FlashlightAttenuationFactors.xyz, + g_FlashlightAttenuationFactors.w, FlashlightSampler, ShadowDepthSampler, + RandRotSampler, 0, bShadows, false, i.vProjPos.xy / i.vProjPos.w, false, g_ShadowTweaks, bHasNormal ); + + diffuseComponent = albedo.xyz * ( diffuseLighting + ( flashlightColor * nDotL * g_TintValuesWithoutLightmapScale.rgb ) ); +#endif + + if( bSelfIllum ) + { + float3 selfIllumComponent = g_SelfIllumTint * albedo.xyz; + diffuseComponent = lerp( diffuseComponent, selfIllumComponent, baseColor.a ); + } + + float3 specularLighting = float3( 0.0f, 0.0f, 0.0f ); +#if CUBEMAP + if( bCubemap ) + { + float3 reflectVect = CalcReflectionVectorUnnormalized( worldSpaceNormal, worldVertToEyeVector ); + + // Calc Fresnel factor + half3 eyeVect = normalize(worldVertToEyeVector); + float fresnel = 1.0 - dot( worldSpaceNormal, eyeVect ); + fresnel = pow( fresnel, 5.0 ); + fresnel = fresnel * g_OneMinusFresnelReflection + g_FresnelReflection; + + specularLighting = ENV_MAP_SCALE * texCUBE( EnvmapSampler, reflectVect ); +#if (CUBEMAP == 2) //cubemap darkened by lightmap mode + specularLighting = lerp( specularLighting, specularLighting * saturate( diffuseLighting ), g_DiffuseCubemapScale ); //reduce the cubemap contribution when the pixel is in shadow +#endif + specularLighting *= specularFactor; + + specularLighting *= g_EnvmapTint; +#if FANCY_BLENDING == 0 + float3 specularLightingSquared = specularLighting * specularLighting; + specularLighting = lerp( specularLighting, specularLightingSquared, g_EnvmapContrast ); + float3 greyScale = dot( specularLighting, float3( 0.299f, 0.587f, 0.114f ) ); + specularLighting = lerp( greyScale, specularLighting, g_EnvmapSaturation ); +#endif + specularLighting *= fresnel; + } +#endif + + #if ( DETAIL_BLEND_MODE != 9 ) + { + if( bDetailTexture ) + { + diffuseComponent = TextureCombinePostLighting( diffuseComponent, detailColor, DETAIL_BLEND_MODE, g_DetailBlendFactor ); + } + } + #endif + + float3 result = diffuseComponent + specularLighting; + +#if ( LIGHTING_PREVIEW == 3 ) + return float4( worldSpaceNormal, i.worldPos_projPosZ.w ); +#endif + +#if ( LIGHTING_PREVIEW == 1 ) + float dotprod = 0.7+0.25 * dot( worldSpaceNormal, normalize( float3( 1, 2, -.5 ) ) ); + return FinalOutput( float4( dotprod*albedo.xyz, alpha ), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +#endif + +#if ( LIGHTING_PREVIEW == 2 ) + LPREVIEW_PS_OUT ret; + ret.color = float4( albedo.xyz,alpha ); + ret.normal = float4( worldSpaceNormal, i.worldPos_projPosZ.w ); + ret.position = float4( worldPos, alpha ); + ret.flags = float4( 1, 1, 1, alpha ); + + return FinalOutput( ret, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +#endif + +#if ( LIGHTING_PREVIEW == 0 ) + bool bWriteDepthToAlpha = false; + + // ps_2_b and beyond +#if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) + bWriteDepthToAlpha = ( WRITE_DEPTH_TO_DESTALPHA != 0 ) && ( WRITEWATERFOGTODESTALPHA == 0 ); +#endif + + float flVertexFogFactor = 0.0f; + #if !HARDWAREFOGBLEND && !DOPIXELFOG + { + #if ( SEAMLESS ) + { + flVertexFogFactor = i.SeamlessTexCoord_fogFactorW.w; + } + #else + { + flVertexFogFactor = i.baseTexCoord_fogFactorZ.z; + } + #endif + } + #endif + float fogFactor = CalcPixelFogFactorSupportsVertexFog( PIXELFOGTYPE, g_FogParams, g_EyePos.xyz, worldPos, i.worldPos_projPosZ.w, flVertexFogFactor ); + +#if WRITEWATERFOGTODESTALPHA && (PIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT) + alpha = fogFactor; +#endif + return FinalOutput( float4( result.rgb, alpha ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, bWriteDepthToAlpha, i.worldPos_projPosZ.w ); +#endif + +} + diff --git a/materialsystem/stdshaders/lightmappedgeneric_ps2x.fxc b/materialsystem/stdshaders/lightmappedgeneric_ps2x.fxc new file mode 100644 index 00000000..151b0248 --- /dev/null +++ b/materialsystem/stdshaders/lightmappedgeneric_ps2x.fxc @@ -0,0 +1,64 @@ +// STATIC: "MASKEDBLENDING" "0..1" +// STATIC: "BASETEXTURE2" "0..1" +// STATIC: "BUMPMAP" "0..2" +// STATIC: "BUMPMAP2" "0..1" +// STATIC: "CUBEMAP" "0..2" +// STATIC: "ENVMAPMASK" "0..1" +// STATIC: "BASEALPHAENVMAPMASK" "0..1" +// STATIC: "SELFILLUM" "0..1" +// STATIC: "NORMALMAPALPHAENVMAPMASK" "0..1" +// STATIC: "DIFFUSEBUMPMAP" "0..1" +// STATIC: "BASETEXTURENOENVMAP" "0..1" +// STATIC: "BASETEXTURE2NOENVMAP" "0..1" +// STATIC: "WARPLIGHTING" "0..1" +// STATIC: "FANCY_BLENDING" "0..1" +// STATIC: "PARALLAX_MAPPING" "0..0" [ps20b] +// STATIC: "PARALLAX_MAPPING" "0..0" [ps20] +// STATIC: "SEAMLESS" "0..1" +// STATIC: "OUTLINE" "0..0" +// STATIC: "SOFTEDGES" "0..1" +// STATIC: "BUMPMASK" "0..1" +// STATIC: "DETAIL_BLEND_MODE" "0..12" +// STATIC: "FLASHLIGHT" "0..1" [ps20b] [XBOX] +// STATIC: "SHADER_SRGB_READ" "0..1" [XBOX] +// STATIC: "SHADER_SRGB_READ" "0..0" [PC] +// STATIC: "LIGHTING_PREVIEW" "0..3" [PC] +// STATIC: "LIGHTING_PREVIEW" "0..0" [XBOX] + +// DYNAMIC: "FASTPATHENVMAPCONTRAST" "0..1" +// DYNAMIC: "FASTPATH" "0..1" +// DYNAMIC: "WRITEWATERFOGTODESTALPHA" "0..1" +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps20b] [XBOX] +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..0" [ps20b] [PC] + +// SKIP: $SEAMLESS && $PARALLAX_MAPPING [ps20b] + +// SKIP: $SEAMLESS && ( $OUTLINE || $SOFTEDGES) +// SKIP: $BASETEXTURE2 && ( $OUTLINE || $SOFTEDGES) +// SKIP: $BUMPMAP2 && ( $OUTLINE || $SOFTEDGES) +// SKIP: $SELFILLUM && ( $OUTLINE || $SOFTEDGES) +// SKIP: $MASKEDBLENDING && ( $OUTLINE || $SOFTEDGES) +// SKIP: $FANCY_BLENDING && ( $OUTLINE || $SOFTEDGES) +// SKIP: $LIGHTING_PREVIEW && ( $OUTLINE || $SOFTEDGES) +// SKIP: ($FASTPATH == 0) && ( $OUTLINE || $SOFTEDGES) +// SKIP: (($DETAIL_BLEND_MODE != 12 ) && $BUMPMAP) && ( $OUTLINE || $SOFTEDGES) +// SKIP: ($WARPLIGHTING) && ( $OUTLINE || $SOFTEDGES) +// SKIP: ($BUMPMAP) && ( $OUTLINE || $SOFTEDGES) +// SKIP: ($DETAIL_BLEND_MODE == 7 ) && ( $SOFTEDGES || $BUMPMAP2) +// SKIP: ($DETAIL_BLEND_MODE == 6 ) +// SKIP: ($DETAIL_BLEND_MODE == 10 ) && ($BUMPMAP == 0 ) +// SKIP: ($DETAIL_BLEND_MODE == 11 ) && ($BUMPMAP != 0 ) +// SKIP: ($FANCY_BLENDING) && ($DETAIL_BLEND_MODE == 7 ) +// SKIP: ($PARALLAX_MAPPING) && ($BASETEXTURE2 || $BUMPMAP2 || $DETAILTEXTURE || $BASETEXTURE2 ) +// SKIP: ($FANCY_BLENDING) && ($BASETEXTURE2 == 0 ) && ($BUMPMAP2 == 0 ) +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 ) + +// program too complex for ps20. Don't do darkened cubemaps and 2 bump maps at the same time. Fairly arbitrary pairing just to get the damn thing compiling +// SKIP: ( $CUBEMAP == 2 ) && ( $BUMPMAP2 ) [ps20] +// program slightly more complex on 360 because of shader srgb read. Eliminate coexistance of srgb read, water fog, and darkened cubemaps +// SKIP: ( $CUBEMAP == 2 ) && ( $PIXELFOGTYPE == 1 ) && ( $SHADER_SRGB_READ == 1 ) [XBOX] + +#include "common_fog_ps_supportsvertexfog_fxc.h" +#include "lightmappedgeneric_ps2_3_x.h" diff --git a/materialsystem/stdshaders/lightmappedgeneric_vs20.fxc b/materialsystem/stdshaders/lightmappedgeneric_vs20.fxc new file mode 100644 index 00000000..27879259 --- /dev/null +++ b/materialsystem/stdshaders/lightmappedgeneric_vs20.fxc @@ -0,0 +1,261 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "ENVMAP_MASK" "0..1" +// STATIC: "TANGENTSPACE" "0..1" +// STATIC: "BUMPMAP" "0..1" +// STATIC: "DETAILTEXTURE" "0..1" +// STATIC: "DIFFUSEBUMPMAP" "0..1" +// STATIC: "VERTEXCOLOR" "0..1" +// STATIC: "VERTEXALPHATEXBLENDFACTOR" "0..1" +// STATIC: "PARALLAX_MAPPING" "0..1" +// STATIC: "SEAMLESS" "0..1" +// STATIC: "BUMPMASK" "0..1" +// STATIC: "FLASHLIGHT" "0..1" [XBOX] +// STATIC: "FANCY_BLENDING" "0..1" +// STATIC: "SELFILLUM" "0..1" +// STATIC: "LIGHTING_PREVIEW" "0..3" [PC] +// STATIC: "LIGHTING_PREVIEW" "0..0" [XBOX] + +// DYNAMIC: "FASTPATH" "0..1" + +// This should not be a combo since I'm a moron with the tangent space and the flashlight. +// SKIP: !$BUMPMAP && $DIFFUSEBUMPMAP +// SKIP: $SEAMLESS && $PARALLAXMAP +// SKIP: $BUMPMASK && $PARALLAXMAP +// SKIP: $BUMPMASK && $SEAMLESS + +// SKIP: $LIGHTING_PREVIEW && $FLASHLIGHT + +#include "common_fog_vs_supportsvertexfog_fxc.h" +#include "common_vs_fxc.h" +#include "common_lightmappedgeneric_fxc.h" + + +static const int g_FogType = DOWATERFOG; +static const bool g_UseSeparateEnvmapMask = ENVMAP_MASK; +static const bool g_bTangentSpace = TANGENTSPACE; +static const bool g_bBumpmap = BUMPMAP; +static const bool g_bBumpmapDiffuseLighting = DIFFUSEBUMPMAP; +static const bool g_bVertexColor = VERTEXCOLOR; +static const bool g_bVertexAlphaTexBlendFactor = VERTEXALPHATEXBLENDFACTOR; +static const bool g_BumpMask = BUMPMASK; + +#if SEAMLESS +const float4 SeamlessScale : register( SHADER_SPECIFIC_CONST_0 ); +#define SEAMLESS_SCALE (SeamlessScale.x) +#else +const float4 cBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_0 ); +const float4 cDetailOrBumpTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_2 ); +#endif +// This should be identity if we are bump mapping, otherwise we'll screw up the lightmapTexCoordOffset. +const float4 cEnvmapMaskTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_4 ); + +#if FLASHLIGHT +const float4x4 g_FlashlightWorldToTexture : register( SHADER_SPECIFIC_CONST_6 ); +#endif + +#if DETAILTEXTURE && BUMPMAP && !SELFILLUM && !FANCY_BLENDING +const float4 cBumpTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_10 ); // not contiguous with the rest! +#else +const float4 cFancyBlendMaskTexCoordTransform[2]: register( SHADER_SPECIFIC_CONST_10 ); // not contiguous with the rest! +#endif + +#if ( LIGHTING_PREVIEW == 3 ) +const float4 g_vEyeVector : register( SHADER_SPECIFIC_CONST_12 ); +#endif + +struct VS_INPUT +{ + float3 vPos : POSITION; + float4 vNormal : NORMAL; + float2 vBaseTexCoord : TEXCOORD0; + float2 vLightmapTexCoord : TEXCOORD1; + float2 vLightmapTexCoordOffset : TEXCOORD2; + float3 vTangentS : TANGENT; + float3 vTangentT : BINORMAL; + float4 vColor : COLOR0; +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 vObjNormal; + DecompressVertex_Normal( v.vNormal, vObjNormal ); + + float4 projPos; + float3 worldPos; + + projPos = mul( float4( v.vPos, 1 ), cModelViewProj ); + o.projPos = projPos; + + worldPos = mul( float4( v.vPos, 1 ), cModel[0] ); + + o.worldPos_projPosZ.w = projPos.z; + o.worldPos_projPosZ.xyz = worldPos; + +#if ( LIGHTING_PREVIEW == 3 ) + o.worldPos_projPosZ.w = dot( g_vEyeVector, worldPos.xyz - cEyePos.xyz ); // Linear depth +#endif + + float3 worldNormal = mul( vObjNormal, ( float3x3 )cModel[0] ); + +#if TANGENTSPACE || LIGHTING_PREVIEW || PARALLAX_MAPPING || defined( _X360 ) + float3 worldTangentS = mul( v.vTangentS, ( const float3x3 )cModel[0] ); + float3 worldTangentT = mul( v.vTangentT, ( const float3x3 )cModel[0] ); + + #if SEAMLESS && BUMPMAP && defined( _X360 ) + float3 n = normalize( worldNormal ); + float3 n2 = n * n; // sums to 1. + + o.tangentSpaceTranspose[0] = normalize( float3( n2.y + n2.z, 0.0f, n2.x ) ); + o.tangentSpaceTranspose[1] = normalize( float3( 0.0f, n2.x + n2.z, n2.y ) ); + o.tangentSpaceTranspose[2] = worldNormal; + #else + o.tangentSpaceTranspose[0] = worldTangentS; + o.tangentSpaceTranspose[1] = worldTangentT; + o.tangentSpaceTranspose[2] = worldNormal; + #endif +#endif + + + float3 worldVertToEyeVector = VSHADER_VECT_SCALE * (cEyePos - worldPos); + + #if ( SEAMLESS ) + { + // we need to fill in the texture coordinate projections + o.SeamlessTexCoord_fogFactorW.xyz = SEAMLESS_SCALE * worldPos; + } + #else + { + if ( FASTPATH ) + { + o.baseTexCoord_fogFactorZ.xy = v.vBaseTexCoord; + } + else + { + o.baseTexCoord_fogFactorZ.x = dot( v.vBaseTexCoord, cBaseTexCoordTransform[0] ) + cBaseTexCoordTransform[0].w; + o.baseTexCoord_fogFactorZ.y = dot( v.vBaseTexCoord, cBaseTexCoordTransform[1] ) + cBaseTexCoordTransform[1].w; + } + // calculate detailorbumptexcoord + if ( FASTPATH ) + { + o.DETAILORBUMPCOORDS = v.vBaseTexCoord.xy; + } + else + { + o.DETAILORBUMPCOORDS = float2( dot( v.vBaseTexCoord, cDetailOrBumpTexCoordTransform[0] ) + cDetailOrBumpTexCoordTransform[0].w, + dot( v.vBaseTexCoord, cDetailOrBumpTexCoordTransform[1] ) + cDetailOrBumpTexCoordTransform[1].w ); + } + } + #endif + if ( FASTPATH ) + { + o.lightmapTexCoord3.zw = v.vBaseTexCoord; +#if DETAILTEXTURE && BUMPMAP && !SELFILLUM && !FANCY_BLENDING + o.BUMPCOORDS = v.vBaseTexCoord; +#endif +#if FANCY_BLENDING + o.FANCYBLENDMASKCOORDS = v.vBaseTexCoord; +#endif + } + else + { +#if DETAILTEXTURE && BUMPMAP && !SELFILLUM && !FANCY_BLENDING + o.BUMPCOORDS = float2( dot( v.vBaseTexCoord, cBumpTexCoordTransform[0] ) + cBumpTexCoordTransform[0].w, + dot( v.vBaseTexCoord, cBumpTexCoordTransform[1] ) + cBumpTexCoordTransform[1].w ); +#endif +#if FANCY_BLENDING + o.FANCYBLENDMASKCOORDS = float2( dot( v.vBaseTexCoord, cFancyBlendMaskTexCoordTransform[0] ) + cFancyBlendMaskTexCoordTransform[0].w, + dot( v.vBaseTexCoord, cFancyBlendMaskTexCoordTransform[1] ) + cFancyBlendMaskTexCoordTransform[1].w ); +#endif + } + + // compute lightmap coordinates + if( g_bBumpmap && g_bBumpmapDiffuseLighting ) + { + o.lightmapTexCoord1And2.xy = v.vLightmapTexCoord + v.vLightmapTexCoordOffset; + + float2 lightmapTexCoord2 = o.lightmapTexCoord1And2.xy + v.vLightmapTexCoordOffset; + float2 lightmapTexCoord3 = lightmapTexCoord2 + v.vLightmapTexCoordOffset; + + // reversed component order + o.lightmapTexCoord1And2.w = lightmapTexCoord2.x; + o.lightmapTexCoord1And2.z = lightmapTexCoord2.y; + + o.lightmapTexCoord3.xy = lightmapTexCoord3; + } + else + { + o.lightmapTexCoord1And2.xy = v.vLightmapTexCoord; + } + + if( g_UseSeparateEnvmapMask || g_BumpMask ) + { + // reversed component order +#if FASTPATH + o.ENVMAPMASKCOORDS = v.vBaseTexCoord.xy; +#else + o.ENVMAPMASKCOORDS = float2( dot( v.vBaseTexCoord, cEnvmapMaskTexCoordTransform[0] ) + cEnvmapMaskTexCoordTransform[0].w, + dot( v.vBaseTexCoord, cEnvmapMaskTexCoordTransform[1] ) + cEnvmapMaskTexCoordTransform[1].w ); +#endif + } + + #if ( HARDWAREFOGBLEND ) + { + o.fog = CalcFixedFunctionFog( worldPos, g_FogType ); + } + #endif + + #if ( !DOPIXELFOG && !HARDWAREFOGBLEND ) + { + #if ( SEAMLESS ) + { + o.SeamlessTexCoord_fogFactorW.w = CalcNonFixedFunctionFog( worldPos, g_FogType ); + } + #else + { + o.baseTexCoord_fogFactorZ.z = CalcNonFixedFunctionFog( worldPos, g_FogType ); + } + #endif + } + #endif + + if ( !g_bVertexColor ) + { + o.vertexColor = float4( 1.0f, 1.0f, 1.0f, cModulationColor.a ); + } + else + { + if ( g_bVertexAlphaTexBlendFactor ) + { + o.vertexColor.rgb = v.vColor.rgb; + o.vertexColor.a = cModulationColor.a; + } + else + { + o.vertexColor = v.vColor; + o.vertexColor.a *= cModulationColor.a; + } + } +#if SEAMLESS + // compute belnd weights in rgb + float3 vNormal=normalize( worldNormal ); + o.vertexColor.xyz = vNormal * vNormal; // sums to 1. +#endif + +// On 360, we have extra iterators and can fold the flashlight into this shader +#if defined( _X360 ) + #if FLASHLIGHT + o.flashlightSpacePos = mul( float4( worldPos, 1.0f ), g_FlashlightWorldToTexture ); + o.vProjPos = projPos; + #endif +#endif + + if ( g_bVertexAlphaTexBlendFactor ) + { + o.vertexBlendX.x = v.vColor.a; + } + + return o; +} diff --git a/materialsystem/stdshaders/lightmappedpaint_dx9_helper.cpp b/materialsystem/stdshaders/lightmappedpaint_dx9_helper.cpp new file mode 100644 index 00000000..f2bf9935 --- /dev/null +++ b/materialsystem/stdshaders/lightmappedpaint_dx9_helper.cpp @@ -0,0 +1,565 @@ +//========= Copyright © 1996-2007, Valve LLC, All rights reserved. ============ +// +// Purpose: Lightmapped paint shader +// +// $Header: $ +// $NoKeywords: $ +//============================================================================= + +#include "lightmappedpaint_dx9_helper.h" +#include "BaseVSShader.h" +#include "shaderlib/commandbuilder.h" +#include "convar.h" +#include "lightmappedgeneric_vs20.inc" +#include "lightmappedpaint_ps20.inc" +#include "lightmappedpaint_ps20b.inc" + +#include "tier0/vprof.h" + +#include "tier0/memdbgon.h" + +extern ConVar mat_fullbright; + +extern ConVar mat_ambient_light_r; +extern ConVar mat_ambient_light_g; +extern ConVar mat_ambient_light_b; + + +void DrawLightmappedPaint_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, + LightmappedGeneric_DX9_Vars_t &info, CBasePerMaterialContextData **pContextDataPtr ) +{ + SHADOW_STATE + { + pShader->SetInitialShadowState(); + } + + bool bSinglePassFlashlight = true; + bool hasFlashlight = pShader->UsingFlashlight( params ); + CLightmappedGeneric_DX9_Context *pContextData = reinterpret_cast< CLightmappedGeneric_DX9_Context *> ( *pContextDataPtr ); + CLightmappedGeneric_DX9_Context *pLightmapContextData = pContextData; + + //the current context data pointer is actually for the main lightmappedgeneric shader, dig one level deeper for the paint context pointer we want + { + Assert( pContextData ); //should have been created by the main lightmappedgeneric shader + + pContextDataPtr = (CBasePerMaterialContextData **)&pLightmapContextData->m_pPaintSubcontext; + pContextData = reinterpret_cast< CLightmappedGeneric_DX9_Context *> ( *pContextDataPtr ); + + if( pContextData ) + { + //copy change state + pContextData->m_nVarChangeID = pLightmapContextData->m_nVarChangeID; + pContextData->m_bMaterialVarsChanged = pLightmapContextData->m_bMaterialVarsChanged; + } + } + + bool bShaderSrgbRead = ( IsX360() && IS_PARAM_DEFINED( info.m_nShaderSrgbRead360 ) && params[info.m_nShaderSrgbRead360]->GetIntValue() ); + + if ( pShaderShadow || ( ! pContextData ) || pContextData->m_bMaterialVarsChanged ) + { + bool bFullyOpaqueWithoutAlphaTest = false; + bool bFullyOpaque = false; + bool bNeedRegenStaticCmds = (! pContextData ) || pShaderShadow; + + if ( ! pContextData ) // make sure allocated + { + pContextData = new CLightmappedGeneric_DX9_Context; + *pContextDataPtr = pContextData; + } + + bool hasBump = g_pConfig->UseBumpmapping(); + bool hasSSBump = hasBump && (info.m_nSelfShadowedBumpFlag != -1) && ( params[info.m_nSelfShadowedBumpFlag]->GetIntValue() ); + bool hasSelfIllum = IS_FLAG_SET( MATERIAL_VAR_SELFILLUM ); + + bool bHasBlendModulateTexture = + (info.m_nBlendModulateTexture != -1) && + (params[info.m_nBlendModulateTexture]->IsTexture() ); + + + pContextData->m_bFullyOpaque = bFullyOpaque; + pContextData->m_bFullyOpaqueWithoutAlphaTest = bFullyOpaqueWithoutAlphaTest; + + bool hasEnvmapMask = params[info.m_nEnvmapMask]->IsTexture(); + + if ( pShaderShadow || bNeedRegenStaticCmds ) + { + bool hasVertexColor = IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR ); + bool hasDiffuseBumpmap = hasBump;// && (params[info.m_nNoDiffuseBumpLighting]->GetIntValue() == 0); + + bool hasEnvmap = true; //params[info.m_nEnvmap]->IsTexture(); + int envmap_variant; //0 = no envmap, 1 = regular, 2 = darken in shadow mode + if( hasEnvmap ) + { + //only enabled darkened cubemap mode when the scale calls for it. And not supported in ps20 when also using a 2nd bumpmap + envmap_variant = ((GetFloatParam( info.m_nEnvMapLightScale, params ) > 0.0f) && g_pHardwareConfig->SupportsPixelShaders_2_b()) ? 2 : 1; + } + else + { + envmap_variant = 0; + } + + bool bSeamlessMapping = ( ( info.m_nSeamlessMappingScale != -1 ) && + ( params[info.m_nSeamlessMappingScale]->GetFloatValue() != 0.0 ) ); + + if ( bNeedRegenStaticCmds ) + { + pContextData->ResetStaticCmds(); + CCommandBufferBuilder< CFixedCommandStorageBuffer< 5000 > > staticCmdsBuf; + + int nLightingPreviewMode = IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER0 ) + 2 * IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER1 ); + if ( ( nLightingPreviewMode == ENABLE_FIXED_LIGHTING_OUTPUTNORMAL_AND_DEPTH ) && IsPC() ) + { + staticCmdsBuf.SetVertexShaderNearAndFarZ( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6 ); // Needed for SSAO + } + + staticCmdsBuf.BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP ); + + staticCmdsBuf.BindStandardTexture( SHADER_SAMPLER6, TEXTURE_SHADOW_NOISE_2D ); //noise + + staticCmdsBuf.BindStandardTexture( SHADER_SAMPLER9, TEXTURE_PAINT ); + + if ( bSeamlessMapping ) + { + staticCmdsBuf.SetVertexShaderConstant4( + VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, + params[info.m_nSeamlessMappingScale]->GetFloatValue(),0,0,0 ); + } + staticCmdsBuf.StoreEyePosInPixelShaderConstant( 10 ); + staticCmdsBuf.SetPixelShaderFogParams( 11 ); + staticCmdsBuf.End(); + // now, copy buf + pContextData->m_pStaticCmds = new uint8[staticCmdsBuf.Size()]; + memcpy( pContextData->m_pStaticCmds, staticCmdsBuf.Base(), staticCmdsBuf.Size() ); + } + if ( pShaderShadow ) + { + pShader->EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + + // Alpha test: FIXME: shouldn't this be handled in Shader_t::SetInitialShadowState + pShaderShadow->EnableAlphaTest( true ); + pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GREATER, 0.0f ); + + + unsigned int flags = VERTEX_POSITION; + + //paint map + pShaderShadow->EnableTexture( SHADER_SAMPLER9, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER9, false ); + + if ( bHasBlendModulateTexture ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER3, false ); + } + + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ) + { + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); + } + else + { + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, false ); + } + + //noise + pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER6, false ); + + //splat bump map + pShaderShadow->EnableTexture( SHADER_SAMPLER7, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER7, false ); + + flags |= VERTEX_TANGENT_S | VERTEX_TANGENT_T | VERTEX_NORMAL; + + if( hasEnvmapMask ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); + } + + if( hasFlashlight ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER13, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER14, true ); + pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER14 ); + pShaderShadow->EnableTexture( SHADER_SAMPLER15, true ); + } + + if( hasVertexColor ) + { + flags |= VERTEX_COLOR; + } + + // texcoord0 : base texcoord + // texcoord1 : lightmap texcoord + // texcoord2 : lightmap texcoord offset + int numTexCoords; + + // if ( pShaderAPI->InEditorMode() ) +// if ( pShader->CanUseEditorMaterials() ) +// { +// numTexCoords = 1; +// } +// else + { + numTexCoords = 2; + if( hasBump ) + { + numTexCoords = 3; + } + } + + int nLightingPreviewMode = IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER0 ) + 2 * IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER1 ); + + pShaderShadow->VertexShaderVertexFormat( flags, numTexCoords, 0, 0 ); + + // Pre-cache pixel shaders + + int bumpmap_variant=(hasSSBump) ? 2 : hasBump; + + DECLARE_STATIC_VERTEX_SHADER( lightmappedgeneric_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( ENVMAP_MASK, hasEnvmapMask ); + SET_STATIC_VERTEX_SHADER_COMBO( TANGENTSPACE, 1 ); //need tangent transpose matrix for lighting + SET_STATIC_VERTEX_SHADER_COMBO( BUMPMAP, hasBump ); + SET_STATIC_VERTEX_SHADER_COMBO( DIFFUSEBUMPMAP, hasDiffuseBumpmap ); + SET_STATIC_VERTEX_SHADER_COMBO( VERTEXCOLOR, IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR ) ); + SET_STATIC_VERTEX_SHADER_COMBO( VERTEXALPHATEXBLENDFACTOR, 0 ); + SET_STATIC_VERTEX_SHADER_COMBO( BUMPMASK, 0 ); + SET_STATIC_VERTEX_SHADER_COMBO( LIGHTING_PREVIEW, nLightingPreviewMode ); + SET_STATIC_VERTEX_SHADER_COMBO( PARALLAX_MAPPING, 0 ); + SET_STATIC_VERTEX_SHADER_COMBO( SEAMLESS, bSeamlessMapping ); + SET_STATIC_VERTEX_SHADER_COMBO( DETAILTEXTURE, 0 ); + SET_STATIC_VERTEX_SHADER_COMBO( FANCY_BLENDING, bHasBlendModulateTexture ); + SET_STATIC_VERTEX_SHADER_COMBO( SELFILLUM, hasSelfIllum ); +#ifdef _X360 + SET_STATIC_VERTEX_SHADER_COMBO( FLASHLIGHT, hasFlashlight); +#endif + SET_STATIC_VERTEX_SHADER( lightmappedgeneric_vs20 ); + +#define TCOMBINE_NONE 12 // there is no detail texture + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( lightmappedpaint_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP, bumpmap_variant ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, envmap_variant ); + SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS, bSeamlessMapping ); +//#ifdef _X360 + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, hasFlashlight); +//#endif + SET_STATIC_PIXEL_SHADER_COMBO( SHADER_SRGB_READ, bShaderSrgbRead ); + SET_STATIC_PIXEL_SHADER( lightmappedpaint_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( lightmappedpaint_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP, bumpmap_variant ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, envmap_variant ); + SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS, bSeamlessMapping ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, hasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( SHADER_SRGB_READ, bShaderSrgbRead ); + SET_STATIC_PIXEL_SHADER( lightmappedpaint_ps20 ); + } + // HACK HACK HACK - enable alpha writes all the time so that we have them for + // underwater stuff and writing depth to dest alpha + // But only do it if we're not using the alpha already for translucency + pShaderShadow->EnableAlphaWrites( bFullyOpaque ); + + pShaderShadow->EnableSRGBWrite( false ); + + pShader->DefaultFog(); + + float flLScale = pShaderShadow->GetLightMapScaleFactor(); + pShader->PI_BeginCommandBuffer(); + pShader->PI_SetModulationPixelShaderDynamicState( 21 ); + + pShader->PI_SetModulationPixelShaderDynamicState_LinearScale_ScaleInW( 12, flLScale ); + pShader->PI_SetModulationVertexShaderDynamicState_LinearScale( flLScale ); + pShader->PI_EndCommandBuffer(); + } // end shadow state + } // end shadow || regen display list + + if ( pShaderAPI && ( pContextData->m_bMaterialVarsChanged ) ) + { + // need to regenerate the semistatic cmds + pContextData->m_SemiStaticCmdsOut.Reset(); + pContextData->m_bMaterialVarsChanged = false; + + bool bHasBlendMaskTransform= ( + (info.m_nBlendMaskTransform != -1) && + (info.m_nMaskedBlending != -1) && + (params[info.m_nMaskedBlending]->GetIntValue() ) && + ( ! (params[info.m_nBumpTransform]->MatrixIsIdentity() ) ) ); + + // If we don't have a texture transform, we don't have + // to set vertex shader constants or run vertex shader instructions + // for the texture transform. + bool bHasTextureTransform = + !( params[info.m_nBaseTextureTransform]->MatrixIsIdentity() && + params[info.m_nBumpTransform]->MatrixIsIdentity() && + params[info.m_nBumpTransform2]->MatrixIsIdentity() && + params[info.m_nEnvmapMaskTransform]->MatrixIsIdentity() ); + + bHasTextureTransform |= bHasBlendMaskTransform; + + pContextData->m_bVertexShaderFastPath = !bHasTextureTransform; + + if( params[info.m_nDetail]->IsTexture() ) + { + pContextData->m_bVertexShaderFastPath = false; + } + int nTransformToLoad = info.m_nBlendMaskTransform; + if( ( hasBump || hasSSBump ) && !hasSelfIllum && !bHasBlendModulateTexture ) + { + nTransformToLoad = info.m_nBumpTransform; + } + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( + VERTEX_SHADER_SHADER_SPECIFIC_CONST_10, nTransformToLoad ); + + if ( ! pContextData->m_bVertexShaderFastPath ) + { + bool bSeamlessMapping = ( ( info.m_nSeamlessMappingScale != -1 ) && + ( params[info.m_nSeamlessMappingScale]->GetFloatValue() != 0.0 ) ); + bool hasEnvmapMask = params[info.m_nEnvmapMask]->IsTexture(); + if (!bSeamlessMapping ) + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, info.m_nBaseTextureTransform ); + // If we have a detail texture, then the bump texcoords are the same as the base texcoords. + if( hasBump ) + { + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, info.m_nBumpTransform ); + } + if( hasEnvmapMask ) + { + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, info.m_nEnvmapMaskTransform ); + } + } + pContextData->m_SemiStaticCmdsOut.SetEnvMapTintPixelShaderDynamicState( 0, info.m_nEnvmapTint ); + + float envmapTintVal[4]; + float selfIllumTintVal[4]; + params[info.m_nEnvmapTint]->GetVecValue( envmapTintVal, 3 ); + params[info.m_nSelfIllumTint]->GetVecValue( selfIllumTintVal, 3 ); + float envmapContrast = params[info.m_nEnvmapContrast]->GetFloatValue(); + float envmapSaturation = params[info.m_nEnvmapSaturation]->GetFloatValue(); + float fresnelReflection = params[info.m_nFresnelReflection]->GetFloatValue(); + bool hasEnvmap = true; //params[info.m_nEnvmap]->IsTexture(); + int envmap_variant; //0 = no envmap, 1 = regular, 2 = darken in shadow mode + if( hasEnvmap ) + { + //only enabled darkened cubemap mode when the scale calls for it. And not supported in ps20 when also using a 2nd bumpmap + envmap_variant = ((GetFloatParam( info.m_nEnvMapLightScale, params ) > 0.0f) && g_pHardwareConfig->SupportsPixelShaders_2_b()) ? 2 : 1; + } + else + { + envmap_variant = 0; + } + + pContextData->m_bPixelShaderFastPath = true; + bool bUsingContrastOrSaturation = hasEnvmap && ( ( (envmapContrast != 0.0f) && (envmapContrast != 1.0f) ) || (envmapSaturation != 1.0f) ); + bool bUsingFresnel = hasEnvmap && (fresnelReflection != 1.0f); + bool bUsingSelfIllumTint = IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) && (selfIllumTintVal[0] != 1.0f || selfIllumTintVal[1] != 1.0f || selfIllumTintVal[2] != 1.0f); + if ( bUsingContrastOrSaturation || bUsingFresnel || bUsingSelfIllumTint || !g_pConfig->bShowSpecular ) + { + pContextData->m_bPixelShaderFastPath = false; + } + if( !pContextData->m_bPixelShaderFastPath ) + { + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstants( 2, 3 ); + pContextData->m_SemiStaticCmdsOut.OutputConstantData( params[info.m_nEnvmapContrast]->GetVecValue() ); + pContextData->m_SemiStaticCmdsOut.OutputConstantData( params[info.m_nEnvmapSaturation]->GetVecValue() ); + float flFresnel = params[info.m_nFresnelReflection]->GetFloatValue(); + // [ 0, 0, 1-R(0), R(0) ] + pContextData->m_SemiStaticCmdsOut.OutputConstantData4( 0., 0., 1.0 - flFresnel, flFresnel ); + + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 7, params[info.m_nSelfIllumTint]->GetVecValue() ); + } + + // parallax and cubemap light scale mapping parms (c20) + if ( envmap_variant == 2 ) + { + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant4( 20, GetFloatParam( info.m_nHeightScale, params), GetFloatParam( info.m_nEnvMapLightScale, params), 0, 0 ); + } + + // texture binds + + // handle mat_fullbright 2 + bool bLightingOnly = mat_fullbright.GetInt() == 2 && !IS_FLAG_SET( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + if( bLightingOnly ) + { + // disable color modulation + float color[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + pContextData->m_SemiStaticCmdsOut.SetVertexShaderConstant( VERTEX_SHADER_MODULATION_COLOR, color ); + + // turn off environment mapping + envmapTintVal[0] = 0.0f; + envmapTintVal[1] = 0.0f; + envmapTintVal[2] = 0.0f; + } + + if( IS_PARAM_DEFINED( info.m_nPaintSplatNormal ) ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER7, info.m_nPaintSplatNormal ); + } + else + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER7, TEXTURE_NORMALMAP_FLAT ); + } + + + if( hasEnvmapMask ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER5, info.m_nEnvmapMask, info.m_nEnvmapMaskFrame ); + } + + if ( bHasBlendModulateTexture ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER3, info.m_nBlendModulateTexture, -1 ); + } + + if ( hasFlashlight ) + { + pContextData->m_SemiStaticCmdsOut.SetVertexShaderFlashlightState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6 ); + + CBCmdSetPixelShaderFlashlightState_t state; + state.m_LightSampler = SHADER_SAMPLER13; + state.m_DepthSampler = SHADER_SAMPLER14; + state.m_ShadowNoiseSampler = SHADER_SAMPLER15; + state.m_nColorConstant = 28; + state.m_nAttenConstant = 13; + state.m_nOriginConstant = 14; + state.m_nDepthTweakConstant = 19; + state.m_nScreenScaleConstant = 31; + state.m_nWorldToTextureConstant = -1; + state.m_bFlashlightNoLambert = false; + state.m_bSinglePassFlashlight = bSinglePassFlashlight; + pContextData->m_SemiStaticCmdsOut.SetPixelShaderFlashlightState( state ); + } + + pContextData->m_SemiStaticCmdsOut.End(); + } + } + DYNAMIC_STATE + { + pShaderAPI->SetDefaultState(); + CCommandBufferBuilder< CFixedCommandStorageBuffer< 1000 > > DynamicCmdsOut; + DynamicCmdsOut.Call( pContextData->m_pStaticCmds ); + DynamicCmdsOut.Call( pContextData->m_SemiStaticCmdsOut.Base() ); + + bool hasEnvmap = params[info.m_nEnvmap]->IsTexture(); + + if( hasEnvmap ) + { + if( IS_PARAM_DEFINED( info.m_nEnvmap ) ) + { + DynamicCmdsOut.BindTexture( pShader, SHADER_SAMPLER2, info.m_nEnvmap, info.m_nEnvmapFrame ); + } + else + { + DynamicCmdsOut.BindTexture( pShader, SHADER_SAMPLER2, info.m_nPaintSplatEnvMap ); + } + } + + bool bVertexShaderFastPath = pContextData->m_bVertexShaderFastPath; + + int nFixedLightingMode = pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_ENABLE_FIXED_LIGHTING ); + if( nFixedLightingMode != ENABLE_FIXED_LIGHTING_NONE ) + { + if ( pContextData->m_bPixelShaderForceFastPathBecauseOutline ) + { + nFixedLightingMode = ENABLE_FIXED_LIGHTING_NONE; + } + else + { + bVertexShaderFastPath = false; + } + } + + bool bWorldNormal = ( nFixedLightingMode == ENABLE_FIXED_LIGHTING_OUTPUTNORMAL_AND_DEPTH ); + if ( bWorldNormal && IsPC() ) + { + float vEyeDir[4]; + pShaderAPI->GetWorldSpaceCameraDirection( vEyeDir ); + + float flFarZ = pShaderAPI->GetFarZ(); + vEyeDir[0] /= flFarZ; // Divide by farZ for SSAO algorithm + vEyeDir[1] /= flFarZ; + vEyeDir[2] /= flFarZ; + DynamicCmdsOut.SetVertexShaderConstant4( 12, vEyeDir[0], vEyeDir[1], vEyeDir[2], 1.0f ); + } + + MaterialFogMode_t fogType = pShaderAPI->GetSceneFogMode(); + DECLARE_DYNAMIC_VERTEX_SHADER( lightmappedgeneric_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( FASTPATH, bVertexShaderFastPath ); + SET_DYNAMIC_VERTEX_SHADER_CMD( DynamicCmdsOut, lightmappedgeneric_vs20 ); + + bool bPixelShaderFastPath = pContextData->m_bPixelShaderFastPath; + + if ( nFixedLightingMode != ENABLE_FIXED_LIGHTING_NONE ) + { + bPixelShaderFastPath = false; + } + bool bWriteDepthToAlpha; + bool bWriteWaterFogToAlpha; + if( pContextData->m_bFullyOpaque ) + { + bWriteDepthToAlpha = pShaderAPI->ShouldWriteDepthToDestAlpha(); + bWriteWaterFogToAlpha = (fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z); + AssertMsg( !(bWriteDepthToAlpha && bWriteWaterFogToAlpha), "Can't write two values to alpha at the same time." ); + } + else + { + //can't write a special value to dest alpha if we're actually using as-intended alpha + bWriteDepthToAlpha = false; + bWriteWaterFogToAlpha = false; + } + + bool bFlashlightShadows = false; + bool bUberlight = false; + if( hasFlashlight && IsX360() ) + { + pShaderAPI->GetFlashlightShaderInfo( &bFlashlightShadows, &bUberlight ); + } + else + { + // only do ambient light when not using flashlight + static ConVarRef mat_ambient_light_r_forced( "mat_ambient_light_r_forced" ); + static ConVarRef mat_ambient_light_g_forced( "mat_ambient_light_g_forced" ); + static ConVarRef mat_ambient_light_b_forced( "mat_ambient_light_b_forced" ); + + float vAmbientColor[4] = { mat_ambient_light_r_forced.GetFloat() != -1.0f ? mat_ambient_light_r_forced.GetFloat() : mat_ambient_light_r.GetFloat(), + mat_ambient_light_g_forced.GetFloat() != -1.0f ? mat_ambient_light_g_forced.GetFloat() : mat_ambient_light_g.GetFloat(), + mat_ambient_light_b_forced.GetFloat() != -1.0f ? mat_ambient_light_b_forced.GetFloat() : mat_ambient_light_b.GetFloat(), + 0.0f }; + if ( mat_fullbright.GetInt() == 1 ) + { + vAmbientColor[0] = vAmbientColor[1] = vAmbientColor[2] = 0.0f; + } + DynamicCmdsOut.SetPixelShaderConstant( 31, vAmbientColor, 1 ); + } + + float envmapContrast = params[info.m_nEnvmapContrast]->GetFloatValue(); + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( lightmappedpaint_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FASTPATH, bPixelShaderFastPath || pContextData->m_bPixelShaderForceFastPathBecauseOutline ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FASTPATHENVMAPCONTRAST, bPixelShaderFastPath && envmapContrast == 1.0f ); + + // Don't write fog to alpha if we're using translucency + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER_CMD( DynamicCmdsOut, lightmappedpaint_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( lightmappedpaint_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FASTPATH, bPixelShaderFastPath ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FASTPATHENVMAPCONTRAST, bPixelShaderFastPath && envmapContrast == 1.0f ); + + // Don't write fog to alpha if we're using translucency + SET_DYNAMIC_PIXEL_SHADER_CMD( DynamicCmdsOut, lightmappedpaint_ps20 ); + } + + DynamicCmdsOut.End(); + pShaderAPI->ExecuteCommandBuffer( DynamicCmdsOut.Base() ); + } + pShader->Draw(); +} diff --git a/materialsystem/stdshaders/lightmappedpaint_dx9_helper.h b/materialsystem/stdshaders/lightmappedpaint_dx9_helper.h new file mode 100644 index 00000000..b79964e4 --- /dev/null +++ b/materialsystem/stdshaders/lightmappedpaint_dx9_helper.h @@ -0,0 +1,18 @@ +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef LIGHTMAPPEDPAINT_DX9_HELPER_H +#define LIGHTMAPPEDPAINT_DX9_HELPER_H + +#include "lightmappedgeneric_dx9_helper.h" + +void DrawLightmappedPaint_DX9( CBaseVSShader *pShader, IMaterialVar** params, + IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, + LightmappedGeneric_DX9_Vars_t &info, CBasePerMaterialContextData **pContextDataPtr ); + + +#endif // LIGHTMAPPEDPAINT_DX9_HELPER_H diff --git a/materialsystem/stdshaders/lightmappedpaint_ps2x.fxc b/materialsystem/stdshaders/lightmappedpaint_ps2x.fxc new file mode 100644 index 00000000..0619e34d --- /dev/null +++ b/materialsystem/stdshaders/lightmappedpaint_ps2x.fxc @@ -0,0 +1,357 @@ +// STATIC: "BUMPMAP" "0..2" +// STATIC: "CUBEMAP" "0..2" +// STATIC: "SEAMLESS" "0..1" +// STATIC: "FLASHLIGHT" "0..1" +// STATIC: "SHADER_SRGB_READ" "0..1" [XBOX] +// STATIC: "SHADER_SRGB_READ" "0..0" [PC] + +// DYNAMIC: "FASTPATHENVMAPCONTRAST" "0..1" +// DYNAMIC: "FASTPATH" "0..1" +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps20b] + +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 ) +// SKIP: ( $CUBEMAP == 0 ) +// SKIP: ( $BUMPMAP == 0 ) + +#include "common_fog_ps_supportsvertexfog_fxc.h" + +#include "common_ps_fxc.h" +#include "common_flashlight_fxc.h" +#define PIXELSHADER +#include "common_lightmappedgeneric_fxc.h" + +#if SEAMLESS +#define USE_FAST_PATH 1 +#else +#define USE_FAST_PATH FASTPATH +#endif + +const float4 g_EnvmapTint : register( c0 ); + +#if USE_FAST_PATH == 1 + +# if FASTPATHENVMAPCONTRAST == 0 +static const float3 g_EnvmapContrast = { 0.0f, 0.0f, 0.0f }; +# else +static const float3 g_EnvmapContrast = { 1.0f, 1.0f, 1.0f }; +# endif +static const float3 g_EnvmapSaturation = { 1.0f, 1.0f, 1.0f }; +static const float g_FresnelReflection = 1.0f; +static const float g_OneMinusFresnelReflection = 0.0f; +static const float4 g_SelfIllumTint = { 1.0f, 1.0f, 1.0f, 1.0f }; + + +#else + +const float3 g_EnvmapContrast : register( c2 ); +const float3 g_EnvmapSaturation : register( c3 ); +const float4 g_FresnelReflectionReg : register( c4 ); +#define g_FresnelReflection g_FresnelReflectionReg.a +#define g_OneMinusFresnelReflection g_FresnelReflectionReg.b +const float4 g_SelfIllumTint : register( c7 ); +#endif + + +const float3 g_EyePos : register( c10 ); +const float4 g_FogParams : register( c11 ); +const float4 g_TintValuesTimesLightmapScale : register( c12 ); + +#define g_flAlpha2 g_TintValuesTimesLightmapScale.w + +const float4 g_FlashlightAttenuationFactors : register( c13 ); +const float3 g_FlashlightPos : register( c14 ); +const float4x4 g_FlashlightWorldToTexture : register( c15 ); // through c18 +const float4 g_ShadowTweaks : register( c19 ); + +#if !defined( SHADER_MODEL_PS_2_0 ) && ( FLASHLIGHT == 0 ) +#define g_cAmbientColor cFlashlightScreenScale.rgb +//const float3 g_cAmbientColor : register( c31 ); +#endif + +#if PARALLAX_MAPPING || (CUBEMAP == 2) +const float4 g_ParallaxMappingControl : register( c20 ); +#endif + +#if (CUBEMAP == 2) +#define g_DiffuseCubemapScale g_ParallaxMappingControl.y +#endif + +const float3 g_TintValuesWithoutLightmapScale : register( c21 ); + + + + +sampler LightmapSampler : register( s1 ); +sampler EnvmapSampler : register( s2 ); +sampler NoiseSampler_2D : register( s6 ); +sampler SplatNormalSampler : register( s7 ); + +sampler PaintSampler : register( s9 ); + +#if defined( _X360 ) && FLASHLIGHT +sampler FlashlightSampler : register( s13 ); +sampler ShadowDepthSampler : register( s14 ); +sampler RandRotSampler : register( s15 ); +#endif + +#define DummySampler SplatNormalSampler + +float4 main( PS_INPUT i ) : COLOR +{ + bool bCubemap = CUBEMAP ? true : false; + + float4 vNormal = float4(0, 0, 1, 1); + float3 coords = float3(0,0,0); + float3 worldPos = i.worldPos_projPosZ.xyz; + float3x3 tangenttranspose = i.tangentSpaceTranspose; + float3x3 worldToTangentSpace = transpose( tangenttranspose ); //yay, math both forwards and backwards, for kicks! + + float3 worldVertToEyeVector = g_EyePos - worldPos; + + +#if SEAMLESS + coords = i.SeamlessTexCoord_fogFactorW.xyz; +#else + coords.xy = i.BASETEXCOORD.xy; +#endif + + float4 vDummy = 0.0f; + + GetBaseTextureAndNormal( DummySampler, DummySampler, DummySampler, + false, false, + coords, vDummy, + i.vertexColor.rgb, vDummy, vDummy, vNormal ); + +#if BUMPMAP == 1 // not ssbump + vNormal.xyz = vNormal.xyz * 2.0f - 1.0f; // make signed if we're not ssbump +#endif + + float3 lightmapColor1 = float3( 1.0f, 1.0f, 1.0f ); + float3 lightmapColor2 = float3( 1.0f, 1.0f, 1.0f ); + float3 lightmapColor3 = float3( 1.0f, 1.0f, 1.0f ); + float4 paintColor; + + { + float2 bumpCoord1; + float2 bumpCoord2; + float2 bumpCoord3; + ComputeBumpedLightmapCoordinates( i.lightmapTexCoord1And2, i.lightmapTexCoord3.xy, + bumpCoord1, bumpCoord2, bumpCoord3 ); + + lightmapColor1 = LightMapSample( LightmapSampler, bumpCoord1 ); + lightmapColor2 = LightMapSample( LightmapSampler, bumpCoord2 ); + lightmapColor3 = LightMapSample( LightmapSampler, bumpCoord3 ); + + float2 paintCoord; + paintCoord.y = bumpCoord1.y; + paintCoord.x = bumpCoord1.x - ( bumpCoord2.x - bumpCoord1.x ); + paintColor = tex2D( PaintSampler, paintCoord ); + } + +#if defined( SHADER_MODEL_PS_2_0 ) + return paintColor; +#endif + + //float noiseSample = tex2D( NoiseSampler_2D, i.lightmapTexCoord1And2.xy * 1000.0f ).r; + //paintColor.a -= noiseSample * 0.2f; + + float alpha = paintColor.a; + clip( alpha - 0.01f ); + + //paint splat guts + + float3 fvViewDirection = mul( normalize( worldVertToEyeVector ), worldToTangentSpace ); + float4 fvSplats = tex2D( SplatNormalSampler, coords ); + float4 fvSplatsPushed = tex2D( SplatNormalSampler, coords + fvViewDirection * fvSplats.a * paintColor.a * 0.05 ); + + float3 fvNormal = normalize( ( fvSplatsPushed.xyz * 2.0f ) - 1.0f ); + fvNormal.xy *= 20.0f; + + float3 fvLightDirection = float3( 0.0f, 0.0f, 1.0f ); //mul( normalize( vLightPos - worldPos ), worldToTangentSpace ); + float2 shadowTex = coords + ( fvLightDirection.xy * 0.005 ); + float4 fvSplatShadow = tex2D( SplatNormalSampler, shadowTex ); + float4 fvLMShadow = tex2D( PaintSampler, shadowTex ).a; + float3 shadowColor = ( fvLMShadow.r + fvSplatShadow.a ); + + alpha = (paintColor.a + max( fvSplats.a, fvSplatsPushed.a ) ); + float shadow = ( shadowColor.r > 0.68f ) * ( alpha < 0.755f ); + + float lerpRange = smoothstep( 1.0f, 0.2f, alpha * 0.5f ); + lerpRange = pow( lerpRange, 6.0f ); + + + fvNormal.xyz = lerp( float4(0, 0, 1, 1), fvNormal, lerpRange ); //use existing vNormal to incorporate any bumpmap on the surface + fvNormal.xyz = normalize( fvNormal.xyz ); + vNormal.xyz = fvNormal; + + + //dark paint color to white'ish paint color + //float4 fvBaseColor = tex2D( grad, smoothstep( 0.3f, 1.4f, fvSplatsPushed.a + fvLM.r ) * 0.2f ); + float3 fvBaseColor = saturate( lerp( paintColor.rgb * 0.32f, float3( 1.0f, 1.0f, 1.0f ), smoothstep( 0.3f, 1.4f, fvSplatsPushed.a + paintColor.a ) * 0.2f )); + + + + + // Save this off for single-pass flashlight, since we'll still need the SSBump vector, not a real normal + float3 vSSBumpVector = vNormal.xyz; + + + float3 diffuseLighting; + { +// ssbump +#if ( BUMPMAP == 2 ) + diffuseLighting = vNormal.x * lightmapColor1 + + vNormal.y * lightmapColor2 + + vNormal.z * lightmapColor3; + + diffuseLighting *= g_TintValuesTimesLightmapScale.rgb; + // now, calculate vNormal for reflection purposes. if vNormal isn't needed, hopefully + // the compiler will eliminate these calculations + vNormal.xyz = normalize( bumpBasis[0]*vNormal.x + bumpBasis[1]*vNormal.y + bumpBasis[2]*vNormal.z); +#else + float3 dp; + dp.x = saturate( dot( vNormal, bumpBasis[0] ) ); + dp.y = saturate( dot( vNormal, bumpBasis[1] ) ); + dp.z = saturate( dot( vNormal, bumpBasis[2] ) ); + dp *= dp; + + diffuseLighting = dp.x * lightmapColor1 + + dp.y * lightmapColor2 + + dp.z * lightmapColor3; + float sum = dot( dp, float3( 1.0f, 1.0f, 1.0f ) ); + diffuseLighting *= g_TintValuesTimesLightmapScale.rgb / sum; +#endif + } + + + + float3 specularLight; + { + float3 vBouncedView = CalcReflectionVectorUnnormalized( fvNormal, fvViewDirection ); + specularLight = vBouncedView.x * lightmapColor1 + + vBouncedView.y * lightmapColor2 + + vBouncedView.z * lightmapColor3; + + specularLight *= g_TintValuesTimesLightmapScale.rgb;// / g_TintValuesWithoutLightmapScale.rgb; + + + specularLight = max( 0.0f, specularLight ); + //return float4( specularLight, 1.0f ); + specularLight = pow( specularLight, 3.0f ); + //specularLight = saturate( specularLight ); + } + + //return float4( diffuseLighting, 1.0f ); + + float3 worldSpaceNormal = mul( vNormal, tangenttranspose ); +#if !defined( SHADER_MODEL_PS_2_0 ) && ( FLASHLIGHT == 0 ) + diffuseLighting += g_cAmbientColor; +#endif + + + float3 diffuseComponent = paintColor.rgb * diffuseLighting; + +#if defined( _X360 ) && FLASHLIGHT + + // ssbump doesn't pass a normal to the flashlight...it computes shadowing a different way +#if ( BUMPMAP == 2 ) + bool bHasNormal = false; + + float3 worldPosToLightVector = g_FlashlightPos - worldPos; + + float3 tangentPosToLightVector; + tangentPosToLightVector.x = dot( worldPosToLightVector, tangenttranspose[0] ); + tangentPosToLightVector.y = dot( worldPosToLightVector, tangenttranspose[1] ); + tangentPosToLightVector.z = dot( worldPosToLightVector, tangenttranspose[2] ); + + tangentPosToLightVector = normalize( tangentPosToLightVector ); + float nDotL = saturate( vSSBumpVector.x*dot( tangentPosToLightVector, bumpBasis[0]) + + vSSBumpVector.y*dot( tangentPosToLightVector, bumpBasis[1]) + + vSSBumpVector.z*dot( tangentPosToLightVector, bumpBasis[2]) ); +#else + bool bHasNormal = true; + float nDotL = 1.0f; +#endif + + bool bShadows = FLASHLIGHTSHADOWS ? true : false; + float3 flashlightColor = DoFlashlight( g_FlashlightPos, worldPos, i.flashlightSpacePos, + worldSpaceNormal, g_FlashlightAttenuationFactors.xyz, + g_FlashlightAttenuationFactors.w, FlashlightSampler, ShadowDepthSampler, + RandRotSampler, 0, bShadows, false, i.vProjPos.xy / i.vProjPos.w, false, g_ShadowTweaks, bHasNormal ); + + diffuseComponent = paintColor.rgb * ( diffuseLighting + ( flashlightColor * nDotL * g_TintValuesWithoutLightmapScale.rgb ) ); +#endif + + float3 specularFactor = 1.0f; + + float3 specularLighting = float3( 0.0f, 0.0f, 0.0f ); +#if CUBEMAP + if( bCubemap ) + { + float3 reflectVect = CalcReflectionVectorUnnormalized( worldSpaceNormal, worldVertToEyeVector ); + + // Calc Fresnel factor + half3 eyeVect = normalize(worldVertToEyeVector); + float fresnel = 1.0 - dot( worldSpaceNormal, eyeVect ); + fresnel = pow( fresnel, 5.0 ); + fresnel = fresnel * g_OneMinusFresnelReflection + g_FresnelReflection; + + specularLighting = ENV_MAP_SCALE * texCUBE( EnvmapSampler, reflectVect ); +#if (CUBEMAP == 2) //cubemap darkened by lightmap mode + specularLighting = lerp( specularLighting, specularLighting * saturate( diffuseLighting ), g_DiffuseCubemapScale ); //reduce the cubemap contribution when the pixel is in shadow +#endif + specularLighting *= specularFactor; + + specularLighting *= g_EnvmapTint; + specularLighting *= fresnel; + + specularLight *= fresnel; + } +#endif + + + float3 result;// = diffuseComponent; + + + //paint guts part 2 + { + + float4 fvSpecular = float4( 0.211765f, 0.209893f, 0.209893f, 1.0f ); + float4 fvAmbient = float4( 0.333f, 0.333f, 0.333f, 1.0f ); + float4 fvDiffuse = float4( 0.888f, 0.888f, 0.888f, 1.0f ); + //float4 fBuffer = tex2D( framebuffer, Input.Screencoord ); + + float3 fvTotalAmbient = fvAmbient * fvBaseColor; + float3 fvTotalDiffuse = diffuseComponent * 0.5f; //fvBaseColor; //fvDiffuse * fNDotL * fvBaseColor; + //float3 fvTotalSpecular = specularLighting * 0.1f * paintColor.rgb; + //float3 fvTotalSpecular = fvSpecular * pow( fRDotV, fSpecularPower ); + float3 fvTotalSpecular = specularLight * 0.2f;// * paintColor.rgb; + + alpha = alpha > 0.75f; + result = saturate( fvTotalAmbient + fvTotalDiffuse + fvTotalSpecular ).rgb; + } + + + + + + + float flVertexFogFactor = 0.0f; + #if !HARDWAREFOGBLEND && !DOPIXELFOG + { + #if ( SEAMLESS ) + { + flVertexFogFactor = i.SeamlessTexCoord_fogFactorW.w; + } + #else + { + flVertexFogFactor = i.baseTexCoord_fogFactorZ.z; + } + #endif + } + #endif + float fogFactor = CalcPixelFogFactorSupportsVertexFog( PIXELFOGTYPE, g_FogParams, g_EyePos.xyz, worldPos, i.worldPos_projPosZ.w, flVertexFogFactor ); + + return FinalOutput( float4( result.rgb, alpha ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, false, i.worldPos_projPosZ.w ); +} + diff --git a/materialsystem/stdshaders/lightmappedreflective.cpp b/materialsystem/stdshaders/lightmappedreflective.cpp new file mode 100644 index 00000000..2bdd1aa3 --- /dev/null +++ b/materialsystem/stdshaders/lightmappedreflective.cpp @@ -0,0 +1,260 @@ +//============ Copyright (c) Valve Corporation, All rights reserved. ============ + +#include "BaseVSShader.h" +#include "mathlib/VMatrix.h" +#include "common_hlsl_cpp_consts.h" // hack hack hack! + +#include "lightmappedreflective_vs20.inc" +#include "lightmappedreflective_ps20.inc" +#include "lightmappedreflective_ps20b.inc" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( LightmappedReflective, LightmappedReflective_DX90 ) + +BEGIN_VS_SHADER( LightmappedReflective_DX90, "Help for Lightmapped Reflective" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( REFRACTTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "_rt_WaterRefraction", "" ) + SHADER_PARAM( REFLECTTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "_rt_WaterReflection", "" ) + SHADER_PARAM( REFRACTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "0", "" ) + SHADER_PARAM( REFRACTTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "refraction tint" ) + SHADER_PARAM( REFLECTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "0.8", "" ) + SHADER_PARAM( REFLECTTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "reflection tint" ) + SHADER_PARAM( NORMALMAP, SHADER_PARAM_TYPE_TEXTURE, "dev/water_normal", "normal map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( ENVMAPMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_envmask", "envmap mask" ) + SHADER_PARAM( ENVMAPMASKFRAME, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( REFLECTANCE, SHADER_PARAM_TYPE_FLOAT, "0.25", "" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + if ( !params[REFLECTANCE]->IsDefined() ) + { + params[REFLECTANCE]->SetFloatValue( 0.25f ); + } + + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + if ( params[BASETEXTURE]->IsDefined() ) + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + if ( g_pConfig->UseBumpmapping() && params[NORMALMAP]->IsDefined() ) + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_BUMPED_LIGHTMAP ); + } + } + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + if ( params[REFRACTTEXTURE]->IsDefined() ) + { + LoadTexture( REFRACTTEXTURE ); + } + if ( params[REFLECTTEXTURE]->IsDefined() ) + { + LoadTexture( REFLECTTEXTURE ); + } + if ( params[NORMALMAP]->IsDefined() ) + { + LoadBumpMap( NORMALMAP ); + } + if ( params[BASETEXTURE]->IsDefined() ) + { + LoadTexture( BASETEXTURE ); + if ( params[ENVMAPMASK]->IsDefined() ) + { + LoadTexture( ENVMAPMASK ); + } + } + else + { + params[ENVMAPMASK]->SetUndefined(); + } + } + + inline void DrawReflectionRefraction( IMaterialVar **params, IShaderShadow *pShaderShadow, + IShaderDynamicAPI *pShaderAPI, bool bReflection, bool bRefraction ) + { + BlendType_t nBlendType = EvaluateBlendRequirements( BASETEXTURE, true ); + bool bFullyOpaque = ( nBlendType != BT_BLENDADD ) && ( nBlendType != BT_BLEND ) && !IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ); //dest alpha is free for special use + + SHADOW_STATE + { + SetInitialShadowState(); + if ( bRefraction ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + } + + if ( bReflection ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, true ); + } + + if ( params[BASETEXTURE]->IsTexture() ) + { + // BASETEXTURE + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + // LIGHTMAP + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + + if ( params[ENVMAPMASK]->IsTexture() ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); + } + } + + // normal map + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + + int fmt = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_TANGENT_S | VERTEX_TANGENT_T; + + // texcoord0 : base texcoord + // texcoord1 : lightmap texcoord + // texcoord2 : lightmap texcoord offset + int numTexCoords = 1; + if ( params[BASETEXTURE]->IsTexture() ) + { + numTexCoords = 3; + } + pShaderShadow->VertexShaderVertexFormat( fmt, numTexCoords, 0, 0 ); + + if ( IS_FLAG_SET( MATERIAL_VAR_TRANSLUCENT ) ) + { + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + + DECLARE_STATIC_VERTEX_SHADER( lightmappedreflective_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( BASETEXTURE, params[BASETEXTURE]->IsTexture() ); + SET_STATIC_VERTEX_SHADER( lightmappedreflective_vs20 ); + + // "REFLECT" "0..1" + // "REFRACT" "0..1" + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( lightmappedreflective_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( REFLECT, bReflection ); + SET_STATIC_PIXEL_SHADER_COMBO( REFRACT, bRefraction ); + SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE, params[BASETEXTURE]->IsTexture() ); + SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPMASK, params[ENVMAPMASK]->IsTexture() && params[BASETEXTURE]->IsTexture() ); + SET_STATIC_PIXEL_SHADER( lightmappedreflective_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( lightmappedreflective_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( REFLECT, bReflection ); + SET_STATIC_PIXEL_SHADER_COMBO( REFRACT, bRefraction ); + SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE, params[BASETEXTURE]->IsTexture() ); + SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPMASK, params[ENVMAPMASK]->IsTexture() && params[BASETEXTURE]->IsTexture() ); + SET_STATIC_PIXEL_SHADER( lightmappedreflective_ps20 ); + } + + FogToFogColor(); + + // we are writing linear values from this shader. + pShaderShadow->EnableSRGBWrite( true ); + + pShaderShadow->EnableAlphaWrites( bFullyOpaque ); + } + DYNAMIC_STATE + { + if ( bRefraction ) + { + // HDRFIXME: add comment about binding.. Specify the number of MRTs in the enable + BindTexture( SHADER_SAMPLER0, REFRACTTEXTURE, -1 ); + } + + if ( bReflection ) + { + BindTexture( SHADER_SAMPLER2, REFLECTTEXTURE, -1 ); + } + + BindTexture( SHADER_SAMPLER4, NORMALMAP, BUMPFRAME ); + + if ( params[BASETEXTURE]->IsTexture() ) + { + BindTexture( SHADER_SAMPLER1, BASETEXTURE, FRAME ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER3, TEXTURE_LIGHTMAP ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, BASETEXTURETRANSFORM ); + + if ( params[ENVMAPMASK]->IsTexture() ) + { + BindTexture( SHADER_SAMPLER6, ENVMAPMASK, ENVMAPMASKFRAME ); + } + } + + // Refraction tint + if ( bRefraction ) + { + SetPixelShaderConstantGammaToLinear( 1, REFRACTTINT ); + } + + // Reflection tint + if ( bReflection ) + { + SetPixelShaderConstantGammaToLinear( 4, REFLECTTINT ); + } + + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, BUMPTRANSFORM ); + + float c0[4] = { 1.0f / 3.0f, 1.0f / 3.0f, 1.0f / 3.0f, 0.0f }; + pShaderAPI->SetPixelShaderConstant( 0, c0, 1 ); + + float c2[4] = { 0.5f, 0.5f, 0.5f, 0.5f }; + pShaderAPI->SetPixelShaderConstant( 2, c2, 1 ); + + // fresnel constants + float c3[4] = { clamp( params[REFLECTANCE]->GetFloatValue(), 0.0f, 1.0f ), 0.0f, 0.0f, 0.0f }; + pShaderAPI->SetPixelShaderConstant( 3, c3, 1 ); + + float c5[4] = { params[REFLECTAMOUNT]->GetFloatValue(), params[REFLECTAMOUNT]->GetFloatValue(), + params[REFRACTAMOUNT]->GetFloatValue(), params[REFRACTAMOUNT]->GetFloatValue() }; + pShaderAPI->SetPixelShaderConstant( 5, c5, 1 ); + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + float vEyePos_SpecExponent[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + vEyePos_SpecExponent[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( lightmappedreflective_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( lightmappedreflective_vs20 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( lightmappedreflective_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bFullyOpaque && pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( lightmappedreflective_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( lightmappedreflective_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( lightmappedreflective_ps20 ); + } + } + Draw(); + } + + SHADER_DRAW + { + bool bRefraction = params[REFRACTTEXTURE]->IsTexture(); + bool bReflection = params[REFLECTTEXTURE]->IsTexture(); + DrawReflectionRefraction( params, pShaderShadow, pShaderAPI, bReflection, bRefraction ); + } + +END_SHADER diff --git a/materialsystem/stdshaders/lightmappedreflective_ps2x.fxc b/materialsystem/stdshaders/lightmappedreflective_ps2x.fxc new file mode 100644 index 00000000..a11838ce --- /dev/null +++ b/materialsystem/stdshaders/lightmappedreflective_ps2x.fxc @@ -0,0 +1,184 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "BASETEXTURE" "0..1" +// STATIC: "REFLECT" "0..1" +// STATIC: "REFRACT" "0..1" +// STATIC: "ENVMAPMASK" "0..1" + +#include "common_fog_ps_fxc.h" +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] + +#if defined( SHADER_MODEL_PS_2_0 ) + #define WRITE_DEPTH_TO_DESTALPHA 0 +#endif + +#include "common_ps_fxc.h" +#include "shader_constant_register_map.h" + +sampler RefractSampler : register( s0 ); +sampler BaseTextureSampler : register( s1 ); +sampler ReflectSampler : register( s2 ); +#if BASETEXTURE + sampler LightmapSampler : register( s3 ); +#endif +#if ENVMAPMASK + sampler EnvMapMaskSampler : register( s6 ); +#endif +sampler NormalSampler : register( s4 ); + +const float4 g_vRefractTint : register( c1 ); +const float g_flReflectance : register( c3 ); +const float4 g_vReflectTint : register( c4 ); +const float4 g_ReflectRefractScale : register( c5 ); // xy - reflect scale, zw - refract scale + +const float4 g_PixelFogParams : register( PSREG_FOG_PARAMS ); +const float4 g_EyePos : register( PSREG_EYEPOS_SPEC_EXPONENT ); + +static const bool g_bReflect = REFLECT ? true : false; +static const bool g_bRefract = REFRACT ? true : false; + +struct PS_INPUT +{ + float4 vBumpTexCoordXY_vTexCoordXY : TEXCOORD0; + float4 vPositionToCameraRayTs_projW : TEXCOORD1; + float4 vReflectXY_vRefractYX : TEXCOORD2; + float4 vProjPos : TEXCOORD4; + float3 worldPos : TEXCOORD5; + +#if BASETEXTURE +// CENTROID: TEXCOORD6 + float4 lightmapTexCoord1And2 : TEXCOORD6; +// CENTROID: TEXCOORD7 + float4 lightmapTexCoord3 : TEXCOORD7; +#endif +}; + +float4 main( PS_INPUT i ) : COLOR +{ + // Load normal and expand range + float4 vNormalTexel = tex2D( NormalSampler, i.vBumpTexCoordXY_vTexCoordXY.xy ); + float3 vNormalTs = normalize( ( vNormalTexel.xyz * 2.0 ) - 1.0 ); + + // Perform division by W only once + float ooW = 1.0f / i.vPositionToCameraRayTs_projW.w; + //float2 unwarpedRefractTexCoord = i.vReflectXY_vRefractYX.wz * ooW; + + // Vectorize the dependent UV calculations (reflect = .xy, refract = .wz) + #ifdef NV3X + float4 vDependentTexCoords = vNormalTs.xyxy * vNormalTexel.a * g_ReflectRefractScale.xyzw; + #else + float4 vN; + vN.xy = vNormalTs.xy; + vN.w = vNormalTs.x; + vN.z = vNormalTs.y; + float4 vDependentTexCoords = vN * vNormalTexel.a * g_ReflectRefractScale.xyzw; + #endif + + vDependentTexCoords.xyzw += i.vReflectXY_vRefractYX.xyzw * ooW; + float2 vReflectTexCoord = vDependentTexCoords.xy; + float2 vRefractTexCoord = vDependentTexCoords.wz; + + // Sample reflection + float3 vReflectColor = float3( 0.0f, 0.0f, 0.0f ); + #if ( REFLECT ) + { + vReflectColor.rgb = tex2D( ReflectSampler, vReflectTexCoord ).rgb; + vReflectColor.rgb *= g_vReflectTint.rgb; + } + #endif + + // Sample refraction + float3 vRefractColor = float3( 0.0f, 0.0f, 0.0f ); + #if ( REFRACT ) + { + vRefractColor = tex2D( RefractSampler, vRefractTexCoord ); + vRefractColor.rgb *= g_vRefractTint.rgb; + } + #endif + + // Schlick Fresnel + float3 vPositionToCameraDirTs = normalize( i.vPositionToCameraRayTs_projW.xyz ); + float flNdotV = saturate( dot( vPositionToCameraDirTs.xyz, vNormalTs.xyz ) ); + float flFresnel = g_flReflectance + ( ( 1.0f - g_flReflectance ) * pow( 1.0f - flNdotV, 5.0f ) ); + //flFresnel = 1.0f - flFresnel; + //return flFresnel; + + float flRefractMask = 0.0f; + #if BASETEXTURE + float4 baseSample = tex2D( BaseTextureSampler, i.vBumpTexCoordXY_vTexCoordXY.zw ); + flRefractMask = baseSample.a; + + float2 bumpCoord1; + float2 bumpCoord2; + float2 bumpCoord3; + ComputeBumpedLightmapCoordinates( i.lightmapTexCoord1And2, i.lightmapTexCoord3.xy, + bumpCoord1, bumpCoord2, bumpCoord3 ); + + float4 lightmapSample1 = tex2D( LightmapSampler, bumpCoord1 ); + float3 lightmapColor1 = lightmapSample1.rgb; + float3 lightmapColor2 = tex2D( LightmapSampler, bumpCoord2 ); + float3 lightmapColor3 = tex2D( LightmapSampler, bumpCoord3 ); + + float3 dp; + dp.x = saturate( dot( vNormalTs, bumpBasis[0] ) ); + dp.y = saturate( dot( vNormalTs, bumpBasis[1] ) ); + dp.z = saturate( dot( vNormalTs, bumpBasis[2] ) ); + dp *= dp; + + float3 diffuseLighting = dp.x * lightmapColor1 + + dp.y * lightmapColor2 + + dp.z * lightmapColor3; + float sum = dot( dp, float3( 1.0f, 1.0f, 1.0f ) ); + diffuseLighting *= LIGHT_MAP_SCALE / sum; + float3 diffuseComponent = baseSample.rgb * diffuseLighting; + #endif + + // Mask + float3 vSpecMask = float3( 1.0f, 1.0f, 1.0f ); + #if ( REFLECT && ENVMAPMASK ) + { + vSpecMask.rgb = tex2D( EnvMapMaskSampler, i.vBumpTexCoordXY_vTexCoordXY.zw ).rgb; + } + #endif + + // NOTE: the BASETEXTURE path hasn't been tested (or really written for that matter, just copied from water) + // What I think should happen is that the alpha of base texture should be its 'translucency' + // which should indicate how much refraction to use. + // We should add an envmapmask to deal with how much reflection to use + // along with all the focus, etc. features + float4 result = float4( 0.0f, 0.0f, 0.0f, 1.0f ); + #if ( REFLECT || REFRACT ) + { + // Refraction + result.rgb = vRefractColor.rgb * ( 1.0f - flFresnel ); + + // Add in diffuse component applying fresnel to pixels with no spec mask + #if ( BASETEXTURE ) + { + result.rgb += lerp( diffuseComponent.rgb, diffuseComponent.rgb * ( 1.0f - flFresnel ), vSpecMask.rgb ); + } + #endif + + // Add reflection + result.rgb += ( vReflectColor.rgb * flFresnel ) * vSpecMask.rgb; + } + #else // No reflect or refract + { + #if ( BASETEXTURE ) + { + result.rgba = float4( diffuseComponent.rgb, flRefractMask ); + } + #endif + } + #endif + + float fogFactor = 0.0f; + #if ( PIXELFOGTYPE == PIXEL_FOG_TYPE_RANGE ) + { + fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_PixelFogParams, g_EyePos.xyz, i.worldPos.xyz, i.vProjPos.z ); + } + #endif + + return FinalOutput( result.rgba, fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_NONE, ( WRITE_DEPTH_TO_DESTALPHA != 0 ), i.vProjPos.z ); +} diff --git a/materialsystem/stdshaders/lightmappedreflective_vs20.fxc b/materialsystem/stdshaders/lightmappedreflective_vs20.fxc new file mode 100644 index 00000000..95852098 --- /dev/null +++ b/materialsystem/stdshaders/lightmappedreflective_vs20.fxc @@ -0,0 +1,109 @@ +//============ Copyright (c) Valve Corporation, All rights reserved. ============ + +// STATIC: "BASETEXTURE" "0..1" + +#include "common_vs_fxc.h" + +const float4 cBumpTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_1 ); +const float4 cBaseTextureTransform[2] : register( SHADER_SPECIFIC_CONST_3 ); + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vNormal : NORMAL; + float4 vBaseTexCoord : TEXCOORD0; + float2 vLightmapTexCoord : TEXCOORD1; + float2 vLightmapTexCoordOffset : TEXCOORD2; + float3 vTangentS : TANGENT; + float3 vTangentT : BINORMAL0; +}; + +struct VS_OUTPUT +{ + float4 vProjPos_POSITION : POSITION; + #if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + float fog : FOG; + #endif + float4 vBumpTexCoordXY_vTexCoordXY : TEXCOORD0; + float4 vPositionToCameraRayTs_projW : TEXCOORD1; + float4 vReflectXY_vRefractYX : TEXCOORD2; + float4 vProjPos : TEXCOORD4; + float3 worldPos : TEXCOORD5; + #if BASETEXTURE + float4 lightmapTexCoord1And2 : TEXCOORD6; + float4 lightmapTexCoord3 : TEXCOORD7; + #endif +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 vObjNormal; + DecompressVertex_Normal( v.vNormal, vObjNormal ); + + // Projected position + float4 vProjPos = mul( v.vPos, cModelViewProj ); + o.vProjPos = o.vProjPos_POSITION = vProjPos; + + // Project tangent basis + float2 vProjTangentS = mul( v.vTangentS, cViewProj ); + float2 vProjTangentT = mul( v.vTangentT, cViewProj ); + + // Map projected position to the reflection texture + float2 vReflectPos; + vReflectPos.x = -vProjPos.x; + vReflectPos.y = -vProjPos.y; // invert Y + vReflectPos = ( vReflectPos + vProjPos.w ) * 0.5f; + + // Map projected position to the refraction texture + float2 vRefractPos; + vRefractPos.x = vProjPos.x; + vRefractPos.y = -vProjPos.y; // invert Y + vRefractPos = ( vRefractPos + vProjPos.w ) * 0.5f; + + // Reflection transform + o.vReflectXY_vRefractYX = float4( vReflectPos.x, vReflectPos.y, vRefractPos.y, vRefractPos.x ); + o.vPositionToCameraRayTs_projW.w = vProjPos.w; + + // Compute fog based on the position + float3 vWorldPos = mul( v.vPos, cModel[0] ); + o.worldPos = vWorldPos; + + #if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + o.fog = CalcFixedFunctionFog( vWorldPos, FOGTYPE_RANGE ); + #endif + + // Eye vector + float3 vPositionToCameraRayWs = cEyePos.xyz - vWorldPos.xyz; + // Transform to the tangent space + o.vPositionToCameraRayTs_projW.x = dot( vPositionToCameraRayWs.xyz, v.vTangentS.xyz ); + o.vPositionToCameraRayTs_projW.y = dot( vPositionToCameraRayWs.xyz, v.vTangentT.xyz ); + o.vPositionToCameraRayTs_projW.z = dot( vPositionToCameraRayWs.xyz, vObjNormal.xyz ); + + // Tranform bump coordinates + o.vBumpTexCoordXY_vTexCoordXY.x = dot( v.vBaseTexCoord, cBumpTexCoordTransform[0] ); + o.vBumpTexCoordXY_vTexCoordXY.y = dot( v.vBaseTexCoord, cBumpTexCoordTransform[1] ); + + #if BASETEXTURE + o.vBumpTexCoordXY_vTexCoordXY.z = dot( v.vBaseTexCoord, cBaseTextureTransform[0] ); + o.vBumpTexCoordXY_vTexCoordXY.w = dot( v.vBaseTexCoord, cBaseTextureTransform[1] ); + + o.lightmapTexCoord1And2.xy = v.vLightmapTexCoord + v.vLightmapTexCoordOffset; + + float2 lightmapTexCoord2 = o.lightmapTexCoord1And2.xy + v.vLightmapTexCoordOffset; + float2 lightmapTexCoord3 = lightmapTexCoord2 + v.vLightmapTexCoordOffset; + + // reversed component order + o.lightmapTexCoord1And2.w = lightmapTexCoord2.x; + o.lightmapTexCoord1And2.z = lightmapTexCoord2.y; + + o.lightmapTexCoord3.xy = lightmapTexCoord3; + #else + o.vBumpTexCoordXY_vTexCoordXY.z = 0.0f; + o.vBumpTexCoordXY_vTexCoordXY.w = 0.0f; + #endif + + return o; +} + diff --git a/materialsystem/stdshaders/lightmappedtwotexture.cpp b/materialsystem/stdshaders/lightmappedtwotexture.cpp new file mode 100644 index 00000000..dd3dd3cc --- /dev/null +++ b/materialsystem/stdshaders/lightmappedtwotexture.cpp @@ -0,0 +1,186 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: Lightmap only shader +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "shaderlib/CShader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +// FIXME!! Need to make dx9 version so that "CENTROID" flags can be added! +BEGIN_SHADER( LightmappedTwoTexture, + "Help for LightmappedTwoTexture" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/Detail", "detail" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "1", "detail scale" ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "Frame for animated envmap" ) + SHADER_PARAM( ENVMAPMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_envmask", "envmap mask" ) + SHADER_PARAM( ENVMAPMASKFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( ENVMAPMASKSCALE, SHADER_PARAM_TYPE_FLOAT, "1", "envmap mask scale" ) + SHADER_PARAM( ENVMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "envmap tint" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + if( !params[ENVMAPMASKSCALE]->IsDefined() ) + params[ENVMAPMASKSCALE]->SetFloatValue( 1.0f ); + + if( !params[DETAILSCALE]->IsDefined() ) + params[DETAILSCALE]->SetFloatValue( 1.0f ); + + if( !params[ENVMAPTINT]->IsDefined() ) + params[ENVMAPTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + + // No texture means no self-illum or env mask in base alpha + if ( !params[BASETEXTURE]->IsDefined() ) + { + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + // If in decal mode, no debug override... + if (IS_FLAG_SET(MATERIAL_VAR_DECAL)) + { + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + } + } + + SHADER_INIT + { + if (params[BASETEXTURE]->IsDefined()) + { + LoadTexture( BASETEXTURE ); + + if (!params[BASETEXTURE]->GetTextureValue()->IsTranslucent()) + { + if (IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK)) + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + } + + if (params[DETAIL]->IsDefined()) + { + LoadTexture( DETAIL ); + } + + // Don't alpha test if the alpha channel is used for other purposes + if (IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK) ) + CLEAR_FLAGS( MATERIAL_VAR_ALPHATEST ); + + if (params[ENVMAP]->IsDefined()) + { + if( !IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE) ) + LoadCubeMap( ENVMAP ); + else + LoadTexture( ENVMAP ); + + if( !g_pHardwareConfig->SupportsCubeMaps() ) + { + SET_FLAGS( MATERIAL_VAR_ENVMAPSPHERE ); + } + + if (params[ENVMAPMASK]->IsDefined()) + LoadTexture( ENVMAPMASK ); + } + } + + SHADER_FALLBACK + { + // The only thing we can't do here is masked env-mapped + if (g_pHardwareConfig->GetSamplerCount() < 2) + { + return "LightmappedTwoTexture_DX5"; + } + return 0; + } + + /* + // FIXME: I didn't remove this because it's modulating against the detail alpha! + // This seems very strange and isn't what FixedFunctionBaseTimesDetailPass does. + // Should it!?!? If so, I want to move this to the FixedFunctionBaseTimesDetailPass. + + void DrawBaseTimesDetail( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + // Base + SHADOW_STATE + { + // alpha test + pShaderShadow->EnableAlphaTest( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) ); + + // Alpha blending, enable alpha blending if the detail texture is translucent + bool detailIsTranslucent = TextureIsTranslucent( DETAIL, false ); + if ( detailIsTranslucent ) + { + if ( IS_FLAG_SET( MATERIAL_VAR_ADDITIVE ) ) + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + else + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + else + { + SetDefaultBlendingShadowState( BASETEXTURE, true ); + } + + // independently configure alpha and color + pShaderShadow->EnableAlphaPipe( true ); + + // Here's the color states (NOTE: SHADER_DRAW_COLOR == use Vertex Color) + pShaderShadow->EnableConstantColor( IsColorModulating() ); + pShaderShadow->EnableTexture( SHADER_TEXTURE_STAGE0, true ); + pShaderShadow->EnableTexture( SHADER_TEXTURE_STAGE1, true ); + + // Here's the alpha states + pShaderShadow->EnableConstantAlpha( IsAlphaModulating() ); + pShaderShadow->EnableVertexAlpha( IS_FLAG_SET(MATERIAL_VAR_VERTEXALPHA) ); + pShaderShadow->EnableTextureAlpha( SHADER_TEXTURE_STAGE0, TextureIsTranslucent(BASETEXTURE, true) ); + pShaderShadow->EnableTextureAlpha( SHADER_TEXTURE_STAGE1, detailIsTranslucent ); + + int flags = SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 | SHADER_DRAW_SECONDARY_TEXCOORD1; + if (IS_FLAG_SET(MATERIAL_VAR_VERTEXCOLOR)) + flags |= SHADER_DRAW_COLOR; + pShaderShadow->DrawFlags( flags ); + DefaultFog(); + } + DYNAMIC_STATE + { + SetFixedFunctionTextureTransform( MATERIAL_TEXTURE0, BASETEXTURETRANSFORM ); + SetFixedFunctionTextureScale( MATERIAL_TEXTURE1, DETAILSCALE ); + BindTexture( SHADER_TEXTURE_STAGE0, BASETEXTURE, FRAME ); + BindTexture( SHADER_TEXTURE_STAGE1, DETAIL ); + SetModulationDynamicState(); + } + Draw(); + + SHADOW_STATE + { + pShaderShadow->EnableAlphaPipe( false ); + } + } + */ + + SHADER_DRAW + { + // Pass 1 : Base + detail + FixedFunctionBaseTimesDetailPass( + BASETEXTURE, FRAME, BASETEXTURETRANSFORM, DETAIL, DETAILSCALE ); + + // Pass 2 : * lightmap + FixedFunctionMultiplyByLightmapPass( BASETEXTURE, FRAME, BASETEXTURETRANSFORM ); + + // Pass 3 : + env + bool envDefined = params[ENVMAP]->IsTexture(); + if (envDefined) + { + FixedFunctionAdditiveMaskedEnvmapPass( + ENVMAP, ENVMAPMASK, BASETEXTURE, + ENVMAPFRAME, ENVMAPMASKFRAME, FRAME, + BASETEXTURETRANSFORM, ENVMAPMASKSCALE, ENVMAPTINT ); + } + } +END_SHADER diff --git a/materialsystem/stdshaders/lightshafts.cpp b/materialsystem/stdshaders/lightshafts.cpp new file mode 100644 index 00000000..f9107076 --- /dev/null +++ b/materialsystem/stdshaders/lightshafts.cpp @@ -0,0 +1,102 @@ +//========= Copyright © 1996-2008, Valve Corporation, All rights reserved. ============// + +#include "BaseVSShader.h" +#include "lightshafts_helper.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( LightShafts, LightShafts_dx9 ) +BEGIN_VS_SHADER( LightShafts_dx9, "LightShafts" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( SHADOWDEPTHTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Shadow Depth Texture" ) + SHADER_PARAM( NOISETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Noise texture for non-uniform density" ) + SHADER_PARAM( COOKIETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Cookie Texture" ) + SHADER_PARAM( COOKIEFRAMENUM, SHADER_PARAM_TYPE_INTEGER, "", "Cookie Frame number for animated cookies" ) + + SHADER_PARAM( WORLDTOTEXTURE, SHADER_PARAM_TYPE_MATRIX, "1", "World to Texture Matrix" ) + SHADER_PARAM( FLASHLIGHTCOLOR, SHADER_PARAM_TYPE_VEC4, "1", "Flashlight color" ) + SHADER_PARAM( ATTENFACTORS, SHADER_PARAM_TYPE_VEC4, "1", "Packed attenuation factors" ) + SHADER_PARAM( ORIGINFARZ, SHADER_PARAM_TYPE_VEC4, "1", "Light origin packed with farz" ) + SHADER_PARAM( QUATORIENTATION, SHADER_PARAM_TYPE_VEC4, "1", "Light orientation (quaternion)" ) + SHADER_PARAM( SHADOWFILTERSIZE, SHADER_PARAM_TYPE_FLOAT, "3", "Shadow filter size" ) + SHADER_PARAM( SHADOWATTEN, SHADER_PARAM_TYPE_FLOAT, "1", "Shadow Attenuation" ) + SHADER_PARAM( SHADOWJITTERSEED, SHADER_PARAM_TYPE_FLOAT, "1", "Shadow jitter seed" ) + SHADER_PARAM( UBERLIGHT, SHADER_PARAM_TYPE_INTEGER, "1", "Is this an uberlight?" ) + SHADER_PARAM( ENABLESHADOWS, SHADER_PARAM_TYPE_INTEGER, "1", "Are shadows enabled?" ) + SHADER_PARAM( NOISESTRENGTH, SHADER_PARAM_TYPE_FLOAT, "1", "Strength of noise in volumetrics" ) + + // Uberlight parameters + SHADER_PARAM( UBERNEARFAR, SHADER_PARAM_TYPE_VEC4, "1", "Packed uberlight near and far parameters" ) + SHADER_PARAM( UBERHEIGHTWIDTH, SHADER_PARAM_TYPE_VEC4, "1", "Packed uberlight height and width parameters" ) + SHADER_PARAM( UBERROUNDNESS, SHADER_PARAM_TYPE_FLOAT, "1", "Uberlight roundness" ) + + SHADER_PARAM( FLASHLIGHTTIME, SHADER_PARAM_TYPE_FLOAT, "0", "Typically driven by SFM, similar to jitter seed" ) + SHADER_PARAM( NUMPLANES, SHADER_PARAM_TYPE_FLOAT, "0", "Need to know this to normalize intensity" ) + + SHADER_PARAM( VOLUMETRICINTENSITY, SHADER_PARAM_TYPE_FLOAT, "1", "Intensity of volumetrics" ) + + END_SHADER_PARAMS + + void SetupVarsLightShafts( LightShaftsVars_t &info ) + { + info.m_nCookieTexture = COOKIETEXTURE; + info.m_nCookieFrameNum = COOKIEFRAMENUM; + info.m_nShadowDepthTexture = SHADOWDEPTHTEXTURE; + info.m_nNoiseTexture = NOISETEXTURE; + info.m_nNoiseStrength = NOISESTRENGTH; + + info.m_nWorldToTexture = WORLDTOTEXTURE; + info.m_nFlashlightColor = FLASHLIGHTCOLOR; + info.m_nAttenFactors = ATTENFACTORS; + info.m_nOriginFarZ = ORIGINFARZ; + info.m_nQuatOrientation = QUATORIENTATION; + info.m_nShadowFilterSize = SHADOWFILTERSIZE; + info.m_nShadowAtten = SHADOWATTEN; + info.m_nShadowJitterSeed = SHADOWJITTERSEED; + info.m_nUberlight = UBERLIGHT; + info.m_nEnableShadows = ENABLESHADOWS; + + info.m_nFlashlightTime = FLASHLIGHTTIME; + info.m_nNumPlanes = NUMPLANES; + + // Uberlight parameters + info.m_nUberNearFar = UBERNEARFAR; + info.m_nUberHeightWidth = UBERHEIGHTWIDTH; + info.m_nUberRoundness = UBERROUNDNESS; + + info.m_nVolumetricIntensity = VOLUMETRICINTENSITY; + } + + SHADER_INIT_PARAMS() + { + LightShaftsVars_t info; + SetupVarsLightShafts( info ); + InitParamsLightShafts( this, params, pMaterialName, info ); + } + + SHADER_FALLBACK + { + if ( !g_pHardwareConfig->HasFastVertexTextures() ) + { + // Fallback to unlit generic + return "Wireframe"; + } + + return 0; + } + + SHADER_INIT + { + LightShaftsVars_t info; + SetupVarsLightShafts( info ); + InitLightShafts( this, params, info ); + } + + SHADER_DRAW + { + LightShaftsVars_t info; + SetupVarsLightShafts( info ); + DrawLightShafts( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } +END_SHADER diff --git a/materialsystem/stdshaders/lightshafts_helper.cpp b/materialsystem/stdshaders/lightshafts_helper.cpp new file mode 100644 index 00000000..5e548a38 --- /dev/null +++ b/materialsystem/stdshaders/lightshafts_helper.cpp @@ -0,0 +1,310 @@ +//========= Copyright © 1996-2007, Valve Corporation, All rights reserved. ============// + +#include "BaseVSShader.h" +#include "mathlib/VMatrix.h" +#include "lightshafts_helper.h" +#include "convar.h" + +// Auto generated inc files +#include "lightshafts_vs30.inc" +#include "lightshafts_ps30.inc" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +void InitParamsLightShafts( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, LightShaftsVars_t &info ) +{ + // Set material flags + SET_FLAGS( MATERIAL_VAR_TRANSLUCENT ); + SET_FLAGS( MATERIAL_VAR_NOCULL ); + SET_PARAM_INT_IF_NOT_DEFINED( info.m_nCookieFrameNum, 0 ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nTime, 0.0f ); +} + +void InitLightShafts( CBaseVSShader *pShader, IMaterialVar** params, LightShaftsVars_t &info ) +{ + // Load textures + if ( (info.m_nCookieTexture != -1) && params[info.m_nCookieTexture]->IsDefined() ) + { + pShader->LoadTexture( info.m_nCookieTexture ); + } + + if ( (info.m_nShadowDepthTexture != -1) && params[info.m_nShadowDepthTexture]->IsDefined() ) + { + pShader->LoadTexture( info.m_nShadowDepthTexture ); + } + + if ( (info.m_nNoiseTexture != -1) && params[info.m_nNoiseTexture]->IsDefined() ) + { + pShader->LoadTexture( info.m_nNoiseTexture ); + } +} + +void DrawLightShafts( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, LightShaftsVars_t &info, VertexCompressionType_t vertexCompression ) +{ + SHADOW_STATE + { + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION; + pShaderShadow->VertexShaderVertexFormat( flags, 0, NULL, 0 ); // no texture coordinates needed + + DECLARE_STATIC_VERTEX_SHADER( lightshafts_vs30 ); + SET_STATIC_VERTEX_SHADER( lightshafts_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( lightshafts_ps30 ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, IsPC() ? g_pHardwareConfig->GetShadowFilterMode() : 0 ); + SET_STATIC_PIXEL_SHADER( lightshafts_ps30 ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); // Cookie texture + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); // Shadow depth texture + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, false ); + pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER1 ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); // Screen-space noise map for shadow filtering + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, false ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); // Projective noise map used for non-uniform atmospherics + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER3, false ); + + pShaderShadow->EnableSRGBWrite( true ); + + pShader->EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); // Additive blending + pShaderShadow->EnableAlphaWrites( false ); + } + DYNAMIC_STATE + { + DECLARE_DYNAMIC_VERTEX_SHADER( lightshafts_vs30 ); + SET_DYNAMIC_VERTEX_SHADER( lightshafts_vs30 ); + + // + // Read material vars into relevant members of flashlightState...kinda icky and verbose... + // + VMatrix worldToTexture; + FlashlightState_t flashlightState; + + if ( (info.m_nWorldToTexture != -1) && params[info.m_nWorldToTexture]->IsDefined() ) + { + const VMatrix &mat = params[info.m_nWorldToTexture]->GetMatrixValue(); + worldToTexture = mat; + } + + if ( (info.m_nFlashlightColor != -1) && params[info.m_nFlashlightColor]->IsDefined() ) + { + params[info.m_nFlashlightColor]->GetVecValue( &(flashlightState.m_Color[0]), 4 ); + } + else + { + flashlightState.m_Color[0] = flashlightState.m_Color[1] = flashlightState.m_Color[2] = flashlightState.m_Color[3] = 1.0f; + } + + // Pre-modulate with intensity factor + if ( (info.m_nVolumetricIntensity != -1) && params[info.m_nVolumetricIntensity]->IsDefined() ) + { + float flVolumetricIntensity = params[info.m_nVolumetricIntensity]->GetFloatValue(); + flashlightState.m_Color[0] *= flVolumetricIntensity; + flashlightState.m_Color[1] *= flVolumetricIntensity; + flashlightState.m_Color[2] *= flVolumetricIntensity; + } + + SetFlashLightColorFromState( flashlightState, pShaderAPI, false, PSREG_FLASHLIGHT_COLOR ); + + if ( (info.m_nAttenFactors != -1) && params[info.m_nAttenFactors]->IsDefined() ) + { + float v[4]; + params[info.m_nAttenFactors]->GetVecValue( v, 4 ); + flashlightState.m_fConstantAtten = v[0]; + flashlightState.m_fLinearAtten = v[1]; + flashlightState.m_fQuadraticAtten = v[2]; + flashlightState.m_FarZAtten = v[3]; + } + + if ( (info.m_nOriginFarZ != -1) && params[info.m_nOriginFarZ]->IsDefined() ) + { + float v[4]; + params[info.m_nOriginFarZ]->GetVecValue( v, 4 ); + flashlightState.m_vecLightOrigin[0] = v[0]; + flashlightState.m_vecLightOrigin[1] = v[1]; + flashlightState.m_vecLightOrigin[2] = v[2]; + flashlightState.m_FarZ = v[3]; + } + + if ( (info.m_nQuatOrientation != -1) && params[info.m_nQuatOrientation]->IsDefined() ) + { + params[info.m_nQuatOrientation]->GetVecValue( flashlightState.m_quatOrientation.Base(), 4 ); + } + + if ( (info.m_nShadowFilterSize != -1) && params[info.m_nShadowFilterSize]->IsDefined() ) + { + flashlightState.m_flShadowFilterSize = params[info.m_nShadowFilterSize]->GetFloatValue(); + } + + if ( (info.m_nShadowAtten != -1) && params[info.m_nShadowAtten]->IsDefined() ) + { + flashlightState.m_flShadowAtten = params[info.m_nShadowAtten]->GetFloatValue(); + } + + if ( (info.m_nShadowJitterSeed != -1) && params[info.m_nShadowJitterSeed]->IsDefined() ) + { + flashlightState.m_flShadowJitterSeed = params[info.m_nShadowJitterSeed]->GetFloatValue(); + } + + if ( (info.m_nFlashlightTime != -1) && params[info.m_nFlashlightTime]->IsDefined() ) + { + flashlightState.m_flFlashlightTime = params[info.m_nFlashlightTime]->GetFloatValue(); + } + + if ( (info.m_nNumPlanes != -1) && params[info.m_nNumPlanes]->IsDefined() ) + { + flashlightState.m_nNumPlanes = params[info.m_nNumPlanes]->GetIntValue(); + } + + if ( (info.m_nUberlight != -1) && params[info.m_nUberlight]->IsDefined() ) + { + flashlightState.m_bUberlight = ( params[info.m_nUberlight]->GetIntValue() != 0 ); + } + + if ( (info.m_nEnableShadows != -1) && params[info.m_nEnableShadows]->IsDefined() ) + { + flashlightState.m_bEnableShadows = ( params[info.m_nEnableShadows]->GetIntValue() != 0 ); + } + + if ( (info.m_nNoiseStrength != -1) && params[info.m_nNoiseStrength]->IsDefined() ) + { + flashlightState.m_flNoiseStrength = params[info.m_nNoiseStrength]->GetFloatValue(); + } + + if ( (info.m_nCookieTexture != -1) && params[info.m_nCookieTexture]->IsDefined() ) + { + ITexture *pCookieTexture = params[info.m_nCookieTexture]->GetTextureValue(); + int nFrameNumber = params[info.m_nCookieFrameNum]->GetIntValue(); + pShader->BindTexture( SHADER_SAMPLER0, pCookieTexture, nFrameNumber ); + } + + if( (info.m_nShadowDepthTexture != -1) && params[info.m_nShadowDepthTexture]->IsDefined() && + g_pConfig->ShadowDepthTexture() && flashlightState.m_bEnableShadows ) + { + ITexture *pFlashlightDepthTexture = params[info.m_nShadowDepthTexture]->GetTextureValue(); + pShader->BindTexture( SHADER_SAMPLER1, pFlashlightDepthTexture ); + + pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_SHADOW_NOISE_2D ); + } + + if( (info.m_nNoiseTexture != -1) && params[info.m_nNoiseTexture]->IsDefined() ) + { + ITexture *pNoiseTexture = params[info.m_nNoiseTexture]->GetTextureValue(); + pShader->BindTexture( SHADER_SAMPLER3, pNoiseTexture ); + } + + // + // Now that we've packed the flashlightState structure from our material vars, we can set constants and draw as normal + // + + float atten[4], pos[4], tweaks[4], packedParams[4], noiseScroll[4]; + atten[0] = flashlightState.m_fConstantAtten; // Set the flashlight attenuation factors + atten[1] = flashlightState.m_fLinearAtten; + atten[2] = flashlightState.m_fQuadraticAtten; + atten[3] = flashlightState.m_FarZAtten; + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_ATTENUATION, atten, 1 ); + + pos[0] = flashlightState.m_vecLightOrigin[0]; // Set the flashlight origin + pos[1] = flashlightState.m_vecLightOrigin[1]; + pos[2] = flashlightState.m_vecLightOrigin[2]; + pos[3] = flashlightState.m_FarZ; + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_POSITION_RIM_BOOST, pos, 1 ); // steps on rim boost + + // Coefficient for projective noise + packedParams[0] = flashlightState.m_flNoiseStrength; + packedParams[1] = 64.0f / (float) flashlightState.m_nNumPlanes; + packedParams[2] = 0.0f; + packedParams[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( 0, packedParams, 1 ); + + // Directions for projective noise + noiseScroll[0] = fmodf( flashlightState.m_flFlashlightTime * 0.043f * 0.394, 1.0f); // UV offset for noise in red + noiseScroll[1] = fmodf( flashlightState.m_flFlashlightTime * 0.043f * 0.919, 1.0f); + noiseScroll[2] = fmodf( flashlightState.m_flFlashlightTime * 0.039f * -0.781, 1.0f); // UV offset for noise in green + noiseScroll[3] = fmodf( flashlightState.m_flFlashlightTime * 0.039f * 0.625, 1.0f); + pShaderAPI->SetPixelShaderConstant( 1, noiseScroll, 1 ); + + // Tweaks associated with a given flashlight + tweaks[0] = ShadowFilterFromState( flashlightState ); + tweaks[1] = ShadowAttenFromState( flashlightState ); + pShader->HashShadow2DJitter( flashlightState.m_flShadowJitterSeed, &tweaks[2], &tweaks[3] ); + pShaderAPI->SetPixelShaderConstant( PSREG_ENVMAP_TINT__SHADOW_TWEAKS, tweaks, 1 ); + + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, worldToTexture.Base(), 4 ); + + if ( flashlightState.m_bUberlight ) + { + // No shear supported at present + flashlightState.m_uberlightState.m_fShearx = 0.0f; + flashlightState.m_uberlightState.m_fSheary = 0.0f; + + if ( (info.m_nUberNearFar != -1) && params[info.m_nUberNearFar]->IsDefined() ) + { + float v[4]; + params[info.m_nUberNearFar]->GetVecValue( v, 4 ); + flashlightState.m_uberlightState.m_fNearEdge = v[0]; + flashlightState.m_uberlightState.m_fFarEdge = v[1]; + flashlightState.m_uberlightState.m_fCutOn = v[2]; + flashlightState.m_uberlightState.m_fCutOff = v[3]; + } + + if ( (info.m_nUberHeightWidth != -1) && params[info.m_nUberHeightWidth]->IsDefined() ) + { + float v[4]; + params[info.m_nUberHeightWidth]->GetVecValue( v, 4 ); + flashlightState.m_uberlightState.m_fWidth = v[0]; + flashlightState.m_uberlightState.m_fWedge = v[1]; + flashlightState.m_uberlightState.m_fHeight = v[2]; + flashlightState.m_uberlightState.m_fHedge = v[3]; + } + + if ( (info.m_nUberRoundness != -1) && params[info.m_nUberRoundness]->IsDefined() ) + { + flashlightState.m_uberlightState.m_fRoundness = params[info.m_nUberRoundness]->GetFloatValue(); + } + + SetupUberlightFromState( pShaderAPI, flashlightState ); + + + QAngle angles; + QuaternionAngles( flashlightState.m_quatOrientation, angles ); + + // World to Light's View matrix + matrix3x4_t viewMatrix, viewMatrixInverse; + AngleMatrix( angles, flashlightState.m_vecLightOrigin, viewMatrixInverse ); + MatrixInvert( viewMatrixInverse, viewMatrix ); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, worldToTexture.Base(), 4 ); + } + else + { + matrix3x4_t identityMatrix; + SetIdentityMatrix( identityMatrix ); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, identityMatrix.Base(), 4 ); + } + + // Dimensions of screen, used for screen-space noise map sampling + float vScreenScale[4] = {1280.0f / 32.0f, 720.0f / 32.0f, 0, 0}; + int nWidth, nHeight; + pShaderAPI->GetBackBufferDimensions( nWidth, nHeight ); + + int nTexWidth, nTexHeight; + pShaderAPI->GetStandardTextureDimensions( &nTexWidth, &nTexHeight, TEXTURE_SHADOW_NOISE_2D ); + + vScreenScale[0] = (float) nWidth / nTexWidth; + vScreenScale[1] = (float) nHeight / nTexHeight; + + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_SCREEN_SCALE, vScreenScale, 1 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( lightshafts_ps30 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, flashlightState.m_bEnableShadows ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( UBERLIGHT, flashlightState.m_bUberlight ); + SET_DYNAMIC_PIXEL_SHADER( lightshafts_ps30 ); + } + pShader->Draw(); +} diff --git a/materialsystem/stdshaders/lightshafts_helper.h b/materialsystem/stdshaders/lightshafts_helper.h new file mode 100644 index 00000000..b7380196 --- /dev/null +++ b/materialsystem/stdshaders/lightshafts_helper.h @@ -0,0 +1,62 @@ +//========= Copyright © 1996-2007, Valve Corporation, All rights reserved. ============// + +#ifndef LIGHT_SHAFTS_HELPER_H +#define LIGHT_SHAFTS_HELPER_H +#ifdef _WIN32 +#pragma once +#endif + +#include + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct LightShaftsVars_t +{ + LightShaftsVars_t() { memset( this, 0xFF, sizeof( LightShaftsVars_t ) ); } + + int m_nShadowDepthTexture; + + int m_nNoiseTexture; + int m_nNoiseStrength; + + int m_nCookieTexture; + int m_nCookieFrameNum; + + int m_nWorldToTexture; + int m_nFlashlightColor; + int m_nAttenFactors; + int m_nOriginFarZ; + int m_nQuatOrientation; + int m_nShadowFilterSize; + int m_nShadowAtten; + int m_nShadowJitterSeed; + int m_nUberlight; + int m_nEnableShadows; + int m_nFlashlightTime; + int m_nNumPlanes; + + // Uberlight parameters + int m_nUberNearFar; + int m_nUberHeightWidth; + int m_nUberRoundness; + + int m_nTime; + + int m_nVolumetricIntensity; +}; + +void InitParamsLightShafts( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, LightShaftsVars_t &info ); +void InitLightShafts( CBaseVSShader *pShader, IMaterialVar** params, LightShaftsVars_t &info ); +void DrawLightShafts( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, LightShaftsVars_t &info, VertexCompressionType_t vertexCompression ); + +#endif // LIGHT_SHAFTS_HELPER_H diff --git a/materialsystem/stdshaders/lightshafts_ps30.fxc b/materialsystem/stdshaders/lightshafts_ps30.fxc new file mode 100644 index 00000000..9c459249 --- /dev/null +++ b/materialsystem/stdshaders/lightshafts_ps30.fxc @@ -0,0 +1,80 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..0" [XBOX] + +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" +// DYNAMIC: "UBERLIGHT" "0..1" [ps30] [PC] + +#include "common_flashlight_fxc.h" +#include "shader_constant_register_map.h" + +const float4 g_PackedParams : register( c0 ); +const float4 g_NoiseScroll : register( c1 ); +const float4 g_ShadowTweaks : register( PSREG_ENVMAP_TINT__SHADOW_TWEAKS ); // c2 +const float4 g_FlashlightAttenuationFactors : register( PSREG_FLASHLIGHT_ATTENUATION ); +const float4 g_FlashlightPos : register( PSREG_FLASHLIGHT_POSITION_RIM_BOOST ); + +#define g_NoiseStrength g_PackedParams.x +#define g_PerPlaneFactor g_PackedParams.y + + +#if UBERLIGHT +const float3 g_vSmoothEdge0 : register( PSREG_UBERLIGHT_SMOOTH_EDGE_0 ); +const float3 g_vSmoothEdge1 : register( PSREG_UBERLIGHT_SMOOTH_EDGE_1 ); +const float3 g_vSmoothOneOverWidth : register( PSREG_UBERLIGHT_SMOOTH_EDGE_OOW ); +const float4 g_vShearRound : register( PSREG_UBERLIGHT_SHEAR_ROUND ); +const float4 g_aAbB : register( PSREG_UBERLIGHT_AABB ); +const float4x4 g_FlashlightWorldToLight : register( PSREG_UBERLIGHT_WORLD_TO_LIGHT ); +#endif + +sampler FlashlightCookieSampler : register( s0 ); +sampler ShadowDepthSampler : register( s1 ); +sampler RandRotSampler : register( s2 ); +sampler NoiseSampler : register( s3 ); + +struct PS_INPUT +{ + float3 vWorldPos : TEXCOORD0; + float4 vProjPos : TEXCOORD1; + float4 spotTexCoord : TEXCOORD2; + float4 uberLightPos : TEXCOORD3; // not currently actually used +}; + + +float4 main( PS_INPUT i ) : COLOR +{ + bool bDoShadows = FLASHLIGHTSHADOWS ? true : false; + + int nShadowSampleLevel = 0; + bool bForceSimple = true; + float2 vProjPos = float2(0, 0); + + if ( bDoShadows ) + { + nShadowSampleLevel = FLASHLIGHTDEPTHFILTERMODE; + vProjPos = i.vProjPos.xy / i.vProjPos.w; // Screen-space position for shadow map noise + } + + float3 flashlightColor = DoFlashlight( g_FlashlightPos, i.vWorldPos, i.spotTexCoord, + float3(1,0,0), g_FlashlightAttenuationFactors.xyz, g_FlashlightAttenuationFactors.w, + FlashlightCookieSampler, ShadowDepthSampler, RandRotSampler, + nShadowSampleLevel, true, false, vProjPos, false, g_ShadowTweaks, false, bForceSimple ); + +#if UBERLIGHT + float4 uberLightPosition = mul( float4( i.vWorldPos, 1.0f ), g_FlashlightWorldToLight ).yzxw; + flashlightColor *= uberlight( uberLightPosition, g_vSmoothEdge0, g_vSmoothEdge1, + g_vSmoothOneOverWidth, g_vShearRound.xy, g_aAbB, g_vShearRound.zw ); +#endif + + // Scrolling noise with adjustable strength + float fNoise = tex2D( NoiseSampler, (i.spotTexCoord.xy / i.spotTexCoord.w) + g_NoiseScroll.xy ).x; + fNoise *= tex2D( NoiseSampler, (i.spotTexCoord.xy / i.spotTexCoord.w) + g_NoiseScroll.zw ).y; + fNoise = lerp( 1.0, fNoise, g_NoiseStrength ); + + // Pre-tonemapped result + float4 vResult = float4( flashlightColor * 0.005f * g_PerPlaneFactor * fNoise, 1 ); + + // Tone map on the way out (no fog and no depthwrite) + return FinalOutput( vResult, 0.0f, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_LINEAR, false, 0 ); +} diff --git a/materialsystem/stdshaders/lightshafts_vs30.fxc b/materialsystem/stdshaders/lightshafts_vs30.fxc new file mode 100644 index 00000000..5ae4e480 --- /dev/null +++ b/materialsystem/stdshaders/lightshafts_vs30.fxc @@ -0,0 +1,56 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#include "common_vs_fxc.h" + + +const float4x4 g_FlashlightWorldToTexture : register( SHADER_SPECIFIC_CONST_0 ); +// SHADER_SPECIFIC_CONST_1 +// SHADER_SPECIFIC_CONST_2 +// SHADER_SPECIFIC_CONST_3 +const float4x4 g_FlashlightWorldToLight : register( SHADER_SPECIFIC_CONST_4 ); +// SHADER_SPECIFIC_CONST_5 +// SHADER_SPECIFIC_CONST_6 +// SHADER_SPECIFIC_CONST_7 + + +//----------------------------------------------------------------------------- +// Input vertex format +//----------------------------------------------------------------------------- +struct VS_INPUT +{ + // This is all of the stuff that we ever use. + float4 vPos : POSITION; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; + float3 vWorldPos : TEXCOORD0; + float4 vProjPos : TEXCOORD1; + float4 spotTexCoord : TEXCOORD2; + float4 uberLightPos : TEXCOORD3; +}; + +//----------------------------------------------------------------------------- +// Main shader entry point +//----------------------------------------------------------------------------- +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = (VS_OUTPUT) 0; + float4 vPosition = v.vPos; + + // Transform to world space + float3 worldPos = vPosition; + + // Transform into projection space + float4 vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + o.projPos = vProjPos; + o.vWorldPos.xyz = worldPos; + + o.vProjPos = vProjPos; + + o.spotTexCoord = mul( float4( worldPos, 1.0f ), g_FlashlightWorldToTexture ); + o.uberLightPos = mul( float4( worldPos, 1.0f ), g_FlashlightWorldToLight ).yzxw; + + return o; +} diff --git a/materialsystem/stdshaders/lpreview1_ps2x.fxc b/materialsystem/stdshaders/lpreview1_ps2x.fxc new file mode 100644 index 00000000..906a860b --- /dev/null +++ b/materialsystem/stdshaders/lpreview1_ps2x.fxc @@ -0,0 +1,70 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#include "common_ps_fxc.h" + +sampler AlbedoSampler : register( s0 ); +sampler NormalSampler : register( s1 ); +sampler PositionSampler : register( s2 ); + + +struct PS_INPUT +{ + float2 texCoord : TEXCOORD0; + float4 lightColor_InnerCos : TEXCOORD1; + float4 lightDir_OuterCos : TEXCOORD2; + float3 lightOrigin : TEXCOORD3; + float4 attnInfo : TEXCOORD4; + float3 SampleXYW : TEXCOORD5; + float3 col : TEXCOORD6; + + +}; + +#define INNER_COS (i.lightColor_InnerCos.w) +#define OUTER_COS (i.lightDir_OuterCos.w) + +#define QUADRATIC_ATTN ( i.attnInfo.x ) +#define LINEAR_ATTN ( i.attnInfo.y ) +#define CONSTANT_ATTN ( i.attnInfo.z ) +#define SCALE_FACTOR ( i.attnInfo.w ) + + +float Lerp5( float f1, float f2, float i1, float i2, float x ) +{ + return f1 + ( f2 - f1 ) * ( x - i1 ) / ( i2 - i1 ); +} + + +float4 main( PS_INPUT i ) : COLOR +{ + // figure out screen sample location + float ooW = 1.0 / i.SampleXYW.z; + + float2 sampleUV = i.SampleXYW.xy * ooW; + + float4 normal = tex2D( NormalSampler, sampleUV ); + float4 albedo = tex2D( AlbedoSampler, sampleUV ); + float4 pos = tex2D( PositionSampler, sampleUV ); + + float3 ldir = i.lightOrigin - pos.xyz; + float dist = sqrt( dot( ldir, ldir ) ); + ldir = normalize( ldir ); + float spot_dot = dot( ldir, -i.lightDir_OuterCos.xyz ); + float3 ret = i.lightColor_InnerCos.xyz * 0.09 * albedo.xyz; // ambient + float dist_falloff = ( SCALE_FACTOR / ( QUADRATIC_ATTN * dist * dist + LINEAR_ATTN * dist + CONSTANT_ATTN ) ); + if ( spot_dot > OUTER_COS ) + { + float falloff = 1; + if (spot_dot < INNER_COS) + { + falloff = Lerp5( 1, 0, INNER_COS, OUTER_COS, spot_dot); + } + float dotprod=max( 0, dot( ldir.xyz, normal.xyz ) ); + ret += dotprod * falloff * ( i.lightColor_InnerCos.xyz * albedo.xyz ); + } + else + dist_falloff = min( 1, dist_falloff ); + ret *= dist_falloff; +// ret += 0.1 * i.col; + return FinalOutput( float4( ret, 1 ), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} diff --git a/materialsystem/stdshaders/lpreview1_vs20.fxc b/materialsystem/stdshaders/lpreview1_vs20.fxc new file mode 100644 index 00000000..492f3641 --- /dev/null +++ b/materialsystem/stdshaders/lpreview1_vs20.fxc @@ -0,0 +1,55 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + + +#include "common_vs_fxc.h" + +struct VS_INPUT +{ + float3 vPos : POSITION; + float2 vBaseTexCoord : TEXCOORD0; + float4 lightColor_InnerCos : TEXCOORD1; + float4 lightDir_OuterCos : TEXCOORD2; + float3 lightOrigin : TEXCOORD3; + float4 attnInfo : TEXCOORD4; + float3 col : TEXCOORD5; + +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; + float2 texCoord : TEXCOORD0; + float4 lightColor_InnerCos : TEXCOORD1; + float4 lightDir_OuterCos : TEXCOORD2; + float3 lightOrigin : TEXCOORD3; + float4 attnInfo : TEXCOORD4; + float3 SampleXYW : TEXCOORD5; + float3 col : TEXCOORD6; + +}; + +float4 Texel_Sizes : register (SHADER_SPECIFIC_CONST_0); + +VS_OUTPUT main( const VS_INPUT v ) +{ + + VS_OUTPUT o; + + o.projPos = float4( v.vPos, 1.0f ); + //o.projPos.xyzw = mul( float4( v.vPos.xyz, 1.0f ), cModelViewProj ); + + float2 vSamplePos; + vSamplePos.x = o.projPos.x; + vSamplePos.y = -o.projPos.y; // invert Y + vSamplePos = (vSamplePos + o.projPos.w) * 0.5f; + o.SampleXYW = float3( vSamplePos.x, vSamplePos.y, o.projPos.w ); + + o.texCoord = v.vBaseTexCoord; + + o.lightColor_InnerCos = v.lightColor_InnerCos; + o.lightDir_OuterCos = v.lightDir_OuterCos; + o.lightOrigin = v.lightOrigin; + o.col = v.col; + o.attnInfo = v.attnInfo; + return o; +} diff --git a/materialsystem/stdshaders/lpreview_output_ps2x.fxc b/materialsystem/stdshaders/lpreview_output_ps2x.fxc new file mode 100644 index 00000000..1e6595e7 --- /dev/null +++ b/materialsystem/stdshaders/lpreview_output_ps2x.fxc @@ -0,0 +1,23 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#include "common_ps_fxc.h" + +sampler InputTexture : register( s0 ); +sampler Albedo : register( s1 ); +sampler Normal : register( s2 ); + +struct PS_INPUT +{ + float2 texCoord : TEXCOORD0; +}; + + +float4 main( PS_INPUT i ) : COLOR +{ + float3 normal = tex2D( Normal, i.texCoord ); + float good = dot( normal, normal ) > 0.9; + float3 input=tex2D( InputTexture, i.texCoord ); + float3 albedo=tex2D( Albedo, i.texCoord ); + input=lerp( albedo, input, good ); + return FinalOutput( float4(input.xyz,1), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} diff --git a/materialsystem/stdshaders/luminance_compare_ps2x.fxc b/materialsystem/stdshaders/luminance_compare_ps2x.fxc new file mode 100644 index 00000000..e79b4c35 --- /dev/null +++ b/materialsystem/stdshaders/luminance_compare_ps2x.fxc @@ -0,0 +1,51 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_fxc.h" + +// This pixel shader compares the luminance against a constant value and retruns all 1's when greater + +sampler TexSampler : register( s0 ); + +struct PS_INPUT +{ + float2 uv0 : TEXCOORD0; +}; + +float3 g_vComparisonMinMaxScale : register( c0 ); +#define g_flComparisonMin g_vComparisonMinMaxScale.x +#define g_flComparisonMax g_vComparisonMinMaxScale.y + +struct PS_OUTPUT +{ + float4 color : COLOR0; + #ifndef _X360 + float depth : DEPTH; // Workaround for ATI driver bug + #endif +}; + +PS_OUTPUT main( PS_INPUT i ) +{ + float3 color = tex2D( TexSampler, i.uv0 ); + + // Formula for calculating luminance based on NTSC standard + float3 tmpv = { 0.2125f, 0.7154f, 0.0721f }; + float flLuminance = dot( color.rgb, tmpv.rgb ); + + // Alternate formula for calculating luminance for linear RGB space (Widely used in color hue and saturation computations) + //float3 tmpv = { 0.3086f, 0.6094f, 0.0820f }; + //float flLuminance = dot( color.rgb, tmpv.rgb ); + + // Simple average + //float flLuminance = ( color.r + color.g + color.b ) * 0.33333f; + + PS_OUTPUT o; + o.color.rgba = step( g_flComparisonMin, flLuminance ) * step( flLuminance, g_flComparisonMax ); + #ifndef _X360 + { + o.depth = 0.0f; // Workaround for ATI driver bug + } + #endif + + return o; +} diff --git a/materialsystem/stdshaders/macros.vsh b/materialsystem/stdshaders/macros.vsh new file mode 100644 index 00000000..9b19f777 --- /dev/null +++ b/materialsystem/stdshaders/macros.vsh @@ -0,0 +1,1393 @@ +;------------------------------------ +; 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; + } +} + +# NOTE: These should match g_LightCombinations in vertexshaderdx8.cpp! +# NOTE: Leave this on single lines or shit might blow up. +@g_staticLightTypeArray = ( "none", "static", "none", "none", "none", "none", "none", "none", "none", "none", "none", "none", "static", "static", "static", "static", "static", "static", "static", "static", "static", "static" ); +@g_ambientLightTypeArray = ( "none", "none", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient" ); +@g_localLightType1Array = ( "none", "none", "none", "spot", "point", "directional", "spot", "spot", "spot", "point", "point", "directional", "none", "spot", "point", "directional", "spot", "spot", "spot", "point", "point", "directional" ); +@g_localLightType2Array = ( "none", "none", "none", "none", "none", "none", "spot", "point", "directional", "point", "directional", "directional", "none", "none", "none", "none", "spot", "point", "directional", "point", "directional", "directional" ); + +$cConstants0 = "c0"; +$cZero = "c0.x"; +$cOne = "c0.y"; +$cTwo = "c0.z"; +$cHalf = "c0.w"; + +$cConstants1 = "c1"; +$cOOGamma = "c1.x"; # 1/2.2 +$cOtherOverbrightFactor = "c1.y"; # overbright +$cOneThird = "c1.z"; # 1/3 +$cOverbrightFactor = "c1.w"; # 1/overbright + +$cEyePos = "c2"; +$cWaterZ = "c2.w"; +$cEyePosWaterZ = "c2"; + +$cLightIndex = "c3"; +$cLight0Offset = "c3.x"; # 27 +$cLight1Offset = "c3.y"; # 32 +$cColorToIntScale = "c3.z"; # matrix array offset = 3.0f * 255.0f + 0.01 (epsilon ensures floor yields desired result) +$cModel0Index = "c3.w"; # base for start of skinning matrices + +; 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"; + +; currently unused +; c12, c13 + +$SHADER_SPECIFIC_CONST_10 = "c14"; +$SHADER_SPECIFIC_CONST_11 = "c15"; + +$cFogParams = "c16"; +$cFogEndOverFogRange = "c16.x"; +$cFogOne = "c16.y"; +$cFogMaxDensity = "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 ] + +$cModulationColor = "c37"; + +$SHADER_SPECIFIC_CONST_0 = "c38"; +$SHADER_SPECIFIC_CONST_1 = "c39"; +$SHADER_SPECIFIC_CONST_2 = "c40"; +$SHADER_SPECIFIC_CONST_3 = "c41"; +$SHADER_SPECIFIC_CONST_4 = "c42"; +$SHADER_SPECIFIC_CONST_5 = "c43"; +$SHADER_SPECIFIC_CONST_6 = "c44"; +$SHADER_SPECIFIC_CONST_7 = "c45"; +$SHADER_SPECIFIC_CONST_8 = "c46"; +$SHADER_SPECIFIC_CONST_9 = "c47"; +; $SHADER_SPECIFIC_CONST_10 is c14 +; $SHADER_SPECIFIC_CONST_11 is c15 + +; There are 16 model matrices for skinning +; NOTE: These must match the same values in vsh_prep.pl! +$cModel0 = "c48"; +$cModel1 = "c49"; +$cModel2 = "c50"; + +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 +{ + local( $projPos ) = 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! + + ; Compute |projPos| + local( $tmp ); + &AllocateRegister( \$tmp ); + dp3 $tmp.x, $projPos.xyw, $projPos.xyw + rsq $tmp.x, $tmp.x + rcp $tmp.x, $tmp.x + + if( $g_dx9 ) + { + mad $tmp, -$tmp.x, $cOOFogRange, $cFogEndOverFogRange + min $tmp, $tmp, $cOne + max oFog, $tmp.x, $cFogMaxDensity + } + else + { + mad $tmp, -$tmp.x, $cOOFogRange, $cFogEndOverFogRange + min $tmp, $tmp, $cOne + max oFog.x, $tmp.x, $cFogMaxDensity + } + &FreeRegister( \$tmp ); +} + +sub DepthFog +{ + local( $projPos ) = shift; + local( $dest ) = shift; + + if ( $dest eq "" ) + { + $dest = "oFog"; + } + + ;------------------------------ + ; 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! + + ; Compute |projPos| + local( $tmp ); + &AllocateRegister( \$tmp ); + + if( $g_dx9 ) + { + mad $tmp, -$projPos.w, $cOOFogRange, $cFogEndOverFogRange + min $tmp, $tmp, $cOne + max $dest, $tmp.x, $cFogMaxDensity + } + else + { + mad $tmp, -$projPos.w, $cOOFogRange, $cFogEndOverFogRange + min $tmp, $tmp, $cOne + max $dest.x, $tmp.x, $cFogMaxDensity + } + + &FreeRegister( \$tmp ); +} + +sub WaterRangeFog +{ + ; oFog.x = 1.0f = no fog + ; oFog.x = 0.0f = full fog + + ; only $worldPos.z is used out of worldPos + local( $worldPos ) = shift; + local( $projPos ) = shift; + + local( $tmp ); + &AllocateRegister( \$tmp ); + + ; This is simple similar triangles. Imagine a line passing from the point directly vertically + ; and another line passing from the point to the eye position. + ; Let d = total distance from point to the eye + ; Let h = vertical distance from the point to the eye + ; Let hw = vertical distance from the point to the water surface + ; Let dw = distance from the point to a point on the water surface that lies along the ray from point to eye + ; Therefore d/h = dw/hw by similar triangles, or dw = d * hw / h. + ; d = |projPos|, h = eyepos.z - worldPos.z, hw = waterheight.z - worldPos.z, dw = what we solve for + + ; Now, tmp.x = hw, and tmp.y = h + add $tmp.xy, $cEyePosWaterZ.wz, -$worldPos.z + + ; 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 + + ; Compute 1 / |projPos| = 1/d + dp3 $tmp.z, $projPos.xyw, $projPos.xyw + rsq $tmp.z, $tmp.z + + ; Now we have h/d + mul $tmp.z, $tmp.z, $tmp.y + + ; Now we have d/h + rcp $tmp.w, $tmp.z + + ; We finally have d * hw / h + ; $tmp.w is now the distance that we see through water. + mul $tmp.w, $tmp.x, $tmp.w + + if( $g_dx9 ) + { + mad $tmp, -$tmp.w, $cOOFogRange, $cFogOne + min $tmp, $tmp, $cOne + max oFog, $tmp.x, $cFogMaxDensity + } + else + { + mad $tmp, -$tmp.w, $cOOFogRange, $cFogOne + min $tmp, $tmp, $cOne + max oFog.x, $tmp.x, $cFogMaxDensity + } + + &FreeRegister( \$tmp ); +} + +sub WaterDepthFog +{ + ; oFog.x = 1.0f = no fog + ; oFog.x = 0.0f = full fog + + ; only $worldPos.z is used out of worldPos + local( $worldPos ) = shift; + local( $projPos ) = shift; + local( $dest ) = shift; + + if ( $dest eq "" ) + { + $dest = "oFog"; + } + + local( $tmp ); + &AllocateRegister( \$tmp ); + + ; This is simple similar triangles. Imagine a line passing from the point directly vertically + ; and another line passing from the point to the eye position. + ; Let d = total distance from point to the eye + ; Let h = vertical distance from the point to the eye + ; Let hw = vertical distance from the point to the water surface + ; Let dw = distance from the point to a point on the water surface that lies along the ray from point to eye + ; Therefore d/h = dw/hw by similar triangles, or dw = d * hw / h. + ; d = projPos.w, h = eyepos.z - worldPos.z, hw = waterheight.z - worldPos.z, dw = what we solve for + + ; Now, tmp.x = hw, and tmp.y = h + add $tmp.xy, $cEyePosWaterZ.wz, -$worldPos.z + + ; 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 + + ; Now we have 1/h + rcp $tmp.z, $tmp.y + + ; Now we have d/h + mul $tmp.w, $projPos.w, $tmp.z + + ; We finally have d * hw / h + ; $tmp.w is now the distance that we see through water. + mul $tmp.w, $tmp.x, $tmp.w + + if( $g_dx9 ) + { + mad $tmp, -$tmp.w, $cOOFogRange, $cFogOne + min $tmp, $tmp, $cOne + max $dest, $tmp.x, $cZero + } + else + { + mad $tmp, -$tmp.w, $cOOFogRange, $cFogOne + min $tmp, $tmp, $cOne + max $dest.x, $tmp.x, $cZero + } + + &FreeRegister( \$tmp ); +} + + +;------------------------------------------------------------------------------ +; Main fogging routine +;------------------------------------------------------------------------------ +sub CalcFog +{ + if( !defined $DOWATERFOG ) + { + die "CalcFog called without using \$DOWATERFOG\n"; + } + my $fogType; + if( $DOWATERFOG == 0 ) + { + $fogType = "rangefog"; + } + else + { + $fogType = "heightfog"; + } + +# print "\$fogType = $fogType\n"; + + ; CalcFog + local( $worldPos ) = shift; + local( $projPos ) = shift; + local( $dest ) = shift; + + if ( $dest eq "" ) + { + $dest = "oFog"; + } + + if( $fogType eq "rangefog" ) + { + &DepthFog( $projPos, $dest ); + } + elsif( $fogType eq "heightfog" ) + { + &WaterDepthFog( $worldPos, $projPos, $dest ); + } + else + { + die; + } +} + +sub CalcRangeFog +{ + ; CalcFog + local( $worldPos ) = shift; + local( $projPos ) = shift; + + if( $DOWATERFOG == 0 ) + { + &RangeFog( $projPos ); + } + elsif( $DOWATERFOG == 1 ) + { + &WaterRangeFog( $worldPos, $projPos ); + } + else + { + die; + } +} + +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; + + local( $vertToEye ); &AllocateRegister( \$vertToEye ); + local( $tmp ); &AllocateRegister( \$tmp ); + + ; compute reflection vector r = 2 * (n dot v) n - v + sub $vertToEye.xyz, $cEyePos.xyz, $worldPos ; $tmp1 = v = c - p + dp3 $tmp, $worldNormal, $vertToEye ; $tmp = n dot v + mul $tmp.xyz, $tmp.xyz, $worldNormal ; $tmp = (n dot v ) n + mad $reflectionVector.xyz, $tmp, $cTwo, -$vertToEye + + &FreeRegister( \$vertToEye ); + &FreeRegister( \$tmp ); +} + +sub ComputeSphereMapTexCoords +{ + local( $reflectionVector ) = shift; + local( $sphereMapTexCoords ) = shift; + + local( $tmp ); &AllocateRegister( \$tmp ); + + ; transform reflection vector into view space + dp3 $tmp.x, $reflectionVector, $cViewModel0 + dp3 $tmp.y, $reflectionVector, $cViewModel1 + dp3 $tmp.z, $reflectionVector, $cViewModel2 + + ; generate + add $tmp.z, $tmp.z, $cOne + + ; find 1 / the length of r2 + dp3 $tmp.w, $tmp, $tmp + rsq $tmp.w, $tmp.w + + ; r1 = r2/|r2| + 1 + mad $tmp.xy, $tmp.w, $tmp, $cOne + mul $sphereMapTexCoords.xy, $tmp.xy, $cHalf + + &FreeRegister( \$tmp ); +} + +sub SkinPosition +{ +# print "\$SKINNING = $SKINNING\n"; + local( $worldPos ) = shift; + + if( !defined $SKINNING ) + { + die "using \$SKINNING without defining.\n"; + } + + if( $SKINNING == 0 ) + { + ; + ; 0 bone skinning (4 instructions) + ; + ; Transform position into world space + ; position + dp4 $worldPos.x, $vPos, $cModel0 + dp4 $worldPos.y, $vPos, $cModel1 + dp4 $worldPos.z, $vPos, $cModel2 + mov $worldPos.w, $cOne + } + else + { + ; + ; 3 bone skinning (19 instructions) + ; + local( $boneIndices ); + local( $blendedMatrix0 ); + local( $blendedMatrix1 ); + local( $blendedMatrix2 ); + local( $localPos ); + &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 + if ( $g_x360 ) + { + mov $boneIndices, $boneIndices.zyxw + } + + ; 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 + + dp4 $worldPos.x, $vPos, $blendedMatrix0 + dp4 $worldPos.y, $vPos, $blendedMatrix1 + dp4 $worldPos.z, $vPos, $blendedMatrix2 + mov $worldPos.w, $cOne + + &FreeRegister( \$boneIndices ); + &FreeRegister( \$blendedMatrix0 ); + &FreeRegister( \$blendedMatrix1 ); + &FreeRegister( \$blendedMatrix2 ); + } +} + + +sub SkinPositionAndNormal +{ +# print "\$SKINNING = $SKINNING\n"; + local( $worldPos ) = shift; + local( $worldNormal ) = shift; + + if( !defined $SKINNING ) + { + die "using \$SKINNING without defining.\n"; + } + + if( $SKINNING == 0 ) + { + ; + ; 0 bone skinning (13 instructions) + ; + ; Transform position + normal + tangentS + tangentT into world space + ; position + dp4 $worldPos.x, $vPos, $cModel0 + dp4 $worldPos.y, $vPos, $cModel1 + dp4 $worldPos.z, $vPos, $cModel2 + mov $worldPos.w, $cOne + ; normal + dp3 $worldNormal.x, $vNormal, $cModel0 + dp3 $worldNormal.y, $vNormal, $cModel1 + dp3 $worldNormal.z, $vNormal, $cModel2 + } + else + { + local( $boneIndices ); + local( $blendedMatrix0 ); + local( $blendedMatrix1 ); + local( $blendedMatrix2 ); + local( $localPos ); + local( $localNormal ); + local( $normalLength ); + local( $ooNormalLength ); + &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 + if ( $g_x360 ) + { + mov $boneIndices, $boneIndices.zyxw + } + + ; 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 + + 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 + + &FreeRegister( \$boneIndices ); + &FreeRegister( \$blendedMatrix0 ); + &FreeRegister( \$blendedMatrix1 ); + &FreeRegister( \$blendedMatrix2 ); + } +} + +sub SkinPositionNormalAndTangentSpace +{ +# print "\$SKINNING = $SKINNING\n"; + local( $worldPos ) = shift; + local( $worldNormal ) = shift; + local( $worldTangentS ) = shift; + local( $worldTangentT ) = shift; + local( $userData ); + local( $localPos ); + local( $localNormal ); + local( $normalLength ); + local( $ooNormalLength ); + + if( !defined $SKINNING ) + { + die "using \$SKINNING without defining.\n"; + } + +# X360TBD: needed for compressed vertex format +# if ( $g_x360 ) +# { +# &AllocateRegister( \$userData ); +# ; remap compressed range [0..1] to [-1..1] +# mad $userData, $vUserData, $cTwo, -$cOne +# } + + if( $SKINNING == 0 ) + { + ; + ; 0 bone skinning (13 instructions) + ; + ; Transform position + normal + tangentS + tangentT into world space + dp4 $worldPos.x, $vPos, $cModel0 + dp4 $worldPos.y, $vPos, $cModel1 + dp4 $worldPos.z, $vPos, $cModel2 + mov $worldPos.w, $cOne + + ; normal + dp3 $worldNormal.x, $vNormal, $cModel0 + dp3 $worldNormal.y, $vNormal, $cModel1 + dp3 $worldNormal.z, $vNormal, $cModel2 + +# X360TBD: needed for compressed vertex format +# if ( $g_x360 ) +# { +# ; tangents +# dp3 $worldTangentS.x, $userData, $cModel0 +# dp3 $worldTangentS.y, $userData, $cModel1 +# dp3 $worldTangentS.z, $userData, $cModel2 +# +# ; calculate tangent t via cross( N, S ) * S[3] +# &Cross( $worldTangentT, $worldNormal, $worldTangentS ); +# mul $worldTangentT.xyz, $userData.w, $worldTangentT.xyz +# } +# else + { + ; tangents + dp3 $worldTangentS.x, $vUserData, $cModel0 + dp3 $worldTangentS.y, $vUserData, $cModel1 + dp3 $worldTangentS.z, $vUserData, $cModel2 + + ; calculate tangent t via cross( N, S ) * S[3] + &Cross( $worldTangentT, $worldNormal, $worldTangentS ); + mul $worldTangentT.xyz, $vUserData.w, $worldTangentT.xyz + } + } + else + { + 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 + if ( $g_x360 ) + { + mov $boneIndices, $boneIndices.zyxw + } + + ; 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 + +# X360TBD: needed for compressed vertex format +# if ( $g_x360 ) +# { +# ; tangents +# dp3 $worldTangentS.x, $userData, $blendedMatrix0 +# dp3 $worldTangentS.y, $userData, $blendedMatrix1 +# dp3 $worldTangentS.z, $userData, $blendedMatrix2 +# +# ; calculate tangent t via cross( N, S ) * S[3] +# &Cross( $worldTangentT, $worldNormal, $worldTangentS ); +# mul $worldTangentT.xyz, $userData.w, $worldTangentT.xyz +# } +# else + { + ; 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 ); + } + +# X360TBD: needed for compressed vertex format +# if ( $g_x360 ) +# { +# &FreeRegister( \$userData ); +# } +} + +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 + + if ( $HALF_LAMBERT == 0 ) + { + ; lambert + max $nDotL.x, $nDotL.x, c0.x ; Clamp to zero + } + elsif ( $HALF_LAMBERT == 1 ) + { + ; half-lambert + mad $nDotL.x, $nDotL.x, $cHalf, $cHalf ; dot = (dot * 0.5 + 0.5)^2 + mul $nDotL.x, $nDotL.x, $nDotL.x + } + else + { + die "\$HALF_LAMBERT is hosed\n"; + } + + if( $add ) + { + mad $linearColor.xyz, c[a0.x], $nDotL.x, $linearColor + } + else + { + mul $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 + + if ( $HALF_LAMBERT == 0 ) + { + ; lambert + max $tmp.x, $tmp.x, c0.x ; Clamp to zero + } + elsif ( $HALF_LAMBERT == 1 ) + { + ; half-lambert + mad $tmp.x, $tmp.x, $cHalf, $cHalf ; dot = (dot * 0.5 + 0.5)^2 + mul $tmp.x, $tmp.x, $tmp.x + } + else + { + die "\$HALF_LAMBERT is hosed\n"; + } + + mul $tmp.x, $tmp.x, $lightDir.w + if( $add ) + { + mad $linearColor.xyz, c[a0.x], $tmp.x, $linearColor + } + else + { + mul $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 + + if ( $HALF_LAMBERT == 0 ) + { + ; lambert + max $litSrc.x, $litSrc.x, c0.x ; Clamp to zero + } + elsif ( $HALF_LAMBERT == 1 ) + { + ; half-lambert + mad $litSrc.x, $litSrc.x, $cHalf, $cHalf ; dot = (dot * 0.5 + 0.5) ^ 2 + mul $litSrc.x, $litSrc.x, $litSrc.x + } + else + { + die "\$HALF_LAMBERT is hosed\n"; + } + + ; 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 + { + mul $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 +{ + if( !defined $LIGHT_COMBO ) + { + die "DoLighting called without using \$LIGHT_COMBO\n"; + } + if ( !defined $HALF_LAMBERT ) + { + die "DoLighting called without using \$HALF_LAMBERT\n"; + } + + my $staticLightType = $g_staticLightTypeArray[$LIGHT_COMBO]; + my $ambientLightType = $g_ambientLightTypeArray[$LIGHT_COMBO]; + my $localLightType1 = $g_localLightType1Array[$LIGHT_COMBO]; + my $localLightType2 = $g_localLightType2Array[$LIGHT_COMBO]; + +# print "\$staticLightType = $staticLightType\n"; +# print "\$ambientLightType = $ambientLightType\n"; +# print "\$localLightType1 = $localLightType1\n"; +# print "\$localLightType2 = $localLightType2\n"; + + local( $worldPos ) = shift; + local( $worldNormal ) = shift; + + ; special case for no lighting + if( $staticLightType eq "none" && $ambientLightType eq "none" && + $localLightType1 eq "none" && $localLightType2 eq "none" ) + { + ; Have to write something here since debug d3d runtime will barf otherwise. + mov oD0, $cOne + 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, $cLight0Offset + &DoLight( $localLightType1, $worldPos, $worldNormal, $linearColor, $add ); + $add = 1; + } + + if( $localLightType2 ne "none" ) + { + mov a0.x, $cLight1Offset + &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, $cOne ; make sure all components are defined + + free $linearColor + free $gammaColor +} + +sub DoDynamicLightingToLinear +{ + local( $worldPos ) = shift; + local( $worldNormal ) = shift; + local( $linearColor ) = shift; + + if( !defined $LIGHT_COMBO ) + { + die "DoLighting called without using \$LIGHT_COMBO\n"; + } + if ( !defined $HALF_LAMBERT ) + { + die "DoLighting called without using \$HALF_LAMBERT\n"; + } + + my $staticLightType = $g_staticLightTypeArray[$LIGHT_COMBO]; + my $ambientLightType = $g_ambientLightTypeArray[$LIGHT_COMBO]; + my $localLightType1 = $g_localLightType1Array[$LIGHT_COMBO]; + my $localLightType2 = $g_localLightType2Array[$LIGHT_COMBO]; + + # 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, $cLight0Offset + &DoLight( $localLightType1, $worldPos, $worldNormal, $linearColor, $add ); + $add = 1; + } + + if( $localLightType2 ne "none" ) + { + mov a0.x, $cLight1Offset + &DoLight( $localLightType2, $worldPos, $worldNormal, $linearColor, $add ); + $add = 1; + } +} + +sub NotImplementedYet +{ + &AllocateRegister( \$projPos ); + dp4 $projPos.x, $worldPos, $cViewProj0 + dp4 $projPos.y, $worldPos, $cViewProj1 + dp4 $projPos.z, $worldPos, $cViewProj2 + dp4 $projPos.w, $worldPos, $cViewProj3 + mov oPos, $projPos + &FreeRegister( \$projPos ); + exit; +} diff --git a/materialsystem/stdshaders/modulate_dx9.cpp b/materialsystem/stdshaders/modulate_dx9.cpp new file mode 100644 index 00000000..75d7523d --- /dev/null +++ b/materialsystem/stdshaders/modulate_dx9.cpp @@ -0,0 +1,355 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=====================================================================================// + +#include "BaseVSShader.h" +#include "convar.h" + +#include "unlitgeneric_vs20.inc" +#include "modulate_ps20.inc" +#include "modulate_ps20b.inc" + +#include "cpp_shader_constant_register_map.h" + +#if !defined( _X360 ) + #include "modulate_ps30.inc" + #include "unlitgeneric_vs30.inc" +#endif + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" +#include "cloak_blended_pass_helper.h" + +static ConVar mat_displacementmap( "mat_displacementmap", "1", FCVAR_CHEAT ); + + +DEFINE_FALLBACK_SHADER( Modulate, Modulate_DX9 ) + +BEGIN_VS_SHADER( Modulate_DX9, + "Help for Modulate" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( WRITEZ, SHADER_PARAM_TYPE_BOOL, "0", "Forces z to be written if set" ) + SHADER_PARAM( MOD2X, SHADER_PARAM_TYPE_BOOL, "0", "forces a 2x modulate so that you can brighten and darken things" ) + + // Cloak Pass + SHADER_PARAM( CLOAKPASSENABLED, SHADER_PARAM_TYPE_BOOL, "0", "Enables cloak render in a second pass" ) + SHADER_PARAM( CLOAKFACTOR, SHADER_PARAM_TYPE_FLOAT, "0.0", "" ) + SHADER_PARAM( CLOAKCOLORTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Cloak color tint" ) + SHADER_PARAM( REFRACTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "2", "" ) + END_SHADER_PARAMS + + SHADER_FALLBACK + { + return 0; + } + + // Cloak Pass + void SetupVarsCloakBlendedPass( CloakBlendedPassVars_t &info ) + { + info.m_nCloakFactor = CLOAKFACTOR; + info.m_nCloakColorTint = CLOAKCOLORTINT; + info.m_nRefractAmount = REFRACTAMOUNT; + } + + bool NeedsPowerOfTwoFrameBufferTexture( IMaterialVar **params, bool bCheckSpecificToThisFrame ) const + { + if ( params[CLOAKPASSENABLED]->GetIntValue() ) // If material supports cloaking + { + if ( bCheckSpecificToThisFrame == false ) // For setting model flag at load time + return true; + else if ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) // Per-frame check + return true; + // else, not cloaking this frame, so check flag2 in case the base material still needs it + } + + // Check flag2 if not drawing cloak pass + return IS_FLAG2_SET( MATERIAL_VAR2_NEEDS_POWER_OF_TWO_FRAME_BUFFER_TEXTURE ); + } + + bool IsTranslucent( IMaterialVar **params ) const + { + if ( params[CLOAKPASSENABLED]->GetIntValue() ) // If material supports cloaking + { + if ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) // Per-frame check + return true; + // else, not cloaking this frame, so check flag in case the base material still needs it + } + + // Check flag if not drawing cloak pass + return IS_FLAG_SET( MATERIAL_VAR_TRANSLUCENT ); + } + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + + // Cloak Pass + if ( !params[CLOAKPASSENABLED]->IsDefined() ) + { + params[CLOAKPASSENABLED]->SetIntValue( 0 ); + } + else if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + InitParamsCloakBlendedPass( this, params, pMaterialName, info ); + } + } + + SHADER_INIT + { + if (params[BASETEXTURE]->IsDefined()) + { + LoadTexture( BASETEXTURE ); + } + + // Cloak Pass + if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + InitCloakBlendedPass( this, params, info ); + } + } + + SHADER_DRAW + { + // Skip the standard rendering if cloak pass is fully opaque + bool bDrawStandardPass = true; + if ( params[CLOAKPASSENABLED]->GetIntValue() && ( pShaderShadow == NULL ) ) // && not snapshotting + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + if ( CloakBlendedPassIsFullyOpaque( params, info ) ) + { + bDrawStandardPass = false; + } + } + + // Standard rendering pass + if ( bDrawStandardPass ) + { + bool bMod2X = params[MOD2X]->IsDefined() && params[MOD2X]->GetIntValue(); + bool bVertexColorOrAlpha = IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR ) || IS_FLAG_SET( MATERIAL_VAR_VERTEXALPHA ); + bool bWriteZ = params[WRITEZ]->GetIntValue() != 0; + BlendType_t nBlendType = EvaluateBlendRequirements( BASETEXTURE, true ); + bool bFullyOpaque = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !IS_FLAG_SET(MATERIAL_VAR_ALPHATEST); //dest alpha is free for special use + + SHADOW_STATE + { + if( bMod2X ) + { + EnableAlphaBlending( SHADER_BLEND_DST_COLOR, SHADER_BLEND_SRC_COLOR ); + } + else + { + EnableAlphaBlending( SHADER_BLEND_DST_COLOR, SHADER_BLEND_ZERO ); + } + + if ( bWriteZ ) + { + // This overrides the disabling of depth writes performed in + // EnableAlphaBlending + pShaderShadow->EnableDepthWrites( true ); + } + + unsigned int flags = VERTEX_POSITION; + int numTexCoords = 0; + int userDataSize = 0; + + if( params[BASETEXTURE]->IsTexture() ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + numTexCoords = 1; + } + + if( bVertexColorOrAlpha ) + { + flags |= VERTEX_COLOR; + } + + // HACK: add 1 texcoord if these verts are too thin (to do with how we + // bind stream 2 - see CShaderShadowDX8::VertexShaderVertexFormat) + // FIXME: instead of this, don't add stream 2 elements to all vertex decls! + if ( !( flags & VERTEX_COLOR ) && ( numTexCoords == 0 ) ) + { + numTexCoords = 1; + } + + // This shader supports compressed vertices, so OR in that flag: + flags |= VERTEX_FORMAT_COMPRESSED; + + pShaderShadow->VertexShaderVertexFormat( flags, numTexCoords, NULL, userDataSize ); + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_STATIC_VERTEX_SHADER( unlitgeneric_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( VERTEXCOLOR, bVertexColorOrAlpha ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER( unlitgeneric_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( modulate_ps20b ); + SET_STATIC_PIXEL_SHADER( modulate_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( modulate_ps20 ); + SET_STATIC_PIXEL_SHADER( modulate_ps20 ); + } + } +#ifndef _X360 + else + { + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_TESSELLATION ); + + DECLARE_STATIC_VERTEX_SHADER( unlitgeneric_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( VERTEXCOLOR, bVertexColorOrAlpha ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER( unlitgeneric_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( modulate_ps30 ); + SET_STATIC_PIXEL_SHADER( modulate_ps30 ); + } +#endif + + // We need to fog to *white* regardless of overbrighting... + if( bMod2X ) + { + FogToGrey(); + } + else + { + FogToOOOverbright(); + } + + pShaderShadow->EnableAlphaWrites( bWriteZ && bFullyOpaque ); + + PI_BeginCommandBuffer(); + + // set constant color for modulation + PI_SetModulationVertexShaderDynamicState(); + + PI_EndCommandBuffer(); + } + DYNAMIC_STATE + { + if( params[BASETEXTURE]->IsTexture() ) + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BASETEXTURETRANSFORM ); + } + + // We need to fog to *white* regardless of overbrighting... + if( bMod2X ) + { + float grey[4] = { 0.5f, 0.5f, 0.5f, 1.0f }; + pShaderAPI->SetPixelShaderConstant( 0, grey ); + } + else + { + float white[4] = { 0.5f, 0.5f, 0.5f, 1.0f }; + pShaderAPI->SetPixelShaderConstant( 0, white ); + } + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + float vEyePos_SpecExponent[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + vEyePos_SpecExponent[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + + BOOL bShaderConstants[1] = { bVertexColorOrAlpha }; + pShaderAPI->SetBooleanVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_BOOL_CONST_0, bShaderConstants, 1 ); + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_DYNAMIC_VERTEX_SHADER( unlitgeneric_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( TESSELLATION, 0 ); + SET_DYNAMIC_VERTEX_SHADER( unlitgeneric_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( modulate_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bWriteZ && bFullyOpaque && pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( modulate_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( modulate_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( modulate_ps20 ); + } + } +#ifndef _X360 + else + { + TessellationMode_t nTessellationMode = pShaderAPI->GetTessellationMode(); + if ( nTessellationMode != TESSELLATION_MODE_DISABLED ) + { + pShaderAPI->BindStandardVertexTexture( SHADER_VERTEXTEXTURE_SAMPLER1, TEXTURE_SUBDIVISION_PATCHES ); + + bool bHasDisplacement = false; // TODO + float vSubDDimensions[4] = { 1.0f/pShaderAPI->GetSubDHeight(), bHasDisplacement && mat_displacementmap.GetBool() ? 1.0f : 0.0f, 0.0f, 0.0f }; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_8, vSubDDimensions ); + +// JasonM - revisit this later...requires plumbing in a separate vertex texture param type?? +// bool bHasDisplacement = (info.m_nDisplacementMap != -1) && params[info.m_nDisplacementMap]->IsTexture(); +// if( bHasDisplacement ) +// { +// pShader->BindVertexTexture( SHADER_VERTEXTEXTURE_SAMPLER2, info.m_nDisplacementMap ); +// } +// else +// { +// pShaderAPI->BindStandardVertexTexture( SHADER_VERTEXTEXTURE_SAMPLER2, VERTEX_TEXTURE_BLACK ); +// } + } + + DECLARE_DYNAMIC_VERTEX_SHADER( unlitgeneric_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( TESSELLATION, nTessellationMode ); + SET_DYNAMIC_VERTEX_SHADER( unlitgeneric_vs30 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( modulate_ps30 ); + + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bWriteZ && bFullyOpaque && pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( modulate_ps30 ); + } +#endif + + } + Draw(); + } + else + { + // Skip this pass! + Draw( false ); + } + + // Cloak Pass + if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + // If ( snapshotting ) or ( we need to draw this frame ) + if ( ( pShaderShadow != NULL ) || ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + DrawCloakBlendedPass( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else // We're not snapshotting and we don't need to draw this frame + { + // Skip this pass! + Draw( false ); + } + } + } +END_SHADER diff --git a/materialsystem/stdshaders/modulate_ps2x.fxc b/materialsystem/stdshaders/modulate_ps2x.fxc new file mode 100644 index 00000000..8283ed7a --- /dev/null +++ b/materialsystem/stdshaders/modulate_ps2x.fxc @@ -0,0 +1,39 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// +//paired with vertexlit_and_unlit_generic_vs## + +#include "common_fog_ps_fxc.h" +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps30] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] + +#if defined( SHADER_MODEL_PS_2_0 ) + #define WRITE_DEPTH_TO_DESTALPHA 0 +#endif + +#include "common_ps_fxc.h" +#include "shader_constant_register_map.h" + +sampler BaseTextureSampler : register( s0 ); + +const float4 g_WhiteGrayMix : register( c0 ); +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT ); + +struct PS_INPUT +{ + float2 vTexCoord0 : TEXCOORD0; + float4 vColor : COLOR0; + + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float4 textureColor = tex2D( BaseTextureSampler, i.vTexCoord0 ); + + float4 resultColor = saturate( textureColor * i.vColor ); + resultColor.rgb = lerp( g_WhiteGrayMix.rgb, resultColor.rgb, resultColor.a ); + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos_SpecExponent.xyz, i.worldPos_projPosZ.xyz, i.worldPos_projPosZ.w ); + return FinalOutput( resultColor, fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_NONE, (WRITE_DEPTH_TO_DESTALPHA != 0), i.worldPos_projPosZ.w ); +} diff --git a/materialsystem/stdshaders/monitorscreen_ps2x.fxc b/materialsystem/stdshaders/monitorscreen_ps2x.fxc new file mode 100644 index 00000000..4899fcc8 --- /dev/null +++ b/materialsystem/stdshaders/monitorscreen_ps2x.fxc @@ -0,0 +1,55 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// +//paired with unlittwotexture_vs20 + +// STATIC: "TEXTURE2" "0..1" + +#include "common_fog_ps_fxc.h" +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] + +#if defined( SHADER_MODEL_PS_2_0 ) +# define WRITE_DEPTH_TO_DESTALPHA 0 +#endif + +#include "shader_constant_register_map.h" +#include "common_ps_fxc.h" + +sampler BaseTextureSampler : register( s0 ); +sampler SecondaryTextureSampler : register( s1 ); + + +const float4 g_Contrast : register( c1 ); +const float4 g_Saturation : register( c2 ); +const float4 g_Tint : register( c3 ); +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT ); + +#define g_Grey float4( 0.33333f, 0.33333f, 0.33333f, 0.33333f ) + +struct PS_INPUT +{ + float2 vTexCoord0 : TEXCOORD0; + float2 vTexCoord1 : TEXCOORD1; + + float4 vColor : COLOR0; + + float4 worldPos_projPosZ : TEXCOORD7; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float4 resultColor = tex2D( BaseTextureSampler, i.vTexCoord0 ) * i.vColor; // base texture modulated with vertex color + +#if (TEXTURE2 == 1) + resultColor = tex2D( SecondaryTextureSampler, i.vTexCoord1 ) * resultColor; // modulate base color by another texture +#endif + + float3 tempColor = resultColor.rgb * resultColor.rgb; //base * base + resultColor.rgb = lerp( resultColor.rgb, tempColor.rgb, g_Contrast.rgb ); // blend between color and color * color + tempColor = dot( resultColor.rgb, g_Grey ); // color greyscaled + resultColor.rgb = lerp( tempColor.rgb, resultColor.rgb, g_Saturation.rgb ); // blend between color and greyscale + resultColor.rgb = resultColor.rgb * g_Tint.rgb; // tint + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos_SpecExponent.xyz, i.worldPos_projPosZ.xyz, i.worldPos_projPosZ.w ); + return FinalOutput( resultColor, fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_NONE, (WRITE_DEPTH_TO_DESTALPHA != 0), i.worldPos_projPosZ.w ); +} diff --git a/materialsystem/stdshaders/morphaccumulate_dx9.cpp b/materialsystem/stdshaders/morphaccumulate_dx9.cpp new file mode 100644 index 00000000..f79a63e1 --- /dev/null +++ b/materialsystem/stdshaders/morphaccumulate_dx9.cpp @@ -0,0 +1,108 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" + + +#include "morphaccumulate_vs30.inc" +#include "morphaccumulate_ps30.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( MorphAccumulate, MorphAccumulate_DX9 ) + +BEGIN_VS_SHADER_FLAGS( MorphAccumulate_DX9, "Help for MorphAccumulate", SHADER_NOT_EDITABLE ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( DELTA, SHADER_PARAM_TYPE_TEXTURE, "", "position/normal deltas" ) + SHADER_PARAM( SIDESPEED, SHADER_PARAM_TYPE_TEXTURE, "", "side/speed map" ) + SHADER_PARAM( DIMENSIONS, SHADER_PARAM_TYPE_VEC3, "", "delta dimensions" ) + SHADER_PARAM( DELTASCALE, SHADER_PARAM_TYPE_FLOAT, "", "delta scale" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + LoadTexture( DELTA ); + LoadTexture( SIDESPEED ); + } + + SHADER_DRAW + { + bool bUseConstantBasedAccum = ( g_pHardwareConfig->NumVertexShaderConstants() >= VERTEX_SHADER_FLEX_WEIGHTS + VERTEX_SHADER_MAX_FLEX_WEIGHT_COUNT ); + + SHADOW_STATE + { + EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); + pShaderShadow->EnableBlendingSeparateAlpha( true ); + pShaderShadow->BlendFuncSeparateAlpha( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); + pShaderShadow->EnableDepthTest( false ); + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableAlphaWrites( true ); + pShaderShadow->EnableCulling( false ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + pShaderShadow->FogMode( SHADER_FOGMODE_DISABLED, false ); + + DECLARE_STATIC_VERTEX_SHADER( morphaccumulate_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( CONSTANTBASEDMORPH, bUseConstantBasedAccum ); + SET_STATIC_VERTEX_SHADER( morphaccumulate_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( morphaccumulate_ps30 ); + SET_STATIC_PIXEL_SHADER_COMBO( CONSTANTBASEDMORPH, bUseConstantBasedAccum ); + SET_STATIC_PIXEL_SHADER( morphaccumulate_ps30 ); + + // NOTE: Color indicates where in the morph accumulator to render into + // Texcoord0 is the texcoord to read from in the source morph texture + // Texcoord1 indicates the strength of the morph target + int pTexCoord[2] = { 4, 1 }; + pShaderShadow->VertexShaderVertexFormat( VERTEX_FORMAT_USE_EXACT_FORMAT, 2, pTexCoord, 0 ); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, DELTA ); + BindTexture( SHADER_SAMPLER1, SIDESPEED ); + + if ( !bUseConstantBasedAccum ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_MORPH_WEIGHTS ); + + int nXOffset = pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_MORPH_WEIGHT_X_OFFSET ); + int nYOffset = pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_MORPH_WEIGHT_Y_OFFSET ); + int nSubrectWidth = pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_MORPH_WEIGHT_SUBRECT_WIDTH ); + int nSubrectHeight = pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_MORPH_WEIGHT_SUBRECT_HEIGHT ); + float pMorphWeightSubrect[4] = { nXOffset, nYOffset, nSubrectWidth, nSubrectHeight }; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, pMorphWeightSubrect ); + + int nWidth, nHeight; + pShaderAPI->GetStandardTextureDimensions( &nWidth, &nHeight, TEXTURE_MORPH_WEIGHTS ); + float pMorphWeightDim[4] = { nWidth, nHeight, 0, 0 }; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, pMorphWeightDim ); + } + + SetPixelShaderConstant( 0, DELTASCALE ); + + DECLARE_DYNAMIC_VERTEX_SHADER( morphaccumulate_vs30 ); + SET_DYNAMIC_VERTEX_SHADER( morphaccumulate_vs30 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( morphaccumulate_ps30 ); + SET_DYNAMIC_PIXEL_SHADER( morphaccumulate_ps30 ); + } + Draw(); + } +END_SHADER + diff --git a/materialsystem/stdshaders/morphaccumulate_ps30.fxc b/materialsystem/stdshaders/morphaccumulate_ps30.fxc new file mode 100644 index 00000000..501d85e6 --- /dev/null +++ b/materialsystem/stdshaders/morphaccumulate_ps30.fxc @@ -0,0 +1,59 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "CONSTANTBASEDMORPH" "0..1" + +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_fxc.h" + +struct PS_INPUT +{ + float2 vSrcCoord : TEXCOORD0; + float2 vSideSpeedCoord : TEXCOORD1; +#if CONSTANTBASEDMORPH + float4 vMorphWeights : TEXCOORD2; +#else + float2 vMorphWeightCoord : TEXCOORD2; +#endif +}; + +sampler MorphTarget : register( s0 ); +sampler SideSpeedMap : register( s1 ); +#if !CONSTANTBASEDMORPH +sampler MorphWeights : register( s2 ); +#endif + +const float4 vMorphScale : register( c0 ); + +HALF4 main( PS_INPUT i ) : COLOR +{ +#if CONSTANTBASEDMORPH + float4 vMorphWeights = i.vMorphWeights; +#else + float4 vMorphWeights = tex2D( MorphWeights, i.vMorphWeightCoord ); +#endif + + float4 delta = tex2D( MorphTarget, i.vSrcCoord ); + float4 sideSpeed = tex2D( SideSpeedMap, i.vSideSpeedCoord ); + + // NOTE: This is necessary to fixup slight errors in the delta. + // On the cpu, only the range 0-65534 is used so we can encode -1, 0, and 1 exactly. + delta *= 65535.0f / 65534.0f; + + // Compute total weight, taking into account side + speed + float flWeight = lerp( vMorphWeights.y, vMorphWeights.x, sideSpeed.y ); + float flStereoWeight = lerp( vMorphWeights.w, vMorphWeights.z, sideSpeed.y ); + float w = lerp( flWeight, flStereoWeight, sideSpeed.x ); + + // Convert 0-1 -> -1 to 1 + delta *= 2.0f; + delta -= float4( 1.0f, 1.0f, 1.0f, 1.0f ); + + // Apply the morph scale + delta *= vMorphScale; + + // Apply weight + delta *= w; + + return delta; +} + diff --git a/materialsystem/stdshaders/morphaccumulate_vs30.fxc b/materialsystem/stdshaders/morphaccumulate_vs30.fxc new file mode 100644 index 00000000..fc40f606 --- /dev/null +++ b/materialsystem/stdshaders/morphaccumulate_vs30.fxc @@ -0,0 +1,54 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "CONSTANTBASEDMORPH" "0..1" + +#include "common_vs_fxc.h" + +struct VS_INPUT +{ + float4 vSrcCoord : TEXCOORD0; + float vMorphWeightId : TEXCOORD1; +}; + +struct VS_OUTPUT +{ + float4 vDestCoord : POSITION; + float2 vSrcCoord : TEXCOORD0; + float2 vSideSpeedCoord : TEXCOORD1; + +#if CONSTANTBASEDMORPH + float4 vMorphWeights : TEXCOORD2; +#else + float2 vMorphWeightCoord : TEXCOORD2; +#endif +}; + +#if !CONSTANTBASEDMORPH +const float4 vMorphWeightSubrect : register( SHADER_SPECIFIC_CONST_0 ); +const float4 vMorphWeightDimensions : register( SHADER_SPECIFIC_CONST_1 ); +#endif + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + // FIXME: Want these to be in pixel centers! + float2 projSpace = v.vSrcCoord.zw; + projSpace *= 2.0f; + projSpace -= 1.0f; + projSpace.y *= -1.0f; + + o.vDestCoord = float4( projSpace.x, projSpace.y, 0.0f, 1.0f ); + o.vSrcCoord = v.vSrcCoord.xy; + o.vSideSpeedCoord = v.vSrcCoord.xy; + +#if CONSTANTBASEDMORPH + o.vMorphWeights = cFlexWeights[ v.vMorphWeightId ]; +#else + float flColumn = floor( v.vMorphWeightId / vMorphWeightSubrect.w ); + o.vMorphWeightCoord.x = vMorphWeightSubrect.x + flColumn + 0.5f; + o.vMorphWeightCoord.y = vMorphWeightSubrect.y + v.vMorphWeightId - flColumn * vMorphWeightSubrect.w + 0.5f; + o.vMorphWeightCoord.xy /= vMorphWeightDimensions.xy; +#endif + return o; +} \ No newline at end of file diff --git a/materialsystem/stdshaders/morphweight_dx9.cpp b/materialsystem/stdshaders/morphweight_dx9.cpp new file mode 100644 index 00000000..8bc58096 --- /dev/null +++ b/materialsystem/stdshaders/morphweight_dx9.cpp @@ -0,0 +1,72 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" + + +#include "morphweight_vs30.inc" +#include "morphweight_ps30.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +//#define V1 1 + +DEFINE_FALLBACK_SHADER( MorphWeight, MorphWeight_DX9 ) + +BEGIN_VS_SHADER_FLAGS( MorphWeight_DX9, "Help for morphweight", SHADER_NOT_EDITABLE ) + + BEGIN_SHADER_PARAMS + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableDepthTest( false ); + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableAlphaWrites( true ); + pShaderShadow->EnableCulling( false ); + pShaderShadow->FogMode( SHADER_FOGMODE_DISABLED, false ); + + DECLARE_STATIC_VERTEX_SHADER( morphweight_vs30 ); + SET_STATIC_VERTEX_SHADER( morphweight_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( morphweight_ps30 ); + SET_STATIC_PIXEL_SHADER( morphweight_ps30 ); + + // Texcoord0 is the texcoord to write the weights into + // Texcoord1 contains the morph weights + int pTexCoord[2] = { 2, 4 }; + + pShaderShadow->VertexShaderVertexFormat( VERTEX_FORMAT_USE_EXACT_FORMAT, 2, pTexCoord, 0 ); + } + DYNAMIC_STATE + { + DECLARE_DYNAMIC_VERTEX_SHADER( morphweight_vs30 ); + SET_DYNAMIC_VERTEX_SHADER( morphweight_vs30 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( morphweight_ps30 ); + SET_DYNAMIC_PIXEL_SHADER( morphweight_ps30 ); + } + Draw(); + } +END_SHADER + diff --git a/materialsystem/stdshaders/morphweight_ps30.fxc b/materialsystem/stdshaders/morphweight_ps30.fxc new file mode 100644 index 00000000..f7070ad4 --- /dev/null +++ b/materialsystem/stdshaders/morphweight_ps30.fxc @@ -0,0 +1,13 @@ +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_fxc.h" + +struct PS_INPUT +{ + float4 vMorphWeights : TEXCOORD0; +}; + +HALF4 main( PS_INPUT i ) : COLOR +{ + return i.vMorphWeights; +} + diff --git a/materialsystem/stdshaders/morphweight_vs30.fxc b/materialsystem/stdshaders/morphweight_vs30.fxc new file mode 100644 index 00000000..d92fc7fa --- /dev/null +++ b/materialsystem/stdshaders/morphweight_vs30.fxc @@ -0,0 +1,29 @@ +#include "common_vs_fxc.h" + +struct VS_INPUT +{ + float2 vSrcCoord : TEXCOORD0; + float4 vMorphWeights : TEXCOORD1; +}; + +struct VS_OUTPUT +{ + float4 vDestCoord : POSITION; + float4 vMorphWeights : TEXCOORD0; +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + // FIXME: Want these to be in pixel centers! + float2 projSpace = v.vSrcCoord.xy; + projSpace *= 2.0f; + projSpace -= 1.0f; + projSpace.y *= -1.0f; + + o.vDestCoord = float4( projSpace.x, projSpace.y, 0.0f, 1.0f ); + o.vMorphWeights = v.vMorphWeights; + + return o; +} \ No newline at end of file diff --git a/materialsystem/stdshaders/motion_blur_dx9.cpp b/materialsystem/stdshaders/motion_blur_dx9.cpp new file mode 100644 index 00000000..d715ae3c --- /dev/null +++ b/materialsystem/stdshaders/motion_blur_dx9.cpp @@ -0,0 +1,141 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" +#include "motion_blur_vs20.inc" +#include "motion_blur_ps20.inc" +#include "motion_blur_ps20b.inc" +#include "convar.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +ConVar mat_motion_blur_percent_of_screen_max( "mat_motion_blur_percent_of_screen_max", "4.0" ); + +DEFINE_FALLBACK_SHADER( MotionBlur, MotionBlur_dx9 ) +BEGIN_VS_SHADER_FLAGS( MotionBlur_dx9, "Motion Blur", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( MOTIONBLURINTERNAL, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0]", "Internal motion blur value set by proxy" ) + SHADER_PARAM( MOTIONBLURVIEWPORTINTERNAL, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0]", "Internal motion blur value set by proxy" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + if ( params[BASETEXTURE]->IsDefined() ) + { + LoadTexture( BASETEXTURE ); + } + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 1, 0, 0 ); + + // NOTE: sRGB is disabled because of the NV8800 brokenness + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, false ); + pShaderShadow->EnableSRGBWrite( false ); + + DECLARE_STATIC_VERTEX_SHADER( motion_blur_vs20 ); + SET_STATIC_VERTEX_SHADER( motion_blur_vs20 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( motion_blur_ps20b ); + SET_STATIC_PIXEL_SHADER( motion_blur_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( motion_blur_ps20 ); + SET_STATIC_PIXEL_SHADER( motion_blur_ps20 ); + } + + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableAlphaWrites( false ); + } + + DYNAMIC_STATE + { + DECLARE_DYNAMIC_VERTEX_SHADER( motion_blur_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( motion_blur_vs20 ); + + // Bind textures + BindTexture( SHADER_SAMPLER0, BASETEXTURE ); + + // Get texture dimensions + ITexture *src_texture = params[BASETEXTURE]->GetTextureValue(); + //int flTextureWidth = src_texture->GetActualWidth(); + int flTextureHeight = src_texture->GetActualHeight(); + + // Percent of screen clamp + float vConst[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vConst[0] = mat_motion_blur_percent_of_screen_max.GetFloat() / 100.0f; + const float *pBlurViewportInternal = params[MOTIONBLURVIEWPORTINTERNAL]->GetVecValue(); + if ( ( pBlurViewportInternal[0] > 0.0f ) || ( pBlurViewportInternal[1] > 0.0f ) || ( pBlurViewportInternal[2] < 1.0f ) || ( pBlurViewportInternal[3] < 1.0f ) ) + { + vConst[0] *= 0.25f; // Reduce the max if we're not rendering full screen (hack to dumb down motion blur in split screen) + } + pShaderAPI->SetPixelShaderConstant( 0, vConst, 1 ); + + // Set values from material proxy + pShaderAPI->SetPixelShaderConstant( 1, params[MOTIONBLURINTERNAL]->GetVecValue(), 1 ); + pShaderAPI->SetPixelShaderConstant( 2, params[MOTIONBLURVIEWPORTINTERNAL]->GetVecValue(), 1 ); + + float flApproximateBlurLength = fabs( params[MOTIONBLURINTERNAL]->GetVecValue()[0] ) + fabs( params[MOTIONBLURINTERNAL]->GetVecValue()[1] ) + + fabs( params[MOTIONBLURINTERNAL]->GetVecValue()[2] ) + fabs( params[MOTIONBLURINTERNAL]->GetVecValue()[3] ); + + // Quality based on screen resolution height + int nNumBlurSamples = 6; + if ( flTextureHeight >= 1080 ) // 1080p and higher + nNumBlurSamples = 14; + else if ( flTextureHeight >= 720 ) // 720p to 1080p + nNumBlurSamples = 10; + else // Lower resolution than 720p + nNumBlurSamples = 6; + + // If we are blurring less than half the allowed blur max, use fewer samples + float flPercentMaxBlur = clamp( 2.0f * flApproximateBlurLength / MIN( mat_motion_blur_percent_of_screen_max.GetFloat() / 100.0f, 4.0f ), 0.0f, 1.0f ); + nNumBlurSamples = ( int )( ( float )nNumBlurSamples * flPercentMaxBlur ); + if ( nNumBlurSamples < 1 ) + nNumBlurSamples = 1; + + if ( flApproximateBlurLength == 0.0f ) + { + // No motion blur this frame, so force 0 blur samples. This will cause the shader to do a single unblurred fetch. + nNumBlurSamples = 0; + } + + nNumBlurSamples = clamp( nNumBlurSamples, 0, 14 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( motion_blur_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( D_NUM_BLUR_SAMPLES, nNumBlurSamples ); + SET_DYNAMIC_PIXEL_SHADER( motion_blur_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( motion_blur_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( D_NUM_BLUR_SAMPLES, nNumBlurSamples ); + SET_DYNAMIC_PIXEL_SHADER( motion_blur_ps20 ); + } + } + + Draw(); + } +END_SHADER diff --git a/materialsystem/stdshaders/motion_blur_ps2x.fxc b/materialsystem/stdshaders/motion_blur_ps2x.fxc new file mode 100644 index 00000000..06e42e02 --- /dev/null +++ b/materialsystem/stdshaders/motion_blur_ps2x.fxc @@ -0,0 +1,88 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// DYNAMIC: "D_NUM_BLUR_SAMPLES" "0..14" + +#ifdef HDRTYPE + #undef HDRTYPE +#endif +#define HDRTYPE HDR_TYPE_NONE + +// Includes ======================================================================================= +#include "common_ps_fxc.h" + +// Texture Samplers =============================================================================== +sampler g_tTexSampler : register( s0 ); + +// Shaders Constants and Globals ================================================================== +float g_flMaxMotionBlur : register( c0 ); +float4 g_vConst5 : register( c1 ); +#define g_vGlobalBlurVector g_vConst5.xy +#define g_flFallingMotionIntensity g_vConst5.z +#define g_flRollBlurIntensity g_vConst5.w + +float4 g_vViewport : register( c2 ); + +// Interpolated values ============================================================================ +struct PS_INPUT +{ + float2 vUv0 : TEXCOORD0; +}; + +// Main =========================================================================================== +float4 main( PS_INPUT i ) : COLOR +{ + // Calculate blur vector + float2 vFallingMotionBlurVector = ( ( i.vUv0.xy * 2.0f ) - 1.0f ); + float2 vRollBlurVector = cross( float3( vFallingMotionBlurVector.xy, 0.0f ), float3( 0.0f, 0.0f, 1.0f ) ).xy; + float2 vGlobalBlurVector = g_vGlobalBlurVector; + vGlobalBlurVector.y = -vGlobalBlurVector.y; + //vGlobalBlurVector.xy = float2( 1.0f, 0.0f ); // For debugging + + float flFallingMotionBlurIntensity = -abs( g_flFallingMotionIntensity ); // Keep samples on screen by keeping vector pointing in + //flFallingMotionBlurIntensity = step( 10, abs(g_flFallingMotionIntensity) ); // For finding the sweet spot in debug mode + vFallingMotionBlurVector.xy *= dot( vFallingMotionBlurVector.xy, vFallingMotionBlurVector.xy ); // Dampen the effect in the middle of the screen + vFallingMotionBlurVector.xy *= flFallingMotionBlurIntensity; + + float flRollBlurIntensity = g_flRollBlurIntensity; + vRollBlurVector.xy *= flRollBlurIntensity; + + float2 vFinalBlurVector = vGlobalBlurVector.xy + vFallingMotionBlurVector.xy + vRollBlurVector.xy; + #if defined( _X360 ) // Disable falling blur on the 360 for perf + vFinalBlurVector.xy = vGlobalBlurVector.xy + vRollBlurVector.xy; + #endif + + // Clamp blur vector to max length + if ( length( vFinalBlurVector.xy ) > g_flMaxMotionBlur ) + { + vFinalBlurVector.xy = normalize( vFinalBlurVector.xy ) * g_flMaxMotionBlur; + } + + // Clamp fetches to viewport + float2 vBlurVectorClamped = i.vUv0.xy + vFinalBlurVector.xy; + vBlurVectorClamped.xy = clamp( vBlurVectorClamped.xy, g_vViewport.xy, g_vViewport.wz ) - i.vUv0.xy; + + // Set number of samples + int nNumSamples = D_NUM_BLUR_SAMPLES + 1; // Make sure we always fetch 1 texel! + + // Step size + float2 vUvOffset = { 0.0f, 0.0f }; + #if ( D_NUM_BLUR_SAMPLES > 0 ) + vUvOffset.xy = vBlurVectorClamped.xy / ( nNumSamples - 1 ); + #endif + + float4 cColor = { 0.0f, 0.0f, 0.0f, 0.0f }; + #if defined( _X360 ) + [unroll] + #endif + for ( int x = 0; x <= D_NUM_BLUR_SAMPLES; x++ ) + { + // Calculate uv + float2 vUvTmp = i.vUv0.xy + ( vUvOffset.xy * x ); + + // Sample pixel + //cColor += kernel[x] * tex2D( g_tTexSampler, vUvTmp ); // Use kernal from above + cColor += ( 1.0f / nNumSamples ) * tex2D( g_tTexSampler, vUvTmp.xy ); // Evenly weight all samples + } + + return float4( cColor.rgb, 1.0f ); +} diff --git a/materialsystem/stdshaders/motion_blur_vs20.fxc b/materialsystem/stdshaders/motion_blur_vs20.fxc new file mode 100644 index 00000000..b8a86977 --- /dev/null +++ b/materialsystem/stdshaders/motion_blur_vs20.fxc @@ -0,0 +1,29 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// Includes ======================================================================================= +#include "common_vs_fxc.h" + +// Input values =================================================================================== +struct VS_INPUT +{ + float3 vPos : POSITION; + float2 vBaseTexCoord : TEXCOORD0; +}; + +// Interpolated values ============================================================================ +struct VS_OUTPUT +{ + float4 projPos : POSITION; + float2 vUv0 : TEXCOORD0; +}; + +// Main =========================================================================================== +VS_OUTPUT main( const VS_INPUT i ) +{ + VS_OUTPUT o; + + o.projPos.xyzw = float4( i.vPos.xyz, 1.0f ); + o.vUv0.xy = i.vBaseTexCoord.xy; + + return o; +} diff --git a/materialsystem/stdshaders/multiblend.cpp b/materialsystem/stdshaders/multiblend.cpp new file mode 100644 index 00000000..c34bd007 --- /dev/null +++ b/materialsystem/stdshaders/multiblend.cpp @@ -0,0 +1,89 @@ +//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============// +// +// Purpose: Multiblending shader for Spy in TF2 (and probably many other things to come) +// +// $NoKeywords: $ +//=====================================================================================// + +#include "BaseVSShader.h" +#include "convar.h" +#include "multiblend_dx9_helper.h" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +DEFINE_FALLBACK_SHADER( Multiblend, Multiblend_DX90 ) + +BEGIN_VS_SHADER( Multiblend_DX90, "Help for Multiblend" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( SPECTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "" ) + SHADER_PARAM( BASETEXTURE2, SHADER_PARAM_TYPE_TEXTURE, "", "" ) + SHADER_PARAM( SPECTEXTURE2, SHADER_PARAM_TYPE_TEXTURE, "", "" ) + SHADER_PARAM( BASETEXTURE3, SHADER_PARAM_TYPE_TEXTURE, "", "" ) + SHADER_PARAM( SPECTEXTURE3, SHADER_PARAM_TYPE_TEXTURE, "", "" ) + SHADER_PARAM( BASETEXTURE4, SHADER_PARAM_TYPE_TEXTURE, "", "" ) + SHADER_PARAM( SPECTEXTURE4, SHADER_PARAM_TYPE_TEXTURE, "", "" ) + SHADER_PARAM( FOW, SHADER_PARAM_TYPE_TEXTURE, "", "FoW Render Target" ) + SHADER_PARAM( ROTATION, SHADER_PARAM_TYPE_FLOAT, "0.0", "" ) + SHADER_PARAM( SCALE, SHADER_PARAM_TYPE_FLOAT, "1.0", "" ) + SHADER_PARAM( ROTATION2, SHADER_PARAM_TYPE_FLOAT, "0.0", "" ) + SHADER_PARAM( SCALE2, SHADER_PARAM_TYPE_FLOAT, "1.0", "" ) + SHADER_PARAM( ROTATION3, SHADER_PARAM_TYPE_FLOAT, "0.0", "" ) + SHADER_PARAM( SCALE3, SHADER_PARAM_TYPE_FLOAT, "1.0", "" ) + SHADER_PARAM( ROTATION4, SHADER_PARAM_TYPE_FLOAT, "0.0", "" ) + SHADER_PARAM( SCALE4, SHADER_PARAM_TYPE_FLOAT, "1.0", "" ) + END_SHADER_PARAMS + + void SetupVars( Multiblend_DX9_Vars_t& info ) + { + info.m_nBaseTextureTransform = BASETEXTURETRANSFORM; + info.m_nBaseTexture = BASETEXTURE; + info.m_nSpecTexture = SPECTEXTURE; + info.m_nBaseTexture2 = BASETEXTURE2; + info.m_nSpecTexture2 = SPECTEXTURE2; + info.m_nBaseTexture3 = BASETEXTURE3; + info.m_nSpecTexture3 = SPECTEXTURE3; + info.m_nBaseTexture4 = BASETEXTURE4; + info.m_nSpecTexture4 = SPECTEXTURE4; + info.m_nFoW = FOW; + info.m_nRotation = ROTATION; + info.m_nRotation2 = ROTATION2; + info.m_nRotation3 = ROTATION3; + info.m_nRotation4 = ROTATION4; + info.m_nScale = SCALE; + info.m_nScale2 = SCALE2; + info.m_nScale3 = SCALE3; + info.m_nScale4 = SCALE4; + info.m_nFlashlightTexture = FLASHLIGHTTEXTURE; + info.m_nFlashlightTextureFrame = FLASHLIGHTTEXTUREFRAME; + } + + SHADER_INIT_PARAMS() + { + Multiblend_DX9_Vars_t info; + SetupVars( info ); + InitParamsMultiblend_DX9( this, params, pMaterialName, info ); + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + Multiblend_DX9_Vars_t info; + SetupVars( info ); + InitMultiblend_DX9( this, params, info ); + } + + SHADER_DRAW + { + Multiblend_DX9_Vars_t info; + SetupVars( info ); + DrawMultiblend_DX9( this, params, pShaderAPI, pShaderShadow, info, vertexCompression, pContextDataPtr ); + } +END_SHADER + diff --git a/materialsystem/stdshaders/multiblend_dx9_helper.cpp b/materialsystem/stdshaders/multiblend_dx9_helper.cpp new file mode 100644 index 00000000..65a51f86 --- /dev/null +++ b/materialsystem/stdshaders/multiblend_dx9_helper.cpp @@ -0,0 +1,491 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" +#include "shaderlib/commandbuilder.h" +#include "multiblend_dx9_helper.h" +#include "..\shaderapidx9\locald3dtypes.h" +#include "convar.h" +#include "cpp_shader_constant_register_map.h" +#include "multiblend_vs20.inc" +#include "multiblend_vs30.inc" +#include "multiblend_ps20.inc" +#include "multiblend_ps20b.inc" +#include "multiblend_ps30.inc" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +// FIXME: doesn't support fresnel! +void InitParamsMultiblend_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, Multiblend_DX9_Vars_t &info ) +{ + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + + params[FLASHLIGHTTEXTURE]->SetStringValue( GetFlashlightTextureFilename() ); +} + +void InitMultiblend_DX9( CBaseVSShader *pShader, IMaterialVar** params, Multiblend_DX9_Vars_t &info ) +{ + if ( params[ info.m_nBaseTexture ]->IsDefined() ) + { + pShader->LoadTexture( info.m_nBaseTexture ); + } + + if ( info.m_nSpecTexture != -1 && params[ info.m_nSpecTexture ]->IsDefined() ) + { + pShader->LoadTexture( info.m_nSpecTexture ); + } + + if ( info.m_nBaseTexture2 != -1 && params[ info.m_nBaseTexture2 ]->IsDefined() ) + { + pShader->LoadTexture( info.m_nBaseTexture2 ); + } + + if ( info.m_nSpecTexture2 != -1 && params[ info.m_nSpecTexture2 ]->IsDefined() ) + { + pShader->LoadTexture( info.m_nSpecTexture2 ); + } + + if ( info.m_nBaseTexture3 != -1 && params[ info.m_nBaseTexture3 ]->IsDefined() ) + { + pShader->LoadTexture( info.m_nBaseTexture3 ); + } + + if ( info.m_nSpecTexture3 != -1 && params[ info.m_nSpecTexture3 ]->IsDefined() ) + { + pShader->LoadTexture( info.m_nSpecTexture3 ); + } + + if ( info.m_nBaseTexture4 != -1 && params[ info.m_nBaseTexture4 ]->IsDefined() ) + { + pShader->LoadTexture( info.m_nBaseTexture4 ); + } + + if ( info.m_nSpecTexture4 != -1 && params[ info.m_nSpecTexture4 ]->IsDefined() ) + { + pShader->LoadTexture( info.m_nSpecTexture4 ); + } + + if ( info.m_nFoW != -1 && params[ info.m_nFoW ]->IsDefined() ) + { + pShader->LoadTexture( info.m_nFoW ); + } +} + +class CMultiblend_DX9_Context : public CBasePerMaterialContextData +{ +public: + CCommandBufferBuilder< CFixedCommandStorageBuffer< 800 > > m_SemiStaticCmdsOut; +}; + +void DrawMultiblend_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, Multiblend_DX9_Vars_t &info, VertexCompressionType_t vertexCompression, + CBasePerMaterialContextData **pContextDataPtr ) +{ +// CMultiblend_DX9_Context *pContextData = reinterpret_cast< CMultiblend_DX9_Context * > ( *pContextDataPtr ); + + bool bIsModel = IS_FLAG_SET( MATERIAL_VAR_MODEL ); + bool bHasFoW = ( ( info.m_nFoW != -1 ) && ( params[ info.m_nFoW ]->IsTexture() != 0 ) ); + if ( bHasFoW == true ) + { + ITexture *pTexture = params[ info.m_nFoW ]->GetTextureValue(); + if ( ( pTexture->GetFlags() & TEXTUREFLAGS_RENDERTARGET ) == 0 ) + { + bHasFoW = false; + } + } + int nLightingPreviewMode = IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER0 ) + 2 * IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER1 ); + bool bHasSpec1 = ( info.m_nSpecTexture != -1 && params[ info.m_nSpecTexture ]->IsDefined() ); + bool bHasSpec2 = ( info.m_nSpecTexture2 != -1 && params[ info.m_nSpecTexture2 ]->IsDefined() ); + bool bHasSpec3 = ( info.m_nSpecTexture3 != -1 && params[ info.m_nSpecTexture3 ]->IsDefined() ); + bool bHasSpec4 = ( info.m_nSpecTexture4 != -1 && params[ info.m_nSpecTexture4 ]->IsDefined() ); + bool bUsingEditor = pShader->CanUseEditorMaterials(); // pShader->UsingEditor( params ); +// bool bSinglePassFlashlight = true; + bool bHasFlashlight = pShader->UsingFlashlight( params ); + +#if 0 + if ( pShader->IsSnapshotting() || ( !pContextData ) || ( pContextData->m_bMaterialVarsChanged ) ) + { + if ( !pContextData ) // make sure allocated + { + pContextData = new CMultiblend_DX9_Context; + *pContextDataPtr = pContextData; + } + + // need to regenerate the semistatic cmds + pContextData->m_SemiStaticCmdsOut.Reset(); + if ( bHasFlashlight ) + { + pContextData->m_SemiStaticCmdsOut.SetVertexShaderFlashlightState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6 ); + + CBCmdSetPixelShaderFlashlightState_t state; + state.m_LightSampler = SHADER_SAMPLER13; + state.m_DepthSampler = SHADER_SAMPLER14; + state.m_ShadowNoiseSampler = SHADER_SAMPLER15; + state.m_nColorConstant = 28; + state.m_nAttenConstant = 13; + state.m_nOriginConstant = 14; + state.m_nDepthTweakConstant = 19; + state.m_nScreenScaleConstant = 31; + state.m_nWorldToTextureConstant = -1; + state.m_bFlashlightNoLambert = false; + state.m_bSinglePassFlashlight = bSinglePassFlashlight; + pContextData->m_SemiStaticCmdsOut.SetPixelShaderFlashlightState( state ); + } + + pContextData->m_SemiStaticCmdsOut.End(); + } +#endif + + SHADOW_STATE + { + pShader->SetInitialShadowState( ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER7, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER8, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER9, true ); + + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); // Always SRGB read on base map 1 + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, true ); // Always SRGB read on base map 2 + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER3, true ); // Always SRGB read on base map 3 + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER4, true ); // Always SRGB read on base map 4 + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER6, true ); // Always SRGB read on spec map 1 + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER7, true ); // Always SRGB read on spec map 1 + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER8, true ); // Always SRGB read on spec map 1 + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER9, true ); // Always SRGB read on spec map 1 + + if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ) + { + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER5, true ); + } + else + { + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER5, false ); + } + if ( bHasFoW ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER10, true ); + } + + if( bHasFlashlight ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER13, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER14, true ); + pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER14 ); + pShaderShadow->EnableTexture( SHADER_SAMPLER15, true ); + } + + pShaderShadow->EnableSRGBWrite( true ); + pShaderShadow->EnableAlphaWrites( true ); // writing water fog alpha always. + + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL; + int nTexCoordCount = 8; + static int s_TexCoordSize[]={ 2, // + 2, // + 0, // + 4, // alpha blend + 4, // vertex / blend color 0 + 4, // vertex / blend color 1 + 4, // vertex / blend color 2 + 4 // vertex / blend color 3 + }; + + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, s_TexCoordSize, 0 ); + int nShadowFilterMode = g_pHardwareConfig->GetShadowFilterMode(); + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_STATIC_VERTEX_SHADER( multiblend_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( SPECULAR, !bUsingEditor ); + SET_STATIC_VERTEX_SHADER_COMBO( FOW, bHasFoW ); + SET_STATIC_VERTEX_SHADER_COMBO( MODEL, bIsModel ); + SET_STATIC_VERTEX_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); + SET_STATIC_VERTEX_SHADER( multiblend_vs20 ); + + // Bind ps_2_b shader so we can get Phong terms + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( multiblend_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( LIGHTING_PREVIEW, nLightingPreviewMode ); + SET_STATIC_PIXEL_SHADER_COMBO( FOW, bHasFoW ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER( multiblend_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( multiblend_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( LIGHTING_PREVIEW, nLightingPreviewMode ); + SET_STATIC_PIXEL_SHADER_COMBO( FOW, bHasFoW ); +// SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); + SET_STATIC_PIXEL_SHADER( multiblend_ps20 ); + } + } +#ifndef _X360 + else + { + // The vertex shader uses the vertex id stream + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + + DECLARE_STATIC_VERTEX_SHADER( multiblend_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( SPECULAR, !bUsingEditor ); + SET_STATIC_VERTEX_SHADER_COMBO( FOW, bHasFoW ); + SET_STATIC_VERTEX_SHADER_COMBO( MODEL, bIsModel ); + SET_STATIC_VERTEX_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); + SET_STATIC_VERTEX_SHADER( multiblend_vs30 ); + + // Bind ps_2_b shader so we can get Phong terms + DECLARE_STATIC_PIXEL_SHADER( multiblend_ps30 ); + SET_STATIC_PIXEL_SHADER_COMBO( LIGHTING_PREVIEW, nLightingPreviewMode ); + SET_STATIC_PIXEL_SHADER_COMBO( FOW, bHasFoW ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER( multiblend_ps30 ); + } +#endif + + pShader->DefaultFog(); + + float flLScale = pShaderShadow->GetLightMapScaleFactor(); + + // Lighting constants + pShader->PI_BeginCommandBuffer(); + pShader->PI_SetPixelShaderAmbientLightCube( PSREG_AMBIENT_CUBE ); +// pShader->PI_SetPixelShaderLocalLighting( PSREG_LIGHT_INFO_ARRAY ); + pShader->PI_SetModulationPixelShaderDynamicState_LinearScale_ScaleInW( PSREG_CONSTANT_43, flLScale ); + pShader->PI_EndCommandBuffer(); + } + DYNAMIC_STATE + { + pShaderAPI->SetDefaultState(); + + // Bind textures + pShader->BindTexture( SHADER_SAMPLER1, info.m_nBaseTexture ); // Base Map 1 + pShader->BindTexture( SHADER_SAMPLER2, info.m_nBaseTexture2 ); // Base Map 2 + pShader->BindTexture( SHADER_SAMPLER3, info.m_nBaseTexture3 ); // Base Map 3 + pShader->BindTexture( SHADER_SAMPLER4, info.m_nBaseTexture4 ); // Base Map 4 + if ( bHasSpec1 == true ) + { + pShader->BindTexture( SHADER_SAMPLER6, info.m_nSpecTexture ); // Spec Map 1 + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER6, TEXTURE_BLACK ); + } + if ( bHasSpec2 == true ) + { + pShader->BindTexture( SHADER_SAMPLER7, info.m_nSpecTexture2 ); // Spec Map 2 + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER7, TEXTURE_BLACK ); + } + if ( bHasSpec3 == true ) + { + pShader->BindTexture( SHADER_SAMPLER8, info.m_nSpecTexture3 ); // Spec Map 3 + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER8, TEXTURE_BLACK ); + } + if ( bHasSpec4 == true ) + { + pShader->BindTexture( SHADER_SAMPLER9, info.m_nSpecTexture4 ); // Spec Map 4 + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER9, TEXTURE_BLACK ); + } + + pShaderAPI->BindStandardTexture( SHADER_SAMPLER5, TEXTURE_LIGHTMAP ); + + +#if 1 + if( bHasFlashlight ) + { + VMatrix worldToTexture; + ITexture *pFlashlightDepthTexture; + FlashlightState_t state = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture ); + + pShader->BindTexture( SHADER_SAMPLER13, state.m_pSpotlightTexture, state.m_nSpotlightTextureFrame ); + + //bFlashlightShadows = state.m_bEnableShadows; + + SetFlashLightColorFromState( state, pShaderAPI, PSREG_FLASHLIGHT_COLOR ); + + if( pFlashlightDepthTexture && g_pConfig->ShadowDepthTexture() && state.m_bEnableShadows ) + { + pShader->BindTexture( SHADER_SAMPLER14, pFlashlightDepthTexture ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER15, TEXTURE_SHADOW_NOISE_2D ); + } + + float atten[4], pos[4], tweaks[4]; + + atten[0] = state.m_fConstantAtten; // Set the flashlight attenuation factors + atten[1] = state.m_fLinearAtten; + atten[2] = state.m_fQuadraticAtten; + atten[3] = state.m_FarZAtten; + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_ATTENUATION, atten, 1 ); + + pos[0] = state.m_vecLightOrigin[0]; // Set the flashlight origin + pos[1] = state.m_vecLightOrigin[1]; + pos[2] = state.m_vecLightOrigin[2]; + pos[3] = state.m_FarZ; + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_POSITION_RIM_BOOST, pos, 1 ); // steps on rim boost + + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, worldToTexture.Base(), 4 ); + + // Tweaks associated with a given flashlight + tweaks[0] = ShadowFilterFromState( state ); + tweaks[1] = ShadowAttenFromState( state ); + pShader->HashShadow2DJitter( state.m_flShadowJitterSeed, &tweaks[2], &tweaks[3] ); + pShaderAPI->SetPixelShaderConstant( PSREG_ENVMAP_TINT__SHADOW_TWEAKS, tweaks, 1 ); + + // Dimensions of screen, used for screen-space noise map sampling + float vScreenScale[4] = {1280.0f / 32.0f, 720.0f / 32.0f, 0, 0}; + int nWidth, nHeight; + pShaderAPI->GetBackBufferDimensions( nWidth, nHeight ); + + int nTexWidth, nTexHeight; + pShaderAPI->GetStandardTextureDimensions( &nTexWidth, &nTexHeight, TEXTURE_SHADOW_NOISE_2D ); + + vScreenScale[0] = (float) nWidth / nTexWidth; + vScreenScale[1] = (float) nHeight / nTexHeight; + + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_SCREEN_SCALE, vScreenScale, 1 ); + + if ( IsX360() ) + { + pShaderAPI->SetBooleanPixelShaderConstant( 0, &state.m_nShadowQuality, 1 ); + } + + QAngle angles; + QuaternionAngles( state.m_quatOrientation, angles ); + +#if 0 + // World to Light's View matrix + matrix3x4_t viewMatrix, viewMatrixInverse; + AngleMatrix( angles, state.m_vecLightOrigin, viewMatrixInverse ); + MatrixInvert( viewMatrixInverse, viewMatrix ); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, worldToTexture.Base(), 4 ); +#endif + } +#endif + + if ( bHasFoW ) + { + pShader->BindTexture( SHADER_SAMPLER10, info.m_nFoW, -1 ); + + float vFoWSize[ 4 ]; + Vector vMins = pShaderAPI->GetVectorRenderingParameter( VECTOR_RENDERPARM_GLOBAL_FOW_MINS ); + Vector vMaxs = pShaderAPI->GetVectorRenderingParameter( VECTOR_RENDERPARM_GLOBAL_FOW_MAXS ); + vFoWSize[ 0 ] = vMins.x; + vFoWSize[ 1 ] = vMins.y; + vFoWSize[ 2 ] = vMaxs.x - vMins.x; + vFoWSize[ 3 ] = vMaxs.y - vMins.y; + pShaderAPI->SetVertexShaderConstant( 26, vFoWSize ); + } + + Vector4D vRotations( DEG2RAD( params[ info.m_nRotation ]->GetFloatValue() ), DEG2RAD( params[ info.m_nRotation2 ]->GetFloatValue() ), + DEG2RAD( params[ info.m_nRotation3 ]->GetFloatValue() ), DEG2RAD( params[ info.m_nRotation4 ]->GetFloatValue() ) ); + pShaderAPI->SetVertexShaderConstant( 27, vRotations.Base() ); + + Vector4D vScales( params[ info.m_nScale ]->GetFloatValue() > 0.0f ? params[ info.m_nScale ]->GetFloatValue() : 1.0f, + params[ info.m_nScale2 ]->GetFloatValue() > 0.0f ? params[ info.m_nScale2 ]->GetFloatValue() : 1.0f, + params[ info.m_nScale3 ]->GetFloatValue() > 0.0f ? params[ info.m_nScale3 ]->GetFloatValue() : 1.0f, + params[ info.m_nScale4 ]->GetFloatValue() > 0.0f ? params[ info.m_nScale4 ]->GetFloatValue() : 1.0f ); + pShaderAPI->SetVertexShaderConstant( 28, vScales.Base() ); + + Vector4D vLightDir; + vLightDir.AsVector3D() = pShaderAPI->GetVectorRenderingParameter( VECTOR_RENDERPARM_GLOBAL_LIGHT_DIRECTION ); + vLightDir.w = pShaderAPI->GetFloatRenderingParameter( FLOAT_RENDERPARM_SPECULAR_POWER ); + pShaderAPI->SetVertexShaderConstant( 29, vLightDir.Base() ); + + + LightState_t lightState; + pShaderAPI->GetDX9LightState( &lightState ); + + bool bFlashlightShadows = false; + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_DYNAMIC_VERTEX_SHADER( multiblend_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER( multiblend_vs20 ); + + // Bind ps_2_b shader so we can get Phong, rim and a cloudier refraction + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( multiblend_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER( multiblend_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( multiblend_ps20 ); +// SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER( multiblend_ps20 ); + } + } +#ifndef _X360 + else + { + DECLARE_DYNAMIC_VERTEX_SHADER( multiblend_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER( multiblend_vs30 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( multiblend_ps30 ); + SET_DYNAMIC_PIXEL_SHADER( multiblend_ps30 ); + } +#endif + + pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, info.m_nBaseTextureTransform ); + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + // Pack phong exponent in with the eye position + float vEyePos_SpecExponent[4]; + float vSpecularTint[4] = {1, 1, 1, 1}; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + +// if ( (info.m_nPhongExponent != -1) && params[info.m_nPhongExponent]->IsDefined() ) +// vEyePos_SpecExponent[3] = params[info.m_nPhongExponent]->GetFloatValue(); // This overrides the channel in the map +// else + vEyePos_SpecExponent[3] = 0; // Use the alpha channel of the normal map for the exponent + + // If it's all zeros, there was no constant tint in the vmt + if ( (vSpecularTint[0] == 0.0f) && (vSpecularTint[1] == 0.0f) && (vSpecularTint[2] == 0.0f) ) + { + vSpecularTint[0] = 1.0f; + vSpecularTint[1] = 1.0f; + vSpecularTint[2] = 1.0f; + } + + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + + // Set c0 and c1 to contain first two rows of ViewProj matrix + VMatrix matView, matProj, matViewProj; + pShaderAPI->GetMatrix( MATERIAL_VIEW, matView.m[0] ); + pShaderAPI->GetMatrix( MATERIAL_PROJECTION, matProj.m[0] ); + matViewProj = matView * matProj; + pShaderAPI->SetPixelShaderConstant( 0, matViewProj.m[0], 2 ); + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + } + pShader->Draw(); +} diff --git a/materialsystem/stdshaders/multiblend_dx9_helper.h b/materialsystem/stdshaders/multiblend_dx9_helper.h new file mode 100644 index 00000000..e5c42929 --- /dev/null +++ b/materialsystem/stdshaders/multiblend_dx9_helper.h @@ -0,0 +1,59 @@ +//====== Copyright © 1996-2006, Valve Corporation, All rights reserved. ======= +// +// Purpose: +// +//============================================================================= + +#ifndef MULTIBLEND_DX9_HELPER_H +#define MULTIBLEND_DX9_HELPER_H +#ifdef _WIN32 +#pragma once +#endif + +#include + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct Multiblend_DX9_Vars_t +{ + Multiblend_DX9_Vars_t() { memset( this, 0xFF, sizeof( *this ) ); } + + int m_nBaseTextureTransform; + int m_nBaseTexture; + int m_nSpecTexture; + int m_nBaseTexture2; + int m_nSpecTexture2; + int m_nBaseTexture3; + int m_nSpecTexture3; + int m_nBaseTexture4; + int m_nSpecTexture4; + int m_nFoW; + int m_nRotation; + int m_nRotation2; + int m_nRotation3; + int m_nRotation4; + int m_nScale; + int m_nScale2; + int m_nScale3; + int m_nScale4; + int m_nFlashlightTexture; + int m_nFlashlightTextureFrame; +}; + +void InitParamsMultiblend_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, + Multiblend_DX9_Vars_t &info ); +void InitMultiblend_DX9( CBaseVSShader *pShader, IMaterialVar** params, Multiblend_DX9_Vars_t &info ); +void DrawMultiblend_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, Multiblend_DX9_Vars_t &info, VertexCompressionType_t vertexCompression, + CBasePerMaterialContextData **pContextDataPtr ); + +#endif // MULTIBLEND_DX9_HELPER_H diff --git a/materialsystem/stdshaders/multiblend_ps2x.fxc b/materialsystem/stdshaders/multiblend_ps2x.fxc new file mode 100644 index 00000000..b88b7670 --- /dev/null +++ b/materialsystem/stdshaders/multiblend_ps2x.fxc @@ -0,0 +1,237 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "LIGHTING_PREVIEW" "0..1" [PC] +// STATIC: "LIGHTING_PREVIEW" "0..0" [XBOX] +// STATIC: "FOW" "0..1" +// STATIC: "FLASHLIGHT" "0..1" [ps20b] +// STATIC: "FLASHLIGHT" "0..1" [ps30] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps20b] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps30] [PC] + +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps20b] + +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 ) + +#include "shader_constant_register_map.h" +#include "common_fog_ps_fxc.h" +#include "fow_ps_fxc.h" +#include "common_flashlight_fxc.h" + +sampler BaseSampler1 : register( s1 ); // Base map 1 +sampler BaseSampler2 : register( s2 ); // Base map 2 +sampler BaseSampler3 : register( s3 ); // Base map 3 +sampler BaseSampler4 : register( s4 ); // Base map 4 +sampler LightmapSampler : register( s5 ); + +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT ); + +#if ((defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0))) + +static const float3 cSpecularColor = float3( 1.0, 1.0, 1.0 ); + +#endif + +#if LIGHTING_PREVIEW == 0 + +static const float3 g_cAmbientColor = float3( 0.0, 0.0, 0.0 ); +const float4 g_TintValuesTimesLightmapScale : register( PSREG_CONSTANT_43 ); + +#endif + + +#if ( FOW == 1 ) + +sampler FoWSampler : register( s10 ); // Fog of War + +#endif + + +#if ( FLASHLIGHT == 1 ) + +const float4 g_FlashlightAttenuationFactors : register( c13 ); +const float3 g_FlashlightPos : register( c14 ); +const float4 g_ShadowTweaks : register( c2 ); + +sampler FlashlightSampler : register( s13 ); +sampler ShadowDepthSampler : register( s14 ); +sampler RandRotSampler : register( s15 ); + +#endif + + +// free floats: texcoord2 ( 4 xyzw ), texcoord7( 1 w ), vBaseTexCoord( 2 zw ) ( when we remove lightmaps ) +struct PS_INPUT +{ + float4 vProjPos : POSITION; + float4 vBaseTexCoord : TEXCOORD0; // xy = blend 1 coord, zw = lightmap cord + float4 worldPos_projPosZ : TEXCOORD1; +#if ( FLASHLIGHT == 1 ) + float4 vFlashlightSpacePos : TEXCOORD2; +#endif + float4 vFowCoord : TEXCOORD3; // xy = fow, zw = blend4 coord + float4 vAlphaBlend : TEXCOORD4; // xyz = alpha blend of 1, 2, 3. w = flSpecPower + float4 vBlendCoords23 : TEXCOORD5; // xy = blend2 coord, zw = blend3 coord + float4 vColorBlend1 : COLOR0; + float4 vColorBlend2 : COLOR1; + float4 vColorBlend3 : TEXCOORD6; + float3 vColorBlend4 : TEXCOORD7; +}; + + +#if ( defined( SHADER_MODEL_PS_2_0 ) ) + +float ComputeMultiBlendFactor( const float BlendEnd, const float BlendAmount, inout float Remaining ) +{ + float Result = 0.0; + + Result = smoothstep( 0.0, BlendEnd, BlendAmount ); + Result = clamp( Result, 0.0, Remaining ); + Remaining -= Result; + + return Result; +} + +#else + +sampler SpecSampler1 : register( s6 ); // Spec map 1 +sampler SpecSampler2 : register( s7 ); // Spec map 2 +sampler SpecSampler3 : register( s8 ); // Spec map 3 +sampler SpecSampler4 : register( s9 ); // Spec map 4 + +float ComputeMultiBlendFactor( const float BlendStart, const float BlendEnd, const float BlendAmount, const float AlphaBlend, inout float Remaining ) +{ + float Result = 0.0; + + if ( Remaining > 0.0 && BlendAmount > 0.0 ) + { + float minb = max( 0.0, BlendEnd - BlendStart ); + float maxb = min( 1.0, BlendEnd + BlendStart ); + + if ( minb != maxb ) + { + Result = smoothstep( minb, maxb, BlendAmount ); + } + else if ( BlendAmount >= minb ) + { + Result = 1.0; + } + + if ( BlendEnd < AlphaBlend ) + { + float alpha = 2.0 - AlphaBlend - BlendEnd; + Result *= clamp( alpha, 0.0, 1.0 ); + } + } + + Result = clamp( Result, 0.0, Remaining ); + Remaining -= Result; + + return Result; +} + +#endif + + +float4 main( PS_INPUT i ) : COLOR +{ + float blendfactor1 = 0.0; + float blendfactor2 = 0.0; + float blendfactor3 = 0.0; + float blendfactor4 = 0.0; + float remaining = 1.0; + + float4 color1 = tex2D( BaseSampler1, i.vBaseTexCoord.xy ) * float4( i.vColorBlend1.rgb, 1.0 ); + float4 color2 = tex2D( BaseSampler2, i.vBlendCoords23.xy ) * float4( i.vColorBlend2.rgb, 1.0 ); + float4 color3 = tex2D( BaseSampler3, i.vBlendCoords23.zw ) * float4( i.vColorBlend3.rgb, 1.0 ); + float4 color4 = tex2D( BaseSampler4, i.vFowCoord.zw ) * float4( i.vColorBlend4.rgb, 1.0 ); + +#if ( defined( SHADER_MODEL_PS_2_0 ) ) + + blendfactor1 = ComputeMultiBlendFactor( color1.a, i.vColorBlend1.a, remaining ); + blendfactor2 = ComputeMultiBlendFactor( color2.a, i.vColorBlend2.a, remaining ); + blendfactor3 = ComputeMultiBlendFactor( color3.a, i.vColorBlend3.a, remaining ); +// blendfactor4 = ComputeMultiBlendFactor( color4.a, i.vColorBlend4.a, remaining ); + blendfactor4 = remaining; + +#else + + float4 spec1 = tex2D( SpecSampler1, i.vBaseTexCoord.xy ); + float4 spec2 = tex2D( SpecSampler2, i.vBlendCoords23.xy ); + float4 spec3 = tex2D( SpecSampler3, i.vBlendCoords23.zw ); + float4 spec4 = tex2D( SpecSampler4, i.vFowCoord.zw ); + + blendfactor1 = ComputeMultiBlendFactor( spec1.a, color1.a, i.vColorBlend1.a, i.vAlphaBlend.r, remaining ); + blendfactor2 = ComputeMultiBlendFactor( spec2.a, color2.a, i.vColorBlend2.a, i.vAlphaBlend.g, remaining ); + blendfactor3 = ComputeMultiBlendFactor( spec3.a, color3.a, i.vColorBlend3.a, i.vAlphaBlend.b, remaining ); +// blendfactor4 = ComputeMultiBlendFactor( spec4.a, color4.a, i.vColorBlend4.a, i.vAlphaBlend.a, remaining ); + blendfactor4 = remaining; + +#endif + + float3 vResult = ( color1.rgb * blendfactor1 ) + ( color2.rgb * blendfactor2 ) + ( color3.rgb * blendfactor3 ) + ( color4.rgb * blendfactor4 ); + +#if ( ( defined( SHADER_MODEL_PS_2_B ) || defined( SHADER_MODEL_PS_3_0 ) ) ) + + float3 fSpecular = i.vAlphaBlend.w * cSpecularColor; + float3 fSpecFinal = float3( 0.0, 0.0, 0.0 ); + if ( blendfactor1 > 0.0 ) + { + fSpecFinal += spec1.rgb * i.vColorBlend1.rgb * blendfactor1; + } + if ( blendfactor2 > 0.0 ) + { + fSpecFinal += spec2.rgb * i.vColorBlend2.rgb * blendfactor2; + } + if ( blendfactor3 > 0.0 ) + { + fSpecFinal += spec3.rgb * i.vColorBlend3.rgb * blendfactor3; + } + if ( blendfactor4 > 0.0 ) + { + fSpecFinal += spec4.rgb * i.vColorBlend4.rgb * blendfactor4; + } + + vResult.rgb += fSpecFinal * fSpecular; + +#endif + + +#if 0 +#if LIGHTING_PREVIEW == 0 + float3 lightmapColor = tex2D( LightmapSampler, i.vBaseTexCoord.zw ); + float3 diffuseLighting = lightmapColor * g_TintValuesTimesLightmapScale.rgb; + diffuseLighting += g_cAmbientColor; + + vResult.rgb *= diffuseLighting; +#endif +#endif + +#if ( FLASHLIGHT == 1 ) +#if ( FLASHLIGHTSHADOWS && (defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) ) ) + int nShadowSampleLevel = FLASHLIGHTDEPTHFILTERMODE; +#else + int nShadowSampleLevel = 0; +#endif + float3 worldSpaceNormal = float3( 0, 0, 1 ); + + bool bShadows = true; + bool bHasNormal = false; + float3 flashlightColor = DoFlashlight( g_FlashlightPos, i.worldPos_projPosZ.xyz, i.vFlashlightSpacePos, + worldSpaceNormal, g_FlashlightAttenuationFactors.xyz, + g_FlashlightAttenuationFactors.w, FlashlightSampler, ShadowDepthSampler, + RandRotSampler, nShadowSampleLevel, bShadows, false, i.vBaseTexCoord.zw, false, g_ShadowTweaks, bHasNormal ); + + vResult.rgb *= flashlightColor; +// vResult.rgb = tex2D( RandRotSampler, i.vBaseTexCoord.xy ).rgb; +#endif + + +#if ( FOW == 1 ) + vResult.rgb = CalcFoW( FoWSampler, i.vFowCoord.xy, vResult.rgb ); +#endif + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos_SpecExponent.xyz, i.worldPos_projPosZ.xyz, i.worldPos_projPosZ.w ); + + return FinalOutput( float4( vResult, fogFactor ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR ); +} diff --git a/materialsystem/stdshaders/multiblend_vs20.fxc b/materialsystem/stdshaders/multiblend_vs20.fxc new file mode 100644 index 00000000..5cdab613 --- /dev/null +++ b/materialsystem/stdshaders/multiblend_vs20.fxc @@ -0,0 +1,141 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// +// +// Purpose: +// +//===========================================================================// + +// STATIC: "MODEL" "0..1" + +#include "common_fog_vs_fxc.h" +// DYNAMIC: "SKINNING" "0..1" +// DYNAMIC: "MORPHING" "0..1" [vs30] [ = pShaderAPI->IsHWMorphingEnabled() ] +// STATIC: "SPECULAR" "0..1" +// STATIC: "FLASHLIGHT" "0..1" +// STATIC: "FOW" "0..1" + +#include "common_vs_fxc.h" +#include "fow_vs_fxc.h" + +static const bool g_bSkinning = SKINNING ? true : false; +static const int g_FogType = DOWATERFOG; + +const float4 cBaseTexCoordTransform[ 2 ] : register( SHADER_SPECIFIC_CONST_6 ); +const float4 g_vFoWWorldSize : register( c26 ); +const float4 g_vRotations : register( c27 ); +const float4 g_vScales : register( c28 ); +const float4 g_vLightDir : register( c29 ); // xyz = light dir, w = spec power + +#if ( FLASHLIGHT == 1 ) + +const float4x4 g_FlashlightWorldToTexture : register( SHADER_SPECIFIC_CONST_0 ); + +#endif + + +struct VS_INPUT +{ + float3 vPos : POSITION; + float4 vNormal : NORMAL; + float2 vBaseTexCoord : TEXCOORD0; + float2 vLightmapTexCoord : TEXCOORD1; +// float2 vLightmapTexCoordOffset : TEXCOORD2; + float4 vAlphaBlend : TEXCOORD3; + float4 vColorBlend1 : TEXCOORD4; + float4 vColorBlend2 : TEXCOORD5; + float4 vColorBlend3 : TEXCOORD6; + float4 vColorBlend4 : TEXCOORD7; +}; + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; + float4 vBaseTexCoord : TEXCOORD0; // xy = blend 1 coord, zw = lightmap cord + float4 worldPos_projPosZ : TEXCOORD1; +#if FLASHLIGHT + float4 vFlashlightSpacePos : TEXCOORD2; +#endif + float4 vFowCoord : TEXCOORD3; // xy = fow, zw = blend4 coord + float4 vAlphaBlend : TEXCOORD4; // xyz = alpha blend of 1, 2, 3. w = flSpecPower +// float3 worldVertToEyeVector : TEXCOORD5; + float4 vBlendCoords23 : TEXCOORD5; + float4 vColorBlend1 : COLOR0; + float4 vColorBlend2 : COLOR1; + float4 vColorBlend3 : TEXCOORD6; + float3 vColorBlend4 : TEXCOORD7; +}; + +float2 ComputeTexCoord( const float2 vBaseCoord, const float flRotation, const float flScale ) +{ + float2 vAdjust = vBaseCoord - float2( 0.5, 0.5 ); + float2 vResult; + float c = cos( flRotation ); + float s = sin( flRotation ); + + vResult.x = ( vAdjust.x * c ) + ( vAdjust.y * -s ); + vResult.y = ( vAdjust.x * s ) + ( vAdjust.y * c ); + + return ( vResult / flScale ) + float2( 0.5, 0.5 ); +} + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o; + + float3 vObjNormal; + DecompressVertex_Normal( v.vNormal, vObjNormal ); + + float4 vProjPos; + float3 vWorldPos; + + vProjPos = mul( float4( v.vPos, 1 ), cModelViewProj ); + o.vProjPos = vProjPos; + + vWorldPos = mul( float4( v.vPos, 1 ), cModel[0] ); + + o.worldPos_projPosZ.w = vProjPos.z; + o.worldPos_projPosZ.xyz = vWorldPos; + +#if ( FOW == 1 ) + o.vFowCoord.xy = CalcFoWCoord( g_vFoWWorldSize, vWorldPos.xy ); +#else + o.vFowCoord.xy = float2( 0.0, 0.0 ); +#endif + + float3 vWorldNormal = mul( vObjNormal, ( float3x3 )cModel[0] ); + + o.vBaseTexCoord.xy = ComputeTexCoord( v.vBaseTexCoord, g_vRotations.x, g_vScales.x ); + o.vBlendCoords23.xy = ComputeTexCoord( v.vBaseTexCoord, g_vRotations.y, g_vScales.y ); + o.vBlendCoords23.zw = ComputeTexCoord( v.vBaseTexCoord, g_vRotations.z, g_vScales.z ); + o.vFowCoord.zw = ComputeTexCoord( v.vBaseTexCoord, g_vRotations.w, g_vScales.w ); + + o.vBaseTexCoord.zw = v.vLightmapTexCoord; // + v.vLightmapTexCoordOffset; + + o.vColorBlend1 = v.vColorBlend1; + o.vColorBlend2 = v.vColorBlend2; + o.vColorBlend3 = v.vColorBlend3; + o.vColorBlend4.xyz = v.vColorBlend4.xyz; + o.vAlphaBlend.xyz = v.vAlphaBlend.xyz; + +#if ( SPECULAR == 1 ) + + float3 vWorldVertToEyeVector = cEyePos - vWorldPos; + float3 vView = normalize( vWorldVertToEyeVector ); + float3 vReflect = reflect( g_vLightDir, vWorldNormal ); + float fDot = dot( vView, vReflect ); + o.vAlphaBlend.w = saturate( pow( saturate( fDot ), g_vLightDir.w ) ); + +#else + + o.vAlphaBlend.w = 0; + +#endif + +#if ( FLASHLIGHT == 1 ) + + o.vFlashlightSpacePos = mul( float4( vWorldPos, 1.0f ), g_FlashlightWorldToTexture ); + o.vBaseTexCoord.zw = vProjPos.xy / vProjPos.w; + +#endif + + return o; +} diff --git a/materialsystem/stdshaders/object_motion_blur_dx9.cpp b/materialsystem/stdshaders/object_motion_blur_dx9.cpp new file mode 100644 index 00000000..c44e9900 --- /dev/null +++ b/materialsystem/stdshaders/object_motion_blur_dx9.cpp @@ -0,0 +1,76 @@ +//===================== Copyright (c) Valve Corporation. All Rights Reserved. ====================== +// +// Object space motion blur shader c++ backing file +// +//================================================================================================== + +#include "BaseVSShader.h" +#include "object_motion_blur_vs20.inc" +#include "object_motion_blur_ps20.inc" +#include "object_motion_blur_ps20b.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_VS_SHADER_FLAGS( ObjectMotionBlur, "Object Motion Blur", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( FB_TEXTURE, SHADER_PARAM_TYPE_TEXTURE, "_rt_FullFrameFB", "Full-screen framebuffer to sample from." ) + SHADER_PARAM( VELOCITY_TEXTURE, SHADER_PARAM_TYPE_TEXTURE, "_rt_SmallHDR0", "Full-screen velocity buffer to sample from." ) + END_SHADER_PARAMS + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + if( params[ FB_TEXTURE ]->IsDefined() ) + { + LoadTexture( FB_TEXTURE ); + } + if( params[ VELOCITY_TEXTURE ]->IsDefined() ) + { + LoadTexture( VELOCITY_TEXTURE ); + } + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 1, 0, 0 ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, false ); + + DECLARE_STATIC_VERTEX_SHADER( object_motion_blur_vs20 ); + SET_STATIC_VERTEX_SHADER( object_motion_blur_vs20 ); + + DECLARE_STATIC_PIXEL_SHADER( object_motion_blur_ps20b ); + SET_STATIC_PIXEL_SHADER( object_motion_blur_ps20b ); + + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableAlphaWrites( false ); + pShaderShadow->EnableSRGBWrite( true ); + } + + DYNAMIC_STATE + { + // Bind textures + BindTexture( SHADER_SAMPLER0, FB_TEXTURE ); + BindTexture( SHADER_SAMPLER1, VELOCITY_TEXTURE ); + + DECLARE_DYNAMIC_VERTEX_SHADER( object_motion_blur_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( object_motion_blur_vs20 ); + + Assert( g_pHardwareConfig->SupportsPixelShaders_2_b() ); + DECLARE_DYNAMIC_PIXEL_SHADER( object_motion_blur_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( object_motion_blur_ps20b ); + } + + Draw(); + } +END_SHADER diff --git a/materialsystem/stdshaders/object_motion_blur_ps2x.fxc b/materialsystem/stdshaders/object_motion_blur_ps2x.fxc new file mode 100644 index 00000000..046c4e66 --- /dev/null +++ b/materialsystem/stdshaders/object_motion_blur_ps2x.fxc @@ -0,0 +1,69 @@ +//====== Copyright © 1996-2007, Valve Corporation, All rights reserved. =========================== + +#ifdef HDRTYPE + #undef HDRTYPE +#endif +#define HDRTYPE HDR_TYPE_NONE + +// Includes ======================================================================================= +#include "common_ps_fxc.h" + +// Texture Samplers =============================================================================== +sampler g_tFullScreenColor : register( s0 ); +sampler g_tFullScreenVelocity : register( s1 ); + +// Shaders Constants and Globals ================================================================== + +// Interpolated values ============================================================================ +struct PS_INPUT +{ + float2 vUv0 : TEXCOORD0; +}; + +// Main =========================================================================================== +float4 main( PS_INPUT i ) : COLOR +{ + float4 vVelocity = tex2D( g_tFullScreenVelocity, i.vUv0.xy ); + vVelocity.xy = vVelocity.xy * 256.0f / 255.0f * 2.0f - float2( 1.0f, 1.0f ); + +#define NUM_SAMPLES 10 +#define STEP_SIZE 0.002 + +#define OLD_METHOD 0 + +#if OLD_METHOD + + float4 cBlurColor = float4( 0, 0, 0, 0 ); + for ( int x = 0; x < NUM_SAMPLES; x ++ ) + { + // Calculate offset uv + float2 vUvTmp = i.vUv0.xy - ( vVelocity.xy * x * STEP_SIZE ); + + cBlurColor += (1.0f / NUM_SAMPLES ) * tex2D( g_tFullScreenColor, vUvTmp.xy ); + } + return float4( cBlurColor.rgb, 1.0f ); + +#else + + float4 cBaseColor = tex2D( g_tFullScreenColor, i.vUv0.xy ); + float4 cBlurColor = float4( 0, 0, 0, 0 ); + + float flTotalBlurWeight = 0.0f; + + // @TODO: unroll loop on X360? + for ( int x = 1; x < NUM_SAMPLES; x ++ ) + { + // Calculate offset uv + float2 vUvTmp = i.vUv0.xy + ( vVelocity.xy * x * STEP_SIZE ); + + float4 vOffsetVelocity = tex2D( g_tFullScreenVelocity, vUvTmp ); + flTotalBlurWeight += vOffsetVelocity.b; + + cBlurColor += vOffsetVelocity.b * tex2D( g_tFullScreenColor, vUvTmp.xy ); + } + + float4 cFinalColor = ( cBlurColor + ( NUM_SAMPLES - flTotalBlurWeight ) * cBaseColor ) / NUM_SAMPLES; + return float4( cFinalColor.rgb, 1.0f ); + +#endif +} diff --git a/materialsystem/stdshaders/object_motion_blur_vs20.fxc b/materialsystem/stdshaders/object_motion_blur_vs20.fxc new file mode 100644 index 00000000..80080b54 --- /dev/null +++ b/materialsystem/stdshaders/object_motion_blur_vs20.fxc @@ -0,0 +1,29 @@ +//====== Copyright © 1996-2007, Valve Corporation, All rights reserved. =========================== + +// Includes ======================================================================================= +#include "common_vs_fxc.h" + +// Input values =================================================================================== +struct VS_INPUT +{ + float3 vPos : POSITION; + float2 vBaseTexCoord : TEXCOORD0; +}; + +// Interpolated values ============================================================================ +struct VS_OUTPUT +{ + float4 projPos : POSITION; + float2 vUv0 : TEXCOORD0; +}; + +// Main =========================================================================================== +VS_OUTPUT main( const VS_INPUT i ) +{ + VS_OUTPUT o; + + o.projPos.xyzw = float4( i.vPos.xyz, 1.0f ); + o.vUv0.xy = i.vBaseTexCoord.xy; + + return o; +} diff --git a/materialsystem/stdshaders/occlusion_dx9.cpp b/materialsystem/stdshaders/occlusion_dx9.cpp new file mode 100644 index 00000000..3abda547 --- /dev/null +++ b/materialsystem/stdshaders/occlusion_dx9.cpp @@ -0,0 +1,70 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" + +#include "writez_vs20.inc" +#include "white_ps20.inc" +#include "white_ps20b.inc" + + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( Occlusion, Occlusion_DX9 ) + +BEGIN_VS_SHADER_FLAGS( Occlusion_DX9, "Help for Occlusion", SHADER_NOT_EDITABLE ) + + BEGIN_SHADER_PARAMS + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableColorWrites( false ); + pShaderShadow->EnableAlphaWrites( false ); + pShaderShadow->EnableDepthWrites( false ); + + DECLARE_STATIC_VERTEX_SHADER( writez_vs20 ); + SET_STATIC_VERTEX_SHADER( writez_vs20 ); + + //no pixel shader, doubles fill rate. + + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + } + DYNAMIC_STATE + { + DECLARE_DYNAMIC_VERTEX_SHADER( writez_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER( writez_vs20 ); + + //no pixel shader, doubles fill rate. + } + Draw(); + } +END_SHADER + diff --git a/materialsystem/stdshaders/overlay_fit.cpp b/materialsystem/stdshaders/overlay_fit.cpp new file mode 100644 index 00000000..ce091721 --- /dev/null +++ b/materialsystem/stdshaders/overlay_fit.cpp @@ -0,0 +1,90 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "BaseVSShader.h" +#include "convar.h" + +#include "overlay_fit_vs11.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +// FIXME: Need to make a dx9 version so that "CENTROID" works. + +BEGIN_VS_SHADER_FLAGS( Overlay_Fit, "Help for TerrainTest2", SHADER_NOT_EDITABLE ) + + BEGIN_SHADER_PARAMS + END_SHADER_PARAMS + + // Set up anything that is necessary to make decisions in SHADER_FALLBACK. + SHADER_INIT_PARAMS() + { + // No texture means no self-illum or env mask in base alpha + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + + // If in decal mode, no debug override... + if (IS_FLAG_SET(MATERIAL_VAR_DECAL)) + { + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + } + + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + } + + SHADER_FALLBACK + { + if ( IsPC() && !g_pHardwareConfig->SupportsVertexAndPixelShaders() ) + return "WorldTwoTextureBlend"; + + return 0; + } + + SHADER_INIT + { + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + LoadTexture( BASETEXTURE ); + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); // BASETEXTURE + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); // LIGHTMAP + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); // BASETEXTURE + + // texcoord0 : base texcoord + // texcoord1 : alpha texcoord (mapped to fill the overlay) + unsigned int flags = VERTEX_POSITION | VERTEX_COLOR; + int numTexCoords = 3; + pShaderShadow->VertexShaderVertexFormat( flags, numTexCoords, 0, 0 ); + + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + + pShaderShadow->EnablePolyOffset( SHADER_POLYOFFSET_DECAL ); + + overlay_fit_vs11_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "Overlay_Fit_vs11", vshIndex.GetIndex() ); + + pShaderShadow->SetPixelShader ( "Overlay_Fit_ps11", 0 ); + + FogToFogColor(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP ); + BindTexture( SHADER_SAMPLER2, BASETEXTURE, FRAME ); + + overlay_fit_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); + } +END_SHADER + diff --git a/materialsystem/stdshaders/parallaxtest.cpp b/materialsystem/stdshaders/parallaxtest.cpp new file mode 100644 index 00000000..a0162fee --- /dev/null +++ b/materialsystem/stdshaders/parallaxtest.cpp @@ -0,0 +1,80 @@ +//========= Copyright © 1996-2008, Valve Corporation, All rights reserved. ============// +// +// Purpose: Parallax Occlusion Mapping test shader +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" +#include "convar.h" +#include "parallaxtest_vs30.inc" +#include "parallaxtest_ps30.inc" + +ConVar mat_parallaxmapsamplesmin( "mat_parallaxmapsamplesmin", "12" ); +ConVar mat_parallaxmapsamplesmax( "mat_parallaxmapsamplesmax", "50" ); + +BEGIN_VS_SHADER( ParallaxTest, + "Help for ParallaxTest" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "bump map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + END_SHADER_PARAMS + + SHADER_FALLBACK + { + return 0; + } + + // Set up anything that is necessary to make decisions in SHADER_FALLBACK. + SHADER_INIT_PARAMS() + { + } + + SHADER_INIT + { + LoadTexture( BASETEXTURE ); + LoadTexture( BUMPMAP ); + } + + SHADER_DRAW + { + SHADOW_STATE + { + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_TANGENT_S | VERTEX_TANGENT_T; + int numTexCoords = 1; + pShaderShadow->VertexShaderVertexFormat( flags, numTexCoords, 0, 0 ); + + // base + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + // normal + height + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + DECLARE_STATIC_VERTEX_SHADER( parallaxtest_vs30 ); + SET_STATIC_VERTEX_SHADER( parallaxtest_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( parallaxtest_ps30 ); + SET_STATIC_PIXEL_SHADER( parallaxtest_ps30 ); + } + DYNAMIC_STATE + { + // base texture + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + + // normal + height + BindTexture( SHADER_SAMPLER1, BUMPMAP, BUMPFRAME ); + + DECLARE_DYNAMIC_VERTEX_SHADER( parallaxtest_vs30 ); + SET_DYNAMIC_VERTEX_SHADER( parallaxtest_vs30 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( parallaxtest_ps30 ); + SET_DYNAMIC_PIXEL_SHADER( parallaxtest_ps30 ); + + Vector4D c0( mat_parallaxmapsamplesmin.GetFloat(), mat_parallaxmapsamplesmax.GetFloat(), 0.0f, 0.0f ); + pShaderAPI->SetPixelShaderConstant( 0, c0.Base(), 1 ); + } + Draw(); + } +END_SHADER + \ No newline at end of file diff --git a/materialsystem/stdshaders/parallaxtest_ps30.fxc b/materialsystem/stdshaders/parallaxtest_ps30.fxc new file mode 100644 index 00000000..6d3406fd --- /dev/null +++ b/materialsystem/stdshaders/parallaxtest_ps30.fxc @@ -0,0 +1,224 @@ +//---------------------------------------------------------------------------------// +// Parallax occlusion mapping algorithm implementation. Pixel shader. +//---------------------------------------------------------------------------------// + +//.......................................................................................... +// Uniform shader parameters declaration +//.......................................................................................... + +const float4 g_ParallaxParms : register( c0 ); + +float fShadowSoftening = 0.59f; // fixme: should be a vmt param +float fHeightMapRange = 0.02f; // fixme: should be a vmt param + +// unused stuff +float fSpecularExponent = 100.0f; // fixme: should be a vmt param +float fDiffuseBrightness = 1.0f; +float4 cAmbientColor = float4( 1.0f, 1.0f, 1.0f, 1.0f ); +float4 cDiffuseColor = float4( 1.0f, 1.0f, 1.0f, 1.0f ); +float4 cSpecularColor = float4( 1.0f, 1.0f, 1.0f, 1.0f ); + +// texture samplers +sampler tBaseMap; +sampler tNormalMap; + +//.......................................................................................... +// Note: centroid is specified if multisampling is enabled through RenderMonkey's DirectX +// window preferences settings +//.......................................................................................... +struct PS_INPUT +{ + float2 texCoord : TEXCOORD0; +// float3 vLightTS : TEXCOORD1_centroid; // light vector in tangent space, denormalized + float3 vViewTS : TEXCOORD2_centroid; // view vector in tangent space, denormalized + float2 vParallaxOffsetTS : TEXCOORD3_centroid; // Parallax offset vector in tangent space + float3 vNormalWS : TEXCOORD4_centroid; // Normal vector in world space + float3 vViewWS : TEXCOORD5_centroid; // View vector in world space + float4 vDebug : TEXCOORD6; +}; + +//.......................................................................................... +// Function: ComputeIllumination +// +// Description: Computes phong illumination for the given pixel using its attribute textures +// and a light vector. +//.......................................................................................... +float4 ComputeIllumination( float2 texCoord, float3 vLightTS, float3 vViewTS, float fOcclusionShadow ) +{ + // Sample the normal from the normal map for the given texture sample: + float3 vNormalTS = normalize( tex2D( tNormalMap, texCoord ) * 2 - 1 ); + + // Sample base map: + float4 cBaseColor = tex2D( tBaseMap, texCoord ); + + // Compute diffuse color component: + float4 cDiffuse = saturate( dot( vNormalTS, vLightTS )) * cDiffuseColor; + + // Compute specular component: + float3 vReflectionTS = normalize( 2 * dot( vViewTS, vNormalTS ) * vNormalTS - vViewTS ); + + float fRdotL = dot( vReflectionTS, vLightTS ); + + float4 cSpecular = saturate( pow( fRdotL, fSpecularExponent )) * cSpecularColor; + + float4 cFinalColor = (( cAmbientColor + cDiffuse ) * cBaseColor + cSpecular ) * fOcclusionShadow; + + return cFinalColor; +} + +//........................................................................................... +// Function: ps_main +// +// Description: Computes pixel illumination result due to applying parallax occlusion mapping +// to simulation of view-dependent surface displacement for a given height map +//........................................................................................... +float4 main( PS_INPUT i ) : COLOR0 +{ + int nMinSamples = g_ParallaxParms.x; + int nMaxSamples = g_ParallaxParms.y; + + // Normalize the interpolated vectors: + float3 vViewTS = normalize( i.vViewTS ); + float3 vViewWS = normalize( i.vViewWS ); +// float3 vLightTS = normalize( i.vLightTS ); + float3 vNormalWS = normalize( i.vNormalWS ); + + float4 cResultColor = float4( 0, 0, 0, 1 ); + + // Compute all the derivatives: + float2 dx = ddx( i.texCoord ); + float2 dy = ddy( i.texCoord ); + + //===============================================// + // Parallax occlusion mapping offset computation // + //===============================================// + + // Utilize dynamic flow control to change the number of samples per ray + // depending on the viewing angle for the surface. Oblique angles require + // smaller step sizes to achieve more accurate precision for computing displacement. + // We express the sampling rate as a linear function of the angle between + // the geometric normal and the view direction ray: + int nNumSteps = (int) lerp( nMaxSamples, nMinSamples, dot( vViewWS, vNormalWS ) ); + + // Intersect the view ray with the height field profile along the direction of + // the parallax offset ray (computed in the vertex shader. Note that the code is + // designed specifically to take advantage of the dynamic flow control constructs + // in HLSL and is very sensitive to specific syntax. When converting to other examples, + // if still want to use dynamic flow control in the resulting assembly shader, + // care must be applied. + // + // In the below steps we approximate the height field profile as piecewise linear + // curve. We find the pair of endpoints between which the intersection between the + // height field profile and the view ray is found and then compute line segment + // intersection for the view ray and the line segment formed by the two endpoints. + // This intersection is the displacement offset from the original texture coordinate. + // See the above paper for more details about the process and derivation. + // + float fCurrHeight = 0.0; + float fStepSize = 1.0 / (float) nNumSteps; + float fPrevHeight = 1.0; + float fNextHeight = 0.0; + + int nStepIndex = 0; + bool bCondition = true; + + float2 vTexOffsetPerStep = fStepSize * i.vParallaxOffsetTS; + float2 vTexCurrentOffset = i.texCoord; + float fCurrentBound = 1.0; + float fParallaxAmount = 0.0; + + float2 pt1 = 0; + float2 pt2 = 0; + + float2 texOffset2 = 0; + + while ( nStepIndex < nNumSteps ) + { + vTexCurrentOffset -= vTexOffsetPerStep; + + // Sample height map which in this case is stored in the alpha channel of the normal map: + fCurrHeight = tex2Dgrad( tNormalMap, vTexCurrentOffset, dx, dy ).a; + + fCurrentBound -= fStepSize; + + if ( fCurrHeight > fCurrentBound ) + { + pt1 = float2( fCurrentBound, fCurrHeight ); + pt2 = float2( fCurrentBound + fStepSize, fPrevHeight ); + + texOffset2 = vTexCurrentOffset - vTexOffsetPerStep; + + nStepIndex = nNumSteps + 1; + } + else + { + nStepIndex++; + fPrevHeight = fCurrHeight; + } + } // End of while ( nStepIndex < nNumSteps ) + + float fDelta2 = pt2.x - pt2.y; + float fDelta1 = pt1.x - pt1.y; + fParallaxAmount = (pt1.x * fDelta2 - pt2.x * fDelta1 ) / ( fDelta2 - fDelta1 ); + + float2 vParallaxOffset = i.vParallaxOffsetTS * (1 - fParallaxAmount ); + + // The computed texture offset for the displaced point on the pseudo-extruded surface: + float2 texSample = i.texCoord - vParallaxOffset; + +// float2 vLightRayTS = vLightTS.xy * fHeightMapRange; + + // Compute the soft blurry shadows taking into account self-occlusion for features of the height + // field: + +// float sh0 = tex2Dgrad( tNormalMap, texSample, dx, dy ).a; +// float shA = (tex2Dgrad( tNormalMap, texSample + vLightRayTS * 0.88, dx, dy ).a - sh0 - 0.88 ) * 1 * fShadowSoftening; +// float sh9 = (tex2Dgrad( tNormalMap, texSample + vLightRayTS * 0.77, dx, dy ).a - sh0 - 0.77 ) * 2 * fShadowSoftening; +// float sh8 = (tex2Dgrad( tNormalMap, texSample + vLightRayTS * 0.66, dx, dy ).a - sh0 - 0.66 ) * 4 * fShadowSoftening; +// float sh7 = (tex2Dgrad( tNormalMap, texSample + vLightRayTS * 0.55, dx, dy ).a - sh0 - 0.55 ) * 6 * fShadowSoftening; +// float sh6 = (tex2Dgrad( tNormalMap, texSample + vLightRayTS * 0.44, dx, dy ).a - sh0 - 0.44 ) * 8 * fShadowSoftening; +// float sh5 = (tex2Dgrad( tNormalMap, texSample + vLightRayTS * 0.33, dx, dy ).a - sh0 - 0.33 ) * 10 * fShadowSoftening; +// float sh4 = (tex2Dgrad( tNormalMap, texSample + vLightRayTS * 0.22, dx, dy ).a - sh0 - 0.22 ) * 12 * fShadowSoftening; + + // Compute the actual shadow strength: +// float fOcclusionShadow = 1 - max( max( max( max( max( max( shA, sh9 ), sh8 ), sh7 ), sh6 ), sh5 ), sh4 ); + + // The previous computation overbrightens the image, let's adjust for that: +// fOcclusionShadow = fOcclusionShadow * 0.6 + 0.4; + + // Compute resulting color for the pixel: +// cResultColor = ComputeIllumination( texSample, vLightTS, vViewTS, fOcclusionShadow ); + + // cResultColor.xyz = ( float )nNumSteps / nMaxSamples; + //cResultColor.xyz = float3( vTexOffsetPerStep, 0.0f ); + cResultColor.xyz = tex2Dgrad( tNormalMap, texSample, dx, dy ).rgb; + cResultColor.a = 1.0f; + +// cResultColor.xyz = float3( vParallaxOffset * 10.0, 0.0f ); +// cResultColor.xyz = ( float3 )fParallaxAmount * .1f; + // cResultColor.xyz = float3( i.texCoord - ( int2 )i.texCoord, 0.0f ); +// cResultColor.xyz = i.vViewTS; +// cResultColor.xyz = i.vNormalWS.xyz; +// cResultColor.xyz = float3( i.vParallaxOffsetTS * 10.0f, 0.0f ); +// cResultColor = i.vDebug; +// cResultColor.xyz = ( float3 )tex2Dgrad( tNormalMap, texSample, dx, dy ).a; +// cResultColor.xyz = float3( vTexOffsetPerStep * 10.0f, 0.0f ); + + +// cResultColor = float4( 1.0f, 0.0f, 0.0f, 1.0f ); + + return cResultColor; + +} // End of float4 ps_main(..) + +#if 0 +struct PS_INPUT +{ + float2 texCoord : TEXCOORD0; +// float3 vLightTS : TEXCOORD1_centroid; // light vector in tangent space, denormalized + float3 vViewTS : TEXCOORD2_centroid; // view vector in tangent space, denormalized + float2 vParallaxOffsetTS : TEXCOORD3_centroid; // Parallax offset vector in tangent space + float3 vNormalWS : TEXCOORD4_centroid; // Normal vector in world space + float3 vViewWS : TEXCOORD5_centroid; // View vector in world space +}; +#endif \ No newline at end of file diff --git a/materialsystem/stdshaders/parallaxtest_vs30.fxc b/materialsystem/stdshaders/parallaxtest_vs30.fxc new file mode 100644 index 00000000..2be83b94 --- /dev/null +++ b/materialsystem/stdshaders/parallaxtest_vs30.fxc @@ -0,0 +1,97 @@ +#include "common_vs_fxc.h" + +//---------------------------------------------------------------------------------// +// Parallax occlusion mapping algorithm implementation. Vertex shader. +//---------------------------------------------------------------------------------// + + +#define matWorldViewProjection cModelViewProj +//float4x4 matViewInverse; +//float4x4 matView; + +//float fBaseTextureRepeat; +//float4 vLightPosition; + +struct VS_INPUT +{ + float4 positionWS : POSITION; + float3 vNormalWS : NORMAL; + float2 texCoord : TEXCOORD0; + float3 vBinormalWS : BINORMAL; + float3 vTangentWS : TANGENT; +}; + +struct VS_OUTPUT +{ + float4 position : POSITION; // proj-space position + float2 texCoord : TEXCOORD0; +// float3 vLightTS : TEXCOORD1; // light vector in tangent space, denormalized + float3 vViewTS : TEXCOORD2; // view vector in tangent space, denormalized + float2 vParallaxOffsetTS : TEXCOORD3; // Parallax offset vector in tangent space + float3 vNormalWS : TEXCOORD4; // Normal vector in world space + float3 vViewWS : TEXCOORD5; // View vector in world space + float4 vDebug : TEXCOORD6; +}; + +VS_OUTPUT main( VS_INPUT i ) +{ + VS_OUTPUT Out = (VS_OUTPUT) 0; + + // Transform and output input position + Out.position = mul( float4( i.positionWS.xyz, 1 ), cModelViewProj ); + //Out.position = mul( matWorldViewProjection, i.positionWS ); + + // Propagate texture coordinate through: + Out.texCoord = i.texCoord; + + // Uncomment this to repeat the texture + // Out.texCoord *= fBaseTextureRepeat; + + // Propagate the world vertex normal through: + Out.vNormalWS = i.vNormalWS; + + // Compute and output the world view vector: + float3 vViewWS = cEyePos - i.positionWS; + Out.vViewWS = vViewWS; + + // Compute denormalized light vector in world space: +// float3 vLightWS = vLightPosition - i.positionWS; + + // Normalize the light and view vectors and transform it to the tangent space: + float3x3 mWorldToTangent = float3x3( i.vTangentWS, i.vBinormalWS, i.vNormalWS ); +// float3x3 mWorldToTangent = float3x3( i.vBinormalWS, i.vTangentWS, i.vNormalWS ); + + // Propagate the view and the light vectors (in tangent space): +// Out.vLightTS = mul( mWorldToTangent, vLightWS ); + Out.vViewTS = mul( mWorldToTangent, vViewWS ); + + float fHeightMapRange = 0.02f; // FIXME: should be a vmt param + + // Compute the ray direction for intersecting the height field profile with + // current view ray. See the above paper for derivation of this computation. + + // Compute initial parallax displacement direction: + float2 vParallaxDirection = normalize( Out.vViewTS.xy ); + + // The length of this vector determines the furthest amount of displacement: + float fLength = length( Out.vViewTS ); + float fParallaxLength = sqrt( fLength * fLength - Out.vViewTS.z * Out.vViewTS.z ) / Out.vViewTS.z; + + // Compute the actual reverse parallax displacement vector: + Out.vParallaxOffsetTS = vParallaxDirection * fParallaxLength; + + // Need to scale the amount of displacement to account for different height ranges + // in height maps. This is controlled by an artist-editable parameter: + Out.vParallaxOffsetTS *= fHeightMapRange; + + Out.vDebug = float4( 1.0f, 0.0f, 0.0f, 1.0f ); + Out.vDebug.xy = vParallaxDirection; + // Out.vDebug.xyz = ( float3 )fHeightMapRange; + Out.vDebug.xyz = fParallaxLength * .1; + Out.vDebug.xyz = fHeightMapRange * 200; + + return Out; + +} // End of VS_OUTPUT vs_main(..) + + \ No newline at end of file diff --git a/materialsystem/stdshaders/particlelitgeneric_dx9.cpp b/materialsystem/stdshaders/particlelitgeneric_dx9.cpp new file mode 100644 index 00000000..4b77ffc8 --- /dev/null +++ b/materialsystem/stdshaders/particlelitgeneric_dx9.cpp @@ -0,0 +1,62 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" +#include "particlelitgeneric_dx9_helper.h" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +BEGIN_VS_SHADER( ParticleLitGeneric_DX9, + "Help for ParticleLitGeneric_DX9" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "bump map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + END_SHADER_PARAMS + + void SetupVars( ParticleLitGeneric_DX9_Vars_t& info ) + { + info.m_nBaseTexture = BASETEXTURE; + info.m_nBaseTextureFrame = FRAME; + info.m_nBaseTextureTransform = BASETEXTURETRANSFORM; + info.m_nBumpmap = BUMPMAP; + info.m_nBumpFrame = BUMPFRAME; + info.m_nBumpTransform = BUMPTRANSFORM; + info.m_nAlphaTestReference = -1; + info.m_nFlashlightTexture = FLASHLIGHTTEXTURE; + info.m_nFlashlightTextureFrame = FLASHLIGHTTEXTUREFRAME; + } + + SHADER_INIT_PARAMS() + { + ParticleLitGeneric_DX9_Vars_t vars; + SetupVars( vars ); +// InitParamsParticleLitGeneric_DX9( this, params, pMaterialName, vars ); + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + ParticleLitGeneric_DX9_Vars_t vars; + SetupVars( vars ); +// InitParticleLitGeneric_DX9( this, params, vars ); + } + + SHADER_DRAW + { + ParticleLitGeneric_DX9_Vars_t vars; + SetupVars( vars ); +// DrawParticleLitGeneric_DX9( this, params, pShaderAPI, pShaderShadow, vars ); + } +END_SHADER diff --git a/materialsystem/stdshaders/particlelitgeneric_dx9_helper.cpp b/materialsystem/stdshaders/particlelitgeneric_dx9_helper.cpp new file mode 100644 index 00000000..38e24ba8 --- /dev/null +++ b/materialsystem/stdshaders/particlelitgeneric_dx9_helper.cpp @@ -0,0 +1,293 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $NoKeywords: $ +// +//===========================================================================// + +#if 0 + +#include "particlelitgeneric_dx9_helper.h" +#include "basevsshader.h" +#include "particlelit_generic_vs30.inc" +#include "particlelit_generic_ps30.inc" +#include "convar.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + +//----------------------------------------------------------------------------- +// Initialize shader parameters +//----------------------------------------------------------------------------- +void InitParamsParticleLitGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, ParticleLitGeneric_DX9_Vars_t &info ) +{ + // FLASHLIGHTFIXME: Do ShaderAPI::BindFlashlightTexture + Assert( info.m_nFlashlightTexture >= 0 ); + + params[FLASHLIGHTTEXTURE]->SetStringValue( GetFlashlightTextureFilename() ); + + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + + if( (info.m_nBumpFrame != -1) && !params[info.m_nBumpFrame]->IsDefined() ) + { + params[info.m_nBumpFrame]->SetIntValue( 0 ); + } + + if( (info.m_nBumpmap != -1) && g_pConfig->UseBumpmapping() && params[info.m_nBumpmap]->IsDefined() ) + { + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + } + else + { + CLEAR_FLAGS( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ); + } +} + + +//----------------------------------------------------------------------------- +// Initialize shader +//----------------------------------------------------------------------------- +void InitParticleLitGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, ParticleLitGeneric_DX9_Vars_t &info ) +{ + Assert( info.m_nFlashlightTexture >= 0 ); + pShader->LoadTexture( info.m_nFlashlightTexture ); + + bool bIsBaseTextureTranslucent = false; + if ( params[info.m_nBaseTexture]->IsDefined() ) + { + pShader->LoadTexture( info.m_nBaseTexture ); + + if ( params[info.m_nBaseTexture]->GetTextureValue()->IsTranslucent() ) + { + bIsBaseTextureTranslucent = true; + } + } + // No alpha channel in any of the textures? No self illum or envmapmask + if ( !bIsBaseTextureTranslucent ) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + if ( g_pConfig->UseBumpmapping() ) + { + if ( (info.m_nBumpmap != -1) && params[info.m_nBumpmap]->IsDefined() ) + { + pShader->LoadBumpMap( info.m_nBumpmap ); + SET_FLAGS2( MATERIAL_VAR2_DIFFUSE_BUMPMAPPED_MODEL ); + } + } + + // Don't alpha test if the alpha channel is used for other purposes + if ( IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK) ) + { + CLEAR_FLAGS( MATERIAL_VAR_ALPHATEST ); + } +} + + +//----------------------------------------------------------------------------- +// Draws the shader +//----------------------------------------------------------------------------- +void DrawParticleLitGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, + IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, ParticleLitGeneric_DX9_Vars_t &info ) +{ + bool hasBaseTexture = params[info.m_nBaseTexture]->IsTexture(); + bool hasBump = (info.m_nBumpmap != -1) && params[info.m_nBumpmap]->IsTexture(); + bool hasVertexColor = IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR ); + bool hasVertexAlpha = IS_FLAG_SET( MATERIAL_VAR_VERTEXALPHA ); + bool bIsAlphaTested = IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) != 0; + bool bNoFog = IS_FLAG_SET( MATERIAL_VAR_NOFOG ); + + HDRType_t hdrType = g_pHardwareConfig->GetHDRType(); + + BlendType_t blendType = pShader->EvaluateBlendRequirements( info.m_nBaseTexture, true ); + if( pShader->IsSnapshotting() ) + { + // look at color and alphamod stuff. + // Unlit generic never uses the flashlight + bool hasFlashlight = CShader_IsFlag2Set( params, MATERIAL_VAR2_USE_FLASHLIGHT ); + bool bHalfLambert = IS_FLAG_SET( MATERIAL_VAR_HALFLAMBERT ); + + // Alpha test: FIXME: shouldn't this be handled in CBaseVSShader::SetInitialShadowState + pShaderShadow->EnableAlphaTest( bIsAlphaTested ); + + if( info.m_nAlphaTestReference != -1 && params[info.m_nAlphaTestReference]->GetFloatValue() > 0.0f ) + { + pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GEQUAL, params[info.m_nAlphaTestReference]->GetFloatValue() ); + } + + if( hasFlashlight ) + { + pShader->SetAdditiveBlendingShadowState( info.m_nBaseTexture, true ); + if( bIsAlphaTested ) + { + // disable alpha test and use the zfunc zequals since alpha isn't guaranteed to + // be the same on both the regular pass and the flashlight pass. + pShaderShadow->EnableAlphaTest( false ); + pShaderShadow->DepthFunc( SHADER_DEPTHFUNC_EQUAL ); + } + pShaderShadow->EnableBlending( true ); + pShaderShadow->EnableDepthWrites( false ); + } + else + { + pShader->SetDefaultBlendingShadowState( info.m_nBaseTexture, true ); + } + + unsigned int flags = VERTEX_POSITION; + + int userDataSize = 0; + if( hasBaseTexture ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + } + if( hasFlashlight ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER7, true ); + userDataSize = 4; // tangent S + } + if( hasBump ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + userDataSize = 4; // tangent S + // Normalizing cube map + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); + } + if( hasVertexColor || hasVertexAlpha ) + { + flags |= VERTEX_COLOR; + } + + pShaderShadow->EnableSRGBWrite( true ); + + // texcoord0 : base texcoord + int pTexCoordCount[2] = { 2, 3 }; + pShaderShadow->VertexShaderVertexFormat( + flags, 2, pTexCoordCount, 0, userDataSize ); + + DECLARE_STATIC_VERTEX_SHADER( particlelit_generic_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT, bHalfLambert); + SET_STATIC_VERTEX_SHADER( particlelit_generic_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( particlelit_generic_ps30 ); + SET_STATIC_PIXEL_SHADER_COMBO( HALFLAMBERT, bHalfLambert); +// SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, hasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( HDRTYPE, hdrType ); + SET_STATIC_PIXEL_SHADER( particlelit_generic_ps30 ); + + if( hasFlashlight ) + { + pShader->FogToBlack(); + } + else + { + pShader->DefaultFog(); + } + + // HACK HACK HACK - enable alpha writes all the time so that we have them for + // underwater stuff + if( blendType != BT_BLENDADD && blendType != BT_BLEND && !bIsAlphaTested ) + { + pShaderShadow->EnableAlphaWrites( true ); + } + } + else + { + bool hasFlashlight = pShaderAPI->InFlashlightMode(); + + if( hasBaseTexture ) + { + pShader->BindTexture( SHADER_SAMPLER0, info.m_nBaseTexture, info.m_nBaseTextureFrame ); + } + if( !g_pConfig->m_bFastNoBump ) + { + if( hasBump ) + { + pShader->BindTexture( SHADER_SAMPLER3, info.m_nBumpmap, info.m_nBumpFrame ); + } + } + else + { + if( hasBump ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER3, TEXTURE_NORMALMAP_FLAT ); + } + } + if( hasFlashlight ) + { + Assert( info.m_nFlashlightTexture >= 0 && info.m_nFlashlightTextureFrame >= 0 ); + pShader->BindTexture( SHADER_SAMPLER7, info.m_nFlashlightTexture, info.m_nFlashlightTextureFrame ); + } + + LightState_t lightState = { 0, false, false }; + if( !hasFlashlight ) + pShaderAPI->GetDX9LightState( &lightState ); + + MaterialFogMode_t fogType = pShaderAPI->GetSceneFogMode(); +// int fogIndex = ( fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ) ? 1 : 0; + + DECLARE_DYNAMIC_VERTEX_SHADER( particlelit_generic_vs30 ); + SET_DYNAMIC_VERTEX_SHADER( particlelit_generic_vs30 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( particlelit_generic_ps30 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( AMBIENT_LIGHT, lightState.m_bAmbientLight ? 1 : 0 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( STATIC_LIGHT, lightState.m_bStaticLight ? 1 : 0 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z && + blendType != BT_BLENDADD && blendType != BT_BLEND && !bIsAlphaTested ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( HDRENABLED, pShader->IsHDREnabled() ); + SET_DYNAMIC_PIXEL_SHADER( particlelit_generic_ps30 ); + + pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, info.m_nBaseTextureTransform ); + if( hasBump ) + { + pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, info.m_nBumpTransform ); + } + if( hasBump ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER5, TEXTURE_NORMALIZATION_CUBEMAP_SIGNED ); + pShaderAPI->SetPixelShaderStateAmbientLightCube( 5 ); + pShaderAPI->CommitPixelShaderLighting( 13 ); + } + + float eyePos[4]; + pShaderAPI->GetWorldSpaceCameraPosition( eyePos ); + pShaderAPI->SetPixelShaderConstant( 20, eyePos, 1 ); + pShaderAPI->SetPixelShaderFogParams( 21 ); + + // flashlightfixme: put this in common code. + if( hasFlashlight ) + { + VMatrix worldToTexture; + const FlashlightState_t &flashlightState = pShaderAPI->GetFlashlightState( worldToTexture ); + + // Set the flashlight attenuation factors + float atten[4]; + atten[0] = flashlightState.m_fConstantAtten; + atten[1] = flashlightState.m_fLinearAtten; + atten[2] = flashlightState.m_fQuadraticAtten; + atten[3] = flashlightState.m_FarZAtten; + pShaderAPI->SetPixelShaderConstant( 22, atten, 1 ); + + // Set the flashlight origin + float pos[4]; + pos[0] = flashlightState.m_vecLightOrigin[0]; + pos[1] = flashlightState.m_vecLightOrigin[1]; + pos[2] = flashlightState.m_vecLightOrigin[2]; + pos[3] = flashlightState.m_FarZ; // didn't have this in main. . probably need this? + pShaderAPI->SetPixelShaderConstant( 23, pos, 1 ); + + pShaderAPI->SetPixelShaderConstant( 24, worldToTexture.Base(), 4 ); + } + } + pShader->Draw(); +} + +// Commenting out this entire file +#endif diff --git a/materialsystem/stdshaders/particlelitgeneric_dx9_helper.h b/materialsystem/stdshaders/particlelitgeneric_dx9_helper.h new file mode 100644 index 00000000..b8380c37 --- /dev/null +++ b/materialsystem/stdshaders/particlelitgeneric_dx9_helper.h @@ -0,0 +1,47 @@ +//========= Copyright © 1996-2005, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef PARTICLELITGENERIC_DX9_HELPER_H +#define PARTICLELITGENERIC_DX9_HELPER_H + +#include + + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct ParticleLitGeneric_DX9_Vars_t +{ + ParticleLitGeneric_DX9_Vars_t() { memset( this, 0xFF, sizeof(ParticleLitGeneric_DX9_Vars_t) ); } + + int m_nBaseTexture; + int m_nBaseTextureFrame; + int m_nBaseTextureTransform; + int m_nBumpmap; + int m_nBumpFrame; + int m_nBumpTransform; + int m_nAlphaTestReference; + int m_nFlashlightTexture; + int m_nFlashlightTextureFrame; +}; + +void InitParamsParticleLitGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, ParticleLitGeneric_DX9_Vars_t &info ); +void InitParticleLitGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, ParticleLitGeneric_DX9_Vars_t &info ); +void DrawParticleLitGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, + IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, ParticleLitGeneric_DX9_Vars_t &info ); + + +#endif // PARTICLELITGENERIC_DX9_HELPER_H \ No newline at end of file diff --git a/materialsystem/stdshaders/particlesphere_dx9.cpp b/materialsystem/stdshaders/particlesphere_dx9.cpp new file mode 100644 index 00000000..8906028b --- /dev/null +++ b/materialsystem/stdshaders/particlesphere_dx9.cpp @@ -0,0 +1,172 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: A wet version of base * lightmap +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" + +#include "particlesphere_vs20.inc" +#include "particlesphere_ps20.inc" +#include "particlesphere_ps20b.inc" + +#include "cpp_shader_constant_register_map.h" + +static ConVar mat_depthfeather_enable( "mat_depthfeather_enable", "1", FCVAR_DEVELOPMENTONLY ); + +int GetDefaultDepthFeatheringValue( void ); //defined in spritecard.cpp + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( ParticleSphere, ParticleSphere_DX9 ) + +BEGIN_VS_SHADER_FLAGS( ParticleSphere_DX9, "Help for BumpmappedEnvMap", SHADER_NOT_EDITABLE ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( DEPTHBLEND, SHADER_PARAM_TYPE_INTEGER, "0", "fade at intersection boundaries" ) + SHADER_PARAM( DEPTHBLENDSCALE, SHADER_PARAM_TYPE_FLOAT, "50.0", "Amplify or reduce DEPTHBLEND fading. Lower values make harder edges." ) + 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, "models/shadertest/shader1_normal", "bumpmap" ) + 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 + + SHADER_INIT_PARAMS() + { + if ( !params[DEPTHBLEND]->IsDefined() ) + { + params[ DEPTHBLEND ]->SetIntValue( GetDefaultDepthFeatheringValue() ); + } + if ( !g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + params[ DEPTHBLEND ]->SetIntValue( 0 ); + } + if ( !params[DEPTHBLENDSCALE]->IsDefined() ) + { + params[ DEPTHBLENDSCALE ]->SetFloatValue( 50.0f ); + } + } + + SHADER_INIT + { + params[USINGPIXELSHADER]->SetIntValue( true ); + LoadBumpMap( BUMPMAP ); + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_DRAW + { + bool bDepthBlend = ( params[DEPTHBLEND]->GetIntValue() != 0 ) && mat_depthfeather_enable.GetBool(); + + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + if ( bDepthBlend ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + } + + int tCoordDimensions[] = {2}; + pShaderShadow->VertexShaderVertexFormat( + VERTEX_POSITION | VERTEX_COLOR, 1, tCoordDimensions, 0 ); + + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + pShaderShadow->EnableDepthWrites( false ); + + DECLARE_STATIC_VERTEX_SHADER( particlesphere_vs20 ); + SET_STATIC_VERTEX_SHADER( particlesphere_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( particlesphere_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( DEPTHBLEND, bDepthBlend ); + SET_STATIC_PIXEL_SHADER( particlesphere_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( particlesphere_ps20 ); + SET_STATIC_PIXEL_SHADER( particlesphere_ps20 ); + } + + FogToFogColor(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BUMPMAP ); + + if ( bDepthBlend ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_FRAME_BUFFER_FULL_DEPTH ); + } + + 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 ); + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + float vEyePos_SpecExponent[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + vEyePos_SpecExponent[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + + pShaderAPI->SetDepthFeatheringPixelShaderConstant( 0, params[DEPTHBLENDSCALE]->GetFloatValue() ); + + // Get viewport and render target dimensions and set shader constant to do a 2D mad + int nViewportX, nViewportY, nViewportWidth, nViewportHeight; + pShaderAPI->GetCurrentViewport( nViewportX, nViewportY, nViewportWidth, nViewportHeight ); + + int nRtWidth, nRtHeight; + pShaderAPI->GetCurrentRenderTargetDimensions( nRtWidth, nRtHeight ); + + float vViewportMad[4]; + vViewportMad[0] = ( float )nViewportWidth / ( float )nRtWidth; + vViewportMad[1] = ( float )nViewportHeight / ( float )nRtHeight; + vViewportMad[2] = ( float )nViewportX / ( float )nRtWidth; + vViewportMad[3] = ( float )nViewportY / ( float )nRtHeight; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_10, vViewportMad, 1 ); + + // Compute the vertex shader index. + DECLARE_DYNAMIC_VERTEX_SHADER( particlesphere_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( FOGTYPE, s_pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER( particlesphere_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( particlesphere_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( particlesphere_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( particlesphere_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( particlesphere_ps20 ); + } + } + Draw(); + } +END_SHADER diff --git a/materialsystem/stdshaders/particlesphere_ps2x.fxc b/materialsystem/stdshaders/particlesphere_ps2x.fxc new file mode 100644 index 00000000..94852361 --- /dev/null +++ b/materialsystem/stdshaders/particlesphere_ps2x.fxc @@ -0,0 +1,66 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "DEPTHBLEND" "0..1" [ps20b] +#include "common_fog_ps_fxc.h" + +#include "shader_constant_register_map.h" + +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT ); + + +const float4 g_DepthFeatheringConstants : register( c0 ); + +sampler BumpmapSampler : register( s0 ); +sampler DepthSampler : register( s1 ); + +struct PS_INPUT +{ + float2 vBumpTexCoord : TEXCOORD0; + float3 vTangentSpaceLightDir : TEXCOORD1; + float3 vAmbientColor : TEXCOORD2; +#if defined( _X360 ) + float4 vScreenPos_ReverseZ : TEXCOORD3; +#else + float4 vScreenPos : TEXCOORD3; +#endif + + float4 vDirLightScale : COLOR0; + + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog +}; + +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; + + //Soft Particles FTW +# if (DEPTHBLEND == 1) +# if defined( _X360 ) + vOutput.a *= DepthFeathering( DepthSampler, i.vScreenPos_ReverseZ.xy / i.vScreenPos_ReverseZ.w, i.vScreenPos_ReverseZ.z, i.vScreenPos_ReverseZ.w, g_DepthFeatheringConstants ); +# else + vOutput.a *= DepthFeathering( DepthSampler, i.vScreenPos.xy / i.vScreenPos.w, i.vScreenPos.z, i.vScreenPos.w, g_DepthFeatheringConstants ); +# endif +# endif + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos_SpecExponent.xyz, i.worldPos_projPosZ.xyz, i.worldPos_projPosZ.w ); + return FinalOutput( vOutput, fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR ); +} + + diff --git a/materialsystem/stdshaders/particlesphere_vs20.fxc b/materialsystem/stdshaders/particlesphere_vs20.fxc new file mode 100644 index 00000000..e2cc75bd --- /dev/null +++ b/materialsystem/stdshaders/particlesphere_vs20.fxc @@ -0,0 +1,135 @@ +// 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 + +const float4 g_vViewportMad : register(SHADER_SPECIFIC_CONST_10); + +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; +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + float fog : FOG; +#endif + float2 vBumpTexCoord : TEXCOORD0; + float3 vTangentSpaceLightDir : TEXCOORD1; + float3 vAmbientColor : TEXCOORD2; + +#if defined( _X360 ) + float4 vScreenPos_ReverseZ : TEXCOORD3; +#else + float4 vScreenPos : TEXCOORD3; +#endif + + + float4 vDirLightScale : COLOR0; + + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = (VS_OUTPUT)0; + + // Transform the input position. + float4 projPos = mul( v.vPos, cModelViewProj ); + o.projPos = projPos; + +#if defined( _X360 ) + o.vScreenPos_ReverseZ.x = projPos.x; + o.vScreenPos_ReverseZ.y = -projPos.y; // invert Y + o.vScreenPos_ReverseZ.xy = (o.vScreenPos_ReverseZ.xy + projPos.w) * 0.5f; + o.vScreenPos_ReverseZ.z = projPos.w - projPos.z; + o.vScreenPos_ReverseZ.w = projPos.w; + + // Adjust for current viewport + o.vScreenPos_ReverseZ.xy = ( ( ( o.vScreenPos_ReverseZ.xy / projPos.w ) * g_vViewportMad.xy ) + g_vViewportMad.zw ) * projPos.w; +#else + o.vScreenPos.x = projPos.x; + o.vScreenPos.y = -projPos.y; // invert Y + o.vScreenPos.xy = (o.vScreenPos.xy + projPos.w) * 0.5f; + o.vScreenPos.z = projPos.z; + o.vScreenPos.w = projPos.w; + + // Adjust for current viewport + o.vScreenPos.xy = ( ( ( o.vScreenPos.xy / projPos.w ) * g_vViewportMad.xy ) + g_vViewportMad.zw ) * projPos.w; +#endif + + o.worldPos_projPosZ = float4( v.vPos.xyz, projPos.z ); + +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + o.fog = CalcFixedFunctionFog( mul( v.vPos, cModel[0] ), g_FogType ); +#endif + + // 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; +} + + diff --git a/materialsystem/stdshaders/phong_dx9_helper.cpp b/materialsystem/stdshaders/phong_dx9_helper.cpp new file mode 100644 index 00000000..a656b55a --- /dev/null +++ b/materialsystem/stdshaders/phong_dx9_helper.cpp @@ -0,0 +1,1039 @@ +//===== Copyright © 1996-2008, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $NoKeywords: $ +// +//===========================================================================// +#include "basevsshader.h" +#include "phong_dx9_helper.h" +#include "convar.h" +#include "cpp_shader_constant_register_map.h" +#include "phong_vs20.inc" +#include "phong_ps20b.inc" +#include "shaderlib/commandbuilder.h" +#include "tier0/vprof.h" + +#ifndef _X360 +#include "phong_vs30.inc" +#include "phong_ps30.inc" +#endif + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +static ConVar mat_fullbright( "mat_fullbright", "0", FCVAR_CHEAT ); +static ConVar mat_displacementmap( "mat_displacementmap", "1", FCVAR_CHEAT ); +static ConVar r_lightwarpidentity( "r_lightwarpidentity", "0", FCVAR_CHEAT ); +static ConVar r_rimlight( "r_rimlight", "1", FCVAR_CHEAT ); + +// Textures may be bound to the following samplers: +// SHADER_SAMPLER0 Base (Albedo) / Gloss in alpha +// SHADER_SAMPLER1 Specular warp (including iridescence) +// SHADER_SAMPLER2 Diffuse Lighting warp texture +// SHADER_SAMPLER3 Normal Map +// SHADER_SAMPLER4 Flashlight Shadow Depth Map +// SHADER_SAMPLER5 Normalization cube map +// SHADER_SAMPLER6 Flashlight Cookie +// SHADER_SAMPLER7 Specular exponent +// SHADER_SAMPLER8 Cubic environment map +// SHADER_SAMPLER9 Compressed wrinklemap +// SHADER_SAMPLER10 Stretched wrinklemap +// SHADER_SAMPLER11 Compressed wrinkle normal map +// SHADER_SAMPLER12 Stretched wrinkle normal map +// SHADER_SAMPLER13 Detail texture +// SHADER_SAMPLER14 Separate self illumination mask +// SHADER_SAMPLER15 Screen space ambient occlusion texture (on PC only) + + +//----------------------------------------------------------------------------- +// Initialize shader parameters +//----------------------------------------------------------------------------- +void InitParamsPhong_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, VertexLitGeneric_DX9_Vars_t &info ) +{ + // FLASHLIGHTFIXME: Do ShaderAPI::BindFlashlightTexture + Assert( info.m_nFlashlightTexture >= 0 ); + + params[FLASHLIGHTTEXTURE]->SetStringValue( GetFlashlightTextureFilename() ); + + // Write over $basetexture with $info.m_nBumpmap if we are going to be using diffuse normal mapping. + if( info.m_nAlbedo != -1 && g_pConfig->UseBumpmapping() && info.m_nBumpmap != -1 && params[info.m_nBumpmap]->IsDefined() && params[info.m_nAlbedo]->IsDefined() && + params[info.m_nBaseTexture]->IsDefined() ) + { + params[info.m_nBaseTexture]->SetStringValue( params[info.m_nAlbedo]->GetStringValue() ); + } + + // This shader can be used with hw skinning + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + + // No texture means no env mask in base alpha + if ( !params[info.m_nBaseTexture]->IsDefined() ) + { + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + // If in decal mode, no debug override... + if (IS_FLAG_SET(MATERIAL_VAR_DECAL)) + { + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + } + + // We always specify we're using user data, therefore we always need tangent spaces + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + bool bBump = (info.m_nBumpmap != -1) && g_pConfig->UseBumpmapping() && params[info.m_nBumpmap]->IsDefined(); + bool bEnvMap = (info.m_nEnvmap != -1) && params[info.m_nEnvmap]->IsDefined(); + bool bDiffuseWarp = (info.m_nDiffuseWarpTexture != -1) && params[info.m_nDiffuseWarpTexture]->IsDefined(); + bool bPhong = (info.m_nPhong != -1) && params[info.m_nPhong]->IsDefined(); + if( !bBump && !bEnvMap && !bDiffuseWarp && !bPhong ) + { + CLEAR_FLAGS( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ); + } + + if ( ( info.m_nSelfIllumFresnelMinMaxExp != -1 ) && ( !params[info.m_nSelfIllumFresnelMinMaxExp]->IsDefined() ) ) + { + params[info.m_nSelfIllumFresnelMinMaxExp]->SetVecValue( 0.0f, 1.0f, 1.0f ); + } + + InitFloatParam( info.m_nEnvmapFresnel, params, 0.0f ); + InitFloatParam( info.m_nAmbientOcclusion, params, 0.0f ); + InitFloatParam( info.m_nDisplacementWrinkleMap, params, 0.0f ); + + InitIntParam( info.m_nSelfIllumFresnel, params, 0 ); + InitIntParam( info.m_nBaseMapAlphaPhongMask, params, 0 ); + InitIntParam( info.m_nBaseMapLuminancePhongMask, params, 0 ); + InitIntParam( info.m_nShaderSrgbRead360, params, 0 ); + InitIntParam( info.m_nAllowDiffuseModulation, params, 1 ); + + InitIntParam( info.m_nPhongDisableHalfLambert, params, 0 ); +} + +//----------------------------------------------------------------------------- +// Initialize shader +//----------------------------------------------------------------------------- +void InitPhong_DX9( CBaseVSShader *pShader, IMaterialVar** params, VertexLitGeneric_DX9_Vars_t &info ) +{ + Assert( info.m_nFlashlightTexture >= 0 ); + pShader->LoadTexture( info.m_nFlashlightTexture ); + + bool bIsBaseTextureTranslucent = false; + if ( params[info.m_nBaseTexture]->IsDefined() ) + { + pShader->LoadTexture( info.m_nBaseTexture ); + + if ( params[info.m_nBaseTexture]->GetTextureValue()->IsTranslucent() ) + { + bIsBaseTextureTranslucent = true; + } + + if ( ( info.m_nWrinkle != -1 ) && ( info.m_nStretch != -1 ) && + params[info.m_nWrinkle]->IsDefined() && params[info.m_nStretch]->IsDefined() ) + { + pShader->LoadTexture( info.m_nWrinkle ); + pShader->LoadTexture( info.m_nStretch ); + } + } + + bool bHasSelfIllumMask = IS_FLAG_SET( MATERIAL_VAR_SELFILLUM ) && IS_FLAG2_SET( MATERIAL_VAR2_SELFILLUMMASK ); + + // No alpha channel in any of the textures? No self illum or envmapmask + if ( !bIsBaseTextureTranslucent ) + { + bool bHasSelfIllumFresnel = IS_FLAG_SET( MATERIAL_VAR_SELFILLUM ) && ( info.m_nSelfIllumFresnel != -1 ) && ( params[info.m_nSelfIllumFresnel]->GetIntValue() != 0 ); + + // Can still be self illum with no base alpha if using one of these alternate modes + if ( !bHasSelfIllumFresnel && !bHasSelfIllumMask ) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + } + + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + if ( (info.m_nPhongExponentTexture != -1) && params[info.m_nPhongExponentTexture]->IsDefined() && + (info.m_nPhong != -1) && params[info.m_nPhong]->IsDefined() ) + { + pShader->LoadTexture( info.m_nPhongExponentTexture ); + } + + if ( (info.m_nDiffuseWarpTexture != -1) && params[info.m_nDiffuseWarpTexture]->IsDefined() && + (info.m_nPhong != -1) && params[info.m_nPhong]->IsDefined() ) + { + pShader->LoadTexture( info.m_nDiffuseWarpTexture ); + } + + if ( (info.m_nPhongWarpTexture != -1) && params[info.m_nPhongWarpTexture]->IsDefined() && + (info.m_nPhong != -1) && params[info.m_nPhong]->IsDefined() ) + { + pShader->LoadTexture( info.m_nPhongWarpTexture ); + } + + if ( info.m_nDetail != -1 && params[info.m_nDetail]->IsDefined() ) + { + int nDetailBlendMode = ( info.m_nDetailTextureCombineMode == -1 ) ? 0 : params[info.m_nDetailTextureCombineMode]->GetIntValue(); + if ( nDetailBlendMode == 0 ) // Mod2X + pShader->LoadTexture( info.m_nDetail ); + else + pShader->LoadTexture( info.m_nDetail ); + } + + if ( g_pConfig->UseBumpmapping() ) + { + if ( (info.m_nBumpmap != -1) && params[info.m_nBumpmap]->IsDefined() ) + { + pShader->LoadBumpMap( info.m_nBumpmap ); + SET_FLAGS2( MATERIAL_VAR2_DIFFUSE_BUMPMAPPED_MODEL ); + + if ( ( info.m_nNormalWrinkle != -1 ) && ( info.m_nNormalStretch != -1 ) && + params[info.m_nNormalWrinkle]->IsDefined() && params[info.m_nNormalStretch]->IsDefined() ) + { + pShader->LoadTexture( info.m_nNormalWrinkle ); + pShader->LoadTexture( info.m_nNormalStretch ); + } + } + } + + if ( params[info.m_nEnvmap]->IsDefined() ) + { + pShader->LoadCubeMap( info.m_nEnvmap ); + } + + if ( bHasSelfIllumMask ) + { + pShader->LoadTexture( info.m_nSelfIllumMask ); + } + + if ( params[info.m_nDisplacementMap]->IsDefined() ) + { + pShader->LoadTexture( info.m_nDisplacementMap ); + } +} + +//----------------------------------------------------------------------------- +// Draws the shader +//----------------------------------------------------------------------------- +class CPhong_DX9_Context : public CBasePerMaterialContextData +{ +public: + CCommandBufferBuilder< CFixedCommandStorageBuffer< 800 > > m_SemiStaticCmdsOut; +}; + +struct PhongShaderInfo_t +{ + bool m_bHasBaseTexture; + bool m_bHasBaseTextureWrinkle; + bool m_bHasBumpWrinkle; + bool m_bHasDiffuseWarp; + bool m_bHasPhong; + bool m_bHasPhongWarp; + bool m_bHasDetailTexture; + bool m_bHasSelfIllum; + bool m_bHasSelfIllumFresnel; + bool m_bHasEnvmap; + bool m_bHasRimLight; +}; + +static void ComputePhongShaderInfo( CBaseVSShader *pShader, IMaterialVar** params, + VertexLitGeneric_DX9_Vars_t &info, bool bHasFlashlightOnly, PhongShaderInfo_t *pInfo ) +{ + pInfo->m_bHasBaseTexture = (info.m_nBaseTexture != -1) && params[info.m_nBaseTexture]->IsTexture(); + pInfo->m_bHasBaseTextureWrinkle = pInfo->m_bHasBaseTexture && + (info.m_nWrinkle != -1) && params[info.m_nWrinkle]->IsTexture() && + (info.m_nStretch != -1) && params[info.m_nStretch]->IsTexture(); + pInfo->m_bHasBumpWrinkle = (info.m_nBumpmap != -1) && params[info.m_nBumpmap]->IsTexture() && + (info.m_nNormalWrinkle != -1) && params[info.m_nNormalWrinkle]->IsTexture() && + (info.m_nNormalStretch != -1) && params[info.m_nNormalStretch]->IsTexture(); + pInfo->m_bHasEnvmap = !bHasFlashlightOnly && params[info.m_nEnvmap]->IsTexture(); + pInfo->m_bHasSelfIllum = IS_FLAG_SET( MATERIAL_VAR_SELFILLUM ) != 0; + pInfo->m_bHasSelfIllumFresnel = ( pInfo->m_bHasSelfIllum ) && ( info.m_nSelfIllumFresnel != -1 ) && ( params[info.m_nSelfIllumFresnel]->GetIntValue() != 0 ); + pInfo->m_bHasPhong = (info.m_nPhong != -1) && ( params[info.m_nPhong]->GetIntValue() != 0 ); + pInfo->m_bHasPhongWarp = (info.m_nPhongWarpTexture != -1) && params[info.m_nPhongWarpTexture]->IsTexture(); + pInfo->m_bHasDiffuseWarp = (info.m_nDiffuseWarpTexture != -1) && params[info.m_nDiffuseWarpTexture]->IsTexture(); + pInfo->m_bHasDetailTexture = ( info.m_nDetail != -1 ) && params[info.m_nDetail]->IsTexture(); + + // Rimlight must be set to non-zero to trigger rim light combo (also requires Phong) + pInfo->m_bHasRimLight = r_rimlight.GetBool() && pInfo->m_bHasPhong && (info.m_nRimLight != -1) && ( params[info.m_nRimLight]->GetIntValue() != 0 ); +} + +void DrawPhong_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, + VertexLitGeneric_DX9_Vars_t &info, VertexCompressionType_t vertexCompression, CBasePerMaterialContextData **pContextDataPtr ) +{ + CPhong_DX9_Context *pContextData = reinterpret_cast< CPhong_DX9_Context *> ( *pContextDataPtr ); + + bool bHasFlashlight = pShader->UsingFlashlight( params ); + bool bHasFlashlightOnly = bHasFlashlight && !IsX360(); +#ifndef _X360 + bool bIsDecal = IS_FLAG_SET( MATERIAL_VAR_DECAL ); +#endif + bool bIsAlphaTested = IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) != 0; + BlendType_t nBlendType = pShader->EvaluateBlendRequirements( info.m_nBaseTexture, true ); + bool bFullyOpaque = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !bIsAlphaTested && !bHasFlashlightOnly; //dest alpha is free for special use + bool bHasDisplacement = (info.m_nDisplacementMap != -1) && params[info.m_nDisplacementMap]->IsTexture(); +#if !defined( PLATFORM_X360 ) + bool bHasDisplacementWrinkles = (info.m_nDisplacementWrinkleMap != -1) && params[info.m_nDisplacementWrinkleMap]->GetIntValue(); +#endif + + if( pShader->IsSnapshotting() ) + { + PhongShaderInfo_t phongInfo; + ComputePhongShaderInfo( pShader, params, info, bHasFlashlightOnly, &phongInfo ); + + bool bShaderSrgbRead = ( IsX360() && IS_PARAM_DEFINED( info.m_nShaderSrgbRead360 ) && params[info.m_nShaderSrgbRead360]->GetIntValue() ); + int nDetailBlendMode = ( info.m_nDetailTextureCombineMode == -1 ) ? 0 : params[info.m_nDetailTextureCombineMode]->GetIntValue(); + bool bHasVertexColor = IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR ); + bool bHasVertexAlpha = IS_FLAG_SET( MATERIAL_VAR_VERTEXALPHA ); + + // look at color and alphamod stuff. + // Unlit generic never uses the flashlight + bool bHasEnvmap = !bHasFlashlightOnly && params[info.m_nEnvmap]->IsTexture(); + + // Alpha test: FIXME: shouldn't this be handled in CBaseVSShader::SetInitialShadowState + pShaderShadow->EnableAlphaTest( bIsAlphaTested ); + + if( info.m_nAlphaTestReference != -1 && params[info.m_nAlphaTestReference]->GetFloatValue() > 0.0f ) + { + pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GEQUAL, params[info.m_nAlphaTestReference]->GetFloatValue() ); + } + + // Based upon vendor and device dependent formats + int nShadowFilterMode = bHasFlashlight ? g_pHardwareConfig->GetShadowFilterMode() : 0; + if( bHasFlashlightOnly ) + { + if (params[info.m_nBaseTexture]->IsTexture()) + { + pShader->SetAdditiveBlendingShadowState( info.m_nBaseTexture, true ); + } + + if( bIsAlphaTested ) + { + // disable alpha test and use the zfunc zequals since alpha isn't guaranteed to + // be the same on both the regular pass and the flashlight pass. + pShaderShadow->EnableAlphaTest( false ); + pShaderShadow->DepthFunc( SHADER_DEPTHFUNC_EQUAL ); + } + pShaderShadow->EnableBlending( true ); + pShaderShadow->EnableDepthWrites( false ); + + // Be sure not to write to dest alpha + pShaderShadow->EnableAlphaWrites( false ); + } + + if ( !bHasFlashlightOnly ) // not flashlight pass + { + if (params[info.m_nBaseTexture]->IsTexture()) + { + pShader->SetDefaultBlendingShadowState( info.m_nBaseTexture, true ); + } + + if ( bHasEnvmap ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER8, true ); // Cubic environment map + if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ) + { + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER8, true ); + } + } + } + + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL; + int userDataSize = 0; + + // Always enable...will bind white if nothing specified... + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); // Base (albedo) map + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, !bShaderSrgbRead ); + + if ( phongInfo.m_bHasBaseTextureWrinkle ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER9, true ); // Base (albedo) compression map + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER9, !bShaderSrgbRead ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER10, true ); // Base (albedo) stretch map + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER10, !bShaderSrgbRead ); + } + + if( phongInfo.m_bHasDiffuseWarp ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); // Diffuse warp texture + } + + if( phongInfo.m_bHasPhongWarp ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); // Specular warp texture + } + + // Specular exponent map or dummy + pShaderShadow->EnableTexture( SHADER_SAMPLER7, true ); // Specular exponent map + + if( bHasFlashlight ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); // Shadow depth map + pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER4 ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER4, false ); + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); // Noise map + pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); // Flashlight cookie + } + + // Always enable, since flat normal will be bound + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); // Normal map + userDataSize = 4; // tangent S + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); // Normalizing cube map + + if ( phongInfo.m_bHasBumpWrinkle || phongInfo.m_bHasBaseTextureWrinkle ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER11, true ); // Normal compression map + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER11, false ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER12, true ); // Normal stretch map + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER12, false ); + } + + if ( phongInfo.m_bHasDetailTexture ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER13, true ); + if ( nDetailBlendMode != 0 ) //Not Mod2X + { + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER13, true ); + } + } + + if ( phongInfo.m_bHasSelfIllum ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER14, true ); + } + + if( bHasVertexColor || bHasVertexAlpha ) + { + flags |= VERTEX_COLOR; + } + + // Always enable ambient occlusion sampler on PC on DX10 parts + if ( IsPC() && g_pHardwareConfig->HasFastVertexTextures() ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER15, true ); + } + + if ( bHasDisplacement && IsPC() && g_pHardwareConfig->HasFastVertexTextures() ) + { + pShaderShadow->EnableVertexTexture( SHADER_VERTEXTEXTURE_SAMPLER2, true ); + } + + pShaderShadow->EnableSRGBWrite( true ); + + // texcoord0 : base texcoord, texcoord2 : decal hw morph delta + int pTexCoordDim[3] = { 2, 0, 3 }; + int nTexCoordCount = 1; + +#ifndef _X360 + // Special morphed decal information + if ( bIsDecal && g_pHardwareConfig->HasFastVertexTextures() ) + { + nTexCoordCount = 3; + } +#endif + + // This shader supports compressed vertices, so OR in that flag: + flags |= VERTEX_FORMAT_COMPRESSED; + + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, pTexCoordDim, userDataSize ); + +#if !defined( PLATFORM_X360 ) + bool bWorldNormal = ( ENABLE_FIXED_LIGHTING_OUTPUTNORMAL_AND_DEPTH == ( IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER0 ) + 2 * IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER1 ))); +#endif + + // This is to allow phong materials to disable half lambert. Half lambert has always been forced on in phong, + // so the only safe way to allow artists to disable half lambert is to create this param that disables the + // default behavior of forcing half lambert on. + bool bPhongHalfLambert = IS_PARAM_DEFINED( info.m_nPhongDisableHalfLambert ) ? ( params[ info.m_nPhongDisableHalfLambert ]->GetIntValue() == 0 ) : true; + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_STATIC_VERTEX_SHADER( phong_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( WORLD_NORMAL, 0 ); + SET_STATIC_VERTEX_SHADER( phong_vs20 ); + + // Assume we're only going to get in here if we support 2b + DECLARE_STATIC_PIXEL_SHADER( phong_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, phongInfo.m_bHasSelfIllum && !bHasFlashlightOnly ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUMFRESNEL, phongInfo.m_bHasSelfIllumFresnel && !bHasFlashlightOnly ); + SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, phongInfo.m_bHasDiffuseWarp && phongInfo.m_bHasPhong ); + SET_STATIC_PIXEL_SHADER_COMBO( PHONGWARPTEXTURE, phongInfo.m_bHasPhongWarp && phongInfo.m_bHasPhong ); + SET_STATIC_PIXEL_SHADER_COMBO( WRINKLEMAP, phongInfo.m_bHasBaseTextureWrinkle ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, phongInfo.m_bHasDetailTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode ); + SET_STATIC_PIXEL_SHADER_COMBO( RIMLIGHT, phongInfo.m_bHasRimLight ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER_COMBO( SHADER_SRGB_READ, bShaderSrgbRead ); + SET_STATIC_PIXEL_SHADER_COMBO( WORLD_NORMAL, 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( PHONG_HALFLAMBERT, bPhongHalfLambert ); + SET_STATIC_PIXEL_SHADER( phong_ps20b ); + } +#ifndef _X360 + else + { + // The vertex shader uses the vertex id stream + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_TESSELLATION ); + + DECLARE_STATIC_VERTEX_SHADER( phong_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( WORLD_NORMAL, bWorldNormal ); + SET_STATIC_VERTEX_SHADER_COMBO( DECAL, bIsDecal ); + SET_STATIC_VERTEX_SHADER( phong_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( phong_ps30 ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, phongInfo.m_bHasSelfIllum && !bHasFlashlightOnly ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUMFRESNEL, phongInfo.m_bHasSelfIllumFresnel && !bHasFlashlightOnly ); + SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, phongInfo.m_bHasDiffuseWarp && phongInfo.m_bHasPhong ); + SET_STATIC_PIXEL_SHADER_COMBO( PHONGWARPTEXTURE, phongInfo.m_bHasPhongWarp && phongInfo.m_bHasPhong ); + SET_STATIC_PIXEL_SHADER_COMBO( WRINKLEMAP, phongInfo.m_bHasBaseTextureWrinkle ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, phongInfo.m_bHasDetailTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode ); + SET_STATIC_PIXEL_SHADER_COMBO( RIMLIGHT, phongInfo.m_bHasRimLight ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER_COMBO( SHADER_SRGB_READ, bShaderSrgbRead ); + SET_STATIC_PIXEL_SHADER_COMBO( WORLD_NORMAL, bWorldNormal ); + SET_STATIC_PIXEL_SHADER_COMBO( PHONG_HALFLAMBERT, bPhongHalfLambert ); + SET_STATIC_PIXEL_SHADER( phong_ps30 ); + } +#endif + + if( bHasFlashlightOnly ) + { + pShader->FogToBlack(); + } + else + { + pShader->DefaultFog(); + } + + // HACK HACK HACK - enable alpha writes all the time so that we have them for underwater stuff + pShaderShadow->EnableAlphaWrites( bFullyOpaque ); + + pShader->PI_BeginCommandBuffer(); + pShader->PI_SetPixelShaderAmbientLightCube( PSREG_AMBIENT_CUBE ); + pShader->PI_SetPixelShaderLocalLighting( PSREG_LIGHT_INFO_ARRAY ); + pShader->PI_SetVertexShaderAmbientLightCube(); + // material can opt out of per-instance modulation via $nodiffusemodulation + bool bAllowDiffuseModulation = ( info.m_nAllowDiffuseModulation == -1 ) ? true : ( params[info.m_nAllowDiffuseModulation]->GetIntValue() != 0 ); + if ( bAllowDiffuseModulation ) + { + pShader->PI_SetModulationPixelShaderDynamicState_LinearColorSpace( 1 ); + } + else + { + pShader->PI_SetModulationPixelShaderDynamicState_Identity( 1 ); + } + pShader->PI_EndCommandBuffer(); + } + else // not snapshotting -- begin dynamic state + { + // Deal with semisatic + if ( ( !pContextData ) || ( pContextData->m_bMaterialVarsChanged ) ) + { + if ( !pContextData ) // make sure allocated + { + pContextData = new CPhong_DX9_Context; + *pContextDataPtr = pContextData; + } + + pContextData->m_SemiStaticCmdsOut.Reset(); + pContextData->m_bMaterialVarsChanged = false; + + PhongShaderInfo_t phongInfo; + ComputePhongShaderInfo( pShader, params, info, bHasFlashlightOnly, &phongInfo ); + + bool bHasBump = (info.m_nBumpmap != -1) && params[info.m_nBumpmap]->IsTexture(); + bool bLightingOnly = mat_fullbright.GetInt() == 2 && !IS_FLAG_SET( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + bool bHasSelfIllumMask = ( phongInfo.m_bHasSelfIllum ) && (info.m_nSelfIllumMask != -1) && params[info.m_nSelfIllumMask]->IsTexture(); + float fBlendFactor = ( info.m_nDetailTextureBlendFactor == -1 )? 1 : params[info.m_nDetailTextureBlendFactor]->GetFloatValue(); + bool bHasSpecularExponentTexture = (info.m_nPhongExponentTexture != -1) && params[info.m_nPhongExponentTexture]->IsTexture(); + bool bHasPhongTintMap = bHasSpecularExponentTexture && (info.m_nPhongAlbedoTint != -1) && ( params[info.m_nPhongAlbedoTint]->GetIntValue() != 0 ); + bool bHasNormalMapAlphaEnvmapMask = IS_FLAG_SET( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ); + bool bHasRimMaskMap = bHasSpecularExponentTexture && phongInfo.m_bHasRimLight && (info.m_nRimMask != -1) && ( params[info.m_nRimMask]->GetIntValue() != 0 ); + bool bHasSinglePassFlashlight = IsX360(); // NOTE: If you change this, fix state.m_nDepthTweakConstant below! And, deal with SINGLE_PASS_FLASHLIGHT in phong_ps20b.fxc + + if( phongInfo.m_bHasBaseTexture ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER0, info.m_nBaseTexture, info.m_nBaseTextureFrame ); + } + else + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_WHITE ); + } + + if ( phongInfo.m_bHasBaseTextureWrinkle ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER9, info.m_nWrinkle, info.m_nBaseTextureFrame ); + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER10, info.m_nStretch, info.m_nBaseTextureFrame ); + } + + if( phongInfo.m_bHasDiffuseWarp && phongInfo.m_bHasPhong ) + { + if ( r_lightwarpidentity.GetBool() ) + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER2, TEXTURE_IDENTITY_LIGHTWARP ); + } + else + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER2, info.m_nDiffuseWarpTexture ); + } + } + + if( phongInfo.m_bHasPhongWarp ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER1, info.m_nPhongWarpTexture ); + } + + if( bHasSpecularExponentTexture && phongInfo.m_bHasPhong ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER7, info.m_nPhongExponentTexture ); + } + else + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER7, TEXTURE_WHITE ); + } + + if( !g_pConfig->m_bFastNoBump ) + { + if( bHasBump ) + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER3, info.m_nBumpmap, info.m_nBumpFrame ); + else + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER3, TEXTURE_NORMALMAP_FLAT ); + + if ( phongInfo.m_bHasBumpWrinkle ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER11, info.m_nNormalWrinkle, info.m_nBumpFrame ); + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER12, info.m_nNormalStretch, info.m_nBumpFrame ); + } + else if ( phongInfo.m_bHasBaseTextureWrinkle ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER11, info.m_nBumpmap, info.m_nBumpFrame ); + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER12, info.m_nBumpmap, info.m_nBumpFrame ); + } + } + else // Just flat bump maps + { + if ( bHasBump ) + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER3, TEXTURE_NORMALMAP_FLAT ); + } + + if ( phongInfo.m_bHasBaseTextureWrinkle || phongInfo.m_bHasBumpWrinkle ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER11, TEXTURE_NORMALMAP_FLAT ); + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER12, TEXTURE_NORMALMAP_FLAT ); + } + } + + if ( phongInfo.m_bHasDetailTexture ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER13, info.m_nDetail, info.m_nDetailFrame ); + } + + if ( phongInfo.m_bHasSelfIllum ) + { + if ( bHasSelfIllumMask ) // Separate texture for self illum? + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER14, info.m_nSelfIllumMask ); // Bind it + } + else // else + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER14, TEXTURE_BLACK ); // Bind dummy + } + } + + if( !bHasFlashlightOnly ) + { + if ( phongInfo.m_bHasEnvmap ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER8, info.m_nEnvmap, info.m_nEnvmapFrame ); + } + } + + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, info.m_nBaseTextureTransform ); + + if( bHasBump ) + { + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, info.m_nBumpTransform ); + } + + if ( phongInfo.m_bHasDetailTexture ) + { + if ( IS_PARAM_DEFINED( info.m_nDetailTextureTransform ) ) + { + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, + info.m_nDetailTextureTransform, + info.m_nDetailScale ); + } + else + { + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, + info.m_nBaseTextureTransform, + info.m_nDetailScale ); + } + } + + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant_W( PSREG_SELFILLUMTINT, info.m_nSelfIllumTint, fBlendFactor ); + bool bInvertPhongMask = ( info.m_nInvertPhongMask != -1 ) && ( params[info.m_nInvertPhongMask]->GetIntValue() != 0 ); + float fInvertPhongMask = bInvertPhongMask ? 1 : 0; + + bool bHasBaseAlphaPhongMask = (info.m_nBaseMapAlphaPhongMask != -1) && ( params[info.m_nBaseMapAlphaPhongMask]->GetIntValue() != 0 ); + float fHasBaseAlphaPhongMask = bHasBaseAlphaPhongMask ? 1 : 0; + bool bBlendTintByBaseAlpha = (info.m_nBlendTintByBaseAlpha != -1) && ( params[info.m_nBlendTintByBaseAlpha]->GetIntValue() != 0 ); + float fBlendTintByBaseAlpha = bBlendTintByBaseAlpha ? 1 : 0; + + // Controls for lerp-style paths through shader code + float vShaderControls[4] = { fHasBaseAlphaPhongMask, 0.0f, 1.0f-fBlendTintByBaseAlpha, fInvertPhongMask }; + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( PSREG_SHADER_CONTROLS, vShaderControls, 1 ); + + if ( phongInfo.m_bHasSelfIllumFresnel && !bHasFlashlightOnly ) + { + float vConstScaleBiasExp[4] = { 1.0f, 0.0f, 1.0f, 0.0f }; + float flMin = IS_PARAM_DEFINED( info.m_nSelfIllumFresnelMinMaxExp ) ? params[info.m_nSelfIllumFresnelMinMaxExp]->GetVecValue()[0] : 0.0f; + float flMax = IS_PARAM_DEFINED( info.m_nSelfIllumFresnelMinMaxExp ) ? params[info.m_nSelfIllumFresnelMinMaxExp]->GetVecValue()[1] : 1.0f; + float flExp = IS_PARAM_DEFINED( info.m_nSelfIllumFresnelMinMaxExp ) ? params[info.m_nSelfIllumFresnelMinMaxExp]->GetVecValue()[2] : 1.0f; + + vConstScaleBiasExp[1] = ( flMax != 0.0f ) ? ( flMin / flMax ) : 0.0f; // Bias + vConstScaleBiasExp[0] = 1.0f - vConstScaleBiasExp[1]; // Scale + vConstScaleBiasExp[2] = flExp; // Exp + vConstScaleBiasExp[3] = flMax; // Brightness + + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( PSREG_SELFILLUM_SCALE_BIAS_EXP, vConstScaleBiasExp, 1 ); + } + + if( !bHasFlashlightOnly ) + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER5, TEXTURE_NORMALIZATION_CUBEMAP_SIGNED ); + + if( phongInfo.m_bHasEnvmap ) + { + float vEnvMapTint_MaskControl[4] = {1.0f, 1.0f, 1.0f, 0.0f}; + + // If we have a tint, grab it + if ( (info.m_nEnvmapTint != -1) && params[info.m_nEnvmapTint]->IsDefined() ) + params[info.m_nEnvmapTint]->GetVecValue(vEnvMapTint_MaskControl, 3); + + // Set control for source of env map mask (normal alpha or base alpha) + vEnvMapTint_MaskControl[3] = bHasNormalMapAlphaEnvmapMask ? 1.0f : 0.0f; + + // Handle mat_fullbright 2 (diffuse lighting only with 50% gamma space basetexture) + if( bLightingOnly ) + { + vEnvMapTint_MaskControl[0] = vEnvMapTint_MaskControl[1] = vEnvMapTint_MaskControl[2] = 0.0f; + } + + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( PSREG_ENVMAP_TINT__SHADOW_TWEAKS, vEnvMapTint_MaskControl, 1 ); + } + } + + // Pack Phong exponent in with the eye position + float vSpecularTint[4] = {1, 1, 1, 4}; + float vFresnelRanges_SpecBoost[4] = {0, 0.5, 1, 1}, vRimBoost[4] = {1, 1, 1, 1}; + + // Get the tint parameter + if ( (info.m_nPhongTint != -1) && params[info.m_nPhongTint]->IsDefined() ) + { + params[info.m_nPhongTint]->GetVecValue(vSpecularTint, 3); + } + + // Get the rim light power (goes in w of Phong tint) + if ( phongInfo.m_bHasRimLight && (info.m_nRimLightPower != -1) && params[info.m_nRimLightPower]->IsDefined() ) + { + vSpecularTint[3] = params[info.m_nRimLightPower]->GetFloatValue(); + vSpecularTint[3] = MAX(vSpecularTint[3], 1.0f); // Make sure this is at least 1 + } + + // Get the rim boost (goes in w of flashlight position) + if ( phongInfo.m_bHasRimLight && (info.m_nRimLightBoost != -1) && params[info.m_nRimLightBoost]->IsDefined() ) + { + vRimBoost[3] = params[info.m_nRimLightBoost]->GetFloatValue(); + } + + // Single pass flashlight has to use a separate constant for this stuff since a flashlight constant is repurposed for rimlighting when doing multi-pass flashlight. + if ( phongInfo.m_bHasRimLight ) + { + if ( bHasSinglePassFlashlight ) + { + float vRimParams[4] = {0, 0, 0, 0}; + vRimParams[0] = bHasRimMaskMap ? params[info.m_nRimMask]->GetFloatValue() : 0.0f; + vRimParams[1] = params[info.m_nRimLightBoost]->GetFloatValue(); + + // Rim mask...if this is true, use alpha channel of spec exponent texture to mask the rim term + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( PSREG_RIMPARAMS, vRimParams, 1 ); + } + else if ( !bHasFlashlight ) + { + float vRimMaskControl[4] = {0, 0, 0, 0}; // Only x is relevant in shader code + vRimMaskControl[0] = bHasRimMaskMap ? params[info.m_nRimMask]->GetFloatValue() : 0.0f; + + // Rim mask...if this is true, use alpha channel of spec exponent texture to mask the rim term + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( PSREG_FLASHLIGHT_ATTENUATION, vRimMaskControl, 1 ); + } + } + + // If it's all zeros, there was no constant tint in the vmt + if ( (vSpecularTint[0] == 0.0f) && (vSpecularTint[1] == 0.0f) && (vSpecularTint[2] == 0.0f) ) + { + if ( bHasPhongTintMap ) // If we have a map to use, tell the shader + { + vSpecularTint[0] = -1; + } + else // Otherwise, just tint with white + { + vSpecularTint[0] = 1.0f; + vSpecularTint[1] = 1.0f; + vSpecularTint[2] = 1.0f; + } + } + + // handle mat_fullbright 2 (diffuse lighting only) + if( bLightingOnly ) + { + // BASETEXTURE + if( phongInfo.m_bHasSelfIllum && !bHasFlashlightOnly ) + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY_ALPHA_ZERO ); + + if ( phongInfo.m_bHasBaseTextureWrinkle || phongInfo.m_bHasBumpWrinkle ) + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER9, TEXTURE_GREY_ALPHA_ZERO ); // Compressed wrinklemap + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER10, TEXTURE_GREY_ALPHA_ZERO ); // Stretched wrinklemap + } + } + else + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY ); + + if ( phongInfo.m_bHasBaseTextureWrinkle || phongInfo.m_bHasBumpWrinkle ) + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER9, TEXTURE_GREY ); // Compressed wrinklemap + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER10, TEXTURE_GREY ); // Stretched wrinklemap + } + } + + // DETAILTEXTURE + if ( phongInfo.m_bHasDetailTexture ) + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER13, TEXTURE_GREY ); + } + + // turn off specularity + vSpecularTint[0] = vSpecularTint[1] = vSpecularTint[2] = 0.0f; + } + + if ( (info.m_nPhongFresnelRanges != -1) && params[info.m_nPhongFresnelRanges]->IsDefined() ) + { + params[info.m_nPhongFresnelRanges]->GetVecValue( vFresnelRanges_SpecBoost, 3 ); // Grab optional Fresnel range parameters + } + + if ( (info.m_nPhongBoost != -1 ) && params[info.m_nPhongBoost]->IsDefined()) // Grab optional Phong boost param + { + vFresnelRanges_SpecBoost[3] = params[info.m_nPhongBoost]->GetFloatValue(); + } + else + { + vFresnelRanges_SpecBoost[3] = 1.0f; + } + + bool bHasBaseLuminancePhongMask = (info.m_nBaseMapLuminancePhongMask != -1) && ( params[info.m_nBaseMapLuminancePhongMask]->GetIntValue() != 0 ); + float fHasBaseLuminancePhongMask = bHasBaseLuminancePhongMask ? 1 : 0; + float vShaderControls2[4] = {0.0f, fHasBaseLuminancePhongMask, 0.0f, 0.0f}; + if ( !bHasFlashlightOnly ) + { + if ( phongInfo.m_bHasEnvmap ) + { + if ( (info.m_nEnvmapFresnel != -1) && params[info.m_nEnvmapFresnel]->IsDefined() ) + { + vShaderControls2[0] = params[info.m_nEnvmapFresnel]->GetFloatValue(); + } + } + } + if ( (info.m_nPhongExponent != -1) && params[info.m_nPhongExponent]->IsDefined() ) + { + vShaderControls2[2] = params[info.m_nPhongExponent]->GetFloatValue(); // This overrides the channel in the map + } + else + { + vShaderControls2[2] = 0; // Use the alpha channel of the normal map for the exponent + } + + vShaderControls2[3] = bHasSelfIllumMask ? 1.0f : 0.0f; + + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( PSREG_FRESNEL_SPEC_PARAMS, vFresnelRanges_SpecBoost, 1 ); + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( PSREG_FLASHLIGHT_POSITION_RIM_BOOST, vRimBoost, 1 ); // Rim boost in w on non-flashlight pass + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( PSREG_SPEC_RIM_PARAMS, vSpecularTint, 1 ); + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( PSREG_SHADER_CONTROLS_2, vShaderControls2, 1 ); + + pContextData->m_SemiStaticCmdsOut.SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + if ( bHasFlashlight ) + { + CBCmdSetPixelShaderFlashlightState_t state; + state.m_LightSampler = SHADER_SAMPLER6; + state.m_DepthSampler = SHADER_SAMPLER4; + state.m_ShadowNoiseSampler = SHADER_SAMPLER5; + state.m_nColorConstant = PSREG_FLASHLIGHT_COLOR; + state.m_nAttenConstant = PSREG_FLASHLIGHT_ATTENUATION; + state.m_nOriginConstant = PSREG_FLASHLIGHT_POSITION_RIM_BOOST; + state.m_nDepthTweakConstant = bHasSinglePassFlashlight ? 43 : PSREG_ENVMAP_TINT__SHADOW_TWEAKS; // NOTE: Reg 43 not available on < ps3.0! + state.m_nScreenScaleConstant = PSREG_FLASHLIGHT_SCREEN_SCALE; + state.m_nWorldToTextureConstant = PSREG_FLASHLIGHT_TO_WORLD_TEXTURE; + state.m_bFlashlightNoLambert = false; + state.m_bSinglePassFlashlight = bHasSinglePassFlashlight; + pContextData->m_SemiStaticCmdsOut.SetPixelShaderFlashlightState( state ); + + if ( !IsX360() && ( g_pHardwareConfig->GetDXSupportLevel() > 92 ) ) + { + pContextData->m_SemiStaticCmdsOut.SetPixelShaderUberLightState( + PSREG_UBERLIGHT_SMOOTH_EDGE_0, PSREG_UBERLIGHT_SMOOTH_EDGE_1, + PSREG_UBERLIGHT_SMOOTH_EDGE_OOW, PSREG_UBERLIGHT_SHEAR_ROUND, + PSREG_UBERLIGHT_AABB, PSREG_UBERLIGHT_WORLD_TO_LIGHT ); + } + } + pContextData->m_SemiStaticCmdsOut.End(); + } + + CCommandBufferBuilder< CFixedCommandStorageBuffer< 1000 > > DynamicCmdsOut; + DynamicCmdsOut.Call( pContextData->m_SemiStaticCmdsOut.Base() ); + + // On PC, we sample from ambient occlusion texture + if ( IsPC() && g_pHardwareConfig->HasFastVertexTextures() ) + { + ITexture *pAOTexture = pShaderAPI->GetTextureRenderingParameter( TEXTURE_RENDERPARM_AMBIENT_OCCLUSION ); + + if ( pAOTexture ) + { + DynamicCmdsOut.BindTexture( pShader, SHADER_SAMPLER15, pAOTexture, 0 ); + } + else + { + DynamicCmdsOut.BindStandardTexture( SHADER_SAMPLER15, TEXTURE_WHITE ); + } + } + + bool bFlashlightShadows = false; + bool bUberlight = false; + float flAmbientOcclusionStrength = ( info.m_nAmbientOcclusion == -1 ) ? 0.0f : params[info.m_nAmbientOcclusion]->GetFloatValue(); + if ( bHasFlashlight ) + { + pShaderAPI->GetFlashlightShaderInfo( &bFlashlightShadows, &bUberlight ); + flAmbientOcclusionStrength *= pShaderAPI->GetFlashlightAmbientOcclusion(); + } + + float vEyePos_AmbientOcclusion[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_AmbientOcclusion ); + vEyePos_AmbientOcclusion[3] = clamp( flAmbientOcclusionStrength, 0.0f, 1.0f ); + DynamicCmdsOut.SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_AmbientOcclusion, 1 ); + + MaterialFogMode_t fogType = pShaderAPI->GetSceneFogMode(); + int numBones = pShaderAPI->GetCurrentNumBones(); + + bool bWriteDepthToAlpha = false; + bool bWriteWaterFogToAlpha = false; + + if( bFullyOpaque ) + { + bWriteDepthToAlpha = pShaderAPI->ShouldWriteDepthToDestAlpha(); + bWriteWaterFogToAlpha = (fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z); + AssertMsg( !(bWriteDepthToAlpha && bWriteWaterFogToAlpha), "Can't write two values to alpha at the same time." ); + } + + LightState_t lightState = { 0, false, false }; + if( !bHasFlashlightOnly ) + { + pShaderAPI->GetDX9LightState( &lightState ); + } + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_DYNAMIC_VERTEX_SHADER( phong_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, numBones > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( TESSELLATION, 0 ); + SET_DYNAMIC_VERTEX_SHADER( phong_vs20 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( phong_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bWriteDepthToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER( phong_ps20b ); + } +#ifndef _X360 + else + { + pShader->SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, SHADER_VERTEXTEXTURE_SAMPLER0 ); + + int nLightingPreviewMode = pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_ENABLE_FIXED_LIGHTING ); + if ( ( nLightingPreviewMode == ENABLE_FIXED_LIGHTING_OUTPUTNORMAL_AND_DEPTH ) && IsPC() ) + { + float vEyeDir[4]; + pShaderAPI->GetWorldSpaceCameraDirection( vEyeDir ); + + float flFarZ = pShaderAPI->GetFarZ(); + vEyeDir[0] /= flFarZ; // Divide by farZ for SSAO algorithm + vEyeDir[1] /= flFarZ; + vEyeDir[2] /= flFarZ; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_8, vEyeDir ); + } + + TessellationMode_t nTessellationMode = pShaderAPI->GetTessellationMode(); + if ( nTessellationMode != TESSELLATION_MODE_DISABLED ) + { + pShaderAPI->BindStandardVertexTexture( SHADER_VERTEXTEXTURE_SAMPLER1, TEXTURE_SUBDIVISION_PATCHES ); + + + + float vSubDDimensions[4] = { 1.0f/pShaderAPI->GetSubDHeight(), + bHasDisplacement && mat_displacementmap.GetBool() ? 1.0f : 0.0f, + bHasDisplacementWrinkles && mat_displacementmap.GetBool() ? 1.0f : 0.0f, 0.0f }; + + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_9, vSubDDimensions ); + if( bHasDisplacement ) + { + pShader->BindVertexTexture( SHADER_VERTEXTEXTURE_SAMPLER2, info.m_nDisplacementMap ); + } + else + { + pShaderAPI->BindStandardVertexTexture( SHADER_VERTEXTEXTURE_SAMPLER2, TEXTURE_BLACK ); + } + + // Currently, tessellation is mutually exclusive with any kind of GPU-side skinning, morphing or vertex compression + Assert( !pShaderAPI->IsHWMorphingEnabled() ); + Assert( numBones == 0 ); + Assert( vertexCompression == 0); + } + DECLARE_DYNAMIC_VERTEX_SHADER( phong_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, ( numBones > 0) && ( nTessellationMode == TESSELLATION_MODE_DISABLED ) ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression && ( nTessellationMode == TESSELLATION_MODE_DISABLED ) ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( TESSELLATION, nTessellationMode ); + SET_DYNAMIC_VERTEX_SHADER( phong_vs30 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( phong_ps30 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, nLightingPreviewMode ? 0 : lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, nLightingPreviewMode ? false : bWriteWaterFogToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bWriteDepthToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, nLightingPreviewMode ? false : bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( UBERLIGHT, bUberlight ); + SET_DYNAMIC_PIXEL_SHADER( phong_ps30 ); + + bool bUnusedTexCoords[3] = { false, false, !pShaderAPI->IsHWMorphingEnabled() || !bIsDecal }; + pShaderAPI->MarkUnusedVertexFields( 0, 3, bUnusedTexCoords ); + + // Set constant to enable translation of VPOS to render target coordinates in ps_3_0 + pShaderAPI->SetScreenSizeForVPOS(); + } +#endif + + DynamicCmdsOut.End(); + pShaderAPI->ExecuteCommandBuffer( DynamicCmdsOut.Base() ); + } + pShader->Draw(); +} diff --git a/materialsystem/stdshaders/phong_dx9_helper.h b/materialsystem/stdshaders/phong_dx9_helper.h new file mode 100644 index 00000000..26beb3d7 --- /dev/null +++ b/materialsystem/stdshaders/phong_dx9_helper.h @@ -0,0 +1,28 @@ +//========= Copyright © 1996-2008, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef PHONG_DX9_HELPER_H +#define PHONG_DX9_HELPER_H + +#include + +#include "vertexlitgeneric_dx9_helper.h" + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + +void InitParamsPhong_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, VertexLitGeneric_DX9_Vars_t &info ); +void InitPhong_DX9( CBaseVSShader *pShader, IMaterialVar** params, VertexLitGeneric_DX9_Vars_t &info ); +void DrawPhong_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, + VertexLitGeneric_DX9_Vars_t &info, VertexCompressionType_t vertexCompression, CBasePerMaterialContextData **pContextDataPtr ); + +#endif // PHONG_DX9_HELPER_H diff --git a/materialsystem/stdshaders/phong_ps20b.fxc b/materialsystem/stdshaders/phong_ps20b.fxc new file mode 100644 index 00000000..9ad68671 --- /dev/null +++ b/materialsystem/stdshaders/phong_ps20b.fxc @@ -0,0 +1,479 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "CUBEMAP" "0..1" +// STATIC: "SELFILLUM" "0..1" +// STATIC: "SELFILLUMFRESNEL" "0..1" +// STATIC: "FLASHLIGHT" "0..1" +// STATIC: "LIGHTWARPTEXTURE" "0..1" +// STATIC: "PHONGWARPTEXTURE" "0..1" +// STATIC: "WRINKLEMAP" "0..1" +// STATIC: "DETAIL_BLEND_MODE" "0..6" +// STATIC: "DETAILTEXTURE" "0..1" +// STATIC: "RIMLIGHT" "0..1" +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps20b] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps30] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..0" [ps20b] [XBOX] +// STATIC: "SHADER_SRGB_READ" "0..1" [XBOX] +// STATIC: "SHADER_SRGB_READ" "0..0" [PC] +// STATIC: "WORLD_NORMAL" "0..0" [ps20b] [PC] +// STATIC: "WORLD_NORMAL" "0..1" [ps30] [PC] +// STATIC: "WORLD_NORMAL" "0..0" [XBOX] +// STATIC: "PHONG_HALFLAMBERT" "0..1" + +// DYNAMIC: "WRITEWATERFOGTODESTALPHA" "0..1" +#include "common_fog_ps_fxc.h" +// DYNAMIC: "NUM_LIGHTS" "0..4" +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps30] +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps20b] +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps30] +// DYNAMIC: "UBERLIGHT" "0..1" [ps30] [PC] + +// blend mode doesn't matter if we only have one texture +// SKIP: (! $DETAILTEXTURE) && ( $DETAIL_BLEND_MODE != 0 ) + +// We don't care about flashlight depth unless the flashlight is on +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 ) + +// We don't care about uberlight unless the flashlight is on +// SKIP: ( $FLASHLIGHT == 0 ) && ( $UBERLIGHT == 1 ) [ps30] + +// Only need self illum fresnel when self illum enabled +// SKIP: ( $SELFILLUM == 0 ) && ( $SELFILLUMFRESNEL == 1 ) + +// Don't skip these on 360 since we do single-pass rendering+flashlight there! +// SKIP: ( $FLASHLIGHT == 1 ) && ( $SELFILLUMFRESNEL == 1 ) [PC] +// SKIP: ( $FLASHLIGHT == 1 ) && ( $SELFILLUM == 1 ) [PC] + +// Only do world normals in constrained case +// SKIP: ( $WORLD_NORMAL == 1 ) && ( $FLASHLIGHTSHADOWS == 1 ) && ( $NUM_LIGHTS != 0 ) && ( $WRITEWATERFOGTODESTALPHA == 1 ) + + +#include "common_flashlight_fxc.h" +#include "shader_constant_register_map.h" + +#ifdef _X360 + #define SINGLE_PASS_FLASHLIGHT 1 +#else + #define SINGLE_PASS_FLASHLIGHT 0 +#endif + +const float4 g_SelfIllumTint_and_DetailBlendFactor : register( PSREG_SELFILLUMTINT ); +#if ( SELFILLUMFRESNEL == 1 ) +const float4 g_SelfIllumScaleBiasExpBrightness : register( PSREG_SELFILLUM_SCALE_BIAS_EXP ); +#endif +const float4 g_DiffuseModulation : register( PSREG_DIFFUSE_MODULATION ); + +const float4 g_vPsConst2 : register( PSREG_ENVMAP_TINT__SHADOW_TWEAKS ); +#define g_vEnvmapTint ( g_vPsConst2.xyz ) +#define g_bHasNormalMapAlphaEnvmapMask g_vPsConst2.w + +#if ( SINGLE_PASS_FLASHLIGHT ) + const float4 g_vPsConst43 : register( c43 ); + #define g_vShadowTweaks g_vPsConst43 +#else + #define g_vShadowTweaks g_vPsConst2 +#endif + +const float3 cAmbientCube[6] : register( PSREG_AMBIENT_CUBE ); +const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT ); +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float4 g_FlashlightAttenuationFactors_RimMask : register( PSREG_FLASHLIGHT_ATTENUATION ); // On non-flashlight pass, x has rim mask control +const float4 g_FlashlightPos_RimBoost : register( PSREG_FLASHLIGHT_POSITION_RIM_BOOST ); // This is overridden too! +const float4x4 g_FlashlightWorldToTexture : register( PSREG_FLASHLIGHT_TO_WORLD_TEXTURE ); +const float4 g_FresnelSpecParams : register( PSREG_FRESNEL_SPEC_PARAMS ); // xyz are fresnel, w is specular boost +const float4 g_SpecularRimParams : register( PSREG_SPEC_RIM_PARAMS ); // xyz are specular tint color, w is rim power +PixelShaderLightInfo cLightInfo[3] : register( PSREG_LIGHT_INFO_ARRAY ); // 2 registers each - 6 registers total (4th light spread across w's) +const float4 g_ShaderControls : register( PSREG_SHADER_CONTROLS ); +const float4 g_ShaderControls2 : register( PSREG_SHADER_CONTROLS_2 ); + +#if UBERLIGHT && defined( SHADER_MODEL_PS_3_0 ) +const float3 g_vSmoothEdge0 : register( PSREG_UBERLIGHT_SMOOTH_EDGE_0 ); // ps_3_0 and up (over 32 registers) +const float3 g_vSmoothEdge1 : register( PSREG_UBERLIGHT_SMOOTH_EDGE_1 ); +const float3 g_vSmoothOneOverWidth : register( PSREG_UBERLIGHT_SMOOTH_EDGE_OOW ); +const float4 g_vShearRound : register( PSREG_UBERLIGHT_SHEAR_ROUND ); +const float4 g_aAbB : register( PSREG_UBERLIGHT_AABB ); +const float4x4 g_FlashlightWorldToLight : register( PSREG_UBERLIGHT_WORLD_TO_LIGHT ); +#endif + +#if ( SINGLE_PASS_FLASHLIGHT ) + const float4 g_RimParams : register( PSREG_RIMPARAMS ); + #define g_RimMaskControl g_RimParams.x + #define g_fRimBoost g_RimParams.y +#else + #define g_RimMaskControl g_FlashlightAttenuationFactors_RimMask.x + #define g_fRimBoost g_FlashlightPos_RimBoost.w +#endif + +#define g_FlashlightPos g_FlashlightPos_RimBoost.xyz +#define g_FresnelRanges g_FresnelSpecParams.xyz +#define g_SpecularBoost g_FresnelSpecParams.w +#define g_SpecularTint g_SpecularRimParams.xyz +#define g_RimExponent g_SpecularRimParams.w +#define g_FlashlightAttenuationFactors g_FlashlightAttenuationFactors_RimMask +#define g_EyePos g_EyePos_SpecExponent.xyz + + +// Could merge g_fBaseMapAlphaPhongMask and g_fBaseLumPhongMask into a single -1, 0, 1 control code with some clever negation/saturation logic +// +// These scalars control behavior with straight-line "control flow" using lerp operations +#define g_fBaseMapAlphaPhongMask g_ShaderControls.x +#define g_fInverseBlendTintByBaseAlpha g_ShaderControls.z +#define g_fInvertPhongMask g_ShaderControls.w +#define g_fEnvMapFresnel g_ShaderControls2.x +#define g_fBaseLumPhongMask g_ShaderControls2.y +#define g_fSpecExp g_ShaderControls2.z +#define g_SelfIllumMaskControl g_ShaderControls2.w +#define g_fAmbientOcclusionStrength g_EyePos_SpecExponent.w + +sampler BaseTextureSampler : register( s0 ); // Base map, selfillum in alpha +sampler SpecularWarpSampler : register( s1 ); // Specular warp sampler (for iridescence etc) +sampler DiffuseWarpSampler : register( s2 ); // Lighting warp sampler (1D texture for diffuse lighting modification) +sampler NormalMapSampler : register( s3 ); // Normal map, specular mask in alpha +sampler ShadowDepthSampler : register( s4 ); // Flashlight shadow depth map sampler +sampler NormalizeRandRotSampler : register( s5 ); // Normalization / RandomRotation samplers +sampler FlashlightSampler : register( s6 ); // Flashlight cookie +sampler SpecExponentSampler : register( s7 ); // Specular exponent map +sampler EnvmapSampler : register( s8 ); // Cubic environment map + +#if WRINKLEMAP +sampler WrinkleSampler : register( s9 ); // Compression base +sampler StretchSampler : register( s10 ); // Expansion base +sampler NormalWrinkleSampler : register( s11 ); // Compression normal +sampler NormalStretchSampler : register( s12 ); // Expansion normal +#endif + +#if DETAILTEXTURE +sampler DetailSampler : register( s13 ); // detail texture +#endif + +sampler SelfIllumMaskSampler : register( s14 ); // selfillummask + +#if !defined( _X360 ) && defined( SHADER_MODEL_PS_3_0 ) +sampler AmbientOcclusionSampler : register( s15 ); // screen space ambient occlusion sampler on PC +#endif + +#define FLASHLIGHT_ONLY ( FLASHLIGHT && !SINGLE_PASS_FLASHLIGHT ) + +struct PS_INPUT +{ +#ifdef SHADER_MODEL_PS_3_0 + float2 vPos : VPOS; // Normalized Screenpos, call ComputeScreenPos() to get useful 2D coordinates +#endif + + float4 baseTexCoordDetailTexCoord : TEXCOORD0; // xy=base zw=detail + float4 lightAtten : TEXCOORD1; // Scalar light attenuation factors for FOUR lights + float3x3 tangentSpaceTranspose : TEXCOORD2; + // second row : TEXCOORD3; + // third row : TEXCOORD4; + float4 projPos_fWrinkleWeight : TEXCOORD5; +#if HARDWAREFOGBLEND || DOPIXELFOG + float3 worldPos_vertexFogFactor : TEXCOORD6; //it's important that this declaration stay down here. Moving it seems to trigger a BS compile error on 360 saying we've run out of temp registers. +#else + float4 worldPos_vertexFogFactor : TEXCOORD6; //it's important that this declaration stay down here. Moving it seems to trigger a BS compile error on 360 saying we've run out of temp registers. +#endif +}; + +#if defined( _X360 ) + // The compiler runs out of temp registers in certain combos, increase the maximum for now + #if ( ( NUM_LIGHTS > 2 ) && ( FLASHLIGHT == 1 ) && ( RIMLIGHT == 1 ) ) + [maxtempreg(39)] + #elif ( SHADER_SRGB_READ == 1 ) || ( SELFILLUMFRESNEL == 1 ) + [maxtempreg(35)] + #endif +#endif + +float4 main( PS_INPUT i ) : COLOR +{ + // Unpacking for convenience + float fWrinkleWeight = i.projPos_fWrinkleWeight.w; + float fSSAODepth = i.projPos_fWrinkleWeight.z; + float3 vProjPos = i.projPos_fWrinkleWeight.xyz; + float3 vWorldPos = i.worldPos_vertexFogFactor.xyz; + float4 vLightAtten = i.lightAtten; + + float4 baseColor = tex2Dsrgb( BaseTextureSampler, i.baseTexCoordDetailTexCoord.xy ); + + float flWrinkleAmount, flStretchAmount, flTextureAmount; + #if ( WRINKLEMAP ) + { + flWrinkleAmount = saturate( -fWrinkleWeight ); // One of these two is zero + flStretchAmount = saturate( fWrinkleWeight ); // while the other is in the 0..1 range + + flTextureAmount = 1.0f - flWrinkleAmount - flStretchAmount; // These should sum to one + + float4 wrinkleColor = tex2Dsrgb( WrinkleSampler, i.baseTexCoordDetailTexCoord.xy ); + float4 stretchColor = tex2Dsrgb( StretchSampler, i.baseTexCoordDetailTexCoord.xy ); + + // Apply wrinkle blend to only RGB. Alpha comes from the base texture + baseColor.rgb = ( flTextureAmount * baseColor ) + ( flWrinkleAmount * wrinkleColor ) + ( flStretchAmount * stretchColor ); + } + #endif + + float4 detailColor; + #if ( DETAILTEXTURE ) + { + detailColor = tex2D( DetailSampler, i.baseTexCoordDetailTexCoord.zw ); + baseColor = TextureCombine( baseColor, detailColor, DETAIL_BLEND_MODE, g_SelfIllumTint_and_DetailBlendFactor.w ); + } + #endif + + float3 lumCoefficients = { 0.3, 0.59, 0.11 }; + float baseLum = dot( baseColor.rgb, lumCoefficients ); + + float fSpecMask = 1.0f; + float4 normalTexel = tex2D( NormalMapSampler, i.baseTexCoordDetailTexCoord.xy ); + #if ( WRINKLEMAP ) + { + float4 wrinkleNormal = tex2D( NormalWrinkleSampler, i.baseTexCoordDetailTexCoord.xy ); + float4 stretchNormal = tex2D( NormalStretchSampler, i.baseTexCoordDetailTexCoord.xy ); + normalTexel = flTextureAmount * normalTexel + flWrinkleAmount * wrinkleNormal + flStretchAmount * stretchNormal; + } + #endif + + float3 tangentSpaceNormal = 2.0f * normalTexel.xyz - 1.0f; + + fSpecMask = lerp( normalTexel.a, baseColor.a, g_fBaseMapAlphaPhongMask ); + fSpecMask = lerp( fSpecMask, baseLum, g_fBaseLumPhongMask ); + + // We need a normal if we're doing any lighting + float3 worldSpaceNormal = normalize( mul( (float3x3)i.tangentSpaceTranspose, tangentSpaceNormal ) ); + //worldSpaceNormal = float3( 0.0f, 0.0f, 0.0f ); + + float3 vEyeDir = normalize( g_EyePos - vWorldPos ); + + float fFresnelRanges; + fFresnelRanges = Fresnel( worldSpaceNormal, vEyeDir, g_FresnelRanges ); + + float3 diffuseLighting = float3( 0.0f, 0.0f, 0.0f ); + float3 envMapColor = float3( 0.0f, 0.0f, 0.0f ); + #if ( !FLASHLIGHT_ONLY ) + { + // Summation of diffuse illumination from all local lights + diffuseLighting = PixelShaderDoLighting( vWorldPos, worldSpaceNormal, + float3( 0.0f, 0.0f, 0.0f ), false, true, vLightAtten, + cAmbientCube, NormalizeRandRotSampler, NUM_LIGHTS, cLightInfo, PHONG_HALFLAMBERT, + LIGHTWARPTEXTURE, DiffuseWarpSampler ); + + #if( CUBEMAP ) + { + float3 vReflect = CalcReflectionVectorUnnormalized( worldSpaceNormal, vEyeDir ); + envMapColor = ENV_MAP_SCALE * texCUBE( EnvmapSampler, vReflect ) * g_vEnvmapTint.xyz; + + // Optionally apply Fresnel to envmap + envMapColor = lerp( envMapColor, fFresnelRanges * envMapColor, g_fEnvMapFresnel ); + + float fEnvMapMask; + // Mask is either normal map alpha or base map alpha + #if ( SELFILLUMFRESNEL == 1 ) // This is to match the 2.0 version of vertexlitgeneric + { + fEnvMapMask = lerp( baseColor.a, g_fInvertPhongMask, g_bHasNormalMapAlphaEnvmapMask ); + } + #else + { + fEnvMapMask = lerp( baseColor.a, fSpecMask, g_bHasNormalMapAlphaEnvmapMask ); + } + #endif + + envMapColor *= lerp( fEnvMapMask, 1-fEnvMapMask, g_fInvertPhongMask ); + } + #endif + } + #endif + float fSpecExp = g_fSpecExp; + + float4 vSpecExpMap = tex2D( SpecExponentSampler, i.baseTexCoordDetailTexCoord.xy ); + float fSpecExpMap = vSpecExpMap.r; + float fRimMask = 0.0f; + + #if ( !FLASHLIGHT_ONLY ) + { + fRimMask = lerp( 1.0f, vSpecExpMap.a, g_RimMaskControl ); // Select rim mask + } + #endif + + // If the exponent passed in as a constant is zero, use the value from the map as the exponent + #if defined( _X360 ) + [flatten] + #endif + if ( fSpecExp == 0 ) + fSpecExp = 1.0f - fSpecExpMap + 150.0f * fSpecExpMap; + + float3 vSpecularTint; + // If constant tint is negative, tint with albedo, based upon scalar tint map + #if defined( _X360 ) + [flatten] + #endif + if ( g_SpecularTint.r < 0 ) + vSpecularTint = lerp( float3(1.0f, 1.0f, 1.0f), baseColor.rgb, vSpecExpMap.g ); + else + vSpecularTint = g_SpecularTint.rgb; + + #if ( PHONGWARPTEXTURE ) + { + fFresnelRanges = Fresnel( worldSpaceNormal, vEyeDir, g_FresnelRanges ); + } + #endif + + float3 albedo = baseColor.rgb; + + float3 specularLighting = float3( 0.0f, 0.0f, 0.0f ); + float3 rimLighting = float3( 0.0f, 0.0f, 0.0f ); + #if ( !FLASHLIGHT_ONLY ) + { + float3 specularLightingFromPhong; + // Summation of specular from all local lights besides the flashlight + PixelShaderDoSpecularLighting( vWorldPos, worldSpaceNormal, + fSpecExp, vEyeDir, vLightAtten, + NUM_LIGHTS, cLightInfo, PHONGWARPTEXTURE, SpecularWarpSampler, fFresnelRanges, RIMLIGHT, g_RimExponent, + + // Outputs + specularLightingFromPhong, rimLighting ); + specularLighting += specularLightingFromPhong; + } + #endif + #if ( FLASHLIGHT ) + { + float4 flashlightSpacePosition = mul( float4( vWorldPos, 1.0f ), g_FlashlightWorldToTexture ); + + float3 diffuseLightingFromFlashlight; + float3 specularLightingFromFlashlight; + + DoSpecularFlashlight( g_FlashlightPos, vWorldPos, flashlightSpacePosition, worldSpaceNormal, + g_FlashlightAttenuationFactors.xyz, g_FlashlightAttenuationFactors.w, + FlashlightSampler, ShadowDepthSampler, NormalizeRandRotSampler, FLASHLIGHTDEPTHFILTERMODE, FLASHLIGHTSHADOWS, true, vProjPos.xy / vProjPos.z, + fSpecExp, vEyeDir, LIGHTWARPTEXTURE, DiffuseWarpSampler, PHONGWARPTEXTURE, SpecularWarpSampler, fFresnelRanges, g_vShadowTweaks, + + // These two values are output + diffuseLightingFromFlashlight, specularLightingFromFlashlight ); + + #if ( UBERLIGHT && defined( SHADER_MODEL_PS_3_0 ) ) + { + float4 uberLightPosition = mul( float4( vWorldPos, 1.0f ), g_FlashlightWorldToLight ).yzxw; + float fUber = uberlight( uberLightPosition, g_vSmoothEdge0, g_vSmoothEdge1, + g_vSmoothOneOverWidth, g_vShearRound.xy, g_aAbB, g_vShearRound.zw ); + diffuseLightingFromFlashlight *= fUber; + specularLightingFromFlashlight *= fUber; + } + #endif + + specularLighting += specularLightingFromFlashlight; + diffuseLighting += diffuseLightingFromFlashlight; + } + #endif + + // Modulate with spec mask, boost and tint + specularLighting *= fSpecMask * g_SpecularBoost * vSpecularTint; + + // If we didn't already apply Fresnel to specular warp, modulate the specular + #if ( !PHONGWARPTEXTURE ) + { + specularLighting *= fFresnelRanges; + } + #endif + + // Optionally use basealpha to blend in the diffuse modulation (saturated add of g_fInverseBlendTintByBaseAlpha turns this on/off) + diffuseLighting *= lerp( float3( 1.0f, 1.0f, 1.0f ), g_DiffuseModulation.rgb, saturate( baseColor.a + g_fInverseBlendTintByBaseAlpha ) ); + + float3 diffuseComponent = albedo * diffuseLighting; + #if ( SELFILLUM && !FLASHLIGHT_ONLY ) + { + #if ( SELFILLUMFRESNEL == 1 ) // To free up the constant register...see top of file + { + // This will apply a Fresnel term based on the vertex normal (not the per-pixel normal!) to help fake and internal glow look + float3 vVertexNormal = normalize( float3( i.tangentSpaceTranspose[0].z, i.tangentSpaceTranspose[1].z, i.tangentSpaceTranspose[2].z ) ); + float3 vSelfIllumMask = tex2D( SelfIllumMaskSampler, i.baseTexCoordDetailTexCoord.xy ); + vSelfIllumMask = lerp( baseColor.aaa, vSelfIllumMask, g_SelfIllumMaskControl ); + float flSelfIllumFresnel = ( pow( saturate( dot( vVertexNormal.xyz, vEyeDir.xyz ) ), g_SelfIllumScaleBiasExpBrightness.z ) * g_SelfIllumScaleBiasExpBrightness.x ) + g_SelfIllumScaleBiasExpBrightness.y; + diffuseComponent = lerp( diffuseComponent, g_SelfIllumTint_and_DetailBlendFactor.rgb * albedo * g_SelfIllumScaleBiasExpBrightness.w, vSelfIllumMask.rgb * saturate( flSelfIllumFresnel ) ); + } + #else + { + float3 vSelfIllumMask = tex2D( SelfIllumMaskSampler, i.baseTexCoordDetailTexCoord.xy ); + vSelfIllumMask = lerp( baseColor.aaa, vSelfIllumMask, g_SelfIllumMaskControl ); + diffuseComponent = lerp( diffuseComponent, g_SelfIllumTint_and_DetailBlendFactor.rgb * albedo, vSelfIllumMask ); + } + #endif + + diffuseComponent = max( 0.0f, diffuseComponent ); + } + #endif + + #if ( DETAILTEXTURE ) + { + diffuseComponent = TextureCombinePostLighting( diffuseComponent, detailColor, DETAIL_BLEND_MODE, g_SelfIllumTint_and_DetailBlendFactor.w ); + } + #endif + + #if ( RIMLIGHT && !FLASHLIGHT_ONLY ) + { + float fRimFresnel = Fresnel4( worldSpaceNormal, vEyeDir ); + + // Add in rim light modulated with tint, mask and traditional Fresnel (not using Fresnel ranges) + rimLighting *= fRimMask * fRimFresnel; + + // Fold rim lighting into specular term by using the max so that we don't really add light twice... + specularLighting = max( specularLighting, rimLighting ); + + // Add in view-ray lookup from ambient cube + specularLighting += fRimFresnel * fRimMask * g_fRimBoost * PixelShaderAmbientLight( vEyeDir, cAmbientCube) * saturate(dot(worldSpaceNormal, float3(0, 0 , 1)) ); + } + #endif + + // Screen-space dynamic ambient occlusion on PC + float fAmbientOcclusion = 1.0f; + #if !defined( _X360 ) && defined( SHADER_MODEL_PS_3_0 ) + { + fAmbientOcclusion = lerp( 1.0f, tex2D( AmbientOcclusionSampler, ComputeScreenPos( i.vPos ) ).r, g_fAmbientOcclusionStrength ); + } + #endif + + float3 result = (specularLighting + envMapColor + diffuseComponent) * fAmbientOcclusion; + + float flVertexFogFactor = 0.0f; + #if ( !HARDWAREFOGBLEND && !DOPIXELFOG ) + { + flVertexFogFactor = i.worldPos_vertexFogFactor.w; + } + #endif + float fogFactor = CalcPixelFogFactorSupportsVertexFog( PIXELFOGTYPE, g_FogParams, g_EyePos_SpecExponent.xyz, vWorldPos.xyz, vProjPos.z, flVertexFogFactor ); + + float alpha; + #if ( WRITEWATERFOGTODESTALPHA && ( PIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT ) ) + { + alpha = fogFactor; + } + #else + { + alpha = g_DiffuseModulation.a; + + // Want to multiply by 1.0 if we are using base alpha for anything that isn't translucency. + float fBaseAlphaIsForTranslucency = 1.0f; + + #if ( SELFILLUM ) + // If we are selfillum, base alpha can only be used for translucency if we have a separate selfillummask + fBaseAlphaIsForTranslucency *= g_SelfIllumMaskControl; + #endif + + // Can't use base alpha for translucency if it's being used for a phong mask. + fBaseAlphaIsForTranslucency *= ( 1.0f - g_fBaseMapAlphaPhongMask ); + + // Lerp between 1.0f and baseColor.a based on if we are using the basealpha for translucency. + alpha *= lerp( 1.0f, baseColor.a, fBaseAlphaIsForTranslucency ); + } + #endif + + bool bWriteDepthToAlpha = ( WRITE_DEPTH_TO_DESTALPHA != 0 ) && ( WRITEWATERFOGTODESTALPHA == 0 ); + + #if ( WORLD_NORMAL ) + { + return float4( worldSpaceNormal, fSSAODepth ); + } + #else + { + //FIXME: need to take dowaterfog into consideration + return FinalOutput( float4( result, alpha ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, bWriteDepthToAlpha, vProjPos.z ); + } + #endif +} diff --git a/materialsystem/stdshaders/phong_vs20.fxc b/materialsystem/stdshaders/phong_vs20.fxc new file mode 100644 index 00000000..a3b0d0fb --- /dev/null +++ b/materialsystem/stdshaders/phong_vs20.fxc @@ -0,0 +1,196 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "DECAL" "0..1" [vs30] +// STATIC: "WORLD_NORMAL" "0..0" [vs20] [PC] +// STATIC: "WORLD_NORMAL" "0..1" [vs30] [PC] +// STATIC: "WORLD_NORMAL" "0..0" [XBOX] + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "SKINNING" "0..1" + +// DYNAMIC: "MORPHING" "0..1" [vs30] [ = pShaderAPI->IsHWMorphingEnabled() ] +// DYNAMIC: "TESSELLATION" "0..2" [vs30] [PC] +// DYNAMIC: "TESSELLATION" "0..0" [vs20] [PC] +// DYNAMIC: "TESSELLATION" "0..0" [XBOX] + +// SKIP: ( $MORPHING || $SKINNING || $COMPRESSED_VERTS ) && $TESSELLATION + +#include "common_fog_vs_supportsvertexfog_fxc.h" +#include "common_vs_fxc.h" + +static const bool g_bSkinning = SKINNING ? true : false; +static const int g_FogType = DOWATERFOG; + +const float4 cBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_0 ); +const float4 cDetailTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_4 ); + +#ifdef SHADER_MODEL_VS_3_0 +// NOTE: cMorphTargetTextureDim.xy = target dimensions, +// cMorphTargetTextureDim.z = 4tuples/morph +const float3 cMorphTargetTextureDim : register( SHADER_SPECIFIC_CONST_6 ); +const float4 cMorphSubrect : register( SHADER_SPECIFIC_CONST_7 ); + +sampler2D morphSampler : register( D3DVERTEXTEXTURESAMPLER0, s0 ); +#endif + +const float4 g_vEyeVector : register( SHADER_SPECIFIC_CONST_8 ); + + +#if TESSELLATION + +#include "tessellation_vs_fxc.h" + +const float4 g_SubDControls : register( SHADER_SPECIFIC_CONST_9 ); +sampler2D BezierSampler : register( s1 ); +sampler2D DispSampler : register( s2 ); +// VS_INPUT defined in header + +#else // no TESSELLATION + +struct VS_INPUT +{ + // This is all of the stuff that we ever use. + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vNormal : NORMAL; + float4 vColor : COLOR0; + float3 vSpecular : COLOR1; + // make these float2's and stick the [n n 0 1] in the dot math. + float4 vTexCoord0 : TEXCOORD0; + float4 vTexCoord1 : TEXCOORD1; + float4 vTexCoord2 : TEXCOORD2; + float4 vTexCoord3 : TEXCOORD3; + float3 vTangentS : TANGENT; + float3 vTangentT : BINORMAL; + float4 vUserData : TANGENT; + + // Position and normal/tangent deltas + float4 vPosFlex : POSITION1; + float4 vNormalFlex : NORMAL1; + +#ifdef SHADER_MODEL_VS_3_0 + float vVertexID : POSITION2; +#endif +}; + +#endif // TESSELLATION + +struct VS_OUTPUT +{ + // Stuff that isn't seen by the pixel shader + float4 projPos : POSITION; + // Stuff that is seen by the pixel shader + float4 baseTexCoordDetailTexCoord : TEXCOORD0; // includes detail tex coord + float4 lightAtten : TEXCOORD1; + float3x3 tangentSpaceTranspose : TEXCOORD2; + // second row : TEXCOORD3; + // third row : TEXCOORD4; + float4 projPos_fWrinkleWeight : TEXCOORD5; + #if DOPIXELFOG + float3 worldPos_vertexFogFactor : TEXCOORD6; //it's important that this declaration stay down here. Moving it seems to trigger a BS compile error on 360 saying we've run out of temp registers. + #else + float4 worldPos_vertexFogFactor : TEXCOORD6; //it's important that this declaration stay down here. Moving it seems to trigger a BS compile error on 360 saying we've run out of temp registers. + #endif +}; + +//----------------------------------------------------------------------------- +// Main shader entry point +//----------------------------------------------------------------------------- +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float4 vPosition, vTangent, vTexCoords; + float3 vNormal, worldPos, worldNormal, worldTangentS, worldTangentT; + + #if TESSELLATION + { + float flBiTangentSign; + EvaluateSubdivisionSurface( v, g_SubDControls.x, g_SubDControls.y, g_SubDControls.z, BezierSampler, DispSampler, + worldNormal, worldPos, worldTangentS, worldTangentT, flBiTangentSign, + o.projPos_fWrinkleWeight.w, o.baseTexCoordDetailTexCoord.xy, o.baseTexCoordDetailTexCoord.zw ); + } + #else // not tessellating + { + vPosition = v.vPos; + + DecompressVertex_NormalTangent( v.vNormal, v.vUserData, vNormal, vTangent ); + + #if ( !defined( SHADER_MODEL_VS_3_0 ) || !MORPHING ) + { + ApplyMorph( v.vPosFlex, v.vNormalFlex, vPosition.xyz, vNormal, vTangent.xyz, o.projPos_fWrinkleWeight.w ); + } + #else + { + ApplyMorph( morphSampler, cMorphTargetTextureDim, cMorphSubrect, v.vVertexID, v.vTexCoord2, + vPosition.xyz, vNormal, vTangent.xyz, o.projPos_fWrinkleWeight.w ); + } + #endif + + // Perform skinning + SkinPositionNormalAndTangentSpace( g_bSkinning, vPosition, vNormal, vTangent, + v.vBoneWeights, v.vBoneIndices, worldPos, + worldNormal, worldTangentS, worldTangentT ); + + // Always normalize since flex path can denormalize + worldNormal = normalize( worldNormal ); + worldTangentS = normalize( worldTangentS ); + worldTangentT = normalize( worldTangentT ); + + #if defined( SHADER_MODEL_VS_3_0 ) && MORPHING && DECAL && ( !WORLD_NORMAL ) + { + // Avoid z precision errors + worldPos += worldNormal * 0.05f * v.vTexCoord2.z; + } + #endif + + vTexCoords = v.vTexCoord0; + + // Texture coordinate transforms + o.baseTexCoordDetailTexCoord.x = dot( vTexCoords, cBaseTexCoordTransform[0] ); + o.baseTexCoordDetailTexCoord.y = dot( vTexCoords, cBaseTexCoordTransform[1] ); + o.baseTexCoordDetailTexCoord.z = dot( vTexCoords, cDetailTexCoordTransform[0] ); + o.baseTexCoordDetailTexCoord.w = dot( vTexCoords, cDetailTexCoordTransform[1] ); + } + #endif + + #if ( !DOPIXELFOG ) + { + o.worldPos_vertexFogFactor.w = CalcNonFixedFunctionFog( worldPos, g_FogType ); + } + #endif + + // Needed for water fog alpha and diffuse lighting + // FIXME: we shouldn't have to compute this all the time. + o.worldPos_vertexFogFactor.xyz = worldPos; + + // Compute lighting attenuations + o.lightAtten.x = GetVertexAttenForLight( worldPos, 0 ); + o.lightAtten.y = GetVertexAttenForLight( worldPos, 1 ); + o.lightAtten.z = GetVertexAttenForLight( worldPos, 2 ); + o.lightAtten.w = GetVertexAttenForLight( worldPos, 3 ); + + // Tangent space transform + o.tangentSpaceTranspose[0].xyz = float3( worldTangentS.x, worldTangentT.x, worldNormal.x ); + o.tangentSpaceTranspose[1].xyz = float3( worldTangentS.y, worldTangentT.y, worldNormal.y ); + o.tangentSpaceTranspose[2].xyz = float3( worldTangentS.z, worldTangentT.z, worldNormal.z ); + // Transform into projection space + o.projPos = mul( float4( worldPos, 1 ), cViewProj ); + o.projPos_fWrinkleWeight.xyz = o.projPos.xyz; + + #if ( WORLD_NORMAL ) + { + o.projPos_fWrinkleWeight.z = dot( g_vEyeVector, worldPos.xyz - cEyePos.xyz ); // Linear depth + } + #endif + + // Don't have to worry about hardware blend here since we never do that with phong. + #if ( !DOPIXELFOG ) + { + o.worldPos_vertexFogFactor.w = CalcNonFixedFunctionFog( worldPos, g_FogType ); + } + #endif + + return o; +} diff --git a/materialsystem/stdshaders/projected.cpp b/materialsystem/stdshaders/projected.cpp new file mode 100644 index 00000000..b7525dbc --- /dev/null +++ b/materialsystem/stdshaders/projected.cpp @@ -0,0 +1,58 @@ +//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============// +// +// Purpose: Projecteding shader for Spy in TF2 (and probably many other things to come) +// +// $NoKeywords: $ +//=====================================================================================// + +#include "BaseVSShader.h" +#include "convar.h" +#include "projected_dx9_helper.h" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +DEFINE_FALLBACK_SHADER( Projected, Projected_DX90 ) + +BEGIN_VS_SHADER( Projected_DX90, "Help for Projected" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( SPECTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "" ) + SHADER_PARAM( FOW, SHADER_PARAM_TYPE_TEXTURE, "", "FoW Render Target" ) + END_SHADER_PARAMS + + void SetupVars( Projected_DX9_Vars_t& info ) + { + info.m_nBaseTextureTransform = BASETEXTURETRANSFORM; + info.m_nBaseTexture = BASETEXTURE; + info.m_nFoW = FOW; + } + + SHADER_INIT_PARAMS() + { + Projected_DX9_Vars_t info; + SetupVars( info ); + InitParamsProjected_DX9( this, params, pMaterialName, info ); + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + Projected_DX9_Vars_t info; + SetupVars( info ); + InitProjected_DX9( this, params, info ); + } + + SHADER_DRAW + { + Projected_DX9_Vars_t info; + SetupVars( info ); + DrawProjected_DX9( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } +END_SHADER + diff --git a/materialsystem/stdshaders/projected_dx9_helper.cpp b/materialsystem/stdshaders/projected_dx9_helper.cpp new file mode 100644 index 00000000..cfc0a075 --- /dev/null +++ b/materialsystem/stdshaders/projected_dx9_helper.cpp @@ -0,0 +1,214 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" +#include "projected_dx9_helper.h" +#include "..\shaderapidx9\locald3dtypes.h" +#include "convar.h" +#include "cpp_shader_constant_register_map.h" +#include "projected_vs20.inc" +#include "projected_vs30.inc" + +#include "projected_ps20.inc" +#include "projected_ps20b.inc" +#include "projected_ps30.inc" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +void InitParamsProjected_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, Projected_DX9_Vars_t &info ) +{ + SET_FLAGS( MATERIAL_VAR_NOCULL ); + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); +} + +void InitProjected_DX9( CBaseVSShader *pShader, IMaterialVar** params, Projected_DX9_Vars_t &info ) +{ + if ( params[ info.m_nBaseTexture ]->IsDefined() ) + { + pShader->LoadTexture( info.m_nBaseTexture ); + } + + if ( info.m_nFoW != -1 && params[ info.m_nFoW ]->IsDefined() ) + { + pShader->LoadTexture( info.m_nFoW ); + } +} + +void DrawProjected_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, Projected_DX9_Vars_t &info, VertexCompressionType_t vertexCompression ) +{ + bool bIsModel = IS_FLAG_SET( MATERIAL_VAR_MODEL ); + bool bHasFoW = ( ( info.m_nFoW != -1 ) && ( params[ info.m_nFoW ]->IsTexture() != 0 ) ); + if ( bHasFoW == true ) + { + ITexture *pTexture = params[ info.m_nFoW ]->GetTextureValue(); + if ( ( pTexture->GetFlags() & TEXTUREFLAGS_RENDERTARGET ) == 0 ) + { + bHasFoW = false; + } + } + + SHADOW_STATE + { + pShader->SetInitialShadowState( ); + + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); // Always SRGB read on base map 1 + + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + if ( bHasFoW ) + { +// pShaderShadow->EnableSRGBRead( SHADER_SAMPLER10, true ); // Always SRGB read on base map + pShaderShadow->EnableTexture( SHADER_SAMPLER10, true ); + } + + pShaderShadow->EnableSRGBWrite( true ); + + unsigned int flags = VERTEX_POSITION | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 0; + + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, 0 ); + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_STATIC_VERTEX_SHADER( projected_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( FOW, bHasFoW ); + SET_STATIC_VERTEX_SHADER_COMBO( MODEL, bIsModel ); + SET_STATIC_VERTEX_SHADER( projected_vs20 ); + + // Bind ps_2_b shader so we can get Phong terms + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( projected_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( FOW, bHasFoW ); + SET_STATIC_PIXEL_SHADER( projected_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( projected_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( FOW, bHasFoW ); + SET_STATIC_PIXEL_SHADER( projected_ps20 ); + } + } +#ifndef _X360 + else + { + // The vertex shader uses the vertex id stream + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + + DECLARE_STATIC_VERTEX_SHADER( projected_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( MODEL, bIsModel ); + SET_STATIC_VERTEX_SHADER_COMBO( FOW, bHasFoW ); + SET_STATIC_VERTEX_SHADER( projected_vs30 ); + + // Bind ps_2_b shader so we can get Phong terms + DECLARE_STATIC_PIXEL_SHADER( projected_ps30 ); + SET_STATIC_PIXEL_SHADER_COMBO( FOW, bHasFoW ); + SET_STATIC_PIXEL_SHADER( projected_ps30 ); + } +#endif + + pShaderShadow->EnablePolyOffset( SHADER_POLYOFFSET_DECAL ); + pShaderShadow->EnableDepthTest( true ); + pShaderShadow->EnableDepthWrites( false ); + + pShader->DefaultFog(); + + pShader->SetAdditiveBlendingShadowState( info.m_nBaseTexture, true ); + pShaderShadow->EnableBlending( true ); + + // Lighting constants + pShader->PI_BeginCommandBuffer(); + pShader->PI_SetPixelShaderAmbientLightCube( PSREG_AMBIENT_CUBE ); + pShader->PI_SetPixelShaderLocalLighting( PSREG_LIGHT_INFO_ARRAY ); + pShader->PI_EndCommandBuffer(); + } + DYNAMIC_STATE + { + pShaderAPI->SetDefaultState(); + + int numBones = pShaderAPI->GetCurrentNumBones(); + + // Bind textures + pShader->BindTexture( SHADER_SAMPLER1, info.m_nBaseTexture ); // Base Map 1 + + if ( bHasFoW ) + { + pShader->BindTexture( SHADER_SAMPLER10, info.m_nFoW, -1 ); + + float vFoWSize[ 4 ]; + Vector vMins = pShaderAPI->GetVectorRenderingParameter( VECTOR_RENDERPARM_GLOBAL_FOW_MINS ); + Vector vMaxs = pShaderAPI->GetVectorRenderingParameter( VECTOR_RENDERPARM_GLOBAL_FOW_MAXS ); + vFoWSize[ 0 ] = vMins.x; + vFoWSize[ 1 ] = vMins.y; + vFoWSize[ 2 ] = vMaxs.x - vMins.x; + vFoWSize[ 3 ] = vMaxs.y - vMins.y; + pShaderAPI->SetVertexShaderConstant( 26, vFoWSize ); + } + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_DYNAMIC_VERTEX_SHADER( projected_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, ( numBones > 0 ) ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, ( int )vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( projected_vs20 ); + + // Bind ps_2_b shader so we can get Phong, rim and a cloudier refraction + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( projected_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( projected_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( projected_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( projected_ps20 ); + } + } +#ifndef _X360 + else + { + DECLARE_DYNAMIC_VERTEX_SHADER( projected_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, ( numBones > 0 ) ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, ( int )vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( projected_vs30 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( projected_ps30 ); + SET_DYNAMIC_PIXEL_SHADER( projected_ps30 ); + } +#endif + + pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, info.m_nBaseTextureTransform ); + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + VMatrix worldToTexture; + FlashlightState_t state = pShaderAPI->GetFlashlightState( worldToTexture ); + + Vector4D vLightDir; + vLightDir.AsVector3D() = state.m_vecLightOrigin; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, vLightDir.Base() ); + + Vector4D vProjectionSize( state.m_flProjectionSize * 2.0f, state.m_flProjectionRotation, 0.0f, 0.0f ); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, vProjectionSize.Base() ); + + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_COLOR, &state.m_Color[ 0 ], 1 ); + + // Set c0 and c1 to contain first two rows of ViewProj matrix + VMatrix matView, matProj, matViewProj; + pShaderAPI->GetMatrix( MATERIAL_VIEW, matView.m[0] ); + pShaderAPI->GetMatrix( MATERIAL_PROJECTION, matProj.m[0] ); + matViewProj = matView * matProj; + pShaderAPI->SetPixelShaderConstant( 0, matViewProj.m[0], 2 ); + } + pShader->Draw(); +} diff --git a/materialsystem/stdshaders/projected_dx9_helper.h b/materialsystem/stdshaders/projected_dx9_helper.h new file mode 100644 index 00000000..40dc9b50 --- /dev/null +++ b/materialsystem/stdshaders/projected_dx9_helper.h @@ -0,0 +1,41 @@ +//====== Copyright © 1996-2006, Valve Corporation, All rights reserved. ======= +// +// Purpose: +// +//============================================================================= + +#ifndef PROJECTED_DX9_HELPER_H +#define PROJECTED_DX9_HELPER_H +#ifdef _WIN32 +#pragma once +#endif + +#include + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct Projected_DX9_Vars_t +{ + Projected_DX9_Vars_t() { memset( this, 0xFF, sizeof( *this ) ); } + + int m_nBaseTextureTransform; + int m_nBaseTexture; + int m_nFoW; +}; + +void InitParamsProjected_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, + Projected_DX9_Vars_t &info ); +void InitProjected_DX9( CBaseVSShader *pShader, IMaterialVar** params, Projected_DX9_Vars_t &info ); +void DrawProjected_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, Projected_DX9_Vars_t &info, VertexCompressionType_t vertexCompression ); + +#endif // PROJECTED_DX9_HELPER_H diff --git a/materialsystem/stdshaders/projected_ps2x.fxc b/materialsystem/stdshaders/projected_ps2x.fxc new file mode 100644 index 00000000..722eb4ec --- /dev/null +++ b/materialsystem/stdshaders/projected_ps2x.fxc @@ -0,0 +1,48 @@ +//========= Copyright © 1996-2007, Valve Corporation, All rights reserved. ============// + +// STATIC: "FOW" "0..1" + +#include "shader_constant_register_map.h" +#include "common_fog_ps_fxc.h" +#include "fow_ps_fxc.h" + +sampler BaseSampler1 : register( s1 ); // Base map 1 + +#if ( FOW == 1 ) + +sampler FoWSampler : register( s10 ); // Fog of War + +#endif + + +struct PS_INPUT +{ + float4 projPos : POSITION; + float2 vBaseTexCoord : TEXCOORD0; +#if ( FOW == 1 ) + float2 vFowCoord : TEXCOORD3; +#endif +}; + + +float4 main( PS_INPUT i ) : COLOR +{ +#if !defined( _X360 ) + if ( i.vBaseTexCoord.x < 0.0 || i.vBaseTexCoord.x > 1.0 || i.vBaseTexCoord.y < 0.0 || i.vBaseTexCoord.y > 1.0 ) + { + discard; + } +#endif + + float3 vResult = tex2D( BaseSampler1, i.vBaseTexCoord.xy ) * cFlashlightColor.rgb; + +#if ( FOW == 1 ) +// return float4( vFoWResult, 0, 0, 255 ); + vResult.rgb = CalcFoW( FoWSampler, i.vFowCoord, vResult.rgb ); +#endif + + float fogFactor = 0.0f; + + return FinalOutput( float4( vResult, 1.0 ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR ); +} + diff --git a/materialsystem/stdshaders/projected_vs20.fxc b/materialsystem/stdshaders/projected_vs20.fxc new file mode 100644 index 00000000..69dae4e4 --- /dev/null +++ b/materialsystem/stdshaders/projected_vs20.fxc @@ -0,0 +1,93 @@ +//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======= +// +// Purpose: +// +//============================================================================= + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "SKINNING" "0..1" +// STATIC: "MODEL" "0..1" +// STATIC: "FOW" "0..1" + +#include "common_fog_vs_fxc.h" +#include "common_vs_fxc.h" +#include "fow_vs_fxc.h" + +//const float4 cBaseTexCoordTransform[ 2 ] : register( SHADER_SPECIFIC_CONST_6 ); + +const float4 g_flProjectedSizeRotation : register( c49 ); +const float4 g_vProjectionOrigin : register( c48 ); + +static const bool g_bSkinning = SKINNING ? true : false; + +#if ( FOW == 1 ) +const float4 g_vFoWWorldSize : register( c26 ); +#endif + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; +}; + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; + float2 vBaseTexCoord : TEXCOORD0; +#if ( FOW == 1 ) + float2 vFowCoord : TEXCOORD3; +#endif +}; + +static const float3 Normal = float3( 0, 0, -1.0 ); + +float3 ClosestPointOnPlane( float3 TestPoint ) +{ + float distance = dot( Normal, TestPoint - g_vProjectionOrigin ); + + return TestPoint - distance*Normal; +} + +float2 ComputeTexCoord( const float3 vWorldPos, const float flRotation, const float flScale ) +{ + float3 vTest = ClosestPointOnPlane( vWorldPos ); + float2 vBaseCoord = ( ( vTest - g_vProjectionOrigin ) / g_flProjectedSizeRotation.x ) + 0.5f; + + float2 vAdjust = vBaseCoord - float2( 0.5, 0.5 ); + float2 vResult; + float c = cos( flRotation ); + float s = sin( flRotation ); + + vResult.x = ( vAdjust.x * c ) + ( vAdjust.y * -s ); + vResult.y = ( vAdjust.x * s ) + ( vAdjust.y * c ); + + return ( vResult / flScale ) + float2( 0.5, 0.5 ); +} + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o; + + float3 vNewPos = v.vPos; +// vNewPos.z += 128.0; + + float4 vProjPos; + float3 vWorldPos; + + SkinPosition( g_bSkinning, v.vPos, v.vBoneWeights, v.vBoneIndices, vWorldPos ); + + // vProjPos = mul( float4( vNewPos, 1 ), cModelViewProj ); + vProjPos = mul( float4( vWorldPos, 1 ), cViewProj ); + o.vProjPos = vProjPos; + +// vWorldPos = mul( float4( vNewPos, 1 ), cModel[0] ); + +#if ( FOW == 1 ) + o.vFowCoord = CalcFoWCoord( g_vFoWWorldSize, vWorldPos.xy ); +#endif + + o.vBaseTexCoord = ComputeTexCoord( vWorldPos, g_flProjectedSizeRotation.y, 1.0 ); + + return o; +} diff --git a/materialsystem/stdshaders/prototype.cpp b/materialsystem/stdshaders/prototype.cpp new file mode 100644 index 00000000..2c30513c --- /dev/null +++ b/materialsystem/stdshaders/prototype.cpp @@ -0,0 +1,55 @@ +//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============// + +#include "BaseVSShader.h" +#include "prototype_helper.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( Prototype, Prototype_dx9 ) +BEGIN_VS_SHADER( Prototype_dx9, "Prototype" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "", "Normal map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "Frame number for $bumpmap" ) + END_SHADER_PARAMS + + void SetupVarsPrototype( PrototypeVars_t &info ) + { + info.m_nBaseTexture = BASETEXTURE; + info.m_nBaseTextureFrame = FRAME; + + info.m_nBumpmap = BUMPMAP; + info.m_nBumpFrame = BUMPFRAME; + } + + SHADER_INIT_PARAMS() + { + PrototypeVars_t info; + SetupVarsPrototype( info ); + InitParamsPrototype( this, params, pMaterialName, info ); + } + + SHADER_FALLBACK + { + if ( ( g_pHardwareConfig->GetDXSupportLevel() < 90 ) || ( !g_pHardwareConfig->SupportsPixelShaders_2_b() ) ) + { + return "Wireframe"; + } + + return 0; + } + + SHADER_INIT + { + PrototypeVars_t info; + SetupVarsPrototype( info ); + InitPrototype( this, params, info ); + } + + SHADER_DRAW + { + PrototypeVars_t info; + SetupVarsPrototype( info ); + DrawPrototype( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } +END_SHADER diff --git a/materialsystem/stdshaders/prototype_helper.cpp b/materialsystem/stdshaders/prototype_helper.cpp new file mode 100644 index 00000000..7de33eda --- /dev/null +++ b/materialsystem/stdshaders/prototype_helper.cpp @@ -0,0 +1,137 @@ +//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============// + +#include "BaseVSShader.h" +#include "mathlib/VMatrix.h" +#include "prototype_helper.h" +#include "convar.h" + +// Auto generated inc files +#include "prototype_vs20.inc" +#include "prototype_ps20b.inc" + +void InitParamsPrototype( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, PrototypeVars_t &info ) +{ + // Set material flags + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + + // Set material parameter default values + if ( (info.m_nBaseTextureFrame != -1 ) && !params[info.m_nBaseTextureFrame]->IsDefined() ) + { + params[info.m_nBaseTextureFrame]->SetIntValue( 0 ); + } + + if ( (info.m_nBumpFrame != -1 ) && !params[info.m_nBumpFrame]->IsDefined() ) + { + params[info.m_nBumpFrame]->SetIntValue( 0 ); + } +} + +void InitPrototype( CBaseVSShader *pShader, IMaterialVar** params, PrototypeVars_t &info ) +{ + // Load textures + if ( (info.m_nBaseTexture != -1) && params[info.m_nBaseTexture]->IsDefined() ) + { + pShader->LoadTexture( info.m_nBaseTexture ); + } + + if ( (info.m_nBumpmap != -1) && params[info.m_nBumpmap]->IsDefined() ) + { + pShader->LoadTexture( info.m_nBumpmap ); + } +} + +void DrawPrototype( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, PrototypeVars_t &info, VertexCompressionType_t vertexCompression ) +{ + SHADOW_STATE + { + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_FORMAT_COMPRESSED; + + bool bHasVertexColor = IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR ); + bool bHasVertexAlpha = IS_FLAG_SET( MATERIAL_VAR_VERTEXALPHA ); + if ( bHasVertexColor || bHasVertexAlpha ) + flags |= VERTEX_COLOR; + + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + // Vertex Shader + DECLARE_STATIC_VERTEX_SHADER( prototype_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( VERTEXCOLOR, bHasVertexColor || bHasVertexAlpha ); + SET_STATIC_VERTEX_SHADER( prototype_vs20 ); + + // Pixel Shader + DECLARE_STATIC_PIXEL_SHADER( prototype_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( VERTEXCOLOR, bHasVertexColor || bHasVertexAlpha ); + SET_STATIC_PIXEL_SHADER( prototype_ps20b ); + + // Textures + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); // Color texture + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); // Bump + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, false ); // Not sRGB + pShaderShadow->EnableSRGBWrite( true ); + + // Blending + //pShader->EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + //pShaderShadow->EnableAlphaWrites( false ); + + // !!! We need to turn this back on because EnableAlphaBlending() above disables it! + //pShaderShadow->EnableDepthWrites( true ); + + pShader->PI_BeginCommandBuffer(); + pShader->PI_SetPixelShaderAmbientLightCube( 3 ); + pShader->PI_SetPixelShaderLocalLighting( 9 ); + pShader->PI_SetVertexShaderAmbientLightCube(); + pShader->PI_EndCommandBuffer(); + } + DYNAMIC_STATE + { + LightState_t lightState = { 0, false, false }; + + // Set Vertex Shader Combos + DECLARE_DYNAMIC_VERTEX_SHADER( prototype_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DYNAMIC_LIGHT, lightState.HasDynamicLight() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( STATIC_LIGHT, lightState.m_bStaticLight ? 1 : 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_VERTEX_SHADER( prototype_vs20 ); + + // Set Vertex Shader Constants + pShaderAPI->GetDX9LightState( &lightState ); + + // Set Pixel Shader Combos + DECLARE_DYNAMIC_PIXEL_SHADER( prototype_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( AMBIENT_LIGHT, lightState.m_bAmbientLight ? 1 : 0 ); + SET_DYNAMIC_PIXEL_SHADER( prototype_ps20b ); + + // Bind textures + pShader->BindTexture( SHADER_SAMPLER0, info.m_nBaseTexture, info.m_nBaseTextureFrame ); + + bool bBumpMapping = ( ( info.m_nBumpmap == -1 ) || !params[info.m_nBumpmap]->IsTexture() ) ? false : true; + if ( bBumpMapping ) + { + pShader->BindTexture( SHADER_SAMPLER1, info.m_nBumpmap, info.m_nBumpFrame ); + } + + // Set c0 and c1 to contain first two rows of ViewProj matrix + VMatrix mView, mProj; + pShaderAPI->GetMatrix( MATERIAL_VIEW, mView.m[0] ); + pShaderAPI->GetMatrix( MATERIAL_PROJECTION, mProj.m[0] ); + VMatrix mViewProj = mView * mProj; + mViewProj = mViewProj.Transpose3x3(); + pShaderAPI->SetPixelShaderConstant( 0, mViewProj.m[0], 2 ); + + // Camera pos + float vEyePos[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos ); + pShaderAPI->SetPixelShaderConstant( 2, vEyePos, 1 ); + } + pShader->Draw(); +} diff --git a/materialsystem/stdshaders/prototype_helper.h b/materialsystem/stdshaders/prototype_helper.h new file mode 100644 index 00000000..f788745b --- /dev/null +++ b/materialsystem/stdshaders/prototype_helper.h @@ -0,0 +1,38 @@ +//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============// + +#ifndef PROTOTYPE_HELPER_H +#define PROTOTYPE_HELPER_H +#ifdef _WIN32 +#pragma once +#endif + +#include + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct PrototypeVars_t +{ + PrototypeVars_t() { memset( this, 0xFF, sizeof(PrototypeVars_t) ); } + + int m_nBaseTexture; + int m_nBaseTextureFrame; + + int m_nBumpmap; + int m_nBumpFrame; +}; + +void InitParamsPrototype( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, PrototypeVars_t &info ); +void InitPrototype( CBaseVSShader *pShader, IMaterialVar** params, PrototypeVars_t &info ); +void DrawPrototype( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, PrototypeVars_t &info, VertexCompressionType_t vertexCompression ); + +#endif // PROTOTYPE_HELPER_H diff --git a/materialsystem/stdshaders/prototype_ps20b.fxc b/materialsystem/stdshaders/prototype_ps20b.fxc new file mode 100644 index 00000000..4a648501 --- /dev/null +++ b/materialsystem/stdshaders/prototype_ps20b.fxc @@ -0,0 +1,93 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "VERTEXCOLOR" "0..1" + +// DYNAMIC: "NUM_LIGHTS" "0..4" [ps20b] +// DYNAMIC: "NUM_LIGHTS" "0..4" [ps30] +// DYNAMIC: "AMBIENT_LIGHT" "0..1" + +// Includes ======================================================================================= +#include "common_vertexlitgeneric_dx9.h" + +// Texture Samplers =============================================================================== +sampler g_tColorSampler : register( s0 ); +sampler g_tBumpSampler : register( s1 ); +sampler g_tDummySampler : register( s2 ); + +// Shaders Constants and Globals ================================================================== +const float4 g_mViewProj0 : register( c0 ); // 1st row of matrix +const float4 g_mViewProj1 : register( c1 ); // 2nd row of matrix +const float4 g_vCameraPosition : register( c2 ); +const float3 g_ambientCube[6] : register( c3 ); + //: register( c4 ); + //: register( c5 ); + //: register( c6 ); + //: register( c7 ); + //: register( c8 ); + +PixelShaderLightInfo g_lightInfo[3] : register( c9 ); // 2 registers each - 6 registers total + //: register( c10 ); + //: register( c11 ); + //: register( c12 ); + //: register( c13 ); + //: register( c14 ); + +// Interpolated values ============================================================================ +struct PS_INPUT +{ + float2 vUv0 : TEXCOORD0; + float3 vWorldNormal : TEXCOORD1; + float3 vWorldTangent : TEXCOORD2; + float3 vWorldBinormal : TEXCOORD3; + float3 vWorldPosition : TEXCOORD4; + float4 vLightAtten : TEXCOORD5; + #if ( VERTEXCOLOR ) + float4 vVertexColor : COLOR0; + #endif +}; + +// Main =========================================================================================== +float4 main( PS_INPUT i ) : COLOR +{ + // Color + float4 cBaseColor = tex2D( g_tColorSampler, i.vUv0.xy ); + + // Bump + float4 vBumpTexel = tex2D( g_tBumpSampler, i.vUv0.xy ); + + // Combine bump layers into tangetn normal + float3 vTangentNormal = ( vBumpTexel * 2.0f ) - 1.0f; + + // Transform into world space + float3 vWorldNormal = Vec3TangentToWorld( vTangentNormal.xyz, i.vWorldNormal.xyz, i.vWorldTangent.xyz, i.vWorldBinormal.xyz ); + + // Lighting + float3 cDiffuse = float3( 0.0f, 0.0f, 0.0f ); + #if ( VERTEXCOLOR ) + { + // Use interpolated vertex colors + cDiffuse.rgb = i.vVertexColor.rgb; + } + #else + { + // Compute lighting + cDiffuse.rgb = PixelShaderDoLighting( i.vWorldPosition.xyz, normalize( vWorldNormal.xyz ), + float3( 0.0f, 0.0f, 0.0f ), false, AMBIENT_LIGHT, i.vLightAtten.xyzw, + g_ambientCube, g_tDummySampler, NUM_LIGHTS, g_lightInfo, false, + false, g_tDummySampler ); + } + #endif + + //===============// + // Combine terms // + //===============// + float4 result; + result.rgb = cBaseColor.rgb; + result.rgb *= cDiffuse.rgb; + + // Set alpha to... + result.a = 0.0f; + + return FinalOutput( result, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_LINEAR ); //go back to final output when it'll fit. +} + \ No newline at end of file diff --git a/materialsystem/stdshaders/prototype_vs20.fxc b/materialsystem/stdshaders/prototype_vs20.fxc new file mode 100644 index 00000000..0410d0ac --- /dev/null +++ b/materialsystem/stdshaders/prototype_vs20.fxc @@ -0,0 +1,91 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "VERTEXCOLOR" "0..1" + +// DYNAMIC: "SKINNING" "0..1" +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "DYNAMIC_LIGHT" "0..1" +// DYNAMIC: "STATIC_LIGHT" "0..1" +// DYNAMIC: "NUM_LIGHTS" "0..4" + +// Includes ======================================================================================= +#include "common_vs_fxc.h" + +// Structs ======================================================================================== +struct VS_INPUT +{ + float4 vPos : POSITION; // Position + float4 vNormal : NORMAL; // Normal + float4 vBoneWeights : BLENDWEIGHT; // Skin weights + float4 vBoneIndices : BLENDINDICES; // Skin indices + float4 vTexCoord0 : TEXCOORD0; // Base texture coordinates + float4 vTangent : TANGENT; + #if ( VERTEXCOLOR ) + float4 vVertexColor : COLOR0; + #endif +}; + +struct VS_OUTPUT +{ + float4 vProjPosition : POSITION; // Projection-space position + float2 vUv0 : TEXCOORD0; + float3 vWorldNormal : TEXCOORD1; + float3 vWorldTangent : TEXCOORD2; + float3 vWorldBinormal : TEXCOORD3; + float3 vWorldPosition : TEXCOORD4; + float4 vLightAtten : TEXCOORD5; + #if ( VERTEXCOLOR ) + float4 vVertexColor : COLOR0; + #endif +}; + +// Main =========================================================================================== +VS_OUTPUT main( const VS_INPUT i ) +{ + VS_OUTPUT o; + + float4 vObjPosition = i.vPos; + float4 vObjTangent = i.vTangent; + float3 vObjNormal; + DecompressVertex_Normal( i.vNormal, vObjNormal ); + + // Transform the position + float3 vWorldPosition = { 0.0f, 0.0f, 0.0f }; + float3 vWorldNormal = { 0.0f, 0.0f, 0.0f }; + float3 vWorldTangent = { 0.0f, 0.0f, 0.0f }; + float3 vWorldBinormal = { 0.0f, 0.0f, 0.0f }; + SkinPositionNormalAndTangentSpace( SKINNING, vObjPosition, vObjNormal.xyz, vObjTangent.xyzw, i.vBoneWeights, i.vBoneIndices, vWorldPosition, vWorldNormal, vWorldTangent, vWorldBinormal ); + vWorldNormal.xyz = normalize( vWorldNormal.xyz ); + vWorldTangent.xyz = normalize( vWorldTangent.xyz ); + vWorldBinormal.xyz = normalize( vWorldBinormal.xyz ); + + o.vWorldNormal.xyz = vWorldNormal.xyz; + o.vWorldTangent.xyz = vWorldTangent.xyz; + o.vWorldBinormal.xyz = vWorldBinormal.xyz; + o.vWorldPosition.xyz = vWorldPosition.xyz; + + // Transform into projection space + float4 vProjPosition = mul( float4( vWorldPosition, 1.0f ), cViewProj ); + o.vProjPosition.xyzw = vProjPosition.xyzw; + + // View vector + float3 vWorldViewVector = normalize( vWorldPosition.xyz - cEyePos.xyz ); + + // Texture coordinates + o.vUv0.xy = i.vTexCoord0.xy; + + // Scalar light attenuation + o.vLightAtten.x = GetVertexAttenForLight( vWorldPosition.xyz, 0 ); + o.vLightAtten.y = GetVertexAttenForLight( vWorldPosition.xyz, 1 ); + o.vLightAtten.z = GetVertexAttenForLight( vWorldPosition.xyz, 2 ); + o.vLightAtten.w = GetVertexAttenForLight( vWorldPosition.xyz, 3 ); + + #if ( VERTEXCOLOR ) + { + o.vVertexColor.rgb = GammaToLinear( i.vVertexColor.rgb ); + o.vVertexColor.a = i.vVertexColor.a; + } + #endif + + return o; +} diff --git a/materialsystem/stdshaders/refract.cpp b/materialsystem/stdshaders/refract.cpp new file mode 100644 index 00000000..ea494671 --- /dev/null +++ b/materialsystem/stdshaders/refract.cpp @@ -0,0 +1,121 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" +#include "convar.h" +#include "refract_dx9_helper.h" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +DEFINE_FALLBACK_SHADER( Refract, Refract_DX90 ) + +BEGIN_VS_SHADER( Refract_DX90, "Help for Refract" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM_OVERRIDE( COLOR, SHADER_PARAM_TYPE_COLOR, "{255 255 255}", "unused", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM_OVERRIDE( ALPHA, SHADER_PARAM_TYPE_FLOAT, "1.0", "unused", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM( REFRACTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "2", "" ) + SHADER_PARAM( REFRACTTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "refraction tint" ) + SHADER_PARAM( NORMALMAP, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "normal map" ) + SHADER_PARAM( NORMALMAP2, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "normal map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $normalmap" ) + SHADER_PARAM( BUMPFRAME2, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $normalmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$normalmap texcoord transform" ) + SHADER_PARAM( BUMPTRANSFORM2, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$normalmap texcoord transform" ) + SHADER_PARAM( TIME, SHADER_PARAM_TYPE_FLOAT, "0.0f", "" ) + SHADER_PARAM( BLURAMOUNT, SHADER_PARAM_TYPE_INTEGER, "1", "0, 1, or 2 for how much blur you want" ) + SHADER_PARAM( FADEOUTONSILHOUETTE, SHADER_PARAM_TYPE_BOOL, "1", "0 for no fade out on silhouette, 1 for fade out on sillhouette" ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "envmap frame number" ) + SHADER_PARAM( ENVMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "envmap tint" ) + SHADER_PARAM( ENVMAPCONTRAST, SHADER_PARAM_TYPE_FLOAT, "0.0", "contrast 0 == normal 1 == color*color" ) + SHADER_PARAM( ENVMAPSATURATION, SHADER_PARAM_TYPE_FLOAT, "1.0", "saturation 0 == greyscale 1 == normal" ) + SHADER_PARAM( REFRACTTINTTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shield", "" ) + SHADER_PARAM( REFRACTTINTTEXTUREFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( FRESNELREFLECTION, SHADER_PARAM_TYPE_FLOAT, "1.0", "1.0 == mirror, 0.0 == water" ) + SHADER_PARAM( NOWRITEZ, SHADER_PARAM_TYPE_INTEGER, "0", "0 == write z, 1 = no write z" ) + SHADER_PARAM( MASKED, SHADER_PARAM_TYPE_BOOL, "0", "mask using dest alpha" ) + SHADER_PARAM( VERTEXCOLORMODULATE, SHADER_PARAM_TYPE_BOOL, "0","Use the vertex color to effect refract color. alpha will adjust refract amount" ) + SHADER_PARAM( NOVIEWPORTFIXUP, SHADER_PARAM_TYPE_INTEGER, "0", "Don't adjust uv's for current viewport" ) + SHADER_PARAM( MIRRORABOUTVIEWPORTEDGES, SHADER_PARAM_TYPE_INTEGER, "0", "don't sample outside of the viewport" ) + SHADER_PARAM( MAGNIFYENABLE, SHADER_PARAM_TYPE_BOOL, "0", "Enable magnification of refracted image around the $magnifyCenter screen position by $magnifyScale" ) + SHADER_PARAM( MAGNIFYCENTER, SHADER_PARAM_TYPE_VEC2, "[0 0]", "Magnify refracted image around this screen position" ) + SHADER_PARAM( MAGNIFYSCALE, SHADER_PARAM_TYPE_FLOAT, "0", "Magnify refracted image by this factor" ) + END_SHADER_PARAMS +// FIXME: doesn't support Fresnel! + + void SetupVars( Refract_DX9_Vars_t& info ) + { + info.m_nBaseTexture = BASETEXTURE; + info.m_nFrame = FRAME; + info.m_nRefractAmount = REFRACTAMOUNT; + info.m_nRefractTint = REFRACTTINT; + info.m_nNormalMap = NORMALMAP; + info.m_nNormalMap2 = NORMALMAP2; + info.m_nBumpFrame = BUMPFRAME; + info.m_nBumpFrame2 = BUMPFRAME2; + info.m_nBumpTransform = BUMPTRANSFORM; + info.m_nBumpTransform2 = BUMPTRANSFORM2; + info.m_nBlurAmount = BLURAMOUNT; + info.m_nFadeOutOnSilhouette = FADEOUTONSILHOUETTE; + info.m_nEnvmap = ENVMAP; + info.m_nEnvmapFrame = ENVMAPFRAME; + info.m_nEnvmapTint = ENVMAPTINT; + info.m_nEnvmapContrast = ENVMAPCONTRAST; + info.m_nEnvmapSaturation = ENVMAPSATURATION; + info.m_nRefractTintTexture = REFRACTTINTTEXTURE; + info.m_nRefractTintTextureFrame = REFRACTTINTTEXTUREFRAME; + info.m_nFresnelReflection = FRESNELREFLECTION; + info.m_nNoWriteZ = NOWRITEZ; + info.m_nMasked = MASKED; + info.m_nVertexColorModulate = VERTEXCOLORMODULATE; + info.m_nNoViewportFixup = NOVIEWPORTFIXUP; + info.m_nMirrorAboutViewportEdges = MIRRORABOUTVIEWPORTEDGES; + info.m_nMagnifyEnable = MAGNIFYENABLE; + info.m_nMagnifyCenter = MAGNIFYCENTER; + info.m_nMagnifyScale = MAGNIFYSCALE; + } + + SHADER_INIT_PARAMS() + { + Refract_DX9_Vars_t info; + SetupVars( info ); + InitParamsRefract_DX9( this, params, pMaterialName, info ); + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + Refract_DX9_Vars_t info; + SetupVars( info ); + InitRefract_DX9( this, params, info ); + } + + SHADER_DRAW + { + Refract_DX9_Vars_t info; + SetupVars( info ); + + // If ( snapshotting ) or ( we need to draw this frame ) + bool bHasFlashlight = this->UsingFlashlight( params ); + bool bSinglePassFlashlight = ( pShaderAPI != NULL ) ? pShaderAPI->SinglePassFlashlightModeEnabled() : false; + if ( ( pShaderShadow != NULL ) || ( !bHasFlashlight ) || ( bSinglePassFlashlight ) ) + { + DrawRefract_DX9( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else + { + Draw( false ); + } + } +END_SHADER diff --git a/materialsystem/stdshaders/refract_dx9_helper.cpp b/materialsystem/stdshaders/refract_dx9_helper.cpp new file mode 100644 index 00000000..66b36bc9 --- /dev/null +++ b/materialsystem/stdshaders/refract_dx9_helper.cpp @@ -0,0 +1,360 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" +#include "refract_dx9_helper.h" +#include "convar.h" +#include "refract_vs20.inc" +#include "refract_ps20.inc" +#include "refract_ps20b.inc" +#include "cpp_shader_constant_register_map.h" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +#define MAXBLUR 1 + +// number of pixels to shrink the viewport by when handling mirroring of texcoords about the viewport edges. This deals with not stepping out of viewport due to blurring, etc. +#define REFRACT_VIEWPORT_SHRINK_PIXELS ( 2 ) + +// FIXME: doesn't support fresnel! +void InitParamsRefract_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, Refract_DX9_Vars_t &info ) +{ + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + SET_FLAGS( MATERIAL_VAR_TRANSLUCENT ); + if( !params[info.m_nEnvmapTint]->IsDefined() ) + { + params[info.m_nEnvmapTint]->SetVecValue( 1.0f, 1.0f, 1.0f ); + } + if( !params[info.m_nEnvmapContrast]->IsDefined() ) + { + params[info.m_nEnvmapContrast]->SetFloatValue( 0.0f ); + } + if( !params[info.m_nEnvmapSaturation]->IsDefined() ) + { + params[info.m_nEnvmapSaturation]->SetFloatValue( 1.0f ); + } + if( !params[info.m_nEnvmapFrame]->IsDefined() ) + { + params[info.m_nEnvmapFrame]->SetIntValue( 0 ); + } + if( !params[info.m_nFresnelReflection]->IsDefined() ) + { + params[info.m_nFresnelReflection]->SetFloatValue( 1.0f ); + } + if( !params[info.m_nMasked]->IsDefined() ) + { + params[info.m_nMasked]->SetIntValue( 0 ); + } + if( !params[info.m_nBlurAmount]->IsDefined() ) + { + params[info.m_nBlurAmount]->SetIntValue( 0 ); + } + if( !params[info.m_nFadeOutOnSilhouette]->IsDefined() ) + { + params[info.m_nFadeOutOnSilhouette]->SetIntValue( 0 ); + } + if( !params[info.m_nNoViewportFixup]->IsDefined() ) + { + params[info.m_nNoViewportFixup]->SetIntValue( 0 ); + } + if( !params[info.m_nMirrorAboutViewportEdges]->IsDefined() ) + { + params[info.m_nMirrorAboutViewportEdges]->SetIntValue( 0 ); + } + if ( !params[info.m_nMagnifyEnable]->IsDefined() ) + { + params[info.m_nMagnifyEnable]->SetIntValue( 0 ); + } + if ( !params[info.m_nMagnifyCenter]->IsDefined() ) + { + params[info.m_nMagnifyCenter]->SetVecValue( 0, 0, 0, 0 ); + } + if ( !params[info.m_nMagnifyScale]->IsDefined() ) + { + params[info.m_nMagnifyScale]->SetIntValue( 0 ); + } + SET_FLAGS2( MATERIAL_VAR2_NEEDS_POWER_OF_TWO_FRAME_BUFFER_TEXTURE ); +} + +void InitRefract_DX9( CBaseVSShader *pShader, IMaterialVar** params, Refract_DX9_Vars_t &info ) +{ + if (params[info.m_nBaseTexture]->IsDefined() ) + { + pShader->LoadTexture( info.m_nBaseTexture ); + } + if (params[info.m_nNormalMap]->IsDefined() ) + { + pShader->LoadBumpMap( info.m_nNormalMap ); + } + if (params[info.m_nNormalMap2]->IsDefined() ) + { + pShader->LoadBumpMap( info.m_nNormalMap2 ); + } + if( params[info.m_nEnvmap]->IsDefined() ) + { + pShader->LoadCubeMap( info.m_nEnvmap ); + } + if( params[info.m_nRefractTintTexture]->IsDefined() ) + { + pShader->LoadTexture( info.m_nRefractTintTexture ); + } +} + +void DrawRefract_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, Refract_DX9_Vars_t &info, VertexCompressionType_t vertexCompression ) +{ + bool bIsModel = IS_FLAG_SET( MATERIAL_VAR_MODEL ); + bool bHasEnvmap = params[info.m_nEnvmap]->IsTexture(); + bool bRefractTintTexture = params[info.m_nRefractTintTexture]->IsTexture(); + bool bFadeOutOnSilhouette = params[info.m_nFadeOutOnSilhouette]->GetIntValue() != 0; + int blurAmount = params[info.m_nBlurAmount]->GetIntValue(); + bool bMasked = (params[info.m_nMasked]->GetIntValue() != 0); + bool bSecondaryNormal = ( ( info.m_nNormalMap2 != -1 ) && ( params[info.m_nNormalMap2]->IsTexture() ) ); + bool bColorModulate = ( ( info.m_nVertexColorModulate != -1 ) && ( params[info.m_nVertexColorModulate]->GetIntValue() ) ); + bool bWriteZ = params[info.m_nNoWriteZ]->GetIntValue() == 0; + bool bMirrorAboutViewportEdges = IsX360() && ( info.m_nMirrorAboutViewportEdges != -1 ) && ( params[info.m_nMirrorAboutViewportEdges]->GetIntValue() != 0 ); + bool bUseMagnification = params[info.m_nMagnifyEnable]->GetIntValue() != 0; + + if( blurAmount < 0 ) + { + blurAmount = 0; + } + else if( blurAmount > MAXBLUR ) + { + blurAmount = MAXBLUR; + } + + BlendType_t nBlendType = pShader->EvaluateBlendRequirements( BASETEXTURE, true ); + bool bFullyOpaque = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !IS_FLAG_SET(MATERIAL_VAR_ALPHATEST); //dest alpha is free for special use + bFullyOpaque &= !bMasked; + + bool bTranslucentNormal = pShader->TextureIsTranslucent( info.m_nNormalMap, false ); + bFullyOpaque &= (! bTranslucentNormal ); + + SHADOW_STATE + { + pShader->SetInitialShadowState( ); + + pShaderShadow->EnableDepthWrites( bWriteZ ); + + // Alpha test: FIXME: shouldn't this be handled in Shader_t::SetInitialShadowState + pShaderShadow->EnableAlphaTest( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) ); + + // If envmap is not specified, the alpha channel is the translucency + // (If envmap *is* specified, alpha channel is the reflection amount) + if ( params[info.m_nNormalMap]->IsTexture() && !bHasEnvmap ) + { + pShader->SetDefaultBlendingShadowState( info.m_nNormalMap, false ); + } + + // source render target that contains the image that we are warping. + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, !IsX360() ); + + // normal map + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + + if ( bSecondaryNormal ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + } + + if( bHasEnvmap ) + { + // envmap + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER4, true ); + } + if( bRefractTintTexture ) + { + // refract tint texture + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER5, true ); + } + + pShaderShadow->EnableSRGBWrite( true ); + + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL; + int userDataSize = 0; + int nTexCoordCount = 1; + if( bIsModel ) + { + userDataSize = 4; + } + else + { + flags |= VERTEX_TANGENT_S | VERTEX_TANGENT_T; + } + + if ( bColorModulate ) + { + flags |= VERTEX_COLOR; + } + + // This shader supports compressed vertices, so OR in that flag: + flags |= VERTEX_FORMAT_COMPRESSED; + + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + DECLARE_STATIC_VERTEX_SHADER( refract_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( MODEL, bIsModel ); + SET_STATIC_VERTEX_SHADER_COMBO( COLORMODULATE, bColorModulate ); + SET_STATIC_VERTEX_SHADER( refract_vs20 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( refract_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( BLUR, blurAmount ); + SET_STATIC_PIXEL_SHADER_COMBO( FADEOUTONSILHOUETTE, bFadeOutOnSilhouette ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( REFRACTTINTTEXTURE, bRefractTintTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( MASKED, bMasked ); + SET_STATIC_PIXEL_SHADER_COMBO( COLORMODULATE, bColorModulate ); + SET_STATIC_PIXEL_SHADER_COMBO( SECONDARY_NORMAL, bSecondaryNormal ); + SET_STATIC_PIXEL_SHADER_COMBO( MIRRORABOUTVIEWPORTEDGES, bMirrorAboutViewportEdges ); + SET_STATIC_PIXEL_SHADER_COMBO( MAGNIFY, bUseMagnification ); + SET_STATIC_PIXEL_SHADER( refract_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( refract_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( BLUR, blurAmount ); + SET_STATIC_PIXEL_SHADER_COMBO( FADEOUTONSILHOUETTE, bFadeOutOnSilhouette ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( REFRACTTINTTEXTURE, bRefractTintTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( MASKED, bMasked ); + SET_STATIC_PIXEL_SHADER_COMBO( COLORMODULATE, bColorModulate ); + SET_STATIC_PIXEL_SHADER_COMBO( SECONDARY_NORMAL, bSecondaryNormal ); + SET_STATIC_PIXEL_SHADER_COMBO( MIRRORABOUTVIEWPORTEDGES, bMirrorAboutViewportEdges ); + SET_STATIC_PIXEL_SHADER_COMBO( MAGNIFY, bUseMagnification ); + SET_STATIC_PIXEL_SHADER( refract_ps20 ); + } + pShader->DefaultFog(); + if( bMasked ) + { + pShader->EnableAlphaBlending( SHADER_BLEND_ONE_MINUS_SRC_ALPHA, SHADER_BLEND_SRC_ALPHA ); + } + + pShaderShadow->EnableAlphaWrites( bFullyOpaque ); + } + DYNAMIC_STATE + { + pShaderAPI->SetDefaultState(); + + if ( params[info.m_nBaseTexture]->IsTexture() ) + { + pShader->BindTexture( SHADER_SAMPLER2, info.m_nBaseTexture, info.m_nFrame ); + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_FRAME_BUFFER_FULL_TEXTURE_0 ); + } + + pShader->BindTexture( SHADER_SAMPLER3, info.m_nNormalMap, info.m_nBumpFrame ); + + if ( bSecondaryNormal ) + { + pShader->BindTexture( SHADER_SAMPLER1, info.m_nNormalMap2, info.m_nBumpFrame2 ); + } + + if( bHasEnvmap ) + { + pShader->BindTexture( SHADER_SAMPLER4, info.m_nEnvmap, info.m_nEnvmapFrame ); + } + + if( bRefractTintTexture ) + { + pShader->BindTexture( SHADER_SAMPLER5, info.m_nRefractTintTexture, info.m_nRefractTintTextureFrame ); + } + + DECLARE_DYNAMIC_VERTEX_SHADER( refract_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( refract_vs20 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( refract_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bWriteZ && bFullyOpaque && pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( refract_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( refract_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( refract_ps20 ); + } + + pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, info.m_nBumpTransform ); // 1 & 2 + pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, info.m_nBumpTransform2 ); // 3 & 4 + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + float vEyePos_SpecExponent[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + vEyePos_SpecExponent[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + + pShader->SetPixelShaderConstantGammaToLinear( 0, info.m_nEnvmapTint ); + pShader->SetPixelShaderConstantGammaToLinear( 1, info.m_nRefractTint ); + pShader->SetPixelShaderConstant( 2, info.m_nEnvmapContrast ); + pShader->SetPixelShaderConstant( 3, info.m_nEnvmapSaturation ); + float c5[4] = { params[info.m_nRefractAmount]->GetFloatValue(), + params[info.m_nRefractAmount]->GetFloatValue(), 0.0f, 0.0f }; + + // Time % 1000 + c5[3] = pShaderAPI->CurrentTime(); + c5[3] -= (float)( (int)( c5[3] / 1000.0f ) ) * 1000.0f; + pShaderAPI->SetPixelShaderConstant( 5, c5, 1 ); + + float c6[4]; + params[info.m_nMagnifyCenter]->GetVecValue( c6, 2 ); + c6[2] = params[info.m_nMagnifyScale]->GetFloatValue(); + if ( c6[2] != 0 ) + { + c6[2] = 1.0f / c6[2]; // Shader uses the inverse scale value + } + pShaderAPI->SetPixelShaderConstant( 6, c6, 1 ); + + float cVs3[4] = { c5[3], 0.0f, 0.0f, 0.0f }; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_5, cVs3, 1 ); + + // Get viewport and render target dimensions and set shader constant to do a 2D mad and also deal with mirror on viewport edges. + int nViewportX, nViewportY, nViewportWidth, nViewportHeight; + pShaderAPI->GetCurrentViewport( nViewportX, nViewportY, nViewportWidth, nViewportHeight ); + + int nRtWidth, nRtHeight; + pShaderAPI->GetCurrentRenderTargetDimensions( nRtWidth, nRtHeight ); + + float vViewportMad[4] = { 1.0f, 1.0f, 0.0f, 0.0f }; + if ( params[ info.m_nNoViewportFixup ]->GetIntValue() == 0 ) + { + vViewportMad[0] = ( float )nViewportWidth / ( float )nRtWidth; + vViewportMad[1] = ( float )nViewportHeight / ( float )nRtHeight; + vViewportMad[2] = ( float )nViewportX / ( float )nRtWidth; + vViewportMad[3] = ( float )nViewportY / ( float )nRtHeight; + } + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, vViewportMad, 1 ); + + if ( bMirrorAboutViewportEdges ) + { + // Need the extents that we are allowed to sample from the refract texture to clamp by for splitscreen, etc. + float vNormalizedViewportMinXYMaxWZ[4]; + + vNormalizedViewportMinXYMaxWZ[0] = ( float )( nViewportX + REFRACT_VIEWPORT_SHRINK_PIXELS ) / ( float )nRtWidth; + vNormalizedViewportMinXYMaxWZ[1] = ( float )( nViewportY + REFRACT_VIEWPORT_SHRINK_PIXELS ) / ( float )nRtHeight; + vNormalizedViewportMinXYMaxWZ[3] = ( float )( nViewportX + nViewportWidth - REFRACT_VIEWPORT_SHRINK_PIXELS - 1 ) / ( float )nRtWidth; + vNormalizedViewportMinXYMaxWZ[2] = ( float )( nViewportY + nViewportHeight - REFRACT_VIEWPORT_SHRINK_PIXELS - 1 ) / ( float )nRtHeight; + + pShaderAPI->SetPixelShaderConstant( 4, vNormalizedViewportMinXYMaxWZ, 1 ); + } + } + pShader->Draw(); +} + diff --git a/materialsystem/stdshaders/refract_dx9_helper.h b/materialsystem/stdshaders/refract_dx9_helper.h new file mode 100644 index 00000000..74b135cb --- /dev/null +++ b/materialsystem/stdshaders/refract_dx9_helper.h @@ -0,0 +1,66 @@ +//====== Copyright © 1996-2006, Valve Corporation, All rights reserved. ======= +// +// Purpose: +// +//============================================================================= + +#ifndef REFRACT_DX9_HELPER_H +#define REFRACT_DX9_HELPER_H +#ifdef _WIN32 +#pragma once +#endif + +#include + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct Refract_DX9_Vars_t +{ + Refract_DX9_Vars_t() { memset( this, 0xFF, sizeof( *this ) ); } + + int m_nBaseTexture; + int m_nFrame; + int m_nRefractAmount; + int m_nRefractTint; + int m_nNormalMap; + int m_nNormalMap2; + int m_nBumpFrame; + int m_nBumpFrame2; + int m_nBumpTransform; + int m_nBumpTransform2; + int m_nBlurAmount; + int m_nFadeOutOnSilhouette; + int m_nEnvmap; + int m_nEnvmapFrame; + int m_nEnvmapTint; + int m_nEnvmapContrast; + int m_nEnvmapSaturation; + int m_nRefractTintTexture; + int m_nRefractTintTextureFrame; + int m_nFresnelReflection; + int m_nNoWriteZ; + int m_nMasked; + int m_nVertexColorModulate; + int m_nNoViewportFixup; + int m_nMirrorAboutViewportEdges; + int m_nMagnifyEnable; + int m_nMagnifyCenter; + int m_nMagnifyScale; +}; + +void InitParamsRefract_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, + Refract_DX9_Vars_t &info ); +void InitRefract_DX9( CBaseVSShader *pShader, IMaterialVar** params, Refract_DX9_Vars_t &info ); +void DrawRefract_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, Refract_DX9_Vars_t &info, VertexCompressionType_t vertexCompression ); + +#endif // REFRACT_DX9_HELPER_H diff --git a/materialsystem/stdshaders/refract_ps2x.fxc b/materialsystem/stdshaders/refract_ps2x.fxc new file mode 100644 index 00000000..414c496b --- /dev/null +++ b/materialsystem/stdshaders/refract_ps2x.fxc @@ -0,0 +1,248 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "MAGNIFY" "0..1" +// STATIC: "BLUR" "0..1" +// STATIC: "FADEOUTONSILHOUETTE" "0..1" +// STATIC: "CUBEMAP" "0..1" +// STATIC: "REFRACTTINTTEXTURE" "0..1" +// STATIC: "MASKED" "0..1" +// STATIC: "COLORMODULATE" "0..1" +// STATIC: "SECONDARY_NORMAL" "0..1" +// STATIC: "MIRRORABOUTVIEWPORTEDGES" "0..1" [XBOX] +// STATIC: "MIRRORABOUTVIEWPORTEDGES" "0..0" [PC] + +#include "common_fog_ps_fxc.h" +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] + +// SKIP: $MASKED && $BLUR + +#if defined( SHADER_MODEL_PS_2_0 ) +# define WRITE_DEPTH_TO_DESTALPHA 0 +#endif + +#ifdef _X360 + #define SHADER_SRGB_READ 1 +#endif + +#include "common_ps_fxc.h" +#include "shader_constant_register_map.h" + +sampler NormalSampler2 : register( s1 ); +sampler RefractSampler : register( s2 ); +sampler NormalSampler : register( s3 ); +#if CUBEMAP +sampler EnvmapSampler : register( s4 ); +#endif +#if REFRACTTINTTEXTURE +sampler RefractTintSampler : register( s5 ); +#endif + +const float3 g_EnvmapTint : register( c0 ); +const float3 g_RefractTint : register( c1 ); +const float3 g_EnvmapContrast : register( c2 ); +const float3 g_EnvmapSaturation : register( c3 ); +const float4 g_NormalizedViewportMinXYMaxWZ : register( c4 ); +const float4 g_c5 : register( c5 ); +#define g_RefractScale g_c5.x +#define g_flTime g_c5.w + +const float4 g_c6 : register( c6 ); +#define g_vMagnifyCenter g_c6.xy +#define g_flInverseMagnifyScale g_c6.z + +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT ); + +static const int g_BlurCount = BLUR; +static const float g_BlurFraction = 1.0f / 512.0f; +static const float g_HalfBlurFraction = 0.5 * g_BlurFraction; +static const float4 g_BlurFractionVec = float4( g_BlurFraction, g_HalfBlurFraction, + -g_BlurFraction,-g_HalfBlurFraction ); + +struct PS_INPUT +{ + float4 vBumpTexCoord : TEXCOORD0; // NormalMap1 in xy, NormalMap2 in wz + float3 vTangentVertToEyeVector : TEXCOORD1; + float3 vWorldNormal : TEXCOORD2; + float3 vWorldTangent : TEXCOORD3; + float3 vWorldBinormal : TEXCOORD4; + float3 vRefractXYW : TEXCOORD5; + float3 vWorldViewVector : TEXCOORD6; + #if COLORMODULATE + float4 ColorModulate : COLOR0; + #endif + + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float3 result; + + float pixelFogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos_SpecExponent.xyz, i.worldPos_projPosZ.xyz, i.worldPos_projPosZ.w ); + + #if FADEOUTONSILHOUETTE || CUBEMAP + float3 vWorldNormal = i.vWorldNormal; + #endif + + + #if FADEOUTONSILHOUETTE + //float blend = -i.projNormal.z; + float blend = saturate( dot( -i.vWorldViewVector.xyz, vWorldNormal.xyz ) ); + blend = blend * blend * blend; + #else + float blend = 1.0f; + #endif + + // Sample normal + float4 normalTexel = tex2D( NormalSampler, i.vBumpTexCoord.xy ); + float4 vNormal = float4( normalTexel.xyz * 2.0f - 1.0f, normalTexel.a ); + + #if SECONDARY_NORMAL + float3 vNormal2 = tex2D( NormalSampler, i.vBumpTexCoord.wz ).xyz * 2.0f - 1.0f; + vNormal.xyz = normalize( vNormal.xyz + vNormal2.xyz ); + #endif + + #if REFRACTTINTTEXTURE + float3 refractTintColor = 2.0 * g_RefractTint * tex2D( RefractTintSampler, i.vBumpTexCoord.xy ); + #else + float3 refractTintColor = g_RefractTint; + #endif + + #if COLORMODULATE + refractTintColor *= i.ColorModulate.rgb; + #endif + + // Perform division by W only once + float ooW = 1.0f / i.vRefractXYW.z; + + // Compute coordinates for sampling refraction + float2 vRefractTexCoordNoWarp = i.vRefractXYW.xy * ooW; + float2 vRefractTexCoord = vNormal.xy; + float scale = vNormal.a * g_RefractScale; + #if COLORMODULATE + scale *= i.ColorModulate.a; + #endif + vRefractTexCoord *= scale; + + #if ( MAGNIFY ) + { + vRefractTexCoord += float2( 0.5, 0.5 ) + float2( g_vMagnifyCenter.x, g_vMagnifyCenter.y ); + vRefractTexCoord += ( vRefractTexCoordNoWarp - float2( 0.5, 0.5 ) - float2( g_vMagnifyCenter.x, g_vMagnifyCenter.y ) ) * g_flInverseMagnifyScale; + } + #else + { + vRefractTexCoord += vRefractTexCoordNoWarp; + } + #endif + + #if ( MIRRORABOUTVIEWPORTEDGES ) + { + // + // need to mirror the texcoords on every border so that one splitscreen viewport doesn't bleed into another one. + // + + // mirror on the min viewport in both dimensions + vRefractTexCoord.xy -= g_NormalizedViewportMinXYMaxWZ.xy; + vRefractTexCoord.xy = abs( vRefractTexCoord.xy ); + vRefractTexCoord.xy += g_NormalizedViewportMinXYMaxWZ.xy; + + // mirror on the max viewport in both dimensions + vRefractTexCoord.xy = g_NormalizedViewportMinXYMaxWZ.wz - vRefractTexCoord.xy; + vRefractTexCoord.xy = abs( vRefractTexCoord.xy ); + vRefractTexCoord.xy = g_NormalizedViewportMinXYMaxWZ.wz - vRefractTexCoord.xy; + } + #endif + + #if (BLUR==1) // use polyphase magic to convert 9 lookups into 4 + + // basic principle behind this transformation: + // [ A B C ] + // [ D E F ] + // [ G H I ] + // use bilinear filtering hardware to weight upper 2x2 samples evenly (0.25* [A + B + D + E]). + // scale the upper 2x2 by 4/9 (total area of kernel occupied) + // use bilinear filtering hardware to weight right 1x2 samples evenly (0.5*[C + F]) + // scale right 1x2 by 2/9 + // use bilinear filtering hardware to weight lower 2x1 samples evenly (0.5*[G + H]) + // scale bottom 2x1 by 2/9 + // fetch last sample (I) and scale by 1/9. + + float2 upper_2x2_loc = vRefractTexCoord.xy - float2(g_HalfBlurFraction, g_HalfBlurFraction); + float2 right_1x2_loc = vRefractTexCoord.xy + float2(g_BlurFraction, -g_HalfBlurFraction); + float2 lower_2x1_loc = vRefractTexCoord.xy + float2(-g_HalfBlurFraction, g_BlurFraction); + float2 singleton_loc = vRefractTexCoord.xy + float2(g_BlurFraction, g_BlurFraction); + result = tex2D(RefractSampler, upper_2x2_loc) * 0.4444444; + result += tex2D(RefractSampler, right_1x2_loc) * 0.2222222; + result += tex2D(RefractSampler, lower_2x1_loc) * 0.2222222; + result += tex2D(RefractSampler, singleton_loc) * 0.1111111; + + if ( IsX360() ) + { + result.rgb = X360GammaToLinear( result.rgb ); + } + + float3 unblurredColor = tex2Dsrgb(RefractSampler, vRefractTexCoordNoWarp.xy); + result = lerp(unblurredColor, result * refractTintColor, blend); + + #elif (BLUR>0) // iteratively step through render target + int x, y; + + result = float3( 0.0f, 0.0f, 0.0f ); + for( x = -g_BlurCount; x <= g_BlurCount; x++ ) + { + for( y = -g_BlurCount; y <= g_BlurCount; y++ ) + { + result += tex2D( RefractSampler, vRefractTexCoord.xy + float2( g_BlurFraction * x, g_BlurFraction * y ) ); + } + } + + if ( IsX360() ) + { + result.rgb = X360GammaToLinear( result.rgb ); + } + + int width = g_BlurCount * 2 + 1; + result *= 1.0f / ( width * width ); + + // result is the blurred one now. . .now lerp. + float3 unblurredColor = tex2Dsrgb( RefractSampler, vRefractTexCoordNoWarp.xy ); + result = lerp( unblurredColor, result * refractTintColor, blend ); + #else + #if MASKED + float4 fMaskedResult = tex2Dsrgb( RefractSampler, vRefractTexCoord.xy ); + return FinalOutput( fMaskedResult, pixelFogFactor, PIXELFOGTYPE, TONEMAP_SCALE_NONE ); + #else + float3 colorWarp = tex2Dsrgb( RefractSampler, vRefractTexCoord.xy ); + float3 colorNoWarp = tex2Dsrgb( RefractSampler, vRefractTexCoordNoWarp.xy ); + + colorWarp *= refractTintColor; + result = lerp( colorNoWarp, colorWarp, blend ); + #endif + #endif + + #if CUBEMAP + float specularFactor = vNormal.a; + + float3 worldSpaceNormal = Vec3TangentToWorld( vNormal.xyz, vWorldNormal, i.vWorldTangent, i.vWorldBinormal ); + + float3 reflectVect = CalcReflectionVectorUnnormalized( worldSpaceNormal, i.vTangentVertToEyeVector ); + float3 specularLighting = texCUBE( EnvmapSampler, reflectVect ); + specularLighting *= specularFactor; + specularLighting *= g_EnvmapTint; + float3 specularLightingSquared = specularLighting * specularLighting; + specularLighting = lerp( specularLighting, specularLightingSquared, g_EnvmapContrast ); + float3 greyScale = dot( specularLighting, float3( 0.299f, 0.587f, 0.114f ) ); + specularLighting = lerp( greyScale, specularLighting, g_EnvmapSaturation ); + result += specularLighting; + #endif + + #if COLORMODULATE + float resultAlpha = i.ColorModulate.a * vNormal.a; + #else + float resultAlpha = vNormal.a; + #endif + + return FinalOutput( float4( result, resultAlpha ), pixelFogFactor, PIXELFOGTYPE, TONEMAP_SCALE_NONE, (WRITE_DEPTH_TO_DESTALPHA != 0), i.worldPos_projPosZ.w ); +} diff --git a/materialsystem/stdshaders/rendertargetblit_ps2x.fxc b/materialsystem/stdshaders/rendertargetblit_ps2x.fxc new file mode 100644 index 00000000..78944902 --- /dev/null +++ b/materialsystem/stdshaders/rendertargetblit_ps2x.fxc @@ -0,0 +1,18 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#include "common_ps_fxc.h" + +sampler TexSampler : register( s0 ); + +struct PS_INPUT +{ + HALF2 baseTexCoord : TEXCOORD0; // Base texture coordinate +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float4 result = tex2D( TexSampler, i.baseTexCoord ); + + return FinalOutput( result, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} + diff --git a/materialsystem/stdshaders/rendertargetblit_vs20.fxc b/materialsystem/stdshaders/rendertargetblit_vs20.fxc new file mode 100644 index 00000000..15452c78 --- /dev/null +++ b/materialsystem/stdshaders/rendertargetblit_vs20.fxc @@ -0,0 +1,24 @@ +#include "common_vs_fxc.h" + +struct VS_INPUT +{ + float3 vPos : POSITION; + float2 vBaseTexCoord : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; + float2 baseTexCoord : TEXCOORD0; +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + o.projPos = float4( v.vPos, 1.0f ); + o.baseTexCoord = v.vBaseTexCoord; + return o; +} + + diff --git a/materialsystem/stdshaders/rendertargetblit_x360.cpp b/materialsystem/stdshaders/rendertargetblit_x360.cpp new file mode 100644 index 00000000..3be15b8e --- /dev/null +++ b/materialsystem/stdshaders/rendertargetblit_x360.cpp @@ -0,0 +1,83 @@ +//========= Copyright © 1996-2001, Valve LLC, All rights reserved. ============ +// +// Purpose: Replaces 360 missing StretchRect() functionality. +// +//============================================================================= + +#include "BaseVSShader.h" +#include "rendertargetblit_vs20.inc" +#include "rendertargetblit_ps20.inc" +#include "rendertargetblit_ps20b.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_VS_SHADER_FLAGS( RenderTargetBlit_X360, "", SHADER_NOT_EDITABLE ) + + BEGIN_SHADER_PARAMS + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + if ( !params[BASETEXTURE]->IsDefined() ) + { + params[BASETEXTURE]->SetStringValue( "_rt_FullFrameFB" ); + } + } + + SHADER_INIT + { + LoadTexture( BASETEXTURE ); + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, false ); + pShaderShadow->EnableSRGBWrite( false ); + + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->DepthFunc( SHADER_DEPTHFUNC_ALWAYS ); + pShaderShadow->EnableCulling( false ); + + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 1, 0, 0 ); + + DECLARE_STATIC_VERTEX_SHADER( rendertargetblit_vs20 ); + SET_STATIC_VERTEX_SHADER( rendertargetblit_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( rendertargetblit_ps20b ); + SET_STATIC_PIXEL_SHADER( rendertargetblit_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( rendertargetblit_ps20 ); + SET_STATIC_PIXEL_SHADER( rendertargetblit_ps20 ); + } + } + + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + + DECLARE_DYNAMIC_VERTEX_SHADER( rendertargetblit_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( rendertargetblit_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( rendertargetblit_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( rendertargetblit_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( rendertargetblit_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( rendertargetblit_ps20 ); + } + } + + Draw(); + } +END_SHADER diff --git a/materialsystem/stdshaders/sample4x4.cpp b/materialsystem/stdshaders/sample4x4.cpp new file mode 100644 index 00000000..b1ad93e1 --- /dev/null +++ b/materialsystem/stdshaders/sample4x4.cpp @@ -0,0 +1,118 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" +#include "common_hlsl_cpp_consts.h" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +BEGIN_VS_SHADER_FLAGS( Sample4x4, "Help for Sample4x4", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( BASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "" ) + SHADER_PARAM( PIXSHADER, SHADER_PARAM_TYPE_STRING, "sample4x4_ps20", "Name of the pixel shader to use" ) + END_SHADER_PARAMS + + SHADER_INIT + { + LoadTexture( BASETEXTURE ); + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableAlphaWrites( true ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + int fmt = VERTEX_POSITION; + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 ); + + pShaderShadow->SetVertexShader( "Downsample_vs20", 0 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + const char *szPixelShader = params[PIXSHADER]->GetStringValue(); + size_t iLength = Q_strlen( szPixelShader ); + + if( (iLength > 5) && (Q_stricmp( &szPixelShader[iLength - 5], "_ps20" ) == 0) ) //detect if it's trying to load a ps20 shader + { + //replace it with the ps20b shader + char *szNewName = (char *)stackalloc( sizeof( char ) * (iLength + 2) ); + memcpy( szNewName, szPixelShader, sizeof( char ) * iLength ); + szNewName[iLength] = 'b'; + szNewName[iLength + 1] = '\0'; + pShaderShadow->SetPixelShader( szNewName, 0 ); + } + else + { + pShaderShadow->SetPixelShader( params[PIXSHADER]->GetStringValue(), 0 ); + } + } + else + { + pShaderShadow->SetPixelShader( params[PIXSHADER]->GetStringValue(), 0 ); + } + +// if ( IsAlphaModulating() ) +// { +// pShaderShadow->EnableBlending( true ); +// pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, +// SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); +// } +// else +// { +// pShaderShadow->EnableBlending( true ); +// pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, +// SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); +// // pShaderShadow->EnableBlending( false ); +// } + } + + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, -1 ); + ITexture *src_texture=params[BASETEXTURE]->GetTextureValue(); + + int width=src_texture->GetActualWidth(); + int height=src_texture->GetActualHeight(); + + float v[4]; + float dX = 1.0f / width; + float dY = 1.0f / height; + + v[0] = -dX; + v[1] = -dY; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, v, 1 ); + v[0] = -dX; + v[1] = dY; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, v, 1 ); + v[0] = dX; + v[1] = -dY; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, v, 1 ); + v[0] = dX; + v[1] = dY; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, v, 1 ); + + pShaderAPI->SetVertexShaderIndex( 0 ); + pShaderAPI->SetPixelShaderIndex( 0 ); + + // store the ALPHA material var into c0 + v[0] = ALPHA; + pShaderAPI->SetPixelShaderConstant( 0, v, 1 ); + + } + Draw(); + } +END_SHADER diff --git a/materialsystem/stdshaders/sample4x4_blend.cpp b/materialsystem/stdshaders/sample4x4_blend.cpp new file mode 100644 index 00000000..29c2fa9f --- /dev/null +++ b/materialsystem/stdshaders/sample4x4_blend.cpp @@ -0,0 +1,108 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" +#include "common_hlsl_cpp_consts.h" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +BEGIN_VS_SHADER( Sample4x4_Blend, "Help for Sample4x4_Blend" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( BASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "" ) + SHADER_PARAM( PIXSHADER, SHADER_PARAM_TYPE_STRING, "sample4x4_ps20", "Name of the pixel shader to use" ) + END_SHADER_PARAMS + + SHADER_INIT + { + LoadTexture( BASETEXTURE ); + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableAlphaWrites( true ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + int fmt = VERTEX_POSITION; + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 ); + + pShaderShadow->SetVertexShader( "Downsample_vs20", 0 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + const char *szPixelShader = params[PIXSHADER]->GetStringValue(); + size_t iLength = Q_strlen( szPixelShader ); + + if( (iLength > 5) && (Q_stricmp( &szPixelShader[iLength - 5], "_ps20" ) == 0) ) //detect if it's trying to load a ps20 shader + { + //replace it with the ps20b shader + char *szNewName = (char *)stackalloc( sizeof( char ) * (iLength + 2) ); + memcpy( szNewName, szPixelShader, sizeof( char ) * iLength ); + szNewName[iLength] = 'b'; + szNewName[iLength + 1] = '\0'; + pShaderShadow->SetPixelShader( szNewName, 0 ); + } + else + { + pShaderShadow->SetPixelShader( params[PIXSHADER]->GetStringValue(), 0 ); + } + } + else + { + pShaderShadow->SetPixelShader( params[PIXSHADER]->GetStringValue(), 0 ); + } + + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, + SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, -1 ); + ITexture *src_texture=params[BASETEXTURE]->GetTextureValue(); + + int width=src_texture->GetActualWidth(); + int height=src_texture->GetActualHeight(); + + float v[4]; + float dX = 1.0f / width; + float dY = 1.0f / height; + + v[0] = -dX; + v[1] = -dY; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, v, 1 ); + v[0] = -dX; + v[1] = dY; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, v, 1 ); + v[0] = dX; + v[1] = -dY; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, v, 1 ); + v[0] = dX; + v[1] = dY; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, v, 1 ); + + pShaderAPI->SetVertexShaderIndex( 0 ); + pShaderAPI->SetPixelShaderIndex( 0 ); + + // store the ALPHA material var into c0 + v[0] = ALPHA; + pShaderAPI->SetPixelShaderConstant( 0, v, 1 ); + + } + Draw(); + } +END_SHADER diff --git a/materialsystem/stdshaders/sample4x4_blend_ps2x.fxc b/materialsystem/stdshaders/sample4x4_blend_ps2x.fxc new file mode 100644 index 00000000..4fde9d54 --- /dev/null +++ b/materialsystem/stdshaders/sample4x4_blend_ps2x.fxc @@ -0,0 +1,28 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_fxc.h" + +sampler TexSampler : register( s0 ); + +struct PS_INPUT +{ + float2 coordTap0 : TEXCOORD0; + float2 coordTap1 : TEXCOORD1; + float2 coordTap2 : TEXCOORD2; + float2 coordTap3 : TEXCOORD3; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float3 s0, s1, s2, s3; + + // Sample 4 taps. We use the trick of sampling four taps with bilinear in order + // to average 16 texels. + s0 = tex2D( TexSampler, i.coordTap0); + s1 = tex2D( TexSampler, i.coordTap1); + s2 = tex2D( TexSampler, i.coordTap2); + s3 = tex2D( TexSampler, i.coordTap3); + return FinalOutput( float4(exp(0.25*(s0+s1+s2+s3)),0.01), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} + diff --git a/materialsystem/stdshaders/sample4x4_ps2x.fxc b/materialsystem/stdshaders/sample4x4_ps2x.fxc new file mode 100644 index 00000000..91b46734 --- /dev/null +++ b/materialsystem/stdshaders/sample4x4_ps2x.fxc @@ -0,0 +1,30 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_fxc.h" + +sampler TexSampler : register( s0 ); + +struct PS_INPUT +{ + float2 coordTap0 : TEXCOORD0; + float2 coordTap1 : TEXCOORD1; + float2 coordTap2 : TEXCOORD2; + float2 coordTap3 : TEXCOORD3; +}; + +float AlphaConst : register( c0 ); + +float4 main( PS_INPUT i ) : COLOR +{ + float3 s0, s1, s2, s3; + + // Sample 4 taps. We use the trick of sampling four taps with bilinear in order + // to average 16 texels. + s0 = tex2D( TexSampler, i.coordTap0); + s1 = tex2D( TexSampler, i.coordTap1); + s2 = tex2D( TexSampler, i.coordTap2); + s3 = tex2D( TexSampler, i.coordTap3); + return FinalOutput( float4(0.25*(s0+s1+s2+s3),1), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} + diff --git a/materialsystem/stdshaders/sample4x4delog_ps2x.fxc b/materialsystem/stdshaders/sample4x4delog_ps2x.fxc new file mode 100644 index 00000000..0e4b7da7 --- /dev/null +++ b/materialsystem/stdshaders/sample4x4delog_ps2x.fxc @@ -0,0 +1,33 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_fxc.h" + +sampler TexSampler : register( s0 ); + +struct PS_INPUT +{ + float2 coordTap0 : TEXCOORD0; + float2 coordTap1 : TEXCOORD1; + float2 coordTap2 : TEXCOORD2; + float2 coordTap3 : TEXCOORD3; +}; + +float AlphaConst : register( c0 ); + +float4 main( PS_INPUT i ) : COLOR +{ + float3 s0, s1, s2, s3; + + // Sample 4 taps. We use the trick of sampling four taps with bilinear in order + // to average 16 texels. + s0 = tex2D( TexSampler, i.coordTap0); + s1 = tex2D( TexSampler, i.coordTap1); + s2 = tex2D( TexSampler, i.coordTap2); + s3 = tex2D( TexSampler, i.coordTap3); + float avglum=0.25*(s0.x+s1.x+s2.x+s3.x); + float elum=exp(avglum); + + return FinalOutput( float4(elum,elum,elum,1), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} + diff --git a/materialsystem/stdshaders/sample4x4log_ps2x.fxc b/materialsystem/stdshaders/sample4x4log_ps2x.fxc new file mode 100644 index 00000000..c82b5415 --- /dev/null +++ b/materialsystem/stdshaders/sample4x4log_ps2x.fxc @@ -0,0 +1,49 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_fxc.h" + +sampler TexSampler : register( s0 ); + +struct PS_INPUT +{ + float2 coordTap0 : TEXCOORD0; + float2 coordTap1 : TEXCOORD1; + float2 coordTap2 : TEXCOORD2; + float2 coordTap3 : TEXCOORD3; +}; + +float AlphaConst : register( c0 ); + +#define LOG_EPSILON 0.000001 + +float luminance(float3 color) : FLOAT +{ + return 0.2125*color.x+0.7154*color.y+0.0721*color.z; +} + +float logluminance(float3 color) : FLOAT +{ + return log(0.2125*color.x+0.7154*color.y+0.0721*color.z+LOG_EPSILON); +} + +float4 main( PS_INPUT i ) : COLOR +{ + float3 s0, s1, s2, s3; + + // Sample 4 taps. We use the trick of sampling four taps with bilinear in order + // to average 16 texels. + s0 = tex2D( TexSampler, i.coordTap0); + s1 = tex2D( TexSampler, i.coordTap1); + s2 = tex2D( TexSampler, i.coordTap2); + s3 = tex2D( TexSampler, i.coordTap3); + float maxlum=max(max(luminance(s0),luminance(s1)),max(luminance(s2),luminance(s3))); + float loglum0=logluminance(s0); + float loglum1=logluminance(s1); + float loglum2=logluminance(s2); + float loglum3=logluminance(s3); + +// return float4(0.25*(loglum0+loglum1+loglum2+loglum3),maxlum,0,1); + return FinalOutput( float4(0.25*(loglum0+loglum1+loglum2+loglum3),0,.5,AlphaConst), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} + diff --git a/materialsystem/stdshaders/sample4x4maxmin_ps2x.fxc b/materialsystem/stdshaders/sample4x4maxmin_ps2x.fxc new file mode 100644 index 00000000..e800b839 --- /dev/null +++ b/materialsystem/stdshaders/sample4x4maxmin_ps2x.fxc @@ -0,0 +1,29 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_Fxc.h" + +sampler TexSampler : register( s0 ); + +struct PS_INPUT +{ + float2 coordTap0 : TEXCOORD0; + float2 coordTap1 : TEXCOORD1; + float2 coordTap2 : TEXCOORD2; + float2 coordTap3 : TEXCOORD3; +}; + +float PixelScale : register( c0 ); + +float4 main( PS_INPUT i ) : COLOR +{ + float3 s0, s1, s2, s3; + + // Sample 4 taps. We use the trick of sampling four taps with bilinear in order + // to average 16 texels. + s0 = tex2D( TexSampler, i.coordTap0); + s1 = tex2D( TexSampler, i.coordTap1); + s2 = tex2D( TexSampler, i.coordTap2); + s3 = tex2D( TexSampler, i.coordTap3); + return FinalOutput( float4(0.25*(s0.xyz+s1.xyz+s2.xyz+s3.xzy),1), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} diff --git a/materialsystem/stdshaders/screenspace_general.cpp b/materialsystem/stdshaders/screenspace_general.cpp new file mode 100644 index 00000000..76450865 --- /dev/null +++ b/materialsystem/stdshaders/screenspace_general.cpp @@ -0,0 +1,321 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" + +#include "screenspaceeffect_vs20.inc" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + +static void GetAdjustedShaderName( char *pOutputBuffer, char const *pShader20Name ) +{ + Q_strcpy( pOutputBuffer, pShader20Name ); + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + size_t iLength = Q_strlen( pOutputBuffer ); + if( ( iLength > 4 ) && + ( + ( Q_stricmp( pOutputBuffer + iLength - 5, "_ps20" ) == 0 ) || + ( Q_stricmp( pOutputBuffer + iLength - 5, "_vs20" ) == 0 ) + ) + ) + { + strcpy( pOutputBuffer + iLength - 2, "20b" ); + } + } +} + +DEFINE_FALLBACK_SHADER( screenspace_general, screenspace_general_dx9 ) +BEGIN_VS_SHADER_FLAGS( screenspace_general_dx9, "Help for screenspace_general", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( C0_X,SHADER_PARAM_TYPE_FLOAT,"0","") + SHADER_PARAM( C0_Y,SHADER_PARAM_TYPE_FLOAT,"0","") + SHADER_PARAM( C0_Z,SHADER_PARAM_TYPE_FLOAT,"0","") + SHADER_PARAM( C0_W,SHADER_PARAM_TYPE_FLOAT,"0","") + SHADER_PARAM( C1_X,SHADER_PARAM_TYPE_FLOAT,"0","") + SHADER_PARAM( C1_Y,SHADER_PARAM_TYPE_FLOAT,"0","") + SHADER_PARAM( C1_Z,SHADER_PARAM_TYPE_FLOAT,"0","") + SHADER_PARAM( C1_W,SHADER_PARAM_TYPE_FLOAT,"0","") + SHADER_PARAM( C2_X,SHADER_PARAM_TYPE_FLOAT,"0","") + SHADER_PARAM( C2_Y,SHADER_PARAM_TYPE_FLOAT,"0","") + SHADER_PARAM( C2_Z,SHADER_PARAM_TYPE_FLOAT,"0","") + SHADER_PARAM( C2_W,SHADER_PARAM_TYPE_FLOAT,"0","") + SHADER_PARAM( C3_X,SHADER_PARAM_TYPE_FLOAT,"0","") + SHADER_PARAM( C3_Y,SHADER_PARAM_TYPE_FLOAT,"0","") + SHADER_PARAM( C3_Z,SHADER_PARAM_TYPE_FLOAT,"0","") + SHADER_PARAM( C3_W,SHADER_PARAM_TYPE_FLOAT,"0","") + SHADER_PARAM( C4_X,SHADER_PARAM_TYPE_FLOAT,"0","") + SHADER_PARAM( C4_Y,SHADER_PARAM_TYPE_FLOAT,"0","") + SHADER_PARAM( C4_Z,SHADER_PARAM_TYPE_FLOAT,"0","") + SHADER_PARAM( C4_W,SHADER_PARAM_TYPE_FLOAT,"0","") + SHADER_PARAM( PIXSHADER, SHADER_PARAM_TYPE_STRING, "", "Name of the pixel shader to use" ) + SHADER_PARAM( VERTEXSHADER, SHADER_PARAM_TYPE_STRING, "", "Name of the vertex shader to use" ) + SHADER_PARAM( DISABLE_COLOR_WRITES,SHADER_PARAM_TYPE_INTEGER,"0","") + SHADER_PARAM( ALPHATESTED,SHADER_PARAM_TYPE_FLOAT,"0","") + SHADER_PARAM( TEXTURE1, SHADER_PARAM_TYPE_TEXTURE, "", "" ) + SHADER_PARAM( TEXTURE2, SHADER_PARAM_TYPE_TEXTURE, "", "" ) + SHADER_PARAM( TEXTURE3, SHADER_PARAM_TYPE_TEXTURE, "", "" ) + SHADER_PARAM( LINEARREAD_BASETEXTURE, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( LINEARREAD_TEXTURE1, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( LINEARREAD_TEXTURE2, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( LINEARREAD_TEXTURE3, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( LINEARWRITE,SHADER_PARAM_TYPE_INTEGER,"0","") + SHADER_PARAM( VERTEXCOLOR,SHADER_PARAM_TYPE_INTEGER, "0", "vertices have color info" ) + SHADER_PARAM( VERTEXTRANSFORM,SHADER_PARAM_TYPE_INTEGER, "0", "verts are in world space" ) + SHADER_PARAM( ALPHABLEND,SHADER_PARAM_TYPE_INTEGER, "0", "whether or not to enable alpha blend" ) + SHADER_PARAM( MULTIPLYCOLOR, SHADER_PARAM_TYPE_INTEGER, "0", "whether or not to multiply src and dest color" ) + SHADER_PARAM( WRITEALPHA,SHADER_PARAM_TYPE_INTEGER, "0", "whether or not to enable alpha write" ) + SHADER_PARAM( WRITEDEPTH,SHADER_PARAM_TYPE_INTEGER, "0", "whether or not to enable depth write" ) + SHADER_PARAM( TCSIZE0, SHADER_PARAM_TYPE_INTEGER, "2", "Number of components in texture coord0" ) + SHADER_PARAM( TCSIZE1, SHADER_PARAM_TYPE_INTEGER, "0", "Number of components in texture coord1" ) + SHADER_PARAM( TCSIZE2, SHADER_PARAM_TYPE_INTEGER, "0", "Number of components in texture coord2" ) + SHADER_PARAM( TCSIZE3, SHADER_PARAM_TYPE_INTEGER, "0", "Number of components in texture coord3" ) + SHADER_PARAM( TCSIZE4, SHADER_PARAM_TYPE_INTEGER, "0", "Number of components in texture coord4" ) + SHADER_PARAM( TCSIZE5, SHADER_PARAM_TYPE_INTEGER, "0", "Number of components in texture coord5" ) + SHADER_PARAM( TCSIZE6, SHADER_PARAM_TYPE_INTEGER, "0", "Number of components in texture coord6" ) + SHADER_PARAM( TCSIZE7, SHADER_PARAM_TYPE_INTEGER, "0", "Number of components in texture coord7" ) + SHADER_PARAM( POINTSAMPLE_BASETEXTURE, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( POINTSAMPLE_TEXTURE1, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( POINTSAMPLE_TEXTURE2, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( POINTSAMPLE_TEXTURE3, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( ALPHA_BLEND_COLOR_OVERLAY, SHADER_PARAM_TYPE_INTEGER, "0", "") + SHADER_PARAM( CULL, SHADER_PARAM_TYPE_INTEGER, "0", "Culling control - 0 = nocull, 1 = do cull" ) + SHADER_PARAM( DEPTHTEST, SHADER_PARAM_TYPE_INTEGER, "0", "Enable Depthtest" ) + SHADER_PARAM( COPYALPHA, SHADER_PARAM_TYPE_INTEGER, "0", "") + SHADER_PARAM( ALPHA_BLEND, SHADER_PARAM_TYPE_INTEGER, "0", "") + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + if ( ! params[TCSIZE0]->IsDefined() ) + params[TCSIZE0]->SetIntValue( 2 ); + } + + SHADER_INIT + { + + if ( params[BASETEXTURE]->IsDefined() ) + { + LoadTexture( BASETEXTURE ); + } + if ( params[TEXTURE1]->IsDefined() ) + { + LoadTexture( TEXTURE1 ); + } + if ( params[TEXTURE2]->IsDefined() ) + { + LoadTexture( TEXTURE2 ); + } + if ( params[TEXTURE3]->IsDefined() ) + { + LoadTexture( TEXTURE3 ); + } + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_DRAW + { + bool bCustomVertexShader = params[VERTEXSHADER]->IsDefined(); + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( params[WRITEDEPTH]->GetIntValue() != 0 ); + if ( params[WRITEDEPTH]->GetIntValue() != 0 ) + { + pShaderShadow->EnableDepthTest( true ); + pShaderShadow->DepthFunc( SHADER_DEPTHFUNC_ALWAYS ); + } + pShaderShadow->EnableAlphaWrites( params[WRITEALPHA]->GetIntValue() != 0 ); + pShaderShadow->EnableDepthTest( params[DEPTHTEST]->GetIntValue() != 0 ); + pShaderShadow->EnableCulling( params[CULL]->GetIntValue() != 0 ); + + if (params[BASETEXTURE]->IsDefined()) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead(SHADER_SAMPLER0, !params[LINEARREAD_BASETEXTURE]->IsDefined() || !params[LINEARREAD_BASETEXTURE]->GetIntValue() ); + } + if (params[TEXTURE1]->IsDefined()) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableSRGBRead(SHADER_SAMPLER1, !params[LINEARREAD_TEXTURE1]->IsDefined() || !params[LINEARREAD_TEXTURE1]->GetIntValue() ); + } + if (params[TEXTURE2]->IsDefined()) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + pShaderShadow->EnableSRGBRead(SHADER_SAMPLER2, !params[LINEARREAD_TEXTURE2]->IsDefined() || !params[LINEARREAD_TEXTURE2]->GetIntValue() ); + } + if (params[TEXTURE3]->IsDefined()) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + pShaderShadow->EnableSRGBRead(SHADER_SAMPLER3,false); + pShaderShadow->EnableSRGBRead(SHADER_SAMPLER3, !params[LINEARREAD_TEXTURE3]->IsDefined() || !params[LINEARREAD_TEXTURE3]->GetIntValue() ); + } + int fmt = VERTEX_POSITION; + + if ( params[VERTEXCOLOR]->GetIntValue() ) + { + fmt |= VERTEX_COLOR; + } + + + + int nTexCoordSize[8]; + int nNumTexCoords = 0; + + static int s_tcSizeIds[]={ TCSIZE0, TCSIZE1, TCSIZE2, TCSIZE3, TCSIZE4, TCSIZE5, TCSIZE6, TCSIZE7 }; + + int nCtr = 0; + while( nCtr < 8 && ( params[s_tcSizeIds[nCtr]]->GetIntValue() ) ) + { + nNumTexCoords++; + nTexCoordSize[nCtr] = params[s_tcSizeIds[nCtr]]->GetIntValue(); + nCtr++; + } + pShaderShadow->VertexShaderVertexFormat( fmt, nNumTexCoords, nTexCoordSize, 0 ); + + if ( IS_FLAG_SET(MATERIAL_VAR_ADDITIVE) ) + { + EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); + } + else if ( params[MULTIPLYCOLOR]->GetIntValue() ) + { + EnableAlphaBlending( SHADER_BLEND_ZERO, SHADER_BLEND_SRC_COLOR ); + } + else if ( params[ALPHABLEND]->GetIntValue() ) + { + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + else + { + pShaderShadow->EnableBlending( false ); + } + + // maybe convert from linear to gamma on write. + bool srgb_write=true; + if (params[LINEARWRITE]->GetFloatValue()) + srgb_write=false; + pShaderShadow->EnableSRGBWrite( srgb_write ); + + char szShaderNameBuf[256]; + + if ( bCustomVertexShader ) + { + GetAdjustedShaderName( szShaderNameBuf, params[VERTEXSHADER]->GetStringValue() ); + pShaderShadow->SetVertexShader( params[VERTEXSHADER]->GetStringValue(), 0 ); //szShaderNameBuf, 0 ); + } + else + { + // Pre-cache shaders + DECLARE_STATIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO_HAS_DEFAULT( VERTEXCOLOR, params[VERTEXCOLOR]->GetIntValue() ); + SET_STATIC_VERTEX_SHADER_COMBO_HAS_DEFAULT( TRANSFORMVERTS, params[VERTEXTRANSFORM]->GetIntValue() ); + SET_STATIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + } + + if (params[DISABLE_COLOR_WRITES]->GetIntValue()) + { + pShaderShadow->EnableColorWrites(false); + } +// if (params[ALPHATESTED]->GetFloatValue()) + { + pShaderShadow->EnableAlphaTest(true); + pShaderShadow->AlphaFunc(SHADER_ALPHAFUNC_GREATER,0.0); + } + + GetAdjustedShaderName( szShaderNameBuf, params[PIXSHADER]->GetStringValue() ); + pShaderShadow->SetPixelShader( szShaderNameBuf, 0 ); + if ( params[ ALPHA_BLEND_COLOR_OVERLAY ]->GetIntValue() ) + { + // Used for adding L4D halos + EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + if ( params[ ALPHA_BLEND ]->GetIntValue() ) + { + // Used for adding L4D halos + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + + + if( params[ COPYALPHA ]->GetIntValue() ) + { + pShaderShadow->EnableBlending( false ); + pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_ALWAYS, 0.0f ); + } + + } + + DYNAMIC_STATE + { + if (params[BASETEXTURE]->IsDefined()) + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, -1 ); + if ( params[POINTSAMPLE_BASETEXTURE]->GetIntValue() ) + pShaderAPI->SetTextureFilterMode( SHADER_SAMPLER0, TFILTER_MODE_POINTSAMPLED ); + } + if (params[TEXTURE1]->IsDefined()) + { + BindTexture( SHADER_SAMPLER1, TEXTURE1, -1 ); + if ( params[POINTSAMPLE_TEXTURE1]->GetIntValue() ) + pShaderAPI->SetTextureFilterMode( SHADER_SAMPLER1, TFILTER_MODE_POINTSAMPLED ); + } + if (params[TEXTURE2]->IsDefined()) + { + BindTexture( SHADER_SAMPLER2, TEXTURE2, -1 ); + if ( params[POINTSAMPLE_TEXTURE2]->GetIntValue() ) + pShaderAPI->SetTextureFilterMode( SHADER_SAMPLER2, TFILTER_MODE_POINTSAMPLED ); + } + if (params[TEXTURE3]->IsDefined()) + { + BindTexture( SHADER_SAMPLER3, TEXTURE3, -1 ); + if ( params[POINTSAMPLE_TEXTURE3]->GetIntValue() ) + pShaderAPI->SetTextureFilterMode( SHADER_SAMPLER3, TFILTER_MODE_POINTSAMPLED ); + } + float c0[]={ + params[C0_X]->GetFloatValue(), + params[C0_Y]->GetFloatValue(), + params[C0_Z]->GetFloatValue(), + params[C0_W]->GetFloatValue(), + params[C1_X]->GetFloatValue(), + params[C1_Y]->GetFloatValue(), + params[C1_Z]->GetFloatValue(), + params[C1_W]->GetFloatValue(), + params[C2_X]->GetFloatValue(), + params[C2_Y]->GetFloatValue(), + params[C2_Z]->GetFloatValue(), + params[C2_W]->GetFloatValue(), + params[C3_X]->GetFloatValue(), + params[C3_Y]->GetFloatValue(), + params[C3_Z]->GetFloatValue(), + params[C3_W]->GetFloatValue(), + params[C4_X]->GetFloatValue(), + params[C4_Y]->GetFloatValue(), + params[C4_Z]->GetFloatValue(), + params[C4_W]->GetFloatValue() + }; + + pShaderAPI->SetPixelShaderConstant( 0, c0, ARRAYSIZE(c0)/4 ); + + float eyePos[4]; + pShaderAPI->GetWorldSpaceCameraPosition( eyePos ); + pShaderAPI->SetPixelShaderConstant( 10, eyePos, 1 ); + + pShaderAPI->SetVertexShaderIndex( 0 ); + pShaderAPI->SetPixelShaderIndex( 0 ); + + if ( ! bCustomVertexShader ) + { + DECLARE_DYNAMIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( screenspaceeffect_vs20 ); + } + } + Draw(); + } +END_SHADER diff --git a/materialsystem/stdshaders/screenspaceeffect_vs20.fxc b/materialsystem/stdshaders/screenspaceeffect_vs20.fxc new file mode 100644 index 00000000..de4ed699 --- /dev/null +++ b/materialsystem/stdshaders/screenspaceeffect_vs20.fxc @@ -0,0 +1,46 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// +// STATIC: "VERTEXCOLOR" "0..1" [=0] +// STATIC: "TRANSFORMVERTS" "0..1" [=0] + + +#include "common_vs_fxc.h" + +struct VS_INPUT +{ + float3 vPos : POSITION; + float2 vBaseTexCoord : TEXCOORD0; + + #if VERTEXCOLOR + float4 vColor : COLOR0; + #endif +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; + float2 baseTexCoord : TEXCOORD0; + + #if VERTEXCOLOR + float4 vColor : TEXCOORD1; + #endif +}; + +float4 Texel_Sizes : register (SHADER_SPECIFIC_CONST_0); + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + if ( TRANSFORMVERTS ) + o.projPos.xyzw = mul( float4( v.vPos.xyz, 1.0f ), cModelViewProj ); + else + o.projPos = float4( v.vPos, 1.0f ); + + o.baseTexCoord = v.vBaseTexCoord; + + #if ( VERTEXCOLOR ) + o.vColor.rgba = v.vColor.rgba; + #endif + + return o; +} diff --git a/materialsystem/stdshaders/shader_constant_register_map.h b/materialsystem/stdshaders/shader_constant_register_map.h new file mode 100644 index 00000000..37d86267 --- /dev/null +++ b/materialsystem/stdshaders/shader_constant_register_map.h @@ -0,0 +1,108 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// +// +// Purpose: Provide convenient mapping for shader constants +// +// $NoKeywords: $ +//===========================================================================// + +#ifndef C_CODE_HACK +#include "common_vertexlitgeneric_dx9.h" +#endif + +#define PSREG_SELFILLUMTINT PSREG_CONSTANT_00 +#define PSREG_DIFFUSE_MODULATION PSREG_CONSTANT_01 +#define PSREG_ENVMAP_TINT__SHADOW_TWEAKS PSREG_CONSTANT_02 +#define PSREG_SELFILLUM_SCALE_BIAS_EXP PSREG_CONSTANT_03 +#define PSREG_AMBIENT_CUBE PSREG_CONSTANT_04 +// PSREG_AMBIENT_CUBE PSREG_CONSTANT_05 +// PSREG_AMBIENT_CUBE PSREG_CONSTANT_06 +// PSREG_AMBIENT_CUBE PSREG_CONSTANT_07 +// PSREG_AMBIENT_CUBE PSREG_CONSTANT_08 +// PSREG_AMBIENT_CUBE PSREG_CONSTANT_09 +#define PSREG_SHADER_CONTROLS_2 PSREG_CONSTANT_10 +#define PSREG_EYEPOS_SPEC_EXPONENT PSREG_CONSTANT_11 +#define PSREG_FOG_PARAMS PSREG_CONSTANT_12 +#define PSREG_FLASHLIGHT_ATTENUATION PSREG_CONSTANT_13 +#define PSREG_FLASHLIGHT_POSITION_RIM_BOOST PSREG_CONSTANT_14 +#define PSREG_FLASHLIGHT_TO_WORLD_TEXTURE PSREG_CONSTANT_15 +// PSREG_FLASHLIGHT_TO_WORLD_TEXTURE PSREG_CONSTANT_16 +// PSREG_FLASHLIGHT_TO_WORLD_TEXTURE PSREG_CONSTANT_17 +// PSREG_FLASHLIGHT_TO_WORLD_TEXTURE PSREG_CONSTANT_18 +#define PSREG_FRESNEL_SPEC_PARAMS PSREG_CONSTANT_19 +#define PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_20 +// PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_21 +// PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_22 +// PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_23 +// PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_24 +// PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_25 +#define PSREG_SPEC_RIM_PARAMS PSREG_CONSTANT_26 +#define PSREG_SHADER_CONTROLS PSREG_CONSTANT_27 +#define PSREG_FLASHLIGHT_COLOR PSREG_CONSTANT_28 +#define PSREG_LINEAR_FOG_COLOR PSREG_CONSTANT_29 +#define PSREG_LIGHT_SCALE PSREG_CONSTANT_30 +#define PSREG_FLASHLIGHT_SCREEN_SCALE PSREG_CONSTANT_31 +// --- End of ps_2_0 and ps_2_b constants --- available to ps_3_0 though! --- +#define PSREG_SCREEN_SIZE PSREG_CONSTANT_32 +#define PSREG_UBERLIGHT_SMOOTH_EDGE_0 PSREG_CONSTANT_33 +#define PSREG_UBERLIGHT_SMOOTH_EDGE_1 PSREG_CONSTANT_34 +#define PSREG_UBERLIGHT_SMOOTH_EDGE_OOW PSREG_CONSTANT_35 +#define PSREG_UBERLIGHT_SHEAR_ROUND PSREG_CONSTANT_36 +#define PSREG_UBERLIGHT_AABB PSREG_CONSTANT_37 +#define PSREG_UBERLIGHT_WORLD_TO_LIGHT PSREG_CONSTANT_38 +// PSREG_UBERLIGHT_WORLD_TO_LIGHT PSREG_CONSTANT_39 +// PSREG_UBERLIGHT_WORLD_TO_LIGHT PSREG_CONSTANT_40 +// PSREG_UBERLIGHT_WORLD_TO_LIGHT PSREG_CONSTANT_41 +#define PSREG_RIMPARAMS PSREG_CONSTANT_42 +#define PSREG_FLESH_LIGHTING_PARAMS PSREG_CONSTANT_43 +#define PSREG_FLESH_SUBSURFACE_PARAMS PSREG_CONSTANT_44 +#define PSREG_FLESH_SUBSURFACE_MODULATION PSREG_CONSTANT_45 + +#ifndef C_CODE_HACK +//for fxc code, map the constants to register names. +#define PSREG_CONSTANT_00 c0 +#define PSREG_CONSTANT_01 c1 +#define PSREG_CONSTANT_02 c2 +#define PSREG_CONSTANT_03 c3 +#define PSREG_CONSTANT_04 c4 +#define PSREG_CONSTANT_05 c5 +#define PSREG_CONSTANT_06 c6 +#define PSREG_CONSTANT_07 c7 +#define PSREG_CONSTANT_08 c8 +#define PSREG_CONSTANT_09 c9 +#define PSREG_CONSTANT_10 c10 +#define PSREG_CONSTANT_11 c11 +#define PSREG_CONSTANT_12 c12 +#define PSREG_CONSTANT_13 c13 +#define PSREG_CONSTANT_14 c14 +#define PSREG_CONSTANT_15 c15 +#define PSREG_CONSTANT_16 c16 +#define PSREG_CONSTANT_17 c17 +#define PSREG_CONSTANT_18 c18 +#define PSREG_CONSTANT_19 c19 +#define PSREG_CONSTANT_20 c20 +#define PSREG_CONSTANT_21 c21 +#define PSREG_CONSTANT_22 c22 +#define PSREG_CONSTANT_23 c23 +#define PSREG_CONSTANT_24 c24 +#define PSREG_CONSTANT_25 c25 +#define PSREG_CONSTANT_26 c26 +#define PSREG_CONSTANT_27 c27 +#define PSREG_CONSTANT_28 c28 +#define PSREG_CONSTANT_29 c29 +#define PSREG_CONSTANT_30 c30 +#define PSREG_CONSTANT_31 c31 +#define PSREG_CONSTANT_32 c32 +#define PSREG_CONSTANT_33 c33 +#define PSREG_CONSTANT_34 c34 +#define PSREG_CONSTANT_35 c35 +#define PSREG_CONSTANT_36 c36 +#define PSREG_CONSTANT_37 c37 +#define PSREG_CONSTANT_38 c38 +#define PSREG_CONSTANT_39 c39 +#define PSREG_CONSTANT_40 c40 +#define PSREG_CONSTANT_41 c41 +#define PSREG_CONSTANT_42 c42 +#define PSREG_CONSTANT_43 c43 +#define PSREG_CONSTANT_44 c44 +#define PSREG_CONSTANT_45 c45 +#endif diff --git a/materialsystem/stdshaders/shadow.cpp b/materialsystem/stdshaders/shadow.cpp new file mode 100644 index 00000000..dffd88b6 --- /dev/null +++ b/materialsystem/stdshaders/shadow.cpp @@ -0,0 +1,221 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" + +#include "shadow_ps20.inc" +#include "shadow_ps20b.inc" +#include "shadow_vs20.inc" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +BEGIN_VS_SHADER_FLAGS( Shadow, "Help for Shadow", SHADER_NOT_EDITABLE ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( MAXFALLOFFAMOUNT, SHADER_PARAM_TYPE_FLOAT, "240", "" ) + SHADER_PARAM( DEFERREDSHADOWS, SHADER_PARAM_TYPE_BOOL, "0", "" ) + SHADER_PARAM( ZFAILENABLE, SHADER_PARAM_TYPE_BOOL, "0", "" ) + SHADER_PARAM( BLOBBYSHADOWS, SHADER_PARAM_TYPE_BOOL, "0", "" ) + SHADER_PARAM( DEPTHTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + /* + The alpha blending state either must be: + + Src Color * Dst Color + Dst Color * 0 + (src color = C*A + 1-A) + + or + + // Can't be this, doesn't work with fog + Src Color * Dst Color + Dst Color * (1-Src Alpha) + (src color = C * A, Src Alpha = A) + */ + INIT_FLOAT_PARM( MAXFALLOFFAMOUNT, 240.0f ); + if ( !params[DEFERREDSHADOWS]->IsDefined() ) + { + params[DEFERREDSHADOWS]->SetIntValue( 0 ); + } + if ( !params[ZFAILENABLE]->IsDefined() ) + { + params[ZFAILENABLE]->SetIntValue( 0 ); + } + if ( !params[BLOBBYSHADOWS]->IsDefined() ) + { + params[BLOBBYSHADOWS]->SetIntValue( 0 ); + } + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + LoadTexture( BASETEXTURE ); + } + + SHADER_DRAW + { + SHADOW_STATE + { + bool bDeferredShadows = ( params[DEFERREDSHADOWS]->GetIntValue() != 0 ); + bool bBlobbyShadows = ( params[BLOBBYSHADOWS]->GetIntValue() != 0 ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + + if ( bDeferredShadows ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, false ); + } + + + if ( !bDeferredShadows ) + { + // NOTE: This is deliberately this way round (instead of "DST_COLOR, ZERO"), + // since these two permutations produce *different* values on 360!! + // This was causing undue darkening of the framebuffer by these + // shadows, which was highly noticeable in very dark areas: + EnableAlphaBlending( SHADER_BLEND_ZERO, SHADER_BLEND_SRC_COLOR ); + + unsigned int flags = VERTEX_POSITION | VERTEX_COLOR; + int numTexCoords = 2; + int texCoordDims[2] = { 3, 3 }; + pShaderShadow->VertexShaderVertexFormat( flags, numTexCoords, texCoordDims, 0 ); + } + else + { + EnableAlphaBlending( SHADER_BLEND_ZERO, SHADER_BLEND_SRC_COLOR ); + + /* + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + + pShaderShadow->EnableBlending( true ); + pShaderShadow->EnableBlendingSeparateAlpha( true ); + pShaderShadow->BlendFuncSeparateAlpha( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); + pShaderShadow->BlendOpSeparateAlpha( SHADER_BLEND_OP_MIN ); + */ + + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL; + int numTexCoords = 7; + int texCoordDims[7] = { 3, 4, 4, 4, 4, 4, 3 }; + pShaderShadow->VertexShaderVertexFormat( flags, numTexCoords, texCoordDims, 0 ); + } + + DECLARE_STATIC_VERTEX_SHADER( shadow_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( DEFERRED_SHADOWS, bDeferredShadows ); + SET_STATIC_VERTEX_SHADER( shadow_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( shadow_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( DEFERRED_SHADOWS, bDeferredShadows ); + SET_STATIC_PIXEL_SHADER_COMBO( BLOBBY_SHADOWS, bBlobbyShadows ); + SET_STATIC_PIXEL_SHADER( shadow_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( shadow_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( DEFERRED_SHADOWS, bDeferredShadows ); + SET_STATIC_PIXEL_SHADER_COMBO( BLOBBY_SHADOWS, bBlobbyShadows ); + SET_STATIC_PIXEL_SHADER( shadow_ps20 ); + } + + pShaderShadow->EnableSRGBWrite( true ); + + if ( bDeferredShadows ) + { + pShaderShadow->DepthFunc( params[ZFAILENABLE]->GetIntValue() ? SHADER_DEPTHFUNC_FARTHER : SHADER_DEPTHFUNC_NEAREROREQUAL ); + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableColorWrites( true ); + pShaderShadow->EnableAlphaWrites( true ); + //pShaderShadow->PolyMode( SHADER_POLYMODEFACE_FRONT_AND_BACK, SHADER_POLYMODE_LINE ); + } + + // We need to fog to *white* regardless of overbrighting... + FogToWhite(); + } + DYNAMIC_STATE + { + bool bDeferredShadows = ( params[DEFERREDSHADOWS]->GetIntValue() != 0 ); + + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + + if ( bDeferredShadows ) + { + BindTexture( SHADER_SAMPLER1, DEPTHTEXTURE ); + //pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_FRAME_BUFFER_FULL_DEPTH ); + } + + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BASETEXTURETRANSFORM ); + SetPixelShaderConstantGammaToLinear( 1, COLOR ); // shadow color + + // Get texture dimensions... + int nWidth = 16; + int nHeight = 16; + ITexture *pTexture = params[BASETEXTURE]->GetTextureValue(); + if (pTexture) + { + nWidth = pTexture->GetActualWidth(); + nHeight = pTexture->GetActualHeight(); + } + + Vector4D vecJitter( 1.0 / nWidth, 1.0 / nHeight, 0.0, 0.0 ); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, vecJitter.Base() ); + + vecJitter.y *= -1.0f; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, vecJitter.Base() ); + + DECLARE_DYNAMIC_VERTEX_SHADER( shadow_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( shadow_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( shadow_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( shadow_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( shadow_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( shadow_ps20 ); + } + + float eyePos[4]; + pShaderAPI->GetWorldSpaceCameraPosition( eyePos ); + pShaderAPI->SetPixelShaderConstant( 2, eyePos, 1 ); + pShaderAPI->SetPixelShaderFogParams( 3 ); + + float fConst[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + fConst[0] = IS_PARAM_DEFINED( MAXFALLOFFAMOUNT ) ? params[MAXFALLOFFAMOUNT]->GetFloatValue() : 240.0f; + fConst[0] /= 255.0f; + + if ( bDeferredShadows ) + { + pTexture = params[DEPTHTEXTURE]->GetTextureValue(); + if (pTexture) + { + nWidth = pTexture->GetActualWidth(); + nHeight = pTexture->GetActualHeight(); + } + //pShaderAPI->GetBackBufferDimensions( nWidth, nHeight ); + fConst[1] = 1.0f / float( nWidth ); + fConst[2] = 1.0f / float( nHeight ); + } + + pShaderAPI->SetPixelShaderConstant( 4, fConst ); + } + Draw( ); + } +END_SHADER diff --git a/materialsystem/stdshaders/shadow_ps2x.fxc b/materialsystem/stdshaders/shadow_ps2x.fxc new file mode 100644 index 00000000..ea03be58 --- /dev/null +++ b/materialsystem/stdshaders/shadow_ps2x.fxc @@ -0,0 +1,230 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "DEFERRED_SHADOWS" "0..1" [XBOX] +// STATIC: "DEFERRED_SHADOWS" "0..0" [PC] +// STATIC: "BLOBBY_SHADOWS" "0..1" +#include "common_fog_ps_fxc.h" + +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_fxc.h" + +const HALF4 g_ShadowColor : register( c1 ); +const HALF3 g_EyePos : register( c2 ); +const HALF4 g_FogParams : register( c3 ); +const float4 g_DeferredParams : register( c4 ); +#define g_MaxFalloffAmount g_DeferredParams.x +#define g_vInvScreenSize g_DeferredParams.yz + +const float4x4 g_mInvViewProj : register( c5 ); + +sampler ShadowSampler : register( s0 ); +sampler sDepth : register( s1 ); + +#if DEFERRED_SHADOWS == 0 + +////////////////////////////////// +// NORMAL SHADOW SHADER +////////////////////////////////// + +// CENTROID: TEXCOORD1 +// CENTROID: TEXCOORD2 +// CENTROID: TEXCOORD3 +struct PS_INPUT +{ + HALF4 worldPos_projPosZ : TEXCOORD0; + #if defined( _X360 ) + float4 vFalloffParams : TEXCOORD1_centroid; + float3 texCoord0_shadowAlpha : TEXCOORD2_centroid; + #else + float4 vFalloffParams : TEXCOORD1; + float3 texCoord0_shadowAlpha : TEXCOORD2; + #endif +#if !defined( _X360 ) + float4 texCoord1_2 : TEXCOORD3; + float4 texCoord3_4 : TEXCOORD4; +#endif +}; + +float4 main( PS_INPUT i ) : COLOR +{ + HALF shadowCoverage; + + #if BLOBBY_SHADOWS == 1 + { + shadowCoverage = tex2D( ShadowSampler, i.texCoord0_shadowAlpha.xy ).a; + } + #elif !defined( _X360 ) + { + HALF samples0; + HALF4 samples1_4; + samples0 = tex2D( ShadowSampler, i.texCoord0_shadowAlpha.xy ).a; + samples1_4.x = tex2D( ShadowSampler, i.texCoord1_2.xy ).a; + samples1_4.y = tex2D( ShadowSampler, i.texCoord1_2.wz ).a; + samples1_4.z = tex2D( ShadowSampler, i.texCoord3_4.xy ).a; + samples1_4.w = tex2D( ShadowSampler, i.texCoord3_4.wz ).a; + + // Interpolate between a bunch of jittered shadow samples. + shadowCoverage = samples0 * 0.2 + dot( samples1_4, HALF4( 0.2, 0.2, 0.2, 0.2 ) ); + } + #else + { + float samples0 = tex2D( ShadowSampler, i.texCoord0_shadowAlpha.xy ).a; + float2 texCoord = i.texCoord0_shadowAlpha.xy; + float4 samples1_4; + asm { + tfetch2D samples1_4.w___, texCoord.xy, ShadowSampler, OffsetX = -1.0, OffsetY = -1.0 + tfetch2D samples1_4._w__, texCoord.xy, ShadowSampler, OffsetX = 1.0, OffsetY = -1.0 + tfetch2D samples1_4.__w_, texCoord.xy, ShadowSampler, OffsetX = -1.0, OffsetY = 1.0 + tfetch2D samples1_4.___w, texCoord.xy, ShadowSampler, OffsetX = 1.0, OffsetY = 1.0 + }; + + // Interpolate between a bunch of jittered shadow samples. + shadowCoverage = samples0 * 0.2 + dot( samples1_4, HALF4( 0.2,0.2,0.2,0.2 ) ); + } + #endif + + // compute "vertex" alpha + // NOTE: 0 means black, non-zero adds towards white... + float fVertAlpha = saturate( i.vFalloffParams.w * i.vFalloffParams.y + i.vFalloffParams.x ); // could pull the mad into the VS + fVertAlpha = saturate( i.vFalloffParams.z + fVertAlpha * g_MaxFalloffAmount ); + //fVertAlpha = i.texCoord0_shadowAlpha.z; + + // To accomplish shadow fading, subtract vertex alpha from texture alpha + shadowCoverage = saturate( shadowCoverage - fVertAlpha ); + + // Blend between white and the constant color... + // return lerp( 1.0-shadowCoverage, 1.0, g_ShadowColor ); + + // this is equivalent, and saves an instruction + HALF4 result = shadowCoverage*g_ShadowColor - shadowCoverage; + result = 1.0 + result; + + float alpha = 1.0f; + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos.xyz, i.worldPos_projPosZ.xyz, i.worldPos_projPosZ.w ); + + // Apply fog here to compensate for our srcColor*dstColor alpha blend into already fogged pixels + result.rgb = 1.0f - ( ( 1.0f - result.rgb ) * pow( ( 1.0f - fogFactor ), 4.0f ) ); + + // Call FinalOutput without fog! + return FinalOutput( float4( result.rgb, alpha ), fogFactor, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} + +#else // DEFERRED_SHADOWS == 1 + +////////////////////////////////// +// X360 DEFERRED SHADOW SHADER +////////////////////////////////// + +// CENTROID: TEXCOORD1 +// CENTROID: TEXCOORD2 +// CENTROID: TEXCOORD3 +struct PS_INPUT +{ + float4 vTexCoordBiasScale : TEXCOORD0; + + #if defined( _X360 ) + float4 vProjToTex0 : TEXCOORD1_centroid; + float4 vProjToTex1 : TEXCOORD2_centroid; + float4 vProjToTex2 : TEXCOORD3_centroid; + #else + float4 vProjToTex0 : TEXCOORD1; + float4 vProjToTex1 : TEXCOORD2; + float4 vProjToTex2 : TEXCOORD3; + #endif + float4 vProjToTex3 : TEXCOORD4; + float3 vFalloffParams : TEXCOORD5; + float2 vPos : VPOS; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float4 vPosCS; + vPosCS.xy = ( i.vPos+float2(0.5, 0.5) ) * g_vInvScreenSize; + vPosCS.z = 1.0 - tex2D( sDepth, vPosCS.xy ); + vPosCS.w = 1.0; + vPosCS.xy = 2.0 * vPosCS.xy - 1.0; + vPosCS.y = -vPosCS.y; + + //return float4((1-vPosCS.z).xxx, 1); + + float4 vPosTS;// = mul( vPosCS, g_mScreenToTexture ); + + // Clip space to shadow texture space transform + vPosTS.x = dot( vPosCS, i.vProjToTex0 ); + vPosTS.y = dot( vPosCS, i.vProjToTex1 ); + vPosTS.z = dot( vPosCS, i.vProjToTex2 ); + vPosTS.w = dot( vPosCS, i.vProjToTex3 ); + vPosTS /= vPosTS.w; + + // check if pixel is within shadow frustum, and early-out if it's not + float2 vClamped = saturate( vPosTS.xy ); + vClamped -= vPosTS.xy; + clip( 0.0001 - dot( vClamped, vClamped ) ); + + // extract normal in texture space + float3 vNormalTS = cross( ddx(vPosTS.xyz), ddy(vPosTS.xyz) ); + + #if BLOBBY_SHADOWS == 0 + float2 vTexCoord = i.vTexCoordBiasScale.xy + i.vTexCoordBiasScale.zw * vPosTS.xy; + #else + float2 vTexCoord = vPosTS.xy; + #endif + + float shadowCoverage = 0.0f; + #if !defined( _X360 ) || ( BLOBBY_SHADOWS == 1 ) + { + shadowCoverage = tex2D( ShadowSampler, vTexCoord ).a; + } + #else + { + float samples0 = tex2D( ShadowSampler, vTexCoord ).a; + float4 samples1_4; + asm { + tfetch2D samples1_4.w___, vTexCoord.xy, ShadowSampler, OffsetX = -1.0, OffsetY = -1.0 + tfetch2D samples1_4._w__, vTexCoord.xy, ShadowSampler, OffsetX = 1.0, OffsetY = -1.0 + tfetch2D samples1_4.__w_, vTexCoord.xy, ShadowSampler, OffsetX = -1.0, OffsetY = 1.0 + tfetch2D samples1_4.___w, vTexCoord.xy, ShadowSampler, OffsetX = 1.0, OffsetY = 1.0 + }; + + // Interpolate between a bunch of jittered shadow samples. + shadowCoverage = samples0 * 0.2 + dot( samples1_4, HALF4( 0.2,0.2,0.2,0.2 ) ); + } + #endif + + // compute "vertex" alpha + // NOTE: 0 means black, non-zero adds towards white... + float fVertAlpha = saturate( vPosTS.z * i.vFalloffParams.y + i.vFalloffParams.x ); // could pull the mad into the VS + fVertAlpha = saturate( i.vFalloffParams.z + fVertAlpha * g_MaxFalloffAmount ); + + // To accomplish shadow fading, subtract vertex alpha from texture alpha + shadowCoverage = saturate( shadowCoverage - fVertAlpha ); + + // mask out shadows on geometry facing away from the shadow direction + shadowCoverage *= saturate(sign(vNormalTS.z)); + + // TODO: Add fog + + // Blend between white and the constant color... + // return lerp( 1.0-shadowCoverage, 1.0, g_ShadowColor ); + + // this is equivalent, and saves an instruction + HALF4 result = shadowCoverage*g_ShadowColor - shadowCoverage; + result = 1.0 + result; + + float alpha = 1.0f; + + // TODO: Add support for fog + float fogFactor = 0; + /* + // Apply fog here to compensate for our srcColor*dstColor alpha blend into already fogged pixels + result.rgb = 1.0f - ( ( 1.0f - result.rgb ) * pow( ( 1.0f - fogFactor ), 4.0f ) ); + */ + + //return float4( g_shadowColor.rgb, shadowCoverage ); + + // Call FinalOutput without fog! + return FinalOutput( float4( result.rgb, alpha ), fogFactor, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} + +#endif diff --git a/materialsystem/stdshaders/shadow_vs20.fxc b/materialsystem/stdshaders/shadow_vs20.fxc new file mode 100644 index 00000000..a93de9e5 --- /dev/null +++ b/materialsystem/stdshaders/shadow_vs20.fxc @@ -0,0 +1,135 @@ + +// STATIC: "DEFERRED_SHADOWS" "0..1" +#include "common_fog_vs_fxc.h" + +#include "common_vs_fxc.h" + +static const int g_FogType = DOWATERFOG; + +const float4 cBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_0 ); +const float4 cTextureJitter[2] : register( SHADER_SPECIFIC_CONST_2 ); + +#if DEFERRED_SHADOWS == 0 + +struct VS_INPUT +{ + // This is all of the stuff that we ever use. + float4 vPos : POSITION; + float4 vColor : COLOR0; + float4 vTexCoord0 : TEXCOORD0; + float3 vFalloffParams : TEXCOORD1; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + float fog : FOG; +#endif + HALF4 worldPos_projPosZ : TEXCOORD0; + float4 vFalloffParams : TEXCOORD1; + float3 texCoord0_shadowAlpha : TEXCOORD2; +#if !defined( _X360 ) + float4 texCoord1_2 : TEXCOORD3; + float4 texCoord3_4 : TEXCOORD4; +#endif +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 worldPos; + float2 texCoord; + worldPos = mul( v.vPos, cModel[0] ); + + float4 projPos = mul( float4( worldPos, 1 ), cViewProj ); + o.projPos = projPos; + +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + o.fog = CalcFixedFunctionFog( worldPos, g_FogType ); +#endif + + o.worldPos_projPosZ = float4( worldPos, projPos.z ); + + o.vFalloffParams.xyz = v.vFalloffParams; + o.vFalloffParams.w = v.vTexCoord0.z; + texCoord.x = dot( v.vTexCoord0, cBaseTexCoordTransform[0] ); + texCoord.y = dot( v.vTexCoord0, cBaseTexCoordTransform[1] ); + + o.texCoord0_shadowAlpha.xy = texCoord; +#if !defined( _X360 ) + { + o.texCoord1_2.xy = texCoord + cTextureJitter[0]; + o.texCoord1_2.wz = texCoord - cTextureJitter[0]; + o.texCoord3_4.xy = texCoord + cTextureJitter[1]; + o.texCoord3_4.wz = texCoord - cTextureJitter[1]; + } +#endif + + o.texCoord0_shadowAlpha.z = v.vColor.a; + return o; +} + + +#else // DEFERRED_SHADOWS == 1 + +struct VS_INPUT +{ + float4 vPos : POSITION; + float3 vNormal : NORMAL; + float3 vShadowDir : TEXCOORD0; + float4 vTexCoordBiasScale : TEXCOORD1; + float4 vProjToTex0 : TEXCOORD2; + float4 vProjToTex1 : TEXCOORD3; + float4 vProjToTex2 : TEXCOORD4; + float4 vProjToTex3 : TEXCOORD5; + float3 vFalloffParams : TEXCOORD6; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; + float4 vTexCoordBiasScale : TEXCOORD0; + float4 vProjToTex0 : TEXCOORD1; + float4 vProjToTex1 : TEXCOORD2; + float4 vProjToTex2 : TEXCOORD3; + float4 vProjToTex3 : TEXCOORD4; + float3 vFalloffParams : TEXCOORD5; +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 worldNormal, worldPos; + float2 texCoord; + + // obj->world xform currently handled on CPU for batching + /* + worldPos = mul( v.vPos, cModel[0] ); + worldNormal = mul( v.vNormal, cModel[0] ); + */ + + worldPos = v.vPos.xyz; + worldNormal = v.vNormal.xyz; + + // bounding volume extrusion + if ( dot( worldNormal, v.vShadowDir ) > 0.0 ) + { + worldPos += v.vShadowDir; + } + + o.vTexCoordBiasScale = v.vTexCoordBiasScale; + o.vProjToTex0 = v.vProjToTex0; + o.vProjToTex1 = v.vProjToTex1; + o.vProjToTex2 = v.vProjToTex2; + o.vProjToTex3 = v.vProjToTex3; + o.vFalloffParams.xyz = v.vFalloffParams; + + float4 projPos = mul( float4( worldPos, 1 ), cViewProj ); + o.projPos = projPos; + return o; +} + +#endif diff --git a/materialsystem/stdshaders/shadowbuild_dx9.cpp b/materialsystem/stdshaders/shadowbuild_dx9.cpp new file mode 100644 index 00000000..c51b1268 --- /dev/null +++ b/materialsystem/stdshaders/shadowbuild_dx9.cpp @@ -0,0 +1,212 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: A shader that builds the shadow using render-to-texture +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" +#include "convar.h" +#include "mathlib/VMatrix.h" + +#include "unlitgeneric_vs20.inc" +#include "shadowbuildtexture_ps20.inc" +#include "shadowbuildtexture_ps20b.inc" + +#if !defined( _X360 ) + #include "shadowbuildtexture_ps30.inc" + #include "unlitgeneric_vs30.inc" +#endif + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +static ConVar mat_displacementmap( "mat_displacementmap", "1", FCVAR_CHEAT ); + +DEFINE_FALLBACK_SHADER( ShadowBuild, ShadowBuild_DX9 ) + +BEGIN_VS_SHADER_FLAGS( ShadowBuild_DX9, "Help for ShadowBuild", SHADER_NOT_EDITABLE ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( TRANSLUCENT_MATERIAL, SHADER_PARAM_TYPE_MATERIAL, "", "Points to a material to grab translucency from" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + if (params[BASETEXTURE]->IsDefined()) + { + LoadTexture(BASETEXTURE); + } + } + + SHADER_DRAW + { + SHADOW_STATE + { + // Add the alphas into the frame buffer + EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); + + // base texture. We just use this for alpha, but enable SRGB read to make everything consistent. + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + + pShaderShadow->EnableSRGBWrite( true ); + + pShaderShadow->EnableAlphaWrites( true ); + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->DepthFunc( SHADER_DEPTHFUNC_ALWAYS ); + + // Specify vertex format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_FORMAT_COMPRESSED; + unsigned int nTexCoordCount = 1; + unsigned int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_STATIC_VERTEX_SHADER( unlitgeneric_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( VERTEXCOLOR, 0 ); + SET_STATIC_VERTEX_SHADER( unlitgeneric_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( shadowbuildtexture_ps20b ); + SET_STATIC_PIXEL_SHADER( shadowbuildtexture_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( shadowbuildtexture_ps20 ); + SET_STATIC_PIXEL_SHADER( shadowbuildtexture_ps20 ); + } + } +#ifndef _X360 + else + { + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_TESSELLATION ); + + DECLARE_STATIC_VERTEX_SHADER( unlitgeneric_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( VERTEXCOLOR, 0 ); + SET_STATIC_VERTEX_SHADER( unlitgeneric_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( shadowbuildtexture_ps30 ); + SET_STATIC_PIXEL_SHADER( shadowbuildtexture_ps30 ); + } +#endif + PI_BeginCommandBuffer(); + PI_SetModulationVertexShaderDynamicState(); + PI_EndCommandBuffer(); + } + DYNAMIC_STATE + { + + // Snack important parameters from the original material + // FIXME: What about alpha modulation? Need a solution for that + ITexture *pTexture = NULL; + IMaterialVar **ppTranslucentParams = NULL; + if (params[TRANSLUCENT_MATERIAL]->IsDefined()) + { + IMaterial *pMaterial = params[TRANSLUCENT_MATERIAL]->GetMaterialValue(); + if (pMaterial) + { + ppTranslucentParams = pMaterial->GetShaderParams(); + if ( ppTranslucentParams[BASETEXTURE]->IsTexture() ) + { + pTexture = ppTranslucentParams[BASETEXTURE]->GetTextureValue(); + } + } + } + + if (pTexture) + { + BindTexture( SHADER_SAMPLER0, pTexture, ppTranslucentParams[FRAME]->GetIntValue() ); + + Vector4D transformation[2]; + const VMatrix &mat = ppTranslucentParams[BASETEXTURETRANSFORM]->GetMatrixValue(); + transformation[0].Init( mat[0][0], mat[0][1], mat[0][2], mat[0][3] ); + transformation[1].Init( mat[1][0], mat[1][1], mat[1][2], mat[1][3] ); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, transformation[0].Base(), 2 ); + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_LIGHTMAP_FULLBRIGHT ); + } + +#ifndef _X360 + TessellationMode_t nTessellationMode = TESSELLATION_MODE_DISABLED; + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + // Compute the vertex shader index. + DECLARE_DYNAMIC_VERTEX_SHADER( unlitgeneric_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( TESSELLATION, 0 ); + SET_DYNAMIC_VERTEX_SHADER( unlitgeneric_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( shadowbuildtexture_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( shadowbuildtexture_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( shadowbuildtexture_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( shadowbuildtexture_ps20 ); + } + } +#ifndef _X360 + else + { + nTessellationMode = pShaderAPI->GetTessellationMode(); + if ( nTessellationMode != TESSELLATION_MODE_DISABLED ) + { + pShaderAPI->BindStandardVertexTexture( SHADER_VERTEXTEXTURE_SAMPLER1, TEXTURE_SUBDIVISION_PATCHES ); + + bool bHasDisplacement = false; // TODO + float vSubDDimensions[4] = { 1.0f/pShaderAPI->GetSubDHeight(), bHasDisplacement && mat_displacementmap.GetBool() ? 1.0f : 0.0f, 0.0f, 0.0f }; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_8, vSubDDimensions ); + +// JasonM - revisit this later...requires plumbing in a separate vertex texture param type?? +// bool bHasDisplacement = (info.m_nDisplacementMap != -1) && params[info.m_nDisplacementMap]->IsTexture(); +// if( bHasDisplacement ) +// { +// pShader->BindVertexTexture( SHADER_VERTEXTEXTURE_SAMPLER2, info.m_nDisplacementMap ); +// } +// else +// { +// pShaderAPI->BindStandardVertexTexture( SHADER_VERTEXTEXTURE_SAMPLER2, VERTEX_TEXTURE_BLACK ); +// } + } + + // Compute the vertex shader index. + DECLARE_DYNAMIC_VERTEX_SHADER( unlitgeneric_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( TESSELLATION, nTessellationMode ); + SET_DYNAMIC_VERTEX_SHADER( unlitgeneric_vs30 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( shadowbuildtexture_ps30 ); + SET_DYNAMIC_PIXEL_SHADER( shadowbuildtexture_ps30 ); + } +#endif + + + } + Draw( ); + } +END_SHADER diff --git a/materialsystem/stdshaders/shadowbuildtexture_ps2x.fxc b/materialsystem/stdshaders/shadowbuildtexture_ps2x.fxc new file mode 100644 index 00000000..71dbc1d6 --- /dev/null +++ b/materialsystem/stdshaders/shadowbuildtexture_ps2x.fxc @@ -0,0 +1,27 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// +//paired with "unlitgeneric_vs20" + +#include "common_ps_fxc.h" + +sampler BaseTextureSampler : register( s0 ); + +struct PS_INPUT +{ + float2 vTexCoord0 : TEXCOORD0; + float4 vColor : COLOR0; + +#if defined( _X360 ) //matching pixel shader inputs to vertex shader outputs to avoid shader patches + float2 vTexCoord1 : TEXCOORD1; + float2 vTexCoord2 : TEXCOORD2; + float2 vTexCoord3 : TEXCOORD3; + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog +#endif +}; + +HALF4 main( PS_INPUT i ) : COLOR +{ + //relevant data is in the alpha channel, modulate vertex alpha by texture alpha + float returnAlpha = tex2D( BaseTextureSampler, i.vTexCoord0 ).a * i.vColor.a; + + return FinalOutput( float4( 1.0f, 1.0f, 1.0f, returnAlpha ), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} diff --git a/materialsystem/stdshaders/shadowmodel_dx9.cpp b/materialsystem/stdshaders/shadowmodel_dx9.cpp new file mode 100644 index 00000000..0ab56788 --- /dev/null +++ b/materialsystem/stdshaders/shadowmodel_dx9.cpp @@ -0,0 +1,148 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +//Note: Not upgraded to vs/ps 2.0 fxc's because this shader is unused and there are no test cases to verify against. +#include "BaseVSShader.h" + +#if !defined( _X360 ) +#include "shadowmodel.inc" +#endif + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( ShadowModel, ShadowModel_DX9 ) + + + +#if !defined( _X360 ) //not used for anything at time of 360 ship, and we want to avoid storing/loading assembly shaders + +//PC version +BEGIN_VS_SHADER_FLAGS( ShadowModel_DX9, "Help for ShadowModel", SHADER_NOT_EDITABLE ) + +BEGIN_SHADER_PARAMS +SHADER_PARAM( BASETEXTUREOFFSET, SHADER_PARAM_TYPE_VEC2, "[0 0]", "$baseTexture texcoord offset" ) +SHADER_PARAM( BASETEXTURESCALE, SHADER_PARAM_TYPE_VEC2, "[1 1]", "$baseTexture texcoord scale" ) +SHADER_PARAM( FALLOFFOFFSET, SHADER_PARAM_TYPE_FLOAT, "0", "Distance at which shadow starts to fade" ) +SHADER_PARAM( FALLOFFDISTANCE, SHADER_PARAM_TYPE_FLOAT, "100", "Max shadow distance" ) +SHADER_PARAM( FALLOFFAMOUNT, SHADER_PARAM_TYPE_FLOAT, "0.9", "Amount to brighten the shadow at max dist" ) +END_SHADER_PARAMS + +SHADER_INIT_PARAMS() +{ + if (!params[BASETEXTURESCALE]->IsDefined()) + { + Vector2D scale(1, 1); + params[BASETEXTURESCALE]->SetVecValue( scale.Base(), 2 ); + } + + if (!params[FALLOFFDISTANCE]->IsDefined()) + params[FALLOFFDISTANCE]->SetFloatValue( 100.0f ); + + if (!params[FALLOFFAMOUNT]->IsDefined()) + params[FALLOFFAMOUNT]->SetFloatValue( 0.9f ); +} + +SHADER_FALLBACK +{ + return 0; +} + +SHADER_INIT +{ + if (params[BASETEXTURE]->IsDefined()) + LoadTexture( BASETEXTURE ); +} + +SHADER_DRAW +{ + SHADOW_STATE + { + // Base texture on stage 0 + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + // Multiplicative blending state... + EnableAlphaBlending( SHADER_BLEND_DST_COLOR, SHADER_BLEND_ZERO ); + + int fmt = VERTEX_POSITION | VERTEX_NORMAL; + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 ); + + shadowmodel_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "ShadowModel", vshIndex.GetIndex() ); + + pShaderShadow->SetPixelShader( "ShadowModel" ); + + // We need to fog to *white* regardless of overbrighting... + FogToWhite(); + + // The constant color is the shadow color... + PI_BeginCommandBuffer(); + PI_SetModulationVertexShaderDynamicState(); + PI_EndCommandBuffer(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + SetVertexShaderMatrix3x4( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BASETEXTURETRANSFORM ); + + SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, BASETEXTUREOFFSET ); + SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, BASETEXTURESCALE ); + + Vector4D shadow; + shadow[0] = params[FALLOFFOFFSET]->GetFloatValue(); + shadow[1] = params[FALLOFFDISTANCE]->GetFloatValue() + shadow[0]; + if (shadow[1] != 0.0f) + shadow[1] = 1.0f / shadow[1]; + shadow[2] = params[FALLOFFAMOUNT]->GetFloatValue(); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_5, shadow.Base(), 1 ); + + shadowmodel_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + vshIndex.SetSKINNING( pShaderAPI->GetCurrentNumBones() > 0 ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw( ); +} +END_SHADER + + + + +#else +//360 version + +BEGIN_VS_SHADER_FLAGS( ShadowModel_DX9, "Help for ShadowModel", SHADER_NOT_EDITABLE ) + +BEGIN_SHADER_PARAMS +SHADER_PARAM( BASETEXTUREOFFSET, SHADER_PARAM_TYPE_VEC2, "[0 0]", "$baseTexture texcoord offset" ) +SHADER_PARAM( BASETEXTURESCALE, SHADER_PARAM_TYPE_VEC2, "[1 1]", "$baseTexture texcoord scale" ) +SHADER_PARAM( FALLOFFOFFSET, SHADER_PARAM_TYPE_FLOAT, "0", "Distance at which shadow starts to fade" ) +SHADER_PARAM( FALLOFFDISTANCE, SHADER_PARAM_TYPE_FLOAT, "100", "Max shadow distance" ) +SHADER_PARAM( FALLOFFAMOUNT, SHADER_PARAM_TYPE_FLOAT, "0.9", "Amount to brighten the shadow at max dist" ) +END_SHADER_PARAMS + +SHADER_INIT_PARAMS() +{ +} + +SHADER_FALLBACK +{ + return 0; +} + +SHADER_INIT +{ +} + +SHADER_DRAW +{ + Draw( false ); +} +END_SHADER + +#endif \ No newline at end of file diff --git a/materialsystem/stdshaders/shatteredglass.cpp b/materialsystem/stdshaders/shatteredglass.cpp new file mode 100644 index 00000000..9c0a3759 --- /dev/null +++ b/materialsystem/stdshaders/shatteredglass.cpp @@ -0,0 +1,286 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: Lightmap only shader +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" + +#include "shatteredglass_ps20.inc" +#include "shatteredglass_ps20b.inc" +#include "shatteredglass_vs20.inc" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +BEGIN_VS_SHADER( ShatteredGlass, + "Help for ShatteredGlass" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM_OVERRIDE( BASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "Glass/glasswindowbreak070b", "unused", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "Glass/glasswindowbreak070b", "detail" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "1.0", "detail scale" ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( ENVMAPMASK, SHADER_PARAM_TYPE_TEXTURE, "glass/glasswindowbreak070b_mask", "envmap mask" ) + SHADER_PARAM( ENVMAPMASKFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( ENVMAPMASKTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$envmapmask texcoord transform" ) + SHADER_PARAM( ENVMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "envmap tint" ) + SHADER_PARAM( ENVMAPCONTRAST, SHADER_PARAM_TYPE_FLOAT, "0.0", "contrast 0 == normal 1 == color*color" ) + SHADER_PARAM( ENVMAPSATURATION, SHADER_PARAM_TYPE_FLOAT, "1.0", "saturation 0 == greyscale 1 == normal" ) + SHADER_PARAM( FRESNELREFLECTION, SHADER_PARAM_TYPE_FLOAT, "1.0", "1.0 == mirror, 0.0 == water" ) + SHADER_PARAM( UNLITFACTOR, SHADER_PARAM_TYPE_FLOAT, "0.7", "0.0 == multiply by lightmap, 1.0 == multiply by 1" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + if( !params[DETAILSCALE]->IsDefined() ) + params[DETAILSCALE]->SetFloatValue( 1.0f ); + + if( !params[ENVMAPTINT]->IsDefined() ) + params[ENVMAPTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + + if( !params[ENVMAPCONTRAST]->IsDefined() ) + params[ENVMAPCONTRAST]->SetFloatValue( 0.0f ); + + if( !params[ENVMAPSATURATION]->IsDefined() ) + params[ENVMAPSATURATION]->SetFloatValue( 1.0f ); + + if( !params[UNLITFACTOR]->IsDefined() ) + params[UNLITFACTOR]->SetFloatValue( 0.3f ); + + if( !params[FRESNELREFLECTION]->IsDefined() ) + params[FRESNELREFLECTION]->SetFloatValue( 1.0f ); + + if( !params[ENVMAPMASKFRAME]->IsDefined() ) + params[ENVMAPMASKFRAME]->SetIntValue( 0 ); + + if( !params[ENVMAPFRAME]->IsDefined() ) + params[ENVMAPFRAME]->SetIntValue( 0 ); + + // No texture means no self-illum or env mask in base alpha + if ( !params[BASETEXTURE]->IsDefined() ) + { + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + // If in decal mode, no debug override... + if (IS_FLAG_SET(MATERIAL_VAR_DECAL)) + { + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + } + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + if (params[BASETEXTURE]->IsDefined()) + { + LoadTexture( BASETEXTURE ); + + if ( !params[BASETEXTURE]->GetTextureValue()->IsTranslucent() ) + { + if ( IS_FLAG_SET( MATERIAL_VAR_BASEALPHAENVMAPMASK ) ) + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + } + + if ( params[DETAIL]->IsDefined() ) + { + LoadTexture( DETAIL ); + } + + // Don't alpha test if the alpha channel is used for other purposes + if ( IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK) ) + CLEAR_FLAGS( MATERIAL_VAR_ALPHATEST ); + + if (params[ENVMAP]->IsDefined()) + { + LoadCubeMap( ENVMAP ); + if ( params[ENVMAPMASK]->IsDefined() ) + { + LoadTexture( ENVMAPMASK ); + } + } + } + + SHADER_DRAW + { + bool bHasEnvmapMask = false; + bool bHasEnvmap = false; + if ( params[ENVMAP]->IsTexture() ) + { + bHasEnvmap = true; + if ( params[ENVMAPMASK]->IsTexture() ) + { + bHasEnvmapMask = true; + } + } + bool bHasVertexColor = IS_FLAG_SET(MATERIAL_VAR_VERTEXCOLOR); + bool bHasBaseAlphaEnvmapMask = IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK); + + // Base + SHADOW_STATE + { + // alpha test + pShaderShadow->EnableAlphaTest( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) ); + + // Alpha blending, enable alpha blending if the detail texture is translucent + bool detailIsTranslucent = TextureIsTranslucent( DETAIL, false ); + if ( detailIsTranslucent ) + { + if ( IS_FLAG_SET( MATERIAL_VAR_ADDITIVE ) ) + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + else + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + else + { + SetDefaultBlendingShadowState( BASETEXTURE, true ); + } + + pShaderShadow->EnableSRGBWrite( true ); + + // Base texture + unsigned int flags = VERTEX_POSITION; + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + + // Lightmap + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ) + { + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); + } + else + { + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, false ); + } + + // Detail texture + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER3, true ); + + // Envmap + if ( bHasEnvmap ) + { + flags |= VERTEX_NORMAL; + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ) + { + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, true ); + } + + if( bHasEnvmapMask ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); + } + } + + // Normalizing cube map + pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); + + if ( bHasVertexColor ) + { + flags |= VERTEX_COLOR; + } + + pShaderShadow->VertexShaderVertexFormat( flags, 3, 0, 0 ); + + DECLARE_STATIC_VERTEX_SHADER( shatteredglass_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( ENVMAP_MASK, bHasEnvmapMask ); + SET_STATIC_VERTEX_SHADER( shatteredglass_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( shatteredglass_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( VERTEXCOLOR, bHasVertexColor ); + SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPMASK, bHasEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( BASEALPHAENVMAPMASK, bHasBaseAlphaEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( HDRTYPE, g_pHardwareConfig->GetHDRType() ); + SET_STATIC_PIXEL_SHADER( shatteredglass_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( shatteredglass_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( VERTEXCOLOR, bHasVertexColor ); + SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPMASK, bHasEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( BASEALPHAENVMAPMASK, bHasBaseAlphaEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( HDRTYPE, g_pHardwareConfig->GetHDRType() ); + SET_STATIC_PIXEL_SHADER( shatteredglass_ps20 ); + } + + DefaultFog(); + + PI_BeginCommandBuffer(); + PI_SetModulationPixelShaderDynamicState( 1 ); + PI_EndCommandBuffer(); + } + DYNAMIC_STATE + { + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BASETEXTURETRANSFORM ); + SetVertexShaderTextureScale( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, DETAILSCALE ); + + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP ); + BindTexture( SHADER_SAMPLER3, DETAIL ); + + if( bHasEnvmap ) + { + BindTexture( SHADER_SAMPLER2, ENVMAP, ENVMAPFRAME ); + if( bHasEnvmapMask ) + { + BindTexture( SHADER_SAMPLER5, ENVMAPMASK, ENVMAPMASKFRAME ); + } + } + + pShaderAPI->BindStandardTexture( SHADER_SAMPLER6, TEXTURE_NORMALIZATION_CUBEMAP_SIGNED ); + + DECLARE_DYNAMIC_VERTEX_SHADER( shatteredglass_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( shatteredglass_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( shatteredglass_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( shatteredglass_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( shatteredglass_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( shatteredglass_ps20 ); + } + + SetEnvMapTintPixelShaderDynamicState( 0, ENVMAPTINT, -1 ); + SetPixelShaderConstant( 2, ENVMAPCONTRAST ); + SetPixelShaderConstant( 3, ENVMAPSATURATION ); + + // [ 0, 0 ,0, R(0) ] + float fresnel[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + fresnel[3] = params[FRESNELREFLECTION]->GetFloatValue(); + fresnel[0] = fresnel[1] = fresnel[2] = 1.0f - fresnel[3]; + pShaderAPI->SetPixelShaderConstant( 4, fresnel ); + + float eyePos[4]; + pShaderAPI->GetWorldSpaceCameraPosition( eyePos ); + pShaderAPI->SetPixelShaderConstant( 5, eyePos, 1 ); + + pShaderAPI->SetPixelShaderFogParams( 12 ); + + float overbright[4]; + overbright[0] = OVERBRIGHT; + overbright[1] = params[UNLITFACTOR]->GetFloatValue(); + overbright[2] = overbright[3] = 1.0f - params[UNLITFACTOR]->GetFloatValue(); + pShaderAPI->SetPixelShaderConstant( 6, overbright ); + } + Draw(); + } +END_SHADER diff --git a/materialsystem/stdshaders/showz.cpp b/materialsystem/stdshaders/showz.cpp new file mode 100644 index 00000000..c81e1a95 --- /dev/null +++ b/materialsystem/stdshaders/showz.cpp @@ -0,0 +1,100 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: Visualize shadow z buffers. Designed to be used when drawing a screen-aligned +// quad with a floating-point z-buffer so that the large z-range is divided down +// into visual range of grayscale colors. +// +// $NoKeywords: $ +//===========================================================================// + +#include "convar.h" +#include "BaseVSShader.h" + +#include "showz_vs11.inc" +#include "showz_ps20.inc" +#include "showz_ps20b.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +static ConVar r_showz_power( "r_showz_power", "1.0f", FCVAR_CHEAT ); + + +BEGIN_VS_SHADER_FLAGS( showz, "Help for ShowZ", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( ALPHADEPTH, SHADER_PARAM_TYPE_INTEGER, "0", "Depth is stored in alpha channel" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + if ( !params[ALPHADEPTH]->IsDefined() ) + { + params[ALPHADEPTH]->SetIntValue( 0 ); + } + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + DECLARE_STATIC_VERTEX_SHADER( showz_vs11 ); + SET_STATIC_VERTEX_SHADER( showz_vs11 ); + + int nShadowFilterMode = g_pHardwareConfig->GetShadowFilterMode(); // Based upon vendor and device dependent formats + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( showz_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER_COMBO( DEPTH_IN_ALPHA, params[ALPHADEPTH]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER( showz_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( showz_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( DEPTH_IN_ALPHA, params[ALPHADEPTH]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER( showz_ps20 ); + } + + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 1, 0, 0 ); + + pShaderShadow->EnableSRGBWrite( false ); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); // Bind shadow depth map + + DECLARE_DYNAMIC_VERTEX_SHADER( showz_vs11 ); + SET_DYNAMIC_VERTEX_SHADER( showz_vs11 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( showz_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( showz_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( showz_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( showz_ps20 ); + } + + Vector4D C0; + C0.x = r_showz_power.GetFloat(); + + pShaderAPI->SetPixelShaderConstant( 0, C0.Base(), 1 ); + } + Draw(); + } +END_SHADER + diff --git a/materialsystem/stdshaders/showz_ps2x.fxc b/materialsystem/stdshaders/showz_ps2x.fxc new file mode 100644 index 00000000..65e21bef --- /dev/null +++ b/materialsystem/stdshaders/showz_ps2x.fxc @@ -0,0 +1,36 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps20b] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..0" [ps20b] [XBOX] +// STATIC: "DEPTH_IN_ALPHA" "0..1" + +#include "common_ps_fxc.h" + +const float4 g_Parameters : register( c0 ); + +sampler DepthTextureSampler : register( s0 ); // Scalar shadow depth map + +float4 main( float2 baseTexCoord : TEXCOORD0 ) : COLOR +{ + float fDepth = 0; + +# if (DEPTH_IN_ALPHA == 1) + { + fDepth = tex2D( DepthTextureSampler, baseTexCoord ).a; + + } +# else + { +# if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) //Minimum requirement of ps2b + { + fDepth = tex2D( DepthTextureSampler, baseTexCoord ).r; + } +# endif + } +# endif + + fDepth = pow( fDepth, g_Parameters.x ); + + return FinalOutput( float4( fDepth, fDepth, fDepth, 1.0f ), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} + diff --git a/materialsystem/stdshaders/showz_vs11.fxc b/materialsystem/stdshaders/showz_vs11.fxc new file mode 100644 index 00000000..0af2430d --- /dev/null +++ b/materialsystem/stdshaders/showz_vs11.fxc @@ -0,0 +1,33 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// +// +// Purpose: +// +//===========================================================================// + +#include "common_vs_fxc.h" + +struct VS_INPUT +{ + // If this is float4, and the input is float3, the w component defaults to one. + float4 vPos : POSITION; + float2 vBaseTexCoords : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; + float2 vBaseTexCoords : TEXCOORD0; +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o; + + float4 projPos; + + projPos = mul( v.vPos, cModelViewProj ); + o.projPos = projPos; + + o.vBaseTexCoords = v.vBaseTexCoords; + return o; +} diff --git a/materialsystem/stdshaders/sky_hdr_compressed_ps2x.fxc b/materialsystem/stdshaders/sky_hdr_compressed_ps2x.fxc new file mode 100644 index 00000000..38ad7200 --- /dev/null +++ b/materialsystem/stdshaders/sky_hdr_compressed_ps2x.fxc @@ -0,0 +1,30 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] + +#include "common_ps_fxc.h" + +#if defined( SHADER_MODEL_PS_2_0 ) +# define WRITE_DEPTH_TO_DESTALPHA 0 +#endif + +sampler ExposureTextureSampler0 : register( s0 ); +sampler ExposureTextureSampler1 : register( s1 ); +sampler ExposureTextureSampler2 : register( s2 ); + +struct PS_INPUT +{ + float2 baseTexCoord : TEXCOORD0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + HALF3 color0 = 0.25*tex2D( ExposureTextureSampler0, i.baseTexCoord ); + HALF3 color1 = 2.0*tex2D( ExposureTextureSampler1, i.baseTexCoord ); + HALF3 color2 = 16.0*tex2D( ExposureTextureSampler2, i.baseTexCoord ); + + // This is never fogged. +// return FinalOutput( float4( max(max(color0,color1),color2), 1.0f ), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_LINEAR, WRITE_DEPTH_TO_DESTALPHA, 1e20 ); //when writing depth to dest alpha, write a value guaranteed to saturate + return FinalOutput( float4(1,0,0,1 ), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_LINEAR, WRITE_DEPTH_TO_DESTALPHA, 1e20 ); //when writing depth to dest alpha, write a value guaranteed to saturate +} diff --git a/materialsystem/stdshaders/sky_hdr_compressed_rgbs_ps2x.fxc b/materialsystem/stdshaders/sky_hdr_compressed_rgbs_ps2x.fxc new file mode 100644 index 00000000..e899fc6e --- /dev/null +++ b/materialsystem/stdshaders/sky_hdr_compressed_rgbs_ps2x.fxc @@ -0,0 +1,82 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] + +#include "common_ps_fxc.h" + +#if defined( SHADER_MODEL_PS_2_0 ) +# define WRITE_DEPTH_TO_DESTALPHA 0 +#endif + +sampler RGBSTextureSampler : register( s0 ); +HALF4 InputScale : register( c0 ); + +float2 texWidthHeight : register( c1 ); + +float4 texOffsets : register( c2 ); + +struct PS_INPUT +{ +//#if defined( _X360 ) +// float2 baseTexCoord : TEXCOORD0; +//#else + float2 baseTexCoord00 : TEXCOORD0; + float2 baseTexCoord01 : TEXCOORD1; + float2 baseTexCoord10 : TEXCOORD2; + float2 baseTexCoord11 : TEXCOORD3; + float2 baseTexCoord_In_Pixels: TEXCOORD4; +//#endif +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float3 result; + +//#if defined( _X360 ) //360 has a cheaper way to handle RGBscale +// float4 Weights; +// float4 samples_0; //no arrays allowed in inline assembly +// float4 samples_1; +// float4 samples_2; +// float4 samples_3; +// float2 vTexCoord = i.baseTexCoord; +// +// asm { +// tfetch2D samples_0, vTexCoord.xy, RGBSTextureSampler, OffsetX = -0.5, OffsetY = -0.5, MinFilter=point, MagFilter=point, MipFilter=keep, UseComputedLOD=false +// tfetch2D samples_1, vTexCoord.xy, RGBSTextureSampler, OffsetX = 0.5, OffsetY = -0.5, MinFilter=point, MagFilter=point, MipFilter=keep, UseComputedLOD=false +// tfetch2D samples_2, vTexCoord.xy, RGBSTextureSampler, OffsetX = -0.5, OffsetY = 0.5, MinFilter=point, MagFilter=point, MipFilter=keep, UseComputedLOD=false +// tfetch2D samples_3, vTexCoord.xy, RGBSTextureSampler, OffsetX = 0.5, OffsetY = 0.5, MinFilter=point, MagFilter=point, MipFilter=keep, UseComputedLOD=false +// +// getWeights2D Weights, vTexCoord.xy, RGBSTextureSampler +// }; +// +// Weights = float4( (1-Weights.x)*(1-Weights.y), Weights.x*(1-Weights.y), (1-Weights.x)*Weights.y, Weights.x*Weights.y ); +// +// result.rgb = samples_0.rgb * (samples_0.a * Weights.x); +// result.rgb += samples_1.rgb * (samples_1.a * Weights.y); +// result.rgb += samples_2.rgb * (samples_2.a * Weights.z); +// result.rgb += samples_3.rgb * (samples_3.a * Weights.w); +// +//#else + float4 s00 = tex2D(RGBSTextureSampler, i.baseTexCoord00); + float4 s10 = tex2D(RGBSTextureSampler, i.baseTexCoord10); + float4 s01 = tex2D(RGBSTextureSampler, i.baseTexCoord01); + float4 s11 = tex2D(RGBSTextureSampler, i.baseTexCoord11); + + float2 fracCoord = frac(i.baseTexCoord_In_Pixels); + + s00.rgb*=s00.a; + s10.rgb*=s10.a; + + s00.xyz = lerp(s00, s10, fracCoord.x); + + s01.rgb*=s01.a; + s11.rgb*=s11.a; + s01.xyz = lerp(s01, s11, fracCoord.x); + + result = lerp(s00, s01, fracCoord.y); +//#endif + + // This is never fogged. + return FinalOutput( float4( InputScale*result, 1.0f ), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_LINEAR, WRITE_DEPTH_TO_DESTALPHA, 1e20 ); //when writing depth to dest alpha, write a value guaranteed to saturate +} diff --git a/materialsystem/stdshaders/sky_hdr_dx9.cpp b/materialsystem/stdshaders/sky_hdr_dx9.cpp new file mode 100644 index 00000000..cf0acc47 --- /dev/null +++ b/materialsystem/stdshaders/sky_hdr_dx9.cpp @@ -0,0 +1,250 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" +#include "sky_vs20.inc" +#include "sky_ps20.inc" +#include "sky_ps20b.inc" +#include "sky_hdr_compressed_ps20.inc" +#include "sky_hdr_compressed_ps20b.inc" +#include "sky_hdr_compressed_rgbs_ps20.inc" +#include "sky_hdr_compressed_rgbs_ps20b.inc" + +#include "ConVar.h" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +static ConVar mat_use_compressed_hdr_textures( "mat_use_compressed_hdr_textures", "1" ); + +DEFINE_FALLBACK_SHADER( Sky, Sky_HDR_DX9 ) + +BEGIN_VS_SHADER( Sky_HDR_DX9, "Help for Sky_HDR_DX9 shader" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( HDRBASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "base texture when running with HDR enabled" ) + SHADER_PARAM( HDRCOMPRESSEDTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "base texture (compressed) for hdr compression method A" ) + SHADER_PARAM( HDRCOMPRESSEDTEXTURE0, SHADER_PARAM_TYPE_TEXTURE, "", "compressed base texture0 for hdr compression method B" ) + SHADER_PARAM( HDRCOMPRESSEDTEXTURE1, SHADER_PARAM_TYPE_TEXTURE, "", "compressed base texture1 for hdr compression method B" ) + SHADER_PARAM( HDRCOMPRESSEDTEXTURE2, SHADER_PARAM_TYPE_TEXTURE, "", "compressed base texture2 for hdr compression method B" ) + SHADER_PARAM_OVERRIDE( COLOR, SHADER_PARAM_TYPE_VEC3, "[ 1 1 1]", "color multiplier", SHADER_PARAM_NOT_EDITABLE ) + END_SHADER_PARAMS + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT_PARAMS() + { + SET_FLAGS( MATERIAL_VAR_NOFOG ); + SET_FLAGS( MATERIAL_VAR_IGNOREZ ); + } + SHADER_INIT + { + if (params[HDRCOMPRESSEDTEXTURE]->IsDefined() && (mat_use_compressed_hdr_textures.GetBool() ) ) + { + LoadTexture( HDRCOMPRESSEDTEXTURE ); + } + else + { + if (params[HDRCOMPRESSEDTEXTURE0]->IsDefined()) + { + LoadTexture( HDRCOMPRESSEDTEXTURE0 ); + if (params[HDRCOMPRESSEDTEXTURE1]->IsDefined()) + { + LoadTexture( HDRCOMPRESSEDTEXTURE1 ); + } + if (params[HDRCOMPRESSEDTEXTURE2]->IsDefined()) + { + LoadTexture( HDRCOMPRESSEDTEXTURE2 ); + } + } + else + { + if (params[HDRBASETEXTURE]->IsDefined()) + { + LoadTexture( HDRBASETEXTURE ); + } + } + } + } + SHADER_DRAW + { + SHADOW_STATE + { + SetInitialShadowState(); + +// pShaderShadow->EnableAlphaWrites( true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 1, NULL, 0 ); + + DECLARE_STATIC_VERTEX_SHADER( sky_vs20 ); + SET_STATIC_VERTEX_SHADER( sky_vs20 ); + + if ( (params[HDRCOMPRESSEDTEXTURE]->IsDefined()) && + mat_use_compressed_hdr_textures.GetBool() ) + { + pShaderShadow->EnableSRGBRead(SHADER_SAMPLER0,false); + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( sky_hdr_compressed_rgbs_ps20b ); + SET_STATIC_PIXEL_SHADER( sky_hdr_compressed_rgbs_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( sky_hdr_compressed_rgbs_ps20 ); + SET_STATIC_PIXEL_SHADER( sky_hdr_compressed_rgbs_ps20 ); + } + } + else + { + if (params[HDRCOMPRESSEDTEXTURE0]->IsDefined()) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + + pShaderShadow->EnableSRGBRead(SHADER_SAMPLER0,false); + pShaderShadow->EnableSRGBRead(SHADER_SAMPLER1,false); + pShaderShadow->EnableSRGBRead(SHADER_SAMPLER2,false); + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( sky_hdr_compressed_ps20b ); + SET_STATIC_PIXEL_SHADER( sky_hdr_compressed_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( sky_hdr_compressed_ps20 ); + SET_STATIC_PIXEL_SHADER( sky_hdr_compressed_ps20 ); + } + } + else + { + ITexture *txtr=params[HDRBASETEXTURE]->GetTextureValue(); + ImageFormat fmt=txtr->GetImageFormat(); + if ((fmt==IMAGE_FORMAT_RGBA16161616F) || (fmt==IMAGE_FORMAT_RGBA16161616)) + pShaderShadow->EnableSRGBRead(SHADER_SAMPLER0,false); + else + pShaderShadow->EnableSRGBRead(SHADER_SAMPLER0,true); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( sky_ps20b ); + SET_STATIC_PIXEL_SHADER( sky_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( sky_ps20 ); + SET_STATIC_PIXEL_SHADER( sky_ps20 ); + } + } + } + // we are writing linear values from this shader. + pShaderShadow->EnableSRGBWrite( true ); + + pShaderShadow->EnableAlphaWrites( true ); + } + + DYNAMIC_STATE + { + DECLARE_DYNAMIC_VERTEX_SHADER( sky_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( sky_vs20 ); + + // Texture coord transform + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, BASETEXTURETRANSFORM ); + + float c0[4]={1,1,1,1}; + if (params[COLOR]->IsDefined()) + { + memcpy(c0,params[COLOR]->GetVecValue(),3*sizeof(float)); + } + if ( + params[HDRCOMPRESSEDTEXTURE]->IsDefined() && + mat_use_compressed_hdr_textures.GetBool() + ) + { + // set up data needs for pixel shader interpolation + ITexture *txtr=params[HDRCOMPRESSEDTEXTURE]->GetTextureValue(); + float w=txtr->GetActualWidth(); + float h=txtr->GetActualHeight(); + float FUDGE=0.01/MAX(w,h); // per ATI + float c1[4]={0.5/w-FUDGE, 0.5/h-FUDGE, w, h }; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, c1); + + BindTexture( SHADER_SAMPLER0, HDRCOMPRESSEDTEXTURE, FRAME ); + c0[0]*=8.0; + c0[1]*=8.0; + c0[2]*=8.0; + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( sky_hdr_compressed_rgbs_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( sky_hdr_compressed_rgbs_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( sky_hdr_compressed_rgbs_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( sky_hdr_compressed_rgbs_ps20 ); + } + } + else + { + float c1[4]={0,0,0,0}; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, c1); + + if (params[HDRCOMPRESSEDTEXTURE0]->IsDefined() ) + { + BindTexture( SHADER_SAMPLER0, HDRCOMPRESSEDTEXTURE0, FRAME ); + BindTexture( SHADER_SAMPLER1, HDRCOMPRESSEDTEXTURE1, FRAME ); + BindTexture( SHADER_SAMPLER2, HDRCOMPRESSEDTEXTURE2, FRAME ); + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( sky_hdr_compressed_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( sky_hdr_compressed_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( sky_hdr_compressed_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( sky_hdr_compressed_ps20 ); + } + + } + else + { + BindTexture( SHADER_SAMPLER0, HDRBASETEXTURE, FRAME ); + ITexture *txtr=params[HDRBASETEXTURE]->GetTextureValue(); + ImageFormat fmt=txtr->GetImageFormat(); + if ( + (fmt==IMAGE_FORMAT_RGBA16161616) || + ( (fmt==IMAGE_FORMAT_RGBA16161616F) && + (g_pHardwareConfig->GetHDRType()==HDR_TYPE_INTEGER)) + ) + { + c0[0]*=16.0; + c0[1]*=16.0; + c0[2]*=16.0; + } + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( sky_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( sky_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( sky_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( sky_ps20 ); + } + } + } + pShaderAPI->SetPixelShaderConstant( 0, c0, 1 ); + } + Draw( ); + } +END_SHADER diff --git a/materialsystem/stdshaders/sky_ps2x.fxc b/materialsystem/stdshaders/sky_ps2x.fxc new file mode 100644 index 00000000..e08fe188 --- /dev/null +++ b/materialsystem/stdshaders/sky_ps2x.fxc @@ -0,0 +1,27 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] + +#include "common_ps_fxc.h" + +#if defined( SHADER_MODEL_PS_2_0 ) +# define WRITE_DEPTH_TO_DESTALPHA 0 +#endif + +sampler BaseTextureSampler : register( s0 ); +HALF4 InputScale : register( c0 ); + +struct PS_INPUT +{ + float2 baseTexCoord : TEXCOORD0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + HALF4 color = tex2D( BaseTextureSampler, i.baseTexCoord.xy ); + color.rgb *= InputScale.rgb; + + // This is never fogged. + return FinalOutput( color, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_LINEAR, WRITE_DEPTH_TO_DESTALPHA, 1e20 ); //when writing depth to dest alpha, write a value guaranteed to saturate +} diff --git a/materialsystem/stdshaders/sky_vs20.fxc b/materialsystem/stdshaders/sky_vs20.fxc new file mode 100644 index 00000000..51a27a00 --- /dev/null +++ b/materialsystem/stdshaders/sky_vs20.fxc @@ -0,0 +1,64 @@ +#include "common_vs_fxc.h" + +const float4 g_vTextureSizeInfo : register( SHADER_SPECIFIC_CONST_0 ); +const float4 g_mBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_1 ); + //SHADER_SPECIFIC_CONST_2 + +#define TEXEL_XINCR (g_vTextureSizeInfo.x) +#define TEXEL_YINCR (g_vTextureSizeInfo.y) +#define U_TO_PIXEL_COORD_SCALE (g_vTextureSizeInfo.z) +#define V_TO_PIXEL_COORD_SCALE (g_vTextureSizeInfo.w) + +struct VS_INPUT +{ + float4 vPos : POSITION; + float2 vTexCoord0 : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; + +//#if defined( _X360 ) +// float2 baseTexCoord : TEXCOORD0; +//#else + float2 baseTexCoord00 : TEXCOORD0; + float2 baseTexCoord01 : TEXCOORD1; + float2 baseTexCoord10 : TEXCOORD2; + float2 baseTexCoord11 : TEXCOORD3; + float2 baseTexCoord_In_Pixels: TEXCOORD4; +//#endif +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + o.projPos = mul( v.vPos, cModelViewProj ); + + float4 vTexCoordInput = { v.vTexCoord0.x, v.vTexCoord0.y, 0.0f, 1.0f }; + float2 vTexCoord; + vTexCoord.x = dot( vTexCoordInput.xyzw, g_mBaseTexCoordTransform[0] ); + vTexCoord.y = dot( vTexCoordInput.xyzw, g_mBaseTexCoordTransform[1] ); + +//#if defined( _X360 ) +// o.baseTexCoord.xy = vTexCoord.xy; +//#else + // Compute quantities needed for pixel shader texture lerping + o.baseTexCoord00.x = vTexCoord.x - TEXEL_XINCR; + o.baseTexCoord00.y = vTexCoord.y - TEXEL_YINCR; + o.baseTexCoord10.x = vTexCoord.x + TEXEL_XINCR; + o.baseTexCoord10.y = vTexCoord.y - TEXEL_YINCR; + + o.baseTexCoord01.x = vTexCoord.x - TEXEL_XINCR; + o.baseTexCoord01.y = vTexCoord.y + TEXEL_YINCR; + o.baseTexCoord11.x = vTexCoord.x + TEXEL_XINCR; + o.baseTexCoord11.y = vTexCoord.y + TEXEL_YINCR; + + o.baseTexCoord_In_Pixels.xy = o.baseTexCoord00.xy; + o.baseTexCoord_In_Pixels.x *= U_TO_PIXEL_COORD_SCALE; + o.baseTexCoord_In_Pixels.y *= V_TO_PIXEL_COORD_SCALE; +//#endif + + return o; +} diff --git a/materialsystem/stdshaders/spline_fxc.h b/materialsystem/stdshaders/spline_fxc.h new file mode 100644 index 00000000..dfa1c5c6 --- /dev/null +++ b/materialsystem/stdshaders/spline_fxc.h @@ -0,0 +1,19 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// derivative of catmull rom spline courtesy of calc +float4 DCatmullRomSpline ( float4 a, float4 b, float4 c, float4 d, float t ) +{ + return 0.5 *( c - a + t * ( 2 * a - 5 * b + 4 * c - d + t * (3 * b - a - 3 * c + d ) ) + + t * ( 2 * a - 5 * b + 4 * c - d + 2 * ( t * ( 3 * b - a - 3 * c + d ) ) ) ); +} + +float3 DCatmullRomSpline3 ( float3 a, float3 b, float3 c, float3 d, float t ) +{ + return 0.5 *( c - a + t * ( 2 * a - 5 * b + 4 * c - d + t * (3 * b - a - 3 * c + d ) ) + + t * ( 2 * a - 5 * b + 4 * c - d + 2 * ( t * ( 3 * b - a - 3 * c + d ) ) ) ); +} + +float4 CatmullRomSpline( float4 a, float4 b, float4 c, float4 d, float t ) +{ + return b + 0.5 * t * ( c - a + t * ( 2 * a - 5 * b + 4 * c - d + t * ( -a + 3 * b -3 * c + d ) ) ); +} diff --git a/materialsystem/stdshaders/splinecard_vsxx.fxc b/materialsystem/stdshaders/splinecard_vsxx.fxc new file mode 100644 index 00000000..5e2097ff --- /dev/null +++ b/materialsystem/stdshaders/splinecard_vsxx.fxc @@ -0,0 +1,123 @@ +#include "common_vs_fxc.h" +#include "spline_fxc.h" + +// These are "0..0" for the splinecard case. We only use these combos in the spritecard case. +// STATIC: "ADDBASETEXTURE2" "0..0" +// STATIC: "EXTRACTGREENALPHA" "0..0" +// STATIC: "DUALSEQUENCE" "0..0" +// STATIC: "DEPTHBLEND" "0..0" +// STATIC: "PACKED_INTERPOLATOR" "0..0" +// These determine the format of VS_OUTPUT: +// STATIC: "ANIMBLEND_OR_MAXLUMFRAMEBLEND1" "0..1" + +// DYNAMIC: "ORIENTATION" "0..3" + +#define ANIMBLEND ANIMBLEND_OR_MAXLUMFRAMEBLEND1 +#define MAXLUMFRAMEBLEND1 ANIMBLEND_OR_MAXLUMFRAMEBLEND1 + +const float4x3 cModelView : register(SHADER_SPECIFIC_CONST_0); +const float4x4 cProj : register(SHADER_SPECIFIC_CONST_3); +const float4 SizeParms : register(SHADER_SPECIFIC_CONST_8); +const float4 SizeParms2 : register(SHADER_SPECIFIC_CONST_9); + +#define MINIMUM_SIZE_FACTOR (SizeParms.x) +#define MAXIMUM_SIZE_FACTOR (SizeParms.y) + +#define START_FADE_SIZE_FACTOR (SizeParms.z) +#define END_FADE_SIZE_FACTOR (SizeParms.w) + +// alpha fade w/ distance +#define START_FAR_FADE ( SizeParms2.x ) +#define FAR_FADE_FACTOR ( SizeParms2.y ) // alpha = 1-min(1,max(0, (dist-start_fade)*factor)) + + +#define ALPHATFADE ( SizeParms2.z ) +#define RADIUSTFADE ( SizeParms2.w ) + +struct VS_INPUT +{ + // This is all of the stuff that we ever use. + float4 vTint : COLOR; + float4 vParms : POSITION; // T V side_id + float4 vSplinePt0 : TEXCOORD0; // x y z rad + float4 vSplinePt1 : TEXCOORD1; // x y z rad + float4 vSplinePt2 : TEXCOORD2; // x y z rad + float4 vSplinePt3 : TEXCOORD3; // x y z rad + float4 vTexCoordRange : TEXCOORD4; // u0 v0 u1 v1 + float4 vEndPointColor : TEXCOORD5; // r g b a at p1 +#if ORIENTATION == 3 + float3 vNormal0 : TEXCOORD6; // normal at p0 + float3 vNormal1 : TEXCOORD7; // normal at p1 +#endif + + +}; + +// VS_OUTPUT in a common file. +#include "common_spritecard_fxc.h" + +// #define P0 float4( 0,0,0,40) +// #define P1 float4( 0,0,100,40) +// #define P2 float4( 0,0,200,40) +// #define P3 float4( 0,0,300,40) + +#define P0 (v.vSplinePt0) +#define P1 (v.vSplinePt1) +#define P2 (v.vSplinePt2) +#define P3 (v.vSplinePt3) + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o; + + o.vecOutlineTint = 1; + + // posrad.xyz is worldspace position and posrad.w is worldspace diameter. + float4 posrad = + CatmullRomSpline( P0, P1, P2, P3, v.vParms.x ); + posrad.w *= lerp( 1, RADIUSTFADE, v.vParms.x ); + float3 v2p = float3( 0, 0, 1 ); + if ( ORIENTATION == 0 ) + { + v2p = posrad.xyz - cEyePos; // screen aligned + } + +#if ( ORIENTATION == 3 ) // use normal + v2p = lerp( v.vNormal0, v.vNormal1, v.vParms.x ); +#endif + + float3 tangent = DCatmullRomSpline3( P0, P1, P2, P3, v.vParms.x ); + float3 ofs = normalize( cross( v2p, normalize( tangent ) ) ); + posrad.xyz += ofs * ( posrad.w * ( v.vParms.z - .5 ) ); + o.projPos = mul( float4(posrad.xyz, 1.0f), cViewProj ); + o.texCoord0_1.wz = o.texCoord0_1.xy = float2( lerp( v.vTexCoordRange.z, v.vTexCoordRange.x, v.vParms.z ), lerp( v.vTexCoordRange.y, v.vTexCoordRange.w, v.vParms.y ) ); + + float4 color1 = float4( GammaToLinear( v.vTint.rgb ), v.vTint.a ); + float4 color2 = float4( GammaToLinear( v.vEndPointColor.rgb ), v.vEndPointColor.a ); + + o.argbcolor = lerp( color1, color2, v.vParms.x ); + o.argbcolor.a *= lerp( 1, ALPHATFADE, v.vParms.x ); + + + // Don't really need these in the splinecard case, but since we aren't typically fillrate limited with + // spline cards (are we?), then go ahead and send it through. +#if HAS_BLENDFACTOR0 + o.blendfactor0.xyzw = float4( 0.0f, 0.0f, 0.0f, 0.0f ); +#endif +#if DEPTHBLEND + #if defined( REVERSE_DEPTH_ON_X360 ) + o.vScreenPos_ReverseZ.xyzw = float4( 0.0f, 0.0f, 0.0f, 0.0f ); + #else + o.vScreenPos.xyzw = float4( 0.0f, 0.0f, 0.0f, 0.0f ); + #endif +#endif + + #if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + { + o.fog = CalcFixedFunctionFog( posrad.xyz, 0 ); + } + #endif + + return o; + +} diff --git a/materialsystem/stdshaders/splinerope.cpp b/materialsystem/stdshaders/splinerope.cpp new file mode 100644 index 00000000..0ad611c5 --- /dev/null +++ b/materialsystem/stdshaders/splinerope.cpp @@ -0,0 +1,162 @@ +//===== Copyright © 1996-2008, Valve Corporation, All rights reserved. ======// + +#include "BaseVSShader.h" +#include "convar.h" + +#include "splinerope_ps20.inc" +#include "splinerope_ps20b.inc" +#include "splinerope_vs20.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +static ConVar rope_min_pixel_diameter( "rope_min_pixel_diameter", "2.0", FCVAR_CHEAT ); + +BEGIN_VS_SHADER( SplineRope, "Help for SplineRope" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( SHADERSRGBREAD360, SHADER_PARAM_TYPE_BOOL, "0", "Simulate srgb read in shader code") + SHADER_PARAM( SHADOWDEPTH, SHADER_PARAM_TYPE_INTEGER, "0", "writing to a shadow depth buffer" ) + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "cable/cablenormalmap", "normal map" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + // srgb read 360 + InitIntParam( SHADERSRGBREAD360, params, 0 ); + InitIntParam( SHADOWDEPTH, params, 0 ); + if ( !params[BUMPMAP]->IsDefined() ) + { + params[BUMPMAP]->SetStringValue( "cable/cablenormalmap" ); + } + SET_FLAGS2( MATERIAL_VAR2_IS_SPRITECARD ); // What's this for? + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + LoadTexture( BASETEXTURE ); + LoadBumpMap( BUMPMAP ); + } + + SHADER_DRAW + { + bool bShaderSrgbRead = ( IsX360() && params[SHADERSRGBREAD360]->GetIntValue() ); + bool bShadowDepth = ( params[SHADOWDEPTH]->GetIntValue() != 0 ); + SHADOW_STATE + { + // draw back-facing because of yaw spin + pShaderShadow->EnableCulling( false ); + + if ( bShadowDepth ) + { + // don't write color and alpha since we only interested in depth for shadow maps. + pShaderShadow->EnableColorWrites( false ); + pShaderShadow->EnableAlphaWrites( false ); + + // polyoffset for shadow maps. + pShaderShadow->EnablePolyOffset( SHADER_POLYOFFSET_SHADOW_BIAS ); + } + else + { + // We need to write to dest alpha for depth feathering. + pShaderShadow->EnableAlphaWrites( true ); + + // base texture + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, !bShaderSrgbRead ); + + // normal map + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + pShaderShadow->EnableSRGBWrite( true ); + + FogToFogColor(); + } + + static int s_TexCoordSize[]={ 4, // (worldspace xyz) (radius (diameter?) of spline at this point) for first control point + 4, // (worldspace xyz) (radius of spline at this point) for second control point + 4, // (worldspace xyz) (radius of spline at this point) for third control point + 4, // (worldspace xyz) (radius of spline at this point) for fourth control point + }; + + unsigned int flags = VERTEX_POSITION | VERTEX_COLOR; + + int numTexCoords = 4; + pShaderShadow->VertexShaderVertexFormat( flags, numTexCoords, s_TexCoordSize, 0 ); + + DECLARE_STATIC_VERTEX_SHADER( splinerope_vs20 ); + SET_STATIC_VERTEX_SHADER( splinerope_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( splinerope_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( SHADER_SRGB_READ, bShaderSrgbRead ); + SET_STATIC_PIXEL_SHADER_COMBO( SHADOWDEPTH, bShadowDepth ); + SET_STATIC_PIXEL_SHADER( splinerope_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( splinerope_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( SHADER_SRGB_READ, bShaderSrgbRead ); + SET_STATIC_PIXEL_SHADER_COMBO( SHADOWDEPTH, bShadowDepth ); + SET_STATIC_PIXEL_SHADER( splinerope_ps20 ); + } + } + DYNAMIC_STATE + { + // We need these only when screen-orienting, which we are always in this shader. + LoadModelViewMatrixIntoVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0 ); + LoadProjectionMatrixIntoVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3 ); + + // Get viewport and render target dimensions and set shader constant to do a 2D mad + int nViewportX, nViewportY, nViewportWidth, nViewportHeight; + pShaderAPI->GetCurrentViewport( nViewportX, nViewportY, nViewportWidth, nViewportHeight ); + + float c7[4]={ 0.0f, 0.0f, 0.0f, 0.0f }; + if ( !g_pHardwareConfig->IsAAEnabled() ) + { + float flMinPixelDiameter = rope_min_pixel_diameter.GetFloat() / ( float )nViewportWidth; + c7[0]= c7[1] = c7[2] = c7[3] = flMinPixelDiameter; + } + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, c7, 1 ); + + // bind base texture + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + + // normal map + BindTexture( SHADER_SAMPLER1, BUMPMAP ); + + if ( !bShadowDepth ) + { + pShaderAPI->SetPixelShaderFogParams( 0 ); + + float vEyePos[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos ); + vEyePos[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( 1, vEyePos, 1 ); + } + + DECLARE_DYNAMIC_VERTEX_SHADER( splinerope_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( splinerope_vs20 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( splinerope_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( splinerope_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( splinerope_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( splinerope_ps20 ); + } + } + Draw( ); + } +END_SHADER diff --git a/materialsystem/stdshaders/splinerope_ps2x.fxc b/materialsystem/stdshaders/splinerope_ps2x.fxc new file mode 100644 index 00000000..0013db54 --- /dev/null +++ b/materialsystem/stdshaders/splinerope_ps2x.fxc @@ -0,0 +1,52 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "SHADER_SRGB_READ" "0..1" [XBOX] +// STATIC: "SHADER_SRGB_READ" "0..0" [PC] +// STATIC: "SHADOWDEPTH" "0..1" +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20] + +#include "common_fog_ps_fxc.h" +#include "common_ps_fxc.h" + +float4 g_FogParams : register( c0 ); +float3 g_EyePos : register( c1 ); + +// VS_OUTPUT in a common file. +#define PIXELSHADER +#include "common_splinerope_fxc.h" + +sampler BaseTextureSampler : register( s0 ); +sampler NormalSampler : register( s1 ); + +float4 main( PS_INPUT i ) : COLOR +{ + #if ( SHADOWDEPTH == 0 ) + { + float3 vNormalMapDir = tex2D( NormalSampler, i.texCoord.xy ); // Get the 3-vector from the normal map + float4 textureColor = tex2Dsrgb( BaseTextureSampler, i.texCoord.xy ); + + //Expand compacted vectors + vNormalMapDir = ( vNormalMapDir - 0.5 ) * 2.0; + float3 vLightDir = float3( 0.0f, 0.0f, 1.0f ); + + float lightDirDotNormalMap = dot( vNormalMapDir, vLightDir ); //normalMap dot dirLightDir + + // do half-lambert on the dot + lightDirDotNormalMap = lightDirDotNormalMap * 0.5 + 0.5; + lightDirDotNormalMap = lightDirDotNormalMap * lightDirDotNormalMap; + + float4 resultColor; + resultColor.xyz = lightDirDotNormalMap * ( textureColor.rgb * i.argbcolor.rgb ); + resultColor.a = textureColor.a * i.argbcolor.a; + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos.xyz, i.worldPos_projPosZ.xyz, i.worldPos_projPosZ.w ); + return FinalOutput( resultColor, fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, (WRITE_DEPTH_TO_DESTALPHA != 0), i.worldPos_projPosZ.w ); + } + #else + { + return float4( 0.0f, 0.0f, 0.0f, 1.0f ); + } + #endif +} diff --git a/materialsystem/stdshaders/splinerope_vsxx.fxc b/materialsystem/stdshaders/splinerope_vsxx.fxc new file mode 100644 index 00000000..5aca3f4c --- /dev/null +++ b/materialsystem/stdshaders/splinerope_vsxx.fxc @@ -0,0 +1,77 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#include "common_vs_fxc.h" +#include "spline_fxc.h" + +const float4x3 cModelView : register(SHADER_SPECIFIC_CONST_0); +const float4x4 cProj : register(SHADER_SPECIFIC_CONST_3); +const float g_MinPixelSize : register(SHADER_SPECIFIC_CONST_7); + +struct VS_INPUT +{ + // This is all of the stuff that we ever use. + float4 vTint : COLOR; + float4 vParms : POSITION; // T V side_id + float4 vSplinePt0 : TEXCOORD0; // x y z rad + float4 vSplinePt1 : TEXCOORD1; // x y z rad + float4 vSplinePt2 : TEXCOORD2; // x y z rad + float4 vSplinePt3 : TEXCOORD3; // x y z rad +}; + +// VS_OUTPUT in a common file. +#include "common_splinerope_fxc.h" + +#define P0 (v.vSplinePt0) +#define P1 (v.vSplinePt1) +#define P2 (v.vSplinePt2) +#define P3 (v.vSplinePt3) + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o; + + // posrad.xyz is worldspace position and posrad.w is worldspace diameter. + float4 posrad = CatmullRomSpline( P0, P1, P2, P3, v.vParms.x ); + + // calculate projected position here so that we can figure out how much to bloat the diameter to avoid aliasing of the sort where you skip pixels in a segment. + { + // PERF FIXME!! This could be simplified quite a bit if this ever becomes a bottleneck. I feel dirty. + // Get the view-space position for two points that are posrad.w units away from each other horizontally. + float3 viewPos1 = mul4x3( float4( posrad.xyz, 1.0f ), cModelView ); + float3 viewPos2 = viewPos1 + float3( posrad.w, 0.0f, 0.0f ); + + // Project both points. + float4 projPos1 = mul( float4( viewPos1, 1.0f ), cProj ); + float4 projPos2 = mul( float4( viewPos2, 1.0f ), cProj ); + + // Get the distance of the two points from each other in normalized screen space. + float projectedDiameterInPixels = abs( ( projPos1.x / projPos1.w ) - ( projPos2.x / projPos2.w ) ); + + // Compare the distance between the two points to the minimum allowed to keep from skipping pixels and causing aliasing. + if ( projectedDiameterInPixels < g_MinPixelSize ) + { + // Scale the radius in world space so that it is bigger than the required pixel size in screen space. + posrad.w *= ( g_MinPixelSize / projectedDiameterInPixels ); + } + } + + float3 v2p = float3( 0, 0, 1 ); + v2p = posrad.xyz - cEyePos; // screen aligned + + float3 tangent = DCatmullRomSpline3( P0, P1, P2, P3, v.vParms.x ); + float3 ofs = normalize( cross( v2p, normalize( tangent ) ) ); + posrad.xyz += ofs * ( posrad.w * ( v.vParms.z - .5 ) ); + o.projPos = mul( float4(posrad.xyz, 1.0f), cViewProj ); + o.worldPos_projPosZ.xyz = posrad.xyz; + o.worldPos_projPosZ.w = o.projPos.z; + o.texCoord.xy = float2( 1.0f - v.vParms.z, v.vParms.y ); + o.argbcolor = float4( v.vTint.rgb, v.vTint.a ); + + #if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + { + o.fog = CalcFixedFunctionFog( posrad.xyz, 0 ); + } + #endif + + return o; +} diff --git a/materialsystem/stdshaders/sprite_dx9.cpp b/materialsystem/stdshaders/sprite_dx9.cpp new file mode 100644 index 00000000..58d0a835 --- /dev/null +++ b/materialsystem/stdshaders/sprite_dx9.cpp @@ -0,0 +1,467 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// + +#include "BaseVSShader.h" +#include +#include "const.h" + +#include "cpp_shader_constant_register_map.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#include "sprite_vs20.inc" +#include "sprite_ps20.inc" +#include "sprite_ps20b.inc" + +// WARNING! Change these in engine/SpriteGn.h if you change them here! +#define SPR_VP_PARALLEL_UPRIGHT 0 +#define SPR_FACING_UPRIGHT 1 +#define SPR_VP_PARALLEL 2 +#define SPR_ORIENTED 3 +#define SPR_VP_PARALLEL_ORIENTED 4 + + +DEFINE_FALLBACK_SHADER( Sprite, Sprite_DX9 ) + +BEGIN_VS_SHADER( Sprite_DX9, + "Help for Sprite_DX9" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( SPRITEORIGIN, SHADER_PARAM_TYPE_VEC3, "[0 0 0]", "sprite origin" ) + SHADER_PARAM( SPRITEORIENTATION, SHADER_PARAM_TYPE_INTEGER, "0", "sprite orientation" ) + SHADER_PARAM( SPRITERENDERMODE, SHADER_PARAM_TYPE_INTEGER, "0", "sprite rendermode" ) + SHADER_PARAM( IGNOREVERTEXCOLORS, SHADER_PARAM_TYPE_BOOL, "1", "ignore vertex colors" ) + SHADER_PARAM( NOSRGB, SHADER_PARAM_TYPE_BOOL, "0", "do not operate in srgb space" ) + SHADER_PARAM( HDRCOLORSCALE, SHADER_PARAM_TYPE_FLOAT, "1.0", "hdr color scale" ) + END_SHADER_PARAMS + + SHADER_FALLBACK + { + return 0; + } + SHADER_INIT_PARAMS() + { + // FIXME: This can share code with sprite.cpp + if (!params[ALPHA]->IsDefined()) + { + params[ALPHA]->SetFloatValue( 1.0f ); + } + + if (!params[HDRCOLORSCALE]->IsDefined()) + { + params[HDRCOLORSCALE]->SetFloatValue( 1.0f ); + } + + if ( !params[NOSRGB]->IsDefined() ) + { + // Disable sRGB reads and writes by default + params[NOSRGB]->SetIntValue( 1 ); + } + + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + SET_FLAGS( MATERIAL_VAR_VERTEXCOLOR ); + SET_FLAGS( MATERIAL_VAR_VERTEXALPHA ); + + // translate from a string orientation to an enumeration + if (params[SPRITEORIENTATION]->IsDefined()) + { + const char *orientationString = params[SPRITEORIENTATION]->GetStringValue(); + if( stricmp( orientationString, "parallel_upright" ) == 0 ) + { + params[SPRITEORIENTATION]->SetIntValue( SPR_VP_PARALLEL_UPRIGHT ); + } + else if( stricmp( orientationString, "facing_upright" ) == 0 ) + { + params[SPRITEORIENTATION]->SetIntValue( SPR_FACING_UPRIGHT ); + } + else if( stricmp( orientationString, "vp_parallel" ) == 0 ) + { + params[SPRITEORIENTATION]->SetIntValue( SPR_VP_PARALLEL ); + } + else if( stricmp( orientationString, "oriented" ) == 0 ) + { + params[SPRITEORIENTATION]->SetIntValue( SPR_ORIENTED ); + } + else if( stricmp( orientationString, "vp_parallel_oriented" ) == 0 ) + { + params[SPRITEORIENTATION]->SetIntValue( SPR_VP_PARALLEL_ORIENTED ); + } + else + { + Warning( "error with $spriteOrientation\n" ); + params[SPRITEORIENTATION]->SetIntValue( SPR_VP_PARALLEL_UPRIGHT ); + } + } + else + { + // default case + params[SPRITEORIENTATION]->SetIntValue( SPR_VP_PARALLEL_UPRIGHT ); + } + } + + SHADER_INIT + { + LoadTexture( BASETEXTURE ); + } + +#define SHADER_USE_VERTEX_COLOR 1 +#define SHADER_USE_CONSTANT_COLOR 2 + + void SetSpriteCommonShadowState( unsigned int shaderFlags, IMaterialVar **params ) + { + IShaderShadow *pShaderShadow = s_pShaderShadow; + s_pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + bool bSRGB = s_ppParams[NOSRGB]->GetIntValue() == 0; + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, bSRGB ); + + unsigned int flags = VERTEX_POSITION; + if( shaderFlags & SHADER_USE_VERTEX_COLOR ) + { + flags |= VERTEX_COLOR; + } + int numTexCoords = 1; + s_pShaderShadow->VertexShaderVertexFormat( flags, numTexCoords, 0, 0 ); + + DECLARE_STATIC_VERTEX_SHADER( sprite_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( VERTEXCOLOR, ( shaderFlags & SHADER_USE_VERTEX_COLOR ) ? true : false ); + SET_STATIC_VERTEX_SHADER_COMBO( SRGB, bSRGB ); + SET_STATIC_VERTEX_SHADER( sprite_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( sprite_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( VERTEXCOLOR, ( shaderFlags & SHADER_USE_VERTEX_COLOR ) ? true : false ); + SET_STATIC_PIXEL_SHADER_COMBO( CONSTANTCOLOR, ( shaderFlags & SHADER_USE_CONSTANT_COLOR ) ? true : false ); + SET_STATIC_PIXEL_SHADER_COMBO( HDRTYPE, g_pHardwareConfig->GetHDRType() ); + SET_STATIC_PIXEL_SHADER_COMBO( SRGB, bSRGB ); + SET_STATIC_PIXEL_SHADER( sprite_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( sprite_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( VERTEXCOLOR, ( shaderFlags & SHADER_USE_VERTEX_COLOR ) ? true : false ); + SET_STATIC_PIXEL_SHADER_COMBO( CONSTANTCOLOR, ( shaderFlags & SHADER_USE_CONSTANT_COLOR ) ? true : false ); + SET_STATIC_PIXEL_SHADER_COMBO( HDRTYPE, g_pHardwareConfig->GetHDRType() ); + SET_STATIC_PIXEL_SHADER_COMBO( SRGB, bSRGB ); + SET_STATIC_PIXEL_SHADER( sprite_ps20 ); + } + + s_pShaderShadow->EnableSRGBWrite( bSRGB ); + } + + void SetSpriteCommonDynamicState( unsigned int shaderFlags ) + { + IShaderDynamicAPI *pShaderAPI = s_pShaderAPI; + bool bSRGB = s_ppParams[NOSRGB]->GetIntValue() == 0; + + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + + DECLARE_DYNAMIC_VERTEX_SHADER( sprite_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( sprite_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( sprite_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( HDRENABLED, IsHDREnabled() ); + SET_DYNAMIC_PIXEL_SHADER( sprite_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( sprite_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( HDRENABLED, IsHDREnabled() ); + SET_DYNAMIC_PIXEL_SHADER( sprite_ps20 ); + } + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + float vEyePos_SpecExponent[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + vEyePos_SpecExponent[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + + if( shaderFlags & SHADER_USE_CONSTANT_COLOR ) + { + if ( bSRGB ) + SetPixelShaderConstantGammaToLinear( 0, COLOR, ALPHA ); + else + SetPixelShaderConstant( 0, COLOR, ALPHA ); + } + + if( IsHDREnabled() ) + { + if ( bSRGB ) + SetPixelShaderConstantGammaToLinear( 1, HDRCOLORSCALE ); + else + SetPixelShaderConstant( 1, HDRCOLORSCALE ); + } + } + + SHADER_DRAW + { + bool bSRGB = params[NOSRGB]->GetIntValue() == 0; + + SHADOW_STATE + { + pShaderShadow->EnableCulling( false ); + } + + switch( params[SPRITERENDERMODE]->GetIntValue() ) + { + case kRenderNormal: + SHADOW_STATE + { + FogToFogColor(); + + SetSpriteCommonShadowState( 0, params ); + } + DYNAMIC_STATE + { + SetSpriteCommonDynamicState( 0 ); + } + Draw(); + break; + case kRenderTransColor: + case kRenderTransTexture: + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + + FogToFogColor(); + + SetSpriteCommonShadowState( SHADER_USE_VERTEX_COLOR, params ); + } + DYNAMIC_STATE + { + SetSpriteCommonDynamicState( SHADER_USE_VERTEX_COLOR ); + } + Draw(); + break; + case kRenderGlow: + case kRenderWorldGlow: + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableDepthTest( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + + FogToBlack(); + + SetSpriteCommonShadowState( SHADER_USE_VERTEX_COLOR, params ); + } + DYNAMIC_STATE + { + SetSpriteCommonDynamicState( SHADER_USE_VERTEX_COLOR ); + } + Draw(); + break; + case kRenderTransAlpha: + // untested cut and past from kRenderTransAlphaAdd . . same as first pass of that. + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + + FogToFogColor(); + + SetSpriteCommonShadowState( SHADER_USE_VERTEX_COLOR, params ); + } + DYNAMIC_STATE + { + SetSpriteCommonDynamicState( SHADER_USE_VERTEX_COLOR ); + } + Draw(); + break; + case kRenderTransAlphaAdd: + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + + FogToFogColor(); + + SetSpriteCommonShadowState( SHADER_USE_VERTEX_COLOR, params ); + } + DYNAMIC_STATE + { + SetSpriteCommonDynamicState( SHADER_USE_VERTEX_COLOR ); + } + Draw(); + + SHADOW_STATE + { + SetInitialShadowState(); + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_ONE_MINUS_SRC_ALPHA, SHADER_BLEND_ONE ); + + FogToBlack(); + + SetSpriteCommonShadowState( SHADER_USE_VERTEX_COLOR, params ); + } + DYNAMIC_STATE + { + SetSpriteCommonDynamicState( SHADER_USE_VERTEX_COLOR ); + } + Draw(); + break; + + case kRenderTransAdd: + { + unsigned int flags = SHADER_USE_CONSTANT_COLOR; + if( !params[ IGNOREVERTEXCOLORS ]->GetIntValue() ) + { + flags |= SHADER_USE_VERTEX_COLOR; + } + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + + FogToBlack(); + + SetSpriteCommonShadowState( flags, params ); + } + DYNAMIC_STATE + { + SetSpriteCommonDynamicState( flags ); + } + } + Draw(); + break; + case kRenderTransAddFrameBlend: + { + float flFrame = params[FRAME]->GetFloatValue(); + float flFade = params[ALPHA]->GetFloatValue(); + unsigned int flags = SHADER_USE_CONSTANT_COLOR; + if( !params[ IGNOREVERTEXCOLORS ]->GetIntValue() ) + { + flags |= SHADER_USE_VERTEX_COLOR; + } + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + + FogToBlack(); + + SetSpriteCommonShadowState( flags, params ); + } + DYNAMIC_STATE + { + float frameBlendAlpha = 1.0f - ( flFrame - ( int )flFrame ); + ITexture *pTexture = params[BASETEXTURE]->GetTextureValue(); + BindTexture( SHADER_SAMPLER0, pTexture, ( int )flFrame ); + + DECLARE_DYNAMIC_VERTEX_SHADER( sprite_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( sprite_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( sprite_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( HDRENABLED, IsHDREnabled() ); + SET_DYNAMIC_PIXEL_SHADER( sprite_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( sprite_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( HDRENABLED, IsHDREnabled() ); + SET_DYNAMIC_PIXEL_SHADER( sprite_ps20 ); + } + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + float vEyePos_SpecExponent[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + vEyePos_SpecExponent[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + + float color[4]; + if ( bSRGB ) + color[0] = color[1] = color[2] = GammaToLinear( flFade * frameBlendAlpha ); + else + color[0] = color[1] = color[2] = flFade * frameBlendAlpha; + color[3] = 1.0f; + s_pShaderAPI->SetPixelShaderConstant( 0, color ); + if( IsHDREnabled() ) + { + if ( bSRGB ) + SetPixelShaderConstantGammaToLinear( 1, HDRCOLORSCALE ); + else + SetPixelShaderConstant( 1, HDRCOLORSCALE ); + } + } + Draw(); + SHADOW_STATE + { + FogToBlack(); + + SetSpriteCommonShadowState( flags, params ); + } + DYNAMIC_STATE + { + float frameBlendAlpha = ( flFrame - ( int )flFrame ); + ITexture *pTexture = params[BASETEXTURE]->GetTextureValue(); + int numAnimationFrames = pTexture->GetNumAnimationFrames(); + BindTexture( SHADER_SAMPLER0, pTexture, ( ( int )flFrame + 1 ) % numAnimationFrames ); + + DECLARE_DYNAMIC_VERTEX_SHADER( sprite_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( sprite_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( sprite_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( HDRENABLED, IsHDREnabled() ); + SET_DYNAMIC_PIXEL_SHADER( sprite_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( sprite_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( HDRENABLED, IsHDREnabled() ); + SET_DYNAMIC_PIXEL_SHADER( sprite_ps20 ); + } + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + float vEyePos_SpecExponent[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + vEyePos_SpecExponent[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + + float color[4]; + if ( bSRGB ) + color[0] = color[1] = color[2] = GammaToLinear( flFade * frameBlendAlpha ); + else + color[0] = color[1] = color[2] = flFade * frameBlendAlpha; + color[3] = 1.0f; + s_pShaderAPI->SetPixelShaderConstant( 0, color ); + if( IsHDREnabled() ) + { + if ( bSRGB ) + SetPixelShaderConstantGammaToLinear( 1, HDRCOLORSCALE ); + else + SetPixelShaderConstant( 1, HDRCOLORSCALE ); + } + } + Draw(); + } + + break; + default: + ShaderWarning( "shader Sprite: Unknown sprite render mode\n" ); + break; + } + } +END_SHADER diff --git a/materialsystem/stdshaders/sprite_ps2x.fxc b/materialsystem/stdshaders/sprite_ps2x.fxc new file mode 100644 index 00000000..95c6e5a1 --- /dev/null +++ b/materialsystem/stdshaders/sprite_ps2x.fxc @@ -0,0 +1,53 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "VERTEXCOLOR" "0..1" +// STATIC: "CONSTANTCOLOR" "0..1" +// STATIC: "HDRTYPE" "0..2" +// STATIC: "SRGB" "0..1" + +// DYNAMIC: "HDRENABLED" "0..1" +#include "common_fog_ps_fxc.h" + +#include "common_ps_fxc.h" +#include "shader_constant_register_map.h" + +const HALF4 g_Color : register( c0 ); +const float g_HDRColorScale : register( c1 ); + +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT ); + +sampler TexSampler : register( s0 ); + +struct PS_INPUT +{ + HALF2 baseTexCoord : TEXCOORD0; // Base texture coordinate + float4 color : TEXCOORD2; // Vertex color (from lighting or unlit) + + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float4 sample = tex2D( TexSampler, i.baseTexCoord ); + +#if VERTEXCOLOR + sample *= i.color; +#endif + +#if CONSTANTCOLOR + sample *= g_Color; +#endif + +#if HDRTYPE && HDRENABLED + sample.xyz *= g_HDRColorScale; +#endif + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos_SpecExponent.xyz, i.worldPos_projPosZ.xyz, i.worldPos_projPosZ.w ); +#if SRGB + return FinalOutput( sample, fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR ); +#else + return FinalOutput( sample, fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_GAMMA ); +#endif +} + diff --git a/materialsystem/stdshaders/sprite_vs20.fxc b/materialsystem/stdshaders/sprite_vs20.fxc new file mode 100644 index 00000000..df3d9518 --- /dev/null +++ b/materialsystem/stdshaders/sprite_vs20.fxc @@ -0,0 +1,65 @@ +// STATIC: "VERTEXCOLOR" "0..1" +// STATIC: "SRGB" "0..1" +#include "common_fog_vs_fxc.h" + +#include "common_vs_fxc.h" + +static const int g_FogType = DOWATERFOG; +static const bool g_bVertexColor = VERTEXCOLOR ? true : false; + +struct VS_INPUT +{ + // This is all of the stuff that we ever use. + float4 vPos : POSITION; + float4 vColor : COLOR0; + // make these float2's and stick the [n n 0 1] in the dot math. + float4 vTexCoord0 : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; // Projection-space position +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + float fog : FOG; +#endif + HALF2 baseTexCoord : TEXCOORD0; // Base texture coordinate + float4 color : TEXCOORD2; // Vertex color (from lighting or unlit) + + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog +}; + + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 worldPos; + worldPos = mul4x3( v.vPos, cModel[0] ); + + // Transform into projection space + float4 projPos = mul( float4( worldPos, 1 ), cViewProj ); + o.projPos = projPos; + + o.worldPos_projPosZ = float4( worldPos.xyz, projPos.z ); + +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + o.fog = CalcFixedFunctionFog( worldPos, g_FogType ); +#endif + + if ( g_bVertexColor ) + { + // Assume that this is unlitgeneric if you are using vertex color. +#if SRGB + o.color.rgba = GammaToLinear( v.vColor.rgba ); +#else + o.color.rgba = v.vColor.rgba; +#endif + } + + // Base texture coordinates + o.baseTexCoord.xy = v.vTexCoord0.xy; + + return o; +} + + diff --git a/materialsystem/stdshaders/spritecard.cpp b/materialsystem/stdshaders/spritecard.cpp new file mode 100644 index 00000000..e0a04448 --- /dev/null +++ b/materialsystem/stdshaders/spritecard.cpp @@ -0,0 +1,603 @@ +//===== Copyright © 1996-2007, Valve Corporation, All rights reserved. ======// +// +// Purpose: shader for drawing sprites as cards, with animation frame lerping +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "basevsshader.h" +#include "convar.h" + +// STDSHADER_DX9_DLL_EXPORT +#include "spritecard_ps20.inc" +#include "spritecard_ps20b.inc" +#include "spritecard_vs20.inc" +#include "splinecard_vs20.inc" + +#include "tier0/icommandline.h" //command line + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#define DEFAULT_PARTICLE_FEATHERING_ENABLED 1 + +static ConVar mat_depthfeather_enable( "mat_depthfeather_enable", "1", FCVAR_DEVELOPMENTONLY ); + +int GetDefaultDepthFeatheringValue( void ) //Allow the command-line to go against the default soft-particle value +{ + static int iRetVal = -1; + + if ( iRetVal == -1 ) + { + #if ( DEFAULT_PARTICLE_FEATHERING_ENABLED == 1 ) + { + if ( CommandLine()->CheckParm( "-softparticlesdefaultoff" ) ) + iRetVal = 0; + else + iRetVal = 1; + } + #else + { + if ( CommandLine()->CheckParm( "-softparticlesdefaulton" ) ) + iRetVal = 1; + else + iRetVal = 0; + } + #endif + } + + return iRetVal; +} + + +BEGIN_VS_SHADER_FLAGS( Spritecard, "Help for Spritecard", SHADER_NOT_EDITABLE ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( DEPTHBLEND, SHADER_PARAM_TYPE_INTEGER, "0", "fade at intersection boundaries" ) + SHADER_PARAM( DEPTHBLENDSCALE, SHADER_PARAM_TYPE_FLOAT, "50.0", "Amplify or reduce DEPTHBLEND fading. Lower values make harder edges." ) + SHADER_PARAM( INVERSEDEPTHBLEND, SHADER_PARAM_TYPE_BOOL, "0", "calculate 1-depthblendalpha so that sprites appear when they are near geometry" ) + SHADER_PARAM( ORIENTATION, SHADER_PARAM_TYPE_INTEGER, "0", "0 = always face camera, 1 = rotate around z, 2= parallel to ground 3=use normal" ) + SHADER_PARAM( ADDBASETEXTURE2, SHADER_PARAM_TYPE_FLOAT, "0.0", "amount to blend second texture into frame by" ) + SHADER_PARAM( OVERBRIGHTFACTOR, SHADER_PARAM_TYPE_FLOAT, "1.0", "overbright factor for texture. For HDR effects.") + SHADER_PARAM( DUALSEQUENCE, SHADER_PARAM_TYPE_INTEGER, "0", "blend two separate animated sequences.") + SHADER_PARAM( SEQUENCE_BLEND_MODE, SHADER_PARAM_TYPE_INTEGER, "0", "defines the blend mode between the images un dual sequence particles. 0 = avg, 1=alpha from first, rgb from 2nd, 2= first over second" ) + SHADER_PARAM( MAXLUMFRAMEBLEND1, SHADER_PARAM_TYPE_INTEGER, "0", "instead of blending between animation frames for the first sequence, select pixels based upon max luminance" ) + SHADER_PARAM( MAXLUMFRAMEBLEND2, SHADER_PARAM_TYPE_INTEGER, "0", "instead of blending between animation frames for the 2nd sequence, select pixels based upon max luminance" ) + SHADER_PARAM( RAMPTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "if specified, then the red value of the image is used to index this ramp to produce the output color" ) + SHADER_PARAM( ZOOMANIMATESEQ2, SHADER_PARAM_TYPE_FLOAT, "1.0", "amount to gradually zoom between frames on the second sequence. 2.0 will double the size of a frame over its lifetime.") + SHADER_PARAM( EXTRACTGREENALPHA, SHADER_PARAM_TYPE_INTEGER, "0", "grayscale data sitting in green/alpha channels") + SHADER_PARAM( ADDOVERBLEND, SHADER_PARAM_TYPE_INTEGER, "0", "use ONE:INVSRCALPHA blending") + SHADER_PARAM( ADDSELF, SHADER_PARAM_TYPE_FLOAT, "0.0", "amount of base texture to additively blend in" ) + SHADER_PARAM( BLENDFRAMES, SHADER_PARAM_TYPE_BOOL, "1", "whether or not to smoothly blend between animated frames" ) + SHADER_PARAM( MINSIZE, SHADER_PARAM_TYPE_FLOAT, "0.0", "minimum screen fractional size of particle") + SHADER_PARAM( STARTFADESIZE, SHADER_PARAM_TYPE_FLOAT, "10.0", "screen fractional size to start fading particle out") + SHADER_PARAM( ENDFADESIZE, SHADER_PARAM_TYPE_FLOAT, "20.0", "screen fractional size to finish fading particle out") + SHADER_PARAM( MAXSIZE, SHADER_PARAM_TYPE_FLOAT, "20.0", "maximum screen fractional size of particle") + SHADER_PARAM( USEINSTANCING, SHADER_PARAM_TYPE_BOOL, "1", "whether to use GPU vertex instancing (submit 1 vert per particle quad)") + SHADER_PARAM( SPLINETYPE, SHADER_PARAM_TYPE_INTEGER, "0", "spline type 0 = none, 1=ctamull rom") + SHADER_PARAM( MAXDISTANCE, SHADER_PARAM_TYPE_FLOAT, "100000.0", "maximum distance to draw particles at") + SHADER_PARAM( FARFADEINTERVAL, SHADER_PARAM_TYPE_FLOAT, "400.0", "interval over which to fade out far away particles") + SHADER_PARAM( SHADERSRGBREAD360, SHADER_PARAM_TYPE_BOOL, "0", "Simulate srgb read in shader code") + SHADER_PARAM( ORIENTATIONMATRIX, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "Matrix used to orient in orientation mode #2" ) + SHADER_PARAM( MOD2X, SHADER_PARAM_TYPE_BOOL, "0", "whether or not to multiply the result of the pixel shader * 2 against the framebuffer" ) + SHADER_PARAM( ALPHATRAILFADE, SHADER_PARAM_TYPE_FLOAT, "1", "Amount to scale alpha by between start and end of trail/rope" ) + SHADER_PARAM( RADIUSTRAILFADE, SHADER_PARAM_TYPE_FLOAT, "1", "Amount to scale radis by between start and end of trail/rope" ) + SHADER_PARAM( SHADOWDEPTH,SHADER_PARAM_TYPE_INTEGER, "0", "writing to a shadow depth buffer" ) + SHADER_PARAM( OPAQUE, SHADER_PARAM_TYPE_BOOL, "0", "Are we opaque? (defaults to 0)" ) + SHADER_PARAM( CROPFACTOR,SHADER_PARAM_TYPE_VEC2, "[1 1]", "writing to a shadow depth buffer" ) + SHADER_PARAM( VERTEXCOLORLERP, SHADER_PARAM_TYPE_BOOL, "0", "Enable computing vertex color by interpolating two color based on vertex r color channel" ) + SHADER_PARAM( LERPCOLOR1, SHADER_PARAM_TYPE_VEC3, "[1 0 0]", "Lerp color 1" ) + SHADER_PARAM( LERPCOLOR2, SHADER_PARAM_TYPE_VEC3, "[0 1 0]", "Lerp color 2" ) + SHADER_PARAM( VERTEXFOGAMOUNT, SHADER_PARAM_TYPE_FLOAT, "1", "Amount of vertex fog to apply" ) + + // distance outline control + SHADER_PARAM( DISTANCEALPHA, SHADER_PARAM_TYPE_BOOL, "0", "Use distance-coded alpha generated from hi-res texture by vtex.") + + SHADER_PARAM( SOFTEDGES, SHADER_PARAM_TYPE_BOOL, "0", "Enable soft edges to distance coded textures.") + SHADER_PARAM( EDGESOFTNESSSTART, SHADER_PARAM_TYPE_FLOAT, "0.6", "Start value for soft edges for distancealpha."); + SHADER_PARAM( EDGESOFTNESSEND, SHADER_PARAM_TYPE_FLOAT, "0.5", "End value for soft edges for distancealpha."); + + SHADER_PARAM( OUTLINE, SHADER_PARAM_TYPE_BOOL, "0", "Enable outline for distance coded textures.") + SHADER_PARAM( OUTLINECOLOR, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "color of outline for distance coded images." ) + SHADER_PARAM( OUTLINEALPHA, SHADER_PARAM_TYPE_FLOAT, "0.0", "alpha value for outline") + SHADER_PARAM( OUTLINESTART0, SHADER_PARAM_TYPE_FLOAT, "0.0", "outer start value for outline") + SHADER_PARAM( OUTLINESTART1, SHADER_PARAM_TYPE_FLOAT, "0.0", "inner start value for outline") + SHADER_PARAM( OUTLINEEND0, SHADER_PARAM_TYPE_FLOAT, "0.0", "inner end value for outline") + SHADER_PARAM( OUTLINEEND1, SHADER_PARAM_TYPE_FLOAT, "0.0", "outer end value for outline") + SHADER_PARAM( PERPARTICLEOUTLINE, SHADER_PARAM_TYPE_BOOL, "0", "Allow per particle outline control" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + INIT_FLOAT_PARM( MAXDISTANCE, 100000.0 ); + INIT_FLOAT_PARM( FARFADEINTERVAL, 400.0 ); + INIT_FLOAT_PARM( MAXSIZE, 20.0 ); + INIT_FLOAT_PARM( ENDFADESIZE, 20.0 ); + INIT_FLOAT_PARM( STARTFADESIZE, 10.0 ); + INIT_FLOAT_PARM( DEPTHBLENDSCALE, 50.0 ); + INIT_FLOAT_PARM( OVERBRIGHTFACTOR, 1.0 ); + INIT_FLOAT_PARM( ADDBASETEXTURE2, 0.0 ); + INIT_FLOAT_PARM( ADDSELF, 0.0 ); + INIT_FLOAT_PARM( ZOOMANIMATESEQ2, 0.0 ); + INIT_FLOAT_PARM( ALPHATRAILFADE, 1. ); + INIT_FLOAT_PARM( RADIUSTRAILFADE, 1. ); + INIT_FLOAT_PARM( VERTEXFOGAMOUNT, 0.0f ); + INIT_FLOAT_PARM( OUTLINEALPHA, 1.0 ); + + if ( !params[ORIENTATIONMATRIX]->IsDefined() ) + { + VMatrix mat; + MatrixSetIdentity( mat ); + params[ORIENTATIONMATRIX]->SetMatrixValue( mat ); + } + + if ( !params[CROPFACTOR]->IsDefined() ) + { + params[CROPFACTOR]->SetVecValue( 1.0f, 1.0f ); + } + + if ( !params[DEPTHBLEND]->IsDefined() ) + { + params[ DEPTHBLEND ]->SetIntValue( GetDefaultDepthFeatheringValue() ); + } + if ( !g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + params[ DEPTHBLEND ]->SetIntValue( 0 ); + } + InitIntParam( DUALSEQUENCE, params, 0 ); + InitIntParam( MAXLUMFRAMEBLEND1, params, 0 ); + InitIntParam( MAXLUMFRAMEBLEND2, params, 0 ); + InitIntParam( EXTRACTGREENALPHA, params, 0 ); + InitIntParam( ADDOVERBLEND, params, 0 ); + InitIntParam( BLENDFRAMES, params, 1 ); + + InitIntParam( DISTANCEALPHA, params, 0 ); + InitIntParam( OUTLINE, params, 0 ); + InitIntParam( SOFTEDGES, params, 0 ); + InitIntParam( PERPARTICLEOUTLINE, params, 0 ); + + + if ( !params[USEINSTANCING]->IsDefined() ) + { + params[ USEINSTANCING ]->SetIntValue( IsX360() ? 1 : 0 ); + } + + // srgb read 360 + InitIntParam( SHADERSRGBREAD360, params, 0 ); + + // default to being translucent since that's what we always were for historical reasons. + InitIntParam( OPAQUE, params, 0 ); + + InitIntParam( VERTEXCOLORLERP, params, 0 ); + if ( !params[LERPCOLOR1]->IsDefined() ) + { + params[LERPCOLOR1]->SetVecValue( 1.0f, 0.0f, 0.0f ); + } + if ( !params[LERPCOLOR2]->IsDefined() ) + { + params[LERPCOLOR2]->SetVecValue( 0.0f, 1.0f, 0.0f ); + } + + if ( params[OPAQUE]->GetIntValue() != 0 ) + { + // none of these make sense if we have $opaque 1: + params[ADDBASETEXTURE2]->SetFloatValue( 0.0f ); + params[DUALSEQUENCE]->SetIntValue( 0 ); + params[SEQUENCE_BLEND_MODE]->SetIntValue( 0 ); + params[MAXLUMFRAMEBLEND1]->SetIntValue( 0 ); + params[MAXLUMFRAMEBLEND2]->SetIntValue( 0 ); + params[EXTRACTGREENALPHA]->SetIntValue( 0 ); + params[RAMPTEXTURE]->SetUndefined(); + params[ZOOMANIMATESEQ2]->SetIntValue( 0 ); + params[ADDOVERBLEND]->SetIntValue( 0 ); + params[ADDSELF]->SetIntValue( 0 ); + params[BLENDFRAMES]->SetIntValue( 0 ); + params[DEPTHBLEND]->SetIntValue( 0 ); + params[INVERSEDEPTHBLEND]->SetIntValue( 0 ); + } + + SET_FLAGS2( MATERIAL_VAR2_IS_SPRITECARD ); + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + + if ( params[BASETEXTURE]->IsDefined() ) + { + bool bExtractGreenAlpha = false; + if ( params[EXTRACTGREENALPHA]->IsDefined() ) + bExtractGreenAlpha = params[EXTRACTGREENALPHA]->GetIntValue() != 0; + + LoadTexture( BASETEXTURE ); + } + if ( params[RAMPTEXTURE]->IsDefined() ) + { + LoadTexture( RAMPTEXTURE ); + } + } + + SHADER_DRAW + { + bool bUseRampTexture = ( params[RAMPTEXTURE]->IsDefined() ); + bool bZoomSeq2 = ( ( params[ZOOMANIMATESEQ2]->GetFloatValue()) > 1.0 ); + bool bDepthBlend = false; + if ( IsX360() ) + { + // Don't create the depth texture. We are looking at not using depth feathering to save memory. + static bool bNoDepthTexture = ( CommandLine()->FindParm( "-nodepthtexture" ) ) ? true : false; + if ( !bNoDepthTexture ) + { + bDepthBlend = ( params[DEPTHBLEND]->GetIntValue() != 0 ) && mat_depthfeather_enable.GetBool(); + } + } + bool bInverseDepthBlend = ( params[INVERSEDEPTHBLEND]->GetIntValue() != 0 ); + bool bAdditive2ndTexture = params[ADDBASETEXTURE2]->GetFloatValue() != 0.0; + bool bExtractGreenAlpha = ( params[EXTRACTGREENALPHA]->GetIntValue() != 0 ); + int nSplineType = params[SPLINETYPE]->GetIntValue(); + bool bUseInstancing = IsX360() ? ( params[ USEINSTANCING ]->GetIntValue() != 0 ) : false; + bool bShaderSrgbRead = ( IsX360() && IS_PARAM_DEFINED( SHADERSRGBREAD360 ) && params[SHADERSRGBREAD360]->GetIntValue() ); + bool bCrop = ( params[CROPFACTOR]->GetVecValue()[0] != 1.0f ) || ( params[CROPFACTOR]->GetVecValue()[1] != 1.0f ); + bool bSecondSequence = params[DUALSEQUENCE]->GetIntValue() != 0; + bool bBlendFrames = ( params[BLENDFRAMES]->GetIntValue() != 0 ); + + bool bDistanceAlpha = ( params[DISTANCEALPHA]->GetIntValue() != 0 ); + bool bOutLine = bDistanceAlpha && ( params[OUTLINE]->GetIntValue() != 0 ); + bool bSoftEdges = bDistanceAlpha && ( params[OUTLINE]->GetIntValue() != 0 ); + bool bPerParticleOutline = bDistanceAlpha && ( !bSecondSequence ) && ( params[PERPARTICLEOUTLINE]->GetIntValue() ); + + if ( nSplineType ) + { + bDepthBlend = false; //splinecard_vsxx.fxc don't output all the data necessary for depth blending + bUseInstancing = false; + bBlendFrames = false; + } + + bool bColorLerpPS = ( params[VERTEXCOLORLERP]->GetIntValue() != 0 ); + bool bPackedInterpolator = bColorLerpPS && !( bExtractGreenAlpha || bSecondSequence || bBlendFrames || params[MAXLUMFRAMEBLEND1]->GetIntValue() ); + + bool bFog = params[VERTEXFOGAMOUNT]->GetFloatValue() != 0; + SHADOW_STATE + { + bool bAddOverBlend = params[ADDOVERBLEND]->GetIntValue() != 0; + bool bMod2X = params[MOD2X]->GetIntValue() != 0; + bool bShadowDepth = ( params[SHADOWDEPTH]->GetIntValue() != 0 ); + bool bAddSelf = params[ADDSELF]->GetFloatValue() != 0.0; + if ( bFog ) + { + pShaderShadow->FogMode( SHADER_FOGMODE_FOGCOLOR, true ); + } + + // draw back-facing because of yaw spin + pShaderShadow->EnableCulling( false ); + + // Don't write to dest alpha. + pShaderShadow->EnableAlphaWrites( false ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + if ( bUseRampTexture ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, !bShaderSrgbRead ); + } + + if ( bDepthBlend ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + } + + if ( bAdditive2ndTexture || bAddSelf ) + pShaderShadow->EnableAlphaTest( false ); + else + pShaderShadow->EnableAlphaTest( true ); + + pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GREATER, 1 / 255 ); + + if ( bMod2X ) + { + EnableAlphaBlending( SHADER_BLEND_DST_COLOR, SHADER_BLEND_SRC_COLOR ); + } + else if ( bAdditive2ndTexture || bAddOverBlend || bAddSelf ) + { + EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + else + { + if ( IS_FLAG_SET(MATERIAL_VAR_ADDITIVE) ) + { + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + } + else + { + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + } + + bool bUseNormal = ( params[ORIENTATION]->GetIntValue() == 3 ); + unsigned int flags = VERTEX_POSITION | VERTEX_COLOR; + static int s_TexCoordSize[8]={4, // 0 = sheet bounding uvs, frame0 + 4, // 1 = sheet bounding uvs, frame 1 + 4, // 2 = frame blend, rot, radius, ??? + 2, // 3 = corner identifier ( 0/0,1/0,1/1, 1/0 ) + 4, // 4 = texture 2 bounding uvs + 4, // 5 = second sequence bounding uvs, frame0.. or glow tint, or normal + 4, // 6 = second sequence bounding uvs, frame1 + 4, // 7 = second sequence frame blend, ?,?,? + }; + static int s_TexCoordSizeSpline[]={4, // 0 = xyz rad pt0 + 4, // 1 = xyz rad pt1 + 4, // 2 = xyz rad pt2 + 4, // 3 = xyz rad pt3 + 4, // 4 = texture range u0,v0-u1,v1 + 4, // 5 = rgba pt1 + 3, // 6 = normal0 + 3, // 7 = normal1 + + }; + + int numTexCoords = 5; + if ( nSplineType ) + { + numTexCoords += 1; // need second rope color + if ( bUseNormal ) + numTexCoords += 2; // need normal vectors + } + else + { + if ( bPerParticleOutline || bUseNormal ) + { + numTexCoords = 6; + } + else + { + if ( bSecondSequence ) + { + // the whole shebang - 2 sequences, with a possible multi-image sequence first + numTexCoords = 8; + } + } + } + pShaderShadow->VertexShaderVertexFormat( flags, + numTexCoords, + nSplineType? s_TexCoordSizeSpline : s_TexCoordSize, 0 ); + + if ( nSplineType ) + { + DECLARE_STATIC_VERTEX_SHADER( splinecard_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( ADDBASETEXTURE2, 0 ); + SET_STATIC_VERTEX_SHADER_COMBO( EXTRACTGREENALPHA, 0 ); + SET_STATIC_VERTEX_SHADER_COMBO( DUALSEQUENCE, 0 ); + SET_STATIC_VERTEX_SHADER_COMBO( DEPTHBLEND, 0 ); + SET_STATIC_VERTEX_SHADER_COMBO( PACKED_INTERPOLATOR, 0 ); + SET_STATIC_VERTEX_SHADER_COMBO( ANIMBLEND_OR_MAXLUMFRAMEBLEND1, bBlendFrames || ( params[MAXLUMFRAMEBLEND1]->GetIntValue() != 0 ) ); + SET_STATIC_VERTEX_SHADER( splinecard_vs20 ); + } + else + { + DECLARE_STATIC_VERTEX_SHADER( spritecard_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( SPRITECARDVERTEXFOG, bFog ); + SET_STATIC_VERTEX_SHADER_COMBO( DUALSEQUENCE, bSecondSequence ); + SET_STATIC_VERTEX_SHADER_COMBO( ADDBASETEXTURE2, bAdditive2ndTexture ); + SET_STATIC_VERTEX_SHADER_COMBO( EXTRACTGREENALPHA, bExtractGreenAlpha ); + SET_STATIC_VERTEX_SHADER_COMBO( DEPTHBLEND, bDepthBlend ); + SET_STATIC_VERTEX_SHADER_COMBO( ANIMBLEND_OR_MAXLUMFRAMEBLEND1, bBlendFrames || ( params[MAXLUMFRAMEBLEND1]->GetIntValue() != 0 ) ); + SET_STATIC_VERTEX_SHADER_COMBO( CROP, bCrop ); + SET_STATIC_VERTEX_SHADER_COMBO( PACKED_INTERPOLATOR, bPackedInterpolator ); + SET_STATIC_VERTEX_SHADER_COMBO( HARDWAREFOGBLEND, !IsX360() && bFog && ( g_pHardwareConfig->GetDXSupportLevel() <= 90 ) ); + SET_STATIC_VERTEX_SHADER_COMBO( PERPARTICLEOUTLINE, bPerParticleOutline ); + SET_STATIC_VERTEX_SHADER( spritecard_vs20 ); + } + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( spritecard_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( ADDBASETEXTURE2, bAdditive2ndTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( ADDSELF, bAddSelf ); + SET_STATIC_PIXEL_SHADER_COMBO( ANIMBLEND, bBlendFrames ); + SET_STATIC_PIXEL_SHADER_COMBO( DUALSEQUENCE, bSecondSequence ); + SET_STATIC_PIXEL_SHADER_COMBO( SEQUENCE_BLEND_MODE, bSecondSequence ? params[SEQUENCE_BLEND_MODE]->GetIntValue() : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( MAXLUMFRAMEBLEND1, params[MAXLUMFRAMEBLEND1]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER_COMBO( MAXLUMFRAMEBLEND2, bSecondSequence? params[MAXLUMFRAMEBLEND1]->GetIntValue() : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( COLORRAMP, bUseRampTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( EXTRACTGREENALPHA, bExtractGreenAlpha ); + SET_STATIC_PIXEL_SHADER_COMBO( DEPTHBLEND, bDepthBlend ); + SET_STATIC_PIXEL_SHADER_COMBO( INVERSEDEPTHBLEND, bInverseDepthBlend ); + SET_STATIC_PIXEL_SHADER_COMBO( SHADER_SRGB_READ, bShaderSrgbRead ); + SET_STATIC_PIXEL_SHADER_COMBO( MOD2X, bMod2X ); + SET_STATIC_PIXEL_SHADER_COMBO( PACKED_INTERPOLATOR, bPackedInterpolator ); + SET_STATIC_PIXEL_SHADER_COMBO( COLOR_LERP_PS, bColorLerpPS ); + SET_STATIC_PIXEL_SHADER_COMBO( DISTANCEALPHA, bDistanceAlpha ); + SET_STATIC_PIXEL_SHADER_COMBO( OUTLINE, bOutLine ); + SET_STATIC_PIXEL_SHADER_COMBO( SOFTEDGES, bSoftEdges ); + SET_STATIC_PIXEL_SHADER( spritecard_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( spritecard_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( ADDBASETEXTURE2, bAdditive2ndTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( DUALSEQUENCE, bSecondSequence ); + SET_STATIC_PIXEL_SHADER_COMBO( ADDSELF, bAddSelf ); + SET_STATIC_PIXEL_SHADER_COMBO( ANIMBLEND, bBlendFrames ); + SET_STATIC_PIXEL_SHADER_COMBO( SEQUENCE_BLEND_MODE, bSecondSequence ? params[SEQUENCE_BLEND_MODE]->GetIntValue() : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( MAXLUMFRAMEBLEND1, params[MAXLUMFRAMEBLEND1]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER_COMBO( MAXLUMFRAMEBLEND2, bSecondSequence? params[MAXLUMFRAMEBLEND1]->GetIntValue() : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( COLORRAMP, bUseRampTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( EXTRACTGREENALPHA, bExtractGreenAlpha ); + SET_STATIC_PIXEL_SHADER_COMBO( INVERSEDEPTHBLEND, bInverseDepthBlend ); + SET_STATIC_PIXEL_SHADER_COMBO( SHADER_SRGB_READ, bShaderSrgbRead ); + SET_STATIC_PIXEL_SHADER_COMBO( MOD2X, bMod2X ); + SET_STATIC_PIXEL_SHADER_COMBO( DEPTHBLEND, bDepthBlend ); + SET_STATIC_PIXEL_SHADER_COMBO( PACKED_INTERPOLATOR, bPackedInterpolator ); + SET_STATIC_PIXEL_SHADER_COMBO( COLOR_LERP_PS, bColorLerpPS ); + SET_STATIC_PIXEL_SHADER_COMBO( DISTANCEALPHA, bDistanceAlpha ); + SET_STATIC_PIXEL_SHADER_COMBO( OUTLINE, bOutLine ); + SET_STATIC_PIXEL_SHADER_COMBO( SOFTEDGES, bSoftEdges ); + SET_STATIC_PIXEL_SHADER( spritecard_ps20 ); + } + + if ( bShadowDepth ) + { + pShaderShadow->EnableColorWrites( false ); + pShaderShadow->EnableAlphaWrites( false ); + pShaderShadow->EnablePolyOffset( SHADER_POLYOFFSET_SHADOW_BIAS ); + } + pShaderShadow->EnableSRGBWrite( true ); + + if( !bExtractGreenAlpha ) + { + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, !bShaderSrgbRead ); + } + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + + if ( bUseRampTexture ) + { + BindTexture( SHADER_SAMPLER1, RAMPTEXTURE, FRAME ); + } + + if ( bDepthBlend ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_FRAME_BUFFER_FULL_DEPTH ); + } + + int nOrientation = params[ORIENTATION]->GetIntValue(); + nOrientation = clamp( nOrientation, 0, 3 ); + + switch ( nOrientation ) + { + case 0: + // We need these only when screen-orienting + LoadModelViewMatrixIntoVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0 ); + LoadProjectionMatrixIntoVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3 ); + break; + + case 2: + // We need this only when doing fixed orientation + SetVertexShaderMatrix3x4( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, ORIENTATIONMATRIX ); + break; + } + + if ( bZoomSeq2 || bFog ) + { + float flZScale=1.0/(params[ZOOMANIMATESEQ2]->GetFloatValue()); + float C0[4]={ 0.5*(1.0+flZScale), flZScale, params[VERTEXFOGAMOUNT]->GetFloatValue(), 0 }; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, C0, + ARRAYSIZE(C0)/4 ); + } + + // set fade constants in vsconsts 8 and 9 + float flMaxDistance = params[MAXDISTANCE]->GetFloatValue(); + float flStartFade = MAX( 1.0, flMaxDistance - params[FARFADEINTERVAL]->GetFloatValue() ); + + float VC0[8]={ params[MINSIZE]->GetFloatValue(), params[MAXSIZE]->GetFloatValue(), + params[STARTFADESIZE]->GetFloatValue(), params[ENDFADESIZE]->GetFloatValue(), + flStartFade, 1.0/(flMaxDistance-flStartFade), + params[ALPHATRAILFADE]->GetFloatValue(), + params[RADIUSTRAILFADE]->GetFloatValue() }; + + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_8, VC0, ARRAYSIZE(VC0)/4 ); + + pShaderAPI->SetDepthFeatheringPixelShaderConstant( 2, params[DEPTHBLENDSCALE]->GetFloatValue() ); + + // Get viewport and render target dimensions and set shader constant to do a 2D mad + int nViewportX, nViewportY, nViewportWidth, nViewportHeight; + pShaderAPI->GetCurrentViewport( nViewportX, nViewportY, nViewportWidth, nViewportHeight ); + + int nRtWidth, nRtHeight; + pShaderAPI->GetCurrentRenderTargetDimensions( nRtWidth, nRtHeight ); + + float vViewportMad[4]; + vViewportMad[0] = ( float )nViewportWidth / ( float )nRtWidth; + vViewportMad[1] = ( float )nViewportHeight / ( float )nRtHeight; + vViewportMad[2] = ( float )nViewportX / ( float )nRtWidth; + vViewportMad[3] = ( float )nViewportY / ( float )nRtHeight; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_10, vViewportMad, 1 ); + + if ( bCrop ) + { + float vCropFactors[4]; + params[CROPFACTOR]->GetVecValue( vCropFactors, 2 ); + vCropFactors[2] = -0.5f * vCropFactors[0] + 0.5f; + vCropFactors[3] = -0.5f * vCropFactors[1] + 0.5f; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_11, vCropFactors, 1 ); + } + + if ( bColorLerpPS ) + { + float vLerpColors[8]; + params[LERPCOLOR1]->GetVecValue( vLerpColors, 3 ); + params[LERPCOLOR2]->GetVecValue( vLerpColors+4, 3 ); + vLerpColors[3] = 1.0f; + vLerpColors[7] = 1.0f; + SetPixelShaderConstantGammaToLinear( 5, vLerpColors, 2 ); + } + + float C0[4]={ params[ADDBASETEXTURE2]->GetFloatValue(), + params[OVERBRIGHTFACTOR]->GetFloatValue(), + params[ADDSELF]->GetFloatValue(), + 0.0f }; + + BOOL bShaderConstants[3] = { bZoomSeq2, bExtractGreenAlpha, bUseInstancing }; + pShaderAPI->SetBooleanVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_BOOL_CONST_0, bShaderConstants, 3 ); + pShaderAPI->SetPixelShaderConstant( 0, C0, ARRAYSIZE(C0)/4 ); + + // Set Mod2xIdentity to be 0.5 if we blend in linear space, or 0.5 Gamma->Linear if we blend in gamma space + float vPsConst1[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vPsConst1[0] = g_pHardwareConfig->UsesSRGBCorrectBlending() ? 0.5f : SrgbGammaToLinear( 0.5f ); + pShaderAPI->SetPixelShaderConstant( 1, vPsConst1, 1 ); + + + // set up distance-coding constants + if ( bDistanceAlpha ) + { + float vDistanceConstants[4 * 3]; // c7, c8,c9 + params[OUTLINECOLOR]->GetVecValue( vDistanceConstants, 3 ); + vDistanceConstants[3] = params[OUTLINEALPHA]->GetFloatValue(); + vDistanceConstants[4] = params[OUTLINESTART0]->GetFloatValue(); + vDistanceConstants[5] = params[OUTLINESTART1]->GetFloatValue(); + vDistanceConstants[6] = params[OUTLINEEND0]->GetFloatValue(); + vDistanceConstants[7] = params[OUTLINEEND1]->GetFloatValue(); + vDistanceConstants[8] = params[EDGESOFTNESSSTART]->GetFloatValue(); + vDistanceConstants[9] = params[EDGESOFTNESSEND]->GetFloatValue(); + vDistanceConstants[10] = 0; + vDistanceConstants[11] = 0; + pShaderAPI->SetPixelShaderConstant( 7, vDistanceConstants, ARRAYSIZE( vDistanceConstants ) / 4 ); + } + + if ( nSplineType ) + { + DECLARE_DYNAMIC_VERTEX_SHADER( splinecard_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( ORIENTATION, nOrientation ); + SET_DYNAMIC_VERTEX_SHADER( splinecard_vs20 ); + } + else + { + DECLARE_DYNAMIC_VERTEX_SHADER( spritecard_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( ORIENTATION, nOrientation ); + SET_DYNAMIC_VERTEX_SHADER( spritecard_vs20 ); + } + + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( spritecard_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( spritecard_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( spritecard_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( spritecard_ps20 ); + } + } + Draw( ); + } +END_SHADER diff --git a/materialsystem/stdshaders/spritecard_ps2x.fxc b/materialsystem/stdshaders/spritecard_ps2x.fxc new file mode 100644 index 00000000..0c4be443 --- /dev/null +++ b/materialsystem/stdshaders/spritecard_ps2x.fxc @@ -0,0 +1,295 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "DUALSEQUENCE" "0..1" +// STATIC: "SEQUENCE_BLEND_MODE" "0..2" +// STATIC: "ADDBASETEXTURE2" "0..1" +// STATIC: "MAXLUMFRAMEBLEND1" "0..1" +// STATIC: "MAXLUMFRAMEBLEND2" "0..1" +// STATIC: "EXTRACTGREENALPHA" "0..1" +// STATIC: "COLORRAMP" "0..1" +// STATIC: "ANIMBLEND" "0..1" +// STATIC: "ADDSELF" "0..1" +// STATIC: "MOD2X" "0..1" +// STATIC: "DEPTHBLEND" "0..1" [XBOX] +// STATIC: "DEPTHBLEND" "0..0" [PC] +// STATIC: "INVERSEDEPTHBLEND" "0..1" [XBOX] +// STATIC: "INVERSEDEPTHBLEND" "0..0" [PC] +// STATIC: "SHADER_SRGB_READ" "0..1" [XBOX] +// STATIC: "SHADER_SRGB_READ" "0..0" [PC] +// STATIC: "COLOR_LERP_PS" "0..1" +// STATIC: "PACKED_INTERPOLATOR" "0..1" +// STATIC: "DISTANCEALPHA" "0..1" +// STATIC: "SOFTEDGES" "0..1" +// STATIC: "OUTLINE" "0..1" + + +// SKIP: ( $DISTANCEALPHA == 0 ) && ( $SOFTEDGES || $OUTLINE ) +// SKIP: $DISTANCEALPHA && $DUALSEQUENCE +// SKIP: $DISTANCEALPHA && ( $MAXLUMFRAMEBLEND2 || $MAXLUMFRAMEBLEND1 ) +// SKIP: ( $DUALSEQUENCE == 0 ) && ( $SEQUENCE_BLEND_MODE != 0 ) +// SKIP: $INVERSEDEPTHBLEND && !$DEPTHBLEND [XBOX] + +// These are mutually exclusive because PACKED_INTERPOLATOR only fetches a single texture tile +// SKIP: $PACKED_INTERPOLATOR && ( $ANIMBLEND || $MAXLUMFRAMEBLEND1 || $EXTRACTGREENALPHA || $DUALSEQUENCE ) + +#define COMBINE_MODE_AVERAGE 0 +#define COMBINE_MODE_USE_FIRST_AS_ALPHA_MASK_ON_SECOND 1 +#define COMBINE_MODE_USE_FIRST_OVER_SECOND 2 + +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_fxc.h" + +float4 g_Parameters : register( c0 ); +#define fAdditiveBlendWeight g_Parameters.x +#define fOverbrightFactor g_Parameters.y +#define fAdditiveSelfBlendWeight g_Parameters.z + +float g_flMod2xIdentity : register( c1 ); +float4 g_DepthFeatheringConstants : register( c2 ); +float4 g_FogParams : register( c3 ); +float3 g_EyePos : register( c4 ); +float3 g_vColor0 : register( c5 ); +float3 g_vColor1 : register( c6 ); + +// VS_OUTPUT in a common file. +#define PIXELSHADER +#include "common_spritecard_fxc.h" + +sampler BaseTextureSampler : register( s0 ); +sampler ColorRampSampler : register( s1 ); +sampler DepthSampler : register( s2 ); + +#if DISTANCEALPHA == 0 +#define EDGESOFTNESS_START 0.5 +#define EDGESOFTNESS_END 0.425 +#define OUTLINECOLOR float4( 0, 1, 0, 1 ) +#define OUTLINESTART0 0.2 +#define OUTLINESTART1 0.3 +#define OUTLINEEND0 0.49 +#define OUTLINEEND1 0.6 +#else +float4 g_vecOutlineColor : register( c7 ); +#define OUTLINECOLOR ( g_vecOutlineColor * i.vecOutlineTint ) +float4 g_vecOutlineControl : register( c8 ); +#define OUTLINESTART0 ( g_vecOutlineControl.x ) +#define OUTLINESTART1 ( g_vecOutlineControl.y ) +#define OUTLINEEND0 ( g_vecOutlineControl.z ) +#define OUTLINEEND1 ( g_vecOutlineControl.w ) +float4 g_vecEdgeControl : register( c9 ); +#define EDGESOFTNESS_START ( g_vecEdgeControl.x ) +#define EDGESOFTNESS_END ( g_vecEdgeControl.y ) +#endif + + +float4 main( PS_INPUT i ) : COLOR +{ + // Sample frames from textures + float4 baseTex0 = tex2Dsrgb( BaseTextureSampler, i.texCoord0_1.xy ); + float4 baseTex1; + + float4 result = baseTex0; + + float4 vVertexColor; + #if ( PACKED_INTERPOLATOR ) + { + vVertexColor.rgba = i.texCoord0_1.zzzw; + } + #else + { + vVertexColor.rgba = i.argbcolor.rgba; + baseTex1 = tex2Dsrgb( BaseTextureSampler, i.texCoord0_1.wz ); + } + #endif + + #if ( COLOR_LERP_PS ) + { + vVertexColor.rgb = lerp( g_vColor0.rgb, g_vColor1.rgb, saturate( vVertexColor.r ) ); + } + #endif + + // Blend by default (may override with bMaxLumFrameBlend1 or bExtractGreenAlpha) + #if ( ANIMBLEND ) + result = lerp( result, baseTex1, i.blendfactor0.x ); + #endif + + #if ( MAXLUMFRAMEBLEND1 ) + { + // Blend between animation frames based upon max luminance + float lum0 = dot( float3(.3, .59, .11), baseTex0.rgb * (1-i.blendfactor0.x)); + float lum1 = dot( float3(.3, .59, .11), baseTex1.rgb * i.blendfactor0.x); + + if ( lum0 > lum1 ) + result = baseTex0; + else + result = baseTex1; + } + #elif( EXTRACTGREENALPHA ) + { + // Weight Green/Alphas from the two frames for a scalar result + result = dot( baseTex0, i.blendfactor0 ) + dot( baseTex1, i.blendfactor1 ); + + } + #endif + + if ( DISTANCEALPHA ) + { + float flOrigAlpha = result.a; + if ( SOFTEDGES ) + { + result.a = smoothstep( EDGESOFTNESS_END, EDGESOFTNESS_START, result.a ); + } + else + { + if ( result.a < 0.5f ) + result = 0; + } + if ( OUTLINE ) + { + result.rgb *= vVertexColor; // multiply by vertex color before glow. + if ( ( flOrigAlpha >= OUTLINESTART0 ) && ( flOrigAlpha <= OUTLINEEND1 ) ) + { + float oFactor = 1.0f; + if ( flOrigAlpha <= OUTLINESTART1 ) + { + oFactor = smoothstep( OUTLINESTART0, OUTLINESTART1, flOrigAlpha ); + } + else + { + oFactor = smoothstep( OUTLINEEND1, OUTLINEEND0, flOrigAlpha ); + } + result = lerp( result, OUTLINECOLOR, oFactor ); + } + } + } + + #if ( DUALSEQUENCE ) + { + baseTex0 = tex2Dsrgb( BaseTextureSampler, i.vSeq2TexCoord0_1.xy ); + baseTex1 = tex2Dsrgb( BaseTextureSampler, i.vSeq2TexCoord0_1.wz ); + + // Blend by default (may override with bMaxLumFrameBlend2) + float4 rgb2 = lerp( baseTex0, baseTex1, i.blendfactor0.z ); + + #if ( MAXLUMFRAMEBLEND2 ) + { + // blend between animation frames based upon max luminance + float tlum0 = dot( float3(.3, .59, .11), baseTex0.rgb * (1-i.blendfactor0.x)); + float tlum1 = dot( float3(.3, .59, .11), baseTex1.rgb * i.blendfactor0.x); + + if ( tlum0 > tlum1 ) + rgb2 = baseTex0; + else + rgb2 = baseTex1; + } + #endif + + #if ( SEQUENCE_BLEND_MODE == COMBINE_MODE_AVERAGE ) + { + result = 0.5 * ( result + rgb2 ); + } + #elif ( SEQUENCE_BLEND_MODE == COMBINE_MODE_USE_FIRST_AS_ALPHA_MASK_ON_SECOND ) + { + result.rgb = rgb2.rgb; + } + #elif ( SEQUENCE_BLEND_MODE == COMBINE_MODE_USE_FIRST_OVER_SECOND ) + { + result.rgb = lerp( result.rgb, rgb2.rgb, rgb2.a ); + } + #endif + } + #endif + + // Optional color ramp + #if ( COLORRAMP ) + { + result.rgb = tex2Dsrgb( ColorRampSampler, float2( result.r, result.g ) ); + } + #endif + + // Overbright + result.rgb *= fOverbrightFactor; + //Soft Particles FTW + #if (DEPTHBLEND == 1) + #if defined( REVERSE_DEPTH_ON_X360 ) + float fDepthBlend = DepthFeathering( DepthSampler, i.vScreenPos_ReverseZ.xy / i.vScreenPos_ReverseZ.w, i.vScreenPos_ReverseZ.z, i.vScreenPos_ReverseZ.w, g_DepthFeatheringConstants ); + #else + float fDepthBlend = DepthFeathering( DepthSampler, i.vScreenPos.xy / i.vScreenPos.w, i.vScreenPos.z, i.vScreenPos.w, g_DepthFeatheringConstants ); + #endif + #if (INVERSEDEPTHBLEND == 1) + fDepthBlend = 1.0f - fDepthBlend; + #endif + + vVertexColor.a *= fDepthBlend; + #endif + // Premultiply the alpha for a ONE:INVALPHA blend + #if ( ADDBASETEXTURE2 ) + { + result.a *= vVertexColor.a; + + // In this case, we don't really want to pre-multiply by alpha + #if ( !COLORRAMP ) + { + result.rgb *= result.a; + } + #endif + + #if ( EXTRACTGREENALPHA ) + { + result.rgb += fAdditiveBlendWeight * vVertexColor.a * result.rgb; + } + #else + { + result.rgb += fOverbrightFactor * fAdditiveBlendWeight * vVertexColor.a * tex2Dsrgb( BaseTextureSampler, i.texCoord2 ); + } + #endif + + result.rgb *= vVertexColor.rgb; + } + #else + { + #if ADDSELF + { + result.a *= vVertexColor.a; + result.rgb *= result.a; + result.rgb += fAdditiveSelfBlendWeight * result.rgb; + result.rgb *= vVertexColor.rgb; + } + #else + { + #if ( MOD2X ) + { + result.rgb = lerp( ( float3 )g_flMod2xIdentity, result.rgb, vVertexColor.rgb ); + result.a *= vVertexColor.a; + } + #else + { + if ( ! OUTLINE ) + { + result *= vVertexColor; // if outlined, we've already done this. don't want to mul glow by particle color. + } + else + { + result.a *= vVertexColor.a; + } + + } + #endif + } + #endif + } + #endif + #if ( MOD2X ) + { + // Blend towards a unity multiply as alpha gets closer to zero + result.rgb = lerp( ( float3 )g_flMod2xIdentity, result.rgb, result.a ); + + // Don't tonemap scale since we are multiplying by what is already in the framebuffer. + return FinalOutput( result, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); + } + #else + { + return FinalOutput( result, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_LINEAR ); + } + #endif +} + diff --git a/materialsystem/stdshaders/spritecard_vsxx.fxc b/materialsystem/stdshaders/spritecard_vsxx.fxc new file mode 100644 index 00000000..94c03b6c --- /dev/null +++ b/materialsystem/stdshaders/spritecard_vsxx.fxc @@ -0,0 +1,464 @@ +// STATIC: "DUALSEQUENCE" "0..1" +// STATIC: "ADDBASETEXTURE2" "0..1" +// STATIC: "EXTRACTGREENALPHA" "0..1" +// STATIC: "DEPTHBLEND" "0..1" [XBOX] +// STATIC: "DEPTHBLEND" "0..0" [PC] +// STATIC: "ANIMBLEND_OR_MAXLUMFRAMEBLEND1" "0..1" +// STATIC: "CROP" "0..1" +// STATIC: "PACKED_INTERPOLATOR" "0..1" +// STATIC: "SPRITECARDVERTEXFOG" "0..1" + +// STATIC: "HARDWAREFOGBLEND" "0..0" [XBOX] +// STATIC: "HARDWAREFOGBLEND" "0..1" [PC] [vs20] +// STATIC: "HARDWAREFOGBLEND" "0..0" [PC] [vs30] + +// STATIC: "PERPARTICLEOUTLINE" "0..1" +// DYNAMIC: "ORIENTATION" "0..3" + +// If we aren't doing any sort of fog, then assume that HARDWAREFOGBLEND is forced to zero. + +// SKIP: $PERPARTICLEOUTLINE && ( $ORIENTATION == 3 ) +// SKIP: $DUALSEQUENCE && ( $PERPARTICLEOUTLINE || ( $ORIENTATION == 3 ) ) +// SKIP: $HARDWAREFOGBLEND && !SPRITECARDVERTEXFOG + +#include "common_vs_fxc.h" + +// Don't want to have extra combos, so define these two to be the same base on a single combo. Bilch. +#define ANIMBLEND ANIMBLEND_OR_MAXLUMFRAMEBLEND1 +#define MAXLUMFRAMEBLEND1 ANIMBLEND_OR_MAXLUMFRAMEBLEND1 + +// VS_OUTPUT in a common file. +#include "common_spritecard_fxc.h" + +const float4x3 cModelView : register(SHADER_SPECIFIC_CONST_0); +const float4x4 cProj : register(SHADER_SPECIFIC_CONST_3); + +#if !defined( SHADER_MODEL_VS_1_1 ) +const float4 ScaleParms : register(SHADER_SPECIFIC_CONST_7); +#define OLDFRM_SCALE_START (ScaleParms.x) +#define OLDFRM_SCALE_END (ScaleParms.y) +#define FOG_SCALE_FACTOR (ScaleParms.z) +#endif + +const float4 SizeParms : register(SHADER_SPECIFIC_CONST_8); +const float4 SizeParms2 : register(SHADER_SPECIFIC_CONST_9); + +const float4 g_vViewportMad : register(SHADER_SPECIFIC_CONST_10); +const float4 g_vCropFactor : register(SHADER_SPECIFIC_CONST_11); + +#if !defined( SHADER_MODEL_VS_1_1 ) +const bool g_bZoomAnimateSeq2 : register( SHADER_SPECIFIC_BOOL_CONST_0 ); +const bool g_bExtractGreenAlpha : register( SHADER_SPECIFIC_BOOL_CONST_1 ); +const bool g_bUseInstancing : register( SHADER_SPECIFIC_BOOL_CONST_2 ); +#endif + +#define MINIMUM_SIZE_FACTOR (SizeParms.x) +#define MAXIMUM_SIZE_FACTOR (SizeParms.y) + +#define START_FADE_SIZE_FACTOR (SizeParms.z) +#define END_FADE_SIZE_FACTOR (SizeParms.w) + +// alpha fade w/ distance +#define START_FAR_FADE ( SizeParms2.x ) +#define FAR_FADE_FACTOR ( SizeParms2.y ) // alpha = 1-min(1,max(0, (dist-start_fade)*factor)) + +// Define stuff for instancing on 360 +#if ( defined( _X360 ) && defined( SHADER_MODEL_VS_2_0 ) ) +#define CONST_PC +#define VERTEX_INDEX_PARAM_360 ,int Index:INDEX +#define DO_INSTANCING 1 +#else +#define CONST_PC const +#define VERTEX_INDEX_PARAM_360 +#endif + + +struct VS_INPUT +{ + // This is all of the stuff that we ever use. + float4 vTint : COLOR; + float4 vPos : POSITION; + float4 vTexCoord0 : TEXCOORD0; + float4 vTexCoord1 : TEXCOORD1; + float4 vParms : TEXCOORD2; // frame blend, rot, radius, yaw + // FIXME: remove this vertex element for (USE_INSTANCING == 1), need to shuffle the following elements down + float2 vCornerID : TEXCOORD3; // 0,0 1,0 1,1 0,1 + float4 vTexCoord2 : TEXCOORD4; +#if DUALSEQUENCE + float4 vSeq2TexCoord0 : TEXCOORD5; + float4 vSeq2TexCoord1 : TEXCOORD6; + float4 vParms1 : TEXCOORD7; // second frame blend, ?,?,? +#endif +#if PERPARTICLEOUTLINE + float4 vecOutlineTint : TEXCOORD5; +#endif +#if ( ORIENTATION == 3 ) // orient to normal + float4 vecNormal : TEXCOORD5; +#endif +}; + +#define BLENDFACTOR v.vParms.x +#define ROTATION v.vParms.y +#define RADIUS v.vParms.z +#define YAW (v.vParms.w) + +#define ONE_OVER_255 0.00392156863 + +#if !defined( SHADER_MODEL_VS_1_1 ) +float getlerpscaled( float l_in, float s0, float s1, float ts ) +{ + l_in = 2.0*(l_in-.5); + l_in *= lerp(s0,s1,ts); + return 0.5+0.5*l_in; +} + +float getlerpscale_for_old_frame( float l_in, float ts ) +{ + return getlerpscaled( l_in, OLDFRM_SCALE_START, OLDFRM_SCALE_END, ts); +} + +float getlerpscale_for_new_frame( float l_in, float ts ) +{ + return getlerpscaled( l_in, 1.0, OLDFRM_SCALE_START, ts ); +} +#endif + +#ifdef DO_INSTANCING +void InstancedVertexRead( inout VS_INPUT v, int index ) +{ + // Duplicate each VB vertex 4 times (and generate vCornerID - the only thing that varies per-corner) + float4 vTint; + float4 vPos; + float4 vTexCoord0; + float4 vTexCoord1; + float4 vParms; + float4 vTexCoord2; + float4 vSeq_TexCoord0; // NOTE: April XDK compiler barfs on var names which have a number in the middle! (i.e. vSeq2TexCoord0) + float4 vSeq_TexCoord1; + float4 vParms1; + float4 vecOutlineTint; + float4 vecNormal; + + int spriteIndex = index / 4; + int cornerIndex = index - 4*spriteIndex; + asm + { + // NOTE: using a computed index disables the post-transform cache, so there are VS perf ramifications + vfetch vTint, spriteIndex, color0; + vfetch vPos, spriteIndex, position0; + vfetch vTexCoord0, spriteIndex, texcoord0; + vfetch vTexCoord1, spriteIndex, texcoord1; + vfetch vParms, spriteIndex, texcoord2; + vfetch vTexCoord2, spriteIndex, texcoord4; +#if DUALSEQUENCE + vfetch vSeq_TexCoord0, spriteIndex, texcoord5; + vfetch vSeq_TexCoord1, spriteIndex, texcoord6; + vfetch vParms1, spriteIndex, texcoord7; +#endif +#if PERPARTICLEOUTLINE + vfetch vecOutlineTint, spriteIndex, texcoord5; +#endif +#if ( ORIENTATION == 3 ) // normal-aligned + vfetch vecNormal, spriteIndex, texcoord5; +#endif + }; + + v.vTint = vTint; + v.vPos = vPos; + v.vTexCoord0 = vTexCoord0; + v.vTexCoord1 = vTexCoord1; + v.vParms = vParms; +#if ADDBASETEXTURE2 + v.vTexCoord2 = vTexCoord2; +#endif +#if DUALSEQUENCE + v.vSeq2TexCoord0 = vSeq_TexCoord0; + v.vSeq2TexCoord1 = vSeq_TexCoord1; + v.vParms1 = vParms1; +#endif +#if PERPARTICLEOUTLINE + v.vecOutlineTint = vecOutlineTint; +#endif +#if ORIENTATION == 3 + v.vecNormal = vecNormal; +#endif + + + // Compute vCornerID - order is: (0,0) (1,0) (1,1) (0,1) + // float2 IDs[4] = { {0,0}, {1,0}, {1,1}, {0,1} }; + // v.vCornerID.xy = IDs[ cornerIndex ]; + // This compiles to 2 ops on 360 (MADDs with abs/sat register read/write modifiers): + v.vCornerID.xy = float2( 1.5f, 0.0f ) + cornerIndex*float2( -1.0f, 1.0f ); + v.vCornerID.xy = saturate( float2(1.5f, -3.0f) + float2( -1.0f, 2.0f )*abs( v.vCornerID.xy ) ); +} +#endif + +VS_OUTPUT main( CONST_PC VS_INPUT v + VERTEX_INDEX_PARAM_360 ) +{ + VS_OUTPUT o; + +#ifdef DO_INSTANCING + if ( g_bUseInstancing ) + { + InstancedVertexRead( v, Index ); + } +#endif + +#if ( ! DUALSEQUENCE ) +#if PERPARTICLEOUTLINE + o.vecOutlineTint = GammaToLinear( v.vecOutlineTint ); +#else + o.vecOutlineTint = 1; +#endif +#endif + +#if SHADER_MODEL_VS_1_1 + float4 tint = v.vTint; +#else + float4 tint = GammaToLinear( v.vTint ); +#endif + + float2 sc_yaw; + sincos( YAW, sc_yaw.y, sc_yaw.x ); + + float2 sc; + sincos( ROTATION, sc.y, sc.x ); + + float2 ix = 2 * v.vCornerID.xy - 1; + + #if ( CROP ) + { + ix *= g_vCropFactor.xy; + } + #endif + + float x1 = dot( ix, sc ); + float y1 = sc.x * ix.y - sc.y * ix.x; + + float4 projPos; + float3 worldPos; + worldPos = mul4x3( v.vPos, cModel[0] ); + + float rad = RADIUS; + float3 v2p = ( worldPos - cEyePos ); + float l = length(v2p); + rad=max(rad, MINIMUM_SIZE_FACTOR * l); + // now, perform fade out +#ifndef SHADER_MODEL_VS_1_1 + if ( rad > START_FADE_SIZE_FACTOR * l ) + { + if ( rad > END_FADE_SIZE_FACTOR *l ) + { + tint = 0; + rad = 0; // cull so we emit 0-sized sprite + } + else + { + tint *= 1-(rad-START_FADE_SIZE_FACTOR*l)/(END_FADE_SIZE_FACTOR*l-START_FADE_SIZE_FACTOR*l); + } + } +#endif + + +#ifndef SHADER_MODEL_VS_1_1 + // perform far fade + float tscale = 1-min(1, max(0, (l-START_FAR_FADE)*FAR_FADE_FACTOR) ); + tint *= tscale; + + if ( tscale <= 0 ) + rad = 0; // cull so we emit 0-sized sprite +#endif + + if ( SPRITECARDVERTEXFOG ) + { + // fade tint.a based upon fog amount + float ffactor = 0.0f; + #if ( HARDWAREFOGBLEND ) + { + // On ps20 hardware, we use fixed-function fog blending, which has a fog factor of 1 for no fog, and 0 for fully fogged. + // Note that the shader constants for fog params are different in both states of HARDWAREFOGBLEND. + ffactor = CalcRangeFogFactorFixedFunction( worldPos, cEyePos, cRadialFogMaxDensity, cFogEndOverFogRange, cOOFogRange ); + } + #else + { + // On ps2b and up, we blend fog in the pixel shader in such a way that we have a fog factor of 0 for no fog, and 1 for fully fogged. + // We want to multiply by 1 where there is no fog, so invert. + // Note that the shader constants for fog params are different in both states of HARDWAREFOGBLEND. + ffactor = CalcRangeFogFactorNonFixedFunction( worldPos, cEyePos, cRadialFogMaxDensity, cFogEndOverFogRange, cOOFogRange ); + ffactor = 1.0f - ffactor; // map from [0,1]->[1,0] Want 0 to be fully fogged instead of 1. + } + #endif + ffactor = lerp( 1, ffactor, FOG_SCALE_FACTOR ); + tint.a *= ffactor; + } + + if ( tint.a < ONE_OVER_255 ) + { + // save fillrate by transforming completely transparent particles to a point + rad = 0; + } + + rad = min( rad, MAXIMUM_SIZE_FACTOR * l ); + +#if ORIENTATION == 0 + // Screen-aligned case + float3 viewPos; + viewPos = mul4x3( v.vPos, cModelView ); + + float3 disp = float3( -x1, y1, 0 ); + + float tmpx = disp.x * sc_yaw.x + disp.z * sc_yaw.y; + disp.z = disp.z * sc_yaw.x - disp.x * sc_yaw.y; + disp.x = tmpx; + + viewPos.xyz += disp * rad; + + projPos = mul( float4( viewPos, 1.0f ), cProj ); +#endif + +#if ( ( ORIENTATION == 1 ) || ( ORIENTATION == 3 ) ) + // Z-aligned case + if (l > rad/2) + { + float3 up = float3(0,0,1); + float3 right = normalize(cross(up, v2p)); + #if ( ORIENTATION == 3 ) + { + float3 vNormal = v.vecNormal.xyz; + float3 vTrialVector = float3( 0, 0, 1 ); + if ( abs( vNormal.z ) > 0.9 ) + { + vTrialVector = float3( 1, 0, 0 ); + } + up = normalize( cross( vNormal, vTrialVector ) ); + right = cross( vNormal, up ); + } + #else // no yaw support for normal aligned + float tmpx = right.x * sc_yaw.x + right.y * sc_yaw.y; + right.y = right.y * sc_yaw.x - right.x * sc_yaw.y; + right.x = tmpx; + #endif + + worldPos += ( x1 * rad ) * right; + worldPos += ( y1 * rad ) * up; + +#ifndef SHADER_MODEL_VS_1_1 + if (l < rad*2 ) + { + tint *= smoothstep(rad/2,rad,l); + } +#endif + + } + projPos = mul( float4(worldPos, 1.0f), cViewProj ); +#endif + +#if ORIENTATION == 2 + // aligned with z plane case - easy + // Need to rotate it into the space of the control point though + // We're using cModelView to store that transformation since it's + // only used as cModelView in ORIENTATION mode 0. + float3 vOffset; + vOffset = mul3x3( float3( y1, x1, 0 ), cModelView ); + + float3 wpos = v.vPos + RADIUS * vOffset; + projPos = mul( float4(wpos, 1.0f), cModelViewProj ); +#endif + +#if HAS_BLENDFACTOR0 + o.blendfactor0 = float4( v.vParms.x, 0, 0, 0 ); +#endif + o.projPos = projPos; + + #if ( CROP ) + { + o.texCoord0_1.xy = lerp( v.vTexCoord0.zw, v.vTexCoord0.xy, v.vCornerID.xy * g_vCropFactor.xy + g_vCropFactor.zw ); + o.texCoord0_1.wz = lerp( v.vTexCoord1.zw, v.vTexCoord1.xy, v.vCornerID.xy * g_vCropFactor.xy + g_vCropFactor.zw ); + } + #else + { + o.texCoord0_1.xy = lerp( v.vTexCoord0.zw, v.vTexCoord0.xy, v.vCornerID.xy ); + o.texCoord0_1.wz = lerp( v.vTexCoord1.zw, v.vTexCoord1.xy, v.vCornerID.xy ); + } + #endif + +#if ADDBASETEXTURE2 + o.texCoord2.xy = lerp( v.vTexCoord2.zw, v.vTexCoord2.xy, v.vCornerID.xy ); +#endif + +#if DUALSEQUENCE + float2 lerpold = v.vCornerID.xy; + float2 lerpnew = v.vCornerID.xy; + + if ( g_bZoomAnimateSeq2 ) + { + lerpold.x = getlerpscale_for_old_frame( v.vCornerID.x, v.vParms1.x ); + lerpold.y = getlerpscale_for_old_frame( v.vCornerID.y, v.vParms1.x ); + lerpnew.x = getlerpscale_for_new_frame( v.vCornerID.x, v.vParms1.x ); + lerpnew.y = getlerpscale_for_new_frame( v.vCornerID.y, v.vParms1.x ); + } + + o.vSeq2TexCoord0_1.xy = lerp( v.vSeq2TexCoord0.zw, v.vSeq2TexCoord0.xy, lerpold.xy ); + o.vSeq2TexCoord0_1.wz = lerp( v.vSeq2TexCoord1.zw, v.vSeq2TexCoord1.xy, lerpnew.xy ); + + o.blendfactor0.z = v.vParms1.x; +#endif + + #if ( EXTRACTGREENALPHA ) + { + o.blendfactor1 = float4( 0.0f, 0.0f, 0.0f, 0.0f ); + // Input range Output range + if ( v.vParms.x < 0.25f ) // 0.0 .. 0.25 + { + o.blendfactor0.a = v.vParms.x * 2 + 0.5f; // 0.5 .. 1.0 + o.blendfactor0.g = 1 - o.blendfactor0.a; // 0.5 .. 0.0 + } + else if ( v.vParms.x < 0.75f ) // 0.25 .. 0.75 + { + o.blendfactor1.g = v.vParms.x * 2 - 0.5f; // 0.0 .. 1.0 + o.blendfactor0.a = 1 - o.blendfactor1.g; // 1.0 .. 0.0 + } + else // 0.75 .. 1.0 + { + o.blendfactor1.a = v.vParms.x * 2 - 1.5f; // 0.0 .. 0.5 + o.blendfactor1.g = 1 - o.blendfactor1.a; // 1.0 .. 0.5 + } + } + #endif + + // Map projected position to the refraction texture + float2 vScreenPos; + vScreenPos.x = projPos.x; + vScreenPos.y = -projPos.y; // invert Y + vScreenPos = (vScreenPos + projPos.w) * 0.5f; + + // Adjust for current viewport + vScreenPos.xy = ( ( ( vScreenPos.xy / projPos.w ) * g_vViewportMad.xy ) + g_vViewportMad.zw ) * projPos.w; + + #if DEPTHBLEND + #if defined( _X360 ) + o.vScreenPos_ReverseZ = float4(vScreenPos.x, vScreenPos.y, projPos.w - projPos.z, projPos.w ); + #else + o.vScreenPos = float4(vScreenPos.x, vScreenPos.y, projPos.z, projPos.w ); + #endif + #endif + + #if ( PACKED_INTERPOLATOR == 1 ) + { + o.texCoord0_1.zw = tint.ra; // use red to lerp between two colors in pixel shaders, alpha to modulate opacity + } + #else + { + o.argbcolor = tint; + } + #endif + + #if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + { + o.fog = 1.0f; + } + #endif + + return o; +} diff --git a/materialsystem/stdshaders/stdshader_dx10.txt b/materialsystem/stdshaders/stdshader_dx10.txt new file mode 100644 index 00000000..8ad1b49a --- /dev/null +++ b/materialsystem/stdshaders/stdshader_dx10.txt @@ -0,0 +1 @@ +// vs 4.0 ps 4.0 shaders collection diff --git a/materialsystem/stdshaders/stdshader_dx9_20b.txt b/materialsystem/stdshaders/stdshader_dx9_20b.txt new file mode 100644 index 00000000..05a35b0b --- /dev/null +++ b/materialsystem/stdshaders/stdshader_dx9_20b.txt @@ -0,0 +1,273 @@ +// +// Standard shaders collection +// +// These shaders are compiled as the following shader models: +// _ps11.vcs +// _ps14.vcs +// _ps20.vcs +// _ps20b.vcs +// _vs11.vcs +// _vs20.vcs +// +// These shaders use the old DirectX compiler. +// + + +aftershock_ps2x.fxc +aftershock_vs20.fxc + +Bloom_ps2x.fxc + +bloomadd_ps2x.fxc + +blurentity_ps2x.fxc + +BlurFilter_ps2x.fxc +BlurFilter_vs20.fxc + +blurgaussian_3x3_ps2x.fxc + +bufferclearobeystencil_ps2x.fxc +bufferclearobeystencil_vs20.fxc + +cable_ps2x.fxc +cable_vs20.fxc + +clearalpha_ps2x.fxc + +cloak_blended_pass_ps2x.fxc +cloak_blended_pass_vs20.fxc + +cloak_ps2x.fxc +cloak_vs20.fxc + +colorcorrection_ps2x.fxc + +compositedeferredshadow_ps2x.fxc + +constant_color_ps2x.fxc + +copy_fp_rt_ps2x.fxc + +debugdrawdepth_ps2x.fxc +debugdrawdepth_vs20.fxc + +debugdrawenvmapmask_ps2x.fxc +debugdrawenvmapmask_vs20.fxc + +debugluxel_vs20.fxc +debugluxel_ps2x.fxc + +debugmrttexture_ps2x.fxc +debugmrttexture_vs20.fxc + +debugtangentspace_vs20.fxc + +decalmodulate_vs20.fxc +decalmodulate_ps2x.fxc + +depth_of_field_ps20b.fxc +depth_of_field_vs20.fxc + +depthwrite_ps2x.fxc +depthwrite_vs20.fxc + +depthtodestalpha_vs20.fxc +depthtodestalpha_ps20b.fxc + +Downsample_nohdr_ps2x.fxc +Downsample_ps2x.fxc +Downsample_vs20.fxc + +downsampledepth_extractnormal_ps2x.fxc + +emissive_scroll_blended_pass_ps2x.fxc +emissive_scroll_blended_pass_vs20.fxc + +Engine_Post_ps2x.fxc + +eye_refract_ps2x.fxc +eye_refract_vs20.fxc + +eyes_ps2x.fxc +eyes_vs20.fxc + +eyes_flashlight_ps2x.fxc +eyes_flashlight_vs20.fxc + +eyeglint_vs20.fxc +eyeglint_ps2x.fxc + +fade_blur_ps2x.fxc + +fillrate_ps2x.fxc +fillrate_vs20.fxc + +filmgrain_vs20.fxc +filmgrain_ps20.fxc +filmdust_ps20.fxc + +flashlight_ps2x.fxc + +flesh_interior_blended_pass_ps2x.fxc +flesh_interior_blended_pass_vs20.fxc + +floatcombine_autoexpose_ps2x.fxc +floatcombine_ps2x.fxc + +floattoscreen_notonemap_ps2x.fxc +floattoscreen_ps2x.fxc +floattoscreen_vanilla_ps2x.fxc + +gamecontrols_ps20.fxc +gamecontrols_vs20.fxc + +haloadd_ps2x.fxc + +HDRCombineTo16Bit_ps2x.fxc +HDRCombineTo16Bit_vs20.fxc + +HDRSelectRange_ps2x.fxc +HDRSelectRange_vs20.fxc + +hsl_filmgrain_pass1_ps2x.fxc +hsl_filmgrain_pass2_ps2x.fxc + +hsv_ps2x.fxc + +lightmappedgeneric_decal_ps2x.fxc +lightmappedgeneric_decal_vs20.fxc +lightmappedgeneric_flashlight_vs20.fxc +lightmappedgeneric_ps2x.fxc +lightmappedgeneric_vs20.fxc + +lightmappedpaint_ps2x.fxc + +lightmappedreflective_ps2x.fxc +lightmappedreflective_vs20.fxc + +lpreview_output_ps2x.fxc +lpreview1_ps2x.fxc +lpreview1_vs20.fxc + +luminance_compare_ps2x.fxc + +modulate_ps2x.fxc + +monitorscreen_ps2x.fxc + +motion_blur_vs20.fxc +motion_blur_ps2x.fxc + +multiblend_ps2x.fxc +multiblend_vs20.fxc + +object_motion_blur_vs20.fxc +object_motion_blur_ps2x.fxc + +particlesphere_ps2x.fxc +particlesphere_vs20.fxc + +projected_ps2x.fxc +projected_vs20.fxc + +prototype_ps20b.fxc +prototype_vs20.fxc + +Refract_ps2x.fxc +Refract_vs20.fxc + +rendertargetblit_ps2x.fxc +rendertargetblit_vs20.fxc + +sample4x4_blend_ps2x.fxc +sample4x4_ps2x.fxc +sample4x4delog_ps2x.fxc +sample4x4log_ps2x.fxc +sample4x4maxmin_ps2x.fxc + +screenspaceeffect_vs20.fxc + +shadow_ps2x.fxc +shadow_vs20.fxc + +shadowbuildtexture_ps2x.fxc + +ShadowModel.psh +ShadowModel.vsh +ShatteredGlass_ps2x.fxc +ShatteredGlass_vs20.fxc + +DebugTextureView_vs20.fxc +DebugTextureView_ps2x.fxc + +showz_ps2x.fxc +showz_vs11.fxc + +phong_ps20b.fxc +phong_vs20.fxc + +sky_ps2x.fxc +sky_vs20.fxc +sky_hdr_compressed_ps2x.fxc +sky_hdr_compressed_rgbs_ps2x.fxc + +splinecard_vsxx.fxc + +splinerope_vsxx.fxc +splinerope_ps2x.fxc + +sprite_ps2x.fxc +sprite_vs20.fxc +spritecard_ps2x.fxc +spritecard_vsxx.fxc + +teeth_ps2x.fxc +teeth_vs20.fxc +teeth_bump_ps2x.fxc +teeth_bump_vs20.fxc +teeth_flashlight_ps2x.fxc +teeth_flashlight_vs20.fxc + +treeleaf_ps2x.fxc +treeleaf_vs20.fxc + +unlitgeneric_notexture_ps2x.fxc +unlitgeneric_ps2x.fxc +unlitgeneric_vs20.fxc + +unlittwotexture_ps2x.fxc +unlittwotexture_vs20.fxc + +vertexlitgeneric_flashlight_vs20.fxc + +vertexlit_and_unlit_generic_bump_ps2x.fxc +vertexlit_and_unlit_generic_bump_vs20.fxc + +vertexlit_and_unlit_generic_ps2x.fxc +vertexlit_and_unlit_generic_vs20.fxc + +vertexlitgeneric_flashlight_vs11.vsh +volume_clouds_vs20.fxc +volume_clouds_ps2x.fxc + +vortwarp_ps2x.fxc +vortwarp_vs20.fxc + +Water_vs20.fxc + +WaterCheap_ps2x.fxc +WaterCheap_vs20.fxc + +white_ps2x.fxc + +windowimposter_ps2x.fxc +windowimposter_vs20.fxc + +WorldTwoTextureBlend_ps2x.fxc + +worldvertexalpha_ps2x.fxc + +WorldVertexTransition.vsh +WorldVertexTransition_Editor.psh +writez_vs20.fxc diff --git a/materialsystem/stdshaders/stdshader_dx9_20b_new.txt b/materialsystem/stdshaders/stdshader_dx9_20b_new.txt new file mode 100644 index 00000000..c303915a --- /dev/null +++ b/materialsystem/stdshaders/stdshader_dx9_20b_new.txt @@ -0,0 +1,10 @@ +// +// New shaders collection +// +// These shaders are compiled as shader model 2.0/2.0b +// using the new compiler. +// _ps20.vcs +// _ps20b.vcs +// _vs20.vcs +// +Water_ps2x.fxc diff --git a/materialsystem/stdshaders/stdshader_dx9_30.txt b/materialsystem/stdshaders/stdshader_dx9_30.txt new file mode 100644 index 00000000..7b0c7924 --- /dev/null +++ b/materialsystem/stdshaders/stdshader_dx9_30.txt @@ -0,0 +1,63 @@ +// +// vs 3.0 ps 3.0 shaders collection +// +// These shaders are forced to compile as shader model 3.0 +// using the new compiler. +// _ps30.vcs +// _vs30.vcs +// + +cloak_vs20.fxc +cloak_ps2x.fxc +cloak_blended_pass_vs20.fxc +cloak_blended_pass_ps2x.fxc +debugmorphaccumulator_vs30.fxc +debugmorphaccumulator_ps30.fxc +decalmodulate_ps2x.fxc +decalmodulate_vs20.fxc +depthwrite_ps2x.fxc +depthwrite_vs20.fxc +emissive_scroll_blended_pass_vs20.fxc +emissive_scroll_blended_pass_ps2x.fxc +eye_refract_vs20.fxc +eye_refract_ps2x.fxc +eyes_vs20.fxc +eyes_ps2x.fxc +eyes_flashlight_vs20.fxc +eyes_flashlight_ps2x.fxc +flashlight_ps2x.fxc +flesh_vs30.fxc +flesh_ps30.fxc +lightmappedgeneric_vs20.fxc +lightmappedgeneric_flashlight_vs20.fxc +lightshafts_vs30.fxc +lightshafts_ps30.fxc +modulate_ps2x.fxc +morphaccumulate_vs30.fxc +morphaccumulate_ps30.fxc +morphweight_vs30.fxc +morphweight_ps30.fxc +multiblend_vs20.fxc +multiblend_ps2x.fxc +parallaxtest_vs30.fxc +parallaxtest_ps30.fxc +projected_vs20.fxc +projected_ps2x.fxc +shadowbuildtexture_ps2x.fxc +phong_vs20.fxc +phong_ps20b.fxc +teeth_vs20.fxc +teeth_ps2x.fxc +teeth_bump_vs20.fxc +teeth_bump_ps2x.fxc +teeth_flashlight_vs20.fxc +teeth_flashlight_ps2x.fxc +unlitgeneric_vs20.fxc +unlitgeneric_ps2x.fxc +vertexlit_and_unlit_generic_vs20.fxc +vertexlit_and_unlit_generic_ps2x.fxc +vertexlit_and_unlit_generic_bump_vs20.fxc +vertexlit_and_unlit_generic_bump_ps2x.fxc +vortwarp_vs20.fxc +vortwarp_ps2x.fxc +worldtwotextureblend_ps2x.fxc \ No newline at end of file diff --git a/materialsystem/stdshaders/stdshader_dx9_30_SDK.txt b/materialsystem/stdshaders/stdshader_dx9_30_SDK.txt new file mode 100644 index 00000000..5c34fe3c --- /dev/null +++ b/materialsystem/stdshaders/stdshader_dx9_30_SDK.txt @@ -0,0 +1,35 @@ +// +// vs 3.0 ps 3.0 shaders collection +// +// These shaders are forced to compile as shader model 3.0 +// using the new compiler. +// _ps30.vcs +// _vs30.vcs +// + +cloak_vs20.fxc +cloak_ps2x.fxc +cloak_blended_pass_vs20.fxc +cloak_blended_pass_ps2x.fxc +emissive_scroll_blended_pass_vs20.fxc +emissive_scroll_blended_pass_ps2x.fxc +eye_refract_vs20.fxc +eye_refract_ps2x.fxc +eyes_vs20.fxc +eyes_ps2x.fxc +eyes_flashlight_vs20.fxc +eyes_flashlight_ps2x.fxc +skin_vs20.fxc +skin_ps20b.fxc +teeth_vs20.fxc +teeth_ps2x.fxc +teeth_bump_vs20.fxc +teeth_bump_ps2x.fxc +teeth_flashlight_vs20.fxc +teeth_flashlight_ps2x.fxc +vertexlit_and_unlit_generic_vs20.fxc +vertexlit_and_unlit_generic_ps2x.fxc +vertexlit_and_unlit_generic_bump_vs20.fxc +vertexlit_and_unlit_generic_bump_ps2x.fxc +vortwarp_vs20.fxc +vortwarp_ps2x.fxc \ No newline at end of file diff --git a/materialsystem/stdshaders/stdshader_dx9_sdk.vcproj b/materialsystem/stdshaders/stdshader_dx9_sdk.vcproj new file mode 100644 index 00000000..667812d8 --- /dev/null +++ b/materialsystem/stdshaders/stdshader_dx9_sdk.vcproj @@ -0,0 +1,5369 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/materialsystem/stdshaders/teeth.cpp b/materialsystem/stdshaders/teeth.cpp new file mode 100644 index 00000000..5396c5b5 --- /dev/null +++ b/materialsystem/stdshaders/teeth.cpp @@ -0,0 +1,545 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "BaseVSShader.h" +#include "cpp_shader_constant_register_map.h" + +#include "teeth_vs20.inc" +#include "teeth_flashlight_vs20.inc" +#include "teeth_bump_vs20.inc" +#include "teeth_ps20.inc" +#include "teeth_ps20b.inc" +#include "teeth_flashlight_ps20.inc" +#include "teeth_flashlight_ps20b.inc" +#include "teeth_bump_ps20.inc" +#include "teeth_bump_ps20b.inc" + +#ifndef _X360 +#include "teeth_vs30.inc" +#include "teeth_ps30.inc" +#include "teeth_bump_vs30.inc" +#include "teeth_bump_ps30.inc" +#include "teeth_flashlight_vs30.inc" +#include "teeth_flashlight_ps30.inc" +#endif + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( Teeth, Teeth_DX9 ) + +BEGIN_VS_SHADER( Teeth_DX9, "Help for Teeth_DX9" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( ILLUMFACTOR, SHADER_PARAM_TYPE_FLOAT, "1", "Amount to darken or brighten the teeth" ) + SHADER_PARAM( FORWARD, SHADER_PARAM_TYPE_VEC3, "[1 0 0]", "Forward direction vector for teeth lighting" ) + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "bump map" ) + SHADER_PARAM( PHONGEXPONENT, SHADER_PARAM_TYPE_FLOAT, "100", "phong exponent" ) + SHADER_PARAM( INTRO, SHADER_PARAM_TYPE_BOOL, "0", "is teeth in the ep1 intro" ) + SHADER_PARAM( ENTITYORIGIN, SHADER_PARAM_TYPE_VEC3,"0.0","center if the model in world space" ) + SHADER_PARAM( WARPPARAM, SHADER_PARAM_TYPE_FLOAT,"0.0","animation param between 0 and 1" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + params[FLASHLIGHTTEXTURE]->SetStringValue( GetFlashlightTextureFilename() ); + + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + + if( !params[INTRO]->IsDefined() ) + { + params[INTRO]->SetIntValue( 0 ); + } + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + LoadTexture( FLASHLIGHTTEXTURE ); + LoadTexture( BASETEXTURE ); + + if( params[BUMPMAP]->IsDefined() ) + { + LoadTexture( BUMPMAP ); + } + } + + void DrawUsingVertexShader( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, VertexCompressionType_t vertexCompression ) + { + bool hasBump = params[BUMPMAP]->IsTexture(); + + BlendType_t nBlendType = EvaluateBlendRequirements( BASETEXTURE, true ); + bool bFullyOpaque = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !IS_FLAG_SET(MATERIAL_VAR_ALPHATEST); //dest alpha is free for special use + + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); // Base map + + int flags = VERTEX_POSITION | VERTEX_NORMAL; + int nTexCoordCount = 1; + int userDataSize = 0; + + if ( hasBump ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); // Bump map + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); // Normalization sampler for per-pixel lighting + userDataSize = 4; // tangent S + } + + // This shader supports compressed vertices, so OR in that flag: + flags |= VERTEX_FORMAT_COMPRESSED; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + if ( hasBump ) + { +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_STATIC_VERTEX_SHADER( teeth_bump_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( INTRO, params[INTRO]->GetIntValue() ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER( teeth_bump_vs20 ); + + // ps_2_b version which does phong + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( teeth_bump_ps20b ); + SET_STATIC_PIXEL_SHADER( teeth_bump_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( teeth_bump_ps20 ); + SET_STATIC_PIXEL_SHADER( teeth_bump_ps20 ); + } + } +#ifndef _X360 + else + { + // The vertex shader uses the vertex id stream + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + + DECLARE_STATIC_VERTEX_SHADER( teeth_bump_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( INTRO, params[INTRO]->GetIntValue() ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER( teeth_bump_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( teeth_bump_ps30 ); + SET_STATIC_PIXEL_SHADER( teeth_bump_ps30 ); + } +#endif + } + else + { +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_STATIC_VERTEX_SHADER( teeth_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( INTRO, params[INTRO]->GetIntValue() ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER( teeth_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( teeth_ps20b ); + SET_STATIC_PIXEL_SHADER( teeth_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( teeth_ps20 ); + SET_STATIC_PIXEL_SHADER( teeth_ps20 ); + } + } +#ifndef _X360 + else + { + // The vertex shader uses the vertex id stream + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + + DECLARE_STATIC_VERTEX_SHADER( teeth_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( INTRO, params[INTRO]->GetIntValue() ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER( teeth_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( teeth_ps30 ); + SET_STATIC_PIXEL_SHADER( teeth_ps30 ); + } +#endif + } + + // On DX9, do sRGB + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBWrite( true ); + + FogToFogColor(); + + pShaderShadow->EnableAlphaWrites( bFullyOpaque ); + + // Lighting constants + PI_BeginCommandBuffer(); + PI_SetPixelShaderAmbientLightCube( PSREG_AMBIENT_CUBE ); + PI_SetPixelShaderLocalLighting( PSREG_LIGHT_INFO_ARRAY ); + + // For non-bumped case, ambient cube is computed in the vertex shader + if ( !hasBump ) + { + PI_SetVertexShaderAmbientLightCube(); + } + + PI_EndCommandBuffer(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + if ( hasBump ) + { + BindTexture( SHADER_SAMPLER1, BUMPMAP ); + } + pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_NORMALIZATION_CUBEMAP_SIGNED ); + + Vector4D lighting; + params[FORWARD]->GetVecValue( lighting.Base(), 3 ); + lighting[3] = params[ILLUMFACTOR]->GetFloatValue(); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, lighting.Base() ); + + LightState_t lightState; + pShaderAPI->GetDX9LightState( &lightState ); + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + float vEyePos_SpecExponent[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + vEyePos_SpecExponent[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + + if ( hasBump ) + { +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_DYNAMIC_VERTEX_SHADER( teeth_bump_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( STATIC_LIGHT, lightState.m_bStaticLight ? 1 : 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( teeth_bump_vs20 ); + + // ps_2_b version which does Phong + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + Vector4D vSpecExponent; + vSpecExponent[3] = params[PHONGEXPONENT]->GetFloatValue(); + + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vSpecExponent.Base(), 1 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( teeth_bump_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( AMBIENT_LIGHT, lightState.m_bAmbientLight ? 1 : 0 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bFullyOpaque && pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( teeth_bump_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( teeth_bump_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( AMBIENT_LIGHT, lightState.m_bAmbientLight ? 1 : 0 ); + SET_DYNAMIC_PIXEL_SHADER( teeth_bump_ps20 ); + } + } +#ifndef _X360 + else + { + SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, SHADER_VERTEXTEXTURE_SAMPLER0 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( teeth_bump_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( STATIC_LIGHT, lightState.m_bStaticLight ? 1 : 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( teeth_bump_vs30 ); + + Vector4D vSpecExponent; + vSpecExponent[3] = params[PHONGEXPONENT]->GetFloatValue(); + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vSpecExponent.Base(), 1 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( teeth_bump_ps30 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( AMBIENT_LIGHT, lightState.m_bAmbientLight ? 1 : 0 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bFullyOpaque && pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( teeth_bump_ps30 ); + } +#endif + } + else + { +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_DYNAMIC_VERTEX_SHADER( teeth_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DYNAMIC_LIGHT, lightState.HasDynamicLight() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( STATIC_LIGHT, lightState.m_bStaticLight ? 1 : 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( teeth_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( teeth_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bFullyOpaque && pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( teeth_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( teeth_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( teeth_ps20 ); + } + } +#ifndef _X360 + else + { + SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, SHADER_VERTEXTEXTURE_SAMPLER0 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( teeth_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DYNAMIC_LIGHT, lightState.HasDynamicLight() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( STATIC_LIGHT, lightState.m_bStaticLight ? 1 : 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( teeth_vs30 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( teeth_ps30 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bFullyOpaque && pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( teeth_ps30 ); + } +#endif + } + + if( params[INTRO]->GetIntValue() ) + { + float curTime = params[WARPPARAM]->GetFloatValue(); + float timeVec[4] = { 0.0f, 0.0f, 0.0f, curTime }; + Assert( params[ENTITYORIGIN]->IsDefined() ); + params[ENTITYORIGIN]->GetVecValue( timeVec, 3 ); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, timeVec, 1 ); + } + } + Draw(); + } + + void DrawFlashlight( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, VertexCompressionType_t vertexCompression ) + { + SHADOW_STATE + { + // Be sure not to write to dest alpha + pShaderShadow->EnableAlphaWrites( false ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); // Base map + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); // Flashlight spot + + // Additive blend the teeth, lit by the flashlight + s_pShaderShadow->EnableAlphaTest( false ); + s_pShaderShadow->BlendFunc( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); + s_pShaderShadow->EnableBlending( true ); + + // Set stream format (note that this shader supports compression) + int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + int nShadowFilterMode = 0; + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); // shadow depth map + pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER2 ); + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); // shadow noise + + nShadowFilterMode = g_pHardwareConfig->GetShadowFilterMode(); // Based upon vendor and device dependent formats + } + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_STATIC_VERTEX_SHADER( teeth_flashlight_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( INTRO, params[INTRO]->GetIntValue() ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER( teeth_flashlight_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( teeth_flashlight_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER( teeth_flashlight_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( teeth_flashlight_ps20 ); + SET_STATIC_PIXEL_SHADER( teeth_flashlight_ps20 ); + } + } +#ifndef _X360 + else + { + // The vertex shader uses the vertex id stream + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + + DECLARE_STATIC_VERTEX_SHADER( teeth_flashlight_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( INTRO, params[INTRO]->GetIntValue() ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER( teeth_flashlight_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( teeth_flashlight_ps30 ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER( teeth_flashlight_ps30 ); + } +#endif + // On DX9, do sRGB + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBWrite( true ); + + FogToFogColor(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + + // State for spotlight projection, attenuation etc + SetFlashlightVertexShaderConstants( false, -1, false, -1, true ); + + VMatrix worldToTexture; + ITexture *pFlashlightDepthTexture; + FlashlightState_t flashlightState = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture ); + SetFlashLightColorFromState( flashlightState, pShaderAPI, false, PSREG_FLASHLIGHT_COLOR ); + + bool bFlashlightShadows = g_pHardwareConfig->SupportsPixelShaders_2_b() ? flashlightState.m_bEnableShadows : false; + if( pFlashlightDepthTexture && g_pConfig->ShadowDepthTexture() && flashlightState.m_bEnableShadows ) + { + BindTexture( SHADER_SAMPLER2, pFlashlightDepthTexture, 0 ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER3, TEXTURE_SHADOW_NOISE_2D ); + } + + Vector4D lighting; + params[FORWARD]->GetVecValue( lighting.Base(), 3 ); + lighting[3] = params[ILLUMFACTOR]->GetFloatValue(); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_8, lighting.Base() ); + + float atten[4], pos[4], tweaks[4]; + SetFlashLightColorFromState( flashlightState, pShaderAPI, false, PSREG_FLASHLIGHT_COLOR ); + + BindTexture( SHADER_SAMPLER1, flashlightState.m_pSpotlightTexture, flashlightState.m_nSpotlightTextureFrame ); + + atten[0] = flashlightState.m_fConstantAtten; // Set the flashlight attenuation factors + atten[1] = flashlightState.m_fLinearAtten; + atten[2] = flashlightState.m_fQuadraticAtten; + atten[3] = flashlightState.m_FarZAtten; + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_ATTENUATION, atten, 1 ); + + pos[0] = flashlightState.m_vecLightOrigin[0]; // Set the flashlight origin + pos[1] = flashlightState.m_vecLightOrigin[1]; + pos[2] = flashlightState.m_vecLightOrigin[2]; + pos[3] = flashlightState.m_FarZ; + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_POSITION_RIM_BOOST, pos, 1 ); // steps on rim boost + + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_TO_WORLD_TEXTURE, worldToTexture.Base(), 4 ); + + // Tweaks associated with a given flashlight + tweaks[0] = ShadowFilterFromState( flashlightState ); + tweaks[1] = ShadowAttenFromState( flashlightState ); + HashShadow2DJitter( flashlightState.m_flShadowJitterSeed, &tweaks[2], &tweaks[3] ); + pShaderAPI->SetPixelShaderConstant( PSREG_ENVMAP_TINT__SHADOW_TWEAKS, tweaks, 1 ); + + // Dimensions of screen, used for screen-space noise map sampling + float vScreenScale[4] = {1280.0f / 32.0f, 720.0f / 32.0f, 0, 0}; + int nWidth, nHeight; + pShaderAPI->GetBackBufferDimensions( nWidth, nHeight ); + int nTexWidth, nTexHeight; + pShaderAPI->GetStandardTextureDimensions( &nTexWidth, &nTexHeight, TEXTURE_SHADOW_NOISE_2D ); + + vScreenScale[0] = (float) nWidth / nTexWidth; + vScreenScale[1] = (float) nHeight / nTexHeight; + + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_SCREEN_SCALE, vScreenScale, 1 ); + + float vFlashlightPos[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vFlashlightPos ); + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_POSITION_RIM_BOOST, vFlashlightPos, 1 ); + + if ( IsX360() ) + { + pShaderAPI->SetBooleanPixelShaderConstant( 0, &flashlightState.m_nShadowQuality, 1 ); + } + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_DYNAMIC_VERTEX_SHADER( teeth_flashlight_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( teeth_flashlight_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( teeth_flashlight_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER( teeth_flashlight_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( teeth_flashlight_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( teeth_flashlight_ps20 ); + } + } +#ifndef _X360 + else + { + SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, SHADER_VERTEXTEXTURE_SAMPLER0 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( teeth_flashlight_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( teeth_flashlight_vs30 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( teeth_flashlight_ps30 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( UBERLIGHT, flashlightState.m_bUberlight ); + SET_DYNAMIC_PIXEL_SHADER( teeth_flashlight_ps30 ); + + SetupUberlightFromState( pShaderAPI, flashlightState ); + } +#endif + + if( params[INTRO]->GetIntValue() ) + { + float curTime = params[WARPPARAM]->GetFloatValue(); + float timeVec[4] = { 0.0f, 0.0f, 0.0f, curTime }; + Assert( params[ENTITYORIGIN]->IsDefined() ); + params[ENTITYORIGIN]->GetVecValue( timeVec, 3 ); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_9, timeVec, 1 ); + } + } + Draw(); + } + + SHADER_DRAW + { + SHADOW_STATE + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + } + bool hasFlashlight = UsingFlashlight( params ); + if ( !hasFlashlight || IsX360() ) + { + DrawUsingVertexShader( params, pShaderAPI, pShaderShadow, vertexCompression ); + SHADOW_STATE + { + SetInitialShadowState(); + } + } + if( hasFlashlight ) + { + DrawFlashlight( params, pShaderAPI, pShaderShadow, vertexCompression ); + } + } +END_SHADER diff --git a/materialsystem/stdshaders/teeth_bump_ps2x.fxc b/materialsystem/stdshaders/teeth_bump_ps2x.fxc new file mode 100644 index 00000000..9148eec3 --- /dev/null +++ b/materialsystem/stdshaders/teeth_bump_ps2x.fxc @@ -0,0 +1,96 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#include "common_fog_ps_fxc.h" +// DYNAMIC: "NUM_LIGHTS" "0..2" [ps20] +// DYNAMIC: "NUM_LIGHTS" "0..4" [ps20b] +// DYNAMIC: "NUM_LIGHTS" "0..4" [ps30] +// DYNAMIC: "AMBIENT_LIGHT" "0..1" +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps30] + +#if defined( SHADER_MODEL_PS_2_0 ) +# define WRITE_DEPTH_TO_DESTALPHA 0 +#endif + +#include "shader_constant_register_map.h" + +const float3 cAmbientCube[6] : register( PSREG_AMBIENT_CUBE ); +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT ); +PixelShaderLightInfo cLightInfo[3] : register( PSREG_LIGHT_INFO_ARRAY ); // 2 registers each - 6 registers total + +sampler BaseTextureSampler : register( s0 ); +sampler BumpTextureSampler : register( s1 ); +sampler NormalizeSampler : register( s2 ); + +struct PS_INPUT +{ + float2 baseTexCoord : TEXCOORD0; + float4 worldVertToEyeVector_Darkening : TEXCOORD1; + float3x3 tangentSpaceTranspose : TEXCOORD2; + // second row : TEXCOORD3; + // third row : TEXCOORD4; + float4 worldPos_projPosZ : TEXCOORD5; + float4 lightAtten0123 : TEXCOORD6; +}; + + + +#if ((defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0))) + +#define worldVertToEyeVector i.worldVertToEyeVector_Darkening.xyz +#define fDarkening i.worldVertToEyeVector_Darkening.w + +#endif + + + +float4 main( PS_INPUT i ) : COLOR +{ + bool bAmbientLight = AMBIENT_LIGHT ? true : false; + int nNumLights = NUM_LIGHTS; + + float4 vLightAtten = i.lightAtten0123; + float4 baseSample = tex2D( BaseTextureSampler, i.baseTexCoord ); + + float3 worldSpaceNormal, tangentSpaceNormal = float3(0, 0, 1); + float fSpecExp = g_EyePos_SpecExponent.w; + + float4 normalTexel = tex2D( BumpTextureSampler, i.baseTexCoord ); + tangentSpaceNormal = 2.0f * normalTexel.xyz - 1.0f; + worldSpaceNormal = normalize( mul( i.tangentSpaceTranspose, tangentSpaceNormal ) ); + + // If the exponent passed in as a constant is zero, use the value from the map as the exponent + if ( fSpecExp == 0 ) + fSpecExp = 1.0f * ( 1.0f - normalTexel.w ) + 150.0f * normalTexel.w; + + // Summation of diffuse illumination from all local lights + float3 diffuseLighting = PixelShaderDoLighting( i.worldPos_projPosZ.xyz, worldSpaceNormal, + float3( 0.0f, 0.0f, 0.0f ), false, + bAmbientLight, vLightAtten, + cAmbientCube, NormalizeSampler, nNumLights, cLightInfo, true, + false, NormalizeSampler ); + +#if ((defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0))) + + float3 vDummy, specularLighting; + + // Summation of specular from all local lights + PixelShaderDoSpecularLighting( i.worldPos_projPosZ.xyz, worldSpaceNormal, fSpecExp, normalize(worldVertToEyeVector), + vLightAtten, nNumLights, cLightInfo, + false, NormalizeSampler, 1.0f, false, 1.0f, + + // Outputs + specularLighting, vDummy ); + + // Specular plus diffuse, all darkened as a function of mouth openness + float3 result = (specularLighting * baseSample.a + baseSample.rgb * diffuseLighting) * fDarkening; + +#else + float3 result = baseSample.rgb * diffuseLighting * i.worldVertToEyeVector_Darkening.w; +#endif + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos_SpecExponent.xyz, i.worldPos_projPosZ.xyz, i.worldPos_projPosZ.w ); + return FinalOutput( float4(result, 1.0f), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, (WRITE_DEPTH_TO_DESTALPHA != 0), i.worldPos_projPosZ.w ); +} diff --git a/materialsystem/stdshaders/teeth_bump_vs20.fxc b/materialsystem/stdshaders/teeth_bump_vs20.fxc new file mode 100644 index 00000000..828cc11d --- /dev/null +++ b/materialsystem/stdshaders/teeth_bump_vs20.fxc @@ -0,0 +1,129 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "INTRO" "0..1" + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +#include "common_fog_vs_fxc.h" +// DYNAMIC: "SKINNING" "0..1" +// DYNAMIC: "STATIC_LIGHT" "0..1" + +// DYNAMIC: "MORPHING" "0..1" [vs30] [ = pShaderAPI->IsHWMorphingEnabled() ] + +#include "vortwarp_vs20_helper.h" + +static const int g_FogType = DOWATERFOG; +static const bool g_bSkinning = SKINNING ? true : false; + +const float4 cTeethLighting : register( SHADER_SPECIFIC_CONST_0 ); +#if INTRO +const float4 const4 : register( SHADER_SPECIFIC_CONST_1 ); +#define g_Time const4.w +#define modelOrigin const4.xyz +#endif + +#ifdef SHADER_MODEL_VS_3_0 +// NOTE: cMorphTargetTextureDim.xy = target dimensions, +// cMorphTargetTextureDim.z = 4tuples/morph +const float3 cMorphTargetTextureDim : register( SHADER_SPECIFIC_CONST_6 ); +const float4 cMorphSubrect : register( SHADER_SPECIFIC_CONST_7 ); + +sampler2D morphSampler : register( D3DVERTEXTEXTURESAMPLER0, s0 ); +#endif + +struct VS_INPUT +{ + // This is all of the stuff that we ever use. + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vNormal : NORMAL; + float2 vTexCoord0 : TEXCOORD0; + float4 vUserData : TANGENT; // Sign for cross product in w + + // Position and normal/tangent deltas + float3 vPosFlex : POSITION1; + float3 vNormalFlex : NORMAL1; +#ifdef SHADER_MODEL_VS_3_0 + float vVertexID : POSITION2; +#endif +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) && !INTRO + float fog : FOG; +#endif + float2 baseTexCoord : TEXCOORD0; + float4 worldVertToEyeVector_Darkening : TEXCOORD1; + float3x3 tangentSpaceTranspose : TEXCOORD2; + // second row : TEXCOORD3; + // third row : TEXCOORD4; + float4 worldPos_projPosZ : TEXCOORD5; + float4 lightAtten0123 : TEXCOORD6; +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float4 vPosition = v.vPos; + float3 vNormal; + float4 vTangent; + DecompressVertex_NormalTangent( v.vNormal, v.vUserData, vNormal, vTangent ); + +#if !defined( SHADER_MODEL_VS_3_0 ) || !MORPHING + ApplyMorph( v.vPosFlex, v.vNormalFlex, vPosition.xyz, vNormal, vTangent.xyz ); +#else + ApplyMorph( morphSampler, cMorphTargetTextureDim, cMorphSubrect, v.vVertexID, float3( 0, 0, 0 ), + vPosition.xyz, vNormal, vTangent.xyz ); +#endif + + // Perform skinning + float3 worldNormal, worldPos, worldTangentS, worldTangentT; + SkinPositionNormalAndTangentSpace( g_bSkinning, vPosition, vNormal, vTangent, + v.vBoneWeights, v.vBoneIndices, worldPos, + worldNormal, worldTangentS, worldTangentT ); + +#if INTRO + WorldSpaceVertexProcess( g_Time, modelOrigin, worldPos, worldNormal, worldTangentS, worldTangentT ); +#endif + + // Always normalize since flex path is controlled by runtime + // constant not a shader combo and will always generate the normalization + worldNormal = normalize( worldNormal ); + worldTangentS = normalize( worldTangentS ); + worldTangentT = normalize( worldTangentT ); + + // Transform into projection space + o.projPos = mul( float4( worldPos, 1 ), cViewProj ); + + o.worldPos_projPosZ = float4( worldPos, o.projPos.z ); + +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) && !INTRO //ran out of instruction slots in intro mode. Don't think we need it in those situations. Drop ps20 fixed function fog support. + o.fog = CalcFixedFunctionFog( worldPos, g_FogType ); +#endif + + // Needed for specular + o.worldVertToEyeVector_Darkening.xyz = cEyePos - worldPos; + + // Special darkening of lights for mouth open/close + o.worldVertToEyeVector_Darkening.w = cTeethLighting.w * saturate( dot( worldNormal, cTeethLighting.xyz ) );; + + // Scalar light attenuation (mouth darkening applied in pixel shader) + o.lightAtten0123.x = GetVertexAttenForLight( worldPos, 0 ); + o.lightAtten0123.y = GetVertexAttenForLight( worldPos, 1 ); + o.lightAtten0123.z = GetVertexAttenForLight( worldPos, 2 ); + o.lightAtten0123.w = GetVertexAttenForLight( worldPos, 3 ); + + o.baseTexCoord = v.vTexCoord0; + + // Tangent space transform + o.tangentSpaceTranspose[0] = float3( worldTangentS.x, worldTangentT.x, worldNormal.x ); + o.tangentSpaceTranspose[1] = float3( worldTangentS.y, worldTangentT.y, worldNormal.y ); + o.tangentSpaceTranspose[2] = float3( worldTangentS.z, worldTangentT.z, worldNormal.z ); + + return o; +} + + diff --git a/materialsystem/stdshaders/teeth_flashlight_ps2x.fxc b/materialsystem/stdshaders/teeth_flashlight_ps2x.fxc new file mode 100644 index 00000000..82f7ecd6 --- /dev/null +++ b/materialsystem/stdshaders/teeth_flashlight_ps2x.fxc @@ -0,0 +1,73 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps20b] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps30] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..0" [ps20b] [XBOX] + +#include "common_fog_ps_fxc.h" +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps20b] +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps30] +// DYNAMIC: "UBERLIGHT" "0..1" [ps30] [PC] + +#include "common_flashlight_fxc.h" +#include "shader_constant_register_map.h" + +sampler BaseTextureSampler : register( s0 ); +sampler SpotSampler : register( s1 ); +sampler FlashlightDepthSampler : register( s2 ); +sampler RandomRotationSampler : register( s3 ); + +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float3 g_EyePos : register( PSREG_EYEPOS_SPEC_EXPONENT ); +const float4 g_ShadowTweaks : register( PSREG_ENVMAP_TINT__SHADOW_TWEAKS ); + +#if UBERLIGHT && defined( SHADER_MODEL_PS_3_0 ) +const float3 g_vSmoothEdge0 : register( PSREG_UBERLIGHT_SMOOTH_EDGE_0 ); // ps_3_0 and up (over 32 registers) +const float3 g_vSmoothEdge1 : register( PSREG_UBERLIGHT_SMOOTH_EDGE_1 ); +const float3 g_vSmoothOneOverWidth : register( PSREG_UBERLIGHT_SMOOTH_EDGE_OOW ); +const float4 g_vShearRound : register( PSREG_UBERLIGHT_SHEAR_ROUND ); +const float4 g_aAbB : register( PSREG_UBERLIGHT_AABB ); +const float4x4 g_FlashlightWorldToLight : register( PSREG_UBERLIGHT_WORLD_TO_LIGHT ); +#endif + + +struct PS_INPUT +{ + float2 baseTexCoord : TEXCOORD0; // Base texture coordinates + float4 spotTexCoord : TEXCOORD1; // Spotlight texture coordinates + float3 vertAtten : TEXCOORD2; // Distance/spot attenuation + float4 projPos : TEXCOORD3; // Projective space position + float3 worldPos : TEXCOORD4; // Necessary for pixel fog +}; + +float4 main( PS_INPUT i ) : COLOR +{ +#if defined( SHADER_MODEL_PS_2_0 ) + float3 result = tex2Dproj( SpotSampler, i.spotTexCoord.xyzw ); +#else + float3 vProjCoords = i.spotTexCoord.xyz / i.spotTexCoord.w; + float3 result = tex2D( SpotSampler, vProjCoords ); +#endif + + result *= cFlashlightColor.rgb; + +#if FLASHLIGHTSHADOWS && ( defined( SHADER_MODEL_PS_2_B ) || defined( SHADER_MODEL_PS_3_0 ) ) + result *= DoFlashlightShadow( FlashlightDepthSampler, RandomRotationSampler, vProjCoords, i.projPos.xy / i.projPos.z, FLASHLIGHTDEPTHFILTERMODE, g_ShadowTweaks, true ); + +#if UBERLIGHT && defined( SHADER_MODEL_PS_3_0 ) + float4 uberLightPosition = mul( float4( i.worldPos, 1.0f ), g_FlashlightWorldToLight ).yzxw; + result *= uberlight( uberLightPosition, g_vSmoothEdge0, g_vSmoothEdge1, + g_vSmoothOneOverWidth, g_vShearRound.xy, g_aAbB, g_vShearRound.zw ); +#endif + +#endif + result *= 0.35f; // Without this, unshadowed teeth always seem to glow + + result *= i.vertAtten; // Distance atten, NdotL and forward vector + + float4 baseSample = tex2D( BaseTextureSampler, i.baseTexCoord ); + result *= baseSample.rgb; // Multiply by base map and diffuse + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos.xyz, i.worldPos.xyz, i.projPos.z ); + return FinalOutput( float4( result, baseSample.a ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR ); +} diff --git a/materialsystem/stdshaders/teeth_flashlight_vs20.fxc b/materialsystem/stdshaders/teeth_flashlight_vs20.fxc new file mode 100644 index 00000000..3d027cf3 --- /dev/null +++ b/materialsystem/stdshaders/teeth_flashlight_vs20.fxc @@ -0,0 +1,151 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "INTRO" "0..1" + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +#include "common_fog_vs_fxc.h" +// DYNAMIC: "SKINNING" "0..1" + +// DYNAMIC: "MORPHING" "0..1" [vs30] [ = pShaderAPI->IsHWMorphingEnabled() ] + +#include "vortwarp_vs20_helper.h" + +static const int g_FogType = DOWATERFOG; +static const bool g_bSkinning = SKINNING ? true : false; + +const float4 cFlashlightPosition : register( SHADER_SPECIFIC_CONST_0 ); +const float4 cSpotlightProj1 : register( SHADER_SPECIFIC_CONST_1 ); +const float4 cSpotlightProj2 : register( SHADER_SPECIFIC_CONST_2 ); +const float4 cSpotlightProj3 : register( SHADER_SPECIFIC_CONST_3 ); +const float4 cSpotlightProj4 : register( SHADER_SPECIFIC_CONST_4 ); +const float4 cFlashlighAtten : register( SHADER_SPECIFIC_CONST_5 ); // const, linear, quadratic & farZ + +const float4 cTeethLighting : register( SHADER_SPECIFIC_CONST_8 ); +#if INTRO +const float4 const4 : register( SHADER_SPECIFIC_CONST_9 ); +#define g_Time const4.w +#define modelOrigin const4.xyz +#endif + +#ifdef SHADER_MODEL_VS_3_0 +// NOTE: cMorphTargetTextureDim.xy = target dimensions, +// cMorphTargetTextureDim.z = 4tuples/morph +const float3 cMorphTargetTextureDim : register( SHADER_SPECIFIC_CONST_6 ); +const float4 cMorphSubrect : register( SHADER_SPECIFIC_CONST_7 ); + +sampler2D morphSampler : register( D3DVERTEXTEXTURESAMPLER0, s0 ); +#endif + + +struct VS_INPUT +{ + // This is all of the stuff that we ever use. + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vNormal : NORMAL; + float2 vTexCoord0 : TEXCOORD0; + + // Position and normal/tangent deltas + float3 vPosFlex : POSITION1; + float3 vNormalFlex : NORMAL1; +#ifdef SHADER_MODEL_VS_3_0 + float vVertexID : POSITION2; +#endif +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + float fog : FOG; +#endif + float2 baseTexCoord : TEXCOORD0; // Base texture coordinates + float4 spotTexCoord : TEXCOORD1; // Spotlight texture coordinates + float3 vertAtten : TEXCOORD2; // Distance/spot attenuation + float4 vProjPos : TEXCOORD3; // Projective space position + float3 worldPos : TEXCOORD4; // Necessary for pixel fog +}; + + +float RemapValClamped_01( float val, float A, float B ) +{ + float cVal = (val - A) / (B - A); + cVal = saturate( cVal ); + return cVal; +} + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float4 vPosition = v.vPos; + float3 vNormal; + DecompressVertex_Normal( v.vNormal, vNormal ); + +#if !defined( SHADER_MODEL_VS_3_0 ) || !MORPHING + ApplyMorph( v.vPosFlex, v.vNormalFlex, vPosition.xyz, vNormal ); +#else + ApplyMorph( morphSampler, cMorphTargetTextureDim, cMorphSubrect, v.vVertexID, float3( 0, 0, 0 ), vPosition.xyz, vNormal ); +#endif + + // Normalize the flexed normal + vNormal.xyz = normalize( vNormal.xyz ); + + // Transform the position + float3 worldPos, worldNormal; + SkinPositionAndNormal( g_bSkinning, vPosition, vNormal, v.vBoneWeights, v.vBoneIndices, worldPos, worldNormal ); + +#if INTRO + float3 dummy = float3( 0.0f, 0.0f, 0.0f ); + WorldSpaceVertexProcess( g_Time, modelOrigin, worldPos, worldNormal, dummy, dummy ); +#endif + + // Transform into projection space + o.projPos = mul( float4( worldPos, 1 ), cViewProj ); + o.worldPos = worldPos.xyz; + o.vProjPos = o.projPos; + +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + o.fog = CalcFixedFunctionFog( worldPos, g_FogType ); +#endif + + // Spotlight texture coordinates + o.spotTexCoord.x = dot( cSpotlightProj1, float4(worldPos, 1) ); + o.spotTexCoord.y = dot( cSpotlightProj2, float4(worldPos, 1) ); + o.spotTexCoord.z = dot( cSpotlightProj3, float4(worldPos, 1) ); + o.spotTexCoord.w = dot( cSpotlightProj4, float4(worldPos, 1) ); + + // Compute vector to light + float3 vWorldPosToLightVector = cFlashlightPosition.xyz - worldPos; + + float3 vDistAtten = float3(1, 1, 1); + vDistAtten.z = dot( vWorldPosToLightVector, vWorldPosToLightVector ); + vDistAtten.y = rsqrt( vDistAtten.z ); + + float flDist = vDistAtten.z * vDistAtten.y; // Distance to light + vDistAtten.z = 1.0f / vDistAtten.z; // 1 / distsquared + + float fFarZ = cFlashlighAtten.w; + + float NdotL = saturate( dot( worldNormal, normalize( vWorldPosToLightVector ) ) ); + + float endFalloffFactor = RemapValClamped_01( flDist, fFarZ, 0.6 * fFarZ ); + o.vertAtten.xyz = endFalloffFactor * dot( vDistAtten, cFlashlighAtten.xyz ); + + // Final attenuation from flashlight only... + float linearAtten = NdotL * dot( vDistAtten, cFlashlighAtten.xyz ) * endFalloffFactor; + + // Forward vector + float3 vForward = cTeethLighting.xyz; + float fIllumFactor = cTeethLighting.w; + + // Modulate flashlight by mouth darkening + o.vertAtten = linearAtten * fIllumFactor * saturate( dot( worldNormal, vForward ) ); + + o.baseTexCoord = v.vTexCoord0; + + return o; +} + + diff --git a/materialsystem/stdshaders/teeth_ps2x.fxc b/materialsystem/stdshaders/teeth_ps2x.fxc new file mode 100644 index 00000000..d66cee36 --- /dev/null +++ b/materialsystem/stdshaders/teeth_ps2x.fxc @@ -0,0 +1,40 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#include "common_fog_ps_fxc.h" +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps30] + + +#if defined( SHADER_MODEL_PS_2_0 ) +# define WRITE_DEPTH_TO_DESTALPHA 0 +#endif + +#include "common_ps_fxc.h" +#include "shader_constant_register_map.h" + +sampler BaseTextureSampler : register( s0 ); + +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT ); + +struct PS_INPUT +{ + float2 baseTexCoord : TEXCOORD0; + float3 vertAtten : TEXCOORD1; + + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float4 baseSample = tex2D( BaseTextureSampler, i.baseTexCoord ); + + float4 result; + result.xyz = baseSample.xyz * i.vertAtten; + result.a = baseSample.a; + + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos_SpecExponent.xyz, i.worldPos_projPosZ.xyz, i.worldPos_projPosZ.w ); + return FinalOutput( result, fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, (WRITE_DEPTH_TO_DESTALPHA != 0), i.worldPos_projPosZ.w ); +} diff --git a/materialsystem/stdshaders/teeth_vs20.fxc b/materialsystem/stdshaders/teeth_vs20.fxc new file mode 100644 index 00000000..914c4fe5 --- /dev/null +++ b/materialsystem/stdshaders/teeth_vs20.fxc @@ -0,0 +1,116 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "INTRO" "0..1" + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +#include "common_fog_vs_fxc.h" +// DYNAMIC: "SKINNING" "0..1" +// DYNAMIC: "DYNAMIC_LIGHT" "0..1" +// DYNAMIC: "STATIC_LIGHT" "0..1" + +// DYNAMIC: "MORPHING" "0..1" [vs30] [ = pShaderAPI->IsHWMorphingEnabled() ] + +#include "vortwarp_vs20_helper.h" + +static const int g_FogType = DOWATERFOG; +static const bool g_bSkinning = SKINNING ? true : false; + +const float4 cTeethLighting : register( SHADER_SPECIFIC_CONST_0 ); +#if INTRO +const float4 const4 : register( SHADER_SPECIFIC_CONST_1 ); +#define g_Time const4.w +#define modelOrigin const4.xyz +#endif + +#ifdef SHADER_MODEL_VS_3_0 +// NOTE: cMorphTargetTextureDim.xy = target dimensions, +// cMorphTargetTextureDim.z = 4tuples/morph +const float3 cMorphTargetTextureDim : register( SHADER_SPECIFIC_CONST_6 ); +const float4 cMorphSubrect : register( SHADER_SPECIFIC_CONST_7 ); + +sampler2D morphSampler : register( D3DVERTEXTEXTURESAMPLER0, s0 ); +#endif + +struct VS_INPUT +{ + // This is all of the stuff that we ever use. + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vNormal : NORMAL; + float2 vTexCoord0 : TEXCOORD0; + + // Position and normal/tangent deltas + float3 vPosFlex : POSITION1; + float3 vNormalFlex : NORMAL1; +#ifdef SHADER_MODEL_VS_3_0 + float vVertexID : POSITION2; +#endif +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + float fog : FOG; +#endif + float2 baseTexCoord : TEXCOORD0; + float3 vertAtten : TEXCOORD1; + + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + bool bDynamicLight = DYNAMIC_LIGHT ? true : false; + bool bStaticLight = STATIC_LIGHT ? true : false; + + float4 vPosition = v.vPos; + float3 vNormal; + DecompressVertex_Normal( v.vNormal, vNormal ); + +#if !defined( SHADER_MODEL_VS_3_0 ) || !MORPHING + ApplyMorph( v.vPosFlex, v.vNormalFlex, vPosition.xyz, vNormal ); +#else + ApplyMorph( morphSampler, cMorphTargetTextureDim, cMorphSubrect, v.vVertexID, float3( 0, 0, 0 ), vPosition.xyz, vNormal ); +#endif + + // Normalize the flexed normal + vNormal.xyz = normalize( vNormal.xyz ); + + // Transform the position + float3 worldPos, worldNormal; + SkinPositionAndNormal( g_bSkinning, vPosition, vNormal, v.vBoneWeights, v.vBoneIndices, worldPos, worldNormal ); + +#if INTRO + float3 dummy = float3( 0.0f, 0.0f, 0.0f ); + WorldSpaceVertexProcess( g_Time, modelOrigin, worldPos, worldNormal, dummy, dummy ); +#endif + + // Transform into projection space + o.projPos = mul( float4( worldPos, 1 ), cViewProj ); + o.worldPos_projPosZ = float4( worldPos.xyz, o.projPos.z ); + +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + o.fog = CalcFixedFunctionFog( worldPos, g_FogType ); +#endif + + // Compute lighting + float3 linearColor = DoLighting( worldPos, worldNormal, float3(0.0f, 0.0f, 0.0f), bStaticLight, bDynamicLight, false ); + + // Forward vector + float3 vForward = cTeethLighting.xyz; + float fIllumFactor = cTeethLighting.w; + + // Darken by forward dot normal and illumination factor + linearColor *= fIllumFactor * saturate( dot( worldNormal, vForward ) ); + + o.vertAtten = linearColor; + o.baseTexCoord = v.vTexCoord0; + + return o; +} + + diff --git a/materialsystem/stdshaders/tessellation_vs_fxc.h b/materialsystem/stdshaders/tessellation_vs_fxc.h new file mode 100644 index 00000000..09566638 --- /dev/null +++ b/materialsystem/stdshaders/tessellation_vs_fxc.h @@ -0,0 +1,383 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// +// +// Purpose: Common code for tessellation +// +// $NoKeywords: $ +// +//===========================================================================// + + +#ifndef TESSELLATION_VS_FXC_H_ +#define TESSELLATION_VS_FXC_H_ +#ifdef SHADER_MODEL_VS_3_0 + +#define TESSELLATION_MODE_ACC_PATCHES_EXTRA 1 +#define TESSELLATION_MODE_ACC_PATCHES_REG 2 + +struct VS_INPUT +{ + float2 UV : POSITION0; // Cartesian UV coordinates + float4 BasisU : TEXCOORD0; // BasisU ( precalculated Bernstein basis functions for U ) + float4 BasisV : TEXCOORD1; // BasisV ( precalculated Bernstein basis functions for V ) + + float4 V0_TanU : POSITION1; // Superprim vertex 0 + float4 V0_tc01 : TEXCOORD2; + float4 V0_tc23 : TEXCOORD3; + + float4 V1_TanU : POSITION2; // Superprim vertex 1 + float4 V1_tc01 : TEXCOORD4; + float4 V1_tc23 : TEXCOORD5; + + float4 V2_TanU : POSITION3; // Superprim vertex 2 + float4 V2_tc01 : TEXCOORD6; + float4 V2_tc23 : TEXCOORD7; + + float4 V3_TanU : POSITION4; // Superprim vertex 3 + float4 V3_tc01 : TEXCOORD8; + float4 V3_tc23 : TEXCOORD9; + + float PatchID : TEXCOORD10; // ID for this patch +}; + +void LoadACCPatchPos( float patchIndex, out float3 Bez[16], + float flOneOverSubDHeight, sampler2D sampSubD ) +{ + float idx = ( patchIndex + 0.5 ) * flOneOverSubDHeight; + [unroll] + for (int i = 0; i < 4; i++) + { + float4 tmp[3]; + + tmp[0] = tex2Dlod( sampSubD, float4((i * 3 + 0.5) / 30, idx, 0, 0) ); + tmp[1] = tex2Dlod( sampSubD, float4((i * 3 + 1.5) / 30, idx, 0, 0) ); + tmp[2] = tex2Dlod( sampSubD, float4((i * 3 + 2.5) / 30, idx, 0, 0) ); + + Bez[4 * i + 0] = tmp[0].xyz; + Bez[4 * i + 1] = float3( tmp[0].w, tmp[1].xy ); + Bez[4 * i + 2] = float3( tmp[1].zw, tmp[2].x ); + Bez[4 * i + 3] = tmp[2].yzw; + } +} + +void LoadACCPatchTan( float patchIndex, out float3 TanU[12], out float3 TanV[12], + float flOneOverSubDHeight, sampler2D sampSubD ) +{ + float idx = ( patchIndex + 0.5 ) * flOneOverSubDHeight; + + // Tangents + [unroll] + for (int i = 0; i < 3; i++) + { + float4 tmp[3]; + + tmp[0] = tex2Dlod(sampSubD, float4((i * 3 + 0.5 + 12) / 30, idx, 0, 0)); + tmp[1] = tex2Dlod(sampSubD, float4((i * 3 + 1.5 + 12) / 30, idx, 0, 0)); + tmp[2] = tex2Dlod(sampSubD, float4((i * 3 + 2.5 + 12) / 30, idx, 0, 0)); + + TanU[4 * i + 0] = tmp[0].xyz; + TanU[4 * i + 1] = float3( tmp[0].w, tmp[1].xy ); + TanU[4 * i + 2] = float3( tmp[1].zw, tmp[2].x ); + TanU[4 * i + 3] = tmp[2].yzw; + } + + // Tangents + [unroll] + for (int i = 0; i < 3; i++) + { + float4 tmp[3]; + + tmp[0] = tex2Dlod(sampSubD, float4((i * 3 + 0.5 + 21) / 30, idx, 0, 0)); + tmp[1] = tex2Dlod(sampSubD, float4((i * 3 + 1.5 + 21) / 30, idx, 0, 0)); + tmp[2] = tex2Dlod(sampSubD, float4((i * 3 + 2.5 + 21) / 30, idx, 0, 0)); + + TanV[4 * i + 0] = tmp[0].xyz; + TanV[4 * i + 1] = float3( tmp[0].w, tmp[1].xy ); + TanV[4 * i + 2] = float3( tmp[1].zw, tmp[2].x ); + TanV[4 * i + 3] = tmp[2].yzw; + } +} + +void EvaluateCubicACCPosPatch( in float4 BasisU, in float4 BasisV, float2 UV, float3 cpP[16], out float3 pos ) +{ + pos = (BasisU.x * cpP[ 0] + BasisU.y * cpP[ 1] + BasisU.z * cpP[ 2] + BasisU.w * cpP[ 3]) * BasisV.x + + (BasisU.x * cpP[ 4] + BasisU.y * cpP[ 5] + BasisU.z * cpP[ 6] + BasisU.w * cpP[ 7]) * BasisV.y + + (BasisU.x * cpP[ 8] + BasisU.y * cpP[ 9] + BasisU.z * cpP[10] + BasisU.w * cpP[11]) * BasisV.z + + (BasisU.x * cpP[12] + BasisU.y * cpP[13] + BasisU.z * cpP[14] + BasisU.w * cpP[15]) * BasisV.w; + +} + +//-------------------------------------------------------------------------------------- +// Cubic Bernstein basis functions +// http://mathworld.wolfram.com/BernsteinPolynomial.html +//-------------------------------------------------------------------------------------- +float4 BernsteinBasis( float t ) +{ + float invT = 1.0f-t; + return float4( invT*invT*invT, 3.0*t*invT*invT, 3.0*t*t*invT, t*t*t ); +} + +float3 BersteinBasisQuad( float t ) +{ + float invT = 1.0f-t; + return float3( invT * invT, 2 * invT * t, t * t ); +} + +void EvaluateCubicACCTanPatches( in float4 BasisU, in float4 BasisV, float2 UV, float3 cpU[12], float3 cpV[12], + out float3 tanU, out float3 tanV ) +{ + // quadratic bernstein basis functions + float3 qBasisU = BersteinBasisQuad( UV.x ); + float3 qBasisV = BersteinBasisQuad( UV.y ); + + tanU = (qBasisU.x * cpU[ 0] + qBasisU.y * cpU[ 1] + qBasisU.z * cpU[ 2]) * BasisV.x + + (qBasisU.x * cpU[ 3] + qBasisU.y * cpU[ 4] + qBasisU.z * cpU[ 5]) * BasisV.y + + (qBasisU.x * cpU[ 6] + qBasisU.y * cpU[ 7] + qBasisU.z * cpU[ 8]) * BasisV.z + + (qBasisU.x * cpU[ 9] + qBasisU.y * cpU[10] + qBasisU.z * cpU[11]) * BasisV.w; + + tanV = (BasisU.x * cpV[ 0] + BasisU.y * cpV[ 1] + BasisU.z * cpV[ 2] + BasisU.w * cpV[ 3]) * qBasisV.x + + (BasisU.x * cpV[ 4] + BasisU.y * cpV[ 5] + BasisU.z * cpV[ 6] + BasisU.w * cpV[ 7]) * qBasisV.y + + (BasisU.x * cpV[ 8] + BasisU.y * cpV[ 9] + BasisU.z * cpV[10] + BasisU.w * cpV[11]) * qBasisV.z; +} + +// We define a patch owner for each edge and vertex of the mesh. +// When sampling a displacement map on the boundaries and corners, owner coords are used +// +// Each patch stores: The superprim verts can store +// all of this data like so: +// -- patch U --> +// | X Y Z W +// p t3|t2 t1|t3 +-----------------------------------+ +// a --0-----1-- | tanX | tanY | tanZ | sBWrnk | <- Binormal sign flip bit and wrinkle weight +// t t1|t0 t0|t2 +-----------------------------------+ +// c | | | innerU | innerV | edgeVU | edgeVV | +// h t2|t0 t0|t1 +-----------------------------------+ +// | --3-----2-- | edgeUU | edgeUV | cornerU| cornerV| +// V t3|t1 t2|t3 +-----------------------------------+ +// +float2 ComputeConsistentDisplacementUVs( float2 UV, + float4 V0_tc01, float4 V0_tc23, + float4 V1_tc01, float4 V1_tc23, + float4 V2_tc01, float4 V2_tc23, + float4 V3_tc01, float4 V3_tc23 ) +{ + // Use the tie-breaking scheme for sampling texture coordinates to avoid cracking + float2 t0[4], t1[4], t2[4], t3[4]; + + t0[0] = V0_tc01.xy; + t0[1] = V0_tc01.zw; + t0[2] = V0_tc23.xy; + t0[3] = V0_tc23.zw; + + t1[0] = V1_tc01.xy; + t1[1] = V1_tc01.zw; + t1[2] = V1_tc23.xy; + t1[3] = V1_tc23.zw; + + t2[0] = V2_tc01.xy; + t2[1] = V2_tc01.zw; + t2[2] = V2_tc23.xy; + t2[3] = V2_tc23.zw; + + t3[0] = V3_tc01.xy; + t3[1] = V3_tc01.zw; + t3[2] = V3_tc23.xy; + t3[3] = V3_tc23.zw; + + float flMaxUV = 0.99; + float flMinUV = 0.01; + + int i0 = 2 * (UV.x < flMinUV) + (UV.y < flMinUV); + int i1 = (UV.x > flMaxUV) + 2 * (UV.y < flMinUV); + int i2 = 2 * (UV.x > flMaxUV) + (UV.y > flMaxUV); + int i3 = (UV.x < flMinUV) + 2 * (UV.y > flMaxUV); + + float2 bottom = lerp( t0[i0], t1[i1], UV.x ); + float2 top = lerp( t3[i3], t2[i2], UV.x ); + return lerp( bottom, top, UV.y ); +} + +void DeCasteljau(float u, float3 p0, float3 p1, float3 p2, float3 p3, out float3 p) +{ + float3 q0, q1, q2; + float3 r0, r1; + + [isolate] + { + q0 = lerp( p0, p1, u ); + q1 = lerp( p1, p2, u ); + q2 = lerp( p2, p3, u ); + r0 = lerp( q0, q1, u ); + r1 = lerp( q1, q2, u ); + p = lerp( r0, r1, u ); + } +} + +void DeCasteljau(float u, float3 p0, float3 p1, float3 p2, float3 p3, out float3 p, out float3 dp) +{ + float3 q0, q1, q2; + float3 r0, r1; + + [isolate] + { + q0 = lerp( p0, p1, u ); + q1 = lerp( p1, p2, u ); + q2 = lerp( p2, p3, u ); + r0 = lerp( q0, q1, u ); + r1 = lerp( q1, q2, u ); + p = lerp( r0, r1, u ); + } + + dp = r0 - r1; +} + +void EvaluateBezierRegular( float2 uv, float3 p[16], out float3 pos, out float3 nor ) +{ + float3 t0, t1, t2, t3; + float3 p0, p1, p2, p3; + + [isolate] + { + DeCasteljau( uv.x, p[ 0], p[ 1], p[ 2], p[ 3], p0, t0 ); + DeCasteljau( uv.x, p[ 4], p[ 5], p[ 6], p[ 7], p1, t1 ); + DeCasteljau( uv.x, p[ 8], p[ 9], p[10], p[11], p2, t2 ); + DeCasteljau( uv.x, p[12], p[13], p[14], p[15], p3, t3 ); + } + + float3 du, dv; + DeCasteljau( uv.y, p0, p1, p2, p3, pos, dv ); + DeCasteljau( uv.y, t0, t1, t2, t3, du ); + + nor = normalize( cross(3 * dv, 3 * du) ); +} + +void EvaluateBezierPosition( float2 uv, float3 p[16], out float3 pos ) +{ + float3 t0, t1, t2, t3; + float3 p0, p1, p2, p3; + + [isolate] + { + DeCasteljau( uv.x, p[ 0], p[ 1], p[ 2], p[ 3], p0, t0 ); + DeCasteljau( uv.x, p[ 4], p[ 5], p[ 6], p[ 7], p1, t1 ); + DeCasteljau( uv.x, p[ 8], p[ 9], p[10], p[11], p2, t2 ); + DeCasteljau( uv.x, p[12], p[13], p[14], p[15], p3, t3 ); + } + DeCasteljau( uv.y, p0, p1, p2, p3, pos ); +} + +void EvaluateSubdivisionSurface( const VS_INPUT v, float flOneOverSubDHeight, float flDoDisplacement, float flDoWrinkledDisplacements, + sampler2D BezierSampler, sampler2D sampDisplacement, + + // Outputs + out float3 vWorldNormal, out float3 vWorldPos, + out float3 vWorldTangentS, out float3 vWorldTangentT, out float flBiTangentSign, + out float flWrinkleWeight, + out float2 vTexUV, out float2 vPatchUV, + + bool bTangentFrame = true ) +{ + float4 vInTan; + float2 vDispUV; + float3 vPatchTangent; + float3 vPatchBiTangent; + float4 vBasisU; + float4 vBasisV; + float flPatchLoadIndex; + + // PatchUV is passed in for us + vPatchUV = v.UV; + + // compute values for tangent based on patchUV + float4 TanUbottom = lerp( v.V0_TanU, v.V1_TanU, vPatchUV.x ); + float4 TanUtop = lerp( v.V3_TanU, v.V2_TanU, vPatchUV.x ); + vInTan = lerp( TanUbottom, TanUtop, vPatchUV.y ); + + // compute values for texcoord based on patchUV + float2 bottom = lerp( v.V0_tc01.xy, v.V1_tc01.xy, vPatchUV.x ); + float2 top = lerp( v.V3_tc01.xy, v.V2_tc01.xy, vPatchUV.x ); + vTexUV = lerp( bottom, top, vPatchUV.y ); + + // Compute consistent displacement UVs for crack-free displacement mapping + vDispUV = ComputeConsistentDisplacementUVs( vPatchUV, + v.V0_tc01, v.V0_tc23, + v.V1_tc01, v.V1_tc23, + v.V2_tc01, v.V2_tc23, + v.V3_tc01, v.V3_tc23 ); + + // Cubic Bernstein basis coefficients are passed in for us + vBasisU = v.BasisU; + vBasisV = v.BasisV; + + // Patch load index is passed in for us + flPatchLoadIndex = v.PatchID; + + float3 ControlPoints[16]; + LoadACCPatchPos( flPatchLoadIndex, ControlPoints, flOneOverSubDHeight, BezierSampler ); + +#if ( TESSELLATION == TESSELLATION_MODE_ACC_PATCHES_REG ) + EvaluateBezierRegular( vPatchUV, ControlPoints, vWorldPos, vWorldNormal ); +#else + // We split the loading and evaluation of Position patches and Tangent patches to reduce temp register pressure. + + // Load and evaluation position +// EvaluateCubicACCPosPatch( vBasisU, vBasisV, vPatchUV, ControlPoints, vWorldPos ); + EvaluateBezierPosition( vPatchUV, ControlPoints, vWorldPos ); + + // Load and evaluate tangent patches + float3 ControlPointsU[12], ControlPointsV[12]; + LoadACCPatchTan( flPatchLoadIndex, ControlPointsU, ControlPointsV, flOneOverSubDHeight, BezierSampler ); + EvaluateCubicACCTanPatches( vBasisU, vBasisV, vPatchUV, ControlPointsU, ControlPointsV, vPatchTangent, vPatchBiTangent ); + + vWorldNormal = normalize( cross( vPatchBiTangent, vPatchTangent ) ); // Compute world normal +#endif + + // Up to three scalar displacements for { Neutral, Compress, Stretch } + float3 vDisplacement = tex2Dlod( sampDisplacement, float4( vDispUV, 0, 0 ) ); + + flBiTangentSign = sign( vInTan.w ); + + if ( bTangentFrame ) + { + vWorldTangentS = normalize( vInTan.xyz - ( vWorldNormal * dot( vInTan.xyz, vWorldNormal ) ) ); // Orthonormalize superprim tangent + vWorldTangentT = cross( vWorldNormal, vWorldTangentS.xyz ) * flBiTangentSign; // Sign encodes Binormal flip + } + else + { + vWorldTangentS = vWorldTangentT = vWorldNormal; + } + + flWrinkleWeight = abs( vInTan.w ) - 2.0f; // Convert wrinkle weight to -1 to 1 range for pixel shader to use + + float3 vDispCoeff = float3(0,0,0); // { Neutral, Compress, Stretch } Displacement Coefficients + vDispCoeff.y = saturate( -flWrinkleWeight ); // One of these two is zero + vDispCoeff.z = saturate( flWrinkleWeight ); // while the other is in the 0..1 range + vDispCoeff *= flDoWrinkledDisplacements; // Separate control for presence of wrinkled displacements (just multiplying by 0 or 1 here) + + vDispCoeff.x = 1.0f - vDispCoeff.y - vDispCoeff.z; // Derive neutral weight since these all sum to one + + // Displace along normal, using wrinkle displacement map coefficients + vWorldPos += vWorldNormal * ( flDoDisplacement * dot( vDisplacement, vDispCoeff ) ); +} + + +// Wrapper for no-tangent-frame, no-wrinkle version +void EvaluateSubdivisionSurface( VS_INPUT v, float flOneOverSubDHeight, float flDoDisplacement, float flDoWrinkledDisplacements, + sampler2D BezierSampler, sampler2D DispSampler, + + // Outputs + out float3 vWorldNormal, out float3 vWorldPos, + out float2 vUV, out float2 vPatchUV ) +{ + float3 vDummyA, vDummyB; + float flDummyWrinkle; + float flDummyBinormalFlip; + EvaluateSubdivisionSurface( v, flOneOverSubDHeight, flDoDisplacement, flDoWrinkledDisplacements, + BezierSampler, DispSampler, vWorldNormal, vWorldPos, vDummyA, vDummyB, + flDummyBinormalFlip, flDummyWrinkle, vUV, vPatchUV, false ); + +} + + +#endif // SHADER_MODEL_VS_3_0 + +#endif //#ifndef TESSELLATION_VS_FXC_H_ diff --git a/materialsystem/stdshaders/tree_sway.h b/materialsystem/stdshaders/tree_sway.h new file mode 100644 index 00000000..03d84129 --- /dev/null +++ b/materialsystem/stdshaders/tree_sway.h @@ -0,0 +1,94 @@ +//============ Copyright (c) Valve Corporation, All rights reserved. ============ + +#ifndef _TREE_SWAY_H +#define _TREE_SWAY_H + +// Tree sway vertex animation function. Requires a number of global variables to be defined. See vertexlit_and_unlit_generic_vs20.fxc or depthwrite_vs20.fxc for details. + +// Tree sway mode 2: +// Hacks to use tree sway code on rectangular sheets of plastic/tarp attached at the four corners. +// Inverts the sway scale radius to be 1 at (0,0,0) in model space and fall off radially towards the edges of the model. +// The model is expected to be build lying in the xy plane in model space, with its center at the origin. +// Treeswaystrength should be 0 in the vmt. + +#if ( TREESWAY ) + float3 ComputeTreeSway( float3 vPositionOS, float flTime ) + { + static const float g_flWindOffsetScale = 19; + + float flWindIntensity = length( g_vWindDir ); + + // Model root position is the translation component of the model to world matrix + float3 vModelRoot = float3( cModel[0][3].x, cModel[0][3].y, cModel[0][3].z ); + + // Transform the wind direction into model space + float3 vWindDirAndIntensityOS = mul( ( float3x3 )cModel[0], float3( g_vWindDir, 0 ) ); + + float flSwayScaleHeight = saturate( ( vPositionOS.z - g_flHeight * g_flStartHeight ) / + ( ( 1.0 - g_flStartHeight ) * g_flHeight ) ); + + float flSwayScaleRadius = saturate( length( ( vPositionOS.xy ) - g_flRadius * g_flStartRadius ) / + ( ( 1.0 - g_flStartRadius ) * g_flRadius ) ); + + // Used to turn off branch sway and scrumble below the minimum sway height + float flHeightThreshold = step( 0, vPositionOS.z - g_flHeight * g_flStartHeight ); + + #if ( TREESWAY == 2 ) + { + // Works better for hanging vines + flHeightThreshold = step( vPositionOS.z - g_flHeight * g_flStartHeight, 0 ); + } + #endif + + #ifdef _X360 + // Scale branch motion based on how orthogonal they are + float flOrthoBranchScale = 1.0 - abs( dot( normalize( vWindDirAndIntensityOS.xyz ), float3( normalize( vPositionOS.xy ), 0 ) ) ); + #else + // Scale branch motion based on how orthogonal they are + // This is what I want to compute: + // float flOrthoBranchScale = 1.0 - abs( dot( normalize( vWindDirAndIntensityOS.xyz ), float3( normalize( vPositionOS.xy ), 0 ) ) ); + // Some NV hardware (7800) will do bad things when normalizing a 0 length vector. Instead, I'm doing the dot product unnormalized + // and divide by the length of the vectors, making sure to avoid divide by 0. + float flOrthoBranchScale = abs( dot( vWindDirAndIntensityOS.xyz, float3( vPositionOS.xy, 0 ) ) ); + flOrthoBranchScale = 1.0 - saturate( flOrthoBranchScale / ( max( length( vWindDirAndIntensityOS.xyz ), 0.0001 ) * max( length( vPositionOS.xy ), 0.0001 ) ) ); + #endif + + float flSwayScaleTrunk = g_flSwayIntensity * pow( flSwayScaleHeight, g_flSwayFalloffCurve ); + float flSwayScaleBranches = g_flSwayIntensity * flOrthoBranchScale * flSwayScaleRadius * flHeightThreshold; + #if ( TREESWAY == 2 ) + { + // Looks stupid on vines + flSwayScaleBranches = 0.0; + } + #endif + float flWindTimeOffset = dot( vModelRoot.xyz, float3( 1, 1, 1 ) ) * g_flWindOffsetScale; + float flSlowSwayTime = ( flTime + flWindTimeOffset ) * g_flSwaySpeed; + + float3 vSwayPosOS = normalize( vPositionOS.xyz ); + float3 vScrumblePosOS = vSwayPosOS * g_flScrumbleWaveCount; + float flScrumbleScale = pow( flSwayScaleRadius, g_flScrumbleFalloffCurve ) * g_flScrumbleIntensity * flHeightThreshold; + + float3 vPositionOffset = float3( 0, 0, 0 ); + + // lerp between slow and fast sines based on wind speed + float flSpeedLerp = smoothstep( g_flWindSpeedLerpStart, g_flWindSpeedLerpEnd, flWindIntensity ); + float4 vABunchOfSines = sin( float4( 1.0, 2.31, g_flFastSwaySpeedScale, 2.14 * g_flFastSwaySpeedScale ) * flSlowSwayTime.xxxx ); + vABunchOfSines.xy = lerp( vABunchOfSines.xy, vABunchOfSines.zw, flSpeedLerp ); + + vPositionOffset.xyz = vWindDirAndIntensityOS * flSwayScaleTrunk * ( vABunchOfSines.x + 0.1 ); + vPositionOffset.xyz += vWindDirAndIntensityOS * flSwayScaleBranches * ( vABunchOfSines.y + 0.4 ); + + float3 vScrumbleScale = flScrumbleScale.xxx; + #if ( TREESWAY == 2 ) + { + vScrumbleScale *= float3( 0.5, 0.5, 1.0 ); + } + #endif + + vPositionOffset.xyz += flWindIntensity * ( vScrumbleScale.xyz * sin( g_flScrumbleSpeed * flTime.xxx + vScrumblePosOS.yzx + flWindTimeOffset.xxx ) ); + + return vPositionOS.xyz + vPositionOffset.xyz; + } +#endif + +#endif // _TREE_SWAY_H \ No newline at end of file diff --git a/materialsystem/stdshaders/unlitgeneric_dx9.cpp b/materialsystem/stdshaders/unlitgeneric_dx9.cpp new file mode 100644 index 00000000..8e497029 --- /dev/null +++ b/materialsystem/stdshaders/unlitgeneric_dx9.cpp @@ -0,0 +1,201 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" +#include "vertexlitgeneric_dx9_helper.h" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +BEGIN_VS_SHADER( UnlitGeneric, "Help for UnlitGeneric" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( ALBEDO, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "albedo (Base texture with no baked lighting)" ) + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/detail", "detail texture" ) + SHADER_PARAM( DETAILFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $detail" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "4", "scale of the detail texture" ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "", "envmap frame number" ) + SHADER_PARAM( ENVMAPMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_envmask", "envmap mask" ) + SHADER_PARAM( ENVMAPMASKFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( ENVMAPMASKTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$envmapmask texcoord transform" ) + SHADER_PARAM( ENVMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "envmap tint" ) + SHADER_PARAM( ENVMAPCONTRAST, SHADER_PARAM_TYPE_FLOAT, "0.0", "contrast 0 == normal 1 == color*color" ) + SHADER_PARAM( ENVMAPSATURATION, SHADER_PARAM_TYPE_FLOAT, "1.0", "saturation 0 == greyscale 1 == normal" ) + SHADER_PARAM( ALPHATESTREFERENCE, SHADER_PARAM_TYPE_FLOAT, "0.7", "" ) + SHADER_PARAM( VERTEXALPHATEST, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( HDRCOLORSCALE, SHADER_PARAM_TYPE_FLOAT, "1.0", "hdr color scale" ) + SHADER_PARAM( PHONGEXPONENT, SHADER_PARAM_TYPE_FLOAT, "5.0", "Phong exponent for local specular lights" ) + SHADER_PARAM( PHONGTINT, SHADER_PARAM_TYPE_VEC3, "5.0", "Phong tint for local specular lights" ) + SHADER_PARAM( PHONGALBEDOTINT, SHADER_PARAM_TYPE_BOOL, "1.0", "Apply tint by albedo (controlled by spec exponent texture" ) + SHADER_PARAM( LIGHTWARPTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "1D ramp texture for tinting scalar diffuse term" ) + SHADER_PARAM( PHONGWARPTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "2D map for warping specular" ) + SHADER_PARAM( PHONGFRESNELRANGES, SHADER_PARAM_TYPE_VEC3, "[0 0.5 1]", "Parameters for remapping fresnel output" ) + SHADER_PARAM( PHONGBOOST, SHADER_PARAM_TYPE_FLOAT, "1.0", "Phong overbrightening factor (specular mask channel should be authored to account for this)" ) + SHADER_PARAM( PHONGEXPONENTTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "Phong Exponent map" ) + SHADER_PARAM( PHONG, SHADER_PARAM_TYPE_BOOL, "0", "enables phong lighting" ) + SHADER_PARAM( DETAILBLENDMODE, SHADER_PARAM_TYPE_INTEGER, "0", "mode for combining detail texture with base. 0=normal, 1= additive, 2=alpha blend detail over base, 3=crossfade" ) + SHADER_PARAM( DETAILBLENDFACTOR, SHADER_PARAM_TYPE_FLOAT, "1", "blend amount for detail texture." ) + SHADER_PARAM( DETAILTEXTURETRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$detail texcoord transform" ) + + SHADER_PARAM( DISTANCEALPHA, SHADER_PARAM_TYPE_BOOL, "0", "Use distance-coded alpha generated from hi-res texture by vtex.") + SHADER_PARAM( DISTANCEALPHAFROMDETAIL, SHADER_PARAM_TYPE_BOOL, "0", "Take the distance-coded alpha mask from the detail texture.") + + SHADER_PARAM( SOFTEDGES, SHADER_PARAM_TYPE_BOOL, "0", "Enable soft edges to distance coded textures.") + SHADER_PARAM( SCALEEDGESOFTNESSBASEDONSCREENRES, SHADER_PARAM_TYPE_BOOL, "0", "Scale the size of the soft edges based upon resolution. 1024x768 = nominal.") + SHADER_PARAM( EDGESOFTNESSSTART, SHADER_PARAM_TYPE_FLOAT, "0.6", "Start value for soft edges for distancealpha."); + SHADER_PARAM( EDGESOFTNESSEND, SHADER_PARAM_TYPE_FLOAT, "0.5", "End value for soft edges for distancealpha."); + + SHADER_PARAM( GLOW, SHADER_PARAM_TYPE_BOOL, "0", "Enable glow/shadow for distance coded textures.") + SHADER_PARAM( GLOWCOLOR, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "color of outter glow for distance coded line art." ) + SHADER_PARAM( GLOWALPHA, SHADER_PARAM_TYPE_FLOAT, "1", "Base glow alpha amount for glows/shadows with distance alpha." ) + SHADER_PARAM( GLOWSTART, SHADER_PARAM_TYPE_FLOAT, "0.7", "start value for glow/shadow") + SHADER_PARAM( GLOWEND, SHADER_PARAM_TYPE_FLOAT, "0.5", "end value for glow/shadow") + SHADER_PARAM( GLOWX, SHADER_PARAM_TYPE_FLOAT, "0", "texture offset x for glow mask.") + SHADER_PARAM( GLOWY, SHADER_PARAM_TYPE_FLOAT, "0", "texture offset y for glow mask.") + + SHADER_PARAM( OUTLINE, SHADER_PARAM_TYPE_BOOL, "0", "Enable outline for distance coded textures.") + SHADER_PARAM( OUTLINECOLOR, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "color of outline for distance coded images." ) + SHADER_PARAM( OUTLINEALPHA, SHADER_PARAM_TYPE_FLOAT, "0.0", "alpha value for outline") + SHADER_PARAM( OUTLINESTART0, SHADER_PARAM_TYPE_FLOAT, "0.0", "outer start value for outline") + SHADER_PARAM( OUTLINESTART1, SHADER_PARAM_TYPE_FLOAT, "0.0", "inner start value for outline") + SHADER_PARAM( OUTLINEEND0, SHADER_PARAM_TYPE_FLOAT, "0.0", "inner end value for outline") + SHADER_PARAM( OUTLINEEND1, SHADER_PARAM_TYPE_FLOAT, "0.0", "outer end value for outline") + SHADER_PARAM( SCALEOUTLINESOFTNESSBASEDONSCREENRES, SHADER_PARAM_TYPE_BOOL, "0", "Scale the size of the soft part of the outline based upon resolution. 1024x768 = nominal.") + + SHADER_PARAM( SEPARATEDETAILUVS, SHADER_PARAM_TYPE_BOOL, "0", "Use texcoord1 for detail texture" ) + + SHADER_PARAM( GAMMACOLORREAD, SHADER_PARAM_TYPE_INTEGER, "0", "Disables SRGB conversion of color texture read." ) + SHADER_PARAM( LINEARWRITE, SHADER_PARAM_TYPE_INTEGER, "0", "Disables SRGB conversion of shader results." ) + + SHADER_PARAM( RECEIVEFLASHLIGHT, SHADER_PARAM_TYPE_INTEGER, "0", "Forces this material to receive flashlights." ) + SHADER_PARAM( SINGLEPASSFLASHLIGHT, SHADER_PARAM_TYPE_INTEGER, "0", "Flags this material as possibly being run through single pass flashlight code" ) + SHADER_PARAM( DISPLACEMENTMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "Displacement map" ) + + SHADER_PARAM( SHADERSRGBREAD360, SHADER_PARAM_TYPE_BOOL, "0", "Simulate srgb read in shader code") + END_SHADER_PARAMS + + void SetupVars( VertexLitGeneric_DX9_Vars_t& info ) + { + info.m_nBaseTexture = BASETEXTURE; + info.m_nBaseTextureFrame = FRAME; + info.m_nBaseTextureTransform = BASETEXTURETRANSFORM; + info.m_nAlbedo = ALBEDO; + info.m_nSelfIllumTint = -1; + info.m_nDetail = DETAIL; + info.m_nDetailFrame = DETAILFRAME; + info.m_nDetailScale = DETAILSCALE; + info.m_nDetailTextureCombineMode = DETAILBLENDMODE; + info.m_nDetailTextureBlendFactor = DETAILBLENDFACTOR; + info.m_nDetailTextureTransform = DETAILTEXTURETRANSFORM; + + info.m_nEnvmap = ENVMAP; + info.m_nEnvmapFrame = ENVMAPFRAME; + info.m_nEnvmapMask = ENVMAPMASK; + info.m_nEnvmapMaskFrame = ENVMAPMASKFRAME; + info.m_nEnvmapMaskTransform = ENVMAPMASKTRANSFORM; + info.m_nEnvmapTint = ENVMAPTINT; + info.m_nBumpmap = -1; + info.m_nBumpFrame = -1; + info.m_nBumpTransform = -1; + info.m_nEnvmapContrast = ENVMAPCONTRAST; + info.m_nEnvmapSaturation = ENVMAPSATURATION; + info.m_nAlphaTestReference = ALPHATESTREFERENCE; + info.m_nVertexAlphaTest = VERTEXALPHATEST; + info.m_nFlashlightTexture = FLASHLIGHTTEXTURE; + info.m_nFlashlightTextureFrame = FLASHLIGHTTEXTUREFRAME; + info.m_nHDRColorScale = HDRCOLORSCALE; + info.m_nPhongExponent = -1; + info.m_nPhongExponentTexture = -1; + info.m_nDiffuseWarpTexture = -1; + info.m_nPhongWarpTexture = -1; + info.m_nPhongBoost = -1; + info.m_nPhongFresnelRanges = -1; + info.m_nPhong = -1; + info.m_nPhongTint = -1; + info.m_nPhongAlbedoTint = -1; + info.m_nSelfIllumEnvMapMask_Alpha = -1; + info.m_nAmbientOnly = -1; + info.m_nBaseMapAlphaPhongMask = -1; + info.m_nEnvmapFresnel = -1; + info.m_nSelfIllumMask = -1; + info.m_nAmbientOcclusion = -1; + info.m_nBaseMapLuminancePhongMask = -1; + + info.m_nDistanceAlpha = DISTANCEALPHA; + info.m_nDistanceAlphaFromDetail = DISTANCEALPHAFROMDETAIL; + info.m_nSoftEdges = SOFTEDGES; + info.m_nEdgeSoftnessStart = EDGESOFTNESSSTART; + info.m_nEdgeSoftnessEnd = EDGESOFTNESSEND; + info.m_nScaleEdgeSoftnessBasedOnScreenRes = SCALEEDGESOFTNESSBASEDONSCREENRES; + + info.m_nGlow = GLOW; + info.m_nGlowColor = GLOWCOLOR; + info.m_nGlowAlpha = GLOWALPHA; + info.m_nGlowStart = GLOWSTART; + info.m_nGlowEnd = GLOWEND; + info.m_nGlowX = GLOWX; + info.m_nGlowY = GLOWY; + + info.m_nOutline = OUTLINE; + info.m_nOutlineColor = OUTLINECOLOR; + info.m_nOutlineAlpha = OUTLINEALPHA; + info.m_nOutlineStart0 = OUTLINESTART0; + info.m_nOutlineStart1 = OUTLINESTART1; + info.m_nOutlineEnd0 = OUTLINEEND0; + info.m_nOutlineEnd1 = OUTLINEEND1; + info.m_nScaleOutlineSoftnessBasedOnScreenRes = SCALEOUTLINESOFTNESSBASEDONSCREENRES; + + info.m_nSeparateDetailUVs = SEPARATEDETAILUVS; + + info.m_nLinearWrite = LINEARWRITE; + info.m_nGammaColorRead = GAMMACOLORREAD; + + info.m_nReceiveFlashlight = RECEIVEFLASHLIGHT; + info.m_nSinglePassFlashlight = SINGLEPASSFLASHLIGHT; + + info.m_nShaderSrgbRead360 = SHADERSRGBREAD360; + info.m_nDisplacementMap = DISPLACEMENTMAP; + } + + SHADER_INIT_PARAMS() + { + VertexLitGeneric_DX9_Vars_t vars; + SetupVars( vars ); + InitParamsVertexLitGeneric_DX9( this, params, pMaterialName, false, vars ); + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + VertexLitGeneric_DX9_Vars_t vars; + SetupVars( vars ); + InitVertexLitGeneric_DX9( this, params, false, vars ); + } + + SHADER_DRAW + { + VertexLitGeneric_DX9_Vars_t vars; + SetupVars( vars ); + + if ( ( pShaderShadow == NULL ) && ( pShaderAPI != NULL ) && (params[RECEIVEFLASHLIGHT]->GetIntValue() == 0) && pShaderAPI->InFlashlightMode() && !IsX360() ) // Not snapshotting && flashlight pass + { + // Don't go in here on the 360 with single-pass flashlight, because there is no 2nd draw call for this material. + // FIXME: Is the !IsX360() test too broad? + Draw( false ); + } + else + { + DrawVertexLitGeneric_DX9( this, params, pShaderAPI, pShaderShadow, false, vars, vertexCompression, pContextDataPtr ); + } + } +END_SHADER diff --git a/materialsystem/stdshaders/unlitgeneric_notexture_ps2x.fxc b/materialsystem/stdshaders/unlitgeneric_notexture_ps2x.fxc new file mode 100644 index 00000000..61256570 --- /dev/null +++ b/materialsystem/stdshaders/unlitgeneric_notexture_ps2x.fxc @@ -0,0 +1,13 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#include "common_ps_fxc.h" + +struct PS_INPUT +{ + float4 vColor0 : COLOR0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + return FinalOutput( i.vColor0, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} \ No newline at end of file diff --git a/materialsystem/stdshaders/unlitgeneric_ps2x.fxc b/materialsystem/stdshaders/unlitgeneric_ps2x.fxc new file mode 100644 index 00000000..1a52e9b5 --- /dev/null +++ b/materialsystem/stdshaders/unlitgeneric_ps2x.fxc @@ -0,0 +1,18 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#include "common_ps_fxc.h" + +sampler TextureSampler : register( s0 ); + +struct PS_INPUT +{ + float4 vColor0 : COLOR0; + float2 vTexCoord0 : TEXCOORD0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float4 result = i.vColor0 * tex2D( TextureSampler, i.vTexCoord0 ); + + return FinalOutput( result, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} \ No newline at end of file diff --git a/materialsystem/stdshaders/unlitgeneric_vs20.fxc b/materialsystem/stdshaders/unlitgeneric_vs20.fxc new file mode 100644 index 00000000..cb893578 --- /dev/null +++ b/materialsystem/stdshaders/unlitgeneric_vs20.fxc @@ -0,0 +1,123 @@ +// STATIC: "VERTEXCOLOR" "0..1" +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "SKINNING" "0..1" +// DYNAMIC: "TESSELLATION" "0..2" [vs30] [PC] +// DYNAMIC: "TESSELLATION" "0..0" [XBOX] +// DYNAMIC: "TESSELLATION" "0..0" [vs20] [PC] + +// SKIP: $TESSELLATION && $VERTEXCOLOR + +#include "common_fog_vs_fxc.h" +#include "common_vs_fxc.h" + +static const int g_FogType = DOWATERFOG; +static const bool g_bSkinning = SKINNING ? true : false; + +const float4 cBaseTextureTransform[2] : register( SHADER_SPECIFIC_CONST_0 ); +const float4 cMaskTextureTransform[2] : register( SHADER_SPECIFIC_CONST_2 ); +const float4 cDetailTextureTransform[2] : register( SHADER_SPECIFIC_CONST_4 ); + +#if TESSELLATION + +#include "tessellation_vs_fxc.h" + +const float4 g_SubDControls : register( SHADER_SPECIFIC_CONST_9 ); +sampler2D BezierSampler : register( s1 ); +sampler2D DispSampler : register( s2 ); +// VS_INPUT defined in header + +#else // no TESSELLATION + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vNormal : NORMAL; +#if VERTEXCOLOR + float4 vColor : COLOR0; +#endif + float4 vTexCoord0 : TEXCOORD0; +}; + +#endif + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; + float2 vTexCoord0 : TEXCOORD0; + float2 vTexCoord1 : TEXCOORD1; + float2 vTexCoord2 : TEXCOORD2; + float2 vTexCoord3 : TEXCOORD3; + + float4 vColor : COLOR0; + +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + float fog : FOG; +#endif + + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog +}; + + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 worldPos; + float3 worldNormal; + float2 vTexCoord0; + float4 vColor; + + #if TESSELLATION + { + float flBiTangentSign; + float3 worldTangentS, worldTangentT; + float2 vDetailCoord; + float flWrinkleWeight; + vColor = float4(1,1,1,1); + + EvaluateSubdivisionSurface( v, g_SubDControls.x, g_SubDControls.y, g_SubDControls.z, BezierSampler, DispSampler, + worldNormal, worldPos, worldTangentS, worldTangentT, flBiTangentSign, + flWrinkleWeight, vTexCoord0, vDetailCoord ); + } + #else // no TESSELLATION + { + //------------------------------------------------------------------------------ + // Vertex blending + //------------------------------------------------------------------------------ + SkinPosition( g_bSkinning, v.vPos, v.vBoneWeights, v.vBoneIndices, worldPos ); + vTexCoord0 = v.vTexCoord0; +#if VERTEXCOLOR + vColor = v.vColor; +#endif + } + #endif + + o.vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + o.worldPos_projPosZ = float4( worldPos.xyz, o.vProjPos.z ); + + //------------------------------------------------------------------------------ + // Fog + //------------------------------------------------------------------------------ +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + o.fog = CalcFixedFunctionFog( worldPos, g_FogType ); +#endif + + //------------------------------------------------------------------------------ + // Texture coord transforms + //------------------------------------------------------------------------------ + o.vTexCoord0 = mul( vTexCoord0, (float2x4)cBaseTextureTransform ); + o.vTexCoord3 = mul( vTexCoord0, (float2x4)cDetailTextureTransform ); + + o.vColor = cModulationColor; + +#if VERTEXCOLOR + o.vColor *= v.vColor; +#endif + + return o; +} + + + diff --git a/materialsystem/stdshaders/unlittwotexture_dx9.cpp b/materialsystem/stdshaders/unlittwotexture_dx9.cpp new file mode 100644 index 00000000..431d94b6 --- /dev/null +++ b/materialsystem/stdshaders/unlittwotexture_dx9.cpp @@ -0,0 +1,283 @@ +//===== Copyright © 1996-2007, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" +#include "cloak_blended_pass_helper.h" +#include "cpp_shader_constant_register_map.h" + +#include "unlittwotexture_vs20.inc" +#include "unlittwotexture_ps20.inc" +#include "unlittwotexture_ps20b.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( UnlitTwoTexture, UnlitTwoTexture_DX9 ) +BEGIN_VS_SHADER( UnlitTwoTexture_DX9, "Help for UnlitTwoTexture_DX9" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( TEXTURE2, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "second texture" ) + SHADER_PARAM( FRAME2, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $texture2" ) + SHADER_PARAM( TEXTURE2TRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$texture2 texcoord transform" ) + + // Cloak Pass + SHADER_PARAM( CLOAKPASSENABLED, SHADER_PARAM_TYPE_BOOL, "0", "Enables cloak render in a second pass" ) + SHADER_PARAM( CLOAKFACTOR, SHADER_PARAM_TYPE_FLOAT, "0.0", "" ) + SHADER_PARAM( CLOAKCOLORTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Cloak color tint" ) + SHADER_PARAM( REFRACTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "2", "" ) + END_SHADER_PARAMS + + SHADER_FALLBACK + { + return 0; + } + + // Cloak Pass + void SetupVarsCloakBlendedPass( CloakBlendedPassVars_t &info ) + { + info.m_nCloakFactor = CLOAKFACTOR; + info.m_nCloakColorTint = CLOAKCOLORTINT; + info.m_nRefractAmount = REFRACTAMOUNT; + } + + bool NeedsPowerOfTwoFrameBufferTexture( IMaterialVar **params, bool bCheckSpecificToThisFrame ) const + { + if ( params[CLOAKPASSENABLED]->GetIntValue() ) // If material supports cloaking + { + if ( bCheckSpecificToThisFrame == false ) // For setting model flag at load time + return true; + else if ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) // Per-frame check + return true; + // else, not cloaking this frame, so check flag2 in case the base material still needs it + } + + // Check flag2 if not drawing cloak pass + return IS_FLAG2_SET( MATERIAL_VAR2_NEEDS_POWER_OF_TWO_FRAME_BUFFER_TEXTURE ); + } + + bool IsTranslucent( IMaterialVar **params ) const + { + if ( params[CLOAKPASSENABLED]->GetIntValue() ) // If material supports cloaking + { + if ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) // Per-frame check + return true; + // else, not cloaking this frame, so check flag in case the base material still needs it + } + + // Check flag if not drawing cloak pass + return IS_FLAG_SET( MATERIAL_VAR_TRANSLUCENT ); + } + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + + // Cloak Pass + if ( !params[CLOAKPASSENABLED]->IsDefined() ) + { + params[CLOAKPASSENABLED]->SetIntValue( 0 ); + } + else if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + InitParamsCloakBlendedPass( this, params, pMaterialName, info ); + } + } + + SHADER_INIT + { + if (params[BASETEXTURE]->IsDefined()) + LoadTexture( BASETEXTURE ); + if (params[TEXTURE2]->IsDefined()) + LoadTexture( TEXTURE2 ); + + // Cloak Pass + if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + InitCloakBlendedPass( this, params, info ); + } + } + + SHADER_DRAW + { + // Skip the standard rendering if cloak pass is fully opaque + bool bDrawStandardPass = true; + if ( params[CLOAKPASSENABLED]->GetIntValue() && ( pShaderShadow == NULL ) ) // && not snapshotting + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + if ( CloakBlendedPassIsFullyOpaque( params, info ) ) + { + bDrawStandardPass = false; + } + } + + // Skip flashlight pass for unlit stuff + bool bNewFlashlightPath = IsX360(); + if ( bDrawStandardPass && ( pShaderShadow == NULL ) && ( pShaderAPI != NULL ) && + !bNewFlashlightPath && ( pShaderAPI->InFlashlightMode() ) ) // not snapshotting && flashlight pass) + { + bDrawStandardPass = false; + } + + // Standard rendering pass + if ( bDrawStandardPass ) + { + BlendType_t nBlendType = EvaluateBlendRequirements( BASETEXTURE, true ); + bool bFullyOpaque = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !IS_FLAG_SET(MATERIAL_VAR_ALPHATEST); //dest alpha is free for special use + + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); + + s_pShaderShadow->EnableSRGBWrite( true ); + + // Either we've got a constant modulation or we've got a texture alpha on either texture + if ( IsAlphaModulating() || IS_FLAG_SET( MATERIAL_VAR_TRANSLUCENT ) || TextureIsTranslucent( BASETEXTURE, true ) || TextureIsTranslucent( TEXTURE2, true ) ) + { + if ( IS_FLAG_SET(MATERIAL_VAR_ADDITIVE) ) + { + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + } + else + { + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + } + else + { + if ( IS_FLAG_SET(MATERIAL_VAR_ADDITIVE) ) + { + EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); + } + else + { + DisableAlphaBlending( ); + } + } + + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + if (IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR )) + { + flags |= VERTEX_COLOR; + } + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + // If this is set, blend with the alpha channels of the textures and modulation color + bool bTranslucent = IsAlphaModulating() || IS_FLAG_SET( MATERIAL_VAR_TRANSLUCENT ) || TextureIsTranslucent( BASETEXTURE, true ) || TextureIsTranslucent( TEXTURE2, true ); + + int nLightingPreviewMode = IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER0 ) + 2 * IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER1 ); + + DECLARE_STATIC_VERTEX_SHADER( unlittwotexture_vs20 ); + SET_STATIC_VERTEX_SHADER( unlittwotexture_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( unlittwotexture_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( TRANSLUCENT, bTranslucent ); + SET_STATIC_PIXEL_SHADER_COMBO( LIGHTING_PREVIEW, nLightingPreviewMode ); + SET_STATIC_PIXEL_SHADER( unlittwotexture_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( unlittwotexture_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( TRANSLUCENT, bTranslucent ); + SET_STATIC_PIXEL_SHADER_COMBO( LIGHTING_PREVIEW, nLightingPreviewMode ); + SET_STATIC_PIXEL_SHADER( unlittwotexture_ps20 ); + } + + DefaultFog(); + + pShaderShadow->EnableAlphaWrites( bFullyOpaque ); + + PI_BeginCommandBuffer(); + PI_SetModulationPixelShaderDynamicState_LinearColorSpace( 1 ); + PI_EndCommandBuffer(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + BindTexture( SHADER_SAMPLER1, TEXTURE2, FRAME2 ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BASETEXTURETRANSFORM ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, TEXTURE2TRANSFORM ); + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + float vEyePos_SpecExponent[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + vEyePos_SpecExponent[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + + int numBones = pShaderAPI->GetCurrentNumBones(); + + bool bWorldNormal = pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_ENABLE_FIXED_LIGHTING ) == ENABLE_FIXED_LIGHTING_OUTPUTNORMAL_AND_DEPTH; + if ( IsPC() && bWorldNormal ) + { + float vEyeDir[4]; + pShaderAPI->GetWorldSpaceCameraDirection( vEyeDir ); + + float flFarZ = pShaderAPI->GetFarZ(); + vEyeDir[0] /= flFarZ; // Divide by farZ for SSAO algorithm + vEyeDir[1] /= flFarZ; + vEyeDir[2] /= flFarZ; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, vEyeDir ); + } + + DECLARE_DYNAMIC_VERTEX_SHADER( unlittwotexture_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, numBones > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( WORLD_NORMAL, bWorldNormal ); + SET_DYNAMIC_VERTEX_SHADER( unlittwotexture_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( unlittwotexture_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bFullyOpaque && pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( unlittwotexture_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( unlittwotexture_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( unlittwotexture_ps20 ); + } + } + Draw(); + } + else + { + // Skip this pass! + Draw( false ); + } + + // Cloak Pass + if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + // If ( snapshotting ) or ( we need to draw this frame ) + if ( ( pShaderShadow != NULL ) || ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + DrawCloakBlendedPass( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else // We're not snapshotting and we don't need to draw this frame + { + // Skip this pass! + Draw( false ); + } + } + } +END_SHADER diff --git a/materialsystem/stdshaders/unlittwotexture_ps2x.fxc b/materialsystem/stdshaders/unlittwotexture_ps2x.fxc new file mode 100644 index 00000000..bf0c6af4 --- /dev/null +++ b/materialsystem/stdshaders/unlittwotexture_ps2x.fxc @@ -0,0 +1,79 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "TRANSLUCENT" "0..1" +// STATIC: "LIGHTING_PREVIEW" "0..3" [PC] +// STATIC: "LIGHTING_PREVIEW" "0..0" [XBOX] + +#include "common_fog_ps_fxc.h" +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] + +#if defined( SHADER_MODEL_PS_2_0 ) + #define WRITE_DEPTH_TO_DESTALPHA 0 +#endif + +#include "common_ps_fxc.h" +#include "shader_constant_register_map.h" + +const HALF4 g_DiffuseModulation : register( c1 ); +#if !FLASHLIGHT + // we don't use these with HDR. + const HALF3 g_EnvmapContrast : register( c2 ); + const HALF3 g_EnvmapSaturation : register( c3 ); +#endif + +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT ); + +const float4 g_FlashlightAttenuationFactors : register( c22 ); +const HALF3 g_FlashlightPos : register( c23 ); +const float4x4 g_FlashlightWorldToTexture : register( c24 ); // through c27 + +sampler BaseTextureSampler : register( s0 ); +sampler BaseTextureSampler2 : register( s1 ); + +struct PS_INPUT +{ + float4 projPos : POSITION; // Projection-space position + HALF2 baseTexCoord : TEXCOORD0; // Base texture coordinate + HALF2 baseTexCoord2 : TEXCOORD1; // Base texture coordinate + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for water fog dest alpha + +#if defined( _X360 ) //matching pixel shader inputs to vertex shader outputs to avoid shader patches + float4 vColor : COLOR0; +#endif +}; + +#if LIGHTING_PREVIEW == 2 +LPREVIEW_PS_OUT main( PS_INPUT i ) : COLOR +#else +float4 main( PS_INPUT i ) : COLOR +#endif +{ + +#if LIGHTING_PREVIEW == 1 + return FinalOutput( float4( 0.0f, 0.0f, 0.0f, 1.0f ), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_LINEAR ); +#endif +#if LIGHTING_PREVIEW == 2 + LPREVIEW_PS_OUT ret; + ret.flags=float4(1,1,1,1); + ret.color=float4( 0.0f, 0.0f, 0.0f, 1.0f ); + ret.normal=float4( 0.0f, 0.0f, 1.0f, 1.0f ); + ret.position=float4( i.worldPos_projPosZ.xyz, 1.0f ); + return FinalOutput( ret, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +#endif +#if (LIGHTING_PREVIEW == 0) || ( LIGHTING_PREVIEW == 3 ) + float4 baseColor = tex2D( BaseTextureSampler, i.baseTexCoord.xy ); + float4 baseColor2 = tex2D( BaseTextureSampler2, i.baseTexCoord2.xy ); + float4 result = baseColor * baseColor2 * g_DiffuseModulation; + + // This material can only get a non-opaque alpha if the material is marked as translucent +# if ( TRANSLUCENT == 0 ) + result.a = 1.0f; +# endif + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos_SpecExponent.xyz, i.worldPos_projPosZ.xyz, i.worldPos_projPosZ.w ); + return FinalOutput( result, fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, (WRITE_DEPTH_TO_DESTALPHA != 0), i.worldPos_projPosZ.w ); +#endif +} + diff --git a/materialsystem/stdshaders/unlittwotexture_vs20.fxc b/materialsystem/stdshaders/unlittwotexture_vs20.fxc new file mode 100644 index 00000000..59715345 --- /dev/null +++ b/materialsystem/stdshaders/unlittwotexture_vs20.fxc @@ -0,0 +1,76 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +#include "common_fog_vs_fxc.h" +// DYNAMIC: "SKINNING" "0..1" +// DYNAMIC: "WORLD_NORMAL" "0..1" [PC] +// DYNAMIC: "WORLD_NORMAL" "0..0" [XBOX] + +#include "common_vs_fxc.h" + +static const bool g_bSkinning = SKINNING ? true : false; +static const int g_FogType = DOWATERFOG; + +const float4 cBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_0 ); // 0 & 1 +const float4 cBaseTexCoordTransform2[2] : register( SHADER_SPECIFIC_CONST_2 ); // 2 & 3 + +const float4 g_vEyeVector : register( SHADER_SPECIFIC_CONST_4 ); + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + // make these float2's and stick the [n n 0 1] in the dot math. + float4 vTexCoord0 : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; // Projection-space position +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + float fog : FOG; +#endif + HALF2 baseTexCoord : TEXCOORD0; // Base texture coordinate + HALF2 baseTexCoord2 : TEXCOORD1; // Base texture coordinate + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for water fog dest alpha + + float4 vColor : COLOR0; +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float4 vPosition = v.vPos; + + // Perform skinning + float3 worldNormal, worldPos; + SkinPosition( g_bSkinning, vPosition, v.vBoneWeights, v.vBoneIndices, worldPos ); + + // Transform into projection space + float4 projPos = mul( float4( worldPos, 1 ), cViewProj ); + o.projPos = projPos; + +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + o.fog = CalcFixedFunctionFog( worldPos, g_FogType ); +#endif + + // Needed for water fog alpha; + o.worldPos_projPosZ = float4( worldPos.xyz, o.projPos.z ); // FIXME: we shouldn't have to compute this all thie time. + + #if WORLD_NORMAL + { + o.worldPos_projPosZ.w = dot( g_vEyeVector, worldPos.xyz - cEyePos.xyz ); // Linear depth + } + #endif + + o.baseTexCoord.x = dot( v.vTexCoord0, cBaseTexCoordTransform[0] ); // Base texture coordinates + o.baseTexCoord.y = dot( v.vTexCoord0, cBaseTexCoordTransform[1] ); + o.baseTexCoord2.x = dot( v.vTexCoord0, cBaseTexCoordTransform2[0] ); // Secondary texture coordinates + o.baseTexCoord2.y = dot( v.vTexCoord0, cBaseTexCoordTransform2[1] ); + + o.vColor = cModulationColor; + + return o; +} diff --git a/materialsystem/stdshaders/vertexlit_and_unlit_generic_bump_ps2x.fxc b/materialsystem/stdshaders/vertexlit_and_unlit_generic_bump_ps2x.fxc new file mode 100644 index 00000000..16454f15 --- /dev/null +++ b/materialsystem/stdshaders/vertexlit_and_unlit_generic_bump_ps2x.fxc @@ -0,0 +1,359 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "CUBEMAP" "0..1" +// STATIC: "DIFFUSELIGHTING" "0..1" +// STATIC: "LIGHTWARPTEXTURE" "0..1" +// STATIC: "SELFILLUM" "0..1" +// STATIC: "SELFILLUMFRESNEL" "0..1" +// STATIC: "NORMALMAPALPHAENVMAPMASK" "0..1" +// STATIC: "HALFLAMBERT" "0..1" +// STATIC: "FLASHLIGHT" "0..1" +// STATIC: "DETAILTEXTURE" "0..1" +// STATIC: "DETAIL_BLEND_MODE" "0..6" +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps20b] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps30] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..0" [ps20b] [XBOX] +// STATIC: "SHADER_SRGB_READ" "0..1" [XBOX] +// STATIC: "SHADER_SRGB_READ" "0..0" [PC] +// STATIC: "STATICLIGHT3" "0..0" [XBOX] +// STATIC: "STATICLIGHT3" "0..0" [PC] +// STATIC: "WORLD_NORMAL" "0..0" [ps20] [PC] +// STATIC: "WORLD_NORMAL" "0..0" [ps20b] [PC] +// STATIC: "WORLD_NORMAL" "0..1" [ps30] [PC] +// STATIC: "WORLD_NORMAL" "0..0" [XBOX] + +// DYNAMIC: "WRITEWATERFOGTODESTALPHA" "0..1" +// DYNAMIC: "NUM_LIGHTS" "0..2" [ps20] +// DYNAMIC: "NUM_LIGHTS" "0..4" [ps20b] +// DYNAMIC: "NUM_LIGHTS" "0..4" [ps30] +// DYNAMIC: "AMBIENT_LIGHT" "0..1" +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps20b] +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps30] [PC] + +// DYNAMIC: "UBERLIGHT" "0..1" [ps30] [PC] + +// We don't use light combos when doing the flashlight +// SKIP: ( $FLASHLIGHT != 0 ) && ( $NUM_LIGHTS > 0 ) [PC] + +// We don't care about flashlight depth unless the flashlight is on +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 ) [ps20b] +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 ) [ps30] + +// We don't care about uberlight unless the flashlight is on +// SKIP: ( $FLASHLIGHT == 0 ) && ( $UBERLIGHT == 1 ) [ps30] + +// SKIP: (! $DETAILTEXTURE) && ( $DETAIL_BLEND_MODE != 0 ) + +// Don't do diffuse warp on flashlight + +// Only warp diffuse if we have it at all +// SKIP: ( $DIFFUSELIGHTING == 0 ) && ( $LIGHTWARPTEXTURE == 1 ) + +// Skip this since it blows ps20 instruction limits +// SKIP: ( $SELFILLUMFRESNEL == 1 ) && ( $LIGHTWARPTEXTURE == 1 ) + +// Only need self illum fresnel when self illum enabled +// SKIP: ( $SELFILLUM == 0 ) && ( $SELFILLUMFRESNEL == 1 ) +// SKIP: ( $FLASHLIGHT == 1 ) && ( $SELFILLUMFRESNEL == 1 ) [PC] +// SKIP: ( $SELFILLUMFRESNEL == 1 ) && ( $DETAILTEXTURE == 1 ) +// SKIP: ( $SELFILLUMFRESNEL == 1 ) && ( $NORMALMAPALPHAENVMAPMASK == 1 ) + +// Only do world normals in constrained case +// SKIP: ( $WORLD_NORMAL == 1 ) && ( $FLASHLIGHTSHADOWS != 0 ) && ( $AMBIENT_LIGHT != 0 ) && ( $NUM_LIGHTS != 0 ) [ps30] + +#include "common_fog_ps_supportsvertexfog_fxc.h" +#include "shader_constant_register_map.h" +#include "common_flashlight_fxc.h" +#include "common_vertexlitgeneric_dx9.h" + + +// new-UP-bump-basis +static const HALF3 upBumpBasis[3] = +{ + HALF3( 0.0f, 0.81649661064147949f, OO_SQRT_3 ), + HALF3( -0.70710676908493042f, -0.40824833512306213f, OO_SQRT_3 ), + HALF3( 0.7071068286895752f, -0.40824821591377258f, OO_SQRT_3 ) +}; + + +const float4 g_EnvmapTint : register( c0 ); +const float4 g_DiffuseModulation : register( c1 ); +const float4 g_EnvmapContrast_ShadowTweaks : register( c2 ); +const float3 g_EnvmapSaturation : register( c3 ); +const float4 g_SelfIllumTint_and_BlendFactor: register( c4 ); +#define g_SelfIllumTint ( g_SelfIllumTint_and_BlendFactor.rgb) +#define g_DetailBlendFactor (g_SelfIllumTint_and_BlendFactor.w) + + + +const float3 cAmbientCube[6] : register( c5 ); + +// 11, 12 not used? +#if ( SELFILLUMFRESNEL == 1 ) + const float4 g_SelfIllumScaleBiasExpBrightness : register( c11 ); +#endif + +const float4 g_ShaderControls : register( c12 ); +#define g_fInverseBlendTintByBaseAlpha g_ShaderControls.x +#define g_fWriteDepthToAlpha g_ShaderControls.y +//#define g_fWriteWaterFogToDestAlpha g_ShaderControls.z + + +// 2 registers each - 6 registers total +PixelShaderLightInfo cLightInfo[3] : register( c13 ); // through c18 + +const float4 g_EyePos_BaseTextureTranslucency : register( c20 ); +const float4 g_FogParams : register( c21 ); + +const float4 g_FlashlightAttenuationFactors : register( c22 ); +const float3 g_FlashlightPos : register( c23 ); +const float4x4 g_FlashlightWorldToTexture : register( c24 ); // through c27 + +#if UBERLIGHT && defined( SHADER_MODEL_PS_3_0 ) +const float3 g_vSmoothEdge0 : register( PSREG_UBERLIGHT_SMOOTH_EDGE_0 ); // ps_3_0 and up (over 32 registers) +const float3 g_vSmoothEdge1 : register( PSREG_UBERLIGHT_SMOOTH_EDGE_1 ); +const float3 g_vSmoothOneOverWidth : register( PSREG_UBERLIGHT_SMOOTH_EDGE_OOW ); +const float4 g_vShearRound : register( PSREG_UBERLIGHT_SHEAR_ROUND ); +const float4 g_aAbB : register( PSREG_UBERLIGHT_AABB ); +const float4x4 g_FlashlightWorldToLight : register( PSREG_UBERLIGHT_WORLD_TO_LIGHT ); +#endif + +sampler BaseTextureSampler : register( s0 ); +sampler EnvmapSampler : register( s1 ); +sampler DetailSampler : register( s2 ); +sampler BumpmapSampler : register( s3 ); +sampler EnvmapMaskSampler : register( s4 ); +sampler NormalizeSampler : register( s5 ); +sampler RandRotSampler : register( s6 ); // RandomRotation sampler +sampler FlashlightSampler : register( s7 ); +sampler ShadowDepthSampler : register( s8 ); // Flashlight shadow depth map sampler +sampler DiffuseWarpSampler : register( s9 ); // Lighting warp sampler (1D texture for diffuse lighting modification) + +struct PS_INPUT +{ + float4 baseTexCoord2_light0e01 : TEXCOORD0; + + #if STATICLIGHT3 + float4 light1e012_light0e2 : TEXCOORD1; + #else + float3 lightAtten : TEXCOORD1; + #endif + + float4 worldVertToEyeVectorXYZ_light2e0 : TEXCOORD2; + float4 vWorldNormal_light2e1 : TEXCOORD3; + float4 vWorldTangent : TEXCOORD4; +#if ((defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0))) + float4 vProjPos : TEXCOORD5; +#else + float3 vWorldBinormal : TEXCOORD5; +#endif + float4 worldPos_projPosZ : TEXCOORD6; + float4 detailTexCoord_atten3_or_light2e2_fogFactorW : TEXCOORD7; + +#if defined( _X360 ) +#if FLASHLIGHT + float4 flashlightSpacePos : TEXCOORD8; +#endif +#endif +}; + +float4 main( PS_INPUT i ) : COLOR +{ + bool bCubemap = CUBEMAP ? true : false; + bool bDiffuseLighting = DIFFUSELIGHTING ? true : false; + bool bDoDiffuseWarp = LIGHTWARPTEXTURE ? true : false; + bool bSelfIllum = SELFILLUM ? true : false; + bool bNormalMapAlphaEnvmapMask = NORMALMAPALPHAENVMAPMASK ? true : false; + bool bHalfLambert = HALFLAMBERT ? true : false; + bool bFlashlight = (FLASHLIGHT!=0) ? true : false; + bool bAmbientLight = AMBIENT_LIGHT ? true : false; + bool bDetailTexture = DETAILTEXTURE ? true : false; + int nNumLights = NUM_LIGHTS; + + float3 vWorldNormal = i.vWorldNormal_light2e1.xyz; + +#if ((defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0))) + float3 vWorldBinormal = cross( vWorldNormal, i.vWorldTangent.xyz ) * i.vWorldTangent.w; +#else + float3 vWorldBinormal = i.vWorldBinormal; +#endif + +#if STATICLIGHT3 + // Unpack vertex lighting + float3 cLight0 = float3( i.baseTexCoord2_light0e01.zw, i.light1e012_light0e2.w ); + float3 cLight1 = i.light1e012_light0e2.xyz; + float3 cLight2 = float3( i.worldVertToEyeVectorXYZ_light2e0.w, i.vWorldNormal_light2e1.w, i.detailTexCoord_atten3_or_light2e2_fogFactorW.z ); +#else + // Unpack four light attenuations + float4 vLightAtten = float4( i.lightAtten, i.detailTexCoord_atten3_or_light2e2_fogFactorW.z ); +#endif + + float4 baseColor = float4( 1.0f, 1.0f, 1.0f, 1.0f ); + baseColor = tex2Dsrgb( BaseTextureSampler, i.baseTexCoord2_light0e01.xy ); + +#if DETAILTEXTURE + float4 detailColor = tex2D( DetailSampler, i.detailTexCoord_atten3_or_light2e2_fogFactorW.xy ); + baseColor = TextureCombine( baseColor, detailColor, DETAIL_BLEND_MODE, g_DetailBlendFactor ); +#endif + + float specularFactor = 1.0f; + float4 normalTexel = tex2D( BumpmapSampler, i.baseTexCoord2_light0e01.xy ); + float3 tangentSpaceNormal = normalTexel * 2.0f - 1.0f; + + if ( bNormalMapAlphaEnvmapMask ) + specularFactor = normalTexel.a; + + float3 diffuseLighting = float3( 1.0f, 1.0f, 1.0f ); + float3 worldSpaceNormal = float3( 0.0f, 0.0f, 1.0f ); + if ( bDiffuseLighting ) + { + worldSpaceNormal = Vec3TangentToWorld( tangentSpaceNormal.xyz, vWorldNormal, i.vWorldTangent, vWorldBinormal ); + +#if ( defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) ) + worldSpaceNormal = normalize( worldSpaceNormal ); +#else + worldSpaceNormal = NormalizeWithCubemap( NormalizeSampler, worldSpaceNormal ); +#endif + +#if STATICLIGHT3 + float3 dp; + dp.x = saturate( dot( tangentSpaceNormal, upBumpBasis[0] ) ); + dp.y = saturate( dot( tangentSpaceNormal, upBumpBasis[1] ) ); + dp.z = saturate( dot( tangentSpaceNormal, upBumpBasis[2] ) ); + dp *= dp; + + diffuseLighting.rgb = dp.x * cLight0 + dp.y * cLight1 + dp.z * cLight2; + + if ( bDoDiffuseWarp ) + { + float fDiffuseScale = 0.5 * length( diffuseLighting.rgb ); + diffuseLighting.rgb *= 2.0 * tex2D( DiffuseWarpSampler, float2( fDiffuseScale, 0 ) ); + } +#else + diffuseLighting = PixelShaderDoLighting( i.worldPos_projPosZ.xyz, worldSpaceNormal, + float3( 0.0f, 0.0f, 0.0f ), false, bAmbientLight, vLightAtten, + cAmbientCube, NormalizeSampler, nNumLights, cLightInfo, bHalfLambert, + bDoDiffuseWarp, DiffuseWarpSampler ); +#endif + } + + float3 albedo = float3( 1.0f, 1.0f, 1.0f ); + float alpha = 1.0f; + albedo *= baseColor; + if ( !bSelfIllum ) + { + alpha *= lerp( 1.0f, baseColor.a, g_EyePos_BaseTextureTranslucency.w ); + } + +#if FLASHLIGHT + if( bFlashlight ) + { + int nShadowSampleLevel = 0; + bool bDoShadows = false; + float2 vProjPos = float2(0, 0); +// On ps_2_b, we can do shadow mapping +#if ( FLASHLIGHTSHADOWS && (defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) ) ) + nShadowSampleLevel = FLASHLIGHTDEPTHFILTERMODE; + bDoShadows = FLASHLIGHTSHADOWS; + vProjPos = i.vProjPos.xy / i.vProjPos.w; // Screen-space position for shadow map noise +#endif + worldSpaceNormal = Vec3TangentToWorldNormalized( tangentSpaceNormal.xyz, vWorldNormal, i.vWorldTangent, vWorldBinormal ); + +#if defined ( _X360 ) + float4 flashlightSpacePosition = i.flashlightSpacePos; +#else + float4 flashlightSpacePosition = mul( float4( i.worldPos_projPosZ.xyz, 1.0f ), g_FlashlightWorldToTexture ); +#endif + + float3 flashlightColor = DoFlashlight( g_FlashlightPos, i.worldPos_projPosZ.xyz, flashlightSpacePosition, + worldSpaceNormal, g_FlashlightAttenuationFactors.xyz, + g_FlashlightAttenuationFactors.w, FlashlightSampler, ShadowDepthSampler, + RandRotSampler, nShadowSampleLevel, bDoShadows, false, vProjPos, false, g_EnvmapContrast_ShadowTweaks ); + +#if UBERLIGHT && defined( SHADER_MODEL_PS_3_0 ) + float4 uberLightPosition = mul( float4( i.worldPos_projPosZ.xyz, 1.0f ), g_FlashlightWorldToLight ).yzxw; + flashlightColor *= uberlight( uberLightPosition, g_vSmoothEdge0, g_vSmoothEdge1, + g_vSmoothOneOverWidth, g_vShearRound.xy, g_aAbB, g_vShearRound.zw ); +#endif + + +#if defined ( _X360 ) + diffuseLighting += flashlightColor; +#else + diffuseLighting = flashlightColor; +#endif + + } +#endif + + // Optionally use basealpha to blend in the diffuse modulation (saturated add of g_fInverseBlendTintByBaseAlpha turns this on/off) + diffuseLighting *= lerp( float3( 1.0f, 1.0f, 1.0f ), g_DiffuseModulation.rgb, saturate( baseColor.a + g_fInverseBlendTintByBaseAlpha ) ); + + alpha *= g_DiffuseModulation.a; + + float3 diffuseComponent = albedo * diffuseLighting; + +#if !FLASHLIGHT || defined ( _X360 ) + if ( bSelfIllum ) + { + #if ( SELFILLUMFRESNEL == 1 ) // To free up the constant register...see top of file + // This will apply a fresnel term based on the vertex normal (not the per-pixel normal!) to help fake and internal glow look + #if ((defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0))) + float3 vVertexNormal = normalize( vWorldNormal.xyz ); + float flSelfIllumFresnel = ( pow( saturate( dot( vVertexNormal.xyz, normalize( i.worldVertToEyeVectorXYZ_light2e0.xyz ) ) ), g_SelfIllumScaleBiasExpBrightness.z ) * g_SelfIllumScaleBiasExpBrightness.x ) + g_SelfIllumScaleBiasExpBrightness.y; + + float3 selfIllumComponent = g_SelfIllumTint * albedo * g_SelfIllumScaleBiasExpBrightness.w; + diffuseComponent = lerp( diffuseComponent, selfIllumComponent, baseColor.a * saturate( flSelfIllumFresnel ) ); + #else + float3 vVertexNormal = vWorldNormal.xyz; + float flSelfIllumFresnel = ( pow( saturate( dot( vVertexNormal.xyz, ( i.worldVertToEyeVectorXYZ_light2e0.xyz ) ) ), g_SelfIllumScaleBiasExpBrightness.z ) * g_SelfIllumScaleBiasExpBrightness.x ) + g_SelfIllumScaleBiasExpBrightness.y; + + float3 selfIllumComponent = g_SelfIllumTint * albedo * g_SelfIllumScaleBiasExpBrightness.w; + diffuseComponent = lerp( diffuseComponent, selfIllumComponent, baseColor.a * saturate( flSelfIllumFresnel ) ); + #endif + #else + float3 selfIllumComponent = g_SelfIllumTint * albedo; + diffuseComponent = lerp( diffuseComponent, selfIllumComponent, baseColor.a ); + #endif + } +#endif + + float3 specularLighting = float3( 0.0f, 0.0f, 0.0f ); +#if !FLASHLIGHT || defined ( _X360 ) + if( bCubemap ) + { + worldSpaceNormal = Vec3TangentToWorld( tangentSpaceNormal.xyz, vWorldNormal, i.vWorldTangent, vWorldBinormal ); + + float3 reflectVect = CalcReflectionVectorUnnormalized( worldSpaceNormal, i.worldVertToEyeVectorXYZ_light2e0.xyz ); + + specularLighting = ENV_MAP_SCALE * texCUBE( EnvmapSampler, reflectVect ); + specularLighting *= specularFactor; + specularLighting *= g_EnvmapTint; + float3 specularLightingSquared = specularLighting * specularLighting; + specularLighting = lerp( specularLighting, specularLightingSquared, g_EnvmapContrast_ShadowTweaks ); + float3 greyScale = dot( specularLighting, float3( 0.299f, 0.587f, 0.114f ) ); + specularLighting = lerp( greyScale, specularLighting, g_EnvmapSaturation ); + } +#endif + + float3 result = diffuseComponent + specularLighting; + + float flVertexFogFactor = 0.0f; + #if ( !HARDWAREFOGBLEND && !DOPIXELFOG ) + { + flVertexFogFactor = i.detailTexCoord_atten3_or_light2e2_fogFactorW.w; + } + #endif + float fogFactor = CalcPixelFogFactorSupportsVertexFog( PIXELFOGTYPE, g_FogParams, g_EyePos_BaseTextureTranslucency.xyz, i.worldPos_projPosZ.xyz, i.worldPos_projPosZ.w, flVertexFogFactor ); + + #if WRITEWATERFOGTODESTALPHA && (PIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT) + alpha = fogFactor; + #endif + +#if ( ( defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) ) && WORLD_NORMAL ) + // Vertex normal + return float4( normalize( vWorldNormal ), i.worldPos_projPosZ.w ); +#else + return FinalOutput( float4( result.rgb, alpha ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, g_fWriteDepthToAlpha, i.worldPos_projPosZ.w ); +#endif +} diff --git a/materialsystem/stdshaders/vertexlit_and_unlit_generic_bump_vs20.fxc b/materialsystem/stdshaders/vertexlit_and_unlit_generic_bump_vs20.fxc new file mode 100644 index 00000000..d1d0988b --- /dev/null +++ b/materialsystem/stdshaders/vertexlit_and_unlit_generic_bump_vs20.fxc @@ -0,0 +1,269 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "HALFLAMBERT" "0..1" +// STATIC: "USE_WITH_2B" "0..1" +// STATIC: "DECAL" "0..1" [vs30] +// STATIC: "FLASHLIGHT" "0..1" [XBOX] +// STATIC: "NORMALIZEEYEVEC" "0..1" +// STATIC: "WORLD_NORMAL" "0..0" [vs20] [PC] +// STATIC: "WORLD_NORMAL" "0..1" [vs30] [PC] +// STATIC: "WORLD_NORMAL" "0..0" [XBOX] +// STATIC: "STATICLIGHT3" "0..0" // MAINTOL4DMERGEFIXME + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "SKINNING" "0..1" + +// DYNAMIC: "MORPHING" "0..1" [vs30] [ = pShaderAPI->IsHWMorphingEnabled() ] +// DYNAMIC: "TESSELLATION" "0..2" [vs30] [PC] +// DYNAMIC: "TESSELLATION" "0..0" [XBOX] +// DYNAMIC: "TESSELLATION" "0..0" [vs20] [PC] + +// When tessellating, we don't have room in the super-prim vertices for more colors, tex coords or objects space positions +// SKIP: ( $STATICLIGHT3 || $MORPHING || $SKINNING || $COMPRESSED_VERTS) && $TESSELLATION + +#include "common_fog_vs_supportsvertexfog_fxc.h" +#include "common_vs_fxc.h" + +static const bool g_bSkinning = SKINNING ? true : false; +static const int g_FogType = DOWATERFOG; + +const float4 cBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_0 ); // 0 & 1 + +const float4 g_vEyeVector : register( SHADER_SPECIFIC_CONST_2 ); + +const float4 cDetailTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_4 ); // 4 & 5 +const float4x4 g_FlashlightWorldToTexture : register( SHADER_SPECIFIC_CONST_6 ); // 6, 7, 8, 9 + +#ifdef SHADER_MODEL_VS_3_0 +// NOTE: cMorphTargetTextureDim.xy = target dimensions, +// cMorphTargetTextureDim.z = 4tuples/morph +const float3 cMorphTargetTextureDim : register( SHADER_SPECIFIC_CONST_10 ); +const float4 cMorphSubrect : register( SHADER_SPECIFIC_CONST_11 ); + +sampler2D morphSampler : register( D3DVERTEXTEXTURESAMPLER0, s0 ); +#endif + + + +#if TESSELLATION + +#include "tessellation_vs_fxc.h" +const float4 g_SubDControls : register( SHADER_SPECIFIC_CONST_3 ); +sampler2D BezierSampler : register( s1 ); +sampler2D DispSampler : register( s2 ); +// VS_INPUT defined in header + +#else // no TESSELLATION + +struct VS_INPUT +{ + // This is all of the stuff that we ever use. + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vNormal : NORMAL; + float4 vColor : COLOR0; + float3 vStaticLight : COLOR1; + #if STATICLIGHT3 + float3 vStaticLight2 : COLOR2; + float3 vStaticLight3 : COLOR3; + #endif + // make these float2's and stick the [n n 0 1] in the dot math. + float4 vTexCoord0 : TEXCOORD0; + float4 vTexCoord1 : TEXCOORD1; + float4 vTexCoord2 : TEXCOORD2; + float4 vTexCoord3 : TEXCOORD3; + float3 vTangentS : TANGENT; + float3 vTangentT : BINORMAL; + float4 vUserData : TANGENT; + // Position and normal/tangent deltas + float3 vPosFlex : POSITION1; + float3 vNormalFlex : NORMAL1; + #ifdef SHADER_MODEL_VS_3_0 + float vVertexID : POSITION2; + #endif +}; + +#endif // TESSELLATION + + +//----------------------------------------------------------------------------- +// Output vertex format +//----------------------------------------------------------------------------- +struct VS_OUTPUT +{ + // Stuff that isn't seen by the pixel shader + float4 projPos : POSITION; +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + float fog : FOG; +#endif + + // Stuff that is seen by the pixel shader + float4 baseTexCoord2_light0e01 : TEXCOORD0; + #if STATICLIGHT3 + float4 light1e012_light0e2 : TEXCOORD1; + #else + float3 lightAtten : TEXCOORD1; + #endif + float4 worldVertToEyeVectorXYZ_light2e0 : TEXCOORD2; + float4 vWorldNormal_light2e1 : TEXCOORD3; + float4 vWorldTangent : TEXCOORD4; + #if USE_WITH_2B + float4 vProjPos : TEXCOORD5; + #else + float3 vWorldBinormal : TEXCOORD5; + #endif + float4 worldPos_projPosZ : TEXCOORD6; + float4 detailTexCoord_atten3_or_light2e2_fogFactorW : TEXCOORD7; + +#if defined( _X360 ) && FLASHLIGHT + float4 flashlightSpacePos : TEXCOORD8; +#endif +}; + + +//----------------------------------------------------------------------------- +// Main shader entry point +//----------------------------------------------------------------------------- +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float4 vPosition, vTangent; + float3 vNormal, worldPos, worldNormal, worldTangentS, worldTangentT; + + #if ( TESSELLATION ) + { + float flDummyWrinkle; + EvaluateSubdivisionSurface( v, g_SubDControls.x, g_SubDControls.y, g_SubDControls.z, BezierSampler, DispSampler, + worldNormal, worldPos, worldTangentS, worldTangentT, vTangent.w, + flDummyWrinkle, o.baseTexCoord2_light0e01.xy, o.detailTexCoord_atten3_or_light2e2_fogFactorW.xy ); + } + #else // no TESSELLATION + { + vPosition = v.vPos; + + DecompressVertex_NormalTangent( v.vNormal, v.vUserData, vNormal, vTangent ); + + #if ( !defined( SHADER_MODEL_VS_3_0 ) || !MORPHING ) + { + ApplyMorph( v.vPosFlex, v.vNormalFlex, vPosition.xyz, vNormal, vTangent.xyz ); + } + #else + { + ApplyMorph( morphSampler, cMorphTargetTextureDim, cMorphSubrect, + v.vVertexID, v.vTexCoord2, vPosition.xyz, vNormal, vTangent.xyz ); + } + #endif + + // Perform skinning + SkinPositionNormalAndTangentSpace( g_bSkinning, vPosition, vNormal, vTangent, + v.vBoneWeights, v.vBoneIndices, worldPos, worldNormal, worldTangentS, worldTangentT ); + + // Always normalize since flex path is controlled by runtime + // constant not a shader combo and will always generate the normalization + worldNormal = normalize( worldNormal ); + worldTangentS = normalize( worldTangentS ); + worldTangentT = normalize( worldTangentT ); + + #if ( defined( SHADER_MODEL_VS_3_0 ) && MORPHING && DECAL ) + { + // Avoid z precision errors + worldPos += worldNormal * 0.05f * v.vTexCoord2.z; + } + #endif + + #if ( STATICLIGHT3 ) + { + // Adjust lighting data + float3 cStaticLight1 = DoLighting( worldPos, worldNormal, v.vStaticLight, true, false, false ); + float3 cStaticLight2 = DoLighting( worldPos, worldNormal, v.vStaticLight2, true, false, false ); + float3 cStaticLight3 = DoLighting( worldPos, worldNormal, v.vStaticLight3, true, false, false ); + + // Pack 3-streams of lighting data + o.baseTexCoord2_light0e01.zw = cStaticLight1.xy; + o.light1e012_light0e2.xyz = cStaticLight2.xyz; + o.light1e012_light0e2.w = cStaticLight1.z; + o.worldVertToEyeVectorXYZ_light2e0.w = cStaticLight3.x; + o.vWorldNormal_light2e1.w = cStaticLight3.y; + o.detailTexCoord_atten3_or_light2e2_fogFactorW.z = cStaticLight3.z; + } + #endif + + // Base texture coordinate transform + o.baseTexCoord2_light0e01.x = dot( v.vTexCoord0, cBaseTexCoordTransform[0] ); + o.baseTexCoord2_light0e01.y = dot( v.vTexCoord0, cBaseTexCoordTransform[1] ); + + // Detail texture coordinate transform + o.detailTexCoord_atten3_or_light2e2_fogFactorW.x = dot( v.vTexCoord0, cDetailTexCoordTransform[0] ); + o.detailTexCoord_atten3_or_light2e2_fogFactorW.y = dot( v.vTexCoord0, cDetailTexCoordTransform[1] ); + } + #endif // TESSELLATION + + // Transform into projection space + o.projPos = mul( float4( worldPos, 1 ), cViewProj ); + + o.vWorldNormal_light2e1.xyz = worldNormal.xyz; + + o.vWorldTangent = float4( worldTangentS.xyz, vTangent.w ); // Propagate binormal sign in world tangent.w + + #if ( USE_WITH_2B ) + { + o.vProjPos = o.projPos; + } + #else + { + o.vWorldBinormal.xyz = worldTangentT.xyz; + } + #endif + + #if ( STATICLIGHT3 == 0 ) + { + // Scalar light attenuation + o.lightAtten.x = GetVertexAttenForLight( worldPos, 0 ); + o.lightAtten.y = GetVertexAttenForLight( worldPos, 1 ); + o.lightAtten.z = GetVertexAttenForLight( worldPos, 2 ); + o.detailTexCoord_atten3_or_light2e2_fogFactorW.z = GetVertexAttenForLight( worldPos, 3 ); + } + #endif + + // Needed for water fog alpha and diffuse lighting + o.worldPos_projPosZ = float4( worldPos, o.projPos.z ); + + #if ( WORLD_NORMAL ) + { + o.worldPos_projPosZ.w = dot( g_vEyeVector, worldPos.xyz - cEyePos.xyz ); // Linear depth + } + #endif + + // Needed for cubemapping + parallax mapping + #if ( NORMALIZEEYEVEC == 1 ) + { + o.worldVertToEyeVectorXYZ_light2e0.xyz = normalize( cEyePos.xyz - worldPos.xyz ); + } + #else + { + o.worldVertToEyeVectorXYZ_light2e0.xyz = cEyePos.xyz - worldPos.xyz; + } + #endif + + #if ( HARDWAREFOGBLEND ) + { + o.fog = CalcFixedFunctionFog( worldPos, g_FogType ); + } + #endif + #if ( !DOPIXELFOG && !HARDWAREFOGBLEND ) + { + o.detailTexCoord_atten3_or_light2e2_fogFactorW.w = CalcNonFixedFunctionFog( worldPos, g_FogType ); + } + #endif + + #if ( defined( _X360 ) && FLASHLIGHT ) + { + o.flashlightSpacePos = mul( float4( worldPos, 1.0f ), g_FlashlightWorldToTexture ); + } + #endif + + + return o; +} diff --git a/materialsystem/stdshaders/vertexlit_and_unlit_generic_ps2x.fxc b/materialsystem/stdshaders/vertexlit_and_unlit_generic_ps2x.fxc new file mode 100644 index 00000000..506d0a10 --- /dev/null +++ b/materialsystem/stdshaders/vertexlit_and_unlit_generic_ps2x.fxc @@ -0,0 +1,560 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// +// +//===========================================================================// +// STATIC: "DETAILTEXTURE" "0..1" +// STATIC: "CUBEMAP" "0..1" +// STATIC: "DIFFUSELIGHTING" "0..1" +// STATIC: "ENVMAPMASK" "0..1" +// STATIC: "BASEALPHAENVMAPMASK" "0..1" +// STATIC: "SELFILLUM" "0..1" +// STATIC: "VERTEXCOLOR" "0..1" +// STATIC: "FLASHLIGHT" "0..1" +// STATIC: "SELFILLUM_ENVMAPMASK_ALPHA" "0..1" +// STATIC: "DETAIL_BLEND_MODE" "0..9" +// STATIC: "SEAMLESS_BASE" "0..1" +// STATIC: "SEAMLESS_DETAIL" "0..1" +// STATIC: "DISTANCEALPHA" "0..1" +// STATIC: "DISTANCEALPHAFROMDETAIL" "0..1" +// STATIC: "SOFT_MASK" "0..1" +// STATIC: "OUTLINE" "0..1" +// STATIC: "OUTER_GLOW" "0..1" +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps20b] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps30] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..0" [ps20b] [XBOX] +// STATIC: "SHADER_SRGB_READ" "0..1" [XBOX] +// STATIC: "SHADER_SRGB_READ" "0..0" [PC] +// STATIC: "DESATURATEWITHBASEALPHA" "0..1" +// STATIC: "LIGHTING_PREVIEW" "0..3" [PC] +// STATIC: "LIGHTING_PREVIEW" "0..0" [XBOX] +// STATIC: "ENVMAPFRESNEL" "0..1" +// STATIC: "FOW" "0..1" + +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps20b] +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps30] +// DYNAMIC: "WRITEWATERFOGTODESTALPHA" "0..1" +// DYNAMIC: "UBERLIGHT" "0..1" [ps30] [PC] + +// detail blend mode 6 = ps20b only +// SKIP: $DETAIL_BLEND_MODE == 6 [ps20] + +// SKIP: ( $FLASHLIGHT == 1 ) && ( $CUBEMAP == 1 ) [PC] +// SKIP: ($DETAILTEXTURE == 0 ) && ( $DETAIL_BLEND_MODE != 0 ) +// SKIP: ($DETAILTEXTURE == 0 ) && ( $SEAMLESS_DETAIL ) +// SKIP: ($ENVMAPMASK || $SELFILLUM_ENVMAPMASK_ALPHA) && ($SEAMLESS_BASE || $SEAMLESS_DETAIL) +// SKIP: $BASEALPHAENVMAPMASK && $ENVMAPMASK +// SKIP: $BASEALPHAENVMAPMASK && $SELFILLUM +// SKIP: $SELFILLUM && $SELFILLUM_ENVMAPMASK_ALPHA +// SKIP: $SELFILLUM_ENVMAPMASK_ALPHA && (! $ENVMAPMASK) +// SKIP: $BASEALPHAENVMAPMASK && ($SEAMLESS_BASE || $SEAMLESS_DETAIL) +// SKIP: ($DISTANCEALPHA == 0) && ($DISTANCEALPHAFROMDETAIL || $SOFT_MASK || $OUTLINE || $OUTER_GLOW) +// SKIP: ($DETAILTEXTURE == 0) && ($DISTANCEALPHAFROMDETAIL) + +// envmap stuff is meaningless if we're not using a cubemap +// SKIP: ( $CUBEMAP == 0 ) && ( ( $ENVMAPFRESNEL == 1 ) || ( $BASEALPHAENVMAPMASK == 1 ) ) +// SKIP: ( $CUBEMAP == 0 ) && ( $ENVMAPMASK == 1 ) && ( $SELFILLUM_ENVMAPMASK_ALPHA == 0 ) + + +// We don't care about flashlight depth unless the flashlight is on +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 ) [ps20b] +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 ) [ps30] + +// We don't care about uberlight unless the flashlight is on +// SKIP: ( $FLASHLIGHT == 0 ) && ( $UBERLIGHT == 1 ) [ps30] + +// DISTANCEALPHA-related skips +// SKIP: ($DISTANCEALPHA) && ($ENVMAPMASK || $BASEALPHAENVMAPMASK || $SELFILLUM || $SELFILLUM_ENVMAPMASK_ALPHA || $ENVMAPFRESNEL) +// SKIP: ($DISTANCEALPHA) && ($SEAMLESS_BASE || $SEAMLESS_DETAIL || $CUBEMAP ) +// SKIP: ($DISTANCEALPHA) && ($WRITEWATERFOGTODESTALPHA || $PIXELFOGTYPE || $FLASHLIGHT || $FLASHLIGHTSHADOWS ) + +// Don't do this with seamless textures for now until we determine if we want to use this. Could probably skip more here to save some combos +// skipping detailtextures to keep combos down +// SKIP: $DESATURATEWITHBASEALPHA && ( $SEAMLESS_BASE || $DETAILTEXTURE ) + +// These don't make sense together since they both use the base alpha channel +// Also, using the same constant for the desaturate amount and the selfillumtint +// SKIP: $DESATURATEWITHBASEALPHA && ( $SELFILLUM || $SELFILLUM_ENVMAPMASK_ALPHA ) + +// These won't fit in ps20 at the same time. +// SKIP: $DESATURATEWITHBASEALPHA && $BASEALPHAENVMAPMASK + +// SKIP: $FLASHLIGHTSHADOWS && ($LIGHTING_PREVIEW == 3) + +// FoW cuts to get it within 2.0 budget +// SKIP: ( $FOW == 1 ) && ( $DETAILTEXTURE == 1 ) +// SKIP: ( $FOW == 1 ) && ( $SEAMLESS_DETAIL == 1) +// SKIP: ( $FOW == 1 ) && ( $SEAMLESS_BASE == 1 ) +// SKIP: ( $FOW == 1 ) && ( $DESATURATEWITHBASEALPHA == 1 ) + + +#define PC_FLASHLIGHT ((FLASHLIGHT == 1) && !defined( _X360)) + +#include "common_fog_ps_supportsvertexfog_fxc.h" +#include "shader_constant_register_map.h" +#include "common_flashlight_fxc.h" +#include "common_vertexlitgeneric_dx9.h" +#include "fow_ps_fxc.h" + + +const float4 g_EnvmapTint_SPF : register( c0 ); //SPF=Single Pass Flashlight, stored in previously unused alpha. +const float4 g_DiffuseModulation : register( c1 ); +const float4 g_EnvmapContrast_ShadowTweaks : register( c2 ); +const float4 g_EnvmapSaturation_SelfIllumMask : register( c3 ); +const float4 g_SelfIllumTintOrSaturateFactor_and_BlendFactor : register( c4 ); + +// glow params +const float4 g_GlowParameters : register( c5 ); +const float4 g_GlowColor : register( c6 ); +#define GLOW_UV_OFFSET g_GlowParameters.xy +#define OUTER_GLOW_MIN_DVALUE g_GlowParameters.z +#define OUTER_GLOW_MAX_DVALUE g_GlowParameters.w +#define OUTER_GLOW_COLOR g_GlowColor + +const float4 g_DistanceAlphaParams : register( c7 ); +#define SOFT_MASK_MAX g_DistanceAlphaParams.x +#define SOFT_MASK_MIN g_DistanceAlphaParams.y +#define g_flBaseAlphaEnvMapMaskBias g_DistanceAlphaParams.z +#define g_flBaseAlphaEnvMapMaskScale g_DistanceAlphaParams.w + +const float4 g_OutlineColor : register( c8 ); +#define OUTLINE_COLOR g_OutlineColor + +const float4 g_OutlineParams : register( c9 ); + +#define OUTLINE_MIN_VALUE0 g_OutlineParams.x +#define OUTLINE_MIN_VALUE1 g_OutlineParams.y +#define OUTLINE_MAX_VALUE0 g_OutlineParams.z +#define OUTLINE_MAX_VALUE1 g_OutlineParams.w + +#if DETAILTEXTURE +const float3 g_DetailTint : register( c10 ); +#endif + +const float g_flSelfIllumScale : register( c11 ); + +const float4 g_ShaderControls : register( c12 ); + +#define g_fInverseBlendTintByBaseAlpha g_ShaderControls.x +#define g_fWriteDepthToAlpha g_ShaderControls.y +//#define g_fWriteWaterFogToDestAlpha g_ShaderControls.z +#define g_fVertexAlpha g_ShaderControls.w + +const float4 g_FresnelConstants : register( c13 ); +#define g_flFresnelBias g_FresnelConstants.x +#define g_flFresnelScale g_FresnelConstants.y +#define g_flFresnelExp g_FresnelConstants.z +#define g_flBaseAlphaEnvMapMaskExp g_FresnelConstants.w + + +const float4 g_EyePos_BaseTextureTranslucency : register( c20 ); +const float4 g_FogParams : register( c21 ); + +#if SELFILLUM || SELFILLUM_ENVMAPMASK_ALPHA + #define g_SelfIllumTint g_SelfIllumTintOrSaturateFactor_and_BlendFactor.xyz +#elif DESATURATEWITHBASEALPHA + #define g_SaturateFactor g_SelfIllumTintOrSaturateFactor_and_BlendFactor.x +#endif +#define g_DetailBlendFactor g_SelfIllumTintOrSaturateFactor_and_BlendFactor.w +#define g_EnvmapSaturation g_EnvmapSaturation_SelfIllumMask.xyz +#define g_SelfIllumMaskControl g_EnvmapSaturation_SelfIllumMask.w + +const float4 g_FlashlightAttenuationFactors : register( c22 ); +const HALF3 g_FlashlightPos : register( c23 ); +const float4x4 g_FlashlightWorldToTexture : register( c24 ); // through c27 + +#if UBERLIGHT +// ps_3_0 and up (over 32 registers) +const float3 g_vSmoothEdge0 : register( PSREG_UBERLIGHT_SMOOTH_EDGE_0 ); +const float3 g_vSmoothEdge1 : register( PSREG_UBERLIGHT_SMOOTH_EDGE_1 ); +const float3 g_vSmoothOneOverWidth : register( PSREG_UBERLIGHT_SMOOTH_EDGE_OOW ); +const float4 g_vShearRound : register( PSREG_UBERLIGHT_SHEAR_ROUND ); +const float4 g_aAbB : register( PSREG_UBERLIGHT_AABB ); +const float4x4 g_FlashlightWorldToLight : register( PSREG_UBERLIGHT_WORLD_TO_LIGHT ); +#endif + +sampler BaseTextureSampler : register( s0 ); +sampler EnvmapSampler : register( s1 ); +sampler DetailSampler : register( s2 ); +sampler EnvmapMaskSampler : register( s4 ); +sampler RandRotSampler : register( s6 ); // RandomRotation sampler +sampler FlashlightSampler : register( s7 ); +sampler ShadowDepthSampler : register( s8 ); // Flashlight shadow depth map sampler +sampler DepthSampler : register( s10 ); // depth buffer sampler for depth blending +sampler SelfIllumMaskSampler : register( s11 ); // selfillummask + +#if ( FOW == 1 ) + +sampler FoWSampler : register( s9 ); // Fog of War + +#endif + +struct PS_INPUT +{ +#if SEAMLESS_BASE + HALF3 baseTexCoord : TEXCOORD0; // Base texture coordinate +#else + HALF2 baseTexCoord : TEXCOORD0; // Base texture coordinate +#endif +#if SEAMLESS_DETAIL + HALF3 detailTexCoord : TEXCOORD1; // Seamless texture coordinate +#else + HALF2 detailTexCoord : TEXCOORD1; // Detail texture coordinate +#endif + +#if CUBEMAP || _X360 || ( !HARDWAREFOGBLEND && !DOPIXELFOG ) + float4 worldVertToEyeVector_fogFactorW : TEXCOORD3; // Necessary for cubemaps +#else + #if CUBEMAP || _X360 + float3 worldVertToEyeVector_fogFactorW : TEXCOORD3; // Necessary for cubemaps + #endif +#endif + float3 worldSpaceNormal : TEXCOORD4; // Necessary for cubemaps and flashlight + +#if ( FLASHLIGHT == 1 ) + float4 flashlightSpacePos : TEXCOORD5; + float4 projPos : TEXCOORD6; +#endif + + float4 worldPos_projPosZ : TEXCOORD7; + +#if SEAMLESS_BASE || SEAMLESS_DETAIL + float3 SeamlessWeights : COLOR0; // x y z projection weights +#endif + +#if FLASHLIGHT + float4 color : COLOR1; // Vertex color (from lighting or unlit) +#else + float4 color : TEXCOORD6; // use high-precision interpolator if possible +#endif + +#if ( FOW == 1 ) + float2 vFowCoord : TEXCOORD2; +#endif +}; + +#if LIGHTING_PREVIEW == 2 +LPREVIEW_PS_OUT main( PS_INPUT i ) : COLOR +#else +float4 main( PS_INPUT i ) : COLOR +#endif +{ + HALF4 baseColor = HALF4( 1.0f, 1.0f, 1.0f, 1.0f ); + #if ( SEAMLESS_BASE ) + { + baseColor = + i.SeamlessWeights.x * tex2D( BaseTextureSampler, i.baseTexCoord.yz )+ + i.SeamlessWeights.y * tex2D( BaseTextureSampler, i.baseTexCoord.zx )+ + i.SeamlessWeights.z * tex2D( BaseTextureSampler, i.baseTexCoord.xy ); + + #if defined ( _X360 ) && ( SHADER_SRGB_READ == 1 ) + { + // Do this after the blending to save shader ops + baseColor.rgb = X360GammaToLinear( baseColor.rgb ); + } + #endif + } + #else + { + baseColor = tex2Dsrgb( BaseTextureSampler, i.baseTexCoord.xy ); + } + #endif + + float distAlphaMask; + #if( DISTANCEALPHA && ( DISTANCEALPHAFROMDETAIL == 0 ) ) + { + distAlphaMask = baseColor.a; + } + #endif + + float4 detailColor; + #if ( DETAILTEXTURE ) + { + #if( SEAMLESS_DETAIL ) + { + detailColor = + i.SeamlessWeights.x * tex2D( DetailSampler, i.detailTexCoord.yz )+ + i.SeamlessWeights.y * tex2D( DetailSampler, i.detailTexCoord.zx )+ + i.SeamlessWeights.z * tex2D( DetailSampler, i.detailTexCoord.xy ); + } + #else + { + detailColor = tex2D( DetailSampler, i.detailTexCoord.xy ); + } + #endif + detailColor.rgb *= g_DetailTint; + + #if ( DISTANCEALPHA && ( DISTANCEALPHAFROMDETAIL == 1 ) ) + { + distAlphaMask = detailColor.a; + detailColor.a = 1.0; // make tcombine treat as 1.0 + } + #endif + baseColor = TextureCombine( baseColor, detailColor, DETAIL_BLEND_MODE, g_DetailBlendFactor ); + } + #endif + + #if ( DESATURATEWITHBASEALPHA ) + { + float grey = dot( baseColor.rgb, float3( 0.3, 0.59, 0.11 ) ); + baseColor.rgb = lerp( baseColor.rgb, ( float3 )grey, baseColor.a * g_SaturateFactor ); + } + #endif + + #if ( DISTANCEALPHA ) + { + // now, do all distance alpha effects + if ( OUTLINE && ( distAlphaMask >= OUTLINE_MIN_VALUE0 ) && ( distAlphaMask <= OUTLINE_MAX_VALUE1 ) ) + { + float oFactor = 1.0f; + if ( distAlphaMask <= OUTLINE_MIN_VALUE1 ) + { + oFactor = smoothstep( OUTLINE_MIN_VALUE0, OUTLINE_MIN_VALUE1, distAlphaMask ); + } + else + { + oFactor = smoothstep( OUTLINE_MAX_VALUE1, OUTLINE_MAX_VALUE0, distAlphaMask ); + } + baseColor = lerp( baseColor, OUTLINE_COLOR, oFactor ); + } + + float mskUsed; + #if ( SOFT_MASK ) + { + mskUsed = smoothstep( SOFT_MASK_MIN, SOFT_MASK_MAX, distAlphaMask ); + baseColor.a *= mskUsed; + } + #else + { + mskUsed = distAlphaMask >= 0.5f; + #if ( DETAILTEXTURE ) + { + baseColor.a *= mskUsed; + } + #else + { + baseColor.a = mskUsed; + } + #endif + } + #endif + + #if ( OUTER_GLOW ) + { + float glowTexel; + #if ( DISTANCEALPHAFROMDETAIL ) + { + glowTexel = tex2D( DetailSampler, i.detailTexCoord.xy+GLOW_UV_OFFSET ).a; + } + #else + { + glowTexel = tex2D( BaseTextureSampler, i.baseTexCoord.xy+GLOW_UV_OFFSET ).a; + } + #endif + + float4 glowc = OUTER_GLOW_COLOR * smoothstep( OUTER_GLOW_MIN_DVALUE, OUTER_GLOW_MAX_DVALUE, glowTexel ); + baseColor = lerp( glowc, baseColor, mskUsed ); + } + #endif + } + #endif + + float3 specularFactor = 1.0f; + float4 envmapMaskTexel; + #if ( ENVMAPMASK ) + { + envmapMaskTexel = tex2D( EnvmapMaskSampler, i.baseTexCoord.xy ); + specularFactor *= envmapMaskTexel.xyz; + } + #endif + + #if ( BASEALPHAENVMAPMASK ) + { + specularFactor *= saturate( g_flBaseAlphaEnvMapMaskScale * pow( baseColor.a, g_flBaseAlphaEnvMapMaskExp ) + g_flBaseAlphaEnvMapMaskBias ); + } + #endif + + #if ( ENVMAPFRESNEL ) + { + float flFresnel = 1-saturate( dot( normalize( i.worldSpaceNormal.xyz ), normalize( i.worldVertToEyeVector_fogFactorW.xyz ) ) ); + flFresnel = g_flFresnelScale * pow( flFresnel, g_flFresnelExp ) + g_flFresnelBias; + specularFactor *= flFresnel; + } + #endif + + float3 diffuseLighting = float3( 1.0f, 1.0f, 1.0f ); + #if ( DIFFUSELIGHTING || VERTEXCOLOR && !( VERTEXCOLOR && DIFFUSELIGHTING ) ) + { + diffuseLighting = i.color.rgb; + } + #endif + + float3 albedo = baseColor.rgb; + float alpha = 1.0f; + #if ( !BASEALPHAENVMAPMASK && !SELFILLUM ) + { + alpha *= lerp( 1.0f, baseColor.a, g_EyePos_BaseTextureTranslucency.w ); + } + #endif + + #if ( FLASHLIGHT ) + { + int nShadowSampleLevel = 0; + bool bDoShadows = false; + // Do shadow mapping on shader models 2b and 30. + #if ( FLASHLIGHTSHADOWS && (defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) ) ) + { + nShadowSampleLevel = FLASHLIGHTDEPTHFILTERMODE; + bDoShadows = true; + } + #endif + + float4 flashlightSpacePosition; + flashlightSpacePosition = i.flashlightSpacePos; + + bool bHasNormal = ( CUBEMAP || DIFFUSELIGHTING ); + float3 flashlightColor = DoFlashlight( g_FlashlightPos, i.worldPos_projPosZ.xyz, flashlightSpacePosition, + i.worldSpaceNormal, g_FlashlightAttenuationFactors.xyz, + g_FlashlightAttenuationFactors.w, FlashlightSampler, ShadowDepthSampler, + RandRotSampler, nShadowSampleLevel, bDoShadows, false, i.projPos.xy / i.projPos.w, false, g_EnvmapContrast_ShadowTweaks, bHasNormal ); + + #if ( UBERLIGHT && defined( SHADER_MODEL_PS_3_0 ) ) + { + float4 uberLightPosition = mul( float4( i.worldPos_projPosZ.xyz, 1.0f ), g_FlashlightWorldToLight ).yzxw; + flashlightColor *= uberlight( uberLightPosition, g_vSmoothEdge0, g_vSmoothEdge1, + g_vSmoothOneOverWidth, g_vShearRound.xy, g_aAbB, g_vShearRound.zw ); + } + #endif + + #if defined ( _X360 ) + { + diffuseLighting += flashlightColor; + } + #else + { + //add to diffuse in single pass flashlight mode, replace diffuse in additive two pass mode + diffuseLighting = (diffuseLighting * g_EnvmapTint_SPF.a) + flashlightColor; + } + #endif + } + #endif + + #if ( defined( SHADER_MODEL_PS_2_0 ) ) + { + // This branch means that g_fInverseBlendTintByBaseAlpha doesn't work with ps20, but we don't care since we're dropping ps20 + diffuseLighting *= g_DiffuseModulation.rgb; + } + #else + { + // Optionally use basealpha to blend in the diffuse modulation (saturated add of g_fInverseBlendTintByBaseAlpha turns this on/off) + diffuseLighting *= lerp( float3( 1.0f, 1.0f, 1.0f ), g_DiffuseModulation.rgb, saturate( baseColor.a + g_fInverseBlendTintByBaseAlpha ) ); + } + #endif + + alpha *= g_DiffuseModulation.a; + + #if ( VERTEXCOLOR && DIFFUSELIGHTING ) + { + albedo *= i.color.rgb; + } + #endif + + alpha = lerp( alpha, alpha * i.color.a, g_fVertexAlpha ); + + float3 diffuseComponent = albedo * diffuseLighting; + + #if ( DETAILTEXTURE ) + { + diffuseComponent = TextureCombinePostLighting( diffuseComponent, detailColor, DETAIL_BLEND_MODE, g_DetailBlendFactor ); + } + #endif + + #if !( FLASHLIGHT && defined( SHADER_MODEL_PS_2_0 ) ) + { + #if SELFILLUM_ENVMAPMASK_ALPHA + { + // range of alpha: + // 0 - 0.125 = lerp(diffuse,selfillum,alpha*8) + // 0.125-1.0 = selfillum*(1+alpha-0.125)*8 (over bright glows) + HALF3 selfIllumComponent = g_SelfIllumTint * albedo; + half Adj_Alpha = 8 * envmapMaskTexel.a; + diffuseComponent = ( max( 0, 1 - Adj_Alpha ) * diffuseComponent) + Adj_Alpha * selfIllumComponent; + } + #elif SELFILLUM + { + float3 vSelfIllumMask = tex2D( SelfIllumMaskSampler, i.baseTexCoord.xy ); + vSelfIllumMask = lerp( baseColor.aaa, vSelfIllumMask, g_SelfIllumMaskControl ); + diffuseComponent = lerp( diffuseComponent, g_SelfIllumTint * albedo, vSelfIllumMask * g_flSelfIllumScale ); + } + #endif + } + #endif + + HALF3 specularLighting = HALF3( 0.0f, 0.0f, 0.0f ); + + //Single pass flashlight mode runs out of instructions and constant registers when both detail textures and cubemaps are enabled on PC. Silently drop cubemaps in that case. + #if ( !PC_FLASHLIGHT ) + { + #if ( CUBEMAP ) + { + HALF3 reflectVect = CalcReflectionVectorUnnormalized( i.worldSpaceNormal, i.worldVertToEyeVector_fogFactorW.xyz ); + + specularLighting = ENV_MAP_SCALE * texCUBE( EnvmapSampler, reflectVect ); + specularLighting *= specularFactor; + specularLighting *= g_EnvmapTint_SPF.rgb; + + #if ( ENVMAPFRESNEL == 0 ) + { + // because of SM 2.0 instruction limits, we only do this stuff if we're not using envmapfresnel + HALF3 specularLightingSquared = specularLighting * specularLighting; + specularLighting = lerp( specularLighting, specularLightingSquared, g_EnvmapContrast_ShadowTweaks ); + HALF3 greyScale = dot( specularLighting, HALF3( 0.299f, 0.587f, 0.114f ) ); + specularLighting = lerp( greyScale, specularLighting, g_EnvmapSaturation ); + } + #endif + } + #endif + } + #endif + + HALF3 result = diffuseComponent + specularLighting; + +#if ( FOW == 1 ) + result.rgb = CalcFoW( FoWSampler, i.vFowCoord, result.rgb ); +#endif + +#if ( LIGHTING_PREVIEW == 0 ) +{ + float fogFactor; + float flVertexFogFactor = 0.0f; + #if ( !HARDWAREFOGBLEND && !DOPIXELFOG ) + { + flVertexFogFactor = i.worldVertToEyeVector_fogFactorW.w; + } + #endif + fogFactor = CalcPixelFogFactorSupportsVertexFog( PIXELFOGTYPE, g_FogParams, g_EyePos_BaseTextureTranslucency.xyz, i.worldPos_projPosZ.xyz, i.worldPos_projPosZ.w, flVertexFogFactor ); + if ( PIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT && WRITEWATERFOGTODESTALPHA ) + { + alpha = fogFactor; + } + return FinalOutput( float4( result.rgb, alpha ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, g_fWriteDepthToAlpha, i.worldPos_projPosZ.w ); +} +#endif +#if ( LIGHTING_PREVIEW == 1 ) +{ + float dotprod = 0.7f + 0.25f * dot( i.worldSpaceNormal, normalize( float3( 1, 2, -.5 ) ) ); + return FinalOutput( float4( dotprod * albedo.xyz, alpha ), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_LINEAR ); +} +#endif +#if ( LIGHTING_PREVIEW == 2 ) +{ + LPREVIEW_PS_OUT ret; + ret.flags = float4( 1, 1, 1, 1 ); + ret.color = float4( albedo.xyz, alpha ); + ret.normal = float4( i.worldSpaceNormal, alpha ); + ret.position = float4( i.worldPos_projPosZ.xyz, alpha ); + return FinalOutput( ret, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} +#endif +#if ( LIGHTING_PREVIEW == 3 ) // normal + depth + return float4( normalize( i.worldSpaceNormal ), i.worldPos_projPosZ.w ); +#endif +} diff --git a/materialsystem/stdshaders/vertexlit_and_unlit_generic_vs20.fxc b/materialsystem/stdshaders/vertexlit_and_unlit_generic_vs20.fxc new file mode 100644 index 00000000..8fd4de6c --- /dev/null +++ b/materialsystem/stdshaders/vertexlit_and_unlit_generic_vs20.fxc @@ -0,0 +1,408 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "VERTEXCOLOR" "0..1" +// STATIC: "CUBEMAP" "0..1" +// STATIC: "HALFLAMBERT" "0..1" +// STATIC: "FLASHLIGHT" "0..1" +// STATIC: "SEAMLESS_BASE" "0..1" +// STATIC: "SEAMLESS_DETAIL" "0..1" +// STATIC: "SEPARATE_DETAIL_UVS" "0..1" +// STATIC: "DECAL" "0..1" [vs30] +// STATIC: "STATICLIGHT3" "0..0" // MAINTOL4DMERGEFIXME +// STATIC: "LIGHTING_PREVIEW" "0..3" [PC] +// STATIC: "LIGHTING_PREVIEW" "0..0" [XBOX] +// STATIC: "FOW" "0..1" +// STATIC: "TREESWAY" "0..2" + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "DYNAMIC_LIGHT" "0..1" +// DYNAMIC: "SKINNING" "0..1" + +// DYNAMIC: "MORPHING" "0..1" [vs30] [ = pShaderAPI->IsHWMorphingEnabled() ] +// DYNAMIC: "TESSELLATION" "0..2" [vs30] [PC] +// DYNAMIC: "TESSELLATION" "0..0" [XBOX] +// DYNAMIC: "TESSELLATION" "0..0" [vs20] [PC] + +// SKIP: ($SEPARATE_DETAIL_UVS) && ($SEAMLESS_DETAIL) +// SKIP: ( $FOW ) && ( $SEAMLESS_DETAIL ) +// SKIP: ( $FOW ) && ( $SEAMLESS_BASE ) +// SKIP: ( $FOW ) && ( $TESSELLATION ) +// SKIP: ($TREESWAY) && ($MORPHING) +// SKIP: ($TREESWAY) && ($TESSELLATION) +// SKIP: ($TREESWAY) && ($FOW) +// SKIP: ( $TREESWAY ) && ( $SEAMLESS_DETAIL || $SEAMLESS_BASE ) + +#include "common_fog_vs_supportsvertexfog_fxc.h" + +// When tessellating, we don't have room in the super-prim vertices for more colors, tex coords or objects space positions +// SKIP: ( $STATICLIGHT3 || $VERTEXCOLOR || $SEAMLESS_BASE || $SEAMLESS_DETAIL || $SEPARATE_DETAIL_UVS || $MORPHING || $SKINNING || $COMPRESSED_VERTS ) && $TESSELLATION +#include "common_vs_fxc.h" +#include "fow_vs_fxc.h" + +static const bool g_bSkinning = SKINNING ? true : false; +static const int g_FogType = DOWATERFOG; +static const bool g_bVertexColor = VERTEXCOLOR ? true : false; +static const bool g_bCubemap = CUBEMAP ? true : false; +static const bool g_bFlashlight = FLASHLIGHT ? true : false; +static const bool g_bHalfLambert = HALFLAMBERT ? true : false; +#if (defined( SHADER_MODEL_VS_3_0 ) && MORPHING && DECAL) +static const bool g_bDecalOffset = true; +#else +static const bool g_bDecalOffset = false; +#endif + +const float4 cBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_0 ); // 0 & 1 + +#if ( LIGHTING_PREVIEW == 3 ) +const float4 g_vEyeVector : register( SHADER_SPECIFIC_CONST_2 ); +#define g_flStaticLightEnabled 0 +#else + const float g_flStaticLightEnabled : register( SHADER_SPECIFIC_CONST_2 ); +#endif + +const float4 g_vMiscParams1 : register( SHADER_SPECIFIC_CONST_3 ); + +#if ( SEAMLESS_DETAIL || SEAMLESS_BASE ) + #define SEAMLESS_SCALE g_vMiscParams1.x +#elif TESSELLATION + #define g_SubDControls g_vMiscParams1 +#elif FOW + #define g_vFoWWorldSize g_vMiscParams1 +#endif + +const float4 cDetailTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_4 ); // 4 & 5 +const float4x4 g_FlashlightWorldToTexture : register( SHADER_SPECIFIC_CONST_6 ); // 6, 7, 8, 9 + +const float4 g_vMiscParams2 : register( SHADER_SPECIFIC_CONST_12 ); +#define cSinglePassFlashlight g_vMiscParams2.x + +const float4 g_vMiscParams3 : register( SHADER_SPECIFIC_CONST_10 ); +const float4 g_vMiscParams4 : register( SHADER_SPECIFIC_CONST_11 ); + +#if ( TREESWAY ) + #define g_flTime g_vMiscParams2.y + #define g_vWindDir g_vMiscParams2.zw + + #define g_flFastSwaySpeedScale g_vMiscParams1.x + #define g_flScrumbleFalloffCurve g_vMiscParams1.y + #define g_flSwayFalloffCurve g_vMiscParams1.z + #define g_flScrumbleSpeed g_vMiscParams1.w + + #define g_flHeight g_vMiscParams3.x + #define g_flStartHeight g_vMiscParams3.y + #define g_flRadius g_vMiscParams3.z + #define g_flStartRadius g_vMiscParams3.w + + #define g_flSwaySpeed g_vMiscParams4.x + #define g_flSwayIntensity g_vMiscParams4.y + #define g_flScrumbleWaveCount g_vMiscParams4.z + #define g_flScrumbleIntensity g_vMiscParams4.w + + #define g_flWindSpeedLerpStart cDetailTexCoordTransform[0].x + #define g_flWindSpeedLerpEnd cDetailTexCoordTransform[0].y +#endif + +#if defined( SHADER_MODEL_VS_3_0 ) + // NOTE: cMorphTargetTextureDim.xy = target dimensions, + // cMorphTargetTextureDim.z = 4tuples/morph + #define cMorphTargetTextureDim g_vMiscParams3 + #define cMorphSubrect g_vMiscParams4 + sampler2D morphSampler : register( D3DVERTEXTEXTURESAMPLER0, s0 ); +#endif + +#if TESSELLATION + +#include "tessellation_vs_fxc.h" +sampler2D BezierSampler : register( s1 ); +sampler2D DispSampler : register( s2 ); +// VS_INPUT defined in header + +#else // no TESSELLATION + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vNormal : NORMAL; + #if VERTEXCOLOR + float4 vColor : COLOR0; + #else + float3 vStaticLight : COLOR1; + #if STATICLIGHT3 + float3 vStaticLight2 : COLOR2; + float3 vStaticLight3 : COLOR3; + #endif + #endif + // make these float2's and stick the [n n 0 1] in the dot math. + float4 vTexCoord0 : TEXCOORD0; + float4 vTexCoord1 : TEXCOORD1; + float4 vTexCoord2 : TEXCOORD2; + float4 vTexCoord3 : TEXCOORD3; + + // Position and normal/tangent deltas + float3 vPosFlex : POSITION1; + float3 vNormalFlex : NORMAL1; + #ifdef SHADER_MODEL_VS_3_0 + float vVertexID : POSITION2; + #endif +}; + +#endif // TESSELLATION + +struct VS_OUTPUT +{ + float4 projPos : POSITION; // Projection-space position +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + float fog : FOG; +#endif + +#if SEAMLESS_BASE + float3 SeamlessTexCoord : TEXCOORD0; // Base texture x/y/z (indexed by swizzle) +#else + float2 baseTexCoord : TEXCOORD0; // Base texture coordinate +#endif +#if SEAMLESS_DETAIL + float3 SeamlessDetailTexCoord : TEXCOORD1; // Detail texture coordinate +#else + float2 detailTexCoord : TEXCOORD1; // Detail texture coordinate +#endif +#if CUBEMAP || _X360 || ( !HARDWAREFOGBLEND && !DOPIXELFOG ) + float4 worldVertToEyeVector_fogFactorW : TEXCOORD3; // Necessary for cubemaps +#else + #if CUBEMAP || _X360 + float3 worldVertToEyeVector_fogFactorW : TEXCOORD3; // Necessary for cubemaps + #endif +#endif + + float3 worldNormal : TEXCOORD4; // Necessary for cubemaps and flashlight + +#if FLASHLIGHT + float4 flashlightSpacePos : TEXCOORD5; + float4 vProjPos : TEXCOORD6; +#endif + + float4 worldPos_ProjPosZ : TEXCOORD7; + +#if SEAMLESS_DETAIL || SEAMLESS_BASE + float3 SeamlessWeights : COLOR0; // x y z projection weights +#endif + +#if FLASHLIGHT + float4 color : COLOR1; // Vertex color (from lighting or unlit) +#else + float4 color : TEXCOORD6; // use high-precision interpolator if possible +#endif + +#if ( FOW == 1 ) + float2 vFowCoord : TEXCOORD2; +#endif +}; + +#include "tree_sway.h" + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + bool bDynamicLight = DYNAMIC_LIGHT ? true : false; + bool bStaticLight = g_flStaticLightEnabled ? true : false; + bool bDoLighting = !g_bVertexColor && (bDynamicLight || bStaticLight); + + float3 worldPos; + + #if ( TESSELLATION ) + { + EvaluateSubdivisionSurface( v, g_SubDControls.x, g_SubDControls.y, g_SubDControls.z, + BezierSampler, DispSampler, + o.worldNormal, worldPos, + o.baseTexCoord, o.detailTexCoord ); + + float3 vDummySpecular = float3(0,0,0); + o.color.xyz = DoLighting( worldPos, o.worldNormal, vDummySpecular, bStaticLight, bDynamicLight, g_bHalfLambert ); + } + #else // no TESSELLATION + { + float4 vPosition = v.vPos; + float3 vNormal = 0; + + if ( bDoLighting || SEAMLESS_BASE || SEAMLESS_DETAIL || LIGHTING_PREVIEW || g_bDecalOffset || CUBEMAP ) + { + // The vertex only contains valid normals if they are actually needed (fetching them when absent makes D3D complain) + DecompressVertex_Normal( v.vNormal, vNormal ); + } + else + { + if ( SEAMLESS_BASE || SEAMLESS_DETAIL || g_bDecalOffset || g_bFlashlight ) + { + // The vertex only contains valid normals if they are actually needed (fetching them when absent makes D3D complain) + DecompressVertex_Normal( v.vNormal, vNormal ); + } + } + + #if ( SEAMLESS_BASE || SEAMLESS_DETAIL ) + { + // compute blend weights in rgb + float3 NNormal = normalize( vNormal ); + o.SeamlessWeights.xyz = NNormal * NNormal; // sums to 1. + } + #endif + + #if ( !defined( SHADER_MODEL_VS_3_0 ) || !MORPHING ) + { + ApplyMorph( v.vPosFlex, v.vNormalFlex, vPosition.xyz, vNormal ); + } + #else + { + ApplyMorph( morphSampler, cMorphTargetTextureDim, cMorphSubrect, v.vVertexID, v.vTexCoord2, vPosition.xyz, vNormal ); + } + #endif + + #if ( TREESWAY ) + { + vPosition.xyz = ComputeTreeSway( vPosition.xyz, g_flTime ); + } + #endif + + SkinPositionAndNormal( g_bSkinning, vPosition, vNormal, v.vBoneWeights, v.vBoneIndices, worldPos, o.worldNormal ); + + if ( !g_bVertexColor ) + { + o.worldNormal = normalize( o.worldNormal ); + } + + #if ( defined( SHADER_MODEL_VS_3_0 ) && MORPHING && DECAL ) + { + // Avoid z precision errors + worldPos += o.worldNormal * 0.05f * v.vTexCoord2.z; + } + #endif + + o.color = float4( 0.0f, 0.0f, 0.0f, 0.0f ); + + #if ( VERTEXCOLOR ) + { + // Assume that this is unlitgeneric if you are using vertex color. + o.color.rgb = GammaToLinear( v.vColor.rgb ); + o.color.a = v.vColor.a; + } + #else + { + // Compute vertex lighting + #if STATICLIGHT3 + { + float3 vStaticLightAvg = ( v.vStaticLight + v.vStaticLight2 + v.vStaticLight3 ) / 3.0f; + o.color.xyz = DoLighting( worldPos, o.worldNormal, vStaticLightAvg, bStaticLight, bDynamicLight, g_bHalfLambert ); + } + #else + { + o.color.xyz = DoLighting( worldPos, o.worldNormal, v.vStaticLight, bStaticLight, bDynamicLight, g_bHalfLambert ); + } + #endif + } + #endif + + #if ( SEAMLESS_BASE ) + { + o.SeamlessTexCoord.xyz = SEAMLESS_SCALE * v.vPos.xyz; + } + #else + { + // Base texture coordinates + o.baseTexCoord.x = dot( v.vTexCoord0, cBaseTexCoordTransform[0] ); + o.baseTexCoord.y = dot( v.vTexCoord0, cBaseTexCoordTransform[1] ); + } + #endif + + #if ( SEAMLESS_DETAIL ) + { + // FIXME: detail texcoord as a 2d xform doesn't make much sense here, so I just do enough so + // that scale works. More smartness could allow 3d xform. + o.SeamlessDetailTexCoord.xyz = (SEAMLESS_SCALE*cDetailTexCoordTransform[0].x) * v.vPos.xyz; + } + #else + { + #if ( TREE_SWAY ) + { + o.detailTexCoord.xy = v.vTexCoord0; + } + #else + { + // Detail texture coordinates + // FIXME: This shouldn't have to be computed all the time. + o.detailTexCoord.x = dot( v.vTexCoord0, cDetailTexCoordTransform[0] ); + o.detailTexCoord.y = dot( v.vTexCoord0, cDetailTexCoordTransform[1] ); + } + #endif + } + #endif + + #if ( SEPARATE_DETAIL_UVS ) + { + o.detailTexCoord.xy = v.vTexCoord1.xy; + } + #endif + } + #endif // TESSELLATION + + + // Needed for cubemaps + #if ( CUBEMAP ) + { + o.worldVertToEyeVector_fogFactorW.xyz = VSHADER_VECT_SCALE * ( cEyePos - worldPos ); + } + #endif + + #if ( !defined (_X360) && FLASHLIGHT ) + { + //zero out the vertex color in additive two-pass flashlight mode + o.color.rgb *= cSinglePassFlashlight.x; + } + #endif + + // Transform into projection space + o.projPos = mul( float4( worldPos, 1 ), cViewProj ); + #if ( FLASHLIGHT ) + { + o.vProjPos = o.projPos; + } + #endif + + o.worldPos_ProjPosZ = float4( worldPos, o.projPos.z ); + +#if ( FOW == 1 ) + o.vFowCoord = CalcFoWCoord( g_vFoWWorldSize, worldPos.xy ); +#endif + + #if ( LIGHTING_PREVIEW == 3 ) + { + o.worldPos_ProjPosZ.w = dot( g_vEyeVector, worldPos.xyz - cEyePos.xyz ); // Linear depth + } + #endif + + #if ( LIGHTING_PREVIEW ) + { + float dot = 0.5 + 0.5 * o.worldNormal * float3( 0.7071, 0.7071, 0 ); + o.color.xyz = float3( dot, dot, dot ); + } + #endif + + #if ( FLASHLIGHT ) + { + o.flashlightSpacePos = mul( float4( worldPos, 1.0f ), g_FlashlightWorldToTexture ); + } + #endif + + #if ( HARDWAREFOGBLEND ) + { + o.fog = CalcFixedFunctionFog( worldPos, g_FogType ); + } + #endif + #if ( !DOPIXELFOG && !HARDWAREFOGBLEND ) + { + o.worldVertToEyeVector_fogFactorW.w = CalcNonFixedFunctionFog( worldPos, g_FogType ); + } + #endif + + return o; +} diff --git a/materialsystem/stdshaders/vertexlit_lighting_only_ps2x.fxc b/materialsystem/stdshaders/vertexlit_lighting_only_ps2x.fxc new file mode 100644 index 00000000..41ddc215 --- /dev/null +++ b/materialsystem/stdshaders/vertexlit_lighting_only_ps2x.fxc @@ -0,0 +1,66 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "DIFFUSELIGHTING" "0..1" +// STATIC: "HALFLAMBERT" "0..1" + +// DYNAMIC: "AMBIENT_LIGHT" "0..1" +// DYNAMIC: "NUM_LIGHTS" "0..2" [ps20] +// DYNAMIC: "NUM_LIGHTS" "0..4" [ps20b] + +#define HDRTYPE HDR_TYPE_NONE +#include "common_vertexlitgeneric_dx9.h" + +const float4 g_OverbrightFactor : register( c4 ); +const float3 cAmbientCube[6] : register( c6 ); + +PixelShaderLightInfo cLightInfo[3] : register(c13); + +sampler BumpmapSampler : register( s0 ); +sampler NormalizeSampler : register( s1 ); + +struct PS_INPUT +{ + float2 baseTexCoord : TEXCOORD0; + // detail textures and bumpmaps are mutually exclusive so that we have enough texcoords. + float2 detailOrBumpTexCoord : TEXCOORD1; + // bump mapping and a separate envmap mask texture are mutually exclusive. + float2 envmapMaskTexCoord : TEXCOORD2; + float3 worldVertToEyeVector : TEXCOORD3; + float3x3 tangentSpaceTranspose : TEXCOORD4; + float4 worldPos_projPosZ : TEXCOORD5; + float2 lightAtten01 : TEXCOORD6; + float2 lightAtten23 : TEXCOORD7; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + bool bDiffuseLighting = DIFFUSELIGHTING ? true : false; + bool bHalfLambert = HALFLAMBERT ? true : false; + bool bAmbientLight = AMBIENT_LIGHT ? true : false; + int nNumLights = NUM_LIGHTS; + + float4 vLightAtten = float4( i.lightAtten01, i.lightAtten23 ); + + float3 tangentSpaceNormal = float3( 0.0f, 0.0f, 1.0f ); + float4 normalTexel = 1.0f; + float4 baseColor = float4( 1.0f, 1.0f, 1.0f, 1.0f ); + + normalTexel = tex2D( BumpmapSampler, i.detailOrBumpTexCoord ); + tangentSpaceNormal = 2.0f * normalTexel - 1.0f; + + float3 diffuseLighting = float3( 1.0f, 1.0f, 1.0f ); + if( bDiffuseLighting ) + { + float3 worldSpaceNormal = mul( i.tangentSpaceTranspose, tangentSpaceNormal ); + float3 staticLightingColor = float3( 0.0f, 0.0f, 0.0f ); + diffuseLighting = PixelShaderDoLighting( i.worldPos_projPosZ.xyz, worldSpaceNormal, + float3( 0.0f, 0.0f, 0.0f ), false, bAmbientLight, + vLightAtten, cAmbientCube, NormalizeSampler, nNumLights, cLightInfo, bHalfLambert, + false, NormalizeSampler ); + // multiply by .5 since we want a 50% (in gamma space) reflective surface) + diffuseLighting *= pow( 0.5f, 2.2f ); + } + + return FinalOutput( float4( diffuseLighting, 1.0f ), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} + diff --git a/materialsystem/stdshaders/vertexlitgeneric_dx9.cpp b/materialsystem/stdshaders/vertexlitgeneric_dx9.cpp new file mode 100644 index 00000000..75d267d4 --- /dev/null +++ b/materialsystem/stdshaders/vertexlitgeneric_dx9.cpp @@ -0,0 +1,513 @@ +//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=====================================================================================// + +#include "BaseVSShader.h" +#include "vertexlitgeneric_dx9_helper.h" +#include "emissive_scroll_blended_pass_helper.h" +#include "cloak_blended_pass_helper.h" +#include "flesh_interior_blended_pass_helper.h" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +BEGIN_VS_SHADER( VertexLitGeneric, "Help for VertexLitGeneric" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( ALBEDO, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "albedo (Base texture with no baked lighting)" ) + SHADER_PARAM( COMPRESS, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "compression wrinklemap" ) + SHADER_PARAM( STRETCH, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "expansion wrinklemap" ) + SHADER_PARAM( SELFILLUMTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Self-illumination tint" ) + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/detail", "detail texture" ) + SHADER_PARAM( DETAILFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $detail" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "4", "scale of the detail texture" ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "envmap frame number" ) + SHADER_PARAM( ENVMAPMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_envmask", "envmap mask" ) + SHADER_PARAM( ENVMAPMASKFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( ENVMAPMASKTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$envmapmask texcoord transform" ) + SHADER_PARAM( ENVMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "envmap tint" ) + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "bump map" ) + SHADER_PARAM( BUMPCOMPRESS, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader3_normal", "compression bump map" ) + SHADER_PARAM( BUMPSTRETCH, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "expansion bump map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( ENVMAPCONTRAST, SHADER_PARAM_TYPE_FLOAT, "0.0", "contrast 0 == normal 1 == color*color" ) + SHADER_PARAM( ENVMAPSATURATION, SHADER_PARAM_TYPE_FLOAT, "1.0", "saturation 0 == greyscale 1 == normal" ) + SHADER_PARAM( SELFILLUM_ENVMAPMASK_ALPHA, SHADER_PARAM_TYPE_FLOAT,"0.0","defines that self illum value comes from env map mask alpha" ) + SHADER_PARAM( SELFILLUMFRESNEL, SHADER_PARAM_TYPE_BOOL, "0", "Self illum fresnel" ) + SHADER_PARAM( SELFILLUMFRESNELMINMAXEXP, SHADER_PARAM_TYPE_VEC4, "0", "Self illum fresnel min, max, exp" ) + SHADER_PARAM( SELFILLUMMASKSCALE, SHADER_PARAM_TYPE_FLOAT, "0", "Scale self illum effect strength" ) + SHADER_PARAM( ALPHATESTREFERENCE, SHADER_PARAM_TYPE_FLOAT, "0.0", "" ) + SHADER_PARAM( FLASHLIGHTNOLAMBERT, SHADER_PARAM_TYPE_BOOL, "0", "Flashlight pass sets N.L=1.0" ) + + // Debugging term for visualizing ambient data on its own + SHADER_PARAM( AMBIENTONLY, SHADER_PARAM_TYPE_INTEGER, "0", "Control drawing of non-ambient light ()" ) + + SHADER_PARAM( PHONGEXPONENT, SHADER_PARAM_TYPE_FLOAT, "5.0", "Phong exponent for local specular lights" ) + SHADER_PARAM( PHONGTINT, SHADER_PARAM_TYPE_VEC3, "5.0", "Phong tint for local specular lights" ) + SHADER_PARAM( PHONGALBEDOTINT, SHADER_PARAM_TYPE_BOOL, "1.0", "Apply tint by albedo (controlled by spec exponent texture" ) + SHADER_PARAM( LIGHTWARPTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "1D ramp texture for tinting scalar diffuse term" ) + SHADER_PARAM( PHONGWARPTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "warp the specular term" ) + SHADER_PARAM( PHONGFRESNELRANGES, SHADER_PARAM_TYPE_VEC3, "[0 0.5 1]", "Parameters for remapping fresnel output" ) + SHADER_PARAM( PHONGBOOST, SHADER_PARAM_TYPE_FLOAT, "1.0", "Phong overbrightening factor (specular mask channel should be authored to account for this)" ) + SHADER_PARAM( PHONGEXPONENTTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "Phong Exponent map" ) + SHADER_PARAM( PHONG, SHADER_PARAM_TYPE_BOOL, "0", "enables phong lighting" ) + SHADER_PARAM( BASEMAPALPHAPHONGMASK, SHADER_PARAM_TYPE_INTEGER, "0", "indicates that there is no normal map and that the phong mask is in base alpha" ) + SHADER_PARAM( INVERTPHONGMASK, SHADER_PARAM_TYPE_INTEGER, "0", "invert the phong mask (0=full phong, 1=no phong)" ) + SHADER_PARAM( ENVMAPFRESNEL, SHADER_PARAM_TYPE_FLOAT, "0", "Degree to which Fresnel should be applied to env map" ) + SHADER_PARAM( SELFILLUMMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "If we bind a texture here, it overrides base alpha (if any) for self illum" ) + SHADER_PARAM( BASEMAPLUMINANCEPHONGMASK, SHADER_PARAM_TYPE_INTEGER, "0", "indicates that the base luminance should be used to mask phong" ) + + // detail texturing + SHADER_PARAM( DETAILBLENDMODE, SHADER_PARAM_TYPE_INTEGER, "0", "mode for combining detail texture with base. 0=normal, 1= additive, 2=alpha blend detail over base, 3=crossfade" ) + SHADER_PARAM( DETAILBLENDFACTOR, SHADER_PARAM_TYPE_FLOAT, "1", "blend amount for detail texture." ) + SHADER_PARAM( DETAILTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "detail texture tint" ) + SHADER_PARAM( DETAILTEXTURETRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$detail texcoord transform" ) + + // Rim lighting terms + SHADER_PARAM( RIMLIGHT, SHADER_PARAM_TYPE_BOOL, "0", "enables rim lighting" ) + SHADER_PARAM( RIMLIGHTEXPONENT, SHADER_PARAM_TYPE_FLOAT, "4.0", "Exponent for rim lights" ) + SHADER_PARAM( RIMLIGHTBOOST, SHADER_PARAM_TYPE_FLOAT, "1.0", "Boost for rim lights" ) + SHADER_PARAM( RIMMASK, SHADER_PARAM_TYPE_BOOL, "0", "Indicates whether or not to use alpha channel of exponent texture to mask the rim term" ) + + // Seamless mapping scale + SHADER_PARAM( SEAMLESS_BASE, SHADER_PARAM_TYPE_BOOL, "0", "whether to apply seamless mapping to the base texture. requires a smooth model." ) + SHADER_PARAM( SEAMLESS_DETAIL, SHADER_PARAM_TYPE_BOOL, "0", "where to apply seamless mapping to the detail texture." ) + SHADER_PARAM( SEAMLESS_SCALE, SHADER_PARAM_TYPE_FLOAT, "1.0", "the scale for the seamless mapping. # of repetions of texture per inch." ) + + // Emissive Scroll Pass + SHADER_PARAM( EMISSIVEBLENDENABLED, SHADER_PARAM_TYPE_BOOL, "0", "Enable emissive blend pass" ) + SHADER_PARAM( EMISSIVEBLENDBASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "self-illumination map" ) + SHADER_PARAM( EMISSIVEBLENDSCROLLVECTOR, SHADER_PARAM_TYPE_VEC2, "[0.11 0.124]", "Emissive scroll vec" ) + SHADER_PARAM( EMISSIVEBLENDSTRENGTH, SHADER_PARAM_TYPE_FLOAT, "1.0", "Emissive blend strength" ) + SHADER_PARAM( EMISSIVEBLENDTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "self-illumination map" ) + SHADER_PARAM( EMISSIVEBLENDTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Self-illumination tint" ) + SHADER_PARAM( EMISSIVEBLENDFLOWTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "flow map" ) + SHADER_PARAM( TIME, SHADER_PARAM_TYPE_FLOAT, "0.0", "Needs CurrentTime Proxy" ) + + // Cloak Pass + SHADER_PARAM( CLOAKPASSENABLED, SHADER_PARAM_TYPE_BOOL, "0", "Enables cloak render in a second pass" ) + SHADER_PARAM( CLOAKFACTOR, SHADER_PARAM_TYPE_FLOAT, "0.0", "" ) + SHADER_PARAM( CLOAKCOLORTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Cloak color tint" ) + SHADER_PARAM( REFRACTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "2", "" ) + + // Flesh Interior Pass + SHADER_PARAM( FLESHINTERIORENABLED, SHADER_PARAM_TYPE_BOOL, "0", "Enable Flesh interior blend pass" ) + SHADER_PARAM( FLESHINTERIORTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh color texture" ) + SHADER_PARAM( FLESHINTERIORNOISETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh noise texture" ) + SHADER_PARAM( FLESHBORDERTEXTURE1D, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh border 1D texture" ) + SHADER_PARAM( FLESHNORMALTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh normal texture" ) + SHADER_PARAM( FLESHSUBSURFACETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh subsurface texture" ) + SHADER_PARAM( FLESHCUBETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh cubemap texture" ) + SHADER_PARAM( FLESHBORDERNOISESCALE, SHADER_PARAM_TYPE_FLOAT, "1.5", "Flesh Noise UV scalar for border" ) + SHADER_PARAM( FLESHDEBUGFORCEFLESHON, SHADER_PARAM_TYPE_BOOL, "0", "Flesh Debug full flesh" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS1, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS2, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS3, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS4, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHSUBSURFACETINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Subsurface Color" ) + SHADER_PARAM( FLESHBORDERWIDTH, SHADER_PARAM_TYPE_FLOAT, "0.3", "Flesh border" ) + SHADER_PARAM( FLESHBORDERSOFTNESS, SHADER_PARAM_TYPE_FLOAT, "0.42", "Flesh border softness (> 0.0 && <= 0.5)" ) + SHADER_PARAM( FLESHBORDERTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Flesh border Color" ) + SHADER_PARAM( FLESHGLOBALOPACITY, SHADER_PARAM_TYPE_FLOAT, "1.0", "Flesh global opacity" ) + SHADER_PARAM( FLESHGLOSSBRIGHTNESS, SHADER_PARAM_TYPE_FLOAT, "0.66", "Flesh gloss brightness" ) + SHADER_PARAM( FLESHSCROLLSPEED, SHADER_PARAM_TYPE_FLOAT, "1.0", "Flesh scroll speed" ) + + SHADER_PARAM( SEPARATEDETAILUVS, SHADER_PARAM_TYPE_BOOL, "0", "Use texcoord1 for detail texture" ) + SHADER_PARAM( LINEARWRITE, SHADER_PARAM_TYPE_INTEGER, "0", "Disables SRGB conversion of shader results." ) + + SHADER_PARAM( SHADERSRGBREAD360, SHADER_PARAM_TYPE_BOOL, "0", "Simulate srgb read in shader code") + + SHADER_PARAM( AMBIENTOCCLUSION, SHADER_PARAM_TYPE_FLOAT, "0.0", "Amount of screen space ambient occlusion to use (0..1 range)") + + SHADER_PARAM( DISPLACEMENTMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "Displacement map" ) + SHADER_PARAM( DISPLACEMENTWRINKLE, SHADER_PARAM_TYPE_BOOL, "0", "Displacement map contains wrinkle displacements") + + SHADER_PARAM( BLENDTINTBYBASEALPHA, SHADER_PARAM_TYPE_BOOL, "0", "Use the base alpha to blend in the $color modulation") + + SHADER_PARAM( DESATURATEWITHBASEALPHA, SHADER_PARAM_TYPE_FLOAT, "0.0", "Use the base alpha to desaturate the base texture. Set to non-zero to enable, value gets multiplied into the alpha channel before desaturating.") + + SHADER_PARAM( ALLOWDIFFUSEMODULATION, SHADER_PARAM_TYPE_BOOL, "1", "Allow per-instance color modulation") + + // vertexlitgeneric envmap fresnel control + SHADER_PARAM( ENVMAPFRESNELMINMAXEXP, SHADER_PARAM_TYPE_VEC3, "[0.0 1.0 2.0]", "Min/max fresnel range and exponent for vertexlitgeneric" ) + SHADER_PARAM( BASEALPHAENVMAPMASKMINMAXEXP, SHADER_PARAM_TYPE_VEC3, "[1.0 0.0 1.0]", "" ) + + // This is to allow phong materials to disable half lambert. Half lambert has always been forced on in phong, + // so the only safe way to allow artists to disable half lambert is to create this param that disables the + // default behavior of forcing half lambert on. + SHADER_PARAM( PHONGDISABLEHALFLAMBERT, SHADER_PARAM_TYPE_BOOL, "0", "Disable half lambert for phong") + + SHADER_PARAM( FOW, SHADER_PARAM_TYPE_TEXTURE, "", "FoW Render Target" ) + + // vertexlitgeneric tree sway animation control + SHADER_PARAM( TREESWAY, SHADER_PARAM_TYPE_INTEGER, "0", "" ); + SHADER_PARAM( TREESWAYHEIGHT, SHADER_PARAM_TYPE_FLOAT, "1000", "" ); + SHADER_PARAM( TREESWAYSTARTHEIGHT, SHADER_PARAM_TYPE_FLOAT, "0.2", "" ); + SHADER_PARAM( TREESWAYRADIUS, SHADER_PARAM_TYPE_FLOAT, "300", "" ); + SHADER_PARAM( TREESWAYSTARTRADIUS, SHADER_PARAM_TYPE_FLOAT, "0.1", "" ); + SHADER_PARAM( TREESWAYSPEED, SHADER_PARAM_TYPE_FLOAT, "1", "" ); + SHADER_PARAM( TREESWAYSPEEDHIGHWINDMULTIPLIER, SHADER_PARAM_TYPE_FLOAT, "2", "" ); + SHADER_PARAM( TREESWAYSTRENGTH, SHADER_PARAM_TYPE_FLOAT, "10", "" ); + SHADER_PARAM( TREESWAYSCRUMBLESPEED, SHADER_PARAM_TYPE_FLOAT, "0.1", "" ); + SHADER_PARAM( TREESWAYSCRUMBLESTRENGTH, SHADER_PARAM_TYPE_FLOAT, "0.1", "" ); + SHADER_PARAM( TREESWAYSCRUMBLEFREQUENCY, SHADER_PARAM_TYPE_FLOAT, "0.1", "" ); + SHADER_PARAM( TREESWAYFALLOFFEXP, SHADER_PARAM_TYPE_FLOAT, "1.5", "" ); + SHADER_PARAM( TREESWAYSCRUMBLEFALLOFFEXP, SHADER_PARAM_TYPE_FLOAT, "1.0", "" ); + SHADER_PARAM( TREESWAYSPEEDLERPSTART, SHADER_PARAM_TYPE_FLOAT, "3", "" ); + SHADER_PARAM( TREESWAYSPEEDLERPEND, SHADER_PARAM_TYPE_FLOAT, "6", "" ); + END_SHADER_PARAMS + + void SetupVars( VertexLitGeneric_DX9_Vars_t& info ) + { + info.m_nBaseTexture = BASETEXTURE; + info.m_nWrinkle = COMPRESS; + info.m_nStretch = STRETCH; + info.m_nBaseTextureFrame = FRAME; + info.m_nBaseTextureTransform = BASETEXTURETRANSFORM; + info.m_nAlbedo = ALBEDO; + info.m_nSelfIllumTint = SELFILLUMTINT; + info.m_nDetail = DETAIL; + info.m_nDetailFrame = DETAILFRAME; + info.m_nDetailScale = DETAILSCALE; + info.m_nEnvmap = ENVMAP; + info.m_nEnvmapFrame = ENVMAPFRAME; + info.m_nEnvmapMask = ENVMAPMASK; + info.m_nEnvmapMaskFrame = ENVMAPMASKFRAME; + info.m_nEnvmapMaskTransform = ENVMAPMASKTRANSFORM; + info.m_nEnvmapTint = ENVMAPTINT; + info.m_nBumpmap = BUMPMAP; + info.m_nNormalWrinkle = BUMPCOMPRESS; + info.m_nNormalStretch = BUMPSTRETCH; + info.m_nBumpFrame = BUMPFRAME; + info.m_nBumpTransform = BUMPTRANSFORM; + info.m_nEnvmapContrast = ENVMAPCONTRAST; + info.m_nEnvmapSaturation = ENVMAPSATURATION; + info.m_nAlphaTestReference = ALPHATESTREFERENCE; + info.m_nFlashlightNoLambert = FLASHLIGHTNOLAMBERT; + + info.m_nFlashlightTexture = FLASHLIGHTTEXTURE; + info.m_nFlashlightTextureFrame = FLASHLIGHTTEXTUREFRAME; + info.m_nSelfIllumEnvMapMask_Alpha = SELFILLUM_ENVMAPMASK_ALPHA; + info.m_nSelfIllumFresnel = SELFILLUMFRESNEL; + info.m_nSelfIllumFresnelMinMaxExp = SELFILLUMFRESNELMINMAXEXP; + info.m_nSelfIllumMaskScale = SELFILLUMMASKSCALE; + + info.m_nAmbientOnly = AMBIENTONLY; + info.m_nPhongExponent = PHONGEXPONENT; + info.m_nPhongExponentTexture = PHONGEXPONENTTEXTURE; + info.m_nPhongTint = PHONGTINT; + info.m_nPhongAlbedoTint = PHONGALBEDOTINT; + info.m_nDiffuseWarpTexture = LIGHTWARPTEXTURE; + info.m_nPhongWarpTexture = PHONGWARPTEXTURE; + info.m_nPhongBoost = PHONGBOOST; + info.m_nPhongFresnelRanges = PHONGFRESNELRANGES; + info.m_nPhong = PHONG; + info.m_nBaseMapAlphaPhongMask = BASEMAPALPHAPHONGMASK; + info.m_nEnvmapFresnel = ENVMAPFRESNEL; + info.m_nDetailTextureCombineMode = DETAILBLENDMODE; + info.m_nDetailTextureBlendFactor = DETAILBLENDFACTOR; + info.m_nDetailTextureTransform = DETAILTEXTURETRANSFORM; + + info.m_nBaseMapLuminancePhongMask = BASEMAPLUMINANCEPHONGMASK; + + // Rim lighting parameters + info.m_nRimLight = RIMLIGHT; + info.m_nRimLightPower = RIMLIGHTEXPONENT; + info.m_nRimLightBoost = RIMLIGHTBOOST; + info.m_nRimMask = RIMMASK; + + // seamless + info.m_nSeamlessScale = SEAMLESS_SCALE; + info.m_nSeamlessDetail = SEAMLESS_DETAIL; + info.m_nSeamlessBase = SEAMLESS_BASE; + + info.m_nSeparateDetailUVs = SEPARATEDETAILUVS; + + info.m_nLinearWrite = LINEARWRITE; + info.m_nDetailTint = DETAILTINT; + info.m_nInvertPhongMask = INVERTPHONGMASK; + + info.m_nSelfIllumMask = SELFILLUMMASK; + + info.m_nShaderSrgbRead360 = SHADERSRGBREAD360; + + info.m_nAmbientOcclusion = AMBIENTOCCLUSION; + + info.m_nBlendTintByBaseAlpha = BLENDTINTBYBASEALPHA; + + info.m_nDesaturateWithBaseAlpha = DESATURATEWITHBASEALPHA; + + info.m_nAllowDiffuseModulation = ALLOWDIFFUSEMODULATION; + + info.m_nEnvMapFresnelMinMaxExp = ENVMAPFRESNELMINMAXEXP; + info.m_nBaseAlphaEnvMapMaskMinMaxExp = BASEALPHAENVMAPMASKMINMAXEXP; + info.m_nDisplacementMap = DISPLACEMENTMAP; + + info.m_nDisplacementWrinkleMap = DISPLACEMENTWRINKLE; + + info.m_nPhongDisableHalfLambert = PHONGDISABLEHALFLAMBERT; + + info.m_nFoW = FOW; + + info.m_nTreeSway = TREESWAY; + info.m_nTreeSwayHeight = TREESWAYHEIGHT; + info.m_nTreeSwayStartHeight = TREESWAYSTARTHEIGHT; + info.m_nTreeSwayRadius = TREESWAYRADIUS; + info.m_nTreeSwayStartRadius = TREESWAYSTARTRADIUS; + info.m_nTreeSwaySpeed = TREESWAYSPEED; + info.m_nTreeSwaySpeedHighWindMultiplier = TREESWAYSPEEDHIGHWINDMULTIPLIER; + info.m_nTreeSwayStrength = TREESWAYSTRENGTH; + info.m_nTreeSwayScrumbleSpeed = TREESWAYSCRUMBLESPEED; + info.m_nTreeSwayScrumbleStrength = TREESWAYSCRUMBLESTRENGTH; + info.m_nTreeSwayScrumbleFrequency = TREESWAYSCRUMBLEFREQUENCY; + info.m_nTreeSwayFalloffExp = TREESWAYFALLOFFEXP; + info.m_nTreeSwayScrumbleFalloffExp = TREESWAYSCRUMBLEFALLOFFEXP; + info.m_nTreeSwaySpeedLerpStart = TREESWAYSPEEDLERPSTART; + info.m_nTreeSwaySpeedLerpEnd = TREESWAYSPEEDLERPEND; + } + + // Cloak Pass + void SetupVarsCloakBlendedPass( CloakBlendedPassVars_t &info ) + { + info.m_nCloakFactor = CLOAKFACTOR; + info.m_nCloakColorTint = CLOAKCOLORTINT; + info.m_nRefractAmount = REFRACTAMOUNT; + + // Delete these lines if not bump mapping! + info.m_nBumpmap = BUMPMAP; + info.m_nBumpFrame = BUMPFRAME; + info.m_nBumpTransform = BUMPTRANSFORM; + } + + bool NeedsPowerOfTwoFrameBufferTexture( IMaterialVar **params, bool bCheckSpecificToThisFrame ) const + { + if ( params[CLOAKPASSENABLED]->GetIntValue() ) // If material supports cloaking + { + if ( bCheckSpecificToThisFrame == false ) // For setting model flag at load time + return true; + else if ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) // Per-frame check + return true; + // else, not cloaking this frame, so check flag2 in case the base material still needs it + } + + // Check flag2 if not drawing cloak pass + return IS_FLAG2_SET( MATERIAL_VAR2_NEEDS_POWER_OF_TWO_FRAME_BUFFER_TEXTURE ); + } + + bool IsTranslucent( IMaterialVar **params ) const + { + if ( params[CLOAKPASSENABLED]->GetIntValue() ) // If material supports cloaking + { + if ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) // Per-frame check + return true; + // else, not cloaking this frame, so check flag in case the base material still needs it + } + + // Check flag if not drawing cloak pass + return IS_FLAG_SET( MATERIAL_VAR_TRANSLUCENT ); + } + + // Emissive Scroll Pass + void SetupVarsEmissiveScrollBlendedPass( EmissiveScrollBlendedPassVars_t &info ) + { + info.m_nBlendStrength = EMISSIVEBLENDSTRENGTH; + info.m_nBaseTexture = EMISSIVEBLENDBASETEXTURE; + info.m_nFlowTexture = EMISSIVEBLENDFLOWTEXTURE; + info.m_nEmissiveTexture = EMISSIVEBLENDTEXTURE; + info.m_nEmissiveTint = EMISSIVEBLENDTINT; + info.m_nEmissiveScrollVector = EMISSIVEBLENDSCROLLVECTOR; + info.m_nTime = TIME; + } + + // Flesh Interior Pass + void SetupVarsFleshInteriorBlendedPass( FleshInteriorBlendedPassVars_t &info ) + { + info.m_nFleshTexture = FLESHINTERIORTEXTURE; + info.m_nFleshNoiseTexture = FLESHINTERIORNOISETEXTURE; + info.m_nFleshBorderTexture1D = FLESHBORDERTEXTURE1D; + info.m_nFleshNormalTexture = FLESHNORMALTEXTURE; + info.m_nFleshSubsurfaceTexture = FLESHSUBSURFACETEXTURE; + info.m_nFleshCubeTexture = FLESHCUBETEXTURE; + + info.m_nflBorderNoiseScale = FLESHBORDERNOISESCALE; + info.m_nflDebugForceFleshOn = FLESHDEBUGFORCEFLESHON; + info.m_nvEffectCenterRadius1 = FLESHEFFECTCENTERRADIUS1; + info.m_nvEffectCenterRadius2 = FLESHEFFECTCENTERRADIUS2; + info.m_nvEffectCenterRadius3 = FLESHEFFECTCENTERRADIUS3; + info.m_nvEffectCenterRadius4 = FLESHEFFECTCENTERRADIUS4; + + info.m_ncSubsurfaceTint = FLESHSUBSURFACETINT; + info.m_nflBorderWidth = FLESHBORDERWIDTH; + info.m_nflBorderSoftness = FLESHBORDERSOFTNESS; + info.m_ncBorderTint = FLESHBORDERTINT; + info.m_nflGlobalOpacity = FLESHGLOBALOPACITY; + info.m_nflGlossBrightness = FLESHGLOSSBRIGHTNESS; + info.m_nflScrollSpeed = FLESHSCROLLSPEED; + + info.m_nTime = TIME; + } + + SHADER_INIT_PARAMS() + { + VertexLitGeneric_DX9_Vars_t vars; + SetupVars( vars ); + InitParamsVertexLitGeneric_DX9( this, params, pMaterialName, true, vars ); + + // Cloak Pass + if ( !params[CLOAKPASSENABLED]->IsDefined() ) + { + params[CLOAKPASSENABLED]->SetIntValue( 0 ); + } + else if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + InitParamsCloakBlendedPass( this, params, pMaterialName, info ); + } + + // Emissive Scroll Pass + if ( !params[EMISSIVEBLENDENABLED]->IsDefined() ) + { + params[EMISSIVEBLENDENABLED]->SetIntValue( 0 ); + } + else if ( params[EMISSIVEBLENDENABLED]->GetIntValue() ) + { + EmissiveScrollBlendedPassVars_t info; + SetupVarsEmissiveScrollBlendedPass( info ); + InitParamsEmissiveScrollBlendedPass( this, params, pMaterialName, info ); + } + + // Flesh Interior Pass + if ( !params[FLESHINTERIORENABLED]->IsDefined() ) + { + params[FLESHINTERIORENABLED]->SetIntValue( 0 ); + } + else if ( params[FLESHINTERIORENABLED]->GetIntValue() ) + { + FleshInteriorBlendedPassVars_t info; + SetupVarsFleshInteriorBlendedPass( info ); + InitParamsFleshInteriorBlendedPass( this, params, pMaterialName, info ); + } + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + VertexLitGeneric_DX9_Vars_t vars; + SetupVars( vars ); + InitVertexLitGeneric_DX9( this, params, true, vars ); + + // Cloak Pass + if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + InitCloakBlendedPass( this, params, info ); + } + + // Emissive Scroll Pass + if ( params[EMISSIVEBLENDENABLED]->GetIntValue() ) + { + EmissiveScrollBlendedPassVars_t info; + SetupVarsEmissiveScrollBlendedPass( info ); + InitEmissiveScrollBlendedPass( this, params, info ); + } + + // Flesh Interior Pass + if ( params[FLESHINTERIORENABLED]->GetIntValue() ) + { + FleshInteriorBlendedPassVars_t info; + SetupVarsFleshInteriorBlendedPass( info ); + InitFleshInteriorBlendedPass( this, params, info ); + } + } + + SHADER_DRAW + { + // Skip the standard rendering if cloak pass is fully opaque + bool bDrawStandardPass = true; + if ( params[CLOAKPASSENABLED]->GetIntValue() && ( pShaderShadow == NULL ) ) // && not snapshotting + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + if ( CloakBlendedPassIsFullyOpaque( params, info ) ) + { + bDrawStandardPass = false; + } + } + + // Standard rendering pass + if ( bDrawStandardPass ) + { + VertexLitGeneric_DX9_Vars_t vars; + SetupVars( vars ); + DrawVertexLitGeneric_DX9( this, params, pShaderAPI, pShaderShadow, true, vars, vertexCompression, pContextDataPtr ); + } + else + { + // Skip this pass! + Draw( false ); + } + + // Cloak Pass + if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + // If ( snapshotting ) or ( we need to draw this frame ) + if ( ( pShaderShadow != NULL ) || ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + DrawCloakBlendedPass( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else // We're not snapshotting and we don't need to draw this frame + { + // Skip this pass! + Draw( false ); + } + } + + // Emissive Scroll Pass + if ( params[EMISSIVEBLENDENABLED]->GetIntValue() ) + { + // If ( snapshotting ) or ( we need to draw this frame ) + if ( ( pShaderShadow != NULL ) || ( params[EMISSIVEBLENDSTRENGTH]->GetFloatValue() > 0.0f ) ) + { + EmissiveScrollBlendedPassVars_t info; + SetupVarsEmissiveScrollBlendedPass( info ); + DrawEmissiveScrollBlendedPass( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else // We're not snapshotting and we don't need to draw this frame + { + // Skip this pass! + Draw( false ); + } + } + + // Flesh Interior Pass + if ( params[FLESHINTERIORENABLED]->GetIntValue() ) + { + // If ( snapshotting ) or ( we need to draw this frame ) + if ( ( pShaderShadow != NULL ) || ( true ) ) + { + FleshInteriorBlendedPassVars_t info; + SetupVarsFleshInteriorBlendedPass( info ); + DrawFleshInteriorBlendedPass( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else // We're not snapshotting and we don't need to draw this frame + { + // Skip this pass! + Draw( false ); + } + } + } +END_SHADER diff --git a/materialsystem/stdshaders/vertexlitgeneric_dx9_helper.cpp b/materialsystem/stdshaders/vertexlitgeneric_dx9_helper.cpp new file mode 100644 index 00000000..d2f1d570 --- /dev/null +++ b/materialsystem/stdshaders/vertexlitgeneric_dx9_helper.cpp @@ -0,0 +1,1698 @@ +//====== Copyright © 1996-2008, Valve Corporation, All rights reserved. =====// +// +// Purpose: +// +// $NoKeywords: $ +// +//===========================================================================// +#include "basevsshader.h" +#include "vertexlitgeneric_dx9_helper.h" +#include "phong_dx9_helper.h" + +#include "vertexlit_and_unlit_generic_vs20.inc" +#include "vertexlit_and_unlit_generic_bump_vs20.inc" + +#include "vertexlit_and_unlit_generic_ps20.inc" +#include "vertexlit_and_unlit_generic_ps20b.inc" +#include "vertexlit_and_unlit_generic_bump_ps20.inc" +#include "vertexlit_and_unlit_generic_bump_ps20b.inc" + +#ifndef _X360 + #include "vertexlit_and_unlit_generic_vs30.inc" + #include "vertexlit_and_unlit_generic_ps30.inc" + #include "vertexlit_and_unlit_generic_bump_vs30.inc" + #include "vertexlit_and_unlit_generic_bump_ps30.inc" +#endif + +#include "shaderlib/commandbuilder.h" +#include "convar.h" + +#include "tier0/vprof.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +static ConVar mat_fullbright( "mat_fullbright","0", FCVAR_CHEAT ); +static ConVar r_lightwarpidentity( "r_lightwarpidentity","0", FCVAR_CHEAT ); +static ConVar mat_phong( "mat_phong", "1" ); +static ConVar mat_displacementmap( "mat_displacementmap", "1", FCVAR_CHEAT ); + +extern ConVar lm_test; +static ConVar mat_force_vertexfog( "mat_force_vertexfog", "0", FCVAR_DEVELOPMENTONLY ); + +static inline bool WantsPhongShader( IMaterialVar** params, const VertexLitGeneric_DX9_Vars_t &info ) +{ + if ( !mat_phong.GetBool() ) + { + return false; + } + if ( info.m_nPhong == -1) // Don't use without Phong flag + return false; + + if ( params[info.m_nPhong]->GetIntValue() == 0 ) // Don't use without Phong flag set to 1 + return false; + + if ( ( info.m_nDiffuseWarpTexture != -1 ) && params[info.m_nDiffuseWarpTexture]->IsTexture() ) // If there's Phong flag and diffuse warp do Phong + return true; + + if ( ( info.m_nBaseMapAlphaPhongMask != -1 ) && params[info.m_nBaseMapAlphaPhongMask]->GetIntValue() != 1 ) + { + if ( info.m_nBumpmap == -1 ) // Don't use without a bump map + return false; + + if ( !params[info.m_nBumpmap]->IsDefined() ) // Don't use if the texture isn't specified + return false; + } + + return true; +} + + +//----------------------------------------------------------------------------- +// Initialize shader parameters +//----------------------------------------------------------------------------- +void InitParamsVertexLitGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, bool bVertexLitGeneric, VertexLitGeneric_DX9_Vars_t &info ) +{ + InitIntParam( info.m_nShaderSrgbRead360, params, 0 ); + + InitIntParam( info.m_nPhong, params, 0 ); + + InitFloatParam( info.m_nAlphaTestReference, params, 0.0f ); + InitIntParam( info.m_nVertexAlphaTest, params, 0 ); + + InitIntParam( info.m_nFlashlightNoLambert, params, 0 ); + + if ( info.m_nDetailTint != -1 && !params[info.m_nDetailTint]->IsDefined() ) + { + params[info.m_nDetailTint]->SetVecValue( 1.0f, 1.0f, 1.0f ); + } + + if ( info.m_nEnvmapTint != -1 && !params[info.m_nEnvmapTint]->IsDefined() ) + { + params[info.m_nEnvmapTint]->SetVecValue( 1.0f, 1.0f, 1.0f ); + } + + InitIntParam( info.m_nEnvmapFrame, params, 0 ); + InitIntParam( info.m_nBumpFrame, params, 0 ); + InitFloatParam( info.m_nDetailTextureBlendFactor, params, 1.0 ); + InitIntParam( info.m_nReceiveFlashlight, params, 0 ); + + InitFloatParam( info.m_nDetailScale, params, 4.0f ); + + if ( (info.m_nSelfIllumTint != -1) && (!params[info.m_nSelfIllumTint]->IsDefined()) ) + { + params[info.m_nSelfIllumTint]->SetVecValue( 1.0f, 1.0f, 1.0f ); + } + + // Set the selfillummask flag2 + if ( ( info.m_nSelfIllumMask != -1 ) && ( params[info.m_nSelfIllumMask]->IsDefined() ) ) + { + SET_FLAGS2( MATERIAL_VAR2_SELFILLUMMASK ); + } + + InitFloatParam( info.m_nSelfIllumMaskScale, params, 1.0f ); + + // Override vertex fog via the global setting if it isn't enabled/disabled in the material file. + if ( !IS_FLAG_DEFINED( MATERIAL_VAR_VERTEXFOG ) && mat_force_vertexfog.GetBool() ) + { + SET_FLAGS( MATERIAL_VAR_VERTEXFOG ); + } + + if ( WantsPhongShader( params, info ) ) + { + if ( !g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + params[info.m_nPhong]->SetIntValue( 0 ); + } + else + { + InitParamsPhong_DX9( pShader, params, pMaterialName, info ); + return; + } + } + + // FLASHLIGHTFIXME: Do ShaderAPI::BindFlashlightTexture + if ( info.m_nFlashlightTexture != -1 ) + { + params[FLASHLIGHTTEXTURE]->SetStringValue( GetFlashlightTextureFilename() ); + } + + // Write over $basetexture with $info.m_nBumpmap if we are going to be using diffuse normal mapping. + if ( info.m_nAlbedo != -1 && g_pConfig->UseBumpmapping() && info.m_nBumpmap != -1 && params[info.m_nBumpmap]->IsDefined() && params[info.m_nAlbedo]->IsDefined() && + params[info.m_nBaseTexture]->IsDefined() ) + { + params[info.m_nBaseTexture]->SetStringValue( params[info.m_nAlbedo]->GetStringValue() ); + } + + // This shader can be used with hw skinning + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + + if ( bVertexLitGeneric ) + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + } + else + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + } + + InitIntParam( info.m_nEnvmapMaskFrame, params, 0 ); + InitFloatParam( info.m_nEnvmapContrast, params, 0.0 ); + InitFloatParam( info.m_nEnvmapSaturation, params, 1.0f ); + InitFloatParam( info.m_nSeamlessScale, params, 0.0 ); + + // handle line art parms + InitFloatParam( info.m_nEdgeSoftnessStart, params, 0.5 ); + InitFloatParam( info.m_nEdgeSoftnessEnd, params, 0.5 ); + InitFloatParam( info.m_nGlowAlpha, params, 1.0 ); + InitFloatParam( info.m_nOutlineAlpha, params, 1.0 ); + + // No texture means no self-illum or env mask in base alpha + if ( info.m_nBaseTexture != -1 && !params[info.m_nBaseTexture]->IsDefined() ) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + // If in decal mode, no debug override... + if (IS_FLAG_SET(MATERIAL_VAR_DECAL)) + { + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + } + + if( ( (info.m_nBumpmap != -1) && g_pConfig->UseBumpmapping() && params[info.m_nBumpmap]->IsDefined() ) + // we don't need a tangent space if we have envmap without bumpmap + // || ( info.m_nEnvmap != -1 && params[info.m_nEnvmap]->IsDefined() ) + ) + { + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + } + else if ( bVertexLitGeneric && (info.m_nDiffuseWarpTexture != -1) && params[info.m_nDiffuseWarpTexture]->IsDefined() ) // diffuse warp goes down bump path... + { + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + } + else // no tangent space needed + { + CLEAR_FLAGS( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ); + } + + bool hasNormalMapAlphaEnvmapMask = IS_FLAG_SET( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ); + if ( hasNormalMapAlphaEnvmapMask ) + { + params[info.m_nEnvmapMask]->SetUndefined(); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + if ( IS_FLAG_SET( MATERIAL_VAR_BASEALPHAENVMAPMASK ) && info.m_nBumpmap != -1 && + params[info.m_nBumpmap]->IsDefined() && !hasNormalMapAlphaEnvmapMask ) + { + Warning( "material %s has a normal map and $basealphaenvmapmask. Must use $normalmapalphaenvmapmask to get specular.\n\n", pMaterialName ); + params[info.m_nEnvmap]->SetUndefined(); + } + + if ( info.m_nEnvmapMask != -1 && params[info.m_nEnvmapMask]->IsDefined() && info.m_nBumpmap != -1 && params[info.m_nBumpmap]->IsDefined() ) + { + params[info.m_nEnvmapMask]->SetUndefined(); + if ( !hasNormalMapAlphaEnvmapMask ) + { + Warning( "material %s has a normal map and an envmapmask. Must use $normalmapalphaenvmapmask.\n\n", pMaterialName ); + params[info.m_nEnvmap]->SetUndefined(); + } + } + + // If mat_specular 0, then get rid of envmap + if ( !g_pConfig->UseSpecular() && info.m_nEnvmap != -1 && params[info.m_nEnvmap]->IsDefined() && params[info.m_nBaseTexture]->IsDefined() ) + { + params[info.m_nEnvmap]->SetUndefined(); + } + + InitFloatParam( info.m_nHDRColorScale, params, 1.0f ); + + InitIntParam( info.m_nLinearWrite, params, 0 ); + InitIntParam( info.m_nGammaColorRead, params, 0 ); + + InitIntParam( info.m_nAllowDiffuseModulation, params, 1 ); + + if ( ( info.m_nEnvMapFresnelMinMaxExp != -1 ) && !params[info.m_nEnvMapFresnelMinMaxExp]->IsDefined() ) + { + params[info.m_nEnvMapFresnelMinMaxExp]->SetVecValue( 0.0f, 1.0f, 2.0f, 0.0f ); + } + if ( ( info.m_nBaseAlphaEnvMapMaskMinMaxExp != -1 ) && !params[info.m_nBaseAlphaEnvMapMaskMinMaxExp]->IsDefined() ) + { + // Default to min: 1 max: 0 exp: 1 so that we default to the legacy behavior for basealphaenvmapmask, which is 1-baseColor.a + // These default values translate to a scale of -1, bias of 1 and exponent 1 in the shader. + params[info.m_nBaseAlphaEnvMapMaskMinMaxExp]->SetVecValue( 1.0f, 0.0f, 1.0f, 0.0f ); + } + + InitIntParam( info.m_nTreeSway, params, 0 ); + InitFloatParam( info.m_nTreeSwayHeight, params, 1000.0f ); + InitFloatParam( info.m_nTreeSwayStartHeight, params, 0.1f ); + InitFloatParam( info.m_nTreeSwayRadius, params, 300.0f ); + InitFloatParam( info.m_nTreeSwayStartRadius, params, 0.2f ); + InitFloatParam( info.m_nTreeSwaySpeed, params, 1.0f ); + InitFloatParam( info.m_nTreeSwaySpeedHighWindMultiplier, params, 2.0f ); + InitFloatParam( info.m_nTreeSwayStrength, params, 10.0f ); + InitFloatParam( info.m_nTreeSwayScrumbleSpeed, params, 5.0f ); + InitFloatParam( info.m_nTreeSwayScrumbleStrength, params, 10.0f ); + InitFloatParam( info.m_nTreeSwayScrumbleFrequency, params, 12.0f ); + InitFloatParam( info.m_nTreeSwayFalloffExp, params, 1.5f ); + InitFloatParam( info.m_nTreeSwayScrumbleFalloffExp, params, 1.0f ); + InitFloatParam( info.m_nTreeSwaySpeedLerpStart, params, 3.0f ); + InitFloatParam( info.m_nTreeSwaySpeedLerpEnd, params, 6.0f ); +} + + +//----------------------------------------------------------------------------- +// Initialize shader +//----------------------------------------------------------------------------- + +void InitVertexLitGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, bool bVertexLitGeneric, VertexLitGeneric_DX9_Vars_t &info ) +{ + // both detailed and bumped = needs Phong shader (for now) + bool bNeedsPhongBecauseOfDetail = false; + + //bool bHasBump = ( info.m_nBumpmap != -1 ) && params[info.m_nBumpmap]->IsTexture(); + //if ( bHasBump ) + //{ + // if ( ( info.m_nDetail != -1 ) && params[info.m_nDetail]->IsDefined() ) + // bNeedsPhongBecauseOfDetail = true; + //} + + if ( bNeedsPhongBecauseOfDetail || + ( info.m_nPhong != -1 && + params[info.m_nPhong]->GetIntValue() ) && + g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + if ( mat_phong.GetBool() ) + { + InitPhong_DX9( pShader, params, info ); + return; + } + } + + if ( info.m_nFlashlightTexture != -1 ) + { + pShader->LoadTexture( info.m_nFlashlightTexture ); + } + + bool bIsBaseTextureTranslucent = false; + if ( info.m_nBaseTexture != -1 && params[info.m_nBaseTexture]->IsDefined() ) + { + pShader->LoadTexture( info.m_nBaseTexture ); + + if ( params[info.m_nBaseTexture]->GetTextureValue()->IsTranslucent() ) + { + bIsBaseTextureTranslucent = true; + } + } + + bool bHasSelfIllumMask = IS_FLAG_SET( MATERIAL_VAR_SELFILLUM ) && (info.m_nSelfIllumMask != -1) && params[info.m_nSelfIllumMask]->IsDefined(); + + // No alpha channel in any of the textures? No self illum or envmapmask + if ( !bIsBaseTextureTranslucent ) + { + bool bHasSelfIllumFresnel = IS_FLAG_SET( MATERIAL_VAR_SELFILLUM ) && ( info.m_nSelfIllumFresnel != -1 ) && ( params[info.m_nSelfIllumFresnel]->GetIntValue() != 0 ); + + // Can still be self illum with no base alpha if using one of these alternate modes + if ( !bHasSelfIllumFresnel && !bHasSelfIllumMask ) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + } + + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + if ( info.m_nDetail != -1 && params[info.m_nDetail]->IsDefined() ) + { + int nDetailBlendMode = ( info.m_nDetailTextureCombineMode == -1 ) ? 0 : params[info.m_nDetailTextureCombineMode]->GetIntValue(); + if ( nDetailBlendMode == 0 ) // Mod2X + pShader->LoadTexture( info.m_nDetail ); + else + pShader->LoadTexture( info.m_nDetail ); + } + + if ( g_pConfig->UseBumpmapping() ) + { + if ( (info.m_nBumpmap != -1) && params[info.m_nBumpmap]->IsDefined() ) + { + pShader->LoadBumpMap( info.m_nBumpmap ); + SET_FLAGS2( MATERIAL_VAR2_DIFFUSE_BUMPMAPPED_MODEL ); + } + else if ( (info.m_nDiffuseWarpTexture != -1) && params[info.m_nDiffuseWarpTexture]->IsDefined() ) + { + SET_FLAGS2( MATERIAL_VAR2_DIFFUSE_BUMPMAPPED_MODEL ); + } + } + + // Don't alpha test if the alpha channel is used for other purposes + if ( ( IS_FLAG_SET( MATERIAL_VAR_SELFILLUM) && !IS_FLAG2_SET( MATERIAL_VAR2_SELFILLUMMASK ) ) || IS_FLAG_SET( MATERIAL_VAR_BASEALPHAENVMAPMASK ) ) + { + CLEAR_FLAGS( MATERIAL_VAR_ALPHATEST ); + } + + if ( info.m_nEnvmap != -1 && params[info.m_nEnvmap]->IsDefined() ) + { + pShader->LoadCubeMap( info.m_nEnvmap ); + } + + if ( info.m_nEnvmapMask != -1 && params[info.m_nEnvmapMask]->IsDefined() ) + { + pShader->LoadTexture( info.m_nEnvmapMask ); + } + + if ( (info.m_nDiffuseWarpTexture != -1) && params[info.m_nDiffuseWarpTexture]->IsDefined() ) + { + pShader->LoadTexture( info.m_nDiffuseWarpTexture ); + } + + if ( bHasSelfIllumMask ) + { + pShader->LoadTexture( info.m_nSelfIllumMask ); + } + + if ( ( info.m_nDisplacementMap != -1 ) && params[info.m_nDisplacementMap]->IsDefined() ) + { + pShader->LoadTexture( info.m_nDisplacementMap ); + } + + if ( info.m_nFoW != -1 && params[ info.m_nFoW ]->IsDefined() ) + { + pShader->LoadTexture( info.m_nFoW ); + } +} + +// FIXME: +// From revision #18 of this file in staging: +// "Quick fix to keep Phong shader from being run if the mat_bumpmap convar is set to zero." +// This change caused shader problems in HLMV (use ep2/Hunter model as an example) and I was told to fix it. -Jeep +// +//extern ConVar mat_bumpmap( "mat_bumpmap", "1" ); + +class CVertexLitGeneric_DX9_Context : public CBasePerMaterialContextData +{ +public: + CCommandBufferBuilder< CFixedCommandStorageBuffer< 800 > > m_SemiStaticCmdsOut; +}; + + +//----------------------------------------------------------------------------- +// Draws the shader +//----------------------------------------------------------------------------- +static void DrawVertexLitGeneric_DX9_Internal( CBaseVSShader *pShader, IMaterialVar** params, + IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, + bool bVertexLitGeneric, bool bHasFlashlight, bool bSinglePassFlashlight, + VertexLitGeneric_DX9_Vars_t &info, + VertexCompressionType_t vertexCompression, + CBasePerMaterialContextData **pContextDataPtr ) + +{ + CVertexLitGeneric_DX9_Context *pContextData = reinterpret_cast< CVertexLitGeneric_DX9_Context *> ( *pContextDataPtr ); + + + bool bHasBump = IsTextureSet( info.m_nBumpmap, params ); +#if !defined( _X360 ) + bool bIsDecal = IS_FLAG_SET( MATERIAL_VAR_DECAL ); +#endif + + float fSinglePassFlashlight = bSinglePassFlashlight ? 1.0f : 0.0f; + + bool hasDiffuseLighting = bVertexLitGeneric; + + bool bShaderSrgbRead = ( IsX360() && IS_PARAM_DEFINED( info.m_nShaderSrgbRead360 ) && params[info.m_nShaderSrgbRead360]->GetIntValue() ); + + bool bIsAlphaTested = IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) != 0; + bool bHasDiffuseWarp = (!bHasFlashlight || bSinglePassFlashlight) && hasDiffuseLighting && (info.m_nDiffuseWarpTexture != -1) && params[info.m_nDiffuseWarpTexture]->IsTexture(); + + + //bool bNoCull = IS_FLAG_SET( MATERIAL_VAR_NOCULL ); + bool bFlashlightNoLambert = false; + if ( ( info.m_nFlashlightNoLambert != -1 ) && params[info.m_nFlashlightNoLambert]->GetIntValue() ) + { + bFlashlightNoLambert = true; + } + + bool bAmbientOnly = IsBoolSet( info.m_nAmbientOnly, params ); + // Hack + + int nDetailBlendMode= GetIntParam( info.m_nDetailTextureCombineMode, params ); + + if ( ( nDetailBlendMode == 6 ) && ( ! (g_pHardwareConfig->SupportsPixelShaders_2_b() ) ) ) + { + nDetailBlendMode = 5; // skip fancy threshold blending if ps2.0 + } + + BlendType_t nBlendType; + + int nDetailTranslucencyTexture = -1; + + float fBlendFactor = GetFloatParam( info.m_nDetailTextureBlendFactor, params, 1.0 ); + bool bHasDetailTexture = IsTextureSet( info.m_nDetail, params ); + if ( bHasDetailTexture && ( fBlendFactor > 0.0 ) ) + { + if ( ( nDetailBlendMode == 3 ) || ( nDetailBlendMode == 8 ) || ( nDetailBlendMode == 9 ) ) + nDetailTranslucencyTexture = info.m_nDetail; + } + + bool bHasDisplacement = (info.m_nDisplacementMap != -1) && params[info.m_nDisplacementMap]->IsTexture(); + + bool bHasBaseTexture = IsTextureSet( info.m_nBaseTexture, params ); + if ( bHasBaseTexture ) + { + nBlendType = pShader->EvaluateBlendRequirements( info.m_nBaseTexture, true, nDetailTranslucencyTexture ); + } + else + { + nBlendType = pShader->EvaluateBlendRequirements( info.m_nEnvmapMask, false ); + } + bool bFullyOpaque = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !bIsAlphaTested && (!bHasFlashlight || bSinglePassFlashlight); //dest alpha is free for special use + + bool bHasEnvmap = (!bHasFlashlight || bSinglePassFlashlight) && info.m_nEnvmap != -1 && params[info.m_nEnvmap]->IsTexture(); + + if ( IsPC() && bHasFlashlight && bHasEnvmap && bSinglePassFlashlight ) + { + Warning( "VertexLitGeneric_Dx9: Unsupported combo! Can't use envmap + flashlight + singlepass flashlight!\n" ); + } + bool bSRGBWrite = true; + if ( ( info.m_nLinearWrite != -1 ) && ( params[info.m_nLinearWrite]->GetIntValue() == 1 ) ) + { + bSRGBWrite = false; + } + + bool bHasVertexColor = bVertexLitGeneric ? false : IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR ); + bool bHasVertexAlpha = bVertexLitGeneric ? false : IS_FLAG_SET( MATERIAL_VAR_VERTEXALPHA ); + + bool bHasFoW = ( ( info.m_nFoW != -1 ) && ( params[ info.m_nFoW ]->IsTexture() != 0 ) ); + if ( bHasFoW == true ) + { + ITexture *pTexture = params[ info.m_nFoW ]->GetTextureValue(); + if ( ( pTexture->GetFlags() & TEXTUREFLAGS_RENDERTARGET ) == 0 ) + { + bHasFoW = false; + } + } + + bool bTreeSway = ( GetIntParam( info.m_nTreeSway, params, 0 ) != 0 ) && !bHasFoW; + int nTreeSwayMode = GetIntParam( info.m_nTreeSway, params, 0 ); + nTreeSwayMode = clamp( nTreeSwayMode, 0, 2 ); + + + if ( pShader->IsSnapshotting() || (! pContextData ) || ( pContextData->m_bMaterialVarsChanged ) ) + { + bool bSeamlessBase = IsBoolSet( info.m_nSeamlessBase, params ) && !bTreeSway; + bool bSeamlessDetail = IsBoolSet( info.m_nSeamlessDetail, params ) && !bTreeSway; + bool bDistanceAlpha = IsBoolSet( info.m_nDistanceAlpha, params ); + bool bHasSelfIllum = (!bHasFlashlight || bSinglePassFlashlight) && IS_FLAG_SET( MATERIAL_VAR_SELFILLUM ); + + bool bHasSelfIllumMask = bHasSelfIllum && IsTextureSet( info.m_nSelfIllumMask, params ); + bool bHasSelfIllumInEnvMapMask = + ( info.m_nSelfIllumEnvMapMask_Alpha != -1 ) && + ( params[info.m_nSelfIllumEnvMapMask_Alpha]->GetFloatValue() != 0.0 ) ; + bool bDesaturateWithBaseAlpha = !bHasSelfIllum && !bHasSelfIllumMask && GetFloatParam( info.m_nDesaturateWithBaseAlpha, params ) > 0.0f; + + if ( pShader->IsSnapshotting() ) + { + // Per-instance state +#if !defined( PLATFORM_X360 ) + int nLightingPreviewMode = IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER0 ) + 2 * IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER1 ); +#endif + pShader->PI_BeginCommandBuffer(); + if ( bVertexLitGeneric ) + { + if ( bHasBump || bHasDiffuseWarp ) + { + pShader->PI_SetPixelShaderAmbientLightCube( 5 ); + pShader->PI_SetPixelShaderLocalLighting( 13 ); + } + pShader->PI_SetVertexShaderAmbientLightCube(); + } + // material can choose to support per-instance modulation via $allowdiffusemodulation + bool bAllowDiffuseModulation = ( info.m_nAllowDiffuseModulation == -1 ) ? true : ( params[info.m_nAllowDiffuseModulation]->GetIntValue() != 0 ); + + if ( bAllowDiffuseModulation ) + { + if ( ( info.m_nHDRColorScale != -1 ) && pShader->IsHDREnabled() ) + { + if ( bSRGBWrite ) + pShader->PI_SetModulationPixelShaderDynamicState_LinearColorSpace_LinearScale( 1, params[info.m_nHDRColorScale]->GetFloatValue() ); + else + pShader->PI_SetModulationPixelShaderDynamicState_LinearScale( 1, params[info.m_nHDRColorScale]->GetFloatValue() ); + } + else + { + if ( bSRGBWrite ) + pShader->PI_SetModulationPixelShaderDynamicState_LinearColorSpace( 1 ); + else + pShader->PI_SetModulationPixelShaderDynamicState( 1 ); + } + } + else + { + pShader->PI_SetModulationPixelShaderDynamicState_Identity( 1 ); + } + pShader->PI_EndCommandBuffer(); + + bool hasBaseAlphaEnvmapMask = IS_FLAG_SET( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + bool hasNormalMapAlphaEnvmapMask = IS_FLAG_SET( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ); + + if ( info.m_nVertexAlphaTest != -1 && params[info.m_nVertexAlphaTest]->GetIntValue() > 0 ) + { + bHasVertexAlpha = true; + } + + // look at color and alphamod stuff. + // Unlit generic never uses the flashlight + bool bHasSelfIllumFresnel = ( !bHasDetailTexture ) && ( bHasSelfIllum ) && ( info.m_nSelfIllumFresnel != -1 ) && ( params[info.m_nSelfIllumFresnel]->GetIntValue() != 0 ); + if ( bHasSelfIllumFresnel ) + { + CLEAR_FLAGS( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ); + hasNormalMapAlphaEnvmapMask = false; + } + + bool bHasEnvmap = (!bHasFlashlight || bSinglePassFlashlight) && ( info.m_nEnvmap != -1 ) && params[info.m_nEnvmap]->IsTexture(); + bool bHasEnvmapMask = (!bHasFlashlight || bSinglePassFlashlight) && ( info.m_nEnvmapMask != -1 && params[info.m_nEnvmapMask]->IsTexture() ); + bool bHasNormal = bVertexLitGeneric || bHasEnvmap || bHasFlashlight || bSeamlessBase || bSeamlessDetail; + if ( IsPC() ) + { + // On PC, LIGHTING_PREVIEW requires normals (they won't use much memory - unlitgeneric isn't used on many models) + bHasNormal = true; + } + + bool bHasEnvMapFresnel = bHasEnvmap && IsBoolSet( info.m_nEnvmapFresnel, params ); + + bool bHalfLambert = IS_FLAG_SET( MATERIAL_VAR_HALFLAMBERT ); + // Alpha test: FIXME: shouldn't this be handled in CBaseVSShader::SetInitialShadowState + pShaderShadow->EnableAlphaTest( bIsAlphaTested ); + + if ( info.m_nAlphaTestReference != -1 && params[info.m_nAlphaTestReference]->GetFloatValue() > 0.0f ) + { + pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GEQUAL, params[info.m_nAlphaTestReference]->GetFloatValue() ); + } + + int nShadowFilterMode = 0; + if ( bHasFlashlight ) + { + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + nShadowFilterMode = g_pHardwareConfig->GetShadowFilterMode(); // Based upon vendor and device dependent formats + } + + if ( bSinglePassFlashlight ) + { + pShader->SetBlendingShadowState( nBlendType ); + } + else + { + //doing the flashlight as a second additive pass + if (params[info.m_nBaseTexture]->IsTexture()) + { + pShader->SetAdditiveBlendingShadowState( info.m_nBaseTexture, true ); + } + else + { + pShader->SetAdditiveBlendingShadowState( info.m_nEnvmapMask, false ); + } + + if ( bIsAlphaTested ) + { + // disable alpha test and use the zfunc zequals since alpha isn't guaranteed to + // be the same on both the regular pass and the flashlight pass. + pShaderShadow->EnableAlphaTest( false ); + pShaderShadow->DepthFunc( SHADER_DEPTHFUNC_EQUAL ); + } + + // Be sure not to write to dest alpha + pShaderShadow->EnableAlphaWrites( false ); + + pShaderShadow->EnableBlending( true ); + pShaderShadow->EnableDepthWrites( false ); + } + } + else + { + pShader->SetBlendingShadowState( nBlendType ); + } + + unsigned int flags = VERTEX_POSITION; + if ( bHasNormal ) + { + flags |= VERTEX_NORMAL; + } + + int userDataSize = 0; + + // basetexture + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + if ( bHasBaseTexture ) + { + if ( ( info.m_nGammaColorRead != -1 ) && ( params[info.m_nGammaColorRead]->GetIntValue() == 1 ) ) + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, false ); + else + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, !bShaderSrgbRead ); + } + + if ( bHasEnvmap ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ) + { + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); + } + } + if ( bHasFlashlight ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER8, true ); // Depth texture + pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER8 ); + pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); // Noise map + pShaderShadow->EnableTexture( SHADER_SAMPLER7, true ); // Flashlight cookie + } + if ( bHasDetailTexture ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + if ( nDetailBlendMode != 0 ) //Not Mod2X + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, true ); + } + if ( bHasBump || bHasDiffuseWarp ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + userDataSize = 4; // tangent S + // Normalizing cube map + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); + } + if ( bHasEnvmapMask ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + } + + if ( bHasVertexColor || bHasVertexAlpha ) + { + flags |= VERTEX_COLOR; + } + else if ( !bHasBump && !bHasDiffuseWarp ) + { + flags |= VERTEX_COLOR_STREAM_1; + } + + if( bHasDiffuseWarp && (!bHasFlashlight || bSinglePassFlashlight) && !bHasSelfIllumFresnel ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER9, true ); // Diffuse warp texture + } + + if ( bHasFoW ) + { + // pShaderShadow->EnableSRGBRead( SHADER_SAMPLER10, true ); // Always SRGB read on base map + pShaderShadow->EnableTexture( SHADER_SAMPLER9, true ); + } + + if( bHasSelfIllum ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER11, true ); // self illum mask + } + if ( bHasDisplacement && IsPC() && g_pHardwareConfig->HasFastVertexTextures() ) + { + pShaderShadow->EnableVertexTexture( SHADER_VERTEXTEXTURE_SAMPLER2, true ); + } + + pShaderShadow->EnableSRGBWrite( bSRGBWrite ); + + // texcoord0 : base texcoord + int pTexCoordDim[3] = { 2, 2, 3 }; + int nTexCoordCount = 1; + + if ( IsBoolSet( info.m_nSeparateDetailUVs, params ) ) + { + ++nTexCoordCount; + } + else + { + pTexCoordDim[1] = 0; + } + +#ifndef _X360 + // Special morphed decal information + if ( bIsDecal && g_pHardwareConfig->HasFastVertexTextures() ) + { + nTexCoordCount = 3; + } +#endif + + // r_staticlight_streams (from engine.dll) + // This is for the 3 color baked prop lighting. + static ConVarRef r_staticlight_streams( "r_staticlight_streams", true ); + bool bStaticLight3Streams = ( r_staticlight_streams.GetInt() == 3 ); + + // This shader supports compressed vertices, so OR in that flag: + flags |= VERTEX_FORMAT_COMPRESSED; + + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, pTexCoordDim, userDataSize ); + + if ( bHasBump || bHasDiffuseWarp ) + { + // We don't want to normalize the eye vector in the vertex shader, as that leads to interpolation artifacts. + // Unfortunately, we run out of pixel shader instructions in 2.0 if we always normalize the eye vector for self illum fresnel. + bool bNormalizeEyeVecInVS = bHasSelfIllumFresnel && !g_pHardwareConfig->SupportsPixelShaders_2_b(); + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_STATIC_VERTEX_SHADER( vertexlit_and_unlit_generic_bump_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT, bHalfLambert); + SET_STATIC_VERTEX_SHADER_COMBO( USE_WITH_2B, g_pHardwareConfig->SupportsPixelShaders_2_b() ); + SET_STATIC_VERTEX_SHADER_COMBO( STATICLIGHT3, bStaticLight3Streams ); + SET_STATIC_VERTEX_SHADER_COMBO( NORMALIZEEYEVEC, bNormalizeEyeVecInVS ); +#ifdef _X360 + SET_STATIC_VERTEX_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); +#endif + SET_STATIC_VERTEX_SHADER_COMBO( WORLD_NORMAL, 0 ); + SET_STATIC_VERTEX_SHADER( vertexlit_and_unlit_generic_bump_vs20 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( vertexlit_and_unlit_generic_bump_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSELIGHTING, hasDiffuseLighting ); + SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, bHasDiffuseWarp && !bHasSelfIllumFresnel && !bHasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, bHasSelfIllum ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUMFRESNEL, bHasSelfIllumFresnel ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMALMAPALPHAENVMAPMASK, hasNormalMapAlphaEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( HALFLAMBERT, bHalfLambert); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, bHasDetailTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER_COMBO( SHADER_SRGB_READ, bShaderSrgbRead ); + SET_STATIC_PIXEL_SHADER_COMBO( STATICLIGHT3, bStaticLight3Streams ); + SET_STATIC_PIXEL_SHADER_COMBO( WORLD_NORMAL, 0 ); + SET_STATIC_PIXEL_SHADER( vertexlit_and_unlit_generic_bump_ps20b ); + } + else // ps_2_0 + { + DECLARE_STATIC_PIXEL_SHADER( vertexlit_and_unlit_generic_bump_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSELIGHTING, hasDiffuseLighting ); + SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, bHasDiffuseWarp && !bHasSelfIllumFresnel ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, bHasSelfIllum ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUMFRESNEL, bHasSelfIllumFresnel ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMALMAPALPHAENVMAPMASK, hasNormalMapAlphaEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( HALFLAMBERT, bHalfLambert); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, bHasDetailTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode ); + SET_STATIC_PIXEL_SHADER_COMBO( SHADER_SRGB_READ, bShaderSrgbRead ); + SET_STATIC_PIXEL_SHADER_COMBO( STATICLIGHT3, bStaticLight3Streams ); + SET_STATIC_PIXEL_SHADER_COMBO( WORLD_NORMAL, 0 ); + SET_STATIC_PIXEL_SHADER( vertexlit_and_unlit_generic_bump_ps20 ); + } + } +#ifndef _X360 + else + { + // The vertex shader uses the vertex id stream + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_TESSELLATION ); + + DECLARE_STATIC_VERTEX_SHADER( vertexlit_and_unlit_generic_bump_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT, bHalfLambert); + SET_STATIC_VERTEX_SHADER_COMBO( USE_WITH_2B, true ); + SET_STATIC_VERTEX_SHADER_COMBO( DECAL, bIsDecal ); + SET_STATIC_VERTEX_SHADER_COMBO( NORMALIZEEYEVEC, false ); + SET_STATIC_VERTEX_SHADER_COMBO( STATICLIGHT3, bStaticLight3Streams ); + SET_STATIC_VERTEX_SHADER_COMBO( WORLD_NORMAL, nLightingPreviewMode == 3 ); + SET_STATIC_VERTEX_SHADER( vertexlit_and_unlit_generic_bump_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( vertexlit_and_unlit_generic_bump_ps30 ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSELIGHTING, hasDiffuseLighting ); + SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, bHasDiffuseWarp && !bHasSelfIllumFresnel ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, bHasSelfIllum && !bHasFlashlight ); // Careful here if we do single-pass flashlight on PC + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUMFRESNEL, bHasSelfIllumFresnel ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMALMAPALPHAENVMAPMASK, hasNormalMapAlphaEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( HALFLAMBERT, bHalfLambert ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, bHasDetailTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER_COMBO( SHADER_SRGB_READ, bShaderSrgbRead ); + SET_STATIC_PIXEL_SHADER_COMBO( STATICLIGHT3, bStaticLight3Streams ); + SET_STATIC_PIXEL_SHADER_COMBO( WORLD_NORMAL, nLightingPreviewMode == 3 ); + SET_STATIC_PIXEL_SHADER( vertexlit_and_unlit_generic_bump_ps30 ); + } +#endif + } + else // !(bHasBump || bHasDiffuseWarp) + { + int nLightingPreviewMode = IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER0 ) + 2 * IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER1 ); + bool bDistanceAlphaFromDetail = false; + bool bSoftMask = false; + bool bGlow = false; + bool bOutline = false; + + bHasSelfIllumInEnvMapMask = bHasSelfIllumInEnvMapMask && bHasEnvmapMask; + if ( bDistanceAlpha ) + { + bDistanceAlphaFromDetail = IsBoolSet( info.m_nDistanceAlphaFromDetail, params ); + bSoftMask = IsBoolSet( info.m_nSoftEdges, params ); + bGlow = IsBoolSet( info.m_nGlow, params ); + bOutline = IsBoolSet( info.m_nOutline, params ); + } + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_STATIC_VERTEX_SHADER( vertexlit_and_unlit_generic_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( VERTEXCOLOR, bHasVertexColor || bHasVertexAlpha ); + SET_STATIC_VERTEX_SHADER_COMBO( CUBEMAP, bHasEnvmap ); + SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT, bHalfLambert ); + SET_STATIC_VERTEX_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); + SET_STATIC_VERTEX_SHADER_COMBO( SEAMLESS_BASE, bSeamlessBase ); + SET_STATIC_VERTEX_SHADER_COMBO( SEAMLESS_DETAIL, bSeamlessDetail ); + SET_STATIC_VERTEX_SHADER_COMBO( SEPARATE_DETAIL_UVS, IsBoolSet( info.m_nSeparateDetailUVs, params ) ); + SET_STATIC_VERTEX_SHADER_COMBO( STATICLIGHT3, bStaticLight3Streams ); + SET_STATIC_VERTEX_SHADER_COMBO( LIGHTING_PREVIEW, nLightingPreviewMode ); + SET_STATIC_VERTEX_SHADER_COMBO( FOW, bHasFoW ); + SET_STATIC_VERTEX_SHADER_COMBO( TREESWAY, bTreeSway ? nTreeSwayMode : 0 ); + SET_STATIC_VERTEX_SHADER( vertexlit_and_unlit_generic_vs20 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( vertexlit_and_unlit_generic_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM_ENVMAPMASK_ALPHA, bHasSelfIllumInEnvMapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, bHasDetailTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSELIGHTING, hasDiffuseLighting ); + SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPMASK, bHasEnvmapMask && ( bHasEnvmap || bHasSelfIllumInEnvMapMask ) ); + SET_STATIC_PIXEL_SHADER_COMBO( BASEALPHAENVMAPMASK, hasBaseAlphaEnvmapMask && bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPFRESNEL, bHasEnvMapFresnel && bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, bHasSelfIllum ); + SET_STATIC_PIXEL_SHADER_COMBO( VERTEXCOLOR, bHasVertexColor ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode ); + SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS_BASE, bSeamlessBase ); + SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS_DETAIL, bSeamlessDetail ); + SET_STATIC_PIXEL_SHADER_COMBO( DISTANCEALPHA, bDistanceAlpha ); + SET_STATIC_PIXEL_SHADER_COMBO( DISTANCEALPHAFROMDETAIL, bDistanceAlphaFromDetail ); + SET_STATIC_PIXEL_SHADER_COMBO( SOFT_MASK, bSoftMask ); + SET_STATIC_PIXEL_SHADER_COMBO( OUTLINE, bOutline ); + SET_STATIC_PIXEL_SHADER_COMBO( OUTER_GLOW, bGlow ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER_COMBO( SHADER_SRGB_READ, bShaderSrgbRead ); + SET_STATIC_PIXEL_SHADER_COMBO( DESATURATEWITHBASEALPHA, bDesaturateWithBaseAlpha ); + SET_STATIC_PIXEL_SHADER_COMBO( LIGHTING_PREVIEW, nLightingPreviewMode ); + SET_STATIC_PIXEL_SHADER_COMBO( FOW, bHasFoW ); + SET_STATIC_PIXEL_SHADER( vertexlit_and_unlit_generic_ps20b ); + } + else // ps_2_0 + { + DECLARE_STATIC_PIXEL_SHADER( vertexlit_and_unlit_generic_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM_ENVMAPMASK_ALPHA, bHasSelfIllumInEnvMapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, bHasDetailTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSELIGHTING, hasDiffuseLighting ); + SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPMASK, bHasEnvmapMask && ( bHasEnvmap || bHasSelfIllumInEnvMapMask ) ); + SET_STATIC_PIXEL_SHADER_COMBO( BASEALPHAENVMAPMASK, hasBaseAlphaEnvmapMask && bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPFRESNEL, bHasEnvMapFresnel && bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, bHasSelfIllum ); + SET_STATIC_PIXEL_SHADER_COMBO( VERTEXCOLOR, bHasVertexColor ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode ); + SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS_BASE, bSeamlessBase ); + SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS_DETAIL, bSeamlessDetail ); + SET_STATIC_PIXEL_SHADER_COMBO( DISTANCEALPHA, bDistanceAlpha ); + SET_STATIC_PIXEL_SHADER_COMBO( DISTANCEALPHAFROMDETAIL, bDistanceAlphaFromDetail ); + SET_STATIC_PIXEL_SHADER_COMBO( SOFT_MASK, bSoftMask ); + SET_STATIC_PIXEL_SHADER_COMBO( OUTLINE, bOutline ); + SET_STATIC_PIXEL_SHADER_COMBO( OUTER_GLOW, bGlow ); + SET_STATIC_PIXEL_SHADER_COMBO( SHADER_SRGB_READ, bShaderSrgbRead ); + SET_STATIC_PIXEL_SHADER_COMBO( DESATURATEWITHBASEALPHA, bDesaturateWithBaseAlpha ); + SET_STATIC_PIXEL_SHADER_COMBO( LIGHTING_PREVIEW, nLightingPreviewMode ); + SET_STATIC_PIXEL_SHADER_COMBO( FOW, bHasFoW ); + SET_STATIC_PIXEL_SHADER( vertexlit_and_unlit_generic_ps20 ); + } + } +#ifndef _X360 + else + { + // The vertex shader uses the vertex id stream + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_TESSELLATION ); + + DECLARE_STATIC_VERTEX_SHADER( vertexlit_and_unlit_generic_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( VERTEXCOLOR, bHasVertexColor || bHasVertexAlpha ); + SET_STATIC_VERTEX_SHADER_COMBO( CUBEMAP, bHasEnvmap ); + SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT, bHalfLambert ); + SET_STATIC_VERTEX_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); + SET_STATIC_VERTEX_SHADER_COMBO( SEAMLESS_BASE, bSeamlessBase ); + SET_STATIC_VERTEX_SHADER_COMBO( SEAMLESS_DETAIL, bSeamlessDetail ); + SET_STATIC_VERTEX_SHADER_COMBO( SEPARATE_DETAIL_UVS, IsBoolSet( info.m_nSeparateDetailUVs, params ) ); + SET_STATIC_VERTEX_SHADER_COMBO( DECAL, bIsDecal ); + SET_STATIC_VERTEX_SHADER_COMBO( STATICLIGHT3, bStaticLight3Streams ); + SET_STATIC_VERTEX_SHADER_COMBO( LIGHTING_PREVIEW, nLightingPreviewMode ); + SET_STATIC_VERTEX_SHADER_COMBO( FOW, bHasFoW ); + SET_STATIC_VERTEX_SHADER_COMBO( TREESWAY, bTreeSway ? nTreeSwayMode : 0 ); + SET_STATIC_VERTEX_SHADER( vertexlit_and_unlit_generic_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( vertexlit_and_unlit_generic_ps30 ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM_ENVMAPMASK_ALPHA, bHasSelfIllumInEnvMapMask && !bHasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, bHasDetailTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSELIGHTING, hasDiffuseLighting ); + SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPMASK, bHasEnvmapMask && !bHasFlashlight && ( bHasEnvmap || bHasSelfIllumInEnvMapMask ) ); // Careful here if we do single-pass flashlight on PC someday + SET_STATIC_PIXEL_SHADER_COMBO( BASEALPHAENVMAPMASK, hasBaseAlphaEnvmapMask && bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPFRESNEL, bHasEnvMapFresnel && bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, bHasSelfIllum ); + SET_STATIC_PIXEL_SHADER_COMBO( VERTEXCOLOR, bHasVertexColor ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode ); + SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS_BASE, bSeamlessBase ); + SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS_DETAIL, bSeamlessDetail ); + SET_STATIC_PIXEL_SHADER_COMBO( DISTANCEALPHA, bDistanceAlpha ); + SET_STATIC_PIXEL_SHADER_COMBO( DISTANCEALPHAFROMDETAIL, bDistanceAlphaFromDetail ); + SET_STATIC_PIXEL_SHADER_COMBO( SOFT_MASK, bSoftMask ); + SET_STATIC_PIXEL_SHADER_COMBO( OUTLINE, bOutline ); + SET_STATIC_PIXEL_SHADER_COMBO( OUTER_GLOW, bGlow ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER_COMBO( SHADER_SRGB_READ, bShaderSrgbRead ); + SET_STATIC_PIXEL_SHADER_COMBO( DESATURATEWITHBASEALPHA, bDesaturateWithBaseAlpha ); + SET_STATIC_PIXEL_SHADER_COMBO( LIGHTING_PREVIEW, nLightingPreviewMode ); + SET_STATIC_PIXEL_SHADER_COMBO( FOW, bHasFoW ); + SET_STATIC_PIXEL_SHADER( vertexlit_and_unlit_generic_ps30 ); + } +#endif + } + + if ( bHasFlashlight && !bSinglePassFlashlight ) + { + pShader->FogToBlack(); + } + else + { + pShader->DefaultFog(); + } + + // HACK HACK HACK - enable alpha writes all the time so that we have them for + // underwater stuff + pShaderShadow->EnableAlphaWrites( bFullyOpaque ); + + } + + if ( pShaderAPI && ( (! pContextData ) || ( pContextData->m_bMaterialVarsChanged ) ) ) + { + if ( !pContextData ) // make sure allocated + { + pContextData = new CVertexLitGeneric_DX9_Context; + *pContextDataPtr = pContextData; + } + pContextData->m_bMaterialVarsChanged = false; + pContextData->m_SemiStaticCmdsOut.Reset(); + pContextData->m_SemiStaticCmdsOut.SetPixelShaderFogParams( 21 ); + if ( bHasBaseTexture ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER0, info.m_nBaseTexture, info.m_nBaseTextureFrame ); + } + else + { + if( bHasEnvmap ) + { + // if we only have an envmap (no basetexture), then we want the albedo to be black. + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_BLACK ); + } + else + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_WHITE ); + } + } + if ( bHasDetailTexture ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER2, info.m_nDetail, info.m_nDetailFrame ); + } + if ( bHasSelfIllum ) + { + if ( bHasSelfIllumMask ) // Separate texture for self illum? + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER11, info.m_nSelfIllumMask, -1 ); // Bind it + } + else // else + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER11, TEXTURE_BLACK ); // Bind dummy + } + } + + if ( bSeamlessDetail || bSeamlessBase ) + { + float flSeamlessData[4] = { params[info.m_nSeamlessScale]->GetFloatValue(), 0, 0, 0 }; + pContextData->m_SemiStaticCmdsOut.SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, flSeamlessData ); + } + + if ( bTreeSway ) + { + float flParams[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + + flParams[0] = GetFloatParam( info.m_nTreeSwaySpeedHighWindMultiplier, params, 2.0f ); + flParams[1] = GetFloatParam( info.m_nTreeSwayScrumbleFalloffExp, params, 1.0f ); + flParams[2] = GetFloatParam( info.m_nTreeSwayFalloffExp, params, 1.0f ); + flParams[3] = GetFloatParam( info.m_nTreeSwayScrumbleSpeed, params, 3.0f ); + pContextData->m_SemiStaticCmdsOut.SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, flParams ); + } + + if ( info.m_nBaseTextureTransform != -1 ) + { + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, info.m_nBaseTextureTransform ); + } + + int nLightingPreviewMode = pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_ENABLE_FIXED_LIGHTING ); + if ( ( nLightingPreviewMode == ENABLE_FIXED_LIGHTING_OUTPUTNORMAL_AND_DEPTH ) && IsPC() ) + { + float vEyeDir[4]; + pShaderAPI->GetWorldSpaceCameraDirection( vEyeDir ); + + float flFarZ = pShaderAPI->GetFarZ(); + vEyeDir[0] /= flFarZ; // Divide by farZ for SSAO algorithm + vEyeDir[1] /= flFarZ; + vEyeDir[2] /= flFarZ; + pContextData->m_SemiStaticCmdsOut.SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, vEyeDir ); // Needed for SSAO + } + + if ( bHasDetailTexture ) + { + if ( !bTreeSway ) + { + if ( IS_PARAM_DEFINED( info.m_nDetailTextureTransform ) ) + { + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, info.m_nDetailTextureTransform, info.m_nDetailScale ); + } + else + { + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, info.m_nBaseTextureTransform, info.m_nDetailScale ); + } + } + + //Assert( !bHasBump ); + if ( info.m_nDetailTint != -1 ) + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstantGammaToLinear( 10, info.m_nDetailTint ); + else + { + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant4( 10, 1, 1, 1, 1 ); + } + } + + if ( bTreeSway ) + { + float32 flParams[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + flParams[0] = GetFloatParam( info.m_nTreeSwaySpeedLerpStart, params, 3.0f ); + flParams[1] = GetFloatParam( info.m_nTreeSwaySpeedLerpEnd, params, 6.0f ); + pContextData->m_SemiStaticCmdsOut.SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, flParams ); + } + + if ( bDistanceAlpha ) + { + float flSoftStart = GetFloatParam( info.m_nEdgeSoftnessStart, params ); + float flSoftEnd = GetFloatParam( info.m_nEdgeSoftnessEnd, params ); + // set all line art shader parms + bool bScaleEdges = IsBoolSet( info.m_nScaleEdgeSoftnessBasedOnScreenRes, params ); + bool bScaleOutline = IsBoolSet( info.m_nScaleOutlineSoftnessBasedOnScreenRes, params ); + + float flResScale = 1.0; + + float flOutlineStart0 = GetFloatParam( info.m_nOutlineStart0, params ); + float flOutlineStart1 = GetFloatParam( info.m_nOutlineStart1, params ); + float flOutlineEnd0 = GetFloatParam( info.m_nOutlineEnd0, params ); + float flOutlineEnd1 = GetFloatParam( info.m_nOutlineEnd1, params ); + + if ( bScaleEdges || bScaleOutline ) + { + int nWidth, nHeight; + pShaderAPI->GetBackBufferDimensions( nWidth, nHeight ); + flResScale=MAX( 0.5, MAX( 1024.0/nWidth, 768/nHeight ) ); + + if ( bScaleEdges ) + { + float flMid = 0.5 * ( flSoftStart + flSoftEnd ); + flSoftStart = clamp( flMid + flResScale * ( flSoftStart - flMid ), 0.05, 0.99 ); + flSoftEnd = clamp( flMid + flResScale * ( flSoftEnd - flMid ), 0.05, 0.99 ); + } + + + if ( bScaleOutline ) + { + // shrink the soft part of the outline, enlarging hard part + float flMidS = 0.5 * ( flOutlineStart1 + flOutlineStart0 ); + flOutlineStart1 = clamp( flMidS + flResScale * ( flOutlineStart1 - flMidS ), 0.05, 0.99 ); + float flMidE = 0.5 * ( flOutlineEnd1 + flOutlineEnd0 ); + flOutlineEnd1 = clamp( flMidE + flResScale * ( flOutlineEnd1 - flMidE ), 0.05, 0.99 ); + } + + } + + float flConsts[]={ + // c5 - glow values + GetFloatParam( info.m_nGlowX, params ), + GetFloatParam( info.m_nGlowY, params ), + GetFloatParam( info.m_nGlowStart, params ), + GetFloatParam( info.m_nGlowEnd, params ), + // c6 - glow color + 0,0,0, // will be filled in + GetFloatParam( info.m_nGlowAlpha, params ), + // c7 - mask range parms and basealphaenvmapmask scale and bias + flSoftStart, + flSoftEnd, + 0,0, // filled in below + // c8 - outline color + 0,0,0, + GetFloatParam( info.m_nOutlineAlpha, params ), + // c9 - outline parms + flOutlineStart0, + flOutlineStart1, + flOutlineEnd0, + flOutlineEnd1, + }; + + if ( info.m_nGlowColor != -1 ) + { + params[info.m_nGlowColor]->GetVecValue( flConsts+4, 3 ); + } + if ( info.m_nOutlineColor != -1 ) + { + params[info.m_nOutlineColor]->GetVecValue( flConsts+12, 3 ); + } + if ( info.m_nBaseAlphaEnvMapMaskMinMaxExp != -1 ) + { + flConsts[10] = params[ info.m_nBaseAlphaEnvMapMaskMinMaxExp ]->GetVecValue()[0]; + flConsts[11] = params[ info.m_nBaseAlphaEnvMapMaskMinMaxExp ]->GetVecValue()[1] - flConsts[10]; + } + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 5, flConsts, 5 ); + + } + else if ( info.m_nBaseAlphaEnvMapMaskMinMaxExp != -1 ) + { + float flConsts[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + + flConsts[2] = params[ info.m_nBaseAlphaEnvMapMaskMinMaxExp ]->GetVecValue()[0]; + flConsts[3] = params[ info.m_nBaseAlphaEnvMapMaskMinMaxExp ]->GetVecValue()[1] - flConsts[2]; + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 7, flConsts, 1 ); + } + + if ( !g_pConfig->m_bFastNoBump ) + { + if ( bHasBump ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER3, info.m_nBumpmap, info.m_nBumpFrame ); + } + else if ( bHasDiffuseWarp ) + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER3, TEXTURE_NORMALMAP_FLAT ); + } + } + else + { + if ( bHasBump ) + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER3, TEXTURE_NORMALMAP_FLAT ); + } + } + // Setting w to 1 means use separate selfillummask + float vEnvMapSaturation_SelfIllumMask[4] = {1.0f, 1.0f, 1.0f, 0.0f}; + if ( info.m_nEnvmapSaturation != -1 ) + params[info.m_nEnvmapSaturation]->GetVecValue( vEnvMapSaturation_SelfIllumMask, 3 ); + + vEnvMapSaturation_SelfIllumMask[3] = bHasSelfIllumMask ? 1.0f : 0.0f; + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 3, vEnvMapSaturation_SelfIllumMask, 1 ); + if ( bHasEnvmap ) + { + pContextData->m_SemiStaticCmdsOut.SetEnvMapTintPixelShaderDynamicStateGammaToLinear( 0, info.m_nEnvmapTint, fSinglePassFlashlight ); + } + else + { + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant4( 0, 0.0f, 0.0f, 0.0f, fSinglePassFlashlight ); + } + bool bHasEnvmapMask = (!bHasFlashlight || bSinglePassFlashlight ) && ( info.m_nEnvmapMask != -1 ) && params[info.m_nEnvmapMask]->IsTexture(); + if ( bHasEnvmapMask ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER4, info.m_nEnvmapMask, info.m_nEnvmapMaskFrame ); + } + + bool bHasEnvMapFresnel = bHasEnvmap && IsBoolSet( info.m_nEnvmapFresnel, params ); + if ( bHasEnvMapFresnel ) + { + float flConsts[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + params[ info.m_nEnvMapFresnelMinMaxExp ]->GetVecValue( flConsts, 3 ); + flConsts[1] -= flConsts[0]; // convert max fresnel into scale factor + + if ( info.m_nBaseAlphaEnvMapMaskMinMaxExp != -1 ) + { + flConsts[3] = params[ info.m_nBaseAlphaEnvMapMaskMinMaxExp ]->GetVecValue()[2]; // basealphaenvmapmask exponent in w + } + + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 13, flConsts, 1 ); + } + else if ( info.m_nBaseAlphaEnvMapMaskMinMaxExp != -1 ) + { + // still need to set exponent for basealphaenvmapmask + float flConsts[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + flConsts[3] = params[ info.m_nBaseAlphaEnvMapMaskMinMaxExp ]->GetVecValue()[2]; // basealphaenvmapmask exponent in w + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 13, flConsts, 1 ); + } + + bool bHasSelfIllumFresnel = ( !bHasDetailTexture ) && ( bHasSelfIllum ) && ( info.m_nSelfIllumFresnel != -1 ) && ( params[info.m_nSelfIllumFresnel]->GetIntValue() != 0 ); + + if ( bHasSelfIllumFresnel && (!bHasFlashlight || bSinglePassFlashlight) ) + { + float vConstScaleBiasExp[4] = { 1.0f, 0.0f, 1.0f, 0.0f }; + float flMin = IS_PARAM_DEFINED( info.m_nSelfIllumFresnelMinMaxExp ) ? params[info.m_nSelfIllumFresnelMinMaxExp]->GetVecValue()[0] : 0.0f; + float flMax = IS_PARAM_DEFINED( info.m_nSelfIllumFresnelMinMaxExp ) ? params[info.m_nSelfIllumFresnelMinMaxExp]->GetVecValue()[1] : 1.0f; + float flExp = IS_PARAM_DEFINED( info.m_nSelfIllumFresnelMinMaxExp ) ? params[info.m_nSelfIllumFresnelMinMaxExp]->GetVecValue()[2] : 1.0f; + + vConstScaleBiasExp[1] = ( flMax != 0.0f ) ? ( flMin / flMax ) : 0.0f; // Bias + vConstScaleBiasExp[0] = 1.0f - vConstScaleBiasExp[1]; // Scale + vConstScaleBiasExp[2] = flExp; // Exp + vConstScaleBiasExp[3] = flMax; // Brightness + + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 11, vConstScaleBiasExp ); + } + else + { + float vSelfIllumScale[4]; + vSelfIllumScale[0] = IS_PARAM_DEFINED( info.m_nSelfIllumMaskScale ) ? params[info.m_nSelfIllumMaskScale]->GetFloatValue() : 1.0f; + vSelfIllumScale[1] = vSelfIllumScale[2] = vSelfIllumScale[3] = 0.0f; + + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 11, vSelfIllumScale ); + } + + // store eye pos in shader constant 20 + float flEyeW = pShader->TextureIsTranslucent( BASETEXTURE, true ) ? 1.0f : 0.0f; + pContextData->m_SemiStaticCmdsOut.StoreEyePosInPixelShaderConstant( 20, flEyeW ); + + if( bHasDiffuseWarp && (!bHasFlashlight || bSinglePassFlashlight) && !bHasSelfIllumFresnel ) + { + if ( r_lightwarpidentity.GetBool() ) + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER9, TEXTURE_IDENTITY_LIGHTWARP ); + } + else + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER9, info.m_nDiffuseWarpTexture, -1 ); + } + } + + if ( bHasFlashlight ) + { + if( IsX360() || !bHasBump ) + { + pContextData->m_SemiStaticCmdsOut.SetVertexShaderFlashlightState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6 ); + } + + CBCmdSetPixelShaderFlashlightState_t state; + state.m_LightSampler = SHADER_SAMPLER7; + state.m_DepthSampler = SHADER_SAMPLER8; + state.m_ShadowNoiseSampler = SHADER_SAMPLER6; + state.m_nColorConstant = 28; + state.m_nAttenConstant = 22; + state.m_nOriginConstant = 23; + state.m_nDepthTweakConstant = 2; + state.m_nScreenScaleConstant = 31; + state.m_nWorldToTextureConstant = IsX360() ? -1 : 24; + state.m_bFlashlightNoLambert = bFlashlightNoLambert; + state.m_bSinglePassFlashlight = bSinglePassFlashlight; + pContextData->m_SemiStaticCmdsOut.SetPixelShaderFlashlightState( state ); + + if ( !IsX360() && ( g_pHardwareConfig->GetDXSupportLevel() > 92 ) ) + { + pContextData->m_SemiStaticCmdsOut.SetPixelShaderUberLightState( + PSREG_UBERLIGHT_SMOOTH_EDGE_0, PSREG_UBERLIGHT_SMOOTH_EDGE_1, + PSREG_UBERLIGHT_SMOOTH_EDGE_OOW, PSREG_UBERLIGHT_SHEAR_ROUND, + PSREG_UBERLIGHT_AABB, PSREG_UBERLIGHT_WORLD_TO_LIGHT ); + } + } + + if ( ( !bHasFlashlight || bSinglePassFlashlight ) && ( info.m_nEnvmapContrast != -1 ) ) + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 2, info.m_nEnvmapContrast ); + + // mat_fullbright 2 handling + bool bLightingOnly = bVertexLitGeneric && mat_fullbright.GetInt() == 2 && !IS_FLAG_SET( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + if( bLightingOnly ) + { + if ( bHasBaseTexture ) + { + if( ( bHasSelfIllum && !bHasSelfIllumInEnvMapMask ) ) + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY_ALPHA_ZERO ); + } + else + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY ); + } + } + if ( bHasDetailTexture ) + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER2, TEXTURE_GREY ); + } + } + + if ( bHasBump || bHasDiffuseWarp ) + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER5, TEXTURE_NORMALIZATION_CUBEMAP_SIGNED ); + } + + if ( bTreeSway ) + { + float flParams[4]; + flParams[0] = GetFloatParam( info.m_nTreeSwayHeight, params, 1000.0f ); + flParams[1] = GetFloatParam( info.m_nTreeSwayStartHeight, params, 0.1f ); + flParams[2] = GetFloatParam( info.m_nTreeSwayRadius, params, 300.0f ); + flParams[3] = GetFloatParam( info.m_nTreeSwayStartRadius, params, 0.2f ); + pContextData->m_SemiStaticCmdsOut.SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_10, flParams ); + + flParams[0] = GetFloatParam( info.m_nTreeSwaySpeed, params, 1.0f ); + flParams[1] = GetFloatParam( info.m_nTreeSwayStrength, params, 10.0f ); + flParams[2] = GetFloatParam( info.m_nTreeSwayScrumbleFrequency, params, 12.0f ); + flParams[3] = GetFloatParam( info.m_nTreeSwayScrumbleStrength, params, 10.0f ); + pContextData->m_SemiStaticCmdsOut.SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_11, flParams ); + } + + if ( bDesaturateWithBaseAlpha ) + { + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant_W( 4, info.m_nDesaturateWithBaseAlpha, fBlendFactor ); + } + else + { + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant_W( 4, info.m_nSelfIllumTint, fBlendFactor ); + } + pContextData->m_SemiStaticCmdsOut.End(); + } + } + if ( pShaderAPI ) + { + CCommandBufferBuilder< CFixedCommandStorageBuffer< 1000 > > DynamicCmdsOut; + DynamicCmdsOut.Call( pContextData->m_SemiStaticCmdsOut.Base() ); + + if ( bHasEnvmap ) + { + DynamicCmdsOut.BindTexture( pShader, SHADER_SAMPLER1, info.m_nEnvmap, info.m_nEnvmapFrame ); + } + + bool bFlashlightShadows = false; + bool bUberlight = false; + if ( bHasFlashlight ) + { + pShaderAPI->GetFlashlightShaderInfo( &bFlashlightShadows, &bUberlight ); + if ( g_pHardwareConfig->GetDXSupportLevel() <= 92 ) + { + bUberlight = false; + } + } + + // Set up light combo state + LightState_t lightState = {0, false, false}; + if ( bVertexLitGeneric && (!bHasFlashlight || bSinglePassFlashlight) ) + { + pShaderAPI->GetDX9LightState( &lightState ); + } + + MaterialFogMode_t fogType = pShaderAPI->GetSceneFogMode(); + int numBones = pShaderAPI->GetCurrentNumBones(); + + bool bWriteDepthToAlpha; + bool bWriteWaterFogToAlpha; + if( bFullyOpaque ) + { + bWriteDepthToAlpha = pShaderAPI->ShouldWriteDepthToDestAlpha(); + bWriteWaterFogToAlpha = (fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z); + AssertMsg( !(bWriteDepthToAlpha && bWriteWaterFogToAlpha), "Can't write two values to alpha at the same time." ); + } + else + { + //can't write a special value to dest alpha if we're actually using as-intended alpha + bWriteDepthToAlpha = false; + bWriteWaterFogToAlpha = false; + } + +#ifndef _X360 + bool bWorldNormal = pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_ENABLE_FIXED_LIGHTING ) == ENABLE_FIXED_LIGHTING_OUTPUTNORMAL_AND_DEPTH; + + TessellationMode_t nTessellationMode = pShaderAPI->GetTessellationMode(); + if ( ( nTessellationMode != TESSELLATION_MODE_DISABLED ) && g_pHardwareConfig->HasFastVertexTextures() ) + { + pShaderAPI->BindStandardVertexTexture( SHADER_VERTEXTEXTURE_SAMPLER1, TEXTURE_SUBDIVISION_PATCHES ); + + float vSubDDimensions[4] = { 1.0f/pShaderAPI->GetSubDHeight(), bHasDisplacement && mat_displacementmap.GetBool() ? 1.0f : 0.0f, 0.0f, 0.0f }; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, vSubDDimensions ); + + if( bHasDisplacement ) + { + pShader->BindVertexTexture( SHADER_VERTEXTEXTURE_SAMPLER2, info.m_nDisplacementMap ); + } + else + { + pShaderAPI->BindStandardVertexTexture( SHADER_VERTEXTEXTURE_SAMPLER2, TEXTURE_BLACK ); + } + + // Currently, tessellation is mutually exclusive with any kind of GPU-side skinning, morphing or vertex compression + Assert( !pShaderAPI->IsHWMorphingEnabled() ); + Assert( numBones == 0 ); + Assert( vertexCompression == 0); + + // Also mutually exclusive with these in the non-bump case: + //$STATICLIGHT3 || $VERTEXCOLOR || $SEAMLESS_BASE || $SEAMLESS_DETAIL || $SEPARATE_DETAIL_UVS + } +#endif + int nLightingPreviewMode = pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_ENABLE_FIXED_LIGHTING ); + if ( ( nLightingPreviewMode == ENABLE_FIXED_LIGHTING_OUTPUTNORMAL_AND_DEPTH ) && IsPC() ) + { + float vEyeDir[4]; + pShaderAPI->GetWorldSpaceCameraDirection( vEyeDir ); + + float flFarZ = pShaderAPI->GetFarZ(); + vEyeDir[0] /= flFarZ; // Divide by farZ for SSAO algorithm + vEyeDir[1] /= flFarZ; + vEyeDir[2] /= flFarZ; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, vEyeDir ); + } + else + { + float vConst[4] = { lightState.m_bStaticLight ? 1.0f : 0.0f, 0.0f, 0.0f, 0.0f }; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, vConst ); + } + if ( bHasFoW ) + { + pShader->BindTexture( SHADER_SAMPLER9, info.m_nFoW, -1 ); + + float vFoWSize[ 4 ]; + Vector vMins = pShaderAPI->GetVectorRenderingParameter( VECTOR_RENDERPARM_GLOBAL_FOW_MINS ); + Vector vMaxs = pShaderAPI->GetVectorRenderingParameter( VECTOR_RENDERPARM_GLOBAL_FOW_MAXS ); + vFoWSize[ 0 ] = vMins.x; + vFoWSize[ 1 ] = vMins.y; + vFoWSize[ 2 ] = vMaxs.x - vMins.x; + vFoWSize[ 3 ] = vMaxs.y - vMins.y; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, vFoWSize ); + } + + if ( bHasBump || bHasDiffuseWarp ) + { +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_DYNAMIC_VERTEX_SHADER( vertexlit_and_unlit_generic_bump_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, numBones > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( TESSELLATION, 0 ); + SET_DYNAMIC_VERTEX_SHADER_CMD( DynamicCmdsOut, vertexlit_and_unlit_generic_bump_vs20 ); + + // Bind ps_2_b shader so we can get shadow mapping... + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( vertexlit_and_unlit_generic_bump_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( AMBIENT_LIGHT, lightState.m_bAmbientLight ? 1 : 0 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_CMD( DynamicCmdsOut, vertexlit_and_unlit_generic_bump_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( vertexlit_and_unlit_generic_bump_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( AMBIENT_LIGHT, lightState.m_bAmbientLight ? 1 : 0 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_CMD( DynamicCmdsOut, vertexlit_and_unlit_generic_bump_ps20 ); + } + } +#ifndef _X360 + else + { + if ( !bTreeSway ) + { + pShader->SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_10, VERTEX_SHADER_SHADER_SPECIFIC_CONST_11, SHADER_VERTEXTEXTURE_SAMPLER0 ); + } + + DECLARE_DYNAMIC_VERTEX_SHADER( vertexlit_and_unlit_generic_bump_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, ( numBones > 0 ) && ( nTessellationMode == TESSELLATION_MODE_DISABLED ) ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression && ( nTessellationMode == TESSELLATION_MODE_DISABLED ) ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( TESSELLATION, nTessellationMode ); + SET_DYNAMIC_VERTEX_SHADER( vertexlit_and_unlit_generic_bump_vs30 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( vertexlit_and_unlit_generic_bump_ps30 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, bWorldNormal ? 0 : lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( AMBIENT_LIGHT, bWorldNormal ? 0 : (lightState.m_bAmbientLight ? 1 : 0 ) ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bWorldNormal ? 0 : bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( UBERLIGHT, bUberlight ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_CMD( DynamicCmdsOut, vertexlit_and_unlit_generic_bump_ps30 ); + + bool bUnusedTexCoords[3] = { false, false, !pShaderAPI->IsHWMorphingEnabled() || !bIsDecal }; + pShaderAPI->MarkUnusedVertexFields( 0, 3, bUnusedTexCoords ); + } +#endif + } + else // !( bHasBump || bHasDiffuseWarp ) + { + if ( bAmbientOnly ) // Override selected light combo to be ambient only + { + lightState.m_bAmbientLight = true; + lightState.m_bStaticLight = false; + lightState.m_nNumLights = 0; + } + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_DYNAMIC_VERTEX_SHADER( vertexlit_and_unlit_generic_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DYNAMIC_LIGHT, lightState.HasDynamicLight() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, numBones > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( TESSELLATION, 0 ); + SET_DYNAMIC_VERTEX_SHADER_CMD( DynamicCmdsOut, vertexlit_and_unlit_generic_vs20 ); + + // Bind ps_2_b shader so we can get shadow mapping + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( vertexlit_and_unlit_generic_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_CMD( DynamicCmdsOut, vertexlit_and_unlit_generic_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( vertexlit_and_unlit_generic_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_CMD( DynamicCmdsOut, vertexlit_and_unlit_generic_ps20 ); + } + } +#ifndef _X360 + else + { + if ( !bTreeSway ) + { + pShader->SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_10, VERTEX_SHADER_SHADER_SPECIFIC_CONST_11, SHADER_VERTEXTEXTURE_SAMPLER0 ); + } + + if ( bWorldNormal && IsPC() ) + { + float vEyeDir[4]; + pShaderAPI->GetWorldSpaceCameraDirection( vEyeDir ); + + float flFarZ = pShaderAPI->GetFarZ(); + vEyeDir[0] /= flFarZ; // Divide by farZ for SSAO algorithm + vEyeDir[1] /= flFarZ; + vEyeDir[2] /= flFarZ; + DynamicCmdsOut.SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, vEyeDir ); + } + + DECLARE_DYNAMIC_VERTEX_SHADER( vertexlit_and_unlit_generic_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DYNAMIC_LIGHT, lightState.HasDynamicLight() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, ( numBones > 0 ) && ( nTessellationMode == TESSELLATION_MODE_DISABLED ) ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression && ( nTessellationMode == TESSELLATION_MODE_DISABLED ) ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( TESSELLATION, nTessellationMode ); + SET_DYNAMIC_VERTEX_SHADER_CMD( DynamicCmdsOut, vertexlit_and_unlit_generic_vs30 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( vertexlit_and_unlit_generic_ps30 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bWorldNormal ? 0 : bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( UBERLIGHT, bUberlight ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_CMD( DynamicCmdsOut, vertexlit_and_unlit_generic_ps30 ); + + bool bUnusedTexCoords[3] = { false, false, !pShaderAPI->IsHWMorphingEnabled() || !bIsDecal }; + pShaderAPI->MarkUnusedVertexFields( 0, 3, bUnusedTexCoords ); + } +#endif + } + + if ( !bHasBump || bTreeSway ) + { + float fTempConst[4]; + fTempConst[0] = fSinglePassFlashlight; + fTempConst[1] = pShaderAPI->CurrentTime(); + Vector windDir = pShaderAPI->GetVectorRenderingParameter( VECTOR_RENDERPARM_WIND_DIRECTION ); + fTempConst[2] = windDir.x; + fTempConst[3] = windDir.y; + DynamicCmdsOut.SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_12, fTempConst ); + } + + float fWriteDepthToAlpha = bWriteDepthToAlpha && IsPC() ? 1.0f : 0.0f; + float fWriteWaterFogToDestAlpha = bWriteWaterFogToAlpha ? 1.0f : 0.0f; + float fVertexAlpha = bHasVertexAlpha ? 1.0f : 0.0f; + float fBlendTintByBaseAlpha = IsBoolSet( info.m_nBlendTintByBaseAlpha, params ) ? 1.0f : 0.0f; + + // Controls for lerp-style paths through shader code (used by bump and non-bump) + float vShaderControls[4] = { 1.0f - fBlendTintByBaseAlpha, fWriteDepthToAlpha, fWriteWaterFogToDestAlpha, fVertexAlpha }; + DynamicCmdsOut.SetPixelShaderConstant( 12, vShaderControls, 1 ); + + DynamicCmdsOut.End(); + pShaderAPI->ExecuteCommandBuffer( DynamicCmdsOut.Base() ); + } + pShader->Draw(); +} + + +void DrawVertexLitGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, bool bVertexLitGeneric, VertexLitGeneric_DX9_Vars_t &info, VertexCompressionType_t vertexCompression, + CBasePerMaterialContextData **pContextDataPtr ) +{ + if ( WantsPhongShader( params, info ) && g_pHardwareConfig->SupportsPixelShaders_2_b() /*&& mat_bumpmap.GetBool()*/ ) + { + DrawPhong_DX9( pShader, params, pShaderAPI, pShaderShadow, info, vertexCompression, pContextDataPtr ); + return; + } + + bool bReceiveFlashlight = bVertexLitGeneric || ( GetIntParam( info.m_nReceiveFlashlight, params ) != 0 ); + bool bHasFlashlight = bReceiveFlashlight && pShader->UsingFlashlight( params ); + + //since single pass flashlights have a different snapshot than multipass. We need to get snapshots of both and only actually draw the enabled mode + if( IsX360() || !bHasFlashlight || (GetIntParam( info.m_nSinglePassFlashlight, params ) == 0) ) + { + //360 only supports single pass flashlight, so bHasFlashlight == bSinglePassFlashlight. And single pass flashlights are the same as multipass when there's no flashlight. + DrawVertexLitGeneric_DX9_Internal( pShader, params, pShaderAPI, + pShaderShadow, bVertexLitGeneric, bHasFlashlight, IsX360(), info, vertexCompression, pContextDataPtr ); + } + else //single pass flashlight enabled material. Support both multipass and single pass flashlight + { + if( pShaderShadow ) + { + //snapshotting, grab a snapshot of both modes + DrawVertexLitGeneric_DX9_Internal( pShader, params, pShaderAPI, + pShaderShadow, bVertexLitGeneric, bHasFlashlight, false, info, vertexCompression, pContextDataPtr ); + DrawVertexLitGeneric_DX9_Internal( pShader, params, pShaderAPI, + pShaderShadow, bVertexLitGeneric, bHasFlashlight, true, info, vertexCompression, pContextDataPtr ); + } + else + { + Assert( pShaderAPI ); + if( pShaderAPI->SinglePassFlashlightModeEnabled() ) + { + //use only the second (singlepass flashlights) snapshot + pShader->Draw( false ); + DrawVertexLitGeneric_DX9_Internal( pShader, params, pShaderAPI, + pShaderShadow, bVertexLitGeneric, bHasFlashlight, true, info, vertexCompression, pContextDataPtr ); + } + else + { + //use only the first (multipass flashlights) snapshot + DrawVertexLitGeneric_DX9_Internal( pShader, params, pShaderAPI, + pShaderShadow, bVertexLitGeneric, bHasFlashlight, false, info, vertexCompression, pContextDataPtr ); + pShader->Draw( false ); + } + } + } +} diff --git a/materialsystem/stdshaders/vertexlitgeneric_dx9_helper.h b/materialsystem/stdshaders/vertexlitgeneric_dx9_helper.h new file mode 100644 index 00000000..1bea75ad --- /dev/null +++ b/materialsystem/stdshaders/vertexlitgeneric_dx9_helper.h @@ -0,0 +1,176 @@ +//========= Copyright © 1996-2007, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef VERTEXLITGENERIC_DX9_HELPER_H +#define VERTEXLITGENERIC_DX9_HELPER_H + +#include + + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct VertexLitGeneric_DX9_Vars_t +{ + VertexLitGeneric_DX9_Vars_t() { memset( this, 0xFF, sizeof(*this) ); } + + int m_nBaseTexture; + int m_nWrinkle; + int m_nStretch; + int m_nBaseTextureFrame; + int m_nBaseTextureTransform; + int m_nAlbedo; + int m_nDetail; + int m_nDetailFrame; + int m_nDetailScale; + int m_nEnvmap; + int m_nEnvmapFrame; + int m_nEnvmapMask; + int m_nEnvmapMaskFrame; + int m_nEnvmapMaskTransform; + int m_nEnvmapTint; + int m_nBumpmap; + int m_nNormalWrinkle; + int m_nNormalStretch; + int m_nBumpFrame; + int m_nBumpTransform; + int m_nEnvmapContrast; + int m_nEnvmapSaturation; + int m_nAlphaTestReference; + int m_nVertexAlphaTest; + int m_nFlashlightNoLambert; + int m_nFlashlightTexture; + int m_nFlashlightTextureFrame; + + int m_nSelfIllumTint; + int m_nSelfIllumFresnel; + int m_nSelfIllumFresnelMinMaxExp; + int m_nSelfIllumMaskScale; + + int m_nPhongExponent; + int m_nPhongTint; + int m_nPhongAlbedoTint; + int m_nPhongExponentTexture; + int m_nDiffuseWarpTexture; + int m_nPhongWarpTexture; + int m_nPhongBoost; + int m_nPhongFresnelRanges; + int m_nSelfIllumEnvMapMask_Alpha; + int m_nAmbientOnly; + int m_nHDRColorScale; + int m_nPhong; + int m_nBaseMapAlphaPhongMask; + int m_nBaseMapLuminancePhongMask; + int m_nEnvmapFresnel; + + int m_nDetailTextureCombineMode; + int m_nDetailTextureBlendFactor; + + // Rim lighting parameters + int m_nRimLight; + int m_nRimLightPower; + int m_nRimLightBoost; + int m_nRimMask; + + int m_nSeamlessScale; + int m_nSeamlessBase; + int m_nSeamlessDetail; + + // distance coded line art parameters + int m_nDistanceAlpha; + int m_nDistanceAlphaFromDetail; + + int m_nSoftEdges; + int m_nEdgeSoftnessStart; + int m_nEdgeSoftnessEnd; + int m_nScaleEdgeSoftnessBasedOnScreenRes; + + int m_nGlow; + int m_nGlowColor; + int m_nGlowAlpha; + int m_nGlowStart; + int m_nGlowEnd; + int m_nGlowX; + int m_nGlowY; + int m_nOutline; + int m_nOutlineColor; + int m_nOutlineAlpha; + int m_nOutlineStart0; + int m_nOutlineStart1; + int m_nOutlineEnd0; + int m_nOutlineEnd1; + int m_nScaleOutlineSoftnessBasedOnScreenRes; + + int m_nSeparateDetailUVs; + int m_nDetailTextureTransform; + + int m_nLinearWrite; + int m_nGammaColorRead; + + int m_nDetailTint; + int m_nInvertPhongMask; + + int m_nSelfIllumMask; + int m_nReceiveFlashlight; + int m_nSinglePassFlashlight; + + int m_nShaderSrgbRead360; + + int m_nAmbientOcclusion; + + int m_nBlendTintByBaseAlpha; + + int m_nDesaturateWithBaseAlpha; + + int m_nAllowDiffuseModulation; + + int m_nEnvMapFresnelMinMaxExp; + + int m_nBaseAlphaEnvMapMaskMinMaxExp; + + int m_nDisplacementMap; + + int m_nDisplacementWrinkleMap; + + int m_nPhongDisableHalfLambert; + + int m_nFoW; + + int m_nTreeSway; + int m_nTreeSwayHeight; + int m_nTreeSwayStartHeight; + int m_nTreeSwayRadius; + int m_nTreeSwayStartRadius; + int m_nTreeSwaySpeed; + int m_nTreeSwaySpeedHighWindMultiplier; + int m_nTreeSwayStrength; + int m_nTreeSwayScrumbleSpeed; + int m_nTreeSwayScrumbleStrength; + int m_nTreeSwayScrumbleFrequency; + int m_nTreeSwayFalloffExp; + int m_nTreeSwayScrumbleFalloffExp; + int m_nTreeSwaySpeedLerpStart; + int m_nTreeSwaySpeedLerpEnd; +}; + +void InitParamsVertexLitGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, bool bVertexLitGeneric, VertexLitGeneric_DX9_Vars_t &info ); +void InitVertexLitGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, bool bVertexLitGeneric, VertexLitGeneric_DX9_Vars_t &info ); +void DrawVertexLitGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, + bool bVertexLitGeneric, VertexLitGeneric_DX9_Vars_t &info, VertexCompressionType_t vertexCompression, + CBasePerMaterialContextData **pContextDataPtr ); + + +#endif // VERTEXLITGENERIC_DX9_HELPER_H diff --git a/materialsystem/stdshaders/vertexlitgeneric_flashlight_vs11.vsh b/materialsystem/stdshaders/vertexlitgeneric_flashlight_vs11.vsh new file mode 100644 index 00000000..d0c3b282 --- /dev/null +++ b/materialsystem/stdshaders/vertexlitgeneric_flashlight_vs11.vsh @@ -0,0 +1,137 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" +# DYNAMIC: "SKINNING" "0..1" +# STATIC: "TEETH" "0..1" + +#include "macros.vsh" + +local( $worldPos, $worldNormal, $projPos ); + +alloc $worldPos +alloc $worldNormal +alloc $projPos + +if( 0 ) +{ + ; NOTE: Don't do this optimization anymore since it would mean a gazillion combos + ; Special case for static prop lighting. We can go directly from + ; world to proj space for position, with the exception of z, which + ; is needed for fogging *if* height fog is enabled. + + ; NOTE: We don't use this path if $envmap is defined since we need + ; worldpos for envmapping. + dp4 $projPos.x, $vPos, $cModelViewProj0 + dp4 $projPos.y, $vPos, $cModelViewProj1 + dp4 $projPos.z, $vPos, $cModelViewProj2 + dp4 $projPos.w, $vPos, $cModelViewProj3 + ; normal + dp3 $worldNormal.x, $vNormal, $cModel0 + dp3 $worldNormal.y, $vNormal, $cModel1 + dp3 $worldNormal.z, $vNormal, $cModel2 + + ; Need this for height fog if it's enabled and for height clipping + dp4 $worldPos.z, $vPos, $cModel2 +} +else +{ + &SkinPositionAndNormal( $worldPos, $worldNormal ); + + if( $SKINNING == 1 ) + { + &Normalize( $worldNormal ); + } + + ;------------------------------------------------------------------------------ + ; Transform the position from world to view space + ;------------------------------------------------------------------------------ + dp4 $projPos.x, $worldPos, $cViewProj0 + dp4 $projPos.y, $worldPos, $cViewProj1 + dp4 $projPos.z, $worldPos, $cViewProj2 + dp4 $projPos.w, $worldPos, $cViewProj3 +} + +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ +&CalcFog( $worldPos, $projPos ); + +; base tex coords +dp4 oT1.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_6 +dp4 oT1.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_7 + +; normal map coords +;dp4 oT3.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_8 +;dp4 oT3.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_9 + +; spotlight texcoords +dp4 oT0.x, $worldPos, $SHADER_SPECIFIC_CONST_1 +dp4 oT0.y, $worldPos, $SHADER_SPECIFIC_CONST_2 +dp4 oT0.z, $worldPos, $SHADER_SPECIFIC_CONST_3 +dp4 oT0.w, $worldPos, $SHADER_SPECIFIC_CONST_4 + +local( $worldPosToLightVector, $distFactors ); + +alloc $worldPosToLightVector + +sub $worldPosToLightVector, $SHADER_SPECIFIC_CONST_0, $worldPos +mov oT2, $worldPosToLightVector + +local( $distatten ); +alloc $distatten +; $distatten = [ 1, 1/dist, 1/distsquared ] + +; dist squared +dp3 $distatten.z, $worldPosToLightVector, $worldPosToLightVector + +; oodist +rsq $distatten.y, $distatten.z + +mov $distatten.x, $cOne + +local( $dist ); +alloc $dist +mul $dist.x, $distatten.z, $distatten.y + +rcp $distatten.z, $distatten.z ; 1/distsquared + +local( $endFalloffFactor ); +alloc $endFalloffFactor + +; ( dist - farZ ) +sub $endFalloffFactor.x, $dist.x, $SHADER_SPECIFIC_CONST_5.w +; 1 / ( (0.6f * farZ) - farZ) +mul $endFalloffFactor, $endFalloffFactor.x, $SHADER_SPECIFIC_CONST_0.w +max $endFalloffFactor, $endFalloffFactor, $cZero +min $endFalloffFactor, $endFalloffFactor, $cOne + +local( $vertAtten ); +alloc $vertAtten +dp3 $vertAtten, $distatten, $SHADER_SPECIFIC_CONST_5 +mul $vertAtten, $vertAtten, $endFalloffFactor + +if( $TEETH ) +{ + alloc $mouthAtten + dp3 $mouthAtten, $worldNormal.xyz, $SHADER_SPECIFIC_CONST_10.xyz + max $mouthAtten, $cZero, $mouthAtten + mul $mouthAtten, $mouthAtten, $SHADER_SPECIFIC_CONST_10.w + mul $vertAtten, $vertAtten, $mouthAtten + free $mouthAtten +} + +mov oD0, $vertAtten + +mov oT3.xyz, $worldNormal.xyz + + +free $dist +free $endFalloffFactor +free $worldPos +free $worldNormal +free $projPos +free $worldPosToLightVector +free $distatten +free $vertAtten diff --git a/materialsystem/stdshaders/vertexlitgeneric_flashlight_vs20.fxc b/materialsystem/stdshaders/vertexlitgeneric_flashlight_vs20.fxc new file mode 100644 index 00000000..826ec0ea --- /dev/null +++ b/materialsystem/stdshaders/vertexlitgeneric_flashlight_vs20.fxc @@ -0,0 +1,126 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "TEETH" "0..1" + +// DYNAMIC: "SKINNING" "0..1" + +#include "common_fog_vs_supportsvertexfog_fxc.h" +#include "common_vs_fxc.h" + +static const bool g_bSkinning = SKINNING ? true : false; +static const int g_FogType = DOWATERFOG; +static const bool g_bTeeth = TEETH ? true: false; + +const float4 cLightPosition : register( SHADER_SPECIFIC_CONST_0 ); +const float4 cWorldToTextureTransform[4] : register( SHADER_SPECIFIC_CONST_1 ); +const float4 cAttenuationFactors : register( SHADER_SPECIFIC_CONST_5 ); +const float4 cBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_6 ); +const float4 cNormalMapOrDetailTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_8 ); +const float4 cTeethAttenuationConst : register( SHADER_SPECIFIC_CONST_10 ); + +struct VS_INPUT +{ + // This is all of the stuff that we ever use. + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vNormal : NORMAL; + + float2 vBaseTexCoord : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; // Projection-space position +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + float fog : FOG; +#endif + + float4 spotTexCoord : TEXCOORD0; + + float2 baseTexCoord : TEXCOORD1; + float3 vWorldToLight : TEXCOORD2; + float3 worldNormal : TEXCOORD3; + + //float2 detailCoords : TEXCOORD4; + float3 worldPos : TEXCOORD5; +#if HARDWAREFOGBLEND || DOPIXELFOG + float3 projPos_fogFactorW : TEXCOORD6; +#else + float4 projPos_fogFactorW : TEXCOORD6; +#endif + + float4 vDiffuse : COLOR0; +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + // Perform skinning + float3 worldNormal, worldPos; + SkinPositionAndNormal( + g_bSkinning, + v.vPos, v.vNormal, + v.vBoneWeights, v.vBoneIndices, + worldPos, worldNormal ); + + if( g_bSkinning ) + { + worldNormal = normalize( worldNormal ); + } + + o.vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + + o.worldPos = worldPos; + o.projPos_fogFactorW.xyz = o.vProjPos.xyz; + +#if HARDWAREFOGBLEND + o.fog = CalcFixedFunctionFog( worldPos, g_FogType ); +#endif +#if !DOPIXELFOG && !HARDWAREFOGBLEND + o.projPos_fogFactorW.w = CalcNonFixedFunctionFog( worldPos, g_FogType ); +#endif + + o.spotTexCoord.x = dot( worldPos, cWorldToTextureTransform[0] ) + cWorldToTextureTransform[0].w; + o.spotTexCoord.y = dot( worldPos, cWorldToTextureTransform[1] ) + cWorldToTextureTransform[1].w; + o.spotTexCoord.z = dot( worldPos, cWorldToTextureTransform[2] ) + cWorldToTextureTransform[2].w; + o.spotTexCoord.w = dot( worldPos, cWorldToTextureTransform[3] ) + cWorldToTextureTransform[3].w; + + o.baseTexCoord.x = dot( v.vBaseTexCoord, cBaseTexCoordTransform[0] ) + cBaseTexCoordTransform[0].w; + o.baseTexCoord.y = dot( v.vBaseTexCoord, cBaseTexCoordTransform[1] ) + cBaseTexCoordTransform[1].w; + + float3 vWorldPosToLight = cLightPosition - worldPos; + o.vWorldToLight = vWorldPosToLight; + + float3 distatten; + distatten.z = dot( vWorldPosToLight, vWorldPosToLight ); + distatten.y = rsqrt( distatten.z ); + distatten.x = 1.0f; + + float dist = distatten.z * distatten.y; + + distatten.z = 1 / distatten.z; + + float endFalloffFactor = dist - cAttenuationFactors.w; + endFalloffFactor *= cLightPosition.w; + endFalloffFactor = saturate( endFalloffFactor ); + + float vertAtten = dot( distatten, cAttenuationFactors.xyz ) * endFalloffFactor; + + if( g_bTeeth ) + { + float mouthAtten = dot( worldNormal.xyz, cTeethAttenuationConst.xyz ); + mouthAtten = max( mouthAtten, 0.0f ); + mouthAtten *= cTeethAttenuationConst.w; + vertAtten *= mouthAtten; + } + + o.vDiffuse = vertAtten; + o.worldNormal = worldNormal; + + return o; +} + + + diff --git a/materialsystem/stdshaders/viewalpha.cpp b/materialsystem/stdshaders/viewalpha.cpp new file mode 100644 index 00000000..96fabb02 --- /dev/null +++ b/materialsystem/stdshaders/viewalpha.cpp @@ -0,0 +1,48 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "shaderlib/CShader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_SHADER_FLAGS( ViewAlpha, "Help for ViewAlpha", SHADER_NOT_EDITABLE ) + + BEGIN_SHADER_PARAMS + END_SHADER_PARAMS + + SHADER_INIT + { + LoadTexture( BASETEXTURE ); + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableCustomPixelPipe( true ); + pShaderShadow->CustomTextureStages( 1 ); + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_COLOR, SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_TEXTUREALPHA, SHADER_TEXARG_CONSTANTCOLOR ); + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_ALPHA, SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_TEXTURE, SHADER_TEXARG_VERTEXCOLOR ); + + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 ); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + SetFixedFunctionTextureTransform( MATERIAL_TEXTURE0, BASETEXTURETRANSFORM ); + } + Draw( ); + + } +END_SHADER diff --git a/materialsystem/stdshaders/volume_clouds.cpp b/materialsystem/stdshaders/volume_clouds.cpp new file mode 100644 index 00000000..5fe9204f --- /dev/null +++ b/materialsystem/stdshaders/volume_clouds.cpp @@ -0,0 +1,53 @@ +//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============// + +#include "BaseVSShader.h" +#include "volume_clouds_helper.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( VolumeClouds, VolumeClouds_dx9 ) +BEGIN_VS_SHADER( VolumeClouds_dx9, "VolumeClouds" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( REFRACTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "2", "" ) + SHADER_PARAM( BASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Texture 1" ) + SHADER_PARAM( BASETEXTURE2, SHADER_PARAM_TYPE_TEXTURE, "", "Texture 2" ) + SHADER_PARAM( BASETEXTURE3, SHADER_PARAM_TYPE_TEXTURE, "", "Texture 3" ) + SHADER_PARAM( TIME, SHADER_PARAM_TYPE_FLOAT, "0.0", "Needs CurrentTime Proxy" ) + END_SHADER_PARAMS + + void SetupVarsVolumeClouds( VolumeCloudsVars_t &info ) + { + info.m_nRefractAmount = REFRACTAMOUNT; + info.m_nTexture1 = BASETEXTURE; + info.m_nTexture2 = BASETEXTURE2; + info.m_nTexture3 = BASETEXTURE3; + info.m_nTime = TIME; + } + + SHADER_INIT_PARAMS() + { + VolumeCloudsVars_t info; + SetupVarsVolumeClouds( info ); + InitParamsVolumeClouds( this, params, pMaterialName, info ); + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + VolumeCloudsVars_t info; + SetupVarsVolumeClouds( info ); + InitVolumeClouds( this, params, info ); + } + + SHADER_DRAW + { + VolumeCloudsVars_t info; + SetupVarsVolumeClouds( info ); + DrawVolumeClouds( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } +END_SHADER diff --git a/materialsystem/stdshaders/volume_clouds_helper.cpp b/materialsystem/stdshaders/volume_clouds_helper.cpp new file mode 100644 index 00000000..08f172f5 --- /dev/null +++ b/materialsystem/stdshaders/volume_clouds_helper.cpp @@ -0,0 +1,141 @@ +//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============// + +#include "BaseVSShader.h" +#include "mathlib/VMatrix.h" +#include "volume_clouds_helper.h" +#include "convar.h" + +// Auto generated inc files +#include "volume_clouds_vs20.inc" +#include "volume_clouds_ps20.inc" +#include "volume_clouds_ps20b.inc" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +void InitParamsVolumeClouds( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, VolumeCloudsVars_t &info ) +{ + // Set material flags + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + SET_FLAGS( MATERIAL_VAR_TRANSLUCENT ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nTime, 0.0f ); + + // Set material parameter default values + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nRefractAmount, kDefaultRefractAmount ); +} + +void InitVolumeClouds( CBaseVSShader *pShader, IMaterialVar** params, VolumeCloudsVars_t &info ) +{ + // Load textures + if ( (info.m_nTexture1 != -1) && params[info.m_nTexture1]->IsDefined() ) + { + pShader->LoadTexture( info.m_nTexture1 ); + } + + if ( (info.m_nTexture2 != -1) && params[info.m_nTexture2]->IsDefined() ) + { + pShader->LoadTexture( info.m_nTexture2 ); + } + + if ( (info.m_nTexture3 != -1) && params[info.m_nTexture3]->IsDefined() ) + { + pShader->LoadTexture( info.m_nTexture3 ); + } +} + +void DrawVolumeClouds( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, VolumeCloudsVars_t &info, VertexCompressionType_t vertexCompression ) +{ + SHADOW_STATE + { + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + // Vertex Shader + DECLARE_STATIC_VERTEX_SHADER( volume_clouds_vs20 ); + SET_STATIC_VERTEX_SHADER( volume_clouds_vs20 ); + + // Pixel Shader + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( volume_clouds_ps20b ); + SET_STATIC_PIXEL_SHADER( volume_clouds_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( volume_clouds_ps20 ); + SET_STATIC_PIXEL_SHADER( volume_clouds_ps20 ); + } + + // Textures + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, true ); + pShaderShadow->EnableSRGBWrite( true ); + + // Blending + pShader->EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + pShaderShadow->EnableAlphaWrites( false ); + + // !!! We need to turn this back on because EnableAlphaBlending() above disables it! + //pShaderShadow->EnableDepthWrites( true ); + } + DYNAMIC_STATE + { + // Set Vertex Shader Combos + DECLARE_DYNAMIC_VERTEX_SHADER( volume_clouds_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( volume_clouds_vs20 ); + + // Set Vertex Shader Constants + + // Time + float vPackedVsConst1[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + float flTime = IS_PARAM_DEFINED( info.m_nTime ) && params[info.m_nTime]->GetFloatValue() > 0.0f ? params[info.m_nTime]->GetFloatValue() : pShaderAPI->CurrentTime(); + float flRotateSpeed = 0.065f; + vPackedVsConst1[0] = flTime * flRotateSpeed * 1.0f; + vPackedVsConst1[1] = flTime * flRotateSpeed * 2.0f; + vPackedVsConst1[2] = flTime * flRotateSpeed * 4.0f; + vPackedVsConst1[0] -= (float)( (int)( vPackedVsConst1[0] / ( 2.0f * 3.14159f ) ) ) * 2.0f * 3.14159f; + vPackedVsConst1[1] -= (float)( (int)( vPackedVsConst1[1] / ( 2.0f * 3.14159f ) ) ) * 2.0f * 3.14159f; + vPackedVsConst1[2] -= (float)( (int)( vPackedVsConst1[2] / ( 2.0f * 3.14159f ) ) ) * 2.0f * 3.14159f; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, vPackedVsConst1, 1 ); + + // Set Pixel Shader Combos + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( volume_clouds_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( volume_clouds_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( volume_clouds_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( volume_clouds_ps20 ); + } + + // Bind textures + pShader->BindTexture( SHADER_SAMPLER0, info.m_nTexture1 ); + pShader->BindTexture( SHADER_SAMPLER1, info.m_nTexture2 ); + pShader->BindTexture( SHADER_SAMPLER2, info.m_nTexture3 ); + + // Set Pixel Shader Constants + float vEyePos[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos ); + pShaderAPI->SetPixelShaderConstant( 5, vEyePos, 1 ); + + float vPackedConst6[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vPackedConst6[0] = IS_PARAM_DEFINED( info.m_nRefractAmount ) ? params[info.m_nRefractAmount]->GetFloatValue() : kDefaultRefractAmount; + vPackedConst6[1] = vPackedVsConst1[0]; // Time % 1000 + pShaderAPI->SetPixelShaderConstant( 6, vPackedConst6, 1 ); + } + pShader->Draw(); +} diff --git a/materialsystem/stdshaders/volume_clouds_helper.h b/materialsystem/stdshaders/volume_clouds_helper.h new file mode 100644 index 00000000..678ba2b7 --- /dev/null +++ b/materialsystem/stdshaders/volume_clouds_helper.h @@ -0,0 +1,41 @@ +//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============// + +#ifndef VOLUME_CLOUDS_HELPER_H +#define VOLUME_CLOUDS_HELPER_H +#ifdef _WIN32 +#pragma once +#endif + +#include + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct VolumeCloudsVars_t +{ + VolumeCloudsVars_t() { memset( this, 0xFF, sizeof( VolumeCloudsVars_t ) ); } + + int m_nRefractAmount; + int m_nTexture1; + int m_nTexture2; + int m_nTexture3; + int m_nTime; +}; + +// Default values (Arrays should only be vec[4]) +static const float kDefaultRefractAmount = 0.1f; + +void InitParamsVolumeClouds( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, VolumeCloudsVars_t &info ); +void InitVolumeClouds( CBaseVSShader *pShader, IMaterialVar** params, VolumeCloudsVars_t &info ); +void DrawVolumeClouds( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, VolumeCloudsVars_t &info, VertexCompressionType_t vertexCompression ); + +#endif // VolumeClouds_HELPER_H diff --git a/materialsystem/stdshaders/volume_clouds_ps2x.fxc b/materialsystem/stdshaders/volume_clouds_ps2x.fxc new file mode 100644 index 00000000..601c3cbc --- /dev/null +++ b/materialsystem/stdshaders/volume_clouds_ps2x.fxc @@ -0,0 +1,63 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// Includes ======================================================================================= +#include "common_vertexlitgeneric_dx9.h" + +// Texture Samplers =============================================================================== +sampler g_tInnerSampler : register( s0 ); +sampler g_tMiddleSampler : register( s1 ); +sampler g_tOuterSampler : register( s2 ); + +// Shaders Constants and Globals ================================================================== +//const float4 g_vPackedConst6 : register( c6 ); +//#define g_flTime g_vPackedConst6.w + +// Interpolated values ============================================================================ +struct PS_INPUT +{ + float4 v2DTangentViewVector01 : TEXCOORD0; + float4 vUv01 : TEXCOORD1; + float4 v2DTangentViewVector2_vUv2 : TEXCOORD2; +}; + +// Main =========================================================================================== +float4 main( PS_INPUT i ) : COLOR +{ + float4 vFinalColor = float4( 0.0f, 0.0f, 0.0f, 1.0f ); + +#if defined(SHADER_MODEL_PS_2_0) + float flNumLayers = 2.0f; +#else + float flNumLayers = 10.0f; +#endif + + //float flColorDim = 1.0f; + for ( float j=flNumLayers-1.0f; j>=0.0f; j-=1.0f ) // From hightest to lowest layer + { + float4 vInnerTexel = tex2D( g_tInnerSampler, saturate( i.vUv01.xy + i.v2DTangentViewVector01.xy * 0.005 * j ) ); + float4 vMiddleTexel = tex2D( g_tMiddleSampler, saturate( i.vUv01.wz + i.v2DTangentViewVector01.wz * 0.005 * j ) ); + float4 vOuterTexel = tex2D( g_tOuterSampler, saturate( i.v2DTangentViewVector2_vUv2.wz + i.v2DTangentViewVector2_vUv2.xy * 0.005 * j ) ); + + float4 vThisTexel; + vThisTexel.rgb = ( vInnerTexel.rgb * vInnerTexel.a ) + ( vMiddleTexel.rgb * vMiddleTexel.a ) + ( vOuterTexel.rgb * vOuterTexel.a ); + vThisTexel.a = 1.0f - ( ( 1.0f - vOuterTexel.a ) * ( 1.0f - vMiddleTexel.a ) * ( 1.0f - vInnerTexel.a ) ); + + //vThisTexel.rgb *= flColorDim; + //flColorDim *= 0.95f; + + // 5.0 and 0.8625 are magic numbers that look good with the current textures + float flBlendValue = saturate( pow( vThisTexel.a, lerp( 5.0f, 0.8625f, saturate( j/(flNumLayers-1.0f) ) ) ) ); + + vFinalColor.rgb = vThisTexel.rgb + ( vFinalColor.rgb * ( 1.0f - flBlendValue ) ); + vFinalColor.a *= 1.0f - flBlendValue; // Dest alpha scalar + } + + //===============// + // Combine terms // + //===============// + float4 result; + result.rgb = vFinalColor.rgb; + result.a = 1.0f - vFinalColor.a; + + return FinalOutput( result, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_LINEAR ); //go back to final output when it'll fit. +} diff --git a/materialsystem/stdshaders/volume_clouds_vs20.fxc b/materialsystem/stdshaders/volume_clouds_vs20.fxc new file mode 100644 index 00000000..f7b6d18d --- /dev/null +++ b/materialsystem/stdshaders/volume_clouds_vs20.fxc @@ -0,0 +1,103 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "SKINNING" "0..1" + +// Includes +#include "common_vs_fxc.h" + +// Globals +static const bool g_bSkinning = SKINNING ? true : false; + +const float3 g_vTime : register( SHADER_SPECIFIC_CONST_0 ); +#define g_flTime1x g_vTime.x +#define g_flTime2x g_vTime.y +#define g_flTime4x g_vTime.z + +const float4 cBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_1 ); + +// Structs +struct VS_INPUT +{ + float4 vPos : POSITION; // Position + float4 vNormal : NORMAL; // Normal + float4 vBoneWeights : BLENDWEIGHT; // Skin weights + float4 vBoneIndices : BLENDINDICES; // Skin indices + float4 vTexCoord0 : TEXCOORD0; // Base texture coordinates + float4 vUserData : TANGENT; +}; + +struct VS_OUTPUT +{ + float4 vProjPosition : POSITION; // Projection-space position + float4 v2DTangentViewVector01 : TEXCOORD0; + float4 vUv01 : TEXCOORD1; + float4 v2DTangentViewVector2_vUv2 : TEXCOORD2; +}; + +// Main +VS_OUTPUT main( const VS_INPUT i ) +{ + VS_OUTPUT o; + + // Decompress compressed normal and tangent + float4 vObjPosition = i.vPos.xyzw; + float3 vObjNormal; + float4 vObjTangent; + DecompressVertex_NormalTangent( i.vNormal, i.vUserData, vObjNormal, vObjTangent ); + + // Transform the position + float3 vWorldPosition = { 0.0f, 0.0f, 0.0f }; + float3 vWorldNormal = { 0.0f, 0.0f, 0.0f }; + float3 vWorldTangent = { 0.0f, 0.0f, 0.0f }; + float3 vWorldBinormal = { 0.0f, 0.0f, 0.0f }; + SkinPositionNormalAndTangentSpace( g_bSkinning, vObjPosition, vObjNormal.xyz, vObjTangent.xyzw, i.vBoneWeights, i.vBoneIndices, vWorldPosition, vWorldNormal, vWorldTangent, vWorldBinormal ); + vWorldNormal.xyz = normalize( vWorldNormal.xyz ); + vWorldTangent.xyz = normalize( vWorldTangent.xyz ); + vWorldBinormal.xyz = normalize( vWorldBinormal.xyz ); + + // Transform into projection space + float4 vProjPosition = mul( float4( vWorldPosition, 1.0f ), cViewProj ); + o.vProjPosition = vProjPosition; + + // View vector + float3 vWorldViewVector = normalize( vWorldPosition.xyz - cEyePos.xyz ); + float3 vTangentViewVector = Vec3WorldToTangentNormalized( vWorldViewVector.xyz, vWorldNormal.xyz, vWorldTangent.xyz, vWorldBinormal.xyz ); + + // Texture coordinates + float4 mRotate; + float2 vBaseUv = i.vTexCoord0.xy; + + // Inner layer + mRotate.x = cos( g_flTime4x ); + mRotate.y = -sin( g_flTime4x ); + mRotate.z = -mRotate.y; + mRotate.w = mRotate.x; + o.vUv01.xy = ( vBaseUv.xy - 0.5f ) * 1.0f; + o.vUv01.xy = float2( dot( o.vUv01.xy, mRotate.xy ), dot( o.vUv01.xy, mRotate.zw ) ); + o.vUv01.xy += 0.5f; + o.v2DTangentViewVector01.xy = float2( dot( vTangentViewVector.xy, mRotate.xy ), dot( vTangentViewVector.xy, mRotate.zw ) ); + + // Middle layer + mRotate.x = cos( g_flTime2x ); + mRotate.y = -sin( g_flTime2x ); + mRotate.z = -mRotate.y; + mRotate.w = mRotate.x; + o.vUv01.wz = ( vBaseUv.xy - 0.5f ) * 1.0f; + o.vUv01.wz = float2( dot( o.vUv01.wz, mRotate.xy ), dot( o.vUv01.wz, mRotate.zw ) ); + o.vUv01.wz += 0.5f; + o.v2DTangentViewVector01.wz = float2( dot( vTangentViewVector.xy, mRotate.xy ), dot( vTangentViewVector.xy, mRotate.zw ) ); + + // Outer layer + mRotate.x = cos( g_flTime1x ); + mRotate.y = -sin( g_flTime1x ); + mRotate.z = -mRotate.y; + mRotate.w = mRotate.x; + float2 vUv2 = ( vBaseUv.xy - 0.5f ) * 1.0f; + vUv2.xy = float2( dot( vUv2.xy, mRotate.xy ), dot( vUv2.xy, mRotate.zw ) ); + vUv2.xy += 0.5f; + o.v2DTangentViewVector2_vUv2.wz = vUv2.xy; + o.v2DTangentViewVector2_vUv2.xy = float2( dot( vTangentViewVector.xy, mRotate.xy ), dot( vTangentViewVector.xy, mRotate.zw ) ); + + return o; +} diff --git a/materialsystem/stdshaders/volumetricfog.cpp b/materialsystem/stdshaders/volumetricfog.cpp new file mode 100644 index 00000000..bc7b2d44 --- /dev/null +++ b/materialsystem/stdshaders/volumetricfog.cpp @@ -0,0 +1,37 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "shaderlib/CShader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_SHADER( VolumetricFog, "Help for VolumetricFog" ) + BEGIN_SHADER_PARAMS + END_SHADER_PARAMS + + SHADER_INIT + { + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->DepthFunc( SHADER_DEPTHFUNC_NEAREROREQUAL ); + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->BlendFunc( SHADER_BLEND_ONE, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_COLOR ); + } + DYNAMIC_STATE + { + } + Draw(); + } +END_SHADER diff --git a/materialsystem/stdshaders/vortwarp_dx9.cpp b/materialsystem/stdshaders/vortwarp_dx9.cpp new file mode 100644 index 00000000..0f2ebeba --- /dev/null +++ b/materialsystem/stdshaders/vortwarp_dx9.cpp @@ -0,0 +1,632 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" +#include "vertexlitgeneric_dx9_helper.h" +#include "vortwarp_vs20.inc" +#include "vortwarp_ps20.inc" +#include "vortwarp_ps20b.inc" +#include "convar.h" + +#ifndef _X360 +#include "vortwarp_vs30.inc" +#include "vortwarp_ps30.inc" +#endif + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +DEFINE_FALLBACK_SHADER( VortWarp, VortWarp_dx9 ) + +struct VortWarp_DX9_Vars_t : public VertexLitGeneric_DX9_Vars_t +{ + VortWarp_DX9_Vars_t() { memset( this, 0xFF, sizeof(*this) ); } + int m_nEntityOrigin; + int m_nWarpParam; + int m_nFlowMap; + int m_nSelfIllumMap; + int m_nUnlit; +}; + + +//----------------------------------------------------------------------------- +// Draws the shader +//----------------------------------------------------------------------------- +void DrawVortWarp_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, bool bVertexLitGeneric, bool hasFlashlight, VortWarp_DX9_Vars_t &info, VertexCompressionType_t vertexCompression ) +{ + bool hasBaseTexture = params[info.m_nBaseTexture]->IsTexture(); + bool hasBump = (info.m_nBumpmap != -1) && params[info.m_nBumpmap]->IsTexture(); + bool hasDetailTexture = !hasBump && params[info.m_nDetail]->IsTexture(); + bool hasNormalMapAlphaEnvmapMask = IS_FLAG_SET( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ); + bool hasVertexColor = bVertexLitGeneric ? false : IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR ); + bool hasVertexAlpha = bVertexLitGeneric ? false : IS_FLAG_SET( MATERIAL_VAR_VERTEXALPHA ); + bool bIsAlphaTested = IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) != 0; + bool hasSelfIllumInEnvMapMask = + ( info.m_nSelfIllumEnvMapMask_Alpha != -1 ) && + ( params[info.m_nSelfIllumEnvMapMask_Alpha]->GetFloatValue() != 0.0 ) ; + bool bHasFlowMap = ( info.m_nFlowMap != -1 ) && params[info.m_nFlowMap]->IsTexture(); + bool bHasSelfIllumMap = ( info.m_nSelfIllumMap != -1 ) && params[info.m_nSelfIllumMap]->IsTexture(); + + BlendType_t blendType; + if ( params[info.m_nBaseTexture]->IsTexture() ) + { + blendType = pShader->EvaluateBlendRequirements( info.m_nBaseTexture, true ); + } + else + { + blendType = pShader->EvaluateBlendRequirements( info.m_nEnvmapMask, false ); + } + + + if( pShader->IsSnapshotting() ) + { + // look at color and alphamod stuff. + // Unlit generic never uses the flashlight + bool hasEnvmap = !hasFlashlight && params[info.m_nEnvmap]->IsTexture(); + bool hasEnvmapMask = (hasSelfIllumInEnvMapMask || !hasFlashlight) && + params[info.m_nEnvmapMask]->IsTexture(); + bool bHasNormal = bVertexLitGeneric || hasEnvmap; + + if( hasFlashlight ) + { + hasEnvmapMask = false; + } + + bool bHalfLambert = IS_FLAG_SET( MATERIAL_VAR_HALFLAMBERT ); + // Alpha test: FIXME: shouldn't this be handled in CBaseVSShader::SetInitialShadowState + pShaderShadow->EnableAlphaTest( bIsAlphaTested ); + + if( info.m_nAlphaTestReference != -1 && params[info.m_nAlphaTestReference]->GetFloatValue() > 0.0f ) + { + pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GEQUAL, params[info.m_nAlphaTestReference]->GetFloatValue() ); + } + + if( hasFlashlight ) + { + if (params[info.m_nBaseTexture]->IsTexture()) + { + pShader->SetAdditiveBlendingShadowState( info.m_nBaseTexture, true ); + } + else + { + pShader->SetAdditiveBlendingShadowState( info.m_nEnvmapMask, false ); + } + if( bIsAlphaTested ) + { + // disable alpha test and use the zfunc zequals since alpha isn't guaranteed to + // be the same on both the regular pass and the flashlight pass. + pShaderShadow->EnableAlphaTest( false ); + pShaderShadow->DepthFunc( SHADER_DEPTHFUNC_EQUAL ); + } + pShaderShadow->EnableBlending( true ); + pShaderShadow->EnableDepthWrites( false ); + } + else + { + if (params[info.m_nBaseTexture]->IsTexture()) + { + pShader->SetDefaultBlendingShadowState( info.m_nBaseTexture, true ); + } + else + { + pShader->SetDefaultBlendingShadowState( info.m_nEnvmapMask, false ); + } + } + + unsigned int flags = VERTEX_POSITION; + int nTexCoordCount = 1; // texcoord0 : base texcoord + int userDataSize = 0; + if( bHasNormal ) + { + flags |= VERTEX_NORMAL; + } + + if( hasBaseTexture ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + } + if( hasEnvmap ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ) + { + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); + } + } + if( hasFlashlight ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER7, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + userDataSize = 4; // tangent S + } + if( hasDetailTexture ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + } + if( hasBump ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + userDataSize = 4; // tangent S + // Normalizing cube map + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); + } + if( hasEnvmapMask ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + } + + if( hasVertexColor || hasVertexAlpha ) + { + flags |= VERTEX_COLOR; + } + + pShaderShadow->EnableSRGBWrite( true ); + + if( bHasSelfIllumMap ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); + } + + if( bHasFlowMap ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + } + + // This shader supports compressed vertices, so OR in that flag: + flags |= VERTEX_FORMAT_COMPRESSED; + + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + Assert( hasBump ); + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_STATIC_VERTEX_SHADER( vortwarp_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT, bHalfLambert); + SET_STATIC_VERTEX_SHADER( vortwarp_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( vortwarp_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE, hasBaseTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, hasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSELIGHTING, !params[info.m_nUnlit]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMALMAPALPHAENVMAPMASK, hasNormalMapAlphaEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( HALFLAMBERT, bHalfLambert); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, hasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( TRANSLUCENT, blendType == BT_BLEND ); + SET_STATIC_PIXEL_SHADER( vortwarp_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( vortwarp_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE, hasBaseTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, hasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSELIGHTING, !params[info.m_nUnlit]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMALMAPALPHAENVMAPMASK, hasNormalMapAlphaEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( HALFLAMBERT, bHalfLambert); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, hasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( TRANSLUCENT, blendType == BT_BLEND ); + SET_STATIC_PIXEL_SHADER( vortwarp_ps20 ); + } + } +#ifndef _X360 + else + { + // The vertex shader uses the vertex id stream + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + + DECLARE_STATIC_VERTEX_SHADER( vortwarp_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT, bHalfLambert); + SET_STATIC_VERTEX_SHADER( vortwarp_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( vortwarp_ps30 ); + SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE, hasBaseTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, hasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSELIGHTING, !params[info.m_nUnlit]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMALMAPALPHAENVMAPMASK, hasNormalMapAlphaEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( HALFLAMBERT, bHalfLambert); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, hasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( TRANSLUCENT, blendType == BT_BLEND ); + SET_STATIC_PIXEL_SHADER( vortwarp_ps30 ); + } +#endif + + if( hasFlashlight ) + { + pShader->FogToBlack(); + } + else + { + pShader->DefaultFog(); + } + + if( blendType == BT_BLEND ) + { + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + pShaderShadow->EnableAlphaWrites( false ); + } + else + { + pShaderShadow->EnableAlphaWrites( true ); + } + + // Lighting constants + pShader->PI_BeginCommandBuffer(); + if( hasBump ) + { + pShader->PI_SetPixelShaderAmbientLightCube( 5 ); + pShader->PI_SetPixelShaderLocalLighting( 13 ); + } + pShader->PI_SetVertexShaderAmbientLightCube(); + if ( ( info.m_nHDRColorScale != -1 ) && pShader->IsHDREnabled() ) + { + pShader->PI_SetModulationPixelShaderDynamicState_LinearColorSpace_LinearScale( 1, params[info.m_nHDRColorScale]->GetFloatValue() ); + } + else + { + pShader->PI_SetModulationPixelShaderDynamicState_LinearColorSpace( 1 ); + } + pShader->PI_EndCommandBuffer(); + } + else + { + bool hasEnvmap = !hasFlashlight && params[info.m_nEnvmap]->IsTexture(); + bool hasEnvmapMask = !hasFlashlight && params[info.m_nEnvmapMask]->IsTexture(); + + if( hasBaseTexture ) + { + pShader->BindTexture( SHADER_SAMPLER0, info.m_nBaseTexture, info.m_nBaseTextureFrame ); + } + if( hasEnvmap ) + { + pShader->BindTexture( SHADER_SAMPLER1, info.m_nEnvmap, info.m_nEnvmapFrame ); + } + if( hasDetailTexture ) + { + pShader->BindTexture( SHADER_SAMPLER2, info.m_nDetail, info.m_nDetailFrame ); + } + if( !g_pConfig->m_bFastNoBump ) + { + if( hasBump ) + { + pShader->BindTexture( SHADER_SAMPLER3, info.m_nBumpmap, info.m_nBumpFrame ); + } + } + else + { + if( hasBump ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER3, TEXTURE_NORMALMAP_FLAT ); + } + } + if( hasEnvmapMask ) + { + pShader->BindTexture( SHADER_SAMPLER4, info.m_nEnvmapMask, info.m_nEnvmapMaskFrame ); + } + + if( hasFlashlight ) + { + Assert( info.m_nFlashlightTexture >= 0 && info.m_nFlashlightTextureFrame >= 0 ); + pShader->BindTexture( SHADER_SAMPLER7, info.m_nFlashlightTexture, info.m_nFlashlightTextureFrame ); + VMatrix worldToTexture; + ITexture *pFlashlightDepthTexture; + FlashlightState_t state = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture ); + SetFlashLightColorFromState( state, pShaderAPI, false ); + } + + // Set up light combo state + LightState_t lightState = {0, false, false}; + if ( bVertexLitGeneric && !hasFlashlight ) + { + pShaderAPI->GetDX9LightState( &lightState ); + } + + MaterialFogMode_t fogType = pShaderAPI->GetSceneFogMode(); + int numBones = pShaderAPI->GetCurrentNumBones(); + + Assert( hasBump ); + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_DYNAMIC_VERTEX_SHADER( vortwarp_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, numBones > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( vortwarp_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( vortwarp_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( AMBIENT_LIGHT, lightState.m_bAmbientLight ? 1 : 0 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z && + blendType != BT_BLENDADD && blendType != BT_BLEND && !bIsAlphaTested ); + float warpParam = params[info.m_nWarpParam]->GetFloatValue(); + // float selfIllumTint = params[info.m_nSelfIllumTint]->GetFloatValue(); + // DevMsg( 1, "warpParam: %f %f\n", warpParam, selfIllumTint ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WARPINGIN, warpParam > 0.0f && warpParam < 1.0f ); + SET_DYNAMIC_PIXEL_SHADER( vortwarp_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( vortwarp_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( AMBIENT_LIGHT, lightState.m_bAmbientLight ? 1 : 0 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z && + blendType != BT_BLENDADD && blendType != BT_BLEND && !bIsAlphaTested ); + float warpParam = params[info.m_nWarpParam]->GetFloatValue(); + // float selfIllumTint = params[info.m_nSelfIllumTint]->GetFloatValue(); + // DevMsg( 1, "warpParam: %f %f\n", warpParam, selfIllumTint ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WARPINGIN, warpParam > 0.0f && warpParam < 1.0f ); + SET_DYNAMIC_PIXEL_SHADER( vortwarp_ps20 ); + } + } +#ifndef _X360 + else + { + pShader->SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, SHADER_VERTEXTEXTURE_SAMPLER0 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( vortwarp_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, numBones > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( vortwarp_vs30 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( vortwarp_ps30 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( AMBIENT_LIGHT, lightState.m_bAmbientLight ? 1 : 0 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z && + blendType != BT_BLENDADD && blendType != BT_BLEND && !bIsAlphaTested ); + float warpParam = params[info.m_nWarpParam]->GetFloatValue(); + // float selfIllumTint = params[info.m_nSelfIllumTint]->GetFloatValue(); + // DevMsg( 1, "warpParam: %f %f\n", warpParam, selfIllumTint ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WARPINGIN, warpParam > 0.0f && warpParam < 1.0f ); + SET_DYNAMIC_PIXEL_SHADER( vortwarp_ps30 ); + } +#endif + + pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, info.m_nBaseTextureTransform ); + + if( hasDetailTexture ) + { + pShader->SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, info.m_nBaseTextureTransform, info.m_nDetailScale ); + Assert( !hasBump ); + } + if( hasBump ) + { + pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, info.m_nBumpTransform ); + Assert( !hasDetailTexture ); + } + if( hasEnvmapMask ) + { + pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, info.m_nEnvmapMaskTransform ); + } + + if( hasEnvmap ) + { + pShader->SetEnvMapTintPixelShaderDynamicState( 0, info.m_nEnvmapTint, -1, true ); + } + + pShader->SetPixelShaderConstant( 2, info.m_nEnvmapContrast ); + pShader->SetPixelShaderConstant( 3, info.m_nEnvmapSaturation ); + + pShader->SetPixelShaderConstant( 4, info.m_nSelfIllumTint ); + if( hasBump ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER5, TEXTURE_NORMALIZATION_CUBEMAP_SIGNED ); + } + + if( bHasSelfIllumMap ) + { + pShader->BindTexture( SHADER_SAMPLER6, info.m_nSelfIllumMap, -1 ); + } + + if( bHasFlowMap ) + { + pShader->BindTexture( SHADER_SAMPLER2, info.m_nFlowMap, -1 ); + } + + float eyePos[4]; + pShaderAPI->GetWorldSpaceCameraPosition( eyePos ); + pShaderAPI->SetPixelShaderConstant( 20, eyePos, 1 ); + pShaderAPI->SetPixelShaderFogParams( 21 ); + + // dynamic drawing code that extends vertexlitgeneric + float curTime = params[info.m_nWarpParam]->GetFloatValue(); + float timeVec[4] = { 0.0f, 0.0f, 0.0f, curTime }; + Assert( params[info.m_nEntityOrigin]->IsDefined() ); + params[info.m_nEntityOrigin]->GetVecValue( timeVec, 3 ); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, timeVec, 1 ); + + curTime = pShaderAPI->CurrentTime(); + timeVec[0] = curTime; + timeVec[1] = curTime; + timeVec[2] = curTime; + timeVec[3] = curTime; + pShaderAPI->SetPixelShaderConstant( 22, timeVec, 1 ); + + // flashlightfixme: put this in common code. + if( hasFlashlight ) + { + VMatrix worldToTexture; + const FlashlightState_t &flashlightState = pShaderAPI->GetFlashlightState( worldToTexture ); + + // Set the flashlight attenuation factors + float atten[4]; + atten[0] = flashlightState.m_fConstantAtten; + atten[1] = flashlightState.m_fLinearAtten; + atten[2] = flashlightState.m_fQuadraticAtten; + atten[3] = flashlightState.m_FarZAtten; + pShaderAPI->SetPixelShaderConstant( 22, atten, 1 ); + + // Set the flashlight origin + float pos[4]; + pos[0] = flashlightState.m_vecLightOrigin[0]; + pos[1] = flashlightState.m_vecLightOrigin[1]; + pos[2] = flashlightState.m_vecLightOrigin[2]; + pos[3] = flashlightState.m_FarZ; // didn't have this in main. . probably need this? + pShaderAPI->SetPixelShaderConstant( 23, pos, 1 ); + + pShaderAPI->SetPixelShaderConstant( 24, worldToTexture.Base(), 4 ); + } + } + pShader->Draw(); +} + + +BEGIN_VS_SHADER( VortWarp_DX9, + "Help for VortWarp_DX9" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( ALBEDO, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "albedo (Base texture with no baked lighting)" ) + SHADER_PARAM( SELFILLUMTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Self-illumination tint" ) + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/detail", "detail texture" ) + SHADER_PARAM( DETAILFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $detail" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "4", "scale of the detail texture" ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "envmap frame number" ) + SHADER_PARAM( ENVMAPMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_envmask", "envmap mask" ) + SHADER_PARAM( ENVMAPMASKFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( ENVMAPMASKTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$envmapmask texcoord transform" ) + SHADER_PARAM( ENVMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "envmap tint" ) + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "bump map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( ENVMAPCONTRAST, SHADER_PARAM_TYPE_FLOAT, "0.0", "contrast 0 == normal 1 == color*color" ) + SHADER_PARAM( ENVMAPSATURATION, SHADER_PARAM_TYPE_FLOAT, "1.0", "saturation 0 == greyscale 1 == normal" ) + SHADER_PARAM( SELFILLUM_ENVMAPMASK_ALPHA, SHADER_PARAM_TYPE_FLOAT,"0.0","defines that self illum value comes from env map mask alpha" ) + + // Debugging term for visualizing ambient data on its own + SHADER_PARAM( AMBIENTONLY, SHADER_PARAM_TYPE_INTEGER, "0", "Control drawing of non-ambient light ()" ) + + + // hack hack hack + + + SHADER_PARAM( ENTITYORIGIN, SHADER_PARAM_TYPE_VEC3,"0.0","center if the model in world space" ) + SHADER_PARAM( WARPPARAM, SHADER_PARAM_TYPE_FLOAT,"0.0","animation param between 0 and 1" ) + + SHADER_PARAM( FLOWMAP, SHADER_PARAM_TYPE_TEXTURE, "", "flow map" ) + SHADER_PARAM( SELFILLUMMAP, SHADER_PARAM_TYPE_TEXTURE, "", "self-illumination map" ) + SHADER_PARAM( UNLIT, SHADER_PARAM_TYPE_BOOL, "", "" ) + + SHADER_PARAM( PHONGEXPONENT, SHADER_PARAM_TYPE_FLOAT, "5.0", "Phong exponent for local specular lights" ) + SHADER_PARAM( PHONGTINT, SHADER_PARAM_TYPE_VEC3, "5.0", "Phong tint for local specular lights" ) + SHADER_PARAM( PHONGALBEDOTINT, SHADER_PARAM_TYPE_BOOL, "1.0", "Apply tint by albedo (controlled by spec exponent texture" ) + SHADER_PARAM( LIGHTWARPTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "1D ramp texture for tinting scalar diffuse term" ) + SHADER_PARAM( PHONGWARPTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "warp specular term" ) + SHADER_PARAM( PHONGFRESNELRANGES, SHADER_PARAM_TYPE_VEC3, "[0 0.5 1]", "Parameters for remapping fresnel output" ) + SHADER_PARAM( PHONGBOOST, SHADER_PARAM_TYPE_FLOAT, "1.0", "Phong overbrightening factor (specular mask channel should be authored to account for this)" ) + SHADER_PARAM( PHONGEXPONENTTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "Phong Exponent map" ) + SHADER_PARAM( PHONG, SHADER_PARAM_TYPE_BOOL, "0", "enables phong lighting" ) + END_SHADER_PARAMS + + void SetupVars( VortWarp_DX9_Vars_t& info ) + { + info.m_nBaseTexture = BASETEXTURE; + info.m_nBaseTextureFrame = FRAME; + info.m_nBaseTextureTransform = BASETEXTURETRANSFORM; + info.m_nAlbedo = ALBEDO; + info.m_nSelfIllumTint = SELFILLUMTINT; + info.m_nDetail = DETAIL; + info.m_nDetailFrame = DETAILFRAME; + info.m_nDetailScale = DETAILSCALE; + info.m_nEnvmap = ENVMAP; + info.m_nEnvmapFrame = ENVMAPFRAME; + info.m_nEnvmapMask = ENVMAPMASK; + info.m_nEnvmapMaskFrame = ENVMAPMASKFRAME; + info.m_nEnvmapMaskTransform = ENVMAPMASKTRANSFORM; + info.m_nEnvmapTint = ENVMAPTINT; + info.m_nBumpmap = BUMPMAP; + info.m_nBumpFrame = BUMPFRAME; + info.m_nBumpTransform = BUMPTRANSFORM; + info.m_nEnvmapContrast = ENVMAPCONTRAST; + info.m_nEnvmapSaturation = ENVMAPSATURATION; + info.m_nAlphaTestReference = -1; + info.m_nFlashlightTexture = FLASHLIGHTTEXTURE; + info.m_nFlashlightTextureFrame = FLASHLIGHTTEXTUREFRAME; + info.m_nSelfIllumEnvMapMask_Alpha = SELFILLUM_ENVMAPMASK_ALPHA; + info.m_nAmbientOnly = AMBIENTONLY; + info.m_nEntityOrigin = ENTITYORIGIN; + info.m_nWarpParam = WARPPARAM; + info.m_nFlowMap = FLOWMAP; + info.m_nSelfIllumMap = SELFILLUMMAP; + info.m_nUnlit = UNLIT; + info.m_nPhongExponent = PHONGEXPONENT; + info.m_nPhongExponentTexture = PHONGEXPONENTTEXTURE; + info.m_nDiffuseWarpTexture = LIGHTWARPTEXTURE; + info.m_nPhongWarpTexture = PHONGWARPTEXTURE; + info.m_nPhongBoost = PHONGBOOST; + info.m_nPhongFresnelRanges = PHONGFRESNELRANGES; + info.m_nPhong = PHONG; + + } + + SHADER_INIT_PARAMS() + { + VortWarp_DX9_Vars_t vars; + if( !params[BUMPMAP]->IsDefined() ) + { + params[BUMPMAP]->SetStringValue( "dev/flat_normal" ); + } + SetupVars( vars ); + if( !params[UNLIT]->IsDefined() ) + { + params[UNLIT]->SetIntValue( 0 ); + } + if( !params[SELFILLUMTINT]->IsDefined() ) + { + params[SELFILLUMTINT]->SetVecValue( 0.0f, 0.0f, 0.0f, 0.0f ); + } + InitParamsVertexLitGeneric_DX9( this, params, pMaterialName, true, vars ); + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + VortWarp_DX9_Vars_t vars; + SetupVars( vars ); + InitVertexLitGeneric_DX9( this, params, true, vars ); + if( params[FLOWMAP]->IsDefined() ) + { + LoadTexture( FLOWMAP ); + } + if( params[SELFILLUMMAP]->IsDefined() ) + { + LoadTexture( SELFILLUMMAP ); + } + } + + SHADER_DRAW + { + VortWarp_DX9_Vars_t vars; + SetupVars( vars ); + // UGH!!! FIXME!!!!! Should fix VertexlitGeneric_dx9_helper so that you + // can override the vertex shader/pixel shader used (along with the combo vars). + bool bHasFlashlight = UsingFlashlight( params ); + if ( bHasFlashlight && IsX360() ) + { + DrawVortWarp_DX9( this, params, pShaderAPI, pShaderShadow, true, false, vars, vertexCompression ); + SHADOW_STATE + { + SetInitialShadowState(); + } + } + DrawVortWarp_DX9( this, params, pShaderAPI, pShaderShadow, true, bHasFlashlight, vars, vertexCompression ); + } +END_SHADER diff --git a/materialsystem/stdshaders/vortwarp_ps2x.fxc b/materialsystem/stdshaders/vortwarp_ps2x.fxc new file mode 100644 index 00000000..e54fff80 --- /dev/null +++ b/materialsystem/stdshaders/vortwarp_ps2x.fxc @@ -0,0 +1,194 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "BASETEXTURE" "0..1" +// STATIC: "CUBEMAP" "0..1" +// STATIC: "DIFFUSELIGHTING" "0..1" +// STATIC: "NORMALMAPALPHAENVMAPMASK" "0..1" +// STATIC: "HALFLAMBERT" "0..1" +// STATIC: "FLASHLIGHT" "0..1" +// STATIC: "TRANSLUCENT" "0..1" + +// DYNAMIC: "WRITEWATERFOGTODESTALPHA" "0..1" +#include "common_fog_ps_fxc.h" +// DYNAMIC: "WARPINGIN" "0..1" +// DYNAMIC: "AMBIENT_LIGHT" "0..1" +// DYNAMIC: "NUM_LIGHTS" "0..2" [ps20] +// DYNAMIC: "NUM_LIGHTS" "0..4" [ps20b] +// DYNAMIC: "NUM_LIGHTS" "0..4" [ps30] + +// We don't use other lights when doing the flashlight, so just skip that +// SKIP: ( $FLASHLIGHT != 0 ) && ( $NUM_LIGHTS > 0 ) [PC] + +#include "common_flashlight_fxc.h" +#include "common_vertexlitgeneric_dx9.h" + +const HALF4 g_EnvmapTint : register( c0 ); +const HALF4 g_DiffuseModulation : register( c1 ); +#if !FLASHLIGHT + const HALF3 g_EnvmapContrast : register( c2 ); + const HALF3 g_EnvmapSaturation : register( c3 ); +#endif +const HALF4 g_SelfIllumTint : register( c4 ); +const float3 cAmbientCube[6] : register( c5 ); + +// 2 registers each - 6 register total +PixelShaderLightInfo cLightInfo[3] : register( c13 ); // through c18 +const HALF3 g_EyePos : register( c20 ); +const HALF4 g_FogParams : register( c21 ); + +#if FLASHLIGHT +const float4 g_FlashlightAttenuationFactors : register( c22 ); +const HALF3 g_FlashlightPos : register( c23 ); +const float4x4 g_FlashlightWorldToTexture : register( c24 ); // through c27 +#else +const float g_Time : register( c22 ); +#endif + +sampler BaseTextureSampler : register( s0 ); +sampler EnvmapSampler : register( s1 ); +sampler FlowMapSampler : register( s2 ); +sampler BumpmapSampler : register( s3 ); +sampler EnvmapMaskSampler : register( s4 ); +sampler NormalizeSampler : register( s5 ); +sampler SelfIllumMapSampler : register( s6 ); +sampler FlashlightSampler : register( s7 ); + +struct PS_INPUT +{ + HALF4 baseTexCoord2_tangentSpaceVertToEyeVectorXY : TEXCOORD0; + + // bump mapping and a separate envmap mask texture are mutually exclusive. + float4 lightAtten : TEXCOORD1; + float4 worldVertToEyeVectorXYZ_tangentSpaceVertToEyeVectorZ : TEXCOORD2; + float3x3 tangentSpaceTranspose : TEXCOORD3; + // second row : TEXCOORD4; + // third row : TEXCOORD5; + float4 worldPos_projPosZ : TEXCOORD6; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + bool bBaseTexture = BASETEXTURE ? true : false; + bool bCubemap = CUBEMAP ? true : false; + bool bDiffuseLighting = DIFFUSELIGHTING ? true : false; + bool bNormalMapAlphaEnvmapMask = NORMALMAPALPHAENVMAPMASK ? true : false; + bool bHalfLambert = HALFLAMBERT ? true : false; + bool bFlashlight = (FLASHLIGHT!=0) ? true : false; + bool bAmbientLight = AMBIENT_LIGHT ? true : false; + int nNumLights = NUM_LIGHTS; + + HALF4 baseColor = HALF4( 1.0f, 1.0f, 1.0f, 1.0f ); + if( bBaseTexture ) + baseColor = tex2D( BaseTextureSampler, i.baseTexCoord2_tangentSpaceVertToEyeVectorXY.xy ); + + float specularFactor = 1.0f; + HALF4 normalTexel = tex2D( BumpmapSampler, i.baseTexCoord2_tangentSpaceVertToEyeVectorXY.xy ); + HALF3 tangentSpaceNormal = 2.0f * normalTexel - 1.0f; + + if( bNormalMapAlphaEnvmapMask ) + specularFactor = normalTexel.a; + + HALF3 diffuseLighting = HALF3( 1.0f, 1.0f, 1.0f ); + if( bDiffuseLighting ) + { + float3 worldSpaceNormal = mul( i.tangentSpaceTranspose, tangentSpaceNormal ); + worldSpaceNormal = NormalizeWithCubemap( NormalizeSampler, worldSpaceNormal ); + diffuseLighting = PixelShaderDoLighting( i.worldPos_projPosZ.xyz, worldSpaceNormal, + float3( 0.0f, 0.0f, 0.0f ), false, bAmbientLight, i.lightAtten, + cAmbientCube, NormalizeSampler, nNumLights, cLightInfo, bHalfLambert, + false, NormalizeSampler ); + } + + HALF3 albedo = HALF3( 1.0f, 1.0f, 1.0f ); + HALF alpha = 1.0f; + if( bBaseTexture ) + { + albedo *= baseColor; + alpha *= baseColor.a; + } + + // If we only have specularity, assume that we want a black diffuse component, and + // get alpha from the envmapmask + if( !bBaseTexture && bCubemap ) + { + diffuseLighting = HALF3( 0.0f, 0.0f, 0.0f ); + if( bNormalMapAlphaEnvmapMask ) + { + alpha *= specularFactor; + } + } + +#if FLASHLIGHT + if( bFlashlight ) + { + float3 worldSpaceNormal = mul( i.tangentSpaceTranspose, tangentSpaceNormal ); + float4 flashlightSpacePosition = mul( float4( i.worldPos_projPosZ.xyz, 1.0f ), g_FlashlightWorldToTexture ); + + diffuseLighting = DoFlashlight( g_FlashlightPos, i.worldPos_projPosZ.xyz, flashlightSpacePosition, + worldSpaceNormal, g_FlashlightAttenuationFactors.xyz, + g_FlashlightAttenuationFactors.w, FlashlightSampler, + EnvmapMaskSampler, EnvmapMaskSampler, 0, false, false, float2(0, 0), true ); + } +#endif + + diffuseLighting *= g_DiffuseModulation.rgb; + alpha *= g_DiffuseModulation.a; + + HALF3 diffuseComponent = albedo * diffuseLighting; + + HALF4 flowmapSample = tex2D( FlowMapSampler, i.baseTexCoord2_tangentSpaceVertToEyeVectorXY.xy ); +#if !FLASHLIGHT + flowmapSample.xy += float2( .11, .124 ) * g_Time.xx; +#endif + HALF4 selfIllumSample = tex2D( SelfIllumMapSampler, flowmapSample.xy ); + +// float thing = ( 0.5f * ( cos( g_Time * 3 ) + 1.0f ) ); +// diffuseComponent.xyz += albedo * 10.0f * pow( selfIllumSample.xyz, thing ); + diffuseComponent.xyz += albedo * g_SelfIllumTint.xyz * selfIllumSample.xyz; + + HALF3 specularLighting = HALF3( 0.0f, 0.0f, 0.0f ); +#if !FLASHLIGHT + if( bCubemap ) + { + // If we've *only* specified a cubemap, blow off the diffuse component + if ( !bBaseTexture && !bDiffuseLighting && !bFlashlight ) + { + diffuseComponent = HALF3( 0.0f, 0.0f, 0.0f ); + } + + HALF3 worldSpaceNormal = mul( i.tangentSpaceTranspose, tangentSpaceNormal ); + + HALF3 reflectVect = CalcReflectionVectorUnnormalized( worldSpaceNormal, i.worldVertToEyeVectorXYZ_tangentSpaceVertToEyeVectorZ.xyz ); + + specularLighting = ENV_MAP_SCALE * texCUBE( EnvmapSampler, reflectVect ); + specularLighting *= specularFactor; + specularLighting *= g_EnvmapTint; + HALF3 specularLightingSquared = specularLighting * specularLighting; + specularLighting = lerp( specularLighting, specularLightingSquared, g_EnvmapContrast ); + HALF3 greyScale = dot( specularLighting, HALF3( 0.299f, 0.587f, 0.114f ) ); + specularLighting = lerp( greyScale, specularLighting, g_EnvmapSaturation ); + } +#endif + + HALF3 result = diffuseComponent + specularLighting; + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos.xyz, i.worldPos_projPosZ.xyz, i.worldPos_projPosZ.w ); +#if WRITEWATERFOGTODESTALPHA && (PIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT) + alpha = fogFactor; +#endif + + + +// result.xyz = float3( 1.0f, 1.0f, 1.0f ); +#if TRANSLUCENT==0 +# if WARPINGIN + alpha = 0.0f; // write alpha where the vortigaunt is so that we can selectivly draw pixels when refracting + #else + alpha = 1.0f; // write alpha where the vortigaunt is so that we can selectivly draw pixels when refracting +# endif +#endif + + //FIXME: need to take dowaterfog into consideration + return FinalOutput( float4( result, alpha ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR ); +} + diff --git a/materialsystem/stdshaders/vortwarp_vs20.fxc b/materialsystem/stdshaders/vortwarp_vs20.fxc new file mode 100644 index 00000000..b4b3b986 --- /dev/null +++ b/materialsystem/stdshaders/vortwarp_vs20.fxc @@ -0,0 +1,154 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "HALFLAMBERT" "0..1" + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +#include "common_fog_vs_fxc.h" +// DYNAMIC: "SKINNING" "0..1" + +// DYNAMIC: "MORPHING" "0..1" [vs30] [ = pShaderAPI->IsHWMorphingEnabled() ] + +// SKIP: $DOWATERFOG + +#include "vortwarp_vs20_helper.h" + +static const bool g_bSkinning = SKINNING ? true : false; +static const int g_FogType = DOWATERFOG; + +const float4 cBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_0 ); + +const float4 const4 : register( SHADER_SPECIFIC_CONST_4 ); +#define g_Time const4.w +#define modelOrigin const4.xyz + +#ifdef SHADER_MODEL_VS_3_0 +// NOTE: cMorphTargetTextureDim.xy = target dimensions, +// cMorphTargetTextureDim.z = 4tuples/morph +const float3 cMorphTargetTextureDim : register( SHADER_SPECIFIC_CONST_6 ); +const float4 cMorphSubrect : register( SHADER_SPECIFIC_CONST_7 ); + +sampler2D morphSampler : register( D3DVERTEXTEXTURESAMPLER0, s0 ); +#endif + + +//----------------------------------------------------------------------------- +// Input vertex format +//----------------------------------------------------------------------------- +struct VS_INPUT +{ + // This is all of the stuff that we ever use. + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vNormal : NORMAL; + float4 vColor : COLOR0; + float3 vSpecular : COLOR1; + // make these float2's and stick the [n n 0 1] in the dot math. + float4 vTexCoord0 : TEXCOORD0; + float4 vTexCoord1 : TEXCOORD1; + float4 vTexCoord2 : TEXCOORD2; + float4 vTexCoord3 : TEXCOORD3; + float3 vTangentS : TANGENT; + float3 vTangentT : BINORMAL; + float4 vUserData : TANGENT; + + // Position and normal/tangent deltas + float3 vPosFlex : POSITION1; + float3 vNormalFlex : NORMAL1; +#ifdef SHADER_MODEL_VS_3_0 + float vVertexID : POSITION2; +#endif +}; + + +//----------------------------------------------------------------------------- +// Output vertex format +//----------------------------------------------------------------------------- +struct VS_OUTPUT +{ + float4 projPos : POSITION; +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + float fog : FOG; +#endif + + HALF4 baseTexCoord2_tangentSpaceVertToEyeVectorXY : TEXCOORD0; + // bump mapping and a separate envmap mask texture are mutually exclusive. + float4 lightAtten : TEXCOORD1; + float4 worldVertToEyeVectorXYZ_tangentSpaceVertToEyeVectorZ : TEXCOORD2; + float3x3 tangentSpaceTranspose : TEXCOORD3; + // second row : TEXCOORD4; + // third row : TEXCOORD5; + float4 worldPos_projPosZ : TEXCOORD6; +}; + +//----------------------------------------------------------------------------- +// Main shader entry point +//----------------------------------------------------------------------------- +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float4 vPosition = v.vPos; + float3 vNormal; + float4 vTangent; + + DecompressVertex_NormalTangent( v.vNormal, v.vUserData, vNormal, vTangent ); + +#if !defined( SHADER_MODEL_VS_3_0 ) || !MORPHING + ApplyMorph( v.vPosFlex, v.vNormalFlex, vPosition.xyz, vNormal, vTangent.xyz ); +#else + ApplyMorph( morphSampler, cMorphTargetTextureDim, cMorphSubrect, v.vVertexID, float3( 0, 0, 0 ), + vPosition.xyz, vNormal, vTangent.xyz ); +#endif + + // Perform skinning + float3 worldNormal, worldPos, worldTangentS, worldTangentT; + SkinPositionNormalAndTangentSpace( + g_bSkinning, + vPosition, vNormal, vTangent, + v.vBoneWeights, v.vBoneIndices, + worldPos, worldNormal, worldTangentS, worldTangentT ); + + WorldSpaceVertexProcess( g_Time, modelOrigin, worldPos, worldNormal, worldTangentS, worldTangentT ); + + // Always normalize since flex path is controlled by runtime + // constant not a shader combo and will always generate the normalization + worldNormal = normalize( worldNormal ); + worldTangentS = normalize( worldTangentS ); + worldTangentT = normalize( worldTangentT ); + + // Transform into projection space + float4 projPos = mul( float4( worldPos, 1 ), cViewProj ); + o.projPos = projPos; + +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + o.fog = CalcFixedFunctionFog( worldPos, g_FogType ); +#endif + + // Needed for water fog alpha and diffuse lighting + // FIXME: we shouldn't have to compute this all the time. + o.worldPos_projPosZ = float4( worldPos, projPos.z ); + + // Needed for cubemapping + parallax mapping + // FIXME: We shouldn't have to compute this all the time. + o.worldVertToEyeVectorXYZ_tangentSpaceVertToEyeVectorZ.xyz = VSHADER_VECT_SCALE * (cEyePos - worldPos); + + // Scalar light attenuation (mouth darkening applied in pixel shader) + o.lightAtten.x = GetVertexAttenForLight( worldPos, 0 ); + o.lightAtten.y = GetVertexAttenForLight( worldPos, 1 ); + o.lightAtten.z = GetVertexAttenForLight( worldPos, 2 ); + o.lightAtten.w = GetVertexAttenForLight( worldPos, 3 ); + + // Base texture coordinate transform + o.baseTexCoord2_tangentSpaceVertToEyeVectorXY.x = dot( v.vTexCoord0, cBaseTexCoordTransform[0] ); + o.baseTexCoord2_tangentSpaceVertToEyeVectorXY.y = dot( v.vTexCoord0, cBaseTexCoordTransform[1] ); + + // Tangent space transform + o.tangentSpaceTranspose[0] = float3( worldTangentS.x, worldTangentT.x, worldNormal.x ); + o.tangentSpaceTranspose[1] = float3( worldTangentS.y, worldTangentT.y, worldNormal.y ); + o.tangentSpaceTranspose[2] = float3( worldTangentS.z, worldTangentT.z, worldNormal.z ); + + return o; +} + + diff --git a/materialsystem/stdshaders/vortwarp_vs20_helper.h b/materialsystem/stdshaders/vortwarp_vs20_helper.h new file mode 100644 index 00000000..d31997c7 --- /dev/null +++ b/materialsystem/stdshaders/vortwarp_vs20_helper.h @@ -0,0 +1,41 @@ +#include "common_vs_fxc.h" + +float Sine( float min, float max, float t ) +{ + return ( sin( t ) * 0.5f + 0.5f ) * ( max - min ) + min; +} + +float3 QuadraticBezier( float3 A, float3 B, float3 C, float t ) +{ + return lerp( lerp( A, B, t ), lerp( B, C, t ), t ); +} + +float3 CubicBezier( float3 A, float3 B, float3 C, float3 D, float t ) +{ + return QuadraticBezier( lerp( A, B, t ), lerp( B, C, t ), lerp( C, D, t ), t ); +} + +void WorldSpaceVertexProcess( in float time, in float3 modelOrigin, inout float3 worldPos, inout float3 worldNormal, inout float3 worldTangentS, inout float3 worldTangentT ) +{ + float myTime = time; + myTime = saturate( 1.0f - myTime ); + myTime *= myTime; + myTime *= myTime; + myTime *= myTime; +// worldPos.z += 72.0f * myTime; + + // end + float3 A = float3( 0.0f, 0.0f, 1.0f ); + float3 B = float3( 1.0f, 1.0f, 1.0f ); + float3 C = float3( 0.0f, 0.0f, 1.0f ); + float3 D = float3( 0.0f, 0.0f, 1.0f ); + // start + +// float3 modelOrigin = float3( 70.0f, -14.0f, 0.0f ); + + float t = worldPos.z * ( 1.0f / ( 72.0f ) ); // about 72 inches tall + t = saturate( t ); + float3 worldPosDelta = ( worldPos - modelOrigin ) * CubicBezier( A, B, C, D, t ); + worldPosDelta.z += Sine( 0.0f, 10.0, worldPos.z ); + worldPos = lerp( worldPos, worldPosDelta + modelOrigin, myTime ); +} diff --git a/materialsystem/stdshaders/water.cpp b/materialsystem/stdshaders/water.cpp new file mode 100644 index 00000000..4bde2068 --- /dev/null +++ b/materialsystem/stdshaders/water.cpp @@ -0,0 +1,800 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "basevsshader.h" +#include "mathlib/vmatrix.h" +#include "common_hlsl_cpp_consts.h" // hack hack hack! +#include "convar.h" + +#include "watercheap_vs20.inc" +#include "watercheap_ps20.inc" +#include "watercheap_ps20b.inc" +#include "water_vs20.inc" +#include "water_ps20.inc" +#include "water_ps20b.inc" +#include "shaderlib/commandbuilder.h" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +DEFINE_FALLBACK_SHADER( Water, Water_DX9_HDR ) + +BEGIN_VS_SHADER( Water_DX90, + "Help for Water" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( REFRACTTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "_rt_WaterRefraction", "" ) + SHADER_PARAM( REFLECTTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "_rt_WaterReflection", "" ) + SHADER_PARAM( REFRACTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "0", "" ) + SHADER_PARAM( REFRACTTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "refraction tint" ) + SHADER_PARAM( REFLECTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "0.8", "" ) + SHADER_PARAM( REFLECTTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "reflection tint" ) + SHADER_PARAM( NORMALMAP, SHADER_PARAM_TYPE_TEXTURE, "dev/water_normal", "normal map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( TIME, SHADER_PARAM_TYPE_FLOAT, "", "" ) + SHADER_PARAM( WATERDEPTH, SHADER_PARAM_TYPE_FLOAT, "", "" ) + SHADER_PARAM( CHEAPWATERSTARTDISTANCE, SHADER_PARAM_TYPE_FLOAT, "", "This is the distance from the eye in inches that the shader should start transitioning to a cheaper water shader." ) + SHADER_PARAM( CHEAPWATERENDDISTANCE, SHADER_PARAM_TYPE_FLOAT, "", "This is the distance from the eye in inches that the shader should finish transitioning to a cheaper water shader." ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "env_cubemap", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( FOGCOLOR, SHADER_PARAM_TYPE_COLOR, "", "" ) + SHADER_PARAM( FORCECHEAP, SHADER_PARAM_TYPE_BOOL, "", "" ) + SHADER_PARAM( REFLECTENTITIES, SHADER_PARAM_TYPE_BOOL, "", "" ) + SHADER_PARAM( FOGSTART, SHADER_PARAM_TYPE_FLOAT, "", "" ) + SHADER_PARAM( FOGEND, SHADER_PARAM_TYPE_FLOAT, "", "" ) + SHADER_PARAM( ABOVEWATER, SHADER_PARAM_TYPE_BOOL, "", "" ) + SHADER_PARAM( REFLECTBLENDFACTOR, SHADER_PARAM_TYPE_FLOAT, "1.0", "" ) + SHADER_PARAM( NOFRESNEL, SHADER_PARAM_TYPE_BOOL, "0", "" ) + SHADER_PARAM( NOLOWENDLIGHTMAP, SHADER_PARAM_TYPE_BOOL, "0", "" ) + SHADER_PARAM( SCROLL1, SHADER_PARAM_TYPE_COLOR, "", "" ) + SHADER_PARAM( SCROLL2, SHADER_PARAM_TYPE_COLOR, "", "" ) + SHADER_PARAM( FLOWMAP, SHADER_PARAM_TYPE_TEXTURE, "", "flowmap" ) + SHADER_PARAM( FLOWMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $flowmap" ) + SHADER_PARAM( FLOWMAPSCROLLRATE, SHADER_PARAM_TYPE_VEC2, "[0 0", "2D rate to scroll $flowmap" ) + SHADER_PARAM( FLOW_NOISE_TEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "flow noise texture" ) + + SHADER_PARAM( FLASHLIGHTTINT, SHADER_PARAM_TYPE_FLOAT, "0", "" ) + SHADER_PARAM( LIGHTMAPWATERFOG, SHADER_PARAM_TYPE_BOOL, "0", "" ) + SHADER_PARAM( FORCEFRESNEL, SHADER_PARAM_TYPE_FLOAT, "0", "" ) + + // New flow params + SHADER_PARAM( FLOW_WORLDUVSCALE, SHADER_PARAM_TYPE_FLOAT, "", "" ) + SHADER_PARAM( FLOW_NORMALUVSCALE, SHADER_PARAM_TYPE_FLOAT, "", "" ) + SHADER_PARAM( FLOW_TIMEINTERVALINSECONDS, SHADER_PARAM_TYPE_FLOAT, "", "" ) + SHADER_PARAM( FLOW_UVSCROLLDISTANCE, SHADER_PARAM_TYPE_FLOAT, "", "" ) + SHADER_PARAM( FLOW_BUMPSTRENGTH, SHADER_PARAM_TYPE_FLOAT, "", "" ) + SHADER_PARAM( FLOW_TIMESCALE, SHADER_PARAM_TYPE_FLOAT, "", "" ) + SHADER_PARAM( FLOW_NOISE_SCALE, SHADER_PARAM_TYPE_FLOAT, "", "" ) + SHADER_PARAM( FLOW_DEBUG, SHADER_PARAM_TYPE_BOOL, "0", "" ) + + SHADER_PARAM( COLOR_FLOW_UVSCALE, SHADER_PARAM_TYPE_FLOAT, "", "" ) + SHADER_PARAM( COLOR_FLOW_TIMESCALE, SHADER_PARAM_TYPE_FLOAT, "", "" ) + SHADER_PARAM( COLOR_FLOW_TIMEINTERVALINSECONDS, SHADER_PARAM_TYPE_FLOAT, "", "" ) + SHADER_PARAM( COLOR_FLOW_UVSCROLLDISTANCE, SHADER_PARAM_TYPE_FLOAT, "", "" ) + SHADER_PARAM( COLOR_FLOW_LERPEXP, SHADER_PARAM_TYPE_FLOAT, "", "" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + if( !params[ABOVEWATER]->IsDefined() ) + { + Warning( "***need to set $abovewater for material %s\n", pMaterialName ); + params[ABOVEWATER]->SetIntValue( 1 ); + } + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + if( !params[CHEAPWATERSTARTDISTANCE]->IsDefined() ) + { + params[CHEAPWATERSTARTDISTANCE]->SetFloatValue( 500.0f ); + } + if( !params[CHEAPWATERENDDISTANCE]->IsDefined() ) + { + params[CHEAPWATERENDDISTANCE]->SetFloatValue( 1000.0f ); + } + if( !params[SCROLL1]->IsDefined() ) + { + params[SCROLL1]->SetVecValue( 0.0f, 0.0f, 0.0f ); + } + if( !params[SCROLL2]->IsDefined() ) + { + params[SCROLL2]->SetVecValue( 0.0f, 0.0f, 0.0f ); + } + if( !params[FOGCOLOR]->IsDefined() ) + { + params[FOGCOLOR]->SetVecValue( 1.0f, 0.0f, 0.0f ); + Warning( "material %s needs to have a $fogcolor.\n", pMaterialName ); + } + if( !params[REFLECTENTITIES]->IsDefined() ) + { + params[REFLECTENTITIES]->SetIntValue( 0 ); + } + if( !params[REFLECTBLENDFACTOR]->IsDefined() ) + { + params[REFLECTBLENDFACTOR]->SetFloatValue( 1.0f ); + } + + InitFloatParam( FLOW_WORLDUVSCALE, params, 1.0f ); + InitFloatParam( FLOW_NORMALUVSCALE, params, 1.0f ); + InitFloatParam( FLOW_TIMEINTERVALINSECONDS, params, 0.4f ); + InitFloatParam( FLOW_UVSCROLLDISTANCE, params, 0.2f ); + InitFloatParam( FLOW_BUMPSTRENGTH, params, 1.0f ); + InitFloatParam( FLOW_TIMESCALE, params, 1.0f ); + InitFloatParam( FLOW_NOISE_SCALE, params, 0.0002f ); + + InitFloatParam( COLOR_FLOW_UVSCALE, params, 1.0f ); + InitFloatParam( COLOR_FLOW_TIMESCALE, params, 1.0f ); + InitFloatParam( COLOR_FLOW_TIMEINTERVALINSECONDS, params, 0.4f ); + InitFloatParam( COLOR_FLOW_UVSCROLLDISTANCE, params, 0.2f ); + InitFloatParam( COLOR_FLOW_LERPEXP, params, 1.0f ); + + InitIntParam( FORCECHEAP, params, 0 ); + InitFloatParam( FLASHLIGHTTINT, params, 1.0f ); + InitIntParam( LIGHTMAPWATERFOG, params, 0 ); + InitFloatParam( FORCEFRESNEL, params, -1.0f ); + + // Fallbacks for water need lightmaps usually + if ( params[BASETEXTURE]->IsDefined() || ( params[LIGHTMAPWATERFOG]->GetIntValue() != 0 ) ) + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + } + + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + // Don't need bumped lightmaps unless we have a basetexture. We only use them otherwise for lighting the water fog, which only needs one sample. + if( params[BASETEXTURE]->IsDefined() && g_pConfig->UseBumpmapping() && params[NORMALMAP]->IsDefined() ) + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_BUMPED_LIGHTMAP ); + } + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + Assert( params[WATERDEPTH]->IsDefined() ); + + if( params[REFRACTTEXTURE]->IsDefined() ) + { + LoadTexture( REFRACTTEXTURE ); + } + if( params[REFLECTTEXTURE]->IsDefined() ) + { + LoadTexture( REFLECTTEXTURE ); + } + if ( params[ENVMAP]->IsDefined() ) + { + LoadCubeMap( ENVMAP ); + } + if ( params[NORMALMAP]->IsDefined() ) + { + LoadBumpMap( NORMALMAP ); + } + if( params[BASETEXTURE]->IsDefined() ) + { + LoadTexture( BASETEXTURE ); + } + if ( params[FLOWMAP]->IsDefined() ) + { + LoadTexture( FLOWMAP ); + } + if ( params[FLOW_NOISE_TEXTURE]->IsDefined() ) + { + LoadTexture( FLOW_NOISE_TEXTURE ); + } + } + + inline void GetVecParam( int constantVar, float *val ) + { + if( constantVar == -1 ) + return; + + IMaterialVar* pVar = s_ppParams[constantVar]; + Assert( pVar ); + + if (pVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + pVar->GetVecValue( val, 4 ); + else + val[0] = val[1] = val[2] = val[3] = pVar->GetFloatValue(); + } + + inline void DrawReflectionRefraction( IMaterialVar **params, IShaderShadow* pShaderShadow, + IShaderDynamicAPI* pShaderAPI, bool bReflection, bool bRefraction ) + { + Vector4D Scroll1; + params[SCROLL1]->GetVecValue( Scroll1.Base(), 4 ); + + bool bHasFlowmap = params[FLOWMAP]->IsTexture(); + bool hasFlashlight = UsingFlashlight( params ); + bool bHasBaseTexture = params[BASETEXTURE]->IsTexture(); + bool bHasMultiTexture = fabs( Scroll1.x ) > 0.0f; + bool bLightmapWaterFog = ( params[LIGHTMAPWATERFOG]->GetIntValue() != 0 ); + + bool bForceFresnel = ( params[FORCEFRESNEL]->GetFloatValue() != -1.0f ); + + if ( bHasFlowmap ) + { + bHasMultiTexture = false; + } + + if ( bHasBaseTexture || bHasMultiTexture ) + { + //hasFlashlight = false; + //bLightmapWaterFog = false; + } + + // LIGHTMAP - needed either with basetexture or lightmapwaterfog. Not sure where the bReflection restriction comes in. + bool bUsingLightmap = bLightmapWaterFog || ( bReflection && bHasBaseTexture ); + + SHADOW_STATE + { + SetInitialShadowState( ); + if ( bRefraction ) + { + // refract sampler + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, !IsX360() ); + } + + if ( bReflection ) + { + // reflect sampler + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, !IsX360() ); + } + + if ( bHasBaseTexture ) + { + // BASETEXTURE + pShaderShadow->EnableTexture( SHADER_SAMPLER10, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER10, true ); + } + + // normal map + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + + if ( bUsingLightmap ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER3, false ); + } + + // flowmap + if ( bHasFlowmap ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER4, false ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER5, false ); + } + + if( hasFlashlight ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER7, true ); + pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER7 ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER8, true ); + } + + int fmt = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_TANGENT_S | VERTEX_TANGENT_T; + + // texcoord0 : base texcoord + // texcoord1 : lightmap texcoord + // texcoord2 : lightmap texcoord offset + int numTexCoords = 1; + // You need lightmap data if you are using lightmapwaterfog or you have a basetexture. + if ( bLightmapWaterFog || bHasBaseTexture ) + { + numTexCoords = 3; + } + pShaderShadow->VertexShaderVertexFormat( fmt, numTexCoords, 0, 0 ); + + DECLARE_STATIC_VERTEX_SHADER( water_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( MULTITEXTURE, bHasMultiTexture ); + SET_STATIC_VERTEX_SHADER_COMBO( BASETEXTURE, bHasBaseTexture ); + SET_STATIC_VERTEX_SHADER_COMBO( FLASHLIGHT, hasFlashlight ); + SET_STATIC_VERTEX_SHADER_COMBO( LIGHTMAPWATERFOG, bLightmapWaterFog ); + SET_STATIC_VERTEX_SHADER_COMBO( FLOWMAP, bHasFlowmap ); + SET_STATIC_VERTEX_SHADER( water_vs20 ); + + // "REFLECT" "0..1" + // "REFRACT" "0..1" + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( water_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( REFLECT, bReflection ); + SET_STATIC_PIXEL_SHADER_COMBO( REFRACT, bRefraction ); + SET_STATIC_PIXEL_SHADER_COMBO( ABOVEWATER, params[ABOVEWATER]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER_COMBO( MULTITEXTURE, bHasMultiTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE, bHasBaseTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( FLOWMAP, bHasFlowmap ); + SET_STATIC_PIXEL_SHADER_COMBO( FLOW_DEBUG, clamp( params[ FLOW_DEBUG ]->GetIntValue(), 0, 2 ) ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, hasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( LIGHTMAPWATERFOG, bLightmapWaterFog ); + SET_STATIC_PIXEL_SHADER_COMBO( FORCEFRESNEL, bForceFresnel ); + SET_STATIC_PIXEL_SHADER( water_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( water_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( REFLECT, bReflection ); + SET_STATIC_PIXEL_SHADER_COMBO( REFRACT, bRefraction ); + SET_STATIC_PIXEL_SHADER_COMBO( ABOVEWATER, params[ABOVEWATER]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER_COMBO( MULTITEXTURE, bHasMultiTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE, bHasBaseTexture ); +// SET_STATIC_PIXEL_SHADER_COMBO( FLOWMAP, bHasFlowmap ); + SET_STATIC_PIXEL_SHADER_COMBO( FLOW_DEBUG, clamp( params[ FLOW_DEBUG ]->GetIntValue(), 0, 2 ) ); + SET_STATIC_PIXEL_SHADER_COMBO( FORCEFRESNEL, bForceFresnel ); + SET_STATIC_PIXEL_SHADER( water_ps20 ); + } + + FogToFogColor(); + + // we are writing linear values from this shader. + pShaderShadow->EnableSRGBWrite( true ); + + pShaderShadow->EnableAlphaWrites( true ); + } + DYNAMIC_STATE + { + pShaderAPI->SetDefaultState(); + if( bRefraction ) + { + // HDRFIXME: add comment about binding.. Specify the number of MRTs in the enable + BindTexture( SHADER_SAMPLER0, REFRACTTEXTURE, -1 ); + } + if( bReflection ) + { + BindTexture( SHADER_SAMPLER1, REFLECTTEXTURE, -1 ); + } + BindTexture( SHADER_SAMPLER2, NORMALMAP, BUMPFRAME ); + + if ( bUsingLightmap ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER3, TEXTURE_LIGHTMAP ); + } + + if( bHasBaseTexture ) + { + BindTexture( SHADER_SAMPLER10, BASETEXTURE, FRAME ); + } + + if ( bHasFlowmap ) + { + BindTexture( SHADER_SAMPLER4, FLOWMAP, FLOWMAPFRAME ); + BindTexture( SHADER_SAMPLER5, FLOW_NOISE_TEXTURE ); + + float vFlowConst1[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vFlowConst1[0] = 1.0f / params[ FLOW_WORLDUVSCALE ]->GetFloatValue(); + vFlowConst1[1] = 1.0f / params[ FLOW_NORMALUVSCALE ]->GetFloatValue(); + vFlowConst1[2] = params[ FLOW_BUMPSTRENGTH ]->GetFloatValue(); + vFlowConst1[3] = params[ FLOW_TIMESCALE ]->GetFloatValue(); + pShaderAPI->SetPixelShaderConstant( 13, vFlowConst1, 1 ); + + float vFlowConst2[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vFlowConst2[0] = params[ FLOW_TIMEINTERVALINSECONDS ]->GetFloatValue(); + vFlowConst2[1] = params[ FLOW_UVSCROLLDISTANCE ]->GetFloatValue(); + vFlowConst2[2] = params[ FLOW_NOISE_SCALE ]->GetFloatValue(); + vFlowConst2[3] = params[ COLOR_FLOW_LERPEXP ]->GetFloatValue(); + pShaderAPI->SetPixelShaderConstant( 14, vFlowConst2, 1 ); + + float vColorFlowConst1[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vColorFlowConst1[0] = 1.0f / params[ COLOR_FLOW_UVSCALE ]->GetFloatValue(); + vColorFlowConst1[1] = params[ COLOR_FLOW_TIMESCALE ]->GetFloatValue(); + vColorFlowConst1[2] = params[ COLOR_FLOW_TIMEINTERVALINSECONDS ]->GetFloatValue(); + vColorFlowConst1[3] = params[ COLOR_FLOW_UVSCROLLDISTANCE ]->GetFloatValue(); + pShaderAPI->SetPixelShaderConstant( 26, vColorFlowConst1, 1 ); + } + + // Time + float vTimeConst[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + float flTime = pShaderAPI->CurrentTime(); + vTimeConst[0] = flTime; + //vTimeConst[0] -= ( float )( ( int )( vTimeConst[0] / 1000.0f ) ) * 1000.0f; + pShaderAPI->SetPixelShaderConstant( 8, vTimeConst, 1 ); + + // These constants are used to rotate the world space water normals around the up axis to align the + // normal with the camera and then give us a 2D offset vector to use for reflection and refraction uv's + VMatrix mView; + pShaderAPI->GetMatrix( MATERIAL_VIEW, mView.m[0] ); + mView = mView.Transpose3x3(); + + Vector4D vCameraRight( mView.m[0][0], mView.m[0][1], mView.m[0][2], 0.0f ); + vCameraRight.z = 0.0f; // Project onto the plane of water + vCameraRight.AsVector3D().NormalizeInPlace(); + + Vector4D vCameraForward; + CrossProduct( Vector( 0.0f, 0.0f, 1.0f ), vCameraRight.AsVector3D(), vCameraForward.AsVector3D() ); // I assume the water surface normal is pointing along z! + + pShaderAPI->SetPixelShaderConstant( 22, vCameraRight.Base() ); + pShaderAPI->SetPixelShaderConstant( 23, vCameraForward.Base() ); + + SetPixelShaderConstant( 25, FORCEFRESNEL ); + + // Refraction tint + if( bRefraction ) + { + SetPixelShaderConstantGammaToLinear( 1, REFRACTTINT ); + } + // Reflection tint + if( bReflection ) + { + if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_INTEGER ) + { + // Need to multiply by 4 in linear space since we premultiplied into + // the render target by .25 to get overbright data in the reflection render target. + float gammaReflectTint[3]; + params[REFLECTTINT]->GetVecValue( gammaReflectTint, 3 ); + float linearReflectTint[4]; + linearReflectTint[0] = GammaToLinear( gammaReflectTint[0] ) * 4.0f; + linearReflectTint[1] = GammaToLinear( gammaReflectTint[1] ) * 4.0f; + linearReflectTint[2] = GammaToLinear( gammaReflectTint[2] ) * 4.0f; + linearReflectTint[3] = 1.0f; + pShaderAPI->SetPixelShaderConstant( 4, linearReflectTint, 1 ); + } + else + { + SetPixelShaderConstantGammaToLinear( 4, REFLECTTINT ); + } + } + + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, BUMPTRANSFORM ); + + float curtime=pShaderAPI->CurrentTime(); + float vc0[4]; + float v0[4]; + params[SCROLL1]->GetVecValue(v0,4); + vc0[0]=curtime*v0[0]; + vc0[1]=curtime*v0[1]; + params[SCROLL2]->GetVecValue(v0,4); + vc0[2]=curtime*v0[0]; + vc0[3]=curtime*v0[1]; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, vc0, 1 ); + + float c0[4] = { 1.0f / 3.0f, 1.0f / 3.0f, 1.0f / 3.0f, 0.0f }; + pShaderAPI->SetPixelShaderConstant( 0, c0, 1 ); + + float c2[4] = { 0.5f, 0.5f, 0.5f, 0.5f }; + pShaderAPI->SetPixelShaderConstant( 2, c2, 1 ); + + // fresnel constants + float c3[4] = { 1.0f, 0.0f, 0.0f, 0.0f }; + pShaderAPI->SetPixelShaderConstant( 3, c3, 1 ); + + float c5[4] = { params[REFLECTAMOUNT]->GetFloatValue(), params[REFLECTAMOUNT]->GetFloatValue(), + params[REFRACTAMOUNT]->GetFloatValue(), params[REFRACTAMOUNT]->GetFloatValue() }; + pShaderAPI->SetPixelShaderConstant( 5, c5, 1 ); + +#if 0 + SetPixelShaderConstantGammaToLinear( 6, FOGCOLOR ); +#else + // Need to use the srgb curve since that we do in UpdatePixelFogColorConstant so that we match the older version of water where we render to an offscreen buffer and fog on the way in. + float fogColorConstant[4]; + + params[FOGCOLOR]->GetVecValue( fogColorConstant, 3 ); + fogColorConstant[3] = 0.0f; + + fogColorConstant[0] = SrgbGammaToLinear( fogColorConstant[0] ); + fogColorConstant[1] = SrgbGammaToLinear( fogColorConstant[1] ); + fogColorConstant[2] = SrgbGammaToLinear( fogColorConstant[2] ); + pShaderAPI->SetPixelShaderConstant( 6, fogColorConstant, 1 ); +#endif + + float c7[4] = + { + params[FOGSTART]->GetFloatValue(), + params[FOGEND]->GetFloatValue() - params[FOGSTART]->GetFloatValue(), + 1.0f, + 0.0f + }; + if (g_pHardwareConfig->GetHDRType() == HDR_TYPE_INTEGER ) + { + // water overbright factor + c7[2] = 4.0; + } + pShaderAPI->SetPixelShaderConstant( 7, c7, 1 ); + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + float vEyePos_SpecExponent[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + vEyePos_SpecExponent[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + + if( bHasFlowmap ) + { + SetPixelShaderConstant( 9, FLOWMAPSCROLLRATE ); + } + + DECLARE_DYNAMIC_VERTEX_SHADER( water_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( water_vs20 ); + + CCommandBufferBuilder< CFixedCommandStorageBuffer< 1000 > > DynamicCmdsOut; + + bool bFlashlightShadows = false; + bool bUberlight = false; + if( hasFlashlight ) + { + pShaderAPI->GetFlashlightShaderInfo( &bFlashlightShadows, &bUberlight ); + + DynamicCmdsOut.SetVertexShaderFlashlightState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4 ); + + CBCmdSetPixelShaderFlashlightState_t state; + state.m_LightSampler = SHADER_SAMPLER6; // FIXME . . don't want this here. + state.m_DepthSampler = SHADER_SAMPLER7; + state.m_ShadowNoiseSampler = SHADER_SAMPLER8; + state.m_nColorConstant = PSREG_FLASHLIGHT_COLOR; + state.m_nAttenConstant = 15; + state.m_nOriginConstant = 16; + state.m_nDepthTweakConstant = 21; + state.m_nScreenScaleConstant = PSREG_FLASHLIGHT_SCREEN_SCALE; + state.m_nWorldToTextureConstant = -1; + state.m_bFlashlightNoLambert = false; + state.m_bSinglePassFlashlight = true; + DynamicCmdsOut.SetPixelShaderFlashlightState( state ); + + DynamicCmdsOut.SetPixelShaderConstant( 10, FLASHLIGHTTINT ); + } + + // Get viewport and render target dimensions and set shader constant to do a 2D mad + int nViewportX, nViewportY, nViewportWidth, nViewportHeight; + pShaderAPI->GetCurrentViewport( nViewportX, nViewportY, nViewportWidth, nViewportHeight ); + + int nRtWidth, nRtHeight; + pShaderAPI->GetCurrentRenderTargetDimensions( nRtWidth, nRtHeight ); + + float vViewportMad[4]; + + // viewport->screen transform + vViewportMad[0] = ( float )nViewportWidth / ( float )nRtWidth; + vViewportMad[1] = ( float )nViewportHeight / ( float )nRtHeight; + vViewportMad[2] = ( float )nViewportX / ( float )nRtWidth; + vViewportMad[3] = ( float )nViewportY / ( float )nRtHeight; + DynamicCmdsOut.SetPixelShaderConstant( 24, vViewportMad, 1 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( water_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER( water_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( water_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( water_ps20 ); + } + + DynamicCmdsOut.End(); + pShaderAPI->ExecuteCommandBuffer( DynamicCmdsOut.Base() ); + } + Draw(); + } + + inline void DrawCheapWater( IMaterialVar **params, IShaderShadow* pShaderShadow, + IShaderDynamicAPI* pShaderAPI, bool bBlend, bool bRefraction ) + { + bool bHasFlowmap = params[FLOWMAP]->IsTexture(); + SHADOW_STATE + { + SetInitialShadowState( ); + + // In edit mode, use nocull + if ( UsingEditor( params ) ) + { + s_pShaderShadow->EnableCulling( false ); + } + + if( bBlend ) + { + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + // envmap + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + // normal map + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + if( bRefraction && bBlend ) + { + // refraction map (used for alpha) + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + } + + // Noise texture + if ( bHasFlowmap ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + } + + // Normalizing cube map + pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); + int fmt = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_TANGENT_S | VERTEX_TANGENT_T; + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 ); + + DECLARE_STATIC_VERTEX_SHADER( watercheap_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( BLEND, bBlend && bRefraction ); + SET_STATIC_VERTEX_SHADER( watercheap_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( watercheap_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( FRESNEL, params[NOFRESNEL]->GetIntValue() == 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( BLEND, bBlend ); + SET_STATIC_PIXEL_SHADER_COMBO( REFRACTALPHA, bRefraction ); + SET_STATIC_PIXEL_SHADER_COMBO( HDRTYPE, g_pHardwareConfig->GetHDRType() ); + Vector4D Scroll1; + params[SCROLL1]->GetVecValue( Scroll1.Base(), 4 ); + SET_STATIC_PIXEL_SHADER_COMBO( MULTITEXTURE,fabs(Scroll1.x) > 0.0); + SET_STATIC_PIXEL_SHADER_COMBO( FLOWMAP, bHasFlowmap ); + SET_STATIC_PIXEL_SHADER_COMBO( FLOW_DEBUG, clamp( params[ FLOW_DEBUG ]->GetIntValue(), 0, 2 ) ); + SET_STATIC_PIXEL_SHADER( watercheap_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( watercheap_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( FRESNEL, params[NOFRESNEL]->GetIntValue() == 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( BLEND, bBlend ); + SET_STATIC_PIXEL_SHADER_COMBO( REFRACTALPHA, bRefraction ); + SET_STATIC_PIXEL_SHADER_COMBO( HDRTYPE, g_pHardwareConfig->GetHDRType() ); + Vector4D Scroll1; + params[SCROLL1]->GetVecValue( Scroll1.Base(), 4 ); + SET_STATIC_PIXEL_SHADER_COMBO( MULTITEXTURE,fabs(Scroll1.x) > 0.0); + SET_STATIC_PIXEL_SHADER_COMBO( FLOWMAP, bHasFlowmap ); + SET_STATIC_PIXEL_SHADER_COMBO( FLOW_DEBUG, clamp( params[ FLOW_DEBUG ]->GetIntValue(), 0, 2 ) ); + SET_STATIC_PIXEL_SHADER( watercheap_ps20 ); + } + + // HDRFIXME: test cheap water! + if( g_pHardwareConfig->GetHDRType() != HDR_TYPE_NONE ) + { + // we are writing linear values from this shader. + pShaderShadow->EnableSRGBWrite( true ); + } + + FogToFogColor(); + } + DYNAMIC_STATE + { + pShaderAPI->SetDefaultState(); + + BindTexture( SHADER_SAMPLER0, ENVMAP, ENVMAPFRAME ); + BindTexture( SHADER_SAMPLER1, NORMALMAP, BUMPFRAME ); + if( bRefraction && bBlend ) + { + BindTexture( SHADER_SAMPLER2, REFRACTTEXTURE, -1 ); + } + + if ( bHasFlowmap ) + { + BindTexture( SHADER_SAMPLER3, FLOWMAP ); + BindTexture( SHADER_SAMPLER4, FLOW_NOISE_TEXTURE ); + + float vFlowConst1[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vFlowConst1[0] = 1.0f / params[ FLOW_WORLDUVSCALE ]->GetFloatValue(); + vFlowConst1[1] = 1.0f / params[ FLOW_NORMALUVSCALE ]->GetFloatValue(); + vFlowConst1[2] = params[ FLOW_BUMPSTRENGTH ]->GetFloatValue(); + vFlowConst1[3] = params[ FLOW_TIMESCALE ]->GetFloatValue(); + pShaderAPI->SetPixelShaderConstant( 13, vFlowConst1, 1 ); + + float vFlowConst2[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vFlowConst2[0] = params[ FLOW_TIMEINTERVALINSECONDS ]->GetFloatValue(); + vFlowConst2[1] = params[ FLOW_UVSCROLLDISTANCE ]->GetFloatValue(); + vFlowConst2[2] = params[ FLOW_NOISE_SCALE ]->GetFloatValue(); + pShaderAPI->SetPixelShaderConstant( 14, vFlowConst2, 1 ); + + // Time % 1000 + float vTimeConst[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + float flTime = pShaderAPI->CurrentTime(); + vTimeConst[0] = flTime; + //vTimeConst[0] -= ( float )( ( int )( vTimeConst[0] / 1000.0f ) ) * 1000.0f; + pShaderAPI->SetPixelShaderConstant( 10, vTimeConst, 1 ); + } + + pShaderAPI->BindStandardTexture( SHADER_SAMPLER6, TEXTURE_NORMALIZATION_CUBEMAP_SIGNED ); + + SetPixelShaderConstant( 0, FOGCOLOR ); + + float cheapWaterStartDistance = params[CHEAPWATERSTARTDISTANCE]->GetFloatValue(); + float cheapWaterEndDistance = params[CHEAPWATERENDDISTANCE]->GetFloatValue(); + float cheapWaterParams[4] = + { + cheapWaterStartDistance * VSHADER_VECT_SCALE, + cheapWaterEndDistance * VSHADER_VECT_SCALE, + PSHADER_VECT_SCALE / ( cheapWaterEndDistance - cheapWaterStartDistance ), + cheapWaterStartDistance / ( cheapWaterEndDistance - cheapWaterStartDistance ), + }; + pShaderAPI->SetPixelShaderConstant( 1, cheapWaterParams ); + + if( g_pConfig->bShowSpecular ) + { + SetPixelShaderConstant( 2, REFLECTTINT, REFLECTBLENDFACTOR ); + } + else + { + float zero[4] = { 0.0f, 0.0f, 0.0f, params[REFLECTBLENDFACTOR]->GetFloatValue() }; + pShaderAPI->SetPixelShaderConstant( 2, zero ); + } + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + float vEyePos_SpecExponent[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + vEyePos_SpecExponent[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + + if( params[SCROLL1]->IsDefined()) + { + float curtime=pShaderAPI->CurrentTime(); + float vc0[4]; + float v0[4]; + params[SCROLL1]->GetVecValue(v0,4); + vc0[0]=curtime*v0[0]; + vc0[1]=curtime*v0[1]; + params[SCROLL2]->GetVecValue(v0,4); + vc0[2]=curtime*v0[0]; + vc0[3]=curtime*v0[1]; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, vc0, 1 ); + } + + DECLARE_DYNAMIC_VERTEX_SHADER( watercheap_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( watercheap_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( watercheap_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( HDRENABLED, IsHDREnabled() ); + SET_DYNAMIC_PIXEL_SHADER( watercheap_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( watercheap_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( HDRENABLED, IsHDREnabled() ); + SET_DYNAMIC_PIXEL_SHADER( watercheap_ps20 ); + } + } + Draw(); + } + + SHADER_DRAW + { + bool bRefraction = params[REFRACTTEXTURE]->IsTexture(); + bool bReflection = params[REFLECTTEXTURE]->IsTexture(); + bool bForceCheap = ( params[FORCECHEAP]->GetIntValue() != 0 ); + + if ( ( bReflection || bRefraction ) && !UsingEditor( params ) && !bForceCheap ) + { + DrawReflectionRefraction( params, pShaderShadow, pShaderAPI, bReflection, bRefraction ); + } + else + { + bool bBlend = false; + DrawCheapWater( params, pShaderShadow, pShaderAPI, bBlend, bRefraction ); + } + } +END_SHADER + +//----------------------------------------------------------------------------- +// This allows us to use a block labelled 'Water_DX9_HDR' in the water materials +//----------------------------------------------------------------------------- +BEGIN_INHERITED_SHADER( Water_DX9_HDR, Water_DX90, + "Help for Water_DX9_HDR" ) + + SHADER_FALLBACK + { + if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ) + { + return "WATER_DX90"; + } + return 0; + } +END_INHERITED_SHADER + diff --git a/materialsystem/stdshaders/water_dudv.cpp b/materialsystem/stdshaders/water_dudv.cpp new file mode 100644 index 00000000..56e12f8e --- /dev/null +++ b/materialsystem/stdshaders/water_dudv.cpp @@ -0,0 +1,95 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + + +#include "BaseVSShader.h" + +#include "waterdudv_vs11.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_VS_SHADER( Water_DuDv, "Help for Water_DuDv" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "", "dudv bump map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( REFRACTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "0", "" ) + SHADER_PARAM( REFRACTTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "refraction tint" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + if ( params[BUMPMAP]->IsDefined() ) + { + LoadTexture( BUMPMAP ); + } + if( !params[REFRACTTINT]->IsDefined() ) + { + params[REFRACTTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + } + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableAlphaWrites( true ); + pShaderShadow->EnableColorWrites( true ); + pShaderShadow->EnableTexture( SHADER_TEXTURE_STAGE0, true ); + int fmt = VERTEX_POSITION | VERTEX_NORMAL; + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0, 0 ); + + pShaderShadow->SetVertexShader( "WaterDuDv_vs11", 0 ); + pShaderShadow->SetPixelShader( "WaterDuDv_ps11", 0 ); + DisableFog(); + } + DYNAMIC_STATE + { + waterdudv_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + vshIndex.SetDOFOG( pShaderAPI->GetSceneFogMode() != MATERIAL_FOG_NONE ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, BUMPTRANSFORM ); + + Vector4D vec; + const float *pTint = params[REFRACTTINT]->GetVecValue(); + float flAverage = ( pTint[0] + pTint[1] + pTint[2] ) / 3.0f; + vec.Init( flAverage, flAverage, flAverage, 1.0f ); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, vec.Base() ); + + // Amount to refract + SetPixelShaderConstant( 0, REFRACTAMOUNT ); + + // Used to renormalize + vec.Init( 1.0f, 1.0f, 1.0f, 1.0f ); + pShaderAPI->SetPixelShaderConstant( 1, vec.Base() ); + + // Used to deal with the red channel + vec.Init( 0.0f, 1.0f, 1.0f, 1.0f ); + pShaderAPI->SetPixelShaderConstant( 2, vec.Base() ); + + vec.Init( 1.0f, 0.0f, 0.0f, 0.0f ); + pShaderAPI->SetPixelShaderConstant( 3, vec.Base() ); + + BindTexture( SHADER_TEXTURE_STAGE0, BUMPMAP, BUMPFRAME ); + } + Draw(); + } +END_SHADER + diff --git a/materialsystem/stdshaders/water_ps2x.fxc b/materialsystem/stdshaders/water_ps2x.fxc new file mode 100644 index 00000000..19dc8dfd --- /dev/null +++ b/materialsystem/stdshaders/water_ps2x.fxc @@ -0,0 +1,607 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +// STATIC: "BASETEXTURE" "0..1" +// STATIC: "MULTITEXTURE" "0..1" +// STATIC: "REFLECT" "0..1" +// STATIC: "REFRACT" "0..1" +// STATIC: "ABOVEWATER" "0..1" +// STATIC: "FLOWMAP" "0..1" [ps20b] +// STATIC: "FLOWMAP" "0..0" [ps20] [ = 0; ] +// STATIC: "FLOW_DEBUG" "0..2" +// STATIC: "FLASHLIGHT" "0..1" [ps20b] +// STATIC: "FLASHLIGHT" "0..0" [ps20] [ = 0; ] +// STATIC: "LIGHTMAPWATERFOG" "0..1" [ps20b] +// STATIC: "LIGHTMAPWATERFOG" "0..0" [ps20] [ = 0; ] +// STATIC: "FORCEFRESNEL" "0..1" +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps20b] +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..0" [ps20] [ = 0; ] + +// Multitexture and basetexture are mutually exclusive. +// SKIP: $MULTITEXTURE && $BASETEXTURE + +// flowmap doesn't play with multitexture +// SKIP: $FLOWMAP && $MULTITEXTURE + +// Have to have the flashlight on to get flashlightshadows. +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 ) + +// basetexture doesn't work with flashlight or lightmapwaterfog. multitexture doesn't either. We don't use basetexture or multitexture in newer code and instead use flowmap and flashlight. +// SKIP: ( $FLASHLIGHT || $LIGHTMAPWATERFOG ) && ( ( $BASETEXTURE && !$FLOWMAP ) || $MULTITEXTURE ) + +#ifdef _X360 + #define SHADER_SRGB_READ 1 +#endif + +#include "common_ps_fxc.h" +#include "common_fog_ps_fxc.h" + +#include "shader_constant_register_map.h" +#include "common_flashlight_fxc.h" + +#if REFRACT + sampler RefractSampler : register( s0 ); +#endif +sampler ReflectSampler : register( s1 ); +sampler NormalSampler : register( s2 ); +sampler LightmapSampler : register( s3 ); + +#if BASETEXTURE + sampler BaseTextureSampler : register( s10 ); +#endif + +#if FLOWMAP + sampler FlowmapSampler : register( s4 ); + sampler FlowNoiseSampler : register( s5 ); +#endif + +#if FLASHLIGHT + sampler FlashlightSampler : register( s6 ); + sampler ShadowDepthSampler : register( s7 ); + sampler RandRotSampler : register( s8 ); +#endif + +const float4 g_vRefractTint : register( c1 ); +const float4 g_vReflectTint : register( c4 ); +const float4 g_ReflectRefractScale : register( c5 ); // xy - reflect scale, zw - refract scale +const float4 g_WaterFogColor : register( c6 ); + +const float4 g_WaterFogParams : register( c7 ); +#define g_WaterFogStart g_WaterFogParams.x +#define g_WaterFogEndMinusStart g_WaterFogParams.y +#define g_Reflect_OverBright g_WaterFogParams.z + +const float g_flTime : register( c8 ); + +#if FLOWMAP + const float2 g_vFlowScrollRate : register( c9 ); +#endif + +// The flashlight on the water surface is basically the diffuse flashlight * waterfogcolor * g_flFlashlightTint. +// g_flFlashlightTint is tweakable in cases where the water fog color is really dark and the flashlight doesn't show up, etc. +const float3 g_flFlashlightTint : register( c10 ); + +const float4 g_PixelFogParams : register( PSREG_FOG_PARAMS ); // c12 +const float3 g_EyePos : register( PSREG_EYEPOS_SPEC_EXPONENT ); // c11 + +const float4 g_vFlowParams1 : register( c13 ); +#define g_flWorldUvScale ( g_vFlowParams1.x ) // 1.0f / 10.0f +#define g_flNormalUvScale ( g_vFlowParams1.y ) // 1.0f / 1.15f +#define g_flBumpStrength ( g_vFlowParams1.z ) // 3.0f +#define g_flTimeScale ( g_vFlowParams1.w ) // 1.0f + +const float4 g_vFlowParams2 : register( c14 ); +#define g_flFlowTimeIntervalInSeconds ( g_vFlowParams2.x ) // 0.4f // Number of seconds to lerp from texture 1 to texture 2 +#define g_flFlowUvScrollDistance ( g_vFlowParams2.y ) // 0.25f // Distance in uv space to fetch +#define g_flNoiseScale ( g_vFlowParams2.z ) +#define g_flColorFlowLerpExp ( g_vFlowParams2.w ) + +const float4 g_vColorFlowParams1 : register( c26 ); +#define g_flColorFlowUvScale ( g_vColorFlowParams1.x ) // 1.0f / 1.15f +#define g_flColorFlowTimeScale ( g_vColorFlowParams1.y ) // 1.0f +#define g_flColorFlowTimeIntervalInSeconds ( g_vColorFlowParams1.z ) // 0.4f // Number of seconds to lerp from texture 1 to texture 2 +#define g_flColorFlowUvScrollDistance ( g_vColorFlowParams1.w ) // 0.25f // Distance in uv space to fetch + +const float4 g_FlashlightAttenuationFactors : register( c15 ); +const float3 g_FlashlightPos : register( c16 ); +const float4x4 g_FlashlightWorldToTexture : register( c17 ); // through c20 +const float4 g_vShadowTweaks : register( c21 ); + +// These constants are used to rotate the world space water normals around the up axis to align the +// normal with the camera and then give us a 2D offset vector to use for reflection and refraction uv's +const float3 g_vWorldToViewWater0 : register( c22 ); +const float3 g_vWorldToViewWater1 : register( c23 ); + +float4 g_vInvViewportTransform : register( c24 ); +const float g_flForcedFresnelValue : register( c25 ); + +struct PS_INPUT +{ + float2 vBumpTexCoord : TEXCOORD0; + float3 vPositionToCameraRayWs : TEXCOORD1; + float4 vReflectXY_vRefractYX : TEXCOORD2; + float4 vProjPos : TEXCOORD3; + float3 worldPos : TEXCOORD4; +#if FLASHLIGHT + float4 flashlightSpacePos : TEXCOORD5; +#endif +#if MULTITEXTURE + float4 vExtraBumpTexCoord : TEXCOORD5; +#endif + +#if ( BASETEXTURE && !FLOWMAP ) +// CENTROID: TEXCOORD5 + #if defined( _X360 ) + float4 lightmapTexCoord1And2 : TEXCOORD5_centroid; + #else + float4 lightmapTexCoord1And2 : TEXCOORD5; + #endif + +// CENTROID: TEXCOORD6 + #if defined( _X360 ) + float2 lightmapTexCoord3 : TEXCOORD6_centroid; + #else + float2 lightmapTexCoord3 : TEXCOORD6; + #endif +#endif + +#if LIGHTMAPWATERFOG +// CENTROID: TEXCOORD7 + #if defined( _X360 ) + float2 lightmapTexCoord : TEXCOORD7_centroid; + #else + float2 lightmapTexCoord : TEXCOORD7; + #endif +#endif +}; + +float2 UnpackNormal2D( float2 vNormal ) +{ + return ( ( vNormal.xy * 2.0 ) - 1.0 ); +} + +float3 UnpackNormal3D( float3 vNormal ) +{ + return ( ( vNormal.xyz * 2.0 ) - 1.0 ); +} + +float3 ComputeNormalFromXY( float2 vXY ) +{ + float3 vNormalTs; + + vNormalTs.xy = vXY.xy; + vNormalTs.z = sqrt( saturate( 1.0 - dot( vNormalTs.xy, vNormalTs.xy ) ) ); + + return vNormalTs.xyz; +} + +float3 ComputeNormalFromRGTexture( float2 vRGPixel ) +{ + float3 vNormalTs; + + vNormalTs.xy = UnpackNormal2D( vRGPixel.rg ); + vNormalTs.z = sqrt( saturate( 1.0 - dot( vNormalTs.xy, vNormalTs.xy ) ) ); + + return vNormalTs.xyz; +} + +#define USE_32BIT_LIGHTMAPS_ON_360 //uncomment to use 32bit lightmaps, be sure to keep this in sync with the same #define in materialsystem/cmatlightmaps.cpp + +float3 LightMapSample( sampler LightmapSampler, float2 vTexCoord ) +{ + #if ( !defined( _X360 ) || !defined( USE_32BIT_LIGHTMAPS_ON_360 ) ) + { + float3 sample = tex2D( LightmapSampler, vTexCoord ); + + return sample; + } + #else + { + #if 0 //1 for cheap sampling, 0 for accurate scaling from the individual samples + { + float4 sample = tex2D( LightmapSampler, vTexCoord ); + + return sample.rgb * sample.a; + } + #else + { + float4 Weights; + float4 samples_0; //no arrays allowed in inline assembly + float4 samples_1; + float4 samples_2; + float4 samples_3; + + asm { + tfetch2D samples_0, vTexCoord.xy, LightmapSampler, OffsetX = -0.5, OffsetY = -0.5, MinFilter=point, MagFilter=point, MipFilter=keep, UseComputedLOD=false + tfetch2D samples_1, vTexCoord.xy, LightmapSampler, OffsetX = 0.5, OffsetY = -0.5, MinFilter=point, MagFilter=point, MipFilter=keep, UseComputedLOD=false + tfetch2D samples_2, vTexCoord.xy, LightmapSampler, OffsetX = -0.5, OffsetY = 0.5, MinFilter=point, MagFilter=point, MipFilter=keep, UseComputedLOD=false + tfetch2D samples_3, vTexCoord.xy, LightmapSampler, OffsetX = 0.5, OffsetY = 0.5, MinFilter=point, MagFilter=point, MipFilter=keep, UseComputedLOD=false + + getWeights2D Weights, vTexCoord.xy, LightmapSampler + }; + + Weights = float4( (1-Weights.x)*(1-Weights.y), Weights.x*(1-Weights.y), (1-Weights.x)*Weights.y, Weights.x*Weights.y ); + + float3 result; + result.rgb = samples_0.rgb * (samples_0.a * Weights.x); + result.rgb += samples_1.rgb * (samples_1.a * Weights.y); + result.rgb += samples_2.rgb * (samples_2.a * Weights.z); + result.rgb += samples_3.rgb * (samples_3.a * Weights.w); + + return result; + } + #endif + } + #endif +} + +float4 main( PS_INPUT i ) : COLOR +{ + float4 vResult; + float flFogFactor; + + /* For debugging - Flash all water surfaces blue + vResult.rgba = float4( 0.25, 0.25, 1.0, 0 ) * ( ( floor( g_flTime * 2.0f ) % 2 ) * 0.9f + 0.1f ); + flFogFactor = 0; + return FinalOutput( float4( vResult.rgb, 1.0f ), flFogFactor, PIXELFOGTYPE, TONEMAP_SCALE_NONE ); + //*/ + + float4 vNormalWs; + float4 vFlowColor = float4( 0.0f, 0.0f, 0.0f, 0.0f ); + #if ( FLOWMAP ) + { + float flWorldUvScale = g_flWorldUvScale; + float flNormalUvScale = g_flNormalUvScale; + float flFlowTimeIntervalInSeconds = g_flFlowTimeIntervalInSeconds; + float flFlowUvScrollDistance = g_flFlowUvScrollDistance; + float flBumpStrength = g_flBumpStrength; + float flTimeScale = g_flTimeScale; + float flNoiseScale = g_flNoiseScale; + + // Input uv + float2 vWorldUv = i.vBumpTexCoord.xy * flWorldUvScale; + float2 vUv1 = float2( i.worldPos.x, -i.worldPos.y ) * flNormalUvScale; + float2 vUv2 = vUv1.xy; + + // Noise texture is used to offset the time interval different spatially so we don't see pulsing + float flNoise = tex2D( FlowNoiseSampler, float2( i.worldPos.x, -i.worldPos.y ) * flNoiseScale ).g; + + // Flow texel has a 2D flow vector in the rg channels of the texture + float4 vFlowTexel = tex2D( FlowmapSampler, vWorldUv.xy ); + #if ( FLOW_DEBUG == 1 ) // Flow vectors + { + vResult.rgba = float4( pow( vFlowTexel.rgb, 2.2f ), 0 ); + flFogFactor = 0; + return FinalOutput( float4( vResult.rgb, 1.0f ), flFogFactor, PIXELFOGTYPE, TONEMAP_SCALE_NONE ); + } + #elif ( FLOW_DEBUG == 2 ) // Noise + { + vResult.rgba = pow( flNoise, 2.2 ); + flFogFactor = 0; + return FinalOutput( float4( vResult.rgb, 1.0f ), flFogFactor, PIXELFOGTYPE, TONEMAP_SCALE_NONE ); + } + #endif + + // Unpack world flow vector from texture + float2 vFlowVectorTs = ( vFlowTexel.rg * 2.0f ) - 1.0f; + + float flTimeInIntervals = ( ( g_flTime * flTimeScale ) + flNoise ) / ( flFlowTimeIntervalInSeconds * 2.0f ); + float flScrollTime1 = frac( flTimeInIntervals ); + float flScrollTime2 = frac( flTimeInIntervals + 0.5f ); // Half an interval off from texture 1 + + // Every interval has a unique offset so we don't see the same bump texels repeating continuously + float flOffset1 = floor( flTimeInIntervals ) * 0.311f; + float flOffset2 = floor( flTimeInIntervals + 0.5f ) * 0.311f + 0.5f; // The +0.5 is to match the phase offset + + // Final flow uv is originalUv + interval offset + ( flowvector * scroll + float2 vFlowUv1 = vUv1.xy + flOffset1 + ( flScrollTime1 * ( flFlowUvScrollDistance * vFlowVectorTs.xy ) ); + float2 vFlowUv2 = vUv2.xy + flOffset2 + ( flScrollTime2 * ( flFlowUvScrollDistance * vFlowVectorTs.xy ) ); + + // Lerp values to blend between the two layers of bump + float flWeight1 = abs( ( 2.0f * frac( flTimeInIntervals + 0.5f ) ) - 1.0f ); + float flWeight2 = abs( ( 2.0f * frac( flTimeInIntervals ) ) - 1.0f ); + + float4 vNormalTexel1 = tex2D( NormalSampler, vFlowUv1.xy ); + float4 vNormalTexel2 = tex2D( NormalSampler, vFlowUv2.xy ); + + float3 vNormal1 = ( vNormalTexel1.rgb ); + float3 vNormal2 = ( vNormalTexel2.rgb ); + + // Combine both layers + vNormalWs.xy = UnpackNormal2D( lerp( vNormal1.xy, vNormal2.xy, flWeight2 ) ); + + // Change bump strength based on the length of the flow vector + //vNormalWs.xy *= ( length( vFlowVectorTs.xy ) + 0.05f ) * flBumpStrength; + vNormalWs.xy *= ( ( vFlowVectorTs.x * vFlowVectorTs.x + vFlowVectorTs.y * vFlowVectorTs.y ) + 0.1f ) * flBumpStrength; + + // Generate normal from 2D scaled normal + vNormalWs.xyz = ComputeNormalFromXY( vNormalWs.xy ); + //return pow( float4( vNormalWs.xy*0.5+0.5, 0, 0), 2.2); + + //vResult.rgba = float4( SrgbGammaToLinear( vNormalWs.xyz * 0.5 + 0.5 ), 0 ); + //flFogFactor = 0; + //return FinalOutput( float4( vResult.rgb, 1.0f ), flFogFactor, PIXELFOGTYPE, TONEMAP_SCALE_NONE ); + + vNormalWs.a = 1.0f; + + //-------------------------------------------------------------// + // Specifying a base texture with flow gives us a sludge layer // + //-------------------------------------------------------------// + #if ( BASETEXTURE ) + { + float2 vColorUv = float2( i.worldPos.x, -i.worldPos.y ) * g_flColorFlowUvScale; + + float flTimeInIntervals = ( ( g_flTime * g_flColorFlowTimeScale ) + flNoise ) / ( g_flColorFlowTimeIntervalInSeconds * 2.0f ); + float flScrollTime1 = frac( flTimeInIntervals ) - 0.5; + float flScrollTime2 = frac( flTimeInIntervals + 0.5f ) - 0.5; // Half an interval off from texture 1 + + float flOffset1 = floor( flTimeInIntervals ) * 0.311f; + float flOffset2 = floor( flTimeInIntervals + 0.5f ) * 0.311f + 0.5f; // The +0.5 is to match the phase offset + + float2 vColorFlowUv1 = vColorUv.xy + flOffset1 + ( flScrollTime1 * ( g_flColorFlowUvScrollDistance * vFlowVectorTs.xy ) ); + float2 vColorFlowUv2 = vColorUv.xy + flOffset2 + ( flScrollTime2 * ( g_flColorFlowUvScrollDistance * vFlowVectorTs.xy ) ); + + float flWeight1 = pow( abs( ( 2.0f * frac( flTimeInIntervals + 0.5f ) ) - 1.0f ), g_flColorFlowLerpExp ); + float flWeight2 = pow( abs( ( 2.0f * frac( flTimeInIntervals ) ) - 1.0f ), g_flColorFlowLerpExp ); + + float4 vColorTexel1 = tex2D( BaseTextureSampler, vColorFlowUv1.xy * .235 ); + float4 vColorTexel2 = tex2D( BaseTextureSampler, vColorFlowUv2.xy * .235 ); + vFlowColor.rgba = vColorTexel1.rgba * flWeight1; + vFlowColor.rgba += vColorTexel2.rgba * flWeight2; + } + #endif + } + #elif ( MULTITEXTURE ) + { + vNormalWs.xyz = tex2D( NormalSampler, i.vBumpTexCoord ); + float3 vNormalWs1 = tex2D( NormalSampler, i.vExtraBumpTexCoord.xy ); + float3 vNormalWs2 = tex2D( NormalSampler, i.vExtraBumpTexCoord.zw ); + vNormalWs.xyz = 0.33 * ( vNormalWs.xyz + vNormalWs1.xyz + vNormalWs2.xyz ); + + vNormalWs.xyz = 2.0 * vNormalWs.xyz - 1.0; + + vNormalWs.a = 1.0f; + } + #else + { + vNormalWs.xyzw = DecompressNormal( NormalSampler, i.vBumpTexCoord, NORM_DECODE_NONE ); + } + #endif + + // Perform division by W only once + float flOoW = 1.0f / i.vProjPos.w; + float2 unwarpedRefractTexCoord = i.vReflectXY_vRefractYX.wz * flOoW; + // Deal with the viewport transform. We don't do splitscreen on PC, so don't bother doing this with PS20. + unwarpedRefractTexCoord = g_vInvViewportTransform.zw + unwarpedRefractTexCoord * g_vInvViewportTransform.xy; + + #if ( ABOVEWATER && REFRACT ) + float4 unwarpedSample = tex2Dsrgb( RefractSampler, unwarpedRefractTexCoord ); + float waterFogDepthValue = unwarpedSample.a; + #else + // We don't actually have valid depth values in alpha when we are underwater looking out, so + // just set to farthest value. + float waterFogDepthValue = 1.0f; + #endif + + float4 vReflectRefractScale = g_ReflectRefractScale; + #if !BASETEXTURE + vReflectRefractScale *= waterFogDepthValue; + #endif + + // Compute coordinates for sampling Reflection + float3 vPositionToCameraDirWs = normalize( i.vPositionToCameraRayWs.xyz ); + + // vectorize the dependent UV calculations (reflect = .xy, refract = .wz) + float4 vN; + vN.x = dot( g_vWorldToViewWater0.xyz, vNormalWs.xyz ); + vN.y = dot( g_vWorldToViewWater1.xyz, vNormalWs.xyz ); + vN.wz = vN.xy; + + float4 vDependentTexCoords = vN.xyzw * vNormalWs.a * vReflectRefractScale; + vDependentTexCoords += i.vReflectXY_vRefractYX * flOoW; + + float2 vReflectTexCoord = vDependentTexCoords.xy; + float2 vRefractTexCoord = vDependentTexCoords.wz; + + float4 vReflectColor = tex2Dsrgb( ReflectSampler, vReflectTexCoord ); + vReflectColor *= g_vReflectTint; + + float4 vRefractColor; + #if REFRACT + #if defined( _X360 ) + { + // deal with the viewport transform for splitscreen + vRefractColor = tex2Dsrgb( RefractSampler, g_vInvViewportTransform.zw + vRefractTexCoord * g_vInvViewportTransform.xy ); + } + #else + { + vRefractColor = tex2Dsrgb( RefractSampler, vRefractTexCoord ); + } + #endif + float warpedAlpha = vRefractColor.a; + // get the depth value from the refracted sample to be used for fog. + #if ABOVEWATER + // Don't mess with this in the underwater case since we don't really have + // depth values there. + waterFogDepthValue = vRefractColor.a; + #endif + #endif + + // Fresnel term + float fFresnel; + #if FORCEFRESNEL + { + fFresnel = g_flForcedFresnelValue; + } + #else + { + float flNdotV = saturate( dot( vPositionToCameraDirWs.xyz, vNormalWs.xyz ) ); + + float g_flReflectance = 0.2f; + fFresnel = g_flReflectance + ( ( 1.0f - g_flReflectance ) * pow( 1.0f - flNdotV, 5.0f ) ); + } + #endif + + float4 vLightmappedWaterFogColor = g_WaterFogColor; + + #if LIGHTMAPWATERFOG + float3 lightmapSample = LightMapSample( LightmapSampler, i.lightmapTexCoord.xy ); + float3 vLightmapColor = lightmapSample * LIGHT_MAP_SCALE * LINEAR_LIGHT_SCALE; + vLightmappedWaterFogColor.xyz *= vLightmapColor.rgb; + #endif + + // blend between refraction and fog color. + #if ABOVEWATER + #if REFRACT + // Avoid seeing things in front of the water warped in the water refraction by not warping when that case happens. + // Causes a bit of artifacting around foreground objects, but looks better than warping the foreground objects in the water surface. + if ( warpedAlpha < 0.05f ) + { + vRefractColor.xyz = unwarpedSample.xyz; + waterFogDepthValue = unwarpedSample.w; + } + #endif + #if REFRACT + float edgeFadeFactor = saturate( 3.5 * waterFogDepthValue ); + vRefractColor = lerp( vRefractColor, vRefractColor * g_vRefractTint, edgeFadeFactor ); + #endif + + #if ( REFLECT && !defined( SHADER_MODEL_PS_2_0 ) ) + { + vReflectColor *= saturate( 2.0 * waterFogDepthValue ); + } + #endif + + #if REFRACT + vRefractColor = lerp( vRefractColor, vLightmappedWaterFogColor, waterFogDepthValue ); + #endif + #endif + + #if !BASETEXTURE + { + // fFresnel == 1.0f means full reflection + #if ( REFRACT ) + { + fFresnel *= saturate( ( waterFogDepthValue - 0.05f ) * 20.0f ); + } + #endif + } + #endif + + #if ( BASETEXTURE && !FLOWMAP ) + float4 baseSample = tex2D( BaseTextureSampler, i.vBumpTexCoord.xy ); + + float2 bumpCoord1; + float2 bumpCoord2; + float2 bumpCoord3; + ComputeBumpedLightmapCoordinates( i.lightmapTexCoord1And2, i.lightmapTexCoord3.xy, + bumpCoord1, bumpCoord2, bumpCoord3 ); + + float4 lightmapSample1 = tex2D( LightmapSampler, bumpCoord1 ); + float3 lightmapColor1 = lightmapSample1.rgb; + float3 lightmapColor2 = tex2D( LightmapSampler, bumpCoord2 ); + float3 lightmapColor3 = tex2D( LightmapSampler, bumpCoord3 ); + + float3 dp; + dp.x = saturate( dot( vNormalWs, bumpBasis[0] ) ); + dp.y = saturate( dot( vNormalWs, bumpBasis[1] ) ); + dp.z = saturate( dot( vNormalWs, bumpBasis[2] ) ); + dp *= dp; + + float3 diffuseLighting = dp.x * lightmapColor1 + + dp.y * lightmapColor2 + + dp.z * lightmapColor3; + float sum = dot( dp, float3( 1.0f, 1.0f, 1.0f ) ); + diffuseLighting *= LIGHT_MAP_SCALE / sum; + float3 diffuseComponent = baseSample.rgb * diffuseLighting; + #endif + + #if ( REFLECT && REFRACT ) + { + #if ( BASETEXTURE && FLOWMAP ) + { + float3 vLight = float3( 1.0f, 1.0f, 1.0f ); + #if ( LIGHTMAPWATERFOG ) + { + vLight.rgb = vLightmapColor.rgb; + } + #endif + + // The alpha of flow color represents translucency from 0.0-0.5. The range 0.5-1.0 allows pixels to float above the water + float3 vSludge = vFlowColor.rgb * vLight.rgb; + float3 vUnderWater = lerp( vRefractColor.rgb, vSludge.rgb, saturate( vFlowColor.a * 2.0f ) ); + float flSludgeAboveWater = smoothstep( 0.5f, 0.7f, vFlowColor.a ); + vResult.rgb = lerp( vUnderWater.rgb, vReflectColor.rgb, saturate( fFresnel * ( 1.0f - flSludgeAboveWater ) ) ); + } + #else + { + vResult = vRefractColor + ( fFresnel * vReflectColor ); + } + #endif + } + #elif ( REFLECT ) + { + #if ( BASETEXTURE && FLOWMAP ) + { + float3 vLight = float3( 1.0f, 1.0f, 1.0f ); + #if ( LIGHTMAPWATERFOG ) + { + vLight.rgb = vLightmapColor.rgb; + } + #endif + + // The alpha of flow color represents translucency from 0.0-0.5. The range 0.5-1.0 allows pixels to float above the water + float3 vSludge = vFlowColor.rgb * vLight.rgb; + float3 vUnderWater = lerp( vLightmappedWaterFogColor.rgb, vSludge.rgb, saturate( vFlowColor.a * 2.0f ) ); + float flSludgeAboveWater = smoothstep( 0.5f, 0.7f, vFlowColor.a ); + vResult.rgb = lerp( vUnderWater.rgb, vReflectColor.rgb, saturate( fFresnel * ( 1.0f - flSludgeAboveWater ) ) ); + + } + #elif ( BASETEXTURE ) + { + vResult = float4( diffuseComponent, 1.0f ) + vReflectColor * fFresnel * baseSample.a; + } + #else + { + vResult = lerp( vLightmappedWaterFogColor, vReflectColor, fFresnel ); + } + #endif + } + #elif ( REFRACT ) + { + vResult = vRefractColor; + } + #else + { + vResult = float4( 0.0f, 0.0f, 0.0f, 0.0f ); + } + #endif + + #if ( FLASHLIGHT ) + { + float3 vFlashlightDiffuseLighting = DoFlashlight( g_FlashlightPos, i.worldPos.xyz, i.flashlightSpacePos.xyzw, vNormalWs, + g_FlashlightAttenuationFactors.xyz, g_FlashlightAttenuationFactors.w, FlashlightSampler, ShadowDepthSampler, + RandRotSampler, 0, FLASHLIGHTSHADOWS, false, + i.vProjPos.xy / i.vProjPos.w, false, g_vShadowTweaks ); + + #if ABOVEWATER && REFRACT + { + vFlashlightDiffuseLighting *= edgeFadeFactor; + } + #endif + + vResult.xyz += g_flFlashlightTint * g_WaterFogColor.rgb * vFlashlightDiffuseLighting.xyz * LINEAR_LIGHT_SCALE; + } + #endif + + #if ( PIXELFOGTYPE == PIXEL_FOG_TYPE_RANGE ) + { + flFogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_PixelFogParams, g_EyePos, i.worldPos, i.vProjPos.z ); + } + #else + { + flFogFactor = 0; + } + #endif + + return FinalOutput( float4( vResult.rgb, 1.0f ), flFogFactor, PIXELFOGTYPE, TONEMAP_SCALE_NONE, true, i.vProjPos.w ); +} diff --git a/materialsystem/stdshaders/white_ps2x.fxc b/materialsystem/stdshaders/white_ps2x.fxc new file mode 100644 index 00000000..c75d9eea --- /dev/null +++ b/materialsystem/stdshaders/white_ps2x.fxc @@ -0,0 +1,12 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#include "common_ps_fxc.h" + +struct PS_INPUT +{ +}; + +HALF4 main( PS_INPUT i ) : COLOR +{ + return FinalOutput( float4( 1.0f, 1.0f, 1.0f, 1.0f ), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} diff --git a/materialsystem/stdshaders/windowimposter_dx90.cpp b/materialsystem/stdshaders/windowimposter_dx90.cpp new file mode 100644 index 00000000..4654f8c5 --- /dev/null +++ b/materialsystem/stdshaders/windowimposter_dx90.cpp @@ -0,0 +1,103 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "BaseVSShader.h" +#include "cpp_shader_constant_register_map.h" + +#include "windowimposter_vs20.inc" +#include "windowimposter_ps20.inc" +#include "windowimposter_ps20b.inc" + + + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( WindowImposter, WindowImposter_DX90 ) + +BEGIN_VS_SHADER( WindowImposter_DX90, + "Help for WindowImposter_DX90" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + END_SHADER_PARAMS + + // Set up anything that is necessary to make decisions in SHADER_FALLBACK. + SHADER_INIT_PARAMS() + { + } + + SHADER_FALLBACK + { + return NULL; + } + + SHADER_INIT + { + LoadCubeMap( ENVMAP ); + } + + SHADER_DRAW + { + SHADOW_STATE + { + if( g_pHardwareConfig->GetHDRType() != HDR_TYPE_NONE ) + pShaderShadow->EnableSRGBWrite( true ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + DECLARE_STATIC_VERTEX_SHADER( windowimposter_vs20 ); + SET_STATIC_VERTEX_SHADER( windowimposter_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( windowimposter_ps20b ); + SET_STATIC_PIXEL_SHADER( windowimposter_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( windowimposter_ps20 ); + SET_STATIC_PIXEL_SHADER( windowimposter_ps20 ); + } + + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 1, 0, 0 ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + pShaderShadow->EnableDepthWrites( false ); + FogToFogColor(); + PI_BeginCommandBuffer(); + PI_SetModulationVertexShaderDynamicState(); + PI_EndCommandBuffer(); + } + DYNAMIC_STATE + { + DECLARE_DYNAMIC_VERTEX_SHADER( windowimposter_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( windowimposter_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( windowimposter_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( windowimposter_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( windowimposter_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( windowimposter_ps20 ); + } + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + float vEyePos_SpecExponent[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + vEyePos_SpecExponent[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + + BindTexture( SHADER_SAMPLER0, ENVMAP, -1 ); + } + Draw(); + } + +END_SHADER diff --git a/materialsystem/stdshaders/windowimposter_ps2x.fxc b/materialsystem/stdshaders/windowimposter_ps2x.fxc new file mode 100644 index 00000000..ff953514 --- /dev/null +++ b/materialsystem/stdshaders/windowimposter_ps2x.fxc @@ -0,0 +1,30 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// + +#include "common_fog_ps_fxc.h" + +#include "common_ps_fxc.h" +#include "shader_constant_register_map.h" + +sampler EnvmapSampler : register( s0 ); + +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT ); + +struct PS_INPUT +{ + float3 eyeToVertVector : TEXCOORD0; + float4 vertexColor : COLOR; + + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog +}; + +float4 main( PS_INPUT i ) : COLOR +{ + HALF4 color; + color.xyz = ENV_MAP_SCALE * texCUBE( EnvmapSampler, i.eyeToVertVector ); + color.a = 1.0f; + color *= i.vertexColor; + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos_SpecExponent.xyz, i.worldPos_projPosZ.xyz, i.worldPos_projPosZ.w ); + return FinalOutput( color, fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR ); +} diff --git a/materialsystem/stdshaders/windowimposter_vs20.fxc b/materialsystem/stdshaders/windowimposter_vs20.fxc new file mode 100644 index 00000000..7754fede --- /dev/null +++ b/materialsystem/stdshaders/windowimposter_vs20.fxc @@ -0,0 +1,47 @@ +#include "common_fog_vs_fxc.h" + +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// +// +// Purpose: +// +//=========================================================================== + +#include "common_vs_fxc.h" + +static const int g_FogType = DOWATERFOG; + +struct VS_INPUT +{ + float3 vPos : POSITION; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + float fog : FOG; +#endif + float3 eyeToVertVector : TEXCOORD0; + float4 vertexColor : COLOR; + + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + o.projPos = mul( float4( v.vPos, 1 ), cModelViewProj ); + + float3 worldPos = mul( float4( v.vPos, 1 ), cModel[0] ); + o.worldPos_projPosZ = float4( worldPos.xyz, o.projPos.z ); + o.eyeToVertVector = worldPos - cEyePos; + +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + o.fog = CalcFixedFunctionFog( worldPos, g_FogType ); +#endif + + o.vertexColor = cModulationColor; + return o; +} + diff --git a/materialsystem/stdshaders/wireframe_dx9.cpp b/materialsystem/stdshaders/wireframe_dx9.cpp new file mode 100644 index 00000000..7bd9c1c6 --- /dev/null +++ b/materialsystem/stdshaders/wireframe_dx9.cpp @@ -0,0 +1,56 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=====================================================================================// + +#include "BaseVSShader.h" +#include "vertexlitgeneric_dx9_helper.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( Wireframe, Wireframe_DX9 ) + +BEGIN_VS_SHADER( Wireframe_DX9, + "Help for Wireframe_DX9" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( DISPLACEMENTMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "Displacement map" ) + SHADER_PARAM( DISPLACEMENTWRINKLE, SHADER_PARAM_TYPE_BOOL, "0", "Displacement map contains wrinkle displacements") + END_SHADER_PARAMS + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT_PARAMS() + { + VertexLitGeneric_DX9_Vars_t vars; + vars.m_nDisplacementMap = DISPLACEMENTMAP; + vars.m_nDisplacementWrinkleMap = DISPLACEMENTWRINKLE; + InitParamsVertexLitGeneric_DX9( this, params, pMaterialName, false, vars ); + + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + SET_FLAGS( MATERIAL_VAR_NOFOG ); + SET_FLAGS( MATERIAL_VAR_WIREFRAME ); + } + + SHADER_INIT + { + VertexLitGeneric_DX9_Vars_t vars; + vars.m_nDisplacementMap = DISPLACEMENTMAP; + vars.m_nDisplacementWrinkleMap = DISPLACEMENTWRINKLE; + InitVertexLitGeneric_DX9( this, params, false, vars ); + } + + SHADER_DRAW + { + VertexLitGeneric_DX9_Vars_t vars; + vars.m_nDisplacementMap = DISPLACEMENTMAP; + vars.m_nDisplacementWrinkleMap = DISPLACEMENTWRINKLE; + DrawVertexLitGeneric_DX9( this, params, pShaderAPI, pShaderShadow, false, vars, vertexCompression, pContextDataPtr ); + } +END_SHADER + diff --git a/materialsystem/stdshaders/worldtwotextureblend.cpp b/materialsystem/stdshaders/worldtwotextureblend.cpp new file mode 100644 index 00000000..42304a73 --- /dev/null +++ b/materialsystem/stdshaders/worldtwotextureblend.cpp @@ -0,0 +1,590 @@ +//===== Copyright © 1996-2007, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" + +#include "ConVar.h" + +#ifndef _X360 +#include "lightmappedgeneric_vs30.inc" +#include "worldtwotextureblend_ps30.inc" +#endif + +#include "lightmappedgeneric_vs20.inc" +#include "worldtwotextureblend_ps20.inc" +#include "worldtwotextureblend_ps20b.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +// FIXME: Need to make a dx9 version so that "CENTROID" works. +BEGIN_VS_SHADER( WorldTwoTextureBlend, + "Help for WorldTwoTextureBlend" ) + +BEGIN_SHADER_PARAMS + SHADER_PARAM_OVERRIDE( BASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/WorldTwoTextureBlend", "iris texture", 0 ) + SHADER_PARAM( ALBEDO, SHADER_PARAM_TYPE_TEXTURE, "shadertest/WorldTwoTextureBlend", "albedo (Base texture with no baked lighting)" ) + SHADER_PARAM( SELFILLUMTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Self-illumination tint" ) + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/WorldTwoTextureBlend_detail", "detail texture" ) + SHADER_PARAM( DETAILFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $detail" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "1.0", "scale of the detail texture" ) + SHADER_PARAM( DETAIL_ALPHA_MASK_BASE_TEXTURE, SHADER_PARAM_TYPE_BOOL, "0", + "If this is 1, then when detail alpha=0, no base texture is blended and when " + "detail alpha=1, you get detail*base*lightmap" ) + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "bump map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( NODIFFUSEBUMPLIGHTING, SHADER_PARAM_TYPE_INTEGER, "0", "0 == Use diffuse bump lighting, 1 = No diffuse bump lighting" ) + SHADER_PARAM( SEAMLESS_SCALE, SHADER_PARAM_TYPE_FLOAT, "0", "Scale factor for 'seamless' texture mapping. 0 means to use ordinary mapping" ) + + SHADER_PARAM( SHADERSRGBREAD360, SHADER_PARAM_TYPE_BOOL, "0", "Simulate srgb read in shader code") +END_SHADER_PARAMS + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT_PARAMS() + { + + if( !params[DETAIL_ALPHA_MASK_BASE_TEXTURE]->IsDefined() ) + { + params[DETAIL_ALPHA_MASK_BASE_TEXTURE]->SetIntValue( 0 ); + } + + params[FLASHLIGHTTEXTURE]->SetStringValue( GetFlashlightTextureFilename() ); + + // Write over $basetexture with $albedo if we are going to be using diffuse normal mapping. + if( g_pConfig->UseBumpmapping() && params[BUMPMAP]->IsDefined() && params[ALBEDO]->IsDefined() && + params[BASETEXTURE]->IsDefined() && + !( params[NODIFFUSEBUMPLIGHTING]->IsDefined() && params[NODIFFUSEBUMPLIGHTING]->GetIntValue() ) ) + { + params[BASETEXTURE]->SetStringValue( params[ALBEDO]->GetStringValue() ); + } + + if( !params[NODIFFUSEBUMPLIGHTING]->IsDefined() ) + { + params[NODIFFUSEBUMPLIGHTING]->SetIntValue( 0 ); + } + + if( !params[SELFILLUMTINT]->IsDefined() ) + { + params[SELFILLUMTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + } + + if( !params[DETAILSCALE]->IsDefined() ) + { + params[DETAILSCALE]->SetFloatValue( 4.0f ); + } + + if( !params[BUMPFRAME]->IsDefined() ) + { + params[BUMPFRAME]->SetIntValue( 0 ); + } + + if( !params[DETAILFRAME]->IsDefined() ) + { + params[DETAILFRAME]->SetIntValue( 0 ); + } + + // No texture means no self-illum or env mask in base alpha + if ( !params[BASETEXTURE]->IsDefined() ) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + // If in decal mode, no debug override... + if (IS_FLAG_SET(MATERIAL_VAR_DECAL)) + { + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + } + + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + if( g_pConfig->UseBumpmapping() && params[BUMPMAP]->IsDefined() && (params[NODIFFUSEBUMPLIGHTING]->GetIntValue() == 0) ) + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_BUMPED_LIGHTMAP ); + } + + // srgb read 360 + InitIntParam( SHADERSRGBREAD360, params, 0 ); + } + + SHADER_INIT + { + if( g_pConfig->UseBumpmapping() && params[BUMPMAP]->IsDefined() ) + { + LoadBumpMap( BUMPMAP ); + } + + if (params[BASETEXTURE]->IsDefined()) + { + LoadTexture( BASETEXTURE ); + + if (!params[BASETEXTURE]->GetTextureValue()->IsTranslucent()) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + } + + if (params[DETAIL]->IsDefined()) + { + LoadTexture( DETAIL ); + } + + LoadTexture( FLASHLIGHTTEXTURE ); + + // Don't alpha test if the alpha channel is used for other purposes + if (IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK) ) + { + CLEAR_FLAGS( MATERIAL_VAR_ALPHATEST ); + } + + // We always need this because of the flashlight. + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + } + + void DrawPass( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, bool hasFlashlight, VertexCompressionType_t vertexCompression ) + { + bool bSinglePassFlashlight = false; + bool hasBump = params[BUMPMAP]->IsTexture(); + bool hasDiffuseBumpmap = hasBump && (params[NODIFFUSEBUMPLIGHTING]->GetIntValue() == 0); + bool hasBaseTexture = params[BASETEXTURE]->IsTexture(); + bool hasDetailTexture = /*!hasBump && */params[DETAIL]->IsTexture(); + bool hasVertexColor = IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR ) != 0; + bool bHasDetailAlpha = params[DETAIL_ALPHA_MASK_BASE_TEXTURE]->GetIntValue() != 0; + bool bIsAlphaTested = IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) != 0; + + BlendType_t nBlendType = EvaluateBlendRequirements( BASETEXTURE, true ); + bool bFullyOpaque = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !IS_FLAG_SET(MATERIAL_VAR_ALPHATEST); //dest alpha is free for special use + + bool bSeamlessMapping = params[SEAMLESS_SCALE]->GetFloatValue() != 0.0; + + bool bShaderSrgbRead = ( IsX360() && IS_PARAM_DEFINED( SHADERSRGBREAD360 ) && params[SHADERSRGBREAD360]->GetIntValue() ); + + SHADOW_STATE + { + int nShadowFilterMode = 0; + + // Alpha test: FIXME: shouldn't this be handled in Shader_t::SetInitialShadowState + pShaderShadow->EnableAlphaTest( bIsAlphaTested ); + if( hasFlashlight ) + { + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + nShadowFilterMode = g_pHardwareConfig->GetShadowFilterMode(); // Based upon vendor and device dependent formats + } + + SetAdditiveBlendingShadowState( BASETEXTURE, true ); + pShaderShadow->EnableDepthWrites( false ); + + // Be sure not to write to dest alpha + pShaderShadow->EnableAlphaWrites( false ); + } + else + { + SetDefaultBlendingShadowState( BASETEXTURE, true ); + } + + unsigned int flags = VERTEX_POSITION; + if( hasBaseTexture ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, !bShaderSrgbRead ); + } + // if( hasLightmap ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); + } + if( hasFlashlight ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER7, true ); + pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER7 ); + flags |= VERTEX_TANGENT_S | VERTEX_TANGENT_T | VERTEX_NORMAL; + } + if( hasDetailTexture ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + } + if( hasBump ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + } + if( hasVertexColor ) + { + flags |= VERTEX_COLOR; + } + + // Normalizing cube map + pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); + + // texcoord0 : base texcoord + // texcoord1 : lightmap texcoord + // texcoord2 : lightmap texcoord offset + int numTexCoords = 2; + if( hasBump ) + { + numTexCoords = 3; + } + + pShaderShadow->VertexShaderVertexFormat( flags, numTexCoords, 0, 0 ); + + // Pre-cache pixel shaders + bool hasSelfIllum = IS_FLAG_SET( MATERIAL_VAR_SELFILLUM ); + + pShaderShadow->EnableSRGBWrite( true ); + + int nLightingPreviewMode = IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER0 ) + 2 * IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER1 ); + +#ifndef _X360 + if ( g_pHardwareConfig->HasFastVertexTextures() ) + { + DECLARE_STATIC_VERTEX_SHADER( lightmappedgeneric_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( ENVMAP_MASK, false ); + SET_STATIC_VERTEX_SHADER_COMBO( BUMPMASK, false ); + SET_STATIC_VERTEX_SHADER_COMBO( TANGENTSPACE, hasFlashlight ); + SET_STATIC_VERTEX_SHADER_COMBO( BUMPMAP, hasBump ); + SET_STATIC_VERTEX_SHADER_COMBO( DIFFUSEBUMPMAP, hasDiffuseBumpmap ); + SET_STATIC_VERTEX_SHADER_COMBO( VERTEXCOLOR, hasVertexColor ); + SET_STATIC_VERTEX_SHADER_COMBO( VERTEXALPHATEXBLENDFACTOR, false ); + SET_STATIC_VERTEX_SHADER_COMBO( PARALLAX_MAPPING, 0 ); //( bumpmap_variant == 2 )?1:0); + SET_STATIC_VERTEX_SHADER_COMBO( SEAMLESS, bSeamlessMapping ); //( bumpmap_variant == 2 )?1:0); + SET_STATIC_VERTEX_SHADER_COMBO( DETAILTEXTURE, hasDetailTexture ); + SET_STATIC_VERTEX_SHADER_COMBO( SELFILLUM, hasSelfIllum ); + SET_STATIC_VERTEX_SHADER_COMBO( FANCY_BLENDING, false ); + SET_STATIC_VERTEX_SHADER_COMBO( LIGHTING_PREVIEW, nLightingPreviewMode != 0 ); + SET_STATIC_VERTEX_SHADER( lightmappedgeneric_vs30 ); + } + else +#endif + { + DECLARE_STATIC_VERTEX_SHADER( lightmappedgeneric_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( ENVMAP_MASK, false ); + SET_STATIC_VERTEX_SHADER_COMBO( BUMPMASK, false ); + SET_STATIC_VERTEX_SHADER_COMBO( TANGENTSPACE, hasFlashlight ); + SET_STATIC_VERTEX_SHADER_COMBO( BUMPMAP, hasBump ); + SET_STATIC_VERTEX_SHADER_COMBO( DIFFUSEBUMPMAP, hasDiffuseBumpmap ); + SET_STATIC_VERTEX_SHADER_COMBO( VERTEXCOLOR, hasVertexColor ); + SET_STATIC_VERTEX_SHADER_COMBO( VERTEXALPHATEXBLENDFACTOR, false ); + SET_STATIC_VERTEX_SHADER_COMBO( PARALLAX_MAPPING, 0 ); //( bumpmap_variant == 2 )?1:0); + SET_STATIC_VERTEX_SHADER_COMBO( SEAMLESS, bSeamlessMapping ); //( bumpmap_variant == 2 )?1:0); + SET_STATIC_VERTEX_SHADER_COMBO( DETAILTEXTURE, hasDetailTexture ); + SET_STATIC_VERTEX_SHADER_COMBO( SELFILLUM, hasSelfIllum ); + SET_STATIC_VERTEX_SHADER_COMBO( FANCY_BLENDING, false ); + SET_STATIC_VERTEX_SHADER_COMBO( LIGHTING_PREVIEW, nLightingPreviewMode != 0 ); + #ifdef _X360 + SET_STATIC_VERTEX_SHADER_COMBO( FLASHLIGHT, hasFlashlight ); + #endif + SET_STATIC_VERTEX_SHADER( lightmappedgeneric_vs20 ); + } + +#ifndef _X360 + if ( g_pHardwareConfig->HasFastVertexTextures() ) + { + DECLARE_STATIC_PIXEL_SHADER( worldtwotextureblend_ps30 ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, hasDetailTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP, hasBump ); + SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSEBUMPMAP, hasDiffuseBumpmap ); + SET_STATIC_PIXEL_SHADER_COMBO( VERTEXCOLOR, hasVertexColor ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, hasSelfIllum ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_ALPHA_MASK_BASE_TEXTURE, bHasDetailAlpha ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, hasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS, bSeamlessMapping ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER_COMBO( SHADER_SRGB_READ, bShaderSrgbRead ); + SET_STATIC_PIXEL_SHADER( worldtwotextureblend_ps30 ); + } + else +#endif + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( worldtwotextureblend_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, hasDetailTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP, hasBump ); + SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSEBUMPMAP, hasDiffuseBumpmap ); + SET_STATIC_PIXEL_SHADER_COMBO( VERTEXCOLOR, hasVertexColor ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, hasSelfIllum ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_ALPHA_MASK_BASE_TEXTURE, bHasDetailAlpha ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, hasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS, bSeamlessMapping ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER_COMBO( SHADER_SRGB_READ, bShaderSrgbRead ); + SET_STATIC_PIXEL_SHADER( worldtwotextureblend_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( worldtwotextureblend_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, hasDetailTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP, hasBump ); + SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSEBUMPMAP, hasDiffuseBumpmap ); + SET_STATIC_PIXEL_SHADER_COMBO( VERTEXCOLOR, hasVertexColor ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, hasSelfIllum ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_ALPHA_MASK_BASE_TEXTURE, bHasDetailAlpha ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, hasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS, bSeamlessMapping ); + SET_STATIC_PIXEL_SHADER_COMBO( SHADER_SRGB_READ, bShaderSrgbRead ); + SET_STATIC_PIXEL_SHADER( worldtwotextureblend_ps20 ); + } + + // HACK HACK HACK - enable alpha writes all the time so that we have them for + // underwater stuff. + // But only do it if we're not using the alpha already for translucency + pShaderShadow->EnableAlphaWrites( bFullyOpaque ); + + if( hasFlashlight ) + { + FogToBlack(); + } + else + { + DefaultFog(); + } + + PI_BeginCommandBuffer(); + PI_SetModulationVertexShaderDynamicState( ); + PI_EndCommandBuffer(); + } + DYNAMIC_STATE + { + if( hasBaseTexture ) + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_WHITE ); + } + + // if( hasLightmap ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP ); + } + + bool bFlashlightShadows = false; + bool bUberlight = false; + if( hasFlashlight ) + { + VMatrix worldToTexture; + ITexture *pFlashlightDepthTexture; + FlashlightState_t state = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture ); + bFlashlightShadows = state.m_bEnableShadows; + bUberlight = state.m_bUberlight; + + SetFlashLightColorFromState( state, pShaderAPI, bSinglePassFlashlight ); + + BindTexture( SHADER_SAMPLER2, state.m_pSpotlightTexture, state.m_nSpotlightTextureFrame ); + + if( pFlashlightDepthTexture && g_pConfig->ShadowDepthTexture() ) + { + BindTexture( SHADER_SAMPLER7, pFlashlightDepthTexture ); + } + } + if( hasDetailTexture ) + { + BindTexture( SHADER_SAMPLER3, DETAIL, DETAILFRAME ); + } + if( hasBump ) + { + if( !g_pConfig->m_bFastNoBump ) + { + BindTexture( SHADER_SAMPLER4, BUMPMAP, BUMPFRAME ); + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER4, TEXTURE_NORMALMAP_FLAT ); + } + } + pShaderAPI->BindStandardTexture( SHADER_SAMPLER6, TEXTURE_NORMALIZATION_CUBEMAP_SIGNED ); + + // If we don't have a texture transform, we don't have + // to set vertex shader constants or run vertex shader instructions + // for the texture transform. + bool bHasTextureTransform = + !( params[BASETEXTURETRANSFORM]->MatrixIsIdentity() && + params[BUMPTRANSFORM]->MatrixIsIdentity() ); + + bool bVertexShaderFastPath = !bHasTextureTransform; + if( params[DETAIL]->IsTexture() ) + { + bVertexShaderFastPath = false; + } + if( pShaderAPI->GetIntRenderingParameter(INT_RENDERPARM_ENABLE_FIXED_LIGHTING) != 0 ) + { + bVertexShaderFastPath = false; + } + + if( !bVertexShaderFastPath ) + { + if ( !bSeamlessMapping ) + { + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BASETEXTURETRANSFORM ); + } + if( hasBump && !bHasDetailAlpha ) + { + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, BUMPTRANSFORM ); + Assert( !hasDetailTexture ); + } + } + + MaterialFogMode_t fogType = pShaderAPI->GetSceneFogMode(); + + if ( IsPC() ) + { + bool bWorldNormal = pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_ENABLE_FIXED_LIGHTING ) == ENABLE_FIXED_LIGHTING_OUTPUTNORMAL_AND_DEPTH; + if ( bWorldNormal ) + { + float vEyeDir[4]; + pShaderAPI->GetWorldSpaceCameraDirection( vEyeDir ); + + float flFarZ = pShaderAPI->GetFarZ(); + vEyeDir[0] /= flFarZ; // Divide by farZ for SSAO algorithm + vEyeDir[1] /= flFarZ; + vEyeDir[2] /= flFarZ; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_12, vEyeDir ); + } + } + +#ifndef _X360 + if (g_pHardwareConfig->HasFastVertexTextures() ) + { + DECLARE_DYNAMIC_VERTEX_SHADER( lightmappedgeneric_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( FASTPATH, bVertexShaderFastPath ); + SET_DYNAMIC_VERTEX_SHADER( lightmappedgeneric_vs30 ); + } + else +#endif + { + DECLARE_DYNAMIC_VERTEX_SHADER( lightmappedgeneric_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( FASTPATH, bVertexShaderFastPath ); + SET_DYNAMIC_VERTEX_SHADER( lightmappedgeneric_vs20 ); + } + + bool bWriteDepthToAlpha; + bool bWriteWaterFogToAlpha; + if( bFullyOpaque ) + { + bWriteDepthToAlpha = pShaderAPI->ShouldWriteDepthToDestAlpha(); + bWriteWaterFogToAlpha = (fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z); + AssertMsg( !(bWriteDepthToAlpha && bWriteWaterFogToAlpha), "Can't write two values to alpha at the same time." ); + } + else + { + //can't write a special value to dest alpha if we're actually using as-intended alpha + bWriteDepthToAlpha = false; + bWriteWaterFogToAlpha = false; + } + +#ifndef _X360 + if ( g_pHardwareConfig->HasFastVertexTextures() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( worldtwotextureblend_ps30 ); + + // Don't write fog to alpha if we're using translucency + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bWriteDepthToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( UBERLIGHT, bUberlight ); + SET_DYNAMIC_PIXEL_SHADER( worldtwotextureblend_ps30 ); + } + else +#endif + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( worldtwotextureblend_ps20b ); + + // Don't write fog to alpha if we're using translucency + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bWriteDepthToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER( worldtwotextureblend_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( worldtwotextureblend_ps20 ); + + // Don't write fog to alpha if we're using translucency + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, (fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z) && + (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !bIsAlphaTested ); + SET_DYNAMIC_PIXEL_SHADER( worldtwotextureblend_ps20 ); + } + + + // always set the transform for detail textures since I'm assuming that you'll + // always have a detailscale. + if( hasDetailTexture ) + { + SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, BASETEXTURETRANSFORM, DETAILSCALE ); + Assert( !( hasBump && !bHasDetailAlpha ) ); + } + + SetPixelShaderConstantGammaToLinear( 7, SELFILLUMTINT ); + + float eyePos[4]; + pShaderAPI->GetWorldSpaceCameraPosition( eyePos ); + pShaderAPI->SetPixelShaderConstant( 10, eyePos, 1 ); + pShaderAPI->SetPixelShaderFogParams( 11 ); + + if ( bSeamlessMapping ) + { + float map_scale[4]={ params[SEAMLESS_SCALE]->GetFloatValue(),0,0,0}; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, map_scale ); + } + + + if( hasFlashlight ) + { + VMatrix worldToTexture; + const FlashlightState_t &flashlightState = pShaderAPI->GetFlashlightState( worldToTexture ); + + // Set the flashlight attenuation factors + float atten[4]; + atten[0] = flashlightState.m_fConstantAtten; + atten[1] = flashlightState.m_fLinearAtten; + atten[2] = flashlightState.m_fQuadraticAtten; + atten[3] = flashlightState.m_FarZAtten; + pShaderAPI->SetPixelShaderConstant( 20, atten, 1 ); + + // Set the flashlight origin + float pos[4]; + pos[0] = flashlightState.m_vecLightOrigin[0]; + pos[1] = flashlightState.m_vecLightOrigin[1]; + pos[2] = flashlightState.m_vecLightOrigin[2]; + pos[3] = flashlightState.m_FarZ; // didn't have this in main. . probably need this? + pShaderAPI->SetPixelShaderConstant( 15, pos, 1 ); + + pShaderAPI->SetPixelShaderConstant( 16, worldToTexture.Base(), 4 ); + + if ( IsPC() && g_pHardwareConfig->HasFastVertexTextures() ) + { + SetupUberlightFromState( pShaderAPI, flashlightState ); + } + } + } + Draw(); + } + + SHADER_DRAW + { + bool bHasFlashlight = UsingFlashlight( params ); + if ( bHasFlashlight && IsX360() ) + { + DrawPass( params, pShaderAPI, pShaderShadow, false, vertexCompression ); + SHADOW_STATE + { + SetInitialShadowState( ); + } + } + DrawPass( params, pShaderAPI, pShaderShadow, bHasFlashlight, vertexCompression ); + } + +END_SHADER diff --git a/materialsystem/stdshaders/worldtwotextureblend_ps2x.fxc b/materialsystem/stdshaders/worldtwotextureblend_ps2x.fxc new file mode 100644 index 00000000..701dc958 --- /dev/null +++ b/materialsystem/stdshaders/worldtwotextureblend_ps2x.fxc @@ -0,0 +1,238 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// +// paired with lightmappedgeneric_vs## + +// STATIC: "DETAILTEXTURE" "0..1" +// STATIC: "BUMPMAP" "0..1" +// STATIC: "VERTEXCOLOR" "0..1" +// STATIC: "SELFILLUM" "0..1" +// STATIC: "DIFFUSEBUMPMAP" "0..1" +// STATIC: "DETAIL_ALPHA_MASK_BASE_TEXTURE" "0..1" +// STATIC: "FLASHLIGHT" "0..1" +// STATIC: "SEAMLESS" "0..1" +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps20b] [ps30] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..0" [ps20b] [XBOX] +// STATIC: "SHADER_SRGB_READ" "0..1" [XBOX] +// STATIC: "SHADER_SRGB_READ" "0..0" [PC] + +// DYNAMIC: "WRITEWATERFOGTODESTALPHA" "0..1" +#include "common_fog_ps_fxc.h" +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [ps30] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps20b] [ps30] +// DYNAMIC: "UBERLIGHT" "0..1" [ps30] [PC] + +// SKIP: $DETAILTEXTURE && ( $BUMPMAP && !$DETAIL_ALPHA_MASK_BASE_TEXTURE ) +// SKIP: !$BUMPMAP && $DIFFUSEBUMPMAP +// SKIP: $VERTEXCOLOR && $BUMPMAP +// SKIP: $FLASHLIGHT && $SELFILLUM +// SKIP: $FLASHLIGHT && $DETAIL_ALPHA_MASK_BASE_TEXTURE +// SKIP: $FLASHLIGHT && ($BUMPMAP || $DIFFUSEBUMPMAP) + +// We don't care about flashlight depth unless the flashlight is on +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 ) [ps20b] [ps30] + +// We don't care about uberlight unless the flashlight is on +// SKIP: ( $FLASHLIGHT == 0 ) && ( $UBERLIGHT == 1 ) [ps30] + + +#if defined( SHADER_MODEL_PS_2_0 ) +# define WRITE_DEPTH_TO_DESTALPHA 0 +#endif + + +#define HDRTYPE HDR_TYPE_NONE +#include "shader_constant_register_map.h" +#include "common_flashlight_fxc.h" +#include "common_ps_fxc.h" + +#define PIXELSHADER +#include "common_lightmappedgeneric_fxc.h" + +const HALF4 g_SelfIllumTint : register( c7 ); +static const HALF g_OverbrightFactor = 2.0f; + +const HALF3 g_EyePos : register( c10 ); +const HALF4 g_FogParams : register( c11 ); + +const HALF3 g_FlashlightPos : register( c15 ); +// flashlightfixme: Move this math into the vertex shader. +const float4x4 g_FlashlightWorldToTexture : register( c16 ); + +const float4 g_FlashlightAttenuationFactors : register( c20 ); + +#if UBERLIGHT && defined( SHADER_MODEL_PS_3_0 ) +const float3 g_vSmoothEdge0 : register( PSREG_UBERLIGHT_SMOOTH_EDGE_0 ); // ps_3_0 and up (over 32 registers) +const float3 g_vSmoothEdge1 : register( PSREG_UBERLIGHT_SMOOTH_EDGE_1 ); +const float3 g_vSmoothOneOverWidth : register( PSREG_UBERLIGHT_SMOOTH_EDGE_OOW ); +const float4 g_vShearRound : register( PSREG_UBERLIGHT_SHEAR_ROUND ); +const float4 g_aAbB : register( PSREG_UBERLIGHT_AABB ); +const float4x4 g_FlashlightWorldToLight : register( PSREG_UBERLIGHT_WORLD_TO_LIGHT ); +#endif + +sampler BaseTextureSampler : register( s0 ); +sampler LightmapSampler : register( s1 ); +sampler FlashlightSampler : register( s2 ); +sampler DetailSampler : register( s3 ); +sampler BumpmapSampler : register( s4 ); +sampler NormalizeSampler : register( s6 ); + +//PS_INPUT defined in common_lightmappedgeneric_fxc.h" + +float4 main( PS_INPUT i ) : COLOR +{ + bool bDetailTexture = DETAILTEXTURE ? true : false; + bool bBumpmap = BUMPMAP ? true : false; + bool bDiffuseBumpmap = DIFFUSEBUMPMAP ? true : false; + bool bVertexColor = VERTEXCOLOR ? true : false; + bool bSelfIllum = SELFILLUM ? true : false; + bool bDetailAlphaMaskBaseTexture = DETAIL_ALPHA_MASK_BASE_TEXTURE ? true : false; + bool bFlashlight = FLASHLIGHT ? true : false; + float2 vBaseTexCoord; + #if ( SEAMLESS ) + { + vBaseTexCoord = i.SeamlessTexCoord_fogFactorW.xy; + } + #else + { + vBaseTexCoord = i.baseTexCoord_fogFactorZ.xy; + } + #endif + + float3 worldPos = i.worldPos_projPosZ.xyz; + + HALF3 lightmapColor1 = HALF3( 1.0f, 1.0f, 1.0f ); + HALF3 lightmapColor2 = HALF3( 1.0f, 1.0f, 1.0f ); + HALF3 lightmapColor3 = HALF3( 1.0f, 1.0f, 1.0f ); + if( bBumpmap && bDiffuseBumpmap ) + { + HALF2 bumpCoord1; + HALF2 bumpCoord2; + HALF2 bumpCoord3; + ComputeBumpedLightmapCoordinates( i.lightmapTexCoord1And2, i.lightmapTexCoord3.xy, + bumpCoord1, bumpCoord2, bumpCoord3 ); + + HALF4 lightmapSample1 = tex2D( LightmapSampler, bumpCoord1 ); + lightmapColor1 = lightmapSample1.rgb; + lightmapColor2 = tex2D( LightmapSampler, bumpCoord2 ); + lightmapColor3 = tex2D( LightmapSampler, bumpCoord3 ); + } + else + { + if( !bFlashlight ) + { + HALF2 bumpCoord1 = ComputeLightmapCoordinates( i.lightmapTexCoord1And2, i.lightmapTexCoord3.xy ); + HALF4 lightmapSample1 = tex2D( LightmapSampler, bumpCoord1 ); + lightmapColor1 = lightmapSample1.rgb; + } + } + + HALF4 detailColor = HALF4( 1.0f, 1.0f, 1.0f, 1.0f ); + if( bDetailTexture ) + { + detailColor = tex2D( DetailSampler, i.detailOrBumpAndEnvmapMaskTexCoord.xy ); + } + + HALF4 baseColor = HALF4( 1.0f, 1.0f, 1.0f, 1.0f ); + baseColor = tex2Dsrgb( BaseTextureSampler, vBaseTexCoord ); + if ( bDetailAlphaMaskBaseTexture ) + { + // This is what WorldTwoTextureBlend_DX6 does. + baseColor.rgb = saturate( saturate( baseColor * 2 ) * detailColor.a + (1 - detailColor.a) ); + baseColor.rgb *= detailColor; + } + else + { + baseColor.rgb = lerp( baseColor, detailColor, detailColor.a ); + } + + HALF3 normal = HALF3( 0.0f, 0.0f, 1.0f ); + if( bBumpmap ) + { + HALF3 normalTexel; + normalTexel = tex2D( BumpmapSampler, i.detailOrBumpAndEnvmapMaskTexCoord.xy ); + normal = 2.0 * normalTexel - 1.0; + } + + HALF3 albedo = HALF3( 1.0f, 1.0f, 1.0f ); + HALF alpha = 1.0f; + albedo *= baseColor; + if( !bSelfIllum ) + { + alpha *= baseColor.a; + } + + // The vertex color contains the modulation color + vertex color combined + albedo *= i.vertexColor; + alpha *= i.vertexColor.a; // not sure about this one + + HALF3 diffuseLighting; + if( bFlashlight ) + { + float3 worldSpaceNormal; + // Make the unbumped version not so fucking stupid and not need tangentSpaceTranspose you knob. + worldSpaceNormal = mul( normal, (float3x3)i.tangentSpaceTranspose ); + + int nShadowSampleLevel = 0; + bool bDoShadows = false; +// On ps_2_b, we can do shadow mapping +#if ( FLASHLIGHTSHADOWS && (defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) ) ) + nShadowSampleLevel = FLASHLIGHTDEPTHFILTERMODE; + bDoShadows = true; +#endif + float4 flashlightSpacePosition = mul( float4( worldPos, 1.0f ), g_FlashlightWorldToTexture ); + + diffuseLighting = DoFlashlight( g_FlashlightPos, worldPos, flashlightSpacePosition, + worldSpaceNormal, g_FlashlightAttenuationFactors.xyz, + g_FlashlightAttenuationFactors.w, FlashlightSampler, FlashlightSampler, NormalizeSampler, + nShadowSampleLevel, bDoShadows, false, float2(0, 0), false ); + +#if UBERLIGHT && defined( SHADER_MODEL_PS_3_0 ) + float4 uberLightPosition = mul( float4( worldPos, 1.0f ), g_FlashlightWorldToLight ).yzxw; + diffuseLighting *= uberlight( uberLightPosition, g_vSmoothEdge0, g_vSmoothEdge1, + g_vSmoothOneOverWidth, g_vShearRound.xy, g_aAbB, g_vShearRound.zw ); +#endif + + } + else + { + if( bBumpmap && bDiffuseBumpmap ) + { + float dot1 = saturate( dot( normal, bumpBasis[0] ) ); + float dot2 = saturate( dot( normal, bumpBasis[1] ) ); + float dot3 = saturate( dot( normal, bumpBasis[2] ) ); + + float sum = dot1 + dot2 + dot3; + diffuseLighting = dot1 * lightmapColor1 + + dot2 * lightmapColor2 + + dot3 * lightmapColor3; + diffuseLighting *= 1.0f / sum; + } + else + { + diffuseLighting = lightmapColor1; + } + + // Only scale here since the flashlight will already be scaled properly + diffuseLighting *= g_OverbrightFactor; + } + + HALF3 diffuseComponent = albedo * diffuseLighting; + + if( bSelfIllum ) + { + HALF3 selfIllumComponent = g_SelfIllumTint * albedo; + diffuseComponent = lerp( diffuseComponent, selfIllumComponent, baseColor.a ); + } + + HALF3 specularLighting = HALF3( 0.0f, 0.0f, 0.0f ); + HALF3 result = diffuseComponent + specularLighting; + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos.xyz, worldPos, i.worldPos_projPosZ.w ); + +#if WRITEWATERFOGTODESTALPHA && (PIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT) + alpha = fogFactor; +#endif + + return FinalOutput( float4( result, alpha ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, (WRITE_DEPTH_TO_DESTALPHA != 0), i.worldPos_projPosZ.w ); +} + diff --git a/materialsystem/stdshaders/worldvertexalpha.cpp b/materialsystem/stdshaders/worldvertexalpha.cpp new file mode 100644 index 00000000..6eff1b12 --- /dev/null +++ b/materialsystem/stdshaders/worldvertexalpha.cpp @@ -0,0 +1,178 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" + +#include "worldvertexalpha_ps20.inc" +#include "worldvertexalpha_ps20b.inc" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +BEGIN_VS_SHADER( WorldVertexAlpha, "Help for WorldVertexAlpha" ) + + BEGIN_SHADER_PARAMS + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + SET_FLAGS2( MATERIAL_VAR2_BLEND_WITH_LIGHTMAP_ALPHA ); + } + SHADER_INIT + { + // Load the base texture here! + LoadTexture( BASETEXTURE ); + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_DRAW + { + if( g_pHardwareConfig->SupportsVertexAndPixelShaders() && !UsingEditor( params ) ) + { + // DX 9 version with HDR support + + // Pass 1 + SHADOW_STATE + { + SetInitialShadowState(); + + pShaderShadow->EnableAlphaWrites( true ); + + // Base time lightmap (Need two texture stages) + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + + int fmt = VERTEX_POSITION; + pShaderShadow->VertexShaderVertexFormat( fmt, 2, 0, 0 ); + + pShaderShadow->EnableBlending( true ); + + // Looks backwards, but this is done so that lightmap alpha = 1 when only + // using 1 texture (needed for translucent displacements). + pShaderShadow->BlendFunc( SHADER_BLEND_ONE_MINUS_SRC_ALPHA, SHADER_BLEND_SRC_ALPHA ); + pShaderShadow->EnableBlendingSeparateAlpha( true ); + pShaderShadow->BlendFuncSeparateAlpha( SHADER_BLEND_ZERO, SHADER_BLEND_SRC_ALPHA ); + + worldvertexalpha_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "WorldVertexAlpha", vshIndex.GetIndex() ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( worldvertexalpha_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( PASS, 0 ); + SET_STATIC_PIXEL_SHADER( worldvertexalpha_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( worldvertexalpha_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( PASS, 0 ); + SET_STATIC_PIXEL_SHADER( worldvertexalpha_ps20 ); + } + + + FogToFogColor(); + } + + DYNAMIC_STATE + { + // Bind the base texture (Stage0) and lightmap (Stage1) + BindTexture( SHADER_SAMPLER0, BASETEXTURE ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP ); + + worldvertexalpha_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( worldvertexalpha_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( worldvertexalpha_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( worldvertexalpha_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( worldvertexalpha_ps20 ); + } + } + Draw(); + + // Pass 2 + SHADOW_STATE + { + SetInitialShadowState(); + + pShaderShadow->EnableAlphaWrites( true ); + pShaderShadow->EnableColorWrites( false ); + + // Base time lightmap (Need two texture stages) + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + + int fmt = VERTEX_POSITION; + pShaderShadow->VertexShaderVertexFormat( fmt, 2, 0, 0 ); + + pShaderShadow->EnableBlending( true ); + + // Looks backwards, but this is done so that lightmap alpha = 1 when only + // using 1 texture (needed for translucent displacements). + pShaderShadow->BlendFunc( SHADER_BLEND_ONE_MINUS_SRC_ALPHA, SHADER_BLEND_SRC_ALPHA ); + pShaderShadow->EnableBlendingSeparateAlpha( true ); + pShaderShadow->BlendFuncSeparateAlpha( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); + + worldvertexalpha_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "WorldVertexAlpha", vshIndex.GetIndex() ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( worldvertexalpha_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( PASS, 1 ); + SET_STATIC_PIXEL_SHADER( worldvertexalpha_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( worldvertexalpha_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( PASS, 1 ); + SET_STATIC_PIXEL_SHADER( worldvertexalpha_ps20 ); + } + + FogToFogColor(); + } + + DYNAMIC_STATE + { + // Bind the base texture (Stage0) and lightmap (Stage1) + BindTexture( SHADER_SAMPLER0, BASETEXTURE ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP ); + + worldvertexalpha_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( worldvertexalpha_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( worldvertexalpha_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( worldvertexalpha_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( worldvertexalpha_ps20 ); + } + } + Draw(); + } + } +END_SHADER diff --git a/materialsystem/stdshaders/worldvertextransition.cpp b/materialsystem/stdshaders/worldvertextransition.cpp new file mode 100644 index 00000000..0817e656 --- /dev/null +++ b/materialsystem/stdshaders/worldvertextransition.cpp @@ -0,0 +1,161 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" +#include "convar.h" + +#include "lightmappedgeneric_dx9_helper.h" +#include "worldvertextransition_dx8_helper.h" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +static LightmappedGeneric_DX9_Vars_t s_info; + + +DEFINE_FALLBACK_SHADER( WorldVertexTransition, WorldVertexTransition_DX9 ) + +BEGIN_VS_SHADER( WorldVertexTransition_DX9, "Help for WorldVertexTransition" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( ALBEDO, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "albedo (Base texture with no baked lighting)" ) + SHADER_PARAM( SELFILLUMTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Self-illumination tint" ) + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/detail", "detail texture" ) + SHADER_PARAM( DETAILFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $detail" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "4", "scale of the detail texture" ) + + // detail (multi-) texturing + SHADER_PARAM( DETAILBLENDMODE, SHADER_PARAM_TYPE_INTEGER, "0", "mode for combining detail texture with base. 0=normal, 1= additive, 2=alpha blend detail over base, 3=crossfade" ) + SHADER_PARAM( DETAILBLENDFACTOR, SHADER_PARAM_TYPE_FLOAT, "1", "blend amount for detail texture." ) + SHADER_PARAM( DETAILTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "detail texture tint" ) + + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( ENVMAPMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_envmask", "envmap mask" ) + SHADER_PARAM( ENVMAPMASKFRAME, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( ENVMAPMASKTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$envmapmask texcoord transform" ) + SHADER_PARAM( ENVMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "envmap tint" ) + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "bump map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( ENVMAPCONTRAST, SHADER_PARAM_TYPE_FLOAT, "0.0", "contrast 0 == normal 1 == color*color" ) + SHADER_PARAM( ENVMAPSATURATION, SHADER_PARAM_TYPE_FLOAT, "1.0", "saturation 0 == greyscale 1 == normal" ) + SHADER_PARAM( FRESNELREFLECTION, SHADER_PARAM_TYPE_FLOAT, "1.0", "1.0 == mirror, 0.0 == water" ) + SHADER_PARAM( NODIFFUSEBUMPLIGHTING, SHADER_PARAM_TYPE_INTEGER, "0", "0 == Use diffuse bump lighting, 1 = No diffuse bump lighting" ) + SHADER_PARAM( BUMPMAP2, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader3_normal", "bump map" ) + SHADER_PARAM( BUMPFRAME2, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM2, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( BUMPMASK, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "bump map" ) + SHADER_PARAM( BASETEXTURE2, SHADER_PARAM_TYPE_TEXTURE, "shadertest/detail", "detail texture" ) + SHADER_PARAM( FRAME2, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $basetexture2" ) + SHADER_PARAM( BASETEXTURENOENVMAP, SHADER_PARAM_TYPE_BOOL, "0", "" ) + SHADER_PARAM( BASETEXTURE2NOENVMAP, SHADER_PARAM_TYPE_BOOL, "0", "" ) + SHADER_PARAM( DETAIL_ALPHA_MASK_BASE_TEXTURE, SHADER_PARAM_TYPE_BOOL, "0", + "If this is 1, then when detail alpha=0, no base texture is blended and when " + "detail alpha=1, you get detail*base*lightmap" ) + SHADER_PARAM( LIGHTWARPTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "light munging lookup texture" ) + SHADER_PARAM( BLENDMODULATETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "texture to use r/g channels for blend range for" ) + SHADER_PARAM( BLENDMASKTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$blendmodulatetexture texcoord transform" ) + SHADER_PARAM( MASKEDBLENDING, SHADER_PARAM_TYPE_INTEGER, "0", "blend using texture with no vertex alpha. For using texture blending on non-displacements" ) + SHADER_PARAM( SSBUMP, SHADER_PARAM_TYPE_INTEGER, "0", "whether or not to use alternate bumpmap format with height" ) + SHADER_PARAM( SEAMLESS_SCALE, SHADER_PARAM_TYPE_FLOAT, "0", "Scale factor for 'seamless' texture mapping. 0 means to use ordinary mapping" ) + SHADER_PARAM( FOW, SHADER_PARAM_TYPE_TEXTURE, "", "FoW Render Target" ) + END_SHADER_PARAMS + + void SetupVars( WorldVertexTransitionEditor_DX8_Vars_t& info ) + { + info.m_nBaseTextureVar = BASETEXTURE; + info.m_nBaseTextureFrameVar = FRAME; + info.m_nBaseTextureTransformVar = BASETEXTURETRANSFORM; + info.m_nBaseTexture2Var = BASETEXTURE2; + info.m_nBaseTexture2FrameVar = FRAME2; + info.m_nBaseTexture2TransformVar = BASETEXTURETRANSFORM; // FIXME!!!! + } + + void SetupVars( LightmappedGeneric_DX9_Vars_t& info ) + { + info.m_nBaseTexture = BASETEXTURE; + info.m_nBaseTextureFrame = FRAME; + info.m_nBaseTextureTransform = BASETEXTURETRANSFORM; + info.m_nAlbedo = ALBEDO; + info.m_nSelfIllumTint = SELFILLUMTINT; + + info.m_nDetail = DETAIL; + info.m_nDetailFrame = DETAILFRAME; + info.m_nDetailScale = DETAILSCALE; + info.m_nDetailTextureCombineMode = DETAILBLENDMODE; + info.m_nDetailTextureBlendFactor = DETAILBLENDFACTOR; + info.m_nDetailTint = DETAILTINT; + + info.m_nEnvmap = ENVMAP; + info.m_nEnvmapFrame = ENVMAPFRAME; + info.m_nEnvmapMask = ENVMAPMASK; + info.m_nEnvmapMaskFrame = ENVMAPMASKFRAME; + info.m_nEnvmapMaskTransform = ENVMAPMASKTRANSFORM; + info.m_nEnvmapTint = ENVMAPTINT; + info.m_nBumpmap = BUMPMAP; + info.m_nBumpFrame = BUMPFRAME; + info.m_nBumpTransform = BUMPTRANSFORM; + info.m_nEnvmapContrast = ENVMAPCONTRAST; + info.m_nEnvmapSaturation = ENVMAPSATURATION; + info.m_nFresnelReflection = FRESNELREFLECTION; + info.m_nNoDiffuseBumpLighting = NODIFFUSEBUMPLIGHTING; + info.m_nBumpmap2 = BUMPMAP2; + info.m_nBumpFrame2 = BUMPFRAME2; + info.m_nBaseTexture2 = BASETEXTURE2; + info.m_nBaseTexture2Frame = FRAME2; + info.m_nBumpTransform2 = BUMPTRANSFORM2; + info.m_nBumpMask = BUMPMASK; + info.m_nBaseTextureNoEnvmap = BASETEXTURENOENVMAP; + info.m_nBaseTexture2NoEnvmap = BASETEXTURE2NOENVMAP; + info.m_nDetailAlphaMaskBaseTexture = DETAIL_ALPHA_MASK_BASE_TEXTURE; + info.m_nFlashlightTexture = FLASHLIGHTTEXTURE; + info.m_nFlashlightTextureFrame = FLASHLIGHTTEXTUREFRAME; + info.m_nLightWarpTexture = LIGHTWARPTEXTURE; + info.m_nBlendModulateTexture = BLENDMODULATETEXTURE; + info.m_nBlendMaskTransform = BLENDMASKTRANSFORM; + info.m_nMaskedBlending = MASKEDBLENDING; + info.m_nSelfShadowedBumpFlag = SSBUMP; + info.m_nSeamlessMappingScale = SEAMLESS_SCALE; + info.m_nAlphaTestReference = -1; + + info.m_nFoW = FOW; + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT_PARAMS() + { + SetupVars( s_info ); + InitParamsLightmappedGeneric_DX9( this, params, pMaterialName, s_info ); + } + + SHADER_INIT + { + SetupVars( s_info ); + InitLightmappedGeneric_DX9( this, params, s_info ); + } + + SHADER_DRAW + { +// if ( UsingEditor( params ) ) +// { +// WorldVertexTransitionEditor_DX8_Vars_t info; +// SetupVars( info ); +// DrawWorldVertexTransitionEditor_DX8( this, params, pShaderAPI, pShaderShadow, info ); +// return; +// } + + DrawLightmappedGeneric_DX9( this, params, pShaderAPI, pShaderShadow, s_info, pContextDataPtr ); + } +END_SHADER + diff --git a/materialsystem/stdshaders/worldvertextransition_dx8_helper.cpp b/materialsystem/stdshaders/worldvertextransition_dx8_helper.cpp new file mode 100644 index 00000000..3bfdbf80 --- /dev/null +++ b/materialsystem/stdshaders/worldvertextransition_dx8_helper.cpp @@ -0,0 +1,78 @@ +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#include "worldvertexTransition_DX8_helper.h" +#include "BaseVSShader.h" + +#include "worldvertextransition.inc" + + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + +void InitParamsWorldVertexTransitionEditor_DX8( IMaterialVar** params, WorldVertexTransitionEditor_DX8_Vars_t &info ) +{ + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); +} + +void InitWorldVertexTransitionEditor_DX8( CBaseVSShader *pShader, IMaterialVar** params, WorldVertexTransitionEditor_DX8_Vars_t &info ) +{ + if ( params[info.m_nBaseTextureVar]->IsDefined() ) + { + pShader->LoadTexture( info.m_nBaseTextureVar ); + } + + if ( params[info.m_nBaseTexture2Var]->IsDefined() ) + { + pShader->LoadTexture( info.m_nBaseTexture2Var ); + } +} + +void DrawWorldVertexTransitionEditor_DX8( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, WorldVertexTransitionEditor_DX8_Vars_t &info ) +{ + SHADOW_STATE + { + // This is the dx8 worldcraft version (non-bumped always.. too bad) + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + + int fmt = VERTEX_POSITION | VERTEX_COLOR; + pShaderShadow->VertexShaderVertexFormat( fmt, 2, 0, 0 ); + + worldvertextransition_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "WorldVertexTransition", vshIndex.GetIndex() ); + pShaderShadow->SetPixelShader( "WorldVertexTransition_Editor" ); + + pShader->FogToFogColor(); + } + DYNAMIC_STATE + { + pShader->BindTexture( SHADER_SAMPLER0, info.m_nBaseTextureVar, info.m_nBaseTextureFrameVar ); + pShader->BindTexture( SHADER_SAMPLER1, info.m_nBaseTexture2Var, info.m_nBaseTexture2FrameVar ); + + // Texture 3 = lightmap + pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_LIGHTMAP ); + + pShader->EnablePixelShaderOverbright( 0, true, true ); + + // JasonM - Gnarly hack since we're calling this legacy shader from DX9 + int nTextureTransformConst = VERTEX_SHADER_SHADER_SPECIFIC_CONST_0; + int nTextureTransformConst2 = VERTEX_SHADER_SHADER_SPECIFIC_CONST_2; + nTextureTransformConst -= 10; + nTextureTransformConst2 -= 10; + + pShader->SetVertexShaderTextureTransform( nTextureTransformConst, info.m_nBaseTextureTransformVar ); + pShader->SetVertexShaderTextureTransform( nTextureTransformConst2, info.m_nBaseTexture2TransformVar ); + + worldvertextransition_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + pShader->Draw(); +} diff --git a/materialsystem/stdshaders/worldvertextransition_dx8_helper.h b/materialsystem/stdshaders/worldvertextransition_dx8_helper.h new file mode 100644 index 00000000..39ef3f19 --- /dev/null +++ b/materialsystem/stdshaders/worldvertextransition_dx8_helper.h @@ -0,0 +1,44 @@ +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef WORLDVERTEXTRANSITION_DX8_HELPER_H +#define WORLDVERTEXTRANSITION_DX8_HELPER_H + +#include + + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct WorldVertexTransitionEditor_DX8_Vars_t +{ + WorldVertexTransitionEditor_DX8_Vars_t() { memset( this, 0xFF, sizeof(WorldVertexTransitionEditor_DX8_Vars_t) ); } + + int m_nBaseTextureVar; + int m_nBaseTextureFrameVar; + int m_nBaseTextureTransformVar; + int m_nBaseTexture2Var; + int m_nBaseTexture2FrameVar; + int m_nBaseTexture2TransformVar; +}; + +void InitParamsWorldVertexTransitionEditor_DX8( IMaterialVar** params, WorldVertexTransitionEditor_DX8_Vars_t &info ); +void InitWorldVertexTransitionEditor_DX8( CBaseVSShader *pShader, IMaterialVar** params, WorldVertexTransitionEditor_DX8_Vars_t &info ); +void DrawWorldVertexTransitionEditor_DX8( CBaseVSShader *pShader, IMaterialVar** params, + IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, WorldVertexTransitionEditor_DX8_Vars_t &info ); + + +#endif // WORLDVERTEXTRANSITION_DX8_HELPER_H \ No newline at end of file diff --git a/materialsystem/stdshaders/writestencil_dx9.cpp b/materialsystem/stdshaders/writestencil_dx9.cpp new file mode 100644 index 00000000..f4610499 --- /dev/null +++ b/materialsystem/stdshaders/writestencil_dx9.cpp @@ -0,0 +1,69 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" + +#include "writez_vs20.inc" +#include "white_ps20.inc" +#include "white_ps20b.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( WriteStencil, WriteStencil_DX9 ) + +BEGIN_VS_SHADER_FLAGS( WriteStencil_DX9, "Help for WriteStencil", SHADER_NOT_EDITABLE ) + + BEGIN_SHADER_PARAMS + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableColorWrites( false ); // + pShaderShadow->EnableAlphaWrites( false ); // Write ONLY to stencil + pShaderShadow->EnableDepthWrites( false ); // + + DECLARE_STATIC_VERTEX_SHADER( writez_vs20 ); + SET_STATIC_VERTEX_SHADER( writez_vs20 ); + + //No pixel shader, doubles fill rate. + + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + } + DYNAMIC_STATE + { + DECLARE_DYNAMIC_VERTEX_SHADER( writez_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER( writez_vs20 ); + + //No pixel shader, doubles fill rate. + } + Draw(); + } +END_SHADER + diff --git a/materialsystem/stdshaders/writez_dx9.cpp b/materialsystem/stdshaders/writez_dx9.cpp new file mode 100644 index 00000000..6530e70f --- /dev/null +++ b/materialsystem/stdshaders/writez_dx9.cpp @@ -0,0 +1,69 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" + + +#include "writez_vs20.inc" +#include "white_ps20.inc" +#include "white_ps20b.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( WriteZ, WriteZ_DX9 ) + +BEGIN_VS_SHADER_FLAGS( WriteZ_DX9, "Help for WriteZ", SHADER_NOT_EDITABLE ) + + BEGIN_SHADER_PARAMS + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableColorWrites( false ); + pShaderShadow->EnableAlphaWrites( false ); + + DECLARE_STATIC_VERTEX_SHADER( writez_vs20 ); + SET_STATIC_VERTEX_SHADER( writez_vs20 ); + + //No pixel shader, doubles fill rate. + + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + } + DYNAMIC_STATE + { + DECLARE_DYNAMIC_VERTEX_SHADER( writez_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER( writez_vs20 ); + + //No pixel shader, doubles fill rate. + } + Draw(); + } +END_SHADER + diff --git a/materialsystem/stdshaders/writez_vs20.fxc b/materialsystem/stdshaders/writez_vs20.fxc new file mode 100644 index 00000000..1e4fdde6 --- /dev/null +++ b/materialsystem/stdshaders/writez_vs20.fxc @@ -0,0 +1,39 @@ +// DYNAMIC: "SKINNING" "0..1" +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +#include "common_fog_vs_fxc.h" + +#include "common_vs_fxc.h" + +struct VS_INPUT +{ + float4 vPos : POSITION; +#if (SKINNING == 1) + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; +#endif +}; + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; +}; + + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + +# if (SKINNING == 1) + { + float3 vWorldPos; + SkinPosition( true, v.vPos, v.vBoneWeights, v.vBoneIndices, vWorldPos ); + o.vProjPos = mul( float4( vWorldPos, 1 ), cViewProj ); + } +# else + { + o.vProjPos = mul( v.vPos, cModelViewProj ); + } +# endif + + return o; +} \ No newline at end of file diff --git a/materialsystem/stdshaders/yuv.cpp b/materialsystem/stdshaders/yuv.cpp new file mode 100644 index 00000000..ff77b13c --- /dev/null +++ b/materialsystem/stdshaders/yuv.cpp @@ -0,0 +1,62 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" + +#include "screenspaceeffect.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_VS_SHADER_FLAGS( YUV, "Help for YUV", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_NEEDS_FULL_FRAME_BUFFER_TEXTURE ); + } + + SHADER_INIT + { + } + + SHADER_FALLBACK + { + // Requires DX8 + above + if ( IsPC() && !g_pHardwareConfig->SupportsVertexAndPixelShaders()) + { + Assert( 0 ); + return "Wireframe"; + } + return 0; + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 1, 0, 0 ); + + screenspaceeffect_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "ScreenSpaceEffect", vshIndex.GetIndex() ); + + pShaderShadow->SetPixelShader( "YUV" ); + } + + DYNAMIC_STATE + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_FRAME_BUFFER_FULL_TEXTURE_0 ); + + screenspaceeffect_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); + } +END_SHADER diff --git a/public/shaderlib/commandbuilder.h b/public/shaderlib/commandbuilder.h new file mode 100644 index 00000000..07836848 --- /dev/null +++ b/public/shaderlib/commandbuilder.h @@ -0,0 +1,633 @@ +//===== Copyright © 1996-2007, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $NoKeywords: $ +// Utility class for building command buffers into memory +//===========================================================================// + +#ifndef COMMANDBUILDER_H +#define COMMANDBUILDER_H + + +#ifdef _WIN32 +#pragma once +#endif + + +#include "shaderapi/commandbuffer.h" +#include "shaderlib/BaseShader.h" +#include "tier1/convar.h" + + +#ifdef DBGFLAG_ASSERT +#define TRACK_STORAGE 1 +#else +#define TRACK_STORAGE 0 +#endif + +//----------------------------------------------------------------------------- +// Buffer for storing commands into +//----------------------------------------------------------------------------- +template class CFixedCommandStorageBuffer +{ +public: + uint8 m_Data[N]; + + uint8 *m_pDataOut; +#if TRACK_STORAGE + size_t m_nNumBytesRemaining; +#endif + + FORCEINLINE CFixedCommandStorageBuffer( void ) + { + m_pDataOut = m_Data; +#if TRACK_STORAGE + m_nNumBytesRemaining = N; +#endif + + } + + FORCEINLINE void EnsureCapacity( size_t sz ) + { +#if TRACK_STORAGE + if ( m_nNumBytesRemaining < sz + 32 ) + Error( "getting scary\n" ); +#endif + Assert( m_nNumBytesRemaining >= sz ); + } + + template FORCEINLINE void Put( T const &nValue ) + { + EnsureCapacity( sizeof( T ) ); + *( reinterpret_cast( m_pDataOut ) ) = nValue; + m_pDataOut += sizeof( nValue ); +#if TRACK_STORAGE + m_nNumBytesRemaining -= sizeof( nValue ); +#endif + } + + FORCEINLINE void PutInt( int nValue ) + { + Put( nValue ); + } + + FORCEINLINE void PutFloat( float nValue ) + { + Put( nValue ); + } + + FORCEINLINE void PutPtr( void * pPtr ) + { + Put( pPtr ); + } + + FORCEINLINE void PutMemory( const void *pMemory, size_t nBytes ) + { + EnsureCapacity( nBytes ); + memcpy( m_pDataOut, pMemory, nBytes ); + m_pDataOut += nBytes; +#if TRACK_STORAGE + m_nNumBytesRemaining -= nBytes; +#endif + } + + FORCEINLINE uint8 *Base( void ) + { + return m_Data; + } + + FORCEINLINE void Reset( void ) + { + m_pDataOut = m_Data; +#if TRACK_STORAGE + m_nNumBytesRemaining = N; +#endif + } + + FORCEINLINE size_t Size( void ) const + { + return m_pDataOut - m_Data; + } + +}; + + +//----------------------------------------------------------------------------- +// Base class used to build up command buffers +//----------------------------------------------------------------------------- +template class CBaseCommandBufferBuilder +{ +public: + S m_Storage; + + FORCEINLINE void End( void ) + { + m_Storage.PutInt( CBCMD_END ); + } + + FORCEINLINE IMaterialVar *Param( int nVar ) const + { + return CBaseShader::s_ppParams[nVar]; + } + + FORCEINLINE void Reset( void ) + { + m_Storage.Reset(); + } + + FORCEINLINE size_t Size( void ) const + { + return m_Storage.Size(); + } + + FORCEINLINE uint8 *Base( void ) + { + return m_Storage.Base(); + } + + FORCEINLINE void OutputConstantData( float const *pSrcData ) + { + m_Storage.PutFloat( pSrcData[0] ); + m_Storage.PutFloat( pSrcData[1] ); + m_Storage.PutFloat( pSrcData[2] ); + m_Storage.PutFloat( pSrcData[3] ); + } + + FORCEINLINE void OutputConstantData4( float flVal0, float flVal1, float flVal2, float flVal3 ) + { + m_Storage.PutFloat( flVal0 ); + m_Storage.PutFloat( flVal1 ); + m_Storage.PutFloat( flVal2 ); + m_Storage.PutFloat( flVal3 ); + } +}; + + +//----------------------------------------------------------------------------- +// Used by SetPixelShaderFlashlightState +//----------------------------------------------------------------------------- +struct CBCmdSetPixelShaderFlashlightState_t +{ + Sampler_t m_LightSampler; + Sampler_t m_DepthSampler; + Sampler_t m_ShadowNoiseSampler; + int m_nColorConstant; + int m_nAttenConstant; + int m_nOriginConstant; + int m_nDepthTweakConstant; + int m_nScreenScaleConstant; + int m_nWorldToTextureConstant; + bool m_bFlashlightNoLambert; + bool m_bSinglePassFlashlight; +}; + + +//----------------------------------------------------------------------------- +// Used to build a per-pass command buffer +//----------------------------------------------------------------------------- +template class CCommandBufferBuilder : public CBaseCommandBufferBuilder +{ + typedef CBaseCommandBufferBuilder PARENT; + +public: + FORCEINLINE void End( void ) + { + this->m_Storage.PutInt( CBCMD_END ); + } + + FORCEINLINE void SetPixelShaderConstants( int nFirstConstant, int nConstants ) + { + this->m_Storage.PutInt( CBCMD_SET_PIXEL_SHADER_FLOAT_CONST ); + this->m_Storage.PutInt( nFirstConstant ); + this->m_Storage.PutInt( nConstants ); + } + + FORCEINLINE void OutputConstantData( float const *pSrcData ) + { + this->m_Storage.PutFloat( pSrcData[0] ); + this->m_Storage.PutFloat( pSrcData[1] ); + this->m_Storage.PutFloat( pSrcData[2] ); + this->m_Storage.PutFloat( pSrcData[3] ); + } + + FORCEINLINE void OutputConstantData4( float flVal0, float flVal1, float flVal2, float flVal3 ) + { + this->m_Storage.PutFloat( flVal0 ); + this->m_Storage.PutFloat( flVal1 ); + this->m_Storage.PutFloat( flVal2 ); + this->m_Storage.PutFloat( flVal3 ); + } + + FORCEINLINE void SetPixelShaderConstant( int nFirstConstant, float const *pSrcData, int nNumConstantsToSet ) + { + SetPixelShaderConstants( nFirstConstant, nNumConstantsToSet ); + this->m_Storage.PutMemory( pSrcData, 4 * sizeof( float ) * nNumConstantsToSet ); + } + + FORCEINLINE void SetPixelShaderConstant( int nFirstConstant, int nVar ) + { + SetPixelShaderConstant( nFirstConstant, this->Param( nVar )->GetVecValue() ); + } + + void SetPixelShaderConstantGammaToLinear( int pixelReg, int constantVar ) + { + float val[4]; + this->Param(constantVar)->GetVecValue( val, 3 ); + val[0] = val[0] > 1.0f ? val[0] : GammaToLinear( val[0] ); + val[1] = val[1] > 1.0f ? val[1] : GammaToLinear( val[1] ); + val[2] = val[2] > 1.0f ? val[2] : GammaToLinear( val[2] ); + val[3] = 1.0; + SetPixelShaderConstant( pixelReg, val ); + } + + FORCEINLINE void SetPixelShaderConstant( int nFirstConstant, float const *pSrcData ) + { + SetPixelShaderConstants( nFirstConstant, 1 ); + OutputConstantData( pSrcData ); + } + + FORCEINLINE void SetPixelShaderConstant4( int nFirstConstant, float flVal0, float flVal1, float flVal2, float flVal3 ) + { + SetPixelShaderConstants( nFirstConstant, 1 ); + OutputConstantData4( flVal0, flVal1, flVal2, flVal3 ); + } + + FORCEINLINE void SetPixelShaderConstant_W( int pixelReg, int constantVar, float fWValue ) + { + if ( constantVar != -1 ) + { + float val[3]; + this->Param(constantVar)->GetVecValue( val, 3); + SetPixelShaderConstant4( pixelReg, val[0], val[1], val[2], fWValue ); + } + } + + FORCEINLINE void SetVertexShaderConstant( int nFirstConstant, float const *pSrcData ) + { + this->m_Storage.PutInt( CBCMD_SET_VERTEX_SHADER_FLOAT_CONST ); + this->m_Storage.PutInt( nFirstConstant ); + this->m_Storage.PutInt( 1 ); + OutputConstantData( pSrcData ); + } + + FORCEINLINE void SetVertexShaderConstant( int nFirstConstant, float const *pSrcData, int nConsts ) + { + this->m_Storage.PutInt( CBCMD_SET_VERTEX_SHADER_FLOAT_CONST ); + this->m_Storage.PutInt( nFirstConstant ); + this->m_Storage.PutInt( nConsts ); + this->m_Storage.PutMemory( pSrcData, 4 * nConsts * sizeof( float ) ); + } + + + FORCEINLINE void SetVertexShaderConstant4( int nFirstConstant, float flVal0, float flVal1, float flVal2, float flVal3 ) + { + this->m_Storage.PutInt( CBCMD_SET_VERTEX_SHADER_FLOAT_CONST ); + this->m_Storage.PutInt( nFirstConstant ); + this->m_Storage.PutInt( 1 ); + this->m_Storage.PutFloat( flVal0 ); + this->m_Storage.PutFloat( flVal1 ); + this->m_Storage.PutFloat( flVal2 ); + this->m_Storage.PutFloat( flVal3 ); + } + + void SetVertexShaderTextureTransform( int vertexReg, int transformVar ) + { + Vector4D transformation[2]; + IMaterialVar* pTransformationVar = this->Param( transformVar ); + if (pTransformationVar && (pTransformationVar->GetType() == MATERIAL_VAR_TYPE_MATRIX)) + { + const VMatrix &mat = pTransformationVar->GetMatrixValue(); + transformation[0].Init( mat[0][0], mat[0][1], mat[0][2], mat[0][3] ); + transformation[1].Init( mat[1][0], mat[1][1], mat[1][2], mat[1][3] ); + } + else + { + transformation[0].Init( 1.0f, 0.0f, 0.0f, 0.0f ); + transformation[1].Init( 0.0f, 1.0f, 0.0f, 0.0f ); + } + SetVertexShaderConstant( vertexReg, transformation[0].Base(), 2 ); + } + + + void SetVertexShaderTextureScaledTransform( int vertexReg, int transformVar, int scaleVar ) + { + Vector4D transformation[2]; + IMaterialVar* pTransformationVar = this->Param( transformVar ); + if (pTransformationVar && (pTransformationVar->GetType() == MATERIAL_VAR_TYPE_MATRIX)) + { + const VMatrix &mat = pTransformationVar->GetMatrixValue(); + transformation[0].Init( mat[0][0], mat[0][1], mat[0][2], mat[0][3] ); + transformation[1].Init( mat[1][0], mat[1][1], mat[1][2], mat[1][3] ); + } + else + { + transformation[0].Init( 1.0f, 0.0f, 0.0f, 0.0f ); + transformation[1].Init( 0.0f, 1.0f, 0.0f, 0.0f ); + } + + Vector2D scale( 1, 1 ); + IMaterialVar* pScaleVar = this->Param( scaleVar ); + if (pScaleVar) + { + if (pScaleVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + pScaleVar->GetVecValue( scale.Base(), 2 ); + else if (pScaleVar->IsDefined()) + scale[0] = scale[1] = pScaleVar->GetFloatValue(); + } + + // Apply the scaling + transformation[0][0] *= scale[0]; + transformation[0][1] *= scale[1]; + transformation[1][0] *= scale[0]; + transformation[1][1] *= scale[1]; + transformation[0][3] *= scale[0]; + transformation[1][3] *= scale[1]; + SetVertexShaderConstant( vertexReg, transformation[0].Base(), 2 ); + } + + FORCEINLINE void SetEnvMapTintPixelShaderDynamicState( int pixelReg, int tintVar ) + { +#ifdef _WIN32 + extern ConVar mat_fullbright; + if( g_pConfig->bShowSpecular && mat_fullbright.GetInt() != 2 ) + { + SetPixelShaderConstant( pixelReg, this->Param( tintVar)->GetVecValue() ); + } + else + { + SetPixelShaderConstant4( pixelReg, 0.0, 0.0, 0.0, 0.0 ); + } +#endif + } + + FORCEINLINE void SetEnvMapTintPixelShaderDynamicStateGammaToLinear( int pixelReg, int tintVar, float fAlphaVal = 1.0f ) + { +#ifdef _WIN32 + extern ConVar mat_fullbright; + if( g_pConfig->bShowSpecular && mat_fullbright.GetInt() != 2 ) + { + float color[4]; + color[3] = fAlphaVal; + this->Param( tintVar)->GetLinearVecValue( color, 3 ); + SetPixelShaderConstant( pixelReg, color ); + } + else + { + SetPixelShaderConstant4( pixelReg, 0.0, 0.0, 0.0, fAlphaVal ); + } +#endif + } + + FORCEINLINE void StoreEyePosInPixelShaderConstant( int nConst, float wValue = 1.0f ) + { + this->m_Storage.PutInt( CBCMD_STORE_EYE_POS_IN_PSCONST ); + this->m_Storage.PutInt( nConst ); + this->m_Storage.PutFloat( wValue ); + } + + FORCEINLINE void SetPixelShaderFogParams( int nReg ) + { + this->m_Storage.PutInt( CBCMD_SETPIXELSHADERFOGPARAMS ); + this->m_Storage.PutInt( nReg ); + } + + FORCEINLINE void BindStandardTexture( Sampler_t nSampler, StandardTextureId_t nTextureId ) + { + this->m_Storage.PutInt( CBCMD_BIND_STANDARD_TEXTURE ); + this->m_Storage.PutInt( nSampler ); + this->m_Storage.PutInt( nTextureId ); + } + + FORCEINLINE void BindTexture( CBaseShader *pShader, Sampler_t nSampler, ITexture *pTexture, int nFrame ) + { + ShaderAPITextureHandle_t hTexture = pShader->GetShaderAPITextureBindHandle( pTexture, nFrame ); + Assert( hTexture != INVALID_SHADERAPI_TEXTURE_HANDLE ); + this->m_Storage.PutInt( CBCMD_BIND_SHADERAPI_TEXTURE_HANDLE ); + this->m_Storage.PutInt( nSampler ); + this->m_Storage.PutInt( hTexture ); + } + + FORCEINLINE void BindTexture( Sampler_t nSampler, ShaderAPITextureHandle_t hTexture ) + { + Assert( hTexture != INVALID_SHADERAPI_TEXTURE_HANDLE ); + this->m_Storage.PutInt( CBCMD_BIND_SHADERAPI_TEXTURE_HANDLE ); + this->m_Storage.PutInt( nSampler ); + this->m_Storage.PutInt( hTexture ); + } + + FORCEINLINE void BindTexture( CBaseShader *pShader, Sampler_t nSampler, int nTextureVar, int nFrameVar = -1 ) + { + ShaderAPITextureHandle_t hTexture = pShader->GetShaderAPITextureBindHandle( nTextureVar, nFrameVar ); + BindTexture( nSampler, hTexture ); + } + + FORCEINLINE void BindMultiTexture( CBaseShader *pShader, Sampler_t nSampler1, Sampler_t nSampler2, int nTextureVar, int nFrameVar ) + { + ShaderAPITextureHandle_t hTexture = pShader->GetShaderAPITextureBindHandle( nTextureVar, nFrameVar, 0 ); + BindTexture( nSampler1, hTexture ); + hTexture = pShader->GetShaderAPITextureBindHandle( nTextureVar, nFrameVar, 1 ); + BindTexture( nSampler2, hTexture ); + } + + FORCEINLINE void SetPixelShaderIndex( int nIndex ) + { + this->m_Storage.PutInt( CBCMD_SET_PSHINDEX ); + this->m_Storage.PutInt( nIndex ); + } + + FORCEINLINE void SetVertexShaderIndex( int nIndex ) + { + this->m_Storage.PutInt( CBCMD_SET_VSHINDEX ); + this->m_Storage.PutInt( nIndex ); + } + + FORCEINLINE void SetDepthFeatheringPixelShaderConstant( int iConstant, float fDepthBlendScale ) + { + this->m_Storage.PutInt( CBCMD_SET_DEPTH_FEATHERING_CONST ); + this->m_Storage.PutInt( iConstant ); + this->m_Storage.PutFloat( fDepthBlendScale ); + } + + FORCEINLINE void SetVertexShaderFlashlightState( int iConstant ) + { + this->m_Storage.PutInt( CBCMD_SET_VERTEX_SHADER_FLASHLIGHT_STATE ); + this->m_Storage.PutInt( iConstant ); + } + + FORCEINLINE void SetPixelShaderFlashlightState( const CBCmdSetPixelShaderFlashlightState_t &state ) + { + this->m_Storage.PutInt( CBCMD_SET_PIXEL_SHADER_FLASHLIGHT_STATE ); + this->m_Storage.PutInt( state.m_LightSampler ); + this->m_Storage.PutInt( state.m_DepthSampler ); + this->m_Storage.PutInt( state.m_ShadowNoiseSampler ); + this->m_Storage.PutInt( state.m_nColorConstant ); + this->m_Storage.PutInt( state.m_nAttenConstant ); + this->m_Storage.PutInt( state.m_nOriginConstant ); + this->m_Storage.PutInt( state.m_nDepthTweakConstant ); + this->m_Storage.PutInt( state.m_nScreenScaleConstant ); + this->m_Storage.PutInt( state.m_nWorldToTextureConstant ); + this->m_Storage.PutInt( state.m_bFlashlightNoLambert ); + this->m_Storage.PutInt( state.m_bSinglePassFlashlight ); + } + + FORCEINLINE void SetPixelShaderUberLightState( int iEdge0Const, int iEdge1Const, int iEdgeOOWConst, int iShearRoundConst, int iAABBConst, int iWorldToLightConst ) + { + this->m_Storage.PutInt( CBCMD_SET_PIXEL_SHADER_UBERLIGHT_STATE ); + this->m_Storage.PutInt( iEdge0Const ); + this->m_Storage.PutInt( iEdge1Const ); + this->m_Storage.PutInt( iEdgeOOWConst ); + this->m_Storage.PutInt( iShearRoundConst ); + this->m_Storage.PutInt( iAABBConst ); + this->m_Storage.PutInt( iWorldToLightConst ); + } + + FORCEINLINE void Goto( uint8 *pCmdBuf ) + { + this->m_Storage.PutInt( CBCMD_JUMP ); + this->m_Storage.PutPtr( pCmdBuf ); + } + + FORCEINLINE void Call( uint8 *pCmdBuf ) + { + this->m_Storage.PutInt( CBCMD_JSR ); + this->m_Storage.PutPtr( pCmdBuf ); + } + + FORCEINLINE void Reset( void ) + { + this->m_Storage.Reset(); + } + + FORCEINLINE size_t Size( void ) const + { + return this->m_Storage.Size(); + } + + FORCEINLINE uint8 *Base( void ) + { + return this->m_Storage.Base(); + } + + FORCEINLINE void SetVertexShaderNearAndFarZ( int iRegNum ) + { + this->m_Storage.PutInt( CBCMD_SET_VERTEX_SHADER_NEARZFARZ_STATE ); + this->m_Storage.PutInt( iRegNum ); + } +}; + + +//----------------------------------------------------------------------------- +// Builds a command buffer specifically for per-instance state setting +//----------------------------------------------------------------------------- +template class CInstanceCommandBufferBuilder : public CBaseCommandBufferBuilder< S > +{ + typedef CBaseCommandBufferBuilder< S > PARENT; + +public: + FORCEINLINE void End( void ) + { + this->m_Storage.PutInt( CBICMD_END ); + } + + FORCEINLINE void SetPixelShaderLocalLighting( int nConst ) + { + this->m_Storage.PutInt( CBICMD_SETPIXELSHADERLOCALLIGHTING ); + this->m_Storage.PutInt( nConst ); + } + + FORCEINLINE void SetPixelShaderAmbientLightCube( int nConst ) + { + this->m_Storage.PutInt( CBICMD_SETPIXELSHADERAMBIENTLIGHTCUBE ); + this->m_Storage.PutInt( nConst ); + } + + FORCEINLINE void SetVertexShaderLocalLighting( ) + { + this->m_Storage.PutInt( CBICMD_SETVERTEXSHADERLOCALLIGHTING ); + } + + FORCEINLINE void SetVertexShaderAmbientLightCube( void ) + { + this->m_Storage.PutInt( CBICMD_SETVERTEXSHADERAMBIENTLIGHTCUBE ); + } + + FORCEINLINE void SetSkinningMatrices( void ) + { + this->m_Storage.PutInt( CBICMD_SETSKINNINGMATRICES ); + } + + FORCEINLINE void SetPixelShaderAmbientLightCubeLuminance( int nConst ) + { + this->m_Storage.PutInt( CBICMD_SETPIXELSHADERAMBIENTLIGHTCUBELUMINANCE ); + this->m_Storage.PutInt( nConst ); + } + + FORCEINLINE void SetPixelShaderGlintDamping( int nConst ) + { + this->m_Storage.PutInt( CBICMD_SETPIXELSHADERGLINTDAMPING ); + this->m_Storage.PutInt( nConst ); + } + + FORCEINLINE void SetModulationPixelShaderDynamicState_LinearColorSpace_LinearScale( int nConst, const Vector &vecGammaSpaceColor2Factor, float scale ) + { + this->m_Storage.PutInt( CBICMD_SETMODULATIONPIXELSHADERDYNAMICSTATE_LINEARCOLORSPACE_LINEARSCALE ); + this->m_Storage.PutInt( nConst ); + this->m_Storage.Put( vecGammaSpaceColor2Factor ); + this->m_Storage.PutFloat( scale ); + } + + FORCEINLINE void SetModulationPixelShaderDynamicState_LinearScale( int nConst, const Vector &vecGammaSpaceColor2Factor, float scale ) + { + this->m_Storage.PutInt( CBICMD_SETMODULATIONPIXELSHADERDYNAMICSTATE_LINEARSCALE ); + this->m_Storage.PutInt( nConst ); + this->m_Storage.Put( vecGammaSpaceColor2Factor ); + this->m_Storage.PutFloat( scale ); + } + + FORCEINLINE void SetModulationPixelShaderDynamicState_LinearScale_ScaleInW( int nConst, const Vector &vecGammaSpaceColor2Factor, float scale ) + { + this->m_Storage.PutInt( CBICMD_SETMODULATIONPIXELSHADERDYNAMICSTATE_LINEARSCALE_SCALEINW ); + this->m_Storage.PutInt( nConst ); + this->m_Storage.Put( vecGammaSpaceColor2Factor ); + this->m_Storage.PutFloat( scale ); + } + + FORCEINLINE void SetModulationPixelShaderDynamicState_LinearColorSpace( int nConst, const Vector &vecGammaSpaceColor2Factor ) + { + this->m_Storage.PutInt( CBICMD_SETMODULATIONPIXELSHADERDYNAMICSTATE_LINEARCOLORSPACE ); + this->m_Storage.PutInt( nConst ); + this->m_Storage.Put( vecGammaSpaceColor2Factor ); + } + + FORCEINLINE void SetModulationPixelShaderDynamicState( int nConst, const Vector &vecGammaSpaceColor2Factor ) + { + this->m_Storage.PutInt( CBICMD_SETMODULATIONPIXELSHADERDYNAMICSTATE ); + this->m_Storage.PutInt( nConst ); + this->m_Storage.Put( vecGammaSpaceColor2Factor ); + } + + FORCEINLINE void SetModulationPixelShaderDynamicState_Identity( int nConst ) + { + this->m_Storage.PutInt( CBICMD_SETMODULATIONPIXELSHADERDYNAMICSTATE_IDENTITY ); + this->m_Storage.PutInt( nConst ); + } + + FORCEINLINE void SetModulationVertexShaderDynamicState( int nConst, const Vector &vecGammaSpaceColor2Factor ) + { + this->m_Storage.PutInt( CBICMD_SETMODULATIONVERTEXSHADERDYNAMICSTATE ); + this->m_Storage.PutInt( nConst ); + this->m_Storage.Put( vecGammaSpaceColor2Factor ); + } + + FORCEINLINE void SetModulationVertexShaderDynamicState_LinearScale( int nConst, const Vector &vecGammaSpaceColor2Factor, float flScale ) + { + this->m_Storage.PutInt( CBICMD_SETMODULATIONVERTEXSHADERDYNAMICSTATE_LINEARSCALE ); + this->m_Storage.PutInt( nConst ); + this->m_Storage.Put( vecGammaSpaceColor2Factor ); + this->m_Storage.PutFloat( flScale ); + } +}; + + +#endif // commandbuilder_h